Dialogue System - acedogblast/Project-Uranium-Godot GitHub Wiki

This page explains the basic usage of the dialogue system

Setup

The dialogue system is a singleton/autoload. To use it, you probably want your scene to be connected to these two signals:

func _ready():
	...
	DialogueSystem.connect("dialogue_start", self, "pause_scene")
	DialogueSystem.connect("dialogue_end", self, "resume_scene")

These two signals (dialogue_start and dialogue_end) are called when a piece of dialogue was started or has ended, respectively. Typically, you'll want to pause some game logic while a dialogue is active, and resume it once it's done. For that, you can connect these signals to methods in your script (in this example, they are respectively pause_scene and resume_scene), to accomplish that.

If you simply want to pause your scene, you can reduce your code to this:

func _ready():
	...
	DialogueSystem.connect("dialogue_start", self, "set_process", [false])
	DialogueSystem.connect("dialogue_end", self, "set_process", [true])

Don't forget to unregister these signals once the scene is unloaded/finished:

func _exit_tree():
	...
	DialogueSystem.disconnect("dialogue_start", self, "pause_scene")
	DialogueSystem.disconnect("dialogue_end", self, "resume_scene")

Start Dialogue

To start a dialogue, just call the method:

	DialogueSystem.start_dialog("This is a piece of dialogue!")

You can supply a string, or a key:

	DialogueSystem.start_dialog("INTERACT_MOKITOWN_HOUSE_TV")

The keys are used in the localization files. You can use simple, normal text for debugging purposes, but once you're ready to publish your work, you should add your string to the localization files. You can find more info in the Localization Files section.

There are also options to customize the appearance of dialogue (such as setting the box to another position, or pointing an arrow to a point). For more info on these, check the Documentation page.

Dialogue Sequences

Sometimes, you want to show several pieces of dialogue at once (such as in a cutscene, or when talking to an NPC). It's cumbersome to call the same method for every dialogue string, so we developed a system to avoid that.

Suppose you have the following dialogue sequence:

NPC_TRAINER_D1
NPC_TRAINER_D2
NPC_TRAINER_D3
NPC_TRAINER_D4
NPC_TRAINER_D5

You can call the following methods:

func start_npc_trainer_dialogue():
	...
	DialogueSystem.set_dialogue_sequence("NPC_TRAINER_D")
	for i in range(5):
		DialogueSystem.next_dialogue()

This sets the dialogue system to use a sequence, titled NPC_TRAINER_D. For every call to next_dialogue, the dialogue system fetches NPC_TRAINER_D1 and increments the counter. All you need to do now is call next_dialogue repeatedly until it's over.

There's also another way to use this, through the usage of signals:

func start_npc_trainer_dialogue():
	...
	DialogueSystem.set_dialogue_sequence("NPC_TRAINER_D")
	DialogueSystem.start_dialogue_sequence()
	yield(DialogueSystem, "dialogue_sequence_end")

Since dialogue_sequence_end is triggered at the end of a sequence, you can yield to wait for a sequence to be over, instead of having to iterate next_dialogue the number of times you need.

Localization files

The dialogue system fetches strings from localization files, in .PO (gettext) format. For your text to be properly localized, you need to add your strings to these files, and create keys to reference them.

These files are located under the Dialogue folder. In it, you'll find a Generated folder with the localized files, and some .pot files, which are the template localization files. You register your keys in the template files, and later run some commands to update the localization files.

Currently, these are the existing files:

  • Cutscenes.pot - Contains text for cutscene events
  • NPC.pot - Contains text for NPC dialogue's
  • UI.pot - Contains text for UI elements
  • Objects.pot - Contains text of objects(Street signs, bookshelf, etc.) in the overworld
  • Maps.pot - Contains text of messages in the overworld

When you add text, add it to one of these files. If you feel your text doesn't belong to any of these, you can create one. Below is a quick cheat sheet of commands to run for certain actions.

Create a new file

Just create your new file inside Dialogue folder. Add this boilerplate code on top:

msgid ""
msgstr ""

"Content-Type: text/plain; charset=UTF-8\n"

After that, you can add your content:

msgid "MY_MESSAGE"
mststr "This is my message."

Add your content in English; to localize it, you'll need to initialize it.

Initialize a localization file

If a file hasn't been initialized, or if doesn't exist in your locale, run this (assuming your file is called Messages.pot):

msginit --no-translator --input=Dialogue/Messages.pot --locale=XX --output=Dialogue/Generated/XX/Messages.po

Where XX is the locale code. You can find valid locale codes here

After this your generated file will be placed on Dialogue/Generated/XX/Messages.po. Now you can open this file and start localizing the strings to your language.

Don't forget to add this file to the project (Project > Project Settings > Localization > Translations > Add your .po file here), otherwise it won't be used!

Merge translation files

If a new key is added to the template files, it needs to be added to the generated files. In order to not lose the current translations, you'll have to merge (assuming the file to be updated is Cutscenes.po):

msgmerge --update --backup=none -N Dialogue/Generated/XX/Cutscenes.po Dialogue/Cutscenes.pot

With XX being the locale code.

Rich text and events

Text can have customization in two forms:

  • Rich Text - Change the aspect of the text, such as color, font, etc...
  • Events - Events can happen during text flow, such as changes in speed, waits, choices, etc...

Both of these features have been coded with Pókemon Essentials syntax, for easier portability of the current text. The general cheatsheet can be read here. The following shows what's currently implemented:

  • <b>...</b> - Bold text.
  • \c[n] - Colored text. n indicates the color:
    • 0 - White
    • 1 - Blue
    • 2 - Red
    • 3 - Green
    • 4 - Cyan
    • 5 - Magenta
    • 6 - Yellow
    • 7 - Gray
    • 8 - White
  • \PN - Displays the player's name.
  • \n - Adds a line-break. Note that text is automatically wrapped if it overflows.
  • \. - Pauses for 0.25 seconds.
  • \| - Pauses for 1 second.
  • \wt[n] - Pauses for n/20 seconds.
  • \wtnp[n] - Pauses for n/20 seconds, and after that auto-skips the rest of the dialogue.

To write codes that start with a \, you'll have to add a double \\ in the localization files, otherwise msginit/msgmerge will try to interpret the codes and fail.

More are being implemented. If you need a specific event, open up an issue to let us know.

Documentation

Here is a base documentation of all methods. You can also look into some cutscenes files to see some of these methods in action, to understand them better:

  • reset() - Resets the dialogue system to a default state. Use this to clear up any configurations made from previous scenes. This is called automatically when using start_dialogue()
  • set_dialogue_sequence(dialogue_sequence) - Sets a dialog sequence to be used.
    • dialogue_sequence - A string indicating the sequence
  • start_dialogue_sequence() - Starts a dialogue sequence. A sequence must have been set prior with set_dialogue_sequence().
    • Emits dialogue_sequence_start and dialogue_sequence_end when the sequence starts and ends, respectively.
    • Emits dialogue_start and dialogue_end after every dialogue string starts and ends, respectively.
  • next_dialogue() - Shows the next dialogue from a sequence. A sequence must have been set prior with set_dialogue_sequence().
    • Returns true if there's was dialogue, and false if the sequence reached the end.
    • Emits dialogue_start and dialogue_end after the dialogue string starts and ends, respectively.
  • set_show_arrow(show_arrow = True) - Sets whether to show the red arrow when the dialogue has ended.
    • show_arrow = True - boolean
  • set_box_position(pos = BOTTOM) - Sets the position of the dialogue box.
    • pos = BOTTOM - Vector2D. You can use the constants TOP, MIDDLE and BOTTOM from the class to set the box to those positions.
  • set_point_to(point_to = null) - Sets a dialogue box to point to a coordinate in the screen.
    • point_to = null - Vector2D. This vector should be in screen coordinates.
  • start_dialogue(text) - Starts a dialogue.
    • text - String to display. This can be a raw string or a key from the localization files.
    • Emits dialogue_start and dialogue_end after the dialogue string starts and ends, respectively.

The rest of the methods present are for internal usage; do not use them, as you can mess up the system.

⚠️ **GitHub.com Fallback** ⚠️