Denizen/0.7/Assignments: Difference between revisions

From Citizens Wiki

< Denizen‎ | 0.7

No edit summary
Line 1: Line 1:
== Assignments ==
== Assignments ==
<div style="margin-right:2.0em; padding:10px; font-family:museo-sans; font-size:110%;">
<div style="font-family:museo-sans; font-size:110%;">
Still reading? Great! You're on your way to making some sweet Denizen NPCs. Let's start out with the basics: Assignments, and Scripts. Denizen needs two things to be functional. A script, and an assignment. Scripts, obviously, hold instructions that are carried out when triggered. Assignments hold information on which scripts should trigger, and when. Bear with me, and keep reading!
</div>


==== General layout of an Interact Script ====
==== Interact Script Assignment ====
<div style="margin-right:2.0em; padding:10px; font-family:museo-sans; font-size:110%;">
Before a Denizen can run a script, it needs to be assigned first.  
This small 'outline' below shows the general layout of a Denizen Assignment. Remember: SPACING is INCREDIBLY important with YML. If you are receiving a SnakeYML error in your console when working with any YML file, 99% of the time it is because of bad spacing or a missing ':' colon. YAML tutorials can be intimidating, but this small tutorial on the Essentials wiki is pretty useful for basic YAML, which is the extent of which Denizens uses.


<pre>
Assignments are defined in '''<code>plugins\Denizen\assignments.yml </code>
Denizens:           
  'Name of Denizen':
    Interact Scripts:
    - .. ...
    - .. ...
    Scheduled Activities:
    - ..:.. ...
    - ..:.. ...
    Texts:
      ....: ...
      ....: ...
</pre>


For information on what goes in Interact Scripts, Scheduled Activities, etc., keep reading. What is show above is just a an outline of the correct spacing, not a valid assignment! Let's take a look at the basics, below.
This yaml file contains a single node called 'Denizens' and each Denizen gets its own entry under this node.
</div>


==== A basic interact script ====
Assignments must be made by hand. We recommend a good text editor like [[http://notepad-plus-plus.org/ Notepad++]]
<div style="margin-right:2.0em; padding:10px; font-family:museo-sans; font-size:110%;">
In order to sufficiently explain an assignment, we first need a script. The great thing about a Denizen script is that it can be simple or advanced, short or long, thanks to a wide array of commands and functions at your disposal. Scripts can work with, extend, and rely on one another to create rich, interactive gameplay. Each script has at least 2 parts, Requirements and Steps. For now, let's take this very simple script as an example. Once you understand the basics of assignments, you can proceed to learning about [[Denizen/Interact Scripts|Interact Scripts]] and [[Denizen/Activities|Activities]].


Remember: Scripts are defined in <code>plugins/Denizen/scripts/</code> folder. They can be put into any YML file contained in that directory. You may need to create the directory yourself if no scripts yet exist.
Here is a very basic example, assigning a single [[Denizen/Interact Scripts|interact script]] to a Denizen named Steve.
 
Example:


<pre>
<pre>
'Daytime in the City':  
Denizens:                        
   Type: Interact
   'Steve':                      
  Requirements:
     Interact Scripts:                    
     Mode: All
     - 10 Daytime in the City 
    List:
     - TIME Day
  Steps:
    1:
      Click Trigger:
        Script:
        - CHAT "Welcome to the city! Isn't it beautiful in the daytime?"
</pre>
</pre>


Hopefully your brain latched right on. Easy, right? :) So what just happened there? A quick literal translation: This script is named <code>'Daytime in the City'</code>. This name is used when assigning Denizen NPCs their scripts. When the script is called by a trigger, in this case a <code>'Click Trigger'</code>, for it to activate the Requirements set must be met, more specifically <code>ALL</code> of the requirements set. In this example, the only requirement is <code>TIME DAY</code> which requires the current time in the world to be daytime. If the Requirements are met, the script defined in the <code>'Click Trigger'</code> is sent to be run. It will have the Denizen NPC chat to the player 'Welcome to the city! Isn't it beautiful in the daytime?'.
Let's break this down.  


But before the script can be triggered, it needs to be assigned.
First, if you are unfamiliar with yaml, 'Interact Scripts:' contains a yaml '''list'''. Each item in the list is prefixed with '-'. indentation and spacing is important.
</div>


==== A basic assignment ====
This assignment will work for Denizens named <code>'Steve'</code>. {{color|red|white|Denizen NPC names are case-sensitive!}} Triggers that involve this NPC, such as a <code>'Click Trigger'</code> will now attempt to call the script named <code>'Daytime in the City'</code>.  
<div style="margin-right:2.0em; padding:10px; font-family:museo-sans; font-size:110%;">
In order for a Denizen to be associated with a script, he needs to be assigned to it. The following shows a simple assignment format.  


Assignments are defined in the Denizens node found in plugins/Denizen/assignments.yml and must be done by hand. Once you edit the config.yml, immediately save and use /denizen reload in-game.
The <code>10</code> before the name is the '''script priority''', useful when assigning multiple scripts.
 
If you wanted to assign this same script to another NPC, you would make another entry like this:


<pre>
<pre>
Line 63: Line 35:
     Interact Scripts:                       
     Interact Scripts:                       
     - 10 Daytime in the City   
     - 10 Daytime in the City   
     Texts:
  'Bob':                       
      No Click Trigger: 'Come back during the day!'
     Interact Scripts:                    
    - 10 Daytime in the City 
</pre>
</pre>


Let's break this down again. This assignement will work for Denizens named <code>'Steve'</code>. Denizen NPC names are case-sensitive! Triggers that involve this NPC, such as a <code>'Click Trigger'</code> will call the script named <code>'Daytime in the City'</code>. The <code>10</code> before the name is the script priority, useful when assigning multiple scripts, but we'll get into that next. If no scripts meet requirements (in this case -- if it's NOT daytime when clicking on Steve), the text defined in the <code>Texts:</code> node called 'No Click Trigger' will trigger instead. So to reiterate, if the player clicks on Steve during the daytime, the player will get a chat containing 'Welcome to the city! Isn't it beautiful in the daytime?' If the player clicks during the nighttime, since the script requirements are not met and therefore no Click Trigger is found, the player will see a chat containing 'Come back during the day!'. Note that the default <code>No Click Trigger</code> text can be changed in the <code>config.yml</code>. Texts will be covered shortly.
Now Bob and Steve both have this one script assigned to them.
</div>
 


==== Multiple Script Assignments ====
==== Multiple Script Assignments ====
<div style="margin-right:2.0em; padding:10px; font-family:museo-sans; font-size:110%;">
The key to Denizens being dynamic is their ability to handle multiple scripts in different situations. Denizens can be assigned multiple interact scripts with varying requirements, changing their behavior based on player, npc, and world conditions.
The key to Denizens being dynamic is their ability to handle multiple scripts in different situations. This is done by assigning a priority to script assignments. Let's take this example configs below to see how script priority is handled. The below code references <code>assignments.yml</code> and a <code>script.yml</code>.
 
The important thing to remember is that:
 
'''For each interaction with a Denizen: ONE, and only ONE script is picked to run.
 
Which script gets picked is based on several factors:
* Each script's '''[[Requirements]]'''
* Each script assignment's '''priority'''
* Which '''triggers''' are defined on the script's active step for this player. (Advanced usage, see [[#An Overlay Interact Script Assignment ]])
 
Ignoring that last item for now, the process goes like this:
 
Starting from highest priority and working towards the lowest, the Denizen engine checks each script's Requirements.
The first script found that meets requirements is picked.
 
Let's look at an example.  


<pre>
---- assignments.yml ----
---- assignments.yml ----


Line 112: Line 99:
</pre>
</pre>


Denizen <code>Steve</code> has been assigned two scripts. Upon player interaction, each script is checked for met requirements. If only one script has their requirements met, it's clear what script will be returned. But what if both meet requirements? That's where the number before each script assigned comes in. Higher priority always wins. To break down this specific situation, if a player with the 'modifyworld.*' permission clicks on Steve, both scripts meet the requirements, but since the script 'Joe the Builder' has a priority of 10, and 'Regular Joe' only has a priority of 0, 'Joe the Builder' sends its script. 'Regular Joe' is simply ignored. Denizens can be issued as many scripts as you want.  If two scripts have the same priority, the first in the list will be the one to trigger, if both scripts meet their requirements.
Denizen <code>Steve</code> has now been assigned two scripts. Upon player interaction, both scripts are checked for met requirements in order of descending priority. Since the "Regular Joe" script has NO requirements at all, it will ALWAYS get picked before scripts of lower priority. This is why you can see in this example we gave it a priority of 0.
</div>
 
What if both scripts had a priority of 0? In that case the first script to appear in the list would get picked. It's always best to give each assigned script a different priority to avoid any confusion.


==== An Overlay Interact Script Assignment ====
==== An Overlay Interact Script Assignment ====
<div style="margin-right:2.0em; padding:10px; font-family:museo-sans; font-size:110%;">
 
{{color|red|white|Advanced usage!}} Overlay Script Assignments are new in 0.7 and open a wide array of new possibilities with multiple script interaction. This is completely optional, and probably should be ignored if you are a first time user and instead be revisited when you start to master Denizen Scripting.
{{color|red|white|Advanced usage!}} Overlay Script Assignments are new in 0.7 and open a wide array of new possibilities with multiple script interaction. This is completely optional, and probably should be ignored if you are a first time user and instead be revisited when you start to master Denizen Scripting.


A normal setup with multiple scripts is 'take this script', 'or take this script' kind of behavior. Interaction is pulled from whichever script has the highest priority, regardless of whether or not an actual trigger exists. If no trigger, default Text is pulled alerting the Player. With an Overlay Assignment, it will only honor the script if the actual trigger exists. If no trigger exists, the script triggering will become to the next script in the list -- the script with the second highest priority. Let's see an example. I should also note that to assign a script as an 'Overlay', use a '^' directly in front of the script name.
Normally, requirement-matching scripts are selected to run regardless of whether or not an actual matching trigger exists.  
 
If no matching trigger exists on the active step in the the script for the player, either nothing happens or some default text is shown, depending on the type of trigger.
 
With an Overlay Assignment, '''the defined triggers become a part of the requirements for selection.'''
 
A script assigned with this option will '''never''' be selected for a trigger type it cannot process.
 
This makes it easy to tack-on script assignments that only handle one trigger type, without having to mash it in to an existing script.
 
To assign a script as an 'Overlay', place a ^ directly in front of the script name.
 
Example time:


<pre>
<pre>
Line 169: Line 169:
</pre>
</pre>


Do you see now the possibilities of the Denizen Script Engine? I love it! Let's see what happens in a few different scenarios.
Here the 2 scripts from the last example will now only be selected for Click interaction, while the new 0 priority script will be selected for any interaction.
 
Let's see what happens in a few different scenarios.


'''First Scenario'''
'''First Scenario'''
Line 180: Line 182:
Player triggers a Proximity Trigger. Player has permission 'modifyworld.*', so the highest matching script is 'Joe the Builder' since it has a priority of 30. But there is no Proximity Trigger for this script, so the next script in line is checked. 'Regular Joe', of course, has no Proximity Trigger either! And since both 'Joe the Builder' and 'Regular Joe' are Overlay Assignments, we're back to 'Proximity Joe' triggering, alerting the player "Nice to see you, Player!".
Player triggers a Proximity Trigger. Player has permission 'modifyworld.*', so the highest matching script is 'Joe the Builder' since it has a priority of 30. But there is no Proximity Trigger for this script, so the next script in line is checked. 'Regular Joe', of course, has no Proximity Trigger either! And since both 'Joe the Builder' and 'Regular Joe' are Overlay Assignments, we're back to 'Proximity Joe' triggering, alerting the player "Nice to see you, Player!".


Do you see now the possibilities of the Denizen Script Engine? I love it


Simple, right? To get your teeth wet, take a look at this additional example situation which uses FLAGS and magic :)
Simple, right? To get your teeth wet, take a look at this additional example situation which uses FLAGS and magic :)
[[Denizen/Example_Scripts/Advanced_Scripts|Advanced Scripts]]


<pre>
# ASSIGNMENTS.YML ----
Denizens:
  Maggie:
    Interact Scripts:
    - 0 Magic Shop
    - 10 ^Magic Shop Not Enough Money
    - 20 ^Magic Shop Feathers
    - 20 ^Magic Shop Dust
   
# MAGIC SHOP.YML ----
   
'Magic Shop':
  Type: Interact
  Requirements:
    Mode: None
  Steps:
    1:
      Proximity Trigger:
        Script:
        - CHAT 'Welcome to my shop! Have a look around!'
      Click Trigger:
        Script:
        - CHAT 'What would you like to buy?'
        - HINT
      Chat Trigger:
        1:
          Trigger: I would like to buy some /feathers/.
          Script:
          - CHAT 'Great! Feathers are 20 coins.'
          - NARRATE 'Right click to purchase some feathers.'
          - FLAG 'MAGICSHOPITEM:FEATHER' 'DURATION:30'
        2:
          Trigger: I would like to buy some /glowstone dust/.
          Script:
          - CHAT 'Great! Glowstone dust is 50 coins.'
          - NARRATE 'Right click to purchase some glowstone dust.'
          - FLAG 'MAGICSHOPITEM:DUST' 'DURATION:30'
        3:
          Trigger: I would like to buy some /*/.
          Script:
          - CHAT "Ah! Sorry, I don't sell any of that!"
         
'Magic Shop Not Enough Money':
  Type: Interact
  Requirements:
    Mode: All
    List:
    - FLAGGED 'MAGICSHOPITEM'
  Steps:
    1:
      Click Trigger:
        Script:
        - CHAT "Ah, sorry! You don't have enough money!"
        - RESET 'FLAG:MAGICSHOPITEM'
       
'Magic Shop Feathers':
  Type: Interact
  Requirements:
    Mode: All
    List:
    - FLAGGED 'MAGICSHOPITEM:FEATHER'
    - MONEY 20
  Steps:
    1:
      Click Trigger:
        Script:
        - TAKE MONEY QTY:20
        - GIVE FEATHER QTY:10
        - CHAT 'Thanks! Here are your feathers.' 
       
'Magic Shop Dust':
  Type: Interact
  Requirements:
    Mode: All
    List:
    - FLAGGED 'MAGICSHOPITEM:DUST'
    - MONEY 50
  Steps:
    1:
      Click Trigger:
        Script:
        - TAKE MONEY QTY:50
        - GIVE GLOWSTONE_DUST QTY:10
        - CHAT "Thanks! Here's your dust."
</pre>


For a good exercise, I'll leave figuring out the flow of this script up to you!
</div>
</div>



Revision as of 04:10, 17 August 2012

Assignments

Interact Script Assignment

Before a Denizen can run a script, it needs to be assigned first.

Assignments are defined in plugins\Denizen\assignments.yml

This yaml file contains a single node called 'Denizens' and each Denizen gets its own entry under this node.

Assignments must be made by hand. We recommend a good text editor like [Notepad++]

Here is a very basic example, assigning a single interact script to a Denizen named Steve.

Denizens:                         
  'Steve':                        
    Interact Scripts:                      
    - 10 Daytime in the City  

Let's break this down.

First, if you are unfamiliar with yaml, 'Interact Scripts:' contains a yaml list. Each item in the list is prefixed with '-'. indentation and spacing is important.

This assignment will work for Denizens named 'Steve'. Denizen NPC names are case-sensitive! Triggers that involve this NPC, such as a 'Click Trigger' will now attempt to call the script named 'Daytime in the City'.

The 10 before the name is the script priority, useful when assigning multiple scripts.

If you wanted to assign this same script to another NPC, you would make another entry like this:

Denizens:                         
  'Steve':                        
    Interact Scripts:                      
    - 10 Daytime in the City  
  'Bob':                        
    Interact Scripts:                      
    - 10 Daytime in the City  

Now Bob and Steve both have this one script assigned to them.


Multiple Script Assignments

The key to Denizens being dynamic is their ability to handle multiple scripts in different situations. Denizens can be assigned multiple interact scripts with varying requirements, changing their behavior based on player, npc, and world conditions.

The important thing to remember is that:

For each interaction with a Denizen: ONE, and only ONE script is picked to run.

Which script gets picked is based on several factors:

Ignoring that last item for now, the process goes like this:

Starting from highest priority and working towards the lowest, the Denizen engine checks each script's Requirements. The first script found that meets requirements is picked.

Let's look at an example.


assignments.yml ----

Denizens:

 'Steve':                        
   Interact Scripts:                      
   - 0 Regular Joe
   - 10 Joe the Builder  

script.yml ----

'Regular Joe':

 Type: Interact   
 Requirements:
   Mode: None
 Steps:
   1:
     Click Trigger:
       Script:
       - CHAT "Hello <PLAYER>! I supply builders only!"

'Joe the Builder':

 Type: Interact  
 Requirements:
   Mode: All
   List:
   - PERMISSION modifyworld.*
 Steps:
   1:
     Click Trigger:
       Script:
       - ENGAGE
       - CHAT "Hello <PLAYER> the Builder! Take this shovel!"
       - GIVE WOOD_SPADE QTY:1
       - FINISH
       - DISENGAGE

Denizen Steve has now been assigned two scripts. Upon player interaction, both scripts are checked for met requirements in order of descending priority. Since the "Regular Joe" script has NO requirements at all, it will ALWAYS get picked before scripts of lower priority. This is why you can see in this example we gave it a priority of 0.

What if both scripts had a priority of 0? In that case the first script to appear in the list would get picked. It's always best to give each assigned script a different priority to avoid any confusion.

An Overlay Interact Script Assignment

Advanced usage! Overlay Script Assignments are new in 0.7 and open a wide array of new possibilities with multiple script interaction. This is completely optional, and probably should be ignored if you are a first time user and instead be revisited when you start to master Denizen Scripting.

Normally, requirement-matching scripts are selected to run regardless of whether or not an actual matching trigger exists.

If no matching trigger exists on the active step in the the script for the player, either nothing happens or some default text is shown, depending on the type of trigger.

With an Overlay Assignment, the defined triggers become a part of the requirements for selection.

A script assigned with this option will never be selected for a trigger type it cannot process.

This makes it easy to tack-on script assignments that only handle one trigger type, without having to mash it in to an existing script.

To assign a script as an 'Overlay', place a ^ directly in front of the script name.

Example time:

---- assignments.yml ----

Denizens:                         
  'Steve':                        
    Interact Scripts:                      
    - 0 Proximity Joe
    - 10 ^Regular Joe
    - 20 ^Joe the Builder  

---- script.yml ----
'Proximity Joe':
  Type: Interact
  Requirements:
    Mode: None
  Steps:
    1:
      Proximity Trigger:
        Script:
        - CHAT "Nice to see you, <PLAYER>!"

'Regular Joe':
  Type: Interact  
  Requirements:
    Mode: None
  Steps:
    1:
      Click Trigger:
        Script:
        - CHAT "Hello <PLAYER>! I supply builders only!"

'Joe the Builder':
  Type: Trigger   
  Requirements:
    Mode: All
    List:
    - PERMISSION modifyworld.*
  Steps:
    1:
      Click Trigger:
        Script:
        - ENGAGE
        - CHAT "Hello <PLAYER> the Builder! Take this shovel!"
        - GIVE WOOD_SPADE QTY:1
        - FINISH
        - DISENGAGE

Here the 2 scripts from the last example will now only be selected for Click interaction, while the new 0 priority script will be selected for any interaction.

Let's see what happens in a few different scenarios.

First Scenario Let's say a Player clicks, doesn't have the permissions 'modifyworld.*', so therefore only two scripts meet requirements: 'Regular Joe' and 'Proximity Joe'. It should be pretty obvious what happens. 'Regular Joe' has higher priority, so a Click Trigger will use that script. The Player will see "Hello Player! I supply builders only!". That's the only trigger, right? Wrong. This leads us into the next scenario.

Second Scenario The first thing to trigger the Denizen NPC would actually be the Proximity Trigger. In a regular assignment situation, with the same permissions situation as the first scenario, 'Regular Joe' would beat out 'Proximity Joe' and since there is no Proximity Trigger in 'Regular Joe', no script would trigger. But this is an Overlay Assignment. Since there is no Proximity Trigger in the script 'Regular Joe', the next script available, 'Proximity Joe', would attempt to trigger instead. And what do we have here? A Proximity Trigger! The Player would see "Nice to see you, Player!".

Third Scenario Player triggers a Proximity Trigger. Player has permission 'modifyworld.*', so the highest matching script is 'Joe the Builder' since it has a priority of 30. But there is no Proximity Trigger for this script, so the next script in line is checked. 'Regular Joe', of course, has no Proximity Trigger either! And since both 'Joe the Builder' and 'Regular Joe' are Overlay Assignments, we're back to 'Proximity Joe' triggering, alerting the player "Nice to see you, Player!".

Do you see now the possibilities of the Denizen Script Engine? I love it

Simple, right? To get your teeth wet, take a look at this additional example situation which uses FLAGS and magic :) Advanced Scripts


Texts

In addition to handling the script assignments, there are also a few other things that can be declared in the Denizens node of assignments.yml. Under the text node you can define single chat lines that will be displayed for each of 3 core trigger types if there is not matching script found. Click, Damage and Chat. Additionally a message can be defined for when the Denizen is Engaged or its interaction cooldown isn't finished.

Settings here override the default setting found in Denizen/config.yml for this Denizen.

Denizens: 
  Castle Guard: 
    Interact Scripts: 
      - 10 Guard_Script
    Texts: 
      No Click Trigger: Don't poke, me, <PLAYER>!
      No Damage Trigger: Ouch! you lookin' to get smacked?
      No Chat Trigger: Eh, what's that?
      Denizen Unavailable: I'm busy right now.

Other Things to Note

Denizens with the same name use the same script assignments. The plus to this is the ability to quickly make 'generic NPCs' such as a 'Townsman' or 'Miner'. You can also assign to NPC IDs instead of name. This is covered in Advanced Usage.

All the scripts and configuration nodes are in YAML. Remember! Spacing is CRITICAL when dealing with YAML files. Each parent node and sibling node should follow the spacing and formatting guidelines set forth by the YAML 1.0 standard. Generally, your indents should remain consistant. In all the examples used in this guide, 2 spaces are used for indenting. Generally, whatever you choose should be maintained through your YAML document. Remember: NO TABS are allowed in YAML files. If you are using notepad++ to edit your scripts, be sure to change the tab->space setting in Preferences>LanguageMenu/Tab Settings.

In all the denizen YAML files, nodes are case sensitive! For example, in a script.yml, 'Scripts:' will work. 'scripts:' will not! All nodes are first letter capital, rest of the word lowercase. Scripts names follow this rule too! Also: Commands/Requirements are generally ALL UPPERCASE, but we'll get to that.

YAML tutorials can be intimidating, but this small tutorial on the Essentials wiki is pretty useful for basic YAML, which is the extent of which Denizens uses.