Reorganize a bit and add more docs (#1043)

Improved dialogue documentation by writing some more guides (Fixes #833)

I checked through the dialogue and nomai text schemas and I don't see
anything missing when compared to base game code.
This commit is contained in:
xen-42 2025-02-14 20:16:34 -05:00 committed by GitHub
commit a55a7d451e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 85 additions and 29 deletions

View File

@ -15,38 +15,14 @@ A dialogue tree is an entire conversation, it's made up of dialogue nodes.
A node is a set of pages shown to the player followed by options the player can choose from to change the flow of the conversation. A node is a set of pages shown to the player followed by options the player can choose from to change the flow of the conversation.
### Condition ### Conditions
A condition is a yes/no value stored **for this loop and this loop only**. It can be used to show new dialogue options, stop someone from talking to you (looking at you Slate), and more. In dialogue, the available conversation topics can be limited by what the player knows, defined using dialogue conditions, persistent conditions, and ship log facts. Dialogue can also set conditions to true or false, and reveal ship log facts to the player. This is covered in detail later on this page.
### Persistent Condition
A persistent condition is similar to a condition, except it _persists_ through loops, and is saved on the players save file.
### Remote Trigger ### Remote Trigger
A remote trigger is used to have an NPC talk to you from a distance; ex: Slate stopping you for the umpteenth time to tell you information you already knew. A remote trigger is used to have an NPC talk to you from a distance; ex: Slate stopping you for the umpteenth time to tell you information you already knew.
### ReuseDialogueOptionsListFrom
This is a custom XML node introduced by New Horizons. Use it when adding new dialogue to existing characters, to repeat the dialogue options list from another node.
For example, Slate's first dialogue with options is named `Scientist5`. To make a custom DialogueNode using these dialogue options (meaning new dialogue said by Slate, but reusing the possible player responses) you can write:
```xml
<DialogueNode>
<Name>...</Name>
<Dialogue>
<Page>NEW DIALOGUE FOR SLATE HERE.</Page>
</Dialogue>
<DialogueOptionsList>
<ReuseDialogueOptionsListFrom>Scientist5</ReuseDialogueOptionsListFrom>
</DialogueOptionsList>
</DialogueNode>
```
Note: If you're loading dialogue in code, 2 frames must pass before entering the conversation in order for ReuseDialogueOptionsListFrom to take effect.
## Example XML ## Example XML
Here's an example dialogue XML: Here's an example dialogue XML:
@ -176,11 +152,39 @@ In addition to `<DialogueOptions>`, there are other ways to control the flow of
Defining `<DialogueTarget>` in the `<DialogueNode>` tag instead of a `<DialogueOption>` will make the conversation go directly to that target after the character is done talking. Defining `<DialogueTarget>` in the `<DialogueNode>` tag instead of a `<DialogueOption>` will make the conversation go directly to that target after the character is done talking.
### DialogueTargetShipLogCondition ### EntryCondition
Used in tandem with `DialogueTarget`, makes it so you must have a [ship log fact](/guides/ship-log#explore-facts) to go to the next node. The first dialogue node that opens when a player starts talking to a character is chosen using this property. To mark a DialogueNode as beginning the dialogue by default, use the condition DEFAULT (a DialogueTree should always have a node with the DEFAULT entry condition to ensure there is a way to start dialogue).
### Adding to existing dialogue The entry condition can be either a condition or a persistent condition.
### Condition
A condition is a yes/no value stored **for this loop and this loop only**. It can be used to show new dialogue options, stop someone from talking to you (looking at you Slate), and more.
Conditions can be set in dialogue using `<SetCondition>CONDITION_NAME</SetCondition>`. This can go in a DialogueNode in which case it will set the condition to true when that node is read. There is a similar version of this for DialogueOptions called `<ConditionToSet>CONDITION_NAME</ConditionToSet>` which will set it to true when that option is selected. Conditions can be disabled using `<ConditionToCancel>CONDITION_NAME</<ConditionToCancel>` in a DialogueOption, but cannot be disabled just by entering a DialogueNode.
You can lock a DialogueOption behind a condition using `<RequiredCondition>CONDITION_NAME</RequiredCondition>`, or remove a DialogueOption after the condition is set to true using `<CancelledCondition>CONDITION_NAME</CancelledCondition>`.
Dialogue conditions can also be set in code with `DialogueConditionManager.SharedInstance.SetConditionState("CONDITION_NAME", true/false)` or read with `DialogueConditionManager.SharedInstance.GetConditionState("CONDITION_NAME")`.
Note that `CONDITION_NAME` is a placeholder that you would replace with whatever you want to call your condition. Consider appending conditions with the name of your mod to make for better compatibility between mods, for example a condition name like `SPOKEN_TO` is very generic and might conflict with other mods whereas `NH_EXAMPLES_SPOKEN_TO_ERNESTO` is much less likely to conflict with another mod.
### Persistent Condition
A persistent condition is similar to a condition, except it _persists_ through loops, and is saved on the players save file.
Persistent conditions shared many similar traits with regular dialogue conditions. You can use `<SetPersistentCondition>`, `<DisablePersistentCondition>`. On dialogue options you can use `<RequiredPersistentCondition>`, `<CancelledPersistentCondition>`
Persistent conditions can also be set in code with `PlayerData.SetPersistentCondition("PERSISTENT_CONDITION_NAME", true/false)` and read using `PlayerData.GetPersistentCondition("PERSISTENT_CONDITION_NAME")`.
### Ship Logs
Dialogue can interact with ship logs, either granting them to the player (`<RevealFacts>` on a DialogueNode) or locking dialogue behind ship log completion (`<RequiredLogCondition>` on a DialogueOption).
You can also use `<DialogueTargetShipLogCondition>` in tandem with `DialogueTarget` to make it so you must have a [ship log fact](/guides/ship-log#explore-facts) to go to the next node.
## Adding to existing dialogue
Here's an example of how to add new dialogue to Slate, without overwriting their existing dialogue. This will also allow multiple mods to all add new dialogue to the same character. Here's an example of how to add new dialogue to Slate, without overwriting their existing dialogue. This will also allow multiple mods to all add new dialogue to the same character.
@ -221,8 +225,33 @@ To use this additional dialogue you need to reference it in a planet config file
] ]
``` ```
### ReuseDialogueOptionsListFrom
This is a custom XML node introduced by New Horizons. Use it when adding new dialogue to existing characters, to repeat the dialogue options list from another node.
For example, Slate's first dialogue with options is named `Scientist5`. To make a custom DialogueNode using these dialogue options (meaning new dialogue said by Slate, but reusing the possible player responses) you can write:
```xml
<DialogueNode>
<Name>...</Name>
<Dialogue>
<Page>NEW DIALOGUE FOR SLATE HERE.</Page>
</Dialogue>
<DialogueOptionsList>
<ReuseDialogueOptionsListFrom>Scientist5</ReuseDialogueOptionsListFrom>
</DialogueOptionsList>
</DialogueNode>
```
Note: If you're loading dialogue in code, 2 frames must pass before entering the conversation in order for ReuseDialogueOptionsListFrom to take effect.
## Dialogue FAQ ## Dialogue FAQ
### How do I easily position my dialogue relative to a speaking character ### How do I easily position my dialogue relative to a speaking character
Use `pathToAnimController` to specify the path to the speaking character (if they are a Nomai or Hearthian make sure this goes directly to whatever script controls their animations), then set `isRelativeToParent` to true (this is setting available on all NH props for easier positioning). Now when you set their `position`, it will be relative to the speaker. Since this position is normally where the character is standing, set the `y` position to match how tall the character is. Instead of `pathToAnimController` you can also use `parentPath`. Use `pathToAnimController` to specify the path to the speaking character (if they are a Nomai or Hearthian make sure this goes directly to whatever script controls their animations), then set `isRelativeToParent` to true (this is setting available on all NH props for easier positioning). Now when you set their `position`, it will be relative to the speaker. Since this position is normally where the character is standing, set the `y` position to match how tall the character is. Instead of `pathToAnimController` you can also use `parentPath`.
### How do I have the dialogue prompt say "Read" or "Play recording"
`<NameField>` sets the name of the character, which will then show in the prompt to start dialogue. You can alternatively use `<NameField>SIGN</NameField>` to have the prompt say "Read", and `<NameField>RECORDING</NameField>` to have it say "Play recording".

View File

@ -0,0 +1,26 @@
---
title: Nomai Text
description: Guide to making Nomai Text in New Horizons
---
This page goes over how to use Nomai text in New Horizons.
## Understanding Nomai Text
Nomai text is the backbone of many story mods. There are two parts to setting up Nomai text: The XML file and the planet config.
### XML
In your XML, you define the actual raw text which will be displayed, the ship logs it unlocks, and the way it branches. See [the Nomai text XML schema](/schemas/text-schema/) for more info.
Nomai text contains a root `<NomaiObject>` node, followed by `<TextBlock>` nodes and optionally a `<ShipLogConditions>` node.
Nomai text is made up of `TextBlock`s. Each text block has an `ID` which must be unique (you can just number them for simplicity). After the first defined text block, each must have a `ParentID`. For scrolls and regular wall text, the text block only gets revealed after its parent block. Multiple text blocks can have the same parent, allowing for branching paths. In recorders and computers, each text block must procede in order (the second parented to the first, the third to the second, etc). In cairns, there is only one text block.
To unlock ship logs after reading each text block, add a `<ShipLogConditions>` node. This can contains multiple `<RevealFact>` nodes, each one defining a `<FactID>`, `<Condition>`. The ship log conditions node can either have `<LocationA/>` or `<LocationB/>`, which means the logs will unlock only if you are at that location. The `<Condition>` lists the TextBlock ids which must be read to reveal the fact as a comma delimited list (e.g., `<Condition>1,2,4</Condition>`)..
### Json
In your planet config, you must define where the Nomai text is positioned. See [the translator text json schema](/schemas/body-schema/defs/translatortextinfo/) for more info.
You can input a `seed` for a wall of text which will randomly generate the position of each arc. To test out different combinations, just keep incrementing the number and then hit "Reload Configs" from the pause menu with debug mode on. This seed ensures the same positioning each time the mod is played. Alternatively, you can use `arcInfo` to set the position and rotation of all text arcs, as well as determining their types (adult, teenager, child, or Stranger). The various age stages make the text look messier, while Stranger allows you to make a translatable version of the DLC text.

View File

@ -14,6 +14,7 @@ Before you release anything, you'll want to make sure:
- Your repo has the description field (click the cog in the right column on the "Code" tab) set. (this will be shown in the manager) - Your repo has the description field (click the cog in the right column on the "Code" tab) set. (this will be shown in the manager)
- There's no `config.json` in your addon. (Not super important, but good practice) - There's no `config.json` in your addon. (Not super important, but good practice)
- Your manifest has a valid name, author, and unique name. - Your manifest has a valid name, author, and unique name.
- You have included any caches New Horizons has made (i.e., slide reel caches). Since these are made in the install location of the mod you will have to manually copy them into the mod repo and ensure they stay up to date. While these files are not required, they ensure that your players will have faster loading times and reduced memory usage on their first loop (after which the caches will generate for them locally).
## Releasing ## Releasing