Files
heros/assets/script/game/hero/DamageQueueComp.ts
panw 7a7a6fa02c fix(战斗系统): 修复伤害数值出错问题
- 修复在DamageEvent接口和DamageQueueComp缺少ext_dmg和dmg_ratio字段问题
- 修复HeroAtkSystem的伤害计算逻辑
- 优化HeroViewComp的hp_show和mp_show方法,直接使用model数据
- 默认显示血条并增加调试日志输出
- 移除冗余的debug日志,优化伤害计算流程
2025-11-28 09:59:01 +08:00

190 lines
5.2 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;
ext_dmg:number //额外伤害
dmg_ratio:number//伤害比例
}
/**
* ==================== 伤害队列组件 ====================
*
* 用途:
* - 存储一个实体在当前帧收到的所有伤害事件
* - 支持批量处理,避免同帧多伤害冲突
* - 提供伤害事件的排序和去重功能
*/
@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,ext_dmg:number=0,dmg_ratio:number=1): 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,
ext_dmg:ext_dmg,
dmg_ratio:dmg_ratio,
};
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,ext_dmg:number=0,dmg_ratio:number=1): void {
let damageQueue = entity.get(DamageQueueComp);
// 如果实体没有伤害队列组件,创建一个
if (!damageQueue) {
damageQueue = entity.add(DamageQueueComp);
}
// 添加伤害事件到队列
damageQueue.addDamageEvent(attrs, caster, s_uuid,ext_dmg,dmg_ratio);
}
/**
* 检查实体是否有待处理的伤害
*/
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;
}
}