Narrator System#

Overview#

An engine system for integrating branching narratives into a game for the GameEngine3D.

  • The system reads a human-readable story document, allowing users to create decision points and redirect to different story sections.
  • It internally represents the document as a graph with nodes and edges to represent flow.
  • It parses the document, checks for syntax errors and invalid redirects, and warns about unreachable text.
  • The graph data is exported as JSON. During runtime, the JSON is read and traversed using the system’s runtime interface.
  • The system has special characters to represent the decision points and the redirects.

Skills / Tech Stack#

C++ Lua ImGui Git

Visual Studio Visual Assist X JSON


Contributions#

  • Designed and implemented the system.

Implementation Details#

Story Text File Structure#

Dialogues#

The dialogues can be written as text in the files. (DialogueNodes).

Any line without the following notations is considered dialogue in the document.

Sections / Knots#

The document can have different sections. All the sections should be named. Sections are marked by (===) at the start of a line, followed by the section name. (KnotNodes)

The section name should contain the character set 0-9 A-Z a-z _

Example:

section_1 (valid)

section2 (valid)

20section (valid)

Section!1 (invalid)

Section#1 (invalid)

Choices#

The choices are marked with (*) in the front, followed by the text. (ChoiceNodes)

Example:

* Your Choice 1

* Your Choice 2

* Your Choice 3

* Your Choice 4

Redirections / Diverts#

The redirections are denoted by the (->) at the start of the line and followed by a valid section name. The sections can be defined later in the document after using a particular redirection node. Still, the section should not be missing from the document. (DivertNode)

The section names are case-sensitive (Section1 is different from section1)

Example:

->section_1 (valid, if the document contains a section named section_1)

->section_1 (invalid, if the document does not contains a knot section_1)

End of the Document / Done#

The end of the document is denoted by either (->END) or (->DONE). This can be added anywhere in the document to mark the end.

All the different flow branches should be marked with either a divert / end / done

->END

->end

->End

->DONE

->done

->Done

(All valid to mark the end of the story)

Example Story Text File#


Data Structures#

The flow of the narration is internally handled by a Graph data structure.

Then Graph is a Directed Graph and can either be cyclic or acyclic.

This Graph contains a few different types of nodes, such as StartNode, EndNode, DialogueNode, DivertNode, KnotNode, ChoiceNode, and DesicionNode.

Nodes#

StartNode – Start of the Narrative Document

EndNode – End of the Narrative Document

DialogueNode – Represents the text with any special meaning to the Graph; this is a Node that contains the text dialogue data.

KnotNode – Then narrative can be broken down into multiple sections called knots.

DivertNode – This redirects the narrative flow to different sections within the same documents.

ChoiceNode – This is used to hold the choice data and information.

DesicionNode – This node tracks the start of the choice nodes internally.

The Graph holds all the nodes, flow indicated by edges from the source node to the destination node. It also maintains an adjacency list for all the nodes, holding information about the nearby nodes from each node. This is used while parsing the story document.

Links πŸ”—#

The flow within these nodes is maintained by Links and their types.

UniIn – Single in-flow Node

UniOut – Single out-flow node

MultiIn – Multiple in-flow nodes

MultiOut – Multiple out-flow nodes

Parsing#

The Parser reads the document line by line. Because of this,

->END (is different from)

->

END

System Usage in the Game#

Header Includes#

#include <Engine/StoryNarrator/Includes.h>

The above header is required to access the runtime methods.

Runtime Methods#

The following methods are available in the StoryNarrator Runtime


bool canRead();

This method tells whether the story can be read. This will be false if the story document has reached the end or a decision point before choices.

std::string Read();

This method returns the current dialogue text.

std::vector<std::string> GetChoices();

This method returns all the current choice texts if it is in the decision nodes.

void SelectChoice(uint32_t i_ChoiceIndex);

This method will select the choice with the current index and then proceed within the selected choice flow

bool FromJSONFile(const std::string& i_JSONFilePath);

This method loads the story asset/story JSON document during the runtime.


Links πŸ”—#

Story Narrator on GitHub