Difference between revisions of "How to create a basic adventure with quests, dialog and scripts"

From Divinity Engine Wiki
Jump to: navigation, search
m
m (Tightened up introduction)
 
(24 intermediate revisions by the same user not shown)
Line 1: Line 1:
 
 
<div class="noautonum">__TOC__</div>
 
<div class="noautonum">__TOC__</div>
  
Line 5: Line 4:
 
----
 
----
  
I love to write stories, and the promise of a game engine that would allow me to create interactive-and-engaging stories appealed to me.  After spending a week learning everything I could about creating realistic levels and terrain, I moved on to working with quests and scripting.... which shortly hit a road-block when I began to get frustrated when my scripts wouldn't work no matter what I tried.
+
This guide will take you through the steps to create a basic adventure -- visual heavy, it is aimed at beginners who want to get started on their custom adventures as quickly as possible.
  
Four days later, I worked it out and decided to put together a basic-adventure guide that would help other modders to more quickly understand the engine so more of us can move on to putting together custom adventures :-). Overall I would like to touch on every system in the game, for a complete reference guide to everything.  Please feel free to also request custom tutorials for different scripts or areas of the engine and I'll integrate them into our evolving story / adventure.
+
== Create your new project and basic level ==
 +
We will be creating a Story mode Adventure, with the main focus being assisting a little girl to find her mummy's medicine. To that end, please create a new Adventure, targeted for story mode with the name '''HelpMyMummy'''.
  
== 1. Create your new project and basic level ==
+
<span style="color:#ffffff">'''1.1. Create a new adventure type project, targeted at Story mode'''</span>
We will be creating a Story mode Adventure, with the main focus being assisting a little girl to find her mummy's medicine. To that end, please create a new Adventure, targeted for story mode with the name '''HelpMyMummy'''.
 
  
=== 1.1. Create a new adventure type project, targeted at Story mode ===
 
 
Create a new project by pressing the green create project button on the top left.  Select the '''Adventure''' project type, and target the project for '''Story''' mode.  Use whatever name you like for the project name – for our tutorial adventure I have called the project '''HelpMyMummy'''.
 
Create a new project by pressing the green create project button on the top left.  Select the '''Adventure''' project type, and target the project for '''Story''' mode.  Use whatever name you like for the project name – for our tutorial adventure I have called the project '''HelpMyMummy'''.
  
 
[[File:BasicAdventure 1 1 SelectYourProjectType.png|none|left|Select your project type|600px]]
 
[[File:BasicAdventure 1 1 SelectYourProjectType.png|none|left|Select your project type|600px]]
  
=== 1.2. Create a new basic level template, called 'TheVillage' ===
+
<span style="color:#ffffff">'''1.2. Create a new basic level template, called 'TheVillage' '''</span>
 +
 
 
Select the '''Basic''' level template, and call your level '''TheVillage''' – or whatever other name you prefer.
 
Select the '''Basic''' level template, and call your level '''TheVillage''' – or whatever other name you prefer.
  
 
[[File:BasicAdventure 1 2 CreateNewBasicLevelTemplate.png|none|left|Create new basic level template|600px]]
 
[[File:BasicAdventure 1 2 CreateNewBasicLevelTemplate.png|none|left|Create new basic level template|600px]]
  
== 2. Add a character ==
+
== Add a character ==
 
We'll keep this bare-boned and simple, placing a character into the level and updating the bits and pieces we will require for the next steps.  We named her '''Elena''' <span style="color:#f1c40f">(5)</span> and used Larian coding standards to give her a reference name of '''S_TV_Elena''' <span style="color:#f1c40f>(6)</span>.  For this stage, feel free to use any character and name.
 
We'll keep this bare-boned and simple, placing a character into the level and updating the bits and pieces we will require for the next steps.  We named her '''Elena''' <span style="color:#f1c40f">(5)</span> and used Larian coding standards to give her a reference name of '''S_TV_Elena''' <span style="color:#f1c40f>(6)</span>.  For this stage, feel free to use any character and name.
  
 
{{note|Highly recommended we follow Larians coding standards for consistency and because they make our job easier long term, both in understanding each-other's scripting and in reducing future 'lookup' time finding more info about items we wish to refer to.}}
 
{{note|Highly recommended we follow Larians coding standards for consistency and because they make our job easier long term, both in understanding each-other's scripting and in reducing future 'lookup' time finding more info about items we wish to refer to.}}
  
=== 2.1. Create a new NPC character model and place it into the level ===
+
<span style="color:#ffffff">'''2.1. Create a new NPC character model and place it into the level'''</span>
  
 
Find the '''Humans_Children''' <span style="color:#f1c40f">(1,2)</span> model and place it into the level <span style="color:#f1c40f">(3,4)</span>, naming her '''Elena''' <span style="color:#f1c40f">(5)</span>.  To keep in line with standards, for her reference, use the name '''S_TV_Elena''' <span style="color:#f1c40f">(6)</span>.  The '''S''' is to let the engine know that we want to reference this local object in the story and the '''TV''' is the prefix for our '''TheVillage''' level.
 
Find the '''Humans_Children''' <span style="color:#f1c40f">(1,2)</span> model and place it into the level <span style="color:#f1c40f">(3,4)</span>, naming her '''Elena''' <span style="color:#f1c40f">(5)</span>.  To keep in line with standards, for her reference, use the name '''S_TV_Elena''' <span style="color:#f1c40f">(6)</span>.  The '''S''' is to let the engine know that we want to reference this local object in the story and the '''TV''' is the prefix for our '''TheVillage''' level.
Line 35: Line 34:
 
[[File:BasicAdventure 2.1 CreateNPCModel.png|none|left|Create new NPC character|800px]]
 
[[File:BasicAdventure 2.1 CreateNPCModel.png|none|left|Create new NPC character|800px]]
  
== 3. Create a simple dialog and save it ==
+
== Create a simple dialog and save it ==
 
In this section we are going to create a simple quest dialog so we can talk with our NPC character and begin a quest.
 
In this section we are going to create a simple quest dialog so we can talk with our NPC character and begin a quest.
  
=== 3.1. Create the start of a simple dialog ===
+
<span style="color:#ffffff">'''3.1. Create the start of a simple dialog'''</span>
  
 
Open up the '''Dialog Editor''' <span style="color:#f1c40f">(1)</span> and create a simple dialog between players and your NPC character.  Create a new '''Greeting''' dialog <span style="color:#f1c40f">(1)</span> and enter the initial greeting <span style="color:#f1c40f">(3)</span>.  Once done press the <b>'x'</b> button <span style="color:#f1c40f">(4)</span> to save your changes and close the '''Edit Tagged Texts''' window.
 
Open up the '''Dialog Editor''' <span style="color:#f1c40f">(1)</span> and create a simple dialog between players and your NPC character.  Create a new '''Greeting''' dialog <span style="color:#f1c40f">(1)</span> and enter the initial greeting <span style="color:#f1c40f">(3)</span>.  Once done press the <b>'x'</b> button <span style="color:#f1c40f">(4)</span> to save your changes and close the '''Edit Tagged Texts''' window.
Line 44: Line 43:
 
[[File:BasicAdventure_3.1_CreateSimpleDialog.png|none|left|Create simple dialog|550px]]
 
[[File:BasicAdventure_3.1_CreateSimpleDialog.png|none|left|Create simple dialog|550px]]
  
=== 3.2.Save the dialog as 'TV_Elena_Dialog' ===
+
<span style="color:#ffffff">'''3.2. Save the dialog as 'TV_Elena_Dialog' '''</span>
  
 
Take this moment to save the dialog.  We know the prefix for this level is '''TV''', that our character is called '''Elena''' and we are referencing a Dialog - thus: '''TV_Elena_Dialog''' <span style="color:#f1c40f">(2)</span>, which we entered earlier.
 
Take this moment to save the dialog.  We know the prefix for this level is '''TV''', that our character is called '''Elena''' and we are referencing a Dialog - thus: '''TV_Elena_Dialog''' <span style="color:#f1c40f">(2)</span>, which we entered earlier.
Line 50: Line 49:
 
[[File:BasicAdventure_3.2_SaveDialog.png|none|left|Save your dialog|686px]]
 
[[File:BasicAdventure_3.2_SaveDialog.png|none|left|Save your dialog|686px]]
  
=== 3.3. Create the rest of the dialog ===
+
<span style="color:#ffffff">'''3.3. Create the rest of the dialog'''</span>
  
 
Follow the steps below to create the rest of the dialog nodes <span style="color:#f1c40f">(1-4)</span>, along with the final node <span style="color:#f1c40f">(5)</span>.
 
Follow the steps below to create the rest of the dialog nodes <span style="color:#f1c40f">(1-4)</span>, along with the final node <span style="color:#f1c40f">(5)</span>.
Line 56: Line 55:
 
[[File:BasicAdventure_3.3_CreateRestOfDialog.png|none|left|Create the rest of your dialog|1069px]]
 
[[File:BasicAdventure_3.3_CreateRestOfDialog.png|none|left|Create the rest of your dialog|1069px]]
  
=== 3.4. Setup and assign speakers for your dialog ===
+
<span style="color:#ffffff">'''3.4. Setup and assign speakers for your dialog'''</span>
  
 
Final step for our dialog is to setup and assign our speakers.  Press the edit <span style="color:#f1c40f">(1)</span> button to add new speakers, searching for our '''S_TV_Elena''' <span style="color:#f1c40f">(3,4)</span> speaker.  Select '''Elena(S_TV_Elena)''' <span style="color:#f1c40f">(4)</span> and add it to the active list of speakers <span style="color:#f1c40f">(5)</span>, pressing '''Ok''' once done <span style="color:#f1c40f">(6)</span>.  
 
Final step for our dialog is to setup and assign our speakers.  Press the edit <span style="color:#f1c40f">(1)</span> button to add new speakers, searching for our '''S_TV_Elena''' <span style="color:#f1c40f">(3,4)</span> speaker.  Select '''Elena(S_TV_Elena)''' <span style="color:#f1c40f">(4)</span> and add it to the active list of speakers <span style="color:#f1c40f">(5)</span>, pressing '''Ok''' once done <span style="color:#f1c40f">(6)</span>.  
Line 66: Line 65:
 
[[File:BasicAdventure_3.4_SetupAndAssignSpeakers.png|none|left|Setup and assign speakers|634px]]
 
[[File:BasicAdventure_3.4_SetupAndAssignSpeakers.png|none|left|Setup and assign speakers|634px]]
  
=== 3.5. Assign the correct speaker to each node ===
+
<span style="color:#ffffff">'''3.5. Assign the correct speaker to each node'''</span>
  
 
The correct speakers should automatically be assigned to their nodes now.  However, if anything isn't correct, you can manually select a node <span style="color:#f1c40f">(1)</span> and update the speaker as need be.
 
The correct speakers should automatically be assigned to their nodes now.  However, if anything isn't correct, you can manually select a node <span style="color:#f1c40f">(1)</span> and update the speaker as need be.
Line 72: Line 71:
 
[[File:BasicAdventure_3.5_AssignCorrectSpeakers.png|none|left|Assign the correct speakers to your dialog nodes|900px]]
 
[[File:BasicAdventure_3.5_AssignCorrectSpeakers.png|none|left|Assign the correct speakers to your dialog nodes|900px]]
  
 
+
== Create our Quest Journal entries ==
== 4. Create our Quest Journal entries ==
 
 
Ah :-), some more of the fun parts.  I'll show you what standards the DOS:2 team use and how we can best setup our quests for our adventure.
 
Ah :-), some more of the fun parts.  I'll show you what standards the DOS:2 team use and how we can best setup our quests for our adventure.
  
=== 4.1. Create our quest categories ===
+
<span style="color:#ffffff">'''4.1. Create our quest categories'''</span>
  
 
Open up the Journal Editor <span style="color:#f1c40f">(1)</span>, select your project <span style="color:#f1c40f">(2)</span>, click on the Quest Categories option <span style="color:#f1c40f">(3)</span> and add two new rows <span style="color:#f1c40f">(4)</span>, for a total of three quest categories.  Once done, update our quest categories to match our screenshot <span style="color:#f1c40f">(5)</span>.
 
Open up the Journal Editor <span style="color:#f1c40f">(1)</span>, select your project <span style="color:#f1c40f">(2)</span>, click on the Quest Categories option <span style="color:#f1c40f">(3)</span> and add two new rows <span style="color:#f1c40f">(4)</span>, for a total of three quest categories.  Once done, update our quest categories to match our screenshot <span style="color:#f1c40f">(5)</span>.
Line 90: Line 88:
 
{{note|Please note that our little adventure has been broken up into categories -- which would normally only occur in a larger adventure -- to demonstrate how the DOS:2 team structure their adventures and to give you a template to build out your own larger scale adventure.}}
 
{{note|Please note that our little adventure has been broken up into categories -- which would normally only occur in a larger adventure -- to demonstrate how the DOS:2 team structure their adventures and to give you a template to build out your own larger scale adventure.}}
  
=== 4.2. Save and reload all ===
+
<span style="color:#ffffff">'''4.2. Save and reload all'''</span>
  
 
Take a quick second to click on the file menu and '''Save All''' <span style="color:#f1c40f">(1)</span>.  Then '''Reload All''' <span style="color:#f1c40f">(2)</span> to update everything.
 
Take a quick second to click on the file menu and '''Save All''' <span style="color:#f1c40f">(1)</span>.  Then '''Reload All''' <span style="color:#f1c40f">(2)</span> to update everything.
Line 96: Line 94:
 
[[File:BasicAdventure_4.2_SaveAndReloadAll.png|none|left|Save and reload all|149px]]
 
[[File:BasicAdventure_4.2_SaveAndReloadAll.png|none|left|Save and reload all|149px]]
  
=== 4.3. Add a new quest under our 'QCA_Chapter_01' category ===
+
<span style="color:#ffffff">'''4.3. Add a new quest under our 'QCA_Chapter_01' category'''</span>
  
 
Select the '''Quests''' <span style="color:#f1c40f">(1)</span> option, add a new quest <span style="color:#f1c40f">(2)</span>, select it <span style="color:#f1c40f">(3)</span> and then update its details <span style="color:#f1c40f">(4)</span>.  Please note the prefixes used, with '''TV''' representing '''TheVillage''' and '''QCA''' indicating that this is a quest category. We will go into more detail about the IsMainQuest, IsShareable and BroadcastLevel settings in future.
 
Select the '''Quests''' <span style="color:#f1c40f">(1)</span> option, add a new quest <span style="color:#f1c40f">(2)</span>, select it <span style="color:#f1c40f">(3)</span> and then update its details <span style="color:#f1c40f">(4)</span>.  Please note the prefixes used, with '''TV''' representing '''TheVillage''' and '''QCA''' indicating that this is a quest category. We will go into more detail about the IsMainQuest, IsShareable and BroadcastLevel settings in future.
Line 102: Line 100:
 
[[File:BasicAdventure_4.3_AddNewQuest.png|none|left|Add a new quest to our quest journal|728px]]
 
[[File:BasicAdventure_4.3_AddNewQuest.png|none|left|Add a new quest to our quest journal|728px]]
  
 
+
== Working with Prefabs ==
== 5. Working with Prefabs ==
 
 
Prefabs are cool :-) -- especially for laying out rocks, vegetation and trees.  In this instance, we want to create some sort of simple structures to indicate a nomad style camp and luckily we have some prefabs that can do just that for us.
 
Prefabs are cool :-) -- especially for laying out rocks, vegetation and trees.  In this instance, we want to create some sort of simple structures to indicate a nomad style camp and luckily we have some prefabs that can do just that for us.
  
 
{{tip|'''What are prefabs?''' -- In the words of Larian, a prefab is a collection of entities, and is used to speed up decoration.  For us this means we can put together a mini-scene, such as an oasis setting and then be able to save that as a collection for use in future levels.}}
 
{{tip|'''What are prefabs?''' -- In the words of Larian, a prefab is a collection of entities, and is used to speed up decoration.  For us this means we can put together a mini-scene, such as an oasis setting and then be able to save that as a collection for use in future levels.}}
  
Open up the '''Root Templates''' panel -- which should already be open at bottom of your screen --, right click on the prefabs icon <span style="color:#f1c40f">(1)</span> and search for 'tent refugee' <span style="color:#f1c40f">(2)</span>, which will provide us with some prefabricated groups of objects that look like a tent we'd find in a desert community.
+
Open up the '''Root Templates''' panel -- which should already be open at bottom of your screen -- and right click on the prefabs icon <span style="color:#f1c40f">(1)</span>, searching for 'tent refugee' <span style="color:#f1c40f">(2)</span>, which will provide us with some prefabricated groups of objects that look like tents we'd find in a nomad community.
  
 
Once you have dragged in two suitable tent prefabs, aligning them however you wish (double click to select and move prefabs in scenes) –- please also grab a set of vases to add a little bit of flavour <span style="color:#f1c40f">(5, 6)</span>.
 
Once you have dragged in two suitable tent prefabs, aligning them however you wish (double click to select and move prefabs in scenes) –- please also grab a set of vases to add a little bit of flavour <span style="color:#f1c40f">(5, 6)</span>.
Line 116: Line 113:
 
{{Tip|'''Prefab usage tip''' -- I struggled with prefabs initially, until I found out you have to '''double-click''' on them to select all objects within a prefab.  If you don't do this then you will just be grabbing one of the objects within the collection (prefab), which can be useful when re-arranging a collection of trees you have recently added.}}
 
{{Tip|'''Prefab usage tip''' -- I struggled with prefabs initially, until I found out you have to '''double-click''' on them to select all objects within a prefab.  If you don't do this then you will just be grabbing one of the objects within the collection (prefab), which can be useful when re-arranging a collection of trees you have recently added.}}
  
 
+
== Shortcut tips for working with objects ==
== 6. Shortcut tips for working with objects ==
 
 
For a while I was clicking on each of these 'Mode' icons on the left hand side to manipulate objects, until I learned about these nifty shortcut keys.  When selecting any objects, use keys 1 - 5 to make changes and hold down the shift key when moving (translating) a selection to create a copy of all selected objects.
 
For a while I was clicking on each of these 'Mode' icons on the left hand side to manipulate objects, until I learned about these nifty shortcut keys.  When selecting any objects, use keys 1 - 5 to make changes and hold down the shift key when moving (translating) a selection to create a copy of all selected objects.
  
Line 148: Line 144:
 
[[File:BasicAdventure 6.0 ShortcutTips.png|none|left|Shortcut tips|700px]]
 
[[File:BasicAdventure 6.0 ShortcutTips.png|none|left|Shortcut tips|700px]]
  
 
+
== Hidden sand piles, secrets and object items ==
== 7. Hidden sand piles, secrets and object items ==
 
 
For our next steps we need to go searching for the medicine that Elena lost while playing.  To set this up we are going to create some hidden dirt piles which the player needs to discover, a handy shovel for digging and some items for our player characters to find.
 
For our next steps we need to go searching for the medicine that Elena lost while playing.  To set this up we are going to create some hidden dirt piles which the player needs to discover, a handy shovel for digging and some items for our player characters to find.
  
=== 7.1. Add a shovel and three instances of a white sand pile ===
+
<span style="color:#ffffff">'''7.1. Add a shovel and three instances of a white sand pile'''</span>
 
Search for our hidden sand pile objects <span style="color:#f1c40f">(1)</span>, add three instances (3 x objects) of '''PUZ_SandWhitepile_A''' <span style="color:#f1c40f">(2)</span> to our level and search for a shovel <span style="color:#f1c40f">(3)</span> to add nearby <span style="color:#f1c40f">(4)</span>.
 
Search for our hidden sand pile objects <span style="color:#f1c40f">(1)</span>, add three instances (3 x objects) of '''PUZ_SandWhitepile_A''' <span style="color:#f1c40f">(2)</span> to our level and search for a shovel <span style="color:#f1c40f">(3)</span> to add nearby <span style="color:#f1c40f">(4)</span>.
  
 
[[File:BasicAdventure_7.1_AddShovelAndSandPiles.png|none|left|Add shovel and sand piles|785px]]
 
[[File:BasicAdventure_7.1_AddShovelAndSandPiles.png|none|left|Add shovel and sand piles|785px]]
  
=== 7.2.  Add some objects into the level to dig up out of our sand piles ===
+
<span style="color:#ffffff">'''7.2.  Add some objects into the level to dig up out of our sand piles'''</span>
  
 
Search through our root templates and add the following objects into our level.
 
Search through our root templates and add the following objects into our level.
Line 170: Line 165:
 
[[File:BasicAdventure_7.2_AddSomeObjects.png|none|left|Add some objects|560px]]
 
[[File:BasicAdventure_7.2_AddSomeObjects.png|none|left|Add some objects|560px]]
  
=== 7.3. Add our objects to our sand-piles item property ===
+
<span style="color:#ffffff">'''7.3. Add our objects to our sand-piles item property'''</span>
  
 
Individually select each of our three sand piles from the '''world outliner''' <span style="color:#f1c40f">(1)</span>, and click on the '''Items''' <span style="color:#f1c40f">(2)</span> property to edit each objects items.  Filter our Edit Items window to only show level items <span style="color:#f1c40f">(3)</span> and then select and assign the four objects in any way you like <span style="color:#f1c40f">(4, 5)</span>.  
 
Individually select each of our three sand piles from the '''world outliner''' <span style="color:#f1c40f">(1)</span>, and click on the '''Items''' <span style="color:#f1c40f">(2)</span> property to edit each objects items.  Filter our Edit Items window to only show level items <span style="color:#f1c40f">(3)</span> and then select and assign the four objects in any way you like <span style="color:#f1c40f">(4, 5)</span>.  
Line 178: Line 173:
 
{{Tip|For our tutorial we have assigned our ball and bottle-of-wine to '''PUZ_SandWhitePile_A_001''', and our teddy bear and potion to '''PUZ_SandWhitePile_A_002'''. Pile 003 has been left empty.}}
 
{{Tip|For our tutorial we have assigned our ball and bottle-of-wine to '''PUZ_SandWhitePile_A_001''', and our teddy bear and potion to '''PUZ_SandWhitePile_A_002'''. Pile 003 has been left empty.}}
  
=== 7.4. Only show our sand piles if the user passes a perception test ===
+
<span style="color:#ffffff">'''7.4. Only show our sand piles if the user passes a perception test'''</span>
  
 
We want to hide our sand piles so that they are not immediately obvious to our players.  Luckily these objects already have the '''PUZZLE_HiddenPerception''' script assigned, which will trigger a default perception check for players to see the object.  Please feel free to use this script on any other world objects you wish to hide until perceived by the player.
 
We want to hide our sand piles so that they are not immediately obvious to our players.  Luckily these objects already have the '''PUZZLE_HiddenPerception''' script assigned, which will trigger a default perception check for players to see the object.  Please feel free to use this script on any other world objects you wish to hide until perceived by the player.
Line 184: Line 179:
 
[[File:BasicAdventure_7.4_OnlyShowPilesIfPerceptionPassed.png|none|left|Only show piles if perception passed|900px]]
 
[[File:BasicAdventure_7.4_OnlyShowPilesIfPerceptionPassed.png|none|left|Only show piles if perception passed|900px]]
  
== 8. Box Triggers, referencing local instances, digging with shovels and treasure rewards ==
+
== Box Triggers, local instances and hidden dirt piles ==
 
We're going to be jumping over to some slightly more complex topics in this section.  Our aim here is to let our story (script) know about how our sand piles behave, specifically how they react and we will also be reviewing our naming conventions for local objects – to ensure we are consistent with Larian's standards.
 
We're going to be jumping over to some slightly more complex topics in this section.  Our aim here is to let our story (script) know about how our sand piles behave, specifically how they react and we will also be reviewing our naming conventions for local objects – to ensure we are consistent with Larian's standards.
  
=== 8.1 Naming and referencing of local instances ===
+
<span style="color:#ffffff">'''8.1 Naming and referencing of local instances'''</span>
  
 
This is going to be cool :-).  Please run through all our sand pile objects (including diggable items) and rename them to:
 
This is going to be cool :-).  Please run through all our sand pile objects (including diggable items) and rename them to:
Line 208: Line 203:
 
You'll also note that we renamed the items to match up with the sand piles, which has helped to order them in our '''World Outliner''' and also makes it easy to see where our items '''Red Ball''', '''Wine''' etc. belong.}}
 
You'll also note that we renamed the items to match up with the sand piles, which has helped to order them in our '''World Outliner''' and also makes it easy to see where our items '''Red Ball''', '''Wine''' etc. belong.}}
  
=== 8.2 Doing a better job hiding our sand piles ===
+
<span style="color:#ffffff">'''8.2 Doing a better job hiding our sand piles'''</span>
  
 
I was curious as to how Larian achieved this, as it seemed pretty obvious where the sand piles were.  Lo and behold, we have a simple solution here – which is to select all of our sand piles <span style="color:#f1c40f">
 
I was curious as to how Larian achieved this, as it seemed pretty obvious where the sand piles were.  Lo and behold, we have a simple solution here – which is to select all of our sand piles <span style="color:#f1c40f">
Line 217: Line 212:
 
[[File:BasicAdventure_8.2_BetterJobHidingSandPiles.png|none|left|Better job hiding sand piles|785px]]
 
[[File:BasicAdventure_8.2_BetterJobHidingSandPiles.png|none|left|Better job hiding sand piles|785px]]
  
=== 8.3 Setting up box triggers to implement digging treasure rewards ===
+
<span style="color:#ffffff">'''8.3 Setting up box triggers to implement digging treasure rewards'''</span>
  
 
We will need to create some box triggers to let our story know where diggable areas exist and where to spawn any found objects.  Please search for '''Box Trigger''' <span style="color:#f1c40f">(1)</span> in the root templates panel and drag out four instances <span style="color:#f1c40f">(2)</span> into your level (one box trigger for each object).  Once done, run through and rename each box trigger <span style="color:#f1c40f">(3)</span> to match up with our sand piles and related items.
 
We will need to create some box triggers to let our story know where diggable areas exist and where to spawn any found objects.  Please search for '''Box Trigger''' <span style="color:#f1c40f">(1)</span> in the root templates panel and drag out four instances <span style="color:#f1c40f">(2)</span> into your level (one box trigger for each object).  Once done, run through and rename each box trigger <span style="color:#f1c40f">(3)</span> to match up with our sand piles and related items.
Line 227: Line 222:
 
[[File:BasicAdventure_8.3_EditShapeBoundsForBoxTriggers.png|none|left|Edit shape bounds for box triggers|750px]]
 
[[File:BasicAdventure_8.3_EditShapeBoundsForBoxTriggers.png|none|left|Edit shape bounds for box triggers|750px]]
  
== 9. Setting up the StoryEditor and scripts for your custom levels ==
+
== Setting up the StoryEditor and scripts for your custom levels ==
  
 
Before we begin, there are a few things we need to understand first about stories and how they work.  Notably that all our goals are placed in alphabetical order and compiled into a single story at run-time – with the only exception being that sub-goals will only run when their parent goal completes.
 
Before we begin, there are a few things we need to understand first about stories and how they work.  Notably that all our goals are placed in alphabetical order and compiled into a single story at run-time – with the only exception being that sub-goals will only run when their parent goal completes.
  
=== 9.1. There is only ever one story, with goals running in alphabetical order ===
+
<span style="color:#ffffff">'''9.1. There is only ever one story, with goals running in alphabetical order'''</span>
  
 
At compilation time, our collection of goals is compiled into one story and sorted alphabetically <span style="color:#f1c40f">(5)</span>.  Regardless of where the goal sits within our Story Editor, whether this be a top level goal or a goal that sits two levels deep under its parent goals.
 
At compilation time, our collection of goals is compiled into one story and sorted alphabetically <span style="color:#f1c40f">(5)</span>.  Regardless of where the goal sits within our Story Editor, whether this be a top level goal or a goal that sits two levels deep under its parent goals.
  
=== 9.2. Sub-goals will only run when their parent goal is 'complete' ===
+
<span style="color:#ffffff">'''9.2. Sub-goals will only run when their parent goal is 'complete' '''<span>
  
 
This is a big caveat, and led me to days of frustration as the scripts I wrote just weren't executing.  What was happening was that my sub goals that I had neatly placed under a parent goal related to my level weren't being triggered because I hadn't set my parent goal to 'complete' <span style="color:#f1c40f">(4)</span>.  Something we will setup and address shortly.
 
This is a big caveat, and led me to days of frustration as the scripts I wrote just weren't executing.  What was happening was that my sub goals that I had neatly placed under a parent goal related to my level weren't being triggered because I hadn't set my parent goal to 'complete' <span style="color:#f1c40f">(4)</span>.  Something we will setup and address shortly.
Line 243: Line 238:
 
{{Note|For clarity sake, I removed the exec INIT section of goal '''"Sandbox"''' which had successfully completed an INIT and EXIT prior to the exec INIT section of goal '''"TheVillage"''' occurring.}}
 
{{Note|For clarity sake, I removed the exec INIT section of goal '''"Sandbox"''' which had successfully completed an INIT and EXIT prior to the exec INIT section of goal '''"TheVillage"''' occurring.}}
  
=== 9.3. Create a parent goal for your level under the __Start goal ===
+
<span style="color:#ffffff">'''9.3. Create a parent goal for your level under the __Start goal'''</span>
  
 
Right click on the '''__Start''' goal <span style="color:#f1c40f">(1)</span> and select the 'Add New Sub Item...' option <span style="color:#f1c40f">(2)</span> to create a goal with the same name as your level <span style="color:#f1c40f">(3)</span>, in our instance this would be '''TheVillage'''.  Press the '''Ok''' button (4) to save the new parent goal for your level and check out the '''GoalCompleted''' code in the '''__Start''' goal (5), as we will be setting up something similar for our newly created parent level goal – '''TheVillage'''.
 
Right click on the '''__Start''' goal <span style="color:#f1c40f">(1)</span> and select the 'Add New Sub Item...' option <span style="color:#f1c40f">(2)</span> to create a goal with the same name as your level <span style="color:#f1c40f">(3)</span>, in our instance this would be '''TheVillage'''.  Press the '''Ok''' button (4) to save the new parent goal for your level and check out the '''GoalCompleted''' code in the '''__Start''' goal (5), as we will be setting up something similar for our newly created parent level goal – '''TheVillage'''.
Line 249: Line 244:
 
[[File:BasicAdventure_9.3_CreateParentGoalForLevel.png|none|left|Create parent goal for level|635px]]
 
[[File:BasicAdventure_9.3_CreateParentGoalForLevel.png|none|left|Create parent goal for level|635px]]
  
=== 9.4. Add in the code that will complete our parent level goal ===
+
<span style="color:#ffffff">'''9.4. Add in the code that will complete our parent level goal</span>
  
 
I re-used this code from the Sandbox parent level goal that Larian had setup.  Like our other goals, it has an '''INIT''', '''KB''' and '''EXIT''' section.
 
I re-used this code from the Sandbox parent level goal that Larian had setup.  Like our other goals, it has an '''INIT''', '''KB''' and '''EXIT''' section.
Line 291: Line 286:
 
</pre>
 
</pre>
  
=== 9.5. Create a new sub item goal under the parent goal for our level – 'TheVillage' ===
+
<span style="color:#ffffff">'''9.5. Create a new sub item goal under the parent goal for our level – 'TheVillage' '''</span>
  
 
Right click '''TheVillage''' <span style="color:#f1c40f">(1)</span> goal and select '''Add New Sub Item...''' <span style="color:#f1c40f">(2)</span> to add a new sub item goal that will execute after '''TheVillage''' goal completes.  Name the new goal '''TV_ShovelArea''' <span style="color:#f1c40f">(3)</span> and click '''Ok''' <span style="color:#f1c40f">(4)</span> once done.
 
Right click '''TheVillage''' <span style="color:#f1c40f">(1)</span> goal and select '''Add New Sub Item...''' <span style="color:#f1c40f">(2)</span> to add a new sub item goal that will execute after '''TheVillage''' goal completes.  Name the new goal '''TV_ShovelArea''' <span style="color:#f1c40f">(3)</span> and click '''Ok''' <span style="color:#f1c40f">(4)</span> once done.
Line 299: Line 294:
 
[[File:BasicAdventure_9.5_CreateNewSubItemGoalUnderParentLevelGoal.png|none|left|Create new sub item goal under parent level goal|280px]]
 
[[File:BasicAdventure_9.5_CreateNewSubItemGoalUnderParentLevelGoal.png|none|left|Create new sub item goal under parent level goal|280px]]
  
=== 9.6. Generate definitions, build and reload ===
+
<span style="color:#ffffff">'''9.6. Generate definitions, build and reload'''</span>
  
 
Click on the file menu and choose '''Generate Definitions, Build and Reload''' to generate all the code we need to reference the local objects in our levels – required before we can move on to the next step.
 
Click on the file menu and choose '''Generate Definitions, Build and Reload''' to generate all the code we need to reference the local objects in our levels – required before we can move on to the next step.
Line 305: Line 300:
 
[[File:BasicAdventure_9.6_GenerateDefinitionsBuildAndReload.PNG|none|left|Generate definitions, build and reload|255px]]
 
[[File:BasicAdventure_9.6_GenerateDefinitionsBuildAndReload.PNG|none|left|Generate definitions, build and reload|255px]]
  
=== 9.7. Add the shared helper code to your new sub item goal – 'TV_ShovelArea' ===
+
<span style="color:#ffffff">'''9.7. Add the shared helper code to your new sub item goal – 'TV_ShovelArea' '''</span>
  
 
Please copy/paste the attached source code <span style="color:#f1c40f">(1)</span> into your '''TV_ShovelArea''' goal and update each of the references to your own triggers, objects and sand piles – using the '''ctrl + space''' code completion feature <span style="color:#f1c40f">(2)</span> to assist.
 
Please copy/paste the attached source code <span style="color:#f1c40f">(1)</span> into your '''TV_ShovelArea''' goal and update each of the references to your own triggers, objects and sand piles – using the '''ctrl + space''' code completion feature <span style="color:#f1c40f">(2)</span> to assist.
Line 343: Line 338:
 
</pre>
 
</pre>
  
== 10. NPC Patrols and moving NPC characters ==
+
== Quest state updates, smarter dialogs and moving characters ==
 +
We're going to take a slight step backwards here and update our dialog with Elena.  The goal here is to activate the 'Started' quest state we created earlier for 'The Lost Medicine' quest, which will then display in the players quest journal.  We will also want to look at getting Elena to run back to her families tent and to say something different to us once we have accepted the quest – otherwise she will continue to ask us to find her medicine, even though we had already started doing just that.
 +
 
 +
<span style="color:#ffffff">'''10.1. How do we update quest states?'''</span>
 +
 
 +
The main mechanism for doing this is the '''ObjectSetFlag()''' Osiris Call, which we can call from any of our scripts.  Another common way of updating our quest states is via Dialogs, and their 'Node Flags' property, which is what we will be using right now.
 +
 
 +
A heads up on updating quest states is that Larian has a syntax we need to follow when updating or checking quest state flags.  The format to use is:
 +
 
 +
<pre>ObjectSetFlag(_Player, "QuestUpdate_<NameOfQuest>_<QuestState>, _");</pre>
 +
 
 +
Thus, to set our quest status to started, we just need to switch on its flag.  An example update format to use is shown below, with the "'''QuestUpdate_LostMedicine_Started'''" string.
 +
 
 +
[[File:BasicAdventure_10.1.1_QuestCategories.png|none|left|Quest categories|264px]]
 +
 
 +
Luckily we can also update quest states from within our dialogs.  For the next steps please open the '''Dialog Editor''' <span style="color:#f1c40f">(1)</span>, open our '''TV_Elena_Dialog''' file <span style="color:#f1c40f">(2-4)</span>, select the final node <span style="color:#f1c40f">(5)</span> and press the edit button for the 'Flags To Set' <span style="color:#f1c40f">(6)</span> property.
 +
 
 +
[[File:BasicAdventure_10.1.2_DialogEditing.PNG|none|left|Dialog editing|615px]]
 +
 
 +
Continuing on from above, we now need to create a custom flag which will be used to update our quest status.  To do so, click on the 'Character' flag category <span style="color:#f1c40f">(1)</span> and enter '''QuestUpdate_LostMedicine_Started''' in the custom flag field <span style="color:#f1c40f">(2)</span>.  Press Add <span style="color:#f1c40f">(3)</span>, and then press Ok <span style="color:#f1c40f">(4)</span> to save your changes.  Once saved, tick the 'QuestUpdate_LostMedicine_Started' flag to update our quest status when our players reach this particular node.
 +
 
 +
[[File:BasicAdventure_10.1.3_UpdatingFlags.png|none|left|Updating quest flags|550px]]
 +
 
 +
Press Ctrl + S to save your changes, and the close the Dialog Editor.
 +
 
 +
<span style="color:#ffffff">'''10.2. Registering our Quest state flags'''</span>
 +
 
 +
Oops!  One step we forgot to do was registering the "Started" quest state in our Story Editor.  This is where this database fact is initialised at startup, ready for an update to occur.  To set this up, please create a new sub item goal called '''TV_JournalUpdate''' and enter in the following code.
 +
 
 +
[[File:BasicAdventure_10.2_RegisterQuestStateFlags.PNG|none|left|Register quest state flags|896px]]
 +
 
 +
I've also attached a version you can copy / paste below, however.  Please note that you will need to update the '''CharacterCreationDummy''' with your own character GUID.
 +
 
 +
<pre>
 +
// Let the story know that our test dummy character is a player character
 +
DB_IsPlayer(CHARACTERGUID_S_GLO_CharacterCreationDummy_001_da072fe7-fdd5-42ae-9139-8bd4b9fca406);
 +
 
 +
// Define the Lost Medicine 'Started' flag for our quest, and so our dialog has a ready to go database fact to update
 +
DB_QuestDef_State("LostMedicine","Started",1);
 +
</pre>
 +
 
 +
<span style="color:#ffffff">'''10.3. Switch to game mode to test the quest journal updates'''</span>
 +
 
 +
Save everything and then switch to the game mode to test the quest journal updates in the level <span style="color:#f1c40f">(1)</span>.
 +
 
 +
[[File:BasicAdventure_10.3.1_SwitchToGameMode.png|none|left|Switch to game mode|377px]]
 +
 
 +
Walk up to Elena and talk to her – after which you should see the following '''Quest Journal''' update ('''The Lost Medicine''') appear on your screen.
 +
 
 +
[[File:BasicAdventure_10.3.2_JournalUpdated.png|none|left|Journal updated|299px]]
 +
 
 +
Opening your journal while in game mode should also now display The Lost Medicine quest details.
 +
 
 +
[[File:BasicAdventure_10.3.3_CheckQuestJournal.png|none|left|Open quest journal|724px]]
 +
 
 +
<span style="color:#ffffff">'''10.4. Improving our dialog with Elena'''</span>
 +
 
 +
Open up the '''Elena''' dialog and add a new greeting <span style="color:#f1c40f">(1)</span>, and a new question that follows our new greeting <span style="color:#f1c40f">(2)</span>.  This greeting is going to be the new dialog chain that will occur when the player starts a dialog with '''Elena''', and has already started the lost medicine quest.
 +
 
 +
Select our new greeting node <span style="color:#f1c40f">(3)</span>, and click on 'Edit' in our 'Flags To Check' field, adding in the '''LostMedicine_Started''' flag.  Finally, tick this flag <span style="color:#f1c40f">(4)</span> so that this greeting dialog chain will only begin if we have already started the lost medicine quest.  To tidy up, also select our original greeting node and add a lost medicine flag <span style="color:#f1c40f">(5)</span>, this time making sure not to tick it – so that this greeting chain only plays if the lost medicine quest has not started.
 +
 
 +
[[File:BasicAdventure_10.4_ImprovingDialog.png|none|left|Improving dialog|765px]]
 +
 
 +
<span style="color:#ffffff">'''10.5. Getting Elena to run back to her tent'''</span>
 +
 
 +
We're going to add in some small updates, creating a point trigger inside Elena's tent and getting her to run there after our quest started flag has been activated.  To get going, search for '''point trigger''' <span style="color:#f1c40f">(1)</span> in the Root Templates panel, select a 'Point Trigger' <span style="color:#f1c40f">(2)</span> and drag it into our scene, inside the tent <span style="color:#f1c40f">(3)</span>.  Once happy with the positioning, go ahead and update the name of the trigger to '''TV_ElenaRunToTent_PointTrigger''' <span style="color:#f1c40f">(4)</span>.
 +
 
 +
[[File:BasicAdventure_10.5.1_AddStoryScript.png|none|left|Add story script|825px]]
 +
 
 +
{{warning|Elena will end up facing wherever she stops running, and is not affected by the facing of the Point Trigger.}}
 +
 
 +
Ok, half way there – next step is to add a bit of code into our Story Editor.  Open up the StoryEditor, right click on 'TheVillage' goal and select 'Add New Sub Item...'.  Then name your new sub-item goal '''TV_Elena''' <span style="color:#f1c40f">(1)</span> as this is where we will be writing code related to her actions.  Once done, open up the KB section and enter in the following code <span style="color:#f1c40f">(2)</span>.
 +
 
 +
[[File:BasicAdventure_10.5_SetupPointTrigger.png|none|left|Setup point trigger|750px]]
 +
 
 +
<pre>
 +
IF
 +
ObjectFlagSet("QuestUpdate_LostMedicine_Started", _player, _)
 +
THEN
 +
ProcCharacterMoveTo(CHARACTERGUID_S_TV_Elena_56d1fd6c-d1ac-4d87-bba8-33a6297fa437, TRIGGERGUID_S_TV_ElenaRunToTent_PointTrigger_9a113b13-6078-44fb-a06f-917c354960ea, 1, "");
 +
</pre>
  
 +
== Animations and gestures ==
  
== 11. Animations and gestures ==
+
[To be continued...]
  
 +
== Encounters ==
  
== 12. Quest states and rewards ==
+
[To be continued...]

Latest revision as of 14:22, 22 December 2017

INTRODUCTION


This guide will take you through the steps to create a basic adventure -- visual heavy, it is aimed at beginners who want to get started on their custom adventures as quickly as possible.

Create your new project and basic level

We will be creating a Story mode Adventure, with the main focus being assisting a little girl to find her mummy's medicine. To that end, please create a new Adventure, targeted for story mode with the name HelpMyMummy.

1.1. Create a new adventure type project, targeted at Story mode

Create a new project by pressing the green create project button on the top left. Select the Adventure project type, and target the project for Story mode. Use whatever name you like for the project name – for our tutorial adventure I have called the project HelpMyMummy.

Select your project type

1.2. Create a new basic level template, called 'TheVillage'

Select the Basic level template, and call your level TheVillage – or whatever other name you prefer.

Create new basic level template

Add a character

We'll keep this bare-boned and simple, placing a character into the level and updating the bits and pieces we will require for the next steps. We named her Elena (5) and used Larian coding standards to give her a reference name of S_TV_Elena (6). For this stage, feel free to use any character and name.

Note.png
Highly recommended we follow Larians coding standards for consistency and because they make our job easier long term, both in understanding each-other's scripting and in reducing future 'lookup' time finding more info about items we wish to refer to.

2.1. Create a new NPC character model and place it into the level

Find the Humans_Children (1,2) model and place it into the level (3,4), naming her Elena (5). To keep in line with standards, for her reference, use the name S_TV_Elena (6). The S is to let the engine know that we want to reference this local object in the story and the TV is the prefix for our TheVillage level.

We're adding this early so we don't have to come back, but for now please enter the text TV_Elena_Dialog (7) for the default dialog that will start when speaking with her.

Create new NPC character

Create a simple dialog and save it

In this section we are going to create a simple quest dialog so we can talk with our NPC character and begin a quest.

3.1. Create the start of a simple dialog

Open up the Dialog Editor (1) and create a simple dialog between players and your NPC character. Create a new Greeting dialog (1) and enter the initial greeting (3). Once done press the 'x' button (4) to save your changes and close the Edit Tagged Texts window.

Create simple dialog

3.2. Save the dialog as 'TV_Elena_Dialog'

Take this moment to save the dialog. We know the prefix for this level is TV, that our character is called Elena and we are referencing a Dialog - thus: TV_Elena_Dialog (2), which we entered earlier.

Save your dialog

3.3. Create the rest of the dialog

Follow the steps below to create the rest of the dialog nodes (1-4), along with the final node (5).

Create the rest of your dialog

3.4. Setup and assign speakers for your dialog

Final step for our dialog is to setup and assign our speakers. Press the edit (1) button to add new speakers, searching for our S_TV_Elena (3,4) speaker. Select Elena(S_TV_Elena) (4) and add it to the active list of speakers (5), pressing Ok once done (6).

Add a new speaker and then follow the same setup steps (3-6) for the GROUP_Players speaker (8), which covers any player talking to our NPC character. Press the Ok button to save your changes (9) once both speakers have been assigned.

Note.png
Don't add both speakers under one node. For example, having Elena(S_TV_Elena) and GROUP_Players both grouped together as speaker one (2). Doing so is only used when we have more than one speaker saying something, such as from a group of 2 or more NPC characters speaking together.
Setup and assign speakers

3.5. Assign the correct speaker to each node

The correct speakers should automatically be assigned to their nodes now. However, if anything isn't correct, you can manually select a node (1) and update the speaker as need be.

Assign the correct speakers to your dialog nodes

Create our Quest Journal entries

Ah :-), some more of the fun parts. I'll show you what standards the DOS:2 team use and how we can best setup our quests for our adventure.

4.1. Create our quest categories

Open up the Journal Editor (1), select your project (2), click on the Quest Categories option (3) and add two new rows (4), for a total of three quest categories. Once done, update our quest categories to match our screenshot (5).

Creating quest categories
a) CategoryID: QCA_Chapter_01 | Description: The Village | SortingPriority: 3
b) CategoryID: QCA_Chapter_02 | Description: Home Sweet Home | SortingPriority: 2
c) CategoryID: QCA_Chapter_03 | Description: The Cave of Sorrows | SortingPriority: 1

Feel free to update descriptions and category IDs in any way you see fit. If possible, work with including the QCA_ prefix with your category ids, for better code / script legibility.

Note.png
Please note that our little adventure has been broken up into categories -- which would normally only occur in a larger adventure -- to demonstrate how the DOS:2 team structure their adventures and to give you a template to build out your own larger scale adventure.

4.2. Save and reload all

Take a quick second to click on the file menu and Save All (1). Then Reload All (2) to update everything.

Save and reload all

4.3. Add a new quest under our 'QCA_Chapter_01' category

Select the Quests (1) option, add a new quest (2), select it (3) and then update its details (4). Please note the prefixes used, with TV representing TheVillage and QCA indicating that this is a quest category. We will go into more detail about the IsMainQuest, IsShareable and BroadcastLevel settings in future.

Add a new quest to our quest journal

Working with Prefabs

Prefabs are cool :-) -- especially for laying out rocks, vegetation and trees. In this instance, we want to create some sort of simple structures to indicate a nomad style camp and luckily we have some prefabs that can do just that for us.

Tip.png
What are prefabs? -- In the words of Larian, a prefab is a collection of entities, and is used to speed up decoration. For us this means we can put together a mini-scene, such as an oasis setting and then be able to save that as a collection for use in future levels.

Open up the Root Templates panel -- which should already be open at bottom of your screen -- and right click on the prefabs icon (1), searching for 'tent refugee' (2), which will provide us with some prefabricated groups of objects that look like tents we'd find in a nomad community.

Once you have dragged in two suitable tent prefabs, aligning them however you wish (double click to select and move prefabs in scenes) –- please also grab a set of vases to add a little bit of flavour (5, 6).

Working with prefabs
Tip.png
Prefab usage tip -- I struggled with prefabs initially, until I found out you have to double-click on them to select all objects within a prefab. If you don't do this then you will just be grabbing one of the objects within the collection (prefab), which can be useful when re-arranging a collection of trees you have recently added.

Shortcut tips for working with objects

For a while I was clicking on each of these 'Mode' icons on the left hand side to manipulate objects, until I learned about these nifty shortcut keys. When selecting any objects, use keys 1 - 5 to make changes and hold down the shift key when moving (translating) a selection to create a copy of all selected objects.

Options Key (requires object to be selected first)
Select objects '1', used to directly select objects
Move objects '2', used to move / translate selected objects (x, y, z)
Rotate objects '3', used to rotate selected objects
Scale objects '4', used to scale selected objects
Add objects '5', used to add objects selected in the Root Templates Panel
Copy objects Select '2' to move selected objects, then hold down 'shift' when moving objects to copy them
Select prefabs Select '1' to select objects, then 'double-click' to select all objects in a prefab
Shortcut tips

Hidden sand piles, secrets and object items

For our next steps we need to go searching for the medicine that Elena lost while playing. To set this up we are going to create some hidden dirt piles which the player needs to discover, a handy shovel for digging and some items for our player characters to find.

7.1. Add a shovel and three instances of a white sand pile Search for our hidden sand pile objects (1), add three instances (3 x objects) of PUZ_SandWhitepile_A (2) to our level and search for a shovel (3) to add nearby (4).

Add shovel and sand piles

7.2. Add some objects into the level to dig up out of our sand piles

Search through our root templates and add the following objects into our level.

1) LOOT_Toy_TeddyBearWornOff_Dynamic
2) CON_Potion_A_Health
3) LOOT_Toy_Ball_Red_A
4) CON_Drink_Bottle_Wine_A

We will shortly be moving them into our sand piles.

Add some objects

7.3. Add our objects to our sand-piles item property

Individually select each of our three sand piles from the world outliner (1), and click on the Items (2) property to edit each objects items. Filter our Edit Items window to only show level items (3) and then select and assign the four objects in any way you like (4, 5).

Add objects to piles
Tip.png
For our tutorial we have assigned our ball and bottle-of-wine to PUZ_SandWhitePile_A_001, and our teddy bear and potion to PUZ_SandWhitePile_A_002. Pile 003 has been left empty.

7.4. Only show our sand piles if the user passes a perception test

We want to hide our sand piles so that they are not immediately obvious to our players. Luckily these objects already have the PUZZLE_HiddenPerception script assigned, which will trigger a default perception check for players to see the object. Please feel free to use this script on any other world objects you wish to hide until perceived by the player.

Only show piles if perception passed

Box Triggers, local instances and hidden dirt piles

We're going to be jumping over to some slightly more complex topics in this section. Our aim here is to let our story (script) know about how our sand piles behave, specifically how they react and we will also be reviewing our naming conventions for local objects – to ensure we are consistent with Larian's standards.

8.1 Naming and referencing of local instances

This is going to be cool :-). Please run through all our sand pile objects (including diggable items) and rename them to:

1) S_TV_SandPile_001
2) S_TV_SandPile_001_RedBall
3) S_TV_SandPile_001_WineBottle
4) S_TV_SandPile_002
5) S_TV_SandPile_002_SmallPotion
6) S_TV_SandPile_002_TeddyBear
7) S_TV_SandPile_003
8) S_TV_SandPile_Shovel

Once completed, our world outliner should look like the following.

World outliner
Note.png
Why make these naming changes? -- A couple of reasons :-). First of all, we add the 'S' as a naming convention for any local objects we want to reference in scripts. This has the benefit of keeping them ordered together, lets the engine know to have references setup for us and improves our code readability (easier to find / understand) – which has ongoing long-term benefits for us and others.

You'll also note that we renamed the items to match up with the sand piles, which has helped to order them in our World Outliner and also makes it easy to see where our items Red Ball, Wine etc. belong.

8.2 Doing a better job hiding our sand piles

I was curious as to how Larian achieved this, as it seemed pretty obvious where the sand piles were. Lo and behold, we have a simple solution here – which is to select all of our sand piles (1), select the translate option (2) and push them further into the ground (3) so that only the top part of the sand piles are visible. This way it isn't so obvious where the sand piles are, whilst at the same time our shovel should help point our players in the right direction.

Better job hiding sand piles

8.3 Setting up box triggers to implement digging treasure rewards

We will need to create some box triggers to let our story know where diggable areas exist and where to spawn any found objects. Please search for Box Trigger (1) in the root templates panel and drag out four instances (2) into your level (one box trigger for each object). Once done, run through and rename each box trigger (3) to match up with our sand piles and related items.

Setting up box triggers for digging treasure rewards

Finally, we just need to make sure our Box Trigger bounds covers our sand piles. Run through and select each box trigger (1), then select the Edit Shape Bounds (2) option to specify the bounds (3) for each trigger.

Edit shape bounds for box triggers

Setting up the StoryEditor and scripts for your custom levels

Before we begin, there are a few things we need to understand first about stories and how they work. Notably that all our goals are placed in alphabetical order and compiled into a single story at run-time – with the only exception being that sub-goals will only run when their parent goal completes.

9.1. There is only ever one story, with goals running in alphabetical order

At compilation time, our collection of goals is compiled into one story and sorted alphabetically (5). Regardless of where the goal sits within our Story Editor, whether this be a top level goal or a goal that sits two levels deep under its parent goals.

9.2. Sub-goals will only run when their parent goal is 'complete'

This is a big caveat, and led me to days of frustration as the scripts I wrote just weren't executing. What was happening was that my sub goals that I had neatly placed under a parent goal related to my level weren't being triggered because I hadn't set my parent goal to 'complete' (4). Something we will setup and address shortly.

Story editor execution order guide
Note.png
For clarity sake, I removed the exec INIT section of goal "Sandbox" which had successfully completed an INIT and EXIT prior to the exec INIT section of goal "TheVillage" occurring.

9.3. Create a parent goal for your level under the __Start goal

Right click on the __Start goal (1) and select the 'Add New Sub Item...' option (2) to create a goal with the same name as your level (3), in our instance this would be TheVillage. Press the Ok button (4) to save the new parent goal for your level and check out the GoalCompleted code in the __Start goal (5), as we will be setting up something similar for our newly created parent level goal – TheVillage.

Create parent goal for level

9.4. Add in the code that will complete our parent level goal

I re-used this code from the Sandbox parent level goal that Larian had setup. Like our other goals, it has an INIT, KB and EXIT section.

- INIT is where all the initialisation code for a goal is placed, think of it like your setup area – all the actions in here occur as soon as the goal initialises.
- KB is where the bulk of the code goes, and contains all the rules that become active as soon as your goal starts initialising.  Which means that the rules in the KB section can react to changes      made in the INIT section of that same goal.
- EXIT is all the actions that are executed once the goal completes, which is generally used to remove existing databases – resulting in smaller save-game sizes and a faster game experience.

Grab a copy of the code blocks below and paste them in your TheVillage parent goal.

// ------- Place in the "INIT" section --------

DB_CheckLevelStart("TheVillage");

// ------- END "INIT" section --------
// -------- Place in the "KB" section --------

IF
RegionStarted("TheVillage")
THEN
GoalCompleted;

IF
DB_CheckLevelStart("TheVillage")
AND
DB_CurrentLevel("TheVillage")
THEN
GoalCompleted;

// ------- END "KB" section --------
// -------- Place in the "EXIT" section --------

NOT DB_CheckLevelStart("TheVillage");

// ------- END "EXIT" section --------

9.5. Create a new sub item goal under the parent goal for our level – 'TheVillage'

Right click TheVillage (1) goal and select Add New Sub Item... (2) to add a new sub item goal that will execute after TheVillage goal completes. Name the new goal TV_ShovelArea (3) and click Ok (4) once done.

We will be using this goal to store the code for letting our story know how to handle character interactions with our secret sand piles.

Create new sub item goal under parent level goal

9.6. Generate definitions, build and reload

Click on the file menu and choose Generate Definitions, Build and Reload to generate all the code we need to reference the local objects in our levels – required before we can move on to the next step.

Generate definitions, build and reload

9.7. Add the shared helper code to your new sub item goal – 'TV_ShovelArea'

Please copy/paste the attached source code (1) into your TV_ShovelArea goal and update each of the references to your own triggers, objects and sand piles – using the ctrl + space code completion feature (2) to assist.

The example below shows the word redball being typed, and then ctrl + space being pressed to allow the user to see a drop-down of all related references, which in this case include both the red-ball object and the red-ball trigger.

Add shared helper codes for shovel area scripts
// ----- Place in the INIT section ------

// Hooks up the Wine-Bottle Box Trigger and associates the reward 'TV_Reward_Wine' with our SandPile_001 object
DB_ShovelArea(TRIGGERGUID_S_TV_SandPile_001_WineBottle_BoxTrigger_a70f5f0f-bb59-43d7-be4a-ec1f627c390e, "TV_Reward_Wine", ITEMGUID_S_TV_SandPile_001_8f8f7e03-22a1-484d-8f7e-8bc05b92f14d);
DB_ShovelArea(TRIGGERGUID_S_TV_SandPile_001_RedBall_BoxTrigger_41f2ff57-a4df-4a40-87ec-1d0ed8e3897d, "TV_Reward_RedBall", ITEMGUID_S_TV_SandPile_001_8f8f7e03-22a1-484d-8f7e-8bc05b92f14d);
DB_ShovelArea(TRIGGERGUID_S_TV_SandPile_002_TeddyBear_BoxTrigger_cea3da18-444d-4ee7-8f2f-8a1b5784ccf8, "TV_Reward_TeddyBear", ITEMGUID_S_TV_SandPile_002_d6b1139e-41dd-4d17-b88f-9a3cf9b1c2cd);
DB_ShovelArea(TRIGGERGUID_S_TV_SandPile_001_RedBall_BoxTrigger_41f2ff57-a4df-4a40-87ec-1d0ed8e3897d, "TV_Reward_SmallPotion", ITEMGUID_S_TV_SandPile_002_d6b1139e-41dd-4d17-b88f-9a3cf9b1c2cd);
DB_ShovelArea(TRIGGERGUID_BoxTrigger_000_e3bf1e01-c05c-4055-889c-a51dd2fbdaff,"Empty",ITEMGUID_S_TV_SandPile_003_a55808f1-39a1-42ae-9a83-8112079c0573);

// Defines that the TV_Reward_Wine is our bottle of wine and that it will spawn on the WineBottle_BoxTrigger
DB_ShovelRewardItemAppear("TV_Reward_Wine",  ITEMGUID_S_TV_SandPile_001_WineBottle_ea94f7c2-7087-458a-a969-eb39b551f4c1, TRIGGERGUID_S_TV_SandPile_001_WineBottle_BoxTrigger_a70f5f0f-bb59-43d7-be4a-ec1f627c390e);
DB_ShovelRewardItemAppear("TV_Reward_RedBall", redball, TRIGGERGUID_S_TV_SandPile_001_RedBall_BoxTrigger_41f2ff57-a4df-4a40-87ec-1d0ed8e3897d);
DB_ShovelRewardItemAppear("TV_Reward_TeddyBear",  ITEMGUID_S_TV_SandPile_002_TeddyBear_e6cb08ec-d52f-4cac-b6b3-c23d08fbfd17, TRIGGERGUID_S_TV_SandPile_002_TeddyBear_BoxTrigger_cea3da18-444d-4ee7-8f2f-8a1b5784ccf8);
DB_ShovelRewardItemAppear("TV_Reward_SmallPotion", ITEMGUID_S_TV_SandPile_002_SmallPotion_42b65a2e-4b4f-4cbd-a639-2b7df62f1606, TRIGGERGUID_S_TV_SandPile_002_SmallPotion_BoxTrigger_30eb13ab-652d-444e-9ce4-3137fbb5ea0b);

// ----- END INIT section ------
// ----- Place in the KB section -----

// Displays the entered text if the character uses our SandPile_003 object
IF
CharacterUsedItem(_Character,ITEMGUID_S_TV_SandPile_003_a55808f1-39a1-42ae-9a83-8112079c0573)
THEN
DisplayText(_Character,"You start digging around the area but find nothing of interest...");

// ----- END KB section ------

Quest state updates, smarter dialogs and moving characters

We're going to take a slight step backwards here and update our dialog with Elena. The goal here is to activate the 'Started' quest state we created earlier for 'The Lost Medicine' quest, which will then display in the players quest journal. We will also want to look at getting Elena to run back to her families tent and to say something different to us once we have accepted the quest – otherwise she will continue to ask us to find her medicine, even though we had already started doing just that.

10.1. How do we update quest states?

The main mechanism for doing this is the ObjectSetFlag() Osiris Call, which we can call from any of our scripts. Another common way of updating our quest states is via Dialogs, and their 'Node Flags' property, which is what we will be using right now.

A heads up on updating quest states is that Larian has a syntax we need to follow when updating or checking quest state flags. The format to use is:

ObjectSetFlag(_Player, "QuestUpdate_<NameOfQuest>_<QuestState>, _");

Thus, to set our quest status to started, we just need to switch on its flag. An example update format to use is shown below, with the "QuestUpdate_LostMedicine_Started" string.

Quest categories

Luckily we can also update quest states from within our dialogs. For the next steps please open the Dialog Editor (1), open our TV_Elena_Dialog file (2-4), select the final node (5) and press the edit button for the 'Flags To Set' (6) property.

Dialog editing

Continuing on from above, we now need to create a custom flag which will be used to update our quest status. To do so, click on the 'Character' flag category (1) and enter QuestUpdate_LostMedicine_Started in the custom flag field (2). Press Add (3), and then press Ok (4) to save your changes. Once saved, tick the 'QuestUpdate_LostMedicine_Started' flag to update our quest status when our players reach this particular node.

Updating quest flags

Press Ctrl + S to save your changes, and the close the Dialog Editor.

10.2. Registering our Quest state flags

Oops! One step we forgot to do was registering the "Started" quest state in our Story Editor. This is where this database fact is initialised at startup, ready for an update to occur. To set this up, please create a new sub item goal called TV_JournalUpdate and enter in the following code.

Register quest state flags

I've also attached a version you can copy / paste below, however. Please note that you will need to update the CharacterCreationDummy with your own character GUID.

// Let the story know that our test dummy character is a player character
DB_IsPlayer(CHARACTERGUID_S_GLO_CharacterCreationDummy_001_da072fe7-fdd5-42ae-9139-8bd4b9fca406);

// Define the Lost Medicine 'Started' flag for our quest, and so our dialog has a ready to go database fact to update
DB_QuestDef_State("LostMedicine","Started",1);

10.3. Switch to game mode to test the quest journal updates

Save everything and then switch to the game mode to test the quest journal updates in the level (1).

Switch to game mode

Walk up to Elena and talk to her – after which you should see the following Quest Journal update (The Lost Medicine) appear on your screen.

Journal updated

Opening your journal while in game mode should also now display The Lost Medicine quest details.

Open quest journal

10.4. Improving our dialog with Elena

Open up the Elena dialog and add a new greeting (1), and a new question that follows our new greeting (2). This greeting is going to be the new dialog chain that will occur when the player starts a dialog with Elena, and has already started the lost medicine quest.

Select our new greeting node (3), and click on 'Edit' in our 'Flags To Check' field, adding in the LostMedicine_Started flag. Finally, tick this flag (4) so that this greeting dialog chain will only begin if we have already started the lost medicine quest. To tidy up, also select our original greeting node and add a lost medicine flag (5), this time making sure not to tick it – so that this greeting chain only plays if the lost medicine quest has not started.

Improving dialog

10.5. Getting Elena to run back to her tent

We're going to add in some small updates, creating a point trigger inside Elena's tent and getting her to run there after our quest started flag has been activated. To get going, search for point trigger (1) in the Root Templates panel, select a 'Point Trigger' (2) and drag it into our scene, inside the tent (3). Once happy with the positioning, go ahead and update the name of the trigger to TV_ElenaRunToTent_PointTrigger (4).

Add story script
Warningred.png
Elena will end up facing wherever she stops running, and is not affected by the facing of the Point Trigger.

Ok, half way there – next step is to add a bit of code into our Story Editor. Open up the StoryEditor, right click on 'TheVillage' goal and select 'Add New Sub Item...'. Then name your new sub-item goal TV_Elena (1) as this is where we will be writing code related to her actions. Once done, open up the KB section and enter in the following code (2).

Setup point trigger
IF
ObjectFlagSet("QuestUpdate_LostMedicine_Started", _player, _)
THEN
ProcCharacterMoveTo(CHARACTERGUID_S_TV_Elena_56d1fd6c-d1ac-4d87-bba8-33a6297fa437, TRIGGERGUID_S_TV_ElenaRunToTent_PointTrigger_9a113b13-6078-44fb-a06f-917c354960ea, 1, "");

Animations and gestures

[To be continued...]

Encounters

[To be continued...]