Guest User

Untitled

a guest
Aug 12th, 2012
215
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 359.12 KB | None | 0 0
  1. /*================================================================================
  2.  
  3. *****************************************************
  4. ************** [Zombie Plague Mod 4.3] **************
  5. *****************************************************
  6.  
  7. ----------------------
  8. -*- Licensing Info -*-
  9. ----------------------
  10.  
  11. Zombie Plague Mod
  12. Copyright (C) 2008-2009 by MeRcyLeZZ
  13.  
  14. This program is free software: you can redistribute it and/or modify
  15. it under the terms of the GNU General Public License as published by
  16. the Free Software Foundation, either version 3 of the License, or
  17. (at your option) any later version.
  18.  
  19. This program is distributed in the hope that it will be useful,
  20. but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. GNU General Public License for more details.
  23.  
  24. You should have received a copy of the GNU General Public License
  25. along with this program. If not, see <http://www.gnu.org/licenses/>.
  26.  
  27. In addition, as a special exception, the author gives permission to
  28. link the code of this program with the Half-Life Game Engine ("HL
  29. Engine") and Modified Game Libraries ("MODs") developed by Valve,
  30. L.L.C ("Valve"). You must obey the GNU General Public License in all
  31. respects for all of the code used other than the HL Engine and MODs
  32. from Valve. If you modify this file, you may extend this exception
  33. to your version of the file, but you are not obligated to do so. If
  34. you do not wish to do so, delete this exception statement from your
  35. version.
  36.  
  37. -------------------
  38. -*- Description -*-
  39. -------------------
  40.  
  41. Zombie Plague is a Counter-Strike server side modification, developed as
  42. an AMX Mod X plugin, which completely revamps the gameplay, turning the
  43. game into an intense "Humans vs Zombies" survival experience.
  44.  
  45. Even though it's strongly based on the classic zombie infection mods, it
  46. takes the concept to a new level by introducing:
  47.  
  48. * New Gameplay Modes: Nemesis, Survivor, Multi Infection, Swarm, Plague
  49. * Zombie Classes System: allows addding unlimited custom zombie classes
  50. * Ammo Packs: awarded to skilled players, can be exchanged for goods
  51. * Extra Items System: allows adding unlimited custom items to buy
  52. * Custom Grenades: Napalms, Frost Nades, Flares, and Infection Bombs
  53. * Deathmatch Mode: where zombies or humans can continually respawn
  54. * Admin Menus: to easily perform the included console commands
  55. * Special Effects: from the HL Engine, such as dynamic lighting and fog
  56.  
  57. There is plenty of customization as well, which enables you to create
  58. several different styles of gameplay. You can:
  59.  
  60. * Set zombies and humans' health, speed, models, rewards, and more
  61. * Toggle unlimited ammo and adjustable knockback for weapons
  62. * Separately enable and customize the new gameplay modes to your liking
  63. * Change overall map lighting (lightnings available for the dark settings)
  64. * Set different colors and sizes for flashlight and nightvision
  65. * Toggle leap (long jumping) and pain shock free (no damage slowdowns)
  66. * Toggle various infection effects, such as sparks and screen shakes
  67. * Enable random spawning (CSDM-spawn friendly)
  68. * Replace sounds or add some background themes
  69. * And many more...
  70.  
  71. -------------
  72. -*- Media -*-
  73. -------------
  74.  
  75. * Gameplay Video 1: http://www.youtube.com/watch?v=HFUyF7-_uzw
  76. * Gameplay Video 2: http://www.youtube.com/watch?v=XByif6Mti-w
  77.  
  78. --------------------
  79. -*- Requirements -*-
  80. --------------------
  81.  
  82. * Mods: Counter-Strike 1.6 or Condition-Zero
  83. * AMXX: Version 1.8.0 or later
  84.  
  85. --------------------
  86. -*- Installation -*-
  87. --------------------
  88.  
  89. Extract the contents from the .zip file to your server's mod directory
  90. ("cstrike" or "czero"). Make sure to keep folder structure.
  91.  
  92. -----------------------
  93. -*- Official Forums -*-
  94. -----------------------
  95.  
  96. For the official Zombie Plague forums visit:
  97. http://forums.alliedmods.net/forumdisplay.php?f=126
  98.  
  99. There you can:
  100.  
  101. * Get the latest releases and early betas
  102. * Discuss new features and suggestions
  103. * Share sub-plugins (expansions) for the mod
  104. * Find the support and help you need
  105. * Report any bugs you might find
  106. * And all that sort of stuff...
  107.  
  108. -------------------------------
  109. -*- CVARS and Customization -*-
  110. -------------------------------
  111.  
  112. For a complete and in-depth cvar list, look at the zombieplague.cfg file
  113. located in the amxmodx\configs directory.
  114.  
  115. Additionally, you can change player models, sounds, weather effects,
  116. and some other stuff from the configuration file zombieplague.ini.
  117.  
  118. As for editing attributes of zombie classes or custom extra items, you'll
  119. find a zp_zombieclasses.ini and zp_extraitems.ini. These files will be
  120. automatically updated as you install new custom classes or items with
  121. new entries for you to edit conveniently.
  122.  
  123. ---------------
  124. -*- History -*-
  125. ---------------
  126.  
  127. This project started back on late 2007, when the free infection mods
  128. around were quite buggy and I wanted to make one on my own. With little
  129. to no experience at AMXX scripting, I had to start from the very scratch.
  130.  
  131. Not after spending over a week looking at many plugins (mainly Zombie
  132. Swarm) and scarce tutorials, I somehow managed to have all the basic
  133. stuff working quite well (even though the code was a real mess). The
  134. following months were spent polishing things up and trying to fulfill
  135. new original ideas, most of them quite worth the hard work.
  136.  
  137. In the meantime, I got the chance to try the plugin out on a 32 man
  138. server. This meant a huge progress on development, and after lots of
  139. testing and bug fixing, the mod turned out to be more than the simple
  140. infection plugin I had originally planned it to be.
  141.  
  142. The project has come a long way since, and I'm glad to say I'm finally
  143. making it freely available. All I'm asking in return is to keep my
  144. name in the plugin.
  145.  
  146. -Enjoy!
  147.  
  148. ----------------------
  149. -*- Infection Mode -*-
  150. ----------------------
  151.  
  152. On every round players start out as humans, equip themselves with a few
  153. weapons and grenades, and head to the closest cover they find, knowing
  154. that one of them is infected with the T-Virus, and will suddenly turn
  155. into a vicious brain eating creature.
  156.  
  157. Only little time after, the battle for survival begins. The first zombie
  158. has to infect as many humans as possible to cluster a numerous zombie
  159. horde and take over the world.
  160.  
  161. Maps are set in the dark by default. Humans must use flashlights to light
  162. their way and spot any enemies. Zombies, on the other hand, have night
  163. vision but can only attack melee.
  164.  
  165. --------------------------
  166. -*- New Gameplay Modes -*-
  167. --------------------------
  168.  
  169. * Nemesis:
  170. The first zombie may turn into a Nemesis, a powerful fast-moving
  171. beast. His goal is to kill every human while sustaining the gunfire.
  172.  
  173. * Survivor:
  174. Everyone became a zombie except him. The survivor gets a machinegun
  175. with unlimited ammo and has to stop the never-ending army of undead.
  176.  
  177. * Multiple Infection:
  178. The round starts with many humans infected, so the remaining players
  179. will have to act quickly in order to control the situation.
  180.  
  181. * Swarm Mode:
  182. Half of the players turn into zombies, the rest become immune and
  183. cannot be infected. It's a battle to death.
  184.  
  185. * Plague Mode: [bonus]
  186. A full armed Survivor and his soldiers are to face Nemesis and
  187. his zombie minions. The future of the world is in their hands.
  188.  
  189. --------------------
  190. -*- In-Game Menu -*-
  191. --------------------
  192.  
  193. Players can access the mod menu by typing "zpmenu" on chat, or by
  194. pressing the M ("chooseteam") key. The menu allows players to choose
  195. their zombie class, buy extra items, get unstuck, or see the ingame
  196. help. Admins will find an additional option to easily perform all
  197. console commands.
  198.  
  199. ----------------------
  200. -*- Admin Commands -*-
  201. ----------------------
  202.  
  203. The following console commands are available:
  204.  
  205. * zp_zombie <target> - Turn someone into a Zombie
  206. * zp_human <target> - Turn someone back to Human
  207. * zp_nemesis <target> - Turn someone into a Nemesis
  208. * zp_survivor <target> - Turn someone into a Survivor
  209. * zp_respawn <target> - Respawn someone
  210. * zp_swarm - Start Swarm Mode (*)
  211. * zp_multi - Start Multi Infection (*)
  212. * zp_plague - Start Plague Mode (*)
  213.  
  214. (*) - These commands can only be used at round start, that is, when the
  215. T-Virus notice is shown on screen.
  216.  
  217. ------------------
  218. -*- Plugin API -*-
  219. ------------------
  220.  
  221. From version 3.6, some natives and forwards have been added to ease the
  222. development of sub-plugins, though you may also find them useful to work
  223. out compatibility issues with existing plugins.
  224.  
  225. Look for the zombieplague.inc file in your amxmodx\scripting\include
  226. folder for the full documented list.
  227.  
  228. ----------------------
  229. -*- Zombie Classes -*-
  230. ----------------------
  231.  
  232. From version 4.0 it is possible to create and add an unlimited number of
  233. zombie classes to the main mod. They can be made as separate plugins,
  234. by using the provided zombie class API, and easily distributed.
  235.  
  236. By default, five zombie classes are included:
  237.  
  238. * Classic Zombie: well balanced zombie for beginners.
  239. * Raptor Zombie: fast moving zombie, but also the weakest.
  240. * Poison Zombie: light weighed zombie, jumps higher.
  241. * Big Zombie: slow but strong zombie, with lots of hit points.
  242. * Leech Zombie: regains additional health when infecting.
  243.  
  244. -------------------
  245. -*- Extra Items -*-
  246. -------------------
  247.  
  248. From version 4.0 it is possible to add an unlimited number of items
  249. which can be purchased through the Extra Items menu. All you need
  250. to do is use the provided item registration natives on your custom
  251. plugins. You can set the name, the cost in ammo packs, and the team
  252. the extra item should be available for.
  253.  
  254. By default there is a number of items already included, listed here:
  255.  
  256. * Night Vision: makes you able to see in the dark for a single round [Human]
  257. * T-Virus Antidote: makes you turn back to your human form [Zombie]
  258. * Zombie Madness: you develop a powerful shield for a short time [Zombie]
  259. * Infection Bomb: infects anyone within its explosion radius [Zombie]
  260.  
  261. You are also able to choose some weapons to act as extra items, and change
  262. ammo packs costs in the customization file (zombieplague.ini).
  263.  
  264. ---------------
  265. -*- Credits -*-
  266. ---------------
  267.  
  268. * AMXX Dev Team: for all the hard work which made this possible
  269. * Imperio LNJ Community: for providing the first server where I
  270. could really test the plugin and for everyone's support
  271. * Mini_Midget: for his Zombie Swarm plugin which I used for reference
  272. on earliest stages of development
  273. * Avalanche: for the random spawning code I got from GunGame and the
  274. original Frostnades concept that I ported in here
  275. * cheap_suit: for some modelchange and knockback codes that I got from
  276. Biohazard
  277. * Simon Logic/ConnorMcLeod: for the Pain Shock Free feature
  278. * KRoT@L: for some code from Follow the Wounded, used to make the zombie
  279. bleeding feature
  280. * VEN: for Fakemeta Utilities and some useful stocks
  281. * RaaPuar and Goltark: for the custom grenade models
  282. * Orangutanz: for finding the precached modelindex offset
  283. * ML Translations: DKs/nunoabc/DarkMarcos (bp), JahMan/KWo (pl), DA (de),
  284. Zombie Lurker (ls), DoPe^ (da), k1nny (fr), NeWbiE' (cz), skymoon (tc),
  285. SUPER MATRIX/Shidla/zDemon/4eRT (ru), zsy314 (cn), lOlIl/Seehank (sk),
  286. Bridgestone (sv), crazyeffect.net/Mave/Wesley (nl), hleV/aaarnas (lt),
  287. darkbad945 (bg), decongamco (vn), beckham9224 (mn), TehGeorge (gr),
  288. shadoww_ro/tuty/georgik57/EastSider (ro)
  289. * Beta testers: for all the feedback, bug reports, and suggestions which
  290. constantly help improve this mod further
  291. * And to all zombie-mod supporters out there!
  292.  
  293. -----------------
  294. -*- Changelog -*-
  295. -----------------
  296.  
  297. * v1.0: (Dec 2007)
  298. - First Release: most of the basic stuff done.
  299. - Added: random spawning, HP display on hud, lighting setting,
  300. simple buy menu, custom nightvision, admin commands, Nemesis
  301. and Survivor modes, glow and leap settings for them.
  302.  
  303. * v2.2: (Jan 2008)
  304. - Added: zombie classes, ammo packs system, buying ammo for weapons,
  305. custom flashlight, admin skins setting, zombieplague.cfg file
  306. - Upgraded: weapons menu improved, flashlight and nightvision colors
  307. now customizable, HamSandwich module used to handle damage.
  308. - Fixed various bugs.
  309.  
  310. * v3.0: (Mar 2008)
  311. - Added: door removal setting, unstuck feature, human cvars, armor
  312. cvar for zombies, weapon knockback, zombie bleeding, flares,
  313. extra items (weapons, antidote, infection bomb), pain shock
  314. free setting, Multiple Infection and Swarm modes.
  315. - Upgraded: dumped Engine, Fun and Cstrike modules, code optimized,
  316. new model change method, new gfx effects for zombie infections.
  317. - Fixed a bunch of gameplay bugs.
  318.  
  319. * v3.5: (May 2008)
  320. - Added: deathmatch setting with spawn protection, unlimited ammo
  321. setting, fire and frost grenades, additional customization cvars,
  322. new extra items, help menu.
  323. - Upgraded: better objectives removal method, dropped weapons now
  324. keep their bpammo, code optimized a lot.
  325. - Fixed: no more game commencing bug when last zombie/human leaves,
  326. no more hegrenade infection bug, reduced svc_bad errors, and
  327. many more.
  328.  
  329. * v3.6: (Jun 2008)
  330. - Added: a few natives and forwards for sub-plugins support,
  331. zombie classes can now have their own models, additional
  332. knockback customization, bot support, various CVARs.
  333. - Upgraded: extra items now supporting grenades and pistols, changed
  334. bomb removal method, players can join on survivor/swarm rounds,
  335. extended lightnings support to other dark settings.
  336. - Fixed: a bunch of minor bugs, and a server crash with CZ bots.
  337.  
  338. * v4.0: (Aug 2008)
  339. - Added: new gameplay mode (Plague Mode), option to remember weapon
  340. selection, command to enable/disable the plugin, more CVARs.
  341. - Upgraded: redid all the menus, extra items and zombie classes now
  342. support external additions, survivor can now have its own model,
  343. upgraded model changing method.
  344. - Fixed: some bugs with bots, win sounds not being precached.
  345.  
  346. * v4.1: (Oct 2008)
  347. - Added: more CVARs, more customization, more natives, custom
  348. leap system, admin zombie models support, and more.
  349. - Upgraded: custom grenades compatible with Nade Modes, ambience
  350. sounds specific game mode support, optimized bandwidth usage
  351. for temp ents, admin commands logged with IP and SteamID.
  352. - Fixed: lots of bugs (some minor, some not)
  353.  
  354. * v4.2: (Feb 2009)
  355. - Added various CVARs for customization, improved prevention of
  356. svc_bad in some cases, optimized ammo handling code.
  357. - Fixed server crash with 'msg 35 has not been sent yet' error,
  358. fixed client overflow issues with ambience sounds, resolved
  359. many gameplay bugs.
  360.  
  361. * v4.3: (Apr 2009)
  362. - Customization settings can now be edited through external files,
  363. added support for global and multiple random zombie models,
  364. added even more CVARs for tweaking stuff, extended admin commands'
  365. functionality, greatly extended API capabilities, implemented a
  366. more efficient Pain Shock Free code, reworked some menus.
  367. - Fixed pretty much all reported bugs to the date.
  368.  
  369. =================================================================================*/
  370.  
  371. /*================================================================================
  372. [Plugin Customization]
  373. =================================================================================*/
  374.  
  375. // All customization settings have been moved
  376. // to external files to allow easier editing
  377. new const ZP_CUSTOMIZATION_FILE[] = "zombieplague.ini"
  378. new const ZP_EXTRAITEMS_FILE[] = "zp_extraitems.ini"
  379. new const ZP_ZOMBIECLASSES_FILE[] = "zp_zombieclasses.ini"
  380.  
  381. // Limiters for stuff not worth making dynamic arrays out of (increase if needed)
  382. const MAX_CSDM_SPAWNS = 128
  383. const MAX_STATS_SAVED = 64
  384.  
  385. /*================================================================================
  386. Customization ends here! Yes, that's it. Editing anything beyond
  387. here is not officially supported. Proceed at your own risk...
  388. =================================================================================*/
  389.  
  390. #include <amxmodx>
  391. #include <amxmisc>
  392. #include <cstrike>
  393. #include <fakemeta>
  394. #include <hamsandwich>
  395. #include <xs>
  396.  
  397. /*================================================================================
  398. [Constants, Offsets, Macros]
  399. =================================================================================*/
  400.  
  401. // Plugin Version
  402. new const PLUGIN_VERSION[] = "4.3 Fix5a"
  403.  
  404. // Customization file sections
  405. enum
  406. {
  407. SECTION_NONE = 0,
  408. SECTION_ACCESS_FLAGS,
  409. SECTION_PLAYER_MODELS,
  410. SECTION_WEAPON_MODELS,
  411. SECTION_GRENADE_SPRITES,
  412. SECTION_SOUNDS,
  413. SECTION_AMBIENCE_SOUNDS,
  414. SECTION_BUY_MENU_WEAPONS,
  415. SECTION_EXTRA_ITEMS_WEAPONS,
  416. SECTION_HARD_CODED_ITEMS_COSTS,
  417. SECTION_WEATHER_EFFECTS,
  418. SECTION_SKY,
  419. SECTION_LIGHTNING,
  420. SECTION_ZOMBIE_DECALS,
  421. SECTION_KNOCKBACK,
  422. SECTION_OBJECTIVE_ENTS,
  423. SECTION_SVC_BAD
  424. }
  425.  
  426. // Access flags
  427. enum
  428. {
  429. ACCESS_ENABLE_MOD = 0,
  430. ACCESS_ADMIN_MENU,
  431. ACCESS_MODE_INFECTION,
  432. ACCESS_MODE_NEMESIS,
  433. ACCESS_MODE_SURVIVOR,
  434. ACCESS_MODE_SWARM,
  435. ACCESS_MODE_MULTI,
  436. ACCESS_MODE_PLAGUE,
  437. ACCESS_MAKE_ZOMBIE,
  438. ACCESS_MAKE_HUMAN,
  439. ACCESS_MAKE_NEMESIS,
  440. ACCESS_MAKE_SURVIVOR,
  441. ACCESS_RESPAWN_PLAYERS,
  442. ACCESS_ADMIN_MODELS,
  443. MAX_ACCESS_FLAGS
  444. }
  445.  
  446. // Task offsets
  447. enum (+= 100)
  448. {
  449. TASK_MODEL = 2000,
  450. TASK_TEAM,
  451. TASK_SPAWN,
  452. TASK_BLOOD,
  453. TASK_AURA,
  454. TASK_BURN,
  455. TASK_NVISION,
  456. TASK_FLASH,
  457. TASK_CHARGE,
  458. TASK_SHOWHUD,
  459. TASK_MAKEZOMBIE,
  460. TASK_WELCOMEMSG,
  461. TASK_THUNDER_PRE,
  462. TASK_THUNDER,
  463. TASK_AMBIENCESOUNDS
  464. }
  465.  
  466. // IDs inside tasks
  467. #define ID_MODEL (taskid - TASK_MODEL)
  468. #define ID_TEAM (taskid - TASK_TEAM)
  469. #define ID_SPAWN (taskid - TASK_SPAWN)
  470. #define ID_BLOOD (taskid - TASK_BLOOD)
  471. #define ID_AURA (taskid - TASK_AURA)
  472. #define ID_BURN (taskid - TASK_BURN)
  473. #define ID_NVISION (taskid - TASK_NVISION)
  474. #define ID_FLASH (taskid - TASK_FLASH)
  475. #define ID_CHARGE (taskid - TASK_CHARGE)
  476. #define ID_SHOWHUD (taskid - TASK_SHOWHUD)
  477.  
  478. // BP Ammo Refill task
  479. #define REFILL_WEAPONID args[0]
  480.  
  481. // For weapon buy menu handlers
  482. #define WPN_STARTID g_menu_data[id][1]
  483. #define WPN_MAXIDS ArraySize(g_primary_items)
  484. #define WPN_SELECTION (g_menu_data[id][1]+key)
  485. #define WPN_AUTO_ON g_menu_data[id][2]
  486. #define WPN_AUTO_PRI g_menu_data[id][3]
  487. #define WPN_AUTO_SEC g_menu_data[id][4]
  488.  
  489. // For player list menu handlers
  490. #define PL_ACTION g_menu_data[id][0]
  491.  
  492. // For remembering menu pages
  493. #define MENU_PAGE_ZCLASS g_menu_data[id][5]
  494. #define MENU_PAGE_EXTRAS g_menu_data[id][6]
  495. #define MENU_PAGE_PLAYERS g_menu_data[id][7]
  496.  
  497. // For extra items menu handlers
  498. #define EXTRAS_CUSTOM_STARTID (EXTRA_WEAPONS_STARTID + ArraySize(g_extraweapon_names))
  499.  
  500. // Menu selections
  501. const MENU_KEY_AUTOSELECT = 7
  502. const MENU_KEY_BACK = 7
  503. const MENU_KEY_NEXT = 8
  504. const MENU_KEY_EXIT = 9
  505.  
  506. // Hard coded extra items
  507. enum
  508. {
  509. EXTRA_NVISION = 0,
  510. EXTRA_ANTIDOTE,
  511. EXTRA_MADNESS,
  512. EXTRA_INFBOMB,
  513. EXTRA_WEAPONS_STARTID
  514. }
  515.  
  516. // Game modes
  517. enum
  518. {
  519. MODE_NONE = 0,
  520. MODE_INFECTION,
  521. MODE_NEMESIS,
  522. MODE_SURVIVOR,
  523. MODE_SWARM,
  524. MODE_MULTI,
  525. MODE_PLAGUE
  526. }
  527.  
  528. // ZP Teams
  529. const ZP_TEAM_NO_ONE = 0
  530. const ZP_TEAM_ANY = 0
  531. const ZP_TEAM_ZOMBIE = (1<<0)
  532. const ZP_TEAM_HUMAN = (1<<1)
  533. const ZP_TEAM_NEMESIS = (1<<2)
  534. const ZP_TEAM_SURVIVOR = (1<<3)
  535. new const ZP_TEAM_NAMES[][] = { "ZOMBIE , HUMAN", "ZOMBIE", "HUMAN", "ZOMBIE , HUMAN", "NEMESIS",
  536. "ZOMBIE , NEMESIS", "HUMAN , NEMESIS", "ZOMBIE , HUMAN , NEMESIS",
  537. "SURVIVOR", "ZOMBIE , SURVIVOR", "HUMAN , SURVIVOR", "ZOMBIE , HUMAN , SURVIVOR",
  538. "NEMESIS , SURVIVOR", "ZOMBIE , NEMESIS , SURVIVOR", "HUMAN, NEMESIS, SURVIVOR",
  539. "ZOMBIE , HUMAN , NEMESIS , SURVIVOR" }
  540.  
  541. // Zombie classes
  542. const ZCLASS_NONE = -1
  543.  
  544. // HUD messages
  545. const Float:HUD_EVENT_X = -1.0
  546. const Float:HUD_EVENT_Y = 0.17
  547. const Float:HUD_INFECT_X = 0.05
  548. const Float:HUD_INFECT_Y = 0.45
  549. const Float:HUD_SPECT_X = 0.6
  550. const Float:HUD_SPECT_Y = 0.8
  551. const Float:HUD_STATS_X = 0.01
  552. const Float:HUD_STATS_Y = 0.23
  553.  
  554. // Hack to be able to use Ham_Player_ResetMaxSpeed (by joaquimandrade)
  555. new Ham:Ham_Player_ResetMaxSpeed = Ham_Item_PreFrame
  556.  
  557. // CS Player PData Offsets (win32)
  558. const PDATA_SAFE = 2
  559. const OFFSET_PAINSHOCK = 108 // ConnorMcLeod
  560. const OFFSET_CSTEAMS = 114
  561. const OFFSET_CSMONEY = 115
  562. const OFFSET_CSMENUCODE = 205
  563. const OFFSET_FLASHLIGHT_BATTERY = 244
  564. const OFFSET_CSDEATHS = 444
  565. const OFFSET_MODELINDEX = 491 // Orangutanz
  566.  
  567. // CS Player CBase Offsets (win32)
  568. const OFFSET_ACTIVE_ITEM = 373
  569.  
  570. // CS Weapon CBase Offsets (win32)
  571. const OFFSET_WEAPONOWNER = 41
  572.  
  573. // Linux diff's
  574. const OFFSET_LINUX = 5 // offsets 5 higher in Linux builds
  575. const OFFSET_LINUX_WEAPONS = 4 // weapon offsets are only 4 steps higher on Linux
  576.  
  577. // CS Teams
  578. enum
  579. {
  580. FM_CS_TEAM_UNASSIGNED = 0,
  581. FM_CS_TEAM_T,
  582. FM_CS_TEAM_CT,
  583. FM_CS_TEAM_SPECTATOR
  584. }
  585. new const CS_TEAM_NAMES[][] = { "UNASSIGNED", "TERRORIST", "CT", "SPECTATOR" }
  586.  
  587. // Some constants
  588. const HIDE_MONEY = (1<<5)
  589. const UNIT_SECOND = (1<<12)
  590. const DMG_HEGRENADE = (1<<24)
  591. const IMPULSE_FLASHLIGHT = 100
  592. const USE_USING = 2
  593. const USE_STOPPED = 0
  594. const STEPTIME_SILENT = 999
  595. const BREAK_GLASS = 0x01
  596. const FFADE_IN = 0x0000
  597. const FFADE_STAYOUT = 0x0004
  598. const PEV_SPEC_TARGET = pev_iuser2
  599.  
  600. // Max BP ammo for weapons
  601. new const MAXBPAMMO[] = { -1, 52, -1, 90, 1, 32, 1, 100, 90, 1, 120, 100, 100, 90, 90, 90, 100, 120,
  602. 30, 120, 200, 32, 90, 120, 90, 2, 35, 90, 90, -1, 100 }
  603.  
  604. // Max Clip for weapons
  605. new const MAXCLIP[] = { -1, 13, -1, 10, -1, 7, -1, 30, 30, -1, 30, 20, 25, 30, 35, 25, 12, 20,
  606. 10, 30, 100, 8, 30, 30, 20, -1, 7, 30, 30, -1, 50 }
  607.  
  608. // Amount of ammo to give when buying additional clips for weapons
  609. new const BUYAMMO[] = { -1, 13, -1, 30, -1, 8, -1, 12, 30, -1, 30, 50, 12, 30, 30, 30, 12, 30,
  610. 10, 30, 30, 8, 30, 30, 30, -1, 7, 30, 30, -1, 50 }
  611.  
  612. // Ammo IDs for weapons
  613. new const AMMOID[] = { -1, 9, -1, 2, 12, 5, 14, 6, 4, 13, 10, 7, 6, 4, 4, 4, 6, 10,
  614. 1, 10, 3, 5, 4, 10, 2, 11, 8, 4, 2, -1, 7 }
  615.  
  616. // Ammo Type Names for weapons
  617. new const AMMOTYPE[][] = { "", "357sig", "", "762nato", "", "buckshot", "", "45acp", "556nato", "", "9mm", "57mm", "45acp",
  618. "556nato", "556nato", "556nato", "45acp", "9mm", "338magnum", "9mm", "556natobox", "buckshot",
  619. "556nato", "9mm", "762nato", "", "50ae", "556nato", "762nato", "", "57mm" }
  620.  
  621. // Weapon IDs for ammo types
  622. new const AMMOWEAPON[] = { 0, CSW_AWP, CSW_SCOUT, CSW_M249, CSW_AUG, CSW_XM1014, CSW_MAC10, CSW_FIVESEVEN, CSW_DEAGLE,
  623. CSW_P228, CSW_ELITE, CSW_FLASHBANG, CSW_HEGRENADE, CSW_SMOKEGRENADE, CSW_C4 }
  624.  
  625. // Primary and Secondary Weapon Names
  626. new const WEAPONNAMES[][] = { "", "P228 Compact", "", "Schmidt Scout", "", "XM1014 M4", "", "Ingram MAC-10", "Steyr AUG A1",
  627. "", "Dual Elite Berettas", "FiveseveN", "UMP 45", "SG-550 Auto-Sniper", "IMI Galil", "Famas",
  628. "USP .45 ACP Tactical", "Glock 18C", "AWP Magnum Sniper", "MP5 Navy", "M249 Para Machinegun",
  629. "M3 Super 90", "M4A1 Carbine", "Schmidt TMP", "G3SG1 Auto-Sniper", "", "Desert Eagle .50 AE",
  630. "SG-552 Commando", "AK-47 Kalashnikov", "", "ES P90" }
  631.  
  632. // Weapon entity names
  633. new const WEAPONENTNAMES[][] = { "", "weapon_p228", "", "weapon_scout", "weapon_hegrenade", "weapon_xm1014", "weapon_c4", "weapon_mac10",
  634. "weapon_aug", "weapon_smokegrenade", "weapon_elite", "weapon_fiveseven", "weapon_ump45", "weapon_sg550",
  635. "weapon_galil", "weapon_famas", "weapon_usp", "weapon_glock18", "weapon_awp", "weapon_mp5navy", "weapon_m249",
  636. "weapon_m3", "weapon_m4a1", "weapon_tmp", "weapon_g3sg1", "weapon_flashbang", "weapon_deagle", "weapon_sg552",
  637. "weapon_ak47", "weapon_knife", "weapon_p90" }
  638.  
  639. // CS sounds
  640. new const sound_flashlight[] = "items/flashlight1.wav"
  641. new const sound_buyammo[] = "items/9mmclip1.wav"
  642. new const sound_armorhit[] = "player/bhit_helmet-1.wav"
  643.  
  644. // Explosion radius for custom grenades
  645. const Float:NADE_EXPLOSION_RADIUS = 240.0
  646.  
  647. // HACK: pev_ field used to store additional ammo on weapons
  648. const PEV_ADDITIONAL_AMMO = pev_iuser1
  649.  
  650. // HACK: pev_ field used to store custom nade types and their values
  651. const PEV_NADE_TYPE = pev_flTimeStepSound
  652. const NADE_TYPE_INFECTION = 1111
  653. const NADE_TYPE_NAPALM = 2222
  654. const NADE_TYPE_FROST = 3333
  655. const NADE_TYPE_FLARE = 4444
  656. const PEV_FLARE_COLOR = pev_punchangle
  657. const PEV_FLARE_DURATION = pev_flSwimTime
  658.  
  659. // Weapon bitsums
  660. const PRIMARY_WEAPONS_BIT_SUM = (1<<CSW_SCOUT)|(1<<CSW_XM1014)|(1<<CSW_MAC10)|(1<<CSW_AUG)|(1<<CSW_UMP45)|(1<<CSW_SG550)|(1<<CSW_GALIL)|(1<<CSW_FAMAS)|(1<<CSW_AWP)|(1<<CSW_MP5NAVY)|(1<<CSW_M249)|(1<<CSW_M3)|(1<<CSW_M4A1)|(1<<CSW_TMP)|(1<<CSW_G3SG1)|(1<<CSW_SG552)|(1<<CSW_AK47)|(1<<CSW_P90)
  661. const SECONDARY_WEAPONS_BIT_SUM = (1<<CSW_P228)|(1<<CSW_ELITE)|(1<<CSW_FIVESEVEN)|(1<<CSW_USP)|(1<<CSW_GLOCK18)|(1<<CSW_DEAGLE)
  662.  
  663. // Allowed weapons for zombies (added grenades/bomb for sub-plugin support, since they shouldn't be getting them anyway)
  664. const ZOMBIE_ALLOWED_WEAPONS_BITSUM = (1<<CSW_KNIFE)|(1<<CSW_HEGRENADE)|(1<<CSW_FLASHBANG)|(1<<CSW_SMOKEGRENADE)|(1<<CSW_C4)
  665.  
  666. // Classnames for separate model entities
  667. new const MODEL_ENT_CLASSNAME[] = "player_model"
  668. new const WEAPON_ENT_CLASSNAME[] = "weapon_model"
  669.  
  670. // Menu keys
  671. const KEYSMENU = MENU_KEY_1|MENU_KEY_2|MENU_KEY_3|MENU_KEY_4|MENU_KEY_5|MENU_KEY_6|MENU_KEY_7|MENU_KEY_8|MENU_KEY_9|MENU_KEY_0
  672.  
  673. // Ambience Sounds
  674. enum
  675. {
  676. AMBIENCE_SOUNDS_INFECTION = 0,
  677. AMBIENCE_SOUNDS_NEMESIS,
  678. AMBIENCE_SOUNDS_SURVIVOR,
  679. AMBIENCE_SOUNDS_SWARM,
  680. AMBIENCE_SOUNDS_PLAGUE,
  681. MAX_AMBIENCE_SOUNDS
  682. }
  683.  
  684. // Admin menu actions
  685. enum
  686. {
  687. ACTION_ZOMBIEFY_HUMANIZE = 0,
  688. ACTION_MAKE_NEMESIS,
  689. ACTION_MAKE_SURVIVOR,
  690. ACTION_RESPAWN_PLAYER,
  691. ACTION_MODE_SWARM,
  692. ACTION_MODE_MULTI,
  693. ACTION_MODE_PLAGUE
  694. }
  695.  
  696. // Custom forward return values
  697. const ZP_PLUGIN_HANDLED = 97
  698.  
  699. /*================================================================================
  700. [Global Variables]
  701. =================================================================================*/
  702.  
  703. // Player vars
  704. new g_zombie[33] // is zombie
  705. new g_nemesis[33] // is nemesis
  706. new g_survivor[33] // is survivor
  707. new g_firstzombie[33] // is first zombie
  708. new g_lastzombie[33] // is last zombie
  709. new g_lasthuman[33] // is last human
  710. new g_frozen[33] // is frozen (can't move)
  711. new Float:g_frozen_gravity[33] // store previous gravity when frozen
  712. new g_nodamage[33] // has spawn protection/zombie madness
  713. new g_respawn_as_zombie[33] // should respawn as zombie
  714. new g_nvision[33] // has night vision
  715. new g_nvisionenabled[33] // has night vision turned on
  716. new g_zombieclass[33] // zombie class
  717. new g_zombieclassnext[33] // zombie class for next infection
  718. new g_flashlight[33] // has custom flashlight turned on
  719. new g_flashbattery[33] = { 100, ... } // custom flashlight battery
  720. new g_canbuy[33] // is allowed to buy a new weapon through the menu
  721. new g_ammopacks[33] // ammo pack count
  722. new g_damagedealt_human[33] // damage dealt as human (used to calculate ammo packs reward)
  723. new g_damagedealt_zombie[33] // damage dealt as zombie (used to calculate ammo packs reward)
  724. new Float:g_lastleaptime[33] // time leap was last used
  725. new Float:g_lastflashtime[33] // time flashlight was last toggled
  726. new g_playermodel[33][32] // current model's short name [player][model]
  727. new g_menu_data[33][8] // data for some menu handlers
  728. new g_ent_playermodel[33] // player model entity
  729. new g_ent_weaponmodel[33] // weapon model entity
  730. new g_burning_duration[33] // burning task duration
  731. new Float:g_buytime[33] // used to calculate custom buytime
  732.  
  733. new g_infectnade[33] // has infection nade
  734. new g_unlimited_clip[33] // has unlimited_clip
  735. new g_painshockfree[33] // has pain shock free
  736.  
  737. // Game vars
  738. new g_pluginenabled // ZP enabled
  739. new g_newround // new round starting
  740. new g_endround // round ended
  741. new g_nemround // nemesis round
  742. new g_survround // survivor round
  743. new g_swarmround // swarm round
  744. new g_plagueround // plague round
  745. new g_modestarted // mode fully started
  746. new g_lastmode // last played mode
  747. new g_scorezombies, g_scorehumans, g_gamecommencing // team scores
  748. new g_spawnCount, g_spawnCount2 // available spawn points counter
  749. new Float:g_spawns[MAX_CSDM_SPAWNS][3], Float:g_spawns2[MAX_CSDM_SPAWNS][3] // spawn points data
  750. new g_lights_i // lightning current lights counter
  751. new g_lights_cycle[32] // current lightning cycle
  752. new g_lights_cycle_len // lightning cycle length
  753. new Float:g_models_targettime // for adding delays between Model Change messages
  754. new Float:g_teams_targettime // for adding delays between Team Change messages
  755. new g_MsgSync, g_MsgSync2 // message sync objects
  756. new g_trailSpr, g_exploSpr, g_flameSpr, g_smokeSpr, g_glassSpr // grenade sprites
  757. new g_modname[32] // for formatting the mod name
  758. new g_freezetime // whether CS's freeze time is on
  759. new g_maxplayers // max players counter
  760. new g_czero // whether we are running on a CZ server
  761. new g_hamczbots // whether ham forwards are registered for CZ bots
  762. new g_fwSpawn, g_fwPrecacheSound // spawn and precache sound forward handles
  763. new g_infbombcounter, g_antidotecounter, g_madnesscounter // to limit buying some items
  764. new g_arrays_created // to prevent stuff from being registered before initializing arrays
  765. new g_lastplayerleaving // flag for whenever a player leaves and another takes his place
  766. new g_switchingteam // flag for whenever a player's team change emessage is sent
  767. new g_buyzone_ent // custom buyzone entity
  768.  
  769. // Message IDs vars
  770. new g_msgScoreInfo, g_msgNVGToggle, g_msgScoreAttrib, g_msgAmmoPickup, g_msgScreenFade,
  771. g_msgDeathMsg, g_msgSetFOV, g_msgFlashlight, g_msgFlashBat, g_msgTeamInfo, g_msgDamage,
  772. g_msgHideWeapon, g_msgCrosshair, g_msgSayText, g_msgScreenShake, g_msgCurWeapon
  773.  
  774. // Some forward handlers
  775. new g_fwRoundStart, g_fwRoundEnd, g_fwUserInfected_pre, g_fwUserInfected_post,
  776. g_fwUserHumanized_pre, g_fwUserHumanized_post, g_fwUserInfect_attempt,
  777. g_fwUserHumanize_attempt, g_fwExtraItemSelected, g_fwUserUnfrozen,
  778. g_fwUserLastZombie, g_fwUserLastHuman, g_fwDummyResult
  779.  
  780. // Temporary Database vars (used to restore players stats in case they get disconnected)
  781. new db_name[MAX_STATS_SAVED][32] // player name
  782. new db_ammopacks[MAX_STATS_SAVED] // ammo pack count
  783. new db_zombieclass[MAX_STATS_SAVED] // zombie class
  784. new db_slot_i // additional saved slots counter (should start on maxplayers+1)
  785.  
  786. // Extra Items vars
  787. new Array:g_extraitem_name // caption
  788. new Array:g_extraitem_cost // cost
  789. new Array:g_extraitem_team // team
  790. new g_extraitem_i // loaded extra items counter
  791.  
  792. // For extra items file parsing
  793. new Array:g_extraitem2_realname, Array:g_extraitem2_name, Array:g_extraitem2_cost,
  794. Array:g_extraitem2_team, Array:g_extraitem_new
  795.  
  796. // Zombie Classes vars
  797. new Array:g_zclass_name // caption
  798. new Array:g_zclass_info // description
  799. new Array:g_zclass_modelsstart // start position in models array
  800. new Array:g_zclass_modelsend // end position in models array
  801. new Array:g_zclass_playermodel // player models array
  802. new Array:g_zclass_modelindex // model indices array
  803. new Array:g_zclass_clawmodel // claw model
  804. new Array:g_zclass_hp // health
  805. new Array:g_zclass_spd // speed
  806. new Array:g_zclass_grav // gravity
  807. new Array:g_zclass_kb // knockback
  808. new g_zclass_i // loaded zombie classes counter
  809.  
  810. // For zombie classes file parsing
  811. new Array:g_zclass2_realname, Array:g_zclass2_name, Array:g_zclass2_info,
  812. Array:g_zclass2_modelsstart, Array:g_zclass2_modelsend, Array:g_zclass2_playermodel,
  813. Array:g_zclass2_modelindex, Array:g_zclass2_clawmodel, Array:g_zclass2_hp,
  814. Array:g_zclass2_spd, Array:g_zclass2_grav, Array:g_zclass2_kb, Array:g_zclass_new
  815.  
  816. // Customization vars
  817. new g_access_flag[MAX_ACCESS_FLAGS], Array:model_nemesis, Array:model_survivor, Array:model_human,
  818. Array:model_admin_zombie, Array:model_admin_human, Array:g_modelindex_human,
  819. Array:g_modelindex_nemesis, Array:g_modelindex_survivor, g_same_models_for_all,
  820. Array:g_modelindex_admin_zombie, Array:g_modelindex_admin_human, model_vknife_human[64],
  821. model_vknife_nemesis[64], model_vweapon_survivor[64], model_grenade_infect[64],
  822. model_grenade_fire[64], model_grenade_frost[64], model_grenade_flare[64],
  823. model_vknife_admin_human[64], model_vknife_admin_zombie[64],
  824. sprite_grenade_trail[64], sprite_grenade_ring[64], sprite_grenade_fire[64],
  825. sprite_grenade_smoke[64], sprite_grenade_glass[64], Array:sound_win_zombies,
  826. Array:sound_win_humans, Array:sound_win_no_one, Array:sound_win_zombies_ismp3,
  827. Array:sound_win_humans_ismp3, Array:sound_win_no_one_ismp3, Array:zombie_infect,
  828. Array:zombie_idle, Array:zombie_pain, Array:nemesis_pain, Array:zombie_die, Array:zombie_fall,
  829. Array:zombie_miss_wall, Array:zombie_hit_normal, Array:zombie_hit_stab, g_ambience_rain,
  830. Array:zombie_idle_last, Array:zombie_madness, Array:sound_nemesis, Array:sound_survivor,
  831. Array:sound_swarm, Array:sound_multi, Array:sound_plague, Array:grenade_infect,
  832. Array:grenade_infect_player, Array:grenade_fire, Array:grenade_fire_player,
  833. Array:grenade_frost, Array:grenade_frost_player, Array:grenade_frost_break,
  834. Array:grenade_flare, Array:sound_antidote, Array:sound_thunder, g_ambience_sounds[MAX_AMBIENCE_SOUNDS],
  835. Array:sound_ambience1, Array:sound_ambience2, Array:sound_ambience3, Array:sound_ambience4,
  836. Array:sound_ambience5, Array:sound_ambience1_duration, Array:sound_ambience2_duration,
  837. Array:sound_ambience3_duration, Array:sound_ambience4_duration,
  838. Array:sound_ambience5_duration, Array:sound_ambience1_ismp3, Array:sound_ambience2_ismp3,
  839. Array:sound_ambience3_ismp3, Array:sound_ambience4_ismp3, Array:sound_ambience5_ismp3,
  840. Array:g_primary_items, Array:g_secondary_items, Array:g_additional_items,
  841. Array:g_primary_weaponids, Array:g_secondary_weaponids, Array:g_extraweapon_names,
  842. Array:g_extraweapon_items, Array:g_extraweapon_costs, g_extra_costs2[EXTRA_WEAPONS_STARTID],
  843. g_ambience_snow, g_ambience_fog, g_fog_density[10], g_fog_color[12], g_sky_enable,
  844. Array:g_sky_names, Array:lights_thunder, Array:zombie_decals, Array:g_objective_ents,
  845. Float:g_modelchange_delay, g_set_modelindex_offset, g_handle_models_on_separate_ent,
  846. Float:kb_weapon_power[31] = { -1.0, ... }, Array:zombie_miss_slash, g_force_consistency
  847.  
  848. // CVAR pointers
  849. new cvar_lighting, cvar_zombiefov, cvar_plague, cvar_plaguechance, cvar_zombiefirsthp,
  850. cvar_removemoney, cvar_thunder, cvar_zombiebonushp, cvar_nemhp, cvar_nem, cvar_surv,
  851. cvar_nemchance, cvar_deathmatch, cvar_nemglow, cvar_customnvg, cvar_hitzones, cvar_humanhp,
  852. cvar_nemgravity, cvar_flashsize, cvar_ammodamage_human, cvar_ammodamage_zombie,
  853. cvar_zombiearmor, cvar_survpainfree, cvar_nempainfree, cvar_nemspd, cvar_survchance,
  854. cvar_survhp, cvar_survspd, cvar_humanspd, cvar_swarmchance, cvar_flashdrain,
  855. cvar_zombiebleeding, cvar_removedoors, cvar_customflash, cvar_randspawn, cvar_multi,
  856. cvar_multichance, cvar_infammo, cvar_swarm, cvar_ammoinfect, cvar_toggle,
  857. cvar_knockbackpower, cvar_freezeduration, cvar_triggered, cvar_flashcharge,
  858. cvar_firegrenades, cvar_frostgrenades, cvar_survgravity, cvar_logcommands, cvar_survglow,
  859. cvar_humangravity, cvar_spawnprotection, cvar_nvgsize, cvar_flareduration, cvar_zclasses,
  860. cvar_extraitems, cvar_showactivity, cvar_humanlasthp, cvar_nemignorefrags, cvar_warmup,
  861. cvar_flashdist, cvar_flarecolor, cvar_survignorefrags, cvar_fireduration, cvar_firedamage,
  862. cvar_flaregrenades, cvar_knockbackducking, cvar_knockbackdamage, cvar_knockbackzvel,
  863. cvar_multiratio, cvar_flaresize, cvar_spawndelay, cvar_extraantidote, cvar_extramadness,
  864. cvar_extraweapons, cvar_extranvision, cvar_nvggive, cvar_preventconsecutive, cvar_botquota,
  865. cvar_buycustom, cvar_zombiepainfree, cvar_fireslowdown, cvar_survbasehp, cvar_survaura,
  866. cvar_nemignoreammo, cvar_survignoreammo, cvar_nemaura, cvar_extrainfbomb, cvar_knockback,
  867. cvar_fragsinfect, cvar_fragskill, cvar_humanarmor, cvar_zombiesilent, cvar_removedropped,
  868. cvar_plagueratio, cvar_blocksuicide, cvar_knockbackdist, cvar_nemdamage, cvar_leapzombies,
  869. cvar_leapzombiesforce, cvar_leapzombiesheight, cvar_leapzombiescooldown, cvar_leapnemesis,
  870. cvar_leapnemesisforce, cvar_leapnemesisheight, cvar_leapnemesiscooldown, cvar_leapsurvivor,
  871. cvar_leapsurvivorforce, cvar_leapsurvivorheight, cvar_nemminplayers, cvar_survminplayers,
  872. cvar_respawnonsuicide, cvar_respawnafterlast, cvar_leapsurvivorcooldown, cvar_statssave,
  873. cvar_swarmminplayers, cvar_multiminplayers, cvar_plagueminplayers, cvar_adminmodelshuman,
  874. cvar_adminmodelszombie, cvar_nembasehp, cvar_blockpushables, cvar_respawnworldspawnkill,
  875. cvar_madnessduration, cvar_plaguenemnum, cvar_plaguenemhpmulti, cvar_plaguesurvhpmulti,
  876. cvar_survweapon, cvar_plaguesurvnum, cvar_infectionscreenfade, cvar_infectionscreenshake,
  877. cvar_infectionsparkle, cvar_infectiontracers, cvar_infectionparticles, cvar_infbomblimit,
  878. cvar_allowrespawnsurv, cvar_flashshowall, cvar_allowrespawninfection, cvar_allowrespawnnem,
  879. cvar_allowrespawnswarm, cvar_allowrespawnplague, cvar_survinfammo, cvar_nemknockback,
  880. cvar_nvgcolor[3], cvar_nemnvgcolor[3], cvar_humnvgcolor[3], cvar_flashcolor[3],
  881. cvar_hudicons, cvar_respawnzomb, cvar_respawnhum, cvar_respawnnem, cvar_respawnsurv,
  882. cvar_startammopacks, cvar_randweapons, cvar_antidotelimit, cvar_madnesslimit,
  883. cvar_adminknifemodelshuman, cvar_adminknifemodelszombie, cvar_keephealthondisconnect,
  884. cvar_buyzonetime, cvar_huddisplay
  885.  
  886. // Cached stuff for players
  887. new g_isconnected[33] // whether player is connected
  888. new g_isalive[33] // whether player is alive
  889. new g_isbot[33] // whether player is a bot
  890. new g_currentweapon[33] // player's current weapon id
  891. new g_playername[33][32] // player's name
  892. new Float:g_zombie_spd[33] // zombie class speed
  893. new Float:g_zombie_knockback[33] // zombie class knockback
  894. new g_zombie_classname[33][32] // zombie class name
  895. #define is_user_valid_connected(%1) (1 <= %1 <= g_maxplayers && g_isconnected[%1])
  896. #define is_user_valid_alive(%1) (1 <= %1 <= g_maxplayers && g_isalive[%1])
  897. #define is_user_valid(%1) (1 <= %1 <= g_maxplayers)
  898.  
  899. // Cached CVARs
  900. new g_cached_customflash, g_cached_zombiesilent, g_cached_leapzombies, g_cached_leapnemesis,
  901. g_cached_leapsurvivor, Float:g_cached_leapzombiescooldown, Float:g_cached_leapnemesiscooldown,
  902. Float:g_cached_leapsurvivorcooldown, Float:g_cached_buytime
  903.  
  904. /*================================================================================
  905. [Natives, Precache and Init]
  906. =================================================================================*/
  907.  
  908. public plugin_natives()
  909. {
  910. // Player specific natives
  911. register_native("zp_get_user_zombie", "native_get_user_zombie", 1)
  912. register_native("zp_get_user_nemesis", "native_get_user_nemesis", 1)
  913. register_native("zp_get_user_survivor", "native_get_user_survivor", 1)
  914. register_native("zp_get_user_first_zombie", "native_get_user_first_zombie", 1)
  915. register_native("zp_get_user_last_zombie", "native_get_user_last_zombie", 1)
  916. register_native("zp_get_user_last_human", "native_get_user_last_human", 1)
  917. register_native("zp_get_user_zombie_class", "native_get_user_zombie_class", 1)
  918. register_native("zp_get_user_next_class", "native_get_user_next_class", 1)
  919. register_native("zp_set_user_zombie_class", "native_set_user_zombie_class", 1)
  920. register_native("zp_get_user_ammo_packs", "native_get_user_ammo_packs", 1)
  921. register_native("zp_set_user_ammo_packs", "native_set_user_ammo_packs", 1)
  922. register_native("zp_get_zombie_maxhealth", "native_get_zombie_maxhealth", 1)
  923. register_native("zp_get_user_batteries", "native_get_user_batteries", 1)
  924. register_native("zp_set_user_batteries", "native_set_user_batteries", 1)
  925. register_native("zp_get_user_nightvision", "native_get_user_nightvision", 1)
  926. register_native("zp_set_user_nightvision", "native_set_user_nightvision", 1)
  927. register_native("zp_infect_user", "native_infect_user", 1)
  928. register_native("zp_disinfect_user", "native_disinfect_user", 1)
  929. register_native("zp_make_user_nemesis", "native_make_user_nemesis", 1)
  930. register_native("zp_make_user_survivor", "native_make_user_survivor", 1)
  931. register_native("zp_respawn_user", "native_respawn_user", 1)
  932. register_native("zp_force_buy_extra_item", "native_force_buy_extra_item", 1)
  933. register_native("zp_override_user_model", "native_override_user_model", 1)
  934.  
  935. // Custom natives
  936. register_native("zp_get_user_frozen", "native_get_user_frozen", 1)
  937. register_native("zp_set_user_frozen", "native_set_user_frozen", 1)
  938. register_native("zp_user_has_infect_nade", "native_user_has_infect_nade", 1)
  939. register_native("zp_get_user_burning", "native_get_user_burning", 1)
  940. register_native("zp_set_user_burning", "native_set_user_burning", 1)
  941. register_native("zp_get_user_unlimited_clip", "native_get_user_unlimited_clip", 1)
  942. register_native("zp_set_user_unlimited_clip", "native_set_user_unlimited_clip", 1)
  943. register_native("zp_get_user_painshockfree", "native_get_user_painshockfree", 1)
  944. register_native("zp_set_user_painshockfree", "native_set_user_painshockfree", 1)
  945. register_native("zp_set_gamemode", "native_zp_set_gamemode", 1)
  946.  
  947. // Round natives
  948. register_native("zp_has_round_started", "native_has_round_started", 1)
  949. register_native("zp_is_nemesis_round", "native_is_nemesis_round", 1)
  950. register_native("zp_is_survivor_round", "native_is_survivor_round", 1)
  951. register_native("zp_is_swarm_round", "native_is_swarm_round", 1)
  952. register_native("zp_is_plague_round", "native_is_plague_round", 1)
  953. register_native("zp_get_zombie_count", "native_get_zombie_count", 1)
  954. register_native("zp_get_human_count", "native_get_human_count", 1)
  955. register_native("zp_get_nemesis_count", "native_get_nemesis_count", 1)
  956. register_native("zp_get_survivor_count", "native_get_survivor_count", 1)
  957.  
  958. // External additions natives
  959. register_native("zp_register_extra_item", "native_register_extra_item", 1)
  960. register_native("zp_register_zombie_class", "native_register_zombie_class", 1)
  961. register_native("zp_get_extra_item_id", "native_get_extra_item_id", 1)
  962. register_native("zp_get_zombie_class_id", "native_get_zombie_class_id", 1)
  963. register_native("zp_get_zombie_class_info", "native_get_zombie_class_info", 1)
  964. }
  965.  
  966. public plugin_precache()
  967. {
  968. // Register earlier to show up in plugins list properly after plugin disable/error at loading
  969. register_plugin("Zombie Plague", PLUGIN_VERSION, "MeRcyLeZZ")
  970.  
  971. // To switch plugin on/off
  972. register_concmd("zp_toggle", "cmd_toggle", _, "<1/0> - Enable/Disable Zombie Plague (will restart the current map)", 0)
  973. cvar_toggle = register_cvar("zp_on", "1")
  974.  
  975. // Plugin disabled?
  976. if (!get_pcvar_num(cvar_toggle)) return;
  977. g_pluginenabled = true
  978.  
  979. // Initialize a few dynamically sized arrays (alright, maybe more than just a few...)
  980. model_human = ArrayCreate(32, 1)
  981. model_nemesis = ArrayCreate(32, 1)
  982. model_survivor = ArrayCreate(32, 1)
  983. model_admin_human = ArrayCreate(32, 1)
  984. model_admin_zombie = ArrayCreate(32, 1)
  985. g_modelindex_human = ArrayCreate(1, 1)
  986. g_modelindex_nemesis = ArrayCreate(1, 1)
  987. g_modelindex_survivor = ArrayCreate(1, 1)
  988. g_modelindex_admin_human = ArrayCreate(1, 1)
  989. g_modelindex_admin_zombie = ArrayCreate(1, 1)
  990. sound_win_zombies = ArrayCreate(64, 1)
  991. sound_win_zombies_ismp3 = ArrayCreate(1, 1)
  992. sound_win_humans = ArrayCreate(64, 1)
  993. sound_win_humans_ismp3 = ArrayCreate(1, 1)
  994. sound_win_no_one = ArrayCreate(64, 1)
  995. sound_win_no_one_ismp3 = ArrayCreate(1, 1)
  996. zombie_infect = ArrayCreate(64, 1)
  997. zombie_pain = ArrayCreate(64, 1)
  998. nemesis_pain = ArrayCreate(64, 1)
  999. zombie_die = ArrayCreate(64, 1)
  1000. zombie_fall = ArrayCreate(64, 1)
  1001. zombie_miss_slash = ArrayCreate(64, 1)
  1002. zombie_miss_wall = ArrayCreate(64, 1)
  1003. zombie_hit_normal = ArrayCreate(64, 1)
  1004. zombie_hit_stab = ArrayCreate(64, 1)
  1005. zombie_idle = ArrayCreate(64, 1)
  1006. zombie_idle_last = ArrayCreate(64, 1)
  1007. zombie_madness = ArrayCreate(64, 1)
  1008. sound_nemesis = ArrayCreate(64, 1)
  1009. sound_survivor = ArrayCreate(64, 1)
  1010. sound_swarm = ArrayCreate(64, 1)
  1011. sound_multi = ArrayCreate(64, 1)
  1012. sound_plague = ArrayCreate(64, 1)
  1013. grenade_infect = ArrayCreate(64, 1)
  1014. grenade_infect_player = ArrayCreate(64, 1)
  1015. grenade_fire = ArrayCreate(64, 1)
  1016. grenade_fire_player = ArrayCreate(64, 1)
  1017. grenade_frost = ArrayCreate(64, 1)
  1018. grenade_frost_player = ArrayCreate(64, 1)
  1019. grenade_frost_break = ArrayCreate(64, 1)
  1020. grenade_flare = ArrayCreate(64, 1)
  1021. sound_antidote = ArrayCreate(64, 1)
  1022. sound_thunder = ArrayCreate(64, 1)
  1023. sound_ambience1 = ArrayCreate(64, 1)
  1024. sound_ambience2 = ArrayCreate(64, 1)
  1025. sound_ambience3 = ArrayCreate(64, 1)
  1026. sound_ambience4 = ArrayCreate(64, 1)
  1027. sound_ambience5 = ArrayCreate(64, 1)
  1028. sound_ambience1_duration = ArrayCreate(1, 1)
  1029. sound_ambience2_duration = ArrayCreate(1, 1)
  1030. sound_ambience3_duration = ArrayCreate(1, 1)
  1031. sound_ambience4_duration = ArrayCreate(1, 1)
  1032. sound_ambience5_duration = ArrayCreate(1, 1)
  1033. sound_ambience1_ismp3 = ArrayCreate(1, 1)
  1034. sound_ambience2_ismp3 = ArrayCreate(1, 1)
  1035. sound_ambience3_ismp3 = ArrayCreate(1, 1)
  1036. sound_ambience4_ismp3 = ArrayCreate(1, 1)
  1037. sound_ambience5_ismp3 = ArrayCreate(1, 1)
  1038. g_primary_items = ArrayCreate(32, 1)
  1039. g_secondary_items = ArrayCreate(32, 1)
  1040. g_additional_items = ArrayCreate(32, 1)
  1041. g_primary_weaponids = ArrayCreate(1, 1)
  1042. g_secondary_weaponids = ArrayCreate(1, 1)
  1043. g_extraweapon_names = ArrayCreate(32, 1)
  1044. g_extraweapon_items = ArrayCreate(32, 1)
  1045. g_extraweapon_costs = ArrayCreate(1, 1)
  1046. g_sky_names = ArrayCreate(32, 1)
  1047. lights_thunder = ArrayCreate(32, 1)
  1048. zombie_decals = ArrayCreate(1, 1)
  1049. g_objective_ents = ArrayCreate(32, 1)
  1050. g_extraitem_name = ArrayCreate(32, 1)
  1051. g_extraitem_cost = ArrayCreate(1, 1)
  1052. g_extraitem_team = ArrayCreate(1, 1)
  1053. g_extraitem2_realname = ArrayCreate(32, 1)
  1054. g_extraitem2_name = ArrayCreate(32, 1)
  1055. g_extraitem2_cost = ArrayCreate(1, 1)
  1056. g_extraitem2_team = ArrayCreate(1, 1)
  1057. g_extraitem_new = ArrayCreate(1, 1)
  1058. g_zclass_name = ArrayCreate(32, 1)
  1059. g_zclass_info = ArrayCreate(32, 1)
  1060. g_zclass_modelsstart = ArrayCreate(1, 1)
  1061. g_zclass_modelsend = ArrayCreate(1, 1)
  1062. g_zclass_playermodel = ArrayCreate(32, 1)
  1063. g_zclass_modelindex = ArrayCreate(1, 1)
  1064. g_zclass_clawmodel = ArrayCreate(32, 1)
  1065. g_zclass_hp = ArrayCreate(1, 1)
  1066. g_zclass_spd = ArrayCreate(1, 1)
  1067. g_zclass_grav = ArrayCreate(1, 1)
  1068. g_zclass_kb = ArrayCreate(1, 1)
  1069. g_zclass2_realname = ArrayCreate(32, 1)
  1070. g_zclass2_name = ArrayCreate(32, 1)
  1071. g_zclass2_info = ArrayCreate(32, 1)
  1072. g_zclass2_modelsstart = ArrayCreate(1, 1)
  1073. g_zclass2_modelsend = ArrayCreate(1, 1)
  1074. g_zclass2_playermodel = ArrayCreate(32, 1)
  1075. g_zclass2_modelindex = ArrayCreate(1, 1)
  1076. g_zclass2_clawmodel = ArrayCreate(32, 1)
  1077. g_zclass2_hp = ArrayCreate(1, 1)
  1078. g_zclass2_spd = ArrayCreate(1, 1)
  1079. g_zclass2_grav = ArrayCreate(1, 1)
  1080. g_zclass2_kb = ArrayCreate(1, 1)
  1081. g_zclass_new = ArrayCreate(1, 1)
  1082.  
  1083. // Allow registering stuff now
  1084. g_arrays_created = true
  1085.  
  1086. // Load customization data
  1087. load_customization_from_files()
  1088.  
  1089. new i, buffer[100]
  1090.  
  1091. // Load up the hard coded extra items
  1092. native_register_extra_item2("NightVision", g_extra_costs2[EXTRA_NVISION], ZP_TEAM_HUMAN)
  1093. native_register_extra_item2("T-Virus Antidote", g_extra_costs2[EXTRA_ANTIDOTE], ZP_TEAM_ZOMBIE)
  1094. native_register_extra_item2("Zombie Madness", g_extra_costs2[EXTRA_MADNESS], ZP_TEAM_ZOMBIE)
  1095. native_register_extra_item2("Infection Bomb", g_extra_costs2[EXTRA_INFBOMB], ZP_TEAM_ZOMBIE)
  1096.  
  1097. // Extra weapons
  1098. for (i = 0; i < ArraySize(g_extraweapon_names); i++)
  1099. {
  1100. ArrayGetString(g_extraweapon_names, i, buffer, charsmax(buffer))
  1101. native_register_extra_item2(buffer, ArrayGetCell(g_extraweapon_costs, i), ZP_TEAM_HUMAN)
  1102. }
  1103.  
  1104. // Custom player models
  1105. for (i = 0; i < ArraySize(model_human); i++)
  1106. {
  1107. ArrayGetString(model_human, i, buffer, charsmax(buffer))
  1108. format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
  1109. ArrayPushCell(g_modelindex_human, engfunc(EngFunc_PrecacheModel, buffer))
  1110. if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
  1111. if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
  1112. // Precache modelT.mdl files too
  1113. copy(buffer[strlen(buffer)-4], charsmax(buffer) - (strlen(buffer)-4), "T.mdl")
  1114. if (file_exists(buffer)) engfunc(EngFunc_PrecacheModel, buffer)
  1115. }
  1116. for (i = 0; i < ArraySize(model_nemesis); i++)
  1117. {
  1118. ArrayGetString(model_nemesis, i, buffer, charsmax(buffer))
  1119. format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
  1120. ArrayPushCell(g_modelindex_nemesis, engfunc(EngFunc_PrecacheModel, buffer))
  1121. if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
  1122. if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
  1123. // Precache modelT.mdl files too
  1124. copy(buffer[strlen(buffer)-4], charsmax(buffer) - (strlen(buffer)-4), "T.mdl")
  1125. if (file_exists(buffer)) engfunc(EngFunc_PrecacheModel, buffer)
  1126. }
  1127. for (i = 0; i < ArraySize(model_survivor); i++)
  1128. {
  1129. ArrayGetString(model_survivor, i, buffer, charsmax(buffer))
  1130. format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
  1131. ArrayPushCell(g_modelindex_survivor, engfunc(EngFunc_PrecacheModel, buffer))
  1132. if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
  1133. if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
  1134. // Precache modelT.mdl files too
  1135. copy(buffer[strlen(buffer)-4], charsmax(buffer) - (strlen(buffer)-4), "T.mdl")
  1136. if (file_exists(buffer)) engfunc(EngFunc_PrecacheModel, buffer)
  1137. }
  1138. for (i = 0; i < ArraySize(model_admin_zombie); i++)
  1139. {
  1140. ArrayGetString(model_admin_zombie, i, buffer, charsmax(buffer))
  1141. format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
  1142. ArrayPushCell(g_modelindex_admin_zombie, engfunc(EngFunc_PrecacheModel, buffer))
  1143. if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
  1144. if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
  1145. // Precache modelT.mdl files too
  1146. copy(buffer[strlen(buffer)-4], charsmax(buffer) - (strlen(buffer)-4), "T.mdl")
  1147. if (file_exists(buffer)) engfunc(EngFunc_PrecacheModel, buffer)
  1148. }
  1149. for (i = 0; i < ArraySize(model_admin_human); i++)
  1150. {
  1151. ArrayGetString(model_admin_human, i, buffer, charsmax(buffer))
  1152. format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
  1153. ArrayPushCell(g_modelindex_admin_human, engfunc(EngFunc_PrecacheModel, buffer))
  1154. if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
  1155. if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
  1156. // Precache modelT.mdl files too
  1157. copy(buffer[strlen(buffer)-4], charsmax(buffer) - (strlen(buffer)-4), "T.mdl")
  1158. if (file_exists(buffer)) engfunc(EngFunc_PrecacheModel, buffer)
  1159. }
  1160.  
  1161. // Custom weapon models
  1162. engfunc(EngFunc_PrecacheModel, model_vknife_human)
  1163. engfunc(EngFunc_PrecacheModel, model_vknife_nemesis)
  1164. engfunc(EngFunc_PrecacheModel, model_vweapon_survivor)
  1165. engfunc(EngFunc_PrecacheModel, model_grenade_infect)
  1166. engfunc(EngFunc_PrecacheModel, model_grenade_fire)
  1167. engfunc(EngFunc_PrecacheModel, model_grenade_frost)
  1168. engfunc(EngFunc_PrecacheModel, model_grenade_flare)
  1169. engfunc(EngFunc_PrecacheModel, model_vknife_admin_human)
  1170. engfunc(EngFunc_PrecacheModel, model_vknife_admin_zombie)
  1171.  
  1172. // Custom sprites for grenades
  1173. g_trailSpr = engfunc(EngFunc_PrecacheModel, sprite_grenade_trail)
  1174. g_exploSpr = engfunc(EngFunc_PrecacheModel, sprite_grenade_ring)
  1175. g_flameSpr = engfunc(EngFunc_PrecacheModel, sprite_grenade_fire)
  1176. g_smokeSpr = engfunc(EngFunc_PrecacheModel, sprite_grenade_smoke)
  1177. g_glassSpr = engfunc(EngFunc_PrecacheModel, sprite_grenade_glass)
  1178.  
  1179. // Custom sounds
  1180. for (i = 0; i < ArraySize(sound_win_zombies); i++)
  1181. {
  1182. ArrayGetString(sound_win_zombies, i, buffer, charsmax(buffer))
  1183. if (ArrayGetCell(sound_win_zombies_ismp3, i))
  1184. {
  1185. format(buffer, charsmax(buffer), "sound/%s", buffer)
  1186. engfunc(EngFunc_PrecacheGeneric, buffer)
  1187. }
  1188. else
  1189. {
  1190. engfunc(EngFunc_PrecacheSound, buffer)
  1191. }
  1192. }
  1193. for (i = 0; i < ArraySize(sound_win_humans); i++)
  1194. {
  1195. ArrayGetString(sound_win_humans, i, buffer, charsmax(buffer))
  1196. if (ArrayGetCell(sound_win_humans_ismp3, i))
  1197. {
  1198. format(buffer, charsmax(buffer), "sound/%s", buffer)
  1199. engfunc(EngFunc_PrecacheGeneric, buffer)
  1200. }
  1201. else
  1202. {
  1203. engfunc(EngFunc_PrecacheSound, buffer)
  1204. }
  1205. }
  1206. for (i = 0; i < ArraySize(sound_win_no_one); i++)
  1207. {
  1208. ArrayGetString(sound_win_no_one, i, buffer, charsmax(buffer))
  1209. if (ArrayGetCell(sound_win_no_one_ismp3, i))
  1210. {
  1211. format(buffer, charsmax(buffer), "sound/%s", buffer)
  1212. engfunc(EngFunc_PrecacheGeneric, buffer)
  1213. }
  1214. else
  1215. {
  1216. engfunc(EngFunc_PrecacheSound, buffer)
  1217. }
  1218. }
  1219. for (i = 0; i < ArraySize(zombie_infect); i++)
  1220. {
  1221. ArrayGetString(zombie_infect, i, buffer, charsmax(buffer))
  1222. engfunc(EngFunc_PrecacheSound, buffer)
  1223. }
  1224. for (i = 0; i < ArraySize(zombie_pain); i++)
  1225. {
  1226. ArrayGetString(zombie_pain, i, buffer, charsmax(buffer))
  1227. engfunc(EngFunc_PrecacheSound, buffer)
  1228. }
  1229. for (i = 0; i < ArraySize(nemesis_pain); i++)
  1230. {
  1231. ArrayGetString(nemesis_pain, i, buffer, charsmax(buffer))
  1232. engfunc(EngFunc_PrecacheSound, buffer)
  1233. }
  1234. for (i = 0; i < ArraySize(zombie_die); i++)
  1235. {
  1236. ArrayGetString(zombie_die, i, buffer, charsmax(buffer))
  1237. engfunc(EngFunc_PrecacheSound, buffer)
  1238. }
  1239. for (i = 0; i < ArraySize(zombie_fall); i++)
  1240. {
  1241. ArrayGetString(zombie_fall, i, buffer, charsmax(buffer))
  1242. engfunc(EngFunc_PrecacheSound, buffer)
  1243. }
  1244. for (i = 0; i < ArraySize(zombie_miss_slash); i++)
  1245. {
  1246. ArrayGetString(zombie_miss_slash, i, buffer, charsmax(buffer))
  1247. engfunc(EngFunc_PrecacheSound, buffer)
  1248. }
  1249. for (i = 0; i < ArraySize(zombie_miss_wall); i++)
  1250. {
  1251. ArrayGetString(zombie_miss_wall, i, buffer, charsmax(buffer))
  1252. engfunc(EngFunc_PrecacheSound, buffer)
  1253. }
  1254. for (i = 0; i < ArraySize(zombie_hit_normal); i++)
  1255. {
  1256. ArrayGetString(zombie_hit_normal, i, buffer, charsmax(buffer))
  1257. engfunc(EngFunc_PrecacheSound, buffer)
  1258. }
  1259. for (i = 0; i < ArraySize(zombie_hit_stab); i++)
  1260. {
  1261. ArrayGetString(zombie_hit_stab, i, buffer, charsmax(buffer))
  1262. engfunc(EngFunc_PrecacheSound, buffer)
  1263. }
  1264. for (i = 0; i < ArraySize(zombie_idle); i++)
  1265. {
  1266. ArrayGetString(zombie_idle, i, buffer, charsmax(buffer))
  1267. engfunc(EngFunc_PrecacheSound, buffer)
  1268. }
  1269. for (i = 0; i < ArraySize(zombie_idle_last); i++)
  1270. {
  1271. ArrayGetString(zombie_idle_last, i, buffer, charsmax(buffer))
  1272. engfunc(EngFunc_PrecacheSound, buffer)
  1273. }
  1274. for (i = 0; i < ArraySize(zombie_madness); i++)
  1275. {
  1276. ArrayGetString(zombie_madness, i, buffer, charsmax(buffer))
  1277. engfunc(EngFunc_PrecacheSound, buffer)
  1278. }
  1279. for (i = 0; i < ArraySize(sound_nemesis); i++)
  1280. {
  1281. ArrayGetString(sound_nemesis, i, buffer, charsmax(buffer))
  1282. engfunc(EngFunc_PrecacheSound, buffer)
  1283. }
  1284. for (i = 0; i < ArraySize(sound_survivor); i++)
  1285. {
  1286. ArrayGetString(sound_survivor, i, buffer, charsmax(buffer))
  1287. engfunc(EngFunc_PrecacheSound, buffer)
  1288. }
  1289. for (i = 0; i < ArraySize(sound_swarm); i++)
  1290. {
  1291. ArrayGetString(sound_swarm, i, buffer, charsmax(buffer))
  1292. engfunc(EngFunc_PrecacheSound, buffer)
  1293. }
  1294. for (i = 0; i < ArraySize(sound_multi); i++)
  1295. {
  1296. ArrayGetString(sound_multi, i, buffer, charsmax(buffer))
  1297. engfunc(EngFunc_PrecacheSound, buffer)
  1298. }
  1299. for (i = 0; i < ArraySize(sound_plague); i++)
  1300. {
  1301. ArrayGetString(sound_plague, i, buffer, charsmax(buffer))
  1302. engfunc(EngFunc_PrecacheSound, buffer)
  1303. }
  1304. for (i = 0; i < ArraySize(grenade_infect); i++)
  1305. {
  1306. ArrayGetString(grenade_infect, i, buffer, charsmax(buffer))
  1307. engfunc(EngFunc_PrecacheSound, buffer)
  1308. }
  1309. for (i = 0; i < ArraySize(grenade_infect_player); i++)
  1310. {
  1311. ArrayGetString(grenade_infect_player, i, buffer, charsmax(buffer))
  1312. engfunc(EngFunc_PrecacheSound, buffer)
  1313. }
  1314. for (i = 0; i < ArraySize(grenade_fire); i++)
  1315. {
  1316. ArrayGetString(grenade_fire, i, buffer, charsmax(buffer))
  1317. engfunc(EngFunc_PrecacheSound, buffer)
  1318. }
  1319. for (i = 0; i < ArraySize(grenade_fire_player); i++)
  1320. {
  1321. ArrayGetString(grenade_fire_player, i, buffer, charsmax(buffer))
  1322. engfunc(EngFunc_PrecacheSound, buffer)
  1323. }
  1324. for (i = 0; i < ArraySize(grenade_frost); i++)
  1325. {
  1326. ArrayGetString(grenade_frost, i, buffer, charsmax(buffer))
  1327. engfunc(EngFunc_PrecacheSound, buffer)
  1328. }
  1329. for (i = 0; i < ArraySize(grenade_frost_player); i++)
  1330. {
  1331. ArrayGetString(grenade_frost_player, i, buffer, charsmax(buffer))
  1332. engfunc(EngFunc_PrecacheSound, buffer)
  1333. }
  1334. for (i = 0; i < ArraySize(grenade_frost_break); i++)
  1335. {
  1336. ArrayGetString(grenade_frost_break, i, buffer, charsmax(buffer))
  1337. engfunc(EngFunc_PrecacheSound, buffer)
  1338. }
  1339. for (i = 0; i < ArraySize(grenade_flare); i++)
  1340. {
  1341. ArrayGetString(grenade_flare, i, buffer, charsmax(buffer))
  1342. engfunc(EngFunc_PrecacheSound, buffer)
  1343. }
  1344. for (i = 0; i < ArraySize(sound_antidote); i++)
  1345. {
  1346. ArrayGetString(sound_antidote, i, buffer, charsmax(buffer))
  1347. engfunc(EngFunc_PrecacheSound, buffer)
  1348. }
  1349. for (i = 0; i < ArraySize(sound_thunder); i++)
  1350. {
  1351. ArrayGetString(sound_thunder, i, buffer, charsmax(buffer))
  1352. engfunc(EngFunc_PrecacheSound, buffer)
  1353. }
  1354.  
  1355. // Ambience Sounds
  1356. if (g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION])
  1357. {
  1358. for (i = 0; i < ArraySize(sound_ambience1); i++)
  1359. {
  1360. ArrayGetString(sound_ambience1, i, buffer, charsmax(buffer))
  1361.  
  1362. if (ArrayGetCell(sound_ambience1_ismp3, i))
  1363. {
  1364. format(buffer, charsmax(buffer), "sound/%s", buffer)
  1365. engfunc(EngFunc_PrecacheGeneric, buffer)
  1366. }
  1367. else
  1368. {
  1369. engfunc(EngFunc_PrecacheSound, buffer)
  1370. }
  1371. }
  1372. }
  1373. if (g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS])
  1374. {
  1375. for (i = 0; i < ArraySize(sound_ambience2); i++)
  1376. {
  1377. ArrayGetString(sound_ambience2, i, buffer, charsmax(buffer))
  1378.  
  1379. if (ArrayGetCell(sound_ambience2_ismp3, i))
  1380. {
  1381. format(buffer, charsmax(buffer), "sound/%s", buffer)
  1382. engfunc(EngFunc_PrecacheGeneric, buffer)
  1383. }
  1384. else
  1385. {
  1386. engfunc(EngFunc_PrecacheSound, buffer)
  1387. }
  1388. }
  1389. }
  1390. if (g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR])
  1391. {
  1392. for (i = 0; i < ArraySize(sound_ambience3); i++)
  1393. {
  1394. ArrayGetString(sound_ambience3, i, buffer, charsmax(buffer))
  1395.  
  1396. if (ArrayGetCell(sound_ambience3_ismp3, i))
  1397. {
  1398. format(buffer, charsmax(buffer), "sound/%s", buffer)
  1399. engfunc(EngFunc_PrecacheGeneric, buffer)
  1400. }
  1401. else
  1402. {
  1403. engfunc(EngFunc_PrecacheSound, buffer)
  1404. }
  1405. }
  1406. }
  1407. if (g_ambience_sounds[AMBIENCE_SOUNDS_SWARM])
  1408. {
  1409. for (i = 0; i < ArraySize(sound_ambience4); i++)
  1410. {
  1411. ArrayGetString(sound_ambience4, i, buffer, charsmax(buffer))
  1412.  
  1413. if (ArrayGetCell(sound_ambience4_ismp3, i))
  1414. {
  1415. format(buffer, charsmax(buffer), "sound/%s", buffer)
  1416. engfunc(EngFunc_PrecacheGeneric, buffer)
  1417. }
  1418. else
  1419. {
  1420. engfunc(EngFunc_PrecacheSound, buffer)
  1421. }
  1422. }
  1423. }
  1424. if (g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE])
  1425. {
  1426. for (i = 0; i < ArraySize(sound_ambience5); i++)
  1427. {
  1428. ArrayGetString(sound_ambience5, i, buffer, charsmax(buffer))
  1429.  
  1430. if (ArrayGetCell(sound_ambience5_ismp3, i))
  1431. {
  1432. format(buffer, charsmax(buffer), "sound/%s", buffer)
  1433. engfunc(EngFunc_PrecacheGeneric, buffer)
  1434. }
  1435. else
  1436. {
  1437. engfunc(EngFunc_PrecacheSound, buffer)
  1438. }
  1439. }
  1440. }
  1441.  
  1442. // CS sounds (just in case)
  1443. engfunc(EngFunc_PrecacheSound, sound_flashlight)
  1444. engfunc(EngFunc_PrecacheSound, sound_buyammo)
  1445. engfunc(EngFunc_PrecacheSound, sound_armorhit)
  1446.  
  1447. new ent
  1448.  
  1449. // Fake Hostage (to force round ending)
  1450. ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "hostage_entity"))
  1451. if (pev_valid(ent))
  1452. {
  1453. engfunc(EngFunc_SetOrigin, ent, Float:{8192.0,8192.0,8192.0})
  1454. dllfunc(DLLFunc_Spawn, ent)
  1455. }
  1456.  
  1457. // Weather/ambience effects
  1458. if (g_ambience_fog)
  1459. {
  1460. ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "env_fog"))
  1461. if (pev_valid(ent))
  1462. {
  1463. fm_set_kvd(ent, "density", g_fog_density, "env_fog")
  1464. fm_set_kvd(ent, "rendercolor", g_fog_color, "env_fog")
  1465. }
  1466. }
  1467. if (g_ambience_rain) engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "env_rain"))
  1468. if (g_ambience_snow) engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "env_snow"))
  1469.  
  1470. // Custom buyzone for all players
  1471. g_buyzone_ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "func_buyzone"))
  1472. if (pev_valid(g_buyzone_ent))
  1473. {
  1474. dllfunc(DLLFunc_Spawn, g_buyzone_ent)
  1475. set_pev(g_buyzone_ent, pev_solid, SOLID_NOT)
  1476. }
  1477.  
  1478. // Prevent some entities from spawning
  1479. g_fwSpawn = register_forward(FM_Spawn, "fw_Spawn")
  1480.  
  1481. // Prevent hostage sounds from being precached
  1482. g_fwPrecacheSound = register_forward(FM_PrecacheSound, "fw_PrecacheSound")
  1483. }
  1484.  
  1485. public plugin_init()
  1486. {
  1487. // Plugin disabled?
  1488. if (!g_pluginenabled) return;
  1489.  
  1490. // No zombie classes?
  1491. if (!g_zclass_i) set_fail_state("No zombie classes loaded!")
  1492.  
  1493. // Language files
  1494. register_dictionary("zombie_plague.txt")
  1495.  
  1496. // Events
  1497. register_event("HLTV", "event_round_start", "a", "1=0", "2=0")
  1498. register_logevent("logevent_round_start",2, "1=Round_Start")
  1499. register_logevent("logevent_round_end", 2, "1=Round_End")
  1500. register_event("AmmoX", "event_ammo_x", "be")
  1501. if (g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION] || g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS] || g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR] || g_ambience_sounds[AMBIENCE_SOUNDS_SWARM] || g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE])
  1502. register_event("30", "event_intermission", "a")
  1503.  
  1504. // HAM Forwards
  1505. RegisterHam(Ham_Spawn, "player", "fw_PlayerSpawn_Post", 1)
  1506. RegisterHam(Ham_Killed, "player", "fw_PlayerKilled")
  1507. RegisterHam(Ham_Killed, "player", "fw_PlayerKilled_Post", 1)
  1508. RegisterHam(Ham_TakeDamage, "player", "fw_TakeDamage")
  1509. RegisterHam(Ham_TakeDamage, "player", "fw_TakeDamage_Post", 1)
  1510. RegisterHam(Ham_TraceAttack, "player", "fw_TraceAttack")
  1511. RegisterHam(Ham_Player_ResetMaxSpeed, "player", "fw_ResetMaxSpeed_Post", 1)
  1512. RegisterHam(Ham_Use, "func_tank", "fw_UseStationary")
  1513. RegisterHam(Ham_Use, "func_tankmortar", "fw_UseStationary")
  1514. RegisterHam(Ham_Use, "func_tankrocket", "fw_UseStationary")
  1515. RegisterHam(Ham_Use, "func_tanklaser", "fw_UseStationary")
  1516. RegisterHam(Ham_Use, "func_tank", "fw_UseStationary_Post", 1)
  1517. RegisterHam(Ham_Use, "func_tankmortar", "fw_UseStationary_Post", 1)
  1518. RegisterHam(Ham_Use, "func_tankrocket", "fw_UseStationary_Post", 1)
  1519. RegisterHam(Ham_Use, "func_tanklaser", "fw_UseStationary_Post", 1)
  1520. RegisterHam(Ham_Use, "func_pushable", "fw_UsePushable")
  1521. RegisterHam(Ham_Touch, "weaponbox", "fw_TouchWeapon")
  1522. RegisterHam(Ham_Touch, "armoury_entity", "fw_TouchWeapon")
  1523. RegisterHam(Ham_Touch, "weapon_shield", "fw_TouchWeapon")
  1524. RegisterHam(Ham_AddPlayerItem, "player", "fw_AddPlayerItem")
  1525. for (new i = 1; i < sizeof WEAPONENTNAMES; i++)
  1526. if (WEAPONENTNAMES[i][0]) RegisterHam(Ham_Item_Deploy, WEAPONENTNAMES[i], "fw_Item_Deploy_Post", 1)
  1527.  
  1528. // FM Forwards
  1529. register_forward(FM_ClientDisconnect, "fw_ClientDisconnect")
  1530. register_forward(FM_ClientDisconnect, "fw_ClientDisconnect_Post", 1)
  1531. register_forward(FM_ClientKill, "fw_ClientKill")
  1532. register_forward(FM_EmitSound, "fw_EmitSound")
  1533. if (!g_handle_models_on_separate_ent) register_forward(FM_SetClientKeyValue, "fw_SetClientKeyValue")
  1534. register_forward(FM_ClientUserInfoChanged, "fw_ClientUserInfoChanged")
  1535. register_forward(FM_GetGameDescription, "fw_GetGameDescription")
  1536. register_forward(FM_SetModel, "fw_SetModel")
  1537. RegisterHam(Ham_Think, "grenade", "fw_ThinkGrenade")
  1538. register_forward(FM_CmdStart, "fw_CmdStart")
  1539. register_forward(FM_PlayerPreThink, "fw_PlayerPreThink")
  1540. unregister_forward(FM_Spawn, g_fwSpawn)
  1541. unregister_forward(FM_PrecacheSound, g_fwPrecacheSound)
  1542.  
  1543. // Client commands
  1544. register_clcmd("say zpmenu", "clcmd_saymenu")
  1545. register_clcmd("say /zpmenu", "clcmd_saymenu")
  1546. register_clcmd("say unstuck", "clcmd_sayunstuck")
  1547. register_clcmd("say /unstuck", "clcmd_sayunstuck")
  1548. register_clcmd("nightvision", "clcmd_nightvision")
  1549. register_clcmd("drop", "clcmd_drop")
  1550. register_clcmd("buyammo1", "clcmd_buyammo")
  1551. register_clcmd("buyammo2", "clcmd_buyammo")
  1552. register_clcmd("chooseteam", "clcmd_changeteam")
  1553. register_clcmd("jointeam", "clcmd_changeteam")
  1554.  
  1555. // Menus
  1556. register_menu("Game Menu", KEYSMENU, "menu_game")
  1557. register_menu("Buy Menu 1", KEYSMENU, "menu_buy1")
  1558. register_menu("Buy Menu 2", KEYSMENU, "menu_buy2")
  1559. register_menu("Mod Info", KEYSMENU, "menu_info")
  1560. register_menu("Admin Menu", KEYSMENU, "menu_admin")
  1561.  
  1562. // CS Buy Menus (to prevent zombies/survivor from buying)
  1563. register_menucmd(register_menuid("#Buy", 1), 511, "menu_cs_buy")
  1564. register_menucmd(register_menuid("BuyPistol", 1), 511, "menu_cs_buy")
  1565. register_menucmd(register_menuid("BuyShotgun", 1), 511, "menu_cs_buy")
  1566. register_menucmd(register_menuid("BuySub", 1), 511, "menu_cs_buy")
  1567. register_menucmd(register_menuid("BuyRifle", 1), 511, "menu_cs_buy")
  1568. register_menucmd(register_menuid("BuyMachine", 1), 511, "menu_cs_buy")
  1569. register_menucmd(register_menuid("BuyItem", 1), 511, "menu_cs_buy")
  1570. register_menucmd(-28, 511, "menu_cs_buy")
  1571. register_menucmd(-29, 511, "menu_cs_buy")
  1572. register_menucmd(-30, 511, "menu_cs_buy")
  1573. register_menucmd(-32, 511, "menu_cs_buy")
  1574. register_menucmd(-31, 511, "menu_cs_buy")
  1575. register_menucmd(-33, 511, "menu_cs_buy")
  1576. register_menucmd(-34, 511, "menu_cs_buy")
  1577.  
  1578. // Admin commands
  1579. register_concmd("zp_zombie", "cmd_zombie", _, "<target> - Turn someone into a Zombie", 0)
  1580. register_concmd("zp_human", "cmd_human", _, "<target> - Turn someone back to Human", 0)
  1581. register_concmd("zp_nemesis", "cmd_nemesis", _, "<target> - Turn someone into a Nemesis", 0)
  1582. register_concmd("zp_survivor", "cmd_survivor", _, "<target> - Turn someone into a Survivor", 0)
  1583. register_concmd("zp_respawn", "cmd_respawn", _, "<target> - Respawn someone", 0)
  1584. register_concmd("zp_swarm", "cmd_swarm", _, " - Start Swarm Mode", 0)
  1585. register_concmd("zp_multi", "cmd_multi", _, " - Start Multi Infection", 0)
  1586. register_concmd("zp_plague", "cmd_plague", _, " - Start Plague Mode", 0)
  1587.  
  1588. // Message IDs
  1589. g_msgScoreInfo = get_user_msgid("ScoreInfo")
  1590. g_msgTeamInfo = get_user_msgid("TeamInfo")
  1591. g_msgDeathMsg = get_user_msgid("DeathMsg")
  1592. g_msgScoreAttrib = get_user_msgid("ScoreAttrib")
  1593. g_msgSetFOV = get_user_msgid("SetFOV")
  1594. g_msgScreenFade = get_user_msgid("ScreenFade")
  1595. g_msgScreenShake = get_user_msgid("ScreenShake")
  1596. g_msgNVGToggle = get_user_msgid("NVGToggle")
  1597. g_msgFlashlight = get_user_msgid("Flashlight")
  1598. g_msgFlashBat = get_user_msgid("FlashBat")
  1599. g_msgAmmoPickup = get_user_msgid("AmmoPickup")
  1600. g_msgDamage = get_user_msgid("Damage")
  1601. g_msgHideWeapon = get_user_msgid("HideWeapon")
  1602. g_msgCrosshair = get_user_msgid("Crosshair")
  1603. g_msgSayText = get_user_msgid("SayText")
  1604. g_msgCurWeapon = get_user_msgid("CurWeapon")
  1605.  
  1606. // Message hooks
  1607. register_message(g_msgCurWeapon, "message_cur_weapon")
  1608. register_message(get_user_msgid("Money"), "message_money")
  1609. register_message(get_user_msgid("Health"), "message_health")
  1610. register_message(g_msgFlashBat, "message_flashbat")
  1611. register_message(g_msgScreenFade, "message_screenfade")
  1612. register_message(g_msgNVGToggle, "message_nvgtoggle")
  1613. if (g_handle_models_on_separate_ent) register_message(get_user_msgid("ClCorpse"), "message_clcorpse")
  1614. register_message(get_user_msgid("WeapPickup"), "message_weappickup")
  1615. register_message(g_msgAmmoPickup, "message_ammopickup")
  1616. register_message(get_user_msgid("Scenario"), "message_scenario")
  1617. register_message(get_user_msgid("HostagePos"), "message_hostagepos")
  1618. register_message(get_user_msgid("TextMsg"), "message_textmsg")
  1619. register_message(get_user_msgid("SendAudio"), "message_sendaudio")
  1620. register_message(get_user_msgid("TeamScore"), "message_teamscore")
  1621. register_message(g_msgTeamInfo, "message_teaminfo")
  1622.  
  1623. // CVARS - General Purpose
  1624. cvar_warmup = register_cvar("zp_delay", "10")
  1625. cvar_lighting = register_cvar("zp_lighting", "a")
  1626. cvar_thunder = register_cvar("zp_thunderclap", "90")
  1627. cvar_triggered = register_cvar("zp_triggered_lights", "1")
  1628. cvar_removedoors = register_cvar("zp_remove_doors", "0")
  1629. cvar_blockpushables = register_cvar("zp_blockuse_pushables", "1")
  1630. cvar_blocksuicide = register_cvar("zp_block_suicide", "1")
  1631. cvar_randspawn = register_cvar("zp_random_spawn", "1")
  1632. cvar_respawnworldspawnkill = register_cvar("zp_respawn_on_worldspawn_kill", "1")
  1633. cvar_removedropped = register_cvar("zp_remove_dropped", "0")
  1634. cvar_removemoney = register_cvar("zp_remove_money", "1")
  1635. cvar_buycustom = register_cvar("zp_buy_custom", "1")
  1636. cvar_buyzonetime = register_cvar("zp_buyzone_time", "0.0")
  1637. cvar_randweapons = register_cvar("zp_random_weapons", "0")
  1638. cvar_adminmodelshuman = register_cvar("zp_admin_models_human", "1")
  1639. cvar_adminknifemodelshuman = register_cvar("zp_admin_knife_models_human", "0")
  1640. cvar_adminmodelszombie = register_cvar("zp_admin_models_zombie", "1")
  1641. cvar_adminknifemodelszombie = register_cvar("zp_admin_knife_models_zombie", "0")
  1642. cvar_zclasses = register_cvar("zp_zombie_classes", "1")
  1643. cvar_statssave = register_cvar("zp_stats_save", "1")
  1644. cvar_startammopacks = register_cvar("zp_starting_ammo_packs", "5")
  1645. cvar_preventconsecutive = register_cvar("zp_prevent_consecutive_modes", "1")
  1646. cvar_keephealthondisconnect = register_cvar("zp_keep_health_on_disconnect", "1")
  1647. cvar_huddisplay = register_cvar("zp_hud_display", "1")
  1648.  
  1649. // CVARS - Deathmatch
  1650. cvar_deathmatch = register_cvar("zp_deathmatch", "0")
  1651. cvar_spawndelay = register_cvar("zp_spawn_delay", "5")
  1652. cvar_spawnprotection = register_cvar("zp_spawn_protection", "5")
  1653. cvar_respawnonsuicide = register_cvar("zp_respawn_on_suicide", "0")
  1654. cvar_respawnafterlast = register_cvar("zp_respawn_after_last_human", "1")
  1655. cvar_allowrespawninfection = register_cvar("zp_infection_allow_respawn", "1")
  1656. cvar_allowrespawnnem = register_cvar("zp_nem_allow_respawn", "0")
  1657. cvar_allowrespawnsurv = register_cvar("zp_surv_allow_respawn", "0")
  1658. cvar_allowrespawnswarm = register_cvar("zp_swarm_allow_respawn", "0")
  1659. cvar_allowrespawnplague = register_cvar("zp_plague_allow_respawn", "0")
  1660. cvar_respawnzomb = register_cvar("zp_respawn_zombies", "1")
  1661. cvar_respawnhum = register_cvar("zp_respawn_humans", "1")
  1662. cvar_respawnnem = register_cvar("zp_respawn_nemesis", "1")
  1663. cvar_respawnsurv = register_cvar("zp_respawn_survivors", "1")
  1664.  
  1665. // CVARS - Extra Items
  1666. cvar_extraitems = register_cvar("zp_extra_items", "1")
  1667. cvar_extraweapons = register_cvar("zp_extra_weapons", "1")
  1668. cvar_extranvision = register_cvar("zp_extra_nvision", "1")
  1669. cvar_extraantidote = register_cvar("zp_extra_antidote", "1")
  1670. cvar_antidotelimit = register_cvar("zp_extra_antidote_limit", "999")
  1671. cvar_extramadness = register_cvar("zp_extra_madness", "1")
  1672. cvar_madnesslimit = register_cvar("zp_extra_madness_limit", "999")
  1673. cvar_madnessduration = register_cvar("zp_extra_madness_duration", "5.0")
  1674. cvar_extrainfbomb = register_cvar("zp_extra_infbomb", "1")
  1675. cvar_infbomblimit = register_cvar("zp_extra_infbomb_limit", "999")
  1676.  
  1677. // CVARS - Flashlight and Nightvision
  1678. cvar_nvggive = register_cvar("zp_nvg_give", "1")
  1679. cvar_customnvg = register_cvar("zp_nvg_custom", "1")
  1680. cvar_nvgsize = register_cvar("zp_nvg_size", "80")
  1681. cvar_nvgcolor[0] = register_cvar("zp_nvg_color_R", "0")
  1682. cvar_nvgcolor[1] = register_cvar("zp_nvg_color_G", "150")
  1683. cvar_nvgcolor[2] = register_cvar("zp_nvg_color_B", "0")
  1684. cvar_humnvgcolor[0] = register_cvar("zp_nvg_hum_color_R", "0")
  1685. cvar_humnvgcolor[1] = register_cvar("zp_nvg_hum_color_G", "150")
  1686. cvar_humnvgcolor[2] = register_cvar("zp_nvg_hum_color_B", "0")
  1687. cvar_nemnvgcolor[0] = register_cvar("zp_nvg_nem_color_R", "150")
  1688. cvar_nemnvgcolor[1] = register_cvar("zp_nvg_nem_color_G", "0")
  1689. cvar_nemnvgcolor[2] = register_cvar("zp_nvg_nem_color_B", "0")
  1690. cvar_customflash = register_cvar("zp_flash_custom", "0")
  1691. cvar_flashsize = register_cvar("zp_flash_size", "10")
  1692. cvar_flashdrain = register_cvar("zp_flash_drain", "1")
  1693. cvar_flashcharge = register_cvar("zp_flash_charge", "5")
  1694. cvar_flashdist = register_cvar("zp_flash_distance", "1000")
  1695. cvar_flashcolor[0] = register_cvar("zp_flash_color_R", "100")
  1696. cvar_flashcolor[1] = register_cvar("zp_flash_color_G", "100")
  1697. cvar_flashcolor[2] = register_cvar("zp_flash_color_B", "100")
  1698. cvar_flashshowall = register_cvar("zp_flash_show_all", "1")
  1699.  
  1700. // CVARS - Knockback
  1701. cvar_knockback = register_cvar("zp_knockback", "0")
  1702. cvar_knockbackdamage = register_cvar("zp_knockback_damage", "1")
  1703. cvar_knockbackpower = register_cvar("zp_knockback_power", "1")
  1704. cvar_knockbackzvel = register_cvar("zp_knockback_zvel", "0")
  1705. cvar_knockbackducking = register_cvar("zp_knockback_ducking", "0.25")
  1706. cvar_knockbackdist = register_cvar("zp_knockback_distance", "500")
  1707. cvar_nemknockback = register_cvar("zp_knockback_nemesis", "0.25")
  1708.  
  1709. // CVARS - Leap
  1710. cvar_leapzombies = register_cvar("zp_leap_zombies", "0")
  1711. cvar_leapzombiesforce = register_cvar("zp_leap_zombies_force", "500")
  1712. cvar_leapzombiesheight = register_cvar("zp_leap_zombies_height", "300")
  1713. cvar_leapzombiescooldown = register_cvar("zp_leap_zombies_cooldown", "5.0")
  1714. cvar_leapnemesis = register_cvar("zp_leap_nemesis", "1")
  1715. cvar_leapnemesisforce = register_cvar("zp_leap_nemesis_force", "500")
  1716. cvar_leapnemesisheight = register_cvar("zp_leap_nemesis_height", "300")
  1717. cvar_leapnemesiscooldown = register_cvar("zp_leap_nemesis_cooldown", "5.0")
  1718. cvar_leapsurvivor = register_cvar("zp_leap_survivor", "0")
  1719. cvar_leapsurvivorforce = register_cvar("zp_leap_survivor_force", "500")
  1720. cvar_leapsurvivorheight = register_cvar("zp_leap_survivor_height", "300")
  1721. cvar_leapsurvivorcooldown = register_cvar("zp_leap_survivor_cooldown", "5.0")
  1722.  
  1723. // CVARS - Humans
  1724. cvar_humanhp = register_cvar("zp_human_health", "100")
  1725. cvar_humanlasthp = register_cvar("zp_human_last_extrahp", "0")
  1726. cvar_humanspd = register_cvar("zp_human_speed", "240")
  1727. cvar_humangravity = register_cvar("zp_human_gravity", "1.0")
  1728. cvar_humanarmor = register_cvar("zp_human_armor_protect", "1")
  1729. cvar_infammo = register_cvar("zp_human_unlimited_ammo", "0")
  1730. cvar_ammodamage_human = register_cvar("zp_human_damage_reward", "500")
  1731. cvar_fragskill = register_cvar("zp_human_frags_for_kill", "1")
  1732.  
  1733. // CVARS - Custom Grenades
  1734. cvar_firegrenades = register_cvar("zp_fire_grenades", "1")
  1735. cvar_fireduration = register_cvar("zp_fire_duration", "10")
  1736. cvar_firedamage = register_cvar("zp_fire_damage", "5")
  1737. cvar_fireslowdown = register_cvar("zp_fire_slowdown", "0.5")
  1738. cvar_frostgrenades = register_cvar("zp_frost_grenades", "1")
  1739. cvar_freezeduration = register_cvar("zp_frost_duration", "3")
  1740. cvar_flaregrenades = register_cvar("zp_flare_grenades","1")
  1741. cvar_flareduration = register_cvar("zp_flare_duration", "60")
  1742. cvar_flaresize = register_cvar("zp_flare_size", "25")
  1743. cvar_flarecolor = register_cvar("zp_flare_color", "0")
  1744.  
  1745. // CVARS - Zombies
  1746. cvar_zombiefirsthp = register_cvar("zp_zombie_first_hp", "2.0")
  1747. cvar_zombiearmor = register_cvar("zp_zombie_armor", "0.75")
  1748. cvar_hitzones = register_cvar("zp_zombie_hitzones", "0")
  1749. cvar_zombiebonushp = register_cvar("zp_zombie_infect_health", "100")
  1750. cvar_zombiefov = register_cvar("zp_zombie_fov", "110")
  1751. cvar_zombiesilent = register_cvar("zp_zombie_silent", "1")
  1752. cvar_zombiepainfree = register_cvar("zp_zombie_painfree", "2")
  1753. cvar_zombiebleeding = register_cvar("zp_zombie_bleeding", "1")
  1754. cvar_ammoinfect = register_cvar("zp_zombie_infect_reward", "1")
  1755. cvar_ammodamage_zombie = register_cvar("zp_zombie_damage_reward", "0")
  1756. cvar_fragsinfect = register_cvar("zp_zombie_frags_for_infect", "1")
  1757.  
  1758. // CVARS - Special Effects
  1759. cvar_infectionscreenfade = register_cvar("zp_infection_screenfade", "1")
  1760. cvar_infectionscreenshake = register_cvar("zp_infection_screenshake", "1")
  1761. cvar_infectionsparkle = register_cvar("zp_infection_sparkle", "1")
  1762. cvar_infectiontracers = register_cvar("zp_infection_tracers", "1")
  1763. cvar_infectionparticles = register_cvar("zp_infection_particles", "1")
  1764. cvar_hudicons = register_cvar("zp_hud_icons", "1")
  1765.  
  1766. // CVARS - Nemesis
  1767. cvar_nem = register_cvar("zp_nem_enabled", "1")
  1768. cvar_nemchance = register_cvar("zp_nem_chance", "20")
  1769. cvar_nemminplayers = register_cvar("zp_nem_min_players", "0")
  1770. cvar_nemhp = register_cvar("zp_nem_health", "0")
  1771. cvar_nembasehp = register_cvar("zp_nem_base_health", "0")
  1772. cvar_nemspd = register_cvar("zp_nem_speed", "250")
  1773. cvar_nemgravity = register_cvar("zp_nem_gravity", "0.5")
  1774. cvar_nemdamage = register_cvar("zp_nem_damage", "250")
  1775. cvar_nemglow = register_cvar("zp_nem_glow", "1")
  1776. cvar_nemaura = register_cvar("zp_nem_aura", "1")
  1777. cvar_nempainfree = register_cvar("zp_nem_painfree", "0")
  1778. cvar_nemignorefrags = register_cvar("zp_nem_ignore_frags", "1")
  1779. cvar_nemignoreammo = register_cvar("zp_nem_ignore_rewards", "1")
  1780.  
  1781. // CVARS - Survivor
  1782. cvar_surv = register_cvar("zp_surv_enabled", "1")
  1783. cvar_survchance = register_cvar("zp_surv_chance", "20")
  1784. cvar_survminplayers = register_cvar("zp_surv_min_players", "0")
  1785. cvar_survhp = register_cvar("zp_surv_health", "0")
  1786. cvar_survbasehp = register_cvar("zp_surv_base_health", "0")
  1787. cvar_survspd = register_cvar("zp_surv_speed", "230")
  1788. cvar_survgravity = register_cvar("zp_surv_gravity", "1.25")
  1789. cvar_survglow = register_cvar("zp_surv_glow", "1")
  1790. cvar_survaura = register_cvar("zp_surv_aura", "1")
  1791. cvar_survpainfree = register_cvar("zp_surv_painfree", "1")
  1792. cvar_survignorefrags = register_cvar("zp_surv_ignore_frags", "1")
  1793. cvar_survignoreammo = register_cvar("zp_surv_ignore_rewards", "1")
  1794. cvar_survweapon = register_cvar("zp_surv_weapon", "weapon_m249")
  1795. cvar_survinfammo = register_cvar("zp_surv_unlimited_ammo", "2")
  1796.  
  1797. // CVARS - Swarm Mode
  1798. cvar_swarm = register_cvar("zp_swarm_enabled", "1")
  1799. cvar_swarmchance = register_cvar("zp_swarm_chance", "20")
  1800. cvar_swarmminplayers = register_cvar("zp_swarm_min_players", "0")
  1801.  
  1802. // CVARS - Multi Infection
  1803. cvar_multi = register_cvar("zp_multi_enabled", "1")
  1804. cvar_multichance = register_cvar("zp_multi_chance", "20")
  1805. cvar_multiminplayers = register_cvar("zp_multi_min_players", "0")
  1806. cvar_multiratio = register_cvar("zp_multi_ratio", "0.15")
  1807.  
  1808. // CVARS - Plague Mode
  1809. cvar_plague = register_cvar("zp_plague_enabled", "1")
  1810. cvar_plaguechance = register_cvar("zp_plague_chance", "30")
  1811. cvar_plagueminplayers = register_cvar("zp_plague_min_players", "0")
  1812. cvar_plagueratio = register_cvar("zp_plague_ratio", "0.5")
  1813. cvar_plaguenemnum = register_cvar("zp_plague_nem_number", "1")
  1814. cvar_plaguenemhpmulti = register_cvar("zp_plague_nem_hp_multi", "0.5")
  1815. cvar_plaguesurvnum = register_cvar("zp_plague_surv_number", "1")
  1816. cvar_plaguesurvhpmulti = register_cvar("zp_plague_surv_hp_multi", "0.5")
  1817.  
  1818. // CVARS - Others
  1819. cvar_logcommands = register_cvar("zp_logcommands", "1")
  1820. cvar_showactivity = get_cvar_pointer("amx_show_activity")
  1821. cvar_botquota = get_cvar_pointer("bot_quota")
  1822. register_cvar("zp_version", PLUGIN_VERSION, FCVAR_SERVER|FCVAR_SPONLY)
  1823. set_cvar_string("zp_version", PLUGIN_VERSION)
  1824.  
  1825. // Custom Forwards
  1826. g_fwRoundStart = CreateMultiForward("zp_round_started", ET_IGNORE, FP_CELL, FP_CELL)
  1827. g_fwRoundEnd = CreateMultiForward("zp_round_ended", ET_IGNORE, FP_CELL)
  1828. g_fwUserInfected_pre = CreateMultiForward("zp_user_infected_pre", ET_IGNORE, FP_CELL, FP_CELL, FP_CELL)
  1829. g_fwUserInfected_post = CreateMultiForward("zp_user_infected_post", ET_IGNORE, FP_CELL, FP_CELL, FP_CELL)
  1830. g_fwUserHumanized_pre = CreateMultiForward("zp_user_humanized_pre", ET_IGNORE, FP_CELL, FP_CELL)
  1831. g_fwUserHumanized_post = CreateMultiForward("zp_user_humanized_post", ET_IGNORE, FP_CELL, FP_CELL)
  1832. g_fwUserInfect_attempt = CreateMultiForward("zp_user_infect_attempt", ET_CONTINUE, FP_CELL, FP_CELL, FP_CELL)
  1833. g_fwUserHumanize_attempt = CreateMultiForward("zp_user_humanize_attempt", ET_CONTINUE, FP_CELL, FP_CELL)
  1834. g_fwExtraItemSelected = CreateMultiForward("zp_extra_item_selected", ET_CONTINUE, FP_CELL, FP_CELL)
  1835. g_fwUserUnfrozen = CreateMultiForward("zp_user_unfrozen", ET_IGNORE, FP_CELL)
  1836. g_fwUserLastZombie = CreateMultiForward("zp_user_last_zombie", ET_IGNORE, FP_CELL)
  1837. g_fwUserLastHuman = CreateMultiForward("zp_user_last_human", ET_IGNORE, FP_CELL)
  1838.  
  1839. // Collect random spawn points
  1840. load_spawns()
  1841.  
  1842. // Set a random skybox?
  1843. if (g_sky_enable)
  1844. {
  1845. new sky[32]
  1846. ArrayGetString(g_sky_names, random_num(0, ArraySize(g_sky_names) - 1), sky, charsmax(sky))
  1847. set_cvar_string("sv_skyname", sky)
  1848. }
  1849.  
  1850. // Disable sky lighting so it doesn't mess with our custom lighting
  1851. set_cvar_num("sv_skycolor_r", 0)
  1852. set_cvar_num("sv_skycolor_g", 0)
  1853. set_cvar_num("sv_skycolor_b", 0)
  1854.  
  1855. // Create the HUD Sync Objects
  1856. g_MsgSync = CreateHudSyncObj()
  1857. g_MsgSync2 = CreateHudSyncObj()
  1858.  
  1859. // Format mod name
  1860. formatex(g_modname, charsmax(g_modname), "Zombie Plague %s", PLUGIN_VERSION)
  1861.  
  1862. // Get Max Players
  1863. g_maxplayers = get_maxplayers()
  1864.  
  1865. // Reserved saving slots starts on maxplayers+1
  1866. db_slot_i = g_maxplayers+1
  1867.  
  1868. // Check if it's a CZ server
  1869. new mymod[6]
  1870. get_modname(mymod, charsmax(mymod))
  1871. if (equal(mymod, "czero")) g_czero = 1
  1872. }
  1873.  
  1874. public plugin_cfg()
  1875. {
  1876. // Plugin disabled?
  1877. if (!g_pluginenabled) return;
  1878.  
  1879. // Get configs dir
  1880. new cfgdir[32]
  1881. get_configsdir(cfgdir, charsmax(cfgdir))
  1882.  
  1883. // Execute config file (zombieplague.cfg)
  1884. server_cmd("exec %s/zombieplague.cfg", cfgdir)
  1885.  
  1886. // Prevent any more stuff from registering
  1887. g_arrays_created = false
  1888.  
  1889. // Save customization data
  1890. save_customization()
  1891.  
  1892. // Lighting task
  1893. set_task(5.0, "lighting_effects", _, _, _, "b")
  1894.  
  1895. // Cache CVARs after configs are loaded / call roundstart manually
  1896. set_task(0.5, "cache_cvars")
  1897. set_task(0.5, "event_round_start")
  1898. set_task(0.5, "logevent_round_start")
  1899. }
  1900.  
  1901. /*================================================================================
  1902. [Main Events]
  1903. =================================================================================*/
  1904.  
  1905. // Event Round Start
  1906. public event_round_start()
  1907. {
  1908. // Remove doors/lights?
  1909. set_task(0.1, "remove_stuff")
  1910.  
  1911. // New round starting
  1912. g_newround = true
  1913. g_endround = false
  1914. g_survround = false
  1915. g_nemround = false
  1916. g_swarmround = false
  1917. g_plagueround = false
  1918. g_modestarted = false
  1919.  
  1920. // Reset bought infection bombs counter
  1921. g_infbombcounter = 0
  1922. g_antidotecounter = 0
  1923. g_madnesscounter = 0
  1924.  
  1925. // Freezetime begins
  1926. g_freezetime = true
  1927.  
  1928. // Show welcome message and T-Virus notice
  1929. remove_task(TASK_WELCOMEMSG)
  1930. set_task(2.0, "welcome_msg", TASK_WELCOMEMSG)
  1931.  
  1932. // Set a new "Make Zombie Task"
  1933. remove_task(TASK_MAKEZOMBIE)
  1934. set_task(2.0 + get_pcvar_float(cvar_warmup), "make_zombie_task", TASK_MAKEZOMBIE)
  1935. }
  1936.  
  1937. // Log Event Round Start
  1938. public logevent_round_start()
  1939. {
  1940. // Freezetime ends
  1941. g_freezetime = false
  1942. }
  1943.  
  1944. // Log Event Round End
  1945. public logevent_round_end()
  1946. {
  1947. // Prevent this from getting called twice when restarting (bugfix)
  1948. static Float:lastendtime, Float:current_time
  1949. current_time = get_gametime()
  1950. if (current_time - lastendtime < 0.5) return;
  1951. lastendtime = current_time
  1952.  
  1953. // Temporarily save player stats?
  1954. if (get_pcvar_num(cvar_statssave))
  1955. {
  1956. static id, team
  1957. for (id = 1; id <= g_maxplayers; id++)
  1958. {
  1959. // Not connected
  1960. if (!g_isconnected[id])
  1961. continue;
  1962.  
  1963. team = fm_cs_get_user_team(id)
  1964.  
  1965. // Not playing
  1966. if (team == FM_CS_TEAM_SPECTATOR || team == FM_CS_TEAM_UNASSIGNED)
  1967. continue;
  1968.  
  1969. save_stats(id)
  1970. }
  1971. }
  1972.  
  1973. // Round ended
  1974. g_endround = true
  1975.  
  1976. // Stop old tasks (if any)
  1977. remove_task(TASK_WELCOMEMSG)
  1978. remove_task(TASK_MAKEZOMBIE)
  1979.  
  1980. // Stop ambience sounds
  1981. if ((g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS] && g_nemround) || (g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR] && g_survround) || (g_ambience_sounds[AMBIENCE_SOUNDS_SWARM] && g_swarmround) || (g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE] && g_plagueround) || (g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION] && !g_nemround && !g_survround && !g_swarmround && !g_plagueround))
  1982. {
  1983. remove_task(TASK_AMBIENCESOUNDS)
  1984. ambience_sound_stop()
  1985. }
  1986.  
  1987. // Show HUD notice, play win sound, update team scores...
  1988. static sound[64]
  1989. if (!fnGetZombies())
  1990. {
  1991. // Human team wins
  1992. set_hudmessage(0, 0, 200, HUD_EVENT_X, HUD_EVENT_Y, 0, 0.0, 3.0, 2.0, 1.0, -1)
  1993. ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "WIN_HUMAN")
  1994.  
  1995. // Play win sound and increase score, unless game commencing
  1996. ArrayGetString(sound_win_humans, random_num(0, ArraySize(sound_win_humans) - 1), sound, charsmax(sound))
  1997. PlaySound(sound)
  1998. if (!g_gamecommencing) g_scorehumans++
  1999.  
  2000. // Round end forward
  2001. ExecuteForward(g_fwRoundEnd, g_fwDummyResult, ZP_TEAM_HUMAN);
  2002. }
  2003. else if (!fnGetHumans())
  2004. {
  2005. // Zombie team wins
  2006. set_hudmessage(200, 0, 0, HUD_EVENT_X, HUD_EVENT_Y, 0, 0.0, 3.0, 2.0, 1.0, -1)
  2007. ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "WIN_ZOMBIE")
  2008.  
  2009. // Play win sound and increase score, unless game commencing
  2010. ArrayGetString(sound_win_zombies, random_num(0, ArraySize(sound_win_zombies) - 1), sound, charsmax(sound))
  2011. PlaySound(sound)
  2012. if (!g_gamecommencing) g_scorezombies++
  2013.  
  2014. // Round end forward
  2015. ExecuteForward(g_fwRoundEnd, g_fwDummyResult, ZP_TEAM_ZOMBIE);
  2016. }
  2017. else
  2018. {
  2019. // No one wins
  2020. set_hudmessage(0, 200, 0, HUD_EVENT_X, HUD_EVENT_Y, 0, 0.0, 3.0, 2.0, 1.0, -1)
  2021. ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "WIN_NO_ONE")
  2022.  
  2023. // Play win sound
  2024. ArrayGetString(sound_win_no_one, random_num(0, ArraySize(sound_win_no_one) - 1), sound, charsmax(sound))
  2025. PlaySound(sound)
  2026.  
  2027. // Round end forward
  2028. ExecuteForward(g_fwRoundEnd, g_fwDummyResult, ZP_TEAM_NO_ONE);
  2029. }
  2030.  
  2031. // Game commencing triggers round end
  2032. g_gamecommencing = false
  2033.  
  2034. // Balance the teams
  2035. balance_teams()
  2036. }
  2037.  
  2038. // Event Map Ended
  2039. public event_intermission()
  2040. {
  2041. // Remove ambience sounds task
  2042. remove_task(TASK_AMBIENCESOUNDS)
  2043. }
  2044.  
  2045. // BP Ammo update
  2046. public event_ammo_x(id)
  2047. {
  2048. // Humans only
  2049. if (g_zombie[id])
  2050. return;
  2051.  
  2052. // Get ammo type
  2053. static type
  2054. type = read_data(1)
  2055.  
  2056. // Unknown ammo type
  2057. if (type >= sizeof AMMOWEAPON)
  2058. return;
  2059.  
  2060. // Get weapon's id
  2061. static weapon
  2062. weapon = AMMOWEAPON[type]
  2063.  
  2064. // Primary and secondary only
  2065. if (MAXBPAMMO[weapon] <= 2)
  2066. return;
  2067.  
  2068. // Get ammo amount
  2069. static amount
  2070. amount = read_data(2)
  2071.  
  2072. // Unlimited BP Ammo?
  2073. if (g_survivor[id] ? get_pcvar_num(cvar_survinfammo) : get_pcvar_num(cvar_infammo))
  2074. {
  2075. if (amount < MAXBPAMMO[weapon])
  2076. {
  2077. // The BP Ammo refill code causes the engine to send a message, but we
  2078. // can't have that in this forward or we risk getting some recursion bugs.
  2079. // For more info see: https://bugs.alliedmods.net/show_bug.cgi?id=3664
  2080. static args[1]
  2081. args[0] = weapon
  2082. set_task(0.1, "refill_bpammo", id, args, sizeof args)
  2083. }
  2084. }
  2085. // Bots automatically buy ammo when needed
  2086. else if (g_isbot[id] && amount <= BUYAMMO[weapon])
  2087. {
  2088. // Task needed for the same reason as above
  2089. set_task(0.1, "clcmd_buyammo", id)
  2090. }
  2091. }
  2092.  
  2093. /*================================================================================
  2094. [Main Forwards]
  2095. =================================================================================*/
  2096.  
  2097. // Entity Spawn Forward
  2098. public fw_Spawn(entity)
  2099. {
  2100. // Invalid entity
  2101. if (!pev_valid(entity)) return FMRES_IGNORED;
  2102.  
  2103. // Get classname
  2104. new classname[32], objective[32], size = ArraySize(g_objective_ents)
  2105. pev(entity, pev_classname, classname, charsmax(classname))
  2106.  
  2107. // Check whether it needs to be removed
  2108. for (new i = 0; i < size; i++)
  2109. {
  2110. ArrayGetString(g_objective_ents, i, objective, charsmax(objective))
  2111.  
  2112. if (equal(classname, objective))
  2113. {
  2114. engfunc(EngFunc_RemoveEntity, entity)
  2115. return FMRES_SUPERCEDE;
  2116. }
  2117. }
  2118.  
  2119. return FMRES_IGNORED;
  2120. }
  2121.  
  2122. // Sound Precache Forward
  2123. public fw_PrecacheSound(const sound[])
  2124. {
  2125. // Block all those unneeeded hostage sounds
  2126. if (equal(sound, "hostage", 7))
  2127. return FMRES_SUPERCEDE;
  2128.  
  2129. return FMRES_IGNORED;
  2130. }
  2131.  
  2132. // Ham Player Spawn Post Forward
  2133. public fw_PlayerSpawn_Post(id)
  2134. {
  2135. // Not alive or didn't join a team yet
  2136. if (!is_user_alive(id) || !fm_cs_get_user_team(id))
  2137. return;
  2138.  
  2139. // Player spawned
  2140. g_isalive[id] = true
  2141.  
  2142. // Remove previous tasks
  2143. remove_task(id+TASK_SPAWN)
  2144. remove_task(id+TASK_MODEL)
  2145. remove_task(id+TASK_BLOOD)
  2146. remove_task(id+TASK_AURA)
  2147. remove_task(id+TASK_BURN)
  2148. remove_task(id+TASK_CHARGE)
  2149. remove_task(id+TASK_FLASH)
  2150. remove_task(id+TASK_NVISION)
  2151.  
  2152. // Spawn at a random location?
  2153. if (get_pcvar_num(cvar_randspawn)) do_random_spawn(id)
  2154.  
  2155. // Hide money?
  2156. if (get_pcvar_num(cvar_removemoney))
  2157. set_task(0.4, "task_hide_money", id+TASK_SPAWN)
  2158.  
  2159. // Respawn player if he dies because of a worldspawn kill?
  2160. if (get_pcvar_num(cvar_respawnworldspawnkill))
  2161. set_task(2.0, "respawn_player_check_task", id+TASK_SPAWN)
  2162.  
  2163. // Spawn as zombie?
  2164. if (g_respawn_as_zombie[id] && !g_newround)
  2165. {
  2166. reset_vars(id, 0) // reset player vars
  2167. zombieme(id, 0, 0, 0, 0) // make him zombie right away
  2168. return;
  2169. }
  2170.  
  2171. // Reset player vars
  2172. reset_vars(id, 0)
  2173. g_buytime[id] = get_gametime()
  2174.  
  2175. // Show custom buy menu?
  2176. if (get_pcvar_num(cvar_buycustom))
  2177. set_task(0.2, "show_menu_buy1", id+TASK_SPAWN)
  2178.  
  2179. // Set health and gravity
  2180. fm_set_user_health(id, get_pcvar_num(cvar_humanhp))
  2181. set_pev(id, pev_gravity, get_pcvar_float(cvar_humangravity))
  2182.  
  2183. // Set human maxspeed
  2184. ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
  2185.  
  2186. // Switch to CT if spawning mid-round
  2187. if (!g_newround && fm_cs_get_user_team(id) != FM_CS_TEAM_CT) // need to change team?
  2188. {
  2189. remove_task(id+TASK_TEAM)
  2190. fm_cs_set_user_team(id, FM_CS_TEAM_CT)
  2191. fm_user_team_update(id)
  2192. }
  2193.  
  2194. // Custom models stuff
  2195. static currentmodel[32], tempmodel[32], already_has_model, i, iRand, size
  2196. already_has_model = false
  2197.  
  2198. if (g_handle_models_on_separate_ent)
  2199. {
  2200. // Set the right model
  2201. if (get_pcvar_num(cvar_adminmodelshuman) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
  2202. {
  2203. iRand = random_num(0, ArraySize(model_admin_human) - 1)
  2204. ArrayGetString(model_admin_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  2205. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_human, iRand))
  2206. }
  2207. else
  2208. {
  2209. iRand = random_num(0, ArraySize(model_human) - 1)
  2210. ArrayGetString(model_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  2211. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_human, iRand))
  2212. }
  2213.  
  2214. // Set model on player model entity
  2215. fm_set_playermodel_ent(id)
  2216.  
  2217. // Remove glow on player model entity
  2218. fm_set_rendering(g_ent_playermodel[id])
  2219. }
  2220. else
  2221. {
  2222. // Get current model for comparing it with the current one
  2223. fm_cs_get_user_model(id, currentmodel, charsmax(currentmodel))
  2224.  
  2225. // Set the right model, after checking that we don't already have it
  2226. if (get_pcvar_num(cvar_adminmodelshuman) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
  2227. {
  2228. size = ArraySize(model_admin_human)
  2229. for (i = 0; i < size; i++)
  2230. {
  2231. ArrayGetString(model_admin_human, i, tempmodel, charsmax(tempmodel))
  2232. if (equal(currentmodel, tempmodel)) already_has_model = true
  2233. }
  2234.  
  2235. if (!already_has_model)
  2236. {
  2237. iRand = random_num(0, size - 1)
  2238. ArrayGetString(model_admin_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  2239. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_human, iRand))
  2240. }
  2241. }
  2242. else
  2243. {
  2244. size = ArraySize(model_human)
  2245. for (i = 0; i < size; i++)
  2246. {
  2247. ArrayGetString(model_human, i, tempmodel, charsmax(tempmodel))
  2248. if (equal(currentmodel, tempmodel)) already_has_model = true
  2249. }
  2250.  
  2251. if (!already_has_model)
  2252. {
  2253. iRand = random_num(0, size - 1)
  2254. ArrayGetString(model_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  2255. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_human, iRand))
  2256. }
  2257. }
  2258.  
  2259. // Need to change the model?
  2260. if (!already_has_model)
  2261. {
  2262. // An additional delay is offset at round start
  2263. // since SVC_BAD is more likely to be triggered there
  2264. if (g_newround)
  2265. set_task(5.0 * g_modelchange_delay, "fm_user_model_update", id+TASK_MODEL)
  2266. else
  2267. fm_user_model_update(id+TASK_MODEL)
  2268. }
  2269.  
  2270. // Remove glow
  2271. fm_set_rendering(id)
  2272. }
  2273.  
  2274. // Bots stuff
  2275. if (g_isbot[id])
  2276. {
  2277. // Turn off NVG for bots
  2278. cs_set_user_nvg(id, 0)
  2279.  
  2280. // Automatically buy extra items/weapons after first zombie is chosen
  2281. if (get_pcvar_num(cvar_extraitems))
  2282. {
  2283. if (g_newround) set_task(10.0 + get_pcvar_float(cvar_warmup), "bot_buy_extras", id+TASK_SPAWN)
  2284. else set_task(10.0, "bot_buy_extras", id+TASK_SPAWN)
  2285. }
  2286. }
  2287.  
  2288. // Enable spawn protection for humans spawning mid-round
  2289. if (!g_newround && get_pcvar_float(cvar_spawnprotection) > 0.0)
  2290. {
  2291. // Do not take damage
  2292. g_nodamage[id] = true
  2293.  
  2294. // Make temporarily invisible
  2295. set_pev(id, pev_effects, pev(id, pev_effects) | EF_NODRAW)
  2296.  
  2297. // Set task to remove it
  2298. set_task(get_pcvar_float(cvar_spawnprotection), "remove_spawn_protection", id+TASK_SPAWN)
  2299. }
  2300.  
  2301. // Turn off his flashlight (prevents double flashlight bug/exploit)
  2302. turn_off_flashlight(id)
  2303.  
  2304. // Set the flashlight charge task to update battery status
  2305. if (g_cached_customflash)
  2306. set_task(1.0, "flashlight_charge", id+TASK_CHARGE, _, _, "b")
  2307.  
  2308. // Replace weapon models (bugfix)
  2309. static weapon_ent
  2310. weapon_ent = fm_cs_get_current_weapon_ent(id)
  2311. if (pev_valid(weapon_ent)) replace_weapon_models(id, cs_get_weapon_id(weapon_ent))
  2312.  
  2313. // Last Zombie Check
  2314. fnCheckLastZombie()
  2315. }
  2316.  
  2317. // Ham Player Killed Forward
  2318. public fw_PlayerKilled(victim, attacker, shouldgib)
  2319. {
  2320. // Player killed
  2321. g_isalive[victim] = false
  2322. // Disable nodamage mode after we die to prevent spectator nightvision using zombie madness colors bug
  2323. g_nodamage[victim] = false
  2324.  
  2325. // Enable dead players nightvision
  2326. set_task(0.1, "spec_nvision", victim)
  2327.  
  2328. // Disable nightvision when killed (bugfix)
  2329. if (get_pcvar_num(cvar_nvggive) == 0 && g_nvision[victim])
  2330. {
  2331. if (get_pcvar_num(cvar_customnvg)) remove_task(victim+TASK_NVISION)
  2332. else if (g_nvisionenabled[victim]) set_user_gnvision(victim, 0)
  2333. g_nvision[victim] = false
  2334. g_nvisionenabled[victim] = false
  2335. }
  2336.  
  2337. // Turn off nightvision when killed (bugfix)
  2338. if (get_pcvar_num(cvar_nvggive) == 2 && g_nvision[victim] && g_nvisionenabled[victim])
  2339. {
  2340. if (get_pcvar_num(cvar_customnvg)) remove_task(victim+TASK_NVISION)
  2341. else set_user_gnvision(victim, 0)
  2342. g_nvisionenabled[victim] = false
  2343. }
  2344.  
  2345. // Turn off custom flashlight when killed
  2346. if (g_cached_customflash)
  2347. {
  2348. // Turn it off
  2349. g_flashlight[victim] = false
  2350. g_flashbattery[victim] = 100
  2351.  
  2352. // Remove previous tasks
  2353. remove_task(victim+TASK_CHARGE)
  2354. remove_task(victim+TASK_FLASH)
  2355. }
  2356.  
  2357. // Stop bleeding/burning/aura when killed
  2358. if (g_zombie[victim])
  2359. {
  2360. remove_task(victim+TASK_BLOOD)
  2361. remove_task(victim+TASK_AURA)
  2362. remove_task(victim+TASK_BURN)
  2363. }
  2364.  
  2365. // Nemesis explodes!
  2366. if (g_nemesis[victim])
  2367. SetHamParamInteger(3, 2)
  2368.  
  2369. // Determine whether the player killed himself
  2370. static selfkill
  2371. selfkill = (victim == attacker || !is_user_valid_connected(attacker)) ? true : false
  2372.  
  2373. // Killed by a non-player entity or self killed
  2374. if (selfkill) return;
  2375.  
  2376. // Ignore Nemesis/Survivor Frags?
  2377. if ((g_nemesis[attacker] && get_pcvar_num(cvar_nemignorefrags)) || (g_survivor[attacker] && get_pcvar_num(cvar_survignorefrags)))
  2378. RemoveFrags(attacker, victim)
  2379.  
  2380. // Zombie/nemesis killed human, reward ammo packs
  2381. if (g_zombie[attacker] && (!g_nemesis[attacker] || !get_pcvar_num(cvar_nemignoreammo)))
  2382. g_ammopacks[attacker] += get_pcvar_num(cvar_ammoinfect)
  2383.  
  2384. // Human killed zombie, add up the extra frags for kill
  2385. if (!g_zombie[attacker] && get_pcvar_num(cvar_fragskill) > 1)
  2386. UpdateFrags(attacker, victim, get_pcvar_num(cvar_fragskill) - 1, 0, 0)
  2387.  
  2388. // Zombie killed human, add up the extra frags for kill
  2389. if (g_zombie[attacker] && get_pcvar_num(cvar_fragsinfect) > 1)
  2390. UpdateFrags(attacker, victim, get_pcvar_num(cvar_fragsinfect) - 1, 0, 0)
  2391. }
  2392.  
  2393. // Ham Player Killed Post Forward
  2394. public fw_PlayerKilled_Post(victim, attacker, shouldgib)
  2395. {
  2396. // Last Zombie Check
  2397. fnCheckLastZombie()
  2398.  
  2399. // Determine whether the player killed himself
  2400. static selfkill
  2401. selfkill = (victim == attacker || !is_user_valid_connected(attacker)) ? true : false
  2402.  
  2403. // Respawn if deathmatch is enabled
  2404. if (get_pcvar_num(cvar_deathmatch))
  2405. {
  2406. // Respawn on suicide?
  2407. if (selfkill && !get_pcvar_num(cvar_respawnonsuicide))
  2408. return;
  2409.  
  2410. // Respawn if human/zombie/nemesis/survivor?
  2411. if ((g_zombie[victim] && !g_nemesis[victim] && !get_pcvar_num(cvar_respawnzomb)) || (!g_zombie[victim] && !g_survivor[victim] && !get_pcvar_num(cvar_respawnhum)) || (g_nemesis[victim] && !get_pcvar_num(cvar_respawnnem)) || (g_survivor[victim] && !get_pcvar_num(cvar_respawnsurv)))
  2412. return;
  2413.  
  2414. // Set the respawn task
  2415. set_task(get_pcvar_float(cvar_spawndelay), "respawn_player_task", victim+TASK_SPAWN)
  2416. }
  2417. }
  2418.  
  2419. // Ham Take Damage Forward
  2420. public fw_TakeDamage(victim, inflictor, attacker, Float:damage, damage_type)
  2421. {
  2422. // Non-player damage or self damage
  2423. if (victim == attacker || !is_user_valid_connected(attacker))
  2424. return HAM_IGNORED;
  2425.  
  2426. // New round starting or round ended
  2427. if (g_newround || g_endround)
  2428. return HAM_SUPERCEDE;
  2429.  
  2430. // Victim shouldn't take damage or victim is frozen
  2431. if (g_nodamage[victim] || g_frozen[victim])
  2432. return HAM_SUPERCEDE;
  2433.  
  2434. // Prevent friendly fire
  2435. if (g_zombie[attacker] == g_zombie[victim])
  2436. return HAM_SUPERCEDE;
  2437.  
  2438. // Attacker is human...
  2439. if (!g_zombie[attacker])
  2440. {
  2441. // Armor multiplier for the final damage on normal zombies
  2442. if (!g_nemesis[victim])
  2443. {
  2444. damage *= get_pcvar_float(cvar_zombiearmor)
  2445. SetHamParamFloat(4, damage)
  2446. }
  2447.  
  2448. // Reward ammo packs to humans for damaging zombies?
  2449. if ((get_pcvar_num(cvar_ammodamage_human) > 0) && (!g_survivor[attacker] || !get_pcvar_num(cvar_survignoreammo)))
  2450. {
  2451. // Store damage dealt
  2452. g_damagedealt_human[attacker] += floatround(damage)
  2453.  
  2454. // Reward ammo packs for every [ammo damage] dealt
  2455. while (g_damagedealt_human[attacker] > get_pcvar_num(cvar_ammodamage_human))
  2456. {
  2457. g_ammopacks[attacker]++
  2458. g_damagedealt_human[attacker] -= get_pcvar_num(cvar_ammodamage_human)
  2459. }
  2460. }
  2461.  
  2462. return HAM_IGNORED;
  2463. }
  2464.  
  2465. // Attacker is zombie...
  2466.  
  2467. // Prevent infection/damage by HE grenade (bugfix)
  2468. if (damage_type & DMG_HEGRENADE)
  2469. return HAM_SUPERCEDE;
  2470.  
  2471. // Nemesis?
  2472. if (g_nemesis[attacker])
  2473. {
  2474. // Ignore nemesis damage override if damage comes from a 3rd party entity
  2475. // (to prevent this from affecting a sub-plugin's rockets e.g.)
  2476. if (inflictor == attacker)
  2477. {
  2478. // Set nemesis damage
  2479. SetHamParamFloat(4, get_pcvar_float(cvar_nemdamage))
  2480. }
  2481.  
  2482. return HAM_IGNORED;
  2483. }
  2484.  
  2485. // Reward ammo packs to zombies for damaging humans?
  2486. if (get_pcvar_num(cvar_ammodamage_zombie) > 0)
  2487. {
  2488. // Store damage dealt
  2489. g_damagedealt_zombie[attacker] += floatround(damage)
  2490.  
  2491. // Reward ammo packs for every [ammo damage] dealt
  2492. while (g_damagedealt_zombie[attacker] > get_pcvar_num(cvar_ammodamage_zombie))
  2493. {
  2494. g_ammopacks[attacker]++
  2495. g_damagedealt_zombie[attacker] -= get_pcvar_num(cvar_ammodamage_zombie)
  2496. }
  2497. }
  2498.  
  2499. // Last human or not an infection round
  2500. if (g_survround || g_nemround || g_swarmround || g_plagueround || fnGetHumans() == 1)
  2501. return HAM_IGNORED; // human is killed
  2502.  
  2503. // Does human armor need to be reduced before infecting?
  2504. if (get_pcvar_num(cvar_humanarmor))
  2505. {
  2506. // Get victim armor
  2507. static Float:armor
  2508. pev(victim, pev_armorvalue, armor)
  2509.  
  2510. // If he has some, block the infection and reduce armor instead
  2511. if (armor > 0.0)
  2512. {
  2513. emit_sound(victim, CHAN_BODY, sound_armorhit, 1.0, ATTN_NORM, 0, PITCH_NORM)
  2514. if (armor - damage > 0.0)
  2515. set_pev(victim, pev_armorvalue, armor - damage)
  2516. else
  2517. cs_set_user_armor(victim, 0, CS_ARMOR_NONE)
  2518. return HAM_SUPERCEDE;
  2519. }
  2520. }
  2521.  
  2522. // Infection allowed
  2523. zombieme(victim, attacker, 0, 0, 1) // turn into zombie
  2524. return HAM_SUPERCEDE;
  2525. }
  2526.  
  2527. // Ham Take Damage Post Forward
  2528. public fw_TakeDamage_Post(victim)
  2529. {
  2530. // Prevent server crash if entity's private data not initalized
  2531. if (pev_valid(victim) != PDATA_SAFE)
  2532. return;
  2533.  
  2534. if(g_painshockfree[victim])
  2535. {
  2536. // Set pain shock free offset
  2537. set_pdata_float(victim, OFFSET_PAINSHOCK, 1.0, OFFSET_LINUX)
  2538. return
  2539. }
  2540.  
  2541. // --- Check if victim should be Pain Shock Free ---
  2542.  
  2543. // Check if proper CVARs are enabled
  2544. if (g_zombie[victim])
  2545. {
  2546. if (g_nemesis[victim])
  2547. {
  2548. if (!get_pcvar_num(cvar_nempainfree)) return;
  2549. }
  2550. else
  2551. {
  2552. switch (get_pcvar_num(cvar_zombiepainfree))
  2553. {
  2554. case 0: return;
  2555. case 2: if (!g_lastzombie[victim]) return;
  2556. case 3: if (!g_firstzombie[victim]) return;
  2557. }
  2558. }
  2559. }
  2560. else
  2561. {
  2562. if (g_survivor[victim])
  2563. {
  2564. if (!get_pcvar_num(cvar_survpainfree)) return;
  2565. }
  2566. else return;
  2567. }
  2568.  
  2569. // Set pain shock free offset
  2570. set_pdata_float(victim, OFFSET_PAINSHOCK, 1.0, OFFSET_LINUX)
  2571. }
  2572.  
  2573. // Ham Trace Attack Forward
  2574. public fw_TraceAttack(victim, attacker, Float:damage, Float:direction[3], tracehandle, damage_type)
  2575. {
  2576. // Non-player damage or self damage
  2577. if (victim == attacker || !is_user_valid_connected(attacker))
  2578. return HAM_IGNORED;
  2579.  
  2580. // New round starting or round ended
  2581. if (g_newround || g_endround)
  2582. return HAM_SUPERCEDE;
  2583.  
  2584. // Victim shouldn't take damage or victim is frozen
  2585. if (g_nodamage[victim] || g_frozen[victim])
  2586. return HAM_SUPERCEDE;
  2587.  
  2588. // Prevent friendly fire
  2589. if (g_zombie[attacker] == g_zombie[victim])
  2590. return HAM_SUPERCEDE;
  2591.  
  2592. // Victim isn't a zombie or not bullet damage, nothing else to do here
  2593. if (!g_zombie[victim] || !(damage_type & DMG_BULLET))
  2594. return HAM_IGNORED;
  2595.  
  2596. // If zombie hitzones are enabled, check whether we hit an allowed one
  2597. if (get_pcvar_num(cvar_hitzones) && !g_nemesis[victim] && !(get_pcvar_num(cvar_hitzones) & (1<<get_tr2(tracehandle, TR_iHitgroup))))
  2598. return HAM_SUPERCEDE;
  2599.  
  2600. // Knockback disabled, nothing else to do here
  2601. if (!get_pcvar_num(cvar_knockback))
  2602. return HAM_IGNORED;
  2603.  
  2604. // Nemesis knockback disabled, nothing else to do here
  2605. if (g_nemesis[victim] && get_pcvar_float(cvar_nemknockback) == 0.0)
  2606. return HAM_IGNORED;
  2607.  
  2608. // Get whether the victim is in a crouch state
  2609. static ducking
  2610. ducking = pev(victim, pev_flags) & (FL_DUCKING | FL_ONGROUND) == (FL_DUCKING | FL_ONGROUND)
  2611.  
  2612. // Zombie knockback when ducking disabled
  2613. if (ducking && get_pcvar_float(cvar_knockbackducking) == 0.0)
  2614. return HAM_IGNORED;
  2615.  
  2616. // Get distance between players
  2617. static origin1[3], origin2[3]
  2618. get_user_origin(victim, origin1)
  2619. get_user_origin(attacker, origin2)
  2620.  
  2621. // Max distance exceeded
  2622. if (get_distance(origin1, origin2) > get_pcvar_num(cvar_knockbackdist))
  2623. return HAM_IGNORED;
  2624.  
  2625. // Get victim's velocity
  2626. static Float:velocity[3]
  2627. pev(victim, pev_velocity, velocity)
  2628.  
  2629. // Use damage on knockback calculation
  2630. if (get_pcvar_num(cvar_knockbackdamage))
  2631. xs_vec_mul_scalar(direction, damage, direction)
  2632.  
  2633. // Use weapon power on knockback calculation
  2634. if (get_pcvar_num(cvar_knockbackpower) && kb_weapon_power[g_currentweapon[attacker]] > 0.0)
  2635. xs_vec_mul_scalar(direction, kb_weapon_power[g_currentweapon[attacker]], direction)
  2636.  
  2637. // Apply ducking knockback multiplier
  2638. if (ducking)
  2639. xs_vec_mul_scalar(direction, get_pcvar_float(cvar_knockbackducking), direction)
  2640.  
  2641. // Apply zombie class/nemesis knockback multiplier
  2642. if (g_nemesis[victim])
  2643. xs_vec_mul_scalar(direction, get_pcvar_float(cvar_nemknockback), direction)
  2644. else
  2645. xs_vec_mul_scalar(direction, g_zombie_knockback[victim], direction)
  2646.  
  2647. // Add up the new vector
  2648. xs_vec_add(velocity, direction, direction)
  2649.  
  2650. // Should knockback also affect vertical velocity?
  2651. if (!get_pcvar_num(cvar_knockbackzvel))
  2652. direction[2] = velocity[2]
  2653.  
  2654. // Set the knockback'd victim's velocity
  2655. set_pev(victim, pev_velocity, direction)
  2656.  
  2657. return HAM_IGNORED;
  2658. }
  2659.  
  2660. // Ham Reset MaxSpeed Post Forward
  2661. public fw_ResetMaxSpeed_Post(id)
  2662. {
  2663. // Freezetime active or player not alive
  2664. if (g_freezetime || !g_isalive[id])
  2665. return;
  2666.  
  2667. set_player_maxspeed(id)
  2668. }
  2669.  
  2670. // Ham Use Stationary Gun Forward
  2671. public fw_UseStationary(entity, caller, activator, use_type)
  2672. {
  2673. // Prevent zombies from using stationary guns
  2674. if (use_type == USE_USING && is_user_valid_connected(caller) && g_zombie[caller])
  2675. return HAM_SUPERCEDE;
  2676.  
  2677. return HAM_IGNORED;
  2678. }
  2679.  
  2680. // Ham Use Stationary Gun Post Forward
  2681. public fw_UseStationary_Post(entity, caller, activator, use_type)
  2682. {
  2683. // Someone stopped using a stationary gun
  2684. if (use_type == USE_STOPPED && is_user_valid_connected(caller))
  2685. replace_weapon_models(caller, g_currentweapon[caller]) // replace weapon models (bugfix)
  2686. }
  2687.  
  2688. // Ham Use Pushable Forward
  2689. public fw_UsePushable()
  2690. {
  2691. // Prevent speed bug with pushables?
  2692. if (get_pcvar_num(cvar_blockpushables))
  2693. return HAM_SUPERCEDE;
  2694.  
  2695. return HAM_IGNORED;
  2696. }
  2697.  
  2698. // Ham Weapon Touch Forward
  2699. public fw_TouchWeapon(weapon, id)
  2700. {
  2701. // Not a player
  2702. if (!is_user_valid_connected(id))
  2703. return HAM_IGNORED;
  2704.  
  2705. // Dont pickup weapons if zombie or survivor (+PODBot MM fix)
  2706. if (g_zombie[id] || (g_survivor[id] && !g_isbot[id]))
  2707. return HAM_SUPERCEDE;
  2708.  
  2709. return HAM_IGNORED;
  2710. }
  2711.  
  2712. // Ham Weapon Pickup Forward
  2713. public fw_AddPlayerItem(id, weapon_ent)
  2714. {
  2715. // HACK: Retrieve our custom extra ammo from the weapon
  2716. static extra_ammo
  2717. extra_ammo = pev(weapon_ent, PEV_ADDITIONAL_AMMO)
  2718.  
  2719. // If present
  2720. if (extra_ammo)
  2721. {
  2722. // Get weapon's id
  2723. static weaponid
  2724. weaponid = cs_get_weapon_id(weapon_ent)
  2725.  
  2726. // Add to player's bpammo
  2727. ExecuteHamB(Ham_GiveAmmo, id, extra_ammo, AMMOTYPE[weaponid], MAXBPAMMO[weaponid])
  2728. set_pev(weapon_ent, PEV_ADDITIONAL_AMMO, 0)
  2729. }
  2730. }
  2731.  
  2732. // Ham Weapon Deploy Forward
  2733. public fw_Item_Deploy_Post(weapon_ent)
  2734. {
  2735. // Get weapon's owner
  2736. static owner
  2737. owner = fm_cs_get_weapon_ent_owner(weapon_ent)
  2738.  
  2739. // Valid owner?
  2740. if (!pev_valid(owner))
  2741. return;
  2742.  
  2743. // Get weapon's id
  2744. static weaponid
  2745. weaponid = cs_get_weapon_id(weapon_ent)
  2746.  
  2747. // Store current weapon's id for reference
  2748. g_currentweapon[owner] = weaponid
  2749.  
  2750. // Replace weapon models with custom ones
  2751. replace_weapon_models(owner, weaponid)
  2752.  
  2753. // Zombie not holding an allowed weapon for some reason
  2754. if (g_zombie[owner] && !((1<<weaponid) & ZOMBIE_ALLOWED_WEAPONS_BITSUM))
  2755. {
  2756. // Switch to knife
  2757. g_currentweapon[owner] = CSW_KNIFE
  2758. engclient_cmd(owner, "weapon_knife")
  2759. }
  2760. }
  2761.  
  2762. // WeaponMod bugfix
  2763. //forward wpn_gi_reset_weapon(id);
  2764. public wpn_gi_reset_weapon(id)
  2765. {
  2766. // Replace knife model
  2767. replace_weapon_models(id, CSW_KNIFE)
  2768. }
  2769.  
  2770. // Client joins the game
  2771. public client_putinserver(id)
  2772. {
  2773. // Plugin disabled?
  2774. if (!g_pluginenabled) return;
  2775.  
  2776. // Player joined
  2777. g_isconnected[id] = true
  2778.  
  2779. // Cache player's name
  2780. get_user_name(id, g_playername[id], charsmax(g_playername[]))
  2781.  
  2782. // Initialize player vars
  2783. reset_vars(id, 1)
  2784.  
  2785. // Load player stats?
  2786. if (get_pcvar_num(cvar_statssave)) load_stats(id)
  2787.  
  2788. set_task( 3.0 , "respawn_welcome", id)
  2789.  
  2790.  
  2791. // Set some tasks for humans only
  2792. if (!is_user_bot(id))
  2793. {
  2794. // Set the custom HUD display task if enabled
  2795. if (get_pcvar_num(cvar_huddisplay))
  2796. set_task(1.0, "ShowHUD", id+TASK_SHOWHUD, _, _, "b")
  2797.  
  2798. // Disable minmodels for clients to see zombies properly
  2799. set_task(5.0, "disable_minmodels", id)
  2800. }
  2801. else
  2802. {
  2803. // Set bot flag
  2804. g_isbot[id] = true
  2805.  
  2806. // CZ bots seem to use a different "classtype" for player entities
  2807. // (or something like that) which needs to be hooked separately
  2808. if (!g_hamczbots && cvar_botquota)
  2809. {
  2810. // Set a task to let the private data initialize
  2811. set_task(0.1, "register_ham_czbots", id)
  2812. }
  2813. }
  2814. }
  2815. // Respawn check
  2816. public respawn_welcome(id)
  2817. {
  2818. static team
  2819. team = fm_cs_get_user_team(id)
  2820.  
  2821. if( id )
  2822. {
  2823. if( is_user_connected(id) && !is_user_connecting(id) )
  2824. {
  2825. if (team == FM_CS_TEAM_SPECTATOR || team == FM_CS_TEAM_UNASSIGNED)
  2826. {
  2827. set_task( 1.0 , "respawn_welcome", id)
  2828. }
  2829. else
  2830. {
  2831.  
  2832. set_task( 1.0 , "deadmau5_respawn_now", id)
  2833.  
  2834. }
  2835.  
  2836. }
  2837. else
  2838. {
  2839. set_task( 1.0 , "respawn_welcome", id)
  2840. }
  2841. }
  2842. else
  2843. {
  2844. new iPlayers[32], iNum
  2845. get_players(iPlayers, iNum, "c")
  2846.  
  2847. for(--iNum; iNum>=0; iNum--)
  2848. {
  2849. id = iPlayers[iNum]
  2850.  
  2851. if( !is_user_connecting(id) )
  2852. {
  2853. if (team == FM_CS_TEAM_SPECTATOR || team == FM_CS_TEAM_UNASSIGNED)
  2854. {
  2855. set_task( 1.0 , "respawn_welcome", id)
  2856. }
  2857. else
  2858. {
  2859. set_task( 1.0 , "deadmau5_respawn_now", id)
  2860.  
  2861. }
  2862.  
  2863. }
  2864. else
  2865. {
  2866. set_task( 1.0 , "respawn_welcome", id)
  2867. }
  2868. }
  2869. }
  2870. }
  2871.  
  2872. // Respawn now!
  2873. public deadmau5_respawn_now(id)
  2874. {
  2875.  
  2876. if (!is_user_alive(id))
  2877. {
  2878.  
  2879. if(g_nemround)
  2880. {
  2881. set_task( 7.5 , "deadmau5_welcome_text", id)
  2882. }
  2883. else if(g_survround)
  2884. {
  2885. set_task( 7.5 , "deadmau5_welcome_text", id)
  2886. }
  2887. else if(g_plagueround)
  2888. {
  2889. set_task( 7.5 , "deadmau5_welcome_text", id)
  2890. }
  2891. else
  2892. {
  2893. set_task( 7.5 , "deadmau5_welcome_text", id)
  2894.  
  2895. set_task(5.0, "respawn_player_task", id+TASK_SPAWN)
  2896. }
  2897. }
  2898. }
  2899.  
  2900. public deadmau5_welcome_text(id)
  2901. {
  2902. set_hudmessage(0, 125, 0, -1.0, 0.17, 1, 2.0, 2.0, 4.0, 2.0, -1)
  2903. ShowSyncHudMsg(id, g_MsgSync, "Sky Arena Zombie vam zeli ugodnu igru!^n IP Servera: 193.192.59.74:27111")
  2904. }
  2905.  
  2906. // Client leaving
  2907. public fw_ClientDisconnect(id)
  2908. {
  2909. // Check that we still have both humans and zombies to keep the round going
  2910. if (g_isalive[id]) check_round(id)
  2911.  
  2912. // Temporarily save player stats?
  2913. if (get_pcvar_num(cvar_statssave)) save_stats(id)
  2914.  
  2915. // Remove previous tasks
  2916. remove_task(id+TASK_TEAM)
  2917. remove_task(id+TASK_MODEL)
  2918. remove_task(id+TASK_FLASH)
  2919. remove_task(id+TASK_CHARGE)
  2920. remove_task(id+TASK_SPAWN)
  2921. remove_task(id+TASK_BLOOD)
  2922. remove_task(id+TASK_AURA)
  2923. remove_task(id+TASK_BURN)
  2924. remove_task(id+TASK_NVISION)
  2925. remove_task(id+TASK_SHOWHUD)
  2926.  
  2927. if (g_handle_models_on_separate_ent)
  2928. {
  2929. // Remove custom model entities
  2930. fm_remove_model_ents(id)
  2931. }
  2932.  
  2933. // Player left, clear cached flags
  2934. g_isconnected[id] = false
  2935. g_isbot[id] = false
  2936. g_isalive[id] = false
  2937. }
  2938.  
  2939. // Client left
  2940. public fw_ClientDisconnect_Post()
  2941. {
  2942. // Last Zombie Check
  2943. fnCheckLastZombie()
  2944. }
  2945.  
  2946. // Client Kill Forward
  2947. public fw_ClientKill()
  2948. {
  2949. // Prevent players from killing themselves?
  2950. if (get_pcvar_num(cvar_blocksuicide))
  2951. return FMRES_SUPERCEDE;
  2952.  
  2953. return FMRES_IGNORED;
  2954. }
  2955.  
  2956. // Emit Sound Forward
  2957. public fw_EmitSound(id, channel, const sample[], Float:volume, Float:attn, flags, pitch)
  2958. {
  2959. // Block all those unneeeded hostage sounds
  2960. if (sample[0] == 'h' && sample[1] == 'o' && sample[2] == 's' && sample[3] == 't' && sample[4] == 'a' && sample[5] == 'g' && sample[6] == 'e')
  2961. return FMRES_SUPERCEDE;
  2962.  
  2963. // Replace these next sounds for zombies only
  2964. if (!is_user_valid_connected(id) || !g_zombie[id])
  2965. return FMRES_IGNORED;
  2966.  
  2967. static sound[64]
  2968.  
  2969. // Zombie being hit
  2970. if (sample[7] == 'b' && sample[8] == 'h' && sample[9] == 'i' && sample[10] == 't')
  2971. {
  2972. if (g_nemesis[id])
  2973. {
  2974. ArrayGetString(nemesis_pain, random_num(0, ArraySize(nemesis_pain) - 1), sound, charsmax(sound))
  2975. emit_sound(id, channel, sound, volume, attn, flags, pitch)
  2976. }
  2977. else
  2978. {
  2979. ArrayGetString(zombie_pain, random_num(0, ArraySize(zombie_pain) - 1), sound, charsmax(sound))
  2980. emit_sound(id, channel, sound, volume, attn, flags, pitch)
  2981. }
  2982. return FMRES_SUPERCEDE;
  2983. }
  2984.  
  2985. // Zombie attacks with knife
  2986. if (sample[8] == 'k' && sample[9] == 'n' && sample[10] == 'i')
  2987. {
  2988. if (sample[14] == 's' && sample[15] == 'l' && sample[16] == 'a') // slash
  2989. {
  2990. ArrayGetString(zombie_miss_slash, random_num(0, ArraySize(zombie_miss_slash) - 1), sound, charsmax(sound))
  2991. emit_sound(id, channel, sound, volume, attn, flags, pitch)
  2992. return FMRES_SUPERCEDE;
  2993. }
  2994. if (sample[14] == 'h' && sample[15] == 'i' && sample[16] == 't') // hit
  2995. {
  2996. if (sample[17] == 'w') // wall
  2997. {
  2998. ArrayGetString(zombie_miss_wall, random_num(0, ArraySize(zombie_miss_wall) - 1), sound, charsmax(sound))
  2999. emit_sound(id, channel, sound, volume, attn, flags, pitch)
  3000. return FMRES_SUPERCEDE;
  3001. }
  3002. else
  3003. {
  3004. ArrayGetString(zombie_hit_normal, random_num(0, ArraySize(zombie_hit_normal) - 1), sound, charsmax(sound))
  3005. emit_sound(id, channel, sound, volume, attn, flags, pitch)
  3006. return FMRES_SUPERCEDE;
  3007. }
  3008. }
  3009. if (sample[14] == 's' && sample[15] == 't' && sample[16] == 'a') // stab
  3010. {
  3011. ArrayGetString(zombie_hit_stab, random_num(0, ArraySize(zombie_hit_stab) - 1), sound, charsmax(sound))
  3012. emit_sound(id, channel, sound, volume, attn, flags, pitch)
  3013. return FMRES_SUPERCEDE;
  3014. }
  3015. }
  3016.  
  3017. // Zombie dies
  3018. if (sample[7] == 'd' && ((sample[8] == 'i' && sample[9] == 'e') || (sample[8] == 'e' && sample[9] == 'a')))
  3019. {
  3020. ArrayGetString(zombie_die, random_num(0, ArraySize(zombie_die) - 1), sound, charsmax(sound))
  3021. emit_sound(id, channel, sound, volume, attn, flags, pitch)
  3022. return FMRES_SUPERCEDE;
  3023. }
  3024.  
  3025. // Zombie falls off
  3026. if (sample[10] == 'f' && sample[11] == 'a' && sample[12] == 'l' && sample[13] == 'l')
  3027. {
  3028. ArrayGetString(zombie_fall, random_num(0, ArraySize(zombie_fall) - 1), sound, charsmax(sound))
  3029. emit_sound(id, channel, sound, volume, attn, flags, pitch)
  3030. return FMRES_SUPERCEDE;
  3031. }
  3032.  
  3033. return FMRES_IGNORED;
  3034. }
  3035.  
  3036. // Forward Set ClientKey Value -prevent CS from changing player models-
  3037. public fw_SetClientKeyValue(id, const infobuffer[], const key[])
  3038. {
  3039. // Block CS model changes
  3040. if (key[0] == 'm' && key[1] == 'o' && key[2] == 'd' && key[3] == 'e' && key[4] == 'l')
  3041. return FMRES_SUPERCEDE;
  3042.  
  3043. return FMRES_IGNORED;
  3044. }
  3045.  
  3046. // Forward Client User Info Changed -prevent players from changing models-
  3047. public fw_ClientUserInfoChanged(id)
  3048. {
  3049. // Cache player's name
  3050. get_user_name(id, g_playername[id], charsmax(g_playername[]))
  3051.  
  3052. if (!g_handle_models_on_separate_ent)
  3053. {
  3054. // Get current model
  3055. static currentmodel[32]
  3056. fm_cs_get_user_model(id, currentmodel, charsmax(currentmodel))
  3057.  
  3058. // If they're different, set model again
  3059. if (!equal(currentmodel, g_playermodel[id]) && !task_exists(id+TASK_MODEL))
  3060. fm_cs_set_user_model(id+TASK_MODEL)
  3061. }
  3062. }
  3063.  
  3064. // Forward Get Game Description
  3065. public fw_GetGameDescription()
  3066. {
  3067. // Return the mod name so it can be easily identified
  3068. forward_return(FMV_STRING, g_modname)
  3069.  
  3070. return FMRES_SUPERCEDE;
  3071. }
  3072.  
  3073. // Forward Set Model
  3074. public fw_SetModel(entity, const model[])
  3075. {
  3076. // We don't care
  3077. if (strlen(model) < 8)
  3078. return;
  3079.  
  3080. // Remove weapons?
  3081. if (get_pcvar_float(cvar_removedropped) > 0.0)
  3082. {
  3083. // Get entity's classname
  3084. static classname[10]
  3085. pev(entity, pev_classname, classname, charsmax(classname))
  3086.  
  3087. // Check if it's a weapon box
  3088. if (equal(classname, "weaponbox"))
  3089. {
  3090. // They get automatically removed when thinking
  3091. set_pev(entity, pev_nextthink, get_gametime() + get_pcvar_float(cvar_removedropped))
  3092. return;
  3093. }
  3094. }
  3095.  
  3096. // Narrow down our matches a bit
  3097. if (model[7] != 'w' || model[8] != '_')
  3098. return;
  3099.  
  3100. // Get damage time of grenade
  3101. static Float:dmgtime
  3102. pev(entity, pev_dmgtime, dmgtime)
  3103.  
  3104. // Grenade not yet thrown
  3105. if (dmgtime == 0.0)
  3106. return;
  3107.  
  3108. // Get whether grenade's owner is a zombie
  3109. if (g_zombie[pev(entity, pev_owner)])
  3110. {
  3111. if (model[9] == 'h' && model[10] == 'e' && get_pcvar_num(cvar_extrainfbomb)) // Infection Bomb
  3112. {
  3113. // Give it a glow
  3114. fm_set_rendering(entity, kRenderFxGlowShell, 0, 200, 0, kRenderNormal, 16);
  3115.  
  3116. // And a colored trail
  3117. message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
  3118. write_byte(TE_BEAMFOLLOW) // TE id
  3119. write_short(entity) // entity
  3120. write_short(g_trailSpr) // sprite
  3121. write_byte(10) // life
  3122. write_byte(10) // width
  3123. write_byte(0) // r
  3124. write_byte(200) // g
  3125. write_byte(0) // b
  3126. write_byte(200) // brightness
  3127. message_end()
  3128.  
  3129. // Set grenade type on the thrown grenade entity
  3130. set_pev(entity, PEV_NADE_TYPE, NADE_TYPE_INFECTION)
  3131. }
  3132. }
  3133. else if (model[9] == 'h' && model[10] == 'e' && get_pcvar_num(cvar_firegrenades)) // Napalm Grenade
  3134. {
  3135. // Give it a glow
  3136. fm_set_rendering(entity, kRenderFxGlowShell, 200, 0, 0, kRenderNormal, 16);
  3137.  
  3138. // And a colored trail
  3139. message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
  3140. write_byte(TE_BEAMFOLLOW) // TE id
  3141. write_short(entity) // entity
  3142. write_short(g_trailSpr) // sprite
  3143. write_byte(10) // life
  3144. write_byte(10) // width
  3145. write_byte(200) // r
  3146. write_byte(0) // g
  3147. write_byte(0) // b
  3148. write_byte(200) // brightness
  3149. message_end()
  3150.  
  3151. // Set grenade type on the thrown grenade entity
  3152. set_pev(entity, PEV_NADE_TYPE, NADE_TYPE_NAPALM)
  3153. }
  3154. else if (model[9] == 'f' && model[10] == 'l' && get_pcvar_num(cvar_frostgrenades)) // Frost Grenade
  3155. {
  3156. // Give it a glow
  3157. fm_set_rendering(entity, kRenderFxGlowShell, 0, 100, 200, kRenderNormal, 16);
  3158.  
  3159. // And a colored trail
  3160. message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
  3161. write_byte(TE_BEAMFOLLOW) // TE id
  3162. write_short(entity) // entity
  3163. write_short(g_trailSpr) // sprite
  3164. write_byte(10) // life
  3165. write_byte(10) // width
  3166. write_byte(0) // r
  3167. write_byte(100) // g
  3168. write_byte(200) // b
  3169. write_byte(200) // brightness
  3170. message_end()
  3171.  
  3172. // Set grenade type on the thrown grenade entity
  3173. set_pev(entity, PEV_NADE_TYPE, NADE_TYPE_FROST)
  3174. }
  3175. else if (model[9] == 's' && model[10] == 'm' && get_pcvar_num(cvar_flaregrenades)) // Flare
  3176. {
  3177. // Build flare's color
  3178. static rgb[3]
  3179. switch (get_pcvar_num(cvar_flarecolor))
  3180. {
  3181. case 0: // white
  3182. {
  3183. rgb[0] = 255 // r
  3184. rgb[1] = 255 // g
  3185. rgb[2] = 255 // b
  3186. }
  3187. case 1: // red
  3188. {
  3189. rgb[0] = random_num(50,255) // r
  3190. rgb[1] = 0 // g
  3191. rgb[2] = 0 // b
  3192. }
  3193. case 2: // green
  3194. {
  3195. rgb[0] = 0 // r
  3196. rgb[1] = random_num(50,255) // g
  3197. rgb[2] = 0 // b
  3198. }
  3199. case 3: // blue
  3200. {
  3201. rgb[0] = 0 // r
  3202. rgb[1] = 0 // g
  3203. rgb[2] = random_num(50,255) // b
  3204. }
  3205. case 4: // random (all colors)
  3206. {
  3207. rgb[0] = random_num(50,200) // r
  3208. rgb[1] = random_num(50,200) // g
  3209. rgb[2] = random_num(50,200) // b
  3210. }
  3211. case 5: // random (r,g,b)
  3212. {
  3213. switch (random_num(1, 3))
  3214. {
  3215. case 1: // red
  3216. {
  3217. rgb[0] = random_num(50,255) // r
  3218. rgb[1] = 0 // g
  3219. rgb[2] = 0 // b
  3220. }
  3221. case 2: // green
  3222. {
  3223. rgb[0] = 0 // r
  3224. rgb[1] = random_num(50,255) // g
  3225. rgb[2] = 0 // b
  3226. }
  3227. case 3: // blue
  3228. {
  3229. rgb[0] = 0 // r
  3230. rgb[1] = 0 // g
  3231. rgb[2] = random_num(50,255) // b
  3232. }
  3233. }
  3234. }
  3235. }
  3236.  
  3237. // Give it a glow
  3238. fm_set_rendering(entity, kRenderFxGlowShell, rgb[0], rgb[1], rgb[2], kRenderNormal, 16);
  3239.  
  3240. // And a colored trail
  3241. message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
  3242. write_byte(TE_BEAMFOLLOW) // TE id
  3243. write_short(entity) // entity
  3244. write_short(g_trailSpr) // sprite
  3245. write_byte(10) // life
  3246. write_byte(10) // width
  3247. write_byte(rgb[0]) // r
  3248. write_byte(rgb[1]) // g
  3249. write_byte(rgb[2]) // b
  3250. write_byte(200) // brightness
  3251. message_end()
  3252.  
  3253. // Set grenade type on the thrown grenade entity
  3254. set_pev(entity, PEV_NADE_TYPE, NADE_TYPE_FLARE)
  3255.  
  3256. // Set flare color on the thrown grenade entity
  3257. set_pev(entity, PEV_FLARE_COLOR, rgb)
  3258. }
  3259. }
  3260.  
  3261. // Ham Grenade Think Forward
  3262. public fw_ThinkGrenade(entity)
  3263. {
  3264. // Invalid entity
  3265. if (!pev_valid(entity)) return HAM_IGNORED;
  3266.  
  3267. // Get damage time of grenade
  3268. static Float:dmgtime, Float:current_time
  3269. pev(entity, pev_dmgtime, dmgtime)
  3270. current_time = get_gametime()
  3271.  
  3272. // Check if it's time to go off
  3273. if (dmgtime > current_time)
  3274. return HAM_IGNORED;
  3275.  
  3276. // Check if it's one of our custom nades
  3277. switch (pev(entity, PEV_NADE_TYPE))
  3278. {
  3279. case NADE_TYPE_INFECTION: // Infection Bomb
  3280. {
  3281. infection_explode(entity)
  3282. return HAM_SUPERCEDE;
  3283. }
  3284. case NADE_TYPE_NAPALM: // Napalm Grenade
  3285. {
  3286. fire_explode(entity)
  3287. return HAM_SUPERCEDE;
  3288. }
  3289. case NADE_TYPE_FROST: // Frost Grenade
  3290. {
  3291. frost_explode(entity)
  3292. return HAM_SUPERCEDE;
  3293. }
  3294. case NADE_TYPE_FLARE: // Flare
  3295. {
  3296. // Get its duration
  3297. static duration
  3298. duration = pev(entity, PEV_FLARE_DURATION)
  3299.  
  3300. // Already went off, do lighting loop for the duration of PEV_FLARE_DURATION
  3301. if (duration > 0)
  3302. {
  3303. // Check whether this is the last loop
  3304. if (duration == 1)
  3305. {
  3306. // Get rid of the flare entity
  3307. engfunc(EngFunc_RemoveEntity, entity)
  3308. return HAM_SUPERCEDE;
  3309. }
  3310.  
  3311. // Light it up!
  3312. flare_lighting(entity, duration)
  3313.  
  3314. // Set time for next loop
  3315. set_pev(entity, PEV_FLARE_DURATION, --duration)
  3316. set_pev(entity, pev_dmgtime, current_time + 2.0)
  3317. }
  3318. // Light up when it's stopped on ground
  3319. else if ((pev(entity, pev_flags) & FL_ONGROUND) && fm_get_speed(entity) < 10)
  3320. {
  3321. // Flare sound
  3322. static sound[64]
  3323. ArrayGetString(grenade_flare, random_num(0, ArraySize(grenade_flare) - 1), sound, charsmax(sound))
  3324. emit_sound(entity, CHAN_WEAPON, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  3325.  
  3326. // Set duration and start lightning loop on next think
  3327. set_pev(entity, PEV_FLARE_DURATION, 1 + get_pcvar_num(cvar_flareduration)/2)
  3328. set_pev(entity, pev_dmgtime, current_time + 0.1)
  3329. }
  3330. else
  3331. {
  3332. // Delay explosion until we hit ground
  3333. set_pev(entity, pev_dmgtime, current_time + 0.5)
  3334. }
  3335. }
  3336. }
  3337.  
  3338. return HAM_IGNORED;
  3339. }
  3340.  
  3341. // Forward CmdStart
  3342. public fw_CmdStart(id, handle)
  3343. {
  3344. // Not alive
  3345. if (!g_isalive[id])
  3346. return;
  3347.  
  3348. // This logic looks kinda weird, but it should work in theory...
  3349. // p = g_zombie[id], q = g_survivor[id], r = g_cached_customflash
  3350. // ¬(p v q v (¬p ^ r)) <==> ¬p ^ ¬q ^ (p v ¬r)
  3351. if (!g_zombie[id] && !g_survivor[id] && (g_zombie[id] || !g_cached_customflash))
  3352. return;
  3353.  
  3354. // Check if it's a flashlight impulse
  3355. if (get_uc(handle, UC_Impulse) != IMPULSE_FLASHLIGHT)
  3356. return;
  3357.  
  3358. // Block it I say!
  3359. set_uc(handle, UC_Impulse, 0)
  3360.  
  3361. // Should human's custom flashlight be turned on?
  3362. if (!g_zombie[id] && !g_survivor[id] && g_flashbattery[id] > 2 && get_gametime() - g_lastflashtime[id] > 1.2)
  3363. {
  3364. // Prevent calling flashlight too quickly (bugfix)
  3365. g_lastflashtime[id] = get_gametime()
  3366.  
  3367. // Toggle custom flashlight
  3368. g_flashlight[id] = !(g_flashlight[id])
  3369.  
  3370. // Play flashlight toggle sound
  3371. emit_sound(id, CHAN_ITEM, sound_flashlight, 1.0, ATTN_NORM, 0, PITCH_NORM)
  3372.  
  3373. // Update flashlight status on the HUD
  3374. message_begin(MSG_ONE, g_msgFlashlight, _, id)
  3375. write_byte(g_flashlight[id]) // toggle
  3376. write_byte(g_flashbattery[id]) // battery
  3377. message_end()
  3378.  
  3379. // Remove previous tasks
  3380. remove_task(id+TASK_CHARGE)
  3381. remove_task(id+TASK_FLASH)
  3382.  
  3383. // Set the flashlight charge task
  3384. set_task(1.0, "flashlight_charge", id+TASK_CHARGE, _, _, "b")
  3385.  
  3386. // Call our custom flashlight task if enabled
  3387. if (g_flashlight[id]) set_task(0.1, "set_user_flashlight", id+TASK_FLASH, _, _, "b")
  3388. }
  3389. }
  3390.  
  3391. // Forward Player PreThink
  3392. public fw_PlayerPreThink(id)
  3393. {
  3394. // Not alive
  3395. if (!g_isalive[id])
  3396. return;
  3397.  
  3398. // Enable custom buyzone for player during buytime, unless zombie or survivor or time expired
  3399. if (g_cached_buytime > 0.0 && !g_zombie[id] && !g_survivor[id] && (get_gametime() < g_buytime[id] + g_cached_buytime))
  3400. {
  3401. if (pev_valid(g_buyzone_ent))
  3402. dllfunc(DLLFunc_Touch, g_buyzone_ent, id)
  3403. }
  3404.  
  3405. // Silent footsteps for zombies?
  3406. if (g_cached_zombiesilent && g_zombie[id] && !g_nemesis[id])
  3407. set_pev(id, pev_flTimeStepSound, STEPTIME_SILENT)
  3408.  
  3409. // Player frozen?
  3410. if (g_frozen[id])
  3411. {
  3412. set_pev(id, pev_velocity, Float:{0.0,0.0,0.0}) // stop motion
  3413. return; // shouldn't leap while frozen
  3414. }
  3415.  
  3416. // --- Check if player should leap ---
  3417.  
  3418. // Don't allow leap during freezetime
  3419. if (g_freezetime)
  3420. return;
  3421.  
  3422. // Check if proper CVARs are enabled and retrieve leap settings
  3423. static Float:cooldown, Float:current_time
  3424. if (g_zombie[id])
  3425. {
  3426. if (g_nemesis[id])
  3427. {
  3428. if (!g_cached_leapnemesis) return;
  3429. cooldown = g_cached_leapnemesiscooldown
  3430. }
  3431. else
  3432. {
  3433. switch (g_cached_leapzombies)
  3434. {
  3435. case 0: return;
  3436. case 2: if (!g_firstzombie[id]) return;
  3437. case 3: if (!g_lastzombie[id]) return;
  3438. }
  3439. cooldown = g_cached_leapzombiescooldown
  3440. }
  3441. }
  3442. else
  3443. {
  3444. if (g_survivor[id])
  3445. {
  3446. if (!g_cached_leapsurvivor) return;
  3447. cooldown = g_cached_leapsurvivorcooldown
  3448. }
  3449. else return;
  3450. }
  3451.  
  3452. current_time = get_gametime()
  3453.  
  3454. // Cooldown not over yet
  3455. if (current_time - g_lastleaptime[id] < cooldown)
  3456. return;
  3457.  
  3458. // Not doing a longjump (don't perform check for bots, they leap automatically)
  3459. if (!g_isbot[id] && !(pev(id, pev_button) & (IN_JUMP | IN_DUCK) == (IN_JUMP | IN_DUCK)))
  3460. return;
  3461.  
  3462. // Not on ground or not enough speed
  3463. if (!(pev(id, pev_flags) & FL_ONGROUND) || fm_get_speed(id) < 80)
  3464. return;
  3465.  
  3466. static Float:velocity[3]
  3467.  
  3468. // Make velocity vector
  3469. velocity_by_aim(id, g_survivor[id] ? get_pcvar_num(cvar_leapsurvivorforce) : g_nemesis[id] ? get_pcvar_num(cvar_leapnemesisforce) : get_pcvar_num(cvar_leapzombiesforce), velocity)
  3470.  
  3471. // Set custom height
  3472. velocity[2] = g_survivor[id] ? get_pcvar_float(cvar_leapsurvivorheight) : g_nemesis[id] ? get_pcvar_float(cvar_leapnemesisheight) : get_pcvar_float(cvar_leapzombiesheight)
  3473.  
  3474. // Apply the new velocity
  3475. set_pev(id, pev_velocity, velocity)
  3476.  
  3477. // Update last leap time
  3478. g_lastleaptime[id] = current_time
  3479. }
  3480.  
  3481. /*================================================================================
  3482. [Client Commands]
  3483. =================================================================================*/
  3484.  
  3485. // Say "/zpmenu"
  3486. public clcmd_saymenu(id)
  3487. {
  3488. show_menu_game(id) // show game menu
  3489. }
  3490.  
  3491. // Say "/unstuck"
  3492. public clcmd_sayunstuck(id)
  3493. {
  3494. menu_game(id, 3) // try to get unstuck
  3495. }
  3496.  
  3497. // Nightvision toggle
  3498. public clcmd_nightvision(id)
  3499. {
  3500. // Nightvision available to player?
  3501. if (g_nvision[id] || (g_isalive[id] && cs_get_user_nvg(id)))
  3502. {
  3503. // Enable-disable
  3504. g_nvisionenabled[id] = !(g_nvisionenabled[id])
  3505.  
  3506. // Custom nvg?
  3507. if (get_pcvar_num(cvar_customnvg))
  3508. {
  3509. remove_task(id+TASK_NVISION)
  3510. if (g_nvisionenabled[id]) set_task(0.1, "set_user_nvision", id+TASK_NVISION, _, _, "b")
  3511. }
  3512. else
  3513. set_user_gnvision(id, g_nvisionenabled[id])
  3514. }
  3515.  
  3516. return PLUGIN_HANDLED;
  3517. }
  3518.  
  3519. // Weapon Drop
  3520. public clcmd_drop(id)
  3521. {
  3522. // Survivor should stick with its weapon
  3523. if (g_survivor[id])
  3524. return PLUGIN_HANDLED;
  3525.  
  3526. return PLUGIN_CONTINUE;
  3527. }
  3528.  
  3529. // Buy BP Ammo
  3530. public clcmd_buyammo(id)
  3531. {
  3532. // Not alive or infinite ammo setting enabled
  3533. if (!g_isalive[id] || get_pcvar_num(cvar_infammo))
  3534. return PLUGIN_HANDLED;
  3535.  
  3536. // Not human
  3537. if (g_zombie[id])
  3538. {
  3539. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_HUMAN_ONLY")
  3540. return PLUGIN_HANDLED;
  3541. }
  3542.  
  3543. // Custom buytime enabled and human player standing in buyzone, allow buying weapon's ammo normally instead
  3544. if (g_cached_buytime > 0.0 && !g_survivor[id] && (get_gametime() < g_buytime[id] + g_cached_buytime) && cs_get_user_buyzone(id))
  3545. return PLUGIN_CONTINUE;
  3546.  
  3547. // Not enough ammo packs
  3548. if (g_ammopacks[id] < 1)
  3549. {
  3550. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "NOT_ENOUGH_AMMO")
  3551. return PLUGIN_HANDLED;
  3552. }
  3553.  
  3554. // Get user weapons
  3555. static weapons[32], num, i, currentammo, weaponid, refilled
  3556. num = 0 // reset passed weapons count (bugfix)
  3557. refilled = false
  3558. get_user_weapons(id, weapons, num)
  3559.  
  3560. // Loop through them and give the right ammo type
  3561. for (i = 0; i < num; i++)
  3562. {
  3563. // Prevents re-indexing the array
  3564. weaponid = weapons[i]
  3565.  
  3566. // Primary and secondary only
  3567. if (MAXBPAMMO[weaponid] > 2)
  3568. {
  3569. // Get current ammo of the weapon
  3570. currentammo = cs_get_user_bpammo(id, weaponid)
  3571.  
  3572. // Give additional ammo
  3573. ExecuteHamB(Ham_GiveAmmo, id, BUYAMMO[weaponid], AMMOTYPE[weaponid], MAXBPAMMO[weaponid])
  3574.  
  3575. // Check whether we actually refilled the weapon's ammo
  3576. if (cs_get_user_bpammo(id, weaponid) - currentammo > 0) refilled = true
  3577. }
  3578. }
  3579.  
  3580. // Weapons already have full ammo
  3581. if (!refilled) return PLUGIN_HANDLED;
  3582.  
  3583. // Deduce ammo packs, play clip purchase sound, and notify player
  3584. g_ammopacks[id]--
  3585. emit_sound(id, CHAN_ITEM, sound_buyammo, 1.0, ATTN_NORM, 0, PITCH_NORM)
  3586. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "AMMO_BOUGHT")
  3587.  
  3588. return PLUGIN_HANDLED;
  3589. }
  3590.  
  3591. // Block Team Change
  3592. public clcmd_changeteam(id)
  3593. {
  3594. static team
  3595. team = fm_cs_get_user_team(id)
  3596.  
  3597. // Unless it's a spectator joining the game
  3598. if (team == FM_CS_TEAM_SPECTATOR || team == FM_CS_TEAM_UNASSIGNED)
  3599. return PLUGIN_CONTINUE;
  3600.  
  3601. // Pressing 'M' (chooseteam) ingame should show the main menu instead
  3602. show_menu_game(id)
  3603. return PLUGIN_HANDLED;
  3604. }
  3605.  
  3606. /*================================================================================
  3607. [Menus]
  3608. =================================================================================*/
  3609.  
  3610. // Game Menu
  3611. show_menu_game(id)
  3612. {
  3613. // Player disconnected?
  3614. if (!g_isconnected[id])
  3615. return;
  3616.  
  3617. static menu[250], len, userflags
  3618. len = 0
  3619. userflags = get_user_flags(id)
  3620.  
  3621. // Title
  3622. len += formatex(menu[len], charsmax(menu) - len, "\y%s^n^n", g_modname)
  3623.  
  3624. // 1. Buy weapons
  3625. if (get_pcvar_num(cvar_buycustom))
  3626. len += formatex(menu[len], charsmax(menu) - len, "\r1.\r %L^n", id, "MENU_BUY")
  3627. else
  3628. len += formatex(menu[len], charsmax(menu) - len, "\d1. %L^n", id, "MENU_BUY")
  3629.  
  3630. // 2. Extra items
  3631. if (get_pcvar_num(cvar_extraitems) && g_isalive[id])
  3632. len += formatex(menu[len], charsmax(menu) - len, "\r2.\w %L^n", id, "MENU_EXTRABUY")
  3633. else
  3634. len += formatex(menu[len], charsmax(menu) - len, "\d2. %L^n", id, "MENU_EXTRABUY")
  3635.  
  3636. // 3. Zombie class
  3637. if (get_pcvar_num(cvar_zclasses))
  3638. len += formatex(menu[len], charsmax(menu) - len, "\r3.\y %L^n", id,"MENU_ZCLASS")
  3639. else
  3640. len += formatex(menu[len], charsmax(menu) - len, "\d3. %L^n", id,"MENU_ZCLASS")
  3641.  
  3642. // 4. Unstuck
  3643. if (g_isalive[id])
  3644. len += formatex(menu[len], charsmax(menu) - len, "\r4.\w %L^n", id, "MENU_UNSTUCK")
  3645. else
  3646. len += formatex(menu[len], charsmax(menu) - len, "\d4. %L^n", id, "MENU_UNSTUCK")
  3647.  
  3648. // 5. Help
  3649. len += formatex(menu[len], charsmax(menu) - len, "\r5.\r %L^n^n", id, "MENU_INFO")
  3650.  
  3651. // 6. Join spec
  3652. if (!g_isalive[id] || !get_pcvar_num(cvar_blocksuicide) || (userflags & g_access_flag[ACCESS_ADMIN_MENU]))
  3653. len += formatex(menu[len], charsmax(menu) - len, "\r6.\w %L^n^n", id, "MENU_SPECTATOR")
  3654. else
  3655. len += formatex(menu[len], charsmax(menu) - len, "\d6. %L^n^n", id, "MENU_SPECTATOR")
  3656.  
  3657. //7. Vip menu
  3658. if (g_isalive[id])
  3659. len += formatex(menu[len], charsmax(menu) - len, "\y7.\r VIP Menu^n^n")
  3660. else
  3661. len += formatex(menu[len], charsmax(menu) - len, "\r7.\d VIP Menu^n^n")
  3662.  
  3663. // 9. Admin menu
  3664. if (userflags & g_access_flag[ACCESS_ADMIN_MENU])
  3665. len += formatex(menu[len], charsmax(menu) - len, "\r9.\y %L", id, "MENU_ADMIN")
  3666. else
  3667. len += formatex(menu[len], charsmax(menu) - len, "\d9. %L", id, "MENU_ADMIN")
  3668.  
  3669. // 0. Exit
  3670. len += formatex(menu[len], charsmax(menu) - len, "^n^n\r0.\r %L", id, "MENU_EXIT")
  3671.  
  3672. // Fix for AMXX custom menus
  3673. if (pev_valid(id) == PDATA_SAFE)
  3674. set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
  3675.  
  3676. show_menu(id, KEYSMENU, menu, -1, "Game Menu")
  3677. }
  3678.  
  3679. // Buy Menu 1
  3680. public show_menu_buy1(taskid)
  3681. {
  3682. // Get player's id
  3683. static id
  3684. (taskid > g_maxplayers) ? (id = ID_SPAWN) : (id = taskid);
  3685.  
  3686. // Player dead?
  3687. if (!g_isalive[id])
  3688. return;
  3689.  
  3690. // Zombies or survivors get no guns
  3691. if (g_zombie[id] || g_survivor[id])
  3692. return;
  3693.  
  3694. // Bots pick their weapons randomly / Random weapons setting enabled
  3695. if (get_pcvar_num(cvar_randweapons) || g_isbot[id])
  3696. {
  3697. buy_primary_weapon(id, random_num(0, ArraySize(g_primary_items) - 1))
  3698. menu_buy2(id, random_num(0, ArraySize(g_secondary_items) - 1))
  3699. return;
  3700. }
  3701.  
  3702. // Automatic selection enabled for player and menu called on spawn event
  3703. if (WPN_AUTO_ON && taskid > g_maxplayers)
  3704. {
  3705. buy_primary_weapon(id, WPN_AUTO_PRI)
  3706. menu_buy2(id, WPN_AUTO_SEC)
  3707. return;
  3708. }
  3709.  
  3710. static menu[300], len, weap, maxloops
  3711. len = 0
  3712. maxloops = min(WPN_STARTID+7, WPN_MAXIDS)
  3713.  
  3714. // Title
  3715. len += formatex(menu[len], charsmax(menu) - len, "\y%L \r[%d-%d]^n^n", id, "MENU_BUY1_TITLE", WPN_STARTID+1, min(WPN_STARTID+7, WPN_MAXIDS))
  3716.  
  3717. // 1-7. Weapon List
  3718. for (weap = WPN_STARTID; weap < maxloops; weap++)
  3719. len += formatex(menu[len], charsmax(menu) - len, "\r%d.\w %s^n", weap-WPN_STARTID+1, WEAPONNAMES[ArrayGetCell(g_primary_weaponids, weap)])
  3720.  
  3721. // 8. Auto Select
  3722. len += formatex(menu[len], charsmax(menu) - len, "^n\r8.\w %L \y[%L]", id, "MENU_AUTOSELECT", id, (WPN_AUTO_ON) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  3723.  
  3724. // 9. Next/Back - 0. Exit
  3725. len += formatex(menu[len], charsmax(menu) - len, "^n^n\r9.\w %L/%L^n^n\r0.\w %L", id, "MENU_NEXT", id, "MENU_BACK", id, "MENU_EXIT")
  3726.  
  3727. // Fix for AMXX custom menus
  3728. if (pev_valid(id) == PDATA_SAFE)
  3729. set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
  3730.  
  3731. show_menu(id, KEYSMENU, menu, -1, "Buy Menu 1")
  3732. }
  3733.  
  3734. // Buy Menu 2
  3735. show_menu_buy2(id)
  3736. {
  3737. // Player dead?
  3738. if (!g_isalive[id])
  3739. return;
  3740.  
  3741. static menu[250], len, weap, maxloops
  3742. len = 0
  3743. maxloops = ArraySize(g_secondary_items)
  3744.  
  3745. // Title
  3746. len += formatex(menu[len], charsmax(menu) - len, "\y%L^n", id, "MENU_BUY2_TITLE")
  3747.  
  3748. // 1-6. Weapon List
  3749. for (weap = 0; weap < maxloops; weap++)
  3750. len += formatex(menu[len], charsmax(menu) - len, "^n\r%d.\w %s", weap+1, WEAPONNAMES[ArrayGetCell(g_secondary_weaponids, weap)])
  3751.  
  3752. // 8. Auto Select
  3753. len += formatex(menu[len], charsmax(menu) - len, "^n^n\r8.\w %L \y[%L]", id, "MENU_AUTOSELECT", id, (WPN_AUTO_ON) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  3754.  
  3755. // 0. Exit
  3756. len += formatex(menu[len], charsmax(menu) - len, "^n^n\r0.\w %L", id, "MENU_EXIT")
  3757.  
  3758. // Fix for AMXX custom menus
  3759. if (pev_valid(id) == PDATA_SAFE)
  3760. set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
  3761.  
  3762. show_menu(id, KEYSMENU, menu, -1, "Buy Menu 2")
  3763. }
  3764.  
  3765. // Extra Items Menu
  3766. show_menu_extras(id)
  3767. {
  3768. // Player dead?
  3769. if (!g_isalive[id])
  3770. return;
  3771.  
  3772. static menuid, menu[128], item, team, buffer[32]
  3773.  
  3774. // Title
  3775. formatex(menu, charsmax(menu), "%L [%L]\r", id, "MENU_EXTRA_TITLE", id, g_zombie[id] ? g_nemesis[id] ? "CLASS_NEMESIS" : "CLASS_ZOMBIE" : g_survivor[id] ? "CLASS_SURVIVOR" : "CLASS_HUMAN")
  3776. menuid = menu_create(menu, "menu_extras")
  3777.  
  3778. // Item List
  3779. for (item = 0; item < g_extraitem_i; item++)
  3780. {
  3781. // Retrieve item's team
  3782. team = ArrayGetCell(g_extraitem_team, item)
  3783.  
  3784. // Item not available to player's team/class
  3785. if ((g_zombie[id] && !g_nemesis[id] && !(team & ZP_TEAM_ZOMBIE)) || (!g_zombie[id] && !g_survivor[id] && !(team & ZP_TEAM_HUMAN)) || (g_nemesis[id] && !(team & ZP_TEAM_NEMESIS)) || (g_survivor[id] && !(team & ZP_TEAM_SURVIVOR)))
  3786. continue;
  3787.  
  3788. // Check if it's one of the hardcoded items, check availability, set translated caption
  3789. switch (item)
  3790. {
  3791. case EXTRA_NVISION:
  3792. {
  3793. if (!get_pcvar_num(cvar_extranvision)) continue;
  3794. formatex(buffer, charsmax(buffer), "%L", id, "MENU_EXTRA1")
  3795. }
  3796. case EXTRA_ANTIDOTE:
  3797. {
  3798. if (!get_pcvar_num(cvar_extraantidote) || g_antidotecounter >= get_pcvar_num(cvar_antidotelimit)) continue;
  3799. formatex(buffer, charsmax(buffer), "%L", id, "MENU_EXTRA2")
  3800. }
  3801. case EXTRA_MADNESS:
  3802. {
  3803. if (!get_pcvar_num(cvar_extramadness) || g_madnesscounter >= get_pcvar_num(cvar_madnesslimit)) continue;
  3804. formatex(buffer, charsmax(buffer), "%L", id, "MENU_EXTRA3")
  3805. }
  3806. case EXTRA_INFBOMB:
  3807. {
  3808. if (!get_pcvar_num(cvar_extrainfbomb) || g_infbombcounter >= get_pcvar_num(cvar_infbomblimit)) continue;
  3809. formatex(buffer, charsmax(buffer), "%L", id, "MENU_EXTRA4")
  3810. }
  3811. default:
  3812. {
  3813. if (item >= EXTRA_WEAPONS_STARTID && item <= EXTRAS_CUSTOM_STARTID-1 && !get_pcvar_num(cvar_extraweapons)) continue;
  3814. ArrayGetString(g_extraitem_name, item, buffer, charsmax(buffer))
  3815. }
  3816. }
  3817.  
  3818. // Add Item Name and Cost
  3819. formatex(menu, charsmax(menu), "%s \y%d %L", buffer, ArrayGetCell(g_extraitem_cost, item), id, "AMMO_PACKS2")
  3820. buffer[0] = item
  3821. buffer[1] = 0
  3822. menu_additem(menuid, menu, buffer)
  3823. }
  3824.  
  3825. // No items to display?
  3826. if (menu_items(menuid) <= 0)
  3827. {
  3828. zp_colored_print(id, "^x04[ZP]^x01 %L", id ,"CMD_NOT_EXTRAS")
  3829. menu_destroy(menuid)
  3830. return;
  3831. }
  3832.  
  3833. // Back - Next - Exit
  3834. formatex(menu, charsmax(menu), "%L", id, "MENU_BACK")
  3835. menu_setprop(menuid, MPROP_BACKNAME, menu)
  3836. formatex(menu, charsmax(menu), "%L", id, "MENU_NEXT")
  3837. menu_setprop(menuid, MPROP_NEXTNAME, menu)
  3838. formatex(menu, charsmax(menu), "%L", id, "MENU_EXIT")
  3839. menu_setprop(menuid, MPROP_EXITNAME, menu)
  3840.  
  3841. // If remembered page is greater than number of pages, clamp down the value
  3842. MENU_PAGE_EXTRAS = min(MENU_PAGE_EXTRAS, menu_pages(menuid)-1)
  3843.  
  3844. // Fix for AMXX custom menus
  3845. if (pev_valid(id) == PDATA_SAFE)
  3846. set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
  3847.  
  3848. menu_display(id, menuid, MENU_PAGE_EXTRAS)
  3849. }
  3850.  
  3851. // Zombie Class Menu
  3852. public show_menu_zclass(id)
  3853. {
  3854. // Player disconnected
  3855. if (!g_isconnected[id])
  3856. return;
  3857.  
  3858. // Bots pick their zombie class randomly
  3859. if (g_isbot[id])
  3860. {
  3861. g_zombieclassnext[id] = random_num(0, g_zclass_i - 1)
  3862. return;
  3863. }
  3864.  
  3865. static menuid, menu[128], class, buffer[32], buffer2[32]
  3866.  
  3867. // Title
  3868. formatex(menu, charsmax(menu), "%L\r", id, "MENU_ZCLASS_TITLE")
  3869. menuid = menu_create(menu, "menu_zclass")
  3870.  
  3871. // Class List
  3872. for (class = 0; class < g_zclass_i; class++)
  3873. {
  3874. // Retrieve name and info
  3875. ArrayGetString(g_zclass_name, class, buffer, charsmax(buffer))
  3876. ArrayGetString(g_zclass_info, class, buffer2, charsmax(buffer2))
  3877.  
  3878. // Add to menu
  3879. if (class == g_zombieclassnext[id])
  3880. formatex(menu, charsmax(menu), "\d%s %s", buffer, buffer2)
  3881. else
  3882. formatex(menu, charsmax(menu), "%s \y%s", buffer, buffer2)
  3883.  
  3884. buffer[0] = class
  3885. buffer[1] = 0
  3886. menu_additem(menuid, menu, buffer)
  3887. }
  3888.  
  3889. // Back - Next - Exit
  3890. formatex(menu, charsmax(menu), "%L", id, "MENU_BACK")
  3891. menu_setprop(menuid, MPROP_BACKNAME, menu)
  3892. formatex(menu, charsmax(menu), "%L", id, "MENU_NEXT")
  3893. menu_setprop(menuid, MPROP_NEXTNAME, menu)
  3894. formatex(menu, charsmax(menu), "%L", id, "MENU_EXIT")
  3895. menu_setprop(menuid, MPROP_EXITNAME, menu)
  3896.  
  3897. // If remembered page is greater than number of pages, clamp down the value
  3898. MENU_PAGE_ZCLASS = min(MENU_PAGE_ZCLASS, menu_pages(menuid)-1)
  3899.  
  3900. // Fix for AMXX custom menus
  3901. if (pev_valid(id) == PDATA_SAFE)
  3902. set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
  3903.  
  3904. menu_display(id, menuid, MENU_PAGE_ZCLASS)
  3905. }
  3906.  
  3907. // Help Menu
  3908. show_menu_info(id)
  3909. {
  3910. // Player disconnected?
  3911. if (!g_isconnected[id])
  3912. return;
  3913.  
  3914. static menu[150]
  3915.  
  3916. formatex(menu, charsmax(menu), "\y%L^n^n\r1.\w %L^n\r2.\w %L^n\r3.\w %L^n\r4.\w %L^n^n\r0.\w %L", id, "MENU_INFO_TITLE", id, "MENU_INFO1", id,"MENU_INFO2", id,"MENU_INFO3", id,"MENU_INFO4", id, "MENU_EXIT")
  3917.  
  3918. // Fix for AMXX custom menus
  3919. if (pev_valid(id) == PDATA_SAFE)
  3920. set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
  3921.  
  3922. show_menu(id, KEYSMENU, menu, -1, "Mod Info")
  3923. }
  3924.  
  3925. // Admin Menu
  3926. show_menu_admin(id)
  3927. {
  3928. // Player disconnected?
  3929. if (!g_isconnected[id])
  3930. return;
  3931.  
  3932. static menu[250], len, userflags
  3933. len = 0
  3934. userflags = get_user_flags(id)
  3935.  
  3936. // Title
  3937. len += formatex(menu[len], charsmax(menu) - len, "\y%L^n^n", id, "MENU_ADMIN_TITLE")
  3938.  
  3939. // 1. Zombiefy/Humanize command
  3940. if (userflags & (g_access_flag[ACCESS_MODE_INFECTION] | g_access_flag[ACCESS_MAKE_ZOMBIE] | g_access_flag[ACCESS_MAKE_HUMAN]))
  3941. len += formatex(menu[len], charsmax(menu) - len, "\r1.\w %L^n", id, "MENU_ADMIN1")
  3942. else
  3943. len += formatex(menu[len], charsmax(menu) - len, "\d1. %L^n", id, "MENU_ADMIN1")
  3944.  
  3945. // 2. Nemesis command
  3946. if (userflags & (g_access_flag[ACCESS_MODE_NEMESIS] | g_access_flag[ACCESS_MAKE_NEMESIS]))
  3947. len += formatex(menu[len], charsmax(menu) - len, "\r2.\w %L^n", id, "MENU_ADMIN2")
  3948. else
  3949. len += formatex(menu[len], charsmax(menu) - len, "\d2. %L^n", id, "MENU_ADMIN2")
  3950.  
  3951. // 3. Survivor command
  3952. if (userflags & (g_access_flag[ACCESS_MODE_SURVIVOR] | g_access_flag[ACCESS_MAKE_SURVIVOR]))
  3953. len += formatex(menu[len], charsmax(menu) - len, "\r3.\w %L^n", id, "MENU_ADMIN3")
  3954. else
  3955. len += formatex(menu[len], charsmax(menu) - len, "\d3. %L^n", id, "MENU_ADMIN3")
  3956.  
  3957. // 4. Respawn command
  3958. if (userflags & g_access_flag[ACCESS_RESPAWN_PLAYERS])
  3959. len += formatex(menu[len], charsmax(menu) - len, "\r4.\w %L^n", id, "MENU_ADMIN4")
  3960. else
  3961. len += formatex(menu[len], charsmax(menu) - len, "\d4. %L^n", id, "MENU_ADMIN4")
  3962.  
  3963. // 5. Swarm mode command
  3964. if ((userflags & g_access_flag[ACCESS_MODE_SWARM]) && allowed_swarm())
  3965. len += formatex(menu[len], charsmax(menu) - len, "\r5.\w %L^n", id, "MENU_ADMIN5")
  3966. else
  3967. len += formatex(menu[len], charsmax(menu) - len, "\d5. %L^n", id, "MENU_ADMIN5")
  3968.  
  3969. // 6. Multi infection command
  3970. if ((userflags & g_access_flag[ACCESS_MODE_MULTI]) && allowed_multi())
  3971. len += formatex(menu[len], charsmax(menu) - len, "\r6.\w %L^n", id, "MENU_ADMIN6")
  3972. else
  3973. len += formatex(menu[len], charsmax(menu) - len, "\d6. %L^n", id, "MENU_ADMIN6")
  3974.  
  3975. // 7. Plague mode command
  3976. if ((userflags & g_access_flag[ACCESS_MODE_PLAGUE]) && allowed_plague())
  3977. len += formatex(menu[len], charsmax(menu) - len, "\r7.\w %L^n", id, "MENU_ADMIN7")
  3978. else
  3979. len += formatex(menu[len], charsmax(menu) - len, "\d7. %L^n", id, "MENU_ADMIN7")
  3980.  
  3981. // 0. Exit
  3982. len += formatex(menu[len], charsmax(menu) - len, "^n\r0.\w %L", id, "MENU_EXIT")
  3983.  
  3984. // Fix for AMXX custom menus
  3985. if (pev_valid(id) == PDATA_SAFE)
  3986. set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
  3987.  
  3988. show_menu(id, KEYSMENU, menu, -1, "Admin Menu")
  3989. }
  3990.  
  3991. // Player List Menu
  3992. show_menu_player_list(id)
  3993. {
  3994. // Player disconnected?
  3995. if (!g_isconnected[id])
  3996. return;
  3997.  
  3998. static menuid, menu[128], player, userflags, buffer[2]
  3999. userflags = get_user_flags(id)
  4000.  
  4001. // Title
  4002. switch (PL_ACTION)
  4003. {
  4004. case ACTION_ZOMBIEFY_HUMANIZE: formatex(menu, charsmax(menu), "%L\r", id, "MENU_ADMIN1")
  4005. case ACTION_MAKE_NEMESIS: formatex(menu, charsmax(menu), "%L\r", id, "MENU_ADMIN2")
  4006. case ACTION_MAKE_SURVIVOR: formatex(menu, charsmax(menu), "%L\r", id, "MENU_ADMIN3")
  4007. case ACTION_RESPAWN_PLAYER: formatex(menu, charsmax(menu), "%L\r", id, "MENU_ADMIN4")
  4008. }
  4009. menuid = menu_create(menu, "menu_player_list")
  4010.  
  4011. // Player List
  4012. for (player = 0; player <= g_maxplayers; player++)
  4013. {
  4014. // Skip if not connected
  4015. if (!g_isconnected[player])
  4016. continue;
  4017.  
  4018. // Format text depending on the action to take
  4019. switch (PL_ACTION)
  4020. {
  4021. case ACTION_ZOMBIEFY_HUMANIZE: // Zombiefy/Humanize command
  4022. {
  4023. if (g_zombie[player])
  4024. {
  4025. if (allowed_human(player) && (userflags & g_access_flag[ACCESS_MAKE_HUMAN]))
  4026. formatex(menu, charsmax(menu), "%s \r[%L]", g_playername[player], id, g_nemesis[player] ? "CLASS_NEMESIS" : "CLASS_ZOMBIE")
  4027. else
  4028. formatex(menu, charsmax(menu), "\d%s [%L]", g_playername[player], id, g_nemesis[player] ? "CLASS_NEMESIS" : "CLASS_ZOMBIE")
  4029. }
  4030. else
  4031. {
  4032. if (allowed_zombie(player) && (g_newround ? (userflags & g_access_flag[ACCESS_MODE_INFECTION]) : (userflags & g_access_flag[ACCESS_MAKE_ZOMBIE])))
  4033. formatex(menu, charsmax(menu), "%s \y[%L]", g_playername[player], id, g_survivor[player] ? "CLASS_SURVIVOR" : "CLASS_HUMAN")
  4034. else
  4035. formatex(menu, charsmax(menu), "\d%s [%L]", g_playername[player], id, g_survivor[player] ? "CLASS_SURVIVOR" : "CLASS_HUMAN")
  4036. }
  4037. }
  4038. case ACTION_MAKE_NEMESIS: // Nemesis command
  4039. {
  4040. if (allowed_nemesis(player) && (g_newround ? (userflags & g_access_flag[ACCESS_MODE_NEMESIS]) : (userflags & g_access_flag[ACCESS_MAKE_NEMESIS])))
  4041. {
  4042. if (g_zombie[player])
  4043. formatex(menu, charsmax(menu), "%s \r[%L]", g_playername[player], id, g_nemesis[player] ? "CLASS_NEMESIS" : "CLASS_ZOMBIE")
  4044. else
  4045. formatex(menu, charsmax(menu), "%s \y[%L]", g_playername[player], id, g_survivor[player] ? "CLASS_SURVIVOR" : "CLASS_HUMAN")
  4046. }
  4047. else
  4048. formatex(menu, charsmax(menu), "\d%s [%L]", g_playername[player], id, g_zombie[player] ? g_nemesis[player] ? "CLASS_NEMESIS" : "CLASS_ZOMBIE" : g_survivor[player] ? "CLASS_SURVIVOR" : "CLASS_HUMAN")
  4049. }
  4050. case ACTION_MAKE_SURVIVOR: // Survivor command
  4051. {
  4052. if (allowed_survivor(player) && (g_newround ? (userflags & g_access_flag[ACCESS_MODE_SURVIVOR]) : (userflags & g_access_flag[ACCESS_MAKE_SURVIVOR])))
  4053. {
  4054. if (g_zombie[player])
  4055. formatex(menu, charsmax(menu), "%s \r[%L]", g_playername[player], id, g_nemesis[player] ? "CLASS_NEMESIS" : "CLASS_ZOMBIE")
  4056. else
  4057. formatex(menu, charsmax(menu), "%s \y[%L]", g_playername[player], id, g_survivor[player] ? "CLASS_SURVIVOR" : "CLASS_HUMAN")
  4058. }
  4059. else
  4060. formatex(menu, charsmax(menu), "\d%s [%L]", g_playername[player], id, g_zombie[player] ? g_nemesis[player] ? "CLASS_NEMESIS" : "CLASS_ZOMBIE" : g_survivor[player] ? "CLASS_SURVIVOR" : "CLASS_HUMAN")
  4061. }
  4062. case ACTION_RESPAWN_PLAYER: // Respawn command
  4063. {
  4064. if (allowed_respawn(player) && (userflags & g_access_flag[ACCESS_RESPAWN_PLAYERS]))
  4065. formatex(menu, charsmax(menu), "%s", g_playername[player])
  4066. else
  4067. formatex(menu, charsmax(menu), "\d%s", g_playername[player])
  4068. }
  4069. }
  4070.  
  4071. // Add player
  4072. buffer[0] = player
  4073. buffer[1] = 0
  4074. menu_additem(menuid, menu, buffer)
  4075. }
  4076.  
  4077. // Back - Next - Exit
  4078. formatex(menu, charsmax(menu), "%L", id, "MENU_BACK")
  4079. menu_setprop(menuid, MPROP_BACKNAME, menu)
  4080. formatex(menu, charsmax(menu), "%L", id, "MENU_NEXT")
  4081. menu_setprop(menuid, MPROP_NEXTNAME, menu)
  4082. formatex(menu, charsmax(menu), "%L", id, "MENU_EXIT")
  4083. menu_setprop(menuid, MPROP_EXITNAME, menu)
  4084.  
  4085. // If remembered page is greater than number of pages, clamp down the value
  4086. MENU_PAGE_PLAYERS = min(MENU_PAGE_PLAYERS, menu_pages(menuid)-1)
  4087.  
  4088. // Fix for AMXX custom menus
  4089. if (pev_valid(id) == PDATA_SAFE)
  4090. set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
  4091.  
  4092. menu_display(id, menuid, MENU_PAGE_PLAYERS)
  4093. }
  4094.  
  4095. /*================================================================================
  4096. [Menu Handlers]
  4097. =================================================================================*/
  4098.  
  4099. // Game Menu
  4100. public menu_game(id, key)
  4101. {
  4102. // Player disconnected?
  4103. if (!g_isconnected[id])
  4104. return PLUGIN_HANDLED;
  4105.  
  4106. switch (key)
  4107. {
  4108. case 0: // Buy Weapons
  4109. {
  4110. // Custom buy menus enabled?
  4111. if (get_pcvar_num(cvar_buycustom))
  4112. {
  4113. // Disable the remember selection setting
  4114. WPN_AUTO_ON = 0
  4115. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "BUY_ENABLED")
  4116.  
  4117. // Show menu if player hasn't yet bought anything
  4118. if (g_canbuy[id]) show_menu_buy1(id)
  4119. }
  4120. else
  4121. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
  4122. }
  4123. case 1: // Extra Items
  4124. {
  4125. // Extra items enabled?
  4126. if (get_pcvar_num(cvar_extraitems))
  4127. {
  4128. // Check whether the player is able to buy anything
  4129. if (g_isalive[id])
  4130. show_menu_extras(id)
  4131. else
  4132. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
  4133. }
  4134. else
  4135. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_EXTRAS")
  4136. }
  4137. case 2: // Zombie Classes
  4138. {
  4139. // Zombie classes enabled?
  4140. if (get_pcvar_num(cvar_zclasses))
  4141. show_menu_zclass(id)
  4142. else
  4143. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ZCLASSES")
  4144. }
  4145. case 3: // Unstuck
  4146. {
  4147. // Check if player is stuck
  4148. if (g_isalive[id])
  4149. {
  4150. if (is_player_stuck(id))
  4151. {
  4152. // Move to an initial spawn
  4153. if (get_pcvar_num(cvar_randspawn))
  4154. do_random_spawn(id) // random spawn (including CSDM)
  4155. else
  4156. do_random_spawn(id, 1) // regular spawn
  4157. }
  4158. else
  4159. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_STUCK")
  4160. }
  4161. else
  4162. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
  4163. }
  4164. case 4: // Help Menu
  4165. {
  4166. show_menu_info(id)
  4167. }
  4168. case 5: // Join Spectator
  4169. {
  4170. // Player alive?
  4171. if (g_isalive[id])
  4172. {
  4173. // Prevent abuse by non-admins if block suicide setting is enabled
  4174. if (get_pcvar_num(cvar_blocksuicide) && !(get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MENU]))
  4175. {
  4176. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
  4177. return PLUGIN_HANDLED;
  4178. }
  4179.  
  4180. // Check that we still have both humans and zombies to keep the round going
  4181. check_round(id)
  4182.  
  4183. // Kill him before he switches team
  4184. dllfunc(DLLFunc_ClientKill, id)
  4185. }
  4186.  
  4187. // Temporarily save player stats?
  4188. if (get_pcvar_num(cvar_statssave)) save_stats(id)
  4189.  
  4190. // Remove previous tasks
  4191. remove_task(id+TASK_TEAM)
  4192. remove_task(id+TASK_MODEL)
  4193. remove_task(id+TASK_FLASH)
  4194. remove_task(id+TASK_CHARGE)
  4195. remove_task(id+TASK_SPAWN)
  4196. remove_task(id+TASK_BLOOD)
  4197. remove_task(id+TASK_AURA)
  4198. remove_task(id+TASK_BURN)
  4199.  
  4200. // Then move him to the spectator team
  4201. fm_cs_set_user_team(id, FM_CS_TEAM_SPECTATOR)
  4202. fm_user_team_update(id)
  4203.  
  4204. }
  4205. case 6: {
  4206. if (g_isalive[id])
  4207. client_cmd(id, "say /vm"); // VIP menu
  4208. else
  4209. zp_colored_print(id, "^x03[VIP Menu]^x01 %L", id, "CMD_NOT")
  4210. }
  4211. case 8: // Admin Menu
  4212. {
  4213. // Check if player has the required access
  4214. if (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MENU])
  4215. show_menu_admin(id)
  4216. else
  4217. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
  4218. }
  4219. }
  4220.  
  4221. return PLUGIN_HANDLED;
  4222. }
  4223.  
  4224. // Buy Menu 1
  4225. public menu_buy1(id, key)
  4226. {
  4227. // Player dead?
  4228. if (!g_isalive[id])
  4229. return PLUGIN_HANDLED;
  4230.  
  4231. // Zombies or survivors get no guns
  4232. if (g_zombie[id] || g_survivor[id])
  4233. return PLUGIN_HANDLED;
  4234.  
  4235. // Special keys / weapon list exceeded
  4236. if (key >= MENU_KEY_AUTOSELECT || WPN_SELECTION >= WPN_MAXIDS)
  4237. {
  4238. switch (key)
  4239. {
  4240. case MENU_KEY_AUTOSELECT: // toggle auto select
  4241. {
  4242. WPN_AUTO_ON = 1 - WPN_AUTO_ON
  4243. }
  4244. case MENU_KEY_NEXT: // next/back
  4245. {
  4246. if (WPN_STARTID+7 < WPN_MAXIDS)
  4247. WPN_STARTID += 7
  4248. else
  4249. WPN_STARTID = 0
  4250. }
  4251. case MENU_KEY_EXIT: // exit
  4252. {
  4253. return PLUGIN_HANDLED;
  4254. }
  4255. }
  4256.  
  4257. // Show buy menu again
  4258. show_menu_buy1(id)
  4259. return PLUGIN_HANDLED;
  4260. }
  4261.  
  4262. // Store selected weapon id
  4263. WPN_AUTO_PRI = WPN_SELECTION
  4264.  
  4265. // Buy primary weapon
  4266. buy_primary_weapon(id, WPN_AUTO_PRI)
  4267.  
  4268. // Show pistols menu
  4269. show_menu_buy2(id)
  4270.  
  4271. return PLUGIN_HANDLED;
  4272. }
  4273.  
  4274. // Buy Primary Weapon
  4275. buy_primary_weapon(id, selection)
  4276. {
  4277. // Drop previous weapons
  4278. drop_weapons(id, 1)
  4279. drop_weapons(id, 2)
  4280.  
  4281. // Strip off from weapons
  4282. fm_strip_user_weapons(id)
  4283. fm_give_item(id, "weapon_knife")
  4284.  
  4285. // Get weapon's id and name
  4286. static weaponid, wname[32]
  4287. weaponid = ArrayGetCell(g_primary_weaponids, selection)
  4288. ArrayGetString(g_primary_items, selection, wname, charsmax(wname))
  4289.  
  4290. // Give the new weapon and full ammo
  4291. fm_give_item(id, wname)
  4292. ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[weaponid], AMMOTYPE[weaponid], MAXBPAMMO[weaponid])
  4293.  
  4294. // Weapons bought
  4295. g_canbuy[id] = false
  4296.  
  4297. // Give additional items
  4298. static i
  4299. for (i = 0; i < ArraySize(g_additional_items); i++)
  4300. {
  4301. ArrayGetString(g_additional_items, i, wname, charsmax(wname))
  4302. fm_give_item(id, wname)
  4303. }
  4304. }
  4305.  
  4306. // Buy Menu 2
  4307. public menu_buy2(id, key)
  4308. {
  4309. // Player dead?
  4310. if (!g_isalive[id])
  4311. return PLUGIN_HANDLED;
  4312.  
  4313. // Zombies or survivors get no guns
  4314. if (g_zombie[id] || g_survivor[id])
  4315. return PLUGIN_HANDLED;
  4316.  
  4317. // Special keys / weapon list exceeded
  4318. if (key >= ArraySize(g_secondary_items))
  4319. {
  4320. // Toggle autoselect
  4321. if (key == MENU_KEY_AUTOSELECT)
  4322. WPN_AUTO_ON = 1 - WPN_AUTO_ON
  4323.  
  4324. // Reshow menu unless user exited
  4325. if (key != MENU_KEY_EXIT)
  4326. show_menu_buy2(id)
  4327.  
  4328. return PLUGIN_HANDLED;
  4329. }
  4330.  
  4331. // Store selected weapon
  4332. WPN_AUTO_SEC = key
  4333.  
  4334. // Drop secondary gun again, in case we picked another (bugfix)
  4335. drop_weapons(id, 2)
  4336.  
  4337. // Get weapon's id
  4338. static weaponid, wname[32]
  4339. weaponid = ArrayGetCell(g_secondary_weaponids, key)
  4340. ArrayGetString(g_secondary_items, key, wname, charsmax(wname))
  4341.  
  4342. // Give the new weapon and full ammo
  4343. fm_give_item(id, wname)
  4344. ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[weaponid], AMMOTYPE[weaponid], MAXBPAMMO[weaponid])
  4345.  
  4346. return PLUGIN_HANDLED;
  4347. }
  4348.  
  4349. // Extra Items Menu
  4350. public menu_extras(id, menuid, item)
  4351. {
  4352. // Player disconnected?
  4353. if (!is_user_connected(id))
  4354. {
  4355. menu_destroy(menuid)
  4356. return PLUGIN_HANDLED;
  4357. }
  4358.  
  4359. // Remember player's menu page
  4360. static menudummy
  4361. player_menu_info(id, menudummy, menudummy, MENU_PAGE_EXTRAS)
  4362.  
  4363. // Menu was closed
  4364. if (item == MENU_EXIT)
  4365. {
  4366. menu_destroy(menuid)
  4367. return PLUGIN_HANDLED;
  4368. }
  4369.  
  4370. // Dead players are not allowed to buy items
  4371. if (!g_isalive[id])
  4372. {
  4373. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
  4374. menu_destroy(menuid)
  4375. return PLUGIN_HANDLED;
  4376. }
  4377.  
  4378. // Retrieve extra item id
  4379. static buffer[2], dummy, itemid
  4380. menu_item_getinfo(menuid, item, dummy, buffer, charsmax(buffer), _, _, dummy)
  4381. itemid = buffer[0]
  4382.  
  4383. // Attempt to buy the item
  4384. buy_extra_item(id, itemid)
  4385. menu_destroy(menuid)
  4386. return PLUGIN_HANDLED;
  4387. }
  4388.  
  4389. // Buy Extra Item
  4390. buy_extra_item(id, itemid, ignorecost = 0)
  4391. {
  4392. // Retrieve item's team
  4393. static team
  4394. team = ArrayGetCell(g_extraitem_team, itemid)
  4395.  
  4396. // Check for team/class specific items
  4397. if ((g_zombie[id] && !g_nemesis[id] && !(team & ZP_TEAM_ZOMBIE)) || (!g_zombie[id] && !g_survivor[id] && !(team & ZP_TEAM_HUMAN)) || (g_nemesis[id] && !(team & ZP_TEAM_NEMESIS)) || (g_survivor[id] && !(team & ZP_TEAM_SURVIVOR)))
  4398. {
  4399. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
  4400. return;
  4401. }
  4402.  
  4403. // Check for unavailable items
  4404. if ((itemid == EXTRA_NVISION && !get_pcvar_num(cvar_extranvision))
  4405. || (itemid == EXTRA_ANTIDOTE && (!get_pcvar_num(cvar_extraantidote) || g_antidotecounter >= get_pcvar_num(cvar_antidotelimit)))
  4406. || (itemid == EXTRA_MADNESS && (!get_pcvar_num(cvar_extramadness) || g_madnesscounter >= get_pcvar_num(cvar_madnesslimit)))
  4407. || (itemid == EXTRA_INFBOMB && (!get_pcvar_num(cvar_extrainfbomb) || g_infbombcounter >= get_pcvar_num(cvar_infbomblimit)))
  4408. || (itemid >= EXTRA_WEAPONS_STARTID && itemid <= EXTRAS_CUSTOM_STARTID-1 && !get_pcvar_num(cvar_extraweapons)))
  4409. {
  4410. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
  4411. return;
  4412. }
  4413.  
  4414. // Check for hard coded items with special conditions
  4415. if ((itemid == EXTRA_ANTIDOTE && (g_endround || g_swarmround || g_nemround || g_survround || g_plagueround || fnGetZombies() <= 1 || (get_pcvar_num(cvar_deathmatch) && !get_pcvar_num(cvar_respawnafterlast) && fnGetHumans() == 1)))
  4416. || (itemid == EXTRA_MADNESS && g_nodamage[id]) || (itemid == EXTRA_INFBOMB && (g_endround || g_swarmround || g_nemround || g_survround || g_plagueround)))
  4417. {
  4418. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_CANTUSE")
  4419. return;
  4420. }
  4421.  
  4422. // Ignore item's cost?
  4423. if (!ignorecost)
  4424. {
  4425. // Check that we have enough ammo packs
  4426. if (g_ammopacks[id] < ArrayGetCell(g_extraitem_cost, itemid))
  4427. {
  4428. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "NOT_ENOUGH_AMMO")
  4429. return;
  4430. }
  4431.  
  4432. // Deduce item cost
  4433. g_ammopacks[id] -= ArrayGetCell(g_extraitem_cost, itemid)
  4434. }
  4435.  
  4436. // Check which kind of item we're buying
  4437. switch (itemid)
  4438. {
  4439. case EXTRA_NVISION: // Night Vision
  4440. {
  4441. g_nvision[id] = true
  4442.  
  4443. if (!g_isbot[id])
  4444. {
  4445. g_nvisionenabled[id] = true
  4446.  
  4447. // Custom nvg?
  4448. if (get_pcvar_num(cvar_customnvg))
  4449. {
  4450. remove_task(id+TASK_NVISION)
  4451. set_task(0.1, "set_user_nvision", id+TASK_NVISION, _, _, "b")
  4452. }
  4453. else
  4454. set_user_gnvision(id, 1)
  4455. }
  4456. else
  4457. cs_set_user_nvg(id, 1)
  4458. }
  4459. case EXTRA_ANTIDOTE: // Antidote
  4460. {
  4461. // Increase antidote purchase count for this round
  4462. g_antidotecounter++
  4463.  
  4464. humanme(id, 0, 0)
  4465. }
  4466. case EXTRA_MADNESS: // Zombie Madness
  4467. {
  4468. // Increase madness purchase count for this round
  4469. g_madnesscounter++
  4470.  
  4471. g_nodamage[id] = true
  4472. set_task(0.1, "zombie_aura", id+TASK_AURA, _, _, "b")
  4473. set_task(get_pcvar_float(cvar_madnessduration), "madness_over", id+TASK_BLOOD)
  4474.  
  4475. static sound[64]
  4476. ArrayGetString(zombie_madness, random_num(0, ArraySize(zombie_madness) - 1), sound, charsmax(sound))
  4477. emit_sound(id, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  4478. }
  4479. case EXTRA_INFBOMB: // Infection Bomb
  4480. {
  4481. // Increase infection bomb purchase count for this round
  4482. g_infbombcounter++
  4483.  
  4484. // Already own one
  4485. if (user_has_weapon(id, CSW_HEGRENADE))
  4486. {
  4487. // Increase BP ammo on it instead
  4488. cs_set_user_bpammo(id, CSW_HEGRENADE, cs_get_user_bpammo(id, CSW_HEGRENADE) + 1)
  4489.  
  4490. // Flash ammo in hud
  4491. message_begin(MSG_ONE_UNRELIABLE, g_msgAmmoPickup, _, id)
  4492. write_byte(AMMOID[CSW_HEGRENADE]) // ammo id
  4493. write_byte(1) // ammo amount
  4494. message_end()
  4495.  
  4496. // Play clip purchase sound
  4497. emit_sound(id, CHAN_ITEM, sound_buyammo, 1.0, ATTN_NORM, 0, PITCH_NORM)
  4498.  
  4499. return; // stop here
  4500. }
  4501.  
  4502. // Give weapon to the player
  4503. fm_give_item(id, "weapon_hegrenade")
  4504. }
  4505. default:
  4506. {
  4507. if (itemid >= EXTRA_WEAPONS_STARTID && itemid <= EXTRAS_CUSTOM_STARTID-1) // Weapons
  4508. {
  4509. // Get weapon's id and name
  4510. static weaponid, wname[32]
  4511. ArrayGetString(g_extraweapon_items, itemid - EXTRA_WEAPONS_STARTID, wname, charsmax(wname))
  4512. weaponid = cs_weapon_name_to_id(wname)
  4513.  
  4514. // If we are giving a primary/secondary weapon
  4515. if (MAXBPAMMO[weaponid] > 2)
  4516. {
  4517. // Make user drop the previous one
  4518. if ((1<<weaponid) & PRIMARY_WEAPONS_BIT_SUM)
  4519. drop_weapons(id, 1)
  4520. else
  4521. drop_weapons(id, 2)
  4522.  
  4523. // Give full BP ammo for the new one
  4524. ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[weaponid], AMMOTYPE[weaponid], MAXBPAMMO[weaponid])
  4525. }
  4526. // If we are giving a grenade which the user already owns
  4527. else if (user_has_weapon(id, weaponid))
  4528. {
  4529. // Increase BP ammo on it instead
  4530. cs_set_user_bpammo(id, weaponid, cs_get_user_bpammo(id, weaponid) + 1)
  4531.  
  4532. // Flash ammo in hud
  4533. message_begin(MSG_ONE_UNRELIABLE, g_msgAmmoPickup, _, id)
  4534. write_byte(AMMOID[weaponid]) // ammo id
  4535. write_byte(1) // ammo amount
  4536. message_end()
  4537.  
  4538. // Play clip purchase sound
  4539. emit_sound(id, CHAN_ITEM, sound_buyammo, 1.0, ATTN_NORM, 0, PITCH_NORM)
  4540.  
  4541. return; // stop here
  4542. }
  4543.  
  4544. // Give weapon to the player
  4545. fm_give_item(id, wname)
  4546. }
  4547. else // Custom additions
  4548. {
  4549. // Item selected forward
  4550. ExecuteForward(g_fwExtraItemSelected, g_fwDummyResult, id, itemid);
  4551.  
  4552. // Item purchase blocked, restore buyer's ammo packs
  4553. if (g_fwDummyResult >= ZP_PLUGIN_HANDLED && !ignorecost)
  4554. g_ammopacks[id] += ArrayGetCell(g_extraitem_cost, itemid)
  4555. }
  4556. }
  4557. }
  4558. }
  4559.  
  4560. // Zombie Class Menu
  4561. public menu_zclass(id, menuid, item)
  4562. {
  4563. // Player disconnected?
  4564. if (!is_user_connected(id))
  4565. {
  4566. menu_destroy(menuid)
  4567. return PLUGIN_HANDLED;
  4568. }
  4569.  
  4570. // Remember player's menu page
  4571. static menudummy
  4572. player_menu_info(id, menudummy, menudummy, MENU_PAGE_ZCLASS)
  4573.  
  4574. // Menu was closed
  4575. if (item == MENU_EXIT)
  4576. {
  4577. menu_destroy(menuid)
  4578. return PLUGIN_HANDLED;
  4579. }
  4580.  
  4581. // Retrieve zombie class id
  4582. static buffer[2], dummy, classid
  4583. menu_item_getinfo(menuid, item, dummy, buffer, charsmax(buffer), _, _, dummy)
  4584. classid = buffer[0]
  4585.  
  4586. // Store selection for the next infection
  4587. g_zombieclassnext[id] = classid
  4588.  
  4589. static name[32]
  4590. ArrayGetString(g_zclass_name, g_zombieclassnext[id], name, charsmax(name))
  4591.  
  4592. // Show selected zombie class info and stats
  4593. zp_colored_print(id, "^x04[ZP]^x01 %L: %s", id, "ZOMBIE_SELECT", name)
  4594. zp_colored_print(id, "^x04[ZP]^x01 %L: %d %L: %d %L: %d %L: %d%%", id, "ZOMBIE_ATTRIB1", ArrayGetCell(g_zclass_hp, g_zombieclassnext[id]), id, "ZOMBIE_ATTRIB2", ArrayGetCell(g_zclass_spd, g_zombieclassnext[id]),
  4595. id, "ZOMBIE_ATTRIB3", floatround(Float:ArrayGetCell(g_zclass_grav, g_zombieclassnext[id]) * 800.0), id, "ZOMBIE_ATTRIB4", floatround(Float:ArrayGetCell(g_zclass_kb, g_zombieclassnext[id]) * 100.0))
  4596.  
  4597. menu_destroy(menuid)
  4598. return PLUGIN_HANDLED;
  4599. }
  4600.  
  4601. // Info Menu
  4602. public menu_info(id, key)
  4603. {
  4604. // Player disconnected?
  4605. if (!g_isconnected[id])
  4606. return PLUGIN_HANDLED;
  4607.  
  4608. static motd[1500], len
  4609. len = 0
  4610.  
  4611. switch (key)
  4612. {
  4613. case 0: // General
  4614. {
  4615. static weather, lighting[2]
  4616. weather = 0
  4617. get_pcvar_string(cvar_lighting, lighting, charsmax(lighting))
  4618. strtolower(lighting)
  4619.  
  4620. len += formatex(motd[len], charsmax(motd) - len, "%L ", id, "MOTD_INFO11", "Zombie Plague", PLUGIN_VERSION, "MeRcyLeZZ")
  4621. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO12")
  4622. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_A")
  4623.  
  4624. if (g_ambience_fog)
  4625. {
  4626. len += formatex(motd[len], charsmax(motd) - len, (weather < 1) ? " %L" : ". %L", id, "MOTD_FOG")
  4627. weather++
  4628. }
  4629. if (g_ambience_rain)
  4630. {
  4631. len += formatex(motd[len], charsmax(motd) - len, (weather < 1) ? " %L" : ". %L", id, "MOTD_RAIN")
  4632. weather++
  4633. }
  4634. if (g_ambience_snow)
  4635. {
  4636. len += formatex(motd[len], charsmax(motd) - len, (weather < 1) ? " %L" : ". %L", id, "MOTD_SNOW")
  4637. weather++
  4638. }
  4639. if (weather < 1) len += formatex(motd[len], charsmax(motd) - len, " %L", id, "MOTD_DISABLED")
  4640.  
  4641. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_B", lighting)
  4642. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_C", id, get_pcvar_num(cvar_triggered) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  4643. if (lighting[0] >= 'a' && lighting[0] <= 'd' && get_pcvar_float(cvar_thunder) > 0.0) len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_D", floatround(get_pcvar_float(cvar_thunder)))
  4644. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_E", id, get_pcvar_num(cvar_removedoors) > 0 ? get_pcvar_num(cvar_removedoors) > 1 ? "MOTD_DOORS" : "MOTD_ROTATING" : "MOTD_ENABLED")
  4645. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_F", id, get_pcvar_num(cvar_deathmatch) > 0 ? get_pcvar_num(cvar_deathmatch) > 1 ? get_pcvar_num(cvar_deathmatch) > 2 ? "MOTD_ENABLED" : "MOTD_DM_ZOMBIE" : "MOTD_DM_HUMAN" : "MOTD_DISABLED")
  4646. if (get_pcvar_num(cvar_deathmatch)) len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_G", floatround(get_pcvar_float(cvar_spawnprotection)))
  4647. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_H", id, get_pcvar_num(cvar_randspawn) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  4648. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_I", id, get_pcvar_num(cvar_extraitems) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  4649. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_J", id, get_pcvar_num(cvar_zclasses) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  4650. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_K", id, get_pcvar_num(cvar_customnvg) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  4651. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_L", id, g_cached_customflash ? "MOTD_ENABLED" : "MOTD_DISABLED")
  4652.  
  4653. show_motd(id, motd)
  4654. }
  4655. case 1: // Humans
  4656. {
  4657. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2")
  4658. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_A", get_pcvar_num(cvar_humanhp))
  4659. if (get_pcvar_num(cvar_humanlasthp) > 0) len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_B", get_pcvar_num(cvar_humanlasthp))
  4660. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_C", get_pcvar_num(cvar_humanspd))
  4661. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_D", floatround(get_pcvar_float(cvar_humangravity) * 800.0))
  4662. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_E", id, get_pcvar_num(cvar_infammo) > 0 ? get_pcvar_num(cvar_infammo) > 1 ? "MOTD_AMMO_CLIP" : "MOTD_AMMO_BP" : "MOTD_LIMITED")
  4663. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_F", get_pcvar_num(cvar_ammodamage_human))
  4664. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_G", id, get_pcvar_num(cvar_firegrenades) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  4665. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_H", id, get_pcvar_num(cvar_frostgrenades) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  4666. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_I", id, get_pcvar_num(cvar_flaregrenades) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  4667. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_J", id, get_pcvar_num(cvar_knockback) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  4668.  
  4669. show_motd(id, motd)
  4670. }
  4671. case 2: // Zombies
  4672. {
  4673. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3")
  4674. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_A", ArrayGetCell(g_zclass_hp, 0))
  4675. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_B", floatround(float(ArrayGetCell(g_zclass_hp, 0)) * get_pcvar_float(cvar_zombiefirsthp)))
  4676. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_C", floatround(get_pcvar_float(cvar_zombiearmor) * 100.0))
  4677. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_D", ArrayGetCell(g_zclass_spd, 0))
  4678. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_E", floatround(Float:ArrayGetCell(g_zclass_grav, 0) * 800.0))
  4679. if (get_pcvar_num(cvar_zombiebonushp)) len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_F", get_pcvar_num(cvar_zombiebonushp))
  4680. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_G", id, get_pcvar_num(cvar_zombiepainfree) > 0 ? get_pcvar_num(cvar_zombiepainfree) > 1 ? "MOTD_LASTZOMBIE" : "MOTD_ENABLED" : "MOTD_DISABLED")
  4681. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_H", id, get_pcvar_num(cvar_zombiebleeding) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  4682. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_I", get_pcvar_num(cvar_ammoinfect))
  4683.  
  4684. show_motd(id, motd)
  4685. }
  4686. case 3: // Gameplay Modes
  4687. {
  4688. static nemhp[5], survhp[5]
  4689.  
  4690. // Get nemesis and survivor health
  4691. num_to_str(get_pcvar_num(cvar_nemhp), nemhp, charsmax(nemhp))
  4692. num_to_str(get_pcvar_num(cvar_survhp), survhp, charsmax(survhp))
  4693.  
  4694. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4")
  4695. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_A", id, get_pcvar_num(cvar_nem) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  4696. if (get_pcvar_num(cvar_nem))
  4697. {
  4698. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_B", get_pcvar_num(cvar_nemchance))
  4699. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_C", get_pcvar_num(cvar_nemhp) > 0 ? nemhp : "[Auto]")
  4700. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_D", get_pcvar_num(cvar_nemspd))
  4701. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_E", floatround(get_pcvar_float(cvar_nemgravity) * 800.0))
  4702. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_F", id, g_cached_leapnemesis ? "MOTD_ENABLED" : "MOTD_DISABLED")
  4703. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_G", id, get_pcvar_num(cvar_nempainfree) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  4704. }
  4705. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_H", id, get_pcvar_num(cvar_surv) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  4706. if (get_pcvar_num(cvar_surv))
  4707. {
  4708. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_I", get_pcvar_num(cvar_survchance))
  4709. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_J", get_pcvar_num(cvar_survhp) > 0 ? survhp : "[Auto]")
  4710. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_K", get_pcvar_num(cvar_survspd))
  4711. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_L", floatround(get_pcvar_float(cvar_survgravity) * 800.0))
  4712. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_M", id, g_cached_leapsurvivor ? "MOTD_ENABLED" : "MOTD_DISABLED")
  4713. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_N", id, get_pcvar_num(cvar_survpainfree) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  4714. }
  4715. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_O", id, get_pcvar_num(cvar_swarm) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  4716. if (get_pcvar_num(cvar_swarm)) len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_P", get_pcvar_num(cvar_swarmchance))
  4717. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_Q", id, get_pcvar_num(cvar_multi) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  4718. if (get_pcvar_num(cvar_multi))
  4719. {
  4720. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_R", get_pcvar_num(cvar_multichance))
  4721. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_S", floatround(get_pcvar_float(cvar_multiratio) * 100.0))
  4722. }
  4723. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_T", id, get_pcvar_num(cvar_plague) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  4724. if (get_pcvar_num(cvar_plague))
  4725. {
  4726. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_U", get_pcvar_num(cvar_plaguechance))
  4727. len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_V", floatround(get_pcvar_float(cvar_plagueratio) * 100.0))
  4728. }
  4729.  
  4730. show_motd(id, motd)
  4731. }
  4732. default: return PLUGIN_HANDLED;
  4733. }
  4734.  
  4735. // Show help menu again if user wishes to read another topic
  4736. show_menu_info(id)
  4737.  
  4738. return PLUGIN_HANDLED;
  4739. }
  4740.  
  4741. // Admin Menu
  4742. public menu_admin(id, key)
  4743. {
  4744. // Player disconnected?
  4745. if (!g_isconnected[id])
  4746. return PLUGIN_HANDLED;
  4747.  
  4748. static userflags
  4749. userflags = get_user_flags(id)
  4750.  
  4751. switch (key)
  4752. {
  4753. case ACTION_ZOMBIEFY_HUMANIZE: // Zombiefy/Humanize command
  4754. {
  4755. if (userflags & (g_access_flag[ACCESS_MODE_INFECTION] | g_access_flag[ACCESS_MAKE_ZOMBIE] | g_access_flag[ACCESS_MAKE_HUMAN]))
  4756. {
  4757. // Show player list for admin to pick a target
  4758. PL_ACTION = ACTION_ZOMBIEFY_HUMANIZE
  4759. show_menu_player_list(id)
  4760. }
  4761. else
  4762. {
  4763. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
  4764. show_menu_admin(id)
  4765. }
  4766. }
  4767. case ACTION_MAKE_NEMESIS: // Nemesis command
  4768. {
  4769. if (userflags & (g_access_flag[ACCESS_MODE_NEMESIS] | g_access_flag[ACCESS_MAKE_NEMESIS]))
  4770. {
  4771. // Show player list for admin to pick a target
  4772. PL_ACTION = ACTION_MAKE_NEMESIS
  4773. show_menu_player_list(id)
  4774. }
  4775. else
  4776. {
  4777. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
  4778. show_menu_admin(id)
  4779. }
  4780. }
  4781. case ACTION_MAKE_SURVIVOR: // Survivor command
  4782. {
  4783. if (userflags & (g_access_flag[ACCESS_MODE_SURVIVOR] | g_access_flag[ACCESS_MAKE_SURVIVOR]))
  4784. {
  4785. // Show player list for admin to pick a target
  4786. PL_ACTION = ACTION_MAKE_SURVIVOR
  4787. show_menu_player_list(id)
  4788. }
  4789. else
  4790. {
  4791. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
  4792. show_menu_admin(id)
  4793. }
  4794. }
  4795. case ACTION_RESPAWN_PLAYER: // Respawn command
  4796. {
  4797. if (userflags & g_access_flag[ACCESS_RESPAWN_PLAYERS])
  4798. {
  4799. // Show player list for admin to pick a target
  4800. PL_ACTION = ACTION_RESPAWN_PLAYER
  4801. show_menu_player_list(id)
  4802. }
  4803. else
  4804. {
  4805. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
  4806. show_menu_admin(id)
  4807. }
  4808. }
  4809. case ACTION_MODE_SWARM: // Swarm Mode command
  4810. {
  4811. if (userflags & g_access_flag[ACCESS_MODE_SWARM])
  4812. {
  4813. if (allowed_swarm())
  4814. command_swarm(id)
  4815. else
  4816. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
  4817. }
  4818. else
  4819. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
  4820.  
  4821. show_menu_admin(id)
  4822. }
  4823. case ACTION_MODE_MULTI: // Multiple Infection command
  4824. {
  4825. if (userflags & g_access_flag[ACCESS_MODE_MULTI])
  4826. {
  4827. if (allowed_multi())
  4828. command_multi(id)
  4829. else
  4830. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
  4831. }
  4832. else
  4833. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
  4834.  
  4835. show_menu_admin(id)
  4836. }
  4837. case ACTION_MODE_PLAGUE: // Plague Mode command
  4838. {
  4839. if (userflags & g_access_flag[ACCESS_MODE_PLAGUE])
  4840. {
  4841. if (allowed_plague())
  4842. command_plague(id)
  4843. else
  4844. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
  4845. }
  4846. else
  4847. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
  4848.  
  4849. show_menu_admin(id)
  4850. }
  4851. }
  4852.  
  4853. return PLUGIN_HANDLED;
  4854. }
  4855.  
  4856. // Player List Menu
  4857. public menu_player_list(id, menuid, item)
  4858. {
  4859. // Player disconnected?
  4860. if (!is_user_connected(id))
  4861. {
  4862. menu_destroy(menuid)
  4863. return PLUGIN_HANDLED;
  4864. }
  4865.  
  4866. // Remember player's menu page
  4867. static menudummy
  4868. player_menu_info(id, menudummy, menudummy, MENU_PAGE_PLAYERS)
  4869.  
  4870. // Menu was closed
  4871. if (item == MENU_EXIT)
  4872. {
  4873. menu_destroy(menuid)
  4874. show_menu_admin(id)
  4875. return PLUGIN_HANDLED;
  4876. }
  4877.  
  4878. // Retrieve player id
  4879. static buffer[2], dummy, playerid
  4880. menu_item_getinfo(menuid, item, dummy, buffer, charsmax(buffer), _, _, dummy)
  4881. playerid = buffer[0]
  4882.  
  4883. // Perform action on player
  4884.  
  4885. // Get admin flags
  4886. static userflags
  4887. userflags = get_user_flags(id)
  4888.  
  4889. // Make sure it's still connected
  4890. if (g_isconnected[playerid])
  4891. {
  4892. // Perform the right action if allowed
  4893. switch (PL_ACTION)
  4894. {
  4895. case ACTION_ZOMBIEFY_HUMANIZE: // Zombiefy/Humanize command
  4896. {
  4897. if (g_zombie[playerid])
  4898. {
  4899. if (userflags & g_access_flag[ACCESS_MAKE_HUMAN])
  4900. {
  4901. if (allowed_human(playerid))
  4902. command_human(id, playerid)
  4903. else
  4904. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
  4905. }
  4906. else
  4907. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
  4908. }
  4909. else
  4910. {
  4911. if (g_newround ? (userflags & g_access_flag[ACCESS_MODE_INFECTION]) : (userflags & g_access_flag[ACCESS_MAKE_ZOMBIE]))
  4912. {
  4913. if (allowed_zombie(playerid))
  4914. command_zombie(id, playerid)
  4915. else
  4916. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
  4917. }
  4918. else
  4919. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
  4920. }
  4921. }
  4922. case ACTION_MAKE_NEMESIS: // Nemesis command
  4923. {
  4924. if (g_newround ? (userflags & g_access_flag[ACCESS_MODE_NEMESIS]) : (userflags & g_access_flag[ACCESS_MAKE_NEMESIS]))
  4925. {
  4926. if (allowed_nemesis(playerid))
  4927. command_nemesis(id, playerid)
  4928. else
  4929. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
  4930. }
  4931. else
  4932. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
  4933. }
  4934. case ACTION_MAKE_SURVIVOR: // Survivor command
  4935. {
  4936. if (g_newround ? (userflags & g_access_flag[ACCESS_MODE_SURVIVOR]) : (userflags & g_access_flag[ACCESS_MAKE_SURVIVOR]))
  4937. {
  4938. if (allowed_survivor(playerid))
  4939. command_survivor(id, playerid)
  4940. else
  4941. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
  4942. }
  4943. else
  4944. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
  4945. }
  4946. case ACTION_RESPAWN_PLAYER: // Respawn command
  4947. {
  4948. if (userflags & g_access_flag[ACCESS_RESPAWN_PLAYERS])
  4949. {
  4950. if (allowed_respawn(playerid))
  4951. command_respawn(id, playerid)
  4952. else
  4953. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
  4954. }
  4955. else
  4956. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
  4957. }
  4958. }
  4959. }
  4960. else
  4961. zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
  4962.  
  4963. menu_destroy(menuid)
  4964. show_menu_player_list(id)
  4965. return PLUGIN_HANDLED;
  4966. }
  4967.  
  4968. // CS Buy Menus
  4969. public menu_cs_buy(id, key)
  4970. {
  4971. // Prevent buying if zombie/survivor (bugfix)
  4972. if (g_zombie[id] || g_survivor[id])
  4973. return PLUGIN_HANDLED;
  4974.  
  4975. return PLUGIN_CONTINUE;
  4976. }
  4977.  
  4978. /*================================================================================
  4979. [Admin Commands]
  4980. =================================================================================*/
  4981.  
  4982. // zp_toggle [1/0]
  4983. public cmd_toggle(id, level, cid)
  4984. {
  4985. // Check for access flag - Enable/Disable Mod
  4986. if (!cmd_access(id, g_access_flag[ACCESS_ENABLE_MOD], cid, 2))
  4987. return PLUGIN_HANDLED;
  4988.  
  4989. // Retrieve arguments
  4990. new arg[2]
  4991. read_argv(1, arg, charsmax(arg))
  4992.  
  4993. // Mod already enabled/disabled
  4994. if (str_to_num(arg) == g_pluginenabled)
  4995. return PLUGIN_HANDLED;
  4996.  
  4997. // Set toggle cvar
  4998. set_pcvar_num(cvar_toggle, str_to_num(arg))
  4999. client_print(id, print_console, "Zombie Plague %L.", id, str_to_num(arg) ? "MOTD_ENABLED" : "MOTD_DISABLED")
  5000.  
  5001. // Retrieve map name
  5002. new mapname[32]
  5003. get_mapname(mapname, charsmax(mapname))
  5004.  
  5005. // Restart current map
  5006. server_cmd("changelevel %s", mapname)
  5007.  
  5008. return PLUGIN_HANDLED;
  5009. }
  5010.  
  5011. // zp_zombie [target]
  5012. public cmd_zombie(id, level, cid)
  5013. {
  5014. // Check for access flag depending on the resulting action
  5015. if (g_newround)
  5016. {
  5017. // Start Mode Infection
  5018. if (!cmd_access(id, g_access_flag[ACCESS_MODE_INFECTION], cid, 2))
  5019. return PLUGIN_HANDLED;
  5020. }
  5021. else
  5022. {
  5023. // Make Zombie
  5024. if (!cmd_access(id, g_access_flag[ACCESS_MAKE_ZOMBIE], cid, 2))
  5025. return PLUGIN_HANDLED;
  5026. }
  5027.  
  5028. // Retrieve arguments
  5029. static arg[32], player
  5030. read_argv(1, arg, charsmax(arg))
  5031. player = cmd_target(id, arg, (CMDTARGET_ONLY_ALIVE | CMDTARGET_ALLOW_SELF))
  5032.  
  5033. // Invalid target
  5034. if (!player) return PLUGIN_HANDLED;
  5035.  
  5036. // Target not allowed to be zombie
  5037. if (!allowed_zombie(player))
  5038. {
  5039. client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
  5040. return PLUGIN_HANDLED
  5041. }
  5042.  
  5043. command_zombie(id, player)
  5044.  
  5045. return PLUGIN_HANDLED;
  5046. }
  5047.  
  5048. // zp_human [target]
  5049. public cmd_human(id, level, cid)
  5050. {
  5051. // Check for access flag - Make Human
  5052. if (!cmd_access(id, g_access_flag[ACCESS_MAKE_HUMAN], cid, 2))
  5053. return PLUGIN_HANDLED;
  5054.  
  5055. // Retrieve arguments
  5056. static arg[32], player
  5057. read_argv(1, arg, charsmax(arg))
  5058. player = cmd_target(id, arg, (CMDTARGET_ONLY_ALIVE | CMDTARGET_ALLOW_SELF))
  5059.  
  5060. // Invalid target
  5061. if (!player) return PLUGIN_HANDLED;
  5062.  
  5063. // Target not allowed to be human
  5064. if (!allowed_human(player))
  5065. {
  5066. client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
  5067. return PLUGIN_HANDLED;
  5068. }
  5069.  
  5070. command_human(id, player)
  5071.  
  5072. return PLUGIN_HANDLED;
  5073. }
  5074.  
  5075. // zp_survivor [target]
  5076. public cmd_survivor(id, level, cid)
  5077. {
  5078. // Check for access flag depending on the resulting action
  5079. if (g_newround)
  5080. {
  5081. // Start Mode Survivor
  5082. if (!cmd_access(id, g_access_flag[ACCESS_MODE_SURVIVOR], cid, 2))
  5083. return PLUGIN_HANDLED;
  5084. }
  5085. else
  5086. {
  5087. // Make Survivor
  5088. if (!cmd_access(id, g_access_flag[ACCESS_MAKE_SURVIVOR], cid, 2))
  5089. return PLUGIN_HANDLED;
  5090. }
  5091.  
  5092. // Retrieve arguments
  5093. static arg[32], player
  5094. read_argv(1, arg, charsmax(arg))
  5095. player = cmd_target(id, arg, (CMDTARGET_ONLY_ALIVE | CMDTARGET_ALLOW_SELF))
  5096.  
  5097. // Invalid target
  5098. if (!player) return PLUGIN_HANDLED;
  5099.  
  5100. // Target not allowed to be survivor
  5101. if (!allowed_survivor(player))
  5102. {
  5103. client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
  5104. return PLUGIN_HANDLED;
  5105. }
  5106.  
  5107. command_survivor(id, player)
  5108.  
  5109. return PLUGIN_HANDLED;
  5110. }
  5111.  
  5112. // zp_nemesis [target]
  5113. public cmd_nemesis(id, level, cid)
  5114. {
  5115. // Check for access flag depending on the resulting action
  5116. if (g_newround)
  5117. {
  5118. // Start Mode Nemesis
  5119. if (!cmd_access(id, g_access_flag[ACCESS_MODE_NEMESIS], cid, 2))
  5120. return PLUGIN_HANDLED;
  5121. }
  5122. else
  5123. {
  5124. // Make Nemesis
  5125. if (!cmd_access(id, g_access_flag[ACCESS_MAKE_NEMESIS], cid, 2))
  5126. return PLUGIN_HANDLED;
  5127. }
  5128.  
  5129. // Retrieve arguments
  5130. static arg[32], player
  5131. read_argv(1, arg, charsmax(arg))
  5132. player = cmd_target(id, arg, (CMDTARGET_ONLY_ALIVE | CMDTARGET_ALLOW_SELF))
  5133.  
  5134. // Invalid target
  5135. if (!player) return PLUGIN_HANDLED;
  5136.  
  5137. // Target not allowed to be nemesis
  5138. if (!allowed_nemesis(player))
  5139. {
  5140. client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
  5141. return PLUGIN_HANDLED;
  5142. }
  5143.  
  5144. command_nemesis(id, player)
  5145.  
  5146. return PLUGIN_HANDLED;
  5147. }
  5148.  
  5149. // zp_respawn [target]
  5150. public cmd_respawn(id, level, cid)
  5151. {
  5152. // Check for access flag - Respawn
  5153. if (!cmd_access(id, g_access_flag[ACCESS_RESPAWN_PLAYERS], cid, 2))
  5154. return PLUGIN_HANDLED;
  5155.  
  5156. // Retrieve arguments
  5157. static arg[32], player
  5158. read_argv(1, arg, charsmax(arg))
  5159. player = cmd_target(id, arg, CMDTARGET_ALLOW_SELF)
  5160.  
  5161. // Invalid target
  5162. if (!player) return PLUGIN_HANDLED;
  5163.  
  5164. // Target not allowed to be respawned
  5165. if (!allowed_respawn(player))
  5166. {
  5167. client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
  5168. return PLUGIN_HANDLED;
  5169. }
  5170.  
  5171. command_respawn(id, player)
  5172.  
  5173. return PLUGIN_HANDLED;
  5174. }
  5175.  
  5176. // zp_swarm
  5177. public cmd_swarm(id, level, cid)
  5178. {
  5179. // Check for access flag - Mode Swarm
  5180. if (!cmd_access(id, g_access_flag[ACCESS_MODE_SWARM], cid, 1))
  5181. return PLUGIN_HANDLED;
  5182.  
  5183. // Swarm mode not allowed
  5184. if (!allowed_swarm())
  5185. {
  5186. client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
  5187. return PLUGIN_HANDLED;
  5188. }
  5189.  
  5190. command_swarm(id)
  5191.  
  5192. return PLUGIN_HANDLED;
  5193. }
  5194.  
  5195. // zp_multi
  5196. public cmd_multi(id, level, cid)
  5197. {
  5198. // Check for access flag - Mode Multi
  5199. if (!cmd_access(id, g_access_flag[ACCESS_MODE_MULTI], cid, 1))
  5200. return PLUGIN_HANDLED;
  5201.  
  5202. // Multi infection mode not allowed
  5203. if (!allowed_multi())
  5204. {
  5205. client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
  5206. return PLUGIN_HANDLED;
  5207. }
  5208.  
  5209. command_multi(id)
  5210.  
  5211. return PLUGIN_HANDLED;
  5212. }
  5213.  
  5214. // zp_plague
  5215. public cmd_plague(id, level, cid)
  5216. {
  5217. // Check for access flag - Mode Plague
  5218. if (!cmd_access(id, g_access_flag[ACCESS_MODE_PLAGUE], cid, 1))
  5219. return PLUGIN_HANDLED;
  5220.  
  5221. // Plague mode not allowed
  5222. if (!allowed_plague())
  5223. {
  5224. client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
  5225. return PLUGIN_HANDLED;
  5226. }
  5227.  
  5228. command_plague(id)
  5229.  
  5230. return PLUGIN_HANDLED;
  5231. }
  5232.  
  5233. /*================================================================================
  5234. [Message Hooks]
  5235. =================================================================================*/
  5236.  
  5237. // Current Weapon info
  5238. public message_cur_weapon(msg_id, msg_dest, msg_entity)
  5239. {
  5240. // Not alive or zombie
  5241. if (!g_isalive[msg_entity] || g_zombie[msg_entity])
  5242. return;
  5243.  
  5244. // Not an active weapon
  5245. if (get_msg_arg_int(1) != 1)
  5246. return;
  5247.  
  5248. if(g_zombie[msg_entity] && user_has_weapon(msg_entity, CSW_HEGRENADE) && get_pcvar_num(cvar_extrainfbomb))
  5249. {
  5250. g_infectnade[msg_entity] = true
  5251. }
  5252. else
  5253. {
  5254. g_infectnade[msg_entity] = false
  5255. }
  5256.  
  5257. if ((g_survivor[msg_entity] && get_pcvar_num(cvar_survinfammo) > 1) || (g_unlimited_clip[msg_entity]) || (!g_survivor[msg_entity] && get_pcvar_num(cvar_infammo) > 1))
  5258. {
  5259. // Get weapon's id
  5260. static weapon
  5261. weapon = get_msg_arg_int(2)
  5262.  
  5263. // Unlimited Clip Ammo for this weapon?
  5264. if (MAXBPAMMO[weapon] > 2)
  5265. {
  5266. // Max out clip ammo
  5267. cs_set_weapon_ammo(fm_cs_get_current_weapon_ent(msg_entity), MAXCLIP[weapon])
  5268.  
  5269. // HUD should show full clip all the time
  5270. set_msg_arg_int(3, get_msg_argtype(3), MAXCLIP[weapon])
  5271. }
  5272. }
  5273.  
  5274. // Unlimited clip disabled for class
  5275. /*if (g_survivor[msg_entity] ? get_pcvar_num(cvar_survinfammo) <= 1 : get_pcvar_num(cvar_infammo) <= 1)
  5276. return;
  5277.  
  5278. // Get weapon's id
  5279. static weapon
  5280. weapon = get_msg_arg_int(2)
  5281.  
  5282. // Unlimited Clip Ammo for this weapon?
  5283. if (MAXBPAMMO[weapon] > 2)
  5284. {
  5285. // Max out clip ammo
  5286. static weapon_ent
  5287. weapon_ent = fm_cs_get_current_weapon_ent(msg_entity)
  5288. if (pev_valid(weapon_ent)) cs_set_weapon_ammo(weapon_ent, MAXCLIP[weapon])
  5289.  
  5290. // HUD should show full clip all the time
  5291. set_msg_arg_int(3, get_msg_argtype(3), MAXCLIP[weapon])
  5292. }*/
  5293. }
  5294.  
  5295. // Take off player's money
  5296. public message_money(msg_id, msg_dest, msg_entity)
  5297. {
  5298. // Remove money setting enabled?
  5299. if (!get_pcvar_num(cvar_removemoney))
  5300. return PLUGIN_CONTINUE;
  5301.  
  5302. fm_cs_set_user_money(msg_entity, 0)
  5303. return PLUGIN_HANDLED;
  5304. }
  5305.  
  5306. // Fix for the HL engine bug when HP is multiples of 256
  5307. public message_health(msg_id, msg_dest, msg_entity)
  5308. {
  5309. // Get player's health
  5310. static health
  5311. health = get_msg_arg_int(1)
  5312.  
  5313. // Don't bother
  5314. if (health < 256) return;
  5315.  
  5316. // Check if we need to fix it
  5317. if (health % 256 == 0)
  5318. fm_set_user_health(msg_entity, pev(msg_entity, pev_health) + 1)
  5319.  
  5320. // HUD can only show as much as 255 hp
  5321. set_msg_arg_int(1, get_msg_argtype(1), 255)
  5322. }
  5323.  
  5324. // Block flashlight battery messages if custom flashlight is enabled instead
  5325. public message_flashbat()
  5326. {
  5327. if (g_cached_customflash)
  5328. return PLUGIN_HANDLED;
  5329.  
  5330. return PLUGIN_CONTINUE;
  5331. }
  5332.  
  5333. // Flashbangs should only affect zombies
  5334. public message_screenfade(msg_id, msg_dest, msg_entity)
  5335. {
  5336. if (get_msg_arg_int(4) != 255 || get_msg_arg_int(5) != 255 || get_msg_arg_int(6) != 255 || get_msg_arg_int(7) < 200)
  5337. return PLUGIN_CONTINUE;
  5338.  
  5339. // Nemesis shouldn't be FBed
  5340. if (g_zombie[msg_entity] && !g_nemesis[msg_entity])
  5341. {
  5342. // Set flash color to nighvision's
  5343. set_msg_arg_int(4, get_msg_argtype(4), get_pcvar_num(cvar_nvgcolor[0]))
  5344. set_msg_arg_int(5, get_msg_argtype(5), get_pcvar_num(cvar_nvgcolor[1]))
  5345. set_msg_arg_int(6, get_msg_argtype(6), get_pcvar_num(cvar_nvgcolor[2]))
  5346. return PLUGIN_CONTINUE;
  5347. }
  5348.  
  5349. return PLUGIN_HANDLED;
  5350. }
  5351.  
  5352. // Prevent spectators' nightvision from being turned off when switching targets, etc.
  5353. public message_nvgtoggle()
  5354. {
  5355. return PLUGIN_HANDLED;
  5356. }
  5357.  
  5358. // Set correct model on player corpses
  5359. public message_clcorpse()
  5360. {
  5361. set_msg_arg_string(1, g_playermodel[get_msg_arg_int(12)])
  5362. }
  5363.  
  5364. // Prevent zombies from seeing any weapon pickup icon
  5365. public message_weappickup(msg_id, msg_dest, msg_entity)
  5366. {
  5367. if (g_zombie[msg_entity])
  5368. return PLUGIN_HANDLED;
  5369.  
  5370. return PLUGIN_CONTINUE;
  5371. }
  5372.  
  5373. // Prevent zombies from seeing any ammo pickup icon
  5374. public message_ammopickup(msg_id, msg_dest, msg_entity)
  5375. {
  5376. if (g_zombie[msg_entity])
  5377. return PLUGIN_HANDLED;
  5378.  
  5379. return PLUGIN_CONTINUE;
  5380. }
  5381.  
  5382. // Block hostage HUD display
  5383. public message_scenario()
  5384. {
  5385. if (get_msg_args() > 1)
  5386. {
  5387. static sprite[8]
  5388. get_msg_arg_string(2, sprite, charsmax(sprite))
  5389.  
  5390. if (equal(sprite, "hostage"))
  5391. return PLUGIN_HANDLED;
  5392. }
  5393.  
  5394. return PLUGIN_CONTINUE;
  5395. }
  5396.  
  5397. // Block hostages from appearing on radar
  5398. public message_hostagepos()
  5399. {
  5400. return PLUGIN_HANDLED;
  5401. }
  5402.  
  5403. // Block some text messages
  5404. public message_textmsg()
  5405. {
  5406. static textmsg[22]
  5407. get_msg_arg_string(2, textmsg, charsmax(textmsg))
  5408.  
  5409. // Game restarting, reset scores and call round end to balance the teams
  5410. if (equal(textmsg, "#Game_will_restart_in"))
  5411. {
  5412. logevent_round_end()
  5413. g_scorehumans = 0
  5414. g_scorezombies = 0
  5415. }
  5416. // Game commencing, reset scores only (round end is automatically triggered)
  5417. else if (equal(textmsg, "#Game_Commencing"))
  5418. {
  5419. g_gamecommencing = true
  5420. g_scorehumans = 0
  5421. g_scorezombies = 0
  5422. }
  5423. // Block round end related messages
  5424. else if (equal(textmsg, "#Hostages_Not_Rescued") || equal(textmsg, "#Round_Draw") || equal(textmsg, "#Terrorists_Win") || equal(textmsg, "#CTs_Win"))
  5425. {
  5426. return PLUGIN_HANDLED;
  5427. }
  5428.  
  5429. return PLUGIN_CONTINUE;
  5430. }
  5431.  
  5432. // Block CS round win audio messages, since we're playing our own instead
  5433. public message_sendaudio()
  5434. {
  5435. static audio[17]
  5436. get_msg_arg_string(2, audio, charsmax(audio))
  5437.  
  5438. if(equal(audio[7], "terwin") || equal(audio[7], "ctwin") || equal(audio[7], "rounddraw"))
  5439. return PLUGIN_HANDLED;
  5440.  
  5441. return PLUGIN_CONTINUE;
  5442. }
  5443.  
  5444. // Send actual team scores (T = zombies // CT = humans)
  5445. public message_teamscore()
  5446. {
  5447. static team[2]
  5448. get_msg_arg_string(1, team, charsmax(team))
  5449.  
  5450. switch (team[0])
  5451. {
  5452. // CT
  5453. case 'C': set_msg_arg_int(2, get_msg_argtype(2), g_scorehumans)
  5454. // Terrorist
  5455. case 'T': set_msg_arg_int(2, get_msg_argtype(2), g_scorezombies)
  5456. }
  5457. }
  5458.  
  5459. // Team Switch (or player joining a team for first time)
  5460. public message_teaminfo(msg_id, msg_dest)
  5461. {
  5462. // Only hook global messages
  5463. if (msg_dest != MSG_ALL && msg_dest != MSG_BROADCAST) return;
  5464.  
  5465. // Don't pick up our own TeamInfo messages for this player (bugfix)
  5466. if (g_switchingteam) return;
  5467.  
  5468. // Get player's id
  5469. static id
  5470. id = get_msg_arg_int(1)
  5471.  
  5472. // Invalid player id? (bugfix)
  5473. if (!(1 <= id <= g_maxplayers)) return;
  5474.  
  5475. // Enable spectators' nightvision if not spawning right away
  5476. set_task(0.2, "spec_nvision", id)
  5477.  
  5478. // Round didn't start yet, nothing to worry about
  5479. if (g_newround) return;
  5480.  
  5481. // Get his new team
  5482. static team[2]
  5483. get_msg_arg_string(2, team, charsmax(team))
  5484.  
  5485. // Perform some checks to see if they should join a different team instead
  5486. switch (team[0])
  5487. {
  5488. case 'C': // CT
  5489. {
  5490. if (g_survround && fnGetHumans()) // survivor alive --> switch to T and spawn as zombie
  5491. {
  5492. g_respawn_as_zombie[id] = true;
  5493. remove_task(id+TASK_TEAM)
  5494. fm_cs_set_user_team(id, FM_CS_TEAM_T)
  5495. set_msg_arg_string(2, "TERRORIST")
  5496. }
  5497. else if (!fnGetZombies()) // no zombies alive --> switch to T and spawn as zombie
  5498. {
  5499. g_respawn_as_zombie[id] = true;
  5500. remove_task(id+TASK_TEAM)
  5501. fm_cs_set_user_team(id, FM_CS_TEAM_T)
  5502. set_msg_arg_string(2, "TERRORIST")
  5503. }
  5504. }
  5505. case 'T': // Terrorist
  5506. {
  5507. if ((g_swarmround || g_survround) && fnGetHumans()) // survivor alive or swarm round w/ humans --> spawn as zombie
  5508. {
  5509. g_respawn_as_zombie[id] = true;
  5510. }
  5511. else if (fnGetZombies()) // zombies alive --> switch to CT
  5512. {
  5513. remove_task(id+TASK_TEAM)
  5514. fm_cs_set_user_team(id, FM_CS_TEAM_CT)
  5515. set_msg_arg_string(2, "CT")
  5516. }
  5517. }
  5518. }
  5519. }
  5520.  
  5521. /*================================================================================
  5522. [Main Functions]
  5523. =================================================================================*/
  5524.  
  5525. // Make Zombie Task
  5526. public make_zombie_task()
  5527. {
  5528. // Call make a zombie with no specific mode
  5529. make_a_zombie(MODE_NONE, 0)
  5530. }
  5531.  
  5532. // Make a Zombie Function
  5533. make_a_zombie(mode, id)
  5534. {
  5535. // Get alive players count
  5536. static iPlayersnum
  5537. iPlayersnum = fnGetAlive()
  5538.  
  5539. // Not enough players, come back later!
  5540. if (iPlayersnum < 1)
  5541. {
  5542. set_task(2.0, "make_zombie_task", TASK_MAKEZOMBIE)
  5543. return;
  5544. }
  5545.  
  5546. // Round started!
  5547. g_newround = false
  5548.  
  5549. // Set up some common vars
  5550. static forward_id, sound[64], iZombies, iMaxZombies
  5551.  
  5552. if ((mode == MODE_NONE && (!get_pcvar_num(cvar_preventconsecutive) || g_lastmode != MODE_SURVIVOR) && random_num(1, get_pcvar_num(cvar_survchance)) == get_pcvar_num(cvar_surv) && iPlayersnum >= get_pcvar_num(cvar_survminplayers)) || mode == MODE_SURVIVOR)
  5553. {
  5554. // Survivor Mode
  5555. g_survround = true
  5556. g_lastmode = MODE_SURVIVOR
  5557.  
  5558. // Choose player randomly?
  5559. if (mode == MODE_NONE)
  5560. id = fnGetRandomAlive(random_num(1, iPlayersnum))
  5561.  
  5562. // Remember id for calling our forward later
  5563. forward_id = id
  5564.  
  5565. // Turn player into a survivor
  5566. humanme(id, 1, 0)
  5567.  
  5568. // Turn the remaining players into zombies
  5569. for (id = 1; id <= g_maxplayers; id++)
  5570. {
  5571. // Not alive
  5572. if (!g_isalive[id])
  5573. continue;
  5574.  
  5575. // Survivor or already a zombie
  5576. if (g_survivor[id] || g_zombie[id])
  5577. continue;
  5578.  
  5579. // Turn into a zombie
  5580. zombieme(id, 0, 0, 1, 0)
  5581. }
  5582.  
  5583. // Play survivor sound
  5584. ArrayGetString(sound_survivor, random_num(0, ArraySize(sound_survivor) - 1), sound, charsmax(sound))
  5585. PlaySound(sound);
  5586.  
  5587. // Show Survivor HUD notice
  5588. set_hudmessage(20, 20, 255, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
  5589. ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_SURVIVOR", g_playername[forward_id])
  5590.  
  5591. // Mode fully started!
  5592. g_modestarted = true
  5593.  
  5594. // Round start forward
  5595. ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_SURVIVOR, forward_id);
  5596. }
  5597. else if ((mode == MODE_NONE && (!get_pcvar_num(cvar_preventconsecutive) || g_lastmode != MODE_SWARM) && random_num(1, get_pcvar_num(cvar_swarmchance)) == get_pcvar_num(cvar_swarm) && iPlayersnum >= get_pcvar_num(cvar_swarmminplayers)) || mode == MODE_SWARM)
  5598. {
  5599. // Swarm Mode
  5600. g_swarmround = true
  5601. g_lastmode = MODE_SWARM
  5602.  
  5603. // Make sure there are alive players on both teams (BUGFIX)
  5604. if (!fnGetAliveTs())
  5605. {
  5606. // Move random player to T team
  5607. id = fnGetRandomAlive(random_num(1, iPlayersnum))
  5608. remove_task(id+TASK_TEAM)
  5609. fm_cs_set_user_team(id, FM_CS_TEAM_T)
  5610. fm_user_team_update(id)
  5611. }
  5612. else if (!fnGetAliveCTs())
  5613. {
  5614. // Move random player to CT team
  5615. id = fnGetRandomAlive(random_num(1, iPlayersnum))
  5616. remove_task(id+TASK_TEAM)
  5617. fm_cs_set_user_team(id, FM_CS_TEAM_CT)
  5618. fm_user_team_update(id)
  5619. }
  5620.  
  5621. // Turn every T into a zombie
  5622. for (id = 1; id <= g_maxplayers; id++)
  5623. {
  5624. // Not alive
  5625. if (!g_isalive[id])
  5626. continue;
  5627.  
  5628. // Not a Terrorist
  5629. if (fm_cs_get_user_team(id) != FM_CS_TEAM_T)
  5630. continue;
  5631.  
  5632. // Turn into a zombie
  5633. zombieme(id, 0, 0, 1, 0)
  5634. }
  5635.  
  5636. // Play swarm sound
  5637. ArrayGetString(sound_swarm, random_num(0, ArraySize(sound_swarm) - 1), sound, charsmax(sound))
  5638. PlaySound(sound);
  5639.  
  5640. // Show Swarm HUD notice
  5641. set_hudmessage(20, 255, 20, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
  5642. ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_SWARM")
  5643.  
  5644. // Mode fully started!
  5645. g_modestarted = true
  5646.  
  5647. // Round start forward
  5648. ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_SWARM, 0);
  5649. }
  5650. else if ((mode == MODE_NONE && (!get_pcvar_num(cvar_preventconsecutive) || g_lastmode != MODE_MULTI) && random_num(1, get_pcvar_num(cvar_multichance)) == get_pcvar_num(cvar_multi) && floatround(iPlayersnum*get_pcvar_float(cvar_multiratio), floatround_ceil) >= 2 && floatround(iPlayersnum*get_pcvar_float(cvar_multiratio), floatround_ceil) < iPlayersnum && iPlayersnum >= get_pcvar_num(cvar_multiminplayers)) || mode == MODE_MULTI)
  5651. {
  5652. // Multi Infection Mode
  5653. g_lastmode = MODE_MULTI
  5654.  
  5655. // iMaxZombies is rounded up, in case there aren't enough players
  5656. iMaxZombies = floatround(iPlayersnum*get_pcvar_float(cvar_multiratio), floatround_ceil)
  5657. iZombies = 0
  5658.  
  5659. // Randomly turn iMaxZombies players into zombies
  5660. while (iZombies < iMaxZombies)
  5661. {
  5662. // Keep looping through all players
  5663. if (++id > g_maxplayers) id = 1
  5664.  
  5665. // Dead or already a zombie
  5666. if (!g_isalive[id] || g_zombie[id])
  5667. continue;
  5668.  
  5669. // Random chance
  5670. if (random_num(0, 1))
  5671. {
  5672. // Turn into a zombie
  5673. zombieme(id, 0, 0, 1, 0)
  5674. iZombies++
  5675. }
  5676. }
  5677.  
  5678. // Turn the remaining players into humans
  5679. for (id = 1; id <= g_maxplayers; id++)
  5680. {
  5681. // Only those of them who aren't zombies
  5682. if (!g_isalive[id] || g_zombie[id])
  5683. continue;
  5684.  
  5685. // Switch to CT
  5686. if (fm_cs_get_user_team(id) != FM_CS_TEAM_CT) // need to change team?
  5687. {
  5688. remove_task(id+TASK_TEAM)
  5689. fm_cs_set_user_team(id, FM_CS_TEAM_CT)
  5690. fm_user_team_update(id)
  5691. }
  5692. }
  5693.  
  5694. // Play multi infection sound
  5695. ArrayGetString(sound_multi, random_num(0, ArraySize(sound_multi) - 1), sound, charsmax(sound))
  5696. PlaySound(sound);
  5697.  
  5698. // Show Multi Infection HUD notice
  5699. set_hudmessage(200, 50, 0, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
  5700. ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_MULTI")
  5701.  
  5702. // Mode fully started!
  5703. g_modestarted = true
  5704.  
  5705. // Round start forward
  5706. ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_MULTI, 0);
  5707. }
  5708. else if ((mode == MODE_NONE && (!get_pcvar_num(cvar_preventconsecutive) || g_lastmode != MODE_PLAGUE) && random_num(1, get_pcvar_num(cvar_plaguechance)) == get_pcvar_num(cvar_plague) && floatround((iPlayersnum-(get_pcvar_num(cvar_plaguenemnum)+get_pcvar_num(cvar_plaguesurvnum)))*get_pcvar_float(cvar_plagueratio), floatround_ceil) >= 1
  5709. && iPlayersnum-(get_pcvar_num(cvar_plaguesurvnum)+get_pcvar_num(cvar_plaguenemnum)+floatround((iPlayersnum-(get_pcvar_num(cvar_plaguenemnum)+get_pcvar_num(cvar_plaguesurvnum)))*get_pcvar_float(cvar_plagueratio), floatround_ceil)) >= 1 && iPlayersnum >= get_pcvar_num(cvar_plagueminplayers)) || mode == MODE_PLAGUE)
  5710. {
  5711. // Plague Mode
  5712. g_plagueround = true
  5713. g_lastmode = MODE_PLAGUE
  5714.  
  5715. // Turn specified amount of players into Survivors
  5716. static iSurvivors, iMaxSurvivors
  5717. iMaxSurvivors = get_pcvar_num(cvar_plaguesurvnum)
  5718. iSurvivors = 0
  5719.  
  5720. while (iSurvivors < iMaxSurvivors)
  5721. {
  5722. // Choose random guy
  5723. id = fnGetRandomAlive(random_num(1, iPlayersnum))
  5724.  
  5725. // Already a survivor?
  5726. if (g_survivor[id])
  5727. continue;
  5728.  
  5729. // If not, turn him into one
  5730. humanme(id, 1, 0)
  5731. iSurvivors++
  5732.  
  5733. // Apply survivor health multiplier
  5734. fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_plaguesurvhpmulti)))
  5735. }
  5736.  
  5737. // Turn specified amount of players into Nemesis
  5738. static iNemesis, iMaxNemesis
  5739. iMaxNemesis = get_pcvar_num(cvar_plaguenemnum)
  5740. iNemesis = 0
  5741.  
  5742. while (iNemesis < iMaxNemesis)
  5743. {
  5744. // Choose random guy
  5745. id = fnGetRandomAlive(random_num(1, iPlayersnum))
  5746.  
  5747. // Already a survivor or nemesis?
  5748. if (g_survivor[id] || g_nemesis[id])
  5749. continue;
  5750.  
  5751. // If not, turn him into one
  5752. zombieme(id, 0, 1, 0, 0)
  5753. iNemesis++
  5754.  
  5755. // Apply nemesis health multiplier
  5756. fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_plaguenemhpmulti)))
  5757. }
  5758.  
  5759. // iMaxZombies is rounded up, in case there aren't enough players
  5760. iMaxZombies = floatround((iPlayersnum-(get_pcvar_num(cvar_plaguenemnum)+get_pcvar_num(cvar_plaguesurvnum)))*get_pcvar_float(cvar_plagueratio), floatround_ceil)
  5761. iZombies = 0
  5762.  
  5763. // Randomly turn iMaxZombies players into zombies
  5764. while (iZombies < iMaxZombies)
  5765. {
  5766. // Keep looping through all players
  5767. if (++id > g_maxplayers) id = 1
  5768.  
  5769. // Dead or already a zombie or survivor
  5770. if (!g_isalive[id] || g_zombie[id] || g_survivor[id])
  5771. continue;
  5772.  
  5773. // Random chance
  5774. if (random_num(0, 1))
  5775. {
  5776. // Turn into a zombie
  5777. zombieme(id, 0, 0, 1, 0)
  5778. iZombies++
  5779. }
  5780. }
  5781.  
  5782. // Turn the remaining players into humans
  5783. for (id = 1; id <= g_maxplayers; id++)
  5784. {
  5785. // Only those of them who arent zombies or survivor
  5786. if (!g_isalive[id] || g_zombie[id] || g_survivor[id])
  5787. continue;
  5788.  
  5789. // Switch to CT
  5790. if (fm_cs_get_user_team(id) != FM_CS_TEAM_CT) // need to change team?
  5791. {
  5792. remove_task(id+TASK_TEAM)
  5793. fm_cs_set_user_team(id, FM_CS_TEAM_CT)
  5794. fm_user_team_update(id)
  5795. }
  5796. }
  5797.  
  5798. // Play plague sound
  5799. ArrayGetString(sound_plague, random_num(0, ArraySize(sound_plague) - 1), sound, charsmax(sound))
  5800. PlaySound(sound);
  5801.  
  5802. // Show Plague HUD notice
  5803. set_hudmessage(0, 50, 200, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
  5804. ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_PLAGUE")
  5805.  
  5806. // Mode fully started!
  5807. g_modestarted = true
  5808.  
  5809. // Round start forward
  5810. ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_PLAGUE, 0);
  5811. }
  5812. else
  5813. {
  5814. // Single Infection Mode or Nemesis Mode
  5815.  
  5816. // Choose player randomly?
  5817. if (mode == MODE_NONE)
  5818. id = fnGetRandomAlive(random_num(1, iPlayersnum))
  5819.  
  5820. // Remember id for calling our forward later
  5821. forward_id = id
  5822.  
  5823. if ((mode == MODE_NONE && (!get_pcvar_num(cvar_preventconsecutive) || g_lastmode != MODE_NEMESIS) && random_num(1, get_pcvar_num(cvar_nemchance)) == get_pcvar_num(cvar_nem) && iPlayersnum >= get_pcvar_num(cvar_nemminplayers)) || mode == MODE_NEMESIS)
  5824. {
  5825. // Nemesis Mode
  5826. g_nemround = true
  5827. g_lastmode = MODE_NEMESIS
  5828.  
  5829. // Turn player into nemesis
  5830. zombieme(id, 0, 1, 0, 0)
  5831. }
  5832. else
  5833. {
  5834. // Single Infection Mode
  5835. g_lastmode = MODE_INFECTION
  5836.  
  5837. // Turn player into the first zombie
  5838. zombieme(id, 0, 0, 0, 0)
  5839. }
  5840.  
  5841. // Remaining players should be humans (CTs)
  5842. for (id = 1; id <= g_maxplayers; id++)
  5843. {
  5844. // Not alive
  5845. if (!g_isalive[id])
  5846. continue;
  5847.  
  5848. // First zombie/nemesis
  5849. if (g_zombie[id])
  5850. continue;
  5851.  
  5852. // Switch to CT
  5853. if (fm_cs_get_user_team(id) != FM_CS_TEAM_CT) // need to change team?
  5854. {
  5855. remove_task(id+TASK_TEAM)
  5856. fm_cs_set_user_team(id, FM_CS_TEAM_CT)
  5857. fm_user_team_update(id)
  5858. }
  5859. }
  5860.  
  5861. if (g_nemround)
  5862. {
  5863. // Play Nemesis sound
  5864. ArrayGetString(sound_nemesis, random_num(0, ArraySize(sound_nemesis) - 1), sound, charsmax(sound))
  5865. PlaySound(sound);
  5866.  
  5867. // Show Nemesis HUD notice
  5868. set_hudmessage(255, 20, 20, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
  5869. ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_NEMESIS", g_playername[forward_id])
  5870.  
  5871. // Mode fully started!
  5872. g_modestarted = true
  5873.  
  5874. // Round start forward
  5875. ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_NEMESIS, forward_id);
  5876. }
  5877. else
  5878. {
  5879. // Show First Zombie HUD notice
  5880. set_hudmessage(255, 0, 0, HUD_EVENT_X, HUD_EVENT_Y, 0, 0.0, 5.0, 1.0, 1.0, -1)
  5881. ShowSyncHudMsg(0, g_MsgSync, "%L",LANG_PLAYER, "NOTICE_FIRST", g_playername[forward_id])
  5882.  
  5883. // Mode fully started!
  5884. g_modestarted = true
  5885.  
  5886. // Round start forward
  5887. ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_INFECTION, forward_id);
  5888. }
  5889. }
  5890.  
  5891. // Start ambience sounds after a mode begins
  5892. if ((g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS] && g_nemround) || (g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR] && g_survround) || (g_ambience_sounds[AMBIENCE_SOUNDS_SWARM] && g_swarmround) || (g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE] && g_plagueround) || (g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION] && !g_nemround && !g_survround && !g_swarmround && !g_plagueround))
  5893. {
  5894. remove_task(TASK_AMBIENCESOUNDS)
  5895. set_task(2.0, "ambience_sound_effects", TASK_AMBIENCESOUNDS)
  5896. }
  5897. }
  5898.  
  5899. // Zombie Me Function (player id, infector, turn into a nemesis, silent mode, deathmsg and rewards)
  5900. zombieme(id, infector, nemesis, silentmode, rewards)
  5901. {
  5902. // User infect attempt forward
  5903. ExecuteForward(g_fwUserInfect_attempt, g_fwDummyResult, id, infector, nemesis)
  5904.  
  5905. // One or more plugins blocked the infection. Only allow this after making sure it's
  5906. // not going to leave us with no zombies. Take into account a last player leaving case.
  5907. // BUGFIX: only allow after a mode has started, to prevent blocking first zombie e.g.
  5908. if (g_fwDummyResult >= ZP_PLUGIN_HANDLED && g_modestarted && fnGetZombies() > g_lastplayerleaving)
  5909. return;
  5910.  
  5911. // Pre user infect forward
  5912. ExecuteForward(g_fwUserInfected_pre, g_fwDummyResult, id, infector, nemesis)
  5913.  
  5914. // Show zombie class menu if they haven't chosen any (e.g. just connected)
  5915. if (g_zombieclassnext[id] == ZCLASS_NONE && get_pcvar_num(cvar_zclasses))
  5916. set_task(0.2, "show_menu_zclass", id)
  5917.  
  5918. // Set selected zombie class
  5919. g_zombieclass[id] = g_zombieclassnext[id]
  5920. // If no class selected yet, use the first (default) one
  5921. if (g_zombieclass[id] == ZCLASS_NONE) g_zombieclass[id] = 0
  5922.  
  5923. // Way to go...
  5924. g_zombie[id] = true
  5925. g_nemesis[id] = false
  5926. g_survivor[id] = false
  5927. g_firstzombie[id] = false
  5928.  
  5929. // Remove survivor's aura (bugfix)
  5930. set_pev(id, pev_effects, pev(id, pev_effects) &~ EF_BRIGHTLIGHT)
  5931.  
  5932. // Remove spawn protection (bugfix)
  5933. g_nodamage[id] = false
  5934. set_pev(id, pev_effects, pev(id, pev_effects) &~ EF_NODRAW)
  5935.  
  5936. // Reset burning duration counter (bugfix)
  5937. g_burning_duration[id] = 0
  5938.  
  5939. // Show deathmsg and reward infector?
  5940. if (rewards && infector)
  5941. {
  5942. // Send death notice and fix the "dead" attrib on scoreboard
  5943. SendDeathMsg(infector, id)
  5944. FixDeadAttrib(id)
  5945.  
  5946. // Reward frags, deaths, health, and ammo packs
  5947. UpdateFrags(infector, id, get_pcvar_num(cvar_fragsinfect), 1, 1)
  5948. g_ammopacks[infector] += get_pcvar_num(cvar_ammoinfect)
  5949. fm_set_user_health(infector, pev(infector, pev_health) + get_pcvar_num(cvar_zombiebonushp))
  5950. }
  5951.  
  5952. // Cache speed, knockback, and name for player's class
  5953. g_zombie_spd[id] = float(ArrayGetCell(g_zclass_spd, g_zombieclass[id]))
  5954. g_zombie_knockback[id] = Float:ArrayGetCell(g_zclass_kb, g_zombieclass[id])
  5955. ArrayGetString(g_zclass_name, g_zombieclass[id], g_zombie_classname[id], charsmax(g_zombie_classname[]))
  5956.  
  5957. // Set zombie attributes based on the mode
  5958. static sound[64]
  5959. if (!silentmode)
  5960. {
  5961. if (nemesis)
  5962. {
  5963. // Nemesis
  5964. g_nemesis[id] = true
  5965.  
  5966. // Set health [0 = auto]
  5967. if (get_pcvar_num(cvar_nemhp) == 0)
  5968. {
  5969. if (get_pcvar_num(cvar_nembasehp) == 0)
  5970. fm_set_user_health(id, ArrayGetCell(g_zclass_hp, 0) * fnGetAlive())
  5971. else
  5972. fm_set_user_health(id, get_pcvar_num(cvar_nembasehp) * fnGetAlive())
  5973. }
  5974. else
  5975. fm_set_user_health(id, get_pcvar_num(cvar_nemhp))
  5976.  
  5977. // Set gravity, if frozen set the restore gravity value instead
  5978. if (!g_frozen[id]) set_pev(id, pev_gravity, get_pcvar_float(cvar_nemgravity))
  5979. else g_frozen_gravity[id] = get_pcvar_float(cvar_nemgravity)
  5980.  
  5981. // Set nemesis maxspeed
  5982. ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
  5983. }
  5984. else if (fnGetZombies() == 1)
  5985. {
  5986. // First zombie
  5987. g_firstzombie[id] = true
  5988.  
  5989. // Set health
  5990. fm_set_user_health(id, floatround(float(ArrayGetCell(g_zclass_hp, g_zombieclass[id])) * get_pcvar_float(cvar_zombiefirsthp)))
  5991.  
  5992. // Set gravity, if frozen set the restore gravity value instead
  5993. if (!g_frozen[id]) set_pev(id, pev_gravity, Float:ArrayGetCell(g_zclass_grav, g_zombieclass[id]))
  5994. else g_frozen_gravity[id] = Float:ArrayGetCell(g_zclass_grav, g_zombieclass[id])
  5995.  
  5996. // Set zombie maxspeed
  5997. ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
  5998.  
  5999. // Infection sound
  6000. ArrayGetString(zombie_infect, random_num(0, ArraySize(zombie_infect) - 1), sound, charsmax(sound))
  6001. emit_sound(id, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  6002. }
  6003. else
  6004. {
  6005. // Infected by someone
  6006.  
  6007. // Set health
  6008. fm_set_user_health(id, ArrayGetCell(g_zclass_hp, g_zombieclass[id]))
  6009.  
  6010. // Set gravity, if frozen set the restore gravity value instead
  6011. if (!g_frozen[id]) set_pev(id, pev_gravity, Float:ArrayGetCell(g_zclass_grav, g_zombieclass[id]))
  6012. else g_frozen_gravity[id] = Float:ArrayGetCell(g_zclass_grav, g_zombieclass[id])
  6013.  
  6014. // Set zombie maxspeed
  6015. ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
  6016.  
  6017. // Infection sound
  6018. ArrayGetString(zombie_infect, random_num(0, ArraySize(zombie_infect) - 1), sound, charsmax(sound))
  6019. emit_sound(id, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  6020.  
  6021. // Show Infection HUD notice
  6022. set_hudmessage(255, 0, 0, HUD_INFECT_X, HUD_INFECT_Y, 0, 0.0, 5.0, 1.0, 1.0, -1)
  6023.  
  6024. if (infector) // infected by someone?
  6025. ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_INFECT2", g_playername[id], g_playername[infector])
  6026. else
  6027. ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_INFECT", g_playername[id])
  6028. }
  6029. }
  6030. else
  6031. {
  6032. // Silent mode, no HUD messages, no infection sounds
  6033.  
  6034. // Set health
  6035. fm_set_user_health(id, ArrayGetCell(g_zclass_hp, g_zombieclass[id]))
  6036.  
  6037. // Set gravity, if frozen set the restore gravity value instead
  6038. if (!g_frozen[id]) set_pev(id, pev_gravity, Float:ArrayGetCell(g_zclass_grav, g_zombieclass[id]))
  6039. else g_frozen_gravity[id] = Float:ArrayGetCell(g_zclass_grav, g_zombieclass[id])
  6040.  
  6041. // Set zombie maxspeed
  6042. ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
  6043. }
  6044.  
  6045. // Remove previous tasks
  6046. remove_task(id+TASK_MODEL)
  6047. remove_task(id+TASK_BLOOD)
  6048. remove_task(id+TASK_AURA)
  6049. remove_task(id+TASK_BURN)
  6050.  
  6051. // Switch to T
  6052. if (fm_cs_get_user_team(id) != FM_CS_TEAM_T) // need to change team?
  6053. {
  6054. remove_task(id+TASK_TEAM)
  6055. fm_cs_set_user_team(id, FM_CS_TEAM_T)
  6056. fm_user_team_update(id)
  6057. }
  6058.  
  6059. // Custom models stuff
  6060. static currentmodel[32], tempmodel[32], already_has_model, i, iRand, size
  6061. already_has_model = false
  6062.  
  6063. if (g_handle_models_on_separate_ent)
  6064. {
  6065. // Set the right model
  6066. if (g_nemesis[id])
  6067. {
  6068. iRand = random_num(0, ArraySize(model_nemesis) - 1)
  6069. ArrayGetString(model_nemesis, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  6070. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_nemesis, iRand))
  6071. }
  6072. else
  6073. {
  6074. if (get_pcvar_num(cvar_adminmodelszombie) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
  6075. {
  6076. iRand = random_num(0, ArraySize(model_admin_zombie) - 1)
  6077. ArrayGetString(model_admin_zombie, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  6078. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_zombie, iRand))
  6079. }
  6080. else
  6081. {
  6082. iRand = random_num(ArrayGetCell(g_zclass_modelsstart, g_zombieclass[id]), ArrayGetCell(g_zclass_modelsend, g_zombieclass[id]) - 1)
  6083. ArrayGetString(g_zclass_playermodel, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  6084. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_zclass_modelindex, iRand))
  6085. }
  6086. }
  6087.  
  6088. // Set model on player model entity
  6089. fm_set_playermodel_ent(id)
  6090.  
  6091. // Nemesis glow / remove glow on player model entity, unless frozen
  6092. if (!g_frozen[id])
  6093. {
  6094. if (g_nemesis[id] && get_pcvar_num(cvar_nemglow))
  6095. fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 255, 0, 0, kRenderNormal, 25)
  6096. else
  6097. fm_set_rendering(g_ent_playermodel[id])
  6098. }
  6099. }
  6100. else
  6101. {
  6102. // Get current model for comparing it with the current one
  6103. fm_cs_get_user_model(id, currentmodel, charsmax(currentmodel))
  6104.  
  6105. // Set the right model, after checking that we don't already have it
  6106. if (g_nemesis[id])
  6107. {
  6108. size = ArraySize(model_nemesis)
  6109. for (i = 0; i < size; i++)
  6110. {
  6111. ArrayGetString(model_nemesis, i, tempmodel, charsmax(tempmodel))
  6112. if (equal(currentmodel, tempmodel)) already_has_model = true
  6113. }
  6114.  
  6115. if (!already_has_model)
  6116. {
  6117. iRand = random_num(0, size - 1)
  6118. ArrayGetString(model_nemesis, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  6119. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_nemesis, iRand))
  6120. }
  6121. }
  6122. else
  6123. {
  6124. if (get_pcvar_num(cvar_adminmodelszombie) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
  6125. {
  6126. size = ArraySize(model_admin_zombie)
  6127. for (i = 0; i < size; i++)
  6128. {
  6129. ArrayGetString(model_admin_zombie, i, tempmodel, charsmax(tempmodel))
  6130. if (equal(currentmodel, tempmodel)) already_has_model = true
  6131. }
  6132.  
  6133. if (!already_has_model)
  6134. {
  6135. iRand = random_num(0, size - 1)
  6136. ArrayGetString(model_admin_zombie, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  6137. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_zombie, iRand))
  6138. }
  6139. }
  6140. else
  6141. {
  6142. for (i = ArrayGetCell(g_zclass_modelsstart, g_zombieclass[id]); i < ArrayGetCell(g_zclass_modelsend, g_zombieclass[id]); i++)
  6143. {
  6144. ArrayGetString(g_zclass_playermodel, i, tempmodel, charsmax(tempmodel))
  6145. if (equal(currentmodel, tempmodel)) already_has_model = true
  6146. }
  6147.  
  6148. if (!already_has_model)
  6149. {
  6150. iRand = random_num(ArrayGetCell(g_zclass_modelsstart, g_zombieclass[id]), ArrayGetCell(g_zclass_modelsend, g_zombieclass[id]) - 1)
  6151. ArrayGetString(g_zclass_playermodel, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  6152. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_zclass_modelindex, iRand))
  6153. }
  6154. }
  6155. }
  6156.  
  6157. // Need to change the model?
  6158. if (!already_has_model)
  6159. {
  6160. // An additional delay is offset at round start
  6161. // since SVC_BAD is more likely to be triggered there
  6162. if (g_newround)
  6163. set_task(5.0 * g_modelchange_delay, "fm_user_model_update", id+TASK_MODEL)
  6164. else
  6165. fm_user_model_update(id+TASK_MODEL)
  6166. }
  6167.  
  6168. // Nemesis glow / remove glow, unless frozen
  6169. if (!g_frozen[id])
  6170. {
  6171. if (g_nemesis[id] && get_pcvar_num(cvar_nemglow))
  6172. fm_set_rendering(id, kRenderFxGlowShell, 255, 0, 0, kRenderNormal, 25)
  6173. else
  6174. fm_set_rendering(id)
  6175. }
  6176. }
  6177.  
  6178. // Remove any zoom (bugfix)
  6179. cs_set_user_zoom(id, CS_RESET_ZOOM, 1)
  6180.  
  6181. // Remove armor
  6182. cs_set_user_armor(id, 0, CS_ARMOR_NONE)
  6183.  
  6184. // Drop weapons when infected
  6185. drop_weapons(id, 1)
  6186. drop_weapons(id, 2)
  6187.  
  6188. // Strip zombies from guns and give them a knife
  6189. fm_strip_user_weapons(id)
  6190. fm_give_item(id, "weapon_knife")
  6191.  
  6192. // Fancy effects
  6193. infection_effects(id)
  6194.  
  6195. // Nemesis aura task
  6196. if (g_nemesis[id] && get_pcvar_num(cvar_nemaura))
  6197. set_task(0.1, "zombie_aura", id+TASK_AURA, _, _, "b")
  6198.  
  6199. // Remove CS nightvision if player owns one (bugfix)
  6200. if (cs_get_user_nvg(id))
  6201. {
  6202. cs_set_user_nvg(id, 0)
  6203. if (get_pcvar_num(cvar_customnvg)) remove_task(id+TASK_NVISION)
  6204. else if (g_nvisionenabled[id]) set_user_gnvision(id, 0)
  6205. }
  6206.  
  6207. // Give Zombies Night Vision?
  6208. if (get_pcvar_num(cvar_nvggive))
  6209. {
  6210. g_nvision[id] = true
  6211.  
  6212. if (!g_isbot[id])
  6213. {
  6214. // Turn on Night Vision automatically?
  6215. if (get_pcvar_num(cvar_nvggive) == 1)
  6216. {
  6217. g_nvisionenabled[id] = true
  6218.  
  6219. // Custom nvg?
  6220. if (get_pcvar_num(cvar_customnvg))
  6221. {
  6222. remove_task(id+TASK_NVISION)
  6223. set_task(0.1, "set_user_nvision", id+TASK_NVISION, _, _, "b")
  6224. }
  6225. else
  6226. set_user_gnvision(id, 1)
  6227. }
  6228. // Turn off nightvision when infected (bugfix)
  6229. else if (g_nvisionenabled[id])
  6230. {
  6231. if (get_pcvar_num(cvar_customnvg)) remove_task(id+TASK_NVISION)
  6232. else set_user_gnvision(id, 0)
  6233. g_nvisionenabled[id] = false
  6234. }
  6235. }
  6236. else
  6237. cs_set_user_nvg(id, 1); // turn on NVG for bots
  6238. }
  6239. // Disable nightvision when infected (bugfix)
  6240. else if (g_nvision[id])
  6241. {
  6242. if (get_pcvar_num(cvar_customnvg)) remove_task(id+TASK_NVISION)
  6243. else if (g_nvisionenabled[id]) set_user_gnvision(id, 0)
  6244. g_nvision[id] = false
  6245. g_nvisionenabled[id] = false
  6246. }
  6247.  
  6248. // Set custom FOV?
  6249. if (get_pcvar_num(cvar_zombiefov) != 90 && get_pcvar_num(cvar_zombiefov) != 0)
  6250. {
  6251. message_begin(MSG_ONE, g_msgSetFOV, _, id)
  6252. write_byte(get_pcvar_num(cvar_zombiefov)) // fov angle
  6253. message_end()
  6254. }
  6255.  
  6256. // Call the bloody task
  6257. if (!g_nemesis[id] && get_pcvar_num(cvar_zombiebleeding))
  6258. set_task(0.7, "make_blood", id+TASK_BLOOD, _, _, "b")
  6259.  
  6260. // Idle sounds task
  6261. if (!g_nemesis[id])
  6262. set_task(random_float(50.0, 70.0), "zombie_play_idle", id+TASK_BLOOD, _, _, "b")
  6263.  
  6264. // Turn off zombie's flashlight
  6265. turn_off_flashlight(id)
  6266.  
  6267. // Post user infect forward
  6268. ExecuteForward(g_fwUserInfected_post, g_fwDummyResult, id, infector, nemesis)
  6269.  
  6270. // Last Zombie Check
  6271. fnCheckLastZombie()
  6272. }
  6273.  
  6274. // Function Human Me (player id, turn into a survivor, silent mode)
  6275. humanme(id, survivor, silentmode)
  6276. {
  6277. // User humanize attempt forward
  6278. ExecuteForward(g_fwUserHumanize_attempt, g_fwDummyResult, id, survivor)
  6279.  
  6280. // One or more plugins blocked the "humanization". Only allow this after making sure it's
  6281. // not going to leave us with no humans. Take into account a last player leaving case.
  6282. // BUGFIX: only allow after a mode has started, to prevent blocking first survivor e.g.
  6283. if (g_fwDummyResult >= ZP_PLUGIN_HANDLED && g_modestarted && fnGetHumans() > g_lastplayerleaving)
  6284. return;
  6285.  
  6286. // Pre user humanize forward
  6287. ExecuteForward(g_fwUserHumanized_pre, g_fwDummyResult, id, survivor)
  6288.  
  6289. // Remove previous tasks
  6290. remove_task(id+TASK_MODEL)
  6291. remove_task(id+TASK_BLOOD)
  6292. remove_task(id+TASK_AURA)
  6293. remove_task(id+TASK_BURN)
  6294. remove_task(id+TASK_NVISION)
  6295.  
  6296. // Reset some vars
  6297. g_zombie[id] = false
  6298. g_nemesis[id] = false
  6299. g_survivor[id] = false
  6300. g_firstzombie[id] = false
  6301. g_canbuy[id] = true
  6302. g_buytime[id] = get_gametime()
  6303.  
  6304. // Remove survivor's aura (bugfix)
  6305. set_pev(id, pev_effects, pev(id, pev_effects) &~ EF_BRIGHTLIGHT)
  6306.  
  6307. // Remove spawn protection (bugfix)
  6308. g_nodamage[id] = false
  6309. set_pev(id, pev_effects, pev(id, pev_effects) &~ EF_NODRAW)
  6310.  
  6311. // Reset burning duration counter (bugfix)
  6312. g_burning_duration[id] = 0
  6313.  
  6314. // Remove CS nightvision if player owns one (bugfix)
  6315. if (cs_get_user_nvg(id))
  6316. {
  6317. cs_set_user_nvg(id, 0)
  6318. if (get_pcvar_num(cvar_customnvg)) remove_task(id+TASK_NVISION)
  6319. else if (g_nvisionenabled[id]) set_user_gnvision(id, 0)
  6320. }
  6321.  
  6322. // Drop previous weapons
  6323. drop_weapons(id, 1)
  6324. drop_weapons(id, 2)
  6325.  
  6326. // Strip off from weapons
  6327. fm_strip_user_weapons(id)
  6328. fm_give_item(id, "weapon_knife")
  6329.  
  6330. // Set human attributes based on the mode
  6331. if (survivor)
  6332. {
  6333. // Survivor
  6334. g_survivor[id] = true
  6335.  
  6336. // Set Health [0 = auto]
  6337. if (get_pcvar_num(cvar_survhp) == 0)
  6338. {
  6339. if (get_pcvar_num(cvar_survbasehp) == 0)
  6340. fm_set_user_health(id, get_pcvar_num(cvar_humanhp) * fnGetAlive())
  6341. else
  6342. fm_set_user_health(id, get_pcvar_num(cvar_survbasehp) * fnGetAlive())
  6343. }
  6344. else
  6345. fm_set_user_health(id, get_pcvar_num(cvar_survhp))
  6346.  
  6347. // Set gravity, if frozen set the restore gravity value instead
  6348. if (!g_frozen[id]) set_pev(id, pev_gravity, get_pcvar_float(cvar_survgravity))
  6349. else g_frozen_gravity[id] = get_pcvar_float(cvar_survgravity)
  6350.  
  6351. // Set survivor maxspeed
  6352. ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
  6353.  
  6354. // Give survivor his own weapon
  6355. static survweapon[32]
  6356. get_pcvar_string(cvar_survweapon, survweapon, charsmax(survweapon))
  6357. fm_give_item(id, survweapon)
  6358. ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[cs_weapon_name_to_id(survweapon)], AMMOTYPE[cs_weapon_name_to_id(survweapon)], MAXBPAMMO[cs_weapon_name_to_id(survweapon)])
  6359.  
  6360. // Turn off his flashlight
  6361. turn_off_flashlight(id)
  6362.  
  6363. // Give the survivor a bright light
  6364. if (get_pcvar_num(cvar_survaura)) set_pev(id, pev_effects, pev(id, pev_effects) | EF_BRIGHTLIGHT)
  6365.  
  6366. // Survivor bots will also need nightvision to see in the dark
  6367. if (g_isbot[id])
  6368. {
  6369. g_nvision[id] = true
  6370. cs_set_user_nvg(id, 1)
  6371. }
  6372. }
  6373. else
  6374. {
  6375. // Human taking an antidote
  6376.  
  6377. // Set health
  6378. fm_set_user_health(id, get_pcvar_num(cvar_humanhp))
  6379.  
  6380. // Set gravity, if frozen set the restore gravity value instead
  6381. if (!g_frozen[id]) set_pev(id, pev_gravity, get_pcvar_float(cvar_humangravity))
  6382. else g_frozen_gravity[id] = get_pcvar_float(cvar_humangravity)
  6383.  
  6384. // Set human maxspeed
  6385. ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
  6386.  
  6387. // Show custom buy menu?
  6388. if (get_pcvar_num(cvar_buycustom))
  6389. set_task(0.2, "show_menu_buy1", id+TASK_SPAWN)
  6390.  
  6391. // Silent mode = no HUD messages, no antidote sound
  6392. if (!silentmode)
  6393. {
  6394. // Antidote sound
  6395. static sound[64]
  6396. ArrayGetString(sound_antidote, random_num(0, ArraySize(sound_antidote) - 1), sound, charsmax(sound))
  6397. emit_sound(id, CHAN_ITEM, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  6398.  
  6399. // Show Antidote HUD notice
  6400. set_hudmessage(0, 0, 255, HUD_INFECT_X, HUD_INFECT_Y, 0, 0.0, 5.0, 1.0, 1.0, -1)
  6401. ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_ANTIDOTE", g_playername[id])
  6402. }
  6403. }
  6404.  
  6405. // Switch to CT
  6406. if (fm_cs_get_user_team(id) != FM_CS_TEAM_CT) // need to change team?
  6407. {
  6408. remove_task(id+TASK_TEAM)
  6409. fm_cs_set_user_team(id, FM_CS_TEAM_CT)
  6410. fm_user_team_update(id)
  6411. }
  6412.  
  6413. // Custom models stuff
  6414. static currentmodel[32], tempmodel[32], already_has_model, i, iRand, size
  6415. already_has_model = false
  6416.  
  6417. if (g_handle_models_on_separate_ent)
  6418. {
  6419. // Set the right model
  6420. if (g_survivor[id])
  6421. {
  6422. iRand = random_num(0, ArraySize(model_survivor) - 1)
  6423. ArrayGetString(model_survivor, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  6424. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_survivor, iRand))
  6425. }
  6426. else
  6427. {
  6428. if (get_pcvar_num(cvar_adminmodelshuman) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
  6429. {
  6430. iRand = random_num(0, ArraySize(model_admin_human) - 1)
  6431. ArrayGetString(model_admin_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  6432. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_human, iRand))
  6433. }
  6434. else
  6435. {
  6436. iRand = random_num(0, ArraySize(model_human) - 1)
  6437. ArrayGetString(model_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  6438. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_human, iRand))
  6439. }
  6440. }
  6441.  
  6442. // Set model on player model entity
  6443. fm_set_playermodel_ent(id)
  6444.  
  6445. // Set survivor glow / remove glow on player model entity, unless frozen
  6446. if (!g_frozen[id])
  6447. {
  6448. if (g_survivor[id] && get_pcvar_num(cvar_survglow))
  6449. fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 0, 0, 255, kRenderNormal, 25)
  6450. else
  6451. fm_set_rendering(g_ent_playermodel[id])
  6452. }
  6453. }
  6454. else
  6455. {
  6456. // Get current model for comparing it with the current one
  6457. fm_cs_get_user_model(id, currentmodel, charsmax(currentmodel))
  6458.  
  6459. // Set the right model, after checking that we don't already have it
  6460. if (g_survivor[id])
  6461. {
  6462. size = ArraySize(model_survivor)
  6463. for (i = 0; i < size; i++)
  6464. {
  6465. ArrayGetString(model_survivor, i, tempmodel, charsmax(tempmodel))
  6466. if (equal(currentmodel, tempmodel)) already_has_model = true
  6467. }
  6468.  
  6469. if (!already_has_model)
  6470. {
  6471. iRand = random_num(0, size - 1)
  6472. ArrayGetString(model_survivor, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  6473. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_survivor, iRand))
  6474. }
  6475. }
  6476. else
  6477. {
  6478. if (get_pcvar_num(cvar_adminmodelshuman) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
  6479. {
  6480. size = ArraySize(model_admin_human)
  6481. for (i = 0; i < size; i++)
  6482. {
  6483. ArrayGetString(model_admin_human, i, tempmodel, charsmax(tempmodel))
  6484. if (equal(currentmodel, tempmodel)) already_has_model = true
  6485. }
  6486.  
  6487. if (!already_has_model)
  6488. {
  6489. iRand = random_num(0, size - 1)
  6490. ArrayGetString(model_admin_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  6491. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_human, iRand))
  6492. }
  6493. }
  6494. else
  6495. {
  6496. size = ArraySize(model_human)
  6497. for (i = 0; i < size; i++)
  6498. {
  6499. ArrayGetString(model_human, i, tempmodel, charsmax(tempmodel))
  6500. if (equal(currentmodel, tempmodel)) already_has_model = true
  6501. }
  6502.  
  6503. if (!already_has_model)
  6504. {
  6505. iRand = random_num(0, size - 1)
  6506. ArrayGetString(model_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
  6507. if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_human, iRand))
  6508. }
  6509. }
  6510. }
  6511.  
  6512. // Need to change the model?
  6513. if (!already_has_model)
  6514. {
  6515. // An additional delay is offset at round start
  6516. // since SVC_BAD is more likely to be triggered there
  6517. if (g_newround)
  6518. set_task(5.0 * g_modelchange_delay, "fm_user_model_update", id+TASK_MODEL)
  6519. else
  6520. fm_user_model_update(id+TASK_MODEL)
  6521. }
  6522.  
  6523. // Set survivor glow / remove glow, unless frozen
  6524. if (!g_frozen[id])
  6525. {
  6526. if (g_survivor[id] && get_pcvar_num(cvar_survglow))
  6527. fm_set_rendering(id, kRenderFxGlowShell, 0, 0, 255, kRenderNormal, 25)
  6528. else
  6529. fm_set_rendering(id)
  6530. }
  6531. }
  6532.  
  6533. // Restore FOV?
  6534. if (get_pcvar_num(cvar_zombiefov) != 90 && get_pcvar_num(cvar_zombiefov) != 0)
  6535. {
  6536. message_begin(MSG_ONE, g_msgSetFOV, _, id)
  6537. write_byte(90) // angle
  6538. message_end()
  6539. }
  6540.  
  6541. // Disable nightvision when turning into human/survivor (bugfix)
  6542. if (g_nvision[id])
  6543. {
  6544. if (get_pcvar_num(cvar_customnvg)) remove_task(id+TASK_NVISION)
  6545. else if (g_nvisionenabled[id]) set_user_gnvision(id, 0)
  6546. g_nvision[id] = false
  6547. g_nvisionenabled[id] = false
  6548. }
  6549.  
  6550. // Post user humanize forward
  6551. ExecuteForward(g_fwUserHumanized_post, g_fwDummyResult, id, survivor)
  6552.  
  6553. // Last Zombie Check
  6554. fnCheckLastZombie()
  6555. }
  6556.  
  6557. /*================================================================================
  6558. [Other Functions and Tasks]
  6559. =================================================================================*/
  6560.  
  6561. public cache_cvars()
  6562. {
  6563. g_cached_zombiesilent = get_pcvar_num(cvar_zombiesilent)
  6564. g_cached_customflash = get_pcvar_num(cvar_customflash)
  6565. g_cached_leapzombies = get_pcvar_num(cvar_leapzombies)
  6566. g_cached_leapzombiescooldown = get_pcvar_float(cvar_leapzombiescooldown)
  6567. g_cached_leapnemesis = get_pcvar_num(cvar_leapnemesis)
  6568. g_cached_leapnemesiscooldown = get_pcvar_float(cvar_leapnemesiscooldown)
  6569. g_cached_leapsurvivor = get_pcvar_num(cvar_leapsurvivor)
  6570. g_cached_leapsurvivorcooldown = get_pcvar_float(cvar_leapsurvivorcooldown)
  6571. g_cached_buytime = get_pcvar_float(cvar_buyzonetime)
  6572. }
  6573.  
  6574. load_customization_from_files()
  6575. {
  6576. // Build customization file path
  6577. new path[64]
  6578. get_configsdir(path, charsmax(path))
  6579. format(path, charsmax(path), "%s/%s", path, ZP_CUSTOMIZATION_FILE)
  6580.  
  6581. // File not present
  6582. if (!file_exists(path))
  6583. {
  6584. new error[100]
  6585. formatex(error, charsmax(error), "Cannot load customization file %s!", path)
  6586. set_fail_state(error)
  6587. return;
  6588. }
  6589.  
  6590. // Set up some vars to hold parsing info
  6591. new linedata[1024], key[64], value[960], section, teams
  6592.  
  6593. // Open customization file for reading
  6594. new file = fopen(path, "rt")
  6595.  
  6596. while (file && !feof(file))
  6597. {
  6598. // Read one line at a time
  6599. fgets(file, linedata, charsmax(linedata))
  6600.  
  6601. // Replace newlines with a null character to prevent headaches
  6602. replace(linedata, charsmax(linedata), "^n", "")
  6603.  
  6604. // Blank line or comment
  6605. if (!linedata[0] || linedata[0] == ';') continue;
  6606.  
  6607. // New section starting
  6608. if (linedata[0] == '[')
  6609. {
  6610. section++
  6611. continue;
  6612. }
  6613.  
  6614. // Get key and value(s)
  6615. strtok(linedata, key, charsmax(key), value, charsmax(value), '=')
  6616.  
  6617. // Trim spaces
  6618. trim(key)
  6619. trim(value)
  6620.  
  6621. switch (section)
  6622. {
  6623. case SECTION_ACCESS_FLAGS:
  6624. {
  6625. if (equal(key, "ENABLE/DISABLE MOD"))
  6626. g_access_flag[ACCESS_ENABLE_MOD] = read_flags(value)
  6627. else if (equal(key, "ADMIN MENU"))
  6628. g_access_flag[ACCESS_ADMIN_MENU] = read_flags(value)
  6629. else if (equal(key, "START MODE INFECTION"))
  6630. g_access_flag[ACCESS_MODE_INFECTION] = read_flags(value)
  6631. else if (equal(key, "START MODE NEMESIS"))
  6632. g_access_flag[ACCESS_MODE_NEMESIS] = read_flags(value)
  6633. else if (equal(key, "START MODE SURVIVOR"))
  6634. g_access_flag[ACCESS_MODE_SURVIVOR] = read_flags(value)
  6635. else if (equal(key, "START MODE SWARM"))
  6636. g_access_flag[ACCESS_MODE_SWARM] = read_flags(value)
  6637. else if (equal(key, "START MODE MULTI"))
  6638. g_access_flag[ACCESS_MODE_MULTI] = read_flags(value)
  6639. else if (equal(key, "START MODE PLAGUE"))
  6640. g_access_flag[ACCESS_MODE_PLAGUE] = read_flags(value)
  6641. else if (equal(key, "MAKE ZOMBIE"))
  6642. g_access_flag[ACCESS_MAKE_ZOMBIE] = read_flags(value)
  6643. else if (equal(key, "MAKE HUMAN"))
  6644. g_access_flag[ACCESS_MAKE_HUMAN] = read_flags(value)
  6645. else if (equal(key, "MAKE NEMESIS"))
  6646. g_access_flag[ACCESS_MAKE_NEMESIS] = read_flags(value)
  6647. else if (equal(key, "MAKE SURVIVOR"))
  6648. g_access_flag[ACCESS_MAKE_SURVIVOR] = read_flags(value)
  6649. else if (equal(key, "RESPAWN PLAYERS"))
  6650. g_access_flag[ACCESS_RESPAWN_PLAYERS] = read_flags(value)
  6651. else if (equal(key, "ADMIN MODELS"))
  6652. g_access_flag[ACCESS_ADMIN_MODELS] = read_flags(value)
  6653. }
  6654. case SECTION_PLAYER_MODELS:
  6655. {
  6656. if (equal(key, "HUMAN"))
  6657. {
  6658. // Parse models
  6659. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6660. {
  6661. // Trim spaces
  6662. trim(key)
  6663. trim(value)
  6664.  
  6665. // Add to models array
  6666. ArrayPushString(model_human, key)
  6667. }
  6668. }
  6669. else if (equal(key, "NEMESIS"))
  6670. {
  6671. // Parse models
  6672. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6673. {
  6674. // Trim spaces
  6675. trim(key)
  6676. trim(value)
  6677.  
  6678. // Add to models array
  6679. ArrayPushString(model_nemesis, key)
  6680. }
  6681. }
  6682. else if (equal(key, "SURVIVOR"))
  6683. {
  6684. // Parse models
  6685. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6686. {
  6687. // Trim spaces
  6688. trim(key)
  6689. trim(value)
  6690.  
  6691. // Add to models array
  6692. ArrayPushString(model_survivor, key)
  6693. }
  6694. }
  6695. else if (equal(key, "ADMIN ZOMBIE"))
  6696. {
  6697. // Parse models
  6698. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6699. {
  6700. // Trim spaces
  6701. trim(key)
  6702. trim(value)
  6703.  
  6704. // Add to models array
  6705. ArrayPushString(model_admin_zombie, key)
  6706. }
  6707. }
  6708. else if (equal(key, "ADMIN HUMAN"))
  6709. {
  6710. // Parse models
  6711. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6712. {
  6713. // Trim spaces
  6714. trim(key)
  6715. trim(value)
  6716.  
  6717. // Add to models array
  6718. ArrayPushString(model_admin_human, key)
  6719. }
  6720. }
  6721. else if (equal(key, "FORCE CONSISTENCY"))
  6722. g_force_consistency = str_to_num(value)
  6723. else if (equal(key, "SAME MODELS FOR ALL"))
  6724. g_same_models_for_all = str_to_num(value)
  6725. else if (g_same_models_for_all && equal(key, "ZOMBIE"))
  6726. {
  6727. // Parse models
  6728. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6729. {
  6730. // Trim spaces
  6731. trim(key)
  6732. trim(value)
  6733.  
  6734. // Add to models array
  6735. ArrayPushString(g_zclass_playermodel, key)
  6736.  
  6737. // Precache model and retrieve its modelindex
  6738. formatex(linedata, charsmax(linedata), "models/player/%s/%s.mdl", key, key)
  6739. ArrayPushCell(g_zclass_modelindex, engfunc(EngFunc_PrecacheModel, linedata))
  6740. if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, linedata)
  6741. if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, linedata)
  6742. // Precache modelT.mdl files too
  6743. copy(linedata[strlen(linedata)-4], charsmax(linedata) - (strlen(linedata)-4), "T.mdl")
  6744. if (file_exists(linedata)) engfunc(EngFunc_PrecacheModel, linedata)
  6745. }
  6746. }
  6747. }
  6748. case SECTION_WEAPON_MODELS:
  6749. {
  6750. if (equal(key, "V_KNIFE HUMAN"))
  6751. copy(model_vknife_human, charsmax(model_vknife_human), value)
  6752. else if (equal(key, "V_KNIFE NEMESIS"))
  6753. copy(model_vknife_nemesis, charsmax(model_vknife_nemesis), value)
  6754. else if (equal(key, "V_M249 SURVIVOR")) // backwards compatibility with old configs
  6755. copy(model_vweapon_survivor, charsmax(model_vweapon_survivor), value)
  6756. else if (equal(key, "V_WEAPON SURVIVOR"))
  6757. copy(model_vweapon_survivor, charsmax(model_vweapon_survivor), value)
  6758. else if (equal(key, "GRENADE INFECT"))
  6759. copy(model_grenade_infect, charsmax(model_grenade_infect), value)
  6760. else if (equal(key, "GRENADE FIRE"))
  6761. copy(model_grenade_fire, charsmax(model_grenade_fire), value)
  6762. else if (equal(key, "GRENADE FROST"))
  6763. copy(model_grenade_frost, charsmax(model_grenade_frost), value)
  6764. else if (equal(key, "GRENADE FLARE"))
  6765. copy(model_grenade_flare, charsmax(model_grenade_flare), value)
  6766. else if (equal(key, "V_KNIFE ADMIN HUMAN"))
  6767. copy(model_vknife_admin_human, charsmax(model_vknife_admin_human), value)
  6768. else if (equal(key, "V_KNIFE ADMIN ZOMBIE"))
  6769. copy(model_vknife_admin_zombie, charsmax(model_vknife_admin_zombie), value)
  6770. }
  6771. case SECTION_GRENADE_SPRITES:
  6772. {
  6773. if (equal(key, "TRAIL"))
  6774. copy(sprite_grenade_trail, charsmax(sprite_grenade_trail), value)
  6775. else if (equal(key, "RING"))
  6776. copy(sprite_grenade_ring, charsmax(sprite_grenade_ring), value)
  6777. else if (equal(key, "FIRE"))
  6778. copy(sprite_grenade_fire, charsmax(sprite_grenade_fire), value)
  6779. else if (equal(key, "SMOKE"))
  6780. copy(sprite_grenade_smoke, charsmax(sprite_grenade_smoke), value)
  6781. else if (equal(key, "GLASS"))
  6782. copy(sprite_grenade_glass, charsmax(sprite_grenade_glass), value)
  6783. }
  6784. case SECTION_SOUNDS:
  6785. {
  6786. if (equal(key, "WIN ZOMBIES"))
  6787. {
  6788. // Parse sounds
  6789. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6790. {
  6791. // Trim spaces
  6792. trim(key)
  6793. trim(value)
  6794.  
  6795. // Add to sounds array
  6796. ArrayPushString(sound_win_zombies, key)
  6797. ArrayPushCell(sound_win_zombies_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
  6798. }
  6799. }
  6800. else if (equal(key, "WIN HUMANS"))
  6801. {
  6802. // Parse sounds
  6803. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6804. {
  6805. // Trim spaces
  6806. trim(key)
  6807. trim(value)
  6808.  
  6809. // Add to sounds array
  6810. ArrayPushString(sound_win_humans, key)
  6811. ArrayPushCell(sound_win_humans_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
  6812. }
  6813. }
  6814. else if (equal(key, "WIN NO ONE"))
  6815. {
  6816. // Parse sounds
  6817. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6818. {
  6819. // Trim spaces
  6820. trim(key)
  6821. trim(value)
  6822.  
  6823. // Add to sounds array
  6824. ArrayPushString(sound_win_no_one, key)
  6825. ArrayPushCell(sound_win_no_one_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
  6826. }
  6827. }
  6828. else if (equal(key, "ZOMBIE INFECT"))
  6829. {
  6830. // Parse sounds
  6831. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6832. {
  6833. // Trim spaces
  6834. trim(key)
  6835. trim(value)
  6836.  
  6837. // Add to sounds array
  6838. ArrayPushString(zombie_infect, key)
  6839. }
  6840. }
  6841. else if (equal(key, "ZOMBIE PAIN"))
  6842. {
  6843. // Parse sounds
  6844. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6845. {
  6846. // Trim spaces
  6847. trim(key)
  6848. trim(value)
  6849.  
  6850. // Add to sounds array
  6851. ArrayPushString(zombie_pain, key)
  6852. }
  6853. }
  6854. else if (equal(key, "NEMESIS PAIN"))
  6855. {
  6856. // Parse sounds
  6857. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6858. {
  6859. // Trim spaces
  6860. trim(key)
  6861. trim(value)
  6862.  
  6863. // Add to sounds array
  6864. ArrayPushString(nemesis_pain, key)
  6865. }
  6866. }
  6867. else if (equal(key, "ZOMBIE DIE"))
  6868. {
  6869. // Parse sounds
  6870. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6871. {
  6872. // Trim spaces
  6873. trim(key)
  6874. trim(value)
  6875.  
  6876. // Add to sounds array
  6877. ArrayPushString(zombie_die, key)
  6878. }
  6879. }
  6880. else if (equal(key, "ZOMBIE FALL"))
  6881. {
  6882. // Parse sounds
  6883. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6884. {
  6885. // Trim spaces
  6886. trim(key)
  6887. trim(value)
  6888.  
  6889. // Add to sounds array
  6890. ArrayPushString(zombie_fall, key)
  6891. }
  6892. }
  6893. else if (equal(key, "ZOMBIE MISS SLASH"))
  6894. {
  6895. // Parse sounds
  6896. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6897. {
  6898. // Trim spaces
  6899. trim(key)
  6900. trim(value)
  6901.  
  6902. // Add to sounds array
  6903. ArrayPushString(zombie_miss_slash, key)
  6904. }
  6905. }
  6906. else if (equal(key, "ZOMBIE MISS WALL"))
  6907. {
  6908. // Parse sounds
  6909. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6910. {
  6911. // Trim spaces
  6912. trim(key)
  6913. trim(value)
  6914.  
  6915. // Add to sounds array
  6916. ArrayPushString(zombie_miss_wall, key)
  6917. }
  6918. }
  6919. else if (equal(key, "ZOMBIE HIT NORMAL"))
  6920. {
  6921. // Parse sounds
  6922. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6923. {
  6924. // Trim spaces
  6925. trim(key)
  6926. trim(value)
  6927.  
  6928. // Add to sounds array
  6929. ArrayPushString(zombie_hit_normal, key)
  6930. }
  6931. }
  6932. else if (equal(key, "ZOMBIE HIT STAB"))
  6933. {
  6934. // Parse sounds
  6935. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6936. {
  6937. // Trim spaces
  6938. trim(key)
  6939. trim(value)
  6940.  
  6941. // Add to sounds array
  6942. ArrayPushString(zombie_hit_stab, key)
  6943. }
  6944. }
  6945. else if (equal(key, "ZOMBIE IDLE"))
  6946. {
  6947. // Parse sounds
  6948. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6949. {
  6950. // Trim spaces
  6951. trim(key)
  6952. trim(value)
  6953.  
  6954. // Add to sounds array
  6955. ArrayPushString(zombie_idle, key)
  6956. }
  6957. }
  6958. else if (equal(key, "ZOMBIE IDLE LAST"))
  6959. {
  6960. // Parse sounds
  6961. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6962. {
  6963. // Trim spaces
  6964. trim(key)
  6965. trim(value)
  6966.  
  6967. // Add to sounds array
  6968. ArrayPushString(zombie_idle_last, key)
  6969. }
  6970. }
  6971. else if (equal(key, "ZOMBIE MADNESS"))
  6972. {
  6973. // Parse sounds
  6974. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6975. {
  6976. // Trim spaces
  6977. trim(key)
  6978. trim(value)
  6979.  
  6980. // Add to sounds array
  6981. ArrayPushString(zombie_madness, key)
  6982. }
  6983. }
  6984. else if (equal(key, "ROUND NEMESIS"))
  6985. {
  6986. // Parse sounds
  6987. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  6988. {
  6989. // Trim spaces
  6990. trim(key)
  6991. trim(value)
  6992.  
  6993. // Add to sounds array
  6994. ArrayPushString(sound_nemesis, key)
  6995. }
  6996. }
  6997. else if (equal(key, "ROUND SURVIVOR"))
  6998. {
  6999. // Parse sounds
  7000. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7001. {
  7002. // Trim spaces
  7003. trim(key)
  7004. trim(value)
  7005.  
  7006. // Add to sounds array
  7007. ArrayPushString(sound_survivor, key)
  7008. }
  7009. }
  7010. else if (equal(key, "ROUND SWARM"))
  7011. {
  7012. // Parse sounds
  7013. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7014. {
  7015. // Trim spaces
  7016. trim(key)
  7017. trim(value)
  7018.  
  7019. // Add to sounds array
  7020. ArrayPushString(sound_swarm, key)
  7021. }
  7022. }
  7023. else if (equal(key, "ROUND MULTI"))
  7024. {
  7025. // Parse sounds
  7026. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7027. {
  7028. // Trim spaces
  7029. trim(key)
  7030. trim(value)
  7031.  
  7032. // Add to sounds array
  7033. ArrayPushString(sound_multi, key)
  7034. }
  7035. }
  7036. else if (equal(key, "ROUND PLAGUE"))
  7037. {
  7038. // Parse sounds
  7039. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7040. {
  7041. // Trim spaces
  7042. trim(key)
  7043. trim(value)
  7044.  
  7045. // Add to sounds array
  7046. ArrayPushString(sound_plague, key)
  7047. }
  7048. }
  7049. else if (equal(key, "GRENADE INFECT EXPLODE"))
  7050. {
  7051. // Parse sounds
  7052. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7053. {
  7054. // Trim spaces
  7055. trim(key)
  7056. trim(value)
  7057.  
  7058. // Add to sounds array
  7059. ArrayPushString(grenade_infect, key)
  7060. }
  7061. }
  7062. else if (equal(key, "GRENADE INFECT PLAYER"))
  7063. {
  7064. // Parse sounds
  7065. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7066. {
  7067. // Trim spaces
  7068. trim(key)
  7069. trim(value)
  7070.  
  7071. // Add to sounds array
  7072. ArrayPushString(grenade_infect_player, key)
  7073. }
  7074. }
  7075. else if (equal(key, "GRENADE FIRE EXPLODE"))
  7076. {
  7077. // Parse sounds
  7078. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7079. {
  7080. // Trim spaces
  7081. trim(key)
  7082. trim(value)
  7083.  
  7084. // Add to sounds array
  7085. ArrayPushString(grenade_fire, key)
  7086. }
  7087. }
  7088. else if (equal(key, "GRENADE FIRE PLAYER"))
  7089. {
  7090. // Parse sounds
  7091. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7092. {
  7093. // Trim spaces
  7094. trim(key)
  7095. trim(value)
  7096.  
  7097. // Add to sounds array
  7098. ArrayPushString(grenade_fire_player, key)
  7099. }
  7100. }
  7101. else if (equal(key, "GRENADE FROST EXPLODE"))
  7102. {
  7103. // Parse sounds
  7104. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7105. {
  7106. // Trim spaces
  7107. trim(key)
  7108. trim(value)
  7109.  
  7110. // Add to sounds array
  7111. ArrayPushString(grenade_frost, key)
  7112. }
  7113. }
  7114. else if (equal(key, "GRENADE FROST PLAYER"))
  7115. {
  7116. // Parse sounds
  7117. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7118. {
  7119. // Trim spaces
  7120. trim(key)
  7121. trim(value)
  7122.  
  7123. // Add to sounds array
  7124. ArrayPushString(grenade_frost_player, key)
  7125. }
  7126. }
  7127. else if (equal(key, "GRENADE FROST BREAK"))
  7128. {
  7129. // Parse sounds
  7130. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7131. {
  7132. // Trim spaces
  7133. trim(key)
  7134. trim(value)
  7135.  
  7136. // Add to sounds array
  7137. ArrayPushString(grenade_frost_break, key)
  7138. }
  7139. }
  7140. else if (equal(key, "GRENADE FLARE"))
  7141. {
  7142. // Parse sounds
  7143. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7144. {
  7145. // Trim spaces
  7146. trim(key)
  7147. trim(value)
  7148.  
  7149. // Add to sounds array
  7150. ArrayPushString(grenade_flare, key)
  7151. }
  7152. }
  7153. else if (equal(key, "ANTIDOTE"))
  7154. {
  7155. // Parse sounds
  7156. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7157. {
  7158. // Trim spaces
  7159. trim(key)
  7160. trim(value)
  7161.  
  7162. // Add to sounds array
  7163. ArrayPushString(sound_antidote, key)
  7164. }
  7165. }
  7166. else if (equal(key, "THUNDER"))
  7167. {
  7168. // Parse sounds
  7169. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7170. {
  7171. // Trim spaces
  7172. trim(key)
  7173. trim(value)
  7174.  
  7175. // Add to sounds array
  7176. ArrayPushString(sound_thunder, key)
  7177. }
  7178. }
  7179. }
  7180. case SECTION_AMBIENCE_SOUNDS:
  7181. {
  7182. if (equal(key, "INFECTION ENABLE"))
  7183. g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION] = str_to_num(value)
  7184. else if (g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION] && equal(key, "INFECTION SOUNDS"))
  7185. {
  7186. // Parse sounds
  7187. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7188. {
  7189. // Trim spaces
  7190. trim(key)
  7191. trim(value)
  7192.  
  7193. // Add to sounds array
  7194. ArrayPushString(sound_ambience1, key)
  7195. ArrayPushCell(sound_ambience1_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
  7196. }
  7197. }
  7198. else if (g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION] && equal(key, "INFECTION DURATIONS"))
  7199. {
  7200. // Parse sounds
  7201. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7202. {
  7203. // Trim spaces
  7204. trim(key)
  7205. trim(value)
  7206.  
  7207. // Add to sounds array
  7208. ArrayPushCell(sound_ambience1_duration, str_to_num(key))
  7209. }
  7210. }
  7211. else if (equal(key, "NEMESIS ENABLE"))
  7212. g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS] = str_to_num(value)
  7213. else if (g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS] && equal(key, "NEMESIS SOUNDS"))
  7214. {
  7215. // Parse sounds
  7216. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7217. {
  7218. // Trim spaces
  7219. trim(key)
  7220. trim(value)
  7221.  
  7222. // Add to sounds array
  7223. ArrayPushString(sound_ambience2, key)
  7224. ArrayPushCell(sound_ambience2_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
  7225. }
  7226. }
  7227. else if (g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS] && equal(key, "NEMESIS DURATIONS"))
  7228. {
  7229. // Parse sounds
  7230. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7231. {
  7232. // Trim spaces
  7233. trim(key)
  7234. trim(value)
  7235.  
  7236. // Add to sounds array
  7237. ArrayPushCell(sound_ambience2_duration, str_to_num(key))
  7238. }
  7239. }
  7240. else if (equal(key, "SURVIVOR ENABLE"))
  7241. g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR] = str_to_num(value)
  7242. else if (g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR] && equal(key, "SURVIVOR SOUNDS"))
  7243. {
  7244. // Parse sounds
  7245. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7246. {
  7247. // Trim spaces
  7248. trim(key)
  7249. trim(value)
  7250.  
  7251. // Add to sounds array
  7252. ArrayPushString(sound_ambience3, key)
  7253. ArrayPushCell(sound_ambience3_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
  7254. }
  7255. }
  7256. else if (g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR] && equal(key, "SURVIVOR DURATIONS"))
  7257. {
  7258. // Parse sounds
  7259. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7260. {
  7261. // Trim spaces
  7262. trim(key)
  7263. trim(value)
  7264.  
  7265. // Add to sounds array
  7266. ArrayPushCell(sound_ambience3_duration, str_to_num(key))
  7267. }
  7268. }
  7269. else if (equal(key, "SWARM ENABLE"))
  7270. g_ambience_sounds[AMBIENCE_SOUNDS_SWARM] = str_to_num(value)
  7271. else if (g_ambience_sounds[AMBIENCE_SOUNDS_SWARM] && equal(key, "SWARM SOUNDS"))
  7272. {
  7273. // Parse sounds
  7274. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7275. {
  7276. // Trim spaces
  7277. trim(key)
  7278. trim(value)
  7279.  
  7280. // Add to sounds array
  7281. ArrayPushString(sound_ambience4, key)
  7282. ArrayPushCell(sound_ambience4_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
  7283. }
  7284. }
  7285. else if (g_ambience_sounds[AMBIENCE_SOUNDS_SWARM] && equal(key, "SWARM DURATIONS"))
  7286. {
  7287. // Parse sounds
  7288. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7289. {
  7290. // Trim spaces
  7291. trim(key)
  7292. trim(value)
  7293.  
  7294. // Add to sounds array
  7295. ArrayPushCell(sound_ambience4_duration, str_to_num(key))
  7296. }
  7297. }
  7298. else if (equal(key, "PLAGUE ENABLE"))
  7299. g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE] = str_to_num(value)
  7300. else if (g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE] && equal(key, "PLAGUE SOUNDS"))
  7301. {
  7302. // Parse sounds
  7303. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7304. {
  7305. // Trim spaces
  7306. trim(key)
  7307. trim(value)
  7308.  
  7309. // Add to sounds array
  7310. ArrayPushString(sound_ambience5, key)
  7311. ArrayPushCell(sound_ambience5_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
  7312. }
  7313. }
  7314. else if (g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE] && equal(key, "PLAGUE DURATIONS"))
  7315. {
  7316. // Parse sounds
  7317. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7318. {
  7319. // Trim spaces
  7320. trim(key)
  7321. trim(value)
  7322.  
  7323. // Add to sounds array
  7324. ArrayPushCell(sound_ambience5_duration, str_to_num(key))
  7325. }
  7326. }
  7327. }
  7328. case SECTION_BUY_MENU_WEAPONS:
  7329. {
  7330. if (equal(key, "PRIMARY"))
  7331. {
  7332. // Parse weapons
  7333. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7334. {
  7335. // Trim spaces
  7336. trim(key)
  7337. trim(value)
  7338.  
  7339. // Add to weapons array
  7340. ArrayPushString(g_primary_items, key)
  7341. ArrayPushCell(g_primary_weaponids, cs_weapon_name_to_id(key))
  7342. }
  7343. }
  7344. else if (equal(key, "SECONDARY"))
  7345. {
  7346. // Parse weapons
  7347. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7348. {
  7349. // Trim spaces
  7350. trim(key)
  7351. trim(value)
  7352.  
  7353. // Add to weapons array
  7354. ArrayPushString(g_secondary_items, key)
  7355. ArrayPushCell(g_secondary_weaponids, cs_weapon_name_to_id(key))
  7356. }
  7357. }
  7358. else if (equal(key, "ADDITIONAL ITEMS"))
  7359. {
  7360. // Parse weapons
  7361. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7362. {
  7363. // Trim spaces
  7364. trim(key)
  7365. trim(value)
  7366.  
  7367. // Add to weapons array
  7368. ArrayPushString(g_additional_items, key)
  7369. }
  7370. }
  7371. }
  7372. case SECTION_EXTRA_ITEMS_WEAPONS:
  7373. {
  7374. if (equal(key, "NAMES"))
  7375. {
  7376. // Parse weapon items
  7377. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7378. {
  7379. // Trim spaces
  7380. trim(key)
  7381. trim(value)
  7382.  
  7383. // Add to weapons array
  7384. ArrayPushString(g_extraweapon_names, key)
  7385. }
  7386. }
  7387. else if (equal(key, "ITEMS"))
  7388. {
  7389. // Parse weapon items
  7390. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7391. {
  7392. // Trim spaces
  7393. trim(key)
  7394. trim(value)
  7395.  
  7396. // Add to weapons array
  7397. ArrayPushString(g_extraweapon_items, key)
  7398. }
  7399. }
  7400. else if (equal(key, "COSTS"))
  7401. {
  7402. // Parse weapon items
  7403. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7404. {
  7405. // Trim spaces
  7406. trim(key)
  7407. trim(value)
  7408.  
  7409. // Add to weapons array
  7410. ArrayPushCell(g_extraweapon_costs, str_to_num(key))
  7411. }
  7412. }
  7413. }
  7414. case SECTION_HARD_CODED_ITEMS_COSTS:
  7415. {
  7416. if (equal(key, "NIGHT VISION"))
  7417. g_extra_costs2[EXTRA_NVISION] = str_to_num(value)
  7418. else if (equal(key, "ANTIDOTE"))
  7419. g_extra_costs2[EXTRA_ANTIDOTE] = str_to_num(value)
  7420. else if (equal(key, "ZOMBIE MADNESS"))
  7421. g_extra_costs2[EXTRA_MADNESS] = str_to_num(value)
  7422. else if (equal(key, "INFECTION BOMB"))
  7423. g_extra_costs2[EXTRA_INFBOMB] = str_to_num(value)
  7424. }
  7425. case SECTION_WEATHER_EFFECTS:
  7426. {
  7427. if (equal(key, "RAIN"))
  7428. g_ambience_rain = str_to_num(value)
  7429. else if (equal(key, "SNOW"))
  7430. g_ambience_snow = str_to_num(value)
  7431. else if (equal(key, "FOG"))
  7432. g_ambience_fog = str_to_num(value)
  7433. else if (equal(key, "FOG DENSITY"))
  7434. copy(g_fog_density, charsmax(g_fog_density), value)
  7435. else if (equal(key, "FOG COLOR"))
  7436. copy(g_fog_color, charsmax(g_fog_color), value)
  7437. }
  7438. case SECTION_SKY:
  7439. {
  7440. if (equal(key, "ENABLE"))
  7441. g_sky_enable = str_to_num(value)
  7442. else if (equal(key, "SKY NAMES"))
  7443. {
  7444. // Parse sky names
  7445. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7446. {
  7447. // Trim spaces
  7448. trim(key)
  7449. trim(value)
  7450.  
  7451. // Add to skies array
  7452. ArrayPushString(g_sky_names, key)
  7453.  
  7454. // Preache custom sky files
  7455. formatex(linedata, charsmax(linedata), "gfx/env/%sbk.tga", key)
  7456. engfunc(EngFunc_PrecacheGeneric, linedata)
  7457. formatex(linedata, charsmax(linedata), "gfx/env/%sdn.tga", key)
  7458. engfunc(EngFunc_PrecacheGeneric, linedata)
  7459. formatex(linedata, charsmax(linedata), "gfx/env/%sft.tga", key)
  7460. engfunc(EngFunc_PrecacheGeneric, linedata)
  7461. formatex(linedata, charsmax(linedata), "gfx/env/%slf.tga", key)
  7462. engfunc(EngFunc_PrecacheGeneric, linedata)
  7463. formatex(linedata, charsmax(linedata), "gfx/env/%srt.tga", key)
  7464. engfunc(EngFunc_PrecacheGeneric, linedata)
  7465. formatex(linedata, charsmax(linedata), "gfx/env/%sup.tga", key)
  7466. engfunc(EngFunc_PrecacheGeneric, linedata)
  7467. }
  7468. }
  7469. }
  7470. case SECTION_LIGHTNING:
  7471. {
  7472. if (equal(key, "LIGHTS"))
  7473. {
  7474. // Parse lights
  7475. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7476. {
  7477. // Trim spaces
  7478. trim(key)
  7479. trim(value)
  7480.  
  7481. // Add to lightning array
  7482. ArrayPushString(lights_thunder, key)
  7483. }
  7484. }
  7485. }
  7486. case SECTION_ZOMBIE_DECALS:
  7487. {
  7488. if (equal(key, "DECALS"))
  7489. {
  7490. // Parse decals
  7491. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7492. {
  7493. // Trim spaces
  7494. trim(key)
  7495. trim(value)
  7496.  
  7497. // Add to zombie decals array
  7498. ArrayPushCell(zombie_decals, str_to_num(key))
  7499. }
  7500. }
  7501. }
  7502. case SECTION_KNOCKBACK:
  7503. {
  7504. // Format weapon entity name
  7505. strtolower(key)
  7506. format(key, charsmax(key), "weapon_%s", key)
  7507.  
  7508. // Add value to knockback power array
  7509. kb_weapon_power[cs_weapon_name_to_id(key)] = str_to_float(value)
  7510. }
  7511. case SECTION_OBJECTIVE_ENTS:
  7512. {
  7513. if (equal(key, "CLASSNAMES"))
  7514. {
  7515. // Parse classnames
  7516. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7517. {
  7518. // Trim spaces
  7519. trim(key)
  7520. trim(value)
  7521.  
  7522. // Add to objective ents array
  7523. ArrayPushString(g_objective_ents, key)
  7524. }
  7525. }
  7526. }
  7527. case SECTION_SVC_BAD:
  7528. {
  7529. if (equal(key, "MODELCHANGE DELAY"))
  7530. g_modelchange_delay = str_to_float(value)
  7531. else if (equal(key, "HANDLE MODELS ON SEPARATE ENT"))
  7532. g_handle_models_on_separate_ent = str_to_num(value)
  7533. else if (equal(key, "SET MODELINDEX OFFSET"))
  7534. g_set_modelindex_offset = str_to_num(value)
  7535. }
  7536. }
  7537. }
  7538. if (file) fclose(file)
  7539.  
  7540. // Build zombie classes file path
  7541. get_configsdir(path, charsmax(path))
  7542. format(path, charsmax(path), "%s/%s", path, ZP_ZOMBIECLASSES_FILE)
  7543.  
  7544. // Parse if present
  7545. if (file_exists(path))
  7546. {
  7547. // Open zombie classes file for reading
  7548. file = fopen(path, "rt")
  7549.  
  7550. while (file && !feof(file))
  7551. {
  7552. // Read one line at a time
  7553. fgets(file, linedata, charsmax(linedata))
  7554.  
  7555. // Replace newlines with a null character to prevent headaches
  7556. replace(linedata, charsmax(linedata), "^n", "")
  7557.  
  7558. // Blank line or comment
  7559. if (!linedata[0] || linedata[0] == ';') continue;
  7560.  
  7561. // New class starting
  7562. if (linedata[0] == '[')
  7563. {
  7564. // Remove first and last characters (braces)
  7565. linedata[strlen(linedata) - 1] = 0
  7566. copy(linedata, charsmax(linedata), linedata[1])
  7567.  
  7568. // Store its real name for future reference
  7569. ArrayPushString(g_zclass2_realname, linedata)
  7570. continue;
  7571. }
  7572.  
  7573. // Get key and value(s)
  7574. strtok(linedata, key, charsmax(key), value, charsmax(value), '=')
  7575.  
  7576. // Trim spaces
  7577. trim(key)
  7578. trim(value)
  7579.  
  7580. if (equal(key, "NAME"))
  7581. ArrayPushString(g_zclass2_name, value)
  7582. else if (equal(key, "INFO"))
  7583. ArrayPushString(g_zclass2_info, value)
  7584. else if (equal(key, "MODELS"))
  7585. {
  7586. // Set models start index
  7587. ArrayPushCell(g_zclass2_modelsstart, ArraySize(g_zclass2_playermodel))
  7588.  
  7589. // Parse class models
  7590. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7591. {
  7592. // Trim spaces
  7593. trim(key)
  7594. trim(value)
  7595.  
  7596. // Add to class models array
  7597. ArrayPushString(g_zclass2_playermodel, key)
  7598. ArrayPushCell(g_zclass2_modelindex, -1)
  7599. }
  7600.  
  7601. // Set models end index
  7602. ArrayPushCell(g_zclass2_modelsend, ArraySize(g_zclass2_playermodel))
  7603. }
  7604. else if (equal(key, "CLAWMODEL"))
  7605. ArrayPushString(g_zclass2_clawmodel, value)
  7606. else if (equal(key, "HEALTH"))
  7607. ArrayPushCell(g_zclass2_hp, str_to_num(value))
  7608. else if (equal(key, "SPEED"))
  7609. ArrayPushCell(g_zclass2_spd, str_to_num(value))
  7610. else if (equal(key, "GRAVITY"))
  7611. ArrayPushCell(g_zclass2_grav, str_to_float(value))
  7612. else if (equal(key, "KNOCKBACK"))
  7613. ArrayPushCell(g_zclass2_kb, str_to_float(value))
  7614. }
  7615. if (file) fclose(file)
  7616. }
  7617.  
  7618. // Build extra items file path
  7619. get_configsdir(path, charsmax(path))
  7620. format(path, charsmax(path), "%s/%s", path, ZP_EXTRAITEMS_FILE)
  7621.  
  7622. // Parse if present
  7623. if (file_exists(path))
  7624. {
  7625. // Open extra items file for reading
  7626. file = fopen(path, "rt")
  7627.  
  7628. while (file && !feof(file))
  7629. {
  7630. // Read one line at a time
  7631. fgets(file, linedata, charsmax(linedata))
  7632.  
  7633. // Replace newlines with a null character to prevent headaches
  7634. replace(linedata, charsmax(linedata), "^n", "")
  7635.  
  7636. // Blank line or comment
  7637. if (!linedata[0] || linedata[0] == ';') continue;
  7638.  
  7639. // New item starting
  7640. if (linedata[0] == '[')
  7641. {
  7642. // Remove first and last characters (braces)
  7643. linedata[strlen(linedata) - 1] = 0
  7644. copy(linedata, charsmax(linedata), linedata[1])
  7645.  
  7646. // Store its real name for future reference
  7647. ArrayPushString(g_extraitem2_realname, linedata)
  7648. continue;
  7649. }
  7650.  
  7651. // Get key and value(s)
  7652. strtok(linedata, key, charsmax(key), value, charsmax(value), '=')
  7653.  
  7654. // Trim spaces
  7655. trim(key)
  7656. trim(value)
  7657.  
  7658. if (equal(key, "NAME"))
  7659. ArrayPushString(g_extraitem2_name, value)
  7660. else if (equal(key, "COST"))
  7661. ArrayPushCell(g_extraitem2_cost, str_to_num(value))
  7662. else if (equal(key, "TEAMS"))
  7663. {
  7664. // Clear teams bitsum
  7665. teams = 0
  7666.  
  7667. // Parse teams
  7668. while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
  7669. {
  7670. // Trim spaces
  7671. trim(key)
  7672. trim(value)
  7673.  
  7674. if (equal(key, ZP_TEAM_NAMES[ZP_TEAM_ZOMBIE]))
  7675. teams |= ZP_TEAM_ZOMBIE
  7676. else if (equal(key, ZP_TEAM_NAMES[ZP_TEAM_HUMAN]))
  7677. teams |= ZP_TEAM_HUMAN
  7678. else if (equal(key, ZP_TEAM_NAMES[ZP_TEAM_NEMESIS]))
  7679. teams |= ZP_TEAM_NEMESIS
  7680. else if (equal(key, ZP_TEAM_NAMES[ZP_TEAM_SURVIVOR]))
  7681. teams |= ZP_TEAM_SURVIVOR
  7682. }
  7683.  
  7684. // Add to teams array
  7685. ArrayPushCell(g_extraitem2_team, teams)
  7686. }
  7687. }
  7688. if (file) fclose(file)
  7689. }
  7690. }
  7691.  
  7692. save_customization()
  7693. {
  7694. new i, k, buffer[512]
  7695.  
  7696. // Build zombie classes file path
  7697. new path[64]
  7698. get_configsdir(path, charsmax(path))
  7699. format(path, charsmax(path), "%s/%s", path, ZP_ZOMBIECLASSES_FILE)
  7700.  
  7701. // Open zombie classes file for appending data
  7702. new file = fopen(path, "at"), size = ArraySize(g_zclass_name)
  7703.  
  7704. // Add any new zombie classes data at the end if needed
  7705. for (i = 0; i < size; i++)
  7706. {
  7707. if (ArrayGetCell(g_zclass_new, i))
  7708. {
  7709. // Add real name
  7710. ArrayGetString(g_zclass_name, i, buffer, charsmax(buffer))
  7711. format(buffer, charsmax(buffer), "^n[%s]", buffer)
  7712. fputs(file, buffer)
  7713.  
  7714. // Add caption
  7715. ArrayGetString(g_zclass_name, i, buffer, charsmax(buffer))
  7716. format(buffer, charsmax(buffer), "^nNAME = %s", buffer)
  7717. fputs(file, buffer)
  7718.  
  7719. // Add info
  7720. ArrayGetString(g_zclass_info, i, buffer, charsmax(buffer))
  7721. format(buffer, charsmax(buffer), "^nINFO = %s", buffer)
  7722. fputs(file, buffer)
  7723.  
  7724. // Add models
  7725. for (k = ArrayGetCell(g_zclass_modelsstart, i); k < ArrayGetCell(g_zclass_modelsend, i); k++)
  7726. {
  7727. if (k == ArrayGetCell(g_zclass_modelsstart, i))
  7728. {
  7729. // First model, overwrite buffer
  7730. ArrayGetString(g_zclass_playermodel, k, buffer, charsmax(buffer))
  7731. }
  7732. else
  7733. {
  7734. // Successive models, append to buffer
  7735. ArrayGetString(g_zclass_playermodel, k, path, charsmax(path))
  7736. format(buffer, charsmax(buffer), "%s , %s", buffer, path)
  7737. }
  7738. }
  7739. format(buffer, charsmax(buffer), "^nMODELS = %s", buffer)
  7740. fputs(file, buffer)
  7741.  
  7742. // Add clawmodel
  7743. ArrayGetString(g_zclass_clawmodel, i, buffer, charsmax(buffer))
  7744. format(buffer, charsmax(buffer), "^nCLAWMODEL = %s", buffer)
  7745. fputs(file, buffer)
  7746.  
  7747. // Add health
  7748. formatex(buffer, charsmax(buffer), "^nHEALTH = %d", ArrayGetCell(g_zclass_hp, i))
  7749. fputs(file, buffer)
  7750.  
  7751. // Add speed
  7752. formatex(buffer, charsmax(buffer), "^nSPEED = %d", ArrayGetCell(g_zclass_spd, i))
  7753. fputs(file, buffer)
  7754.  
  7755. // Add gravity
  7756. formatex(buffer, charsmax(buffer), "^nGRAVITY = %.2f", Float:ArrayGetCell(g_zclass_grav, i))
  7757. fputs(file, buffer)
  7758.  
  7759. // Add knockback
  7760. formatex(buffer, charsmax(buffer), "^nKNOCKBACK = %.2f^n", Float:ArrayGetCell(g_zclass_kb, i))
  7761. fputs(file, buffer)
  7762. }
  7763. }
  7764. fclose(file)
  7765.  
  7766. // Build extra items file path
  7767. get_configsdir(path, charsmax(path))
  7768. format(path, charsmax(path), "%s/%s", path, ZP_EXTRAITEMS_FILE)
  7769.  
  7770. // Open extra items file for appending data
  7771. file = fopen(path, "at")
  7772. size = ArraySize(g_extraitem_name)
  7773.  
  7774. // Add any new extra items data at the end if needed
  7775. for (i = EXTRAS_CUSTOM_STARTID; i < size; i++)
  7776. {
  7777. if (ArrayGetCell(g_extraitem_new, i))
  7778. {
  7779. // Add real name
  7780. ArrayGetString(g_extraitem_name, i, buffer, charsmax(buffer))
  7781. format(buffer, charsmax(buffer), "^n[%s]", buffer)
  7782. fputs(file, buffer)
  7783.  
  7784. // Add caption
  7785. ArrayGetString(g_extraitem_name, i, buffer, charsmax(buffer))
  7786. format(buffer, charsmax(buffer), "^nNAME = %s", buffer)
  7787. fputs(file, buffer)
  7788.  
  7789. // Add cost
  7790. formatex(buffer, charsmax(buffer), "^nCOST = %d", ArrayGetCell(g_extraitem_cost, i))
  7791. fputs(file, buffer)
  7792.  
  7793. // Add team
  7794. formatex(buffer, charsmax(buffer), "^nTEAMS = %s^n", ZP_TEAM_NAMES[ArrayGetCell(g_extraitem_team, i)])
  7795. fputs(file, buffer)
  7796. }
  7797. }
  7798. fclose(file)
  7799.  
  7800. // Free arrays containing class/item overrides
  7801. ArrayDestroy(g_zclass2_realname)
  7802. ArrayDestroy(g_zclass2_name)
  7803. ArrayDestroy(g_zclass2_info)
  7804. ArrayDestroy(g_zclass2_modelsstart)
  7805. ArrayDestroy(g_zclass2_modelsend)
  7806. ArrayDestroy(g_zclass2_playermodel)
  7807. ArrayDestroy(g_zclass2_modelindex)
  7808. ArrayDestroy(g_zclass2_clawmodel)
  7809. ArrayDestroy(g_zclass2_hp)
  7810. ArrayDestroy(g_zclass2_spd)
  7811. ArrayDestroy(g_zclass2_grav)
  7812. ArrayDestroy(g_zclass2_kb)
  7813. ArrayDestroy(g_zclass_new)
  7814. ArrayDestroy(g_extraitem2_realname)
  7815. ArrayDestroy(g_extraitem2_name)
  7816. ArrayDestroy(g_extraitem2_cost)
  7817. ArrayDestroy(g_extraitem2_team)
  7818. ArrayDestroy(g_extraitem_new)
  7819. }
  7820.  
  7821. // Register Ham Forwards for CZ bots
  7822. public register_ham_czbots(id)
  7823. {
  7824. // Make sure it's a CZ bot and it's still connected
  7825. if (g_hamczbots || !g_isconnected[id] || !get_pcvar_num(cvar_botquota))
  7826. return;
  7827.  
  7828. RegisterHamFromEntity(Ham_Spawn, id, "fw_PlayerSpawn_Post", 1)
  7829. RegisterHamFromEntity(Ham_Killed, id, "fw_PlayerKilled")
  7830. RegisterHamFromEntity(Ham_Killed, id, "fw_PlayerKilled_Post", 1)
  7831. RegisterHamFromEntity(Ham_TakeDamage, id, "fw_TakeDamage")
  7832. RegisterHamFromEntity(Ham_TakeDamage, id, "fw_TakeDamage_Post", 1)
  7833. RegisterHamFromEntity(Ham_TraceAttack, id, "fw_TraceAttack")
  7834. RegisterHamFromEntity(Ham_Player_ResetMaxSpeed, id, "fw_ResetMaxSpeed_Post", 1)
  7835.  
  7836. // Ham forwards for CZ bots succesfully registered
  7837. g_hamczbots = true
  7838.  
  7839. // If the bot has already spawned, call the forward manually for him
  7840. if (is_user_alive(id)) fw_PlayerSpawn_Post(id)
  7841. }
  7842.  
  7843. // Disable minmodels task
  7844. public disable_minmodels(id)
  7845. {
  7846. if (!g_isconnected[id]) return;
  7847. client_cmd(id, "cl_minmodels 0")
  7848. }
  7849.  
  7850. // Bots automatically buy extra items
  7851. public bot_buy_extras(taskid)
  7852. {
  7853. // Nemesis or Survivor bots have nothing to buy by default
  7854. if (!g_isalive[ID_SPAWN] || g_survivor[ID_SPAWN] || g_nemesis[ID_SPAWN])
  7855. return;
  7856.  
  7857. if (!g_zombie[ID_SPAWN]) // human bots
  7858. {
  7859. // Attempt to buy Night Vision
  7860. buy_extra_item(ID_SPAWN, EXTRA_NVISION)
  7861.  
  7862. // Attempt to buy a weapon
  7863. buy_extra_item(ID_SPAWN, random_num(EXTRA_WEAPONS_STARTID, EXTRAS_CUSTOM_STARTID-1))
  7864. }
  7865. else // zombie bots
  7866. {
  7867. // Attempt to buy an Antidote
  7868. buy_extra_item(ID_SPAWN, EXTRA_ANTIDOTE)
  7869. }
  7870. }
  7871.  
  7872. // Refill BP Ammo Task
  7873. public refill_bpammo(const args[], id)
  7874. {
  7875. // Player died or turned into a zombie
  7876. if (!g_isalive[id] || g_zombie[id])
  7877. return;
  7878.  
  7879. set_msg_block(g_msgAmmoPickup, BLOCK_ONCE)
  7880. ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[REFILL_WEAPONID], AMMOTYPE[REFILL_WEAPONID], MAXBPAMMO[REFILL_WEAPONID])
  7881. }
  7882.  
  7883. // Balance Teams Task
  7884. balance_teams()
  7885. {
  7886. // Get amount of users playing
  7887. static iPlayersnum
  7888. iPlayersnum = fnGetPlaying()
  7889.  
  7890. // No players, don't bother
  7891. if (iPlayersnum < 1) return;
  7892.  
  7893. // Split players evenly
  7894. static iTerrors, iMaxTerrors, id, team[33]
  7895. iMaxTerrors = iPlayersnum/2
  7896. iTerrors = 0
  7897.  
  7898. // First, set everyone to CT
  7899. for (id = 1; id <= g_maxplayers; id++)
  7900. {
  7901. // Skip if not connected
  7902. if (!g_isconnected[id])
  7903. continue;
  7904.  
  7905. team[id] = fm_cs_get_user_team(id)
  7906.  
  7907. // Skip if not playing
  7908. if (team[id] == FM_CS_TEAM_SPECTATOR || team[id] == FM_CS_TEAM_UNASSIGNED)
  7909. continue;
  7910.  
  7911. // Set team
  7912. remove_task(id+TASK_TEAM)
  7913. fm_cs_set_user_team(id, FM_CS_TEAM_CT)
  7914. team[id] = FM_CS_TEAM_CT
  7915. }
  7916.  
  7917. // Then randomly set half of the players to Terrorists
  7918. while (iTerrors < iMaxTerrors)
  7919. {
  7920. // Keep looping through all players
  7921. if (++id > g_maxplayers) id = 1
  7922.  
  7923. // Skip if not connected
  7924. if (!g_isconnected[id])
  7925. continue;
  7926.  
  7927. // Skip if not playing or already a Terrorist
  7928. if (team[id] != FM_CS_TEAM_CT)
  7929. continue;
  7930.  
  7931. // Random chance
  7932. if (random_num(0, 1))
  7933. {
  7934. fm_cs_set_user_team(id, FM_CS_TEAM_T)
  7935. team[id] = FM_CS_TEAM_T
  7936. iTerrors++
  7937. }
  7938. }
  7939. }
  7940.  
  7941. // Welcome Message Task
  7942. public welcome_msg()
  7943. {
  7944. // Show mod info
  7945. zp_colored_print(0, "^x01**** ^x04%s^x01 ****", g_modname)
  7946. zp_colored_print(0, "^x04[ZP]^x01 %L", LANG_PLAYER, "NOTICE_INFO1")
  7947. if (!get_pcvar_num(cvar_infammo)) zp_colored_print(0, "^x04[ZP]^x01 %L", LANG_PLAYER, "NOTICE_INFO2")
  7948.  
  7949. // Show T-virus HUD notice
  7950. set_hudmessage(0, 125, 200, HUD_EVENT_X, HUD_EVENT_Y, 0, 0.0, 3.0, 2.0, 1.0, -1)
  7951. ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_VIRUS_FREE")
  7952. }
  7953.  
  7954. // Respawn Player Task (deathmatch)
  7955. public respawn_player_task(taskid)
  7956. {
  7957. // Already alive or round ended
  7958. if (g_isalive[ID_SPAWN] || g_endround)
  7959. return;
  7960.  
  7961. // Get player's team
  7962. static team
  7963. team = fm_cs_get_user_team(ID_SPAWN)
  7964.  
  7965. // Player moved to spectators
  7966. if (team == FM_CS_TEAM_SPECTATOR || team == FM_CS_TEAM_UNASSIGNED)
  7967. return;
  7968.  
  7969. // Respawn player automatically if allowed on current round
  7970. if ((!g_survround || get_pcvar_num(cvar_allowrespawnsurv)) && (!g_swarmround || get_pcvar_num(cvar_allowrespawnswarm)) && (!g_nemround || get_pcvar_num(cvar_allowrespawnnem)) && (!g_plagueround || get_pcvar_num(cvar_allowrespawnplague)))
  7971. {
  7972. // Infection rounds = none of the above
  7973. if (!get_pcvar_num(cvar_allowrespawninfection) && !g_survround && !g_nemround && !g_swarmround && !g_plagueround)
  7974. return;
  7975.  
  7976. // Respawn if only the last human is left? (ignore this setting on survivor rounds)
  7977. if (!g_survround && !get_pcvar_num(cvar_respawnafterlast) && fnGetHumans() <= 1)
  7978. return;
  7979.  
  7980. // Respawn as zombie?
  7981. if (get_pcvar_num(cvar_deathmatch) == 2 || (get_pcvar_num(cvar_deathmatch) == 3 && random_num(0, 1)) || (get_pcvar_num(cvar_deathmatch) == 4 && fnGetZombies() < fnGetAlive()/2))
  7982. g_respawn_as_zombie[ID_SPAWN] = true
  7983.  
  7984. // Override respawn as zombie setting on nemesis and survivor rounds
  7985. if (g_survround) g_respawn_as_zombie[ID_SPAWN] = true
  7986. else if (g_nemround) g_respawn_as_zombie[ID_SPAWN] = false
  7987.  
  7988. respawn_player_manually(ID_SPAWN)
  7989. }
  7990. }
  7991.  
  7992. // Respawn Player Check Task (if killed by worldspawn)
  7993. public respawn_player_check_task(taskid)
  7994. {
  7995. // Successfully spawned or round ended
  7996. if (g_isalive[ID_SPAWN] || g_endround)
  7997. return;
  7998.  
  7999. // Get player's team
  8000. static team
  8001. team = fm_cs_get_user_team(ID_SPAWN)
  8002.  
  8003. // Player moved to spectators
  8004. if (team == FM_CS_TEAM_SPECTATOR || team == FM_CS_TEAM_UNASSIGNED)
  8005. return;
  8006.  
  8007. // If player was being spawned as a zombie, set the flag again
  8008. if (g_zombie[ID_SPAWN]) g_respawn_as_zombie[ID_SPAWN] = true
  8009. else g_respawn_as_zombie[ID_SPAWN] = false
  8010.  
  8011. respawn_player_manually(ID_SPAWN)
  8012. }
  8013.  
  8014. // Respawn Player Manually (called after respawn checks are done)
  8015. respawn_player_manually(id)
  8016. {
  8017. // Set proper team before respawning, so that the TeamInfo message that's sent doesn't confuse PODBots
  8018. if (g_respawn_as_zombie[id])
  8019. fm_cs_set_user_team(id, FM_CS_TEAM_T)
  8020. else
  8021. fm_cs_set_user_team(id, FM_CS_TEAM_CT)
  8022.  
  8023. // Respawning a player has never been so easy
  8024. ExecuteHamB(Ham_CS_RoundRespawn, id)
  8025. }
  8026.  
  8027. // Check Round Task -check that we still have both zombies and humans on a round-
  8028. check_round(leaving_player)
  8029. {
  8030. // Round ended or make_a_zombie task still active
  8031. if (g_endround || task_exists(TASK_MAKEZOMBIE))
  8032. return;
  8033.  
  8034. // Get alive players count
  8035. static iPlayersnum, id
  8036. iPlayersnum = fnGetAlive()
  8037.  
  8038. // Last alive player, don't bother
  8039. if (iPlayersnum < 2)
  8040. return;
  8041.  
  8042. // Last zombie disconnecting
  8043. if (g_zombie[leaving_player] && fnGetZombies() == 1)
  8044. {
  8045. // Only one CT left, don't bother
  8046. if (fnGetHumans() == 1 && fnGetCTs() == 1)
  8047. return;
  8048.  
  8049. // Pick a random one to take his place
  8050. while ((id = fnGetRandomAlive(random_num(1, iPlayersnum))) == leaving_player ) { /* keep looping */ }
  8051.  
  8052. // Show last zombie left notice
  8053. zp_colored_print(0, "^x04[ZP]^x01 %L", LANG_PLAYER, "LAST_ZOMBIE_LEFT", g_playername[id])
  8054.  
  8055. // Set player leaving flag
  8056. g_lastplayerleaving = true
  8057.  
  8058. // Turn into a Nemesis or just a zombie?
  8059. if (g_nemesis[leaving_player])
  8060. zombieme(id, 0, 1, 0, 0)
  8061. else
  8062. zombieme(id, 0, 0, 0, 0)
  8063.  
  8064. // Remove player leaving flag
  8065. g_lastplayerleaving = false
  8066.  
  8067. // If Nemesis, set chosen player's health to that of the one who's leaving
  8068. if (get_pcvar_num(cvar_keephealthondisconnect) && g_nemesis[leaving_player])
  8069. fm_set_user_health(id, pev(leaving_player, pev_health))
  8070. }
  8071.  
  8072. // Last human disconnecting
  8073. else if (!g_zombie[leaving_player] && fnGetHumans() == 1)
  8074. {
  8075. // Only one T left, don't bother
  8076. if (fnGetZombies() == 1 && fnGetTs() == 1)
  8077. return;
  8078.  
  8079. // Pick a random one to take his place
  8080. while ((id = fnGetRandomAlive(random_num(1, iPlayersnum))) == leaving_player ) { /* keep looping */ }
  8081.  
  8082. // Show last human left notice
  8083. zp_colored_print(0, "^x04[ZP]^x01 %L", LANG_PLAYER, "LAST_HUMAN_LEFT", g_playername[id])
  8084.  
  8085. // Set player leaving flag
  8086. g_lastplayerleaving = true
  8087.  
  8088. // Turn into a Survivor or just a human?
  8089. if (g_survivor[leaving_player])
  8090. humanme(id, 1, 0)
  8091. else
  8092. humanme(id, 0, 0)
  8093.  
  8094. // Remove player leaving flag
  8095. g_lastplayerleaving = false
  8096.  
  8097. // If Survivor, set chosen player's health to that of the one who's leaving
  8098. if (get_pcvar_num(cvar_keephealthondisconnect) && g_survivor[leaving_player])
  8099. fm_set_user_health(id, pev(leaving_player, pev_health))
  8100. }
  8101. }
  8102.  
  8103. // Lighting Effects Task
  8104. public lighting_effects()
  8105. {
  8106. // Cache some CVAR values at every 5 secs
  8107. cache_cvars()
  8108.  
  8109. // Get lighting style
  8110. static lighting[2]
  8111. get_pcvar_string(cvar_lighting, lighting, charsmax(lighting))
  8112. strtolower(lighting)
  8113.  
  8114. // Lighting disabled? ["0"]
  8115. if (lighting[0] == '0')
  8116. return;
  8117.  
  8118. // Darkest light settings?
  8119. if (lighting[0] >= 'a' && lighting[0] <= 'd')
  8120. {
  8121. static thunderclap_in_progress, Float:thunder
  8122. thunderclap_in_progress = task_exists(TASK_THUNDER)
  8123. thunder = get_pcvar_float(cvar_thunder)
  8124.  
  8125. // Set thunderclap tasks if not existant
  8126. if (thunder > 0.0 && !task_exists(TASK_THUNDER_PRE) && !thunderclap_in_progress)
  8127. {
  8128. g_lights_i = 0
  8129. ArrayGetString(lights_thunder, random_num(0, ArraySize(lights_thunder) - 1), g_lights_cycle, charsmax(g_lights_cycle))
  8130. g_lights_cycle_len = strlen(g_lights_cycle)
  8131. set_task(thunder, "thunderclap", TASK_THUNDER_PRE)
  8132. }
  8133.  
  8134. // Set lighting only when no thunderclaps are going on
  8135. if (!thunderclap_in_progress) engfunc(EngFunc_LightStyle, 0, lighting)
  8136. }
  8137. else
  8138. {
  8139. // Remove thunderclap tasks
  8140. remove_task(TASK_THUNDER_PRE)
  8141. remove_task(TASK_THUNDER)
  8142.  
  8143. // Set lighting
  8144. engfunc(EngFunc_LightStyle, 0, lighting)
  8145. }
  8146. }
  8147.  
  8148. // Thunderclap task
  8149. public thunderclap()
  8150. {
  8151. // Play thunder sound
  8152. if (g_lights_i == 0)
  8153. {
  8154. static sound[64]
  8155. ArrayGetString(sound_thunder, random_num(0, ArraySize(sound_thunder) - 1), sound, charsmax(sound))
  8156. PlaySound(sound)
  8157. }
  8158.  
  8159. // Set lighting
  8160. static light[2]
  8161. light[0] = g_lights_cycle[g_lights_i]
  8162. engfunc(EngFunc_LightStyle, 0, light)
  8163.  
  8164. g_lights_i++
  8165.  
  8166. // Lighting cycle end?
  8167. if (g_lights_i >= g_lights_cycle_len)
  8168. {
  8169. remove_task(TASK_THUNDER)
  8170. lighting_effects()
  8171. }
  8172. // Lighting cycle start?
  8173. else if (!task_exists(TASK_THUNDER))
  8174. set_task(0.1, "thunderclap", TASK_THUNDER, _, _, "b")
  8175. }
  8176.  
  8177. // Ambience Sound Effects Task
  8178. public ambience_sound_effects(taskid)
  8179. {
  8180. // Play a random sound depending on the round
  8181. static sound[64], iRand, duration
  8182.  
  8183. if (g_nemround) // Nemesis Mode
  8184. {
  8185. iRand = random_num(0, ArraySize(sound_ambience2) - 1)
  8186. ArrayGetString(sound_ambience2, iRand, sound, charsmax(sound))
  8187. duration = ArrayGetCell(sound_ambience2_duration, iRand)
  8188. }
  8189. else if (g_survround) // Survivor Mode
  8190. {
  8191. iRand = random_num(0, ArraySize(sound_ambience3) - 1)
  8192. ArrayGetString(sound_ambience3, iRand, sound, charsmax(sound))
  8193. duration = ArrayGetCell(sound_ambience3_duration, iRand)
  8194. }
  8195. else if (g_swarmround) // Swarm Mode
  8196. {
  8197. iRand = random_num(0, ArraySize(sound_ambience4) - 1)
  8198. ArrayGetString(sound_ambience4, iRand, sound, charsmax(sound))
  8199. duration = ArrayGetCell(sound_ambience4_duration, iRand)
  8200. }
  8201. else if (g_plagueround) // Plague Mode
  8202. {
  8203. iRand = random_num(0, ArraySize(sound_ambience5) - 1)
  8204. ArrayGetString(sound_ambience5, iRand, sound, charsmax(sound))
  8205. duration = ArrayGetCell(sound_ambience5_duration, iRand)
  8206. }
  8207. else // Infection Mode
  8208. {
  8209. iRand = random_num(0, ArraySize(sound_ambience1) - 1)
  8210. ArrayGetString(sound_ambience1, iRand, sound, charsmax(sound))
  8211. duration = ArrayGetCell(sound_ambience1_duration, iRand)
  8212. }
  8213.  
  8214. // Play it on clients
  8215. PlaySound(sound)
  8216.  
  8217. // Set the task for when the sound is done playing
  8218. set_task(float(duration), "ambience_sound_effects", TASK_AMBIENCESOUNDS)
  8219. }
  8220.  
  8221. // Ambience Sounds Stop Task
  8222. ambience_sound_stop()
  8223. {
  8224. client_cmd(0, "mp3 stop; stopsound")
  8225. }
  8226.  
  8227. // Flashlight Charge Task
  8228. public flashlight_charge(taskid)
  8229. {
  8230. // Drain or charge?
  8231. if (g_flashlight[ID_CHARGE])
  8232. g_flashbattery[ID_CHARGE] -= get_pcvar_num(cvar_flashdrain)
  8233. else
  8234. g_flashbattery[ID_CHARGE] += get_pcvar_num(cvar_flashcharge)
  8235.  
  8236. // Battery fully charged
  8237. if (g_flashbattery[ID_CHARGE] >= 100)
  8238. {
  8239. // Don't exceed 100%
  8240. g_flashbattery[ID_CHARGE] = 100
  8241.  
  8242. // Update flashlight battery on HUD
  8243. message_begin(MSG_ONE, g_msgFlashBat, _, ID_CHARGE)
  8244. write_byte(100) // battery
  8245. message_end()
  8246.  
  8247. // Task not needed anymore
  8248. remove_task(taskid);
  8249. return;
  8250. }
  8251.  
  8252. // Battery depleted
  8253. if (g_flashbattery[ID_CHARGE] <= 0)
  8254. {
  8255. // Turn it off
  8256. g_flashlight[ID_CHARGE] = false
  8257. g_flashbattery[ID_CHARGE] = 0
  8258.  
  8259. // Play flashlight toggle sound
  8260. emit_sound(ID_CHARGE, CHAN_ITEM, sound_flashlight, 1.0, ATTN_NORM, 0, PITCH_NORM)
  8261.  
  8262. // Update flashlight status on HUD
  8263. message_begin(MSG_ONE, g_msgFlashlight, _, ID_CHARGE)
  8264. write_byte(0) // toggle
  8265. write_byte(0) // battery
  8266. message_end()
  8267.  
  8268. // Remove flashlight task for this player
  8269. remove_task(ID_CHARGE+TASK_FLASH)
  8270. }
  8271. else
  8272. {
  8273. // Update flashlight battery on HUD
  8274. message_begin(MSG_ONE_UNRELIABLE, g_msgFlashBat, _, ID_CHARGE)
  8275. write_byte(g_flashbattery[ID_CHARGE]) // battery
  8276. message_end()
  8277. }
  8278. }
  8279.  
  8280. // Remove Spawn Protection Task
  8281. public remove_spawn_protection(taskid)
  8282. {
  8283. // Not alive
  8284. if (!g_isalive[ID_SPAWN])
  8285. return;
  8286.  
  8287. // Remove spawn protection
  8288. g_nodamage[ID_SPAWN] = false
  8289. set_pev(ID_SPAWN, pev_effects, pev(ID_SPAWN, pev_effects) & ~EF_NODRAW)
  8290. }
  8291.  
  8292. // Hide Player's Money Task
  8293. public task_hide_money(taskid)
  8294. {
  8295. // Not alive
  8296. if (!g_isalive[ID_SPAWN])
  8297. return;
  8298.  
  8299. // Hide money
  8300. message_begin(MSG_ONE, g_msgHideWeapon, _, ID_SPAWN)
  8301. write_byte(HIDE_MONEY) // what to hide bitsum
  8302. message_end()
  8303.  
  8304. // Hide the HL crosshair that's drawn
  8305. message_begin(MSG_ONE, g_msgCrosshair, _, ID_SPAWN)
  8306. write_byte(0) // toggle
  8307. message_end()
  8308. }
  8309.  
  8310. // Turn Off Flashlight and Restore Batteries
  8311. turn_off_flashlight(id)
  8312. {
  8313. // Restore batteries for the next use
  8314. fm_cs_set_user_batteries(id, 100)
  8315.  
  8316. // Check if flashlight is on
  8317. if (pev(id, pev_effects) & EF_DIMLIGHT)
  8318. {
  8319. // Turn it off
  8320. set_pev(id, pev_impulse, IMPULSE_FLASHLIGHT)
  8321. }
  8322. else
  8323. {
  8324. // Clear any stored flashlight impulse (bugfix)
  8325. set_pev(id, pev_impulse, 0)
  8326. }
  8327.  
  8328. // Turn off custom flashlight
  8329. if (g_cached_customflash)
  8330. {
  8331. // Turn it off
  8332. g_flashlight[id] = false
  8333. g_flashbattery[id] = 100
  8334.  
  8335. // Update flashlight HUD
  8336. message_begin(MSG_ONE, g_msgFlashlight, _, id)
  8337. write_byte(0) // toggle
  8338. write_byte(100) // battery
  8339. message_end()
  8340.  
  8341. // Remove previous tasks
  8342. remove_task(id+TASK_CHARGE)
  8343. remove_task(id+TASK_FLASH)
  8344. }
  8345. }
  8346.  
  8347. // Infection Bomb Explosion
  8348. infection_explode(ent)
  8349. {
  8350. // Round ended (bugfix)
  8351. if (g_endround) return;
  8352.  
  8353. // Get origin
  8354. static Float:originF[3]
  8355. pev(ent, pev_origin, originF)
  8356.  
  8357. // Make the explosion
  8358. create_blast(originF)
  8359.  
  8360. // Infection nade explode sound
  8361. static sound[64]
  8362. ArrayGetString(grenade_infect, random_num(0, ArraySize(grenade_infect) - 1), sound, charsmax(sound))
  8363. emit_sound(ent, CHAN_WEAPON, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  8364.  
  8365. // Get attacker
  8366. static attacker
  8367. attacker = pev(ent, pev_owner)
  8368.  
  8369. // Infection bomb owner disconnected? (bugfix)
  8370. if (!is_user_valid_connected(attacker))
  8371. {
  8372. // Get rid of the grenade
  8373. engfunc(EngFunc_RemoveEntity, ent)
  8374. return;
  8375. }
  8376.  
  8377. // Collisions
  8378. static victim
  8379. victim = -1
  8380.  
  8381. while ((victim = engfunc(EngFunc_FindEntityInSphere, victim, originF, NADE_EXPLOSION_RADIUS)) != 0)
  8382. {
  8383. // Only effect alive non-spawnprotected humans
  8384. if (!is_user_valid_alive(victim) || g_zombie[victim] || g_nodamage[victim])
  8385. continue;
  8386.  
  8387. // Last human is killed
  8388. if (fnGetHumans() == 1)
  8389. {
  8390. ExecuteHamB(Ham_Killed, victim, attacker, 0)
  8391. continue;
  8392. }
  8393.  
  8394. // Infected victim's sound
  8395. ArrayGetString(grenade_infect_player, random_num(0, ArraySize(grenade_infect_player) - 1), sound, charsmax(sound))
  8396. emit_sound(victim, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  8397.  
  8398. // Turn into zombie
  8399. zombieme(victim, attacker, 0, 1, 1)
  8400. }
  8401.  
  8402. // Get rid of the grenade
  8403. engfunc(EngFunc_RemoveEntity, ent)
  8404. }
  8405.  
  8406. // Fire Grenade Explosion
  8407. fire_explode(ent)
  8408. {
  8409. // Get origin
  8410. static Float:originF[3]
  8411. pev(ent, pev_origin, originF)
  8412.  
  8413. // Make the explosion
  8414. create_blast2(originF)
  8415.  
  8416. // Fire nade explode sound
  8417. static sound[64]
  8418. ArrayGetString(grenade_fire, random_num(0, ArraySize(grenade_fire) - 1), sound, charsmax(sound))
  8419. emit_sound(ent, CHAN_WEAPON, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  8420.  
  8421. // Collisions
  8422. static victim
  8423. victim = -1
  8424.  
  8425. while ((victim = engfunc(EngFunc_FindEntityInSphere, victim, originF, NADE_EXPLOSION_RADIUS)) != 0)
  8426. {
  8427. // Only effect alive zombies
  8428. if (!is_user_valid_alive(victim) || !g_zombie[victim] || g_nodamage[victim])
  8429. continue;
  8430.  
  8431. // Heat icon?
  8432. if (get_pcvar_num(cvar_hudicons))
  8433. {
  8434. message_begin(MSG_ONE_UNRELIABLE, g_msgDamage, _, victim)
  8435. write_byte(0) // damage save
  8436. write_byte(0) // damage take
  8437. write_long(DMG_BURN) // damage type
  8438. write_coord(0) // x
  8439. write_coord(0) // y
  8440. write_coord(0) // z
  8441. message_end()
  8442. }
  8443.  
  8444. if (g_nemesis[victim]) // fire duration (nemesis is fire resistant)
  8445. g_burning_duration[victim] += get_pcvar_num(cvar_fireduration)
  8446. else
  8447. g_burning_duration[victim] += get_pcvar_num(cvar_fireduration) * 5
  8448.  
  8449. // Set burning task on victim if not present
  8450. if (!task_exists(victim+TASK_BURN))
  8451. set_task(0.2, "burning_flame", victim+TASK_BURN, _, _, "b")
  8452. }
  8453.  
  8454. // Get rid of the grenade
  8455. engfunc(EngFunc_RemoveEntity, ent)
  8456. }
  8457.  
  8458. // Frost Grenade Explosion
  8459. frost_explode(ent)
  8460. {
  8461. // Get origin
  8462. static Float:originF[3]
  8463. pev(ent, pev_origin, originF)
  8464.  
  8465. // Make the explosion
  8466. create_blast3(originF)
  8467.  
  8468. // Frost nade explode sound
  8469. static sound[64]
  8470. ArrayGetString(grenade_frost, random_num(0, ArraySize(grenade_frost) - 1), sound, charsmax(sound))
  8471. emit_sound(ent, CHAN_WEAPON, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  8472.  
  8473. // Collisions
  8474. static victim
  8475. victim = -1
  8476.  
  8477. while ((victim = engfunc(EngFunc_FindEntityInSphere, victim, originF, NADE_EXPLOSION_RADIUS)) != 0)
  8478. {
  8479. // Only effect alive unfrozen zombies
  8480. if (!is_user_valid_alive(victim) || !g_zombie[victim] || g_frozen[victim] || g_nodamage[victim])
  8481. continue;
  8482.  
  8483. // Nemesis shouldn't be frozen
  8484. if (g_nemesis[victim])
  8485. {
  8486. // Get player's origin
  8487. static origin2[3]
  8488. get_user_origin(victim, origin2)
  8489.  
  8490. // Broken glass sound
  8491. ArrayGetString(grenade_frost_break, random_num(0, ArraySize(grenade_frost_break) - 1), sound, charsmax(sound))
  8492. emit_sound(victim, CHAN_BODY, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  8493.  
  8494. // Glass shatter
  8495. message_begin(MSG_PVS, SVC_TEMPENTITY, origin2)
  8496. write_byte(TE_BREAKMODEL) // TE id
  8497. write_coord(origin2[0]) // x
  8498. write_coord(origin2[1]) // y
  8499. write_coord(origin2[2]+24) // z
  8500. write_coord(16) // size x
  8501. write_coord(16) // size y
  8502. write_coord(16) // size z
  8503. write_coord(random_num(-50, 50)) // velocity x
  8504. write_coord(random_num(-50, 50)) // velocity y
  8505. write_coord(25) // velocity z
  8506. write_byte(10) // random velocity
  8507. write_short(g_glassSpr) // model
  8508. write_byte(10) // count
  8509. write_byte(25) // life
  8510. write_byte(BREAK_GLASS) // flags
  8511. message_end()
  8512.  
  8513. continue;
  8514. }
  8515.  
  8516. // Freeze icon?
  8517. if (get_pcvar_num(cvar_hudicons))
  8518. {
  8519. message_begin(MSG_ONE_UNRELIABLE, g_msgDamage, _, victim)
  8520. write_byte(0) // damage save
  8521. write_byte(0) // damage take
  8522. write_long(DMG_DROWN) // damage type - DMG_FREEZE
  8523. write_coord(0) // x
  8524. write_coord(0) // y
  8525. write_coord(0) // z
  8526. message_end()
  8527. }
  8528.  
  8529. // Light blue glow while frozen
  8530. if (g_handle_models_on_separate_ent)
  8531. fm_set_rendering(g_ent_playermodel[victim], kRenderFxGlowShell, 0, 100, 200, kRenderNormal, 25)
  8532. else
  8533. fm_set_rendering(victim, kRenderFxGlowShell, 0, 100, 200, kRenderNormal, 25)
  8534.  
  8535. // Freeze sound
  8536. ArrayGetString(grenade_frost_player, random_num(0, ArraySize(grenade_frost_player) - 1), sound, charsmax(sound))
  8537. emit_sound(victim, CHAN_BODY, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  8538.  
  8539. // Add a blue tint to their screen
  8540. message_begin(MSG_ONE, g_msgScreenFade, _, victim)
  8541. write_short(0) // duration
  8542. write_short(0) // hold time
  8543. write_short(FFADE_STAYOUT) // fade type
  8544. write_byte(0) // red
  8545. write_byte(50) // green
  8546. write_byte(200) // blue
  8547. write_byte(100) // alpha
  8548. message_end()
  8549.  
  8550. // Set the frozen flag
  8551. g_frozen[victim] = true
  8552.  
  8553. // Save player's old gravity (bugfix)
  8554. pev(victim, pev_gravity, g_frozen_gravity[victim])
  8555.  
  8556. // Prevent from jumping
  8557. if (pev(victim, pev_flags) & FL_ONGROUND)
  8558. set_pev(victim, pev_gravity, 999999.9) // set really high
  8559. else
  8560. set_pev(victim, pev_gravity, 0.000001) // no gravity
  8561.  
  8562. // Prevent from moving
  8563. ExecuteHamB(Ham_Player_ResetMaxSpeed, victim)
  8564.  
  8565. // Set a task to remove the freeze
  8566. set_task(get_pcvar_float(cvar_freezeduration), "remove_freeze", victim)
  8567. }
  8568.  
  8569. // Get rid of the grenade
  8570. engfunc(EngFunc_RemoveEntity, ent)
  8571. }
  8572.  
  8573. // Remove freeze task
  8574. public remove_freeze(id)
  8575. {
  8576. // Not alive or not frozen anymore
  8577. if (!g_isalive[id] || !g_frozen[id])
  8578. return;
  8579.  
  8580. // Unfreeze
  8581. g_frozen[id] = false;
  8582.  
  8583. // Restore gravity and maxspeed (bugfix)
  8584. set_pev(id, pev_gravity, g_frozen_gravity[id])
  8585. ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
  8586.  
  8587. // Restore rendering
  8588. if (g_handle_models_on_separate_ent)
  8589. {
  8590. // Nemesis or Survivor glow / remove glow on player model entity
  8591. if (g_nemesis[id] && get_pcvar_num(cvar_nemglow))
  8592. fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 255, 0, 0, kRenderNormal, 25)
  8593. else if (g_survivor[id] && get_pcvar_num(cvar_survglow))
  8594. fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 0, 0, 255, kRenderNormal, 25)
  8595. else
  8596. fm_set_rendering(g_ent_playermodel[id])
  8597. }
  8598. else
  8599. {
  8600. // Nemesis or Survivor glow / remove glow
  8601. if (g_nemesis[id] && get_pcvar_num(cvar_nemglow))
  8602. fm_set_rendering(id, kRenderFxGlowShell, 255, 0, 0, kRenderNormal, 25)
  8603. else if (g_survivor[id] && get_pcvar_num(cvar_survglow))
  8604. fm_set_rendering(id, kRenderFxGlowShell, 0, 0, 255, kRenderNormal, 25)
  8605. else
  8606. fm_set_rendering(id)
  8607. }
  8608.  
  8609. // Gradually remove screen's blue tint
  8610. message_begin(MSG_ONE, g_msgScreenFade, _, id)
  8611. write_short(UNIT_SECOND) // duration
  8612. write_short(0) // hold time
  8613. write_short(FFADE_IN) // fade type
  8614. write_byte(0) // red
  8615. write_byte(50) // green
  8616. write_byte(200) // blue
  8617. write_byte(100) // alpha
  8618. message_end()
  8619.  
  8620. // Broken glass sound
  8621. static sound[64]
  8622. ArrayGetString(grenade_frost_break, random_num(0, ArraySize(grenade_frost_break) - 1), sound, charsmax(sound))
  8623. emit_sound(id, CHAN_BODY, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  8624.  
  8625. // Get player's origin
  8626. static origin2[3]
  8627. get_user_origin(id, origin2)
  8628.  
  8629. // Glass shatter
  8630. message_begin(MSG_PVS, SVC_TEMPENTITY, origin2)
  8631. write_byte(TE_BREAKMODEL) // TE id
  8632. write_coord(origin2[0]) // x
  8633. write_coord(origin2[1]) // y
  8634. write_coord(origin2[2]+24) // z
  8635. write_coord(16) // size x
  8636. write_coord(16) // size y
  8637. write_coord(16) // size z
  8638. write_coord(random_num(-50, 50)) // velocity x
  8639. write_coord(random_num(-50, 50)) // velocity y
  8640. write_coord(25) // velocity z
  8641. write_byte(10) // random velocity
  8642. write_short(g_glassSpr) // model
  8643. write_byte(10) // count
  8644. write_byte(25) // life
  8645. write_byte(BREAK_GLASS) // flags
  8646. message_end()
  8647.  
  8648. ExecuteForward(g_fwUserUnfrozen, g_fwDummyResult, id);
  8649. }
  8650.  
  8651. // Remove Stuff Task
  8652. public remove_stuff()
  8653. {
  8654. static ent
  8655.  
  8656. // Remove rotating doors
  8657. if (get_pcvar_num(cvar_removedoors) > 0)
  8658. {
  8659. ent = -1;
  8660. while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "func_door_rotating")) != 0)
  8661. engfunc(EngFunc_SetOrigin, ent, Float:{8192.0 ,8192.0 ,8192.0})
  8662. }
  8663.  
  8664. // Remove all doors
  8665. if (get_pcvar_num(cvar_removedoors) > 1)
  8666. {
  8667. ent = -1;
  8668. while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "func_door")) != 0)
  8669. engfunc(EngFunc_SetOrigin, ent, Float:{8192.0 ,8192.0 ,8192.0})
  8670. }
  8671.  
  8672. // Triggered lights
  8673. if (!get_pcvar_num(cvar_triggered))
  8674. {
  8675. ent = -1
  8676. while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "light")) != 0)
  8677. {
  8678. dllfunc(DLLFunc_Use, ent, 0); // turn off the light
  8679. set_pev(ent, pev_targetname, 0) // prevent it from being triggered
  8680. }
  8681. }
  8682. }
  8683.  
  8684. // Set Custom Weapon Models
  8685. replace_weapon_models(id, weaponid)
  8686. {
  8687. switch (weaponid)
  8688. {
  8689. case CSW_KNIFE: // Custom knife models
  8690. {
  8691. if (g_zombie[id])
  8692. {
  8693. if (g_nemesis[id]) // Nemesis
  8694. {
  8695. set_pev(id, pev_viewmodel2, model_vknife_nemesis)
  8696. set_pev(id, pev_weaponmodel2, "")
  8697. }
  8698. else // Zombies
  8699. {
  8700. // Admin knife models?
  8701. if (get_pcvar_num(cvar_adminknifemodelszombie) && get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS])
  8702. {
  8703. set_pev(id, pev_viewmodel2, model_vknife_admin_zombie)
  8704. set_pev(id, pev_weaponmodel2, "")
  8705. }
  8706. else
  8707. {
  8708. static clawmodel[100]
  8709. ArrayGetString(g_zclass_clawmodel, g_zombieclass[id], clawmodel, charsmax(clawmodel))
  8710. format(clawmodel, charsmax(clawmodel), "models/zombie_plague/%s", clawmodel)
  8711. set_pev(id, pev_viewmodel2, clawmodel)
  8712. set_pev(id, pev_weaponmodel2, "")
  8713. }
  8714. }
  8715. }
  8716. else // Humans
  8717. {
  8718. // Admin knife models?
  8719. if (get_pcvar_num(cvar_adminknifemodelshuman) && get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS])
  8720. {
  8721. set_pev(id, pev_viewmodel2, model_vknife_admin_human)
  8722. set_pev(id, pev_weaponmodel2, "models/p_knife.mdl")
  8723. }
  8724. else
  8725. {
  8726. set_pev(id, pev_viewmodel2, model_vknife_human)
  8727. set_pev(id, pev_weaponmodel2, "models/p_knife.mdl")
  8728. }
  8729. }
  8730. }
  8731. case CSW_HEGRENADE: // Infection bomb or fire grenade
  8732. {
  8733. if (g_zombie[id])
  8734. set_pev(id, pev_viewmodel2, model_grenade_infect)
  8735. else
  8736. set_pev(id, pev_viewmodel2, model_grenade_fire)
  8737. }
  8738. case CSW_FLASHBANG: // Frost grenade
  8739. {
  8740. set_pev(id, pev_viewmodel2, model_grenade_frost)
  8741. }
  8742. case CSW_SMOKEGRENADE: // Flare grenade
  8743. {
  8744. set_pev(id, pev_viewmodel2, model_grenade_flare)
  8745. }
  8746. }
  8747.  
  8748. // Survivor's custom weapon model
  8749. static survweaponname[32]
  8750. get_pcvar_string(cvar_survweapon, survweaponname, charsmax(survweaponname))
  8751. if (g_survivor[id] && weaponid == cs_weapon_name_to_id(survweaponname))
  8752. set_pev(id, pev_viewmodel2, model_vweapon_survivor)
  8753.  
  8754. // Update model on weaponmodel ent
  8755. if (g_handle_models_on_separate_ent) fm_set_weaponmodel_ent(id)
  8756. }
  8757.  
  8758. // Reset Player Vars
  8759. reset_vars(id, resetall)
  8760. {
  8761. g_zombie[id] = false
  8762. g_nemesis[id] = false
  8763. g_survivor[id] = false
  8764. g_firstzombie[id] = false
  8765. g_lastzombie[id] = false
  8766. g_lasthuman[id] = false
  8767. g_frozen[id] = false
  8768. g_nodamage[id] = false
  8769. g_respawn_as_zombie[id] = false
  8770. g_nvision[id] = false
  8771. g_nvisionenabled[id] = false
  8772. g_flashlight[id] = false
  8773. g_flashbattery[id] = 100
  8774. g_canbuy[id] = true
  8775. g_burning_duration[id] = 0
  8776.  
  8777. if (resetall)
  8778. {
  8779. g_ammopacks[id] = get_pcvar_num(cvar_startammopacks)
  8780. g_zombieclass[id] = ZCLASS_NONE
  8781. g_zombieclassnext[id] = ZCLASS_NONE
  8782. g_damagedealt_human[id] = 0
  8783. g_damagedealt_zombie[id] = 0
  8784. WPN_AUTO_ON = 0
  8785. WPN_STARTID = 0
  8786. PL_ACTION = 0
  8787. MENU_PAGE_ZCLASS = 0
  8788. MENU_PAGE_EXTRAS = 0
  8789. MENU_PAGE_PLAYERS = 0
  8790. }
  8791. }
  8792.  
  8793. // Set spectators nightvision
  8794. public spec_nvision(id)
  8795. {
  8796. // Not connected, alive, or bot
  8797. if (!g_isconnected[id] || g_isalive[id] || g_isbot[id])
  8798. return;
  8799.  
  8800. // Give Night Vision?
  8801. if (get_pcvar_num(cvar_nvggive))
  8802. {
  8803. g_nvision[id] = true
  8804.  
  8805. // Turn on Night Vision automatically?
  8806. if (get_pcvar_num(cvar_nvggive) == 1)
  8807. {
  8808. g_nvisionenabled[id] = true
  8809.  
  8810. // Custom nvg?
  8811. if (get_pcvar_num(cvar_customnvg))
  8812. {
  8813. remove_task(id+TASK_NVISION)
  8814. set_task(0.1, "set_user_nvision", id+TASK_NVISION, _, _, "b")
  8815. }
  8816. else
  8817. set_user_gnvision(id, 1)
  8818. }
  8819. }
  8820. }
  8821.  
  8822. // Show HUD Task
  8823. public ShowHUD(taskid)
  8824. {
  8825. static id
  8826. id = ID_SHOWHUD;
  8827.  
  8828. // Player died?
  8829. if (!g_isalive[id])
  8830. {
  8831. // Get spectating target
  8832. id = pev(id, PEV_SPEC_TARGET)
  8833.  
  8834. // Target not alive
  8835. if (!g_isalive[id]) return;
  8836. }
  8837.  
  8838. // Format classname
  8839. static class[32]
  8840.  
  8841. if (g_zombie[id]) // zombies
  8842. {
  8843. if (g_nemesis[id])
  8844. formatex(class, charsmax(class), "%L", ID_SHOWHUD, "CLASS_NEMESIS")
  8845. else
  8846. copy(class, charsmax(class), g_zombie_classname[id])
  8847. }
  8848. else // humans
  8849. {
  8850. if (g_survivor[id])
  8851. formatex(class, charsmax(class), "%L", ID_SHOWHUD, "CLASS_SURVIVOR")
  8852. else
  8853. formatex(class, charsmax(class), "%L", ID_SHOWHUD, "CLASS_HUMAN")
  8854. }
  8855.  
  8856. // Spectating someone else?
  8857. if (id != ID_SHOWHUD)
  8858. {
  8859. // Show name, health, class, and ammo packs
  8860. set_hudmessage(255, 255, 255, HUD_SPECT_X, HUD_SPECT_Y, 0, 6.0, 1.1, 0.0, 0.0, -1)
  8861. ShowSyncHudMsg(ID_SHOWHUD, g_MsgSync2, "%L %s^nHP: %d - %L %s - %L %d", ID_SHOWHUD, "SPECTATING", g_playername[id], pev(id, pev_health), ID_SHOWHUD, "CLASS_CLASS", class, ID_SHOWHUD, "AMMO_PACKS1", g_ammopacks[id])
  8862. }
  8863. else
  8864. {
  8865. // Show health, class and ammo packs
  8866. set_hudmessage(150, 150, 0, HUD_STATS_X, HUD_STATS_Y, 0, 6.0, 1.1, 0.0, 0.0, -1)
  8867. ShowSyncHudMsg(ID_SHOWHUD, g_MsgSync2, "[%L: %d]^n[%L %s]^n[%L %d]", id, "ZOMBIE_ATTRIB1", pev(ID_SHOWHUD, pev_health), ID_SHOWHUD, "CLASS_CLASS", class, ID_SHOWHUD, "AMMO_PACKS1", g_ammopacks[ID_SHOWHUD])
  8868. }
  8869. }
  8870.  
  8871. // Play idle zombie sounds
  8872. public zombie_play_idle(taskid)
  8873. {
  8874. // Round ended/new one starting
  8875. if (g_endround || g_newround)
  8876. return;
  8877.  
  8878. static sound[64]
  8879.  
  8880. // Last zombie?
  8881. if (g_lastzombie[ID_BLOOD])
  8882. {
  8883. ArrayGetString(zombie_idle_last, random_num(0, ArraySize(zombie_idle_last) - 1), sound, charsmax(sound))
  8884. emit_sound(ID_BLOOD, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  8885. }
  8886. else
  8887. {
  8888. ArrayGetString(zombie_idle, random_num(0, ArraySize(zombie_idle) - 1), sound, charsmax(sound))
  8889. emit_sound(ID_BLOOD, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  8890. }
  8891. }
  8892.  
  8893. // Madness Over Task
  8894. public madness_over(taskid)
  8895. {
  8896. g_nodamage[ID_BLOOD] = false
  8897. }
  8898.  
  8899. // Place user at a random spawn
  8900. do_random_spawn(id, regularspawns = 0)
  8901. {
  8902. static hull, sp_index, i
  8903.  
  8904. // Get whether the player is crouching
  8905. hull = (pev(id, pev_flags) & FL_DUCKING) ? HULL_HEAD : HULL_HUMAN
  8906.  
  8907. // Use regular spawns?
  8908. if (!regularspawns)
  8909. {
  8910. // No spawns?
  8911. if (!g_spawnCount)
  8912. return;
  8913.  
  8914. // Choose random spawn to start looping at
  8915. sp_index = random_num(0, g_spawnCount - 1)
  8916.  
  8917. // Try to find a clear spawn
  8918. for (i = sp_index + 1; /*no condition*/; i++)
  8919. {
  8920. // Start over when we reach the end
  8921. if (i >= g_spawnCount) i = 0
  8922.  
  8923. // Free spawn space?
  8924. if (is_hull_vacant(g_spawns[i], hull))
  8925. {
  8926. // Engfunc_SetOrigin is used so ent's mins and maxs get updated instantly
  8927. engfunc(EngFunc_SetOrigin, id, g_spawns[i])
  8928. break;
  8929. }
  8930.  
  8931. // Loop completed, no free space found
  8932. if (i == sp_index) break;
  8933. }
  8934. }
  8935. else
  8936. {
  8937. // No spawns?
  8938. if (!g_spawnCount2)
  8939. return;
  8940.  
  8941. // Choose random spawn to start looping at
  8942. sp_index = random_num(0, g_spawnCount2 - 1)
  8943.  
  8944. // Try to find a clear spawn
  8945. for (i = sp_index + 1; /*no condition*/; i++)
  8946. {
  8947. // Start over when we reach the end
  8948. if (i >= g_spawnCount2) i = 0
  8949.  
  8950. // Free spawn space?
  8951. if (is_hull_vacant(g_spawns2[i], hull))
  8952. {
  8953. // Engfunc_SetOrigin is used so ent's mins and maxs get updated instantly
  8954. engfunc(EngFunc_SetOrigin, id, g_spawns2[i])
  8955. break;
  8956. }
  8957.  
  8958. // Loop completed, no free space found
  8959. if (i == sp_index) break;
  8960. }
  8961. }
  8962. }
  8963.  
  8964. // Get Zombies -returns alive zombies number-
  8965. fnGetZombies()
  8966. {
  8967. static iZombies, id
  8968. iZombies = 0
  8969.  
  8970. for (id = 1; id <= g_maxplayers; id++)
  8971. {
  8972. if (g_isalive[id] && g_zombie[id])
  8973. iZombies++
  8974. }
  8975.  
  8976. return iZombies;
  8977. }
  8978.  
  8979. // Get Humans -returns alive humans number-
  8980. fnGetHumans()
  8981. {
  8982. static iHumans, id
  8983. iHumans = 0
  8984.  
  8985. for (id = 1; id <= g_maxplayers; id++)
  8986. {
  8987. if (g_isalive[id] && !g_zombie[id])
  8988. iHumans++
  8989. }
  8990.  
  8991. return iHumans;
  8992. }
  8993.  
  8994. // Get Nemesis -returns alive nemesis number-
  8995. fnGetNemesis()
  8996. {
  8997. static iNemesis, id
  8998. iNemesis = 0
  8999.  
  9000. for (id = 1; id <= g_maxplayers; id++)
  9001. {
  9002. if (g_isalive[id] && g_nemesis[id])
  9003. iNemesis++
  9004. }
  9005.  
  9006. return iNemesis;
  9007. }
  9008.  
  9009. // Get Survivors -returns alive survivors number-
  9010. fnGetSurvivors()
  9011. {
  9012. static iSurvivors, id
  9013. iSurvivors = 0
  9014.  
  9015. for (id = 1; id <= g_maxplayers; id++)
  9016. {
  9017. if (g_isalive[id] && g_survivor[id])
  9018. iSurvivors++
  9019. }
  9020.  
  9021. return iSurvivors;
  9022. }
  9023.  
  9024. // Get Alive -returns alive players number-
  9025. fnGetAlive()
  9026. {
  9027. static iAlive, id
  9028. iAlive = 0
  9029.  
  9030. for (id = 1; id <= g_maxplayers; id++)
  9031. {
  9032. if (g_isalive[id])
  9033. iAlive++
  9034. }
  9035.  
  9036. return iAlive;
  9037. }
  9038.  
  9039. // Get Random Alive -returns index of alive player number n -
  9040. fnGetRandomAlive(n)
  9041. {
  9042. static iAlive, id
  9043. iAlive = 0
  9044.  
  9045. for (id = 1; id <= g_maxplayers; id++)
  9046. {
  9047. if (g_isalive[id])
  9048. iAlive++
  9049.  
  9050. if (iAlive == n)
  9051. return id;
  9052. }
  9053.  
  9054. return -1;
  9055. }
  9056.  
  9057. // Get Playing -returns number of users playing-
  9058. fnGetPlaying()
  9059. {
  9060. static iPlaying, id, team
  9061. iPlaying = 0
  9062.  
  9063. for (id = 1; id <= g_maxplayers; id++)
  9064. {
  9065. if (g_isconnected[id])
  9066. {
  9067. team = fm_cs_get_user_team(id)
  9068.  
  9069. if (team != FM_CS_TEAM_SPECTATOR && team != FM_CS_TEAM_UNASSIGNED)
  9070. iPlaying++
  9071. }
  9072. }
  9073.  
  9074. return iPlaying;
  9075. }
  9076.  
  9077. // Get CTs -returns number of CTs connected-
  9078. fnGetCTs()
  9079. {
  9080. static iCTs, id
  9081. iCTs = 0
  9082.  
  9083. for (id = 1; id <= g_maxplayers; id++)
  9084. {
  9085. if (g_isconnected[id])
  9086. {
  9087. if (fm_cs_get_user_team(id) == FM_CS_TEAM_CT)
  9088. iCTs++
  9089. }
  9090. }
  9091.  
  9092. return iCTs;
  9093. }
  9094.  
  9095. // Get Ts -returns number of Ts connected-
  9096. fnGetTs()
  9097. {
  9098. static iTs, id
  9099. iTs = 0
  9100.  
  9101. for (id = 1; id <= g_maxplayers; id++)
  9102. {
  9103. if (g_isconnected[id])
  9104. {
  9105. if (fm_cs_get_user_team(id) == FM_CS_TEAM_T)
  9106. iTs++
  9107. }
  9108. }
  9109.  
  9110. return iTs;
  9111. }
  9112.  
  9113. // Get Alive CTs -returns number of CTs alive-
  9114. fnGetAliveCTs()
  9115. {
  9116. static iCTs, id
  9117. iCTs = 0
  9118.  
  9119. for (id = 1; id <= g_maxplayers; id++)
  9120. {
  9121. if (g_isalive[id])
  9122. {
  9123. if (fm_cs_get_user_team(id) == FM_CS_TEAM_CT)
  9124. iCTs++
  9125. }
  9126. }
  9127.  
  9128. return iCTs;
  9129. }
  9130.  
  9131. // Get Alive Ts -returns number of Ts alive-
  9132. fnGetAliveTs()
  9133. {
  9134. static iTs, id
  9135. iTs = 0
  9136.  
  9137. for (id = 1; id <= g_maxplayers; id++)
  9138. {
  9139. if (g_isalive[id])
  9140. {
  9141. if (fm_cs_get_user_team(id) == FM_CS_TEAM_T)
  9142. iTs++
  9143. }
  9144. }
  9145.  
  9146. return iTs;
  9147. }
  9148.  
  9149. // Last Zombie Check -check for last zombie and set its flag-
  9150. fnCheckLastZombie()
  9151. {
  9152. static id
  9153. for (id = 1; id <= g_maxplayers; id++)
  9154. {
  9155. // Last zombie
  9156. if (g_isalive[id] && g_zombie[id] && !g_nemesis[id] && fnGetZombies() == 1)
  9157. {
  9158. if (!g_lastzombie[id])
  9159. {
  9160. // Last zombie forward
  9161. ExecuteForward(g_fwUserLastZombie, g_fwDummyResult, id);
  9162. }
  9163. g_lastzombie[id] = true
  9164. }
  9165. else
  9166. g_lastzombie[id] = false
  9167.  
  9168. // Last human
  9169. if (g_isalive[id] && !g_zombie[id] && !g_survivor[id] && fnGetHumans() == 1)
  9170. {
  9171. if (!g_lasthuman[id])
  9172. {
  9173. // Last human forward
  9174. ExecuteForward(g_fwUserLastHuman, g_fwDummyResult, id);
  9175.  
  9176. // Reward extra hp
  9177. fm_set_user_health(id, pev(id, pev_health) + get_pcvar_num(cvar_humanlasthp))
  9178. }
  9179. g_lasthuman[id] = true
  9180. }
  9181. else
  9182. g_lasthuman[id] = false
  9183. }
  9184. }
  9185.  
  9186. // Save player's stats to database
  9187. save_stats(id)
  9188. {
  9189. // Check whether there is another record already in that slot
  9190. if (db_name[id][0] && !equal(g_playername[id], db_name[id]))
  9191. {
  9192. // If DB size is exceeded, write over old records
  9193. if (db_slot_i >= sizeof db_name)
  9194. db_slot_i = g_maxplayers+1
  9195.  
  9196. // Move previous record onto an additional save slot
  9197. copy(db_name[db_slot_i], charsmax(db_name[]), db_name[id])
  9198. db_ammopacks[db_slot_i] = db_ammopacks[id]
  9199. db_zombieclass[db_slot_i] = db_zombieclass[id]
  9200. db_slot_i++
  9201. }
  9202.  
  9203. // Now save the current player stats
  9204. copy(db_name[id], charsmax(db_name[]), g_playername[id]) // name
  9205. db_ammopacks[id] = g_ammopacks[id] // ammo packs
  9206. db_zombieclass[id] = g_zombieclassnext[id] // zombie class
  9207. }
  9208.  
  9209. // Load player's stats from database (if a record is found)
  9210. load_stats(id)
  9211. {
  9212. // Look for a matching record
  9213. static i
  9214. for (i = 0; i < sizeof db_name; i++)
  9215. {
  9216. if (equal(g_playername[id], db_name[i]))
  9217. {
  9218. // Bingo!
  9219. g_ammopacks[id] = db_ammopacks[i]
  9220. g_zombieclass[id] = db_zombieclass[i]
  9221. g_zombieclassnext[id] = db_zombieclass[i]
  9222. return;
  9223. }
  9224. }
  9225. }
  9226.  
  9227. // Checks if a player is allowed to be zombie
  9228. allowed_zombie(id)
  9229. {
  9230. if ((g_zombie[id] && !g_nemesis[id]) || g_endround || !g_isalive[id] || task_exists(TASK_WELCOMEMSG) || (!g_newround && !g_zombie[id] && fnGetHumans() == 1))
  9231. return false;
  9232.  
  9233. return true;
  9234. }
  9235.  
  9236. // Checks if a player is allowed to be human
  9237. allowed_human(id)
  9238. {
  9239. if ((!g_zombie[id] && !g_survivor[id]) || g_endround || !g_isalive[id] || task_exists(TASK_WELCOMEMSG) || (!g_newround && g_zombie[id] && fnGetZombies() == 1))
  9240. return false;
  9241.  
  9242. return true;
  9243. }
  9244.  
  9245. // Checks if a player is allowed to be survivor
  9246. allowed_survivor(id)
  9247. {
  9248. if (g_endround || g_survivor[id] || !g_isalive[id] || task_exists(TASK_WELCOMEMSG) || (!g_newround && g_zombie[id] && fnGetZombies() == 1))
  9249. return false;
  9250.  
  9251. return true;
  9252. }
  9253.  
  9254. // Checks if a player is allowed to be nemesis
  9255. allowed_nemesis(id)
  9256. {
  9257. if (g_endround || g_nemesis[id] || !g_isalive[id] || task_exists(TASK_WELCOMEMSG) || (!g_newround && !g_zombie[id] && fnGetHumans() == 1))
  9258. return false;
  9259.  
  9260. return true;
  9261. }
  9262.  
  9263. // Checks if a player is allowed to respawn
  9264. allowed_respawn(id)
  9265. {
  9266. static team
  9267. team = fm_cs_get_user_team(id)
  9268.  
  9269. if (g_endround || team == FM_CS_TEAM_SPECTATOR || team == FM_CS_TEAM_UNASSIGNED || g_isalive[id])
  9270. return false;
  9271.  
  9272. return true;
  9273. }
  9274.  
  9275. // Checks if swarm mode is allowed
  9276. allowed_swarm()
  9277. {
  9278. if (g_endround || !g_newround || task_exists(TASK_WELCOMEMSG))
  9279. return false;
  9280.  
  9281. return true;
  9282. }
  9283.  
  9284. // Checks if multi infection mode is allowed
  9285. allowed_multi()
  9286. {
  9287. if (g_endround || !g_newround || task_exists(TASK_WELCOMEMSG) || floatround(fnGetAlive()*get_pcvar_float(cvar_multiratio), floatround_ceil) < 2 || floatround(fnGetAlive()*get_pcvar_float(cvar_multiratio), floatround_ceil) >= fnGetAlive())
  9288. return false;
  9289.  
  9290. return true;
  9291. }
  9292.  
  9293. // Checks if plague mode is allowed
  9294. allowed_plague()
  9295. {
  9296. if (g_endround || !g_newround || task_exists(TASK_WELCOMEMSG) || floatround((fnGetAlive()-(get_pcvar_num(cvar_plaguenemnum)+get_pcvar_num(cvar_plaguesurvnum)))*get_pcvar_float(cvar_plagueratio), floatround_ceil) < 1
  9297. || fnGetAlive()-(get_pcvar_num(cvar_plaguesurvnum)+get_pcvar_num(cvar_plaguenemnum)+floatround((fnGetAlive()-(get_pcvar_num(cvar_plaguenemnum)+get_pcvar_num(cvar_plaguesurvnum)))*get_pcvar_float(cvar_plagueratio), floatround_ceil)) < 1)
  9298. return false;
  9299.  
  9300. return true;
  9301. }
  9302.  
  9303. // Admin Command. zp_zombie
  9304. command_zombie(id, player)
  9305. {
  9306. // Show activity?
  9307. switch (get_pcvar_num(cvar_showactivity))
  9308. {
  9309. case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_INFECT")
  9310. case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_INFECT")
  9311. }
  9312.  
  9313. // Log to Zombie Plague log file?
  9314. if (get_pcvar_num(cvar_logcommands))
  9315. {
  9316. static logdata[100], authid[32], ip[16]
  9317. get_user_authid(id, authid, charsmax(authid))
  9318. get_user_ip(id, ip, charsmax(ip), 1)
  9319. formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %s %L (Players: %d/%d)", g_playername[id], authid, ip, g_playername[player], LANG_SERVER, "CMD_INFECT", fnGetPlaying(), g_maxplayers)
  9320. log_to_file("zombieplague.log", logdata)
  9321. }
  9322.  
  9323. // New round?
  9324. if (g_newround)
  9325. {
  9326. // Set as first zombie
  9327. remove_task(TASK_MAKEZOMBIE)
  9328. make_a_zombie(MODE_INFECTION, player)
  9329. }
  9330. else
  9331. {
  9332. // Just infect
  9333. zombieme(player, 0, 0, 0, 0)
  9334. }
  9335. }
  9336.  
  9337. // Admin Command. zp_human
  9338. command_human(id, player)
  9339. {
  9340. // Show activity?
  9341. switch (get_pcvar_num(cvar_showactivity))
  9342. {
  9343. case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_DISINFECT")
  9344. case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_DISINFECT")
  9345. }
  9346.  
  9347. // Log to Zombie Plague log file?
  9348. if (get_pcvar_num(cvar_logcommands))
  9349. {
  9350. static logdata[100], authid[32], ip[16]
  9351. get_user_authid(id, authid, charsmax(authid))
  9352. get_user_ip(id, ip, charsmax(ip), 1)
  9353. formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %s %L (Players: %d/%d)", g_playername[id], authid, ip, g_playername[player], LANG_SERVER,"CMD_DISINFECT", fnGetPlaying(), g_maxplayers)
  9354. log_to_file("zombieplague.log", logdata)
  9355. }
  9356.  
  9357. // Turn to human
  9358. humanme(player, 0, 0)
  9359. }
  9360.  
  9361. // Admin Command. zp_survivor
  9362. command_survivor(id, player)
  9363. {
  9364. // Show activity?
  9365. switch (get_pcvar_num(cvar_showactivity))
  9366. {
  9367. case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_SURVIVAL")
  9368. case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_SURVIVAL")
  9369. }
  9370.  
  9371. // Log to Zombie Plague log file?
  9372. if (get_pcvar_num(cvar_logcommands))
  9373. {
  9374. static logdata[100], authid[32], ip[16]
  9375. get_user_authid(id, authid, charsmax(authid))
  9376. get_user_ip(id, ip, charsmax(ip), 1)
  9377. formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %s %L (Players: %d/%d)", g_playername[id], authid, ip, g_playername[player], LANG_SERVER,"CMD_SURVIVAL", fnGetPlaying(), g_maxplayers)
  9378. log_to_file("zombieplague.log", logdata)
  9379. }
  9380.  
  9381. // New round?
  9382. if (g_newround)
  9383. {
  9384. // Set as first survivor
  9385. remove_task(TASK_MAKEZOMBIE)
  9386. make_a_zombie(MODE_SURVIVOR, player)
  9387. }
  9388. else
  9389. {
  9390. // Turn player into a Survivor
  9391. humanme(player, 1, 0)
  9392. }
  9393. }
  9394.  
  9395. // Admin Command. zp_nemesis
  9396. command_nemesis(id, player)
  9397. {
  9398. // Show activity?
  9399. switch (get_pcvar_num(cvar_showactivity))
  9400. {
  9401. case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_NEMESIS")
  9402. case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_NEMESIS")
  9403. }
  9404.  
  9405. // Log to Zombie Plague log file?
  9406. if (get_pcvar_num(cvar_logcommands))
  9407. {
  9408. static logdata[100], authid[32], ip[16]
  9409. get_user_authid(id, authid, charsmax(authid))
  9410. get_user_ip(id, ip, charsmax(ip), 1)
  9411. formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %s %L (Players: %d/%d)", g_playername[id], authid, ip, g_playername[player], LANG_SERVER,"CMD_NEMESIS", fnGetPlaying(), g_maxplayers)
  9412. log_to_file("zombieplague.log", logdata)
  9413. }
  9414.  
  9415. // New round?
  9416. if (g_newround)
  9417. {
  9418. // Set as first nemesis
  9419. remove_task(TASK_MAKEZOMBIE)
  9420. make_a_zombie(MODE_NEMESIS, player)
  9421. }
  9422. else
  9423. {
  9424. // Turn player into a Nemesis
  9425. zombieme(player, 0, 1, 0, 0)
  9426. }
  9427. }
  9428.  
  9429. // Admin Command. zp_respawn
  9430. command_respawn(id, player)
  9431. {
  9432. // Show activity?
  9433. switch (get_pcvar_num(cvar_showactivity))
  9434. {
  9435. case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_RESPAWN")
  9436. case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_RESPAWN")
  9437. }
  9438.  
  9439. // Log to Zombie Plague log file?
  9440. if (get_pcvar_num(cvar_logcommands))
  9441. {
  9442. static logdata[100], authid[32], ip[16]
  9443. get_user_authid(id, authid, charsmax(authid))
  9444. get_user_ip(id, ip, charsmax(ip), 1)
  9445. formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %s %L (Players: %d/%d)", g_playername[id], authid, ip, g_playername[player], LANG_SERVER, "CMD_RESPAWN", fnGetPlaying(), g_maxplayers)
  9446. log_to_file("zombieplague.log", logdata)
  9447. }
  9448.  
  9449. // Respawn as zombie?
  9450. if (get_pcvar_num(cvar_deathmatch) == 2 || (get_pcvar_num(cvar_deathmatch) == 3 && random_num(0, 1)) || (get_pcvar_num(cvar_deathmatch) == 4 && fnGetZombies() < fnGetAlive()/2))
  9451. g_respawn_as_zombie[player] = true
  9452.  
  9453. // Override respawn as zombie setting on nemesis and survivor rounds
  9454. if (g_survround) g_respawn_as_zombie[player] = true
  9455. else if (g_nemround) g_respawn_as_zombie[player] = false
  9456.  
  9457. respawn_player_manually(player);
  9458. }
  9459.  
  9460. // Admin Command. zp_swarm
  9461. command_swarm(id)
  9462. {
  9463. // Show activity?
  9464. switch (get_pcvar_num(cvar_showactivity))
  9465. {
  9466. case 1: client_print(0, print_chat, "ADMIN - %L", LANG_PLAYER, "CMD_SWARM")
  9467. case 2: client_print(0, print_chat, "ADMIN %s - %L", g_playername[id], LANG_PLAYER, "CMD_SWARM")
  9468. }
  9469.  
  9470. // Log to Zombie Plague log file?
  9471. if (get_pcvar_num(cvar_logcommands))
  9472. {
  9473. static logdata[100], authid[32], ip[16]
  9474. get_user_authid(id, authid, charsmax(authid))
  9475. get_user_ip(id, ip, charsmax(ip), 1)
  9476. formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %L (Players: %d/%d)", g_playername[id], authid, ip, LANG_SERVER, "CMD_SWARM", fnGetPlaying(), g_maxplayers)
  9477. log_to_file("zombieplague.log", logdata)
  9478. }
  9479.  
  9480. // Call Swarm Mode
  9481. remove_task(TASK_MAKEZOMBIE)
  9482. make_a_zombie(MODE_SWARM, 0)
  9483. }
  9484.  
  9485. // Admin Command. zp_multi
  9486. command_multi(id)
  9487. {
  9488. // Show activity?
  9489. switch (get_pcvar_num(cvar_showactivity))
  9490. {
  9491. case 1: client_print(0, print_chat, "ADMIN - %L", LANG_PLAYER, "CMD_MULTI")
  9492. case 2: client_print(0, print_chat, "ADMIN %s - %L", g_playername[id], LANG_PLAYER, "CMD_MULTI")
  9493. }
  9494.  
  9495. // Log to Zombie Plague log file?
  9496. if (get_pcvar_num(cvar_logcommands))
  9497. {
  9498. static logdata[100], authid[32], ip[16]
  9499. get_user_authid(id, authid, charsmax(authid))
  9500. get_user_ip(id, ip, charsmax(ip), 1)
  9501. formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %L (Players: %d/%d)", g_playername[id], authid, ip, LANG_SERVER,"CMD_MULTI", fnGetPlaying(), g_maxplayers)
  9502. log_to_file("zombieplague.log", logdata)
  9503. }
  9504.  
  9505. // Call Multi Infection
  9506. remove_task(TASK_MAKEZOMBIE)
  9507. make_a_zombie(MODE_MULTI, 0)
  9508. }
  9509.  
  9510. // Admin Command. zp_plague
  9511. command_plague(id)
  9512. {
  9513. // Show activity?
  9514. switch (get_pcvar_num(cvar_showactivity))
  9515. {
  9516. case 1: client_print(0, print_chat, "ADMIN - %L", LANG_PLAYER, "CMD_PLAGUE")
  9517. case 2: client_print(0, print_chat, "ADMIN %s - %L", g_playername[id], LANG_PLAYER, "CMD_PLAGUE")
  9518. }
  9519.  
  9520. // Log to Zombie Plague log file?
  9521. if (get_pcvar_num(cvar_logcommands))
  9522. {
  9523. static logdata[100], authid[32], ip[16]
  9524. get_user_authid(id, authid, charsmax(authid))
  9525. get_user_ip(id, ip, charsmax(ip), 1)
  9526. formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %L (Players: %d/%d)", g_playername[id], authid, ip, LANG_SERVER,"CMD_PLAGUE", fnGetPlaying(), g_maxplayers)
  9527. log_to_file("zombieplague.log", logdata)
  9528. }
  9529.  
  9530. // Call Plague Mode
  9531. remove_task(TASK_MAKEZOMBIE)
  9532. make_a_zombie(MODE_PLAGUE, 0)
  9533. }
  9534.  
  9535. // Set proper maxspeed for player
  9536. set_player_maxspeed(id)
  9537. {
  9538. // If frozen, prevent from moving
  9539. if (g_frozen[id])
  9540. {
  9541. set_pev(id, pev_maxspeed, 1.0)
  9542. }
  9543. // Otherwise, set maxspeed directly
  9544. else
  9545. {
  9546. if (g_zombie[id])
  9547. {
  9548. if (g_nemesis[id])
  9549. set_pev(id, pev_maxspeed, get_pcvar_float(cvar_nemspd))
  9550. else
  9551. set_pev(id, pev_maxspeed, g_zombie_spd[id])
  9552. }
  9553. else
  9554. {
  9555. if (g_survivor[id])
  9556. set_pev(id, pev_maxspeed, get_pcvar_float(cvar_survspd))
  9557. else if (get_pcvar_float(cvar_humanspd) > 0.0)
  9558. set_pev(id, pev_maxspeed, get_pcvar_float(cvar_humanspd))
  9559. }
  9560. }
  9561. }
  9562.  
  9563. /*================================================================================
  9564. [Custom Natives]
  9565. =================================================================================*/
  9566.  
  9567. // Native: zp_get_user_zombie
  9568. public native_get_user_zombie(id)
  9569. {
  9570. if (!is_user_valid(id))
  9571. {
  9572. log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
  9573. return -1;
  9574. }
  9575.  
  9576. return g_zombie[id];
  9577. }
  9578.  
  9579. // Native: zp_get_user_nemesis
  9580. public native_get_user_nemesis(id)
  9581. {
  9582. if (!is_user_valid(id))
  9583. {
  9584. log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
  9585. return -1;
  9586. }
  9587.  
  9588. return g_nemesis[id];
  9589. }
  9590.  
  9591. // Native: zp_get_user_survivor
  9592. public native_get_user_survivor(id)
  9593. {
  9594. if (!is_user_valid(id))
  9595. {
  9596. log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
  9597. return -1;
  9598. }
  9599.  
  9600. return g_survivor[id];
  9601. }
  9602.  
  9603. public native_get_user_first_zombie(id)
  9604. {
  9605. if (!is_user_valid(id))
  9606. {
  9607. log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
  9608. return -1;
  9609. }
  9610.  
  9611. return g_firstzombie[id];
  9612. }
  9613.  
  9614. // Native: zp_get_user_last_zombie
  9615. public native_get_user_last_zombie(id)
  9616. {
  9617. if (!is_user_valid(id))
  9618. {
  9619. log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
  9620. return -1;
  9621. }
  9622.  
  9623. return g_lastzombie[id];
  9624. }
  9625.  
  9626. // Native: zp_get_user_last_human
  9627. public native_get_user_last_human(id)
  9628. {
  9629. if (!is_user_valid(id))
  9630. {
  9631. log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
  9632. return -1;
  9633. }
  9634.  
  9635. return g_lasthuman[id];
  9636. }
  9637.  
  9638. // Native: zp_get_user_zombie_class
  9639. public native_get_user_zombie_class(id)
  9640. {
  9641. if (!is_user_valid(id))
  9642. {
  9643. log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
  9644. return -1;
  9645. }
  9646.  
  9647. return g_zombieclass[id];
  9648. }
  9649.  
  9650. // Native: zp_get_user_next_class
  9651. public native_get_user_next_class(id)
  9652. {
  9653. if (!is_user_valid(id))
  9654. {
  9655. log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
  9656. return -1;
  9657. }
  9658.  
  9659. return g_zombieclassnext[id];
  9660. }
  9661.  
  9662. // Native: zp_set_user_zombie_class
  9663. public native_set_user_zombie_class(id, classid)
  9664. {
  9665. if (!is_user_valid(id))
  9666. {
  9667. log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
  9668. return false;
  9669. }
  9670.  
  9671. if (classid < 0 || classid >= g_zclass_i)
  9672. {
  9673. log_error(AMX_ERR_NATIVE, "[ZP] Invalid zombie class id (%d)", classid)
  9674. return false;
  9675. }
  9676.  
  9677. g_zombieclassnext[id] = classid
  9678. return true;
  9679. }
  9680.  
  9681. // Native: zp_get_user_ammo_packs
  9682. public native_get_user_ammo_packs(id)
  9683. {
  9684. if (!is_user_valid(id))
  9685. {
  9686. log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
  9687. return -1;
  9688. }
  9689.  
  9690. return g_ammopacks[id];
  9691. }
  9692.  
  9693. // Native: zp_set_user_ammo_packs
  9694. public native_set_user_ammo_packs(id, amount)
  9695. {
  9696. if (!is_user_valid(id))
  9697. {
  9698. log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
  9699. return false;
  9700. }
  9701.  
  9702. g_ammopacks[id] = amount;
  9703. return true;
  9704. }
  9705.  
  9706. // Native: zp_get_zombie_maxhealth
  9707. public native_get_zombie_maxhealth(id)
  9708. {
  9709. // ZP disabled
  9710. if (!g_pluginenabled)
  9711. return -1;
  9712.  
  9713. if (!is_user_valid(id))
  9714. {
  9715. log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
  9716. return -1;
  9717. }
  9718.  
  9719. if (!g_zombie[id] || g_nemesis[id])
  9720. {
  9721. log_error(AMX_ERR_NATIVE, "[ZP] Player not a normal zombie (%d)", id)
  9722. return -1;
  9723. }
  9724.  
  9725. if (g_firstzombie[id])
  9726. return floatround(float(ArrayGetCell(g_zclass_hp, g_zombieclass[id])) * get_pcvar_float(cvar_zombiefirsthp));
  9727.  
  9728. return ArrayGetCell(g_zclass_hp, g_zombieclass[id]);
  9729. }
  9730.  
  9731. // Native: zp_get_user_batteries
  9732. public native_get_user_batteries(id)
  9733. {
  9734. if (!is_user_valid(id))
  9735. {
  9736. log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
  9737. return -1;
  9738. }
  9739.  
  9740. return g_flashbattery[id];
  9741. }
  9742.  
  9743. // Native: zp_set_user_batteries
  9744. public native_set_user_batteries(id, value)
  9745. {
  9746. // ZP disabled
  9747. if (!g_pluginenabled)
  9748. return false;
  9749.  
  9750. if (!is_user_valid_connected(id))
  9751. {
  9752. log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
  9753. return false;
  9754. }
  9755.  
  9756. g_flashbattery[id] = clamp(value, 0, 100);
  9757.  
  9758. if (g_cached_customflash)
  9759. {
  9760. // Set the flashlight charge task to update battery status
  9761. remove_task(id+TASK_CHARGE)
  9762. set_task(1.0, "flashlight_charge", id+TASK_CHARGE, _, _, "b")
  9763. }
  9764. return true;
  9765. }
  9766.  
  9767. // Native: zp_get_user_nightvision
  9768. public native_get_user_nightvision(id)
  9769. {
  9770. if (!is_user_valid(id))
  9771. {
  9772. log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
  9773. return -1;
  9774. }
  9775.  
  9776. return g_nvision[id];
  9777. }
  9778.  
  9779. // Native: zp_set_user_nightvision
  9780. public native_set_user_nightvision(id, set)
  9781. {
  9782. // ZP disabled
  9783. if (!g_pluginenabled)
  9784. return false;
  9785.  
  9786. if (!is_user_valid_connected(id))
  9787. {
  9788. log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
  9789. return false;
  9790. }
  9791.  
  9792. if (set)
  9793. {
  9794. g_nvision[id] = true
  9795.  
  9796. if (!g_isbot[id])
  9797. {
  9798. g_nvisionenabled[id] = true
  9799.  
  9800. // Custom nvg?
  9801. if (get_pcvar_num(cvar_customnvg))
  9802. {
  9803. remove_task(id+TASK_NVISION)
  9804. set_task(0.1, "set_user_nvision", id+TASK_NVISION, _, _, "b")
  9805. }
  9806. else
  9807. set_user_gnvision(id, 1)
  9808. }
  9809. else
  9810. cs_set_user_nvg(id, 1)
  9811. }
  9812. else
  9813. {
  9814. // Remove CS nightvision if player owns one (bugfix)
  9815. cs_set_user_nvg(id, 0)
  9816.  
  9817. if (get_pcvar_num(cvar_customnvg)) remove_task(id+TASK_NVISION)
  9818. else if (g_nvisionenabled[id]) set_user_gnvision(id, 0)
  9819. g_nvision[id] = false
  9820. g_nvisionenabled[id] = false
  9821. }
  9822. return true;
  9823. }
  9824.  
  9825. // Native: zp_infect_user
  9826. public native_infect_user(id, infector, silent, rewards)
  9827. {
  9828. // ZP disabled
  9829. if (!g_pluginenabled)
  9830. return false;
  9831.  
  9832. if (!is_user_valid_alive(id))
  9833. {
  9834. log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
  9835. return false;
  9836. }
  9837.  
  9838. // Not allowed to be zombie
  9839. if (!allowed_zombie(id))
  9840. return false;
  9841.  
  9842. // New round?
  9843. if (g_newround)
  9844. {
  9845. // Set as first zombie
  9846. remove_task(TASK_MAKEZOMBIE)
  9847. make_a_zombie(MODE_INFECTION, id)
  9848. }
  9849. else
  9850. {
  9851. // Just infect (plus some checks)
  9852. zombieme(id, is_user_valid_alive(infector) ? infector : 0, 0, (silent == 1) ? 1 : 0, (rewards == 1) ? 1 : 0)
  9853. }
  9854. return true;
  9855. }
  9856.  
  9857. // Native: zp_disinfect_user
  9858. public native_disinfect_user(id, silent)
  9859. {
  9860. // ZP disabled
  9861. if (!g_pluginenabled)
  9862. return false;
  9863.  
  9864. if (!is_user_valid_alive(id))
  9865. {
  9866. log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
  9867. return false;
  9868. }
  9869.  
  9870. // Not allowed to be human
  9871. if (!allowed_human(id))
  9872. return false;
  9873.  
  9874. // Turn to human
  9875. humanme(id, 0, (silent == 1) ? 1 : 0)
  9876. return true;
  9877. }
  9878.  
  9879. // Native: zp_make_user_nemesis
  9880. public native_make_user_nemesis(id)
  9881. {
  9882. // ZP disabled
  9883. if (!g_pluginenabled)
  9884. return false;
  9885.  
  9886. if (!is_user_valid_alive(id))
  9887. {
  9888. log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
  9889. return false;
  9890. }
  9891.  
  9892. // Not allowed to be nemesis
  9893. if (!allowed_nemesis(id))
  9894. return false;
  9895.  
  9896. // New round?
  9897. if (g_newround)
  9898. {
  9899. // Set as first nemesis
  9900. remove_task(TASK_MAKEZOMBIE)
  9901. make_a_zombie(MODE_NEMESIS, id)
  9902. }
  9903. else
  9904. {
  9905. // Turn player into a Nemesis
  9906. zombieme(id, 0, 1, 0, 0)
  9907. }
  9908. return true;
  9909. }
  9910.  
  9911. // Native: zp_make_user_survivor
  9912. public native_make_user_survivor(id)
  9913. {
  9914. // ZP disabled
  9915. if (!g_pluginenabled)
  9916. return false;
  9917.  
  9918. if (!is_user_valid_alive(id))
  9919. {
  9920. log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
  9921. return false;
  9922. }
  9923.  
  9924. // Not allowed to be survivor
  9925. if (!allowed_survivor(id))
  9926. return false;
  9927.  
  9928. // New round?
  9929. if (g_newround)
  9930. {
  9931. // Set as first survivor
  9932. remove_task(TASK_MAKEZOMBIE)
  9933. make_a_zombie(MODE_SURVIVOR, id)
  9934. }
  9935. else
  9936. {
  9937. // Turn player into a Survivor
  9938. humanme(id, 1, 0)
  9939. }
  9940.  
  9941. return true;
  9942. }
  9943.  
  9944. // Native: zp_respawn_user
  9945. public native_respawn_user(id, team)
  9946. {
  9947. // ZP disabled
  9948. if (!g_pluginenabled)
  9949. return false;
  9950.  
  9951. if (!is_user_valid_connected(id))
  9952. {
  9953. log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
  9954. return false;
  9955. }
  9956.  
  9957. // Respawn not allowed
  9958. if (!allowed_respawn(id))
  9959. return false;
  9960.  
  9961. // Respawn as zombie?
  9962. g_respawn_as_zombie[id] = (team == ZP_TEAM_ZOMBIE) ? true : false
  9963.  
  9964. // Respawnish!
  9965. respawn_player_manually(id)
  9966. return true;
  9967. }
  9968.  
  9969. // Native: zp_force_buy_extra_item
  9970. public native_force_buy_extra_item(id, itemid, ignorecost)
  9971. {
  9972. // ZP disabled
  9973. if (!g_pluginenabled)
  9974. return false;
  9975.  
  9976. if (!is_user_valid_alive(id))
  9977. {
  9978. log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
  9979. return false;
  9980. }
  9981.  
  9982. if (itemid < 0 || itemid >= g_extraitem_i)
  9983. {
  9984. log_error(AMX_ERR_NATIVE, "[ZP] Invalid extra item id (%d)", itemid)
  9985. return false;
  9986. }
  9987.  
  9988. buy_extra_item(id, itemid, ignorecost)
  9989. return true;
  9990. }
  9991.  
  9992. // Native: zp_override_user_model
  9993. public native_override_user_model(id, const newmodel[], modelindex)
  9994. {
  9995. // ZP disabled
  9996. if (!g_pluginenabled)
  9997. return false;
  9998.  
  9999. if (!is_user_valid_connected(id))
  10000. {
  10001. log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
  10002. return false;
  10003. }
  10004.  
  10005. // Strings passed byref
  10006. param_convert(2)
  10007.  
  10008. // Remove previous tasks
  10009. remove_task(id+TASK_MODEL)
  10010.  
  10011. // Custom models stuff
  10012. static currentmodel[32]
  10013.  
  10014. if (g_handle_models_on_separate_ent)
  10015. {
  10016. // Set the right model
  10017. copy(g_playermodel[id], charsmax(g_playermodel[]), newmodel)
  10018. if (g_set_modelindex_offset && modelindex) fm_cs_set_user_model_index(id, modelindex)
  10019.  
  10020. // Set model on player model entity
  10021. fm_set_playermodel_ent(id)
  10022. }
  10023. else
  10024. {
  10025. // Get current model for comparing it with the current one
  10026. fm_cs_get_user_model(id, currentmodel, charsmax(currentmodel))
  10027.  
  10028. // Set the right model, after checking that we don't already have it
  10029. if (!equal(currentmodel, newmodel))
  10030. {
  10031. copy(g_playermodel[id], charsmax(g_playermodel[]), newmodel)
  10032. if (g_set_modelindex_offset && modelindex) fm_cs_set_user_model_index(id, modelindex)
  10033.  
  10034. // An additional delay is offset at round start
  10035. // since SVC_BAD is more likely to be triggered there
  10036. if (g_newround)
  10037. set_task(5.0 * g_modelchange_delay, "fm_user_model_update", id+TASK_MODEL)
  10038. else
  10039. fm_user_model_update(id+TASK_MODEL)
  10040. }
  10041. }
  10042. return true;
  10043. }
  10044.  
  10045. //#include "include/zp_newnatives.inl"
  10046.  
  10047. // Native: zp_has_round_started
  10048. public native_has_round_started()
  10049. {
  10050. if (g_newround) return 0; // not started
  10051. if (g_modestarted) return 1; // started
  10052. return 2; // starting
  10053. }
  10054.  
  10055. // Native: zp_is_nemesis_round
  10056. public native_is_nemesis_round()
  10057. {
  10058. return g_nemround;
  10059. }
  10060.  
  10061. // Native: zp_is_survivor_round
  10062. public native_is_survivor_round()
  10063. {
  10064. return g_survround;
  10065. }
  10066.  
  10067. // Native: zp_is_swarm_round
  10068. public native_is_swarm_round()
  10069. {
  10070. return g_swarmround;
  10071. }
  10072.  
  10073. // Native: zp_is_plague_round
  10074. public native_is_plague_round()
  10075. {
  10076. return g_plagueround;
  10077. }
  10078.  
  10079. // Native: zp_get_zombie_count
  10080. public native_get_zombie_count()
  10081. {
  10082. return fnGetZombies();
  10083. }
  10084.  
  10085. // Native: zp_get_human_count
  10086. public native_get_human_count()
  10087. {
  10088. return fnGetHumans();
  10089. }
  10090.  
  10091. // Native: zp_get_nemesis_count
  10092. public native_get_nemesis_count()
  10093. {
  10094. return fnGetNemesis();
  10095. }
  10096.  
  10097. // Native: zp_get_survivor_count
  10098. public native_get_survivor_count()
  10099. {
  10100. return fnGetSurvivors();
  10101. }
  10102.  
  10103. // Native: zp_register_extra_item
  10104. public native_register_extra_item(const name[], cost, team)
  10105. {
  10106. // ZP disabled
  10107. if (!g_pluginenabled)
  10108. return -1;
  10109.  
  10110. // Strings passed byref
  10111. param_convert(1)
  10112.  
  10113. // Arrays not yet initialized
  10114. if (!g_arrays_created)
  10115. {
  10116. log_error(AMX_ERR_NATIVE, "[ZP] Can't register extra item yet (%s)", name)
  10117. return -1;
  10118. }
  10119.  
  10120. if (strlen(name) < 1)
  10121. {
  10122. log_error(AMX_ERR_NATIVE, "[ZP] Can't register extra item with an empty name")
  10123. return -1;
  10124. }
  10125.  
  10126. new index, extraitem_name[32]
  10127. for (index = 0; index < g_extraitem_i; index++)
  10128. {
  10129. ArrayGetString(g_extraitem_name, index, extraitem_name, charsmax(extraitem_name))
  10130. if (equali(name, extraitem_name))
  10131. {
  10132. log_error(AMX_ERR_NATIVE, "[ZP] Extra item already registered (%s)", name)
  10133. return -1;
  10134. }
  10135. }
  10136.  
  10137. // For backwards compatibility
  10138. if (team == ZP_TEAM_ANY)
  10139. team = (ZP_TEAM_ZOMBIE|ZP_TEAM_HUMAN)
  10140.  
  10141. // Add the item
  10142. ArrayPushString(g_extraitem_name, name)
  10143. ArrayPushCell(g_extraitem_cost, cost)
  10144. ArrayPushCell(g_extraitem_team, team)
  10145.  
  10146. // Set temporary new item flag
  10147. ArrayPushCell(g_extraitem_new, 1)
  10148.  
  10149. // Override extra items data with our customizations
  10150. new i, buffer[32], size = ArraySize(g_extraitem2_realname)
  10151. for (i = 0; i < size; i++)
  10152. {
  10153. ArrayGetString(g_extraitem2_realname, i, buffer, charsmax(buffer))
  10154.  
  10155. // Check if this is the intended item to override
  10156. if (!equal(name, buffer))
  10157. continue;
  10158.  
  10159. // Remove new item flag
  10160. ArraySetCell(g_extraitem_new, g_extraitem_i, 0)
  10161.  
  10162. // Replace caption
  10163. ArrayGetString(g_extraitem2_name, i, buffer, charsmax(buffer))
  10164. ArraySetString(g_extraitem_name, g_extraitem_i, buffer)
  10165.  
  10166. // Replace cost
  10167. buffer[0] = ArrayGetCell(g_extraitem2_cost, i)
  10168. ArraySetCell(g_extraitem_cost, g_extraitem_i, buffer[0])
  10169.  
  10170. // Replace team
  10171. buffer[0] = ArrayGetCell(g_extraitem2_team, i)
  10172. ArraySetCell(g_extraitem_team, g_extraitem_i, buffer[0])
  10173. }
  10174.  
  10175. // Increase registered items counter
  10176. g_extraitem_i++
  10177.  
  10178. // Return id under which we registered the item
  10179. return g_extraitem_i-1;
  10180. }
  10181.  
  10182. // Function: zp_register_extra_item (to be used within this plugin only)
  10183. native_register_extra_item2(const name[], cost, team)
  10184. {
  10185. // Add the item
  10186. ArrayPushString(g_extraitem_name, name)
  10187. ArrayPushCell(g_extraitem_cost, cost)
  10188. ArrayPushCell(g_extraitem_team, team)
  10189.  
  10190. // Set temporary new item flag
  10191. ArrayPushCell(g_extraitem_new, 1)
  10192.  
  10193. // Increase registered items counter
  10194. g_extraitem_i++
  10195. }
  10196.  
  10197. // Native: zp_register_zombie_class
  10198. public native_register_zombie_class(const name[], const info[], const model[], const clawmodel[], hp, speed, Float:gravity, Float:knockback)
  10199. {
  10200. // ZP disabled
  10201. if (!g_pluginenabled)
  10202. return -1;
  10203.  
  10204. // Strings passed byref
  10205. param_convert(1)
  10206. param_convert(2)
  10207. param_convert(3)
  10208. param_convert(4)
  10209.  
  10210. // Arrays not yet initialized
  10211. if (!g_arrays_created)
  10212. {
  10213. log_error(AMX_ERR_NATIVE, "[ZP] Can't register zombie class yet (%s)", name)
  10214. return -1;
  10215. }
  10216.  
  10217. if (strlen(name) < 1)
  10218. {
  10219. log_error(AMX_ERR_NATIVE, "[ZP] Can't register zombie class with an empty name")
  10220. return -1;
  10221. }
  10222.  
  10223. new index, zombieclass_name[32]
  10224. for (index = 0; index < g_zclass_i; index++)
  10225. {
  10226. ArrayGetString(g_zclass_name, index, zombieclass_name, charsmax(zombieclass_name))
  10227. if (equali(name, zombieclass_name))
  10228. {
  10229. log_error(AMX_ERR_NATIVE, "[ZP] Zombie class already registered (%s)", name)
  10230. return -1;
  10231. }
  10232. }
  10233.  
  10234. // Add the class
  10235. ArrayPushString(g_zclass_name, name)
  10236. ArrayPushString(g_zclass_info, info)
  10237.  
  10238. // Using same zombie models for all classes?
  10239. if (g_same_models_for_all)
  10240. {
  10241. ArrayPushCell(g_zclass_modelsstart, 0)
  10242. ArrayPushCell(g_zclass_modelsend, ArraySize(g_zclass_playermodel))
  10243. }
  10244. else
  10245. {
  10246. ArrayPushCell(g_zclass_modelsstart, ArraySize(g_zclass_playermodel))
  10247. ArrayPushString(g_zclass_playermodel, model)
  10248. ArrayPushCell(g_zclass_modelsend, ArraySize(g_zclass_playermodel))
  10249. ArrayPushCell(g_zclass_modelindex, -1)
  10250. }
  10251.  
  10252. ArrayPushString(g_zclass_clawmodel, clawmodel)
  10253. ArrayPushCell(g_zclass_hp, hp)
  10254. ArrayPushCell(g_zclass_spd, speed)
  10255. ArrayPushCell(g_zclass_grav, gravity)
  10256. ArrayPushCell(g_zclass_kb, knockback)
  10257.  
  10258. // Set temporary new class flag
  10259. ArrayPushCell(g_zclass_new, 1)
  10260.  
  10261. // Override zombie classes data with our customizations
  10262. new i, k, buffer[32], Float:buffer2, nummodels_custom, nummodels_default, prec_mdl[100], size = ArraySize(g_zclass2_realname)
  10263. for (i = 0; i < size; i++)
  10264. {
  10265. ArrayGetString(g_zclass2_realname, i, buffer, charsmax(buffer))
  10266.  
  10267. // Check if this is the intended class to override
  10268. if (!equal(name, buffer))
  10269. continue;
  10270.  
  10271. // Remove new class flag
  10272. ArraySetCell(g_zclass_new, g_zclass_i, 0)
  10273.  
  10274. // Replace caption
  10275. ArrayGetString(g_zclass2_name, i, buffer, charsmax(buffer))
  10276. ArraySetString(g_zclass_name, g_zclass_i, buffer)
  10277.  
  10278. // Replace info
  10279. ArrayGetString(g_zclass2_info, i, buffer, charsmax(buffer))
  10280. ArraySetString(g_zclass_info, g_zclass_i, buffer)
  10281.  
  10282. // Replace models, unless using same models for all classes
  10283. if (!g_same_models_for_all)
  10284. {
  10285. nummodels_custom = ArrayGetCell(g_zclass2_modelsend, i) - ArrayGetCell(g_zclass2_modelsstart, i)
  10286. nummodels_default = ArrayGetCell(g_zclass_modelsend, g_zclass_i) - ArrayGetCell(g_zclass_modelsstart, g_zclass_i)
  10287.  
  10288. // Replace each player model and model index
  10289. for (k = 0; k < min(nummodels_custom, nummodels_default); k++)
  10290. {
  10291. ArrayGetString(g_zclass2_playermodel, ArrayGetCell(g_zclass2_modelsstart, i) + k, buffer, charsmax(buffer))
  10292. ArraySetString(g_zclass_playermodel, ArrayGetCell(g_zclass_modelsstart, g_zclass_i) + k, buffer)
  10293.  
  10294. // Precache player model and replace its modelindex with the real one
  10295. formatex(prec_mdl, charsmax(prec_mdl), "models/player/%s/%s.mdl", buffer, buffer)
  10296. ArraySetCell(g_zclass_modelindex, ArrayGetCell(g_zclass_modelsstart, g_zclass_i) + k, engfunc(EngFunc_PrecacheModel, prec_mdl))
  10297. if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, prec_mdl)
  10298. if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, prec_mdl)
  10299. // Precache modelT.mdl files too
  10300. copy(prec_mdl[strlen(prec_mdl)-4], charsmax(prec_mdl) - (strlen(prec_mdl)-4), "T.mdl")
  10301. if (file_exists(prec_mdl)) engfunc(EngFunc_PrecacheModel, prec_mdl)
  10302. }
  10303.  
  10304. // We have more custom models than what we can accommodate,
  10305. // Let's make some space...
  10306. if (nummodels_custom > nummodels_default)
  10307. {
  10308. for (k = nummodels_default; k < nummodels_custom; k++)
  10309. {
  10310. ArrayGetString(g_zclass2_playermodel, ArrayGetCell(g_zclass2_modelsstart, i) + k, buffer, charsmax(buffer))
  10311. ArrayInsertStringAfter(g_zclass_playermodel, ArrayGetCell(g_zclass_modelsstart, g_zclass_i) + k - 1, buffer)
  10312.  
  10313. // Precache player model and retrieve its modelindex
  10314. formatex(prec_mdl, charsmax(prec_mdl), "models/player/%s/%s.mdl", buffer, buffer)
  10315. ArrayInsertCellAfter(g_zclass_modelindex, ArrayGetCell(g_zclass_modelsstart, g_zclass_i) + k - 1, engfunc(EngFunc_PrecacheModel, prec_mdl))
  10316. if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, prec_mdl)
  10317. if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, prec_mdl)
  10318. // Precache modelT.mdl files too
  10319. copy(prec_mdl[strlen(prec_mdl)-4], charsmax(prec_mdl) - (strlen(prec_mdl)-4), "T.mdl")
  10320. if (file_exists(prec_mdl)) engfunc(EngFunc_PrecacheModel, prec_mdl)
  10321. }
  10322.  
  10323. // Fix models end index for this class
  10324. ArraySetCell(g_zclass_modelsend, g_zclass_i, ArrayGetCell(g_zclass_modelsend, g_zclass_i) + (nummodels_custom - nummodels_default))
  10325. }
  10326.  
  10327. /* --- Not needed since classes can't have more than 1 default model for now ---
  10328. // We have less custom models than what this class has by default,
  10329. // Get rid of those extra entries...
  10330. if (nummodels_custom < nummodels_default)
  10331. {
  10332. for (k = nummodels_custom; k < nummodels_default; k++)
  10333. {
  10334. ArrayDeleteItem(g_zclass_playermodel, ArrayGetCell(g_zclass_modelsstart, g_zclass_i) + nummodels_custom)
  10335. }
  10336.  
  10337. // Fix models end index for this class
  10338. ArraySetCell(g_zclass_modelsend, g_zclass_i, ArrayGetCell(g_zclass_modelsend, g_zclass_i) - (nummodels_default - nummodels_custom))
  10339. }
  10340. */
  10341. }
  10342.  
  10343. // Replace clawmodel
  10344. ArrayGetString(g_zclass2_clawmodel, i, buffer, charsmax(buffer))
  10345. ArraySetString(g_zclass_clawmodel, g_zclass_i, buffer)
  10346.  
  10347. // Precache clawmodel
  10348. formatex(prec_mdl, charsmax(prec_mdl), "models/zombie_plague/%s", buffer)
  10349. engfunc(EngFunc_PrecacheModel, prec_mdl)
  10350.  
  10351. // Replace health
  10352. buffer[0] = ArrayGetCell(g_zclass2_hp, i)
  10353. ArraySetCell(g_zclass_hp, g_zclass_i, buffer[0])
  10354.  
  10355. // Replace speed
  10356. buffer[0] = ArrayGetCell(g_zclass2_spd, i)
  10357. ArraySetCell(g_zclass_spd, g_zclass_i, buffer[0])
  10358.  
  10359. // Replace gravity
  10360. buffer2 = Float:ArrayGetCell(g_zclass2_grav, i)
  10361. ArraySetCell(g_zclass_grav, g_zclass_i, buffer2)
  10362.  
  10363. // Replace knockback
  10364. buffer2 = Float:ArrayGetCell(g_zclass2_kb, i)
  10365. ArraySetCell(g_zclass_kb, g_zclass_i, buffer2)
  10366. }
  10367.  
  10368. // If class was not overriden with customization data
  10369. if (ArrayGetCell(g_zclass_new, g_zclass_i))
  10370. {
  10371. // If not using same models for all classes
  10372. if (!g_same_models_for_all)
  10373. {
  10374. // Precache default class model and replace modelindex with the real one
  10375. formatex(prec_mdl, charsmax(prec_mdl), "models/player/%s/%s.mdl", model, model)
  10376. ArraySetCell(g_zclass_modelindex, ArrayGetCell(g_zclass_modelsstart, g_zclass_i), engfunc(EngFunc_PrecacheModel, prec_mdl))
  10377. if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, prec_mdl)
  10378. if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, prec_mdl)
  10379. // Precache modelT.mdl files too
  10380. copy(prec_mdl[strlen(prec_mdl)-4], charsmax(prec_mdl) - (strlen(prec_mdl)-4), "T.mdl")
  10381. if (file_exists(prec_mdl)) engfunc(EngFunc_PrecacheModel, prec_mdl)
  10382. }
  10383.  
  10384. // Precache default clawmodel
  10385. formatex(prec_mdl, charsmax(prec_mdl), "models/zombie_plague/%s", clawmodel)
  10386. engfunc(EngFunc_PrecacheModel, prec_mdl)
  10387. }
  10388.  
  10389. // Increase registered classes counter
  10390. g_zclass_i++
  10391.  
  10392. // Return id under which we registered the class
  10393. return g_zclass_i-1;
  10394. }
  10395.  
  10396. // Native: zp_get_extra_item_id
  10397. public native_get_extra_item_id(const name[])
  10398. {
  10399. // ZP disabled
  10400. if (!g_pluginenabled)
  10401. return -1;
  10402.  
  10403. // Strings passed byref
  10404. param_convert(1)
  10405.  
  10406. // Loop through every item (not using Tries since ZP should work on AMXX 1.8.0)
  10407. static i, item_name[32]
  10408. for (i = 0; i < g_extraitem_i; i++)
  10409. {
  10410. ArrayGetString(g_extraitem_name, i, item_name, charsmax(item_name))
  10411.  
  10412. // Check if this is the item to retrieve
  10413. if (equali(name, item_name))
  10414. return i;
  10415. }
  10416.  
  10417. return -1;
  10418. }
  10419.  
  10420. // Native: zp_get_zombie_class_id
  10421. public native_get_zombie_class_id(const name[])
  10422. {
  10423. // ZP disabled
  10424. if (!g_pluginenabled)
  10425. return -1;
  10426.  
  10427. // Strings passed byref
  10428. param_convert(1)
  10429.  
  10430. // Loop through every class (not using Tries since ZP should work on AMXX 1.8.0)
  10431. static i, class_name[32]
  10432. for (i = 0; i < g_zclass_i; i++)
  10433. {
  10434. ArrayGetString(g_zclass_name, i, class_name, charsmax(class_name))
  10435.  
  10436. // Check if this is the class to retrieve
  10437. if (equali(name, class_name))
  10438. return i;
  10439. }
  10440.  
  10441. return -1;
  10442. }
  10443.  
  10444. // Native: zp_get_zombie_class_info
  10445. public native_get_zombie_class_info(classid, info[], len)
  10446. {
  10447. // ZP disabled
  10448. if (!g_pluginenabled)
  10449. return false;
  10450.  
  10451. // Invalid class
  10452. if (classid < 0 || classid >= g_zclass_i)
  10453. {
  10454. log_error(AMX_ERR_NATIVE, "[ZP] Invalid zombie class id (%d)", classid)
  10455. return false;
  10456. }
  10457.  
  10458. // Strings passed byref
  10459. param_convert(2)
  10460.  
  10461. // Fetch zombie class info
  10462. ArrayGetString(g_zclass_info, classid, info, len)
  10463. return true;
  10464. }
  10465.  
  10466. /*================================================================================
  10467. [Custom Messages]
  10468. =================================================================================*/
  10469.  
  10470. // Custom Night Vision
  10471. public set_user_nvision(taskid)
  10472. {
  10473. // Get player's origin
  10474. static origin[3]
  10475. get_user_origin(ID_NVISION, origin)
  10476.  
  10477. // Nightvision message
  10478. message_begin(MSG_ONE_UNRELIABLE, SVC_TEMPENTITY, _, ID_NVISION)
  10479. write_byte(TE_DLIGHT) // TE id
  10480. write_coord(origin[0]) // x
  10481. write_coord(origin[1]) // y
  10482. write_coord(origin[2]) // z
  10483. write_byte(get_pcvar_num(cvar_nvgsize)) // radius
  10484.  
  10485. // Nemesis / Madness / Spectator in nemesis round
  10486. if (g_nemesis[ID_NVISION] || (g_zombie[ID_NVISION] && g_nodamage[ID_NVISION]) || (!g_isalive[ID_NVISION] && g_nemround))
  10487. {
  10488. write_byte(get_pcvar_num(cvar_nemnvgcolor[0])) // r
  10489. write_byte(get_pcvar_num(cvar_nemnvgcolor[1])) // g
  10490. write_byte(get_pcvar_num(cvar_nemnvgcolor[2])) // b
  10491. }
  10492. // Human / Spectator in normal round
  10493. else if (!g_zombie[ID_NVISION] || !g_isalive[ID_NVISION])
  10494. {
  10495. write_byte(get_pcvar_num(cvar_humnvgcolor[0])) // r
  10496. write_byte(get_pcvar_num(cvar_humnvgcolor[1])) // g
  10497. write_byte(get_pcvar_num(cvar_humnvgcolor[2])) // b
  10498. }
  10499. // Zombie
  10500. else
  10501. {
  10502. write_byte(get_pcvar_num(cvar_nvgcolor[0])) // r
  10503. write_byte(get_pcvar_num(cvar_nvgcolor[1])) // g
  10504. write_byte(get_pcvar_num(cvar_nvgcolor[2])) // b
  10505. }
  10506.  
  10507. write_byte(2) // life
  10508. write_byte(0) // decay rate
  10509. message_end()
  10510. }
  10511.  
  10512. // Game Nightvision
  10513. set_user_gnvision(id, toggle)
  10514. {
  10515. // Toggle NVG message
  10516. message_begin(MSG_ONE, g_msgNVGToggle, _, id)
  10517. write_byte(toggle) // toggle
  10518. message_end()
  10519. }
  10520.  
  10521. // Custom Flashlight
  10522. public set_user_flashlight(taskid)
  10523. {
  10524. // Get player and aiming origins
  10525. static Float:originF[3], Float:destoriginF[3]
  10526. pev(ID_FLASH, pev_origin, originF)
  10527. fm_get_aim_origin(ID_FLASH, destoriginF)
  10528.  
  10529. // Max distance check
  10530. if (get_distance_f(originF, destoriginF) > get_pcvar_float(cvar_flashdist))
  10531. return;
  10532.  
  10533. // Send to all players?
  10534. if (get_pcvar_num(cvar_flashshowall))
  10535. engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, destoriginF, 0)
  10536. else
  10537. message_begin(MSG_ONE_UNRELIABLE, SVC_TEMPENTITY, _, ID_FLASH)
  10538.  
  10539. // Flashlight
  10540. write_byte(TE_DLIGHT) // TE id
  10541. engfunc(EngFunc_WriteCoord, destoriginF[0]) // x
  10542. engfunc(EngFunc_WriteCoord, destoriginF[1]) // y
  10543. engfunc(EngFunc_WriteCoord, destoriginF[2]) // z
  10544. write_byte(get_pcvar_num(cvar_flashsize)) // radius
  10545. write_byte(get_pcvar_num(cvar_flashcolor[0])) // r
  10546. write_byte(get_pcvar_num(cvar_flashcolor[1])) // g
  10547. write_byte(get_pcvar_num(cvar_flashcolor[2])) // b
  10548. write_byte(3) // life
  10549. write_byte(0) // decay rate
  10550. message_end()
  10551. }
  10552.  
  10553. // Infection special effects
  10554. infection_effects(id)
  10555. {
  10556. // Screen fade? (unless frozen)
  10557. if (!g_frozen[id] && get_pcvar_num(cvar_infectionscreenfade))
  10558. {
  10559. message_begin(MSG_ONE_UNRELIABLE, g_msgScreenFade, _, id)
  10560. write_short(UNIT_SECOND) // duration
  10561. write_short(0) // hold time
  10562. write_short(FFADE_IN) // fade type
  10563. if (g_nemesis[id])
  10564. {
  10565. write_byte(get_pcvar_num(cvar_nemnvgcolor[0])) // r
  10566. write_byte(get_pcvar_num(cvar_nemnvgcolor[1])) // g
  10567. write_byte(get_pcvar_num(cvar_nemnvgcolor[2])) // b
  10568. }
  10569. else
  10570. {
  10571. write_byte(get_pcvar_num(cvar_nvgcolor[0])) // r
  10572. write_byte(get_pcvar_num(cvar_nvgcolor[1])) // g
  10573. write_byte(get_pcvar_num(cvar_nvgcolor[2])) // b
  10574. }
  10575. write_byte (255) // alpha
  10576. message_end()
  10577. }
  10578.  
  10579. // Screen shake?
  10580. if (get_pcvar_num(cvar_infectionscreenshake))
  10581. {
  10582. message_begin(MSG_ONE_UNRELIABLE, g_msgScreenShake, _, id)
  10583. write_short(UNIT_SECOND*4) // amplitude
  10584. write_short(UNIT_SECOND*2) // duration
  10585. write_short(UNIT_SECOND*10) // frequency
  10586. message_end()
  10587. }
  10588.  
  10589. // Infection icon?
  10590. if (get_pcvar_num(cvar_hudicons))
  10591. {
  10592. message_begin(MSG_ONE_UNRELIABLE, g_msgDamage, _, id)
  10593. write_byte(0) // damage save
  10594. write_byte(0) // damage take
  10595. write_long(DMG_NERVEGAS) // damage type - DMG_RADIATION
  10596. write_coord(0) // x
  10597. write_coord(0) // y
  10598. write_coord(0) // z
  10599. message_end()
  10600. }
  10601.  
  10602. // Get player's origin
  10603. static origin[3]
  10604. get_user_origin(id, origin)
  10605.  
  10606. // Tracers?
  10607. if (get_pcvar_num(cvar_infectiontracers))
  10608. {
  10609. message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
  10610. write_byte(TE_IMPLOSION) // TE id
  10611. write_coord(origin[0]) // x
  10612. write_coord(origin[1]) // y
  10613. write_coord(origin[2]) // z
  10614. write_byte(128) // radius
  10615. write_byte(20) // count
  10616. write_byte(3) // duration
  10617. message_end()
  10618. }
  10619.  
  10620. // Particle burst?
  10621. if (get_pcvar_num(cvar_infectionparticles))
  10622. {
  10623. message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
  10624. write_byte(TE_PARTICLEBURST) // TE id
  10625. write_coord(origin[0]) // x
  10626. write_coord(origin[1]) // y
  10627. write_coord(origin[2]) // z
  10628. write_short(50) // radius
  10629. write_byte(70) // color
  10630. write_byte(3) // duration (will be randomized a bit)
  10631. message_end()
  10632. }
  10633.  
  10634. // Light sparkle?
  10635. if (get_pcvar_num(cvar_infectionsparkle))
  10636. {
  10637. message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
  10638. write_byte(TE_DLIGHT) // TE id
  10639. write_coord(origin[0]) // x
  10640. write_coord(origin[1]) // y
  10641. write_coord(origin[2]) // z
  10642. write_byte(20) // radius
  10643. write_byte(get_pcvar_num(cvar_nvgcolor[0])) // r
  10644. write_byte(get_pcvar_num(cvar_nvgcolor[1])) // g
  10645. write_byte(get_pcvar_num(cvar_nvgcolor[2])) // b
  10646. write_byte(2) // life
  10647. write_byte(0) // decay rate
  10648. message_end()
  10649. }
  10650. }
  10651.  
  10652. // Nemesis/madness aura task
  10653. public zombie_aura(taskid)
  10654. {
  10655. // Not nemesis, not in zombie madness
  10656. if (!g_nemesis[ID_AURA] && !g_nodamage[ID_AURA])
  10657. {
  10658. // Task not needed anymore
  10659. remove_task(taskid);
  10660. return;
  10661. }
  10662.  
  10663. // Get player's origin
  10664. static origin[3]
  10665. get_user_origin(ID_AURA, origin)
  10666.  
  10667. // Colored Aura
  10668. message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
  10669. write_byte(TE_DLIGHT) // TE id
  10670. write_coord(origin[0]) // x
  10671. write_coord(origin[1]) // y
  10672. write_coord(origin[2]) // z
  10673. write_byte(20) // radius
  10674. write_byte(get_pcvar_num(cvar_nemnvgcolor[0])) // r
  10675. write_byte(get_pcvar_num(cvar_nemnvgcolor[1])) // g
  10676. write_byte(get_pcvar_num(cvar_nemnvgcolor[2])) // b
  10677. write_byte(2) // life
  10678. write_byte(0) // decay rate
  10679. message_end()
  10680. }
  10681.  
  10682. // Make zombies leave footsteps and bloodstains on the floor
  10683. public make_blood(taskid)
  10684. {
  10685. // Only bleed when moving on ground
  10686. if (!(pev(ID_BLOOD, pev_flags) & FL_ONGROUND) || fm_get_speed(ID_BLOOD) < 80)
  10687. return;
  10688.  
  10689. // Get user origin
  10690. static Float:originF[3]
  10691. pev(ID_BLOOD, pev_origin, originF)
  10692.  
  10693. // If ducking set a little lower
  10694. if (pev(ID_BLOOD, pev_bInDuck))
  10695. originF[2] -= 18.0
  10696. else
  10697. originF[2] -= 36.0
  10698.  
  10699. // Send the decal message
  10700. engfunc(EngFunc_MessageBegin, MSG_PAS, SVC_TEMPENTITY, originF, 0)
  10701. write_byte(TE_WORLDDECAL) // TE id
  10702. engfunc(EngFunc_WriteCoord, originF[0]) // x
  10703. engfunc(EngFunc_WriteCoord, originF[1]) // y
  10704. engfunc(EngFunc_WriteCoord, originF[2]) // z
  10705. write_byte(ArrayGetCell(zombie_decals, random_num(0, ArraySize(zombie_decals) - 1)) + (g_czero * 12)) // random decal number (offsets +12 for CZ)
  10706. message_end()
  10707. }
  10708.  
  10709. // Flare Lighting Effects
  10710. flare_lighting(entity, duration)
  10711. {
  10712. // Get origin and color
  10713. static Float:originF[3], color[3]
  10714. pev(entity, pev_origin, originF)
  10715. pev(entity, PEV_FLARE_COLOR, color)
  10716.  
  10717. // Lighting
  10718. engfunc(EngFunc_MessageBegin, MSG_PAS, SVC_TEMPENTITY, originF, 0)
  10719. write_byte(TE_DLIGHT) // TE id
  10720. engfunc(EngFunc_WriteCoord, originF[0]) // x
  10721. engfunc(EngFunc_WriteCoord, originF[1]) // y
  10722. engfunc(EngFunc_WriteCoord, originF[2]) // z
  10723. write_byte(get_pcvar_num(cvar_flaresize)) // radius
  10724. write_byte(color[0]) // r
  10725. write_byte(color[1]) // g
  10726. write_byte(color[2]) // b
  10727. write_byte(21) //life
  10728. write_byte((duration < 2) ? 3 : 0) //decay rate
  10729. message_end()
  10730.  
  10731. // Sparks
  10732. engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
  10733. write_byte(TE_SPARKS) // TE id
  10734. engfunc(EngFunc_WriteCoord, originF[0]) // x
  10735. engfunc(EngFunc_WriteCoord, originF[1]) // y
  10736. engfunc(EngFunc_WriteCoord, originF[2]) // z
  10737. message_end()
  10738. }
  10739.  
  10740. // Burning Flames
  10741. public burning_flame(taskid)
  10742. {
  10743. // Get player origin and flags
  10744. static origin[3], flags
  10745. get_user_origin(ID_BURN, origin)
  10746. flags = pev(ID_BURN, pev_flags)
  10747.  
  10748. // Madness mode - in water - burning stopped
  10749. if (g_nodamage[ID_BURN] || (flags & FL_INWATER) || g_burning_duration[ID_BURN] < 1)
  10750. {
  10751. // Smoke sprite
  10752. message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
  10753. write_byte(TE_SMOKE) // TE id
  10754. write_coord(origin[0]) // x
  10755. write_coord(origin[1]) // y
  10756. write_coord(origin[2]-50) // z
  10757. write_short(g_smokeSpr) // sprite
  10758. write_byte(random_num(15, 20)) // scale
  10759. write_byte(random_num(10, 20)) // framerate
  10760. message_end()
  10761.  
  10762. // Task not needed anymore
  10763. remove_task(taskid);
  10764. return;
  10765. }
  10766.  
  10767. // Randomly play burning zombie scream sounds (not for nemesis)
  10768. if (!g_nemesis[ID_BURN] && !random_num(0, 20))
  10769. {
  10770. static sound[64]
  10771. ArrayGetString(grenade_fire_player, random_num(0, ArraySize(grenade_fire_player) - 1), sound, charsmax(sound))
  10772. emit_sound(ID_BURN, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
  10773. }
  10774.  
  10775. // Fire slow down, unless nemesis
  10776. if (!g_nemesis[ID_BURN] && (flags & FL_ONGROUND) && get_pcvar_float(cvar_fireslowdown) > 0.0)
  10777. {
  10778. static Float:velocity[3]
  10779. pev(ID_BURN, pev_velocity, velocity)
  10780. xs_vec_mul_scalar(velocity, get_pcvar_float(cvar_fireslowdown), velocity)
  10781. set_pev(ID_BURN, pev_velocity, velocity)
  10782. }
  10783.  
  10784. // Get player's health
  10785. static health
  10786. health = pev(ID_BURN, pev_health)
  10787.  
  10788. // Take damage from the fire
  10789. if (health - floatround(get_pcvar_float(cvar_firedamage), floatround_ceil) > 0)
  10790. fm_set_user_health(ID_BURN, health - floatround(get_pcvar_float(cvar_firedamage), floatround_ceil))
  10791.  
  10792. // Flame sprite
  10793. message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
  10794. write_byte(TE_SPRITE) // TE id
  10795. write_coord(origin[0]+random_num(-5, 5)) // x
  10796. write_coord(origin[1]+random_num(-5, 5)) // y
  10797. write_coord(origin[2]+random_num(-10, 10)) // z
  10798. write_short(g_flameSpr) // sprite
  10799. write_byte(random_num(5, 10)) // scale
  10800. write_byte(200) // brightness
  10801. message_end()
  10802.  
  10803. // Decrease burning duration counter
  10804. g_burning_duration[ID_BURN]--
  10805. }
  10806.  
  10807. // Infection Bomb: Green Blast
  10808. create_blast(const Float:originF[3])
  10809. {
  10810. // Smallest ring
  10811. engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
  10812. write_byte(TE_BEAMCYLINDER) // TE id
  10813. engfunc(EngFunc_WriteCoord, originF[0]) // x
  10814. engfunc(EngFunc_WriteCoord, originF[1]) // y
  10815. engfunc(EngFunc_WriteCoord, originF[2]) // z
  10816. engfunc(EngFunc_WriteCoord, originF[0]) // x axis
  10817. engfunc(EngFunc_WriteCoord, originF[1]) // y axis
  10818. engfunc(EngFunc_WriteCoord, originF[2]+385.0) // z axis
  10819. write_short(g_exploSpr) // sprite
  10820. write_byte(0) // startframe
  10821. write_byte(0) // framerate
  10822. write_byte(4) // life
  10823. write_byte(60) // width
  10824. write_byte(0) // noise
  10825. write_byte(0) // red
  10826. write_byte(200) // green
  10827. write_byte(0) // blue
  10828. write_byte(200) // brightness
  10829. write_byte(0) // speed
  10830. message_end()
  10831.  
  10832. // Medium ring
  10833. engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
  10834. write_byte(TE_BEAMCYLINDER) // TE id
  10835. engfunc(EngFunc_WriteCoord, originF[0]) // x
  10836. engfunc(EngFunc_WriteCoord, originF[1]) // y
  10837. engfunc(EngFunc_WriteCoord, originF[2]) // z
  10838. engfunc(EngFunc_WriteCoord, originF[0]) // x axis
  10839. engfunc(EngFunc_WriteCoord, originF[1]) // y axis
  10840. engfunc(EngFunc_WriteCoord, originF[2]+470.0) // z axis
  10841. write_short(g_exploSpr) // sprite
  10842. write_byte(0) // startframe
  10843. write_byte(0) // framerate
  10844. write_byte(4) // life
  10845. write_byte(60) // width
  10846. write_byte(0) // noise
  10847. write_byte(0) // red
  10848. write_byte(200) // green
  10849. write_byte(0) // blue
  10850. write_byte(200) // brightness
  10851. write_byte(0) // speed
  10852. message_end()
  10853.  
  10854. // Largest ring
  10855. engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
  10856. write_byte(TE_BEAMCYLINDER) // TE id
  10857. engfunc(EngFunc_WriteCoord, originF[0]) // x
  10858. engfunc(EngFunc_WriteCoord, originF[1]) // y
  10859. engfunc(EngFunc_WriteCoord, originF[2]) // z
  10860. engfunc(EngFunc_WriteCoord, originF[0]) // x axis
  10861. engfunc(EngFunc_WriteCoord, originF[1]) // y axis
  10862. engfunc(EngFunc_WriteCoord, originF[2]+555.0) // z axis
  10863. write_short(g_exploSpr) // sprite
  10864. write_byte(0) // startframe
  10865. write_byte(0) // framerate
  10866. write_byte(4) // life
  10867. write_byte(60) // width
  10868. write_byte(0) // noise
  10869. write_byte(0) // red
  10870. write_byte(200) // green
  10871. write_byte(0) // blue
  10872. write_byte(200) // brightness
  10873. write_byte(0) // speed
  10874. message_end()
  10875. }
  10876.  
  10877. // Fire Grenade: Fire Blast
  10878. create_blast2(const Float:originF[3])
  10879. {
  10880. // Smallest ring
  10881. engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
  10882. write_byte(TE_BEAMCYLINDER) // TE id
  10883. engfunc(EngFunc_WriteCoord, originF[0]) // x
  10884. engfunc(EngFunc_WriteCoord, originF[1]) // y
  10885. engfunc(EngFunc_WriteCoord, originF[2]) // z
  10886. engfunc(EngFunc_WriteCoord, originF[0]) // x axis
  10887. engfunc(EngFunc_WriteCoord, originF[1]) // y axis
  10888. engfunc(EngFunc_WriteCoord, originF[2]+385.0) // z axis
  10889. write_short(g_exploSpr) // sprite
  10890. write_byte(0) // startframe
  10891. write_byte(0) // framerate
  10892. write_byte(4) // life
  10893. write_byte(60) // width
  10894. write_byte(0) // noise
  10895. write_byte(200) // red
  10896. write_byte(100) // green
  10897. write_byte(0) // blue
  10898. write_byte(200) // brightness
  10899. write_byte(0) // speed
  10900. message_end()
  10901.  
  10902. // Medium ring
  10903. engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
  10904. write_byte(TE_BEAMCYLINDER) // TE id
  10905. engfunc(EngFunc_WriteCoord, originF[0]) // x
  10906. engfunc(EngFunc_WriteCoord, originF[1]) // y
  10907. engfunc(EngFunc_WriteCoord, originF[2]) // z
  10908. engfunc(EngFunc_WriteCoord, originF[0]) // x axis
  10909. engfunc(EngFunc_WriteCoord, originF[1]) // y axis
  10910. engfunc(EngFunc_WriteCoord, originF[2]+470.0) // z axis
  10911. write_short(g_exploSpr) // sprite
  10912. write_byte(0) // startframe
  10913. write_byte(0) // framerate
  10914. write_byte(4) // life
  10915. write_byte(60) // width
  10916. write_byte(0) // noise
  10917. write_byte(200) // red
  10918. write_byte(50) // green
  10919. write_byte(0) // blue
  10920. write_byte(200) // brightness
  10921. write_byte(0) // speed
  10922. message_end()
  10923.  
  10924. // Largest ring
  10925. engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
  10926. write_byte(TE_BEAMCYLINDER) // TE id
  10927. engfunc(EngFunc_WriteCoord, originF[0]) // x
  10928. engfunc(EngFunc_WriteCoord, originF[1]) // y
  10929. engfunc(EngFunc_WriteCoord, originF[2]) // z
  10930. engfunc(EngFunc_WriteCoord, originF[0]) // x axis
  10931. engfunc(EngFunc_WriteCoord, originF[1]) // y axis
  10932. engfunc(EngFunc_WriteCoord, originF[2]+555.0) // z axis
  10933. write_short(g_exploSpr) // sprite
  10934. write_byte(0) // startframe
  10935. write_byte(0) // framerate
  10936. write_byte(4) // life
  10937. write_byte(60) // width
  10938. write_byte(0) // noise
  10939. write_byte(200) // red
  10940. write_byte(0) // green
  10941. write_byte(0) // blue
  10942. write_byte(200) // brightness
  10943. write_byte(0) // speed
  10944. message_end()
  10945. }
  10946.  
  10947. // Frost Grenade: Freeze Blast
  10948. create_blast3(const Float:originF[3])
  10949. {
  10950. // Smallest ring
  10951. engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
  10952. write_byte(TE_BEAMCYLINDER) // TE id
  10953. engfunc(EngFunc_WriteCoord, originF[0]) // x
  10954. engfunc(EngFunc_WriteCoord, originF[1]) // y
  10955. engfunc(EngFunc_WriteCoord, originF[2]) // z
  10956. engfunc(EngFunc_WriteCoord, originF[0]) // x axis
  10957. engfunc(EngFunc_WriteCoord, originF[1]) // y axis
  10958. engfunc(EngFunc_WriteCoord, originF[2]+385.0) // z axis
  10959. write_short(g_exploSpr) // sprite
  10960. write_byte(0) // startframe
  10961. write_byte(0) // framerate
  10962. write_byte(4) // life
  10963. write_byte(60) // width
  10964. write_byte(0) // noise
  10965. write_byte(0) // red
  10966. write_byte(100) // green
  10967. write_byte(200) // blue
  10968. write_byte(200) // brightness
  10969. write_byte(0) // speed
  10970. message_end()
  10971.  
  10972. // Medium ring
  10973. engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
  10974. write_byte(TE_BEAMCYLINDER) // TE id
  10975. engfunc(EngFunc_WriteCoord, originF[0]) // x
  10976. engfunc(EngFunc_WriteCoord, originF[1]) // y
  10977. engfunc(EngFunc_WriteCoord, originF[2]) // z
  10978. engfunc(EngFunc_WriteCoord, originF[0]) // x axis
  10979. engfunc(EngFunc_WriteCoord, originF[1]) // y axis
  10980. engfunc(EngFunc_WriteCoord, originF[2]+470.0) // z axis
  10981. write_short(g_exploSpr) // sprite
  10982. write_byte(0) // startframe
  10983. write_byte(0) // framerate
  10984. write_byte(4) // life
  10985. write_byte(60) // width
  10986. write_byte(0) // noise
  10987. write_byte(0) // red
  10988. write_byte(100) // green
  10989. write_byte(200) // blue
  10990. write_byte(200) // brightness
  10991. write_byte(0) // speed
  10992. message_end()
  10993.  
  10994. // Largest ring
  10995. engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
  10996. write_byte(TE_BEAMCYLINDER) // TE id
  10997. engfunc(EngFunc_WriteCoord, originF[0]) // x
  10998. engfunc(EngFunc_WriteCoord, originF[1]) // y
  10999. engfunc(EngFunc_WriteCoord, originF[2]) // z
  11000. engfunc(EngFunc_WriteCoord, originF[0]) // x axis
  11001. engfunc(EngFunc_WriteCoord, originF[1]) // y axis
  11002. engfunc(EngFunc_WriteCoord, originF[2]+555.0) // z axis
  11003. write_short(g_exploSpr) // sprite
  11004. write_byte(0) // startframe
  11005. write_byte(0) // framerate
  11006. write_byte(4) // life
  11007. write_byte(60) // width
  11008. write_byte(0) // noise
  11009. write_byte(0) // red
  11010. write_byte(100) // green
  11011. write_byte(200) // blue
  11012. write_byte(200) // brightness
  11013. write_byte(0) // speed
  11014. message_end()
  11015. }
  11016.  
  11017. // Fix Dead Attrib on scoreboard
  11018. FixDeadAttrib(id)
  11019. {
  11020. message_begin(MSG_BROADCAST, g_msgScoreAttrib)
  11021. write_byte(id) // id
  11022. write_byte(0) // attrib
  11023. message_end()
  11024. }
  11025.  
  11026. // Send Death Message for infections
  11027. SendDeathMsg(attacker, victim)
  11028. {
  11029. message_begin(MSG_BROADCAST, g_msgDeathMsg)
  11030. write_byte(attacker) // killer
  11031. write_byte(victim) // victim
  11032. write_byte(1) // headshot flag
  11033. write_string("infection") // killer's weapon
  11034. message_end()
  11035. }
  11036.  
  11037. // Update Player Frags and Deaths
  11038. UpdateFrags(attacker, victim, frags, deaths, scoreboard)
  11039. {
  11040. // Set attacker frags
  11041. set_pev(attacker, pev_frags, float(pev(attacker, pev_frags) + frags))
  11042.  
  11043. // Set victim deaths
  11044. fm_cs_set_user_deaths(victim, cs_get_user_deaths(victim) + deaths)
  11045.  
  11046. // Update scoreboard with attacker and victim info
  11047. if (scoreboard)
  11048. {
  11049. message_begin(MSG_BROADCAST, g_msgScoreInfo)
  11050. write_byte(attacker) // id
  11051. write_short(pev(attacker, pev_frags)) // frags
  11052. write_short(cs_get_user_deaths(attacker)) // deaths
  11053. write_short(0) // class?
  11054. write_short(fm_cs_get_user_team(attacker)) // team
  11055. message_end()
  11056.  
  11057. message_begin(MSG_BROADCAST, g_msgScoreInfo)
  11058. write_byte(victim) // id
  11059. write_short(pev(victim, pev_frags)) // frags
  11060. write_short(cs_get_user_deaths(victim)) // deaths
  11061. write_short(0) // class?
  11062. write_short(fm_cs_get_user_team(victim)) // team
  11063. message_end()
  11064. }
  11065. }
  11066.  
  11067. // Remove Player Frags (when Nemesis/Survivor ignore_frags cvar is enabled)
  11068. RemoveFrags(attacker, victim)
  11069. {
  11070. // Remove attacker frags
  11071. set_pev(attacker, pev_frags, float(pev(attacker, pev_frags) - 1))
  11072.  
  11073. // Remove victim deaths
  11074. fm_cs_set_user_deaths(victim, cs_get_user_deaths(victim) - 1)
  11075. }
  11076.  
  11077. // Plays a sound on clients
  11078. PlaySound(const sound[])
  11079. {
  11080. if (equal(sound[strlen(sound)-4], ".mp3"))
  11081. client_cmd(0, "mp3 play ^"sound/%s^"", sound)
  11082. else
  11083. client_cmd(0, "spk ^"%s^"", sound)
  11084. }
  11085.  
  11086. // Prints a colored message to target (use 0 for everyone), supports ML formatting.
  11087. // Note: I still need to make something like gungame's LANG_PLAYER_C to avoid unintended
  11088. // argument replacement when a function passes -1 (it will be considered a LANG_PLAYER)
  11089. zp_colored_print(target, const message[], any:...)
  11090. {
  11091. static buffer[512], i, argscount
  11092. argscount = numargs()
  11093.  
  11094. // Send to everyone
  11095. if (!target)
  11096. {
  11097. static player
  11098. for (player = 1; player <= g_maxplayers; player++)
  11099. {
  11100. // Not connected
  11101. if (!g_isconnected[player])
  11102. continue;
  11103.  
  11104. // Remember changed arguments
  11105. static changed[5], changedcount // [5] = max LANG_PLAYER occurencies
  11106. changedcount = 0
  11107.  
  11108. // Replace LANG_PLAYER with player id
  11109. for (i = 2; i < argscount; i++)
  11110. {
  11111. if (getarg(i) == LANG_PLAYER)
  11112. {
  11113. setarg(i, 0, player)
  11114. changed[changedcount] = i
  11115. changedcount++
  11116. }
  11117. }
  11118.  
  11119. // Format message for player
  11120. vformat(buffer, charsmax(buffer), message, 3)
  11121.  
  11122. // Send it
  11123. message_begin(MSG_ONE_UNRELIABLE, g_msgSayText, _, player)
  11124. write_byte(player)
  11125. write_string(buffer)
  11126. message_end()
  11127.  
  11128. // Replace back player id's with LANG_PLAYER
  11129. for (i = 0; i < changedcount; i++)
  11130. setarg(changed[i], 0, LANG_PLAYER)
  11131. }
  11132. }
  11133. // Send to specific target
  11134. else
  11135. {
  11136. /*
  11137. // Not needed since you should set the ML argument
  11138. // to the player's id for a targeted print message
  11139.  
  11140. // Replace LANG_PLAYER with player id
  11141. for (i = 2; i < argscount; i++)
  11142. {
  11143. if (getarg(i) == LANG_PLAYER)
  11144. setarg(i, 0, target)
  11145. }
  11146. */
  11147.  
  11148. // Format message for player
  11149. vformat(buffer, charsmax(buffer), message, 3)
  11150.  
  11151. // Send it
  11152. message_begin(MSG_ONE, g_msgSayText, _, target)
  11153. write_byte(target)
  11154. write_string(buffer)
  11155. message_end()
  11156. }
  11157. }
  11158.  
  11159. /*================================================================================
  11160. [Stocks]
  11161. =================================================================================*/
  11162.  
  11163. // Set an entity's key value (from fakemeta_util)
  11164. stock fm_set_kvd(entity, const key[], const value[], const classname[])
  11165. {
  11166. set_kvd(0, KV_ClassName, classname)
  11167. set_kvd(0, KV_KeyName, key)
  11168. set_kvd(0, KV_Value, value)
  11169. set_kvd(0, KV_fHandled, 0)
  11170.  
  11171. dllfunc(DLLFunc_KeyValue, entity, 0)
  11172. }
  11173.  
  11174. // Set entity's rendering type (from fakemeta_util)
  11175. stock fm_set_rendering(entity, fx = kRenderFxNone, r = 255, g = 255, b = 255, render = kRenderNormal, amount = 16)
  11176. {
  11177. static Float:color[3]
  11178. color[0] = float(r)
  11179. color[1] = float(g)
  11180. color[2] = float(b)
  11181.  
  11182. set_pev(entity, pev_renderfx, fx)
  11183. set_pev(entity, pev_rendercolor, color)
  11184. set_pev(entity, pev_rendermode, render)
  11185. set_pev(entity, pev_renderamt, float(amount))
  11186. }
  11187.  
  11188. // Get entity's speed (from fakemeta_util)
  11189. stock fm_get_speed(entity)
  11190. {
  11191. static Float:velocity[3]
  11192. pev(entity, pev_velocity, velocity)
  11193.  
  11194. return floatround(vector_length(velocity));
  11195. }
  11196.  
  11197. // Get entity's aim origins (from fakemeta_util)
  11198. stock fm_get_aim_origin(id, Float:origin[3])
  11199. {
  11200. static Float:origin1F[3], Float:origin2F[3]
  11201. pev(id, pev_origin, origin1F)
  11202. pev(id, pev_view_ofs, origin2F)
  11203. xs_vec_add(origin1F, origin2F, origin1F)
  11204.  
  11205. pev(id, pev_v_angle, origin2F);
  11206. engfunc(EngFunc_MakeVectors, origin2F)
  11207. global_get(glb_v_forward, origin2F)
  11208. xs_vec_mul_scalar(origin2F, 9999.0, origin2F)
  11209. xs_vec_add(origin1F, origin2F, origin2F)
  11210.  
  11211. engfunc(EngFunc_TraceLine, origin1F, origin2F, 0, id, 0)
  11212. get_tr2(0, TR_vecEndPos, origin)
  11213. }
  11214.  
  11215. // Find entity by its owner (from fakemeta_util)
  11216. stock fm_find_ent_by_owner(entity, const classname[], owner)
  11217. {
  11218. while ((entity = engfunc(EngFunc_FindEntityByString, entity, "classname", classname)) && pev(entity, pev_owner) != owner) { /* keep looping */ }
  11219. return entity;
  11220. }
  11221.  
  11222. // Set player's health (from fakemeta_util)
  11223. stock fm_set_user_health(id, health)
  11224. {
  11225. (health > 0) ? set_pev(id, pev_health, float(health)) : dllfunc(DLLFunc_ClientKill, id);
  11226. }
  11227.  
  11228. // Give an item to a player (from fakemeta_util)
  11229. stock fm_give_item(id, const item[])
  11230. {
  11231. static ent
  11232. ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, item))
  11233. if (!pev_valid(ent)) return;
  11234.  
  11235. static Float:originF[3]
  11236. pev(id, pev_origin, originF)
  11237. set_pev(ent, pev_origin, originF)
  11238. set_pev(ent, pev_spawnflags, pev(ent, pev_spawnflags) | SF_NORESPAWN)
  11239. dllfunc(DLLFunc_Spawn, ent)
  11240.  
  11241. static save
  11242. save = pev(ent, pev_solid)
  11243. dllfunc(DLLFunc_Touch, ent, id)
  11244. if (pev(ent, pev_solid) != save)
  11245. return;
  11246.  
  11247. engfunc(EngFunc_RemoveEntity, ent)
  11248. }
  11249.  
  11250. // Strip user weapons (from fakemeta_util)
  11251. stock fm_strip_user_weapons(id)
  11252. {
  11253. static ent
  11254. ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "player_weaponstrip"))
  11255. if (!pev_valid(ent)) return;
  11256.  
  11257. dllfunc(DLLFunc_Spawn, ent)
  11258. dllfunc(DLLFunc_Use, ent, id)
  11259. engfunc(EngFunc_RemoveEntity, ent)
  11260. }
  11261.  
  11262. // Collect random spawn points
  11263. stock load_spawns()
  11264. {
  11265. // Check for CSDM spawns of the current map
  11266. new cfgdir[32], mapname[32], filepath[100], linedata[64]
  11267. get_configsdir(cfgdir, charsmax(cfgdir))
  11268. get_mapname(mapname, charsmax(mapname))
  11269. formatex(filepath, charsmax(filepath), "%s/csdm/%s.spawns.cfg", cfgdir, mapname)
  11270.  
  11271. // Load CSDM spawns if present
  11272. if (file_exists(filepath))
  11273. {
  11274. new csdmdata[10][6], file = fopen(filepath,"rt")
  11275.  
  11276. while (file && !feof(file))
  11277. {
  11278. fgets(file, linedata, charsmax(linedata))
  11279.  
  11280. // invalid spawn
  11281. if(!linedata[0] || str_count(linedata,' ') < 2) continue;
  11282.  
  11283. // get spawn point data
  11284. parse(linedata,csdmdata[0],5,csdmdata[1],5,csdmdata[2],5,csdmdata[3],5,csdmdata[4],5,csdmdata[5],5,csdmdata[6],5,csdmdata[7],5,csdmdata[8],5,csdmdata[9],5)
  11285.  
  11286. // origin
  11287. g_spawns[g_spawnCount][0] = floatstr(csdmdata[0])
  11288. g_spawns[g_spawnCount][1] = floatstr(csdmdata[1])
  11289. g_spawns[g_spawnCount][2] = floatstr(csdmdata[2])
  11290.  
  11291. // increase spawn count
  11292. g_spawnCount++
  11293. if (g_spawnCount >= sizeof g_spawns) break;
  11294. }
  11295. if (file) fclose(file)
  11296. }
  11297. else
  11298. {
  11299. // Collect regular spawns
  11300. collect_spawns_ent("info_player_start")
  11301. collect_spawns_ent("info_player_deathmatch")
  11302. }
  11303.  
  11304. // Collect regular spawns for non-random spawning unstuck
  11305. collect_spawns_ent2("info_player_start")
  11306. collect_spawns_ent2("info_player_deathmatch")
  11307. }
  11308.  
  11309. // Collect spawn points from entity origins
  11310. stock collect_spawns_ent(const classname[])
  11311. {
  11312. new ent = -1
  11313. while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", classname)) != 0)
  11314. {
  11315. // get origin
  11316. new Float:originF[3]
  11317. pev(ent, pev_origin, originF)
  11318. g_spawns[g_spawnCount][0] = originF[0]
  11319. g_spawns[g_spawnCount][1] = originF[1]
  11320. g_spawns[g_spawnCount][2] = originF[2]
  11321.  
  11322. // increase spawn count
  11323. g_spawnCount++
  11324. if (g_spawnCount >= sizeof g_spawns) break;
  11325. }
  11326. }
  11327.  
  11328. // Collect spawn points from entity origins
  11329. stock collect_spawns_ent2(const classname[])
  11330. {
  11331. new ent = -1
  11332. while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", classname)) != 0)
  11333. {
  11334. // get origin
  11335. new Float:originF[3]
  11336. pev(ent, pev_origin, originF)
  11337. g_spawns2[g_spawnCount2][0] = originF[0]
  11338. g_spawns2[g_spawnCount2][1] = originF[1]
  11339. g_spawns2[g_spawnCount2][2] = originF[2]
  11340.  
  11341. // increase spawn count
  11342. g_spawnCount2++
  11343. if (g_spawnCount2 >= sizeof g_spawns2) break;
  11344. }
  11345. }
  11346.  
  11347. // Drop primary/secondary weapons
  11348. stock drop_weapons(id, dropwhat)
  11349. {
  11350. // Get user weapons
  11351. static weapons[32], num, i, weaponid
  11352. num = 0 // reset passed weapons count (bugfix)
  11353. get_user_weapons(id, weapons, num)
  11354.  
  11355. // Loop through them and drop primaries or secondaries
  11356. for (i = 0; i < num; i++)
  11357. {
  11358. // Prevent re-indexing the array
  11359. weaponid = weapons[i]
  11360.  
  11361. if ((dropwhat == 1 && ((1<<weaponid) & PRIMARY_WEAPONS_BIT_SUM)) || (dropwhat == 2 && ((1<<weaponid) & SECONDARY_WEAPONS_BIT_SUM)))
  11362. {
  11363. // Get weapon entity
  11364. static wname[32], weapon_ent
  11365. get_weaponname(weaponid, wname, charsmax(wname))
  11366. weapon_ent = fm_find_ent_by_owner(-1, wname, id)
  11367.  
  11368. // Hack: store weapon bpammo on PEV_ADDITIONAL_AMMO
  11369. set_pev(weapon_ent, PEV_ADDITIONAL_AMMO, cs_get_user_bpammo(id, weaponid))
  11370.  
  11371. // Player drops the weapon and looses his bpammo
  11372. engclient_cmd(id, "drop", wname)
  11373. cs_set_user_bpammo(id, weaponid, 0)
  11374. }
  11375. }
  11376. }
  11377.  
  11378. // Stock by (probably) Twilight Suzuka -counts number of chars in a string
  11379. stock str_count(const str[], searchchar)
  11380. {
  11381. new count, i, len = strlen(str)
  11382.  
  11383. for (i = 0; i <= len; i++)
  11384. {
  11385. if(str[i] == searchchar)
  11386. count++
  11387. }
  11388.  
  11389. return count;
  11390. }
  11391.  
  11392. // Checks if a space is vacant (credits to VEN)
  11393. stock is_hull_vacant(Float:origin[3], hull)
  11394. {
  11395. engfunc(EngFunc_TraceHull, origin, origin, 0, hull, 0, 0)
  11396.  
  11397. if (!get_tr2(0, TR_StartSolid) && !get_tr2(0, TR_AllSolid) && get_tr2(0, TR_InOpen))
  11398. return true;
  11399.  
  11400. return false;
  11401. }
  11402.  
  11403. // Check if a player is stuck (credits to VEN)
  11404. stock is_player_stuck(id)
  11405. {
  11406. static Float:originF[3]
  11407. pev(id, pev_origin, originF)
  11408.  
  11409. engfunc(EngFunc_TraceHull, originF, originF, 0, (pev(id, pev_flags) & FL_DUCKING) ? HULL_HEAD : HULL_HUMAN, id, 0)
  11410.  
  11411. if (get_tr2(0, TR_StartSolid) || get_tr2(0, TR_AllSolid) || !get_tr2(0, TR_InOpen))
  11412. return true;
  11413.  
  11414. return false;
  11415. }
  11416.  
  11417. // Simplified get_weaponid (CS only)
  11418. stock cs_weapon_name_to_id(const weapon[])
  11419. {
  11420. static i
  11421. for (i = 0; i < sizeof WEAPONENTNAMES; i++)
  11422. {
  11423. if (equal(weapon, WEAPONENTNAMES[i]))
  11424. return i;
  11425. }
  11426.  
  11427. return 0;
  11428. }
  11429.  
  11430. // Get User Current Weapon Entity
  11431. stock fm_cs_get_current_weapon_ent(id)
  11432. {
  11433. // Prevent server crash if entity's private data not initalized
  11434. if (pev_valid(id) != PDATA_SAFE)
  11435. return -1;
  11436.  
  11437. return get_pdata_cbase(id, OFFSET_ACTIVE_ITEM, OFFSET_LINUX);
  11438. }
  11439.  
  11440. // Get Weapon Entity's Owner
  11441. stock fm_cs_get_weapon_ent_owner(ent)
  11442. {
  11443. // Prevent server crash if entity's private data not initalized
  11444. if (pev_valid(ent) != PDATA_SAFE)
  11445. return -1;
  11446.  
  11447. return get_pdata_cbase(ent, OFFSET_WEAPONOWNER, OFFSET_LINUX_WEAPONS);
  11448. }
  11449.  
  11450. // Set User Deaths
  11451. stock fm_cs_set_user_deaths(id, value)
  11452. {
  11453. // Prevent server crash if entity's private data not initalized
  11454. if (pev_valid(id) != PDATA_SAFE)
  11455. return;
  11456.  
  11457. set_pdata_int(id, OFFSET_CSDEATHS, value, OFFSET_LINUX)
  11458. }
  11459.  
  11460. // Get User Team
  11461. stock fm_cs_get_user_team(id)
  11462. {
  11463. // Prevent server crash if entity's private data not initalized
  11464. if (pev_valid(id) != PDATA_SAFE)
  11465. return FM_CS_TEAM_UNASSIGNED;
  11466.  
  11467. return get_pdata_int(id, OFFSET_CSTEAMS, OFFSET_LINUX);
  11468. }
  11469.  
  11470. // Set a Player's Team
  11471. stock fm_cs_set_user_team(id, team)
  11472. {
  11473. // Prevent server crash if entity's private data not initalized
  11474. if (pev_valid(id) != PDATA_SAFE)
  11475. return;
  11476.  
  11477. set_pdata_int(id, OFFSET_CSTEAMS, team, OFFSET_LINUX)
  11478. }
  11479.  
  11480. // Set User Money
  11481. stock fm_cs_set_user_money(id, value)
  11482. {
  11483. // Prevent server crash if entity's private data not initalized
  11484. if (pev_valid(id) != PDATA_SAFE)
  11485. return;
  11486.  
  11487. set_pdata_int(id, OFFSET_CSMONEY, value, OFFSET_LINUX)
  11488. }
  11489.  
  11490. // Set User Flashlight Batteries
  11491. stock fm_cs_set_user_batteries(id, value)
  11492. {
  11493. // Prevent server crash if entity's private data not initalized
  11494. if (pev_valid(id) != PDATA_SAFE)
  11495. return;
  11496.  
  11497. set_pdata_int(id, OFFSET_FLASHLIGHT_BATTERY, value, OFFSET_LINUX)
  11498. }
  11499.  
  11500. // Update Player's Team on all clients (adding needed delays)
  11501. stock fm_user_team_update(id)
  11502. {
  11503. static Float:current_time
  11504. current_time = get_gametime()
  11505.  
  11506. if (current_time - g_teams_targettime >= 0.1)
  11507. {
  11508. set_task(0.1, "fm_cs_set_user_team_msg", id+TASK_TEAM)
  11509. g_teams_targettime = current_time + 0.1
  11510. }
  11511. else
  11512. {
  11513. set_task((g_teams_targettime + 0.1) - current_time, "fm_cs_set_user_team_msg", id+TASK_TEAM)
  11514. g_teams_targettime = g_teams_targettime + 0.1
  11515. }
  11516. }
  11517.  
  11518. // Send User Team Message
  11519. public fm_cs_set_user_team_msg(taskid)
  11520. {
  11521. // Note to self: this next message can now be received by other plugins
  11522.  
  11523. // Set the switching team flag
  11524. g_switchingteam = true
  11525.  
  11526. // Tell everyone my new team
  11527. emessage_begin(MSG_ALL, g_msgTeamInfo)
  11528. ewrite_byte(ID_TEAM) // player
  11529. ewrite_string(CS_TEAM_NAMES[fm_cs_get_user_team(ID_TEAM)]) // team
  11530. emessage_end()
  11531.  
  11532. // Done switching team
  11533. g_switchingteam = false
  11534. }
  11535.  
  11536. // Set the precached model index (updates hitboxes server side)
  11537. stock fm_cs_set_user_model_index(id, value)
  11538. {
  11539. // Prevent server crash if entity's private data not initalized
  11540. if (pev_valid(id) != PDATA_SAFE)
  11541. return;
  11542.  
  11543. set_pdata_int(id, OFFSET_MODELINDEX, value, OFFSET_LINUX)
  11544. }
  11545.  
  11546. // Set Player Model on Entity
  11547. stock fm_set_playermodel_ent(id)
  11548. {
  11549. // Make original player entity invisible without hiding shadows or firing effects
  11550. fm_set_rendering(id, kRenderFxNone, 255, 255, 255, kRenderTransTexture, 1)
  11551.  
  11552. // Format model string
  11553. static model[100]
  11554. formatex(model, charsmax(model), "models/player/%s/%s.mdl", g_playermodel[id], g_playermodel[id])
  11555.  
  11556. // Set model on entity or make a new one if unexistant
  11557. if (!pev_valid(g_ent_playermodel[id]))
  11558. {
  11559. g_ent_playermodel[id] = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "info_target"))
  11560. if (!pev_valid(g_ent_playermodel[id])) return;
  11561.  
  11562. set_pev(g_ent_playermodel[id], pev_classname, MODEL_ENT_CLASSNAME)
  11563. set_pev(g_ent_playermodel[id], pev_movetype, MOVETYPE_FOLLOW)
  11564. set_pev(g_ent_playermodel[id], pev_aiment, id)
  11565. set_pev(g_ent_playermodel[id], pev_owner, id)
  11566. }
  11567.  
  11568. engfunc(EngFunc_SetModel, g_ent_playermodel[id], model)
  11569. }
  11570.  
  11571. // Set Weapon Model on Entity
  11572. stock fm_set_weaponmodel_ent(id)
  11573. {
  11574. // Get player's p_ weapon model
  11575. static model[100]
  11576. pev(id, pev_weaponmodel2, model, charsmax(model))
  11577.  
  11578. // Set model on entity or make a new one if unexistant
  11579. if (!pev_valid(g_ent_weaponmodel[id]))
  11580. {
  11581. g_ent_weaponmodel[id] = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "info_target"))
  11582. if (!pev_valid(g_ent_weaponmodel[id])) return;
  11583.  
  11584. set_pev(g_ent_weaponmodel[id], pev_classname, WEAPON_ENT_CLASSNAME)
  11585. set_pev(g_ent_weaponmodel[id], pev_movetype, MOVETYPE_FOLLOW)
  11586. set_pev(g_ent_weaponmodel[id], pev_aiment, id)
  11587. set_pev(g_ent_weaponmodel[id], pev_owner, id)
  11588. }
  11589.  
  11590. engfunc(EngFunc_SetModel, g_ent_weaponmodel[id], model)
  11591. }
  11592.  
  11593. // Remove Custom Model Entities
  11594. stock fm_remove_model_ents(id)
  11595. {
  11596. // Remove "playermodel" ent if present
  11597. if (pev_valid(g_ent_playermodel[id]))
  11598. {
  11599. engfunc(EngFunc_RemoveEntity, g_ent_playermodel[id])
  11600. g_ent_playermodel[id] = 0
  11601. }
  11602. // Remove "weaponmodel" ent if present
  11603. if (pev_valid(g_ent_weaponmodel[id]))
  11604. {
  11605. engfunc(EngFunc_RemoveEntity, g_ent_weaponmodel[id])
  11606. g_ent_weaponmodel[id] = 0
  11607. }
  11608. }
  11609.  
  11610. // Set User Model
  11611. public fm_cs_set_user_model(taskid)
  11612. {
  11613. set_user_info(ID_MODEL, "model", g_playermodel[ID_MODEL])
  11614. }
  11615.  
  11616. // Get User Model -model passed byref-
  11617. stock fm_cs_get_user_model(player, model[], len)
  11618. {
  11619. get_user_info(player, "model", model, len)
  11620. }
  11621.  
  11622. // Update Player's Model on all clients (adding needed delays)
  11623. public fm_user_model_update(taskid)
  11624. {
  11625. static Float:current_time
  11626. current_time = get_gametime()
  11627.  
  11628. if (current_time - g_models_targettime >= g_modelchange_delay)
  11629. {
  11630. fm_cs_set_user_model(taskid)
  11631. g_models_targettime = current_time
  11632. }
  11633. else
  11634. {
  11635. set_task((g_models_targettime + g_modelchange_delay) - current_time, "fm_cs_set_user_model", taskid)
  11636. g_models_targettime = g_models_targettime + g_modelchange_delay
  11637. }
  11638. }
Add Comment
Please, Sign In to add comment