Halloween Boss Tutorial

May 25, 2015
390
307
I originally wrote this tutorial for the Valve Developer Community, but considering it's very much so TF2 related, I thought it may be worth it to post it here as well. The tutorial on the VDC can be found here: https://developer.valvesoftware.com/wiki/Team_Fortress_2_Halloween_Bosses

Team Fortress 2 have a variety of halloween bosses that can be used in a map. These are special entities that acts like NPCs. Most of them requires a nav mesh to work.
Ghost
harvest-ghost.png
The ghost appears in Harvest Event, Moonshine and a couple of other maps. It's a blue ghost wearing a Ghastly Gibus on it's head. It will roam around the map for a while, stunning any players that come to close to it.

Tutorial
This tutorial will show how to set up a ghost to periodically appear and roam around the map, like in Harvest Event.
1. First, create a func_tracktrain about 48w*48l*80h textured with tools/toolsnodraw where you want the ghost to be when it's inactive. This is what will make the ghost actually move around in the map. In Harvest Event, this is a small room underneath the map. Give it a name. For this tutorial, it will be ghost_train.

2. Set the rest of the train's keyvalues to the following:

Render Mode: Don't Render
Disable Recieving Shadows: Yes
Disable Shadows: Yes
First Stop Target: ghost_path_home
Max Speed (units / second): 90
Change Velocity: Linear blend
Change angles: Ease in/ease out
Distance Between the Wheels: 20
Height above track: 0
Damage on Crush: 1000

Also set the following spawn flags to be on, No User Control, Passable, Is unblockable by player and leave the rest off.

3. Next, create a path_track at the same place as the func_tracktrain and name it ghost_path_home. This will serve as the starting point for the ghost when it's not in use.

4. Create a 255l*256w*72h brush textured with tools/toolstrigger. Make this brush a trigger_stun and name it ghost_stun. Set it's parent to ghost_train. Also set it's Trigger Delay to .5, Duration to 3, Stun Type to Loser State + Controls + Movement and enable Stun Effects. Add the following output to it:

OnStartTouch | ghost_sound_boo | PlaySound | <none> | 0.00

5. Create three ambient_generic entities. Name one of them ghost_sound_boo, and the other two ghost_sound_haunted. Make sure that the Start Silent and Is NOT Looped spawnflags are enabled on all of them. Set the SourceEntityName to ghost_train for all of them.

6. Set ghost_sound_boo's Sound Name to Halloween.GhostBoo, and it's Max Audible Distance to 1944.

7. For one of the ghost_sound_haunting entities, set the Sound Name to Halloween.GhostMoan and the Max Audible Distance to 1352. For the second ghost_sound_haunting, set the Sound Name to Halloween.Haunted and the Max Audible Distance to 1944.

8. Next, create a prop_dynamic, set its model to models/props_halloween/ghost.mdl and position it within the ghost_train. Disable its shadows, set collision to Not Solid and set its Default Animation to idle. Finally, set its parent to ghost_train.

9. Create an info_particle_system slightly underneath the ghost model. Name it ghost_teleport_effect and set its parent to ghost_train. Set its Particle System Name to ghost_appearation.

10. Create a path_track entity where you want the first path the ghost will follow to start 48 units above the ground and name it ghost_path1_0. No other options or spawn flags should be set.

11. Shift-drag ghost_path1_0 to copy it. The previous path_track will automaticly be linked to the new one. Continue doing this until you have track of path_track entities that the ghost will follow. Optionally, you can create a different path named ghost_path2_* (where * is replaced by a number, starting with 0) and clone it to create a separate track that the ghost also can follow.

12. In the first path_track entity in each track, add the following outputs:

OnTeleport | ghost_train | StartForward | <none> | 0.00
OnTeleport | ghost_teleport_effect | Start | <none> | 0.00
OnTeleport | ghost_sound_haunting | PlaySound | <none> | 0.01

And in the last path_track entity in each track, add the following outputs:

OnPass | ghost_train | TeleportToPathTrack | ghost_path_home | 0.00 | No
OnPass | ghost_teleport_effect | Stop | <none> | 0.00 | No

13. Next, create a logic_timer and a logic_case. Name the logic_timer ghost_timer and the logic_case ghost_case. Set Minimum Random Interval on ghost_timer to 14 and Maximum Random Interval to 20. Also enable Use Random Time. Add the following output to it:

OnTimer | ghost_case | PickRandomShuffle | <none> | 0.00

14. Add the following outputs to ghost_case. Replace ghost_path*_0 with whatever you named the first points in each of your tracks respectively.

OnCase01 | ghost_train | TeleportToPathTrack | ghost_path1_0 | 0.00
OnCase02 | ghost_train | TeleportToPathTrack | ghost_path2_0 | 0.00
OnCase03 | ghost_train | TeleportToPathTrack | ghost_path3_0 | 0.00

15. Compile the map and test if everything works. The ghost should occasinally appear and follow the paths until it reaches the end and disappears.

Horseless Headless Horsemann
mann_manor-headless_hatman.png
The Horseless Headless Horsemann was the first Boss NPC to be added to Team Fortress 2. It requires a nav mesh to move around the map. It will remain in the map until its killed and won't disappear on its own. It will also not respawn after dying.

Tutorial
1. Create a point_template somewhere in your map. Name it hhh_template. Set its first template to hhh_entity.

2. Create a new entity at the same place as hhh_template. Change its entity class to headless_hatman. This entity does not exist in the FGD and will be displayed as obsolete. Turn off Smart-Edit and add a keyvalue called targetname with a value off hhh_entity.

3. Create a prop_dynamic somewhere in your map and set its model to models/bots/headless_hatman.mdl. Disable shadows on it, set its solidity to Not Solid and its render mode to Don't render.

4. Place an env_entity_maker where you want the Horseless Headless Horsemann to spawn. Name it hhh_maker and set its template to spawn to hhh_template. To spawn the Horseless Headless Horsemann, send a ForceSpawn input to the hhh_maker entity.

Monoculus
eyeaduct-eyeball_boss.png
Monoculus (stylised as MONOCULUS!) was the second Halloween Boss to be added to Team Fortress 2. It appears in Eyeaduct, Hellstone and a few other maps. It will shoot eyeballs at players that acts like critical rockets. It will occasionally teleport in the map, leaving behind a swirling purple vortex that takes any players that jumps into it to the underworld.
Monoculus will automaticly disappear after two minutes if it isn't defeated. It requires a nav mesh to work properly.

Tutorial
1. Create a point_template entity somewhere in the map and name it monoculus_template. Set its first template to monoculus_entity.

2. Place a new entity in the same place as monoculus_template and set its classname to eyeball_boss. It will appear as obsolete in Hammer, but it will work in-game. Turn off Smart-edit and add a new keyvalue kalled targetname with its value set to monoculus_entity.

3. Create a prop_dynamic somewhere in the map with its model set to models/props_halloween/halloween_demoeye.mdl. Disable its shadows and set its collisions to Not Solid and its render mode to Dont render.

4. Place a few info_target entities around your map named spawn_boss_alt. Monoculus will occasionally teleport to a randomly selected one of these.

5. Create an env_entity_maker where you want Monoculus to spawn named monoculus_maker. Set its template to spawn to monoculus_template.

To spawn Monoculus, send a ForceSpawn input to monoculus_maker.

Truce
Monoculus and Merasmus can have a truce called when they spawn. During a truce, no players will be allowed to attack any player on the other team. To allow truces to be used in the map, send a SetMapForcedTruceDuringBossFight input with a parameter of 1 to the tf_gamerules entity in the map.

The truce will automaticly start when a boss spawns into the map, and will automaticly end when there are no bosses left in the map, either becuase they are dead, or becuase they have left after a certain amount of time.

tf_gamerules will fire OnTruceStart and OnTruceEnd outputs when the truce starts and ends respectively, allowing you to disable map objectives such as control points and flags during the truce.

Underworld
eyeaduct-underworld.jpg
The '''underworld''' is where players are taken when they jump into the vortex Monoculus leaves behind when it teleports.

The underworld requires the following entities to work:
  • A few info_target entities named spawn_purgatory. These are where the players will teleport after jumping into Monoculus's teleport vortex.
  • A trigger_add_tf_player_condition covering the entire underworld with its condition set to 108 and duration set to -1. This will add a temporary übercharge and heal the player to full health when entered, and give the player a critboost, speedboost and übercharge after leaving the underworld. Damage done to Monoculus while under these effects will temporarily stun it.
  • A trigger_hurt covering the underworld, with its damage type set to Bullet, and its damage per second set to 9.
Finally, to allow players to get out of the underworld, there should be two trigger_teleport brush entities at the end of the underworld. One of them need to have its filter set to a filter_activator_tfteam set to only allow RED players, and target an info_teleport_destination in the normal map, and the other trigger_teleport should have a filter only allowing BLU players and target a different info_teleport_destination.

Merasmus
ghost_fort-merasmus.png
Merasmus (stylised as MERASMUS! in-game) was the third Halloween boss to be added to Team Fortress 2. He appears in Ghost Fort among other maps.
His attacks includes attacking with his staff, launching players in the air, and using the bombonomicon to summon bombs to launch at players if there is one control point in the map. He requires a nav mesh to work.

Tutorial
1. Create a point_template entity somewhere in the map and name it merasmus_template. Set its first template to merasmus_entity.

2. Place a new entity in the same place as merasmus_template and set its classname to merasmus. It will appear as obsolete in Hammer, but it will work in-game. Turn off Smart-edit and add a new keyvalue kalled targetname with its value set to merasmus_entity.

3. Create a prop_dynamic somewhere in the map with its model set to models/bots/merasmus/merasmus.mdl. Disable its shadows and set its collisions to Not Solid and its render mode to Dont render.

4. Create a brush covering the entire area that you want Merasmus to be able to move around in. Tie it to a func_nav_prefer entity, and name it boss_nav_prefer. Merasmus will stay within this area when he is on the map, and he will ocassionally teleport within it. Players within this volume will also randomly be selected by the bombonomicon to have their heads replaced with bombs. They are instructed to run these to Merasmus to stun him, making him imobile and take more damage for a limited time.

5. Create an env_entity_maker where you want Merasmus to spawn named merasmus_maker. Set its template to spawn to merasmus_template.

To spawn Monoculus, send a ForceSpawn input to merasmus_maker. Merasmus can also have a truce called when he spawns. For more information, see the truce section above.

Skeleton
helltower-skeletons.png
Skeletons are hostile npcs that will attack any player, or players on the opposite team if summoned belonging to a team. They appear in Helltower, spawning regularly, but can also be sommuned by players to attack the enemy team through spells. There are two types of skeletons, regular skeletons and the skeleton king, with the skeleton king being much more stronger than regular skeletons. Skeletons require a nav mesh to work.

Tutorial
1. Create a couple of tf_zombie_spawner entities around the map. The skeletons will be spawned from these.

2. Set up the tf_zombie_spawners' keyvalues. Skeleton Life Time is how long the skeletons will live before they automaticly disappears. Skeleton Count is how many skeletons this spawner will spawn before it needs to be enabled again. Infinite Spawn means that it will continue to spawn skeletons until it reaches the skeleton count until it's disabled. The Skeleton Type determines wether or not the skeletons spawned will be a normal skeleton, or the skeleton king.

3. To spawn the skeletons, send an Enable input to the tf_zombie_spawner entities.
 

Benoist3012

L3: Member
Dec 25, 2015
148
207
tf2 had no npcs
all halloween bosses are Nextbot
You do get the meaning of NPCs? (Non playable characters) Are those bosses playable (outside of server hack that doesn't reproduce the boss 100%)? No.

So using NPC therm isn't wrong, they are Nextbot yes, but that doesn't mean they aren't Npcs. You actually contradicted your own answer, if you read Nextbot, you have the therm bot, and a bot is a non playable character aka NPC.

Nextbot is therm (actually a C++ class) used by valve in their game code, INextBot from where they build their NPCs.

Halloween bosses are NPCs that their AI were written over the INextBot C++ server class.
 

killohurtz

Distinction in Applied Carving
aa
Feb 22, 2014
1,016
1,277
Bots in TF2 (that includes both player bots and Halloween ones) are NPCs in the general sense of the term, but not in the context of Source. Source NPCs generally refer to the ones in, for example, HL2, and have some entities and tools designed to work with them specifically. This NPC code does not exist in TF2. So, both of you are right.
 

Benoist3012

L3: Member
Dec 25, 2015
148
207
Bots in TF2 (that includes both player bots and Halloween ones) are NPCs in the general sense of the term, but not in the context of Source. Source NPCs generally refer to the ones in, for example, HL2, and have some entities and tools designed to work with them specifically. This NPC code does not exist in TF2. So, both of you are right.

The NPC code does exits in TF2 code it is just unused, and npcs (in general therm), made from the INextBot class, does collide with NPC clip textured brush, and have/share the same inputs, as well with the same C++ function event, for death and spawn, used for an HL2 Npc.

The only and current bug with npcs made with INextBot as base class, aren't detected by the NPC trigger spawn flag neither by the bot flag, I could email valve about it, but that's kinda useless, since it can be resolved by setting the everything but debris flag, and using a classname filter.
 

ics

http://ics-base.net
aa
Jun 17, 2010
841
543
Gonna post here so people who make halloween maps can see the guidance on how to implement these bosses.