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
-39
View File
@@ -1,39 +0,0 @@
import type { ActivityLogEntry } from '@/lib/game/types';
import { DebugName } from '@/components/game/debug/debug-context';
interface ActivityLogProps {
activityLog: ActivityLogEntry[];
maxEntries?: number;
}
export function ActivityLog({ activityLog, maxEntries = 20 }: ActivityLogProps) {
const entries = activityLog.slice(0, maxEntries);
if (entries.length === 0) {
return (
<DebugName name="ActivityLog">
<div className="text-sm text-gray-500 italic p-2">
No activity yet.
</div>
</DebugName>
);
}
return (
<DebugName name="ActivityLog">
<div className="space-y-1 max-h-64 overflow-y-auto">
{entries.map((entry) => (
<div
key={entry.id}
className="text-xs text-gray-300 border-b border-gray-700 pb-1 last:border-0"
>
<span className="text-gray-500 mr-1">
[{entry.eventType}]
</span>
{entry.message}
</div>
))}
</div>
</DebugName>
);
}
+48 -2
View File
@@ -1,12 +1,14 @@
'use client';
import { useAttunementStore } from '@/lib/game/stores';
import { useAttunementStore, usePrestigeStore } from '@/lib/game/stores';
import { ATTUNEMENTS_DEF, ATTUNEMENT_SLOT_NAMES, getAttunementXPForLevel, MAX_ATTUNEMENT_LEVEL } from '@/lib/game/data/attunements';
import type { AttunementDef, AttunementState } from '@/lib/game/types';
import { Card, CardContent } from '@/components/ui/card';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { DebugName } from '@/components/game/debug/debug-context';
import { fmt } from '@/lib/game/stores';
import { Unlock } from 'lucide-react';
// ─── Helpers ─────────────────────────────────────────────────────────────────
@@ -25,14 +27,31 @@ function isAttunementUnlocked(id: string, attunements: Record<string, Attunement
return id in attunements;
}
/**
* Check whether an attunement's unlock condition is met.
* Evaluates the condition based on current game state.
*/
function isUnlockConditionMet(id: string, defeatedGuardians: number[]): boolean {
switch (id) {
case 'invoker':
return defeatedGuardians.includes(10);
case 'fabricator':
return false; // No specific gating condition implemented
default:
return false;
}
}
// ─── Attunement Card ─────────────────────────────────────────────────────────
interface AttunementCardProps {
def: AttunementDef;
state?: AttunementState;
canUnlock?: boolean;
onUnlock?: (id: string) => void;
}
function AttunementCard({ def, state }: AttunementCardProps) {
function AttunementCard({ def, state, canUnlock, onUnlock }: AttunementCardProps) {
const unlocked = !!state;
const isStarting = def.unlocked === true;
const xpProgress = state ? getXpProgress(state) : 0;
@@ -143,6 +162,21 @@ function AttunementCard({ def, state }: AttunementCardProps) {
</div>
)}
{/* Unlock button (locked + condition met) */}
{!unlocked && canUnlock && onUnlock && (
<div className="pt-2" style={{ borderTop: `1px solid ${color}15` }}>
<Button
size="sm"
variant="outline"
className="w-full text-xs"
style={{ borderColor: `${color}66`, color }}
onClick={() => onUnlock(def.id)}
>
<Unlock className="w-3 h-3 mr-1" /> Unlock {def.name}
</Button>
</div>
)}
{/* Details grid */}
<div
className="grid grid-cols-2 gap-2 text-xs pt-3"
@@ -231,10 +265,20 @@ function AttunementCard({ def, state }: AttunementCardProps) {
export function AttunementsTab() {
const attunements = useAttunementStore((s) => s.attunements);
const unlockAttunement = useAttunementStore((s) => s.unlockAttunement);
const defeatedGuardians = usePrestigeStore((s) => s.defeatedGuardians);
const allDefs = Object.values(ATTUNEMENTS_DEF);
const unlockedCount = allDefs.filter((d) => isAttunementUnlocked(d.id, attunements)).length;
const handleUnlock = (id: string) => {
const prestigeState = usePrestigeStore.getState();
const success = unlockAttunement(id, prestigeState.defeatedGuardians);
if (!success) {
console.warn(`Failed to unlock attunement: ${id}`);
}
};
return (
<DebugName name="AttunementsTab">
<div className="space-y-4">
@@ -268,6 +312,8 @@ export function AttunementsTab() {
key={def.id}
def={def}
state={attunements[def.id]}
canUnlock={isUnlockConditionMet(def.id, defeatedGuardians)}
onUnlock={handleUnlock}
/>
))}
</div>