L4D2 Level Design/Foot Lockers
Foot lockers (AKA item stashes, item caches) were introduced in "The Passing" update and are highly customizable. Rather than being a specialized entity, such as the ammo crates in Half-Life 2, these stashes are constructed from existing entities. In fact, the only new assets introduced were the model and sounds. Discussed here are static-persistent lockers, spawnable lockers, and lockers that containing multiple item classes.
This is the most basic type of boot locker: it will always be present in the world (as opposed to lockers which are chosen to spawn at random in-game) and will include whichever type of item the level designer decides to include.
Doesn't look like much from inside Hammer, does it? Here's how it's made.
1: Locker model and collision mesh
The first building block is the locker model - a simple prop_dynamic. Insert one into a blank map (preferably saved with your desired instance name) and give it these properties (the rest can be left as default):
- World Model: models/props_waterfront/footlocker01.mdl - This is the model used.
- Name: static_locker - The name of the model will be fixed up as needed when the instance is inserted into your map.
- Start Fade Dist: 1500 - This is the general distance Valve have used to begin fading the locker out.
- End Fade Dist: 1900 - At this distance away, the locker will no longer be visible. Make sure that it is actually out-of-sight at this distance, otherwise you may be able to see the items inside.
- Collisions: Not Solid - The locker model does not actually have a collision mesh, so setting this option will ensure that the console doesn't complain in-game.
Next, put in a couple of nodraw-textured brushes so that the player and objects will appear to collide with the locker. Valve left the locker with no collision model of its own probably because it would require more expensive VPhysics calculations to include one (since the locker is a concave shape), so brushes are used to act as the solid sides and base of the locker.
The collision brushes should be 2 units thick and follow the edges of the locker. Putting one in for the locker base is also useful. Don't forget to tie all of these brushes to a func_detail, otherwise they will play havoc with your visleaves.
2: Locker items and other entities
Place your desired items into the locker and rotate/position them. I have used health kits and pistols here, since I designed this locker to be present at the beginning of my campaign. If you are using other items, it's best to pretty much fill the entire bottom of the locker model with a layer of items.
If you are using items such as pipe bombs, molotovs or boomer bile, you'll want to set their "Count" value to 10, or maybe higher. This means that players will be able to take more than one item from each spawner in-game; of course, if you just want single item pickups (like the health kits in the picture), set the "Count" value to 1.
Name all the items you have added as "static_locker_items".
Set your locker's animation back to "ref" (to close the lid) and add an ambient_generic somewhere near the locker. The position doesn't really matter, as we'll be specifying the origin point of the sound in the ambient_generic's properties.
The properties can be left at the defaults, apart from these:
- Name: static_locker_snd_open - This will allow us to trigger the sound later on.
- Sound Name: Trunk.Open - The soundscript entry for the locker opening sound.
- SourceEntityName: static_locker - This is the name of the prop_dynamic locker model. When triggered, the sound will originate from the locker model rather than from the position of the ambient_generic itself.
Spawning the items
Next, we need a point_template in order to spawn our items when we want them. Simply ticking the "Must Exist" flag on the items may cause their glow effect to be visible through the edges of the locker model, so the point_template ensures that the items are only created when they are needed. For lockers which may or may not be present, the point_template allows the spawning of the items only if the locker exists (it's considered a set).
Setting up the point_template is simple:
- Name: static_locker_template - The name of the point_template.
- Template 1: static_locker_items - When triggered, the point_template will spawn our static_locker_items (that we named earlier) at their appropriate spawn points.
Add in a logic_game_event entity that the locker has been opened. It is assumed that this is needed because it is not a "specialized" entity where the game event would be triggered for every instance of the entity class. This may not be in Hammer's entity list (FGD), so add in a different entity (such as an info_target) and change its name in the drop-down box to logic_game_event. You may have to add these KeyValues manually:
- Key: targetname, Value: static_locker_event - The name of the entity.
- Key: eventName, Value: foot_locker_opened - The name of the game event this entity will fire when triggered.
- Key: spawnflags, Value: 1 - No idea what this flag does. I'm copying the values from Valve's maps to be on the safe side.
Now surround the foot locker with a brush and tie it to the func_button entity. Texture the button in nodraw. It should typically extend about 4 units further out from each side of the locker model (apart from the bottom, of course, where it should be in-line with the locker base).
The following properties will need to be changed:
- Name: static_locker_button - In case you want to lock/unlock the button at any time though inputs.
- Glow Entity: static_locker - When the player is in range of the button and looks at it, the prop_dynamic model of the locker will glow to invite the player to open it.
These spawnflags will need to be set:
- Don't Move.
The button also needs the following outputs:
- OnPressed, static_locker -> SetAnimation: opening.
- OnPressed, self -> Kill.
- OnPressed, static_locker_snd_open -> PlaySound.
- OnPressed, !activator -> Speakresponseconcept: OpenLocker.
- OnPressed, static_locker_template -> ForceSpawn.
- OnPressed, static_locker_event -> FireEvent.
All of these need the "Fire Once Only" box ticked. An explanation of each:
- 1. Sets the animation of the locker model, to open it. The animation stops automatically, so there's no need to send another input to do so.
- 2. Gets rid of the func_button, so that it can't be pressed again and doesn't block the top of the box, prohibiting the player from picking up the items.
- 3. Plays the locker opening sound.
- 4. Tells the character who "opened" the locker (the one who pressed the button) to say a line, mainly to tell the other players that they've found the items.
- 5. Spawns the items inside the locker.
- 6. Fires the game event to the Director. Only include this output if you followed the optional step 5.5 above.
The final step is to add an info_remarkable, to let the engine know that the characters should say something when they spot the locker. Set these properties:
- Name: static_locker_remarkable - The name of the entity.
- Subject Context: WorldFootLocker - This tells the game that the characters should say something related to spotting the locker, like "Let's open it up" or similar.
Your locker should look something similar to this:
Compile and load your map to test your foot locker in-game.
A spawnable locker is similar to a static locker with the exception of a few modifications.
In The Passing, a foot locker can have randomized item spawn types. For example, instead of having an overwhelming amount of pain pills in a round, the contents a particular foot locker may contain a large cache of Molotovs instead. This only involves a few more entities and modifications.
To do: finish article (steps, pictures, testing, condense, and finally celebrate the existence of a diverse set of foot lockers in-game).