From 1bd2fb7354d50af813eea7551ed1dfca0f515815 Mon Sep 17 00:00:00 2001 From: BotoX Date: Wed, 17 Feb 2016 09:03:40 +0100 Subject: [PATCH] reworked mother zombie "randomizer" uses randomized round-robin ensuring that a client will not be infected twice in a row --- src/zr/immunityhandler.inc | 2 +- src/zr/infect.inc | 109 ++++++++++++++++++++++++++++--------- src/zr/spawnprotect.inc | 6 +- 3 files changed, 87 insertions(+), 30 deletions(-) diff --git a/src/zr/immunityhandler.inc b/src/zr/immunityhandler.inc index 40e22d6..ad077e0 100644 --- a/src/zr/immunityhandler.inc +++ b/src/zr/immunityhandler.inc @@ -278,7 +278,7 @@ Action:ImmunityOnClientDamage(client, attacker, &Float:damage) } // Check if spawn protection is on. - if (bInfectImmune[client][INFECT_TYPE_NORMAL]) + if (bInfectImmune[client]) { // Block damage. return Plugin_Handled; diff --git a/src/zr/infect.inc b/src/zr/infect.inc index 5c32493..1f5a863 100644 --- a/src/zr/infect.inc +++ b/src/zr/infect.inc @@ -65,18 +65,24 @@ new Handle:hInfectCountdownData = INVALID_HANDLE; new bool:bZombie[MAXPLAYERS + 1]; /** - * @section bInfectImmune indexes - */ -#define INFECT_TYPE_MOTHER 0 -#define INFECT_TYPE_NORMAL 1 -/** - * @endsection + * Array for flagging client to be protected. */ +new bool:bInfectImmune[MAXPLAYERS + 1]; /** - * Array for flagging client to be protected. (See defines above) + * Available mother zombie infection status. */ -new bool:bInfectImmune[MAXPLAYERS + 1][2]; +enum InfectMotherStatus +{ + MotherStatus_None = 0, + MotherStatus_Chosen = 1, + MotherStatus_Last = 2 +} + +/** + * Array for storing client mother zombie protection status. + */ +new InfectMotherStatus:g_InfectMotherStatus[MAXPLAYERS + 1]; /** * Available mother zombie infection modes. @@ -139,9 +145,11 @@ InfectOnCommandsCreate() */ InfectClientInit(client) { - // Reset infect immunity flags. - bInfectImmune[client][INFECT_TYPE_MOTHER] = false; - bInfectImmune[client][INFECT_TYPE_NORMAL] = false; + // Reset infect immunity flag. + bInfectImmune[client] = false; + + // Reset mother zombie protection. + g_InfectMotherStatus[client] = MotherStatus_None; } /** @@ -340,7 +348,7 @@ InfectOnClientHurt(client, attacker, const String:weapon[]) } // If client has infect immunity, then stop. - if (bInfectImmune[client][INFECT_TYPE_NORMAL]) + if (bInfectImmune[client]) { return; } @@ -460,7 +468,7 @@ public Action:InfectMotherZombie(Handle:timer) } // Prune list of immune clients. - eligibleclients = InfectRemoveImmuneClients(arrayEligibleClients); + //eligibleclients = InfectRemoveImmuneClients(arrayEligibleClients); // Move all clients to CT. InfectMoveAllToCT(); @@ -531,29 +539,77 @@ public Action:InfectMotherZombie(Handle:timer) } } + new candidates = 0; + new Handle:aCandidates = CreateArray(); + for (new n = 0; n < eligibleclients; n++) + { + // Get the client stored in the array index. + new client = GetArrayCell(arrayEligibleClients, n); + + // If client hasn't been chosen this cycle, put into aCandidates array. + if (g_InfectMotherStatus[client] == MotherStatus_None) + { + PushArrayCell(aCandidates, client); + candidates++; + } + } + + // Not enough candidates found. + if (candidates < mothercount) + { + for (new n = 0; n < eligibleclients; n++) + { + // Get the client stored in the array index. + new client = GetArrayCell(arrayEligibleClients, n); + + // If client hasn't been chosen last round, put into aCandidates array, + // but only until we have enough candidates. + if (!(g_InfectMotherStatus[client] & MotherStatus_Last)) + { + PushArrayCell(aCandidates, client); + candidates++; + + // Enough candidates found. + if(candidates >= mothercount) + break; + } + } + + // Restart the cycle. + // Reset all players MotherStatus. + for (int client = 0; client <= MAXPLAYERS; client++) + { + g_InfectMotherStatus[client] = MotherStatus_None; + } + } + + // Remove MotherStatus_Last flag from all players. + for (int client = 0; client <= MAXPLAYERS; client++) + { + g_InfectMotherStatus[client] &= ~MotherStatus_Last; + } + // 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) + // Stop if there are no more candidates. + if (candidates <= 0) { break; } // Get a random array index. - new i = Math_GetRandomInt(0, eligibleclients - 1); + new i = Math_GetRandomInt(0, candidates - 1); // Get the client stored in the random array index. - new client = GetArrayCell(arrayEligibleClients, i); + new client = GetArrayCell(aCandidates, i); // Infect player. InfectHumanToZombie(client, _, true); // Remove player from eligible client list. - RemoveFromArray(arrayEligibleClients, i); + RemoveFromArray(aCandidates, i); + candidates--; } // Mother zombies have been infected. @@ -561,6 +617,7 @@ public Action:InfectMotherZombie(Handle:timer) // Destroy client list. CloseHandle(arrayEligibleClients); + CloseHandle(aCandidates); } /** @@ -596,7 +653,7 @@ InfectMoveAllToCT() * @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); @@ -632,6 +689,7 @@ InfectRemoveImmuneClients(Handle:clientList, bool:keepLastPlayer = true) return len; } +*/ /** * Timer callback, displays countdown to clients. @@ -716,17 +774,16 @@ InfectHumanToZombie(client, attacker = -1, bool:motherinfect = false, bool:respa new bool:infectconsecutiveblock = GetConVarBool(g_hCvarsList[CVAR_INFECT_CONSECUTIVE_BLOCK]); if (infectconsecutiveblock) { - // If this is a mother infect, flag the player as immune for next mother - // infection. Otherwise do nothing and keep the current flag. + // If this is a mother infect, update the mother zombie protection status if (motherinfect) { - bInfectImmune[client][INFECT_TYPE_MOTHER] = true; + g_InfectMotherStatus[client] = MotherStatus_Chosen | MotherStatus_Last; } } else { // Consecutive infection protection is disabled. No immunity. - bInfectImmune[client][INFECT_TYPE_MOTHER] = false; + g_InfectMotherStatus[client] = MotherStatus_None; } // Apply effects. diff --git a/src/zr/spawnprotect.inc b/src/zr/spawnprotect.inc index 322c101..ebfbc9c 100644 --- a/src/zr/spawnprotect.inc +++ b/src/zr/spawnprotect.inc @@ -76,7 +76,7 @@ SpawnProtectOnClientSpawnPost(client) } // Disable spawn protection on client. - bInfectImmune[client][INFECT_TYPE_NORMAL] = false; + bInfectImmune[client] = false; // Start spawn protection. SpawnProtectStart(client); @@ -158,7 +158,7 @@ SpawnProtectStart(client) } // Set spawn protect flag on client. - bInfectImmune[client][INFECT_TYPE_NORMAL] = true; + bInfectImmune[client] = true; // Set spawn protect attributes. ClassApplySpeedEx(client, speed); @@ -212,7 +212,7 @@ public Action:SpawnProtectTimer(Handle:timer, any:client) if (pSpawnProtectTime[client] <= 0) { // Remove protect flag. - bInfectImmune[client][INFECT_TYPE_NORMAL] = false; + bInfectImmune[client] = false; // Tell client spawn protection is over. TranslationPrintHintText(client, "Spawn protection end");