diff --git a/assets/script/game/hero/HeroAtkSystem.ts b/assets/script/game/hero/HeroAtkSystem.ts index 16bcc3b5..f5db2f8b 100644 --- a/assets/script/game/hero/HeroAtkSystem.ts +++ b/assets/script/game/hero/HeroAtkSystem.ts @@ -128,7 +128,7 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpda // 暴击判定 // 使用施法者的暴击率属性(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); // 计算基础伤害 @@ -187,7 +187,7 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpda 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); // 击退判定 diff --git a/assets/script/game/hero/HeroAttrsComp.ts b/assets/script/game/hero/HeroAttrsComp.ts index f237b75b..52ff2f6e 100644 --- a/assets/script/game/hero/HeroAttrsComp.ts +++ b/assets/script/game/hero/HeroAttrsComp.ts @@ -115,7 +115,8 @@ export class HeroAttrsComp extends ecs.Comp { const oldHp = this.hp; let addValue = value; 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; // ✅ 仅标记需要更新 if (this.debugMode) { 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; } + /** 最终冰冻率 = 驻场实时冰冻率 + 限时修饰(加法模型) */ + 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。 */ public getEffectiveSkillCd(skillId: number): number { const skill = this.skills[skillId]; diff --git a/assets/script/game/skill/Skill.ts b/assets/script/game/skill/Skill.ts index ce4670f8..368745f0 100644 --- a/assets/script/game/skill/Skill.ts +++ b/assets/script/game/skill/Skill.ts @@ -210,14 +210,14 @@ export class Skill extends ecs.Entity { const sBck = (config.bck ?? 0) + (SUp.bck * skill_lv); const sAp = config.ap + (SUp.ap * 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.critical] = cAttrsComp.getRuntimeCritical() + sCrt; - sDataCom.Attrs[Attrs.critical_damage] = cAttrsComp.getRuntimeCritDamageBonus(); - sDataCom.Attrs[Attrs.freeze_chance] = cAttrsComp.getRuntimeFreezeChance() + sFrz; - sDataCom.Attrs[Attrs.stun_chance] = cAttrsComp.getRuntimeStunChance() + sStun; - sDataCom.Attrs[Attrs.knockback_chance] = cAttrsComp.knockback_chance + sBck; - sDataCom.Attrs[Attrs.knockback_distance] = cAttrsComp.knockback_distance || 0; - sDataCom.Attrs[Attrs.puncture_chance] = cAttrsComp.getRuntimePunctureChance(); // 初始化携带施法者的穿透概率 + sDataCom.Attrs[Attrs.ap] = Math.floor(cAttrsComp.getFinalAp() * sAp / 100); //技能的ap是百分值 需要/100 而且需要再最终计算总ap时再/100,不然会出现ap为90%变0 + sDataCom.Attrs[Attrs.critical] = cAttrsComp.getFinalCritical() + sCrt; + sDataCom.Attrs[Attrs.critical_damage] = cAttrsComp.getFinalCritDamage(); + sDataCom.Attrs[Attrs.freeze_chance] = cAttrsComp.getFinalFreezeChance() + sFrz; + sDataCom.Attrs[Attrs.stun_chance] = cAttrsComp.getFinalStunChance() + sStun; + sDataCom.Attrs[Attrs.knockback_chance] = cAttrsComp.getFinalKnockbackChance() + sBck; + sDataCom.Attrs[Attrs.knockback_distance] = cAttrsComp.getFinalKnockbackDistance(); + sDataCom.Attrs[Attrs.puncture_chance] = cAttrsComp.getFinalPunctureChance(); // 初始化携带施法者的穿透概率 sDataCom.s_uuid = s_uuid sDataCom.skill_lv = Math.max(0, skill_lv); sDataCom.fac = cAttrsComp.fac