major update so that boss rounds also can feature minion zombies that dont count towards winning the round

This commit is contained in:
2024-02-25 19:33:13 +01:00
parent 8c80d4ac05
commit 8455a1a231
5 changed files with 536 additions and 271 deletions
+234 -120
View File
@@ -69,6 +69,8 @@ int g_iBotStuckCounts;
int g_iLoadClassesIndex;
int g_iHumanCount;
int g_iZombieCount;
int g_iZombieBossIndex[g_dIndexes];
int g_iBossBotCount;
float g_fKnockBackIndex[g_dIndexes + 1];
float g_fJumpHeightIndex[g_dIndexes + 1];
@@ -86,7 +88,8 @@ bool g_bSwitchingIndex;
bool g_bRoundInProgress;
bool g_bFallDamage[g_dIndexes];
bool g_bClientProtection[g_dIndexes];
bool g_bIsBossRound;
bool g_bClientIsBoss[MAXPLAYERS + 1];
Handle g_hClientZMCookie;
Handle g_hClientHumanCookie;
@@ -1061,6 +1064,7 @@ public void OnClientPostAdminCheck(int client)
g_fJumpHeightIndex[client] = 1.0;
g_fJumpDistanceIndex[client] = 1.0;
g_fDamageMultiplier[client] = 1.0;
g_bClientIsBoss[client] = false;
g_iClientRespawnCount[client] = g_iClientRespawnCountNum;
char sCookieValue[12];
GetClientCookie(client, g_hClientZMCookie, sCookieValue, sizeof(sCookieValue));
@@ -1117,6 +1121,7 @@ public void OnClientDisconnect(int client)
g_fJumpDistanceIndex[client] = 1.0;
g_fDamageMultiplier[client] = 1.0;
g_iClientRespawnCount[client] = 0;
g_bClientIsBoss[client] = false;
SDKUnhook(client, SDKHook_OnTakeDamage, OnTakeDamage);
SDKUnhook(client, SDKHook_WeaponEquip, OnWeaponEquip);
}
@@ -1129,7 +1134,24 @@ public void Event_roundStart(Handle event, const char[] name, bool dontBroadcast
g_iZombieCount = 999;
g_bRoundInProgress = false;
g_bSwitchingIndex = true;
g_iBossBotCount = 0;
CreateTimer(g_fSwitchingTimer, Timer_switchingModel, INVALID_HANDLE);
if (g_hAmbient != null)
delete g_hAmbient;
if (StrContains(g_cDaysTitles[g_iWave - 1], "BOSS", false) != -1) //the daystitle contains the word boss in it
{
g_bIsBossRound = true; //boss rounds need BOSS in the title
EmitAmbience(g_cBossSound); //nobody will ever understand why megalovania was on the servers since 2020.
g_hAmbient = CreateTimer(g_fBossSoundLoopDuration, Timer_Ambient, INVALID_HANDLE, TIMER_REPEAT); // 0.3 seconds without sound
}
else
{
g_bIsBossRound = false; //boss rounds need BOSS in the title
int index = ambient_index();
EmitAmbience(g_cAmbientSOund[index]);
g_hAmbient = CreateTimer(g_fAmbientSoundLoopDuration, Timer_Ambient, INVALID_HANDLE, TIMER_REPEAT); // 0.3 seconds without sound
}
RetrieveWaveSettings(g_iWave);
for (int i = 1; i <= MaxClients; i++)
@@ -1138,6 +1160,7 @@ public void Event_roundStart(Handle event, const char[] name, bool dontBroadcast
{
if (IsFakeClient(i))
{
g_bClientIsBoss[i] = false;
CreateTimer(0.3, Timer_delayedSelectWaveBasedZM, GetClientUserId(i));
continue;
}
@@ -1148,19 +1171,6 @@ public void Event_roundStart(Handle event, const char[] name, bool dontBroadcast
}
}
}
if (g_hAmbient != null)
delete g_hAmbient;
if (StrContains(g_cDaysTitles[g_iWave - 1], "BOSS", false) != -1) //the daystitle contains the word boss in it
{
EmitAmbience(g_cBossSound); //nobody will ever understand why megalovania was on the servers since 2020.
g_hAmbient = CreateTimer(g_fBossSoundLoopDuration, Timer_Ambient, INVALID_HANDLE, TIMER_REPEAT); // 0.3 seconds without sound
}
else
{
int index = ambient_index();
EmitAmbience(g_cAmbientSOund[index]);
g_hAmbient = CreateTimer(g_fAmbientSoundLoopDuration, Timer_Ambient, INVALID_HANDLE, TIMER_REPEAT); // 0.3 seconds without sound
}
}
public int ambient_index()
@@ -1204,7 +1214,6 @@ public Action RetrieveWaveSettings(int wave)
Format(hostname, sizeof(hostname), "UNLOZE | [ZRiot: Day %i/%i] %s | Ranking", wave, total_days, g_cDaysTitles[wave - 1]);
ServerCommand("hostname \"%s\"", hostname);
PrintToChatAll("Day %i: %s", wave, g_cDaysTitles[wave - 1]);
LoadWave(wave);
delete l_hWave;
@@ -1276,13 +1285,35 @@ public void LoadWave(int wave)
g_iClientRespawnCountNum = kv.GetNum("Respawns", 5);
l_iBotQuote = kv.GetNum("bot_scaling", 1);
int l_iBotQuoteStatic = kv.GetNum("bot_static", 1);
if (l_iBotQuote == 0) //we use static bot amount instead
l_iPlayers = 0; //counting legit players for bot scaling.
for (int i = 1; i < MaxClients; i++)
{
SettingBotQoute(l_iBotQuoteStatic, true);
if (IsValidClient(i) && !IsFakeClient(i) && CS_TEAM_CT == GetClientTeam(i))
{
l_iPlayers++;
}
}
if (g_bIsBossRound)
{
//its boss round. bot_scaling is used for minion bots. bot_static is used for boss bot amount
// bot_static + bot_scaling
addBots(l_iBotQuoteStatic + (l_iPlayers * l_iBotQuote));
g_iBossBotCount = l_iBotQuoteStatic;
}
else
{
SettingBotQoute(l_iBotQuote, false);
//its not boss round.
if (l_iBotQuote == 0) //we use static bot amount instead of scaling bots based on playercount.
{
addBots(l_iBotQuoteStatic);
}
else
{
//we use bot_scaling.
addBots(l_iPlayers * l_iBotQuote);
}
}
while (!IsEndOfFile(l_hFile) && ReadFileLine(l_hFile, l_cLine, sizeof(l_cLine)))
{
@@ -1426,28 +1457,6 @@ public void LoadWave(int wave)
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void SettingBotQoute(int botscale, bool bot_static)
{
int l_iPlayers;
for (int i = 1; i < MaxClients; i++)
{
if (IsValidClient(i) && !IsFakeClient(i) && CS_TEAM_CT == GetClientTeam(i))
{
l_iPlayers++;
}
}
if (bot_static)
{
addBots(botscale);
}
else
{
addBots(l_iPlayers * botscale);
}
}
//----------------------------------------------------------------------------------------------------
// Purpose:
//----------------------------------------------------------------------------------------------------
public void addBots(int botcount)
{
if (botcount > 44)
@@ -1472,70 +1481,75 @@ public bool skipIndex(int index)
//----------------------------------------------------------------------------------------------------
public void ReadingClassValuesFromFile(int index, char[] Line)
{
char li_c[g_dLength];
Format(li_c, sizeof(li_c), Line);
if (StrContains(Line, "unique name") > -1)
{
ReplaceStrings(li_c, "unique name");
Format(g_cUniqueName[index][g_iLength], sizeof(g_cUniqueName), li_c);
}
else if (StrContains(Line, "team") > -1)
{
ReplaceStrings(li_c, "team");
Format(g_cTeam[index][g_iLength], sizeof(g_cTeam), li_c);
}
else if (StrContains(Line, "group") > -1)
{
ReplaceStrings(li_c, "group");
Format(g_cGroup[index][g_iLength], sizeof(g_cGroup), li_c);
}
else if (StrContains(Line, "sm_flags") > -1)
{
ReplaceStrings(li_c, "sm_flags");
Format(g_cSMFLAGS[index][g_iLength], sizeof(g_cSMFLAGS), li_c);
}
else if (StrContains(Line, "model path") > -1)
{
ReplaceStrings(li_c, "model path");
Format(g_cModelPath[index][g_iLength], sizeof(g_cModelPath), li_c);
PrecacheModel(li_c);
}
else if (StrContains(Line, "no_fall_damage") > -1)
{
ReplaceStrings(li_c, "no_fall_damage");
Format(g_cNoFallDmg[index][g_iLength], sizeof(g_cNoFallDmg), li_c);
}
else if (StrContains(Line, "health") > -1)
{
ReplaceStrings(li_c, "health");
Format(g_cHealth[index][g_iLength], sizeof(g_cHealth), li_c);
}
else if (StrContains(Line, "speed") > -1)
{
ReplaceStrings(li_c, "speed");
Format(g_cSpeed[index][g_iLength], sizeof(g_cSpeed), li_c);
}
else if (StrContains(Line, "knockback") > -1)
{
ReplaceStrings(li_c, "knockback");
Format(g_cKnockback[index][g_iLength], sizeof(g_cKnockback), li_c);
}
else if (StrContains(Line, "jump_height") > -1)
{
ReplaceStrings(li_c, "jump_height");
Format(g_cJumpHeight[index][g_iLength], sizeof(g_cJumpHeight), li_c);
}
else if (StrContains(Line, "jump_distance") > -1)
{
ReplaceStrings(li_c, "jump_distance");
Format(g_cJumpDistance[index][g_iLength], sizeof(g_cJumpDistance), li_c);
}
else if (StrContains(Line, "damage_multiplier") > -1)
{
ReplaceStrings(li_c, "damage_multiplier");
Format(g_cDamageMultiplier[index][g_iLength], sizeof(g_cDamageMultiplier), li_c);
g_iLoadClassesIndex++;
}
char li_c[g_dLength];
Format(li_c, sizeof(li_c), Line);
if (StrContains(Line, "unique name") > -1)
{
ReplaceStrings(li_c, "unique name");
Format(g_cUniqueName[index][g_iLength], sizeof(g_cUniqueName), li_c);
}
else if (StrContains(Line, "team") > -1)
{
ReplaceStrings(li_c, "team");
Format(g_cTeam[index][g_iLength], sizeof(g_cTeam), li_c);
}
else if (StrContains(Line, "group") > -1)
{
ReplaceStrings(li_c, "group");
Format(g_cGroup[index][g_iLength], sizeof(g_cGroup), li_c);
}
else if (StrContains(Line, "sm_flags") > -1)
{
ReplaceStrings(li_c, "sm_flags");
Format(g_cSMFLAGS[index][g_iLength], sizeof(g_cSMFLAGS), li_c);
}
else if (StrContains(Line, "model path") > -1)
{
ReplaceStrings(li_c, "model path");
Format(g_cModelPath[index][g_iLength], sizeof(g_cModelPath), li_c);
PrecacheModel(li_c);
}
else if (StrContains(Line, "no_fall_damage") > -1)
{
ReplaceStrings(li_c, "no_fall_damage");
Format(g_cNoFallDmg[index][g_iLength], sizeof(g_cNoFallDmg), li_c);
}
else if (StrContains(Line, "health") > -1)
{
ReplaceStrings(li_c, "health");
Format(g_cHealth[index][g_iLength], sizeof(g_cHealth), li_c);
}
else if (StrContains(Line, "speed") > -1)
{
ReplaceStrings(li_c, "speed");
Format(g_cSpeed[index][g_iLength], sizeof(g_cSpeed), li_c);
}
else if (StrContains(Line, "knockback") > -1)
{
ReplaceStrings(li_c, "knockback");
Format(g_cKnockback[index][g_iLength], sizeof(g_cKnockback), li_c);
}
else if (StrContains(Line, "jump_height") > -1)
{
ReplaceStrings(li_c, "jump_height");
Format(g_cJumpHeight[index][g_iLength], sizeof(g_cJumpHeight), li_c);
}
else if (StrContains(Line, "jump_distance") > -1)
{
ReplaceStrings(li_c, "jump_distance");
Format(g_cJumpDistance[index][g_iLength], sizeof(g_cJumpDistance), li_c);
}
else if (StrContains(Line, "damage_multiplier") > -1)
{
ReplaceStrings(li_c, "damage_multiplier");
Format(g_cDamageMultiplier[index][g_iLength], sizeof(g_cDamageMultiplier), li_c);
}
else if (StrContains(Line, "boss_class") > -1)
{
ReplaceStrings(li_c, "boss_class");
g_iZombieBossIndex[index] = StringToInt(li_c);
g_iLoadClassesIndex++; //use this at the last keyvalue to indicate we are done.
}
}
//----------------------------------------------------------------------------------------------------
// Purpose:
@@ -1595,26 +1609,111 @@ public Action SelectWaveBasedZM(int client, int state)
if (state == 0)
{
for (int i = 0; i < g_dIndexes; i++)
if (g_bIsBossRound && g_iBossBotCount > 0 && !g_bClientIsBoss[client]) //does not work setting on roundstart. so instead doing when applying ZM skin.
{
if (strlen(g_cZMRoundClasses[i][g_iLength]) > 0 && strlen(g_cGroup[i][g_iLength]) < 1 && strlen(g_cSMFLAGS[i][g_iLength]) < 1)
g_bClientIsBoss[client] = true;
g_iBossBotCount--; //picking certain bots as the boss bots. all other bots are the minions.
}
if (g_bIsBossRound)
{
if (g_bClientIsBoss[client])
{
l_iZMIndex++;
//its boss round and we set class for a boss bot
for (int i = 0; i < g_dIndexes; i++)
{
if (strlen(g_cZMRoundClasses[i][g_iLength]) > 0 && strlen(g_cGroup[i][g_iLength]) < 1 && strlen(g_cSMFLAGS[i][g_iLength]) < 1
&& g_iZombieBossIndex[i])
{
l_iZMIndex++; //we set amount of boss classes that the boss bot can pick between.
}
}
l_ibotIndex = GetRandomInt(0, l_iZMIndex -1);
l_iZMIndex = 0;
for (int i = 0; i < g_dIndexes; i++)
{
if (strlen(g_cZMRoundClasses[i][g_iLength]) > 0 && strlen(g_cGroup[i][g_iLength]) < 1 && strlen(g_cSMFLAGS[i][g_iLength]) < 1)
{
if (!g_iZombieBossIndex[i])
{
continue;
}
else if (l_ibotIndex == l_iZMIndex)
{
g_iClientZMClasses[client] = i;
break;
}
else
{
l_iZMIndex++;
}
}
}
}
else
{
//its boss round and we set class for a minion bot
for (int i = 0; i < g_dIndexes; i++)
{
if (strlen(g_cZMRoundClasses[i][g_iLength]) > 0 && strlen(g_cGroup[i][g_iLength]) < 1 && strlen(g_cSMFLAGS[i][g_iLength]) < 1
&& !g_iZombieBossIndex[i])
{
l_iZMIndex++; //we set amount of normal zombie classes the minion bot can pick between. skipping out the boss classes.
}
}
l_ibotIndex = GetRandomInt(0, l_iZMIndex -1);
l_iZMIndex = 0;
for (int i = 0; i < g_dIndexes; i++)
{
if (strlen(g_cZMRoundClasses[i][g_iLength]) > 0 && strlen(g_cGroup[i][g_iLength]) < 1 && strlen(g_cSMFLAGS[i][g_iLength]) < 1)
{
if (g_iZombieBossIndex[i])
{
continue;
}
else if (l_ibotIndex == l_iZMIndex)
{
g_iClientZMClasses[client] = i;
break;
}
else
{
l_iZMIndex++;
}
}
}
}
}
l_ibotIndex = GetRandomInt(0, l_iZMIndex -1);
l_iZMIndex = 0;
for (int i = 0; i < g_dIndexes; i++)
else
{
if (strlen(g_cZMRoundClasses[i][g_iLength]) > 0 && strlen(g_cGroup[i][g_iLength]) < 1 && strlen(g_cSMFLAGS[i][g_iLength]) < 1)
//its normal round. just setting the classes randomly.
for (int i = 0; i < g_dIndexes; i++)
{
if (l_ibotIndex == l_iZMIndex)
if (strlen(g_cZMRoundClasses[i][g_iLength]) > 0 && strlen(g_cGroup[i][g_iLength]) < 1 && strlen(g_cSMFLAGS[i][g_iLength]) < 1)
{
g_iClientZMClasses[client] = i;
break;
l_iZMIndex++; //here we get to know what the last index is, that way the randomint can pick between index 0 and last index for ZM classes.
}
}
l_ibotIndex = GetRandomInt(0, l_iZMIndex -1);
l_iZMIndex = 0;
for (int i = 0; i < g_dIndexes; i++)
{
if (strlen(g_cZMRoundClasses[i][g_iLength]) > 0 && strlen(g_cGroup[i][g_iLength]) < 1 && strlen(g_cSMFLAGS[i][g_iLength]) < 1)
{
if (l_ibotIndex == l_iZMIndex)
{
g_iClientZMClasses[client] = i;
break;
}
else
{
l_iZMIndex++;
}
}
else
l_iZMIndex++;
}
}
}
@@ -1942,10 +2041,25 @@ public Action UpdateWaveCount(int client)
}
}
}
g_iZMCount--;
PrintHintTextToAll("Day %i: %s\nRemaining Zombies: %i\nHumans: %i\nZombies: %i", g_iWave, g_cDaysTitles[g_iWave - 1], g_iZMCount, humanCount, zombieCount);
g_iHumanCount = humanCount;
g_iZombieCount = zombieCount;
if (g_bIsBossRound)
{
//we only reduce zombie count if the killed bot had a boss zombie class.
//if the killed bot instead had a zombie class of a minion we do not reduce the zombie count.
if (g_bClientIsBoss[client])
{
g_iZMCount--;
PrintHintTextToAll("Day %i: %s\nRemaining Zombies: %i\nHumans: %i\nZombies: %i", g_iWave, g_cDaysTitles[g_iWave - 1], g_iZMCount, humanCount, zombieCount);
g_iHumanCount = humanCount;
g_iZombieCount = zombieCount;
}
}
else
{
g_iZMCount--;
PrintHintTextToAll("Day %i: %s\nRemaining Zombies: %i\nHumans: %i\nZombies: %i", g_iWave, g_cDaysTitles[g_iWave - 1], g_iZMCount, humanCount, zombieCount);
g_iHumanCount = humanCount;
g_iZombieCount = zombieCount;
}
}
if (g_iZMCount <= 0 && g_bRoundInProgress)
{