Implemented infection modes. Compiles, but not tested.
This commit is contained in:
parent
ed4c628e81
commit
d87138977b
@ -289,9 +289,21 @@ zr_hitgroups "1"
|
||||
|
||||
// General
|
||||
|
||||
// Number of mother zombies to infect (when infect timer is up) in proportion to number of humans on the server.
|
||||
// Default: "5"
|
||||
zr_infect_mzombie_ratio "5"
|
||||
// Mother zombie infection mode. ['dynamic' = every n-th zombie (ratio) | 'absolute' = n zombies (ratio) | 'range' = min/max]
|
||||
// Default: "dynamic"
|
||||
zr_infect_mzombie_mode "dynamic"
|
||||
|
||||
// Dynamic mode: Infection ratio. Every n-th player is infected. | Absolute mode: Number of zombies to infect (positive ratio), or number of humans to keep (negative ratio).
|
||||
// Default: "7"
|
||||
zr_infect_mzombie_ratio "7"
|
||||
|
||||
// Minimum number of mother zombies. Range mode only, cannot be zero.
|
||||
// Default: "1"
|
||||
zr_infect_mzombie_min "1"
|
||||
|
||||
// Maximum number of mother zombies. Range mode only, cannot be zero.
|
||||
// Default: "3"
|
||||
zr_infect_mzombie_max "3"
|
||||
|
||||
// Counts down to the first infection of the round. The counter is displayed in the middle of the screen.
|
||||
// Default: "0"
|
||||
|
@ -101,7 +101,10 @@ enum CvarsList
|
||||
Handle:CVAR_INFECT_SPAWNTIME_MAX,
|
||||
Handle:CVAR_INFECT_CONSECUTIVE_BLOCK,
|
||||
Handle:CVAR_INFECT_WEAPONS_DROP,
|
||||
Handle:CVAR_INFECT_MZOMBIE_MODE,
|
||||
Handle:CVAR_INFECT_MZOMBIE_RATIO,
|
||||
Handle:CVAR_INFECT_MZOMBIE_MIN,
|
||||
Handle:CVAR_INFECT_MZOMBIE_MAX,
|
||||
Handle:CVAR_INFECT_MZOMBIE_COUNTDOWN,
|
||||
Handle:CVAR_INFECT_MZOMBIE_RESPAWN,
|
||||
Handle:CVAR_INFECT_EXPLOSION,
|
||||
@ -319,7 +322,10 @@ CvarsCreate()
|
||||
// ===========================
|
||||
|
||||
// General
|
||||
g_hCvarsList[CVAR_INFECT_MZOMBIE_RATIO] = CreateConVar("zr_infect_mzombie_ratio", "5", "Number of mother zombies to infect (when infect timer is up) in proportion to number of humans on the server.");
|
||||
g_hCvarsList[CVAR_INFECT_MZOMBIE_MODE] = CreateConVar("zr_infect_mzombie_mode", "dynamic", "Mother zombie infection mode. ['dynamic' = every n-th zombie (ratio) | 'absolute' = n zombies (ratio) | 'range' = min/max]");
|
||||
g_hCvarsList[CVAR_INFECT_MZOMBIE_RATIO] = CreateConVar("zr_infect_mzombie_ratio", "7", "Dynamic mode: Infection ratio. Every n-th player is infected. | Absolute mode: Number of zombies to infect (positive ratio), or number of humans to keep (negative ratio).");
|
||||
g_hCvarsList[CVAR_INFECT_MZOMBIE_MIN] = CreateConVar("zr_infect_mzombie_min", "1", "Minimum number of mother zombies. Range mode only, cannot be zero.");
|
||||
g_hCvarsList[CVAR_INFECT_MZOMBIE_MAX] = CreateConVar("zr_infect_mzombie_max", "3", "Maximum number of mother zombies. Range mode only, cannot be zero.");
|
||||
g_hCvarsList[CVAR_INFECT_MZOMBIE_COUNTDOWN] = CreateConVar("zr_infect_mzombie_countdown", "0", "Counts down to the first infection of the round. Countdown is printed in the middle of the client's screen.");
|
||||
g_hCvarsList[CVAR_INFECT_MZOMBIE_RESPAWN] = CreateConVar("zr_infect_mzombie_respawn", "0", "Teleport mother zombies back to spawn on infect.");
|
||||
g_hCvarsList[CVAR_INFECT_SPAWNTIME_MIN] = CreateConVar("zr_infect_spawntime_min", "30.0", "Minimum time from the start of the round until picking the mother zombie(s).");
|
||||
|
@ -78,6 +78,17 @@ new bool:bZombie[MAXPLAYERS + 1];
|
||||
*/
|
||||
new bool:bInfectImmune[MAXPLAYERS + 1][2];
|
||||
|
||||
/**
|
||||
* Available mother zombie infection modes.
|
||||
*/
|
||||
enum InfectMode
|
||||
{
|
||||
InfectMode_Invalid = -1, /** Invalid mode, used by validators. */
|
||||
InfectMode_Dynamic, /** Every n-th player is infected. */
|
||||
InfectMode_Absolute, /** Keep n humans (negative n) or infect n zombies. */
|
||||
InfectMode_Range /** An absolute number of zombies infected (min to max). */
|
||||
}
|
||||
|
||||
/**
|
||||
* Map is ending.
|
||||
*/
|
||||
@ -454,126 +465,178 @@ public Action:InfectMotherZombie(Handle:timer)
|
||||
return;
|
||||
}
|
||||
|
||||
// Variable to store client stored in random array index.
|
||||
new client;
|
||||
|
||||
// Prune list of immune clients.
|
||||
// x = Array index.
|
||||
// client = client index.
|
||||
for (new x = 0; x < eligibleclients; x++)
|
||||
eligibleclients = InfectRemoveImmuneClients(arrayEligibleClients);
|
||||
|
||||
// Move all clients to CT.
|
||||
InfectMoveAllToCT();
|
||||
|
||||
new mothercount;
|
||||
new ratio = GetConVarInt(g_hCvarsList[CVAR_INFECT_MZOMBIE_RATIO]);
|
||||
new min = GetConVarInt(g_hCvarsList[CVAR_INFECT_MZOMBIE_MIN]);
|
||||
new max = GetConVarInt(g_hCvarsList[CVAR_INFECT_MZOMBIE_MAX]);
|
||||
|
||||
// Count valid human clients.
|
||||
new humancount;
|
||||
ZRCountValidClients(_, humancount, _, true);
|
||||
|
||||
// Get and validate infection mode. This will also log a warning on error.
|
||||
new InfectMode:mode = InfectGetModeOrFail();
|
||||
|
||||
// Apply infection mode.
|
||||
switch (mode)
|
||||
{
|
||||
// Stop pruning if there is only 1 player left.
|
||||
if (eligibleclients <= 1)
|
||||
case InfectMode_Invalid:
|
||||
{
|
||||
// Validation failed. Fall back to one mother zombie.
|
||||
mothercount = 1;
|
||||
}
|
||||
case InfectMode_Dynamic:
|
||||
{
|
||||
// Dynamic mode. Every n-th player is infected.
|
||||
|
||||
// A ratio of 0 will infect one zombie (to keep backwards compatibility).
|
||||
if (ratio == 0)
|
||||
{
|
||||
mothercount = 1;
|
||||
}
|
||||
|
||||
// Calculate number of zombies to infect.
|
||||
mothercount = RoundToNearest(float(humancount) / ratio);
|
||||
|
||||
// Require at least one mother zombie.
|
||||
if (mothercount == 0)
|
||||
{
|
||||
mothercount = 1;
|
||||
}
|
||||
}
|
||||
case InfectMode_Absolute:
|
||||
{
|
||||
if (ratio > 0)
|
||||
{
|
||||
// Infect n humans.
|
||||
mothercount = ratio;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Infect all but n humans. Since ratio already is negative
|
||||
// just add the numbers. (Zero ratio is catched by validator.)
|
||||
mothercount = humancount + ratio;
|
||||
|
||||
// Force at least one mother zombie.
|
||||
if (mothercount == 0)
|
||||
{
|
||||
mothercount = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
case InfectMode_Range:
|
||||
{
|
||||
// Get a random number between the range.
|
||||
mothercount = Math_GetRandomInt(min, max);
|
||||
}
|
||||
}
|
||||
|
||||
// Infect players.
|
||||
for (new n = 0; n < mothercount; n++)
|
||||
{
|
||||
// Recount eligible clients.
|
||||
eligibleclients = GetArraySize(arrayEligibleClients);
|
||||
|
||||
// Stop if there are no more eligible clients.
|
||||
if (eligibleclients <= 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Get client stored in array index.
|
||||
client = GetArrayCell(arrayEligibleClients, x);
|
||||
// Get a random array index.
|
||||
new i = Math_GetRandomInt(0, eligibleclients - 1);
|
||||
|
||||
// If client is immune from being a mother zombie, then stop.
|
||||
// Get the client stored in the random array index.
|
||||
new client = GetArrayCell(arrayEligibleClients, i);
|
||||
|
||||
// Infect player.
|
||||
InfectHumanToZombie(client, _, true);
|
||||
|
||||
// Remove player from eligible client list.
|
||||
RemoveFromArray(arrayEligibleClients, i);
|
||||
}
|
||||
|
||||
// Mother zombies have been infected.
|
||||
g_bZombieSpawned = true;
|
||||
|
||||
// Destroy client list.
|
||||
CloseHandle(arrayEligibleClients);
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves all alive clients to the CT team.
|
||||
*/
|
||||
InfectMoveAllToCT()
|
||||
{
|
||||
// Move all clients to CT
|
||||
for (new client = 1; client <= MaxClients; client++)
|
||||
{
|
||||
// If client isn't in-game, then stop.
|
||||
if (!IsClientInGame(client))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// If client is dead, then stop.
|
||||
if (!IsPlayerAlive(client))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Switch client to CT team.
|
||||
CS_SwitchTeam(client, CS_TEAM_CT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes immune clients from a client list. If a client is removed, their
|
||||
* immunity is also removed.
|
||||
*
|
||||
* @param clientList List of clients.
|
||||
* @param keepLastPlayer Don't remove if there's only one player left.
|
||||
*
|
||||
* @return Number of clients remaining.
|
||||
*/
|
||||
InfectRemoveImmuneClients(Handle:clientList, bool:keepLastPlayer = true)
|
||||
{
|
||||
new len = GetArraySize(clientList);
|
||||
|
||||
// Loop though client list.
|
||||
for (new i = 0; i < len; i++)
|
||||
{
|
||||
// Stop pruning if there is only one player left.
|
||||
if (keepLastPlayer && len <= 1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Get client.
|
||||
new client = GetArrayCell(clientList, i);
|
||||
|
||||
// Check if client is immune from mother zombie infection.
|
||||
if (bInfectImmune[client][INFECT_TYPE_MOTHER])
|
||||
{
|
||||
// Take away immunity.
|
||||
bInfectImmune[client][INFECT_TYPE_MOTHER] = false;
|
||||
|
||||
// Remove client from array.
|
||||
RemoveFromArray(arrayEligibleClients, x);
|
||||
RemoveFromArray(clientList, i);
|
||||
|
||||
// Subtract one from count.
|
||||
eligibleclients--;
|
||||
// Update list size.
|
||||
len--;
|
||||
|
||||
// Backtrack one index, because we deleted it out from under the loop.
|
||||
x--;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
// Ratio of mother zombies to humans.
|
||||
new ratio = GetConVarInt(g_hCvarsList[CVAR_INFECT_MZOMBIE_RATIO]);
|
||||
|
||||
// If ratio is 0 or lower, then pick 1 zombie.
|
||||
if (ratio <= 0)
|
||||
{
|
||||
// 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.
|
||||
InfectHumanToZombie(client, _, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Initialize count variables
|
||||
new zombiecount;
|
||||
new humancount;
|
||||
|
||||
// Count valid human clients
|
||||
ZRCountValidClients(zombiecount, humancount, _, true);
|
||||
|
||||
// Calculate mother zombie count.
|
||||
new mothercount = RoundToNearest(float(humancount) / ratio);
|
||||
|
||||
// If mothercount is 0, then set to 1.
|
||||
if (!mothercount)
|
||||
{
|
||||
mothercount = 1;
|
||||
}
|
||||
|
||||
// x = current mother zombie count.
|
||||
for (new x = 0; x < mothercount; x++)
|
||||
{
|
||||
// Recount eligible clients.
|
||||
eligibleclients = GetArraySize(arrayEligibleClients);
|
||||
|
||||
// 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.
|
||||
InfectHumanToZombie(client, _, true);
|
||||
|
||||
// Remove player from eligible zombie list.
|
||||
RemoveFromArray(arrayEligibleClients, randindex);
|
||||
}
|
||||
}
|
||||
|
||||
// Mother zombies have been infected.
|
||||
g_bZombieSpawned = true;
|
||||
|
||||
// Destroy handle.
|
||||
CloseHandle(arrayEligibleClients);
|
||||
return len;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1289,3 +1352,100 @@ public Action:InfectHumanCommand(client, argc)
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a string to an infection mode.
|
||||
*
|
||||
* @param mode Mode string to convert.
|
||||
*
|
||||
* @return Infection mode or InfectMode_Invalid on error.
|
||||
*/
|
||||
InfectMode:InfectStringToMode(const String:mode[])
|
||||
{
|
||||
if (strlen(mode) == 0)
|
||||
{
|
||||
return InfectMode_Invalid;
|
||||
}
|
||||
|
||||
if (StrEqual(mode, "dynamic", false))
|
||||
{
|
||||
return InfectMode_Dynamic;
|
||||
}
|
||||
else if (StrEqual(mode, "absolute", false))
|
||||
{
|
||||
return InfectMode_Absolute;
|
||||
}
|
||||
else if (StrEqual(mode, "range", false))
|
||||
{
|
||||
return InfectMode_Range;
|
||||
}
|
||||
|
||||
return InfectMode_Invalid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets and validates the infection mode. On error it will log a warning.
|
||||
*
|
||||
* @return Infection mode or InfectMode_Invalid on error.
|
||||
*/
|
||||
InfectMode:InfectGetModeOrFail()
|
||||
{
|
||||
new String:modeName[16];
|
||||
GetConVarString(g_hCvarsList[CVAR_INFECT_MZOMBIE_MODE], modeName, sizeof(modeName));
|
||||
|
||||
new InfectMode:mode = InfectStringToMode(modeName);
|
||||
new ratio = GetConVarInt(g_hCvarsList[CVAR_INFECT_MZOMBIE_RATIO]);
|
||||
new min = GetConVarInt(g_hCvarsList[CVAR_INFECT_MZOMBIE_MIN]);
|
||||
new max = GetConVarInt(g_hCvarsList[CVAR_INFECT_MZOMBIE_MAX]);
|
||||
|
||||
// Validate.
|
||||
switch (mode)
|
||||
{
|
||||
case InfectMode_Invalid:
|
||||
{
|
||||
LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModule_Infect, "Config Validation", "Warning: Invalid infection mode (\"%s\"). Falling back to one mother zombie.", modeName);
|
||||
}
|
||||
case InfectMode_Dynamic:
|
||||
{
|
||||
if (ratio < 0)
|
||||
{
|
||||
LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModule_Infect, "Config Validation", "Warning: Invalid infection ratio (\"%d\"). Must be zero or positive in dynamic mode. Falling back to one mother zombie.", ratio);
|
||||
return InfectMode_Invalid;
|
||||
}
|
||||
}
|
||||
case InfectMode_Absolute:
|
||||
{
|
||||
if (ratio == 0)
|
||||
{
|
||||
LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModule_Infect, "Config Validation", "Warning: Invalid infection ratio (\"%d\"). Must be nonzero in absolute mode. Falling back to one mother zombie.", ratio);
|
||||
return InfectMode_Invalid;
|
||||
}
|
||||
}
|
||||
case InfectMode_Range:
|
||||
{
|
||||
new bool:failed = false;
|
||||
if (min <= 0)
|
||||
{
|
||||
LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModule_Infect, "Config Validation", "Warning: Invalid infection range (\"%d\"). Cvar zr_infect_mzombie_min must be nonzero and positive. Falling back to one mother zombie.", min);
|
||||
failed = true;
|
||||
}
|
||||
if (max <= 0)
|
||||
{
|
||||
LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModule_Infect, "Config Validation", "Warning: Invalid infection range (\"%d\"). Cvar zr_infect_mzombie_max must be nonzero and positive. Falling back to one mother zombie.", max);
|
||||
failed = true;
|
||||
}
|
||||
if (min > max || max < min)
|
||||
{
|
||||
LogEvent(false, LogType_Error, LOG_CORE_EVENTS, LogModule_Infect, "Config Validation", "Warning: Infection range values are overlapping or reversed. Check zr_infect_mzombie_min and zr_infect_mzombie_min. Falling back to one mother zombie.");
|
||||
failed = true;
|
||||
}
|
||||
|
||||
if (failed)
|
||||
{
|
||||
return InfectMode_Invalid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mode;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user