Merged heads.
This commit is contained in:
		| @@ -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,25 +9,36 @@ | ||||
|  | ||||
| 		"Offsets" | ||||
| 		{ | ||||
|  | ||||
| 			"EyeAngles" | ||||
| 			{ | ||||
| 				"windows"	"206" | ||||
| 				"linux"		"207" | ||||
| 			} | ||||
|  | ||||
| 			"TraceAttack" | ||||
| 			{ | ||||
| 				"windows"	"58" | ||||
| 				"linux"		"59" | ||||
| 			} | ||||
| 		 | ||||
|  | ||||
| 			"OnTakeDamage" | ||||
| 			{ | ||||
| 				"windows"	"60" | ||||
| 				"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.  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          zombiereloaded.sp | ||||
|  *  Type:          Base | ||||
| @@ -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); | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          account.inc | ||||
|  *  Type:          Module | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          antistick.inc | ||||
|  *  Type:          Module | ||||
| @@ -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, | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Map is starting. | ||||
|  * Create commands related to antistick here. | ||||
|  */ | ||||
| AntiStickOnMapStart() | ||||
| AntiStickOnCommandsCreate() | ||||
| { | ||||
|     // Reset timer handle. | ||||
|     tAntiStick = INVALID_HANDLE; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * The round is starting. | ||||
|  */ | ||||
| AntiStickOnRoundStart() | ||||
| { | ||||
|     // If timer is running, kill it. | ||||
|     if (tAntiStick != INVALID_HANDLE) | ||||
|     { | ||||
|         KillTimer(tAntiStick); | ||||
|     } | ||||
|     // 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>"); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Creates/loads antistick data file. | ||||
|  */ | ||||
| AntiStickLoad() | ||||
| { | ||||
|     // 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; | ||||
|         } | ||||
|          | ||||
|         GetClientAbsOrigin(x, stuckloc); | ||||
|          | ||||
|         // 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 (clientloc[2] <= stuckloc[2]) | ||||
|             { | ||||
|                 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++) | ||||
|     // 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); | ||||
|      | ||||
|     if (max1y < min2y || min1y > max2y) | ||||
|     { | ||||
|         // 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; | ||||
|         return false; | ||||
|     } | ||||
|      | ||||
|     // Stop if the player is still stuck. | ||||
|     if (AntiStickIsStuck(client) > -1) | ||||
|     // 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) | ||||
|     { | ||||
|         return Plugin_Continue; | ||||
|         return false; | ||||
|     } | ||||
|      | ||||
|     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; | ||||
| } | ||||
|          | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          commands.inc | ||||
|  *  Type:          Core | ||||
| @@ -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; | ||||
| }*/ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          config.inc | ||||
|  *  Type:          Core | ||||
| @@ -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."  | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          cookies.inc | ||||
|  *  Type:          Module | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          cvars.inc | ||||
|  *  Type:          Core | ||||
| @@ -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: \", \"]"); | ||||
|      | ||||
|      | ||||
| @@ -385,8 +388,9 @@ 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]                        =    CreateConVar("zr_antistick",               "1",                    "Automatically unstick players when stuck within each others' collision hull."); | ||||
|     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) | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          damage.inc | ||||
|  *  Type:          Core | ||||
| @@ -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 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 cvar for this team is disabled, then stop. | ||||
|     if (!blocksuicide) | ||||
|     // If client is a human, and suicide intercept is disabled for humans, then let command go. | ||||
|     if (InfectIsClientHuman(client) && !suicidehuman) | ||||
|     { | ||||
|         return Plugin_Continue; | ||||
|     } | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          downloads.inc | ||||
|  *  Type:          Core | ||||
| @@ -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) | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          event.inc | ||||
|  *  Type:          Core | ||||
| @@ -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); | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          global.inc | ||||
|  *  Type:          Core | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          hitgroup.inc | ||||
|  *  Type:          Core | ||||
| @@ -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. | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          infect.inc | ||||
|  *  Type:          Core | ||||
| @@ -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. | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          jumpboost.inc | ||||
|  *  Type:          Module | ||||
| @@ -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. | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          knockback.inc | ||||
|  *  Type:          Module | ||||
| @@ -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); | ||||
| @@ -198,15 +198,4 @@ 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); | ||||
| } | ||||
| } | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          log.h.inc | ||||
|  *  Type:          Core | ||||
| @@ -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, | ||||
| } | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          log.inc | ||||
|  *  Type:          Core | ||||
| @@ -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; | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          menu.inc | ||||
|  *  Type:          Core | ||||
| @@ -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; | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          models.inc | ||||
|  *  Type:          Core | ||||
| @@ -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); | ||||
| } | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          napalm.inc | ||||
|  *  Type:          Module  | ||||
| @@ -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); | ||||
| } | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          overlays.inc | ||||
|  *  Type:          Core | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          apply.inc | ||||
|  *  Type:          Core | ||||
| @@ -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; | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          attributes.inc | ||||
|  *  Type:          Core | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:        classcommands.inc | ||||
|  *  Type:        Core  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          classevents.inc | ||||
|  *  Type:          Core | ||||
| @@ -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 | ||||
|         { | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          classmenus.inc | ||||
|  *  Type:          Core | ||||
| @@ -384,7 +384,7 @@ public ClassTeamSelectHandle(Handle:menu, MenuAction:action, client, slot) | ||||
|         { | ||||
|             if (slot == MenuCancel_ExitBack) | ||||
|             { | ||||
|                 ZRAdminMenu(client); | ||||
|                 ZAdminMenu(client); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          clientalpha.inc | ||||
|  *  Type:          Core | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          clientoverlays.inc | ||||
|  *  Type:          Core  | ||||
| @@ -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. | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          filtertools.inc | ||||
|  *  Type:          Core  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          healthregen.inc | ||||
|  *  Type:          Core  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          playerclasses.inc | ||||
|  *  Type:          Core  | ||||
| @@ -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); | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          respawn.inc | ||||
|  *  Type:          Module  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          roundend.inc | ||||
|  *  Type:          Core | ||||
| @@ -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); | ||||
|      | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          roundstart.inc | ||||
|  *  Type:          Core | ||||
| @@ -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. | ||||
|  */ | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          sayhooks.inc | ||||
|  *  Type:          Core | ||||
| @@ -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); | ||||
| } | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          ambientsounds.inc | ||||
|  *  Type:          Core  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          soundeffects.inc | ||||
|  *  Type:          Core  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          zombiesounds.inc | ||||
|  *  Type:          Core  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          spawnprotect.inc | ||||
|  *  Type:          Module | ||||
| @@ -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)); | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          steamidcache.inc | ||||
|  *  Type:          Core | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          tools.inc | ||||
|  *  Type:          Core | ||||
| @@ -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"); | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          tools_functions.inc | ||||
|  *  Type:          Core | ||||
| @@ -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]; | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          translation.inc | ||||
|  *  Type:          Core | ||||
| @@ -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); | ||||
| } | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          ragdoll.inc | ||||
|  *  Type:          Module | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          visualambience.inc | ||||
|  *  Type:          Module | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          visualeffects.inc | ||||
|  *  Type:          Module | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          menu_weapons.inc | ||||
|  *  Type:          Core | ||||
| @@ -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]))); | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          restrict.inc | ||||
|  *  Type:          Core | ||||
| @@ -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); | ||||
|      | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          weaponalpha.inc | ||||
|  *  Type:          Core  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          weaponammo.inc | ||||
|  *  Type:          Core  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          weapons.inc | ||||
|  *  Type:          Core  | ||||
| @@ -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. | ||||
|  *  | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          zmarket.inc | ||||
|  *  Type:          Module | ||||
| @@ -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) | ||||
|     // 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 + 1; x++) | ||||
|     { | ||||
|         g_hZMarketAutoRebuyCookie = RegClientCookie(ZMARKET_COOKIE_AUTOREBUY, "The toggle state of auto-rebuy.", CookieAccess_Public); | ||||
|         // 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); | ||||
|          | ||||
|         decl String:rebuycookiename[32]; | ||||
|         decl String:rebuycookiedesc[64]; | ||||
|          | ||||
|         // x = Weapon slot. | ||||
|         for (new x = 0; x < WEAPONS_SLOTS_MAX; 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); | ||||
|         } | ||||
|         // Register client cookie. | ||||
|         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)); | ||||
| } | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          zadmin.inc | ||||
|  *  Type:          Core | ||||
| @@ -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); | ||||
|         } | ||||
|     } | ||||
|      | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          zcookies.inc | ||||
|  *  Type:          Module | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          zhp.inc | ||||
|  *  Type:          Module | ||||
| @@ -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); | ||||
| } | ||||
|  | ||||
| /** | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          zombiereloaded.inc | ||||
|  *  Type:          Core  | ||||
| @@ -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)) | ||||
|     { | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          zspawn.inc | ||||
|  *  Type:          Module | ||||
| @@ -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; | ||||
| @@ -177,60 +188,78 @@ bool:ZSpawnClient(client) | ||||
|     // If client isn't on a team, then stop. | ||||
|     if (!ZRIsClientOnTeam(client)) | ||||
|     { | ||||
|         // Tell client the command may only be used when on a team. | ||||
|         TranslationPrintToChat(client, "Must be on team"); | ||||
|         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)) | ||||
|     { | ||||
|         // Tell client the command may only be used when dead. | ||||
|         TranslationPrintToChat(client, "Must be dead"); | ||||
|         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; | ||||
|     } | ||||
|      | ||||
|     // 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]); | ||||
|     new bool:teamzombie; | ||||
|      | ||||
|     // Block is the time limit is up. | ||||
|     new bool:zspawntimelimit = GetConVarBool(g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT]); | ||||
|     if (zspawntimelimit) | ||||
|     if (!force) | ||||
|     { | ||||
|         if (tZSpawn == INVALID_HANDLE) | ||||
|         // Check if zspawn override is enabled, and if so get overidden value. | ||||
|         new bool:teamoverride = GetConVarBool(g_hCvarsList[CVAR_ZSPAWN_TEAM_OVERRIDE]); | ||||
|         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]); | ||||
|         if (zspawntimelimit) | ||||
|         { | ||||
|             new zspawntimelimitzombie = GetConVarInt(g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT_ZOMBIE]); | ||||
|             switch(zspawntimelimitzombie) | ||||
|             if (tZSpawn == INVALID_HANDLE) | ||||
|             { | ||||
|                 case -1: | ||||
|                 new zspawntimelimitzombie = GetConVarInt(g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT_ZOMBIE]); | ||||
|                 switch(zspawntimelimitzombie) | ||||
|                 { | ||||
|                     // Get timelimit | ||||
|                     new Float:zspawntime = GetConVarFloat(g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT_TIME]); | ||||
|                      | ||||
|                     // Tell client the timelimit for this command has expired. | ||||
|                     TranslationPrintToChat(client, "ZSpawn timelimit", RoundToNearest(zspawntime)); | ||||
|                     return false; | ||||
|                 } | ||||
|                 case 0: | ||||
|                 { | ||||
|                     teamzombie = false; | ||||
|                 } | ||||
|                 case 1: | ||||
|                 { | ||||
|                     teamzombie = true; | ||||
|                     case -1: | ||||
|                     { | ||||
|                         // Get timelimit | ||||
|                         new Float:zspawntime = GetConVarFloat(g_hCvarsList[CVAR_ZSPAWN_TIMELIMIT_TIME]); | ||||
|                          | ||||
|                         // Tell client the timelimit for this command has expired. | ||||
|                         TranslationPrintToChat(client, "ZSpawn timelimit", RoundToNearest(zspawntime)); | ||||
|                         return false; | ||||
|                     } | ||||
|                     case 0: | ||||
|                     { | ||||
|                         teamzombie = false; | ||||
|                     } | ||||
|                     case 1: | ||||
|                     { | ||||
|                         teamzombie = true; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     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. | ||||
|  *  | ||||
|   | ||||
							
								
								
									
										156
									
								
								src/zr/ztele.inc
									
									
									
									
									
								
							
							
						
						
									
										156
									
								
								src/zr/ztele.inc
									
									
									
									
									
								
							| @@ -1,7 +1,7 @@ | ||||
| /* | ||||
|  * ============================================================================ | ||||
|  * | ||||
|  *   Zombie:Reloaded | ||||
|  *  Zombie:Reloaded | ||||
|  * | ||||
|  *  File:          ztele.inc | ||||
|  *  Type:          Module | ||||
| @@ -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); | ||||
| @@ -174,19 +179,26 @@ bool:ZTeleClient(client) | ||||
|     // If teleport is already in progress, then stop. | ||||
|     if (tZTele[client] != INVALID_HANDLE) | ||||
|     { | ||||
|         TranslationPrintToChat(client, "ZTele in progress"); | ||||
|         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. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user