feat(战斗系统): 实现伤害队列机制优化战斗处理
重构伤害处理逻辑,将直接伤害组件改为队列系统 - 新增DamageQueueComp组件管理伤害事件队列 - 添加DamageQueueHelper工具类处理伤害事件添加和查询 - 修改HeroAtkSystem改为处理伤害队列而非单个伤害 - 移除旧的DmgDataCom组件及相关引用 - 优化SkillView.apply_damage使用新队列系统
This commit is contained in:
185
assets/script/game/hero/DamageQueueComp.ts
Normal file
185
assets/script/game/hero/DamageQueueComp.ts
Normal file
@@ -0,0 +1,185 @@
|
||||
import { ecs } from "../../../../extensions/oops-plugin-framework/assets/libs/ecs/ECS";
|
||||
import { HeroViewComp } from "./HeroViewComp";
|
||||
|
||||
/**
|
||||
* ==================== 伤害事件数据 ====================
|
||||
*
|
||||
* 单个伤害事件的数据结构
|
||||
*/
|
||||
export interface DamageEvent {
|
||||
/** 伤害属性数据 */
|
||||
Attrs: any;
|
||||
|
||||
/** 施法者 */
|
||||
caster: HeroViewComp;
|
||||
|
||||
/** 技能UUID */
|
||||
s_uuid: number;
|
||||
|
||||
/** 伤害创建时间戳(用于排序和调试) */
|
||||
timestamp: number;
|
||||
|
||||
/** 伤害事件ID(用于去重和调试) */
|
||||
eventId: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* ==================== 伤害队列组件 ====================
|
||||
*
|
||||
* 用途:
|
||||
* - 存储一个实体在当前帧收到的所有伤害事件
|
||||
* - 支持批量处理,避免同帧多伤害冲突
|
||||
* - 提供伤害事件的排序和去重功能
|
||||
*/
|
||||
@ecs.register('DamageQueue')
|
||||
export class DamageQueueComp extends ecs.Comp {
|
||||
/** 伤害事件队列 */
|
||||
damageEvents: DamageEvent[] = [];
|
||||
|
||||
/** 队列创建时间 */
|
||||
createTime: number = 0;
|
||||
|
||||
/** 是否正在处理中 */
|
||||
isProcessing: boolean = false;
|
||||
|
||||
/** 已处理的伤害数量 */
|
||||
processedCount: number = 0;
|
||||
|
||||
reset() {
|
||||
this.damageEvents = [];
|
||||
this.createTime = 0;
|
||||
this.isProcessing = false;
|
||||
this.processedCount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加伤害事件到队列
|
||||
*/
|
||||
addDamageEvent(attrs: any, caster: HeroViewComp, s_uuid: number): void {
|
||||
const timestamp = Date.now();
|
||||
const eventId = `${caster.ent.eid}_${s_uuid}_${timestamp}_${Math.random()}`;
|
||||
|
||||
const damageEvent: DamageEvent = {
|
||||
Attrs: attrs ? { ...attrs } : null, // 深拷贝属性数据
|
||||
caster: caster,
|
||||
s_uuid: s_uuid,
|
||||
timestamp: timestamp,
|
||||
eventId: eventId
|
||||
};
|
||||
|
||||
this.damageEvents.push(damageEvent);
|
||||
|
||||
// 如果是第一个伤害事件,记录创建时间
|
||||
if (this.damageEvents.length === 1) {
|
||||
this.createTime = timestamp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取下一个待处理的伤害事件
|
||||
*/
|
||||
getNextDamageEvent(): DamageEvent | null {
|
||||
if (this.damageEvents.length === 0) return null;
|
||||
return this.damageEvents.shift() || null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取队列中剩余的伤害事件数量
|
||||
*/
|
||||
getRemainingCount(): number {
|
||||
return this.damageEvents.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查队列是否为空
|
||||
*/
|
||||
isEmpty(): boolean {
|
||||
return this.damageEvents.length === 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 清空队列
|
||||
*/
|
||||
clear(): void {
|
||||
this.damageEvents = [];
|
||||
this.processedCount = 0;
|
||||
this.isProcessing = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按时间戳排序伤害事件(可选功能)
|
||||
*/
|
||||
sortByTimestamp(): void {
|
||||
this.damageEvents.sort((a, b) => a.timestamp - b.timestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* 去除重复的伤害事件(基于eventId)
|
||||
*/
|
||||
removeDuplicates(): void {
|
||||
const seen = new Set<string>();
|
||||
this.damageEvents = this.damageEvents.filter(event => {
|
||||
if (seen.has(event.eventId)) {
|
||||
return false;
|
||||
}
|
||||
seen.add(event.eventId);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取队列统计信息(用于调试)
|
||||
*/
|
||||
getQueueStats(): {
|
||||
totalEvents: number;
|
||||
processedEvents: number;
|
||||
remainingEvents: number;
|
||||
isProcessing: boolean;
|
||||
createTime: number;
|
||||
} {
|
||||
return {
|
||||
totalEvents: this.processedCount + this.damageEvents.length,
|
||||
processedEvents: this.processedCount,
|
||||
remainingEvents: this.damageEvents.length,
|
||||
isProcessing: this.isProcessing,
|
||||
createTime: this.createTime
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ==================== 伤害队列辅助工具 ====================
|
||||
*/
|
||||
export class DamageQueueHelper {
|
||||
/**
|
||||
* 为实体添加伤害事件
|
||||
* 如果实体没有伤害队列组件,会自动创建
|
||||
*/
|
||||
static addDamageToEntity(entity: ecs.Entity, attrs: any, caster: HeroViewComp, s_uuid: number): void {
|
||||
let damageQueue = entity.get(DamageQueueComp);
|
||||
|
||||
// 如果实体没有伤害队列组件,创建一个
|
||||
if (!damageQueue) {
|
||||
damageQueue = entity.add(DamageQueueComp);
|
||||
}
|
||||
|
||||
// 添加伤害事件到队列
|
||||
damageQueue.addDamageEvent(attrs, caster, s_uuid);
|
||||
}
|
||||
|
||||
/**
|
||||
* 检查实体是否有待处理的伤害
|
||||
*/
|
||||
static hasPendingDamage(entity: ecs.Entity): boolean {
|
||||
const damageQueue = entity.get(DamageQueueComp);
|
||||
return damageQueue ? !damageQueue.isEmpty() : false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取实体的伤害队列统计信息
|
||||
*/
|
||||
static getEntityDamageStats(entity: ecs.Entity): any {
|
||||
const damageQueue = entity.get(DamageQueueComp);
|
||||
return damageQueue ? damageQueue.getQueueStats() : null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user