From 92b622cf50dd83463909062e85938f8a639bfed2 Mon Sep 17 00:00:00 2001 From: Juju Adams Date: Fri, 27 Sep 2024 15:58:14 +0100 Subject: [PATCH] Starting on 2.17 docs --- docs/2.17/Alternatives.md | 11 + docs/2.17/README.md | 66 ++++ docs/2.17/_sidebar.md | 27 ++ docs/2.17/concept-actions-functions.md | 234 ++++++++++++ docs/2.17/concept-chatterboxes.md | 25 ++ docs/2.17/concept-metadata-and-speakers.md | 56 +++ docs/2.17/concept-source-files.md | 9 + docs/2.17/concept-yarn-script.md | 391 +++++++++++++++++++++ docs/2.17/getting-started.md | 279 +++++++++++++++ docs/2.17/reference-chatterboxes.md | 82 +++++ docs/2.17/reference-configuration.md | 285 +++++++++++++++ docs/2.17/reference-content-getters.md | 149 ++++++++ docs/2.17/reference-flow.md | 134 +++++++ docs/2.17/reference-localisation.md | 50 +++ docs/2.17/reference-option-getters.md | 165 +++++++++ docs/2.17/reference-setup.md | 211 +++++++++++ docs/2.17/reference-variables.md | 208 +++++++++++ 17 files changed, 2382 insertions(+) create mode 100644 docs/2.17/Alternatives.md create mode 100644 docs/2.17/README.md create mode 100644 docs/2.17/_sidebar.md create mode 100644 docs/2.17/concept-actions-functions.md create mode 100644 docs/2.17/concept-chatterboxes.md create mode 100644 docs/2.17/concept-metadata-and-speakers.md create mode 100644 docs/2.17/concept-source-files.md create mode 100644 docs/2.17/concept-yarn-script.md create mode 100644 docs/2.17/getting-started.md create mode 100644 docs/2.17/reference-chatterboxes.md create mode 100644 docs/2.17/reference-configuration.md create mode 100644 docs/2.17/reference-content-getters.md create mode 100644 docs/2.17/reference-flow.md create mode 100644 docs/2.17/reference-localisation.md create mode 100644 docs/2.17/reference-option-getters.md create mode 100644 docs/2.17/reference-setup.md create mode 100644 docs/2.17/reference-variables.md diff --git a/docs/2.17/Alternatives.md b/docs/2.17/Alternatives.md new file mode 100644 index 00000000..80cea863 --- /dev/null +++ b/docs/2.17/Alternatives.md @@ -0,0 +1,11 @@ +# Alternatives + +  + +Chatterbox might not be the perfect fit for your game. The GameMaker community has produced other solutions that you might like to try: + +- [FriendlyCosmonaut's dialogue system](https://friendlycosmonaut.itch.io/dialoguesystem) + +- [Quack](https://marketplace.yoyogames.com/assets/8789/quack-dialogue-system) + +- [gmdialogue](https://github.com/danielpancake/gmdialogue) \ No newline at end of file diff --git a/docs/2.17/README.md b/docs/2.17/README.md new file mode 100644 index 00000000..0b57bd8b --- /dev/null +++ b/docs/2.17/README.md @@ -0,0 +1,66 @@ + +

2.16

+

Narrative engine for GameMaker 2022 LTS by Juju Adams

+ +

Download the .yymps

+

Download the visual editor by Faulty

+ +--- + +Chatterbox is a GameMaker implementation of the [Yarn language](https://yarnspinner.dev/), used in games such as [Far From Noise](https://www.georgebatchelor.com/farfromnoise), [Knights and Bikes](https://foamswordgames.com/#knights), and [Night In The Woods](http://www.nightinthewoods.com/). + +Yarn is designed to be accessible to writers who have little or no programming knowledge. It makes no assumptions about how your game presents dialogue to the player, or about how the player chooses their responses. Yarn has lots of [thorough documentation](https://yarnspinner.dev/docs/tutorial). + +Syntax and features specific to Chatterbox [can be found here](concept-yarn-script). Chatterbox attempts to be a full implementation of the Yarn specification; if there's anything missing, please [create an Issue](https://github.com/JujuAdams/Chatterbox/issues) and Juju will do his best to meet your request. + +Yarn files can be written by hand, but the best way to start with Yarn is to use an editor. The best editor to use with YarnScript v2 is [Crochet](https://github.com/FaultyFunctions/Crochet), available on [Windows, MacOS, & Ubuntu](https://github.com/FaultyFunctions/Crochet/releases), or as a [web-based editor](https://faultyfunctions.github.io/Crochet/). + +## Features + +- **Powerful**
+ Yarn is node-based, with each node containing dialogue and options as you'd expect. But the real power to bring life to your stories is found in Yarn's [in-line commands](concept-yarn-script#actions). These can be used at any point to execute GML functions from specific points in your text, triggering cutscenes or animating faces or playing sound effects.
+ +- **Familiarity**
+ Yarn looks similar to [Twine](https://twinery.org/) in many ways, but avoids the trappings of that tool. There's no [debating what version to use](https://www.reddit.com/r/twinegames/comments/eic3na/which_version_should_i_start_with/) or what particular standard is best like with Twine - Yarn has a single standard. The [visual editor](https://faultyfunctions.github.io/Crochet/) should feel comfortable for anyone who's worked in narrative design before. + +- **Tools**
+ Chatterbox is designed to be easy to implement and easy to make games with. [YarnScript](concept-yarn-script) can be written by hand or, more commonly, an editor is used to write your stories. There's a [web editor](https://faultyfunctions.github.io/Crochet/) as well as [Windows, MacOS, & Ubuntu](https://github.com/FaultyFunctions/Crochet/releases) binaries. Chatterbox loads in Yarn files straight from your [Included Files](https://manual.yoyogames.com/Settings/Included_Files.htm) with a [single command](reference-configuration#chatterboxloadfromfilefilename-aliasname) without any other setup. + +- **Community**
+ Yarn has a thriving community of narrative designers. The maintainers of Yarn run a [Slack group](http://lab.to/narrativegamedev) & [Discord server](https://discord.gg/yarnspinner), and [YarnSpinner](https://github.com/YarnSpinnerTool/) and [Crochet](https://faultyfunctions.github.io/Crochet/) (community maintained editor for Yarn v2) are constantly being updated. + +?> For a full explanation of Yarn's features and syntax, please read the [YarnScript](concept-yarn-script) page. + +## Updating + +Releases go out once in while, typically expedited if there is a serious bug. This library uses [semantic versioning](https://semver.org/). In short, if the left-most number in the version is increased then this is a "major version increase". Major version increases introduce breaking changes and you'll almost certainly have to rewrite some code. However, if the middle or right-most number in the version is increased then you probably won't have to rewrite any code. For example, moving from `1.1.0` to `2.0.0` is a major version increase but moving from `1.1.0` to `1.2.0` isn't. + +?> Please always read patch notes. Very occasionally a minor breaking change in an obscure feature may be introduced by a minor version increase. + +At any rate, the process to update is as follows: + +1. **Back up your whole project using source control!** +2. Back up the contents of your configuration script (`__ChatterboxConfig` or `__ChatterboxConfigMacros` depending on the version) within your project. Duplicating the script is sufficient +3. Delete all library scripts from your project. Unless you've moved things around, this means deleting the library folder from the asset browser +4. Import the latest [.yymps](https://github.com/JujuAdams/chatterbox/releases/) +5. Restore your configuration script from the back-up line by line + +!> Because configuration macros might be added or removed between versions, it's important to restore your configuration script carefully. + +## About & Support + +If you'd like to report a bug or suggest a feature, please use the repo's [Issues page](https://github.com/JujuAdams/chatterbox/issues). Chatterbox is constantly being maintained and upgraded; bugs are usually addressed within a few days of being reported. + +Chatterbox is supported for all GameMaker export modules, apart from HTML5. You might run into edge cases on platforms that I haven't tested; please [report any bugs](https://github.com/JujuAdams/chatterbox/issues) if and when you find them. + +--- + +Chatterbox is built and maintained by [Juju Adams](https://www.jujuadams.com/) who has a long history of fiddling with text engines. Juju's worked on a lot of [commercial GameMaker games](http://www.jujuadams.com/); Chatterbox is the product of experience writing a custom narrative scripting language for [Retrace](https://store.steampowered.com/app/1052640/Retrace/) and tooling for another major GameMaker title, as yet unreleased. + +Additional contributions have been made by [squircledev](https://github.com/squircledev) and [Faulty](https://github.com/FaultyFunctions). A big thank you to Els White, Jukio Kallio, rIKmAN, and squircledev for helping to test this library. + +Chatterbox will never truly be finished because contributions and suggestions from new users are always welcome. Chatterbox wouldn't be the same without [your](https://tenor.com/search/whos-awesome-gifs) input! Make a suggestion on the repo's [Issues page](https://github.com/JujuAdams/chatterbox/issues) if you'd like a feature to be added. + +## License + +Chatterbox is licensed under the [MIT License](https://github.com/JujuAdams/Chatterbox/blob/master/LICENSE). diff --git a/docs/2.17/_sidebar.md b/docs/2.17/_sidebar.md new file mode 100644 index 00000000..95a81679 --- /dev/null +++ b/docs/2.17/_sidebar.md @@ -0,0 +1,27 @@ +- [Introduction](README) +- [Alternatives](Alternatives) +- [Getting Started](getting-started) +- [Spider Lily's Tutorial](https://spiderlilystudios.medium.com/clickable-choices-in-gms2-using-chatterbox-and-scribble-0ed81dfe16a5) + +--- + +**Concepts** + +- [YarnScript](concept-yarn-script) +- [Source Files](concept-source-files) +- [Chatterboxes](concept-chatterboxes) +- [Metadata and Speakers](concept-metadata-and-speakers) +- [Actions and Functions](concept-actions-functions) + +--- + +**API Reference** + +- [Configuration](reference-configuration) +- [Setup](reference-setup) +- [Chatterboxes](reference-chatterboxes) +- [Content Getters](reference-content-getters) +- [Option Getters](reference-option-getters) +- [Flow Control](reference-flow) +- [Variables and Constants](reference-variables) +- [Localisation](reference-localisation) diff --git a/docs/2.17/concept-actions-functions.md b/docs/2.17/concept-actions-functions.md new file mode 100644 index 00000000..fd4abcfd --- /dev/null +++ b/docs/2.17/concept-actions-functions.md @@ -0,0 +1,234 @@ +# Actions and Functions + +YarnScript allows for flow control and the execution of external code by using its "action" syntax. Actions in YarnScript are commands written in between `<<` and `>>` like so: + +```yaml +title: FlowerSeedShelf +--- + +<> +<> + +You see upon the shelf a selection of packets of flower seeds arranged clumsily. +-> Inspect them. + Their attractive full-colour printing is rather eye-catching. Their names are unfamiliar to you, as though the words were made of jumbled syllables. +-> Pick one at random. + <= $maximumFlowerSeeds>> + You pick up a packet but another in your hands slips through your fingers. You're holding as many flower seeds as you can. + <> + <> + You thrust your hand into the pile of seed packets and choose by feel... though they all feel the same to you. + <> +-> Move down the aisle. You don't trust yourself to grow flowers anyway. + <> + +//Replay this node until the player chooses to move down the aisle +<> +=== +``` + +  + +Chatterbox has the following in-built actions: + +### `jump` + +*Example:* `<>` + +*Example*: `<>` + +*Example*: `<>` + +The `<>` action causes a chatterbox to immediately swap execution to another node in a YarnScript file. Execution will start from the top of the new node. If you `<>` back to the old node then you will start execution from the top of the node. You can specify a particular YarnScript file to jump to by specifying the filename first, typing a `:` colon, and then specifying the node in that file. If you don't specify a file then Chatterbox will search in the current file for the desired node. `<>` can be used to jump to a node stored in a variable by referencing the variable as the destination node title. + +  + +### `hop` and `hopback` + +*Example:* `<>` and later `<>` + +*Example:* `<>` and later `<>` + +*Example*: `<>` and later `<>` + + +`<>` operates similarly to `<>` (see above). `<>` differs from `<>` insofar as you can hop back into a node from where you hopped out. This operates on a stack such that calling `<>` twice and then calling `<>` twice will result in a chatterbox being at the exact same position that the first `<>` was called. + +!> It is not possible to save or load the hop stack. Do not rely on the hop stack for tracking important game logic that may need to persist between game sessions. + +  + +### `declare` + +*Example:* `<>` + +*Example:* `<>` + +This action instructs Chatterbox to declare a variable and to give it a default value. + +  + +### `set` + +*Example:* `<>` + +*Example:* `<>` + +Sets the value of a variable, plain and simple. The datatype of a variable (string, number, or boolean `true`/`false`) cannot change. + +  + +### `const` + +*Example:* `<>` + +The `<>` action defines a special kind of variable - it is a variable whose value cannot be changed. This might seem contradictory at first glace - a variable must surely be able to vary?! - but this behaviour is very helpful when trying to keep track of so-called "magic numbers" in your game. For example, you might want to set the maximum number of health points that a player can have. At some point in development, that number might need to go up or down in order to balance the game's difficulty. Using a constant means that you can tweak the maximum number of health points throughout the game without having to find and adjust every single occurrence of a special number (a time-consuming endeavour that is likely to result in bugs). + +  + +### `wait` + +*Example:* `<>` + +`<>` will put a chatterbox into a "waiting" state. This is used to break up sections of dialogue in non-singleton mode. You can tell a chatterbox to "un-wait" by calling `ChatterboxContinue()`. + +?> In singleton mode this action does nothing because `<>` is implicitly and automatically called after every line of dialogue (so long as that dialogue isn't followed immediately by an `->` option). + +?> `<>` is analogous to the `ChatterboxWait()` function. + +  + +### `stop` + +*Example:* `<>` + +Tells a chatterbox to stop processing entirely. The chatterbox can be restarted by calling `ChatterboxJump()`. + +?> `<>` is analogous to the `ChatterboxStop()` function. + +  + +### `if`, `else` etc. + +Branching logic is also written in between `<<` and `>>` too, such as `<>`. These are used to selectively execute parts of your YarnScript but aren't considered "actions" per se. + +  + +## Functions + +Chatterbox contains one native function: `visited("NodeTitle")`. This function returns the number of times that a particular node has been visited. You can specifiy a node in a particular file by You can specifying the filename first, typing a `:` colon, and then specifying the node in that file. If you don't specify a file then Chatterbox will search in the current file for the desired node. + +Powerful custom functions can be added to Chatterbox using the [`ChatterboxAddFunction()`](reference-configuration#chatterboxaddfunctionname-function) function. This is a global function and you only need to call it once per custom function. Custom functions can do anything that GML can do... because they're written in GML! + +!> Custom functions must be defined before calling [`ChatterboxCreate()`](reference-chatterboxes#chatterboxcreatefilename-singletontext-localscope). + +Custom functions can have parameters. Parameters should be separated by spaces and are passed into a script as an array of values in `argument0`. Custom functions can return values, and like Chatterbox variables, a function must return a number, a string, or a boolean `true` / `false`. A function can also return nothing (`undefined`). + +?> You can use the `CHATTERBOX_CURRENT` read-only macro to get the chatterbox that is currently being processed. This is helpful when using `ChatterboxJump()` etc. + + + +#### **GML** + +```gml +function am_i_dead() +{ + return instance_exists(obj_player); +} + + +ChatterboxLoad("example.json"); +ChatterboxAddFunction("AmIDead", am_i_dead); +``` + +#### **YarnScript** + +```yarn +Am I dead? +<> + Yup. Definitely dead. +<> + Not today! +<> +``` + + + +This example shows how the script `am_i_dead()` is called by Chatterbox in an if statement. The value returned from `am_i_dead()` determines which text is displayed. + +  + +## Custom Actions + +A function that has been added to Chatterbox can further be executed as an action. This means you can execute any old code you like using Chatterbox; if you were so inclined you code write an entire game's logic from within YarnScript. + +You can also define custom actions which are used in a similar way to in-built actions: + +```yarn +What a beautiful evening, Amelia. +-> It'd be a shame if the Moon hid behind the clouds. + <> +-> The stars are so bright! + <> +``` + +In this example, both `<>` and `<>` are custom actions. + +There are three ways that custom actions can be used in Chatterbox; to swap between the different implementations set [`CHATTERBOX_ACTION_MODE`](reference-configuration?id=chatterbox_action_mode) to one of the following (the default is option `1`): +- `0` Pass YarnScript actions as a raw string to a function, defined by `CHATTERBOX_ACTION_FUNCTION` +- `1` Treat actions as expressions +- `2` Treat actions as they were in version 1 (Python-esque function calls) + +Mode `0` is the official recommendation from the Yarn team. This mode instructs a chatter to actions as a strings into the game engine for manual interpretation. Chatterbox's implementation is that the function defined by `CHATTERBOX_ACTION_FUNCTION` is called when Chatterbox encounters an action, the first argument (`argument0`) for the function call being the text inside the action as a string. The intention is that you'd then parse that text and execute behaviour accordingly but... this sucks, it's a ton of work to actually do this, let's move on. + +Mode `1` is the default Chatterbox behaviour: +1. Every custom action is expected to use GML-like syntax: functions are executed using their name followed by a comma-separated list of arguments e.g. `<>` +2. Variables are referenced by using the standard dollar-prefixed token e.g. `<>` +3. You can also do basic operations, such as concatenation and basic arithmetic, in function arguments as you would expect in GML e.g. `<>` + +Mode `2` is provided as an easier-to-use alternative for larger teams where people are working with writers who are uncomfortable with GML-like function syntax. The examples above would be written like so: +1. `<>` +2. You can reference variables by using the standard dollar-prefixed token wrapped in `{` `}` curly brackets e.g. `<>` +3. `<>` + +  + +## Asynchronous Functions + +This is an advanced power move! It's possible to create asynchronous function execution so that you can temporarily pause a chatterbox whilst something else happens in your game, such as running an animation or showing a cutscene. To do this we need three different components: +1. `CHATTERBOX_CURRENT` - Macro that contains a reference to the chatterbox that is currently being processed +2. `ChatterboxWait()` - Function that forces a chatterbox into a waiting state (pauses processing) +3. `ChatterboxContinue()` - Function that resumes processing for a chatterbox + +The following example assumes [`CHATTERBOX_ACTION_MODE`](reference-configuration?id=chatterbox_action_mode) has been set to `1` and [`CHATTERBOX_FUNCTION_ARRAY_ARGUMENTS`](reference-configuration?id=chatterbox_function_array_arguments) has been set to `true`. + + + +#### **GML** + +```gml +ChatterboxAddFunction("example", function(_argumentArray) +{ + ChatterboxWait(CHATTERBOX_CURRENT); + show_debug_message("Waiting chatterbox for " + string(_argumentArray[0]) + " frames..."); + time_source_start(time_source_create(time_source_game, _argumentArray[0], time_source_units_frames, + function(_chatterbox) + { + show_debug_message("...continuing chatterbox!"); + ChatterboxContinue(_chatterbox); + }, + [CHATTERBOX_CURRENT])); +}); +``` + +#### **YarnScript** + +```yarn +Hello there, would you like to wait 5 seconds? +-> Nah... +-> Please. + <> +Okey dokey. +``` + + diff --git a/docs/2.17/concept-chatterboxes.md b/docs/2.17/concept-chatterboxes.md new file mode 100644 index 00000000..a32deb1a --- /dev/null +++ b/docs/2.17/concept-chatterboxes.md @@ -0,0 +1,25 @@ +# Chatterboxes + +A chatterbox is a dialogue container, effectively a little virtual machine that lives inside your game. Chatterboxes handle story flow, they store dialogue content and options text, and they set variables and execute functions when directed to by [YarnScript](concept-yarn-script). + +Chatterboxes are created with the [`ChatterboxCreate()`](reference-chatterboxes#chatterboxcreatefilename-singletontext-localscope) but chatterboxes **do not** need to be deleted, destroyed, or freed (unlike GameMaker's native [data structures](https://manual.yoyogames.com/GameMaker_Language/GML_Reference/Drawing/Surfaces/Surfaces.htm) or [surfaces](https://manual.yoyogames.com/GameMaker_Language/GML_Reference/Drawing/Surfaces/Surfaces.htm)). The memory that each chatterbox uses is automatically freed when you lose reference to the chatterbox (much like an array or a struct). + +To initialise a chatterbox, call [`ChatterboxJump()`](reference-flow#chatterboxjumpchatterbox-nodetitle-filename) targetting the desired node. When you call [`ChatterboxJump()`](reference-flow#chatterboxjumpchatterbox-nodetitle-filename) (or in fact any of the [Flow functions](reference-flow)), the chatterbox runs your YarnScript a bit like a simple computer programme. The programme will continue running until one of three things happens: + +1. The chatterbox has hit a `<>` command, or the chatterbox is in [singleton mode](reference-configuration#chatterboxcreatefilename-singletontext-localscope) and a line of dialogue has been processed +2. The YarnScript has hit a `<>` command or there's no more dialogue to show +3. The player needs to select an option + +?> Chatterbox packages are distributed with [singleton mode](reference-configuration#chatterboxcreatefilename-singletontext-localscope) switched on by default. Please read the documentation on [`ChatterboxCreate()`](reference-chatterboxes#chatterboxcreatefilename-singletontext-localscope) and [`__ChatterboxConfig()`](reference-configuration#__chatterboxconfig) for more information. + +Chatterbox provides three functions to find out what state a chatterbox is in, and they correspond to the list above: + +1. If [`ChatterboxIsWaiting()`](reference-flow#chatterboxiswaitingchatterbox) is `true` then the chatterbox is waiting +2. If [`ChatterboxIsStopped()`](reference-flow#chatterboxisstoppedchatterbox) is `true` then the chatterbox has stopped +3. If [`ChatterboxGetOptionCount()`](reference-getters#chatterboxgetoptioncountchatterbox) is greater than 0 then the chatterbox has at least one [option](concept-yarn-script#option-syntax) that must be chosen to proceed + +To advance the text and update a chatterbox's content and options, there are two functions available: [`ChatterboxContinue()`](reference-flow#chatterboxcontinuechatterbox) should be called when a chatterbox is waiting ([`ChatterboxIsWaiting()`](reference-flow#chatterboxiswaitingchatterbox) is `true`). To select an option, [`ChatterboxSelect()`](reference-flow#chatterboxselectchatterbox-optionindex) should be used. If a chatterbox has stopped then this indicates you should no longer show dialogue at all and gameplay should proceed. + +Chatterboxes keep a copy of the content (text/dialogue) and options that should be shown to the player. These can be retrieved using the [Getter functions](reference-getters). A chatterbox will update its content and options whenever [`ChatterboxJump()`](reference-flow#chatterboxjumpchatterbox-nodetitle-filename), [`ChatterboxSelect()`](reference-flow#chatterboxselectchatterbox-optionindex), or [`ChatterboxContinue()`](reference-flow#chatterboxcontinuechatterbox) are called. + +Exactly how the content and options are displayed, and how the player interacts with options, is entirely up to you. Chatterbox makes no assumptions about your text display system. Regardless of how you present content and options to the player, you should use the [Getter functions](reference-getters) to read the data from a chatterbox. diff --git a/docs/2.17/concept-metadata-and-speakers.md b/docs/2.17/concept-metadata-and-speakers.md new file mode 100644 index 00000000..dcb4902b --- /dev/null +++ b/docs/2.17/concept-metadata-and-speakers.md @@ -0,0 +1,56 @@ +# Metadata and Speakers + +## Metadata + +Games with a narrative focus typically have lines of dialogue delivered by specific characters. To indicate a different character is speaking, a game might show a portrait on-screen, it might use a different sound effect for text display, it might cause an animation to play in the game world for the character. A speaker for a line of dialogue is a type of "metadata" - the data itself is the line of dialogue and who's speaking is data attached to the dialogue. + +Chatterbox has support for metadata out of the box: + +```yarn +Welcome to the frog shop! #FrogShopkeeper +How may I *hop* to your assistance today? +Oh... I... thought this was the dog shop. #Customer +That's what I said, dog shop. Welcome to the dog shop. #FrogShopkeeper #DogMask +``` + +Metadata can be retrieved from a line of dialogue using the `ChatterboxGetContentMetadata()` function, and options can have metadata attached to them as well. Metadata is returned as an array of strings; if no metadata is attached to a line of dialogue then an empty array is returned. In the example above, the arrays returned by `ChatterboxGetContentMetadata()` would be the following: + +```gml +["FrogShopkeeper"] +[] +["Customer"] +["FrogShopkeeper", "DogMask"] +``` + +Metadata is useful tons of other things, not least identifying individual strings for localisation. + +  + +## Speakers + +However, this metadata notion is unfamiliar for writers and can be hard to read. Instead, Chatterbox offers a separate system to metadata that allows for a more convenient syntax to describe who's speaking. It looks like this: + +```yarn +FrogShopkeeper: Welcome to the frog shop! +How may I *hop* to your assistance today? +Customer: Oh... I... thought this was the dog shop. +FrogShopkeeper[DogMask]: That's what I said, dog shop. Welcome to the dog shop. +``` + +?> You can control speaker syntax using [`CHATTERBOX_SPEAKER_DELIMITER`](reference-configuration?id=chatterbox_speaker_delimiter), [`CHATTERBOX_SPEAKER_DATA_START`](reference-configuration?id=chatterbox_speaker_data_start), and [`CHATTERBOX_SPEAKER_DATA_END`](reference-configuration?id=chatterbox_speaker_data_end). + +Reading out each line of dialogue using the typical `ChatterboxGetContent()` function will simply return the entire line, including the character speaking the line. To read out dialogue in this formating, you'll need to use the following functions: +- `ChatterboxGetContentSpeech()` +- `ChatterboxGetContentSpeaker()` +- `ChatterboxGetContentSpeakerData()` + +Using the example example these functions will return the following strings: + +|Speaker |Speaker Data|Speech | +|-------------------|------------|----------------------------------------------------------| +|`"FrogShopkeeper"` |`""` |`"Welcome to the frog shop!"` | +|`""` |`""` |`"How may I *hop* to your assistance today?"` | +|`"Customer"` |`""` |`"Oh... I... thought this was the dog shop."` | +|`"FrogShopkeeper"` |`"DogMask"` |`"That's what I said, dog shop. Welcome to the dog shop."`| + +For more complex situations you may want to perform additional parsing on the speaker data yourself e.g. splitting up the speaker data into an array. In the example above, `"DogMask"` could be used to control a subimage for a portrait sprite, or perhaps to trigger an animation. \ No newline at end of file diff --git a/docs/2.17/concept-source-files.md b/docs/2.17/concept-source-files.md new file mode 100644 index 00000000..f7f22c9d --- /dev/null +++ b/docs/2.17/concept-source-files.md @@ -0,0 +1,9 @@ +# Source Files + +--- + +Chatterbox uses [YarnScript](concept-yarn-script) to define and describe how your story should progress, and Chatterbox uses YarnScript version 2. YarnScript can be written by hand, but the best way to start with Yarn is to use an editor. The best editor to use with YarnScript v2 is [Crochet](https://github.com/FaultyFunctions/Crochet), available on [Windows, MacOS, & Ubuntu](https://github.com/FaultyFunctions/Crochet/releases), or as a [web-based editor](https://faultyfunctions.github.io/Crochet/). + +Crochet exports `.yarn` files which contain the structure of your writing. Source files should be included with your project as [Included Files](https://manual.yoyogames.com/Settings/Included_Files.htm). These files can then be loaded using [`ChatterboxLoadFromFile()`](reference-configuration#chatterboxloadfromfilefilename-aliasname) and, once loaded, those files can then be referenced by other Chatterbox functions. + +Chatterbox has some extended functionality regarding stories spread across multiple files - please see the [YarnScript](concept-yarn-script#links-between-nodes) page for more information. diff --git a/docs/2.17/concept-yarn-script.md b/docs/2.17/concept-yarn-script.md new file mode 100644 index 00000000..77fd353b --- /dev/null +++ b/docs/2.17/concept-yarn-script.md @@ -0,0 +1,391 @@ +# YarnScript + +--- + +?> This is an edited copy of the [YarnSpinner Quick Refence Guide](https://github.com/thesecretlab/YarnSpinner/blob/master/Documentation/YarnSpinner-Dialogue/Yarn-Syntax.md) (retrieved 2019-04-18) + +## Introduction + +Chatterbox is an implementation of the YarnScripting language. However, Chatterbox does slightly extend its functionality, +adding more control to variable handling. This enables convenient direct access of GML variables from inside the dialogue script. +Please see the [Variables & Conditionals](concept-yarn-script#variables-amp-conditionals) and [Functions](concept-yarn-script#functions) sections for more information. Chatterbox additionally allows redirects and options to +point to nodes found in other [source files](concept-source-files). + +This document is intended to act as a comprehensive and concise reference for Yarn syntax and structure, for use by programmers +and designers. It assumes a working knowledge of modern programming/scripting languages. For a more thorough explanation +of Yarn usage, see the [offical Yarn tutorial](https://yarnspinner.dev/docs/tutorial). + +!> **Note**: As of 29/07/2021, the official Yarn tutorials show syntax from version 1 of Yarn, while Chatterbox v2 implements the updated version 2 of the Yarn specification. The syntax listed here is the most up to date for what Chatterbox v2 uses. + +## Nodes + +Nodes act as containers for YarnScript, and must have unique titles within each [source file](concept-source-files). The script in the body of a node is processed line by line. A node's header contains its metadata - by default, Yarn only uses the title field, but can be extended to use arbitrary fields. + +```yarn +title: ExampleNodeName +tags: foo, bar +--- + +Yarn content goes here. +This is the second line. + +=== +``` + +A script file can contain multiple nodes. In this case, nodes are delineated using three equals (`===`) characters. +Additionally, Yarn can check if a node has been visited by calling `visited("NodeName")` in an if-statement +(i.e. `<>`). + +## Options + +Options allow for small branches in YarnScripts without requiring extra nodes. Options can have any number of sub-branches, but it's recommended that branching is kept somewhat limited for the sake of script readability. + +```yarn +Mae: What did you say to her? +-> Nothing. + Mae: Oh, man. Maybe you should have. +-> That she was a jerk. + Mae: Hah! I bet that pissed her off. + Mae: How'd she react? + -> She didn't. + Mae: Booooo. That's boring. + -> Furiously. + Mae: That's what I like to hear! +Mae: Anyway, I'd better get going. +``` + +Additionally, shortcut options can utilize conditional logic, actions, and functions (detailed below), and can include standard node +links: + +```yarn +Bob: What would you like? +-> A burger. < 5>> + Bob: Nice. Enjoy! + <> +-> A soda. < 2>> + Bob: Yum! + <> +-> Nothing. + Bob: Okay. +Bob: Thanks for coming! +``` + +## Random Outcomes + +The option syntax above can be extended to allow for random outcomes by using the `<>` action. + +```yarn +The hedge rustle besides you. +-> Investigate +You peer into the hedge and ... +<> +-> + Out hops a rabbit! +-> + A cat tumbles through a gap in the branches! +-> + A bird cheeps at you, irritated by your nosiness! +``` + +Options that follow a `<>` action are never presented to the player (and don't need any option text) and instead are chosen at random by Chatterbox. Options can be weighted by percentage by using metadata. Any option that doesn't have a percentage weight will "split the difference" between the accumulated percentage and 100%. + +```yarn +Letting forth a discrete drunken burp, you put all your chips on lucky red number 1 and let the roulette wheel spin. You cross your fingers in your pocket, hoping no one will notice your anxiety. +<> +-> #45% + Oooh, the ball lands on black ... better luck next time. + If you had any money there'd be a next time anyway. +-> #40% + Your eyes fuzz over for a second. By the time you regain your composure your chips have been shuffled away. + What number did it land on? You can't recall, but it wasn't red number 1. +-> //Implicitly a 14% chance + As you're focusing on your life-changing bet, Daniel stumbles into you and spills his pina colada all down your trousers. + To make things worse, the wheel isn't kind either and you lose your bet. Dammit Daniel! +-> #1% + It ... lands on lucky red number 1! Incredible! + <> +``` + +Randomly chosen options also respect if-statements. Any option that is set to be randomly chosen and fails the if-statement check cannot be selected. + +```yarn +<> +-> <> + Out hops a rabbit! +-> <> + A cat tumbles through a gap in the branches! +-> <> + A bird cheeps at you, irritated by your nosiness! +-> + Nothing but the wind ... +``` + +In the above example, if the player has obtained all three items then they have an equal chance of each of the four outcomes happening. + +## Links Between Nodes + +Moving between nodes can be done using a `<>` action (other action are available, see below): + +```yarn +After this text is shown, we'll move to another node. +<> +``` + +Jump actions can be placed after options which allows for branching dialogue organised across multiple nodes. + +```yarn +-> This is a link to a node. +<> +-> This is a link to a different node. +<> +``` + +Chatterbox adds the ability to target nodes in other files: + +```yarn +-> A link to a node in another file. + <> +``` + +The name of the file (with that file's extension!) comes first, followed by a colon (`:`), followed by the name of the node. + +?> **Please note:** Referencing nodes in other [source files](concept-source-files) is not officially supported by Yarn and this feature is an addition unique to Chatterbox. + +You can also opt to "hop" out of a node to some other destination node. A hop is a reversible jump; you can hop back from your destination node back to your origin node at exactly the place you hopped out. You can call `<>` to return to the node you came from. You can hop back and forth as much as you want. If you call `<>` without any node to hop to then Chatterbox will instead interpret that command as a `<>`. + + + +#### Origin + +```yarn +I wonder what I should have for breakfast. +-> We have something tasty in the fridge I think? + <> +-> I don't have time for this! +Time to start my day. +``` + +#### Destination + +```yarn +-> Pineapple juice + Refreshing! +-> Ham and cheese + Sustaining! +-> Fresh milk + Creamy! +<> +``` + + + +Hopping to a node counts as visiting a node for the purposes of the `visited()` function. If a node doesn't have `<>` or `<>` at the end and Chatterbox reaches the very bottom of a node then it'll assume that you want to call `<>` (and if there're no nodes to hop back to then this will stop execution). You can change this behaviour by changing the value of the config macro `CHATTERBOX_END_OF_NODE_HOPBACK`. + +!> Hops are not serialized by Chatterbox. If you save in the middle of a hop you might find that the game is in an invalid state and the player cannot continue playing. Use hops carefully! + +## Actions + +Chatterbox has the following native actions: + +```yarn +<> +<> +<> +<> +<> +<> +<> +<> +<> +<> +<> +``` + +Custom actions can be added to Chatterbox by using the [`ChatterboxAddFunction()`](reference-configuration#chatterboxaddfunctionname-function) script. Custom actions should be added before +calling [`ChatterboxCreate()`](reference-chatterboxes#chatterboxcreatefilename-singletontext-localscope). + + + +#### **GML** + +```gml +ChatterboxLoad("example.json"); +ChatterboxAddFunction("playMusic", play_background_music); +``` + +#### **YarnScript** + +```yarn +Here's some text! +<> +The music will have started now. +``` + + + +By adding the custom action `playMusic` and binding it to the script `play_background_music()`, Chatterbox will now call this script +whenever `<>` is processed by Chatterbox. + +Custom actions can also have parameters. These parameters can be any Chatterbox value - a real number, a string, or a variable. +Parameters should separated by spaces. Parameters are passed into a script as an array of values in argument0. + + + +#### **GML** + +```gml +ChatterboxLoad("example.json"); +ChatterboxAddFunction("gotoRoom", go_to_room); +``` + +#### **YarnScript** + +```yarn +Let's go see what the priest is up to. +<> +<> +``` + + + +Chatterbox will execute the script `go_to_room()` whenever `<>` is processed. In this case, `go_to_room()` will receive an array +of two values from Chatterbox. The first (index 0) element of the array will be `"rChapel"` and the second (index 1) element will +hold whatever value is in the `$entrance` variable. + +## Variables & Conditionals + +Declaring and Setting Variables: +This statement serves to set a variable's value. No declarative statement is required; setting a variable's value brings it into existence. + +```yarn +<> +``` + +All variables must start with a dollar sign. Internal Yarn variables are, in reality, key:value pairs stored in a global ds_map. Chatterbox has [a handful of functions](reference-variables) dedicated to handling variables, including importing and exporting them. + +If needed, you can access this ds_map via the `CHATTERBOX_VARIABLES_MAP` macro, found in [`__ChatterboxConfig()`](reference-configuration#__chatterboxconfig). + +### if/else Statements: + +Yarn supports standard if/else/elseif statements. + +```yarn +<> + The two strings are the same! +<> +<> + Success! +<> + Success...? +<> + No success. :( +<> +``` + +### Expressions: + +There are four different types of variable in Yarn: strings, floating-point numbers, booleans, and null. + +Yarn will automatically convert between types. For example: + +```yarn +<> + The two strings are the same! +<> + +<> + Strings get joined together with other values! +<> +``` + +## Functions + +By default, Chatterbox includes a `visited()` function which returns the number of times a node has been entered. + +```yarn +<> + We have gone to the city before! +<> +``` + +Chatterbox also includes the `optionChosen()` function. This works similarly to `visited()` but can only be used in the condition for an option, like so: + +```yarn +How can I help? +-> Can I buy some green eggs please? <> + No... This is a stationery shop. +-> Do you have any ham for sale? <> + Huh? We mostly sell birthday cards. +``` + +Using `optionChosen()` outside of an option condition is invalid and will throw an error. What options have been chosen is not intended to persist between gameplay sessions and is not included in the data returned by `ChatterboxVariablesExport()`. If you want to track which options have been chosen, you will instead need to write your own system. + +Other custom functions can be added to Chatterbox using the [`ChatterboxAddFunction()`](reference-configuration#chatterboxaddfunctionname-function) script. Much like custom actions, custom functions can have parameters. Custom functions should be defined before calling [`ChatterboxCreate()`](reference-chatterboxes#chatterboxcreatefilename-singletontext-localscope). + + + +#### **GML** + +```gml +ChatterboxLoad("example.json"); +ChatterboxAddFunction("AmIDead", am_i_dead); +``` + +#### **YarnScript** + +```yarn +Am I dead? +<> + Yup. Definitely dead. +<> + No, not yet! +<> +``` + + + +This example shows how the script `am_i_dead()` is called by Chatterbox in an if statement. The value returned from `am_i_dead()` determines which text is displayed. + +  + +Here's a list of supported operators (in no particular order) that are supported in expressions: + +| Word | Symbol | Use | +| :----------: | :----: | -------------------------------------- | +| `not` | `!` | Logical negation | +| | `+` | Real addition, or string concatenation | +| | `-` | Real substraction, or negative | +| | `*` | Real multiplication | +| | `/` | Real division | +| _Assignment_ | | | +| `to` | `=` | Assignment | +| | `+=` | Add or concatenate, then assign | +| | `-=` | Subtract, then assign | +| | `*=` | Multiply, then assign | +| | `/=` | Divide, then assign | +| _Comparison_ | | | +| `and` | `&&` | Logical AND | +| `le` | `<` | Less than | +| `gt` | `>` | Greater than | +| `or` | `\|\|` | Logical OR | +| `leq` | `<=` | Less-than-or-equal-to | +| `geq` | `>=` | Greater-than-or-equal-to | +| `lte` | `<=` | Less-than-or-equal-to | +| `gte` | `>=` | Greater-than-or-equal-to | +| `eq` | `==` | Equal to | +| `is` | `==` | Equal to | +| `neq` | `!=` | Not equal to | + +## Fast-Forwarding + +Chatterbox allows you to, at will, fast-forward past content strings. This is handy for games with a ton of content, or with a lot of replayability value as it allows players to skip past things they've seen before. Fast-forwarding will speed allow, skipping content strings, until hitting one of the following: + +1. The end of a Chatterbox or `<>` + +2. An option `->` + +3. A `<>` action + +Fast-forwarding is typically triggered by calling `ChatterboxFastForward()` but you may also find it useful to trigger a fast-forward from YarnScript. You can do this using `<>` in YarnScript as you would other actions. + +You can also turn fast-forwarding off from inside YarnScript as well; this is done with the `<>` action. Content **after** `<>` will still appear but any content between triggering fast-forwarding and `<>` will not appear. \ No newline at end of file diff --git a/docs/2.17/getting-started.md b/docs/2.17/getting-started.md new file mode 100644 index 00000000..4b68caa6 --- /dev/null +++ b/docs/2.17/getting-started.md @@ -0,0 +1,279 @@ +# Getting Started + +The Chatterbox library is built around little digital machines, called chatterboxes, that interpret narrative instructions stored in external files using a language called YarnScript. A chatterbox processes YarnScript and spits out text (called **content**) and sometimes a list of **options**. You can control these chatterbox machines by calling ["flow control" functions](reference-flow) using GML from your game, and this is how you communicate player decisions to chatterboxes. + +Chatterbox itself does little more than hand you lines of text that you can draw to the screen, but you are entirely responsible for determining how to draw that text. Equally, chatterboxes do no processing unless you specifically call a function to tell them to do something. Chatterbox execution is "synchronous" - when you tell a chatterbox to do something, it'll do it immediately. You can build functionality to make some behaviour asynchronous if you'd like but that is not a native feature. + +Chatterbox offers a lot of ways to [configure](reference-configuration) the way it works so that it can adapt to varied use cases, and has many functions available to otherwise interact with YarnScript data. This guide is intended to demonstrate basic usage for simple visual novel-style dialogue delivery which is generally applicable across most games. + +  + +## YarnScript + +As mentioned, chatterboxes read instructions written in a language called YarnScript. You can find detailed information about Chatterbox's implementation of YarnScript [here](concept-yarn-script). YarnScript files are made out of nodes, and nodes contain lines of instructions. Every node in a YarnScript file has a unique name, and node names cannot contain spaces. You can also attach metadata to nodes should you wish, though we won't cover that in this particular guide. Beyond requiring a certain structure, YarnScript files themselves are "just text files" and you can edit them by hand if needed. + +?> We recommend that you use the free visual edtior [Crochet](https://github.com/FaultyFunctions/Crochet) developed by [FaultyFunctions](https://twitter.com/faultyfunctions/). Crochet removes a lot of the organisational hurdles of writing YarnScript and gets you straight to writing dialogue. + +YarnScript is a procedural language just like GML. Instructions start at the top of a node and are executed from top to bottom, one at a time. Let's presume we've got Chatterbox set up for operation in "singleton mode" where each line of dialogue is delivered one-by-one, like any number of visual novels or RPGs. If we write out the following YarnScript in a node like so: + +```yarn +This is the first line. +A second line. +And, finally, a third line. +``` + +...then what we'll get in Chatterbox is three separate lines of text in the order that we wrote them. Straightforward lines of text to be displayed to the player are called **content**. Lines of dialogue typically comprise the majority of a node. We'll discuss later how to actually read **content** strings in GML. + +!> Once chatterbox reaches the end of a node it puts the chatterbox into a stopped state. If you want a node to flow into another node automatically you should use the `<>` action, explained a little later in this guide. + +YarnScript also supports **options**. Options come in blocks and you can have any number of options in a block which means you can have a single-choice option block if you'd like. Options work similarly to a line of dialogue but have a `->` little arrow at the start of the line. + +```yarn +Where would you like to go today? +-> To the shops. +-> To outer space. +Very well! Let's go. +``` + +You can choose to show dialogue after an option too. Dialogue that is indented and placed immediately following an option will only be shown if the player chooses that option and that option alone. In the following example, an appropriate response is scripted to appear after the player chooses an option. Note that the final line of dialogue will be shown regardless of which option the player chose. + +```yarn +Where would you like to go today? +-> To the shops. + Yes, I'm hungry too. +-> To outer space. + Have you packed your spacesuit? +Very well! Let's go. +``` + +You can also nest options, again using indentation to indicate the structure of the branching dialogue. + +```yarn +Where would you like to go today? +-> To the shops. + Yes, I'm hungry too. +-> To outer space. + Have you packed your spacesuit? + -> No... + We'll have to swing by the shops then. + -> Sure have! +Very well! Let's go. +``` + +One last thing before we talk about the GML-side implementation of Chatterbox - actions. Actions are neither **content** nor **options** and represent either flow control for the YarnScript, or a way to execute code that can affect the rest of your game. You'll always see actions written in `<<` angle brackets `>>`. For example: + +```yarn +Where would you like to go today? +-> To the shops. + Yes, I'm hungry too. + <> +-> To outer space. + Have you packed your spacesuit? + -> No... + We'll have to swing by the shops then. + <> + -> Sure have! + <> +Very well! Let's go. +<> +``` + +This example demonstrates a couple of more advanced concepts - the `<>` action which is used to set the value of Chatterbox variables, and the `<>` action which is used to navigate between nodes. We'll go into depth for these two actions (they're very useful) further on. + +  + +## GML Implementation + +Chatterbox requires a little setup inside GameMaker before you can start interacting with your YarnScript. There are a few steps to start things up, and we'll go through them in detail, but here's an overview: + +1. Import the Chatterbox .yymps into your project +2. Call `ChatterboxLoadFromFile()` to load the YarnScript source file from Included Files +3. Call `ChatterboxCreate()` to create a new chatterbox to manage YarnScript processing +4. Call various [flow control](reference-flow) functions to navigate your dialogue +5. Extract [content](reference-content-getters) and [option](reference-option-getters) strings from the chatterbox + +### 1. Importing Chatterbox + +Chatterbox is distributed as a .yymps file. This is a compressed file (literally a .zip!) that contains all the GML code that Chatterbox needs to run. You can find the latest release [here](https://github.com/JujuAdams/Chatterbox/releases) and it can be imported via the `Tools` dropdown menu then `Import Local Pakage`. Generally, you'll want to be on the latest stable version. You can always check what version you're using by checking the debug log - Chatterbox outputs its version on boot - or by reading the value of the `__CHATTERBOX_VERSION` macro. Make sure to import all the assets in the .yymps! + +### 2. Loading your YarnScript source file + +Before you can create a chatterbox you'll need to load in a YarnScript file. Make sure you've added a source file to GameMaker as an "Included File" by saving it to the `\datafiles` directory in your project files. Loading that file is then as simple as calling `ChatterboxLoadFromFile()` targeting that specific filename: + +```gml +/// Create event for an object +ChatterboxLoadFromFile("example.yarn"); +``` + +Once a source file has been loaded it can be accessed from anywhere by a chatterbox. You will encounter errors if a source file has not been loaded and you try to use it so be careful how you structure your YarnScript. + +?> The first file that you load becomes the "default" source file for Chatterbox. + +!> Chatterbox parses and compiles YarnScript files when loaded for better performance later; as a result, you may find that there's a short hang when loading large YarnScript files. You should try to load YarnScript files during a loading screen to minimise disruption to the user experience. + +### 3. Initializing a chatterbox + +Now that a YarnScript source file has been loaded, we can spin up a chatterbox and start navigating dialogue. Here's how: + +```gml +/// Create event for an object +ChatterboxLoadFromFile("example.yarn"); +chatterbox = ChatterboxCreate(); +ChatterboxJump(chatterbox, "StartNode"); +``` + +It's very important to hold a reference to the chatterbox that gets created by `ChatterboxCreate()` as you'll need it for all other API functions. In this case, because we've only loaded one source file, we don't need to specify a file for `ChatterboxCreate()`. If you load more than one file you'll need to tell `ChatterboxCreate()` which file to start reading from. `ChatterboxCreate()` can be further customised by setting values for its optional arguments, and you can read more about what those do [here](reference-chatterboxes). + +### 4. Flow control + +Flow control functions are the way that you as a developer control how Chatterbox moves around inside a YarnScript file. You can see a full list of flow control functions [here](reference-flow). + +`ChatterboxJump()`, used above in the GML example, is one of these "flow control" functions, and is analogous to the `<>` action that's available for use in YarnScript itself. Whenever either the GML function or the YarnScript action are called, a chatterbox will jump to the specified node and start processing instruction from the top of that node. + +In singleton mode, the default processing mode for Chatterbox, each line of content is delivered one at a time. This means that after processing each line of dialogue (and if there are no options that come after that line of dialogue) a chatterbox will enter a "waiting" state. You can detect when a chatterbox is waiting by using the `ChatterboxIsWaiting()` function. In order to get a chatterbox to proceed onto the next line of dialogue, you must call the `ChatterboxContinue()` function. + +?> If you are not in singleton mode, you can force a chatterbox to wait at a particular line by using the `<>` action in YarnScript. + +As just mentioned, a chatterbox **won't** enter into a "waiting" state if there are any options that might need to be selected. If a chatterbox is waiting for an option to be selected, `ChatterboxContinue()` will do nothing. Instead, you should call `ChatterboxSelect()` to indicate which option the player has chosen. You can check how many options are being presented to the player with the `ChatterboxGetOptionCount()` function. This function will return `0` if no option are present, and any number greater than `0` indicates that the chatterbox is waiting for user input. + +Finally, you can completely stop processing in a chatterbox using `ChatterboxStop()`, which is also analogous to the `<>` command that can be used in YarnScript itself. A stopped chatterbox will return no content nor options. If a chatterbox reaches the end of a node and there are no more instructions to run, it'll enter into this "stopped" state. You can check if a chatterbox has stopped using the `ChatterboxIsStopped()` GML function. You can use `ChatterboxJump()` to restart a chatterbox if stopped, should you wish to. + +Here's an example of how to set up very simple user input, taken from the basic example in the GitHub repo. + +```gml +if (ChatterboxIsStopped(box)) +{ + //If we're stopped then don't respond to user input +} +else if (ChatterboxIsWaiting(box)) +{ + //If we're in a "waiting" state then let the user press to advance dialogue + if (keyboard_check_released(vk_space)) + { + ChatterboxContinue(box); + } +} +else +{ + //If we're not waiting then we have some options! + //Check for any keyboard input + var _index = undefined; + if (keyboard_check_released(ord("1"))) _index = 0; + if (keyboard_check_released(ord("2"))) _index = 1; + if (keyboard_check_released(ord("3"))) _index = 2; + if (keyboard_check_released(ord("4"))) _index = 3; + + //If we've pressed a button, select that option + if (_index != undefined) ChatterboxSelect(box, _index); +} +``` + +### 5. Drawing chatterbox text + +Chatterbox is, ultimately, a string delivery device with some clever logic attached to it. You are responsible for marshalling, queuing, and displaying text that Chatterbox returns. To this end, the output functions that are available in Chatterbox are very simple. They're split into two kinds: **content** and **options**. + +Content is plain text that is intended to be displayed to the player for them to read. You might want to come up with your own text formatting system or a particular syntax for controlling the details of text rendering, but to Chatterbox, all content is plain text. In singleton mode, the default setting for Chatterbox, you should only receive one content string at a time which correlates to each individiual line of text in a YarnScript node. Regardless, you can find the number of content strings that a chatterbox is handing over to you by using `ChatterboxGetContentCount()` and you can read each individual piece of content using `ChatterboxGetContent()`. + +?> In non-singleton mode, you may receive many content strings at a time. Each line of text will be returned as a separate content string. If you're intending on displaying multiple lines of text using newlines, you may want to consider using `ChatterboxGetAllContentString()` to return a block of text. + +Similarly, options are also plain text. You can get the total number of options using `ChatterboxGetOptionCount()` and the text for each individual option with `ChatterboxGetOption()`. Options strings may be returned by a chatterbox at the same time as content strings depending on the layout of your YarnScript. Please read the previous section for more details. + +Exactly how and where you present content and options is up to you. Radial menu? Scrollable list? Roulette wheel? The choice is yours. Here's a very basic example of how to display content and options together taken from the basic example in the GitHub repo: + +```gml +var _x = 10; +var _y = 10; + +if (ChatterboxIsStopped(chatterbox)) +{ + //If we're stopped then show that + draw_text(_x, _y, "(Chatterbox stopped)"); +} +else +{ + //Draw all content + var _i = 0; + repeat(ChatterboxGetContentCount(chatterbox)) + { + var _string = ChatterboxGetContent(chatterbox, _i); + draw_text(_x, _y, _string); + _y += string_height(_string); + ++_i; + } + + _y += 30; //Bit of spacing... + + if (ChatterboxIsWaiting(chatterbox)) + { + //If we're in a "waiting" state then prompt the user for basic input + draw_text(_x, _y, "(Press Space)"); + } + else + { + //Draw all options + var _i = 0; + repeat(ChatterboxGetOptionCount(chatterbox)) + { + var _string = ChatterboxGetOption(chatterbox, _i); + draw_text(_x, _y, string(_i+1) + ") " + _string); + _y += string_height(_string); + ++_i; + } + } +} +``` + +  + +## Further YarnScript features + +YarnScript is considerably more complex than showing content and options and navigating through branching dialogue. YarnScript offers you variables, conditional logic, metadata, string insertion and [so much more](concept-yarn-script). I'd like to highlight a couple key features here, ones that are uniquely helpful when writing interactive storylines for your game. + +Firstly, the `<>` action allows you to move between nodes in a YarnScript source file. The syntax for this action is `<>`. You can also jump to a node whose name is stored in a variable (and we saw an example of this earlier) by simply inserting the variable into the action, like so: `<>` where `$nodeVariable` is the variable that holds the name of the node to jump to. + +There's more, however! `<>` can also allow you to jump to a node in a _different_ source file entirely. You must have previously loaded the source file into memory using `ChatterboxLoadFromFile()`, and you can jump to a node into another file using this syntax: `<>`. If you want to jump to node outside the current source file then you **must** specify the filename. + +?> Remember, node names must be unique _within_ a YarnScript file. Node names are allowed to collide _between_ source files. This is useful for templating character interactions. + +The other powerful feature I'd like to talk about is **Chatterbox variables**. These will be familiar to you if you've done really any work with GML. Chatterbox variables have a few special rules, however, and are a little stricter than their GML counterparts. + +1. Chatterbox variables must be prefixed with `$` in YarnScript. +2. Chatterbox variables are globally scoped. You can access them at any point anywhere in YarnScript (`$variableName`) and GML (`ChatterboxVariableGet()`) +3. Chatterbox variables are sandboxed. You can only access them using Chatterbox functions. +4. Chatterbox variables should be declared before use, either using YarnScript (`<>`) or GML (`ChatterboxVariableDefault()`). Variable declarations are important because they ensure type safety and that all Chatterbox variables have legal default value. +5. Chatterbox variables must only be strings, numbers, or booleans. Complex types are not permitted. + +When working with YarnScript, you can set variables using the `<>` action e.g. `<>`. This is already useful, but the real power with variables can be found in conditional logic - the almighty `<>` action and its siblings `<>` `<>` and `<>`. + +`<>` is a special kind of action that performs flow control inside a node. Again, if you've written much GML, an if-statement will not be alien to you and YarnScript works in exactly the same way. + +```yarn +<> + Five cat plan in three cats! +<= 5>> + I think you have enough cats already. +<> + More cats might help you on your journey. +<> +``` + +We can also apply `<>` actions to options, allowing more intelligent options to be shown to the player. + +```yarn +Have you packed your spacesuit? +-> No... <> + We'll have to swing by the shops then. + <> +-> Sure have! <> + <> +``` + +As per the YarnScript specification, all options will made available **regardless of whether the if-statement returns `true` or `false`**. This is unexpected behaviour but it does give you more control over how you communicate failed conditions e.g. showing options that are unavailable due to a low charisma stat and so on. To determine whether to display an option or not to a player you can call `ChatterboxGetOptionConditionBool()` which tells you the state of the associated condition. + +Variables allow you to branch dialogue in response to a value that you're tracking, and that value will be reacting to decisions that the player has made. With a little effort, you could write an entire game in YarnScript with a very simple GameMaker program wrapped around it. + +  + +## Closing thoughts + +Chatterbox is a powerful tool and we've only scratched the surface. Please take the time to poke around the rest of the documentation and, if you have any questions, please swing by the [Discord server](https://discord.gg/8krYCqr). \ No newline at end of file diff --git a/docs/2.17/reference-chatterboxes.md b/docs/2.17/reference-chatterboxes.md new file mode 100644 index 00000000..b72dd6df --- /dev/null +++ b/docs/2.17/reference-chatterboxes.md @@ -0,0 +1,82 @@ +# Chatterboxes + +Functions on this page relate to chatterboxes, the basic machines that use source files as input and output strings of text that you can display in your game. Most functions on this page are prefixed with `Chatterbox`. + +  + +## `ChatterboxCreate()` + +_Full function name:_ `ChatterboxCreate([filename], [singletonText]), [localScope])` + +_Returns:_ A new [chatterbox](concept-chatterboxes) + +|Name |Datatype |Purpose | +|-----------------|---------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +|`[filename]` |string |[Source file](concept-source-files) to target. If not specified, the default [source file](concept-source-files) will be used (the first [source file](concept-source-files) that was [loaded](reference-configuration#chatterboxloadfromfilefilename-aliasname) into Chatterbox)| +|`[singletonText]`|boolean |Whether content is revealed one line at a time (see below). If not specified, [`CHATTERBOX_DEFAULT_SINGLETON`](reference-configuration#__chatterboxconfig) is used instead | +|`[localScope]` |instance/struct|Scope to execute Yarn function calls in | + +If `singletonText` is set to `true` then dialogue will be outputted one line at a time. This is typical behaviour for RPGs like Pokémon or Final Fantasy where characters talk one at a time. Only one piece of dialogue will be shown at a time. + +However, if `singletonText` is set to `false` then dialogue will be outputted multiple lines at a time. More modern narrative games, especially those by Inkle or Failbetter, tend to show larger blocks of text. Content will be stacked up until Chatterbox reaches a command that requires user input: a shortcut, an option, or a `<>` or `<>` command. + +  + +## `IsChatterbox(value)` + +_Full function name:_ `IsChatterbox(value)` + +_Returns:_ Boolean, whether the given value is a [chatterbox](concept-chatterboxes) + +|Name |Datatype|Purpose | +|-------|--------|------------------| +|`value`|any |The value to check| + +  + +## `...GetVisited()` + +_Full function name:_ `ChatterboxGetVisited(nodeTitle, filename)` + +_Returns:_ Number, how many times the given node has been visited + +|Name |Datatype|Purpose | +|----------|--------|--------------------------------------------------------| +|`nodeTile`|string |Name of the node to check | +|`filename`|string |Name of the [source file](concept-source-files) to check| + +  + +## `...GetCurrent()` + +_Full function name:_ `ChatterboxGetCurrent(chatterbox)` + +_Returns:_ String, the name of the node that the given [chatterbox](concept-chatterboxes) is currently on + +|Name |Datatype |Purpose | +|------------|----------------------------------|------------------------------------------------| +|`chatterbox`|[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target| + +  + +## `...GetCurrentMetadata()` + +_Full function name:_ `ChatterboxGetCurrentMetadata(chatterbox)` + +_Returns:_ Array, the metadata associated with the node + +|Name |Datatype |Purpose | +|------------|----------------------------------|------------------------------------------------| +|`chatterbox`|[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target| + +  + +## `...GetCurrentSource()` + +_Full function name:_ `ChatterboxGetCurrentSource(chatterbox)` + +_Returns:_ String, the name of the source that the given [chatterbox](concept-chatterboxes) is currently on + +|Name |Datatype |Purpose | +|------------|----------------------------------|------------------------------------------------| +|`chatterbox`|[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target| \ No newline at end of file diff --git a/docs/2.17/reference-configuration.md b/docs/2.17/reference-configuration.md new file mode 100644 index 00000000..eb190537 --- /dev/null +++ b/docs/2.17/reference-configuration.md @@ -0,0 +1,285 @@ +# Configuration + +The `__ChatterboxConfig()` script contains a multitude of macros that you can use to customise the behaviour of Chatterbox. `__ChatterboxConfig()` never needs to be directly called in code, but the script and the macros it contains must be present in a project for Chatterbox to work. + +!> You should edit `__ChatterboxConfig()` to customise Chatterbox for your own purposes. + +  + +## `CHATTERBOX_DEFAULT_SINGLETON` + +_Typical value:_ `true` + +Whether chatterboxes should default to being singleton. + +  + +## `CHATTERBOX_ALLOW_SCRIPTS` + +_Typical value:_ `true` + +Whether to allow scripts to be added as Chatterbox functions. + +  + +## `CHATTERBOX_FUNCTION_ARRAY_ARGUMENTS` + +_Typical value:_ `true` + +Whether to execute callbacks with an array of arguments. Setting this to `false` will execute callbacks with individual arguments. + +  + +## `CHATTERBOX_SINGLETON_WAIT_BEFORE_OPTION` + +_Typical value:_ `false` + +Whether a chatterbox will enter into a waiting state before options are enumerated. + +  + +## `CHATTERBOX_WAIT_BEFORE_STOP` + +_Typical value:_ `true` + +Whether a chatterbox will enter into a waiting state before a chatterbox goes into a `<>` state. + +  + +## `CHATTERBOX_VERBOSE` + +_Typical value:_ `false` + +Whether Chatterbox will send lots of potentially useful debug information to the output log. You may find this debug information distracting, especially after you get more comfortable with Chatterbox, so you may want to set this macro to `false` to clean up your debug log. Warning messages are not turned off by `CHATTERBOX_VERBOSE`. + +  + +## `CHATTERBOX_REPLACE_ALIAS_BACKSLASHES` + +_Typical value:_ `true` + +Set to `true` to automatically replace backslashes `\` in paths for forward slashes `/`. This standardises path references making a number of path-related arguments consistent across many Chatterbox functions. Setting this macro to `false` will turn off slash replacement and may result in, for example, files being reported as non-existent or not loaded. + +  + +## `CHATTERBOX_KEYWORD_OPERATORS` + +_Typical value:_ `true` + +Whether to allow use of keyword operators. Setting this macro to `true` will enable use of the following operators as keywords: + +|Keyword|Operator| +|-------|--------| +|`and` |`&&` | +|`le` |`<` | +|`lt` |`<` | +|`ge` |`>` | +|`gt` |`>` | +|`or` |`||` | +|`lte` |`<=` | +|`gte` |`>=` | +|`leq` |`<=` | +|`geq` |`>=` | +|`eq` |`==` | +|`is` |`==` | +|`neq` |`!=` | +|`to` |`=` | +|`not` |`!` | + +  + +## `CHATTERBOX_SHOW_REJECTED_OPTIONS` + +_Typical value:_ `true` + +Whether to expose options whose conditional check has failed. Setting this to `false` will never expose rejected options. + +  + +## `CHATTERBOX_END_OF_NODE_HOPBACK` + +_Typical value:_ `true` + +Whether nodes without an explicit `<>` or `<>` instruct at the end should default to `<>`. Legacy behaviour (pre-2.7) is to set this to `false`. + +  + +## `CHATTERBOX_ACTION_MODE` + +_Typical value:_ `1` + +`CHATTERBOX_ACTION_MODE` should be either 0, 1, or 2: + +- `0` Pass YarnScript actions as a raw string to a function, defined by `CHATTERBOX_ACTION_FUNCTION` +- `1` Treat actions as expressions +- `2` Treat actions as they were in version 1 (Python-esque function calls) + +### `CHATTERBOX_ACTION_MODE` = 0 + +This is the officially recommended behaviour. The full contents of the direction (everything between `<<` and `>>`) are passed as a string to a function for parsing and execution by the developer (you). I think this behaviour is stupid but I've included it here because technically that is what the YarnScript specification says. You can set the function that receives the direction string by setting `CHATTERBOX_ACTION_FUNCTION`. Exactly what syntax you use for actions is therefore completely up to you. + +### `CHATTERBOX_ACTION_MODE` = 1 + +Chatterbox will treat actions as expressions to be executed in a similar manner to in-line expressions. This is covenient if you want to treat actions as little snippets of code that Chatterbox can run. Syntax for actions becomes the same as in-line expressions, which is broadly similar to "standard" GML syntax. Functions that you wish to execute must be added by calling ChatterboxAddFunction(). An example would be: `<>` + +### `CHATTERBOX_ACTION_MODE` = 2 + +Chatterbox will treat actions as expressions with a greatly simplified syntax. This is useful for writers and narrative designers who are less familiar with the particulars of coding and instead want to use a simple syntax to communicate with the underlying GameMaker application. The direction is sliced into arguments using spaces as delimiters. The first token in the direction is the name of the function call, as added by `ChatterboxAddFunction()`. Subsequent tokens are passed to the function call with each token being a function parameter. All parameters are passed as strings. If a parameter needs to contain a space then you may enclose the string in `"` double quote marks. An example, analogous to the example above, would be: `<>`. + +  + +## `CHATTERBOX_DIRECTION_FUNCTION` + +_Typical value:_ `ExampleActionFunction` + +Function to use to handle actions. This only applies in mode `0` (see below). + +  + +## `CHATTERBOX_END_OF_NODE_HOPBACK` + +_Typical value:_ `true` + +Whether nodes without an explicit `<>` or `<>` command at the end should default to `<>`. Legacy behaviour (pre-2.7) is to set this to `false`. + +  + +### `CHATTERBOX_SPEAKER_DELIMITER` + +_Typical value:_ `":"` + +Character that separates speaker (and speaker data) from speech. This can be any arbitrary string, potentially composed of multiple characters. Please see the [speakers documentation](concept-metadata-and-speakers?id=speakers) for more information. + +  + +## `CHATTERBOX_SPEAKER_DATA_START` + +_Typical value:_ `"["` + +Character that indicates where the speaker data string starts. This can be any arbitrary string, potentially composed of multiple characters. Please see the [speakers documentation](concept-metadata-and-speakers?id=speakers) for more information. + +  + +## `CHATTERBOX_SPEAKER_DATA_END` + +_Typical value:_ `"]"` + +WCharacter that indicates where the speaker data string ends. This can be any arbitrary string, potentially composed of multiple characters. Please see the [speakers documentation](concept-metadata-and-speakers?id=speakers) for more information. + +  + +### `CHATTERBOX_ESCAPE_FILE_TAGS` + +_Typical value:_ `true` + +Whether file metadata tags are [escaped](https://en.wikipedia.org/wiki/Escape_character). + +  + +## `CHATTERBOX_ESCAPE_NODE_TAGS` + +_Typical value:_ `true` + +Whether node metadata tags are [escaped](https://en.wikipedia.org/wiki/Escape_character). + +  + +## `CHATTERBOX_ESCAPE_CONTENT` + +_Typical value:_ `true` + +Whether content strings are [escaped](https://en.wikipedia.org/wiki/Escape_character). + +  + +## `CHATTERBOX_ESCAPE_EXPRESSION_STRINGS` + +_Typical value:_ `false` + +Whether expression strings are [escaped](https://en.wikipedia.org/wiki/Escape_character). + +  + +## `CHATTERBOX_INCLUDED_FILES_SUBDIRECTORY` + +_Typical value:_ `""` (empty string) + +Directory inside Included Files that holds all external `.yarn` files. Use an empty string for the root of Included Files. + +  + +## `CHATTERBOX_DECLARE_ON_COMPILE` + +_Typical value:_ `true` + +Whether to declare variables when Chatterbox script is compiled. Set to `false` for legacy (2.1 and earlier) behaviour. + +  + +## `CHATTERBOX_LEGACY_WEIRD_OPERATOR_PRECEDENCE` + +_Typical value:_ `false` + +  + +## `CHATTERBOX_INDENT_TAB_SIZE` + +_Typical value:_ `4` + +Size of tabs for YarnScript input. + +  + +## `CHATTERBOX_FILENAME_SEPARATOR` + +_Typical value:_ `":"` + +Separator to use to concatenate filenames to node names, used to reference nodes in other source files. + +  + +## `CHATTERBOX_ERROR_NONSTANDARD_SYNTAX` + +_Typical value:_ `true` + +Whether to throw an error when using a reasonable, though technically incorrect, syntax e.g. `<>` or `<>`. + +  + +## `CHATTERBOX_ERROR_UNDECLARED_VARIABLE` + +_Typical value:_ `true` + +Throws an error when trying to set a variable that has not been declared (either using `<>` or `ChatterboxVariableDefault()`). + +  + +## `CHATTERBOX_ERROR_UNSET_VARIABLE` + +_Typical value:_ `true` + +Throws an error when trying to read a variable that doesn't exist. + +  + +## `CHATTERBOX_ERROR_REDECLARED_VARIABLE` + +_Typical value:_ `true` + +Throws an error when trying to redeclare a variable (either using `<>` or `ChatterboxVariableDefault()`). + +  + +## `CHATTERBOX_ERROR_NO_LOCAL_SCOPE` + +_Typical value:_ `true` + +Throws an error when trying to execute a function without a local scope being available. + +  + +## `CHATTERBOX_VARIABLE_MISSING_VALUE` + +_Typical value:_ `0` + +Value to return from a variable that doesn't exist. This is only relevant if `CHATTERBOX_ERROR_UNSET_VARIABLE` is `false` and the `default` argument for `ChatterboxVariableGet()` has not been specified. diff --git a/docs/2.17/reference-content-getters.md b/docs/2.17/reference-content-getters.md new file mode 100644 index 00000000..5c0829a3 --- /dev/null +++ b/docs/2.17/reference-content-getters.md @@ -0,0 +1,149 @@ +# Content Getters + +Functions on this page relate to getting content data from a chatterbox. All functions on this page are prefixed with `ChatterboxGet`. + +  + +## `...Content()` + +_Full function name:_ `ChatterboxGetContent(chatterbox, contentIndex)` + +_Returns:_ String, content with the given index + +|Name |Datatype |Purpose | +|--------------|----------------------------------|------------------------------------------------| +|`chatterbox` |[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target| +|`contentIndex`|integer |Content item to return | + +  + +## `...AllContentString()` + +_Full function name:_ `ChatterboxGetAllContentString(chatterbox, [separator])` + +_Returns:_ String, all individual content strings currently available in a chatterbox concatenated together, with a separator substring between each one + +|Name |Datatype |Purpose | +|-------------|----------------------------------|---------------------------------------------------------------------------------------------------| +|`chatterbox` |[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target | +|`[separator]`|string |String to use to separate individual content strings. Defaults to a single newline character (`\n`)| + +?> This function is intended for use with singleton mode **turned off**. If you use this function in singleton mode then it will only return one content string at a time. + +  + +## `...ContentMetadata()` + +_Full function name:_ `ChatterboxGetContentMetadata(chatterbox, contentIndex)` + +_Returns:_ Array, the metadata tags associated with the content + +|Name |Datatype |Purpose | +|--------------|----------------------------------|------------------------------------------------| +|`chatterbox` |[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target| +|`contentIndex`|integer |Content item to return | + +  + +## `...ContentCount()` + +_Full function name:_ `ChatterboxGetContentCount(chatterbox)` + +_Returns:_ Integer, the total number of content strings in the given [chatterbox](concept-chatterboxes) + +|Name |Datatype |Purpose | +|------------|----------------------------------|------------------------------------------------| +|`chatterbox`|[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target| + +  + +## `...ContentSpeech()` + +_Full function name:_ `ChatterboxGetContentSpeech(chatterbox, contentIndex, [default])` + +_Returns:_ String + +|Name |Datatype |Purpose | +|--------------|----------------------------------|---------------------------------------------------------------------------------------------| +|`chatterbox` |[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target | +|`contentIndex`|integer |Content item to return the speech for | +|`[default]` |any |Default value to return if no valid speech is found. If not specified this is an empty string| + +This is an optional function that adds additional helpful parsing capabilities to Chatterbox. For `ChatterboxGetContentSpeech()` to work properly, line of text in your Yarn file should be formatted like so: + +``` +Speaker Name: The words that the speaker is saying. +``` + +In this case, the "speech" part of this string is everything after the colon (`The words that the speaker is saying.`). Any whitespace that leads or follows speech is removed. + +  + +## `...ContentSpeaker()` + +_Full function name:_ `ChatterboxGetContentSpeaker(chatterbox, contentIndex, [default])` + +_Returns:_ String + +|Name |Datatype |Purpose | +|--------------|----------------------------------|---------------------------------------------------------------------------------------------| +|`chatterbox` |[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target | +|`contentIndex`|integer |Content item to return the speaker for | +|`[default]` |any |Default value to return if no valid speech is found. If not specified this is an empty string| + +This is an optional function that adds additional helpful parsing capabilities to Chatterbox. For `ChatterboxGetContentSpeaker()` to work properly, line of text in your Yarn file should be formatted like so: + +``` +Speaker Name: The words that the speaker is saying. +``` + +In this case, the "speaker" part of this string is everything before the colon (`Speaker Name`). Any whitespace that leads or follows the speaker name is removed. In the next example, "speaker data" is added to the line of text. + +``` +Speaker Name[additional speaker data]: The words that the speaker is saying. +``` + +The speaker part of this string is everything before the speaker data start symbol (see below), which is again `Speaker Name`. + +  + +## `...ContentSpeakerData()` + +_Full function name:_ `ChatterboxGetContentSpeakerData(chatterbox, contentIndex, [default])` + +_Returns:_ String + +|Name |Datatype |Purpose | +|--------------|----------------------------------|---------------------------------------------------------------------------------------------| +|`chatterbox` |[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target | +|`contentIndex`|integer |Content item to return the speaker data for | +|`[default]` |any |Default value to return if no valid speech is found. If not specified this is an empty string| + +This is an optional function that adds additional helpful parsing capabilities to Chatterbox. For `ChatterboxGetContentSpeakerData()` to work properly, line of text in your Yarn file should be formatted like so: + +``` +Speaker Name[additional speaker data]: The words that the speaker is saying. +``` + +In this case, the "speaker data" part of this string is everything between `[` and `]` (`additional speaker data`). Any whitespace that leads or follows the speaker data is removed. The symbols used to define where speaker data is stored is controlled by the `CHATTERBOX_SPEAKER_DATA_START` and `CHATTERBOX_SPEAKER_DATA_END` macros. Speaker data must follow the speaker's name and precede the colon that separates the speaker from the speech. If no speaker data is found, the provided default value is returned. + +  + +## `...ContentArray()` + +_Full function name:_ `ChatterboxGetContentArray(chatterbox)` + +_Returns:_ Array, containing one struct (see below) for each available content string for the given chatterbox + +|Name |Datatype |Purpose | +|--------------|----------------------------------|------------------------------------------------| +|`chatterbox` |[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target| + +The returned array is populated in canonical order: the 0th element of the array is equivalent to `ChatterboxGetContent(chatterbox, 0)` etc. Each struct in the array has this format: + +|Member Variable|Purpose | +|---------------|-----------------------------------------------------| +|`.text` |The text for the content string | +|`.metadata` |An array of metadata tags associated with the content| + +?> This function is intended for use with singleton mode **turned off**. If you use this function in singleton mode then it will only return one struct at a time. \ No newline at end of file diff --git a/docs/2.17/reference-flow.md b/docs/2.17/reference-flow.md new file mode 100644 index 00000000..05395458 --- /dev/null +++ b/docs/2.17/reference-flow.md @@ -0,0 +1,134 @@ +# Flow Control + +Functions on this page relate to controlling the flow of a chatterbox as it progresses through YarnScript. All functions on this page are prefixed with `Chatterbox`. + +  + +## `...Jump()` + +_Full function name:_ `ChatterboxJump(chatterbox, nodeTitle, [filename])` + +_Returns:_ N/A (`undefined`) + +|Name |Datatype |Purpose | +|------------|----------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +|`chatterbox`|[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target | +|`nodeTitle` |string |Name of the node to jump to | +|`[filename]`|string |[Source file](concept-source-files) to target. If not specified, the current [source file](concept-source-files) for the [chatterbox](concept-chatterboxes) will be used| + +This function jumps to a specific node in a [source file](concept-source-files). + +  + +## `...Select()` + +_Full function name:_ `ChatterboxSelect(chatterbox, optionIndex)` + +_Returns:_ N/A (`undefined`) + +|Name |Datatype |Purpose | +|-------------|----------------------------------|-------------------------------------------------------------------------------------------------------------------------| +|`chatterbox` |[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target | +|`optionIndex`|integer |Option to select, as detailed by [`chatterbox_get_option()`](reference-getters#chatterboxgetoptionchatterbox-optionindex)| + +This function selects an option as defined by a Yarn shortcut (`->`). + +  + +## `...Continue()` + +_Full function name:_ `ChatterboxContinue(chatterbox)` + +_Returns:_ N/A (`undefined`) + +|Name |Datatype |Purpose | +|------------|----------------------------------|------------------------------------------------| +|`chatterbox`|[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target| + +Advances dialogue in a chatterbox that's "waiting", either due to a Yarn `<>` command, calling `ChatterboxWait()` or singleton behaviour. + +  + +## `...Hop()` + +_Full function name:_ `ChatterboxHop(chatterbox, nodeTitle, [filename])` + +_Returns:_ N/A (`undefined`) + +|Name |Datatype |Purpose | +|------------|----------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +|`chatterbox`|[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target | +|`nodeTitle` |string |Name of the node to jump to | +|`[filename]`|string |[Source file](concept-source-files) to target. If not specified, the current [source file](concept-source-files) for the [chatterbox](concept-chatterboxes) will be used| + +This function pushes the current node (and position in the node) to an internal stack, and then jumps to a specific node in a [source file](concept-source-files). You can then hop back to where you left off by calling `ChatterboxHopBack()`. + +!> The hop stack is not available to be manually accessed or modified. The hop stack cannot be exported or imported. You should not rely on the hop stack to exist if you're handling savedata. + +  + +## `...HopBack()` + +_Full function name:_ `ChatterboxHopBack(chatterbox)` + +_Returns:_ N/A (`undefined`) + +|Name |Datatype |Purpose | +|------------|----------------------------------|------------------------------------------------| +|`chatterbox`|[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target| + +This function pops a node and position from the internal stack, and then jumps to that specific node and position. Please see `ChatterboxHop()` above for more information. + +  + +## `...Wait()` + +_Full function name:_ `ChatterboxWait(chatterbox)` + +_Returns:_ N/A (`undefined`) + +|Name |Datatype |Purpose | +|------------|----------------------------------|------------------------------------------------| +|`chatterbox`|[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target| + +Forces a chatterbox to wait at the current instruction. This is similar to returning `"<>"` from a function called by an `<>`. + +?> When calling this function it's often useful to know the current chatterbox that's being executed. You can access the current chatterbox by using the `CHATTERBOX_CURRENT` macro. + +  + +## `...IsWaiting()` + +_Full function name:_ `ChatterboxIsWaiting(chatterbox)` + +_Returns:_ Boolean, whether the given [chatterbox](concept-chatterboxes) is in a "waiting" state, either due to a Yarn `<>` command or singleton behaviour + +|Name |Datatype |Purpose | +|------------|----------------------------------|------------------------------------------------| +|`chatterbox`|[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target| + +  + +## `...IsStopped()` + +_Full function name:_ `ChatterboxIsStopped(chatterbox)` + +_Returns:_ Boolean, whether a [chatterbox](concept-chatterboxes) has stopped, either due to a `<>` command or because it has run out of content to display + +|Name |Datatype |Purpose | +|------------|----------------------------------|------------------------------------------------| +|`chatterbox`|[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target| + +  + +## `...FastForward()` + +_Full function name:_ `ChatterboxFastForward(chatterbox)` + +_Returns:_ N/A (`undefined`) + +|Name |Datatype |Purpose | +|------------|----------------------------------|------------------------------------------------| +|`chatterbox`|[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target| + +Essentially a super-charged version of [`ChatterboxContinue()`](reference-flow#chatterboxcontinuechatterbox). Advances dialogue in a chatterbox all the way until the next occasion where the player is prompted to make a decision i.e. where options are being displayed and [`ChatterboxSelect()`](reference-flow#chatterboxselectchatterbox-optionindex) would be used. Fast forwarding ignores `<>` commands; if you'd like to force a fast forwarding chatterbox to wait then please use `<>` instead. diff --git a/docs/2.17/reference-localisation.md b/docs/2.17/reference-localisation.md new file mode 100644 index 00000000..1a840bcb --- /dev/null +++ b/docs/2.17/reference-localisation.md @@ -0,0 +1,50 @@ +# Localisation + +The functions on this page relate to the use of Chatterbox's native localisation implement. Use of these functions is purely optional and you may find using your own solution is preferable. + +Chatterbox's localisation system automates a lot of the process for you. Of particular note is `LocalizationBuild()` which automatically tags every line in your Yarn files with metadata in the format `#line:??????` where the question marks are a unique hash that identifies a line of dialogue. Note that the hash is attached to the _line_ rather than the _text_ and the hash isn't generated based on the content of the line itself. The hash for each line of dialogue indentifies that line of dialogue and allows Chatterbox to replace the original text with new text. + +`LocalizationBuild()` not only writes line metadata into Yarn files but also saves out a CSV file that contains all the lines of dialogue. This CSV file can have its content edited and then loaded back into the game via `ChatterboxLocalizationLoad()` using the aforementioned hashes to identify each line. You can unload the current localisation file by using `ChatterboxLocalizationClear()`. To support multiple different languages you should make many copies of the CSV file (by passing in multiple strings for `csvPathArray`) and edit one CSV for each language. + +If your Yarn file has been edited and is now out of sync with your CSV file(s) then you can re-run `ChatterboxLocalizationBuild()` and target the localised CSV files. The function will mark any adjusted or new lines in the CSV file allowing your localisation team to update the CSV file as necessary. + +  + +## `...LocalizationBuild()` + +_Full function name:_ `ChatterboxLocalizationBuild(yarnPathArray, csvPathArray)` + +_Returns:_ N/A (`undefined`) + +|Name |Datatype |Purpose | +|---------------|----------------|------------------------------------------------------------------------------------| +|`yarnPathArray`|array of strings|Array of paths to Yarn files to build localisation for | +|`csvPathArray` |array of strings|Array of paths to save the resulting localisation CSV to e.g. for multiple languages| + +Adds `#line` metadata to any unmarked lines in the Yarn files specified, and exports a CSV containing all text in the Yarn files (including previously marked lines). If the CSV file already exists it will be modified in place, noting any changed lines. + +!> This function will modify the Yarn files on disk. Ensure you have backed up your work in source control. + +  + +## `...LocalizationLoad()` + +_Full function name:_ `ChatterboxLocalizationLoad(path)` + +_Returns:_ N/A (`undefined`) + +|Name |Datatype|Purpose | +|------|--------|-----------------------------------------| +|`path`|string |Path to the localisation CSV file to load| + +  + +## `...LocalizationClear()` + +_Full function name:_ `ChatterboxLocalizationClear()` + +_Returns:_ N/A (`undefined`) + +|Name|Datatype|Purpose| +|----|--------|-------| +|N/A | | | diff --git a/docs/2.17/reference-option-getters.md b/docs/2.17/reference-option-getters.md new file mode 100644 index 00000000..8c94bc66 --- /dev/null +++ b/docs/2.17/reference-option-getters.md @@ -0,0 +1,165 @@ +# Option Getters + +Functions on this page relate to getting option data from a chatterbox. All functions on this page are prefixed with `ChatterboxGet`. + +  + +## `...Option()` + +_Full function name:_ `ChatterboxGetOption(chatterbox, optionIndex)` + +_Returns:_ String, option with the given index + +|Name |Datatype |Purpose | +|-------------|----------------------------------|------------------------------------------------| +|`chatterbox` |[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target| +|`optionIndex`|integer |Option item to return | + +  + +## `...OptionMetadata()` + +_Full function name:_ `ChatterboxGetOptionMetadata(chatterbox, optionIndex)` + +_Returns:_ String, the metadata tags associated with the option + +|Name |Datatype |Purpose | +|-------------|----------------------------------|------------------------------------------------| +|`chatterbox` |[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target| +|`optionIndex`|integer |Option item to return | + +  + +## `...OptionConditionBool()` + +_Full function name:_ `ChatterboxGetOptionConditionBool(chatterbox, optionIndex)` + +_Returns:_ Boolean, whether the option's if-statement passed + +|Name |Datatype |Purpose | +|-------------|----------------------------------|------------------------------------------------| +|`chatterbox` |[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target| +|`optionIndex`|integer |Option item to return | + +If the option had no if-statement associated with it then this function will always return `true`. + +  + +## `...OptionChosen()` + +_Full function name:_ `ChatterboxGetOptionChosen(chatterbox, optionIndex)` + +_Returns:_ Number, how many times the option has been chosen + +|Name |Datatype |Purpose | +|-------------|----------------------------------|------------------------------------------------| +|`chatterbox` |[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target| +|`optionIndex`|integer |Option item to return | + +If the option has not been chosen at all, this function will return `0`. + +  + +## `...OptionCount()` + +_Full function name:_ `ChatterboxGetOptionCount(chatterbox)` + +_Returns:_ Integer, the total number of option strings in the given [chatterbox](concept-chatterboxes) + +|Name |Datatype |Purpose | +|------------|----------------------------------|------------------------------------------------| +|`chatterbox`|[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target| + +  + +## `...OptionArray()` + +_Full function name:_ `ChatterboxGetOptionArray(chatterbox)` + +_Returns:_ Array, containing one struct (see below) for each available option for the given chatterbox + +|Name |Datatype |Purpose | +|--------------|----------------------------------|------------------------------------------------| +|`chatterbox` |[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target| + +The returned array is populated in canonical order: the 0th element of the array is equivalent to `ChatterboxGetOption(chatterbox, 0)` etc. Each struct in the array has this format: + +|Member Variable |Purpose | +|----------------|--------------------------------------------------------------| +|`.text` |The text for the option | +|`.conditionBool`|Whether the conditional check for this option passed or failed| +|`.metadata` |An array of metadata tags associated with the content | + +  + +## `...OptionSpeech()` + +_Full function name:_ `ChatterboxGetOptionSpeech(chatterbox, optionIndex, [default])` + +_Returns:_ String + +|Name |Datatype |Purpose | +|-------------|----------------------------------|---------------------------------------------------------------------------------------------| +|`chatterbox` |[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target | +|`optionIndex`|integer |Option to return the speaker data for | +|`[default]` |any |Default value to return if no valid speech is found. If not specified this is an empty string| + +This is an optional function that adds additional helpful parsing capabilities to Chatterbox. For `ChatterboxGetOptionSpeech()` to work properly, line of text in your Yarn file should be formatted like so: + +``` +-> Speaker Name: The words that the speaker is saying. +``` + +In this case, the "speech" part of this string is everything after the colon (`The words that the speaker is saying.`). Any whitespace that leads or follows speech is removed. + +  + +## `...OptionSpeaker()` + +_Full function name:_ `ChatterboxGetOptionSpeaker(chatterbox, contentIndex, [default])` + +_Returns:_ String + +|Name |Datatype |Purpose | +|-------------|----------------------------------|---------------------------------------------------------------------------------------------| +|`chatterbox` |[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target | +|`optionIndex`|integer |Option to return the speaker data for | +|`[default]` |any |Default value to return if no valid speech is found. If not specified this is an empty string| + +This is an optional function that adds additional helpful parsing capabilities to Chatterbox. For `ChatterboxGetOptionSpeaker()` to work properly, line of text in your Yarn file should be formatted like so: + +``` +Speaker Name: The words that the speaker is saying. +``` + +In this case, the "speaker" part of this string is everything before the colon (`Speaker Name`). Any whitespace that leads or follows the speaker name is removed. In the next example, "speaker data" is added to the line of text. + +``` +-> Speaker Name[additional speaker data]: The words that the speaker is saying. +``` + +The speaker part of this string is everything before the speaker data start symbol (see below), which is again `Speaker Name`. + +  + +## `...OptionSpeakerData()` + +_Full function name:_ `ChatterboxGetOptionSpeakerData(chatterbox, contentIndex, [default])` + +_Returns:_ String + +|Name |Datatype |Purpose | +|-------------|----------------------------------|---------------------------------------------------------------------------------------------| +|`chatterbox` |[chatterbox](concept-chatterboxes)|The [chatterbox](concept-chatterboxes) to target | +|`optionIndex`|integer |Option to return the speaker data for | +|`[default]` |any |Default value to return if no valid speech is found. If not specified this is an empty string| + +This is an optional function that adds additional helpful parsing capabilities to Chatterbox. For `ChatterboxGetOptionSpeakerData()` to work properly, line of text in your Yarn file should be formatted like so: + +``` +-> Speaker Name[additional speaker data]: The words that the speaker is saying. +``` + +In this case, the "speaker data" part of this string is everything between `[` and `]` (`additional speaker data`). Any whitespace that leads or follows the speaker data is removed. The symbols used to define where speaker data is stored is controlled by the `CHATTERBOX_SPEAKER_DATA_START` and `CHATTERBOX_SPEAKER_DATA_END` macros. Speaker data must follow the speaker's name and precede the colon that separates the speaker from the speech. If no speaker data is found, the provided default value is returned. + +  \ No newline at end of file diff --git a/docs/2.17/reference-setup.md b/docs/2.17/reference-setup.md new file mode 100644 index 00000000..ad86f42f --- /dev/null +++ b/docs/2.17/reference-setup.md @@ -0,0 +1,211 @@ +# Setup + +Functions on this page relate to setting up how Chatterbox loads and interprets source files. All functions on this page are prefixed with `Chatterbox`. + +  + +## `...LoadFromFile()` + +_Full function name:_ `ChatterboxLoadFromFile(filename, [aliasName])` + +_Returns:_ N/A (`undefined`) + +|Name |Datatype|Purpose | +|-------------|--------|-----------------------------------------------------------------------------------------------| +|`filename` |string |Name of the file to load as a [source file](concept-source-files) | +|`[aliasName]`|string |Optional name to use when referencing this file. If not specified, the filename is used instead| + +If you use this function to reload a file (i.e. using the same filename as an existing [source file](concept-source-files)) then all in-progress [chatterboxes](concept-chatterboxes) that were using the previous [source file](concept-source-files) will be invalidated and will need to be restarted. + +  + +## `...LoadFromString()` + +_Full function name:_ `ChatterboxLoadFromString(filename, string)` + +_Returns:_ N/A (`undefined`) + +|Name |Datatype|Purpose | +|-----------|--------|--------------------------------------------------------------------------| +|`aliasName`|string |Name to use to reference the string (the "filename" to use for the string)| +|`string` |string |String to parse as a [source file](concept-source-files) | + +Loads a string as a source file, emulating the [`ChatterboxLoadFromFile()`](reference-configuration#chatterboxloadfromfilefilename-aliasname). The string should be formatted as a `.yarn` file. See the [Source Files](concept-source-files) pages for more information. + +If you use this function to reload a file (i.e. load a buffer using the same filename as an existing [source file](concept-source-files)) then all in-progress [chatterboxes](concept-chatterboxes) that were using the previous [source file](concept-source-files) will be invalidated and will need to be restarted. + +  + +## `...LoadFromBuffer()` + +_Full function name:_ `ChatterboxLoadFromBuffer(filename, buffer)` + +_Returns:_ N/A (`undefined`) + +|Name |Datatype |Purpose | +|-----------|----------------------------------------------------------------------------------------|--------------------------------------------------------------------------| +|`aliasName`|string |Name to use to reference the buffer (the "filename" to use for the buffer)| +|`buffer` |[buffer](https://manual.yoyogames.com/Additional_Information/Guide_To_Using_Buffers.htm)|Buffer to use as a [source file](concept-source-files) | + +Loads a buffer as a source file, emulating the [`ChatterboxLoadFromFile()`](reference-configuration#chatterboxloadfromfilefilename-aliasname). The buffer should contain a single string that is formatted as a `.yarn` file. See the [Source Files](concept-source-files) pages for more information. + +If you use this function to reload a file (i.e. load a buffer using the same filename as an existing [source file](concept-source-files)) then all in-progress [chatterboxes](concept-chatterboxes) that were using the previous [source file](concept-source-files) will be invalidated and will need to be restarted. + +  + +## `...Unload()` + +_Full function name:_ `ChatterboxUnload(filename)` + +_Returns:_ N/A (`undefined`) + +|Name |Datatype|Purpose | +|----------|--------|--------------------------| +|`filename`|string |Name of the file to unload| + +Frees memory associated with the source. All in-progress [chatterboxes](concept-chatterboxes) that are using the given filename will be invalidated when this function is called. + +  + +## `...IsLoaded()` + +_Full function name:_ `ChatterboxIsLoaded(filename)` + +_Returns:_ Boolean, if the given file has been loaded as a [source file](concept-source-files) + +|Name |Datatype|Purpose | +|----------|--------|-------------------------| +|`filename`|string |Name of the file to check| + +  + +## `...AddFunction()` + +_Full function name:_ `ChatterboxAddFunction(name, function)` + +_Returns:_ Boolean, whether the function was added successfully + +|Name |Datatype |Purpose | +|----------|---------------|----------------------------------| +|`name` |string |Function name to use in YarnScript| +|`function`|function/method|GML function to call | + +Adds a custom function that can be called by Yarn expressions. + +Custom functions can return values, but they should be **numbers** or **strings**. + +GML: + +```gml +ChatterboxLoad("example.json"); +ChatterboxAddFunction("AmIDead", am_i_dead); +``` + +Yarn: + +```yarn +Am I dead? +<> +Yup. Definitely dead. +<> +No, not yet! +<> +``` + +This example shows how the script `am_i_dead()` is called by Chatterbox in an if statement. The value returned from `am_i_dead()` determines which text is displayed. + +Parameters for custom functions executed by YarnScript should be separated by spaces. The parameters are passed into the given function as an array of values as `argument0`. + +Custom functions can be added at any point but should be added before loading in any source files. + +  + +## `...AddFindReplace()` + +_Full function name:_ `ChatterboxAddFindReplace(oldString, newString)` + +_Returns:_ N/A (`undefined`) + +|Name |Datatype|Purpose | +|-----------|--------|-------------------------------------------------------------| +|`oldString`|string |String to search for in a [source file](concept-source-files)| +|`newString`|string |String that replaces all instances of the search string | + +Find-replace operations are applied to all source files on load. These operations can be defined at any point but should be added before loading in any source files. + +  + +## `...NodeChangeCallback()` + +_Full function name:_ `ChatterboxNodeChangeCallback(function)` + +_Returns:_ N/A (`undefined`) + +|Name |Datatype|Purpose | +|----------|--------|---------------------------------------------| +|`function`|function|Function to execute when moving between nodes| + +Sets a callback function that is executed whenever a chatterbox changes node. The callback will be executed in the following situations: + +- Jumping to a node + +- Hopping to a node + +- Hopping back to a node + +The callback will be executed with the following arguments: + +|Name |Datatype|Purpose | +|---------|--------|----------------------------------| +|`oldNode`|string |Name of the node that we have left| +|`newNode`|string |Name of the node we have entered | + +  + +## `...SourceNodeExists()` + +_Full function name:_ `ChatterboxSourceNodeExists(sourceName, nodeTitle)` + +_Returns:_ Boolean, if the given node exists in the given source + +|Name |Datatype|Purpose | +|------------|--------|------------------------------| +|`sourceName`|string |Name of the source to check in| +|`nodeTitle` |string |Name of the node to check for | + +  + +## `...SourceNodeCount()` + +_Full function name:_ `ChatterboxSourceNodeCount(sourceName)` + +_Returns:_ Integer, the number of nodes in the source + +|Name |Datatype|Purpose | +|------------|--------|----------------------------| +|`sourceName`|string |Name of the source to target| + +  + +## `...SourceGetTags()` + +_Full function name:_ `ChatterboxSourceGetTags(sourceName)` + +_Returns:_ Array, the metadata tags associated with the source + +|Name |Datatype|Purpose | +|------------|--------|----------------------------| +|`sourceName`|string |Name of the source to target| + +  + +## `...SourceGetNodeMetadata` + +_Full function name:_ `ChatterboxSourceGetNodeMetadata(sourceName, nodeTitle)` + +_Returns:_ Struct, the metadata for the node in the given source + +|Name |Datatype|Purpose | +|------------|--------|------------------------------| +|`sourceName`|string |Name of the source to check in| +|`nodeTitle` |string |Name of the node to check for | \ No newline at end of file diff --git a/docs/2.17/reference-variables.md b/docs/2.17/reference-variables.md new file mode 100644 index 00000000..923216fd --- /dev/null +++ b/docs/2.17/reference-variables.md @@ -0,0 +1,208 @@ +# Variables and Constants + +Functions on this page allow you to declare, access, and manipulate variables stored inside the Chatterbox library. Variables are shared across all individual chatterbox instances and are therefore "global" in scope. All functions on this page are prefixed with `ChatterboxVariable` or `ChatterboxVariables` (depending on scope). + +!> Whilst it's tempting to want to directly manipulate variables in standard GML code using Chatterbox, this often leads to confusion over why variables are changing value and is further unsafe from a security standpoint. As a result, Chatterbox variables are stored in their own sandbox and it is not possible to modify or access GML variables out-of-the-box. You can bind custom fuctions to Chatterbox using `ChatterboxAddFunction()` to do this for you, but you do so at your own risk. + +  + +## `...Default()` + +_Full function name:_ `ChatterboxVariableDefault(name)` + +_Returns:_ N/A (`undefined`) + +|Name |Datatype|Purpose | +|-------|--------|-----------------------| +|`name` |string |Variable to set | +|`value`|any |The default value to set| + +This function sets the default value for a Chatterbox variable. This is equivalent to using the `<>` action in YarnScript. Chatterbox variables must be strings, booleans, or numbers. + +?> Whilst Chatterbox and YarnScript don't require any particular naming convention, we encourage the use of `camelCase` for variable names. + +  + +## `...Get()` + +_Full function name:_ `ChatterboxVariableGet(name)` + +_Returns:_ The value for the given Chatterbox variable + +|Name |Datatype|Purpose | +|------|--------|-----------------------------| +|`name`|string |Variable to get the value for| + +Returns the value stored in a Chatterbox variable. + +  + +## `...Set()` + +_Full function name:_ `ChatterboxVariableSet(name, value)` + +_Returns:_ N/A (`undefined`) + +|Name |Datatype|Purpose | +|-------|--------|----------------------------| +|`name` |string |Variable to set | +|`value`|any |Value to set the variable to| + +Sets the value of a Chatterbox variable. Chatterbox variables must be strings, booleans, or numbers, and you cannot change the datatype of a variable once it has been declared. Additionally, Chatterbox constants cannot have their value changed (see below). + +?> Whilst Chatterbox and YarnScript don't require any particular naming convention, we encourage the use of `camelCase` for variable names. + +  + +## `...SetCallback()` + +_Full function name:_ `ChatterboxVariableSetCallback(function)` + +_Returns:_ N/A (`undefined`) + +|Name |Datatype|Purpose | +|----------|--------|------------------------------------------| +|`function`|function|Function to execute when a variable is set| + +Sets a callback function that is executed whenever a Chatterbox variable is set. The callback will be executed in the following situations: + +- Setting a variable in YarnScript + +- Calling `ChatterboxVariableSet()` + +- Calling `ChatterboxVariableReset()` + +The callback will be executed with the following arguments: + +|Name |Datatype|Purpose | +|--------------|--------|------------------------------------------------------------------| +|`variableName`|string |Name of the variable that has been set (without the preceding `$`)| +|`newValue` |any |New value for the variable | +|`oldValue` |any |Old value for the variable | + +  + +## `...SetConstant()` + +_Full function name:_ `ChatterboxVariableSetConstant(name, value)` + +_Returns:_ N/A (`undefined`) + +|Name |Datatype|Purpose | +|-------|--------|-----------------------------| +|`name` |string |Variable to set as a constant| +|`value`|any |Value to set the variable to | + +Equivalent to the `<>` action in YarnScript. Setting a Chatterbox variable as a constant causes it to behave differently to a "standard" variable: + +1. Constants cannot have their value set using either `ChatterboxVariableSet()` or the YarnScript `<>` action. +2. Constants will not be exported or imported using `ChatterboxVariablesExport()` or `ChatterboxVariablesImport()`. + +Chatterbox constants can still have their value read by `ChatterboxVariableGet()` and can be found using `ChatterboxVariableFind()`. + +?> Whilst Chatterbox and YarnScript don't require any particular naming convention, we encourage the use of `SCREAMING_SNAKE_CASE` for constant names. + +  + +## `...Reset()` + +_Full function name:_ `ChatterboxVariableReset(name)` + +_Returns:_ N/A (`undefined`) + +|Name |Datatype|Purpose | +|------|--------|-----------------| +|`name`|string |Variable to reset| + +Resets the value of a Chatterbox variable to its default starting value, either set by a `<>` YarnScript action or `ChatterboxVariableDefault()`. + +  + +## `...ResetAll()` + +_Full function name:_ `ChatterboxVariablesResetAll()` + +_Returns:_ N/A (`undefined`) + +|Name|Datatype|Purpose| +|----|--------|-------| +|N/A | | | + +Resets the value of **all** Chatterbox variables (including `visited()` state) to their default values, as defined by `ChatterboxVariableDefault()` or `<>`. + +  + +## `...Export()` + +_Full function name:_ `ChatterboxVariablesExport()` + +_Returns:_ String, a JSON string that contains all Chatterbox variables and their values + +|Name|Datatype|Purpose| +|----|--------|-------| +|N/A | | | + +The returned string also contains data on what nodes have been visited. This function will exclude Chatterbox constants. + +  + +## `...Import()` + +_Full function name:_ `ChatterboxVariablesImport(string)` + +_Returns:_ N/A (`undefined`) + +|Name |Datatype|Purpose | +|--------|--------|--------------------------------------------------------------------------------------------------------------------| +|`string`|string |JSON string to import, as exported by [`ChatterboxVariablesExport()`](reference-variables#chatterboxvariablesexport)| + +This function overwrites all Chatterbox variables, excluding constants, with whatever values are found in the input JSON. If a variable is not present in the input JSON then that variable will either be reset to its default value (see `ChatterboxVariableDefault()`) or outright deleted. + +  + +## `...ClearVisited()` + +_Full function name:_ `ChatterboxVariablesClearVisited(node, filename)` + +_Returns:_ N/A (`undefined`) + +|Name |Datatype|Purpose | +|----------|--------|--------------------------------------| +|`node` |string |Node to "unvisit" | +|`filename`|string |Filename that the node can be found in| + +Clears the visited state, as returned by the YarnScript native function `visited()`, for the given node found in the given file. + +  + +## `...ClearVisitedAll()` + +_Full function name:_ `ChatterboxVariablesClearVisitedAll()` + +_Returns:_ N/A (`undefined`) + +|Name|Datatype|Purpose| +|----|--------|-------| +|N/A | | | + +Clears the visited state, as returned by YarnScript native function `visited()`, for all nodes across all files. + +  + +## `...Find()` + +_Full function name:_ `ChatterboxVariablesFind(substring, mode, caseSensitive)` + +_Returns:_ Array, variables names that match the given search substring and mode + +|Name |Datatype|Purpose | +|---------------|--------|-----------------------------------------------------| +|`substring` |string |Substring to search for in variable names | +|`mode` |integer |See below | +|`caseSensitive`|boolean |Whether the search operation should be case sensitive| + +Mode should be 0, 1, or 2: + +0. Substring must be present anywhere in the variable name +1. Substring must prefix the variable name +2. Substring must suffix the variable name