feat: implement golemancy combat system (spec §6, §9)
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m19s
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m19s
- Add ActiveGolem interface and activeGolems to GolemancyState - Add maxRoomDuration to all 12 golem definitions - Create golem-combat-actions.ts with pure golem combat logic (summoning, maintenance, attacks, room-duration) - Create golem-combat.ts pipeline for golem combat setup - Wire golem maintenance and attacks into processCombatTick - Wire golem summoning into advanceRoomOrFloor on room entry - Wire golem room-duration countdown into onFloorCleared callback - Update combat-actions tests for new processCombatTick signature - All 921 tests pass, all files under 400-line limit Closes #259
This commit is contained in:
@@ -7,6 +7,8 @@ import { generateSpireFloorState, getRoomsForFloor } from '../utils/spire-utils'
|
||||
import { getGuardianForFloor } from '../data/guardian-encounters';
|
||||
import { usePrestigeStore } from './prestigeStore';
|
||||
import { useDisciplineStore } from './discipline-slice';
|
||||
import { useManaStore } from './manaStore';
|
||||
import { summonGolemsOnRoomEntry } from './golem-combat-actions';
|
||||
import type { FloorState } from '../types';
|
||||
|
||||
type GetFn = () => CombatStore;
|
||||
@@ -78,6 +80,9 @@ export function advanceRoomOrFloor(get: GetFn, set: SetFn): void {
|
||||
});
|
||||
}
|
||||
|
||||
// ── Golem summoning on room entry (spec §9.3) ─────────────────────
|
||||
summonGolemsForRoom(get, set);
|
||||
|
||||
onEnterRoomDescend(get, set);
|
||||
} else {
|
||||
// ── Ascending (spec §4.4) ─────────────────────────────────────────────
|
||||
@@ -116,6 +121,9 @@ export function advanceRoomOrFloor(get: GetFn, set: SetFn): void {
|
||||
});
|
||||
}
|
||||
|
||||
// ── Golem summoning on room entry (spec §9.3) ─────────────────────
|
||||
summonGolemsForRoom(get, set);
|
||||
|
||||
// Handle non-combat rooms on ascent
|
||||
const room = get().currentRoom;
|
||||
if (room.roomType === 'library') {
|
||||
@@ -126,6 +134,39 @@ export function advanceRoomOrFloor(get: GetFn, set: SetFn): void {
|
||||
}
|
||||
}
|
||||
|
||||
// ─── Golem Summoning on Room Entry (spec §9.3) ──────────────────────────────
|
||||
|
||||
function summonGolemsForRoom(get: GetFn, set: SetFn): void {
|
||||
const s = get();
|
||||
const manaState = useManaStore.getState();
|
||||
const enabledGolems = s.golemancy?.enabledGolems ?? [];
|
||||
if (enabledGolems.length === 0) return;
|
||||
|
||||
const currentActiveGolems = s.golemancy?.activeGolems ?? [];
|
||||
const summonResult = summonGolemsOnRoomEntry(
|
||||
enabledGolems,
|
||||
manaState.rawMana,
|
||||
manaState.elements,
|
||||
s.currentFloor,
|
||||
currentActiveGolems,
|
||||
);
|
||||
|
||||
if (summonResult.logMessages.length > 0) {
|
||||
summonResult.logMessages.forEach((msg) => get().addActivityLog('special_effect', msg));
|
||||
}
|
||||
|
||||
// Write summoned golems back to combat store
|
||||
set({
|
||||
golemancy: { ...s.golemancy, activeGolems: summonResult.activeGolems },
|
||||
});
|
||||
|
||||
// Deduct summon costs from mana store
|
||||
useManaStore.setState({
|
||||
rawMana: summonResult.rawMana,
|
||||
elements: summonResult.elements,
|
||||
});
|
||||
}
|
||||
|
||||
// ─── onEnterRoomDescend (climbing spec §4.7) ──────────────────────────────────
|
||||
|
||||
export function onEnterRoomDescend(get: GetFn, set: SetFn): void {
|
||||
@@ -240,6 +281,7 @@ export function createEnterSpireMode(get: GetFn, set: SetFn, generateFloorState:
|
||||
roomResetState: {},
|
||||
descentPeak: null,
|
||||
isDescentComplete: false,
|
||||
golemancy: { enabledGolems: [], summonedGolems: [], activeGolems: [], lastSummonFloor: 0 },
|
||||
});
|
||||
|
||||
get().addActivityLog('floor_transition',
|
||||
|
||||
Reference in New Issue
Block a user