diff options
Diffstat (limited to 'sourcemod-1.5-dev/scripting/include/smlib/clients.inc')
| -rw-r--r-- | sourcemod-1.5-dev/scripting/include/smlib/clients.inc | 3121 |
1 files changed, 0 insertions, 3121 deletions
diff --git a/sourcemod-1.5-dev/scripting/include/smlib/clients.inc b/sourcemod-1.5-dev/scripting/include/smlib/clients.inc deleted file mode 100644 index a3afd78..0000000 --- a/sourcemod-1.5-dev/scripting/include/smlib/clients.inc +++ /dev/null @@ -1,3121 +0,0 @@ -#if defined _smlib_client_included - #endinput -#endif -#define _smlib_client_included - -// Defined here beacause needed in teams.inc -#define CLIENTFILTER_ALL 0 // No filtering -#define CLIENTFILTER_BOTS ( 1 << 1 ) // Fake clients -#define CLIENTFILTER_NOBOTS ( 1 << 2 ) // No fake clients -#define CLIENTFILTER_AUTHORIZED ( 1 << 3 ) // SteamID validated -#define CLIENTFILTER_NOTAUTHORIZED ( 1 << 4 ) // SteamID not validated (yet) -#define CLIENTFILTER_ADMINS ( 1 << 5 ) // Generic Admins (or higher) -#define CLIENTFILTER_NOADMINS ( 1 << 6 ) // No generic admins -// All flags below require ingame checking (optimization) -#define CLIENTFILTER_INGAME ( 1 << 7 ) // Ingame -#define CLIENTFILTER_INGAMEAUTH ( 1 << 8 ) // Ingame & Authorized -#define CLIENTFILTER_NOTINGAME ( 1 << 9 ) // Not ingame (currently connecting) -#define CLIENTFILTER_ALIVE ( 1 << 10 ) // Alive -#define CLIENTFILTER_DEAD ( 1 << 11 ) // Dead -#define CLIENTFILTER_SPECTATORS ( 1 << 12 ) // Spectators -#define CLIENTFILTER_NOSPECTATORS ( 1 << 13 ) // No Spectators -#define CLIENTFILTER_OBSERVERS ( 1 << 14 ) // Observers -#define CLIENTFILTER_NOOBSERVERS ( 1 << 15 ) // No Observers -#define CLIENTFILTER_TEAMONE ( 1 << 16 ) // First Team (Terrorists, ...) -#define CLIENTFILTER_TEAMTWO ( 1 << 17 ) // Second Team (Counter-Terrorists, ...) - -#include <sourcemod> -#include <entity_prop_stocks> -#include <sdktools_engine> -#include <sdktools_trace> -#include <sdktools_voice> -#include <smlib/general> -#include <smlib/colors> -#include <smlib/edicts> -#include <smlib/math> -#include <smlib/teams> -#include <smlib/weapons> - -/** - * Very useful macro to iterate all clients - * matching the specified flags. - * - * @param 1 Name of the client index variable (will be only valid in the loop). - * @param 2 CLIENTFILTER_ flags to check. - */ -#define LOOP_CLIENTS(%1,%2) for (new %1=Client_GetNext(%2); %1 >= 1 && %1 <= MaxClients; %1=Client_GetNext(%2, ++%1)) - -/** - * Macro for iterating trough all observers of a player. - * - * @param 1 Client Index for who to get the observers. - * @param 2 Name of the observer client index variable (will be only valid in the loop). - * @param 3 CLIENTFILTER_ flags to check. - */ -#define LOOP_OBSERVERS(%1,%2,%3) for (new %2=Client_GetNextObserver(%1, 1, %3); %2 >= 1 && %2 <= MaxClients; %2=Client_GetNextObserver(%1, ++%2, %3)) - -/** - * Very useful macro to iterate all weapons of a client. - * - * @param 1 Client Index - * @param 2 Name of the weapon index variable (will be only valid in the loop). - * @param 3 Name of the client's weapon index variable (will be only valid in the loop). - */ -#define LOOP_CLIENTWEAPONS(%1,%2,%3) for (new %3, %2=Client_GetNextWeapon(%1, %3); %2 != -1; %2=Client_GetNextWeapon(%1, %3)) - -// Hud Element hiding flags (possibly outdated) -#define HIDEHUD_WEAPONSELECTION ( 1<<0 ) // Hide ammo count & weapon selection -#define HIDEHUD_FLASHLIGHT ( 1<<1 ) -#define HIDEHUD_ALL ( 1<<2 ) -#define HIDEHUD_HEALTH ( 1<<3 ) // Hide health & armor / suit battery -#define HIDEHUD_PLAYERDEAD ( 1<<4 ) // Hide when local player's dead -#define HIDEHUD_NEEDSUIT ( 1<<5 ) // Hide when the local player doesn't have the HEV suit -#define HIDEHUD_MISCSTATUS ( 1<<6 ) // Hide miscellaneous status elements (trains, pickup history, death notices, etc) -#define HIDEHUD_CHAT ( 1<<7 ) // Hide all communication elements (saytext, voice icon, etc) -#define HIDEHUD_CROSSHAIR ( 1<<8 ) // Hide crosshairs -#define HIDEHUD_VEHICLE_CROSSHAIR ( 1<<9 ) // Hide vehicle crosshair -#define HIDEHUD_INVEHICLE ( 1<<10 ) -#define HIDEHUD_BONUS_PROGRESS ( 1<<11 ) // Hide bonus progress display (for bonus map challenges) - -/** -* Sets the Hide-Hud flags of a client -* -* @param client Client index. -* @param flags Flag to set, use one of the HIDEHUD_ hiding constants -* @noreturn -*/ -stock Client_SetHideHud(client, flags) -{ - SetEntProp(client, Prop_Send, "m_iHideHUD", flags); -} - -/** -* Checks if the specified index is a player and connected. -* -* @param entity An entity index. -* @param checkConnected Set to false to skip the IsClientConnected check -* @return Returns true if the specified entity index is a player connected, false otherwise. -*/ -stock bool:Client_IsValid(client, bool:checkConnected=true) -{ - if (client > 4096) { - client = EntRefToEntIndex(client); - } - - if (client < 1 || client > MaxClients) { - return false; - } - - if (checkConnected && !IsClientConnected(client)) { - return false; - } - - return true; -} - -/** -* Checks if the specified index is a player and ingame. -* -* @param entity An entity index. -* @return Returns true if the specified index is a player and ingame, false otherwise. -*/ -stock bool:Client_IsIngame(client) -{ - if (!Client_IsValid(client, false)) { - return false; - } - - return IsClientInGame(client); -} - -/** -* Checks if the specified index is a player, ingame and authorized. -* -* @param entity An entity index. -* @return Returns true if the specified index is a player, ingame and authed, false otherwise. -*/ -stock bool:Client_IsIngameAuthorized(client) -{ - if (!Client_IsIngame(client)) { - return false; - } - - return IsClientAuthorized(client); -} - -#define MAX_STEAMAUTH_LENGTH 21 - -/** -* Finds a player by his SteamID -* -* @param auth SteamID to search for -* @return Client Index or -1 -*/ -stock Client_FindBySteamId(const String:auth[]) -{ - new String:clientAuth[MAX_STEAMAUTH_LENGTH]; - for (new client=1; client <= MaxClients; client++) { - if (!IsClientAuthorized(client)) { - continue; - } - - GetClientAuthString(client, clientAuth, sizeof(clientAuth)); - - if (StrEqual(auth, clientAuth)) { - return client; - } - } - - return -1; -} - -/** -* Finds a player by his name. -* Only returns the first matching player. -* -* @param name Name to search for. -* @param partOfName Whether to search for the part of a name or compare the full name. -* @param caseSensitive If true, comparison is case sensitive. If false (default), comparison is case insensitive. -* @return Client Index or -1 -*/ -stock Client_FindByName(const String:name[], bool:partOfName=true, bool:caseSensitive=false) -{ - new String:clientName[MAX_NAME_LENGTH]; - for (new client=1; client <= MaxClients; client++) { - if (!IsClientAuthorized(client)) { - continue; - } - - GetClientName(client, clientName, sizeof(clientName)); - - if (partOfName) { - if (StrContains(clientName, name, caseSensitive) != -1) { - return client; - } - } - else if (StrEqual(name, clientName, caseSensitive)) { - return client; - } - } - - return -1; -} - -// Spectator Movement modes -enum Obs_Mode -{ - OBS_MODE_NONE = 0, // not in spectator mode - OBS_MODE_DEATHCAM, // special mode for death cam animation - OBS_MODE_FREEZECAM, // zooms to a target, and freeze-frames on them - OBS_MODE_FIXED, // view from a fixed camera position - OBS_MODE_IN_EYE, // follow a player in first person view - OBS_MODE_CHASE, // follow a player in third person view - OBS_MODE_ROAMING, // free roaming - - NUM_OBSERVER_MODES -}; - -// Force Camera Restrictions with mp_forcecamera -enum Obs_Allow -{ - OBS_ALLOW_ALL = 0, // allow all modes, all targets - OBS_ALLOW_TEAM, // allow only own team & first person, no PIP - OBS_ALLOW_NONE, // don't allow any spectating after death (fixed & fade to black) - - OBS_ALLOW_NUM_MODES, -}; - -/** - * Gets the client's observer mode (Obs_Mode). - * - * @param client Client Index. - * @return The current observer mode (ObsMode). - */ -stock Obs_Mode:Client_GetObserverMode(client) -{ - return Obs_Mode:GetEntProp(client, Prop_Send, "m_iObserverMode"); -} - - -/** - * Sets the client's observer mode. - * Use a value of the Obs_Mode enum. - * This is a rewrite of CBasePlayer::SetObserverMode(). - * - * @param client Client Index. - * @param mode New Observer mode value (Obs_Mode). - * @param updateMoveType Set to true (default) to allow this function updating the movetype, false otherwise. - * @noreturn - */ -stock bool:Client_SetObserverMode(client, Obs_Mode:mode, bool:updateMoveType=true) -{ - if (mode < OBS_MODE_NONE || mode >= NUM_OBSERVER_MODES) { - return false; - } - - // check mp_forcecamera settings for dead players - if (mode > OBS_MODE_FIXED && GetClientTeam(client) > TEAM_SPECTATOR) - { - new Handle:mp_forcecamera = FindConVar("mp_forcecamera"); - - if (mp_forcecamera != INVALID_HANDLE) { - switch (GetConVarInt(mp_forcecamera)) - { - case OBS_ALLOW_TEAM: { - mode = OBS_MODE_IN_EYE; - } - case OBS_ALLOW_NONE: { - mode = OBS_MODE_FIXED; // don't allow anything - } - } - } - } - - new Obs_Mode:observerMode = Client_GetObserverMode(client); - if (observerMode > OBS_MODE_DEATHCAM) { - // remember mode if we were really spectating before - Client_SetObserverLastMode(client, observerMode); - } - - SetEntProp(client, Prop_Send, "m_iObserverMode", _:mode); - - switch (mode) { - case OBS_MODE_NONE, OBS_MODE_FIXED, OBS_MODE_DEATHCAM: { - Client_SetFOV(client, 0); // Reset FOV - - if (updateMoveType) { - SetEntityMoveType(client, MOVETYPE_NONE); - } - } - case OBS_MODE_CHASE, OBS_MODE_IN_EYE: { - // udpate FOV and viewmodels - Client_SetViewOffset(client, NULL_VECTOR); - - if (updateMoveType) { - SetEntityMoveType(client, MOVETYPE_OBSERVER); - } - } - case OBS_MODE_ROAMING: { - Client_SetFOV(client, 0); // Reset FOV - Client_SetViewOffset(client, NULL_VECTOR); - - if (updateMoveType) { - SetEntityMoveType(client, MOVETYPE_OBSERVER); - } - } - } - - return true; -} - -/** - * Gets the client's last oberserver mode - * - * @param client Client Index. - * @return Last Observer mode - */ -stock Obs_Mode:Client_GetObserverLastMode(client) -{ - return Obs_Mode:GetEntProp(client, Prop_Data, "m_iObserverLastMode"); -} - -/** - * Sets the client's last oberserver mode - * - * @param client Client Index. - * @param mode Last Observer mode - * @noreturn - */ -stock Client_SetObserverLastMode(client, Obs_Mode:mode) -{ - SetEntProp(client, Prop_Data, "m_iObserverLastMode", _:mode); -} - -/** - * Gets the client's view offset. - * This is the position relative to the client itself. - * - * @param client Client Index. - * @param vec Vector Buffer. - * @noreturn - */ -stock Client_GetViewOffset(client, Float:vec[3]) -{ - GetEntPropVector(client, Prop_Data, "m_vecViewOffset", vec); -} - -/** - * Sets the client's view offset. - * This is the position relative to the client itself. - * - * @param client Client Index. - * @param vec Vector buffer. - * @noreturn - */ -stock Client_SetViewOffset(client, Float:vec[3]) -{ - SetEntPropVector(client, Prop_Data, "m_vecViewOffset", vec); -} - -/** - * Gets the client's current observer target entity. - * - * @param client Client Index. - * @return Observed Entity Index. - */ -stock Client_GetObserverTarget(client) -{ - return GetEntPropEnt(client, Prop_Send, "m_hObserverTarget"); -} - -/** - * Sets the client's current observer target entity. - * - * @param client Client Index. - * @param entity Observed Entity Index. - * @param resetFOV If to reset the client's field of view. - * @noreturn - */ -stock Client_SetObserverTarget(client, entity, bool:resetFOV=true) -{ - SetEntPropEnt(client, Prop_Send, "m_hObserverTarget", entity); - - if (resetFOV) { - Client_SetFOV(client, 0); - } -} - -/** - * Gets the client's Field Of View. - * - * @param client Client Index. - * @return Field Of View - */ -stock Client_GetFOV(client) -{ - return GetEntProp(client, Prop_Send, "m_iFOV"); -} - -/** - * Sets the client's Field Of View. - * - * @param client Client Index. - * @param value Field Of View - * @noreturn - */ -stock Client_SetFOV(client, value) -{ - SetEntProp(client, Prop_Send, "m_iFOV", value); -} - -/** - * Checks if the client's View Model is drawn for the client. - * - * @param client Client Index. - * @return True if the viewmodel is drawn, false otherwise. - */ -stock bool:Client_DrawViewModel(client) -{ - return bool:GetEntProp(client, Prop_Send, "m_bDrawViewmodel"); -} - -/** - * Sets if to draw the client's view model for the client. - * - * @param client Client Index. - * @param drawViewModel Set to true if to draw, false otherwise. - * @noreturn - */ -stock Client_SetDrawViewModel(client, bool:drawViewModel) -{ - SetEntProp(client, Prop_Send, "m_bDrawViewmodel", drawViewModel); -} - -/** - * Puts the specified client into thirdperson or back to firstperson when false - * This doesn't work correctly in all games, it works in CS:S and DOD:S and some other games. - * Todo: Enhance this - * - * @param client Client Index. - * @param enable If set to true, the client will be put into thirdperson mode, - * if false the client will be put in firstperson mode. - * @noreturn - */ -stock Client_SetThirdPersonMode(client, enable=true) -{ - if (enable) { - Client_SetObserverTarget(client, 0); - Client_SetObserverMode(client, OBS_MODE_DEATHCAM, false); - Client_SetDrawViewModel(client, false); - Client_SetFOV(client, 120); - } - else { - Client_SetObserverTarget(client, -1); - Client_SetObserverMode(client, OBS_MODE_NONE, false); - Client_SetDrawViewModel(client, true); - Client_SetFOV(client, 90); - } -} - -/** - * Checks if the client is in thirdperson mode - * - * @param client Cient Undex - * @return true if the client is currently in thirdperson mode, false otherwise - */ -stock Client_IsInThirdPersonMode(client) -{ - return GetEntProp(client, Prop_Data, "m_iObserverMode"); -} - -#define FFADE_IN 0x0001 // Just here so we don't pass 0 into the function -#define FFADE_OUT 0x0002 // Fade out (not in) -#define FFADE_MODULATE 0x0004 // Modulate (don't blend) -#define FFADE_STAYOUT 0x0008 // ignores the duration, stays faded out until new ScreenFade message received -#define FFADE_PURGE 0x0010 // Purges all other fades, replacing them with this one - -/** - * Fades a client's screen to a specified color - * Your adviced to read the FFADE_ Comments - * - * @param client Player for which to fade the screen - * @param duration duration in seconds the effect stays - * @param mode fade mode, see FFADE_ defines - * @param holdtime holdtime in seconds - * @param r red amount - * @param g green amount - * @param b blue amount - * @param a transparency - * @return True on success, false otherwise - */ -stock bool:Client_ScreenFade(client, duration, mode, holdtime=-1, r=0, g=0, b=0, a=255, bool:reliable=true) -{ - new Handle:userMessage = StartMessageOne("Fade", client, (reliable?USERMSG_RELIABLE:0)); - - if (userMessage == INVALID_HANDLE) { - return false; - } - - if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available && - GetUserMessageType() == UM_Protobuf) { - - new color[4]; - color[0] = r; - color[1] = g; - color[2] = b; - color[3] = a; - - PbSetInt(userMessage, "duration", duration); - PbSetInt(userMessage, "hold_time", holdtime); - PbSetInt(userMessage, "flags", mode); - PbSetColor(userMessage, "clr", color); - } - else { - BfWriteShort(userMessage, duration); // Fade duration - BfWriteShort(userMessage, holdtime); // Fade hold time - BfWriteShort(userMessage, mode); // What to do - BfWriteByte(userMessage, r); // Color R - BfWriteByte(userMessage, g); // Color G - BfWriteByte(userMessage, b); // Color B - BfWriteByte(userMessage, a); // Color Alpha - } - EndMessage(); - - return true; -} - -/** - * This function retrieves an array that holds all clones of a client by IP check. - * Size of CloneList has to be MaxClients at least, or MAX_PLAYERS - * - * @param client Client index. - * @param closelist An array that holds all clones of a client. - * @return Returns how many clones a client has. - */ -stock Client_GetClones(client, cloneList[]) -{ - new x=0; - decl String:ip_client[16], String:ip_player[16]; - - GetClientIP(client, ip_client, sizeof(client)); - - for (new player=1; player <= MaxClients; player++) { - - if (IsClientInGame(player)) { - GetClientIP(player, ip_player, sizeof(ip_player)); - - if (StrEqual(ip_client, ip_player, false)) { - cloneList[x++] = player; - } - } - } - - return x; -} - -/* - * This function returns true if the client is at a ladder.. - * - * @param client Client index. - * @return Returns true if the client is on a ladder other wise false. - */ -stock bool:Client_IsOnLadder(client) -{ - new MoveType:movetype = GetEntityMoveType(client); - - if (movetype == MOVETYPE_LADDER) { - return true; - } - else{ - return false; - } -} - -enum Water_level -{ - WATER_LEVEL_NOT_IN_WATER = 0, - WATER_LEVEL_FEET_IN_WATER, - WATER_LEVEL_WAIST_IN_WATER, - WATER_LEVEL_HEAD_IN_WATER -}; - -/* - * This function returns how deep a client is in water. - * - * @param client Client index. - * @return Returns 0 if not in water. 1 if feets are in water. 2 if waist is in water. 3 if head is in water. - */ -stock Water_Level:Client_GetWaterLevel(client) -{ - return Water_Level:GetEntProp(client, Prop_Send, "m_nWaterLevel"); -} - -/* - * Returns how much suit sprint power a client has left in percent. - * - * @param client Client index. - * @return returns the actual power left in percent. - */ -stock Float:Client_GetSuitSprintPower(client) -{ - return GetEntPropFloat(client, Prop_Send, "m_flSuitPower"); -} - -/* - * Sets a client suit sprint power in percent. - * - * @param client Client index. - * @param power power (0.0 to 100.0) - * @noreturn - */ -stock Client_SetSuitSprintPower(client, Float:power) -{ - SetEntPropFloat(client, Prop_Send, "m_flSuitPower", power); -} - -/* - * Returns the client count put in the server. - * - * @param inGameOnly If false connecting players are also counted. - * @param countBots If true bots will be counted too. - * @return Client count in the server. - */ -stock Client_GetCount(bool:countInGameOnly=true, bool:countFakeClients=true) -{ - new numClients = 0; - - for (new client=1; client <= MaxClients; client++) { - - if (!IsClientConnected(client)) { - continue; - } - - if (countInGameOnly && !IsClientInGame(client)) { - continue; - } - - if (!countFakeClients && IsFakeClient(client)) { - continue; - } - - numClients++; - } - - return numClients; -} - -/* - * Returns the ping of a client like it is displayed in the scoreboard. - * The weird calculation formula is taken from Valve's SDK - * hl2sdk\game\server\util.cpp: UTIL_GetPlayerConnectionInfo() - * The Scoreboard uses the goldSource corrected Ping, the net_graph doesn't - * For Fake Clients 0 is returned. - * - * @param client Client index - * @param goldSource If true, get the ping as displayed in the player's scoreboard, false returns the net_graph variant. - * @return Client's fake ping or 0 for fake clients - */ -stock Client_GetFakePing(client, bool:goldSource=true) -{ - if (IsFakeClient(client)) { - return 0; - } - - new ping; - new Float:latency = GetClientLatency(client, NetFlow_Outgoing); // in seconds - - // that should be the correct latency, we assume that cmdrate is higher - // then updaterate, what is the case for default settings - decl String:cl_cmdrate[4]; - GetClientInfo(client, "cl_cmdrate", cl_cmdrate, sizeof(cl_cmdrate)); - - new Float:tickRate = GetTickInterval(); - latency -= (0.5 / StringToInt(cl_cmdrate)) + TICKS_TO_TIME(1.0); // correct latency - - if (goldSource) { - // in GoldSrc we had a different, not fixed tickrate. so we have to adjust - // Source pings by half a tick to match the old GoldSrc pings. - latency -= tickRate * 0.5; - } - - ping = RoundFloat(latency * 1000.0); // as msecs - ping = Math_Clamp(ping, 5, 1000); // set bounds, dont show pings under 5 msecs - - return ping; -} - -/** - * Searches for the closest client in relation to the given client. - * - * @param client Client index - * @return The closest client or -1 - */ -stock Client_GetClosestToClient(client) -{ - return Edict_GetClosestToEdict(client, true); -} - -/** - * Gets the name of the last place (if set by the game) - * - * @param entity Entity index. - * @param buffer String buffer - * @param size Size of the String buffer - * @noreturn - */ -stock Client_GetLastPlaceName(client, String:buffer[], size) -{ - GetEntPropString(client, Prop_Send, "m_szLastPlaceName", buffer, size); -} - -/** - * Returns the client's Score. - * - * @param client Client's index. - * @return Score. - */ -stock Client_GetScore(client) -{ - return GetClientFrags(client); -} - -/** - * Sets the client's Score. - * - * @param client Client's index. - * @param value Score. - * @noreturn - */ -stock Client_SetScore(client, value) -{ - SetEntProp(client, Prop_Data, "m_iFrags", value); -} - -/** - * Returns the client's Death count - * - * @param client Client's index. - * @return Death count - */ -stock Client_GetDeaths(client) -{ - return GetEntProp(client, Prop_Data, "m_iDeaths"); -} - -/** - * Sets the client's Death count. - * - * @param client Client's index. - * @param value Death count - * @noreturn - */ -stock Client_SetDeaths(client, value) -{ - SetEntProp(client, Prop_Data, "m_iDeaths", value); -} - -/** - * Returns the client's Armor - * - * @param client Client's index. - * @return Armor value - */ -stock Client_GetArmor(client) -{ - return GetEntProp(client, Prop_Data, "m_ArmorValue"); -} - -/** - * Sets the client's Armor. - * - * @param client Client's index. - * @param value Armor value - * @noreturn - */ -stock Client_SetArmor(client, value) -{ - SetEntProp(client, Prop_Data, "m_ArmorValue", value); -} - -/** - * Returns the client's Suitpower - * - * @param client Client's index. - * @return Suitpower - */ -stock Float:Client_GetSuitPower(client) -{ - return Float:GetEntPropFloat(client, Prop_Data, "m_flSuitPower"); -} - -/** - * Sets the client's Suitpower - * - * @param client Client's index. - * @param value Suitpower - * @noreturn - */ -stock Client_SetSuitPower(client, Float:value) -{ - SetEntPropFloat(client, Prop_Data, "m_flSuitPower", value); -} - -// suit usage bits -#define bits_SUIT_DEVICE_SPRINT 0x00000001 -#define bits_SUIT_DEVICE_FLASHLIGHT 0x00000002 -#define bits_SUIT_DEVICE_BREATHER 0x00000004 -#define MAX_SUIT_DEVICES 3 - -/** - * Returns the client's active devices (Max MAX_SUIT_DEVICES) - * The return is a bitwise value with bits_SUIT_DEVICE_SPRINT, - * bits_SUIT_DEVICE_FLASHLIGHT and/or bits_SUIT_DEVICE_BREATHER set. - * - * @param client Client's index. - * @return The active devices (bitwise value) - */ -stock Client_GetActiveDevices(client) -{ - return GetEntProp(client, Prop_Send, "m_bitsActiveDevices"); -} - -/** - * Returns the time when the client is allowed to spray - * a decal again. - * - * @param client Client's index. - * @return Next decal time - */ -stock Float:Client_GetNextDecalTime(client) -{ - return GetEntPropFloat(client, Prop_Data, "m_flNextDecalTime"); -} - -/** - * Returns whether the client is allowed to spray a decal or not. - * - * @param client Client's index. - * @return True if he is allowed to spray a decal, false otherwise - */ -stock bool:Client_CanSprayDecal(client) -{ - return Client_GetNextDecalTime(client) <= GetGameTime(); -} - -/** - * Returns the vehicle the client is in, if the client - * isn't in a vehicle, -1 is returned. - * - * @param client Client's index. - * @return Vehicle index, -1 if the client isn't in a vehicle. - */ -stock Client_GetVehicle(client) -{ - new m_hVehicle = GetEntPropEnt(client, Prop_Send, "m_hVehicle"); - - return m_hVehicle; -} - -/** - * Returns whether the client is in a vehicle or not. - * - * @param client Client's index. - * @return True if he is in a vehicle, false otherwise - */ -stock bool:Client_IsInVehicle(client) -{ - return !(Client_GetVehicle(client) == -1); -} - -/** - * Removes all decals for a client - * - * @param client Client's index. - * @noreturn - */ -stock Client_RemoveAllDecals(client) -{ - ClientCommand(client, "r_cleardecals"); -} - -/** - * Let's the client exit the vehicle - * - * @param vehicle Client index. - * @return True on success, false otherwise. - */ -stock bool:Client_ExitVehicle(client) -{ - new vehicle = Client_GetVehicle(client); - - if (vehicle == -1) { - return false; - } - - return AcceptEntityInput(vehicle, "ExitVehicle"); -} - -/** - * Plays a soundfile as if the player is using voicecomm for a single client. - * The voiceindicator is shown on the right, as if the players is talking. - * Thanks to Peace-Maker for the function. - * - * @param client For whom to play the sound. - * @param emitter Player/Entity the voice stream comes from. - * @param soundfile Path to the soundfile relative to the sound folder. - * @param length Length in seconds how long the hud "voiceindicator" is shown. - * @param pitch The pitch of the audiofile. - * @return True on success, false on failure. - */ -stock bool:Client_RawAudio(client, const emitter, const String:soundfile[], Float:length = 0.0, pitch = 100) -{ - new Handle:message = StartMessageOne("RawAudio", client); - - if (message == INVALID_HANDLE) { - return false; - } - - if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available - && GetUserMessageType() == UM_Protobuf) { - - PbSetInt(message, "pitch", pitch); - PbSetInt(message, "entidx", emitter); - PbSetFloat(message, "duration", length ); - PbSetString(message, "voice_filename", soundfile); - } - else { - BfWriteByte(message, pitch); - BfWriteByte(message, emitter); - BfWriteFloat(message, length); - BfWriteString(message, soundfile); - } - EndMessage(); - - return true; -} - -/** - * Plays a soundfile as if the player is using voicecomm for all players. - * The voiceindicator is shown on the right, as if the players is talking. - * Thanks to Peace-Maker for the function. - * - * @param emitter Player/Entity the voice stream comes from. - * @param soundfile Path to the soundfile relative to the sound folder. - * @param length Length in seconds how long the hud "voiceindicator" is shown. - * @param pitch The pitch of the audiofile. - * @return True on success, false on failure. - */ -stock bool:Client_RawAudioToAll(const emitter, const String:soundfile[], Float:length = 0.0, pitch = 100) -{ - new Handle:message = StartMessageAll("RawAudio"); - - if (message == INVALID_HANDLE) { - return false; - } - - if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available - && GetUserMessageType() == UM_Protobuf) { - - PbSetInt(message, "pitch", pitch); - PbSetInt(message, "entidx", emitter); - PbSetFloat(message, "duration", length); - PbSetString(message, "voice_filename", soundfile); - } - else { - BfWriteByte(message, pitch); - BfWriteByte(message, emitter); - BfWriteFloat(message, length); - BfWriteString(message, soundfile); - } - EndMessage(); - - return true; -} - -/** - * Sets an Impulse value for a client (eg: "impulse 100" for flashlight, value would be 100). - * See: http://developer.valvesoftware.com/wiki/Impulse - * - * @param client Client Index - * @param value The impulse command value. - * @return True on success, false on failure. - */ -stock Client_Impulse(client, value) -{ - SetEntProp(client, Prop_Data, "m_nImpulse", value); -} - -/** - * Gets the offset for a client's weapon list (m_hMyWeapons). - * The offset will saved globally for optimization. - * - * @param client Client Index. - * @return Weapon list offset or -1 on failure. - */ -stock Client_GetWeaponsOffset(client) -{ - static offset = -1; - - if (offset == -1) { - offset = FindDataMapOffs(client, "m_hMyWeapons"); - } - - return offset; -} - -/** - * Gets the current/active weapon of a client - * - * @param client Client Index. - * @return Weapon Index or INVALID_ENT_REFERENCE if the client has no active weapon. - */ -stock Client_GetActiveWeapon(client) -{ - new weapon = GetEntPropEnt(client, Prop_Data, "m_hActiveWeapon"); - - if (!Entity_IsValid(weapon)) { - return INVALID_ENT_REFERENCE; - } - - return weapon; -} - -/** - * Gets the classname and entity index of the current/active weapon of a client. - * - * @param client Client Index. - * @param buffer String Buffer to store the weapon's classname. - * @param size Max size of String: buffer. - * @return Weapon Entity Index on success or INVALID_ENT_REFERENCE otherwise - */ -stock Client_GetActiveWeaponName(client, String:buffer[], size) -{ - new weapon = Client_GetActiveWeapon(client); - - if (weapon == INVALID_ENT_REFERENCE) { - buffer[0] = '\0'; - return INVALID_ENT_REFERENCE; - } - - Entity_GetClassName(weapon, buffer, size); - - return weapon; -} - -/** - * Changes the active/current weapon of a player by Index. - * Note: No changing animation will be played ! - * - * @param client Client Index. - * @param weapon Index of a valid weapon. - * @noreturn - */ -stock Client_SetActiveWeapon(client, weapon) -{ - SetEntPropEnt(client, Prop_Data, "m_hActiveWeapon", weapon); - ChangeEdictState(client, FindDataMapOffs(client, "m_hActiveWeapon")); -} - -/** - * Changes the active weapon the client is holding. - * Note: No changing animation will be played ! - * - * @param client Client Index. - * @param className Weapon Classname. - * @return True on success, false on failure. - */ -stock bool:Client_ChangeWeapon(client, const String:className[]) -{ - new weapon = Client_GetWeapon(client, className); - - if (weapon == INVALID_ENT_REFERENCE) { - return false; - } - - Client_SetActiveWeapon(client,weapon); - - return true; -} - -/** - * Changes the active weapon to the last. - * If the last active weapon can't be found, the default weapon is taken. - * If the default weapon can't be found, the first weapon in the list is taken. - * If the first weapon can't be found, INVALID_ENT_REFERENCEE is returned. - * - * @param client Client Index. - * @return Entity Index or, INVALID_ENT_REFERENCE. - */ -stock Client_ChangeToLastWeapon(client) -{ - new weapon = Client_GetLastActiveWeapon(client); - - if (weapon == INVALID_ENT_REFERENCE) { - weapon = Client_GetDefaultWeapon(client); - - if (weapon == INVALID_ENT_REFERENCE) { - weapon = Client_GetFirstWeapon(client); - - if (weapon == INVALID_ENT_REFERENCE) { - return INVALID_ENT_REFERENCE; - } - } - } - - Client_SetActiveWeapon(client, weapon); - - return weapon; -} - -/** - * Gets the last active weapon of a client. - * - * @param client Client Index. - * @return Entity Index of the weapon on success, INVALID_ENT_REFERENCE on failure. - */ -stock Client_GetLastActiveWeapon(client) -{ - new weapon = GetEntPropEnt(client, Prop_Data, "m_hLastWeapon"); - - if (!Entity_IsValid(weapon)) { - return INVALID_ENT_REFERENCE; - } - - return weapon; -} - -/** - * Gets the classname of the last active weapon of a client. - * - * @param client Client Index. - * @param buffer Buffer to store the weapon classname. - * @param size Max size of String: buffer. - * @return True on success, false on failure. - */ -stock bool:Client_GetLastActiveWeaponName(client, String:buffer[], size) -{ - new weapon = Client_GetLastActiveWeapon(client); - - if (weapon == INVALID_ENT_REFERENCE) { - buffer[0] = '\0'; - return false; - } - - Entity_GetClassName(weapon, buffer, size); - - return true; -} - -/** - * Sets the last active weapon of a client. - * - * @param client Client Index. - * @param weapon Entity Index of a weapon. - * @noreturn - */ -stock Client_SetLastActiveWeapon(client, weapon) -{ - SetEntPropEnt(client, Prop_Data, "m_hLastWeapon", weapon); - ChangeEdictState(client, FindDataMapOffs(client, "m_hLastWeapon")); -} - -/** - * Equips (attaches) a weapon to a client. - * - * @param client Client Index. - * @param weapon Entity Index of the weapon. - * @param switchTo If true, the client will switch to that weapon (make it active). - * @noreturn - */ -stock Client_EquipWeapon(client, weapon, bool:switchTo=false) -{ - EquipPlayerWeapon(client, weapon); - - if (switchTo) { - Client_SetActiveWeapon(client, weapon); - } -} - -/** - * Savly detaches a clients weapon, to remove it as example. - * The client will select his last weapon when detached. - * - * @param client Client Index. - * @param weapon Entity Index of the weapon, you'd like to detach. - * @return True on success, false otherwise. - */ -stock bool:Client_DetachWeapon(client, weapon) -{ - if (!RemovePlayerItem(client, weapon)) { - return false; - } - - if (Client_GetActiveWeapon(client) == INVALID_ENT_REFERENCE) { - Client_ChangeToLastWeapon(client); - } - - return true; -} - -/** - * Gives a client a weapon. - * - * @param client Client Index. - * @param className Weapon Classname String. - * @param switchTo If set to true, the client will switch the active weapon to the new weapon. - * @return Entity Index of the given weapon on success, INVALID_ENT_REFERENCE on failure. - */ -stock Client_GiveWeapon(client, const String:className[], bool:switchTo=true) -{ - new weapon = Client_GetWeapon(client, className); - - if (weapon == INVALID_ENT_REFERENCE) { - weapon = Weapon_CreateForOwner(client, className); - - if (weapon == INVALID_ENT_REFERENCE) { - return INVALID_ENT_REFERENCE; - } - } - - Client_EquipWeapon(client, weapon, switchTo); - - return weapon; -} - -/** - * Gives a client a weapon and ammo for that weapon. - * - * @param client Client Index. - * @param className Weapon Classname String. - * @param switchTo If set to true, the client will switch the active weapon to the new weapon. - * @param primaryAmmo Primary ammo stock value from the client, if -1 the value is untouched. - * @param secondaryAmmo Secondary ammo stock value from the client, if -1 the value is untouched. - * @param primaryClip Primary ammo value in the weapon clip, if -1 the value is untouched. - * @param secondaryClip Secondary ammo value in the weapon clip, if -1 the value is untouched. - * @return Entity Index of the given weapon on success, INVALID_ENT_REFERENCE on failure. - */ -stock Client_GiveWeaponAndAmmo(client, const String:className[], bool:switchTo=true, primaryAmmo=-1, secondaryAmmo=-1, primaryClip=-1, secondaryClip=-1) -{ - new weapon = Client_GiveWeapon(client, className, switchTo); - - if (weapon == INVALID_ENT_REFERENCE) { - return INVALID_ENT_REFERENCE; - } - - if (primaryClip != -1) { - Weapon_SetPrimaryClip(weapon, primaryClip); - } - - if (secondaryClip != -1) { - Weapon_SetSecondaryClip(weapon, secondaryClip); - } - - Client_SetWeaponPlayerAmmoEx(client, weapon, primaryAmmo, secondaryAmmo); - - return weapon; -} - -/** - * Removes a weapon from a client. - * - * @param client Client Index. - * @param className Weapon Classname String. - * @param firstOnly If false it loops trough the whole weapon list and deletes all weapons that match the specified classname. - * @param clearAmmo If true, the ammo the client carries for that weapon will be set to 0 (primary and secondary). - * @return True on success, false otherwise. - */ -stock bool:Client_RemoveWeapon(client, const String:className[], bool:firstOnly=true, bool:clearAmmo=false) -{ - new offset = Client_GetWeaponsOffset(client) - 4; - - for (new i=0; i < MAX_WEAPONS; i++) { - offset += 4; - - new weapon = GetEntDataEnt2(client, offset); - - if (!Weapon_IsValid(weapon)) { - continue; - } - - if (!Entity_ClassNameMatches(weapon, className)) { - continue; - } - - if (clearAmmo) { - Client_SetWeaponPlayerAmmoEx(client, weapon, 0, 0); - } - - if (Client_GetActiveWeapon(client) == weapon) { - Client_ChangeToLastWeapon(client); - } - - if (RemovePlayerItem(client, weapon)) { - Entity_Kill(weapon); - } - - if (firstOnly) { - return true; - } - } - - return false; -} - -/** - * Removes all weapons of a client. - * You can specify a weapon it shouldn't remove and if to - * clear the player's ammo for a weapon when it gets removed. - * - * @param client Client Index. - * @param exclude If not empty, this weapon won't be removed from the client. - * @param clearAmmo If true, the ammo the player carries for all removed weapons are set to 0 (primary and secondary). - * @return Number of removed weapons. - */ -stock Client_RemoveAllWeapons(client, const String:exclude[]="", bool:clearAmmo=false) -{ - new offset = Client_GetWeaponsOffset(client) - 4; - - new numWeaponsRemoved = 0; - for (new i=0; i < MAX_WEAPONS; i++) { - offset += 4; - - new weapon = GetEntDataEnt2(client, offset); - - if (!Weapon_IsValid(weapon)) { - continue; - } - - if (exclude[0] != '\0' && Entity_ClassNameMatches(weapon, exclude)) { - Client_SetActiveWeapon(client, weapon); - continue; - } - - if (clearAmmo) { - Client_SetWeaponPlayerAmmoEx(client, weapon, 0, 0); - } - - if (RemovePlayerItem(client, weapon)) { - Entity_Kill(weapon); - } - - numWeaponsRemoved++; - } - - return numWeaponsRemoved; -} - -/** - * Checks if a client has a specific weapon. - * - * @param client Client Index. - * @param className Weapon Classname. - * @return True if client has the weapon, otherwise false. - */ -stock Client_HasWeapon(client, const String:className[]) -{ - new weapon = Client_GetWeapon(client, className); - - return (weapon != INVALID_ENT_REFERENCE); -} - -/** - * Gets the weapon of a client by the weapon's classname. - * - * @param client Client Index. - * @param className Classname of the weapon. - * @return Entity index on success or INVALID_ENT_REFERENCE. - */ -stock Client_GetWeapon(client, const String:className[]) -{ - new offset = Client_GetWeaponsOffset(client) - 4; - new weapon = INVALID_ENT_REFERENCE; - for (new i=0; i < MAX_WEAPONS; i++) { - offset += 4; - - weapon = GetEntDataEnt2(client, offset); - - if (!Weapon_IsValid(weapon)) { - continue; - } - - if (Entity_ClassNameMatches(weapon, className)) { - return weapon; - } - } - - return INVALID_ENT_REFERENCE; -} - -/** - * Gets the weapon of a client by slot number. - * Note: This is incompatible to games that have multiple - * weapons in one slot (eg.: hl2dm). - * - * @param client Client Index. - * @param slot Slot Index. - * @return Entity index on success or INVALID_ENT_REFERENCE. - */ -stock Client_GetWeaponBySlot(client, slot) -{ - return GetPlayerWeaponSlot(client, slot); -} - -/** - * Gets the clients default weapon (Entity Index). - * - * @param client Client Index. - * @return Entity Index on success, INVALID_ENT_REFERENCE on failure. - */ -stock Client_GetDefaultWeapon(client) -{ - decl String:weaponName[MAX_WEAPON_STRING]; - if (Client_GetDefaultWeaponName(client, weaponName, sizeof(weaponName))) { - return INVALID_ENT_REFERENCE; - } - - return Client_GetWeapon(client, weaponName); -} - -/** - * Gets the clients default weapon (classname). - * This function doesn't work in all games (maybe only works in hl2dm). - * It will return an empty string if cl_defaultweapon doesn't exist. - * - * @param client Client Index. - * @param buffer Buffer to store the default weapon's classname. - * @param size Max size of string: buffer. - * @return True on success, false otherwise. - */ -stock bool:Client_GetDefaultWeaponName(client, String:buffer[], size) -{ - if (!GetClientInfo(client, "cl_defaultweapon", buffer, size)) { - buffer[0] = '\0'; - return false; - } - - return true; -} - -/** - * Gets the first weapon of the client's weapon list (m_hMyWeapons). - * Note: This has nothing to do with weapon slots. - * - * @param client Client Index. - * @return Entity Index of the weapon or INVALID_ENT_REFERENCE. - */ -stock Client_GetFirstWeapon(client) -{ - new offset = Client_GetWeaponsOffset(client) - 4; - - for (new i=0; i < MAX_WEAPONS; i++) { - offset += 4; - - new weapon = GetEntDataEnt2(client, offset); - - if (!Weapon_IsValid(weapon)) { - continue; - } - - return weapon; - } - - return INVALID_ENT_REFERENCE; -} - -/** - * Gets the number of weapons a client has. - * - * @param client Client Index. - * @return Number of weapons. - */ -stock Client_GetWeaponCount(client) -{ - new numWeapons = 0; - - new offset = Client_GetWeaponsOffset(client) - 4; - - for (new i=0; i < MAX_WEAPONS; i++) { - offset += 4; - - new weapon = GetEntDataEnt2(client, offset); - - if (!Weapon_IsValid(weapon)) { - continue; - } - - numWeapons++; - } - - return numWeapons; -} - -/** - * Checks whether the client is currently reloading his active weapon. - * - * @param client Client Index. - * @return True if client is reloading, false otherwise. - */ -stock bool:Client_IsReloading(client) -{ - new weapon = Client_GetActiveWeapon(client); - - if (weapon == INVALID_ENT_REFERENCE) { - return false; - } - - return Weapon_IsReloading(weapon); -} - -/** - * Sets the primary and secondary clip value of a weapon. - * - * @param client Client Index. - * @param classname Classname of a weapon. - * @param primaryClip Primary ammo value in the weapon clip, if -1 the value is untouched. - * @param secondaryClip Secondary ammo value in the weapon clip, if -1 the value is untouched. - * @return True on success, false on failure. - */ -stock bool:Client_SetWeaponClipAmmo(client, const String:className[], primaryClip=-1, secondoaryClip=-1) -{ - new weapon = Client_GetWeapon(client, className); - - if (weapon == INVALID_ENT_REFERENCE) { - return false; - } - - if (primaryClip != -1) { - Weapon_SetPrimaryClip(weapon, primaryClip); - } - - if (secondoaryClip != -1) { - Weapon_SetSecondaryClip(weapon, primaryClip); - } - - return true; -} - -/** - * Gets the primary and secondary ammo the player carries for a specific weapon classname. - * - * @param client Client Index. - * @param classname Classname of a weapon. - * @param primaryAmmo Primary ammo stock from the client, if -1 the value is untouched. - * @param secondaryAmmo Secondary ammo stock from the client, if -1 the value is untouched. - * @return True on success, false on failure. - */ -stock bool:Client_GetWeaponPlayerAmmo(client, const String:className[], &primaryAmmo=-1, &secondaryAmmo=-1) -{ - new weapon = Client_GetWeapon(client, className); - - if (weapon == INVALID_ENT_REFERENCE) { - return false; - } - - new offset_ammo = FindDataMapOffs(client, "m_iAmmo"); - - if (primaryAmmo != -1) { - new offset = offset_ammo + (Weapon_GetPrimaryAmmoType(weapon) * 4); - primaryAmmo = GetEntData(client, offset); - } - - if (secondaryAmmo != -1) { - new offset = offset_ammo + (Weapon_GetSecondaryAmmoType(weapon) * 4); - secondaryAmmo = GetEntData(client, offset); - } - - return true; -} - -/** - * Gets the primary and secondary ammo the player carries for a specific weapon index. - * - * @param client Client Index. - * @param weapon Weapon Entity Index. - * @param primaryAmmo Primary ammo stock value from the client, if -1 the value is untouched. - * @param secondaryAmmo Secondary ammo stock value from the client, if -1 the value is untouched. - * @noreturn - */ -stock Client_GetWeaponPlayerAmmoEx(client, weapon, &primaryAmmo=-1, &secondaryAmmo=-1) -{ - new offset_ammo = FindDataMapOffs(client, "m_iAmmo"); - - if (primaryAmmo != -1) { - new offset = offset_ammo + (Weapon_GetPrimaryAmmoType(weapon) * 4); - primaryAmmo = GetEntData(client, offset); - } - - if (secondaryAmmo != -1) { - new offset = offset_ammo + (Weapon_GetSecondaryAmmoType(weapon) * 4); - secondaryAmmo = GetEntData(client, offset); - } -} - -/** - * Sets the primary and secondary ammo the player carries for a specific weapon classname. - * - * @param client Client Index. - * @param classname Weapon Classname String. - * @param primaryAmmo Primary ammo stock from the client, if -1 the value is untouched. - * @param secondaryAmmo Secondary ammo stock from the client, if -1 the value is untouched. - * @return True on success, false on failure. - */ -stock bool:Client_SetWeaponPlayerAmmo(client, const String:className[], primaryAmmo=-1, secondaryAmmo=-1) -{ - new weapon = Client_GetWeapon(client, className); - - if (weapon == INVALID_ENT_REFERENCE) { - return false; - } - - Client_SetWeaponPlayerAmmoEx(client, weapon, primaryAmmo, secondaryAmmo); - - return true; -} - -/** - * Sets the primary and secondary ammo the player carries for a specific weapon index. - * - * @param client Client Index. - * @param weapon Weapon Entity Index. - * @param primaryAmmo Primary ammo stock value from the client, if -1 the value is untouched. - * @param secondaryAmmo Secondary ammo stock value from the client, if -1 the value is untouched. - * @noreturn - */ -stock Client_SetWeaponPlayerAmmoEx(client, weapon, primaryAmmo=-1, secondaryAmmo=-1) -{ - new offset_ammo = FindDataMapOffs(client, "m_iAmmo"); - - if (primaryAmmo != -1) { - new offset = offset_ammo + (Weapon_GetPrimaryAmmoType(weapon) * 4); - SetEntData(client, offset, primaryAmmo, 4, true); - } - - if (secondaryAmmo != -1) { - new offset = offset_ammo + (Weapon_GetSecondaryAmmoType(weapon) * 4); - SetEntData(client, offset, secondaryAmmo, 4, true); - } -} - -/** - * Sets the value from primary and secondary ammo stock, of a client. - * - * @param client Client Index. - * @param className Classname of a weapon. - * @param primaryAmmo Primary ammo stock value from the client, if -1 the value is untouched. - * @param secondaryAmmo Secondary ammo stock value from the client, if -1 the value is untouched. - * @param primaryClip Primary ammo value in the weapon clip, if -1 the value is untouched. - * @param secondaryClip Secondary ammo value in the weapon clip, if -1 the value is untouched. - * @return Entity Index of the given weapon on success, INVALID_ENT_REFERENCE on failure. - */ -stock Client_SetWeaponAmmo(client, const String:className[], primaryAmmo=-1, secondaryAmmo=-1, primaryClip=-1, secondaryClip=-1) -{ - new weapon = Client_GetWeapon(client, className); - - if (weapon == INVALID_ENT_REFERENCE) { - return false; - } - - if (primaryClip != -1) { - Weapon_SetPrimaryClip(weapon, primaryClip); - } - if (secondaryClip != -1) { - Weapon_SetSecondaryClip(weapon, secondaryClip); - } - Client_SetWeaponPlayerAmmoEx(client, weapon, primaryAmmo, secondaryAmmo); - - return true; -} - -/** - * Gets the next weapon of a client, starting at start. - * - * @param client Client Index (must be a valid client ingame). - * @param index Reference to an index variable, will contain the index of the next weapon to check. - * @return Weapon Index or -1 if no more weapons are found. - */ -stock Client_GetNextWeapon(client, &index = 0) -{ - new offset = Client_GetWeaponsOffset(client) + (index * 4); - - new weapon; - while (index < MAX_WEAPONS) { - index++; - - weapon = GetEntDataEnt2(client, offset); - - if (Weapon_IsValid(weapon)) { - return weapon; - } - - offset += 4; - } - - return -1; -} - -/** - * Prints white text to the bottom center of the screen - * for one client. Does not work in all games. - * Line Breaks can be done with "\n". - * - * @param client Client Index. - * @param format Formatting rules. - * @param ... Variable number of format parameters. - * @return True on success, false if this usermessage doesn't exist. - */ -stock bool:Client_PrintHintText(client, const String:format[], any:...) -{ - new Handle:userMessage = StartMessageOne("HintText", client); - - if (userMessage == INVALID_HANDLE) { - return false; - } - - decl String:buffer[254]; - - SetGlobalTransTarget(client); - VFormat(buffer, sizeof(buffer), format, 3); - - - if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available - && GetUserMessageType() == UM_Protobuf) { - - PbSetString(userMessage, "text", format); - } - else { - BfWriteByte(userMessage, 1); - BfWriteString(userMessage, buffer); - } - - EndMessage(); - - return true; -} - -/** - * Prints white text to the bottom center of the screen - * for all clients. Does not work in all games. - * Line Breaks can be done with "\n". - * - * @param format Formatting rules. - * @param ... Variable number of format parameters. - * @noreturn - */ -stock Client_PrintHintTextToAll(const String:format[], any:...) -{ - decl String:buffer[254]; - - for (new client=1; client <= MaxClients; client++) { - - if (!IsClientInGame(client)) { - continue; - } - - SetGlobalTransTarget(client); - VFormat(buffer, sizeof(buffer), format, 2); - Client_PrintHintText(client, buffer); - } -} - -/** - * Prints white text to the right-center side of the screen - * for one client. Does not work in all games. - * Line Breaks can be done with "\n". - * - * @param client Client Index. - * @param format Formatting rules. - * @param ... Variable number of format parameters. - * @return True on success, false if this usermessage doesn't exist. - */ -stock bool:Client_PrintKeyHintText(client, const String:format[], any:...) -{ - new Handle:userMessage = StartMessageOne("KeyHintText", client); - - if (userMessage == INVALID_HANDLE) { - return false; - } - - decl String:buffer[254]; - - SetGlobalTransTarget(client); - VFormat(buffer, sizeof(buffer), format, 3); - - if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available - && GetUserMessageType() == UM_Protobuf) { - - PbSetString(userMessage, "hints", buffer); - } - else { - BfWriteByte(userMessage, 1); - BfWriteString(userMessage, buffer); - } - - EndMessage(); - - return true; -} - -/** - * Prints white text to the right-center side of the screen - * for all clients. Does not work in all games. - * Line Breaks can be done with "\n". - * - * @param format Formatting rules. - * @param ... Variable number of format parameters. - * @noreturn - */ -stock Client_PrintKeyHintTextToAll(const String:format[], any:...) -{ - decl String:buffer[254]; - - for (new client=1; client <= MaxClients; client++) { - - if (!IsClientInGame(client)) { - continue; - } - - SetGlobalTransTarget(client); - VFormat(buffer, sizeof(buffer), format, 2); - Client_PrintKeyHintText(client, buffer); - } -} - -/** - * Prints a reliable raw chat message to a client in the chat area. - * If the client == 0, the message will printed to server console. - * - * @param client Client Index. - * @param message String Message. - * @param subject Client Index/Subject (normally used for teamcolors) - * @param isChat Tells the game to handle the chat as normal (false) or chat message (true, plays a sound), only works if SayText2 is supported. - * @noreturn - */ -stock Client_PrintToChatRaw(client, const String:message[], subject=0, bool:isChat=false) -{ - if (client == 0) { - decl String:buffer[253]; - Color_StripFromChatText(message, buffer, sizeof(buffer)); - PrintToServer(buffer); - return; - } - - static sayText2_supported = true; - static sayText2_checked = false; - - if (!sayText2_checked) { - - if (GetUserMessageId("SayText2") == INVALID_MESSAGE_ID) { - sayText2_supported = false; - } - - sayText2_checked = true; - } - - new Handle:userMessage = INVALID_HANDLE; - - if (sayText2_supported) { - userMessage = StartMessageOne("SayText2", client, USERMSG_RELIABLE); - - if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available - && GetUserMessageType() == UM_Protobuf) { - - PbSetInt(userMessage, "ent_idx", subject); - PbSetBool(userMessage, "chat", isChat); - PbSetString(userMessage, "msg_name", message); - - // psychonic: Furthermore, some usermessages with repeated field, - // such as the commonly-used SayText2, expected an undocumented - // specific number of values added, else the client will crash when receiving. - PbAddString(userMessage, "params", ""); - PbAddString(userMessage, "params", ""); - PbAddString(userMessage, "params", ""); - PbAddString(userMessage, "params", ""); - } - else { - BfWriteByte(userMessage , subject); - BfWriteByte(userMessage , isChat); - BfWriteString(userMessage , message); - } - } - else { - userMessage = StartMessageOne("SayText", client, USERMSG_RELIABLE); - - if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available - && GetUserMessageType() == UM_Protobuf) { - - PbSetInt(userMessage, "ent_idx", subject); - PbSetString(userMessage, "text", message); - PbSetBool(userMessage, "chat", isChat); - } - else { - BfWriteByte(userMessage , subject); - BfWriteString(userMessage , message); - // For DoD:S nickname coloring - BfWriteByte(userMessage , -1); - } - } - - EndMessage(); -} - -/** - * Prints a reliable chat message to one client in the chat area. - * Allows up to 253 Characters (including \0) to be printed. - * Supports chat color tags (see: colors.inc). - * - * @param client Client Index. - * @param isChat Tells the game to handle the chat as normal (false) or chat message (true, plays a sound), only works if SayText2 is supported. - * @param format Formatting rules String. - * @param ... Variable number of format parameters. - * @noreturn - */ -stock Client_PrintToChat(client, bool:isChat, const String:format[], any:...) -{ - decl - String:buffer[512], - String:buffer2[253]; - - SetGlobalTransTarget(client); - VFormat(buffer, sizeof(buffer), format, 4); - new subject = Color_ParseChatText(buffer, buffer2, sizeof(buffer2)); - - Client_PrintToChatRaw(client, buffer2, subject, isChat); - - Color_ChatClearSubject(); -} - -static printToChat_excludeclient = -1; - -/** - * Exclude a client from the next call to a Client_PrintToChat function. - * - * @param client Client Index. - * @noreturn - */ -stock Client_PrintToChatExclude(client) -{ - printToChat_excludeclient = client; -} - -/** - * Prints a reliable chat message to all clients in the chat area. - * Allows up to 253 Characters (including \0) to be printed. - * Supports chat color tags (see: colors.inc). - * - * @param isChat Tells the game to handle the chat as normal (false) or chat message (true, plays a sound), only works if SayText2 is supported. - * @param format Formatting rules String. - * @param ... Variable number of format parameters. - * @noreturn - */ -stock Client_PrintToChatAll(bool:isChat, const String:format[], any:...) -{ - decl - String:buffer[512], - String:buffer2[253]; - new - subject, - language, - lastLanguage = -1; - - for (new client=1; client <= MaxClients; client++) { - - if (!IsClientInGame(client)) { - continue; - } - - if (client == printToChat_excludeclient) { - printToChat_excludeclient = -1; - continue; - } - - language = GetClientLanguage(client); - - if (language != lastLanguage) { - SetGlobalTransTarget(client); - VFormat(buffer, sizeof(buffer), format, 3); - subject = Color_ParseChatText(buffer, buffer2, sizeof(buffer2)); - - lastLanguage = language; - } - - Client_PrintToChatRaw(client, buffer2, subject, isChat); - } - - Color_ChatClearSubject(); -} - -/** - * Prints a reliable chat message to the specified clients in the chat area. - * Allows up to 253 Characters (including \0) to be print. - * Supports chat color tags (see: colors.inc). - * - * @param clients Client Array. - * @param numClients Number of clients in the client array. - * @param isChat Tells the game to handle the chat as normal (false) or chat message (true, plays a sound), only works if SayText2 is supported. - * @param format Formatting rules. - * @param ... Variable number of format parameters. - * @noreturn - */ -stock Client_PrintToChatEx(clients[], numClients, bool:isChat, const String:format[], any:...) -{ - decl - String:buffer[512], - String:buffer2[253]; - new - client, - subject, - language, - lastLanguage = -1; - - for (new i=0; i < numClients; i++) { - - client = clients[i]; - - if (!IsClientInGame(client)) { - continue; - } - - if (client == printToChat_excludeclient) { - printToChat_excludeclient = -1; - continue; - } - - language = GetClientLanguage(client); - - if (language != lastLanguage) { - SetGlobalTransTarget(client); - VFormat(buffer, sizeof(buffer), format, 5); - subject = Color_ParseChatText(buffer, buffer2, sizeof(buffer2)); - - lastLanguage = language; - } - - Client_PrintToChatRaw(client, buffer2, subject, isChat); - } - - Color_ChatClearSubject(); -} - -enum ClientHudPrint { - ClientHudPrint_Notify = 1, - ClientHudPrint_Console, - ClientHudPrint_Talk, - Client_HudPrint_Center -}; - -/** - * Prints a relieable message to the client's console. - * Allows up to 254 Characters (including \0) to be print (253 for talk). - * Supports chat color tags (see: colors.inc, only available in Left 4 Dead (2) or higher). - * Chat colors are stripped automatically if not supported. - * - * @param clients Client Array. - * @param format Formatting rules. - * @param ... Variable number of format parameters. - * @noreturn - */ -stock Client_PrintToConsole(client, const String:format[], any:...) -{ - decl String:buffer[512]; - - SetGlobalTransTarget(client); - VFormat(buffer, sizeof(buffer), format, 3); - - Client_Print(client, ClientHudPrint_Console, buffer); -} - -/** - * Prints a relieable message to the client's console. - * Allows up to 254 Characters (including \0) to be print. - * Supports chat color tags in chat & console (see: colors.inc). - * Chat colors are stripped automatically if not supported in the destination. - * - * @param clients Client Array. - * @param destination Destination place (use onf of the ClientHudPrint_) - * @param format Formatting rules. - * @param ... Variable number of format parameters. - * @noreturn - */ -stock Client_Print(client, ClientHudPrint:destination, const String:format[], any:...) -{ - decl String:buffer[512], String:buffer2[254]; - - SetGlobalTransTarget(client); - VFormat(buffer, sizeof(buffer), format, 4); - - new subject = Color_ParseChatText(buffer, buffer2, sizeof(buffer2)); - - if (destination == ClientHudPrint_Talk) { - Client_PrintToChatRaw(client, buffer2, subject, false); - return; - } - - new EngineVersion:engineVersion = GetEngineVersion(); - if (client == 0 || - destination != ClientHudPrint_Console || - (destination == ClientHudPrint_Console - && engineVersion != Engine_Left4Dead && engineVersion != Engine_Left4Dead2)) - { - Color_StripFromChatText(buffer2, buffer2, sizeof(buffer2)); - - if (client == 0) { - PrintToServer(buffer2); - return; - } - } - - new Handle:userMessage = INVALID_HANDLE; - userMessage = StartMessageOne("TextMsg", client, USERMSG_RELIABLE); - - if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available - && GetUserMessageType() == UM_Protobuf) { - - PbSetInt(userMessage, "msg_dst", _:destination); - PbAddString(userMessage, "params", buffer2); - PbAddString(userMessage, "params", ""); - PbAddString(userMessage, "params", ""); - PbAddString(userMessage, "params", ""); - PbAddString(userMessage, "params", ""); - } - else { - BfWriteByte(userMessage , _:destination); - BfWriteString(userMessage , buffer2); - } - - EndMessage(); -} - -/** - * Replies to a message in a command. - * A client index of 0 will use PrintToServer(). - * If the command was from the console, Client_PrintToConsole() is used. - * If the command was from chat, Client_PrintToChat() is used. - * - * @param client Client Index. - * @param format Formatting rules String. - * @param ... Variable number of format parameters. - * @noreturn - */ -stock Client_Reply(client, const String:format[], any:...) -{ - decl String:buffer[255]; - - SetGlobalTransTarget(client); - VFormat(buffer, sizeof(buffer), format, 3); - - if (GetCmdReplySource() == SM_REPLY_TO_CONSOLE) { - Client_PrintToConsole(client, buffer); - } - else { - Client_PrintToChat(client, false, buffer); - } -} - -#define SHAKE_START 0 // Starts the screen shake for all players within the radius. -#define SHAKE_STOP 1 // Stops the screen shake for all players within the radius. -#define SHAKE_AMPLITUDE 2 // Modifies the amplitude of an active screen shake for all players within the radius. -#define SHAKE_FREQUENCY 3 // Modifies the frequency of an active screen shake for all players within the radius. -#define SHAKE_START_RUMBLEONLY 4 // Starts a shake effect that only rumbles the controller, no screen effect. -#define SHAKE_START_NORUMBLE 5 // Starts a shake that does NOT rumble the controller. - -/** - * Shakes a client's screen with the specified amptitude, - * frequency & duration. - * - * @param client Client Index. - * @param command Shake Mode, use one of the SHAKE_ definitions. - * @param amplitude Shake magnitude/amplitude. - * @param frequency Shake noise frequency. - * @param duration Shake lasts this long. - * @return True on success, false otherwise. - */ -stock bool:Client_Shake(client, command=SHAKE_START, Float:amplitude=50.0, Float:frequency=150.0, Float:duration=3.0) -{ - if (command == SHAKE_STOP) { - amplitude = 0.0; - } - else if (amplitude <= 0.0) { - return false; - } - - new Handle:userMessage = StartMessageOne("Shake", client); - - if (userMessage == INVALID_HANDLE) { - return false; - } - - if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available - && GetUserMessageType() == UM_Protobuf) { - - PbSetInt(userMessage, "command", command); - PbSetFloat(userMessage, "local_amplitude", amplitude); - PbSetFloat(userMessage, "frequency", frequency); - PbSetFloat(userMessage, "duration", duration); - } - else { - BfWriteByte(userMessage, command); // Shake Command - BfWriteFloat(userMessage, amplitude); // shake magnitude/amplitude - BfWriteFloat(userMessage, frequency); // shake noise frequency - BfWriteFloat(userMessage, duration); // shake lasts this long - } - - EndMessage(); - - return true; -} - -/** - * Checks whether the client is a generic admin. - * - * @param Client Index. - * @return True if the client is a generic admin, false otheriwse. - */ -stock bool:Client_IsAdmin(client) -{ - new AdminId:adminId = GetUserAdmin(client); - - if (adminId == INVALID_ADMIN_ID) { - return false; - } - - return GetAdminFlag(adminId, Admin_Generic); -} - -/** - * Checks whether a client has certain admin flags - * - * @param Client Index. - * @return True if the client has the admin flags, false otherwise. - */ -stock bool:Client_HasAdminFlags(client, flags=ADMFLAG_GENERIC) -{ - new AdminId:adminId = GetUserAdmin(client); - - if (adminId == INVALID_ADMIN_ID) { - return false; - } - - return bool:(GetAdminFlags(adminId, Access_Effective) & flags); -} - -/** - * Returns whether a player is in a specific admin group. - * - * @param client Client Index. - * @param groupName Admin group name to check. - * @param caseSensitive True if the group check has to be case sensitive, false otherwise. - * @return True if the client is in the admin group, false otherwise. - */ -stock bool:Client_IsInAdminGroup(client, const String:groupName[], bool:caseSensitive=true) -{ - new AdminId:adminId = GetUserAdmin(client); - - // Validate id. - if (adminId == INVALID_ADMIN_ID) { - return false; - } - - // Get number of groups. - new count = GetAdminGroupCount(adminId); - - // Validate number of groups. - if (count == 0) { - return false; - } - - decl String:groupname[64]; - - // Loop through each group. - for (new i = 0; i < count; i++) { - // Get group name. - GetAdminGroup(adminId, i, groupname, sizeof(groupname)); - - // Compare names. - if (StrEqual(groupName, groupname, caseSensitive)) { - return true; - } - } - - // No match. - return false; -} - -/** - * Checks if the client is currently looking at the wall in front - * of him with the given distance as max value. - * - * @param client Client Index. - * @param distance Max Distance as Float value. - * @return True if he is looking at a wall, false otherwise. - */ -stock bool:Client_IsLookingAtWall(client, Float:distance=40.0) { - - decl Float:posEye[3], Float:posEyeAngles[3]; - new bool:isClientLookingAtWall = false; - - GetClientEyePosition(client, posEye); - GetClientEyeAngles(client, posEyeAngles); - - posEyeAngles[0] = 0.0; - - new Handle:trace = TR_TraceRayFilterEx(posEye, posEyeAngles, CONTENTS_SOLID, RayType_Infinite, _smlib_TraceEntityFilter); - - if (TR_DidHit(trace)) { - - if (TR_GetEntityIndex(trace) > 0) { - CloseHandle(trace); - return false; - } - - decl Float:posEnd[3]; - - TR_GetEndPosition(posEnd, trace); - - if (GetVectorDistance(posEye, posEnd, true) <= (distance * distance)) { - isClientLookingAtWall = true; - } - } - - CloseHandle(trace); - - return isClientLookingAtWall; -} - -public bool:_smlib_TraceEntityFilter(entity, contentsMask) -{ - return entity == 0; -} - -/** - * Gets a client's class. - * Currently supported games are: TF2, Dark Messiah. - * Other games maybe work too, but are not tested. - * - * @param client Client Index. - * @return Class Index. - */ -stock Client_GetClass(client) -{ - if (GetEngineVersion() == Engine_DarkMessiah) { - return GetEntProp(client, Prop_Send, "m_iPlayerClass"); - } - - return GetEntProp(client, Prop_Send, "m_iClass"); -} - -/** - * Sets a client's class. - * Currently supported games are: TF2, Dark Messiah. - * Other games maybe work too, but are not tested. - * - * @param client Client Index. - * @param playerClass The class number to set the player to. Depends on game. - * @param persistant If true changes the players desired class so the change stays after death (probably TF2 only). - * @return Class Index. - */ -stock Client_SetClass(client, playerClass, bool:persistant=false) -{ - if (GetEngineVersion() == Engine_DarkMessiah) { - SetEntProp(client, Prop_Send, "m_iPlayerClass", playerClass); - } else { - SetEntProp(client, Prop_Send, "m_iClass", playerClass); - - if (persistant) { - SetEntProp(client, Prop_Send, "m_iDesiredPlayerClass", playerClass); - } - } -} - -/** - * Returns what buttons are currently pressed by the client. - * - * @param client Client Index. - * @return Buttons as bitflag. - */ -stock Client_GetButtons(client) -{ - return GetClientButtons(client); -} - -/** - * Sets the client buttons. - * Note: This will only work OnPreThink (sdkhooks) or OnPlayerRunCmd. - * - * @param client Client Index. - * @param buttons Buttons as bitflag. - * @noreturn - */ -stock Client_SetButtons(client, buttons) -{ - SetEntProp(client, Prop_Data, "m_nButtons", buttons); -} - -/** - * Adds buttons to the already pressed buttons. - * Note: This will likely only work OnPreThink (sdkhooks) or OnPlayerRunCmd. - * - * @param client Client Index. - * @param buttons Buttons as bitflag. - * @noreturn - */ -stock Client_AddButtons(client, buttons) -{ - new newButtons = Client_GetButtons(client); - newButtons |= buttons; - Client_SetButtons(client, newButtons); -} - -/** - * Removes buttons from the already pressed buttons. - * Note: This will only work OnPreThink (sdkhooks) or OnPlayerRunCmd. - * - * @param client Client Index. - * @param buttons Buttons as bitflag. - * @noreturn - */ -stock Client_RemoveButtons(client, buttons) -{ - new newButtons = Client_GetButtons(client); - newButtons &= ~buttons; - Client_SetButtons(client, newButtons); -} - -/** - * Clears all buttons. - * Note: This will likely only work OnPreThink (sdkhooks) or OnPlayerRunCmd. - * - * @param client Client Index. - * @noreturn - */ -stock Client_ClearButtons(client) -{ - Client_SetButtons(client,0); -} - -/** - * Returns if the given buttons are pressed by the client or not. - * - * @param client Client Index. - * @param buttons Buttons as bitflag. - * @return True if the buttons are pressed otherwise false. - */ -stock bool:Client_HasButtons(client, buttons) -{ - return bool:(Client_GetButtons(client) & buttons); -} - -/** - * Returns only the buttons that have changed since the last call of this. - * Example usage: Within OnPlayerRunCmd use this function to call another function only once when a player pressed or released a button. - * - * @param client Client Index. - * @param buttons Buttons as bitflag. - * @return - */ -stock Client_GetChangedButtons(client) -{ - static oldButtons[MAXPLAYERS+1] = {0,...}; - - new buttons = Client_GetButtons(client); - new changedButtons = buttons ^ oldButtons[client]; - - oldButtons[client] = buttons; - - return changedButtons; -} - -/** - * Sets the client's maxspeed to the given value (in units per second) - * - * @param Client Client Index - * @param maxspeed the maximum speed the client can move - * @noreturn - */ -stock Client_SetMaxSpeed(client, Float:value) -{ - Entity_SetMaxSpeed(client, value); -} - -/** - * Shows a screen overlay tp a client. - * There can only be one overlay at a time. - * If you want to clear the overlay, pass - * an empty string to this function. - * - * @param Client Client Index. - * @param path Overlay path (based on the game/materials/ folder) or empty String to not show any overlay. - * @noreturn - */ -stock Client_SetScreenOverlay(client, const String:path[]) -{ - ClientCommand(client, "r_screenoverlay \"%s\"", path); -} - -/** - * Shows a screen overlay to all clients. - * There can only be one overlay at a time. - * If you want to clear the overlay, pass - * an empty string to this function. - * - * @param Client Client Index. - * @param path Overlay path (based on the game/materials/ folder) or empty String to not show any overlay. - * @noreturn - */ -stock Client_SetScreenOverlayForAll(const String:path[]) -{ - LOOP_CLIENTS(client, CLIENTFILTER_INGAME | CLIENTFILTER_NOBOTS) { - Client_SetScreenOverlay(client, path); - } -} - -/** - * Mutes a client's voice - * - * @param Client Client Index. - * @noreturn - */ -stock Client_Mute(client) -{ - SetClientListeningFlags(client, VOICE_MUTED); -} - -/** - * UnMutes a client's voice - * Code copied from basecomm.sp - * - * @param Client Client Index. - * @noreturn - */ -stock Client_UnMute(client) -{ - static Handle:cvDeadTalk = INVALID_HANDLE; - - if (cvDeadTalk == INVALID_HANDLE) { - cvDeadTalk = FindConVar("sm_deadtalk"); - } - - if (cvDeadTalk == INVALID_HANDLE) { - SetClientListeningFlags(client, VOICE_NORMAL); - } - else { - if (GetConVarInt(cvDeadTalk) == 1 && !IsPlayerAlive(client)) { - SetClientListeningFlags(client, VOICE_LISTENALL); - } - else if (GetConVarInt(cvDeadTalk) == 2 && !IsPlayerAlive(client)) { - SetClientListeningFlags(client, VOICE_TEAM); - } - else { - SetClientListeningFlags(client, VOICE_NORMAL); - } - } -} - -/** - * Checks if a client's voice is muted - * - * @param Client Client Index. - * @return True if the client is muted, false otherwise. - */ -stock bool:Client_IsMuted(client) -{ - return bool:(GetClientListeningFlags(client) & VOICE_MUTED); -} - -/** - * Checks if a client matches the specified flag filter. - * Use one of the CLIENTFILTER_ constants. - * Note that this already checks if the client is ingame or connected - * so you don't have to do that yourself. - * This function is optimized to make as less native calls as possible :) - * - * @param Client Client Index. - * @param flags Client Filter Flags (Use the CLIENTFILTER_ constants). - * @return True if the client if the client matches, false otherwise. - */ -stock bool:Client_MatchesFilter(client, flags) -{ - new bool:isIngame = false; - - if (flags >= CLIENTFILTER_INGAME) { - isIngame = IsClientInGame(client); - - if (isIngame) { - if (flags & CLIENTFILTER_NOTINGAME) { - return false; - } - } - else { - return false; - } - } - else if (!IsClientConnected(client)) { - return false; - } - - if (!flags) { - return true; - } - - if (flags & CLIENTFILTER_INGAMEAUTH) { - flags |= CLIENTFILTER_INGAME | CLIENTFILTER_AUTHORIZED; - } - - if (flags & CLIENTFILTER_BOTS && !IsFakeClient(client)) { - return false; - } - - if (flags & CLIENTFILTER_NOBOTS && IsFakeClient(client)) { - return false; - } - - if (flags & CLIENTFILTER_ADMINS && !Client_IsAdmin(client)) { - return false; - } - - if (flags & CLIENTFILTER_NOADMINS && Client_IsAdmin(client)) { - return false; - } - - if (flags & CLIENTFILTER_AUTHORIZED && !IsClientAuthorized(client)) { - return false; - } - - if (flags & CLIENTFILTER_NOTAUTHORIZED && IsClientAuthorized(client)) { - return false; - } - - if (isIngame) { - - if (flags & CLIENTFILTER_ALIVE && !IsPlayerAlive(client)) { - return false; - } - - if (flags & CLIENTFILTER_DEAD && IsPlayerAlive(client)) { - return false; - } - - if (flags & CLIENTFILTER_SPECTATORS && GetClientTeam(client) != TEAM_SPECTATOR) { - return false; - } - - if (flags & CLIENTFILTER_NOSPECTATORS && GetClientTeam(client) == TEAM_SPECTATOR) { - return false; - } - - if (flags & CLIENTFILTER_OBSERVERS && !IsClientObserver(client)) { - return false; - } - - if (flags & CLIENTFILTER_NOOBSERVERS && IsClientObserver(client)) { - return false; - } - - if (flags & CLIENTFILTER_TEAMONE && GetClientTeam(client) != TEAM_ONE) { - return false; - } - - if (flags & CLIENTFILTER_TEAMTWO && GetClientTeam(client) != TEAM_TWO) { - return false; - } - } - - return true; -} - -/** - * Gets all clients matching the specified flags filter. - * - * @param client Client Array, size should be MaxClients or MAXPLAYERS - * @param flags Client Filter Flags (Use the CLIENTFILTER_ constants). - * @return The number of clients stored in the array - */ -stock Client_Get(clients[], flags=CLIENTFILTER_ALL) -{ - new x=0; - for (new client = 1; client <= MaxClients; client++) { - - if (!Client_MatchesFilter(client, flags)) { - continue; - } - - clients[x++] = client; - } - - return x; -} - -/** - * Gets a random client matching the specified flags filter. - * - * @param flags Client Filter Flags (Use the CLIENTFILTER_ constants). - * @return Client Index or -1 if no client was found - */ -stock Client_GetRandom(flags=CLIENTFILTER_ALL) -{ - decl clients[MaxClients]; - new num = Client_Get(clients, flags); - - if (num == 0) { - return -1; - } - else if (num == 1) { - return clients[0]; - } - - new random = Math_GetRandomInt(0, num-1); - - return clients[random]; -} - -/** - * Gets a client matching certain flags starting at start. - * - * @param flags Client Filter Flags (Use the CLIENTFILTER_ constants). - * @param start Start Index. - * @return Client Index or -1 if no client was found - */ -stock Client_GetNext(flags, start=1) -{ - for (new client=start; client <= MaxClients; client++) { - - if (Client_MatchesFilter(client, flags)) { - return client; - } - } - - return -1; -} - -/** - * Retrieves the time duration a client played on the current map. - * - * @param client Client Index. - * @return Time in seconds as Float - */ -stock Float:Client_GetMapTime(client) -{ - new Float:fClientTime = GetClientTime(client); - new Float:fGameTime = GetGameTime(); - - return (fClientTime < fGameTime) ? fClientTime : fGameTime; -} - -/** - * Gets client money value (for games like Counter-Strike:Source). - * - * @param client Client Index. - * @return Money value from the client. - */ -stock Client_GetMoney(client) -{ - return GetEntProp(client, Prop_Send, "m_iAccount"); -} - -/** - * Sets client money value (for games like Counter-Strike:Source). - * - * @param client Client Index. - * @param value Money value to set. - * @noreturn - */ -stock Client_SetMoney(client, value) -{ - SetEntProp(client, Prop_Send, "m_iAccount", value); -} - -/** - * Gets a client's observers. - * - * @param client Client Index. - * @param observers Array with size of MaxClients or MAXPLAYERS. - * @param flags Client Filter Flags (Use the CLIENTFILTER_ constants). - * @return Number of observers found. - */ -stock Client_GetObservers(client, observers[], flags=CLIENTFILTER_ALL) -{ - new count = 0; - - LOOP_CLIENTS(player, CLIENTFILTER_OBSERVERS | flags) { - - if (Client_GetObserverTarget(player) == client) { - observers[count++] = player; - } - } - - return count; -} - -static Float:getPlayersInRadius_distances[MAXPLAYERS+1]; - -/** - * Gets all players near a player in a certain radius and - * orders the players by distance (optional). - * - * @param client Client Index. - * @param clients Array with size of MaxClients or MAXPLAYERS. - * @param radius radius Float (max distance) - * @param orderByDistance Set to true to order the clients by distance, false otherwise. - * @return Number of clients found. - */ -stock Client_GetPlayersInRadius(client, clients[], Float:radius, bool:orderByDistance=true) -{ - decl Float:origin_client[3]; - new - Float:distance, - count=0; - - Entity_GetAbsOrigin(client, origin_client); - - LOOP_CLIENTS(player, CLIENTFILTER_INGAME) { - - if (player == client) { - continue; - } - - distance = Entity_GetDistanceOrigin(player, origin_client); - - if (distance <= radius) { - clients[count++] = player; - - if (orderByDistance) { - getPlayersInRadius_distances[player] = distance; - } - } - } - - if (orderByDistance) { - SortCustom1D(clients, count, __smlib_GetPlayersInRadius_Sort); - } - - return count; -} - -public __smlib_GetPlayersInRadius_Sort(player1, player2, const clients[], Handle:hndl) -{ - return FloatCompare(getPlayersInRadius_distances[player1], getPlayersInRadius_distances[player2]); -} - -/** - * Gets the next player observing client starting at start. - * - * @param client Client Index (Observer Target) - * @param start Start Index. - * @param flags Client Filter Flags (Use the CLIENTFILTER_ constants). - * @return Client Index or -1 if no client was found - */ -stock Client_GetNextObserver(client, start=1, flags=CLIENTFILTER_ALL) -{ - for (new player=start; player <= MaxClients; player++) { - - if (Client_MatchesFilter(player, CLIENTFILTER_OBSERVERS | flags)) { - - if (Client_GetObserverTarget(player) == client) { - return player; - } - } - } - - return -1; -} - -/** - * Searchs and returns the game's player_manager entity. - * This should be called on every map start. - * - * @return player_manager entity or INVALID_ENT_REFERENCE if not found. - */ -stock Client_GetPlayerManager() -{ - static player_manager = INVALID_ENT_REFERENCE; - - if (player_manager != INVALID_ENT_REFERENCE) { - - if (Entity_IsValid(player_manager)) { - return player_manager; - } - else { - player_manager = INVALID_ENT_REFERENCE; - } - } - - new maxEntities = GetMaxEntities(); - - for (new entity=0; entity < maxEntities; entity++) { - - if (!Entity_IsValid(entity)) { - continue; - } - - if (Entity_ClassNameMatches(entity, "player_manager", true)) { - player_manager = EntIndexToEntRef(entity); - - return player_manager; - } - } - - return INVALID_ENT_REFERENCE; -} - -/** - * Sets the client's ping as displayed in the scoreboards. - * Should be called OnGameFrame. - * - * @param client Client Index - * @param start New ping value. - * @return True on sucess, false otherwise. - */ -stock Client_SetPing(client, value) -{ - new player_manager = Client_GetPlayerManager(); - - static offset = -1; - - if (offset== -1) { - offset = GetEntSendPropOffs(player_manager, "m_iPing", true); - - if (offset == -1) { - return false; - } - } - - SetEntData(player_manager, offset + (client * 4), value, 4, true); - - return true; -} - -static printToTop_excludeclient = -1; - -/** - * Exclude a client from the next call to a Client_PrintToTop function. - * - * @param client Client Index. - * @noreturn - */ -stock Client_PrintToTopExclude(client) -{ - printToTop_excludeclient = client; -} - -/** - * Prints colored text to the top left of the screen - * for one client. Does not work in all games. - * Line Breaks can't be done. - * - * @param client Client Index. - * @param r Red amount. - * @param g Green amount. - * @param b Blue amount. - * @param a Transparency. - * @param duration Duration in seconds the text stays (min 10 - max 200 seconds). - * @param text Text to print to. - * @return True on success, false if the key value for the dialog couldn't be created or closed. - */ -stock bool:Client_PrintToTopRaw(client, r=255, g=255, b=255, a=255, Float:duration=10.0, const String:text[]) -{ - //message line max 50 - //overline: 39*_ - //underline: 44*T - new Handle:keyValue = CreateKeyValues("Stuff", "title", text); - - if (keyValue == INVALID_HANDLE) { - return false; - } - - KvSetColor(keyValue, "color", r, g, b, a); - KvSetNum(keyValue, "level", 1); - KvSetNum(keyValue, "time", RoundToFloor(duration)); - - CreateDialog(client, keyValue, DialogType_Msg); - - if (!CloseHandle(keyValue)) { - return false; - } - return true; -} - -/** - * Prints colored text to the top left of the screen - * for one client. Does not work in all games. - * Line Breaks can't be done. - * - * @param client Client Index. - * @param r Red amount. - * @param g Green amount. - * @param b Blue amount. - * @param a Transparency. - * @param duration Duration in seconds the text stays (min 10 - max 200 seconds). - * @param format Formatting rules. - * @param ... Variable number of format parameters. - * @return True on success, false if the key value for the dialog couldn't be created or closed. - */ -stock bool:Client_PrintToTop(client, r=255, g=255, b=255, a=255, Float:duration=10.0, const String:format[], any:...) -{ - new String:buffer[150]; - SetGlobalTransTarget(client); - VFormat(buffer, sizeof(buffer), format, 8); - - return Client_PrintToTopRaw(client, r, g, b, a, duration, buffer); -} - -/** - * Prints colored text to the top left of the screen - * to all clients. Does not work in all games. - * Line Breaks can't be done. - * - * @param r Red amount. - * @param g Green amount. - * @param b Blue amount. - * @param a Transparency. - * @param duration Duration in seconds the text stays (min 10 - max 200 seconds). - * @param format Formatting rules. - * @param ... Variable number of format parameters. - * @noreturn - */ -stock Client_PrintToTopAll(r=255, g=255, b=255, a=255, Float:duration=10.0, const String:format[], any:...) -{ - decl - String:buffer[150]; - new - language, - lastLanguage = -1; - - for (new client=1; client <= MaxClients; client++) { - - if (!IsClientInGame(client)) { - continue; - } - - if (client == printToTop_excludeclient) { - printToTop_excludeclient = -1; - continue; - } - - language = GetClientLanguage(client); - - if (language != lastLanguage) { - SetGlobalTransTarget(client); - VFormat(buffer, sizeof(buffer), format, 7); - - lastLanguage = language; - } - - Client_PrintToTopRaw(client, r, g, b, a, duration, buffer); - } -} - -/** - * Prints colored text to the top left of the screen - * to specified clients. Does not work in all games. - * Line Breaks can't be done. - * - * @param clients Client Array. - * @param numClients Number of clients in the clients array. - * @param r Red amount. - * @param g Green amount. - * @param b Blue amount. - * @param a Transparency. - * @param duration Duration in seconds the text stays (min 10 - max 200 seconds). - * @param format Formatting rules. - * @param ... Variable number of format parameters. - * @noreturn - */ -stock Client_PrintToTopEx(clients[], numClients, r=255, g=255, b=255, a=255, Float:duration=10.0, const String:format[], any:...) -{ - decl - String:buffer[150]; - new - client, - language, - lastLanguage = -1; - - for (new i=0; i < numClients; i++) { - - client = clients[i]; - - if (!IsClientInGame(client)) { - continue; - } - - if (client == printToTop_excludeclient) { - printToTop_excludeclient = -1; - continue; - } - - language = GetClientLanguage(client); - - if (language != lastLanguage) { - SetGlobalTransTarget(client); - VFormat(buffer, sizeof(buffer), format, 9); - - lastLanguage = language; - } - - Client_PrintToTopRaw(client, r, g, b, a, duration, buffer); - } -} - -/** - * Opens the scoreboard for a specific client - * - * @tested csgo - * @param client Client index - * @noreturn - */ -stock Client_ShowScoreboard(client, flags=USERMSG_RELIABLE | USERMSG_BLOCKHOOKS) -{ - new Handle:handle = StartMessageOne("VGUIMenu", client, flags); - - if (GetFeatureStatus(FeatureType_Native, "GetUserMessageType") == FeatureStatus_Available && - GetUserMessageType() == UM_Protobuf) { - - PbSetString(handle, "name", "scores"); - PbSetBool(handle, "show", true); - } - else { - BfWriteString(handle, "scores"); - BfWriteByte(handle, 1); // Show - BfWriteByte(handle, 0); // subkeys count - } - - EndMessage(); -} |
