refactor: 删除污染严重的 TEnemy 和 THero,仅在战斗系统中包含

This commit is contained in:
unanmed 2026-05-17 23:56:40 +08:00
parent 13e8547a37
commit 370f285964
25 changed files with 276 additions and 257 deletions

View File

@ -12,16 +12,18 @@ import {
} from './types'; } from './types';
import { SaveCompression } from '@user/data-common'; import { SaveCompression } from '@user/data-common';
export class EnemyManager<TAttr> implements IEnemyManager<TAttr> { export class EnemyManager<TEnemy> implements IEnemyManager<TEnemy> {
/** 特殊属性注册表code -> 创建函数 */ /** 特殊属性注册表code -> 创建函数 */
private readonly specialRegistry: Map<number, SpecialCreation<any, TAttr>> = private readonly specialRegistry: Map<
new Map(); number,
SpecialCreation<any, TEnemy>
> = new Map();
/** 自定义怪物属性注册表name -> 默认值 */ /** 自定义怪物属性注册表name -> 默认值 */
private readonly attributeRegistry: Map<keyof TAttr, any> = new Map(); private readonly attributeRegistry: Map<keyof TEnemy, any> = new Map();
/** 怪物模板表code -> IEnemy */ /** 怪物模板表code -> IEnemy */
private readonly prefabByCode: Map<number, IEnemy<TAttr>> = new Map(); private readonly prefabByCode: Map<number, IEnemy<TEnemy>> = new Map();
/** 怪物模板表id -> IEnemy */ /** 怪物模板表id -> IEnemy */
private readonly prefabById: Map<string, IEnemy<TAttr>> = new Map(); private readonly prefabById: Map<string, IEnemy<TEnemy>> = new Map();
/** 旧样板怪物 id 到 code 的映射,用于 fromLegacyEnemy 快速查找已有模板 */ /** 旧样板怪物 id 到 code 的映射,用于 fromLegacyEnemy 快速查找已有模板 */
private readonly legacyIdToCode: Map<string, number> = new Map(); private readonly legacyIdToCode: Map<string, number> = new Map();
/** 复用映射reusedCode -> sourceCode */ /** 复用映射reusedCode -> sourceCode */
@ -31,21 +33,21 @@ export class EnemyManager<TAttr> implements IEnemyManager<TAttr> {
/** 脏模板集合,存储发生了变化的模板 code */ /** 脏模板集合,存储发生了变化的模板 code */
private readonly dirtySet: Set<number> = new Set(); private readonly dirtySet: Set<number> = new Set();
/** 参考快照code -> IReadonlyEnemy由 compareWith 提供 */ /** 参考快照code -> IReadonlyEnemy由 compareWith 提供 */
private referenceByCode: Map<number, IReadonlyEnemy<TAttr>> = new Map(); private referenceByCode: Map<number, IReadonlyEnemy<TEnemy>> = new Map();
/** 当前附加的怪物比较器 */ /** 当前附加的怪物比较器 */
private comparer: IEnemyComparer<TAttr> | null = null; private comparer: IEnemyComparer<TEnemy> | null = null;
/** 是否已首次调用 compareWith */ /** 是否已首次调用 compareWith */
private hasReference: boolean = false; private hasReference: boolean = false;
constructor(readonly bridge: IEnemyLegacyBridge<TAttr>) {} constructor(readonly bridge: IEnemyLegacyBridge<TEnemy>) {}
registerSpecial(code: number, cons: SpecialCreation<any, TAttr>): void { registerSpecial(code: number, cons: SpecialCreation<any, TEnemy>): void {
this.specialRegistry.set(code, cons); this.specialRegistry.set(code, cons);
} }
setAttributeDefaults<K extends keyof TAttr>( setAttributeDefaults<K extends keyof TEnemy>(
name: K, name: K,
defaultValue: TAttr[K] defaultValue: TEnemy[K]
): void { ): void {
if ( if (
typeof defaultValue === 'function' || typeof defaultValue === 'function' ||
@ -59,7 +61,7 @@ export class EnemyManager<TAttr> implements IEnemyManager<TAttr> {
this.attributeRegistry.set(name, defaultValue); this.attributeRegistry.set(name, defaultValue);
} }
fromLegacyEnemy(code: number, enemy: Enemy): IEnemy<TAttr> { fromLegacyEnemy(code: number, enemy: Enemy): IEnemy<TEnemy> {
// 如果该旧样板怪物已经通过 addPrefabFromLegacy 注册为模板,直接克隆模板 // 如果该旧样板怪物已经通过 addPrefabFromLegacy 注册为模板,直接克隆模板
const existingCode = this.legacyIdToCode.get(enemy.id); const existingCode = this.legacyIdToCode.get(enemy.id);
if (existingCode) { if (existingCode) {
@ -76,15 +78,15 @@ export class EnemyManager<TAttr> implements IEnemyManager<TAttr> {
* *
* @param enemy * @param enemy
*/ */
private createAttributes(enemy: Enemy): TAttr { private createAttributes(enemy: Enemy): TEnemy {
const attrs: Partial<TAttr> = {}; const attrs: Partial<TEnemy> = {};
for (const [name, defaultValue] of this.attributeRegistry) { for (const [name, defaultValue] of this.attributeRegistry) {
attrs[name] = structuredClone(defaultValue); attrs[name] = structuredClone(defaultValue);
} }
Object.assign(attrs, this.bridge.fromLegacyEnemy(enemy, attrs)); Object.assign(attrs, this.bridge.fromLegacyEnemy(enemy, attrs));
return attrs as TAttr; return attrs as TEnemy;
} }
/** /**
@ -92,9 +94,9 @@ export class EnemyManager<TAttr> implements IEnemyManager<TAttr> {
* @param code * @param code
* @param enemy * @param enemy
*/ */
private convertLegacyEnemy(code: number, enemy: Enemy): IEnemy<TAttr> { private convertLegacyEnemy(code: number, enemy: Enemy): IEnemy<TEnemy> {
const attrs = this.createAttributes(enemy); const attrs = this.createAttributes(enemy);
const result = new EnemyImpl<TAttr>( const result = new EnemyImpl<TEnemy>(
enemy.id, enemy.id,
code, code,
structuredClone(attrs) structuredClone(attrs)
@ -114,13 +116,13 @@ export class EnemyManager<TAttr> implements IEnemyManager<TAttr> {
return result; return result;
} }
createEnemy(code: number): IEnemy<TAttr> | null { createEnemy(code: number): IEnemy<TEnemy> | null {
const prefab = this.prefabByCode.get(code); const prefab = this.prefabByCode.get(code);
if (!prefab) return null; if (!prefab) return null;
return prefab.clone(); return prefab.clone();
} }
createEnemyById(id: string): IEnemy<TAttr> | null { createEnemyById(id: string): IEnemy<TEnemy> | null {
const prefab = this.prefabById.get(id); const prefab = this.prefabById.get(id);
if (!prefab) return null; if (!prefab) return null;
return prefab.clone(); return prefab.clone();
@ -136,7 +138,7 @@ export class EnemyManager<TAttr> implements IEnemyManager<TAttr> {
} }
} }
addPrefab(enemy: IEnemy<TAttr>): void { addPrefab(enemy: IEnemy<TEnemy>): void {
if ( if (
this.prefabByCode.has(enemy.code) || this.prefabByCode.has(enemy.code) ||
this.prefabById.has(enemy.id) this.prefabById.has(enemy.id)
@ -160,12 +162,12 @@ export class EnemyManager<TAttr> implements IEnemyManager<TAttr> {
this.updateDirty(code, prefab); this.updateDirty(code, prefab);
} }
getPrefab(code: number): IReadonlyEnemy<TAttr> | null { getPrefab(code: number): IReadonlyEnemy<TEnemy> | null {
const sourceCode = this.reuseByCode.get(code) ?? code; const sourceCode = this.reuseByCode.get(code) ?? code;
return this.prefabByCode.get(sourceCode) ?? null; return this.prefabByCode.get(sourceCode) ?? null;
} }
getPrefabById(id: string): IReadonlyEnemy<TAttr> | null { getPrefabById(id: string): IReadonlyEnemy<TEnemy> | null {
const sourceId = this.reuseById.get(id) ?? id; const sourceId = this.reuseById.get(id) ?? id;
return this.prefabById.get(sourceId) ?? null; return this.prefabById.get(sourceId) ?? null;
} }
@ -177,7 +179,7 @@ export class EnemyManager<TAttr> implements IEnemyManager<TAttr> {
this.prefabById.delete(prefab.id); this.prefabById.delete(prefab.id);
} }
changePrefab(code: number | string, enemy: IEnemy<TAttr>): void { changePrefab(code: number | string, enemy: IEnemy<TEnemy>): void {
// 先删除旧的模板(如果存在) // 先删除旧的模板(如果存在)
this.deletePrefab(code); this.deletePrefab(code);
// 再添加新的模板 // 再添加新的模板
@ -193,7 +195,7 @@ export class EnemyManager<TAttr> implements IEnemyManager<TAttr> {
this.reuseById.set(id, prefab.id); this.reuseById.set(id, prefab.id);
} }
compareWith(reference: ReadonlyMap<number, IReadonlyEnemy<TAttr>>): void { compareWith(reference: ReadonlyMap<number, IReadonlyEnemy<TEnemy>>): void {
const isSubsequentCall = this.hasReference; const isSubsequentCall = this.hasReference;
if (isSubsequentCall) { if (isSubsequentCall) {
logger.warn(117); logger.warn(117);
@ -211,7 +213,7 @@ export class EnemyManager<TAttr> implements IEnemyManager<TAttr> {
modifyPrefabAttribute( modifyPrefabAttribute(
code: number | string, code: number | string,
modify: (prefab: IEnemy<TAttr>) => IEnemy<TAttr> modify: (prefab: IEnemy<TEnemy>) => IEnemy<TEnemy>
): void { ): void {
const prefab = this.internalGetPrefab(code); const prefab = this.internalGetPrefab(code);
if (!prefab) return; if (!prefab) return;
@ -230,16 +232,16 @@ export class EnemyManager<TAttr> implements IEnemyManager<TAttr> {
this.updateDirty(result.code, result); this.updateDirty(result.code, result);
} }
attachEnemyComparer(comparer: IEnemyComparer<TAttr>): void { attachEnemyComparer(comparer: IEnemyComparer<TEnemy>): void {
this.comparer = comparer; this.comparer = comparer;
} }
getEnemyComparer(): IEnemyComparer<TAttr> | null { getEnemyComparer(): IEnemyComparer<TEnemy> | null {
return this.comparer; return this.comparer;
} }
saveState(compression: SaveCompression): IEnemyManagerSaveState<TAttr> { saveState(compression: SaveCompression): IEnemyManagerSaveState<TEnemy> {
const modified: Map<number, IEnemySaveState<TAttr>> = new Map(); const modified: Map<number, IEnemySaveState<TEnemy>> = new Map();
for (const code of this.dirtySet) { for (const code of this.dirtySet) {
const prefab = this.prefabByCode.get(code); const prefab = this.prefabByCode.get(code);
if (!prefab) continue; if (!prefab) continue;
@ -249,7 +251,7 @@ export class EnemyManager<TAttr> implements IEnemyManager<TAttr> {
} }
loadState( loadState(
state: IEnemyManagerSaveState<TAttr>, state: IEnemyManagerSaveState<TEnemy>,
compression: SaveCompression compression: SaveCompression
): void { ): void {
for (const [code, enemyState] of state.modified) { for (const [code, enemyState] of state.modified) {
@ -269,7 +271,7 @@ export class EnemyManager<TAttr> implements IEnemyManager<TAttr> {
* @param code * @param code
* @param current * @param current
*/ */
private updateDirty(code: number, current: IEnemy<TAttr>): void { private updateDirty(code: number, current: IEnemy<TEnemy>): void {
if (!this.hasReference) return; if (!this.hasReference) return;
if (!this.comparer) { if (!this.comparer) {
logger.warn(118); logger.warn(118);

View File

@ -2,21 +2,26 @@ import { IHeroFollower, IHeroState } from './hero';
import { IEnemyManager } from './enemy'; import { IEnemyManager } from './enemy';
import { IFlagSystem } from './flag'; import { IFlagSystem } from './flag';
import { IMapStore } from './map'; import { IMapStore } from './map';
import { IDataCommon, ISaveableContent } from '@user/data-common'; import {
IDataCommon,
IEnemyAttr,
IHeroAttr,
ISaveableContent
} from '@user/data-common';
export interface IStateSaveData { export interface IStateSaveData {
/** 跟随者列表 */ /** 跟随者列表 */
readonly followers: readonly IHeroFollower[]; readonly followers: readonly IHeroFollower[];
} }
export interface IStateBase<TEnemy, THero> extends IDataCommon { export interface IStateBase extends IDataCommon {
/** 地图状态 */ /** 地图状态 */
readonly maps: IMapStore; readonly maps: IMapStore;
/** 勇士状态 */ /** 勇士状态 */
readonly hero: IHeroState<THero>; readonly hero: IHeroState<IHeroAttr>;
/** 怪物管理器 */ /** 怪物管理器 */
readonly enemyManager: IEnemyManager<TEnemy>; readonly enemyManager: IEnemyManager<IEnemyAttr>;
/** Flag 系统 */ /** Flag 系统 */
readonly flags: IFlagSystem; readonly flags: IFlagSystem;
@ -35,7 +40,7 @@ export interface IStateBase<TEnemy, THero> extends IDataCommon {
getSaveableContent<T>(id: string): ISaveableContent<T> | null; getSaveableContent<T>(id: string): ISaveableContent<T> | null;
} }
export interface IStateBaseExtended<TEnemy = unknown, THero = unknown> { export interface IStateBaseExtended {
/** 当前对象对应的数据层对象Layer 1 对象) */ /** 当前对象对应的数据层对象Layer 1 对象) */
readonly state: IStateBase<TEnemy, THero>; readonly state: IStateBase;
} }

View File

@ -1,6 +1,47 @@
import { ITileLocator } from '@motajs/common';
import { IFaceManager, IRoleFaceBinder } from './common'; import { IFaceManager, IRoleFaceBinder } from './common';
import { ITileStore } from './store'; import { ITileStore } from './store';
export interface IEnemyAttr {
/** 怪物生命值 */
hp: number;
/** 怪物攻击力 */
atk: number;
/** 怪物防御力 */
def: number;
/** 怪物金币 */
money: number;
/** 怪物经验值 */
exp: number;
/** 怪物加点量 */
point: number;
/** 支援来源怪物坐标索引列表 */
guard: Set<ITileLocator>;
}
export interface IHeroAttr {
/** 勇士名称 */
name: string;
/** 勇士生命值 */
hp: number;
/** 勇士生命值上限 */
hpmax: number;
/** 勇士攻击力 */
atk: number;
/** 勇士防御力 */
def: number;
/** 勇士护盾 */
mdef: number;
/** 勇士魔法值 */
mana: number;
/** 勇士魔法上限 */
manamax: number;
/** 勇士拥有的金币 */
money: number;
/** 勇士拥有的经验 */
exp: number;
}
export interface IDataCommon { export interface IDataCommon {
/** 图块定义存储 */ /** 图块定义存储 */
readonly tileStore: ITileStore<MapDataOf<keyof NumberToId>>; readonly tileStore: ITileStore<MapDataOf<keyof NumberToId>>;

View File

@ -11,7 +11,9 @@ import {
Dir4FaceHandler, Dir4FaceHandler,
Dir8FaceHandler, Dir8FaceHandler,
FaceGroup, FaceGroup,
FaceDirection FaceDirection,
IHeroAttr,
IEnemyAttr
} from '@user/data-common'; } from '@user/data-common';
import { import {
EnemyManager, EnemyManager,
@ -48,8 +50,7 @@ import {
MainMapDamageConverter, MainMapDamageConverter,
MainMapDamageReducer, MainMapDamageReducer,
registerSpecials, registerSpecials,
MainEnemyComparer, MainEnemyComparer
IEnemyAttr
} from './enemy'; } from './enemy';
import { import {
BG2_ZINDEX, BG2_ZINDEX,
@ -61,7 +62,6 @@ import {
TILE_HEIGHT, TILE_HEIGHT,
TILE_WIDTH TILE_WIDTH
} from './shared'; } from './shared';
import { IHeroAttr } from './hero';
import { LegacyTileData, TileLegacyBridge } from './legacy'; import { LegacyTileData, TileLegacyBridge } from './legacy';
import { ILoadProgressTotal, LoadProgressTotal } from '@motajs/loader'; import { ILoadProgressTotal, LoadProgressTotal } from '@motajs/loader';
import { isNil } from 'lodash-es'; import { isNil } from 'lodash-es';
@ -82,8 +82,8 @@ export class CoreState implements ICoreState {
// Layer 2 执行层,游戏逻辑对象都在这 // Layer 2 执行层,游戏逻辑对象都在这
readonly enemyContext: IEnemyContext<IEnemyAttr, IHeroAttr>; readonly enemyContext: IEnemyContext<IEnemyAttr, IHeroAttr>;
readonly triggerRegistry: ITriggerRegistry<IEnemyAttr, IHeroAttr>; readonly triggerRegistry: ITriggerRegistry;
readonly triggerCollector: ITriggerCollector<IEnemyAttr, IHeroAttr>; readonly triggerCollector: ITriggerCollector;
// 用户层内容,也就是最顶层的内容,一般仅用于初始化 // 用户层内容,也就是最顶层的内容,一般仅用于初始化
readonly loadProgress: ILoadProgressTotal; readonly loadProgress: ILoadProgressTotal;
@ -171,10 +171,8 @@ export class CoreState implements ICoreState {
this.enemyContext = enemyContext; this.enemyContext = enemyContext;
// 触发器注册与收集器 // 触发器注册与收集器
const triggerRegistry = new TriggerRegistry<IEnemyAttr, IHeroAttr>( const triggerRegistry = new TriggerRegistry(this);
this const triggerCollector = new TriggerCollector();
);
const triggerCollector = new TriggerCollector<IEnemyAttr, IHeroAttr>();
triggerCollector.attachRegistry(triggerRegistry); triggerCollector.attachRegistry(triggerRegistry);
this.triggerRegistry = triggerRegistry; this.triggerRegistry = triggerRegistry;
this.triggerCollector = triggerCollector; this.triggerCollector = triggerCollector;

View File

@ -18,8 +18,7 @@ import {
} from '@user/data-system'; } from '@user/data-system';
import { IReadonlyEnemy, ISpecial } from '@user/data-base'; import { IReadonlyEnemy, ISpecial } from '@user/data-base';
import { IHaloValue } from './special'; import { IHaloValue } from './special';
import { IEnemyAttr } from './types'; import { IHeroAttr, IEnemyAttr } from '@user/data-common';
import { IHeroAttr } from '../hero';
const FULL_RANGE = new FullRange(); const FULL_RANGE = new FullRange();
const RECT_RANGE = new RectRange(); const RECT_RANGE = new RectRange();
@ -176,7 +175,7 @@ export class GuardAura implements IEnemyAuraView<
if (locator.x === this.locator.x && locator.y === this.locator.y) { if (locator.x === this.locator.x && locator.y === this.locator.y) {
return; return;
} }
enemy.getAttribute('guard').add(this.sourceView); enemy.getAttribute('guard').add(this.locator);
} }
applySpecial(): IEnemySpecialModifier<IEnemyAttr> | null { applySpecial(): IEnemySpecialModifier<IEnemyAttr> | null {

View File

@ -4,10 +4,10 @@ import {
IEnemyDamageInfo, IEnemyDamageInfo,
IReadonlyEnemyHandler IReadonlyEnemyHandler
} from '@user/data-system'; } from '@user/data-system';
import { IEnemyAttr } from './types'; import { IEnemyAttr, IHeroAttr } from '@user/data-common';
import { IVampireValue } from './special'; import { IVampireValue } from './special';
import { IHeroAttr } from '../hero';
import { state } from '../ins'; import { state } from '../ins';
import { logger } from '@motajs/common';
export class MainDamageCalculator implements IDamageCalculator< export class MainDamageCalculator implements IDamageCalculator<
IEnemyAttr, IEnemyAttr,
@ -87,8 +87,14 @@ export class MainDamageCalculator implements IDamageCalculator<
// 因此回合数需要加上打支援怪的回合数 // 因此回合数需要加上打支援怪的回合数
for (const guard of guards) { for (const guard of guards) {
// 直接把 enemy 传过去,因此支援的 enemy 会吃到其原本所在位置的光环加成 // 直接把 enemy 传过去,因此支援的 enemy 会吃到其原本所在位置的光环加成
const view = handler.context.getEnemyByLocator(guard);
if (!view) {
logger.warn(137, guard.x.toString(), guard.y.toString());
continue;
}
const extraInfo = this.calculate({ const extraInfo = this.calculate({
enemy: guard.getComputedEnemy(), enemy: view.getComputedEnemy(),
context: handler.context,
locator, locator,
hero, hero,
data: handler.data data: handler.data

View File

@ -1,5 +1,5 @@
import { IEnemyComparer, IReadonlyEnemy } from '@user/data-base'; import { IEnemyComparer, IReadonlyEnemy } from '@user/data-base';
import { IEnemyAttr } from './types'; import { IEnemyAttr } from '@user/data-common';
export class MainEnemyComparer implements IEnemyComparer<IEnemyAttr> { export class MainEnemyComparer implements IEnemyComparer<IEnemyAttr> {
compare( compare(

View File

@ -1,6 +1,5 @@
import { IEnemyFinalEffect, IEnemyHandler } from '@user/data-system'; import { IEnemyFinalEffect, IEnemyHandler } from '@user/data-system';
import { IEnemyAttr } from './types'; import { IEnemyAttr, IHeroAttr } from '@user/data-common';
import { IHeroAttr } from '../hero';
export class MainEnemyFinalEffect implements IEnemyFinalEffect< export class MainEnemyFinalEffect implements IEnemyFinalEffect<
IEnemyAttr, IEnemyAttr,

View File

@ -1,5 +1,5 @@
import { IEnemyLegacyBridge } from '@user/data-base'; import { IEnemyLegacyBridge } from '@user/data-base';
import { IEnemyAttr } from './types'; import { IEnemyAttr } from '@user/data-common';
export class EnemyLegacyBridge implements IEnemyLegacyBridge<IEnemyAttr> { export class EnemyLegacyBridge implements IEnemyLegacyBridge<IEnemyAttr> {
fromLegacyEnemy( fromLegacyEnemy(

View File

@ -24,8 +24,8 @@ import {
IReadonlyEnemy IReadonlyEnemy
} from '@user/data-base'; } from '@user/data-base';
import { IZoneValue } from './special'; import { IZoneValue } from './special';
import { IEnemyAttr, MapDamageType } from './types'; import { MapDamageType } from './types';
import { IHeroAttr } from '../hero'; import { IHeroAttr, IEnemyAttr } from '@user/data-common';
import { IFaceHandler, FaceGroup } from '@user/data-common'; import { IFaceHandler, FaceGroup } from '@user/data-common';
const RECT_RANGE = new RectRange(); const RECT_RANGE = new RectRange();

View File

@ -4,7 +4,7 @@ import {
IEnemyManager IEnemyManager
} from '@user/data-base'; } from '@user/data-base';
import { getHeroStatusOn } from '../legacy/hero'; import { getHeroStatusOn } from '../legacy/hero';
import { IEnemyAttr } from './types'; import { IEnemyAttr } from '@user/data-common';
//#region 复合属性值类型 //#region 复合属性值类型

View File

@ -1,5 +1,3 @@
import { IEnemyView } from '@user/data-system';
export interface IEnemyAttr { export interface IEnemyAttr {
/** 怪物生命值 */ /** 怪物生命值 */
hp: number; hp: number;
@ -13,8 +11,8 @@ export interface IEnemyAttr {
exp: number; exp: number;
/** 怪物加点量 */ /** 怪物加点量 */
point: number; point: number;
/** 支援来源怪物视图列表 */ /** 支援来源怪物坐标索引列表 */
guard: Set<IEnemyView<IEnemyAttr>>; guard: Set<number>;
} }
export const enum MapDamageType { export const enum MapDamageType {

View File

@ -1,26 +1,5 @@
//#region 勇士属性 //#region 勇士属性
export interface IHeroAttr { export interface IHeroAttr {}
/** 勇士名称 */
name: string;
/** 勇士生命值 */
hp: number;
/** 勇士生命值上限 */
hpmax: number;
/** 勇士攻击力 */
atk: number;
/** 勇士防御力 */
def: number;
/** 勇士护盾 */
mdef: number;
/** 勇士魔法值 */
mana: number;
/** 勇士魔法上限 */
manamax: number;
/** 勇士拥有的金币 */
money: number;
/** 勇士拥有的经验 */
exp: number;
}
//#endregion //#endregion

View File

@ -1,4 +1,4 @@
import { IHeroAttr } from './hero'; import { IHeroAttr } from '@user/data-common';
//#region 地图相关 //#region 地图相关

View File

@ -1,21 +1,19 @@
import { IMotaDataLoader, IStateBase } from '@user/data-base'; import { IMotaDataLoader, IStateBase } from '@user/data-base';
import { IEnemyAttr } from './enemy';
import { IHeroAttr } from './hero';
import { ILoadProgressTotal } from '@motajs/loader'; import { ILoadProgressTotal } from '@motajs/loader';
import { ISaveSystem } from './save'; import { ISaveSystem } from './save';
import { IStateSystem } from '@user/data-system'; import { IStateSystem } from '@user/data-system';
import { ISaveableContent } from '@user/data-common'; import { ISaveableContent } from '@user/data-common';
export interface ISaveableExecutor<T, TEnemy = IEnemyAttr, THero = IHeroAttr> { export interface ISaveableExecutor<T> {
/** /**
* *
* @param data * @param data
* @param state * @param state
*/ */
afterLoad(data: T, state: IStateBase<TEnemy, THero>): void; afterLoad(data: T, state: IStateBase): void;
} }
export interface ICoreState extends IStateSystem<IEnemyAttr, IHeroAttr> { export interface ICoreState extends IStateSystem {
/** 加载进度对象 */ /** 加载进度对象 */
readonly loadProgress: ILoadProgressTotal; readonly loadProgress: ILoadProgressTotal;
/** 数据端加载对象 */ /** 数据端加载对象 */

View File

@ -100,7 +100,7 @@ export class EnemyContext<TEnemy, THero> implements IEnemyContext<
width: number = 0; width: number = 0;
height: number = 0; height: number = 0;
constructor(readonly dataState: IStateBase<TEnemy, THero>) {} constructor(readonly dataState: IStateBase) {}
resize(width: number, height: number): void { resize(width: number, height: number): void {
this.clear(); this.clear();
@ -210,7 +210,13 @@ export class EnemyContext<TEnemy, THero> implements IEnemyContext<
enemy: IEnemy<TEnemy>, enemy: IEnemy<TEnemy>,
locator: ITileLocator locator: ITileLocator
): IEnemyHandler<TEnemy, THero> { ): IEnemyHandler<TEnemy, THero> {
return { enemy, locator, hero: this.bindedHero!, data: this.dataState }; return {
enemy,
context: this,
locator,
hero: this.bindedHero!,
data: this.dataState
};
} }
getEnemyLocator(enemy: IEnemy<TEnemy>): Readonly<ITileLocator> | null { getEnemyLocator(enemy: IEnemy<TEnemy>): Readonly<ITileLocator> | null {

View File

@ -34,7 +34,7 @@ export class DamageContext<TEnemy, THero> implements IDamageContext<
/** 当前勇士属性 */ /** 当前勇士属性 */
protected heroStatus: IReadonlyHeroAttribute<THero> | null; protected heroStatus: IReadonlyHeroAttribute<THero> | null;
readonly dataState: IStateBase<TEnemy, THero>; readonly dataState: IStateBase;
constructor( constructor(
readonly context: IEnemyContext<TEnemy, THero>, readonly context: IEnemyContext<TEnemy, THero>,
@ -57,7 +57,13 @@ export class DamageContext<TEnemy, THero> implements IDamageContext<
locator: ITileLocator, locator: ITileLocator,
hero: IReadonlyHeroAttribute<THero> hero: IReadonlyHeroAttribute<THero>
): IReadonlyEnemyHandler<TEnemy, THero> { ): IReadonlyEnemyHandler<TEnemy, THero> {
return { enemy, locator, hero, data: this.dataState }; return {
enemy,
context: this.context,
locator,
hero,
data: this.dataState
};
} }
getDamageInfo(enemy: IEnemyView<TEnemy>): IEnemyDamageInfo | null { getDamageInfo(enemy: IEnemyView<TEnemy>): IEnemyDamageInfo | null {

View File

@ -64,7 +64,7 @@ export class MapDamage<TEnemy, THero> implements IMapDamage<TEnemy, THero> {
/** 坐标索引对象 */ /** 坐标索引对象 */
private readonly indexer: ILocationHelper; private readonly indexer: ILocationHelper;
readonly dataState: IStateBase<TEnemy, THero>; readonly dataState: IStateBase;
constructor(readonly context: IEnemyContext<TEnemy, THero>) { constructor(readonly context: IEnemyContext<TEnemy, THero>) {
this.indexer = context.indexer; this.indexer = context.indexer;
@ -89,6 +89,7 @@ export class MapDamage<TEnemy, THero> implements IMapDamage<TEnemy, THero> {
if (!hero) return null; if (!hero) return null;
return { return {
enemy: view.getComputedEnemy(), enemy: view.getComputedEnemy(),
context: this.context,
locator, locator,
hero, hero,
data: this.context.dataState data: this.context.dataState

View File

@ -14,23 +14,27 @@ import { ILocationHelper } from '@user/data-common';
export interface IEnemyHandler<TEnemy, THero> { export interface IEnemyHandler<TEnemy, THero> {
/** 怪物属性信息 */ /** 怪物属性信息 */
readonly enemy: IEnemy<TEnemy>; readonly enemy: IEnemy<TEnemy>;
/** 怪物上下文 */
readonly context: IEnemyContext<TEnemy, THero>;
/** 怪物定位符 */ /** 怪物定位符 */
readonly locator: ITileLocator; readonly locator: ITileLocator;
/** 勇士属性信息 */ /** 勇士属性信息 */
readonly hero: IReadonlyHeroAttribute<THero>; readonly hero: IReadonlyHeroAttribute<THero>;
/** 当前全局状态对象 */ /** 当前全局状态对象 */
readonly data: IStateBase<TEnemy, THero>; readonly data: IStateBase;
} }
export interface IReadonlyEnemyHandler<TEnemy, THero> { export interface IReadonlyEnemyHandler<TEnemy, THero> {
/** 怪物属性信息 */ /** 怪物属性信息 */
readonly enemy: IReadonlyEnemy<TEnemy>; readonly enemy: IReadonlyEnemy<TEnemy>;
/** 怪物上下文 */
readonly context: IReadonlyEnemyContext<TEnemy, THero>;
/** 怪物定位符 */ /** 怪物定位符 */
readonly locator: ITileLocator; readonly locator: ITileLocator;
/** 勇士属性信息 */ /** 勇士属性信息 */
readonly hero: IReadonlyHeroAttribute<THero>; readonly hero: IReadonlyHeroAttribute<THero>;
/** 当前全局状态对象 */ /** 当前全局状态对象 */
readonly data: IStateBase<TEnemy, THero>; readonly data: IStateBase;
} }
//#endregion //#endregion
@ -282,7 +286,7 @@ export interface IMapDamage<TEnemy, THero> {
/** 当前绑定的怪物上下文 */ /** 当前绑定的怪物上下文 */
readonly context: IEnemyContext<TEnemy, THero>; readonly context: IEnemyContext<TEnemy, THero>;
/** 地图伤害系统绑定的全局状态对象 */ /** 地图伤害系统绑定的全局状态对象 */
readonly dataState: IStateBase<TEnemy, THero>; readonly dataState: IStateBase;
/** /**
* *
@ -398,7 +402,7 @@ export interface IDamageCalculator<TEnemy, THero> {
export interface IDamageContext<TEnemy, THero> { export interface IDamageContext<TEnemy, THero> {
/** 伤害上下文所属的全局状态对象 */ /** 伤害上下文所属的全局状态对象 */
readonly dataState: IStateBase<TEnemy, THero>; readonly dataState: IStateBase;
/** /**
* *
@ -479,7 +483,7 @@ export interface IDamageSystem<TEnemy, THero> extends IDamageContext<
//#region 上下文 //#region 上下文
export interface IEnemyContext<TEnemy, THero> { export interface IReadonlyEnemyContext<TEnemy, THero> {
/** 怪物上下文宽度 */ /** 怪物上下文宽度 */
readonly width: number; readonly width: number;
/** 怪物上下文高度 */ /** 怪物上下文高度 */
@ -487,7 +491,84 @@ export interface IEnemyContext<TEnemy, THero> {
/** 此上下文使用的索引对象 */ /** 此上下文使用的索引对象 */
readonly indexer: ILocationHelper; readonly indexer: ILocationHelper;
/** 当前怪物上下文绑定的全局状态对象 */ /** 当前怪物上下文绑定的全局状态对象 */
readonly dataState: IStateBase<TEnemy, THero>; readonly dataState: IStateBase;
/**
*
*/
getBindedHero(): IReadonlyHeroAttribute<THero> | null;
/**
*
* @param enemy
*/
getEnemyLocator(enemy: IEnemy<TEnemy>): Readonly<ITileLocator> | null;
/**
*
* @param view
*/
getEnemyLocatorByView(
view: IEnemyView<TEnemy>
): Readonly<ITileLocator> | null;
/**
*
* @param locator
*/
getEnemyByLocator(locator: ITileLocator): IEnemyView<TEnemy> | null;
/**
*
* @param x
* @param y
*/
getEnemyByLoc(x: number, y: number): IEnemyView<TEnemy> | null;
/**
*
* @param enemy
*/
getViewByComputed(enemy: IReadonlyEnemy<TEnemy>): IEnemyView<TEnemy> | null;
/**
*
* @param range
* @param param
*/
scanRange<T>(
range: IRange<T>,
param: T
): Iterable<[ITileLocator, IEnemyView<TEnemy>]>;
/**
*
*/
iterateEnemy(): Iterable<[ITileLocator, IEnemyView<TEnemy>]>;
/**
*
*/
getMapDamage(): IMapDamage<TEnemy, THero> | null;
/**
*
*/
getDamageSystem(): IDamageSystem<TEnemy, THero> | null;
}
export interface IEnemyContext<TEnemy, THero> extends IReadonlyEnemyContext<
TEnemy,
THero
> {
/** 怪物上下文宽度 */
readonly width: number;
/** 怪物上下文高度 */
readonly height: number;
/** 此上下文使用的索引对象 */
readonly indexer: ILocationHelper;
/** 当前怪物上下文绑定的全局状态对象 */
readonly dataState: IStateBase;
/** /**
* *
@ -572,44 +653,6 @@ export interface IEnemyContext<TEnemy, THero> {
*/ */
bindHero(hero: IReadonlyHeroAttribute<THero> | null): void; bindHero(hero: IReadonlyHeroAttribute<THero> | null): void;
/**
*
*/
getBindedHero(): IReadonlyHeroAttribute<THero> | null;
/**
*
* @param enemy
*/
getEnemyLocator(enemy: IEnemy<TEnemy>): Readonly<ITileLocator> | null;
/**
*
* @param view
*/
getEnemyLocatorByView(
view: IEnemyView<TEnemy>
): Readonly<ITileLocator> | null;
/**
*
* @param locator
*/
getEnemyByLocator(locator: ITileLocator): IEnemyView<TEnemy> | null;
/**
*
* @param x
* @param y
*/
getEnemyByLoc(x: number, y: number): IEnemyView<TEnemy> | null;
/**
*
* @param enemy
*/
getViewByComputed(enemy: IReadonlyEnemy<TEnemy>): IEnemyView<TEnemy> | null;
/** /**
* *
* @param locator * @param locator
@ -623,21 +666,6 @@ export interface IEnemyContext<TEnemy, THero> {
*/ */
deleteEnemy(locator: ITileLocator): void; deleteEnemy(locator: ITileLocator): void;
/**
*
* @param range
* @param param
*/
scanRange<T>(
range: IRange<T>,
param: T
): Iterable<[ITileLocator, IEnemyView<TEnemy>]>;
/**
*
*/
iterateEnemy(): Iterable<[ITileLocator, IEnemyView<TEnemy>]>;
/** /**
* *
* @param aura * @param aura
@ -656,22 +684,12 @@ export interface IEnemyContext<TEnemy, THero> {
*/ */
attachMapDamage(damage: IMapDamage<TEnemy, THero> | null): void; attachMapDamage(damage: IMapDamage<TEnemy, THero> | null): void;
/**
*
*/
getMapDamage(): IMapDamage<TEnemy, THero> | null;
/** /**
* *
* @param system * @param system
*/ */
attachDamageSystem(system: IDamageSystem<TEnemy, unknown> | null): void; attachDamageSystem(system: IDamageSystem<TEnemy, unknown> | null): void;
/**
*
*/
getDamageSystem(): IDamageSystem<TEnemy, THero> | null;
/** /**
* *
* *

View File

@ -1,13 +1,10 @@
import { ITrigger, ITriggerCollection, ITriggerHandler } from './types'; import { ITrigger, ITriggerCollection, ITriggerHandler } from './types';
export class TriggerCollection< export class TriggerCollection implements ITriggerCollection {
TEnemy = unknown,
THero = unknown
> implements ITriggerCollection<TEnemy, THero> {
/** 当前集合内部维护的触发器列表 */ /** 当前集合内部维护的触发器列表 */
private readonly triggerList: ITrigger<TEnemy, THero>[]; private readonly triggerList: ITrigger[];
constructor(triggers: Iterable<ITrigger<TEnemy, THero>>) { constructor(triggers: Iterable<ITrigger>) {
this.triggerList = [...triggers]; this.triggerList = [...triggers];
} }
@ -15,19 +12,15 @@ export class TriggerCollection<
return this.triggerList.length; return this.triggerList.length;
} }
async trigger(handler: ITriggerHandler<TEnemy, THero>): Promise<void> { async trigger(handler: ITriggerHandler): Promise<void> {
for (const trigger of this.triggerList) { for (const trigger of this.triggerList) {
await trigger.trigger(handler); await trigger.trigger(handler);
} }
} }
async *triggerIter( async *triggerIter(
handler: ITriggerHandler<TEnemy, THero> handler: ITriggerHandler
): AsyncGenerator< ): AsyncGenerator<ITrigger, void, ITriggerHandler | null> {
ITrigger<TEnemy, THero>,
void,
ITriggerHandler<TEnemy, THero> | null
> {
let currentHandler = handler; let currentHandler = handler;
for (const trigger of this.triggerList) { for (const trigger of this.triggerList) {
await trigger.trigger(currentHandler); await trigger.trigger(currentHandler);
@ -40,21 +33,19 @@ export class TriggerCollection<
} }
} }
iterate(): Iterable<ITrigger<TEnemy, THero>> { iterate(): Iterable<ITrigger> {
return this.triggerList.values(); return this.triggerList.values();
} }
push(trigger: ITrigger<TEnemy, THero>): void { push(trigger: ITrigger): void {
this.triggerList.push(trigger); this.triggerList.push(trigger);
} }
unshift(trigger: ITrigger<TEnemy, THero>): void { unshift(trigger: ITrigger): void {
this.triggerList.unshift(trigger); this.triggerList.unshift(trigger);
} }
concat( concat(...others: ITriggerCollection[]): ITriggerCollection {
...others: ITriggerCollection<TEnemy, THero>[]
): ITriggerCollection<TEnemy, THero> {
const merged = [...this.triggerList]; const merged = [...this.triggerList];
for (const other of others) { for (const other of others) {
merged.push(...other.iterate()); merged.push(...other.iterate());

View File

@ -8,18 +8,11 @@ import {
import { logger } from '@motajs/common'; import { logger } from '@motajs/common';
import { TriggerCollection } from './collection'; import { TriggerCollection } from './collection';
export class TriggerCollector< export class TriggerCollector implements ITriggerCollector {
TEnemy = unknown,
THero = unknown
> implements ITriggerCollector<TEnemy, THero> {
/** 当前收集器使用的注册对象 */ /** 当前收集器使用的注册对象 */
private registry: ITriggerRegistry<TEnemy, THero> | null = null; private registry: ITriggerRegistry | null = null;
collect( collect(x: number, y: number, layer: IMapLayer): ITriggerCollection {
x: number,
y: number,
layer: IMapLayer
): ITriggerCollection<TEnemy, THero> {
if (!this.registry) { if (!this.registry) {
logger.warn(135); logger.warn(135);
return new TriggerCollection([]); return new TriggerCollection([]);
@ -62,8 +55,8 @@ export class TriggerCollector<
const duplicate = new Set<number>(); const duplicate = new Set<number>();
if (staticTrigger) { if (staticTrigger) {
// 有静态触发器 // 有静态触发器
const lessTriggers: ITrigger<TEnemy, THero>[] = []; const lessTriggers: ITrigger[] = [];
const greaterTriggers: ITrigger<TEnemy, THero>[] = []; const greaterTriggers: ITrigger[] = [];
// 先收集所有的触发器,并记录重复情况 // 先收集所有的触发器,并记录重复情况
for (const tile of layer.dynamicLayer.getDynamicTilesAt(x, y)) { for (const tile of layer.dynamicLayer.getDynamicTilesAt(x, y)) {
const trigger = this.registry.create(tile.triggerType); const trigger = this.registry.create(tile.triggerType);
@ -92,7 +85,7 @@ export class TriggerCollector<
return new TriggerCollection(arr); return new TriggerCollection(arr);
} else { } else {
// 没有静态触发器 // 没有静态触发器
const triggers: ITrigger<TEnemy, THero>[] = []; const triggers: ITrigger[] = [];
for (const tile of layer.dynamicLayer.getDynamicTilesAt(x, y)) { for (const tile of layer.dynamicLayer.getDynamicTilesAt(x, y)) {
const trigger = this.registry.create(tile.triggerType); const trigger = this.registry.create(tile.triggerType);
if (trigger) { if (trigger) {
@ -113,7 +106,7 @@ export class TriggerCollector<
} }
} }
attachRegistry(registry: ITriggerRegistry<TEnemy, THero> | null): void { attachRegistry(registry: ITriggerRegistry | null): void {
this.registry = registry; this.registry = registry;
} }
} }

View File

@ -2,28 +2,24 @@ import { logger } from '@motajs/common';
import { ITrigger, ITriggerRegistry, TriggerFactory } from './types'; import { ITrigger, ITriggerRegistry, TriggerFactory } from './types';
import { IStateBase } from '@user/data-base'; import { IStateBase } from '@user/data-base';
export class TriggerRegistry< export class TriggerRegistry implements ITriggerRegistry {
TEnemy = unknown,
THero = unknown
> implements ITriggerRegistry<TEnemy, THero> {
/** 数字类型到触发器工厂的映射 */ /** 数字类型到触发器工厂的映射 */
private readonly typeMap: Map<number, TriggerFactory<TEnemy, THero>> = private readonly typeMap: Map<number, TriggerFactory> = new Map();
new Map();
constructor(public readonly state: IStateBase<TEnemy, THero>) {} constructor(public readonly state: IStateBase) {}
register(type: number, factory: TriggerFactory<TEnemy, THero>): void { register(type: number, factory: TriggerFactory): void {
if (this.typeMap.has(type)) { if (this.typeMap.has(type)) {
logger.warn(132, 'type', type.toString()); logger.warn(132, 'type', type.toString());
} }
this.typeMap.set(type, factory); this.typeMap.set(type, factory);
} }
get(type: number): TriggerFactory<TEnemy, THero> | null { get(type: number): TriggerFactory | null {
return this.typeMap.get(type) ?? null; return this.typeMap.get(type) ?? null;
} }
create(num: number): ITrigger<TEnemy, THero> | null { create(num: number): ITrigger | null {
const factory = this.get(num); const factory = this.get(num);
if (!factory) return null; if (!factory) return null;
return factory(num, this.state); return factory(num, this.state);

View File

@ -6,9 +6,9 @@ import {
IStateBaseExtended IStateBaseExtended
} from '@user/data-base'; } from '@user/data-base';
export interface ITriggerHandler<TEnemy = unknown, THero = unknown> { export interface ITriggerHandler {
/** 当前全局状态对象 */ /** 当前全局状态对象 */
readonly state: IStateBase<TEnemy, THero>; readonly state: IStateBase;
/** 当前楼层状态对象 */ /** 当前楼层状态对象 */
readonly layer?: ILayerState; readonly layer?: ILayerState;
/** 当前参与触发的图层对象 */ /** 当前参与触发的图层对象 */
@ -17,15 +17,9 @@ export interface ITriggerHandler<TEnemy = unknown, THero = unknown> {
readonly locator?: ITileLocator; readonly locator?: ITileLocator;
} }
export type TriggerFactory<TEnemy, THero> = ( export type TriggerFactory = (type: number, state: IStateBase) => ITrigger;
type: number,
state: IStateBase<TEnemy, THero>
) => ITrigger<TEnemy, THero>;
export interface ITrigger< export interface ITrigger extends IStateBaseExtended {
TEnemy = unknown,
THero = unknown
> extends IStateBaseExtended<TEnemy, THero> {
/** 触发器类型标识 */ /** 触发器类型标识 */
readonly type: number; readonly type: number;
/** 触发器优先级 */ /** 触发器优先级 */
@ -35,39 +29,36 @@ export interface ITrigger<
* 使 * 使
* @param handler * @param handler
*/ */
trigger(handler: ITriggerHandler<TEnemy, THero>): Promise<void>; trigger(handler: ITriggerHandler): Promise<void>;
/** /**
* *
*/ */
collection(): ITriggerCollection<TEnemy, THero>; collection(): ITriggerCollection;
} }
export interface ITriggerRegistry< export interface ITriggerRegistry extends IStateBaseExtended {
TEnemy = unknown,
THero = unknown
> extends IStateBaseExtended<TEnemy, THero> {
/** /**
* *
* @param type * @param type
* @param factory * @param factory
*/ */
register(type: number, factory: TriggerFactory<TEnemy, THero>): void; register(type: number, factory: TriggerFactory): void;
/** /**
* *
* @param type * @param type
*/ */
get(type: number): TriggerFactory<TEnemy, THero> | null; get(type: number): TriggerFactory | null;
/** /**
* `null` * `null`
* @param num * @param num
*/ */
create(num: number): ITrigger<TEnemy, THero> | null; create(num: number): ITrigger | null;
} }
export interface ITriggerCollection<TEnemy, THero> { export interface ITriggerCollection {
/** /**
* *
*/ */
@ -77,62 +68,52 @@ export interface ITriggerCollection<TEnemy, THero> {
* *
* @param handler * @param handler
*/ */
trigger(handler: ITriggerHandler<TEnemy, THero>): Promise<void>; trigger(handler: ITriggerHandler): Promise<void>;
/** /**
* *
* @param handler * @param handler
*/ */
triggerIter( triggerIter(
handler: ITriggerHandler<TEnemy, THero> handler: ITriggerHandler
): AsyncGenerator< ): AsyncGenerator<ITrigger, void, ITriggerHandler | null>;
ITrigger<TEnemy, THero>,
void,
ITriggerHandler<TEnemy, THero> | null
>;
/** /**
* *
*/ */
iterate(): Iterable<ITrigger<TEnemy, THero>>; iterate(): Iterable<ITrigger>;
/** /**
* *
* @param trigger * @param trigger
*/ */
push(trigger: ITrigger<TEnemy, THero>): void; push(trigger: ITrigger): void;
/** /**
* *
* @param trigger * @param trigger
*/ */
unshift(trigger: ITrigger<TEnemy, THero>): void; unshift(trigger: ITrigger): void;
/** /**
* *
* @param others * @param others
*/ */
concat( concat(...others: ITriggerCollection[]): ITriggerCollection;
...others: ITriggerCollection<TEnemy, THero>[]
): ITriggerCollection<TEnemy, THero>;
} }
export interface ITriggerCollector<TEnemy, THero> { export interface ITriggerCollector {
/** /**
* *
* @param x * @param x
* @param y * @param y
* @param layer * @param layer
*/ */
collect( collect(x: number, y: number, layer: IMapLayer): ITriggerCollection;
x: number,
y: number,
layer: IMapLayer
): ITriggerCollection<TEnemy, THero>;
/** /**
* collector 使 * collector 使
* @param registry * @param registry
*/ */
attachRegistry(registry: ITriggerRegistry<TEnemy, THero> | null): void; attachRegistry(registry: ITriggerRegistry | null): void;
} }

View File

@ -1,17 +1,18 @@
import { IStateBase } from '@user/data-base'; import { IStateBase } from '@user/data-base';
import { IEnemyContext } from './combat'; import { IEnemyContext } from './combat';
import { ITriggerCollector, ITriggerRegistry } from './trigger'; import { ITriggerCollector, ITriggerRegistry } from './trigger';
import { IEnemyAttr, IHeroAttr } from '@user/data-common';
export interface IStateSystem<TEnemy, THero> extends IStateBase<TEnemy, THero> { export interface IStateSystem extends IStateBase {
/** 怪物上下文 */ /** 怪物上下文 */
readonly enemyContext: IEnemyContext<TEnemy, THero>; readonly enemyContext: IEnemyContext<IEnemyAttr, IHeroAttr>;
/** 触发器注册 */ /** 触发器注册 */
readonly triggerRegistry: ITriggerRegistry<TEnemy, THero>; readonly triggerRegistry: ITriggerRegistry;
/** 触发器收集器 */ /** 触发器收集器 */
readonly triggerCollector: ITriggerCollector<TEnemy, THero>; readonly triggerCollector: ITriggerCollector;
} }
export interface IStateSystemExtended<TEnemy = unknown, THero = unknown> { export interface IStateSystemExtended {
/** 当前对象对应的执行层对象Layer 2 对象) */ /** 当前对象对应的执行层对象Layer 2 对象) */
readonly state: IStateSystem<TEnemy, THero>; readonly state: IStateSystem;
} }

View File

@ -193,6 +193,7 @@
"133": "TileStore.addTile: tile number $1 already exists (id: '$2'), old tile data will be overridden.", "133": "TileStore.addTile: tile number $1 already exists (id: '$2'), old tile data will be overridden.",
"134": "TileStore.addTile: tile id '$1' already maps to number $2, old tile data will be overridden.", "134": "TileStore.addTile: tile id '$1' already maps to number $2, old tile data will be overridden.",
"135": "Expected a trigger registry attched before collect triggers.", "135": "Expected a trigger registry attched before collect triggers.",
"136": "Unexpected duplicate trigger priority $1, which may cause trigger executed in an unexpected order." "136": "Unexpected duplicate trigger priority $1, which may cause trigger executed in an unexpected order.",
"137": "Unknown guard enemy at locator '$1,$2'."
} }
} }