Merged heads.
This commit is contained in:
commit
62c1ab4cc5
@ -10,6 +10,7 @@
|
||||
// ----------------------------------------------------------------------------
|
||||
// Defaults:
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
materials/models/player/zh/Zombie_Classic_sheet.vmt
|
||||
materials/models/player/zh/corpse1.vmt
|
||||
materials/models/player/zh/Charple1_sheet.vmt
|
||||
|
@ -12,7 +12,7 @@
|
||||
// Attribute: Values: Description:
|
||||
// ----------------------------------------------------------------------------
|
||||
// index number The hitgroup index.
|
||||
// damage yes/no Allow damage to be done on this hitgroup for zombies.
|
||||
// damage on/off Allow damage to be done on this hitgroup for zombies.
|
||||
// knockback decimal The knockback multiplier for this hitgroup.
|
||||
|
||||
"hitgroups" // Counter-Strike: Source hitgroups
|
||||
@ -23,7 +23,7 @@
|
||||
"index" "0"
|
||||
|
||||
// Damage
|
||||
"damage" "yes"
|
||||
"damage" "on"
|
||||
|
||||
// Knockback
|
||||
"knockback" "1.0"
|
||||
@ -35,7 +35,7 @@
|
||||
"index" "1"
|
||||
|
||||
// Damage
|
||||
"damage" "yes"
|
||||
"damage" "on"
|
||||
|
||||
// Knockback
|
||||
"knockback" "2.0"
|
||||
@ -47,7 +47,7 @@
|
||||
"index" "2"
|
||||
|
||||
// Damage
|
||||
"damage" "yes"
|
||||
"damage" "on"
|
||||
|
||||
// Knockback
|
||||
"knockback" "1.3"
|
||||
@ -59,7 +59,7 @@
|
||||
"index" "3"
|
||||
|
||||
// Damage
|
||||
"damage" "yes"
|
||||
"damage" "on"
|
||||
|
||||
// Knockback
|
||||
"knockback" "1.2"
|
||||
@ -71,7 +71,7 @@
|
||||
"index" "4"
|
||||
|
||||
// Damage
|
||||
"damage" "yes"
|
||||
"damage" "on"
|
||||
|
||||
// Knockback
|
||||
"knockback" "1.0"
|
||||
@ -83,7 +83,7 @@
|
||||
"index" "5"
|
||||
|
||||
// Damage
|
||||
"damage" "yes"
|
||||
"damage" "on"
|
||||
|
||||
// Knockback
|
||||
"knockback" "1.0"
|
||||
@ -95,7 +95,7 @@
|
||||
"index" "6"
|
||||
|
||||
// Damage
|
||||
"damage" "yes"
|
||||
"damage" "on"
|
||||
|
||||
// Knockback
|
||||
"knockback" "0.9"
|
||||
@ -107,7 +107,7 @@
|
||||
"index" "7"
|
||||
|
||||
// Damage
|
||||
"damage" "yes"
|
||||
"damage" "on"
|
||||
|
||||
// Knockback
|
||||
"knockback" "0.9"
|
||||
@ -119,7 +119,7 @@
|
||||
"index" "8"
|
||||
|
||||
// Damage
|
||||
"damage" "yes"
|
||||
"damage" "on"
|
||||
|
||||
// Knockback
|
||||
"knockback" "1.0"
|
||||
|
@ -6,12 +6,25 @@
|
||||
// Check the weapon configuration section in the manual for detailed info.
|
||||
//
|
||||
// ============================================================================
|
||||
// Format:
|
||||
// ----------------------------------------------------------------------------
|
||||
// the/path/to/the/model ;public/hidden/adminonly/etc
|
||||
// * ;public - The model will be treated as a model that any client has access to.
|
||||
// * ;hidden - The model can only be accessed through explicit use of a player class.
|
||||
// E.g. If a class uses the "random" setting for model, then any non-public
|
||||
// models will not be chosen.
|
||||
// ============================================================================
|
||||
// * Each uncommented line will be used as a model path for clients to download,
|
||||
// and classes to utilize.
|
||||
// * If no ;<string> is specified, the model will be assumed as public.
|
||||
// ----------------------------------------------------------------------------
|
||||
// Defaults:
|
||||
// ----------------------------------------------------------------------------
|
||||
models/player/zh/zh_charple001
|
||||
models/player/zh/zh_zombie003
|
||||
models/player/zh/zh_corpse002
|
||||
models/player/ics/hellknight_red/t_guerilla
|
||||
|
||||
models/player/zh/zh_charple001 ;public
|
||||
models/player/zh/zh_zombie003 ;public
|
||||
models/player/zh/zh_corpse002 ;public
|
||||
models/player/ics/hellknight_red/t_guerilla ;public
|
||||
// models/player/adminmodels/1337model ;adminonly // None of these models will be randomly chosen.
|
||||
// models/player/donatormodels/donatormodel ;donator
|
||||
// models/player/hiddenmodels/myhiddenmodel ;non-public
|
@ -1,9 +1,8 @@
|
||||
// ============================================================================
|
||||
//
|
||||
// ZOMBIE:RELOADED
|
||||
// Class configuration
|
||||
// Zombie:Reloaded Class configuration
|
||||
//
|
||||
// Check the class configuration section in the manual for detailed info.
|
||||
// See Class Configuration (3.7) in the manual for detailed info.
|
||||
//
|
||||
// ============================================================================
|
||||
//
|
||||
@ -52,7 +51,7 @@
|
||||
// Zombie classes
|
||||
//
|
||||
// ------------------------------------------
|
||||
"classic"
|
||||
"zombie_classic"
|
||||
{
|
||||
// General
|
||||
"enabled" "1"
|
||||
@ -95,7 +94,7 @@
|
||||
"jump_distance" "1.2"
|
||||
}
|
||||
|
||||
"fast"
|
||||
"zombie_fast"
|
||||
{
|
||||
// General
|
||||
"enabled" "1"
|
||||
@ -138,7 +137,7 @@
|
||||
"jump_distance" "1.2"
|
||||
}
|
||||
|
||||
"mutated"
|
||||
"zombie_mutated"
|
||||
{
|
||||
// General
|
||||
"enabled" "1"
|
||||
@ -181,7 +180,7 @@
|
||||
"jump_distance" "1.3"
|
||||
}
|
||||
|
||||
"heavy"
|
||||
"zombie_heavy"
|
||||
{
|
||||
// General
|
||||
"enabled" "1"
|
||||
@ -224,6 +223,92 @@
|
||||
"jump_distance" "0.9"
|
||||
}
|
||||
|
||||
"mother_zombie"
|
||||
{
|
||||
// General
|
||||
"enabled" "1"
|
||||
"team" "0"
|
||||
"team_default" "0"
|
||||
"flags" "2"
|
||||
|
||||
"name" "Mother zombie"
|
||||
"description" "+HP regen | +Speed | +Jump | -Knockback"
|
||||
|
||||
// Model
|
||||
"model_path" "models/player/zh/zh_charple001.mdl"
|
||||
"alpha_initial" "255"
|
||||
"alpha_damaged" "255"
|
||||
"alpha_damage" "0"
|
||||
|
||||
// Hud
|
||||
"overlay_path" "overlays/zr/zvision"
|
||||
"nvgs" "0"
|
||||
"fov" "110"
|
||||
|
||||
// Effects
|
||||
"has_napalm" "0"
|
||||
"napalm_time" "5.0"
|
||||
|
||||
// Player behaviour
|
||||
"immunity_mode" "0"
|
||||
"immunity_amount" "0.0"
|
||||
"no_fall_damage" "1"
|
||||
|
||||
"health" "2500"
|
||||
"health_regen_interval" "0.25"
|
||||
"health_regen_amount" "10"
|
||||
"health_infect_gain" "700"
|
||||
"kill_bonus" "1"
|
||||
|
||||
"speed" "400"
|
||||
"knockback" "2.8"
|
||||
"jump_height" "1.2"
|
||||
"jump_distance" "1.3"
|
||||
}
|
||||
|
||||
"mother_zombie_admin"
|
||||
{
|
||||
// General
|
||||
"enabled" "1"
|
||||
"team" "0"
|
||||
"team_default" "0"
|
||||
"flags" "3"
|
||||
|
||||
"name" "Admin mother zombie"
|
||||
"description" "+HP regen | +Speed | +Jump | -Knockback"
|
||||
|
||||
// Model
|
||||
"model_path" "models/player/zh/zh_charple001.mdl"
|
||||
"alpha_initial" "255"
|
||||
"alpha_damaged" "255"
|
||||
"alpha_damage" "0"
|
||||
|
||||
// Hud
|
||||
"overlay_path" "overlays/zr/zvision"
|
||||
"nvgs" "0"
|
||||
"fov" "110"
|
||||
|
||||
// Effects
|
||||
"has_napalm" "0"
|
||||
"napalm_time" "3.0"
|
||||
|
||||
// Player behaviour
|
||||
"immunity_mode" "0"
|
||||
"immunity_amount" "0.0"
|
||||
"no_fall_damage" "1"
|
||||
|
||||
"health" "3500"
|
||||
"health_regen_interval" "0.25"
|
||||
"health_regen_amount" "10"
|
||||
"health_infect_gain" "700"
|
||||
"kill_bonus" "1"
|
||||
|
||||
"speed" "425"
|
||||
"knockback" "2.8"
|
||||
"jump_height" "1.2"
|
||||
"jump_distance" "1.3"
|
||||
}
|
||||
|
||||
// ------------------------------------------
|
||||
//
|
||||
// Human classes
|
||||
@ -273,6 +358,92 @@
|
||||
"jump_distance" "1.0"
|
||||
}
|
||||
|
||||
"human_vip"
|
||||
{
|
||||
// General
|
||||
"enabled" "1"
|
||||
"team" "1"
|
||||
"team_default" "0"
|
||||
"flags" "0"
|
||||
|
||||
"name" "VIP Human"
|
||||
"description" "Human class for important players"
|
||||
|
||||
// Model
|
||||
"model_path" "default"
|
||||
"alpha_initial" "255"
|
||||
"alpha_damaged" "255"
|
||||
"alpha_damage" "0"
|
||||
|
||||
// Hud
|
||||
"overlay_path" ""
|
||||
"nvgs" "0"
|
||||
"fov" "90"
|
||||
|
||||
// Effects
|
||||
"has_napalm" "1"
|
||||
"napalm_time" "0.0"
|
||||
|
||||
// Player behaviour
|
||||
"immunity_mode" "0"
|
||||
"immunity_amount" "0.0"
|
||||
"no_fall_damage" "0"
|
||||
|
||||
"health" "200"
|
||||
"health_regen_interval" "1.0"
|
||||
"health_regen_amount" "10"
|
||||
"health_infect_gain" "0"
|
||||
"kill_bonus" "2"
|
||||
|
||||
"speed" "320"
|
||||
"knockback" "0"
|
||||
"jump_height" "1.1"
|
||||
"jump_distance" "1.1"
|
||||
}
|
||||
|
||||
"human_admin"
|
||||
{
|
||||
// General
|
||||
"enabled" "1"
|
||||
"team" "1"
|
||||
"team_default" "0"
|
||||
"flags" "1"
|
||||
|
||||
"name" "Admin Human"
|
||||
"description" "Human class for admins"
|
||||
|
||||
// Model
|
||||
"model_path" "default"
|
||||
"alpha_initial" "255"
|
||||
"alpha_damaged" "255"
|
||||
"alpha_damage" "0"
|
||||
|
||||
// Hud
|
||||
"overlay_path" ""
|
||||
"nvgs" "0"
|
||||
"fov" "90"
|
||||
|
||||
// Effects
|
||||
"has_napalm" "1"
|
||||
"napalm_time" "0.0"
|
||||
|
||||
// Player behaviour
|
||||
"immunity_mode" "0"
|
||||
"immunity_amount" "0.0"
|
||||
"no_fall_damage" "1"
|
||||
|
||||
"health" "200"
|
||||
"health_regen_interval" "1.0"
|
||||
"health_regen_amount" "10"
|
||||
"health_infect_gain" "0"
|
||||
"kill_bonus" "2"
|
||||
|
||||
"speed" "320"
|
||||
"knockback" "0"
|
||||
"jump_height" "1.1"
|
||||
"jump_distance" "1.1"
|
||||
}
|
||||
|
||||
"human_speedy"
|
||||
{
|
||||
// General
|
||||
|
@ -736,6 +736,7 @@
|
||||
// General
|
||||
|
||||
"weapontype" "All, Equipment"
|
||||
"weaponslot" "5"
|
||||
|
||||
// Restrict (core)
|
||||
|
||||
|
@ -9,13 +9,6 @@
|
||||
|
||||
"Offsets"
|
||||
{
|
||||
|
||||
"EyeAngles"
|
||||
{
|
||||
"windows" "206"
|
||||
"linux" "207"
|
||||
}
|
||||
|
||||
"TraceAttack"
|
||||
{
|
||||
"windows" "58"
|
||||
@ -28,6 +21,24 @@
|
||||
"linux" "61"
|
||||
}
|
||||
|
||||
"StartTouch"
|
||||
{
|
||||
"windows" "88"
|
||||
"linux" "89"
|
||||
}
|
||||
|
||||
"Touch"
|
||||
{
|
||||
"windows" "89"
|
||||
"linux" "90"
|
||||
}
|
||||
|
||||
"EndTouch"
|
||||
{
|
||||
"windows" "90"
|
||||
"linux" "91"
|
||||
}
|
||||
|
||||
"Weapon_CanUse"
|
||||
{
|
||||
"windows" "216"
|
||||
|
@ -143,7 +143,7 @@
|
||||
|
||||
"Config command reload all stats begin"
|
||||
{
|
||||
"en" "Reloading all Zombie:Reloaded config files...\n ------------------------------------------------"
|
||||
"en" "Reloading all Zombie:Reloaded config files...\n------------------------------------------------"
|
||||
}
|
||||
|
||||
"Config command reload all stats successful"
|
||||
@ -432,37 +432,37 @@
|
||||
"Menu main zclass"
|
||||
{
|
||||
"#format" "{1:s}"
|
||||
"en" "ZClass - Configure your class settings. (Command: {1})"
|
||||
"en" "ZClass - Configure class settings. (Command: {1})"
|
||||
}
|
||||
|
||||
"Menu main zcookies"
|
||||
{
|
||||
"#format" "{1:s}"
|
||||
"en" "ZCookies - Toggle your personal ZR settings here. (Command: {1})"
|
||||
"en" "ZCookies - Toggle personal ZR settings here. (Command: {1})"
|
||||
}
|
||||
|
||||
"Menu main zspawn"
|
||||
{
|
||||
"#format" "{1:s}"
|
||||
"en" "ZSpawn - Join late? Use this to spawn. (Command: {1})"
|
||||
"en" "ZSpawn - Join late? Spawn with this. (Command: {1})"
|
||||
}
|
||||
|
||||
"Menu main ztele"
|
||||
{
|
||||
"#format" "{1:s}"
|
||||
"en" "ZTele - Teleport back to your spawn location. (Command: {1})"
|
||||
"en" "ZTele - Stuck? Teleport back to spawn. (Command: {1})"
|
||||
}
|
||||
|
||||
"Menu main zhp"
|
||||
{
|
||||
"#format" "{1:s}"
|
||||
"en" "ZHP - Toggle real HP display when infected. (Command: {1})"
|
||||
"en" "ZHP - Shows real HP as zombie. (Command: {1})"
|
||||
}
|
||||
|
||||
"Menu main zmarket"
|
||||
{
|
||||
"#format" "{1:s}"
|
||||
"en" "ZMarket - Need a weapon? Buy them here. (Command: {1})"
|
||||
"en" "ZMarket - Customize loadouts here. (Command: {1})"
|
||||
}
|
||||
|
||||
// ===========================
|
||||
@ -634,7 +634,7 @@
|
||||
"Weapons menu restrict types unrestrict all"
|
||||
{
|
||||
"#format" "{1:s}"
|
||||
"en" "Unrestrict weapon type {1}\n "
|
||||
"en" "Unrestrict weapon type {1}"
|
||||
}
|
||||
|
||||
"Weapons menu restrict zmarket title"
|
||||
@ -683,7 +683,7 @@
|
||||
|
||||
"Weapons menu zmarket loadout title"
|
||||
{
|
||||
"en" "ZMarket\nMy Current Loadout:\nRebuy refers to these weapons"
|
||||
"en" "ZMarket\nMy Current Loadout:\nSelect weapon slot to clear.\nNote: Rebuy refers to these weapons."
|
||||
}
|
||||
|
||||
"Weapons menu zmarket loadout primary"
|
||||
@ -716,6 +716,12 @@
|
||||
"en" "Explosive: {1}"
|
||||
}
|
||||
|
||||
"Weapons menu zmarket loadout nvgs"
|
||||
{
|
||||
"#format" "{1:s}"
|
||||
"en" "NVGs: {1}"
|
||||
}
|
||||
|
||||
"Weapons menu zmarket loadout empty"
|
||||
{
|
||||
"en" "(None)"
|
||||
@ -747,6 +753,25 @@
|
||||
// Hitgroups (core)
|
||||
// ===========================
|
||||
|
||||
// Menu
|
||||
|
||||
"Hitgroups menu hitgroups title"
|
||||
{
|
||||
"en" "Hitgroup Management\nCommands: zr_hitgroup(_enable_all/_headshots_only)\nSelect a Hitgroup to Toggle:"
|
||||
}
|
||||
|
||||
"Hitgroups menu hitgroups enable all"
|
||||
{
|
||||
"en" "Enable All Hitgroups"
|
||||
}
|
||||
|
||||
"Hitgroups menu hitgroups headshots only"
|
||||
{
|
||||
"en" "Headshots Only"
|
||||
}
|
||||
|
||||
// Commands
|
||||
|
||||
"Hitgroups command syntax"
|
||||
{
|
||||
"en" "Toggles or sets if a zombie's hitgroup can be damaged. Usage: zr_hitgroup <hitgroup alias> [1/0]"
|
||||
@ -790,6 +815,85 @@
|
||||
"en" "Zombies may now only be damaged by headshots."
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// ZAdmin (core)
|
||||
// ===========================
|
||||
|
||||
"ZAdmin main title"
|
||||
{
|
||||
"en" "ZAdmin\nSelect Category:"
|
||||
}
|
||||
|
||||
"ZAdmin main class multipliers"
|
||||
{
|
||||
"en" "Class Multipliers"
|
||||
}
|
||||
|
||||
"ZAdmin main weapons"
|
||||
{
|
||||
"en" "Weapon Management"
|
||||
}
|
||||
|
||||
"ZAdmin main hitgroups"
|
||||
{
|
||||
"en" "Hitgroup Management"
|
||||
}
|
||||
|
||||
"ZAdmin main zombie"
|
||||
{
|
||||
"en" "Zombie Management"
|
||||
}
|
||||
|
||||
"ZAdmin main force zspawn"
|
||||
{
|
||||
"en" "Force ZSpawn"
|
||||
}
|
||||
|
||||
"ZAdmin main force ztele"
|
||||
{
|
||||
"en" "Force ZTele"
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// AntiStick (module)
|
||||
// ===========================
|
||||
|
||||
// Commands
|
||||
|
||||
"AntiStick command set width syntax"
|
||||
{
|
||||
"en" "Sets the width of a model's hull. (See zr_antistick_list_models) Usage: zr_antistick_set_width <model/player> <width>"
|
||||
}
|
||||
|
||||
"AntiStick command list models list"
|
||||
{
|
||||
"en" "Showing all players' model data...\n------------------------------------------------"
|
||||
}
|
||||
|
||||
"AntiStick command list models name"
|
||||
{
|
||||
"#format" "{1:s},{2:s},{3:f}"
|
||||
"en" "Player Name: {1} | Model Name: {2} | Model Hull Width: {3}"
|
||||
}
|
||||
|
||||
"AntiStick command set width successful"
|
||||
{
|
||||
"#format" "{1:s},{2:f}"
|
||||
"en" "Model hull width for model \"{1}\" has been changed to \"{2}.\""
|
||||
}
|
||||
|
||||
"AntiStick command set width invalid model"
|
||||
{
|
||||
"#format" "{1:s}"
|
||||
"en" "Invalid model/player specified: \"{1}\""
|
||||
}
|
||||
|
||||
"AntiStick command set width invalid width"
|
||||
{
|
||||
"#format" "{1:f}"
|
||||
"en" "Invalid model hull width specified: \"{1}\""
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// Spawn Protect (module)
|
||||
// ===========================
|
||||
@ -848,6 +952,8 @@
|
||||
// ZSpawn (module)
|
||||
// ===========================
|
||||
|
||||
// General
|
||||
|
||||
"ZSpawn double spawn"
|
||||
{
|
||||
"en" "ZSpawn can only be used if you joined late during a round in progress."
|
||||
@ -859,6 +965,33 @@
|
||||
"en" "The timelimit ({1} seconds), to use ZSpawn, has already expired."
|
||||
}
|
||||
|
||||
// Menu
|
||||
|
||||
"ZSpawn clients title"
|
||||
{
|
||||
"en" "Force ZSpawn (zr_zspawn_force)\nSelect a Player:"
|
||||
}
|
||||
|
||||
// Commands
|
||||
|
||||
"ZSpawn command force syntax"
|
||||
{
|
||||
"en" "Force ZSpawn on a client. Usage: zr_zspawn_force <client> ['0' = Spawn as human | '1' = Spawn as zombie]"
|
||||
|
||||
}
|
||||
|
||||
"ZSpawn command force successful"
|
||||
{
|
||||
"#format" "{1:s}"
|
||||
"en" "Player {1} was successfully spawned."
|
||||
}
|
||||
|
||||
"ZSpawn command force unsuccessful"
|
||||
{
|
||||
"#format" "{1:s}"
|
||||
"en" "Player {1} couldn't be spawned."
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// ZTele (module)
|
||||
// ===========================
|
||||
@ -906,6 +1039,33 @@
|
||||
"en" "Teleported back to spawn. (Count: {1}/{2})"
|
||||
}
|
||||
|
||||
// Menu
|
||||
|
||||
"ZTele clients title"
|
||||
{
|
||||
"en" "Force ZTele (zr_ztele_force)\nSelect a Player:"
|
||||
}
|
||||
|
||||
// Commands
|
||||
|
||||
"ZTele command force syntax"
|
||||
{
|
||||
"en" "Force ZTele on a client. Usage: zr_ztele_force <client>"
|
||||
|
||||
}
|
||||
|
||||
"ZTele command force successful"
|
||||
{
|
||||
"#format" "{1:s}"
|
||||
"en" "Player {1} was successfully teleported."
|
||||
}
|
||||
|
||||
"ZTele command force unsuccessful"
|
||||
{
|
||||
"#format" "{1:s}"
|
||||
"en" "Player {1} couldn't be teleported."
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// ZHP (module)
|
||||
// ===========================
|
||||
@ -946,28 +1106,4 @@
|
||||
"#format" "{1:s},{2:d}"
|
||||
"en" "Player \"{1}\" has been slayed for camping in a restricted area (ID: {2})."
|
||||
}
|
||||
|
||||
// ===========================
|
||||
// ZAdmin Menu
|
||||
// ===========================
|
||||
|
||||
"ZAdmin main title"
|
||||
{
|
||||
"en" "ZAdmin\n Select Category:"
|
||||
}
|
||||
|
||||
"ZAdmin main class multipliers"
|
||||
{
|
||||
"en" "Class Multipliers"
|
||||
}
|
||||
|
||||
"ZAdmin main weapons"
|
||||
{
|
||||
"en" "Weapon Management"
|
||||
}
|
||||
|
||||
"ZAdmin main zombie"
|
||||
{
|
||||
"en" "Zombie Management"
|
||||
}
|
||||
}
|
@ -324,12 +324,16 @@ zr_damage_block_blast "1"
|
||||
// Suicide Intercept
|
||||
|
||||
// Intercept suicide commands attempted by zombies.
|
||||
// Default: "0"
|
||||
zr_damage_suicide_zombie "0"
|
||||
|
||||
// Intercept suicide commands attempted by mother zombies.
|
||||
// Default: "1"
|
||||
zr_damage_suicide_zombie "1"
|
||||
zr_damage_suicide_mzombie "1"
|
||||
|
||||
// Intercept suicide commands attempted by humans.
|
||||
// Default: "1"
|
||||
zr_damage_suicide_human "1"
|
||||
// Default: "0"
|
||||
zr_damage_suicide_human "0"
|
||||
|
||||
// List of client commands to intercept as suicide attempts. [Delimiter: ", "]
|
||||
// Default: "kill, spectate, jointeam"
|
||||
@ -503,9 +507,13 @@ zr_ambientsounds_volume "0.8"
|
||||
// Default: "1"
|
||||
zr_antistick "1"
|
||||
|
||||
// Time between each check for stuck players. [Dependency: zr_antistick]
|
||||
// Default: "0.5"
|
||||
zr_antistick_interval "0.5"
|
||||
// The default width of player models, don't touch if you don't know what you're doing. [Dependency: zr_antistick]
|
||||
// Default: "32.0"
|
||||
zr_antistick_default_width "32.0"
|
||||
|
||||
// File to store antistick model hull data. [Dependency: zr_antistick]
|
||||
// Default: "data/antistick.dat"
|
||||
zr_antistick_file_path "data/antistick.dat"
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
236
docs/zr_3.0_release_notes.txt
Normal file
236
docs/zr_3.0_release_notes.txt
Normal file
@ -0,0 +1,236 @@
|
||||
===============================================================================
|
||||
|
||||
Zombie:Reloaded Release Notes
|
||||
|
||||
Targets plugin version 3.0.0, (not released)
|
||||
Written by Richard Helgeby
|
||||
|
||||
Last modified: 2009.06.27
|
||||
|
||||
===============================================================================
|
||||
|
||||
Release Notes
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
This is a major release and it do break compatibility with older configuration!
|
||||
Clean install of configuration files and reconfiguring is recommended.
|
||||
|
||||
A lot of work is put into this plugin. The entire plugin is completely recoded
|
||||
with lots of improvements and fixes.
|
||||
|
||||
Our code base have expanded at least five times compared to version 2.5.1 (now
|
||||
with source files above 20 000 lines). Of course, made with optimizing in mind.
|
||||
This is, as far as we know, the biggest SourceMod plugin ever made!
|
||||
|
||||
We also hope Zombie:Reloaded will be a good learning resource for new or
|
||||
existing coders to find out how certain things are done. The code is well
|
||||
structured and documented with comments explaining almost what every line do.
|
||||
|
||||
In addition we try to make this a quality release with a well tested release
|
||||
and a full user manual. Read the user manual for details on how to use or
|
||||
configure individual features. Better quality and less time spent on support
|
||||
gives more time for us to what we really want to do.
|
||||
|
||||
|
||||
Richard Helgeby &
|
||||
Greyscale
|
||||
|
||||
|
||||
OVERVIEW OF MAJOR CHANGES
|
||||
---------------------------
|
||||
|
||||
* New configuration style. Configuration files and CVARs are also validated so
|
||||
errors and invalid values are caught early.
|
||||
|
||||
* Expanded class system with support for human classes and additional
|
||||
attributes like setting transparency on player classes, effects or other
|
||||
special behaviour.
|
||||
|
||||
* New weapon configurations that support knock back multipliers per weapon and
|
||||
custom weapon groups for easy restriction.
|
||||
|
||||
* Market feature for pre configuring or buying equimpents and weapons from the
|
||||
oposite team, also outside the buy zone if allowed in configuration.
|
||||
|
||||
* Improved knock back with support for scaling based on different modules. Now
|
||||
it's possible to fully customize knock back behaviour.
|
||||
|
||||
* Volumetric features. Define areas in maps and do certain stuff to players in
|
||||
those areas based on a selection of features like the anti-camp.
|
||||
|
||||
* Improved teleport settings. Delays and limits separated per team.
|
||||
|
||||
* Admin menu. Configure certain settings in-game, do generic commands like
|
||||
infect, spawn and teleport.
|
||||
|
||||
* Cookies. This plugin is using the cookie system of SourceMod so player
|
||||
preferences can be saved until next time they connect.
|
||||
|
||||
* New logging system that is fully customizable. Makes it possible to decide
|
||||
what stuff to be logged by setting generic logging flags and applying module
|
||||
filters.
|
||||
|
||||
|
||||
CONFIGURATION CHANGES
|
||||
-----------------------
|
||||
|
||||
Configuration settings are validated when the plugin starts. The plugin will
|
||||
stop, use defaults or disable features if there are invalid values. Also a
|
||||
warning is logged in the SourceMod error logs.
|
||||
|
||||
The validation prevents unexpected or invalid behaviour in the plugin. Dealing
|
||||
with errors or warnings in error logs helps a lot troubleshooting eventual
|
||||
eventual issues in the plugin caused by incorrect configurations.
|
||||
|
||||
It's also possible to specify the path of configuration files. This can be used
|
||||
in combination with map configs, so it's possible to have different
|
||||
configuration sets per map.
|
||||
|
||||
Support for post map configs is made. These are configs executed after the
|
||||
plugin and its features are loaded. Some settings can only be changed or
|
||||
overridden after loading. Those commands must be placed in post map configs.
|
||||
|
||||
|
||||
IMPROVED CLASS SYSTEM
|
||||
-----------------------
|
||||
|
||||
There's a lot of new features in the class system. The major change is that
|
||||
it's made for multiple teams (humans and zombies). Now human classes can be
|
||||
made. It has support for extended team filtering where admin-only and mother
|
||||
zombie classes can be made.
|
||||
|
||||
In addition any attribute on one or more classes can be modified in-game, which
|
||||
expands the possibilities in combination with map configs. This makes it easier
|
||||
to improve the map balance by adjusting attributes like health, knock back and
|
||||
running speed.
|
||||
|
||||
One of the new features is transparency on players. There are also immunity
|
||||
modes (but it's currently a incomplete feature) that could implement slow
|
||||
infection that requires zombies to stab multiple times with its knife before
|
||||
the humans get infected, or stab them to death (turning into a zombie).
|
||||
|
||||
|
||||
IMPROVED WEAPON SYSTEM
|
||||
------------------------
|
||||
|
||||
The new weapon system lets makes it possible to do more than just restricting
|
||||
weapons. Now it's possible to set knock back multipliers per weapon.
|
||||
|
||||
Hit groups can also be configured with knock back multipliers, or disable
|
||||
damage on certain hit groups completely.
|
||||
|
||||
There's also a new market feature which is a custom buy menu with all available
|
||||
weapons, including from the oposite team. It's also possible to buy weapons
|
||||
outside the buy zone if the server admins enable that setting.
|
||||
|
||||
Weapon selections can be pre configured and even saved using cookies so they
|
||||
can be quickly bought on next spawn or on next connect to the server.
|
||||
|
||||
|
||||
CUSTOMIZING KNOCK BACK
|
||||
------------------------
|
||||
|
||||
The knock back is based on three factors that are multiplied into the effective
|
||||
knock back:
|
||||
|
||||
- Class knock back. This is the main value.
|
||||
|
||||
- Weapon knock back. Set knock back scale values per weapon.
|
||||
|
||||
- Hit group knock back. Customize or completely disable knock back scale
|
||||
per hit group.
|
||||
|
||||
With these factors it's possible to fully customize knock back.
|
||||
|
||||
|
||||
VOLUMETRIC FEATURES
|
||||
---------------------
|
||||
|
||||
(Currently in development)
|
||||
|
||||
This is a brand new useful feature where custom defined areas in maps can do
|
||||
certain stuff on players. These are the available features:
|
||||
|
||||
- Anti-camp: Slay or warn players that stay too long in a certain area.
|
||||
Useful in unfair camping places, or to avoid glitches in maps.
|
||||
|
||||
- Modify class attributes.
|
||||
|
||||
- Restrict weapons. Takes away ammo, and gives back when leaving area.
|
||||
|
||||
- Modify ammo modes.
|
||||
|
||||
- Modify knock back set on players or knock back in hit groups.
|
||||
|
||||
- Teleporter.
|
||||
|
||||
Features that modify settings will be reverted when players leave volumes.
|
||||
Example of usage is to only allow pistols in tubes, use the anti-camp to hurt
|
||||
humans camping in a certain unfair place, or fine tune knock back for a area in
|
||||
the map.
|
||||
|
||||
|
||||
TELEPORTER
|
||||
------------
|
||||
|
||||
The teleporter is improved with more settings like these:
|
||||
|
||||
- Deciding when players can teleport per team, before or after mother
|
||||
zombie.
|
||||
|
||||
- Setting teleport delays per team.
|
||||
|
||||
- Limiting number of teleports per team.
|
||||
|
||||
- Abuse protection: Automatically aborting a teleport in progress if the
|
||||
player moves a certain distance (configurable).
|
||||
|
||||
|
||||
ADMIN MENU
|
||||
------------
|
||||
|
||||
A menu for admins with basic commands to configure certain settings in-game
|
||||
or do generic commands. That is:
|
||||
|
||||
- Infecting players.
|
||||
|
||||
- Spawning players.
|
||||
|
||||
- Modifying weapon restrictions.
|
||||
|
||||
- Modifying class data.
|
||||
|
||||
- Configuring log messages.
|
||||
|
||||
|
||||
LOGGING SYSTEM
|
||||
----------------
|
||||
|
||||
The logging system is based on logging flags and filtering that gives full
|
||||
control of what log types and events to be logged.
|
||||
|
||||
There are a few generic log events and settings, like these:
|
||||
|
||||
- Core events: Executing config files, error messages, etc.
|
||||
|
||||
- Game events: Admin commands, suicide prevention, anticamp kills, etc.
|
||||
|
||||
- Player commands: Commands executed by non-admins: zspawn, teleport, class
|
||||
change, etc.
|
||||
|
||||
- Debug messages, if any. Usually only developers use this one.
|
||||
|
||||
- Debug messages with more detail. It may cause spam, but this can be
|
||||
avoided in combination with module filtering.
|
||||
|
||||
- Ignoring log events caused by server commands (console), like from map
|
||||
configs.
|
||||
|
||||
- Logging to admin chat: A copy of the message is also logged to admins.
|
||||
|
||||
In addition a module filter can be enabled. Only log messages from modules
|
||||
listed in the filter is logged, other are ignored. Except fatal errors, those
|
||||
are logged anyways.
|
||||
|
||||
The logging system is made this way so server admins can monitor activity in
|
||||
Zombie:Reloaded whithout reading spammed log messages.
|
164
docs/zr_dev_manual.txt
Normal file
164
docs/zr_dev_manual.txt
Normal file
@ -0,0 +1,164 @@
|
||||
===============================================================================
|
||||
|
||||
Zombie:Reloaded
|
||||
Technical Manual For Developers
|
||||
|
||||
Targets plugin version 3.0.0, (not released)
|
||||
Written by Richard Helgeby
|
||||
|
||||
Manual last modified: 2009.04.25
|
||||
|
||||
===============================================================================
|
||||
|
||||
INDEX
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
1.0 . . Introduction
|
||||
1.1 . . . About This Manual
|
||||
1.2 . . . Briefing
|
||||
|
||||
2.0 . . Plugin Core
|
||||
2.1 . . . Startup
|
||||
2.2 . . . Console Variables
|
||||
2.3 . . . Translations
|
||||
2.4 . . . Offsets
|
||||
2.5 . . . Models
|
||||
2.6 . . . Round End Handler
|
||||
2.7 . . . Infection Handler
|
||||
2.8 . . . Damage Handler
|
||||
|
||||
(account)
|
||||
(say hooks)
|
||||
(menu)
|
||||
(commands)
|
||||
(events)
|
||||
|
||||
3.0 . . Log Module
|
||||
3.1 . . . Description
|
||||
3.2 . . . Logging Flags And Filters
|
||||
3.3 . . . Formatted Log Messages
|
||||
3.4 . . . The Log Function
|
||||
|
||||
4.0 . . Class Module
|
||||
|
||||
5.0 . . Weapon Module
|
||||
|
||||
6.0 . . Hit Groups Module
|
||||
|
||||
7.0 . . Visual Effects Module
|
||||
|
||||
8.0 . . Sound Effects Module
|
||||
|
||||
9.0 . . Anti-Stick Module
|
||||
|
||||
10.0 . Knockback Module
|
||||
|
||||
11.0 . Respawn Module
|
||||
|
||||
12.0 . Spawn Protect Module
|
||||
|
||||
13.0 . Napalm Grenades Module
|
||||
|
||||
14.0 . HP Display Module
|
||||
|
||||
15.0 . Teleport Module
|
||||
|
||||
|
||||
1.0 INTRODUCTION
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
1.1 ABOUT THIS MANUAL
|
||||
------------------------
|
||||
|
||||
The point of this manual is to describe how the plugin technically works so
|
||||
it's easier for other developers to make modifications or join the development.
|
||||
|
||||
|
||||
1.2 BRIEFING
|
||||
---------------
|
||||
|
||||
The entire plugin is based on events in the game. It has a lot of features and
|
||||
each feature is separated in its own module. Events are then forwarded to those
|
||||
modules.
|
||||
|
||||
There are core modules and optional modules. Core modules is features and stuff
|
||||
that cannot be disabled and is required for the plugin to function. Optional
|
||||
modules like respawning, sound effects or weapon restrictions can be disabled.
|
||||
|
||||
Each module takes care of its own task. But modules have dependency, and events
|
||||
should be forwarded in correct order. Usually only core modules depends on other
|
||||
core modules. Optional modules should be independent.
|
||||
|
||||
|
||||
2.0 PLUGIN CORE
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
|
||||
3.0 LOG MODULE
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
3.1 DESCRIPTION
|
||||
------------------
|
||||
|
||||
A plugin with a lots of modules and events needs a good logging system. The
|
||||
user should be able to decide what's logged with logging flags.
|
||||
|
||||
|
||||
3.2 LOGGING FLAGS AND FILTERS
|
||||
--------------------------------
|
||||
|
||||
The log system decides what to log based on some generic log flags. Those flags
|
||||
are stored in a bid field (http://en.wikipedia.org/wiki/Bit_field).
|
||||
|
||||
An optional module filter can be enabled to only allow log events from user
|
||||
specified modules.
|
||||
|
||||
For performance reasons there should be a single function that tells whether it
|
||||
should log or not, based on the specified module and generic event. The logging
|
||||
function itself should not do such check and always log a message when called.
|
||||
|
||||
(incomplete)
|
||||
|
||||
How to store module flags? Key/values? Reading those flags MUST be cheap, so
|
||||
the overall plugin performance isn't affected.
|
||||
|
||||
|
||||
3.3 FORMATTED LOG MESSAGES
|
||||
-----------------------------
|
||||
|
||||
Each log message should tell the module and what part of it that fired the
|
||||
log event. Also it must be possible to supply additional info as parameters
|
||||
(the "any:..." parameter) to be used in the log message. These are easily'
|
||||
parsed with VFormat.
|
||||
|
||||
|
||||
3.4 THE LOG FUNCTION
|
||||
-----------------------
|
||||
|
||||
Syntax:
|
||||
|
||||
LogMessageFormatted(client,
|
||||
const String:module[],
|
||||
const String:block[],
|
||||
const String:message[],
|
||||
type = LOG_FORMAT_TYPE_FULL,
|
||||
any:...)
|
||||
|
||||
Parameter: Description:
|
||||
---------------------------------------------------------------------------
|
||||
client Specifies what client that triggered the event. Use -1 for
|
||||
core events.
|
||||
module What module the event was triggered in.
|
||||
block What function or block that triggered the event.
|
||||
message The log message. Can be formatted.
|
||||
type Optional. Specifies what log type to use. Defaults to full.
|
||||
any:... Formatting parameters for the log message.
|
||||
|
||||
Example usage with flag check:
|
||||
|
||||
if (LogCheckFlag(LOG_CORE_EVENTS, LOG_MODULE_CLASSES))
|
||||
{
|
||||
LogMessageFormatted(-1, "Classes", "Load", "Warning: Maximum classes reached (%d). Skipping other classes.", _, ZR_CLASS_MAX + 1);
|
||||
}
|
||||
|
||||
The module check will be replaced with something other than defined constants.
|
2120
docs/zr_manual.txt
Normal file
2120
docs/zr_manual.txt
Normal file
File diff suppressed because it is too large
Load Diff
@ -125,6 +125,81 @@ native ZRTools_HookOnTakeDamage(client, ZRTools_OnTakeDamage:callback);
|
||||
*/
|
||||
native ZRTools_UnhookOnTakeDamage(hookid);
|
||||
|
||||
/**
|
||||
* Callback function for StartTouch.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @param entity The entity index of the entity being touched.
|
||||
*/
|
||||
functag public ZRTools_Action:ZRTools_StartTouch(client, entity);
|
||||
|
||||
/**
|
||||
* Hooks StartTouch on a client.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @param callback The callback function for hook.
|
||||
* @return The unique HookID.
|
||||
*/
|
||||
native ZRTools_HookStartTouch(client, ZRTools_StartTouch:callback);
|
||||
|
||||
/**
|
||||
* Unhooks StartTouch on a client.
|
||||
*
|
||||
* @param hookid The HookID of the hook.
|
||||
* @error Invalid HookID.
|
||||
*/
|
||||
native ZRTools_UnhookStartTouch(hookid);
|
||||
|
||||
/**
|
||||
* Callback function for Touch.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @param entity The entity index of the entity being touched.
|
||||
*/
|
||||
functag public ZRTools_Action:ZRTools_Touch(client, entity);
|
||||
|
||||
/**
|
||||
* Hooks Touch on a client.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @param callback The callback function for hook.
|
||||
* @return The unique HookID.
|
||||
*/
|
||||
native ZRTools_HookTouch(client, ZRTools_Touch:callback);
|
||||
|
||||
/**
|
||||
* Unhooks Touch on a client.
|
||||
*
|
||||
* @param hookid The HookID of the hook.
|
||||
* @error Invalid HookID.
|
||||
*/
|
||||
native ZRTools_UnhookTouch(hookid);
|
||||
|
||||
/**
|
||||
* Callback function for EndTouch.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @param entity The entity index of the entity being touched.
|
||||
*/
|
||||
functag public ZRTools_Action:ZRTools_EndTouch(client, entity);
|
||||
|
||||
/**
|
||||
* Hooks EndTouch on a client.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @param callback The callback function for hook.
|
||||
* @return The unique HookID.
|
||||
*/
|
||||
native ZRTools_HookEndTouch(client, ZRTools_EndTouch:callback);
|
||||
|
||||
/**
|
||||
* Unhooks EndTouch on a client.
|
||||
*
|
||||
* @param hookid The HookID of the hook.
|
||||
* @error Invalid HookID.
|
||||
*/
|
||||
native ZRTools_UnhookEndTouch(hookid);
|
||||
|
||||
/**
|
||||
* Callback function for Weapon_CanUse.
|
||||
* Called when a client attempts to pick up a weapon.
|
||||
|
@ -136,7 +136,6 @@ public OnMapStart()
|
||||
RoundEndOnMapStart();
|
||||
InfectOnMapStart();
|
||||
SEffectsOnMapStart();
|
||||
AntiStickOnMapStart();
|
||||
ZSpawnOnMapStart();
|
||||
|
||||
}
|
||||
@ -163,6 +162,7 @@ public OnConfigsExecuted()
|
||||
InfectLoad();
|
||||
VEffectsLoad();
|
||||
SEffectsLoad();
|
||||
AntiStickLoad();
|
||||
ClassLoad();
|
||||
VolLoad();
|
||||
|
||||
@ -185,6 +185,7 @@ public OnClientPutInServer(client)
|
||||
InfectClientInit(client);
|
||||
DamageClientInit(client);
|
||||
SEffectsClientInit(client);
|
||||
AntiStickClientInit(client);
|
||||
SpawnProtectClientInit(client);
|
||||
RespawnClientInit(client);
|
||||
ZTeleClientInit(client);
|
||||
@ -203,6 +204,7 @@ public OnClientDisconnect(client)
|
||||
WeaponsOnClientDisconnect(client);
|
||||
InfectOnClientDisconnect(client);
|
||||
DamageOnClientDisconnect(client);
|
||||
AntiStickOnClientDisconnect(client);
|
||||
ZSpawnOnClientDisconnect(client);
|
||||
VolOnPlayerDisconnect(client);
|
||||
}
|
||||
|
@ -35,58 +35,58 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* @section Offsets relating to player hull dimensions.
|
||||
*/
|
||||
#define ANTISTICK_PLAYER_HULL_XY_OFFSET 32
|
||||
#define ANTISTICK_PLAYER_HULL_Z_OFFSET 12
|
||||
#define ANTISTICK_PLAYER_HULL_STACK_OFFSET 14
|
||||
/**
|
||||
* @endsection
|
||||
*/
|
||||
* Default player hull width.
|
||||
*/
|
||||
#define ANTISTICK_DEFAULT_HULL_WIDTH GetConVarFloat(g_hCvarsList[CVAR_ANTISTICK_DEFAULT_WIDTH])
|
||||
|
||||
/**
|
||||
* Variable to store antistick offset value.
|
||||
* Handle to keyvalue structure where data is stored.
|
||||
*/
|
||||
new g_iToolsCollisionGroup;
|
||||
new Handle:g_kvAntiStick = INVALID_HANDLE;
|
||||
|
||||
/**
|
||||
* Handle to keep track of AntiStickTimer.
|
||||
* Stores "StartTouch" HookID's for each client.
|
||||
*/
|
||||
new Handle:tAntiStick = INVALID_HANDLE;
|
||||
new g_iStartTouchHookID[MAXPLAYERS + 1] = {-1, ...};
|
||||
|
||||
/**
|
||||
* Find antistick-specific offsets here.
|
||||
* List of components that make up the model's rectangular boundaries.
|
||||
*
|
||||
* F = Front
|
||||
* B = Back
|
||||
* L = Left
|
||||
* R = Right
|
||||
* U = Upper
|
||||
* D = Down
|
||||
*/
|
||||
AntiStickOnOffsetsFound()
|
||||
enum AntiStickBoxBound
|
||||
{
|
||||
// If offset "m_CollisionGroup" can't be found, then stop the plugin.
|
||||
g_iToolsCollisionGroup = FindSendPropInfo("CBaseEntity", "m_CollisionGroup");
|
||||
if (g_iToolsCollisionGroup == -1)
|
||||
{
|
||||
LogEvent(false, LogType_Fatal, LOG_CORE_EVENTS, LogModule_Antistick, "Offsets", "Offset \"CBaseEntity::m_CollisionGroup\" was not found.");
|
||||
}
|
||||
BoxBound_FUR = 0, /** Front upper right */
|
||||
BoxBound_FUL, /** etc.. */
|
||||
BoxBound_FDR,
|
||||
BoxBound_FDL,
|
||||
BoxBound_BUR,
|
||||
BoxBound_BUL,
|
||||
BoxBound_BDR,
|
||||
BoxBound_BDL,
|
||||
}
|
||||
/**
|
||||
* Create commands related to antistick here.
|
||||
*/
|
||||
AntiStickOnCommandsCreate()
|
||||
{
|
||||
// Create public command to list model data.
|
||||
RegConsoleCmd("zr_antistick_list_models", AntiStickListModelsCommand, "Lists all players and their model data in console. Usage: zr_antistick_list_models");
|
||||
|
||||
// Create admin command to set model hull width.
|
||||
RegAdminCmd("zr_antistick_set_width", AntiStickSetWidthCommand, ADMFLAG_GENERIC, "Sets the width of a model's hull. (See zr_antistick_list_models) Usage: zr_antistick_set_width <model/player> <width>");
|
||||
}
|
||||
|
||||
/**
|
||||
* Map is starting.
|
||||
* Creates/loads antistick data file.
|
||||
*/
|
||||
AntiStickOnMapStart()
|
||||
AntiStickLoad()
|
||||
{
|
||||
// Reset timer handle.
|
||||
tAntiStick = INVALID_HANDLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* The round is starting.
|
||||
*/
|
||||
AntiStickOnRoundStart()
|
||||
{
|
||||
// If timer is running, kill it.
|
||||
if (tAntiStick != INVALID_HANDLE)
|
||||
{
|
||||
KillTimer(tAntiStick);
|
||||
}
|
||||
|
||||
// If antistick is disabled, then stop.
|
||||
new bool:antistick = GetConVarBool(g_hCvarsList[CVAR_ANTISTICK]);
|
||||
if (!antistick)
|
||||
@ -94,118 +94,441 @@ AntiStickOnRoundStart()
|
||||
return;
|
||||
}
|
||||
|
||||
new Float:interval = GetConVarFloat(g_hCvarsList[CVAR_ANTISTICK_INTERVAL]);
|
||||
tAntiStick = CreateTimer(interval, AntiStickTimer, _, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
|
||||
// Create antistick keyvalues if it hasn't been created yet.
|
||||
if (g_kvAntiStick == INVALID_HANDLE)
|
||||
{
|
||||
g_kvAntiStick = CreateKeyValues("antistick");
|
||||
}
|
||||
|
||||
// Initialize keyvalues.
|
||||
if (!AntiStickLoadData())
|
||||
{
|
||||
AntiStickSaveData();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Client is joining the server.
|
||||
*
|
||||
* @param client The client index.
|
||||
*/
|
||||
AntiStickClientInit(client)
|
||||
{
|
||||
// Hook "StartTouch" and "EndTouch" on client.
|
||||
g_iStartTouchHookID[client] = ZRTools_HookStartTouch(client, AntiStickStartTouch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unhook StartTouch and EndTouch function on a client.
|
||||
*
|
||||
* @param client The client index.
|
||||
*/
|
||||
AntiStickOnClientDisconnect(client)
|
||||
{
|
||||
// Unhook "StartTouch" callback, and reset variable.
|
||||
if (g_iStartTouchHookID[client] != -1)
|
||||
{
|
||||
ZRTools_UnhookStartTouch(g_iStartTouchHookID[client]);
|
||||
g_iStartTouchHookID[client] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Load antistick data from file.
|
||||
*
|
||||
* @return True if loaded successfully, false if file wasn't found.
|
||||
*/
|
||||
stock bool:AntiStickLoadData()
|
||||
{
|
||||
// Get cvar's path.
|
||||
decl String:filepath[PLATFORM_MAX_PATH];
|
||||
GetConVarString(g_hCvarsList[CVAR_ANTISTICK_FILE_PATH], filepath, sizeof(filepath));
|
||||
|
||||
// Build full path in return string.
|
||||
decl String:fullpath[PLATFORM_MAX_PATH];
|
||||
BuildPath(Path_SM, fullpath, PLATFORM_MAX_PATH, filepath);
|
||||
|
||||
// Log action to game events.
|
||||
LogEvent(false, LogType_Normal, LOG_GAME_EVENTS, LogModule_AntiStick, "Loaded Data", "Antistick data has been loaded from \"%s\"", fullpath);
|
||||
|
||||
// Retrieve keyvalue data from a file, and store in server's memory.
|
||||
KvRewind(g_kvAntiStick);
|
||||
return FileToKeyValues(g_kvAntiStick, fullpath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save antistick data to file.
|
||||
*/
|
||||
stock AntiStickSaveData()
|
||||
{
|
||||
// Get cvar's path.
|
||||
decl String:filepath[PLATFORM_MAX_PATH];
|
||||
GetConVarString(g_hCvarsList[CVAR_ANTISTICK_FILE_PATH], filepath, sizeof(filepath));
|
||||
|
||||
// Build full path in return string.
|
||||
decl String:fullpath[PLATFORM_MAX_PATH];
|
||||
BuildPath(Path_SM, fullpath, PLATFORM_MAX_PATH, filepath);
|
||||
|
||||
// Log action to game events.
|
||||
LogEvent(false, LogType_Normal, LOG_GAME_EVENTS, LogModule_AntiStick, "Saved Data", "Antistick data has been saved to \"%s\"", fullpath);
|
||||
|
||||
// Dump keyvalue structure into a file from the server's memory.
|
||||
KvRewind(g_kvAntiStick);
|
||||
KeyValuesToFile(g_kvAntiStick, fullpath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get hull width on a client's model. (or return default)
|
||||
*
|
||||
* @param client The client index.
|
||||
* @param model If a client index of 0 is given, this model is used.
|
||||
*/
|
||||
stock Float:AntiStickGetModelHullWidth(client, const String:model[] = "")
|
||||
{
|
||||
decl String:clientmodel[PLATFORM_MAX_PATH];
|
||||
|
||||
if (ZRIsClientValid(client))
|
||||
{
|
||||
// Get client's model.
|
||||
GetClientModel(client, clientmodel, sizeof(clientmodel));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Copy given model to 'clientmodel.'
|
||||
strcopy(clientmodel, sizeof(clientmodel), model);
|
||||
}
|
||||
|
||||
// Find model in antistick data.
|
||||
KvRewind(g_kvAntiStick);
|
||||
if (KvJumpToKey(g_kvAntiStick, clientmodel))
|
||||
{
|
||||
// Return value from file.
|
||||
return KvGetFloat(g_kvAntiStick, "hull_width", ANTISTICK_DEFAULT_HULL_WIDTH);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Return default CS:S hull width.
|
||||
return ANTISTICK_DEFAULT_HULL_WIDTH;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set hull width on a client's model.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @param model If a client index of 0 is given, this model is used.
|
||||
* @param hull_width The width of the model hull.
|
||||
*/
|
||||
stock AntiStickSetModelHullWidth(client, const String:model[] = "", Float:hull_width)
|
||||
{
|
||||
decl String:clientmodel[PLATFORM_MAX_PATH];
|
||||
|
||||
if (ZRIsClientValid(client))
|
||||
{
|
||||
// Get client's model.
|
||||
GetClientModel(client, clientmodel, sizeof(clientmodel));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Copy given model to 'clientmodel.'
|
||||
strcopy(clientmodel, sizeof(clientmodel), model);
|
||||
}
|
||||
|
||||
// Replace "/" with "-" because a slash indicates a new level in keyvalues.
|
||||
ReplaceString(clientmodel, sizeof(clientmodel), "/", "-");
|
||||
|
||||
// Find model in antistick data.
|
||||
KvRewind(g_kvAntiStick);
|
||||
|
||||
// Create key if it doesn't already exist.
|
||||
KvJumpToKey(g_kvAntiStick, clientmodel, true);
|
||||
|
||||
// Set value.
|
||||
KvSetFloat(g_kvAntiStick, "hull_width", hull_width);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback function for StartTouch.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @param entity The entity index of the entity being touched.
|
||||
*/
|
||||
public ZRTools_Action:AntiStickStartTouch(client, entity)
|
||||
{
|
||||
// If client isn't in-game, then stop.
|
||||
if (!IsClientInGame(client))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If client is touching themselves, then leave them alone :P
|
||||
if (client == entity)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If touched entity isn't a valid client, then stop.
|
||||
if (!ZRIsClientValid(entity))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If the clients aren't colliding, then stop.
|
||||
if (!AntiStickIsModelBoxColliding(client, entity))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Disable collisions to unstick, and start timers to re-solidify.
|
||||
if (AntiStickClientCollisionGroup(client) == ANTISTICK_COLLISIONS_ON)
|
||||
{
|
||||
AntiStickClientCollisionGroup(client, true, ANTISTICK_COLLISIONS_OFF);
|
||||
CreateTimer(0.0, AntiStickSolidifyTimer, client, TIMER_FLAG_NO_MAPCHANGE|TIMER_REPEAT);
|
||||
}
|
||||
|
||||
if (AntiStickClientCollisionGroup(entity) == ANTISTICK_COLLISIONS_ON)
|
||||
{
|
||||
AntiStickClientCollisionGroup(entity, true, ANTISTICK_COLLISIONS_OFF);
|
||||
CreateTimer(0.0, AntiStickSolidifyTimer, entity, TIMER_FLAG_NO_MAPCHANGE|TIMER_REPEAT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback function for EndTouch.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @param entity The entity index of the entity being touched.
|
||||
*/
|
||||
public Action:AntiStickSolidifyTimer(Handle:timer, any:client)
|
||||
{
|
||||
// If client has left, then stop the timer.
|
||||
if (!IsClientInGame(client))
|
||||
{
|
||||
return Plugin_Stop;
|
||||
}
|
||||
|
||||
// If the client's collisions are already on, then stop.
|
||||
if (AntiStickClientCollisionGroup(client) == ANTISTICK_COLLISIONS_ON)
|
||||
{
|
||||
return Plugin_Stop;
|
||||
}
|
||||
|
||||
// Loop through all client's and check if client is stuck in them.
|
||||
for (new x = 1; x <= MaxClients; x++)
|
||||
{
|
||||
// If client isn't in-game, then stop.
|
||||
if (!IsClientInGame(x))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Don't compare the same clients.
|
||||
if (client == x)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the client is colliding with a client, then allow timer to continue.
|
||||
if (AntiStickIsModelBoxColliding(client, x))
|
||||
{
|
||||
return Plugin_Continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Change collisions back to normal.
|
||||
AntiStickClientCollisionGroup(client, true, ANTISTICK_COLLISIONS_ON);
|
||||
|
||||
return Plugin_Stop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build the model box by finding all vertices.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @param boundaries Array with 'AntiStickBoxBounds' for indexes to return bounds into.
|
||||
* @param width The width of the model box.
|
||||
*/
|
||||
stock AntiStickBuildModelBox(client, Float:boundaries[AntiStickBoxBound][3], Float:width)
|
||||
{
|
||||
new Float:clientloc[3];
|
||||
new Float:twistang[3];
|
||||
new Float:cornerang[3];
|
||||
new Float:sideloc[3];
|
||||
new Float:finalloc[4][3];
|
||||
|
||||
// Get needed vector info.
|
||||
GetClientAbsOrigin(client, clientloc);
|
||||
|
||||
// Set the pitch to 0.
|
||||
twistang[1] = 90.0;
|
||||
cornerang[1] = 0.0;
|
||||
|
||||
for (new x = 0; x < 4; x++)
|
||||
{
|
||||
// Jump to point on player's left side.
|
||||
AntiStickJumpToPoint(clientloc, twistang, width / 2, sideloc);
|
||||
|
||||
// From this point, jump to the corner, which would be half the width from the middle of a side.
|
||||
AntiStickJumpToPoint(sideloc, cornerang, width / 2, finalloc[x]);
|
||||
|
||||
// Twist 90 degrees to find next side/corner.
|
||||
twistang[1] += 90.0;
|
||||
cornerang[1] += 90.0;
|
||||
|
||||
// Fix angles.
|
||||
if (twistang[1] > 180.0)
|
||||
{
|
||||
twistang[1] -= 360.0;
|
||||
}
|
||||
|
||||
if (cornerang[1] > 180.0)
|
||||
{
|
||||
cornerang[1] -= 360.0;
|
||||
}
|
||||
}
|
||||
|
||||
// Copy all horizontal model box data to array.
|
||||
boundaries[BoxBound_FUR][0] = finalloc[3][0];
|
||||
boundaries[BoxBound_FUR][1] = finalloc[3][1];
|
||||
boundaries[BoxBound_FUL][0] = finalloc[0][0];
|
||||
boundaries[BoxBound_FUL][1] = finalloc[0][1];
|
||||
boundaries[BoxBound_FDR][0] = finalloc[3][0];
|
||||
boundaries[BoxBound_FDR][1] = finalloc[3][1];
|
||||
boundaries[BoxBound_FDL][0] = finalloc[0][0];
|
||||
boundaries[BoxBound_FDL][1] = finalloc[0][1];
|
||||
boundaries[BoxBound_BUR][0] = finalloc[2][0];
|
||||
boundaries[BoxBound_BUR][1] = finalloc[2][1];
|
||||
boundaries[BoxBound_BUL][0] = finalloc[1][0];
|
||||
boundaries[BoxBound_BUL][1] = finalloc[1][1];
|
||||
boundaries[BoxBound_BDR][0] = finalloc[2][0];
|
||||
boundaries[BoxBound_BDR][1] = finalloc[2][1];
|
||||
boundaries[BoxBound_BDL][0] = finalloc[1][0];
|
||||
boundaries[BoxBound_BDL][1] = finalloc[1][1];
|
||||
|
||||
// Set Z bounds.
|
||||
new Float:eyeloc[3];
|
||||
GetClientEyePosition(client, eyeloc);
|
||||
|
||||
boundaries[BoxBound_FUR][2] = eyeloc[2];
|
||||
boundaries[BoxBound_FUL][2] = eyeloc[2];
|
||||
boundaries[BoxBound_FDR][2] = clientloc[2] + 15.0;
|
||||
boundaries[BoxBound_FDL][2] = clientloc[2] + 15.0;
|
||||
boundaries[BoxBound_BUR][2] = eyeloc[2];
|
||||
boundaries[BoxBound_BUL][2] = eyeloc[2];
|
||||
boundaries[BoxBound_BDR][2] = clientloc[2] + 15.0;
|
||||
boundaries[BoxBound_BDL][2] = clientloc[2] + 15.0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Jumps from a point to another based off angle and distance.
|
||||
*
|
||||
* @param vec Point to jump from.
|
||||
* @param ang Angle to base jump off of.
|
||||
* @param distance Distance to jump
|
||||
* @param result Resultant point.
|
||||
*/
|
||||
stock AntiStickJumpToPoint(const Float:vec[3], const Float:ang[3], Float:distance, Float:result[3])
|
||||
{
|
||||
new Float:viewvec[3];
|
||||
|
||||
// Turn client angle, into a vector.
|
||||
GetAngleVectors(ang, viewvec, NULL_VECTOR, NULL_VECTOR);
|
||||
|
||||
// Normalize vector.
|
||||
NormalizeVector(viewvec, viewvec);
|
||||
|
||||
// Scale to the given distance.
|
||||
ScaleVector(viewvec, distance);
|
||||
|
||||
// Add the vectors together.
|
||||
AddVectors(vec, viewvec, result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the max/min value of a 3D box on any axis.
|
||||
*
|
||||
* @param axis The axis to check.
|
||||
* @param boundaries The boundaries to check.
|
||||
* @param min Return the min value instead.
|
||||
*/
|
||||
stock Float:AntiStickGetBoxMaxBoundary(axis, Float:boundaries[AntiStickBoxBound][3], bool:min = false)
|
||||
{
|
||||
// Create 'outlier' with initial value of first boundary.
|
||||
new Float:outlier = boundaries[0][axis];
|
||||
|
||||
// x = Boundary index. (Start at 1 because we initialized 'outlier' with the 0 index's value)
|
||||
new size = sizeof(boundaries);
|
||||
for (new x = 1; x < size; x++)
|
||||
{
|
||||
if (!min && boundaries[x][axis] > outlier)
|
||||
{
|
||||
outlier = boundaries[x][axis];
|
||||
}
|
||||
else if (min && boundaries[x][axis] < outlier)
|
||||
{
|
||||
outlier = boundaries[x][axis];
|
||||
}
|
||||
}
|
||||
|
||||
// Return value.
|
||||
return outlier;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a player is currently stuck within another player.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @return The client index of the other stuck player, -1 when
|
||||
* player is not stuck.
|
||||
* @param client1 The first client index.
|
||||
* @param client2 The second client index.
|
||||
* @return True if they are stuck together, false if not.
|
||||
*/
|
||||
AntiStickIsStuck(client)
|
||||
stock bool:AntiStickIsModelBoxColliding(client1, client2)
|
||||
{
|
||||
new Float:clientloc[3];
|
||||
new Float:stuckloc[3];
|
||||
new Float:client1modelbox[AntiStickBoxBound][3];
|
||||
new Float:client2modelbox[AntiStickBoxBound][3];
|
||||
|
||||
GetClientAbsOrigin(client, clientloc);
|
||||
// Get model hull widths.
|
||||
new Float:hull_width1 = AntiStickGetModelHullWidth(client1);
|
||||
new Float:hull_width2 = AntiStickGetModelHullWidth(client2);
|
||||
|
||||
// x = client index.
|
||||
for (new x = 1; x <= MaxClients; x++)
|
||||
// Build model boxes for each client.
|
||||
AntiStickBuildModelBox(client1, client1modelbox, hull_width1);
|
||||
AntiStickBuildModelBox(client2, client2modelbox, hull_width2);
|
||||
|
||||
// Compare x values.
|
||||
new Float:max1x = AntiStickGetBoxMaxBoundary(0, client1modelbox);
|
||||
new Float:max2x = AntiStickGetBoxMaxBoundary(0, client2modelbox);
|
||||
new Float:min1x = AntiStickGetBoxMaxBoundary(0, client1modelbox, true);
|
||||
new Float:min2x = AntiStickGetBoxMaxBoundary(0, client2modelbox, true);
|
||||
|
||||
if (max1x < min2x || min1x > max2x)
|
||||
{
|
||||
// Validate player is in-game, alive, and isn't the player being checked. ('client')
|
||||
if (!IsClientInGame(x) || !IsPlayerAlive(x) || x == client)
|
||||
{
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
|
||||
GetClientAbsOrigin(x, stuckloc);
|
||||
// Compare y values.
|
||||
new Float:max1y = AntiStickGetBoxMaxBoundary(1, client1modelbox);
|
||||
new Float:max2y = AntiStickGetBoxMaxBoundary(1, client2modelbox);
|
||||
new Float:min1y = AntiStickGetBoxMaxBoundary(1, client1modelbox, true);
|
||||
new Float:min2y = AntiStickGetBoxMaxBoundary(1, client2modelbox, true);
|
||||
|
||||
// x-y plane distance formula: sqrt((x2-x1)^2 + (y2-y1)^2)
|
||||
new Float:xydistance = SquareRoot(Pow(stuckloc[0] - clientloc[0], 2.0) + Pow(stuckloc[1] - clientloc[1], 2.0));
|
||||
if (xydistance < ANTISTICK_PLAYER_HULL_XY_OFFSET)
|
||||
if (max1y < min2y || min1y > max2y)
|
||||
{
|
||||
if (clientloc[2] <= stuckloc[2])
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compare z values.
|
||||
new Float:max1z = AntiStickGetBoxMaxBoundary(2, client1modelbox);
|
||||
new Float:max2z = AntiStickGetBoxMaxBoundary(2, client2modelbox);
|
||||
new Float:min1z = AntiStickGetBoxMaxBoundary(2, client1modelbox, true);
|
||||
new Float:min2z = AntiStickGetBoxMaxBoundary(2, client2modelbox, true);
|
||||
|
||||
if (max1z < min2z || min1z > max2z)
|
||||
{
|
||||
new Float:eyeloc[3];
|
||||
GetClientEyePosition(client, eyeloc);
|
||||
|
||||
// Get the distance between the eyes and feet and subtract the stack "view crush."
|
||||
new Float:eyedistance = FloatAbs(eyeloc[2] - clientloc[2]) - ANTISTICK_PLAYER_HULL_STACK_OFFSET;
|
||||
new Float:zdistance = FloatAbs(stuckloc[2] - clientloc[2]);
|
||||
|
||||
if (zdistance <= eyedistance + ANTISTICK_PLAYER_HULL_Z_OFFSET)
|
||||
{
|
||||
return x;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Timer callback, automatically unsticks players that are stuck together.
|
||||
*/
|
||||
public Action:AntiStickTimer(Handle:timer)
|
||||
{
|
||||
// x = client index
|
||||
for (new x = 1; x <= MaxClients; x++)
|
||||
{
|
||||
// Validate player is in-game and alive.
|
||||
if (!IsClientInGame(x) || !IsPlayerAlive(x))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Stop if the player isn't stuck.
|
||||
new stuckindex = AntiStickIsStuck(x);
|
||||
if (stuckindex == -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (AntiStickClientCollisionGroup(x, false) == ANTISTICK_COLLISIONS_ON)
|
||||
{
|
||||
AntiStickClientCollisionGroup(x, true, ANTISTICK_COLLISIONS_OFF);
|
||||
CreateTimer(0.5, AntiStickSolidify, x, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
|
||||
}
|
||||
|
||||
if (AntiStickClientCollisionGroup(stuckindex, false) == ANTISTICK_COLLISIONS_ON)
|
||||
{
|
||||
AntiStickClientCollisionGroup(stuckindex, true, ANTISTICK_COLLISIONS_OFF);
|
||||
CreateTimer(0.5, AntiStickSolidify, stuckindex, TIMER_REPEAT|TIMER_FLAG_NO_MAPCHANGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Repeated timer function.
|
||||
* Re-solidifies a player being unstuck.
|
||||
*
|
||||
* @param timer The timer handle.
|
||||
* @param client The client index.
|
||||
*/
|
||||
public Action:AntiStickSolidify(Handle:timer, any:client)
|
||||
{
|
||||
// Validate player is in-game, alive, and is being unstuck.
|
||||
if (!IsClientInGame(client) || !IsPlayerAlive(client) || AntiStickClientCollisionGroup(client, false) == ANTISTICK_COLLISIONS_ON)
|
||||
{
|
||||
return Plugin_Stop;
|
||||
}
|
||||
|
||||
// Stop if the player is still stuck.
|
||||
if (AntiStickIsStuck(client) > -1)
|
||||
{
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
AntiStickClientCollisionGroup(client, true, ANTISTICK_COLLISIONS_ON);
|
||||
|
||||
return Plugin_Stop;
|
||||
// They are intersecting.
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -214,14 +537,110 @@ public Action:AntiStickSolidify(Handle:timer, any:client)
|
||||
* @param collisiongroup Collision group flag.
|
||||
* @return The collision group on the client, -1 if applying collision group.
|
||||
*/
|
||||
AntiStickClientCollisionGroup(client, bool:apply = true, collisiongroup = 0)
|
||||
AntiStickClientCollisionGroup(client, bool:apply = false, collisiongroup = 0)
|
||||
{
|
||||
if (apply)
|
||||
{
|
||||
SetEntData(client, g_iToolsCollisionGroup, collisiongroup, 1, true);
|
||||
SetEntProp(client, Prop_Data, "m_CollisionGroup", collisiongroup);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
return GetEntData(client, g_iToolsCollisionGroup, 1);
|
||||
return GetEntProp(client, Prop_Data, "m_CollisionGroup");
|
||||
}
|
||||
|
||||
/**
|
||||
* Command callback (zr_antistick_list_models)
|
||||
* Lists all player's models and model hull data.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @param argc Argument count.
|
||||
*/
|
||||
public Action:AntiStickListModelsCommand(client, argc)
|
||||
{
|
||||
// Tell client we are listing model data.
|
||||
TranslationPrintToConsole(client, "AntiStick command list models list");
|
||||
|
||||
decl String:clientname[MAX_NAME_LENGTH];
|
||||
decl String:modelname[PLATFORM_MAX_PATH];
|
||||
new Float:hull_width;
|
||||
|
||||
// x = Client index.
|
||||
for (new x = 1; x <= MaxClients; x++)
|
||||
{
|
||||
// If client isn't in-game, then stop.
|
||||
if (!IsClientInGame(x))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get all needed data.
|
||||
GetClientName(x, clientname, sizeof(clientname));
|
||||
GetClientModel(x, modelname, sizeof(modelname));
|
||||
hull_width = AntiStickGetModelHullWidth(x);
|
||||
|
||||
TranslationPrintToConsole(client, "AntiStick command list models name", clientname, modelname, hull_width);
|
||||
}
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Command callback (zr_antistick_set_width)
|
||||
* Set the hull width on any model.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @param argc Argument count.
|
||||
*/
|
||||
public Action:AntiStickSetWidthCommand(client, argc)
|
||||
{
|
||||
// If not enough arguments given, then stop.
|
||||
if (argc < 2)
|
||||
{
|
||||
TranslationReplyToCommand(client, "AntiStick command set width syntax");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
// Get target model.
|
||||
decl String:model[PLATFORM_MAX_PATH];
|
||||
GetCmdArg(1, model, sizeof(model));
|
||||
|
||||
// If model doesn't exist, then stop.
|
||||
if (!FileExists(model))
|
||||
{
|
||||
new target = FindTarget(client, model);
|
||||
if (target <= 0)
|
||||
{
|
||||
TranslationReplyToCommand(client, "AntiStick command set width invalid model", model);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get the target's model.
|
||||
GetClientModel(target, model, sizeof(model));
|
||||
}
|
||||
}
|
||||
|
||||
// Get the given hull width..
|
||||
decl String:strHullwidth[PLATFORM_MAX_PATH];
|
||||
GetCmdArg(2, strHullwidth, sizeof(strHullwidth));
|
||||
|
||||
new Float:hull_width = StringToFloat(strHullwidth);
|
||||
if (hull_width <= 0.0)
|
||||
{
|
||||
TranslationReplyToCommand(client, "AntiStick command set width invalid width", hull_width);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
// Set hull width.
|
||||
AntiStickSetModelHullWidth(0, model, hull_width);
|
||||
|
||||
// Tell client it was successful.
|
||||
TranslationReplyToCommand(client, "AntiStick command set width successful", model, hull_width);
|
||||
|
||||
// Save data.
|
||||
AntiStickSaveData();
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
@ -39,6 +39,7 @@ CommandsInit()
|
||||
InfectOnCommandsCreate();
|
||||
MenuOnCommandsCreate();
|
||||
ZAdminOnCommandsCreate();
|
||||
AntiStickOnCommandsCreate();
|
||||
ZCookiesOnCommandsCreate();
|
||||
ZSpawnOnCommandsCreate();
|
||||
ZTeleOnCommandsCreate();
|
||||
@ -51,200 +52,3 @@ CommandsInit()
|
||||
ClassOnCommandsHook();
|
||||
DamageOnCommandsHook();
|
||||
}
|
||||
|
||||
/*CreateCommands()
|
||||
{
|
||||
RegAdminCmd("zr_infect", Command_Infect, ADMFLAG_GENERIC, "Infects the specified player");
|
||||
RegAdminCmd("zr_spawn", Command_Respawn, ADMFLAG_GENERIC, "Respawns the specified player following auto-respawning rules");
|
||||
|
||||
|
||||
//RegAdminCmd("zr_set_class_knockback", Command_SetClassKnockback, ADMFLAG_GENERIC, "Sets the knockback to the specified class. Usage: zr_set_class_knockback <class name> <value>");
|
||||
//RegAdminCmd("zr_get_class_knockback", Command_GetClassKnockback, ADMFLAG_GENERIC, "Gets the knockback to the specified class. Usage: zr_get_class_knockback <class name>");
|
||||
|
||||
RegAdminCmd("zr_admin", Command_AdminMenu, ADMFLAG_GENERIC, "Displays the admin menu for Zombie: Reloaded.");
|
||||
//RegAdminCmd("zr_knockback_m", Command_KnockbackMMenu, ADMFLAG_GENERIC, "Displays the knockback multiplier menu.");
|
||||
|
||||
RegAdminCmd("zr_anticamp_create_volume", Command_AnticampCreateVolume, ADMFLAG_GENERIC, "Creates a rectangular hurt volume between two points. Usage: ht_create_volume <damage> <interval> <x1> <y1> <z1> <x2> <y2> <z2>");
|
||||
RegAdminCmd("zr_anticamp_remove_volume", Command_AnticampRemoveVolume, ADMFLAG_GENERIC, "Removes a volume. Use zr_anticamp_list to list volumes. Usage: zr_anticamp_remove_volume <volume index>");
|
||||
RegAdminCmd("zr_anticamp_list", Command_AnticampList, ADMFLAG_GENERIC, "List current volumes.");
|
||||
|
||||
RegConsoleCmd("zr_log_flags", Command_LogFlags, "List available logging flags.");
|
||||
}*/
|
||||
|
||||
/*public Action:Command_Infect(client, argc)
|
||||
{
|
||||
new bool:enabled = GetConVarBool(g_hCvarsList[CVAR_ENABLE]);
|
||||
if (argc < 1 || !enabled)
|
||||
{
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
decl String:arg1[32];
|
||||
GetCmdArg(1, arg1, sizeof(arg1));
|
||||
|
||||
decl String:target_name_list[MAX_TARGET_LENGTH];
|
||||
new targets[MAXPLAYERS];
|
||||
new bool:tn_is_ml;
|
||||
|
||||
new tcount = ProcessTargetString(arg1, client, targets, MAXPLAYERS, COMMAND_FILTER_ALIVE, target_name_list, sizeof(target_name_list), tn_is_ml);
|
||||
if (tcount <= 0)
|
||||
{
|
||||
ReplyToTargetError(client, tcount);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
decl String:target_name[64];
|
||||
decl String:client_name[64];
|
||||
|
||||
if (client > 0)
|
||||
{
|
||||
GetClientName(client, client_name, sizeof(client_name));
|
||||
}
|
||||
else
|
||||
{
|
||||
client_name = "Console\0";
|
||||
}
|
||||
|
||||
for (new x = 0; x < tcount; x++)
|
||||
{
|
||||
InfectHumanToZombie(targets[x]);
|
||||
if (LogCheckFlag(LOG_GAME_EVENTS, LOG_MODULE_COMMANDS))
|
||||
{
|
||||
GetClientName(targets[x], target_name, sizeof(target_name));
|
||||
LogMessageFormatted(client, "admin commands", "infect", "\"%s\" infected \"%s\".", true, client_name, target_name);
|
||||
}
|
||||
}
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action:Command_Respawn(client, argc)
|
||||
{
|
||||
new bool:enabled = GetConVarBool(g_hCvarsList[CVAR_ENABLE]);
|
||||
if (argc < 1 || !enabled)
|
||||
{
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
decl String:arg1[32];
|
||||
GetCmdArg(1, arg1, sizeof(arg1));
|
||||
|
||||
decl String:target_name_list[MAX_TARGET_LENGTH];
|
||||
new targets[MAXPLAYERS];
|
||||
new bool:tn_is_ml;
|
||||
|
||||
new tcount = ProcessTargetString(arg1, client, targets, MAXPLAYERS, COMMAND_FILTER_DEAD, target_name_list, sizeof(target_name_list), tn_is_ml);
|
||||
if (tcount <= 0)
|
||||
{
|
||||
ReplyToTargetError(client, tcount);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
decl String:client_name[64];
|
||||
decl String:target_name[64];
|
||||
|
||||
if (client > 0)
|
||||
{
|
||||
GetClientName(client, client_name, sizeof(client_name));
|
||||
}
|
||||
else
|
||||
{
|
||||
client_name = "Console\0";
|
||||
}
|
||||
|
||||
new team;
|
||||
for (new x = 0; x < tcount; x++)
|
||||
{
|
||||
team = GetClientTeam(targets[x]);
|
||||
if (team == CS_TEAM_T || team == CS_TEAM_CT)
|
||||
{
|
||||
if (LogCheckFlag(LOG_GAME_EVENTS, LOG_MODULE_COMMANDS))
|
||||
{
|
||||
GetClientName(targets[x], target_name, sizeof(target_name));
|
||||
LogMessageFormatted(targets[x], "admin commands", "spawn", "\"%s\" spawned player \"%s\".", true, client_name, target_name);
|
||||
}
|
||||
|
||||
RespawnSpawnClient(targets[x]);
|
||||
}
|
||||
}
|
||||
|
||||
return Plugin_Handled;
|
||||
}*/
|
||||
|
||||
/*public Action:Command_AdminMenu(client, argc)
|
||||
{
|
||||
if (ZRIsClientValid(client))
|
||||
{
|
||||
ZRAdminMenu(client);
|
||||
}
|
||||
else
|
||||
{
|
||||
// BAD!
|
||||
// ReplyToCommand(client, "This menu cannot be used from the console.");
|
||||
}
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action:Command_KnockbackMMenu(client, argc)
|
||||
{
|
||||
if (ZRIsClientValid(client))
|
||||
{
|
||||
// Disabled, under construction.
|
||||
// ZRKnockbackMMenu(client);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Tsk tsk no translation? :P
|
||||
//ReplyToCommand(client, "This menu cannot be used from the console.");
|
||||
}
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action:Command_TeleMenu(client, argc)
|
||||
{
|
||||
if (ZRIsClientValid(client))
|
||||
{
|
||||
ZRZTeleMenu(client);
|
||||
}
|
||||
else
|
||||
{
|
||||
// BAD!
|
||||
ReplyToCommand(client, "This menu cannot be used from the console.");
|
||||
}
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
public Action:Command_LogFlags(client, argc)
|
||||
{
|
||||
decl String:message[2048];
|
||||
message[0] = 0;
|
||||
|
||||
StrCat(message, sizeof(message), "LOG_CORE_EVENTS (1) - Log core events like executing files, error messages, etc.\n");
|
||||
StrCat(message, sizeof(message), "LOG_GAME_EVENTS (2) - Log game events like admin commands, suicide prevention and anticamp kills.\n");
|
||||
StrCat(message, sizeof(message), "LOG_PLAYER_COMMANDS (4) - Log commands made by the player.\n");
|
||||
StrCat(message, sizeof(message), "LOG_DEBUG (8) - Enable debug messages (if they exist).\n");
|
||||
StrCat(message, sizeof(message), "LOG_DEBUG_DETAIL (16) - Detailed debug messages. May cause spam.\n");
|
||||
StrCat(message, sizeof(message), "LOG_DEBUG_MAX_DETAIL (32) - Low level detailed debug messages. Causes spam! Only enable right before and after testing.\n");
|
||||
StrCat(message, sizeof(message), "LOG_LOG_TO_ADMINS (64) - Display log messages to admin chat.\n");
|
||||
StrCat(message, sizeof(message), "LOG_LOG_TO_CLIENT (128) - Display log messages to the client that executed the event/command.\n");
|
||||
StrCat(message, sizeof(message), "LOG_IGNORE_CONSOLE (256) - Don't log messages from client 0 (console).\n");
|
||||
StrCat(message, sizeof(message), "LOG_MODULES_ENABLED (512) - Enable detailed log control for developers. Module logs overrides previous flags.\n");
|
||||
StrCat(message, sizeof(message), "LOG_MODULE_ZOMBIE (1024) - zombie.inc");
|
||||
|
||||
ReplyToCommand(client, message);
|
||||
message[0] = 0;
|
||||
|
||||
StrCat(message, sizeof(message), "LOG_MODULE_AMBIENTSOUNDS (2048) - ambientsounds.inc\n");
|
||||
StrCat(message, sizeof(message), "LOG_MODULE_OVERLAYS (4096) - overlays.inc\n");
|
||||
StrCat(message, sizeof(message), "LOG_MODULE_SAYTRIGGERS (8192) - sayhooks.inc\n");
|
||||
StrCat(message, sizeof(message), "LOG_MODULE_TELEPORT (16384) - teleport.inc\n");
|
||||
StrCat(message, sizeof(message), "LOG_MODULE_CLASSES (32768) - classes.inc\n");
|
||||
StrCat(message, sizeof(message), "LOG_MODULE_WEAPONRESTICT (65536) - weaponrestrict.inc\n");
|
||||
StrCat(message, sizeof(message), "LOG_MODULE_COMMANDS (131072) - commands.inc\n");
|
||||
StrCat(message, sizeof(message), "LOG_MODULE_ANTICAMP (262144) - anticamp.inc\n");
|
||||
StrCat(message, sizeof(message), "LOG_MODULE_DAMAGE (524288) - damage.inc\n");
|
||||
StrCat(message, sizeof(message), "LOG_MODULE_OFFSETS (524288) - offsets.inc");
|
||||
|
||||
ReplyToCommand(client, message);
|
||||
return Plugin_Handled;
|
||||
}*/
|
||||
|
@ -254,7 +254,7 @@ ConfigOnModulesLoaded()
|
||||
ServerCommand("exec %s", mapconfig);
|
||||
|
||||
// Log action.
|
||||
LogEvent(false, LogType_Normal, LOG_CORE_EVENTS, LogModule_Config, "Executed post map config file: %s", path);
|
||||
LogEvent(false, LogType_Normal, LOG_CORE_EVENTS, LogModule_Config, "Post Map Configs", "Executed post map config file: %s", path);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -422,9 +422,10 @@ stock ConfigGetConfigAlias(ConfigFile:config, String:alias[], maxlen)
|
||||
*
|
||||
* @param config The config file to load.
|
||||
* @param arrayConfig Handle of the main array containing file data.
|
||||
* @param blocksize The max length of the contained strings.
|
||||
* @return True if file was loaded successfuly, false otherwise.
|
||||
*/
|
||||
stock bool:ConfigLoadConfig(ConfigFile:config, &Handle:arrayConfig)
|
||||
stock bool:ConfigLoadConfig(ConfigFile:config, &Handle:arrayConfig, blocksize = CONFIG_MAX_LENGTH)
|
||||
{
|
||||
// Get config's structure.
|
||||
new ConfigStructure:structure = ConfigGetConfigStructure(config);
|
||||
@ -441,7 +442,7 @@ stock bool:ConfigLoadConfig(ConfigFile:config, &Handle:arrayConfig)
|
||||
if (arrayConfig == INVALID_HANDLE)
|
||||
{
|
||||
// Create array in handle.
|
||||
arrayConfig = CreateArray(CONFIG_MAX_LENGTH);
|
||||
arrayConfig = CreateArray(blocksize);
|
||||
}
|
||||
|
||||
switch(structure)
|
||||
@ -463,17 +464,8 @@ stock bool:ConfigLoadConfig(ConfigFile:config, &Handle:arrayConfig)
|
||||
|
||||
decl String:line[PLATFORM_MAX_PATH];
|
||||
|
||||
while(!IsEndOfFile(hFile))
|
||||
while(ReadFileLine(hFile, line, sizeof(line)))
|
||||
{
|
||||
// Get current line text.
|
||||
ReadFileLine(hFile, line, sizeof(line));
|
||||
|
||||
// If line contains a ";", then stop.
|
||||
if (StrContains(line, ";") > -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Cut out comments at the end of a line.
|
||||
if (StrContains(line, "//") > -1)
|
||||
{
|
||||
@ -518,7 +510,7 @@ stock bool:ConfigLoadConfig(ConfigFile:config, &Handle:arrayConfig)
|
||||
do
|
||||
{
|
||||
// Create new array to store information for config entry.
|
||||
new Handle:arrayConfigEntry = CreateArray(CONFIG_MAX_LENGTH);
|
||||
new Handle:arrayConfigEntry = CreateArray(blocksize);
|
||||
|
||||
// Push the key name into the config entry's array.
|
||||
decl String:keyname[CONFIG_MAX_LENGTH];
|
||||
@ -884,15 +876,15 @@ public Action:ConfigReloadAllCommand(client, argc)
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts string of "yes" or "no" to a boolean value.
|
||||
* Converts string of "yes/on" or "no/off" to a boolean value.
|
||||
*
|
||||
* @param option "yes" or "no" string to be converted.
|
||||
* @param option "yes/on" or "no/off" string to be converted.
|
||||
* @return True if string is "yes", false otherwise.
|
||||
*/
|
||||
stock bool:ConfigSettingToBool(const String:option[])
|
||||
{
|
||||
// If option is equal to "yes," then return true.
|
||||
if (StrEqual(option, "yes", false))
|
||||
if (StrEqual(option, "yes", false) || StrEqual(option, "on", false))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -904,8 +896,8 @@ stock bool:ConfigSettingToBool(const String:option[])
|
||||
/**
|
||||
* Converts boolean value to "yes" or "no".
|
||||
*
|
||||
* @param bOption True/false value to be converted to "yes"/"no", respectively.
|
||||
* @param option Destination string buffer to store "yes" or "no" in.
|
||||
* @param bOption True/false value to be converted to "yes/on"/"no/off", respectively.
|
||||
* @param option Destination string buffer to store "yes/on" or "no/off" in.
|
||||
* @param maxlen Length of destination string buffer (wont't be more than 4).
|
||||
* @param yesno When true, returns "yes/no", false returns "on/off."
|
||||
*/
|
||||
|
@ -73,6 +73,7 @@ enum CvarsList
|
||||
Handle:CVAR_DAMAGE_BLOCK_FF,
|
||||
Handle:CVAR_DAMAGE_BLOCK_BLAST,
|
||||
Handle:CVAR_DAMAGE_SUICIDE_ZOMBIE,
|
||||
Handle:CVAR_DAMAGE_SUICIDE_MZOMBIE,
|
||||
Handle:CVAR_DAMAGE_SUICIDE_HUMAN,
|
||||
Handle:CVAR_DAMAGE_SUICIDE_CMDS,
|
||||
Handle:CVAR_SAYHOOKS_QUIET,
|
||||
@ -125,7 +126,8 @@ enum CvarsList
|
||||
Handle:CVAR_AMBIENTSOUNDS_LENGTH,
|
||||
Handle:CVAR_AMBIENTSOUNDS_VOLUME,
|
||||
Handle:CVAR_ANTISTICK,
|
||||
Handle:CVAR_ANTISTICK_INTERVAL,
|
||||
Handle:CVAR_ANTISTICK_DEFAULT_WIDTH,
|
||||
Handle:CVAR_ANTISTICK_FILE_PATH,
|
||||
Handle:CVAR_SPAWNPROTECT,
|
||||
Handle:CVAR_SPAWNPROTECT_TIME,
|
||||
Handle:CVAR_SPAWNPROTECT_SPEED,
|
||||
@ -234,7 +236,7 @@ CvarsCreate()
|
||||
g_hCvarsList[CVAR_CLASSES_SPAWN] = CreateConVar("zr_classes_spawn", "0", "Re-display class selection menu every spawn.");
|
||||
g_hCvarsList[CVAR_CLASSES_RANDOM] = CreateConVar("zr_classes_random", "0", "Player is assigned a random class every spawn. [Override: zr_classes_spawn and zr_classes_default_*]");
|
||||
g_hCvarsList[CVAR_CLASSES_DEFAULT_ZOMBIE] = CreateConVar("zr_classes_default_zombie", "random", "Zombie class assigned to players on connect. [\"random\" = Random zombie class | \"\" = Class config default]");
|
||||
g_hCvarsList[CVAR_CLASSES_DEFAULT_M_ZOMB] = CreateConVar("zr_classes_default_mother_zombie", "random", "Zombie class assigned to mother zombies. [\"motherzombies\" = Random mother zombie class | \"random\" = Random regular zombie class | \"disabled\" = Don't change class on mother zombies]");
|
||||
g_hCvarsList[CVAR_CLASSES_DEFAULT_M_ZOMB] = CreateConVar("zr_classes_default_mother_zombie", "motherzombies","Zombie class assigned to mother zombies. [\"motherzombies\" = Random mother zombie class | \"random\" = Random regular zombie class | \"disabled\" = Don't change class on mother zombies]");
|
||||
g_hCvarsList[CVAR_CLASSES_DEFAULT_HUMAN] = CreateConVar("zr_classes_default_human", "random", "Human class assigned to players on connect. [\"random\" = Random human class | \"\" = Class config default]");
|
||||
g_hCvarsList[CVAR_CLASSES_DEFAULT_ADMIN] = CreateConVar("zr_classes_default_admin", "random", "Admin class assigned to admins on connect. [\"random\" = Random admin class | \"\" = Class config default]");
|
||||
|
||||
@ -307,8 +309,9 @@ CvarsCreate()
|
||||
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_ZOMBIE] = CreateConVar("zr_damage_suicide_zombie", "0", "Intercept suicide commands attempted by zombies.");
|
||||
g_hCvarsList[CVAR_DAMAGE_SUICIDE_MZOMBIE] = CreateConVar("zr_damage_suicide_mzombie", "1", "Intercept suicide commands attempted by mother zombies.");
|
||||
g_hCvarsList[CVAR_DAMAGE_SUICIDE_HUMAN] = CreateConVar("zr_damage_suicide_human", "0", "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: \", \"]");
|
||||
|
||||
|
||||
@ -386,7 +389,8 @@ CvarsCreate()
|
||||
// Anti-Stick (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]");
|
||||
g_hCvarsList[CVAR_ANTISTICK_DEFAULT_WIDTH] = CreateConVar("zr_antistick_default_width", "32.0", "The default width of player models, don't touch if you don't know what you're doing. [Dependency: zr_antistick]");
|
||||
g_hCvarsList[CVAR_ANTISTICK_FILE_PATH] = CreateConVar("zr_antistick_file_path", "data/antistick.dat", "File to store antistick model hull data. [Dependency: zr_antistick]");
|
||||
|
||||
// ===========================
|
||||
// Spawn Protect (module)
|
||||
|
@ -48,6 +48,11 @@ new g_iDamageTraceAttackHookID[MAXPLAYERS + 1] = {-1, ...};
|
||||
*/
|
||||
new g_iDamageOnTakeDamageHookID[MAXPLAYERS + 1] = {-1, ...};
|
||||
|
||||
/**
|
||||
* Array to keep track of normal/mother zombies.
|
||||
*/
|
||||
new bool:g_bDamageMotherZombie[MAXPLAYERS + 1];
|
||||
|
||||
/**
|
||||
* Hook commands related to damage here.
|
||||
*/
|
||||
@ -106,6 +111,18 @@ DamageOnClientDisconnect(client)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A client was infected.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @param motherinfect True if the zombie is mother, false if not.
|
||||
*/
|
||||
DamageOnClientInfected(client, bool:motherinfect)
|
||||
{
|
||||
// Update if client is a mother zombie or not.
|
||||
g_bDamageMotherZombie[client] = motherinfect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook: TraceAttack
|
||||
* Called right before the bullet enters a client.
|
||||
@ -153,6 +170,13 @@ public ZRTools_Action:DamageTraceAttack(client, inflictor, attacker, Float:damag
|
||||
|
||||
// Here we know that attacker and client are different teams.
|
||||
|
||||
// If client is a human, then allow damage.
|
||||
if (InfectIsClientHuman(client))
|
||||
{
|
||||
// Allow damage.
|
||||
return ZRTools_Continue;
|
||||
}
|
||||
|
||||
// If damage hitgroups cvar is disabled, then allow damage.
|
||||
new bool:damagehitgroups = GetConVarBool(g_hCvarsList[CVAR_DAMAGE_HITGROUPS]);
|
||||
if (!damagehitgroups)
|
||||
@ -317,18 +341,29 @@ public Action:DamageSuicideIntercept(client, argc)
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
// Get zombie flag on client.
|
||||
new bool:clientzombie = InfectIsClientInfected(client);
|
||||
|
||||
// Get cvar values for suicide interception.
|
||||
new bool:suicidezombie = GetConVarBool(g_hCvarsList[CVAR_DAMAGE_SUICIDE_ZOMBIE]);
|
||||
new bool:suicidezombiemother = GetConVarBool(g_hCvarsList[CVAR_DAMAGE_SUICIDE_MZOMBIE]);
|
||||
new bool:suicidehuman = GetConVarBool(g_hCvarsList[CVAR_DAMAGE_SUICIDE_HUMAN]);
|
||||
|
||||
// Determine whether to block suicide based off of the client's zombie flag and cvar values.
|
||||
new bool:blocksuicide = clientzombie ? suicidezombie : suicidehuman;
|
||||
// Check if client is a zombie.
|
||||
if (InfectIsClientInfected(client))
|
||||
{
|
||||
// If client is a normal zombie, and suicide intercept is disabled for zombies, then let command go.
|
||||
if (!g_bDamageMotherZombie[client] && !suicidezombie)
|
||||
{
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
||||
// If cvar for this team is disabled, then stop.
|
||||
if (!blocksuicide)
|
||||
// If client is a mother zombie, and suicide intercept is disabled for mother zombies, then let command go.
|
||||
if (g_bDamageMotherZombie[client] && !suicidezombiemother)
|
||||
{
|
||||
return Plugin_Continue;
|
||||
}
|
||||
}
|
||||
|
||||
// If client is a human, and suicide intercept is disabled for humans, then let command go.
|
||||
if (InfectIsClientHuman(client) && !suicidehuman)
|
||||
{
|
||||
return Plugin_Continue;
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ DownloadsLoad()
|
||||
ConfigSetConfigPath(File_Downloads, pathdownloads);
|
||||
|
||||
// Load config from file and create array structure.
|
||||
new bool:success = ConfigLoadConfig(File_Downloads, arrayDownloads);
|
||||
new bool:success = ConfigLoadConfig(File_Downloads, arrayDownloads, PLATFORM_MAX_PATH);
|
||||
|
||||
// Unexpected error, stop plugin.
|
||||
if (!success)
|
||||
|
@ -87,7 +87,6 @@ public Action:EventRoundStart(Handle:event, const String:name[], bool:dontBroadc
|
||||
RoundEndOnRoundStart();
|
||||
InfectOnRoundStart();
|
||||
SEffectsOnRoundStart();
|
||||
AntiStickOnRoundStart();
|
||||
ZSpawnOnRoundStart();
|
||||
VolOnRoundStart();
|
||||
|
||||
@ -138,6 +137,7 @@ public Action:EventRoundEnd(Handle:event, const String:name[], bool:dontBroadcas
|
||||
new reason = GetEventInt(event, "reason");
|
||||
|
||||
// Forward event to modules.
|
||||
WeaponsOnRoundEnd();
|
||||
RoundEndOnRoundEnd(reason);
|
||||
InfectOnRoundEnd();
|
||||
SEffectsOnRoundEnd();
|
||||
@ -184,23 +184,13 @@ public Action:EventPlayerSpawn(Handle:event, const String:name[], bool:dontBroad
|
||||
AccountOnClientSpawn(index); // Some modules depend on this to finish first.
|
||||
ClassOnClientSpawn(index);
|
||||
WeaponsOnClientSpawn(index);
|
||||
RoundStartOnClientSpawn(index);
|
||||
SEffectsOnClientSpawn(index);
|
||||
SpawnProtectOnClientSpawn(index);
|
||||
RespawnOnClientSpawn(index);
|
||||
ZTeleOnClientSpawn(index);
|
||||
ZHPOnClientSpawn(index);
|
||||
VolOnPlayerSpawn(index);
|
||||
|
||||
// Get public chat trigger prefix.
|
||||
decl String:publictrigger[4];
|
||||
SayHooksGetPublicChatTrigger(publictrigger, sizeof(publictrigger));
|
||||
|
||||
// If public chat trigger is disabled, then don't print message.
|
||||
if (!StrEqual(publictrigger, "N/A", false))
|
||||
{
|
||||
TranslationPrintToChat(index, "General zmenu reminder", publictrigger, SAYHOOKS_KEYWORD_ZMENU);
|
||||
}
|
||||
|
||||
// Fire post player_spawn event.
|
||||
CreateTimer(0.0, EventPlayerSpawnPost, index);
|
||||
}
|
||||
|
@ -349,6 +349,154 @@ stock Float:HitgroupsGetKnockback(index)
|
||||
return Float:GetArrayCell(arrayHitgroup, _:HITGROUPS_DATA_KNOCKBACK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends list of hitgroups to client.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @return True if sent successfully, false if not.
|
||||
*/
|
||||
bool:HitgroupsMenuHitgroups(client)
|
||||
{
|
||||
// If hitgroups is disabled, then stop.
|
||||
new bool:hitgroups = GetConVarBool(g_hCvarsList[CVAR_HITGROUPS]);
|
||||
if (!hitgroups)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Create menu handle.
|
||||
new Handle:menu_hitgroups = CreateMenu(HitgroupsMenuHitgroupsHandle);
|
||||
|
||||
// Set client as translation target.
|
||||
SetGlobalTransTarget(client);
|
||||
|
||||
SetMenuTitle(menu_hitgroups, "%t\n ", "Hitgroups menu hitgroups title");
|
||||
|
||||
decl String:enableall[32];
|
||||
decl String:headshotsonly[32];
|
||||
|
||||
// Format menu options.
|
||||
Format(enableall, sizeof(enableall), "%t", "Hitgroups menu hitgroups enable all");
|
||||
Format(headshotsonly, sizeof(headshotsonly), "%t\n ", "Hitgroups menu hitgroups headshots only");
|
||||
|
||||
// Add options to menu.
|
||||
AddMenuItem(menu_hitgroups, "Enable All", enableall);
|
||||
AddMenuItem(menu_hitgroups, "Headshots Only", headshotsonly);
|
||||
|
||||
decl String:hitgroupoption[MAX_NAME_LENGTH];
|
||||
decl String:hitgroupcandamage[MAX_NAME_LENGTH];
|
||||
decl String:hitgroupid[4];
|
||||
|
||||
// x = Hitgroup index.
|
||||
new size = GetArraySize(arrayHitgroups);
|
||||
for (new x = 0; x < size; x++)
|
||||
{
|
||||
// Get hitgroup name.
|
||||
HitgroupsGetName(x, hitgroupoption, sizeof(hitgroupoption));
|
||||
IntToString(x, hitgroupid, sizeof(hitgroupid));
|
||||
|
||||
// Convert bool to "On/Off"
|
||||
ConfigBoolToSetting(HitgroupsCanDamage(x), hitgroupcandamage, sizeof(hitgroupcandamage), false);
|
||||
|
||||
// Format "on/off" to the option.
|
||||
Format(hitgroupoption, sizeof(hitgroupoption), "%s: %s", hitgroupoption, hitgroupcandamage);
|
||||
|
||||
// Add option to menu.
|
||||
AddMenuItem(menu_hitgroups, hitgroupid, hitgroupoption);
|
||||
}
|
||||
|
||||
// Create a "Back" button to the main admin menu.
|
||||
SetMenuExitBackButton(menu_hitgroups, true);
|
||||
|
||||
// Send menu.
|
||||
DisplayMenu(menu_hitgroups, client, MENU_TIME_FOREVER);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when client selects option in the infect clients menu, and handles it.
|
||||
* @param menu_weapons_main Handle of the menu being used.
|
||||
* @param action The action done on the menu (see menus.inc, enum MenuAction).
|
||||
* @param client The client index.
|
||||
* @param slot The slot index selected (starting from 0).
|
||||
*/
|
||||
public HitgroupsMenuHitgroupsHandle(Handle:menu_hitgroups, MenuAction:action, client, slot)
|
||||
{
|
||||
// Client selected an option.
|
||||
if (action == MenuAction_Select)
|
||||
{
|
||||
switch(slot)
|
||||
{
|
||||
// Enable all hitgroups.
|
||||
case 0:
|
||||
{
|
||||
// x = Hitgroup index.
|
||||
new size = GetArraySize(arrayHitgroups);
|
||||
for (new x = 0; x < size; x++)
|
||||
{
|
||||
// Enable hitgroup.
|
||||
HitgroupsSetDamage(x, true);
|
||||
}
|
||||
|
||||
// Tell the server that all hitgroups have been enabled.
|
||||
TranslationPrintToChatAll(true, false, "Hitgroups command enable all successful");
|
||||
}
|
||||
// Headshots only.
|
||||
case 1:
|
||||
{
|
||||
// x = Hitgroup index.
|
||||
new size = GetArraySize(arrayHitgroups);
|
||||
for (new x = 0; x < size; x++)
|
||||
{
|
||||
if (HitgroupsGetIndex(x) == HITGROUP_HEAD)
|
||||
{
|
||||
// Enable hitgroup.
|
||||
HitgroupsSetDamage(x, true);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Disable hitgroup.
|
||||
HitgroupsSetDamage(x, false);
|
||||
}
|
||||
|
||||
// Tell the server that headshots only been enabled.
|
||||
TranslationPrintToChatAll(true, false, "Hitgroups command headshots only successful");
|
||||
}
|
||||
default:
|
||||
{
|
||||
// Get selected hitgroup index.
|
||||
decl String:hitgroupid[4];
|
||||
GetMenuItem(menu_hitgroups, slot, hitgroupid, sizeof(hitgroupid));
|
||||
new hitgroup = StringToInt(hitgroupid);
|
||||
|
||||
// Toggle value.
|
||||
new bool:hitgroupcandamage = HitgroupsCanDamage(hitgroup);
|
||||
HitgroupsSetDamage(hitgroup, !hitgroupcandamage);
|
||||
}
|
||||
}
|
||||
|
||||
// Re-send menu.
|
||||
HitgroupsMenuHitgroups(client);
|
||||
}
|
||||
// Client closed the menu.
|
||||
if (action == MenuAction_Cancel)
|
||||
{
|
||||
// Client hit "Back" button.
|
||||
if (slot == MenuCancel_ExitBack)
|
||||
{
|
||||
// Re-open admin menu.
|
||||
ZAdminMenu(client);
|
||||
}
|
||||
}
|
||||
// Client hit "Exit" button.
|
||||
else if (action == MenuAction_End)
|
||||
{
|
||||
CloseHandle(menu_hitgroups);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Command callback (zr_hitgroup)
|
||||
* Toggles or sets if a zombie's hitgroup can be damaged.
|
||||
@ -358,6 +506,14 @@ stock Float:HitgroupsGetKnockback(index)
|
||||
*/
|
||||
public Action:HitgroupsCommand(client, argc)
|
||||
{
|
||||
// If module is disabled, then stop.
|
||||
new bool:hitgroups = GetConVarBool(g_hCvarsList[CVAR_HITGROUPS]);
|
||||
if (!hitgroups)
|
||||
{
|
||||
TranslationReplyToCommand(client, "Feature is disabled");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
// If not enough arguments given, then stop.
|
||||
if (argc < 1)
|
||||
{
|
||||
@ -436,17 +592,20 @@ public Action:HitgroupsCommand(client, argc)
|
||||
*/
|
||||
public Action:HitgroupsEnableAllCommand(client, argc)
|
||||
{
|
||||
new hitgroup;
|
||||
// If module is disabled, then stop.
|
||||
new bool:hitgroups = GetConVarBool(g_hCvarsList[CVAR_HITGROUPS]);
|
||||
if (!hitgroups)
|
||||
{
|
||||
TranslationReplyToCommand(client, "Feature is disabled");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
// x = Hitgroup index.
|
||||
new size = GetArraySize(arrayHitgroups);
|
||||
for (new x = 0; x < size; x++)
|
||||
{
|
||||
// Get CS:S hitgroup index.
|
||||
hitgroup = HitgroupsGetIndex(x);
|
||||
|
||||
// Set that hitgroup index to true for damage.
|
||||
HitgroupsSetDamage(hitgroup, true);
|
||||
HitgroupsSetDamage(x, true);
|
||||
}
|
||||
|
||||
// Tell the server that all hitgroups have been enabled.
|
||||
@ -467,27 +626,30 @@ public Action:HitgroupsEnableAllCommand(client, argc)
|
||||
*/
|
||||
public Action:HitgroupsHeadshotsOnlyCommand(client, argc)
|
||||
{
|
||||
new hitgroup;
|
||||
// If module is disabled, then stop.
|
||||
new bool:hitgroups = GetConVarBool(g_hCvarsList[CVAR_HITGROUPS]);
|
||||
if (!hitgroups)
|
||||
{
|
||||
TranslationReplyToCommand(client, "Feature is disabled");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
// x = Hitgroup index.
|
||||
new size = GetArraySize(arrayHitgroups);
|
||||
for (new x = 0; x < size; x++)
|
||||
{
|
||||
// Get CS:S hitgroup index.
|
||||
hitgroup = HitgroupsGetIndex(x);
|
||||
|
||||
// If this hitgroup is the head, then enable it and stop.
|
||||
if (hitgroup == HITGROUP_HEAD)
|
||||
if (HitgroupsGetIndex(x) == HITGROUP_HEAD)
|
||||
{
|
||||
HitgroupsSetDamage(hitgroup, true);
|
||||
HitgroupsSetDamage(x, true);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Set that hitgroup index to true for damage.
|
||||
HitgroupsSetDamage(hitgroup, false);
|
||||
HitgroupsSetDamage(x, false);
|
||||
}
|
||||
|
||||
// Tell the server that all hitgroups have been enabled.
|
||||
// Tell the server that headshots only been enabled.
|
||||
TranslationPrintToChatAll(true, false, "Hitgroups command headshots only successful");
|
||||
|
||||
// Log action to game events.
|
||||
|
@ -556,47 +556,6 @@ InfectHumanToZombie(client, attacker = -1, bool:motherinfect = false, bool:respa
|
||||
// Mark player as zombie.
|
||||
bZombie[client] = true;
|
||||
|
||||
// Get a list of all client's weapon indexes.
|
||||
new weapons[WeaponsSlot];
|
||||
WeaponsGetClientWeapons(client, weapons);
|
||||
|
||||
// Check if weapons drop is enabled.
|
||||
new bool:weaponsdrop = GetConVarBool(g_hCvarsList[CVAR_INFECT_WEAPONS_DROP]);
|
||||
|
||||
// Loop through array slots and force drop.
|
||||
// x = weapon slot.
|
||||
for (new x = 0; x < WEAPONS_SLOTS_MAX; x++)
|
||||
{
|
||||
// If weapon is invalid, then stop.
|
||||
if (weapons[x] == -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (weaponsdrop)
|
||||
{
|
||||
// If this is the knife slot, then stop.
|
||||
if (WeaponsSlot:x == Slot_Melee)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Force client to drop weapon.
|
||||
WeaponsForceClientDrop(client, weapons[x]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Strip weapon.
|
||||
RemovePlayerItem(client, weapons[x]);
|
||||
}
|
||||
}
|
||||
|
||||
// If client has no knife, give them one.
|
||||
if (GetPlayerWeaponSlot(client, _:Slot_Melee) == -1)
|
||||
{
|
||||
GivePlayerItem(client, "weapon_knife");
|
||||
}
|
||||
|
||||
// Check if consecutive infection protection is enabled.
|
||||
new bool:infectconsecutiveblock = GetConVarBool(g_hCvarsList[CVAR_INFECT_CONSECUTIVE_BLOCK]);
|
||||
|
||||
@ -669,9 +628,52 @@ InfectHumanToZombie(client, attacker = -1, bool:motherinfect = false, bool:respa
|
||||
// Forward event to modules.
|
||||
ClassOnClientInfected(client, motherinfect);
|
||||
RoundEndOnClientInfected();
|
||||
DamageOnClientInfected(client, motherinfect);
|
||||
SEffectsOnClientInfected(client);
|
||||
ZTeleOnClientInfected(client);
|
||||
ZHPOnClientInfected(client);
|
||||
|
||||
// Get a list of all client's weapon indexes.
|
||||
new weapons[WeaponsSlot];
|
||||
WeaponsGetClientWeapons(client, weapons);
|
||||
|
||||
// Check if weapons drop is enabled.
|
||||
new bool:weaponsdrop = GetConVarBool(g_hCvarsList[CVAR_INFECT_WEAPONS_DROP]);
|
||||
|
||||
// This must be after the event forwarding because it fixes a problem caused by changing models in ClassOnClientInfected.
|
||||
// Loop through array slots and force drop.
|
||||
// x = weapon slot.
|
||||
for (new x = 0; x < WEAPONS_SLOTS_MAX; x++)
|
||||
{
|
||||
// If weapon is invalid, then stop.
|
||||
if (weapons[x] == -1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (weaponsdrop)
|
||||
{
|
||||
// If this is the knife slot, then stop.
|
||||
if (WeaponsSlot:x == Slot_Melee)
|
||||
{
|
||||
// Strip knife.
|
||||
RemovePlayerItem(client, weapons[x]);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Force client to drop weapon.
|
||||
WeaponsForceClientDrop(client, weapons[x]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Strip weapon.
|
||||
RemovePlayerItem(client, weapons[x]);
|
||||
}
|
||||
}
|
||||
|
||||
// Give zombie a new knife. (If you leave the old one there will be glitches with the knife positioning)
|
||||
GivePlayerItem(client, "weapon_knife");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -701,6 +703,14 @@ InfectZombieToHuman(client, bool:respawn = false, bool:protect = false)
|
||||
RoundEndOnClientInfected();
|
||||
ZTeleOnClientInfected(client);
|
||||
|
||||
// Give human a new knife. (If you leave the old one there will be glitches with the knife positioning)
|
||||
new knife = GetPlayerWeaponSlot(client, _:Slot_Melee);
|
||||
if (knife != -1)
|
||||
{
|
||||
RemovePlayerItem(client, knife);
|
||||
GivePlayerItem(client, "weapon_knife");
|
||||
}
|
||||
|
||||
// Check if we should respawn the client.
|
||||
if (respawn)
|
||||
{
|
||||
@ -806,7 +816,7 @@ InfectMenuClients(client)
|
||||
|
||||
SetMenuTitle(menu_infect_clients, "%t\n ", "Infect menu clients title");
|
||||
|
||||
decl String:clientoption[MAX_NAME_LENGTH];
|
||||
decl String:clientoption[64];
|
||||
decl String:clientuserid[8];
|
||||
|
||||
// x = Client index.
|
||||
@ -861,11 +871,8 @@ public InfectMenuClientsHandle(Handle:menu_infect_clients, MenuAction:action, cl
|
||||
// Client selected an option.
|
||||
if (action == MenuAction_Select)
|
||||
{
|
||||
decl String:clientuserid[8];
|
||||
GetMenuItem(menu_infect_clients, slot, clientuserid, sizeof(clientuserid));
|
||||
|
||||
// Get the targetted client through their userid which was set into the menu slot's info param.
|
||||
new target = GetClientOfUserId(StringToInt(clientuserid));
|
||||
// Get selected client index.
|
||||
new target = MenuGetClientIndex(menu_infect_clients, slot);
|
||||
|
||||
// If target has left the server, then stop.
|
||||
if (!target)
|
||||
@ -899,7 +906,7 @@ public InfectMenuClientsHandle(Handle:menu_infect_clients, MenuAction:action, cl
|
||||
if (slot == MenuCancel_ExitBack)
|
||||
{
|
||||
// Re-open admin menu.
|
||||
ZRAdminMenu(client);
|
||||
ZAdminMenu(client);
|
||||
}
|
||||
}
|
||||
// Client hit "Exit" button.
|
||||
|
@ -47,7 +47,7 @@ JumpBoostOnClientJumpPost(client)
|
||||
// Get client's current velocity.
|
||||
ToolsClientVelocity(client, vecVelocity, false);
|
||||
|
||||
// If they have exceeded the max jump speed, then stop.
|
||||
// Only apply horizontal multiplier if it's not a bhop.
|
||||
if (!JumpBoostIsBHop(vecVelocity))
|
||||
{
|
||||
// Apply horizontal multipliers to jump vector.
|
||||
|
@ -78,7 +78,7 @@ KnockbackOnClientHurt(client, attacker, const String:weapon[], hitgroup, dmg_hea
|
||||
|
||||
// Get attackers eye angles.
|
||||
new Float:attackerang[3];
|
||||
KnockbackGetClientEyeAngles(attacker, attackerang);
|
||||
GetClientEyeAngles(attacker, attackerang);
|
||||
|
||||
// Calculate knockback end-vector.
|
||||
TR_TraceRayFilter(attackerloc, attackerang, MASK_ALL, RayType_Infinite, KnockbackTRFilter);
|
||||
@ -199,14 +199,3 @@ KnockbackFindExplodingGrenade(Float:heLoc[3])
|
||||
// Didn't find the grenade.
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get client's eye angles.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @param vecAngles The angle vector of the client's eyes.
|
||||
*/
|
||||
KnockbackGetClientEyeAngles(client, Float:vecAngles[3])
|
||||
{
|
||||
SDKCall(g_hToolsEyeAngles, client, vecAngles);
|
||||
}
|
||||
|
@ -70,7 +70,7 @@ enum LogModules
|
||||
bool:LogModule_Invalid = 0, /** Used as return value when an error occoured.*/
|
||||
|
||||
bool:LogModule_Account,
|
||||
bool:LogModule_Antistick,
|
||||
bool:LogModule_AntiStick,
|
||||
bool:LogModule_Config,
|
||||
bool:LogModule_Cvars,
|
||||
bool:LogModule_Damage,
|
||||
@ -84,7 +84,9 @@ enum LogModules
|
||||
bool:LogModule_Tools,
|
||||
bool:LogModule_Volfeatures,
|
||||
bool:LogModule_Weapons,
|
||||
bool:LogModule_Weaponrestrict
|
||||
bool:LogModule_Weaponrestrict,
|
||||
bool:LogModule_ZSpawn,
|
||||
bool:LogModule_ZTele,
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -59,7 +59,7 @@ LogGetModuleNameString(String:buffer[], maxlen, LogModules:module, bool:shortNam
|
||||
{
|
||||
return shortName ? strcopy(buffer, maxlen, "account") : strcopy(buffer, maxlen, "Account");
|
||||
}
|
||||
case LogModule_Antistick:
|
||||
case LogModule_AntiStick:
|
||||
{
|
||||
return shortName ? strcopy(buffer, maxlen, "antistick") : strcopy(buffer, maxlen, "Anti-Stick");
|
||||
}
|
||||
@ -119,6 +119,14 @@ LogGetModuleNameString(String:buffer[], maxlen, LogModules:module, bool:shortNam
|
||||
{
|
||||
return shortName ? strcopy(buffer, maxlen, "weaponrestrict") : strcopy(buffer, maxlen, "Weapon Restrictions");
|
||||
}
|
||||
case LogModule_ZSpawn:
|
||||
{
|
||||
return shortName ? strcopy(buffer, maxlen, "zspawn") : strcopy(buffer, maxlen, "ZSpawn");
|
||||
}
|
||||
case LogModule_ZTele:
|
||||
{
|
||||
return shortName ? strcopy(buffer, maxlen, "ztele") : strcopy(buffer, maxlen, "ZTele");
|
||||
}
|
||||
}
|
||||
|
||||
// Module mismatch.
|
||||
@ -140,7 +148,7 @@ LogModules:LogGetModule(const String:moduleName[])
|
||||
}
|
||||
else if (StrEqual(moduleName, "antistick", false))
|
||||
{
|
||||
return LogModule_Antistick;
|
||||
return LogModule_AntiStick;
|
||||
}
|
||||
else if (StrEqual(moduleName, "config", false))
|
||||
{
|
||||
@ -198,6 +206,14 @@ LogModules:LogGetModule(const String:moduleName[])
|
||||
{
|
||||
return LogModule_Weaponrestrict;
|
||||
}
|
||||
else if (StrEqual(moduleName, "zspawn", false))
|
||||
{
|
||||
return LogModule_ZSpawn;
|
||||
}
|
||||
else if (StrEqual(moduleName, "ztele", false))
|
||||
{
|
||||
return LogModule_ZTele;
|
||||
}
|
||||
|
||||
// No match.
|
||||
return LogModule_Invalid;
|
||||
|
@ -90,10 +90,10 @@ ZMenuMain(client)
|
||||
decl String:zmarket[256];
|
||||
|
||||
// Translate each line into client's language.
|
||||
Format(zadmin, sizeof(zadmin), "%t", "Menu main zadmin", SAYHOOKS_KEYWORD_ZMENU);
|
||||
Format(zclass, sizeof(zclass), "%t", "Menu main zclass", SAYHOOKS_KEYWORD_ZADMIN);
|
||||
Format(zadmin, sizeof(zadmin), "%t", "Menu main zadmin", SAYHOOKS_KEYWORD_ZADMIN);
|
||||
Format(zclass, sizeof(zclass), "%t", "Menu main zclass", SAYHOOKS_KEYWORD_ZCLASS);
|
||||
Format(zcookies, sizeof(zcookies), "%t", "Menu main zcookies", SAYHOOKS_KEYWORD_ZCOOKIES);
|
||||
Format(zspawn, sizeof(zspawn), "%t", "Menu main zspawn", SAYHOOKS_KEYWORD_ZCLASS);
|
||||
Format(zspawn, sizeof(zspawn), "%t", "Menu main zspawn", SAYHOOKS_KEYWORD_ZSPAWN);
|
||||
Format(ztele, sizeof(ztele), "%t", "Menu main ztele", SAYHOOKS_KEYWORD_ZTELE);
|
||||
Format(zhp, sizeof(zhp), "%t", "Menu main zhp", SAYHOOKS_KEYWORD_ZHP);
|
||||
Format(zmarket, sizeof(zmarket), "%t", "Menu main zmarket", SAYHOOKS_KEYWORD_ZMARKET);
|
||||
@ -138,7 +138,7 @@ public ZMenuMainHandle(Handle:menu, MenuAction:action, client, slot)
|
||||
case 0:
|
||||
{
|
||||
// Copy return to resend variable.
|
||||
resend = !ZRAdminMenu(client);
|
||||
resend = !ZAdminMenu(client);
|
||||
}
|
||||
// Select ZClass.
|
||||
case 1:
|
||||
@ -197,12 +197,78 @@ public ZMenuMainHandle(Handle:menu, MenuAction:action, client, slot)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a list of all clients to a client, different handlers can be used for this, as well as title.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @param handler The menu handler.
|
||||
* @param any Title is a translations phrase.
|
||||
*/
|
||||
stock MenuClientList(client, MenuHandler:handler, any:...)
|
||||
{
|
||||
// Create menu handle.
|
||||
new Handle:menu_clients = CreateMenu(handler);
|
||||
|
||||
// Set client as translation target.
|
||||
SetGlobalTransTarget(client);
|
||||
|
||||
// Translate phrase.
|
||||
decl String:translation[TRANSLATION_MAX_LENGTH_CHAT];
|
||||
VFormat(translation, sizeof(translation), "%t", 3);
|
||||
|
||||
// Set menu title to the translated phrase.
|
||||
SetMenuTitle(menu_clients, translation);
|
||||
|
||||
decl String:clientoption[MAX_NAME_LENGTH];
|
||||
decl String:clientuserid[8];
|
||||
|
||||
// x = Client index.
|
||||
for (new x = 1; x <= MaxClients; x++)
|
||||
{
|
||||
// If client isn't in-game, then stop.
|
||||
if (!IsClientInGame(x))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Get client info.
|
||||
GetClientName(x, clientoption, sizeof(clientoption));
|
||||
IntToString(GetClientUserId(x), clientuserid, sizeof(clientuserid));
|
||||
|
||||
// Add option to menu.
|
||||
AddMenuItem(menu_clients, clientuserid, clientoption);
|
||||
}
|
||||
|
||||
// Create a "Back" button to the main admin menu.
|
||||
SetMenuExitBackButton(menu_clients, true);
|
||||
|
||||
// Send menu.
|
||||
DisplayMenu(menu_clients, client, MENU_TIME_FOREVER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the client index of the selected client in the menu.
|
||||
*
|
||||
* @param menu The menu handle.
|
||||
* @param slot The menu slot that was selected.
|
||||
* @return The client index, 0 if the selected client is no longer in the server.
|
||||
*/
|
||||
stock MenuGetClientIndex(Handle:menu, slot)
|
||||
{
|
||||
// Get menu slot's information.
|
||||
decl String:clientuserid[8];
|
||||
GetMenuItem(menu, slot, clientuserid, sizeof(clientuserid));
|
||||
|
||||
// Return the targetted client through their userid which was set into the menu slot's info param.
|
||||
return GetClientOfUserId(StringToInt(clientuserid));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return itemdraw flag for SM menus.
|
||||
*
|
||||
* @param condition If this is true, item will be drawn normally.
|
||||
*/
|
||||
MenuGetItemDraw(bool:condition)
|
||||
stock MenuGetItemDraw(bool:condition)
|
||||
{
|
||||
return condition ? ITEMDRAW_DEFAULT : ITEMDRAW_DISABLED;
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ ModelsLoad()
|
||||
ConfigSetConfigPath(File_Models, pathmodels);
|
||||
|
||||
// Load config from file and create array structure.
|
||||
new bool:success = ConfigLoadConfig(File_Models, arrayModels);
|
||||
new bool:success = ConfigLoadConfig(File_Models, arrayModels, PLATFORM_MAX_PATH);
|
||||
|
||||
// Unexpected error, stop plugin.
|
||||
if (!success)
|
||||
@ -72,7 +72,8 @@ ModelsLoad()
|
||||
}
|
||||
|
||||
new modelcount;
|
||||
new modelvalidcount;
|
||||
new modelpublicvalidcount;
|
||||
new modelnonpublicvalidcount;
|
||||
new modelfilecount;
|
||||
|
||||
decl String:modelbase[PLATFORM_MAX_PATH];
|
||||
@ -91,9 +92,9 @@ ModelsLoad()
|
||||
// x = model array index.
|
||||
for (new x = 0; x < models; x++)
|
||||
{
|
||||
// Get base model path (rawline in models.txt)
|
||||
GetArrayString(arrayModels, x, modelbase, sizeof(modelbase));
|
||||
|
||||
// Get base model path, excluding the public/non-public setting.
|
||||
ModelReturnPath(x, modelbase, sizeof(modelbase));
|
||||
PrintToServer("PATH BASE [%s]", modelbase);
|
||||
// Explode path into pieces. (separated by "/")
|
||||
new strings = ExplodeString(modelbase, "/", baseexploded, MODELS_PATH_MAX_DEPTH, MODELS_PATH_DIR_MAX_LENGTH);
|
||||
|
||||
@ -147,10 +148,18 @@ ModelsLoad()
|
||||
modelfilecount++;
|
||||
}
|
||||
|
||||
// Increment modelvalidcount if model files are valid.
|
||||
// Increment variable if model files are valid.
|
||||
if (modelfilecount)
|
||||
{
|
||||
modelvalidcount++;
|
||||
// Increment proper variable.
|
||||
if (ModelIsPublic(x))
|
||||
{
|
||||
modelpublicvalidcount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
modelnonpublicvalidcount++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -169,12 +178,12 @@ ModelsLoad()
|
||||
}
|
||||
|
||||
// Log model validation info.
|
||||
LogEvent(false, LogType_Normal, LOG_CORE_EVENTS, LogModule_Models, "Config Validation", "Total: %d | Successful: %d | Unsuccessful: %d", modelcount, modelvalidcount, modelcount - modelvalidcount);
|
||||
LogEvent(false, LogType_Normal, LOG_CORE_EVENTS, LogModule_Models, "Config Validation", "Total: %d | Successful Public: %d | Successful Non-Public: %d | Unsuccessful: %d", modelcount, modelpublicvalidcount, modelnonpublicvalidcount, modelcount - (modelpublicvalidcount + modelnonpublicvalidcount));
|
||||
|
||||
// If none of the model paths are valid, then log and fail.
|
||||
if (!modelvalidcount)
|
||||
if (!modelpublicvalidcount)
|
||||
{
|
||||
LogEvent(false, LogType_Fatal, LOG_CORE_EVENTS, LogModule_Models, "Config Validation", "No usable model paths in %s", pathmodels);
|
||||
LogEvent(false, LogType_Fatal, LOG_CORE_EVENTS, LogModule_Models, "Config Validation", "No usable (public) model paths in %s", pathmodels);
|
||||
}
|
||||
|
||||
// Set config data.
|
||||
@ -191,3 +200,118 @@ public ModelsOnConfigReload(ConfigFile:config)
|
||||
// Reload models config.
|
||||
ModelsLoad();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a model is public.
|
||||
*
|
||||
* @param modelindex The array index of the model to check.
|
||||
* @return True if public, false if not.
|
||||
*/
|
||||
stock bool:ModelIsPublic(modelindex)
|
||||
{
|
||||
// Get the entire model string to parse for what we need.
|
||||
decl String:modelsetting[PLATFORM_MAX_PATH + 16];
|
||||
GetArrayString(arrayModels, modelindex, modelsetting, sizeof(modelsetting));
|
||||
|
||||
// We define this to use as little memory as possible, because the value won't be used.
|
||||
decl String:modelpath[1];
|
||||
decl String:strpublic[32];
|
||||
|
||||
if (StrContains(modelsetting, ";") > -1)
|
||||
{
|
||||
// Get string index of where the public setting starts.
|
||||
new strindex = SplitString(modelsetting, ";", modelpath, sizeof(modelpath));
|
||||
|
||||
// Copy setting to new string
|
||||
strcopy(strpublic, sizeof(strpublic), modelsetting[strindex]);
|
||||
|
||||
// Trim the whitespace.
|
||||
TrimString(strpublic);
|
||||
|
||||
// If public, return true, non-public returns false.
|
||||
return StrEqual(strpublic, "public", false);
|
||||
}
|
||||
|
||||
// If nothing is specified, assume public.
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path of a given model index.
|
||||
*
|
||||
* @param modelindex The array index of the model.
|
||||
* @param modelpath The output string of the model path.
|
||||
* @param maxlen The maximum length of the output string.
|
||||
*/
|
||||
stock ModelReturnPath(modelindex, String:modelpath[], maxlen)
|
||||
{
|
||||
// Get the entire model string to parse for what we need.
|
||||
decl String:modelsetting[PLATFORM_MAX_PATH + 16];
|
||||
GetArrayString(arrayModels, modelindex, modelsetting, sizeof(modelsetting));
|
||||
|
||||
// Copy to path before split just in case the string has no ";"
|
||||
strcopy(modelpath, maxlen, modelsetting);
|
||||
if (StrContains(modelsetting, ";") > -1)
|
||||
{
|
||||
SplitString(modelsetting, ";", modelpath, maxlen);
|
||||
}
|
||||
|
||||
// Trim whitespace.
|
||||
TrimString(modelpath);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random model index in arrayModels, allows you to specify a filter.
|
||||
*
|
||||
* @param modelpath The output string of the model path.
|
||||
* @param maxlen The maximum length of the output string.
|
||||
* @param all True to choose any of the models in the file, false to use 'publicmodels' param.
|
||||
* @param publicmodels True to find a random public model, false to find non-public.
|
||||
*/
|
||||
stock ModelsGetRandomModelIndex(String:modelpath[], maxlen, bool:all = true, bool:publicmodels = true)
|
||||
{
|
||||
new modelindex = -1;
|
||||
|
||||
// Return any random model.
|
||||
if (all)
|
||||
{
|
||||
// Get random model index and return the string in it.
|
||||
modelindex = GetRandomInt(0, GetArraySize(arrayModels) - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
new Handle:modelsarray = CreateArray(PLATFORM_MAX_PATH);
|
||||
decl String:modelsetting[PLATFORM_MAX_PATH];
|
||||
|
||||
// x = Array index.
|
||||
new size = GetArraySize(arrayModels);
|
||||
for (new x = 0; x < size; x++)
|
||||
{
|
||||
if (publicmodels == ModelIsPublic(x))
|
||||
{
|
||||
// Transfer model to temp array.
|
||||
GetArrayString(arrayModels, x, modelsetting, sizeof(modelsetting));
|
||||
PushArrayString(modelsarray, modelsetting);
|
||||
}
|
||||
}
|
||||
|
||||
// y = Array index.
|
||||
size = GetArraySize(modelsarray);
|
||||
|
||||
// If there are no models then copy a blank string to the output.
|
||||
if (size == 0)
|
||||
{
|
||||
strcopy(modelpath, maxlen, "");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get random model index from the temp list, and return the string in it.
|
||||
modelindex = GetRandomInt(0, GetArraySize(modelsarray) - 1);
|
||||
|
||||
// Destroy the handle.
|
||||
CloseHandle(modelsarray);
|
||||
}
|
||||
|
||||
// Get the path to the selected model.
|
||||
ModelReturnPath(modelindex, modelpath, maxlen);
|
||||
}
|
@ -39,6 +39,12 @@
|
||||
*/
|
||||
NapalmOnClientHurt(client, attacker, const String:weapon[])
|
||||
{
|
||||
// If there's no attacker, then stop.
|
||||
if (!attacker)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If player isn't a zombie, then stop.
|
||||
if (!InfectIsClientInfected(client))
|
||||
{
|
||||
@ -107,8 +113,8 @@ NapalmOnWeaponFire(client, const String:weapon[])
|
||||
return;
|
||||
}
|
||||
|
||||
// Wait .1 seconds.
|
||||
CreateTimer(0.1, NapalmIgniteGrenade);
|
||||
// Wait .15 seconds.
|
||||
CreateTimer(0.15, NapalmIgniteGrenade);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -93,8 +93,7 @@ bool:ClassApplyModel(client, classindex, cachetype = ZR_CLASS_CACHE_PLAYER)
|
||||
if (strcmp(modelpath, "random", false) == 0)
|
||||
{
|
||||
// TODO: Make a function that gets a random model from the specified team.
|
||||
new randmodel = GetRandomInt(0, GetArraySize(arrayModels) - 1);
|
||||
GetArrayString(arrayModels, randmodel, modelpath, sizeof(modelpath));
|
||||
ModelsGetRandomModelIndex(modelpath, sizeof(modelpath), false, true);
|
||||
Format(modelpath, sizeof(modelpath), "%s.mdl", modelpath);
|
||||
}
|
||||
|
||||
@ -211,8 +210,8 @@ bool:ClassApplyNightVision(client, classindex, cachetype = ZR_CLASS_CACHE_PLAYER
|
||||
nvgs = ClassGetNvgs(classindex, cachetype);
|
||||
}
|
||||
|
||||
ToolsClientNightVision(client, nvgs);
|
||||
ToolsClientNightVision(client, nvgs, false);
|
||||
ToolsSetClientNightVision(client, nvgs);
|
||||
ToolsSetClientNightVision(client, nvgs, false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -93,6 +93,12 @@ ClassOnClientSpawn(client)
|
||||
GetClientModel(client, originalmodel, sizeof(originalmodel));
|
||||
strcopy(ClassOriginalPlayerModel[client], PLATFORM_MAX_PATH, originalmodel);
|
||||
|
||||
// Exclude special class flags like mother zombies and admin classes.
|
||||
new denyflags = ZR_CLASS_SPECIALFLAGS;
|
||||
|
||||
// Allow admin classes if admin.
|
||||
denyflags -= ZRIsClientAdmin(client) ? ZR_CLASS_FLAG_ADMIN_ONLY : 0;
|
||||
|
||||
// Get random class setting.
|
||||
new bool:randomclass = GetConVarBool(g_hCvarsList[CVAR_CLASSES_RANDOM]);
|
||||
|
||||
@ -101,15 +107,15 @@ ClassOnClientSpawn(client)
|
||||
if (randomclass || StrEqual(steamid, "BOT"))
|
||||
{
|
||||
// Get random classes for each type.
|
||||
new randomzombie = ClassGetRandomClass(ZR_CLASS_TEAM_ZOMBIES);
|
||||
new randomhuman = ClassGetRandomClass(ZR_CLASS_TEAM_HUMANS);
|
||||
new randomzombie = ClassGetRandomClass(ZR_CLASS_TEAM_ZOMBIES, _, _, denyflags);
|
||||
new randomhuman = ClassGetRandomClass(ZR_CLASS_TEAM_HUMANS, _, _, denyflags);
|
||||
|
||||
// Mark zombie class as selected.
|
||||
// Save selected zombie class index.
|
||||
ClassSelected[client][ZR_CLASS_TEAM_ZOMBIES] = randomzombie;
|
||||
ClassGetName(randomzombie, classname, sizeof(classname), ZR_CLASS_TEAM_ZOMBIES);
|
||||
TranslationPrintToChat(client, "Classes random assignment", classname);
|
||||
|
||||
// Mark human class as selected.
|
||||
// Save selected human class index.
|
||||
ClassSelected[client][ZR_CLASS_TEAM_HUMANS] = randomhuman;
|
||||
ClassGetName(randomhuman, classname, sizeof(classname), ZR_CLASS_TEAM_HUMANS);
|
||||
TranslationPrintToChat(client, "Classes random assignment", classname);
|
||||
@ -193,11 +199,29 @@ ClassOnClientInfected(client, bool:motherzombie = false)
|
||||
{
|
||||
// Get random regular zombie class. Remove admin flag if admin.
|
||||
motherindex = ClassGetRandomClass(ZR_CLASS_TEAM_ZOMBIES, _, _, ZR_CLASS_SPECIALFLAGS - isadmin);
|
||||
|
||||
// Validate index. Do not change class if it's invalid.
|
||||
if (ClassValidateIndex(motherindex))
|
||||
{
|
||||
// Change class.
|
||||
classindex = motherindex;
|
||||
}
|
||||
}
|
||||
else if (StrEqual(motherzombiesetting, "motherzombies", false))
|
||||
{
|
||||
// Get random mother zombie class.
|
||||
motherindex = ClassGetRandomClass(ZR_CLASS_TEAM_ZOMBIES, _, ZR_CLASS_FLAG_MOTHER_ZOMBIE, isadmin);
|
||||
// Get random mother zombie class. Include admin classes if admin.
|
||||
motherindex = ClassGetRandomClass(ZR_CLASS_TEAM_ZOMBIES, _, ZR_CLASS_FLAG_MOTHER_ZOMBIE + isadmin, ZR_CLASS_FLAG_ADMIN_ONLY - isadmin);
|
||||
|
||||
// Validate index. Do not change class if it's invalid.
|
||||
if (ClassValidateIndex(motherindex))
|
||||
{
|
||||
// This is a mother zombie class. Reset mother zombie setting so
|
||||
// class skills aren't improved.
|
||||
motherzombie = false;
|
||||
|
||||
// Change class.
|
||||
classindex = motherindex;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -384,7 +384,7 @@ public ClassTeamSelectHandle(Handle:menu, MenuAction:action, client, slot)
|
||||
{
|
||||
if (slot == MenuCancel_ExitBack)
|
||||
{
|
||||
ZRAdminMenu(client);
|
||||
ZAdminMenu(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -73,12 +73,8 @@ ClassOverlayOnCommandsHook()
|
||||
*/
|
||||
ClassOverlayOnCookiesCreate()
|
||||
{
|
||||
// If cookie doesn't already exist, then create it.
|
||||
g_hOverlayEnabledCookie = FindClientCookie(CLASSOVERLAY_COOKIE_ENABLED);
|
||||
if (g_hOverlayEnabledCookie == INVALID_HANDLE)
|
||||
{
|
||||
g_hOverlayEnabledCookie = RegClientCookie(CLASSOVERLAY_COOKIE_ENABLED, "The toggle state of the class overlay.", CookieAccess_Public);
|
||||
}
|
||||
// Create overlay cookie.
|
||||
g_hOverlayEnabledCookie = RegClientCookie(CLASSOVERLAY_COOKIE_ENABLED, "The toggle state of the class overlay.", CookieAccess_Protected);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -141,7 +137,7 @@ ClassOverlayInitialize(client, const String:overlay[])
|
||||
decl String:togglecmds[CLASSOVERLAY_TOGGLE_MAX_CMDS * CLASSOVERLAY_TOGGLE_MAX_LENGTH];
|
||||
GetConVarString(g_hCvarsList[CVAR_CLASSES_OVERLAY_TOGGLECMDS], togglecmds, sizeof(togglecmds));
|
||||
|
||||
TranslationPrintHUDText(client, "Classes overlay toggle", togglecmds);
|
||||
TranslationPrintHintText(client, "Classes overlay toggle", togglecmds);
|
||||
}
|
||||
|
||||
// Display class overlays.
|
||||
|
@ -166,9 +166,9 @@
|
||||
#define ZR_CLASS_SPEED_MAX 2000.0
|
||||
#define ZR_CLASS_KNOCKBACK_MIN -30.0
|
||||
#define ZR_CLASS_KNOCKBACK_MAX 30.0
|
||||
#define ZR_CLASS_JUMP_HEIGHT_MIN -500.0
|
||||
#define ZR_CLASS_JUMP_HEIGHT_MAX 500.0
|
||||
#define ZR_CLASS_JUMP_DISTANCE_MIN -5.0
|
||||
#define ZR_CLASS_JUMP_HEIGHT_MIN 0.0
|
||||
#define ZR_CLASS_JUMP_HEIGHT_MAX 5.0
|
||||
#define ZR_CLASS_JUMP_DISTANCE_MIN 0.0
|
||||
#define ZR_CLASS_JUMP_DISTANCE_MAX 5.0
|
||||
/**
|
||||
* @endsection
|
||||
@ -488,7 +488,7 @@ ClassLoad(bool:keepMultipliers = false)
|
||||
ClassData[ClassCount][class_health] = KvGetNum(kvClassData, "health", ZR_CLASS_DEFAULT_HEALTH);
|
||||
ClassData[ClassCount][class_health_regen_interval] = KvGetFloat(kvClassData, "health_regen_interval", ZR_CLASS_DEFAULT_HEALTH_REGEN_INTERVAL);
|
||||
ClassData[ClassCount][class_health_regen_amount] = KvGetNum(kvClassData, "health_regen_amount", ZR_CLASS_DEFAULT_HEALTH_REGEN_AMOUNT);
|
||||
ClassData[ClassCount][class_health_infect_gain] = KvGetNum(kvClassData, "health_infect_bonus", ZR_CLASS_DEFAULT_HEALTH_INFECT_GAIN);
|
||||
ClassData[ClassCount][class_health_infect_gain] = KvGetNum(kvClassData, "health_infect_gain", ZR_CLASS_DEFAULT_HEALTH_INFECT_GAIN);
|
||||
ClassData[ClassCount][class_kill_bonus] = KvGetNum(kvClassData, "kill_bonus", ZR_CLASS_DEFAULT_KILL_BONUS);
|
||||
|
||||
ClassData[ClassCount][class_speed] = KvGetFloat(kvClassData, "speed", ZR_CLASS_DEFAULT_SPEED);
|
||||
|
@ -162,6 +162,26 @@ RoundEndOnRoundEnd(reason)
|
||||
// Get outcome of the round.
|
||||
new RoundEndOutcome:outcome = RoundEndReasonToOutcome(reason);
|
||||
|
||||
// Update team scores.
|
||||
new teamscore;
|
||||
switch(outcome)
|
||||
{
|
||||
// Zombies won the round.
|
||||
case ZombiesWin:
|
||||
{
|
||||
// Increment T score.
|
||||
teamscore = GetTeamScore(CS_TEAM_T);
|
||||
SetTeamScore(CS_TEAM_T, ++teamscore);
|
||||
}
|
||||
// Humans won the round.
|
||||
case HumansWin:
|
||||
{
|
||||
// Increment CT score.
|
||||
teamscore = GetTeamScore(CS_TEAM_CT);
|
||||
SetTeamScore(CS_TEAM_CT, ++teamscore);
|
||||
}
|
||||
}
|
||||
|
||||
// Display the overlay to all clients.
|
||||
RoundEndOverlayStart(outcome);
|
||||
|
||||
|
@ -30,6 +30,33 @@
|
||||
*/
|
||||
#define ROUNDSTART_OBJECTIVE_ENTITIES "func_bomb_target|func_hostage_rescue|c4|hostage_entity"
|
||||
|
||||
/**
|
||||
* Client is spawning into the game.
|
||||
*
|
||||
* @param client The client index.
|
||||
*/
|
||||
RoundStartOnClientSpawn(client)
|
||||
{
|
||||
// If client hasn't spawned yet, then stop.
|
||||
if (!IsPlayerAlive(client))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Get public chat trigger prefix.
|
||||
decl String:publictrigger[4];
|
||||
SayHooksGetPublicChatTrigger(publictrigger, sizeof(publictrigger));
|
||||
|
||||
// If public chat trigger is disabled, then don't print message.
|
||||
if (StrEqual(publictrigger, "N/A", false))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Print to client, how to access ZMenu.
|
||||
TranslationPrintToChat(client, "General zmenu reminder", publictrigger, SAYHOOKS_KEYWORD_ZMENU);
|
||||
}
|
||||
|
||||
/**
|
||||
* The round is starting.
|
||||
*/
|
||||
|
@ -90,6 +90,9 @@ SayHooksGetPublicChatTrigger(String:trigger[], maxlen)
|
||||
{
|
||||
strcopy(trigger, maxlen, "N/A");
|
||||
}
|
||||
|
||||
// Close the handle.
|
||||
CloseHandle(kvCore);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -126,4 +129,7 @@ SayHooksGetSilentChatTrigger(String:trigger[], maxlen)
|
||||
{
|
||||
strcopy(trigger, maxlen, "N/A");
|
||||
}
|
||||
|
||||
// Close the handle.
|
||||
CloseHandle(kvCore);
|
||||
}
|
@ -47,14 +47,17 @@ SpawnProtectClientInit(client)
|
||||
}
|
||||
|
||||
/**
|
||||
* Client is spawning into the game.
|
||||
* Client is spawning into the game. *Post
|
||||
*
|
||||
* @param client The client index.
|
||||
*/
|
||||
SpawnProtectOnClientSpawn(client)
|
||||
SpawnProtectOnClientSpawnPost(client)
|
||||
{
|
||||
// Disable spawn protection on client.
|
||||
bInfectImmune[client][INFECT_TYPE_NORMAL] = false;
|
||||
// If client is dead, then they are joining the server, not spawning.
|
||||
if (!IsPlayerAlive(client))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If timer is currently running, kill it.
|
||||
if (tSpawnProtect[client] != INVALID_HANDLE)
|
||||
@ -64,15 +67,7 @@ SpawnProtectOnClientSpawn(client)
|
||||
|
||||
// Reset timer handle.
|
||||
tSpawnProtect[client] = INVALID_HANDLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Client is spawning into the game. *Post
|
||||
*
|
||||
* @param client The client index.
|
||||
*/
|
||||
SpawnProtectOnClientSpawnPost(client)
|
||||
{
|
||||
// If protect cvar is disabled, then stop.
|
||||
new bool:protect = GetConVarBool(g_hCvarsList[CVAR_SPAWNPROTECT]);
|
||||
if (!protect)
|
||||
@ -80,6 +75,9 @@ SpawnProtectOnClientSpawnPost(client)
|
||||
return;
|
||||
}
|
||||
|
||||
// Disable spawn protection on client.
|
||||
bInfectImmune[client][INFECT_TYPE_NORMAL] = false;
|
||||
|
||||
// Start spawn protection.
|
||||
SpawnProtectStart(client);
|
||||
}
|
||||
@ -145,7 +143,7 @@ SpawnProtectStart(client)
|
||||
TranslationPrintToChat(client, "Spawn protection begin", protect_time);
|
||||
|
||||
// Send time left in a hud message.
|
||||
TranslationPrintHUDText(client, "Spawn Protect", pSpawnProtectTime[client]);
|
||||
TranslationPrintHintText(client, "Spawn Protect", pSpawnProtectTime[client]);
|
||||
|
||||
// Start repeating timer.
|
||||
tSpawnProtect[client] = CreateTimer(1.0, SpawnProtectTimer, client, TIMER_FLAG_NO_MAPCHANGE|TIMER_REPEAT);
|
||||
@ -179,7 +177,7 @@ public Action:SpawnProtectTimer(Handle:timer, any:client)
|
||||
pSpawnProtectTime[client]--;
|
||||
|
||||
// Print time left to client.
|
||||
TranslationPrintHUDText(client, "Spawn Protect", pSpawnProtectTime[client]);
|
||||
TranslationPrintHintText(client, "Spawn Protect", pSpawnProtectTime[client]);
|
||||
|
||||
// Time has expired.
|
||||
if (pSpawnProtectTime[client] <= 0)
|
||||
@ -188,7 +186,7 @@ public Action:SpawnProtectTimer(Handle:timer, any:client)
|
||||
bInfectImmune[client][INFECT_TYPE_NORMAL] = false;
|
||||
|
||||
// Tell client spawn protection is over.
|
||||
TranslationPrintHUDText(client, "Spawn protection end");
|
||||
TranslationPrintHintText(client, "Spawn protection end");
|
||||
|
||||
// Fix attributes.
|
||||
ToolsSetClientAlpha(client, ClassGetAlphaInitial(client));
|
||||
|
@ -42,7 +42,6 @@ new g_iToolsDefaultFOV;
|
||||
* Initialize global SDKTools handles.
|
||||
*/
|
||||
new Handle:g_hToolsGameConfig = INVALID_HANDLE;
|
||||
new Handle:g_hToolsEyeAngles = INVALID_HANDLE;
|
||||
new Handle:g_hToolsTerminateRound = INVALID_HANDLE;
|
||||
new Handle:g_hToolsCSWeaponDrop = INVALID_HANDLE;
|
||||
/**
|
||||
@ -108,7 +107,6 @@ ToolsFindOffsets()
|
||||
WeaponsOnOffsetsFound();
|
||||
AccountOnOffsetsFound();
|
||||
VEffectsOnOffsetsFound();
|
||||
AntiStickOnOffsetsFound();
|
||||
ZMarketOnOffsetsFound();
|
||||
}
|
||||
|
||||
@ -126,18 +124,6 @@ ToolsSetupGameData()
|
||||
LogEvent(false, LogType_Fatal, LOG_CORE_EVENTS, LogModule_Tools, "GameData", "Can't load game config file (plugin.zombiereloaded.txt) from the gamedata directory.");
|
||||
}
|
||||
|
||||
// Prep the SDKCall for "EyeAngles."
|
||||
StartPrepSDKCall(SDKCall_Player);
|
||||
PrepSDKCall_SetFromConf(g_hToolsGameConfig, SDKConf_Virtual, "EyeAngles");
|
||||
PrepSDKCall_SetReturnInfo(SDKType_QAngle, SDKPass_ByValue);
|
||||
g_hToolsEyeAngles = EndPrepSDKCall();
|
||||
|
||||
// If offset "EyeAngles" can't be found, then stop the plugin.
|
||||
if(g_hToolsEyeAngles == INVALID_HANDLE)
|
||||
{
|
||||
LogEvent(false, LogType_Fatal, LOG_CORE_EVENTS, LogModule_Tools, "GameData", "Offset \"EyeAngles\" was not found.");
|
||||
}
|
||||
|
||||
// Prep the SDKCall for "TerminateRound."
|
||||
StartPrepSDKCall(SDKCall_GameRules);
|
||||
PrepSDKCall_SetFromConf(g_hToolsGameConfig, SDKConf_Signature, "TerminateRound");
|
||||
|
@ -33,7 +33,7 @@
|
||||
* @param stack If modifying velocity, then true will stack new velocity onto the client's
|
||||
* current velocity, false will reset it.
|
||||
*/
|
||||
ToolsClientVelocity(client, Float:vecVelocity[3], bool:apply = true, bool:stack = true)
|
||||
stock ToolsClientVelocity(client, Float:vecVelocity[3], bool:apply = true, bool:stack = true)
|
||||
{
|
||||
// If retrieve if true, then get client's velocity.
|
||||
if (!apply)
|
||||
@ -72,12 +72,30 @@ ToolsClientVelocity(client, Float:vecVelocity[3], bool:apply = true, bool:stack
|
||||
* @param client The client index.
|
||||
* @param value LMV value. (1.0 = default, 2.0 = double)
|
||||
*/
|
||||
ToolsSetClientLMV(client, Float:fLMV)
|
||||
stock ToolsSetClientLMV(client, Float:fLMV)
|
||||
{
|
||||
// Set lagged movement value of client.
|
||||
SetEntDataFloat(client, g_iToolsLMV, fLMV / 300.0, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get nightvision values on a client.
|
||||
* @param client The client index.
|
||||
* @param ownership If true, function will return the value of the client's ownership of nightvision.
|
||||
* If false, function will return the value of the client's on/off state of the nightvision.
|
||||
* @return True if aspect of nightvision is enabled on the client, false if not.
|
||||
*/
|
||||
stock bool:ToolsGetClientNightVision(client, bool:ownership = true)
|
||||
{
|
||||
// If ownership is true, then toggle the ownership of nightvision on client.
|
||||
if (ownership)
|
||||
{
|
||||
return bool:GetEntData(client, g_iToolsHasNightVision, 1);
|
||||
}
|
||||
|
||||
return bool:GetEntData(client, g_iToolsNightVisionOn, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Control nightvision values on a client.
|
||||
* @param client The client index.
|
||||
@ -85,7 +103,7 @@ ToolsSetClientLMV(client, Float:fLMV)
|
||||
* @param ownership If true, enable will toggle the client's ownership of nightvision.
|
||||
* If false, enable will toggle the client's on/off state of the nightvision.
|
||||
*/
|
||||
ToolsClientNightVision(client, bool:enable, bool:ownership = true)
|
||||
stock ToolsSetClientNightVision(client, bool:enable, bool:ownership = true)
|
||||
{
|
||||
// If ownership is true, then toggle the ownership of nightvision on client.
|
||||
if (ownership)
|
||||
@ -104,7 +122,7 @@ ToolsClientNightVision(client, bool:enable, bool:ownership = true)
|
||||
* @param client The client index.
|
||||
* @param FOV The field of vision of the client.
|
||||
*/
|
||||
ToolsSetClientDefaultFOV(client, FOV)
|
||||
stock ToolsSetClientDefaultFOV(client, FOV)
|
||||
{
|
||||
SetEntData(client, g_iToolsDefaultFOV, FOV, 1, true);
|
||||
}
|
||||
@ -118,7 +136,7 @@ ToolsSetClientDefaultFOV(client, FOV)
|
||||
* @param value The value of the client's score or deaths.
|
||||
* @return The score or death count of the client, -1 if setting.
|
||||
*/
|
||||
ToolsClientScore(client, bool:score = true, bool:apply = true, value = 0)
|
||||
stock ToolsClientScore(client, bool:score = true, bool:apply = true, value = 0)
|
||||
{
|
||||
if (!apply)
|
||||
{
|
||||
@ -156,7 +174,7 @@ ToolsClientScore(client, bool:score = true, bool:apply = true, value = 0)
|
||||
* @param alpha The alpha value to set client's alpha to. (0-255)
|
||||
* @param weapons Apply alpha to all client's weapons.
|
||||
*/
|
||||
ToolsSetClientAlpha(client, alpha)
|
||||
stock ToolsSetClientAlpha(client, alpha)
|
||||
{
|
||||
// Turn rendermode on, on the client.
|
||||
SetEntityRenderMode(client, RENDER_TRANSALPHA);
|
||||
@ -174,7 +192,7 @@ ToolsSetClientAlpha(client, alpha)
|
||||
* @param client The client index.
|
||||
* @return The alpha value of the client. (0-255)
|
||||
*/
|
||||
ToolsGetEntityAlpha(entity)
|
||||
stock ToolsGetEntityAlpha(entity)
|
||||
{
|
||||
static bool:gotconfig = false;
|
||||
static String:prop[32];
|
||||
|
@ -49,11 +49,6 @@
|
||||
* @endsection
|
||||
*/
|
||||
|
||||
/**
|
||||
* HUD text usermsg
|
||||
*/
|
||||
#define TRANSLATION_USERMSG_HINTTEXT "HintText"
|
||||
|
||||
/**
|
||||
* Load translations file here.
|
||||
*/
|
||||
@ -285,7 +280,7 @@ stock TranslationPrintCenterText(client, any:...)
|
||||
* @param client The client index.
|
||||
* @param ... Translation formatting parameters.
|
||||
*/
|
||||
stock TranslationPrintHUDText(client, any:...)
|
||||
stock TranslationPrintHintText(client, any:...)
|
||||
{
|
||||
// Set translation target
|
||||
SetGlobalTransTarget(client);
|
||||
@ -295,17 +290,7 @@ stock TranslationPrintHUDText(client, any:...)
|
||||
VFormat(translation, sizeof(translation), "%t", 2);
|
||||
|
||||
// Print translated phrase to client.
|
||||
|
||||
// If hint text usermsg is invalid, then stop.
|
||||
new Handle:hHintText = StartMessageOne(TRANSLATION_USERMSG_HINTTEXT, client);
|
||||
if (hHintText == INVALID_HANDLE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
BfWriteByte(hHintText, -1);
|
||||
BfWriteString(hHintText, translation);
|
||||
EndMessage();
|
||||
PrintHintText(client, translation);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -104,7 +104,7 @@ public WeaponsMenuMainHandle(Handle:menu_weapons_main, MenuAction:action, client
|
||||
if (slot == MenuCancel_ExitBack)
|
||||
{
|
||||
// Re-open admin menu.
|
||||
ZRAdminMenu(client);
|
||||
ZAdminMenu(client);
|
||||
}
|
||||
}
|
||||
// Client hit "Exit" button.
|
||||
@ -210,7 +210,7 @@ WeaponsMenuTypeWeapons(client)
|
||||
decl String:unrestrictall[64];
|
||||
|
||||
Format(restrictall, sizeof(restrictall), "%t", "Weapons menu restrict types restrict all", typename);
|
||||
Format(unrestrictall, sizeof(unrestrictall), "%t", "Weapons menu restrict types unrestrict all", typename);
|
||||
Format(unrestrictall, sizeof(unrestrictall), "%t\n ", "Weapons menu restrict types unrestrict all", typename);
|
||||
|
||||
// Draw items as selectable only if not all weapons within the type are restricted or unrestricted.
|
||||
AddMenuItem(menu_weapons_typeweapons, "restrictall", restrictall, MenuGetItemDraw(!RestrictIsTypeUniform(true, g_iWeaponsCurType[client])));
|
||||
|
@ -43,6 +43,11 @@ enum RestrictData
|
||||
*/
|
||||
new g_iCanUseHookID[MAXPLAYERS + 1] = {-1, ...};
|
||||
|
||||
/**
|
||||
* Array to block any client from picking up weapons.
|
||||
*/
|
||||
new bool:g_bRestrictBlockWeapon[MAXPLAYERS + 1];
|
||||
|
||||
/**
|
||||
* Array to store a list of different weapon groups
|
||||
*/
|
||||
@ -134,6 +139,9 @@ RestrictClientInit(client)
|
||||
{
|
||||
// Hook "Weapon_CanUse" on client.
|
||||
g_iCanUseHookID[client] = ZRTools_HookWeapon_CanUse(client, RestrictCanUse);
|
||||
|
||||
// Reset block weapons flag.
|
||||
g_bRestrictBlockWeapon[client] = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -161,6 +169,48 @@ RestrictOnClientSpawn(client)
|
||||
// Re-hook "canuse" on client.
|
||||
ZRTools_UnhookWeapon_CanUse(g_iCanUseHookID[client]);
|
||||
g_iCanUseHookID[client] = ZRTools_HookWeapon_CanUse(client, RestrictCanUse);
|
||||
|
||||
// H4x. Unfortunately I can't disable this flag early enough for CS:S to give start USP/Glock.
|
||||
// So I have to give BOOTLEG weapons. (Sorry Valve)
|
||||
if (g_bRestrictBlockWeapon[client])
|
||||
{
|
||||
// Reset block weapons flag.
|
||||
g_bRestrictBlockWeapon[client] = false;
|
||||
|
||||
if (ZRIsClientOnTeam(client, CS_TEAM_T))
|
||||
{
|
||||
GivePlayerItem(client, WEAPONS_SPAWN_T_WEAPON);
|
||||
}
|
||||
else if (ZRIsClientOnTeam(client, CS_TEAM_CT))
|
||||
{
|
||||
GivePlayerItem(client, WEAPONS_SPAWN_CT_WEAPON);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The round is ending.
|
||||
*/
|
||||
RestrictOnRoundEnd()
|
||||
{
|
||||
// x = Client index.
|
||||
for (new x = 1; x <= MaxClients; x++)
|
||||
{
|
||||
// If client isn't in-game, then stop.
|
||||
if (!IsClientInGame(x))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// If client is a human, then stop.
|
||||
if (InfectIsClientHuman(x))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Enable block weapon flag.
|
||||
g_bRestrictBlockWeapon[x] = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -181,7 +231,7 @@ public Action:RestrictBuyCommand(client, argc)
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
decl String:weapon[64];
|
||||
decl String:weapon[WEAPONS_MAX_LENGTH];
|
||||
GetCmdArg(1, weapon, sizeof(weapon));
|
||||
|
||||
ReplaceString(weapon, sizeof(weapon), "weapon_", "");
|
||||
@ -199,7 +249,11 @@ public Action:RestrictBuyCommand(client, argc)
|
||||
// If weapon is restricted, then stop.
|
||||
if (RestrictIsWeaponRestricted(index))
|
||||
{
|
||||
TranslationPrintToChat(client, "Weapon is restricted", weapon);
|
||||
// Get display name.
|
||||
decl String:weapondisplay[WEAPONS_MAX_LENGTH];
|
||||
WeaponsGetName(index, weapondisplay, sizeof(weapondisplay));
|
||||
|
||||
TranslationPrintToChat(client, "Weapon is restricted", weapondisplay);
|
||||
|
||||
// Block command.
|
||||
return Plugin_Handled;
|
||||
@ -545,6 +599,18 @@ public ZRTools_Action:RestrictCanUse(client, weapon)
|
||||
return ZRTools_Continue;
|
||||
}
|
||||
|
||||
// If the player is a zombie, then prevent pickup.
|
||||
if (InfectIsClientInfected(client))
|
||||
{
|
||||
return ZRTools_Handled;
|
||||
}
|
||||
|
||||
// If client is flagged for not picking up weapons, then stop.
|
||||
if (g_bRestrictBlockWeapon[client])
|
||||
{
|
||||
return ZRTools_Handled;
|
||||
}
|
||||
|
||||
// If weapons module is disabled, then stop.
|
||||
new bool:weapons = GetConVarBool(g_hCvarsList[CVAR_WEAPONS]);
|
||||
if (!weapons)
|
||||
@ -575,12 +641,6 @@ public ZRTools_Action:RestrictCanUse(client, weapon)
|
||||
return ZRTools_Handled;
|
||||
}
|
||||
|
||||
// If the player is a zombie, then prevent pickup.
|
||||
if (InfectIsClientInfected(client))
|
||||
{
|
||||
return ZRTools_Handled;
|
||||
}
|
||||
|
||||
// Forward event to weapons module.
|
||||
WeaponsOnItemPickup(client, weapon);
|
||||
|
||||
|
@ -31,10 +31,19 @@
|
||||
#define WEAPONS_MAX_LENGTH 32
|
||||
|
||||
/**
|
||||
* Number of weapon slots (For CS:S)
|
||||
* Number of REAL weapon slots (For CS:S)
|
||||
*/
|
||||
#define WEAPONS_SLOTS_MAX 5
|
||||
|
||||
/**
|
||||
* @section CS:S start weapons.
|
||||
*/
|
||||
#define WEAPONS_SPAWN_T_WEAPON "weapon_glock"
|
||||
#define WEAPONS_SPAWN_CT_WEAPON "weapon_usp"
|
||||
/**
|
||||
* @endsection
|
||||
*/
|
||||
|
||||
/**
|
||||
* Weapon config data indexes.
|
||||
*/
|
||||
@ -73,6 +82,7 @@ enum WeaponsSlot
|
||||
Slot_Melee = 2, /** Melee (knife) weapon slot. */
|
||||
Slot_Projectile = 3, /** Projectile (grenades, flashbangs, etc) weapon slot. */
|
||||
Slot_Explosive = 4, /** Explosive (c4) weapon slot. */
|
||||
Slot_NVGs = 5, /** NVGs (fake) equipment slot. */
|
||||
}
|
||||
|
||||
/**
|
||||
@ -325,6 +335,15 @@ WeaponsOnClientSpawnPost(client)
|
||||
ZMarketOnClientSpawnPost(client);
|
||||
}
|
||||
|
||||
/**
|
||||
* The round is ending.
|
||||
*/
|
||||
WeaponsOnRoundEnd()
|
||||
{
|
||||
// Forward event to sub-modules.
|
||||
RestrictOnRoundEnd();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a client picks up an item.
|
||||
*
|
||||
|
@ -65,25 +65,21 @@ ZMarketOnCommandsCreate()
|
||||
|
||||
ZMarketOnCookiesCreate()
|
||||
{
|
||||
// If auto-rebuy cookie doesn't already exist, then create all ZMarket cookies.
|
||||
g_hZMarketAutoRebuyCookie = FindClientCookie(ZMARKET_COOKIE_AUTOREBUY);
|
||||
if (g_hZMarketAutoRebuyCookie == INVALID_HANDLE)
|
||||
{
|
||||
g_hZMarketAutoRebuyCookie = RegClientCookie(ZMARKET_COOKIE_AUTOREBUY, "The toggle state of auto-rebuy.", CookieAccess_Public);
|
||||
// Create all cookies.
|
||||
g_hZMarketAutoRebuyCookie = RegClientCookie(ZMARKET_COOKIE_AUTOREBUY, "The toggle state of auto-rebuy.", CookieAccess_Protected);
|
||||
|
||||
decl String:rebuycookiename[32];
|
||||
decl String:rebuycookiedesc[64];
|
||||
|
||||
// x = Weapon slot.
|
||||
for (new x = 0; x < WEAPONS_SLOTS_MAX; x++)
|
||||
for (new x = 0; x < WEAPONS_SLOTS_MAX + 1; x++)
|
||||
{
|
||||
// Format cookie name and description.
|
||||
Format(rebuycookiename, sizeof(rebuycookiename), "%s_%d", ZMARKET_COOKIE_REBUY, x);
|
||||
Format(rebuycookiedesc, sizeof(rebuycookiedesc), "Current loadout weapon for slot %d", x);
|
||||
|
||||
// Register client cookie.
|
||||
RegClientCookie(rebuycookiename, rebuycookiedesc, CookieAccess_Public);
|
||||
}
|
||||
RegClientCookie(rebuycookiename, rebuycookiedesc, CookieAccess_Protected);
|
||||
}
|
||||
}
|
||||
|
||||
@ -161,6 +157,12 @@ ZMarketOnClientSpawnPost(client)
|
||||
return;
|
||||
}
|
||||
|
||||
// If client is a zombie, then stop.
|
||||
if (InfectIsClientInfected(client))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// If auto-rebuy is enabled, then force client to rebuy weapons.
|
||||
if (CookiesGetClientCookieBool(client, g_hZMarketAutoRebuyCookie))
|
||||
{
|
||||
@ -382,10 +384,11 @@ bool:ZMarketMenuLoadout(client)
|
||||
decl String:meleeweapon[WEAPONS_MAX_LENGTH];
|
||||
decl String:projectileweapon[WEAPONS_MAX_LENGTH];
|
||||
decl String:explosiveweapon[WEAPONS_MAX_LENGTH];
|
||||
decl String:nvgsweapon[WEAPONS_MAX_LENGTH];
|
||||
|
||||
// Transfer cookie values into an array.
|
||||
new String:rebuyweapons[WeaponsSlot][WEAPONS_MAX_LENGTH];
|
||||
ZMarketCookiesToArray(client, rebuyweapons, WEAPONS_SLOTS_MAX, sizeof(rebuyweapons[]));
|
||||
ZMarketCookiesToArray(client, rebuyweapons, WEAPONS_SLOTS_MAX + 1, sizeof(rebuyweapons[]));
|
||||
|
||||
// Return the display name for all the client's weapon classname's.
|
||||
WeaponsClassnameToDisplay(rebuyweapons[Slot_Primary], sizeof(rebuyweapons[]), primaryweapon, sizeof(primaryweapon));
|
||||
@ -393,6 +396,7 @@ bool:ZMarketMenuLoadout(client)
|
||||
WeaponsClassnameToDisplay(rebuyweapons[Slot_Melee], sizeof(rebuyweapons[]), meleeweapon, sizeof(meleeweapon));
|
||||
WeaponsClassnameToDisplay(rebuyweapons[Slot_Projectile], sizeof(rebuyweapons[]), projectileweapon, sizeof(projectileweapon));
|
||||
WeaponsClassnameToDisplay(rebuyweapons[Slot_Explosive], sizeof(rebuyweapons[]), explosiveweapon, sizeof(explosiveweapon));
|
||||
WeaponsClassnameToDisplay(rebuyweapons[Slot_NVGs], sizeof(rebuyweapons[]), nvgsweapon, sizeof(nvgsweapon));
|
||||
|
||||
// Get the empty translation.
|
||||
decl String:empty[64];
|
||||
@ -420,11 +424,16 @@ bool:ZMarketMenuLoadout(client)
|
||||
strcopy(explosiveweapon, sizeof(explosiveweapon), empty);
|
||||
}
|
||||
|
||||
// Copy "Yes/No" to NVGs string.
|
||||
decl String:nvgsbool[8];
|
||||
ConfigBoolToSetting(bool:nvgsweapon[0], nvgsbool, sizeof(nvgsbool));
|
||||
|
||||
decl String:primary[64];
|
||||
decl String:secondary[64];
|
||||
decl String:melee[64];
|
||||
decl String:projectile[64];
|
||||
decl String:explosive[64];
|
||||
decl String:nvgs[64];
|
||||
|
||||
// Format all the lines of the menu.
|
||||
Format(primary, sizeof(primary), "%t", "Weapons menu zmarket loadout primary", primaryweapon);
|
||||
@ -432,13 +441,15 @@ bool:ZMarketMenuLoadout(client)
|
||||
Format(melee, sizeof(melee), "%t", "Weapons menu zmarket loadout melee", meleeweapon);
|
||||
Format(projectile, sizeof(projectile), "%t", "Weapons menu zmarket loadout projectile", projectileweapon);
|
||||
Format(explosive, sizeof(explosive), "%t", "Weapons menu zmarket loadout explosive", explosiveweapon);
|
||||
Format(nvgs, sizeof(nvgs), "%t", "Weapons menu zmarket loadout nvgs", nvgsbool);
|
||||
|
||||
// Add formatted options to menu.
|
||||
AddMenuItem(menu_zmarket_loadout, primary, primary, ITEMDRAW_DISABLED);
|
||||
AddMenuItem(menu_zmarket_loadout, secondary, secondary, ITEMDRAW_DISABLED);
|
||||
AddMenuItem(menu_zmarket_loadout, melee, melee, ITEMDRAW_DISABLED);
|
||||
AddMenuItem(menu_zmarket_loadout, projectile, projectile, ITEMDRAW_DISABLED);
|
||||
AddMenuItem(menu_zmarket_loadout, explosive, explosive, ITEMDRAW_DISABLED);
|
||||
AddMenuItem(menu_zmarket_loadout, "0", primary, MenuGetItemDraw(!StrEqual(primaryweapon, empty)));
|
||||
AddMenuItem(menu_zmarket_loadout, "1", secondary, MenuGetItemDraw(!StrEqual(secondaryweapon, empty)));
|
||||
AddMenuItem(menu_zmarket_loadout, "2", melee, MenuGetItemDraw(!StrEqual(meleeweapon, empty)));
|
||||
AddMenuItem(menu_zmarket_loadout, "3", projectile, MenuGetItemDraw(!StrEqual(projectileweapon, empty)));
|
||||
AddMenuItem(menu_zmarket_loadout, "4", explosive, MenuGetItemDraw(!StrEqual(explosiveweapon, empty)));
|
||||
AddMenuItem(menu_zmarket_loadout, "5", nvgs, MenuGetItemDraw(bool:nvgsweapon[0]));
|
||||
|
||||
// Set exit back button.
|
||||
SetMenuExitBackButton(menu_zmarket_loadout, true);
|
||||
@ -457,6 +468,15 @@ bool:ZMarketMenuLoadout(client)
|
||||
*/
|
||||
public ZMarketMenuLoadoutHandle(Handle:menu_zmarket_loadout, MenuAction:action, client, slot)
|
||||
{
|
||||
// Client selected an option.
|
||||
if (action == MenuAction_Select)
|
||||
{
|
||||
// Clear rebuy slot.
|
||||
ZMarketSetRebuyCookie(client, WeaponsSlot:slot, "");
|
||||
|
||||
// Re-send menu.
|
||||
ZMarketMenuLoadout(client);
|
||||
}
|
||||
// Client closed the menu.
|
||||
if (action == MenuAction_Cancel)
|
||||
{
|
||||
@ -779,6 +799,32 @@ stock bool:ZMarketEquip(client, const String:weapon[], bool:rebuy = false)
|
||||
return false;
|
||||
}
|
||||
|
||||
// Copy the 'weapon' variable into a local variable for indexing.
|
||||
decl String:weaponname[WEAPONS_MAX_LENGTH];
|
||||
strcopy(weaponname, sizeof(weaponname), weapon);
|
||||
|
||||
// Get the display name for the weapon.
|
||||
decl String:weapondisplay[WEAPONS_MAX_LENGTH];
|
||||
WeaponsClassnameToDisplay(weaponname, sizeof(weaponname), weapondisplay, sizeof(weapondisplay));
|
||||
|
||||
// Check to make sure the weapon isn't restricted.
|
||||
new bool:restricted = RestrictIsWeaponRestricted(weaponindex);
|
||||
if (restricted)
|
||||
{
|
||||
TranslationPrintToChat(client, "Weapon is restricted", weapondisplay);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the purchase count information for this weapon.
|
||||
new purchasemax = WeaponsGetZMarketPurchaseMax(weaponindex);
|
||||
new purchasecount = ZMarketGetPurchaseCount(client, weapon);
|
||||
new purchasesleft = purchasemax - purchasecount;
|
||||
if (purchasemax > 0 && purchasesleft <= 0)
|
||||
{
|
||||
TranslationPrintToChat(client, "Weapons zmarket purchase max", weapondisplay, purchasemax);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get client's current money.
|
||||
new cash = AccountGetClientCash(client);
|
||||
|
||||
@ -795,34 +841,16 @@ stock bool:ZMarketEquip(client, const String:weapon[], bool:rebuy = false)
|
||||
// Set client's new cash after purchase.
|
||||
AccountSetClientCash(client, cash - itemprice);
|
||||
|
||||
// Check to make sure the weapon isn't restricted.
|
||||
new bool:restricted = RestrictIsWeaponRestricted(weaponindex);
|
||||
if (restricted)
|
||||
{
|
||||
TranslationPrintToChat(client, "Weapon is restricted", weapon);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the purchase count information for this weapon.
|
||||
new purchasemax = WeaponsGetZMarketPurchaseMax(weaponindex);
|
||||
new purchasecount = ZMarketGetPurchaseCount(client, weapon);
|
||||
new purchasesleft = purchasemax - purchasecount;
|
||||
if (purchasemax > 0 && purchasesleft <= 0)
|
||||
{
|
||||
TranslationPrintToChat(client, "Weapons zmarket purchase max", weapon, purchasemax);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get a list of the client's current weapons.
|
||||
new weapons[WeaponsSlot];
|
||||
WeaponsGetClientWeapons(client, weapons);
|
||||
|
||||
// Check if client is buying the weapon or ammo for it.
|
||||
if (!hasweapon || slot == Slot_Invalid || slot == Slot_Projectile)
|
||||
if (!hasweapon || slot == Slot_Projectile || slot == Slot_NVGs)
|
||||
{
|
||||
|
||||
// Check if the slot is valid and NOT a projectile (grenade).
|
||||
if (slot != Slot_Invalid && slot != Slot_Projectile)
|
||||
// If the item is a projectile or NVGs, then skip.
|
||||
if (slot != Slot_Projectile && slot != Slot_NVGs)
|
||||
{
|
||||
// If there is already a weapon in the slot, then force client to drop it.
|
||||
if (weapons[slot] > -1)
|
||||
@ -835,8 +863,8 @@ stock bool:ZMarketEquip(client, const String:weapon[], bool:rebuy = false)
|
||||
// Format name into entity name.
|
||||
decl String:weaponentity[WEAPONS_MAX_LENGTH];
|
||||
|
||||
// If the slot is invalid, this means the item is not a usable weapon, it's equipment.
|
||||
if (slot == Slot_Invalid)
|
||||
// If this is the NVGs slot, then format "item_" in front instead of "weapon_".
|
||||
if (slot == Slot_NVGs)
|
||||
{
|
||||
Format(weaponentity, sizeof(weaponentity), "item_%s", weapon);
|
||||
}
|
||||
@ -854,10 +882,10 @@ stock bool:ZMarketEquip(client, const String:weapon[], bool:rebuy = false)
|
||||
// Add 1 to the client's purchase count.
|
||||
ZMarketSetPurchaseCount(client, weapon, 1, true);
|
||||
|
||||
if (slot != Slot_Invalid && slot != Slot_Projectile)
|
||||
if (slot != Slot_Projectile && slot != Slot_NVGs)
|
||||
{
|
||||
// Tell client they bought a weapon.
|
||||
TranslationPrintToChat(client, "Weapons zmarket purchase", weapon);
|
||||
TranslationPrintToChat(client, "Weapons zmarket purchase", weapondisplay);
|
||||
}
|
||||
}
|
||||
else if (!rebuy)
|
||||
@ -926,6 +954,18 @@ bool:ZMarketGetCurrentLoadout(client)
|
||||
ZMarketSetRebuyCookie(client, WeaponsSlot:x, weaponname);
|
||||
}
|
||||
|
||||
// Update nightvision ownership.
|
||||
new bool:nightvision = ToolsGetClientNightVision(client);
|
||||
if (!nightvision)
|
||||
{
|
||||
// Empty rebuy slot.
|
||||
ZMarketSetRebuyCookie(client, Slot_NVGs, "");
|
||||
}
|
||||
else
|
||||
{
|
||||
ZMarketSetRebuyCookie(client, Slot_NVGs, "nvgs");
|
||||
}
|
||||
|
||||
// Tell client their loadout has been updated.
|
||||
TranslationPrintToChat(client, "Weapons zmarket get current loadout");
|
||||
|
||||
@ -997,6 +1037,12 @@ stock ZMarketSetRebuyCookie(client, WeaponsSlot:slot, const String:value[])
|
||||
|
||||
// Find cookie handle, and retrieve its value.
|
||||
new Handle:rebuycookie = FindClientCookie(rebuycookiename);
|
||||
if (rebuycookie == INVALID_HANDLE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Set weapon to cookie.
|
||||
SetClientCookie(client, rebuycookie, value);
|
||||
}
|
||||
|
||||
@ -1023,10 +1069,10 @@ ZMarketRebuy(client, bool:autorebuy = false)
|
||||
|
||||
// Transfer cookie values into an array.
|
||||
new String:rebuyweapons[WeaponsSlot][WEAPONS_MAX_LENGTH];
|
||||
ZMarketCookiesToArray(client, rebuyweapons, WEAPONS_SLOTS_MAX, sizeof(rebuyweapons[]));
|
||||
ZMarketCookiesToArray(client, rebuyweapons, WEAPONS_SLOTS_MAX + 1, sizeof(rebuyweapons[]));
|
||||
|
||||
// x = Weapon slot.
|
||||
for (new x = 0; x < WEAPONS_SLOTS_MAX; x++)
|
||||
for (new x = 0; x < WEAPONS_SLOTS_MAX + 1; x++)
|
||||
{
|
||||
// If slot is empty, then stop.
|
||||
if (!rebuyweapons[x][0])
|
||||
@ -1036,9 +1082,6 @@ ZMarketRebuy(client, bool:autorebuy = false)
|
||||
|
||||
ZMarketEquip(client, rebuyweapons[x], true);
|
||||
}
|
||||
|
||||
// Copy values back to cookies.
|
||||
ZMarketArrayToCookies(client, rebuyweapons, WEAPONS_SLOTS_MAX, sizeof(rebuyweapons));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -51,7 +51,7 @@ public Action:ZAdminCommand(client, argc)
|
||||
}
|
||||
|
||||
// Send admin menu.
|
||||
ZRAdminMenu(client);
|
||||
ZAdminMenu(client);
|
||||
|
||||
// This stops the "Unknown command" message in client's console.
|
||||
return Plugin_Handled;
|
||||
@ -62,7 +62,7 @@ public Action:ZAdminCommand(client, argc)
|
||||
*
|
||||
* @param client The client index.
|
||||
*/
|
||||
bool:ZRAdminMenu(client)
|
||||
bool:ZAdminMenu(client)
|
||||
{
|
||||
// If client isn't an admin, then stop.
|
||||
if (!ZRIsClientAdmin(client))
|
||||
@ -72,7 +72,7 @@ bool:ZRAdminMenu(client)
|
||||
}
|
||||
|
||||
// Create menu handle.
|
||||
new Handle:menu_zadmin = CreateMenu(ZRAdminMenuHandle);
|
||||
new Handle:menu_zadmin = CreateMenu(ZAdminMenuHandle);
|
||||
|
||||
// Set translation target as the client.
|
||||
SetGlobalTransTarget(client);
|
||||
@ -80,24 +80,31 @@ bool:ZRAdminMenu(client)
|
||||
SetMenuTitle(menu_zadmin, "%t\n ", "ZAdmin main title");
|
||||
|
||||
decl String:classmultipliers[64];
|
||||
//decl String:zspawn[64];
|
||||
//decl String:ztele[64];
|
||||
decl String:weapons[64];
|
||||
decl String:hitgroups[64];
|
||||
decl String:infect[64];
|
||||
decl String:zspawn[64];
|
||||
decl String:ztele[64];
|
||||
//decl String:logflags[64];
|
||||
|
||||
Format(classmultipliers, sizeof(classmultipliers), "%t", "ZAdmin main class multipliers");
|
||||
Format(weapons, sizeof(weapons), "%t", "ZAdmin main weapons");
|
||||
Format(hitgroups, sizeof(hitgroups), "%t", "ZAdmin main hitgroups");
|
||||
Format(infect, sizeof(infect), "%t", "ZAdmin main zombie");
|
||||
//Format(zspawn, sizeof(zspawn), "%t", "!zadmin main spawn");
|
||||
//Format(ztele, sizeof(ztele), "%t", "!zadmin main tele");
|
||||
Format(zspawn, sizeof(zspawn), "%t", "ZAdmin main force zspawn");
|
||||
Format(ztele, sizeof(ztele), "%t", "ZAdmin main force ztele");
|
||||
//Format(logflags, sizeof(logflags), "%t", "!zadmin main logflags");
|
||||
|
||||
// Get conditions for options.
|
||||
new bool:hitgroupsenabled = GetConVarBool(g_hCvarsList[CVAR_HITGROUPS]);
|
||||
|
||||
// Add items to menu.
|
||||
AddMenuItem(menu_zadmin, "classmultipliers", classmultipliers);
|
||||
AddMenuItem(menu_zadmin, "weapons", weapons);
|
||||
AddMenuItem(menu_zadmin, "hitgroups", hitgroups, MenuGetItemDraw(hitgroupsenabled));
|
||||
AddMenuItem(menu_zadmin, "infect", infect);
|
||||
//AddMenuItem(menu_zadmin, "zspawn", zspawn);
|
||||
//AddMenuItem(menu_zadmin, "ztele", ztele, ITEMDRAW_DISABLED);
|
||||
AddMenuItem(menu_zadmin, "zspawn", zspawn);
|
||||
AddMenuItem(menu_zadmin, "ztele", ztele);
|
||||
//AddMenuItem(menu_zadmin, "logflags", logflags);
|
||||
|
||||
// Set "Back" button.
|
||||
@ -118,7 +125,7 @@ bool:ZRAdminMenu(client)
|
||||
* @param client The client index.
|
||||
* @param slot The menu slot selected. (starting from 0)
|
||||
*/
|
||||
public ZRAdminMenuHandle(Handle:menu_zadmin, MenuAction:action, client, slot)
|
||||
public ZAdminMenuHandle(Handle:menu_zadmin, MenuAction:action, client, slot)
|
||||
{
|
||||
if (action == MenuAction_Select)
|
||||
{
|
||||
@ -137,8 +144,13 @@ public ZRAdminMenuHandle(Handle:menu_zadmin, MenuAction:action, client, slot)
|
||||
{
|
||||
resend = !WeaponsMenuMain(client);
|
||||
}
|
||||
// Zombie management.
|
||||
// Hitgroup management.
|
||||
case 2:
|
||||
{
|
||||
resend = !HitgroupsMenuHitgroups(client);
|
||||
}
|
||||
// Zombie management.
|
||||
case 3:
|
||||
{
|
||||
// We're not resending this menu.
|
||||
resend = false;
|
||||
@ -146,12 +158,30 @@ public ZRAdminMenuHandle(Handle:menu_zadmin, MenuAction:action, client, slot)
|
||||
// Send list of clients to infect.
|
||||
InfectMenuClients(client);
|
||||
}
|
||||
// Force ZSpawn.
|
||||
case 4:
|
||||
{
|
||||
// We're not resending this menu.
|
||||
resend = false;
|
||||
|
||||
// Send list of clients to infect.
|
||||
MenuClientList(client, ZSpawnForceHandle, "ZSpawn clients title");
|
||||
}
|
||||
// Force ZTele.
|
||||
case 5:
|
||||
{
|
||||
// We're not resending this menu.
|
||||
resend = false;
|
||||
|
||||
// Send list of clients to infect.
|
||||
MenuClientList(client, ZTeleForceHandle, "ZTele clients title");
|
||||
}
|
||||
}
|
||||
|
||||
// Re-send menu if selection failed.
|
||||
if (resend)
|
||||
{
|
||||
ZRAdminMenu(client);
|
||||
ZAdminMenu(client);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,12 +54,8 @@ ZHPOnCommandsCreate()
|
||||
*/
|
||||
ZHPOnCookiesCreate()
|
||||
{
|
||||
// If cookie doesn't already exist, then create it.
|
||||
g_hZHPEnabledCookie = FindClientCookie(ZHP_COOKIE_ENABLED);
|
||||
if (g_hZHPEnabledCookie == INVALID_HANDLE)
|
||||
{
|
||||
g_hZHPEnabledCookie = RegClientCookie(ZHP_COOKIE_ENABLED, "The toggle state of ZHP.", CookieAccess_Public);
|
||||
}
|
||||
// Create ZHP cookie.
|
||||
g_hZHPEnabledCookie = RegClientCookie(ZHP_COOKIE_ENABLED, "The toggle state of ZHP.", CookieAccess_Protected);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -242,7 +238,7 @@ ZHPUpdateHUD(client)
|
||||
}
|
||||
|
||||
// Display HP
|
||||
TranslationPrintHUDText(client, "Display HP", health);
|
||||
TranslationPrintHintText(client, "Display HP", health);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -248,6 +248,7 @@ stock bool:ZRIsClientAdmin(client, AdminFlag:flag = Admin_Generic)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// If client doesn't have the Admin_Generic flag, then stop.
|
||||
if (!GetAdminFlag(GetUserAdmin(client), flag))
|
||||
{
|
||||
|
@ -42,6 +42,9 @@ ZSpawnOnCommandsCreate()
|
||||
{
|
||||
// Register ZSpawn command.
|
||||
RegConsoleCmd(SAYHOOKS_KEYWORD_ZSPAWN, ZSpawnCommand, "Spawn into the game after joining late.");
|
||||
|
||||
// Register admin command to force ZSpawn.
|
||||
RegAdminCmd("zr_zspawn_force", ZSpawnForceCommand, ADMFLAG_GENERIC, "Force ZSpawn on a client. Usage: zr_zspawn_force <client> ['0' = Spawn as human | '1' = Spawn as zombie]");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -69,6 +72,12 @@ ZSpawnOnMapStart()
|
||||
*/
|
||||
ZSpawnOnClientDisconnect(client)
|
||||
{
|
||||
// So people who are connecting that click "cancel" aren't added to the list.
|
||||
if (!IsClientInGame(client))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if client is a bot.
|
||||
if (IsFakeClient(client))
|
||||
{
|
||||
@ -162,13 +171,15 @@ ZSpawnOnRoundEnd()
|
||||
* Spawns a late-joining client into the game.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @param force (Optional) True to force spawning of the client, false to follow rules.
|
||||
* @param zombie (Optional) If you are forcing spawn, you must override the team here.
|
||||
* @return True if successful, false otherwise.
|
||||
*/
|
||||
bool:ZSpawnClient(client)
|
||||
bool:ZSpawnClient(client, bool:force = false, bool:zombie = false)
|
||||
{
|
||||
// If zspawn is disabled, then stop.
|
||||
new bool:zspawn = GetConVarBool(g_hCvarsList[CVAR_ZSPAWN]);
|
||||
if (!zspawn)
|
||||
if (!force && !zspawn)
|
||||
{
|
||||
TranslationPrintToChat(client, "Feature is disabled");
|
||||
return false;
|
||||
@ -176,31 +187,43 @@ bool:ZSpawnClient(client)
|
||||
|
||||
// If client isn't on a team, then stop.
|
||||
if (!ZRIsClientOnTeam(client))
|
||||
{
|
||||
if (!force)
|
||||
{
|
||||
// Tell client the command may only be used when on a team.
|
||||
TranslationPrintToChat(client, "Must be on team");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// If client is alive, then stop.
|
||||
if (IsPlayerAlive(client))
|
||||
{
|
||||
if (!force)
|
||||
{
|
||||
// Tell client the command may only be used when dead.
|
||||
TranslationPrintToChat(client, "Must be dead");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Block if client has already played during this round.
|
||||
if (SteamidCacheClientExists(g_hZSpawnSteamIDCache, client))
|
||||
if (!force && SteamidCacheClientExists(g_hZSpawnSteamIDCache, client))
|
||||
{
|
||||
// Tell client the command may only be used when joining late.
|
||||
TranslationPrintToChat(client, "ZSpawn double spawn");
|
||||
return false;
|
||||
}
|
||||
|
||||
new bool:teamzombie;
|
||||
|
||||
if (!force)
|
||||
{
|
||||
// Check if zspawn override is enabled, and if so get overidden value.
|
||||
new bool:teamoverride = GetConVarBool(g_hCvarsList[CVAR_ZSPAWN_TEAM_OVERRIDE]);
|
||||
new bool:teamzombie = teamoverride ? GetConVarBool(g_hCvarsList[CVAR_ZSPAWN_TEAM_ZOMBIE]) : GetConVarBool(g_hCvarsList[CVAR_RESPAWN_TEAM_ZOMBIE]);
|
||||
teamzombie = teamoverride ? GetConVarBool(g_hCvarsList[CVAR_ZSPAWN_TEAM_ZOMBIE]) : GetConVarBool(g_hCvarsList[CVAR_RESPAWN_TEAM_ZOMBIE]);
|
||||
|
||||
// Block is the time limit is up.
|
||||
new bool:zspawntimelimit = GetConVarBool(g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT]);
|
||||
@ -231,6 +254,12 @@ bool:ZSpawnClient(client)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Use the override team in the function if were forcing the spawn.
|
||||
teamzombie = zombie;
|
||||
}
|
||||
|
||||
// Tell respawn module to respawn client.
|
||||
RespawnSpawnClient(client, teamzombie);
|
||||
@ -238,6 +267,60 @@ bool:ZSpawnClient(client)
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Menu callback (zspawn_force)
|
||||
* Forces ZSpawn on a client.
|
||||
*
|
||||
* @param menu The menu handle.
|
||||
* @param action Action client is doing in menu.
|
||||
* @param client The client index.
|
||||
* @param slot The menu slot selected. (starting from 0)
|
||||
*/
|
||||
public ZSpawnForceHandle(Handle:menu_zspawn_force, MenuAction:action, client, slot)
|
||||
{
|
||||
// Client selected an option.
|
||||
if (action == MenuAction_Select)
|
||||
{
|
||||
// Get the client index of the selected client.
|
||||
new target = MenuGetClientIndex(menu_zspawn_force, slot);
|
||||
|
||||
// Get the target's name for future use.
|
||||
decl String:targetname[MAX_NAME_LENGTH];
|
||||
GetClientName(target, targetname, sizeof(targetname));
|
||||
|
||||
// Force ZSpawn on the target.
|
||||
new bool:success = ZSpawnClient(target, true);
|
||||
|
||||
// Tell admin the outcome of the action.
|
||||
if (success)
|
||||
{
|
||||
TranslationReplyToCommand(client, "ZSpawn command force successful", targetname);
|
||||
}
|
||||
else
|
||||
{
|
||||
TranslationReplyToCommand(client, "ZSpawn command force unsuccessful", targetname);
|
||||
}
|
||||
|
||||
// Re-send the menu.
|
||||
MenuClientList(client, ZSpawnForceHandle, "ZSpawn clients title");
|
||||
}
|
||||
// Client closed the menu.
|
||||
if (action == MenuAction_Cancel)
|
||||
{
|
||||
// Client hit "Back" button.
|
||||
if (slot == MenuCancel_ExitBack)
|
||||
{
|
||||
// Re-open admin menu.
|
||||
ZAdminMenu(client);
|
||||
}
|
||||
}
|
||||
// Client exited menu.
|
||||
if (action == MenuAction_End)
|
||||
{
|
||||
CloseHandle(menu_zspawn_force);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Command callback (zspawn)
|
||||
* Spawn into the game after joining late.
|
||||
@ -261,6 +344,72 @@ public Action:ZSpawnCommand(client, argc)
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Command callback (zr_zspawn_force)
|
||||
* Force ZSpawn on a client.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @param argc Argument count.
|
||||
*/
|
||||
public Action:ZSpawnForceCommand(client, argc)
|
||||
{
|
||||
// If not enough arguments given, then stop.
|
||||
if (argc < 1)
|
||||
{
|
||||
TranslationReplyToCommand(client, "ZSpawn command force syntax");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
decl String:target[MAX_NAME_LENGTH], String:targetname[MAX_NAME_LENGTH];
|
||||
new targets[MAXPLAYERS], bool:tn_is_ml, result;
|
||||
|
||||
// Get targetname.
|
||||
GetCmdArg(1, target, sizeof(target));
|
||||
|
||||
// Find a target.
|
||||
result = ProcessTargetString(target, client, targets, sizeof(targets), COMMAND_FILTER_DEAD, targetname, sizeof(targetname), tn_is_ml);
|
||||
|
||||
// Check if there was a problem finding a client.
|
||||
if (result <= 0)
|
||||
{
|
||||
ZRReplyToTargetError(client, result);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
// Get item to give to client.
|
||||
decl String:strZombie[4];
|
||||
GetCmdArg(2, strZombie, sizeof(strZombie));
|
||||
|
||||
// Copy value of second (optional) parameter to 'zombie'.
|
||||
// It will be false if the parameter wasn't specified.
|
||||
new bool:zombie = bool:StringToInt(strZombie);
|
||||
|
||||
// x = Client index.
|
||||
for (new x = 0; x < result; x++)
|
||||
{
|
||||
// Give client the item.
|
||||
new bool:success = ZSpawnClient(targets[x], true, zombie);
|
||||
|
||||
// Tell admin the outcome of the command if only 1 client was targetted.
|
||||
if (result == 1)
|
||||
{
|
||||
if (success)
|
||||
{
|
||||
TranslationReplyToCommand(client, "ZSpawn command force successful", targetname);
|
||||
}
|
||||
else
|
||||
{
|
||||
TranslationReplyToCommand(client, "ZSpawn command force unsuccessful", targetname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Log action to game events.
|
||||
LogEvent(false, LogType_Normal, LOG_GAME_EVENTS, LogModule_ZSpawn, "Force ZSpawn", "Admin \"%L\" forced player(s) to spawn. (zr_zspawn_force)", client);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Timer callback, resets handle.
|
||||
*
|
||||
|
152
src/zr/ztele.inc
152
src/zr/ztele.inc
@ -55,8 +55,11 @@ new g_iZTeleTimeLeft[MAXPLAYERS + 1];
|
||||
*/
|
||||
ZTeleOnCommandsCreate()
|
||||
{
|
||||
// Register ZMenu command.
|
||||
// Register ZTele command.
|
||||
RegConsoleCmd(SAYHOOKS_KEYWORD_ZTELE, ZTeleCommand, "Teleport back to spawn if you are stuck.");
|
||||
|
||||
// Register admin command to force ZTele.
|
||||
RegAdminCmd("zr_ztele_force", ZTeleForceCommand, ADMFLAG_GENERIC, "Force ZTele on a client. Usage: zr_ztele_force <client>");
|
||||
}
|
||||
|
||||
/**
|
||||
@ -131,9 +134,11 @@ ZTeleOnClientInfected(client)
|
||||
* Teleports a client back to spawn if conditions are met.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @param force (Optional) True to force teleporting of the client, false to follow rules.
|
||||
* @param zombie (Optional) True to teleport instantly, false to use delay.
|
||||
* @return True if teleport was successful, false otherwise.
|
||||
*/
|
||||
bool:ZTeleClient(client)
|
||||
bool:ZTeleClient(client, bool:force = false)
|
||||
{
|
||||
// If the client is dead, then stop.
|
||||
if (!IsPlayerAlive(client))
|
||||
@ -145,7 +150,7 @@ bool:ZTeleClient(client)
|
||||
|
||||
// If zombie cvar is disabled and the client is a zombie, then stop.
|
||||
new bool:ztelezombie = GetConVarBool(g_hCvarsList[CVAR_ZTELE_ZOMBIE]);
|
||||
if (infected && !ztelezombie)
|
||||
if (!force && infected && !ztelezombie)
|
||||
{
|
||||
// Tell client they must be human to use this feature.
|
||||
TranslationPrintToChat(client, "Must be human");
|
||||
@ -155,7 +160,7 @@ bool:ZTeleClient(client)
|
||||
// If zombie has spawned, get before value, get the after value otherwise.
|
||||
// If the cvar is disabled and the client is a human, then stop.
|
||||
new bool:ztelehuman = g_bZombieSpawned ? GetConVarBool(g_hCvarsList[CVAR_ZTELE_HUMAN_AFTER]) : GetConVarBool(g_hCvarsList[CVAR_ZTELE_HUMAN_BEFORE]);
|
||||
if (!infected && !ztelehuman)
|
||||
if (!force && !infected && !ztelehuman)
|
||||
{
|
||||
// Tell client that feature is restricted at this time.
|
||||
TranslationPrintToChat(client, "ZTele restricted human");
|
||||
@ -164,7 +169,7 @@ bool:ZTeleClient(client)
|
||||
|
||||
// If the tele limit has been reached, then stop.
|
||||
new ztelemax = infected ? GetConVarInt(g_hCvarsList[CVAR_ZTELE_MAX_ZOMBIE]) : GetConVarInt(g_hCvarsList[CVAR_ZTELE_MAX_HUMAN]);
|
||||
if (g_iZTeleCount[client] >= ztelemax)
|
||||
if (!force && g_iZTeleCount[client] >= ztelemax)
|
||||
{
|
||||
// Tell client that they have already reached their limit.
|
||||
TranslationPrintToChat(client, "ZTele max", ztelemax);
|
||||
@ -173,20 +178,27 @@ bool:ZTeleClient(client)
|
||||
|
||||
// If teleport is already in progress, then stop.
|
||||
if (tZTele[client] != INVALID_HANDLE)
|
||||
{
|
||||
if (!force)
|
||||
{
|
||||
TranslationPrintToChat(client, "ZTele in progress");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we are forcing, then teleport now and stop.
|
||||
if (force)
|
||||
{
|
||||
// Teleport client to spawn.
|
||||
ZTeleTeleportClient(client);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get current location.
|
||||
GetClientAbsOrigin(client, g_vecZTeleOrigin[client]);
|
||||
|
||||
// If timer is running, kill it.
|
||||
if (tZTele[client] != INVALID_HANDLE)
|
||||
{
|
||||
KillTimer(tZTele[client]);
|
||||
}
|
||||
|
||||
// Set timeleft array to value of respective cvar.
|
||||
g_iZTeleTimeLeft[client] = infected ? GetConVarInt(g_hCvarsList[CVAR_ZTELE_DELAY_ZOMBIE]) : GetConVarInt(g_hCvarsList[CVAR_ZTELE_DELAY_HUMAN]);
|
||||
if (g_iZTeleTimeLeft[client] > 0)
|
||||
@ -199,12 +211,10 @@ bool:ZTeleClient(client)
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset timer handle.
|
||||
tZTele[client] = INVALID_HANDLE;
|
||||
|
||||
// Teleport client to spawn.
|
||||
ZTeleTeleportClient(client);
|
||||
|
||||
// If we're forcing the ZTele, then don't increment the count or print how many teleports they have used.
|
||||
// Tell client they've been teleported.
|
||||
TranslationPrintCenterText(client, "ZTele countdown end", g_iZTeleCount[client], ztelemax);
|
||||
|
||||
@ -227,7 +237,119 @@ ZTeleTeleportClient(client)
|
||||
}
|
||||
|
||||
/**
|
||||
* Command callback (zmenu)
|
||||
* Menu callback (ztele_force)
|
||||
* Forces ZTele on a client.
|
||||
*
|
||||
* @param menu The menu handle.
|
||||
* @param action Action client is doing in menu.
|
||||
* @param client The client index.
|
||||
* @param slot The menu slot selected. (starting from 0)
|
||||
*/
|
||||
public ZTeleForceHandle(Handle:menu_ztele_force, MenuAction:action, client, slot)
|
||||
{
|
||||
// Client selected an option.
|
||||
if (action == MenuAction_Select)
|
||||
{
|
||||
// Get the client index of the selected client.
|
||||
new target = MenuGetClientIndex(menu_ztele_force, slot);
|
||||
|
||||
// Get the target's name for future use.
|
||||
decl String:targetname[MAX_NAME_LENGTH];
|
||||
GetClientName(target, targetname, sizeof(targetname));
|
||||
|
||||
// Force ZSpawn on the target.
|
||||
new bool:success = ZTeleClient(target, true);
|
||||
|
||||
// Tell admin the outcome of the action.
|
||||
if (success)
|
||||
{
|
||||
TranslationReplyToCommand(client, "ZTele command force successful", targetname);
|
||||
}
|
||||
else
|
||||
{
|
||||
TranslationReplyToCommand(client, "ZTele command force unsuccessful", targetname);
|
||||
}
|
||||
|
||||
// Re-send the menu.
|
||||
MenuClientList(client, ZTeleForceHandle, "ZTele clients title");
|
||||
}
|
||||
// Client closed the menu.
|
||||
if (action == MenuAction_Cancel)
|
||||
{
|
||||
// Client hit "Back" button.
|
||||
if (slot == MenuCancel_ExitBack)
|
||||
{
|
||||
// Re-open admin menu.
|
||||
ZAdminMenu(client);
|
||||
}
|
||||
}
|
||||
// Client exited menu.
|
||||
if (action == MenuAction_End)
|
||||
{
|
||||
CloseHandle(menu_ztele_force);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Command callback (zr_ztele_force)
|
||||
* Force ZSpawn on a client.
|
||||
*
|
||||
* @param client The client index.
|
||||
* @param argc Argument count.
|
||||
*/
|
||||
public Action:ZTeleForceCommand(client, argc)
|
||||
{
|
||||
// If not enough arguments given, then stop.
|
||||
if (argc < 1)
|
||||
{
|
||||
TranslationReplyToCommand(client, "ZTele command force syntax");
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
decl String:target[MAX_NAME_LENGTH], String:targetname[MAX_NAME_LENGTH];
|
||||
new targets[MAXPLAYERS], bool:tn_is_ml, result;
|
||||
|
||||
// Get targetname.
|
||||
GetCmdArg(1, target, sizeof(target));
|
||||
|
||||
// Find a target.
|
||||
result = ProcessTargetString(target, client, targets, sizeof(targets), COMMAND_FILTER_ALIVE, targetname, sizeof(targetname), tn_is_ml);
|
||||
|
||||
// Check if there was a problem finding a client.
|
||||
if (result <= 0)
|
||||
{
|
||||
ZRReplyToTargetError(client, result);
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
// x = Client index.
|
||||
for (new x = 0; x < result; x++)
|
||||
{
|
||||
// Give client the item.
|
||||
new bool:success = ZTeleClient(targets[x], true);
|
||||
|
||||
// Tell admin the outcome of the command if only 1 client was targetted.
|
||||
if (result == 1)
|
||||
{
|
||||
if (success)
|
||||
{
|
||||
TranslationReplyToCommand(client, "ZTele command force successful", targetname);
|
||||
}
|
||||
else
|
||||
{
|
||||
TranslationReplyToCommand(client, "ZTele command force unsuccessful", targetname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Log action to game events.
|
||||
LogEvent(false, LogType_Normal, LOG_GAME_EVENTS, LogModule_ZTele, "Force ZTele", "Admin \"%L\" forced player(s) to teleport to spawn. (zr_ztele_force)", client);
|
||||
|
||||
return Plugin_Handled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Command callback (ztele)
|
||||
* Teleport back to spawn if you are stuck.
|
||||
*
|
||||
* @param client The client index.
|
||||
|
Loading…
Reference in New Issue
Block a user