Dialog

Assets/Scripts/Rokojori/Dialog - a standalone dialog engine plus a UI-facing singleton on top of it. See outline/tech/index.page for the design intent and the open assumptions this implementation made.

The Three Layers

DialogProcessor is the engine - it only knows about IDialogDisplay, nothing about UI or DialogManager. DialogManager is the UI-facing singleton - implements IDialogDisplay, and StartDialog() is the only entry point anyone outside this folder should call. DialogPhase (in Simulation/) is a thin wrapper so a dialog can be one step in a turn loop.

Execution Loop

DialogProcessor.Run( start ) repeats current = await current.Run( display ) until current is null. Each DialogBlock decides its own next step; the base class default is simply "return next" (linear flow), and only PlayerChoice / DialogBranch override that to branch.

Block-by-Block Behaviour

DialogLine - calls display.Show(this), awaits it, returns next.
PlayerChoice - calls display.Show(this), reads answer.selectedOptionIndex, runs that option's action if set, returns that option's next.
DialogBranch - no display call. Returns branch if condition.Evaluate() is true, else the inherited next.
DialogList - runs its own blocks in flat order, ignoring each child's own "next" while inside the list, then returns its own next. This is an assumption, not confirmed - see outline/tech "Implementation Status". Practical effect: don't put a PlayerChoice/DialogBranch directly inside a DialogList's blocks, its branch target will be silently discarded.
ReturnBlock - always returns null, ending the whole dialog (even if nested inside a DialogList).
CommentBlock - editor-only, no override, just falls through to next like the default.

Conditions & Actions

GameStateCondition (CompareInt, HasObject, ListCondition) and GameStateAction (SetProperty, ModifyProperty, ActionList) both read/write through GameStateManager.instance - they never touch DialogBlock state directly. HasObject currently checks a GameStateBoolVariable flag since there's no inventory/object system to check membership against yet.

PlayerChoice.options[i].action is not in the original design outline - added to give choices a way to change game state, since Conditions and Actions were described as a pair but no block explicitly triggered an Action.

Testing Without UI

HeadlessDialogDisplay implements IDialogDisplay without any Unity UI - it logs every block it's shown into visitedBlocks and answers PlayerChoice via the chooseOption delegate (defaults to always picking option 0). Drive a dialog with DialogProcessor.Create( new HeadlessDialogDisplay() ).Run( start ) to test branching logic in isolation.

Gotcha

DialogManager.Show() currently throws NotImplementedException - there's no real UI wired up yet (Assets/UI is empty). Use HeadlessDialogDisplay for anything that doesn't need to render.