S2ZE - Map Porting Guide

Source 2 Zombie Escape

Map Porting Guide

Discord: https://discord.gg/s2ze (back up link)

Github: https://github.com/Source2ZE

Last Update: 2025 / 07 / 24


Contents

-1.0 - Urgent Information        5

-1.1 - Import Tool Not Functioning        5

-1.2 - Missing Material Fatal Error        5

0.0 - Porting Guidelines        7

0.1 - Disclaimer        7

0.2 - Useful Links        8

0.3 - Useful Tools        8

1.0 - Mandatory Works        9

1.1 - Stripper Configs        9

1.2 - The Import Tool        10

1.2.1 - Preparations        10

1.2.2 - During Use        11

1.2.2.1 - Logging the Import Tool        11

1.2.3 - After the Import        12

1.3 - S1 Entities        14

1.3.1 - Missing Entities        14

1.3.2 - Missing Entities From .fgd        14

1.3.3 - prop_exploding_barrel        15

1.3.4 - func_tracktrain        15

1.3.5 - env_fire        16

1.3.6 - env_spark        16

1.3.7 - Ropes        16

1.4 - S2 Quirks        16

1.5 - Water        18

1.5.1 - Skybox Water Transition        18

1.6 - Cubemap & Light Probe        20

1.6.1 - Cubemap Blends        21

1.6.2 - Changing Cubemap Resolution        22

1.7 - Custom Sounds        23

1.8 - Models        24

1.8.1 - Porting Models        24

1.8.1.1 - cs_mdl_importer        24

1.8.1.2 - Manual Import        25

1.9 - SourceTS (new VScript)        25

1.10 - VIS        25

1.10.1 - Areaportals        25

1.10.2 - Changing Voxel Size        26

1.11 - Minimap        27

1.11.1 - Multi-layered Minimap        28

1.12 - Particles        30

1.12.1 - Patching the Particle Editor        30

1.12.2 - Particle Rendering        30

1.12.3 - Importing Particles        32

1.12.4 - Control Points        32

1.12.4.1 - Precipitation        34

1.13 - Items        35

1.14 - Skybox        36

1.14.1 - Skybox Clipping        36

1.14.2 - Recreating env_sun        36

1.15 - Applying ZR        37

1.16 - Level Systems        39

1.17 - Nav        39

1.18- Packing the Map with the Steam Workshop        40

1.18.1 - Packed Assets        40

1.18.2 - Uploading to the Steam Workshop        41

1.18.3 - Notes about the Steam Workshop        43

2.0 - Improving the Map        45

2.1 - Third-party Tools        45

2.1.1 - Source 2 Viewer        45

2.1.2 - CS2Fixes        46

2.1.2.1 - Setting up CS2Fixes Offline in Tools Mode        46

2.2 - Using S2 Entities        47

2.2.1 - Cinematic Cameras        47

2.2.2 - Cubemap Fog        47

2.2.3 - Lightmapres Volume        47

2.2.4 - Fog on Players        48

2.3 - Loading Screen        49

2.3.1 - Background Images        49

2.3.2 - Map Icon        50

2.3.3 - Custom Text        50

2.4 - Replacing Assets        50

2.4.1 - Textures        50

2.4.2 - Models        51

2.5 - Lighting        52

2.5.1 - Specular Lightning        53

2.5.2 - Stationary and Dynamic Lights        53

2.5.2.1 - Dynamic Shadows        53

2.5.3 - Light Entities        54

2.6 - Post Processing        56

2.7 - Movements        56

2.7.1 - Surf Ramps        56

2.8 - Textures        57

2.9 - Optimisations        58

2.9.1 - Reducing Map File Size        58

2.9.1.1 - Lightmap resolution        58

2.9.1.2 - Bake lightning on props        58

2.9.1.3 - Audio Quality        58

2.9.1.4 - Steam Audio        59

2.10 - Advanced Techniques        59

2.10.1 - Manual Import of Models        59

2.10.2 - Adjusting CSM Properties        61

2.10.3 - Adding Tree Sways on Foliage Props        61

2.10.4 - Creating CS2-compatible .svg        62

2.11 - Your Additions        63

3.0 - Examples of ported maps and their CSGO counterparts        64

3.1 - ze_antartika        65

3.2 - ze_chronus        66

3.3 - ze_ELEVATOR_escape        67

3.4 - ze_hidden_fortress        68

3.5 - ze_hypernova        69

3.6 - ze_PUTA        70

3.7 - ze_saw        71

3.8 - ze_STRANGE_escape        72

Changelogs        77


-1.0 - Urgent Information

This section was supposed to be a temporary section set up in response to the update on 5th December. However, the update on 14th December made porting new maps basically impossible (without applying a workaround at least). So this section will be set up in a more organized manner like the other sections in this guide.

As the contents of this section is vital for you to know, and since they are not really about procedures to take when porting a map, it will remain here with an awkward numbering of '-1'.

-1.1 - Import Tool Not Functioning

Since the update on 14th December, the import tool will simply not work. It now fails to read a CS:GO .vpk file, meaning the importer cannot import base CS:GO assets.

The current workaround is finding vpk.signatures in game/bin/win64, and have it named something else.

-1.2 - Missing Material Fatal Error

In an update on 5th December, Valve has set any missing textures present in a map (and hence substituting them as the error texture) as a fatal error of the game. As you can imagine, this will result in fatal shutdown on a live server as well, making the map totally unplayable both offline and online. This also occurs for workshop submitted maps.

The error message when loading a map with missing textures.

For reference, this is the current set up in the gameinfo.gi file, in which the key value of "ErrorMaterialIsFatalError" "1" is present. It is speculative about the reason why this was deemed necessary by Valve, however one thing for certain is that this requires the utmost attention when porting a map (at least for the time being).

The solution is simple - replace any missing textures from the map. This can be done relatively easily by loading the map in tools mode and inputting mat_print_error_materials into the console. As the name suggests, this command will print out the name of the materials that are encountering errors when the map is loading. You can then look for lines that end with [Error Resource] and hopefully identify the missing texture(s) you have.

If you want to test your map for missing materials afterwards, you can run the game without tools mode and load the map with map_workshop <addon> <map> in the console. With this you do not have to upload the map to the workshop whilst testing the map as if it was uploaded.

Update on 14th December 2023 and 7th February 2024: With this update, Valve has deleted some (presumably unused) assets in mirage and inferno. The Arms Race update has also deleted more CS2 assets. As you can imagine, this did cause some maps using these assets to crash after the update. With that in mind, this is a PSA that current stable ports can become obsolete in future updates in a similar fashion.


0.0 - Porting Guidelines

This is the porting guidelines as outlined by Source 2 Zombie Escape, which you may choose to follow when working on your own port.

  • Use as few textures from CSS/CS:GO as possible, only when there are no matches in CS2.
  • Take advantage of CS2/Source 2 graphical advancements, which includes but is not limited to: PBR textures, overhauled lighting entities and post-processing effects.
  • Improve the map where applicable, this could include visual or gameplay elements. A balance should be struck between the original map and the ported version, following the original mappers wishes and vision.
  • Compress the map to a reasonable degree, with lightmap sizes, cubemap scales, or other such methods. This is to prevent file sizes getting absurdly high and long download times.
  • If applicable, ports must include the various stripper fixes seen in CS:GO. Bug fixes should be applied, however, excessive gameplay changes are not necessary. Refer to the Github repositories for stripper fixes such as those by Mapeadores or GFL.

0.1 - Disclaimer

  • This guide is not meant to be read in one sitting - consider it more like a wiki where you can always come back and read about a topic you need help with.
  • This guide is made mainly for zombie escape maps, but it can be easily applied for other gamemodes as well. Do note that any gamemode specific setup's (e.g. timer zones in surf or kz) will need to be referred from other guides.
  • The guide is not a mapping tutorial - the guide will assume you know how to use S1 hammer + S2 hammer + importer tools already.
  • If you have to modify your game files or if you do not know what you are doing always add -insecure to launch parameters! You have been warned!
  • This is done by adding the launch parameters to shortcuts of the CS2 game and CS2 tools launcher.
  • If at any point you have to modify gameinfo.gi, you will not be able to join any secure servers (you can revert any changes made).
  • The guide assumes that you are porting a CS:GO map, although the process is still very similar with CS:S maps, just needing to also account for things that normally would’ve been done in the CS:GO port.

In the end, this is not the ultimate guide to porting and likewise you should not treat it as one. Not only are there new features added (or existing ones taken away) with every CS2 update, every now and then we are also discovering cool methods to exploit many of the new S2 features. And of course, there also may be errors that we did not spot when writing this guide!

If you do not understand some parts of the guide or if you have some suggestions, then feel free to join us in our discord and share your thoughts with us! We are always open to porters who want to create high quality ports for CS2.

0.2 - Useful Links

  • Mapeadores Stripper Github repository - Link
  • GFL ZE Configs Github repository - Link
  • Valve's basic guide on porting - Link
  • Archive of Rules of _p vmfs - Link
  • Another archive of Rules of _p vmfs - Link

0.3 - Useful Tools

  • BSPSource (S1) .bsp decompiler - Link
  • Crowbar (S1) .mdl decompiler - Link
  • Stripplier (S1) Stripper config .cfg applier - Link
  • GCFScape file extractor tool for .vpk files - Link
  • Source 2 Viewer & Decompiler (previously was ValveResourceFormat) - Link
  • Simple Level System prefab for CS2 maps - Link

1.0 - Mandatory Works

This section will list the minimum work required to have the map to be at a playable state for CS2.

1.1 - Stripper Configs

In S1, many Zombie Escape maps had serverside adjustments made to the map with strippers. Strippers were mainly used to fix issues within the map without having to compile the map for a new version.

When porting stripper-dependent maps to CS2, the modifications made by these stripper configs need to be implemented into the map. Not only is this required since a stripper equivalent feature is not present in CS2 (yet), but maps should never depend on strippers in the long-term since it is another file that a server has to manage for.

Fortunately, we have written a Python script that will make this process much easier. With the stripper applier, or Stripplier, any modifications made within a stripper config will automatically apply to a .vmf file. More information is written on the Github page, but to briefly describe its procedures:

  1. You provide a stripper config .cfg together with a .vmf and a .bsp of the map with the same name.
  2. You run the script and provide the name of the map.
  3. That's it!

TIP: All entities modified by the script will be given "strippered" "1" keyvalue so that you can easily filter for them via the Entity Report menu.

Make sure you check if all changes are correctly applied, save the .vmf file at least once, and the map should be almost ready to port.

Note: You can choose to implement stripper fixes manually, but naturally this is not recommended as this creates more opportunity for errors to be made.

1.2 - The Import Tool

Within CS2 files, Valve has included the tool necessary to port CS:GO maps to CS2. Instructions on how to set up and use the import script, and the fix-ups you should do to the ported .vmap is described on the dedicated page on VDC.

This section will present you with additional information you should know when using the import tool.

1.2.1 - Preparations

Before using the import tool, here are some points that you should watch out for and make changes in S1 hammer when necessary:

  • If you are using a decompiled .vmf you have to save the .vmf at least once in S1 hammer for the import tool to work.
  • Any broken connections (for example targeting entities with changing targetname), wildcard calls, and reserved targetnames that start with ! (e.g. !self, !activator, !caller…) WILL FAIL TO PORT. The importer will spit out a list of outputs it failed to import correctly, so keep an eye out for these during importing, or check them in S1 hammer beforehand.
  • These can be fixed by creating an entity with the exact same targetname. For example, you can create info_target's with the same targetnames as info_target is typically not a widely used entity and thus it is easy to filter for.
  • Some S1 legacy textures, such as HINT and SKIP, will be deleted with the import tool. This will also delete any func entities that use these textures.
  • Make sure to replace these textures on func entities (for example to NODRAW) before importing.
  • The import tool will create a duplicate mesh on top of func_wall and func_wall_toggle entities. This creates additional work for you especially if the map has a large amount of those entities.
  • You can temporarily change these to a func_brush, but make sure to take note of the Start Invisible spawnflag.
  • The importer VBSP does not properly cull map geometries when there are leaks in the (S1) map or when there are brush entities that has origin in the void. Not only should this not be happening in the first place, it also causes a headache for you later as any faces facing the void in the ported map will not be properly deleted.
  • Just like how it was in S1, there is no easy way to see where the problematic entities are, other than attempting to compile the map. Fortunately, a leak in the import tool VBSP will also generate a Pointfile to the leak, which you can open in S1 hammer.
  • Any surf ramps in the map will greatly benefit by turning all of them to func_brush beforehand. If you want to know why this is necessary then you can refer to the later section about surf ramps.

1.2.2 - During Use

The import tool is not exactly the most stable tool in the world, and can be prone to failures when porting a map. Here are some issues we have encountered, and solutions we have found to work reliably:

  • The importer dislikes some default CSGO skyboxes. HDR ones in particular may result in an error during compile. This can be fixed by simply changing the 2D Skybox the map uses before using the import tool.
  • The importer also likes to trip up on missing model textures. Each imported model will come with a _refs.txt file with all the textures. You will have to search through each one to find where the missing texture lies (use Notepad++ or some alternative to search through them en-masse).
  • Some dev/ textures may not import during compile. This can be fixed by simply importing them later on or replacing them with another texture. This can also be applied to anything the importer may not pick up on.

1.2.2.1 - Logging the Import Tool

Another caveat of the import tool is that it does not perform any logging, meaning you will lose all console outputs from the import tool after you close the console window. Furthermore, as Windows Terminal is limited to 9,999 lines of output, any outputs beyond the most recent 9,999 outputs will not be recoverable when the import tool completes. This is fairly troublesome as it may result in you missing out on important console outputs, which could help later when fixing the ported map.

Fortunately, you can use Windows Powershell to generate a log file of the import tool. You only need to add an extra argument to the importing commands, such that:

<Python import commands> | tee <name of log>.txt

where you would use the same commands for the import tool in place of the angular brackets. To launch Powershell, you can type 'powershell' instead of 'cmd' in the Windows Explorer address bar.

As a further example, the full command should be similar to:

python import_map_community.py "<s1 directory>" "<s1 contents>" "<s2 directory>" addon_name map_name -usebsp | tee output.txt

This will create a log file named output.txt within the directory where you have ran the import tool.

You will have to enter 'y' for a couple of times when an user input is requested. Do note that it will not always display a message asking for an user input, in which case you should still input with 'y' in the blank newline. When the importing process does begin, you can let the tool continue normally.

Note: The log text file will be overwritten if a same name is used every time the import tool is executed. To prevent any overwrites, you may choose to move the log file to the relevant addon folder every the import tool finishes running. Otherwise, you can give a full directory (starting from the volume) to the log file instead.

1.2.3 - After the Import

After the import tool finishes porting your map, you should follow these steps so that you have easier time making modifications to the map in CS2 hammer:

  • First and foremost, you save a copy of the imported .vmap. You may wish to refer back to the initial .vmap in the future and so saving a copy will prevent you running the import tool again.
  • The import tool will result with a main .vmap and a few _prefab .vmap's. You can collapse these prefabs in the main map - select everything in the main .vmap, and select Collapse All Prefabs via the F1 menu.

  • If the map has a 3D skybox, the skybox has to be moved to a separate .vmap file. The exact procedures to move your 3D skybox is provided within Valve's guide. Make sure to compile the 3D skybox map to have it in game as well.
  • All func entities in your map will have a duplicate mesh created at the world origin. You can safely delete these duplicate meshes.

Note: An env_sky entity is also created at world origin, so make sure you don't delete everything at the world origin. In fact, you should move the env_sky entity into your map.

  • All decals and overlays are converted to the new Static Overlay entity. Unfortunately, some static overlays can have incorrect orientations and/or scaling.
  • Until the import tool itself can be improved, you have to make the fixes manually. You should have the map open in S1 hammer so that you can quickly refer to the correct orientations/scale.
  • If your map has an env_sun, then skybox geometries will fail to block out the sunlight. This is because the skybox geometries are not part of the main map.
  •  The "official" solution as used in many official Valve maps is to copy the skybox geometries into the main map, adjust so that they have correct scalings and positions, and then change their textures to Block Light.
  • Any Alphatest textures in the skybox will simply not render in.
  • Simply change it to Translucent instead.
  • All outputs that did not have a parameter will be inserted with '(null)'. This may cause problems for output that do depend on the parameter, for example in math_counter InValue input where having a parameter or none both works.
  • Select all entities in your map and remove all (null) in the output parameter.

Note: We have listed more CS2 issues in our Github.

1.3 - S1 Entities

Many S1 entities do not currently work as intended in S2, or they are outright removed with S2. This section will highlight these entities and provide a suitable replacement if applicable.

1.3.1 - Missing Entities

There are quite a few missing entities in CS2 (compared to CSGO), here are a few common ones with their potential replacement

  • player_speedmod: no suitable replacement yet.
  • game_ui: no suitable replacement yet.
  • game_text: does still exist, but is completely non-functional due to the removal of VGUI; no suitable replacement yet.
  • point_viewcontrol: replaced with team_select for the team select background.
  • point_viewcontrol_multiplayer: no suitable replacement yet.
  • func_water_analog: water now works as a func entity with func_water and as a result they can now dynamically change positions. However, moving func_water only moves their collision and not the water texture itself.
  • A fix to this problem is to have a func_movelinear with its faces applied with the same water texture and placed at the same location, and have the func_water follow the func_movelinear.
  • Several particle based entities (env_steam, func_dustmotes, etc.) have been removed. These can be replaced with particle effects.
  • point_spotlight: can also be replaced with particle effects.

1.3.2 - Missing Entities From .fgd

Some entities are missing from hammer .fgd files, but they can be made to work again after substituting them from CS:GO. These entities are:

  • filter_activator_team
  • env_sun - this entity will be removed in the near-future. The current alternative method used by Valve is to have a 'sun mesh' in the 3D skybox at a very far away distance from the map origin.

The following section will explain how to re-enable filter_activator_team.

The entity is missing in hammer from base.fgd. The .fgd for this entity can be copied directly from CS:GO .fgd, or alternatively can be copied from below:

@FilterClass base(BaseFilter) size(-8 -8 -8, 8 8 8) = filter_activator_team :

        "A filter that filters by the team of the activator."

[

        filterteam(choices) : "Filter Team Number" : 2 : "The team number to filter by.  If the filter mode is Allow, only entities whose "+

                "team number matches the given team will pass the filter. If the filter mode is Disallow, "+

                "all entities EXCEPT those whose team number matches the given team will pass the filter." =

        [

                2 : "Terrorist"

                3 : "Counter-Terrorist"

        ]

]

For consistency, this block can be pasted in near other filter_* entities in the base.fgd. If you have no idea what this means and would rather play it safe, then place this block at the end of base.fgd.

1.3.3 - prop_exploding_barrel

The default model of this entity is currently missing in CS2, which causes the entity to not function correctly in game. We expect this to be fixed when the Danger Zone gamemode ships.

To fix the issue for now, you can manually import the barrel model with procedures as described in the model section. After the model (and the material) is manually ported, you have to place these assets in the exact same directory as CS:GO.

1.3.4 - func_tracktrain

The Orientation Style of Face the Direction of Motion needs some modifications in CS2. First, you have to create at least one more path_track before the corner, which will reduce the time the tracktrain turns around the corner. Then, set Change angles to Near path tracks so that the tracktrain turns at a gradual pace. You can refer to the screenshot of the configuration in hammer for a visual example.

This is a screenshot from ze_boatescape101’s .vmap with the aforementioned method.

1.3.5 - env_fire

The hurting mechanism works, but the particles do not show. You can fix this by replacing the particles directly with info_particle_system.

1.3.6 - env_spark

This entity does not work as intended. You can attempt to fix this by having the sparks on an info_particle_system enabled via a logic_timer, or using a looping spark particle.

1.3.7 - Ropes

If you have any path_particle_rope in your map, this will show as an obsolete entity in your map. Fortunately, the fix is easy as replaced them to path_particle_rope_clientside.

1.4 - S2 Quirks

These are some of the quirks that exist in the current version of CS2. Until CS2 is fully released (and realistically for a few years after release), you should not consider this list to be final. Any solutions to these problems are only suggestive, and should not be used for the majority of the cases (since Valve may patch these later). The list will be updated whenever necessary.

  • Players get stuck on water floors.
  • The best solution is to provide additional ladders / extend existing ladders so that they touch the water floors.
  • You can also try putting trigger_push near the water floors, however this may cause unintended effects.
  • Any AddOutput outputs that change a keyvalue of an entity will no longer work.
  • No good solution, other than to replace those outputs to those that work or to duplicate the targetted entity with the replaced parameters.
  • For example, for AddOutput's changing the teleport destination of trigger_teleport, the best workaround is to place a point_teleport at a desired location to Teleport the info_teleport_destination itself. Make sure to have the targetname of info_teleport_destination as the target of point_teleport.
  • Random teleportation target mechanism that used to work in CS:GO (having multiple info_teleport_destination with the same targetname) no longer works in CS2. Instead, change them into point_teleport's with !activator as its target, and change the trigger_teleport into a trigger_multiple. Then, create a logic_case and have each case targeting each point_teleport, and in the trigger_multiple have an output target the logic_case with PickRandomShuffle.
  • Some areas may be drawn in when they should not, including in cases when they are completely separated by the void. Refer to this section.
  • team_intro's will stop any music played during its cinematics - this likely would not be a concern on live servers.
  • func_movelinear with mp_solid_teammates 0 will kill colliding players if func_movelinear has block damage; if not, the entity will simply be stuck until players do not collide with each other
  • A potential solution is to use func_tracktrain instead.
  • Collisions on moving entities are fairly clunky, where it can result in players getting stuck. This usually occurs when a player collides into the front or the ceiling of the moving object, making then clip to the outside of the object.
  • As this is a default behavior of the game, there is not much that can be done other than to hope that a future update fixes this.
  • Any "explosion damage", i.e. having BLAST damage on trigger_hurt or any env_explosion that hurts players, can cause a crash on a live server. We do not know in full detail what the cause is yet as this crash is not consistent.
  • For trigger_hurt, you can replace the damage type to something else.
  • For env_explosion, see if you can replace the damaging mechanism with a trigger_hurt instead. Otherwise, there is no good alternative yet.
  • trigger_push appends its push force every tick - i.e. players within these push triggers are sent flying even with a seemingly low push force.
  • If you do not require a constant pushing effect, you can tick Trigger on Start Touch parameter for the push to be applied only on the tick when the player touches the trigger.
  • Else, you may have to replace recreate the effect manually by using a repeating timer with logic_timer.
  • trigger_gravity does not reset the gravity enacted on a player upon leaving the trigger.
  • If possible, create a separate trigger_gravity surrounding the area which resets the player's gravity (gravity of 1).
  • prop_door_rotating can be broken by a HE grenade.
  • Target an input on those doors with SetUnbreakable. This will come up as a broken output, but they do work in game; it is simply missing from the hammer .fgd.

Note: On a live server, most of these issues could be remedied with our metamod plugin CS2Fixes. To try to test your port offline with CS2Fixes enabled, refer to the section dedicated to CS2Fixes.

1.5 - Water

Water in CS2 is done by having the water mesh be a func_water. The texture configuration is still the same - only the top face has the water texture and the rest of the faces must be nodraw.

Note: If you are looking for a replacement for func_water_analog then refer to the section on missing S1 entities.

1.5.1 - Skybox Water Transition

If the map has a transition the main map and the skybox on a large body of water (e.g. to create a perception of 'infinite water'), then you will have to do extra work to make the transition smooth. The old S1 method of just aligning the textures will not work as effectively anymore.

In short, we will be making use of cubemaps, and changing the properties of the water texture for a gradual transition of the water into the skybox. More information about cubemaps and how to place them in the map will be discussed in the next section.

First, extend the water mesh in the main map by about 512 units beyond the skybox into the void, into directions where the water is in the skybox. For example, if the map is surrounded by water then you want to extend the water mesh in your main map into all four cardinal directions. The amount of units to extend is arbitrary - the deeper the extension the more gradual the transition will be.

Next, place at least one env_combined_light_probe_volume above the body of water in the skybox. This is to ensure that the skybox fade has a proper reference to refer to. Make sure that this light probe volume is near the water mesh in the skybox.

Finally, you have to edit the properties of the water texture in the Material Editor. Assuming that the texture has the correct water shader, the texture will have additional settings that can be modified under the tab of Map Settings. Within this tab, you have to change the values of Map UV Min and Map UV Max; these are the minimum and maximum coordinates (in x and y coordinates) of the water mesh in the main map. When in doubt, you can set these coordinates to some extreme values.

Example configuration of the water texture Map Settings properties

Afterwards, you have to play around with the other settings within the Map Settings tab until you observe a nice transition between the main map and skybox water textures.

Before and after comparison shots in ze_voodoo_islands

Note: You may notice some granularity in the transition. This is unfixable because of how transparency is projected in S2.

Note: If you need to have water transitions made at multiple locations (and heights) within your map, then you have to duplicate the water texture and change Map UV Min/Max to each individual cases.

1.6 - Cubemap & Light Probe

In S2, a new entity env_combined_light_probe_volume calculates light probes for object lighting and builds cubemap textures within a single volume. This entity is mandatory when making a CS2 map, as otherwise props, player models, and view models will be unlit (aside from dynamic light sources).

Normally, maps imported by the import tool will have few of these entities placed in the map. However, the placements made by the import tool are not optimal, so it is much preferred if you place these entities by yourself from scratch.

The placement is similar to how you would place env_cubemap in S1 - the white spheric gizmo should be placed in an open space about 64 units above the floor - the eye height of players in CS2.

The volume of env_combined_light_probe_volume is adjusted by moving the arrow gizmos for each axis. The volume of this entity does not have to follow the exact geometry of the enclosing areas, but do make sure the volume covers the enclosing areas completely.

The above screenshot is an example from ze_tkara’s .vmap. The white outlines show the boundaries of each volume. The blue box is a selected volume, where you can adjust the dimensions of the volume.

How many env_combined_light_probe_volume you need is entirely dependent on how much time you are willing to spend on them. As a general rule of thumb, you want to have at least one env_combined_light_probe_volume for every unique room, hallway, area, etc. Do note that cubemaps are one of the things that take most of your map file size. The resolution can be changed and will be discussed a bit further down in the guide.

Note: make sure to build your cubemaps at least once. Otherwise, any textures with specular indirect (i.e. cubemaps) enabled will show purple-hint and the map could be prone to crashing!

Note: If you want to just have either a cubemap or a light probe you can use env_cubemap_box or env_light_probe_volume respectively.

1.6.1 - Cubemap Blends

Unlike env_cubemap in S1, cubemaps in S2 can optionally be blended with other cubemaps, allowing for smooth transitions between different cubemaps. This is most noticeable on your viewmodel and shiny surfaces.

The extent of these blends are set with Edge Fade Dist parameter, where each input box represents the units from the edge of the volume in each dimensional axis where cubemap blending is enabled. Here is a section within Valve's wiki explaining more about cubemap blends.

Here is a screenshot from ze_hidden_fortress’s .vmap. It shows off the blended edges as mentioned above.

Note: Cubemap blending can be very expensive with overlapping cubemap blends you have on a surface. Use cubemap blending sparingly, only along edges where a blend is necessary, and try not to overlap more than 3 cubemap blends.

1.6.2 - Changing Cubemap Resolution

One of the things that bloats CS2 maps are cubemaps. If you are looking to reduce the file size of your map, this is the first thing you would want to work on.

To reduce the resolution of cubemaps, go to gameinfo.gi found in csgo_core/ directory. Search for EnvironmentMapFaceSize within the file, and replace the value with the resolution you desire, but do note that this must be in powers of 2 (32, 64, 128, 256, 512,...). For reference, the default value is 256.

Note: Changing this resolution may result in your game ignoring roughness on various textures. This also affects textures in official Valve maps as well.

1.7 - Custom Sounds

Every custom sound or music that you wish to add to your map now has to be defined as a soundevent in your custom soundevent .vsndevts file. This .sndevts file has to be located in content/<addon name>/soundevents/.

Before doing anything with the soundevent file, first you have to make sure that the sound files (.mp3, .wav) are located in the correct directory. This is not different from S1 however, you just have to ensure that all sounds are within contents/<addon name>/sounds/ directory.

Note: In CS:GO sound files were located in csgo/sound/ folder; notice the spelling difference between sound and sounds!

If you have created your addon via the tools launch menu, then an example .sndevts file called 'soundevents_addon.vsndevts' will automatically be created for you in the correct directory. Within this example file, you can find a few pre-defined soundevents that you may choose to modify or create new soundevents upon. This file also has detailed comments explaining some of key soundevent parameters, so you should take a few minutes off to read these comments. You will also find a list of all the dsp reverb presets should you want a different echo profile in your map, or perhaps switch between presets depending on the area.

Note: If you wish to hear your custom soundevents in hammer and in game, then your .vsndevts file has to be named soundevents_addon.vsndevts. Only soundevent files of this name is read automatically read by the game in addons.

TIP: If you cannot hear your custom sounds in hammer even if your soundevent file is named as soundevents_addon.sndevts, then double check if the syntax within the file is correct and that the sounds have actually compiled to .vsnd_c.

To play these custom sounds, simply create a point_soundevent entity which references a custom soundevent you have created. ambient_generic is now considered obsolete and should not be used.

TIP: You can set the volume of a soundevent higher than 1 to a maximum of 10. Don’t tell Luffaren that!

As a side note, in CS2 there are three different types of soundevents: csgo_mega, csgo_music, and csgo_3d. csgo_mega is a general soundevent type that you would use for the majority of sounds, csgo_music is specifically used for music, and csgo_3d for other general ambient sounds.

1.8 - Models

Any input that changes the animation sequence on a prop_dynamic will be broken, as the input has a slightly different name in S2. Make sure you replace these for any animated props you may have in your map.

1.8.1 - Porting Models

Sometimes, your ported map may be missing some models. This can happen due to the import tool failing to import a specific model, or the import tool simply did not recognize that the model is present in the map. In any case, this subsection will cover the different methods you can use to have these models ported successfully.

On a relevant note, a missing model can be seen with the default error model both in hammer and in game. Furthermore, the list of missing models in your map can be seen when compiling your map. Any missing models are shown with red error messages near the beginning of the compilation window.

1.8.1.1 - cs_mdl_importer

The import tool may not have properly imported some models that are present in your map; most notably any gib models that spawns from a breakable model. In this case, you can try using cs_mdl_importer.exe which is included with your game files. This executable can be called from anywhere if the importer is set up correctly, but if the importer is not set up correctly then you can find it in game\bin\win64 and run it directly.

First, you have to create a .txt file that lists all the models that you require importing in terms of their directory; e.g. in some format of models/some_folder/some_model.mdl. If you want to import multiple models at once, you have to list each model directories on separate lines. Once the list is done, simply execute the tool with the command prompt by using the command below:

cs_mdl_import -i <path_to_s1_csgo> -o <path_to_cs2_addon> -l <path_to_list.txt>

1.8.1.2 - Manual Import

If some models fail to import with either of the methods mentioned above, then you have to import the model manually. The detailed procedures are written in the later section.

1.9 - SourceTS (new VScript)

Note: With the arms race update, Valve has enabled use of a new scripting language using Javascript/Typescript. The previous version of this section describing the old VScript using Lua, and patching it for unofficial support has been deleted.

This update seems to have brought a bunch of content for map-based scripting, which evidently means this section will be rewritten, adding more guides and tips as we learn more about it.

1.10 - VIS

As you may know already, how visibility works in CS2 is completely different. In CS2, VIS is calculated by using voxel and these voxels are then merged into "chunks". These chunks then determine the visibility a player can have.

Unfortunately, the new VIS may introduce new problems to your port, especially if your map has multiple isolated areas. If you have compiled your port at this point, you may have noticed that you can see objects through the skybox when you should normally not be seeing them.

If the object that is drawn through different areas is small (i.e. a single mesh or something similar), you can disable Mesh Merging in the object's properties window. This is done because all static geometries (including meshes, props) are merged into chunks primarily by VIS, but other factors, including materials, can merge geometries that are largely separated from each other as well. Thus by specifically disabling Mesh Merging we can skip this behavior and force the object to not merge with other objects.

Note: This usually works best with individual objects. If you have an entire area displaying through the skybox, then you should continue on to the next subsection.

1.10.1 - Areaportals

func_areaportal and func_areaportalwindow do not exist in CS2 anymore. As such, hiding certain areas (e.g. behind skybox) is now extremely problematic.

The current solution to areaportals is to manipulate VIS blocks so that a line of sight is blocked between the current area and the area you want to hide. For this, we use visibility_hint entity to cut VIS manually - we can define the Hint Type to specify what kind of operation a visibility_hint should do:

  • [x, y, z]-axis: cut VIS along an axis.
  • Higher resolution [8 units]: increase the resolution (i.e. have smaller voxels) within the volume of visbility_hint.

A configuration that we think works the best is to have two visibility_hint's that cuts VIS blocks along an equal axis, and have another visibility_hint around the area where the axis-cut visiblity_hint's are placed. These should usually be placed perpendicular to the direction of your map's gameplay; think of how you would use areaportals in S1.

Note: Unfortunately, VIS is something that we do not completely understand yet. If you think that you have a better solution then please do let us know!

1.10.2 - Changing Voxel Size

If your map has many large areas (and we mean large, like areas spanning couple of thousands of units) then you may have already noticed that the duration of VIS compilation takes an extremely long time. This is because the default voxel size for VIS compilation is at 8 units, so maps with large areas will have more voxel volumes to calculate for.

Fortunately, an entity exists where you can dynamically set the VIS voxel size within a specified volume, using visibility_hint. The method of operation works similarly to a lightprobing volume, where you can change the volume by dragging the gizmos in each axis. Then within the entity properties window, you are able to set the Hint Type which you can then change the resolution, or reversely equivalent the voxel size within the volume. The range extends from voxel size of 8 (default in CS2) to 256.

To change the voxel size in the entire map, simply create one visibility_hint that encompasses the map. Although the compiler may show the default voxel size of 8, the hint will work properly when projecting the compiled vis later, and the hint voxel size should also show in the compiler as well.

TIP: We recommend values of either 16 or 32, as these values have worked well from our experiences. Going further than this number may introduce more VIS issues.

A consequence of having higher voxel size is that you may introduce new VIS issues between different areas. To avoid this, make sure areas are being separated by no less units than the VIS voxel size; e.g. a 20 unit gap between rooms when using 32 voxel size would be bad.

1.11 - Minimap

Creating a minimap in CS2 is fairly "automatic", in a sense that the entire process of creating minimap files is done by the tool. However, you still have to do some extra steps to ensure that the minimap is displayed correctly in game.

Before generating a minimap, you first have to create cs_minimap_boundaries at two opposite boundaries of your map so that the volume within these two entities covers your entire map. For example, place one at the minimum coordinates, and one at the maximum. The selection volume from these two entities should cover your entire map.

To generate a minimap, you can tick compile minimap on load parameter in the compilation window, and run your map from hammer (or build if cs_minimap_boundaries's are not yet present in your map). Alternatively, you can generate a minimap in game by typing minimap_create in console.

Note: The resolution of minimaps can be changed by putting cs_minimap_create_output_size x in console, where x is the resolution that you want (default is 512). Do note that the maximum resolution of the minimap generation is limited to your current game resolution.

The minimap texture is saved in content/<addon name>/panorama/images/overheadmaps/<map_name>_radar.tga. However, the minimap material has to be made into a Valve texture and also needs some additional parameters to have it properly displayed in game.

Create a new Generic or a Csgo Composite Generic material in the Material Editor, and save the material in the same directory and the same name as the raw minimap .tga file. Next, import the minimal .tga as the color texture. When using the Generic material, you have to toggle on the Translucent parameter in the left hand side menu. Save the material and compile it. If you navigate to your addon folder in game/ directory, you should find the compiled minimap texture there.

TIP: You can create radars with transparent backgrounds when using the Csgo Composite Generic material, but an alpha channels needs to be established in the minimap image.

Note: If you do not see either materials in the list, tick “dev shaders” at the bottom.

If the minimap was compiled successfully, then you may realize that the compiled materials are given a unique suffix. You have to delete this suffix so that the name of the compiled material becomes <map_name>_tga.vtex_c.

If you now run your map in game, you should see the minimap displayed correctly.

Note: You may have to restart your game for the minimap to be properly displayed.

1.11.1 - Multi-layered Minimap

For more complex maps, it is likely that the map will have overlapping areas across different heights, which may necessitate the use of a multi-layered minimap. Fortunately, this is still supported in CS2 and the process of generating one is not much different than from CS:GO.

In short, you have to generate a minimap image for each desired layer, and define these layers in the .txt file under game/csgo_addons/<addon name>/resource/overview/. This text file will have the same name as your map.

First, follow the steps in the previous section for a single-layered minimap, and generate the aforementioned text file. This step will automatically calculate the minimap positioning and scaling based on the cs_minimap_boundaries's you have placed in the map. If you have verified that this text file has been generated, then you can carry on to the next step.

Note: This initial minimap generation must include the entire map in the x-y plane - i.e., you cannot adjust the minimap positioning and scaling for each layer.

Next, the actual minimap image for each layer will need to be generated. Navigate to this text file, and add the following at the end of the first block:

"verticalsections"

{

 "1"

{

"AltitudeMin"            "-16000"

"AltitudeMax"            "x"

}

"2"

{

"AltitudeMin"            "x+1"

"AltitudeMax"            "y"

}

//repeat until…

"n"

{

"AltitudeMin"            "z"

"AltitudeMax"            "16000"

}

}

Each block inside the “verticalsections” will be the layers you want to generate; you have to find the minimum and maximum altitude values manually. These layers are ordered in the ascending order, and any overlap of ranges is not tolerated (notice x+1 for the minimum value for layer 2). The numbering of layers 1, 2, …, n is just an example - it will not make any difference if the naming is changed.

Note: You should aim to use the least number of layers possible. The minimap images are fairly large in file size, and having many layers will bloat your port unnecessarily.

Now, do a generation of the minimap via the compile window or the in-game console command. If done correctly, the minimap image for each layer will be generated in the content folder. All that is required at this point is to create a .vmat file for each layer, do the compiling, and remove the unnecessary suffix on the compiled material.

1.12 - Particles

This section will be dedicated to using particles in your port, and how to manipulate them with the CS2 Particle Editor.

1.12.1 - Patching the Particle Editor

Although the Particle Editor has been part of the CS2 tools since the limited beta, it is unfortunately locked away by Valve for an unknown reason.

Fortunately, it can be unlocked easily by modifying your game files. The Particle Editor can be enabled by editing game/bin/sdkenginetools.txt where you find the Particle Editor entry and remove the following 4 lines:

        m_ExcludeFromMods =

[

"csgo",

]        

Note: Just like with VScript, there could be a strategical reason from Valve why the Particle Editor is locked away.

Note: Particle Editor requires a whole new guide of its own. If you need a tutorial about using the Particle Editor, then this video of the S1 particle editor may be a good starting point for you. The new particle editor has significantly more features in comparison, the vast majority of which completely lack documentation.

1.12.2 - Particle Rendering

Particles and particle systems remain relatively the same as in CS:GO. However, particles in CS2 make use of OIT (Order-independent transparency) sorting, which unfortunately cause heavy performance drops when looking at even the most simple particles.

Fortunately, enabling certain particle properties in the Particle Editor (which needs patching to use them) can greatly improve performance for a little to no impact to the visuals of the particles.

Before continuing on, you may want to look at the visual difference between enabling depth feathering on a particle - they essentially enable particles to blend more naturally with the world and minimising abrupt cut-off's.

Showing the difference between depth feathering disabled and enabled on a particle.

For now, there are four distinctive configurations that you can have on a particle:

  • Default (i.e. no properties enabled): this is the current configuration particles in CS2 have. It is the most heavy on performance.
  • Game overlay pass (enable Only Render in effects game overlay pass): this property provides the maximum uplift to performance. Unfortunately, this will render particles in front of smoke (from the smoke grenade), and will not support depth feathering.
  • Mixed resolution rendering (enable Use Mixed Resolution Rendering): this provides a medium uplift to performance, somewhere in between default and game overlay pass. This however will render correctly through smoke, and support depth feathering.
  • Bloom pass (enable Only Render in effects bloom pass): this property also provides the maximum uplift to performance, and unlike the default settings it can properly display through smoke and support depth feathering. Unfortunately, it is unsuitable for darker colored sprites due to the bloom effect.

For Zombie Escape, it is extremely unlikely that a smoke grenade will ever be used within the map. Thus, almost all particles should make use of game overlay pass if depth feathering is not an issue. If not, you should prioritise using bloom pass and then mixed resolution rendering if the particle also happens to be dark. For other game modes, using mixed resolution rendering is recommended.

Note: This can only be done on custom particles; you cannot modify base CS2 particles, unless they have been extracted using Source 2 Viewer.

Note: The list above is not a definitive list. There may be better configurations that we are simply not aware of yet.

1.12.3 - Importing Particles

With one of the recent updates, the import tool is no longer able to import particles. This means that any particles that your map used in S1 cannot be imported yet using the import tool. For now, there are a couple of methods you can try.

The first is to replace particles with ones that are provided with base CS2. Just be aware that some particles do not work as they are simple direct import from CS:GO.

The second is to use an older version of the import tool (not recommended), or to use a third-party import tool such as kristiker's source1import. Note, you should still use Valve's import tool to port your map, and use this third-party tool to import particles only. The material of the particle will not be properly imported, and so those textures will need to be converted for S2 manually.

The last option is to remake particles completely from scratch with the Particle Editor. Unfortunately, this is not an optimal solution as making particles is not particularly easy (and tedious), and as of now Particle Editor is locked away by default.

1.12.4 - Control Points

Control points offer a powerful method of manipulating properties of a particle from the same system. Although control points are not new with S2, they now have the ability to accept inputs from control points to modify the particle system, such as their spawn rates or colors. In other words, control points offer an upgrade from S1, where in S1 a particle had to have multiple copies for minuscule changes.

The following example below is our recreation of func_dustmotes in CS2 as a particle. At the fundamental level, this particle has the initializer of ‘Position within sphere random’, emitter of ‘Continuous emitter’, and renderer of ‘Sprite renderer’. In the Particle Editor, we are able to modify some properties of the particle to take in values from a control point.

In this example, the x-axis of CP #2 controls the radius of particle generation, y-axis of CP #2 controls how many particles are generated per second, and CP #3 allows tinting of particle colors.

In hammer, using info_particle_system in this instance, we are able to define the control points we wish to use and give corresponding values. Note, how the same particle system has been used in both info_particle_system.

We input the control points and the corresponding values to customize the same particle with different properties.

After a quick compilation, we are able to see the clear differences between these two systems as shown in the screenshot below:

Two different particles using the same system.

Naturally, these are not the only properties that can accept control points, which further highlights the true power of them in CS2.

1.12.4.1 - Precipitation

As mentioned previously in the section about missing entities in S2, many func entities that use particles are no longer supported in CS2. As you may expect with our replacement for func_dustmotes above, Easter has created a prefab of many particle systems (amongst others) to replace more missing entities.

Example use of rain particle prefab and its modification for snow in our ports.

1.13 - Items

Items can sometimes be crucial for the map flow of Zombie Escape maps. It is a mechanism that is simple to implement, and yet can bring big variety between each run depending on how the items are used. This section will introduce some issues exclusive to CS2, and the solutions regarding them.

TIP: Make sure that the items are imported correctly! Broken outputs are fairly common in items, and remember that the import tool does not handle them correctly.

func_button kills teammates on moving objects

For some unknown reason, players that “collide” with a func_button on a moving object, specifically func_movelinear, will cause collision damage upon them.

You can replace any func_movelinear which players have to stand on into a func_tracktrain instead.

Item holder cannot see the item

This is because the items are attached to you, and since the textures on the items are not using the character shader they will become invisible to the item holder.

As you may have guessed, the fix is creating a duplicate texture that the item uses, and setting them to use Csgo Character shader.

Playing sounds on the item

As ambient_generic is obsolete, a new method is needed to play sounds on items.

You can use snd_event_point, and have the Source Entity Name point to the func_physbox. Note, you should not target the weapon itself.

Placing grenades in the map

Due to an oversight within the game itself, any grenade that is picked up by a player will not be intractable unless scrolling through the entire inventory.

Create a new key with String Property Type in the Object Properties menu of the grenade, and insert subclass_name as the key. The value for each grenade is listed below:

        43        Flashbang

44        HE grenade

45        Smoke grenade

        46        Molotov

        47        Decoy

        48        Incendiary grenade

1.14 - Skybox

Skybox has seen some changes in the transition from CS:GO to CS2. This section will highlight some of the crucial changes.

1.14.1 - Skybox Clipping

Unlike S1, skybox textures are no longer solid - players are now able to fall out of the map through any skybox faces. This unfortunately is not a good behavior for Zombie Escape, since unlike the base game, zombies are often capable of reaching these areas via knockback boosts.

Fortunately, it is rather easy to add clips to all skybox faces. Simply select all faces with skybox texture in face mode, copy paste them, and change their texture to a clip texture.

1.14.2 - Recreating env_sun

With the removal of env_sun from .fgd, the Sun has to be replaced by a mesh placed inside the map instead. This was an intentional change made by Valve, as how env_sun generated its effects were expensive, and they realized a simple sun mesh in the skybox was an adequate replacement with some bloom in post processing.

Note: It is recommended to create the Sun mesh in the skybox. Due to the large scaling of the skybox compared to the main map, the skybox will be better at recreating the far perceived distance of the Sun.

First, create a circular mesh at the world origin. Then, copy the angle keyvalue from light_environment and apply it to the mesh. At this point the mesh is rotated 90° off from the desired angles.

Switch to local coordinates, and rotate the mesh until the arrow from light_environment is perpendicular to the mesh. If done correctly, the orientation between the light_environment and the mesh should look like the screenshot below.

The desired orientation between light_environment and the mesh.

You can now drag the mesh to the very edge of the map. Simply replace the mesh texture to a suitable material; many materials that have ‘sun’ in their name are a good choice. At this point, you should experiment with different materials, having multiple stacked meshes, and or changing the scale to create the Sun that looks reasonably good.

Note: Although it is possible to have these meshes beyond the hammer grid, it is recommended to have them within. Some transparent materials (to recreate the sun glare for example) may not display properly if placed beyond the grid.

1.15 - Applying ZR

With the remake of the Zombie:Reloaded plugin into CS2 with Zombie:Reborn, a new feature has been added that allows mappers to disable (and re-enable) zombie respawns at will, typically with a 'nuke' at the end of the map. This replaces the old trigger_hurt based automatic “repeat kill detectors”, which were often vulnerable to false positives.

To modify zombie respawns, create an additional output on whatever entity that triggers the nuke such that:

Action: <OnWhatever>

Target: zr_toggle_respawn

Output: choose one output listed below:

Disable        - disable zombie respawn (does nothing if already disabled)

Enable        - enable zombie respawn (does nothing if already enabled)

Delay: you can have whatever value here for the delay of the output.

Note: Trigger output still exists for legacy purposes. However, there have been instances where the Trigger output would unintentionally re-enable zombie respawns, such as when triggered via a trigger_once. Thus, it is not recommended to use the Trigger output.

It is very important to not miss this step! If this is not set up correctly, then zombies will infinitely respawn in a loop on live servers, which will make your port unplayable.

Note: A map may have multiple ways of triggering the nuke; make sure this output is added to all such entities!

TIP: A possible way of testing zombie respawn toggles offline is to create a logic_relay with the same name of zr_toggle_respawn in your map. Within this relay, you can add an output that prints to console / chat whenever zombie respawns is modified. Make sure you delete the relay before publishing your map though, otherwise your messages will still print on live servers.

TIP: With this new feature in ZR, it would technically be possible to enable zombie respawns again by using the same outputs and continue to toggle as many times as you desire. Perhaps you can use this feature to implement a unique ZE gameplay into your map?


1.16 - Level Systems

In many Zombie Escape maps, a level system may be present which divides the entire map into smaller segments. This allowed maps to have a sense of progression and to prevent maps being tediously long for average players to play through. In S1, a level system was made from various of methods - using tricks with permanent entities, using VScript, or using the notorious physics based system.

In S2, we have found another system that is much cleaner to use, and easier to understand for more novice mappers. Essentially, the new system exploits the fact that any entity in the skybox map (that is usually not permanent) becomes permanent - any information that is stored in an entity is kept throughout all rounds.

We exploit this fact and create a math_counter in the skybox which stores the progression of levels. For every new round, we force the math_counter to output its value to a logic_case, which in turn relays outputs to set up the desired level. A prefab to the skybox level system can be found here.

We really encourage mappers to use this new level system, or to replace existing ones in ported maps. This system is much more intuitive to understand and as such is less prone to mistakes. This system also does not require you to understand VScript or advanced entity works, and isn’t susceptible to random breakage.

1.17 - Nav

Note: It has been discovered that having an improperly built nav mesh has a great potential to lag out on a server, especially at a higher player count and/or in a large enough map. As both conditions are true in majority of Zombie Escape maps, we recommend you to not compile a nav mesh at all - having a nav mesh does not make a difference on a live server.

Unlike S1, a .nav is not generated automatically when the game detects that your map is missing a .nav file. Instead, launching maps without a .nav file in CS2 will do absolutely nothing; no bots will be able to spawn into the map.

To generate a .nav file, you need to place at least one point_nav_walkable near player spawns. If there are multiple spawning areas, then you have to make sure to have at least one point_nav_walkable per spawning area. Do note that this is the absolute minimum required to compile nav.

1.18- Packing the Map with the Steam Workshop

With the release of the Workshop for CS2, having all assets of the map packed, and sharing the map with other players have become easier for mappers.

For some mappers, uploading maps to the Workshop could already be familiar from CS:GO. For Zombie Escape (and likely other community gamemode) mappers however, this will likely be their first time using the Steam Workshop. Whatever your familiarity with the Workshop may be, this section will introduce how to upload maps to the Workshop and explain which assets are automatically packed with the upload.

1.18.1 - Packed Assets

When you upload a map addon to the workshop, the file gameinfo.gi, which is located in game/csgo/, will dictate which paths within your addon game folder are whitelisted - i.e. which paths will be automatically packed into your map.

In the default configuration, files in these directories are packed (i.e. "include"):

maps

cfg/maps

materials

models

panorama/images/overheadmaps

particles

resource/overviews

scripts/vscripts

sounds

soundevents

lighting/postprocessing

postprocess

addoninfo.txt

Files in these directories are not packed (i.e. "exclude"):

        maps/content_examples

Although the whitelist list is pretty comprehensive, it does miss out on couple of paths that may improve the quality of the map. For example, in the current default configuration, any files required for the loading screen will not be packed.

As you may have guessed, you can add new lines, edit or delete existing lines to make modifications to the whitelist. Carrying on the example of loading screen files, you will be able to pack those files by changing "panorama/images/overheadmaps" into "panorama". Do note that all paths has to be relative to the game folder of your addon.

Here are some noteworthy mentions when uploading to the workshop:

  • Soundevents need to be named as soundevents_addon.vsndevts in order to play any custom sound events you have made. If you are unfamiliar with soundevents, refer back to the section about having custom sounds in your map.

1.18.2 - Uploading to the Steam Workshop

After the final compilation of your map, and after you made sure everything is working correctly, you will be uploading the map to the steam workshop so that it becomes public for other players to play on.

Fortunately, the steam workshop is very streamlined and easy to use, with an added advantage that as a mapper uploading is really all you need to do - distribution of files are done automatically by the workshop. With that said, let us go through the steps of uploading a map to the steam workshop.

In the asset browser, look for the 'Counter-Strike 2 Workshop Manager', or click on the logo as shown in the image below.

If the manager pops up, you would have to create a New Submission to upload your addon. After the pop up page for a submission opens up, you can now select the addon you want to upload, and give some descriptions about the map. Don't worry if this page seems a bit barebones to you (becaust it is), you will be able to edit your submission once it has been uploaded.

Example submission of ze_sorrento_escape_p

Some notes about each field:

  • Preview Image: This is the image everybody will see when browsing through the workshop, and the first image that is shown on the map workshop page. You can add more images later after the submission is uploaded.
  • Upload Size: This will display the contents of your map and their respective sizes.
  • Game Mode Tags: This is mainly for the search filter on the workshop browser, but it is recommended to set this as 'Custom' for completeness.
  • Visibility: This will obviously depend on what you or the original mapper intend to do with the port, but 'Public' is the recommended option here.

Note: You can edit these settings later via the workshop manager.

After the addon has been submitted, a steam moderator will then review your submission. This can take any time between a few minutes to a day. In most cases this will just be an extra waiting time you can spend treating yourself a nice cup of coffee, or finally the time to clean your room for once.

Note: During this review period the visibility of the submission is automatically set to 'Hidden', so any other people with the link to your submission will not be able to see or subscribe to your submission.

TIP: Any edits that you make to your submission will require another review - this includes minor things such as changing the description or adding a few more images. You do not have to wait until a review is completed to make edits to your submission!

Note: The steam workshop moderation is actually fairly lenient, provided that you follow Steam's rules and guidelines.

Assuming things go well, you are done! Your submission would have passed the review and the visibility will be set back to whichever you have chosen when submitting.

1.18.3 - Notes about the Steam Workshop

If you are familiar about uploading to the Steam workshop already, then you can skip this section. For Zombie Escape mappers however, you should be aware of these difference between the old distribution method (FastDL) and the Steam workshop.

Take these considerations with a grain of salt though, as some are about running maps on a server, but nonetheless are things a mapper should be aware of.

  • Version control: The uploader of a submission will have access to revert to a previous version of the submission. This is useful when the updated map has a major bug that affects the playability of the map. However, this feature is only given to the uploader, and as such is very limited. If you are the uploader then be very careful whenever reverting to an older version as this affects all players and servers subscribed to your submission.
  • Server contents: With the possibility of multi-addons loading on a server, servers can now load maps alongside their own asset addon. However, server owners can still choose to create their own modified map addon based on your work, for example for the reason of stricter version control.
  • Map vs. Addon: Whenever you upload a submission to the workshop, you are uploading the entire addon and not just the map. If you have multiple maps that share the same assets, then theoretically you will be able to upload multiple maps into one addon. The practicality of this has not been experimented yet, so for now you should avoid doing this.
  • Dependencies: As Zombie Escape development matures, we could be expecting a return of various quality of life plugins such as entwatch, boss HUD, or even stripper. If you assume a similar architecture to CS:GO, then any dependent config files will have to be distributed by other means, likely using third-party file distributors (i.e. like how it was in CS:GO). This is far into the future though so again, take it with a grain of salt!
  • Uniqueness: Since each workshop submission is given an unique ID, it is now possible to have multiple maps of the same name. You should generally avoid doing this though for the reason of future proofing.

2.0 - Improving the Map

This section will cover how you can further improve the map to make sure you use the most out of the new S2 features, and overall make the map more pleasing to look at.

2.1 - Third-party Tools

As CS2 modding matures more and more, many useful tools and programs have been created to aid mappers (and porters alike). This guide will briefly cover the highlights of some CS2 tools, although as you may guess this guide will not do justice in showcasing the full capabilities of the tools that are introduced here.

2.1.1 - Source 2 Viewer

Source 2 Viewer is a powerful tool that allows you to browse VPK archives, view, extract, and decompile Source 2 assets, including maps, models, materials, textures, sounds, and more. This open-source project is based entirely on a reverse engineered effort as there is no Source 2 SDK.”

As stated in their introductory message, Source 2 Viewer is an extremely powerful tool that will likely accompany you in all mapping and or porting projects that you may do. When compared to S1 tools, it is essentially a combination of BSPSource (decompiling for .vmap and embedded assets), GCFScape (view and extract within a .vpk file), VIDE (view entity lump information), and more. Although the tool currently does not have extensive documentation (for mappers), the tool itself is very intuitive and easy to use.

Here are some instances where you may use Source 2 Viewer for your port:

  • Decompiling and extracting assets from CS2 game files (pak_dir.vpk found in game/csgo/) and custom workshop maps.
  • .vpk for workshop maps can be found in Steam/steamapps/workshop/content/730/<workshop_id>/. The workshop id can be found in the URL of the map’s Steam Workshop page.
  • You can also view the embedded assets within the tool itself.
  • Look at irradiance.vtex_c of a map (found under maps/lightmaps/) and fix any exceptional lightmap usages.

Irradiance of de_mirage in the closed beta before the lightmap was optimized. Notice how a few meshes takes up a good chunk of the lightmap, which reduces the available lightmap space for the rest of the map. (credit: @Angel in S2ZE discord)

  • View folder ordering within a compiled map, such as looking at the folder ordering and the required name formatting of the images used for loading screen background images.
  • Visualize a .vpk as if you have opened the corresponding .vmap in hammer, and the ability to look at entity lump information.

2.1.2 - CS2Fixes

Although CS2Fixes mainly acts as the fundamental plugin to run Zombie Escape servers, it offers many features that porters can use. You can find the detailed documentation for mappers on our github page.

Note: Although tempting, you should not use these features when creating new maps. These features are only implemented to be a community fix for many features that CS2 does not support anymore.

2.1.2.1 - Setting up CS2Fixes Offline in Tools Mode

Likewise, the installation guide of CS2Fixes can be found on the main github page. However, running the game in tools mode will simply crash when loading the Workshop Tools.

The fix is simple - create a folder such that content/csgo/addons/metamod/ exists.

2.2 - Using S2 Entities

2.2.1 - Cinematic Cameras

These new entities can be placed in your map to give more cinematic views during various phases of a game match: team_select, counterterrorist_team_intro, terrorist_team_intro, and end_of_match.

We rcommended for you to use team_select (replaces point_viewcontrol). This is because if team_select is not used, the team selection camera centers to the world origin, which may be in the void depending on the map.

end_of_match shows a 'MVP' screen similar to panorama CS:GO end of match screen - this is not mandatory as some servers may choose to skip this screen and move to the next map early.

Do not use any team intros cameras. These may interfere with maps that play music early in the round, and are unlikely to work properly in Zombie Escape servers with 64 players. In fact, due to the issue it causes with music, the intro cameras would most likely be disabled on live servers.

The character placements shown in hammer are exactly the same in game.

2.2.2 - Cubemap Fog

As a complimentary entity to env_gradient_fog, env_cubemap_fog creates fog within the skybox, which provides a nice blend between the world and skybox. The parameters are similar to that of an env_gradient_fog except that this entity calculates color directly from the skybox.

You can check ze_antartika comparison shots to see this entity in effect.

Note: env_cubemap_fog does not give fog to the skybox texture itself.

2.2.3 - Lightmapres Volume

The player light map resolution texture, 'tools/playerlightmapres', is a mesh entity texture that increases lightmap resolution to faces within and around the lightmapres volume. This is a nice way to have sharper light resolutions within playable areas where they do matter.

Note: Areas further away from lightmapres volumes will gradually have lower lightmap resolution - either create volumes for all playable areas or use none at all.

2.2.4 - Fog on Players

If your map has heavy fog, you may have noticed that the fog does not apply to players, or at least that the fog does not apply as heavily.

Fortunately, an entity exists where you can change the visibility settings applied on players with env_player_visibility. Below you can see the difference the entity can make in a fog heavy map.

Left: Default player visibility settings in a fog heavy map. Right: Adjusted player visibility settings with bots at the same locations.


The recommended values for each settings are:

  • Player Visibility Postprocessing Strength:        0
  • Player Fog Distance Multiplier:                        1
  • Player Fog Max Density Multiplier:                1

2.3 - Loading Screen

Although adding custom contents to your map's loading screen is not a new feature, some work needs to be done to have them working in CS2.

2.3.1 - Background Images

Having your custom images displayed in the loading screen works differently in S2, because you have to compile your images before they can be used in game.

First, place your custom image into content/<addon name>/panorama/images/map_icons/screenshots/1080p/. In the Material Editor, create a new Csgo Composite Generic material, and set its color texture with the screenshot image.

Note: If you do not see the Csgo Composite Generic material, untick 'show recommended materials' and tick 'show dev materials' at the bottom of the texture types menu.

After everything is set up correctly, you can save the material under the same directory but following a strict naming format of:

<map_name>_png                or        <map_name>_1_png (up to 9).

As the naming format suggests, you may have up to 10 custom loading screen images.

Note: Unlike S1, you have to have at least 2 images to have them display consistently throughout all map loads. If you provide only one image, the game will inconsistently display your image because the game chooses from all possible 10 loading screens it can load with.

You can compile the materials and see if the image is compiled with .vtex file suffix in game/<addon name>/panorama/images/map_icons/screenshots/1080p/. If the compiled image is not found in the directory, then you should double check if you have followed the previous steps correctly.

If the images were compiled successfully, then you may realize that the compiled materials are given a unique suffix. You have to delete this suffix so that the name becomes equal to what you have saved the original material with.

TIP: When loading a map, the right-hand side of the screen will be used to display map information; in other words, the right-hand side of an image is relatively hidden in the loading screen.

2.3.2 - Map Icon

Fortunately, implementing a custom map icon follows the same step as in CS:GO. If you have the .svg file ready, then all you have to do is to place it in content/panorama/images/map_icons/ folder. The name of the .svg should not be changed - i.e it is still called as 'map_icon_<name of map>.svg', where you would replace the brackets with the name of your map.

Afterwards, you have to compile and check that the compiled svg .vsvg_c file is generated in the game/ folder. The .svg file can be force compiled in the Asset Browser.

Note: If you are creating a new .svg, or otherwise have difficulties displaying the .svg properly in the loading screen, you should refer to the section on creating a CS2-compatible .svg.

2.3.3 - Custom Text

Likewise, adding custom map loading text is the same as in CS:GO. The text .txt file does not need any compilation however, and can be directly placed in game/maps/ folder as '<name of map>.txt', replacing the brackets with the name of your map.

Note: As of writing this guide, HTML formatting does not work.

2.4 - Replacing Assets

A good trick to know when using the Asset Browser is that only native CS2 assets can be seen by filtering for csgo in the addon filter menu.

2.4.1 - Textures

To reduce the filesize of the map, you should try to replace textures to base CS2 textures. Likewise, the new CS2 textures make use of new PBR features and as such are at a much higher quality. Replacing textures can done by finding similar substitutions. Unless it is a texture that is extremely iconic, not many people will recognize the differences.

In certain instances, CS2 may already have the equivalent texture to an imported texture - these textures can be seen in the Asset Browser by filtering for the Overridden Asset and Read-Only Asset tags, as seen below:

Unfortunately, your map will be using the imported texture meaning the map would be unnecessarily bloated. These duplicate textures have to be deleted by using the filters explained above.

Check out the comparison shots in ze_antartika and  ze_PUTA for a visual example of changing textures to CS2 ones.

2.4.2 - Models

A similar explanation follows to the reason why models should be replaced with CS2 models; it is very likely that the imported models from CS:GO are at a lower quality than native CS2 models. As such, you can use the same filters as above to look for any duplicate models in your addon. Naturally, same exceptions apply - iconic models (e.g. mako reactor) should ideally be kept.

All imported foliage models, however, will lose support for env_wind sways. These should be all replaced by CS2 foliage models. However, not all CS2 foliage models will support env_wind sways, so do trial and error until you find a foliage model that fits with your needs

Note: If you cannot find a suitable replacement for foliage models, you can attempt to add tree sway support to the imported model yourself. Be aware that this is an advanced technique that requires use of blender.

2.5 - Lighting

Improving lighting to make use of new CS2 lighting features should always be your top priority as these can significantly improve the quality of the map.

For that reason, it is important to understand what different lightning options do:

  • Static: a standard light that only provides baked lightning and baked shadows within an area. Most of the lights in your map will be static. They don’t have a dynamic specular highlight but it can still be baked to cubemaps.
  • Stationary: a light as the name suggests is stationary, but provides more capabilities than a static light. It is a mix of both static and dynamic, where static objects cast baked shadows and dynamic objects cast dynamic shadows. In this case, baked shadows are in a separate shadowmap. Stationary lights can be toggled or change colors, but cannot be moved. They also have a dynamic specular highlight.

Note: There is a limit of 4 overlapping stationary lights at any given luxel, which may include one for light_environment (unless baked shadowing is disabled, or for any VIS clusters that are "indoors") - any more stationary lights will not show up properly and cause lighting artefacts!

  • This is because each stationary light uses up a channel in the shadow map, and there are 4 channels in total (red, green, blue, alpha).
  • This overlap is entirely dependent on the radius and shape of the light - this means lights separated by the void may still affect each other!

TIP: If you would like to have the additional layer for stationary light, you can disable Baked Shadowing in light_environment so that you can use the extra channel normally reserved for light_environment in outdoor areas. Be warned that this will disable CSM (or in laymans term this will disable shadows casted from the light_environment).

  • Dynamic: Dynamic lights, as the name implies, are fully dynamic. It casts dynamic shadows of the entire scene (unless the object has disabled dynamic shadows) and is thus the most expensive type. Dynamic lights can be fully manipulated in real time and spawned at will. However, if shadows are enabled, it will be limited to the dynamic shadow atlas, which depends on the user’s shadow quality setting as follows:
  • Very high: 6144x4096
  • High: 3072x2048
  • Medium: 1536x1536
  • Low: 1280x640

Thus, as of the writing this guide, having medium or low video settings will may disable any non-stationary lights if dynamic shadows is enabled.

Should you need to view the baked lighting lightmap within your map, you can use Source 2 Viewer (ValveResourceFormat) to open the map .vpk file, and navigate to lightmaps/irradiance.vtex. If there are any abnormally large faces in the lightmap, you may want to take a closer look at the map and optimise.

2.5.1 - Specular Lightning

Static lights in your map should have bake specular to cubemaps enabled. This allows the light itself to be reflected on reflective surfaces via cubemaps.

You can see examples of specular lightning in ze_ELEVATOR_escape and ze_hidden_fortress comparison shots.

2.5.2 - Stationary and Dynamic Lights

Any lights that you need to change at run time should at least be a stationary light. It should be dynamic light if the light needs to change positions as well.

2.5.2.1 - Dynamic Shadows

A stationary/dynamic light can support dynamic shadows by enabling Baked Shadowing. This will allow shadows to be dynamically drawn from players (including yourself), prop objects, or any moving entities.

  • These can greatly change the atmosphere of an area - you should try to use dynamic shadows whenever possible, but…
  • The limit of 4 overlapping stationary lights still applies here - any additional stationary lights with dynamic shadows will not work properly.
  • Because of this limit, dynamic shadows should only be used for lightning that can benefit the most from dynamic shadows.

TIP: Once again, you can disable Baked Shadowing in light_environment so that you gain an extra layer of dynamic shadows that you can use instead. Use this only if your map does not depend on CSM from light_environment, for example it’s nighttime without a moon or the sky is cloudy.

Check out how having dynamic shadows enabled changes the visuals of an area in ze_hypernova.

2.5.3 - Light Entities

  • light_environment: equivalent to S1, gives environmental light to your map.

TIP: You can adjust the properties of CSM from a light_environment, which is disabled in hammer by default. More information on how to patch is mentioned in the later section.

  • light_omni: legacy entity equivalent to light entity in S1; do not use this light entity!
  • light_omni2: new S2 light that has equal properties to the light entity in S1 - provides uniform lighting around the source at default settings. A basic light but also is highly customisable.
  • Shape:
  • Point (default): Light is emitted as it were emitted from a single point in space - shadows will be as sharp as the lightmap luxels.
  • Sphere: Light is emitted from the outer layer of a sphere - viable for any hanging lights that has a considerable volume/size, baked shadows will be softer the bigger the light source is.
  • Tube without end cap: Light is emitted from the outer layer of the cylinder, with no light from the top or bottom of the cylinder - perfect for fluorescent lights.
  • Tube with end cap: Light is emitted from all areas of the cylinder.
  • Angles: The inner and outer angles can be modified so that the light becomes directional. This is vital for any lightning from the ceiling, or any lightning that has a cap that prevents light to go through.

Note: changing the angle does not impact the brightness of the light.

  • Cookies: A texture to apply on top of illuminated areas. Imagine as if you place a film layer of the texture in front of the lightning, and opaque areas in the texture result in shadows on the illuminated areas. A great way to mimic complex shadows, for example lighting through a window frame, without having to use stationary light for sharper shadows.

You can see how fluorescent lights are made with light_omni2 in ze_ELEVATOR_escape and ze_saw.

TIP: light_omni2 is a very powerful light entity in source 2 with the most customization possible.

  • light_barn: new S2 light that is best suited for 'barn' lighting - i.e. any light that illuminates in a specific direction, mainly to illuminate the floor in an area. Great for ceiling lamps, hanging lamps with caps, and outside lamps such as street lamps.
  • Shape: the shape of the projected light can be changed with three numbers given in the shape parameter - size of light source in x-axis, size of light source in y-axis, and angle of projection. Increasing the angle of projection will increase the area the light illuminates, at a cost of light resolution.
  • light_spot: equivalent to S1, best suited for focused lightning on a small area. For example with spotlights and floodgates. Superseded by light_barn.

Note: by default light_spot will be non-static with dynamic shadows enabled.

  • light_rect: a light that is emitted from a flat plane. Best suited when creating fake ambient lighting from outside such as behind windows and skylights.
  • light_ortho: a directional (parallel) light source akin to light_environment but within a user-specified cube. Similar to light_rect, it can be used to provide direct sunlight through a window when there is no skybox, or provide a different kind of sunlight in a separate part of the map (perhaps combined with a skybox change).

Note: Unlike S1, it is now possible to have these light entities directly inside the lightning models instead. In fact, this would be the most preferred method of doing lightning as demonstrated in ze_STRANGE_escape.

2.6 - Post Processing

Strictly speaking, post processing is not a new feature with CS2, but the new tool makes it significantly easier to change post processing effects and observe the changes in real time both in hammer and in game. Furthermore, bloom is significantly improved when compared to S1, to the point that glow sprites around lights are no longer needed and can be removed altogether.

TIP: When creating a new post processing file, you should use both Tone Mapping and Bloom together. With Bloom you can set how much bloom should be given off from bright light sources and selfillum materials, and with Tone Mapping you can adjust the general brightness and intensity of them.

Applying post processing into your map requires use of a new mesh entity called post_processing_volume. These volumes have to cover the areas you want post processing to be enabled. Alternatively, if you want it to be enabled across the entire map then you can tick the 'Master' parameter.

How post processing can affect the visuals of a map can be seen in ze_chronus and ze_PUTA.

2.7 - Movements

This section will veer a bit off from Zombie Escape and discuss about elements from other movement based community gamemodes.

2.7.1 - Surf Ramps

Edge bugs (where players seemingly "lose all momentum" at the end or even in the middle of a surf ramp) are much more prominent in CS2. This of course defeats the purpose of the surf gamemode, and within a ZE map this can make a map be unplayable. This gets progressively worse on ramps with bad mesh geometry, such as ones generated from the import tool.

With a little preparation before using the import tool howerver, the frequency of such happening can be greatly reduced. This is with converting surf ramps temporarily into func_brush, so that their S1 geometry stays in tact during the import of the map.

2.8 - Textures

Although many of the material parameters are not much different from S1, the new Material Editor likewise makes editing materials much easier, and allows viewing the changes in hammer and also in game immediately as well.

Some CS:GO materials and many custom materials will likely have textures without any details. Depending on the type of texture, the quality of the materials can be greatly improved with some extra work. Here are some key layers you should know about and understand what effects they provide:

  • Normal map: a texture layer which provides height (and depth) information for the material. Having a heightmap will give a perception of 3D on a 2D surface.
  • To create a heightmap, it is best to use a third party software / online tool that generates a heightmap from an image. A recommendation for this is with a third-party tool 'Crazybump'.
  • Roughness: a texture layer which provides information about light reflectivity. Roughness maps are typically grayscale with brighter regions being more rough (less reflective).
  • To create a roughness texture, the easiest way is to make a copy of the color texture, convert to grayscale, and adjust the contrast accordingly via an image editor like GIMP or photoshop.

The left-hand side menu shows the material features, for example enabling transparency via translucent/alphatest, or enabling specular lighting from cubemaps and stationary/dynamic lights.

These examples are only scratching the surface, it will be worth your time to go through each of the parameters and observe what effects they give in game!

Comparison shots of ze_ELEVATOR_escape and ze_saw will show you how much a single texture can be improved. Additionally, ze_PUTA modifies textures on lamp models to give a more realistic lighting from those lamp models.

2.9 - Optimisations

This section will explain the optimisation methods you can take to make your map more accessible to players. Hopefully this section will see more entries as we do more ports, especially after the full release of CS2.

2.9.1 - Reducing Map File Size

CS2 will supposedly not have any size limitation to a map upload (in contrast to the 150 mb limit for CS:GO FastDL), except for a 2 GB size limit when uploading to the workshop. In any case, we highly recommend compressing the map size as much as reasonably possible, for example to help players with slower internet speeds.

Potential methods of reducing the cubemap resolution and removing .los files before uploading to workshop has been discussed already, but if applicable, your port can be reduced in file size even more.

2.9.1.1 - Lightmap resolution

You can, when compiling the map, choose the appropriate lightmap scale (512, 1k, 2k, etc.) for the size and complexity of a map. The higher the lightmap resolution, the more space it will take up in the final .vpk. A simple map with only a couple of rooms would not need a 8k lightmap!

2.9.1.2 - Bake lightning on props

By default, lightning on props are baked onto the lightmap. Not only does this occupy a section of the lightmap which can be used on world meshes, we have found that props using baked lightning increases the size of the map as well.

By disabling Baked Lightning on props, the prop will be forced to use lightning using light probes insetad. This will result in slightly worser lightning, however in most of the cases it will be 'good enough' that most players will not notice during gameplay.

TIP: Disabling Baked Lightning is most beneficial for props that have large textures, for example with foliage models.

2.9.1.3 - Audio Quality

This method was more prominent in S1, but still is applicable in S2. Essentially, you reduce the bitrate of a sound file to a cheaper but acceptable quality. Although you do not have to be as strict in S2, you should still attempt this method if a sound file uses extremely high quality music for no valid reason.

In reality, it is more likely you will encounter the opposite when porting CS:GO maps; many music files had to have lower quality to meet with the FastDL size limit. In this case, you can attempt to identify the source of music and redownload them at a higher quality. Remember, the quality of the map is still something you have to consider when porting a map.

2.9.1.4 - Steam Audio

Since the Arms Race update, a new option has been added to the compile menu under Steam Audio. This will enhance the quality of audio within the map, at the cost of extra file size.

Naturally, for Zombie Escape maps, this feature is completely unnecessary and its use should be refrained. This is because Zombie Escape maps are usually busy in audio, for example together with the map music. Most importantly however, Zombie Escape is a casual gamemode where having good audio quality is not necessary at all, and most players would likely not even notice the improvements this feature may add.

2.10 - Advanced Techniques

This section lists topics that are too long to be included with the main text and/or was not deemed to be a required knowledge when porting.

2.10.1 - Manual Import of Models

Although some knowledge about S1 models helps with the process, it is not necessary to know when porting simple models to S2.

If you already have the model files that you want to import, then you can skip this step. If not, then you have to search for these model files. If the model you want to import is a native CS:GO model, then you have to use an extractor tool such as GCFscape to extract model files from pak01_dir.vpk found in your csgo/ folder.

Note: "model files" in this instance mean a combination of 4 files in total of the same name. Older source models have 5 files or a different combination.

Next, you have to decompile these models to obtain their .smd files. To do this, you have to use Crowbar, a tool that is used for everything related to S1 models. More information about how to set up the tool and how to operate is found on the official guide made by its developer.

From Crowbar, we only need to obtain .smd files, which may be a singular or multiple files depending on the prop that is being imported. The table below shows which .smd files you should tick for in the decompile tab of Crowbar. If are not familiar with Crowbar, leave everything else at default settings.

All props

Reference mesh SMD file

(This is the actual model)

Props that have collisions

Physics mesh SMD file

(This is the collision model)

Props that have animations

Bone animation SMD file

(This stores information about how the model should transform throughout time; i.e. animations)

If you have done the decompilation successfully, you now will have .smd files of the model and a bunch of other unimportant files. Move these .smd files into the CS2 addons folder, making sure that you keep the same model directories as CS:GO (you cannot open files that are outside of the addons folder).

Open up ModelDoc and create a new .vmdl file in the same directory of the original .mdl. Afterwards, you can follow this guide written in mapcore to import the decompiled .smd files into ModelDoc. Even though we use different import model files, the process of adding in imported model meshes in ModelDoc is still the same.

If all .smd are imported correctly, you should now be able to compile the model. After compiling the model, you can use the ModelDoc window to see if all prop properties have been implemented correctly. If applicable, you can now add other properties to the prop and compile again.

If you are unsure or get stuck, then you are always welcome to ask for help in our discord!

2.10.2 - Adjusting CSM Properties

Editing CSM properties is by default disabled in csgo.fgd. If you wish to modify CSM, you will need to edit the file.

First, search for the block for light_environment. Afterwards, delete all the lines with (remove_key) in them.

If you launch hammer after completing the modification, you will find new parameters you can edit with light_environment.

Note: Editing the distance is a bit of a give and take; higher distance will increase the reach of the cascade layer at the cost of resolution. A good starting distance values are 1024, 512, 256, and 128 for cascade layers 1, 2, 3, and 4 respectively.

2.10.3 - Adding Tree Sways on Foliage Props

This requires use of blender (with a vertex coloring addon, such as Vertex Color Master for Blender, or any modeling software) to change the vertex colors on foliage meshes. Unless you have experience with them already, we recommend that you replace the problematic foliage props with CS2 ones.

When applying colors to the meshes, red should be used for the general sway of the tree, and blue should be used for individual flutters of leaves. First, apply a gradient from black to red from the bottom to the top of the foliage; darker colors represent less sway. Afterwards, apply blue to the edges of each branches/stems of the foliage mesh

In the end you would need to have a general red hue near the base of the branches, whilst the end of branches to be of blue hue - refer to the image below.

Example vertex coloring on a tree foliage model.

2.10.4 - Creating CS2-compatible .svg

While porting your map, you may have decided to create a map icon for the loading screen and may have encountered some problems. Or it could be that the .svg that used to work in CS:GO seems to no longer work in CS2. This section aims to provide a solution for such issues.

To briefly describe the problem, the paths (i.e. the shapes) in .svg files can be defined in absolute or relative coordinates. If the .svg is written in relative coordinates, only the first layer will be displayed in CS2; it is presumed that the .svg interpreter in CS2 does not support translating the relative coordinates over the multiple layers. More technical explanation can be found here.

If you know how to use a svg vector editor, then the fix is pretty simple. Simply set the preferences of your editor to use absolute coordinates, move around the layers a bit so that you can save the .svg, and you should see it fixed immediately in CS2.

If you do not know how to use one however, it is recommended to use this png to svg converter as this converter will output a .svg in absolute coordinates. This will reduce the quality of the map icon, however it will not be perceivable on the loading screen itself.

2.11 - Your Additions

Obviously, the main purpose of ports is that you convert maps from older games using as much of the new CS2 features as possible, while not changing much of the core gameplay or visuals of the ported map. This is the core mentality of the Source2 Zombie Escape ports, to simply increase the quality of the map and only making adjustments to make the map be playable in CS2.

However, and especially when working on your own port as / on behalf of the original mapper, you may choose to bring in additions to the map that deviates from the original map. In the end, it is up to your own discretion to decide the changes you want to bring to the ported map. With that said however, you should abide by as much of the original mapper's wishes as possible, as they are the ones that allowed you to port the maps in the first place.


3.0 - Examples of ported maps and their CSGO counterparts

This section will display comparison screenshots from a couple of ported Zombie Escape maps, listed in the alphabetical order. Hopefully these comparison screenshots provide you a better idea of the potentials S2 can achieve, and convince you to spend more time to substantially increase the quality of your port!


3.1 - ze_antartika

Showing off the new cs_office snow texture which replaced the previous ground texture, and with some additional shininess as well. Notice how the treeline in the skybox has adapted colors from the skybox.

3.2 - ze_chronus

Overall bloom and dustmote improvements in caverns, in addition to having swaying trees in the outside areas.


3.3 - ze_ELEVATOR_escape

PBR enhanced textures that have parallax cubemaps, and further enhanced by general bloom improvements.

3.4 - ze_hidden_fortress

PBR enhanced floor with better bloom and postprocessing. This fire here is a stationary light that casts real time speculars.

3.5 - ze_hypernova

Overhauled lighting using the new Source2 light entities, including enabling dynamic shadows to cast shadows from the fans. Further modified materials for extra shininess on surfaces with parallax cubemaps.

3.6 - ze_PUTA

Almost entirely re-textured with CS2 materials, and many ported materials and models are revamped to match with CS2 quality. General improvement on lightning as well for more realistic lightning casting.

3.7 - ze_saw

Improved textures using PBR shininess and revamped lightning for more realism.

(We are aware of the weird lightning cutoff on the ground!)

3.8 - ze_STRANGE_escape

Revamped lighting by using a more realistic approach where light is emitted directly from the light-sources.


4.0 - Obsolete Guidelines

This hidden section will list any (potential) obsolete information that was only valid in the past versions of the game or the workshop tools; i.e. you should not be following any information present in this part. This section is only made for historical records.

In a situation where a future update revalidates a certain section, or if we find out that some information in this part is useful again, then they will be moved back into the main body of the guide as needed.

4.1 - env_soundscape at Player Spawn

Sounds have seen a massive change with S2, where now all sounds, including any custom sounds you may have, are all played with soundevents.

If you have tried compiling your map already, you may have noticed this issue when you launched your map in game - all sounds have echos regardless of whether you are indoors or outdoors. This is because every new round stops all soundevents played in the previous round, and this results in a state where no soundevents are playing in the new round.

To fix this issue, we simply need to add an env_soundscape near player spawns - this can even be an empty sound as we just need to have a soundevent playing at the start of each round.

From our tests, we have found that soundevents that have a dsp preset of reverb_22_outsideOpen provide the best quality for the in game sounds. This can be done by creating a custom soundevent (explained in the next subsection) and setting the dsp preset directly. Below is an example soundevent that you can use for your custom .sndevts file:

"Your.Soundevent.Name.Here"

{

type = "csgo_mega"

vsnd_files_track_01 = "sounds/common/null.vsnd"

override_dsp_preset = true

dsp_preset = "reverb_22_outsideOpen"

}

Simply have the env_soundscape refer to this soundevent (make sure to tick Override with soundevent), and set the radius of the env_soundscape to -1. A radius of -1 will allow the soundevent to play for all players that have a direct line of sight to the entity.

If you cannot get the env_soundscape to have a line of sight with all player spawns, or if the player spawns are divided into multiple areas, then you may choose to duplicate it for each spawn area, or set a suitable radius instead. If choosing a custom radius, ensure that the entity completely covers all player spawn points. Alternatively, you can use a trigger_soundscape in conjunction with an env_soundscape_triggerable.

Note: There are a plethora of soundevents available in base CS2. Our example above is only a recommendation, so feel free to use any other existing soundevents that you think gives better in-game audio qualities.

4.2 - Manual Packing into Standalone .vpk File

In release version of CS2, we expect that uploading your map to the workshop will automatically pack all necessary assets to your map. If true, you can simply upload your map to workshop without needing to change anything else (but perhaps you can try to improve the map a bit more with the next main section?).

However, there may be instances where you would rather have the map exported as a standalone .vpk file. For example, Zombie Escape servers in the future may use another method for file distribution (like fastdl in CS:GO). This section will introduce you to the steps you have to take to manually pack the map.

4.2.1 - Precaching Soundevent Files

As mentioned in the section about custom soundevents, you have to rename your .sndevts file to something other than 'soundevents_addon.vsndevts' when you are manually packing the map. Unfortunately, this in return will stop playing your custom sounds in game as any .vsndevts file other than 'soundevents_addon.vsndevts' will need to be precached in advance.

Precaching soundevents follows similar to CS:GO, as in using VScript to precache soundevents. You create a .lua VScript file with a Precache function within and place the script in game/<addon name>/scripts/vscripts/. This script then needs to be referenced by an entity in your map which will persist throughout all rounds, for example with a logic_auto. The script file itself must have a content similar to below:

function Precache(context)

 PrecacheResource("soundevents/<custom name>.vsndevts", context)

end

where you input the name of your own .vsndevts file replacing the angular brackets.

Naturally, this will require you to patch VScript as well which you can find in the section about patching VScript.

4.2.2 - Manual Packing

Thankfully with the new addons system with S2, your game assets folder will never be contaminated, nor will assets from different addons contaminate with each other. This makes manual packing of your map easier (and cleaner) than in S1.

Your addon folder in the game/ directory is essentially what you need to pack your map into a .vpk file. The map is packed into a .vpk file by dragging the parent folder which contains all map assets into vpk.exe located in the Counter Strike: Global Offensive/bin/ folder.

Note: This vpk.exe is located in your CS:GO game folder, not your CS2 game folder.

However, your addon folder will also contain extra files that do not need to be packed; for example .los (lines of sight) files which are generated during the VIS compile step and are not needed in-game. Furthermore, your addon folder may contain compiled assets that your map no longer uses.

To remedy this issue, you can use an auto map packer made by a member of S2ZE to automatically pack the map or to detect assets the map uses and have them manually packed instead. When using the auto map packer, all assets that the map uses (including the 3D skybox vpk and all its assets) except for sounds and soundevent files will be made ready for you. You can move the sounds and soundevents folder by yourself after the packer is executed.

If you want to test if the map has been packed successfully, you have to unload the map addon first (or open the non-tools standalone CS2) and then launch your map. Additionally, you can use GCFScape to see the contents of your packed .vpk file.

Note: You can pack the map manually without using any tools, but this is really not recommended for a simple reason that you may miss unused assets when filtering manually.


Changelogs

3 September 2023

  • Release version.

11 September 2023

  • Added section about import tool logging and relevant formatting work.
  • Fixed some incorrect entity names.

12 September 2023

  • Added extra info about inserting filter_activator_team into .fgd files.
  • Changed discord link to permanent link.

18 September 2023

  • Added some notes about explosion / blast damage crashes.
  • Fixed typo on zr_toggle_respawn.

26 Septebmer 2023

  • Updated loading screen background image material type to Csgo Composite Generic.

27 September 2023

  • Added info about trigger_push issue.
  • Added info about crouch/uncrouch re-triggering in trigger_ entities.

5 October 2023

  • Minor spelling mistakes (it's over).

15 October 2023

  • Minor correction to cs_mdl_importer.

3 November 2023

Workshop! Updates!

  • Added additional section dedicated to obsolete information.
  • Deleted information about weapon_* entities crashing clients upon pick up.
  • Made section about using env_soundscape at player spawns to fix weird echos obsolete.
  • Deleted information about using custom vsndevent files for manual packing.
  • Added section about using the Steam Workshop.
  • Added disclaimer about CS2Fixes for S2 quirks.

7 November 2023

  • Added more details about workshop whitelisted paths.
  • Added instructions about using and uploading to the steam workshop.
  • Added some food for thoughts about using the workshop.
  • Modified a section to mention entities missing from .fgd.
  • Added small section about obsolete rope entity.

8 November 2023

  • Removed incorrect statements about uploading to the steam workshop.

9 November 2023

  • Added disclaimer for light_environment Direct Lightning Type. (has been fixed with an update)
  • Added section about movement modes, specifically to talk about surf ramp bugs.
  • Added extra step in the import tool preparations of setting surf ramps into func_brush.
  • Added disclaimer for custom sounds in soundevents_addon.vsndevts not working currently.
  • Updated workshop whitelisted paths.
  • Added warning about removal of env_sun from the game.

11 November 2023

  • Changed recommended solution for changing teleport destination on trigger_teleport using AddOutput.
  • Added alternative solution to env_sun.

15 November 2023

  • Removed xen's map autopacker from the Useful Tools list - obsolete.
  • Updated formatting for figure captions.
  • Added section for skybox water transitions.

17 November 2023

  • Removed disclaimer for custom sounds in soundevents_addon.vsndevts not working - fixed with update.

30 November 2023

  • Updated section about vertex color painting on foliage models for env_wind swaying support.

5 December 2023

  • Added temporary section for missing textures fatal error.

7 December 2023

  • Improved the technique used to search for missing textures in models.

14 December 2023

  • Updated the Urgent Information section to more reflect on the current dire situation regarding the import tool.

16 December 2023

  • Added .fgd block for ai_changetarget.
  • Added solution for random teleportation targeting.

19 December 2023

  • Removed crouch and uncrouch triggering issue as it is fixed in an update.
  • Updated and reformatted the section about particles.
  • Added information about different properties you can enable on particles for performance boost.

27 December 2023

  • Added workaround for the import tool trying to read an unexisting file.

28 December 2023

  • Edited workaround for the import tool trying to read an unexisting file - having pak01 and pak01_dir at the same time does not work.

6 January 2024

  • Edited workaround for the import tool trying to read an unexisting file - again; rename vpk.signatures.
  • Edited section on .nav and discourage ZE mappers from compiling nav mesh.

13 January 2024

  • Updated instructions on zombie respawns.

7 February 2024

Arms race!

  • Deleted the VScript section for the new SourceTS scripting language.
  • Promote point_teleport to change teleport destination as ai_changetarget is now obsolete.

11 February 2024

  • Added section to discourage usage of Steam Audio compiles.

20 February 2024

  • Added trigger_gravity not resetting gravity upon leaving into S2 Quirks.

25 February 2024

  • Improved method for finding missing materials.

5 March 2024

  • Revised fix for func_tracktrain.
  • Modified content about server assets and multi-addons loading.

11 May 2024

Major update! (to the guide, not the game)

  • Minimap:
  • Added some messages about minimap generations.
  • Added subsection about multi-layered minimaps.
  • Particles:
  • Reorganized the section.
  • Added subsection about using control points in Particle Editor and their usefulness.
  • Highlight the use of particles as a replacement for precipitation.
  • Items:
  • Added entire section dedicated to items.
  • Skybox:
  • Added subsection showing how to place sun mesh in maps to replace env_sun.
  • Third-party tools:
  • Added section to talk about Source 2 Viewer and CS2Fixes
  • Loading screen:
  • Added subsection to assist in creating CS2-compatible .svg.

12 May 2024

  • Revised part about identifying leaks during import tool VBSP.

16 May 2024

  • Corrected player collision issues with items.

29 May 2024

  • Removed ai_changetarget from missing from .fgd list.

2 August 2024

  • Changed method of changing VIS voxel size from modifying game files to using visibility_hint.

9 September 2024

  • Added section about adding custom key of subclass_name to grenades to make them interactable by players.
  • Added section about using env_player_visibility to better apply fogs to players.
  • Added section to fix HE grenades breaking prop_door_rotating doors.

12 December 2024

  • Correction to func_water_analog fix.

26 January 2025

Happy (late) new year!

  • Deleted text on deleting .los files when uploading a map to the workshop.

24 February 2025

  • Added info about using Csgo Composite Generic material when creating minimaps.

24 July 2025

  • Fixed false information about keyvalue type when placing grenades in the map.