feat(golemancy): Phase 1 - Component-based construction system data definitions
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m18s

- Add new golem component types (Core, Frame, MindCircuit, Enchantment)
- Create 4 Core tiers, 7 Frames, 4 Mind Circuits, 8 Enchantments
- Rewrite golem utils for component-based stat computation
- Update GolemancyState with new fields (golemDesigns, golemLoadout, activeGolems)
- Update combat store, actions, and pipelines for new golem system
- Rewrite GolemancyTab with component selection UI
- Update fabricator discipline perks for new system
- Add comprehensive tests for component registries and utilities
- All files under 400 lines, all 743 tests passing
This commit is contained in:
2026-06-06 16:50:26 +02:00
parent c40e4ee940
commit 4b7aa82953
43 changed files with 2763 additions and 944 deletions
+17 -12
View File
@@ -7,10 +7,14 @@ import { getGuardianForFloor } from '../data/guardian-encounters';
import type { CombatStore, CombatState } from './combat-state.types';
import type { SpellState, EnemyState, EquipmentInstance, FloorState } from '../types';
import { applyOnHitEffect, processDoTPhase } from './dot-runtime';
import type { ActiveGolem } from '../types';
import type { ActiveGolem, RuntimeActiveGolem } from '../types';
import { getFloorMaxHP, getFloorElement, getMultiElementBonus, calcDamage, calcMeleeDamage, canAffordSpellCost, deductSpellCost } from '../utils';
import { computeDisciplineEffects } from '../effects/discipline-effects';
import { processGolemMaintenance, processGolemAttacks } from './golem-combat-actions';
import {
processGolemMaintenance,
processGolemAttacks,
processGolemManaRegen,
} from './golem-combat-actions';
import { applyDamageToRoom } from './combat-damage';
// ─── Result Type ───────────────────────────────────────────────────────────────
@@ -22,7 +26,7 @@ function makeDefaultCombatTickResult(
rawMana: number,
elements: Record<string, { current: number; max: number; unlocked: boolean }>,
state: CombatState,
activeGolems: ActiveGolem[],
activeGolems: RuntimeActiveGolem[],
): CombatTickResult {
return {
rawMana,
@@ -52,7 +56,7 @@ export interface CombatTickResult {
maxFloorReached: number;
castProgress: number;
equipmentSpellStates: CombatState['equipmentSpellStates'];
activeGolems: ActiveGolem[];
activeGolems: RuntimeActiveGolem[];
meleeSwordProgress: Record<string, number>;
currentRoom: FloorState;
}
@@ -73,7 +77,7 @@ export function processCombatTick(
modifiedDamage?: number;
},
signedPacts: number[],
golemancyState: { activeGolems: ActiveGolem[] },
golemancyState: { activeGolems: RuntimeActiveGolem[] },
golemApplyDamageToRoom: (dmg: number) => { floorHP: number; floorMaxHP: number; roomCleared: boolean },
applyEnemyDefenses: (
dmg: number,
@@ -94,9 +98,11 @@ export function processCombatTick(
}
try {
// ─── Golem maintenance (spec §9.5) ──────────────────────────────────────
// ─── Golem maintenance (spec §13) ──────────────────────────────────────
const golemDesigns = state.golemancy.golemDesigns || {};
const maintenanceResult = processGolemMaintenance(
golemancyState.activeGolems,
golemDesigns,
rawMana,
elements,
);
@@ -105,6 +111,9 @@ export function processCombatTick(
elements = maintenanceResult.elements;
logMessages.push(...maintenanceResult.logMessages);
// ─── Golem mana regen (spec §12) ───────────────────────────────────────
activeGolems = processGolemManaRegen(activeGolems, golemDesigns);
// Write maintained golems back immediately so tick state stays consistent
set({ golemancy: { ...state.golemancy, activeGolems } });
@@ -289,15 +298,11 @@ export function processCombatTick(
}
}
// ─── Golem attacks (spec §9.4) ───────────────────────────────────────────
// ─── Golem attacks (spec §11) ───────────────────────────────────────────
if (activeGolems.length > 0 && floorHP > 0) {
const golemResult = processGolemAttacks(
activeGolems,
rawMana,
elements,
floorHP,
floorMaxHP,
currentFloor,
golemDesigns,
onDamageDealt,
golemApplyDamageToRoom,
);