mirror of
https://github.com/motajs/template.git
synced 2026-05-21 18:31:11 +08:00
Compare commits
1 Commits
5f989b949a
...
4b23f5d17b
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4b23f5d17b |
@ -1,44 +0,0 @@
|
||||
# 需求综述
|
||||
|
||||
触发器系统主体已经完成,下一步开始逐步补充内置触发器类型。当前第一批只先设计两个最基础的内置触发器:战斗触发器与开门触发器。
|
||||
|
||||
本文只确认这两个类型的职责、使用频率预期与当前待补充的设计边界,不展开实现思路,也不列涉及文件。后续如果继续新增对话、商店、自定义事件等内置触发器,再在此文档上继续补充即可。
|
||||
|
||||
---
|
||||
|
||||
# 共通约束
|
||||
|
||||
这两个内置触发器都只是 `ITrigger` 的内置实现。当前阶段不建议先给它们增加额外公共配置成员,怪物信息、门信息原则上应跟随当前触发位置上的图块或运行时载体,而不是在触发器实例里重复保存一份。
|
||||
|
||||
- `type`:预期频率**低频**。由注册表和类型定义决定,通常只在注册、调试或排查问题时关注。
|
||||
- `priority`:预期频率**低频**。大多数情况下使用固定默认值即可,只有极少数“同格混合触发”场景才需要显式调整。
|
||||
- `trigger(handler)`:预期频率**中频**。平时更多通过 `ITriggerCollection.trigger(...)` 间接触发,直接持有某个内置触发器并手动调用的场景相对有限。
|
||||
- `collection()`:预期频率**中频**。继承 `ITrigger` 的统一包装能力,使用方式与其他触发器一致,这里不做额外语义扩展。
|
||||
|
||||
---
|
||||
|
||||
# 类型设计与预期
|
||||
|
||||
## 战斗触发器(暂定 `IBattleTrigger`)
|
||||
|
||||
- 核心职责:在当前触发位置执行一次与怪物的战斗。
|
||||
- `IBattleTrigger.trigger(handler)`:预期频率**中频**。典型使用场景:玩家移动到怪物格后,移动系统收集到该触发器并交给集合统一触发;或脚本手动触发某个战斗事件。
|
||||
- 校验要求:触发前必须确认当前指定图块或对应的运行时载体确实是怪物。若不是怪物,发出警告并终止本次触发,不进入战斗流程。
|
||||
- 数据要求:需要能从当前触发位置解析出“这是怪物”这一事实,以及后续进入战斗流程所需的怪物信息。
|
||||
- 职责边界:该触发器当前只先负责“确认目标是怪物并进入战斗分支”。战斗后怪物移除、地图更新、事件派发等后续职责,先不在本文中拍死。
|
||||
|
||||
## 开门触发器(暂定 `IOpenDoorTrigger`)
|
||||
|
||||
- 核心职责:在当前触发位置执行一次开门行为。
|
||||
- `IOpenDoorTrigger.trigger(handler)`:预期频率**中频**。典型使用场景:玩家撞到门格或主动交互门格后,系统收集到该触发器并尝试开门;或脚本在演出中手动触发某扇门的开启。
|
||||
- 校验要求:触发前必须确认当前指定图块或对应的运行时载体包含门相关信息。若不包含,发出警告并终止本次触发,不执行开门行为。
|
||||
- 数据要求:需要能从当前触发位置读取门相关信息,并定位到既有的 `openDoor` 流程。
|
||||
- 职责边界:该触发器当前只先负责“确认目标是门并进入开门分支”。钥匙校验、动画等待、图块替换、开门后事件等具体流程,先依附既有开门系统,不在本文中提前拆开。
|
||||
|
||||
---
|
||||
|
||||
# 当前待补充设计
|
||||
|
||||
1. 运行时需要一条统一路径,让触发器能从 `handler` 提供的上下文中读取当前位置对应的怪物信息或门信息;这一层目前还没有最终定稿。
|
||||
2. 这两个内置触发器原则上都不应在实例上重复保存业务对象;更合理的方向是由当前位置的图块或运行时载体提供数据。若后续发现这条路线不够用,再单独讨论是否为内置触发器补配置成员。
|
||||
3. 这两个触发器当前都只先定义“校验 + 进入对应系统”的第一层职责。后续如果需要细分成更多内置类型,例如强制战斗、免钥匙开门、条件开门等,再在这个基础上继续扩展。
|
||||
@ -12,18 +12,16 @@ import {
|
||||
} from './types';
|
||||
import { SaveCompression } from '@user/data-common';
|
||||
|
||||
export class EnemyManager<TEnemy> implements IEnemyManager<TEnemy> {
|
||||
export class EnemyManager<TAttr> implements IEnemyManager<TAttr> {
|
||||
/** 特殊属性注册表,code -> 创建函数 */
|
||||
private readonly specialRegistry: Map<
|
||||
number,
|
||||
SpecialCreation<any, TEnemy>
|
||||
> = new Map();
|
||||
private readonly specialRegistry: Map<number, SpecialCreation<any, TAttr>> =
|
||||
new Map();
|
||||
/** 自定义怪物属性注册表,name -> 默认值 */
|
||||
private readonly attributeRegistry: Map<keyof TEnemy, any> = new Map();
|
||||
private readonly attributeRegistry: Map<keyof TAttr, any> = new Map();
|
||||
/** 怪物模板表,code -> IEnemy */
|
||||
private readonly prefabByCode: Map<number, IEnemy<TEnemy>> = new Map();
|
||||
private readonly prefabByCode: Map<number, IEnemy<TAttr>> = new Map();
|
||||
/** 怪物模板表,id -> IEnemy */
|
||||
private readonly prefabById: Map<string, IEnemy<TEnemy>> = new Map();
|
||||
private readonly prefabById: Map<string, IEnemy<TAttr>> = new Map();
|
||||
/** 旧样板怪物 id 到 code 的映射,用于 fromLegacyEnemy 快速查找已有模板 */
|
||||
private readonly legacyIdToCode: Map<string, number> = new Map();
|
||||
/** 复用映射,reusedCode -> sourceCode */
|
||||
@ -33,21 +31,21 @@ export class EnemyManager<TEnemy> implements IEnemyManager<TEnemy> {
|
||||
/** 脏模板集合,存储发生了变化的模板 code */
|
||||
private readonly dirtySet: Set<number> = new Set();
|
||||
/** 参考快照,code -> IReadonlyEnemy,由 compareWith 提供 */
|
||||
private referenceByCode: Map<number, IReadonlyEnemy<TEnemy>> = new Map();
|
||||
private referenceByCode: Map<number, IReadonlyEnemy<TAttr>> = new Map();
|
||||
/** 当前附加的怪物比较器 */
|
||||
private comparer: IEnemyComparer<TEnemy> | null = null;
|
||||
private comparer: IEnemyComparer<TAttr> | null = null;
|
||||
/** 是否已首次调用 compareWith */
|
||||
private hasReference: boolean = false;
|
||||
|
||||
constructor(readonly bridge: IEnemyLegacyBridge<TEnemy>) {}
|
||||
constructor(readonly bridge: IEnemyLegacyBridge<TAttr>) {}
|
||||
|
||||
registerSpecial(code: number, cons: SpecialCreation<any, TEnemy>): void {
|
||||
registerSpecial(code: number, cons: SpecialCreation<any, TAttr>): void {
|
||||
this.specialRegistry.set(code, cons);
|
||||
}
|
||||
|
||||
setAttributeDefaults<K extends keyof TEnemy>(
|
||||
setAttributeDefaults<K extends keyof TAttr>(
|
||||
name: K,
|
||||
defaultValue: TEnemy[K]
|
||||
defaultValue: TAttr[K]
|
||||
): void {
|
||||
if (
|
||||
typeof defaultValue === 'function' ||
|
||||
@ -61,7 +59,7 @@ export class EnemyManager<TEnemy> implements IEnemyManager<TEnemy> {
|
||||
this.attributeRegistry.set(name, defaultValue);
|
||||
}
|
||||
|
||||
fromLegacyEnemy(code: number, enemy: Enemy): IEnemy<TEnemy> {
|
||||
fromLegacyEnemy(code: number, enemy: Enemy): IEnemy<TAttr> {
|
||||
// 如果该旧样板怪物已经通过 addPrefabFromLegacy 注册为模板,直接克隆模板
|
||||
const existingCode = this.legacyIdToCode.get(enemy.id);
|
||||
if (existingCode) {
|
||||
@ -78,15 +76,15 @@ export class EnemyManager<TEnemy> implements IEnemyManager<TEnemy> {
|
||||
* 根据旧样板怪物与注册过的默认属性构造属性对象
|
||||
* @param enemy 旧样板怪物对象
|
||||
*/
|
||||
private createAttributes(enemy: Enemy): TEnemy {
|
||||
const attrs: Partial<TEnemy> = {};
|
||||
private createAttributes(enemy: Enemy): TAttr {
|
||||
const attrs: Partial<TAttr> = {};
|
||||
for (const [name, defaultValue] of this.attributeRegistry) {
|
||||
attrs[name] = structuredClone(defaultValue);
|
||||
}
|
||||
|
||||
Object.assign(attrs, this.bridge.fromLegacyEnemy(enemy, attrs));
|
||||
|
||||
return attrs as TEnemy;
|
||||
return attrs as TAttr;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -94,9 +92,9 @@ export class EnemyManager<TEnemy> implements IEnemyManager<TEnemy> {
|
||||
* @param code 怪物图块数字
|
||||
* @param enemy 旧样板怪物对象
|
||||
*/
|
||||
private convertLegacyEnemy(code: number, enemy: Enemy): IEnemy<TEnemy> {
|
||||
private convertLegacyEnemy(code: number, enemy: Enemy): IEnemy<TAttr> {
|
||||
const attrs = this.createAttributes(enemy);
|
||||
const result = new EnemyImpl<TEnemy>(
|
||||
const result = new EnemyImpl<TAttr>(
|
||||
enemy.id,
|
||||
code,
|
||||
structuredClone(attrs)
|
||||
@ -116,13 +114,13 @@ export class EnemyManager<TEnemy> implements IEnemyManager<TEnemy> {
|
||||
return result;
|
||||
}
|
||||
|
||||
createEnemy(code: number): IEnemy<TEnemy> | null {
|
||||
createEnemy(code: number): IEnemy<TAttr> | null {
|
||||
const prefab = this.prefabByCode.get(code);
|
||||
if (!prefab) return null;
|
||||
return prefab.clone();
|
||||
}
|
||||
|
||||
createEnemyById(id: string): IEnemy<TEnemy> | null {
|
||||
createEnemyById(id: string): IEnemy<TAttr> | null {
|
||||
const prefab = this.prefabById.get(id);
|
||||
if (!prefab) return null;
|
||||
return prefab.clone();
|
||||
@ -138,7 +136,7 @@ export class EnemyManager<TEnemy> implements IEnemyManager<TEnemy> {
|
||||
}
|
||||
}
|
||||
|
||||
addPrefab(enemy: IEnemy<TEnemy>): void {
|
||||
addPrefab(enemy: IEnemy<TAttr>): void {
|
||||
if (
|
||||
this.prefabByCode.has(enemy.code) ||
|
||||
this.prefabById.has(enemy.id)
|
||||
@ -162,12 +160,12 @@ export class EnemyManager<TEnemy> implements IEnemyManager<TEnemy> {
|
||||
this.updateDirty(code, prefab);
|
||||
}
|
||||
|
||||
getPrefab(code: number): IReadonlyEnemy<TEnemy> | null {
|
||||
getPrefab(code: number): IReadonlyEnemy<TAttr> | null {
|
||||
const sourceCode = this.reuseByCode.get(code) ?? code;
|
||||
return this.prefabByCode.get(sourceCode) ?? null;
|
||||
}
|
||||
|
||||
getPrefabById(id: string): IReadonlyEnemy<TEnemy> | null {
|
||||
getPrefabById(id: string): IReadonlyEnemy<TAttr> | null {
|
||||
const sourceId = this.reuseById.get(id) ?? id;
|
||||
return this.prefabById.get(sourceId) ?? null;
|
||||
}
|
||||
@ -179,7 +177,7 @@ export class EnemyManager<TEnemy> implements IEnemyManager<TEnemy> {
|
||||
this.prefabById.delete(prefab.id);
|
||||
}
|
||||
|
||||
changePrefab(code: number | string, enemy: IEnemy<TEnemy>): void {
|
||||
changePrefab(code: number | string, enemy: IEnemy<TAttr>): void {
|
||||
// 先删除旧的模板(如果存在)
|
||||
this.deletePrefab(code);
|
||||
// 再添加新的模板
|
||||
@ -195,7 +193,7 @@ export class EnemyManager<TEnemy> implements IEnemyManager<TEnemy> {
|
||||
this.reuseById.set(id, prefab.id);
|
||||
}
|
||||
|
||||
compareWith(reference: ReadonlyMap<number, IReadonlyEnemy<TEnemy>>): void {
|
||||
compareWith(reference: ReadonlyMap<number, IReadonlyEnemy<TAttr>>): void {
|
||||
const isSubsequentCall = this.hasReference;
|
||||
if (isSubsequentCall) {
|
||||
logger.warn(117);
|
||||
@ -213,7 +211,7 @@ export class EnemyManager<TEnemy> implements IEnemyManager<TEnemy> {
|
||||
|
||||
modifyPrefabAttribute(
|
||||
code: number | string,
|
||||
modify: (prefab: IEnemy<TEnemy>) => IEnemy<TEnemy>
|
||||
modify: (prefab: IEnemy<TAttr>) => IEnemy<TAttr>
|
||||
): void {
|
||||
const prefab = this.internalGetPrefab(code);
|
||||
if (!prefab) return;
|
||||
@ -232,16 +230,16 @@ export class EnemyManager<TEnemy> implements IEnemyManager<TEnemy> {
|
||||
this.updateDirty(result.code, result);
|
||||
}
|
||||
|
||||
attachEnemyComparer(comparer: IEnemyComparer<TEnemy>): void {
|
||||
attachEnemyComparer(comparer: IEnemyComparer<TAttr>): void {
|
||||
this.comparer = comparer;
|
||||
}
|
||||
|
||||
getEnemyComparer(): IEnemyComparer<TEnemy> | null {
|
||||
getEnemyComparer(): IEnemyComparer<TAttr> | null {
|
||||
return this.comparer;
|
||||
}
|
||||
|
||||
saveState(compression: SaveCompression): IEnemyManagerSaveState<TEnemy> {
|
||||
const modified: Map<number, IEnemySaveState<TEnemy>> = new Map();
|
||||
saveState(compression: SaveCompression): IEnemyManagerSaveState<TAttr> {
|
||||
const modified: Map<number, IEnemySaveState<TAttr>> = new Map();
|
||||
for (const code of this.dirtySet) {
|
||||
const prefab = this.prefabByCode.get(code);
|
||||
if (!prefab) continue;
|
||||
@ -251,7 +249,7 @@ export class EnemyManager<TEnemy> implements IEnemyManager<TEnemy> {
|
||||
}
|
||||
|
||||
loadState(
|
||||
state: IEnemyManagerSaveState<TEnemy>,
|
||||
state: IEnemyManagerSaveState<TAttr>,
|
||||
compression: SaveCompression
|
||||
): void {
|
||||
for (const [code, enemyState] of state.modified) {
|
||||
@ -271,7 +269,7 @@ export class EnemyManager<TEnemy> implements IEnemyManager<TEnemy> {
|
||||
* @param code 怪物图块数字
|
||||
* @param current 当前模板对象
|
||||
*/
|
||||
private updateDirty(code: number, current: IEnemy<TEnemy>): void {
|
||||
private updateDirty(code: number, current: IEnemy<TAttr>): void {
|
||||
if (!this.hasReference) return;
|
||||
if (!this.comparer) {
|
||||
logger.warn(118);
|
||||
|
||||
@ -2,26 +2,21 @@ import { IHeroFollower, IHeroState } from './hero';
|
||||
import { IEnemyManager } from './enemy';
|
||||
import { IFlagSystem } from './flag';
|
||||
import { IMapStore } from './map';
|
||||
import {
|
||||
IDataCommon,
|
||||
IEnemyAttr,
|
||||
IHeroAttr,
|
||||
ISaveableContent
|
||||
} from '@user/data-common';
|
||||
import { IDataCommon, ISaveableContent } from '@user/data-common';
|
||||
|
||||
export interface IStateSaveData {
|
||||
/** 跟随者列表 */
|
||||
readonly followers: readonly IHeroFollower[];
|
||||
}
|
||||
|
||||
export interface IStateBase extends IDataCommon {
|
||||
export interface IStateBase<TEnemy, THero> extends IDataCommon {
|
||||
/** 地图状态 */
|
||||
readonly maps: IMapStore;
|
||||
/** 勇士状态 */
|
||||
readonly hero: IHeroState<IHeroAttr>;
|
||||
readonly hero: IHeroState<THero>;
|
||||
|
||||
/** 怪物管理器 */
|
||||
readonly enemyManager: IEnemyManager<IEnemyAttr>;
|
||||
readonly enemyManager: IEnemyManager<TEnemy>;
|
||||
|
||||
/** Flag 系统 */
|
||||
readonly flags: IFlagSystem;
|
||||
@ -40,7 +35,7 @@ export interface IStateBase extends IDataCommon {
|
||||
getSaveableContent<T>(id: string): ISaveableContent<T> | null;
|
||||
}
|
||||
|
||||
export interface IStateBaseExtended {
|
||||
export interface IStateBaseExtended<TEnemy = unknown, THero = unknown> {
|
||||
/** 当前对象对应的数据层对象(Layer 1 对象) */
|
||||
readonly state: IStateBase;
|
||||
readonly state: IStateBase<TEnemy, THero>;
|
||||
}
|
||||
|
||||
@ -1,47 +1,6 @@
|
||||
import { ITileLocator } from '@motajs/common';
|
||||
import { IFaceManager, IRoleFaceBinder } from './common';
|
||||
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 {
|
||||
/** 图块定义存储 */
|
||||
readonly tileStore: ITileStore<MapDataOf<keyof NumberToId>>;
|
||||
|
||||
@ -11,9 +11,7 @@ import {
|
||||
Dir4FaceHandler,
|
||||
Dir8FaceHandler,
|
||||
FaceGroup,
|
||||
FaceDirection,
|
||||
IHeroAttr,
|
||||
IEnemyAttr
|
||||
FaceDirection
|
||||
} from '@user/data-common';
|
||||
import {
|
||||
EnemyManager,
|
||||
@ -50,7 +48,8 @@ import {
|
||||
MainMapDamageConverter,
|
||||
MainMapDamageReducer,
|
||||
registerSpecials,
|
||||
MainEnemyComparer
|
||||
MainEnemyComparer,
|
||||
IEnemyAttr
|
||||
} from './enemy';
|
||||
import {
|
||||
BG2_ZINDEX,
|
||||
@ -62,6 +61,7 @@ import {
|
||||
TILE_HEIGHT,
|
||||
TILE_WIDTH
|
||||
} from './shared';
|
||||
import { IHeroAttr } from './hero';
|
||||
import { LegacyTileData, TileLegacyBridge } from './legacy';
|
||||
import { ILoadProgressTotal, LoadProgressTotal } from '@motajs/loader';
|
||||
import { isNil } from 'lodash-es';
|
||||
@ -69,23 +69,23 @@ import { logger } from '@motajs/common';
|
||||
import { ISaveSystem, SaveSystem } from './save';
|
||||
|
||||
export class CoreState implements ICoreState {
|
||||
// Layer 0 公共层
|
||||
// Layer 0 内容
|
||||
readonly roleFace: IRoleFaceBinder;
|
||||
readonly faceManager: IFaceManager;
|
||||
readonly tileStore: ITileStore<LegacyTileData>;
|
||||
|
||||
// Layer 1 数据层,所有可存档内容都在这
|
||||
// Layer 1 内容
|
||||
readonly maps: IMapStore;
|
||||
readonly hero: IHeroState<IHeroAttr>;
|
||||
readonly enemyManager: IEnemyManager<IEnemyAttr>;
|
||||
readonly flags: IFlagSystem;
|
||||
|
||||
// Layer 2 执行层,游戏逻辑对象都在这
|
||||
// Layer 2 内容
|
||||
readonly enemyContext: IEnemyContext<IEnemyAttr, IHeroAttr>;
|
||||
readonly triggerRegistry: ITriggerRegistry;
|
||||
readonly triggerCollector: ITriggerCollector;
|
||||
|
||||
// 用户层内容,也就是最顶层的内容,一般仅用于初始化
|
||||
// 用户层内容
|
||||
readonly loadProgress: ILoadProgressTotal;
|
||||
readonly dataLoader: IMotaDataLoader;
|
||||
readonly saveSystem: ISaveSystem;
|
||||
@ -171,7 +171,7 @@ export class CoreState implements ICoreState {
|
||||
this.enemyContext = enemyContext;
|
||||
|
||||
// 触发器注册与收集器
|
||||
const triggerRegistry = new TriggerRegistry(this);
|
||||
const triggerRegistry = new TriggerRegistry();
|
||||
const triggerCollector = new TriggerCollector();
|
||||
triggerCollector.attachRegistry(triggerRegistry);
|
||||
this.triggerRegistry = triggerRegistry;
|
||||
@ -247,6 +247,7 @@ export class CoreState implements ICoreState {
|
||||
* @param data 旧样板怪物存储对象
|
||||
*/
|
||||
private initEnemyManager(data: Record<EnemyIds, Enemy>) {
|
||||
// TODO: 修改怪物模板并存入存档,即 core.setEnemy
|
||||
const manager = this.enemyManager;
|
||||
const reference = new Map<number, IReadonlyEnemy<IEnemyAttr>>();
|
||||
for (const [id, enemy] of Object.entries(structuredClone(data))) {
|
||||
|
||||
@ -18,7 +18,8 @@ import {
|
||||
} from '@user/data-system';
|
||||
import { IReadonlyEnemy, ISpecial } from '@user/data-base';
|
||||
import { IHaloValue } from './special';
|
||||
import { IHeroAttr, IEnemyAttr } from '@user/data-common';
|
||||
import { IEnemyAttr } from './types';
|
||||
import { IHeroAttr } from '../hero';
|
||||
|
||||
const FULL_RANGE = new FullRange();
|
||||
const RECT_RANGE = new RectRange();
|
||||
@ -175,7 +176,7 @@ export class GuardAura implements IEnemyAuraView<
|
||||
if (locator.x === this.locator.x && locator.y === this.locator.y) {
|
||||
return;
|
||||
}
|
||||
enemy.getAttribute('guard').add(this.locator);
|
||||
enemy.getAttribute('guard').add(this.sourceView);
|
||||
}
|
||||
|
||||
applySpecial(): IEnemySpecialModifier<IEnemyAttr> | null {
|
||||
|
||||
@ -4,10 +4,10 @@ import {
|
||||
IEnemyDamageInfo,
|
||||
IReadonlyEnemyHandler
|
||||
} from '@user/data-system';
|
||||
import { IEnemyAttr, IHeroAttr } from '@user/data-common';
|
||||
import { IEnemyAttr } from './types';
|
||||
import { IVampireValue } from './special';
|
||||
import { IHeroAttr } from '../hero';
|
||||
import { state } from '../ins';
|
||||
import { logger } from '@motajs/common';
|
||||
|
||||
export class MainDamageCalculator implements IDamageCalculator<
|
||||
IEnemyAttr,
|
||||
@ -87,14 +87,8 @@ export class MainDamageCalculator implements IDamageCalculator<
|
||||
// 因此回合数需要加上打支援怪的回合数
|
||||
for (const guard of guards) {
|
||||
// 直接把 enemy 传过去,因此支援的 enemy 会吃到其原本所在位置的光环加成
|
||||
const view = handler.context.getEnemyByLocator(guard);
|
||||
if (!view) {
|
||||
logger.warn(137, guard.x.toString(), guard.y.toString());
|
||||
continue;
|
||||
}
|
||||
const extraInfo = this.calculate({
|
||||
enemy: view.getComputedEnemy(),
|
||||
context: handler.context,
|
||||
enemy: guard.getComputedEnemy(),
|
||||
locator,
|
||||
hero,
|
||||
data: handler.data
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { IEnemyComparer, IReadonlyEnemy } from '@user/data-base';
|
||||
import { IEnemyAttr } from '@user/data-common';
|
||||
import { IEnemyAttr } from './types';
|
||||
|
||||
export class MainEnemyComparer implements IEnemyComparer<IEnemyAttr> {
|
||||
compare(
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { IEnemyFinalEffect, IEnemyHandler } from '@user/data-system';
|
||||
import { IEnemyAttr, IHeroAttr } from '@user/data-common';
|
||||
import { IEnemyAttr } from './types';
|
||||
import { IHeroAttr } from '../hero';
|
||||
|
||||
export class MainEnemyFinalEffect implements IEnemyFinalEffect<
|
||||
IEnemyAttr,
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { IEnemyLegacyBridge } from '@user/data-base';
|
||||
import { IEnemyAttr } from '@user/data-common';
|
||||
import { IEnemyAttr } from './types';
|
||||
|
||||
export class EnemyLegacyBridge implements IEnemyLegacyBridge<IEnemyAttr> {
|
||||
fromLegacyEnemy(
|
||||
|
||||
@ -24,8 +24,8 @@ import {
|
||||
IReadonlyEnemy
|
||||
} from '@user/data-base';
|
||||
import { IZoneValue } from './special';
|
||||
import { MapDamageType } from './types';
|
||||
import { IHeroAttr, IEnemyAttr } from '@user/data-common';
|
||||
import { IEnemyAttr, MapDamageType } from './types';
|
||||
import { IHeroAttr } from '../hero';
|
||||
import { IFaceHandler, FaceGroup } from '@user/data-common';
|
||||
|
||||
const RECT_RANGE = new RectRange();
|
||||
|
||||
@ -4,7 +4,7 @@ import {
|
||||
IEnemyManager
|
||||
} from '@user/data-base';
|
||||
import { getHeroStatusOn } from '../legacy/hero';
|
||||
import { IEnemyAttr } from '@user/data-common';
|
||||
import { IEnemyAttr } from './types';
|
||||
|
||||
//#region 复合属性值类型
|
||||
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
import { IEnemyView } from '@user/data-system';
|
||||
|
||||
export interface IEnemyAttr {
|
||||
/** 怪物生命值 */
|
||||
hp: number;
|
||||
@ -11,8 +13,8 @@ export interface IEnemyAttr {
|
||||
exp: number;
|
||||
/** 怪物加点量 */
|
||||
point: number;
|
||||
/** 支援来源怪物坐标索引列表 */
|
||||
guard: Set<number>;
|
||||
/** 支援来源怪物视图列表 */
|
||||
guard: Set<IEnemyView<IEnemyAttr>>;
|
||||
}
|
||||
|
||||
export const enum MapDamageType {
|
||||
|
||||
@ -1,5 +1,26 @@
|
||||
//#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
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { IHeroAttr } from '@user/data-common';
|
||||
import { IHeroAttr } from './hero';
|
||||
|
||||
//#region 地图相关
|
||||
|
||||
|
||||
@ -1,19 +1,21 @@
|
||||
import { IMotaDataLoader, IStateBase } from '@user/data-base';
|
||||
import { IEnemyAttr } from './enemy';
|
||||
import { IHeroAttr } from './hero';
|
||||
import { ILoadProgressTotal } from '@motajs/loader';
|
||||
import { ISaveSystem } from './save';
|
||||
import { IStateSystem } from '@user/data-system';
|
||||
import { ISaveableContent } from '@user/data-common';
|
||||
|
||||
export interface ISaveableExecutor<T> {
|
||||
export interface ISaveableExecutor<T, TEnemy = IEnemyAttr, THero = IHeroAttr> {
|
||||
/**
|
||||
* 当数据读取后执行的函数,允许对其他存档对象进行读取
|
||||
* @param data 对应可存档对象的存档数据
|
||||
* @param state 当前的基础状态
|
||||
*/
|
||||
afterLoad(data: T, state: IStateBase): void;
|
||||
afterLoad(data: T, state: IStateBase<TEnemy, THero>): void;
|
||||
}
|
||||
|
||||
export interface ICoreState extends IStateSystem {
|
||||
export interface ICoreState extends IStateSystem<IEnemyAttr, IHeroAttr> {
|
||||
/** 加载进度对象 */
|
||||
readonly loadProgress: ILoadProgressTotal;
|
||||
/** 数据端加载对象 */
|
||||
|
||||
@ -100,7 +100,7 @@ export class EnemyContext<TEnemy, THero> implements IEnemyContext<
|
||||
width: number = 0;
|
||||
height: number = 0;
|
||||
|
||||
constructor(readonly dataState: IStateBase) {}
|
||||
constructor(readonly dataState: IStateBase<TEnemy, THero>) {}
|
||||
|
||||
resize(width: number, height: number): void {
|
||||
this.clear();
|
||||
@ -210,13 +210,7 @@ export class EnemyContext<TEnemy, THero> implements IEnemyContext<
|
||||
enemy: IEnemy<TEnemy>,
|
||||
locator: ITileLocator
|
||||
): IEnemyHandler<TEnemy, THero> {
|
||||
return {
|
||||
enemy,
|
||||
context: this,
|
||||
locator,
|
||||
hero: this.bindedHero!,
|
||||
data: this.dataState
|
||||
};
|
||||
return { enemy, locator, hero: this.bindedHero!, data: this.dataState };
|
||||
}
|
||||
|
||||
getEnemyLocator(enemy: IEnemy<TEnemy>): Readonly<ITileLocator> | null {
|
||||
|
||||
@ -34,7 +34,7 @@ export class DamageContext<TEnemy, THero> implements IDamageContext<
|
||||
/** 当前勇士属性 */
|
||||
protected heroStatus: IReadonlyHeroAttribute<THero> | null;
|
||||
|
||||
readonly dataState: IStateBase;
|
||||
readonly dataState: IStateBase<TEnemy, THero>;
|
||||
|
||||
constructor(
|
||||
readonly context: IEnemyContext<TEnemy, THero>,
|
||||
@ -57,13 +57,7 @@ export class DamageContext<TEnemy, THero> implements IDamageContext<
|
||||
locator: ITileLocator,
|
||||
hero: IReadonlyHeroAttribute<THero>
|
||||
): IReadonlyEnemyHandler<TEnemy, THero> {
|
||||
return {
|
||||
enemy,
|
||||
context: this.context,
|
||||
locator,
|
||||
hero,
|
||||
data: this.dataState
|
||||
};
|
||||
return { enemy, locator, hero, data: this.dataState };
|
||||
}
|
||||
|
||||
getDamageInfo(enemy: IEnemyView<TEnemy>): IEnemyDamageInfo | null {
|
||||
|
||||
@ -64,7 +64,7 @@ export class MapDamage<TEnemy, THero> implements IMapDamage<TEnemy, THero> {
|
||||
/** 坐标索引对象 */
|
||||
private readonly indexer: ILocationHelper;
|
||||
|
||||
readonly dataState: IStateBase;
|
||||
readonly dataState: IStateBase<TEnemy, THero>;
|
||||
|
||||
constructor(readonly context: IEnemyContext<TEnemy, THero>) {
|
||||
this.indexer = context.indexer;
|
||||
@ -89,7 +89,6 @@ export class MapDamage<TEnemy, THero> implements IMapDamage<TEnemy, THero> {
|
||||
if (!hero) return null;
|
||||
return {
|
||||
enemy: view.getComputedEnemy(),
|
||||
context: this.context,
|
||||
locator,
|
||||
hero,
|
||||
data: this.context.dataState
|
||||
|
||||
@ -14,27 +14,23 @@ import { ILocationHelper } from '@user/data-common';
|
||||
export interface IEnemyHandler<TEnemy, THero> {
|
||||
/** 怪物属性信息 */
|
||||
readonly enemy: IEnemy<TEnemy>;
|
||||
/** 怪物上下文 */
|
||||
readonly context: IEnemyContext<TEnemy, THero>;
|
||||
/** 怪物定位符 */
|
||||
readonly locator: ITileLocator;
|
||||
/** 勇士属性信息 */
|
||||
readonly hero: IReadonlyHeroAttribute<THero>;
|
||||
/** 当前全局状态对象 */
|
||||
readonly data: IStateBase;
|
||||
readonly data: IStateBase<TEnemy, THero>;
|
||||
}
|
||||
|
||||
export interface IReadonlyEnemyHandler<TEnemy, THero> {
|
||||
/** 怪物属性信息 */
|
||||
readonly enemy: IReadonlyEnemy<TEnemy>;
|
||||
/** 怪物上下文 */
|
||||
readonly context: IReadonlyEnemyContext<TEnemy, THero>;
|
||||
/** 怪物定位符 */
|
||||
readonly locator: ITileLocator;
|
||||
/** 勇士属性信息 */
|
||||
readonly hero: IReadonlyHeroAttribute<THero>;
|
||||
/** 当前全局状态对象 */
|
||||
readonly data: IStateBase;
|
||||
readonly data: IStateBase<TEnemy, THero>;
|
||||
}
|
||||
|
||||
//#endregion
|
||||
@ -286,7 +282,7 @@ export interface IMapDamage<TEnemy, THero> {
|
||||
/** 当前绑定的怪物上下文 */
|
||||
readonly context: IEnemyContext<TEnemy, THero>;
|
||||
/** 地图伤害系统绑定的全局状态对象 */
|
||||
readonly dataState: IStateBase;
|
||||
readonly dataState: IStateBase<TEnemy, THero>;
|
||||
|
||||
/**
|
||||
* 设置地图伤害转换器,并基于当前上下文重建所有地图伤害视图
|
||||
@ -402,7 +398,7 @@ export interface IDamageCalculator<TEnemy, THero> {
|
||||
|
||||
export interface IDamageContext<TEnemy, THero> {
|
||||
/** 伤害上下文所属的全局状态对象 */
|
||||
readonly dataState: IStateBase;
|
||||
readonly dataState: IStateBase<TEnemy, THero>;
|
||||
|
||||
/**
|
||||
* 获取战斗伤害信息
|
||||
@ -483,7 +479,7 @@ export interface IDamageSystem<TEnemy, THero> extends IDamageContext<
|
||||
|
||||
//#region 上下文
|
||||
|
||||
export interface IReadonlyEnemyContext<TEnemy, THero> {
|
||||
export interface IEnemyContext<TEnemy, THero> {
|
||||
/** 怪物上下文宽度 */
|
||||
readonly width: number;
|
||||
/** 怪物上下文高度 */
|
||||
@ -491,84 +487,7 @@ export interface IReadonlyEnemyContext<TEnemy, THero> {
|
||||
/** 此上下文使用的索引对象 */
|
||||
readonly indexer: ILocationHelper;
|
||||
/** 当前怪物上下文绑定的全局状态对象 */
|
||||
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;
|
||||
readonly dataState: IStateBase<TEnemy, THero>;
|
||||
|
||||
/**
|
||||
* 调整上下文尺寸,并清空当前上下文中的所有怪物与状态
|
||||
@ -653,6 +572,44 @@ export interface IEnemyContext<TEnemy, THero> extends IReadonlyEnemyContext<
|
||||
*/
|
||||
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 地图定位符
|
||||
@ -666,6 +623,21 @@ export interface IEnemyContext<TEnemy, THero> extends IReadonlyEnemyContext<
|
||||
*/
|
||||
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 光环视图
|
||||
@ -684,12 +656,22 @@ export interface IEnemyContext<TEnemy, THero> extends IReadonlyEnemyContext<
|
||||
*/
|
||||
attachMapDamage(damage: IMapDamage<TEnemy, THero> | null): void;
|
||||
|
||||
/**
|
||||
* 获取当前绑定的地图伤害管理器
|
||||
*/
|
||||
getMapDamage(): IMapDamage<TEnemy, THero> | null;
|
||||
|
||||
/**
|
||||
* 绑定伤害计算系统
|
||||
* @param system 伤害系统
|
||||
*/
|
||||
attachDamageSystem(system: IDamageSystem<TEnemy, unknown> | null): void;
|
||||
|
||||
/**
|
||||
* 获取当前绑定的伤害计算系统
|
||||
*/
|
||||
getDamageSystem(): IDamageSystem<TEnemy, THero> | null;
|
||||
|
||||
/**
|
||||
* 重建当前上下文中的全部怪物计算结果
|
||||
*
|
||||
|
||||
@ -12,15 +12,17 @@ export class TriggerCollection implements ITriggerCollection {
|
||||
return this.triggerList.length;
|
||||
}
|
||||
|
||||
async trigger(handler: ITriggerHandler): Promise<void> {
|
||||
async trigger<TEnemy = unknown, THero = unknown>(
|
||||
handler: ITriggerHandler<TEnemy, THero>
|
||||
): Promise<void> {
|
||||
for (const trigger of this.triggerList) {
|
||||
await trigger.trigger(handler);
|
||||
}
|
||||
}
|
||||
|
||||
async *triggerIter(
|
||||
handler: ITriggerHandler
|
||||
): AsyncGenerator<ITrigger, void, ITriggerHandler | null> {
|
||||
async *triggerIter<TEnemy = unknown, THero = unknown>(
|
||||
handler: ITriggerHandler<TEnemy, THero>
|
||||
): AsyncGenerator<ITrigger, void, ITriggerHandler<TEnemy, THero> | null> {
|
||||
let currentHandler = handler;
|
||||
for (const trigger of this.triggerList) {
|
||||
await trigger.trigger(currentHandler);
|
||||
|
||||
@ -1,12 +1,17 @@
|
||||
import { logger } from '@motajs/common';
|
||||
import { ITrigger, ITriggerRegistry, TriggerFactory } from './types';
|
||||
import { IStateBase } from '@user/data-base';
|
||||
import {
|
||||
ITrigger,
|
||||
ITriggerRegistry,
|
||||
TriggerFactory,
|
||||
TriggerStringFactory
|
||||
} from './types';
|
||||
|
||||
export class TriggerRegistry implements ITriggerRegistry {
|
||||
/** 数字类型到触发器工厂的映射 */
|
||||
private readonly typeMap: Map<number, TriggerFactory> = new Map();
|
||||
|
||||
constructor(public readonly state: IStateBase) {}
|
||||
/** 字符串 id 到触发器工厂的映射 */
|
||||
private readonly stringMap: Map<string, TriggerStringFactory> = new Map();
|
||||
|
||||
register(type: number, factory: TriggerFactory): void {
|
||||
if (this.typeMap.has(type)) {
|
||||
@ -22,6 +27,23 @@ export class TriggerRegistry implements ITriggerRegistry {
|
||||
create(num: number): ITrigger | null {
|
||||
const factory = this.get(num);
|
||||
if (!factory) return null;
|
||||
return factory(num, this.state);
|
||||
return factory(num);
|
||||
}
|
||||
|
||||
registerString(id: string, factory: TriggerStringFactory): void {
|
||||
if (this.stringMap.has(id)) {
|
||||
logger.warn(132, 'id', id);
|
||||
}
|
||||
this.stringMap.set(id, factory);
|
||||
}
|
||||
|
||||
getString(id: string): TriggerStringFactory | null {
|
||||
return this.stringMap.get(id) ?? null;
|
||||
}
|
||||
|
||||
createByString(id: string): ITrigger | null {
|
||||
const factory = this.getString(id);
|
||||
if (!factory) return null;
|
||||
return factory();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,14 +1,9 @@
|
||||
import { ITileLocator } from '@motajs/common';
|
||||
import {
|
||||
ILayerState,
|
||||
IMapLayer,
|
||||
IStateBase,
|
||||
IStateBaseExtended
|
||||
} from '@user/data-base';
|
||||
import { ILayerState, IMapLayer, IStateBase } from '@user/data-base';
|
||||
|
||||
export interface ITriggerHandler {
|
||||
export interface ITriggerHandler<TEnemy = unknown, THero = unknown> {
|
||||
/** 当前全局状态对象 */
|
||||
readonly state: IStateBase;
|
||||
readonly state: IStateBase<TEnemy, THero>;
|
||||
/** 当前楼层状态对象 */
|
||||
readonly layer?: ILayerState;
|
||||
/** 当前参与触发的图层对象 */
|
||||
@ -17,9 +12,11 @@ export interface ITriggerHandler {
|
||||
readonly locator?: ITileLocator;
|
||||
}
|
||||
|
||||
export type TriggerFactory = (type: number, state: IStateBase) => ITrigger;
|
||||
export type TriggerFactory = (type: number) => ITrigger;
|
||||
|
||||
export interface ITrigger extends IStateBaseExtended {
|
||||
export type TriggerStringFactory = () => ITrigger;
|
||||
|
||||
export interface ITrigger {
|
||||
/** 触发器类型标识 */
|
||||
readonly type: number;
|
||||
/** 触发器优先级 */
|
||||
@ -29,7 +26,9 @@ export interface ITrigger extends IStateBaseExtended {
|
||||
* 使用给定上下文触发当前触发器
|
||||
* @param handler 触发上下文对象
|
||||
*/
|
||||
trigger(handler: ITriggerHandler): Promise<void>;
|
||||
trigger<TEnemy = unknown, THero = unknown>(
|
||||
handler: ITriggerHandler<TEnemy, THero>
|
||||
): Promise<void>;
|
||||
|
||||
/**
|
||||
* 将当前触发器包装为单元素触发器集合
|
||||
@ -37,7 +36,7 @@ export interface ITrigger extends IStateBaseExtended {
|
||||
collection(): ITriggerCollection;
|
||||
}
|
||||
|
||||
export interface ITriggerRegistry extends IStateBaseExtended {
|
||||
export interface ITriggerRegistry {
|
||||
/**
|
||||
* 注册一个按类型创建的触发器工厂
|
||||
* @param type 触发器类型
|
||||
@ -56,6 +55,25 @@ export interface ITriggerRegistry extends IStateBaseExtended {
|
||||
* @param num 触发器类型
|
||||
*/
|
||||
create(num: number): ITrigger | null;
|
||||
|
||||
/**
|
||||
* 注册一个按字符串 id 查询的触发器工厂
|
||||
* @param id 触发器字符串 id
|
||||
* @param factory 触发器工厂函数
|
||||
*/
|
||||
registerString(id: string, factory: TriggerStringFactory): void;
|
||||
|
||||
/**
|
||||
* 获取指定字符串 id 对应的触发器工厂
|
||||
* @param id 触发器字符串 id
|
||||
*/
|
||||
getString(id: string): TriggerStringFactory | null;
|
||||
|
||||
/**
|
||||
* 根据字符串 id 创建一个触发器实例,如果对应工厂不存在则返回 `null`
|
||||
* @param id 触发器字符串 id
|
||||
*/
|
||||
createByString(id: string): ITrigger | null;
|
||||
}
|
||||
|
||||
export interface ITriggerCollection {
|
||||
@ -68,15 +86,17 @@ export interface ITriggerCollection {
|
||||
* 顺序触发当前集合中的所有触发器
|
||||
* @param handler 初始触发上下文对象
|
||||
*/
|
||||
trigger(handler: ITriggerHandler): Promise<void>;
|
||||
trigger<TEnemy = unknown, THero = unknown>(
|
||||
handler: ITriggerHandler<TEnemy, THero>
|
||||
): Promise<void>;
|
||||
|
||||
/**
|
||||
* 逐个触发当前集合中的触发器,并允许为下一次推进提供新上下文
|
||||
* @param handler 初始触发上下文对象
|
||||
*/
|
||||
triggerIter(
|
||||
handler: ITriggerHandler
|
||||
): AsyncGenerator<ITrigger, void, ITriggerHandler | null>;
|
||||
triggerIter<TEnemy = unknown, THero = unknown>(
|
||||
handler: ITriggerHandler<TEnemy, THero>
|
||||
): AsyncGenerator<ITrigger, void, ITriggerHandler<TEnemy, THero> | null>;
|
||||
|
||||
/**
|
||||
* 迭代当前集合中的所有触发器
|
||||
|
||||
@ -1,18 +1,17 @@
|
||||
import { IStateBase } from '@user/data-base';
|
||||
import { IEnemyContext } from './combat';
|
||||
import { ITriggerCollector, ITriggerRegistry } from './trigger';
|
||||
import { IEnemyAttr, IHeroAttr } from '@user/data-common';
|
||||
|
||||
export interface IStateSystem extends IStateBase {
|
||||
export interface IStateSystem<TEnemy, THero> extends IStateBase<TEnemy, THero> {
|
||||
/** 怪物上下文 */
|
||||
readonly enemyContext: IEnemyContext<IEnemyAttr, IHeroAttr>;
|
||||
readonly enemyContext: IEnemyContext<TEnemy, THero>;
|
||||
/** 触发器注册 */
|
||||
readonly triggerRegistry: ITriggerRegistry;
|
||||
/** 触发器收集器 */
|
||||
readonly triggerCollector: ITriggerCollector;
|
||||
}
|
||||
|
||||
export interface IStateSystemExtended {
|
||||
export interface IStateSystemExtended<TEnemy = unknown, THero = unknown> {
|
||||
/** 当前对象对应的执行层对象(Layer 2 对象) */
|
||||
readonly state: IStateSystem;
|
||||
readonly state: IStateSystem<TEnemy, THero>;
|
||||
}
|
||||
|
||||
@ -193,7 +193,6 @@
|
||||
"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.",
|
||||
"135": "Expected a trigger registry attched before collect triggers.",
|
||||
"136": "Unexpected duplicate trigger priority $1, which may cause trigger executed in an unexpected order.",
|
||||
"137": "Unknown guard enemy at locator '$1,$2'."
|
||||
"136": "Unexpected duplicate trigger priority $1, which may cause trigger executed in an unexpected order."
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user