How to Make Race Missions

This page covers how to use the features of Quest and Mission Framework+ in Blueprints to make a race mission.

IIMPORTANT - PLEASE READ: This example is from a large game codebase. If you want a simpler version, see the demo content that comes with the plugin. The code used here is built for scalability and commercial release, which is why I'm showing it.

Setting up the data table:

  1. Create a struct with the variables you will need for your race, in my race quest I have these variables.

  1. Now, create a data table from this struct you just created and fill it out.

  1. We will use this data table in various places to set rewards, maximum ring count, time remaining, description, quest name, and delegates. Your data table may look different if you need other data points.

Setting up the manager:

Each quest should have a manager to handle its operations. Let's create one for race missions.

  1. Create a new folder in your content browser named "Manager". Ideally, this should be under a race quest folder.

  2. Right click anywhere in the context browser and click "Blueprint Class" then select "Actor".

  1. Once the new actor is made, name it something like "BP_RaceManager" and drag it into your level, you only need one of these in your level.

  2. Now open up this manager actor.

  3. In my game, races consist of two main parts: the rings that track progress and the timer that determines if the quest succeeds or fails. Both of these use quest delegates. Let's create two quest delegate bindings at the start of play so they can be called later. See screenshots in sections for when these are called.

Quest Delegates can be given any name you like, in my game I name them with acronyms like "CQD" for "Challenge Quest Delegate" but you can name them however you like, just make sure the name aligns with where you call them(explained later) and they are uniquely named.

I'm using an early version of the plugin, which is why it's called "Ultimate Quest Subsystem" and why some variable names are different, like Quest Name instead of Quest Delegate. Everything else should remain the same.

  1. With our delegates set up, we need to bind their callbacks to functions. I am using the create event node to remotely bind them to other custom events in my manager.

Binding the Timer Quest Delegate:

Input:

We bound a delegate at the beginning of play in our manager to start a timer. Here is the code

  1. Countdown Timer Functionality

    The start countdown timer is a simple function. It uses a data table to find the corresponding row by the current active quest name. I set the initial maximum time remaining from this data table. Then, I create a timer that counts down every second, reducing the time remaining. This time is stored as a quest progress named CQ_RaceTimer. I then check if CQ_RaceTimer is less than or equal to 0; if so, I cancel the quest.

Click to zoom in for node details

This is the cancel challenge function called when the timer reaches 0:

Here is the reset ring progress function called above:

Binding the Ring Spawn Delegate:

We also bound a delegate at the beginning of our manager's play to spawn rings. Now, we need to create the function

  1. This one is very simple function, it calls a multicast blueprint event dispatcher to the ring splines(next section), and spawns a widget that says "Quest Starting".

If you are wondering where the quest is set active and started, that is done on a quest giver. I will go over that in the end when we add the quest to our level.

Setting up the Rings:

In my example, I am placing the rings along a spline, so I will be demonstrating spline math. You don't have to use splines if you don't want to make spawning easier.

  1. Make two new actors, a BP_Ring and BP_RingSplineSpawner.

Setting up the Ring Spline Spawner:

  1. In your BP_RingSplineSpawner or your Ring Spawner, make a function that uses the node get actor of class of your manager and binds the delegate we called for spawning rings,

NOTE: This is not a quest delegate as we need it to multicast to all splines in the level.

  1. On the event dispatcher callback from the manager, we want to get the current active quest and compare it to an instance-editable string variable that is set in the level editor when we design our race missions later.

You don't need to worry about this editable string just yet; we name it later when we add it to our level.

  1. if the quest we want is active then we want to spawn the ring along the spline, here is my code for it.

First half of the logic:

Second Half of the logic:

Note: The maximum ring count will be set from the data table. We are also passing the quest name to our rings that we spawn so they can track progress.

Setting up the rings to track progress:

Since we already made this actor in step 1 of the Setting up the Ring Spline Spawner, we dont need to create it here.

  1. You will want to add a shape and a box collider to this actor to begin. I used a torus from blender and a hologram material to make this.

  1. Event Overlap Handling for Box Collider

    Upon event overlap of the box collider, execute this code. It checks if the quest name we passed to the spline spawner is active. If active, it increments the quest progress of the sub-quest that tracks ring progress. If the progress reaches the maximum amount from the data table, retrieve the quest manager and mark the quest completed through its complete function.

Click to zoom in

Here is the Get race challenge data pure function I am using for reference:

  1. For the most part, we are finished. We just need to set up the quest giver/activator and integrate it into our level.

Setting up the Quest Giver/Activator:

NOTE: I am using an actor for my quest giver since my quest givers don't need to move, but you can make them into characters that can follow you and such if needed.

  1. Make an actor or character that has a mesh and a box collider to trigger things.

  2. On your box collider overlap event, create a widget with accept, decline, and description UI elements added to it.

  1. To pass the Quest Name variable, which should be instance-editable, from your quest giver/activator to the quest acceptance widget, you can do this by making the quest name variable instance-editable and setting it to expose on spawn in your widget.

  1. In your widget blueprint, use these nodes on the accept button with the quest name you passed from your quest giver.

  2. Once you click "Accept," your quest will start, and the rings will spawn. We still need to add these actors to our level, so let's do that.

Adding everything to our level:

  1. Place the Quest Giver/Activator, the Quest Manager(only one manager per level), and the BP_RingSplineSpawner into your level where you want them.

  2. Go to each one and fill out their instance editable variables to align with the data table, for example the Quest name should align with the row in the data table.

My Race Giver details panel:

My BP_RingSplineSpawner Details panel:

My data table where this race data is defined:

My level where the giver and spline spawner are placed:

How to quickly make more races:

Now that we built our race mission to be scalable, we can quickly add more races to our game. Here's how to do that:

  1. Make a new data table entry for a new race, make sure you fill out its details to be unique from the others, and ensure its row name matches its quest name like the one above, "CQ_GroundRace_1".

  2. Add another quest giver and spline spawner to your level and assign them the new quest name found in the data table row.

  3. Thats it, the new quest should now work because we built this to be scalable.

Need support or have questions:

Join our discord and I will be happy to help you out with any questions or setting up different types of quests. https://discord.gg/GXZ7c74sTm

Last updated