refactor(attr system): 统一使用属性获取方法,让限时buff生效

1. 重构HeroAtkSystem中的暴击、击晕判定逻辑,改用getFinal方法获取抗性
2. 重构Skill.ts中的属性赋值逻辑,替换为对应的最终属性获取方法
3. 修复血量钳制逻辑,使用getFinalHpMax确保限时血量上限buff生效
4. 新增多个属性的最终值获取方法,统一处理限时修饰符
This commit is contained in:
pan
2026-07-23 16:55:33 +08:00
parent 2381812d06
commit 1afa06efb8
3 changed files with 83 additions and 11 deletions

View File

@@ -128,7 +128,7 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
// 暴击判定 // 暴击判定
// 使用施法者的暴击率属性damageEvent.Attrs 快照),- 被攻击者的暴击抗性属 // 使用施法者的暴击率属性damageEvent.Attrs 快照),- 被攻击者的暴击抗性属
const criticalChance = (damageEvent.Attrs[Attrs.critical] || 0) - (TAttrsComp.critical_res || 0); const criticalChance = (damageEvent.Attrs[Attrs.critical] || 0) - TAttrsComp.getFinalCriticalRes();
const isCrit = this.checkChance(criticalChance); const isCrit = this.checkChance(criticalChance);
// 计算基础伤害 // 计算基础伤害
@@ -187,7 +187,7 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
const isFrost = !TAttrsComp.isFrost() && this.checkChance(freezeChance); const isFrost = !TAttrsComp.isFrost() && this.checkChance(freezeChance);
// 击晕判定 // 击晕判定
const stunChance = (damageEvent.Attrs[Attrs.stun_chance] || 0) - (TAttrsComp.stun_res || 0); const stunChance = (damageEvent.Attrs[Attrs.stun_chance] || 0) - TAttrsComp.getFinalStunRes();
const isStun = !TAttrsComp.isStun() && this.checkChance(stunChance); const isStun = !TAttrsComp.isStun() && this.checkChance(stunChance);
// 击退判定 // 击退判定

View File

@@ -115,7 +115,8 @@ export class HeroAttrsComp extends ecs.Comp {
const oldHp = this.hp; const oldHp = this.hp;
let addValue = value; let addValue = value;
this.hp += addValue; this.hp += addValue;
this.hp = Math.max(0, Math.min(this.hp, this.hp_max)); // 血量钳制使用 getFinalHpMax(),让限时 hp_max buff 也生效于血量上限
this.hp = Math.max(0, Math.min(this.hp, this.getFinalHpMax()));
this.dirty_hp = true; // ✅ 仅标记需要更新 this.dirty_hp = true; // ✅ 仅标记需要更新
if (this.debugMode) { if (this.debugMode) {
mLogger.log(this.debugMode, 'HeroAttrs', ` HP变更: ${this.hero_name}, 变化=${addValue.toFixed(1)}, ${oldHp.toFixed(1)} -> ${this.hp.toFixed(1)}`); mLogger.log(this.debugMode, 'HeroAttrs', ` HP变更: ${this.hero_name}, 变化=${addValue.toFixed(1)}, ${oldHp.toFixed(1)} -> ${this.hp.toFixed(1)}`);
@@ -392,6 +393,77 @@ export class HeroAttrsComp extends ecs.Comp {
return base + mods.flatSum + mods.pctSum; return base + mods.flatSum + mods.pctSum;
} }
/** 最终冰冻率 = 驻场实时冰冻率 + 限时修饰(加法模型) */
public getFinalFreezeChance(): number {
const base = this.getRuntimeFreezeChance();
const mods = this.aggregateTimedMods(Attrs.freeze_chance);
return base + mods.flatSum + mods.pctSum;
}
/** 最终击晕率 = 驻场实时击晕率 + 限时修饰(加法模型) */
public getFinalStunChance(): number {
const base = this.getRuntimeStunChance();
const mods = this.aggregateTimedMods(Attrs.stun_chance);
return base + mods.flatSum + mods.pctSum;
}
/** 最终击退概率 = 基础击退 + 限时修饰(加法模型) */
public getFinalKnockbackChance(): number {
const mods = this.aggregateTimedMods(Attrs.knockback_chance);
return this.knockback_chance + mods.flatSum + mods.pctSum;
}
/** 最终击退距离 = 基础击退距离 + 限时修饰(加法模型) */
public getFinalKnockbackDistance(): number {
const mods = this.aggregateTimedMods(Attrs.knockback_distance);
return this.knockback_distance + mods.flatSum + mods.pctSum;
}
/** 最终额外暴击伤害 = 驻场实时暴伤 + 限时修饰(加法模型) */
public getFinalCritDamage(): number {
const base = this.getRuntimeCritDamageBonus();
const mods = this.aggregateTimedMods(Attrs.critical_damage);
return base + mods.flatSum + mods.pctSum;
}
/** 最终穿透概率 = 驻场实时穿透 + 限时修饰(加法模型) */
public getFinalPunctureChance(): number {
const base = this.getRuntimePunctureChance();
const mods = this.aggregateTimedMods(Attrs.puncture_chance);
return base + mods.flatSum + mods.pctSum;
}
/** 最终风怒概率 = 驻场实时风怒 + 限时修饰(加法模型) */
public getFinalWindFury(): number {
const base = this.getRuntimeWindFury();
const mods = this.aggregateTimedMods(Attrs.wfuny);
return base + mods.flatSum + mods.pctSum;
}
/** 最终暴击抗性 = 基础 + 限时修饰(加法模型) */
public getFinalCriticalRes(): number {
const mods = this.aggregateTimedMods(Attrs.critical_res);
return this.critical_res + mods.flatSum + mods.pctSum;
}
/** 最终冰冻抗性 = 基础 + 限时修饰(加法模型) */
public getFinalFreezeRes(): number {
const mods = this.aggregateTimedMods(Attrs.freeze_res);
return this.freeze_res + mods.flatSum + mods.pctSum;
}
/** 最终击晕抗性 = 基础 + 限时修饰(加法模型) */
public getFinalStunRes(): number {
const mods = this.aggregateTimedMods(Attrs.stun_res);
return this.stun_res + mods.flatSum + mods.pctSum;
}
/** 最终击退抗性 = 基础 + 限时修饰(加法模型) */
public getFinalKnockbackRes(): number {
const mods = this.aggregateTimedMods(Attrs.knockback_res);
return this.knockback_res + mods.flatSum + mods.pctSum;
}
/** 根据攻速加成换算实际攻击间隔,避免直接改写配置里的基础 CD。 */ /** 根据攻速加成换算实际攻击间隔,避免直接改写配置里的基础 CD。 */
public getEffectiveSkillCd(skillId: number): number { public getEffectiveSkillCd(skillId: number): number {
const skill = this.skills[skillId]; const skill = this.skills[skillId];

View File

@@ -210,14 +210,14 @@ export class Skill extends ecs.Entity {
const sBck = (config.bck ?? 0) + (SUp.bck * skill_lv); const sBck = (config.bck ?? 0) + (SUp.bck * skill_lv);
const sAp = config.ap + (SUp.ap * skill_lv); const sAp = config.ap + (SUp.ap * skill_lv);
const sHit = config.hit_count + (SUp.hit_count * skill_lv); const sHit = config.hit_count + (SUp.hit_count * skill_lv);
sDataCom.Attrs[Attrs.ap] = Math.floor(cAttrsComp.ap * sAp / 100); //技能的ap是百分值 需要/100 而且需要再最终计算总ap时再/100不然会出现ap为90%变0 sDataCom.Attrs[Attrs.ap] = Math.floor(cAttrsComp.getFinalAp() * sAp / 100); //技能的ap是百分值 需要/100 而且需要再最终计算总ap时再/100不然会出现ap为90%变0
sDataCom.Attrs[Attrs.critical] = cAttrsComp.getRuntimeCritical() + sCrt; sDataCom.Attrs[Attrs.critical] = cAttrsComp.getFinalCritical() + sCrt;
sDataCom.Attrs[Attrs.critical_damage] = cAttrsComp.getRuntimeCritDamageBonus(); sDataCom.Attrs[Attrs.critical_damage] = cAttrsComp.getFinalCritDamage();
sDataCom.Attrs[Attrs.freeze_chance] = cAttrsComp.getRuntimeFreezeChance() + sFrz; sDataCom.Attrs[Attrs.freeze_chance] = cAttrsComp.getFinalFreezeChance() + sFrz;
sDataCom.Attrs[Attrs.stun_chance] = cAttrsComp.getRuntimeStunChance() + sStun; sDataCom.Attrs[Attrs.stun_chance] = cAttrsComp.getFinalStunChance() + sStun;
sDataCom.Attrs[Attrs.knockback_chance] = cAttrsComp.knockback_chance + sBck; sDataCom.Attrs[Attrs.knockback_chance] = cAttrsComp.getFinalKnockbackChance() + sBck;
sDataCom.Attrs[Attrs.knockback_distance] = cAttrsComp.knockback_distance || 0; sDataCom.Attrs[Attrs.knockback_distance] = cAttrsComp.getFinalKnockbackDistance();
sDataCom.Attrs[Attrs.puncture_chance] = cAttrsComp.getRuntimePunctureChance(); // 初始化携带施法者的穿透概率 sDataCom.Attrs[Attrs.puncture_chance] = cAttrsComp.getFinalPunctureChance(); // 初始化携带施法者的穿透概率
sDataCom.s_uuid = s_uuid sDataCom.s_uuid = s_uuid
sDataCom.skill_lv = Math.max(0, skill_lv); sDataCom.skill_lv = Math.max(0, skill_lv);
sDataCom.fac = cAttrsComp.fac sDataCom.fac = cAttrsComp.fac