refactor(战斗系统): 重构攻击处理逻辑并优化击退机制

- 将闪避、暴击和击退的概率检查统一为checkChance方法
- 移除HeroAtkComp类并清理无用代码
- 新增clearTalBuffByAttr方法用于清除特定属性的天赋buff
- 修改HeroViewComp.do_atked方法支持可选击退参数
- 移除Attrs.BACK属性及相关配置
This commit is contained in:
2025-11-20 16:48:14 +08:00
parent b4fd807ddc
commit 51f32b1d29
4 changed files with 42 additions and 54 deletions

View File

@@ -8,14 +8,7 @@ import { HeroViewComp } from "./HeroViewComp";
import { DamageQueueComp, DamageEvent, DamageQueueHelper } from "./DamageQueueComp";
import { smc } from "../common/SingletonModuleComp";
/** 业务层对象 */
@ecs.register('HeroAtk')
export class HeroAtkComp extends ecs.Comp {
/** 业务层组件移除时,重置所有数据为默认值 */
reset() {
}
}
/** 最终伤害数据接口 */
interface FinalData {
damage: number;
@@ -94,17 +87,17 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
* @returns 最终伤害数据
*/
private doAttack(target: ecs.Entity, damageEvent: DamageEvent): FinalData {
const targetModel = target.get(HeroAttrsComp);
const targetAttrs = target.get(HeroAttrsComp);
const targetView = target.get(HeroViewComp);
let reDate:FinalData={
damage:0,
isCrit:false,
isDodge:false,
}
if (!targetModel || targetModel.is_dead) return reDate;
if (!targetAttrs || targetAttrs.is_dead) return reDate;
// 获取攻击者数据
const caster = damageEvent.caster;
const attackerModel = caster?.ent?.get(HeroAttrsComp);
// 获取技能配置
const skillConf = SkillSet[damageEvent.s_uuid];
@@ -114,38 +107,40 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
this.onAttacked(target);
// 闪避判定
if (this.checkDodge(targetModel)) {
const isDodge =this.checkChance(targetAttrs.Attrs[Attrs.DODGE] || 0);
if (isDodge) {
// TODO: 触发闪避视图表现
reDate.isDodge=true;
return reDate;
}
// 暴击判定
const isCrit = this.checkCrit(targetModel.Attrs[Attrs.CRITICAL]);
const isCrit = this.checkChance(damageEvent.Attrs[Attrs.CRITICAL]);
if (isCrit) attackerModel?.clearTalBuffByAttr(Attrs.CRITICAL);
// 计算伤害
let damage = this.dmgCount(damageEvent.Attrs,damageEvent.s_uuid);
if (isCrit) {
damage = Math.floor(damage * (1 + (FightSet.CRIT_DAMAGE + targetModel.Attrs[Attrs.CRITICAL_DMG]) / 100));
damage = Math.floor(damage * (1 + (FightSet.CRIT_DAMAGE + targetAttrs.Attrs[Attrs.CRITICAL_DMG]) / 100));
reDate.isCrit=true;
}
// 伤害计算考虑易伤等debuff
damage = this.calculateDamage(targetModel, damage);
damage = this.calculateDamage(targetAttrs, damage);
// 护盾吸收
damage =Math.floor(this.absorbShield(targetModel, damage))
damage =Math.floor(this.absorbShield(targetAttrs, damage))
if (damage <= 0) return reDate;
// 应用伤害到数据层
targetModel.hp -= damage;
targetModel.atked_count++;
targetAttrs.hp -= damage;
targetAttrs.atked_count++;
//击退判定
const isBack = this.checkChance(damageEvent.Attrs[Attrs.BACK_CHANCE] || 0);
if (isBack) attackerModel?.clearTalBuffByAttr(Attrs.BACK_CHANCE);
// ✅ 触发视图层表现(伤害数字、受击动画、后退)
if (targetView) {
targetView.do_atked(damage, isCrit, damageEvent.s_uuid);
}
if (targetView) targetView.do_atked(damage, isCrit, damageEvent.s_uuid, isBack);
// 检查死亡
if (targetModel.hp <= 0) {
if (targetAttrs.hp <= 0) {
this.doDead(target);
// ✅ 触发死亡视图表现
if (targetView) {
@@ -154,7 +149,7 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
}
if (this.debugMode) {
console.log(`[HeroAtkSystem] ${targetModel.hero_name} 受到 ${damage} 点伤害 (暴击: ${isCrit})`);
console.log(`[HeroAtkSystem] ${targetAttrs.hero_name} 受到 ${damage} 点伤害 (暴击: ${isCrit})`);
}
reDate.damage=damage;
@@ -184,31 +179,15 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
}
}
/**
* 闪避判定
*/
private checkDodge(model: HeroAttrsComp): boolean {
if (model.Attrs[Attrs.DODGE] > 0) {
const random = Math.random() * 100;
if (random < model.Attrs[Attrs.DODGE]) {
if (this.debugMode) {
console.log(`[HeroBattleSystem] ${model.hero_name} 闪避了攻击`);
}
return true;
}
}
return false;
}
/**
* 暴击判定
*/
private checkCrit(critRate: number): boolean {
if (critRate > 0) {
const random = Math.random() * 100;
return random < critRate;
}
return false;
private checkChance(rate: number): boolean {
if (rate <= 0) return false;
const r = Math.random() * 100;
return r < rate;
}
/**

View File

@@ -425,6 +425,17 @@ export class HeroAttrsComp extends ecs.Comp {
delete this.BUFFS_TAL[t_uuid];
this.recalculateSingleAttr(attrIndex);
}
clearTalBuffByAttr(attrIndex: number) {
let changed = false;
for (const key in this.BUFFS_TAL) {
const b = this.BUFFS_TAL[Number(key)];
if (b && b.attrIndex === attrIndex) {
delete this.BUFFS_TAL[Number(key)];
changed = true;
}
}
if (changed) this.recalculateSingleAttr(attrIndex);
}
addTalent(eff: number, value: number) {
const t = this.Talents[eff] || { value: 0, count: 0 };

View File

@@ -350,7 +350,7 @@ export class HeroViewComp extends CCComp {
this.ent.destroy();
}
do_atked(damage:number,isCrit:boolean,s_uuid:number){
do_atked(damage:number,isCrit:boolean,s_uuid:number,isBack:boolean=false){
// 受到攻击时显示血条并设置显示时间即使伤害为0也显示
this.top_node.active = true;
this.hpBarShowCD = this.hpBarShowTime;
@@ -359,8 +359,8 @@ export class HeroViewComp extends CCComp {
// 视图层表现
let SConf=SkillSet[s_uuid]
this.back()
this.showDamage(damage, isCrit, SConf.DAnm); // 暴击状态由战斗系统内部处理, DAnm和EAnm共用设定数组
if (isBack) this.back()
this.showDamage(damage, isCrit, SConf.DAnm);
}
private isBackingUp: boolean = false; // 🔥 添加后退状态标记