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
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:
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user