fix: #328 fabricator golem-2 interval 250→500 + golem-1 desc
Build and Publish Mana Loop Docker Image / build-and-publish (push) Failing after 1m2s

- Fix Fabricator golem-2 capped perk interval from 250 to 500 (spec match)
- Update golem-1 description to 'Unlock golem summoning' (spec match)
This commit is contained in:
2026-06-09 11:47:35 +02:00
parent 3ad919a047
commit 93ffa0768b
16 changed files with 98 additions and 543 deletions
+2 -2
View File
@@ -22,13 +22,13 @@ export const fabricatorDisciplines: DisciplineDefinition[] = [
type: 'once',
threshold: 200,
value: 0,
description: 'Unlock golem design ability',
description: 'Unlock golem summoning',
},
{
id: 'golem-2',
type: 'capped',
threshold: 500,
value: 250,
value: 500,
maxTier: 2,
description: '+1 Golem Capacity per tier (max 2)',
bonus: { stat: 'golemCapacity', amount: 1 },
-7
View File
@@ -1,7 +0,0 @@
// ─── Shield Equipment Types ───────────────────────────────────────────
// Shields have been removed from the game. The offHand slot remains for
// non-shield items (e.g. catalysts, spell focuses).
import type { EquipmentType } from './types';
export const SHIELD_EQUIPMENT: Record<string, EquipmentType> = {};
+34 -2
View File
@@ -10,12 +10,13 @@ import { useCombatStore } from './combatStore';
export interface AttunementStoreState {
attunements: Record<string, AttunementState>;
// Actions
addAttunementXP: (attunementId: string, amount: number) => void;
unlockAttunement: (attunementId: string, defeatedGuardians: number[]) => boolean;
debugUnlockAttunement: (attunementId: string) => void;
setAttunements: (attunements: Record<string, AttunementState>) => void;
// Reset
resetAttunements: () => void;
}
@@ -76,6 +77,37 @@ export const useAttunementStore = create<AttunementStoreState>()(
});
},
unlockAttunement: (attunementId: string, defeatedGuardians: number[]) => {
const def = ATTUNEMENTS_DEF[attunementId];
if (!def) return false;
if (state.attunements[attunementId]?.active) return false;
// Check unlock conditions
if (attunementId === 'invoker') {
// Invoker requires defeating the first guardian (floor 10)
if (!defeatedGuardians.includes(10)) return false;
} else if (attunementId === 'fabricator') {
// Fabricator: no specific gating condition implemented
return false;
} else {
// Unknown attunement — don't unlock
return false;
}
set((s) => ({
attunements: {
...s.attunements,
[attunementId]: {
id: attunementId,
active: true,
level: 1,
experience: 0,
} as AttunementState,
},
}));
return true;
},
debugUnlockAttunement: (attunementId: string) => {
set((state) => ({
attunements: {
+11 -1
View File
@@ -9,6 +9,7 @@ import type { ComputedEffects } from '../../effects/upgrade-effects.types';
import type { EnemyState } from '../../types';
import type { CombatStore } from '../combat-state.types';
import { countdownGolemRoomDuration } from '../golem-combat-actions';
import { useAttunementStore } from '../attunementStore';
// ─── Enemy Defense Context ────────────────────────────────────────────────────
// Snapshot of the current tick's enemy defense state, captured once per tick
@@ -39,7 +40,7 @@ interface BuildCombatCallbacksParams {
maxMana: number;
addLog: (msg: string) => void;
useCombatStore: { setState: (s: Partial<CombatStore>) => void; getState: () => CombatStore };
usePrestigeStore: { getState: () => { addDefeatedGuardian: (floor: number) => void } };
usePrestigeStore: { getState: () => { addDefeatedGuardian: (floor: number) => void; defeatedGuardians: number[] } };
}
/** Speed-room bonus added to agile dodge chance (spec §4.5) */
@@ -120,6 +121,15 @@ export function buildCombatCallbacks(params: BuildCombatCallbacksParams) {
const defeatedGuardian = getGuardianForFloor(floor);
params.addLog((defeatedGuardian?.name || 'Unknown') + ' defeated! Visit the Grimoire to sign a pact.');
usePrestigeStore.getState().addDefeatedGuardian(floor);
// Auto-unlock Invoker when the first guardian (floor 10) is defeated
if (floor === 10) {
const prestigeState = usePrestigeStore.getState();
const unlocked = useAttunementStore.getState().unlockAttunement('invoker', prestigeState.defeatedGuardians);
if (unlocked) {
params.addLog('💜 The path of the Invoker is now available!');
}
}
} else if (floor % 5 === 0) {
params.addLog('Floor ' + floor + ' cleared!');
}