Novella in Divooka

The Divooka.Novella package makes every Novella concept a node, and the nodes compose in all four kinds of graph (see Graph Contexts):

Graph What it does with Novella
Routine A procedure that creates a game, configures it, loads its content and runs it.
Events A game written as a class: the graph's base type is Novella Application, and it implements the game's callbacks.
Function Describes a game as data: sequences, labels, a story, a Game Definition.
Flows Calls such a function and previews what it returns.

The procedural graphs are the foundation: a game runs because a graph creates and starts it. The functional graphs are a convenient way to write and preview a story, and their result is handed to a procedural graph to run for real. Installation says which distributions include the package.

The Novella toolbox

Everything is in one toolbox, Novella, with a category per type. Node names below are the names the palette shows.

Novella Game

The game itself, for procedural graphs. Every node but the two constructors takes the game as its receiver (wired in a Routine graph, implicit in an Events graph).

Node What it does
Make Novella Game A game with a title, width and height.
Make Novella Game From Definition A game from a Game Definition built by a functional graph.
Set Resolution, Set Title The resolution everything is laid out at, and the title.
Set Config, Set Theme A configuration or theme setting, written as a script would write it; it holds over the scripts' own define of the same key.
Add Library Assets The files embedded in this document's library. The library input is supplied by the document; it needs no wire.
Add Asset Folder, Add Asset A folder on disk, or one file from bytes.
Load Script, Load Script File, Load Scripts From Assets Script text, a script file, or every .novella file among the assets (optionally under a folder).
Add Story A story built by the functional nodes.
Define Character, Define Image, Set Default Definitions without a script.
Register Command Binds a run command name to a function with no inputs and no outputs (see Function Reference).
Validate The lint: one line per problem.
Run Opens the game in a window and returns when the player quits.

The same category holds the live script nodes, which play immediately while a live script runs (see Events graphs): Say, Narrate, Show, Scene, Hide, With, Pause, Play, Stop, Menu (returns the chosen index), Input (returns the text), Call Label, Notify, Achieve, Set Variable, Get Variable, Get Number and Random Integer. Random Integer draws from the story's own generator, so rolling back and choosing again draws the same number. Two more serve the Command event: Set Result answers the command being handled, and Translate Text puts text through the story's string translations.

Story Writing

Pure nodes that build a Sequence: each takes a sequence and returns a new one with one more statement, so a chain reads top to bottom like a script.

Node Statement
Start Sequence An empty sequence to build on.
Say, Narrate A line of dialogue (character id, text, optional image attributes), or narration.
Show, Scene, Hide, With Stage changes, with positions (left, right, a defined transform) and transitions (dissolve, fade(1.0)).
Pause A click, or some seconds.
Play Music, Play Sound, Play, Stop Audio on the music channel, the sound channel, or any channel.
Menu A caption and two to four Choice values, each carrying the sequence that follows it.
If A condition expression, the sequence when it holds, and an optional sequence when it does not.
Set An assignment or expression, as after $: affection += 1.
Jump, Call, Return Flow between labels.
Input, Notify, Achieve, Movie, Voice, Window The matching statements.
Run Command A run command with comma-separated argument expressions.
Script Any statements written as script, for what the other nodes do not cover.
Concatenate One sequence followed by another.
Sequence To Script The sequence as script text, to read what a chain has written.

Choice

Make Choice builds a menu choice from its text, the Sequence that follows it, and an optional condition such as affection > 2; choices feed the Menu node.

Story

Node What it does
Make Label A label from a name and a sequence; the game starts at start.
Start Story An empty story.
Add Label, Add Character, Add Image, Add Default A story with one more label (replacing one of the same name), character, image or variable default.
Story From Script A story read from script text.
Story From Library A story read from a script file in the document's library.
Combine Stories Two stories as one.
Story To Script, Label Names The story as script text, and its labels' names.
Check Story Checks a story on its own: undefined labels, characters, transforms and transitions.

Characters

Make Character makes a character from an id, a display name, a name colour, an image tag, and whether it uses a side image or speaks on the NVL page. Style Character returns a copy with a different text colour, font, or quotation marks.

Game Definition

Node What it does
Make Game Definition A whole game as data: a title, a story, a width and a height.
With Config, With Theme A copy with one setting changed, which holds over the story's own define of the same key.
With Library Assets A copy that reads files from the document's library, optionally also loading the library's scripts into the story.
With Asset Folder A copy that reads files from a folder.
With Story A copy with another story's content added.
Check Game The lint, with the story checked against the files.
Run Game Definition Runs a definition in a window: the procedural end of a functional description.

The functional nodes return new values and never change their inputs, because a dataflow graph caches values and may hand one to two branches.

Routine graphs

A Routine graph is the C# program as nodes. On its execution path:

  1. Make Novella Game: title The Red Thread, width 1920, height 1080.
  2. Add Library Assets: the game's images, sounds, fonts and scripts, embedded in the document.
  3. Load Scripts From Assets: folder scripts.
  4. Set Config: autosave_slots, 8.
  5. Run.

Run the graph and the game opens in a window. Validate in place of Run, followed by a print of its result, is the lint.

Register Command binds a run command to a function with no inputs and no result, which suits commands that only do something, such as writing a log or opening a web page. A command that takes arguments or answers with a value for _return, like The Red Thread's run fortune, is written as the Command event of an Events graph.

Events graphs

In an Events graph, a game is a class. Set the graph's base type to Novella Application (a Novella Game) and the game's callbacks become events the graph can implement, while every Novella Game node acts on the graph's own game without a receiver wired:

Event When it runs
Setup Once, before the window opens: settings, assets, scripts, definitions.
Script If implemented, starting a game runs it as a live script instead of the story's start label.
Command For a run command nobody registered: it receives the name and the arguments as text and returns nothing; it answers with Set Result, which the story reads as _return (none if it sets nothing).
Label Entered Whenever the story enters a label.
Game Ended When a story ends, before the main menu returns.

Only the events a graph actually implements take effect, so leaving Script out keeps the story's labels in charge and leaving Command out makes an unknown command an error.

The Red Thread's document answers its story's run fortune this way:

Command → Set Result, fed by Translate Text of one slip from an array of fortunes, the slip picked by Random Integer from 0 to the last index

A Setup that loads scripts from the document's library is a complete game:

Setup → Set Resolution (1920, 1080) → Add Library Assets → Load Scripts From Assets (scripts)

To run it, run the graph; the Novella framework that the package registers for Novella Application opens the window. Plugins > Frameworks > Novella > Run Novella Game does the same from the menu, for the document's entry graph.

Live scripts as nodes

Implementing Script makes the event's execution path the story. Say, Show, Scene and the rest play one at a time and continue when the player has answered; Menu returns the chosen index for a Branch or Switch, and Input returns what was typed:

Script → Scene (bg garden, fade) → Show (qinglan smile, right, dissolve) → Say (q, What hangs in the treetop?) → Menu (A gong, The moon) → Branch on choice = 1 → Say (q, The moon. Correct.)

It is the most direct way to write a small game as nodes. Its limit is stated, not hidden: a graph's execution position is not data, so a live script cannot be saved, loaded or rolled back. Call Label runs a story label from the live script, but saving and rollback stay unavailable while the live script is underneath it. For a game players will save, write the story as labels, in script or with the functional nodes, and keep the Events graph for setup and commands. See Concepts.

Functional story building

The functional nodes write a story without any script. One label is a chain:

Start Sequence → Scene (bg garden, fade) → Show (qinglan smile, right, dissolve) → Say (q, You came.) → Menu (caption, Make Choice I did. with its own sequence, Make Choice I was passing. with its own) → Make Label (start)

and the story collects labels and definitions:

Start Story → Add Label (start) → Add Label (garden) → Add Character (Make Character q, Qinglan, #c0392b, image qinglan) → Add Default (affection, 0) → Make Game Definition (The Garden, story) → With Library Assets → With Theme (text_size, 40)

The two styles mix freely: Story From Script or Script nodes bring in script text where nodes are clumsy, Combine Stories merges a scripted story with a node-built one, and Story To Script shows any of it as script.

Describe, preview, run

The intended workflow keeps the game's description in one place and plays it from two:

  1. Describe the game in a Function graph. Build the story, characters and settings with the functional nodes, and return a Game Definition from the graph.
  2. Call it from a Flows graph to preview it. Place the function in a Flows graph, select its output, and open the Custom Preview in the Properties panel. The game plays in a window of its own, on a thread of its own, with saves kept in memory (a preview never touches a player's real saves) and the developer console on (Shift+O; jump label warps), even if the game's scripts set developer_mode to false.
  3. Hand the same definition to a procedural graph to run it for real: Make Novella Game From Definition → Run, or Run Game Definition.

The Custom Preview plays more than whole games. A Story with no start label starts at its first label, a Label plays as a one-label story, a Sequence plays as the start label, and a Novella Game plays its definition, so any node along a chain can be tried on its own. Without the custom preview, the ordinary preview shows the value as script: a sequence, label or story as the script it amounts to, a character as its character line, and a game definition as a summary followed by its script.

Assets in the document

A Divooka document can carry its game: images, sounds, fonts, videos and scripts embedded in the document's asset library (in Divooka Compute, the Asset library, Ctrl+Shift+A, with Import files…). Paths in the library are what scripts refer to, so keep the folders the scripts expect (bg/, sprites/qinglan/, audio/bgm/), and images name themselves from their paths there exactly as on disk.

Style Node What it reads
Procedural Add Library Assets Every file in the library becomes one of the game's files; follow it with Load Scripts From Assets for the scripts.
Functional With Library Assets The same for a definition; turn on its script option to load the library's scripts into the story too.
Functional Story From Library One script file from the library, as a story.

All three take the document's library automatically. Library files and folders can be combined: a later source wins for the same path, so a folder added after the library can override some of its files while testing.

What Divooka does not reach

A few C# extension points have no node yet: registering expression functions (RegisterFunction), custom screens (RegisterScreen, which are C# classes), commands that take arguments directly (use the Command event instead), and a live script outside an Events graph. See Development for them.