Guest User

maniek motion

a guest
Aug 20th, 2019
143
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 139.48 KB | None | 0 0
  1. /*
  2.  
  3. Title:
  4. * NadeModes
  5.  
  6. Description:
  7. * Adds more modes to the classic grenades, it is similar with
  8. * some of the weapons in Half-Life [Trip, Satchel, Normal Grenade]
  9.  
  10. Home page:
  11. * http://forums.alliedmods.net/showthread.php?t=175632
  12.  
  13. Terms:
  14. * Copyright (C) 2012 OT
  15.  
  16. * This program is free software: you can redistribute it and/or modify
  17. * it under the terms of the GNU General Public License as published by
  18. * the Free Software Foundation, either version 3 of the License, or
  19. * (at your option) any later version.
  20.  
  21. * This program is distributed in the hope that it will be useful,
  22. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  23. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  24. * GNU General Public License for more details.
  25.  
  26. * You should have received a copy of the GNU General Public License
  27. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  28.  
  29. */
  30.  
  31. #include <amxmodx>
  32. #include <amxmisc>
  33. #include <cstrike>
  34. #include <engine>
  35. #include <fakemeta>
  36. #include <hamsandwich>
  37. #include <xs>
  38.  
  39. #define VERSION "11.2"
  40.  
  41. /* -------------------------------
  42. [Plugin Link]
  43. ------------------------------- */
  44. /*
  45. * https://forums.alliedmods.net/showthread.php?t=75322&page=21
  46. */
  47.  
  48. /* -------------------------------
  49. [Changelog]
  50. ------------------------------- */
  51. /*
  52. Version 3.0
  53. - Initial release.
  54.  
  55. Version 3.1
  56. - Changing an item on the second page will rebuild the menu and display on the second page.
  57.  
  58. Version 4
  59. - Improve to the trip grenade and sounds
  60.  
  61. Version 5
  62. - Full grenade support + satchel charge mode
  63.  
  64. Version 5.2
  65. - Automatic save system + team bug fix
  66.  
  67. Version 5.5
  68. - Nade choose system
  69.  
  70. Version 5.7
  71. - New menu system
  72.  
  73. Version 5.8
  74. - Added compatibility with Biohazzard/Zombie Plague Mod. The nades will be removed when a player is turned into a zombie
  75.  
  76. Version 5.9
  77. - Added new cvar for teamplay the plugin won't follow friendlyfire anymore, bot support
  78.  
  79. Version 5.9b
  80. - Bug fix -> zombie
  81.  
  82. Version 6.0
  83. - Nade damage control (all of them)
  84.  
  85. Version 6.0b
  86. - Nademodes invalid player bug fix + admin spectator bug fix
  87.  
  88. Version 6.0c
  89. - Nademodes grenade disapearing bug fix + new feature the plugin can be seen on what servers is played on.
  90.  
  91. Version 7.0
  92. - Nademodes limit added, now plugin works with ghw model change, CSX module removed + laser engine bug fix + less cpu usage
  93.  
  94. Version 7.0a
  95. - Nademodes invalid entity bug fix, nademodes remove counter bug fix
  96.  
  97. Version 7.0aa
  98. - Nademodes invalid entity bug fix in play_sound
  99.  
  100. Version 7.0b
  101. - Nademodes code change, now plugin relies on more modules! (More efficient), change part of the code (no more hardcodes)
  102.  
  103. Version 7.5
  104. - Nademodes smart plugin effects mode added! Changed damage system! Changed primary menu! Now we have stuff organised! Added Homing grenade!
  105.  
  106. Version 8.0
  107. - Nademodes added hit points system! Made sec explo more customizable!
  108.  
  109. Version 8.5
  110. - Fixed all known bugs, added client mode selection!
  111.  
  112. Version 8.6
  113. - Fixed menu drunk cvar bug, and forward drunk bug
  114.  
  115. Version 8.7
  116. - Added new cvar to fix the SVC_BAD errors -> use this only if the clients report that problem!!!
  117.  
  118. Version 8.8
  119. - New grenade shot detection method (supports walls now), HP system for other nades modes (NORMAL,IMPACT,HOMING)
  120.  
  121. Version 8.9
  122. - Added bot support for trip nades
  123.  
  124. Version 9.0
  125. - Animation and sound for grenades that have been shot, effects when grenades desintegrate, hp system more configurable
  126.  
  127. Version 9.1
  128. - Shot method a little different now, supports shot through all entities, added penetration
  129.  
  130. Version 9.2
  131. - Fixed the smoke grenade block problem, fixed secondary explosions server crash
  132.  
  133. Version 9.3
  134. - Some small code tweaks, made some predefined values for things that you would like to modify
  135.  
  136. Version 9.4
  137. - Last adjustments
  138.  
  139. Version 9.5
  140. - Final fixes and some security mesures, final suggestions, removed update owner cvar (unfortunately nothing else could have been done)
  141.  
  142. Version 9.6
  143. - Team bug fix, Owner set bug fix, Homing now follows team play, Damage system bug fix
  144.  
  145. Version 9.61
  146. - Small unregistration bug fix!
  147.  
  148. Version 9.62
  149. - Menu position fix, added some small conditions in damage detection, also made the nades that have exploded be ignored
  150.  
  151. Version 9.63
  152. - Fixed the error within the is_grenade native.
  153.  
  154. Version 9.7
  155. - Added more configurations to the MOTION and PROXIMITY modes both support line of sight options, also added delay between explosions for SATCHEL
  156.  
  157. Version 9.8
  158. - Added new type of effect transmition mode: "Low Bandwidth Mode" - conserve bandwidth as much as possible (useful for servers with many many grenades)
  159.  
  160. Version 9.9
  161. - Fixed the way the cone angle was calculated, optimized parts of the plugin, added metric and inch unit conversion in the menu for better understanding
  162.  
  163. Version 10
  164. - Optimized the code, added possibility to remove the normal grenade mode, removed amx_nms feature due to "Info string length exceded" errors, added a special forward for compatibility issues, added support for monstermod
  165.  
  166. Version 11
  167. - Changemode bug fix, disappearing bug fix, zombie round start bug fix, made menus more understandable, mode switch when limit reached, sound for proximity grenades, smart angle twist for trip grenades, option with remove grenades if player dies, post forward, memory/CPU optimizations
  168.  
  169. Version 11.1
  170. - Cvar cache fix made all options 0, is_alive error
  171.  
  172. Version 11.2
  173. - C4 remove bug fix
  174. */
  175.  
  176. /* -------------------------------
  177. [Thanks to]
  178. ------------------------------- */
  179. /*
  180. - Grenade Modes by Nomexous
  181. - Shoot Grenades by joaquimandrade
  182. - Testers
  183. - Translators
  184. - Everyone who enjoys having fun with grenades.
  185. */
  186.  
  187. /* -------------------------------
  188. [To do]
  189. * Recheck cvar system reload
  190. * Add is player statement
  191. ------------------------------- */
  192.  
  193. new const ACTIVATE[] = "weapons/mine_activate.wav"
  194. new const DEPLOY[] = "weapons/mine_deploy.wav"
  195. new const CHARGE[] = "weapons/mine_charge.wav"
  196. new const GEIGER[] = "player/geiger1.wav"
  197. new const PING[] = "turret/tu_ping.wav"
  198. new const BUTTON[] = "buttons/button9.wav"
  199.  
  200. new const SOUND_HIT[5][] = { "debris/bustmetal1.wav", "debris/bustmetal2.wav", "debris/metal1.wav", "debris/metal2.wav", "debris/metal3.wav" }
  201.  
  202. // Defines that can be modified
  203. #define MAX_PLAYERS 32
  204.  
  205. #define ADMIN_ACCESS ADMIN_RCON
  206.  
  207. #define NOTEAM_RGB_R_COLOR 0
  208. #define NOTEAM_RGB_G_COLOR 214
  209. #define NOTEAM_RGB_B_COLOR 198
  210.  
  211. #define TEAMCT_RGB_R_COLOR 0
  212. #define TEAMCT_RGB_G_COLOR 0
  213. #define TEAMCT_RGB_B_COLOR 255
  214.  
  215. #define TEAMTE_RGB_R_COLOR 255
  216. #define TEAMTE_RGB_G_COLOR 0
  217. #define TEAMTE_RGB_B_COLOR 0
  218.  
  219. #define DELAY_ADDED_TO_USE 0.2
  220.  
  221. // Some defines, I suggest not modifying these! Only if you understand the code completely!
  222. #define RING_SIZE_CONSTANT_PROXIMITY 2.1
  223. #define RING_SIZE_CONSTANT_MOTION 9.27
  224.  
  225. #define SETTINGS_REFRESH_TIME 2.0
  226.  
  227. #define OFFSET_WEAPONID 43
  228. #define EXTRAOFFSET_WEAPONS 4
  229.  
  230. #define SMART_DISTANCE_LINE_PVS 800.0
  231. #define SMART_RADIUS_RING_SHOW 1500.0
  232. #define CONE_DROP_ANGLE_COSINUS -0.30
  233. #define EXTRALENGTH_VECTOR 200.0
  234.  
  235. #define SHOT_PENETRATION_DISTANCE 4.0
  236. #define SHOT_PENETRATION_READD_TIMES 20
  237. #define SHOT_SECOND_TEST_RADIUS 10.0
  238. #define SHOT_KNIFE_REAL_RADIUS 6.0
  239. #define SHOT_ENTITY_QUEUE_LENGTH 5
  240.  
  241. #define BOT_MIN_DISTANCE_ATTACH 400.0
  242. #define BOT_WALL_MIN_COSINUS 0.866026
  243. #define BOT_MIN_HEIGHT_ALLOW 18.0
  244. #define BOT_MIN_CROUCH_HEIGHT_ALLOW 10.0
  245. #define BOT_MAX_HEIGHT_ALLOW 55.0
  246. #define BOT_FORCE_CROUCH_HEIGHT_CONST 76.0
  247.  
  248. #define CVAR_STRING_ALLOC 100
  249. #define CVAR_MAX_ASSIGNED_VALUES 30
  250. #define CVAR_MAX_STRING_LENGTH 10
  251.  
  252. #define DMG_CS_KNIFE_BULLETS (1 << 12 | 1 << 0)
  253.  
  254. #define CONE_CALC_ANGLE_MAX 75.0
  255. #define CONE_CALC_ANGLE_MIN 2.0
  256. #define CONE_CALC_DISTANCE_MAX 400.0
  257. #define CONE_CALC_DISTANCE_MIN 10000.0
  258. #define CONE_BASE_RADIUS 200.0
  259.  
  260. // Macros, made specially to make the code easier to read
  261. #define CONVERT_TO_METERS(%0) (%0 * 0.0254)
  262.  
  263. #define get_option(%1) ccvars[%1]
  264. #define toggle_option(%1) set_pcvar_num(pcvars[%1], !get_pcvar_num(pcvars[%1]))
  265. #define get_option_float(%1) Float:ccvars[%1]
  266. #define set_option_float(%1,%2) set_pcvar_float(pcvars[%1], %2)
  267.  
  268. #define is_player_alive(%1) ((cl_is_alive & (1<<%1)) && (0 < %1 <= g_maxplayers))
  269.  
  270. #define is_grenade_c4(%1) (get_pdata_int(%1, 96) & (1<<8)) // 96 is the C4 offset
  271.  
  272. #define make_explode(%1) entity_set_float(%1, EV_FL_dmgtime, 0.0)
  273. #define grenade_can_be_used(%1) (get_option(OPTION_NADES_IN_EFFECT) & NADE_BIT[%1]) ? 1 : 0
  274. #define allow_grenade_explode(%1) (get_gametime() < entity_get_float(%1, EV_FL_fuser2)) ? 0 : 1
  275. #define get_grenade_type(%1) NadeType:entity_get_int(%1, EV_INT_iuser1)
  276. #define set_grenade_allow_explode(%1,%2) entity_set_float(%1, EV_FL_fuser2, get_gametime() + %2)
  277. #define delay_explosion(%1) entity_set_float(%1, EV_FL_dmgtime, get_gametime() + get_option_float(OPTION_EXPLOSION_DELAY_TIME))
  278. #define get_trip_grenade_end_origin(%1,%2) entity_get_vector(%1, EV_VEC_vuser1, %2)
  279. #define set_trip_grenade_end_origin(%1,%2) entity_set_vector(%1, EV_VEC_vuser1, %2)
  280. #define set_trip_grenade_fly_velocity(%1,%2) entity_set_vector(%1, EV_VEC_vuser2, %2)
  281. #define get_trip_grenade_fly_velocity(%1,%2) entity_get_vector(%1, EV_VEC_vuser2, %2)
  282. #define get_trip_grenade_middle_origin(%1,%2) entity_get_vector(%1, EV_VEC_vuser3, %2)
  283. #define set_trip_grenade_middle_origin(%1,%2) entity_set_vector(%1, EV_VEC_vuser3, %2)
  284. #define get_trip_grenade_arm_time(%1) entity_get_float(%1, EV_FL_fuser1)
  285. #define set_trip_grenade_arm_time(%1,%2) entity_set_float(%1, EV_FL_fuser1, get_gametime() + %2)
  286. #define set_trip_grenade_attached_to(%1,%2) entity_set_int(%1, EV_INT_iuser4, %2)
  287. #define get_trip_grenade_attached_to(%1) entity_get_int(%1, EV_INT_iuser4)
  288. #define get_trip_grenade_mode(%1) TripNadeMode:entity_get_int(%1, EV_INT_iuser3)
  289. #define set_trip_grenade_mode(%1,%2) entity_set_int(%1, EV_INT_iuser3, _:%2)
  290. #define play_sound(%1,%2) (get_option(OPTION_PLAY_SOUNDS)) ? emit_sound(%1, CHAN_WEAPON, %2, 1.0, ATTN_STATIC, 0, PITCH_NORM) : 0
  291. #define play_sound2(%1,%2) (get_option(OPTION_PLAY_SOUNDS)) ? emit_sound(%1, CHAN_ITEM, %2, 1.0, ATTN_STATIC, 0, PITCH_NORM) : 0
  292. #define refresh_can_use_nade(%1,%2) get_enabled_modes(%1,%2) ? (cl_can_use_nade[%2] |= (1<<%1)) : (cl_can_use_nade[%2] &= ~(1<<%1))
  293.  
  294. // Enums! First time I've ever used them. These should make the code infinitely easier to read.
  295. enum NadeRace
  296. {
  297. GRENADE_EXPLOSIVE = 0,
  298. GRENADE_FLASHBANG,
  299. GRENADE_SMOKEGREN,
  300. }
  301.  
  302. new const NADE_MODEL[][] =
  303. {
  304. "w_hegrenade.mdl",
  305. "w_flashbang.mdl",
  306. "w_smokegrenade.mdl"
  307. }
  308.  
  309. new const NADE_WPID[NadeRace] =
  310. {
  311. CSW_HEGRENADE,
  312. CSW_FLASHBANG,
  313. CSW_SMOKEGRENADE
  314. }
  315.  
  316. new const NADE_BIT[NadeRace] =
  317. {
  318. (1<<0),
  319. (1<<1),
  320. (1<<2)
  321. }
  322.  
  323. enum NadeType
  324. {
  325. NADE_DUD = -1,
  326. NADE_NORMAL,
  327. NADE_PROXIMITY,
  328. NADE_IMPACT,
  329. NADE_TRIP,
  330. NADE_MOTION,
  331. NADE_SATCHEL,
  332. NADE_HOMING
  333. }
  334.  
  335. new UNCOUNTABLE_NADE_MODES = ((1 << (_:NADE_DUD + 1)) | (1 << (_:NADE_NORMAL + 1)) | (1 << (_:NADE_IMPACT + 1)) | (1 << (_:NADE_HOMING + 1)))
  336. new const NADE_DONT_COUNT = (1<<31)
  337.  
  338. enum Fward
  339. {
  340. FWD_NONE_ACTIVE = 0,
  341. FWD_CMDSTART = (1<<0),
  342. FWD_THINK = (1<<1),
  343. FWD_SETMODEL = (1<<2),
  344. FWD_TOUCH = (1<<3),
  345. FWD_SEC_EXPLODE = (1<<4),
  346. FWD_TAKEDAMAGE = (1<<5),
  347. FWD_THINK_POST = (1<<6),
  348. FWD_MESSAGE = (1<<7),
  349. FWD_HPSYSTEM = (1<<8)
  350. }
  351.  
  352. enum ZmFunc
  353. {
  354. ZM_NO_ZM_ACTIVE = 0,
  355. ZM_ZM_ACTIVE = 1,
  356. ZM_CAN_THINK = 2,
  357. ZM_DO_ALL = 3
  358. }
  359.  
  360. enum TripNadeMode
  361. {
  362. TRIP_NOT_ATTACHED = 0,
  363. TRIP_ATTACHED,
  364. TRIP_WAITING,
  365. TRIP_SCANNING,
  366. TRIP_SHOULD_DETONATE,
  367. TRIP_DETONATED
  368. }
  369.  
  370. enum Option
  371. {
  372. // Primary Off/On cvar
  373. OPTION_ENABLE_NADE_MODES,
  374.  
  375. // General settings
  376. OPTION_FRIENDLY_FIRE,
  377. OPTION_BOT_ALLOW,
  378. OPTION_NADES_IN_EFFECT,
  379. OPTION_REMOVE_IF_DIES,
  380. OPTION_SUPPRESS_FITH,
  381. OPTION_DISPLAY_MODE_ON_DRAW,
  382. OPTION_PLAY_SOUNDS,
  383. OPTION_RESET_MODE_ON_THROW,
  384. OPTION_RESOURCE_USE,
  385. OPTION_MSG_SVC_BAD,
  386. OPTION_TEAM_PLAY,
  387. OPTION_AFFECT_OWNER,
  388. OPTION_UNITS_SYSTEM,
  389. OPTION_MONSTERMOD_SUPPORT,
  390.  
  391. // Grenade modes control menu
  392. OPTION_NORMAL_ENABLED,
  393. OPTION_PROXIMITY_ENABLED,
  394. OPTION_IMPACT_ENABLED,
  395. OPTION_TRIP_ENABLED,
  396. OPTION_MOTION_ENABLED,
  397. OPTION_SATCHEL_ENABLED,
  398. OPTION_HOMING_ENABLED,
  399.  
  400. OPTION_REACT_TRIP_G,
  401. OPTION_REACT_TRIP_F,
  402. OPTION_REACT_TRIP_S,
  403.  
  404. OPTION_PROXIMITY_LOS,
  405. OPTION_MOTION_LOS,
  406. OPTION_SATCHEL_DELAY,
  407.  
  408. // Limit settings
  409. OPTION_LIMIT_SYSTEM,
  410.  
  411. OPTION_LIMIT_PROXIMITY,
  412. OPTION_LIMIT_TRIP,
  413. OPTION_LIMIT_MOTION,
  414. OPTION_LIMIT_SATCHEL,
  415.  
  416. OPTION_INFINITE_GRENADES,
  417. OPTION_INFINITE_FLASHES,
  418. OPTION_INFINITE_SMOKES,
  419.  
  420. // Hitpoints system settings
  421. OPTION_MATERIAL_SYSTEM,
  422.  
  423. OPTION_SEC_EXPLO_AFFECT,
  424.  
  425. OPTION_HITPOINT_NORMAL,
  426. OPTION_HITPOINT_PROXIMITY,
  427. OPTION_HITPOINT_IMPACT,
  428. OPTION_HITPOINT_TRIP,
  429. OPTION_HITPOINT_MOTION,
  430. OPTION_HITPOINT_SATCHEL,
  431. OPTION_HITPOINT_HOMING,
  432.  
  433. OPTION_HITPOINT_DEATH,
  434. OPTION_HITPOINT_FF,
  435. OPTION_HITPOINT_INTER_DMG,
  436.  
  437. // Damage settings
  438. OPTION_DAMAGE_SYSTEM,
  439.  
  440. OPTION_DMG_THROUGH_WALL,
  441. OPTION_DMG_SELF,
  442. OPTION_DMG_TEAMMATES,
  443.  
  444. OPTION_DMG_NORMAL,
  445. OPTION_DMG_PROXIMITY,
  446. OPTION_DMG_IMPACT,
  447. OPTION_DMG_TRIP,
  448. OPTION_DMG_MOTION,
  449. OPTION_DMG_SATCHEL,
  450. OPTION_DMG_HOMING,
  451.  
  452. // Internal functional settings
  453. OPTION_EXPLOSION_DELAY_TIME,
  454. OPTION_RADIUS_SEC_EXPLOSION,
  455.  
  456. OPTION_ARM_TIME_TRIP,
  457. OPTION_ARM_TIME_MOTION,
  458. OPTION_ARM_TIME_SATCHEL,
  459. OPTION_ARM_TIME_PROXIMITY,
  460.  
  461. OPTION_TRIP_DETECT_DISTANCE,
  462. OPTION_TRIP_FLY_SPEED,
  463.  
  464. OPTION_RADIUS_PROXIMITY,
  465. OPTION_RADIUS_MOTION,
  466.  
  467. OPTION_HOMING_SCAN_RANGE,
  468. OPTION_HOMING_SUPER_RANGE,
  469. OPTION_HOMING_EXTRATIME,
  470. OPTION_HOMING_SPEED_ADD
  471. }
  472.  
  473. enum OptionType
  474. {
  475. TOPTION_TOGGLE = 1,
  476. TOPTION_CELL,
  477. TOPTION_FLOAT,
  478. }
  479.  
  480. enum TraceHandles
  481. {
  482. TH_LOS,
  483. TH_DMG,
  484. TH_TRIP,
  485. TH_BOT
  486. }
  487.  
  488. // Mod texts that appear when right clicking for mode change
  489. new modetext[][] = { "Normal", "Proximity", "Impact", "Trip laser", "Motion sensor", "Satchel chage", "Homing" }
  490.  
  491. // CFG data [name and file path]
  492. new const CFG_FILE_NAME[] = "nade_modes.cfg"
  493. new CFG_FILE[200]
  494.  
  495. // Current nade mode
  496. new NadeType:mode[MAX_PLAYERS + 1][NadeRace]
  497.  
  498. // Global server variables
  499. new g_maxplayers
  500.  
  501. // Cached client data [bot,alive,weapon,team]
  502. new cl_is_bot = 0
  503. new cl_is_alive = 0
  504. new cl_weapon[MAX_PLAYERS + 1]
  505. new CsTeams:cl_team[MAX_PLAYERS + 1]
  506.  
  507. // Limit system counter/blocker
  508. new cl_counter[MAX_PLAYERS + 1][NadeRace][NadeType]
  509. new cl_can_use_nade[NadeRace]
  510.  
  511. // Next +use time, used in satchel charge nade types when the delay explosion is set
  512. new Float:cl_nextusetime[MAX_PLAYERS + 1]
  513.  
  514. // Special queue used in penetration detection of grenades
  515. new cl_entity_queue[MAX_PLAYERS + 1][SHOT_ENTITY_QUEUE_LENGTH]
  516.  
  517. // Trace handles used in different situations
  518. new g_ptrace[TraceHandles]
  519.  
  520. // Hp system global variables [enable/disable, global trace attack class registration]
  521. new g_check_hpsystem = -1
  522. new Trie:trace_attack_reg_class
  523.  
  524. // First enabled modes, so that the plugin knows where to start
  525. new NadeType:g_firstenabledmode[NadeRace]
  526.  
  527. // Plugin functionality enable/disable mechanism
  528. new Fward:bs_forward_collection = FWD_NONE_ACTIVE
  529.  
  530. // Menu variables
  531. new settingsmenu[MAX_PLAYERS + 1] // Settings menu handler
  532. new cvar_menu_pos[MAX_PLAYERS + 1] // Cvar menu handler
  533. new callbacks[2] // Settings menu callbacks
  534.  
  535. // Cvars [Options]
  536. new OptionType:option_type[Option]
  537. new Array:option_value[Option]
  538. new pcvars[Option] // Cvar pointers
  539. new ccvars[Option] // Cached cvars
  540.  
  541. // Mod dependent variables [CZ/ZM]
  542. new ZmFunc:g_zombie_mod
  543. new g_botquota
  544.  
  545. // Forwards
  546. new g_FW_property, g_PFW_property
  547.  
  548. // Messages
  549. new beampoint
  550. new shockwave
  551. new nadebits
  552.  
  553.  
  554.  
  555. /* -------------------------------
  556. [Plugin Start]
  557. ------------------------------- */
  558. public plugin_precache()
  559. {
  560. // Registered before all the nade plugins
  561. RegisterHam(Ham_Think, "grenade", "fw_think")
  562. RegisterHam(Ham_Think, "grenade", "fw_track_explosion")
  563. RegisterHam(Ham_Think, "grenade", "fw_think_post", 1)
  564.  
  565. // Trace attack register trie
  566. trace_attack_reg_class = TrieCreate()
  567.  
  568. // We register this here to track shots, it is also important
  569. register_forward(FM_Spawn, "fw_spawn", 1)
  570.  
  571. beampoint = precache_model("sprites/laserbeam.spr")
  572. shockwave = precache_model("sprites/shockwave.spr")
  573. nadebits = precache_model("models/chromegibs.mdl")
  574.  
  575. precache_sound(ACTIVATE)
  576. precache_sound(CHARGE)
  577. precache_sound(DEPLOY)
  578. precache_sound(GEIGER)
  579. precache_sound(PING)
  580. precache_sound(BUTTON)
  581.  
  582. for (new i=0;i<5;i++)
  583. {
  584. precache_sound(SOUND_HIT[i])
  585. }
  586. }
  587.  
  588. public plugin_init()
  589. {
  590. // Plugin registration (normal and net)
  591. register_plugin("NadeModes", VERSION, "Nomexous & OT")
  592. register_cvar("nademodes_version", VERSION, FCVAR_SERVER|FCVAR_SPONLY)
  593.  
  594. // Commands
  595. register_clcmd("amx_nade_mode_menu", "conjure_menu", ADMIN_ACCESS, "Shows settings menu for grenade modes.")
  596. register_clcmd("amx_nmm", "conjure_menu", ADMIN_ACCESS, "Shows settings menu for grenade modes.")
  597.  
  598. register_clcmd("say /nadehelp", "conjure_help", -1, "Shows help for grenade modes.")
  599. register_clcmd("say_team /nadehelp", "conjure_help", -1, "Shows help for grenade modes.")
  600.  
  601. // General Settings Options
  602. pcvars[OPTION_FRIENDLY_FIRE] = get_cvar_pointer("mp_friendlyfire")
  603.  
  604. register_option(OPTION_ENABLE_NADE_MODES, "nademodes_enable", "1")
  605. register_option(OPTION_NADES_IN_EFFECT, "nademodes_nades_in_effect", "7", TOPTION_CELL)
  606. register_option(OPTION_MSG_SVC_BAD, "nademodes_svc_bad_error_fix", "0")
  607.  
  608. register_option(OPTION_PLAY_SOUNDS, "nademodes_play_grenade_sounds", "1")
  609. register_option(OPTION_RESOURCE_USE, "nademodes_effects", "2", TOPTION_CELL)
  610.  
  611. register_option(OPTION_DISPLAY_MODE_ON_DRAW, "nademodes_display_mode_on_draw", "1")
  612. register_option(OPTION_RESET_MODE_ON_THROW, "nademodes_reset_mode_on_throw", "0")
  613. register_option(OPTION_SUPPRESS_FITH, "nademodes_suppress_fire_in_the_hole", "0")
  614.  
  615. register_option(OPTION_BOT_ALLOW, "nademodes_bot_support", "1")
  616.  
  617. register_option(OPTION_REMOVE_IF_DIES, "nademodes_remove_if_player_dies", "0")
  618. register_option(OPTION_AFFECT_OWNER, "nademodes_affect_owner", "1")
  619. register_option(OPTION_TEAM_PLAY, "nademodes_team_play", "1")
  620. register_option(OPTION_UNITS_SYSTEM, "nademodes_unit_system", "1")
  621.  
  622. register_option(OPTION_MONSTERMOD_SUPPORT, "nademodes_monstermod_support", "0")
  623.  
  624. // General Settings Option Values
  625. register_option_value(OPTION_RESOURCE_USE, "0;1;2;3")
  626. register_option_value(OPTION_NADES_IN_EFFECT, "0;1;2;3;4;5;6;7")
  627.  
  628. // Mode Settings Options
  629. register_option(OPTION_NORMAL_ENABLED, "nademodes_normal_enabled", "1")
  630. register_option(OPTION_PROXIMITY_ENABLED, "nademodes_proximity_enabled", "1")
  631. register_option(OPTION_IMPACT_ENABLED, "nademodes_impact_enabled", "1")
  632. register_option(OPTION_TRIP_ENABLED, "nademodes_trip_enabled", "1")
  633. register_option(OPTION_MOTION_ENABLED, "nademodes_motion_enabled", "1")
  634. register_option(OPTION_SATCHEL_ENABLED, "nademodes_satchel_enabled", "1")
  635. register_option(OPTION_HOMING_ENABLED, "nademodes_homing_enabled", "1")
  636.  
  637. register_option(OPTION_REACT_TRIP_G, "nademodes_grenade_react", "1")
  638. register_option(OPTION_REACT_TRIP_F, "nademodes_flash_react", "1")
  639. register_option(OPTION_REACT_TRIP_S, "nademodes_smoke_react", "1")
  640.  
  641. register_option(OPTION_PROXIMITY_LOS, "nademodes_proximity_fov", "0")
  642. register_option(OPTION_MOTION_LOS, "nademodes_motion_fov", "1")
  643. register_option(OPTION_SATCHEL_DELAY, "nademodes_satchel_delay", "0")
  644.  
  645. // Limit Settings Options
  646. register_option(OPTION_LIMIT_SYSTEM, "nademodes_limit_system", "2", TOPTION_CELL)
  647. register_option(OPTION_LIMIT_PROXIMITY, "nademodes_proximity_limit", "5", TOPTION_CELL)
  648. register_option(OPTION_LIMIT_TRIP, "nademodes_trip_limit", "5", TOPTION_CELL)
  649. register_option(OPTION_LIMIT_MOTION, "nademodes_motion_limit", "5", TOPTION_CELL)
  650. register_option(OPTION_LIMIT_SATCHEL, "nademodes_satchel_limit", "5", TOPTION_CELL)
  651.  
  652. register_option(OPTION_INFINITE_GRENADES, "nademodes_infinite_grenades", "0")
  653. register_option(OPTION_INFINITE_FLASHES, "nademodes_infinite_flashes", "0")
  654. register_option(OPTION_INFINITE_SMOKES, "nademodes_infinite_smokes", "0")
  655.  
  656. // Limit Settings Option Values
  657. register_option_value(OPTION_LIMIT_SYSTEM, "0;1;2")
  658.  
  659. register_option_value(OPTION_LIMIT_PROXIMITY, "0;1;2;3;4;5;6;7;8;9;10;11;12;13;14;15")
  660. register_option_value(OPTION_LIMIT_TRIP, "0;1;2;3;4;5;6;7;8;9;10;11;12;13;14;15")
  661. register_option_value(OPTION_LIMIT_MOTION, "0;1;2;3;4;5;6;7;8;9;10;11;12;13;14;15")
  662. register_option_value(OPTION_LIMIT_SATCHEL, "0;1;2;3;4;5;6;7;8;9;10;11;12;13;14;15")
  663.  
  664. // Hitpoint Options
  665. register_option(OPTION_MATERIAL_SYSTEM, "nademodes_material_system", "0", TOPTION_CELL)
  666. register_option(OPTION_HITPOINT_DEATH, "nademodes_grenade_death","1")
  667.  
  668. register_option(OPTION_SEC_EXPLO_AFFECT, "nademodes_secondary_explosions_mode", "0")
  669.  
  670. register_option(OPTION_HITPOINT_NORMAL, "nademodes_hitpoints_normal", "10", TOPTION_CELL)
  671. register_option(OPTION_HITPOINT_PROXIMITY, "nademodes_hitpoints_proximity", "100", TOPTION_CELL)
  672. register_option(OPTION_HITPOINT_IMPACT, "nademodes_hitpoints_impact", "10", TOPTION_CELL)
  673. register_option(OPTION_HITPOINT_TRIP, "nademodes_hitpoints_trip", "100", TOPTION_CELL)
  674. register_option(OPTION_HITPOINT_MOTION, "nademodes_hitpoints_motion", "100", TOPTION_CELL)
  675. register_option(OPTION_HITPOINT_SATCHEL, "nademodes_hitpoints_satchel", "100", TOPTION_CELL)
  676. register_option(OPTION_HITPOINT_HOMING, "nademodes_hitpoints_homing", "10", TOPTION_CELL)
  677.  
  678. register_option(OPTION_HITPOINT_INTER_DMG, "nademodes_hitpoints_intergrenade_damage", "100", TOPTION_FLOAT)
  679. register_option(OPTION_HITPOINT_FF, "nademodes_hitpoints_friendlyfire_ammount", "50", TOPTION_FLOAT)
  680.  
  681. // Hitpoint Options Values
  682. register_option_value(OPTION_MATERIAL_SYSTEM, "0;1;2")
  683.  
  684. register_option_value(OPTION_HITPOINT_NORMAL, "0;1;10;20;30;40;50;60;70;80;90;100;110;120;130;140;150;175;200;250;300;400;500;750;1000")
  685. register_option_value(OPTION_HITPOINT_PROXIMITY, "0;1;10;20;30;40;50;60;70;80;90;100;110;120;130;140;150;175;200;250;300;400;500;750;1000")
  686. register_option_value(OPTION_HITPOINT_IMPACT, "0;1;10;20;30;40;50;60;70;80;90;100;110;120;130;140;150;175;200;250;300;400;500;750;1000")
  687. register_option_value(OPTION_HITPOINT_TRIP, "0;1;10;20;30;40;50;60;70;80;90;100;110;120;130;140;150;175;200;250;300;400;500;750;1000")
  688. register_option_value(OPTION_HITPOINT_MOTION, "0;1;10;20;30;40;50;60;70;80;90;100;110;120;130;140;150;175;200;250;300;400;500;750;1000")
  689. register_option_value(OPTION_HITPOINT_SATCHEL, "0;1;10;20;30;40;50;60;70;80;90;100;110;120;130;140;150;175;200;250;300;400;500;750;1000")
  690. register_option_value(OPTION_HITPOINT_HOMING, "0;1;10;20;30;40;50;60;70;80;90;100;110;120;130;140;150;175;200;250;300;400;500;750;1000")
  691.  
  692. register_option_value(OPTION_HITPOINT_INTER_DMG, "0;5;10;15;20;25;30;35;45;50;55;60;65;70;75;80;85;90;95;100")
  693. register_option_value(OPTION_HITPOINT_FF, "0;5;10;15;20;25;30;35;45;50;55;60;65;70;75;80;85;90;95;100")
  694.  
  695. // Damage System Option Registration
  696. register_option(OPTION_DAMAGE_SYSTEM, "nademodes_damage_system", "2", TOPTION_CELL)
  697.  
  698. register_option(OPTION_DMG_THROUGH_WALL, "nademodes_damage_through_wall", "50", TOPTION_CELL)
  699. register_option(OPTION_DMG_SELF, "nademodes_damage_self", "50", TOPTION_CELL)
  700. register_option(OPTION_DMG_TEAMMATES, "nademodes_damage_teammate", "50", TOPTION_CELL)
  701.  
  702. register_option(OPTION_DMG_NORMAL, "nademodes_damage_normal", "1.0", TOPTION_FLOAT)
  703. register_option(OPTION_DMG_IMPACT, "nademodes_damage_impact", "1.0", TOPTION_FLOAT)
  704. register_option(OPTION_DMG_PROXIMITY, "nademodes_damage_proximity", "1.0", TOPTION_FLOAT)
  705. register_option(OPTION_DMG_MOTION, "nademodes_damage_motion", "1.0", TOPTION_FLOAT)
  706. register_option(OPTION_DMG_SATCHEL, "nademodes_damage_satchel", "1.0", TOPTION_FLOAT)
  707. register_option(OPTION_DMG_TRIP, "nademodes_damage_trip", "1.0", TOPTION_FLOAT)
  708. register_option(OPTION_DMG_HOMING, "nademodes_damage_homing", "1.0", TOPTION_FLOAT)
  709.  
  710. // Damage System Option Values
  711. register_option_value(OPTION_DAMAGE_SYSTEM, "0;1;2")
  712.  
  713. register_option_value(OPTION_DMG_THROUGH_WALL, "0;5;10;15;20;25;30;35;45;50;55;60;65;70;75;80;85;90;95;100")
  714. register_option_value(OPTION_DMG_SELF, "0;5;10;15;20;25;30;35;45;50;55;60;65;70;75;80;85;90;95;100")
  715. register_option_value(OPTION_DMG_TEAMMATES, "0;5;10;15;20;25;30;35;45;50;55;60;65;70;75;80;85;90;95;100")
  716.  
  717. register_option_value(OPTION_DMG_NORMAL, "0.2;0.4;0.6;0.8;1;1.2;1.4;1.6;1.8;2;2.2;2.4;2.6;2.8;3;3.2;3.4;3.6;3.8;4;5;6;7")
  718. register_option_value(OPTION_DMG_IMPACT, "0.2;0.4;0.6;0.8;1;1.2;1.4;1.6;1.8;2;2.2;2.4;2.6;2.8;3;3.2;3.4;3.6;3.8;4;5;6;7")
  719. register_option_value(OPTION_DMG_MOTION, "0.2;0.4;0.6;0.8;1;1.2;1.4;1.6;1.8;2;2.2;2.4;2.6;2.8;3;3.2;3.4;3.6;3.8;4;5;6;7")
  720. register_option_value(OPTION_DMG_PROXIMITY, "0.2;0.4;0.6;0.8;1;1.2;1.4;1.6;1.8;2;2.2;2.4;2.6;2.8;3;3.2;3.4;3.6;3.8;4;5;6;7")
  721. register_option_value(OPTION_DMG_SATCHEL, "0.2;0.4;0.6;0.8;1;1.2;1.4;1.6;1.8;2;2.2;2.4;2.6;2.8;3;3.2;3.4;3.6;3.8;4;5;6;7")
  722. register_option_value(OPTION_DMG_TRIP, "0.2;0.4;0.6;0.8;1;1.2;1.4;1.6;1.8;2;2.2;2.4;2.6;2.8;3;3.2;3.4;3.6;3.8;4;5;6;7")
  723. register_option_value(OPTION_DMG_HOMING, "0.2;0.4;0.6;0.8;1;1.2;1.4;1.6;1.8;2;2.2;2.4;2.6;2.8;3;3.2;3.4;3.6;3.8;4;5;6;7")
  724.  
  725. // Internal Settings Float Options
  726. register_option(OPTION_EXPLOSION_DELAY_TIME, "nademodes_explosion_delay_time", "60000.0", TOPTION_FLOAT)
  727.  
  728. register_option(OPTION_RADIUS_SEC_EXPLOSION, "nademodes_secondary_explosion_radius", "275.0", TOPTION_FLOAT)
  729.  
  730. register_option(OPTION_ARM_TIME_TRIP, "nademodes_trip_grenade_arm_time", "3.0", TOPTION_FLOAT)
  731. register_option(OPTION_ARM_TIME_PROXIMITY, "nademodes_proximity_arm_time", "2.0", TOPTION_FLOAT)
  732. register_option(OPTION_ARM_TIME_MOTION, "nademodes_motion_arm_time", "2.0", TOPTION_FLOAT)
  733. register_option(OPTION_ARM_TIME_SATCHEL, "nademodes_satchel_arm_time", "2.0", TOPTION_FLOAT)
  734.  
  735. register_option(OPTION_TRIP_FLY_SPEED, "nademodes_trip_grenade_fly_speed", "400.0", TOPTION_FLOAT)
  736. register_option(OPTION_TRIP_DETECT_DISTANCE, "nademodes_trip_grenade_detection_limit", "16000.0", TOPTION_FLOAT)
  737.  
  738. register_option(OPTION_RADIUS_PROXIMITY, "nademodes_proximity_radius", "150.0", TOPTION_FLOAT)
  739. register_option(OPTION_RADIUS_MOTION, "nademodes_motion_radius", "200.0", TOPTION_FLOAT)
  740.  
  741. register_option(OPTION_HOMING_SCAN_RANGE, "nademodes_homing_detection_range", "500.0", TOPTION_FLOAT)
  742. register_option(OPTION_HOMING_SUPER_RANGE, "nademodes_homing_superhoming_range", "100.0", TOPTION_FLOAT)
  743. register_option(OPTION_HOMING_EXTRATIME, "nademodes_homing_extratime", "0.5", TOPTION_FLOAT)
  744. register_option(OPTION_HOMING_SPEED_ADD, "nademodes_homing_velocity_deviation", "60.0", TOPTION_FLOAT)
  745.  
  746. // Internal Settings Option Values
  747. register_option_value(OPTION_EXPLOSION_DELAY_TIME, "600;700;800;900;1000;1400;1800;2200;2600;3000;4000;5000;6000;10000;60000")
  748.  
  749. register_option_value(OPTION_RADIUS_SEC_EXPLOSION, "25;50;75;100;125;150;175;200;225;250;275;300;325;350")
  750.  
  751. register_option_value(OPTION_ARM_TIME_TRIP, "1;1.5;2;2.5;3;3.5;4;4.5;5")
  752. register_option_value(OPTION_ARM_TIME_PROXIMITY, "1;1.5;2;2.5;3;3.5;4;4.5;5")
  753. register_option_value(OPTION_ARM_TIME_MOTION, "1;1.5;2;2.5;3;3.5;4;4.5;5")
  754. register_option_value(OPTION_ARM_TIME_SATCHEL, "1;1.5;2;2.5;3;3.5;4;4.5;5")
  755.  
  756. register_option_value(OPTION_TRIP_FLY_SPEED, "200;250;300;350;400;450;500;550;600;650;700;750;800;850;900;1000")
  757. register_option_value(OPTION_TRIP_DETECT_DISTANCE, "400;800;1000;2000;4000;8000;16000")
  758.  
  759. register_option_value(OPTION_RADIUS_PROXIMITY, "100;110;120;130;140;150;160;170;180;190;200")
  760. register_option_value(OPTION_RADIUS_MOTION, "150;160;170;180;190;200;210;220;230;240;250")
  761.  
  762. register_option_value(OPTION_HOMING_SCAN_RANGE,"200;250;300;350;400;450;500;550;600;650;700;750;800;850;900;950;1000")
  763. register_option_value(OPTION_HOMING_SUPER_RANGE, "40;60;80;100;120;140;160;180;200;220;240;260;280;300")
  764. register_option_value(OPTION_HOMING_EXTRATIME, "0;0.1;0.2;0.3;0.4;0.5;0.6;0.7;0.8;0.9;1")
  765. register_option_value(OPTION_HOMING_SPEED_ADD, "10;15;20;25;30;35;40;45;50;55;60;65;70;75;80;85;90;95;100;125;150")
  766.  
  767. cacheCvars()
  768.  
  769. register_event("CurWeapon", "event_armnade", "b", "1=1", "2=4", "2=9", "2=25")
  770. register_event("CurWeapon", "event_curweapon", "b", "1=1")
  771. register_event("HLTV", "event_new_round", "a", "1=0", "2=0")
  772.  
  773. register_dictionary("nademodes.txt")
  774.  
  775. g_firstenabledmode[GRENADE_EXPLOSIVE] = NADE_NORMAL
  776. g_firstenabledmode[GRENADE_FLASHBANG] = NADE_NORMAL
  777. g_firstenabledmode[GRENADE_SMOKEGREN] = NADE_NORMAL
  778.  
  779. g_ptrace[TH_LOS] = create_tr2()
  780. g_ptrace[TH_DMG] = create_tr2()
  781. g_ptrace[TH_TRIP] = create_tr2()
  782. g_ptrace[TH_BOT] = create_tr2()
  783.  
  784. callbacks[0] = menu_makecallback("callback_disabled")
  785. callbacks[1] = menu_makecallback("callback_enabled")
  786.  
  787. // Register all the forwards
  788. RegisterHam(Ham_TakeDamage, "player", "fw_takedamage")
  789. RegisterHam(Ham_Killed, "player", "fw_killed_post", 1)
  790. RegisterHam(Ham_Spawn, "player", "fw_spawn_post", 1)
  791. RegisterHam(Ham_TakeDamage, "func_wall", "fw_monster_takedamage")
  792. RegisterHam(Ham_Player_PreThink, "player", "fw_playerprethink")
  793.  
  794. RegisterHam(Ham_Touch, "grenade", "fw_touch")
  795. RegisterHam(Ham_TakeDamage, "grenade", "fw_grenade_takedamage")
  796.  
  797. RegisterHam(Ham_TraceAttack, "worldspawn", "fw_global_traceattack", 1)
  798. RegisterHam(Ham_TraceAttack, "player", "fw_global_traceattack", 1)
  799.  
  800. g_FW_property = CreateMultiForward("fw_NM_nade_property_set", ET_STOP, FP_CELL, FP_CELL)
  801. g_PFW_property = CreateMultiForward("fw_NM_nade_property_set_post", ET_IGNORE, FP_CELL, FP_CELL, FP_CELL)
  802.  
  803. register_forward(FM_CmdStart, "fw_cmdstart")
  804. register_forward(FM_SetModel, "fw_setmodel", 1)
  805. register_forward(FM_TraceLine, "fw_traceline")
  806.  
  807. register_message(get_user_msgid("SendAudio"), "fith_audio")
  808. register_message(get_user_msgid("TextMsg"), "fith_text")
  809.  
  810. set_task(SETTINGS_REFRESH_TIME, "update_forward_registration", 0, "", 0, "b", 0)
  811.  
  812. g_botquota = cvar_exists("bot_quota") ? get_cvar_pointer("bot_quota") : 0;
  813. g_zombie_mod = ZM_NO_ZM_ACTIVE // Initially we are not sure if a zombie mod is on or not
  814. }
  815.  
  816. public plugin_cfg()
  817. {
  818. // Get the config dir
  819. new config[sizeof(CFG_FILE)]
  820. get_configsdir(config, charsmax(CFG_FILE))
  821. format(CFG_FILE, charsmax(CFG_FILE), "%s/%s", config, CFG_FILE_NAME)
  822.  
  823. // Execute the CFG file
  824. if(file_exists(CFG_FILE))
  825. {
  826. server_cmd("exec %s", CFG_FILE)
  827. cacheCvars()
  828. }
  829.  
  830. AddMenuItem("Nade Mode Menu", "amx_nmm", ADMIN_ACCESS, "NadeModes")
  831. }
  832.  
  833. public plugin_end()
  834. {
  835. TrieDestroy(trace_attack_reg_class)
  836. DestroyForward(g_FW_property)
  837. DestroyForward(g_PFW_property)
  838.  
  839. free_tr2(g_ptrace[TH_LOS])
  840. free_tr2(g_ptrace[TH_DMG])
  841. free_tr2(g_ptrace[TH_TRIP])
  842. free_tr2(g_ptrace[TH_BOT])
  843.  
  844. save_cfg()
  845. }
  846.  
  847. register_option(Option:option, const name[300], const string[], OptionType:type = TOPTION_TOGGLE, flags = 0, Float:value = 0.0)
  848. {
  849. pcvars[option] = register_cvar(name, string, flags, value)
  850. option_type[option] = type
  851. return
  852. }
  853.  
  854. register_option_value(Option:option, values[CVAR_STRING_ALLOC])
  855. {
  856. if (option_type[option] == TOPTION_TOGGLE)
  857. return
  858.  
  859. option_value[option] = ArrayCreate(CVAR_STRING_ALLOC + 1)
  860. ArrayPushString(option_value[option], values)
  861. }
  862.  
  863. stock unregister_all_option_value()
  864. {
  865. for (new Option:option=OPTION_ENABLE_NADE_MODES; option <= OPTION_HOMING_SPEED_ADD; option += OPTION_FRIENDLY_FIRE)
  866. {
  867. if (option_type[option] == TOPTION_TOGGLE)
  868. return
  869.  
  870. ArrayDestroy(option_value[option])
  871. }
  872. }
  873.  
  874. cacheCvars()
  875. {
  876. for (new Option:option=OPTION_ENABLE_NADE_MODES; option <= OPTION_HOMING_SPEED_ADD; option += OPTION_FRIENDLY_FIRE)
  877. {
  878. if (option_type[option] == TOPTION_FLOAT)
  879. {
  880. ccvars[option] = _:get_pcvar_float(pcvars[option])
  881. }
  882. else
  883. {
  884. ccvars[option] = get_pcvar_num(pcvars[option])
  885. }
  886. }
  887. }
  888.  
  889. public save_cfg()
  890. {
  891. static file[3000]
  892. format(file, charsmax(file), "echo [NadeModes] Executing config file ...^n")
  893.  
  894. format(file, charsmax(file), "%s^n// General CVARS^n^n", file)
  895.  
  896. format(file, charsmax(file), "%snademodes_enable %d^n", file, get_option(OPTION_ENABLE_NADE_MODES))
  897. format(file, charsmax(file), "%snademodes_nades_in_effect %d^n", file, get_option(OPTION_NADES_IN_EFFECT))
  898.  
  899. format(file, charsmax(file), "%snademodes_effects %d^n", file, get_option(OPTION_RESOURCE_USE))
  900. format(file, charsmax(file), "%snademodes_play_grenade_sounds %d^n", file, get_option(OPTION_PLAY_SOUNDS))
  901. format(file, charsmax(file), "%snademodes_svc_bad_error_fix %d^n", file, get_option(OPTION_MSG_SVC_BAD))
  902.  
  903. format(file, charsmax(file), "%snademodes_display_mode_on_draw %d^n", file, get_option(OPTION_DISPLAY_MODE_ON_DRAW))
  904. format(file, charsmax(file), "%snademodes_reset_mode_on_throw %d^n", file, get_option(OPTION_RESET_MODE_ON_THROW))
  905. format(file, charsmax(file), "%snademodes_suppress_fire_in_the_hole %d^n", file, get_option(OPTION_SUPPRESS_FITH))
  906.  
  907. format(file, charsmax(file), "%snademodes_bot_support %d^n", file, get_option(OPTION_BOT_ALLOW))
  908.  
  909. format(file, charsmax(file), "%snademodes_remove_if_player_dies %d^n", file, get_option(OPTION_REMOVE_IF_DIES))
  910. format(file, charsmax(file), "%snademodes_affect_owner %d^n", file, get_option(OPTION_AFFECT_OWNER))
  911. format(file, charsmax(file), "%snademodes_team_play %d^n", file, get_option(OPTION_TEAM_PLAY))
  912. format(file, charsmax(file), "%snademodes_unit_system %d^n", file, get_option(OPTION_UNITS_SYSTEM))
  913.  
  914. format(file, charsmax(file), "%snademodes_monstermod_support %d^n", file, get_option(OPTION_MONSTERMOD_SUPPORT))
  915.  
  916. format(file, charsmax(file), "%s^n// Mode CVARS^n^n", file)
  917.  
  918. format(file, charsmax(file), "%snademodes_normal_enabled %d^n", file, get_option(OPTION_NORMAL_ENABLED))
  919. format(file, charsmax(file), "%snademodes_proximity_enabled %d^n", file, get_option(OPTION_PROXIMITY_ENABLED))
  920. format(file, charsmax(file), "%snademodes_impact_enabled %d^n", file, get_option(OPTION_IMPACT_ENABLED))
  921. format(file, charsmax(file), "%snademodes_trip_enabled %d^n", file, get_option(OPTION_TRIP_ENABLED))
  922. format(file, charsmax(file), "%snademodes_motion_enabled %d^n", file, get_option(OPTION_MOTION_ENABLED))
  923. format(file, charsmax(file), "%snademodes_satchel_enabled %d^n", file, get_option(OPTION_SATCHEL_ENABLED))
  924. format(file, charsmax(file), "%snademodes_homing_enabled %d^n", file, get_option(OPTION_HOMING_ENABLED))
  925.  
  926. format(file, charsmax(file), "%snademodes_grenade_react %d^n", file, get_option(OPTION_REACT_TRIP_G))
  927. format(file, charsmax(file), "%snademodes_flash_react %d^n", file, get_option(OPTION_REACT_TRIP_F))
  928. format(file, charsmax(file), "%snademodes_smoke_react %d^n", file, get_option(OPTION_REACT_TRIP_S))
  929.  
  930. format(file, charsmax(file), "%snademodes_proximity_fov %d^n", file, get_option(OPTION_PROXIMITY_LOS))
  931. format(file, charsmax(file), "%snademodes_motion_fov %d^n", file, get_option(OPTION_MOTION_LOS))
  932. format(file, charsmax(file), "%snademodes_satchel_delay %d^n", file, get_option(OPTION_SATCHEL_DELAY))
  933.  
  934. format(file, charsmax(file), "%s^n// Limit & Test CVARS^n^n", file)
  935.  
  936. format(file, charsmax(file), "%snademodes_limit_system %d^n", file, get_option(OPTION_LIMIT_SYSTEM))
  937.  
  938. format(file, charsmax(file), "%snademodes_proximity_limit %d^n", file, get_option(OPTION_LIMIT_PROXIMITY))
  939. format(file, charsmax(file), "%snademodes_trip_limit %d^n", file, get_option(OPTION_LIMIT_TRIP))
  940. format(file, charsmax(file), "%snademodes_motion_limit %d^n", file, get_option(OPTION_LIMIT_MOTION))
  941. format(file, charsmax(file), "%snademodes_satchel_limit %d^n", file, get_option(OPTION_LIMIT_SATCHEL))
  942.  
  943. format(file, charsmax(file), "%snademodes_infinite_grenades %d^n", file, get_option(OPTION_INFINITE_GRENADES))
  944. format(file, charsmax(file), "%snademodes_infinite_flashes %d^n", file, get_option(OPTION_INFINITE_FLASHES))
  945. format(file, charsmax(file), "%snademodes_infinite_smokes %d^n", file, get_option(OPTION_INFINITE_SMOKES))
  946.  
  947. format(file, charsmax(file), "%s^n// Intergrenade CVARS CVARS^n^n", file)
  948.  
  949.  
  950. format(file, charsmax(file), "%snademodes_material_system %d^n", file, get_option(OPTION_MATERIAL_SYSTEM))
  951. format(file, charsmax(file), "%snademodes_grenade_death %d^n", file, get_option(OPTION_HITPOINT_DEATH))
  952.  
  953. format(file, charsmax(file), "%snademodes_secondary_explosions_mode %d^n", file, get_option(OPTION_SEC_EXPLO_AFFECT))
  954. format(file, charsmax(file), "%snademodes_secondary_explosion_radius %f^n", file, get_option_float(OPTION_RADIUS_SEC_EXPLOSION))
  955.  
  956. format(file, charsmax(file), "%snademodes_hitpoints_normal %d^n", file, get_option(OPTION_HITPOINT_NORMAL))
  957. format(file, charsmax(file), "%snademodes_hitpoints_proximity %d^n", file, get_option(OPTION_HITPOINT_PROXIMITY))
  958. format(file, charsmax(file), "%snademodes_hitpoints_impact %d^n", file, get_option(OPTION_HITPOINT_IMPACT))
  959. format(file, charsmax(file), "%snademodes_hitpoints_trip %d^n", file, get_option(OPTION_HITPOINT_TRIP))
  960. format(file, charsmax(file), "%snademodes_hitpoints_motion %d^n", file, get_option(OPTION_HITPOINT_MOTION))
  961. format(file, charsmax(file), "%snademodes_hitpoints_satchel %d^n", file, get_option(OPTION_HITPOINT_SATCHEL))
  962. format(file, charsmax(file), "%snademodes_hitpoints_homing %d^n", file, get_option(OPTION_HITPOINT_HOMING))
  963.  
  964. format(file, charsmax(file), "%snademodes_hitpoints_intergrenade_damage %f^n", file, get_option_float(OPTION_HITPOINT_INTER_DMG))
  965. format(file, charsmax(file), "%snademodes_hitpoints_friendlyfire_ammount %f^n", file, get_option_float(OPTION_HITPOINT_FF))
  966.  
  967. format(file, charsmax(file), "%s^n// Damage CVARS^n^n", file)
  968.  
  969. format(file, charsmax(file), "%snademodes_damage_system %d^n", file, get_option(OPTION_DAMAGE_SYSTEM))
  970.  
  971. format(file, charsmax(file), "%snademodes_damage_self %d^n", file, get_option(OPTION_DMG_SELF))
  972. format(file, charsmax(file), "%snademodes_damage_through_wall %d^n", file, get_option(OPTION_DMG_THROUGH_WALL))
  973. format(file, charsmax(file), "%snademodes_damage_teammate %d^n", file, get_option(OPTION_DMG_TEAMMATES))
  974.  
  975. format(file, charsmax(file), "%snademodes_damage_normal %f^n", file, get_option_float(OPTION_DMG_NORMAL))
  976. format(file, charsmax(file), "%snademodes_damage_proximity %f^n", file, get_option_float(OPTION_DMG_PROXIMITY))
  977. format(file, charsmax(file), "%snademodes_damage_impact %f^n", file, get_option_float(OPTION_DMG_IMPACT))
  978. format(file, charsmax(file), "%snademodes_damage_trip %f^n", file, get_option_float(OPTION_DMG_TRIP))
  979. format(file, charsmax(file), "%snademodes_damage_motion %f^n", file, get_option_float(OPTION_DMG_MOTION))
  980. format(file, charsmax(file), "%snademodes_damage_satchel %f^n", file, get_option_float(OPTION_DMG_SATCHEL))
  981. format(file, charsmax(file), "%snademodes_damage_homing %f^n", file, get_option_float(OPTION_DMG_HOMING))
  982.  
  983. format(file, charsmax(file), "%s^n// Internal Funcitonal CVARS^n^n", file)
  984.  
  985. format(file, charsmax(file), "%snademodes_explosion_delay_time %f^n", file, get_option_float(OPTION_EXPLOSION_DELAY_TIME))
  986.  
  987. format(file, charsmax(file), "%snademodes_proximity_arm_time %f^n", file, get_option_float(OPTION_ARM_TIME_PROXIMITY))
  988. format(file, charsmax(file), "%snademodes_proximity_radius %f^n", file, get_option_float(OPTION_RADIUS_PROXIMITY))
  989.  
  990. format(file, charsmax(file), "%snademodes_trip_grenade_arm_time %f^n", file, get_option_float(OPTION_ARM_TIME_TRIP))
  991. format(file, charsmax(file), "%snademodes_trip_grenade_fly_speed %f^n", file, get_option_float(OPTION_TRIP_FLY_SPEED))
  992. format(file, charsmax(file), "%snademodes_trip_grenade_detection_limit %f^n", file, get_option_float(OPTION_TRIP_DETECT_DISTANCE))
  993.  
  994. format(file, charsmax(file), "%snademodes_motion_arm_time %f^n", file, get_option_float(OPTION_ARM_TIME_MOTION))
  995. format(file, charsmax(file), "%snademodes_motion_radius %f^n", file, get_option_float(OPTION_RADIUS_MOTION))
  996.  
  997. format(file, charsmax(file), "%snademodes_satchel_arm_time %f^n", file, get_option_float(OPTION_ARM_TIME_SATCHEL))
  998.  
  999. format(file, charsmax(file), "%snademodes_homing_detection_range %f^n", file, get_option_float(OPTION_HOMING_SCAN_RANGE))
  1000. format(file, charsmax(file), "%snademodes_homing_superhoming_range %f^n", file, get_option_float(OPTION_HOMING_SUPER_RANGE))
  1001. format(file, charsmax(file), "%snademodes_homing_extratime %f^n", file, get_option_float(OPTION_HOMING_EXTRATIME))
  1002. format(file, charsmax(file), "%snademodes_homing_velocity_deviation %f^n", file, get_option_float(OPTION_HOMING_SPEED_ADD))
  1003.  
  1004. format(file, charsmax(file), "%s^necho [NadeModes] Settings loaded from config file", file)
  1005.  
  1006. delete_file(CFG_FILE)
  1007. write_file(CFG_FILE, file)
  1008. }
  1009.  
  1010. /* -------------------------------
  1011. [Plugin Commands & Menus]
  1012. ------------------------------- */
  1013. public conjure_help(id)
  1014. {
  1015. static help_file[3000]
  1016.  
  1017. format(help_file, charsmax(help_file), "%L", id, "NADE_HTML")
  1018.  
  1019. delete_file("nmm.htm")
  1020. write_file("nmm.htm", help_file)
  1021. show_motd(id, "nmm.htm", "Mega-Nade Mod")
  1022.  
  1023. return PLUGIN_CONTINUE
  1024. }
  1025.  
  1026. public conjure_menu(id, level, cid)
  1027. {
  1028. if (cmd_access(id, level, cid, 1))
  1029. {
  1030. main_menu(id)
  1031. }
  1032.  
  1033. return PLUGIN_HANDLED
  1034. }
  1035.  
  1036. stock main_menu(id)
  1037. {
  1038. static menu
  1039. settingsmenu[id] = menu_create("NadeModes - Main Menu", "menu_handler")
  1040. menu = settingsmenu[id]
  1041.  
  1042. add_option_toggle(menu, OPTION_ENABLE_NADE_MODES, "Enable nade modes", "Yes", "No")
  1043.  
  1044. menu_additem(menu, "Execute config file")
  1045. menu_additem(menu, "General settings", _, _, get_option(OPTION_ENABLE_NADE_MODES) ? callbacks[1] : callbacks[0])
  1046. menu_additem(menu, "Mode control menu", _, _, get_option(OPTION_ENABLE_NADE_MODES) ? callbacks[1] : callbacks[0])
  1047. menu_additem(menu, "Mode limit & test menu", _, _, is_nademodes_enabled() ? callbacks[1] : callbacks[0])
  1048. menu_additem(menu, "Hitpoints menu", _, _, is_nademodes_enabled() ? callbacks[1] : callbacks[0])
  1049. menu_additem(menu, "Mode damage settings", _, _, is_nademodes_enabled() ? callbacks[1] : callbacks[0])
  1050. menu_additem(menu, "Internal functional settings", _, _, is_nademodes_enabled() ? callbacks[1] : callbacks[0])
  1051.  
  1052. menu_display(id, settingsmenu[id])
  1053. return PLUGIN_CONTINUE
  1054. }
  1055.  
  1056. public menu_handler(id, menu, item)
  1057. {
  1058. if (item < 0)
  1059. {
  1060. return PLUGIN_HANDLED
  1061. }
  1062.  
  1063. switch (item)
  1064. {
  1065. case 0:
  1066. {
  1067. toggle_option(OPTION_ENABLE_NADE_MODES)
  1068. update_forward_registration()
  1069. }
  1070. case 1:
  1071. {
  1072. if(file_exists(CFG_FILE))
  1073. {
  1074. server_cmd("exec %s", CFG_FILE)
  1075. update_forward_registration()
  1076. }
  1077. else
  1078. {
  1079. client_print(id, print_chat, "[NDM] Config file not found!")
  1080. }
  1081. }
  1082.  
  1083. default:
  1084. {
  1085. menu_destroy(menu)
  1086. cvar_menu(id, 0, item - 1)
  1087. return PLUGIN_HANDLED
  1088. }
  1089. }
  1090.  
  1091.  
  1092. menu_destroy(menu)
  1093. main_menu(id)
  1094. return PLUGIN_HANDLED
  1095. }
  1096.  
  1097. stock cvar_menu(id, page = 0, menu_set = 0)
  1098. {
  1099. if (menu_set <= 0)
  1100. return PLUGIN_CONTINUE
  1101.  
  1102. static menu
  1103.  
  1104. switch (menu_set)
  1105. {
  1106. case 1:
  1107. {
  1108. settingsmenu[id] = menu_create("NadeModes - General Settings", "cvar_menu_handler")
  1109. menu = settingsmenu[id]
  1110.  
  1111. add_nade_option(menu, OPTION_NADES_IN_EFFECT, "Grenades that can use the nademodes")
  1112.  
  1113. add_option_quatrotoggle(menu, OPTION_RESOURCE_USE, "Plugin effects", "\rOff", "\yNormal", "\ySmart Mode", "\yLow Bandwidth Mode")
  1114. add_option_toggle(menu, OPTION_PLAY_SOUNDS, "Grenade sounds", "On", "Off")
  1115. add_option_toggle(menu, OPTION_MONSTERMOD_SUPPORT, "Monstermod support", "On", "Off")
  1116. add_option_toggle(menu, OPTION_MSG_SVC_BAD, "SVC_BAD fix", "On^n \yNote: \wTurn on when the server has this problem!^n", "Off^n \yNote: \wTurn on when the server has this problem!^n")
  1117. add_option_toggle(menu, OPTION_BOT_ALLOW, "Allow bots to use the moded nades", "Yes^n", "No^n")
  1118.  
  1119. add_option_toggle(menu, OPTION_DISPLAY_MODE_ON_DRAW, "Display mode on draw", "Yes", "No")
  1120. add_option_toggle(menu, OPTION_RESET_MODE_ON_THROW, "Reset mode on throw", "Yes^n", "No^n")
  1121.  
  1122. add_option_toggle(menu, OPTION_REMOVE_IF_DIES, "Remove the nades if player dies", "Yes", "No")
  1123. add_option_toggle(menu, OPTION_AFFECT_OWNER, "Traps can be activated by owner", "Yes", "No")
  1124. add_option_toggle(menu, OPTION_TEAM_PLAY, "Team play (teammates will not be affected by nades)", "Yes^n", "No^n")
  1125.  
  1126. add_option_toggle(menu, OPTION_SUPPRESS_FITH, "Suppress ^"Fire in the hole!^"", "Yes^n", "No^n")
  1127.  
  1128. add_option_toggle(menu, OPTION_UNITS_SYSTEM, "Unit system:", "Metric", "Inch")
  1129.  
  1130. }
  1131. case 2:
  1132. {
  1133. settingsmenu[id] = menu_create("NadeModes - Mode Control", "cvar_menu_handler")
  1134. menu = settingsmenu[id]
  1135.  
  1136. add_option_toggle(menu, OPTION_NORMAL_ENABLED, "Enable normal grenades", "Yes", "No")
  1137. add_option_toggle(menu, OPTION_PROXIMITY_ENABLED, "Enable proximity grenades", "Yes", "No")
  1138. add_option_toggle(menu, OPTION_IMPACT_ENABLED, "Enable impact grenades", "Yes", "No")
  1139. add_option_toggle(menu, OPTION_TRIP_ENABLED, "Enable trip grenades", "Yes", "No")
  1140. add_option_toggle(menu, OPTION_MOTION_ENABLED, "Enable motion sensor grenades", "Yes", "No")
  1141. add_option_toggle(menu, OPTION_SATCHEL_ENABLED, "Enable satchel charge grenades", "Yes", "No")
  1142. add_option_toggle(menu, OPTION_HOMING_ENABLED, "Enable homing grenades", "Yes^n", "No^n")
  1143.  
  1144. add_option_toggle(menu, OPTION_REACT_TRIP_G, "Trip grenade react method", "Boom", "Fly", OPTION_TRIP_ENABLED)
  1145. add_option_toggle(menu, OPTION_REACT_TRIP_F, "Trip flash react method", "Boom", "Fly", OPTION_TRIP_ENABLED)
  1146. add_option_toggle(menu, OPTION_REACT_TRIP_S, "Trip smoke react method", "Boom^n", "Fly^n", OPTION_TRIP_ENABLED)
  1147.  
  1148. add_option_toggle(menu, OPTION_PROXIMITY_LOS, "Proximity detonate only if player is in line of sight", "Yes", "No", OPTION_PROXIMITY_ENABLED)
  1149. add_option_toggle(menu, OPTION_MOTION_LOS, "Motion detonate only if player is in line of sight", "Yes", "No", OPTION_MOTION_ENABLED)
  1150. add_option_toggle(menu, OPTION_SATCHEL_DELAY, "Add delay between satchel explotions", "Yes", "No", OPTION_SATCHEL_ENABLED)
  1151. }
  1152. case 3:
  1153. {
  1154. settingsmenu[id] = menu_create("NadeModes - Limit & Test Menu", "cvar_menu_handler")
  1155. menu = settingsmenu[id]
  1156.  
  1157. add_option_tritoggle(menu, OPTION_LIMIT_SYSTEM, "Limit system", "\rOff^n", "\yAvailable for each nade^n", "\yAvailable for all nades summed up^n")
  1158.  
  1159. add_cell_option(menu, OPTION_LIMIT_PROXIMITY, "Proximity throw limit", "grenades", OPTION_LIMIT_SYSTEM)
  1160. add_cell_option(menu, OPTION_LIMIT_TRIP, "Trip grenade throw limit", "grenades", OPTION_LIMIT_SYSTEM)
  1161. add_cell_option(menu, OPTION_LIMIT_MOTION, "Motion throw limit", "grenades", OPTION_LIMIT_SYSTEM)
  1162. add_cell_with_space_option(menu, OPTION_LIMIT_SATCHEL, "Stachel throw limit", "grenades", OPTION_LIMIT_SYSTEM)
  1163.  
  1164. add_option_toggle(menu, OPTION_INFINITE_GRENADES, "Infinite grenades", "Yes", "No")
  1165. add_option_toggle(menu, OPTION_INFINITE_FLASHES, "Infinite flashes", "Yes", "No")
  1166. add_option_toggle(menu, OPTION_INFINITE_SMOKES, "Infinite smokes", "Yes", "No")
  1167. }
  1168. case 4:
  1169. {
  1170. settingsmenu[id] = menu_create("NadeModes - Hitpoint Menu", "cvar_menu_handler")
  1171. menu = settingsmenu[id]
  1172.  
  1173. add_option_tritoggle(menu, OPTION_MATERIAL_SYSTEM, "Interaction system", "\rOff", "\ySecondary Explosions", "\yHit Point System")
  1174.  
  1175.  
  1176.  
  1177. switch (get_option(OPTION_MATERIAL_SYSTEM))
  1178. {
  1179. case 0:
  1180. {
  1181. add_option_toggle(menu, OPTION_HITPOINT_DEATH, "Nade death", "Explode^n", "Desintegrate^n",OPTION_MATERIAL_SYSTEM)
  1182.  
  1183. add_cell_option(menu, OPTION_HITPOINT_NORMAL, "Normal grenade hitpoints", "hitpoints", OPTION_MATERIAL_SYSTEM)
  1184. add_cell_option(menu, OPTION_HITPOINT_PROXIMITY, "Proximity grenade hitpoints", "hitpoints", OPTION_MATERIAL_SYSTEM)
  1185. add_cell_option(menu, OPTION_HITPOINT_IMPACT, "Impact grenade hitpoints", "hitpoints", OPTION_MATERIAL_SYSTEM)
  1186. add_cell_option(menu, OPTION_HITPOINT_TRIP, "Trip grenade hitpoints", "hitpoints", OPTION_MATERIAL_SYSTEM)
  1187. add_cell_option(menu, OPTION_HITPOINT_MOTION, "Motion grenade hitpoints", "hitpoints", OPTION_MATERIAL_SYSTEM)
  1188. add_cell_option(menu, OPTION_HITPOINT_SATCHEL, "Satchel grenade hitpoints", "hitpoints", OPTION_MATERIAL_SYSTEM)
  1189. add_cell_option(menu, OPTION_HITPOINT_HOMING, "Homing grenade hitpoints", "hitpoints", OPTION_MATERIAL_SYSTEM)
  1190. }
  1191.  
  1192. case 1:
  1193. {
  1194. add_option_toggle(menu, OPTION_SEC_EXPLO_AFFECT, "Secondary explosions", "\yEach nade affects each!^n", "\yHe grenade affects all^n")
  1195. add_float_unit_option(menu, OPTION_RADIUS_SEC_EXPLOSION, "Secondary explosion radius affection", "")
  1196. }
  1197.  
  1198. case 2:
  1199. {
  1200. add_option_toggle(menu, OPTION_HITPOINT_DEATH, "Nade death", "Explode^n", "Desintegrate^n",OPTION_MATERIAL_SYSTEM)
  1201.  
  1202. add_cell_option(menu, OPTION_HITPOINT_NORMAL, "Normal grenade hitpoints", "hitpoints", OPTION_NORMAL_ENABLED)
  1203. add_cell_option(menu, OPTION_HITPOINT_PROXIMITY, "Proximity grenade hitpoints", "hitpoints", OPTION_PROXIMITY_ENABLED)
  1204. add_cell_option(menu, OPTION_HITPOINT_IMPACT, "Impact grenade hitpoints", "hitpoints", OPTION_IMPACT_ENABLED)
  1205. add_cell_option(menu, OPTION_HITPOINT_TRIP, "Trip grenade hitpoints", "hitpoints", OPTION_TRIP_ENABLED)
  1206. add_cell_option(menu, OPTION_HITPOINT_MOTION, "Motion grenade hitpoints", "hitpoints", OPTION_MOTION_ENABLED)
  1207. add_cell_option(menu, OPTION_HITPOINT_SATCHEL, "Satchel grenade hitpoints", "hitpoints", OPTION_SATCHEL_ENABLED)
  1208. add_cell_option(menu, OPTION_HITPOINT_HOMING, "Homing grenade hitpoints", "hitpoints^n", OPTION_HOMING_ENABLED)
  1209.  
  1210. add_float_option(menu, OPTION_HITPOINT_FF, "Friendlyfire", "%", OPTION_MATERIAL_SYSTEM)
  1211. add_float_option(menu, OPTION_HITPOINT_INTER_DMG, "Damage between the grenades", "%", OPTION_MATERIAL_SYSTEM)
  1212.  
  1213. }
  1214. }
  1215. }
  1216. case 5:
  1217. {
  1218. settingsmenu[id] = menu_create("NadeModes - Damage Settings", "cvar_menu_handler")
  1219. menu = settingsmenu[id]
  1220.  
  1221. add_option_tritoggle(menu, OPTION_DAMAGE_SYSTEM, "Damage system", "\rOff^n", "\yActive for every mode^n", "\yEach mode configurable^n")
  1222.  
  1223. add_float_option(menu, OPTION_DMG_SELF, "Nade self damage percent", "%", OPTION_DAMAGE_SYSTEM)
  1224. add_float_option(menu, OPTION_DMG_THROUGH_WALL, "Nade through wall damage percent", "%", OPTION_DAMAGE_SYSTEM)
  1225.  
  1226. switch (get_option(OPTION_DAMAGE_SYSTEM))
  1227. {
  1228. case 0:
  1229. {
  1230. add_float_option(menu, OPTION_DMG_TEAMMATES, "Team mates damage percent", "%^n", OPTION_DAMAGE_SYSTEM)
  1231. }
  1232.  
  1233. case 1:
  1234. {
  1235. add_float_option(menu, OPTION_DMG_TEAMMATES, "Team mates damage percent", "%^n", OPTION_FRIENDLY_FIRE)
  1236.  
  1237. add_float_option(menu, OPTION_DMG_NORMAL, "Grenade general damage multiply","times")
  1238. }
  1239.  
  1240. case 2:
  1241. {
  1242. add_float_option(menu, OPTION_DMG_TEAMMATES, "Team mates damage percent", "%^n", OPTION_FRIENDLY_FIRE)
  1243.  
  1244. add_float_option(menu, OPTION_DMG_NORMAL, "Normal Grenade - damage multiply","times",OPTION_NORMAL_ENABLED)
  1245. add_float_option(menu, OPTION_DMG_PROXIMITY, "Proximity Grenade - damage multiply","times", OPTION_PROXIMITY_ENABLED)
  1246. add_float_option(menu, OPTION_DMG_IMPACT, "Impact Grenade - damage multiply","times", OPTION_IMPACT_ENABLED)
  1247. add_float_option(menu, OPTION_DMG_TRIP, "Trip Grenade - damage multiply","times", OPTION_TRIP_ENABLED)
  1248. add_float_option(menu, OPTION_DMG_MOTION, "Motion Grenade - damage multiply","times", OPTION_MOTION_ENABLED)
  1249. add_float_option(menu, OPTION_DMG_SATCHEL, "Satchel Grenade - damage multiply","times", OPTION_SATCHEL_ENABLED)
  1250. add_float_option(menu, OPTION_DMG_HOMING, "Homing Grenade - damage multiply","times", OPTION_HOMING_ENABLED)
  1251. }
  1252. }
  1253. }
  1254. case 6:
  1255. {
  1256. settingsmenu[id] = menu_create("NadeModes - Internal Functional Settings", "cvar_menu_handler")
  1257. menu = settingsmenu[id]
  1258.  
  1259. add_float_option(menu, OPTION_EXPLOSION_DELAY_TIME, "Grenade general delay explode time", "seconds^n")
  1260.  
  1261. add_float_option(menu, OPTION_ARM_TIME_PROXIMITY, "Proximity arm time", "seconds", OPTION_PROXIMITY_ENABLED)
  1262. add_float_unit_option(menu, OPTION_RADIUS_PROXIMITY, "Proximity detection radius", "^n", OPTION_PROXIMITY_ENABLED)
  1263.  
  1264. add_float_option(menu, OPTION_ARM_TIME_TRIP, "Trip grenade arm time", "seconds", OPTION_TRIP_ENABLED)
  1265. add_float_unit_option(menu, OPTION_TRIP_DETECT_DISTANCE, "Trip grenade detection distance", "", OPTION_TRIP_ENABLED)
  1266. add_float_unit_option(menu, OPTION_TRIP_FLY_SPEED, "Trip grenade fly speed", "^n", OPTION_TRIP_ENABLED)
  1267.  
  1268. add_float_option(menu, OPTION_ARM_TIME_SATCHEL, "Satchel charge arm time", "seconds^n", OPTION_SATCHEL_ENABLED)
  1269.  
  1270. add_float_option(menu, OPTION_ARM_TIME_MOTION, "Motion sensor arm time", "seconds", OPTION_MOTION_ENABLED)
  1271. add_float_unit_option(menu, OPTION_RADIUS_MOTION, "Motion sensor detection radius", "^n", OPTION_MOTION_ENABLED)
  1272.  
  1273. add_float_option(menu, OPTION_HOMING_EXTRATIME, "Homing extra arm explosion time", "seconds", OPTION_HOMING_ENABLED)
  1274. add_float_unit_option(menu, OPTION_HOMING_SCAN_RANGE, "Homing grenade detection range", "", OPTION_HOMING_ENABLED)
  1275. add_float_unit_option(menu, OPTION_HOMING_SUPER_RANGE, "Homing grenade superhoming range", "", OPTION_HOMING_ENABLED)
  1276. add_float_unit_option(menu, OPTION_HOMING_SPEED_ADD, "Homing grenade air acceleration", "", OPTION_HOMING_ENABLED)
  1277. }
  1278. }
  1279.  
  1280. cvar_menu_pos[id] = menu_set
  1281. menu_display(id, settingsmenu[id], page)
  1282. return PLUGIN_CONTINUE
  1283. }
  1284.  
  1285. stock add_option_toggle(menu, Option:control_option, const basetext[], const yestext[], const notext[], Option:displayif = Option:-1)
  1286. {
  1287. static cmd[4], itemtext[100]
  1288. num_to_str(_:control_option, cmd, charsmax(cmd))
  1289.  
  1290. format(itemtext, charsmax(itemtext), "%s: %s%s", basetext, (get_option(control_option) ? "\y" : "\r" ), (get_option(control_option) ? yestext : notext))
  1291. menu_additem(menu, itemtext, cmd, _, (displayif != Option:-1 && !get_option(displayif)) ? callbacks[0] : callbacks[1])
  1292. }
  1293.  
  1294. stock add_option_tritoggle(menu, Option:control_option, const basetext[], const text[], const text2[], const text3[], Option:displayif = Option:-1)
  1295. {
  1296. static cmd[4], itemtext[100]
  1297. num_to_str(_:control_option, cmd, charsmax(cmd))
  1298.  
  1299. format(itemtext, charsmax(itemtext), "%s:\y %s%s%s", basetext, (get_option(control_option) == 0 ? text : "" ), (get_option(control_option) == 1 ? text2 : "" ), (get_option(control_option) == 2 ? text3 : "" ))
  1300. menu_additem(menu, itemtext, cmd, _, (displayif != Option:-1 && !get_option(displayif)) ? callbacks[0] : callbacks[1])
  1301. }
  1302.  
  1303. stock add_option_quatrotoggle(menu, Option:control_option, const basetext[], const text[], const text2[], const text3[], const text4[], Option:displayif = Option:-1)
  1304. {
  1305. static cmd[4], itemtext[100]
  1306. num_to_str(_:control_option, cmd, charsmax(cmd))
  1307.  
  1308. format(itemtext, charsmax(itemtext), "%s:\y %s%s%s%s", basetext, (get_option(control_option) == 0 ? text : "" ), (get_option(control_option) == 1 ? text2 : "" ), (get_option(control_option) == 2 ? text3 : "" ), (get_option(control_option) == 3 ? text4 : "" ))
  1309. menu_additem(menu, itemtext, cmd, _, (displayif != Option:-1 && !get_option(displayif)) ? callbacks[0] : callbacks[1])
  1310. }
  1311.  
  1312. stock add_nade_option(menu, Option:control_option, const basetext[])
  1313. {
  1314. static cmd[4], itemtext[100]
  1315. num_to_str(_:control_option, cmd, charsmax(cmd))
  1316.  
  1317. format(itemtext, charsmax(itemtext), "%s:%s%s%s%s^n", basetext, (get_option(control_option) ? "\y" : " \rNone" ), ((get_option(control_option) & NADE_BIT[GRENADE_EXPLOSIVE]) ? " He" : ""), ((get_option(control_option) & NADE_BIT[GRENADE_FLASHBANG]) ? " Flash" : ""), ((get_option(control_option) & NADE_BIT[GRENADE_SMOKEGREN]) ? " Smoke" : ""))
  1318. menu_additem(menu, itemtext, cmd, _, _)
  1319. }
  1320.  
  1321. stock add_float_option(menu, Option:control_option, const basetext[], const unit[], Option:displayif = Option:-1)
  1322. {
  1323. static cmd[4], itemtext[100], value[20]
  1324. float_to_str(get_option_float(control_option), value, charsmax(value))
  1325. format(value, charsmax(value), "%0.2f", get_option_float(control_option))
  1326.  
  1327. num_to_str(_:control_option, cmd, charsmax(cmd))
  1328.  
  1329. format(itemtext, charsmax(itemtext), "%s: \y%s \r%s", basetext, value, unit)
  1330. menu_additem(menu, itemtext, cmd, _, (displayif != Option:-1 && !get_option(displayif)) ? callbacks[0] : callbacks[1])
  1331. }
  1332.  
  1333. stock add_cell_option(menu, Option:control_option, const basetext[], const unit[], Option:displayif = Option:-1)
  1334. {
  1335. static cmd[4], itemtext[100], value[20]
  1336. num_to_str(get_option(control_option), value, charsmax(value))
  1337. format(value, charsmax(value), "%d", get_option(control_option))
  1338. if (!get_option(control_option))
  1339. {
  1340. value = "Off"
  1341. }
  1342.  
  1343. num_to_str(_:control_option, cmd, charsmax(cmd))
  1344.  
  1345. format(itemtext, charsmax(itemtext), "%s: \y%s \r%s", basetext, value, get_option(control_option) ? unit : "")
  1346. menu_additem(menu, itemtext, cmd, _, (displayif != Option:-1 && !get_option(displayif)) ? callbacks[0] : callbacks[1])
  1347. }
  1348.  
  1349. stock add_cell_with_space_option(menu, Option:control_option, const basetext[], const unit[], Option:displayif = Option:-1)
  1350. {
  1351. static cmd[4], itemtext[100], value[20]
  1352. num_to_str(get_option(control_option), value, charsmax(value))
  1353. format(value, charsmax(value), "%d", get_option(control_option))
  1354. if (!get_option(control_option))
  1355. {
  1356. value = "Off"
  1357. }
  1358.  
  1359. num_to_str(_:control_option, cmd, charsmax(cmd))
  1360.  
  1361. format(itemtext, charsmax(itemtext), "%s: \y%s \r%s^n", basetext, value, get_option(control_option) ? unit : "")
  1362. menu_additem(menu, itemtext, cmd, _, (displayif != Option:-1 && !get_option(displayif)) ? callbacks[0] : callbacks[1])
  1363. }
  1364.  
  1365. stock add_float_unit_option(menu, Option:control_option, const basetext[], const extratext[], Option:displayif = Option:-1)
  1366. {
  1367. static cmd[4], itemtext[100], value[20]
  1368. format(value, charsmax(value), "%0.2f", get_option(OPTION_UNITS_SYSTEM) ? CONVERT_TO_METERS(get_option_float(control_option)) : get_option_float(control_option))
  1369.  
  1370. num_to_str(_:control_option, cmd, charsmax(cmd))
  1371.  
  1372. format(itemtext, charsmax(itemtext), "%s: \y%s \r%s%s", basetext, value, get_option(OPTION_UNITS_SYSTEM) ? "meters" : "inches", extratext)
  1373. menu_additem(menu, itemtext, cmd, _, (displayif != Option:-1 && !get_option(displayif)) ? callbacks[0] : callbacks[1])
  1374. }
  1375.  
  1376.  
  1377. public cvar_menu_handler(id, menu, item)
  1378. {
  1379. new access, info[4], callback
  1380. menu_item_getinfo(menu, item, access, info, charsmax(info), _, _, callback)
  1381.  
  1382. if (item < 0)
  1383. {
  1384. save_cfg()
  1385. update_forward_registration()
  1386. main_menu(id)
  1387. return PLUGIN_HANDLED
  1388. }
  1389.  
  1390. new cvar = str_to_num(info)
  1391.  
  1392. switch (option_type[Option:cvar])
  1393. {
  1394. case TOPTION_TOGGLE:
  1395. {
  1396. toggle_option(Option:cvar)
  1397. }
  1398. case TOPTION_CELL:
  1399. {
  1400. new value_string[CVAR_STRING_ALLOC];
  1401. ArrayGetString(option_value[Option:cvar], 0, value_string, charsmax(value_string))
  1402. format(value_string, charsmax(value_string), "%s;", value_string)
  1403.  
  1404. new values[CVAR_MAX_ASSIGNED_VALUES][CVAR_MAX_STRING_LENGTH]
  1405. new true_value[CVAR_MAX_ASSIGNED_VALUES]
  1406.  
  1407. new last = 0, newpos = 0, k = 0;
  1408.  
  1409. for (new i=0;i<CVAR_STRING_ALLOC;i++)
  1410. {
  1411. if(equal(value_string[i], ";", 1))
  1412. {
  1413. newpos = i
  1414. }
  1415.  
  1416. if (newpos > last)
  1417. {
  1418. for (new j=last;j<newpos;j++)
  1419. {
  1420. format(values[k], CVAR_MAX_STRING_LENGTH - 1, "%s%s", values[k], value_string[j])
  1421. }
  1422.  
  1423. last = newpos + 1
  1424. k++
  1425. }
  1426.  
  1427. if (k == CVAR_MAX_ASSIGNED_VALUES)
  1428. {
  1429. break
  1430. }
  1431. }
  1432.  
  1433. new bool:ok = false
  1434. new counter = 0
  1435.  
  1436. for (new i=0;i<k;i++)
  1437. {
  1438. counter++
  1439.  
  1440. true_value[i] = str_to_num(values[i])
  1441.  
  1442. if (ok == true)
  1443. {
  1444. set_pcvar_num(pcvars[Option:cvar], true_value[i])
  1445. counter = 0
  1446. break
  1447. }
  1448.  
  1449. if (true_value[i] == get_option(Option:cvar))
  1450. ok = true
  1451. }
  1452.  
  1453. if (counter == k)
  1454. {
  1455. set_pcvar_num(pcvars[Option:cvar], true_value[0])
  1456. }
  1457. }
  1458. case TOPTION_FLOAT:
  1459. {
  1460. new value_string_float[CVAR_STRING_ALLOC];
  1461. ArrayGetString(option_value[Option:cvar], 0, value_string_float, charsmax(value_string_float))
  1462. format(value_string_float, charsmax(value_string_float), "%s;", value_string_float)
  1463.  
  1464. new values_float[CVAR_MAX_ASSIGNED_VALUES][CVAR_MAX_STRING_LENGTH]
  1465. new Float:true_value_float[CVAR_MAX_ASSIGNED_VALUES]
  1466.  
  1467. new last = 0, newpos = 0, k = 0;
  1468.  
  1469. for (new i=0;i<CVAR_STRING_ALLOC;i++)
  1470. {
  1471. if(equal(value_string_float[i], ";", 1))
  1472. {
  1473. newpos = i
  1474. }
  1475.  
  1476. if (newpos > last)
  1477. {
  1478. for (new j=last;j<newpos;j++)
  1479. {
  1480. format(values_float[k], CVAR_MAX_STRING_LENGTH - 1, "%s%s", values_float[k], value_string_float[j])
  1481. }
  1482.  
  1483. last = newpos + 1
  1484. k++
  1485. }
  1486.  
  1487. if (k == CVAR_MAX_ASSIGNED_VALUES)
  1488. {
  1489. break
  1490. }
  1491. }
  1492.  
  1493. new bool:ok=false
  1494. new counter = 0
  1495.  
  1496. for (new i=0;i<k;i++)
  1497. {
  1498. counter++
  1499.  
  1500. true_value_float[i] = str_to_float(values_float[i])
  1501.  
  1502. if (ok == true)
  1503. {
  1504. set_pcvar_float(pcvars[Option:cvar], true_value_float[i])
  1505. counter = 0
  1506. break
  1507. }
  1508.  
  1509. if (true_value_float[i] == get_option_float(Option:cvar))
  1510. ok = true
  1511. }
  1512.  
  1513. if (counter == k)
  1514. {
  1515. set_pcvar_float(pcvars[Option:cvar], true_value_float[0])
  1516. }
  1517.  
  1518. }
  1519. }
  1520.  
  1521. menu_destroy(menu)
  1522. update_forward_registration()
  1523. cvar_menu(id, item / 7, cvar_menu_pos[id])
  1524. save_cfg()
  1525. return PLUGIN_HANDLED
  1526. }
  1527.  
  1528. public callback_disabled(id, menu, item)
  1529. {
  1530. return ITEM_DISABLED
  1531. }
  1532.  
  1533. public callback_enabled(id, menu, item)
  1534. {
  1535. return ITEM_ENABLED
  1536. }
  1537.  
  1538. /* -------------------------------
  1539. [Client Internet Forwards]
  1540. ------------------------------- */
  1541. public client_connect(id)
  1542. {
  1543. mode[id][GRENADE_EXPLOSIVE] = FirstEnabledMode(GRENADE_EXPLOSIVE)
  1544. mode[id][GRENADE_FLASHBANG] = FirstEnabledMode(GRENADE_FLASHBANG)
  1545. mode[id][GRENADE_SMOKEGREN] = FirstEnabledMode(GRENADE_SMOKEGREN)
  1546.  
  1547. resetCounter(id)
  1548. }
  1549.  
  1550. public client_putinserver(id)
  1551. {
  1552. // Add the bot property if user is bot
  1553. if (is_user_bot(id))
  1554. {
  1555. cl_is_bot |= (1<<id)
  1556.  
  1557. if (g_botquota != 0)
  1558. {
  1559. // Delay for private data to initialize
  1560. if (get_pcvar_num(g_botquota))
  1561. set_task(0.1, "task_botHamHooks", id)
  1562. }
  1563. }
  1564. }
  1565.  
  1566. public task_botHamHooks(id)
  1567. {
  1568. if (g_botquota == 0 || !is_user_connected(id))
  1569. return
  1570.  
  1571. // Check again for safety
  1572. if (is_user_bot(id) && get_pcvar_num(g_botquota) > 0)
  1573. {
  1574. // Post spawn fix for cz bots, since RegisterHam does not work for them
  1575. RegisterHamFromEntity(Ham_Killed, id, "fw_killed_post", 1)
  1576. RegisterHamFromEntity(Ham_Spawn, id, "fw_spawn_post", 1)
  1577. RegisterHamFromEntity(Ham_TakeDamage, id, "fw_takedamage")
  1578. RegisterHamFromEntity(Ham_Player_PreThink, id, "fw_playerprethink")
  1579.  
  1580. // Only needs to run once after ham is registed.
  1581. g_botquota = 0
  1582. }
  1583.  
  1584. // Added this if other bots that come here and don't know what to do.
  1585. fw_spawn_post(id)
  1586.  
  1587. }
  1588.  
  1589. public client_disconnected(id)
  1590. {
  1591. // Remove the bot property (doesn't matter wether it was true or false)
  1592. cl_is_bot &= ~(1<<id)
  1593.  
  1594. mode[id][GRENADE_EXPLOSIVE] = FirstEnabledMode(GRENADE_EXPLOSIVE)
  1595. mode[id][GRENADE_FLASHBANG] = FirstEnabledMode(GRENADE_FLASHBANG)
  1596. mode[id][GRENADE_SMOKEGREN] = FirstEnabledMode(GRENADE_SMOKEGREN)
  1597.  
  1598. resetCounter(id)
  1599.  
  1600. cl_nextusetime[id] = 0.0
  1601.  
  1602. cl_team[id] = CS_TEAM_UNASSIGNED
  1603. }
  1604.  
  1605. /* -------------------------------
  1606. [Forwards Registration Toggle]
  1607. ------------------------------- */
  1608. public update_forward_registration()
  1609. {
  1610. // Here we also update some global constants
  1611. cacheCvars()
  1612. g_maxplayers = get_maxplayers()
  1613.  
  1614. if (g_check_hpsystem == -1)
  1615. {
  1616. g_check_hpsystem = get_option(OPTION_MATERIAL_SYSTEM)
  1617. }
  1618. else
  1619. {
  1620. if (!is_nademodes_enabled() && get_option(OPTION_MATERIAL_SYSTEM) == 2)
  1621. {
  1622. new i=-1
  1623. while ((i = find_ent_by_class(i, "grenade")))
  1624. {
  1625. if (!is_grenade(i))
  1626. continue
  1627.  
  1628. if (entity_get_float(i, EV_FL_health))
  1629. {
  1630. entity_set_float(i, EV_FL_takedamage, DAMAGE_NO)
  1631. }
  1632. }
  1633. }
  1634.  
  1635. if (g_check_hpsystem != get_option(OPTION_MATERIAL_SYSTEM))
  1636. {
  1637. if ((get_option(OPTION_MATERIAL_SYSTEM) == 0 || get_option(OPTION_MATERIAL_SYSTEM) == 1) && g_check_hpsystem == 2)
  1638. {
  1639. new i=-1
  1640. while ((i = find_ent_by_class(i, "grenade")))
  1641. {
  1642. if (!is_grenade(i))
  1643. continue
  1644.  
  1645. if (entity_get_float(i, EV_FL_health))
  1646. {
  1647. entity_set_float(i, EV_FL_takedamage, DAMAGE_NO)
  1648. }
  1649. }
  1650. }
  1651.  
  1652. if (get_option(OPTION_MATERIAL_SYSTEM) == 2 && (g_check_hpsystem == 1 || g_check_hpsystem == 0))
  1653. {
  1654.  
  1655. new i=-1
  1656. while ((i = find_ent_by_class(i, "grenade")))
  1657. {
  1658. if (!is_grenade(i))
  1659. continue
  1660.  
  1661. if (entity_get_float(i, EV_FL_health))
  1662. {
  1663. entity_set_float(i, EV_FL_takedamage, DAMAGE_YES)
  1664. }
  1665. }
  1666. }
  1667. }
  1668.  
  1669. g_check_hpsystem = get_option(OPTION_MATERIAL_SYSTEM)
  1670. }
  1671.  
  1672. if (is_nademodes_enabled())
  1673. {
  1674. bs_forward_collection |= FWD_CMDSTART | FWD_SETMODEL | FWD_THINK | FWD_TOUCH
  1675.  
  1676. if (get_option(OPTION_DAMAGE_SYSTEM))
  1677. {
  1678. bs_forward_collection |= FWD_TAKEDAMAGE
  1679. }
  1680. else
  1681. {
  1682. bs_forward_collection &= ~FWD_TAKEDAMAGE
  1683. }
  1684.  
  1685. if (get_option(OPTION_RESOURCE_USE))
  1686. {
  1687. bs_forward_collection |= FWD_THINK_POST
  1688. }
  1689. else
  1690. {
  1691. bs_forward_collection &= ~FWD_THINK_POST
  1692. }
  1693.  
  1694. if (!get_option(OPTION_MATERIAL_SYSTEM) || get_option(OPTION_MATERIAL_SYSTEM) > 2 || get_option(OPTION_MATERIAL_SYSTEM) < 0)
  1695. {
  1696. bs_forward_collection &= ~(FWD_SEC_EXPLODE | FWD_HPSYSTEM)
  1697. }
  1698.  
  1699. if (get_option(OPTION_MATERIAL_SYSTEM) == 1)
  1700. {
  1701. bs_forward_collection |= FWD_SEC_EXPLODE
  1702. }
  1703. else
  1704. {
  1705. bs_forward_collection &= ~FWD_SEC_EXPLODE
  1706. }
  1707.  
  1708. if (get_option(OPTION_MATERIAL_SYSTEM) == 2)
  1709. {
  1710. bs_forward_collection |= FWD_HPSYSTEM
  1711. }
  1712. else
  1713. {
  1714. bs_forward_collection &= ~FWD_HPSYSTEM
  1715. }
  1716.  
  1717. if (get_option(OPTION_SUPPRESS_FITH))
  1718. {
  1719. bs_forward_collection |= FWD_MESSAGE
  1720. }
  1721. else
  1722. {
  1723. bs_forward_collection &= ~FWD_MESSAGE
  1724. }
  1725.  
  1726. }
  1727. else
  1728. {
  1729. bs_forward_collection = FWD_NONE_ACTIVE
  1730. }
  1731. }
  1732. /* -------------------------------
  1733. [Events]
  1734. ------------------------------- */
  1735. public event_armnade(id)
  1736. {
  1737. static nade
  1738.  
  1739. switch (read_data(2))
  1740. {
  1741. case CSW_HEGRENADE: nade = _:GRENADE_EXPLOSIVE
  1742. case CSW_FLASHBANG: nade = _:GRENADE_FLASHBANG
  1743. case CSW_SMOKEGRENADE: nade = _:GRENADE_SMOKEGREN
  1744. default: return PLUGIN_CONTINUE
  1745. }
  1746.  
  1747. if (!is_nademodes_enabled())
  1748. return PLUGIN_CONTINUE
  1749.  
  1750. if (get_option(OPTION_INFINITE_GRENADES + Option:nade))
  1751. {
  1752. cs_set_user_bpammo(id, NADE_WPID[NadeRace:nade], 2000)
  1753. }
  1754.  
  1755. if (!(cl_can_use_nade[NadeRace:nade] & (1<<id)))
  1756. {
  1757. client_print(id, print_center, "Mode: Not allowed to throw anymore!")
  1758. return PLUGIN_CONTINUE
  1759. }
  1760.  
  1761. if (get_option(OPTION_DISPLAY_MODE_ON_DRAW) && grenade_can_be_used(NadeRace:nade))
  1762. {
  1763. client_print(id, print_center, "Mode: %s", modetext[_:mode[id][NadeRace:nade]])
  1764. }
  1765.  
  1766. if (!is_mode_enabled(id, mode[id][NadeRace:nade], NadeRace:nade))
  1767. {
  1768. changemode(id, NadeRace:nade)
  1769. }
  1770.  
  1771. return PLUGIN_CONTINUE
  1772. }
  1773.  
  1774. public event_curweapon(id)
  1775. {
  1776. cl_weapon[id] = read_data(2)
  1777. }
  1778.  
  1779. public event_new_round()
  1780. {
  1781. static players[32], count, id
  1782. get_players(players, count)
  1783.  
  1784. for (new i=0;i<count;i++)
  1785. {
  1786. id = players[i]
  1787. resetCounter(id)
  1788. }
  1789.  
  1790. static ent
  1791.  
  1792. ent = -1
  1793. while ((ent = find_ent_by_class(ent, "grenade")))
  1794. {
  1795. if(is_grenade(ent) && get_grenade_type(ent) != NADE_NORMAL)
  1796. entity_set_int(ent, EV_INT_flags, entity_get_int(ent, EV_INT_flags) | FL_KILLME)
  1797. }
  1798.  
  1799. cacheCvars()
  1800.  
  1801. g_zombie_mod &= ~ZM_CAN_THINK // Disable thinking of ents before the first infection (this will prevent false explosions)
  1802.  
  1803. return PLUGIN_CONTINUE
  1804. }
  1805.  
  1806. /* -------------------------------
  1807. [Message Engine Forwads]
  1808. ------------------------------- */
  1809. public fith_audio(msg_id, msg_dest, entity)
  1810. {
  1811. if (!(bs_forward_collection & FWD_MESSAGE))
  1812. return PLUGIN_CONTINUE
  1813.  
  1814. // Get the string that holds the message and test it to see wether to block it or not
  1815. static string[18]
  1816. get_msg_arg_string(2, string, charsmax(string))
  1817.  
  1818. if (equal(string, "%!MRAD_FIREINHOLE")) return PLUGIN_HANDLED
  1819.  
  1820. return PLUGIN_CONTINUE
  1821. }
  1822.  
  1823. public fith_text(msg_id, msg_dest, entity)
  1824. {
  1825. if (!(bs_forward_collection & FWD_MESSAGE))
  1826. return PLUGIN_CONTINUE
  1827.  
  1828. static string[18]
  1829.  
  1830. // Get the string that holds the message and test it to see wether to block it or not
  1831. if (get_msg_args() == 5) // CS
  1832. {
  1833. get_msg_arg_string(5, string, charsmax(string))
  1834. }
  1835. else
  1836. {
  1837. if (get_msg_args() == 6) // CZ
  1838. {
  1839. get_msg_arg_string(6, string, charsmax(string))
  1840. }
  1841. else
  1842. {
  1843. return PLUGIN_CONTINUE
  1844. }
  1845. }
  1846.  
  1847. return (equal(string, "#Fire_in_the_hole")) ? PLUGIN_HANDLED : PLUGIN_CONTINUE
  1848. }
  1849.  
  1850. /* -------------------------------
  1851. [Ham & Fakemeta Forwards]
  1852. ------------------------------- */
  1853. public fw_playerprethink(id)
  1854. {
  1855. if (!is_user_connected(id) || is_user_connecting(id) || is_user_hltv(id))
  1856. return HAM_IGNORED
  1857.  
  1858. switch (cs_get_user_team(id))
  1859. {
  1860. case CS_TEAM_T: cl_team[id] = CS_TEAM_T
  1861. case CS_TEAM_CT: cl_team[id] = CS_TEAM_CT
  1862. default: return HAM_IGNORED
  1863. }
  1864.  
  1865. return HAM_IGNORED
  1866. }
  1867.  
  1868. public fw_cmdstart(id, uc_handle, seed)
  1869. {
  1870. if (!(bs_forward_collection & FWD_CMDSTART))
  1871. return FMRES_IGNORED
  1872.  
  1873. if (!(cl_is_alive & (1<<id)))
  1874. return FMRES_IGNORED
  1875.  
  1876. static bool:key[MAX_PLAYERS + 1] = {false, ...}
  1877.  
  1878. static buttons
  1879. buttons = get_uc(uc_handle, UC_Buttons)
  1880.  
  1881. if (!(buttons & IN_USE))
  1882. {
  1883. cl_nextusetime[id] = 0.0
  1884. }
  1885.  
  1886. if (buttons & IN_ATTACK)
  1887. {
  1888. switch (cl_weapon[id])
  1889. {
  1890. case CSW_HEGRENADE: if (!(cl_can_use_nade[GRENADE_EXPLOSIVE] & (1<<id))) set_uc(uc_handle, UC_Buttons, buttons & ~IN_ATTACK)
  1891. case CSW_FLASHBANG: if (!(cl_can_use_nade[GRENADE_FLASHBANG] & (1<<id))) set_uc(uc_handle, UC_Buttons, buttons & ~IN_ATTACK)
  1892. case CSW_SMOKEGRENADE: if (!(cl_can_use_nade[GRENADE_SMOKEGREN] & (1<<id))) set_uc(uc_handle, UC_Buttons, buttons & ~IN_ATTACK)
  1893. }
  1894. }
  1895.  
  1896. if (buttons & IN_ATTACK2)
  1897. {
  1898. if (!key[id])
  1899. {
  1900. switch (cl_weapon[id])
  1901. {
  1902. case CSW_HEGRENADE: if (cl_can_use_nade[GRENADE_EXPLOSIVE] & (1<<id)) changemode(id, GRENADE_EXPLOSIVE)
  1903. case CSW_FLASHBANG: if (cl_can_use_nade[GRENADE_FLASHBANG] & (1<<id)) changemode(id, GRENADE_FLASHBANG)
  1904. case CSW_SMOKEGRENADE: if (cl_can_use_nade[GRENADE_SMOKEGREN] & (1<<id)) changemode(id, GRENADE_SMOKEGREN)
  1905. }
  1906. }
  1907.  
  1908. key[id] = true
  1909. }
  1910. else
  1911. {
  1912. key[id] = false
  1913. }
  1914.  
  1915. return FMRES_IGNORED
  1916. }
  1917.  
  1918. public fw_setmodel(ent, model[])
  1919. {
  1920. if (!pev_valid(ent))
  1921. {
  1922. return FMRES_IGNORED
  1923. }
  1924.  
  1925. // Not yet thrown
  1926. if (entity_get_float(ent, EV_FL_gravity) == 0.0)
  1927. {
  1928. return FMRES_IGNORED
  1929. }
  1930.  
  1931. for (new i=0;i<3;i++)
  1932. {
  1933. if (containi(model, NADE_MODEL[i]) != -1)
  1934. {
  1935. set_pdata_int(ent, OFFSET_WEAPONID, NADE_WPID[NadeRace:i], EXTRAOFFSET_WEAPONS)
  1936.  
  1937. if (bs_forward_collection & FWD_SETMODEL)
  1938. grenade_process(pev(ent, pev_owner), ent, NadeRace:i)
  1939.  
  1940. break
  1941. }
  1942. }
  1943.  
  1944. return FMRES_IGNORED
  1945. }
  1946.  
  1947. grenade_process(id, grenade, NadeRace:nade)
  1948. {
  1949. if ((cl_is_bot & (1<<id)) && get_option(OPTION_BOT_ALLOW) && grenade_can_be_used(nade))
  1950. {
  1951. // We place the NADE_TRIP last so we can easily make another choice if it doesn't work ;)
  1952. static const NadeType:random_vec[] = {NADE_NORMAL, NADE_IMPACT, NADE_MOTION, NADE_PROXIMITY, NADE_HOMING, NADE_TRIP}
  1953. static NadeType:decision
  1954.  
  1955. decision = random_vec[random_num(0, charsmax(random_vec))]
  1956. mode[id][nade] = decision
  1957.  
  1958. if (is_mode_enabled(id, mode[id][nade], nade))
  1959. {
  1960. if (decision == NADE_TRIP)
  1961. {
  1962. static loop[4][2] = { {0, 1}, {0, -1}, {1, 1}, {1, -1} }
  1963. // Search in order: axis +X axis -X axis +Y axis -Y axis
  1964.  
  1965. new Float:origin[3], Float:end[3], Float:fdest[3], Float:calc_vector[3], Float:height, Float: minimum, Float:distance = 9999999.999, Float:fraction
  1966.  
  1967. entity_get_vector(id, EV_VEC_origin, origin)
  1968.  
  1969. xs_vec_copy(origin, end)
  1970. end[2] += 16000.0
  1971.  
  1972. engfunc(EngFunc_TraceLine, origin, end, IGNORE_MONSTERS, id, g_ptrace[TH_BOT])
  1973.  
  1974. get_tr2(g_ptrace[TH_BOT], TR_vecEndPos, end)
  1975.  
  1976. xs_vec_sub(end, origin, end)
  1977.  
  1978. height = xs_vec_len(end)
  1979.  
  1980.  
  1981. xs_vec_copy(origin, end)
  1982. end[2] -= 16000.0
  1983.  
  1984. engfunc(EngFunc_TraceLine, origin, end, IGNORE_MONSTERS, id, g_ptrace[TH_BOT])
  1985.  
  1986. get_tr2(g_ptrace[TH_BOT], TR_vecEndPos, end)
  1987.  
  1988. xs_vec_sub(end, origin, end)
  1989.  
  1990. height += xs_vec_len(end)
  1991.  
  1992. if ( height > BOT_FORCE_CROUCH_HEIGHT_CONST)
  1993. {
  1994. minimum = BOT_MIN_HEIGHT_ALLOW
  1995. }
  1996. else
  1997. {
  1998. minimum = BOT_MIN_CROUCH_HEIGHT_ALLOW
  1999. height -= BOT_MIN_CROUCH_HEIGHT_ALLOW
  2000.  
  2001. }
  2002.  
  2003. if ( height > BOT_MAX_HEIGHT_ALLOW )
  2004. {
  2005. height = BOT_MAX_HEIGHT_ALLOW
  2006. }
  2007.  
  2008. if (xs_vec_len(end) < height)
  2009. {
  2010. xs_vec_mul_scalar(end, - random_float(minimum - xs_vec_len(end),height - xs_vec_len(end)) / xs_vec_len(end), end)
  2011. xs_vec_add(end, origin, origin)
  2012. }
  2013. else
  2014. {
  2015. if (xs_vec_len(end) < height)
  2016. {
  2017. xs_vec_mul_scalar(end, (xs_vec_len(end) - random_float(minimum, height)) / xs_vec_len(end), end)
  2018. xs_vec_add(end, origin, origin)
  2019. }
  2020. else
  2021. {
  2022. xs_vec_mul_scalar(end, (xs_vec_len(end) - random_float(minimum, height)) / xs_vec_len(end), end)
  2023. xs_vec_add(end, origin, origin)
  2024. }
  2025. }
  2026.  
  2027. for(new i=0;i<4;i++)
  2028. {
  2029. // Add search direction
  2030. xs_vec_copy(origin, end)
  2031. end[loop[i][0]] = origin[loop[i][0]] + (16000.0 * float(loop[i][1]))
  2032.  
  2033. // Trace to get the entity where we can attach our nade
  2034. engfunc(EngFunc_TraceLine, origin, end, IGNORE_MONSTERS, id, g_ptrace[TH_BOT])
  2035.  
  2036. // Get fraction to see if it has hited something
  2037. get_tr2(g_ptrace[TH_BOT], TR_flFraction, fraction)
  2038.  
  2039. if (fraction < 1.0)
  2040. {
  2041. if ( (!is_attachable_surface(get_tr2(g_ptrace[TH_BOT], TR_pHit))) || get_tr2(g_ptrace[TH_BOT], TR_AllSolid) )
  2042. {
  2043. continue
  2044. }
  2045.  
  2046. // Get plane normal for the wall
  2047. get_tr2(g_ptrace[TH_BOT], TR_vecPlaneNormal, calc_vector)
  2048.  
  2049. // Check if we have a wall
  2050. if ( xs_vec_dot(calc_vector, Float:{0.0,0.0,1.0}) > BOT_WALL_MIN_COSINUS || xs_vec_dot(calc_vector, Float:{0.0,0.0,1.0}) < (-BOT_WALL_MIN_COSINUS) )
  2051. {
  2052. continue
  2053. }
  2054.  
  2055. // We use the end point for extra calculations
  2056. get_tr2(g_ptrace[TH_BOT], TR_vecEndPos, end)
  2057.  
  2058. xs_vec_sub(origin, end, calc_vector)
  2059.  
  2060. if (xs_vec_len(calc_vector) < distance)
  2061. {
  2062. distance = xs_vec_len(calc_vector)
  2063. xs_vec_normalize(calc_vector, calc_vector)
  2064. xs_vec_mul_scalar(calc_vector, 1.5, calc_vector)
  2065. xs_vec_add(end, calc_vector, end)
  2066. xs_vec_copy(end, fdest)
  2067. }
  2068. }
  2069.  
  2070. }
  2071.  
  2072. for(new i=0;i<2;i++)
  2073. {
  2074. for(new j=2;j<4;j++)
  2075. {
  2076. // Add search direction
  2077. xs_vec_copy(origin, end)
  2078.  
  2079. end[loop[i][0]] = origin[loop[i][0]] + (16000.0 * float(loop[i][1]))
  2080. end[loop[j][0]] = origin[loop[j][0]] + (16000.0 * float(loop[j][1]))
  2081.  
  2082. engfunc(EngFunc_TraceLine, origin, end, IGNORE_MONSTERS, id, g_ptrace[TH_BOT])
  2083.  
  2084. get_tr2(g_ptrace[TH_BOT], TR_flFraction, fraction)
  2085.  
  2086. if (fraction < 1.0)
  2087. {
  2088. if ( (!is_attachable_surface(get_tr2(g_ptrace[TH_BOT], TR_pHit))) || get_tr2(g_ptrace[TH_BOT], TR_AllSolid) )
  2089. {
  2090. continue
  2091. }
  2092.  
  2093. get_tr2(g_ptrace[TH_BOT], TR_vecPlaneNormal, calc_vector)
  2094.  
  2095. if ( xs_vec_dot(calc_vector, Float:{0.0,0.0,1.0}) > BOT_WALL_MIN_COSINUS || xs_vec_dot(calc_vector, Float:{0.0,0.0,1.0}) < (-BOT_WALL_MIN_COSINUS) )
  2096. {
  2097. continue
  2098. }
  2099.  
  2100. get_tr2(g_ptrace[TH_BOT], TR_vecEndPos, end)
  2101.  
  2102. xs_vec_sub(origin, end, calc_vector)
  2103.  
  2104. if (xs_vec_len(calc_vector) < distance)
  2105. {
  2106. distance = xs_vec_len(calc_vector)
  2107. xs_vec_normalize(calc_vector, calc_vector)
  2108. xs_vec_mul_scalar(calc_vector, 3.0, calc_vector)
  2109. xs_vec_add(end, calc_vector, end)
  2110. xs_vec_copy(end, fdest)
  2111. }
  2112.  
  2113. }
  2114.  
  2115. }
  2116. }
  2117.  
  2118. xs_vec_sub(fdest, origin, calc_vector)
  2119.  
  2120. if (xs_vec_len(calc_vector) <= BOT_MIN_DISTANCE_ATTACH)
  2121. {
  2122. xs_vec_normalize(calc_vector, calc_vector)
  2123. xs_vec_mul_scalar(calc_vector, 20.0, calc_vector)
  2124. entity_set_vector(grenade, EV_VEC_velocity, calc_vector)
  2125. entity_set_int(grenade, EV_INT_movetype, MOVETYPE_FLY)
  2126. entity_set_origin(grenade, fdest)
  2127. set_grenade_type(grenade, mode[id][nade])
  2128.  
  2129. }
  2130. else
  2131. {
  2132. decision = random_vec[random_num(0, charsmax(random_vec) - 1)]
  2133. mode[id][nade] = decision
  2134. set_grenade_type(grenade, mode[id][nade])
  2135. }
  2136.  
  2137. }
  2138. else
  2139. {
  2140. set_grenade_type(grenade, mode[id][nade])
  2141. }
  2142. }
  2143. else
  2144. {
  2145. mode[id][nade] = NADE_NORMAL
  2146. set_grenade_type(grenade, mode[id][nade])
  2147. }
  2148.  
  2149. return
  2150. }
  2151.  
  2152. if (is_nademodes_enabled() && is_mode_enabled(id, mode[id][nade], nade) && grenade_can_be_used(nade))
  2153. {
  2154. set_grenade_type(grenade, mode[id][nade])
  2155. }
  2156. else
  2157. {
  2158. changemode(id,nade);
  2159. set_grenade_type(grenade, mode[id][nade])
  2160. }
  2161.  
  2162. if (get_option(OPTION_RESET_MODE_ON_THROW))
  2163. {
  2164. mode[id][nade] = NADE_NORMAL
  2165. }
  2166.  
  2167. return
  2168. }
  2169.  
  2170. public fw_spawn(ent)
  2171. {
  2172. if (!pev_valid(ent))
  2173. return FMRES_IGNORED
  2174.  
  2175. static classname[32]
  2176. pev(ent, pev_classname, classname, charsmax(classname))
  2177.  
  2178. if(!TrieKeyExists(trace_attack_reg_class, classname))
  2179. {
  2180. RegisterHam(Ham_TraceAttack, classname, "fw_global_traceattack", 1)
  2181. TrieSetCell(trace_attack_reg_class, classname, true)
  2182. }
  2183.  
  2184. return FMRES_IGNORED
  2185. }
  2186.  
  2187. public fw_track_explosion(grenade)
  2188. {
  2189. if (entity_get_float(grenade, EV_FL_dmgtime) >= get_gametime())
  2190. return HAM_IGNORED
  2191.  
  2192. if (is_grenade_c4(grenade))
  2193. return HAM_IGNORED
  2194.  
  2195. new NadeType:type, owner
  2196. owner = entity_get_edict(grenade, EV_ENT_owner)
  2197. type = get_grenade_type(grenade)
  2198.  
  2199. if (!is_user_connected(owner) || is_user_connecting(owner) || cl_team[owner] == CS_TEAM_UNASSIGNED)
  2200. {
  2201. entity_set_int(grenade, EV_INT_flags, entity_get_int(grenade, EV_INT_flags) | FL_KILLME)
  2202. return HAM_IGNORED
  2203. }
  2204.  
  2205. if (_:type & NADE_DONT_COUNT)
  2206. {
  2207. return HAM_IGNORED
  2208. }
  2209. else
  2210. {
  2211. type &= ~NadeType:NADE_DONT_COUNT
  2212.  
  2213. if (get_grenade_race(grenade) == _:GRENADE_SMOKEGREN)
  2214. {
  2215. if (entity_get_float(grenade, EV_FL_animtime) == 0.0)
  2216. {
  2217. return HAM_IGNORED
  2218. }
  2219. else
  2220. {
  2221. entity_set_float(grenade, EV_FL_animtime, 0.0)
  2222. }
  2223.  
  2224. clear_line(grenade)
  2225. }
  2226. else
  2227. {
  2228. clear_line(grenade)
  2229. }
  2230.  
  2231. if (!(_:UNCOUNTABLE_NADE_MODES & (1 << (_:type + 1))))
  2232. {
  2233. cl_counter[owner][NadeRace:get_grenade_race(grenade)][type] -= 1
  2234. refresh_can_use_nade(owner, GRENADE_EXPLOSIVE)
  2235. refresh_can_use_nade(owner, GRENADE_FLASHBANG)
  2236. refresh_can_use_nade(owner, GRENADE_SMOKEGREN)
  2237. }
  2238.  
  2239. entity_set_int(grenade, EV_INT_iuser1, entity_get_int(grenade, EV_INT_iuser1) | NADE_DONT_COUNT)
  2240. }
  2241.  
  2242. if (!(bs_forward_collection & FWD_SEC_EXPLODE))
  2243. return HAM_IGNORED
  2244.  
  2245. new Float:origin[3]
  2246. new Float:range
  2247. entity_get_vector(grenade, EV_VEC_origin, origin)
  2248. range = get_option_float(OPTION_RADIUS_SEC_EXPLOSION)
  2249.  
  2250. new i
  2251. i = g_maxplayers
  2252.  
  2253. if (!get_option(OPTION_SEC_EXPLO_AFFECT) && get_grenade_race(grenade) == _:GRENADE_EXPLOSIVE)
  2254. {
  2255. while ((i = find_ent_in_sphere(i, origin, range)))
  2256. {
  2257. if (i == grenade)
  2258. continue
  2259.  
  2260. if (is_grenade(i, true))
  2261. {
  2262. if (entity_get_float(i, EV_FL_animtime) == 0.0 && get_grenade_race(i) == _:GRENADE_SMOKEGREN)
  2263. {
  2264. continue
  2265. }
  2266.  
  2267. make_explode(i)
  2268.  
  2269. if (get_grenade_race(i) == _:GRENADE_SMOKEGREN)
  2270. {
  2271. entity_set_int(i, EV_INT_flags, entity_get_int(i, EV_INT_flags) | FL_ONGROUND)
  2272. dllfunc(DLLFunc_Think, i)
  2273. }
  2274. }
  2275. }
  2276. }
  2277. else
  2278. {
  2279. static race
  2280. race = get_grenade_race(grenade)
  2281.  
  2282. while ((i = find_ent_in_sphere(i, origin, range)))
  2283. {
  2284. if (i == grenade)
  2285. continue
  2286.  
  2287. if (is_grenade(i, true))
  2288. {
  2289. if (get_grenade_race(i) == race)
  2290. {
  2291. if (entity_get_float(i, EV_FL_animtime) == 0.0 && race == _:GRENADE_SMOKEGREN)
  2292. {
  2293. continue
  2294. }
  2295.  
  2296. make_explode(i)
  2297.  
  2298. if (race == _:GRENADE_SMOKEGREN)
  2299. {
  2300. entity_set_int(i, EV_INT_flags, entity_get_int(i, EV_INT_flags) | FL_ONGROUND)
  2301. dllfunc(DLLFunc_Think, i)
  2302. }
  2303. }
  2304. }
  2305. }
  2306. }
  2307.  
  2308. return HAM_IGNORED
  2309. }
  2310.  
  2311. public fw_think(ent)
  2312. {
  2313. if (!(bs_forward_collection & FWD_THINK) || !is_valid_ent(ent))
  2314. return HAM_IGNORED
  2315.  
  2316. if (is_grenade_c4(ent))
  2317. return HAM_IGNORED
  2318.  
  2319. if ((g_zombie_mod & ZM_ZM_ACTIVE) && !(g_zombie_mod & ZM_CAN_THINK) && !(get_grenade_type(ent) == NADE_TRIP && (TRIP_ATTACHED <= get_trip_grenade_mode(ent) <= TRIP_WAITING)))
  2320. return HAM_IGNORED
  2321.  
  2322. static i, Float:origin[3], Float:porigin[3], Float:fraction, owner, bs_holds
  2323. static Float:radius, affect_owner, team_play, los
  2324.  
  2325. affect_owner = get_option(OPTION_AFFECT_OWNER)
  2326. team_play = get_option(OPTION_TEAM_PLAY)
  2327.  
  2328. entity_get_vector(ent, EV_VEC_origin, origin)
  2329.  
  2330. owner = entity_get_edict(ent, EV_ENT_owner)
  2331.  
  2332. if (!is_user_connected(owner) || is_user_connecting(owner) || cl_team[owner] == CS_TEAM_UNASSIGNED)
  2333. {
  2334. entity_set_int(ent, EV_INT_flags, entity_get_int(ent, EV_INT_flags) | FL_KILLME)
  2335. return HAM_IGNORED
  2336. }
  2337.  
  2338. switch (get_grenade_type(ent))
  2339. {
  2340. case NADE_DUD:
  2341. {
  2342. return HAM_SUPERCEDE
  2343. }
  2344.  
  2345. case NADE_NORMAL:
  2346. {
  2347. return HAM_IGNORED
  2348. }
  2349.  
  2350. case NADE_PROXIMITY:
  2351. {
  2352. if (!allow_grenade_explode(ent))
  2353. return HAM_IGNORED
  2354.  
  2355. if (entity_get_float(ent, EV_FL_fuser4) <= get_gametime())
  2356. play_sound(ent, BUTTON);
  2357.  
  2358. i = -1
  2359. radius = get_option_float(OPTION_RADIUS_PROXIMITY)
  2360. los = get_option(OPTION_PROXIMITY_LOS)
  2361.  
  2362. while ((i = find_ent_in_sphere(i, origin, radius)))
  2363. {
  2364. if (i > g_maxplayers)
  2365. {
  2366. if (get_option(OPTION_MONSTERMOD_SUPPORT))
  2367. {
  2368. if (is_ent_monster(i))
  2369. {
  2370. entity_get_vector(i, EV_VEC_origin, porigin)
  2371.  
  2372. engfunc(EngFunc_TraceLine, origin, porigin, IGNORE_MONSTERS, 0, g_ptrace[TH_LOS])
  2373. get_tr2(g_ptrace[TH_LOS], TR_flFraction, fraction)
  2374.  
  2375. if (fraction < 1.0)
  2376. continue
  2377.  
  2378. make_explode(ent)
  2379. return HAM_IGNORED
  2380. }
  2381. else
  2382. continue
  2383. }
  2384.  
  2385. return HAM_IGNORED
  2386. }
  2387.  
  2388. if (!is_player_alive(i))
  2389. continue
  2390.  
  2391. if (los)
  2392. {
  2393. entity_get_vector(i, EV_VEC_origin, porigin)
  2394.  
  2395. engfunc(EngFunc_TraceLine, origin, porigin, IGNORE_MONSTERS, 0, g_ptrace[TH_LOS])
  2396. get_tr2(g_ptrace[TH_LOS], TR_flFraction, fraction)
  2397.  
  2398. if (fraction < 1.0)
  2399. continue
  2400. }
  2401.  
  2402. if (i == owner)
  2403. {
  2404. if (affect_owner)
  2405. {
  2406. make_explode(ent)
  2407. return HAM_IGNORED
  2408. }
  2409. else
  2410. {
  2411. continue
  2412. }
  2413. }
  2414.  
  2415. if (!team_play)
  2416. {
  2417. make_explode(ent)
  2418. return HAM_IGNORED
  2419. }
  2420. else
  2421. {
  2422. if (cl_team[i] != cl_team[owner])
  2423. {
  2424. make_explode(ent)
  2425. return HAM_IGNORED
  2426. }
  2427. }
  2428. }
  2429. return HAM_IGNORED
  2430. }
  2431.  
  2432. case NADE_TRIP:
  2433. {
  2434. static hit, Float:point[3], Float:normal[3], Float:temp[3], Float:end[3], Float:fly[3]
  2435. static Float:fly_speed, Float:detect_distance, Float:arm_time
  2436.  
  2437. fly_speed = get_option_float(OPTION_TRIP_FLY_SPEED)
  2438. detect_distance = get_option_float(OPTION_TRIP_DETECT_DISTANCE)
  2439. arm_time = get_option_float(OPTION_ARM_TIME_TRIP)
  2440.  
  2441. switch (get_trip_grenade_mode(ent))
  2442. {
  2443. case TRIP_NOT_ATTACHED, TRIP_DETONATED:
  2444. {
  2445. return HAM_IGNORED
  2446. }
  2447.  
  2448. case TRIP_ATTACHED:
  2449. {
  2450. static loop[6][2] = { {2, 1}, {2, -1}, {0, 1}, {0, -1}, {1, 1}, {1, -1} }
  2451. // Search in order: +Z axis -Z axis +X axis -X axis +Y axis -Y axis
  2452.  
  2453. for (new i; i < 6; i++)
  2454. {
  2455. xs_vec_copy(origin, point)
  2456.  
  2457. point[loop[i][0]] = origin[loop[i][0]] + (2.0 * float(loop[i][1]))
  2458.  
  2459. engfunc(EngFunc_TraceLine, origin, point, IGNORE_MONSTERS, ent, g_ptrace[TH_TRIP])
  2460.  
  2461. get_tr2(g_ptrace[TH_TRIP], TR_flFraction, fraction)
  2462.  
  2463. if (fraction < 1.0)
  2464. {
  2465. hit = get_tr2(g_ptrace[TH_TRIP], TR_pHit)
  2466.  
  2467. if (!is_attachable_surface(hit))
  2468. {
  2469. set_grenade_type(ent, NADE_DUD)
  2470. return HAM_IGNORED
  2471. }
  2472.  
  2473. get_tr2(g_ptrace[TH_TRIP], TR_vecPlaneNormal, normal)
  2474.  
  2475. set_trip_grenade_attached_to(ent, hit)
  2476.  
  2477. // Calculate and store fly velocity.
  2478. xs_vec_mul_scalar(normal, fly_speed, temp)
  2479. set_trip_grenade_fly_velocity(ent, temp)
  2480.  
  2481. // Calculate and store endpoint.
  2482. xs_vec_mul_scalar(normal, detect_distance, temp)
  2483. xs_vec_add(temp, origin, end)
  2484.  
  2485. // Trace to it
  2486. engfunc(EngFunc_TraceLine, origin, end, IGNORE_MONSTERS, ent, g_ptrace[TH_TRIP])
  2487. get_tr2(g_ptrace[TH_TRIP], TR_flFraction, fraction)
  2488.  
  2489. // Final endpoint with no possible wall collision
  2490. xs_vec_mul_scalar(normal, (detect_distance * fraction), temp)
  2491. xs_vec_add(temp, origin, end)
  2492. set_trip_grenade_end_origin(ent, end)
  2493.  
  2494. xs_vec_mul_scalar(temp, 0.5, temp)
  2495. xs_vec_add(temp, origin, temp)
  2496. set_trip_grenade_middle_origin(ent, temp)
  2497.  
  2498. set_trip_grenade_arm_time(ent, arm_time)
  2499.  
  2500. play_sound(ent, DEPLOY)
  2501.  
  2502. entity_set_vector(ent, EV_VEC_velocity, Float:{0.0, 0.0, 0.0}) // Stop if from moving
  2503.  
  2504. entity_set_int(ent, EV_INT_sequence, 0) // Otherwise, grenade might make wierd motions.
  2505.  
  2506. vector_to_angle(normal, normal)
  2507.  
  2508. entity_set_vector(ent, EV_VEC_angles, normal)
  2509.  
  2510. set_trip_grenade_mode(ent, TRIP_WAITING)
  2511.  
  2512. set_task(0.1, "trip_activation", ent)
  2513.  
  2514. return HAM_IGNORED
  2515. }
  2516. }
  2517.  
  2518. // If we reach here, we have serious problems. This means that the grenade hit something like a func_breakable
  2519. // that disappeared before the scan was able to take place. Now, the grenade is floating in mid air. So we just
  2520. // kaboom it!!!
  2521.  
  2522. make_explode(ent)
  2523.  
  2524. if (NadeRace:get_grenade_race(ent) == GRENADE_SMOKEGREN)
  2525. {
  2526. entity_set_int(ent, EV_INT_flags, entity_get_int(ent, EV_INT_flags) | FL_ONGROUND)
  2527. }
  2528.  
  2529. return HAM_IGNORED
  2530. }
  2531.  
  2532. case TRIP_WAITING:
  2533. {
  2534.  
  2535. if (!is_attachable_surface(get_trip_grenade_attached_to(ent)))
  2536. {
  2537. make_explode(ent)
  2538.  
  2539. if (NadeRace:get_grenade_race(ent) == GRENADE_SMOKEGREN)
  2540. {
  2541. entity_set_int(ent, EV_INT_flags, entity_get_int(ent, EV_INT_flags) | FL_ONGROUND)
  2542. clear_line(ent)
  2543. }
  2544.  
  2545. return HAM_IGNORED
  2546. }
  2547.  
  2548. if (get_gametime() > get_trip_grenade_arm_time(ent))
  2549. {
  2550. set_trip_grenade_mode(ent, TRIP_SCANNING)
  2551. play_sound(ent, ACTIVATE)
  2552. }
  2553.  
  2554. return HAM_IGNORED
  2555. }
  2556.  
  2557. case TRIP_SCANNING:
  2558. {
  2559. if (!is_attachable_surface(get_trip_grenade_attached_to(ent)))
  2560. {
  2561. make_explode(ent)
  2562.  
  2563. if (NadeRace:get_grenade_race(ent) == GRENADE_SMOKEGREN)
  2564. {
  2565. entity_set_int(ent, EV_INT_flags, entity_get_int(ent, EV_INT_flags) | FL_ONGROUND)
  2566. clear_line(ent)
  2567. }
  2568.  
  2569. return HAM_IGNORED
  2570. }
  2571.  
  2572. get_trip_grenade_end_origin(ent, end)
  2573. engfunc(EngFunc_TraceLine, end, origin, DONT_IGNORE_MONSTERS, 0, g_ptrace[TH_TRIP])
  2574.  
  2575. static target
  2576. target = get_tr2(g_ptrace[TH_TRIP], TR_pHit)
  2577.  
  2578. if (is_player_alive(target))
  2579. {
  2580. if (owner == target)
  2581. {
  2582. if (affect_owner)
  2583. {
  2584. set_trip_grenade_mode(ent, TRIP_SHOULD_DETONATE)
  2585. entity_set_float(ent, EV_FL_nextthink, get_gametime() + 0.001)
  2586. return HAM_IGNORED
  2587. }
  2588. else
  2589. {
  2590. entity_set_float(ent, EV_FL_nextthink, get_gametime() + 0.001)
  2591. return HAM_IGNORED
  2592. }
  2593. }
  2594.  
  2595. if (!team_play)
  2596. {
  2597. set_trip_grenade_mode(ent, TRIP_SHOULD_DETONATE)
  2598. }
  2599. else
  2600. {
  2601. if (cl_team[owner] != cl_team[target])
  2602. set_trip_grenade_mode(ent, TRIP_SHOULD_DETONATE)
  2603. }
  2604. }
  2605. else if (get_option(OPTION_MONSTERMOD_SUPPORT) && is_ent_monster(target))
  2606. {
  2607. set_trip_grenade_mode(ent, TRIP_SHOULD_DETONATE)
  2608. }
  2609.  
  2610. entity_set_float(ent, EV_FL_nextthink, get_gametime() + 0.001)
  2611. return HAM_IGNORED
  2612. }
  2613.  
  2614. case TRIP_SHOULD_DETONATE:
  2615. {
  2616. static mode
  2617. mode = get_trip_grenade_react_method(ent)
  2618. set_trip_grenade_mode(ent, TRIP_DETONATED)
  2619.  
  2620. clear_line(ent)
  2621. play_sound(ent, ACTIVATE)
  2622.  
  2623. if (mode == 0)
  2624. {
  2625. cl_counter[owner][NadeRace:get_grenade_race(ent)][NADE_TRIP] -= 1
  2626.  
  2627. refresh_can_use_nade(owner, GRENADE_EXPLOSIVE)
  2628. refresh_can_use_nade(owner, GRENADE_FLASHBANG)
  2629. refresh_can_use_nade(owner, GRENADE_SMOKEGREN)
  2630.  
  2631. get_trip_grenade_fly_velocity(ent, fly)
  2632. get_trip_grenade_end_origin(ent, end)
  2633. entity_set_vector(ent, EV_VEC_velocity, fly) // Send the grenade on its way.
  2634. set_grenade_type(ent, NADE_IMPACT) // Kaboom!
  2635. }
  2636. else
  2637. {
  2638. make_explode(ent)
  2639.  
  2640. if (NadeRace:get_grenade_race(ent) == GRENADE_SMOKEGREN)
  2641. {
  2642. entity_set_int(ent, EV_INT_flags, entity_get_int(ent, EV_INT_flags) | FL_ONGROUND)
  2643. clear_line(ent)
  2644. }
  2645. }
  2646.  
  2647. return HAM_IGNORED
  2648. }
  2649. }
  2650. }
  2651.  
  2652. case NADE_MOTION:
  2653. {
  2654. if (!allow_grenade_explode(ent))
  2655. return HAM_IGNORED
  2656.  
  2657. static Float:v[3], Float:velocity
  2658.  
  2659. i = -1
  2660. bs_holds = 0
  2661. radius = get_option_float(OPTION_RADIUS_MOTION)
  2662. los = get_option(OPTION_MOTION_LOS)
  2663.  
  2664. while ((i = find_ent_in_sphere(i, origin, radius)))
  2665. {
  2666. if (i > g_maxplayers)
  2667. {
  2668. entity_set_int(ent, EV_INT_iuser2, bs_holds)
  2669.  
  2670. if (get_option(OPTION_MONSTERMOD_SUPPORT))
  2671. {
  2672. if (is_ent_monster(i))
  2673. {
  2674. entity_get_vector(i, EV_VEC_origin, porigin)
  2675.  
  2676. engfunc(EngFunc_TraceLine, origin, porigin, IGNORE_MONSTERS, 0, g_ptrace[TH_LOS])
  2677. get_tr2(g_ptrace[TH_LOS], TR_flFraction, fraction)
  2678.  
  2679. if (fraction < 1.0)
  2680. continue
  2681.  
  2682. entity_get_vector(i, EV_VEC_velocity, v)
  2683. velocity = xs_vec_len(v)
  2684.  
  2685. if (velocity > 115.0)
  2686. {
  2687. make_explode(ent)
  2688. return HAM_IGNORED
  2689. }
  2690. }
  2691. else
  2692. continue
  2693. }
  2694.  
  2695. return HAM_IGNORED
  2696. }
  2697.  
  2698. if (!is_player_alive(i))
  2699. continue
  2700.  
  2701. if (los)
  2702. {
  2703. entity_get_vector(i, EV_VEC_origin, porigin)
  2704.  
  2705. engfunc(EngFunc_TraceLine, origin, porigin, IGNORE_MONSTERS, 0, g_ptrace[TH_LOS])
  2706. get_tr2(g_ptrace[TH_LOS], TR_flFraction, fraction)
  2707.  
  2708. if (fraction < 1.0)
  2709. continue
  2710. }
  2711.  
  2712. entity_get_vector(i, EV_VEC_velocity, v)
  2713. velocity = xs_vec_len(v)
  2714.  
  2715. if (velocity > 215.0)
  2716. {
  2717. if (i == owner)
  2718. {
  2719. if (affect_owner)
  2720. {
  2721. make_explode(ent)
  2722. return HAM_IGNORED
  2723. }
  2724. else
  2725. {
  2726. bs_holds |= (1<<i)
  2727. continue
  2728. }
  2729. }
  2730. if (!team_play)
  2731. {
  2732. make_explode(ent)
  2733. return HAM_IGNORED
  2734. }
  2735. else
  2736. {
  2737. if (cl_team[i] != cl_team[owner])
  2738. {
  2739. make_explode(ent)
  2740. return HAM_IGNORED
  2741. }
  2742. }
  2743.  
  2744. bs_holds |= (1<<i)
  2745. entity_set_int(ent, EV_INT_iuser2, bs_holds)
  2746. play_sound(ent, GEIGER)
  2747. }
  2748. else if (velocity == 0.0)
  2749. {
  2750. continue
  2751. }
  2752. else
  2753. {
  2754. play_sound(ent, GEIGER)
  2755.  
  2756. // Add the player to the bitsum if he is moving
  2757. bs_holds |= (1<<i)
  2758. }
  2759.  
  2760. }
  2761.  
  2762. entity_set_int(ent, EV_INT_iuser2, bs_holds)
  2763. return HAM_IGNORED
  2764. }
  2765.  
  2766. case NADE_SATCHEL:
  2767. {
  2768. if (!allow_grenade_explode(ent))
  2769. return HAM_IGNORED
  2770.  
  2771. if (entity_get_int(owner, EV_INT_button) & IN_USE)
  2772. {
  2773. if (get_option(OPTION_SATCHEL_DELAY))
  2774. {
  2775. if (cl_nextusetime[owner] > get_gametime())
  2776. {
  2777. return HAM_IGNORED
  2778. }
  2779. else
  2780. {
  2781. cl_nextusetime[owner] = get_gametime() + DELAY_ADDED_TO_USE
  2782. }
  2783. }
  2784.  
  2785. make_explode(ent)
  2786.  
  2787. if (NadeRace:get_grenade_race(ent) == GRENADE_SMOKEGREN)
  2788. {
  2789. entity_set_int(ent, EV_INT_flags, entity_get_int(ent, EV_INT_flags) | FL_ONGROUND)
  2790. }
  2791. }
  2792.  
  2793.  
  2794. return HAM_IGNORED
  2795. }
  2796.  
  2797. case NADE_HOMING:
  2798. {
  2799. static target, Float:extravel
  2800. target = entity_get_int(ent, EV_INT_iuser2)
  2801. extravel = get_option_float(OPTION_HOMING_SPEED_ADD)
  2802.  
  2803. if (target == 0)
  2804. {
  2805. static i, Float:distance
  2806. i = -1
  2807. distance = get_option_float(OPTION_HOMING_SCAN_RANGE)
  2808.  
  2809. while ((i = find_ent_in_sphere(i, origin, distance)))
  2810. {
  2811. if (i > g_maxplayers)
  2812. {
  2813. if (get_option(OPTION_MONSTERMOD_SUPPORT))
  2814. {
  2815. if (is_ent_monster(i))
  2816. {
  2817. static Float:o[3]
  2818. entity_get_vector(i, EV_VEC_origin, o)
  2819. static Float:new_distance
  2820. new_distance = get_distance_f(o, origin)
  2821.  
  2822. if (new_distance < distance)
  2823. {
  2824. distance = new_distance
  2825. entity_set_int(ent, EV_INT_iuser2, i)
  2826. }
  2827. }
  2828. else
  2829. {
  2830. continue
  2831. }
  2832. }
  2833. else
  2834. break
  2835. }
  2836.  
  2837. if (!is_player_alive(i))
  2838. continue
  2839.  
  2840. if (i == owner)
  2841. continue
  2842.  
  2843. if ((cl_team[i] != cl_team[owner] && team_play) || !team_play)
  2844. {
  2845. static Float:o[3]
  2846. entity_get_vector(i, EV_VEC_origin, o)
  2847. static Float:new_distance
  2848. new_distance = get_distance_f(o, origin)
  2849.  
  2850. if (new_distance < distance)
  2851. {
  2852. distance = new_distance
  2853. entity_set_int(ent, EV_INT_iuser2, i)
  2854. }
  2855. }
  2856. }
  2857.  
  2858. return HAM_IGNORED
  2859. }
  2860. else if (!(cl_is_alive & (1<<target)) && target <= g_maxplayers)
  2861. {
  2862. return HAM_IGNORED
  2863. }
  2864. else if (is_in_los(ent, target))
  2865. {
  2866. //set_user_rendering(target)
  2867. static Float:velocity[3], Float:aim[3], Float:targetorigin[3], Float:velocity_normal[3], Float:aim_normal[3]
  2868.  
  2869. entity_get_vector(target, EV_VEC_origin, targetorigin)
  2870.  
  2871. entity_get_vector(ent, EV_VEC_velocity, velocity)
  2872.  
  2873. xs_vec_sub(targetorigin, origin, aim)
  2874.  
  2875. xs_vec_normalize(velocity, velocity_normal)
  2876. xs_vec_normalize(aim, aim_normal)
  2877.  
  2878. play_sound(ent, PING)
  2879.  
  2880. if (velocity_normal[0] < aim_normal[0])
  2881. {
  2882. velocity[0] += extravel
  2883. }
  2884. else if (velocity_normal[0] > aim_normal[0])
  2885. {
  2886. velocity[0] -= extravel
  2887. }
  2888.  
  2889. if (velocity_normal[1] < aim_normal[1])
  2890. {
  2891. velocity[1] += extravel
  2892. }
  2893. else if (velocity_normal[1] > aim_normal[1])
  2894. {
  2895. velocity[1] -= extravel
  2896. }
  2897.  
  2898. if (velocity_normal[2] < aim_normal[2])
  2899. {
  2900. velocity[2] += extravel
  2901. }
  2902. else if (velocity_normal[2] > aim_normal[2])
  2903. {
  2904. velocity[2] -= extravel
  2905. }
  2906.  
  2907. velocity[2] += 5.0
  2908.  
  2909. entity_set_vector(ent, EV_VEC_velocity, velocity)
  2910.  
  2911. // When within blasting range, make our homing grenade think much much faster; results in better homing.
  2912. if (get_distance_f(origin, targetorigin) < get_option_float(OPTION_HOMING_SUPER_RANGE))
  2913. {
  2914. entity_set_float(ent, EV_FL_nextthink, (get_gametime() + 0.05))
  2915. }
  2916. else
  2917. {
  2918. entity_set_float(ent, EV_FL_nextthink, (get_gametime() + 0.15))
  2919. }
  2920. }
  2921.  
  2922. return HAM_IGNORED
  2923. }
  2924. }
  2925.  
  2926. return HAM_IGNORED
  2927. }
  2928.  
  2929. public trip_activation(ent)
  2930. {
  2931. if (is_valid_ent(ent))
  2932. play_sound(ent, CHARGE)
  2933. }
  2934.  
  2935. public fw_think_post(ent)
  2936. {
  2937. if (!is_valid_ent(ent))
  2938. return HAM_IGNORED
  2939.  
  2940. if (is_grenade_c4(ent))
  2941. return HAM_IGNORED
  2942.  
  2943. static owner, Float:origin[3], Float:gametime, bs_affected
  2944.  
  2945. gametime = get_gametime()
  2946.  
  2947. if (entity_get_float(ent, EV_FL_dmgtime) <= gametime)
  2948. return HAM_IGNORED
  2949.  
  2950. entity_get_vector(ent, EV_VEC_origin, origin)
  2951. owner = entity_get_edict(ent, EV_ENT_owner)
  2952.  
  2953. if (!is_user_connected(owner) || is_user_connecting(owner) || cl_team[owner] == CS_TEAM_UNASSIGNED)
  2954. {
  2955. entity_set_int(ent, EV_INT_flags, entity_get_int(ent, EV_INT_flags) | FL_KILLME)
  2956. return HAM_IGNORED
  2957. }
  2958.  
  2959. if (!(bs_forward_collection & FWD_THINK_POST))
  2960. {
  2961. switch (get_grenade_type(ent))
  2962. {
  2963. case NADE_PROXIMITY:
  2964. {
  2965. // We do this for the sound of the entity
  2966. if (entity_get_float(ent, EV_FL_fuser4) <= gametime)
  2967. entity_set_float(ent, EV_FL_fuser4, gametime + 2.0)
  2968. }
  2969. case NADE_TRIP:
  2970. {
  2971. // We do this in order to make the trip nades be 10000% more accurate!
  2972. entity_set_float(ent, EV_FL_nextthink, get_gametime() + 0.001)
  2973. }
  2974. }
  2975.  
  2976. return HAM_IGNORED
  2977. }
  2978.  
  2979. bs_affected = 0
  2980.  
  2981. if (get_option(OPTION_RESOURCE_USE) != 3)
  2982. {
  2983. bs_affected = ~0
  2984. }
  2985. else
  2986. {
  2987. static team_play, affect_owner
  2988. team_play = get_option(OPTION_TEAM_PLAY)
  2989. affect_owner = get_option(OPTION_AFFECT_OWNER)
  2990.  
  2991. if (!team_play)
  2992. {
  2993. bs_affected = affect_owner ? ~0 : ~(1<<owner)
  2994. }
  2995. else
  2996. {
  2997. for (new i=1;i<=g_maxplayers;i++)
  2998. {
  2999. if (!is_user_connected(i))
  3000. continue
  3001.  
  3002. if (affect_owner & i == owner)
  3003. bs_affected |= (1<<i)
  3004.  
  3005. if (team_play && cs_get_user_team(i) != cs_get_user_team(owner))
  3006. bs_affected |= (1<<i)
  3007. }
  3008. }
  3009. }
  3010.  
  3011. switch (get_grenade_type(ent))
  3012. {
  3013. case NADE_PROXIMITY:
  3014. {
  3015. if (!allow_grenade_explode(ent))
  3016. return HAM_IGNORED
  3017.  
  3018. if (entity_get_float(ent, EV_FL_fuser4) <= gametime)
  3019. {
  3020. entity_set_float(ent, EV_FL_fuser4, gametime + 2.0)
  3021.  
  3022. if (entity_get_int(ent, EV_INT_flags) & FL_ONGROUND)
  3023. {
  3024. if (!get_option(OPTION_TEAM_PLAY) || ((g_zombie_mod & ZM_ZM_ACTIVE) && !(g_zombie_mod & ZM_CAN_THINK)))
  3025. {
  3026. if (get_option(OPTION_RESOURCE_USE) == 1)
  3027. {
  3028. show_ring(origin, get_option_float(OPTION_RADIUS_PROXIMITY) * RING_SIZE_CONSTANT_PROXIMITY, 5)
  3029. }
  3030. else
  3031. {
  3032. static i
  3033. i = -1
  3034.  
  3035. while ( (i = find_ent_in_sphere(i, origin, SMART_RADIUS_RING_SHOW)) )
  3036. {
  3037. if (i > g_maxplayers)
  3038. break
  3039.  
  3040. if (!(cl_is_alive & (1<<i)) || (cl_is_bot & (1<<i)))
  3041. continue
  3042.  
  3043. if (bs_affected & (1<<i))
  3044. show_ring(origin, get_option_float(OPTION_RADIUS_PROXIMITY) * RING_SIZE_CONSTANT_PROXIMITY, 5, _, _, _, i)
  3045. }
  3046. }
  3047. }
  3048. else
  3049. {
  3050. switch (cl_team[owner])
  3051. {
  3052. case CS_TEAM_T:
  3053. {
  3054. if (get_option(OPTION_RESOURCE_USE) == 1)
  3055. {
  3056. show_ring(origin, get_option_float(OPTION_RADIUS_PROXIMITY) * RING_SIZE_CONSTANT_PROXIMITY, 5, TEAMTE_RGB_R_COLOR, TEAMTE_RGB_G_COLOR, TEAMTE_RGB_B_COLOR)
  3057. }
  3058. else
  3059. {
  3060. static i
  3061. i = -1
  3062.  
  3063. while ( (i = find_ent_in_sphere(i, origin, SMART_RADIUS_RING_SHOW)) )
  3064. {
  3065. if (i > g_maxplayers)
  3066. break
  3067.  
  3068. if (!(cl_is_alive & (1<<i)) || (cl_is_bot & (1<<i)))
  3069. continue
  3070.  
  3071. if (bs_affected & (1<<i))
  3072. show_ring(origin, get_option_float(OPTION_RADIUS_PROXIMITY) * RING_SIZE_CONSTANT_PROXIMITY, 5, TEAMTE_RGB_R_COLOR, TEAMTE_RGB_G_COLOR, TEAMTE_RGB_B_COLOR, i)
  3073. }
  3074. }
  3075.  
  3076. }
  3077. case CS_TEAM_CT:
  3078. {
  3079. if (get_option(OPTION_RESOURCE_USE) == 1)
  3080. {
  3081. show_ring(origin, get_option_float(OPTION_RADIUS_PROXIMITY) * RING_SIZE_CONSTANT_PROXIMITY, 5, TEAMCT_RGB_R_COLOR, TEAMCT_RGB_G_COLOR, TEAMCT_RGB_B_COLOR)
  3082. }
  3083. else
  3084. {
  3085. static i
  3086. i = -1
  3087.  
  3088. while ( (i = find_ent_in_sphere(i, origin, SMART_RADIUS_RING_SHOW)) )
  3089. {
  3090. if (i > g_maxplayers)
  3091. break
  3092.  
  3093. if (!(cl_is_alive & (1<<i)) || (cl_is_bot & (1<<i)))
  3094. continue
  3095.  
  3096. if (bs_affected & (1<<i))
  3097. show_ring(origin, get_option_float(OPTION_RADIUS_PROXIMITY) * RING_SIZE_CONSTANT_PROXIMITY, 5, TEAMCT_RGB_R_COLOR, TEAMCT_RGB_G_COLOR, TEAMCT_RGB_B_COLOR, i)
  3098. }
  3099. }
  3100. }
  3101. }
  3102. }
  3103. }
  3104. }
  3105. }
  3106.  
  3107. case NADE_MOTION:
  3108. {
  3109. static bs_holds
  3110. bs_holds = entity_get_int(ent, EV_INT_iuser2)
  3111.  
  3112. if (bs_holds && entity_get_float(ent, EV_FL_fuser4) <= gametime)
  3113. {
  3114. entity_set_float(ent, EV_FL_fuser4, get_gametime() + 0.1)
  3115.  
  3116. if (!get_option(OPTION_TEAM_PLAY) || ((g_zombie_mod & ZM_ZM_ACTIVE) && !(g_zombie_mod & ZM_CAN_THINK)))
  3117. {
  3118. if ( get_option(OPTION_RESOURCE_USE) == 1)
  3119. {
  3120. show_ring(origin, get_option_float(OPTION_RADIUS_MOTION) * RING_SIZE_CONSTANT_MOTION, 1)
  3121. }
  3122. else
  3123. {
  3124. for (new i=1;i<=g_maxplayers;i++)
  3125. {
  3126. if ((bs_holds & (1<<i)) && (bs_affected & (1<<i)))
  3127. show_ring(origin, get_option_float(OPTION_RADIUS_MOTION) * RING_SIZE_CONSTANT_MOTION, 1, _, _, _, i)
  3128. }
  3129. }
  3130. }
  3131. else
  3132. {
  3133. switch (cl_team[owner])
  3134. {
  3135. case CS_TEAM_T:
  3136. {
  3137. if ( get_option(OPTION_RESOURCE_USE) == 1 )
  3138. {
  3139. show_ring(origin, get_option_float(OPTION_RADIUS_MOTION) * RING_SIZE_CONSTANT_MOTION, 1, TEAMTE_RGB_R_COLOR, TEAMTE_RGB_G_COLOR, TEAMTE_RGB_B_COLOR)
  3140. }
  3141. else
  3142. {
  3143. for (new i=1;i<=g_maxplayers;i++)
  3144. {
  3145. if ((bs_holds & (1<<i)) && (bs_affected & (1<<i)))
  3146. show_ring(origin, get_option_float(OPTION_RADIUS_MOTION) * RING_SIZE_CONSTANT_MOTION, 1, TEAMTE_RGB_R_COLOR, TEAMTE_RGB_G_COLOR, TEAMTE_RGB_B_COLOR, i)
  3147. }
  3148. }
  3149. }
  3150. case CS_TEAM_CT:
  3151. {
  3152. if ( get_option(OPTION_RESOURCE_USE) == 1 )
  3153. {
  3154. show_ring(origin, get_option_float(OPTION_RADIUS_MOTION) * RING_SIZE_CONSTANT_MOTION, 1, TEAMCT_RGB_R_COLOR, TEAMCT_RGB_G_COLOR, TEAMCT_RGB_B_COLOR)
  3155. }
  3156. else
  3157. {
  3158. for (new i=1;i<=g_maxplayers;i++)
  3159. {
  3160. if ((bs_holds & (1<<i)) && (bs_affected & (1<<i)))
  3161. show_ring(origin, get_option_float(OPTION_RADIUS_MOTION) * RING_SIZE_CONSTANT_MOTION, 1, TEAMCT_RGB_R_COLOR, TEAMCT_RGB_G_COLOR, TEAMCT_RGB_B_COLOR, i)
  3162. }
  3163. }
  3164. }
  3165. default:
  3166. {
  3167. if ( get_option(OPTION_RESOURCE_USE) == 1 )
  3168. {
  3169. show_ring(origin, get_option_float(OPTION_RADIUS_MOTION) * RING_SIZE_CONSTANT_MOTION, 1, _, _, _)
  3170. }
  3171. else
  3172. {
  3173. for (new i=1;i<=g_maxplayers;i++)
  3174. {
  3175. if ((bs_holds & (1<<i)) && (bs_affected & (1<<i)))
  3176. show_ring(origin, get_option_float(OPTION_RADIUS_MOTION) * RING_SIZE_CONSTANT_MOTION, 1, _, _, _, i)
  3177. }
  3178. }
  3179. }
  3180. }
  3181. }
  3182. }
  3183. }
  3184.  
  3185. case NADE_TRIP:
  3186. {
  3187. if (get_trip_grenade_mode(ent) != TRIP_SCANNING)
  3188. return HAM_IGNORED
  3189.  
  3190. // We do this in order to make the trip nades be 10000% more accurate!
  3191. entity_set_float(ent, EV_FL_nextthink, get_gametime() + 0.001)
  3192.  
  3193. if (entity_get_float(ent, EV_FL_fuser4) <= gametime)
  3194. {
  3195. new Float:end[3]
  3196. get_trip_grenade_end_origin(ent, end)
  3197.  
  3198. if (get_option(OPTION_RESOURCE_USE) == 1)
  3199. {
  3200. if (!get_option(OPTION_TEAM_PLAY) || ((g_zombie_mod & ZM_ZM_ACTIVE) && !(g_zombie_mod & ZM_CAN_THINK)))
  3201. {
  3202. draw_line_from_entity_broadcast(ent, end, 5, _, _, _)
  3203. }
  3204. else
  3205. {
  3206. switch (cl_team[owner])
  3207. {
  3208. case CS_TEAM_T:
  3209. {
  3210. draw_line_from_entity_broadcast(ent, end, 5, TEAMTE_RGB_R_COLOR, TEAMTE_RGB_G_COLOR, TEAMTE_RGB_B_COLOR)
  3211. }
  3212. case CS_TEAM_CT:
  3213. {
  3214. draw_line_from_entity_broadcast(ent, end, 5, TEAMCT_RGB_R_COLOR, TEAMCT_RGB_G_COLOR, TEAMCT_RGB_B_COLOR)
  3215. }
  3216. default:
  3217. {
  3218. draw_line_from_entity_broadcast(ent, end, 5, _, _, _)
  3219. }
  3220. }
  3221. }
  3222.  
  3223. entity_set_float(ent, EV_FL_fuser4, gametime + 0.5)
  3224. return HAM_IGNORED
  3225. }
  3226.  
  3227. static Float:first[3], Float:second[3], Float:porigin[3], Float:anglefraction, Float:third[3], Float:fourth[3]
  3228.  
  3229. xs_vec_sub(origin,end,first)
  3230.  
  3231. anglefraction = 1.0 - calc_cone_angle_from_distance(xs_vec_len(first))
  3232.  
  3233. if (xs_vec_len(first) <= SMART_DISTANCE_LINE_PVS)
  3234. {
  3235. get_trip_grenade_middle_origin(ent, first)
  3236.  
  3237. if (!get_option(OPTION_TEAM_PLAY) || ((g_zombie_mod & ZM_ZM_ACTIVE) && !(g_zombie_mod & ZM_CAN_THINK)))
  3238. {
  3239. draw_line_from_entity(ent, end, 5, _, _, _, 0, first)
  3240. }
  3241. else
  3242. {
  3243. switch (cl_team[owner])
  3244. {
  3245. case CS_TEAM_T:
  3246. {
  3247. draw_line_from_entity(ent, end, 5, TEAMTE_RGB_R_COLOR, TEAMTE_RGB_G_COLOR, TEAMTE_RGB_B_COLOR, 0, first)
  3248. }
  3249. case CS_TEAM_CT:
  3250. {
  3251. draw_line_from_entity(ent, end, 5, TEAMCT_RGB_R_COLOR, TEAMCT_RGB_G_COLOR, TEAMCT_RGB_B_COLOR, 0, first)
  3252. }
  3253. default:
  3254. {
  3255. draw_line_from_entity(ent, end, 5, _, _, _, 0, first)
  3256. }
  3257. }
  3258. }
  3259.  
  3260. entity_set_float(ent, EV_FL_fuser4, gametime + 0.5)
  3261. return HAM_IGNORED
  3262. }
  3263.  
  3264. xs_vec_mul_scalar(first,EXTRALENGTH_VECTOR / xs_vec_len(first),first)
  3265. xs_vec_sub(end,first,fourth)
  3266. xs_vec_add(origin,first,first)
  3267.  
  3268. static players[32],num,id
  3269. get_players(players,num,"ac")
  3270.  
  3271. for (new i=0;i<num;i++)
  3272. {
  3273. id = players[i]
  3274. entity_get_vector(id, EV_VEC_origin, porigin)
  3275.  
  3276. xs_vec_sub(porigin, fourth, second)
  3277. xs_vec_normalize(second, second)
  3278.  
  3279. xs_vec_sub(porigin, first, third)
  3280. xs_vec_normalize(third, third)
  3281.  
  3282. xs_vec_sub(first,fourth,first)
  3283. xs_vec_normalize(first,first)
  3284.  
  3285. if ( xs_vec_dot(first,second) <= CONE_DROP_ANGLE_COSINUS || (0 - xs_vec_dot(first,third)) <= CONE_DROP_ANGLE_COSINUS )
  3286. continue
  3287.  
  3288. if (bs_affected & (1<<id))
  3289. {
  3290. if ( xs_vec_dot(first, second) >= anglefraction )
  3291. {
  3292. if (!get_option(OPTION_TEAM_PLAY) || ((g_zombie_mod & ZM_ZM_ACTIVE) && !(g_zombie_mod & ZM_CAN_THINK)))
  3293. {
  3294. draw_line_from_entity(ent, end, 5, _, _, _, id)
  3295. }
  3296. else
  3297. {
  3298. switch (cl_team[owner])
  3299. {
  3300. case CS_TEAM_T:
  3301. {
  3302. draw_line_from_entity(ent, end, 5, TEAMTE_RGB_R_COLOR, TEAMTE_RGB_G_COLOR, TEAMTE_RGB_B_COLOR, id)
  3303. }
  3304. case CS_TEAM_CT:
  3305. {
  3306. draw_line_from_entity(ent, end, 5, TEAMCT_RGB_R_COLOR, TEAMCT_RGB_G_COLOR, TEAMCT_RGB_B_COLOR, id)
  3307. }
  3308. default:
  3309. {
  3310. draw_line_from_entity(ent, end, 5, _, _, _, id)
  3311. }
  3312. }
  3313. }
  3314. }
  3315. else
  3316. {
  3317. if ( (0 - xs_vec_dot(first, third)) >= anglefraction )
  3318. {
  3319. if (!get_option(OPTION_TEAM_PLAY) || ((g_zombie_mod & ZM_ZM_ACTIVE) && !(g_zombie_mod & ZM_CAN_THINK)))
  3320. {
  3321. draw_line_from_entity(ent, end, 5, _, _, _, id)
  3322. }
  3323. else if (bs_affected & (1<<id))
  3324. {
  3325. switch (cl_team[owner])
  3326. {
  3327. case CS_TEAM_T:
  3328. {
  3329. draw_line_from_entity(ent, end, 5, TEAMTE_RGB_R_COLOR, TEAMTE_RGB_G_COLOR, TEAMTE_RGB_B_COLOR, id)
  3330. }
  3331. case CS_TEAM_CT:
  3332. {
  3333. draw_line_from_entity(ent, end, 5, TEAMCT_RGB_R_COLOR, TEAMCT_RGB_G_COLOR, TEAMCT_RGB_B_COLOR, id)
  3334. }
  3335. default:
  3336. {
  3337. draw_line_from_entity(ent, end, 5, _, _, _, id)
  3338. }
  3339. }
  3340. }
  3341. }
  3342. }
  3343. }
  3344. }
  3345.  
  3346. entity_set_float(ent, EV_FL_fuser4, gametime + 0.5)
  3347.  
  3348. }
  3349. }
  3350.  
  3351. default : return HAM_IGNORED
  3352. }
  3353.  
  3354. return HAM_IGNORED
  3355. }
  3356.  
  3357. public fw_touch(toucher, touched)
  3358. {
  3359. if (!(bs_forward_collection & FWD_TOUCH))
  3360. return HAM_IGNORED
  3361.  
  3362. switch (get_grenade_type(toucher))
  3363. {
  3364. case NADE_IMPACT:
  3365. {
  3366. if (is_solid(touched))
  3367. {
  3368. make_explode(toucher)
  3369.  
  3370. entity_set_float(toucher, EV_FL_nextthink, get_gametime() + 0.001)
  3371.  
  3372. if (NadeRace:get_grenade_race(toucher) == GRENADE_SMOKEGREN)
  3373. {
  3374. entity_set_int(toucher, EV_INT_flags, entity_get_int(toucher, EV_INT_flags) | FL_ONGROUND)
  3375. }
  3376. }
  3377. }
  3378.  
  3379. case NADE_TRIP:
  3380. {
  3381. static classname[10]
  3382. entity_get_string(touched, EV_SZ_classname, classname, charsmax(classname))
  3383.  
  3384. if (get_trip_grenade_mode(toucher) > TRIP_NOT_ATTACHED || is_user_connected(touched))
  3385. {
  3386. return HAM_IGNORED
  3387. }
  3388. else
  3389. {
  3390. if (is_solid(touched))
  3391. {
  3392. entity_set_int(toucher, EV_INT_movetype, MOVETYPE_NONE)
  3393. set_trip_grenade_mode(toucher, TRIP_ATTACHED)
  3394. return (containi(classname, "door") != -1) ? HAM_SUPERCEDE : HAM_IGNORED
  3395. }
  3396. }
  3397. }
  3398. }
  3399.  
  3400. return HAM_IGNORED
  3401. }
  3402.  
  3403. public fw_spawn_post(id)
  3404. {
  3405. if (is_user_alive(id))
  3406. {
  3407. cl_is_alive |= (1<<id)
  3408. }
  3409. else
  3410. {
  3411. cl_is_alive &= ~(1<<id)
  3412. }
  3413.  
  3414. return HAM_IGNORED
  3415. }
  3416.  
  3417. public fw_killed_post(id, attacker, gib)
  3418. {
  3419. if (is_user_alive(id))
  3420. {
  3421. cl_is_alive |= (1<<id)
  3422. }
  3423. else
  3424. {
  3425. cl_is_alive &= ~(1<<id)
  3426. }
  3427.  
  3428. if (!get_option(OPTION_REMOVE_IF_DIES))
  3429. return HAM_IGNORED
  3430.  
  3431. mode[id][GRENADE_EXPLOSIVE] = FirstEnabledMode(GRENADE_EXPLOSIVE)
  3432. mode[id][GRENADE_FLASHBANG] = FirstEnabledMode(GRENADE_FLASHBANG)
  3433. mode[id][GRENADE_SMOKEGREN] = FirstEnabledMode(GRENADE_SMOKEGREN)
  3434.  
  3435. resetCounter(id)
  3436. removeNades(id)
  3437.  
  3438.  
  3439. return HAM_IGNORED
  3440. }
  3441.  
  3442. public fw_takedamage(victim, inflictor, attacker, Float:damage, damagebits)
  3443. {
  3444. if (!(bs_forward_collection & FWD_TAKEDAMAGE))
  3445. return HAM_IGNORED
  3446.  
  3447. static aclassname[7], iclassname[8]
  3448.  
  3449. entity_get_string(attacker, EV_SZ_classname, aclassname, charsmax(aclassname))
  3450. entity_get_string(inflictor, EV_SZ_classname, iclassname, charsmax(iclassname))
  3451.  
  3452. if ((damagebits & DMG_BLAST))
  3453. return HAM_IGNORED
  3454.  
  3455. if (!equal(aclassname, "player") || !equal(iclassname, "grenade"))
  3456. return HAM_IGNORED
  3457.  
  3458. if (attacker == victim)
  3459. {
  3460. damage *= (get_option_float(OPTION_DMG_SELF) / 100.0)
  3461. }
  3462. else
  3463. {
  3464. if (cl_team[attacker] == cl_team[victim] && get_option(OPTION_FRIENDLY_FIRE))
  3465. {
  3466. damage *= 0.02 * get_option_float(OPTION_DMG_TEAMMATES)
  3467. }
  3468. }
  3469.  
  3470. static Float:origin[3], Float:user_origin[3], Float:fraction
  3471.  
  3472. entity_get_vector(victim, EV_VEC_origin, user_origin)
  3473. entity_get_vector(inflictor, EV_VEC_origin, origin)
  3474. origin[2] += 2.0
  3475. engfunc(EngFunc_TraceLine, user_origin, origin, IGNORE_MONSTERS, victim, g_ptrace[TH_DMG])
  3476.  
  3477. get_tr2(g_ptrace[TH_DMG], TR_flFraction, fraction)
  3478.  
  3479. if (fraction < 1.0)
  3480. {
  3481. damage *= (get_option_float(OPTION_DMG_THROUGH_WALL) / 100.0)
  3482. }
  3483.  
  3484. if ( get_option(OPTION_DAMAGE_SYSTEM) == 1)
  3485. {
  3486. damage *= get_option_float(OPTION_DMG_NORMAL)
  3487. }
  3488. else
  3489. {
  3490. new type = _:get_grenade_type(inflictor)
  3491. type &= ~NADE_DONT_COUNT
  3492.  
  3493. switch ( type )
  3494. {
  3495. case NADE_NORMAL:
  3496. {
  3497. damage *= get_option_float(OPTION_DMG_NORMAL)
  3498. }
  3499.  
  3500. case NADE_PROXIMITY:
  3501. {
  3502. damage *= get_option_float(OPTION_DMG_PROXIMITY)
  3503. }
  3504.  
  3505. case NADE_IMPACT:
  3506. {
  3507. damage *= get_option_float(OPTION_DMG_IMPACT)
  3508. }
  3509.  
  3510. case NADE_TRIP:
  3511. {
  3512. damage *= get_option_float(OPTION_DMG_TRIP)
  3513. }
  3514.  
  3515. case NADE_MOTION:
  3516. {
  3517. damage *= get_option_float(OPTION_DMG_MOTION)
  3518. }
  3519.  
  3520. case NADE_SATCHEL:
  3521. {
  3522. damage *= get_option_float(OPTION_DMG_SATCHEL)
  3523. }
  3524.  
  3525. case NADE_HOMING:
  3526. {
  3527. damage *= get_option_float(OPTION_DMG_HOMING)
  3528. }
  3529.  
  3530. default:
  3531. {
  3532. damage *= get_option_float(OPTION_DMG_NORMAL)
  3533. }
  3534. }
  3535. }
  3536.  
  3537. SetHamParamFloat(4, damage)
  3538.  
  3539. return HAM_HANDLED
  3540. }
  3541.  
  3542. public fw_monster_takedamage(victim, inflictor, attacker, Float:damage, damagebits)
  3543. {
  3544. if (!(bs_forward_collection & FWD_TAKEDAMAGE) || !get_option(OPTION_MONSTERMOD_SUPPORT))
  3545. return HAM_IGNORED
  3546.  
  3547. static aclassname[7], iclassname[8]
  3548.  
  3549. entity_get_string(attacker, EV_SZ_classname, aclassname, charsmax(aclassname))
  3550. entity_get_string(inflictor, EV_SZ_classname, iclassname, charsmax(iclassname))
  3551.  
  3552. if ((damagebits & DMG_BLAST))
  3553. return HAM_IGNORED
  3554.  
  3555. if (!equal(aclassname, "player") || !equal(iclassname, "grenade"))
  3556. return HAM_IGNORED
  3557.  
  3558. static Float:origin[3], Float:user_origin[3], Float:fraction
  3559.  
  3560. entity_get_vector(victim, EV_VEC_origin, user_origin)
  3561. entity_get_vector(inflictor, EV_VEC_origin, origin)
  3562. origin[2] += 2.0
  3563. engfunc(EngFunc_TraceLine, user_origin, origin, IGNORE_MONSTERS, victim, g_ptrace[TH_DMG])
  3564.  
  3565. get_tr2(g_ptrace[TH_DMG], TR_flFraction, fraction)
  3566.  
  3567. if (fraction < 1.0)
  3568. {
  3569. damage *= (get_option_float(OPTION_DMG_THROUGH_WALL) / 100.0)
  3570. }
  3571.  
  3572. if ( get_option(OPTION_DAMAGE_SYSTEM) == 1)
  3573. {
  3574. damage *= get_option_float(OPTION_DMG_NORMAL)
  3575. }
  3576. else
  3577. {
  3578. new type = _:get_grenade_type(inflictor)
  3579. type &= ~NADE_DONT_COUNT
  3580.  
  3581. switch ( type )
  3582. {
  3583. case NADE_NORMAL:
  3584. {
  3585. damage *= get_option_float(OPTION_DMG_NORMAL)
  3586. }
  3587.  
  3588. case NADE_PROXIMITY:
  3589. {
  3590. damage *= get_option_float(OPTION_DMG_PROXIMITY)
  3591. }
  3592.  
  3593. case NADE_IMPACT:
  3594. {
  3595. damage *= get_option_float(OPTION_DMG_IMPACT)
  3596. }
  3597.  
  3598. case NADE_TRIP:
  3599. {
  3600. damage *= get_option_float(OPTION_DMG_TRIP)
  3601. }
  3602.  
  3603. case NADE_MOTION:
  3604. {
  3605. damage *= get_option_float(OPTION_DMG_MOTION)
  3606. }
  3607.  
  3608. case NADE_SATCHEL:
  3609. {
  3610. damage *= get_option_float(OPTION_DMG_SATCHEL)
  3611. }
  3612.  
  3613. case NADE_HOMING:
  3614. {
  3615. damage *= get_option_float(OPTION_DMG_HOMING)
  3616. }
  3617.  
  3618. default:
  3619. {
  3620. damage *= get_option_float(OPTION_DMG_NORMAL)
  3621. }
  3622. }
  3623. }
  3624.  
  3625. SetHamParamFloat(4, damage)
  3626.  
  3627. return HAM_HANDLED
  3628. }
  3629.  
  3630. public fw_grenade_takedamage(grenade, inflictor, attacker, Float:damage, bits)
  3631. {
  3632. if (!(bs_forward_collection & FWD_HPSYSTEM))
  3633. return HAM_IGNORED
  3634.  
  3635. if (inflictor == grenade)
  3636. {
  3637. SetHamReturnInteger(0)
  3638. return HAM_SUPERCEDE
  3639. }
  3640.  
  3641. new Float:health, Float:origin[3], ok = false
  3642. health = entity_get_float(grenade, EV_FL_health)
  3643.  
  3644. if (!(1 <= attacker <= g_maxplayers))
  3645. return HAM_SUPERCEDE
  3646.  
  3647. if ((entity_get_int(grenade, EV_INT_flags) & FL_GODMODE) || (entity_get_float(grenade, EV_FL_takedamage) == DAMAGE_NO))
  3648. return HAM_SUPERCEDE
  3649.  
  3650. entity_get_vector(grenade, EV_VEC_origin, origin)
  3651.  
  3652. if (entity_get_edict(grenade, EV_ENT_owner) != attacker && cl_team[entity_get_edict(grenade, EV_ENT_owner)] == cl_team[attacker])
  3653. {
  3654. damage *= get_option_float(OPTION_HITPOINT_FF) / 100.0
  3655. ok = true
  3656. }
  3657.  
  3658. new string[8]
  3659. entity_get_string(inflictor, EV_SZ_classname, string, charsmax(string))
  3660.  
  3661. if (equal(string,"grenade"))
  3662. {
  3663. damage *= get_option_float(OPTION_HITPOINT_INTER_DMG) / 100.0
  3664. ok = true
  3665. }
  3666.  
  3667. play_sound2(grenade, SOUND_HIT[random_num(0,4)])
  3668.  
  3669. if (floatcmp(damage,health) != -1)
  3670. {
  3671. static NadeType:type, owner
  3672. owner = entity_get_edict(grenade, EV_ENT_owner)
  3673. type = get_grenade_type(grenade)
  3674. type &= ~NadeType:NADE_DONT_COUNT
  3675.  
  3676. if (get_option(OPTION_HITPOINT_DEATH))
  3677. {
  3678. make_explode(grenade)
  3679.  
  3680. if (NadeRace:get_grenade_race(grenade) == GRENADE_SMOKEGREN)
  3681. {
  3682. entity_set_int(grenade, EV_INT_flags, entity_get_int(grenade, EV_INT_flags) | FL_ONGROUND)
  3683. dllfunc(DLLFunc_Think, grenade)
  3684. clear_line(grenade)
  3685. }
  3686.  
  3687. return HAM_SUPERCEDE
  3688. }
  3689.  
  3690. entity_set_int(grenade, EV_INT_flags, entity_get_int(grenade, EV_INT_flags) | FL_KILLME)
  3691.  
  3692. if (!(_:UNCOUNTABLE_NADE_MODES & (1 << (_:type + 1))))
  3693. {
  3694. cl_counter[owner][NadeRace:get_grenade_race(grenade)][type] -= 1
  3695. refresh_can_use_nade(owner, GRENADE_EXPLOSIVE)
  3696. refresh_can_use_nade(owner, GRENADE_FLASHBANG)
  3697. refresh_can_use_nade(owner, GRENADE_SMOKEGREN)
  3698. }
  3699.  
  3700. if (get_option(OPTION_RESOURCE_USE))
  3701. metal_gibs(origin)
  3702.  
  3703. clear_line(grenade)
  3704.  
  3705. return HAM_SUPERCEDE
  3706. }
  3707.  
  3708. if (ok)
  3709. {
  3710. SetHamParamFloat(4, damage)
  3711. return HAM_HANDLED
  3712. }
  3713.  
  3714. return HAM_IGNORED
  3715. }
  3716.  
  3717. public fw_traceline(Float:start[3], Float:end[3], conditions, id, trace)
  3718. {
  3719. if (!(bs_forward_collection & FWD_HPSYSTEM))
  3720. return FMRES_IGNORED
  3721.  
  3722. if (!is_player_alive(id))
  3723. return FMRES_IGNORED
  3724.  
  3725. if (cl_weapon[id] != CSW_KNIFE)
  3726. return FMRES_IGNORED
  3727.  
  3728. if (pev_valid(get_tr2(trace,TR_pHit)))
  3729. return FMRES_IGNORED
  3730.  
  3731. static Float:vec_end[3], i
  3732. i = g_maxplayers
  3733.  
  3734. get_tr2(trace, TR_vecEndPos, vec_end)
  3735.  
  3736. while ((i = find_ent_in_sphere(i, vec_end, SHOT_SECOND_TEST_RADIUS)))
  3737. {
  3738. if (is_grenade(i, true))
  3739. {
  3740. static Float:origin[3]
  3741. pev(i,pev_origin,origin)
  3742. xs_vec_sub(origin,vec_end,origin)
  3743. if (xs_vec_len(origin) > SHOT_KNIFE_REAL_RADIUS)
  3744. continue
  3745.  
  3746. set_tr2(trace, TR_pHit, i)
  3747. break
  3748. }
  3749. }
  3750.  
  3751. return FMRES_HANDLED
  3752. }
  3753.  
  3754. public fw_global_traceattack(ent, attacker, Float:damage, Float:direction[3], tracehdl, damagebits)
  3755. {
  3756. if (!(bs_forward_collection & FWD_HPSYSTEM))
  3757. return FMRES_IGNORED
  3758.  
  3759. if (attacker > g_maxplayers || attacker < 1)
  3760. return HAM_IGNORED
  3761.  
  3762. if (cl_weapon[attacker] == CSW_KNIFE)
  3763. return HAM_IGNORED
  3764.  
  3765. static Float:origin[3],Float:offs[3]
  3766. pev(attacker,pev_origin,origin)
  3767. pev(attacker,pev_view_ofs,offs)
  3768. xs_vec_add(origin,offs,origin)
  3769.  
  3770. static Float:end[3], Float:point[3], Float:origin_nade[3], Float:track[3]
  3771. get_tr2(tracehdl,TR_vecEndPos,end)
  3772.  
  3773. xs_vec_sub(end,origin,point)
  3774. xs_vec_mul_scalar(point, SHOT_PENETRATION_DISTANCE / xs_vec_len(point), point)
  3775. xs_vec_add(end, point, end)
  3776.  
  3777. static grenade
  3778. static bool:ok
  3779. static bool:reset_queue
  3780.  
  3781. grenade = -1
  3782. reset_queue = false
  3783.  
  3784. while ((grenade = find_ent_by_class(grenade,"grenade")))
  3785. {
  3786. if (entity_get_float(grenade, EV_FL_dmgtime) < get_gametime())
  3787. continue
  3788.  
  3789. ok = false
  3790. entity_get_vector(grenade, EV_VEC_origin, origin_nade)
  3791.  
  3792. for (new i=0;i<SHOT_ENTITY_QUEUE_LENGTH;i++)
  3793. {
  3794. if (grenade == cl_entity_queue[attacker][i])
  3795. {
  3796. cl_entity_queue[attacker][i] = 0;
  3797. ok = true;
  3798. reset_queue = true;
  3799. break;
  3800. }
  3801. }
  3802.  
  3803. if (ok)
  3804. {
  3805. continue;
  3806. }
  3807.  
  3808. engfunc(EngFunc_TraceModel,origin,end,HULL_POINT,grenade,g_ptrace[TH_DMG])
  3809.  
  3810. if(get_tr2(g_ptrace[TH_DMG],TR_pHit) == grenade)
  3811. {
  3812. ExecuteHamB(Ham_TraceAttack, grenade, attacker, damage, direction, g_ptrace[TH_DMG], damagebits)
  3813.  
  3814. insert_in_queue(attacker, grenade)
  3815. }
  3816. else
  3817. {
  3818. new times = 1
  3819.  
  3820. xs_vec_sub(origin_nade, end, track)
  3821.  
  3822. while (times != SHOT_PENETRATION_READD_TIMES + 1 && xs_vec_len(track) > SHOT_SECOND_TEST_RADIUS)
  3823. {
  3824. xs_vec_add(end, point, track)
  3825.  
  3826. for (new i=1;i<=times;++i)
  3827. {
  3828. xs_vec_add(track, point, track)
  3829. }
  3830.  
  3831. xs_vec_sub(origin_nade, track, track)
  3832.  
  3833. times++;
  3834. }
  3835.  
  3836. if ( xs_vec_len(track) <= SHOT_SECOND_TEST_RADIUS )
  3837. {
  3838. set_tr2(g_ptrace[TH_DMG], TR_pHit, grenade)
  3839.  
  3840. xs_vec_add(origin_nade, track, track)
  3841. set_tr2(g_ptrace[TH_DMG], TR_vecEndPos, track)
  3842.  
  3843. ExecuteHamB(Ham_TraceAttack, grenade, attacker, (damage / 2), direction, g_ptrace[TH_DMG], damagebits)
  3844.  
  3845. insert_in_queue(attacker, grenade)
  3846. }
  3847. }
  3848. }
  3849.  
  3850. if (reset_queue)
  3851. {
  3852. for (new i=0;i<SHOT_ENTITY_QUEUE_LENGTH;i++)
  3853. {
  3854. cl_entity_queue[attacker][i] = 0
  3855. }
  3856. }
  3857.  
  3858. return HAM_IGNORED
  3859. }
  3860.  
  3861. /* -------------------------------
  3862. [Plugin Zombie Mod Compatibility Forwards]
  3863. ------------------------------- */
  3864. public zp_user_infected_post(id, infector)
  3865. {
  3866. g_zombie_mod |= ZM_DO_ALL
  3867.  
  3868. // Reset the mode on infection
  3869. mode[id][GRENADE_EXPLOSIVE] = FirstEnabledMode(GRENADE_EXPLOSIVE)
  3870. mode[id][GRENADE_FLASHBANG] = FirstEnabledMode(GRENADE_FLASHBANG)
  3871. mode[id][GRENADE_SMOKEGREN] = FirstEnabledMode(GRENADE_SMOKEGREN)
  3872.  
  3873. resetCounter(id)
  3874. removeNades(id)
  3875.  
  3876. return PLUGIN_CONTINUE
  3877. }
  3878.  
  3879. public event_infect(id, attacker)
  3880. {
  3881. g_zombie_mod |= ZM_DO_ALL
  3882.  
  3883. // Reset the mode on infection
  3884. mode[id][GRENADE_EXPLOSIVE] = FirstEnabledMode(GRENADE_EXPLOSIVE)
  3885. mode[id][GRENADE_FLASHBANG] = FirstEnabledMode(GRENADE_FLASHBANG)
  3886. mode[id][GRENADE_SMOKEGREN] = FirstEnabledMode(GRENADE_SMOKEGREN)
  3887.  
  3888. resetCounter(id)
  3889. removeNades(id)
  3890.  
  3891. return PLUGIN_CONTINUE
  3892. }
  3893.  
  3894. /* -------------------------------
  3895. [Usefull Functions -> NadeMode Tolls]
  3896. ------------------------------- */
  3897. stock is_nademodes_enabled()
  3898. {
  3899. if (get_option(OPTION_ENABLE_NADE_MODES))
  3900. {
  3901. return ((get_option(OPTION_NORMAL_ENABLED)<<0) | (get_option(OPTION_PROXIMITY_ENABLED)<<1) | (get_option(OPTION_IMPACT_ENABLED)<<2) | (get_option(OPTION_TRIP_ENABLED)<<3) | (get_option(OPTION_MOTION_ENABLED)<<4) | (get_option(OPTION_SATCHEL_ENABLED)<<5) | (get_option(OPTION_HOMING_ENABLED)<<6))
  3902. }
  3903.  
  3904. return 0
  3905. }
  3906.  
  3907. stock NadeType:FirstEnabledMode(NadeRace:race)
  3908. {
  3909. if (is_mode_cvarenabled(g_firstenabledmode[race], race))
  3910. return g_firstenabledmode[race]
  3911.  
  3912. for (new NadeType:i=NADE_NORMAL;i<=NADE_HOMING;i++)
  3913. {
  3914. if (is_mode_cvarenabled(i, race))
  3915. {
  3916. g_firstenabledmode[race] = i
  3917. return i
  3918. }
  3919. }
  3920.  
  3921. return NADE_NORMAL
  3922. }
  3923.  
  3924. public is_mode_cvarenabled(NadeType:type, NadeRace:nade)
  3925. {
  3926. switch (type)
  3927. {
  3928. case NADE_NORMAL:
  3929. {
  3930. return get_option(OPTION_NORMAL_ENABLED)
  3931. }
  3932.  
  3933. case NADE_PROXIMITY:
  3934. {
  3935. return get_option(OPTION_PROXIMITY_ENABLED)
  3936. }
  3937.  
  3938. case NADE_IMPACT:
  3939. {
  3940. return get_option(OPTION_IMPACT_ENABLED)
  3941. }
  3942.  
  3943. case NADE_TRIP:
  3944. {
  3945. return get_option(OPTION_TRIP_ENABLED)
  3946. }
  3947.  
  3948. case NADE_MOTION:
  3949. {
  3950. return get_option(OPTION_MOTION_ENABLED)
  3951. }
  3952.  
  3953. case NADE_SATCHEL:
  3954. {
  3955. return get_option(OPTION_SATCHEL_ENABLED)
  3956. }
  3957.  
  3958. case NADE_HOMING:
  3959. {
  3960. return get_option(OPTION_HOMING_ENABLED)
  3961. }
  3962. }
  3963.  
  3964. return 0
  3965. }
  3966.  
  3967. public is_mode_enabled(id, NadeType:type, NadeRace:nade)
  3968. {
  3969. switch (type)
  3970. {
  3971. case NADE_NORMAL:
  3972. {
  3973. return get_option(OPTION_NORMAL_ENABLED)
  3974. }
  3975.  
  3976. case NADE_PROXIMITY:
  3977. {
  3978. if (!get_option(OPTION_PROXIMITY_ENABLED))
  3979. return 0
  3980.  
  3981. if (!get_option(OPTION_LIMIT_SYSTEM))
  3982. return 1
  3983.  
  3984. if (!get_option(OPTION_LIMIT_PROXIMITY))
  3985. return 1
  3986.  
  3987. if (get_option(OPTION_LIMIT_SYSTEM) == 1 && cl_counter[id][nade][type] < get_option(OPTION_LIMIT_PROXIMITY))
  3988. return 1
  3989.  
  3990. if (get_option(OPTION_LIMIT_SYSTEM) == 2 && (cl_counter[id][GRENADE_EXPLOSIVE][type] + cl_counter[id][GRENADE_SMOKEGREN][type] + cl_counter[id][GRENADE_FLASHBANG][type]) < get_option(OPTION_LIMIT_PROXIMITY))
  3991. return 1
  3992.  
  3993. return 0
  3994. }
  3995.  
  3996. case NADE_IMPACT:
  3997. {
  3998. return get_option(OPTION_IMPACT_ENABLED)
  3999. }
  4000.  
  4001. case NADE_TRIP:
  4002. {
  4003. if (!get_option(OPTION_TRIP_ENABLED))
  4004. return 0
  4005.  
  4006. if (!get_option(OPTION_LIMIT_SYSTEM))
  4007. return 1
  4008.  
  4009. if (!get_option(OPTION_LIMIT_TRIP))
  4010. return 1
  4011.  
  4012. if (get_option(OPTION_LIMIT_SYSTEM) == 1 && cl_counter[id][nade][type] < get_option(OPTION_LIMIT_TRIP))
  4013. return 1
  4014.  
  4015. if (get_option(OPTION_LIMIT_SYSTEM) == 2 && (cl_counter[id][GRENADE_EXPLOSIVE][type] + cl_counter[id][GRENADE_SMOKEGREN][type] + cl_counter[id][GRENADE_FLASHBANG][type]) < get_option(OPTION_LIMIT_TRIP))
  4016. return 1
  4017.  
  4018. return 0
  4019. }
  4020.  
  4021. case NADE_MOTION:
  4022. {
  4023. if (!get_option(OPTION_MOTION_ENABLED))
  4024. return 0
  4025.  
  4026. if (!get_option(OPTION_LIMIT_SYSTEM))
  4027. return 1
  4028.  
  4029. if (!get_option(OPTION_LIMIT_MOTION))
  4030. return 1
  4031.  
  4032. if (get_option(OPTION_LIMIT_SYSTEM) == 1 && cl_counter[id][nade][type] < get_option(OPTION_LIMIT_MOTION))
  4033. return 1
  4034.  
  4035. if (get_option(OPTION_LIMIT_SYSTEM) == 2 && (cl_counter[id][GRENADE_EXPLOSIVE][type] + cl_counter[id][GRENADE_SMOKEGREN][type] + cl_counter[id][GRENADE_FLASHBANG][type]) < get_option(OPTION_LIMIT_MOTION))
  4036. return 1
  4037.  
  4038. return 0
  4039. }
  4040.  
  4041. case NADE_SATCHEL:
  4042. {
  4043. if (!get_option(OPTION_SATCHEL_ENABLED))
  4044. return 0
  4045.  
  4046. if (!get_option(OPTION_LIMIT_SYSTEM))
  4047. return 1
  4048.  
  4049. if (!get_option(OPTION_LIMIT_SATCHEL))
  4050. return 1
  4051.  
  4052. if (get_option(OPTION_LIMIT_SYSTEM) == 1 && cl_counter[id][nade][type] < get_option(OPTION_LIMIT_SATCHEL))
  4053. return 1
  4054.  
  4055. if (get_option(OPTION_LIMIT_SYSTEM) == 2 && (cl_counter[id][GRENADE_EXPLOSIVE][type] + cl_counter[id][GRENADE_SMOKEGREN][type] + cl_counter[id][GRENADE_FLASHBANG][type]) < get_option(OPTION_LIMIT_SATCHEL))
  4056. return 1
  4057.  
  4058. return 0
  4059. }
  4060.  
  4061. case NADE_HOMING:
  4062. {
  4063. return get_option(OPTION_HOMING_ENABLED)
  4064. }
  4065. }
  4066.  
  4067. return 1
  4068. }
  4069.  
  4070. public get_enabled_modes(id, NadeRace:nade)
  4071. {
  4072. for (new NadeType:type = NADE_NORMAL; type <= NADE_HOMING; type = type + NADE_PROXIMITY)
  4073. {
  4074. if (is_mode_enabled(id, type, nade))
  4075. return 1
  4076. }
  4077.  
  4078. return 0;
  4079. }
  4080.  
  4081.  
  4082. public changemode(id, NadeRace:NADE_TYPE)
  4083. {
  4084. if (!(grenade_can_be_used(NADE_TYPE)))
  4085. {
  4086. return
  4087. }
  4088.  
  4089. if (!is_mode_enabled(id, ++mode[id][NADE_TYPE], NADE_TYPE))
  4090. {
  4091. changemode(id, NADE_TYPE)
  4092. return
  4093. }
  4094.  
  4095. switch (mode[id][NADE_TYPE])
  4096. {
  4097. case NADE_NORMAL:
  4098. {
  4099. client_print(id, print_center, "Mode - Normal")
  4100. }
  4101.  
  4102. case NADE_PROXIMITY:
  4103. {
  4104. client_print(id, print_center, "Mode - Proximity")
  4105. }
  4106.  
  4107. case NADE_IMPACT:
  4108. {
  4109. client_print(id, print_center, "Mode - Impact")
  4110. }
  4111.  
  4112. case NADE_TRIP:
  4113. {
  4114. client_print(id, print_center, "Mode - Trip laser")
  4115. }
  4116.  
  4117. case NADE_MOTION:
  4118. {
  4119. client_print(id, print_center, "Mode - Motion sensor")
  4120. }
  4121.  
  4122. case NADE_SATCHEL:
  4123. {
  4124. client_print(id, print_center, "Mode - Satchel charge")
  4125. }
  4126.  
  4127. case NADE_HOMING:
  4128. {
  4129. client_print(id, print_center, "Mode - Homing")
  4130. }
  4131.  
  4132. default:
  4133. {
  4134. mode[id][NADE_TYPE] = NADE_DUD
  4135. changemode(id, NADE_TYPE)
  4136. }
  4137. }
  4138. }
  4139.  
  4140. resetCounter(id)
  4141. {
  4142. cl_counter[id][GRENADE_EXPLOSIVE][NADE_MOTION] = 0
  4143. cl_counter[id][GRENADE_EXPLOSIVE][NADE_PROXIMITY] = 0
  4144. cl_counter[id][GRENADE_EXPLOSIVE][NADE_TRIP] = 0
  4145. cl_counter[id][GRENADE_EXPLOSIVE][NADE_SATCHEL] = 0
  4146. cl_counter[id][GRENADE_FLASHBANG][NADE_MOTION] = 0
  4147. cl_counter[id][GRENADE_FLASHBANG][NADE_PROXIMITY] = 0
  4148. cl_counter[id][GRENADE_FLASHBANG][NADE_TRIP] = 0
  4149. cl_counter[id][GRENADE_FLASHBANG][NADE_SATCHEL] = 0
  4150. cl_counter[id][GRENADE_SMOKEGREN][NADE_MOTION] = 0
  4151. cl_counter[id][GRENADE_SMOKEGREN][NADE_PROXIMITY] = 0
  4152. cl_counter[id][GRENADE_SMOKEGREN][NADE_TRIP] = 0
  4153. cl_counter[id][GRENADE_SMOKEGREN][NADE_SATCHEL] = 0
  4154.  
  4155. cl_can_use_nade[GRENADE_EXPLOSIVE] |= (1<<id)
  4156. cl_can_use_nade[GRENADE_FLASHBANG] |= (1<<id)
  4157. cl_can_use_nade[GRENADE_SMOKEGREN] |= (1<<id)
  4158.  
  4159. return
  4160. }
  4161.  
  4162. removeNades(id)
  4163. {
  4164. static ent
  4165. ent = -1
  4166.  
  4167. // Get all the grenade entities
  4168. while ((ent = find_ent_by_class(ent, "grenade")))
  4169. {
  4170. if (entity_get_edict(ent, EV_ENT_owner) != id)
  4171. continue
  4172.  
  4173. // Set the remove property if they aren't normal nades
  4174. if(is_grenade(ent) && get_grenade_type(ent) != NADE_NORMAL)
  4175. entity_set_int(ent, EV_INT_flags , entity_get_int(ent, EV_INT_flags) | FL_KILLME)
  4176. }
  4177.  
  4178. return
  4179. }
  4180.  
  4181. /* -------------------------------
  4182. [Usefull Functions -> Grenade Property Set/Get]
  4183. ------------------------------- */
  4184. is_grenade(ent, bool:enforce = false)
  4185. {
  4186. if (!is_valid_ent(ent))
  4187. {
  4188. return 0
  4189. }
  4190.  
  4191. if (enforce)
  4192. {
  4193. if (!is_classname(ent, "grenade"))
  4194. return 0
  4195. }
  4196.  
  4197. if (is_grenade_c4(ent))
  4198. return 0
  4199.  
  4200. static weapon_id
  4201. weapon_id = cs_get_weapon_id(ent)
  4202.  
  4203. for (new i=0;i<3;i++)
  4204. {
  4205. if (weapon_id == NADE_WPID[NadeRace:i])
  4206. return 1
  4207. }
  4208.  
  4209. return 0
  4210. }
  4211.  
  4212. is_classname(ent, const string[])
  4213. {
  4214. new classname[20]
  4215.  
  4216. entity_get_string(ent, EV_SZ_classname, classname, charsmax(classname))
  4217.  
  4218. return equali(string, classname, strlen(string))
  4219. }
  4220.  
  4221. public get_grenade_race(grenade)
  4222. {
  4223. switch (cs_get_weapon_id(grenade))
  4224. {
  4225. case CSW_HEGRENADE: return _:GRENADE_EXPLOSIVE
  4226. case CSW_FLASHBANG: return _:GRENADE_FLASHBANG
  4227. case CSW_SMOKEGRENADE: return _:GRENADE_SMOKEGREN
  4228. }
  4229.  
  4230. return -1
  4231. }
  4232.  
  4233. set_grenade_type(grenade, NadeType:g_type, bool:property = true)
  4234. {
  4235. if (!is_valid_ent(grenade)) return
  4236.  
  4237. static NadeRace:nade
  4238. static owner
  4239.  
  4240. owner = entity_get_edict(grenade, EV_ENT_owner)
  4241.  
  4242. nade = NadeRace:get_grenade_race(grenade)
  4243.  
  4244. if (g_FW_property > 0 && g_type != NADE_DUD)
  4245. {
  4246. new ret
  4247. ExecuteForward(g_FW_property, ret, grenade, g_type)
  4248.  
  4249. if (ret > PLUGIN_CONTINUE)
  4250. {
  4251. if (g_PFW_property > 0)
  4252. ExecuteForward(g_PFW_property, ret, grenade, g_type, 1)
  4253.  
  4254. return
  4255. }
  4256.  
  4257. if (g_PFW_property > 0)
  4258. ExecuteForward(g_PFW_property, ret, grenade, g_type, 0)
  4259. }
  4260.  
  4261. // Set grenade properties and empty the slots so we can put some info
  4262. entity_set_int(grenade, EV_INT_iuser1, _:g_type)
  4263. entity_set_int(grenade, EV_INT_iuser2, 0)
  4264. entity_set_int(grenade, EV_INT_iuser3, 0)
  4265. entity_set_int(grenade, EV_INT_iuser4, 0)
  4266.  
  4267. entity_set_vector(grenade, EV_VEC_vuser1, Float:{0.0, 0.0, 0.0})
  4268. entity_set_vector(grenade, EV_VEC_vuser2, Float:{0.0, 0.0, 0.0})
  4269. entity_set_vector(grenade, EV_VEC_vuser3, Float:{0.0, 0.0, 0.0})
  4270. entity_set_vector(grenade, EV_VEC_vuser4, Float:{0.0, 0.0, 0.0})
  4271.  
  4272. if (property == true)
  4273. {
  4274. switch (g_type)
  4275. {
  4276. case NADE_DUD:
  4277. {
  4278. entity_set_int(grenade, EV_INT_movetype, MOVETYPE_BOUNCE)
  4279. entity_set_vector(grenade, EV_VEC_velocity, Float:{0.0, 0.0, 0.0})
  4280. }
  4281.  
  4282. case NADE_NORMAL:
  4283. {
  4284. entity_set_float(grenade, EV_FL_health, floatabs(get_option_float(OPTION_HITPOINT_NORMAL)))
  4285.  
  4286. if (get_option(OPTION_MATERIAL_SYSTEM) == 2 && get_option(OPTION_HITPOINT_NORMAL))
  4287. {
  4288. entity_set_float(grenade, EV_FL_takedamage, DAMAGE_YES)
  4289. }
  4290. }
  4291.  
  4292. case NADE_PROXIMITY:
  4293. {
  4294. delay_explosion(grenade)
  4295. set_grenade_allow_explode(grenade, get_option_float(OPTION_ARM_TIME_PROXIMITY))
  4296.  
  4297. entity_set_float(grenade, EV_FL_health, floatabs(get_option_float(OPTION_HITPOINT_PROXIMITY)))
  4298.  
  4299. if (get_option(OPTION_MATERIAL_SYSTEM) == 2 && get_option(OPTION_HITPOINT_PROXIMITY))
  4300. {
  4301. entity_set_float(grenade, EV_FL_takedamage, DAMAGE_YES)
  4302. }
  4303.  
  4304. cl_counter[owner][nade][NADE_PROXIMITY] += 1
  4305.  
  4306. refresh_can_use_nade(owner, GRENADE_EXPLOSIVE)
  4307. refresh_can_use_nade(owner, GRENADE_FLASHBANG)
  4308. refresh_can_use_nade(owner, GRENADE_SMOKEGREN)
  4309. }
  4310.  
  4311. case NADE_IMPACT:
  4312. {
  4313. delay_explosion(grenade)
  4314. entity_set_int(grenade, EV_INT_movetype, MOVETYPE_BOUNCE)
  4315.  
  4316. entity_set_float(grenade, EV_FL_health, floatabs(get_option_float(OPTION_HITPOINT_IMPACT)))
  4317.  
  4318. if (get_option(OPTION_MATERIAL_SYSTEM) == 2 && get_option(OPTION_HITPOINT_IMPACT))
  4319. {
  4320. entity_set_float(grenade, EV_FL_takedamage, DAMAGE_YES)
  4321. }
  4322. }
  4323.  
  4324. // I don't recommend setting a grenade to trip if it was another type in the first place.
  4325. case NADE_TRIP:
  4326. {
  4327. delay_explosion(grenade)
  4328.  
  4329. entity_set_float(grenade, EV_FL_health, floatabs(get_option_float(OPTION_HITPOINT_TRIP)))
  4330.  
  4331. if (get_option(OPTION_MATERIAL_SYSTEM) == 2 && get_option(OPTION_HITPOINT_TRIP))
  4332. {
  4333. entity_set_float(grenade, EV_FL_takedamage, DAMAGE_YES)
  4334. }
  4335.  
  4336. cl_counter[owner][nade][NADE_TRIP] += 1
  4337.  
  4338. refresh_can_use_nade(owner, GRENADE_EXPLOSIVE)
  4339. refresh_can_use_nade(owner, GRENADE_FLASHBANG)
  4340. refresh_can_use_nade(owner, GRENADE_SMOKEGREN)
  4341. }
  4342.  
  4343. case NADE_MOTION:
  4344. {
  4345. delay_explosion(grenade)
  4346. set_grenade_allow_explode(grenade, get_option_float(OPTION_ARM_TIME_MOTION))
  4347.  
  4348. entity_set_float(grenade, EV_FL_health, floatabs(get_option_float(OPTION_HITPOINT_MOTION)))
  4349.  
  4350. if (get_option(OPTION_MATERIAL_SYSTEM) == 2 && get_option(OPTION_HITPOINT_MOTION))
  4351. {
  4352. entity_set_float(grenade, EV_FL_takedamage, DAMAGE_YES)
  4353. }
  4354.  
  4355. cl_counter[owner][nade][NADE_MOTION] += 1
  4356.  
  4357. refresh_can_use_nade(owner, GRENADE_EXPLOSIVE)
  4358. refresh_can_use_nade(owner, GRENADE_FLASHBANG)
  4359. refresh_can_use_nade(owner, GRENADE_SMOKEGREN)
  4360. }
  4361.  
  4362. case NADE_SATCHEL:
  4363. {
  4364. delay_explosion(grenade)
  4365. set_grenade_allow_explode(grenade, get_option_float(OPTION_ARM_TIME_SATCHEL))
  4366.  
  4367. entity_set_float(grenade, EV_FL_health, floatabs(get_option_float(OPTION_HITPOINT_SATCHEL)))
  4368.  
  4369. if (get_option(OPTION_MATERIAL_SYSTEM) == 2 && get_option(OPTION_HITPOINT_SATCHEL))
  4370. {
  4371. entity_set_float(grenade, EV_FL_takedamage, DAMAGE_YES)
  4372. }
  4373.  
  4374. cl_counter[owner][nade][NADE_SATCHEL] += 1
  4375.  
  4376. refresh_can_use_nade(owner, GRENADE_EXPLOSIVE)
  4377. refresh_can_use_nade(owner, GRENADE_FLASHBANG)
  4378. refresh_can_use_nade(owner, GRENADE_SMOKEGREN)
  4379. }
  4380.  
  4381. case NADE_HOMING:
  4382. {
  4383. entity_set_float(grenade, EV_FL_dmgtime, entity_get_float(grenade, EV_FL_dmgtime) + get_option_float(OPTION_HOMING_EXTRATIME))
  4384.  
  4385. entity_set_float(grenade, EV_FL_health, floatabs(get_option_float(OPTION_HITPOINT_HOMING)))
  4386.  
  4387. if (get_option(OPTION_MATERIAL_SYSTEM) == 2 && get_option(OPTION_HITPOINT_HOMING))
  4388. {
  4389. entity_set_float(grenade, EV_FL_takedamage, DAMAGE_YES)
  4390. }
  4391. }
  4392. }
  4393. }
  4394. }
  4395.  
  4396.  
  4397.  
  4398. public get_trip_grenade_react_method(grenade)
  4399. {
  4400. new NadeRace:grenade_race = NadeRace:get_grenade_race(grenade)
  4401.  
  4402. switch (grenade_race)
  4403. {
  4404. case GRENADE_EXPLOSIVE: return get_option(OPTION_REACT_TRIP_G)
  4405. case GRENADE_FLASHBANG: return get_option(OPTION_REACT_TRIP_F)
  4406. case GRENADE_SMOKEGREN: return get_option(OPTION_REACT_TRIP_S)
  4407. }
  4408.  
  4409. return -1
  4410. }
  4411.  
  4412. /* -------------------------------
  4413. [Usefull Functions -> Surface and solid tests + line of sight]
  4414. ------------------------------- */
  4415. public bool:is_ent_monster(ent)
  4416. {
  4417. if (!pev_valid(ent))
  4418. return false
  4419.  
  4420. if (!is_classname(ent, "func_wall"))
  4421. return false
  4422.  
  4423. return !!(pev(ent, pev_flags) & FL_MONSTER)
  4424. }
  4425.  
  4426. public bool:is_solid(ent)
  4427. {
  4428. // Here we account for ent = 0, where 0 means it's part of the map (and therefore is solid)
  4429. return ( ent ? ( (entity_get_int(ent, EV_INT_solid) > SOLID_TRIGGER) ? true : false ) : true )
  4430. }
  4431.  
  4432. public bool:is_attachable_surface(entity)
  4433. {
  4434. static Float:velocity[3]
  4435.  
  4436. if (is_valid_ent(entity))
  4437. {
  4438. if (!is_solid(entity)) return false // This is for func_breakables. The entity technically exists, but isn't solid.
  4439. entity_get_vector(entity, EV_VEC_velocity, velocity) // This is for func_doors. The grenade touches the door, causing it to move.
  4440. return (xs_vec_equal(velocity, Float:{0.0, 0.0, 0.0}) ? true : false)
  4441. }
  4442.  
  4443. return true
  4444. }
  4445.  
  4446. public bool:is_in_los(grenade_ent, player)
  4447. {
  4448. static Float:start[3], Float:end[3]
  4449. entity_get_vector(grenade_ent, EV_VEC_origin, start)
  4450. entity_get_vector(player, EV_VEC_origin, end)
  4451.  
  4452. start[2] += 2.0
  4453.  
  4454. engfunc(EngFunc_TraceLine, start, end, IGNORE_MONSTERS, grenade_ent, g_ptrace[TH_LOS])
  4455.  
  4456. static Float:dist
  4457. get_tr2(g_ptrace[TH_LOS], TR_flFraction, dist)
  4458.  
  4459. return ((dist == 1.0) ? true : false)
  4460. }
  4461.  
  4462.  
  4463. // This function is limited, it returns the same values unter CONE_CALC_DISTANCE_MAX
  4464. stock Float:calc_cone_angle_from_distance(Float:distance)
  4465. {
  4466. // The angle is calculated from a formula that looks like this
  4467. // angle = atan(A*(CONE_BASE_RADIUS/(distance-B)))
  4468. static Float:A,Float:B;
  4469.  
  4470. // The constants A and B need to be calculated first, this if will only happen once
  4471. if (A == 0.0 && B == 0.0)
  4472. {
  4473. if (CONE_BASE_RADIUS == 0.0)
  4474. {
  4475. A = ((CONE_CALC_DISTANCE_MIN-CONE_CALC_DISTANCE_MAX)*floattan(CONE_CALC_ANGLE_MAX, degrees)*floattan(CONE_CALC_ANGLE_MIN, degrees))/(floattan(CONE_CALC_ANGLE_MAX, degrees)-floattan(CONE_CALC_ANGLE_MIN, degrees))
  4476. B = (CONE_CALC_DISTANCE_MAX*floattan(CONE_CALC_ANGLE_MAX, degrees) - CONE_CALC_DISTANCE_MIN*floattan(CONE_CALC_ANGLE_MIN, degrees))/(floattan(CONE_CALC_ANGLE_MAX, degrees)-floattan(CONE_CALC_ANGLE_MIN, degrees))
  4477. }
  4478. else
  4479. {
  4480. A = CONE_BASE_RADIUS;
  4481. B = CONE_CALC_DISTANCE_MAX - CONE_BASE_RADIUS/floattan(CONE_CALC_ANGLE_MAX, degrees)
  4482. }
  4483. }
  4484.  
  4485. // Return the angle in radians that is checked
  4486. return (distance < CONE_CALC_DISTANCE_MAX) ? floatatan(A/((CONE_CALC_DISTANCE_MIN)-B), radian) : floatatan(A/((distance)-B), radian)
  4487. }
  4488.  
  4489. public insert_in_queue(id, ent_id)
  4490. {
  4491. for (new i=0;i<SHOT_ENTITY_QUEUE_LENGTH;i++)
  4492. {
  4493. if (cl_entity_queue[id][i] == 0)
  4494. {
  4495. cl_entity_queue[id][i] = ent_id
  4496. break;
  4497. }
  4498.  
  4499. if (i == SHOT_ENTITY_QUEUE_LENGTH - 1)
  4500. {
  4501. server_print("[NDM] Error! Unable to save so much entities!")
  4502. server_print("[NDM] Increase the value of the ^"SHOT_ENTITY_QUEUE_LENGTH^" define and recompile!")
  4503. log_amx("[NDM] Error! Unable to save so much entities")
  4504. log_amx("[NDM] Increase the value of the ^"SHOT_ENTITY_QUEUE_LENGTH^" define and recompile!")
  4505. }
  4506. }
  4507. }
  4508. /* -------------------------------
  4509. [Message Functions]
  4510. ------------------------------- */
  4511. draw_line_from_entity(entid, Float:end[3], staytime, R = NOTEAM_RGB_R_COLOR, G = NOTEAM_RGB_G_COLOR, B = NOTEAM_RGB_B_COLOR, id = 0, Float:pvs[3] = {0.0, 0.0, 0.0})
  4512. {
  4513. ( id == 0 ) ? engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, pvs, 0) : engfunc(EngFunc_MessageBegin, get_option(OPTION_MSG_SVC_BAD) ? MSG_ONE : MSG_ONE_UNRELIABLE, SVC_TEMPENTITY, pvs, id)
  4514. write_byte(TE_BEAMENTPOINT)
  4515. write_short(entid) // start entity
  4516. engfunc(EngFunc_WriteCoord, end[0])
  4517. engfunc(EngFunc_WriteCoord, end[1])
  4518. engfunc(EngFunc_WriteCoord, end[2])
  4519. write_short(beampoint)
  4520. write_byte(0)
  4521. write_byte(0)
  4522. write_byte(staytime)
  4523. write_byte(10)
  4524. write_byte(0)
  4525. write_byte(R)
  4526. write_byte(G)
  4527. write_byte(B)
  4528. write_byte(127)
  4529. write_byte(1)
  4530. message_end()
  4531. }
  4532.  
  4533. stock draw_line(Float:start[3], Float:end[3], staytime, R = NOTEAM_RGB_R_COLOR, G = NOTEAM_RGB_G_COLOR, B = NOTEAM_RGB_B_COLOR)
  4534. {
  4535. engfunc(EngFunc_MessageBegin, MSG_ALL, SVC_TEMPENTITY, Float:{0.0,0.0,0.0}, 0)
  4536. write_byte(TE_BEAMPOINTS)
  4537. engfunc(EngFunc_WriteCoord, start[0])
  4538. engfunc(EngFunc_WriteCoord, start[1])
  4539. engfunc(EngFunc_WriteCoord, start[2])
  4540. engfunc(EngFunc_WriteCoord, end[0])
  4541. engfunc(EngFunc_WriteCoord, end[1])
  4542. engfunc(EngFunc_WriteCoord, end[2])
  4543. write_short(beampoint)
  4544. write_byte(0)
  4545. write_byte(0)
  4546. write_byte(staytime)
  4547. write_byte(10)
  4548. write_byte(0)
  4549. write_byte(R)
  4550. write_byte(G)
  4551. write_byte(B)
  4552. write_byte(127)
  4553. write_byte(1)
  4554. message_end()
  4555. }
  4556.  
  4557. draw_line_from_entity_broadcast(entid, Float:end[3], staytime, R = NOTEAM_RGB_R_COLOR, G = NOTEAM_RGB_G_COLOR, B = NOTEAM_RGB_B_COLOR)
  4558. {
  4559. engfunc(EngFunc_MessageBegin, get_option(OPTION_MSG_SVC_BAD) ? MSG_ALL : MSG_BROADCAST, SVC_TEMPENTITY, {0.0, 0.0, 0.0}, 0)
  4560. write_byte(TE_BEAMENTPOINT)
  4561. write_short(entid) // start entity
  4562. engfunc(EngFunc_WriteCoord, end[0])
  4563. engfunc(EngFunc_WriteCoord, end[1])
  4564. engfunc(EngFunc_WriteCoord, end[2])
  4565. write_short(beampoint)
  4566. write_byte(0)
  4567. write_byte(0)
  4568. write_byte(staytime)
  4569. write_byte(10)
  4570. write_byte(0)
  4571. write_byte(R)
  4572. write_byte(G)
  4573. write_byte(B)
  4574. write_byte(127)
  4575. write_byte(1)
  4576. message_end()
  4577. }
  4578.  
  4579. clear_line(entid)
  4580. {
  4581. message_begin(MSG_ALL, SVC_TEMPENTITY)
  4582. write_byte(TE_KILLBEAM)
  4583. write_short(entid)
  4584. message_end()
  4585. }
  4586.  
  4587. show_ring(Float:origin[3], Float:addict, staytime, R = NOTEAM_RGB_R_COLOR, G = NOTEAM_RGB_G_COLOR, B = NOTEAM_RGB_B_COLOR , id = 0)
  4588. {
  4589. ( id == 0 ) ? engfunc(EngFunc_MessageBegin, get_option(OPTION_MSG_SVC_BAD) ? MSG_ALL : MSG_BROADCAST, SVC_TEMPENTITY, {0.0, 0.0, 0.0}, 0) : engfunc(EngFunc_MessageBegin, get_option(OPTION_MSG_SVC_BAD) ? MSG_ONE : MSG_ONE_UNRELIABLE , SVC_TEMPENTITY, {0.0, 0.0, 0.0}, id)
  4590. write_byte(TE_BEAMCYLINDER) // TE_BEAMCYLINDER
  4591. engfunc(EngFunc_WriteCoord, origin[0]) // start X
  4592. engfunc(EngFunc_WriteCoord, origin[1]) // start Y
  4593. engfunc(EngFunc_WriteCoord, origin[2]) // start Z
  4594. engfunc(EngFunc_WriteCoord, origin[0]) // something X
  4595. engfunc(EngFunc_WriteCoord, origin[1]) // something Y
  4596. engfunc(EngFunc_WriteCoord, origin[2] + addict) // something Z
  4597. write_short(shockwave) // sprite
  4598. write_byte(0) // startframe
  4599. write_byte(0) // framerate
  4600. write_byte(staytime) // life
  4601. write_byte(60) // width
  4602. write_byte(0) // noise
  4603. write_byte(R) // red
  4604. write_byte(G) // green
  4605. write_byte(B) // blue
  4606. write_byte(100) // brightness
  4607. write_byte(0) // speed
  4608. message_end()
  4609. }
  4610.  
  4611. metal_gibs(const Float: origin[3])
  4612. {
  4613. message_begin(get_option(OPTION_MSG_SVC_BAD) ? MSG_ALL : MSG_BROADCAST, SVC_TEMPENTITY, {0, 0, 0}, 0)
  4614. write_byte(TE_BREAKMODEL) // TE_BREAKMODEL
  4615. engfunc(EngFunc_WriteCoord,origin[0]) // x
  4616. engfunc(EngFunc_WriteCoord,origin[1]) // y
  4617. engfunc(EngFunc_WriteCoord,origin[2] + 24) // z
  4618. engfunc(EngFunc_WriteCoord,20.0) // size x
  4619. engfunc(EngFunc_WriteCoord,20.0) // size y
  4620. engfunc(EngFunc_WriteCoord,20.0) // size z
  4621. engfunc(EngFunc_WriteCoord,random_num(-50,50)) // velocity x
  4622. engfunc(EngFunc_WriteCoord,random_num(-50,50)) // velocity y
  4623. engfunc(EngFunc_WriteCoord,25.0) // velocity z
  4624. write_byte(10) // random velocity
  4625. write_short(nadebits) // model
  4626. write_byte(10) // count
  4627. write_byte(25) // life
  4628. write_byte(2) // flags: BREAK_METAL
  4629. message_end()
  4630. }
Add Comment
Please, Sign In to add comment