Files
heros/assets/script/game/hero/DamageQueueComp.ts
walkpan b8f48e09d6 feat(战斗系统): 实现伤害队列机制优化战斗处理
重构伤害处理逻辑,将直接伤害组件改为队列系统
- 新增DamageQueueComp组件管理伤害事件队列
- 添加DamageQueueHelper工具类处理伤害事件添加和查询
- 修改HeroAtkSystem改为处理伤害队列而非单个伤害
- 移除旧的DmgDataCom组件及相关引用
- 优化SkillView.apply_damage使用新队列系统
2025-10-31 20:08:43 +08:00

185 lines
4.9 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;
}
}