HOW-TO: Create a new quest
Here’s how to create a generic monster hunter quest in the REDkit using mostly existing elements.
This tutorial will help you learn some of the basic aspects of quest creation.
It explain how to:
create notice boards - where the player can find the quest-giver’s notice,
create a NPC quest giver (known as reward_giver) and their dialogues
place an area where the monster will spawn once the player gets close
get the trophy after the monster is dead and collect the reward for it
Please take a look at the HOW-TO: Use quest nodes article since this tutorial will make use of these nodes during the quest creation process.
1. Create a quest file
Open the Editor and either load in a world or create a new one (HOW-TO: Create a new world).
Now open the Asset Browser (CTRL+A), go to the levels folder and find your world’s main folder. Right-click on the background in that folder and choose Create > Quest to add a new quest file.
1.1. Quest files
When you open an existing .quest file, they are represented in the Editor by quest graphs which consist of different quest nodes. Think of it as a web of interconnected dots which tell the game which action to trigger if something happens or certain conditions are met.
Main quest files for a world can define the game structure. They are used not only for quests, but also for placing in spawns, encounters, conditions and more. It's basically a complete graph of all the content of the world.
Both .quest and .questphase files can be opened and edited in Quest Editor. The main difference between the two is the fact that .quest is the parent file which may contain multiple .questphases within.
2. DLC Quests
You should aim at making standalone quests without modifying any existing vanilla game files.
To do this, create your own .reddlc file with a quest mounter, add your .w2quest reference and taintFact. The dlc will automatically start the next time the game starts/save is loaded.
Create a new dlc folder (in the Asset Browser, go to the
dlc
folder, right click “Create Directory here” and give it the name of your mod.Inside the folder, create a new .reddlc file (in the Asset Browser, right click in the empty space “Create” >”DLC definition”.
Give the DLC a name, and in the
mounters
list, click on theplus
icon to add a new mounter,Then on the
arrow
icon to select the mounter type. SelectCR4QuestDLCMounter
Fill in the
quest
variable with a path to your quest file created in the step aboveAdd a
taintfact
to mark savegames as modified by this quest
2.1. Add a Game Definition for testing (Optional)
Basic information about the role and setup of Game Definition files has been previously explained here:
Before we jump into graph editing, we should create a game definition file that will be used to start the game from the context where the quest is supposed to be started, so it’s easier to test it. You can create on using Context menu > Create > R4 game defintion.
Open the definition file and connect the files visible on the screen to their properties - select files in the Asset Browser and then add them in the appropriate slot of the Game Resource Editor (as explained here HOW-TO: Make a new world come alive | 1.1 Edit the .redgame file).
3. Quest graph and spawn points
Time to start building the quest graph which is a set of nodes indicating what / when / if something should happen and which conditions have to be met.
In the Asset Browser, go to your world’s Quest File and open it.
You should see the still empty Graph Editor.
First we need to create our main input and output nodes by right-clicking on the graph Editor and choosing Complexity management > Start/End.
Now let’s add a Teleport node (right-click Gameplay > Teleport) that will move the player to a desired spot. Where do we want to teleport the player once the quest starts? You choose that spot with a Spawn Point in the next steps.
First define where the player will be spawned when loading the game using our Game Definition file. Create a layer called start_level. Go to the Scene panel, right-click on the root and select Add layer in the context menu. In the Create Layer dialog, put in the name of the layer, and select Quest build Tag and Non-static (dynamic entities) as type. Press Create. The layer should be now visible. To add objects to a layer it needs to be active - activate a layer by double clicking on it.
Time to place in a Spawn Point where the player will be placed. With our new start_level layer active, now right click on the Editor’s main viewport and choose Gameplay > SpawnPoint > Add Spawn point.
Notice that a CEntity class component called spawnpoint0 has appeared in the layer.
If you cannot see a visual representation of the Spawn Point in the Editor’s, you should apply the following debug display settings in View > Settings > Editor options > Debug and make sure that the checkbox called Waypoints is toggled. More on that: HOW-TO: Change display settings.
Now a green object (the Spawn Point) should be visible in the Editor.Select the spawnpoint0 object - which recently appeared - in in the Scene Panel under the start_level layer. Head over to Properties tab. Here we currently need to only set the tags fields with, for this tutorial, player_sp. This will be often referenced later.
Go back to the Graph Editor and the Teleport node to set the locationTag as player_sp (the same value which you have specified earlier in your spawnpoint) and as it needs the actor’s tag that will be teleported to the location, set the actorsTag as PLAYER.
Check if your Game Definition file works following these steps Start the game from the editor | Start game from game definition.
4. Phase node for the quest
Let’s continue building our quest graph.
Open up the quest file of the level, and add a Phase node using Complexity Management > Phase. Phase nodes can contain other sub graphs of nodes so we can maintain our overall structure a little easier. The phase node we created will contain all our quests related to our world, so let’s name it simply Quests. Open the Quests node and you will see that you have an empty graph with an in and out socket pair.
Create a new phase node and name it for your quest. In this scenario we will go with QUEST - mh_fogling. Make sure to connect the input to the phase input pin like this.
Now open the QUEST - mh_fogling node and let’s start building the quest itself!
After following the multiple steps described below and building phases, this is how the end result should look like:
5. Setup phase
First, we need to decide how we want to the player to be exposed to the quest. There are a few ways in which this can happen:
Put a note on a noticeboard
Place an NPC who signals the players and asks them for help
Finding a clue
…and more.
Of course there’s even a small chance that the player will accidentally stumble upon our monster and kill it. That’s why we need to take that outcome into account as well (killing the main quest monster without picking up a notice or talking to any NPCs.)
In this tutorial we will allow the player to get the quest from either a notice board or from an NPC quest-giver.
We need to spawn the NPC who will take the role of our reward giver. For this we will need a Story phase setter node (Gameplay > Story phase setter). These nodes have spawnsets - we can specify the path to the community file and the phase which we want to initiate the spawn. You can read more about communities in other parts of this documentation.
To create a Community file we need to open our level folder in the Asset Browser and create a new community there by right-clicking and choosing Create > Community. Name the file mh_fogling_reward_giver.
Open the mh_fogling_reward_giver.w2comm file and you should see an empty row in the Spawnset tab. Right click on each square separator and click on add element to activate the gray sections of the record row. There are a lot of columns that can be specified, but right now we will only focus to fill out these ones:
Entity Template: the path of the NPC’s template we will use an already made asset from quests\generic_quests\no_mans_land\quest_files\mh108_fogling\characters\mh108_reward_giver.w2ent
Entity Spawn Tags: This tag is used to reference this entity from almost anywhere in our Editor, use something like mh_fogling_reward_giver.
Initializers (Entity Initializers): Give a value by right clicking and choose create object.
Story Phase Name - Since a community file can define multiple spawnset elements, we need to set phases where each spawnset element will use one phase. Later in our quest graph we can reference this phase so that only the elements that are using it will be spawned. We can type in a value like “Default”.
Time/Quantity/Respawn Delay/Respawn - Also be careful; We need to “Add Element” to the Time and not leave it as blank.
CCommunityInitializers element should be inserted in the cell. Now open it by double clicking and a dialog box will appear. Add an element to the initializers array field and search for CSpawnTreeInitializerGuardArea then choose it. Now the inserted fields can be ignored except the guardAreaTag. Here we will choose a tag for our guard area where the NPC will be contained.
In the main Editor window place a guard area where you want to place the reward giver NPC. Make sure that you give the tag that you specified in the above community file.
Story Phase Name: Here you can specify in which phase the NPC should spawn. We want to spawn him as soon as the player enters the world so we can choose Default.
Timetable Name: This step is optional. Timetables are good for specifying the NPCs daily routines, in which layer - in what times - in what category class and what action points are associated with our NPC. Timetables are not always needed. But for the sake of this tutorial, I show what can be done with this:
AP tags are good if you want to specify some job to the NPC like sitting around or hammering something until you start talk with it. (not needed for our quest.)
Spawn Point Tags: The tag reference to the Spawn point/Way point where the NPC will be placed exactly when the layer will load up.
mh_fogling_reward_giver_sp
Go ahead and place a spawn point inside the previously marked guard area with this tag.
Back to our quest graph, put the path of your newly created community file into the spawnset of the Story phase setter node, and select Default in to the phase field. Now if you set the quest field inside the game definition properties of your world and launch the world starting with that game definition (for more details search up the Game definition part of this documentation.) You should see the NPC spawned in.
Next let’s put in a notice board where the player can read what’s the note that the NPC left there. Put an additional Script node next to the Story phase setter node and connect the setter’s output into the new Script’s input like so:
In the functionName field search for AddErrandsToTheNoticeBoard and select it.
boardTag: tag reference to the notice board.
errandStringKey: the localization string key for the contents of the notice. Basically the id of the text that’s displayed when you open the notice to read it.
newQuestFact: Facts are used in a Database called FactDB. All variables (called facts) can be found and be used globally for conditions, checks, etc.
addedItemName: The item that’s getting into the player’s inventory when he selects the contract from the board.
Some of the values are from already made assets for the sake of this tutorial being simple.
Again, Fire up the asset browser and search for notice_board_template. Add a Non_static + quest tagged layer into the scene panel and put this template into that layer. You can place this board wherever you want.
Go ahead and play the definition again, you should be able to use the board and see the contract of the quest on it.
Like in most of the quest the reward giver is usually highlighted on the map so the player can easily recognise it among the other NPCs. These highlights are called Mappin-s. For this we’re going to use another Script called EnableDynamicMappin.
Script arguments:
tag: the reference tag of the thing or NPC which should be highlighted.
type: what type of highlight should be used. (there are a lot of types, we’re going to use the EDM_QuestAvailable enum, which is the exclamation mark that is being used for the purpose to highlight quest NPCs.)
There are other scripts like EnableGlossaryImageOrverrideQuest which can update the player’s Glossary record for a certain monster. Monster hunter quests tend to use a two step reveal for the special monsters where at the start of the quest only a dark figure will appear with little info about the monster and then after the player gets the trophy the glossary will unlock and reveal the full description and image of that monster. In this example we are only at the start of the quest so now we can only get a blurry image for the wanted monster:
That will be enough for the setup phase. Make sure to connect the output socket of the last node to the ‘Out’ output of our phase, then step out of the phase by double clicking on the background.
QUEST mh_fogling / Contract phase:
In our new contract phase we will be focusing on the ways how the quest can start. This can be done by taking the job notice from the board or by meeting the quest giver NPC.
Quest progression is done by using Journal - quest nodes, where each node is referencing an entry of the overall quest. Quests are made out of entries and entries can be specified into different types like (Description, Investigation and Contract entries). For better understanding of these groups our quest entry structure is the following:
Quest - Hunt: Fogling:
Descriptions:
Start Noticeboard
Start Peat Worker
Fogling
End Short
End Long
Investigation:
Investigate strange fog
Investigate killings in the fog
Find ancient fogling’s lair, beware…
Explore fogling’s lair
Use Eye of Nephalem to dispel the illusion.
Contract:
Talk with peat digger
Kill the ancient fogling
Get ancient fogling’s trophy
Collect reward for the ancient fogling
Check Burrows village noticeboard
Return in a week to get bigger reward
Collect your full reward from quest giver..
So the quest nodes can be used to Activate, Deactivate, Succeed or fail a quest entry at certain conditions and points in our graph to progress our quest state.
Now that we know this let’s handle the case when the player gets the notice from the board. Put a pause node to setup a condition from which the signal can only continue if the specified condition(s) are met: (Flow control > Pause )
This node takes an array of conditions as arguments so you can specify more than one condition. Right now we only want to check if the fact mh108_job_taken flag is equal to one meaning our player have taken the contract from the board so insert a new CQuestFactsDBCondition element into this array.
The signal comes through because the player took the contract from the notice board let’s put a (Journal > Quest) node.
questEntry: The entry that we will modify with our node (activate / deactivate / success / fail)
showInfoOnScreen: Shows on hud that the quest was updated.
track: If the quest updates then it will set it as the tracked quest for the player.
Set the mappin to highlight the NPC and save the game with an autosave (checkpoint).
Now we can define what happens if the player decides to meet with the quest giver after taking the contract from the board. For that, create a phase node and step inside it:
QUEST mh_fogling / Contract phase / QuestGiver phase:
Notice that there’s a quest entry named ‘Talk with peat digger’ so that the quest can tell the player to go talk to the NPC. We can do this by activating it with a quest node like so:
The player approaches the NPC for a chat. For that we’ll use an interaction node. (Scenes > Interaction Dialog). Using this node we can add a scene from our asset browser which will be played with the specified actorTags when the player talks to the NPC. This tutorial uses this specific scene quests\generic_quests\no_mans_land\quest_files\mh108_fogling\scenes\mh108_reward.w2scene
But you can choose whatever scene you want.
We want to loop the conversation so it can be repeated, this can be done by the following condition within a pause node:
If the player is finished talking with our guy, we can go ahead and close this entry of the quest saying (‘Talk with peat digger’ entry succeeded)
Let’s say that our fellow player is unlucky enough to stumble into the monster without even talking to the NPC beforehand. For that we’re going to use a pause CQuestActorCondition with a checkType of W3QuestCond_IsTargetOf condition where the monster targets the player.
In this case the entry of talking with the NPC will fail like so:
Jumping back to our QUEST mh_fogling / Contract phase:
So we handled the case where the player visits the notice board and then the quest giver. Now we only need to handle what happens if the player only approaches the quest giver. For that we don’t have to do anything new that the previously mentioned methods:
We setup a simple interaction dialog (in this example in a phase node)
then enable a dynamic mappin
save the game
Finally we can modify a fact for the factDB so we can note that the player took the job. This can be done by using (Game systems control > FactsDB Change) We the arguments of the factID what we want to modify, and the new value, which now will be 1.
Now after that’s done, here is the complete Contract phase:
QUEST mh_fogling / Combat phase:
In this phase we will specify how the quest spawns the monster that needs to be hunted, what happens in combat and after combat (like taking the trophy of the monster etc.)
Spawning of course can be done the same way we spawned our quest giver, in an instant after the level is loaded at the start of playing our game definition. But let’s make our monster spawn a little more interesting with a simple trigger. Let’s say that we only want to spawn down the monster when the player gets inside a trigger area to make it feel like a more sudden encounter. In our world scene viewport let’s place in a trigger area using context menu > Gameplay > Area > Trigger Area. Scale it a little bigger, and give a reference tag to it.
As we previously needed a spawnpoint for the player, this time we need another spawnpoint for the monster. So go ahead and use Gameplay > SpawnPoint > Add Spawnpoint in the viewport and place it somewhere inside the trigger area. It’s important to give this spawnpoint a tag that can be later referenced in the quest graph. You can name the tag however you want, the only important thing to remember is that the tag value needs to be the same inside the community that will later spawn the monster with a story phase setter node. We’ll talk about this in a moment. So go ahead and give a tag to the spawnpoint properties: mh108_ancient_fogling_wp.
Getting back to the quest graph, place a pause condition with a CQuestInsideTriggerCondition using this trigger’s tag as argument. This condition node will only let the signal pass if the player gets inside the trigger area.
Now we can use a previously described Story phase setter with a community file for the monster. We’re going to use an already defined community located at quests\generic_quests\no_mans_land\quest_files\mh108_fogling\spawnsets\mh108_ancient_fogling.w2comm. (You can also use your very own custom community if you know what you’re doing. ) When opening up the community Editor, you can see the tag reference inside it that matches the spawnpoint tag we defined earlier:
Spawn Point Tags: This is refering to the spawnpoint (using it’s tag reference) where the entity should be spawned at.
Entity Spawn Tags: This is the tag value which the entity will be marked with once it’s spawned, so that later after the spawn we can reference it from the quest graph.
Save the community once you finished editing it, and paste it’s reference into a story phase setter like so:
Since the community already had a phase defined we can use that in the phase field. (But you can edit the community file with some other phase if you’d like to.)
After the monster was spawned we need to make sure that it will be hostile as well to the player. This can be done with a script right? Yes, indeed but be careful here. Spawning an NPC is not done instantaneously all the time. We need to make sure that the spawn has finished entirely. For that we can check it’s presence; We can use a presence condition like so:
This also references the monster by a tag reference. This reference was also defined with the community’s Entity Spawn Tag.
Assign attitude to a hostile group (monsters):
call AssignNPCGroupAttitudeQuest script.
Another way to do this is to call SetAttitudeTowardsNPC script
At this point the player will be attacked by the monster.
Given that the player killed the monster we can setup a condition that will check if that’s done
Put a FactDB change that the fogling was killed (mh108_fogling_died = 1)
For the is killed condition we can use a CQuestFightCondition:
Now that the monster is dead it will Drop it’s loot specified in the inventory tab of it’s entity template. Make sure that you generated navmesh under the area where the monster spawns. If there’s no valid navmesh under the monster when it dies it won’t drop down its loot therefore the player cannot get the trophy.
We can make a pause condition whether the player looted the trophy out already:
After that we can play the scene where Geralt decapitates the monster’s head, for this we need a script that sets up the actors positions for the scene:
Then we can play the scene of beheading:
Then call another script called ProcessMonsterHuntTrophyQuest which is will move the looted trophy item to the horse’s inventory thus making the trophy appear on the horse saddle
, and finally fade out from the scene.
QUEST mh_fogling / Combat Journal phase:
In here we will make a few checks related to combat and passing them will make the quest progress further. Basically we will use the same fogling_is_killed and player_has_trophy checks what we used previously at combat node, but this time these checks are only for quest progression.
QUEST mh_fogling / Collect Reward phase:
The only thing whats left is to handle the part when the player already took care of the monster, has the trophy and only need to get back to the quest giver to say that the job is done.
Progress the quest by notifying the player to collect the reward for the monster.
As you might have guessed, we need an interaction dialog but this time the scene has a new dialog option (hopefully) to get the reward.
using this scene: quests\generic_quests\no_mans_land\quest_files\mh108_fogling\scenes\mh108_reward.w2scene
To get the reward dialog option, the player needs the trophy at hand!
You might be wondering where does the dialog check whether the player has the trophy or not? The answer is that dialogs also have graphs with conditions like this. Open the interaction dialog scene Editor by double clicking on the dialog node. Notice that next to the Timeline tab there is a Graph tab, let’s select that.
Notice the choice node (mh108_choice) with the text “I’m here to collect the reward.” We can see that the signal goes from that socket and gets put into a condition that checks if a fact is true or not. This is the exact condition needed to make the reward collect option available to our NPC.
Back to our quest graph’s interaction dialog: Notice that the interaction dialog has a Reward output socket. This can be used to attach to a reward node that will reference to the exact reward that was defined for our quest. Go ahead and create a Gameplay > Reward node with the reward name of mh108_final_reward and the targetEntityTag of PLAYER.
Finally, we can put an end to this quest by using a journal quest node and connect the signal to its success socket. Go ahead and choose the root Generic/NML Hunt: Fogling/ quest entry so that the quest itself will be marked as succeeded.
Additionally we can put a FactsDB Change (mh108_done = 1) that the quest is done and save the game with a checkpoint node. After all that we can put the signal to the ‘Out’ socket.
Now the entire phase in one picture should look like this:
Done! Now we have a functional quest in our hands. There is a lot more you can still do to it like investigating clues, place illusion walls that would hide the monster's lair, unlock the monster’s true identity by updating the glossary record of it, etc.. This very basic quest is based on an existing monster hunting quest located in the main quest file of the game.
______________________________________
The Witcher 3: Wild Hunt Complete Edition © 2024 CD PROJEKT S.A. Published by CD PROJEKT S.A. Developed by CD PROJEKT RED. CD PROJEKT®, The Witcher®, REDengine® are registered trademarks of CD PROJEKT Capital Group. All rights reserved. The Witcher game is set in the universe created by Andrzej Sapkowski in his series of books. All rights reserved.