diff --git a/cstrike/addons/sourcemod/configs/zr/playerclasses.txt b/cstrike/addons/sourcemod/configs/zr/playerclasses.txt index 3ba0449..7bb150d 100644 --- a/cstrike/addons/sourcemod/configs/zr/playerclasses.txt +++ b/cstrike/addons/sourcemod/configs/zr/playerclasses.txt @@ -12,11 +12,15 @@ // Attribute: Values: Description: // ---------------------------------------------------------------------------- // enabled 0/1 Enables or disables a class. -// team number Specifies what type of class it is: +// team number Specifies what team the class belongs to: // 0 - Zombies // 1 - Humans -// 2 - Admins only (incomplete feature!) +// 2 - Admin mode classes (incomplete feautre!) // team_default 0/1 Marks the class as the default class in the team. +// flags number Special class flags (bit field). To combine multiple flags +// use a sum of the flag values. Available flags: +// 1 - Admins only +// 2 - Mother zombies only // name text The class name used in class menu. // description text The class description used in class menu. // model_path text Path to model to use. Relative to cstrike folder. @@ -26,7 +30,7 @@ // overlay_path text Overlay displayed at the player. // nvgs 0/1 Give night vision. // fov number Field of view value. 90 is default. -// has_napalm 0/1 Allows player to throw napalm grenades. Humans only. +// has_napalm 0/1 Allows player to throw napalm grenades. Humans only. // napalm_time decimal Napalm burn duration. Zombies only. // immunity_mode number Sets the immunity mode. // immunity_amount decimal Sets the immunity value. @@ -54,7 +58,7 @@ "enabled" "1" "team" "0" "team_default" "1" - "admin_only" "0" + "flags" "0" "name" "Classic" "description" "Need brains!!! Arrrrggghh!" @@ -97,7 +101,7 @@ "enabled" "1" "team" "0" "team_default" "0" - "admin_only" "0" + "flags" "0" "name" "Fast" "description" "-HP | +Speed | +Jump | +Knockback" @@ -140,7 +144,7 @@ "enabled" "1" "team" "0" "team_default" "0" - "admin_only" "0" + "flags" "0" "name" "Mutated" "description" "+HP | -Speed | +Jump | +Knockback" @@ -183,7 +187,7 @@ "enabled" "1" "team" "0" "team_default" "0" - "admin_only" "0" + "flags" "0" "name" "Heavy" "description" "+HP | -Speed | -Jump | -Knockback" @@ -232,7 +236,7 @@ "enabled" "1" "team" "1" "team_default" "1" - "admin_only" "0" + "flags" "0" "name" "Normal Human" "description" "Default Counter-Strike settings" @@ -275,7 +279,7 @@ "enabled" "1" "team" "1" "team_default" "0" - "admin_only" "0" + "flags" "0" "name" "Speedy" "description" "Fast human" @@ -318,7 +322,7 @@ "enabled" "1" "team" "1" "team_default" "0" - "admin_only" "0" + "flags" "0" "name" "Light" "description" "Regular human with improved jump skills" diff --git a/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg b/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg index cdaa541..32d538b 100644 --- a/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg +++ b/cstrike/cfg/sourcemod/zombiereloaded/zombiereloaded.cfg @@ -6,8 +6,11 @@ // Check the plugin configuration section in the manual for detailed info. // // ============================================================================ + +// ---------------------------------------------------------------------------- // Zombie-Related Server Variables // ---------------------------------------------------------------------------- + // Amount of time, in minutes, zombies have to infect all humans. // Default: "5" mp_roundtime 5 @@ -19,19 +22,24 @@ sv_turbophysics 1 // Multiplier for how easy props are moved ['1' = No push] // Default: "3" phys_pushscale 3 + + // ---------------------------------------------------------------------------- // Ammo Reserve Settings // ---------------------------------------------------------------------------- -ammo_50AE_max 500 // deagle -ammo_762mm_max 300 // scout, ak47, g3sg1, aug -ammo_556mm_box_max 300 // m249 -ammo_556mm_max 300 // galil, sg552, famas, m4a1, sg550 -ammo_338mag_max 100 // awp -ammo_9mm_max 500 // mp5navy, tmp, glock, elite -ammo_buckshot_max 64 // m3, xm1014 -ammo_45acp_max 500 // ump45, mac10, usp -ammo_357sig_max 500 // P228 -ammo_57mm_max 500 // p90, fiveseven + +ammo_50AE_max 500 // deagle +ammo_762mm_max 300 // scout, ak47, g3sg1, aug +ammo_556mm_box_max 300 // m249 +ammo_556mm_max 300 // galil, sg552, famas, m4a1, sg550 +ammo_338mag_max 100 // awp +ammo_9mm_max 500 // mp5navy, tmp, glock, elite +ammo_buckshot_max 64 // m3, xm1014 +ammo_45acp_max 500 // ump45, mac10, usp +ammo_357sig_max 500 // P228 +ammo_57mm_max 500 // p90, fiveseven + + // ---------------------------------------------------------------------------- // Notes // ---------------------------------------------------------------------------- @@ -69,9 +77,12 @@ ammo_57mm_max 500 // p90, fiveseven // // Value: // The value of the flag. Usually a referenced cvar. + + // ---------------------------------------------------------------------------- // Log (core) // ---------------------------------------------------------------------------- + // Enable logging of events in the plugin. Fatal errors are logged independent on this setting. // Default: "1" zr_log "1" @@ -95,9 +106,12 @@ zr_log_print_admins "0" // Print log events to public chat in addition to the log file. // Default: "0" zr_log_print_chat "0" + + // ---------------------------------------------------------------------------- // Config (core) // ---------------------------------------------------------------------------- + // Path, relative to root sourcemod directory, to models config file. // Default: "configs/zr/models.txt" zr_config_path_models "configs/zr/models.txt" @@ -117,6 +131,8 @@ zr_config_path_weapons "configs/zr/weapons.txt" // Path, relative to root sourcemod directory, to hitgroups config file. // Default: "configs/zr/hitgroups.txt" zr_config_path_hitgroups "configs/zr/hitgroups.txt" + + // ---------------------------------------------------------------------------- // Classes (core) // ---------------------------------------------------------------------------- @@ -127,22 +143,26 @@ zr_config_path_hitgroups "configs/zr/hitgroups.txt" // Default: "0" zr_classes_spawn "0" -// Player is assigned a random class every spawn. [Override: zr_classes_spawn&zr_classes_default_*] +// Player is assigned a random class every spawn. [Override: zr_classes_spawn & zr_classes_default_*] // Default: "0" zr_classes_random "0" -// Admin class assigned to admins on connect. ['random' = Random class | '""' = Class config default] +// Admin class assigned to admins on connect. ["random" = Random admin class | "" = Class config default] // Default: "random" zr_classes_default_admin "random" -// Human class assigned to players on connect. ['random' = Random class | '""' = Class config default] +// Human class assigned to players on connect. ["random" = Random human class | "" = Class config default] // Default: "random" zr_classes_default_human "random" -// Zombie class assigned to players on connect. ['random' = Random class | '""' = Class config default] +// Zombie class assigned to players on connect. ["random" = Random zombie class | "" = Class config default] // Default: "random" zr_classes_default_zombie "random" +// Zombie class assigned to mother zombies. ["motherzombies" = Random mother zombie class | "random" = Random regular zombie class | "disabled" = Don't change class on mother zombies] +// Default: "random" +zr_classes_default_mother_zombie "random" + // Menu // Automatically close class selection menu. @@ -162,6 +182,8 @@ zr_classes_overlay_togglecmds "nightvision" // Default class overlay toggle state set on connecting player. [Dependency: zr_classes_overlay_toggle] // Default: "0" zr_classes_overlay_default "0" + + // ---------------------------------------------------------------------------- // Weapons (core) // ---------------------------------------------------------------------------- @@ -195,12 +217,17 @@ zr_weapons_zmarket_rebuy "1" // Allow players to automatically rebuy their previous weapons. [Dependency: zr_weapons_zmarket&zr_weapons_zmarket_rebuy] // Default: "1" zr_weapons_zmarket_rebuy_auto "1" + + // ---------------------------------------------------------------------------- // Hitgroups (core) // ---------------------------------------------------------------------------- + // Enable hitgroups module, disabling this will disable hitgroup-related features. (hitgroup knockback multipliers, hitgroup damage control) // Default: "1" zr_hitgroups "1" + + // ---------------------------------------------------------------------------- // Infect (core) // ---------------------------------------------------------------------------- @@ -268,6 +295,8 @@ zr_infect_shake_frequency "1.0" // Duration of shaking effect. [Dependency: zr_infect_shake] // Default: "5.0" zr_infect_shake_duration "5.0" + + // ---------------------------------------------------------------------------- // Damage (core) // ---------------------------------------------------------------------------- @@ -301,15 +330,21 @@ zr_damage_suicide_human "1" // List of client commands to intercept as suicide attempts. [Delimiter: ", "] // Default: "kill, spectate, jointeam" zr_damage_suicide_cmds "kill, spectate, jointeam" + + // ---------------------------------------------------------------------------- // Overlays (core) // ---------------------------------------------------------------------------- + // How often to update overlays on players. [0.0 = Disabled] // Default: "1.0" zr_overlays_update_time "1.0" + + // ---------------------------------------------------------------------------- // Round End (core) // ---------------------------------------------------------------------------- + // Show specified overlay to players depending on winner when the round ends. // Default: "1" zr_roundend_overlay "1" @@ -321,9 +356,12 @@ zr_roundend_overlays_zombie "overlays/zr/zombies_win" // Overlay, relative to "materials" folder, to display when humans win the round. [Dependency: zr_roundend_overlay] // Default: "overlays/zr/humans_win" zr_roundend_overlays_human "overlays/zr/humans_win" + + // ---------------------------------------------------------------------------- // Account (module) // ---------------------------------------------------------------------------- + // Reset player's cash each spawn. // Default: "1" zr_account_cashfill "1" @@ -335,6 +373,8 @@ zr_account_cashfill_value "12000" // Attacker receives amount of cash equivalent to the damage that was inflicted. // Default: "0" zr_account_cashdmg "0" + + // ---------------------------------------------------------------------------- // Visual Effects (module) // ---------------------------------------------------------------------------- @@ -412,6 +452,8 @@ zr_veffects_ragdoll_dissolve "-1" // Time to wait before removing the ragdoll. [Dependency: zr_veffects_ragdoll_remove] // Default: "0.5" zr_veffects_ragdoll_delay "0.5" + + // ---------------------------------------------------------------------------- // Sound Effects (module) // ---------------------------------------------------------------------------- @@ -447,9 +489,12 @@ zr_ambientsounds_length "60.0" // Volume of the ambient sound. [1.0 = Max volume | 0.0001 = Not audible | Dependency: zr_ambientsounds] // Default: "0.8" zr_ambientsounds_volume "0.8" + + // ---------------------------------------------------------------------------- // Anti-Stick (module) // ---------------------------------------------------------------------------- + // Automatically unstick players when stuck within each others' collision hull. // Default: "1" zr_antistick "1" @@ -457,9 +502,12 @@ zr_antistick "1" // Time between each check for stuck players. [Dependency: zr_antistick] // Default: "0.5" zr_antistick_interval "0.5" + + // ---------------------------------------------------------------------------- // Spawn Protect (module) // ---------------------------------------------------------------------------- + // Player will be protected from infection when spawning into the game late. // Default: "1" zr_spawnprotect "1" @@ -475,9 +523,12 @@ zr_spawnprotect_speed "600.0" // Alpha of the player during protection. ['255' = Fully visible | '0' = Completely invisible | Dependency: zr_spawnprotect] // Default: "0" zr_spawnprotect_alpha "0" + + // ---------------------------------------------------------------------------- // Respawn (module) // ---------------------------------------------------------------------------- + // Respawn players after death. [Recommended: (Enable) zr_zspawn*] // Default: "0" zr_respawn "0" @@ -493,15 +544,21 @@ zr_respawn_team_zombie "1" // Respawn player as a zombie if player was killed by the world. [Override: zr_respawn_team_zombie] // Default: "1" zr_respawn_team_zombie_world "1" + + // ---------------------------------------------------------------------------- // Napalm (module) // ---------------------------------------------------------------------------- + // Ignite grenade in mid-air after player throws it. [Dependency: Human Attribute 'napalm'] // Default: "1" zr_napalm_ignite "1" + + // ---------------------------------------------------------------------------- // Jump Boost (module) // ---------------------------------------------------------------------------- + // Prevent players from using forward jump boost multipliers to bunny hop. // Default: "1" zr_jumpboost_bunnyhop_protect "1" @@ -513,9 +570,12 @@ zr_jumpboost_bunnyhop_max "275" // Specifies whether the speed should be reset, or limited to maximum when the limit is reached. // Default: "1" zr_jumpboost_bunnyhop_reset "1" + + // ---------------------------------------------------------------------------- // Volumetric Features (module) // ---------------------------------------------------------------------------- + // Enables volumetric features. // Default: "1" zr_vol "1" @@ -527,9 +587,12 @@ zr_vol_update_interval "1.0" // How often to check for delayed events, in seconds. Use lower values for more precise delays. // Default: "1.0" zr_vol_trigger_interval "1.0" + + // ---------------------------------------------------------------------------- // ZSpawn (module) // ---------------------------------------------------------------------------- + // Allow players to spawn into the game late. // Default: "1" zr_zspawn "1" @@ -549,9 +612,12 @@ zr_zspawn_timelimit "1" // Time from the start of the round to allow ZSpawn. [Dependency: zr_zspawn_timelimit] // Default: "120.0" zr_zspawn_timelimit_time "120.0" + + // ---------------------------------------------------------------------------- // ZTele (module) // ---------------------------------------------------------------------------- + // Allow zombies to use ZTele. // Default: "1" zr_ztele_zombie "1" @@ -587,9 +653,12 @@ zr_ztele_autocancel "1" // Maximum distance, in feet, player is allowed to travel before teleport is cancelled. [Dependency: zr_ztele_autocancel] // Default: "20" zr_ztele_autocancel_distance "20" + + // ---------------------------------------------------------------------------- // ZHP (module) // ---------------------------------------------------------------------------- + // Allow player to toggle real HP display as a zombie. // Default: "1" zr_zhp "1" diff --git a/src/zr/cvars.inc b/src/zr/cvars.inc index 09350dd..2900ae6 100644 --- a/src/zr/cvars.inc +++ b/src/zr/cvars.inc @@ -55,6 +55,7 @@ enum CvarsList Handle:CVAR_CLASSES_SPAWN, Handle:CVAR_CLASSES_RANDOM, Handle:CVAR_CLASSES_DEFAULT_ZOMBIE, + Handle:CVAR_CLASSES_DEFAULT_M_ZOMB, Handle:CVAR_CLASSES_DEFAULT_HUMAN, Handle:CVAR_CLASSES_DEFAULT_ADMIN, Handle:CVAR_CLASSES_MENU_AUTOCLOSE, @@ -228,11 +229,12 @@ CvarsCreate() // =========================== // General - g_hCvarsList[CVAR_CLASSES_SPAWN] = CreateConVar("zr_classes_spawn", "0", "Re-display class selection menu every spawn."); - g_hCvarsList[CVAR_CLASSES_RANDOM] = CreateConVar("zr_classes_random", "0", "Player is assigned a random class every spawn. [Override: zr_classes_spawn&zr_classes_default_*]"); - g_hCvarsList[CVAR_CLASSES_DEFAULT_ZOMBIE] = CreateConVar("zr_classes_default_zombie", "random", "Zombie class assigned to players on connect. ['random' = Random class | '\"\"' = Class config default]"); - g_hCvarsList[CVAR_CLASSES_DEFAULT_HUMAN] = CreateConVar("zr_classes_default_human", "random", "Human class assigned to players on connect. ['random' = Random class | '\"\"' = Class config default]"); - g_hCvarsList[CVAR_CLASSES_DEFAULT_ADMIN] = CreateConVar("zr_classes_default_admin", "random", "Admin class assigned to admins on connect. ['random' = Random class | '\"\"' = Class config default]"); + g_hCvarsList[CVAR_CLASSES_SPAWN] = CreateConVar("zr_classes_spawn", "0", "Re-display class selection menu every spawn."); + g_hCvarsList[CVAR_CLASSES_RANDOM] = CreateConVar("zr_classes_random", "0", "Player is assigned a random class every spawn. [Override: zr_classes_spawn and zr_classes_default_*]"); + g_hCvarsList[CVAR_CLASSES_DEFAULT_ZOMBIE] = CreateConVar("zr_classes_default_zombie", "random", "Zombie class assigned to players on connect. [\"random\" = Random zombie class | \"\" = Class config default]"); + g_hCvarsList[CVAR_CLASSES_DEFAULT_M_ZOMB] = CreateConVar("zr_classes_default_mother_zombie", "random", "Zombie class assigned to mother zombies. [\"motherzombies\" = Random mother zombie class | \"random\" = Random regular zombie class | \"disabled\" = Don't change class on mother zombies]"); + g_hCvarsList[CVAR_CLASSES_DEFAULT_HUMAN] = CreateConVar("zr_classes_default_human", "random", "Human class assigned to players on connect. [\"random\" = Random human class | \"\" = Class config default]"); + g_hCvarsList[CVAR_CLASSES_DEFAULT_ADMIN] = CreateConVar("zr_classes_default_admin", "random", "Admin class assigned to admins on connect. [\"random\" = Random admin class | \"\" = Class config default]"); // Menu g_hCvarsList[CVAR_CLASSES_MENU_AUTOCLOSE] = CreateConVar("zr_classes_menu_autoclose", "0", "Automatically close class selection menu."); diff --git a/src/zr/jumpboost.inc b/src/zr/jumpboost.inc index 689af7a..168c96b 100644 --- a/src/zr/jumpboost.inc +++ b/src/zr/jumpboost.inc @@ -40,8 +40,8 @@ JumpBoostOnClientJump(client) new Float:distance = ClassGetJumpDistance(client); new Float:height = ClassGetJumpHeight(client); - // Do not apply jump boost if class jump boost multiplier is 1.0. - if (height == 1.0 && distance == 1.0) + // Do not apply jump boost if settings indicate no boost. + if (height == 0.0 && distance == 0.2) { return; } diff --git a/src/zr/playerclasses/apply.inc b/src/zr/playerclasses/apply.inc index 9489113..cc845d8 100644 --- a/src/zr/playerclasses/apply.inc +++ b/src/zr/playerclasses/apply.inc @@ -39,11 +39,18 @@ bool:ClassApplyAttributes(client, bool:improved = false) { new classindex = ClassGetActiveIndex(client); - if (classindex < 0) + // Validate class index. + if (!ClassValidateIndex(classindex)) { return false; } + // Override improved settings if it's a mother zombie class. + if (ClassHasFlags(classindex, ZR_CLASS_FLAG_MOTHER_ZOMBIE)) + { + improved = false; + } + ClassApplyModel(client, classindex); ClassApplyAlpha(client, classindex); ClassApplyOverlay(client, classindex); diff --git a/src/zr/playerclasses/attributes.inc b/src/zr/playerclasses/attributes.inc index d830aab..d7636f3 100644 --- a/src/zr/playerclasses/attributes.inc +++ b/src/zr/playerclasses/attributes.inc @@ -133,7 +133,7 @@ stock bool:ClassGetTeamDefault(index, cachetype = ZR_CLASS_CACHE_MODIFIED) } /** - * Checks if the specified class is for admins only or not. + * Gets flags for the specified class. * * @param index Index of the class in a class cache or a client index, * depending on the cache type specified. @@ -143,23 +143,57 @@ stock bool:ClassGetTeamDefault(index, cachetype = ZR_CLASS_CACHE_MODIFIED) * data. * ZR_CLASS_CACHE_PLAYER - Player cache. If this one is used, * index will be used as a client index. - * @return True if it's for admins only, false otherwise. + * @return Class flags, or -1 if failed. */ -stock bool:ClassGetAdminOnly(index, cachetype = ZR_CLASS_CACHE_MODIFIED) +stock ClassGetFlags(index, cachetype = ZR_CLASS_CACHE_MODIFIED) { switch (cachetype) { case ZR_CLASS_CACHE_ORIGINAL: { - return ClassData[index][class_admin_only]; + return ClassData[index][class_flags]; } case ZR_CLASS_CACHE_MODIFIED: { - return ClassDataCache[index][class_admin_only]; + return ClassDataCache[index][class_flags]; } case ZR_CLASS_CACHE_PLAYER: { - return ClassPlayerCache[index][class_admin_only]; + return ClassPlayerCache[index][class_flags]; + } + } + return -1; +} + +/** + * Do bitwise compare on flags in the specified class. + * + * @param index Index of the class in a class cache or a client index, + * depending on the cache type specified. + * @param flags Class flags to check. + * @param cachetype Optional. Specifies what class cache to read from. Options: + * ZR_CLASS_CACHE_ORIGINAL - Unchanced class data. + * ZR_CLASS_CACHE_MODIFIED (default) - Changed/newest class + * data. + * ZR_CLASS_CACHE_PLAYER - Player cache. If this one is used, + * index will be used as a client index. + * @return True if the flags are set, false otherwise or if failed. + */ +stock bool:ClassHasFlags(index, flags, cachetype = ZR_CLASS_CACHE_MODIFIED) +{ + switch (cachetype) + { + case ZR_CLASS_CACHE_ORIGINAL: + { + return bool:(ClassData[index][class_flags] & flags); + } + case ZR_CLASS_CACHE_MODIFIED: + { + return bool:(ClassDataCache[index][class_flags] & flags); + } + case ZR_CLASS_CACHE_PLAYER: + { + return bool:(ClassPlayerCache[index][class_flags] & flags); } } return false; @@ -986,107 +1020,111 @@ stock ClassAttributeNameToFlag(const String:attributename[]) // Check attribute names. if (StrEqual(attributename, "enabled", false)) { - return ZR_CLASS_FLAG_ENABLED; + return ZR_CLASS_ENABLED; } else if (StrEqual(attributename, "team", false)) { - return ZR_CLASS_FLAG_TEAM; + return ZR_CLASS_TEAM; } else if (StrEqual(attributename, "team_default", false)) { - return ZR_CLASS_FLAG_TEAM_DEFAULT; + return ZR_CLASS_TEAM_DEFAULT; } - else if (StrEqual(attributename, "admin_only", false)) + else if (StrEqual(attributename, "flags", false)) { - return ZR_CLASS_FLAG_ADMIN_ONLY; + return ZR_CLASS_FLAGS; } else if (StrEqual(attributename, "name", false)) { - return ZR_CLASS_FLAG_NAME; + return ZR_CLASS_NAME; } else if (StrEqual(attributename, "description", false)) { - return ZR_CLASS_FLAG_DESCRIPTION; + return ZR_CLASS_DESCRIPTION; } else if (StrEqual(attributename, "model_path", false)) { - return ZR_CLASS_FLAG_MODEL_PATH; + return ZR_CLASS_MODEL_PATH; } else if (StrEqual(attributename, "alpha_initial", false)) { - return ZR_CLASS_FLAG_ALPHA_INITIAL; + return ZR_CLASS_ALPHA_INITIAL; } else if (StrEqual(attributename, "alpha_damaged", false)) { - return ZR_CLASS_FLAG_ALPHA_DAMAGED; + return ZR_CLASS_ALPHA_DAMAGED; } else if (StrEqual(attributename, "alpha_damage", false)) { - return ZR_CLASS_FLAG_ALPHA_DAMAGE; + return ZR_CLASS_ALPHA_DAMAGE; } else if (StrEqual(attributename, "overlay_path", false)) { - return ZR_CLASS_FLAG_OVERLAY_PATH; + return ZR_CLASS_OVERLAY_PATH; } else if (StrEqual(attributename, "nvgs", false)) { - return ZR_CLASS_FLAG_NVGS; + return ZR_CLASS_NVGS; } else if (StrEqual(attributename, "fov", false)) { - return ZR_CLASS_FLAG_FOV; + return ZR_CLASS_FOV; + } + else if (StrEqual(attributename, "has_napalm", false)) + { + return ZR_CLASS_HAS_NAPALM; } else if (StrEqual(attributename, "napalm_time", false)) { - return ZR_CLASS_FLAG_NAPALM_TIME; + return ZR_CLASS_NAPALM_TIME; } else if (StrEqual(attributename, "immunity_mode", false)) { - return ZR_CLASS_FLAG_IMMUNITY_MODE; + return ZR_CLASS_IMMUNITY_MODE; } else if (StrEqual(attributename, "immunity_amount", false)) { - return ZR_CLASS_FLAG_IMMUNITY_AMOUNT; + return ZR_CLASS_IMMUNITY_AMOUNT; } else if (StrEqual(attributename, "no_fall_damage", false)) { - return ZR_CLASS_FLAG_NO_FALL_DAMAGE; + return ZR_CLASS_NO_FALL_DAMAGE; } else if (StrEqual(attributename, "health", false)) { - return ZR_CLASS_FLAG_HEALTH; + return ZR_CLASS_HEALTH; } else if (StrEqual(attributename, "health_regen_interval", false)) { - return ZR_CLASS_FLAG_HEALTH_REGEN_INTERVAL; + return ZR_CLASS_HEALTH_REGEN_INTERVAL; } else if (StrEqual(attributename, "health_regen_amount", false)) { - return ZR_CLASS_FLAG_HEALTH_REGEN_AMOUNT; + return ZR_CLASS_HEALTH_REGEN_AMOUNT; } else if (StrEqual(attributename, "health_infect_gain", false)) { - return ZR_CLASS_FLAG_HEALTH_INFECT_GAIN; + return ZR_CLASS_HEALTH_INFECT_GAIN; } else if (StrEqual(attributename, "kill_bonus", false)) { - return ZR_CLASS_FLAG_KILL_BONUS; + return ZR_CLASS_KILL_BONUS; } else if (StrEqual(attributename, "speed", false)) { - return ZR_CLASS_FLAG_SPEED; + return ZR_CLASS_SPEED; } else if (StrEqual(attributename, "knockback", false)) { - return ZR_CLASS_FLAG_KNOCKBACK; + return ZR_CLASS_KNOCKBACK; } else if (StrEqual(attributename, "jump_height", false)) { - return ZR_CLASS_FLAG_JUMP_HEIGHT; + return ZR_CLASS_JUMP_HEIGHT; } else if (StrEqual(attributename, "jump_distance", false)) { - return ZR_CLASS_FLAG_JUMP_DISTANCE; + return ZR_CLASS_JUMP_DISTANCE; } // Invalid attribute name. @@ -1156,45 +1194,46 @@ stock ClassDataTypes:ClassGetAttributeType(attributeflag) switch (attributeflag) { // Boolean. - case ZR_CLASS_FLAG_ENABLED, - ZR_CLASS_FLAG_NVGS, - ZR_CLASS_FLAG_NO_FALL_DAMAGE, - ZR_CLASS_FLAG_ADMIN_ONLY: + case ZR_CLASS_ENABLED, + ZR_CLASS_NVGS, + ZR_CLASS_HAS_NAPALM, + ZR_CLASS_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: + case ZR_CLASS_FLAGS, + ZR_CLASS_ALPHA_INITIAL, + ZR_CLASS_ALPHA_DAMAGED, + ZR_CLASS_ALPHA_DAMAGE, + ZR_CLASS_FOV, + ZR_CLASS_IMMUNITY_MODE, + ZR_CLASS_HEALTH, + ZR_CLASS_HEALTH_REGEN_AMOUNT, + ZR_CLASS_HEALTH_INFECT_GAIN, + ZR_CLASS_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: + case ZR_CLASS_NAPALM_TIME, + ZR_CLASS_IMMUNITY_AMOUNT, + ZR_CLASS_HEALTH_REGEN_INTERVAL, + ZR_CLASS_SPEED, + ZR_CLASS_KNOCKBACK, + ZR_CLASS_JUMP_HEIGHT, + ZR_CLASS_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: + case ZR_CLASS_NAME, + ZR_CLASS_DESCRIPTION, + ZR_CLASS_MODEL_PATH, + ZR_CLASS_OVERLAY_PATH: { return ClassDataType_String; } diff --git a/src/zr/playerclasses/classcommands.inc b/src/zr/playerclasses/classcommands.inc index 79ca7b8..d7354a4 100644 --- a/src/zr/playerclasses/classcommands.inc +++ b/src/zr/playerclasses/classcommands.inc @@ -610,22 +610,22 @@ stock bool:ClassModifyBoolean(classindex, attributeflag, bool:value) switch (attributeflag) { - case ZR_CLASS_FLAG_ENABLED: + case ZR_CLASS_ENABLED: { ClassDataCache[classindex][class_enabled] = bool:value; return true; } - case ZR_CLASS_FLAG_NVGS: + case ZR_CLASS_NVGS: { ClassDataCache[classindex][class_nvgs] = bool:value; return true; } - case ZR_CLASS_FLAG_NO_FALL_DAMAGE: + case ZR_CLASS_NO_FALL_DAMAGE: { ClassDataCache[classindex][class_no_fall_damage] = bool:value; return true; } - case ZR_CLASS_FLAG_HAS_NAPALM: + case ZR_CLASS_HAS_NAPALM: { ClassDataCache[classindex][class_has_napalm] = bool:value; return true; @@ -661,7 +661,12 @@ stock ClassModifyInteger(classindex, attributeflag, value, Float:multiplier = 0. switch (attributeflag) { - case ZR_CLASS_FLAG_ALPHA_INITIAL: + case ZR_CLASS_FLAGS: + { + ClassDataCache[classindex][class_flags] = value; + return true; + } + case ZR_CLASS_ALPHA_INITIAL: { if (ismultiplier) { @@ -670,7 +675,7 @@ stock ClassModifyInteger(classindex, attributeflag, value, Float:multiplier = 0. ClassDataCache[classindex][class_alpha_initial] = value; return true; } - case ZR_CLASS_FLAG_ALPHA_DAMAGED: + case ZR_CLASS_ALPHA_DAMAGED: { if (ismultiplier) { @@ -679,7 +684,7 @@ stock ClassModifyInteger(classindex, attributeflag, value, Float:multiplier = 0. ClassDataCache[classindex][class_alpha_damaged] = value; return true; } - case ZR_CLASS_FLAG_ALPHA_DAMAGE: + case ZR_CLASS_ALPHA_DAMAGE: { if (ismultiplier) { @@ -688,17 +693,17 @@ stock ClassModifyInteger(classindex, attributeflag, value, Float:multiplier = 0. ClassDataCache[classindex][class_alpha_damage] = value; return true; } - case ZR_CLASS_FLAG_FOV: + case ZR_CLASS_FOV: { ClassDataCache[classindex][class_fov] = value; return true; } - case ZR_CLASS_FLAG_IMMUNITY_MODE: + case ZR_CLASS_IMMUNITY_MODE: { ClassDataCache[classindex][class_fov] = value; return true; } - case ZR_CLASS_FLAG_HEALTH: + case ZR_CLASS_HEALTH: { if (ismultiplier) { @@ -707,7 +712,7 @@ stock ClassModifyInteger(classindex, attributeflag, value, Float:multiplier = 0. ClassDataCache[classindex][class_health] = value; return true; } - case ZR_CLASS_FLAG_HEALTH_REGEN_AMOUNT: + case ZR_CLASS_HEALTH_REGEN_AMOUNT: { if (ismultiplier) { @@ -716,7 +721,7 @@ stock ClassModifyInteger(classindex, attributeflag, value, Float:multiplier = 0. ClassDataCache[classindex][class_health_regen_amount] = value; return true; } - case ZR_CLASS_FLAG_HEALTH_INFECT_GAIN: + case ZR_CLASS_HEALTH_INFECT_GAIN: { if (ismultiplier) { @@ -725,7 +730,7 @@ stock ClassModifyInteger(classindex, attributeflag, value, Float:multiplier = 0. ClassDataCache[classindex][class_health_infect_gain] = value; return true; } - case ZR_CLASS_FLAG_KILL_BONUS: + case ZR_CLASS_KILL_BONUS: { if (ismultiplier) { @@ -761,7 +766,7 @@ stock ClassModifyFloat(classindex, attributeflag, Float:value, bool:ismultiplier switch (attributeflag) { - case ZR_CLASS_FLAG_NAPALM_TIME: + case ZR_CLASS_NAPALM_TIME: { if (ismultiplier) { @@ -770,7 +775,7 @@ stock ClassModifyFloat(classindex, attributeflag, Float:value, bool:ismultiplier ClassDataCache[classindex][class_napalm_time] = value; return true; } - case ZR_CLASS_FLAG_IMMUNITY_AMOUNT: + case ZR_CLASS_IMMUNITY_AMOUNT: { if (ismultiplier) { @@ -779,7 +784,7 @@ stock ClassModifyFloat(classindex, attributeflag, Float:value, bool:ismultiplier ClassDataCache[classindex][class_immunity_amount] = value; return true; } - case ZR_CLASS_FLAG_HEALTH_REGEN_INTERVAL: + case ZR_CLASS_HEALTH_REGEN_INTERVAL: { if (ismultiplier) { @@ -788,7 +793,7 @@ stock ClassModifyFloat(classindex, attributeflag, Float:value, bool:ismultiplier ClassDataCache[classindex][class_health_regen_interval] = value; return true; } - case ZR_CLASS_FLAG_SPEED: + case ZR_CLASS_SPEED: { if (ismultiplier) { @@ -797,7 +802,7 @@ stock ClassModifyFloat(classindex, attributeflag, Float:value, bool:ismultiplier ClassDataCache[classindex][class_speed] = value; return true; } - case ZR_CLASS_FLAG_KNOCKBACK: + case ZR_CLASS_KNOCKBACK: { if (ismultiplier) { @@ -806,7 +811,7 @@ stock ClassModifyFloat(classindex, attributeflag, Float:value, bool:ismultiplier ClassDataCache[classindex][class_knockback] = value; return true; } - case ZR_CLASS_FLAG_JUMP_HEIGHT: + case ZR_CLASS_JUMP_HEIGHT: { if (ismultiplier) { @@ -815,7 +820,7 @@ stock ClassModifyFloat(classindex, attributeflag, Float:value, bool:ismultiplier ClassDataCache[classindex][class_jump_height] = value; return true; } - case ZR_CLASS_FLAG_JUMP_DISTANCE: + case ZR_CLASS_JUMP_DISTANCE: { if (ismultiplier) { @@ -848,22 +853,22 @@ stock ClassModifyString(classindex, attributeflag, const String:value[]) switch (attributeflag) { - case ZR_CLASS_FLAG_NAME: + case ZR_CLASS_NAME: { strcopy(ClassDataCache[classindex][class_name], 64, value); return true; } - case ZR_CLASS_FLAG_DESCRIPTION: + case ZR_CLASS_DESCRIPTION: { strcopy(ClassDataCache[classindex][class_description], 256, value); return true; } - case ZR_CLASS_FLAG_MODEL_PATH: + case ZR_CLASS_MODEL_PATH: { strcopy(ClassDataCache[classindex][class_model_path], PLATFORM_MAX_PATH, value); return true; } - case ZR_CLASS_FLAG_OVERLAY_PATH: + case ZR_CLASS_OVERLAY_PATH: { strcopy(ClassDataCache[classindex][class_overlay_path], PLATFORM_MAX_PATH, value); return true; diff --git a/src/zr/playerclasses/classevents.inc b/src/zr/playerclasses/classevents.inc index 3772f88..f8a4eda 100644 --- a/src/zr/playerclasses/classevents.inc +++ b/src/zr/playerclasses/classevents.inc @@ -155,10 +155,52 @@ ClassOnClientDeath(client) ClassOnClientInfected(client, bool:motherzombie = false) { new classindex = ClassGetActiveIndex(client); + new isadmin; + new motherindex; + + decl String:motherzombiesetting[64]; // Disable class attributes with timers. ClassHealthRegenStop(client); + // Check if it's a mother zombie. + if (motherzombie) + { + // Set negative admin flag if client is admin, so it's removed in + // special class flags. + isadmin = ZRIsClientAdmin(client) ? -ZR_CLASS_FLAG_ADMIN_ONLY : 0; + + // Get default mother zombie setting. + GetConVarString(g_hCvarsList[CVAR_CLASSES_DEFAULT_M_ZOMB], motherzombiesetting, sizeof(motherzombiesetting)); + + if (StrEqual(motherzombiesetting, "disabled", false)) + { + // Do nothing. Keep current class. + } + else if (StrEqual(motherzombiesetting, "random", false)) + { + // Get random regular zombie class. Remove admin flag if admin. + motherindex = ClassGetRandomClass(ZR_CLASS_TEAM_ZOMBIES, _, _, ZR_CLASS_SPECIALFLAGS + isadmin); + } + else if (StrEqual(motherzombiesetting, "motherzombies", false)) + { + // Get random mother zombie class. + motherindex = ClassGetRandomClass(ZR_CLASS_TEAM_ZOMBIES, _, ZR_CLASS_FLAG_MOTHER_ZOMBIE, isadmin); + } + else + { + // Assume it's a class name. Get index for the specified class name. + motherindex = ClassGetIndex(motherzombiesetting); + + // Validate index. + if (ClassValidateIndex(motherindex)) + { + // Change class. + classindex = motherindex; + } + } + } + // Update the players cache with zombie attributes. ClassReloadPlayerCache(client, classindex); diff --git a/src/zr/playerclasses/classmenus.inc b/src/zr/playerclasses/classmenus.inc index f039bc7..a992c79 100644 --- a/src/zr/playerclasses/classmenus.inc +++ b/src/zr/playerclasses/classmenus.inc @@ -177,7 +177,7 @@ ClassMenuSelect(client, teamid) new Handle:menu = CreateMenu(ClassMenuSelectHandle); new arraycount; new classindex; - new bool:clientisadmin = ZRIsClientAdmin(client); + new denyflags; decl String:title[64]; decl String:classname[64]; @@ -207,9 +207,12 @@ ClassMenuSelect(client, teamid) // Create buffer array. new Handle:classarray = CreateArray(); - // Copy all class indexes into the array, with the specified team filter. - // Also list admin-only classes if client is a admin. - if (ClassAddToArray(classarray, teamid, _, clientisadmin)) + // Set up filtering. + denyflags = ZR_CLASS_FLAG_MOTHER_ZOMBIE; // Hide mother zombie classes. + denyflags += !ZRIsClientAdmin(client) ? ZR_CLASS_FLAG_ADMIN_ONLY : 0; // Hide admin-only classes if not admin. + + // Copy all class indexes into the array, with the specified filter settings. + if (ClassAddToArray(classarray, teamid, _, _, denyflags)) { // Get number of classes. arraycount = GetArraySize(classarray); @@ -222,7 +225,7 @@ ClassMenuSelect(client, teamid) ClassGetName(classindex, classname, sizeof(classname), ZR_CLASS_CACHE_MODIFIED); ClassGetDescription(classindex, description, sizeof(description), ZR_CLASS_CACHE_MODIFIED); - // Add menu item. + // Add menu item. Using extra spaces for indention on the second line. Format(menuitem, sizeof(menuitem), "%s\n %s", classname, description); AddMenuItem(menu, classname, menuitem); } diff --git a/src/zr/playerclasses/filtertools.inc b/src/zr/playerclasses/filtertools.inc index dc91f11..23083bd 100644 --- a/src/zr/playerclasses/filtertools.inc +++ b/src/zr/playerclasses/filtertools.inc @@ -47,8 +47,8 @@ stock bool:ClassValidateTeamRequirements(cachetype = ZR_CLASS_CACHE_ORIGINAL) } // Test if a zombie and human class was found. - zombieindex = ClassGetFirstClass(ZR_CLASS_TEAM_ZOMBIES, _, _, cachetype); - humanindex = ClassGetFirstClass(ZR_CLASS_TEAM_HUMANS, _, _, cachetype); + zombieindex = ClassGetFirstClass(ZR_CLASS_TEAM_ZOMBIES, _, _, ZR_CLASS_SPECIALFLAGS, cachetype); + humanindex = ClassGetFirstClass(ZR_CLASS_TEAM_HUMANS, _, _, ZR_CLASS_SPECIALFLAGS, cachetype); // Validate indexes. if (ClassValidateIndex(zombieindex) && ClassValidateIndex(humanindex)) @@ -79,8 +79,8 @@ stock bool:ClassValidateTeamDefaults(cachetype = ZR_CLASS_CACHE_ORIGINAL) } // Test if a default zombie and human class was found. - zombieindex = ClassGetDefaultClass(ZR_CLASS_TEAM_ZOMBIES, _, _, cachetype); - humanindex = ClassGetDefaultClass(ZR_CLASS_TEAM_HUMANS, _, _, cachetype); + zombieindex = ClassGetDefaultClass(ZR_CLASS_TEAM_ZOMBIES, _, _, _, cachetype); + humanindex = ClassGetDefaultClass(ZR_CLASS_TEAM_HUMANS, _, _, _, cachetype); // Validate indexes. if (ClassValidateIndex(zombieindex) && ClassValidateIndex(humanindex)) @@ -109,13 +109,19 @@ stock ClassValidateAttributes(classindex) // Team. if (ClassData[classindex][class_team] < ZR_CLASS_TEAM_MIN || ClassData[classindex][class_team] > ZR_CLASS_TEAM_MAX) { - flags += ZR_CLASS_FLAG_TEAM; + flags += ZR_CLASS_TEAM; + } + + // Class flags. + if (ClassData[classindex][class_flags] < ZR_CLASS_FLAGS_MIN || ClassData[classindex][class_flags] > ZR_CLASS_FLAGS_MAX) + { + flags += ZR_CLASS_FLAGS; } // Name. if (strlen(ClassData[classindex][class_name]) < ZR_CLASS_NAME_MIN) { - flags += ZR_CLASS_FLAG_NAME; + flags += ZR_CLASS_NAME; } else { @@ -128,21 +134,21 @@ stock ClassValidateAttributes(classindex) StrEqual(name, "zombies", false) || StrEqual(name, "admins", false)) { - flags += ZR_CLASS_FLAG_NAME; + flags += ZR_CLASS_NAME; } } // Description. if (strlen(ClassData[classindex][class_description]) < ZR_CLASS_DESCRIPTION_MIN) { - flags += ZR_CLASS_FLAG_DESCRIPTION; + flags += ZR_CLASS_DESCRIPTION; } // Model path. decl String:model_path[PLATFORM_MAX_PATH]; if (strcopy(model_path, sizeof(model_path), ClassData[classindex][class_model_path]) == 0) { - flags += ZR_CLASS_FLAG_MODEL_PATH; + flags += ZR_CLASS_MODEL_PATH; } else { @@ -152,7 +158,7 @@ stock ClassValidateAttributes(classindex) // Check if the file exists. if (!FileExists(model_path)) { - flags += ZR_CLASS_FLAG_MODEL_PATH; + flags += ZR_CLASS_MODEL_PATH; } } } @@ -161,21 +167,21 @@ stock ClassValidateAttributes(classindex) new alpha_initial = ClassData[classindex][class_alpha_initial]; if (!(alpha_initial >= ZR_CLASS_ALPHA_INITIAL_MIN && alpha_initial <= ZR_CLASS_ALPHA_INITIAL_MAX)) { - flags += ZR_CLASS_FLAG_ALPHA_INITIAL; + flags += ZR_CLASS_ALPHA_INITIAL; } // Alpha, damaged. new alpha_damaged = ClassData[classindex][class_alpha_damaged]; if (!(alpha_damaged >= ZR_CLASS_ALPHA_DAMAGED_MIN && alpha_damaged <= ZR_CLASS_ALPHA_DAMAGED_MAX)) { - flags += ZR_CLASS_FLAG_ALPHA_DAMAGED; + flags += ZR_CLASS_ALPHA_DAMAGED; } // Alpha, damage. new alpha_damage = ClassData[classindex][class_alpha_damage]; if (!(alpha_damage >= ZR_CLASS_ALPHA_DAMAGE_MIN && alpha_damage <= ZR_CLASS_ALPHA_DAMAGE_MAX)) { - flags += ZR_CLASS_FLAG_ALPHA_DAMAGE; + flags += ZR_CLASS_ALPHA_DAMAGE; } // Overlay path. @@ -187,7 +193,7 @@ stock ClassValidateAttributes(classindex) Format(overlay, sizeof(overlay), "materials/%s.vmt", overlay_path); if (!FileExists(overlay)) { - flags += ZR_CLASS_FLAG_OVERLAY_PATH; + flags += ZR_CLASS_OVERLAY_PATH; } } @@ -195,85 +201,84 @@ stock ClassValidateAttributes(classindex) new fov = ClassData[classindex][class_fov]; if (!(fov >= ZR_CLASS_FOV_MIN && fov <= ZR_CLASS_FOV_MAX)) { - flags += ZR_CLASS_FLAG_FOV; + flags += ZR_CLASS_FOV; } // Napalm time. new Float:napalm_time = ClassData[classindex][class_napalm_time]; if (!(napalm_time >= ZR_CLASS_NAPALM_TIME_MIN && napalm_time <= ZR_CLASS_NAPALM_TIME_MAX)) { - flags += ZR_CLASS_FLAG_NAPALM_TIME; + flags += ZR_CLASS_NAPALM_TIME; } // Health. new health = ClassData[classindex][class_health]; if (!(health >= ZR_CLASS_HEALTH_MIN && health <= ZR_CLASS_HEALTH_MAX)) { - flags += ZR_CLASS_FLAG_HEALTH; + flags += ZR_CLASS_HEALTH; } // Health regen interval. new Float:regen_interval = ClassData[classindex][class_health_regen_interval]; - if (!(regen_interval >= ZR_CLASS_HEALTH_REGEN_INTERVAL_MIN && regen_interval <= ZR_CLASS_HEALTH_REGEN_INTERVAL_MAX)) + if (!(regen_interval >= ZR_CLASS_REGEN_INTERVAL_MIN && regen_interval <= ZR_CLASS_REGEN_INTERVAL_MAX)) { - flags += ZR_CLASS_FLAG_HEALTH_REGEN_INTERVAL; + flags += ZR_CLASS_HEALTH_REGEN_INTERVAL; } // Health regen amount. new regen_amount = ClassData[classindex][class_health_regen_amount]; - if (!(regen_amount >= ZR_CLASS_HEALTH_REGEN_AMOUNT_MIN && regen_amount <= ZR_CLASS_HEALTH_REGEN_AMOUNT_MAX)) + if (!(regen_amount >= ZR_CLASS_REGEN_AMOUNT_MIN && regen_amount <= ZR_CLASS_REGEN_AMOUNT_MAX)) { - flags += ZR_CLASS_FLAG_HEALTH_REGEN_AMOUNT; + flags += ZR_CLASS_HEALTH_REGEN_AMOUNT; } // Health infect gain. 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_HEALTH_INFECT_GAIN; + flags += ZR_CLASS_HEALTH_INFECT_GAIN; } // Kill bonus. new kill_bonus = ClassData[classindex][class_kill_bonus]; if (!(kill_bonus >= ZR_CLASS_KILL_BONUS_MIN && kill_bonus <= ZR_CLASS_KILL_BONUS_MAX)) { - flags += ZR_CLASS_FLAG_KILL_BONUS; + flags += ZR_CLASS_KILL_BONUS; } // Speed. new Float:speed = ClassData[classindex][class_speed]; if (!(speed >= ZR_CLASS_SPEED_MIN && speed <= ZR_CLASS_SPEED_MAX)) { - flags += ZR_CLASS_FLAG_SPEED; + flags += ZR_CLASS_SPEED; } // Knockback. new Float:knockback = ClassData[classindex][class_knockback]; if (!(knockback >= ZR_CLASS_KNOCKBACK_MIN && knockback <= ZR_CLASS_KNOCKBACK_MAX)) { - flags += ZR_CLASS_FLAG_KNOCKBACK; + flags += ZR_CLASS_KNOCKBACK; } // Jump height. new Float:jump_height = ClassData[classindex][class_jump_height]; if (!(jump_height >= ZR_CLASS_JUMP_HEIGHT_MIN && jump_height <= ZR_CLASS_JUMP_HEIGHT_MAX)) { - flags += ZR_CLASS_FLAG_JUMP_HEIGHT; + flags += ZR_CLASS_JUMP_HEIGHT; } // Jump distance. new Float:jump_distance = ClassData[classindex][class_jump_distance]; if (!(jump_distance >= ZR_CLASS_JUMP_DISTANCE_MIN && jump_distance <= ZR_CLASS_JUMP_DISTANCE_MAX)) { - flags += ZR_CLASS_FLAG_JUMP_DISTANCE; + flags += ZR_CLASS_JUMP_DISTANCE; } return flags; } /** - * Checks if the specified class index points to a existing class in the - * ClassData array. + * Checks if the specified class index is a valid index. * * @param classindex The class index to validate. * @return True if the class exist, false otherwise. @@ -444,6 +449,73 @@ stock Float:ClassGetAttributeMultiplier(client, ClassMultipliers:attribute) } } +/** + * Check if a class pass the specified flag filters. + * + * @param index Index of the class in a class cache or a client index, + * depending on the cache type specified. + * @param require Class flags to require. 0 for no filter. + * @param deny Class flags to exclude. 0 for no filter. + * @param cachetype Specifies what class cache to read from. Options: + * ZR_CLASS_CACHE_ORIGINAL - Unchanced class data. + * ZR_CLASS_CACHE_MODIFIED (default) - Changed/newest + * class data. + * ZR_CLASS_CACHE_PLAYER - Player cache. If this one is + * used index will be used as a client index. + * @return True if passed, false otherwise. + */ +stock bool:ClassFlagFilterMatch(index, require, deny, cachetype) +{ + new flags; + new bool:requirepassed; + new bool:denypassed; + + // Do quick check for optimization reasons: Check if no flags are specified. + if (require == 0 && deny == 0) + { + return true; + } + + // Cache flags. + flags = ClassGetFlags(index, cachetype); + + // Match require filter. + if (require == 0 || flags & require) + { + // All required flags are set. + requirepassed = true; + } + else + { + // Not all required flags are set. + requirepassed = false; + } + + // Match deny filter. + if (deny == 0 || ~flags & deny) + { + // No denied flags are set. + denypassed = true; + } + else + { + // It has denied flags set. + denypassed = false; + } + + // Check if required and denied flags passed the filter. + if (requirepassed && denypassed) + { + // The class pass the filter. + return true; + } + else + { + // The class didn't pass the filter. + return false; + } +} + /** * Gets all class indexes or from a specified team, and adds them to the * specified array. @@ -453,8 +525,10 @@ stock Float:ClassGetAttributeMultiplier(client, ClassMultipliers:attribute) * for no filter (default). * @param ignoreEnabled Optional. Ignore whether the class is enabled or * not. Default is false. - * @param ignoreAdminOnly Optional. Ignore whether the class is for admins - * only or not. Default is false. + * @param requireflags Optional. Require certain class flags to be set. + * Default is no filtering. + * @param denyflags Optional. Require certain class flags to be off. + * Default is no filtering. * @param cachetype Optional. Specifies what class cache to read from. * Options: * ZR_CLASS_CACHE_ORIGINAL - Unchanced class data. @@ -463,7 +537,7 @@ stock Float:ClassGetAttributeMultiplier(client, ClassMultipliers:attribute) * @return True on success. False on error or if no classes were added or * found. */ -stock bool:ClassAddToArray(Handle:array, teamfilter = -1, bool:ignoreEnabled = false, bool:ignoreAdminOnly = false, cachetype = ZR_CLASS_CACHE_MODIFIED) +stock bool:ClassAddToArray(Handle:array, teamfilter = -1, bool:ignoreEnabled = false, requireflags = 0, denyflags = 0, cachetype = ZR_CLASS_CACHE_MODIFIED) { // Validate the array. if (array == INVALID_HANDLE) @@ -491,10 +565,10 @@ stock bool:ClassAddToArray(Handle:array, teamfilter = -1, bool:ignoreEnabled = f continue; } - if (!ignoreAdminOnly && ClassGetAdminOnly(classindex, cachetype)) + // Check flag filter match. + if (!ClassFlagFilterMatch(classindex, requireflags, denyflags, cachetype)) { - // The class is for admins only. This attribute isn't ignored so - // skip to the next class. + // The class didn't pass filter. continue; } @@ -535,8 +609,10 @@ stock bool:ClassAddToArray(Handle:array, teamfilter = -1, bool:ignoreEnabled = f * no filter (default). * @param ignoreEnabled Optional. Ignore whether the class is enabled or * not. Default is false. - * @param ignoreAdminOnly Optional. Ignore whether the class is for admins - * only or not. Default is false. + * @param requireflags Optional. Require certain class flags to be set. + * Default is no filtering. + * @param denyflags Optional. Require certain class flags to be off. + * Default is no filtering. * @param cachetype Optional. Specifies what class cache to read from. * Options: * ZR_CLASS_CACHE_ORIGINAL - Unchanced class data. @@ -544,7 +620,7 @@ stock bool:ClassAddToArray(Handle:array, teamfilter = -1, bool:ignoreEnabled = f * class data. * @return Number of total classes or classes in the specified team. */ -stock ClassCountTeam(teamfilter = -1, bool:ignoreEnabled = false, bool:ignoreAdminOnly = false, cachetype = ZR_CLASS_CACHE_MODIFIED) +stock ClassCountTeam(teamfilter = -1, bool:ignoreEnabled = false, requireflags = 0, denyflags = 0, cachetype = ZR_CLASS_CACHE_MODIFIED) { // Check if there are no classes. if (ClassCount == 0) @@ -566,10 +642,10 @@ stock ClassCountTeam(teamfilter = -1, bool:ignoreEnabled = false, bool:ignoreAdm continue; } - if (!ignoreAdminOnly && ClassGetAdminOnly(classindex, cachetype)) + // Check flag filter match. + if (!ClassFlagFilterMatch(classindex, requireflags, denyflags, cachetype)) { - // The class is for admins only. This attribute isn't ignored so - // skip to the next class. + // The class didn't pass filter. continue; } @@ -601,8 +677,10 @@ stock ClassCountTeam(teamfilter = -1, bool:ignoreEnabled = false, bool:ignoreAdm * for no filter (default). * @param ignoreEnabled Optional. Ignore whether the class is enabled or * not. Default is false. - * @param ignoreAdminOnly Optional. Ignore whether the class is for admins - * only or not. Default is false. + * @param requireflags Optional. Require certain class flags to be set. + * Default is no filtering. + * @param denyflags Optional. Require certain class flags to be off. + * Default is no filtering. * @param cachetype Optional. Specifies what class cache to read from. * Options: * ZR_CLASS_CACHE_ORIGINAL - Unchanced class data. @@ -610,7 +688,7 @@ stock ClassCountTeam(teamfilter = -1, bool:ignoreEnabled = false, bool:ignoreAdm * class data. * @return The class index if successful, or -1 on error. */ -stock ClassGetRandomClass(teamfilter = -1, bool:ignoreEnabled = false, bool:ignoreAdminOnly = false, cachetype = ZR_CLASS_CACHE_MODIFIED) +stock ClassGetRandomClass(teamfilter = -1, bool:ignoreEnabled = false, requireflags = 0, denyflags = 0, cachetype = ZR_CLASS_CACHE_MODIFIED) { new Handle:classarray; new arraycount; @@ -619,7 +697,7 @@ stock ClassGetRandomClass(teamfilter = -1, bool:ignoreEnabled = false, bool:igno classarray = CreateArray(); // Try to get a class list. - if (ClassAddToArray(classarray, teamfilter, ignoreEnabled, ignoreAdminOnly, cachetype)) + if (ClassAddToArray(classarray, teamfilter, ignoreEnabled, requireflags, denyflags, cachetype)) { // Get a random index from the new class array. arraycount = GetArraySize(classarray); @@ -643,8 +721,10 @@ stock ClassGetRandomClass(teamfilter = -1, bool:ignoreEnabled = false, bool:igno * for no filter (default). * @param ignoreEnabled Optional. Ignore whether the class is enabled or * not. Default is false. - * @param ignoreAdminOnly Optional. Ignore whether the class is for admins - * only or not. Default is false. + * @param requireflags Optional. Require certain class flags to be set. + * Default is no filtering. + * @param denyflags Optional. Require certain class flags to be off. + * Default is no filtering. * @param cachetype Optional. Specifies what class cache to read from. * Options: * ZR_CLASS_CACHE_ORIGINAL - Unchanced class data. @@ -653,7 +733,7 @@ stock ClassGetRandomClass(teamfilter = -1, bool:ignoreEnabled = false, bool:igno * @return The first class index, or the first class index with the specified * team ID. -1 on error. */ -stock ClassGetFirstClass(teamfilter = -1, bool:ignoreEnabled = false, bool:ignoreAdminOnly = false, cachetype = ZR_CLASS_CACHE_MODIFIED) +stock ClassGetFirstClass(teamfilter = -1, bool:ignoreEnabled = false, requireflags = 0, denyflags = 0, cachetype = ZR_CLASS_CACHE_MODIFIED) { // Check if there are no classes. if (ClassCount == 0) @@ -673,10 +753,10 @@ stock ClassGetFirstClass(teamfilter = -1, bool:ignoreEnabled = false, bool:ignor continue; } - if (!ignoreAdminOnly && ClassGetAdminOnly(classindex, cachetype)) + // Check flag filter match. + if (!ClassFlagFilterMatch(classindex, requireflags, denyflags, cachetype)) { - // The class is for admins only. This attribute isn't ignored so - // skip to the next class. + // The class didn't pass filter. continue; } @@ -704,8 +784,11 @@ stock ClassGetFirstClass(teamfilter = -1, bool:ignoreEnabled = false, bool:ignor * @param teamid The team ID. * @param ignoreEnabled Optional. Ignore whether the class is enabled or * not. Default is false. - * @param ignoreAdminOnly Optional. Ignore whether the class is for admins - * only or not. Default is false. + * @param requireflags Optional. Require certain class flags to be set. + * Default is no filtering. + * @param denyflags Optional. Require certain class flags to be off. + * Default is to deny classes with special flags + * (ZR_CLASS_SPECIALFLAGS). * @param cachetype Optional. Specifies what class cache to read from. * Options: * ZR_CLASS_CACHE_ORIGINAL - Unchanced class data. @@ -713,7 +796,7 @@ stock ClassGetFirstClass(teamfilter = -1, bool:ignoreEnabled = false, bool:ignor * class data. * @return The first default class index. -1 on error. */ -stock ClassGetDefaultClass(teamid, bool:ignoreEnabled = false, bool:ignoreAdminOnly = false, cachetype = ZR_CLASS_CACHE_MODIFIED) +stock ClassGetDefaultClass(teamid, bool:ignoreEnabled = false, requireflags = 0, denyflags = ZR_CLASS_SPECIALFLAGS, cachetype = ZR_CLASS_CACHE_MODIFIED) { new Handle:classarray; new arraycount; @@ -722,7 +805,7 @@ stock ClassGetDefaultClass(teamid, bool:ignoreEnabled = false, bool:ignoreAdminO classarray = CreateArray(); // Get all classes from the specified team. - if (!ClassAddToArray(classarray, teamid, ignoreEnabled, ignoreAdminOnly, cachetype)) + if (!ClassAddToArray(classarray, teamid, ignoreEnabled, requireflags, denyflags, cachetype)) { // Failed to get classes. return -1; @@ -792,8 +875,9 @@ stock ClassGetDefaultSpawnClass(teamid, cachetype = ZR_CLASS_CACHE_MODIFIED) // Check if the user set "random" as default class. if (strcmp(classname, "random", false) == 0) { - // Get a list of all classes with the specified team ID. - classindex = ClassGetRandomClass(teamid, _, _, cachetype); + // Get a list of all classes with the specified team ID. Deny + // classes with special flags. + classindex = ClassGetRandomClass(teamid, _, _, ZR_CLASS_SPECIALFLAGS, cachetype); // Validate the result, in case there were errors. if (ClassValidateIndex(classindex)) @@ -847,6 +931,6 @@ stock ClassGetDefaultSpawnClass(teamid, cachetype = ZR_CLASS_CACHE_MODIFIED) else { // Blank class name, get the default class and return the index. - return ClassGetDefaultClass(teamid, _, _, cachetype); + return ClassGetDefaultClass(teamid, _, _, ZR_CLASS_SPECIALFLAGS, cachetype); } } diff --git a/src/zr/playerclasses/playerclasses.inc b/src/zr/playerclasses/playerclasses.inc index 424b462..8e76e5f 100644 --- a/src/zr/playerclasses/playerclasses.inc +++ b/src/zr/playerclasses/playerclasses.inc @@ -84,6 +84,18 @@ * @endsection */ +/** + * @section Flags for special classes. + */ +#define ZR_CLASS_FLAG_ADMIN_ONLY (1<<0) /** Class is usable by admins only. */ +#define ZR_CLASS_FLAG_MOTHER_ZOMBIE (1<<1) /** Class is usable by mother zombies only. */ + +/** A combination of special class flags. Used to exclude special classes. */ +#define ZR_CLASS_SPECIALFLAGS ZR_CLASS_FLAG_ADMIN_ONLY + ZR_CLASS_FLAG_MOTHER_ZOMBIE +/** + * @endsection + */ + /** * @section Overall default class settings. Since this is a zombie plugin the * default values represent a zombie. @@ -91,7 +103,7 @@ #define ZR_CLASS_DEFAULT_ENABLED true #define ZR_CLASS_DEFAULT_TEAM ZR_CLASS_TEAM_ZOMBIES #define ZR_CLASS_DEFAULT_TEAM_DEFAULT true -#define ZR_CLASS_DEFAULT_ADMIN_ONLY false +#define ZR_CLASS_DEFAULT_FLAGS 0 #define ZR_CLASS_DEFAULT_NAME "classic" #define ZR_CLASS_DEFAULT_DESCRIPTION "Need brains!!! Arrrrggghh!" #define ZR_CLASS_DEFAULT_MODEL_PATH "models/player/zh/zh_zombie003.mdl" @@ -124,6 +136,8 @@ */ #define ZR_CLASS_TEAM_MIN 0 #define ZR_CLASS_TEAM_MAX 2 +#define ZR_CLASS_FLAGS_MIN 0 +#define ZR_CLASS_FLAGS_MAX 3 #define ZR_CLASS_NAME_MIN 1 #define ZR_CLASS_DESCRIPTION_MIN 1 /** Model path is checked for existance. */ @@ -140,10 +154,10 @@ #define ZR_CLASS_NAPALM_TIME_MAX 600.0 #define ZR_CLASS_HEALTH_MIN 1 #define ZR_CLASS_HEALTH_MAX 20000 -#define ZR_CLASS_HEALTH_REGEN_INTERVAL_MIN 0.0 -#define ZR_CLASS_HEALTH_REGEN_INTERVAL_MAX 900.0 -#define ZR_CLASS_HEALTH_REGEN_AMOUNT_MIN 0 -#define ZR_CLASS_HEALTH_REGEN_AMOUNT_MAX 10000 +#define ZR_CLASS_REGEN_INTERVAL_MIN 0.0 +#define ZR_CLASS_REGEN_INTERVAL_MAX 900.0 +#define ZR_CLASS_REGEN_AMOUNT_MIN 0 +#define ZR_CLASS_REGEN_AMOUNT_MAX 10000 #define ZR_CLASS_HEALTH_INFECT_GAIN_MIN 0 #define ZR_CLASS_HEALTH_INFECT_GAIN_MAX 20000 #define ZR_CLASS_KILL_BONUS_MIN 0 @@ -161,35 +175,35 @@ */ /** - * @section Flags used for specifying one or more attributes. + * @section Class attribute flags. */ -#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_ADMIN_ONLY (1<<3) -#define ZR_CLASS_FLAG_NAME (1<<4) -#define ZR_CLASS_FLAG_DESCRIPTION (1<<5) -#define ZR_CLASS_FLAG_MODEL_PATH (1<<6) -#define ZR_CLASS_FLAG_ALPHA_INITIAL (1<<7) -#define ZR_CLASS_FLAG_ALPHA_DAMAGED (1<<8) -#define ZR_CLASS_FLAG_ALPHA_DAMAGE (1<<9) -#define ZR_CLASS_FLAG_OVERLAY_PATH (1<<10) -#define ZR_CLASS_FLAG_NVGS (1<<11) -#define ZR_CLASS_FLAG_FOV (1<<12) -#define ZR_CLASS_FLAG_HAS_NAPALM (1<<13) -#define ZR_CLASS_FLAG_NAPALM_TIME (1<<14) -#define ZR_CLASS_FLAG_IMMUNITY_MODE (1<<15) -#define ZR_CLASS_FLAG_IMMUNITY_AMOUNT (1<<16) -#define ZR_CLASS_FLAG_NO_FALL_DAMAGE (1<<17) -#define ZR_CLASS_FLAG_HEALTH (1<<18) -#define ZR_CLASS_FLAG_HEALTH_REGEN_INTERVAL (1<<19) -#define ZR_CLASS_FLAG_HEALTH_REGEN_AMOUNT (1<<20) -#define ZR_CLASS_FLAG_HEALTH_INFECT_GAIN (1<<21) -#define ZR_CLASS_FLAG_KILL_BONUS (1<<22) -#define ZR_CLASS_FLAG_SPEED (1<<23) -#define ZR_CLASS_FLAG_KNOCKBACK (1<<24) -#define ZR_CLASS_FLAG_JUMP_HEIGHT (1<<25) -#define ZR_CLASS_FLAG_JUMP_DISTANCE (1<<26) +#define ZR_CLASS_ENABLED (1<<0) +#define ZR_CLASS_TEAM (1<<1) +#define ZR_CLASS_TEAM_DEFAULT (1<<2) +#define ZR_CLASS_FLAGS (1<<3) +#define ZR_CLASS_NAME (1<<4) +#define ZR_CLASS_DESCRIPTION (1<<5) +#define ZR_CLASS_MODEL_PATH (1<<6) +#define ZR_CLASS_ALPHA_INITIAL (1<<7) +#define ZR_CLASS_ALPHA_DAMAGED (1<<8) +#define ZR_CLASS_ALPHA_DAMAGE (1<<9) +#define ZR_CLASS_OVERLAY_PATH (1<<10) +#define ZR_CLASS_NVGS (1<<11) +#define ZR_CLASS_FOV (1<<12) +#define ZR_CLASS_HAS_NAPALM (1<<13) +#define ZR_CLASS_NAPALM_TIME (1<<14) +#define ZR_CLASS_IMMUNITY_MODE (1<<15) +#define ZR_CLASS_IMMUNITY_AMOUNT (1<<16) +#define ZR_CLASS_NO_FALL_DAMAGE (1<<17) +#define ZR_CLASS_HEALTH (1<<18) +#define ZR_CLASS_HEALTH_REGEN_INTERVAL (1<<19) +#define ZR_CLASS_HEALTH_REGEN_AMOUNT (1<<20) +#define ZR_CLASS_HEALTH_INFECT_GAIN (1<<21) +#define ZR_CLASS_KILL_BONUS (1<<22) +#define ZR_CLASS_SPEED (1<<23) +#define ZR_CLASS_KNOCKBACK (1<<24) +#define ZR_CLASS_JUMP_HEIGHT (1<<25) +#define ZR_CLASS_JUMP_DISTANCE (1<<26) /** * @endsection */ @@ -203,7 +217,7 @@ enum ClassAttributes bool:class_enabled, class_team, bool:class_team_default, - bool:class_admin_only, + class_flags, String:class_name[64], String:class_description[256], @@ -429,7 +443,7 @@ ClassLoad(bool:keepMultipliers = false) ClassData[ClassCount][class_enabled] = bool:KvGetNum(kvClassData, "enabled", ZR_CLASS_DEFAULT_ENABLED); ClassData[ClassCount][class_team] = KvGetNum(kvClassData, "team", ZR_CLASS_DEFAULT_TEAM); ClassData[ClassCount][class_team_default] = bool:KvGetNum(kvClassData, "team_default", ZR_CLASS_DEFAULT_TEAM_DEFAULT); - ClassData[ClassCount][class_admin_only] = bool:KvGetNum(kvClassData, "admin_only", ZR_CLASS_DEFAULT_ADMIN_ONLY); + ClassData[ClassCount][class_flags] = KvGetNum(kvClassData, "flags", ZR_CLASS_DEFAULT_FLAGS); KvGetString(kvClassData, "name", name, sizeof(name), ZR_CLASS_DEFAULT_NAME); strcopy(ClassData[ClassCount][class_name], 64, name); @@ -557,7 +571,7 @@ bool:ClassReloadDataCache() ClassDataCache[classindex][class_enabled] = ClassData[classindex][class_enabled]; ClassDataCache[classindex][class_team] = ClassData[classindex][class_team]; ClassDataCache[classindex][class_team_default] = ClassData[classindex][class_team_default]; - ClassDataCache[classindex][class_admin_only] = ClassData[classindex][class_admin_only]; + ClassDataCache[classindex][class_flags] = ClassData[classindex][class_flags]; strcopy(ClassDataCache[classindex][class_name], 64, ClassData[classindex][class_name]); strcopy(ClassDataCache[classindex][class_description], 256, ClassData[classindex][class_description]); @@ -621,7 +635,7 @@ bool:ClassReloadPlayerCache(client, classindex, cachetype = ZR_CLASS_CACHE_MODIF ClassPlayerCache[client][class_enabled] = ClassData[classindex][class_enabled]; ClassPlayerCache[client][class_team] = ClassData[classindex][class_team]; ClassPlayerCache[client][class_team_default] = ClassData[classindex][class_team_default]; - ClassPlayerCache[client][class_admin_only] = ClassData[classindex][class_admin_only]; + ClassPlayerCache[client][class_flags] = ClassData[classindex][class_flags]; strcopy(ClassPlayerCache[client][class_name], 64, ClassData[classindex][class_name]); strcopy(ClassPlayerCache[client][class_description], 256, ClassData[classindex][class_description]); @@ -660,7 +674,7 @@ bool:ClassReloadPlayerCache(client, classindex, cachetype = ZR_CLASS_CACHE_MODIF ClassPlayerCache[client][class_enabled] = ClassDataCache[classindex][class_enabled]; ClassPlayerCache[client][class_team] = ClassDataCache[classindex][class_team]; ClassPlayerCache[client][class_team_default] = ClassDataCache[classindex][class_team_default]; - ClassPlayerCache[client][class_admin_only] = ClassDataCache[classindex][class_admin_only]; + ClassPlayerCache[client][class_flags] = ClassDataCache[classindex][class_flags]; strcopy(ClassPlayerCache[client][class_name], 64, ClassDataCache[classindex][class_name]); strcopy(ClassPlayerCache[client][class_description], 256, ClassDataCache[classindex][class_description]); @@ -859,7 +873,7 @@ ClassDumpData(index, cachetype, String:buffer[], maxlen) Format(attribute, sizeof(attribute), "team_default: \"%d\"\n", ClassGetTeamDefault(index, cachetype)); cellcount += StrCat(buffer, maxlen, attribute); - Format(attribute, sizeof(attribute), "admin_only: \"%d\"\n", ClassGetAdminOnly(index, cachetype)); + Format(attribute, sizeof(attribute), "flags: \"%d\"\n", ClassGetFlags(index, cachetype)); cellcount += StrCat(buffer, maxlen, attribute); ClassGetName(index, format_buffer, sizeof(format_buffer), cachetype);