refactor: simplify buildCombatState and fix formatting in encounter
system Refactor `buildCombatState` to derive encounter data directly from `runState` instead of requiring it as an argument. Also apply consistent 2-space indentation and formatting to the encounter lifecycle module.
This commit is contained in:
parent
89d96d838b
commit
8142fbfa60
|
|
@ -1,9 +1,19 @@
|
|||
import type { PointCrawlMap } from '../map/types';
|
||||
import type { CombatState, EnemyEntity, PlayerEntity, EffectTable } from '../combat/types';
|
||||
import type { EncounterData, EnemyData, EffectData, IntentData } from '../types';
|
||||
import type { RunState } from './types';
|
||||
import { generateDeckFromInventory } from '../deck/factory';
|
||||
import { ReadonlyRNG } from '@/utils/rng';
|
||||
import type { PointCrawlMap } from "../map/types";
|
||||
import type {
|
||||
CombatState,
|
||||
EnemyEntity,
|
||||
PlayerEntity,
|
||||
EffectTable,
|
||||
} from "../combat/types";
|
||||
import type {
|
||||
EncounterData,
|
||||
EnemyData,
|
||||
EffectData,
|
||||
IntentData,
|
||||
} from "../types";
|
||||
import type { RunState } from "./types";
|
||||
import { generateDeckFromInventory } from "../deck/factory";
|
||||
import { ReadonlyRNG } from "@/utils/rng";
|
||||
|
||||
// -- Encounter assignment to nodes --
|
||||
|
||||
|
|
@ -14,7 +24,7 @@ import { ReadonlyRNG } from '@/utils/rng';
|
|||
export function assignEncounterToNode(
|
||||
map: PointCrawlMap,
|
||||
nodeId: string,
|
||||
encounter: EncounterData
|
||||
encounter: EncounterData,
|
||||
): void {
|
||||
const node = map.nodes.get(nodeId);
|
||||
if (!node) {
|
||||
|
|
@ -30,12 +40,12 @@ export function assignEncounterToNode(
|
|||
export function assignEncountersFromPool(
|
||||
map: PointCrawlMap,
|
||||
encounterPool: EncounterData[],
|
||||
rng: ReadonlyRNG
|
||||
rng: ReadonlyRNG,
|
||||
): void {
|
||||
if (encounterPool.length === 0) return;
|
||||
|
||||
for (const node of map.nodes.values()) {
|
||||
if (node.type === 'start' || node.type === 'end') continue;
|
||||
if (node.type === "start" || node.type === "end") continue;
|
||||
if (node.encounter) continue;
|
||||
|
||||
const assigned = encounterPool[rng.nextInt(encounterPool.length)];
|
||||
|
|
@ -50,10 +60,10 @@ export function assignEncountersFromPool(
|
|||
export function assignAllEncounters(
|
||||
map: PointCrawlMap,
|
||||
encounterIndex: Map<string, EncounterData[]>,
|
||||
rng: ReadonlyRNG
|
||||
rng: ReadonlyRNG,
|
||||
): void {
|
||||
for (const node of map.nodes.values()) {
|
||||
if (node.type === 'start' || node.type === 'end') continue;
|
||||
if (node.type === "start" || node.type === "end") continue;
|
||||
if (node.encounter) continue;
|
||||
|
||||
const encounterType = node.type;
|
||||
|
|
@ -72,10 +82,11 @@ export function assignAllEncounters(
|
|||
* - Creates PlayerEntity with energy (3), deck from inventory, and HP from run state
|
||||
* - Sets initial phase to 'playerTurn', turn 1
|
||||
*/
|
||||
export function buildCombatState(
|
||||
encounter: EncounterData,
|
||||
runState: RunState,
|
||||
): CombatState {
|
||||
export function buildCombatState(runState: RunState): CombatState {
|
||||
const encounter = getCurrentEncounterData(runState);
|
||||
if (!encounter)
|
||||
throw new Error(`No encounter found for node ${runState.currentNodeId}`);
|
||||
|
||||
const enemies = createEnemyEntities(encounter);
|
||||
const deck = generateDeckFromInventory(runState.inventory);
|
||||
const player = createPlayerEntity(runState, deck);
|
||||
|
|
@ -84,7 +95,7 @@ export function buildCombatState(
|
|||
enemies,
|
||||
player,
|
||||
inventory: runState.inventory,
|
||||
phase: 'playerTurn',
|
||||
phase: "playerTurn",
|
||||
turnNumber: 1,
|
||||
result: null,
|
||||
loot: [],
|
||||
|
|
@ -95,9 +106,7 @@ export function buildCombatState(
|
|||
* Creates EnemyEntity instances from encounter enemy definitions.
|
||||
* Each enemy gets: HP from encounter tuple, initial buffs from encounter, intents from enemy definition.
|
||||
*/
|
||||
export function createEnemyEntities(
|
||||
encounter: EncounterData,
|
||||
): EnemyEntity[] {
|
||||
export function createEnemyEntities(encounter: EncounterData): EnemyEntity[] {
|
||||
const enemies: EnemyEntity[] = [];
|
||||
let instanceCounter = 0;
|
||||
|
||||
|
|
@ -126,9 +135,7 @@ export function createEnemyEntities(
|
|||
/**
|
||||
* Builds a map of intent ID -> IntentData for an enemy.
|
||||
*/
|
||||
function buildIntentMap(
|
||||
enemy: EnemyData,
|
||||
): Record<string, IntentData> {
|
||||
function buildIntentMap(enemy: EnemyData): Record<string, IntentData> {
|
||||
const intents: Record<string, IntentData> = {};
|
||||
for (const intent of enemy.intents) {
|
||||
intents[intent.id] = intent;
|
||||
|
|
@ -165,7 +172,10 @@ function buildEffectTable(buffs: readonly [EffectData, number][]): EffectTable {
|
|||
/**
|
||||
* Creates a PlayerEntity from the run state and deck.
|
||||
*/
|
||||
function createPlayerEntity(runState: RunState, deck: ReturnType<typeof generateDeckFromInventory>): PlayerEntity {
|
||||
function createPlayerEntity(
|
||||
runState: RunState,
|
||||
deck: ReturnType<typeof generateDeckFromInventory>,
|
||||
): PlayerEntity {
|
||||
return {
|
||||
id: "player",
|
||||
hp: runState.player.currentHp,
|
||||
|
|
@ -184,7 +194,9 @@ function createPlayerEntity(runState: RunState, deck: ReturnType<typeof generate
|
|||
/**
|
||||
* Gets the encounter data for the current node.
|
||||
*/
|
||||
export function getCurrentEncounterData(runState: RunState): EncounterData | undefined {
|
||||
export function getCurrentEncounterData(
|
||||
runState: RunState,
|
||||
): EncounterData | undefined {
|
||||
const node = runState.map.nodes.get(runState.currentNodeId);
|
||||
return node?.encounter;
|
||||
}
|
||||
|
|
@ -207,7 +219,7 @@ export function startEncounter(runState: RunState): CombatState | null {
|
|||
return null;
|
||||
}
|
||||
|
||||
return buildCombatState(encounter, runState);
|
||||
return buildCombatState(runState);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -217,10 +229,10 @@ export function startEncounter(runState: RunState): CombatState | null {
|
|||
*/
|
||||
export function resolveCombatEncounter(
|
||||
runState: RunState,
|
||||
combatState: CombatState
|
||||
combatState: CombatState,
|
||||
): { success: true } | { success: false; reason: string } {
|
||||
if (runState.currentEncounter.resolved) {
|
||||
return { success: false, reason: '该遭遇已解决' };
|
||||
return { success: false, reason: "该遭遇已解决" };
|
||||
}
|
||||
|
||||
// Apply HP from combat state back to run state
|
||||
|
|
@ -228,7 +240,7 @@ export function resolveCombatEncounter(
|
|||
|
||||
// Apply loot
|
||||
for (const loot of combatState.loot) {
|
||||
if (loot.type === 'gold') {
|
||||
if (loot.type === "gold") {
|
||||
runState.player.gold += loot.amount;
|
||||
}
|
||||
// Item rewards are handled by the caller via addItem()
|
||||
|
|
|
|||
Loading…
Reference in New Issue