2009-04-11 01:56:22 +02:00
/*
* ============================================================================
*
2009-07-05 08:49:23 +02:00
* Zombie : Reloaded
2009-04-11 01:56:22 +02:00
*
2009-06-12 05:51:26 +02:00
* File : classevents . inc
* Type : Core
* Description : Functions for handling class related events .
2009-04-11 01:56:22 +02:00
*
2013-01-12 08:47:36 +01:00
* Copyright ( C ) 2009 - 2013 Greyscale , Richard Helgeby
*
* 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-11 01:56:22 +02:00
* ============================================================================
*/
2010-02-20 02:41:24 +01:00
/**
* Keeps track of if a client has been authorized as an admin .
*/
new bool : g_bAdminChecked [ MAXPLAYERS + 1 ];
2009-04-11 01:56:22 +02:00
/* ------------------------------------
*
* GAME EVENTS
*
* ------------------------------------
*/
2009-06-21 21:24:24 +02:00
/**
* Create class - related cookies here .
*/
ClassOnCookiesCreate ()
{
// Forward event to sub-modules.
ClassOverlayOnCookiesCreate ();
2016-02-06 00:47:47 +01:00
2009-10-10 18:26:27 +02:00
// Create cookie handles only if they don't exist.
if ( g_hClassCookieClassSelected [ ZR_CLASS_TEAM_HUMANS ] == INVALID_HANDLE )
2009-10-08 19:47:23 +02:00
{
2009-10-10 18:26:27 +02:00
g_hClassCookieClassSelected [ ZR_CLASS_TEAM_HUMANS ] = RegClientCookie ( " zr_humanclass " , " The last human class selected. " , CookieAccess_Protected );
2009-10-08 19:47:23 +02:00
}
2009-10-10 18:26:27 +02:00
if ( g_hClassCookieClassSelected [ ZR_CLASS_TEAM_ZOMBIES ] == INVALID_HANDLE )
2009-10-08 19:47:23 +02:00
{
2009-10-10 18:26:27 +02:00
g_hClassCookieClassSelected [ ZR_CLASS_TEAM_ZOMBIES ] = RegClientCookie ( " zr_zombieclass " , " The last zombie class selected. " , CookieAccess_Protected );
2009-10-08 19:47:23 +02:00
}
2009-10-10 18:26:27 +02:00
if ( g_hClassCookieClassSelected [ ZR_CLASS_TEAM_ADMINS ] == INVALID_HANDLE )
2009-10-08 19:47:23 +02:00
{
2009-10-10 18:26:27 +02:00
g_hClassCookieClassSelected [ ZR_CLASS_TEAM_ADMINS ] = RegClientCookie ( " zr_adminclass " , " The last admin mode class selected. " , CookieAccess_Protected );
2009-10-08 19:47:23 +02:00
}
2009-06-21 21:24:24 +02:00
}
/**
* Called when all modules are done loading .
*/
ClassOnModulesLoaded ()
{
// Set default classes on all player slots.
ClassClientSetDefaultIndexes ();
}
2009-11-11 22:50:19 +01:00
/**
* Called when map is loading , before configs are loaded . Used for
* initializing class module .
*/
ClassOnMapStart ()
{
2018-07-30 21:53:45 +02:00
// Clear multipliers.
ClassResetMultiplierCache ();
2016-02-06 00:47:47 +01:00
2018-07-30 21:53:45 +02:00
// Prepare hp regeneration module.
ClassHealthRegenInit ();
2009-11-11 22:50:19 +01:00
}
2010-07-04 17:58:27 +02:00
/**
* Called when all configs are executed .
*/
ClassOnConfigsExecuted ()
{
new ClassSpeedMethods : speedMethod = ClassGetSpeedMethod ();
2016-02-06 00:47:47 +01:00
2010-07-04 17:58:27 +02:00
if ( speedMethod != ClassSpeed_Invalid )
{
// Set speed method.
ClassSpeedMethod = speedMethod ;
}
else
{
// Fall back on default to avoid errors.
ClassSpeedMethod = ClassSpeed_Prop ;
LogEvent ( false , LogType_Error , LOG_CORE_EVENTS , LogModules : LogModule_Playerclasses , " Config validation " , " Warning: Invalid value in zr_classes_speed_method. Using default value. " );
}
}
2010-02-20 02:41:24 +01:00
/**
* Client has just connected to the server .
*/
ClassOnClientConnected ( client )
{
2010-07-04 17:58:27 +02:00
// Unhook "PreThinkPost" on the client.
SDKUnhook ( client , SDKHook_PreThinkPost , ClassPreThinkPost );
2016-02-06 00:47:47 +01:00
2010-02-20 02:41:24 +01:00
// Initialize the admin checked variable.
g_bAdminChecked [ client ] = false ;
}
2009-04-11 01:56:22 +02:00
/**
2009-06-18 03:33:09 +02:00
* Called when a client connects to the server ( OnClientPutInServer ) .
2009-04-11 01:56:22 +02:00
*/
ClassClientInit ( client )
{
2010-07-04 17:58:27 +02:00
// Hook "PreThinkPost" on the client.
SDKHook ( client , SDKHook_PreThinkPost , ClassPreThinkPost );
2016-02-06 00:47:47 +01:00
2009-11-20 18:20:45 +01:00
// Reset spawn flag.
ClassPlayerSpawned [ client ] = false ;
2009-05-14 02:28:26 +02:00
}
2010-02-04 23:53:58 +01:00
/**
2016-02-06 00:47:47 +01:00
* Called once a client is authorized and fully in - game , and
* after all post - connection authorizations have been performed .
2010-02-04 23:53:58 +01:00
*
2016-02-06 00:47:47 +01:00
* This callback is gauranteed to occur on all clients , and always
2010-02-20 02:41:24 +01:00
* after each OnClientPutInServer () call .
*
2018-07-30 21:53:45 +02:00
* @ param client Client index .
2010-02-20 02:41:24 +01:00
* @ noreturn
*/
ClassOnClientPostAdminCheck ( client )
{
// Client has been checked.
g_bAdminChecked [ client ] = true ;
2016-02-06 00:47:47 +01:00
2010-02-20 02:41:24 +01:00
// Below this depends on client cookies.
if ( ! AreClientCookiesCached ( client ))
return ;
2016-02-06 00:47:47 +01:00
2010-02-20 02:41:24 +01:00
// Check if classes are loaded successfully and the client is valid.
if ( ClassValidated )
{
// Set default class indexes on the player.
ClassClientSetDefaultIndexes ( client );
}
}
/**
* Called once a client ' s saved cookies have been loaded from the database .
2016-02-06 00:47:47 +01:00
*
2018-07-30 21:53:45 +02:00
* @ param client Client index .
2010-02-04 23:53:58 +01:00
*/
2010-02-20 02:41:24 +01:00
ClassOnCookiesCached ( client )
2010-02-04 23:53:58 +01:00
{
2010-02-20 02:41:24 +01:00
// Check if classes are loaded successfully.
if ( ClassValidated )
{
// Forward event to sub-modules.
ClassOverlayOnCookiesCached ( client );
}
2016-02-06 00:47:47 +01:00
2010-02-20 02:41:24 +01:00
// Below this depends on client authorization.
if ( ! g_bAdminChecked [ client ])
return ;
2016-02-06 00:47:47 +01:00
2010-02-04 23:53:58 +01:00
// Check if classes are loaded successfully and the client is valid.
2010-02-20 02:41:24 +01:00
if ( ClassValidated )
2010-02-04 23:53:58 +01:00
{
// Set default class indexes on the player.
ClassClientSetDefaultIndexes ( client );
}
}
2009-06-18 03:33:09 +02:00
/**
* Called a client disconnects .
*/
2009-04-11 01:56:22 +02:00
ClassOnClientDisconnect ( client )
{
2009-05-10 18:49:47 +02:00
// Disable class attributes with timers.
ClassHealthRegenStop ( client );
2016-02-06 00:47:47 +01:00
2009-07-22 14:06:18 +02:00
// Reset previously selected class indexes.
2009-07-23 23:26:14 +02:00
ClassResetNextIndexes ( client );
2009-04-11 01:56:22 +02:00
}
2009-05-14 02:28:26 +02:00
/**
* Client is spawning into the game .
2016-02-06 00:47:47 +01:00
*
2009-05-14 02:28:26 +02:00
* @ param client The client index .
*/
2009-04-11 01:56:22 +02:00
ClassOnClientSpawn ( client )
{
2009-06-22 17:01:26 +02:00
decl String : originalmodel [ PLATFORM_MAX_PATH ];
decl String : classname [ 64 ];
2009-08-14 22:10:52 +02:00
new filter [ ClassFilter ];
2016-02-06 00:47:47 +01:00
2009-07-23 23:26:14 +02:00
// Check if the player is dead. Spawning into the game is also a event in
// the connection process.
2009-04-29 02:50:25 +02:00
if ( ! IsPlayerAlive ( client ))
{
2009-05-10 18:49:47 +02:00
return ;
}
2016-02-06 00:47:47 +01:00
2009-07-22 14:06:18 +02:00
// Check if there are no valid classes. Block this event if classes aren't
2009-05-10 18:49:47 +02:00
// done loading.
if ( ! ClassValidated )
{
2009-04-29 02:50:25 +02:00
return ;
}
2016-02-06 00:47:47 +01:00
2009-06-18 02:09:55 +02:00
// Reset attributes by triggering death event.
ClassOnClientDeath ( client );
2016-02-06 00:47:47 +01:00
2009-07-23 23:26:14 +02:00
// Restore class indexes to be selected on spawn, if available.
ClassRestoreNextIndexes ( client );
2016-02-06 00:47:47 +01:00
2009-06-22 17:01:26 +02:00
// Cache original player model.
GetClientModel ( client , originalmodel , sizeof ( originalmodel ));
strcopy ( ClassOriginalPlayerModel [ client ], PLATFORM_MAX_PATH , originalmodel );
2016-02-06 00:47:47 +01:00
2009-04-29 02:50:25 +02:00
// Check if the player should spawn in admin mode.
2009-07-23 23:26:14 +02:00
if ( ClassPlayerInAdminMode [ client ])
2009-04-11 01:56:22 +02:00
{
2009-04-29 02:50:25 +02:00
// Mark player as in admin mode.
ClassPlayerInAdminMode [ client ] = true ;
2016-02-06 00:47:47 +01:00
2009-07-23 23:26:14 +02:00
// TODO: This is the place to initialize admin mode stuff like no-block
// and other stuff.
2009-04-29 02:50:25 +02:00
}
else
{
// Mark player as not in admin mode.
ClassPlayerInAdminMode [ client ] = false ;
2016-02-06 00:47:47 +01:00
2015-03-21 15:45:29 +01:00
// Get random class setting.
2009-07-23 23:26:14 +02:00
new bool : randomclass = GetConVarBool ( g_hCvarsList [ CVAR_CLASSES_RANDOM ]);
2016-02-06 00:47:47 +01:00
2009-07-23 23:26:14 +02:00
// Assign random classes if enabled. Always do it for bots.
2015-03-21 15:45:29 +01:00
if ( randomclass || IsFakeClient ( client ))
2009-07-23 23:26:14 +02:00
{
2009-08-14 22:10:52 +02:00
// Setup filtering
// ---------------
2016-02-06 00:47:47 +01:00
2009-08-14 22:10:52 +02:00
// Exclude special class flags like mother zombies and admin classes.
filter [ ClassFilter_DenyFlags ] = ZR_CLASS_SPECIALFLAGS ;
2016-02-06 00:47:47 +01:00
2009-07-23 23:26:14 +02:00
// Allow admin classes if admin.
2009-08-14 22:10:52 +02:00
filter [ ClassFilter_DenyFlags ] -= ZRIsClientAdmin ( client ) ? ZR_CLASS_FLAG_ADMIN_ONLY : 0 ;
2016-02-06 00:47:47 +01:00
2009-08-14 22:10:52 +02:00
// Specify client for checking group permissions.
filter [ ClassFilter_Client ] = client ;
2016-02-06 00:47:47 +01:00
2009-08-14 22:10:52 +02:00
// Get classes
// -----------
2016-02-06 00:47:47 +01:00
2009-07-23 23:26:14 +02:00
// Get random classes for each type.
2009-08-14 22:10:52 +02:00
new randomzombie = ClassGetRandomClass ( ZR_CLASS_TEAM_ZOMBIES , filter );
new randomhuman = ClassGetRandomClass ( ZR_CLASS_TEAM_HUMANS , filter );
2016-02-06 00:47:47 +01:00
2009-07-23 23:26:14 +02:00
// Set selected zombie class index.
ClassSelected [ client ][ ZR_CLASS_TEAM_ZOMBIES ] = randomzombie ;
ClassGetName ( randomzombie , classname , sizeof ( classname ), ZR_CLASS_TEAM_ZOMBIES );
TranslationPrintToChat ( client , " Classes random assignment " , classname );
2016-02-06 00:47:47 +01:00
2009-07-23 23:26:14 +02:00
// Set selected human class index.
ClassSelected [ client ][ ZR_CLASS_TEAM_HUMANS ] = randomhuman ;
ClassGetName ( randomhuman , classname , sizeof ( classname ), ZR_CLASS_TEAM_HUMANS );
TranslationPrintToChat ( client , " Classes random assignment " , classname );
}
2016-02-06 00:47:47 +01:00
2009-11-20 18:20:45 +01:00
// Display class menu if either menu cvar is set.
new bool : menuspawn = GetConVarBool ( g_hCvarsList [ CVAR_CLASSES_MENU_SPAWN ]);
new bool : menujoin = GetConVarBool ( g_hCvarsList [ CVAR_CLASSES_MENU_JOIN ]);
if ( menuspawn || ( menujoin && ! ClassPlayerSpawned [ client ]))
2009-08-10 19:01:43 +02:00
{
2009-11-20 18:20:45 +01:00
ClassPlayerSpawned [ client ] = true ;
2009-08-10 19:01:43 +02:00
ClassMenuMain ( client );
}
2009-04-11 01:56:22 +02:00
}
2016-02-06 00:47:47 +01:00
2010-04-05 00:54:21 +02:00
// Load class attributes for the active class.
2009-07-23 23:26:14 +02:00
ClassReloadPlayerCache ( client , ClassGetActiveIndex ( client ));
2016-02-06 00:47:47 +01:00
2010-04-05 00:54:21 +02:00
// Note: Class attributes are applied in ClassOnClientSpawnPost.
2016-02-06 00:47:47 +01:00
2009-08-10 19:01:43 +02:00
// Check if instant class change cvar is set.
new Float : instantspawn = GetConVarFloat ( g_hCvarsList [ CVAR_CLASSES_CHANGE_TIMELIMIT ]);
if ( instantspawn > 0 )
{
// Allow instant class change.
ClassAllowInstantChange [ client ] = true ;
2016-02-06 00:47:47 +01:00
2009-08-10 19:01:43 +02:00
// Create timer to disable instant change.
CreateTimer ( instantspawn , Event_ClassDisableInstantSpawn , client , TIMER_FLAG_NO_MAPCHANGE );
}
else
{
// Make sure instant change is not allowed.
ClassAllowInstantChange [ client ] = false ;
}
2009-04-11 01:56:22 +02:00
}
2010-04-05 00:54:21 +02:00
/**
* Client have just spawned ( delayed event ) .
2016-02-06 00:47:47 +01:00
*
2010-04-05 00:54:21 +02:00
* @ param client The client index .
*/
ClassOnClientSpawnPost ( client )
{
// Check if there are no valid classes. Block this event if classes aren't
// done loading.
if ( ! ClassValidated )
{
return ;
}
2016-02-06 00:47:47 +01:00
2010-04-05 00:54:21 +02:00
ClassApplyAttributes ( client );
}
2009-06-18 03:33:09 +02:00
/**
* Client died . Stops timers and reset certain attributes . Call this event to
* clean up class related stuff .
2016-02-06 00:47:47 +01:00
*
2009-06-18 03:33:09 +02:00
* @ param client The client index .
*/
2009-04-11 01:56:22 +02:00
ClassOnClientDeath ( client )
{
2009-05-10 18:49:47 +02:00
// Disable class attributes with timers.
2009-04-11 01:56:22 +02:00
ClassHealthRegenStop ( client );
2016-02-06 00:47:47 +01:00
2009-04-29 02:50:25 +02:00
// Set client's FOV back to normal.
ToolsSetClientDefaultFOV ( client , 90 );
2016-02-06 00:47:47 +01:00
2009-05-21 07:13:51 +02:00
// Forward event to sub-modules.
ClassOverlayOnClientDeath ( client );
2009-04-11 01:56:22 +02:00
}
2009-06-18 03:33:09 +02:00
/**
* Client got infected . Reloads class attributes .
2016-02-06 00:47:47 +01:00
*
2009-06-18 03:33:09 +02:00
* @ param client The client index .
*/
2009-04-11 01:56:22 +02:00
ClassOnClientInfected ( client , bool : motherzombie = false )
{
new classindex = ClassGetActiveIndex ( client );
2009-06-22 01:09:51 +02:00
new isadmin ;
new motherindex ;
2009-08-14 22:10:52 +02:00
new filter [ ClassFilter ];
2016-02-06 00:47:47 +01:00
2009-06-22 01:09:51 +02:00
decl String : motherzombiesetting [ 64 ];
2016-02-06 00:47:47 +01:00
2009-05-10 18:49:47 +02:00
// Disable class attributes with timers.
ClassHealthRegenStop ( client );
2016-02-06 00:47:47 +01:00
2009-08-10 19:01:43 +02:00
// Make sure the player is not allowed to instantly change class.
ClassAllowInstantChange [ client ] = false ;
2016-02-06 00:47:47 +01:00
2009-06-22 01:09:51 +02:00
// Check if it's a mother zombie.
if ( motherzombie )
{
2009-06-22 16:29:13 +02:00
// Set admin flag if client is admin, so it's removed in special class
// flags.
isadmin = ZRIsClientAdmin ( client ) ? ZR_CLASS_FLAG_ADMIN_ONLY : 0 ;
2016-02-06 00:47:47 +01:00
2009-06-22 01:09:51 +02:00
// Get default mother zombie setting.
GetConVarString ( g_hCvarsList [ CVAR_CLASSES_DEFAULT_M_ZOMB ], motherzombiesetting , sizeof ( motherzombiesetting ));
2016-02-06 00:47:47 +01:00
2009-06-22 01:09:51 +02:00
if ( StrEqual ( motherzombiesetting , " disabled " , false ))
{
// Do nothing. Keep current class.
}
else if ( StrEqual ( motherzombiesetting , " random " , false ))
{
2009-08-14 22:10:52 +02:00
// Setup filtering
// ---------------
2016-02-06 00:47:47 +01:00
2009-08-14 22:10:52 +02:00
// Exclude special class flags.
filter [ ClassFilter_DenyFlags ] = ZR_CLASS_SPECIALFLAGS ;
2016-02-06 00:47:47 +01:00
2009-08-14 22:10:52 +02:00
// Allow admin classes if admin.
filter [ ClassFilter_DenyFlags ] -= isadmin ;
2016-02-06 00:47:47 +01:00
2009-08-14 22:10:52 +02:00
// Specify client for checking group permissions.
filter [ ClassFilter_Client ] = client ;
2016-02-06 00:47:47 +01:00
2009-08-14 22:10:52 +02:00
// Get class
// ---------
2016-02-06 00:47:47 +01:00
2009-06-22 01:09:51 +02:00
// Get random regular zombie class. Remove admin flag if admin.
2009-08-14 22:10:52 +02:00
motherindex = ClassGetRandomClass ( ZR_CLASS_TEAM_ZOMBIES , filter );
2016-02-06 00:47:47 +01:00
2009-07-08 02:16:29 +02:00
// Validate index. Do not change class if it's invalid.
if ( ClassValidateIndex ( motherindex ))
2009-07-23 23:26:14 +02:00
{
// Save active class index to be restored next spawn.
ClassSelectedNext [ client ][ ZR_CLASS_TEAM_ZOMBIES ] = classindex ;
2016-02-06 00:47:47 +01:00
2009-07-08 02:16:29 +02:00
// Change class.
classindex = motherindex ;
}
2009-06-22 01:09:51 +02:00
}
else if ( StrEqual ( motherzombiesetting , " motherzombies " , false ))
{
2009-08-14 22:10:52 +02:00
// Setup filtering
// ---------------
2016-02-06 00:47:47 +01:00
2009-08-14 22:10:52 +02:00
// Exclude special class flags except mother zombies.
filter [ ClassFilter_DenyFlags ] = ZR_CLASS_SPECIALFLAGS - ZR_CLASS_FLAG_MOTHER_ZOMBIE ;
2016-02-06 00:47:47 +01:00
2009-08-14 22:10:52 +02:00
// Require mother zombie class flag.
filter [ ClassFilter_RequireFlags ] = ZR_CLASS_FLAG_MOTHER_ZOMBIE ;
2016-02-06 00:47:47 +01:00
2009-08-14 22:10:52 +02:00
// Allow admin classes if admin.
filter [ ClassFilter_DenyFlags ] -= isadmin ;
2016-02-06 00:47:47 +01:00
2009-08-14 22:10:52 +02:00
// Specify client for checking group permissions.
filter [ ClassFilter_Client ] = client ;
2016-02-06 00:47:47 +01:00
2009-08-14 22:10:52 +02:00
// Get class
// ---------
2016-02-06 00:47:47 +01:00
2009-07-08 02:16:29 +02:00
// Get random mother zombie class. Include admin classes if admin.
2009-08-14 22:10:52 +02:00
motherindex = ClassGetRandomClass ( ZR_CLASS_TEAM_ZOMBIES , filter );
2016-02-06 00:47:47 +01:00
2009-07-08 02:16:29 +02:00
// Validate index. Do not change class if it's invalid.
if ( ClassValidateIndex ( motherindex ))
{
2009-07-23 23:26:14 +02:00
// This is a mother zombie class. Reset mother zombie setting
// so class skills aren't improved.
2009-07-08 02:16:29 +02:00
motherzombie = false ;
2016-02-06 00:47:47 +01:00
2009-07-23 23:26:14 +02:00
// Save active class index to be restored next spawn.
ClassSelectedNext [ client ][ ZR_CLASS_TEAM_ZOMBIES ] = classindex ;
2016-02-06 00:47:47 +01:00
2009-07-08 02:16:29 +02:00
// Change class.
classindex = motherindex ;
}
2009-06-22 01:09:51 +02:00
}
else
{
// Assume it's a class name. Get index for the specified class name.
motherindex = ClassGetIndex ( motherzombiesetting );
2016-02-06 00:47:47 +01:00
2009-06-22 01:09:51 +02:00
// Validate index.
if ( ClassValidateIndex ( motherindex ))
{
2009-07-23 23:26:14 +02:00
// Save active class index to be restored next spawn.
ClassSelectedNext [ client ][ ZR_CLASS_TEAM_ZOMBIES ] = classindex ;
2016-02-06 00:47:47 +01:00
2009-06-22 01:09:51 +02:00
// Change class.
classindex = motherindex ;
}
}
}
2016-02-06 00:47:47 +01:00
2009-07-23 23:26:14 +02:00
// Update the player's selected class index.
ClassSelected [ client ][ ZR_CLASS_TEAM_ZOMBIES ] = classindex ;
2016-02-06 00:47:47 +01:00
2009-07-23 23:26:14 +02:00
// Restore next indexes, if available. But don't restore the zombie index.
ClassRestoreNextIndexes ( client , ZR_CLASS_TEAM_ZOMBIES );
2016-02-06 00:47:47 +01:00
2009-07-23 23:26:14 +02:00
// Update the player's cache with zombie attributes.
2009-04-11 01:56:22 +02:00
ClassReloadPlayerCache ( client , classindex );
2016-02-06 00:47:47 +01:00
2009-04-11 01:56:22 +02:00
// Apply the new attributes.
ClassApplyAttributes ( client , motherzombie );
}
2009-08-10 19:01:43 +02:00
/**
* Timer callback for disabling instant class change setting on a client .
*/
public Action : Event_ClassDisableInstantSpawn ( Handle : timer , any : client )
{
// Disable instant class change.
ClassAllowInstantChange [ client ] = false ;
}