Counter-Strike: Global Offensive/Game Modes/Co-op Strike: Difference between revisions

From Valve Developer Community
Jump to navigation Jump to search
(Tutorial on how to create your own Co-op Strike map)
 
m (Nesciuse moved page Counter-Strike: Global Offensive/Game Modes/Co-op Strike/en to Counter-Strike: Global Offensive/Game Modes/Co-op Strike without leaving a redirect: Move en subpage to basepage)
 
(24 intermediate revisions by 13 users not shown)
Line 1: Line 1:
Co-op Strike is a cooperative game mode first introduced in Counter-Strike: Global Offensive as part of the Operation Wildfire Gemini Campaign.
{{LanguageBar}}
Like Guardian, it is exclusively available through Operation Wildfire, but can be easily accessed through the console.
{{back|Counter-Strike: Global Offensive Level Creation}}{{Delisted|csgo}}
<noinclude></noinclude>
[[File:Csgo icon coopstrike.png|left|link=]]
'''Co-op Strike''' (internally: <code>'''coopmission'''</code>) is a cooperative [[game mode]] in {{csgo|4}}.


In Co-op Strike, 2 players go against a staged fight against an AI controlled terrorist team in a story-driven scenario.
It was first introduced as part of the Operation Wildfire Gemini Campaign. And now on the Steam Community Workshop. Like {{csgo mode|Guardian}}, it is exclusively available through Operations or the Steam Workshop, but can be easily accessed through the console.
The map prefix for these maps is coop_. It shares the same prefix as some custom community Co-op game modes.


Creating a Co-op Strike map is long and it is expected from the readers that they have basic knowledge on how to create maps and work with entities/Inputs/Outputs.
In Co-op Strike, two human players go against a staged fight against an [[AI]] controlled terrorist team in a story-driven scenario. The map prefix for these maps is <code>coop_</code>. It shares the same prefix as some custom community Co-op game modes.
It is not adviced to create a Co-op Strike map if there is no prior experience in mapping.
 
= Entities used in Co-op Strike =
Creating a Co-op Strike map in [[Valve]]'s style is a long process and it is expected from the readers that they have basic knowledge on how to create maps and work with entities, [[I/O]], along with a basic knowledge of [[VScript]]. It is not advised to create a Co-op Strike map if there is no prior experience in mapping.
First off lets go over all the entities introduced with the Co-op Strike gamemode and some entities that will be used in this tutorial.
 
* [[info_enemy_terrorist_spawn]]: The places where the enemies will spawn.
== Game Mode Description ==
* [[logic_script]]: The entity we connect out Vscript to in order for us to be able to use functions without our script.
If a standard map is loaded in this game mode, this game mode is technically comparable with {{csgo mode|Comp}}, but with the following differences:
* [[game_coopmission_manager]]: This is the entity that fires when a special event happens. For example when a Wave is completed this entity registers this and can fire an Output if needed.
* Human players are assigned to CTs and spawn at enabled [[info_player_counterterrorist]] entities as usual, whereas enemy [[bot]]s spawn at enabled [[info_enemy_terrorist_spawn]] entities. Players spawn at the round beginning but also when [[List of CS:GO Script Functions#Co-op Strike|an appropriate VScript function]] is called. During warmup, all players respawn if they die, as usual.
* [[item_coop_coin]]: The secret coop coin for extra points at the end of the level. At the moment 3 coins need to be in your map for the coop coin system to work.
* The round does not end if the Terrorists are eliminated due to {{ent|mp_use_respawn_waves|2}}.
* [[point_hiding_spot]]: Simply said this is a given spot by the creator of the map that tells the bots "this is a good hiding spot".
* CTs always wear an [[item_heavyassaultsuit]] that has slightly different properties in this game mode.
* [[prop_exploding_barrel]]: The oh so great exploding barrels.
* CTs cannot defuse planted [[weapon_c4|C4 entities]].
* If all human players are dead, they lose the mission and a new round begins.
* If the human players win the round (either by rescuing a [[hostage_entity|hostage]] or via [[game_round_end]]), they complete the mission and the next map loads.
 
== Creating the Map ==
=== Entities used in Co-op Strike ===
These are entities introduced with the Co-op Strike game mode along with some other entities that will be used in this tutorial.
* [[info_enemy_terrorist_spawn]]: The places where the enemy bots will spawn. No other spawn entities are used for them. It is the Co-op variant of [[info_player_terrorist]], so to speak.
* [[logic_script]]: The entity we connect out VScript to in order to be able to use functions via [[I/O]].
* [[game_coopmission_manager]]: This entity fires outputs when special Co-op events occur, for example when a wave is completed.
* [[item_coop_coin]]: The secret Co-op coin for extra points at the end of the level. At the moment, exactly 3 coins need to be in a map for the Co-op coin system to work.
* [[point_hiding_spot]]: Simply said, this is an entity that tells the bots "Here is a good hiding spot".
* [[prop_exploding_barrel]]: The oh so great exploding barrels. Place them a few units above the ground to prevent them from getting "sucked" into it.
* [[info_hostage_spawn]]: Rescuing the hostage is one way of completing the level.
* [[info_hostage_spawn]]: Rescuing the hostage is one way of completing the level.
* [[game_round_end]]: This entity can end rounds on command and make a team win. Used in coop maps where you dont rescue a hostage and just have to get to the end of the level.
* [[game_round_end]]: This entity can end rounds on command and make a team win. Used in Co-op maps where rescuing a hostage is not the winning condition.
The entities above will be the entities that will be used in co-op maps.
The entities above will be the entities that will be used in Co-op maps.
= Creating the Map =
 
=== Environment ===
=== Environment ===
When starting your map keep Co-op in your mind. Make sure there are plenty of hiding spots for either the Players or the bots. Think of places where you want to place new weapons for the players to use. Think of maybe nifty ways to use the environment to the players advantage. Note that it is Players VS AI which is different from any other gamemode.
When starting your map keep Co-op in your mind. Make sure there are plenty of hiding spots for either the players or the bots. Think of places where you want to place new weapons for the players to use. Think of maybe nifty ways to use the environment to the players' advantage. Note that it is players vs. AI which is different from any other game mode.
 
Co-op is based around a "wave" system. This means that a group of enemies will spawn, usually 5, that the players has to exterminate in order to advance to the next part of the map. So when creating the map, split your map up in multiple parts. Each part will have its own enemies by your choosing. Unless you want one big linear map with 40 enemies at once. Split your map up in different parts so that you can only advance once each wave is completed.
 
=== Player Spawns ===
In this game mode, the idea is to place both human and bot spawn points across the map where needed and to only have a set of them enabled so players won't spawn in the wrong places. This will be managed by the VScript functions <code>OnSpawnsReset()</code> and <code>OnWaveCompleted()</code> that we will deal with later, see [[#Explanation of Code]].
{{note|Remember to place spawn point entities at least 8 units above the ground or players might not spawn properly.}}
{{note|Player spawn entities are [[preserved entities]]. When a new round starts, their properties don't reset. That's why a Co-op VScript comes in handy.}}
 
==== Human Player Spawns ====
The human players (re)spawn at enabled [[info_player_counterterrorist]] entities.
 
It is a good idea to have a spawn point where the players can "relax" and setup for the fights that are about to commence. For that purpose, Valve has made spawn rooms in their Co-op maps where the players can choose weapons and grenades that they will use in the upcoming level. There can also be a way to adjust the difficulty of the bots so that the level is playable in [[#Hard Mode]]. For better gameplay, give the players "crappy" weapons at the beginning so they will look around in your map for better gear.
 
The way you create your spawn is up to you. You can either have a simple door divide the spawn with the enemies or you could have a fancy helicopter "cutscene" take you to the actual level. Be as creative as you can be.
 
If the human players can die in the mission (which will most likely be the case!) and if you don't want the human players to respawn at their very first spawn points of the map, you can place more CT spawns as "checkpoints" and leave them <code>Disabled</code> by default. The Co-op VScript later can access these.


Co-op is based around a "Wave" system. This means that there is a group of enemies, usually 5, that the player has to exterminate in order to advance to the next part of the map. So when creating the map split your map up in multiple parts. Each part will have its own enemies by your choosing. Unles you want one big linear map with 40 enemies at once. Split your map up in different parts so that you can only advance once the "Wave" is completed.
==== Enemy Spawns ====
=== Player Spawn ===
[[File:Csgo coop info enemy terrorist spawn.png|right]]
The players will need a spawnpoint where they can "relax" and setup for the fight that is about to commence. In the spawnroom the player will have to choose weapons and grenades that they will use in the upcoming level. In the spawn there should also be a way to adjust the difficulty of the bots so that the level is playable in "hardcore mode". For better gameplay give the players "crappy" weapons at the beginning so they will look around in your map for better gear.
The enemy bots (re)spawn at enabled [[info_enemy_terrorist_spawn]] entities.


The way you create your spawn is up to you. You can either have a simple door devide the spawn with the enemies or you coul have a fancy helicopter "cutscene" take you to the actual level. Be as creative as you can be.
For each section in your map you will need to have these entities in order for bots to spawn. Also give all of these spawn points in a section the same name. Say for the first section of the map you will enter, you name all the [[info_enemy_terrorist_spawn]] entities <code>wave_01</code>. Do this for each section of your map in chronological order, e.g. <code>wave_02</code>, <code>wave_03</code>, and so forth.
=== Must have Co-op Entities ===
In order for Co-op strike to function properly you'll have to place a [[logic_script]] and [[game_coopmission_manager]] inside your level. Give them an easy name to find back later.
=== Enemy Spawn points ===
[[info_enemy_terrorist_spawn]] Are the entities where the enemy bots will be spawning. For each section in your map you will need to have these entities in order for bots to spawn. Also per section give those spawnpoints their own name. So lets say for the first section/part of the may you will enter you name all the [[info_enemy_terrorist_spawn]] "wave_01". Do this for each section of your map in chronological order(eg, wave_02, wave_03. etc)


http://i.imgur.com/A4eY6B7.png
You can give the spawn points different properties.
* For starters you can give them weapons. <code>glock</code> is the default weapon but you can add weapons by using the comma character <code>,</code> so you can set something like <code>glock, ak47</code> and the bot on that location will spawn with a [[weapon_glock]] and a [[weapon_ak47]].
* You can also give the bot a different player model by using the <code>Override player model</code> [[keyvalue]]. One example for this is <code>tm_phoenix_heavy.mdl</code> which is also used in ''coop_cementplant''. More model names can be found [[Choosing Player Models#Model List|here]].
After you've chosen your properties you need to set <code>Enabled by default</code> to <code>No</code>, except for the first wave of enemies that you come across those need to be <code>Enabled</code> instead of <code>Disabled</code>.


You can give the spawnpoints different properties. For starters you can give them weapons. glock is the default weapon but you can add weapon by using the "," so you can get something like "glock, ak47" and the bot on that location will spawn with a glock and a ak47. You can also give the bot a different player model by using the "Override player model". One example of this is "tm_phoenix_heavy.mdl" which is also used in coop_cementplant. After you've chosen your properties you need to set "Enabled by default" on "No" Later in the script that will have to be made for a Co-op map you will enable the desired spawn so enemies wont spawn in the wrong places. It is very important that this is done.
Remember to place spawnpoint atleast 8 units above the ground or bots might not spawn properly. (same goes for playerspawns)
=== Doorways to new Sections ===
=== Doorways to new Sections ===
Since you have to devide your map into different sections you will need to have doorways that connect these sections and can only be accesed once a "Wave" is completed. Simply put, put down a prop_door_rotating between your sections, lock them so players cant rush through the map without completing the waves and give them a proper name so you can find them later when you're working on your script.
Since you have to divide your map into different sections you will need to have doorways that connect these sections and can only be accesed once a wave is completed. Simply put, put down a [[prop_door_rotating]] between your sections, lock them so players cannot rush through the map without completing the waves and give them a proper name so you can find them later when you're working on your script.
 
=== Collectible Coins ===
=== Collectible Coins ===
If you want players to explore your map more in order to get more points you can use the [[item_coop_coin]] once all 3 coins are collected in a level the players will get bonus points at the end of the level. As of right now 3 coins is the minimum and maximum of coins that can be collected. So if you have 2 coins in your map, the players will never be able to get the bonus points. You can have more than 3 coins but this has no extra effect. Once the players have 3 coins they get the bonus points. Collecting more than 3 coins give nothing extra as of writing this tutorial.
If you want players to explore your map more in order to get more points you can use the [[item_coop_coin]]. Once all 3 coins are collected in a level the players will get bonus points at the end of the level. Exactly 3 coins should be placed in a map: If you have 2 coins, the players will never be able to get the bonus points; Collecting more than 3 coins has the same effect as collecting only 3.
=== Co-op Weapons/Items/Ammo ===
 
You have 2 new Items that can be used in Co-op Strike maps. You have the [[weapon_healthshot]] and the [[weapon_tagrenade]]. The healthshot can be used to heal the player and the tagrenade is used for a short "wallhack" to know where the enemies are for a brief amount of time. Healthshot are good to give before a difficult next fight. Do not give too many Healthshot otherwise your map will be to easy for the player.
=== Co-op Gear ===
Here is some inspiration of what you can or should supply the human players with throughout the map:
;Weapons
:See [[:Category: Counter-Strike: Global Offensive Weapons]] for a list of weapons. There are multiple ideas to supply players with new weapons.
:*Use map-placed weapon entities, such as [[weapon_ak47]], which can only be picked up once per round.
:*Equip bots with them that the players will kill and loot.
:*A simple "infinite" weapon pickup can be created with an invisible, non-solid [[func_button]] and a [[game_player_equip]] entity together with a [[prop_dynamic]] of the corresponding weapon.
:*[[CS:GO VScript Examples#Equip players|VScript can also handle the equipping]].
 
;[[weapon_healthshot]]
:Players can use healthshots to heal themselves. They are good to be given before a difficult fight. Do not give too many healthshots, otherwise your map will be to easy.
 
;[[weapon_tagrenade]]
:The tagrenade grants a short "wallhack" effect: It makes enemies close to its explosion glow through walls for a brief moment.
 
;[[point_give_ammo]]
:If this entity receives the <code>GiveAmmo</code> input, it gives the activator full ammo for all his weapons. In ''coop_cementplant'' they used the ammo models <code>models\props\coop_cementplant\coop_ammo_stash\coop_ammo_stash_full.mdl</code> and <code>\coop_ammo_stash_empty.mdl</code>, when once used, the model changes from the former to the latter. Make it so that players can only take ammo from that point once so they can't run back in the level to restock on ammo again.
 
;[[prop_ammo_box_generic]]
:Each time this entity is [[+use]]d, the reserve ammo of the activator's active weapon is increased by one clip size. The entity can be used 4 times.
 
;[[prop_weapon_refill_heavyarmor]]
:Don't forget about armor: As the players will lose armor points with each fight, they will soon appreciate this entity which can be [[+use]]d by one player to replenish his armor to 200 points.
 
;[[weapon_zone_repulsor]]
:{{todo}}


Ammo is also crucial in fights. When the player runs out of ammo they will have to switch to knifing which is the greatest trategy against a Heavy Phoenix. With the use of [[point_give_ammo]] You can give the player that calls for this entitie full ammo again. In coop_cementplant they used the ammo model when once pressed the model changes to the same model but without the bullets. Make it so that players can only take ammo from that point once so they cant run back in the level to restock on ammo again.
=== Co-op Tasks ===
=== Co-op Tasks ===
Since you are trying to make a coop(cooperative) map, it is fun to include simples puzzles and task that can only be achived if 2 players work together. It can go from once player standing on an elevator and the other activating this elevator or a door with 2 levers to one player being blind and the other has to guide him/her thought a darkroom. Be creative!
Since you are trying to make a ''cooperative'' map, it is fun to include simple puzzles and tasks that can only be achieved if players work together. It can go from one player standing on an elevator and the other activating this elevator or a door with 2 levers to one player being blind and the other has to guide him/her through a dark room. Be creative!
 
=== Glowing props ===
=== Glowing props ===
Use glowing Doors or buttons to tell the player "Go here to advance" or "Press me to advance". You can make it so that a prop (the doorway to the next part of the map) is glowing so its easy for players to find their way through your map.
Use glowing doors or buttons to tell the players "Go here to advance" or "Press me to advance". You can make props (the doorway to the next part of the map) glow so it's easy for players to find their way through your map.


http://i.imgur.com/dSNml7O.png
[[File:Csgo coop map example.png|center]]


= Creating the Script =
== Creating the Script ==
Co-op Strike uses [[VScript]] to make the system function. Without the script the gamemode cant work properly. So each Co-op map will have its own script.
Co-op Strike uses [[VScript]] written in {{sq}} [[Squirrel]] to make the system function. Without the script the game mode can't work properly, so each Co-op map needs its own script.
Start by creating your script and give it a name. For example <code>cooptutorial.nut</code>. Make sure and this is important that the extension of the file is '''.nut''' otherwise the game wont be able to read the file. Now place this file in the correct folder inside your gamefiles. For Example: <code>Steam\steamapps\common\Counter-Strike Global Offensive\csgo\scripts\vscripts\custom</code>. Make sure its inside the Vscripts folder.
* Start by creating your script (text file) and give it a name, for example <code>cooptutorial.nut</code>. Important: Make sure that the extension of the file is '''.nut''', otherwise the game won't be able to read the file.
* Now place this file in the correct folder inside your game files, for example <code>Steam/steamapps/common/Counter-Strike&nbsp;Global&nbsp;Offensive/csgo/scripts/vscripts/custom/</code>. Make sure it is somewhere inside the <code>vscripts</code> folder. Subdirectories are arbitrary.
Once you've placed it inside the correct folder you can start editing it with notepad or any other text editor.
Once you've placed it inside the correct folder you can start editing it with notepad or any other text editor.
This script will be later be used for the <code>Entity Scripts</code> property of a [[logic_script]], which means that the script will be executed each time a new round begins. Variables and functions ("table slots" to be precise) will be saved after the execution and can be called when firing the inputs <code>RunScriptCode</code> or <code>RunScriptFunction</code> to that logic_script.


=== Code used in Example ===
=== Code used in Example ===
Here an example of a Co-op Script. Feel free to copy this inside your own script file since alot is usefull for every Co-op Strike map script.
Here an example of a Co-op Script. Feel free to copy this into your own script file since much of it is useful for every Co-op Strike map script.
An example vmf will be provided at the end of this Guide that works together with this script.
An example vmf will be provided at the end of this guide that works together with this script.
<syntaxhighlight lang="cpp">
{| class="mw-collapsible mw-collapsed" style="background:none"
|+ style=text-align:left|
| <syntaxhighlight lang="cpp">
wave <- 0;
wave <- 0;


function RoundInit(){
function RoundInit()
{
//Will do this everytime you start the map/round because we call it in the OnLevelReset
//Will do this everytime you start the map/round because we call it in the OnLevelReset
wave = 0;
wave = 0;
Line 90: Line 149:
}
}


function SpawnNextWave( amount ){
function SpawnNextWave( amount )
{
ScriptCoopMissionSpawnNextWave( amount );
ScriptCoopMissionSpawnNextWave( amount );
wave++;
wave++;
Line 155: Line 215:
}
}
</syntaxhighlight>
</syntaxhighlight>
|}
=== Explanation of Code ===
=== Explanation of Code ===
Ill go over everything inside the script and explain what it all does.
We will go over everything inside the script and explain what it all does.
<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
wave <- 0;
wave <- 0;


function RoundInit(){
function RoundInit()
{
//Will do this everytime you start the map/round because we call it in the OnLevelReset
//Will do this everytime you start the map/round because we call it in the OnLevelReset
wave = 0;
wave = 0;
Line 168: Line 231:
}
}
</syntaxhighlight>
</syntaxhighlight>
First <code>wave <- 0;</code> What we do here is initialize a variable that we will call for in later functions. Functions are names for larger pieces of code that do multiple things after each other. so we have the function <code>RoundInit()</code> that sets the variable <code>wave</code> to 0. After that it tells the console to set the bot difficulty to 1 (the easiest). After this it refreshes all the bot spawns.
First <code>wave <- 0;</code>: What we do here is define and initialize a variable that functions can call later. We have the function <code>RoundInit()</code> that sets the variable <code>wave</code> to 0. After that it tells the console to set the bot difficulty to 1, the easiest. After this it refreshes all the bot spawns.
<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
function ChangeGameModeToCoopIfNotCorrect()
function ChangeGameModeToCoopIfNotCorrect()
Line 177: Line 240:
         local map = GetMapName();
         local map = GetMapName();


if (game_mode != 1 || game_type != 4)
if (game_type != 4 || game_mode != 1)
{
{
SendToConsole("game_mode 1; game_type 4; changelevel " + map);
SendToConsole("game_type 4; game_mode 1; changelevel " + map);
}
}
}
}
</syntaxhighlight>
</syntaxhighlight>
What this function <code>ChangeGameModeToCoopIfNotCorrect()</code> does is it changes the game_mode and game_type to the correct ones so that the game knows its playing a Co-op map. Sadly valve didnt set it up that the game knows its a coop map with the prefix coop_ . You dont really have to know how this works just call this function when the map is startet (OnMapSpawn). More on this in "Making your Script work with your Map"
The function <code>ChangeGameModeToCoopIfNotCorrect()</code> changes the [[game_type]] and [[game_mode]] to 4 and 1 so that the game knows its playing a Co-op map. The <code>coop_</code> map prefix is not sufficient to get the game mode right. You don't really have to know how this works; Just call this function when the map is started with the <code>OnMapSpawn</code> output of a [[logic_auto]]. More on this in [[#Making your Script work with your Map]].
<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
function SpawnFirstEnemies( amount )
function SpawnFirstEnemies( amount )
{
{
ScriptCoopMissionSpawnFirstEnemies( amount );
ScriptCoopMissionSpawnFirstEnemies( amount );
ScriptCoopResetRoundStartTime();
ScriptCoopResetRoundStartTime(); // sets round time to 45 minutes
wave++;
wave++;
}
}


function SpawnNextWave( amount ){
function SpawnNextWave( amount )
{
ScriptCoopMissionSpawnNextWave( amount );
ScriptCoopMissionSpawnNextWave( amount );
wave++;
wave++;
}
}
</syntaxhighlight>
</syntaxhighlight>
These are the 2 functions that will make the bots spawn. <code>SpawnFirstEnemies(amount)</code> Will spawn the first wave of your level and reset the timer to 15 minutes. Within the ( ) there is amount, <code>(amount). From within Hammer we will cal this function and give it an amount to spawn. So if we want 3 bots to spawn we would use this function like this: <code>SpawnFirstEnemies(3)</code> What it also does <code>wave++</code> which means that it adds 1 to the variable <code>wave</code> so when the level starts <code>wave</code> is 0 but once a wave is spawns it adds 1 so <code>wave = 1</code>. <code>SpawnNextWave(amount)</code> is used in every next wave. We use the variable <code>wave</code> to let the map know at which wave the players currently are.
These are the 2 functions that will make the bots spawn. <code>SpawnFirstEnemies(amount)</code> will spawn the first wave of your level and reset the timer to 45 minutes. From within [[Hammer]] we will call this function and replace <code>amount</code> with a number of enemies to spawn. So if we want 3 bots to spawn we call <code>SpawnFirstEnemies(3)</code>. What it also does is <code>wave++</code> which means that it adds 1 to the variable <code>wave</code> so when the level starts <code>wave</code> is 0 but once a wave is spawned, it adds 1 so that <code>wave == 1</code>. <code>SpawnNextWave(amount)</code> is used in every subsequent wave. We use the variable <code>wave</code> to let the map know at which wave the players currently are.
<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
function SpawnFirstEnemies( amount )
function OnMissionCompleted()
function OnMissionCompleted()
{
{
Line 218: Line 281:
}
}
</syntaxhighlight>
</syntaxhighlight>
The names of the functions already say when they should be used. As in coop_cementplant Valve made it so that your "Boss" gives a little message.
The names of the functions say it all. As in ''coop_cementplant'', Valve made it so that your "Boss" gives a little message.
<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
function OnRoundReset()  
function OnRoundReset()  
Line 238: Line 301:
}
}
</syntaxhighlight>
</syntaxhighlight>
<code>OnRoundReset()</code> is called when the players have died and the round "resets" we call for the function <code>RoundInit()</code>. <code>RoundInit()</code> is explained above.
<code>OnRoundReset()</code> is called when the players have died and the round "resets". It calls the function <code>RoundInit()</code>, which is explained above.
The we have <code>OnSpawnsReset()</code>. This is called just before the round resets. This gives the map time to reset the player and enemy spawns to its original state. Here we Disable every <code>wave_</code> entity and enable only the first wave for enemies. You can do the same for CT spawns. Multiple CT spawns are used in bigger levels so that the player doesnt have to walk from spawn to the point they were if 1 player died and respawned.
 
Entfire is seen as an Output like in Hammer Could be seen as the Output <code>OnPressed - wave_* - SetDisabled</code>.
Then we have <code>OnSpawnsReset()</code>. This is called just before the round resets. This gives the map time to reset the player and enemy spawns to its original state. Here we Disable every entity whose targetname starts with <code>wave_</code> and enable only the first wave for enemies. You can do the same for CT spawns. Multiple CT spawns are used in bigger levels so that the players don't have to walk from their first spawn to the point where one player died.
<code>EntFire</code> is used for [[I/O]] like in Hammer, but here we don't need to specify an output. Normally, the output defines "when" an input should be fired, but in VScript, that point in time is when the <code>EntFire</code> line is executed. For example <code>EntFire( "wave_*", "SetDisabled", "", 0 )</code> fires the input <code>SetDisabled</code> to all entities starting with "wave_", with an empty parameter override (<code>""</code>) and no delay (<code>0</code>).
<syntaxhighlight lang="cpp">
<syntaxhighlight lang="cpp">
function OnWaveCompleted()
function OnWaveCompleted()
Line 266: Line 330:
}
}
</syntaxhighlight>
</syntaxhighlight>
Last we have OnWaveCompleted. This is called when you've killed every enemy of a wave. Because we keep track on which wave we are with the variable <code>wave</code> we can do different thing for different waves. Here we say: "If wave = 1" it disables all the enemy spawns but the spawnpoint for wave2. We also unlock the door to the next section of the map and set the door to Glow so its easier for the players to find their way.
Last we have <code>OnWaveCompleted</code>. This is called when you've killed every enemy of a wave. Because we keep track on which wave we are with the variable <code>wave</code>, we can do different things for different waves. Here we say: "If <code>wave</code> equals 1" then it disables all the enemy spawns but the spawn point for wave 2. We also unlock the door to the next section of the map and set the door to glow so it is easier for the players to find their way.
 
This is all the code that is needed for a working Co-op map. If you didn't quite understand a lot of this, try copying the code from here into your own.


This is all the code that is needed for a working co-op map. If you didnt quite understand alot of this try copying the code from here into your own.
=== Info about Code ===
=== Info about Code ===
There are a few functions that can be used to do different things.
There are a few functions that can be used to do different things.
* ScriptCoopMissionSpawnFirstEnemies(#); Spawns the first enemies
* <code>ScriptCoopResetRoundStartTime()</code> - Resets the roundtime to 45 minutes.
* ScriptCoopResetRoundStartTime(); Resets the roundtime
* <code>ScriptCoopMissionSpawnFirstEnemies(#)</code> - Spawns the first <code>#</code> enemies.
* ScriptCoopMissionSpawnNextWave(#); Spawns a new wave # is the amount you want to spawn eg, ScriptCoopMissionSpawnNextWave(5)
* <code>ScriptCoopMissionSpawnNextWave(#)</code> - Spawns a new wave, where <code>#</code> is the number of enemies you want to spawn, for example <code>ScriptCoopMissionSpawnNextWave(5)</code>.
* ScriptCoopMissionRespawnDeadPlayers(); When this is called for it will respawn all dead CT's.
* <code>ScriptCoopMissionRespawnDeadPlayers()</code> - When this is called, it will respawn all dead CTs.
When creating code you have to end every line where you have written something with a ";" but not when its a function or if there are brackets "{ or }", see the code given for reference.
{{note|There are way more, see [[List of CS:GO Script Functions]]. To learn more on how coding works, see [[VScript]] or {{sq}} [[Squirrel]] for more links.}}
To learn more on how coding work I suggest you look at [[VScript]] more links can be found there if intrested.
 
= Making your Script work with your Map =
== Making your Script work with your Map ==
We now have created a map and created our script but your map wont work without connecting the 2.
We now have created a map and our script but your map won't work without connecting them.
 
=== Setting up the entities to work with the script ===
=== Setting up the entities to work with the script ===
Earlier in this guid you probably created a logic_script somewhere in your map. If not do so now and name it something easy like "logic_script". Then go to the property "Entity Scripts", click on Manage... , click on the + and search for your script which we places in "scripts/vscripts/custom". Add it and we are done with the logic_script.
If you haven't already, create a [[logic_script]] and give it a simple name such as <code>logic_script</code>.
{{note|The targetname <code>logic_script</code> can be disadvantageous because outputs targeting <code>logic_script</code> will target all <code>logic_script</code> entities in the map. A targetname such as <code>coop_script</code> would avoid this because it is not a classname.}}
Go to the property <code>Entity Scripts</code>, click on <code>Manage...</code>, click on the <code>+</code> and search for your script which should be placed in a subfolder of <code>csgo/scripts/vscripts/</code>. Add it and the logic_script is done.


http://i.imgur.com/tUJ0YOe.png
[[File:Csgo coop logic script.png|center]]


Now we should have also placed a game_coopmission_manager, go to this entity and go to its outputs. The properties are not important. Now for every Output, except for the OnUser ones you create one. So for example: "OnMissionCompleted - logic_script - RunScriptCode - OnMissionCompleted()"
There should also be a [[game_coopmission_manager]] entity in the map. Go to its outputs and create one for every output that exists (except for the <code>OnUser</code> ones).
What this output does is it call for the script function OnMissionCompleted() that we created in the scripting part. Do the same for all the other outputs with its names as the Parameter.


http://i.imgur.com/IJ0GYU4.png
[[File:Csgo coop game manager outputs.png|center]]
 
These outputs call the script functions that we created in the scripting part.
{{note|The script function names are arbitrary, it's just that they must be the same in the script file and in the parameter value of these outputs.}}


=== Setting up the doorways between sections ===
=== Setting up the doorways between sections ===
Since Co-op Strike is a waved base system we have different section in the map. With each section being unlocked when a wave is completed. Now we need to make sure that enemies will spawn once you enter a new section. So what we want to do is Spawn the bots when you for example open the door to the next section.  
Since Co-op Strike is a wave based system, we usually want to divide the map into sections with each section being unlocked when a wave is completed. Now we need to make sure that enemies will spawn once you enter a new section. So for example, we want to spawn bots when the players open the door to the next section.
An output would look like this: "OnOpen - logic_script - RunScriptCode - SpawnFirstEnemies(3)" this for the first Wave
An output would look like this:
And for the rest of the waves "OnOpen - logic_script - RunScriptCode - SpawnNextWave(5)"
{| {{OutputsTable}}
Of course you do not have to use door you can use whatever entity you'd like.
| [[File:Io11.png]] || OnOpen || logic_script || RunScriptCode || SpawnFirstEnemies(3) || 0.00 || No
= Finishing touches =
|}
Do this for the first wave.
For the other waves, use this:
{| {{OutputsTable}}
| [[File:Io11.png]] || OnOpen || logic_script || RunScriptCode || SpawnNextWave(5) || 0.00 || No
|}
Of course you do not have to use a door - you can use whatever entity you'd like, such as [[trigger_once]] (OnTrigger), [[func_button]] (OnPressed), etc.
 
== Finishing touches ==
Just a few more things to think about to complete the map.
 
=== Ending the Map ===
=== Ending the Map ===
Just a few more things to think about to complete out map.
If you want the map to reload in the right [[game_type]] and [[game_mode]] if they were wrong, create a [[logic_auto]] and add the output:
First we want out map to fix itself so create a logic_auto and add the output: "OnMapSpawn - logic_script - RunScriptCode - ChangeGameModeToCoopIfNotCorrect()"
 
Secondsly if you have a hostage map all you need to finish your map is a hostage and a hostage rescue zone. If however you do not have a hostage in your map and just want the players to get to an end point you'll have to use a [[game_round_end]]. Setup a trigger at the end of your map with the output: "OnStartTouch - game_round_end - EndRound_CounterTerroristsWin"
[[File:Csgo coop change game mode.png|center]]
And voila your map is fully playable.
 
Secondly, if you have a [[hostage_entity]] in the map, the players can win the map by bringing it to a [[func_hostage_rescue]].
If you want the players to win by getting to an end point you'll have to use a [[game_round_end]]. Create a [[trigger]] at the end of your map with the output:
 
{| {{OutputsTable}}
| [[File:Io11.png]] || OnStartTouch || game_round_end || EndRound_CounterTerroristsWin || 5 || 0.00 || No
|}


http://i.imgur.com/C2SUVCe.png
And voilà, your map is fully playable.


=== Proper bot navigation ===
=== Proper bot navigation ===
Since you are playing against bots you'll have to make a proper navigation file so your bots dont look as much like bots. With the commands listed here: [[Navigation_Mesh_Commands]] you can do many thing to improve the navigation of bots. You can also put [[point_hiding_spot]]s in your map to tell your bots that, that is a good spot for them to hide.
Since you are playing against [[bot]]s you'll have to make a proper navigation file so your bots don't look as much like bots. With the commands listed at [[Nav Mesh Commands|Navigation Mesh Commands]] and [[Nav Mesh Editing|Navigation Mesh Editing]], you can do many things to improve the bot navigation. You can also put [[point_hiding_spot]]s in your map to control where bots should hide.
= Testing your map =
 
Now that your map is complete you'll have to test it ingame.
=== Hard Mode ===
all you have to do is open up your console type in "map mymapname" and it will load your map. If the gamemode or gametype are not correct the map should reload itself and set thos to the correct values.
As with ''coop_cementplant'' and all succeeding Co-op maps by Valve, there was a secret lever to play the map in Hard Mode to get extra points at the end of the game. To do that, you'll have to set the console variable <code>mp_coopmission_bot_difficulty_offset</code> with a [[point_servercommand]]. The value 1 stands for the easiest mode; If set to 5, the game will register that it's in Hard Mode. If you really want to give your players a challenge, use an offset of 7. You can also give your [[info_enemy_terrorist_spawn]] entities a difficulty which stacks on top of the one that is set with <code>mp_coopmission_bot_difficulty_offset</code>.
 
== Testing your Map ==
Now that your map is complete you'll have to test it in-game.
All you have to do is open up your console, type in <code>[[map (console command)|map]] <mapname> coop</code> and it will load your map. If <code>coop</code> is omitted, the game_type and/or game_mode are most likely not correct, so if you have set up the script function <code>ChangeGameModeToCoopIfNotCorrect</code>, the map should reload itself and set those to the correct values.
 
Make sure to check the console for VScript errors whenever code will be executed. Examples:
<pre style="background:#444; color:#ddd; border-color:#666">
<filename>.nut line = (1) column = (26) : error expression expected
FAILED to compile and execute script file named scripts/vscripts/<path>/<filename>.nut
</pre>
<pre style="background:#444; color:#ddd; border-color:#666">
AN ERROR HAS OCCURED [the index 'wave' does not exist]
 
CALLSTACK
*FUNCTION [main()] <filename>.nut line [1]
 
LOCALS
[this] TABLE
</pre>
 
{{tip|For debugging, it can make sense to add lines in the code that print a message or the current value of a variable, such as <code>println("...")</code> or <code>ScriptPrintMessageChatAll("...")</code>.}}
 
 


I hope this guide will help alot of people. Happy Mapping :)
I hope this guide will help a lot of people. Happy Mapping :)


Here is an example of a working simple co-op map with its script:
== External links ==
https://www.dropbox.com/s/val79djogsjzw9z/Creating%20a%20Co-op%20Strike%20Map%20Example.rar?dl=0
Here is an example of a working simple Co-op map with its script:
https://www.dropbox.com/s/val79djogsjzw9z/Creating%20a%20Co-op%20Strike%20Map%20Example.rar?dl=0{{csgo-navbox}}
[[Category: Counter-Strike: Global Offensive]]
[[Category: Level Design]]
[[Category: Tutorials]]

Latest revision as of 05:46, 12 July 2024

English (en)Русский (ru)Translate (Translate)
Counter-Strike: Global Offensive Level Creation
Icon-delisted.png
This page documents information about a game or software, Counter-Strike: Global Offensive Counter-Strike: Global Offensive, that is no longer available for purchase or download digitally.
It is covered here for historical and technical reference.
Csgo icon coopstrike.png

Co-op Strike (internally: coopmission) is a cooperative game mode in Counter-Strike: Global Offensive Counter-Strike: Global Offensive.

It was first introduced as part of the Operation Wildfire Gemini Campaign. And now on the Steam Community Workshop. Like CS:GO Guardian Guardian, it is exclusively available through Operations or the Steam Workshop, but can be easily accessed through the console.

In Co-op Strike, two human players go against a staged fight against an AI controlled terrorist team in a story-driven scenario. The map prefix for these maps is coop_. It shares the same prefix as some custom community Co-op game modes.

Creating a Co-op Strike map in Valve's style is a long process and it is expected from the readers that they have basic knowledge on how to create maps and work with entities, I/O, along with a basic knowledge of VScript. It is not advised to create a Co-op Strike map if there is no prior experience in mapping.

Game Mode Description

If a standard map is loaded in this game mode, this game mode is technically comparable with CS:GO/CS2 Competitive Competitive, but with the following differences:

Creating the Map

Entities used in Co-op Strike

These are entities introduced with the Co-op Strike game mode along with some other entities that will be used in this tutorial.

  • info_enemy_terrorist_spawn: The places where the enemy bots will spawn. No other spawn entities are used for them. It is the Co-op variant of info_player_terrorist, so to speak.
  • logic_script: The entity we connect out VScript to in order to be able to use functions via I/O.
  • game_coopmission_manager: This entity fires outputs when special Co-op events occur, for example when a wave is completed.
  • item_coop_coin: The secret Co-op coin for extra points at the end of the level. At the moment, exactly 3 coins need to be in a map for the Co-op coin system to work.
  • point_hiding_spot: Simply said, this is an entity that tells the bots "Here is a good hiding spot".
  • prop_exploding_barrel: The oh so great exploding barrels. Place them a few units above the ground to prevent them from getting "sucked" into it.
  • info_hostage_spawn: Rescuing the hostage is one way of completing the level.
  • game_round_end: This entity can end rounds on command and make a team win. Used in Co-op maps where rescuing a hostage is not the winning condition.

The entities above will be the entities that will be used in Co-op maps.

Environment

When starting your map keep Co-op in your mind. Make sure there are plenty of hiding spots for either the players or the bots. Think of places where you want to place new weapons for the players to use. Think of maybe nifty ways to use the environment to the players' advantage. Note that it is players vs. AI which is different from any other game mode.

Co-op is based around a "wave" system. This means that a group of enemies will spawn, usually 5, that the players has to exterminate in order to advance to the next part of the map. So when creating the map, split your map up in multiple parts. Each part will have its own enemies by your choosing. Unless you want one big linear map with 40 enemies at once. Split your map up in different parts so that you can only advance once each wave is completed.

Player Spawns

In this game mode, the idea is to place both human and bot spawn points across the map where needed and to only have a set of them enabled so players won't spawn in the wrong places. This will be managed by the VScript functions OnSpawnsReset() and OnWaveCompleted() that we will deal with later, see #Explanation of Code.

Note.pngNote:Remember to place spawn point entities at least 8 units above the ground or players might not spawn properly.
Note.pngNote:Player spawn entities are preserved entities. When a new round starts, their properties don't reset. That's why a Co-op VScript comes in handy.

Human Player Spawns

The human players (re)spawn at enabled info_player_counterterrorist entities.

It is a good idea to have a spawn point where the players can "relax" and setup for the fights that are about to commence. For that purpose, Valve has made spawn rooms in their Co-op maps where the players can choose weapons and grenades that they will use in the upcoming level. There can also be a way to adjust the difficulty of the bots so that the level is playable in #Hard Mode. For better gameplay, give the players "crappy" weapons at the beginning so they will look around in your map for better gear.

The way you create your spawn is up to you. You can either have a simple door divide the spawn with the enemies or you could have a fancy helicopter "cutscene" take you to the actual level. Be as creative as you can be.

If the human players can die in the mission (which will most likely be the case!) and if you don't want the human players to respawn at their very first spawn points of the map, you can place more CT spawns as "checkpoints" and leave them Disabled by default. The Co-op VScript later can access these.

Enemy Spawns

Csgo coop info enemy terrorist spawn.png

The enemy bots (re)spawn at enabled info_enemy_terrorist_spawn entities.

For each section in your map you will need to have these entities in order for bots to spawn. Also give all of these spawn points in a section the same name. Say for the first section of the map you will enter, you name all the info_enemy_terrorist_spawn entities wave_01. Do this for each section of your map in chronological order, e.g. wave_02, wave_03, and so forth.

You can give the spawn points different properties.

  • For starters you can give them weapons. glock is the default weapon but you can add weapons by using the comma character , so you can set something like glock, ak47 and the bot on that location will spawn with a weapon_glock and a weapon_ak47.
  • You can also give the bot a different player model by using the Override player model keyvalue. One example for this is tm_phoenix_heavy.mdl which is also used in coop_cementplant. More model names can be found here.

After you've chosen your properties you need to set Enabled by default to No, except for the first wave of enemies that you come across those need to be Enabled instead of Disabled.

Doorways to new Sections

Since you have to divide your map into different sections you will need to have doorways that connect these sections and can only be accesed once a wave is completed. Simply put, put down a prop_door_rotating between your sections, lock them so players cannot rush through the map without completing the waves and give them a proper name so you can find them later when you're working on your script.

Collectible Coins

If you want players to explore your map more in order to get more points you can use the item_coop_coin. Once all 3 coins are collected in a level the players will get bonus points at the end of the level. Exactly 3 coins should be placed in a map: If you have 2 coins, the players will never be able to get the bonus points; Collecting more than 3 coins has the same effect as collecting only 3.

Co-op Gear

Here is some inspiration of what you can or should supply the human players with throughout the map:

Weapons
See Category: Counter-Strike: Global Offensive Weapons for a list of weapons. There are multiple ideas to supply players with new weapons.
weapon_healthshot
Players can use healthshots to heal themselves. They are good to be given before a difficult fight. Do not give too many healthshots, otherwise your map will be to easy.
weapon_tagrenade
The tagrenade grants a short "wallhack" effect: It makes enemies close to its explosion glow through walls for a brief moment.
point_give_ammo
If this entity receives the GiveAmmo input, it gives the activator full ammo for all his weapons. In coop_cementplant they used the ammo models models\props\coop_cementplant\coop_ammo_stash\coop_ammo_stash_full.mdl and \coop_ammo_stash_empty.mdl, when once used, the model changes from the former to the latter. Make it so that players can only take ammo from that point once so they can't run back in the level to restock on ammo again.
prop_ammo_box_generic
Each time this entity is +used, the reserve ammo of the activator's active weapon is increased by one clip size. The entity can be used 4 times.
prop_weapon_refill_heavyarmor
Don't forget about armor: As the players will lose armor points with each fight, they will soon appreciate this entity which can be +used by one player to replenish his armor to 200 points.
weapon_zone_repulsor
[Todo]

Co-op Tasks

Since you are trying to make a cooperative map, it is fun to include simple puzzles and tasks that can only be achieved if players work together. It can go from one player standing on an elevator and the other activating this elevator or a door with 2 levers to one player being blind and the other has to guide him/her through a dark room. Be creative!

Glowing props

Use glowing doors or buttons to tell the players "Go here to advance" or "Press me to advance". You can make props (the doorway to the next part of the map) glow so it's easy for players to find their way through your map.

Csgo coop map example.png

Creating the Script

Co-op Strike uses VScript written in Squirrel Squirrel to make the system function. Without the script the game mode can't work properly, so each Co-op map needs its own script.

  • Start by creating your script (text file) and give it a name, for example cooptutorial.nut. Important: Make sure that the extension of the file is .nut, otherwise the game won't be able to read the file.
  • Now place this file in the correct folder inside your game files, for example Steam/steamapps/common/Counter-Strike Global Offensive/csgo/scripts/vscripts/custom/. Make sure it is somewhere inside the vscripts folder. Subdirectories are arbitrary.

Once you've placed it inside the correct folder you can start editing it with notepad or any other text editor.

This script will be later be used for the Entity Scripts property of a logic_script, which means that the script will be executed each time a new round begins. Variables and functions ("table slots" to be precise) will be saved after the execution and can be called when firing the inputs RunScriptCode or RunScriptFunction to that logic_script.

Code used in Example

Here an example of a Co-op Script. Feel free to copy this into your own script file since much of it is useful for every Co-op Strike map script. An example vmf will be provided at the end of this guide that works together with this script.

wave <- 0;

function RoundInit()
{
	//Will do this everytime you start the map/round because we call it in the OnLevelReset
	wave = 0;
	//Reset the difficulty to normal at start of the round
	SendToConsoleServer( "mp_coopmission_bot_difficulty_offset 1" );
	ScriptCoopSetBotQuotaAndRefreshSpawns( 0 );
}

function ChangeGameModeToCoopIfNotCorrect()
{
	// This will change the game mode and game type if the player has not initialized this before starting the map.
        local game_mode = ScriptGetGameMode();
        local game_type = ScriptGetGameType();
        local map = GetMapName();

	if (game_mode != 1 || game_type != 4)
	{
		SendToConsole("game_mode 1; game_type 4; changelevel " + map);
	}
}

function SpawnFirstEnemies( amount )
{
	ScriptCoopMissionSpawnFirstEnemies( amount );	
	ScriptCoopResetRoundStartTime();
	wave++;
}

function SpawnNextWave( amount )
{
	ScriptCoopMissionSpawnNextWave( amount );
	wave++;
}

function OnMissionCompleted()
{
	//what will happen once you've completed the mission (you could play a sound)
	
}

function OnRoundLostKilled()
{
	//what will happen if you loose the round because you died (you could tell the players that your grandma is better than them)
	
}

function OnRoundLostTime()
{
	//what will happen if you loose the round because the time runs out (you could tell the player that they are like turtles)
	
}

function OnRoundReset() 
{
	//called when the round resets
	// IMPORTANT: you need a game_coopmission_manager that has the output 'OnLevelReset' when this is called you NEED to call this function
	// in order for the level to work properly every round!
	RoundInit();
}

function OnSpawnsReset()
{
	//called right before the round resets (usually used for correcting stuff when on a new round other stuff is immediately called)
	//enabled/disabled the correct spawns for the start. * means every group going from Terrorist_00 to infinite enemygroup_example
	EntFire( "wave_*", "SetDisabled", "", 0 );
	EntFire( "wave_01", "SetEnabled", "", 0 );
	EntFire( "CT_*", "SetDisabled", "", 0 );
	EntFire( "CT_1", "SetEnabled", "", 0 );
}

function OnWaveCompleted()
{	
	//Check which wave the player is and do stuff
	if ( wave == 1 )
	{
		EntFire( "wave_*", "SetDisabled", "", 0 );
		EntFire( "wave_02", "SetEnabled", "", 0 );
		EntFire( "door_wave_01", "Unlock", "", 1 );
		EntFire( "door_wave_01", "SetGlowEnabled", "", 1 );
	}
	else if ( wave == 2 )
	{
		EntFire( "wave_*", "SetDisabled", "", 0 );
		EntFire( "wave_03", "SetEnabled", "", 0 );
		EntFire( "door_wave_02", "Unlock", "", 1 );
		EntFire( "door_wave_02", "SetGlowEnabled", "", 1 );
	}
	else if ( wave == 3 )
	{
		EntFire( "door_wave_03", "Unlock", "", 1 );
		EntFire( "door_wave_03", "SetGlowEnabled", "", 1 );
	}
}

Explanation of Code

We will go over everything inside the script and explain what it all does.

wave <- 0;

function RoundInit()
{
	//Will do this everytime you start the map/round because we call it in the OnLevelReset
	wave = 0;
	//Reset the difficulty to normal at start of the round
	SendToConsoleServer( "mp_coopmission_bot_difficulty_offset 1" );
	ScriptCoopSetBotQuotaAndRefreshSpawns( 0 );
}

First wave <- 0;: What we do here is define and initialize a variable that functions can call later. We have the function RoundInit() that sets the variable wave to 0. After that it tells the console to set the bot difficulty to 1, the easiest. After this it refreshes all the bot spawns.

function ChangeGameModeToCoopIfNotCorrect()
{
	// This will change the game mode and game type if the player has not initialized this before starting the map.
        local game_mode = ScriptGetGameMode();
        local game_type = ScriptGetGameType();
        local map = GetMapName();

	if (game_type != 4 || game_mode != 1)
	{
		SendToConsole("game_type 4; game_mode 1; changelevel " + map);
	}
}

The function ChangeGameModeToCoopIfNotCorrect() changes the game_type and game_mode to 4 and 1 so that the game knows its playing a Co-op map. The coop_ map prefix is not sufficient to get the game mode right. You don't really have to know how this works; Just call this function when the map is started with the OnMapSpawn output of a logic_auto. More on this in #Making your Script work with your Map.

function SpawnFirstEnemies( amount )
{
	ScriptCoopMissionSpawnFirstEnemies( amount );	
	ScriptCoopResetRoundStartTime(); // sets round time to 45 minutes
	wave++;
}

function SpawnNextWave( amount )
{
	ScriptCoopMissionSpawnNextWave( amount );
	wave++;
}

These are the 2 functions that will make the bots spawn. SpawnFirstEnemies(amount) will spawn the first wave of your level and reset the timer to 45 minutes. From within Hammer we will call this function and replace amount with a number of enemies to spawn. So if we want 3 bots to spawn we call SpawnFirstEnemies(3). What it also does is wave++ which means that it adds 1 to the variable wave so when the level starts wave is 0 but once a wave is spawned, it adds 1 so that wave == 1. SpawnNextWave(amount) is used in every subsequent wave. We use the variable wave to let the map know at which wave the players currently are.

function OnMissionCompleted()
{
	//what will happen once you've completed the mission (you could play a sound)
	
}

function OnRoundLostKilled()
{
	//what will happen if you loose the round because you died (you could tell the players that your grandma is better than them)
	
}

function OnRoundLostTime()
{
	//what will happen if you loose the round because the time runs out (you could tell the player that they are like turtles)
	
}

The names of the functions say it all. As in coop_cementplant, Valve made it so that your "Boss" gives a little message.

function OnRoundReset() 
{
	//called when the round resets
	// IMPORTANT: you need a game_coopmission_manager that has the output 'OnLevelReset' when this is called you NEED to call this function
	// in order for the level to work properly every round!
	RoundInit();
}

function OnSpawnsReset()
{
	//called right before the round resets (usually used for correcting stuff when on a new round other stuff is immediately called)
	//enabled/disabled the correct spawns for the start. * means every group going from Terrorist_00 to infinite enemygroup_example
	EntFire( "wave_*", "SetDisabled", "", 0 );
	EntFire( "wave_01", "SetEnabled", "", 0 );
	EntFire( "CT_*", "SetDisabled", "", 0 );
	EntFire( "CT_1", "SetEnabled", "", 0 );
}

OnRoundReset() is called when the players have died and the round "resets". It calls the function RoundInit(), which is explained above.

Then we have OnSpawnsReset(). This is called just before the round resets. This gives the map time to reset the player and enemy spawns to its original state. Here we Disable every entity whose targetname starts with wave_ and enable only the first wave for enemies. You can do the same for CT spawns. Multiple CT spawns are used in bigger levels so that the players don't have to walk from their first spawn to the point where one player died. EntFire is used for I/O like in Hammer, but here we don't need to specify an output. Normally, the output defines "when" an input should be fired, but in VScript, that point in time is when the EntFire line is executed. For example EntFire( "wave_*", "SetDisabled", "", 0 ) fires the input SetDisabled to all entities starting with "wave_", with an empty parameter override ("") and no delay (0).

function OnWaveCompleted()
{	
	//Check which wave the player is and do stuff
	if ( wave == 1 )
	{
		EntFire( "wave_*", "SetDisabled", "", 0 );
		EntFire( "wave_02", "SetEnabled", "", 0 );
		EntFire( "door_wave_01", "Unlock", "", 1 );
		EntFire( "door_wave_01", "SetGlowEnabled", "", 1 );
	}
	else if ( wave == 2 )
	{
		EntFire( "wave_*", "SetDisabled", "", 0 );
		EntFire( "wave_03", "SetEnabled", "", 0 );
		EntFire( "door_wave_02", "Unlock", "", 1 );
		EntFire( "door_wave_02", "SetGlowEnabled", "", 1 );
	}
	else if ( wave == 3 )
	{
		EntFire( "door_wave_03", "Unlock", "", 1 );
		EntFire( "door_wave_03", "SetGlowEnabled", "", 1 );
	}
}

Last we have OnWaveCompleted. This is called when you've killed every enemy of a wave. Because we keep track on which wave we are with the variable wave, we can do different things for different waves. Here we say: "If wave equals 1" then it disables all the enemy spawns but the spawn point for wave 2. We also unlock the door to the next section of the map and set the door to glow so it is easier for the players to find their way.

This is all the code that is needed for a working Co-op map. If you didn't quite understand a lot of this, try copying the code from here into your own.

Info about Code

There are a few functions that can be used to do different things.

  • ScriptCoopResetRoundStartTime() - Resets the roundtime to 45 minutes.
  • ScriptCoopMissionSpawnFirstEnemies(#) - Spawns the first # enemies.
  • ScriptCoopMissionSpawnNextWave(#) - Spawns a new wave, where # is the number of enemies you want to spawn, for example ScriptCoopMissionSpawnNextWave(5).
  • ScriptCoopMissionRespawnDeadPlayers() - When this is called, it will respawn all dead CTs.
Note.pngNote:There are way more, see List of CS:GO Script Functions. To learn more on how coding works, see VScript or Squirrel Squirrel for more links.

Making your Script work with your Map

We now have created a map and our script but your map won't work without connecting them.

Setting up the entities to work with the script

If you haven't already, create a logic_script and give it a simple name such as logic_script.

Note.pngNote:The targetname logic_script can be disadvantageous because outputs targeting logic_script will target all logic_script entities in the map. A targetname such as coop_script would avoid this because it is not a classname.

Go to the property Entity Scripts, click on Manage..., click on the + and search for your script which should be placed in a subfolder of csgo/scripts/vscripts/. Add it and the logic_script is done.

Csgo coop logic script.png

There should also be a game_coopmission_manager entity in the map. Go to its outputs and create one for every output that exists (except for the OnUser ones).

Csgo coop game manager outputs.png

These outputs call the script functions that we created in the scripting part.

Note.pngNote:The script function names are arbitrary, it's just that they must be the same in the script file and in the parameter value of these outputs.

Setting up the doorways between sections

Since Co-op Strike is a wave based system, we usually want to divide the map into sections with each section being unlocked when a wave is completed. Now we need to make sure that enemies will spawn once you enter a new section. So for example, we want to spawn bots when the players open the door to the next section. An output would look like this:

  My Output Target Entity Target Input Parameter Delay Only Once
Io11.png OnOpen logic_script RunScriptCode SpawnFirstEnemies(3) 0.00 No

Do this for the first wave. For the other waves, use this:

  My Output Target Entity Target Input Parameter Delay Only Once
Io11.png OnOpen logic_script RunScriptCode SpawnNextWave(5) 0.00 No

Of course you do not have to use a door - you can use whatever entity you'd like, such as trigger_once (OnTrigger), func_button (OnPressed), etc.

Finishing touches

Just a few more things to think about to complete the map.

Ending the Map

If you want the map to reload in the right game_type and game_mode if they were wrong, create a logic_auto and add the output:

Csgo coop change game mode.png

Secondly, if you have a hostage_entity in the map, the players can win the map by bringing it to a func_hostage_rescue. If you want the players to win by getting to an end point you'll have to use a game_round_end. Create a trigger at the end of your map with the output:

  My Output Target Entity Target Input Parameter Delay Only Once
Io11.png OnStartTouch game_round_end EndRound_CounterTerroristsWin 5 0.00 No

And voilà, your map is fully playable.

Proper bot navigation

Since you are playing against bots you'll have to make a proper navigation file so your bots don't look as much like bots. With the commands listed at Navigation Mesh Commands and Navigation Mesh Editing, you can do many things to improve the bot navigation. You can also put point_hiding_spots in your map to control where bots should hide.

Hard Mode

As with coop_cementplant and all succeeding Co-op maps by Valve, there was a secret lever to play the map in Hard Mode to get extra points at the end of the game. To do that, you'll have to set the console variable mp_coopmission_bot_difficulty_offset with a point_servercommand. The value 1 stands for the easiest mode; If set to 5, the game will register that it's in Hard Mode. If you really want to give your players a challenge, use an offset of 7. You can also give your info_enemy_terrorist_spawn entities a difficulty which stacks on top of the one that is set with mp_coopmission_bot_difficulty_offset.

Testing your Map

Now that your map is complete you'll have to test it in-game. All you have to do is open up your console, type in map <mapname> coop and it will load your map. If coop is omitted, the game_type and/or game_mode are most likely not correct, so if you have set up the script function ChangeGameModeToCoopIfNotCorrect, the map should reload itself and set those to the correct values.

Make sure to check the console for VScript errors whenever code will be executed. Examples:

<filename>.nut line = (1) column = (26) : error expression expected
FAILED to compile and execute script file named scripts/vscripts/<path>/<filename>.nut
AN ERROR HAS OCCURED [the index 'wave' does not exist]

CALLSTACK
*FUNCTION [main()] <filename>.nut line [1]

LOCALS
[this] TABLE
Tip.pngTip:For debugging, it can make sense to add lines in the code that print a message or the current value of a variable, such as println("...") or ScriptPrintMessageChatAll("...").


I hope this guide will help a lot of people. Happy Mapping :)

External links

Here is an example of a working simple Co-op map with its script:

https://www.dropbox.com/s/val79djogsjzw9z/Creating%20a%20Co-op%20Strike%20Map%20Example.rar?dl=0