CSGO Quirks

From AlliedModders Wiki
Revision as of 12:47, 2 December 2012 by Psychonic (talk | contribs) (Created page with "''Others are encouraged to expand on this article with their findings or to clarify any information'' This article explains some of the quirks when coding for CS:GO and offer...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Others are encouraged to expand on this article with their findings or to clarify any information

This article explains some of the quirks when coding for CS:GO and offers some workarounds when available and other information.

Playing Sounds

Since Left 4 Dead, all normally played sounds must exist in the sound cache on the client. This is an issue for custom sounds as adding to the sound cache requires the client to run snd_rebuildaudiocache (not executable by the server), which also takes a sizable amount of time to run while otherwise locking up the game.


Note that with any of these methods, it is still required that you still add the sound to the download table if you need the client to download it from the server or "fastdl".

All of the listed workarounds involve explicitly telling the client to stream the sound directly from the disk rather than starting it from the cache. This is less than ideal, but seems to work well enough. These have only been made to work with mp3 files. A way to support wav files has not yet been found.

The "play" client command

If you don't need all of the flexibility that the EmitSound* natives expose and just need one or more clients to hear a sound, you can use the ClientCommand native with the 'play' command. The only difference from normal operation is the prefixing of an asterisk (*) to the path which denotes the sound to be streamed. For this method, you do not need to use PrecacheSound on the server.

Example: for csgo/sound/custom/ur.mp3

ClientCommand( client, "play *custom/ur.mp3" );

Fake precaching and EmitSound

For this method, you also need to make use of the asterisk trick. Unfortunately, the EmitSound natives will fail if the file is not listed in the soundprecache table, and PrecacheSound will fail if the file does not exist, (which is won't, as it treats the asterisk as part of the path when doing the lookup).

Since the sound will be streamed, not needing to actually be precached other than to satisfy the check in EmitSound, we can work around this by manually adding the path, with the asterisk prefixed, directly to the soundprecache table. Then you use the EmitSound native of choice as usual with the exception of the asterisk.

Full plugin example:

#include <sourcemod>
#include <sdktools>
new const String:FULL_SOUND_PATH[] = "sound/custom/ur.mp3";
new const String:RELATIVE_SOUND_PATH[] = "*custom/ur.mp3";
public OnPluginStart()
	RegConsoleCmd( "sm_testsound", sm_testsound );
public OnMapStart()
	AddFileToDownloadsTable( FULL_SOUND_PATH );
	FakePrecacheSound( RELATIVE_SOUND_PATH );
public Action:sm_testsound( client, argc )
	EmitSoundToClient( client, RELATIVE_SOUND_PATH );
	return Plugin_Handled;
stock FakePrecacheSound( const String:szPath[] )
	AddToStringTable( FindStringTable( "soundprecache" ), szPath );

Using the music directory

By adding your custom sounds under sound/music/, they will automatically be streamed from disk. They can also be used just like sounds in any other game with regard to PrecacheSound (albeit not necessary to be beyond adding to soundprecache table) and EmitSound.

This will have the side effect of your sounds volume being tied to the game's music volume, which many players turn down or off. For this reason, it's not recommended.

Max Players, Clients

CS:GO has four different values that all affect the maximum number of players that can join a game. The lowest one of the four determines the value used.

The absolute maximum

The current absolute maximum number of players for CS:GO, including GOTV is 64. This is a compile-time maximum in the engine on both client and server and cannot be changed.

(This is the maximum value as returned by IServerGameClients::GetPlayerLimits).

The engine's Maxclients

This is the number known as gpGlobals->maxClients in SM extensions or MM:S plugins and MaxClients in SourcePawn.

It is able to be changed in other games, up to the maximum, by setting the -maxplayers command line parameter. As this doesn't exist in CS:GO, it acts like other games when not set and uses a hardcoded default, 32 for CS:GO.

(This is the default value as returned by IServerGameClients::GetPlayerLimits).

You can also restore the -maxplayers command line functionality with the CS:GO Max plugin, allowing you to override the default value, up to the absolute maximum.

The GameTypes maxplayers

CS:GO has a new "GameTypes" system with it's own set of game mode and type -specifec params. There is more on this below, but it also includes a maxplayers value, also referred to as numSlots or MaxHumanPlayers in some areas.

This is the value set in gamemodes.txt or overridden in gamemodes_server.txt or overridden by the new -maxplayer_override command line parameter.

It is used for showing the maxplayers listed in the output of the status command as well as the max count used for the server browser (unless overridden by sv_visiblemaxplayers).

This does not include the count set by the "extraspectators" value in the gamemodes.txt, but both maxplayers and extraspectators must be equal or less than the engine's Maxclients.

The GameTypes max can be retrieved in SourcePawn with the new GetMaxHumanPlayers native or in C++ with IServerGameClients::GetMaxHumanPlayers.

Spawnpoint count

Regardless of the above values, you're limited by the running map's number of spawnpoints, evenly split per team (30 for stock maps).

You can use a mod like Stripper:Source or Spawn Tools 7 to add more spawnpoint entities.


This section refers to CHudMenu menus on the client triggered by the ShowMenu usermessage on the server. (Radio-style menus in SourceMod)

The older "Valve-style" menus created by IServerPluginHelpers::CreateMessage with the DIALOG_MENU type aren't supported at all due at least to missing res file info on the client.


At some larger resolutions, the client display of menus is grossly oversized.

This cannot be fixed from the server.

Input while observing

While observing, either dead or as spectator, the slot key inputs are captured by the specgui spectator panel and are not forwarded to the menu system. Therefore, the server never receives the menuselect commands resulting in menu choices being ignored.

The specgui vgui panel in CS:GO is one of the new Scaleform panels and thus does not respond to the normal hide panel requests from the server (with the VGUIMenu usermessage, show value of 0/false), else it could be hidden and blocked while menus are up and restored afterward.

The only known workaround is to block the specgui usermessage completely, causing it to never be shown in the first place. This would result in observers not being able to change their spectator target as, aside from that panel (which also catches spec_next, spec_prev, etc.), "buttons" (IN_ATTACK, IN_ATTACK2) are ignored while observing.

GameTypes / GameModes

CS:GO uses a new "GameTypes" system for coordinating server mode and type info between the server, client, and matchmaking, as well as for handling some server rules.

Some things handled by the GameTypes system:

  • Game types
  • Game modes
  • Config to execute for each mode
  • Weapon progression for applicable modes
  • Maps and map order for each mode
  • Maxplayers for each type and mode
  • Player and view models for each map
  • Bot difficulty
  • ELO ranking data

gamemodes.txt is the main data file (in KeyValues format) holding the backing info, with an optional gamemodes_server.txt being merged into it.

The gamemodes data files should not be accessed directly, but rather through the IGameTypes interface. None of it is currently exposed in SourceMod but there are plans to add a new extension giving access to much of the data.

In C++, you can easily get a pointer to the gametypes interface with CreateInterfaceFn from the matchmaking_ds binary, looking up VENGINE_GAMETYPES_VERSION.

See: http://hg.alliedmods.net/hl2sdks/hl2sdk-csgo/file/tip/public/matchmaking/igametypes.h