feat(hero&config): 新增反伤属性与反伤结算逻辑

1. 新增反伤相关配置属性thorns_dmg和thorns_rate
2. 在HeroAttrsComp中添加反伤属性字段与初始化逻辑
3. 实现反伤伤害结算逻辑,支持固定值+比例混合反伤
4. 新增计时buff施加概率与目标覆写配置项
This commit is contained in:
panFD
2026-09-05 17:53:21 +08:00
parent 0097e8c4c7
commit 370b455352
4 changed files with 61 additions and 2 deletions

View File

@@ -46,6 +46,8 @@ export enum Attrs {
paralyze_power = "paralyze_power", // 麻痹强化(百分点;提升麻痹对技能 CD 的减速量,累计达 100 则 CD 停止增长) paralyze_power = "paralyze_power", // 麻痹强化(百分点;提升麻痹对技能 CD 的减速量,累计达 100 则 CD 停止增长)
heal_power = "heal_power", // 治疗强化(百分点;放大该英雄施放技能的治疗量,辅助专精天赋写入) heal_power = "heal_power", // 治疗强化(百分点;放大该英雄施放技能的治疗量,辅助专精天赋写入)
buff_power = "buff_power", // buff 强化(百分点;放大该英雄施加的友方 buff 数值,辅助专精天赋写入) buff_power = "buff_power", // buff 强化(百分点;放大该英雄施加的友方 buff 数值,辅助专精天赋写入)
thorns_dmg = "thorns_dmg", // 反伤伤害(固定值,受到攻击时对攻击者造成等量伤害)
thorns_rate = "thorns_rate", // 反伤比例(百分点;反伤值 = 实际受到伤害 * thorns_rate / 100 + thorns_dmg)
} }
/** /**

View File

@@ -168,6 +168,9 @@ export interface SkillConfig {
timed_buff_id?: number, // 计时性 buff 配置 id(指向 BuffList),存在时走 buffManager 而非永久 add_* timed_buff_id?: number, // 计时性 buff 配置 id(指向 BuffList),存在时走 buffManager 而非永久 add_*
buff_value?: number, // 覆写计时 buff 的修饰数值(modifiers.value / tick.damage_or_heal),由药水卡自定义档位 buff_value?: number, // 覆写计时 buff 的修饰数值(modifiers.value / tick.damage_or_heal),由药水卡自定义档位
buff_duration?: number, // 覆写计时 buff 的持续时间(秒),不配置则用 BuffList 默认值 buff_duration?: number, // 覆写计时 buff 的持续时间(秒),不配置则用 BuffList 默认值
buff_chance?: number, // 计时 buff 施加概率(百分点,缺省 100)
/** 计时 buff 施加目标覆写:缺省按技能主效果推导(伤害→被命中者,辅助→友方) */
buff_target?: BuffTarget,
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, // 是否逐渐加速飞行

View File

@@ -192,6 +192,16 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
this.checkAndTriggerAtkedSkills(TAttrsComp, targetView); this.checkAndTriggerAtkedSkills(TAttrsComp, targetView);
} }
// 反伤结算:实际受到伤害后,目标将自身 thorns_dmg 反弹给攻击者
// 反伤值 = 实际受到伤害 * thorns_rate / 100 + thorns_dmg(固定值+比例混合)
// DoT 不触发反伤(持续伤害类效果通常不触发荆棘)
if (!isDot && damage > 0) {
const thornsDmg = Math.floor(damage * TAttrsComp.thorns_rate / 100) + TAttrsComp.thorns_dmg;
if (thornsDmg > 0) {
this.applyThornsDamage(casterEid, thornsDmg);
}
}
mLogger.log(this.debugMode, 'HeroAtkSystem', ` 英雄${TAttrsComp.hero_name} (uuid: ${TAttrsComp.hero_uuid}) 受到 eid:${casterEid} 的 伤害 ${damage},${isCrit ? "暴击" : "普通"}攻击,技能ID ${damageEvent.s_uuid}`); mLogger.log(this.debugMode, 'HeroAtkSystem', ` 英雄${TAttrsComp.hero_name} (uuid: ${TAttrsComp.hero_uuid}) 受到 eid:${casterEid} 的 伤害 ${damage},${isCrit ? "暴击" : "普通"}攻击,技能ID ${damageEvent.s_uuid}`);
// 冰冻判定 // 冰冻判定
@@ -548,6 +558,44 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
return { remainingDamage: damage - absorbed, absorbedDamage: absorbed }; return { remainingDamage: damage - absorbed, absorbedDamage: absorbed };
} }
/**
* 对攻击者施加反伤伤害
*
* 反伤为固定数值伤害,直接扣减攻击者 HP,不走暴击/防御/护盾等常规结算
* (反伤通常是真实伤害或固定伤害,避免嵌套结算导致无限循环)
*
* @param casterEid 攻击者实体 ID
* @param thornsDmg 反伤伤害值
*/
private applyThornsDamage(casterEid: number, thornsDmg: number): void {
const caster = ecs.getEntityByEid(casterEid);
if (!caster) return;
const casterAttrs = caster.get(HeroAttrsComp);
if (!casterAttrs || casterAttrs.is_dead || casterAttrs.is_reviving) return;
// 反伤直接扣血,不经过护盾/防御结算(避免反伤-反伤无限循环)
casterAttrs.add_hp(-thornsDmg);
// 反伤计入评分统计(仅英雄阵营的反伤被统计,怪物反伤通常源于英雄技能/天赋)
if (casterAttrs.fac === FacSet.HERO) {
smc.vmdata.scores.thorns_dmg += thornsDmg;
}
mLogger.log(this.debugMode, 'HeroAtkSystem', ` 反伤: ${casterAttrs.hero_name} 受到 ${thornsDmg} 点反伤伤害`);
// 反伤致死检查
if (casterAttrs.hp <= 0) {
this.triggerDeadSkills(caster);
casterAttrs.death_count++;
this.doDead(caster);
const casterView = caster.get(HeroViewComp);
if (casterView) {
casterView.do_dead();
}
}
}
/** /**
* 解析 timed_buff_id 的施加目标实体列表。 * 解析 timed_buff_id 的施加目标实体列表。
* 缺省(undefined / BuffTarget.Hit)返回被命中者;显式配置可切换到施法者自身、全体友方或全体敌方。 * 缺省(undefined / BuffTarget.Hit)返回被命中者;显式配置可切换到施法者自身、全体友方或全体敌方。
@@ -583,8 +631,10 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
/** /**
* 被攻击时触发的事件 * 被攻击时触发的事件
* *
* 预留的扩展点,用于处理被攻击时的特殊逻辑: * 当前已实现的逻辑:
* - 触发反伤效果(荆棘光环等) * - 反伤效果:目标通过 thorns_dmg 属性对攻击者造成固定反伤(在 doAttack 中结算)
*
* 预留的扩展点:
* - 触发被攻击天赋(如受击回血、受击反击等) * - 触发被攻击天赋(如受击回血、受击反击等)
* - 触发特殊状态(如受伤狂暴、受伤护盾等) * - 触发特殊状态(如受伤狂暴、受伤护盾等)
* *

View File

@@ -91,6 +91,8 @@ export class HeroAttrsComp extends ecs.Comp {
vulnerable_res: number = 0; // 易伤抗性(百分比减免易伤附加伤害) vulnerable_res: number = 0; // 易伤抗性(百分比减免易伤附加伤害)
heal_power: number = 0; // 治疗强化(百分点;放大该英雄施放技能的治疗量,辅助专精天赋写入) heal_power: number = 0; // 治疗强化(百分点;放大该英雄施放技能的治疗量,辅助专精天赋写入)
buff_power: number = 0; // buff 强化(百分点;放大该英雄施加的友方 buff 数值,辅助专精天赋写入) buff_power: number = 0; // buff 强化(百分点;放大该英雄施加的友方 buff 数值,辅助专精天赋写入)
thorns_dmg: number = 0; // 反伤伤害(固定值,受到攻击时对攻击者造成等量伤害)
thorns_rate: number = 0; // 反伤比例(百分点;反伤值 = 实际受到伤害 * thorns_rate / 100 + thorns_dmg)
revived_count: number = 0; // 已复活次数(从 dead 触发配置的 revive_count 限制) revived_count: number = 0; // 已复活次数(从 dead 触发配置的 revive_count 限制)
death_count: number = 0; // 本回合死亡次数(用于 dead 触发统计) death_count: number = 0; // 本回合死亡次数(用于 dead 触发统计)
@@ -655,6 +657,8 @@ export class HeroAttrsComp extends ecs.Comp {
this.vulnerable_res = 0; this.vulnerable_res = 0;
this.heal_power = 0; this.heal_power = 0;
this.buff_power = 0; this.buff_power = 0;
this.thorns_dmg = 0;
this.thorns_rate = 0;
this.boom = false; this.boom = false;
// 重置技能距离缓存 // 重置技能距离缓存