Skip to content

Conditions

Now that you know how to give the player tasks using objectives, it is time to learn about conditions. These are another essential building blog of quests as they allow you to create different outcomes based on the player's actions. This works by attaching conditions to any conversation, event or objective. For example, you could have a conversation option that is only available if the player has a certain item in their inventory.

In this tutorial, you will learn how to create and use conditions!

Download Tutorial Setup

⚠ Don't do this if you already have the configs of the previous tutorial step. ⚠

Enter this command in the chat to download the pre-made setup for this tutorial:

/bq download BetonQuest/Quest-Tutorials refs/tags/v2.1.3 QuestPackages /Basics/Conditions/1-DirectoryStructure /tutorialQuest
You can now find all files needed for this tutorial in this location: "YOUR-SERVER-LOCATION/plugins/BetonQuest/QuestPackages/tutorialQuest"

1. Creating the folder structure for your first condition🔗

Add a new file to your "tutorialQuest" QuestPackage named "conditions.yml". The file structure should look like this now:

  • tutorialQuest
    • package.yml
    • events.yml
    • objectives.yml
    • conditions.yml
    • conversations
      • jack.yml
      • blacksmith.yml

We now have our file structure in place and can begin creating conditions!

2. Defining your first condition🔗

Now that we've created it, open "conditions.yml" and add the following content:

conditions.yml
1
2
conditions: # (1)!
  isDay: "time 6-18"
  1. All conditions must be defined in a section called conditions.

So, what are we looking at here?

  • isDay is the name of a condition. You can name it whatever you want to. It is recommended to name it after what it should check.
  • The Condition Instruction:
    • time: The first value in the instruction is always the condition type.
    • 6-18: This is an option of the time condition. It defines the timespan in which the condition is true. In this case, it is true from 6am to 6pm.

Now we've created your first condition that checks if a specific game time is set on the server. Save the file and continue with the next step!

3. Checking the condition in-game🔗

You can check conditions if they are true or false in-game.

It is very important to save all files everytime you test something! Type /bq reload on your server after saving.

Running a command is the simplest way to accomplish this:

Enter /bq condition NAME tutorialQuest.isDay on the server. This command will show you the result "false" or "true" depending on what time it is. During day time, the result will show true. In the nighttime it will be false.

Tip

Change the world time using the /time set day and /time set night commands. This will allow you to test your conditions in-game.

Command Part Meaning
/bq conditions Tells BetonQuest that some conditions should be checked if true or false.
NAME A player's name.
tutorialQuest The name of a QuestPackage. This is required because you could have events with the same name in different packages.
isDay The name of the condition to check. Don't forget to separate it with a dot from the package tutorialQuest.isDay.
Is the example not working?

Get the correct configs by running the following command.

⚠ This will overwrite any changes (including NPC ID's and locations) you have made to the example.

Linking NPCs to conversations is explained in the basics tutorial.

/bq download BetonQuest/Quest-Tutorials refs/tags/v2.1.3 QuestPackages /Basics/Conditions/2-FirstCondition /tutorialQuest overwrite

4. Integrating conditions into objectives🔗

Conditions can be added to objectives to limit the player's ability to progress and complete the objective. The objective will only progress when the condition is "true". In this case, we want to achieve that the player is only able to make progress when he's fishing at night. Let's add the condition isDay to the objective:

objectives.yml
objectives:
  fishingObj: "fish COD 3 hookLocation:100;63;100;world range:20 events:caughtAllFish conditions:!isDay"
We can see multiple things here:

  • conditions: - this option works on all objectives. Multiple conditions can be added if seperated by comma (conditions:con1,con2,con3).

  • The exclamation mark (!) in front of a condition inverts it. That means that a condition that is "true" will be received as "false" and the other way around. This must be set per condition if multiple conditions are in use (conditions:!con1,!con2,!con3).

  • Remember that our condition is configured to check if it is daytime (6-18). We need to invert the isDay condition because we want to make progress when it is night. Now the condition will return "true" if it's nighttime (23-2).

Make these changes, reload and test!

5. Integrating conditions into conversations🔗

Conditions can be used in conversations to control the available player_options. This is a powerful feature for creating complex conversations with multiple answers.

For example, the current dialog with the NPC Jack can be repeated infinitely. The player will always obtain more food. This is not what we want.

5.1. Making Jack only give food once🔗

To solve this problem we need to create an alternative path for the conversation. It must only be shown if the player has obtained the food. To do so, we will create an event to give the player a "tag" and add a condition to the conversation.

We will start with a tag condition:

conditions.yml
conditions:
  isNight: "time 6-18"
  hasReceivedFood: "tag foodReceived"

What is a tag?

A tag is a label that can be added to a player. It is a simple way to store permanent information about the player. Later on, you will learn more about them in another tutorial.

This tag condition is "true" if the player has the defined tag. Let's break it down:

  • hasRecivedFood: The name of the condition. You can name it whatever you want to. It is recommended to name it after what it should check.
  • The Condition Instruction:
    • tag: The first value in the instruction is always the condition type.
    • foodReceived: This is the name of the tag that the player must have.

Tags can be assigned to a player using events. Let's create an event that gives the player the tag:

events.yml
events:
  # Other events not shown
  addFoodReceivedTag: "tag add foodReceived"

Tip

If you don't understand why we created the event in the events section, you should go back to the events tutorial and read carefully!

We are now ready for the next step: Adding the condition and event to the conversation.

Open up your jack.yml file in the conversations folder and add the event to give the tag to a player and the condition to not repeat the specified part of the conversation.

jack.yml
conversations:
  Jack:
    quester: "Jack"
    first: "alreadyReceivedFood,firstGreeting" #(1)!

    NPC_options:
      firstGreeting: #(2)!
        text: "Hello and welcome to my town traveler! Nice to see you. Where are you from?"
        pointer: "whereYouFrom"
      # Other NPC_options not shown
      foodAnswer:
        text: "You're welcome! Take it... &7*gives food*"
        events: "giveFoodToPlayer,addFoodReceivedTag" #(3)!
        pointer: "thankYou"
        conditions: "!hasReceivedFood"
      alreadyReceivedFood:
        text: "Hey %player%! I think I already gave you your welcome food..."
        conditions: "hasReceivedFood"  #(4)!
        pointer: "saySorry"
      # Other NPC_options not shown

    player_options:
      # Other player_options not shown
      saySorry:
        text: "You are right. Thanks again!"
        pointer: "townTour"
      # Other player_options not shown
  1. This option checks all possible starting points for the conversation from left to right. The first option that the player matches the conditions for will be used. The conditions can be found down in the NPC_options. If the player matches none of the conditions, the conversation will not start.

    In this case, if the player meets the condition hasRecivedFood, they will start at the alreadyReceivedFood option.
  2. This option will be shown if no other option matches the conditions. This is because this option has no conditions and is the last option in the first list.
  3. These events will be executed if the player chooses the foodAnswer option. It will give the player the food and the tag foodReceived.
  4. This condition ensures that the player will only see the alreadyFoodReceived option if he has the tag foodReceived.

As you can see, we also added new options to it. Now the NPC will say that you already received the food and won't give you more!

Note about testing

If you want to test this conversation again, you need to remove the tag from the player. You can do this by using the /bq tag remove <player> <tag> command.

Is the example not working?

Get the correct configs by running the following command.

⚠ This will overwrite any changes (including NPC ID's and locations) you have made to the example.

Linking NPCs to conversations is explained in the basics tutorial.

/bq download BetonQuest/Quest-Tutorials refs/tags/v2.1.3 QuestPackages /Basics/Conditions/3-ConditionsInConversations /tutorialQuest overwrite

5.2. Limiting the town tour as well🔗

The same problem exists with the town tour. The player can do it over and over again. Try to fix it on your own using the method you just learned.

Solution

Get the correct configs by running the following command.
⚠ This will overwrite any changes (including NPC ID's and locations) you have made to the example.
Linking NPCs to conversations is explained in the basics tutorial.

/bq download BetonQuest/Quest-Tutorials refs/tags/v2.1.3 QuestPackages /Basics/Conditions/4-JackCompleted /tutorialQuest overwrite

5.3. Making the Blacksmith only trade the armor once🔗

The blacksmith conversation suffers from a similar problem. There is no way to get the reward, the conversation will start over and over again. Let's fix that!

5.3.1 Preparing the conversation🔗

Let's add some dialog for when the player has accepted the quest but not completed it yet:

blacksmith.yml
conversations:
  Blacksmith:
    quester: "Blacksmith"
    first: "alreadyStarted,firstGreeting"
    NPC_options:
      firstGreeting:
        # Other player_options not shown
      alreadyStarted:
        text: "Come back to me if you caught all the fish!"
        conditions: "hasStartedFishing"
    player_options:
      # Other player_options not shown
      accept:
        text: "Sure! I could use a new armour."
        event: "startFishingObj,addStartedFishingTag"
        pointer: "goodLuck"
      # Other player_options not shown

As usual, we need to add the condition to the "conditions.yml". We will also add a condition to check if the player has the required amount of cod in their inventory. We can do so with an item condition.

conditions.yml
conditions:
  isNight: "time 6-18"
  hasRecivedFood: "tag foodReceived"
  hasDoneTour: "tag tourDone"
  hasStartedFishing: "tag startedFishing"
  hasFishInInv: "item cod:3"
  hasDoneQuest: "tag questDone"
Additionally, we must add the new events as well. Those remove three cod from the player's inventory and add a tag for completing the quest.

events.yml
events:
  # Other events not shown
  addStartedFishingTag: "tag add startedFishing"
  addQuestDoneTag: "tag add questDone"
  takeFishFromPlayer: "take cod:3"  

Now let's use all these new elements to finish up the conversation.

Note that we check the hasFishInInv twice in the dialog. This prevents players from cheating by dropping the items once the starting option is determined. If they do so, the conversation will simply end without giving out any items.

blacksmith.yml
conversations:
  Blacksmith:
    quester: "Blacksmith"
    first: "questDone,caughtAllFish,alreadyStarted,firstGreeting"
    NPC_options:
      firstGreeting:
        # Other player_options not shown
      caughtAllFish:
        text: "Oh let me see! Amazing.. Can I have them?"
        pointer: "agree"
        conditions: "hasFishInInv"
      giveFishToBlacksmith:
        text: "Thank you very much and here is the promised armour!"
        pointer: "seeYouSoon"
        events: "takeFishFromPlayer,addQuestDoneTag"
        conditions: "hasFishInInv" #(1)!
      goodbye:
        text: "It was nice to meet you! I hope we will see us soon again. Goodbye"
      questDone: 
        text: "Nice to see you again %player%!" #(2)!
        conditions: "hasDoneQuest"
    player_options:
      # Other player_options not shown
      deny:
        text: "I dont have time right now."
        pointer: "maybeLater"
      agree:
        text: "Of course! Take em."
        pointer: "giveFishToBlacksmith"
      seeYouSoon:
        text: "That was a pleasure! See you soon..."
        pointer: "goodbye"
  1. This is the cheat protection we talked about earlier. If the player drops the items, the conversation will end.
  2. Some dialog for when the player has already completed the quest.

5.3.2 Handing out the armor🔗

Now add an event to reward the player on your own. Tip: You must use the give event to hand out items that are defined in the items section of your "package.yml" file.

SPOILER: Solution
package.yml
items:
  # Other items not shown
  ironHelmet: "IRON_HELMET"
  ironChestplate: "IRON_CHESTPLATE"
  ironLeggings: "IRON_LEGGINGS"
  ironBoots: "IRON_BOOTS"
events.yml
events:
  # Other events not shown
  rewardPlayer: "give ironBoots,ironChestplate,ironLeggings,ironHelmet"
blacksmith.yml
giveFishToBlacksmith:
  text: "Thank you very much and here is the promised armour!"
  pointer: "seeYouSoon"
  events: "takeFishFromPlayer,addQuestDoneTag,rewardPlayer"
  conditions: "hasFishInInv"
Is the example not working?

Get the correct configs by running the following command.

⚠ This will overwrite any changes (including NPC ID's and locations) you have made to the example.

Linking NPCs to conversations is explained in the basics tutorial.

/bq download BetonQuest/Quest-Tutorials refs/tags/v2.1.3 QuestPackages /Basics/Conditions/5-FullExample /tutorialQuest overwrite

6. Conditions in Events🔗

In this section, you will learn how to use conditions in events. This is handy when you want to block an event from triggering because some conditions for the players are not met.

We will temporarily create a tag condition called receiveNotify in the "conditions.yml" like so:

conditions.yml
conditions:
  receiveNotify: "tag receiveNotify"

We will now create an event to test our recently created condition. For testing purposes, we will use a notify event:

events.yml
events:
  notifyPlayer: "notify You completed the quest! io:Title sound:firework_rocket conditions:receiveNotify"

Let's break it down:

  • notifyPlayer: The name of the event.
  • notify: The event type - notify events are used to send notifications to the player.
  • You completed the quest!: The message of the notification.
  • io:Title: The message will be displayed as a title.
  • sound:firework_rocket: The message will be accompanied by a firework sound.
  • conditions:receiveNotify: The event will only trigger if the condition receiveNotify is met. This argument works for all events.

You can see that the notify event uses a condition. This means the player is only able to receive the notification if they have the tag. Save, reload and execute the command in the game to test how it works!

You can test it with this BetonQuest command:

/bq event PLAYERNAME tutorialQuest.notifyPlayer
Nothing should happen because the player doesn't have the receiveNotify tag.

Now run the following command and then try the command from above again.

/bq tag PLAYERNAME add tutorialQuest.receiveNotify
You should now see the notification on your screen!

You can also manually delete a tag using

/bq tag PLAYERNAME del tutorialQuest.receiveNotify`.
This is very helpful when you are testing your quest and want to reset the player's progress.

If you like, you could add the event to your blacksmith conversation. Make sure to remove the condition from the event's instruction. There is no use for it in this quest, but the notify event is a good example to show how to use conditions in events.

Summary🔗

You've learned what conditions are and how to they are used in objectives, conversations and events. More conditions can be found in the conditions list.