mirror of
https://github.com/motajs/template.git
synced 2026-05-19 16:41:09 +08:00
feat: 触发器收集
This commit is contained in:
parent
7428f41c93
commit
03dc5ea60b
@ -33,7 +33,11 @@ import {
|
||||
DamageSystem,
|
||||
EnemyContext,
|
||||
IEnemyContext,
|
||||
MapDamage
|
||||
ITriggerCollector,
|
||||
ITriggerRegistry,
|
||||
MapDamage,
|
||||
TriggerCollector,
|
||||
TriggerRegistry
|
||||
} from '@user/data-system';
|
||||
import {
|
||||
CommonAuraConverter,
|
||||
@ -78,6 +82,8 @@ export class CoreState implements ICoreState {
|
||||
|
||||
// Layer 2 内容
|
||||
readonly enemyContext: IEnemyContext<IEnemyAttr, IHeroAttr>;
|
||||
readonly triggerRegistry: ITriggerRegistry;
|
||||
readonly triggerCollector: ITriggerCollector;
|
||||
|
||||
// 用户层内容
|
||||
readonly loadProgress: ILoadProgressTotal;
|
||||
@ -95,26 +101,43 @@ export class CoreState implements ICoreState {
|
||||
> = new Map();
|
||||
|
||||
constructor() {
|
||||
//#region L0 初始化
|
||||
|
||||
// 朝向
|
||||
this.roleFace = new RoleFaceBinder();
|
||||
this.faceManager = new FaceManager();
|
||||
const dir4 = new Dir4FaceHandler();
|
||||
const dir8 = new Dir8FaceHandler();
|
||||
this.faceManager.register(FaceGroup.Dir4, dir4);
|
||||
this.faceManager.registerById('dir4', dir4);
|
||||
this.faceManager.register(FaceGroup.Dir8, dir8);
|
||||
this.faceManager.registerById('dir8', dir8);
|
||||
|
||||
// 图块
|
||||
const tileStore = new TileStore<LegacyTileData>();
|
||||
tileStore.attachLegacyConverter(new TileLegacyBridge());
|
||||
this.tileStore = tileStore;
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region L1 初始化
|
||||
|
||||
// Flag 系统
|
||||
this.flags = new FlagSystem();
|
||||
|
||||
// 地图
|
||||
this.maps = new MapStore(tileStore, this);
|
||||
|
||||
this.loadProgress = new LoadProgressTotal();
|
||||
this.dataLoader = new MotaDataLoader(this.loadProgress);
|
||||
|
||||
//#region 勇士初始化
|
||||
|
||||
// 勇士
|
||||
const heroMover = new HeroMover();
|
||||
const heroAttribute = new HeroAttribute(HERO_DEFAULT_ATTRIBUTE);
|
||||
const heroState = new HeroState(heroMover, heroAttribute);
|
||||
this.hero = heroState;
|
||||
|
||||
//#endregion
|
||||
this.loadProgress = new LoadProgressTotal();
|
||||
this.dataLoader = new MotaDataLoader(this.loadProgress);
|
||||
|
||||
//#region 怪物初始化
|
||||
|
||||
// 怪物管理器初始化
|
||||
// 怪物管理器
|
||||
const comparer = new MainEnemyComparer();
|
||||
const enemyManager = new EnemyManager(new EnemyLegacyBridge());
|
||||
enemyManager.attachEnemyComparer(comparer);
|
||||
@ -126,7 +149,12 @@ export class CoreState implements ICoreState {
|
||||
enemyManager.setAttributeDefaults('point', 0);
|
||||
registerSpecials(enemyManager);
|
||||
this.enemyManager = enemyManager;
|
||||
// 怪物上下文初始化
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region L2 初始化
|
||||
|
||||
// 怪物上下文
|
||||
const enemyContext = new EnemyContext<IEnemyAttr, IHeroAttr>(this);
|
||||
const damageSystem = new DamageSystem(enemyContext);
|
||||
const mapDamage = new MapDamage(enemyContext);
|
||||
@ -142,10 +170,18 @@ export class CoreState implements ICoreState {
|
||||
enemyContext.bindHero(heroAttribute);
|
||||
this.enemyContext = enemyContext;
|
||||
|
||||
// 触发器注册与收集器
|
||||
const triggerRegistry = new TriggerRegistry();
|
||||
const triggerCollector = new TriggerCollector();
|
||||
triggerCollector.attachRegistry(triggerRegistry);
|
||||
this.triggerRegistry = triggerRegistry;
|
||||
this.triggerCollector = triggerCollector;
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region 存档系统
|
||||
//#region 顶层初始化
|
||||
|
||||
// 存档系统
|
||||
this.saveSystem = new SaveSystem();
|
||||
// 配置存档系统,一般情况下不建议动,除非你知道你在干什么
|
||||
this.saveSystem.config({
|
||||
@ -155,29 +191,16 @@ export class CoreState implements ICoreState {
|
||||
saveTimeTolerance: 100,
|
||||
autosaveStackSize: 20
|
||||
});
|
||||
|
||||
this.addSaveableContent('@system/hero', this.hero);
|
||||
this.addSaveableContent('@system/flags', this.flags);
|
||||
this.addSaveableContent('@system/maps', this.maps);
|
||||
this.addSaveableContent('@system/enemy', this.enemyManager);
|
||||
// 初始化存档数据库,不要动
|
||||
loading.once('coreInit', () => {
|
||||
this.saveSystem.init(`@game/${core.firstData.name}`);
|
||||
});
|
||||
|
||||
//#endregion
|
||||
|
||||
//#region 其他初始化
|
||||
|
||||
// 朝向
|
||||
this.roleFace = new RoleFaceBinder();
|
||||
this.faceManager = new FaceManager();
|
||||
const dir4 = new Dir4FaceHandler();
|
||||
const dir8 = new Dir8FaceHandler();
|
||||
this.faceManager.register(FaceGroup.Dir4, dir4);
|
||||
this.faceManager.registerById('dir4', dir4);
|
||||
this.faceManager.register(FaceGroup.Dir8, dir8);
|
||||
this.faceManager.registerById('dir8', dir8);
|
||||
|
||||
this.flags = new FlagSystem();
|
||||
|
||||
// 加载先使用兼容层实现
|
||||
// 加载初始化,先使用兼容层实现
|
||||
loading.once('loaded', () => {
|
||||
this.initTileStore(core.maps.blocksInfo);
|
||||
this.initEnemyManager(enemys_fcae963b_31c9_42b4_b48c_bb48d09f3f80);
|
||||
@ -186,13 +209,6 @@ export class CoreState implements ICoreState {
|
||||
core.floors as Record<FloorIds, ResolvedFloor>
|
||||
);
|
||||
});
|
||||
|
||||
this.addSaveableContent('@system/hero', this.hero);
|
||||
this.addSaveableContent('@system/flags', this.flags);
|
||||
this.addSaveableContent('@system/maps', this.maps);
|
||||
this.addSaveableContent('@system/enemy', this.enemyManager);
|
||||
|
||||
//#endregion
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -5,7 +5,7 @@ export class TriggerCollection implements ITriggerCollection {
|
||||
private readonly triggerList: ITrigger[];
|
||||
|
||||
constructor(triggers: Iterable<ITrigger>) {
|
||||
this.triggerList = Array.from(triggers);
|
||||
this.triggerList = [...triggers];
|
||||
}
|
||||
|
||||
count(): number {
|
||||
|
||||
112
packages-user/data-system/src/trigger/collector.ts
Normal file
112
packages-user/data-system/src/trigger/collector.ts
Normal file
@ -0,0 +1,112 @@
|
||||
import { IMapLayer } from '@user/data-base';
|
||||
import {
|
||||
ITrigger,
|
||||
ITriggerCollection,
|
||||
ITriggerCollector,
|
||||
ITriggerRegistry
|
||||
} from './types';
|
||||
import { logger } from '@motajs/common';
|
||||
import { TriggerCollection } from './collection';
|
||||
|
||||
export class TriggerCollector implements ITriggerCollector {
|
||||
/** 当前收集器使用的注册对象 */
|
||||
private registry: ITriggerRegistry | null = null;
|
||||
|
||||
collect(x: number, y: number, layer: IMapLayer): ITriggerCollection {
|
||||
if (!this.registry) {
|
||||
logger.warn(135);
|
||||
return new TriggerCollection([]);
|
||||
}
|
||||
const staticType = layer.getTriggerType(x, y);
|
||||
const staticTrigger = this.registry.create(staticType);
|
||||
const dynamics = [...layer.dynamicLayer.getDynamicTilesAt(x, y)];
|
||||
|
||||
if (dynamics.length === 0) {
|
||||
// 没有动态图块
|
||||
if (staticTrigger) {
|
||||
return new TriggerCollection([staticTrigger]);
|
||||
} else {
|
||||
return new TriggerCollection([]);
|
||||
}
|
||||
} else if (dynamics.length === 1) {
|
||||
// 一个动态图块,只需要进行一次额外判断即可
|
||||
const dynamic = dynamics[0];
|
||||
const dynamicTrigger = this.registry.create(dynamic.triggerType);
|
||||
// 直接穷举所有可能情况
|
||||
if (!staticTrigger && !dynamicTrigger) {
|
||||
return new TriggerCollection([]);
|
||||
} else if (staticTrigger && !dynamicTrigger) {
|
||||
return new TriggerCollection([staticTrigger]);
|
||||
} else if (!staticTrigger && dynamicTrigger) {
|
||||
return new TriggerCollection([dynamicTrigger]);
|
||||
} else {
|
||||
// 静态动态都有,则需要额外判断优先级,动态图层在前,因此包含等号
|
||||
if (dynamicTrigger!.priority >= staticTrigger!.priority) {
|
||||
const arr = [dynamicTrigger!, staticTrigger!];
|
||||
return new TriggerCollection(arr);
|
||||
} else {
|
||||
const arr = [staticTrigger!, dynamicTrigger!];
|
||||
return new TriggerCollection(arr);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// 动态图块大于两个,使用通用方案,记录重复触发器并抛出警告
|
||||
const usedPriority = new Set<number>();
|
||||
const duplicate = new Set<number>();
|
||||
if (staticTrigger) {
|
||||
// 有静态触发器
|
||||
const lessTriggers: ITrigger[] = [];
|
||||
const greaterTriggers: ITrigger[] = [];
|
||||
// 先收集所有的触发器,并记录重复情况
|
||||
for (const tile of layer.dynamicLayer.getDynamicTilesAt(x, y)) {
|
||||
const trigger = this.registry.create(tile.triggerType);
|
||||
if (trigger) {
|
||||
if (usedPriority.has(trigger.priority)) {
|
||||
duplicate.add(trigger.priority);
|
||||
}
|
||||
usedPriority.add(trigger.priority);
|
||||
|
||||
// 同优先级下动态在前,因此包含等号
|
||||
if (trigger.priority >= staticTrigger.priority) {
|
||||
greaterTriggers.push(trigger);
|
||||
} else {
|
||||
lessTriggers.push(trigger);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (duplicate.size > 0) {
|
||||
logger.warn(136, [...duplicate].join(','));
|
||||
}
|
||||
const arr = [
|
||||
...greaterTriggers.sort((a, b) => b.priority - a.priority),
|
||||
staticTrigger,
|
||||
...lessTriggers.sort((a, b) => b.priority - a.priority)
|
||||
];
|
||||
return new TriggerCollection(arr);
|
||||
} else {
|
||||
// 没有静态触发器
|
||||
const triggers: ITrigger[] = [];
|
||||
for (const tile of layer.dynamicLayer.getDynamicTilesAt(x, y)) {
|
||||
const trigger = this.registry.create(tile.triggerType);
|
||||
if (trigger) {
|
||||
if (usedPriority.has(trigger.priority)) {
|
||||
duplicate.add(trigger.priority);
|
||||
}
|
||||
usedPriority.add(trigger.priority);
|
||||
triggers.push(trigger);
|
||||
}
|
||||
}
|
||||
if (duplicate.size > 0) {
|
||||
logger.warn(136, [...duplicate].join(','));
|
||||
}
|
||||
return new TriggerCollection(
|
||||
triggers.sort((a, b) => b.priority - a.priority)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
attachRegistry(registry: ITriggerRegistry | null): void {
|
||||
this.registry = registry;
|
||||
}
|
||||
}
|
||||
@ -1,3 +1,4 @@
|
||||
export * from './types';
|
||||
export * from './collection';
|
||||
export * from './collector';
|
||||
export * from './registry';
|
||||
export * from './types';
|
||||
|
||||
@ -1,9 +1,14 @@
|
||||
import { IStateBase } from '@user/data-base';
|
||||
import { IEnemyContext } from './combat';
|
||||
import { ITriggerCollector, ITriggerRegistry } from './trigger';
|
||||
|
||||
export interface IStateSystem<TEnemy, THero> extends IStateBase<TEnemy, THero> {
|
||||
/** 怪物上下文 */
|
||||
readonly enemyContext: IEnemyContext<TEnemy, THero>;
|
||||
/** 触发器注册 */
|
||||
readonly triggerRegistry: ITriggerRegistry;
|
||||
/** 触发器收集器 */
|
||||
readonly triggerCollector: ITriggerCollector;
|
||||
}
|
||||
|
||||
export interface IStateSystemExtended<TEnemy = unknown, THero = unknown> {
|
||||
|
||||
@ -55,8 +55,7 @@
|
||||
"53": "Expected serializable value set as enemy's default attribute.",
|
||||
"54": "Legacy '$1' API has been removed, consider using new APIs: '$2'.",
|
||||
"55": "Cannot load MapStore state: reference data (compareWith) has not been set.",
|
||||
"56": "Cannot convert legacy tile data since no tile legacy converter is attached to TileStore.",
|
||||
"1201": "Floor-damage extension needs 'floor-binder' extension as dependency."
|
||||
"56": "Cannot convert legacy tile data since no tile legacy converter is attached to TileStore."
|
||||
},
|
||||
"warn": {
|
||||
"1": "Resource with type of 'none' is loaded.",
|
||||
@ -193,6 +192,7 @@
|
||||
"132": "Trigger registry entry of $1 '$2' already exists, new factory will override old factory.",
|
||||
"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.",
|
||||
"1001": "Item-detail extension needs 'floor-binder' and 'floor-damage' extension as dependency."
|
||||
"135": "Expected a trigger registry attched before collect triggers.",
|
||||
"136": "Unexpected duplicate trigger priority $1, which may cause trigger executed in an unexpected order."
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user