From ecc9cf5167a23879da6a967c527f40299ee7c8cb Mon Sep 17 00:00:00 2001 From: Greyscale Date: Fri, 17 Apr 2009 12:16:44 +0200 Subject: [PATCH] Removed player list functions, recoded mother zombie picking function, removed allow_player_team cvar as models are handled by class system now, prefixed generic plugin functions with ZR, added comments in zombiereloaded.inc, added new function to check if clients are on either or both teams. --- src/zombiereloaded.sp | 14 +- src/zr/cvars.inc | 1 - src/zr/event.inc | 22 +-- src/zr/menu.inc | 2 +- src/zr/overlays.inc | 2 +- src/zr/playerclasses/classevents.inc | 2 +- src/zr/respawn.inc | 2 +- src/zr/sayhooks.inc | 7 - src/zr/spawnprotect.inc | 2 +- src/zr/teleport.inc | 2 +- src/zr/weapons/markethandler.inc | 2 +- src/zr/weapons/menu_weapons.inc | 4 +- src/zr/weapons/restrict.inc | 2 +- src/zr/weapons/weapons.inc | 2 +- src/zr/zombie.inc | 136 +++++++++++++----- src/zr/zombiereloaded.inc | 206 ++++++++++++++++----------- 16 files changed, 242 insertions(+), 166 deletions(-) diff --git a/src/zombiereloaded.sp b/src/zombiereloaded.sp index 7b802f7..189aa1d 100644 --- a/src/zombiereloaded.sp +++ b/src/zombiereloaded.sp @@ -109,7 +109,7 @@ public OnPluginStart() // ====================================================================== - market = LibraryExists("market"); + g_bMarket = LibraryExists("market"); // ====================================================================== @@ -126,7 +126,7 @@ public OnLibraryRemoved(const String:name[]) { if (StrEqual(name, "market")) { - market = false; + g_bMarket = false; } } @@ -134,7 +134,7 @@ public OnLibraryAdded(const String:name[]) { if (StrEqual(name, "market")) { - market = true; + g_bMarket = true; } } @@ -187,7 +187,7 @@ public OnConfigsExecuted() public OnClientPutInServer(client) { - gBlockMotherInfect[client] = false; + bMotherInfectImmune[client] = false; // Forward event to modules. ClassClientInit(client); @@ -198,14 +198,12 @@ public OnClientPutInServer(client) ZHPClientInit(client); ClientHookAttack(client); - FindClientDXLevel(client); + ZRFindClientDXLevel(client); for (new x = 0; x < MAXTIMERS; x++) { tHandles[client][x] = INVALID_HANDLE; } - - RefreshList(); } public OnClientDisconnect(client) @@ -227,8 +225,6 @@ public OnClientDisconnect(client) tHandles[client][x] = INVALID_HANDLE; } } - - RefreshList(); } MapChangeCleanup() diff --git a/src/zr/cvars.inc b/src/zr/cvars.inc index be00a60..d84ee42 100644 --- a/src/zr/cvars.inc +++ b/src/zr/cvars.inc @@ -101,7 +101,6 @@ CreateCvars() { gCvars[CVAR_ENABLE] = CreateConVar("zr_enable", "1", "Enable zombie gameplay (0: Disable)"); gCvars[CVAR_LOG] = CreateConVar("zr_log", "331", "Logging flags. Log messages to sourcemod logs, server console or client console. Use zr_log_flags to see a list of flags. (0: Disable)"); - gCvars[CVAR_ALLOW_PLAYER_TEAM] = CreateConVar("zr_allow_player_team", "0", "This will allow the player_team event to be fired on first team join, enable when using mani model menu (0: Disable)"); gCvars[CVAR_AMBIENTSOUNDS] = CreateConVar("zr_ambientsounds", "1", "Enable creepy ambience to be played throughout the game (0: Disable)"); gCvars[CVAR_AMBIENTSOUNDS_FILE] = CreateConVar("zr_ambientsounds_file", "ambient/zr/zr_ambience.mp3", "Path to ambient sound file that will be played throughout the game, when zr_ambience is 1"); gCvars[CVAR_AMBIENTSOUNDS_LENGTH] = CreateConVar("zr_ambientsounds_length", "60.0", "The length, in seconds, of the ambient sound file"); diff --git a/src/zr/event.inc b/src/zr/event.inc index 3305d8f..00fe2c2 100644 --- a/src/zr/event.inc +++ b/src/zr/event.inc @@ -35,7 +35,6 @@ UnhookEvents() public Action:RoundStart(Handle:event, const String:name[], bool:dontBroadcast) { ChangeLightStyle(); - RefreshList(); // Forward event to sub-modules. SEffectsOnRoundStart(); @@ -97,7 +96,7 @@ public Action:RoundEnd(Handle:event, const String:name[], bool:dontBroadcast) tInfect = INVALID_HANDLE; } - zombieSpawned = false; + g_bZombieSpawned = false; for (new x = 1; x<= MaxClients; x++) { @@ -106,10 +105,7 @@ public Action:RoundEnd(Handle:event, const String:name[], bool:dontBroadcast) continue; } - gZombie[x] = false; - - new bool:consecutive_infect = GetConVarBool(gCvars[CVAR_CONSECUTIVE_INFECT]); - gBlockMotherInfect[x] = consecutive_infect ? false : motherZombie[x]; + bZombie[x] = false; } BalanceTeams(); @@ -135,14 +131,7 @@ public Action:PlayerTeam(Handle:event, const String:name[], bool:dontBroadcast) if (team == CS_TEAM_SPECTATOR) { - gZombie[index] = false; - motherZombie[index] = false; - } - - new bool:allow_player_team = GetConVarBool(gCvars[CVAR_ALLOW_PLAYER_TEAM]); - if (allow_player_team && !IsPlayerInList(index)) - { - return Plugin_Continue; + bZombie[index] = false; } return Plugin_Handled; @@ -161,8 +150,7 @@ public Action:PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) } } - gZombie[index] = false; - motherZombie[index] = false; + bZombie[index] = false; // Reset FOV and overlay. SetPlayerFOV(index, 90); @@ -182,7 +170,7 @@ public Action:PlayerSpawn(Handle:event, const String:name[], bool:dontBroadcast) NightVisionOn(index, false); NightVision(index, false); - if (zombieSpawned) + if (g_bZombieSpawned) { if (ZRIsClientOnTeam(index, CS_TEAM_T)) { diff --git a/src/zr/menu.inc b/src/zr/menu.inc index 70a96df..dd8d652 100644 --- a/src/zr/menu.inc +++ b/src/zr/menu.inc @@ -32,7 +32,7 @@ MainMenu(client) AddMenuItem(menu_main, "zadmin", zadmin, itemdraw); AddMenuItem(menu_main, "zclass", zclass); - if (market) + if (g_bMarket) { AddMenuItem(menu_main, "zmarket", zmarket); } diff --git a/src/zr/overlays.inc b/src/zr/overlays.inc index 0324c60..022d274 100644 --- a/src/zr/overlays.inc +++ b/src/zr/overlays.inc @@ -25,7 +25,7 @@ ShowOverlays(Float:time, ZTeam:winner) { if (IsClientInGame(x)) { - DisplayClientOverlay(x, overlay); + ZRDisplayClientOverlay(x, overlay); } } diff --git a/src/zr/playerclasses/classevents.inc b/src/zr/playerclasses/classevents.inc index d7a59d1..4f16795 100644 --- a/src/zr/playerclasses/classevents.inc +++ b/src/zr/playerclasses/classevents.inc @@ -56,7 +56,7 @@ ClassOnClientSpawn(client) // If the first zombie spawned, and the player is on the terrorist team, then // find a random zombie class, otherwise find a human class. - if (zombieSpawned && teamid == CS_TEAM_T) + if (g_bZombieSpawned && teamid == CS_TEAM_T) { new classindex = ClassGetRandomClass(ZR_CLASS_TEAM_ZOMBIES); ClassSelected[client][ZR_CLASS_TEAM_ZOMBIES] = classindex; diff --git a/src/zr/respawn.inc b/src/zr/respawn.inc index 46aefc4..5ef2c77 100644 --- a/src/zr/respawn.inc +++ b/src/zr/respawn.inc @@ -115,7 +115,7 @@ RespawnSpawnClient(client) CS_RespawnPlayer(client); // Stop here if the first zombie hasn't spawned yet. - if (!zombieSpawned) + if (!g_bZombieSpawned) { return; } diff --git a/src/zr/sayhooks.inc b/src/zr/sayhooks.inc index 71bb290..f315405 100644 --- a/src/zr/sayhooks.inc +++ b/src/zr/sayhooks.inc @@ -98,13 +98,6 @@ ZSpawn(client) { return; } - - if (IsPlayerInList(client)) - { - return; - } RespawnSpawnClient(client); - - AddPlayerToList(client); } \ No newline at end of file diff --git a/src/zr/spawnprotect.inc b/src/zr/spawnprotect.inc index d9c1e58..074a0fd 100644 --- a/src/zr/spawnprotect.inc +++ b/src/zr/spawnprotect.inc @@ -62,7 +62,7 @@ SpawnProtectOnClientSpawn(client) } // If zombie hasn't spawned, then stop. - if (!zombieSpawned) + if (!g_bZombieSpawned) { return; } diff --git a/src/zr/teleport.inc b/src/zr/teleport.inc index 8561ccf..a2f312c 100644 --- a/src/zr/teleport.inc +++ b/src/zr/teleport.inc @@ -386,7 +386,7 @@ bool:ZTele(client) tele_humans = true; } - if (!tele_humans && zombieSpawned) + if (!tele_humans && g_bZombieSpawned) { ZR_PrintToChat(client, "!ztele humans restricted"); return false; diff --git a/src/zr/weapons/markethandler.inc b/src/zr/weapons/markethandler.inc index f55a754..c92884b 100644 --- a/src/zr/weapons/markethandler.inc +++ b/src/zr/weapons/markethandler.inc @@ -14,7 +14,7 @@ bool:ZMarketSend(client) { // If market is disabled, then stop. - if (!market) + if (!g_bMarket) { // Tell client market is disabled. ZR_PrintToChat(client, "Feature is disabled"); diff --git a/src/zr/weapons/menu_weapons.inc b/src/zr/weapons/menu_weapons.inc index b431f5e..bf99c3e 100644 --- a/src/zr/weapons/menu_weapons.inc +++ b/src/zr/weapons/menu_weapons.inc @@ -50,7 +50,7 @@ WeaponsMenuMain(client) AddMenuItem(menu_weapons_main, "togglewgrouprestriction", togglewgrouprestriction); // Disable market option if market isn't installed. - if (market) + if (g_bMarket) { AddMenuItem(menu_weapons_main, "zmarket", zmarket); } @@ -422,7 +422,7 @@ WeaponsMenuMarket(client) decl String:togglebuyzone[64]; decl String:curSetting[8]; - BoolToConfigSetting(GetConVarBool(gCvars[CVAR_ZMARKET_BUYZONE]), curSetting, sizeof(curSetting)); + ZRBoolToConfigSetting(GetConVarBool(gCvars[CVAR_ZMARKET_BUYZONE]), curSetting, sizeof(curSetting)); Format(togglebuyzone, sizeof(togglebuyzone), "%t", "Weapons menu market toggle buyzone", curSetting); diff --git a/src/zr/weapons/restrict.inc b/src/zr/weapons/restrict.inc index db05086..832f1df 100644 --- a/src/zr/weapons/restrict.inc +++ b/src/zr/weapons/restrict.inc @@ -107,7 +107,7 @@ RestrictDefaultRestrictions() decl String:restrict[8]; KvGetString(kvWeapons, "restrict", restrict, sizeof(restrict), "no"); - if (ConfigSettingToBool(restrict)) + if (ZRConfigSettingToBool(restrict)) { new WpnRestrictQuery:output = RestrictRestrict(weapon, display); RestrictPrintRestrictOutput(0, output, display, true); diff --git a/src/zr/weapons/weapons.inc b/src/zr/weapons/weapons.inc index dc44866..e54426f 100644 --- a/src/zr/weapons/weapons.inc +++ b/src/zr/weapons/weapons.inc @@ -234,7 +234,7 @@ bool:WeaponsIsWeaponMenu(const String:weapon[]) KvGetString(kvWeapons, "menu", menu, sizeof(menu), "yes"); // Return weapon's setting. - return ConfigSettingToBool(menu); + return ZRConfigSettingToBool(menu); } } while (KvGotoNextKey(kvWeapons)); } diff --git a/src/zr/zombie.inc b/src/zr/zombie.inc index 36e244e..ea46094 100644 --- a/src/zr/zombie.inc +++ b/src/zr/zombie.inc @@ -96,67 +96,127 @@ public RestartGameHook(Handle:convar, const String:oldValue[], const String:newV TerminateRound(StringToFloat(newValue), Round_Draw); } +/** + * Timer callback, chooses mother zombies. + * + * @param timer The timer handle. + */ public Action:MotherZombie(Handle:timer) { - RefreshList(); + // Reset timer handle. + tInfect = INVALID_HANDLE; - new size = GetArraySize(pList); - new immune = 0; + // Create array. + new Handle:arrayEligibleClients = CreateArray(); - for (new x = 0; x < size; x++) + // Populate list with eligible clients. + // x = client index. + for (new x = 1; x <= MaxClients; x++) { - new index = GetArrayCell(pList, x); - - if (gBlockMotherInfect[index]) - { - immune++; - } - - if (!IsPlayerAlive(index) || IsPlayerZombie(index)) + // If client isn't in-game, then stop. + if (!IsClientInGame(x)) { continue; } - CS_SwitchTeam(index, CS_TEAM_CT); + // If client is dead, then stop. + if (!IsPlayerAlive(x)) + { + continue; + } + + // If client is immune from being a mother zombie, then stop. + if (bMotherInfectImmune[x]) + { + // Take away immunity. + bMotherInfectImmune[x] = false; + + continue; + } + + // Add eligible client to array. + PushArrayCell(arrayEligibleClients, x); } - if (!(size - immune)) + // If there are no eligible client's then stop. + new eligibleclients = GetArraySize(arrayEligibleClients); + if (!eligibleclients) { - tInfect = INVALID_HANDLE; - return; } - new randclient; + // Move all clients to CT + for (new x = 1; x <= MaxClients; x++) + { + // If client isn't in-game, then stop. + if (!IsClientInGame(x)) + { + continue; + } + + // If client is dead, then stop. + if (!IsPlayerAlive(x)) + { + continue; + } + + // Switch client to CT team. + CS_SwitchTeam(x, CS_TEAM_CT); + } + + // Variable to store randomly chosen array index. + new randindex; + + // Variable to store client stored in random array index. + new client; + + // Ratio of mother zombies to humans. new ratio = GetConVarInt(gCvars[CVAR_MOTHER_ZOMBIE_RATIO]); + // If ratio is 0 or lower, then pick 1 zombie. if (ratio <= 0) { - do - { - randclient = RandomPlayerFromList(); - } while (!IsPlayerAlive(randclient) || gBlockMotherInfect[randclient]); + // Get a random valid array index. + randindex = GetRandomInt(0, eligibleclients - 1); - InfectPlayer(randclient, _, true); + // Get the client stored in the random array index. + client = GetArrayCell(arrayEligibleClients, randindex); + + // Infect player. + InfectPlayer(client, _, true); } else { - new mothercount = RoundToCeil(float(size) / ratio); + // Calculate mother zombie sound. + new mothercount = RoundToCeil(float(eligibleclients) / ratio); + // x = current mother zombie count. for (new x = 0; x < mothercount; x++) { - do - { - randclient = RandomPlayerFromList(); - } while (IsPlayerZombie(randclient) || !IsPlayerAlive(randclient) || gBlockMotherInfect[randclient]); + // Recount eligible clients. + eligibleclients = GetArraySize(arrayEligibleClients); - InfectPlayer(randclient, _, true); + // If there are no more eligible clients, then break loop. + if (!eligibleclients) + { + break; + } + // Get a random valid array index. + randindex = GetRandomInt(0, eligibleclients - 1); + + // Get the client stored in the random array index. + client = GetArrayCell(arrayEligibleClients, randindex); + + // Infect player. + InfectPlayer(client, _, true); + + // Remove player from eligible zombie list. + RemoveFromArray(arrayEligibleClients, randindex); } } - tInfect = INVALID_HANDLE; - - zombieSpawned = true; + // Mother zombies have been infected. + g_bZombieSpawned = true; } /** @@ -184,8 +244,7 @@ InfectPlayer(client, attacker = -1, bool:motherinfect = false) } // Set player status. - gZombie[client] = true; - motherZombie[client] = motherinfect; + bZombie[client] = true; // Remove all weapons and give a knife. RemoveAllPlayersWeapons(client); @@ -200,6 +259,9 @@ InfectPlayer(client, attacker = -1, bool:motherinfect = false) // Switch the player to terrorists. CS_SwitchTeam(client, CS_TEAM_T); + // Flag player to be immune from being mother zombie twice. + bMotherInfectImmune[client] = motherinfect; + // Forward event to modules. ClassOnClientInfected(client, motherinfect); SEffectsOnClientInfected(client); @@ -333,7 +395,7 @@ PlayerLeft(client) for (new x = 1; x <= MaxClients; x++) { - if (!IsClientInGame(x) || !IsPlayerAlive(x) || client == x || GetClientTeam(x) != CS_TEAM_CT || gBlockMotherInfect[x]) + if (!IsClientInGame(x) || !IsPlayerAlive(x) || client == x || GetClientTeam(x) != CS_TEAM_CT || bMotherInfectImmune[x]) { continue; } @@ -405,7 +467,7 @@ ZTeam:IsRoundOver() if (humans && !zombies) { - if (zombieSpawned) + if (g_bZombieSpawned) { return Human; } @@ -486,12 +548,12 @@ public Action:RoundOver(Handle:timer) bool:IsPlayerZombie(client) { - return gZombie[client]; + return bZombie[client]; } bool:IsPlayerHuman(client) { - return !gZombie[client]; + return !bZombie[client]; } ZTeam:GetPlayerZTeam(client) diff --git a/src/zr/zombiereloaded.inc b/src/zr/zombiereloaded.inc index 3faef3b..b569c5b 100644 --- a/src/zr/zombiereloaded.inc +++ b/src/zr/zombiereloaded.inc @@ -6,13 +6,6 @@ * ==================== */ -enum ZTeam -{ - Neither, /** Round is not over */ - Zombie, /** Round is over because zombies win */ - Human, /** Round is over because humans wins */ -} - #define Target_Bombed 1 // Target Successfully Bombed! #define VIP_Escaped 2 // The VIP has escaped! #define VIP_Assassinated 3 // VIP has been assassinated! @@ -63,14 +56,52 @@ enum ZTeam * @endsection */ -new bool:market; +/** + * Lists possible returns of the game at any time. + */ +enum ZTeam +{ + Neither, /** Round is not over */ + Zombie, /** Round is over because zombies win */ + Human, /** Round is over because humans wins */ +} + +/** + * Global variable set to true if market plugin is installed + */ +new bool:g_bMarket; + +/** + * The DirectX level of a client. + */ new dxLevel[MAXPLAYERS + 1]; -new bool:zombieSpawned; -new bool:motherZombie[MAXPLAYERS + 1]; -new bool:gZombie[MAXPLAYERS + 1]; -new bool:gBlockMotherInfect[MAXPLAYERS + 1]; +/** + * Global variable set to true when the first zombie(s) is/are spawned. + */ +new bool:g_bZombieSpawned; +/** + * Array for flagging client as zombie. + */ +new bool:bZombie[MAXPLAYERS + 1]; + +/** + * Array for flagging player has immune to mother infect. + */ +new bool:bMotherInfectImmune[MAXPLAYERS + 1]; + +/** + * Global variable to store round win timer handle. + */ +new Handle:tRound = INVALID_HANDLE; + +/** + * Global variable to store the infect timer handle. + */ +new Handle:tInfect = INVALID_HANDLE; + +// TODO: MOVE TO TELEPORT MODULE. new Float:spawnLoc[MAXPLAYERS + 1][3]; new Float:bufferLoc[MAXPLAYERS + 1][3]; new bool:ztele_spawned[MAXPLAYERS + 1] = {false, ...}; @@ -82,145 +113,134 @@ new Handle:ztele_startup_timer = INVALID_HANDLE; new Handle:ztele_countdown_timer[MAXPLAYERS + 1] = {INVALID_HANDLE, ...}; new Handle:ztele_cooldown_timer[MAXPLAYERS + 1] = {INVALID_HANDLE, ...}; -new Handle:tRound = INVALID_HANDLE; -new Handle:tInfect = INVALID_HANDLE; - -new Handle:pList = INVALID_HANDLE; +// TODO: USE SEPARATE VARIABLE TO STORE TELEPORT TIMER HANDLE +// THEN WE CAN REMOVE tHandles ARRAY FOR GOOD. #define MAXTIMERS 1 #define TTELE 1 new Handle:tHandles[MAXPLAYERS + 1][MAXTIMERS]; -new QueryCookie:mat_dxlevel; - -bool:ConfigSettingToBool(const String:option[]) +/** + * Converts string of "yes" or "no" to a boolean value. + * + * @param option "yes" or "no" string to be converted. + * @return True if string is "yes", false otherwise. + */ +bool:ZRConfigSettingToBool(const String:option[]) { + // If option is equal to "yes," then return true. if (StrEqual(option, "yes", false)) { return true; } + // Option isn't "yes." return false; } -BoolToConfigSetting(bool:bOption, String:option[], maxlen) +/** + * Converts boolean value to "yes" or "no". + * + * @param bOption True/false value to be converted to "yes"/"no", respectively. + * @param option Variable to store "yes" or "no" in. + * @param maxlen Max length of return string, (can't be more than 4) + */ +ZRBoolToConfigSetting(bool:bOption, String:option[], maxlen) { + // If option is true, then copy "yes" to return string. if (bOption) { strcopy(option, maxlen, "yes"); } + // If option is false, then copy "no" to return string. else { strcopy(option, maxlen, "no"); } } -FindClientDXLevel(client) +/** + * Global variable to store a convar query cookie + */ +new QueryCookie:mat_dxlevel; + +/** + * Finds DX level of a client. + * + * @param client The client index. + */ +ZRFindClientDXLevel(client) { + // If client is fake (or bot), then stop. if (IsFakeClient(client)) { return; } - mat_dxlevel = QueryClientConVar(client, "mat_dxlevel", DXLevelClientQuery); + // Query mat_dxlevel on client. + mat_dxlevel = QueryClientConVar(client, "mat_dxlevel", ZRDXLevelClientQuery); } -public DXLevelClientQuery(QueryCookie:cookie, client, ConVarQueryResult:result, const String:cvarName[], const String:cvarValue[]) +/** + * Query callback function. + * + * @param cookie Unique cookie of the query. + * @param client The client index. + * @param result The result of the query (see console.inc enum ConVarQueryResult) + * @param cvarName Name of the cvar. + * @param cvarValue Value of the cvar. + */ +public ZRDXLevelClientQuery(QueryCookie:cookie, client, ConVarQueryResult:result, const String:cvarName[], const String:cvarValue[]) { + // If query cookie does not match cookie given by mat_dxlevel query, then stop, this isn't our query. if (cookie != mat_dxlevel) { return; } + // Reset dxLevel. dxLevel[client] = 0; + // If result is any other than ConVarQuery_Okay, then stop. if (result != ConVarQuery_Okay) { return; } + // Copy cvar value to dxLevel array. dxLevel[client] = StringToInt(cvarValue); } -DisplayClientOverlay(client, const String:overlay[]) +/** + * Displays overlay to client, or prints unsupported message on client's screen. + * + * @param client The client index. + * @param overlay The overlay path. + */ +ZRDisplayClientOverlay(client, const String:overlay[]) { + // If dxLevel is 0, then query on client failed, so try again, then stop. if (!dxLevel[client]) { - FindClientDXLevel(client); - + // Query dxlevel cvar. + ZRFindClientDXLevel(client); return; } + // If dxLevel is above or equal to minimum requirement, then display overlay. if (dxLevel[client] >= DXLEVEL_MIN) { ClientCommand(client, "r_screenoverlay \"%s\"", overlay); } + // If client doesn't meet minimum requirement, then print unsupported text. else { ZR_PrintCenterText(client, "DX90 not supported", dxLevel[client], DXLEVEL_MIN); } } -RefreshList() -{ - ClearList(); - - pList = CreateArray(); - - for (new x = 1; x <= MaxClients; x++) - { - if (IsClientInGame(x) && IsPlayerAlive(x)) - { - new team = GetClientTeam(x); - if (team == CS_TEAM_T || team == CS_TEAM_CT) - { - PushArrayCell(pList, x); - } - } - } -} - -AddPlayerToList(client) -{ - if (pList != INVALID_HANDLE) - { - PushArrayCell(pList, client); - } -} - -ClearList() -{ - if (pList != INVALID_HANDLE) - { - ClearArray(pList); - } -} - -RandomPlayerFromList() -{ - if (pList != INVALID_HANDLE) - { - new size = GetArraySize(pList); - new index = GetRandomInt(0, size - 1); - - return GetArrayCell(pList, index); - } - - return -1; -} - -bool:IsPlayerInList(client) -{ - if (pList != INVALID_HANDLE) - { - return (FindValueInArray(pList, client) != -1); - } - - return false; -} - /** * Check if a client index is a valid player. * @@ -266,6 +286,24 @@ bool:ZRIsClientOnTeam(client, team = -1) return (clientteam == team); } +/** + * Check if there are clients on a team. + * + * @param team (Optional) Team to check if there are clients on. + */ +ZRTeamHasClients(team = -1) +{ + // If team is + if (team == -1) + { + // Return true if both teams have at least 1 client. + return (GetTeamClientCount(CS_TEAM_T) && GetTeamClientCount(CS_TEAM_CT)); + } + + // Return true if given team has at least 1 client. + return (GetTeamClientCount(team)); +} + /** * Returns whether a player is a generic admin or not. *