diff --git a/src/zombiereloaded.sp b/src/zombiereloaded.sp index 69be134..9325e19 100644 --- a/src/zombiereloaded.sp +++ b/src/zombiereloaded.sp @@ -30,6 +30,7 @@ #include "zr/serial" #include "zr/sayhooks" #include "zr/tools" +#include "zr/paramtools" #include "zr/models" #include "zr/downloads" #include "zr/overlays" @@ -73,7 +74,7 @@ public Plugin:myinfo = author = "Greyscale | Richard Helgeby", description = "Infection/survival style gameplay", version = VERSION, - url = "" + url = "http://www.zombiereloaded.com" }; /** @@ -174,6 +175,7 @@ public OnConfigsExecuted() VEffectsLoad(); SEffectsLoad(); ClassLoad(); + VolLoad(); ConfigOnModulesLoaded(); ClassOnModulesLoaded(); @@ -212,4 +214,5 @@ public OnClientDisconnect(client) InfectOnClientDisconnect(client); DamageOnClientDisconnect(client); ZSpawnOnClientDisconnect(client); + VolOnPlayerDisconnect(client); } diff --git a/src/zr/commands.inc b/src/zr/commands.inc index 2008702..d66bf28 100644 --- a/src/zr/commands.inc +++ b/src/zr/commands.inc @@ -18,6 +18,7 @@ CommandsInit() // Forward event to modules. (create commands) ConfigOnCommandsCreate(); WeaponsOnCommandsCreate(); + VolOnCommandsCreate(); // Forward event to modules. (hook commands) ClassOnCommandsHook(); diff --git a/src/zr/cvars.inc b/src/zr/cvars.inc index b2cd842..efecfb9 100644 --- a/src/zr/cvars.inc +++ b/src/zr/cvars.inc @@ -114,6 +114,9 @@ enum CvarsList Handle:CVAR_RESPAWN_TEAM_ZOMBIE, Handle:CVAR_RESPAWN_TEAM_ZOMBIE_WORLD, Handle:CVAR_JUMPBOOST_BUNNYHOP_PROTECT, + Handle:CVAR_VOL, + Handle:CVAR_VOL_UPDATE_INTERVAL, + Handle:CVAR_VOL_TRIGGER_INTERVAL, Handle:CVAR_ZSPAWN, Handle:CVAR_ZSPAWN_TEAM_OVERRIDE, Handle:CVAR_ZSPAWN_TEAM_ZOMBIE, @@ -180,13 +183,12 @@ CvarsCreate() // =========================== // General (Core) // =========================== - g_hCvarsList[CVAR_ENABLE] = CreateConVar("zr_enable", "1", ""); + // =========================== // Log (core) // =========================== - g_hCvarsList[CVAR_LOG] = CreateConVar("zr_log", "1", "Logs key actions performed by the plugin, including errors and debug."); g_hCvarsList[CVAR_LOG_FILTER_MODULES] = CreateConVar("zr_log_filter_modules", "", "If any log module name is within this string, log will be suppressed. [Dependency: zr_log]"); g_hCvarsList[CVAR_LOG_FILTER_DESCRIPTION] = CreateConVar("zr_log_filter_description", "", "If any log description is within this string, log will be suppressed. [Dependency: zr_log]"); @@ -195,16 +197,17 @@ CvarsCreate() g_hCvarsList[CVAR_LOG_PRINT_CHAT] = CreateConVar("zr_log_print_chat", "1", "Print log to admin's chat area. [Dependency: zr_log & zr_log_print_admins]"); g_hCvarsList[CVAR_LOG_PRINT_CONSOLE] = CreateConVar("zr_log_print_console", "1", "Print log to admin's console. [Dependency: zr_log & zr_log_print_admins]"); + // =========================== // Translations (core) // =========================== // (None) + // =========================== // Config (core) // =========================== - g_hCvarsList[CVAR_CONFIG_PATH_MODELS] = CreateConVar("zr_config_path_models", "configs/zr/models.txt", "Path, relative to root sourcemod directory, to models config file."); g_hCvarsList[CVAR_CONFIG_PATH_DOWNLOADS] = CreateConVar("zr_config_path_downloads", "configs/zr/downloads.txt", "Path, relative to root sourcemod directory, to downloads file."); g_hCvarsList[CVAR_CONFIG_PATH_CLASSES] = CreateConVar("zr_config_path_playerclasses", "configs/zr/playerclasses.txt", "Path, relative to root sourcemod directory, to playerclasses config file."); @@ -212,24 +215,26 @@ CvarsCreate() g_hCvarsList[CVAR_CONFIG_PATH_WEAPONGROUPS] = CreateConVar("zr_config_path_weapongroups", "configs/zr/weapons/weapongroups.txt", "Path, relative to root sourcemod directory, to weapongroups config file."); g_hCvarsList[CVAR_CONFIG_PATH_HITGROUPS] = CreateConVar("zr_config_path_hitgroups", "configs/zr/hitgroups.txt", "Path, relative to root sourcemod directory, to hitgroups config file."); + // =========================== // Tools (core) // =========================== // (None) + // =========================== // Models (core) // =========================== // TODO: config file path. + // =========================== // Classes (core) // =========================== // 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]"); @@ -237,41 +242,37 @@ CvarsCreate() 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]"); // Menu - g_hCvarsList[CVAR_CLASSES_MENU_AUTOCLOSE] = CreateConVar("zr_classes_menu_autoclose", "0", "Automatically close class selection menu."); // Overlays - g_hCvarsList[CVAR_CLASSES_OVERLAY_TOGGLE] = CreateConVar("zr_classes_overlay_toggle", "1", "Allow players to toggle class overlay."); g_hCvarsList[CVAR_CLASSES_OVERLAY_TOGGLECMDS] = CreateConVar("zr_classes_overlay_togglecmds", "nightvision", "List of commands to hook that players can use to toggle class overlay. [Dependency: zr_classes_overlay_toggle | Delimiter: \", \"]"); g_hCvarsList[CVAR_CLASSES_OVERLAY_DEFAULT] = CreateConVar("zr_classes_overlay_default", "0", "Default class overlay toggle state set on connecting player. [Dependency: zr_classes_overlay_toggle]"); + // =========================== // Weapons (core) // =========================== // General - g_hCvarsList[CVAR_WEAPONS] = CreateConVar("zr_weapons", "1", "Enable weapons module, disabling this will disable any weapons-related features. (weapon restrictions, weapon knockback multipliers, etc)"); // Restrict - g_hCvarsList[CVAR_WEAPONS_RESTRICT] = CreateConVar("zr_weapons_restrict", "1", "Enable weapon restriction module, disabling this will disable weapon restriction commands."); // Market Handler - g_hCvarsList[CVAR_WEAPONS_ZMARKET_BUYZONE] = CreateConVar("zr_weapons_zmarket_buyzone", "1", "Requires player to be inside a buyzone to use ZMarket."); + // =========================== // Hitgroups (core) // =========================== - g_hCvarsList[CVAR_HITGROUPS] = CreateConVar("zr_hitgroups", "1", "Enable hitgroups module, disabling this will disable hitgroup-related features. (hitgroup knockback multipliers, hitgroup damage control)"); + // =========================== // Infect (core) // =========================== - g_hCvarsList[CVAR_INFECT_MZOMBIE_RATIO] = CreateConVar("zr_infect_mzombie_ratio", "5", "Number of mother zombies to infect (when infect timer is up) in proportion to number of humans on the server."); g_hCvarsList[CVAR_INFECT_MZOMBIE_RESPAWN] = CreateConVar("zr_infect_mzombie_respawn", "0", "Teleport mother zombies back to spawn on infect."); g_hCvarsList[CVAR_INFECT_SPAWNTIME_MIN] = CreateConVar("zr_infect_spawntime_min", "30.0", "Minimum time from the start of the round until picking the mother zombie(s)."); @@ -280,7 +281,6 @@ CvarsCreate() g_hCvarsList[CVAR_INFECT_WEAPONS_DROP] = CreateConVar("zr_infect_weapons_drop", "1", "Force player to drop all weapons on infect, disabling this will strip weapons instead."); // Effects - g_hCvarsList[CVAR_INFECT_FIREBALL] = CreateConVar("zr_infect_fireball", "1", "Spawn a fireball effect around player on infection."); g_hCvarsList[CVAR_INFECT_SMOKE] = CreateConVar("zr_infect_smoke", "1", "Spawn a smoke cloud effect around player on infection."); g_hCvarsList[CVAR_INFECT_SPARKS] = CreateConVar("zr_infect_sparks", "1", "Emit sparks from player on infection."); @@ -291,75 +291,70 @@ CvarsCreate() g_hCvarsList[CVAR_INFECT_SHAKE_FREQUENCY] = CreateConVar("zr_infect_shake_frequency", "1.0", "Frequency of shaking effect. [Dependency: zr_infect_shake]"); g_hCvarsList[CVAR_INFECT_SHAKE_DURATION] = CreateConVar("zr_infect_shake_duration", "5.0", "Duration of shaking effect. [Dependency: zr_infect_shake]"); + // =========================== // Damage (core) // =========================== // Hitgroup Damage - g_hCvarsList[CVAR_DAMAGE_HITGROUPS] = CreateConVar("zr_damage_hitgroups", "1", "Read hitgroup damage control from hitgroup config file, disabling this allows all zombie hitgroups to be shot."); // Block Damage Types - g_hCvarsList[CVAR_DAMAGE_BLOCK_FF] = CreateConVar("zr_damage_block_ff", "1", "Block friendly fire."); g_hCvarsList[CVAR_DAMAGE_BLOCK_BLAST] = CreateConVar("zr_damage_block_blast", "1", "Block blast damage inflicted on self or teammates."); // Suicide Intercept - g_hCvarsList[CVAR_DAMAGE_SUICIDE_ZOMBIE] = CreateConVar("zr_damage_suicide_zombie", "1", "Intercept suicide commands attempted by zombies."); g_hCvarsList[CVAR_DAMAGE_SUICIDE_HUMAN] = CreateConVar("zr_damage_suicide_human", "1", "Intercept suicide commands attempted by humans."); g_hCvarsList[CVAR_DAMAGE_SUICIDE_CMDS] = CreateConVar("zr_damage_suicide_cmds", "kill, spectate, jointeam", "List of client commands to intercept as suicide attempts. [Delimiter: \", \"]"); + // =========================== // Say Hooks (core) // =========================== - g_hCvarsList[CVAR_SAYHOOKS_QUIET] = CreateConVar("zr_sayhooks_quiet", "1", "Stop certain in-game commands from appearing in chat. [See zr_sayhooks_quiet_filter & zr_sayhooks_quiet_flags]"); g_hCvarsList[CVAR_SAYHOOKS_QUIET_FILTER] = CreateConVar("zr_sayhooks_quiet_filter", "1", "Stops any failed in-game command from showing in chat. Ex: Typing !zspawn while alive. [Dependency: zr_sayhooks_quiet]"); g_hCvarsList[CVAR_SAYHOOKS_QUIET_FLAGS] = CreateConVar("zr_sayhooks_quiet_flags", "58", "Flag separate in-game commands to always hide from chat. [Dependency: zr_sayhooks_quiet]\n In-Game Command Flags:\n * Add numbers of desired flags together to produce final flag value.\n --------------------------------------------------------------------\n 1: !zmenu\n 2: !zadmin\n 4: !zclass\n 8: !zspawn\n 16: !ztele\n 32: !zhp\n 64: !zmarket"); // Flags (default: 2 + 8 + 16 + 32) + // =========================== // Overlays (core) // =========================== - g_hCvarsList[CVAR_OVERLAYS_UPDATE_TIME] = CreateConVar("zr_overlays_update_time", "1.0", "How often to update overlays on players. [0.0 = Disabled]"); + // =========================== // Round End (core) // =========================== - g_hCvarsList[CVAR_ROUNDEND_OVERLAY] = CreateConVar("zr_roundend_overlay", "1", "Show specified overlay to players depending on winner when the round ends."); g_hCvarsList[CVAR_ROUNDEND_OVERLAY_HUMAN] = CreateConVar("zr_roundend_overlays_human", "overlays/zr/humans_win", "Overlay, relative to \"materials\" folder, to display when humans win the round. [Dependency: zr_roundend_overlay]"); g_hCvarsList[CVAR_ROUNDEND_OVERLAY_ZOMBIE] = CreateConVar("zr_roundend_overlays_zombie", "overlays/zr/zombies_win", "Overlay, relative to \"materials\" folder, to display when zombies win the round. [Dependency: zr_roundend_overlay]"); + // =========================== // Account (module) // =========================== - g_hCvarsList[CVAR_ACCOUNT_CASHFILL] = CreateConVar("zr_account_cashfill", "1", "Reset player's cash each spawn."); g_hCvarsList[CVAR_ACCOUNT_CASHFILL_VALUE] = CreateConVar("zr_account_cashfill_value", "12000", "Amount of cash to set player's account to. [Dependency: zr_account_cashfill]"); + // =========================== // Visual Effects (module) // =========================== // Lightstyle - g_hCvarsList[CVAR_VEFFECTS_LIGHTSTYLE] = CreateConVar("zr_veffects_lightstyle", "1", "Change lightstyle (brightness) of the map."); g_hCvarsList[CVAR_VEFFECTS_LIGHTSTYLE_VALUE] = CreateConVar("zr_veffects_lightstyle_value", "b", "Lightstyle value. ['a' = Darkest | 'z' = Brightest | Dependency: zr_veffects_lightstyle]"); // Sky - g_hCvarsList[CVAR_VEFFECTS_SKY] = CreateConVar("zr_veffects_sky", "1", "Change map skybox."); g_hCvarsList[CVAR_VEFFECTS_SKY_PATH] = CreateConVar("zr_veffects_sky_path", "sky_borealis01up.vmt", "Skybox file, relative to \"materials/skybox\" folder, to change map skybox to. [Dependency: zr_veffects_sky]"); // Sun - g_hCvarsList[CVAR_VEFFECTS_SUN_DISABLE] = CreateConVar("zr_veffects_sun_disable", "1", "Disable sun rendering on map."); // Fog - g_hCvarsList[CVAR_VEFFECTS_FOG] = CreateConVar("zr_veffects_fog", "0", "(UNSUPPORTED) Enable fog rendering on the map."); g_hCvarsList[CVAR_VEFFECTS_FOG_OVERRIDE] = CreateConVar("zr_veffects_fog_override", "0", "(UNSUPPORTED) If fog exists already on the map, then replace with new modified fog. [Dependency: zr_veffects_fog]"); g_hCvarsList[CVAR_VEFFECTS_FOG_PCOLOR] = CreateConVar("zr_veffects_fog_pcolor", "255 255 255", "(UNSUPPORTED) Primary color of the fog. [Dependency: zr_veffects_fog]"); @@ -369,70 +364,79 @@ CvarsCreate() g_hCvarsList[CVAR_VEFFECTS_FOG_ENDDIST] = CreateConVar("zr_veffects_fog_enddist", "400", "(UNSUPPORTED) Distance from player to stop rendering fog. [Dependency: zr_veffects_fog]"); g_hCvarsList[CVAR_VEFFECTS_FOG_FARZ] = CreateConVar("zr_veffects_fog_farz", "2000", "(UNSUPPORTED) Vertical clipping plane."); + // =========================== // Sound Effects (module) // =========================== // Zombie Sounds - g_hCvarsList[CVAR_SEFFECTS_MOAN] = CreateConVar("zr_seffects_moan", "30.0", "Time between emission of a moan sound from a zombie."); g_hCvarsList[CVAR_SEFFECTS_GROAN] = CreateConVar("zr_seffects_groan", "5", "The probability that a groan sound will be emitted from a zombie when shot. ['100' = 1% chance | '50' = 2% chance | '1' = 100% chance]"); g_hCvarsList[CVAR_SEFFECTS_DEATH] = CreateConVar("zr_seffects_death", "1", "Emit a death sound when a zombie dies."); // Ambient Sounds - g_hCvarsList[CVAR_AMBIENTSOUNDS] = CreateConVar("zr_ambientsounds", "1", "Play an ambient sound to all players during gameplay."); g_hCvarsList[CVAR_AMBIENTSOUNDS_FILE] = CreateConVar("zr_ambientsounds_file", "ambient/zr/zr_ambience.mp3", "Sound file, relative to \"sounds\" folder, to play as ambience. [Dependency: zr_ambientsounds]"); g_hCvarsList[CVAR_AMBIENTSOUNDS_LENGTH] = CreateConVar("zr_ambientsounds_length", "60.0", "Length of the ambient sound. [Dependency: zr_ambientsounds]"); g_hCvarsList[CVAR_AMBIENTSOUNDS_VOLUME] = CreateConVar("zr_ambientsounds_volume", "0.8", "Volume of the ambient sound. [1.0 = Max volume | 0.0001 = Not audible | Dependency: zr_ambientsounds]"); + // =========================== // Antistick (module) // =========================== - g_hCvarsList[CVAR_ANTISTICK] = CreateConVar("zr_antistick", "1", "Automatically unstick players when stuck within each others' collision hull."); g_hCvarsList[CVAR_ANTISTICK_INTERVAL] = CreateConVar("zr_antistick_interval", "0.5", "Time between each check for stuck players. [Dependency: zr_antistick]"); + // =========================== // Knockback (module) // =========================== // (None) + // =========================== // Spawn Protect (module) // =========================== - g_hCvarsList[CVAR_SPAWNPROTECT] = CreateConVar("zr_spawnprotect", "1", ""); g_hCvarsList[CVAR_SPAWNPROTECT_TIME] = CreateConVar("zr_spawnprotect_time", "10", ""); g_hCvarsList[CVAR_SPAWNPROTECT_SPEED] = CreateConVar("zr_spawnprotect_speed", "600.0", ""); g_hCvarsList[CVAR_SPAWNPROTECT_ALPHA] = CreateConVar("zr_spawnprotect_alpha", "0", ""); + // =========================== // Respawn (module) // =========================== - g_hCvarsList[CVAR_RESPAWN] = CreateConVar("zr_respawn", "0", "Respawn players after death. [Recommended: (Enable) zr_zspawn*]"); g_hCvarsList[CVAR_RESPAWN_DELAY] = CreateConVar("zr_respawn_delay", "1", "Time after death to delay player respawn. [Dependency: zr_respawn]"); g_hCvarsList[CVAR_RESPAWN_TEAM_ZOMBIE] = CreateConVar("zr_respawn_team_zombie", "1", "Respawn player as a zombie. [Dependency: zr_respawn]"); g_hCvarsList[CVAR_RESPAWN_TEAM_ZOMBIE_WORLD] = CreateConVar("zr_respawn_team_zombie_world", "1", "Respawn player as a zombie if player was killed by the world. [Override: zr_respawn_team_zombie]"); + // =========================== // Napalm (module) // =========================== // (None) + // =========================== // Jump Boost (module) // =========================== - g_hCvarsList[CVAR_JUMPBOOST_BUNNYHOP_PROTECT] = CreateConVar("zr_jumpboost_bunnyhop_protect", "1", "Prevent players from using forward jump boost multipliers to bunny hop."); + + // =========================== + // Volumetric features (module) + // =========================== + g_hCvarsList[CVAR_VOL] = CreateConVar("zr_vol", "1", "Enables volumetric features."); + g_hCvarsList[CVAR_VOL_UPDATE_INTERVAL] = CreateConVar("zr_vol_update_interval", "1.0", "How often to update player positions and trigger events, in seconds."); + g_hCvarsList[CVAR_VOL_TRIGGER_INTERVAL] = CreateConVar("zr_vol_trigger_interval", "1.0", "How often to check for delayed events, in seconds. Use lower values for more precise delays."); + + // =========================== // ZSpawn (module) // =========================== - g_hCvarsList[CVAR_ZSPAWN] = CreateConVar("zr_zspawn", "1", "Allow players to spawn into the game late."); g_hCvarsList[CVAR_ZSPAWN_TEAM_OVERRIDE] = CreateConVar("zr_zspawn_team_override", "1", "Override spawn team when spawning by means of ZSpawn."); @@ -440,10 +444,11 @@ CvarsCreate() g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT] = CreateConVar("zr_zspawn_timelimit", "1", "Put a time limit on the use of ZSpawn."); g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT_TIME] = CreateConVar("zr_zspawn_timelimit_time", "120.0", "Time from the start of the round to allow ZSpawn. [Dependency: zr_zspawn_timelimit]"); + + // =========================== // ZTele (module) // =========================== - g_hCvarsList[CVAR_ZTELE_ZOMBIE] = CreateConVar("zr_ztele_zombie", "1", "Allow zombies to use ZTele."); g_hCvarsList[CVAR_ZTELE_HUMAN_BEFORE] = CreateConVar("zr_ztele_human_before", "1", "Allow humans to use ZTele before the mother zombie has spawned."); g_hCvarsList[CVAR_ZTELE_HUMAN_AFTER] = CreateConVar("zr_ztele_human_after", "0", "Allow humans to use ZTele after the mother zombie has spawned."); @@ -454,13 +459,14 @@ CvarsCreate() g_hCvarsList[CVAR_ZTELE_AUTOCANCEL] = CreateConVar("zr_ztele_autocancel", "1", "Automatically cancel ZTele if player moves out of a set boundary. [Dependency: zr_ztele_(zombie)/(human)[_(before)/(after)]]"); g_hCvarsList[CVAR_ZTELE_AUTOCANCEL_DISTANCE] = CreateConVar("zr_ztele_autocancel_distance", "20", "Maximum distance, in feet, player is allowed to travel before teleport is cancelled. [Dependency: zr_ztele_autocancel]"); + // =========================== // ZHP (module) // =========================== - g_hCvarsList[CVAR_ZHP] = CreateConVar("zr_zhp", "1", "Allow player to toggle real HP display as a zombie."); g_hCvarsList[CVAR_ZHP_DEFAULT] = CreateConVar("zr_zhp_default", "1", "Default ZHP toggle state set on connecting player. [Dependency: zr_zhp]"); + // Auto-generate config file if it doesn't exist, then execute. AutoExecConfig(true, "zombiereloaded", "sourcemod/zombiereloaded"); } @@ -480,6 +486,8 @@ CvarsHook(bool:unhook = false) UnhookConVarChange(g_hLimitTeams, CvarsHookLocked); UnhookConVarChange(g_hRestartGame, CvarsHookRestartGame); + UnhookConVarChange(g_hCvarsList[CVAR_VOL], VolEnabledChanged); + // Stop after unhooking cvars. return; } @@ -492,6 +500,8 @@ CvarsHook(bool:unhook = false) HookConVarChange(g_hAutoTeamBalance, CvarsHookLocked); HookConVarChange(g_hLimitTeams, CvarsHookLocked); HookConVarChange(g_hRestartGame, CvarsHookRestartGame); + + HookConVarChange(g_hCvarsList[CVAR_VOL], VolEnabledChanged); } /** diff --git a/src/zr/event.inc b/src/zr/event.inc index f9d1e16..3b2a59d 100644 --- a/src/zr/event.inc +++ b/src/zr/event.inc @@ -187,6 +187,7 @@ public Action:EventPlayerSpawn(Handle:event, const String:name[], bool:dontBroad RespawnOnClientSpawn(index); ZTeleOnClientSpawn(index); ZHPOnClientSpawn(index); + VolOnPlayerSpawn(index); TranslationPrintToChat(index, "General zmenu reminder"); diff --git a/src/zr/paramtools.inc b/src/zr/paramtools.inc new file mode 100644 index 0000000..cb61b20 --- /dev/null +++ b/src/zr/paramtools.inc @@ -0,0 +1,200 @@ +/* + * ============================================================================ + * + * Zombie:Reloaded + * + * File: paramtools.inc + * Type: Core + * Description: Provides functions for parsing strings with parameters in + * key=value format. + * + * Copyright (C) 2009 Greyscale, Richard Helgeby + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * ============================================================================ + */ + + +/** + * Counts number of parameters in a string. + */ +stock GetParameterCount(const String:rawString[]) +{ + new lenRawString = strlen(rawString); + new paramCount; + + // Check if the raw string is empty. + if (lenRawString == 0) + { + return 0; + } + + // Count number of "=". + for (new searchPos = 0; searchPos < lenRawString; searchPos++) + { + // Set searchPos and check if "=" was found. + searchPos = StrContains(rawString[searchPos], "="); + if (searchPos) + { + paramCount++; + + // Increment one position so we dont find the same "=" again. + searchPos++; + } + else + { + // Exit loop. + break; + } + } + + return paramCount; +} + +/** + * Gets a value from a string in key=value format and writes it to a buffer. + * + * Note: No spaces in values or parameter names. Only spaces between each + * key/value set. + * + * Example raw string: "key1=val1 key2=5.3 key3=1" + * + * @param buffer Destination string bufffer. + * @param maxlen Length of destination buffer. + * @param rawString Source string to read from. + * @param parameter Parameter to read. + * + * @return Number of cells written. -1 if the parameter wasn't + * found. + */ +stock GetParameterValue(String:buffer[], maxlen, const String:rawString[], const String:parameter[]) +{ + new paramPos; + new paramLen; + new valuePos; + new valueLen; + new nextPos; + + // Get the position of parameter. + paramPos = StrContains(rawString, parameter, false); + + // Check if found. + if (paramPos >= 0) + { + // Get parameter length. + paramLen = strlen(parameter); + + // Get the position of the next parameter. + nextPos = StrContains(rawString[paramPos + 1], " "); + + // Check if the next parameter was found. + if (nextPos >= 0) + { + // Calculate value starting position. + valuePos = paramPos + paramLen + 1; + + // Calculate value length. + valueLen = nextPos - valuePos; + + // Check if value length is longer than buffer size. + if (valueLen > maxlen) + { + valueLen = maxlen; + } + + // Copy value to buffer. + return strcopy(buffer, valueLen, rawString[valuePos]); + + } + else + { + // It's the last or only parameter, get the rest of the string. + return strcopy(buffer, maxlen, rawString[paramPos + paramLen + 1]); + } + } + else + { + return -1; + } +} + +/** + * Gets the name of the parameter at the specified index. + * + * @param buffer Destination string bufffer. + * @param maxlen Length of destination buffer. + * @param rawString Source string to read from. + * @param parameterIndex The zero-based parameter index to read. + * + * @return Number of cells written. -1 if failed. + */ +stock GetParameterName(String:buffer[], maxlen, const String:rawString[], parameterIndex) +{ + new paramPos; + new valuePos; + new nextValuePos; + + // Check if the raw string is empty. + if (strlen(rawString) == 0) + { + return -1; + } + + if (parameterIndex > 0) + { + // Get the value starting position for the previous index. + for (new index = 0; index < parameterIndex - 1; index++) + { + valuePos = StrContains(rawString[valuePos], "="); + } + + // Find the next space from valuePos where the specified parameter + // starts. + paramPos = StrContains(rawString[valuePos], " ") + 1; + + // Find the next value position from paramPos to get the end position + // of the parameter name. + nextValuePos = StrContains(rawString[paramPos], "="); + + // Check if a value is specified. + if (nextValuePos > 0) + { + // Return the parameter name between paramPos and nextValuePos. + return strcopy(buffer, nextValuePos - paramPos, rawString[paramPos]); + } + else + { + // No value specified. Return the rest of rawString from paramPos. + return strcopy(buffer, maxlen, rawString[paramPos]); + } + } + else + { + // It's the first parameter. Read the string until '=' is found. + valuePos = StrContains(rawString, "="); + + // Check if a value is specified. + if (valuePos > 0) + { + // Return the parameter name. + return strcopy(buffer, valuePos, rawString); + } + else + { + // No value specified, return the entire raw string. + return strcopy(buffer, maxlen, rawString); + } + } +} diff --git a/src/zr/playerclasses/attributes.inc b/src/zr/playerclasses/attributes.inc index 5f6fbb5..e37efbf 100644 --- a/src/zr/playerclasses/attributes.inc +++ b/src/zr/playerclasses/attributes.inc @@ -31,7 +31,7 @@ * index will be used as a client index. * @return True if it's enabled, false otherwise. */ -bool:ClassIsEnabled(index, cachetype = ZR_CLASS_CACHE_MODIFIED) +stock bool:ClassIsEnabled(index, cachetype = ZR_CLASS_CACHE_MODIFIED) { switch (cachetype) { @@ -63,7 +63,7 @@ bool:ClassIsEnabled(index, cachetype = ZR_CLASS_CACHE_MODIFIED) * is used, index will be used as a client index. * @return The team ID if successful, -1 otherwise. */ -ClassGetTeamID(index, cachetype = ZR_CLASS_CACHE_PLAYER) +stock ClassGetTeamID(index, cachetype = ZR_CLASS_CACHE_PLAYER) { switch (cachetype) { @@ -97,7 +97,7 @@ ClassGetTeamID(index, cachetype = ZR_CLASS_CACHE_PLAYER) * index will be used as a client index. * @return True if it's default for its current team, false otherwise. */ -bool:ClassGetTeamDefault(index, cachetype = ZR_CLASS_CACHE_MODIFIED) +stock bool:ClassGetTeamDefault(index, cachetype = ZR_CLASS_CACHE_MODIFIED) { switch (cachetype) { @@ -131,7 +131,7 @@ bool:ClassGetTeamDefault(index, cachetype = ZR_CLASS_CACHE_MODIFIED) * is used, index will be used as a client index. * @return Number of cells written. -1 on error. */ -ClassGetName(index, String:buffer[], maxlen, cachetype = ZR_CLASS_CACHE_PLAYER) +stock ClassGetName(index, String:buffer[], maxlen, cachetype = ZR_CLASS_CACHE_PLAYER) { switch (cachetype) { @@ -166,7 +166,7 @@ ClassGetName(index, String:buffer[], maxlen, cachetype = ZR_CLASS_CACHE_PLAYER) * is used, index will be used as a client index. * @return Number of cells written. -1 on error. */ -ClassGetDescription(index, String:buffer[], maxlen, cachetype = ZR_CLASS_CACHE_PLAYER) +stock ClassGetDescription(index, String:buffer[], maxlen, cachetype = ZR_CLASS_CACHE_PLAYER) { switch (cachetype) { @@ -210,7 +210,7 @@ ClassGetDescription(index, String:buffer[], maxlen, cachetype = ZR_CLASS_CACHE_P * is used, index will be used as a client index. * @return Number of cells written. -1 on error. */ -ClassGetModelPath(index, String:buffer[], maxlen, cachetype = ZR_CLASS_CACHE_PLAYER) +stock ClassGetModelPath(index, String:buffer[], maxlen, cachetype = ZR_CLASS_CACHE_PLAYER) { switch (cachetype) { @@ -242,7 +242,7 @@ ClassGetModelPath(index, String:buffer[], maxlen, cachetype = ZR_CLASS_CACHE_PLA * is used, index will be used as a client index. * @return The initial alpha value from the specified class. -1 on error. */ -ClassGetAlphaInitial(index, cachetype = ZR_CLASS_CACHE_PLAYER) +stock ClassGetAlphaInitial(index, cachetype = ZR_CLASS_CACHE_PLAYER) { switch (cachetype) { @@ -275,7 +275,7 @@ ClassGetAlphaInitial(index, cachetype = ZR_CLASS_CACHE_PLAYER) * @return The alpha value when damaged, from the specified class. -1 on * error. */ -ClassGetAlphaDamaged(index, cachetype = ZR_CLASS_CACHE_PLAYER) +stock ClassGetAlphaDamaged(index, cachetype = ZR_CLASS_CACHE_PLAYER) { switch (cachetype) { @@ -308,7 +308,7 @@ ClassGetAlphaDamaged(index, cachetype = ZR_CLASS_CACHE_PLAYER) * @return The damage amount needed to change alpha, from the specified class. * -1 on error. */ -ClassGetAlphaDamage(index, cachetype = ZR_CLASS_CACHE_PLAYER) +stock ClassGetAlphaDamage(index, cachetype = ZR_CLASS_CACHE_PLAYER) { switch (cachetype) { @@ -352,7 +352,7 @@ ClassGetAlphaDamage(index, cachetype = ZR_CLASS_CACHE_PLAYER) * is used, index will be used as a client index. * @return Number of cells written. -1 on error. */ -ClassGetOverlayPath(index, String:buffer[], maxlen, cachetype = ZR_CLASS_CACHE_PLAYER) +stock ClassGetOverlayPath(index, String:buffer[], maxlen, cachetype = ZR_CLASS_CACHE_PLAYER) { switch (cachetype) { @@ -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) +stock bool:ClassGetNvgs(index, cachetype = ZR_CLASS_CACHE_PLAYER) { switch (cachetype) { @@ -416,7 +416,7 @@ bool:ClassGetNvgs(index, cachetype = ZR_CLASS_CACHE_PLAYER) * is used, index will be used as a client index. * @return The field of view value from the specified class. -1 on error. */ -ClassGetFOV(index, cachetype = ZR_CLASS_CACHE_PLAYER) +stock ClassGetFOV(index, cachetype = ZR_CLASS_CACHE_PLAYER) { switch (cachetype) { @@ -458,7 +458,7 @@ ClassGetFOV(index, cachetype = ZR_CLASS_CACHE_PLAYER) * is used, index will be used as a client index. * @return The napalm grenades time from the specified class. -1.0 on error. */ -Float:ClassGetNapalmTime(index, cachetype = ZR_CLASS_CACHE_PLAYER) +stock Float:ClassGetNapalmTime(index, cachetype = ZR_CLASS_CACHE_PLAYER) { switch (cachetype) { @@ -500,7 +500,7 @@ Float:ClassGetNapalmTime(index, cachetype = ZR_CLASS_CACHE_PLAYER) * is used, index will be used as a client index. * @return Current immunity mode to the specified class. -1 on error. */ -ClassGetImmunityMode(index, cachetype = ZR_CLASS_CACHE_PLAYER) +stock ClassGetImmunityMode(index, cachetype = ZR_CLASS_CACHE_PLAYER) { switch (cachetype) { @@ -532,7 +532,7 @@ ClassGetImmunityMode(index, cachetype = ZR_CLASS_CACHE_PLAYER) * is used, index will be used as a client index. * @return Current immunity amount to the specified class. -1.0 on error. */ -Float:ClassGetImmunityAmount(index, cachetype = ZR_CLASS_CACHE_PLAYER) +stock Float:ClassGetImmunityAmount(index, cachetype = ZR_CLASS_CACHE_PLAYER) { switch (cachetype) { @@ -565,7 +565,7 @@ Float:ClassGetImmunityAmount(index, cachetype = ZR_CLASS_CACHE_PLAYER) * @return The no fall damage setting from the specified class. False on * error. */ -bool:ClassGetNoFallDamage(index, cachetype = ZR_CLASS_CACHE_PLAYER) +stock bool:ClassGetNoFallDamage(index, cachetype = ZR_CLASS_CACHE_PLAYER) { switch (cachetype) { @@ -597,7 +597,7 @@ bool:ClassGetNoFallDamage(index, cachetype = ZR_CLASS_CACHE_PLAYER) * is used, index will be used as a client index. * @return Health points from the specified class. -1 on error. */ -ClassGetHealth(index, cachetype = ZR_CLASS_CACHE_PLAYER) +stock ClassGetHealth(index, cachetype = ZR_CLASS_CACHE_PLAYER) { switch (cachetype) { @@ -630,7 +630,7 @@ ClassGetHealth(index, cachetype = ZR_CLASS_CACHE_PLAYER) * @return The health regen interval time from the specified class. -1.0 on * error. */ -Float:ClassGetHealthRegenInterval(index, cachetype = ZR_CLASS_CACHE_PLAYER) +stock Float:ClassGetHealthRegenInterval(index, cachetype = ZR_CLASS_CACHE_PLAYER) { switch (cachetype) { @@ -663,7 +663,7 @@ Float:ClassGetHealthRegenInterval(index, cachetype = ZR_CLASS_CACHE_PLAYER) * @return The health regen amount value from the specified class. -1 on * error. */ -ClassGetHealthRegenAmount(index, cachetype = ZR_CLASS_CACHE_PLAYER) +stock ClassGetHealthRegenAmount(index, cachetype = ZR_CLASS_CACHE_PLAYER) { switch (cachetype) { @@ -696,7 +696,7 @@ ClassGetHealthRegenAmount(index, cachetype = ZR_CLASS_CACHE_PLAYER) * @return The health infect gain value from the specified class. -1 on * error. */ -ClassGetHealthInfectGain(index, cachetype = ZR_CLASS_CACHE_PLAYER) +stock ClassGetHealthInfectGain(index, cachetype = ZR_CLASS_CACHE_PLAYER) { switch (cachetype) { @@ -728,7 +728,7 @@ ClassGetHealthInfectGain(index, cachetype = ZR_CLASS_CACHE_PLAYER) * is used, index will be used as a client index. * @return The kill bonus points from the specified class. */ -ClassGetKillBonus(index, cachetype = ZR_CLASS_CACHE_PLAYER) +stock ClassGetKillBonus(index, cachetype = ZR_CLASS_CACHE_PLAYER) { switch (cachetype) { @@ -760,7 +760,7 @@ ClassGetKillBonus(index, cachetype = ZR_CLASS_CACHE_PLAYER) * is used, index will be used as a client index. * @return The running speed value from the specified class. -1.0 on error. */ -Float:ClassGetSpeed(index, cachetype = ZR_CLASS_CACHE_PLAYER) +stock Float:ClassGetSpeed(index, cachetype = ZR_CLASS_CACHE_PLAYER) { switch (cachetype) { @@ -792,7 +792,7 @@ Float:ClassGetSpeed(index, cachetype = ZR_CLASS_CACHE_PLAYER) * is used, index will be used as a client index. * @return The knock back boost from the specified class. 0.0 on error. */ -Float:ClassGetKnockback(index, cachetype = ZR_CLASS_CACHE_PLAYER) +stock Float:ClassGetKnockback(index, cachetype = ZR_CLASS_CACHE_PLAYER) { switch (cachetype) { @@ -824,7 +824,7 @@ Float:ClassGetKnockback(index, cachetype = ZR_CLASS_CACHE_PLAYER) * is used, index will be used as a client index. * @return The jump height boost from the specified class. -1.0 on error. */ -Float:ClassGetJumpHeight(index, cachetype = ZR_CLASS_CACHE_PLAYER) +stock Float:ClassGetJumpHeight(index, cachetype = ZR_CLASS_CACHE_PLAYER) { switch (cachetype) { @@ -856,7 +856,7 @@ Float:ClassGetJumpHeight(index, cachetype = ZR_CLASS_CACHE_PLAYER) * is used, index will be used as a client index. * @return The jump distance boost from the specified class. -1.0 on error. */ -Float:ClassGetJumpDistance(index, cachetype = ZR_CLASS_CACHE_PLAYER) +stock Float:ClassGetJumpDistance(index, cachetype = ZR_CLASS_CACHE_PLAYER) { switch (cachetype) { @@ -883,7 +883,7 @@ Float:ClassGetJumpDistance(index, cachetype = ZR_CLASS_CACHE_PLAYER) * @return The flag that reporesent the specified attribute. * -1 on error. */ -ClassAttributeNameToFlag(const String:attributename[]) +stock ClassAttributeNameToFlag(const String:attributename[]) { // Check attribute names. if (StrEqual(attributename, "enabled", false)) @@ -998,7 +998,7 @@ ClassAttributeNameToFlag(const String:attributename[]) * @return The data type used in the specified attribute, or * ClassType_InvalidType if failed. */ -ClassDataTypes:ClassGetAttributeType(attributeflag) +stock ClassDataTypes:ClassGetAttributeType(attributeflag) { switch (attributeflag) { diff --git a/src/zr/playerclasses/filtertools.inc b/src/zr/playerclasses/filtertools.inc index 70380df..79a8ed9 100644 --- a/src/zr/playerclasses/filtertools.inc +++ b/src/zr/playerclasses/filtertools.inc @@ -20,7 +20,7 @@ * ZR_CLASS_CACHE_MODIFIED (modified class data). * @return True if validation was successful, false otherwise. */ -bool:ClassValidateTeamRequirements(cachetype = ZR_CLASS_CACHE_ORIGINAL) +stock bool:ClassValidateTeamRequirements(cachetype = ZR_CLASS_CACHE_ORIGINAL) { new zombieindex; new humanindex; @@ -52,7 +52,7 @@ bool:ClassValidateTeamRequirements(cachetype = ZR_CLASS_CACHE_ORIGINAL) * ZR_CLASS_CACHE_MODIFIED (modified class data). * @return True if validation was successful, false otherwise. */ -bool:ClassValidateTeamDefaults(cachetype = ZR_CLASS_CACHE_ORIGINAL) +stock bool:ClassValidateTeamDefaults(cachetype = ZR_CLASS_CACHE_ORIGINAL) { new zombieindex; new humanindex; @@ -85,7 +85,7 @@ bool:ClassValidateTeamDefaults(cachetype = ZR_CLASS_CACHE_ORIGINAL) * @param classindex The index of the class to validate. * @return A value with attribute error flags. */ -ClassValidateAttributes(classindex) +stock ClassValidateAttributes(classindex) { // TODO: Validate immunity mode and amount. @@ -257,7 +257,7 @@ ClassValidateAttributes(classindex) * @param classindex The class index to validate. * @return True if the class exist, false otherwise. */ -bool:ClassValidateIndex(classindex) +stock bool:ClassValidateIndex(classindex) { if (classindex >= 0 && classindex < ClassCount) { @@ -284,7 +284,7 @@ bool:ClassValidateIndex(classindex) * index will be used as a client index. * @return True if equal, false otherwise. */ -bool:ClassTeamCompare(index, teamid, cachetype = ZR_CLASS_CACHE_MODIFIED) +stock bool:ClassTeamCompare(index, teamid, cachetype = ZR_CLASS_CACHE_MODIFIED) { switch (cachetype) { @@ -324,7 +324,7 @@ bool:ClassTeamCompare(index, teamid, cachetype = ZR_CLASS_CACHE_MODIFIED) * data. * @return The class index if successful, -1 otherwise. */ -ClassGetIndex(const String:name[], cachetype = ZR_CLASS_CACHE_MODIFIED) +stock ClassGetIndex(const String:name[], cachetype = ZR_CLASS_CACHE_MODIFIED) { decl String:current_name[64]; @@ -356,7 +356,7 @@ ClassGetIndex(const String:name[], cachetype = ZR_CLASS_CACHE_MODIFIED) * @param client The client index. * @return The active class index. -1 on error or if a spectactor. */ -ClassGetActiveIndex(client) +stock ClassGetActiveIndex(client) { new teamid = GetClientTeam(client); @@ -405,7 +405,7 @@ ClassGetActiveIndex(client) * @return True on success. False on error or if no classes were added or * found. */ -bool:ClassAddToArray(Handle:array, teamfilter = -1, bool:ignoreEnabled = false, cachetype = ZR_CLASS_CACHE_MODIFIED) +stock bool:ClassAddToArray(Handle:array, teamfilter = -1, bool:ignoreEnabled = false, cachetype = ZR_CLASS_CACHE_MODIFIED) { // Validate the array. if (array == INVALID_HANDLE) @@ -476,7 +476,7 @@ bool:ClassAddToArray(Handle:array, teamfilter = -1, bool:ignoreEnabled = false, * class data. * @return Number of total classes or classes in the specified team. */ -ClassCountTeam(teamfilter = -1, bool:ignoreEnabled = false, cachetype = ZR_CLASS_CACHE_MODIFIED) +stock ClassCountTeam(teamfilter = -1, bool:ignoreEnabled = false, cachetype = ZR_CLASS_CACHE_MODIFIED) { // Check if there are no classes. if (ClassCount == 0) @@ -533,7 +533,7 @@ ClassCountTeam(teamfilter = -1, bool:ignoreEnabled = false, cachetype = ZR_CLASS * class data. * @return The class index if successful, or -1 on error. */ -ClassGetRandomClass(teamfilter = -1, bool:ignoreEnabled = false, cachetype = ZR_CLASS_CACHE_MODIFIED) +stock ClassGetRandomClass(teamfilter = -1, bool:ignoreEnabled = false, cachetype = ZR_CLASS_CACHE_MODIFIED) { new Handle:classarray; new arraycount; @@ -574,7 +574,7 @@ ClassGetRandomClass(teamfilter = -1, bool:ignoreEnabled = false, cachetype = ZR_ * @return The first class index, or the first class index with the specified * team ID. -1 on error. */ -ClassGetFirstClass(teamfilter = -1, bool:ignoreEnabled = false, cachetype = ZR_CLASS_CACHE_MODIFIED) +stock ClassGetFirstClass(teamfilter = -1, bool:ignoreEnabled = false, cachetype = ZR_CLASS_CACHE_MODIFIED) { // Check if there are no classes. if (ClassCount == 0) @@ -623,7 +623,7 @@ ClassGetFirstClass(teamfilter = -1, bool:ignoreEnabled = false, cachetype = ZR_C * class data. * @return The first default class index. -1 on error. */ -ClassGetDefaultClass(teamid, bool:ignoreEnabled = false, cachetype = ZR_CLASS_CACHE_MODIFIED) +stock ClassGetDefaultClass(teamid, bool:ignoreEnabled = false, cachetype = ZR_CLASS_CACHE_MODIFIED) { new Handle:classarray; new arraycount; @@ -669,7 +669,7 @@ ClassGetDefaultClass(teamid, bool:ignoreEnabled = false, cachetype = ZR_CLASS_CA * successful. -1 on critical errors. Otherwise it will try to fall * back on the first class in the specified team. */ -ClassGetDefaultSpawnClass(teamid, cachetype = ZR_CLASS_CACHE_MODIFIED) +stock ClassGetDefaultSpawnClass(teamid, cachetype = ZR_CLASS_CACHE_MODIFIED) { decl String:classname[64]; new classindex; diff --git a/src/zr/volfeatures/volanticamp.inc b/src/zr/volfeatures/volanticamp.inc index 5af4e3b..1f6b31f 100644 --- a/src/zr/volfeatures/volanticamp.inc +++ b/src/zr/volfeatures/volanticamp.inc @@ -1,11 +1,26 @@ /* * ============================================================================ * - * Zombie:Reloaded + * Zombie:Reloaded * - * File: volanticamp.inc - * Type: Module - * Description: Anti-camp handler. + * File: volanticamp.inc + * Type: Module + * Description: Anti-camp handler. + * + * Copyright (C) 2009 Greyscale, Richard Helgeby + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . * * ============================================================================ */ @@ -15,9 +30,37 @@ */ enum VolTypeAnticamp { - anticamp_damage, - anticamp_interval, - Handle:anticamp_timer + Float:anticamp_interval, /** How often to trigger an action. */ + Handle:anticamp_timer, /** Action timer handle. */ + + VolAnticampAction:antivamp_action, /** What to do with players in anti-camp volumes */ + Float:anticamp_amount, /** Amount depending on action type. Usually time in seconds or damage amount. */ + + VolAnticampeWarningType:anticamp_warning, /** How to warn the player. */ + String:anticamp_message[256] /** Override warning message. Max 256 characters. */ +} + +/** + * Actions to do with players in anti-camp volumes. + */ +enum VolAnticampAction +{ + anticamp_no_action, /** Do nothing but give a warning. */ + anticamp_damage, /** Give damage to player. */ + anticamp_slay, /** Slay player. */ + anticamp_drug, /** Drug player. */ + anticamp_fire /** Ignite player. */ +} + +/** + * Warning types. + */ +enum VolAnticampeWarningType +{ + anticamp_no_warning, /** No warning messages. */ + anticamp_chat, /** Print warning in chat area. */ + anticamp_center, /** Print centered warning message. */ + anticamp_menu /** Print a menu-like warning message with close option. */ } /** diff --git a/src/zr/volfeatures/volcommands.inc b/src/zr/volfeatures/volcommands.inc new file mode 100644 index 0000000..de40f3d --- /dev/null +++ b/src/zr/volfeatures/volcommands.inc @@ -0,0 +1,225 @@ +/* + * ============================================================================ + * + * Zombie:Reloaded + * + * File: volcommands.inc + * Type: Module + * Description: Command handler for volumetric features. + * + * Copyright (C) 2009 Greyscale, Richard Helgeby + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * ============================================================================ + */ + +/* +Add volume +------------ + +Syntax: + + zr_vol_add [params] + +Parameters: + + zn, yn, zn Max and min location. + type Feature type. + params A string with optional parameters: + team=all|humans|zombies + delay=0 + effect=none|wireframe|smoke + effect_color=0,0,0 + enabled=1 + +Example: + + zr_vol_add 0 0 0 100 200 300 anticamp team=humans delay=5 effect=wireframe effect_color=255,0,0 +*/ + +public Action:VolAddVolumeCommand(client, argc) +{ + +} + +/** + * Creates a new volume with minimum parameters. + * + * Note: Extra volume attributes must be set using VolSetAttributes. + * + * @param locMin Minimum x, y and z values. + * @param locMax Maximum x, y and z values. + * @param volumeType Specifies the volumetric feature type. + * @param dataIndex Data index in remote array for feature data. + * + * @return The new volume index, or -1 if failed. + */ +VolAdd(Float:locMin[3], Float:locMax[3], VolumeFeatureTypes:volumeType, dataIndex) +{ + new volumeIndex; + + // Get a free volume index. + volumeIndex = VolGetFreeVolume(); + + // Validate index. + if (volumeIndex >= 0) + { + // Mark volume as enabled and in use. + Volumes[volumeIndex][vol_enabled] = true; + Volumes[volumeIndex][vol_in_use] = true; + + // Set location data. + Volumes[volumeIndex][vol_x_min] = locMin[0]; + Volumes[volumeIndex][vol_y_min] = locMin[1]; + Volumes[volumeIndex][vol_z_min] = locMin[2]; + + Volumes[volumeIndex][vol_x_max] = locMax[0]; + Volumes[volumeIndex][vol_y_max] = locMax[1]; + Volumes[volumeIndex][vol_z_max] = locMax[2]; + + // Set type. + Volumes[volumeIndex][vol_type] = volumeType; + Volumes[volumeIndex][vol_data_index] = dataIndex; + + // Return the new index. + return volumeIndex; + } + else + { + // No free volumes. + return -1; + } +} + +/** + * Removes the specified volume. + * + * @param volumeIndex The volume index. + * @return True if successful, false otherwise. + */ +bool:VolRemove(volumeIndex) +{ + // Validate index. + if (volumeIndex >= 0) + { + // Trigger event. + VolOnVolumeDisabled(volumeIndex); + + // Mark volume as disabled and unused. + Volumes[volumeIndex][vol_enabled] = false; + Volumes[volumeIndex][vol_in_use] = false; + + return true; + } + else + { + // Invalid index. + return false; + } +} + +/** + * Sets extra attributes on a volume. + * + * @param volumeIndex The volume index. + * @param attributes A string with one or more attributes in key=value + * format. + * @return Number of successful attributes set, -1 on error. + */ +VolSetAttributes(volumeIndex, const String:attributes[]) +{ + new attribCount; + new successfulCount; + decl String:attribName[64]; + decl String:attribValue[256]; + + // Validate volume index. + if (!VolIsValidIndex(volumeIndex)) + { + return -1; + } + + // Count attributes. + attribCount = GetParameterCount(attributes); + + // Check if empty. + if (!attribCount) + { + return -1; + } + + // Loop through all attributes. + for (new attrib = 0; attrib > attribCount; attrib++) + { + // Get attribute name. + GetParameterName(attribName, sizeof(attribName), attributes, attrib); + + // Get attribute value. + GetParameterValue(attribValue, sizeof(attribValue), attributes, attribName); + + // Check names and set volume attributes. + if (strcmp(attribName, "team", false)) + { + // Parse team string value. + if (VolSetTeamString(volumeIndex, attribValue)) + { + successfulCount++; + } + } + else if (strcmp(attribName, "delay", false)) + { + // Parse delay string value. + if (VolSetDelayString(volumeIndex, attribValue)) + { + successfulCount++; + } + } + else if (strcmp(attribName, "effect", false)) + { + // Parse effect string value. + if (VolSetEffectString(volumeIndex, attribValue)) + { + successfulCount++; + } + } + else if (strcmp(attribName, "effect_color", false)) + { + // Parse effect color string value. + if (VolSetEffectColorString(volumeIndex, attribValue)) + { + successfulCount++; + } + } + else if (strcmp(attribName, "enabled", false)) + { + // Parse enabled string value. + if (VolSetEnabledString(volumeIndex, attribValue)) + { + successfulCount++; + } + } + } + + // Return number of successfully attributes set. + return successfulCount; +} + +/** + * Creates commands for managing volumes. + */ +VolOnCommandsCreate() +{ + RegAdminCmd("zr_vol_add", VolAddVolumeCommand, ADMFLAG_GENERIC, "Adds a new volume. Usage: zr_vol_add [params]"); +} diff --git a/src/zr/volfeatures/volevents.inc b/src/zr/volfeatures/volevents.inc index 5889542..3531c3d 100644 --- a/src/zr/volfeatures/volevents.inc +++ b/src/zr/volfeatures/volevents.inc @@ -1,11 +1,26 @@ /* * ============================================================================ * - * Zombie:Reloaded + * Zombie:Reloaded * - * File: volevents.inc - * Type: Module - * Description: Handles volumetric feature events. + * File: volevents.inc + * Type: Module + * Description: Handles generic events for volumetric features. + * + * Copyright (C) 2009 Greyscale, Richard Helgeby + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . * * ============================================================================ */ @@ -18,7 +33,12 @@ */ VolOnPlayerEnter(client, volumeIndex) { - // TODO: Check if volfeatures is enabled first. + // Check if volumetric features is enabled. + if (!VolEnabled) + { + // Volumetric features disabled. + return; + } // Forward event to features. // VolAnticampStart(client, volume); @@ -32,7 +52,12 @@ VolOnPlayerEnter(client, volumeIndex) */ VolOnPlayerLeave(client, volumeIndex) { - // TODO: Check if volfeatures is enabled first. + // Check if volumetric features is enabled. + if (!VolEnabled) + { + // Volumetric features disabled. + return; + } // Forward event to features. // VolAnticampStop(client, volume); @@ -45,14 +70,40 @@ VolOnPlayerLeave(client, volumeIndex) */ VolOnPlayerSpawn(client) { + // Check if volumetric features is enabled. + if (!VolEnabled) + { + // Volumetric features disabled. + return; + } + + // Cache player location. VolUpdatePlayerLocation(client); } +/** + * Called when a player disconnects. + * + * @param client The client index. + */ +VolOnPlayerDisconnect(client) +{ + // Disable trigger delay counters. + VolResetCountDown(client); +} + /** * Called when the round starts. Main enable event for volumetric features. */ VolOnRoundStart() { + // Check if volumetric features is enabled. + if (!VolEnabled) + { + // Volumetric features disabled. + return; + } + // Start main timer. VolStartUpdateTimer(); } @@ -68,3 +119,23 @@ VolOnRoundEnd() // Forward stop event to features. // VolAnticampStop(); } + +/** + * Called when a volume is disabled. + * @param volumeIndex The volume index. + */ +VolOnVolumeDisabled(volumeIndex) +{ + // Forward stop event to features. + +} + +/** + * Called when a volume is enabled. + * @param volumeIndex The volume index. + */ +VolOnVolumeEnabled(volumeIndex) +{ + // Forward start event to features. + +} diff --git a/src/zr/volfeatures/volfeatures.inc b/src/zr/volfeatures/volfeatures.inc index d8b1d1e..6466084 100644 --- a/src/zr/volfeatures/volfeatures.inc +++ b/src/zr/volfeatures/volfeatures.inc @@ -1,11 +1,26 @@ /* * ============================================================================ * - * Zombie:Reloaded + * Zombie:Reloaded * - * File: volfeatures.inc - * Type: Module - * Description: Provides functions for managing volumetric features. + * File: volfeatures.inc + * Type: Module + * Description: Provides functions for managing volumetric features. + * + * Copyright (C) 2009 Greyscale, Richard Helgeby + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . * * ============================================================================ */ @@ -21,23 +36,30 @@ enum VolumeAttributes { /* General */ - bool:vol_enabled, /** Volume state. */ - bool:vol_in_use, /** Marks if the volume is used. */ + bool:vol_enabled, /** Volume state. */ + bool:vol_in_use, /** Marks if the volume is used. */ /* Location */ - Float:vol_x_min, /** Minimum x position. */ - Float:vol_x_max, /** Maximum x position. */ + Float:vol_x_min, /** Minimum x position. */ + Float:vol_x_max, /** Maximum x position. */ - Float:vol_y_min, /** Minimum y position. */ - Float:vol_y_max, /** Maximum y position. */ + Float:vol_y_min, /** Minimum y position. */ + Float:vol_y_max, /** Maximum y position. */ - Float:vol_z_min, /** Minimum z position. */ - Float:vol_z_max, /** Maximum z position. */ + Float:vol_z_min, /** Minimum z position. */ + Float:vol_z_max, /** Maximum z position. */ + + /* Style */ + VolumeEffects:vol_effect, /** Visual effect to apply on the volume. */ + vol_effect_color[3], /** Render color of the effect. RGB colors. */ /* Data */ - VolumeEffects:vol_effect, /** Visual effect to apply on the volume. */ - VolumeFeatureTypes:vol_type, /** The volumetric feature type. */ - vol_data_index /** Index in remote feature array. */ + VolumeFeatureTypes:vol_type, /** The volumetric feature type. */ + vol_data_index, /** Index in remote feature array. */ + + /* Behaviour */ + VolumeTeamFilters:vol_team_filter, /** Team filtering. Trigger by certain teams, or all. */ + Float:vol_trigger_delay /** Trigger delay. How many seconds players have to stay to trigger volume events. */ } /** @@ -49,6 +71,9 @@ enum VolumeFeatureTypes VolFeature_Knockback } +/** + * Effects that can be applied on a volume. (Currently no effects.) + */ enum VolumeEffects { VolEffect_None = 0, @@ -56,6 +81,16 @@ enum VolumeEffects VolEffect_Smoke } +/** + * Available team filter settings. + */ +enum VolumeTeamFilters +{ + VolTeam_All = 0, + VolTeam_Humans, + VolTeam_Zombies +} + /** * Volumes. */ @@ -72,56 +107,95 @@ new VolumeCount; new Float:VolPlayerLoc[MAXPLAYERS + 1][3]; /** - * Specifies whether the volumetric features module is enabled or not. To be - * synced with zr_volfeatures_enabled CVAR. + * Specifies whether the volumetric features module is enabled or not. Synced + * with zr_vol CVAR. */ new bool:VolEnabled; /** - * Timer handle for timer that updates player locations. This is the main timer + * Counter for trigger delay. + */ +new Float:VolPlayerCountDown[MAXPLAYERS + 1][ZR_VOLUMES_MAX]; + +/** + * The handle for a timer that updates player locations. This is the main timer * and any feature events can't be updated faster than this interval. * * Note: Some features may have its own timer. */ new Handle:hVolUpdateTimer; +/** + * The handle for a timer that do count down on trigger delays. + */ +new Handle:hVolTriggerTimer; + +/** + * Cached interval value for trigger timer. + */ +new Float:VolTriggerInterval; + #include "zr/volfeatures/volevents" +#include "zr/volfeatures/volgenericattributes" +#include "zr/volfeatures/volcommands" #include "zr/volfeatures/volanticamp" + +/** + * Initialize volumetric features. + */ +VolLoad() +{ + // Cache CVAR value. + VolEnabled = GetConVarBool(g_hCvarsList[CVAR_VOL]); +} + +/** + * Function alias for fully stopping volumetric features. + */ +VolDisable() +{ + VolEnabled = false; + VolStopUpdateTimer(); + + // TODO: Send disable/stop event to volumes with their own timers. +} + /** * Starts the update timer. + * + * @return True if timer is started, false otherwise. */ bool:VolStartUpdateTimer() { - // TODO: Read from CVAR (zr_volfeatures_enabled). - VolEnabled = true; - + // Check if volumetric features is enabled. if (!VolEnabled) { // Volumetric features disabled. return false; } - // TODO: Read from CVAR (zr_volfeatures_interval). - new Float:interval = 1.0; + // Stop timer if it exist. + VolStopUpdateTimer(); + + // Get update interval. + new Float:interval = GetConVarFloat(g_hCvarsList[CVAR_VOL_UPDATE_INTERVAL]); // Validate interval. if (interval > 0.0) { - // Stop timer if it exist. - VolStopUpdateTimer(); - // Create a new timer. hVolUpdateTimer = CreateTimer(interval, Event_VolUpdateTimer, _, TIMER_REPEAT); + // Also start the trigger delay timer. + VolStartTriggerTimer(); + // Volumetric features started. return true; } else { - // Volumetric features disabled. Do explicit stop. - VolStopUpdateTimer(); - + // Volumetric features disabled. return false; } } @@ -137,6 +211,84 @@ VolStopUpdateTimer() KillTimer(hVolUpdateTimer); hVolUpdateTimer = INVALID_HANDLE; } + + // Also stop trigger delay timer. + VolStopTriggerTimer(); + + // Reset all trigger delay counters. + VolResetCountDown(); +} + +/** + * Starts the update timer if it exists. + * + * @return True if timer is started, false otherwise. + */ +bool:VolStartTriggerTimer() +{ + // Make sure existing timer is killed. + VolStopTriggerTimer(); + + // Get trigger interval and cache it. + VolTriggerInterval = GetConVarFloat(g_hCvarsList[CVAR_VOL_TRIGGER_INTERVAL]); + + // Validate interval. + if (VolTriggerInterval > 0.0) + { + // Start the timer. + hVolTriggerTimer = CreateTimer(VolTriggerInterval, Event_VolUpdateTimer, _, TIMER_REPEAT); + + // Trigger timer started. + return true; + } + else + { + // Trigger timer not running. Either disabled or invalid interval. + return false; + } +} + +/** + * Kills the trigger delay timer if it exists. + */ +VolStopTriggerTimer() +{ + // Kill the timer if it's running. + if (hVolTriggerTimer != INVALID_HANDLE) + { + KillTimer(hVolTriggerTimer); + hVolTriggerTimer = INVALID_HANDLE; + } +} + +/** + * Resets volume trigger delay counters on one or more players. + * + * @param client Optional. Specifies a single player to reset. Default is + * -1, all players. + */ +VolResetCountDown(client = -1) +{ + // Check if a client is specified. + if (client > -1) + { + // Reset volume counters. + for (new volumeIndex = 0; volumeIndex < ZR_VOLUMES_MAX; volumeIndex++) + { + VolPlayerCountDown[client][volumeIndex] = -1.0; + } + } + else + { + // Reset all volume counters. + for (new clientIndex = 0; clientIndex <= MAXPLAYERS + 1; clientIndex++) + { + for (new volumeIndex = 0; volumeIndex < ZR_VOLUMES_MAX; volumeIndex++) + { + VolPlayerCountDown[clientIndex][volumeIndex] = -1.0; + } + } + } } /** @@ -157,7 +309,7 @@ VolUpdatePlayerLocation(client = -1) } else { - for (new client = 1; client <= MaxClients; client++) + for (client = 1; client <= MaxClients; client++) { // Check if client is in game and alive. if (!IsClientConnected(client) || !IsClientInGame(client) || !IsPlayerAlive(client)) @@ -183,6 +335,9 @@ VolUpdatePlayerChanges() new bool:newState; new bool:oldState; + new Float:trigger_delay; + + // Loop through all players. for (new client = 1; client <= MaxClients; client++) { // Check if client is in game and alive. @@ -212,14 +367,33 @@ VolUpdatePlayerChanges() // No change. Skip to next volume. break; } + + // Check if client entered the volume. else if (!newState && oldState) { - // Client entered volume. Trigger event. - VolOnPlayerEnter(client, volumeIndex); + // Get trigger delay value. + trigger_delay = Volumes[volumeIndex][vol_trigger_delay]; + + // Check if the volume has a trigger delay. + if (trigger_delay > 0.0) + { + // Set count down value. + VolPlayerCountDown[client][volumeIndex] = trigger_delay; + } + else + { + // No trigger delay, trigger event instantly. + VolOnPlayerEnter(client, volumeIndex); + } } + + // Check if client left the volume. else if (newState && !oldState) { - // Client left the volume. Trigger event. + // Make sure count down value is reset. + VolPlayerCountDown[client][volumeIndex] = -1.0; + + // Trigger event. VolOnPlayerLeave(client, volumeIndex); } } @@ -264,6 +438,8 @@ bool:IsPositionInLocation(Float:pos[3], Float:min[3], Float:max[3]) /** * Returns wether a volume is marked as in use. * + * Note: Does not validate index. + * * @param volumeIndex The volume index. * @return True if in use, false otherwise. */ @@ -272,6 +448,24 @@ bool:VolIsInUse(volumeIndex) return Volumes[volumeIndex][vol_in_use]; } +/** + * Validates a volume index. + * + * @param volumeIndex The volume index. + * @return True if valid, false otherwise. + */ +bool:VolIsValidIndex(volumeIndex) +{ + if (volumeIndex >= 0 && volumeIndex < ZR_VOLUMES_MAX) + { + return true; + } + else + { + return false; + } +} + /** * Gets the first free volume index. * @@ -354,3 +548,61 @@ public Action:Event_VolUpdateTimer(Handle:timer) { VolUpdatePlayerChanges(); } + +/** + * Callback for trigger delay timer. + */ +public Action:Event_VolTriggerTimer(Handle:timer) +{ + new Float:countDown; + + // Loop through all players. + for (new client = 1; client <= MaxClients; client++) + { + // Loop through all volumes. + for (new volumeIndex = 0; volumeIndex < ZR_VOLUMES_MAX; volumeIndex++) + { + // Get count down value. + countDown = VolPlayerCountDown[client][volumeIndex]; + + // Check if volume trigger delay is enabled. + if (countDown > 0.0) + { + // Substract by trigger interval. + countDown -= VolTriggerInterval; + + // Check if zero or below. + if (countDown <= 0.0) + { + // Trigger volume enter event. + VolOnPlayerEnter(client, volumeIndex); + + // Reset count down value. + VolPlayerCountDown[client][volumeIndex] = -1.0; + } + } + } + } +} + +/** + * Called when zr_vol CVAR is changed. + */ +public VolEnabledChanged(Handle:cvar, const String:oldvalue[], const String:newvalue[]) +{ + new bool:isEnabled = bool:StringToInt(newvalue); + + if (isEnabled) + { + // Volumetric features is enabled. + VolEnabled = true; + + // Start timers. + VolStartUpdateTimer(); + } + else + { + // Volumetric features is disabled. + VolDisable(); + } +} diff --git a/src/zr/volfeatures/volgenericattributes.inc b/src/zr/volfeatures/volgenericattributes.inc new file mode 100644 index 0000000..461665a --- /dev/null +++ b/src/zr/volfeatures/volgenericattributes.inc @@ -0,0 +1,281 @@ +/* + * ============================================================================ + * + * Zombie:Reloaded + * + * File: volgenericattributes.inc + * Type: Module + * Description: Functions for getting or setting general volume attributes. + * + * Copyright (C) 2009 Greyscale, Richard Helgeby + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * ============================================================================ + */ + +/** + * Parses a team string value and applies it to the specified volume. + * + * @param volumeIndex The volume index to apply to. + * @param team A team string value. Valid options: "all", "humans" + * and "zombies". + * @return True if successfully set, false otherwise. + */ +stock bool:VolSetTeamString(volumeIndex, const String:team[]) +{ + new VolumeTeamFilters:teamfilter; + + // Check if string value is empty. + if (strlen(team) == 0) + { + return false; + } + + // Convert value. + if (strcmp(team, "all", false)) + { + teamfilter = VolTeam_All; + } + else if (strcmp(team, "humans", false)) + { + teamfilter = VolTeam_Humans; + } + else if (strcmp(team, "zombies", false)) + { + teamfilter = VolTeam_Zombies; + } + + // Apply value. + Volumes[volumeIndex][vol_team_filter] = teamfilter; + return true; + +} + +/** + * Sets the feam filter attribute on a volume. + * + * @param volumeIndex The volume index to apply to. + * @param team The team filter value. + */ +stock VolSetTeam(volumeIndex, VolumeTeamFilters:team[]) +{ + Volumes[volumeIndex][vol_team_filter] = team; +} + +/** + * Parses a delay string value and applies it to the specified volume. + * + * @param volumeIndex The volume index to apply to. + * @param delay The delay to apply. A floating point number formatted + * as a string. + * @return True if successfully set, false otherwise. + */ +stock bool:VolSetDelayString(volumeIndex, const String:delay[]) +{ + new Float:triggerdelay; + + // Check if string value is empty. + if (strlen(delay) == 0) + { + return false; + } + + // Convert value. + triggerdelay = StringToFloat(delay); + + // Apply value. + Volumes[volumeIndex][vol_trigger_delay] = triggerdelay; + return true; +} + +/** + * Sets the trigger delay attribute on a volume. + * + * @param volumeIndex The volume index to apply to. + * @param delay The trigger delay, in seconds. + */ +stock VolSetDelay(volumeIndex, Float:delay) +{ + Volumes[volumeIndex][vol_trigger_delay] = delay; +} + +/** + * Parses a effect string value and applies it to the specified volume. + * + * @param volumeIndex The volume index to apply to. + * @param effect A effect string value. Valid options: see VolumeEffects + * enumeration, exclude prefix. + * @return True if successfully set, false otherwise. + */ +stock bool:VolSetEffectString(volumeIndex, const String:effect[]) +{ + // Check if string value is empty. + if (strlen(effect) == 0) + { + return false; + } + + // Check effect string values and apply them to the volume. + if (strcmp(effect, "none", false)) + { + Volumes[volumeIndex][vol_effect] = VolEffect_None; + return true; + } + else if (strcmp(effect, "wireframe", false)) + { + Volumes[volumeIndex][vol_effect] = VolEffect_Wireframe; + return true; + } + else if (strcmp(effect, "smoke", false)) + { + Volumes[volumeIndex][vol_effect] = VolEffect_Smoke; + return true; + } + + // The string value didn't match any valid effects. + return false; +} + +/** + * Sets the effect attribute on a volume. + * + * @param volumeIndex The volume index to apply to. + * @param effect Specifies what effect to apply on the volume. + */ +stock VolSetEffect(volumeIndex, VolumeEffects:effect) +{ + Volumes[volumeIndex][vol_effect] = effect; +} + +/** + * Parses a effect color string value and applies it to the specified volume. + * + * @param volumeIndex The volume index to apply to. + * @param effect_color A effect color string value. No whitespace! Format + * (0-255): "red,green,blue". + * @return True if successfully set, false otherwise. + */ +stock bool:VolSetEffectColorString(volumeIndex, const String:effect_color[]) +{ + new String:colors[3][3]; + new red, green, blue; + + // Check if string value is empty. + if (strlen(effect_color) == 0) + { + return false; + } + + // Split values into a string array. + ExplodeString(effect_color, ",", colors, 3, 3); + + // Convert values. + red = StringToInt(colors[0]); + green = StringToInt(colors[1]); + blue = StringToInt(colors[2]); + + // Apply values. + Volumes[volumeIndex][vol_effect_color][0] = red; + Volumes[volumeIndex][vol_effect_color][1] = green; + Volumes[volumeIndex][vol_effect_color][2] = blue; + return true; +} + +/** + * Sets the effect color attribute on a volume. + * + * @param volumeIndex The volume index to apply to. + * @param red Amount of red color. 0 to 255. + * @param green Amount of green color. 0 to 255. + * @param blue Amount of blue color. 0 to 255. + */ +stock VolSetEffectColor(volumeIndex, red, green, blue) +{ + Volumes[volumeIndex][vol_effect_color][0] = red; + Volumes[volumeIndex][vol_effect_color][1] = green; + Volumes[volumeIndex][vol_effect_color][2] = blue; +} + +/** + * Parses a enabled string value and applies it to the specified volume. + * + * @param volumeIndex The volume index to apply to. + * @param enabled A enabled string value. Valid options: A number that + * evaluates to true or false, "yes" or "no". + * @return True if successfully set, false otherwise. + */ +stock bool:VolSetEnabledString(volumeIndex, const String:enabled[]) +{ + // Check if string value is empty. + if (strlen(enabled) == 0) + { + return false; + } + + new bool:val = bool:StringToInt(enabled); + + // Check yes or no values first. + if (strcmp(enabled, "yes", false) == 0) + { + val = true; + } + else if (strcmp(enabled, "no", false) == 0) + { + val = false; + } + + // Check if the new value is different from the current. + if (Volumes[volumeIndex][vol_enabled] != val) + { + // Forward event. + if (val) + { + VolOnVolumeEnabled(volumeIndex); + } + else + { + VolOnVolumeDisabled(volumeIndex); + } + } + + // Apply converted value. + Volumes[volumeIndex][vol_enabled] = val; + return true; +} + +/** + * Sets the enabled attribute on a volume. + * + * @param volumeIndex The volume index to apply to. + * @param enabled Specifies if the volume should be enabled or not. + */ +stock VolSetEnabled(volumeIndex, bool:enabled) +{ + // Check if the new value is different from the current. + if (Volumes[volumeIndex][vol_enabled] != enabled) + { + // Forward event. + if (enabled) + { + VolOnVolumeEnabled(volumeIndex); + } + else + { + VolOnVolumeDisabled(volumeIndex); + } + } + + Volumes[volumeIndex][vol_enabled] = enabled; +} diff --git a/src/zr/zadmin.inc b/src/zr/zadmin.inc index 287c551..b2ffc52 100644 --- a/src/zr/zadmin.inc +++ b/src/zr/zadmin.inc @@ -537,14 +537,3 @@ public ZRLogFlagsMenuHandle(Handle:menu_log_flags, MenuAction:action, client, sl CloseHandle(menu_log_flags); } } - -AddToKnockbackMultiplier(Float:value) -{ - new Float:current_val = GetConVarFloat(g_hCvarsList[CVAR_ZOMBIE_KNOCKBACK]); - SetConVarFloat(g_hCvarsList[CVAR_ZOMBIE_KNOCKBACK], current_val + value); -} - -AddToClassKnockback(classindex, Float:value) -{ - arrayClasses[classindex][data_knockback] = arrayClasses[classindex][data_knockback] + value; -} diff --git a/src/zr/zombiereloaded.inc b/src/zr/zombiereloaded.inc index 87b48e1..4e0223e 100644 --- a/src/zr/zombiereloaded.inc +++ b/src/zr/zombiereloaded.inc @@ -116,7 +116,7 @@ stock bool:ZRIsClientValid(client, bool:console = false) */ stock bool:ZRIsConsole(index) { - // Return true if index is = to console's index. + // Return true if index is equal to console's index. return (index == ZR_CONSOLE_INDEX); }