now adding cvar to exclude fakeclients, afks and autism bots from being mother zombie, also cvar for how long people must be afk before they cant be mother zombie. also critically a cvar that says fakeclients, autismbots and afks can actually be mother zombie if less than this cvar amount of players are connected. with 3 real players its not good if they constantly are mother zombie, hence at a low player count we still allow afks, fakes and autismbots to be. this update was done by claude AI
This commit is contained in:
+278
-33
@@ -32,6 +32,7 @@
|
||||
|
||||
#tryinclude "AFKManager.inc"
|
||||
#tryinclude "TeamManager.inc"
|
||||
#include <BotTargeting>
|
||||
|
||||
/* Restore old REQUIRE_PLUGIN value if necessary */
|
||||
#if defined TEMP_REQUIRE_PLUGIN
|
||||
@@ -41,6 +42,7 @@
|
||||
|
||||
new bool:g_AFKManagerLoaded = false;
|
||||
new bool:g_TeamManagerLoaded = false;
|
||||
new bool:g_BotTargetingLoaded = false;
|
||||
|
||||
/**
|
||||
* @section Explosion flags.
|
||||
@@ -122,6 +124,9 @@ InfectOnAllPluginsLoaded()
|
||||
g_TeamManagerLoaded = LibraryExists("TeamManager");
|
||||
LogMessage("TeamManager: %s", (g_TeamManagerLoaded ? "loaded" : "not loaded"));
|
||||
#endif
|
||||
|
||||
g_BotTargetingLoaded = LibraryExists("BotTargeting");
|
||||
LogMessage("BotTargeting: %s", (g_BotTargetingLoaded ? "loaded" : "not loaded"));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,6 +144,11 @@ InfectOnLibraryAdded(const String:name[])
|
||||
// TeamManager loaded.
|
||||
g_TeamManagerLoaded = true;
|
||||
}
|
||||
else if (StrEqual(name, "BotTargeting"))
|
||||
{
|
||||
// BotTargeting loaded.
|
||||
g_BotTargetingLoaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -156,6 +166,200 @@ InfectOnLibraryRemoved(const String:name[])
|
||||
// TeamManager unloaded.
|
||||
g_TeamManagerLoaded = false;
|
||||
}
|
||||
else if (StrEqual(name, "BotTargeting"))
|
||||
{
|
||||
// BotTargeting unloaded.
|
||||
g_BotTargetingLoaded = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a (non-fake) client is AFK according to AFKManager.
|
||||
*
|
||||
* @param client The client index. Must be in-game and not a fake client.
|
||||
* @return True if AFKManager is loaded and the client has been idle for
|
||||
* at least zr_infect_mzombie_exclude_afk_time seconds.
|
||||
*/
|
||||
bool:InfectIsClientAFK(client)
|
||||
{
|
||||
#if defined _AFKManager_Included
|
||||
if (g_AFKManagerLoaded && GetClientIdleTime(client) >= GetConVarInt(g_hCvarsList[CVAR_INFECT_MZOMBIE_EXCLUDE_AFK_TIME]))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a (non-fake) client is an autism bot according to BotTargeting.
|
||||
*
|
||||
* @param client The client index. Must be in-game and not a fake client.
|
||||
* @return True if BotTargeting is loaded and says the client is an autism bot.
|
||||
*/
|
||||
bool:InfectIsClientAutismBot(client)
|
||||
{
|
||||
// The native throws on unauthorized clients, so check that first.
|
||||
return (g_BotTargetingLoaded && IsClientAuthorized(client) && IsClientAutismBot(client));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a client falls in one of the categories excluded from mother zombie
|
||||
* by the zr_infect_mzombie_exclude_fakeclients/afk/autismbots cvars.
|
||||
*
|
||||
* This only looks at the category cvars, not at zr_infect_mzombie_exclude_min_real.
|
||||
*
|
||||
* @param client The client index. Must be in-game.
|
||||
* @return True if the client is excluded, false otherwise.
|
||||
*/
|
||||
bool:InfectIsClientMotherExcluded(client)
|
||||
{
|
||||
// Bots / SourceTV.
|
||||
if (IsFakeClient(client))
|
||||
{
|
||||
return GetConVarBool(g_hCvarsList[CVAR_INFECT_MZOMBIE_EXCLUDE_FAKECLIENTS]);
|
||||
}
|
||||
|
||||
// AFK players.
|
||||
if (GetConVarBool(g_hCvarsList[CVAR_INFECT_MZOMBIE_EXCLUDE_AFK]) && InfectIsClientAFK(client))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Autism bots.
|
||||
if (GetConVarBool(g_hCvarsList[CVAR_INFECT_MZOMBIE_EXCLUDE_AUTISMBOTS]) && InfectIsClientAutismBot(client))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a client is a "real" player, as used by zr_infect_mzombie_exclude_min_real.
|
||||
*
|
||||
* A real player is in-game, on a team (not spectate/unassigned), alive, and is
|
||||
* not a fake client, not AFK and not an autism bot. This definition is fixed and
|
||||
* does not depend on the zr_infect_mzombie_exclude_* category cvars.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @return True if the client is a real player, false otherwise.
|
||||
*/
|
||||
bool:InfectIsClientRealPlayer(client)
|
||||
{
|
||||
if (!IsClientInGame(client) || !ZRIsClientOnTeam(client) || !IsPlayerAlive(client))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (IsFakeClient(client) || InfectIsClientAFK(client) || InfectIsClientAutismBot(client))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the mother zombie exclusions currently apply, based on
|
||||
* zr_infect_mzombie_exclude_min_real.
|
||||
*
|
||||
* @return True if there are at least zr_infect_mzombie_exclude_min_real real
|
||||
* players (or the cvar is 0), false otherwise.
|
||||
*/
|
||||
bool:InfectMotherExclusionsActive()
|
||||
{
|
||||
new minreal = GetConVarInt(g_hCvarsList[CVAR_INFECT_MZOMBIE_EXCLUDE_MIN_REAL]);
|
||||
if (minreal <= 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
new realplayers = 0;
|
||||
for (new x = 1; x <= MaxClients; x++)
|
||||
{
|
||||
if (InfectIsClientRealPlayer(x))
|
||||
{
|
||||
realplayers++;
|
||||
}
|
||||
}
|
||||
|
||||
return (realplayers >= minreal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the mother zombie candidate lists.
|
||||
*
|
||||
* All alive humans on a team that the API allows are split into two lists:
|
||||
* - arrayEligibleClients: regular candidates. Only these go through the
|
||||
* consecutive block / round-robin cycle logic.
|
||||
* - arrayExcludedClients: fake clients, AFKs and autism bots excluded by the
|
||||
* zr_infect_mzombie_exclude_* cvars. Only used as a last resort when the
|
||||
* regular candidates can't fill the mother zombie count.
|
||||
*
|
||||
* When zr_infect_mzombie_exclude_min_real isn't reached, nobody is excluded.
|
||||
*
|
||||
* @param arrayEligibleClients Array to push regular candidates into.
|
||||
* @param arrayExcludedClients Array to push excluded candidates into.
|
||||
* @return Number of regular candidates.
|
||||
*/
|
||||
InfectCreateMotherCandidateLists(Handle:arrayEligibleClients, Handle:arrayExcludedClients)
|
||||
{
|
||||
new Handle:arrayAllClients = CreateArray();
|
||||
new allclients = ZRCreateEligibleClientList(arrayAllClients, true, true, true, true);
|
||||
|
||||
new bool:exclude = InfectMotherExclusionsActive();
|
||||
new eligibleclients = 0;
|
||||
|
||||
for (new n = 0; n < allclients; n++)
|
||||
{
|
||||
new client = GetArrayCell(arrayAllClients, n);
|
||||
|
||||
if (exclude && InfectIsClientMotherExcluded(client))
|
||||
{
|
||||
PushArrayCell(arrayExcludedClients, client);
|
||||
}
|
||||
else
|
||||
{
|
||||
PushArrayCell(arrayEligibleClients, client);
|
||||
eligibleclients++;
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(arrayAllClients);
|
||||
return eligibleclients;
|
||||
}
|
||||
|
||||
/**
|
||||
* Picks a random client from the list that is still human.
|
||||
*
|
||||
* @param arrayClients List of client indexes.
|
||||
* @return Client index, or -1 if nobody in the list is human.
|
||||
*/
|
||||
InfectGetRandomHumanFromList(Handle:arrayClients)
|
||||
{
|
||||
new Handle:arrayHumans = CreateArray();
|
||||
new size = GetArraySize(arrayClients);
|
||||
|
||||
for (new n = 0; n < size; n++)
|
||||
{
|
||||
new client = GetArrayCell(arrayClients, n);
|
||||
if (IsClientInGame(client) && InfectIsClientHuman(client))
|
||||
{
|
||||
PushArrayCell(arrayHumans, client);
|
||||
}
|
||||
}
|
||||
|
||||
new client = -1;
|
||||
new humans = GetArraySize(arrayHumans);
|
||||
if (humans)
|
||||
{
|
||||
client = GetArrayCell(arrayHumans, Math_GetRandomInt(0, humans - 1));
|
||||
}
|
||||
|
||||
CloseHandle(arrayHumans);
|
||||
return client;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -234,15 +438,10 @@ InfectClientInit(client)
|
||||
if(!IsClientInGame(x))
|
||||
continue;
|
||||
|
||||
/*
|
||||
#if defined _AFKManager_Included
|
||||
if(g_AFKManagerLoaded)
|
||||
{
|
||||
if(GetClientIdleTime(x) > 3 * 60)
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
*/
|
||||
// Clients that can never be mother zombie are never in the cycle,
|
||||
// don't let them water down the ratio.
|
||||
if(InfectIsClientMotherExcluded(x))
|
||||
continue;
|
||||
|
||||
players++;
|
||||
|
||||
@@ -580,15 +779,18 @@ public Action:InfectMotherZombie(Handle:timer)
|
||||
}
|
||||
#endif
|
||||
|
||||
// Create eligible player list.
|
||||
// Create candidate lists: regular candidates and excluded (fake clients, AFKs, autism bots).
|
||||
new Handle:arrayEligibleClients = CreateArray();
|
||||
new eligibleclients = ZRCreateEligibleClientList(arrayEligibleClients, true, true, true, true);
|
||||
new Handle:arrayExcludedClients = CreateArray();
|
||||
new eligibleclients = InfectCreateMotherCandidateLists(arrayEligibleClients, arrayExcludedClients);
|
||||
new excludedclients = GetArraySize(arrayExcludedClients);
|
||||
|
||||
// If there are no eligible client's then stop.
|
||||
if (!eligibleclients)
|
||||
// If nobody is alive on a team (everyone dead or in spectate), then stop.
|
||||
if (!eligibleclients && !excludedclients)
|
||||
{
|
||||
// Destroy handle.
|
||||
// Destroy handles.
|
||||
CloseHandle(arrayEligibleClients);
|
||||
CloseHandle(arrayExcludedClients);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -690,6 +892,15 @@ public Action:InfectMotherZombie(Handle:timer)
|
||||
}
|
||||
}
|
||||
|
||||
// Split excluded clients too, so the last resort prefers those who weren't mother zombie last round.
|
||||
new Handle:aExcludedMain = CreateArray();
|
||||
new Handle:aExcludedAlt = CreateArray();
|
||||
for (new n = 0; n < excludedclients; n++)
|
||||
{
|
||||
new client = GetArrayCell(arrayExcludedClients, n);
|
||||
PushArrayCell(g_bInfectMotherLast[client] ? aExcludedAlt : aExcludedMain, client);
|
||||
}
|
||||
|
||||
// Remove mother zombie last flag from all players.
|
||||
for (int client = 0; client <= MAXPLAYERS; client++)
|
||||
{
|
||||
@@ -701,7 +912,11 @@ public Action:InfectMotherZombie(Handle:timer)
|
||||
// Infect players.
|
||||
new infected = 0;
|
||||
new infected_human_to_zombie_failed = 0;
|
||||
while (infected < mothercount)
|
||||
|
||||
// Only run the regular selection (and its cycle reset) if there are regular candidates.
|
||||
// If there are none, all alive players are excluded ones and the cycle of the regular
|
||||
// players must not be touched.
|
||||
while (eligibleclients && infected < mothercount)
|
||||
{
|
||||
// Infect one of the main candidates.
|
||||
if (candidatesMain)
|
||||
@@ -751,40 +966,70 @@ public Action:InfectMotherZombie(Handle:timer)
|
||||
}
|
||||
else // We have no candidates at all. time to fuck over random people!
|
||||
{
|
||||
// Infect player.
|
||||
if (eligibleclients)
|
||||
// Pick a random regular candidate that is still human (ignores the consecutive block).
|
||||
new client = InfectGetRandomHumanFromList(arrayEligibleClients);
|
||||
if (client == -1)
|
||||
{
|
||||
new randindex = Math_GetRandomInt(0, eligibleclients - 1);
|
||||
new client = GetArrayCell(arrayEligibleClients, randindex);
|
||||
if (InfectHumanToZombie(client, _, true))
|
||||
{
|
||||
infected++;
|
||||
}
|
||||
else
|
||||
{
|
||||
infected_human_to_zombie_failed++;
|
||||
if (infected_human_to_zombie_failed > 100)
|
||||
{
|
||||
break;
|
||||
//doing testround on dev server would cause script time execution, hence this was added.
|
||||
}
|
||||
}
|
||||
break; // All regular candidates are zombies already, fall through to the excluded clients.
|
||||
}
|
||||
|
||||
// Infect player.
|
||||
if (InfectHumanToZombie(client, _, true))
|
||||
{
|
||||
infected++;
|
||||
}
|
||||
else
|
||||
{
|
||||
break; //prevent infinite loop. should be very unlikely we end up here.
|
||||
infected_human_to_zombie_failed++;
|
||||
if (infected_human_to_zombie_failed > 100)
|
||||
{
|
||||
break;
|
||||
//doing testround on dev server would cause script time execution, hence this was added.
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Last resort: not enough regular candidates, so infect excluded clients (fake clients, AFKs,
|
||||
// autism bots). A round must not start without mother zombies.
|
||||
// Prefer those who weren't mother zombie last round.
|
||||
while (infected < mothercount)
|
||||
{
|
||||
new Handle:aExcluded = INVALID_HANDLE;
|
||||
if (GetArraySize(aExcludedMain))
|
||||
{
|
||||
aExcluded = aExcludedMain;
|
||||
}
|
||||
else if (GetArraySize(aExcludedAlt))
|
||||
{
|
||||
aExcluded = aExcludedAlt;
|
||||
}
|
||||
else
|
||||
{
|
||||
break; // Nobody left.
|
||||
}
|
||||
|
||||
new i = Math_GetRandomInt(0, GetArraySize(aExcluded) - 1);
|
||||
new client = GetArrayCell(aExcluded, i);
|
||||
RemoveFromArray(aExcluded, i);
|
||||
|
||||
if (IsClientInGame(client) && InfectIsClientHuman(client) && InfectHumanToZombie(client, _, true))
|
||||
{
|
||||
infected++;
|
||||
}
|
||||
}
|
||||
|
||||
// Mother zombies have been infected.
|
||||
g_bZombieSpawned = true;
|
||||
|
||||
// Destroy client list.
|
||||
CloseHandle(arrayEligibleClients);
|
||||
CloseHandle(arrayExcludedClients);
|
||||
CloseHandle(aCandidatesMain);
|
||||
CloseHandle(aCandidatesAlt);
|
||||
CloseHandle(aExcludedMain);
|
||||
CloseHandle(aExcludedAlt);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user