UE5 Quest System
This page is part of the documentaiton for my UE5 Quest System

Quest Objectives

UE5 Quest System Version: 2.0

    What are Objectives?

    Quest objectives are the specific tasks or goals that players must achieve to complete a quest. Each quest can contain multiple objectives, and each objective can be individually customized with its own settings, configurations, and definitions. This allows for a diverse range of challenges and requirements that players need to fulfill as part of their quest experience.

    How to add an objective to a quest

    Adding objectives to quests is handled through our quest data table.

    1. Open DT_Quests in the Blueprints/Variables/DataTables/ folder.
    2. From the list, select the quest you wish to add an objective to.
    3. Locate the QuestObjectives array, then click the new element button next to it.
    4. Expand the added element to expose all the objective related variables.

    This is where you will define the criteria for your objective. Not everything is required, at minimum you need to define an objective type, and based on its type will determine the TargetData you use. The next section on this page will outline each of these variables.

    Objective Type

    Objective Type - This is the type of objective, this controls how our objective works. Included you will find a handful of example objectives.

    To help you get started I've included a few of the most common quest objectives: Interact, Travel, Destroy, Turn In, and Custom. You'll find detailed descriptions of each objective type in the following sections of this page.

    Interact / Pickup Objective

    The interact objective type can be used if you want the player to interact with an actor, as in get close to it and press the interact input key binding. What happens when you interact can be controlled using the Quest Events through the objective's on objective complete event (see below).

    To use this objective type define your Tag in your TargetData. Remember the Tag is our Actor Tag that we also added to our actor in our level we want to interact with. You can also use the Count TargetData if you would like the player to interact with multiple actors (using the Require Unique Actors objective option), or the one actor multiple times (by default).

    When progress related to an actor is handled the quest system will attempt to tell the actor using the onObjectiveProgress event added through the BPI_Quest_ActorOptions. We talk a bit more about this in the Quest Actor chapter.

    This objective is completed by our AC_QuestSystem_Actor component, you can learn more about this component on the Quest Actor page.


    Timmy Dyno? What happened to the pickup objective from Version 1?

    For those curious about what happened to the Pickup objective type from the previous version... The key difference between this Pickup and Interact objective type was that pickup used the Count variable and Interact did not.

    In this version I decided to just combine the functionality into one, and take less assumption on how each is to be used. The act of interacting is an event which was already applied to both, and it really shouldn't matter if you want to interact with one thing or many, the Count was not a good enough reason to have separate objective types in this version since the underlying code would be the same, this redundancy is why Pickup was merged into Interact in this version. You can perform either with just the one now.

    Travel To Objective

    When we want the player to travel to an actor or an area we use the Travel To Target objective type. As soon as the player gets close enough to this target the objective will be completed.

    To use this objective type define your Tag in your TargetData. Remember the Tag is our Actor Tag that we also added to our actor in our level we want the player to travel to.

    This objective is completed by our AC_QuestSystem_Actor component, you can learn more about this component on the Quest Actor page.

    We can adjust the size of this range (sphere radius) to our target using the getSphereRadiusOverride interface function added through the BPI_Quest_ActorOptions blueprint interface. You can learn more about this blueprint interface, and what else it has to offer on the Quest Actors page.

    To help you with providing travel to targets when no actors are actually used I've included the Travel To Quest Helper. This quest helper gives you a visual location in the editor, but at runtime is completely empty. This actor can be tagged, and you can easily adjust and preview the range of the overlap detection. Check out the Quest Helpers chapter to learn more.

    Destroy Target Objective

    When we want the player to destroy a target we can use the Destroy Target objective type.

    To use this objective type define your Tag in your TargetData. Remember the Tag is our Actor Tag that we also added to our actor in our level we want the player to destroy. You can also use the Count TargetData if you would like the player to destroy multiple actors (using the Require Unique Actors objective option), or the one actor multiple times (by default).

    This objective is completed by the AC_QuestSystem_Actor component added to your objective target actor.


    Timmy Dyno ... I destroyed the actor when it took damage but I did not get credit for the objective, what gives?

    Timing is critical Timmy! You most likely did not give the actor a chance to run its own any damage event dispatcher which is what we are listening to. Pay attention to this next part, as this will most likely explain why this is happening for you.


    How the Destroy Target Objective Works ...

    In a basic setup, our actor component reacts to damage and destruction by connecting to the relevant events in your actor.

    When the AnyDamage event occurs, and you need to destroy the actor immediately, remember to allow the actor time to process its own internal "any damage" event. If you connect DestroyActor directly to the AnyDamage event, the actor won't have the opportunity to trigger its own internal event dispatcher, which is what the actor component is binding into.

    Instead of immediate destruction, use a brief SetLifespan or a slight delay (event a DelayUntilNextTick is good enough.). This way, the AnyDamage event can complete and trigger its internal processes, which will in turn complete the objective.

    Alternatively you can also manually call the crediting event before your destroy event to do it all without having to account for this timing issue. Learn how to manually call the crediting event below.


    If you don't actually apply damage, or can't depend on it ...

    You can manually get the AC_QuestSystem_Actor component and call the addKillCreditPlayer event on this component to award the player with credit. You will also have the option to award the credit right away through AwardNow?, as well as the option to AwardAll? players currently on the credit earned list. If you call addKillCreditPlayer and do not use AwardNow? you will need to call awardKillCreditPlayers when you are ready to award credit for destroying this actor.

    You can manually remove a player from the credit earned list through the removeKillCreditPlayer event on this component, and if you call the resetKillCreditPlayers this will remove all players currently on the earned credit list.

    Look inside the blueprint's event graph for some helpful usage tips related to some of the most common scenarios.


    If you don't actually destroy your target ...

    You can manually get the AC_QuestSystem_Actor component and call the awardKillCreditPlayers event on this component when you are ready to award your players.

    Turn In Item Objective

    The turn in quest objective type uses the Inventory related functions of our Connected Systems BPI to require the player to turn in specific items to our target actor.

    To use this objective type define your Tag in your TargetData. Remember the Tag is our Actor Tag that we also added to our actor in our level we want the player to turn the items into. We use RowName to define the ItemRowName of the item we want the player to turn in. You should use Count to define the number (or quantity) of the Item you want the player to turn in.

    When the player interacts with the actor defined by our Tag they will see a special quest window showing the required items. The Item Name, the Icon, and the quantity will be shown. This item specific data, as well as the player's current count of the item, is obtained through your inventory system through the getItemForQuest function added through the Connected Systems BPI.

    If the player has ALL required items they can turn them in to complete the objective(s). At this point the quest system will tell your side (also through the Connected Systems BPI) to remove the items through the removeItemForQuestObjective function. If your side confirms that the items have been removed (through returning true from this implemented function) the quest system will complete the associated objective.

    Each objective is limited to a single item, so if you want to require multiple items you will need to add an objective for each in the current version.

    Custom Objective

    The custom objective type can be used whenever you have a simple need that doesn't necessarily need its own objective type, and you want to manually progress it through calling the CompleteObjective event on the AC_QuestSystem_PlayerState component. For example our very first quest in the demo world with the button to open the main door, jumping on this button is what actually completes this objective. This is handled through this custom objective type.

    This type of objective type is also handy when you don't actually have an actor, perhaps you would like to complete an objective when the player progresses through a dialogue series with an npc. You would use this type of objective to handle something like that.

    Objective Title

    Objective Title - This is the Text for the objective. This text will be shown in the Quest Window as well as the Quest Tracker and Small Quest Alerts.

    Objective TargetData

    This is the data specific to our target, the keys are predetermined, and the value is what you provide for the keys needed by your objective. The keys below are included and you can see which are required, and examples of values for the Objective Types (outlined in next part of this page):

    Tag - The tag of the actor used for this objective.
    Count - The total number of this objective type needed to satisfy the objective.
    RowName - For quest objectives requiring a row name such as our Item Row Name used with the Item Turn In objective type.
    Custom - If you need to supply a custom variable which is accessible when you get the quest or objective data.

    Objective Options

    Like quests, each of our objectives also has its own set of options, here is a breakdown of each found in the ObjectiveOptions structure:

    Can Share Progress? - In multiplayer when this objective is completed, should the progress be shared with other players on the quest?
    Require Last To Complete? - Should the previous objective be completed before this one can be?
    Require Last To Show in UI? - Should the previous objective be completed before this one can be seen in the UI?
    Require Unique Actors? - If using the Count TargetData, should each actor be unique? Keep in mind this is only tracked in the session and does not keep track of unique actors between game restarts.
    Auto Rescan for Targets? - Should the quest system rescan for targets? This should be used sparingly, using it in excess can be expensive. You should check in your actors into the BP_QuestHelper_World when they spawn instead. View the World Quest Helper page in the docs for more information.
    No Indicator - When set to true the indicator will be hidden for this objective.
    Show Count as Percentage - If using the Count TargetData we can force any display of our count as a percentage instead of the default X / Y format by setting this value to true.
    Override Indicator Mesh - If you would like to override the default indicator mesh you can do so here. You should not be using this to set the indicator for every objective, instead make that kind of change inside the BP_Indicator.

    Objective Prerequisites

    You can also define quest prerequisites which are required before your objective can be completed. These are the same as our Quest Prerequisites so if you would like to learn more about those make sure to check out that chapter.

    Objective Complete Events

    When objectives are completed you have the option to initialize our Quest Events. One thing you will want to keep in mind for objectives is that Run on Reload? will only reoccur for completed objectives while the quest is still In Progress. If the quest is Ready to Turn In or Completed these will not run again.

    Forcing the Flow of Objectives

    The Require Last to Complete? Objective Option can be used to force the player to complete the objectives in the order you define, without them being able to jump ahead to complete objectives later in the quest. You can also optionally hide the unavailable objectives in the UI until the previous is completed using the Require Last to Show in UI? Objective option.

    Complete Objectives Manually

    The CompleteObjective event in the AC_QuestSystem_PlayerState is designed for manually setting a quest objective to a completed state. This event requires two inputs: QuestRowName and ObjectiveIndex. Here's how it works:

    QuestRowName - This is the identifier for the specific quest whose objective you want to complete. It should match the quest's row name in your quest data table.
    ObjectiveIndex - This is the index (or position) of the objective within the quest that you wish to mark as completed. Objective indexes start from 0, so the first objective would be index 0, the second would be index 1, and so on.

    This functionality is particularly useful in scenarios where objectives are tied to specific actions or triggers within the game world, such as pressing a button or interacting with a UI element, as illustrated in the demo world examples.

    See the Working in Blueprint section of this documentation for an outline of some more useful functions you might need to know how to do from blueprint.

    This documentation and asset version are new. If you encounter any bugs or if anything doesn't make sense, please let me know.