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);
}