import { useEffect } from 'react'; import { useDialogueStore } from '../../store/dialogueStore'; import { ConditionClause } from '../../types/dialogue'; import { MAIN_CHARACTER } from '../../constants/characters'; import styles from './PlayModeOverlay.module.css'; function evalConditions(clauses: ConditionClause[], flags: Record): boolean { return clauses.every(c => { const actual = flags[c.flag] ?? 0; switch (c.op) { case 'Equals': return actual == c.value; case 'NotEquals': return actual != c.value; case 'GreaterThan': return Number(actual) > Number(c.value); case 'LessThan': return Number(actual) < Number(c.value); } }); } export function PlayModeOverlay() { const { file, selectedDialogueId, playState, advancePlay, setPlayFlag, stopPlay } = useDialogueStore(); const dialogue = file?.dialogues.find(d => d.id === selectedDialogueId); const node = dialogue?.nodes.find(n => n.id === playState?.currentNodeId); // Auto-advance for Condition and SetFlag useEffect(() => { if (!node || !playState) return; if (node.type === 'Condition') { const timer = setTimeout(() => { const passes = evalConditions(node.conditions, playState.flags); advancePlay(passes ? node.trueNext : node.falseNext); }, 300); return () => clearTimeout(timer); } if (node.type === 'SetFlag') { const timer = setTimeout(() => { for (const effect of node.effects) { setPlayFlag(effect.flag, effect.value); } advancePlay(node.next); }, 100); return () => clearTimeout(timer); } }, [node?.id, node?.type]); if (!playState || !node) return null; const portraitPath = node.type === 'Line' || node.type === 'Choice' ? `../${node.portrait}` : null; return (
e.stopPropagation()}>
{node.type === 'Line' && ( <>
{node.speaker} { (e.target as HTMLImageElement).style.display = 'none'; }} /> {node.speaker[0]}
{node.speaker}
{node.text}
{node.next ? ( ) : (
⚠ No next node set
)} )} {node.type === 'Choice' && ( <>
{node.speaker} { (e.target as HTMLImageElement).style.display = 'none'; }} /> {node.speaker[0]}
{node.speaker}
{node.text &&
{node.text}
}
{node.choices.map(choice => ( ))}
)} {node.type === 'Condition' && (
Evaluating condition...
{node.conditions.map((c, i) => ( {c.flag} {c.op} {c.value} ))}
)} {node.type === 'SetFlag' && (
Setting flags...
)} {node.type === 'CutsceneStart' && ( <>
Cutscene: {node.cutsceneId}
)} {node.type === 'End' && (
Dialogue ended.
)}
node: {node.id} {Object.entries(playState.flags).map(([k, v]) => ( {k}={v} ))}
); }