feat(skill): add proc skill trigger system
实现技能命中后概率触发额外技能的完整流程 1. 新增proc_skill技能配置字段与数据组件 2. 新增公共技能派发工具方法 3. 在HeroAtkSystem中添加触发逻辑 4. 完善伤害事件与技能视图传递proc_skill参数
This commit is contained in:
@@ -171,6 +171,15 @@ export interface SkillConfig {
|
|||||||
call_hero?: number, // 召唤技能召唤英雄id(可选)
|
call_hero?: number, // 召唤技能召唤英雄id(可选)
|
||||||
summon_count?: number, // 单次施法召唤的技能实体个数(未配置时回退 prefab 上 SkillView.summon_count)
|
summon_count?: number, // 单次施法召唤的技能实体个数(未配置时回退 prefab 上 SkillView.summon_count)
|
||||||
is_accel?: boolean, // 是否逐渐加速飞行
|
is_accel?: boolean, // 是否逐渐加速飞行
|
||||||
|
/**
|
||||||
|
* 命中后概率触发额外技能(技能级触发器)。
|
||||||
|
* s_uuid: 被触发的技能 uuid;chance: 触发概率(百分点,缺省 100)。
|
||||||
|
* overrides: 透传给被触发技能的覆写参数(如 ap/hit_count 等),用于自定义被触发技能的伤害/数值;
|
||||||
|
* 与被触发技能自身在 heroSet 中的 overrides 叠加(本次传入优先)。
|
||||||
|
* 触发走 SkillTriggerHelper/forceCastTriggerSkill 通道(无视 CD、无施法前摇),与 atking 同一通道。
|
||||||
|
* 支持在 lv_entries 的 overrides 里按等级覆写(利用 overrides 浅合并机制)。
|
||||||
|
*/
|
||||||
|
proc_skill?: { s_uuid: number; chance?: number; overrides?: SkillOverrides },
|
||||||
info: string, // 技能描述
|
info: string, // 技能描述
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,6 +211,9 @@ export interface SkillOverrides {
|
|||||||
revive_hp?: number;
|
revive_hp?: number;
|
||||||
/** 复活次数上限,配合 revive_hp 使用(仅 dead 触发有效) */
|
/** 复活次数上限,配合 revive_hp 使用(仅 dead 触发有效) */
|
||||||
revive_count?: number;
|
revive_count?: number;
|
||||||
|
/** 命中后概率触发额外技能(技能级触发器,覆写 SkillConfig.proc_skill),支持 lv_entries 按等级覆写;
|
||||||
|
* overrides 字段可自定义被触发技能的伤害/数值(如 ap),透传给 forceCastTriggerSkill */
|
||||||
|
proc_skill?: { s_uuid: number; chance?: number; overrides?: SkillOverrides };
|
||||||
/** 英雄语境专属图标(图鉴面板/技能弹窗展示用):配置后覆盖 SkillSet.icon,
|
/** 英雄语境专属图标(图鉴面板/技能弹窗展示用):配置后覆盖 SkillSet.icon,
|
||||||
* 实现"同一底座、不同英雄/档位不同外观"(如 5002 普攻与冲刺斩同 6004 但图标不同) */
|
* 实现"同一底座、不同英雄/档位不同外观"(如 5002 普攻与冲刺斩同 6004 但图标不同) */
|
||||||
icon?: string;
|
icon?: string;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||||
import { HeroViewComp } from "./HeroViewComp";
|
import { HeroViewComp } from "./HeroViewComp";
|
||||||
|
import { SkillOverrides } from "../common/config/SkillSet";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* ==================== 伤害事件数据 ====================
|
* ==================== 伤害事件数据 ====================
|
||||||
@@ -29,6 +30,9 @@ export interface DamageEvent {
|
|||||||
* 跳过 dmgCount 公式直接用该值,且不走击退/受击动画,其余(暴击/冰冻/击晕/护盾/死亡链)与普攻一致
|
* 跳过 dmgCount 公式直接用该值,且不走击退/受击动画,其余(暴击/冰冻/击晕/护盾/死亡链)与普攻一致
|
||||||
*/
|
*/
|
||||||
dot_dmg?:number
|
dot_dmg?:number
|
||||||
|
/** 命中后概率触发额外技能(由施法技能实体快照自合并后配置,HeroAtkSystem 据此判定;
|
||||||
|
* overrides 字段透传给被触发技能,用于自定义伤害/数值) */
|
||||||
|
proc_skill?: { s_uuid: number; chance?: number; overrides?: SkillOverrides }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -65,7 +69,7 @@ export class DamageQueueComp extends ecs.Comp {
|
|||||||
/**
|
/**
|
||||||
* 添加伤害事件到队列
|
* 添加伤害事件到队列
|
||||||
*/
|
*/
|
||||||
addDamageEvent(attrs: any, casterEid: number, s_uuid: number,ext_dmg:number=0,dmg_ratio:number=1,dot_dmg:number=0): void {
|
addDamageEvent(attrs: any, casterEid: number, s_uuid: number,ext_dmg:number=0,dmg_ratio:number=1,dot_dmg:number=0,proc_skill?: { s_uuid: number; chance?: number; overrides?: SkillOverrides }): void {
|
||||||
const timestamp = Date.now();
|
const timestamp = Date.now();
|
||||||
|
|
||||||
const damageEvent: DamageEvent = {
|
const damageEvent: DamageEvent = {
|
||||||
@@ -77,6 +81,7 @@ export class DamageQueueComp extends ecs.Comp {
|
|||||||
ext_dmg:ext_dmg,
|
ext_dmg:ext_dmg,
|
||||||
dmg_ratio:dmg_ratio,
|
dmg_ratio:dmg_ratio,
|
||||||
dot_dmg:dot_dmg,
|
dot_dmg:dot_dmg,
|
||||||
|
proc_skill:proc_skill,
|
||||||
};
|
};
|
||||||
|
|
||||||
this.damageEvents.push(damageEvent);
|
this.damageEvents.push(damageEvent);
|
||||||
@@ -182,7 +187,7 @@ export class DamageQueueHelper {
|
|||||||
* 为实体添加伤害事件
|
* 为实体添加伤害事件
|
||||||
* 如果实体没有伤害队列组件,会自动创建
|
* 如果实体没有伤害队列组件,会自动创建
|
||||||
*/
|
*/
|
||||||
static addDamageToEntity(entity: ecs.Entity, attrs: any, casterEid: number, s_uuid: number,ext_dmg:number=0,dmg_ratio:number=1,dot_dmg:number=0): void {
|
static addDamageToEntity(entity: ecs.Entity, attrs: any, casterEid: number, s_uuid: number,ext_dmg:number=0,dmg_ratio:number=1,dot_dmg:number=0,proc_skill?: { s_uuid: number; chance?: number; overrides?: SkillOverrides }): void {
|
||||||
let damageQueue = entity.get(DamageQueueComp);
|
let damageQueue = entity.get(DamageQueueComp);
|
||||||
|
|
||||||
// 如果实体没有伤害队列组件,创建一个
|
// 如果实体没有伤害队列组件,创建一个
|
||||||
@@ -191,7 +196,7 @@ export class DamageQueueHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 添加伤害事件到队列
|
// 添加伤害事件到队列
|
||||||
damageQueue.addDamageEvent(attrs, casterEid, s_uuid,ext_dmg,dmg_ratio,dot_dmg);
|
damageQueue.addDamageEvent(attrs, casterEid, s_uuid,ext_dmg,dmg_ratio,dot_dmg,proc_skill);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -271,6 +271,25 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 命中概率触发额外技能(proc_skill):配置由施法技能实体快照自合并后配置(含 heroSet overrides/lv_entries),
|
||||||
|
// 触发走 SkillTriggerHelper/forceCastTriggerSkill 通道(无视 CD、无施法前摇),与 atking 同一通道。
|
||||||
|
// 防递归:被触发的技能经 forceCastTriggerSkill 不再产生 proc_skill 伤害事件之外的新事件,且不会累加 atk_count。
|
||||||
|
if (!isDot && damageEvent.proc_skill) {
|
||||||
|
const proc = damageEvent.proc_skill;
|
||||||
|
const procChance = proc.chance ?? 100;
|
||||||
|
if (procChance >= 100 || Math.random() * 100 < procChance) {
|
||||||
|
const caster = ecs.getEntityByEid(casterEid);
|
||||||
|
if (caster) {
|
||||||
|
const casterAttrs = caster.get(HeroAttrsComp);
|
||||||
|
const casterView = caster.get(HeroViewComp);
|
||||||
|
if (casterAttrs && casterView && !casterAttrs.is_dead && !casterAttrs.is_reviving) {
|
||||||
|
// proc_skill.overrides 透传给被触发技能(如自定义 ap 伤害),与被触发技能自身 overrides 叠加(本次传入优先)
|
||||||
|
SkillTriggerHelper.dispatchSinglePublic(proc.s_uuid, casterAttrs, casterView, SkillTriggerType.Atking, proc.overrides);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// 检查死亡
|
// 检查死亡
|
||||||
if (TAttrsComp.hp <= 0) {
|
if (TAttrsComp.hp <= 0) {
|
||||||
|
|||||||
@@ -166,4 +166,17 @@ export class SkillTriggerHelper {
|
|||||||
overrides: overrides
|
overrides: overrides
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 公共单技能派发(供 HeroAtkSystem 等命中后触发场景调用)。
|
||||||
|
* 直接复用 TriggerSkill 通道(forceCastTriggerSkill),无视 CD、无施法前摇。
|
||||||
|
* @param s_uuid 被触发的技能 uuid
|
||||||
|
* @param model 施法者属性组件
|
||||||
|
* @param view 施法者视图组件
|
||||||
|
* @param type 触发类型(语义来源,如 SkillTriggerType.Atking)
|
||||||
|
* @param overrides 透传给被触发技能的覆写参数
|
||||||
|
*/
|
||||||
|
public static dispatchSinglePublic(s_uuid: number, model: HeroAttrsComp, view: HeroViewComp, type: SkillTriggerType, overrides?: SkillOverrides) {
|
||||||
|
this.dispatchSingle(s_uuid, model, view, type, overrides);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||||
import { BoxSet } from "../common/config/GameSet";
|
import { BoxSet } from "../common/config/GameSet";
|
||||||
|
import { SkillOverrides } from "../common/config/SkillSet";
|
||||||
|
|
||||||
/** 业务层对象 */
|
/** 业务层对象 */
|
||||||
//技能数据
|
//技能数据
|
||||||
@@ -16,6 +17,9 @@ export class SDataCom extends ecs.Comp {
|
|||||||
dmg_ratio:number=1 //伤害比例
|
dmg_ratio:number=1 //伤害比例
|
||||||
hit_count:number=0 //击中数量
|
hit_count:number=0 //击中数量
|
||||||
max_hit_count:number=0 //最大可命中次数
|
max_hit_count:number=0 //最大可命中次数
|
||||||
|
/** 命中后概率触发额外技能(由 Skill.load 从合并后配置快照;DamageEvent 透传给 HeroAtkSystem 判定;
|
||||||
|
* overrides 字段透传给被触发技能,用于自定义伤害/数值) */
|
||||||
|
proc_skill?: { s_uuid: number; chance?: number; overrides?: SkillOverrides };
|
||||||
reset() {
|
reset() {
|
||||||
this.Attrs=null
|
this.Attrs=null
|
||||||
this.group=BoxSet.HERO
|
this.group=BoxSet.HERO
|
||||||
@@ -27,6 +31,7 @@ export class SDataCom extends ecs.Comp {
|
|||||||
this.max_hit_count=0
|
this.max_hit_count=0
|
||||||
this.ext_dmg=0
|
this.ext_dmg=0
|
||||||
this.dmg_ratio=1
|
this.dmg_ratio=1
|
||||||
|
this.proc_skill=undefined
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -242,6 +242,8 @@ export class Skill extends ecs.Entity {
|
|||||||
sDataCom.ext_dmg = ext_dmg
|
sDataCom.ext_dmg = ext_dmg
|
||||||
sDataCom.hit_count = 0
|
sDataCom.hit_count = 0
|
||||||
sDataCom.max_hit_count = Math.max(1, sHit)
|
sDataCom.max_hit_count = Math.max(1, sHit)
|
||||||
|
// 快照合并后(基础配置+heroSet overrides/lv_entries)的 proc_skill,命中时由 HeroAtkSystem 判定触发
|
||||||
|
sDataCom.proc_skill = config.proc_skill;
|
||||||
SView.init();
|
SView.init();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -219,6 +219,8 @@ export class SkillView extends CCComp {
|
|||||||
this.sData.s_uuid,
|
this.sData.s_uuid,
|
||||||
this.sData.ext_dmg,
|
this.sData.ext_dmg,
|
||||||
finalRatio,
|
finalRatio,
|
||||||
|
0,
|
||||||
|
this.sData.proc_skill,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
close_collider() {
|
close_collider() {
|
||||||
|
|||||||
Reference in New Issue
Block a user