refactor: 将旧样板怪物移植单独提取出来

This commit is contained in:
unanmed 2026-04-15 23:12:28 +08:00
parent 6c1acb990e
commit 39e91b241f
6 changed files with 72 additions and 14 deletions

View File

@ -1,13 +1,18 @@
import { logger } from '@motajs/common'; import { logger } from '@motajs/common';
import { Enemy as EnemyImpl } from './enemy'; import { Enemy as EnemyImpl } from './enemy';
import { IEnemy, IEnemyManager, SpecialCreation } from './types'; import {
IEnemy,
IEnemyManager,
IEnemyLegacyBridge,
SpecialCreation
} from './types';
export class EnemyManager<TAttr> implements IEnemyManager<TAttr> { export class EnemyManager<TAttr> implements IEnemyManager<TAttr> {
/** 特殊属性注册表code -> 创建函数 */ /** 特殊属性注册表code -> 创建函数 */
private readonly specialRegistry: Map<number, SpecialCreation<any, TAttr>> = private readonly specialRegistry: Map<number, SpecialCreation<any, TAttr>> =
new Map(); new Map();
/** 自定义怪物属性注册表name -> 默认值 */ /** 自定义怪物属性注册表name -> 默认值 */
private readonly attributeRegistry: Map<string, any> = new Map(); private readonly attributeRegistry: Map<keyof TAttr, any> = new Map();
/** 怪物模板表code -> IEnemy */ /** 怪物模板表code -> IEnemy */
private readonly prefabByCode: Map<number, IEnemy<TAttr>> = new Map(); private readonly prefabByCode: Map<number, IEnemy<TAttr>> = new Map();
/** 怪物模板表id -> IEnemy */ /** 怪物模板表id -> IEnemy */
@ -15,11 +20,16 @@ export class EnemyManager<TAttr> implements IEnemyManager<TAttr> {
/** 旧样板怪物 id 到 code 的映射,用于 fromLegacyEnemy 快速查找已有模板 */ /** 旧样板怪物 id 到 code 的映射,用于 fromLegacyEnemy 快速查找已有模板 */
private readonly legacyIdToCode: Map<string, number> = new Map(); private readonly legacyIdToCode: Map<string, number> = new Map();
constructor(readonly bridge: IEnemyLegacyBridge<TAttr>) {}
registerSpecial(code: number, cons: SpecialCreation<any, TAttr>): void { registerSpecial(code: number, cons: SpecialCreation<any, TAttr>): void {
this.specialRegistry.set(code, cons); this.specialRegistry.set(code, cons);
} }
registerAttribute(name: string, defaultValue: any): void { setAttributeDefaults<K extends keyof TAttr>(
name: K,
defaultValue: TAttr[K]
): void {
if ( if (
typeof defaultValue === 'function' || typeof defaultValue === 'function' ||
typeof defaultValue === 'symbol' || typeof defaultValue === 'symbol' ||
@ -50,16 +60,13 @@ export class EnemyManager<TAttr> implements IEnemyManager<TAttr> {
* @param enemy * @param enemy
*/ */
private createAttributes(enemy: Enemy): TAttr { private createAttributes(enemy: Enemy): TAttr {
const attrs: Record<string, any> = {}; const attrs: Partial<TAttr> = {};
for (const [name, defaultValue] of this.attributeRegistry) { for (const [name, defaultValue] of this.attributeRegistry) {
attrs[name] = structuredClone(defaultValue); attrs[name] = structuredClone(defaultValue);
} }
attrs.hp = enemy.hp;
attrs.atk = enemy.atk; Object.assign(attrs, this.bridge.fromLegacyEnemy(enemy, attrs));
attrs.def = enemy.def;
attrs.money = enemy.money;
attrs.exp = enemy.exp;
attrs.point = enemy.point;
return attrs as TAttr; return attrs as TAttr;
} }

View File

@ -1,5 +1,7 @@
import { IRange, ITileLocator } from '@motajs/common'; import { IRange, ITileLocator } from '@motajs/common';
//#region 怪物基础
export interface ISpecial<T = void> { export interface ISpecial<T = void> {
/** 特殊属性代码 */ /** 特殊属性代码 */
readonly code: number; readonly code: number;
@ -121,8 +123,20 @@ export interface IEnemy<TAttr> extends IReadonlyEnemy<TAttr> {
copyFrom(enemy: IReadonlyEnemy<TAttr>): void; copyFrom(enemy: IReadonlyEnemy<TAttr>): void;
} }
//#endregion
//#region 怪物管理器
export type SpecialCreation<T, TAttr> = (enemy: IEnemy<TAttr>) => ISpecial<T>; export type SpecialCreation<T, TAttr> = (enemy: IEnemy<TAttr>) => ISpecial<T>;
export interface IEnemyLegacyBridge<TAttr> {
/**
*
* @param enemy
*/
fromLegacyEnemy(enemy: Enemy, defaultValue: Partial<TAttr>): TAttr;
}
export interface IEnemyManager<TAttr> { export interface IEnemyManager<TAttr> {
/** /**
* *
@ -136,7 +150,10 @@ export interface IEnemyManager<TAttr> {
* @param name * @param name
* @param defaultValue * @param defaultValue
*/ */
registerAttribute(name: string, defaultValue: any): void; setAttributeDefaults<K extends keyof TAttr>(
name: K,
defaultValue: TAttr[K]
): void;
/** /**
* *
@ -196,6 +213,8 @@ export interface IEnemyManager<TAttr> {
changePrefab(code: number | string, enemy: IEnemy<TAttr>): void; changePrefab(code: number | string, enemy: IEnemy<TAttr>): void;
} }
//#endregion
//#region 辅助接口 //#region 辅助接口
export interface IMapLocHelper { export interface IMapLocHelper {

View File

@ -13,6 +13,7 @@ import {
import { IEnemyAttributes } from './enemy/types'; import { IEnemyAttributes } from './enemy/types';
import { import {
CommonAuraConverter, CommonAuraConverter,
EnemyLegacyBridge,
GuardAuraConverter, GuardAuraConverter,
MainEnemyFinalEffect, MainEnemyFinalEffect,
MainMapDamageConverter, MainMapDamageConverter,
@ -38,9 +39,18 @@ export class CoreState implements ICoreState {
this.idNumberMap = new Map(); this.idNumberMap = new Map();
this.numberIdMap = new Map(); this.numberIdMap = new Map();
//#region 怪物初始化
// 怪物管理器初始化 // 怪物管理器初始化
this.enemyManager = new EnemyManager(); const enemyManager = new EnemyManager(new EnemyLegacyBridge());
registerSpecials(this.enemyManager); enemyManager.setAttributeDefaults('hp', 0);
enemyManager.setAttributeDefaults('atk', 0);
enemyManager.setAttributeDefaults('def', 0);
enemyManager.setAttributeDefaults('exp', 0);
enemyManager.setAttributeDefaults('money', 0);
enemyManager.setAttributeDefaults('point', 0);
registerSpecials(enemyManager);
this.enemyManager = enemyManager;
// 怪物上下文初始化 // 怪物上下文初始化
const enemyContext = new EnemyContext<IEnemyAttributes>(); const enemyContext = new EnemyContext<IEnemyAttributes>();
const damageSystem = new DamageSystem(enemyContext); const damageSystem = new DamageSystem(enemyContext);
@ -54,6 +64,8 @@ export class CoreState implements ICoreState {
enemyContext.registerFinalEffect(new MainEnemyFinalEffect()); enemyContext.registerFinalEffect(new MainEnemyFinalEffect());
enemyContext.resize(TILE_WIDTH, TILE_HEIGHT); enemyContext.resize(TILE_WIDTH, TILE_HEIGHT);
this.enemyContext = enemyContext; this.enemyContext = enemyContext;
//#endregion
} }
saveState(): IStateSaveData { saveState(): IStateSaveData {

View File

@ -1,5 +1,6 @@
export * from './aura'; export * from './aura';
export * from './damage'; export * from './damage';
export * from './final'; export * from './final';
export * from './legacy';
export * from './mapDamage'; export * from './mapDamage';
export * from './special'; export * from './special';

View File

@ -0,0 +1,19 @@
import { IEnemyLegacyBridge } from '@user/data-base';
import { IEnemyAttributes } from './types';
export class EnemyLegacyBridge implements IEnemyLegacyBridge<IEnemyAttributes> {
fromLegacyEnemy(
enemy: Enemy,
defaultAttr: Partial<IEnemyAttributes>
): IEnemyAttributes {
return {
hp: enemy.hp ?? defaultAttr.hp ?? 0,
atk: enemy.atk ?? defaultAttr.atk ?? 0,
def: enemy.def ?? defaultAttr.def ?? 0,
money: enemy.money ?? defaultAttr.money ?? 0,
exp: enemy.exp ?? defaultAttr.exp ?? 0,
point: enemy.point ?? defaultAttr.point ?? 0,
guard: defaultAttr.guard ?? new Set()
};
}
}

View File

@ -51,7 +51,7 @@ export interface IHaloValue {
export function registerSpecials( export function registerSpecials(
manager: IEnemyManager<IEnemyAttributes> manager: IEnemyManager<IEnemyAttributes>
): void { ): void {
manager.registerAttribute('guard', new Set()); manager.setAttributeDefaults('guard', new Set());
// 0 - 空 // 0 - 空
manager.registerSpecial( manager.registerSpecial(