fix: encounter generation
This commit is contained in:
parent
af0906561c
commit
a80852bc59
|
|
@ -1,11 +1,9 @@
|
|||
import type { PointCrawlMap, MapNode } from '../map/types';
|
||||
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, GameItemMeta } from './types';
|
||||
import type { GridInventory } from '../grid-inventory/types';
|
||||
import type { RunState } from './types';
|
||||
import { generateDeckFromInventory } from '../deck/factory';
|
||||
import { ReadonlyRNG } from '@/utils/rng';
|
||||
import { createRegion } from '@/core/region';
|
||||
|
||||
// -- Encounter assignment to nodes --
|
||||
|
||||
|
|
@ -77,10 +75,8 @@ export function assignAllEncounters(
|
|||
export function buildCombatState(
|
||||
encounter: EncounterData,
|
||||
runState: RunState,
|
||||
intentPool: IntentData[] = []
|
||||
): CombatState {
|
||||
const intentIndex = buildIntentIndex(intentPool);
|
||||
const enemies = createEnemyEntities(encounter, intentIndex);
|
||||
const enemies = createEnemyEntities(encounter);
|
||||
const deck = generateDeckFromInventory(runState.inventory);
|
||||
const player = createPlayerEntity(runState, deck);
|
||||
|
||||
|
|
@ -95,47 +91,33 @@ export function buildCombatState(
|
|||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an index of intents by their ID for fast lookup.
|
||||
*/
|
||||
function buildIntentIndex(intentPool: IntentData[]): Map<string, IntentData> {
|
||||
const index = new Map<string, IntentData>();
|
||||
for (const intent of intentPool) {
|
||||
index.set(intent.id, intent);
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates EnemyEntity instances from encounter enemy definitions.
|
||||
* Each enemy gets: initial HP from enemy data, initial buffs from encounter, intents from enemy definition.
|
||||
* Each enemy gets: HP from encounter tuple, initial buffs from encounter, intents from enemy definition.
|
||||
*/
|
||||
export function createEnemyEntities(
|
||||
encounter: EncounterData,
|
||||
intentIndex: Map<string, IntentData>
|
||||
): EnemyEntity[] {
|
||||
const enemies: EnemyEntity[] = [];
|
||||
let instanceCounter = 0;
|
||||
|
||||
for (const [enemyData, count, encounterBuffs] of encounter.enemies) {
|
||||
for (let i = 0; i < count; i++) {
|
||||
const instanceId = `${enemyData.id}-${instanceCounter++}`;
|
||||
const intents = buildIntentMap(enemyData, intentIndex);
|
||||
const initialIntentId = findInitialIntent(enemyData, intentIndex);
|
||||
const effects = buildEffectTable(encounterBuffs);
|
||||
for (const [enemyData, hp, encounterBuffs] of encounter.enemies) {
|
||||
const instanceId = `${enemyData.id}-${instanceCounter++}`;
|
||||
const intents = buildIntentMap(enemyData);
|
||||
const initialIntent = findInitialIntent(enemyData);
|
||||
const effects = buildEffectTable(encounterBuffs);
|
||||
|
||||
const entity: EnemyEntity = {
|
||||
id: instanceId,
|
||||
enemy: enemyData,
|
||||
hp: enemyData.hp,
|
||||
maxHp: enemyData.hp,
|
||||
isAlive: true,
|
||||
effects,
|
||||
intents,
|
||||
currentIntentId: initialIntentId,
|
||||
};
|
||||
enemies.push(entity);
|
||||
}
|
||||
const entity: EnemyEntity = {
|
||||
id: instanceId,
|
||||
enemy: enemyData,
|
||||
hp,
|
||||
maxHp: hp,
|
||||
isAlive: true,
|
||||
effects,
|
||||
intents,
|
||||
currentIntent: initialIntent,
|
||||
};
|
||||
enemies.push(entity);
|
||||
}
|
||||
|
||||
return enemies;
|
||||
|
|
@ -146,14 +128,10 @@ export function createEnemyEntities(
|
|||
*/
|
||||
function buildIntentMap(
|
||||
enemy: EnemyData,
|
||||
intentIndex: Map<string, IntentData>
|
||||
): Record<string, IntentData> {
|
||||
const intents: Record<string, IntentData> = {};
|
||||
for (const intentId of enemy.intentIds) {
|
||||
const intent = intentIndex.get(intentId);
|
||||
if (intent) {
|
||||
intents[intentId] = intent;
|
||||
}
|
||||
for (const intent of enemy.intents) {
|
||||
intents[intent.id] = intent;
|
||||
}
|
||||
return intents;
|
||||
}
|
||||
|
|
@ -161,18 +139,16 @@ function buildIntentMap(
|
|||
/**
|
||||
* Finds the initial intent ID for an enemy.
|
||||
*/
|
||||
function findInitialIntent(
|
||||
enemy: EnemyData,
|
||||
intentIndex: Map<string, IntentData>
|
||||
): string {
|
||||
for (const intentId of enemy.intentIds) {
|
||||
const intent = intentIndex.get(intentId);
|
||||
if (intent?.initialIntent) {
|
||||
return intentId;
|
||||
function findInitialIntent(enemy: EnemyData): IntentData {
|
||||
for (const intent of enemy.intents) {
|
||||
if (intent.initialIntent) {
|
||||
return intent;
|
||||
}
|
||||
}
|
||||
// Fallback: first intent
|
||||
return enemy.intentIds[0] ?? '';
|
||||
if (enemy.intents.length === 0) {
|
||||
throw new Error(`Enemy "${enemy.id}" has no intents`);
|
||||
}
|
||||
return enemy.intents[0];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -191,6 +167,7 @@ function buildEffectTable(buffs: readonly [EffectData, number][]): EffectTable {
|
|||
*/
|
||||
function createPlayerEntity(runState: RunState, deck: ReturnType<typeof generateDeckFromInventory>): PlayerEntity {
|
||||
return {
|
||||
id: "player",
|
||||
hp: runState.player.currentHp,
|
||||
maxHp: runState.player.maxHp,
|
||||
isAlive: runState.player.currentHp > 0,
|
||||
|
|
@ -224,13 +201,13 @@ export function isCombatEncounter(runState: RunState): boolean {
|
|||
* Starts the encounter at the current node.
|
||||
* Returns the constructed CombatState, or null if no combat encounter.
|
||||
*/
|
||||
export function startEncounter(runState: RunState, intentPool: IntentData[] = []): CombatState | null {
|
||||
export function startEncounter(runState: RunState): CombatState | null {
|
||||
const encounter = getCurrentEncounterData(runState);
|
||||
if (!encounter || encounter.enemies.length === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return buildCombatState(encounter, runState, intentPool);
|
||||
return buildCombatState(encounter, runState);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
Loading…
Reference in New Issue