Difference between revisions of "Dialogue"
DeamonHunter (Talk | contribs) (Restructure page.) |
m |
||
(7 intermediate revisions by 2 users not shown) | |||
Line 3: | Line 3: | ||
− | = | + | = Creating New Dialogue = |
− | + | The dialogue system was created using [https://www.secretlab.com.au/yarnspinner/ Yarn]. This gives much more power to the dialogue system but in addition causes a lot more issues when trying to explain. This tutorial will try to explain as much as possible, with as little confusion as possible. | |
− | Creating this file is very simple with only two properties. The full file looks like; | + | == Setup == |
+ | Yarn, thankfully, has its own software to help you out when you create dialogue. The [https://github.com/InfiniteAmmoInc/Yarn Yarn Editor] can be used to heavily speed up dialogue creation as you can focus on creating the text, rather than having to format files correctly. To help you out, here are steps in order to get ready for dialogue creation; | ||
+ | |||
+ | # Download the latest version of the editor: http://infiniteammo.com/Yarn/Yarn-2016-08-15-win.zip (Link subject to change) | ||
+ | # Extract the file to a location you want. | ||
+ | # Download bartwe's yarn edit: https://github.com/bartwe/Yarn | ||
+ | # Drag all files in the app folder to yarn's folder, merge and replace all files. | ||
+ | # Run <tt>''Yarn.exe''</tt> in the new folder. | ||
+ | |||
+ | You can also set up a start menu shortcut to the exe by Right Clicking <tt>''Yarn.exe''</tt> then clicking <tt>''Pin To Start''</tt>. | ||
+ | |||
+ | |||
+ | == Creating the dialogue == | ||
+ | Hopefully you will have started Yarn and been greeted with this screen; | ||
+ | [[File:Yarn Clean Start.png]] | ||
+ | |||
+ | Here is a brief explanation of all of the UI elements. | ||
+ | |||
+ | * In the top left is the search bar and search options. Useful when creating large files, but not needed in this tutorial. | ||
+ | * In the center, is a box. This box is what is called a node. It has a title, in this case "Start", and a body containing "Empty Text". When you are hovering over the box more options will appear; | ||
+ | ** The left and right arrows will change the colour of the title. Useful for large files and organisation. | ||
+ | ** A rubbish bin for deleting the node. This will delete everything in the node. | ||
+ | * In the top right is two buttons; | ||
+ | ** The +Node button adds another box (Which is called a node). This will be used later. | ||
+ | ** The File button is a drop down for allowing you to load and save files. You will be mainly using the <tt>''"Open..."''</tt> and the <tt>''"Save as JSON..."''</tt> options. | ||
+ | |||
+ | |||
+ | That's good and all but how does that help us create dialogue? Well good question, here is how. | ||
+ | |||
+ | |||
+ | Double Click on the node in the middle. A new window should appear like below; | ||
+ | [[File:Yarn Clean Node.png]] | ||
+ | |||
+ | Again here is a brief explanation of the new window; | ||
+ | * In the top is the title. For now keep this as "Start". (One node titled "Start" must exist for every dialogue file. | ||
+ | * Underneath the title, is another line. This is for adding tags to this node. This is a mostly unused feature for Staxel however. | ||
+ | * Under the two lines, is the body. This is where all the dialogue will be going. | ||
+ | |||
+ | With that out of the way, we shall start writing dialogue. However you will need to add stuff so that it can set the game up right. Add the following to the "Start" node. | ||
+ | |||
+ | <pre> | ||
+ | <<lockPlayerInConversation>> | ||
+ | <<typewriterMode on>> | ||
+ | </pre> | ||
+ | |||
+ | All three of these are what is known as <tt>'''"Functions"</tt>'''. These do special stuff in the game and is always surround by <code><< >></code>. We will probably end up using more of these later. For now here is an explanation for each line; | ||
+ | |||
+ | * <code><<lockPlayerInConversation>></code>: This makes it so the player cannot walk away from the conversation. It'll also bring the camera towards the NPC and also activate the black bars. Skipping this line sets it up more like the Merchants in the town square. | ||
+ | * <code><<typewriterMode on>></code>: This makes the game write every character 1 by 1, instead of writing the entire line at once. The "on" part is a parameter, which tells the function that we want the typewriter to be on. | ||
+ | |||
+ | |||
+ | Most new dialogues will have these two lines at the very start. (With the main exceptions being the Town Square merchants.) From now on we will be focusing on writing stuff that will actually appear to the player. | ||
+ | |||
+ | |||
+ | While still in the "Start" node, you should add the following lines; | ||
+ | |||
+ | <pre> | ||
+ | <<if $met_player != 1>> | ||
+ | [[Hello]] | ||
+ | <<else>> | ||
+ | [[Choice]] | ||
+ | <<endif>> | ||
+ | </pre> | ||
+ | |||
+ | This particular code sets up a simple "Greet the player if you haven't met them yet. Otherwise go to other dialogue.". A quick explanation below. | ||
+ | |||
+ | * Line 1: This is an if statement, which is checking for the variable "$met_player" is not equal to 1. On the first run this will not be true. | ||
+ | * Line 2: This section happens if the if statement was true. Then it will reach this line. <nowiki><code>[[Hello]]</code></nowiki> is the code in order to send the dialogue to the node with the title "Hello". | ||
+ | * Line 3: This ends the first block. It only passes here is the if statement was false. | ||
+ | * Line 4: Similar to line 2. This section happens when the if statement is false. It will go to the node labelled <nowiki><code>[[Choice]]</code></nowiki>. | ||
+ | * Line 5: Needed to end the If section. (Always need to go If → End If. e.g. If → elseif → else → endif) | ||
+ | |||
+ | |||
+ | With that, click outside of the box onto the dark area. With that click the <tt>''+Node''</tt> button in the top left of the screen. Click and drag the new box to the left. You should have something similar to this; | ||
+ | [[File:Yarn One Node Completed.png]] | ||
+ | |||
+ | Double click on the new node. Name this node exactly "Hello". This will be the node that we want to add our greeting to. (Finally some actual dialogue!). Feel free to add your own text but here is some example text; | ||
+ | |||
+ | <pre> | ||
+ | Hey there! | ||
+ | I was waiting to see if you would show up. | ||
+ | I've always been fond of farmers. But the last one left. | ||
+ | So it'll look like we'll probably be good friends. | ||
+ | Well I gotta get going. I'll see you later. | ||
+ | </pre> | ||
+ | |||
+ | Any old greeting will do. That being said, the game will show one line at a time. As such, "Hey There!" will be it's own textbox. After the player clicks "I've always been fond of farmers. But the last one left." Will be shown next. An example of such as below; | ||
+ | |||
+ | // Add in greeting showoff. | ||
+ | |||
+ | As a note do not let your lines get too long. Staxel does not handle lines that are too long yet. | ||
+ | |||
+ | |||
+ | With that we probably want to end this node off properly first. Add the following two lines to the end of the node. | ||
+ | <pre> | ||
+ | <<set $met_player = 1>> | ||
+ | [[End]] | ||
+ | </pre> | ||
+ | |||
+ | The first line sets it the initial if statement to go the other direction again. (So we don't greet twice.) The second line sets this to go to a completely new node called "End". | ||
+ | |||
+ | |||
+ | Lets go set that new node up. Create a new node. Drag it downwards. Double click on it. Name it "End". This will be a very simple node, and as such just copy and past the following into it. | ||
+ | <pre> | ||
+ | <<typewriterMode off True True>> | ||
+ | <<releasePlayerFromConversation>> | ||
+ | </pre> | ||
+ | |||
+ | And that's it. These two lines do the following; | ||
+ | |||
+ | * <<typewriterMode off True True>>: This is the "typewriterMode" mode function again. But this time it has the parameters "off", "True" and "True". The off is self explanatory (It turns typewriter off), but the "True True" cleans up the dialogue at the end. | ||
+ | * <<releasePlayerFromConversation>>: Does exactly on the tin. Releases the player from the conversation, by giving them back movement and free roaming camera. | ||
+ | |||
+ | |||
+ | And that's it. Your first dialogue line is complete. Although as you may have noticed, we still have another path to go. But first double check you have something similar to; | ||
+ | |||
+ | [[File:Yarn One Branch Completed.png]] | ||
+ | |||
+ | |||
+ | Now is probably a good time to save the file. Go to <code> File → Save As Json...</code> and save the file. | ||
+ | |||
+ | |||
+ | By this point, it may be worth saying that you can zoom in and out by using the scroll wheel and move around with the arrow keys. (Although the arrow keys are a pain in this version.) | ||
+ | |||
+ | |||
+ | Next lets continue on with the new branch. Create a node that has the title, "Choice". Add the following to it's body; | ||
+ | |||
+ | <pre> | ||
+ | <<requestGoToQuestIfAvailable>> | ||
+ | <<pickRandomPath>> | ||
+ | <<BranchingPath>> | ||
+ | <<MultipleOptionTest>> | ||
+ | <<SellingAnItem>> | ||
+ | <<flushRandomPath>> | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | This probably looks like a mess of characters at this point. So here is the explanation for each line; | ||
+ | |||
+ | * Line 1: <code><<requestGoToQuestIfAvailable>></code>: This is used to tell the game that it's OK to go to the quest that the game has. If there is no quest then it'll go to Line 2 instead. | ||
+ | * Line 2: <code><<pickRandomPath>></code>: This is a special function that tells the game to look at all the lines below, up until <<flushRandomPath>>. And randomly choose one of these lines as the direction we want to go. | ||
+ | * Line 3-5: These are all functions that contain the title of the node to go to. In essence these are the same as <nowiki><code>[[BranchingPath]], [[MultipleOptionTest]], [[SellingAnItem]]</code></nowiki>. | ||
+ | * Line 6: <code><<flushRandomPath>></code>: This line tells <code><<pickRandomPath>> to stop going any further. | ||
+ | |||
+ | |||
+ | With that under way. Lets create another node and title it "BranchingPath". Add the following to the file: | ||
+ | <pre> | ||
+ | This is an example of something that causes a branching path. | ||
+ | <<branchCurrentSeasonIs Summer SummerNode>> | ||
+ | Today is quite cool you know. | ||
+ | I feel like summer is just around the corner though. | ||
+ | [[End]] | ||
+ | </pre> | ||
+ | |||
+ | This node is fairly self explanatory except for the second line. This second line is another Function with the name "branchCurrentSeasonIs". This function takes two inputs, this case "Summer" and "SummerNode". It will take the first input and compare it to the current season. So if you input "Summer" it will try to compare that to the game's current season. (Other inputs are "Winter", "Autumn" and "Spring".) If the season is indeed Summer then it will take the second input and then make the dialogue go to that note. That is, if it is "Summer", then make the dialogue do the same as <code><nowiki>[[SummerNode]]</nowiki></code>. Otherwise just make it go on like normal. | ||
+ | |||
+ | |||
+ | Lets fill this branch out by add another node named "SummerNode". Add something like the following to it; | ||
+ | <pre> | ||
+ | Argh! It's summer! | ||
+ | I hate it when it is summer. | ||
+ | I just want to stay inside but there is nothing to do. | ||
+ | [[End]] | ||
+ | </pre> | ||
+ | |||
+ | At this point the file should start looking like; | ||
+ | |||
+ | [[File:Yarn Second Branch Completed.png]] | ||
+ | |||
+ | Don't forget to save before continuing. | ||
+ | |||
+ | |||
+ | Lets get onto the second random choice. Create another node named "MultipleOptionTest". Then add the following to it. | ||
+ | |||
+ | <pre> | ||
+ | Hey! | ||
+ | Do you like Cats? | ||
+ | [[Yes!|MultChoiceYes]] | ||
+ | [[No.|MultChoiceNo]] | ||
+ | </pre> | ||
+ | |||
+ | This actually sets up a multiple choice. The 3rd line <code><nowiki>[[Yes!|MultChoiceYes]]</nowiki></code> sets up an option that says "Yes!" and when that is chosen it will go to the node <code><nowiki>[[MultChoiceYes]]</nowiki></code>. Similar for <code><nowiki>[[No.|MultChoiceNo]]</nowiki></code>. | ||
+ | |||
+ | |||
+ | Lets create both of those nodes then. First lets create the first node, "MultChoiceYes". Add the following to that as well; | ||
+ | <pre> | ||
+ | Nice! | ||
+ | They are pretty cute right. | ||
+ | [[End]] | ||
+ | </pre> | ||
+ | |||
+ | And a similar thing for "MultChoiceNo". | ||
+ | <pre> | ||
+ | Boo! | ||
+ | Cats are love. Cats are life. | ||
+ | Come back to me when you believe! | ||
+ | [[End]] | ||
+ | </pre> | ||
+ | |||
+ | And now you have another branch going. Only 1 more to go for this tutorial. The file is probably starting to look like some mess similar to; | ||
+ | [[File:Yarn 3rd Branch Completed.png]] | ||
+ | |||
+ | |||
+ | Now we just have the final branch. Create another node named "SellingAnItem". In this add the following. | ||
+ | |||
+ | <pre> | ||
+ | <<loadItemBuyPrice item staxel.item.crafting.RawStone 1 $stone>> | ||
+ | Oh hi there! | ||
+ | I was looking to sell this fine looking rock. Do you want it? | ||
+ | [[Yes! ($currency;$stone;)|BuyYes]] | ||
+ | [[No.|BuyNo]] | ||
+ | </pre> | ||
+ | |||
+ | So this will take a little bit of explaining. | ||
+ | |||
+ | * Line 1: <code><<loadItemBuyPrice item staxel.item.crafting.RawStone 1 $stone>></code>: This finds the item "staxel.item.crafting.RawStone" and grabs the price of "1" of them. It will then place the price in the variable $stone (Remember back to $met_player?). | ||
+ | * Line 4: This is exactly like the options that we made before. Except there is something special to it. "Yes!($currency;$stone;)" will basically translate to "Yes! ($3)" (Except using the petals sign). This is because $currency is a global variable which contains the currency symbol, and the price is stored in the other variable. | ||
+ | |||
+ | |||
+ | With that we need to create a new node titled "BuyYes". Add the following to it; | ||
+ | <pre> | ||
+ | <<branchPlayerCantAffordItem item staxel.item.crafting.RawStone 1 CantAfford>> | ||
+ | Here you go! | ||
+ | <<playerPurchaseItem item staxel.item.crafting.RawStone>> | ||
+ | [[End]] | ||
+ | </pre> | ||
+ | |||
+ | Again some explanation; | ||
+ | |||
+ | * Line 1: This is very similar to our BranchCurrentSeasonIs function that we used before. But this is checking whether or not the player can afford the item. If not go to "CantAfford" instead. | ||
+ | * Line 3: The function to actually purchase the item. | ||
+ | |||
+ | |||
+ | With that create a node titled "CantAfford". Then add the following; | ||
+ | <pre> | ||
+ | Oh. It looks like you don't have money. | ||
+ | Well I'll just throw it away, I guess. | ||
+ | [[End]] | ||
+ | </pre> | ||
+ | |||
+ | And then finally lets set up the node, "BuyNo". Add the following to it; | ||
+ | <pre> | ||
+ | Oh really? | ||
+ | Fine. Looks like I'll just throw it away then. | ||
+ | [[End]] | ||
+ | </pre> | ||
+ | |||
+ | |||
+ | And with that you have a dialogue file! It should be looking similar to; | ||
+ | [[File:Yarn Completed.png]] | ||
+ | |||
+ | |||
+ | That must have taken forever. Make sure to save the file and then with that you are ready to continue on. | ||
+ | |||
+ | |||
+ | == Creating the *.dialogue file == | ||
+ | ''Before you start this part of the tutorial, be sure to head through [[Modding#Getting Started with Staxel Modding]].'' | ||
+ | |||
+ | === Adding the Dialogue via Asset Manager === | ||
+ | ''Follow [[Modding#Using the AssetManager to Create Mods]] to open up the Asset Manager.'' | ||
+ | |||
+ | With the Asset Manager open, head to <code>View → Characters and Animals → Villager Assets</code>. When the new window is open, head to <code>Asset → Add → New Asset</code> and the following window will show up. | ||
+ | |||
+ | [[File:Asset Manager - New Asset.png]] | ||
+ | |||
+ | First click on the button Asset Path and navigate upwards to the <code>/content/</code> folder. Once there, open the <code>/mods/</code> folder and create a new folder. Name this new folder to what you want the mod to be called and then open this new folder. When you open this folder give the asset a name, then click on the drop down and select ''<tt>Dialogue Asset</tt>''. Then click save, give the item a code then click OK. | ||
+ | |||
+ | After the asset is created, it will have been automatically selected. With that there is only one thing to do right now. Tell the game where the <tt>''"*.json"''</tt> is. | ||
+ | |||
+ | # Click on the Dialogue. Click on the [...]. Navigate to the Dialogue file you created before. And then click OK. | ||
+ | |||
+ | |||
+ | With that, hit Crtl+S to save the file. And then go to <code>File → All Assets → Build and Validate Assets</code>. If this succeeds, then HURRAY! you have a new tile in the game. If it fails, try and read the error to see what you have done wrong. | ||
+ | |||
+ | |||
+ | However, this Dialogue is currently useless. You will need to follow [[Dialogue Pools#Creating New Dialogue Pools]]. | ||
+ | |||
+ | |||
+ | === Adding the Dialogue via Text Files === | ||
+ | |||
+ | ''Follow [[Modding#Using a Text Editor to Create Mods]] in order to be properly set up for this step.'' | ||
+ | |||
+ | |||
+ | Creating this file is very simple as it only two properties. The full file will looks like; | ||
<pre> | <pre> | ||
{ | { | ||
Line 13: | Line 296: | ||
} | } | ||
</pre> | </pre> | ||
− | |||
+ | With the file being this short, there is no need for pictures. Here is the explanation of the two properties. | ||
− | + | * [[#"code"|"code"]]: A unique [[Modding_Key_Terms#String|String]] that would be used to identify this object from others. For example this is like "staxel.item.crafting.BakingPowder" or "staxel.tile.grass". You will most commonly want to use you use the path to the Accessory Model but replace <code>/</code> with <code>.</code>, as this will ensure your design will have a different code to all other designs. | |
+ | |||
+ | * [[#"dialogue"|"dialogue"]]: A [[Modding_Key_Terms#String|String]] that is the path to the dialogue you created in the first section. The path starts at the <code>/content/</code> directory and therefore will mostly start with <code>mods/modname/</code>. | ||
+ | |||
+ | |||
+ | After you have done editing the file, head to <code>gamedata/bin/</code> folder, and start up <tt>'''Staxel.ContentBuilder.exe'''</tt>. When this has started up, click "Tag dialogue and generate language file". This will open up a file browser. Go to your newly created file (The .dialogue file from the first section.) and select that. After that, click <tt>'''Validate Resources'''<tt> and wait until the progress bar has done. And with that you should have a working item. If you are confused then go to the #Modding channel on Discord and ask there. | ||
+ | |||
+ | |||
+ | However, this Dialogue is currently useless. You will need to follow [[Dialogue Pools#Creating New Dialogue Pools]]. | ||
+ | |||
+ | |||
+ | = Config Options = | ||
== "code" == | == "code" == | ||
'''Valid options (String): <code>A unique string which dialogue what this object is.</code>''' | '''Valid options (String): <code>A unique string which dialogue what this object is.</code>''' | ||
Line 37: | Line 331: | ||
= The Yarn *.json file = | = The Yarn *.json file = | ||
− | [https://www.secretlab.com.au/yarnspinner/ Yarn] is the program which creates the dialogue files for Staxel. It utilises it's own scripting language which can make choices and also use conditional statements in order to provide the right dialogue. They also include an | + | [https://www.secretlab.com.au/yarnspinner/ Yarn] is the program which creates the dialogue files for Staxel. It utilises it's own scripting language which can make choices and also use conditional statements in order to provide the right dialogue. They also include an which helps visualise these files. |
Look at the documentation around Yarn, particularly sections such as [https://github.com/thesecretlab/YarnSpinner/blob/master/Documentation/YarnSpinner-Dialogue/Usage.md this]. Do not Yarn is changing frequently and documentation might not line up with the implementation used in Staxel. | Look at the documentation around Yarn, particularly sections such as [https://github.com/thesecretlab/YarnSpinner/blob/master/Documentation/YarnSpinner-Dialogue/Usage.md this]. Do not Yarn is changing frequently and documentation might not line up with the implementation used in Staxel. | ||
Line 59: | Line 353: | ||
Useful for checking for completed actions, such as checking if the player has placed a Pet House. | Useful for checking for completed actions, such as checking if the player has placed a Pet House. | ||
+ | |||
+ | |||
+ | === branchAndLoadMissingCriticalTotem === | ||
+ | '''Usage: <code><<branchAndLoadMissingCriticalTotem $ttm $price 1.50 TotemMissing>></code>''' | ||
+ | |||
+ | Parameter 1: The name of the variable you want to use to store the totem name. Should start with $. | ||
+ | |||
+ | Parameter 2: The name of the variable you want to use to store the price of the item. Should start with $. | ||
+ | |||
+ | Parameter 3: The premium multiplier. (The price will end up being, the cost of the totem * premium). | ||
+ | |||
+ | Parameter 4: Title of the Node to move to. | ||
+ | |||
+ | |||
+ | When this function is hit, check to see if a critical totem is missing. If so, then load said Totem's name to Parameter 1 and the price (multiplied by Parameter 3) to Parameter 2, then go to the node. If no critical totem is missing, then continue on normally without loading to variables. | ||
Line 77: | Line 386: | ||
− | === | + | === branchCurrentSeasonIs=== |
− | '''Usage: <code><< | + | '''Usage: <code><<branchCurrentSeasonIs Summer SummerNode>></code>''' |
+ | |||
+ | Parameter 1: Summer, Winter, Spring, Autumn | ||
+ | |||
+ | Parameter 2: Title of the Node to move to. | ||
+ | |||
+ | When this function is hit, check to see if the Season matches parameter 1. If so branch, otherwise continue normally. | ||
+ | |||
+ | |||
+ | === branchMissingTotem === | ||
+ | '''Usage: <code><<branchMissingTotem staxel.totem.AirshipLanding HouseMissing false>></code>''' | ||
+ | |||
+ | Parameter 1: Code of the [[Totems|Totem]] you want to check. (e.g. staxel.totem.AirshipLanding) | ||
+ | |||
+ | Parameter 2: Title of the Node to move to. | ||
+ | |||
+ | Parameter 3: Whether or not this totem should have been built to it's lowest tier. | ||
+ | |||
+ | When this function is hit, it will check to see if the totem is missing. If parameter 3 is true, then it will check if the villager has a built totem of this type. If it does continue and if not branch. If parameter 3 is false, then it will check if the totem has either been place or exists in the players inventory. If either of those are true, continue normally and branch if not. | ||
− | |||
− | + | useful for when you want to check if a totem has been lost before giving another totem. | |
Mainly used by Farm Fan to give the player rewards. Not too useful for other players. | Mainly used by Farm Fan to give the player rewards. Not too useful for other players. | ||
+ | |||
+ | |||
+ | === BranchValidStructureExistsWithTier === | ||
+ | '''Usage: <code><<BranchValidStructureExistsWithTier staxel.totem.AirshipLanding 1 AirshipAvailable>></code>''' | ||
+ | |||
+ | Parameter 1: Code of the [[Totems|Totem]] you want to check. (e.g. staxel.totem.AirshipLanding) | ||
+ | |||
+ | Parameter 1: The lowest Tier of the existing building you want. | ||
+ | |||
+ | Parameter 3: Title of the Node to move to. | ||
+ | |||
+ | |||
+ | When this function is hit, it will search to see if a valid totem of the type specified exists. If it does, check if it has a tier at or higher than specified. If it succeeds, then it will head to the specified node. Otherwise if it does not exist or it's not a high enough tier then continue on normally. | ||
+ | |||
+ | |||
+ | Useful for checking that a building actually exists, and is at a certain tier, before going to it/ talking about it. (e.g. Making a villager complain that a building is not max tier.) | ||
+ | |||
+ | ''If you want to know that the building existed at some point then head to [[#branchBuildingHasExisted]]. Or if you just want it to exist, head to [[#branchValidStructureExists]]'' | ||
+ | |||
+ | |||
+ | === branchNotServerOwner=== | ||
+ | '''Usage: <code><<branchNotServerOwner NotOwner>></code>''' | ||
+ | |||
+ | Parameter 1: Title of the Node to move to. | ||
+ | |||
+ | When this function is hit, it will check if the player is the server owner. If they are, then it will head to the specified node, otherwise continues on normally. | ||
+ | |||
+ | |||
+ | Mainly used by Farm Fan to make sure that only the server owner gets the tutorial. | ||
Line 91: | Line 446: | ||
'''Usage: <code><<branchPlayerCantAffordItem item staxel.item.crafting.MugOSap 1 CantAfford>></code>''' | '''Usage: <code><<branchPlayerCantAffordItem item staxel.item.crafting.MugOSap 1 CantAfford>></code>''' | ||
− | Parameter 1: Can be <code>item, tilePlacer, plant, recipe or clothing</code>. Use item for [[Items]]. Use tilePlacer for [[Tile|Tiles]]. Use plant for [[Plants|seeds. Use recipe for [[Recipes]] and use clothing for [[Accessory|Accessories]]. | + | Parameter 1: Can be <code>item, tilePlacer, plant, recipe or clothing</code>. Use item for [[Items]]. Use tilePlacer for [[Tile|Tiles]]. Use plant for [[Plants|seeds]]. Use recipe for [[Recipes]] and use clothing for [[Accessory|Accessories]]. |
Parameter 2: Code of the thing you want to buy. (e.g. staxel.item.crafting.MugOSap) | Parameter 2: Code of the thing you want to buy. (e.g. staxel.item.crafting.MugOSap) | ||
Line 120: | Line 475: | ||
This is useful for checking if the player has an item that the NPC wants. (For example, check for seeds so that the tutorial can teach the player how to place them.) | This is useful for checking if the player has an item that the NPC wants. (For example, check for seeds so that the tutorial can teach the player how to place them.) | ||
+ | |||
+ | |||
+ | === branchPlayerDoesntHaveEnoughOfItem=== | ||
+ | '''Usage: <code><<BranchPlayerDoesntHaveEnoughOfItemstaxel.item.FarmRegistrationLetter 2 GoodBye>></code>''' | ||
+ | |||
+ | Parameter 1: Code of the [[Items|Item]] you want to check. (e.g. staxel.crop.tomato) | ||
+ | |||
+ | Parameter 2: The minimum number of the item you want. | ||
+ | |||
+ | Parameter 3: Title of the Node to move to. | ||
+ | |||
+ | |||
+ | When this function is hit, it will check if the player has an item of a specific code. If they do check if it meets the minimum requirement, if so continue on normally and if not, move to the specified node. | ||
+ | |||
+ | |||
+ | This is useful for checking if the player has an enough of an item that the NPC wants. (For example, check for seeds so that the tutorial can teach the player how to place them.) | ||
Line 134: | Line 505: | ||
This is useful for checking if the player has an item that the NPC wants. (For example, check for seeds so that the tutorial can teach the player how to place them.) | This is useful for checking if the player has an item that the NPC wants. (For example, check for seeds so that the tutorial can teach the player how to place them.) | ||
+ | |||
+ | |||
+ | === branchPlayerHasItem === | ||
+ | '''Usage: <code><<branchPlayerHasItem staxel.item.crafting.MugOSap CantAfford>></code>''' | ||
+ | |||
+ | Parameter 1: Code of the [[Items|Item]] you want to search for. (e.g. staxel.item.crafting.MugOSap) | ||
+ | |||
+ | Parameter 2: Title of the Node to move to. | ||
+ | |||
+ | |||
+ | When this function is hit, it will check if the player has the item. If they do then branch, otherwise continue on normally. | ||
Line 177: | Line 559: | ||
Useful for checking that a building actually exists, and is still existing, before going to it/ talking about it. | Useful for checking that a building actually exists, and is still existing, before going to it/ talking about it. | ||
− | ''If you want to know that the building existed at some point then head to [[# | + | ''If you want to know that the building existed at some point then head to [[#branchBuildingHasExisted]].'' |
+ | |||
+ | |||
+ | === BranchValidStructureExistsWithTier === | ||
+ | '''Usage: <code><<BranchValidStructureExistsWithTier staxel.totem.AirshipLanding 1 AirshipAvailable>></code>''' | ||
+ | |||
+ | Parameter 1: Code of the [[Totems|Totem]] you want to check. (e.g. staxel.totem.AirshipLanding) | ||
+ | |||
+ | Parameter 1: The lowest Tier of the existing building you want. | ||
+ | |||
+ | Parameter 3: Title of the Node to move to. | ||
+ | |||
+ | |||
+ | When this function is hit, it will search to see if a valid totem of the type specified exists. If it does, check if it has a tier at or higher than specified. If it succeeds, then it will head to the specified node. Otherwise if it does not exist or it's not a high enough tier then continue on normally. | ||
+ | |||
+ | |||
+ | Useful for checking that a building actually exists, and is at a certain tier, before going to it/ talking about it. (e.g. Making a villager complain that a building is not max tier.) | ||
+ | |||
+ | ''If you want to know that the building existed at some point then head to [[#branchBuildingHasExisted]]. Or if you just want it to exist, head to [[#branchValidStructureExists]]'' | ||
Line 196: | Line 596: | ||
This is used for all dialogue that is personal to the player. (i.e. Not merchant chatter.) | This is used for all dialogue that is personal to the player. (i.e. Not merchant chatter.) | ||
+ | |||
+ | |||
+ | === moveToNext === | ||
+ | '''Usage: <code><<moveToNext>></code>''' | ||
+ | |||
+ | Proceed to the next Dialogue immediately after displaying. This is mainly used in order to complete conversations properly and not wait for an input. This is because if the dialogue goes to an empty line, it will do a couple things, such as adjust the NPC's reputation. | ||
+ | |||
+ | ''Not needed if using [[#typewriterMode]] as the same thing is done in <<typewriterMode off true true>>.'' | ||
+ | |||
+ | |||
+ | === pickRandomFromDialoguePools === | ||
+ | '''Usage: <<pickRandomFromDialoguePools>>''' | ||
+ | |||
+ | |||
+ | Make the villager go to a new random Dialogue. This chooses from a number of different dialogues and can be quite complicated to follow. Here are the steps it takes; | ||
+ | |||
+ | # Add any dialogues overrides provided by [[Festivals]] to the list of options first. | ||
+ | # If [[Villager Personalities#"suppressGeneralDialogue"]] is false and, if overriden by a festival, [[Festivals#"suppressPersonality"]] is false then proceed to sub steps. | ||
+ | ## If the villager is preparing to leave town and their home is still gone or broken, then ''immediately return'' a Random Dialogue that is in a Dialogue Pool with the [[Dialogue_Pools#"type"]] leaving. | ||
+ | ## If not preparing to leave, check if villager has doesn't have a quest. | ||
+ | ### Check to see if Player has finished their Farm License. If not add that to the list of options. | ||
+ | ### Add in a Random Dialogue that is in a Dialogue Pool with the [[Dialogue_Pools#"type"]] general. | ||
+ | ### If the weather has dialogue pools, and it isn't night time. Then add one of those in as well. | ||
+ | ### If the player has theft recently, then add in a Random Dialogue that is in a Dialogue Pool with the [[Dialogue_Pools#"type"]] theft. | ||
+ | # If the villager is not overriden or if overriden by a festival, [[Festivals#.22suppressPersonality.22]] is false then proceed to sub steps. | ||
+ | ## Add in a random [[Villager NPCs#Unique Dialogues|Base Unique Dialogue Pool]]. | ||
+ | ## Add in a random [[Villager NPCs#Unique Dialogues|Liked Unique Dialogue Pool]] if high enough reputation. | ||
+ | ## Add in a random [[Villager NPCs#Unique Dialogues|Fond Unique Dialogue Pool]] if high enough reputation. | ||
+ | ## Add in a random [[Villager NPCs#Unique Dialogues|Best Friend Unique Dialogue Pool]] if high enough reputation. | ||
+ | ## Add in a random [[Villager Personalities#"dialoguePools"]]. | ||
+ | ## If season has Dialogue associated with it, add in a random season dialogue. | ||
+ | # If Villager has a [[Villager Jobs|Job]], is not overriden or if overriden by a festival, [[Festivals#.22suppressPersonality.22]] is false then proceed to sub steps. | ||
+ | ## If They are working. That is the time is between their work time. Then continue to sub steps. | ||
+ | ### If Workplace is missing then add in a Random Dialogue that is in [[Villager Jobs#"workPlaceMissingPools"]] with the [[Dialogue_Pools#"type"]] WorkPlaceMissing. | ||
+ | ### If it exists, then add in a Random Dialogue that is in [[Villager Jobs#"dialoguePools"]] with the [[Dialogue_Pools#"type"]] Job. | ||
+ | # If the villager does not have a job, is not overriden or if overriden by a festival, [[Festivals#.22suppressPersonality.22]] is false then add in a Random Dialogue that is in a Dialogue Pool with the [[Dialogue_Pools#"type"]] Unemployed. | ||
+ | # With that, choose a random dialogue out of all of the dialogues added. | ||
+ | |||
+ | '''TLDR''': Choose a random dialogue based on a lot of circumstances, with special attention being paid to Festivals overriding dialogue. | ||
+ | |||
+ | |||
+ | This is most often used by Workers, as they have their working dialogue prioritised. This allows them to still use their personality even while working. (For examples look at Mayor Dialogue and Mechanic Dialogue.) | ||
Line 247: | Line 689: | ||
Make the next set of options be in a random order when shown to the player. | Make the next set of options be in a random order when shown to the player. | ||
+ | |||
+ | |||
+ | === transitionToNew === | ||
+ | '''Usage: <code><<transitionToNew>></code>''' | ||
+ | |||
+ | |||
+ | Restart the dialogue after finishing. | ||
Line 282: | Line 731: | ||
Play a specified emote and wait until it is finished. | Play a specified emote and wait until it is finished. | ||
+ | |||
+ | |||
+ | === giveItemToPlayer === | ||
+ | '''Usage: <code><<giveItemToPlayer item staxel.item.tool.Hoe>></code>''' | ||
+ | |||
+ | Parameter 1: Can be <code>item, tilePlacer, plant, recipe or clothing</code>. Use item for [[Items]]. Use tilePlacer for [[Tile|Tiles]]. Use plant for [[Plants|seeds]]. Use recipe for [[Recipes]] and use clothing for [[Accessory|Accessories]]. | ||
+ | |||
+ | Parameter 2: Code of the thing you want to check and give. (e.g. staxel.item.tool.Hoe) | ||
+ | |||
+ | Parameter 3: (Optional) Number of the item you want to give the player. | ||
+ | |||
+ | |||
+ | Give an item to the player with no checks. | ||
Line 287: | Line 749: | ||
'''Usage: <code><<giveItemToPlayerIfDoesntHave item staxel.item.tool.Hoe>></code>''' | '''Usage: <code><<giveItemToPlayerIfDoesntHave item staxel.item.tool.Hoe>></code>''' | ||
− | Parameter 1: Can be <code>item, tilePlacer, plant, recipe or clothing</code>. Use item for [[Items]]. Use tilePlacer for [[Tile|Tiles]]. Use plant for [[Plants|seeds. Use recipe for [[Recipes]] and use clothing for [[Accessory|Accessories]]. | + | Parameter 1: Can be <code>item, tilePlacer, plant, recipe or clothing</code>. Use item for [[Items]]. Use tilePlacer for [[Tile|Tiles]]. Use plant for [[Plants|seeds]]. Use recipe for [[Recipes]] and use clothing for [[Accessory|Accessories]]. |
Parameter 2: Code of the thing you want to check and give. (e.g. staxel.item.tool.Hoe) | Parameter 2: Code of the thing you want to check and give. (e.g. staxel.item.tool.Hoe) | ||
− | Parameter 3: Number of the item you want to give the player. | + | Parameter 3: (Optional) Number of the item you want to give the player. |
Line 300: | Line 762: | ||
'''Usage: <code><<giveItemToPlayerIfCantAfford plant staxel.crop.Tomato>></code>''' | '''Usage: <code><<giveItemToPlayerIfCantAfford plant staxel.crop.Tomato>></code>''' | ||
− | Parameter 1: Can be <code>item, tilePlacer, plant, recipe or clothing</code>. Use item for [[Items]]. Use tilePlacer for [[Tile|Tiles]]. Use plant for [[Plants|seeds. Use recipe for [[Recipes]] and use clothing for [[Accessory|Accessories]]. | + | Parameter 1: Can be <code>item, tilePlacer, plant, recipe or clothing</code>. Use item for [[Items]]. Use tilePlacer for [[Tile|Tiles]]. Use plant for [[Plants|seeds]]. Use recipe for [[Recipes]] and use clothing for [[Accessory|Accessories]]. |
Parameter 2: Code of the thing you want to check and give. (e.g. staxel.item.tool.Hoe) | Parameter 2: Code of the thing you want to check and give. (e.g. staxel.item.tool.Hoe) | ||
− | Parameter 3: Number of the item you want to give the player. | + | Parameter 3: (Optional) Number of the item you want to give the player. |
Line 333: | Line 795: | ||
Give all the unclaimed items from achievements to the player. | Give all the unclaimed items from achievements to the player. | ||
+ | |||
+ | |||
+ | === giveRandomPet === | ||
+ | '''Usage: <code><<giveRandomPet >></code>''' | ||
+ | |||
+ | |||
+ | Give a random pet to the player. | ||
Line 338: | Line 807: | ||
'''Usage: <code><<loadItemBuyPrice item staxel.item.crafting.MugOSap 1 $sap>></code>''' | '''Usage: <code><<loadItemBuyPrice item staxel.item.crafting.MugOSap 1 $sap>></code>''' | ||
− | Parameter 1: Can be <code>item, tilePlacer, plant, recipe or clothing</code>. Use item for [[Items]]. Use tilePlacer for [[Tile|Tiles]]. Use plant for [[Plants|seeds. Use recipe for [[Recipes]] and use clothing for [[Accessory|Accessories]]. | + | Parameter 1: Can be <code>item, tilePlacer, plant, recipe or clothing</code>. Use item for [[Items]]. Use tilePlacer for [[Tile|Tiles]]. Use plant for [[Plants|seeds]]. Use recipe for [[Recipes]] and use clothing for [[Accessory|Accessories]]. |
Parameter 2: Code of the thing you want to check and give. (e.g. staxel.item.tool.Hoe) | Parameter 2: Code of the thing you want to check and give. (e.g. staxel.item.tool.Hoe) | ||
Line 348: | Line 817: | ||
Calculates the cost of the specified item and places the value into the variable specified. | Calculates the cost of the specified item and places the value into the variable specified. | ||
+ | |||
+ | |||
+ | === loadRandomNumber=== | ||
+ | '''Usage: <code><<loadVillagerName 5 $rnd>></code>''' | ||
+ | |||
+ | Parameter 1: The maximum random number. | ||
+ | |||
+ | Parameter 2: The name of the variable you want to use. Should start with $. | ||
+ | |||
+ | Chooses a random number between 0-max and saves it to the variable. | ||
+ | |||
+ | |||
+ | Useful for doing random checks in Dialogue. (i.e. <code><<if $rnd > 2>></code>) | ||
+ | |||
+ | |||
+ | === loadTotemExistence === | ||
+ | '''Usage: <code><<loadVillagerName staxel.totem.MechanicHome $rnd>></code>''' | ||
+ | |||
+ | Parameter 1: Code of the [[Totems|Totem]] to search for. (e.g staxel.totem.MechanicHome) | ||
+ | |||
+ | Parameter 2: The name of the variable you want to use. Should start with $. | ||
+ | |||
+ | |||
+ | Searches for a totem with the specified name. If that totem does exist in the village, then sets the variable to 1, else sets to 0. | ||
+ | |||
+ | |||
+ | Useful for doing random checks in Dialogue. (i.e. <code><<if $rnd > 2>></code>) | ||
Line 356: | Line 852: | ||
Parameter 2: The name of the variable you want to use. Should start with $. | Parameter 2: The name of the variable you want to use. Should start with $. | ||
+ | |||
Searches for a villager with the specified name. If that villager does exist, then it places their code name into the target variable. | Searches for a villager with the specified name. If that villager does exist, then it places their code name into the target variable. | ||
Line 375: | Line 872: | ||
This is used specifically for loading the right translation for the villager's name. | This is used specifically for loading the right translation for the villager's name. | ||
+ | |||
+ | |||
+ | === playExpression === | ||
+ | '''Usage: <code><<emote staxel.expression.Happy>></code>''' | ||
+ | |||
+ | Parameter 1: Code of the [[Expression]] you want to play. (e.g. staxel.emote.ScratchHead) | ||
+ | |||
+ | |||
+ | Play the specified expression. | ||
Line 380: | Line 886: | ||
'''Usage: <code><<playerPurchaseItem item staxel.item.crafting.MugOSap>></code>''' | '''Usage: <code><<playerPurchaseItem item staxel.item.crafting.MugOSap>></code>''' | ||
− | Parameter 1: Can be <code>item, tilePlacer, plant, recipe or clothing</code>. Use item for [[Items]]. Use tilePlacer for [[Tile|Tiles]]. Use plant for [[Plants|seeds. Use recipe for [[Recipes]] and use clothing for [[Accessory|Accessories]]. | + | Parameter 1: Can be <code>item, tilePlacer, plant, recipe or clothing</code>. Use item for [[Items]]. Use tilePlacer for [[Tile|Tiles]]. Use plant for [[Plants|seeds]]. Use recipe for [[Recipes]] and use clothing for [[Accessory|Accessories]]. |
Parameter 2: Code of the thing you want to check and give. (e.g. staxel.item.tool.Hoe) | Parameter 2: Code of the thing you want to check and give. (e.g. staxel.item.tool.Hoe) | ||
Line 415: | Line 921: | ||
Remove the item specified if the player has it. Do nothing if there is no item. | Remove the item specified if the player has it. Do nothing if there is no item. | ||
+ | |||
+ | |||
+ | Use this in combination with [[#branchPlayerDoesntHavePlayerItem]] to enforce that an item is needed. | ||
+ | |||
+ | |||
+ | === removeAllOfPlayerItem === | ||
+ | '''Usage: <code><<removePlayerItem staxel.item.FarmRegistrationLetter>></code>''' | ||
+ | |||
+ | Parameter 1: Code of the [[Items|Item]] you want to remove. (e.g. staxel.crop.tomato) | ||
+ | |||
+ | |||
+ | Removes all items of the specified code if the player has it. Do nothing if there is no item. | ||
Line 478: | Line 996: | ||
For how to use these variables, look at the barkeep's dialogue. | For how to use these variables, look at the barkeep's dialogue. | ||
+ | |||
+ | |||
+ | === requestGoToQuestIfAvailable === | ||
+ | '''Usage: <code><<requestGoToQuestIfAvailable >></code>''' | ||
+ | |||
+ | If the villager has a quest, then go immediately to that quest. | ||
+ | |||
+ | |||
+ | This is used to signal to the game that it is ok to go to the quest. Most villagers should have this somewhere in their dialogue. | ||
+ | |||
+ | |||
+ | == Villager Arrival Functions == | ||
+ | These functions main use are to allow the player to get more villagers into the game. These are mainly intended to be only used by Mayor Maximillian. | ||
+ | |||
+ | |||
+ | === branchAndLoadMissingArrivalQuestTotem=== | ||
+ | '''Usage: <code><<branchAndLoadMissingArrivalQuestTotem $ttm TotemMissing>></code>''' | ||
+ | |||
+ | Parameter 1: The name of the variable you want to use. Should start with $. | ||
+ | |||
+ | Parameter 2: Title of the Node to move to. | ||
+ | |||
+ | |||
+ | When this function is hit, check to see if a villager quest is active. If not continue normally. If a quest is active, check to see if the player has the totem. If they don't branch, otherwise continue. | ||
+ | |||
+ | |||
+ | === branchNewVillagerArrivalQuestAvailable === | ||
+ | '''Usage: <code><<branchQuestActive CheckCompletion>></code>''' | ||
+ | |||
+ | Parameter 1: Title of the Node to move to. | ||
+ | |||
+ | |||
+ | When this function is hit, check to see if an existing villager arrival quest is already ongoing. If it does exist continue on normally. If it doesn't exist, then check if a new villager arrival can be gotten. Go to the node if a quest is available, otherwise continue normally. | ||
+ | |||
+ | === setAndGiveActiveVillagerArrivalQuestTotem=== | ||
+ | '''Usage: <code><<SetAndGiveActiveVillagerArrivalQuestTotem>></code>''' | ||
+ | |||
+ | |||
+ | Get the new villager arrival quest, and save it. (Thus giving you the quest.) Then give the totem to the player. | ||
+ | |||
+ | |||
+ | === giveActiveVillagerArrivalQuestTotem=== | ||
+ | '''Usage: <code><<giveActiveVillagerArrivalQuestTotem>></code>''' | ||
+ | |||
+ | |||
+ | If a quest is ongoing, then give the player the totem associated with the quest. | ||
+ | |||
+ | |||
+ | == Coming Soon (Village-Registered TSE Functions) == | ||
+ | These functions main use are to register, place and track TileObjects for use in Quests. | ||
+ | |||
+ | |||
+ | === branchQuestTseOfCategoryExists === | ||
+ | '''Usage: <code><<branchQuestTseOfCategoryExists category 1 targetNode>></code>''' | ||
+ | |||
+ | parameter 1: The category of TileObject to check the village-registered quest tileobjects list for. | ||
+ | |||
+ | parameter 2: The amount of the tileObject to check for (will branch if there is greater than or equal to this amount of tileObjects) | ||
+ | |||
+ | parameter 3: Title of the node to move to | ||
+ | |||
+ | |||
+ | When this function is hit, it will check the list of village-registered tileObjects for the amount of tileObjects with the category defined. | ||
+ | If there are equal to or more tileObjects than the count defined, it will move to the specified node. | ||
+ | |||
+ | |||
+ | === placeQuestTileObjectsAtTotem === | ||
+ | '''Usage: <code><<placeQuestTileObjectsAtTotem totemCode tileCode 1 10>></code>''' | ||
+ | |||
+ | parameter 1: The code of the totem to place tileObjects around | ||
+ | |||
+ | parameter 2: The code of the tileObject to place | ||
+ | |||
+ | parameter 3: the amount of tileObjects to place | ||
+ | |||
+ | parameter 4: the radius around the totem in which to place the tileObjects | ||
+ | |||
+ | When this function is hit, it will place the defined count of tileObjects randomly around the totem defined, using the radius defined. | ||
+ | These entities will be registered with the village for use in other Quest TSE-based commands. | ||
+ | (If no totem with the code exists it will not place any tileObjects) |
Latest revision as of 23:54, 11 July 2019
In Staxel, there are two files which are used to specify all villager dialogue in game. These files are the *.dialogue files which point to an associated .json file that was created using Yarn.
Contents
- 1 Creating New Dialogue
- 2 Config Options
- 3 The Yarn *.json file
- 4 Additional Dialogue Functions
- 4.1 Branching Functions
- 4.1.1 branchAchievementNotCompleted
- 4.1.2 branchAndLoadMissingCriticalTotem
- 4.1.3 branchBuildingHasExisted
- 4.1.4 branchCurrentSeasonIs
- 4.1.5 branchMissingTotem
- 4.1.6 BranchValidStructureExistsWithTier
- 4.1.7 branchNotServerOwner
- 4.1.8 branchPlayerCantAffordItem
- 4.1.9 branchPlayerDoesntHaveItemOfCategory
- 4.1.10 branchPlayerDoesntHaveEnoughOfItem
- 4.1.11 branchPlayerDoesntHavePlayerItem
- 4.1.12 branchPlayerHasItem
- 4.1.13 branchNoVillagerWithPersonality
- 4.1.14 branchNoVillagerWithName
- 4.1.15 branchValidStructureExists
- 4.1.16 BranchValidStructureExistsWithTier
- 4.2 Dialogue Control Functions
- 4.3 Useful Functions
- 4.3.1 adjustReputation
- 4.3.2 emote
- 4.3.3 giveItemToPlayer
- 4.3.4 giveItemToPlayerIfDoesntHave
- 4.3.5 giveItemToPlayerIfCantAfford
- 4.3.6 givePlayerPetals
- 4.3.7 givePlayerPetalsIfInsufficient
- 4.3.8 giveUnlockedAchievementRewards
- 4.3.9 giveRandomPet
- 4.3.10 loadItemBuyPrice
- 4.3.11 loadRandomNumber
- 4.3.12 loadTotemExistence
- 4.3.13 loadVillagerName
- 4.3.14 loadVillagerNameForPersonality
- 4.3.15 playExpression
- 4.3.16 playerPurchaseItem
- 4.3.17 moveTo
- 4.3.18 leadTo
- 4.3.19 removePlayerItem
- 4.3.20 removeAllOfPlayerItem
- 4.4 Quest Functions
- 4.5 Villager Arrival Functions
- 4.6 Coming Soon (Village-Registered TSE Functions)
- 4.1 Branching Functions
Creating New Dialogue
The dialogue system was created using Yarn. This gives much more power to the dialogue system but in addition causes a lot more issues when trying to explain. This tutorial will try to explain as much as possible, with as little confusion as possible.
Setup
Yarn, thankfully, has its own software to help you out when you create dialogue. The Yarn Editor can be used to heavily speed up dialogue creation as you can focus on creating the text, rather than having to format files correctly. To help you out, here are steps in order to get ready for dialogue creation;
- Download the latest version of the editor: http://infiniteammo.com/Yarn/Yarn-2016-08-15-win.zip (Link subject to change)
- Extract the file to a location you want.
- Download bartwe's yarn edit: https://github.com/bartwe/Yarn
- Drag all files in the app folder to yarn's folder, merge and replace all files.
- Run Yarn.exe in the new folder.
You can also set up a start menu shortcut to the exe by Right Clicking Yarn.exe then clicking Pin To Start.
Creating the dialogue
Hopefully you will have started Yarn and been greeted with this screen;
Here is a brief explanation of all of the UI elements.
- In the top left is the search bar and search options. Useful when creating large files, but not needed in this tutorial.
- In the center, is a box. This box is what is called a node. It has a title, in this case "Start", and a body containing "Empty Text". When you are hovering over the box more options will appear;
- The left and right arrows will change the colour of the title. Useful for large files and organisation.
- A rubbish bin for deleting the node. This will delete everything in the node.
- In the top right is two buttons;
- The +Node button adds another box (Which is called a node). This will be used later.
- The File button is a drop down for allowing you to load and save files. You will be mainly using the "Open..." and the "Save as JSON..." options.
That's good and all but how does that help us create dialogue? Well good question, here is how.
Double Click on the node in the middle. A new window should appear like below;
Again here is a brief explanation of the new window;
- In the top is the title. For now keep this as "Start". (One node titled "Start" must exist for every dialogue file.
- Underneath the title, is another line. This is for adding tags to this node. This is a mostly unused feature for Staxel however.
- Under the two lines, is the body. This is where all the dialogue will be going.
With that out of the way, we shall start writing dialogue. However you will need to add stuff so that it can set the game up right. Add the following to the "Start" node.
<<lockPlayerInConversation>> <<typewriterMode on>>
All three of these are what is known as "Functions". These do special stuff in the game and is always surround by << >>
. We will probably end up using more of these later. For now here is an explanation for each line;
-
<<lockPlayerInConversation>>
: This makes it so the player cannot walk away from the conversation. It'll also bring the camera towards the NPC and also activate the black bars. Skipping this line sets it up more like the Merchants in the town square. -
<<typewriterMode on>>
: This makes the game write every character 1 by 1, instead of writing the entire line at once. The "on" part is a parameter, which tells the function that we want the typewriter to be on.
Most new dialogues will have these two lines at the very start. (With the main exceptions being the Town Square merchants.) From now on we will be focusing on writing stuff that will actually appear to the player.
While still in the "Start" node, you should add the following lines;
<<if $met_player != 1>> [[Hello]] <<else>> [[Choice]] <<endif>>
This particular code sets up a simple "Greet the player if you haven't met them yet. Otherwise go to other dialogue.". A quick explanation below.
- Line 1: This is an if statement, which is checking for the variable "$met_player" is not equal to 1. On the first run this will not be true.
- Line 2: This section happens if the if statement was true. Then it will reach this line. <code>[[Hello]]</code> is the code in order to send the dialogue to the node with the title "Hello".
- Line 3: This ends the first block. It only passes here is the if statement was false.
- Line 4: Similar to line 2. This section happens when the if statement is false. It will go to the node labelled <code>[[Choice]]</code>.
- Line 5: Needed to end the If section. (Always need to go If → End If. e.g. If → elseif → else → endif)
With that, click outside of the box onto the dark area. With that click the +Node button in the top left of the screen. Click and drag the new box to the left. You should have something similar to this;
Double click on the new node. Name this node exactly "Hello". This will be the node that we want to add our greeting to. (Finally some actual dialogue!). Feel free to add your own text but here is some example text;
Hey there! I was waiting to see if you would show up. I've always been fond of farmers. But the last one left. So it'll look like we'll probably be good friends. Well I gotta get going. I'll see you later.
Any old greeting will do. That being said, the game will show one line at a time. As such, "Hey There!" will be it's own textbox. After the player clicks "I've always been fond of farmers. But the last one left." Will be shown next. An example of such as below;
// Add in greeting showoff.
As a note do not let your lines get too long. Staxel does not handle lines that are too long yet.
With that we probably want to end this node off properly first. Add the following two lines to the end of the node.
<<set $met_player = 1>> [[End]]
The first line sets it the initial if statement to go the other direction again. (So we don't greet twice.) The second line sets this to go to a completely new node called "End".
Lets go set that new node up. Create a new node. Drag it downwards. Double click on it. Name it "End". This will be a very simple node, and as such just copy and past the following into it.
<<typewriterMode off True True>> <<releasePlayerFromConversation>>
And that's it. These two lines do the following;
- <<typewriterMode off True True>>: This is the "typewriterMode" mode function again. But this time it has the parameters "off", "True" and "True". The off is self explanatory (It turns typewriter off), but the "True True" cleans up the dialogue at the end.
- <<releasePlayerFromConversation>>: Does exactly on the tin. Releases the player from the conversation, by giving them back movement and free roaming camera.
And that's it. Your first dialogue line is complete. Although as you may have noticed, we still have another path to go. But first double check you have something similar to;
Now is probably a good time to save the file. Go to File → Save As Json...
and save the file.
By this point, it may be worth saying that you can zoom in and out by using the scroll wheel and move around with the arrow keys. (Although the arrow keys are a pain in this version.)
Next lets continue on with the new branch. Create a node that has the title, "Choice". Add the following to it's body;
<<requestGoToQuestIfAvailable>> <<pickRandomPath>> <<BranchingPath>> <<MultipleOptionTest>> <<SellingAnItem>> <<flushRandomPath>>
This probably looks like a mess of characters at this point. So here is the explanation for each line;
- Line 1:
<<requestGoToQuestIfAvailable>>
: This is used to tell the game that it's OK to go to the quest that the game has. If there is no quest then it'll go to Line 2 instead. - Line 2:
<<pickRandomPath>>
: This is a special function that tells the game to look at all the lines below, up until <<flushRandomPath>>. And randomly choose one of these lines as the direction we want to go. - Line 3-5: These are all functions that contain the title of the node to go to. In essence these are the same as <code>[[BranchingPath]], [[MultipleOptionTest]], [[SellingAnItem]]</code>.
- Line 6:
<<flushRandomPath>>
: This line tells<<pickRandomPath>> to stop going any further.
With that under way. Lets create another node and title it "BranchingPath". Add the following to the file:
This is an example of something that causes a branching path. <<branchCurrentSeasonIs Summer SummerNode>> Today is quite cool you know. I feel like summer is just around the corner though. [[End]]
This node is fairly self explanatory except for the second line. This second line is another Function with the name "branchCurrentSeasonIs". This function takes two inputs, this case "Summer" and "SummerNode". It will take the first input and compare it to the current season. So if you input "Summer" it will try to compare that to the game's current season. (Other inputs are "Winter", "Autumn" and "Spring".) If the season is indeed Summer then it will take the second input and then make the dialogue go to that note. That is, if it is "Summer", then make the dialogue do the same as <code>[[SummerNode]]. Otherwise just make it go on like normal.
Lets fill this branch out by add another node named "SummerNode". Add something like the following to it;
Argh! It's summer! I hate it when it is summer. I just want to stay inside but there is nothing to do. [[End]]
At this point the file should start looking like;
Don't forget to save before continuing.
Lets get onto the second random choice. Create another node named "MultipleOptionTest". Then add the following to it.
Hey! Do you like Cats? [[Yes!|MultChoiceYes]] [[No.|MultChoiceNo]]
This actually sets up a multiple choice. The 3rd line [[Yes!|MultChoiceYes]]
sets up an option that says "Yes!" and when that is chosen it will go to the node [[MultChoiceYes]]
. Similar for [[No.|MultChoiceNo]]
.
Lets create both of those nodes then. First lets create the first node, "MultChoiceYes". Add the following to that as well;
Nice! They are pretty cute right. [[End]]
And a similar thing for "MultChoiceNo".
Boo! Cats are love. Cats are life. Come back to me when you believe! [[End]]
And now you have another branch going. Only 1 more to go for this tutorial. The file is probably starting to look like some mess similar to;
Now we just have the final branch. Create another node named "SellingAnItem". In this add the following.
<<loadItemBuyPrice item staxel.item.crafting.RawStone 1 $stone>> Oh hi there! I was looking to sell this fine looking rock. Do you want it? [[Yes! ($currency;$stone;)|BuyYes]] [[No.|BuyNo]]
So this will take a little bit of explaining.
- Line 1:
<<loadItemBuyPrice item staxel.item.crafting.RawStone 1 $stone>>
: This finds the item "staxel.item.crafting.RawStone" and grabs the price of "1" of them. It will then place the price in the variable $stone (Remember back to $met_player?). - Line 4: This is exactly like the options that we made before. Except there is something special to it. "Yes!($currency;$stone;)" will basically translate to "Yes! ($3)" (Except using the petals sign). This is because $currency is a global variable which contains the currency symbol, and the price is stored in the other variable.
With that we need to create a new node titled "BuyYes". Add the following to it;
<<branchPlayerCantAffordItem item staxel.item.crafting.RawStone 1 CantAfford>> Here you go! <<playerPurchaseItem item staxel.item.crafting.RawStone>> [[End]]
Again some explanation;
- Line 1: This is very similar to our BranchCurrentSeasonIs function that we used before. But this is checking whether or not the player can afford the item. If not go to "CantAfford" instead.
- Line 3: The function to actually purchase the item.
With that create a node titled "CantAfford". Then add the following;
Oh. It looks like you don't have money. Well I'll just throw it away, I guess. [[End]]
And then finally lets set up the node, "BuyNo". Add the following to it;
Oh really? Fine. Looks like I'll just throw it away then. [[End]]
And with that you have a dialogue file! It should be looking similar to;
That must have taken forever. Make sure to save the file and then with that you are ready to continue on.
Creating the *.dialogue file
Before you start this part of the tutorial, be sure to head through Modding#Getting Started with Staxel Modding.
Adding the Dialogue via Asset Manager
Follow Modding#Using the AssetManager to Create Mods to open up the Asset Manager.
With the Asset Manager open, head to View → Characters and Animals → Villager Assets
. When the new window is open, head to Asset → Add → New Asset
and the following window will show up.
First click on the button Asset Path and navigate upwards to the /content/
folder. Once there, open the /mods/
folder and create a new folder. Name this new folder to what you want the mod to be called and then open this new folder. When you open this folder give the asset a name, then click on the drop down and select Dialogue Asset. Then click save, give the item a code then click OK.
After the asset is created, it will have been automatically selected. With that there is only one thing to do right now. Tell the game where the "*.json" is.
- Click on the Dialogue. Click on the [...]. Navigate to the Dialogue file you created before. And then click OK.
With that, hit Crtl+S to save the file. And then go to File → All Assets → Build and Validate Assets
. If this succeeds, then HURRAY! you have a new tile in the game. If it fails, try and read the error to see what you have done wrong.
However, this Dialogue is currently useless. You will need to follow Dialogue Pools#Creating New Dialogue Pools.
Adding the Dialogue via Text Files
Follow Modding#Using a Text Editor to Create Mods in order to be properly set up for this step.
Creating this file is very simple as it only two properties. The full file will looks like;
{ "code" : "mods.modname.village.character.dialogue.CecileFond", "dialogue" : "staxel/village/character/dialogue/CecileFond.json" }
With the file being this short, there is no need for pictures. Here is the explanation of the two properties.
- "code": A unique String that would be used to identify this object from others. For example this is like "staxel.item.crafting.BakingPowder" or "staxel.tile.grass". You will most commonly want to use you use the path to the Accessory Model but replace
/
with.
, as this will ensure your design will have a different code to all other designs.
- "dialogue": A String that is the path to the dialogue you created in the first section. The path starts at the
/content/
directory and therefore will mostly start withmods/modname/
.
After you have done editing the file, head to gamedata/bin/
folder, and start up Staxel.ContentBuilder.exe. When this has started up, click "Tag dialogue and generate language file". This will open up a file browser. Go to your newly created file (The .dialogue file from the first section.) and select that. After that, click Validate Resources<tt> and wait until the progress bar has done. And with that you should have a working item. If you are confused then go to the #Modding channel on Discord and ask there.
However, this Dialogue is currently useless. You will need to follow Dialogue Pools#Creating New Dialogue Pools.
Config Options
"code"
Valid options (String): A unique string which dialogue what this object is.
Default Value: No default value is specified. Always need to provide your own.
A string containing the unique identifier of this dialogue. This is commonly only used in Dialogue Pools.
"dialogue"
Valid options (String): A string which contains the path to a Yarn .json file.
Default Value: Null or nothing specified.
A string containing the path of the item the blob will be referring to.
The Yarn *.json file
Yarn is the program which creates the dialogue files for Staxel. It utilises it's own scripting language which can make choices and also use conditional statements in order to provide the right dialogue. They also include an which helps visualise these files.
Look at the documentation around Yarn, particularly sections such as this. Do not Yarn is changing frequently and documentation might not line up with the implementation used in Staxel.
Additional Dialogue Functions
These are additional functions that Staxel offers to integrate the dialogue into the game. They range from functions that do decision making to functions which give and take items and money from the player.
Branching Functions
These functions cause the game to go to a different dialogue when a certain condition is met.
branchAchievementNotCompleted
Usage: <<branchAchievementNotCompleted staxel.achievement.PlantCrop PlantingWait>>
Parameter 1: Code of the Achievement you want to check. (e.g. staxel.achievement.PlantCrop)
Parameter 2: Title of the Node to move to.
When this function is hit, it will check if the selected Achievement has been completed. If it has been completed it will continue on normally. If it has not been completed, then it will move to the specified node.
Useful for checking for completed actions, such as checking if the player has placed a Pet House.
branchAndLoadMissingCriticalTotem
Usage: <<branchAndLoadMissingCriticalTotem $ttm $price 1.50 TotemMissing>>
Parameter 1: The name of the variable you want to use to store the totem name. Should start with $.
Parameter 2: The name of the variable you want to use to store the price of the item. Should start with $.
Parameter 3: The premium multiplier. (The price will end up being, the cost of the totem * premium).
Parameter 4: Title of the Node to move to.
When this function is hit, check to see if a critical totem is missing. If so, then load said Totem's name to Parameter 1 and the price (multiplied by Parameter 3) to Parameter 2, then go to the node. If no critical totem is missing, then continue on normally without loading to variables.
branchBuildingHasExisted
Usage: <<branchBuildingHasExisted staxel.totem.workplace.Patisserie Existed>>
Parameter 1: Code of the Totem you want to check. (e.g. staxel.totem.workplace.Patisserie)
Parameter 2: Title of the Node to move to.
When this function is hit, it will check if the specified Totem has been completed at some point (i.e Has been built). If it hasn't then continue on normally. If it has been completed, then move to the specified node.
This is useful for making sure you only talk about buildings that exist or have existed. (Note: Building does need to have been built before. Just placing totem doesn't count.)
If you require that it does exist then check #branchValidStructureExists.
branchCurrentSeasonIs
Usage: <<branchCurrentSeasonIs Summer SummerNode>>
Parameter 1: Summer, Winter, Spring, Autumn
Parameter 2: Title of the Node to move to.
When this function is hit, check to see if the Season matches parameter 1. If so branch, otherwise continue normally.
branchMissingTotem
Usage: <<branchMissingTotem staxel.totem.AirshipLanding HouseMissing false>>
Parameter 1: Code of the Totem you want to check. (e.g. staxel.totem.AirshipLanding)
Parameter 2: Title of the Node to move to.
Parameter 3: Whether or not this totem should have been built to it's lowest tier.
When this function is hit, it will check to see if the totem is missing. If parameter 3 is true, then it will check if the villager has a built totem of this type. If it does continue and if not branch. If parameter 3 is false, then it will check if the totem has either been place or exists in the players inventory. If either of those are true, continue normally and branch if not.
useful for when you want to check if a totem has been lost before giving another totem.
Mainly used by Farm Fan to give the player rewards. Not too useful for other players.
BranchValidStructureExistsWithTier
Usage: <<BranchValidStructureExistsWithTier staxel.totem.AirshipLanding 1 AirshipAvailable>>
Parameter 1: Code of the Totem you want to check. (e.g. staxel.totem.AirshipLanding)
Parameter 1: The lowest Tier of the existing building you want.
Parameter 3: Title of the Node to move to.
When this function is hit, it will search to see if a valid totem of the type specified exists. If it does, check if it has a tier at or higher than specified. If it succeeds, then it will head to the specified node. Otherwise if it does not exist or it's not a high enough tier then continue on normally.
Useful for checking that a building actually exists, and is at a certain tier, before going to it/ talking about it. (e.g. Making a villager complain that a building is not max tier.)
If you want to know that the building existed at some point then head to #branchBuildingHasExisted. Or if you just want it to exist, head to #branchValidStructureExists
branchNotServerOwner
Usage: <<branchNotServerOwner NotOwner>>
Parameter 1: Title of the Node to move to.
When this function is hit, it will check if the player is the server owner. If they are, then it will head to the specified node, otherwise continues on normally.
Mainly used by Farm Fan to make sure that only the server owner gets the tutorial.
branchPlayerCantAffordItem
Usage: <<branchPlayerCantAffordItem item staxel.item.crafting.MugOSap 1 CantAfford>>
Parameter 1: Can be item, tilePlacer, plant, recipe or clothing
. Use item for Items. Use tilePlacer for Tiles. Use plant for seeds. Use recipe for Recipes and use clothing for Accessories.
Parameter 2: Code of the thing you want to buy. (e.g. staxel.item.crafting.MugOSap)
Parameter 3: Number of the item you want the player to buy.
Parameter 4: Title of the Node to move to.
Parameter 5: (Optional) The multiplier to the price. (i.e. 2.00 to make it 2 times as expensive. 0.5 to make it half as expensive.)
When this function is hit, it will check if the player can afford the item. If they can then continue on normally. If they can't then move onto the specified node.
This is useful for checking if the player can actually afford the item.
branchPlayerDoesntHaveItemOfCategory
Usage: <<branchPlayerDoesntHaveItemOfCategory seed PlantingGive>>
Parameter 1: Category to look for for any item in the player's inventory.
Parameter 2: Title of the Node to move to.
When this function is hit, it will check if the player has an item with the specific category. If they do, continue on normally and if they don't, move to the specified node.
This is useful for checking if the player has an item that the NPC wants. (For example, check for seeds so that the tutorial can teach the player how to place them.)
branchPlayerDoesntHaveEnoughOfItem
Usage: <<BranchPlayerDoesntHaveEnoughOfItemstaxel.item.FarmRegistrationLetter 2 GoodBye>>
Parameter 1: Code of the Item you want to check. (e.g. staxel.crop.tomato)
Parameter 2: The minimum number of the item you want.
Parameter 3: Title of the Node to move to.
When this function is hit, it will check if the player has an item of a specific code. If they do check if it meets the minimum requirement, if so continue on normally and if not, move to the specified node.
This is useful for checking if the player has an enough of an item that the NPC wants. (For example, check for seeds so that the tutorial can teach the player how to place them.)
branchPlayerDoesntHavePlayerItem
Usage: <<branchPlayerDoesntHavePlayerItem staxel.item.FarmRegistrationLetter GoodBye>>
Parameter 1: Code of the Item you want to check. (e.g. staxel.crop.tomato)
Parameter 2: Title of the Node to move to.
When this function is hit, it will check if the player has an item of a specific code. If they do, continue on normally and if they don't, move to the specified node.
This is useful for checking if the player has an item that the NPC wants. (For example, check for seeds so that the tutorial can teach the player how to place them.)
branchPlayerHasItem
Usage: <<branchPlayerHasItem staxel.item.crafting.MugOSap CantAfford>>
Parameter 1: Code of the Item you want to search for. (e.g. staxel.item.crafting.MugOSap)
Parameter 2: Title of the Node to move to.
When this function is hit, it will check if the player has the item. If they do then branch, otherwise continue on normally.
branchNoVillagerWithPersonality
Usage: <<branchNoVillagerWithPersonality staxel.village.personality.Tomboy NoTomboy>>
Parameter 1: Code of the Villager Personality to search for. (e.g staxel.village.personality.Tomboy)
Parameter 2: Title of the Node to move to.
When this function is hit, it will search to see if a villager with the specified personality exists in the world. If they do, continue on normally and if they don't, move to the specified node.
This is useful for when you want to talk about another type of villager that may or may not be in the village.
branchNoVillagerWithName
Usage: <<branchNoVillagerWithName Leif TellRumour>>
Parameter 1: Name of villager to look for.
Parameter 2: Title of the Node to move to.
When this function is hit, it will search to see if a villager with the specified name exists in the world. If they do, continue on normally and if they don't, then move to the specified node.
This is useful for when you want to talk about another specific villager that may or may not be in the village. It is probably better to use #branchNoVillagerWithPersonality as it is more specific.
branchValidStructureExists
Usage: <<branchValidStructureExists staxel.totem.AirshipLanding AirshipAvailable>>
Parameter 1: Code of the Totem you want to check. (e.g. staxel.totem.AirshipLanding)
Parameter 2: Title of the Node to move to.
When this function is hit, it will search to see if a valid totem of the type specified exists. If it does, then head to the specified node otherwise it continues on normally.
Useful for checking that a building actually exists, and is still existing, before going to it/ talking about it.
If you want to know that the building existed at some point then head to #branchBuildingHasExisted.
BranchValidStructureExistsWithTier
Usage: <<BranchValidStructureExistsWithTier staxel.totem.AirshipLanding 1 AirshipAvailable>>
Parameter 1: Code of the Totem you want to check. (e.g. staxel.totem.AirshipLanding)
Parameter 1: The lowest Tier of the existing building you want.
Parameter 3: Title of the Node to move to.
When this function is hit, it will search to see if a valid totem of the type specified exists. If it does, check if it has a tier at or higher than specified. If it succeeds, then it will head to the specified node. Otherwise if it does not exist or it's not a high enough tier then continue on normally.
Useful for checking that a building actually exists, and is at a certain tier, before going to it/ talking about it. (e.g. Making a villager complain that a building is not max tier.)
If you want to know that the building existed at some point then head to #branchBuildingHasExisted. Or if you just want it to exist, head to #branchValidStructureExists
Dialogue Control Functions
These functions determine how the dialogue looks and feels to the player.
lockPlayerInConversation / releasePlayerFromConversation
Usage: <<lockPlayerInConversation>>
or <<releasePlayerFromConversation>>
LockPlayerInConversation forces the player to enter into conversation mode. Conversation mode does several things;
- Stop the player from moving.
- Brings in the black bars
- Focuses player focus onto the NPC
ReleasePlayerFromConversation removes conversation mode from the player. Allowing them to move off and end the conversation. A <<typewriterMode off true true>>
should be placed with this command if <<typewritermode on>>
was present.
This is used for all dialogue that is personal to the player. (i.e. Not merchant chatter.)
moveToNext
Usage: <<moveToNext>>
Proceed to the next Dialogue immediately after displaying. This is mainly used in order to complete conversations properly and not wait for an input. This is because if the dialogue goes to an empty line, it will do a couple things, such as adjust the NPC's reputation.
Not needed if using #typewriterMode as the same thing is done in <<typewriterMode off true true>>.
pickRandomFromDialoguePools
Usage: <<pickRandomFromDialoguePools>>
Make the villager go to a new random Dialogue. This chooses from a number of different dialogues and can be quite complicated to follow. Here are the steps it takes;
- Add any dialogues overrides provided by Festivals to the list of options first.
- If Villager Personalities#"suppressGeneralDialogue" is false and, if overriden by a festival, Festivals#"suppressPersonality" is false then proceed to sub steps.
- If the villager is preparing to leave town and their home is still gone or broken, then immediately return a Random Dialogue that is in a Dialogue Pool with the Dialogue_Pools#"type" leaving.
- If not preparing to leave, check if villager has doesn't have a quest.
- Check to see if Player has finished their Farm License. If not add that to the list of options.
- Add in a Random Dialogue that is in a Dialogue Pool with the Dialogue_Pools#"type" general.
- If the weather has dialogue pools, and it isn't night time. Then add one of those in as well.
- If the player has theft recently, then add in a Random Dialogue that is in a Dialogue Pool with the Dialogue_Pools#"type" theft.
- If the villager is not overriden or if overriden by a festival, Festivals#.22suppressPersonality.22 is false then proceed to sub steps.
- Add in a random Base Unique Dialogue Pool.
- Add in a random Liked Unique Dialogue Pool if high enough reputation.
- Add in a random Fond Unique Dialogue Pool if high enough reputation.
- Add in a random Best Friend Unique Dialogue Pool if high enough reputation.
- Add in a random Villager Personalities#"dialoguePools".
- If season has Dialogue associated with it, add in a random season dialogue.
- If Villager has a Job, is not overriden or if overriden by a festival, Festivals#.22suppressPersonality.22 is false then proceed to sub steps.
- If They are working. That is the time is between their work time. Then continue to sub steps.
- If Workplace is missing then add in a Random Dialogue that is in Villager Jobs#"workPlaceMissingPools" with the Dialogue_Pools#"type" WorkPlaceMissing.
- If it exists, then add in a Random Dialogue that is in Villager Jobs#"dialoguePools" with the Dialogue_Pools#"type" Job.
- If They are working. That is the time is between their work time. Then continue to sub steps.
- If the villager does not have a job, is not overriden or if overriden by a festival, Festivals#.22suppressPersonality.22 is false then add in a Random Dialogue that is in a Dialogue Pool with the Dialogue_Pools#"type" Unemployed.
- With that, choose a random dialogue out of all of the dialogues added.
TLDR: Choose a random dialogue based on a lot of circumstances, with special attention being paid to Festivals overriding dialogue.
This is most often used by Workers, as they have their working dialogue prioritised. This allows them to still use their personality even while working. (For examples look at Mayor Dialogue and Mechanic Dialogue.)
pickRandomLine
Usage:
<<pickRandomLine>> This is line 1. This is line 2. <<flushRandomLine>>
Choose a single line, from a number of text only lines, randomly up either up to the end of the node or up to the command <<flushRandomLine>>. Used to select either a random section of text so that it doesn't repeat the same text too often.
pickRandomPath
Usage:
<<pickRandomPath>> <<NodeName1>> <<NodeName2>> <<flushRandomPath>>
Choose a single line, from a number of node names, randomly up either up to the end of the node or up to the command <<flushRandomPath>>. Used to select a random node to go to so the same section of text isn't repeated often. Less clutter, in the one node, than #pickRandomPath when dealing with larger conversations.
resumeProgress
Usage: <<resumeProgress>>>>
Resume the last node that was saved for the current player. If there is no saved value or if saved value is the "Start" node then continue on the current node.
saveProgress
Usage: <<saveProgress>> or <<saveProgress NodeA>>
Parameter 1: The title of the node to save. (Skipping means the last node is saved.)
This saves the current node to a variable which is then stored. Useful for when a conversation needs to be completed. (e.g. It is used in the tutorial to save the last location Farm Fan was in.)
shuffleNextOptions
Usage: <<shuffleNextOptions>>
Make the next set of options be in a random order when shown to the player.
transitionToNew
Usage: <<transitionToNew>>
Restart the dialogue after finishing.
typewriterMode
Usage: <<typewriterMode on>> or <<typewriterMode off true true>>
Parameter 1: Turn on or off typewriter mode.
Parameter 2: (If Parameter 1 is off) Clear the message so it doesn't stay around. (Set to False to keep messages after this value)
Paremeter 3: (If Parameter 1 is off and Parameter 2 is True) Setting to True lets the current node immediately end without the need to click. (e.g Ending conversation immediately.)
Setting the typewriter to on makes it so text is filtered out a single character at a time instead of the entire message appearing at once. Should be turned off at the end of a conversation (i.e. <<typewriterMode off true true>>) before releasing from conversation.
Useful Functions
These are a collection of functions that will provide useful game benefits. This includes giving items, money and other functions.
adjustReputation
Usage: <<adjustReputation 20>>
Parameter 1: Amount to adjust by.
Adjust the player's reputation with this villager by the amount specified.
emote
Usage: <<emote staxel.emote.ScratchHead>>
Parameter 1: Code of the Emote you want to play. (e.g. staxel.emote.ScratchHead)
Play a specified emote and wait until it is finished.
giveItemToPlayer
Usage: <<giveItemToPlayer item staxel.item.tool.Hoe>>
Parameter 1: Can be item, tilePlacer, plant, recipe or clothing
. Use item for Items. Use tilePlacer for Tiles. Use plant for seeds. Use recipe for Recipes and use clothing for Accessories.
Parameter 2: Code of the thing you want to check and give. (e.g. staxel.item.tool.Hoe)
Parameter 3: (Optional) Number of the item you want to give the player.
Give an item to the player with no checks.
giveItemToPlayerIfDoesntHave
Usage: <<giveItemToPlayerIfDoesntHave item staxel.item.tool.Hoe>>
Parameter 1: Can be item, tilePlacer, plant, recipe or clothing
. Use item for Items. Use tilePlacer for Tiles. Use plant for seeds. Use recipe for Recipes and use clothing for Accessories.
Parameter 2: Code of the thing you want to check and give. (e.g. staxel.item.tool.Hoe)
Parameter 3: (Optional) Number of the item you want to give the player.
Give an item to the player if they do not have the item already.
giveItemToPlayerIfCantAfford
Usage: <<giveItemToPlayerIfCantAfford plant staxel.crop.Tomato>>
Parameter 1: Can be item, tilePlacer, plant, recipe or clothing
. Use item for Items. Use tilePlacer for Tiles. Use plant for seeds. Use recipe for Recipes and use clothing for Accessories.
Parameter 2: Code of the thing you want to check and give. (e.g. staxel.item.tool.Hoe)
Parameter 3: (Optional) Number of the item you want to give the player.
Give an item to the player if they can't afford to buy that item.
givePlayerPetals
Usage: <<givePlayerPetals 42>>
Parameter 1: Amount of Petals to give.
Give the amount of petals specified to the player.
givePlayerPetalsIfInsufficient
Usage: <<givePlayerPetalsIfInsufficient 42>>
Parameter 1: Amount of Petals to check for. Amount of Petals to give.
Give the amount of petals specified to the player if the player does not have the amount or more. (If player has less than 1000 petals, give 1000 petals)
giveUnlockedAchievementRewards
Usage: <<giveUnlockedAchievementRewards>>
Give all the unclaimed items from achievements to the player.
giveRandomPet
Usage: <<giveRandomPet >>
Give a random pet to the player.
loadItemBuyPrice
Usage: <<loadItemBuyPrice item staxel.item.crafting.MugOSap 1 $sap>>
Parameter 1: Can be item, tilePlacer, plant, recipe or clothing
. Use item for Items. Use tilePlacer for Tiles. Use plant for seeds. Use recipe for Recipes and use clothing for Accessories.
Parameter 2: Code of the thing you want to check and give. (e.g. staxel.item.tool.Hoe)
Parameter 3: Number of the item you want to give the player.
Parameter 4: The name of the variable you want to use. Should start with $.
Calculates the cost of the specified item and places the value into the variable specified.
loadRandomNumber
Usage: <<loadVillagerName 5 $rnd>>
Parameter 1: The maximum random number.
Parameter 2: The name of the variable you want to use. Should start with $.
Chooses a random number between 0-max and saves it to the variable.
Useful for doing random checks in Dialogue. (i.e. <<if $rnd > 2>>
)
loadTotemExistence
Usage: <<loadVillagerName staxel.totem.MechanicHome $rnd>>
Parameter 1: Code of the Totem to search for. (e.g staxel.totem.MechanicHome)
Parameter 2: The name of the variable you want to use. Should start with $.
Searches for a totem with the specified name. If that totem does exist in the village, then sets the variable to 1, else sets to 0.
Useful for doing random checks in Dialogue. (i.e. <<if $rnd > 2>>
)
loadVillagerName
Usage: <<loadVillagerName Cecile $c_name>>
Parameter 1: Name of villager to search for.
Parameter 2: The name of the variable you want to use. Should start with $.
Searches for a villager with the specified name. If that villager does exist, then it places their code name into the target variable.
This is used specifically for loading the right translation for the villager's name. It is probably better to use #loadVillagerNameForPersonality as it is more specific.
loadVillagerNameForPersonality
Usage: <<loadVillagerNameForPersonality staxel.village.personality.Mayor $mayor_name>>
Parameter 1: Code of the Villager Personality to search for. (e.g staxel.village.personality.Mayor)
Parameter 2: The name of the variable you want to use. Should start with $.
Searches for a villager with the specified personality. If that villager does exist, then it places their name into the target variable.
This is used specifically for loading the right translation for the villager's name.
playExpression
Usage: <<emote staxel.expression.Happy>>
Parameter 1: Code of the Expression you want to play. (e.g. staxel.emote.ScratchHead)
Play the specified expression.
playerPurchaseItem
Usage: <<playerPurchaseItem item staxel.item.crafting.MugOSap>>
Parameter 1: Can be item, tilePlacer, plant, recipe or clothing
. Use item for Items. Use tilePlacer for Tiles. Use plant for seeds. Use recipe for Recipes and use clothing for Accessories.
Parameter 2: Code of the thing you want to check and give. (e.g. staxel.item.tool.Hoe)
Parameter 3: Number of the item you want to give the player.
Purchases the item if the player can afford the item.
moveTo
Usage: <<moveTo TavernEntrance>>
Parameter 1: Waypoint Kind to find. Can be one of: Any, ChillSpot, Tutorial Spawn, NearShippingDock, NearCatalogue, Fields, Totem, Pathing, MayorsOffice, Shop, TavernEntrance, BarArea, TownSquare, ShopEntrance
Move the NPC to the nearest node of the kind specified. You cannot specify any particular node, just the closest.
leadTo
Usage: <<leadTo TavernEntrance>>
Parameter 1: Waypoint Kind to find. Can be one of: Any, ChillSpot, Tutorial Spawn, NearShippingDock, NearCatalogue, Fields, Totem, Pathing, MayorsOffice, Shop, TavernEntrance, BarArea, TownSquare, ShopEntrance
Move the NPC to the nearest node of the kind specified. Stops to wave at player if they are too far away.
removePlayerItem
Usage: <<removePlayerItem staxel.item.FarmRegistrationLetter>>
Parameter 1: Code of the Item you want to remove. (e.g. staxel.crop.tomato)
Remove the item specified if the player has it. Do nothing if there is no item.
Use this in combination with #branchPlayerDoesntHavePlayerItem to enforce that an item is needed.
removeAllOfPlayerItem
Usage: <<removePlayerItem staxel.item.FarmRegistrationLetter>>
Parameter 1: Code of the Item you want to remove. (e.g. staxel.crop.tomato)
Removes all items of the specified code if the player has it. Do nothing if there is no item.
Use this in combination with #branchPlayerDoesntHavePlayerItem to enforce that an item is needed.
Quest Functions
These functions are useful for organising quests. You will generally not have to deal with these functions unless you want to make new quests.
acceptQuest
Usage: <<acceptQuest>>
If the speaker has a quest, then activate the quest for the player. Gives the start item (i.e. Delivery Item), if needed, to the player.
branchQuestActive
Usage: <<branchQuestActive CheckCompletion>>
Parameter 1: Title of the Node to move to.
When this function is hit, it will check if the player has this person's specific quest. If the speaker has no quest or the player doesn't have the quest or the player does have the quest but it's for the wrong day, continue on normally. Otherwise go to the node.
branchQuestCompletable
Usage: <<branchQuestCompletable CompleteQuest>>
Parameter 1: Title of the Node to move to.
When this function is hit, it will check if the player has completed this person's specific quest. If the speaker has no quest or the player does have the quest but it's for the wrong day or if the quest is not complete-able then continue on normally. Otherwise go to the node.
branchQuestTarget
Usage: <<branchQuestTarget TargetDialogue>>
Parameter 1: Title of the Node to move to.
This is specifically for delivery type quests. When this function is hit, it will check if the player has a quest for the villager and if so, check to see if the the villager is the target of the quest. If the speaker has no quest for the villager or the villager is not the target then continue on normally. Otherwise go to the node.
cancelQuest
Usage: <<cancelQuest>>
If the player has a quest for the current speaker, then cancel that quest. Otherwise do nothing.
completeQuest
Usage: <<completeQuest>>
If the speaker has a quest, and it is completable then set the quest complete. Also give the quest reward.
loadVillageActiveQuestsInfo
Usage: <<loadVillageActiveQuestsInfo>>
Loads all the current quest givers. Each consecutive quest giver is stored in the variable "$quest_giver_i" where i is the number of the quest giver starting at 0. Also stores the number of quests in the variable "$quest_count".
For how to use these variables, look at the barkeep's dialogue.
requestGoToQuestIfAvailable
Usage: <<requestGoToQuestIfAvailable >>
If the villager has a quest, then go immediately to that quest.
This is used to signal to the game that it is ok to go to the quest. Most villagers should have this somewhere in their dialogue.
Villager Arrival Functions
These functions main use are to allow the player to get more villagers into the game. These are mainly intended to be only used by Mayor Maximillian.
branchAndLoadMissingArrivalQuestTotem
Usage: <<branchAndLoadMissingArrivalQuestTotem $ttm TotemMissing>>
Parameter 1: The name of the variable you want to use. Should start with $.
Parameter 2: Title of the Node to move to.
When this function is hit, check to see if a villager quest is active. If not continue normally. If a quest is active, check to see if the player has the totem. If they don't branch, otherwise continue.
branchNewVillagerArrivalQuestAvailable
Usage: <<branchQuestActive CheckCompletion>>
Parameter 1: Title of the Node to move to.
When this function is hit, check to see if an existing villager arrival quest is already ongoing. If it does exist continue on normally. If it doesn't exist, then check if a new villager arrival can be gotten. Go to the node if a quest is available, otherwise continue normally.
setAndGiveActiveVillagerArrivalQuestTotem
Usage: <<SetAndGiveActiveVillagerArrivalQuestTotem>>
Get the new villager arrival quest, and save it. (Thus giving you the quest.) Then give the totem to the player.
giveActiveVillagerArrivalQuestTotem
Usage: <<giveActiveVillagerArrivalQuestTotem>>
If a quest is ongoing, then give the player the totem associated with the quest.
Coming Soon (Village-Registered TSE Functions)
These functions main use are to register, place and track TileObjects for use in Quests.
branchQuestTseOfCategoryExists
Usage: <<branchQuestTseOfCategoryExists category 1 targetNode>>
parameter 1: The category of TileObject to check the village-registered quest tileobjects list for.
parameter 2: The amount of the tileObject to check for (will branch if there is greater than or equal to this amount of tileObjects)
parameter 3: Title of the node to move to
When this function is hit, it will check the list of village-registered tileObjects for the amount of tileObjects with the category defined.
If there are equal to or more tileObjects than the count defined, it will move to the specified node.
placeQuestTileObjectsAtTotem
Usage: <<placeQuestTileObjectsAtTotem totemCode tileCode 1 10>>
parameter 1: The code of the totem to place tileObjects around
parameter 2: The code of the tileObject to place
parameter 3: the amount of tileObjects to place
parameter 4: the radius around the totem in which to place the tileObjects
When this function is hit, it will place the defined count of tileObjects randomly around the totem defined, using the radius defined. These entities will be registered with the village for use in other Quest TSE-based commands. (If no totem with the code exists it will not place any tileObjects)