Implemented infection modes. Compiles, but not tested.
This commit is contained in:
parent
ed4c628e81
commit
d87138977b
@ -289,9 +289,21 @@ zr_hitgroups "1"
|
|||||||
|
|
||||||
// General
|
// General
|
||||||
|
|
||||||
// Number of mother zombies to infect (when infect timer is up) in proportion to number of humans on the server.
|
// Mother zombie infection mode. ['dynamic' = every n-th zombie (ratio) | 'absolute' = n zombies (ratio) | 'range' = min/max]
|
||||||
// Default: "5"
|
// Default: "dynamic"
|
||||||
zr_infect_mzombie_ratio "5"
|
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.
|
// Counts down to the first infection of the round. The counter is displayed in the middle of the screen.
|
||||||
// Default: "0"
|
// Default: "0"
|
||||||
|
@ -101,7 +101,10 @@ enum CvarsList
|
|||||||
Handle:CVAR_INFECT_SPAWNTIME_MAX,
|
Handle:CVAR_INFECT_SPAWNTIME_MAX,
|
||||||
Handle:CVAR_INFECT_CONSECUTIVE_BLOCK,
|
Handle:CVAR_INFECT_CONSECUTIVE_BLOCK,
|
||||||
Handle:CVAR_INFECT_WEAPONS_DROP,
|
Handle:CVAR_INFECT_WEAPONS_DROP,
|
||||||
|
Handle:CVAR_INFECT_MZOMBIE_MODE,
|
||||||
Handle:CVAR_INFECT_MZOMBIE_RATIO,
|
Handle:CVAR_INFECT_MZOMBIE_RATIO,
|
||||||
|
Handle:CVAR_INFECT_MZOMBIE_MIN,
|
||||||
|
Handle:CVAR_INFECT_MZOMBIE_MAX,
|
||||||
Handle:CVAR_INFECT_MZOMBIE_COUNTDOWN,
|
Handle:CVAR_INFECT_MZOMBIE_COUNTDOWN,
|
||||||
Handle:CVAR_INFECT_MZOMBIE_RESPAWN,
|
Handle:CVAR_INFECT_MZOMBIE_RESPAWN,
|
||||||
Handle:CVAR_INFECT_EXPLOSION,
|
Handle:CVAR_INFECT_EXPLOSION,
|
||||||
@ -319,7 +322,10 @@ CvarsCreate()
|
|||||||
// ===========================
|
// ===========================
|
||||||
|
|
||||||
// General
|
// 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_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_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).");
|
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];
|
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.
|
* Map is ending.
|
||||||
*/
|
*/
|
||||||
@ -454,126 +465,178 @@ public Action:InfectMotherZombie(Handle:timer)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Variable to store client stored in random array index.
|
|
||||||
new client;
|
|
||||||
|
|
||||||
// Prune list of immune clients.
|
// Prune list of immune clients.
|
||||||
// x = Array index.
|
eligibleclients = InfectRemoveImmuneClients(arrayEligibleClients);
|
||||||
// client = client index.
|
|
||||||
for (new x = 0; x < eligibleclients; x++)
|
// 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.
|
case InfectMode_Invalid:
|
||||||
if (eligibleclients <= 1)
|
{
|
||||||
|
// 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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get client stored in array index.
|
// Get a random array index.
|
||||||
client = GetArrayCell(arrayEligibleClients, x);
|
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])
|
if (bInfectImmune[client][INFECT_TYPE_MOTHER])
|
||||||
{
|
{
|
||||||
// Take away immunity.
|
// Take away immunity.
|
||||||
bInfectImmune[client][INFECT_TYPE_MOTHER] = false;
|
bInfectImmune[client][INFECT_TYPE_MOTHER] = false;
|
||||||
|
|
||||||
// Remove client from array.
|
// Remove client from array.
|
||||||
RemoveFromArray(arrayEligibleClients, x);
|
RemoveFromArray(clientList, i);
|
||||||
|
|
||||||
// Subtract one from count.
|
// Update list size.
|
||||||
eligibleclients--;
|
len--;
|
||||||
|
|
||||||
// Backtrack one index, because we deleted it out from under the loop.
|
// Backtrack one index, because we deleted it out from under the loop.
|
||||||
x--;
|
i--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move all clients to CT
|
return len;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1289,3 +1352,100 @@ public Action:InfectHumanCommand(client, argc)
|
|||||||
|
|
||||||
return Plugin_Handled;
|
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