import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS"; import { FacSet } from "../common/config/BoxSet"; import { Attrs } from "../common/config/HeroAttrs"; import { FightSet } from "../common/config/Mission"; import { SkillSet } from "../common/config/SkillSet"; import { HeroAttrsComp } from "./HeroAttrsComp"; 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; isCrit: boolean; isDodge: boolean; } /** 业务层业务逻辑处理对象 伤害处理系统 */ @ecs.register('HeroAtkSystem') export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate { private debugMode: boolean = false; // 是否启用调试模式 /** * 过滤器:处理拥有伤害队列的实体 */ filter(): ecs.IMatcher { return ecs.allOf(HeroAttrsComp, DamageQueueComp); } /** * 系统更新(每帧调用) * 处理伤害队列中的所有伤害事件 */ update(e: ecs.Entity): void { if(!smc.mission.play || smc.mission.pause) return; const model = e.get(HeroAttrsComp); const damageQueue = e.get(DamageQueueComp); if (!model || !damageQueue || damageQueue.isEmpty()) return; // 标记正在处理 damageQueue.isProcessing = true; // 处理队列中的所有伤害事件 let processedCount = 0; while (!damageQueue.isEmpty()) { const damageEvent = damageQueue.getNextDamageEvent(); if (!damageEvent) break; // 处理单个伤害事件 const FDData = this.doAttack(e, damageEvent); processedCount++; damageQueue.processedCount++; if (this.debugMode) { const casterName = damageEvent.caster?.ent?.get(HeroAttrsComp)?.hero_name || "未知"; const casterUuid = damageEvent.caster?.ent?.get(HeroAttrsComp)?.hero_uuid || 0; console.log(`[HeroAtkSystem] 英雄${model.hero_name} (uuid: ${model.hero_uuid}) 受到 ${casterName}(uuid: ${casterUuid})的 伤害 ${FDData.damage},${FDData.isCrit?"暴击":"普通"}攻击,技能ID ${damageEvent.s_uuid}`); } // 如果目标已死亡,停止处理后续伤害 if (model.is_dead) { if (this.debugMode) { console.log(`[HeroAtkSystem] ${model.hero_name} 已死亡,停止处理剩余伤害`); } damageQueue.clear(); // 清空剩余伤害 break; } } // 如果队列已空,移除伤害队列组件 if (damageQueue.isEmpty()) { e.remove(DamageQueueComp); if (this.debugMode && processedCount > 0) { console.log(`[HeroAtkSystem] ${model.hero_name} 伤害队列处理完成,共处理 ${processedCount} 个伤害事件`); } } } /** * 执行攻击计算 * @param target 目标实体 * @param damageEvent 伤害事件数据 * @returns 最终伤害数据 */ private doAttack(target: ecs.Entity, damageEvent: DamageEvent): FinalData { const targetModel = target.get(HeroAttrsComp); const targetView = target.get(HeroViewComp); let reDate:FinalData={ damage:0, isCrit:false, isDodge:false, } if (!targetModel || targetModel.is_dead) return reDate; // 获取攻击者数据 const caster = damageEvent.caster; const casterModel = caster.ent.get(HeroAttrsComp); if (!casterModel) return reDate; // 获取技能配置 const skillConf = SkillSet[damageEvent.s_uuid]; if (!skillConf) return reDate; // 触发被攻击事件 this.onAttacked(target); // 闪避判定 if (this.checkDodge(targetModel)) { // TODO: 触发闪避视图表现 reDate.isDodge=true; return reDate; } // 暴击判定 const isCrit = this.checkCrit(targetModel.Attrs[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)); reDate.isCrit=true; } // 伤害计算(考虑易伤等debuff) damage = this.calculateDamage(targetModel, damage); // 护盾吸收 damage =Math.floor(this.absorbShield(targetModel, damage)) if (damage <= 0) return reDate; // 应用伤害到数据层 targetModel.hp -= damage; targetModel.atked_count++; // ✅ 触发视图层表现(伤害数字、受击动画、后退) if (targetView) { targetView.do_atked(damage, isCrit, damageEvent.s_uuid); } // 检查死亡 if (targetModel.hp <= 0) { this.doDead(target); // ✅ 触发死亡视图表现 if (targetView) { targetView.do_dead(); } } if (this.debugMode) { console.log(`[HeroAtkSystem] ${targetModel.hero_name} 受到 ${damage} 点伤害 (暴击: ${isCrit})`); } reDate.damage=damage; return reDate; } //伤害计算,暂时简单计算 private dmgCount(CAttrs:any,s_uuid:number){ let sConf = SkillSet[s_uuid]; if (!sConf) return 0; let AP = sConf.ap*CAttrs[Attrs.AP]/100; return AP; } /** * 处理角色死亡 */ private doDead(entity: ecs.Entity): void { const model = entity.get(HeroAttrsComp); if (!model || model.is_dead) return; model.is_dead = true; // 触发死亡事件 this.onDeath(entity); if (this.debugMode) { console.log(`[HeroBattleSystem] ${model.hero_name} 死亡`); } } /** * 闪避判定 */ 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; } /** * 伤害计算(考虑易伤等debuff) */ private calculateDamage(model: HeroAttrsComp, baseDamage: number): number { // 这里可以添加易伤等debuff的计算逻辑 // 例如:如果目标有易伤buff,增加受到的伤害 return baseDamage; } /** * 护盾吸收伤害 */ private absorbShield(model: HeroAttrsComp, damage: number): number { if (model.shield <= 0) return damage; if (model.shield >= damage) { model.shield -= damage; if (model.shield <= 0) { model.shield = 0; model.Attrs[Attrs.SHIELD_MAX] = 0; } return 0; } else { const remainingDamage = damage - model.shield; model.shield = 0; model.Attrs[Attrs.SHIELD_MAX] = 0; return remainingDamage; } } /** * 被攻击时触发的事件 */ private onAttacked(entity: ecs.Entity): void { const model = entity.get(HeroAttrsComp); if (!model || model.is_dead) return; // 这里可以添加被攻击时的特殊处理逻辑 if (model.fac === FacSet.MON) return; // 例如:触发某些天赋效果、反击逻辑等 } /** * 死亡时触发的事件 */ private onDeath(entity: ecs.Entity): void { const model = entity.get(HeroAttrsComp); if (!model) return; if (model.fac === FacSet.MON) { // 怪物死亡处理 this.scheduleDrop(entity); } else if (model.fac === FacSet.HERO) { // 英雄死亡处理 this.scheduleHeroDeath(entity); } } /** * 延迟执行掉落逻辑 */ private scheduleDrop(entity: ecs.Entity): void { // 这里可以添加掉落逻辑 // 例如:延迟一段时间后生成掉落物品 } /** * 延迟执行英雄死亡逻辑 */ private scheduleHeroDeath(entity: ecs.Entity): void { // 这里可以添加英雄死亡的特殊处理 // 例如:触发游戏结束、复活机制等 } /** * 启用调试模式 */ enableDebug() { this.debugMode = true; } /** * 禁用调试模式 */ disableDebug() { this.debugMode = false; } }