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,7 @@ import { getGuardianForFloor } from '../../data/guardian-encounters';
|
||||
import { hasSpecial, SPECIAL_EFFECTS } from '../../effects/special-effects';
|
||||
import type { ComputedEffects } from '../../effects/upgrade-effects.types';
|
||||
import type { EnemyState } from '../../types';
|
||||
import { countdownGolemRoomDuration } from '../golem-combat-actions';
|
||||
|
||||
// ─── Enemy Defense Context ────────────────────────────────────────────────────
|
||||
// Snapshot of the current tick's enemy defense state, captured once per tick
|
||||
@@ -55,6 +56,19 @@ export function buildCombatCallbacks(params: BuildCombatCallbacksParams) {
|
||||
params.addLog('Floor ' + floor + ' cleared!');
|
||||
}
|
||||
useCombatStore.setState({ guardianShield: 0, guardianShieldMax: 0, guardianBarrier: 0, guardianBarrierMax: 0 });
|
||||
|
||||
// ── Golem room-duration countdown (spec §9.6) ──────────────────────
|
||||
const cs = useCombatStore.getState();
|
||||
const activeGolems = cs.golemancy?.activeGolems ?? [];
|
||||
if (activeGolems.length > 0) {
|
||||
const result = countdownGolemRoomDuration(activeGolems);
|
||||
if (result.logMessages.length > 0) {
|
||||
result.logMessages.forEach((msg) => params.addLog(msg));
|
||||
}
|
||||
useCombatStore.setState({
|
||||
golemancy: { ...cs.golemancy, activeGolems: result.remainingGolems },
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
/** Mage barrier recharge rate (spec §5.2): 5% per tick */
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
// ─── Golem Combat Pipeline ─────────────────────────────────────────────────────
|
||||
// Extracts golem combat setup from gameStore.ts tick()
|
||||
// to keep the coordinator under the 400-line file limit.
|
||||
|
||||
import { useCombatStore } from '../combatStore';
|
||||
import { useManaStore } from '../manaStore';
|
||||
import { processGolemRoomDuration } from '../golem-combat-actions';
|
||||
import type { ActiveGolem } from '../../types';
|
||||
|
||||
export interface GolemCombatContext {
|
||||
addLog: (msg: string) => void;
|
||||
ctx: {
|
||||
combat: {
|
||||
currentFloor: number;
|
||||
currentRoom: { roomType: string; unknown: Array<{ name: string }> };
|
||||
};
|
||||
prestige: { signedPacts: number[] };
|
||||
};
|
||||
rawMana: number;
|
||||
elements: Record<string, { current: number; max: number; unlocked: boolean }>;
|
||||
maxMana: number;
|
||||
}
|
||||
|
||||
export interface GolemCombatResult {
|
||||
rawMana: number;
|
||||
elements: Record<string, { current: number; max: number; unlocked: boolean }>;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the golem combat pipeline for the current tick.
|
||||
* Returns golem state needed by processCombatTick.
|
||||
*/
|
||||
export function buildGolemCombatPipeline(_addLog: (msg: string) => void): {
|
||||
activeGolems: ActiveGolem[];
|
||||
golemApplyDamageToRoom: (dmg: number) => { floorHP: number; floorMaxHP: number; roomCleared: boolean };
|
||||
} {
|
||||
const activeGolems = useCombatStore.getState().golemancy?.activeGolems ?? [];
|
||||
|
||||
const golemApplyDamageToRoom = (dmg: number) => {
|
||||
const cs = useCombatStore.getState();
|
||||
if (dmg > 0) {
|
||||
const newFloorHP = Math.max(0, cs.floorHP - dmg);
|
||||
useCombatStore.setState({ floorHP: newFloorHP });
|
||||
}
|
||||
const roomCleared = useCombatStore.getState().floorHP <= 0;
|
||||
return { floorHP: cs.floorHP, floorMaxHP: cs.floorMaxHP, roomCleared };
|
||||
};
|
||||
|
||||
return { activeGolems, golemApplyDamageToRoom };
|
||||
}
|
||||
Reference in New Issue
Block a user