diff --git a/cstrike/addons/sourcemod/translations/es/zombiereloaded.phrases.txt b/cstrike/addons/sourcemod/translations/es/zombiereloaded.phrases.txt index c890184..0c8f0dc 100644 --- a/cstrike/addons/sourcemod/translations/es/zombiereloaded.phrases.txt +++ b/cstrike/addons/sourcemod/translations/es/zombiereloaded.phrases.txt @@ -358,6 +358,13 @@ "es" "El ultimo zombi a dejado el juego, y te ha pasado la infeccion a ti. (luego se lo agradeces xD)" } + // Center Text + + "Infect countdown" + { + "en" "First infection in {1} seconds." + } + // Menu "Infect menu clients title" diff --git a/cstrike/addons/sourcemod/translations/no/zombiereloaded.phrases.txt b/cstrike/addons/sourcemod/translations/no/zombiereloaded.phrases.txt index be8633e..7f10b76 100644 --- a/cstrike/addons/sourcemod/translations/no/zombiereloaded.phrases.txt +++ b/cstrike/addons/sourcemod/translations/no/zombiereloaded.phrases.txt @@ -357,6 +357,13 @@ "no" "Den siste zombien har forlatt spillet. Du er blitt valgt som erstatning." } + // Center Text + + "Infect countdown" + { + "en" "Første infeksjon om {1} sekunder." + } + // Menu "Infect menu clients title" diff --git a/cstrike/addons/sourcemod/translations/ru/zombiereloaded.phrases.txt b/cstrike/addons/sourcemod/translations/ru/zombiereloaded.phrases.txt index 255312c..5b40cd5 100644 --- a/cstrike/addons/sourcemod/translations/ru/zombiereloaded.phrases.txt +++ b/cstrike/addons/sourcemod/translations/ru/zombiereloaded.phrases.txt @@ -358,6 +358,13 @@ "ru" "Последний зомби покинул игру, поэтому вам досталась его инфекция." } + // Center Text + + "Infect countdown" + { + "en" "First infection in {1} seconds." + } + // Menu "Infect menu clients title" diff --git a/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt b/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt index 2483b57..a88e08e 100644 --- a/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt +++ b/cstrike/addons/sourcemod/translations/zombiereloaded.phrases.txt @@ -372,6 +372,14 @@ "en" "The last zombie has left the game, and has passed the infection on to you." } + // Center Text + + "Infect countdown" + { + "#format" "{1:d}" + "en" "First infection in {1} seconds." + } + // Menu "Infect menu clients title" diff --git a/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg b/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg index a6a2956..c230cff 100644 --- a/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg +++ b/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg @@ -289,6 +289,10 @@ zr_hitgroups "1" // Default: "5" zr_infect_mzombie_ratio "5" +// Counts down to the first infection of the round. The counter is displayed in the middle of the screen. +// Default: "0" +zr_infect_mzombie_countdown "0" + // Teleport mother zombies back to spawn on infect. // Default: "0" zr_infect_mzombie_respawn "0" diff --git a/docs/zr_manual.htm b/docs/zr_manual.htm index b177ff9..ea34835 100644 --- a/docs/zr_manual.htm +++ b/docs/zr_manual.htm @@ -2570,6 +2570,19 @@ tune game balance.

+ + zr_infect_mzombie_countdown + 0 + + + +

Counts down to the first infection of the round. The counter is + displayed in the middle of the screen.

+

Options:
+ 0 or 1

+ + + zr_infect_mzombie_respawn 0 diff --git a/src/zr/cvars.inc b/src/zr/cvars.inc index 261898a..ce3390c 100644 --- a/src/zr/cvars.inc +++ b/src/zr/cvars.inc @@ -100,6 +100,7 @@ enum CvarsList Handle:CVAR_INFECT_CONSECUTIVE_BLOCK, Handle:CVAR_INFECT_WEAPONS_DROP, Handle:CVAR_INFECT_MZOMBIE_RATIO, + Handle:CVAR_INFECT_MZOMBIE_COUNTDOWN, Handle:CVAR_INFECT_MZOMBIE_RESPAWN, Handle:CVAR_INFECT_EXPLOSION, Handle:CVAR_INFECT_FIREBALL, @@ -316,6 +317,7 @@ 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_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)."); g_hCvarsList[CVAR_INFECT_SPAWNTIME_MAX] = CreateConVar("zr_infect_spawntime_max", "50.0", "Maximum time from the start of the round until picking the mother zombie(s)."); diff --git a/src/zr/infect.inc b/src/zr/infect.inc index 9f7f415..15ff065 100644 --- a/src/zr/infect.inc +++ b/src/zr/infect.inc @@ -46,9 +46,13 @@ */ /** - * Global variable to store infect timer handle. + * @section Global variables to store infect timer handles. */ new Handle:tInfect = INVALID_HANDLE; +new Handle:tInfectCountdown = INVALID_HANDLE; +/** + * @endsection + */ /** * Array for flagging client as zombie. @@ -74,8 +78,9 @@ new bool:bInfectImmune[MAXPLAYERS + 1][2]; */ InfectOnMapStart() { - // Reset timer handle. - tInfect = INVALID_HANDLE; + // Stop timers if running. + ZREndTimer(tInfect); + ZREndTimer(tInfectCountdown); } /** @@ -336,15 +341,9 @@ InfectOnClientHurt(client, attacker, const String:weapon[]) */ InfectOnRoundStart() { - // If infect timer is running, then kill it. - if (tInfect != INVALID_HANDLE) - { - // Kill timer. - KillTimer(tInfect); - - // Reset timer handle. - tInfect = INVALID_HANDLE; - } + // Stop infect timers if running. + ZREndTimer(tInfect); + ZREndTimer(tInfectCountdown); // Tell plugin there are no zombies. g_bZombieSpawned = false; @@ -355,12 +354,9 @@ InfectOnRoundStart() */ InfectOnRoundFreezeEnd() { - // If infect timer is running, then kill it. - if (tInfect != INVALID_HANDLE) - { - // Kill timer. - KillTimer(tInfect); - } + // Stop infect timers if running. + ZREndTimer(tInfect); + ZREndTimer(tInfectCountdown); // If the zombie has spawned already (had to be through admin) then stop. if (g_bZombieSpawned) @@ -375,7 +371,24 @@ InfectOnRoundFreezeEnd() // Pick random time between min and max. new Float:randomtime = GetRandomFloat(infectspawntimemin, infectspawntimemax); + // Round to the nearest whole number (and convert back to a float) so the countdown is synched with it. + float(RoundToNearest(randomtime)); + tInfect = CreateTimer(randomtime, InfectMotherZombie, _, TIMER_FLAG_NO_MAPCHANGE); + + // Check cvar and start a countdown timer if enabled. + new bool:countdown = GetConVarBool(g_hCvarsList[CVAR_INFECT_MZOMBIE_COUNTDOWN]); + if (countdown) + { + // Store the time until infection, and initialize the counter. + new Handle:hCountdownData = CreateDataPack(); + WritePackFloat(hCountdownData, randomtime); + WritePackFloat(hCountdownData, 0.0); + tInfectCountdown = CreateTimer(1.0, InfectCountdown, hCountdownData, TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE); + + // Display initial tick. + InfectCountdown(tInfectCountdown, hCountdownData); + } } /** @@ -551,6 +564,49 @@ public Action:InfectMotherZombie(Handle:timer) CloseHandle(arrayEligibleClients); } +/** + * Timer callback, displays countdown to clients. + * + * @param timer The timer handle. + */ +public Action:InfectCountdown(Handle:timer, Handle:hCountdownData) +{ + new bool:countdown = GetConVarBool(g_hCvarsList[CVAR_INFECT_MZOMBIE_COUNTDOWN]); + if (!countdown) + { + // Kill the timer. + ZREndTimer(tInfectCountdown, false); + CloseHandle(hCountdownData); + return Plugin_Stop; + } + + // Read the info from the datapack. + ResetPack(hCountdownData); + new Float:length = ReadPackFloat(hCountdownData); + new Float:counter = ReadPackFloat(hCountdownData); + + // Check if the countdown has finished. + if (counter >= length) + { + // Kill timer. + ZREndTimer(tInfectCountdown, false); + CloseHandle(hCountdownData); + return Plugin_Stop; + } + + // Print the countdown text to the clients. + TranslationPrintCenterTextAll(false, "Infect countdown", RoundToNearest(length - counter)); + + counter++; + + // Write the new counter value to the datapack. + ResetPack(hCountdownData); + WritePackFloat(hCountdownData, length); + WritePackFloat(hCountdownData, counter); + + return Plugin_Continue; +} + /** * Infects a client. Execute events, sets attributes and flags that indicate * that the client is a zombie. diff --git a/src/zr/translation.inc b/src/zr/translation.inc index 812fdae..9e72e1c 100644 --- a/src/zr/translation.inc +++ b/src/zr/translation.inc @@ -274,6 +274,46 @@ stock TranslationPrintCenterText(client, any:...) PrintCenterText(client, translation); } +/** + * Print center text to all clients. (with style) + * + * @param client The client index. + * @param ... Translation formatting parameters. + */ +stock TranslationPrintCenterTextAll(bool:admin, any:...) +{ + for (new client = 1; client <= MaxClients; client++) + { + // Skip clients not in game. + if (!IsClientInGame(client)) + { + continue; + } + + // Skip clients who haven't selected a team yet (team menu open). + if (GetClientTeam(client) == CS_TEAM_NONE) + { + continue; + } + + // Skip non-admins if only printing to admins. + if (admin && !ZRIsClientAdmin(client)) + { + continue; + } + + // Set translation target + SetGlobalTransTarget(client); + + // Translate phrase. + decl String:translation[TRANSLATION_MAX_LENGTH_CHAT]; + VFormat(translation, sizeof(translation), "%t", 2); + + // Print translated phrase to client. + PrintCenterText(client, translation); + } +} + /** * Print HUD text to client. (with style) *