Merged heads.
This commit is contained in:
commit
67ec1f8433
|
@ -36,8 +36,8 @@
|
|||
// kill_bonus number How many points to give per kill. Humans only.
|
||||
// speed decimal The player speed.
|
||||
// knockback decimal Force of the knockback when shot at. Zombies only.
|
||||
// jump_height decimal Extra upwards jump boost.
|
||||
// jump_distance decimal Extra forwards jump boost.
|
||||
// jump_height decimal Extra upwards jump boost in units. 0.0 for no extra boost.
|
||||
// jump_distance decimal Extra forwards jump boost multiplier. 0.2 is normal distance.
|
||||
|
||||
"classes"
|
||||
{
|
||||
|
@ -75,16 +75,16 @@
|
|||
"immunity_amount" "0.0"
|
||||
"no_fall_damage" "1"
|
||||
|
||||
"health" "3000"
|
||||
"health" "2500"
|
||||
"health_regen_interval" "0.0"
|
||||
"health_regen_amount" "0"
|
||||
"health_infect_gain" "800"
|
||||
"health_infect_gain" "700"
|
||||
"kill_bonus" "2"
|
||||
|
||||
"speed" "350"
|
||||
"knockback" "3"
|
||||
"jump_height" "40.0"
|
||||
"jump_distance" "1.5"
|
||||
"knockback" "4"
|
||||
"jump_height" "10.0"
|
||||
"jump_distance" "0.3"
|
||||
}
|
||||
|
||||
"fast"
|
||||
|
@ -123,9 +123,9 @@
|
|||
"kill_bonus" "2"
|
||||
|
||||
"speed" "380"
|
||||
"knockback" "3.5"
|
||||
"jump_height" "60.0"
|
||||
"jump_distance" "2.0"
|
||||
"knockback" "4.5"
|
||||
"jump_height" "30.0"
|
||||
"jump_distance" "0.4"
|
||||
}
|
||||
|
||||
"mutated"
|
||||
|
@ -157,16 +157,16 @@
|
|||
"immunity_amount" "0.0"
|
||||
"no_fall_damage" "1"
|
||||
|
||||
"health" "5000"
|
||||
"health" "3500"
|
||||
"health_regen_interval" "0.0"
|
||||
"health_regen_amount" "0"
|
||||
"health_infect_gain" "1000"
|
||||
"health_infect_gain" "850"
|
||||
"kill_bonus" "2"
|
||||
|
||||
"speed" "275"
|
||||
"knockback" "3.5"
|
||||
"jump_height" "40.0"
|
||||
"jump_distance" "1.3"
|
||||
"jump_height" "20.0"
|
||||
"jump_distance" "0.4"
|
||||
}
|
||||
|
||||
"heavy"
|
||||
|
@ -198,16 +198,16 @@
|
|||
"immunity_amount" "0.0"
|
||||
"no_fall_damage" "1"
|
||||
|
||||
"health" "5000"
|
||||
"health" "4000"
|
||||
"health_regen_interval" "0.0"
|
||||
"health_regen_amount" "0"
|
||||
"health_infect_gain" "1000"
|
||||
"kill_bonus" "2"
|
||||
|
||||
"speed" "280"
|
||||
"knockback" "2.0"
|
||||
"knockback" "2.5"
|
||||
"jump_height" "0.0"
|
||||
"jump_distance" "0.8"
|
||||
"jump_distance" "0.2"
|
||||
}
|
||||
|
||||
// ------------------------------------------
|
||||
|
@ -254,7 +254,7 @@
|
|||
"speed" "300"
|
||||
"knockback" "0"
|
||||
"jump_height" "0.0"
|
||||
"jump_distance" "1.0"
|
||||
"jump_distance" "0.2"
|
||||
}
|
||||
|
||||
"human_speedy"
|
||||
|
@ -295,7 +295,7 @@
|
|||
"speed" "380"
|
||||
"knockback" "0"
|
||||
"jump_height" "0.0"
|
||||
"jump_distance" "1.0"
|
||||
"jump_distance" "0.2"
|
||||
}
|
||||
|
||||
"human_light"
|
||||
|
@ -335,7 +335,7 @@
|
|||
|
||||
"speed" "300"
|
||||
"knockback" "0"
|
||||
"jump_height" "64.0"
|
||||
"jump_distance" "2.0"
|
||||
"jump_height" "30.0"
|
||||
"jump_distance" "0.4"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -200,6 +200,9 @@ public OnConfigsExecuted()
|
|||
VEffectsLoad();
|
||||
SEffectsLoad();
|
||||
ClassLoad();
|
||||
|
||||
ConfigOnModulesLoaded();
|
||||
ClassOnModulesLoaded();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -26,7 +26,9 @@ CreateCommands()
|
|||
RegAdminCmd("zr_anticamp_list", Command_AnticampList, ADMFLAG_GENERIC, "List current volumes.");
|
||||
|
||||
RegConsoleCmd("zr_log_flags", Command_LogFlags, "List available logging flags.");
|
||||
|
||||
RegConsoleCmd("zr_class_dump", Command_ClassDump, "Dumps class data at a specified index in the specified cache. Usage: zr_class_dump <cachetype> <index|targetname>");
|
||||
RegAdminCmd("zr_class_modify", Command_ClassModify, ADMFLAG_GENERIC, "Modify class data on one or more classes. Usage: zr_class_modify <classname|\"zombies\"|\"humans\"|\"admins\"> <attribute> <value> [is_multiplier]");
|
||||
}
|
||||
|
||||
public Action:Command_Infect(client, argc)
|
||||
|
@ -229,60 +231,6 @@ public Action:Command_Unrestrict(client, argc)
|
|||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
/*public Action:Command_SetClassKnockback(client, argc)
|
||||
{
|
||||
if (argc < 2)
|
||||
{
|
||||
ReplyToCommand(client, "Sets the specified class knockback. Usage: zr_set_class_knockback <classname> <knockback>");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
decl String:classname[64];
|
||||
decl String:knockback_arg[8];
|
||||
new classindex;
|
||||
new Float:knockback;
|
||||
|
||||
GetCmdArg(1, classname, sizeof(classname));
|
||||
GetCmdArg(2, knockback_arg, sizeof(knockback_arg));
|
||||
classindex = GetClassIndex(classname);
|
||||
knockback = StringToFloat(knockback_arg);
|
||||
|
||||
if (classindex < 0)
|
||||
{
|
||||
ReplyToCommand(client, "Could not find the class %s.", classname);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
arrayClasses[classindex][data_knockback] = knockback;
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action:Command_GetClassKnockback(client, argc)
|
||||
{
|
||||
if (argc < 1)
|
||||
{
|
||||
ReplyToCommand(client, "Gets the specified class knockback. Usage: zr_get_class_knockback <classname>");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
decl String:classname[64];
|
||||
new classindex;
|
||||
new Float:knockback;
|
||||
|
||||
GetCmdArg(1, classname, sizeof(classname));
|
||||
classindex = GetClassIndex(classname);
|
||||
|
||||
if (classindex < 0)
|
||||
{
|
||||
ReplyToCommand(client, "Could not find the class %s.", classname);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
knockback = arrayClasses[classindex][data_knockback];
|
||||
ReplyToCommand(client, "Current knockback for %s: %f", classname, knockback);
|
||||
|
||||
return Plugin_Handled;
|
||||
}*/
|
||||
|
||||
public Action:Command_AdminMenu(client, argc)
|
||||
{
|
||||
|
|
|
@ -41,6 +41,9 @@
|
|||
*/
|
||||
#define CONFIG_OPTION_MAX_LENGTH 32
|
||||
|
||||
/**
|
||||
* Actions to use when working on key/values.
|
||||
*/
|
||||
enum ConfigKeyvalueAction
|
||||
{
|
||||
Create, /** Create a key. */
|
||||
|
@ -48,6 +51,9 @@ enum ConfigKeyvalueAction
|
|||
Set, /** Modify setting of a key. */
|
||||
Get, /** Get setting of a key. */
|
||||
}
|
||||
/**
|
||||
* @endsection
|
||||
*/
|
||||
|
||||
/**
|
||||
* @section Global data handle initializations.
|
||||
|
@ -57,6 +63,7 @@ new Handle:kvClassData = INVALID_HANDLE;
|
|||
new Handle:kvWeapons = INVALID_HANDLE;
|
||||
new Handle:kvWeaponGroups = INVALID_HANDLE;
|
||||
new Handle:kvHitgroups = INVALID_HANDLE;
|
||||
|
||||
/**
|
||||
* Load plugin configs.
|
||||
*/
|
||||
|
@ -88,6 +95,48 @@ ConfigLoad()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executed when modules are done loading. After all init calls in
|
||||
* OnConfigsExecuted.
|
||||
*
|
||||
* Executes post map configs if they exist.
|
||||
*/
|
||||
ConfigOnModulesLoaded()
|
||||
{
|
||||
decl String:mapname[256];
|
||||
decl String:mapconfig[PLATFORM_MAX_PATH];
|
||||
decl String:path[PLATFORM_MAX_PATH];
|
||||
new bool:cfgexists;
|
||||
|
||||
// Get map name and format into config path.
|
||||
GetCurrentMap(mapname, sizeof(mapname));
|
||||
Format(mapconfig, sizeof(mapconfig), "sourcemod/zombiereloaded/%s.post.cfg", mapname);
|
||||
|
||||
// Prepend cfg to path.
|
||||
Format(path, sizeof(path), "cfg/%s", mapconfig);
|
||||
|
||||
// Workaround for bug 3083 in SourceMod compiler. Having FileExist directly
|
||||
// in the if in this function makes it crash. Storing the result in a
|
||||
// boolean first works.
|
||||
|
||||
// Check if the file exist.
|
||||
cfgexists = FileExists(path);
|
||||
if (!cfgexists)
|
||||
{
|
||||
// File doesn't exist, then stop.
|
||||
return;
|
||||
}
|
||||
|
||||
// Execute config file.
|
||||
ServerCommand("exec %s", mapconfig);
|
||||
|
||||
// Log action.
|
||||
if (LogCheckFlag(LOG_CORE_EVENTS))
|
||||
{
|
||||
LogMessageFormatted(-1, "", "", "Executed post map config file: %s.", LOG_FORMAT_TYPE_SIMPLE, mapconfig);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load config file.
|
||||
*
|
||||
|
@ -106,6 +155,7 @@ bool:ConfigGetFilePath(CvarsList:cvar, String:path[])
|
|||
return FileExists(path);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates, deletes, sets, or gets any key/setting of any ZR config keyvalue file in memory.
|
||||
* Only use when interacting with a command or manipulating single keys/values,
|
||||
|
|
|
@ -28,13 +28,13 @@ JumpBoostOnClientJump(client)
|
|||
// Apply jump values.
|
||||
vecVelocity[0] *= distance;
|
||||
vecVelocity[1] *= distance;
|
||||
vecVelocity[2] = height;
|
||||
vecVelocity[2] += height;
|
||||
|
||||
JumpBoostSetClientVelocity(client, vecVelocity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply jump boost force on client. (Special method separate from ToolsClientVelocity)
|
||||
* Set new velocity on client. (Special method separate from ToolsClientVelocity)
|
||||
*
|
||||
* @param client The client index.
|
||||
* @param vecVelocity Velocity to set on client.
|
||||
|
|
|
@ -92,6 +92,7 @@ LogInit()
|
|||
* LOG_FORMAT_TYPE_SIMPLE - Simple, no module or block info.
|
||||
* LOG_FORMAT_TYPE_FULL - Full, with module and block info, printed in normal log.
|
||||
* LOG_FORMAT_TYPE_ERROR - Full, printed in error log.
|
||||
* LOG_FORMAT_TYPE_FATALERROR - Full, stops the plugin.
|
||||
* @param any... Formatting parameters.
|
||||
*/
|
||||
LogMessageFormatted(client, const String:module[], const String:block[], const String:message[], type = LOG_FORMAT_TYPE_FULL, any:...)
|
||||
|
|
|
@ -24,7 +24,7 @@ MenuMain(client)
|
|||
SetGlobalTransTarget(client);
|
||||
|
||||
// Set menu title.
|
||||
SetMenuTitle(menu_main, "%t\n ", "!zmenu title");
|
||||
SetMenuTitle(menu_main, "%t\n ", "Menu main title");
|
||||
|
||||
// Initialize menu lines.
|
||||
decl String:zadmin[64];
|
||||
|
|
|
@ -40,6 +40,9 @@ ModelsLoad()
|
|||
*/
|
||||
ModelsPrepModels()
|
||||
{
|
||||
// Initialize log boolean.
|
||||
new bool:enablelog = LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_CORE);
|
||||
|
||||
// Get models file path.
|
||||
decl String:pathmodels[PLATFORM_MAX_PATH];
|
||||
new bool:exists = ConfigGetFilePath(CVAR_CONFIG_PATH_MODELS, pathmodels);
|
||||
|
@ -48,10 +51,7 @@ ModelsPrepModels()
|
|||
if (!exists)
|
||||
{
|
||||
// Log failure and stop plugin.
|
||||
if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_CORE))
|
||||
{
|
||||
LogMessageFormatted(-1, "Models", "Config Validation", "Missing models file: %s", LOG_FORMAT_TYPE_FATALERROR, pathmodels);
|
||||
}
|
||||
LogMessageFormatted(-1, "Models", "Config Validation", "Fatal error: Missing models file: \"%s\"", LOG_FORMAT_TYPE_FATALERROR, pathmodels);
|
||||
}
|
||||
|
||||
// If model array exists, then destroy it.
|
||||
|
@ -65,7 +65,7 @@ ModelsPrepModels()
|
|||
// If array couldn't be created, then fail.
|
||||
if (arrayModelsList == INVALID_HANDLE)
|
||||
{
|
||||
LogMessageFormatted(-1, "Models", "Config Validation", "Error parsing %s", LOG_FORMAT_TYPE_FATALERROR, pathmodels);
|
||||
LogMessageFormatted(-1, "Models", "Config Validation", "Fatal error: Error parsing \"%s\"", LOG_FORMAT_TYPE_FATALERROR, pathmodels);
|
||||
}
|
||||
|
||||
new modelcount;
|
||||
|
@ -155,7 +155,7 @@ ModelsPrepModels()
|
|||
x--;
|
||||
|
||||
// Log missing model files.
|
||||
if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_CORE))
|
||||
if (enablelog)
|
||||
{
|
||||
LogMessageFormatted(-1, "Models", "Config Validation", "Missing model files on server (%s)", LOG_FORMAT_TYPE_ERROR, modelbase);
|
||||
}
|
||||
|
@ -163,12 +163,15 @@ ModelsPrepModels()
|
|||
}
|
||||
|
||||
// Log model validation info.
|
||||
LogMessageFormatted(-1, "Models", "Config Validation", "Total: %d | Successful: %d | Unsuccessful: %d", LOG_FORMAT_TYPE_FULL, modelcount, modelvalidcount, modelcount - modelvalidcount);
|
||||
if (enablelog)
|
||||
{
|
||||
LogMessageFormatted(-1, "Models", "Config Validation", "Total: %d | Successful: %d | Unsuccessful: %d", LOG_FORMAT_TYPE_FULL, modelcount, modelvalidcount, modelcount - modelvalidcount);
|
||||
}
|
||||
|
||||
// If none of the model paths are valid, then log and fail.
|
||||
if (!modelvalidcount)
|
||||
{
|
||||
if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_CORE))
|
||||
if (enablelog)
|
||||
{
|
||||
LogMessageFormatted(-1, "Models", "Config Validation", "No usable model paths in %s", LOG_FORMAT_TYPE_FATALERROR, pathmodels);
|
||||
}
|
||||
|
@ -180,6 +183,9 @@ ModelsPrepModels()
|
|||
*/
|
||||
ModelsPrepDownloads()
|
||||
{
|
||||
// Initialize log boolean.
|
||||
new bool:enablelog = LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_CORE);
|
||||
|
||||
// Get downloads file path.
|
||||
decl String:pathdownloads[PLATFORM_MAX_PATH];
|
||||
new bool:exists = ConfigGetFilePath(CVAR_CONFIG_PATH_DOWNLOADS, pathdownloads);
|
||||
|
@ -188,9 +194,9 @@ ModelsPrepDownloads()
|
|||
if (!exists)
|
||||
{
|
||||
// Log error, then stop.
|
||||
if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_CORE))
|
||||
if (enablelog)
|
||||
{
|
||||
LogMessageFormatted(-1, "Downloads", "Config Validation", "Missing downloads file: %s", LOG_FORMAT_TYPE_ERROR, pathdownloads);
|
||||
LogMessageFormatted(-1, "Downloads", "Config Validation", "Missing downloads file: \"%s\"", LOG_FORMAT_TYPE_ERROR, pathdownloads);
|
||||
}
|
||||
|
||||
return;
|
||||
|
@ -201,9 +207,9 @@ ModelsPrepDownloads()
|
|||
// If array couldn't be created, then fail.
|
||||
if (arrayModelsList == INVALID_HANDLE)
|
||||
{
|
||||
if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_CORE))
|
||||
if (enablelog)
|
||||
{
|
||||
LogMessageFormatted(-1, "Downloads", "Config Validation", "Error parsing %s", LOG_FORMAT_TYPE_ERROR, pathdownloads);
|
||||
LogMessageFormatted(-1, "Downloads", "Config Validation", "Error parsing \"%s\"", LOG_FORMAT_TYPE_ERROR, pathdownloads);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -232,9 +238,9 @@ ModelsPrepDownloads()
|
|||
// Backtrack one index, because we deleted it out from under the loop.
|
||||
x--;
|
||||
|
||||
if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_CORE))
|
||||
if (enablelog)
|
||||
{
|
||||
LogMessageFormatted(-1, "Downloads", "Config Validation", "Missing file (%s)", LOG_FORMAT_TYPE_ERROR, downloadpath);
|
||||
LogMessageFormatted(-1, "Downloads", "Config Validation", "Missing file \"%s\"", LOG_FORMAT_TYPE_ERROR, downloadpath);
|
||||
}
|
||||
|
||||
continue;
|
||||
|
@ -248,5 +254,8 @@ ModelsPrepDownloads()
|
|||
}
|
||||
|
||||
// Log model validation info.
|
||||
LogMessageFormatted(-1, "Downloads", "Config Validation", "Total: %d | Successful: %d | Unsuccessful: %d", LOG_FORMAT_TYPE_FULL, downloadcount, downloadvalidcount, downloadcount - downloadvalidcount);
|
||||
if (enablelog)
|
||||
{
|
||||
LogMessageFormatted(-1, "Downloads", "Config Validation", "Total: %d | Successful: %d | Unsuccessful: %d", LOG_FORMAT_TYPE_FULL, downloadcount, downloadvalidcount, downloadcount - downloadvalidcount);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -875,3 +875,177 @@ Float:ClassGetJumpDistance(index, cachetype = ZR_CLASS_CACHE_PLAYER)
|
|||
}
|
||||
return -1.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the attribute flag that represent the specified attribute.
|
||||
*
|
||||
* @param attributename The attribute name.
|
||||
* @return The flag that reporesent the specified attribute.
|
||||
* -1 on error.
|
||||
*/
|
||||
ClassAttributeNameToFlag(const String:attributename[])
|
||||
{
|
||||
// Check attribute names.
|
||||
if (StrEqual(attributename, "enabled", false))
|
||||
{
|
||||
return ZR_CLASS_FLAG_ENABLED;
|
||||
}
|
||||
else if (StrEqual(attributename, "team", false))
|
||||
{
|
||||
return ZR_CLASS_FLAG_TEAM;
|
||||
}
|
||||
else if (StrEqual(attributename, "team_default", false))
|
||||
{
|
||||
return ZR_CLASS_FLAG_TEAM_DEFAULT;
|
||||
}
|
||||
else if (StrEqual(attributename, "name", false))
|
||||
{
|
||||
return ZR_CLASS_FLAG_NAME;
|
||||
}
|
||||
else if (StrEqual(attributename, "description", false))
|
||||
{
|
||||
return ZR_CLASS_FLAG_DESCRIPTION;
|
||||
}
|
||||
else if (StrEqual(attributename, "model_path", false))
|
||||
{
|
||||
return ZR_CLASS_FLAG_MODEL_PATH;
|
||||
}
|
||||
else if (StrEqual(attributename, "alpha_initial", false))
|
||||
{
|
||||
return ZR_CLASS_FLAG_ALPHA_INITIAL;
|
||||
}
|
||||
else if (StrEqual(attributename, "alpha_damaged", false))
|
||||
{
|
||||
return ZR_CLASS_FLAG_ALPHA_DAMAGED;
|
||||
}
|
||||
else if (StrEqual(attributename, "alpha_damage", false))
|
||||
{
|
||||
return ZR_CLASS_FLAG_ALPHA_DAMAGE;
|
||||
}
|
||||
else if (StrEqual(attributename, "overlay_path", false))
|
||||
{
|
||||
return ZR_CLASS_FLAG_OVERLAY_PATH;
|
||||
}
|
||||
else if (StrEqual(attributename, "nvgs", false))
|
||||
{
|
||||
return ZR_CLASS_FLAG_NVGS;
|
||||
}
|
||||
else if (StrEqual(attributename, "fov", false))
|
||||
{
|
||||
return ZR_CLASS_FLAG_FOV;
|
||||
}
|
||||
else if (StrEqual(attributename, "napalm_time", false))
|
||||
{
|
||||
return ZR_CLASS_FLAG_NAPALM_TIME;
|
||||
}
|
||||
else if (StrEqual(attributename, "immunity_mode", false))
|
||||
{
|
||||
return ZR_CLASS_FLAG_IMMUNITY_MODE;
|
||||
}
|
||||
else if (StrEqual(attributename, "immunity_amount", false))
|
||||
{
|
||||
return ZR_CLASS_FLAG_IMMUNITY_AMOUNT;
|
||||
}
|
||||
else if (StrEqual(attributename, "no_fall_damage", false))
|
||||
{
|
||||
return ZR_CLASS_FLAG_NO_FALL_DAMAGE;
|
||||
}
|
||||
else if (StrEqual(attributename, "health", false))
|
||||
{
|
||||
return ZR_CLASS_FLAG_HEALTH;
|
||||
}
|
||||
else if (StrEqual(attributename, "health_regen_interval", false))
|
||||
{
|
||||
return ZR_CLASS_FLAG_HEALTH_REGEN_INTERVAL;
|
||||
}
|
||||
else if (StrEqual(attributename, "health_regen_amount", false))
|
||||
{
|
||||
return ZR_CLASS_FLAG_HEALTH_REGEN_AMOUNT;
|
||||
}
|
||||
else if (StrEqual(attributename, "health_infect_gain", false))
|
||||
{
|
||||
return ZR_CLASS_FLAG_HEALTH_INFECT_GAIN;
|
||||
}
|
||||
else if (StrEqual(attributename, "kill_bonus", false))
|
||||
{
|
||||
return ZR_CLASS_FLAG_KILL_BONUS;
|
||||
}
|
||||
else if (StrEqual(attributename, "speed", false))
|
||||
{
|
||||
return ZR_CLASS_FLAG_SPEED;
|
||||
}
|
||||
else if (StrEqual(attributename, "knockback", false))
|
||||
{
|
||||
return ZR_CLASS_FLAG_KNOCKBACK;
|
||||
}
|
||||
else if (StrEqual(attributename, "jump_height", false))
|
||||
{
|
||||
return ZR_CLASS_FLAG_JUMP_HEIGHT;
|
||||
}
|
||||
else if (StrEqual(attributename, "jump_distance", false))
|
||||
{
|
||||
return ZR_CLASS_FLAG_JUMP_DISTANCE;
|
||||
}
|
||||
|
||||
// Invalid attribute name.
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the datatype used in the specified attribute.
|
||||
*
|
||||
* @param attributeflag A flag specifying the attribute to check.
|
||||
* @return The data type used in the specified attribute, or
|
||||
* ClassType_InvalidType if failed.
|
||||
*/
|
||||
ClassDataTypes:ClassGetAttributeType(attributeflag)
|
||||
{
|
||||
switch (attributeflag)
|
||||
{
|
||||
// Boolean.
|
||||
case ZR_CLASS_FLAG_ENABLED,
|
||||
ZR_CLASS_FLAG_NVGS,
|
||||
ZR_CLASS_FLAG_NO_FALL_DAMAGE:
|
||||
{
|
||||
return ClassDataType_Boolean;
|
||||
}
|
||||
|
||||
// Integer.
|
||||
case ZR_CLASS_FLAG_ALPHA_INITIAL,
|
||||
ZR_CLASS_FLAG_ALPHA_DAMAGED,
|
||||
ZR_CLASS_FLAG_ALPHA_DAMAGE,
|
||||
ZR_CLASS_FLAG_FOV,
|
||||
ZR_CLASS_FLAG_IMMUNITY_MODE,
|
||||
ZR_CLASS_FLAG_HEALTH,
|
||||
ZR_CLASS_FLAG_HEALTH_REGEN_AMOUNT,
|
||||
ZR_CLASS_FLAG_HEALTH_INFECT_GAIN,
|
||||
ZR_CLASS_FLAG_KILL_BONUS:
|
||||
{
|
||||
return ClassDataType_Integer;
|
||||
}
|
||||
|
||||
// Float.
|
||||
case ZR_CLASS_FLAG_NAPALM_TIME,
|
||||
ZR_CLASS_FLAG_IMMUNITY_AMOUNT,
|
||||
ZR_CLASS_FLAG_HEALTH_REGEN_INTERVAL,
|
||||
ZR_CLASS_FLAG_SPEED,
|
||||
ZR_CLASS_FLAG_KNOCKBACK,
|
||||
ZR_CLASS_FLAG_JUMP_HEIGHT,
|
||||
ZR_CLASS_FLAG_JUMP_DISTANCE:
|
||||
{
|
||||
return ClassDataType_Float;
|
||||
}
|
||||
|
||||
// String.
|
||||
case ZR_CLASS_FLAG_NAME,
|
||||
ZR_CLASS_FLAG_DESCRIPTION,
|
||||
ZR_CLASS_FLAG_MODEL_PATH,
|
||||
ZR_CLASS_FLAG_OVERLAY_PATH:
|
||||
{
|
||||
return ClassDataType_String;
|
||||
}
|
||||
}
|
||||
|
||||
// Invalid flag or multiple flags combined.
|
||||
return ClassDataType_InvalidType;
|
||||
}
|
||||
|
|
|
@ -97,3 +97,499 @@ public Action:Command_ClassDump(client, argc)
|
|||
return Plugin_Handled;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Modifies class data on one or more classes.
|
||||
*
|
||||
* Syntax: zr_class_modify <class> <attribute> <value> [is_multiplier]
|
||||
*
|
||||
* class: The class to modify. Can be any class name, or one of the
|
||||
* following team names; "all", "humans", "zombies" or
|
||||
* "admins".
|
||||
* attribute: The name of the class attribute.
|
||||
* value: Value to set. Use quotes if value is a string.
|
||||
* is_multiplier: Optional. specifies wether the original value should be
|
||||
* multiplied by the specified value. Defaults to false.
|
||||
*
|
||||
* Note: Original values are retrieved from the original class cache, not the
|
||||
* modified class cache.
|
||||
*/
|
||||
public Action:Command_ClassModify(client, argc)
|
||||
{
|
||||
decl String:syntax[1024];
|
||||
syntax[0] = 0;
|
||||
|
||||
if (argc < 3)
|
||||
{
|
||||
// Write syntax info.
|
||||
StrCat(syntax, sizeof(syntax), "Modifies class data on one or more classes. Usage: zr_class_modify <class> <attribute> <value> [is_multiplier]\n\n");
|
||||
StrCat(syntax, sizeof(syntax), "class: The class to modify. Can be any class name, or one of the following team names; all, humans, zombies or admins.\n");
|
||||
StrCat(syntax, sizeof(syntax), "attribute: The name of the class attribute.\n");
|
||||
StrCat(syntax, sizeof(syntax), "value: Value to set. Use quotes if value is a string.\n");
|
||||
StrCat(syntax, sizeof(syntax), "is_multiplier: Optional. specifies wether the original value should be multiplied by the specified value. Not all attributes support multiplying. Defaults to false.\n\n");
|
||||
StrCat(syntax, sizeof(syntax), "Note: Original values are retrieved from the original class cache, not the modified class cache.");
|
||||
ReplyToCommand(client, syntax);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
decl String:classname[64];
|
||||
decl String:attributename[128];
|
||||
decl String:value[256];
|
||||
decl String:ismultiplier[4];
|
||||
|
||||
new attributeflag;
|
||||
new ClassDataTypes:attributetype;
|
||||
new bool:isgroup;
|
||||
new bool:hasmultiplier;
|
||||
new Handle:classlist;
|
||||
|
||||
new classindex;
|
||||
new bool:listresult;
|
||||
classlist = CreateArray();
|
||||
|
||||
// Get command arguments.
|
||||
GetCmdArg(1, classname, sizeof(classname));
|
||||
GetCmdArg(2, attributename, sizeof(attributename));
|
||||
GetCmdArg(3, value, sizeof(value));
|
||||
|
||||
// Get last command argument if specified.
|
||||
if (argc == 4)
|
||||
{
|
||||
GetCmdArg(4, ismultiplier, sizeof(ismultiplier));
|
||||
if (StringToInt(ismultiplier))
|
||||
{
|
||||
hasmultiplier = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Get attribute flag.
|
||||
attributeflag = ClassAttributeNameToFlag(attributename);
|
||||
|
||||
// Validate attribute flag.
|
||||
if (attributeflag < 0)
|
||||
{
|
||||
ReplyToCommand(client, "Invalid class attribute specified.");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
// Get attribute data type.
|
||||
attributetype = ClassGetAttributeType(attributeflag);
|
||||
|
||||
// Check if classname is a group. Add classes to the class list
|
||||
// and use the specified team filter.
|
||||
if (StrEqual(classname, "all", false))
|
||||
{
|
||||
listresult = ClassAddToArray(classlist);
|
||||
isgroup = true;
|
||||
}
|
||||
else if (StrEqual(classname, "humans", false))
|
||||
{
|
||||
listresult = ClassAddToArray(classlist, ZR_CLASS_TEAM_HUMANS);
|
||||
isgroup = true;
|
||||
}
|
||||
else if (StrEqual(classname, "zombies", false))
|
||||
{
|
||||
listresult = ClassAddToArray(classlist, ZR_CLASS_TEAM_ZOMBIES);
|
||||
isgroup = true;
|
||||
}
|
||||
else if (StrEqual(classname, "admins", false))
|
||||
{
|
||||
listresult = ClassAddToArray(classlist, ZR_CLASS_TEAM_ADMINS);
|
||||
isgroup = true;
|
||||
}
|
||||
|
||||
// Check if classname is a group.
|
||||
if (isgroup)
|
||||
{
|
||||
// Check if the list is valid.
|
||||
if (!listresult)
|
||||
{
|
||||
ReplyToCommand(client, "Failed to get classes in the specified team: \"%s\".", classname);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
// Loop through all classes in the list.
|
||||
new listsize = GetArraySize(classlist);
|
||||
|
||||
for (new i = 0; i < listsize; i++)
|
||||
{
|
||||
classindex = GetArrayCell(classlist, i);
|
||||
|
||||
switch (attributetype)
|
||||
{
|
||||
case ClassDataType_Boolean:
|
||||
{
|
||||
if (!ClassModifyBoolean(classindex, attributeflag, bool:StringToInt(value)))
|
||||
{
|
||||
ReplyToCommand(client, "Failed to set \"%s\" to \"%s\" in class \"%d\".", attributename, value, classindex);
|
||||
}
|
||||
}
|
||||
case ClassDataType_Integer:
|
||||
{
|
||||
if (hasmultiplier)
|
||||
{
|
||||
if (!ClassModifyInteger(classindex, attributeflag, StringToInt(value), StringToFloat(value)))
|
||||
{
|
||||
ReplyToCommand(client, "Failed to set \"%s\" to \"%s\" in class \"%d\".", attributename, value, classindex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ClassModifyInteger(classindex, attributeflag, StringToInt(value)))
|
||||
{
|
||||
ReplyToCommand(client, "Failed to set \"%s\" to \"%s\" in class \"%d\".", attributename, value, classindex);
|
||||
}
|
||||
}
|
||||
}
|
||||
case ClassDataType_Float:
|
||||
{
|
||||
if (!ClassModifyFloat(classindex, attributeflag, StringToFloat(value), hasmultiplier))
|
||||
{
|
||||
ReplyToCommand(client, "Failed to set \"%s\" to \"%s\" in class \"%d\".", attributename, value, classindex);
|
||||
}
|
||||
}
|
||||
case ClassDataType_String:
|
||||
{
|
||||
if (!ClassModifyString(classindex, attributeflag, value))
|
||||
{
|
||||
ReplyToCommand(client, "Failed to set \"%s\" to \"%s\" in class \"%d\".", attributename, value, classindex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// It's a single class.
|
||||
classindex = ClassGetIndex(classname);
|
||||
|
||||
// Validate classindex.
|
||||
if (!ClassValidateIndex(classindex))
|
||||
{
|
||||
ReplyToCommand(client, "Invalid class name specified.");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
switch (attributetype)
|
||||
{
|
||||
case ClassDataType_Boolean:
|
||||
{
|
||||
if (!ClassModifyBoolean(classindex, attributeflag, bool:StringToInt(value)))
|
||||
{
|
||||
ReplyToCommand(client, "Failed to set \"%s\" to \"%s\" in class \"%d\".", attributename, value, classindex);
|
||||
}
|
||||
}
|
||||
case ClassDataType_Integer:
|
||||
{
|
||||
if (hasmultiplier)
|
||||
{
|
||||
if (!ClassModifyInteger(classindex, attributeflag, StringToInt(value), StringToFloat(value)))
|
||||
{
|
||||
ReplyToCommand(client, "Failed to set \"%s\" to \"%s\" in class \"%d\".", attributename, value, classindex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!ClassModifyInteger(classindex, attributeflag, StringToInt(value)))
|
||||
{
|
||||
ReplyToCommand(client, "Failed to set \"%s\" to \"%s\" in class \"%d\".", attributename, value, classindex);
|
||||
}
|
||||
}
|
||||
}
|
||||
case ClassDataType_Float:
|
||||
{
|
||||
if (!ClassModifyFloat(classindex, attributeflag, StringToFloat(value)), hasmultiplier)
|
||||
{
|
||||
ReplyToCommand(client, "Failed to set \"%s\" to \"%s\" in class \"%d\".", attributename, value, classindex);
|
||||
}
|
||||
}
|
||||
case ClassDataType_String:
|
||||
{
|
||||
if (!ClassModifyString(classindex, attributeflag, value))
|
||||
{
|
||||
ReplyToCommand(client, "Failed to set \"%s\" to \"%s\" in class \"%d\".", attributename, value, classindex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify class boolean attribute on a class.
|
||||
*
|
||||
* @param classindex The class index.
|
||||
* @param attributeflag Attribute to modify (a single attribute flag).
|
||||
* @param value New value to set.
|
||||
* @return True on success, false otherwise.
|
||||
*/
|
||||
bool:ClassModifyBoolean(classindex, attributeflag, bool:value)
|
||||
{
|
||||
// Validate class index.
|
||||
if (!ClassValidateIndex(classindex))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (attributeflag)
|
||||
{
|
||||
case ZR_CLASS_FLAG_ENABLED:
|
||||
{
|
||||
ClassDataCache[classindex][class_enabled] = bool:value;
|
||||
return true;
|
||||
}
|
||||
case ZR_CLASS_FLAG_NVGS:
|
||||
{
|
||||
ClassDataCache[classindex][class_nvgs] = bool:value;
|
||||
return true;
|
||||
}
|
||||
case ZR_CLASS_FLAG_NO_FALL_DAMAGE:
|
||||
{
|
||||
ClassDataCache[classindex][class_no_fall_damage] = bool:value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Invalid flag or multiple flags combined.
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify class integer attribute on a class.
|
||||
*
|
||||
* @param classindex The class index.
|
||||
* @param attributeflag Attribute to modify (a single attribute flag).
|
||||
* @param value New value to set, or multiply with.
|
||||
* @param multiplier Optional. Use a multiplier instead of the value,
|
||||
* that multiplies with the original class value.
|
||||
* Not all attributes support multipliers. 0.0 to
|
||||
* disable. Value is ignored if this is non-zero.
|
||||
* @return True on success, false otherwise.
|
||||
*/
|
||||
ClassModifyInteger(classindex, attributeflag, value, Float:multiplier = 0.0)
|
||||
{
|
||||
// Validate class index.
|
||||
if (!ClassValidateIndex(classindex))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if multiplier is specified.
|
||||
new bool:ismultiplier = (multiplier != 0.0) ? true : false;
|
||||
|
||||
switch (attributeflag)
|
||||
{
|
||||
case ZR_CLASS_FLAG_ALPHA_INITIAL:
|
||||
{
|
||||
if (ismultiplier)
|
||||
{
|
||||
value = RoundToNearest(float(ClassData[classindex][class_alpha_initial]) * multiplier);
|
||||
}
|
||||
ClassDataCache[classindex][class_alpha_initial] = value;
|
||||
return true;
|
||||
}
|
||||
case ZR_CLASS_FLAG_ALPHA_DAMAGED:
|
||||
{
|
||||
if (ismultiplier)
|
||||
{
|
||||
value = RoundToNearest(float(ClassData[classindex][class_alpha_damaged]) * multiplier);
|
||||
}
|
||||
ClassDataCache[classindex][class_alpha_damaged] = value;
|
||||
return true;
|
||||
}
|
||||
case ZR_CLASS_FLAG_ALPHA_DAMAGE:
|
||||
{
|
||||
if (ismultiplier)
|
||||
{
|
||||
value = RoundToNearest(float(ClassData[classindex][class_alpha_damage]) * multiplier);
|
||||
}
|
||||
ClassDataCache[classindex][class_alpha_damage] = value;
|
||||
return true;
|
||||
}
|
||||
case ZR_CLASS_FLAG_FOV:
|
||||
{
|
||||
ClassDataCache[classindex][class_fov] = value;
|
||||
return true;
|
||||
}
|
||||
case ZR_CLASS_FLAG_IMMUNITY_MODE:
|
||||
{
|
||||
ClassDataCache[classindex][class_fov] = value;
|
||||
return true;
|
||||
}
|
||||
case ZR_CLASS_FLAG_HEALTH:
|
||||
{
|
||||
if (ismultiplier)
|
||||
{
|
||||
value = RoundToNearest(float(ClassData[classindex][class_health]) * multiplier);
|
||||
}
|
||||
ClassDataCache[classindex][class_health] = value;
|
||||
return true;
|
||||
}
|
||||
case ZR_CLASS_FLAG_HEALTH_REGEN_AMOUNT:
|
||||
{
|
||||
if (ismultiplier)
|
||||
{
|
||||
value = RoundToNearest(float(ClassData[classindex][class_health_regen_amount]) * multiplier);
|
||||
}
|
||||
ClassDataCache[classindex][class_health_regen_amount] = value;
|
||||
return true;
|
||||
}
|
||||
case ZR_CLASS_FLAG_HEALTH_INFECT_GAIN:
|
||||
{
|
||||
if (ismultiplier)
|
||||
{
|
||||
value = RoundToNearest(float(ClassData[classindex][class_health_infect_gain]) * multiplier);
|
||||
}
|
||||
ClassDataCache[classindex][class_health_infect_gain] = value;
|
||||
return true;
|
||||
}
|
||||
case ZR_CLASS_FLAG_KILL_BONUS:
|
||||
{
|
||||
if (ismultiplier)
|
||||
{
|
||||
value = RoundToNearest(float(ClassData[classindex][class_kill_bonus]) * multiplier);
|
||||
}
|
||||
ClassDataCache[classindex][class_kill_bonus] = value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Invalid flag or multiple flags combined.
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify class float attribute on a class.
|
||||
*
|
||||
* @param classindex The class index.
|
||||
* @param attributeflag Attribute to modify (a single attribute flag).
|
||||
* @param value New value to set, or multiply with.
|
||||
* @param ismultiplier Optional. Specifies wether to value as a multiplier
|
||||
* that multiplies with the original class value.
|
||||
* Not all attributes support multipliers.
|
||||
* @return True on success, false otherwise.
|
||||
*/
|
||||
ClassModifyFloat(classindex, attributeflag, Float:value, bool:ismultiplier = false)
|
||||
{
|
||||
// Validate class index.
|
||||
if (!ClassValidateIndex(classindex))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (attributeflag)
|
||||
{
|
||||
case ZR_CLASS_FLAG_NAPALM_TIME:
|
||||
{
|
||||
if (ismultiplier)
|
||||
{
|
||||
value = ClassData[classindex][class_napalm_time] * value;
|
||||
}
|
||||
ClassDataCache[classindex][class_napalm_time] = value;
|
||||
return true;
|
||||
}
|
||||
case ZR_CLASS_FLAG_IMMUNITY_AMOUNT:
|
||||
{
|
||||
if (ismultiplier)
|
||||
{
|
||||
value = ClassData[classindex][class_immunity_amount] * value;
|
||||
}
|
||||
ClassDataCache[classindex][class_immunity_amount] = value;
|
||||
return true;
|
||||
}
|
||||
case ZR_CLASS_FLAG_HEALTH_REGEN_INTERVAL:
|
||||
{
|
||||
if (ismultiplier)
|
||||
{
|
||||
value = ClassData[classindex][class_health_regen_interval] * value;
|
||||
}
|
||||
ClassDataCache[classindex][class_health_regen_interval] = value;
|
||||
return true;
|
||||
}
|
||||
case ZR_CLASS_FLAG_SPEED:
|
||||
{
|
||||
if (ismultiplier)
|
||||
{
|
||||
value = ClassData[classindex][class_speed] * value;
|
||||
}
|
||||
ClassDataCache[classindex][class_speed] = value;
|
||||
return true;
|
||||
}
|
||||
case ZR_CLASS_FLAG_KNOCKBACK:
|
||||
{
|
||||
if (ismultiplier)
|
||||
{
|
||||
value = ClassData[classindex][class_knockback] * value;
|
||||
}
|
||||
ClassDataCache[classindex][class_knockback] = value;
|
||||
return true;
|
||||
}
|
||||
case ZR_CLASS_FLAG_JUMP_HEIGHT:
|
||||
{
|
||||
if (ismultiplier)
|
||||
{
|
||||
value = ClassData[classindex][class_jump_height] * value;
|
||||
}
|
||||
ClassDataCache[classindex][class_jump_height] = value;
|
||||
return true;
|
||||
}
|
||||
case ZR_CLASS_FLAG_JUMP_DISTANCE:
|
||||
{
|
||||
if (ismultiplier)
|
||||
{
|
||||
value = ClassData[classindex][class_jump_distance] * value;
|
||||
}
|
||||
ClassDataCache[classindex][class_jump_distance] = value;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Invalid flag or multiple flags combined.
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify class string attribute on a class.
|
||||
*
|
||||
* @param classindex The class index.
|
||||
* @param attributeflag Attribute to modify (a single attribute flag).
|
||||
* @param value New value to set.
|
||||
* @return True on success, false otherwise.
|
||||
*/
|
||||
ClassModifyString(classindex, attributeflag, const String:value[])
|
||||
{
|
||||
// Validate class index.
|
||||
if (!ClassValidateIndex(classindex))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (attributeflag)
|
||||
{
|
||||
case ZR_CLASS_FLAG_NAME:
|
||||
{
|
||||
strcopy(ClassDataCache[classindex][class_name], 64, value);
|
||||
return true;
|
||||
}
|
||||
case ZR_CLASS_FLAG_DESCRIPTION:
|
||||
{
|
||||
strcopy(ClassDataCache[classindex][class_description], 256, value);
|
||||
return true;
|
||||
}
|
||||
case ZR_CLASS_FLAG_MODEL_PATH:
|
||||
{
|
||||
strcopy(ClassDataCache[classindex][class_model_path], PLATFORM_MAX_PATH, value);
|
||||
return true;
|
||||
}
|
||||
case ZR_CLASS_FLAG_OVERLAY_PATH:
|
||||
{
|
||||
strcopy(ClassDataCache[classindex][class_overlay_path], PLATFORM_MAX_PATH, value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Invalid flag or multiple flags combined.
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -23,24 +23,42 @@
|
|||
*/
|
||||
ClassClientInit(client)
|
||||
{
|
||||
if (ZRIsClientValid(client))
|
||||
// Check if there are valid classes and the client is valid.
|
||||
if (ClassValidated && ZRIsClientValid(client))
|
||||
{
|
||||
// Set default class indexes on the player.
|
||||
ClassClientSetDefaultIndexes(client);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when all modules are done loading.
|
||||
*/
|
||||
ClassOnModulesLoaded()
|
||||
{
|
||||
// Set default classes on all player slots.
|
||||
ClassClientSetDefaultIndexes();
|
||||
}
|
||||
|
||||
ClassOnClientDisconnect(client)
|
||||
{
|
||||
// Stop timers related to class attributes.
|
||||
// Disable class attributes with timers.
|
||||
ClassHealthRegenStop(client);
|
||||
ClassOverlayStop(client);
|
||||
}
|
||||
|
||||
ClassOnClientSpawn(client)
|
||||
{
|
||||
// Check if the player is alive.
|
||||
if (!IsPlayerAlive(client))
|
||||
{
|
||||
// The client isn't alive.
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if there are valid classes. Block this event if classes aren't
|
||||
// done loading.
|
||||
if (!ClassValidated)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -97,7 +115,7 @@ ClassOnClientSpawn(client)
|
|||
|
||||
ClassOnClientDeath(client)
|
||||
{
|
||||
// Reset certain attributes to not make spectating disorted.
|
||||
// Disable class attributes with timers.
|
||||
ClassHealthRegenStop(client);
|
||||
ClassOverlayStop(client);
|
||||
|
||||
|
@ -109,17 +127,13 @@ ClassOnClientInfected(client, bool:motherzombie = false)
|
|||
{
|
||||
new classindex = ClassGetActiveIndex(client);
|
||||
|
||||
// Disable class attributes with timers.
|
||||
ClassHealthRegenStop(client);
|
||||
ClassOverlayStop(client);
|
||||
|
||||
// Update the players cache with zombie attributes.
|
||||
ClassReloadPlayerCache(client, classindex);
|
||||
|
||||
// Apply the new attributes.
|
||||
ClassApplyAttributes(client, motherzombie);
|
||||
}
|
||||
|
||||
/* ------------------------------------
|
||||
*
|
||||
* PLAYER COMMANDS
|
||||
*
|
||||
* ------------------------------------
|
||||
*/
|
||||
|
||||
|
|
|
@ -96,6 +96,20 @@ ClassValidateAttributes(classindex)
|
|||
{
|
||||
flags += ZR_CLASS_FLAG_NAME;
|
||||
}
|
||||
else
|
||||
{
|
||||
decl String:name[64];
|
||||
strcopy(name, sizeof(name), ClassData[classindex][class_name]);
|
||||
|
||||
// Check for reserved name keyworks.
|
||||
if (StrEqual(name, "all", false) ||
|
||||
StrEqual(name, "humans", false) ||
|
||||
StrEqual(name, "zombies", false) ||
|
||||
StrEqual(name, "admins", false))
|
||||
{
|
||||
flags += ZR_CLASS_FLAG_NAME;
|
||||
}
|
||||
}
|
||||
|
||||
// Description.
|
||||
if (strlen(ClassData[classindex][class_description]) < ZR_CLASS_DESCRIPTION_MIN)
|
||||
|
@ -195,7 +209,7 @@ ClassValidateAttributes(classindex)
|
|||
new infect_gain = ClassData[classindex][class_health_infect_gain];
|
||||
if (!(infect_gain >= ZR_CLASS_HEALTH_INFECT_GAIN_MIN && infect_gain <= ZR_CLASS_HEALTH_INFECT_GAIN_MAX))
|
||||
{
|
||||
flags += ZR_CLASS_FLAG_INFECT_GAIN;
|
||||
flags += ZR_CLASS_FLAG_HEALTH_INFECT_GAIN;
|
||||
}
|
||||
|
||||
// Kill bonus.
|
||||
|
@ -660,6 +674,9 @@ ClassGetDefaultSpawnClass(teamid, cachetype = ZR_CLASS_CACHE_MODIFIED)
|
|||
decl String:classname[64];
|
||||
new classindex;
|
||||
|
||||
// Initialize log boolean.
|
||||
new bool:enablelog = LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_CLASSES);
|
||||
|
||||
// Get the default class name from the correct CVAR depending on teamid.
|
||||
switch (teamid)
|
||||
{
|
||||
|
@ -723,7 +740,7 @@ ClassGetDefaultSpawnClass(teamid, cachetype = ZR_CLASS_CACHE_MODIFIED)
|
|||
// in the specified team, and log a warning.
|
||||
classindex = ClassGetFirstClass(teamid, _, cachetype);
|
||||
|
||||
if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_CLASSES))
|
||||
if (enablelog)
|
||||
{
|
||||
LogMessageFormatted(-1, "Classes", "DefaultSpawnClass", "Warning: Failed to set \"%s\" as default spawn class for team %d. The class doesn't exist or the team IDs doesn't match. Falling back to the first class in the team.", _, classname, teamid);
|
||||
}
|
||||
|
@ -732,7 +749,7 @@ ClassGetDefaultSpawnClass(teamid, cachetype = ZR_CLASS_CACHE_MODIFIED)
|
|||
if (ClassValidateIndex(classindex))
|
||||
{
|
||||
// Log a warning.
|
||||
if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_CLASSES))
|
||||
if (enablelog)
|
||||
{
|
||||
LogMessageFormatted(-1, "Classes", "DefaultSpawnClass", "Warning: The default class name \"%s\" does not exist or matches the team ID.", _, classname);
|
||||
}
|
||||
|
|
|
@ -156,40 +156,44 @@
|
|||
#define ZR_CLASS_KNOCKBACK_MAX 30.0
|
||||
#define ZR_CLASS_JUMP_HEIGHT_MIN -500.0
|
||||
#define ZR_CLASS_JUMP_HEIGHT_MAX 500.0
|
||||
#define ZR_CLASS_JUMP_DISTANCE_MIN -500.0
|
||||
#define ZR_CLASS_JUMP_DISTANCE_MAX 500.0
|
||||
#define ZR_CLASS_JUMP_DISTANCE_MIN -5.0
|
||||
#define ZR_CLASS_JUMP_DISTANCE_MAX 5.0
|
||||
/**
|
||||
* @endsection
|
||||
*/
|
||||
|
||||
/**
|
||||
* @section Error flags for invalid class attributes.
|
||||
* @section Flags used for specifying one or more attributes.
|
||||
*/
|
||||
#define ZR_CLASS_FLAG_NAME (1<<0)
|
||||
#define ZR_CLASS_FLAG_DESCRIPTION (1<<1)
|
||||
#define ZR_CLASS_FLAG_MODEL_PATH (1<<2)
|
||||
#define ZR_CLASS_FLAG_ALPHA_INITIAL (1<<3)
|
||||
#define ZR_CLASS_FLAG_ALPHA_DAMAGED (1<<4)
|
||||
#define ZR_CLASS_FLAG_ALPHA_DAMAGE (1<<5)
|
||||
#define ZR_CLASS_FLAG_OVERLAY_PATH (1<<6)
|
||||
#define ZR_CLASS_FLAG_FOV (1<<7)
|
||||
#define ZR_CLASS_FLAG_NAPALM_TIME (1<<8)
|
||||
#define ZR_CLASS_FLAG_IMMUNITY_MODE (1<<9)
|
||||
#define ZR_CLASS_FLAG_IMMUNITY_AMOUNT (1<<10)
|
||||
#define ZR_CLASS_FLAG_HEALTH (1<<11)
|
||||
#define ZR_CLASS_FLAG_HEALTH_REGEN_INTERVAL (1<<12)
|
||||
#define ZR_CLASS_FLAG_HEALTH_REGEN_AMOUNT (1<<13)
|
||||
#define ZR_CLASS_FLAG_INFECT_GAIN (1<<14)
|
||||
#define ZR_CLASS_FLAG_KILL_BONUS (1<<15)
|
||||
#define ZR_CLASS_FLAG_SPEED (1<<16)
|
||||
#define ZR_CLASS_FLAG_KNOCKBACK (1<<17)
|
||||
#define ZR_CLASS_FLAG_JUMP_HEIGHT (1<<18)
|
||||
#define ZR_CLASS_FLAG_JUMP_DISTANCE (1<<19)
|
||||
#define ZR_CLASS_FLAG_ENABLED (1<<0)
|
||||
#define ZR_CLASS_FLAG_TEAM (1<<1)
|
||||
#define ZR_CLASS_FLAG_TEAM_DEFAULT (1<<2)
|
||||
#define ZR_CLASS_FLAG_NAME (1<<3)
|
||||
#define ZR_CLASS_FLAG_DESCRIPTION (1<<4)
|
||||
#define ZR_CLASS_FLAG_MODEL_PATH (1<<5)
|
||||
#define ZR_CLASS_FLAG_ALPHA_INITIAL (1<<6)
|
||||
#define ZR_CLASS_FLAG_ALPHA_DAMAGED (1<<7)
|
||||
#define ZR_CLASS_FLAG_ALPHA_DAMAGE (1<<8)
|
||||
#define ZR_CLASS_FLAG_OVERLAY_PATH (1<<9)
|
||||
#define ZR_CLASS_FLAG_NVGS (1<<10)
|
||||
#define ZR_CLASS_FLAG_FOV (1<<11)
|
||||
#define ZR_CLASS_FLAG_NAPALM_TIME (1<<12)
|
||||
#define ZR_CLASS_FLAG_IMMUNITY_MODE (1<<13)
|
||||
#define ZR_CLASS_FLAG_IMMUNITY_AMOUNT (1<<14)
|
||||
#define ZR_CLASS_FLAG_NO_FALL_DAMAGE (1<<15)
|
||||
#define ZR_CLASS_FLAG_HEALTH (1<<16)
|
||||
#define ZR_CLASS_FLAG_HEALTH_REGEN_INTERVAL (1<<17)
|
||||
#define ZR_CLASS_FLAG_HEALTH_REGEN_AMOUNT (1<<18)
|
||||
#define ZR_CLASS_FLAG_HEALTH_INFECT_GAIN (1<<19)
|
||||
#define ZR_CLASS_FLAG_KILL_BONUS (1<<20)
|
||||
#define ZR_CLASS_FLAG_SPEED (1<<21)
|
||||
#define ZR_CLASS_FLAG_KNOCKBACK (1<<22)
|
||||
#define ZR_CLASS_FLAG_JUMP_HEIGHT (1<<23)
|
||||
#define ZR_CLASS_FLAG_JUMP_DISTANCE (1<<24)
|
||||
/**
|
||||
* @endsection
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Generic player attributes.
|
||||
*/
|
||||
|
@ -231,7 +235,19 @@ enum ClassAttributes
|
|||
Float:class_speed,
|
||||
Float:class_knockback,
|
||||
Float:class_jump_height,
|
||||
Float:class_jump_distance,
|
||||
Float:class_jump_distance
|
||||
}
|
||||
|
||||
/**
|
||||
* Data types used in class attributes.
|
||||
*/
|
||||
enum ClassDataTypes
|
||||
{
|
||||
ClassDataType_InvalidType, /** Invalid type */
|
||||
ClassDataType_Boolean, /** Boolean value */
|
||||
ClassDataType_Integer, /** Integer value */
|
||||
ClassDataType_Float, /** Floating point value */
|
||||
ClassDataType_String /** String value */
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -264,6 +280,12 @@ new ClassPlayerCache[MAXPLAYERS + 1][ClassAttributes];
|
|||
*/
|
||||
new ClassCount;
|
||||
|
||||
/**
|
||||
* Specifies wether the class team requirement and attributes are valid or not.
|
||||
* Used to block events that happend before the module is done loading.
|
||||
*/
|
||||
new bool:ClassValidated;
|
||||
|
||||
/**
|
||||
* Stores what class that the player have selected, for each team.
|
||||
*/
|
||||
|
@ -300,6 +322,9 @@ new ClassPlayerNextAdminClass[MAXPLAYERS + 1];
|
|||
*/
|
||||
ClassLoad()
|
||||
{
|
||||
// Initialize log boolean.
|
||||
new bool:enablelog = LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_WEAPONS);
|
||||
|
||||
// Make sure kvClassData is ready to use.
|
||||
if (kvClassData != INVALID_HANDLE)
|
||||
{
|
||||
|
@ -314,15 +339,17 @@ ClassLoad()
|
|||
// If file doesn't exist, then log and stop.
|
||||
if (!exists)
|
||||
{
|
||||
// Log failure.
|
||||
if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_WEAPONS))
|
||||
{
|
||||
LogMessageFormatted(-1, "Classes", "Config Validation", "Missing playerclasses config file: %s", LOG_FORMAT_TYPE_FATALERROR, pathclasses);
|
||||
}
|
||||
LogMessageFormatted(-1, "Classes", "Load", "Fatal error: Missing playerclasses config file \"%s\"", LOG_FORMAT_TYPE_FATALERROR, pathclasses);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Log what class file that is loaded.
|
||||
if (enablelog)
|
||||
{
|
||||
LogMessageFormatted(-1, "Classes", "Load", "Loading classes from file \"%s\".", LOG_FORMAT_TYPE_SIMPLE, pathclasses);
|
||||
}
|
||||
|
||||
// Put file data into memory.
|
||||
FileToKeyValues(kvClassData, pathclasses);
|
||||
|
||||
|
@ -330,7 +357,7 @@ ClassLoad()
|
|||
KvRewind(kvClassData);
|
||||
if (!KvGotoFirstSubKey(kvClassData))
|
||||
{
|
||||
LogMessageFormatted(-1, "Classes", "Config Validation", "Can't find any classes in %s", LOG_FORMAT_TYPE_FATALERROR, pathclasses);
|
||||
LogMessageFormatted(-1, "Classes", "Load", "Fatal error: Can't find any classes in \"%s\"", LOG_FORMAT_TYPE_FATALERROR, pathclasses);
|
||||
}
|
||||
|
||||
decl String:name[64];
|
||||
|
@ -339,6 +366,7 @@ ClassLoad()
|
|||
decl String:overlay_path[PLATFORM_MAX_PATH];
|
||||
|
||||
ClassCount = 0;
|
||||
new failedcount;
|
||||
new ClassErrorFlags;
|
||||
|
||||
// Loop through all classes and store attributes in the ClassData array.
|
||||
|
@ -347,7 +375,7 @@ ClassLoad()
|
|||
if (ClassCount > ZR_CLASS_MAX)
|
||||
{
|
||||
// Maximum classes reached. Write a warning and exit the loop.
|
||||
if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_CLASSES))
|
||||
if (enablelog)
|
||||
{
|
||||
LogMessageFormatted(-1, "Classes", "Load", "Warning: Maximum classes reached (%d). Skipping other classes.", _, ZR_CLASS_MAX + 1);
|
||||
}
|
||||
|
@ -411,10 +439,12 @@ ClassLoad()
|
|||
// There's one or more invalid class attributes. Disable the class
|
||||
// and log an error message.
|
||||
ClassData[ClassCount][class_enabled] = false;
|
||||
if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_CLASSES))
|
||||
if (enablelog)
|
||||
{
|
||||
LogMessageFormatted(-1, "Classes", "Config Validation", "Warning: Invalid class at index %d, disabled class. Class error flags: %d.", LOG_FORMAT_TYPE_ERROR, ClassCount, ClassErrorFlags);
|
||||
}
|
||||
|
||||
failedcount++;
|
||||
}
|
||||
|
||||
// Update the counter.
|
||||
|
@ -424,17 +454,26 @@ ClassLoad()
|
|||
// Validate team requirements.
|
||||
if (!ClassValidateTeamRequirements())
|
||||
{
|
||||
LogMessageFormatted(-1, "Classes", "Config Validation", "The class configuration doesn't match the team requirements.", LOG_FORMAT_TYPE_FATALERROR);
|
||||
LogMessageFormatted(-1, "Classes", "Config Validation", "Fatal error: The class configuration doesn't match the team requirements.", LOG_FORMAT_TYPE_FATALERROR);
|
||||
}
|
||||
|
||||
// Validate team default requirements.
|
||||
if (!ClassValidateTeamDefaults())
|
||||
{
|
||||
LogMessageFormatted(-1, "Classes", "Config Validation", "Couldn't find a default class for one or more teams. At least one class per team must be marked as default.", LOG_FORMAT_TYPE_FATALERROR);
|
||||
LogMessageFormatted(-1, "Classes", "Config Validation", "Fatal error: Couldn't find a default class for one or more teams. At least one class per team must be marked as default.", LOG_FORMAT_TYPE_FATALERROR);
|
||||
}
|
||||
|
||||
// Cache class data.
|
||||
ClassReloadDataCache();
|
||||
|
||||
// Mark classes as valid.
|
||||
ClassValidated = true;
|
||||
|
||||
// Log summary.
|
||||
if (enablelog)
|
||||
{
|
||||
LogMessageFormatted(-1, "Classes", "Config Validation", "Total: %d | Successful: %d | Unsuccessful: %d", _, ClassCount, ClassCount - failedcount, failedcount);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -57,6 +57,9 @@ bool:AmbientSoundsValidateConfig()
|
|||
return false;
|
||||
}
|
||||
|
||||
// Initialize log boolean.
|
||||
new bool:enablelog = LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_AMBIENTSOUNDS);
|
||||
|
||||
// Get ambient sound file.
|
||||
decl String:sound[SOUND_MAX_PATH];
|
||||
GetConVarString(g_hCvarsList[CVAR_AMBIENTSOUNDS_FILE], sound, sizeof(sound));
|
||||
|
@ -66,7 +69,7 @@ bool:AmbientSoundsValidateConfig()
|
|||
if (!FileExists(sound, true))
|
||||
{
|
||||
// Log invalid sound file error.
|
||||
if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_AMBIENTSOUNDS))
|
||||
if (enablelog)
|
||||
{
|
||||
LogMessageFormatted(-1, "Ambient Sounds", "Config Validation", "Invalid sound file specified in zr_ambientsounds_file.", LOG_FORMAT_TYPE_ERROR);
|
||||
}
|
||||
|
@ -79,7 +82,7 @@ bool:AmbientSoundsValidateConfig()
|
|||
if (ambientvolume <= 0.0)
|
||||
{
|
||||
// Log invalid ambient sound volume error.
|
||||
if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_AMBIENTSOUNDS))
|
||||
if (enablelog)
|
||||
{
|
||||
LogMessageFormatted(-1, "Ambient Sounds", "Config Validation", "Ambient sound is either muted or invalid.", LOG_FORMAT_TYPE_ERROR);
|
||||
}
|
||||
|
@ -92,9 +95,9 @@ bool:AmbientSoundsValidateConfig()
|
|||
if (ambientlength <= 0.0)
|
||||
{
|
||||
// Log invalid ambient sound length error.
|
||||
if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_AMBIENTSOUNDS))
|
||||
if (enablelog)
|
||||
{
|
||||
LogMessageFormatted(-1, "Ambient Sounds", "Config Validation", "Ambient sound length is invalid.", LOG_FORMAT_TYPE_ERROR);
|
||||
LogMessageFormatted(-1, "Ambient Sounds", "Config Validation", "Specified ambient sound length is invalid.", LOG_FORMAT_TYPE_ERROR);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
@ -36,6 +36,12 @@ ZSpawnOnMapStart()
|
|||
*/
|
||||
ZSpawnOnClientDisconnect(client)
|
||||
{
|
||||
// Check if client is a bot.
|
||||
if (IsFakeClient(client))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Get client's unique serial number.
|
||||
new serial = GetClientSerial(client);
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user