// Detective's checklist: the "what do I do next" rail. Four objectives derived // entirely from game state; the ACCUSE step pulses when the player is ready. import { useState } from 'preact/hooks' import { HOT_SUSPICION, useGame } from '../store' import { Btn } from './components' function useObjectives() { const g = useGame() const c = g.case const questioned = c.suspects.filter((s) => (g.state.interrogations[s.id] || []).length > 1).length const presented = Object.values(g.state.usedEv).some((l) => l.length > 0) const crackedAny = Object.values(g.state.cracked).some(Boolean) const hot = Object.values(g.state.suspicion).some((v) => v >= HOT_SUSPICION) const ready = (questioned >= c.suspects.length && presented && crackedAny) || hot return { g, total: c.suspects.length, questioned, presented, crackedAny, ready } } function Step({ done, label }: { done: boolean; label: string }) { return (
{done ? '■' : '□'} {label}
) } export function Checklist({ slim = false }: { slim?: boolean }) { const { g, total, questioned, presented, crackedAny, ready } = useObjectives() const doneCount = (questioned >= total ? 1 : 0) + (presented ? 1 : 0) + (crackedAny ? 1 : 0) const [open, setOpen] = useState(questioned === 0) // collapse once the player gets going const steps = ( <> = total} label={`QUESTION EVERY SUSPECT ${questioned}/${total}`} /> g.nav('accuse')} > {ready ? '▸ MAKE THE ACCUSATION' : 'Accuse ▸'} ) if (!slim) return
{steps}
return (
{open &&
{steps}
} {!open && ready && ( g.nav('accuse')}>▸ ACCUSE )}
) }