feat: 新增闪避与命中属性系统,完善战斗判定逻辑

1.  新增全局默认闪避/命中率配置,为英雄和怪物提供缺省属性兜底
2.  扩展英雄属性组件,添加闪避、命中率属性与对应计算接口
3.  实现闪避判定逻辑,修正伤害流程,添加闪避提示效果
4.  新增闪避/命中相关buff、技能与光环配置
5.  完善属性值计算与 tooltip 显示逻辑
This commit is contained in:
panFD
2026-09-07 20:41:49 +08:00
parent 22fe31a769
commit aa488d55e7
11 changed files with 123 additions and 1 deletions

View File

@@ -162,6 +162,9 @@ export class Hero extends ecs.Entity {
}
model.speed = hero.speed ?? 200;
// 闪避/命中:配置优先,缺省取全局默认值(百分点)
model.dodge = hero.dodge ?? FightSet.DEFAULT_DODGE;
model.accuracy = hero.accuracy ?? FightSet.DEFAULT_ACCURACY;
// 构建技能表并注入运行时冷却字段 ccd;overrides 按英雄等级 resolve 分档(下游无感知)
model.skills = {};

View File

@@ -134,6 +134,14 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
// 触发被攻击事件
this.onAttacked(target);
// 闪避判定(DoT 不参与):闪避率 = 目标闪避 − 施法者命中
if (!isDot && this.checkDodge(damageEvent, TAttrsComp)) {
smc.vmdata.scores.dod_count++;
targetView?.showMiss?.();
// 预留:闪避后触发技能(SkillTriggerType.Dodged)在此接入
return reDate;
}
// 暴击判定
// 使用施法者的暴击率属性(damageEvent.Attrs 快照)- 被攻击者的暴击抗性 + 目标出血层数附加的被暴击率
const criticalChance = (damageEvent.Attrs[Attrs.critical] || 0) - TAttrsComp.getFinalCriticalRes() + this.getBleedCritBonus(target);
@@ -528,6 +536,19 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpda
return (layers?.length ?? 0) * BLEED_CRIT_PER_STACK;
}
/**
* 闪避判定:闪避率 = 目标闪避 − 施法者命中,再按该值判定是否闪避。
* 命中未配置时(accuracy=0)闪避率 = 目标闪避,即无命中加成时闪避全额生效。
* @param damageEvent 伤害事件(含施法者属性快照)
* @param TAttrsComp 目标属性组件
* @returns true=闪避成功,false=命中
*/
private checkDodge(damageEvent: DamageEvent, TAttrsComp: HeroAttrsComp): boolean {
const dodgeChance = TAttrsComp.getFinalDodge() - (damageEvent.Attrs[Attrs.accuracy] || 0);
if (dodgeChance <= 0) return false;
return this.checkChance(dodgeChance);
}
/**
* 计算易伤附加伤害:汇总目标每层易伤 buff 的数值(value_override 优先),再被易伤抗性百分比减免。
* @returns 附加伤害值(向下取整,非负)

View File

@@ -75,6 +75,8 @@ export class HeroAttrsComp extends ecs.Comp {
// ==================== 特殊属性 ====================
critical: number = 0; // 暴击率
critical_res: number = 0; // 暴击抗性
dodge: number = 0; // 闪避率(被攻击时闪避概率,百分点)
accuracy: number = 0; // 命中率(攻击时命中概率,百分点;削减目标闪避)
freeze_chance: number = 0; // 冰冻概率
freeze_res: number = 0; // 冰冻抗性
stun_chance: number = 0; // 击晕概率
@@ -350,6 +352,18 @@ export class HeroAttrsComp extends ecs.Comp {
return this.critical + HeroAttrsComp.getFieldPercentValue(FieldSkillType.HeroCrit);
}
/** 英雄实时闪避率 = 基础闪避率 + 驻场闪避率。 */
public getRuntimeDodge(): number {
if (this.fac !== FacSet.HERO) return this.dodge;
return this.dodge + HeroAttrsComp.getFieldPercentValue(FieldSkillType.HeroDodge);
}
/** 英雄实时命中率 = 基础命中率 + 驻场命中率。 */
public getRuntimeAccuracy(): number {
if (this.fac !== FacSet.HERO) return this.accuracy;
return this.accuracy + HeroAttrsComp.getFieldPercentValue(FieldSkillType.HeroHit);
}
/** 英雄实时冰冻率 = 基础冰冻率 + 驻场冰冻率。 */
public getRuntimeFreezeChance(): number {
if (this.fac !== FacSet.HERO) return this.freeze_chance;
@@ -541,6 +555,20 @@ export class HeroAttrsComp extends ecs.Comp {
return this.critical_res + mods.flatSum + mods.pctSum;
}
/** 最终闪避率 = 驻场实时闪避率 + 限时修饰(加法模型) */
public getFinalDodge(): number {
const base = this.getRuntimeDodge();
const mods = this.aggregateTimedMods(Attrs.dodge);
return base + mods.flatSum + mods.pctSum;
}
/** 最终命中率 = 驻场实时命中率 + 限时修饰(加法模型) */
public getFinalAccuracy(): number {
const base = this.getRuntimeAccuracy();
const mods = this.aggregateTimedMods(Attrs.accuracy);
return base + mods.flatSum + mods.pctSum;
}
/** 最终冰冻抗性 = 基础 + 限时修饰(加法模型) */
public getFinalFreezeRes(): number {
const mods = this.aggregateTimedMods(Attrs.freeze_res);
@@ -687,6 +715,8 @@ export class HeroAttrsComp extends ecs.Comp {
this.runtime_field = undefined;
this.critical = 0;
this.critical_res = 0;
this.dodge = 0;
this.accuracy = 0;
this.freeze_chance = 0;
this.freeze_res = 0;
this.stun_chance = 0;

View File

@@ -241,6 +241,11 @@ export class HeroViewComp extends CCComp {
shield_tip(absorbed: number) {
this.hp_tip(TooltipTypes.shield, NumberFormatter.formatNumber(Math.max(0, Math.floor(absorbed))));
}
/** 闪避提示 */
showMiss() {
this.hp_tip(TooltipTypes.miss, "闪避");
}
public playBuff(anm: string = "") {
if (anm === "") return;
var path = "game/skill/buff/" + anm;

View File

@@ -176,6 +176,9 @@ export class Monster extends ecs.Entity {
// TODO: 局外升级机制落地后,此处基础值将与存档强化累加重算
model.defense = Math.round(hero.def * coef);
model.speed = hero.speed ?? 800;
// 闪避/命中:配置优先,缺省取全局默认值(百分点)
model.dodge = hero.dodge ?? FightSet.DEFAULT_DODGE;
model.accuracy = hero.accuracy ?? FightSet.DEFAULT_ACCURACY;
model.type = hero.type;
model.fac = FacSet.MON;
// lv12 职业属性专项:按 11 级当前有效值追加 50%(怪物无局内升级,初始超档直接补齐)