2009-04-22 04:53:19 +02:00
/*
* ============================================================================
*
2009-07-05 08:49:23 +02:00
* Zombie : Reloaded
2009-04-22 04:53:19 +02:00
*
2009-06-12 05:51:26 +02:00
* File : infect . inc
* Type : Core
* Description : Client infection functions .
*
2013-01-12 08:47:36 +01:00
* Copyright ( C ) 2009 - 2013 Greyscale , Richard Helgeby
2009-06-12 05:51:26 +02:00
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http :// www . gnu . org / licenses />.
2009-04-22 04:53:19 +02:00
*
* ============================================================================
*/
2020-12-08 21:37:01 +01:00
#if defined REQUIRE_PLUGIN
#define TEMP_REQUIRE_PLUGIN
#undef REQUIRE_PLUGIN
#endif
#tryinclude "AFKManager.inc"
#tryinclude "TeamManager.inc"
/* Restore old REQUIRE_PLUGIN value if necessary */
#if defined TEMP_REQUIRE_PLUGIN
#define REQUIRE_PLUGIN
#undef TEMP_REQUIRE_PLUGIN
#endif
new bool : g_AFKManagerLoaded = false ;
new bool : g_TeamManagerLoaded = false ;
2009-04-22 04:53:19 +02:00
/**
* @ section Explosion flags .
*/
#define EXP_NODAMAGE 1
#define EXP_REPEATABLE 2
#define EXP_NOFIREBALL 4
#define EXP_NOSMOKE 8
#define EXP_NODECAL 16
#define EXP_NOSPARKS 32
#define EXP_NOSOUND 64
#define EXP_RANDOMORIENTATION 128
#define EXP_NOFIREBALLSMOKE 256
#define EXP_NOPARTICLES 512
#define EXP_NODLIGHTS 1024
#define EXP_NOCLAMPMIN 2048
#define EXP_NOCLAMPMAX 4096
/**
* @ endsection
*/
/**
2011-12-26 17:45:08 +01:00
* @ section Global variables to store infect timer handles .
2009-04-22 04:53:19 +02:00
*/
2017-01-22 15:09:22 +01:00
new Handle : g_tInfect = INVALID_HANDLE ;
new Handle : g_tInfectCountdown = INVALID_HANDLE ;
2011-12-26 17:45:08 +01:00
/**
* @ endsection
*/
2009-04-22 04:53:19 +02:00
2012-05-31 12:43:48 +02:00
/**
* Infection countdown data pack .
*/
2017-01-22 15:09:22 +01:00
new Handle : g_hInfectCountdownData = INVALID_HANDLE ;
2012-05-31 12:43:48 +02:00
2009-04-22 04:53:19 +02:00
/**
* Array for flagging client as zombie .
*/
2017-01-22 15:09:22 +01:00
new bool : g_bZombie [ MAXPLAYERS + 1 ];
2009-04-22 04:53:19 +02:00
/**
2016-02-17 09:03:40 +01:00
* Array for flagging client to be protected .
2009-04-22 04:53:19 +02:00
*/
2017-01-22 15:09:22 +01:00
new bool : g_bInfectImmune [ MAXPLAYERS + 1 ];
2016-02-17 09:03:40 +01:00
2009-04-22 04:53:19 +02:00
/**
2017-01-22 15:09:22 +01:00
* Array for storing client mother zombie last flag .
2009-04-22 04:53:19 +02:00
*/
2017-01-22 15:09:22 +01:00
new bool : g_bInfectMotherLast [ MAXPLAYERS + 1 ];
2009-04-22 04:53:19 +02:00
/**
2017-01-22 15:09:22 +01:00
* SteamID cache for storing client mother zombie protection status .
2009-04-22 04:53:19 +02:00
*/
2017-01-22 15:09:22 +01:00
new Handle : g_hInfectMotherCycle = INVALID_HANDLE ;
2020-12-08 21:37:01 +01:00
new Handle : g_hInfectMotherCycleRTD = INVALID_HANDLE ;
2009-04-22 04:53:19 +02:00
2013-01-10 06:21:30 +01:00
/**
* 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). */
}
2020-12-08 21:37:01 +01:00
/**
* All plugins have finished loading .
*/
InfectOnAllPluginsLoaded ()
{
#if defined _AFKManager_Included
g_AFKManagerLoaded = LibraryExists ( " AFKManager " );
LogMessage ( " AFKManager: %s " , ( g_AFKManagerLoaded ? " loaded " : " not loaded " ));
#endif
#if defined _TeamManager_include
g_TeamManagerLoaded = LibraryExists ( " TeamManager " );
LogMessage ( " TeamManager: %s " , ( g_TeamManagerLoaded ? " loaded " : " not loaded " ));
#endif
}
/**
* A library was added .
*/
InfectOnLibraryAdded ( const String : name [])
{
if ( StrEqual ( name , " AFKManager " ))
{
// AFKManager loaded.
g_AFKManagerLoaded = true ;
}
else if ( StrEqual ( name , " TeamManager " ))
{
// TeamManager loaded.
g_TeamManagerLoaded = true ;
}
}
/**
* A library was removed .
*/
InfectOnLibraryRemoved ( const String : name [])
{
if ( StrEqual ( name , " AFKManager " ))
{
// AFKManager unloaded.
g_AFKManagerLoaded = false ;
}
else if ( StrEqual ( name , " TeamManager " ))
{
// TeamManager unloaded.
g_TeamManagerLoaded = false ;
}
}
2009-04-22 04:53:19 +02:00
/**
2012-05-29 23:40:32 +02:00
* Map is ending .
2009-04-22 04:53:19 +02:00
*/
2012-05-29 23:40:32 +02:00
InfectOnMapEnd ()
2009-04-22 04:53:19 +02:00
{
2012-05-29 23:40:32 +02:00
// Reset timers. Infect timers are invalidated on a map change if they are
// still running.
2017-01-22 15:09:22 +01:00
ZREndTimer ( g_tInfect );
ZREndTimer ( g_tInfectCountdown );
2012-05-31 12:43:48 +02:00
InfectStopCountdown ();
2017-01-22 15:09:22 +01:00
// Clear mother zombie round-robin cycle storage.
SteamidCacheReset ( g_hInfectMotherCycle );
2020-12-08 21:37:01 +01:00
SteamidCacheReset ( g_hInfectMotherCycleRTD );
2009-04-23 06:39:11 +02:00
}
/**
* Loads downloadable content data for infect module .
*/
InfectLoad ()
{
2017-08-26 23:55:11 +02:00
// Create mother zombie round-robin cycle storage.
g_hInfectMotherCycle = SteamidCacheCreate ();
2020-12-08 21:37:01 +01:00
g_hInfectMotherCycleRTD = SteamidCacheCreate ();
2017-08-26 23:55:11 +02:00
2009-04-22 04:53:19 +02:00
// Get infection sound.
decl String : sound [ PLATFORM_MAX_PATH ];
GetConVarString ( g_hCvarsList [ CVAR_INFECT_SOUND ], sound , sizeof ( sound ));
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// If infect sound cvar is empty, then stop.
if ( ! sound [ 0 ])
{
return ;
}
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// Prepend sound/ to the path.
Format ( sound , sizeof ( sound ), " sound/%s " , sound );
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// Add sound file to downloads table.
AddFileToDownloadsTable ( sound );
}
2009-06-15 21:43:06 +02:00
/**
* Create commands specific to infect here .
*/
InfectOnCommandsCreate ()
{
2009-10-26 23:17:22 +01:00
RegConsoleCmd ( " zr_infect " , InfectInfectCommand , " Infect a client. Usage: zr_infect <filter> [respawn - 1/0] " );
RegConsoleCmd ( " zr_human " , InfectHumanCommand , " Turn a client into a human. Usage: zr_human <filter> [respawn - 1/0] " );
2009-06-15 21:43:06 +02:00
}
2009-04-22 04:53:19 +02:00
/**
* Client is joining the server .
2016-02-06 00:47:47 +01:00
*
* @ param client The client index .
2009-04-22 04:53:19 +02:00
*/
InfectClientInit ( client )
{
2016-02-17 09:03:40 +01:00
// Reset infect immunity flag.
2017-01-22 15:09:22 +01:00
g_bInfectImmune [ client ] = false ;
2016-02-17 09:03:40 +01:00
2017-01-22 15:09:22 +01:00
// Reset mother zombie last flag.
g_bInfectMotherLast [ client ] = false ;
2020-12-08 21:37:01 +01:00
new bool : infectroundrobinrtd = GetConVarBool ( g_hCvarsList [ CVAR_INFECT_ROUND_ROBIN_RTD ]);
if ( infectroundrobinrtd && ! SteamidCacheClientExists ( g_hInfectMotherCycleRTD , client ))
{
SteamidCacheAddClient ( g_hInfectMotherCycleRTD , client );
int players = 0 ;
int playersInList = 0 ;
for ( int x = 1 ; x <= MaxClients ; x ++ )
{
if ( ! IsClientInGame ( x ))
continue ;
#if defined _AFKManager_Included
if ( g_AFKManagerLoaded )
{
if ( GetClientIdleTime ( x ) > 3 * 60 )
continue ;
}
#endif
players ++ ;
if ( SteamidCacheClientExists ( g_hInfectMotherCycle , x ))
playersInList ++ ;
}
if ( players && playersInList )
{
float mzombiechance = float ( playersInList ) / float ( players );
float dice = GetRandomFloat ();
if ( dice < mzombiechance )
SteamidCacheAddClient ( g_hInfectMotherCycle , client );
}
}
2009-04-22 04:53:19 +02:00
}
/**
* Client is leaving the server .
2016-02-06 00:47:47 +01:00
*
2009-04-22 04:53:19 +02:00
* @ param client The client index .
*/
InfectOnClientDisconnect ( client )
{
2009-06-16 06:45:50 +02:00
// If client is still connecting, then stop.
if ( ! IsClientInGame ( client ))
{
return ;
}
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// If zombie hasn't spawned, then stop.
2015-03-22 18:06:40 +01:00
if ( ! InfectHasZombieSpawned ())
2009-04-22 04:53:19 +02:00
{
return ;
}
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// If client is dead, then stop.
if ( ! IsPlayerAlive ( client ))
{
return ;
}
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// Initialize count variables
new zombiecount ;
new humancount ;
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// Count valid clients.
ZRCountValidClients ( zombiecount , humancount );
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// If client is a human.
2009-04-24 05:02:19 +02:00
if ( InfectIsClientHuman ( client ))
2009-04-22 04:53:19 +02:00
{
// If there are other humans (ignoring this human), then stop.
if ( humancount > 1 )
{
return ;
}
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// If there are no more clients in the server, then stop.
if ( ! ZRTeamHasClients ( CS_TEAM_T ))
{
return ;
}
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// Manually terminate round.
2009-04-29 01:58:41 +02:00
RoundEndTerminateRound ( ROUNDEND_DELAY , ZombiesWin );
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
return ;
}
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// We know here that player is a zombie.
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// If there is 1 or less humans, then stop.
if ( humancount <= 1 )
{
return ;
}
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// If there are other zombies (ignoring this zombie), then stop.
if ( zombiecount - 1 )
{
return ;
}
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// Create eligible player list.
2020-12-08 21:37:01 +01:00
new Handle : arrayEligibleClients = CreateArray ();
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// Create eligible client list, with no mother infect immunities
new eligibleclients = ZRCreateEligibleClientList ( arrayEligibleClients , true , true , true );
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// If there are no eligible client's then stop.
if ( ! eligibleclients )
{
2009-07-24 02:05:04 +02:00
// Destroy handle.
CloseHandle ( arrayEligibleClients );
2009-04-22 04:53:19 +02:00
return ;
}
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// Get a random valid array index.
2011-06-17 14:44:51 +02:00
new randindex = Math_GetRandomInt ( 0 , eligibleclients - 1 );
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// Get the client stored in the random array index.
new randclient = GetArrayCell ( arrayEligibleClients , randindex );
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// Infect player.
2009-06-15 21:43:06 +02:00
InfectHumanToZombie ( randclient );
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// Tell client they have been randomly been chosen to replace disconnecting zombie.
2009-05-14 09:32:01 +02:00
TranslationPrintToChat ( randclient , " Infect disconnect " );
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// Destroy handle.
CloseHandle ( arrayEligibleClients );
}
/**
* Client is joining a team .
2016-02-06 00:47:47 +01:00
*
2009-04-22 04:53:19 +02:00
* @ param client The client index .
2016-02-06 00:47:47 +01:00
* @ param team The team index .
2009-04-22 04:53:19 +02:00
*/
InfectOnClientTeam ( client , team )
{
// If client isn't joining spec, then stop.
if ( team != CS_TEAM_SPECTATOR )
{
return ;
}
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// Disable zombie flag on client.
2017-01-22 15:09:22 +01:00
g_bZombie [ client ] = false ;
2009-04-22 04:53:19 +02:00
}
/**
* Client is spawning into the game .
2016-02-06 00:47:47 +01:00
*
2009-04-22 04:53:19 +02:00
* @ param client The client index .
*/
InfectOnClientSpawn ( client )
{
2018-08-28 13:22:54 +02:00
// Disable zombie flag on client.
g_bZombie [ client ] = false ;
2018-09-06 13:50:30 +02:00
// Check if client is spawning on the terrorists team.
if ( ZRIsClientOnTeam ( client , CS_TEAM_T ) && InfectHasZombieSpawned ())
{
CS_SwitchTeam ( client , CS_TEAM_CT );
CS_RespawnPlayer ( client );
}
2019-09-27 16:40:58 +02:00
// Unglitch kevlar, set last hitgroup to HITGROUP_GENERIC
ToolsSetClientLastHitGroup ( client , HITGROUP_GENERIC );
2018-08-28 14:54:42 +02:00
// Forward event to modules.
ZSpawnOnClientSpawn ( client );
2009-04-22 04:53:19 +02:00
}
2009-05-21 07:39:24 +02:00
/**
* Client has been killed .
2016-02-06 00:47:47 +01:00
*
2009-05-21 07:39:24 +02:00
* @ param client The client index .
* @ param attacker The attacker index .
*/
InfectOnClientDeath ( client , attacker )
{
// If attacker isn't valid, then stop.
2009-05-21 07:42:45 +02:00
if ( ! ZRIsClientValid ( attacker ))
2009-05-21 07:39:24 +02:00
{
return ;
}
2016-02-06 00:47:47 +01:00
2009-05-21 07:39:24 +02:00
// If attacker isn't a human, then stop.
if ( ! InfectIsClientHuman ( attacker ))
{
return ;
}
2016-02-06 00:47:47 +01:00
2009-05-21 07:39:24 +02:00
// If client isn't a zombie, then stop.
if ( ! InfectIsClientInfected ( client ))
{
return ;
}
2016-02-06 00:47:47 +01:00
2009-05-21 07:39:24 +02:00
// Add kill bonus to attacker's score.
2009-05-21 07:42:45 +02:00
new bonus = ClassGetKillBonus ( client );
2009-05-21 07:39:24 +02:00
new score = ToolsClientScore ( attacker , true , false );
ToolsClientScore ( attacker , true , true , score + bonus );
}
2013-01-05 02:44:46 +01:00
/**
* Client has been hurt .
2009-04-22 04:53:19 +02:00
*
* @ param client The client index .
* @ param attacker The attacker index .
* @ param weapon The weapon used .
*/
InfectOnClientHurt ( client , attacker , const String : weapon [])
{
// If attacker isn't valid, then stop.
2009-04-24 05:02:19 +02:00
if ( ! ZRIsClientValid ( attacker ))
2009-04-22 04:53:19 +02:00
{
return ;
}
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// If client isn't a human, then stop.
2009-04-24 05:02:19 +02:00
if ( ! InfectIsClientHuman ( client ))
2009-04-22 04:53:19 +02:00
{
return ;
}
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// Attacker isn't a zombie, then stop.
2009-04-24 05:02:19 +02:00
if ( ! InfectIsClientInfected ( attacker ))
2009-04-22 04:53:19 +02:00
{
return ;
}
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// If client has infect immunity, then stop.
2017-01-22 15:09:22 +01:00
if ( g_bInfectImmune [ client ])
2009-04-22 04:53:19 +02:00
{
return ;
}
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// If weapon isn't a knife, then stop.
if ( ! StrEqual ( weapon , " knife " ))
{
return ;
}
2016-02-06 00:47:47 +01:00
2013-01-05 02:44:46 +01:00
// Check if the immunity module is handling the infection.
if ( ImmunityOnClientInfect ( client , attacker ))
{
2013-01-05 16:59:53 +01:00
//PrintToChatAll("InfectOnClientHurt - Infect blocked.");
2013-01-05 02:44:46 +01:00
return ;
}
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// Infect client.
2009-06-15 21:43:06 +02:00
InfectHumanToZombie ( client , attacker );
2009-04-22 04:53:19 +02:00
}
/**
* The round is starting .
*/
InfectOnRoundStart ()
{
2011-12-26 17:45:08 +01:00
// Stop infect timers if running.
2017-01-22 15:09:22 +01:00
ZREndTimer ( g_tInfect );
ZREndTimer ( g_tInfectCountdown );
2016-02-06 00:47:47 +01:00
2009-06-25 08:57:39 +02:00
// Tell plugin there are no zombies.
g_bZombieSpawned = false ;
2009-04-22 04:53:19 +02:00
}
/**
* The freeze time is ending .
*/
InfectOnRoundFreezeEnd ()
{
2011-12-26 17:45:08 +01:00
// Stop infect timers if running.
2017-01-22 15:09:22 +01:00
ZREndTimer ( g_tInfect );
ZREndTimer ( g_tInfectCountdown );
2016-02-06 00:47:47 +01:00
2010-02-14 17:07:43 +01:00
// If the zombie has spawned already (had to be through admin) then stop.
2015-03-22 18:06:40 +01:00
if ( InfectHasZombieSpawned ())
2010-02-14 17:07:43 +01:00
{
return ;
}
2016-02-06 00:47:47 +01:00
2020-12-08 21:37:01 +01:00
// Warmup
#if defined _TeamManager_include
if ( g_TeamManagerLoaded && TeamManager_InWarmup ())
{
return ;
}
#endif
2009-04-22 04:53:19 +02:00
// Get min and max times.
new Float : infectspawntimemin = GetConVarFloat ( g_hCvarsList [ CVAR_INFECT_SPAWNTIME_MIN ]);
new Float : infectspawntimemax = GetConVarFloat ( g_hCvarsList [ CVAR_INFECT_SPAWNTIME_MAX ]);
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// Pick random time between min and max.
new Float : randomtime = GetRandomFloat ( infectspawntimemin , infectspawntimemax );
2016-02-06 00:47:47 +01:00
2017-01-22 15:09:22 +01:00
g_tInfect = CreateTimer ( randomtime , InfectMotherZombie , _ , TIMER_FLAG_NO_MAPCHANGE );
2016-02-06 00:47:47 +01:00
2011-12-26 17:45:08 +01:00
// Check cvar and start a countdown timer if enabled.
new bool : countdown = GetConVarBool ( g_hCvarsList [ CVAR_INFECT_MZOMBIE_COUNTDOWN ]);
2011-12-27 09:05:27 +01:00
if ( countdown && randomtime > 1.0 )
2011-12-26 17:45:08 +01:00
{
2012-05-31 12:43:48 +02:00
// Stop old countdown timer, if it exists.
InfectStopCountdown ();
2016-02-06 00:47:47 +01:00
2011-12-26 17:45:08 +01:00
// Store the time until infection, and initialize the counter.
2017-01-22 15:09:22 +01:00
g_hInfectCountdownData = CreateDataPack ();
WritePackFloat ( g_hInfectCountdownData , randomtime );
WritePackFloat ( g_hInfectCountdownData , 0.0 );
g_tInfectCountdown = CreateTimer ( 1.0 , InfectCountdown , _ , TIMER_REPEAT | TIMER_FLAG_NO_MAPCHANGE );
2016-02-06 00:47:47 +01:00
2011-12-26 17:45:08 +01:00
// Display initial tick.
2017-01-22 15:09:22 +01:00
InfectCountdown ( g_tInfectCountdown );
2011-12-26 17:45:08 +01:00
}
2009-04-22 04:53:19 +02:00
}
/**
* The round is ending .
*/
InfectOnRoundEnd ()
{
2012-05-20 21:08:07 +02:00
// Stop infect timers if running.
2017-01-22 15:09:22 +01:00
ZREndTimer ( g_tInfect );
ZREndTimer ( g_tInfectCountdown );
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// x = client index.
2016-08-24 23:06:51 +02:00
for ( new x = 1 ; x <= MaxClients ; x ++ )
2009-04-22 04:53:19 +02:00
{
// Disable zombie flag on client.
2017-01-22 15:09:22 +01:00
g_bZombie [ x ] = false ;
2009-04-22 04:53:19 +02:00
}
}
/**
* Timer callback , chooses mother zombies .
2016-02-06 00:47:47 +01:00
*
* @ param timer The timer handle .
*/
2009-04-22 04:53:19 +02:00
public Action : InfectMotherZombie ( Handle : timer )
{
// Reset timer handle.
2017-01-22 15:09:22 +01:00
g_tInfect = INVALID_HANDLE ;
2016-02-06 00:47:47 +01:00
2020-12-08 21:37:01 +01:00
// Warmup
#if defined _TeamManager_include
if ( g_TeamManagerLoaded && TeamManager_InWarmup ())
{
return ;
}
#endif
2009-04-22 04:53:19 +02:00
// Create eligible player list.
2020-12-08 21:37:01 +01:00
new Handle : arrayEligibleClients = CreateArray ();
new eligibleclients = ZRCreateEligibleClientList ( arrayEligibleClients , true , true , true , true );
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// If there are no eligible client's then stop.
if ( ! eligibleclients )
{
2009-07-24 02:05:04 +02:00
// Destroy handle.
CloseHandle ( arrayEligibleClients );
2009-04-22 04:53:19 +02:00
return ;
}
2016-02-06 00:47:47 +01:00
2013-01-10 06:21:30 +01:00
// Move all clients to CT.
InfectMoveAllToCT ();
2016-02-06 00:47:47 +01:00
2013-01-10 06:21:30 +01:00
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 ]);
2016-02-06 00:47:47 +01:00
2013-01-10 06:21:30 +01:00
// Count valid human clients.
new humancount ;
ZRCountValidClients ( _ , humancount , _ , true );
2016-02-06 00:47:47 +01:00
2013-01-10 06:21:30 +01:00
// Get and validate infection mode. This will also log a warning on error.
new InfectMode : mode = InfectGetModeOrFail ();
2016-02-06 00:47:47 +01:00
2013-01-10 06:21:30 +01:00
// Apply infection mode.
switch ( mode )
2009-04-22 04:53:19 +02:00
{
2013-01-10 06:21:30 +01:00
case InfectMode_Invalid :
2009-04-29 01:58:41 +02:00
{
2013-01-10 06:21:30 +01:00
// Validation failed. Fall back to one mother zombie.
mothercount = 1 ;
2009-04-29 01:58:41 +02:00
}
2013-01-10 06:21:30 +01:00
case InfectMode_Dynamic :
2009-04-22 04:53:19 +02:00
{
2013-01-10 06:21:30 +01:00
// Dynamic mode. Every n-th player is infected.
2016-02-06 00:47:47 +01:00
2013-01-10 06:21:30 +01:00
// A ratio of 0 will infect one zombie (to keep backwards compatibility).
if ( ratio == 0 )
{
mothercount = 1 ;
}
2016-02-06 00:47:47 +01:00
2013-01-10 06:21:30 +01:00
// Calculate number of zombies to infect.
mothercount = RoundToNearest ( float ( humancount ) / ratio );
2016-02-06 00:47:47 +01:00
2013-01-10 06:21:30 +01:00
// 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 ;
2016-02-06 00:47:47 +01:00
2013-01-10 06:21:30 +01:00
// 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 );
2009-04-22 04:53:19 +02:00
}
}
2016-02-06 00:47:47 +01:00
2020-12-06 18:43:19 +01:00
new bool : infectroundrobin = GetConVarBool ( g_hCvarsList [ CVAR_INFECT_ROUND_ROBIN ]);
2017-10-06 13:49:11 +02:00
new candidatesMain = 0 ;
new candidatesAlt = 0 ;
new Handle : aCandidatesMain = CreateArray ();
new Handle : aCandidatesAlt = CreateArray ();
2016-02-17 09:03:40 +01:00
for ( new n = 0 ; n < eligibleclients ; n ++ )
{
// Get the client stored in the array index.
new client = GetArrayCell ( arrayEligibleClients , n );
2017-10-12 02:18:52 +02:00
// If client hasn't been chosen last round.
if ( ! g_bInfectMotherLast [ client ])
2016-02-17 09:03:40 +01:00
{
2017-10-12 02:18:52 +02:00
// If client hasn't been chosen this cycle, put into aCandidatesMain array.
2020-12-06 18:43:19 +01:00
if ( ! infectroundrobin || ! SteamidCacheClientExists ( g_hInfectMotherCycle , client ))
2017-10-12 02:18:52 +02:00
{
PushArrayCell ( aCandidatesMain , client );
candidatesMain ++ ;
}
2016-02-17 09:03:40 +01:00
2017-10-12 02:18:52 +02:00
// Else put into aCandidatesAlt array.
else
{
PushArrayCell ( aCandidatesAlt , client );
candidatesAlt ++ ;
}
2016-02-17 09:03:40 +01:00
}
}
2017-01-22 15:09:22 +01:00
// Remove mother zombie last flag from all players.
2016-02-17 09:03:40 +01:00
for ( int client = 0 ; client <= MAXPLAYERS ; client ++ )
{
2017-01-22 15:09:22 +01:00
g_bInfectMotherLast [ client ] = false ;
2016-02-17 09:03:40 +01:00
}
2017-10-06 13:49:11 +02:00
new bool : resetcycle ;
2013-01-10 06:21:30 +01:00
// Infect players.
2017-10-06 13:49:11 +02:00
new infected = 0 ;
while ( infected < mothercount )
2013-01-10 06:21:30 +01:00
{
2017-10-06 13:49:11 +02:00
// Infect one of the main candidates.
if ( candidatesMain )
2013-01-10 06:21:30 +01:00
{
2017-10-06 13:49:11 +02:00
// Get a random array index.
new i = Math_GetRandomInt ( 0 , candidatesMain - 1 );
// Get the client stored in the random array index.
new client = GetArrayCell ( aCandidatesMain , i );
// Infect player.
if ( InfectHumanToZombie ( client , _ , true ))
infected ++ ;
// Remove player from eligible client list.
RemoveFromArray ( aCandidatesMain , i );
candidatesMain -- ;
2013-01-10 06:21:30 +01:00
}
2020-12-05 20:15:28 +01:00
else
2017-10-06 13:49:11 +02:00
{
2020-12-05 20:15:28 +01:00
// No main candidates, reset the mother zombie cycle now before infecting anyone else.
2020-12-06 18:43:19 +01:00
if ( infectroundrobin && ! resetcycle )
2020-12-05 20:15:28 +01:00
{
resetcycle = true ;
// Clear mother zombie round-robin cycle storage.
SteamidCacheReset ( g_hInfectMotherCycle );
2020-12-08 21:37:01 +01:00
SteamidCacheReset ( g_hInfectMotherCycleRTD );
2017-10-06 13:49:11 +02:00
2020-12-05 20:15:28 +01:00
// Announce start of new cycle
TranslationPrintToChatAll ( true , false , " Mother zombie infect cycle reset " );
}
2016-02-06 00:47:47 +01:00
2020-12-05 20:15:28 +01:00
// Infect one of the alternate candidates.
if ( candidatesAlt )
{
// Get a random array index.
new i = Math_GetRandomInt ( 0 , candidatesAlt - 1 );
2016-02-06 00:47:47 +01:00
2020-12-05 20:15:28 +01:00
// Get the client stored in the random array index.
new client = GetArrayCell ( aCandidatesAlt , i );
2016-02-06 00:47:47 +01:00
2020-12-05 20:15:28 +01:00
// Infect player.
if ( InfectHumanToZombie ( client , _ , true ))
infected ++ ;
2017-10-12 02:18:52 +02:00
2020-12-05 20:15:28 +01:00
// Remove player from eligible client list.
RemoveFromArray ( aCandidatesAlt , i );
candidatesAlt -- ;
}
else // We have no candidates at all, abort!
{
break ;
}
2017-10-06 13:49:11 +02:00
}
}
2013-01-10 06:21:30 +01:00
// Mother zombies have been infected.
g_bZombieSpawned = true ;
2016-02-06 00:47:47 +01:00
2013-01-10 06:21:30 +01:00
// Destroy client list.
CloseHandle ( arrayEligibleClients );
2017-10-06 13:49:11 +02:00
CloseHandle ( aCandidatesMain );
CloseHandle ( aCandidatesAlt );
2013-01-10 06:21:30 +01:00
}
/**
* Moves all alive clients to the CT team .
*/
InfectMoveAllToCT ()
{
2009-04-22 04:53:19 +02:00
// Move all clients to CT
2013-01-10 06:21:30 +01:00
for ( new client = 1 ; client <= MaxClients ; client ++ )
2009-04-22 04:53:19 +02:00
{
// If client isn't in-game, then stop.
2013-01-10 06:21:30 +01:00
if ( ! IsClientInGame ( client ))
2009-04-22 04:53:19 +02:00
{
continue ;
}
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// If client is dead, then stop.
2013-01-10 06:21:30 +01:00
if ( ! IsPlayerAlive ( client ))
2009-04-22 04:53:19 +02:00
{
continue ;
}
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// Switch client to CT team.
2013-01-10 06:21:30 +01:00
CS_SwitchTeam ( client , CS_TEAM_CT );
2009-04-22 04:53:19 +02:00
}
2013-01-10 06:21:30 +01:00
}
2011-12-26 17:45:08 +01:00
/**
* Timer callback , displays countdown to clients .
2016-02-06 00:47:47 +01:00
*
* @ param timer The timer handle .
*/
2012-05-31 12:43:48 +02:00
public Action : InfectCountdown ( Handle : timer )
2011-12-26 17:45:08 +01:00
{
new bool : countdown = GetConVarBool ( g_hCvarsList [ CVAR_INFECT_MZOMBIE_COUNTDOWN ]);
if ( ! countdown )
{
2012-05-31 12:43:48 +02:00
InfectStopCountdown ();
2011-12-26 17:45:08 +01:00
return Plugin_Stop ;
}
2016-02-06 00:47:47 +01:00
2011-12-26 17:45:08 +01:00
// Read the info from the datapack.
2017-01-22 15:09:22 +01:00
ResetPack ( g_hInfectCountdownData );
new Float : length = ReadPackFloat ( g_hInfectCountdownData );
new Float : counter = ReadPackFloat ( g_hInfectCountdownData );
2016-02-06 00:47:47 +01:00
2011-12-26 17:45:08 +01:00
// Check if the countdown has finished.
if ( counter >= length )
{
2012-05-31 12:43:48 +02:00
InfectStopCountdown ();
2011-12-26 17:45:08 +01:00
return Plugin_Stop ;
}
2016-02-06 00:47:47 +01:00
2019-01-23 18:48:00 +01:00
// Ask plugin API if timer should be shown.
if ( APIOnInfectCountdown () == Plugin_Continue )
{
// Print the countdown text to the clients.
TranslationPrintCenterTextAll ( false , " Infect countdown " , RoundToNearest ( length - counter ));
}
2016-02-06 00:47:47 +01:00
2011-12-26 17:45:08 +01:00
counter ++ ;
2016-02-06 00:47:47 +01:00
2011-12-26 17:45:08 +01:00
// Write the new counter value to the datapack.
2017-01-22 15:09:22 +01:00
ResetPack ( g_hInfectCountdownData );
WritePackFloat ( g_hInfectCountdownData , length );
WritePackFloat ( g_hInfectCountdownData , counter );
2016-02-06 00:47:47 +01:00
2011-12-26 17:45:08 +01:00
return Plugin_Continue ;
}
2012-05-31 12:43:48 +02:00
/**
* Stops the infection countdown timer .
*/
InfectStopCountdown ()
{
// Kill the timer.
2017-01-22 15:09:22 +01:00
ZREndTimer ( g_tInfectCountdown );
2016-02-06 00:47:47 +01:00
2012-05-31 12:43:48 +02:00
// Destroy data pack.
2017-01-22 15:09:22 +01:00
if ( g_hInfectCountdownData != INVALID_HANDLE )
2012-05-31 12:43:48 +02:00
{
2017-01-22 15:09:22 +01:00
CloseHandle ( g_hInfectCountdownData );
g_hInfectCountdownData = INVALID_HANDLE ;
2012-05-31 12:43:48 +02:00
}
}
2009-04-22 04:53:19 +02:00
/**
2009-06-15 21:43:06 +02:00
* Infects a client . Execute events , sets attributes and flags that indicate
* that the client is a zombie .
2009-04-22 04:53:19 +02:00
*
2009-06-15 21:43:06 +02:00
* @ param client The client to infect .
* @ param attacker ( Optional ) The attacker who did the infect .
* @ param motherinfect ( Optional ) Indicates a mother zombie infect .
* @ param respawnoverride ( Optional ) Set to true to override respawn cvar .
* @ param respawn ( Optional ) Value to override with .
2009-04-22 04:53:19 +02:00
*/
2009-06-15 21:43:06 +02:00
InfectHumanToZombie ( client , attacker = - 1 , bool : motherinfect = false , bool : respawnoverride = false , bool : respawn = false )
2009-04-22 04:53:19 +02:00
{
2010-11-14 15:17:19 +01:00
// Forward pre-event to modules.
new Action : result = APIOnClientInfect ( client , attacker , motherinfect , respawnoverride , respawn );
2016-02-06 00:47:47 +01:00
2010-11-14 15:17:19 +01:00
// Check if infection should be blocked.
if ( result == Plugin_Handled )
{
2017-10-06 13:49:11 +02:00
return false ;
2010-11-14 15:17:19 +01:00
}
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// Mark player as zombie.
2017-01-22 15:09:22 +01:00
g_bZombie [ client ] = true ;
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// Check if consecutive infection protection is enabled.
new bool : infectconsecutiveblock = GetConVarBool ( g_hCvarsList [ CVAR_INFECT_CONSECUTIVE_BLOCK ]);
2020-12-06 18:43:19 +01:00
new bool : infectroundrobin = GetConVarBool ( g_hCvarsList [ CVAR_INFECT_ROUND_ROBIN ]);
// If this is a mother infect, update the mother zombie protection status
if ( motherinfect )
2011-06-17 14:08:05 +02:00
{
2020-12-06 18:43:19 +01:00
g_bInfectMotherLast [ client ] = infectconsecutiveblock ;
if ( infectroundrobin )
2020-12-08 21:37:01 +01:00
{
2017-01-22 15:09:22 +01:00
SteamidCacheAddClient ( g_hInfectMotherCycle , client );
2020-12-08 21:37:01 +01:00
}
2011-06-17 14:08:05 +02:00
}
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// Apply effects.
2009-04-24 05:02:19 +02:00
InfectFireEffects ( client );
2016-02-06 00:47:47 +01:00
2013-01-11 10:19:31 +01:00
// Stop coundown, if running.
InfectStopCountdown ();
2016-02-06 00:47:47 +01:00
2009-04-23 06:39:11 +02:00
// If attacker is valid, then continue.
2009-04-24 05:02:19 +02:00
if ( ZRIsClientValid ( attacker ))
2009-04-22 04:53:19 +02:00
{
// Create and send custom player_death event.
new Handle : event = CreateEvent ( " player_death " );
if ( event != INVALID_HANDLE )
{
SetEventInt ( event , " userid " , GetClientUserId ( client ));
SetEventInt ( event , " attacker " , GetClientUserId ( attacker ));
SetEventString ( event , " weapon " , " zombie_claws_of_death " );
FireEvent ( event , false );
}
2016-02-06 00:47:47 +01:00
2013-01-11 10:07:18 +01:00
// Apply score and health gain.
InfectUpdateScore ( attacker , client );
2009-04-22 04:53:19 +02:00
}
2016-02-06 00:47:47 +01:00
2009-07-06 23:42:25 +02:00
// Check if weapons drop is enabled.
new bool : weaponsdrop = GetConVarBool ( g_hCvarsList [ CVAR_INFECT_WEAPONS_DROP ]);
2016-02-06 00:47:47 +01:00
2009-07-06 23:33:11 +02:00
// This must be after the event forwarding because it fixes a problem caused by changing models in ClassOnClientInfected.
2009-08-27 21:56:29 +02:00
// Remove all weapons but knife.
WeaponsRemoveAllClientWeapons ( client , weaponsdrop );
2016-02-06 00:47:47 +01:00
2017-07-05 23:00:50 +02:00
// Zombie won't be able to use their knife for this amount of time
new Float : knifecooldown = GetConVarFloat ( g_hCvarsList [ CVAR_INFECT_KNIFE_COOLDOWN ]);
SetEntPropFloat ( client , Prop_Send , " m_flNextAttack " , GetGameTime () + knifecooldown );
2009-07-21 22:25:11 +02:00
// Switch the player to terrorists.
// TODO: A solution to stop confusing bots? Respawn and teleport?
CS_SwitchTeam ( client , CS_TEAM_T );
2016-02-06 00:47:47 +01:00
2009-07-21 22:25:11 +02:00
// If respawn is enabled, then teleport mother zombie back to spawnpoint.
if ( motherinfect )
{
new bool : zombierespawn = GetConVarBool ( g_hCvarsList [ CVAR_INFECT_MZOMBIE_RESPAWN ]);
if ( zombierespawn )
{
2015-03-29 18:42:04 +02:00
ZTele_TeleportClient ( client );
2009-07-21 22:25:11 +02:00
}
}
// Check override.
else
{
2019-12-30 14:19:05 +01:00
new bool : teleport = GetConVarBool ( g_hCvarsList [ CVAR_INFECT_TELEPORT ]);
2009-07-21 22:25:11 +02:00
if ( respawnoverride && respawn )
{
2015-03-29 18:42:04 +02:00
ZTele_TeleportClient ( client );
2009-07-21 22:25:11 +02:00
}
2019-12-30 14:19:05 +01:00
// Teleport to attacker when infected
else if ( teleport && ZRIsClientValid ( attacker ))
{
// Get client's position.
new Float : clientloc [ 3 ];
GetClientAbsOrigin ( attacker , clientloc );
TeleportEntity ( client , clientloc , NULL_VECTOR , NULL_VECTOR );
}
2009-07-21 22:25:11 +02:00
}
2016-02-06 00:47:47 +01:00
2016-02-12 04:16:59 +01:00
// Remove kevlar and helmet
SetEntProp ( client , Prop_Send , " m_ArmorValue " , 0 , 1 );
SetEntProp ( client , Prop_Send , " m_bHasHelmet " , 0 );
2009-07-21 22:25:11 +02:00
// Print message to client.
TranslationPrintToChat ( client , " Infect infected " );
2016-02-06 00:47:47 +01:00
2009-07-21 22:25:11 +02:00
// Forward event to modules.
ClassOnClientInfected ( client , motherinfect );
RoundEndOnClientInfected ();
DamageOnClientInfected ( client , motherinfect );
SEffectsOnClientInfected ( client );
2015-03-29 18:42:04 +02:00
ZTele_OnClientInfected ( client );
2009-07-21 22:25:11 +02:00
ZHPOnClientInfected ( client );
2010-11-14 15:17:19 +01:00
APIOnClientInfected ( client , attacker , motherinfect , respawnoverride , respawn );
2013-01-05 22:58:43 +01:00
ImmunityOnClientInfected ( client );
2016-02-17 00:48:42 +01:00
ZSpawnOnClientInfected ( client );
2017-10-06 13:49:11 +02:00
return true ;
2009-04-22 04:53:19 +02:00
}
2009-06-15 21:43:06 +02:00
/**
* Turns a zombie back into a human . Execute events , sets attributes and flags that indicate
* that the client is a human .
*
* @ param client The client to make human .
* @ param respawn Teleport client back to spawn if true .
* @ param protect Start spawn protection on new human .
*/
InfectZombieToHuman ( client , bool : respawn = false , bool : protect = false )
{
2010-11-14 15:17:19 +01:00
// Forward pre-event to modules.
new Action : result = APIOnClientHuman ( client , respawn , protect );
2016-02-06 00:47:47 +01:00
2010-11-14 15:17:19 +01:00
// Check if action should be blocked.
if ( result == Plugin_Handled )
{
2017-10-06 13:49:11 +02:00
return false ;
2010-11-14 15:17:19 +01:00
}
2016-02-06 00:47:47 +01:00
2009-06-15 21:43:06 +02:00
// Mark player as human.
2017-01-22 15:09:22 +01:00
g_bZombie [ client ] = false ;
2016-02-06 00:47:47 +01:00
2009-06-15 21:43:06 +02:00
// Switch the player to counter-terrorists.
CS_SwitchTeam ( client , CS_TEAM_CT );
2016-02-06 00:47:47 +01:00
2009-06-15 21:43:06 +02:00
// Set client as translation target.
SetGlobalTransTarget ( client );
2016-02-06 00:47:47 +01:00
2009-06-15 21:43:06 +02:00
// Print message to client.
TranslationPrintToChat ( client , " Infect human " );
2016-02-06 00:47:47 +01:00
2009-06-15 21:43:06 +02:00
// Forward event to modules.
2009-06-18 03:33:09 +02:00
ClassReloadPlayer ( client );
2009-06-15 21:43:06 +02:00
RoundEndOnClientInfected ();
2015-03-29 18:42:04 +02:00
ZTele_OnClientInfected ( client );
2016-02-06 00:47:47 +01:00
2018-07-29 15:13:31 +02:00
// Remove all knifes.
2018-07-29 15:14:22 +02:00
WeaponsClearClientWeaponSlot ( client , Slot_Melee , false );
2018-07-29 15:13:31 +02:00
2009-07-06 23:33:11 +02:00
// Give human a new knife. (If you leave the old one there will be glitches with the knife positioning)
2018-07-29 15:13:31 +02:00
GivePlayerItem ( client , " weapon_knife " );
2016-02-06 00:47:47 +01:00
2009-06-15 21:43:06 +02:00
// Check if we should respawn the client.
if ( respawn )
{
2015-03-29 18:42:04 +02:00
ZTele_TeleportClient ( client );
2009-06-15 21:43:06 +02:00
}
2016-02-06 00:47:47 +01:00
2009-06-15 21:43:06 +02:00
// Check if we should spawn protect the client.
if ( protect )
{
SpawnProtectStart ( client );
}
2016-02-06 00:47:47 +01:00
2019-09-27 16:40:58 +02:00
// Unglitch kevlar, set last hitgroup to HITGROUP_GENERIC
ToolsSetClientLastHitGroup ( client , HITGROUP_GENERIC );
2016-02-12 04:16:59 +01:00
2009-08-21 21:47:32 +02:00
// Forward event to modules.
SEffectsOnClientHuman ( client );
2010-11-14 15:17:19 +01:00
APIOnClientHumanPost ( client , respawn , protect );
2013-01-05 21:10:38 +01:00
ImmunityOnClientHuman ( client );
2016-02-17 00:48:42 +01:00
ZSpawnOnClientHuman ( client );
2017-10-06 13:49:11 +02:00
return true ;
2009-06-15 21:43:06 +02:00
}
2013-01-11 10:07:18 +01:00
/**
* Updates score for attacker and victim . Applies health gain for attacker .
*/
InfectUpdateScore ( attacker , victim )
{
// Give client's infector a point.
new score = ToolsClientScore ( attacker , true , false );
ToolsClientScore ( attacker , true , true , ++ score );
2016-02-06 00:47:47 +01:00
2013-01-11 10:07:18 +01:00
// Add a death to the zombie's score.
new deaths = ToolsClientScore ( victim , false , false );
ToolsClientScore ( victim , false , true , ++ deaths );
2016-02-06 00:47:47 +01:00
2013-01-11 10:07:18 +01:00
// Apply infect HP gain.
new healthgain = ClassGetHealthInfectGain ( attacker );
new health = GetClientHealth ( attacker );
2016-02-06 00:47:47 +01:00
2013-01-11 10:07:18 +01:00
// Set attacker's new health.
SetEntityHealth ( attacker , health + healthgain );
2016-02-06 00:47:47 +01:00
2013-01-11 10:07:18 +01:00
// Forward event to modules.
ZHPOnHealthInfectGain ( attacker );
}
2009-04-22 04:53:19 +02:00
/**
* Creates effects on a newly infected client .
2016-02-06 00:47:47 +01:00
*
2009-04-22 04:53:19 +02:00
* @ param client The client index .
*/
2009-04-24 05:02:19 +02:00
InfectFireEffects ( client )
2009-04-22 04:53:19 +02:00
{
2009-04-27 04:00:38 +02:00
// Initialize vector variables.
2009-04-22 04:53:19 +02:00
new Float : clientloc [ 3 ];
new Float : direction [ 3 ] = { 0.0 , 0.0 , 0.0 };
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// Get client's position.
GetClientAbsOrigin ( client , clientloc );
clientloc [ 2 ] += 30 ;
2016-02-06 00:47:47 +01:00
2009-06-21 22:08:02 +02:00
new bool : explosion = GetConVarBool ( g_hCvarsList [ CVAR_INFECT_EXPLOSION ]);
if ( explosion )
{
// Initialize explosion flags variable.
new flags ;
2016-02-06 00:47:47 +01:00
2009-06-21 22:08:02 +02:00
// Set "nofireball" flag if fireball is disabled.
new bool : fireball = GetConVarBool ( g_hCvarsList [ CVAR_INFECT_FIREBALL ]);
if ( ! fireball )
{
flags = flags | EXP_NOFIREBALL ;
}
2016-02-06 00:47:47 +01:00
2009-06-21 22:08:02 +02:00
// Set "nosmoke" flag if smoke is disabled.
new bool : smoke = GetConVarBool ( g_hCvarsList [ CVAR_INFECT_SMOKE ]);
if ( ! smoke )
{
flags = flags | EXP_NOSMOKE ;
}
2016-02-06 00:47:47 +01:00
2009-06-21 22:08:02 +02:00
// Set "nosparks" flag if sparks are disabled.
new bool : sparks = GetConVarBool ( g_hCvarsList [ CVAR_INFECT_SPARKS ]);
if ( ! sparks )
{
flags = flags | EXP_NOSPARKS ;
}
2016-02-06 00:47:47 +01:00
2009-06-21 22:08:02 +02:00
// Create explosion at client's origin.
VEffectsCreateExplosion ( clientloc , flags );
}
2016-02-06 00:47:47 +01:00
2010-04-05 01:36:32 +02:00
// Emit scream sound if enabled.
ZombieSoundsScream ( client );
2016-02-06 00:47:47 +01:00
2009-04-27 04:00:38 +02:00
// If energy splash effect is enabled, then continue.
2009-04-22 04:53:19 +02:00
new bool : esplash = GetConVarBool ( g_hCvarsList [ CVAR_INFECT_ESPLASH ]);
if ( esplash )
{
2009-04-27 04:00:38 +02:00
// Create energy splash effect.
VEffectsCreateEnergySplash ( clientloc , direction , true );
2009-04-22 04:53:19 +02:00
}
2016-02-06 00:47:47 +01:00
2009-04-22 04:53:19 +02:00
// If shake effect is enabled, then continue.
new bool : shake = GetConVarBool ( g_hCvarsList [ CVAR_INFECT_SHAKE ]);
if ( shake )
{
2009-04-27 04:00:38 +02:00
// Get shake info.
new Float : shakeamp = GetConVarFloat ( g_hCvarsList [ CVAR_INFECT_SHAKE_AMP ]);
new Float : shakefrequency = GetConVarFloat ( g_hCvarsList [ CVAR_INFECT_SHAKE_FREQUENCY ]);
new Float : shakeduration = GetConVarFloat ( g_hCvarsList [ CVAR_INFECT_SHAKE_DURATION ]);
2016-02-06 00:47:47 +01:00
2009-04-27 04:00:38 +02:00
// Shake client's screen.
VEffectsShakeClientScreen ( client , shakeamp , shakefrequency , shakeduration );
2009-04-22 04:53:19 +02:00
}
2009-04-24 05:02:19 +02:00
}
2009-06-25 08:57:39 +02:00
/**
* Sends list of clients to infect / human .
2016-02-06 00:47:47 +01:00
*
2009-06-25 08:57:39 +02:00
* @ param client The client index .
*/
InfectMenuClients ( client )
{
// Create menu handle.
new Handle : menu_infect_clients = CreateMenu ( InfectMenuClientsHandle );
2016-02-06 00:47:47 +01:00
2009-06-25 08:57:39 +02:00
// Set client as translation target.
SetGlobalTransTarget ( client );
2016-02-06 00:47:47 +01:00
2009-07-28 02:02:49 +02:00
decl String : title [ MENU_LINE_TITLE_LENGTH ];
2009-07-27 22:25:23 +02:00
decl String : clientoption [ MENU_LINE_REG_LENGTH ];
2009-06-25 08:57:39 +02:00
decl String : clientuserid [ 8 ];
2016-02-06 00:47:47 +01:00
2009-06-25 08:57:39 +02:00
// x = Client index.
for ( new x = 1 ; x <= MaxClients ; x ++ )
{
// If client isn't in-game, then stop.
if ( ! IsClientInGame ( x ))
{
continue ;
}
2016-02-06 00:47:47 +01:00
2009-06-25 08:57:39 +02:00
// If client isn't alive, then stop.
if ( ! IsPlayerAlive ( x ))
{
continue ;
}
2016-02-06 00:47:47 +01:00
2009-06-25 08:57:39 +02:00
// Get client info.
GetClientName ( x , clientoption , sizeof ( clientoption ));
IntToString ( GetClientUserId ( x ), clientuserid , sizeof ( clientuserid ));
2016-02-06 00:47:47 +01:00
2009-06-25 08:57:39 +02:00
// Append client's current team to the option.
if ( InfectIsClientInfected ( x ))
{
Format ( clientoption , sizeof ( clientoption ), " %s [%t] " , clientoption , " Zombie " );
}
else
{
Format ( clientoption , sizeof ( clientoption ), " %s [%t] " , clientoption , " Human " );
}
2016-02-06 00:47:47 +01:00
2009-06-25 08:57:39 +02:00
// Add option to menu.
AddMenuItem ( menu_infect_clients , clientuserid , clientoption );
}
2016-02-06 00:47:47 +01:00
2009-07-28 02:02:49 +02:00
Format ( title , sizeof ( title ), " %t \n " , " Infect menu clients title " );
SetMenuTitle ( menu_infect_clients , title );
2016-02-06 00:47:47 +01:00
2009-06-25 08:57:39 +02:00
// Create a "Back" button to the main admin menu.
SetMenuExitBackButton ( menu_infect_clients , true );
2016-02-06 00:47:47 +01:00
2009-06-25 08:57:39 +02:00
// Send menu.
DisplayMenu ( menu_infect_clients , client , MENU_TIME_FOREVER );
}
/**
* Called when client selects option in the infect clients menu , and handles it .
2009-07-27 22:25:23 +02:00
* @ param menu_infect_clients Handle of the menu being used .
2009-06-25 08:57:39 +02:00
* @ param action The action done on the menu ( see menus . inc , enum MenuAction ) .
* @ param client The client index .
* @ param slot The slot index selected ( starting from 0 ) .
2016-02-06 00:47:47 +01:00
*/
2009-06-25 08:57:39 +02:00
public InfectMenuClientsHandle ( Handle : menu_infect_clients , MenuAction : action , client , slot )
{
// Client selected an option.
if ( action == MenuAction_Select )
{
2009-06-26 02:03:34 +02:00
// Get selected client index.
new target = MenuGetClientIndex ( menu_infect_clients , slot );
2016-02-06 00:47:47 +01:00
2009-06-25 08:57:39 +02:00
// If target has left the server, then stop.
if ( ! target )
{
// Re-send menu.
InfectMenuClients ( client );
return ;
}
2016-02-06 00:47:47 +01:00
2009-06-25 08:57:39 +02:00
// Create an array with a single slot and set target to it.
new targets [ 1 ];
targets [ 0 ] = target ;
2016-02-06 00:47:47 +01:00
2009-06-25 08:57:39 +02:00
// Toggle infect on the client.
if ( InfectIsClientInfected ( target ))
{
InfectManualHuman ( client , targets , 1 );
}
else
{
InfectManualInfect ( client , targets , 1 );
}
2016-02-06 00:47:47 +01:00
2009-06-25 08:57:39 +02:00
// Re-send menu.
InfectMenuClients ( client );
}
// Client closed the menu.
if ( action == MenuAction_Cancel )
{
// Client hit "Back" button.
if ( slot == MenuCancel_ExitBack )
{
// Re-open admin menu.
2009-06-26 02:03:34 +02:00
ZAdminMenu ( client );
2009-06-25 08:57:39 +02:00
}
}
// Client hit "Exit" button.
else if ( action == MenuAction_End )
{
CloseHandle ( menu_infect_clients );
}
}
2015-03-22 18:06:40 +01:00
bool : InfectHasZombieSpawned ()
{
return g_bZombieSpawned ;
}
2009-04-24 05:02:19 +02:00
/**
* Returns if a client is infected .
2016-02-06 00:47:47 +01:00
*
2009-04-24 05:02:19 +02:00
* @ param client The client index .
* @ return True if the client has been infected , false otherwise .
2016-02-06 00:47:47 +01:00
*/
2009-04-24 05:02:19 +02:00
bool : InfectIsClientInfected ( client )
{
// If client is invalid, then stop.
if ( ! ZRIsClientValid ( client ))
{
return false ;
}
2016-02-06 00:47:47 +01:00
2009-04-24 05:02:19 +02:00
// Return client's zombie flag.
2017-01-22 15:09:22 +01:00
return g_bZombie [ client ];
2009-04-24 05:02:19 +02:00
}
/**
* Returns if a client is a human .
2016-02-06 00:47:47 +01:00
*
2009-04-24 05:02:19 +02:00
* @ param client The client index .
* @ return True if the client is a human , false otherwise .
*/
bool : InfectIsClientHuman ( client )
{
// If client is invalid, then stop.
if ( ! ZRIsClientValid ( client ))
{
return true ;
}
2016-02-06 00:47:47 +01:00
2009-04-24 05:02:19 +02:00
// Return opposite of client's zombie flag.
2017-01-22 15:09:22 +01:00
return ! g_bZombie [ client ];
2009-05-01 11:22:45 +02:00
}
2009-06-15 21:43:06 +02:00
/**
2009-06-25 08:57:39 +02:00
* Infecting a client manually ( via zr_infect or the " Zombie Management " menu )
2016-02-06 00:47:47 +01:00
*
2009-06-25 08:57:39 +02:00
* @ param client The client index infecting another client .
* @ param targets Array containing all clients to infect .
* @ param count The number of clients in the array .
* @ param respawnoverride ( Optional ) True to override respawn cvar .
* @ param respawn ( Optional ) True to respawn client on infect .
2009-06-15 21:43:06 +02:00
*/
2009-06-25 08:57:39 +02:00
stock InfectManualInfect ( client , targets [], count , bool : respawnoverride = false , bool : respawn = false )
2009-06-15 21:43:06 +02:00
{
2015-03-22 18:06:40 +01:00
new bool : zombiespawned = InfectHasZombieSpawned ();
2016-02-06 00:47:47 +01:00
2009-06-19 00:53:22 +02:00
// If zombie hasn't spawned, then make targetted player(s) mother zombies.
if ( ! zombiespawned )
2009-06-15 21:43:06 +02:00
{
2009-06-19 00:53:22 +02:00
// Stop mother infect timer.
2017-01-22 15:09:22 +01:00
if ( g_tInfect != INVALID_HANDLE )
2009-06-19 00:53:22 +02:00
{
2017-01-22 15:09:22 +01:00
KillTimer ( g_tInfect );
g_tInfect = INVALID_HANDLE ;
2009-06-19 00:53:22 +02:00
}
2016-02-06 00:47:47 +01:00
2009-06-19 00:53:22 +02:00
// Move all clients to CT
for ( new x = 1 ; x <= MaxClients ; x ++ )
{
// If client isn't in-game, then stop.
if ( ! IsClientInGame ( x ))
{
continue ;
}
2016-02-06 00:47:47 +01:00
2009-06-19 00:53:22 +02:00
// If client is dead, then stop.
if ( ! IsPlayerAlive ( x ))
{
continue ;
}
2016-02-06 00:47:47 +01:00
2009-06-19 00:53:22 +02:00
// Switch client to CT team.
CS_SwitchTeam ( x , CS_TEAM_CT );
}
2016-02-06 00:47:47 +01:00
2009-06-19 00:53:22 +02:00
// Tell the plugin a mother zombie has spawned.
g_bZombieSpawned = true ;
}
2016-02-06 00:47:47 +01:00
2009-06-25 08:57:39 +02:00
decl String : targetname [ MAX_NAME_LENGTH ];
2016-04-22 01:24:10 +02:00
decl String : adminname [ MAX_NAME_LENGTH ];
// Get admin's name for later use.
if ( client > 0 )
GetClientName ( client , adminname , sizeof ( adminname ));
else
strcopy ( adminname , sizeof ( adminname ), " Console " );
2016-02-06 00:47:47 +01:00
2017-05-01 23:59:38 +02:00
new bool : success = false ;
2009-06-19 00:53:22 +02:00
// x = Client index.
2009-06-25 08:57:39 +02:00
for ( new x = 0 ; x < count ; x ++ )
2009-06-19 00:53:22 +02:00
{
2009-06-25 08:57:39 +02:00
// Get client's name for later use.
GetClientName ( targets [ x ], targetname , sizeof ( targetname ));
2016-02-06 00:47:47 +01:00
2009-06-19 00:53:22 +02:00
// Check if client is a human before turning into zombie.
if ( ! InfectIsClientHuman ( targets [ x ]))
{
continue ;
}
2016-02-06 00:47:47 +01:00
2009-06-19 00:53:22 +02:00
// If zombie hasn't spawned, then make targetted player(s) mother zombies.
if ( ! zombiespawned )
{
// Turn client into a mother zombie.
InfectHumanToZombie ( targets [ x ], _ , true , respawnoverride , respawn );
2016-02-06 00:47:47 +01:00
2017-05-01 23:59:38 +02:00
// Log action to game events.
LogEvent ( false , LogType_Normal , LOG_GAME_EVENTS , LogModule_Infect , " Manual Infect " , " \" %L \" turned \" %L \" into a mother zombie " , client , targets [ x ]);
2016-02-06 00:47:47 +01:00
2017-05-01 23:59:38 +02:00
success = true ;
2009-06-19 00:53:22 +02:00
continue ;
}
2016-02-06 00:47:47 +01:00
2009-06-15 21:43:06 +02:00
// Turn client into a zombie.
2009-06-19 00:53:22 +02:00
InfectHumanToZombie ( targets [ x ], _ , false , respawnoverride , respawn );
2016-02-06 00:47:47 +01:00
2017-05-01 23:59:38 +02:00
// Log action to game events.
LogEvent ( false , LogType_Normal , LOG_GAME_EVENTS , LogModule_Infect , " Manual Infect " , " \" %L \" turned \" %L \" into a zombie " , client , targets [ x ]);
success = true ;
}
// Tell admin the outcome of the command.
if ( success )
{
if ( ! zombiespawned )
{
TranslationReplyToCommand ( client , " Infect command infect mother successful " , targetname );
TranslationPrintToChatAllExcept ( false , false , client , " Infect command infect mother successful public " , adminname , targetname );
}
else
2009-06-19 00:53:22 +02:00
{
TranslationReplyToCommand ( client , " Infect command infect successful " , targetname );
2017-05-01 23:59:38 +02:00
TranslationPrintToChatAllExcept ( false , false , client , " Infect command infect successful public " , adminname , targetname );
2009-06-19 00:53:22 +02:00
}
2009-06-15 21:43:06 +02:00
}
2017-05-01 23:59:38 +02:00
else
{
// Tell admin command was unsuccessful.
TranslationReplyToCommand ( client , " Infect command infect unsuccessful " , targetname );
}
2009-06-25 08:57:39 +02:00
}
/**
* Infecting a client manually ( via zr_human or the " Zombie Management " menu )
2016-02-06 00:47:47 +01:00
*
2009-06-25 08:57:39 +02:00
* @ param client The client index changing a zombie to human .
* @ param targets Array containing all clients to make human .
* @ param count The number of clients in the array .
* @ param respawn ( Optional ) True to respawn client upon changing to human .
* @ param protect ( Optional ) True to protect client upon changing to human .
*/
stock InfectManualHuman ( client , targets [], count , bool : respawn = false , bool : protect = false )
{
decl String : targetname [ MAX_NAME_LENGTH ];
2016-04-22 01:24:10 +02:00
decl String : adminname [ MAX_NAME_LENGTH ];
// Get admin's name for later use.
if ( client > 0 )
GetClientName ( client , adminname , sizeof ( adminname ));
else
strcopy ( adminname , sizeof ( adminname ), " Console " );
2016-02-06 00:47:47 +01:00
2017-05-01 23:59:38 +02:00
new bool : success = false ;
2009-06-25 08:57:39 +02:00
// x = Client index.
for ( new x = 0 ; x < count ; x ++ )
{
// Get client's name for later use.
GetClientName ( targets [ x ], targetname , sizeof ( targetname ));
2016-02-06 00:47:47 +01:00
2009-06-25 08:57:39 +02:00
// Check if client is a human before turning into zombie.
if ( InfectIsClientInfected ( targets [ x ]))
{
// Turn client into a zombie.
InfectZombieToHuman ( targets [ x ], respawn , protect );
2016-02-06 00:47:47 +01:00
2017-05-01 23:59:38 +02:00
// Log action to game events.
LogEvent ( false , LogType_Normal , LOG_GAME_EVENTS , LogModule_Infect , " Manual Human " , " \" %L \" turned \" %L \" into a human " , client , targets [ x ]);
success = true ;
2009-06-25 08:57:39 +02:00
}
}
2017-05-01 23:59:38 +02:00
// Tell admin the outcome of the command.
if ( success )
{
TranslationReplyToCommand ( client , " Infect command human successful " , targetname );
TranslationPrintToChatAllExcept ( false , false , client , " Infect command human successful public " , adminname , targetname );
}
else
{
TranslationReplyToCommand ( client , " Infect command human unsuccessful " , targetname );
}
2009-06-25 08:57:39 +02:00
}
/**
* Command callback ( zr_infect )
* Infects a client .
2016-02-06 00:47:47 +01:00
*
2009-06-25 08:57:39 +02:00
* @ param client The client index .
* @ param argc Argument count .
*/
public Action : InfectInfectCommand ( client , argc )
{
2009-10-26 23:17:22 +01:00
// Check if privileged.
if ( ! ZRIsClientPrivileged ( client , OperationType_Generic ))
{
TranslationReplyToCommand ( client , " No access to command " );
return Plugin_Handled ;
}
2016-02-06 00:47:47 +01:00
2009-06-25 08:57:39 +02:00
// If not enough arguments given, then stop.
if ( argc < 1 )
{
TranslationReplyToCommand ( client , " Infect command infect syntax " );
return Plugin_Handled ;
}
2016-02-06 00:47:47 +01:00
2009-06-25 08:57:39 +02:00
decl String : target [ MAX_NAME_LENGTH ], String : targetname [ MAX_NAME_LENGTH ];
new targets [ MAXPLAYERS ], bool : tn_is_ml , result ;
2016-02-06 00:47:47 +01:00
2009-06-25 08:57:39 +02:00
// Get targetname.
GetCmdArg ( 1 , target , sizeof ( target ));
2016-02-06 00:47:47 +01:00
2009-06-25 08:57:39 +02:00
// Find a target.
result = ProcessTargetString ( target , client , targets , sizeof ( targets ), COMMAND_FILTER_ALIVE , targetname , sizeof ( targetname ), tn_is_ml );
2016-02-06 00:47:47 +01:00
2009-06-25 08:57:39 +02:00
// Check if there was a problem finding a client.
if ( result <= 0 )
{
ZRReplyToTargetError ( client , result );
return Plugin_Handled ;
}
2016-02-06 00:47:47 +01:00
2009-06-25 08:57:39 +02:00
// Get respawn parameter.
decl String : strRespawn [ 8 ];
GetCmdArg ( 2 , strRespawn , sizeof ( strRespawn ));
2016-02-06 00:47:47 +01:00
2009-06-25 08:57:39 +02:00
new bool : respawnoverride , bool : respawn ;
2016-02-06 00:47:47 +01:00
2009-06-25 08:57:39 +02:00
// If parameter exists then cast it into a bool and feed it to infect function.
if ( strRespawn [ 0 ])
{
respawnoverride = true ;
respawn = bool : StringToInt ( strRespawn );
}
2016-02-06 00:47:47 +01:00
2009-06-25 08:57:39 +02:00
// Infect player.
InfectManualInfect ( client , targets , result , respawnoverride , respawn );
2016-02-06 00:47:47 +01:00
2009-06-15 21:43:06 +02:00
return Plugin_Handled ;
}
/**
* Command callback ( zr_human )
* Turns a client into a human .
2016-02-06 00:47:47 +01:00
*
2009-06-15 21:43:06 +02:00
* @ param client The client index .
* @ param argc Argument count .
*/
public Action : InfectHumanCommand ( client , argc )
{
2009-10-26 23:17:22 +01:00
// Check if privileged.
if ( ! ZRIsClientPrivileged ( client , OperationType_Generic ))
{
TranslationReplyToCommand ( client , " No access to command " );
return Plugin_Handled ;
}
2016-02-06 00:47:47 +01:00
2009-06-15 21:43:06 +02:00
// If not enough arguments given, then stop.
if ( argc < 1 )
{
TranslationReplyToCommand ( client , " Infect command human syntax " );
return Plugin_Handled ;
}
2016-02-06 00:47:47 +01:00
2009-06-15 21:43:06 +02:00
decl String : target [ MAX_NAME_LENGTH ], String : targetname [ MAX_NAME_LENGTH ];
new targets [ MAXPLAYERS ], bool : tn_is_ml , result ;
2016-02-06 00:47:47 +01:00
2009-06-15 21:43:06 +02:00
// Get targetname.
GetCmdArg ( 1 , target , sizeof ( target ));
2016-02-06 00:47:47 +01:00
2009-06-15 21:43:06 +02:00
// Find a target.
2009-06-19 00:53:22 +02:00
result = ProcessTargetString ( target , client , targets , sizeof ( targets ), COMMAND_FILTER_ALIVE , targetname , sizeof ( targetname ), tn_is_ml );
2016-02-06 00:47:47 +01:00
2009-06-15 21:43:06 +02:00
// Check if there was a problem finding a client.
if ( result <= 0 )
{
ZRReplyToTargetError ( client , result );
return Plugin_Handled ;
}
2016-02-06 00:47:47 +01:00
2009-06-25 08:57:39 +02:00
// Get respawn&protect parameters
decl String : strRespawn [ 8 ], String : strProtect [ 8 ];
GetCmdArg ( 2 , strRespawn , sizeof ( strRespawn ));
GetCmdArg ( 3 , strProtect , sizeof ( strProtect ));
2016-02-06 00:47:47 +01:00
2009-06-25 08:57:39 +02:00
// If parameter exists then cast it into a bool and feed it to "humanize" function.
new bool : respawn = ( strRespawn [ 0 ]) ? ( bool : StringToInt ( strRespawn )) : false ;
new bool : protect = ( strProtect [ 0 ]) ? ( bool : StringToInt ( strProtect )) : false ;
2016-02-06 00:47:47 +01:00
2009-06-25 08:57:39 +02:00
// Turn client into human.
InfectManualHuman ( client , targets , result , respawn , protect );
2016-02-06 00:47:47 +01:00
2009-06-15 21:43:06 +02:00
return Plugin_Handled ;
2009-08-27 21:56:29 +02:00
}
2013-01-10 06:21:30 +01:00
/**
* 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 ;
}
2016-02-06 00:47:47 +01:00
2013-01-10 06:21:30 +01:00
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 ;
}
2016-02-06 00:47:47 +01:00
2013-01-10 06:21:30 +01:00
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 ));
2016-02-06 00:47:47 +01:00
2013-01-10 06:21:30 +01:00
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 ]);
2016-02-06 00:47:47 +01:00
2013-01-10 06:21:30 +01:00
// 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 ;
}
2016-02-06 00:47:47 +01:00
2013-01-10 06:21:30 +01:00
if ( failed )
{
return InfectMode_Invalid ;
}
}
}
2016-02-06 00:47:47 +01:00
2013-01-10 06:21:30 +01:00
return mode ;
}