From 32c2f0a0676d3c8285b59a39e0add75cc1133350 Mon Sep 17 00:00:00 2001 From: richard Date: Mon, 6 Apr 2009 03:30:27 +0200 Subject: [PATCH 1/4] Changed branch to zr-3.0.0-dev (development branch). From cdc52e4b67b85a32f8885dd18e9ade5b5a4fa494 Mon Sep 17 00:00:00 2001 From: richard Date: Mon, 6 Apr 2009 03:36:03 +0200 Subject: [PATCH 2/4] Removed other plugins from the repository that doesn't belong here. --- src/zr_ammo.sp | 62 --------------------------------------------- src/zr_hitsounds.sp | 59 ------------------------------------------ src/zr_info.sp | 52 ------------------------------------- 3 files changed, 173 deletions(-) delete mode 100644 src/zr_ammo.sp delete mode 100644 src/zr_hitsounds.sp delete mode 100644 src/zr_info.sp diff --git a/src/zr_ammo.sp b/src/zr_ammo.sp deleted file mode 100644 index b42c6d7..0000000 --- a/src/zr_ammo.sp +++ /dev/null @@ -1,62 +0,0 @@ - -#include - -/* -thx to Infinite Ammo by twistedeuphoria - http://forums.alliedmods.net/showthread.php?t=55381 -*/ - -public Plugin:myinfo = { - name = "Ammo Script for Zombie:Reloaded", - author = "[SG-10]Cpt.Moore", - description = "", - version = "1.0", - url = "http://jupiter.swissquake.ch/zombie/page" -}; - -new activeOffset = -1; -new clip1Offset = -1; -new clip2Offset = -1; -new secAmmoTypeOffset = -1; -new priAmmoTypeOffset = -1; - -// native hooks - -public OnPluginStart() -{ - HookEvent("weapon_fire", Event_WeaponFire); - activeOffset = FindSendPropOffs("CAI_BaseNPC", "m_hActiveWeapon"); - - clip1Offset = FindSendPropOffs("CBaseCombatWeapon", "m_iClip1"); - clip2Offset = FindSendPropOffs("CBaseCombatWeapon", "m_iClip2"); - - priAmmoTypeOffset = FindSendPropOffs("CBaseCombatWeapon", "m_iPrimaryAmmoCount"); - secAmmoTypeOffset = FindSendPropOffs("CBaseCombatWeapon", "m_iSecondaryAmmoCount"); -} - -// event hooks - -public Event_WeaponFire(Handle:event, const String:name[], bool:dontBroadcast) -{ - new userid = GetEventInt(event, "userid"); - new client = GetClientOfUserId(userid); - if(!IsFakeClient(client)) - { - Client_ResetAmmo(client); - } -} - -// helpers - -public Client_ResetAmmo(client) -{ - new zomg = GetEntDataEnt(client, activeOffset); - if (clip1Offset != -1) - SetEntData(zomg, clip1Offset, 104, 4, true); - if (clip2Offset != -1) - SetEntData(zomg, clip2Offset, 104, 4, true); - if (priAmmoTypeOffset != -1) - SetEntData(zomg, priAmmoTypeOffset, 200, 4, true); - if (secAmmoTypeOffset != -1) - SetEntData(zomg, secAmmoTypeOffset, 200, 4, true); -} - diff --git a/src/zr_hitsounds.sp b/src/zr_hitsounds.sp deleted file mode 100644 index 88b4c7b..0000000 --- a/src/zr_hitsounds.sp +++ /dev/null @@ -1,59 +0,0 @@ - -#include -#include - -public Plugin:myinfo = { - name = "Hit Sounds for Zombie:Reloaded", - author = "[SG-10]Cpt.Moore", - description = "", - version = "1.0", - url = "http://zombie.swissquake.ch/" -}; - -static const String:hit_head[] = {"hit_head.wav"}; -static const String:hit_body[] = {"hit_body.wav"}; - -// native hooks -public OnPluginStart() -{ - HookEvent("player_hurt", Event_PlayerHurt); - LoadSound(hit_head); - LoadSound(hit_body); -} - -public OnMapStart() -{ - LoadSound(hit_head); - LoadSound(hit_body); -} - -public Event_PlayerHurt(Handle:event, const String:name[], bool:dontBroadcast) -{ - new attackerId = GetEventInt(event, "attacker"); - new attacker = GetClientOfUserId(attackerId); - //new damage = GetEventInt(event, "dmg_health"); - new hitgroup = GetEventInt(event,"hitgroup"); - - if( attacker > 0 && !IsFakeClient(attacker) ) - { - if ( hitgroup == 1 ) - { - EmitSoundToClient(attacker, hit_head); - } - else - { - EmitSoundToClient(attacker, hit_body); - } - } -} - -// utility functions - -public LoadSound(const String:sound_file[]) -{ - new String:sound_path[PLATFORM_MAX_PATH]; - Format(sound_path, sizeof(sound_path), "sound/%s", sound_file); - PrecacheSound(sound_file, true); - AddFileToDownloadsTable(sound_path); -} - diff --git a/src/zr_info.sp b/src/zr_info.sp deleted file mode 100644 index 144b6f6..0000000 --- a/src/zr_info.sp +++ /dev/null @@ -1,52 +0,0 @@ - -#include - -public Plugin:myinfo = { - name = "Info Script for Zombie:Reloaded", - author = "[SG-10]Cpt.Moore", - description = "", - version = "1.0", - url = "http://zombie.swissquake.ch/" -}; - -public OnPluginStart() -{ - RegConsoleCmd("sm_show_cvar", Command_Show_CVar); -} - -new String:g_sCVar[128]; -new String:g_sCVarValue[128]; -new Handle:g_hCVar; - -public Action:Command_Show_CVar(client,args) -{ - GetCmdArgString(g_sCVar,sizeof(g_sCVar)); - - g_hCVar = FindConVar(g_sCVar); - if (g_hCVar != INVALID_HANDLE) - { //not found - GetConVarString(g_hCVar, g_sCVarValue, sizeof(g_sCVarValue)); - if (client == 0) - { - PrintToServer("\"%s\" = \"%s\"", g_sCVar, g_sCVarValue); - } - else - { - PrintToConsole(client, "\"%s\" = \"%s\"", g_sCVar, g_sCVarValue); - } - } - else - { //found - if (client == 0) - { - PrintToServer("Couldn't find %s", g_sCVar); - } - else - { - PrintToConsole(client,"Couldn't find %s", g_sCVar); - } - } - - return Plugin_Handled; -} - From 907788e36a3535433514098d510939c37f8f51c7 Mon Sep 17 00:00:00 2001 From: richard Date: Tue, 7 Apr 2009 02:13:25 +0200 Subject: [PATCH 3/4] Finished functions for applying class attributes. --- src/zr/ambience.inc | 2 + src/zr/playerclasses/apply.inc | 181 +++++++++++++++++++++++++ src/zr/playerclasses/attributes.inc | 2 +- src/zr/playerclasses/healthregen.inc | 66 +++++++++ src/zr/playerclasses/playerclasses.inc | 1 + 5 files changed, 251 insertions(+), 1 deletion(-) create mode 100644 src/zr/playerclasses/healthregen.inc diff --git a/src/zr/ambience.inc b/src/zr/ambience.inc index bd59d0e..2056350 100644 --- a/src/zr/ambience.inc +++ b/src/zr/ambience.inc @@ -6,6 +6,8 @@ * ==================== */ +// TODO: Move skybox and lightning functions into this file. + new bool:AmbienceLoaded = false; new String:AmbienceSound[64]; new Float:AmbienceVolume; diff --git a/src/zr/playerclasses/apply.inc b/src/zr/playerclasses/apply.inc index 6a56004..5043268 100644 --- a/src/zr/playerclasses/apply.inc +++ b/src/zr/playerclasses/apply.inc @@ -32,6 +32,11 @@ bool:ClassApplyAttributes(client, bool:improved = false) ClassApplyModel(client, classindex); ClassApplyAlpha(client, classindex); ClassApplyOverlay(client, classindex); + ClassApplyNightVision(client, classindex); + ClassApplyFOV(client, classindex); + ClassApplyHealth(client, classindex, improved); + ClassApplyHealthRegen(client, classindex); + ClassApplySpeed(client, classindex); } /** @@ -145,3 +150,179 @@ bool:ClassApplyOverlay(client, classindex, cachetype = ZR_CLASS_CACHE_PLAYER) ClassOverlayInitialize(client, overlay); return true; } + +/** + * Gives night vision to a player. + * + * @param client The client index. + * @param classindex The class to read from. + * @param cachetype Optional. Specifies what class cache to read from. + * Options: + * ZR_CLASS_CACHE_ORIGINAL - Unchanced class data. + * ZR_CLASS_CACHE_MODIFIED - Changed/newest class data. + * ZR_CLASS_CACHE_PLAYER (default) - Player cache. + * @return True on success, false otherwise. + */ +bool:ClassApplyNightVision(client, classindex, cachetype = ZR_CLASS_CACHE_PLAYER) +{ + new bool:nvgs; + + // Get the night vision setting from the specified cache. + if (cachetype == ZR_CLASS_CACHE_PLAYER) + { + nvgs = ClassGetNvgs(client, cachetype); + } + else + { + nvgs = ClassGetNvgs(classindex, cachetype); + } + + NightVision(client, nvgs); + + // Turn on night vision if applied. + if (nvgs) + { + NightVisionOn(client, nvgs); + } + return true; +} + +/** + * Sets the field of view setting on a player. + * + * @param client The client index. + * @param classindex The class to read from. + * @param cachetype Optional. Specifies what class cache to read from. + * Options: + * ZR_CLASS_CACHE_ORIGINAL - Unchanced class data. + * ZR_CLASS_CACHE_MODIFIED - Changed/newest class data. + * ZR_CLASS_CACHE_PLAYER (default) - Player cache. + * @return True on success, false otherwise. + */ +bool:ClassApplyFOV(client, classindex, cachetype = ZR_CLASS_CACHE_PLAYER) +{ + new fov; + + // Get the field of view setting from the specified cache. + if (cachetype == ZR_CLASS_CACHE_PLAYER) + { + fov = ClassGetFOV(client, cachetype); + } + else + { + fov = ClassGetFOV(classindex, cachetype); + } + + SetPlayerFOV(client, fov); + return true; +} + +/** + * Gives health points on a player. + * + * @param client The client index. + * @param classindex The class to read from. + * @param boost Double health boost. Default: false + * @param cachetype Optional. Specifies what class cache to read from. + * Options: + * ZR_CLASS_CACHE_ORIGINAL - Unchanced class data. + * ZR_CLASS_CACHE_MODIFIED - Changed/newest class data. + * ZR_CLASS_CACHE_PLAYER (default) - Player cache. + * @return True on success, false otherwise. + */ +bool:ClassApplyHealth(client, classindex, bool:boost = false, cachetype = ZR_CLASS_CACHE_PLAYER) +{ + new health; + + // Get the health points from the specified cache. + if (cachetype == ZR_CLASS_CACHE_PLAYER) + { + health = ClassGetHealth(client, cachetype); + } + else + { + health = ClassGetHealth(classindex, cachetype); + } + + if (boost) + { + health *= 2; + } + + SetEntityHealth(client, health); + return true; +} + +/** + * Applies health regeneration on a player if enabled. + * + * @param client The client index. + * @param classindex The class to read from. + * @param boost Double health boost. Default: false + * @param cachetype Optional. Specifies what class cache to read from. + * Options: + * ZR_CLASS_CACHE_ORIGINAL - Unchanced class data. + * ZR_CLASS_CACHE_MODIFIED - Changed/newest class data. + * ZR_CLASS_CACHE_PLAYER (default) - Player cache. + * @return True if applied, false otherwise. + */ +bool:ClassApplyHealthRegen(client, classindex, cachetype = ZR_CLASS_CACHE_PLAYER) +{ + new Float:interval; + new amount; + new max; + + // Get the health regeneration info from the specified cache. + if (cachetype == ZR_CLASS_CACHE_PLAYER) + { + interval = ClassGetHealthRegenInterval(client, cachetype); + amount = ClassGetHealthRegenAmount(client, cachetype); + max = ClassGetHealth(client, cachetype); + } + else + { + interval = ClassGetHealthRegenInterval(classindex, cachetype); + amount = ClassGetHealthRegenAmount(classindex, cachetype); + max = ClassGetHealth(classindex, cachetype); + } + + if (interval > 0) + { + ClassHealthRegenInitialize(client, interval, amount, max); + return true; + } + else + { + return false; + } +} + +/** + * Sets the players speed. + * + * @param client The client index. + * @param classindex The class to read from. + * @param cachetype Optional. Specifies what class cache to read from. + * Options: + * ZR_CLASS_CACHE_ORIGINAL - Unchanced class data. + * ZR_CLASS_CACHE_MODIFIED - Changed/newest class data. + * ZR_CLASS_CACHE_PLAYER (default) - Player cache. + * @return True on success, false otherwise. + */ +bool:ClassApplySpeed(client, classindex, cachetype = ZR_CLASS_CACHE_PLAYER) +{ + new speed; + + // Get the health points from the specified cache. + if (cachetype == ZR_CLASS_CACHE_PLAYER) + { + speed = ClassGetSpeed(client, cachetype); + } + else + { + speed = ClassGetSpeed(classindex, cachetype); + } + + SetPlayerSpeed(client, speed); + return true; +} diff --git a/src/zr/playerclasses/attributes.inc b/src/zr/playerclasses/attributes.inc index a6400e5..4927837 100644 --- a/src/zr/playerclasses/attributes.inc +++ b/src/zr/playerclasses/attributes.inc @@ -384,7 +384,7 @@ ClassGetOverlayPath(index, String:buffer[], maxlen, cachetype = ZR_CLASS_CACHE_P * is used, index will be used as a client index. * @return The night vision setting from the specified class. False on error. */ -bool:ClassGetNVGs(index, cachetype = ZR_CLASS_CACHE_PLAYER) +bool:ClassGetNvgs(index, cachetype = ZR_CLASS_CACHE_PLAYER) { switch (cachetype) { diff --git a/src/zr/playerclasses/healthregen.inc b/src/zr/playerclasses/healthregen.inc new file mode 100644 index 0000000..84ccee6 --- /dev/null +++ b/src/zr/playerclasses/healthregen.inc @@ -0,0 +1,66 @@ +/* + * ============================================================================ + * + * Zombie:Reloaded + * + * File: healthregen.inc + * Description: Functions for managing health regeneration on a client. + * Author: Richard Helgeby + * + * ============================================================================ + */ + +new ClientHealthRegenAmount[MAXPLAYERS + 1]; +new ClientHealthRegenMax[MAXPLAYERS + 1]; +new Handle:tHealthRegen[MAXPLAYERS + 1] = {INVALID_HANDLE, ...}; + +ClassHealthRegenInitialize(client, Float:interval, amount, max) +{ + ClientHealthRegenAmount[client] = amount; + ClientHealthRegenMax[client] = max; + ClassHealthRegenStart(client, interval); +} + +ClassHealthRegenStart(client, Float:interval) +{ + // Kill the timer if it exist. + if (tHealthRegen[client] != INVALID_HANDLE) + { + KillTimer(tHealthRegen[client]); + tHealthRegen[client] = INVALID_HANDLE; + } + + tHealthRegen[client] = CreateTimer(interval, ClassHealthRegenTimer, client, TIMER_REPEAT); +} + +ClassHealthRegenStop(client) +{ + // Kill the timer if it exist. + if (tHealthRegen[client] != INVALID_HANDLE) + { + KillTimer(tHealthRegen[client]); + tHealthRegen[client] = INVALID_HANDLE; + } +} + +public Action:ClassHealthRegenTimer(Handle:timer, any:client) +{ + // Kill the timer if the player is dead. + if (!IsPlayerAlive(client)) + { + tHealthRegen[client] = INVALID_HANDLE; + return Plugin_Stop; + } + + new health = GetClientHealth(client); + health += ClientHealthRegenAmount[client]; + + // Check if the health points is below the limit. + if (health < ClientHealthRegenMax[client]) + { + // Increase health. + SetEntityHealth(client, health); + } + + return Plugin_Continue; +} \ No newline at end of file diff --git a/src/zr/playerclasses/playerclasses.inc b/src/zr/playerclasses/playerclasses.inc index 02af8a6..7b0b148 100644 --- a/src/zr/playerclasses/playerclasses.inc +++ b/src/zr/playerclasses/playerclasses.inc @@ -208,6 +208,7 @@ new ClassActive[MAXPLAYERS + 1][ZR_CLASS_TEAMCOUNT - 1]; #include "zr/playerclasses/attributes" #include "zr/playerclasses/apply" #include "zr/playerclasses/clientoverlays" +#include "zr/playerclasses/healthregen" /** * Loads class attributes from playerclasses.txt into the ClassData array. If From d3b51c1b1a257e72193c4edbdd99943535eaeef6 Mon Sep 17 00:00:00 2001 From: richard Date: Tue, 7 Apr 2009 04:44:37 +0200 Subject: [PATCH 4/4] Added validation on class attributes. Some attributes still aren't validated because of unknown limits. --- src/zr/playerclasses/apply.inc | 2 + src/zr/playerclasses/filtertools.inc | 140 +++++++++++++++++++++++-- src/zr/playerclasses/playerclasses.inc | 50 +++++++-- 3 files changed, 172 insertions(+), 20 deletions(-) diff --git a/src/zr/playerclasses/apply.inc b/src/zr/playerclasses/apply.inc index 5043268..6934400 100644 --- a/src/zr/playerclasses/apply.inc +++ b/src/zr/playerclasses/apply.inc @@ -74,6 +74,8 @@ bool:ClassApplyModel(client, classindex, cachetpye = ZR_CLASS_CACHE_PLAYER) Format(modelpath, sizeof(modelpath), "%s.mdl", modelpath); } + // TODO: Add support for keeping the default cs model ("default"). + SetPlayerModel(client, modelpath); return true; } diff --git a/src/zr/playerclasses/filtertools.inc b/src/zr/playerclasses/filtertools.inc index e05daae..fa7b7bf 100644 --- a/src/zr/playerclasses/filtertools.inc +++ b/src/zr/playerclasses/filtertools.inc @@ -45,15 +45,138 @@ bool:ClassValidateTeamRequirements(cachetype = ZR_CLASS_CACHE_ORIGINAL) /** * Validates all the class attributes in the original class data array, to - * check if they have invalid values. + * check if they have invalid values. Boolean settings are not validated. * * @param classindex The index of the class to validate. - * @return True if validation was successful, false otherwise. + * @return A value with attribute error flags. */ -bool:ClassValidateAttributes(classindex) +ClassValidateAttributes(classindex) { - return true; - // TODO: Manually check each attribute (hard coded). Better solutions? + // TODO: Validate immunity mode and amount. + // TODO: Validate jump values. + + new flags; + + // Name. + if (strlen(ClassData[classindex][class_name]) == 0) + { + flags += ZR_CLASS_ATTRIB_ERR_NAME; + } + + // Description. + if (strlen(ClassData[classindex][class_description]) == 0) + { + flags += ZR_CLASS_ATTRIB_ERR_DESCRIPTION; + } + + // Model path. + decl String:model_path[256]; + if (strcopy(model_path, sizeof(model_path), ClassData[classindex][class_model_path]) == 0) + { + flags += ZR_CLASS_ATTRIB_ERR_MODEL_PATH; + } + else + { + // Check if default or random model is specified. + if (strcmp(model_path, "random", false) != 0 && strcmp(model_path, "default", false) != 0) + { + // Check if the file exists. + if (!FileExists(model_path)) + { + flags += ZR_CLASS_ATTRIB_ERR_MODEL_PATH; + } + } + } + + // Alpha, initial. + new alpha_initial = ClassData[classindex][class_alpha_initial]; + if (!(alpha_initial >= 0 && alpha_initial <= 255)) + { + flags += ZR_CLASS_ATTRIB_ERR_ALPHA_INITIAL; + } + + // Alpha, damaged. + new alpha_damaged = ClassData[classindex][class_alpha_damaged]; + if (!(alpha_damaged >= 0 && alpha_damaged <= 255)) + { + flags += ZR_CLASS_ATTRIB_ERR_ALPHA_DAMAGED; + } + + // Alpha, damage. + new alpha_damage = ClassData[classindex][class_alpha_damage]; + if (!(alpha_damage >= 0 && alpha_damage <= 65536)) + { + flags += ZR_CLASS_ATTRIB_ERR_ALPHA_DAMAGE; + } + + // Overlay path. + decl String:overlay_path[256]; + if (strcopy(overlay_path, sizeof(overlay_path), ClassData[classindex][class_overlay_path]) != 0) + { + // Check if the file exists. + if (!FileExists(overlay_path)) + { + flags += ZR_CLASS_ATTRIB_ERR_OVERLAY_PATH; + } + } + + // Field of view. + new fov = ClassData[classindex][class_fov]; + if (!(fov > 15 && fov < 180)) + { + flags += ZR_CLASS_ATTRIB_ERR_FOV; + } + + // Napalm time. + new Float:napalm_time = ClassData[classindex][class_napalm_time]; + if (!(napalm_time >= 0.0 && napalm_time <= 900.0)) + { + flags += ZR_CLASS_ATTRIB_ERR_NAPALM_TIME; + } + + // Health regen interval. + new Float:regen_interval = ClassData[classindex][class_health_regen_interval]; + if (!(regen_interval >= 0.0 && regen_interval <= 900.0)) + { + flags += ZR_CLASS_ATTRIB_ERR_HEALTH_REGEN_INTERVAL; + } + + // Health regen amount. + new regen_amount = ClassData[classindex][class_health_regen_amount]; + if (!(regen_amount > 0 && regen_amount <= 65536)) + { + flags += ZR_CLASS_ATTRIB_ERR_HEALTH_REGEN_AMOUNT; + } + + // Health infect gain. + new infect_gain = ClassData[classindex][class_health_infect_gain]; + if (!(infect_gain >= 0 && infect_gain <= 65536)) + { + flags += ZR_CLASS_ATTRIB_ERR_INFECT_GAIN; + } + + // Kill bonus. + new kill_bonus = ClassData[classindex][class_kill_bonus]; + if (!(kill_bonus >= 0 && kill_bonus <= 128)) + { + flags += ZR_CLASS_ATTRIB_ERR_KILL_BONUS; + } + + // Speed. + new Float:speed = ClassData[classindex][class_speed]; + if (!(speed >= 0.0 && speed <= 1024.0)) + { + flags += ZR_CLASS_ATTRIB_ERR_SPEED; + } + + // Knockback. + new Float:knockback = ClassData[classindex][class_knockback]; + if (!(knockback >= -10.0 && knockback <= 50.0)) + { + flags += ZR_CLASS_ATTRIB_ERR_KNOCKBACK; + } + + return flags; } /** @@ -65,12 +188,7 @@ bool:ClassValidateAttributes(classindex) */ bool:ClassValidateIndex(classindex) { - if (ClassCount == 0) - { - return false; - } - - if (classindex >= 0 && classid < ClassCount) + if (classindex >= 0 && classindex < ClassCount) { return true; } diff --git a/src/zr/playerclasses/playerclasses.inc b/src/zr/playerclasses/playerclasses.inc index 7b0b148..2509331 100644 --- a/src/zr/playerclasses/playerclasses.inc +++ b/src/zr/playerclasses/playerclasses.inc @@ -129,6 +129,34 @@ * @endsection */ +/** + * @section Error flags for invalid class attributes. + */ +#define ZR_CLASS_ATTRIB_ERR_OK 0 +#define ZR_CLASS_ATTRIB_ERR_NAME 1 +#define ZR_CLASS_ATTRIB_ERR_DESCRIPTION 2 +#define ZR_CLASS_ATTRIB_ERR_MODEL_PATH 4 +#define ZR_CLASS_ATTRIB_ERR_ALPHA_INITIAL 8 +#define ZR_CLASS_ATTRIB_ERR_ALPHA_DAMAGED 16 +#define ZR_CLASS_ATTRIB_ERR_ALPHA_DAMAGE 32 +#define ZR_CLASS_ATTRIB_ERR_OVERLAY_PATH 64 +#define ZR_CLASS_ATTRIB_ERR_FOV 128 +#define ZR_CLASS_ATTRIB_ERR_NAPALM_TIME 256 +#define ZR_CLASS_ATTRIB_ERR_IMMUNITY_MODE 512 +#define ZR_CLASS_ATTRIB_ERR_IMMUNITY_AMOUNT 1024 +#define ZR_CLASS_ATTRIB_ERR_HEALTH_REGEN_INTERVAL 2048 +#define ZR_CLASS_ATTRIB_ERR_HEALTH_REGEN_AMOUNT 4096 +#define ZR_CLASS_ATTRIB_ERR_INFECT_GAIN 8192 +#define ZR_CLASS_ATTRIB_ERR_KILL_BONUS 16384 +#define ZR_CLASS_ATTRIB_ERR_SPEED 32768 +#define ZR_CLASS_ATTRIB_ERR_KNOCKBACK 65536 +#define ZR_CLASS_ATTRIB_ERR_JUMP_HEIGHT 131072 +#define ZR_CLASS_ATTRIB_ERR_JUMP_DISTANCE 262144 +/** + * @endsection + */ + + /** * Generic player attributes. */ @@ -249,6 +277,7 @@ ClassLoad(const String:classfile[256] = "configs/zr/playerclasses.txt") decl String:overlay_path[256]; ClassCount = 0; + new ClassErrorFlags; // Loop through all classes and store attributes in the ClassData array. do @@ -313,17 +342,20 @@ ClassLoad(const String:classfile[256] = "configs/zr/playerclasses.txt") ClassData[ClassCount][class_jump_distance] = KvGetFloat(kvClassData, "jump_distance", ZR_CLASS_DEFAULT_JUMP_DISTANCE); // Validate the class attributes. - if (!ClassValidateAttributes(ClassCount)) + ClassErrorFlags = ClassValidateAttributes(ClassCount); + if (ClassErrorFlags > 0) { - // TODO: There's an invalid class, what do we do? - // Skip it (clearing data too), disable it and give a log warning, - // or set the plugin in a failed state? - } - else - { - // The class is valid. Update the counter. - ClassCount++; + // There's one or more invalid class attributes. Disable the class + // and log an error message. + ClassData[ClassCount][class_enabled] = false; + if (LogFlagCheck(LOG_CORE_EVENTS, LOG_MODULE_CLASSES)) + { + ZR_LogMessageFormatted(-1, "classes", "load", "Invalid class at index %d. Class error flags: %d.", LOG_FORMAT_TYPE_ERROR, ClassCount, ClassErrorFlags); + } } + + // Update the counter. + ClassCount++; } while (KvGotoNextKey(kvClassData)); // Validate team requirements.