Field notebook: capture NPC lines, tear pages onto the board
A dialogue line gains a "✎ Note this" capture that saves it to a per-playthrough notebook (migration 035 + notebook endpoints). The inventory notebook lists captured pages in a handwriting font (Google "Reenie Beanie") and "✂ Tear to board" drops a page onto the current board as a note exhibit (reusing addNote), then removes the page. Board notes render handwritten too. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+4
-2
@@ -81,7 +81,7 @@ export function CutsceneHost({ componentKey, label, onComplete }: { componentKey
|
||||
|
||||
// Walk a dialogue node's utterance tree: play NPC lines, present player options at a
|
||||
// branch, follow a chosen option to the next line or out through its exit terminal.
|
||||
export function DialoguePlayer({ node, onExit, onAward, inline, startId }: { node: { utterances: RuntimeUtterance[]; rootId: string | null }; onExit: (terminalKey?: string) => void; onAward?: (utteranceId: string) => void; inline?: boolean; startId?: string | null }) {
|
||||
export function DialoguePlayer({ node, onExit, onAward, onCapture, inline, startId }: { node: { utterances: RuntimeUtterance[]; rootId: string | null }; onExit: (terminalKey?: string) => void; onAward?: (utteranceId: string) => void; onCapture?: (text: string, utteranceId: string) => void; inline?: boolean; startId?: string | null }) {
|
||||
const byId = useMemo(() => new Map(node.utterances.map(u => [u.id, u])), [node.utterances])
|
||||
const [currentId, setCurrentId] = useState<string | null>(startId ?? node.rootId)
|
||||
const onAwardRef = useRef(onAward)
|
||||
@@ -149,7 +149,9 @@ export function DialoguePlayer({ node, onExit, onAward, inline, startId }: { nod
|
||||
<div className="dialogue-scrim" aria-hidden />
|
||||
<div className="dialogue-box">
|
||||
<div className="dialogue-panel">
|
||||
<div className="dialogue-speaker"><strong>{current.speaker.name}</strong>{current.speaker.role && <em>{current.speaker.role}</em>}</div>
|
||||
<div className="dialogue-speaker"><strong>{current.speaker.name}</strong>{current.speaker.role && <em>{current.speaker.role}</em>}
|
||||
{onCapture && !inline && current.utterer === 'npc' && done && <button className="dialogue-capture" title="Copy to notebook" onClick={event => { event.stopPropagation(); onCapture(current.text, current.id) }}>✎ Note this</button>}
|
||||
</div>
|
||||
<p className="dialogue-text">{fullText.slice(0, charCount)}<span className="dialogue-caret" aria-hidden>{done ? '' : '▍'}</span></p>
|
||||
{showChoices
|
||||
? <div className="dialogue-choices">{options.map(option => <button key={option.id} onClick={event => { event.stopPropagation(); pick(option) }}>{option.text || '(choice)'}</button>)}</div>
|
||||
|
||||
Reference in New Issue
Block a user