template/packages-user/data-state/src/content/triggers.ts
2026-07-26 20:22:36 +08:00

163 lines
4.9 KiB
TypeScript

import { IFacedTileLocator, logger } from '@motajs/common';
import {
IHeroChangeFloorInfo,
IHeroState,
IMapLayer,
IMapState,
IStateBase
} from '@user/data-base';
import {
ChangeFloorPos,
ChangeFloorTarget,
ChangeFloorType,
FaceDirection,
IChangeFloorData,
IHeroAttr
} from '@user/data-common';
import {
BaseTrigger,
ITrigger,
ITriggerCollection,
ITriggerHandler,
TriggerCollection
} from '@user/data-system';
import { isNil } from 'lodash-es';
export const enum TriggerType {
/** 楼层切换触发器 */
ChangeFloor
}
export class ChangeFloorTrigger extends BaseTrigger implements ITrigger {
readonly type: number = TriggerType.ChangeFloor;
readonly priority: number = 10;
constructor(
state: IStateBase,
readonly maps: IMapState,
readonly hero: IHeroState<IHeroAttr>
) {
super(state);
}
/**
* 获取楼层切换的目标楼层
* @param data 楼层切换数据
*/
private getFloorTarget(data: IChangeFloorData): string | undefined {
if (data.floorType === ChangeFloorType.Specified) {
if (isNil(data.targetFloor)) {
logger.warn(165);
return void 0;
}
return data.targetFloor;
} else {
if (isNil(data.relatedFloor)) {
logger.warn(166);
return void 0;
}
const curr = this.hero.location.floorId;
if (isNil(curr)) {
logger.warn(167);
return void 0;
}
const index = this.maps.maps.indexOf(curr);
if (index === -1) {
logger.warn(168);
return void 0;
}
if (data.relatedFloor === ChangeFloorTarget.Next) {
const next = this.maps.maps[index + 1];
if (isNil(next)) {
logger.warn(169);
return void 0;
}
return next;
} else {
const next = this.maps.maps[index - 1];
if (isNil(next)) {
logger.warn(169);
return void 0;
}
}
}
}
private getPosTarget(
data: IChangeFloorData,
layer: IMapLayer
): IFacedTileLocator | undefined {
if (data.posType === ChangeFloorType.Specified) {
if (!data.targetPos) {
logger.warn(165);
return void 0;
}
return data.targetPos;
} else {
if (isNil(data.relatedPos)) {
logger.warn(166);
return void 0;
}
const { x, y, floorId } = this.hero.location;
if (isNil(floorId)) {
logger.warn(167);
return void 0;
}
const { width, height } = layer;
switch (data.relatedPos) {
case ChangeFloorPos.Stand:
return {
direction: FaceDirection.Unknown,
x,
y
};
case ChangeFloorPos.SymmetryX:
return {
direction: FaceDirection.Unknown,
x: width - x - 1,
y
};
case ChangeFloorPos.SymmetryY:
return {
direction: FaceDirection.Unknown,
x,
y: height - y - 1
};
case ChangeFloorPos.CentralSymmetry:
return {
direction: FaceDirection.Unknown,
x: width - x - 1,
y: height - y - 1
};
}
}
}
async trigger(handler: ITriggerHandler): Promise<void> {
if (!handler.layer || !handler.locator || !handler.mapLayer) {
logger.warn(164);
return;
}
const { x, y } = handler.locator;
const data = handler.mapLayer.getLocationData(x, y);
if (!data || !data.block.changeFloor) return;
const floor = this.getFloorTarget(data.block.changeFloor);
const pos = this.getPosTarget(data.block.changeFloor, handler.mapLayer);
if (isNil(floor) || isNil(pos)) return;
const hero = handler.state.hero;
const isUnknown = pos.direction === FaceDirection.Unknown;
const defaults = hero.location.mover.faceDirection;
const info: IHeroChangeFloorInfo = {
target: floor,
x: pos.x,
y: pos.y,
face: isUnknown ? defaults : pos.direction
};
return handler.state.hero.changeFloor(info);
}
collection(): ITriggerCollection {
return new TriggerCollection([this]);
}
}