import type { Vec2 } from '../core/types'; import { EventBus } from '../core/EventBus'; import React from 'react'; /** Dialogue node types */ export type DialogueNodeType = 'start' | 'text' | 'choice' | 'branch' | 'set_variable' | 'check_variable' | 'event' | 'random' | 'end'; /** Variable types supported in dialogues */ export type DialogueVarType = 'boolean' | 'number' | 'string'; /** Comparison operators for conditions */ export type ComparisonOp = 'eq' | 'neq' | 'gt' | 'lt' | 'gte' | 'lte' | 'contains' | 'startsWith' | 'endsWith'; /** Character emotion types */ export type EmotionType = 'neutral' | 'happy' | 'sad' | 'angry' | 'surprised' | 'scared' | 'disgusted' | 'confused' | 'thoughtful' | 'excited' | 'tired' | 'love' | 'custom'; /** Text effect types */ export type TextEffectType = 'none' | 'typewriter' | 'shake' | 'wave' | 'rainbow' | 'fade'; export interface DialogueVariable { id: string; name: string; type: DialogueVarType; defaultValue: boolean | number | string; description?: string; persistent?: boolean; scope: 'conversation' | 'global'; } export interface VariableCondition { variableId: string; operator: ComparisonOp; value: boolean | number | string; } export interface DialogueCharacter { id: string; name: string; displayName: string; /** Portrait images per emotion */ portraits: Record; voiceId?: string; defaultEmotion: EmotionType; textColor?: string; nameColor?: string; textSpeed?: number; } export interface DialogueNodeBase { id: string; type: DialogueNodeType; position: Vec2; comment?: string; tags?: string[]; } export interface StartNode extends DialogueNodeBase { type: 'start'; label: string; nextNode: string | null; } export interface TextNode extends DialogueNodeBase { type: 'text'; characterId: string; text: string; emotion?: EmotionType; textEffect?: TextEffectType; audioClip?: string; duration?: number; nextNode: string | null; } export interface ChoiceOption { id: string; text: string; nextNode: string | null; conditions?: VariableCondition[]; /** Variables to set when this choice is selected */ setVariables?: { variableId: string; value: boolean | number | string; }[]; disabled?: boolean; tooltip?: string; } export interface ChoiceNode extends DialogueNodeBase { type: 'choice'; characterId?: string; prompt?: string; options: ChoiceOption[]; timeout?: number; defaultOption?: string; } export interface BranchNode extends DialogueNodeBase { type: 'branch'; conditions: VariableCondition[]; /** AND or OR logic for multiple conditions */ logic: 'and' | 'or'; trueNode: string | null; falseNode: string | null; } export interface SetVariableNode extends DialogueNodeBase { type: 'set_variable'; variableId: string; operation: 'set' | 'add' | 'subtract' | 'multiply' | 'toggle' | 'append'; value: boolean | number | string; nextNode: string | null; } export interface CheckVariableNode extends DialogueNodeBase { type: 'check_variable'; conditions: VariableCondition[]; logic: 'and' | 'or'; trueNode: string | null; falseNode: string | null; } export interface EventNode extends DialogueNodeBase { type: 'event'; eventType: string; eventData: Record; nextNode: string | null; } export interface RandomNode extends DialogueNodeBase { type: 'random'; outputs: { id: string; weight: number; nextNode: string | null; }[]; } export interface EndNode extends DialogueNodeBase { type: 'end'; result?: 'success' | 'failure' | 'neutral'; setVariables?: { variableId: string; value: boolean | number | string; }[]; } export type DialogueNode = StartNode | TextNode | ChoiceNode | BranchNode | SetVariableNode | CheckVariableNode | EventNode | RandomNode | EndNode; export interface DialogueTree { id: string; name: string; description?: string; version: string; characters: DialogueCharacter[]; variables: DialogueVariable[]; nodes: DialogueNode[]; startNodeId: string; metadata: { author?: string; created: string; modified: string; tags?: string[]; locale: string; }; } export interface DialogueState { treeId: string; currentNodeId: string | null; variables: Record; history: string[]; choicesMade: { nodeId: string; optionId: string; timestamp: number; }[]; startTime: number; isActive: boolean; isPaused: boolean; } export type DialogueEventType = 'dialogue:started' | 'dialogue:ended' | 'dialogue:node-entered' | 'dialogue:text-displayed' | 'dialogue:choice-selected' | 'dialogue:variable-changed' | 'dialogue:event-triggered' | 'dialogue:paused' | 'dialogue:resumed'; export interface DialogueEvent { type: DialogueEventType; treeId: string; nodeId?: string; data?: unknown; timestamp: number; } export declare class DialogueEngine { private trees; private globalVariables; private currentState; private events; private onTextCallback?; private onChoiceCallback?; private onEndCallback?; constructor(events?: EventBus); registerTree(tree: DialogueTree): void; unregisterTree(treeId: string): void; getTree(treeId: string): DialogueTree | undefined; getAllTrees(): DialogueTree[]; setGlobalVariable(name: string, value: boolean | number | string): void; getGlobalVariable(name: string): boolean | number | string | undefined; getVariable(variableId: string): boolean | number | string | undefined; private setVariable; startDialogue(treeId: string, startLabel?: string): boolean; endDialogue(): void; pauseDialogue(): void; resumeDialogue(): void; getState(): DialogueState | null; isActive(): boolean; private goToNode; private processNode; private processTextNode; private processChoiceNode; private processBranchNode; private processSetVariableNode; private processEventNode; private processRandomNode; private processEndNode; selectChoice(optionId: string): boolean; /** Advance to next node (for text nodes) */ advance(): boolean; private evaluateConditions; private evaluateCondition; onText(callback: (node: TextNode, character: DialogueCharacter) => void): void; onChoice(callback: (node: ChoiceNode, options: ChoiceOption[]) => void): void; onEnd(callback: (node: EndNode, state: DialogueState) => void): void; private emitEvent; subscribe(eventType: DialogueEventType, handler: (event: DialogueEvent) => void): () => void; } export declare class DialogueTreeBuilder { private tree; private nodeCounter; constructor(id: string, name: string); private generateId; description(desc: string): this; author(author: string): this; locale(locale: string): this; tags(tags: string[]): this; addCharacter(character: DialogueCharacter): this; addVariable(variable: DialogueVariable): this; boolVar(id: string, name: string, defaultValue?: boolean, scope?: 'conversation' | 'global'): this; numVar(id: string, name: string, defaultValue?: number, scope?: 'conversation' | 'global'): this; strVar(id: string, name: string, defaultValue?: string, scope?: 'conversation' | 'global'): this; addStart(label: string, nextNode?: string | null, position?: Vec2): this; addText(characterId: string, text: string, nextNode?: string | null, options?: Partial>): this; addChoice(options: ChoiceOption[], settings?: Partial>): this; addBranch(conditions: VariableCondition[], trueNode: string | null, falseNode: string | null, logic?: 'and' | 'or', position?: Vec2): this; addSetVariable(variableId: string, operation: SetVariableNode['operation'], value: boolean | number | string, nextNode?: string | null, position?: Vec2): this; addEvent(eventType: string, eventData: Record, nextNode?: string | null, position?: Vec2): this; addRandom(outputs: { weight: number; nextNode: string | null; }[], position?: Vec2): this; addEnd(result?: EndNode['result'], setVariables?: EndNode['setVariables'], position?: Vec2): this; build(): DialogueTree; /** Get the ID of the last added node */ lastNodeId(): string; /** Get node by index (1-based for readability) */ nodeId(index: number): string; } export interface DialogueBoxProps { /** The text to display */ text: string; /** Character name */ characterName?: string; /** Character portrait URL */ portrait?: string; /** Emotion for styling */ emotion?: EmotionType; /** Text effect */ textEffect?: TextEffectType; /** Characters per second for typewriter effect */ textSpeed?: number; /** Called when text fully displayed */ onComplete?: () => void; /** Called when user clicks to advance */ onAdvance?: () => void; /** Custom styles */ className?: string; style?: React.CSSProperties; } /** * React hook for typewriter text effect */ export declare function useTypewriter(text: string, speed?: number, enabled?: boolean): { displayedText: string; isComplete: boolean; skip: () => void; }; /** * DialogueBox component for displaying dialogue text */ export declare const DialogueBox: React.FC; export interface ChoiceListProps { /** Available choices */ options: ChoiceOption[]; /** Prompt text */ prompt?: string; /** Called when a choice is selected */ onSelect: (optionId: string) => void; /** Timeout in ms (optional) */ timeout?: number; /** Custom styles */ className?: string; style?: React.CSSProperties; } /** * ChoiceList component for displaying dialogue choices */ export declare const ChoiceList: React.FC; /** * Serialize dialogue tree to JSON string */ export declare function serializeDialogueTree(tree: DialogueTree): string; /** * Deserialize dialogue tree from JSON string */ export declare function deserializeDialogueTree(json: string): DialogueTree; /** * Validate dialogue tree structure */ export declare function validateDialogueTree(tree: unknown): DialogueTree; /** * Find unreachable nodes in dialogue tree */ export declare function findUnreachableNodes(tree: DialogueTree): string[]; export interface DialogueLocalization { treeId: string; locale: string; texts: Record; characterNames: Record; } /** * Extract all translatable strings from a dialogue tree */ export declare function extractTranslatableStrings(tree: DialogueTree): { nodeTexts: Record; characterNames: Record; }; /** * Apply localization to a dialogue tree (creates a copy) */ export declare function applyLocalization(tree: DialogueTree, localization: DialogueLocalization): DialogueTree; export declare const DEFAULT_TEXT_SPEED = 50; export declare const EMOTION_COLORS: Record; export declare function createEmptyDialogueTree(id: string, name: string): DialogueTree;