You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
AdLike2048/assets/mx/module/battle/combat/LifecycleSystem.ts

61 lines
2.5 KiB

3 weeks ago
import type { World, EntityId } from 'db://assets/mx/module/ecs';
18 hours ago
import { BattleEventFactory } from '../events/BattleEvents';
import type { BattleEventBus } from '../events/BattleEventBus';
3 weeks ago
import type { GridMap } from '../battlefield/GridMap';
import type { SpatialGrid } from '../battlefield/SpatialGrid';
import type { AbilitySystem } from './AbilitySystem';
/** 暂缓 kill 判定(还魂丹等:死亡特效播完再复活或真死) */
export type TryDeferEntityKillFn = (victim: EntityId, killer: EntityId, hpBeforeKill: number) => boolean;
/** 实体生命周期 */
export class LifecycleSystem {
private _tryDeferKill: TryDeferEntityKillFn | null = null;
constructor(
private readonly _world: World,
private readonly _grid: GridMap,
private readonly _spatial: SpatialGrid,
private readonly _events: BattleEventBus,
private readonly _abilities: AbilitySystem,
) {}
/** 注册暂缓 kill 回调(BattleSession.tryDeferEntityKill 桥接) */
setTryDeferKillPredicate(fn: TryDeferEntityKillFn | null): void {
this._tryDeferKill = fn;
}
/**
* @param victim 被击杀实体 ID
* @param killer 击杀者实体 ID
* @param hpBeforeKill 致死前血量(还魂丹等复活继承用)
* @param damageType 致死伤害类型
* @param fromPassiveResult 是否来自被动 result
*/
kill(victim: EntityId, killer: EntityId, hpBeforeKill = 0, damageType?: string, fromPassiveResult = false): void {
if (!this._world.isAlive(victim)) return;
if (this._tryDeferKill?.(victim, killer, hpBeforeKill)) return;
// 先解绑触发器,避免后续 fireEvent('OnKill') 仍把 victim 当作施法者
this._abilities.unbindEntity(victim);
this._grid.clearOccupant(victim);
this._spatial.removeEntity(victim);
// 立即派发:金币/飞桃需在 destroy 前读到 UnitMeta / 怪物节点
this._events.emit(BattleEventFactory.entityKilled(killer, victim, damageType, fromPassiveResult), true);
this._world.destroy(victim);
this._abilities.fireEvent('OnKill', { killer, victim });
}
/** 无击杀结算移除(复活回收上场怪等) */
despawn(entity: EntityId): void {
if (!this._world.isAlive(entity)) return;
this._abilities.unbindEntity(entity);
this._grid.clearOccupant(entity);
this._spatial.removeEntity(entity);
this._events.emit(BattleEventFactory.unitDespawned(entity), true);
this._world.destroy(entity);
}
}