No More Room in Hell

No More Room in Hell

Not enough ratings
No More Room In Hell How To Make An Objective Map In Hammer
By Hectic Morder
This guide aims to teach you the overall basics of mapping and objectives in the Hammer editor.
   
Award
Favorite
Favorited
Unfavorite
🍉Introduction
No more room in hell maps are unique in that zombies, objectives, survival, can have a high level of complexity especially when it comes to objective maps. This guide involves the basics of Hammer editor and how to make objective maps in nmrih. The Hammer editor is also very overwhelming combined with No more room in hell's high level of complexity it's a big undertaking for those who are new to this. The system may seem complex at first but is quite flexible.




Requirements/Recommendations
  • No more room in hell steam client.
  • Hammer ++ SDK 2013 MULTIPLAYER
  • Notepad ++ More advanced file editor.
  • Basic file browsing knowledge.
  • Basic knowledge of scripting .txt files if you want to add vscips or soundscapes to your map.
  • Basic hammer editor knowledge is required to setup an objectives system.
  • Some level of patience maps take time to build.
  • Quality assurance don't upload and flood the workshop with unfinished broken maps.
  • Somewhat good computer compiling, running hammer and no more room in hell game client at the same time can crash your GPU or outright crash your computer It's faster having them up at the same time for testing.


General steps to making and publishing objective maps.
  1. Make a text document (this will be used in reference if you decide to take a break) note down what's your map going to be for example "prison map" and then some names for your map.
  2. Add to the text document, simple objectives that are going to be in the map for example "unlock the door".
  3. If needed build a rough sketch on your desired app for the map you plan to build.
  4. Load up hammer++.
  5. Build geometry walls, floor, ceilings, etc.
  6. Add the dev textures to your geometry.
  7. Place down player spawns "info_player_nmrih".
  8. Tests for leaks when compiling the map in hammer.
  9. Test the geometry size in-game.
  10. Add textures to your geometry.
  11. Place down props lights, lights, sprites, map sun, tone-map.
  12. Test your lighting.
  13. Add and place Props, triggers.
  14. Build objectives and extraction.
  15. Tests for errors in-game.
  16. Add objectives to Visgroups.
  17. Make .nmo file with the Objective Graph Editor.
  18. Test your objectives in-game.
  19. Add env_cube maps.
  20. Add Zombie Brush's.
  21. Add Navigation from within the game.
  22. Build cube maps in-game.
  23. Test map.
  24. Publish to workshop.






🔨Hammer Editor Setup
There are a few things we need to obtain before we start making some awesome maps. In this section we will be going over hammer and the better version made by the community hammer++.





Hammer Editor

Valve Hammer Editor (more informally known as Hammer, and previously called Worldcraft) is the official mapping tool for Valve's engines: GoldSrc, Source, and Source 2. It is also included in every game made with Source Engine that is not a mod or third-party.


We are going to avoid the original Hammer editor and install the latest Hammer++[ficool2.github.io] version. This is a community-made modified version of Hammer 4.x that has significantly more features and better stability with faster compile times

Hammer++ Does not support some features from Hammer 4.x, such as "Convert WAD to VMT...", or loading GoldSrc ".MAP" files directly.







Before we start installing hammer++, run the normal hammer.exe that's in the game's bin folder,
E:\SteamLibrary\steamapps\common\nmrih\bin
Then close the hammer.exe

This loads and establishes all the game's custom entity models, materials, scripts, etc. for hammer++ to use.

Now navigate to the hammer++[ficool2.github.io] website and download the Source SDK 2013
or click[github.com] this to download the file directly from here.

After you have installed the zip file unzip hammer++ into the bin folder
E:\SteamLibrary\steamapps\common\nmrih\bin

Go to the bin file and pin hammerplusplus.exe to your windows start bar do this for hammer.exe as well.


For a complete guide on Hammer++ check this guide out How To Use Hammer++ For NMRiH!

Hammer Manual Configuration

TopHATTwaffle Hammer Tutorial Launching Hammer, initial configuration, making a room.
https://youtu.be/jF3er5lsaeg?list=PL-454Fe3dQH1L38FnKkz_O1CqYx6sKaXk



⚒️Building Objectives #1
Note:
When naming your objective map, you must have "nmo_" before the name of your map.
Example
nmo_objective_map

If you have not checked out TopHATTwaffle's Hammer Tutorial on YouTube please do as basic understanding of building, texture's, placing entity's is needed.

https://youtu.be/jF3er5lsaeg





Objective Setup

For each objective (but NOT for anti objectives!) you need a nmrih_objective_boundary entity. These entities must be placed inside of the corresponding visgroups. This entity controls the beginning and end of objectives (hence the name 'boundary'). Only one boundary entity per objective! The name of the entity does not matter.

In order to signal objective completion, use the boundary's ObjectiveComplete input. To signal objective failure, use the boundary's ObjectiveFailed input. In order to signal objective completion and immediately go to extraction, use the boundary's ObjectiveCompleteTriggerExtraction input with a parameter override.





Objective 1

We are going to make a keycard open a locked door.





prop_physics_override
Let's start with the entity tool and place a info_player_nmrih then change this to a prop_physics_override to the map then look for the world model card.mdl name the prop in the keyvalues "card" without the quotes.





There should be a tab called Flags make sure these parameters are checked.




filter_activator_name
Now add filter_activator_name this is for the card when we setup a trigger it will call the filter_activator_name if the option is enabled in the. "keyvalues" Change the name to card_filter and add the card name to filter name. "card"










prop_door_rotating
Place a info_player_nmrih then change this to a prop_door_rotating and look for a world model in the keyvalues door01_dynamic.mdl. Change the name to locked_door then go to flags and make sure they are the same as whats displayed in the picture.
door01_dynamic.mdl









trigger_once
Go to the block tool in hammer and make a small square box then change the texture to the trigger brush. "Tools/toolstrigger" After that seclect the box and hold "ALT" and pless "T" this will tie the box to an entity. Now change it to a trigger_once "class" and name it card_trigger.

Then go to the Outputs tab and add a new output
  • add "my output name" = OnTrigger
  • add "target entities named" = locked_door
  • add "via this input" = Unlock
trigger_once
Class Info
Flags
Outputs Tab







nmrih_objective_boundary
Place a info_player_nmrih then change this to a nmrih_objective_boundary in the keyvalues change the name to objective 1. (This can be anything you want for example: unlock the door )
When someone is playing your map, this name will be displayed to all players centre top of the screen. In the nmrih_objective_boundary keyvalues add the card name to glow entity #1 this will show up on the compass when players pless "C" and lastly add an output to the trigger once entity. This will be an output for completing the objective perimeters are.

OnTrigger
objective 1
ObjectiveComplete

nmrih_objective_boundary and trigger once





🛠️Building Objectives #2

Objective 2

Objective 2 will be explained with less detail most info can be refereed to from above.

We are going to make a button compete objective 2.






func_button
Go to the block tool in hammer and make a small square box then change the texture to nodraw . Now select the box and hold "CTRL" and pless "T" this will tie the box to an entity. In the keyvalues Change the class it to a func_button and name it obj_button.



















prop_dynamic
Place a prop_dynamic then look for a world model in the keyvalues named cj_comp_newmonitor_objective.mdl and change the name to pc1
















nmrih_objective_boundary
Place a info_player_nmrih then change this to a nmrih_objective_boundary in the keyvalues change the name to objective 2. (This can be anything you want for example: unlock the door ) In the nmrih_objective_boundary keyvalues add tne PC name to glow entity #1 and lastly add some outputs to the func_button entity.


















🛠️Building Objectives #3
Objective 3

For this objective we are going to move a wooded box to a location when placed it will trigger excitation. "map ending"








prop_physics

Place a prop_physics with the entity tool then look for a world model in the keyvalues named wood_crate001a.mdl and change the name to wood_box. This will be the box we need to move to a location on the map.
























prop_dynamic_override
Place a prop_dynamic_override with the entity tool then look for a world model in the keyvalues named wood_crate001a.mdl and change the name to wood_box_dummy. This will be the box that we use as a marker to place the wood_box at. There are a few parameters in the keyvalues and flags that need to be changed for this to work properly.

FX amount: from 225 to 150
Transparency amount, requires a Render Mode other than Normal. 0 is invisible, 255 is fully visible.
Render Mode: from normal to color




















func_brush
Select the nodraw brush then select the wood_box_dummy and now select block tool in hammer and make a square box as the same size as the box_dummy, With the top view this will make a perfect size square box. Now select the nodraw box and hold "CTRL" and pless "T" this will tie the box to an entity. In the keyvalues Change the class it to a func_brush and name it wood_box_dummy_brush.

















trigger_once
Go to the block tool in hammer and make a small square box then change the texture to the trigger brush. "Tools/toolstrigger" After that Seclect the box and hold "CTRL" and pless "T" this will tie the box to an entity. Now change it to a trigger_once "class" and name it box_trigger.

trigger_multiple
Go to the block tool in hammer and make a small square box then change the texture to the trigger brush. "Tools/toolstrigger" After that seclect the box and hold "CTRL" and pless "T" this will tie the box to an entity. Now change it to a trigger_multiple "class" and name it timer_trigger.

point_template
Place a info_player_nmrih then change this to a point_template in the keyvalues change the name to box_spawner and add the name wood_box_dummy to "Template 1".

logic_timer
Place a info_player_nmrih then change this to a logic_timer in the keyvalues change the name to box_timer and start disabled keyvalue to "YES".


math_counter
Place a info_player_nmrih then change this to a math_counter in the keyvalues change the name to box_counter and change the Minimum legal value to "1"


filter_activator_name
Place a info_player_nmrih then change this to a filter_activator_name in the keyvalues change the name to box_filter and add wood_box as the filter name.


nmrih_objective_boundary
Place a info_player_nmrih then change this to a nmrih_objective_boundary in the keyvalues change the name to objective 3. (This can be anything you want for example: unlock the door ) In the nmrih_objective_boundary keyvalues add the wood_box name to glow entity #1. Add the wood_box_dummy name to glow entity #2 and lastly add some outputs to these entity's.


















Outputs
"Putting everything together"
trigger_once
trigger_multiple
math_counter






🚁Extraction
🔧Setting up Extraction
Find a nice open space for your extraction point.

The func_nmrih_extractionzone should be somewhere between 32 and 64 units high you can also have more than one extractionzone setup on your map. 'extraction_zone_1', 'extraction_zone_2' etc.

The nmrih_extract_preview has two options: Stationary and Rotating camera.

"More info about Extraction Setup"
https://wiki.nomoreroominhell.com/Extraction_Setup
















📐func_nmrih_extractionzone
Go to the block tool in hammer and make a small square box then change the texture to the trigger brush. "Tools/toolsextract" After that seclect the box and hold "CTRL" and pless "T" this will tie the box to an entity. Now change it to a func_nmrih_extractionzone "class" and name it extractionzone.

🎥nmrih_extract_preview
Place a info_player_nmrih then change this to a nmrih_extract_preview in the keyvalues change the name to extract_preview

⭕️nmrih_extract_point
Place a info_player_nmrih then change this to a nmrih_extract_point in the keyvalues change the name to extract_point and add extractionzone as the "Extraction Zone" Then add extract_preview as the "Extraction Cam".



























⛳Visgroups






🍉Intro
Objectives and Anti-Objectives are defined as visgroups inside of Hammer. Inside these visgroups will be all entities associated with that objective. Entities inside of the objective visgroups will only spawn if their objective is chosen for a round.

Because Hammer likes to remove empty visgroups, initial setup of them is futile; this section will simplify the required layout of the visgroups. All objective visgroups must be children to one main visgroup named "Objectives". All anti-objective visgroups must be children to one main visgroup named "anti", which must be a child to the visgroup "Objectives". Anti-objective visgroups must also be named the same as their corresponding objective visgroup.
Preview









⛳Setting up visgroups

When setting up visgroups you only need to add the nmrih_objective_boundary entity and what trigger has the ObjectiveComplete ect, In the outputs.
Example
Here is where i have the math_counter and nmrih_objective_boundary selected. This can be done by holding 'CTRL' and then 'left click' both entity's. Now with both selected hold 'LEFT ALT' and pless 'ENTER' this will have both showing up on the Keyvalues, Be careful not to change anything but the visgroups tab.
Example






Now that we have whats needed to be selected to connect the objective together go to the visgroups tab and click on edit groups.


A small window will pop up with all the visgroups that are on your map

Select a new group and name it this can be the nmrih_objective_boundary name like "open the locked door" or something like "objective 1, 2, 3," etc.





















Once you have created a new group and named it close that small window and go to the visgroups tab.
Here you must select the visgroup you just created with the check box located next to its name and then hit apply once done you cannot remove the items individually from the visgroup, "But" you can add more to a visgroup that was created.
Example




















No we must connect all the visgroups thet were just created to the main visgroup that has to be named "Objectives" just simply create one in the visgroup on the right panel of hammer.

All objective visgroups must be children to one main visgroup named "Objectives".















On the right side panel you will see visgroups right click objective 1 and hold now move it on top of the Objectives visgroup then let go of the right mouse key this will place the objective 1 into the main visgroup now do this with the rest of your objective's.


















📊Objective Graph Editor
The Objective Graph Editor is an application located inside your Main No More In Hell's directory as it's used to connect your objective's together can compile it into an .NMO file for other players so they can enjoy all the hard work you just created.





Navigate to E:\SteamLibrary\steamapps\common\nmrih\nmrih\util
Inside the utils folder in the NMRiH build you will find NMRObjective.exe, Run this.
A window will pop up this is the Objective Graph Editor the first time you start up, it will ask you for the location of your NMRiH maps directory (where the BSPs are stored). This tool will be used to link your objectives to one another.




















Click on the folder icon in the Objective Graph Editor to open your VMF. file. A couple of coloured blocks will appear on the screen, corresponding to your objectives and extraction points you created in the visgroup.











Click and drag these blocks around to position them in a logical layout (position is only cosmetic and has no effect on the game). To select multiple objectives, hold CTRL. In order to link one objective to the next, RIGHT CLICK on an objective, DRAG the mouse to the next objective, and release. In order to unlink two objectives, select them both using CTRL and click the 'Unlink' button.

Note:
  • Keep in mind that extraction zones are the end of the round -- they will not continue on to other objectives.
  • You can name each objective by clicking on its block and filling in the "Description" field on the bottom of the screen.














When you are all finished, click the Save button. This will save a .NMO file in your map's directory, as well as a .NMOS file in the same directory as your VMF. The .NMOS file will preserve your layout the next time you open that VMF in the objective tool.




↩️Navigation Setup


🖌️Zombie Brush
Before we start building navigation into your map, you need to make some zombie brush around your map, and you are also required to have a single overlord_zombie_helper entity anywhere in your map. This step is important.

While func_zombie_spawns can support multiple stories of a building, it is recommended to separate your floors. Each zone should be 1-100 units high, 1-2000 units above the ground, and at least 13 units from walls.

Objective mode features a dynamic gameplay where players roam a map which is usually filled with zombies wherever they go. With these maps, the spawn system will automatically fill your func_zombie_spawns while they are enabled as the players roam and complete objectives.
Set up one spawn brush per room or hallway, and try to split larger outdoor zones into logical zones where players can't see separate areas. Large fully visible areas should be one large zone with a high spawn density.






















🗺️ Navigation

Once you have set up your Spawn Brushes, you will need to setup the navigation within your map. Navigation is controlled with nav meshes; this means you must create a .nav file in order for the func_zombie_spawn brushes to activate properly.

To create a .nav you must

Start NMRiH up and load your map as a local server (highly recommended that you compile the newest version of your map for this purpose) now bring up the dev console with the ~ key make sure its enabled in the options.

"Type these commands into the dev console"
  1. sv_cheats 1 (Cheats on)
  2. sv_idle_autokick_enabled 0 (Stop's you from being kick from the game.)
  3. nav_edit 1 (interactively edit the Navigation Mesh)
  4. nav_generate (Generate a Navigation Mesh for the current map and save it to disk.)
  5. nav_analyze (Loads the Navigation Mesh for the current map.)
  6. nav_save (Saves the current Navigation Mesh to a .NAV file.)


Note:
  • If your map has multiple floors on different levels here is how to set up Navigation after you have run the nav_generate command in the dev console.

  • When you have nav_edit enabled and moving around your map ie "noclipping" you will see the navigation mesh on the floor make sure the map is fully covered like this in the example picture below.

  • The nav_generate_incremental will add new areas to existing ones (but only in 2000 units radius. It is default number for nav_generate_incremental_range, you can change it via console and it will break all current nav_jumps (to fix it, type nav_generate_fixup_jump_areas 0, but it will add many unnecessary nav_jumps with incremental generation.
"Type these commands into the dev console"
  1. nav_edit 1 (interactively edit the Navigation Mesh)
  2. nav_mark_walkable (Mark the current location as a walkable position. These positions are used as seed locations when sampling the map to generate a Navigation Mesh.)
  3. nav_generate_incremental 2000 (Run the generation process from walkable markers instead of on the entire mesh. Newly created areas will usually connect to preexisting areas.)
  4. nav_analyze (Loads the Navigation Mesh for the current map.)
  5. nav_save (Saves the current Navigation Mesh to a .NAV file.)

Example Pictures
nav_edit
nav_mark_walkable








Navigation Mesh Editing
https://developer.valvesoftware.com/wiki/Nav_Mesh_Editing

Navigation commands
https://developer.valvesoftware.com/wiki/Nav_Mesh/Console_commands




🔗Embedding Custom Content

Let's start by looking at some files you may want to add to your map and embed that content so other players can see it when they download your .BSP file.




🖼️VTF
The Valve Texture Format (VTF) is the proprietary texture format made in the "VTFEdit".
More about the VTF Here.



💽VMT
A VMT ("Valve Material") file defines the material used by a two-dimensional surface. It contains all of the information needed for Source to simulate the surface visually, aurally, and physically.
If a material is missing, it will produce the infamous Source pink and black checkered pattern. A white wireframe is not a missing material, but instead a missing shader.
More about VMT Here.

Examples:
"LightmappedGeneric" { "$basetexture" "Hectic/curepic" "$surfaceprop" "Wood_Solid" }
"Refract" { "$refractamount" ".025" "$bluramount" "1" "$REFRACTTINT" "{183 204 218}" "$scale" "[1 1]" "$dudvmap" "reacz\portal\glass\refractive\Glass_refract03" "$normalmap" "reacz\portal\glass\refractive\Glass_refract03" "$surfaceprop" "glass" "%keywords" "reacz,glass,refractive" "$envmap" "env_cubemap" "$envmapcontrast" "1" "$envmapsaturation" "[1 1 1]" "$envmaptint" "[.71 .79 .85]" }



📻Custom Soundscape's

A Soundscape is a type of audio script used to add ambience to maps Requires only a single entity to implement and does not generate any network traffic. Soundscapes use a mixture of looped and randomly played sounds. More about Soundscape Here.

To create a "Custom Soundscape" first navigate to the scrips folder in the main No More Room In hell directory:
E:\SteamLibrary\steamapps\common\nmrih\nmrih\scripts
And Create a .txt file then name it as you map's name.

Example:
soundscapes_nmo_broadway.txt

Then open the .txt file and add your sounds.

Example:
"start room" { "dsp" "1" "playlooping" { "volume" "0.1" "pitch" "80" "position" "0" "wave" "ambient\zombies\bangonglass_group.wav" } "dsp" "1" "playlooping" { "volume" "0.4" "pitch" "100" "wave" "ambient\atmosphere\underground_hall_loop1.wav" } "dsp" "1" "playrandom" { "time" "80,100" "volume" "0.1,0.3" "pitch" "90,100" "position" "random" "rndwave" { "wave" "ambient\levels\labs\teleport_weird_voices1.wav" "wave" "ambient\chinatown\distant_fire1.wav" } } }





🔗Embedding Custom Content
First up we need to download a program named "VIDE" Valve Integrated Development Environment is a third-party tool used by Source developers and mappers that embeds custom content into the .BSP file and features a mass VTF/VMT file editor.
Pakrat is an alternative program to the VIDE, It's a bit deprecated.


Once you have Vide installed on to your computer open the folder and click on the VIDE.exe pull down the tools tab and click on Pakfile Lump Editor and open your map BSP.

  1. Click Pakfile Options > Scan.

  2. For Game Directory, choose your No More Room In Hell/nmrih folder.
    E:\SteamLibrary\steamapps\common\nmrih\nmrih

  3. Click Scan. This will find any files that need to be added.

  4. Click Auto. This will automatically mark any non-default files.

  5. Click Apply. This adds the previous list of files into the list that VIDE will to add to your BSP.

  6. If you've got any content that you have in your \custom folder, you will need to go back to step 4 and do everything again, except you will need to select whatever folder inside of \custom you have stuff inside in step 5.

  7. Click Save. If you aren't sure if everything worked as you wanted, you may want to save as a different filename. Overwriting works fine, however.


📁Manually Packing Files

VIDE wont always detect all of the files that you want to pack for example. .VTF and soundscapes so you might have to manually add some files.

Go through steps 1-3 of the above tutorial.
  1. Click Pakfile Options > Add.

  2. Choose the file(s) you want to add.

    VIDE will show you a menu of directories like this. Click Cancel.





















  3. VIDE will show you a file path to the file(s) you selected. Delete "nmrih", as well as everything before it. Then change the path from \ to /














  4. Click Save.









📋Conclusion/Debugging
Debugging



🛑Map Leak
maps must be completely internally sealed. No part of the interior of the level, the world, should connect with the outside void.

When a map like this is compiled, with a gap to the void, VBSP generates an error similar to this in the compile log:
ProcessBlock_Thread: 0...1...2...3...4...5...6...7...8...9...10 (0) **** leaked **** Entity light (-1607.69 -1094.12 -183.00) leaked!
A leak in a level has a number of bad effects to fix a "Leak" in hammer go to the map tab and click on Load pointfile and follow the line to the opening of the void.













⚠️Map Limits

entdata has no limit and is only a suggestion and can be ignored.

edicts will most likely hit the limit first, so keep an eye out on entity use
(can use report_entities console command in-game to get total count)
Anything over 1900 is unstable and will lead to ed_alloc no free edicts when the map starts or restarts and game will completely crash.

(ed_alloc no free edict) This means you have too many entities in the map, or you use a lot of prop_dynamic's,
Sprites and lights they are quite expensive for the engine.
Buttons, triggers and logics will eat up edicts quick the same goes for weapons and ammo.
Make sure everything is prop_static unless it has to be otherwise may lead to crashes. If you use prop_dynamic disable bone followers.
Remember to leave headroom for zombies, players spawns, weapons/ammo boxes i.e. anything that can be dynamically spawned.


















👁️‍🗨️Conclusion




♻️Adding Reflections

env_cubemap is a internal point entity available in all Source games. It specifies a location for which a cubemap will be generated when the buildcubemaps console command is executed. Materials with $envmap will use the nearest cubemap as their reflection.

You can achieve this by copy-pasting env_cubemap entities around the map floor and then use Hammer's Entity Report function to select all env_cubemap entities and then moving them 64 units upward by using the Transform tool Ctrl+M.

More about env_cubemap here






📝End Notes

Now you have the .bsp, .nmo and .nav files of your map it's time to start testing with some friends before you start posting it on the steam Workshop. If you don't have friends, come join us on the nmrih discord there are staff members and the community members who are willing to test your map.

When you think it's ready load up nmrih and upload your map files in the game menu.















5 Comments
EddieSpaghettiYeti 3 Jul @ 8:35pm 
perfect guide tysm :bloody::steamthumbsup:
Hectic Morder  [author] 2 Jan @ 12:02am 
area portals are to be used wisely not just paced anywhere or will lead to the map being more buggy then when you started pacing them
Hectic Morder  [author] 1 Jan @ 11:59pm 
i did have area portals on the map removed them coz didint see much change in frames also alot of my doors have windows map has like 2 door i can put area portals on it that is worth placing and im close to map limit and i think area portals are part of the edicts limit cant test this as im busy with work Conclusion/Debugging has some optimization ill add some links for hint skip and area portals Tophattwaffle has a good guide on TY i can link this is mainly for people that want to start making an objective map less about Hmmer its self or this guide will be 30 pages longer
Ice 1 Jan @ 8:29am 
add area portals to nmo_fema_labs and add optimization to this guide
Hectic Morder  [author] 12 Dec, 2023 @ 5:07am 
i am no way an expert in this field i just hope this helps new mappers :melon: