feat: 勇士撞击行为

This commit is contained in:
AncTe committed 2026-06-29 19:57:46 +08:00
1 parent 0508dfb9e4
commit c4bcecdf8a
12 files changed
+380 -254

No files matched your search

@@ -1,73 +1,18 @@
import { ITileLocator } from '@motajs/common';
import { FaceDirection, PassBit } from '@user/data-common';
import { IHeroState, IStateBase, ITerrainPassChecker } from '@user/data-base';
import {
IHeroState,
IMapStore,
IPassCheckerHandler,
ITerrainPassChecker
} from '@user/data-base';
import { isNil } from 'lodash-es';
export class DefaultPassChecker implements ITerrainPassChecker {
constructor(
readonly state: IStateBase,
readonly maps: IMapStore,
readonly hero: IHeroState<unknown>
) {}
canPass(
locator: ITileLocator,
direction: FaceDirection,
floorId: string | undefined
): boolean {
if (isNil(floorId)) return false;
if (
direction === FaceDirection.LeftDown ||
direction === FaceDirection.LeftUp ||
direction === FaceDirection.RightDown ||
direction === FaceDirection.RightUp
) {
return true;
}
const layerState = this.state.maps.getLayerState(floorId);
if (!layerState) return false;
const eventLayer = layerState.eventLayer;
if (!eventLayer) return false;
const { x, y } = locator;
const face = this.hero.location.mover.faceHandler;
const { x: dx, y: dy } = face.movement(direction);
const nx = x + dx;
const ny = y + dy;
const opposite = face.opposite(direction);
const leaveMask = this.directionToPassBit(direction);
const enterMask = this.directionToPassBit(opposite);
let canLeave = true;
let canEnter = true;
const eventCurr = eventLayer.getLocationData(x, y);
const eventNext = eventLayer.getLocationData(nx, ny);
if (eventCurr && eventCurr.raw) {
canLeave = !!(leaveMask & eventCurr.raw.pass.outPass);
}
if (eventNext && eventNext.raw) {
canEnter = !!(enterMask & eventNext.raw.pass.inPass);
}
if (!canLeave || !canEnter) return false;
for (const layer of layerState.layerList) {
if (layer === eventLayer) continue;
const curr = layer.getLocationData(x, y);
const next = layer.getLocationData(nx, ny);
if (curr && curr.raw && curr.raw.pass.onlyEvents) {
canLeave = !!(leaveMask & curr.raw.pass.outPass);
}
if (next && next.raw && next.raw.pass.onlyEvents) {
canEnter = !!(enterMask & next.raw.pass.inPass);
}
if (!canLeave || !canEnter) return false;
}
return true;
}
/**
* 将朝向转换为对应的通行性位掩码。
* @param dir 朝向
@@ -86,4 +31,87 @@ export class DefaultPassChecker implements ITerrainPassChecker {
return 0;
}
}
inBound(x: number, y: number, floorId: string | undefined): boolean {
if (isNil(floorId)) return false;
const layerState = this.maps.getLayerState(floorId);
if (!layerState) return false;
const { width, height } = layerState;
return x >= 0 && y >= 0 && x < width && y < height;
}
canPass(handler: IPassCheckerHandler): boolean {
const { currLoc, nextLoc, direction, floorId, face } = handler;
if (isNil(floorId)) return false;
// 四角朝向直接判定为可通行
if (
direction === FaceDirection.LeftDown ||
direction === FaceDirection.LeftUp ||
direction === FaceDirection.RightDown ||
direction === FaceDirection.RightUp
) {
return true;
}
const layerState = this.maps.getLayerState(floorId);
if (!layerState) return false;
const eventLayer = layerState.eventLayer;
if (!eventLayer) return false;
const { x, y } = currLoc;
const { x: nx, y: ny } = nextLoc;
const opposite = face.opposite(direction);
const leaveMask = this.directionToPassBit(direction);
const enterMask = this.directionToPassBit(opposite);
let canLeave = true;
let canEnter = true;
// 判断事件层
const curr = eventLayer.getLocationData(x, y);
const next = eventLayer.getLocationData(nx, ny);
if (curr && curr.raw) {
canLeave = !!(leaveMask & curr.raw.pass.outPass);
}
if (next && next.raw) {
canEnter = !!(enterMask & next.raw.pass.inPass);
}
if (!canLeave || !canEnter) return false;
// 判断其他层
for (const layer of layerState.layerList) {
if (layer === eventLayer) continue;
const curr = layer.getLocationData(x, y);
const next = layer.getLocationData(nx, ny);
let canLeave = true;
let canEnter = true;
if (curr && curr.raw && curr.raw.pass.onlyEvents) {
canLeave = !!(leaveMask & curr.raw.pass.outPass);
}
if (next && next.raw && next.raw.pass.onlyEvents) {
canEnter = !!(enterMask & next.raw.pass.inPass);
}
if (!canLeave || !canEnter) return false;
}
return true;
}
shouldHit(handler: IPassCheckerHandler): boolean {
const { nextLoc, floorId } = handler;
if (isNil(floorId)) return false;
const layerState = this.maps.getLayerState(floorId);
if (!layerState) return false;
const eventLayer = layerState.eventLayer;
if (!eventLayer) return false;
const { x: nx, y: ny } = nextLoc;
const next = eventLayer.getLocationData(nx, ny);
if (!next || !next.raw) return false;
return !next.raw.eventPass;
}
}
+6 -8
View File
@@ -36,25 +36,22 @@ export class TileLegacyBridge implements ITileLegacyConverter<LegacyTileData> {
private getPass(num: number, legacy: LegacyTileData): ITilePassData {
if (num === 0) {
// 空图块
return {
onlyEvents: true,
inPass: 0b1111,
outPass: 0b1111
};
} else if (num === 17) {
// 空气墙
return {
onlyEvents: false,
inPass: 0b0000,
outPass: 0b0000
};
} else {
if (legacy.noPass) {
return {
onlyEvents: true,
inPass: 0b0000,
outPass: 0b1111
};
} else if (legacy.cannotIn && legacy.cannotOut) {
// 正常图块
if (legacy.cannotIn && legacy.cannotOut) {
let inPass = 0b1111;
let outPass = 0b1111;
if (legacy.cannotIn.includes('up')) {
@@ -102,7 +99,8 @@ export class TileLegacyBridge implements ITileLegacyConverter<LegacyTileData> {
id: legacy.id,
trigger: -1,
type: this.getTileType(num, legacy),
pass: this.getPass(num, legacy)
pass: this.getPass(num, legacy),
eventPass: !legacy.noPass
};
}
}