Counter-Strike: Global Offensive

Counter-Strike: Global Offensive

Not enough ratings
How to Randomize Your Map Round-to-Round in Hammer
By sn0wsh00
Want to make your map look different round-to-round? Well, I got the guide for you!
   
Award
Favorite
Favorited
Unfavorite
Introduction
It's possible to have a CS:GO map vary its appearance round-to-round, as seen in the video below:

Or as seen in this GIF below:


You've also probably already seen this randomization in action in multigame maps where in each round, you'll spawn in a random arena. This tutorial will present several examples on how to vary various elements of a CS:GO map such as skyboxes or soundscapes using two Valve Hammer entities: logic_eventlistener and logic_case. Hopefully, these example will help you understand how to use those two entities to create dynamically changing maps.
Logic_eventlistener and logic_case
As I mentioned, there are two main entities you will be dealing with when it comes to varying elements round to round: logic_case and logic_eventlistener. When it comes to randomizing maps, logic_case presents all the potential variations (or cases) that could happen on a map. Each logic_case allows for up to 16 different cases. Logic_eventlistener chooses which of the cases logic_case should fire if certain events, such as a round ending, occur.

Before we go into detail on how to randomize specific elements round-to-round, we first need to create two logic_eventlistener entities. For the first logic_eventlistener, set "Name" to ListenRoundStart and "Event Name" to round_start. For the other logic_eventlistener, set "Name" to ListenRoundEnd and "Event Name" to round_end. What these entities will do is pick a random case in the logic_case to fire upon either the start of a round or the end of a round.

ListenRoundStart logic_eventlistener entities can also be substituted with a logic_auto entity. To make it behave like ListenRoundStart, set a logic_auto's output to OnMapSpawn.
Spawns
Spawning in CS:GO is already random, in that the point you spawn at in a spawn area will usually vary round-to-round. But say instead of just randomizing spawn points an area, you want to randomize where the whole team spawns round-to-round. Maybe you have a bunch of separate arenas and you want your players to spawn in a random arena each round, as seen in multigame maps. To do this,

  1. Create your three sets of spawns (info_player_counterterrorist/info_player_terrorist) for CTs and Ts. Name the first set of spawns SpawnPoint_1, the second SpawnPoint_2 and the third SpawnPoint_3



  2. Create a logic_case entity and name that logic case Random_Spawnpoint
  3. Clicking on the Outputs tab in Random_Spawnpoint's properties, click "Add..." to create an output. In the dropdown menus below, set "My output named" to OnCase01, "Target entities named" to SpawnPoint_1 and "Via this input" to SetEnabled.
  4. Creating another output, set "My output named" to OnCase02, "Target entities named" to SpawnPoint_2 and "Via this input" to SetDisabled.
  5. Creating a third output, set "My output named" to OnCase02, "Target entities named" to SpawnPoint_3 and "Via this input" to SetDisabled.
  6. Create another three output with the same Target Entity names (SpawnPoint_1..), but this time change output names to OnCase02, set SpawnPoint_2 to SetEnabled and SpawnPoint_1 and SpawnPoint_3 to SetDisabled.
  7. And once again create another three output with the same Target Entity names (SpawnPoint_1..), but this time change output names to OnCase03, set SpawnPoint_3 to SetEnabled and SpawnPoint_1 and SpawnPoint_2 to SetDisabled.



  8. Going to your ListenRoundEnd logic_eventlistener entity, go the output tab and click "Add...". In the dropdown menus below, set "My output named" to OnEventFired, "Targets entities named" to Random_Spawnpoint and "Via this input" to PickRandom and "After a delay in seconds of" to 0. All other examples in this tutorial will have a a delay of 0 seconds.


What this will do is that at the end of a round, CS:GO will choose randomly which case in Random_Spawnpoint to fire, which will lead to one group of info_player_counterterrorist/info_player_terrorist entities being enabled and spawnable and the other two groups being disabled. Note that for each case, you need to specify all the spawn groups you want disabled and the single spawn group you want enabled. In turn, the number of outputs in Random_Spawnpoint will be equal to the number of cases square (3 cases require 9 outputs, 4 cases 16 outputs etc.). So be aware of that. Also note that because this logic_eventlistener relies on the event "round_end," you can NOT substitute the logic_eventlistener entity in this example with a logic_auto.

Special thanks to Nymphalow on Reddit for his explanation on how to do this:
https://www.reddit.com/r/hammer/comments/7ifmd1/csgo_how_do_i_make_group_spawns/dqygm2p/
Geometry
It is possible to vary the geometry of a map round-to-round using func_brush. Cs_havana was notorious for this, randomly blocking or unblocking windows or doors round-to-round and causing a lot of confusion. Hopefully, if you do randomize geometry round-to-round, the changes would be only be cosmetic.

Say we want to have the game choose between two different variations of a wall round-to-round,
  1. Tie the brushes that make up the first wall variation to func_brush and name that group SpawnWall_1.
  2. Do the same thing with brushes that make up the second wall, naming that group of brushes SpawnWall_2.
  3. Create a logic_case entity named Walls
  4. In the Outputs tab, create two outputs named OnCase01 and two outputs named OnCase02.
  5. For the OnCase01 outputs, set SpawnWall_1 input to to Enable and SpawnWall_2 input to Disable
  6. For the OnCase02 outputs, set SpawnWall_1 input to to Disable and SpawnWall_2 input to Enable

  7. Under the ListenRoundStart logic_eventlistener entity (note that this is the round_start, NOT the round_end logic_eventlistener), create an output named OnEventFire. Set target entity to Walls and target input to PickRandom.
Soundscapes
To have the map randomly choose between two different soundscapes,
  1. Create two env_soundscape entities
  2. In this example, I want CS:GO to choose between mill.Outside and canals.Water. In turn, we need to name the canals.Water env_soundscape to sound_canalswater and the mill.Outside env_soundscape to sound_milloutside
  3. Create a logic_case named soundscape_vary
  4. In the Outputs tab, create two outputs named OnCase01 and two outputs named OnCase02
  5. For the OnCase01 outputs, set sound_canalswater input to to Enable and sound_milloutside input to Disable
  6. For the OnCase02 outputs, set sound_milloutside input to to Enable and sound_canalswater input to Disable

  7. Under the ListenRoundStart logic_eventlistener entity, create an output named OnEventFire. Set target entity to soundscape_vary and target input to PickRandom.
Skyboxes
To have the map randomly choose between three different skyboxes each round,
  1. Create three skybox_swapper entities. Name these entities SkyboxSwap1, SkyboxSwap2 and SkyboxSwap3
  2. Under the Skybox Material Name entry for each skybox_swapper, choose a skybox you want the map to choose from. Make sure the skybox is different from the other two skybox_swappers, obviously.
  3. Create a logic_case entity and name it skybox
  4. Under the Outputs tab, create three outputs.
  5. For OnCase01, set target entity to SkyboxSwap1. For OnCase02, SkyboxSwap2. For OnCase03, SkyboxSwap3.

  6. Set the target input for all three cases to Trigger. Unlike group spawns or geometry, skybox_swapper will automatically override previously enabled skyboxes.
  7. In the Outputs tab of the ListenRoundStart logic_eventlistener, create an output setting "My output named" to OnEventFired, "Targets entities named" to skybox and "Via this input" to PickRandom

Packing programs such as CompilePal or VIDE will not automatically pack the skybox textures into your BSP. Therefore, you will need to manually add the other skybox textures in using VIDE.
Spinning Platforms
Unlike with func_brushes, I haven't found a way to use logic_case and logic_eventlistener to make moving platforms and spinning objects completely disappear. However, I did find a way to alter brush speeds round to round. For those who want have a brush vary between spinning and standing still between rounds:
  1. Create a func_physbox brush entity, along with a phys_motor entity. Name the func_physbox brush spinner and the phys_motor entity spinner_motor. Connect spinner_motor to spinner
  2. Create a logic_case entity and name it spinning. Under the Outputs tab, create two outputs, each with a target entity of spinner_motor and a target input of SetSpeed.
  3. For OnCase01, set the parameter override to 0. For OnCase02, set the parameter override to 200. In turn, this will allow the game to randomly choose between having the platform move at 200 units/sec or 0 units/sec
  4. In the Outputs tab of the ListenRoundStart logic_eventlistener entity, create an output setting "My output named" to OnEventFired, "Targets entities named" to spinning and "Via this input" to PickRandom
Starting Weapons (old way)
Say you want the terrorists to spawn with either a Tec-9 and a Glock and the Counter-Terrorists to randomly spawn with either a Five-Seven and a USP-S. This seemingly easy thing to do is actually much more complicated compared to the other examples in this guide. To do this, first
  1. Create two logic_case entities. Name one logic_case weapon_equip_logic_case_ct and the other weapon_equip_logic_case_t
  2. Create two filter_activator_team entities. Name one filter_t and the other filter_ct
  3. In filter_t, set Filter Team Number to Terrorist. In filter_ct, set Filter Team Name to Counter-Terrorists
  4. Create two game_player_equip entities, naming one equip_players and the other wep_knife.
  5. In wep_knife, disable SmartEdit. Set key to weapon_knife and Value to 1 and click Add.
  6. Under the Flags tag for wep_knife, enable only the "Strip All Weapons First" flag. What wep_knife will do now is make sure both Ts and CTs will spawn with a knife.
  7. Under the Flags tag for equip_players, enable only the "Only Strip Same Weapon Type" flag. What equip_players will do now is make sure both Ts and CTs spawn with round's chosen pistols.

Once we've created the logic_case, filter_activator_team and game_player_equip entities (you should have created six entities so far), we now need to create several brush entities

  1. Create two trigger brushes around T spawn and and two trigger brushes around CT spawn and tie those brushes to trigger_multiple. Name the brushes around T spawn wep_spawn_1_t and wep_spawn_2_t, and the brushes around CT spawn wep_spawn_1_ct and wep_spawn_2_ct.

  2. Set "Filter Name" for both wep_spawn_1_t and wep_spawn_2_t to filter_t. Set "Filter Name" for both wep_spawn_1_ct and wep_spawn_2_ct to filter_ct. This will insure that only CT and T will trigger their respective weapon spawns.
  3. Set "Delay Before Reset" to -1
  4. If you have multiple group spawns, simply copy the trigger_multiple brushes to the other spawn areas, keeping the same names and filter names.
  5. In wep_spawn_1_t, set "My output named" to OnStartTouch, "Targets entities named" to equip_players, "Via this input" to TriggerForActivatedPlayers and "With a parameter override of" to weapon_tec9. Also make sure "Fire once only" is unchecked.

  6. In wep_spawn_2_t, do the same thing, but this time change the "With a paramemter override of" value to weapon_glock
  7. Do the same things again with wep_spawn_1_ct and wep_spawn_2_ct, making sure the override parameters are weapon_usp_silencer and usp_fiveseven respectively

Now that we've filled out the properties for our trigger_multiple brush entities (you should have made at least 4 brushes), it's time to move back to logic_case

  1. In the logic_case entity that you named weapon_equip_logic_case_t, create two outputs for OnCase01 and two outputs for OnCase02.
  2. For OnCase01, set target entity to wep_spawn_1_t and input to enable. For the other OnCase01 output, set target entity to wep_spawn_2_t and input to Disable. For OnCase02, do the reverse, setting wep_spawn_1_t to Disable and wep_spawn_2_t to enable.
  3. For weapon_equip_logic_case_ct, create the same outputs as you did with the terrorist version, but make sure you substitute wep_spawn_1_t and wep_spawn_2_t target entities with wep_spawn_1_ct and wep_spawn_2_ct respectively.
  4. In the Outputs tab of the ListenRoundStart logic_eventlistener, create an output setting "My output named" to OnEventFired, "Targets entities named" to weapon_equip_logic_case_t and "Via this input" to PickRandom. Also make sure "Fire only once" is checked.
  5. Create a second output with the same output name and input, but this time change the target name to weapon_equip_logic_case_ct. Once again, make sure "Fire only once" is checked.

Special thanks to Barnahalo and Nymphalow on Reddit for explaining how to make team specific game_player_equip in Hammer.

In summary, here are all the entities you have to create for this example:

Name
Entity Type
Description
weapon_equip_logic_case_ct
logic_case
Determines whether wep_spawn_1_ct or wep_spawn_2_ct is enabled, depending on case
weapon_equip_logic_case_t
logic_case
Determines whether wep_spawn_1_t or wep_spawn_2_t is enabled, depending on case
filter_t
filter_activator_team
Forces wep_spawn_1_t or wep_spawn_2_t to give weapons only to Ts
filter_ct
filter_activator_team
Forces wep_spawn_1_ct orwep_spawn_2_ct to give weapons only to CTs
equip_players
game_player_equip
Used by the trigger_multiple entities to give weapons to players
wep_knife
game_player_equip
Gives all players knives
wep_spawn_1_t
trigger_multiple
Gives terrorists Tec-9s via equip_players
wep_spawn_2_t
trigger_multiple
Gives terrorists Glocks via equip_players
wep_spawn_1_ct
trigger_multiple
Gives CTs USP-S via equip_players
wep_spawn_2_ct
trigger_multiple
Gives CTs Five-Sevens via equip_players
Starting weapons using math_counter (recommended way)
There's another (and better) way to have CT's and T's spawn with corresponding random weapons, by using math_counter entities. This method is really useful if you have many sets of weapons you want players to spawn with but don't want to deal with a lot of trigger_multiple entities.

Once again, say you want one round where the terrorists and counter-terrorists spawn with a Tec-9 and Five-Seven respectively, and another round where they spawn with a Glock and a USP-S. Using the math_counter method:
  1. Create two filter_activator_team entities. Name one filter_t and the other filter_ct
  2. Create two math_counter entities. Name one counter_ct and the other counter_t. For both counters, set the minimum legal value to 0 and the maximum legal value to 20.
  3. Create four game_player_equip entities. Name them equip_ct_usps, equip_t_glock, equip_ct_57 and equip_t_tec9
  4. For all four game_player_equip entities, make sure the "Use Only" and "Strip All Weapons First" flags are checked
  5. Disabling SmartEdit, add entries for weapon_knife for the four game_player_equip entities.
  6. Keeping SmartEdit disabled, add an entry of weapon_usp_silencer for equip_ct_usps, weapon_glock for equip_t_glock, weapon_fiveseven for equip_ct_57 and weapon_tec9 for equip_t_tec9. You should have two weapon entries for each game_player_equip, as shown below:

  7. Create a logic_case entity called counter_chooser and create two outputs for OnCase01 and two outputs for OnCase02
  8. For the first OnCase01 output, set target entity to counter_ct and input to SetValue. For the other OnCase01 output, set target entity to counter_t. For both OnCase01 outputs, set parameter override to 10. Do the same thing for the two OnCase02 outputs, but set the parameter override value for those outputs to 20. The output table for counter_chooser should look like the following:

  9. Create two more logic_case entities named logic_ct_chooser and logic_t_chooser
  10. Under class info for both logic_ct_chooser and logic_t_chooser, set the Case 01 value to 10 and the Case 02 value to 20.

  11. Under logic_ct_chooser outputs tab, create an output for OnCase01 with a target entity of equip_ct_usps and a "Via this input" of Use. Because Use is not a default FGD input, the word "Use" will appear red. Don't worry about this, though, as CS:GO will recognize this input.
  12. Create an output for OnCase02, and do the same thing you did with OnCase01, but replace the target entity with equip_ct_57. The logic_ct_chooser outputs tab should now look like this:

  13. For logic_t_chooser, do what you did with logic_ct_chooser, but replace the the target entities of equip_ct_usps and equip_ct_57 with equip_t_glock and equip_t_tec9 respectively
  14. Returning to counter_t, in the output table, create an output named OnGetValue with a target entity of logic_t_chooser and a "Via this input" of InValue. Do the same for counter_ct, replacing logic_t_chooser with logic_ct_chooser. Keep the parameter override fields blank.
  15. Back at the ListenRoundStart logic_eventlistener outputs table, create an output named OnEventFired, set target entity to counter_chooser and "Via this input" to PickRandom.

Now it's time to create the trigger_multiple brushes. Unlike the previous random weapon method, this method will only need a single pair of trigger_multiple brushes for each group spawn.

  1. Create a single trigger_multiple brush around CT spawn and a single trigger_multiple brush around T spawn. Name those trigger_multiples wep_spawn_ct and wep_spawn_t respectively. Once again, if you have multiple group spawns, simply copy the trigger_multiple brushes to the other spawn areas, keeping the same entity and filter names.

  2. Set "Filter Name" for wep_spawn_ct and wep_spawn_t to filter_ct and filter_t respectively
  3. Set "Delay Before Reset" to -1
  4. In wep_spawn_t, set "My output named" to OnStartTouch, "Targets entities named" to counter_t, "Via this input" to GetValue and a delay of at least 0.01 seconds (this delay is necessary for the game_player_equip entities to work). Also make sure "Fire once only" is unchecked.
  5. Do the same thing with wep_spawn_ct, but change "Targets entities named" to counter_ct.

In summary, here are all the entities you have to create for this example:
Name
Entity Type
Description
ListenRoundStart
logic_eventlistener
Tells counter_chooser to pick a random case at the start of each round
counter_chooser
logic_case
Sets the values of counter_ct and counter_t
counter_ct
math_counter
Sends its value to logic_ct_chooser upon receiving a GetValue command
counter_t
math_counter
Sends its value to logic_t_chooser upon receiving a GetValue command
logic_ct_chooser
logic_case
Defines which game_player_equip entity to use (an action that will equip the CT). Also defines which case to fire depending on value defined in counter_ct.
logic_t_chooser
logic_case
Defines which game_player_equip entity to use (an action that will equip the T). Also defines which case to fire depending on value defined in counter_t.
equip_ct_usps
game_player_equip
Gives using players a USP-S and a knife
equip_t_glock
game_player_equip
Gives using players a Glock and a knife
equip_ct_57
game_player_equip
Gives using players a Fiveseven and a knife
equip_t_tec9
game_player_equip
Gives using players a Tec9 and a knife
wep_spawn_ct
trigger_multiple
Causes counter_ct to fire its OnGetValue output when a player touches it, which will in turn send its value to logic_ct_chooser
wep_spawn_t
trigger_multiple
Causes counter_t to fire its OnGetValue output when a player touches it, which will in turn send its value to logic_t_chooser
filter_t
filter_activator_team
Forces wep_spawn_t to only activate with Ts
filter_ct
filter_activator_team
Forces wep_spawn_ct to only activate with CTs

And here's a chart to visually show how all these entities relate to each other:
Example Maps
I've created a few maps that uses some of the randomization techniques in this guide. You can use BSPSource to decompile these maps if you want to take a look at the randomizations yourself:
  • Five Infernos: Like a multi-game map, this fight yard map cycles between five different de_inferno inspired arenas. You can also watch some gameplay video here.
  • Vary Map by Round Test[drive.google.com]: The map seen in the video at the top of this guide. This map incorporates all but the math_counter example in this guide
  • Obstacle Course[drive.google.com]: An simple obstacle course whose obstacles vary round to round
  • Random Weapons with math_counter[drive.google.com]: Map using the math_counter method to randomize weapons
  • MG_Space_Race: Another obstacle course map whose obstacles vary round to round
  • AIM_Six_Arenas: Random weapons every round
< >
3 Comments
WILD BANAN Mar 2 @ 1:54pm 
Has good stuff indeed for beginners. Good job! Some steps can be done with simple vscript which gives way more possibilities D.
sniggyfigbat Mar 1 @ 7:15am 
Hmm. This has got some good stuff in it, cheers.
braaap stututu Jun 22, 2020 @ 4:51am 
comment on my profile i`m trying to collect comments. ty