refactor(attr system): 统一使用属性获取方法,让限时buff生效
1. 重构HeroAtkSystem中的暴击、击晕判定逻辑,改用getFinal方法获取抗性 2. 重构Skill.ts中的属性赋值逻辑,替换为对应的最终属性获取方法 3. 修复血量钳制逻辑,使用getFinalHpMax确保限时血量上限buff生效 4. 新增多个属性的最终值获取方法,统一处理限时修饰符
This commit is contained in:
@@ -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);
|
||||||
|
|
||||||
// 击退判定
|
// 击退判定
|
||||||
|
|||||||
@@ -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];
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user