Build a quest template with instances
We're going to use a helpful tool known as instancing within the Hammer Editor. Instancing allows your main map to reference other maps and includes them in the build. We'll be making a "quest instance," which will be the template for every other quest we add later. Once we have our first instance, we can quickly duplicate it, place it in the map, and tweak its settings for each new quest. We can use an instance many times and change properties to make each one unique in order to save a lot of time during development. These instances will control the gameplay and logic of our RPG because they will contain the dialogue and character actions in the game. Unfortunately, Episode Two doesn't fully support instances, so we have to convert them into the level before compiling (which we'll cover when we're ready to compile at the end of this tutorial).
In order to set up our quest instance, we're going to need a new map file. Within Hammer, go to File, New to create a new map, and then save the map as "quest_instance" in a folder named "instances" within the same location as your main map.
Figure 4 shows how our quest_instance should look after we add all the necessary entities. We'll cover those necessary entities next.
Figure 4: Our basic quest instance template.
It's best to place your entities as close to the origin coordinates (0,0,0) as possible. We also want to have them sitting on top of the X/Y axis because when the instance is imported into the main map it will be oriented around the func_instance entity, which means you might lose sight of entities under the world if they are too low. You can check the location of your entities by using the top and side viewports to determine where they are. If needed, use the Selection Tool to place them above the X/Y axis. Our instance also gives all the entities inside it a prefix of our choice. We'll leave the triggers until the end of placing all the entities and leave some values out until later, so don't worry if it looks like we missed something.
We're going to need all of the entities mentioned in the list in Figure 3. Let's start by placing a NPC. With the Entity Tool selected, find npc_citizen on the drop-down list and place it at the origin coordinates. This will be our quest giver. Hit Alt + Enter to open his properties and make his name "giver." Also change Prevent picking up weapons? to Yes. Hit Apply and then go into his Flags panel and check Not Commandable, or else the quest giver will follow your player around the map. We'll also want to enable Don't drop weapons and Ignore player push (don't give way to player).
Next we're going to need a trigger that tells us when the player has approached our quest giver. Create a brush that is 64 units tall, 32 units wide, and 4 units thick, and then place it just in front of our NPC. We'll change its texture to "nodraw" so that it doesn't get rendered in the game. To change the texture, just select the brush, switch to the Toggle texture application tool, click the Browse button, filter for nodraw, double-click the nodraw texture, and click Apply. Then tie the trigger to an entity by pressing Ctrl + T and selecting func_button from the class list. Let's name it "trigger_start" and change the speed to 0. Hit Apply to save the changes we've just made.
Next, add a sprite that will alert the player that the NPC has a quest. Place an env_sprite entity above your NPC's head and open up the Object Properties window by hitting Alt + Enter. Name it "Sprite." We're also going to need to change the render mode so that the sprite renders properly in the game. Within the Object Properties window, locate the Render Mode option box and select World Space Glow from the drop-down menu. You can change the sprite image in this menu if you have one that you want to add to your game, but for now the standard sprite will do. Also, make sure that Start on is checked in the Flags tab.
Now we're going to add some dialogue. Find logic_choreographed_scene in the entity list and place it next to our NPC. We're going to need at least two of these for each quest, one for the start dialogue and one for the end dialogue, so copy and paste a second one above the first. Name one scene_start and the other scene_end. We won't add the actual dialogue just yet, but we'll cover that soon.
We will also need an audio notification that the player has accepted the quest and that it's begun. Create an ambient_generic entity, place it near your NPC, and name it sound_start. If you don't already have one you want to use, try using elevbell1.wav by typing "plats\elevbell1.wav" into the Sound Name field. Then go to the Flags tab and make sure all three options are checked.
After that we're going to add the text that explains the quest to the instance. Add two separate game_text entities and name them "text_start" and "text_end." The Hold Time for both will need to be a high value, like 99999, so that the message won't disappear until we kill that entity. We also want the text to be off to the side of the screen where it won't obstruct the player's view, so set the X and Y fields to 0.1 for both game_text entities. Text_start will be the message that displays during the quest and text_end will be the message that tells the player to return to the quest giver or a certain area.
We're going to need some relays to keep our triggers organized. A relay is an entity that activates other entities when it gets triggered. They're used by level designers to keep triggered events that occur at the same time together in one place, and they can easily be enabled and disabled. Create two logic_relay entities and place them near your NPC. Name them "relay_content" and "relay_complete." These will be the relays that activate all of the entities in the quest. The specifics of the actual quest are up to you to create for the player to complete. You'll need to set up a condition for the player to meet, like "get to a specific location" or "collect a certain number of objects." You can use entities such as math_counters, or brush entities such as trigger_once to check whether the condition has been met. If those entities find that the condition has been met, they will then trigger the relay_complete entity that we've set up. The relay_complete will then trigger all the entities needed to run the end of the quest. Make sure that "relay_complete" is triggered when your quest section is completed.
Now we need the audio notification for the end of the level. Add another ambient_generic entity and name it "sound_complete." Set it to a sound that indicates the quest has been completed, such as a bell or cash register. To keep it simple we'll use "plats\elevbell1.wav" again for now.
We'll need to add one more trigger in front of the NPC. This will be the same as the starting trigger we made earlier, so just copy and paste trigger_start. Name this new trigger "trigger_end" and make sure that Starts locked is checked in the Flags tab. Make sure both triggers are not overlapping each other at all and that trigger_start is in front by using your top and side viewports to place them. Also, make sure that they are in front of the NPC's hitbox, or else the game cannot tell if you are selecting the trigger or button. To check the hitbox location, just select your NPC and a yellow wireframe bounding box should appear around it.
Let's set up all of the triggers listed in Figure 5. For now, you don't have to worry about the triggers in [brackets] because we'll add them later. Select the listed entities, open their Object Properties, go to the Outputs tab, and add the designated outputs to each entity using the table below for reference. Be sure to hit Apply to save each output!
Figure 5: Our trigger listing.
That's how we set up our quest instance. Now we can take that instance and put it into different places around our map. Right now, our instance is essentially a basic quest template that we can easily modify and add new elements to.