You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
AdLike2048/assets/mx/module/battle/deploy/DeployValidator.ts

72 lines
2.8 KiB

3 weeks ago
import type { BattleServices } from '../combat/BattleServices';
import type { Cell } from '../battlefield/Cell';
import type { DeployResult, DeployRule } from './DeployTypes';
import { BattlePhase } from '../core/BattlePhase';
/** 仅允许 PREP 阶段部署(连续模式放宽) */
export class PrepPhaseOnlyRule implements DeployRule {
check(services: BattleServices, _playerId: number, _unitDefId: string, cells: Cell[]): DeployResult {
if (services.phase !== BattlePhase.PREP && !services.isContinuousFlow) {
return { ok: false, reason: 'not_prep_phase' };
}
return { ok: true, cells };
}
}
/** 格子必须在玩家部署区域内 */
export class InPlayerRegionRule implements DeployRule {
check(services: BattleServices, playerId: number, _unitDefId: string, cells: Cell[]): DeployResult {
const player = services.players[playerId];
if (!player) return { ok: false, reason: 'invalid_player' };
for (const c of cells) {
if (!player.region.contains(c)) return { ok: false, reason: 'out_of_region' };
}
return { ok: true, cells };
}
}
/** 格子必须未被 ECS 占用(合成格由 DeploySync 在部署前同步 buildable) */
export class CellEmptyRule implements DeployRule {
check(services: BattleServices, _playerId: number, _unitDefId: string, cells: Cell[]): DeployResult {
for (const c of cells) {
const s = services.grid.getCell(c);
if (!s) return { ok: false, reason: 'out_of_bounds' };
if (s.occupant != null) return { ok: false, reason: 'cell_occupied' };
}
return { ok: true, cells };
}
}
/** 玩家金币必须足够 */
export class EnoughGoldRule implements DeployRule {
check(services: BattleServices, playerId: number, unitDefId: string, _cells: Cell[]): DeployResult {
const def = services.config.getUnit(unitDefId);
const cost = def?.deploy?.cost ?? 0;
const player = services.players[playerId];
if (!player || player.gold < cost) return { ok: false, reason: 'not_enough_gold' };
return { ok: true };
}
}
/** 占地形状必须在地图范围内 */
export class ShapeInBoundsRule implements DeployRule {
check(services: BattleServices, _playerId: number, _unitDefId: string, cells: Cell[]): DeployResult {
for (const c of cells) {
if (!services.grid.inBounds(c)) return { ok: false, reason: 'out_of_bounds' };
}
return { ok: true, cells };
}
}
/** @returns 默认部署规则链 */
export function createDefaultDeployRules(): DeployRule[] {
return [
new PrepPhaseOnlyRule(),
new ShapeInBoundsRule(),
new InPlayerRegionRule(),
new CellEmptyRule(),
];
}
export type { DeployRule };