feat(战斗系统): 实现伤害队列机制优化战斗处理
重构伤害处理逻辑,将直接伤害组件改为队列系统 - 新增DamageQueueComp组件管理伤害事件队列 - 添加DamageQueueHelper工具类处理伤害事件添加和查询 - 修改HeroAtkSystem改为处理伤害队列而非单个伤害 - 移除旧的DmgDataCom组件及相关引用 - 优化SkillView.apply_damage使用新队列系统
This commit is contained in:
@@ -3,9 +3,9 @@ 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 { DmgDataCom } from "../skill/SDataCom";
|
||||
import { HeroAttrsComp } from "./HeroAttrsComp";
|
||||
import { HeroViewComp } from "./HeroViewComp";
|
||||
import { DamageQueueComp, DamageEvent, DamageQueueHelper } from "./DamageQueueComp";
|
||||
|
||||
/** 业务层对象 */
|
||||
@ecs.register('HeroAtk')
|
||||
@@ -15,72 +15,99 @@ export class HeroAtkComp extends ecs.Comp {
|
||||
|
||||
}
|
||||
}
|
||||
interface FDData{
|
||||
damage:number,
|
||||
isCrit:boolean,
|
||||
isDodge:boolean,
|
||||
/** 最终伤害数据接口 */
|
||||
interface FinalData {
|
||||
damage: number;
|
||||
isCrit: boolean;
|
||||
isDodge: boolean;
|
||||
}
|
||||
/** 业务层业务逻辑处理对象 伤害处理系统 */
|
||||
@ecs.register('HeroAtkSystem')
|
||||
export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate, ecs.IEntityEnterSystem {
|
||||
export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpdate {
|
||||
|
||||
private debugMode: boolean = false; // 是否启用调试模式
|
||||
|
||||
/**
|
||||
* 过滤器:只处理拥有伤害数据的实体
|
||||
* 过滤器:处理拥有伤害队列的实体
|
||||
*/
|
||||
filter(): ecs.IMatcher {
|
||||
return ecs.allOf(HeroAttrsComp, DmgDataCom);
|
||||
return ecs.allOf(HeroAttrsComp, DamageQueueComp);
|
||||
}
|
||||
|
||||
/**
|
||||
* 实体首次进入系统时调用(每个实体只调用一次)
|
||||
* 系统更新(每帧调用)
|
||||
* 处理伤害队列中的所有伤害事件
|
||||
*/
|
||||
entityEnter(e: ecs.Entity): void {
|
||||
update(e: ecs.Entity): void {
|
||||
const model = e.get(HeroAttrsComp);
|
||||
const dmgData = e.get(DmgDataCom);
|
||||
if (!model || !dmgData) return;
|
||||
const caster = dmgData.caster;
|
||||
// 深度拷贝伤害数据,避免组件移除后数据丢失
|
||||
const dmgDataCopy = this.deepCopyDmgData(dmgData);
|
||||
// 立即移除组件,避免重复处理
|
||||
e.remove(DmgDataCom);
|
||||
const damageQueue = e.get(DamageQueueComp);
|
||||
|
||||
// 使用拷贝的数据进行伤害计算
|
||||
let FDData = this.doAttack(e, dmgDataCopy);
|
||||
console.log(`[HeroAtkSystem] 英雄${model.hero_name} (uuid: ${model.hero_uuid}) 受到 ${caster.ent.get(HeroAttrsComp).hero_name}(uuid: ${caster.ent.get(HeroAttrsComp).hero_uuid})的 伤害 ${FDData.damage},${FDData.isCrit?"暴击":"普通"}攻击,技能ID ${dmgDataCopy.s_uuid}`);
|
||||
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 deepCopyDmgData(dmgData: DmgDataCom): any {
|
||||
return {
|
||||
Attrs: dmgData.Attrs ? { ...dmgData.Attrs } : null,
|
||||
s_uuid: dmgData.s_uuid
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* 处理角色被攻击
|
||||
* @param target 被攻击的目标实体
|
||||
* @param dmgData 伤害数据(可以是组件或拷贝的对象)
|
||||
* @returns 实际造成的伤害
|
||||
*/
|
||||
public doAttack(target: ecs.Entity, dmgDataCopy: any): FDData {
|
||||
private doAttack(target: ecs.Entity, damageEvent: DamageEvent): FinalData {
|
||||
const targetModel = target.get(HeroAttrsComp);
|
||||
const targetView = target.get(HeroViewComp);
|
||||
let reDate:FDData={
|
||||
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[dmgDataCopy.s_uuid];
|
||||
const skillConf = SkillSet[damageEvent.s_uuid];
|
||||
if (!skillConf) return reDate;
|
||||
|
||||
// 触发被攻击事件
|
||||
@@ -95,7 +122,7 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
||||
|
||||
// 暴击判定
|
||||
const isCrit = this.checkCrit(targetModel.Attrs[Attrs.CRITICAL]);
|
||||
let damage = this.dmgCount(dmgDataCopy.Attrs,dmgDataCopy.s_uuid);
|
||||
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;
|
||||
@@ -114,7 +141,7 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
||||
|
||||
// ✅ 触发视图层表现(伤害数字、受击动画、后退)
|
||||
if (targetView) {
|
||||
targetView.do_atked(damage, isCrit, dmgDataCopy.s_uuid);
|
||||
targetView.do_atked(damage, isCrit, damageEvent.s_uuid);
|
||||
}
|
||||
|
||||
// 检查死亡
|
||||
@@ -273,12 +300,5 @@ export class HeroAtkSystem extends ecs.ComblockSystem implements ecs.ISystemUpd
|
||||
this.debugMode = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 系统更新(每帧调用)
|
||||
* 可以在这里添加需要每帧处理的战斗逻辑
|
||||
*/
|
||||
update(e: ecs.Entity): void {
|
||||
// 这里可以添加需要每帧处理的战斗逻辑
|
||||
// 例如:持续伤害、战斗状态检查等
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user