Denizen/0.7

From Citizens Wiki
Denizen.png

Denizen is an extension for Citizens that allows scripting of NPCs to handle tasks, quests, player interaction and more!

Current Version: 0.7 BETA

Developers: aufdemrand

Source: Github

Development Builds: Jenkins

Latest Developmental Build: 2.0.2

Support tickets: Tickets on Github, but please read the entirety of this document first.

Donate: A lot of man hours has been put into Denizen. Your donations add a lot to the project and are always welcome! Your donations will probably help remodel my house and feed my kids. :) Donate to aufdemrand Don't forget to donate to the Citizens2 project as well, as none of this would be possible without that!

Thank You: A lot of people have stepped forward to help out with Denizen, and that's awesome! Special thanks to everyone who has beta tested, and a huge to these people: fullwall, AgentKid, aPunch, NeonMaster, Instinx, tenowg, groggluebutt, Wreyth, jrbudda, spidi, the list could go on!

CitizensUI: For a GUI interface, check out CitizensUI by jrbudda which provides an interface for Citizens NPCs as well as managing scripts and other NPC types.

Denizens are a great way to add MUD-style RPG Citizens to your server. Denizen NPCs use mini scripts with steps and events to interact with the player and world. Imagine interactive gate-keepers, magical wizards, experience trainers, bankers, talking townspeople and more! They can be used in thousands of different ways, from tutorials, to questing, to administrating.. your imagination is just about the limit! Though Denizen uses Scripting, it is not to be confused with Citizens2 Core Scripting which utilizes JavaScript and other major scripting languages to implement Goals. Instead, Denizen uses its own YML 'scripting language' which is designed to be easily read and edited by hand.


Script Repository

http://form.jotform.us/form/21498151597160|https://www.dropbox.com/sh/hw6x3f980maa8d9/DNtzAw8cn3Script Repository.png
About this image


Change Log

First, thanks for being patient, I know there has been a lot of anxious people waiting for the new release. This took a lot longer to do than I thought, but it's worth it! Updating code and adding content is easier than ever, so keep those feature requests coming in! I also want to put out there that I took OUT the PLAYERTASK command, so please be patient with me as I know a lot of you were looking for more 'quest types'. I am instead placing this in another plugin that will extend Denizen called the Adventurer. This will have similar functionality to the 1.2 Quester, but use Denizen as the core so it can be more flexible and powerful than ever!

Second, a huge sorry to current faithful users. I have made a promise to myself and you to try to maintain compatibility throughout the evolution of Denizen. I take that seriously, and that being said, I had to change some syntax around in regards to new commands to make way for cleaner code and the ability to have greater flexibility. The upside to this is there are more options and modifiers for commands than ever before! The downside is there's probably a few commands that you will have to check and fix syntax for if trying to run a 0.6 Denizen Script with the new builds. I am EXTREMELY sorry, but expect some syntax to change on some Requirements soon, too!

Here's what's changed!


0.7 BETA builds #125 - #280:

  • Updated! Less bugs! We're still in beta, but there has been some major code cleanup!
  • New! Triggers, Commands, and Activities are now extensible by plugin programmers. See: Custom Denizen Commands on the Citizens2 Wiki. Documentation for extending Triggers and Activities coming soon. Note: Requirements will be extensible very soon.
  • New! Debug Mode will let you see the logic of interaction and script execution to help you find problems in scripts faster than ever.
  • New! Info-Click lets you see Denizen stats and specifics, such as script assignments and associated bookmarks with just a crouch and a click.
  • New! Location Triggers can trigger a script when a Player walks over a Location Bookmark.
  • New! Damage Triggers separate the left and right clicks for more control over interaction.
  • New! Script Overlay mode is a whole new way to assign a script. Less copying/pasting when working with multiple scripts, not to mention more control!
  • New! HINT command will hint to the Player acceptable Chat Triggers for the current step and script.
  • New! FLAG command lets you set 'flags', on players to store progress, important information, or other variables that can be used with the FLAG requirement.
  • New! FLAG requirement can require special flags and values to be set in order to be eligible for a script.
  • New! The activity engine has been implemented which will allow your Denizens to do things on their own. There's a whole lot more to this concept, but you can try out the new WANDER activity with bukkit commands or script commands.
  • New! In-game commands now let you easily manage assignments, texts, and bookmarks!
  • Updated! Extended/unified command syntax for almost every existing command.


You can see more at the full Denizen changelog.

Getting started with Denizen

Denizen is in BETA! Expect a few bugs here and there! If you are having problems, /denizen debug is your friend! We're always willing to help out in #denizen-dev on EsperNET as well. If you do come across any errors beyond bad command syntax, please report them to the Github Issues page for Denizens.

Denizen is not a drag-and-go type of plugin. In fact, Denizen won't do anything unless you assign and define scripts to NPCs. It's highly customizable. In order to write awesome scripts, you will need to read the entirety of this wiki page and think outside the box! I'm always around IRC to help out and provide suggestions, but please don't ask about the basics unless you have consulted here first.

Some Denizen commands and requirements REQUIRE you to have Vault installed with a compatible Permissions System and and Economy System. If the commands deals with money or permissions, chances are you will need Vault in order to utilize it.

The easiest way to use Denizen for the first time is to download the Start-up Kit with sample .yml configuration files and scripts. This includes the default config file, sample scripts, and sample assignments to get you started.

Denizen relies on a few files to run properly, so let's first go over the file structure.

File Structure

Denizen File Structure

Denizen requires the use of a few different YML files to operate properly. This includes a config.yml, assignments.yml, scripts, and saves.yml.

denizen.jar

I've gotten a few questions about where to place the Denizen JAR file. It should be treated like any other bukkit plugin and be placed in your craftbukkit/plugins/ folder. Please note that while a lot of plugins will automatically generate a folder to go along with it, Denizen does not, and this should be either created by hand and populated, or generated by copying the Start-up Kit with sample .yml configuration files and scripts.

config.yml

The Denizen config.yml contains nodes to alter the stock behavior and look of Denizen. You'll notice that Denizen does not create its own config.yml. Why is this? Denizen stores its entire config inside memory, so it's not necessary to have a copy inside the Denizen folder unless you need to change the defaults. You can use the config.yml to override those defaults. Not having Denizen write to the config.yml itself (as well as scripts files) ensures that upon a /denizen reload, the config.yml, between a save and reload, is never changed when you don't want it to. This also keeps code comments inside the YML files stay intact, exactly the way you left them from last edit allowing you to leave yourself and others detailed notes and ideas.

This file can be reloaded from disk to Denizen memory at any time by using /denizen reload. Some changes in the config.yml may require a restart of the server. This includes interact_delay_in_ticks, but is not limited to that config node.

See: Denizen config.yml for a stock copy and explanation of all available options.

assignments.yml

This YML is where you can define all the options and information for your Denizen NPCs. This will be explained further along in this document, but the most common information in this file is [Interact Script Assignments], [Activity Script Schedule], and [Custom Interact Texts].

This file can be reloaded from disk into Denizen memory at any time by using /denizen reload, and, if using in-game commands to assign scripts, it should be saved to disk before editing it by hand with /denizen save.

See: #A basic assignment for information on how to get started with assignments.

saves.yml

This file is not meant to be edited by hand, Denizen will create and populate this file automatically as needed. It stores important information such as player progression, flags, Denizen location and block bookmarks, active activity script progression and more. If you absolutely need to make changes by hand, it's best to stop the server, edit, and then restart your server, as this file is constantly being written to by Denizen which will overwrite any changes you make.

To reiterate: This file saves periodically, and automatically, upon progression and a server stop, and should only be edited by hand when the server is off or Denizen is disabled.

read-only-scripts.yml

This is another files that Denizen creates and should not be edited by hand. This is a combination of the files contained in the scripts folder that Denizen reads from.

This file is populated on a server restart, or by using the /denizen reload command.

/scripts/ folder

This folder is where Denizen will read all the script information from. Upon a server load or /denizen reload, the files are combined and put into the read-only-scripts.yml for the Denizen to read from. This allows better organization of scripts to be maintained, since the amount of scripts can easily get into the triple digits.

The files in the plugins/Denizen/scripts/ folder can be named whatever you please, as long as they end in .yml. Be sure not to duplicate script names from file to file as this will cause problems. All scripts in the scripts folder are merged into read-only-scripts.yml, so there will be an issue if two scripts are named the same.

See: A basic Interact Script for information on how to get started with scripts.


In-Game Commands

Denizen has some in-game commands that help manage Denizen NPCs and scripts. Some commands will require additional knowledge of other parts of Denizen, but I've included this first to get them out of the way. Note: There are NO commands for Players using Denizens. Commands are intended for OP use only. These are to be used in addition with all the core C2 NPC commands, so you should know those as well.

Denizen NPC Creation

Creating a Denizen NPC is easy! Simply use the core C2 commands as such:

/npc create 'Name of NPC'
/npc trait denizen

That's it! You can, of course, use any of the core C2 commands to change the mob-type and other traits, which are referenced in the Citizens2 command page. Baby Chicken Denizens? Totally cool! Charged Creeper Denizens? Even cooler!

Info-Click

/denizen info

The best way to get information about your Denizen NPC is to use Info-Click. If you are OP, simply crouch-right click an NPC to get a list of NPC stats, script assignments, block bookmarks, texts, and trigger statuses. This information can also be reached by selecting an NPC (C2 Core Function, usually by right-clicking with a Stick), and using the /denizen info command.

Debug Mode

/denizen debug
/denizen stacktrace

I've done my best to catch errors and output them in a friendly and informative matter. This can be enabled by using /denizen debug. It is recommended that you use this if you get unpredictable behavior from your scripts. If you are running into a problem that seems to beyond bad command syntax, I may ask you to use the /denizen stacktrace command in conjuntion with debug mode. This will enable stacktraces for serious errors which help me find the location of problems in the code.

Script Assignment

/denizen assign [#] [(^)Name of Script]
/denizen remove [Name of Script]
/denizen list

Script assignment can always be done by hand (which is what I personally prefer) by simply editing the assignments.yml and using a /denizen reload, but if you would rather use in-game commands, they are provided. Scripts assignments require a priority and a script name. You can also use a '^' at the beginning of the script name to indicate an Overlay Script Assignment. This is all covered in the Assignments section.s are covered further down in the document.

Bookmark Creation

/denizen bookmark block [name]
/denizen bookmark location [name]
/denizen bookmark remove [name]
/denizen bookmark list

Bookmarks are 'saved locations' for your Denizen to reference in Scripts. There are currently two types: Location Bookmarks and Block Bookmarks. Bookmarks are an easier way to handle locations, since X Y and Z coordinates can get out of hand very easily. You can always check which bookmarks a Denizen NPC has by using Info-Click, or by selecting a Denizen NPC and typing /denizen bookmark list.

Block Bookmarks

Block bookmarks are created by first selecting a Denizen you wish to assign the bookmark to, then by pointing your crosshairs to a block and typing /denizen bookmark block [name]. Remember, names should only be one word and are case-sensitive. Commands such as CHANGE, and SWITCH require block bookmarks. The POWERED requirement also requires a block bookmark. When listing bookmarks you can easily see the Material of the block as well as if it is currently powered by redstone. Possible Scenario: Need to check the status of a redstone torch in your script? Easy! Create a block bookmark at that location and use the POWERED [bookmark] requirement to base script interaction on the status of the torch. Any block that can be powered can be used.

Location Bookmarks

Location bookmarks store the X,Y and Z coordinates as well as the Pitch/Yaw of the Player are useful in a couple different ways. First, they store an exact X,Y,Z Location that can be utilized with commands such as TELEPORT, SPAWN, and WALKTO. The second set of information in a Location bookmarks is the Pitch and Yaw, which can be useful with the LOOK command. Upon creation, the location, pitch, and yaw of the Player is the information that is stored. Possible Scenario: Need a Denizen to look at a clue? Easy! Create a Location bookmark while looking at the spot, then use LOOK [bookmark] to have the NPC Denizen look in the same direction.

Location bookmarks are also used to define the 'Trigger: node' in Location Triggers.

Assignments

Still reading? Great! You're on your way to writing some sweet scripts. Let's start out with the basics: Interact Scripts and Assignments. 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!

A basic interact script

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. We'll get more detailed later on.

Remember: Scripts are defined in plugins/Denizen/scripts/ 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.

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

So what just happened there? A quick literal translation: This script is named 'Daytime in the City'. This name is used when assigning Denizen NPCs their scripts. When the script is called by a trigger, in this case a 'Click Trigger', for it to activate the Requirements set must be met, more specifically ALL of the requirements set. In this example, the only requirement is TIME DAY which requires the current time in the world to be daytime. If the Requirements are met, the script defined in the 'Click Trigger' 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?'.

But before the script can be triggered, it needs to be assigned.

A basic assignment

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.

Denizens:                         
  'Steve':                        
    Interact Scripts:                      
    - 10 Daytime in the City  
    Texts:
      No Click Trigger: 'Come back during the day!'

Let's break this down again. This assignement will work for Denizens named 'Steve'. Denizen NPC names are case-sensitive! Triggers that involve this NPC, such as a 'Click Trigger' will call the script named 'Daytime in the City'. The 10 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 Texts: 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 No Click Trigger text can be changed in the config.yml. Texts will be covered shortly.

Multiple Script Assignments

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 assignments.yml and a script.yml.

---- assignments.yml ----

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

---- script.yml ----

'Regular Joe':
  Type: Trigger   
  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

Denizen Steve 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.

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.

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.

---- assignments.yml ----

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

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

'Regular Joe':
  Type: Trigger   
  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

Do you see now the possibilities of the Denizen Script Engine? I love it! 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!".


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

# 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 /*/.
          - 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."

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

Texts

In addition to handling the script assignments, there are also a few other things that cam 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.

Interact Scripts

Hopefully you've gotten a basic idea of a script by reading about Assignments in the previous section. If you have, you'll notice that the general structure of a script should always include the 'Name', 'Type', 'Requirements', and 'Steps' nodes.

Scripts are defined in the plugins/Denizen/scripts/ folder. Any .yml file in that directory will be loaded into Denizen. For example purposes on this website, reference to script.yml is made, but again, jimbobjoe.yml or 'skeeter the cat.yml' would work just the same..

General layout of an Interact Script

'Name of script':   # Name Node
  Type: Interact    # Type Node
  Requirements:     # Requirements Node
    ...:
    ...:
      - ...
      - ...
  Steps:            # Steps Node
    ...:
      - ...
    ...:

Name Node

This node is pretty self-explanatory, but here are some things to keep in mind.

  • Names, just like nodes are case-sensitive! 'This script name' is different than 'THIS SCRIPT NAME'.
  • Names that contain spaces should have single or double quotes around it. ie: "This script": or 'This script': is acceptable.
  • If the name includes a single quote in it, you must use double quotes around it, or 'escape' the quote with another quote. ie: "John's Script": or 'John''s Script':

Type Node

Let's Denizen know the type of script. For interact scripts, as explained in this section, use TYPE: INTERACT. For reference, there are also TASK scripts and ACTIVITY scripts, which is covered later.

Requirements Node

This node sets the rules for the player to qualify for the script. There are a couple different options that you should know when using requirements. For example:

 Requirements:
   Mode: All
   List:
   - TIME Night
   - MONEY 1000000
   - STORMY

This would be a difficult script to obtain, for sure. To trigger, the time must be night-time, the player would need one million units of currency, and the weather must be storming, but it shows the flexibility of requirements. First is the 'Mode'. Currently there are three different types. Second is the requirement type, with arguments if applicable.

Requirements Mode

[] indicates required field.

ALL

  Requires all requirements listed to be met.

ANY [#]

  Requires the specified number of requirements to be met out of the total of requirements.

NONE

  No requirements need to be met. There is also no need to have a LIST node if using NONE.
Requirements

Note: Requirements are due for a re-code to make them extensible like Commands. This will improve tolerence and allow for better debugging, as well as make it easy for other plugin programmers to extend Denizen. What this means to you is that it will probably change up some syntax formatting in future updates.

[] indicates required field, () indicates an optional field, | indicates alternative usage.

Click on any requirement to get more information and example usages.

Player Requirements

  [Player Name]  (Player Name)  (Player Name) ...
  [[ITEM_NAME]|[#]:[#]]  (Quantity)
  [[ITEM_NAME]|[#]:[#]]  (Quantity)
  [[ITEM_NAME]|[#]:[#]]
  [Full|Hungry|Starving]
  [# or higher]  OR  LEVEL  [At least this Level #]  [No more than this Level #]
  [POTION_TYPE]
  [>,<,=] [#|#%]

WORLD REQUIREMENTS

  [World Name]  (World Name)  (World Name) ...
  [Day|Night|Dusk|Dawn] OR TIME [0-23999] [1-24000]
  [Block Bookmark]
  
  

SCRIPT REQUIREMENTS

  (# of times)  [Script Name]
  (# of times)  [Script Name]
  [Name of Activity]
  (FlagName:Value OR FlagName #)

VAULT REQUIREMENTS

These requirements only work if you have Vault installed and a compatible permissions/economy plugin.

  [permission.node]
  [Group Name]  (Group Name)  (Group Name) ...
  [Quantity]

Negative Requirements

Requirements can also be 'negative' requirements. In the Requirements List, just place a '-' in front of the requirement to inverse its logic. For example, 'HOLDING IRON_SWORD' would require the player to be holding an Iron Sword. '-HOLDING IRON_SWORD' would require the player to NOT be holding an Iron Sword. All requirements have a negative alternative, even ones whose function may overlap, such as '-WEATHER Precipitating' and 'WEATHER Sunny', which technically do the same thing. If anything, it can add to script readability. The negative requirement '-' should not be confused with the 'list item -' with a trailing space in front of each Requirement in the List, as that is standard YAML list format. See below:

 Requirements:
   Mode: All
   List:
   - -TIME Night
   - -MONEY 1000000
   - -STORMY

Negative requirements can completely change the original example around. In this 'revised' example, for this script to trigger, time needs to be day, the weather in the current world must NOT be storming, and the player have less than 1000000 units of currency on them.

Steps Node

Steps are the meat of the script. They control what to listen for and what actions to take. Each script can have multiple steps, each with multiple triggers. Let's use an example.

'Welcome to Harbortown':
  Type: Interact
  Requirements:
    Mode: NONE
  Steps:
    '1':
      Click Trigger:
        Script:
        - CHAT 'What's your name, stranger?'
      Chat Trigger:
        '1':
          Trigger: My name is /<PLAYER>/.
          Script:
          - CHAT 'Ah ha, your name sounds familiar! '
          - CHAT 'Are you from around this area?'
          - ZAP
    '2':
      Click Trigger:
        Script:
        - HINT
      Chat Trigger:
        '1':
          Trigger: /Yes/, I grew up in Harbortown!
          Script:
          - CHAT 'I thought so, welcome back! 
            Have you heard about Tom the Taylor? 
            Isn't that just horrible?'
          - ZAP 3 
        '2':
          Trigger: /No/, you must be mistaken. 
          Script:
          - CHAT 'Oh, sorry about that.' 
          - CHAT 'Hey, if you're looking for some work, 
            Bill the Baker is understaffed! 
            This is the bakery's busy season.'
          - ZAP 4
    '3':
      Click Trigger:
        Script:
        - CHAT 'I wonder if Tom the Taylor is doing any better.'
        - NARRATE 'Perhaps you should check on Tom the Taylor.'
    '4':
      Click Trigger:
        Script:
        - CHAT 'Oh, nice to see you again <PLAYER>!'
        - CHAT 'Have you stopped by the bakery?'

The sub-sections below reference this example.

Trigger Nodes

Steps handle the flow of commands and messages with triggers.

Denizen Triggers trigger from interaction with Denizens. They are defined in the Steps: node.

  • Click Triggers activate when the Denizen is right-clicked.
Click Trigger:
  Script:
  - CHAT "Teehee, that tickles!"
  - EMOTE "giggles"
  • Damage Triggers activate when the Denizen is left-clicked. If the Denizen has Damage Triggers disabled, this will count as a Click Trigger.
Damage Trigger:
  Script:
  - CHAT "OUCH, You'll pay for that!"
  - STRIKE <PLAYER>
  • Proximity Triggers activate when a player walks close to the Denizen.
Proximity Trigger:
  Script:
  - CHAT 'Eek! get away, you smell bad, <PLAYER>.'


  • Chat Triggers activate when players chat with Denizens. Players' chat within the configurable range will be directed to the Denizen instead of global chat. Chat also follows the configuration setting. a single chat trigger entry can handle multiple words, see below:
Chat Trigger:
  '1':
    Trigger: The word needed to /Trigger/ is inside slashes, this whole sentence will appear to be said by the player
    Script:
    - CHAT "Good to know!"
  '2':
    Trigger: A chat trigger can also catch on any word not otherwise caught using /*/. 
    Script:
    - CHAT "I don't know what <*> mean, <PLAYER> !

  • Location Triggers activate when players walk near a Location Bookmark. Like chat triggers, multiple locations can be defined in one Location Trigger.
Location Trigger:
  '1':
    Trigger: TreasureRoom
    - TELEPORT Jail
  '2':
    Trigger: BedRoom
    - NARRATE 'You enter the bedroom of the dead man, looking for clues'

For a full list of commands, see #Script Commands

Task Scripts in detail

Task scripts are script that are called by either the RUNTASK command or PLAYERTASK command. These are more basic than trigger scripts since they have no requirements or step nodes. The types of commands are also more limited since there is no NPC Denizen associated with the script, but useful for certain situations.

General layout of a Trigger Script

'Name of script':   # Name Node
  Type: Task        # Type Node
  Script:           # Script Node
  - ...
  - ...

Using a Task Script with RUNTASK

Imagine a scenario where you'd like to check a single outcome from multiple sources. Say, for instance, you have multiple 'quests' that all have the same outcome. You could check the completion for each quest, or, you could have all the quests call a Task Script and check against that.

This is a very basic example for something that can in theory be very complex. Imagination, hoooo!

'Apple Reward': 
  Type: Task    
  Script:       
  - NARRATE You've received some APPLES. Nice!
  - GIVE APPLE 10
  - FINISH

'Apple Quest 1':
  Type: Trigger
  Requirements:
    Mode: All
    List:
    - -FINISHED Apple Reward
  Steps:
    '1':
      Click Trigger:
        Script:
        - CHAT Welcome to my house, have some apples!
        - RUNTASK Apple Reward
  
'Apple Quest 2':
  Type: Trigger
  Requirements:
    Mode: All
    List:
    - -FINISHED Apple Reward
  Steps:
    '1':
      Click Trigger:
        Script:
        - CHAT Welcome to my orchard, have some apples!
        - RUNTASK Apple Reward

Using a Task Script with PLAYERTASK

Tasks scripts are very straight forward when using with a PLAYERTASK command. The script that is called when the 'player task' is complete is a Task script.

'Graveyard Investigation':
  Type: Trigger
  Requirements:
    Mode: NONE
  Steps:
    '1':
      Click Trigger:
        Script:
        - CHAT Go investigate the graveyard for me!
        - PLAYERTASK LOCATION graveyard 20 120 Graveyard Search

'Graveyard Search': 
  Type: Task    
  Script:       
  - NARRATE You are thoroughly spooked out. Maybe you should return to Dave.
  - FINISH

'Graveyard Investigated Complete':
  Type: Trigger
  Requirements:
    Mode: All
    List:
    - FINISHED Graveyard Search
  Steps:
    '1':
      Click Trigger:
        Script:
        - CHAT Ahhh, dang. You couldn't find anything? Ah well, thanks for your help!

Interact Script Commands

Note: There are plenty more to come, be patient, more are coming! Have ideas for a good command? Let me know!

[] indicates required field, () indicates an optional field, OR indicates alternative usage.

Script Flow Commands

These commands have no external affect on the world, but can control the flow of scripts within Denizen. Though not required, and with the exception of WAIT, it is generally recommended to run these as Instant Commands to ensure smooth Script feedback to players.

ENGAGE

DURATION:[#]) (NPCID:[#])

Blocks player interaction from triggering the NPC. This may be useful if a long script required the player to listen or watch a series of events and you didn't want the Player to be able to interact while these commands were being taken out. Use with either a DURATION or DISENGAGE. DURATION will automatically DISENGAGE after the specified amount of seconds. If no NPCID is included, the Denizen triggered is used. Remember: While ENGAGED, no scripts will trigger, so be diligent in using!

Example Usages

- ENGAGE
- ENGAGE DURATION:12 NPCID:3
- ENGAGE NPCID:2

DISENGAGE

  (NPCID:[#])

Allowed an ENGAGED Denizen to be interacted with again, the counterpart to the ENGAGE command. Can also specify the NPCID of a different Denizen

ZAP

([Step #]) ('SCRIPT:[Name of Script]') (DURATION:[#]) ('RANDOM:[#] (#)')

A very powerful command, indeed. This is how Scripts progress through their steps. It is not done automatically, instead, you get to decide how to progress. ZAP used alone will simply progress the Player to the next step in the Script. Note: Denizen does not check whether the step exists, so you can use that to your advantage in an Overlay Script Assignment. If an Integer is used, that step will be used.

Specify a SCRIPT to change the active step for a Player in a specific Script. If not specified, the triggering Script is used. A DURATION can be set to provide an automatic "DEZAP" of sorts, reverting the step back after a specific amount of seconds, unless, in that duration another ZAP command has taken place. This can be used as a 'timeout' of sorts. RANDOM can be used to let chance select the step to progress the Player to. If one Integer is included, steps 1 through the chosen number will be randomly selected. You can also use a range of numbers if two Integers are used.

Example Usages

- ZAP
- ZAP 'RANDOM:3 6' DURATION:60
- ZAP 'SCRIPT:Another Script' 6

WAIT

  [# of Seconds]  (QUEUE:TASK|TRIGGER)

Pauses a Queue for a specified amount of seconds. If no QUEUE is specified, the sending queue is used. For example, if the command is sent from an Interact (Triggered) Script, the queue that will be held is the 'Trigger Queue'. Could be useful in advanced usage situations when using both Task Scripts and Interact Scripts together.

Example Usages

- WAIT 6
- WAIT 30 QUEUE:TASK

FLAG

  '[Flag Name]' OR '[[Flag Name]:[Flag Value]]' OR [[Flag Name]:++|--]' (DURATION:[#])

Requires one of the above arguments. FLAG store variables, or 'flags', to a Player. This can be used to keep track of information that can be check against with the FLAGGED requirement. Usage of the command is easy, and can be used in 3 different ways. A Boolean (true/false) value can be set with only a flag name. If set, the value is TRUE. When RESET, it is FALSE. FLAG can also set Integer (or number) variables, and easily increment or decrease them with the use of the ++ and -- arguments accordingly. The command can also store a String value, see the example below. Using a DURATION will revert the value of the flag to the previous value, if during the duration the flag has not changed.

Example Usages

- FLAG 'Sample Boolean Flag'
- FLAG Alignment:++
- FLAG Alignment:--
- FLAG 'Active Item:60 Feathers'
- FLAG HasHealingFlag DURATION:180

FINISH

  ('SCRIPT:[Name of Script]')

Marks a script as 'Finished' to check against with the FINISHED requirement. This is kind of like a built-in flag for scripts, and acts much like a Counter, ie. You can FINISH a script multiple times and it will keep track of the total number, unless RESET.

Example Usages

- FINISH
- FINISH 'SCRIPT:Another Script'

FAIL

  ('SCRIPT:[Name of Script]')

Marks a script as 'Failed' to check against with the FAILED requirement. This is identical to the FINISH command, except keeps track of 'fails' instead. Again, this is kind of like a built-in flag for scripts, and acts much like a Counter, ie. You can FAIL a script multiple times and it will keep track of the total number, unless RESET. Note: A script can be both 'finished' and 'failed', the two commands work independently.

Example Usages

- FAIL
- FAIL 'SCRIPT:Magic Feathers'

RESET

  ('SCRIPT:[Name of Script]')

Sets either FINISHED or FAILED of the specified script to False. Remember: Script names are case sensitive!

Example Usages

- FAIL
- RESET FINISHED 'SCRIPT:Magic Feathers'

Server Commands

EXECUTE

[ASPLAYER|ASSERVER|ASNPC] '[command with arguments]'

Runs a Minecraft/Bukkit command. Specifying ASPLAYER, ASSERVER, or ASNPC defines how the command should be executed. ASNPC will run the command as the Denizen interacting, temporarily granting OP privileges, if the Denizen NPC is a Human-type NPC. Running ASSERVER will run as a console command, and running ASPLAYER will simply run the command as the Player. When specifying the command and arguments, it is not necessary to use the '/' that is generally used when running commands in-game. You may also use <PLAYER> and <WORLD> as variables inside the command arguments.

Example Usages

EXECUTE ASSERVER 'gamemode <PLAYER> 2'
EXECUTE ASNPC 'toggledownfall'
EXECUTE ASPLAYER 'spawn'

</npc>

Text Commands

These commands show some text to the player interacting, and usually to bystanders around. Note that all text commands must be surrounded by quotes single ' or double ". See: Which Quotes? for more information. Text commands also have some auto-formatting, such as making sure no words will be cut off on long messages, and applying color codes. See: Denizen Color Codes. Formatting for how NPCs and Players talk can be customized in the config.yml.

CHAT

["The text to chat."] (NPCID:[#]) (NOPLAYER)

Makes the Denizen talk to the player. This is the standard chat mechanism in Denizen. You can also change the NPC doing the talking by specifying a Denizen's C2 NPCID. If you would rather the Denizen NPC not speak to the Player directly, use the NOPLAYER argument.

Example Usages

- CHAT NOPLAYER "Here ye, hear ye!"
- CHAT "Hello there, children!"
- CHAT NPCID:6 'I only supply tools to builders!'

WHISPER

["The text to whisper."] (NPCID:[#]) (NOPLAYER)

Whispers the text to the player. Really just an alternative to CHAT. By default, bystanders can't hear what the NPC whispers to the interacting Player. As with the CHAT command, NPCID can be specified. Using NOPLAYER is possible too, since it may be of use in some circumstances. But remember: by default, no bystanders can see the actual text the NPC Denizen whispers. This can be changed in the config.yml.

Example Usages

- WHISPER "The password is.. 42."
- WHISPER NPCID:2 "Hey, I didn't want to blurt this out so everyone could hear, but..."

SHOUT

["The text to chat."] (NPCID:[#]) (NOPLAYER)

Shouts the text to players nearby. The range that a bystander can hear an NPC Denizen shout is larger then that of a standard CHAT, so it also has some technical advantages. NPCID can be specified. Using NOPLAYER will drop reference to the Player when talking. You can still reference <PLAYER>, however, if need be. See the example below for an idea for usage.

Example Usages

- SHOUT "EEEK! a spider!"
- SHOUT NOPLAYER "<PLAYER> is a thief! Get him!"

EMOTE

['The text to emote.'] (NPCID:[#])

Let's the Denizen NPC show emotion. Similar to the /me command in IRC, for example. Could be useful for describing to the player what an NPC Denizen may need, or how the NPC Denizen is feeling. NPCID can be specified to change the Denizen NPC doing the 'emote'.

Example Usages

- EMOTE 'is looking a bit nervous.'
- EMOTE NPCID:82 'thinks you should ask a few questions.'
- EMOTE "could use a stiff drink."

NARRATE

['The text to narrate.']

Makes a message appear to player without sender information.

Example Usages

- NARRATE "There is a small mailbox here."

ANNOUNCE

['The text to announce.']

Sends the text as a sever announcement to all players, regardless of their place in the world. Could be especially useful for any kind of administration script.

Example Usages

- ANNOUNCE "<PLAYER> has found a secret!"

Denizen NPC Commands

Denizen NPC commands are meant to help bring your Denizen to life by allowing fine-control of small movements. These are not necessarily meant for making the Denizen NPC do large/long activities, those will instead be done by the Activity Engine, which is just now starting to be implemented into Denizen. The next 'large' update will focus on Activities.

LOOK

LOOK [[DIRECTION]|BOOKMARK:[BOOKMARK_NAME]|[CLOSE|AWAY]] (NPCID:[#]) (DURATION:[#])

This command controls where the NPC Denizen is looking. It requires either a Direction, Bookmark, or look-close trait state. Valid directions: UP, DOWN, LEFT, RIGHT, NORTH, SOUTH, EAST, WEST, AT, and BACK. Looking AT or BACK takes the Player's position for reference. AT will look at the Player, BACK will look away from the player. Using CLOSE

  • FOLLOW [PLAYER|NOBODY]
    Makes the Denizen follow the player, or stop following the player.
  • WALKTO [Location Bookmark]
    Makes the Denizen walk to a specified location.

Note: I've been having problems getting the NPCs to WALKTO a bookmarked location that is far away, perhaps in a different chunk? Working on it with the C2 team. I may have another workaround as well.

  • WALK [Z] [X] [Y] Note: Z(-NORTH(2)/+SOUTH(0)) X(-WEST(1)/+EAST(3)) Y (+UP/-DOWN)
    Makes the Denizen walk. This is not for making the Denizen to specific coordinates. The values for X Y and Z will get added or subtracted from the Denizen's current location.
  • RETURN
    Can be used after initiating a WALK command. This will make the denizen return to its previous location.
  • RESPAWN [Location Bookmark]
    Despawns the Denizen and respawns it to a bookmarked location.

Note: There is something funny going on with NPCs spawning to a location you are very near to. You sometimes have to back away before they show up. This seems to be an issue with Craftbukkit and/or Minecraft Server.

Vault Commands

The commands below require Vault and a valid permissions and economy system. Though Vault is not required to use Denizen, the commands below DO require Vault and its dependencies to be installed. Remember: Vault is not an economy or permissions system, merely a hook to help Denizen connect to your favorite systems!

  • WEATHER [Sunny|Stormy|Precipitating]
    Sets the weather for the world.
  • PERMISS [permission.node.to.add]
    Gives to the player interacting the specified permission node for the current world.
  • REFUSE [permission.node.to.take]
    Takes from the player interacting the specified permission node for the current world.

World Interaction Commands

These commands do something physical to the world or player.

  • SWITCH [Block Bookmark]
    If a lever is found at the block location, it will be switched ON or OFF.
  • SPAWN [ENTITY_TYPE] [AMOUNT] (Location Bookmark)
    Spawns a specified amount of entities. If the location bookmark is missing, they will spawn near the Denizen.
  • TELEPORT [Denizen Name] OR [BOOKMARK:BookmarkName] OR ['BOOKMARK:Denizen Name:BookmarkName']
    Teleports the player interacting to a bookmark or Denizen/
  • STRIKE
    Strikes the player with lightning.

Player Interaction Commands

  • GIVE [ITEM_NAME] (Quantity)
    Denizen will drop specified items.
  • TAKE [ITEM_NAME|MONEY] (Quantity)
    Takes specific item or money from the player.
  • CAST [POTION_TYPE] [Duration in seconds] [Amplifier]
    Gives the player interacting a potion effect. Note: Valid potion types are the same as the Alchemist's. Amplifier specifies 'level, strength, or duration', depending on the type of potion effect. Try 1-5 for most types.