Quest plugin - Triggers

Discussion in 'Spigot Plugin Development' started by MrDienns, May 4, 2017.

  1. Hi,

    I'm working on a custom questing plugin but I'm sort off stuck.

    I have a folder/database (JSON based) that contains a bunch of files that build up a quest. A quest can have a bunch of triggers and conditions to activate it. For example:

    Right clicking an NPC, while in a certain world, having a minimum level of x and have x amount of wood in your hand. That'd be a trigger to start a quest. The event would be right clicking an NPC and everything after it are just conditions.

    How would I go from an NPC click event into the quest and test its conditions? Downloading all (houndreds) quests and looping through all of them seems like a horrible idea. Any thoughts and tips would be helpfull

    Thanks
     
  2. Why don't you just give all the quests an id or a name. Then all you have to do is make some sort of map that gets loaded at startup.
     
  3. I have one. I have a very big list of all quests and their ID's. This however does not mean I have all of them loaded. To determine wether a player wants to start a quest, I must load the full object from the database and check all of the triggers and conditions it has.

    The only thing I can imagine doing right now (which is extremely inefficiƫnt, thus this thread) would be this (pseudo):

    Code (Text):
    onNPCClickEvent
        foreach quest in quests (from external database)
        if quest trigger equals NPCClickEvent
            if quest NPC equals event NPC
                foreach condition in conditions
                    if condition is false > error message
     
  4. WAS

    WAS

    As you said it yourself they are triggers. These should be loaded into memory to refer to dynamically. Create a Map with key pointers. You are right in not touching the files. All pointers that identify quests should be in memory on load, this just inherently speeds things up.

    Once you have pointers and triggers you can call quest data from files when actually needed
     
    • Like Like x 1
  5. Makes some sense. I'll try it out. Thanks for the tip
     
    • Like Like x 1
  6. WAS

    WAS

    As a very basic example assume you have a bunch of custom items with custom names and short data for textures. You could load all their names formatted with ChatColor as the keys with the short value as thr value. You can easily than check if a item occuring in game is a custom item (and ensure it with its short value and any other means) and than load your custom item data you need such as its cool particle effects, potion effects, etc
     
  7. Why not just use an Enum class with your quests and create methods for each quest? ...or what about something like an API for all of them here you include variables like world, player, exp points, iteminhand, etc
     
  8. Managing the quest isn't the issue. The fact that I click on a random NPC and that I somehow have to activate some quest is the issue.

    Let's say I have over 500 quests. I click on an NPC because I want to start a single quest. This NPC is in no way affiliated with the quest (not yet). The issue is that I would have to loop over every single quest to determine if there's any quest to activate from that NPC. I'll most likely solve it by injecting some data into the quest NPC, like quest ID's so I can simply loop over only those instead.
     
  9. I can't think of a better solution for you, to be honest.
     
  10. Choco

    Moderator

    Any reason you don't have a Quest object? As people mentioned before, you should load all quests into memory onEnable(), and you would then be able to easily manage them without having to worry a whole lot about performance. For things such as triggers, a good call would be to have some sort of Trigger enum (or abstract class to allow for a more flexible trigger system) and a few constants to represent the triggers you create. Essentially what I'm envisioning is something sort of like this:
    Code (Java):
    Quest quest = questManager.getQuest()
        .withTrigger(Trigger.CLICK_NPC)
        .withConditionalTrigger(Trigger.EXPERIENCE_RANGE, player.getExp() >= 0 && player.getExp() <= 10)
        .withConditionalTrigger(Trigger.HOLD_MATERIAL, player.getInventory().contains(Material.LOG, 10));
    Something similar. Idk
     
    • Agree Agree x 1
  11. As suggested make an enum of quests, and a separate quest listener class, your quests can be loaded into the enum at startup all 500 or 5000 of them.

    If you want to make an npc for a quest you'll need the type of npc and maybe their location. Those should be fields in the enum.

    If a particular quest does Not require a npc make it null.

    Same with the quest items, if it requires it load it in as item 1 with qty 1, if no item required set it to null and 0.

    Then In your listener you can loop through the quests in the most efficient way.

    If the quest requires clicking an npc of a specific type as you're going through the loaded in memory list of quests you can skip any npc fields that are null, and any of the wrong type which will greatly speed up your searching.

    Or put the quests into different types.
    NPC_INTERACTION, ENTERING_REGION, CRAFTING_ITEM, KILLING_ENTITY, etc

    These would allow you to set up the quests based on the action required to start them. All the click_npc would obviously be started in the interact event, and your code wouldn't even need to iterate through the other quest types.


    Sent from my iPhone using Tapatalk