fix: complete golemancy component-based redesign cleanup
Build and Publish Mana Loop Docker Image / build-and-publish (push) Successful in 1m18s

- Fix summonGolemsForRoom to use golemLoadout instead of removed enabledGolems
- Fix discBonus hardcoded to 0 in golem-combat.ts pipeline (now computed from discipline effects)
- Remove deprecated types: SummonedGolem, ActiveGolem, GolemDef
- Remove legacy GolemancyState fields: enabledGolems, summonedGolems, legacyActiveGolems
- Remove orphaned store actions: toggleGolem, setEnabledGolems
- Delete orphaned legacy data files: base-golems.ts, elemental-golems.ts, hybrid-golems.ts
- Update GolemDebugSection to use new golemLoadout system
- Update golemancy-spec.md §17 to reflect all features as complete
- Update all test files to match new type shapes
- All 958 tests passing
This commit is contained in:
2026-06-06 18:37:09 +02:00
parent bd15df85ff
commit 9d4b3f3c69
28 changed files with 89 additions and 443 deletions
+8 -9
View File
@@ -154,17 +154,16 @@ describe('ElementDebugSection store interactions', () => {
});
describe('GolemDebugSection store interactions', () => {
it('setEnabledGolems is callable with all golem IDs', () => {
const mockSet = vi.fn();
const allIds = ['stoneGolem', 'fireGolem'];
mockSet(allIds);
expect(mockSet).toHaveBeenCalledWith(allIds);
it('addGolemDesign is callable', () => {
const mockAdd = vi.fn();
mockAdd({ id: 'test', name: 'Test', coreId: 'basic', frameId: 'earth', mindCircuitId: 'simple', enchantmentIds: [], selectedManaTypes: [], selectedSpells: [] });
expect(mockAdd).toHaveBeenCalled();
});
it('setEnabledGolems is callable with empty array to disable all', () => {
const mockSet = vi.fn();
mockSet([]);
expect(mockSet).toHaveBeenCalledWith([]);
it('toggleGolemLoadoutEntry is callable', () => {
const mockToggle = vi.fn();
mockToggle('test-design');
expect(mockToggle).toHaveBeenCalledWith('test-design');
});
});
@@ -107,8 +107,10 @@ function EnchantmentCard({ enchant }: { enchant: GolemEnchantmentDefinition }) {
}
export function GolemDebugSection() {
const setEnabledGolems = useCombatStore((s) => s.setEnabledGolems);
const enabledGolems = useCombatStore((s) => s.golemancy?.enabledGolems) ?? [];
const golemLoadout = useCombatStore((s) => s.golemancy?.golemLoadout) ?? [];
const golemDesigns = useCombatStore((s) => s.golemancy?.golemDesigns) ?? {};
const toggleGolemLoadoutEntry = useCombatStore((s) => s.toggleGolemLoadoutEntry);
const addGolemDesign = useCombatStore((s) => s.addGolemDesign);
const allComponentIds = [
...ALL_CORES.map((c) => c.id),
@@ -117,18 +119,36 @@ export function GolemDebugSection() {
...ALL_GOLEM_ENCHANTMENTS.map((e) => e.id),
];
const handleEnableAll = () => setEnabledGolems(allComponentIds);
const handleCreateTestDesigns = () => {
// Create a test design from the first core/frame/circuit
const core = ALL_CORES[0];
const frame = ALL_FRAMES[0];
const circuit = ALL_MIND_CIRCUITS[0];
if (!core || !frame || !circuit) return;
const handleDisableAll = () => setEnabledGolems([]);
addGolemDesign({
id: `test-design-${Date.now()}`,
name: `Test ${core.name} ${frame.name}`,
coreId: core.id,
frameId: frame.id,
mindCircuitId: circuit.id,
enchantmentIds: [],
selectedManaTypes: core.manaTypes.slice(0, 1),
selectedSpells: [],
});
};
const handleToggleComponent = (id: string) => {
if (enabledGolems.includes(id)) {
setEnabledGolems(enabledGolems.filter((x) => x !== id));
} else {
setEnabledGolems([...enabledGolems, id]);
const handleClearLoadout = () => {
// Disable all loadout entries
for (const entry of golemLoadout) {
if (entry.enabled) {
toggleGolemLoadoutEntry(entry.designId);
}
}
};
const enabledCount = golemLoadout.filter((e) => e.enabled).length;
return (
<DebugName name="GolemDebugSection">
<Card className="bg-gray-900/80 border-gray-700">
@@ -140,15 +160,15 @@ export function GolemDebugSection() {
</CardHeader>
<CardContent className="space-y-4">
<div className="flex gap-2 flex-wrap">
<Button size="sm" variant="outline" onClick={handleEnableAll}>
Enable All Components
<Button size="sm" variant="outline" onClick={handleCreateTestDesigns}>
Create Test Design
</Button>
<Button size="sm" variant="outline" onClick={handleDisableAll}>
Disable All
<Button size="sm" variant="outline" onClick={handleClearLoadout}>
Disable All Loadout
</Button>
</div>
<div className="text-xs text-gray-400">
Enabled: {enabledGolems.length} / {allComponentIds.length}
Designs: {Object.keys(golemDesigns).length} · Loadout: {enabledCount} / {golemLoadout.length} enabled
</div>
{/* ─── Cores ─────────────────────────────────────────────── */}
@@ -160,14 +180,6 @@ export function GolemDebugSection() {
{ALL_CORES.map((core) => (
<div key={core.id} className="relative">
<CoreCard core={core} />
<Button
size="sm"
variant={enabledGolems.includes(core.id) ? 'default' : 'outline'}
className="absolute top-1 right-1 h-6 px-2 text-[10px]"
onClick={() => handleToggleComponent(core.id)}
>
{enabledGolems.includes(core.id) ? 'On' : 'Off'}
</Button>
</div>
))}
</div>
@@ -182,14 +194,6 @@ export function GolemDebugSection() {
{ALL_FRAMES.map((frame) => (
<div key={frame.id} className="relative">
<FrameCard frame={frame} />
<Button
size="sm"
variant={enabledGolems.includes(frame.id) ? 'default' : 'outline'}
className="absolute top-1 right-1 h-6 px-2 text-[10px]"
onClick={() => handleToggleComponent(frame.id)}
>
{enabledGolems.includes(frame.id) ? 'On' : 'Off'}
</Button>
</div>
))}
</div>
@@ -204,14 +208,6 @@ export function GolemDebugSection() {
{ALL_MIND_CIRCUITS.map((circuit) => (
<div key={circuit.id} className="relative">
<MindCircuitCard circuit={circuit} />
<Button
size="sm"
variant={enabledGolems.includes(circuit.id) ? 'default' : 'outline'}
className="absolute top-1 right-1 h-6 px-2 text-[10px]"
onClick={() => handleToggleComponent(circuit.id)}
>
{enabledGolems.includes(circuit.id) ? 'On' : 'Off'}
</Button>
</div>
))}
</div>
@@ -226,14 +222,6 @@ export function GolemDebugSection() {
{ALL_GOLEM_ENCHANTMENTS.map((enchant) => (
<div key={enchant.id} className="relative">
<EnchantmentCard enchant={enchant} />
<Button
size="sm"
variant={enabledGolems.includes(enchant.id) ? 'default' : 'outline'}
className="absolute top-1 right-1 h-6 px-2 text-[10px]"
onClick={() => handleToggleComponent(enchant.id)}
>
{enabledGolems.includes(enchant.id) ? 'On' : 'Off'}
</Button>
</div>
))}
</div>
@@ -242,10 +242,16 @@ describe('canAffordGolemDesign', () => {
// ─── Test: Combat store golemancy state ───────────────────────────────────────
describe('Combat store golemancy', () => {
it('toggleGolem is a function', async () => {
it('toggleGolemLoadoutEntry is a function', async () => {
const { useCombatStore } = await import('@/lib/game/stores/combatStore');
const state = useCombatStore.getState();
expect(typeof state.toggleGolem).toBe('function');
expect(typeof state.toggleGolemLoadoutEntry).toBe('function');
});
it('addGolemDesign is a function', async () => {
const { useCombatStore } = await import('@/lib/game/stores/combatStore');
const state = useCombatStore.getState();
expect(typeof state.addGolemDesign).toBe('function');
});
it('golemancy state has correct shape', async () => {