· 6 years ago · Mar 28, 2020, 08:46 PM
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 ** v4.3.Fix6a [Dec 2015]
370
371 - Added Armor information.
372 - Added Aim info with cvar , // got code from zpa
373 - Added 5 new Modes ,Sniper, Assassin, armageddon , sniper Vs Assassin and NightMare Mode.
374 - Changed HUD_SPECT_X , got code from zpa and changed spcetating color and size.
375 - Added P model for sniper Model
376 - Fixed Glow Size , that appear white glow without enable cvar_glow for nemesis, survivor, sniper. assassin. (bug fixed)
377 - Fixed nemesis Glow
378 - Removed cvar_survweapon. and added AK-47 & XM1014 weapon for survivor. if you want to change, search it "// Update model on weaponmodel ent".
379 - Fixed player can walk when zombie is freeze (bug fixed)
380 - new CVAR zp_dmg_while_frost, if enable, zombie will not get dmg while frost
381 - Fixed SetHamParamInteger (fw_PlayerKilled runtime error)
382 - Added 2 new natives from zpa . zp_get_user_model & zp_set_user_model
383 - Removed Unlimited Clip. Survivor is now given 32767 clips
384 - Added zp_zombie_painfree <3> setting (only affect first zombie)
385 - Added zp_human_kill_reward setting (rewards ammopacks for killing zombie)
386
387=================================================================================*/
388
389/*================================================================================
390 [Plugin Customization]
391=================================================================================*/
392
393// All customization settings have been moved
394// to external files to allow easier editing
395new const ZP_CUSTOMIZATION_FILE[] = "zombieplague.ini"
396new const ZP_EXTRAITEMS_FILE[] = "zp_extraitems.ini"
397new const ZP_ZOMBIECLASSES_FILE[] = "zp_zombieclasses.ini"
398
399// Limiters for stuff not worth making dynamic arrays out of (increase if needed)
400const MAX_CSDM_SPAWNS = 128
401const MAX_STATS_SAVED = 64
402
403/*================================================================================
404 Customization ends here! Yes, that's it. Editing anything beyond
405 here is not officially supported. Proceed at your own risk...
406=================================================================================*/
407
408#include <amxmodx>
409#include <amxmisc>
410#include <cstrike>
411#include <fakemeta>
412#include <hamsandwich>
413#include <xs>
414
415/*================================================================================
416 [Constants, Offsets, Macros]
417=================================================================================*/
418
419// Plugin Version
420new const PLUGIN_VERSION[] = "4.3 Fix6a"
421
422// Customization file sections
423enum
424{
425 SECTION_NONE = 0,
426 SECTION_ACCESS_FLAGS,
427 SECTION_PLAYER_MODELS,
428 SECTION_WEAPON_MODELS,
429 SECTION_GRENADE_SPRITES,
430 SECTION_SOUNDS,
431 SECTION_AMBIENCE_SOUNDS,
432 SECTION_BUY_MENU_WEAPONS,
433 SECTION_EXTRA_ITEMS_WEAPONS,
434 SECTION_HARD_CODED_ITEMS_COSTS,
435 SECTION_WEATHER_EFFECTS,
436 SECTION_SKY,
437 SECTION_LIGHTNING,
438 SECTION_ZOMBIE_DECALS,
439 SECTION_KNOCKBACK,
440 SECTION_OBJECTIVE_ENTS,
441 SECTION_SVC_BAD
442}
443
444// Access flags
445enum
446{
447 ACCESS_ENABLE_MOD = 0,
448 ACCESS_ADMIN_MENU,
449 ACCESS_ADMIN_MODES_MENU,
450 ACCESS_MODE_INFECTION,
451 ACCESS_MODE_NEMESIS,
452 ACCESS_MODE_ASSASSIN,
453 ACCESS_MODE_SURVIVOR,
454 ACCESS_MODE_SNIPER,
455 ACCESS_MODE_SWARM,
456 ACCESS_MODE_MULTI,
457 ACCESS_MODE_PLAGUE,
458 ACCESS_MODE_ARMAGEDDON,
459 ACCESS_MODE_APOCALYPSE,
460 ACCESS_MODE_NIGHTMARE,
461 ACCESS_MAKE_ZOMBIE,
462 ACCESS_MAKE_HUMAN,
463 ACCESS_MAKE_NEMESIS,
464 ACCESS_MAKE_ASSASSIN,
465 ACCESS_MAKE_SURVIVOR,
466 ACCESS_MAKE_SNIPER,
467 ACCESS_RESPAWN_PLAYERS,
468 ACCESS_ADMIN_MODELS,
469 MAX_ACCESS_FLAGS
470}
471
472// Task offsets
473enum (+= 100)
474{
475 TASK_MODEL = 2000,
476 TASK_TEAM,
477 TASK_SPAWN,
478 TASK_BLOOD,
479 TASK_AURA,
480 TASK_BURN,
481 TASK_NVISION,
482 TASK_FLASH,
483 TASK_CHARGE,
484 TASK_SHOWHUD,
485 TASK_MAKEZOMBIE,
486 TASK_WELCOMEMSG,
487 TASK_THUNDER_PRE,
488 TASK_THUNDER,
489 TASK_AMBIENCESOUNDS
490}
491
492// IDs inside tasks
493#define ID_MODEL (taskid - TASK_MODEL)
494#define ID_TEAM (taskid - TASK_TEAM)
495#define ID_SPAWN (taskid - TASK_SPAWN)
496#define ID_BLOOD (taskid - TASK_BLOOD)
497#define ID_AURA (taskid - TASK_AURA)
498#define ID_BURN (taskid - TASK_BURN)
499#define ID_NVISION (taskid - TASK_NVISION)
500#define ID_FLASH (taskid - TASK_FLASH)
501#define ID_CHARGE (taskid - TASK_CHARGE)
502#define ID_SHOWHUD (taskid - TASK_SHOWHUD)
503
504// BP Ammo Refill task
505#define REFILL_WEAPONID args[0]
506
507// For weapon buy menu handlers
508#define WPN_STARTID g_menu_data[id][1]
509#define WPN_MAXIDS ArraySize(g_primary_items)
510#define WPN_SELECTION (g_menu_data[id][1]+key)
511#define WPN_AUTO_ON g_menu_data[id][2]
512#define WPN_AUTO_PRI g_menu_data[id][3]
513#define WPN_AUTO_SEC g_menu_data[id][4]
514
515// For player list menu handlers
516#define PL_ACTION g_menu_data[id][0]
517
518// For remembering menu pages
519#define MENU_PAGE_ZCLASS g_menu_data[id][5]
520#define MENU_PAGE_EXTRAS g_menu_data[id][6]
521#define MENU_PAGE_PLAYERS g_menu_data[id][7]
522
523// For extra items menu handlers
524#define EXTRAS_CUSTOM_STARTID (EXTRA_WEAPONS_STARTID + ArraySize(g_extraweapon_names))
525
526// Menu selections
527const MENU_KEY_AUTOSELECT = 7
528const MENU_KEY_BACK = 7
529const MENU_KEY_NEXT = 8
530const MENU_KEY_EXIT = 9
531
532// Hard coded extra items
533enum
534{
535 EXTRA_NVISION = 0,
536 EXTRA_ANTIDOTE,
537 EXTRA_MADNESS,
538 EXTRA_INFBOMB,
539 EXTRA_WEAPONS_STARTID
540}
541
542// Game modes
543enum
544{
545 MODE_NONE = 0,
546 MODE_INFECTION,
547 MODE_NEMESIS,
548 MODE_ASSASSIN,
549 MODE_SURVIVOR,
550 MODE_SNIPER,
551 MODE_SWARM,
552 MODE_MULTI,
553 MODE_PLAGUE,
554 MODE_ARMAGEDDON,
555 MODE_APOCALYPSE,
556 MODE_NIGHTMARE
557}
558
559// ZP Teams
560const ZP_TEAM_NO_ONE = 0
561const ZP_TEAM_ANY = 0
562const ZP_TEAM_ZOMBIE = (1<<0)
563const ZP_TEAM_HUMAN = (1<<1)
564const ZP_TEAM_NEMESIS = (1<<2)
565const ZP_TEAM_ASSASSIN = (1<<3)
566const ZP_TEAM_SURVIVOR = (1<<4)
567const ZP_TEAM_SNIPER = (1<<5)
568new const ZP_TEAM_NAMES[][] =
569{
570 "ZOMBIE , HUMAN",
571 "ZOMBIE",
572 "HUMAN",
573 "ZOMBIE , HUMAN",
574 "NEMESIS",
575 "ZOMBIE , NEMESIS",
576 "HUMAN , NEMESIS",
577 "ZOMBIE , HUMAN , NEMESIS",
578 "ASSASSIN",
579 "ZOMBIE , ASSASSIN",
580 "HUMAN , ASSASSIN",
581 "ZOMBIE, HUMAN, ASSASSIN",
582 "NEMESIS , ASSASSIN",
583 "ZOMBIE , NEMESIS , ASSASSIN",
584 "HUMAN, NEMESIS, ASSASSIN",
585 "ZOMBIE , HUMAN , NEMESIS , ASSASSIN",
586 "SURVIVOR",
587 "ZOMBIE, SURVIVOR",
588 "HUMAN, SURVIVOR",
589 "ZOMBIE, HUMAN, SURVIVOR",
590 "NEMESIS , SURVIVOR",
591 "ZOMBIE , NEMESIS , SURVIVOR",
592 "HUMAN , NEMESIS , SURVIVOR",
593 "ZOMBIE , HUMAN , NEMESIS , SURVIVOR",
594 "ASSASSIN, SURVIVOR",
595 "ZOMBIE, ASSASSIN, SURVIVOR",
596 "HUMAN, ASSASSIN, SURVIVOR",
597 "ZOMBIE, HUMAN, ASSASSIN, SURVIVOR",
598 "NEMESIS, ASSASSIN, SURVIVOR",
599 "ZOMBIE, NEMESIS, ASSASSIN, SURVIVOR",
600 "HUMAN, NEMESIS, ASSASSIN, SURVIVOR",
601 "ZOMBIE, HUMAN, NEMESIS, ASSASSIN, SURVIVOR",
602 "SNIPER",
603 "ZOMBIE, SNIPER",
604 "HUMAN, SNIPER",
605 "ZOMBIE, HUMAN, SNIPER",
606 "NEMESIS, SNIPER",
607 "ZOMBIE, NEMESIS, SNIPER",
608 "HUMAN, NEMESIS, SNIPER",
609 "ZOMBIE, HUMAN, NEMESIS, SNIPER",
610 "ASSASSIN, SNIPER",
611 "ZOMBIE, ASSASSIN, SNIPER",
612 "HUMAN, ASSASSIN, SNIPER",
613 "ZOMBIE, HUMAN, ASSASSIN, SNIPER",
614 "NEMESIS, ASSASSIN, SNIPER",
615 "ZOMBIE, NEMESIS, ASSASSIN, SNIPER",
616 "HUMAN, NEMESIS, ASSASSIN, SNIPER",
617 "ZOMBIE, HUMAN, NEMESIS, ASSASSIN, SNIPER",
618 "SURVIVOR, SNIPER",
619 "ZOMBIE, SURVIVOR, SNIPER",
620 "HUMAN, SURVIVOR, SNIPER",
621 "ZOMBIE, HUMAN, SURVIVOR, SNIPER",
622 "NEMESIS, SURVIVOR, SNIPER",
623 "ZOMBIE, NEMESIS, SURVIVOR, SNIPER",
624 "HUMAN, NEMESIS, SURVIVOR, SNIPER",
625 "ZOMBIE, HUMAN, NEMESIS, SURVIVOR, SNIPER",
626 "ASSASSIN, SURVIVOR, SNIPER",
627 "ZOMBIE, ASSASSIN, SURVIVOR, SNIPER",
628 "HUMAN, ASSASSIN, SURVIVOR, SNIPER",
629 "ZOMBIE, HUMAN, ASSASSIN, SURVIVOR, SNIPER",
630 "NEMESIS, ASSASSIN, SURVIVOR, SNIPER",
631 "ZOMBIE, NEMESIS, ASSASSIN, SURVIVOR, SNIPER",
632 "HUMAN, NEMESIS, ASSASSIN, SURVIVOR, SNIPER",
633 "ZOMBIE, HUMAN, NEMESIS, ASSASSIN, SURVIVOR, SNIPER"
634}
635
636// Zombie classes
637const ZCLASS_NONE = -1
638
639// HUD messages
640const Float:HUD_EVENT_X = -1.0
641const Float:HUD_EVENT_Y = 0.17
642const Float:HUD_INFECT_X = 0.05
643const Float:HUD_INFECT_Y = 0.45
644const Float:HUD_SPECT_X = -1.0
645const Float:HUD_SPECT_Y = 0.8
646const Float:HUD_STATS_X = 0.01
647const Float:HUD_STATS_Y = 0.04
648
649// Hack to be able to use Ham_Player_ResetMaxSpeed (by joaquimandrade)
650new Ham:Ham_Player_ResetMaxSpeed = Ham_Item_PreFrame
651
652// CS Player PData Offsets (win32)
653const PDATA_SAFE = 2
654const OFFSET_PAINSHOCK = 108 // ConnorMcLeod
655const OFFSET_CSTEAMS = 114
656const OFFSET_CSMONEY = 115
657const OFFSET_CSMENUCODE = 205
658const OFFSET_FLASHLIGHT_BATTERY = 244
659const OFFSET_CSDEATHS = 444
660const OFFSET_MODELINDEX = 491 // Orangutanz
661
662// CS Player CBase Offsets (win32)
663const OFFSET_ACTIVE_ITEM = 373
664
665// CS Weapon CBase Offsets (win32)
666const OFFSET_WEAPONOWNER = 41
667
668// Linux diff's
669const OFFSET_LINUX = 5 // offsets 5 higher in Linux builds
670const OFFSET_LINUX_WEAPONS = 4 // weapon offsets are only 4 steps higher on Linux
671
672// CS Teams
673enum
674{
675 FM_CS_TEAM_UNASSIGNED = 0,
676 FM_CS_TEAM_T,
677 FM_CS_TEAM_CT,
678 FM_CS_TEAM_SPECTATOR
679}
680new const CS_TEAM_NAMES[][] = { "UNASSIGNED", "TERRORIST", "CT", "SPECTATOR" }
681
682// Some constants
683const HIDE_MONEY = (1<<5)
684const UNIT_SECOND = (1<<12)
685const DMG_HEGRENADE = (1<<24)
686const IMPULSE_FLASHLIGHT = 100
687const USE_USING = 2
688const USE_STOPPED = 0
689const STEPTIME_SILENT = 999
690const BREAK_GLASS = 0x01
691const FFADE_IN = 0x0000
692const FFADE_STAYOUT = 0x0004
693const PEV_SPEC_TARGET = pev_iuser2
694
695// Max BP ammo for weapons
696new const MAXBPAMMO[] = { -1, 52, -1, 90, 1, 32, 1, 100, 90, 1, 120, 100, 100, 90, 90, 90, 100, 120,
697 30, 120, 200, 32, 90, 120, 90, 2, 35, 90, 90, -1, 100 }
698
699// Max Clip for weapons
700new const MAXCLIP[] = { -1, 13, -1, 10, -1, 7, -1, 30, 30, -1, 30, 20, 25, 30, 35, 25, 12, 20,
701 10, 30, 100, 8, 30, 30, 20, -1, 7, 30, 30, -1, 50 }
702
703// Amount of ammo to give when buying additional clips for weapons
704new const BUYAMMO[] = { -1, 13, -1, 30, -1, 8, -1, 12, 30, -1, 30, 50, 12, 30, 30, 30, 12, 30,
705 10, 30, 30, 8, 30, 30, 30, -1, 7, 30, 30, -1, 50 }
706
707// Ammo IDs for weapons
708new const AMMOID[] = { -1, 9, -1, 2, 12, 5, 14, 6, 4, 13, 10, 7, 6, 4, 4, 4, 6, 10,
709 1, 10, 3, 5, 4, 10, 2, 11, 8, 4, 2, -1, 7 }
710
711// Ammo Type Names for weapons
712new const AMMOTYPE[][] = { "", "357sig", "", "762nato", "", "buckshot", "", "45acp", "556nato", "", "9mm", "57mm", "45acp",
713 "556nato", "556nato", "556nato", "45acp", "9mm", "338magnum", "9mm", "556natobox", "buckshot",
714 "556nato", "9mm", "762nato", "", "50ae", "556nato", "762nato", "", "57mm" }
715
716// Weapon IDs for ammo types
717new const AMMOWEAPON[] = { 0, CSW_AWP, CSW_SCOUT, CSW_M249, CSW_AUG, CSW_XM1014, CSW_MAC10, CSW_FIVESEVEN, CSW_DEAGLE,
718 CSW_P228, CSW_ELITE, CSW_FLASHBANG, CSW_HEGRENADE, CSW_SMOKEGRENADE, CSW_C4 }
719
720// Primary and Secondary Weapon Names
721new const WEAPONNAMES[][] = { "", "P228 Compact", "", "Schmidt Scout", "", "XM1014 M4", "", "Ingram MAC-10", "Steyr AUG A1",
722 "", "Dual Elite Berettas", "FiveseveN", "UMP 45", "SG-550 Auto-Sniper", "IMI Galil", "Famas",
723 "USP .45 ACP Tactical", "Glock 18C", "AWP Magnum Sniper", "MP5 Navy", "M249 Para Machinegun",
724 "M3 Super 90", "M4A1 Carbine", "Schmidt TMP", "G3SG1 Auto-Sniper", "", "Desert Eagle .50 AE",
725 "SG-552 Commando", "AK-47 Kalashnikov", "", "ES P90" }
726
727// Weapon entity names
728new const WEAPONENTNAMES[][] = { "", "weapon_p228", "", "weapon_scout", "weapon_hegrenade", "weapon_xm1014", "weapon_c4", "weapon_mac10",
729 "weapon_aug", "weapon_smokegrenade", "weapon_elite", "weapon_fiveseven", "weapon_ump45", "weapon_sg550",
730 "weapon_galil", "weapon_famas", "weapon_usp", "weapon_glock18", "weapon_awp", "weapon_mp5navy", "weapon_m249",
731 "weapon_m3", "weapon_m4a1", "weapon_tmp", "weapon_g3sg1", "weapon_flashbang", "weapon_deagle", "weapon_sg552",
732 "weapon_ak47", "weapon_knife", "weapon_p90" }
733
734// CS sounds
735new const sound_flashlight[] = "items/flashlight1.wav"
736new const sound_buyammo[] = "items/9mmclip1.wav"
737new const sound_armorhit[] = "player/bhit_helmet-1.wav"
738
739// Explosion radius for custom grenades
740const Float:NADE_EXPLOSION_RADIUS = 240.0
741
742// HACK: pev_ field used to store additional ammo on weapons
743const PEV_ADDITIONAL_AMMO = pev_iuser1
744
745// HACK: pev_ field used to store custom nade types and their values
746const PEV_NADE_TYPE = pev_flTimeStepSound
747const NADE_TYPE_INFECTION = 1111
748const NADE_TYPE_NAPALM = 2222
749const NADE_TYPE_FROST = 3333
750const NADE_TYPE_FLARE = 4444
751const PEV_FLARE_COLOR = pev_punchangle
752const PEV_FLARE_DURATION = pev_flSwimTime
753
754// Weapon bitsums
755const 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)
756const SECONDARY_WEAPONS_BIT_SUM = (1<<CSW_P228)|(1<<CSW_ELITE)|(1<<CSW_FIVESEVEN)|(1<<CSW_USP)|(1<<CSW_GLOCK18)|(1<<CSW_DEAGLE)
757
758// Allowed weapons for zombies (added grenades/bomb for sub-plugin support, since they shouldn't be getting them anyway)
759const ZOMBIE_ALLOWED_WEAPONS_BITSUM = (1<<CSW_KNIFE)|(1<<CSW_HEGRENADE)|(1<<CSW_FLASHBANG)|(1<<CSW_SMOKEGRENADE)|(1<<CSW_C4)
760
761// Classnames for separate model entities
762new const MODEL_ENT_CLASSNAME[] = "player_model"
763new const WEAPON_ENT_CLASSNAME[] = "weapon_model"
764
765// Menu keys
766const 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
767
768// Ambience Sounds
769enum
770{
771 AMBIENCE_SOUNDS_INFECTION = 0,
772 AMBIENCE_SOUNDS_NEMESIS,
773 AMBIENCE_SOUNDS_ASSASSIN,
774 AMBIENCE_SOUNDS_SURVIVOR,
775 AMBIENCE_SOUNDS_SNIPER,
776 AMBIENCE_SOUNDS_SWARM,
777 AMBIENCE_SOUNDS_PLAGUE,
778 AMBIENCE_SOUNDS_ARMAGEDDON,
779 AMBIENCE_SOUNDS_APOCALYPSE,
780 AMBIENCE_SOUNDS_NIGHTMARE,
781 MAX_AMBIENCE_SOUNDS
782}
783
784// Admin menu actions
785enum
786{
787 ACTION_ZOMBIEFY_HUMANIZE = 0,
788 ACTION_MAKE_NEMESIS,
789 ACTION_MAKE_ASSASSIN,
790 ACTION_MAKE_SURVIVOR,
791 ACTION_MAKE_SNIPER,
792 ACTION_RESPAWN_PLAYER,
793 ACTION_MODES_MENU
794
795}
796
797// Admin modes menu actions
798enum
799{
800 ACTION_MODE_SWARM,
801 ACTION_MODE_MULTI,
802 ACTION_MODE_PLAGUE,
803 ACTION_MODE_ARMAGEDDON,
804 ACTION_MODE_APOCALYPSE,
805 ACTION_MODE_NIGHTMARE
806}
807
808// Custom forward return values
809const ZP_PLUGIN_HANDLED = 97
810
811/*================================================================================
812 [Global Variables]
813=================================================================================*/
814
815// Player vars
816new g_zombie[33] // is zombie
817new g_nemesis[33] // is nemesis
818new g_assassin[33] // is assassin
819new g_survivor[33] // is survivor
820new g_sniper[33] // is assassin
821new g_firstzombie[33] // is first zombie
822new g_lastzombie[33] // is last zombie
823new g_lasthuman[33] // is last human
824new g_frozen[33] // is frozen (can't move)
825new Float:g_frozen_gravity[33] // store previous gravity when frozen
826new g_nodamage[33] // has spawn protection/zombie madness
827new g_respawn_as_zombie[33] // should respawn as zombie
828new g_nvision[33] // has night vision
829new g_nvisionenabled[33] // has night vision turned on
830new g_zombieclass[33] // zombie class
831new g_zombieclassnext[33] // zombie class for next infection
832new g_flashlight[33] // has custom flashlight turned on
833new g_flashbattery[33] = { 100, ... } // custom flashlight battery
834new g_canbuy[33] // is allowed to buy a new weapon through the menu
835new g_ammopacks[33] // ammo pack count
836new g_damagedealt_human[33] // damage dealt as human (used to calculate ammo packs reward)
837new g_damagedealt_zombie[33] // damage dealt as zombie (used to calculate ammo packs reward)
838new Float:g_lastleaptime[33] // time leap was last used
839new Float:g_lastflashtime[33] // time flashlight was last toggled
840new g_playermodel[33][32] // current model's short name [player][model]
841new g_menu_data[33][8] // data for some menu handlers
842new g_ent_playermodel[33] // player model entity
843new g_ent_weaponmodel[33] // weapon model entity
844new g_burning_duration[33] // burning task duration
845new Float:g_buytime[33] // used to calculate custom buytime
846
847// Game vars
848new g_pluginenabled // ZP enabled
849new g_newround // new round starting
850new g_endround // round ended
851new g_nemround // nemesis round
852new g_assaround // assassin round
853new g_survround // survivor round
854new g_sniround // sniper round
855new g_swarmround // swarm round
856new g_plagueround // plague round
857new g_armageround // armageddon round
858new g_apocround // apocalypse round
859new g_nightround // nightmare round
860new g_modestarted // mode fully started
861new g_lastmode // last played mode
862new g_scorezombies, g_scorehumans, g_gamecommencing // team scores
863new g_spawnCount, g_spawnCount2 // available spawn points counter
864new Float:g_spawns[MAX_CSDM_SPAWNS][3], Float:g_spawns2[MAX_CSDM_SPAWNS][3] // spawn points data
865new g_lights_i // lightning current lights counter
866new g_lights_cycle[32] // current lightning cycle
867new g_lights_cycle_len // lightning cycle length
868new Float:g_models_targettime // for adding delays between Model Change messages
869new Float:g_teams_targettime // for adding delays between Team Change messages
870new g_MsgSync, g_MsgSync2, g_MsgSync3 // message sync objects
871new g_trailSpr, g_exploSpr, g_flameSpr, g_smokeSpr, g_glassSpr // grenade sprites
872new g_modname[32] // for formatting the mod name
873new g_freezetime // whether CS's freeze time is on
874new g_maxplayers // max players counter
875new g_czero // whether we are running on a CZ server
876new g_hamczbots // whether ham forwards are registered for CZ bots
877new g_fwSpawn, g_fwPrecacheSound // spawn and precache sound forward handles
878new g_infbombcounter, g_antidotecounter, g_madnesscounter // to limit buying some items
879new g_arrays_created // to prevent stuff from being registered before initializing arrays
880new g_lastplayerleaving // flag for whenever a player leaves and another takes his place
881new g_switchingteam // flag for whenever a player's team change emessage is sent
882new g_buyzone_ent // custom buyzone entity
883
884// Message IDs vars
885new g_msgScoreInfo, g_msgNVGToggle, g_msgScoreAttrib, g_msgAmmoPickup, g_msgScreenFade,
886g_msgDeathMsg, g_msgSetFOV, g_msgFlashlight, g_msgFlashBat, g_msgTeamInfo, g_msgDamage,
887g_msgHideWeapon, g_msgCrosshair, g_msgSayText, g_msgScreenShake, g_msgCurWeapon
888
889// Some forward handlers
890new g_fwRoundStart, g_fwRoundEnd, g_fwUserInfected_pre, g_fwUserInfected_post,
891g_fwUserHumanized_pre, g_fwUserHumanized_post, g_fwUserInfect_attempt,
892g_fwUserHumanize_attempt, g_fwExtraItemSelected, g_fwUserUnfrozen,
893g_fwUserLastZombie, g_fwUserLastHuman, g_fwDummyResult
894
895// Temporary Database vars (used to restore players stats in case they get disconnected)
896new db_name[MAX_STATS_SAVED][32] // player name
897new db_ammopacks[MAX_STATS_SAVED] // ammo pack count
898new db_zombieclass[MAX_STATS_SAVED] // zombie class
899new db_slot_i // additional saved slots counter (should start on maxplayers+1)
900
901// Extra Items vars
902new Array:g_extraitem_name // caption
903new Array:g_extraitem_cost // cost
904new Array:g_extraitem_team // team
905new g_extraitem_i // loaded extra items counter
906
907// For extra items file parsing
908new Array:g_extraitem2_realname, Array:g_extraitem2_name, Array:g_extraitem2_cost,
909Array:g_extraitem2_team, Array:g_extraitem_new
910
911// Zombie Classes vars
912new Array:g_zclass_name // caption
913new Array:g_zclass_info // description
914new Array:g_zclass_modelsstart // start position in models array
915new Array:g_zclass_modelsend // end position in models array
916new Array:g_zclass_playermodel // player models array
917new Array:g_zclass_modelindex // model indices array
918new Array:g_zclass_clawmodel // claw model
919new Array:g_zclass_hp // health
920new Array:g_zclass_spd // speed
921new Array:g_zclass_grav // gravity
922new Array:g_zclass_kb // knockback
923new g_zclass_i // loaded zombie classes counter
924
925// For zombie classes file parsing
926new Array:g_zclass2_realname, Array:g_zclass2_name, Array:g_zclass2_info,
927Array:g_zclass2_modelsstart, Array:g_zclass2_modelsend, Array:g_zclass2_playermodel,
928Array:g_zclass2_modelindex, Array:g_zclass2_clawmodel, Array:g_zclass2_hp,
929Array:g_zclass2_spd, Array:g_zclass2_grav, Array:g_zclass2_kb, Array:g_zclass_new
930
931// Customization vars
932new g_access_flag[MAX_ACCESS_FLAGS], Array:model_nemesis, Array:model_survivor, Array:model_human,
933Array:model_admin_zombie, Array:model_admin_human, Array:g_modelindex_human,
934Array:g_modelindex_nemesis, Array:g_modelindex_survivor, g_same_models_for_all,
935Array:g_modelindex_admin_zombie, Array:g_modelindex_admin_human, model_vknife_human[64],
936model_vknife_nemesis[64], model_vweapon_survivor[64], model_grenade_infect[64],
937model_grenade_fire[64], model_grenade_frost[64], model_grenade_flare[64],
938model_vknife_admin_human[64], model_vknife_admin_zombie[64],
939sprite_grenade_trail[64], sprite_grenade_ring[64], sprite_grenade_fire[64],
940sprite_grenade_smoke[64], sprite_grenade_glass[64], Array:sound_win_zombies,
941Array:sound_win_humans, Array:sound_win_no_one, Array:sound_win_zombies_ismp3,
942Array:sound_win_humans_ismp3, Array:sound_win_no_one_ismp3, Array:zombie_infect,
943Array:zombie_idle, Array:zombie_pain, Array:nemesis_pain, Array:zombie_die, Array:zombie_fall,
944Array:zombie_miss_wall, Array:zombie_hit_normal, Array:zombie_hit_stab, g_ambience_rain,
945Array:zombie_idle_last, Array:zombie_madness, Array:sound_nemesis, Array:sound_survivor,
946Array:sound_swarm, Array:sound_multi, Array:sound_plague, Array:grenade_infect,
947Array:grenade_infect_player, Array:grenade_fire, Array:grenade_fire_player,
948Array:grenade_frost, Array:grenade_frost_player, Array:grenade_frost_break,
949Array:grenade_flare, Array:sound_antidote, Array:sound_thunder, g_ambience_sounds[MAX_AMBIENCE_SOUNDS],
950Array:sound_ambience1, Array:sound_ambience2, Array:sound_ambience3, Array:sound_ambience4,
951Array:sound_ambience5, Array:sound_ambience1_duration, Array:sound_ambience2_duration,
952Array:sound_ambience3_duration, Array:sound_ambience4_duration,
953Array:sound_ambience5_duration, Array:sound_ambience1_ismp3, Array:sound_ambience2_ismp3,
954Array:sound_ambience3_ismp3, Array:sound_ambience4_ismp3, Array:sound_ambience5_ismp3,
955Array:g_primary_items, Array:g_secondary_items, Array:g_additional_items,
956Array:g_primary_weaponids, Array:g_secondary_weaponids, Array:g_extraweapon_names,
957Array:g_extraweapon_items, Array:g_extraweapon_costs, g_extra_costs2[EXTRA_WEAPONS_STARTID],
958g_ambience_snow, g_ambience_fog, g_fog_density[10], g_fog_color[12], g_sky_enable,
959Array:g_sky_names, Array:lights_thunder, Array:zombie_decals, Array:g_objective_ents,
960Float:g_modelchange_delay, g_set_modelindex_offset, g_handle_models_on_separate_ent,
961Float:kb_weapon_power[31] = { -1.0, ... }, Array:zombie_miss_slash, g_force_consistency,
962Array:model_assassin, Array:model_sniper, Array:g_modelindex_assassin, Array:g_modelindex_sniper, model_vknife_assassin[64],
963model_vawp_sniper[64], model_pawp_sniper[64], Array:assassin_pain, Array:sound_assassin, Array:sound_sniper, Array:sound_ambience6,
964Array:sound_ambience6_duration, Array:sound_ambience6_ismp3, Array:sound_ambience7, Array:sound_ambience7_duration, Array:sound_ambience7_ismp3,
965Array:sound_armageddon, Array:sound_apocalypse, Array:sound_ambience9, Array:sound_ambience9_duration, Array:sound_ambience9_ismp3, Array:sound_nightmare, Array:sound_ambience10, Array:sound_ambience10_duration, Array:sound_ambience10_ismp3,
966Array:sound_ambience8_ismp3, Array:sound_ambience8, Array:sound_ambience8_duration
967
968
969// CVAR pointers
970new cvar_lighting, cvar_zombiefov, cvar_plague, cvar_plaguechance, cvar_zombiefirsthp,
971cvar_removemoney, cvar_thunder, cvar_zombiebonushp, cvar_nemhp, cvar_nem, cvar_surv,
972cvar_nemchance, cvar_deathmatch, cvar_nemglow, cvar_customnvg, cvar_hitzones, cvar_humanhp,
973cvar_nemgravity, cvar_flashsize, cvar_ammodamage_human, cvar_ammodamage_zombie,
974cvar_zombiearmor, cvar_survpainfree, cvar_nempainfree, cvar_nemspd, cvar_survchance,
975cvar_survhp, cvar_survspd, cvar_humanspd, cvar_swarmchance, cvar_flashdrain,
976cvar_zombiebleeding, cvar_removedoors, cvar_customflash, cvar_randspawn, cvar_multi,
977cvar_multichance, cvar_infammo, cvar_swarm, cvar_ammoinfect, cvar_toggle,
978cvar_knockbackpower, cvar_freezeduration, cvar_triggered, cvar_flashcharge,
979cvar_firegrenades, cvar_frostgrenades, cvar_survgravity, cvar_logcommands, cvar_survglow,
980cvar_humangravity, cvar_spawnprotection, cvar_nvgsize, cvar_flareduration, cvar_zclasses,
981cvar_extraitems, cvar_showactivity, cvar_humanlasthp, cvar_nemignorefrags, cvar_warmup,
982cvar_flashdist, cvar_flarecolor, cvar_survignorefrags, cvar_fireduration, cvar_firedamage,
983cvar_flaregrenades, cvar_knockbackducking, cvar_knockbackdamage, cvar_knockbackzvel,
984cvar_multiratio, cvar_flaresize, cvar_spawndelay, cvar_extraantidote, cvar_extramadness,
985cvar_extraweapons, cvar_extranvision, cvar_nvggive, cvar_preventconsecutive, cvar_botquota,
986cvar_buycustom, cvar_zombiepainfree, cvar_fireslowdown, cvar_survbasehp, cvar_survaura,
987cvar_nemignoreammo, cvar_survignoreammo, cvar_nemaura, cvar_extrainfbomb, cvar_knockback,
988cvar_fragsinfect, cvar_fragskill, cvar_humanarmor, cvar_zombiesilent, cvar_removedropped,
989cvar_plagueratio, cvar_blocksuicide, cvar_knockbackdist, cvar_nemdamage, cvar_leapzombies,
990cvar_leapzombiesforce, cvar_leapzombiesheight, cvar_leapzombiescooldown, cvar_leapnemesis,
991cvar_leapnemesisforce, cvar_leapnemesisheight, cvar_leapnemesiscooldown, cvar_leapsurvivor,
992cvar_leapsurvivorforce, cvar_leapsurvivorheight, cvar_nemminplayers, cvar_survminplayers,
993cvar_respawnonsuicide, cvar_respawnafterlast, cvar_leapsurvivorcooldown, cvar_statssave,
994cvar_swarmminplayers, cvar_multiminplayers, cvar_plagueminplayers, cvar_adminmodelshuman,
995cvar_adminmodelszombie, cvar_nembasehp, cvar_blockpushables, cvar_respawnworldspawnkill,
996cvar_madnessduration, cvar_plaguenemnum, cvar_plaguenemhpmulti, cvar_plaguesurvhpmulti,
997cvar_plaguesurvnum, cvar_infectionscreenfade, cvar_infectionscreenshake,
998cvar_infectionsparkle, cvar_infectiontracers, cvar_infectionparticles, cvar_infbomblimit,
999cvar_allowrespawnsurv, cvar_flashshowall, cvar_allowrespawninfection, cvar_allowrespawnnem,
1000cvar_allowrespawnswarm, cvar_allowrespawnplague, cvar_survinfammo, cvar_nemknockback,
1001cvar_nvgcolor[3], cvar_nemnvgcolor[3], cvar_humnvgcolor[3], cvar_flashcolor[3],
1002cvar_hudicons, cvar_respawnzomb, cvar_respawnhum, cvar_respawnnem, cvar_respawnsurv,
1003cvar_startammopacks, cvar_randweapons, cvar_antidotelimit, cvar_madnesslimit,
1004cvar_adminknifemodelshuman, cvar_adminknifemodelszombie, cvar_keephealthondisconnect,
1005cvar_buyzonetime, cvar_huddisplay, cvar_leapsniper, cvar_leapsniperforce, cvar_leapsniperheight,
1006cvar_leapsnipercooldown, cvar_sniminplayers, cvar_leapassassin, cvar_leapassassinforce, cvar_leapassassinheight,
1007cvar_leapassassincooldown, cvar_sni, cvar_snipainfree, cvar_snichance, cvar_snihp, cvar_snispd,
1008cvar_snigravity, cvar_sniglow, cvar_assahp, cvar_assa, cvar_assachance, cvar_assagravity, cvar_assaglow,
1009cvar_assapainfree, cvar_assaspd, cvar_assadamage, cvar_snibasehp, cvar_sniaura, cvar_assaminplayers,
1010cvar_assabasehp, cvar_allowrespawnassa, cvar_assaknockback, cvar_assanvgcolor[3], cvar_respawnassa, cvar_snidamage, cvar_allowrespawnsni,
1011cvar_sniinfammo, cvar_respawnsni, cvar_assaaura, cvar_assaignoreammo, cvar_assaignorefrags, cvar_snipignorefrags, cvar_snipignoreammo,
1012cvar_armage, cvar_armagechance, cvar_armageminplayers, cvar_armageratio, cvar_armagenemhpmulti, cvar_armagesurvhpmulti, cvar_apoc, cvar_apocchance,
1013cvar_apocminplayers, cvar_apocratio, cvar_apocassahpmulti, cvar_apocsniphpmulti, cvar_night, cvar_nightchance, cvar_nightminplayers, cvar_nightratio,
1014cvar_nightassahpmulti, cvar_nightsniphpmulti, cvar_nightnemhpmulti, cvar_nightsurvhpmulti, cvar_allowrespawnarmage, cvar_allowrespawnapoc, cvar_allowrespawnnight, cvar_aiminfo, cvar_dmg_while_freeze
1015
1016// Cached stuff for players
1017new g_isconnected[33] // whether player is connected
1018new g_isalive[33] // whether player is alive
1019new g_isbot[33] // whether player is a bot
1020new g_currentweapon[33] // player's current weapon id
1021new g_playername[33][32] // player's name
1022new Float:g_zombie_spd[33] // zombie class speed
1023new Float:g_zombie_knockback[33] // zombie class knockback
1024new g_zombie_classname[33][32] // zombie class name
1025#define is_user_valid_connected(%1) (1 <= %1 <= g_maxplayers && g_isconnected[%1])
1026#define is_user_valid_alive(%1) (1 <= %1 <= g_maxplayers && g_isalive[%1])
1027#define is_user_valid(%1) (1 <= %1 <= g_maxplayers)
1028
1029// Cached CVARs
1030new g_cached_customflash, g_cached_zombiesilent, g_cached_leapzombies, g_cached_leapnemesis,
1031g_cached_leapsurvivor, Float:g_cached_leapzombiescooldown, Float:g_cached_leapnemesiscooldown, g_cached_leapassassin, Float:g_cached_leapassassincooldown,
1032Float:g_cached_leapsurvivorcooldown, Float:g_cached_buytime, g_cached_leapsniper, Float:g_cached_leapsnipercooldown
1033
1034
1035/*================================================================================
1036 [Natives, Precache and Init]
1037=================================================================================*/
1038
1039public plugin_natives()
1040{
1041 // Player specific natives
1042 register_native("zp_get_user_zombie", "native_get_user_zombie", 1)
1043 register_native("zp_get_user_nemesis", "native_get_user_nemesis", 1)
1044 register_native("zp_get_user_assassin", "native_get_user_assassin", 1)
1045 register_native("zp_get_user_survivor", "native_get_user_survivor", 1)
1046 register_native("zp_get_user_sniper", "native_get_user_sniper", 1)
1047 register_native("zp_get_user_first_zombie", "native_get_user_first_zombie", 1)
1048 register_native("zp_get_user_last_zombie", "native_get_user_last_zombie", 1)
1049 register_native("zp_get_user_last_human", "native_get_user_last_human", 1)
1050 register_native("zp_get_user_zombie_class", "native_get_user_zombie_class", 1)
1051 register_native("zp_get_user_next_class", "native_get_user_next_class", 1)
1052 register_native("zp_set_user_zombie_class", "native_set_user_zombie_class", 1)
1053 register_native("zp_get_user_ammo_packs", "native_get_user_ammo_packs", 1)
1054 register_native("zp_set_user_ammo_packs", "native_set_user_ammo_packs", 1)
1055 register_native("zp_get_zombie_maxhealth", "native_get_zombie_maxhealth", 1)
1056 register_native("zp_get_user_batteries", "native_get_user_batteries", 1)
1057 register_native("zp_set_user_batteries", "native_set_user_batteries", 1)
1058 register_native("zp_get_user_nightvision", "native_get_user_nightvision", 1)
1059 register_native("zp_set_user_nightvision", "native_set_user_nightvision", 1)
1060 register_native("zp_infect_user", "native_infect_user", 1)
1061 register_native("zp_disinfect_user", "native_disinfect_user", 1)
1062 register_native("zp_make_user_nemesis", "native_make_user_nemesis", 1)
1063 register_native("zp_make_user_assassin", "native_make_user_assassin", 1)
1064 register_native("zp_make_user_survivor", "native_make_user_survivor", 1)
1065 register_native("zp_make_user_sniper", "native_make_user_sniper", 1)
1066 register_native("zp_respawn_user", "native_respawn_user", 1)
1067 register_native("zp_force_buy_extra_item", "native_force_buy_extra_item", 1)
1068 register_native("zp_override_user_model", "native_override_user_model", 1)
1069
1070 // new natives
1071 register_native("zp_get_user_model", "native_get_user_model", 0)
1072 register_native("zp_set_user_model", "native_set_user_model", 1)
1073
1074 // Round natives
1075 register_native("zp_has_round_started", "native_has_round_started", 1)
1076 register_native("zp_is_nemesis_round", "native_is_nemesis_round", 1)
1077 register_native("zp_is_assassin_round", "native_is_assassin_round", 1)
1078 register_native("zp_is_survivor_round", "native_is_survivor_round", 1)
1079 register_native("zp_is_sniper_round", "native_is_sniper_round", 1)
1080 register_native("zp_is_swarm_round", "native_is_swarm_round", 1)
1081 register_native("zp_is_plague_round", "native_is_plague_round", 1)
1082 register_native("zp_is_armageddon_round", "native_is_armageddon_round", 1)
1083 register_native("zp_is_apocalypse_round", "native_is_apocalypse_round", 1)
1084 register_native("zp_is_nightmare_round", "native_is_nightmare_round", 1)
1085 register_native("zp_get_zombie_count", "native_get_zombie_count", 1)
1086 register_native("zp_get_human_count", "native_get_human_count", 1)
1087 register_native("zp_get_nemesis_count", "native_get_nemesis_count", 1)
1088 register_native("zp_get_assassin_count", "native_get_assassin_count", 1)
1089 register_native("zp_get_survivor_count", "native_get_survivor_count", 1)
1090 register_native("zp_get_sniper_count", "native_get_sniper_count", 1)
1091
1092 // External additions natives
1093 register_native("zp_register_extra_item", "native_register_extra_item", 1)
1094 register_native("zp_register_zombie_class", "native_register_zombie_class", 1)
1095 register_native("zp_get_extra_item_id", "native_get_extra_item_id", 1)
1096 register_native("zp_get_zombie_class_id", "native_get_zombie_class_id", 1)
1097 register_native("zp_get_zombie_class_info", "native_get_zombie_class_info", 1)
1098}
1099
1100public plugin_precache()
1101{
1102 // Register earlier to show up in plugins list properly after plugin disable/error at loading
1103 register_plugin("Zombie Plague", PLUGIN_VERSION, "MeRcyLeZZ")
1104
1105 // To switch plugin on/off
1106 register_concmd("zp_toggle", "cmd_toggle", _, "<1/0> - Enable/Disable Zombie Plague (will restart the current map)", 0)
1107 cvar_toggle = register_cvar("zp_on", "1")
1108
1109 // Plugin disabled?
1110 if (!get_pcvar_num(cvar_toggle)) return;
1111 g_pluginenabled = true
1112
1113 // Initialize a few dynamically sized arrays (alright, maybe more than just a few...)
1114 model_human = ArrayCreate(32, 1)
1115 model_nemesis = ArrayCreate(32, 1)
1116 model_assassin = ArrayCreate(32, 1)
1117 model_survivor = ArrayCreate(32, 1)
1118 model_sniper = ArrayCreate(32, 1)
1119 model_admin_human = ArrayCreate(32, 1)
1120 model_admin_zombie = ArrayCreate(32, 1)
1121 g_modelindex_human = ArrayCreate(1, 1)
1122 g_modelindex_nemesis = ArrayCreate(1, 1)
1123 g_modelindex_assassin = ArrayCreate(1, 1)
1124 g_modelindex_survivor = ArrayCreate(1, 1)
1125 g_modelindex_sniper = ArrayCreate(1, 1)
1126 g_modelindex_admin_human = ArrayCreate(1, 1)
1127 g_modelindex_admin_zombie = ArrayCreate(1, 1)
1128 sound_win_zombies = ArrayCreate(64, 1)
1129 sound_win_zombies_ismp3 = ArrayCreate(1, 1)
1130 sound_win_humans = ArrayCreate(64, 1)
1131 sound_win_humans_ismp3 = ArrayCreate(1, 1)
1132 sound_win_no_one = ArrayCreate(64, 1)
1133 sound_win_no_one_ismp3 = ArrayCreate(1, 1)
1134 zombie_infect = ArrayCreate(64, 1)
1135 zombie_pain = ArrayCreate(64, 1)
1136 nemesis_pain = ArrayCreate(64, 1)
1137 assassin_pain = ArrayCreate(64, 1)
1138 zombie_die = ArrayCreate(64, 1)
1139 zombie_fall = ArrayCreate(64, 1)
1140 zombie_miss_slash = ArrayCreate(64, 1)
1141 zombie_miss_wall = ArrayCreate(64, 1)
1142 zombie_hit_normal = ArrayCreate(64, 1)
1143 zombie_hit_stab = ArrayCreate(64, 1)
1144 zombie_idle = ArrayCreate(64, 1)
1145 zombie_idle_last = ArrayCreate(64, 1)
1146 zombie_madness = ArrayCreate(64, 1)
1147 sound_nemesis = ArrayCreate(64, 1)
1148 sound_assassin = ArrayCreate(64, 1)
1149 sound_survivor = ArrayCreate(64, 1)
1150 sound_sniper = ArrayCreate(64, 1)
1151 sound_swarm = ArrayCreate(64, 1)
1152 sound_multi = ArrayCreate(64, 1)
1153 sound_plague = ArrayCreate(64, 1)
1154 sound_armageddon = ArrayCreate(64, 1)
1155 sound_apocalypse = ArrayCreate(64, 1)
1156 sound_nightmare = ArrayCreate(64, 1)
1157 grenade_infect = ArrayCreate(64, 1)
1158 grenade_infect_player = ArrayCreate(64, 1)
1159 grenade_fire = ArrayCreate(64, 1)
1160 grenade_fire_player = ArrayCreate(64, 1)
1161 grenade_frost = ArrayCreate(64, 1)
1162 grenade_frost_player = ArrayCreate(64, 1)
1163 grenade_frost_break = ArrayCreate(64, 1)
1164 grenade_flare = ArrayCreate(64, 1)
1165 sound_antidote = ArrayCreate(64, 1)
1166 sound_thunder = ArrayCreate(64, 1)
1167 sound_ambience1 = ArrayCreate(64, 1)
1168 sound_ambience2 = ArrayCreate(64, 1)
1169 sound_ambience3 = ArrayCreate(64, 1)
1170 sound_ambience4 = ArrayCreate(64, 1)
1171 sound_ambience5 = ArrayCreate(64, 1)
1172 sound_ambience6 = ArrayCreate(64, 1)
1173 sound_ambience7 = ArrayCreate(64, 1)
1174 sound_ambience8 = ArrayCreate(64, 1)
1175 sound_ambience9 = ArrayCreate(64, 1)
1176 sound_ambience10 = ArrayCreate(64, 1)
1177 sound_ambience1_duration = ArrayCreate(1, 1)
1178 sound_ambience2_duration = ArrayCreate(1, 1)
1179 sound_ambience3_duration = ArrayCreate(1, 1)
1180 sound_ambience4_duration = ArrayCreate(1, 1)
1181 sound_ambience5_duration = ArrayCreate(1, 1)
1182 sound_ambience6_duration = ArrayCreate(1, 1)
1183 sound_ambience7_duration = ArrayCreate(1, 1)
1184 sound_ambience8_duration = ArrayCreate(1, 1)
1185 sound_ambience9_duration = ArrayCreate(1, 1)
1186 sound_ambience10_duration = ArrayCreate(1, 1)
1187 sound_ambience1_ismp3 = ArrayCreate(1, 1)
1188 sound_ambience2_ismp3 = ArrayCreate(1, 1)
1189 sound_ambience3_ismp3 = ArrayCreate(1, 1)
1190 sound_ambience4_ismp3 = ArrayCreate(1, 1)
1191 sound_ambience5_ismp3 = ArrayCreate(1, 1)
1192 sound_ambience6_ismp3 = ArrayCreate(1, 1)
1193 sound_ambience7_ismp3 = ArrayCreate(1, 1)
1194 sound_ambience8_ismp3 = ArrayCreate(1, 1)
1195 sound_ambience9_ismp3 = ArrayCreate(1, 1)
1196 sound_ambience10_ismp3 = ArrayCreate(1, 1)
1197 g_primary_items = ArrayCreate(32, 1)
1198 g_secondary_items = ArrayCreate(32, 1)
1199 g_additional_items = ArrayCreate(32, 1)
1200 g_primary_weaponids = ArrayCreate(1, 1)
1201 g_secondary_weaponids = ArrayCreate(1, 1)
1202 g_extraweapon_names = ArrayCreate(32, 1)
1203 g_extraweapon_items = ArrayCreate(32, 1)
1204 g_extraweapon_costs = ArrayCreate(1, 1)
1205 g_sky_names = ArrayCreate(32, 1)
1206 lights_thunder = ArrayCreate(32, 1)
1207 zombie_decals = ArrayCreate(1, 1)
1208 g_objective_ents = ArrayCreate(32, 1)
1209 g_extraitem_name = ArrayCreate(32, 1)
1210 g_extraitem_cost = ArrayCreate(1, 1)
1211 g_extraitem_team = ArrayCreate(1, 1)
1212 g_extraitem2_realname = ArrayCreate(32, 1)
1213 g_extraitem2_name = ArrayCreate(32, 1)
1214 g_extraitem2_cost = ArrayCreate(1, 1)
1215 g_extraitem2_team = ArrayCreate(1, 1)
1216 g_extraitem_new = ArrayCreate(1, 1)
1217 g_zclass_name = ArrayCreate(32, 1)
1218 g_zclass_info = ArrayCreate(32, 1)
1219 g_zclass_modelsstart = ArrayCreate(1, 1)
1220 g_zclass_modelsend = ArrayCreate(1, 1)
1221 g_zclass_playermodel = ArrayCreate(32, 1)
1222 g_zclass_modelindex = ArrayCreate(1, 1)
1223 g_zclass_clawmodel = ArrayCreate(32, 1)
1224 g_zclass_hp = ArrayCreate(1, 1)
1225 g_zclass_spd = ArrayCreate(1, 1)
1226 g_zclass_grav = ArrayCreate(1, 1)
1227 g_zclass_kb = ArrayCreate(1, 1)
1228 g_zclass2_realname = ArrayCreate(32, 1)
1229 g_zclass2_name = ArrayCreate(32, 1)
1230 g_zclass2_info = ArrayCreate(32, 1)
1231 g_zclass2_modelsstart = ArrayCreate(1, 1)
1232 g_zclass2_modelsend = ArrayCreate(1, 1)
1233 g_zclass2_playermodel = ArrayCreate(32, 1)
1234 g_zclass2_modelindex = ArrayCreate(1, 1)
1235 g_zclass2_clawmodel = ArrayCreate(32, 1)
1236 g_zclass2_hp = ArrayCreate(1, 1)
1237 g_zclass2_spd = ArrayCreate(1, 1)
1238 g_zclass2_grav = ArrayCreate(1, 1)
1239 g_zclass2_kb = ArrayCreate(1, 1)
1240 g_zclass_new = ArrayCreate(1, 1)
1241
1242 // Allow registering stuff now
1243 g_arrays_created = true
1244
1245 // Load customization data
1246 load_customization_from_files()
1247
1248 new i, buffer[100]
1249
1250 // Load up the hard coded extra items
1251 native_register_extra_item2("NightVision", g_extra_costs2[EXTRA_NVISION], ZP_TEAM_HUMAN)
1252 native_register_extra_item2("T-Virus Antidote", g_extra_costs2[EXTRA_ANTIDOTE], ZP_TEAM_ZOMBIE)
1253 native_register_extra_item2("Zombie Madness", g_extra_costs2[EXTRA_MADNESS], ZP_TEAM_ZOMBIE)
1254 native_register_extra_item2("Infection Bomb", g_extra_costs2[EXTRA_INFBOMB], ZP_TEAM_ZOMBIE)
1255
1256 // Extra weapons
1257 for (i = 0; i < ArraySize(g_extraweapon_names); i++)
1258 {
1259 ArrayGetString(g_extraweapon_names, i, buffer, charsmax(buffer))
1260 native_register_extra_item2(buffer, ArrayGetCell(g_extraweapon_costs, i), ZP_TEAM_HUMAN)
1261 }
1262
1263 // Custom player models
1264 for (i = 0; i < ArraySize(model_human); i++)
1265 {
1266 ArrayGetString(model_human, i, buffer, charsmax(buffer))
1267 format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
1268 ArrayPushCell(g_modelindex_human, engfunc(EngFunc_PrecacheModel, buffer))
1269 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
1270 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
1271 // Precache modelT.mdl files too
1272 copy(buffer[strlen(buffer)-4], charsmax(buffer) - (strlen(buffer)-4), "T.mdl")
1273 if (file_exists(buffer)) engfunc(EngFunc_PrecacheModel, buffer)
1274 }
1275 for (i = 0; i < ArraySize(model_nemesis); i++)
1276 {
1277 ArrayGetString(model_nemesis, i, buffer, charsmax(buffer))
1278 format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
1279 ArrayPushCell(g_modelindex_nemesis, engfunc(EngFunc_PrecacheModel, buffer))
1280 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
1281 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
1282 // Precache modelT.mdl files too
1283 copy(buffer[strlen(buffer)-4], charsmax(buffer) - (strlen(buffer)-4), "T.mdl")
1284 if (file_exists(buffer)) engfunc(EngFunc_PrecacheModel, buffer)
1285 }
1286 for (i = 0; i < ArraySize(model_assassin); i++)
1287 {
1288 ArrayGetString(model_assassin, i, buffer, charsmax(buffer))
1289 format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
1290 ArrayPushCell(g_modelindex_assassin, engfunc(EngFunc_PrecacheModel, buffer))
1291 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
1292 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
1293 }
1294 for (i = 0; i < ArraySize(model_survivor); i++)
1295 {
1296 ArrayGetString(model_survivor, i, buffer, charsmax(buffer))
1297 format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
1298 ArrayPushCell(g_modelindex_survivor, engfunc(EngFunc_PrecacheModel, buffer))
1299 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
1300 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
1301 // Precache modelT.mdl files too
1302 copy(buffer[strlen(buffer)-4], charsmax(buffer) - (strlen(buffer)-4), "T.mdl")
1303 if (file_exists(buffer)) engfunc(EngFunc_PrecacheModel, buffer)
1304 }
1305 for (i = 0; i < ArraySize(model_sniper); i++)
1306 {
1307 ArrayGetString(model_sniper, i, buffer, charsmax(buffer))
1308 format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
1309 ArrayPushCell(g_modelindex_sniper, engfunc(EngFunc_PrecacheModel, buffer))
1310 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
1311 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
1312 }
1313 for (i = 0; i < ArraySize(model_admin_zombie); i++)
1314 {
1315 ArrayGetString(model_admin_zombie, i, buffer, charsmax(buffer))
1316 format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
1317 ArrayPushCell(g_modelindex_admin_zombie, engfunc(EngFunc_PrecacheModel, buffer))
1318 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
1319 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
1320 // Precache modelT.mdl files too
1321 copy(buffer[strlen(buffer)-4], charsmax(buffer) - (strlen(buffer)-4), "T.mdl")
1322 if (file_exists(buffer)) engfunc(EngFunc_PrecacheModel, buffer)
1323 }
1324 for (i = 0; i < ArraySize(model_admin_human); i++)
1325 {
1326 ArrayGetString(model_admin_human, i, buffer, charsmax(buffer))
1327 format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
1328 ArrayPushCell(g_modelindex_admin_human, engfunc(EngFunc_PrecacheModel, buffer))
1329 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
1330 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
1331 // Precache modelT.mdl files too
1332 copy(buffer[strlen(buffer)-4], charsmax(buffer) - (strlen(buffer)-4), "T.mdl")
1333 if (file_exists(buffer)) engfunc(EngFunc_PrecacheModel, buffer)
1334 }
1335
1336 // Custom weapon models
1337 engfunc(EngFunc_PrecacheModel, model_vknife_human)
1338 engfunc(EngFunc_PrecacheModel, model_vknife_nemesis)
1339 engfunc(EngFunc_PrecacheModel, model_vknife_assassin)
1340 engfunc(EngFunc_PrecacheModel, model_vweapon_survivor)
1341 engfunc(EngFunc_PrecacheModel, model_vawp_sniper)
1342 engfunc(EngFunc_PrecacheModel, model_pawp_sniper)
1343 engfunc(EngFunc_PrecacheModel, model_grenade_infect)
1344 engfunc(EngFunc_PrecacheModel, model_grenade_fire)
1345 engfunc(EngFunc_PrecacheModel, model_grenade_frost)
1346 engfunc(EngFunc_PrecacheModel, model_grenade_flare)
1347 engfunc(EngFunc_PrecacheModel, model_vknife_admin_human)
1348 engfunc(EngFunc_PrecacheModel, model_vknife_admin_zombie)
1349
1350 // Custom sprites for grenades
1351 g_trailSpr = engfunc(EngFunc_PrecacheModel, sprite_grenade_trail)
1352 g_exploSpr = engfunc(EngFunc_PrecacheModel, sprite_grenade_ring)
1353 g_flameSpr = engfunc(EngFunc_PrecacheModel, sprite_grenade_fire)
1354 g_smokeSpr = engfunc(EngFunc_PrecacheModel, sprite_grenade_smoke)
1355 g_glassSpr = engfunc(EngFunc_PrecacheModel, sprite_grenade_glass)
1356
1357 // Custom sounds
1358 for (i = 0; i < ArraySize(sound_win_zombies); i++)
1359 {
1360 ArrayGetString(sound_win_zombies, i, buffer, charsmax(buffer))
1361 if (ArrayGetCell(sound_win_zombies_ismp3, i))
1362 {
1363 format(buffer, charsmax(buffer), "sound/%s", buffer)
1364 engfunc(EngFunc_PrecacheGeneric, buffer)
1365 }
1366 else
1367 {
1368 engfunc(EngFunc_PrecacheSound, buffer)
1369 }
1370 }
1371 for (i = 0; i < ArraySize(sound_win_humans); i++)
1372 {
1373 ArrayGetString(sound_win_humans, i, buffer, charsmax(buffer))
1374 if (ArrayGetCell(sound_win_humans_ismp3, i))
1375 {
1376 format(buffer, charsmax(buffer), "sound/%s", buffer)
1377 engfunc(EngFunc_PrecacheGeneric, buffer)
1378 }
1379 else
1380 {
1381 engfunc(EngFunc_PrecacheSound, buffer)
1382 }
1383 }
1384 for (i = 0; i < ArraySize(sound_win_no_one); i++)
1385 {
1386 ArrayGetString(sound_win_no_one, i, buffer, charsmax(buffer))
1387 if (ArrayGetCell(sound_win_no_one_ismp3, i))
1388 {
1389 format(buffer, charsmax(buffer), "sound/%s", buffer)
1390 engfunc(EngFunc_PrecacheGeneric, buffer)
1391 }
1392 else
1393 {
1394 engfunc(EngFunc_PrecacheSound, buffer)
1395 }
1396 }
1397 for (i = 0; i < ArraySize(zombie_infect); i++)
1398 {
1399 ArrayGetString(zombie_infect, i, buffer, charsmax(buffer))
1400 engfunc(EngFunc_PrecacheSound, buffer)
1401 }
1402 for (i = 0; i < ArraySize(zombie_pain); i++)
1403 {
1404 ArrayGetString(zombie_pain, i, buffer, charsmax(buffer))
1405 engfunc(EngFunc_PrecacheSound, buffer)
1406 }
1407 for (i = 0; i < ArraySize(nemesis_pain); i++)
1408 {
1409 ArrayGetString(nemesis_pain, i, buffer, charsmax(buffer))
1410 engfunc(EngFunc_PrecacheSound, buffer)
1411 }
1412 for (i = 0; i < ArraySize(assassin_pain); i++)
1413 {
1414 ArrayGetString(assassin_pain, i, buffer, charsmax(buffer))
1415 engfunc(EngFunc_PrecacheSound, buffer)
1416 }
1417 for (i = 0; i < ArraySize(zombie_die); i++)
1418 {
1419 ArrayGetString(zombie_die, i, buffer, charsmax(buffer))
1420 engfunc(EngFunc_PrecacheSound, buffer)
1421 }
1422 for (i = 0; i < ArraySize(zombie_fall); i++)
1423 {
1424 ArrayGetString(zombie_fall, i, buffer, charsmax(buffer))
1425 engfunc(EngFunc_PrecacheSound, buffer)
1426 }
1427 for (i = 0; i < ArraySize(zombie_miss_slash); i++)
1428 {
1429 ArrayGetString(zombie_miss_slash, i, buffer, charsmax(buffer))
1430 engfunc(EngFunc_PrecacheSound, buffer)
1431 }
1432 for (i = 0; i < ArraySize(zombie_miss_wall); i++)
1433 {
1434 ArrayGetString(zombie_miss_wall, i, buffer, charsmax(buffer))
1435 engfunc(EngFunc_PrecacheSound, buffer)
1436 }
1437 for (i = 0; i < ArraySize(zombie_hit_normal); i++)
1438 {
1439 ArrayGetString(zombie_hit_normal, i, buffer, charsmax(buffer))
1440 engfunc(EngFunc_PrecacheSound, buffer)
1441 }
1442 for (i = 0; i < ArraySize(zombie_hit_stab); i++)
1443 {
1444 ArrayGetString(zombie_hit_stab, i, buffer, charsmax(buffer))
1445 engfunc(EngFunc_PrecacheSound, buffer)
1446 }
1447 for (i = 0; i < ArraySize(zombie_idle); i++)
1448 {
1449 ArrayGetString(zombie_idle, i, buffer, charsmax(buffer))
1450 engfunc(EngFunc_PrecacheSound, buffer)
1451 }
1452 for (i = 0; i < ArraySize(zombie_idle_last); i++)
1453 {
1454 ArrayGetString(zombie_idle_last, i, buffer, charsmax(buffer))
1455 engfunc(EngFunc_PrecacheSound, buffer)
1456 }
1457 for (i = 0; i < ArraySize(zombie_madness); i++)
1458 {
1459 ArrayGetString(zombie_madness, i, buffer, charsmax(buffer))
1460 engfunc(EngFunc_PrecacheSound, buffer)
1461 }
1462 for (i = 0; i < ArraySize(sound_nemesis); i++)
1463 {
1464 ArrayGetString(sound_nemesis, i, buffer, charsmax(buffer))
1465 engfunc(EngFunc_PrecacheSound, buffer)
1466 }
1467 for (i = 0; i < ArraySize(sound_assassin); i++)
1468 {
1469 ArrayGetString(sound_assassin, i, buffer, charsmax(buffer))
1470 engfunc(EngFunc_PrecacheSound, buffer)
1471 }
1472 for (i = 0; i < ArraySize(sound_survivor); i++)
1473 {
1474 ArrayGetString(sound_survivor, i, buffer, charsmax(buffer))
1475 engfunc(EngFunc_PrecacheSound, buffer)
1476 }
1477 for (i = 0; i < ArraySize(sound_sniper); i++)
1478 {
1479 ArrayGetString(sound_sniper, i, buffer, charsmax(buffer))
1480 engfunc(EngFunc_PrecacheSound, buffer)
1481 }
1482 for (i = 0; i < ArraySize(sound_swarm); i++)
1483 {
1484 ArrayGetString(sound_swarm, i, buffer, charsmax(buffer))
1485 engfunc(EngFunc_PrecacheSound, buffer)
1486 }
1487 for (i = 0; i < ArraySize(sound_multi); i++)
1488 {
1489 ArrayGetString(sound_multi, i, buffer, charsmax(buffer))
1490 engfunc(EngFunc_PrecacheSound, buffer)
1491 }
1492 for (i = 0; i < ArraySize(sound_plague); i++)
1493 {
1494 ArrayGetString(sound_plague, i, buffer, charsmax(buffer))
1495 engfunc(EngFunc_PrecacheSound, buffer)
1496 }
1497 for (i = 0; i < ArraySize(sound_armageddon); i++)
1498 {
1499 ArrayGetString(sound_armageddon, i, buffer, charsmax(buffer))
1500 engfunc(EngFunc_PrecacheSound, buffer)
1501 }
1502 for (i = 0; i < ArraySize(sound_apocalypse); i++)
1503 {
1504 ArrayGetString(sound_apocalypse, i, buffer, charsmax(buffer))
1505 engfunc(EngFunc_PrecacheSound, buffer)
1506 }
1507 for (i = 0; i < ArraySize(sound_nightmare); i++)
1508 {
1509 ArrayGetString(sound_nightmare, i, buffer, charsmax(buffer))
1510 engfunc(EngFunc_PrecacheSound, buffer)
1511 }
1512 for (i = 0; i < ArraySize(grenade_infect); i++)
1513 {
1514 ArrayGetString(grenade_infect, i, buffer, charsmax(buffer))
1515 engfunc(EngFunc_PrecacheSound, buffer)
1516 }
1517 for (i = 0; i < ArraySize(grenade_infect_player); i++)
1518 {
1519 ArrayGetString(grenade_infect_player, i, buffer, charsmax(buffer))
1520 engfunc(EngFunc_PrecacheSound, buffer)
1521 }
1522 for (i = 0; i < ArraySize(grenade_fire); i++)
1523 {
1524 ArrayGetString(grenade_fire, i, buffer, charsmax(buffer))
1525 engfunc(EngFunc_PrecacheSound, buffer)
1526 }
1527 for (i = 0; i < ArraySize(grenade_fire_player); i++)
1528 {
1529 ArrayGetString(grenade_fire_player, i, buffer, charsmax(buffer))
1530 engfunc(EngFunc_PrecacheSound, buffer)
1531 }
1532 for (i = 0; i < ArraySize(grenade_frost); i++)
1533 {
1534 ArrayGetString(grenade_frost, i, buffer, charsmax(buffer))
1535 engfunc(EngFunc_PrecacheSound, buffer)
1536 }
1537 for (i = 0; i < ArraySize(grenade_frost_player); i++)
1538 {
1539 ArrayGetString(grenade_frost_player, i, buffer, charsmax(buffer))
1540 engfunc(EngFunc_PrecacheSound, buffer)
1541 }
1542 for (i = 0; i < ArraySize(grenade_frost_break); i++)
1543 {
1544 ArrayGetString(grenade_frost_break, i, buffer, charsmax(buffer))
1545 engfunc(EngFunc_PrecacheSound, buffer)
1546 }
1547 for (i = 0; i < ArraySize(grenade_flare); i++)
1548 {
1549 ArrayGetString(grenade_flare, i, buffer, charsmax(buffer))
1550 engfunc(EngFunc_PrecacheSound, buffer)
1551 }
1552 for (i = 0; i < ArraySize(sound_antidote); i++)
1553 {
1554 ArrayGetString(sound_antidote, i, buffer, charsmax(buffer))
1555 engfunc(EngFunc_PrecacheSound, buffer)
1556 }
1557 for (i = 0; i < ArraySize(sound_thunder); i++)
1558 {
1559 ArrayGetString(sound_thunder, i, buffer, charsmax(buffer))
1560 engfunc(EngFunc_PrecacheSound, buffer)
1561 }
1562
1563 // Ambience Sounds
1564 if (g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION])
1565 {
1566 for (i = 0; i < ArraySize(sound_ambience1); i++)
1567 {
1568 ArrayGetString(sound_ambience1, i, buffer, charsmax(buffer))
1569
1570 if (ArrayGetCell(sound_ambience1_ismp3, i))
1571 {
1572 format(buffer, charsmax(buffer), "sound/%s", buffer)
1573 engfunc(EngFunc_PrecacheGeneric, buffer)
1574 }
1575 else
1576 {
1577 engfunc(EngFunc_PrecacheSound, buffer)
1578 }
1579 }
1580 }
1581 if (g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS])
1582 {
1583 for (i = 0; i < ArraySize(sound_ambience2); i++)
1584 {
1585 ArrayGetString(sound_ambience2, i, buffer, charsmax(buffer))
1586
1587 if (ArrayGetCell(sound_ambience2_ismp3, i))
1588 {
1589 format(buffer, charsmax(buffer), "sound/%s", buffer)
1590 engfunc(EngFunc_PrecacheGeneric, buffer)
1591 }
1592 else
1593 {
1594 engfunc(EngFunc_PrecacheSound, buffer)
1595 }
1596 }
1597 }
1598 if (g_ambience_sounds[AMBIENCE_SOUNDS_ASSASSIN])
1599 {
1600 for (i = 0; i < ArraySize(sound_ambience6); i++)
1601 {
1602 ArrayGetString(sound_ambience6, i, buffer, charsmax(buffer))
1603
1604 if (ArrayGetCell(sound_ambience6_ismp3, i))
1605 {
1606 format(buffer, charsmax(buffer), "sound/%s", buffer)
1607 engfunc(EngFunc_PrecacheGeneric, buffer)
1608 }
1609 else
1610 {
1611 engfunc(EngFunc_PrecacheSound, buffer)
1612 }
1613 }
1614 }
1615 if (g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR])
1616 {
1617 for (i = 0; i < ArraySize(sound_ambience3); i++)
1618 {
1619 ArrayGetString(sound_ambience3, i, buffer, charsmax(buffer))
1620
1621 if (ArrayGetCell(sound_ambience3_ismp3, i))
1622 {
1623 format(buffer, charsmax(buffer), "sound/%s", buffer)
1624 engfunc(EngFunc_PrecacheGeneric, buffer)
1625 }
1626 else
1627 {
1628 engfunc(EngFunc_PrecacheSound, buffer)
1629 }
1630 }
1631 }
1632 if (g_ambience_sounds[AMBIENCE_SOUNDS_SNIPER])
1633 {
1634 for (i = 0; i < ArraySize(sound_ambience5); i++)
1635 {
1636 ArrayGetString(sound_ambience5, i, buffer, charsmax(buffer))
1637
1638 if (ArrayGetCell(sound_ambience5_ismp3, i))
1639 {
1640 format(buffer, charsmax(buffer), "sound/%s", buffer)
1641 engfunc(EngFunc_PrecacheGeneric, buffer)
1642 }
1643 else
1644 {
1645 engfunc(EngFunc_PrecacheSound, buffer)
1646 }
1647 }
1648 }
1649 if (g_ambience_sounds[AMBIENCE_SOUNDS_SWARM])
1650 {
1651 for (i = 0; i < ArraySize(sound_ambience4); i++)
1652 {
1653 ArrayGetString(sound_ambience4, i, buffer, charsmax(buffer))
1654
1655 if (ArrayGetCell(sound_ambience4_ismp3, i))
1656 {
1657 format(buffer, charsmax(buffer), "sound/%s", buffer)
1658 engfunc(EngFunc_PrecacheGeneric, buffer)
1659 }
1660 else
1661 {
1662 engfunc(EngFunc_PrecacheSound, buffer)
1663 }
1664 }
1665 }
1666 if (g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE])
1667 {
1668 for (i = 0; i < ArraySize(sound_ambience5); i++)
1669 {
1670 ArrayGetString(sound_ambience5, i, buffer, charsmax(buffer))
1671
1672 if (ArrayGetCell(sound_ambience5_ismp3, i))
1673 {
1674 format(buffer, charsmax(buffer), "sound/%s", buffer)
1675 engfunc(EngFunc_PrecacheGeneric, buffer)
1676 }
1677 else
1678 {
1679 engfunc(EngFunc_PrecacheSound, buffer)
1680 }
1681 }
1682 }
1683 if (g_ambience_sounds[AMBIENCE_SOUNDS_ARMAGEDDON])
1684 {
1685 for (i = 0; i < ArraySize(sound_ambience8); i++)
1686 {
1687 ArrayGetString(sound_ambience8, i, buffer, charsmax(buffer))
1688
1689 if (ArrayGetCell(sound_ambience8_ismp3, i))
1690 {
1691 format(buffer, charsmax(buffer), "sound/%s", buffer)
1692 engfunc(EngFunc_PrecacheGeneric, buffer)
1693 }
1694 else
1695 {
1696 engfunc(EngFunc_PrecacheSound, buffer)
1697 }
1698 }
1699 }
1700 if (g_ambience_sounds[AMBIENCE_SOUNDS_APOCALYPSE])
1701 {
1702 for (i = 0; i < ArraySize(sound_ambience9); i++)
1703 {
1704 ArrayGetString(sound_ambience9, i, buffer, charsmax(buffer))
1705
1706 if (ArrayGetCell(sound_ambience9_ismp3, i))
1707 {
1708 format(buffer, charsmax(buffer), "sound/%s", buffer)
1709 engfunc(EngFunc_PrecacheGeneric, buffer)
1710 }
1711 else
1712 {
1713 engfunc(EngFunc_PrecacheSound, buffer)
1714 }
1715 }
1716 }
1717 if (g_ambience_sounds[AMBIENCE_SOUNDS_NIGHTMARE])
1718 {
1719 for (i = 0; i < ArraySize(sound_ambience10); i++)
1720 {
1721 ArrayGetString(sound_ambience10, i, buffer, charsmax(buffer))
1722
1723 if (ArrayGetCell(sound_ambience10_ismp3, i))
1724 {
1725 format(buffer, charsmax(buffer), "sound/%s", buffer)
1726 engfunc(EngFunc_PrecacheGeneric, buffer)
1727 }
1728 else
1729 {
1730 engfunc(EngFunc_PrecacheSound, buffer)
1731 }
1732 }
1733 }
1734
1735 // CS sounds (just in case)
1736 engfunc(EngFunc_PrecacheSound, sound_flashlight)
1737 engfunc(EngFunc_PrecacheSound, sound_buyammo)
1738 engfunc(EngFunc_PrecacheSound, sound_armorhit)
1739
1740 new ent
1741
1742 // Fake Hostage (to force round ending)
1743 ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "hostage_entity"))
1744 if (pev_valid(ent))
1745 {
1746 engfunc(EngFunc_SetOrigin, ent, Float:{8192.0,8192.0,8192.0})
1747 dllfunc(DLLFunc_Spawn, ent)
1748 }
1749
1750 // Weather/ambience effects
1751 if (g_ambience_fog)
1752 {
1753 ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "env_fog"))
1754 if (pev_valid(ent))
1755 {
1756 fm_set_kvd(ent, "density", g_fog_density, "env_fog")
1757 fm_set_kvd(ent, "rendercolor", g_fog_color, "env_fog")
1758 }
1759 }
1760 if (g_ambience_rain) engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "env_rain"))
1761 if (g_ambience_snow) engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "env_snow"))
1762
1763 // Custom buyzone for all players
1764 g_buyzone_ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "func_buyzone"))
1765 if (pev_valid(g_buyzone_ent))
1766 {
1767 dllfunc(DLLFunc_Spawn, g_buyzone_ent)
1768 set_pev(g_buyzone_ent, pev_solid, SOLID_NOT)
1769 }
1770
1771 // Prevent some entities from spawning
1772 g_fwSpawn = register_forward(FM_Spawn, "fw_Spawn")
1773
1774 // Prevent hostage sounds from being precached
1775 g_fwPrecacheSound = register_forward(FM_PrecacheSound, "fw_PrecacheSound")
1776}
1777
1778public plugin_init()
1779{
1780 // Plugin disabled?
1781 if (!g_pluginenabled) return;
1782
1783 // No zombie classes?
1784 if (!g_zclass_i) set_fail_state("No zombie classes loaded!")
1785
1786 // Language files
1787 register_dictionary("zombie_plague.txt")
1788
1789 // Events
1790 register_event("HLTV", "event_round_start", "a", "1=0", "2=0")
1791 register_event("StatusValue", "event_show_status", "be", "1=2", "2!0")
1792 register_event("StatusValue", "event_hide_status", "be", "1=1", "2=0")
1793 register_logevent("logevent_round_start",2, "1=Round_Start")
1794 register_logevent("logevent_round_end", 2, "1=Round_End")
1795 register_event("AmmoX", "event_ammo_x", "be")
1796 if (g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION] || g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS] || g_ambience_sounds[AMBIENCE_SOUNDS_ASSASSIN] || g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR] || g_ambience_sounds[AMBIENCE_SOUNDS_SNIPER]
1797 || g_ambience_sounds[AMBIENCE_SOUNDS_SWARM] || g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE] || g_ambience_sounds[AMBIENCE_SOUNDS_ARMAGEDDON] || g_ambience_sounds[AMBIENCE_SOUNDS_APOCALYPSE] || g_ambience_sounds[AMBIENCE_SOUNDS_NIGHTMARE])
1798 register_event("30", "event_intermission", "a")
1799
1800 // HAM Forwards
1801 RegisterHam(Ham_Spawn, "player", "fw_PlayerSpawn_Post", 1)
1802 RegisterHam(Ham_Killed, "player", "fw_PlayerKilled")
1803 RegisterHam(Ham_Killed, "player", "fw_PlayerKilled_Post", 1)
1804 RegisterHam(Ham_TakeDamage, "player", "fw_TakeDamage")
1805 RegisterHam(Ham_TakeDamage, "player", "fw_TakeDamage_Post", 1)
1806 RegisterHam(Ham_TraceAttack, "player", "fw_TraceAttack")
1807 RegisterHam(Ham_Player_ResetMaxSpeed, "player", "fw_ResetMaxSpeed_Post", 1)
1808 RegisterHam(Ham_Use, "func_tank", "fw_UseStationary")
1809 RegisterHam(Ham_Use, "func_tankmortar", "fw_UseStationary")
1810 RegisterHam(Ham_Use, "func_tankrocket", "fw_UseStationary")
1811 RegisterHam(Ham_Use, "func_tanklaser", "fw_UseStationary")
1812 RegisterHam(Ham_Use, "func_tank", "fw_UseStationary_Post", 1)
1813 RegisterHam(Ham_Use, "func_tankmortar", "fw_UseStationary_Post", 1)
1814 RegisterHam(Ham_Use, "func_tankrocket", "fw_UseStationary_Post", 1)
1815 RegisterHam(Ham_Use, "func_tanklaser", "fw_UseStationary_Post", 1)
1816 RegisterHam(Ham_Use, "func_pushable", "fw_UsePushable")
1817 RegisterHam(Ham_Touch, "weaponbox", "fw_TouchWeapon")
1818 RegisterHam(Ham_Touch, "armoury_entity", "fw_TouchWeapon")
1819 RegisterHam(Ham_Touch, "weapon_shield", "fw_TouchWeapon")
1820 RegisterHam(Ham_AddPlayerItem, "player", "fw_AddPlayerItem")
1821 for (new i = 1; i < sizeof WEAPONENTNAMES; i++)
1822 if (WEAPONENTNAMES[i][0]) RegisterHam(Ham_Item_Deploy, WEAPONENTNAMES[i], "fw_Item_Deploy_Post", 1)
1823
1824 // FM Forwards
1825 register_forward(FM_ClientDisconnect, "fw_ClientDisconnect")
1826 register_forward(FM_ClientDisconnect, "fw_ClientDisconnect_Post", 1)
1827 register_forward(FM_ClientKill, "fw_ClientKill")
1828 register_forward(FM_EmitSound, "fw_EmitSound")
1829 if (!g_handle_models_on_separate_ent) register_forward(FM_SetClientKeyValue, "fw_SetClientKeyValue")
1830 register_forward(FM_ClientUserInfoChanged, "fw_ClientUserInfoChanged")
1831 register_forward(FM_GetGameDescription, "fw_GetGameDescription")
1832 register_forward(FM_SetModel, "fw_SetModel")
1833 RegisterHam(Ham_Think, "grenade", "fw_ThinkGrenade")
1834 register_forward(FM_CmdStart, "fw_CmdStart")
1835 register_forward(FM_PlayerPreThink, "fw_PlayerPreThink")
1836 unregister_forward(FM_Spawn, g_fwSpawn)
1837 unregister_forward(FM_PrecacheSound, g_fwPrecacheSound)
1838
1839 // Client commands
1840 register_clcmd("say zpmenu", "clcmd_saymenu")
1841 register_clcmd("say /zpmenu", "clcmd_saymenu")
1842 register_clcmd("say unstuck", "clcmd_sayunstuck")
1843 register_clcmd("say /unstuck", "clcmd_sayunstuck")
1844 register_clcmd("nightvision", "clcmd_nightvision")
1845 register_clcmd("drop", "clcmd_drop")
1846 register_clcmd("buyammo1", "clcmd_buyammo")
1847 register_clcmd("buyammo2", "clcmd_buyammo")
1848 register_clcmd("chooseteam", "clcmd_changeteam")
1849 register_clcmd("jointeam", "clcmd_changeteam")
1850
1851 // Menus
1852 register_menu("Game Menu", KEYSMENU, "menu_game")
1853 register_menu("Buy Menu 1", KEYSMENU, "menu_buy1")
1854 register_menu("Buy Menu 2", KEYSMENU, "menu_buy2")
1855 register_menu("Mod Info", KEYSMENU, "menu_info")
1856 register_menu("Admin Menu", KEYSMENU, "menu_admin")
1857 register_menu("Admin Modes Menu", KEYSMENU, "menu_modes_admin")
1858
1859 // CS Buy Menus (to prevent zombies/survivor from buying)
1860 register_menucmd(register_menuid("#Buy", 1), 511, "menu_cs_buy")
1861 register_menucmd(register_menuid("BuyPistol", 1), 511, "menu_cs_buy")
1862 register_menucmd(register_menuid("BuyShotgun", 1), 511, "menu_cs_buy")
1863 register_menucmd(register_menuid("BuySub", 1), 511, "menu_cs_buy")
1864 register_menucmd(register_menuid("BuyRifle", 1), 511, "menu_cs_buy")
1865 register_menucmd(register_menuid("BuyMachine", 1), 511, "menu_cs_buy")
1866 register_menucmd(register_menuid("BuyItem", 1), 511, "menu_cs_buy")
1867 register_menucmd(-28, 511, "menu_cs_buy")
1868 register_menucmd(-29, 511, "menu_cs_buy")
1869 register_menucmd(-30, 511, "menu_cs_buy")
1870 register_menucmd(-32, 511, "menu_cs_buy")
1871 register_menucmd(-31, 511, "menu_cs_buy")
1872 register_menucmd(-33, 511, "menu_cs_buy")
1873 register_menucmd(-34, 511, "menu_cs_buy")
1874
1875 // Admin commands
1876 register_concmd("zp_zombie", "cmd_zombie", _, "<target> - Turn someone into a Zombie", 0)
1877 register_concmd("zp_human", "cmd_human", _, "<target> - Turn someone back to Human", 0)
1878 register_concmd("zp_nemesis", "cmd_nemesis", _, "<target> - Turn someone into a Nemesis", 0)
1879 register_concmd("zp_assassin", "cmd_assassin", _, "<target> - Turn someone into an Assassin", 0)
1880 register_concmd("zp_survivor", "cmd_survivor", _, "<target> - Turn someone into a Survivor", 0)
1881 register_concmd("zp_sniper", "cmd_sniper", _, "<target> - Turn someone into a Sniper", 0)
1882 register_concmd("zp_respawn", "cmd_respawn", _, "<target> - Respawn someone", 0)
1883 register_concmd("zp_swarm", "cmd_swarm", _, " - Start Swarm Mode", 0)
1884 register_concmd("zp_multi", "cmd_multi", _, " - Start Multi Infection", 0)
1885 register_concmd("zp_plague", "cmd_plague", _, " - Start Plague Mode", 0)
1886 register_concmd("zp_armageddon", "cmd_armageddon", _, " - Start Armageddon Mode", 0)
1887 register_concmd("zp_apocalypse", "cmd_apocalypse", _, " - Start Apocalypse Mode", 0)
1888 register_concmd("zp_nightmare", "cmd_nightmare", _, " - Start Nightmare Mode", 0)
1889
1890 // Message IDs
1891 g_msgScoreInfo = get_user_msgid("ScoreInfo")
1892 g_msgTeamInfo = get_user_msgid("TeamInfo")
1893 g_msgDeathMsg = get_user_msgid("DeathMsg")
1894 g_msgScoreAttrib = get_user_msgid("ScoreAttrib")
1895 g_msgSetFOV = get_user_msgid("SetFOV")
1896 g_msgScreenFade = get_user_msgid("ScreenFade")
1897 g_msgScreenShake = get_user_msgid("ScreenShake")
1898 g_msgNVGToggle = get_user_msgid("NVGToggle")
1899 g_msgFlashlight = get_user_msgid("Flashlight")
1900 g_msgFlashBat = get_user_msgid("FlashBat")
1901 g_msgAmmoPickup = get_user_msgid("AmmoPickup")
1902 g_msgDamage = get_user_msgid("Damage")
1903 g_msgHideWeapon = get_user_msgid("HideWeapon")
1904 g_msgCrosshair = get_user_msgid("Crosshair")
1905 g_msgSayText = get_user_msgid("SayText")
1906 g_msgCurWeapon = get_user_msgid("CurWeapon")
1907
1908 // Message hooks
1909 register_message(g_msgCurWeapon, "message_cur_weapon")
1910 register_message(get_user_msgid("Money"), "message_money")
1911 register_message(get_user_msgid("Health"), "message_health")
1912 register_message(g_msgFlashBat, "message_flashbat")
1913 register_message(g_msgScreenFade, "message_screenfade")
1914 register_message(g_msgNVGToggle, "message_nvgtoggle")
1915 if (g_handle_models_on_separate_ent) register_message(get_user_msgid("ClCorpse"), "message_clcorpse")
1916 register_message(get_user_msgid("WeapPickup"), "message_weappickup")
1917 register_message(g_msgAmmoPickup, "message_ammopickup")
1918 register_message(get_user_msgid("Scenario"), "message_scenario")
1919 register_message(get_user_msgid("HostagePos"), "message_hostagepos")
1920 register_message(get_user_msgid("TextMsg"), "message_textmsg")
1921 register_message(get_user_msgid("SendAudio"), "message_sendaudio")
1922 register_message(get_user_msgid("TeamScore"), "message_teamscore")
1923 register_message(g_msgTeamInfo, "message_teaminfo")
1924
1925 // CVARS - General Purpose
1926 cvar_warmup = register_cvar("zp_delay", "10")
1927 cvar_lighting = register_cvar("zp_lighting", "a")
1928 cvar_thunder = register_cvar("zp_thunderclap", "90")
1929 cvar_triggered = register_cvar("zp_triggered_lights", "1")
1930 cvar_removedoors = register_cvar("zp_remove_doors", "0")
1931 cvar_blockpushables = register_cvar("zp_blockuse_pushables", "1")
1932 cvar_blocksuicide = register_cvar("zp_block_suicide", "1")
1933 cvar_randspawn = register_cvar("zp_random_spawn", "1")
1934 cvar_respawnworldspawnkill = register_cvar("zp_respawn_on_worldspawn_kill", "1")
1935 cvar_removedropped = register_cvar("zp_remove_dropped", "0")
1936 cvar_removemoney = register_cvar("zp_remove_money", "1")
1937 cvar_buycustom = register_cvar("zp_buy_custom", "1")
1938 cvar_buyzonetime = register_cvar("zp_buyzone_time", "0.0")
1939 cvar_randweapons = register_cvar("zp_random_weapons", "0")
1940 cvar_adminmodelshuman = register_cvar("zp_admin_models_human", "1")
1941 cvar_adminknifemodelshuman = register_cvar("zp_admin_knife_models_human", "0")
1942 cvar_adminmodelszombie = register_cvar("zp_admin_models_zombie", "1")
1943 cvar_adminknifemodelszombie = register_cvar("zp_admin_knife_models_zombie", "0")
1944 cvar_zclasses = register_cvar("zp_zombie_classes", "1")
1945 cvar_statssave = register_cvar("zp_stats_save", "1")
1946 cvar_startammopacks = register_cvar("zp_starting_ammo_packs", "5")
1947 cvar_preventconsecutive = register_cvar("zp_prevent_consecutive_modes", "1")
1948 cvar_keephealthondisconnect = register_cvar("zp_keep_health_on_disconnect", "1")
1949 cvar_huddisplay = register_cvar("zp_hud_display", "1")
1950 cvar_aiminfo = register_cvar("zp_aim_info", "1")
1951 cvar_dmg_while_freeze = register_cvar("zp_dmg_while_frost", "1")
1952
1953 // CVARS - Deathmatch
1954 cvar_deathmatch = register_cvar("zp_deathmatch", "0")
1955 cvar_spawndelay = register_cvar("zp_spawn_delay", "5")
1956 cvar_spawnprotection = register_cvar("zp_spawn_protection", "5")
1957 cvar_respawnonsuicide = register_cvar("zp_respawn_on_suicide", "0")
1958 cvar_respawnafterlast = register_cvar("zp_respawn_after_last_human", "1")
1959 cvar_allowrespawninfection = register_cvar("zp_infection_allow_respawn", "1")
1960 cvar_allowrespawnnem = register_cvar("zp_nem_allow_respawn", "0")
1961 cvar_allowrespawnassa = register_cvar("zp_assa_allow_respawn", "0")
1962 cvar_allowrespawnsurv = register_cvar("zp_surv_allow_respawn", "0")
1963 cvar_allowrespawnsni = register_cvar("zp_sni_allow_respawn", "0")
1964 cvar_allowrespawnswarm = register_cvar("zp_swarm_allow_respawn", "0")
1965 cvar_allowrespawnplague = register_cvar("zp_plague_allow_respawn", "0")
1966 cvar_allowrespawnarmage = register_cvar("zp_armageddon_allow_respawn", "0")
1967 cvar_allowrespawnapoc = register_cvar("zp_apocalypse_allow_respawn", "0")
1968 cvar_allowrespawnnight = register_cvar("zp_nightmare_allow_respawn", "0")
1969 cvar_respawnzomb = register_cvar("zp_respawn_zombies", "1")
1970 cvar_respawnhum = register_cvar("zp_respawn_humans", "1")
1971 cvar_respawnnem = register_cvar("zp_respawn_nemesis", "1")
1972 cvar_respawnassa = register_cvar("zp_respawn_assassins", "0")
1973 cvar_respawnsurv = register_cvar("zp_respawn_survivors", "1")
1974 cvar_respawnsni = register_cvar("zp_respawn_snipers", "0")
1975
1976 // CVARS - Extra Items
1977 cvar_extraitems = register_cvar("zp_extra_items", "1")
1978 cvar_extraweapons = register_cvar("zp_extra_weapons", "1")
1979 cvar_extranvision = register_cvar("zp_extra_nvision", "1")
1980 cvar_extraantidote = register_cvar("zp_extra_antidote", "1")
1981 cvar_antidotelimit = register_cvar("zp_extra_antidote_limit", "999")
1982 cvar_extramadness = register_cvar("zp_extra_madness", "1")
1983 cvar_madnesslimit = register_cvar("zp_extra_madness_limit", "999")
1984 cvar_madnessduration = register_cvar("zp_extra_madness_duration", "5.0")
1985 cvar_extrainfbomb = register_cvar("zp_extra_infbomb", "1")
1986 cvar_infbomblimit = register_cvar("zp_extra_infbomb_limit", "999")
1987
1988 // CVARS - Flashlight and Nightvision
1989 cvar_nvggive = register_cvar("zp_nvg_give", "1")
1990 cvar_customnvg = register_cvar("zp_nvg_custom", "1")
1991 cvar_nvgsize = register_cvar("zp_nvg_size", "80")
1992 cvar_nvgcolor[0] = register_cvar("zp_nvg_color_R", "0")
1993 cvar_nvgcolor[1] = register_cvar("zp_nvg_color_G", "150")
1994 cvar_nvgcolor[2] = register_cvar("zp_nvg_color_B", "0")
1995 cvar_humnvgcolor[0] = register_cvar("zp_nvg_hum_color_R", "0")
1996 cvar_humnvgcolor[1] = register_cvar("zp_nvg_hum_color_G", "150")
1997 cvar_humnvgcolor[2] = register_cvar("zp_nvg_hum_color_B", "0")
1998 cvar_nemnvgcolor[0] = register_cvar("zp_nvg_nem_color_R", "150")
1999 cvar_nemnvgcolor[1] = register_cvar("zp_nvg_nem_color_G", "0")
2000 cvar_nemnvgcolor[2] = register_cvar("zp_nvg_nem_color_B", "0")
2001 cvar_assanvgcolor[0] = register_cvar("zp_nvg_assa_color_R", "0")
2002 cvar_assanvgcolor[1] = register_cvar("zp_nvg_assa_color_G", "150")
2003 cvar_assanvgcolor[2] = register_cvar("zp_nvg_assa_color_B", "90")
2004 cvar_customflash = register_cvar("zp_flash_custom", "0")
2005 cvar_flashsize = register_cvar("zp_flash_size", "10")
2006 cvar_flashdrain = register_cvar("zp_flash_drain", "1")
2007 cvar_flashcharge = register_cvar("zp_flash_charge", "5")
2008 cvar_flashdist = register_cvar("zp_flash_distance", "1000")
2009 cvar_flashcolor[0] = register_cvar("zp_flash_color_R", "100")
2010 cvar_flashcolor[1] = register_cvar("zp_flash_color_G", "100")
2011 cvar_flashcolor[2] = register_cvar("zp_flash_color_B", "100")
2012 cvar_flashshowall = register_cvar("zp_flash_show_all", "1")
2013
2014 // CVARS - Knockback
2015 cvar_knockback = register_cvar("zp_knockback", "0")
2016 cvar_knockbackdamage = register_cvar("zp_knockback_damage", "1")
2017 cvar_knockbackpower = register_cvar("zp_knockback_power", "1")
2018 cvar_knockbackzvel = register_cvar("zp_knockback_zvel", "0")
2019 cvar_knockbackducking = register_cvar("zp_knockback_ducking", "0.25")
2020 cvar_knockbackdist = register_cvar("zp_knockback_distance", "500")
2021 cvar_nemknockback = register_cvar("zp_knockback_nemesis", "0.25")
2022 cvar_assaknockback = register_cvar("zp_knockback_assassin", "0.7")
2023
2024 // CVARS - Leap
2025 cvar_leapzombies = register_cvar("zp_leap_zombies", "0")
2026 cvar_leapzombiesforce = register_cvar("zp_leap_zombies_force", "500")
2027 cvar_leapzombiesheight = register_cvar("zp_leap_zombies_height", "300")
2028 cvar_leapzombiescooldown = register_cvar("zp_leap_zombies_cooldown", "5.0")
2029 cvar_leapnemesis = register_cvar("zp_leap_nemesis", "1")
2030 cvar_leapnemesisforce = register_cvar("zp_leap_nemesis_force", "500")
2031 cvar_leapnemesisheight = register_cvar("zp_leap_nemesis_height", "300")
2032 cvar_leapnemesiscooldown = register_cvar("zp_leap_nemesis_cooldown", "5.0")
2033 cvar_leapassassin = register_cvar("zp_leap_assassin", "0")
2034 cvar_leapassassinforce = register_cvar("zp_leap_assassin_force", "500")
2035 cvar_leapassassinheight = register_cvar("zp_leap_assassin_height", "300")
2036 cvar_leapassassincooldown = register_cvar("zp_leap_assassin_cooldown", "5.0")
2037 cvar_leapsurvivor = register_cvar("zp_leap_survivor", "0")
2038 cvar_leapsurvivorforce = register_cvar("zp_leap_survivor_force", "500")
2039 cvar_leapsurvivorheight = register_cvar("zp_leap_survivor_height", "300")
2040 cvar_leapsurvivorcooldown = register_cvar("zp_leap_survivor_cooldown", "5.0")
2041 cvar_leapsniper = register_cvar("zp_leap_sniper", "0")
2042 cvar_leapsniperforce = register_cvar("zp_leap_sniper_force", "500")
2043 cvar_leapsniperheight = register_cvar("zp_leap_sniper_height", "300")
2044 cvar_leapsnipercooldown = register_cvar("zp_leap_sniper_cooldown", "5.0")
2045
2046 // CVARS - Humans
2047 cvar_humanhp = register_cvar("zp_human_health", "100")
2048 cvar_humanlasthp = register_cvar("zp_human_last_extrahp", "0")
2049 cvar_humanspd = register_cvar("zp_human_speed", "240")
2050 cvar_humangravity = register_cvar("zp_human_gravity", "1.0")
2051 cvar_humanarmor = register_cvar("zp_human_armor_protect", "1")
2052 cvar_infammo = register_cvar("zp_human_unlimited_ammo", "0")
2053 cvar_ammodamage_human = register_cvar("zp_human_damage_reward", "500")
2054 cvar_fragskill = register_cvar("zp_human_frags_for_kill", "1")
2055
2056 // CVARS - Custom Grenades
2057 cvar_firegrenades = register_cvar("zp_fire_grenades", "1")
2058 cvar_fireduration = register_cvar("zp_fire_duration", "10")
2059 cvar_firedamage = register_cvar("zp_fire_damage", "5")
2060 cvar_fireslowdown = register_cvar("zp_fire_slowdown", "0.5")
2061 cvar_frostgrenades = register_cvar("zp_frost_grenades", "1")
2062 cvar_freezeduration = register_cvar("zp_frost_duration", "3")
2063 cvar_flaregrenades = register_cvar("zp_flare_grenades","1")
2064 cvar_flareduration = register_cvar("zp_flare_duration", "60")
2065 cvar_flaresize = register_cvar("zp_flare_size", "25")
2066 cvar_flarecolor = register_cvar("zp_flare_color", "0")
2067
2068 // CVARS - Zombies
2069 cvar_zombiefirsthp = register_cvar("zp_zombie_first_hp", "2.0")
2070 cvar_zombiearmor = register_cvar("zp_zombie_armor", "0.75")
2071 cvar_hitzones = register_cvar("zp_zombie_hitzones", "0")
2072 cvar_zombiebonushp = register_cvar("zp_zombie_infect_health", "100")
2073 cvar_zombiefov = register_cvar("zp_zombie_fov", "110")
2074 cvar_zombiesilent = register_cvar("zp_zombie_silent", "1")
2075 cvar_zombiepainfree = register_cvar("zp_zombie_painfree", "2")
2076 cvar_zombiebleeding = register_cvar("zp_zombie_bleeding", "1")
2077 cvar_ammoinfect = register_cvar("zp_zombie_infect_reward", "1")
2078 cvar_ammodamage_zombie = register_cvar("zp_zombie_damage_reward", "0")
2079 cvar_fragsinfect = register_cvar("zp_zombie_frags_for_infect", "1")
2080
2081 // CVARS - Special Effects
2082 cvar_infectionscreenfade = register_cvar("zp_infection_screenfade", "1")
2083 cvar_infectionscreenshake = register_cvar("zp_infection_screenshake", "1")
2084 cvar_infectionsparkle = register_cvar("zp_infection_sparkle", "1")
2085 cvar_infectiontracers = register_cvar("zp_infection_tracers", "1")
2086 cvar_infectionparticles = register_cvar("zp_infection_particles", "1")
2087 cvar_hudicons = register_cvar("zp_hud_icons", "1")
2088
2089 // CVARS - Nemesis
2090 cvar_nem = register_cvar("zp_nem_enabled", "1")
2091 cvar_nemchance = register_cvar("zp_nem_chance", "20")
2092 cvar_nemminplayers = register_cvar("zp_nem_min_players", "0")
2093 cvar_nemhp = register_cvar("zp_nem_health", "0")
2094 cvar_nembasehp = register_cvar("zp_nem_base_health", "0")
2095 cvar_nemspd = register_cvar("zp_nem_speed", "250")
2096 cvar_nemgravity = register_cvar("zp_nem_gravity", "0.5")
2097 cvar_nemdamage = register_cvar("zp_nem_damage", "250")
2098 cvar_nemglow = register_cvar("zp_nem_glow", "1")
2099 cvar_nemaura = register_cvar("zp_nem_aura", "1")
2100 cvar_nempainfree = register_cvar("zp_nem_painfree", "0")
2101 cvar_nemignorefrags = register_cvar("zp_nem_ignore_frags", "1")
2102 cvar_nemignoreammo = register_cvar("zp_nem_ignore_rewards", "1")
2103
2104 // CVARS - Assassin
2105 cvar_assa = register_cvar("zp_assa_enabled", "1")
2106 cvar_assachance = register_cvar("zp_assa_chance", "50")
2107 cvar_assaminplayers = register_cvar("zp_assa_min_players", "0")
2108 cvar_assahp = register_cvar("zp_assa_health", "25000")
2109 cvar_assabasehp = register_cvar("zp_assa_base_health", "0")
2110 cvar_assaspd = register_cvar("zp_assa_speed", "650")
2111 cvar_assagravity = register_cvar("zp_assa_gravity", "0.5")
2112 cvar_assadamage = register_cvar("zp_assa_damage", "250")
2113 cvar_assaglow = register_cvar("zp_assa_glow", "0")
2114 cvar_assaaura = register_cvar("zp_assa_aura", "0")
2115 cvar_assapainfree = register_cvar("zp_assa_painfree", "0")
2116 cvar_assaignorefrags = register_cvar("zp_assassin_ignore_frags", "1")
2117 cvar_assaignoreammo = register_cvar("zp_assassin_ignore_rewards", "1")
2118
2119 // CVARS - Survivor
2120 cvar_surv = register_cvar("zp_surv_enabled", "1")
2121 cvar_survchance = register_cvar("zp_surv_chance", "20")
2122 cvar_survminplayers = register_cvar("zp_surv_min_players", "0")
2123 cvar_survhp = register_cvar("zp_surv_health", "0")
2124 cvar_survbasehp = register_cvar("zp_surv_base_health", "0")
2125 cvar_survspd = register_cvar("zp_surv_speed", "230")
2126 cvar_survgravity = register_cvar("zp_surv_gravity", "1.25")
2127 cvar_survglow = register_cvar("zp_surv_glow", "1")
2128 cvar_survaura = register_cvar("zp_surv_aura", "1")
2129 cvar_survpainfree = register_cvar("zp_surv_painfree", "1")
2130 cvar_survignorefrags = register_cvar("zp_surv_ignore_frags", "1")
2131 cvar_survignoreammo = register_cvar("zp_surv_ignore_rewards", "1")
2132 cvar_survinfammo = register_cvar("zp_surv_unlimited_ammo", "2")
2133
2134 // CVARS - Sniper
2135 cvar_sni = register_cvar("zp_sni_enabled", "1")
2136 cvar_snichance = register_cvar("zp_sni_chance", "250")
2137 cvar_sniminplayers = register_cvar("zp_sni_min_players", "0")
2138 cvar_snihp = register_cvar("zp_sni_health", "3000")
2139 cvar_snibasehp = register_cvar("zp_sni_base_health", "0")
2140 cvar_snispd = register_cvar("zp_sni_speed", "230")
2141 cvar_snigravity = register_cvar("zp_sni_gravity", "1.25")
2142 cvar_sniglow = register_cvar("zp_sni_glow", "1")
2143 cvar_sniaura = register_cvar("zp_sni_aura", "0")
2144 cvar_snipainfree = register_cvar("zp_sni_painfree", "0")
2145 cvar_snipignorefrags = register_cvar("zp_sniper_ignore_frags", "1")
2146 cvar_snipignoreammo = register_cvar("zp_sniper_ignore_rewards", "1")
2147 cvar_snidamage = register_cvar("zp_sni_damage", "4500")
2148 cvar_sniinfammo = register_cvar("zp_sni_unlimited_ammo", "1")
2149
2150 // CVARS - Swarm Mode
2151 cvar_swarm = register_cvar("zp_swarm_enabled", "1")
2152 cvar_swarmchance = register_cvar("zp_swarm_chance", "20")
2153 cvar_swarmminplayers = register_cvar("zp_swarm_min_players", "0")
2154
2155 // CVARS - Multi Infection
2156 cvar_multi = register_cvar("zp_multi_enabled", "1")
2157 cvar_multichance = register_cvar("zp_multi_chance", "20")
2158 cvar_multiminplayers = register_cvar("zp_multi_min_players", "0")
2159 cvar_multiratio = register_cvar("zp_multi_ratio", "0.15")
2160
2161 // CVARS - Plague Mode
2162 cvar_plague = register_cvar("zp_plague_enabled", "1")
2163 cvar_plaguechance = register_cvar("zp_plague_chance", "30")
2164 cvar_plagueminplayers = register_cvar("zp_plague_min_players", "0")
2165 cvar_plagueratio = register_cvar("zp_plague_ratio", "0.5")
2166 cvar_plaguenemnum = register_cvar("zp_plague_nem_number", "1")
2167 cvar_plaguenemhpmulti = register_cvar("zp_plague_nem_hp_multi", "0.5")
2168 cvar_plaguesurvnum = register_cvar("zp_plague_surv_number", "1")
2169 cvar_plaguesurvhpmulti = register_cvar("zp_plague_surv_hp_multi", "0.5")
2170
2171 // CVARS - Armageddon Mode
2172 cvar_armage = register_cvar("zp_armageddon_enabled", "1")
2173 cvar_armagechance = register_cvar("zp_armageddon_chance", "25")
2174 cvar_armageminplayers = register_cvar("zp_armageddon_min_players", "0")
2175 cvar_armageratio = register_cvar("zp_armageddon_ratio", "0.5")
2176 cvar_armagenemhpmulti = register_cvar("zp_armageddon_nemesis_hp_multi", "0.5")
2177 cvar_armagesurvhpmulti = register_cvar("zp_armageddon_survivor_hp_multi", "0.5")
2178
2179 // CVARS - Apocalypse Mode
2180 cvar_apoc = register_cvar("zp_apocalypse_enabled", "1")
2181 cvar_apocchance = register_cvar("zp_apocalypse_chance", "25")
2182 cvar_apocminplayers = register_cvar("zp_apocalypse_min_players", "0")
2183 cvar_apocratio = register_cvar("zp_apocalypse_ratio", "0.5")
2184 cvar_apocassahpmulti = register_cvar("zp_apocalypse_assassin_hp_multi", "0.5")
2185 cvar_apocsniphpmulti = register_cvar("zp_apocalypse_sniper_hp_multi", "0.5")
2186
2187 // CVARS - Nightmare Mode
2188 cvar_night = register_cvar("zp_nightmare_enabled", "1")
2189 cvar_nightchance = register_cvar("zp_nightmare_chance", "25")
2190 cvar_nightminplayers = register_cvar("zp_nightmare_min_players", "0")
2191 cvar_nightratio = register_cvar("zp_nightmare_ratio", "0.5")
2192 cvar_nightassahpmulti = register_cvar("zp_nightmare_assassin_hp_multi", "0.5")
2193 cvar_nightsniphpmulti = register_cvar("zp_nightmare_sniper_hp_multi", "0.5")
2194 cvar_nightnemhpmulti = register_cvar("zp_nightmare_nemesis_hp_multi", "0.5")
2195 cvar_nightsurvhpmulti = register_cvar("zp_nightmare_survivor_hp_multi", "0.5")
2196
2197 // CVARS - Others
2198 cvar_logcommands = register_cvar("zp_logcommands", "1")
2199 cvar_showactivity = get_cvar_pointer("amx_show_activity")
2200 cvar_botquota = get_cvar_pointer("bot_quota")
2201 register_cvar("zp_version", PLUGIN_VERSION, FCVAR_SERVER|FCVAR_SPONLY)
2202 set_cvar_string("zp_version", PLUGIN_VERSION)
2203
2204 // Custom Forwards
2205 g_fwRoundStart = CreateMultiForward("zp_round_started", ET_IGNORE, FP_CELL, FP_CELL)
2206 g_fwRoundEnd = CreateMultiForward("zp_round_ended", ET_IGNORE, FP_CELL)
2207 g_fwUserInfected_pre = CreateMultiForward("zp_user_infected_pre", ET_IGNORE, FP_CELL, FP_CELL, FP_CELL)
2208 g_fwUserInfected_post = CreateMultiForward("zp_user_infected_post", ET_IGNORE, FP_CELL, FP_CELL, FP_CELL)
2209 g_fwUserHumanized_pre = CreateMultiForward("zp_user_humanized_pre", ET_IGNORE, FP_CELL, FP_CELL)
2210 g_fwUserHumanized_post = CreateMultiForward("zp_user_humanized_post", ET_IGNORE, FP_CELL, FP_CELL)
2211 g_fwUserInfect_attempt = CreateMultiForward("zp_user_infect_attempt", ET_CONTINUE, FP_CELL, FP_CELL, FP_CELL)
2212 g_fwUserHumanize_attempt = CreateMultiForward("zp_user_humanize_attempt", ET_CONTINUE, FP_CELL, FP_CELL)
2213 g_fwExtraItemSelected = CreateMultiForward("zp_extra_item_selected", ET_CONTINUE, FP_CELL, FP_CELL)
2214 g_fwUserUnfrozen = CreateMultiForward("zp_user_unfrozen", ET_IGNORE, FP_CELL)
2215 g_fwUserLastZombie = CreateMultiForward("zp_user_last_zombie", ET_IGNORE, FP_CELL)
2216 g_fwUserLastHuman = CreateMultiForward("zp_user_last_human", ET_IGNORE, FP_CELL)
2217
2218 // Collect random spawn points
2219 load_spawns()
2220
2221 // Set a random skybox?
2222 if (g_sky_enable)
2223 {
2224 new sky[32]
2225 ArrayGetString(g_sky_names, random_num(0, ArraySize(g_sky_names) - 1), sky, charsmax(sky))
2226 set_cvar_string("sv_skyname", sky)
2227 }
2228
2229 // Disable sky lighting so it doesn't mess with our custom lighting
2230 set_cvar_num("sv_skycolor_r", 0)
2231 set_cvar_num("sv_skycolor_g", 0)
2232 set_cvar_num("sv_skycolor_b", 0)
2233
2234 // Create the HUD Sync Objects
2235 g_MsgSync = CreateHudSyncObj()
2236 g_MsgSync2 = CreateHudSyncObj()
2237 g_MsgSync3 = CreateHudSyncObj()
2238
2239 // Format mod name
2240 formatex(g_modname, charsmax(g_modname), "[RBE] Zombie Plague", PLUGIN_VERSION)
2241
2242 // Get Max Players
2243 g_maxplayers = get_maxplayers()
2244
2245 // Reserved saving slots starts on maxplayers+1
2246 db_slot_i = g_maxplayers+1
2247
2248 // Check if it's a CZ server
2249 new mymod[6]
2250 get_modname(mymod, charsmax(mymod))
2251 if (equal(mymod, "czero")) g_czero = 1
2252}
2253
2254public plugin_cfg()
2255{
2256 // Plugin disabled?
2257 if (!g_pluginenabled) return;
2258
2259 // Get configs dir
2260 new cfgdir[32]
2261 get_configsdir(cfgdir, charsmax(cfgdir))
2262
2263 // Execute config file (zombieplague.cfg)
2264 server_cmd("exec %s/zombieplague.cfg", cfgdir)
2265
2266 // Prevent any more stuff from registering
2267 g_arrays_created = false
2268
2269 // Save customization data
2270 save_customization()
2271
2272 // Lighting task
2273 set_task(5.0, "lighting_effects", _, _, _, "b")
2274
2275 // Cache CVARs after configs are loaded / call roundstart manually
2276 set_task(0.5, "cache_cvars")
2277 set_task(0.5, "event_round_start")
2278 set_task(0.5, "logevent_round_start")
2279}
2280
2281// Some one aimed at someone
2282public event_show_status(id)
2283{
2284 // Not a bot and is still connected
2285 if (!g_isbot[id] && g_isconnected[id] && get_pcvar_num(cvar_aiminfo))
2286 {
2287 // Retrieve the aimed player's id
2288 static aimid
2289 aimid = read_data(2)
2290
2291 // Only show friends status ?
2292 if (g_zombie[id] == g_zombie[aimid])
2293 {
2294 static class[32], red, blue
2295
2296 // Format the class name according to the player's team
2297 if (g_zombie[id])
2298 {
2299 red = 255
2300 blue = 0
2301
2302 if (g_nemesis[aimid])
2303 formatex(class, charsmax(class), "%L %L", id, "CLASS_CLASS", id, "CLASS_NEMESIS")
2304 else if (g_assassin[aimid])
2305 formatex(class, charsmax(class), "%L %L", id, "CLASS_CLASS", id, "CLASS_ASSASSIN")
2306 else
2307 formatex(class, charsmax(class), "%L %s", id, "CLASS_CLASS", g_zombie_classname[aimid])
2308 }
2309 else
2310 {
2311 red = 0
2312 blue = 255
2313
2314 if (g_survivor[aimid])
2315 formatex(class, charsmax(class), "%L %L", id, "CLASS_CLASS", id, "CLASS_SURVIVOR")
2316 else if (g_sniper[aimid])
2317 formatex(class, charsmax(class), "%L %L", id, "CLASS_CLASS", id, "CLASS_SNIPER")
2318 else
2319 formatex(class, charsmax(class), "%L %L", id, "CLASS_CLASS", id, "CLASS_HUMAN")
2320 }
2321
2322 // Show the notice
2323 set_hudmessage(red, 50, blue, -1.0, 0.60, 1, 0.01, 3.0, 0.01, 0.01, -1)
2324 ShowSyncHudMsg(id, g_MsgSync3,"%L", id, "AIM_INFO", g_playername[aimid], class, pev(aimid, pev_health), pev(aimid, pev_armorvalue), g_ammopacks[aimid])
2325 }
2326 }
2327}
2328
2329// Remove the aim-info message
2330public event_hide_status(id)
2331{
2332 ClearSyncHud(id, g_MsgSync3)
2333}
2334
2335/*================================================================================
2336 [Main Events]
2337=================================================================================*/
2338
2339// Event Round Start
2340public event_round_start()
2341{
2342 // Remove doors/lights?
2343 set_task(0.1, "remove_stuff")
2344
2345 // New round starting
2346 g_newround = true
2347 g_endround = false
2348 g_survround = false
2349 g_sniround = false
2350 g_nemround = false
2351 g_assaround = false
2352 g_swarmround = false
2353 g_plagueround = false
2354 g_armageround = false
2355 g_apocround = false
2356 g_nightround = false
2357 g_modestarted = false
2358
2359 // Reset bought infection bombs counter
2360 g_infbombcounter = 0
2361 g_antidotecounter = 0
2362 g_madnesscounter = 0
2363
2364 // Freezetime begins
2365 g_freezetime = true
2366
2367 // Show welcome message and T-Virus notice
2368 remove_task(TASK_WELCOMEMSG)
2369 set_task(2.0, "welcome_msg", TASK_WELCOMEMSG)
2370
2371 // Set a new "Make Zombie Task"
2372 remove_task(TASK_MAKEZOMBIE)
2373 set_task(2.0 + get_pcvar_float(cvar_warmup), "make_zombie_task", TASK_MAKEZOMBIE)
2374}
2375
2376// Log Event Round Start
2377public logevent_round_start()
2378{
2379 // Freezetime ends
2380 g_freezetime = false
2381}
2382
2383// Log Event Round End
2384public logevent_round_end()
2385{
2386 // Prevent this from getting called twice when restarting (bugfix)
2387 static Float:lastendtime, Float:current_time
2388 current_time = get_gametime()
2389 if (current_time - lastendtime < 0.5) return;
2390 lastendtime = current_time
2391
2392 // Temporarily save player stats?
2393 if (get_pcvar_num(cvar_statssave))
2394 {
2395 static id, team
2396 for (id = 1; id <= g_maxplayers; id++)
2397 {
2398 // Not connected
2399 if (!g_isconnected[id])
2400 continue;
2401
2402 team = fm_cs_get_user_team(id)
2403
2404 // Not playing
2405 if (team == FM_CS_TEAM_SPECTATOR || team == FM_CS_TEAM_UNASSIGNED)
2406 continue;
2407
2408 save_stats(id)
2409 }
2410 }
2411
2412 // Round ended
2413 g_endround = true
2414
2415 // Stop old tasks (if any)
2416 remove_task(TASK_WELCOMEMSG)
2417 remove_task(TASK_MAKEZOMBIE)
2418
2419 // Stop ambience sounds
2420 if ((g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS] && g_nemround) || (g_ambience_sounds[AMBIENCE_SOUNDS_ASSASSIN] && g_assaround) || (g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR] && g_survround) || (g_ambience_sounds[AMBIENCE_SOUNDS_SNIPER] && g_sniround) || (g_ambience_sounds[AMBIENCE_SOUNDS_SWARM] && g_swarmround) || (g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE] && g_plagueround)
2421 || (g_ambience_sounds[AMBIENCE_SOUNDS_ARMAGEDDON] && g_armageround) || (g_ambience_sounds[AMBIENCE_SOUNDS_APOCALYPSE] && g_apocround) || (g_ambience_sounds[AMBIENCE_SOUNDS_NIGHTMARE] && g_nightround) || (g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION] && !g_nemround && !g_assaround && !g_survround && !g_sniround && !g_swarmround && !g_plagueround && !g_armageround && !g_apocround && !g_nightround))
2422 {
2423 remove_task(TASK_AMBIENCESOUNDS)
2424 ambience_sound_stop()
2425 }
2426
2427 // Show HUD notice, play win sound, update team scores...
2428 static sound[64]
2429 if (!fnGetZombies())
2430 {
2431 // Human team wins
2432 set_hudmessage(0, 0, 200, HUD_EVENT_X, HUD_EVENT_Y, 0, 0.0, 3.0, 2.0, 1.0, -1)
2433 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "WIN_HUMAN")
2434
2435 // Play win sound and increase score, unless game commencing
2436 ArrayGetString(sound_win_humans, random_num(0, ArraySize(sound_win_humans) - 1), sound, charsmax(sound))
2437 PlaySound(sound)
2438 if (!g_gamecommencing) g_scorehumans++
2439
2440 // Round end forward
2441 ExecuteForward(g_fwRoundEnd, g_fwDummyResult, ZP_TEAM_HUMAN);
2442 }
2443 else if (!fnGetHumans())
2444 {
2445 // Zombie team wins
2446 set_hudmessage(200, 0, 0, HUD_EVENT_X, HUD_EVENT_Y, 0, 0.0, 3.0, 2.0, 1.0, -1)
2447 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "WIN_ZOMBIE")
2448
2449 // Play win sound and increase score, unless game commencing
2450 ArrayGetString(sound_win_zombies, random_num(0, ArraySize(sound_win_zombies) - 1), sound, charsmax(sound))
2451 PlaySound(sound)
2452 if (!g_gamecommencing) g_scorezombies++
2453
2454 // Round end forward
2455 ExecuteForward(g_fwRoundEnd, g_fwDummyResult, ZP_TEAM_ZOMBIE);
2456 }
2457 else
2458 {
2459 // No one wins
2460 set_hudmessage(0, 200, 0, HUD_EVENT_X, HUD_EVENT_Y, 0, 0.0, 3.0, 2.0, 1.0, -1)
2461 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "WIN_NO_ONE")
2462
2463 // Play win sound
2464 ArrayGetString(sound_win_no_one, random_num(0, ArraySize(sound_win_no_one) - 1), sound, charsmax(sound))
2465 PlaySound(sound)
2466
2467 // Round end forward
2468 ExecuteForward(g_fwRoundEnd, g_fwDummyResult, ZP_TEAM_NO_ONE);
2469 }
2470
2471 // Game commencing triggers round end
2472 g_gamecommencing = false
2473
2474 // Balance the teams
2475 balance_teams()
2476}
2477
2478// Event Map Ended
2479public event_intermission()
2480{
2481 // Remove ambience sounds task
2482 remove_task(TASK_AMBIENCESOUNDS)
2483}
2484
2485// BP Ammo update
2486public event_ammo_x(id)
2487{
2488 // Humans only
2489 if (g_zombie[id])
2490 return;
2491
2492 // Get ammo type
2493 static type
2494 type = read_data(1)
2495
2496 // Unknown ammo type
2497 if (type >= sizeof AMMOWEAPON)
2498 return;
2499
2500 // Get weapon's id
2501 static weapon
2502 weapon = AMMOWEAPON[type]
2503
2504 // Primary and secondary only
2505 if (MAXBPAMMO[weapon] <= 2)
2506 return;
2507
2508 // Get ammo amount
2509 static amount
2510 amount = read_data(2)
2511
2512 // Unlimited BP Ammo?
2513 if (g_survivor[id] ? get_pcvar_num(cvar_survinfammo) : g_sniper[id] ? get_pcvar_num(cvar_sniinfammo) : get_pcvar_num(cvar_infammo))
2514 {
2515 if (amount < MAXBPAMMO[weapon])
2516 {
2517 // The BP Ammo refill code causes the engine to send a message, but we
2518 // can't have that in this forward or we risk getting some recursion bugs.
2519 // For more info see: https://bugs.alliedmods.net/show_bug.cgi?id=3664
2520 static args[1]
2521 args[0] = weapon
2522 set_task(0.1, "refill_bpammo", id, args, sizeof args)
2523 }
2524 }
2525 // Bots automatically buy ammo when needed
2526 else if (g_isbot[id] && amount <= BUYAMMO[weapon])
2527 {
2528 // Task needed for the same reason as above
2529 set_task(0.1, "clcmd_buyammo", id)
2530 }
2531}
2532
2533/*================================================================================
2534 [Main Forwards]
2535=================================================================================*/
2536
2537// Entity Spawn Forward
2538public fw_Spawn(entity)
2539{
2540 // Invalid entity
2541 if (!pev_valid(entity)) return FMRES_IGNORED;
2542
2543 // Get classname
2544 new classname[32], objective[32], size = ArraySize(g_objective_ents)
2545 pev(entity, pev_classname, classname, charsmax(classname))
2546
2547 // Check whether it needs to be removed
2548 for (new i = 0; i < size; i++)
2549 {
2550 ArrayGetString(g_objective_ents, i, objective, charsmax(objective))
2551
2552 if (equal(classname, objective))
2553 {
2554 engfunc(EngFunc_RemoveEntity, entity)
2555 return FMRES_SUPERCEDE;
2556 }
2557 }
2558
2559 return FMRES_IGNORED;
2560}
2561
2562// Sound Precache Forward
2563public fw_PrecacheSound(const sound[])
2564{
2565 // Block all those unneeeded hostage sounds
2566 if (equal(sound, "hostage", 7))
2567 return FMRES_SUPERCEDE;
2568
2569 return FMRES_IGNORED;
2570}
2571
2572// Ham Player Spawn Post Forward
2573public fw_PlayerSpawn_Post(id)
2574{
2575 // Not alive or didn't join a team yet
2576 if (!is_user_alive(id) || !fm_cs_get_user_team(id))
2577 return;
2578
2579 // Player spawned
2580 g_isalive[id] = true
2581
2582 // Remove previous tasks
2583 remove_task(id+TASK_SPAWN)
2584 remove_task(id+TASK_MODEL)
2585 remove_task(id+TASK_BLOOD)
2586 remove_task(id+TASK_AURA)
2587 remove_task(id+TASK_BURN)
2588 remove_task(id+TASK_CHARGE)
2589 remove_task(id+TASK_FLASH)
2590 remove_task(id+TASK_NVISION)
2591
2592 // Spawn at a random location?
2593 if (get_pcvar_num(cvar_randspawn)) do_random_spawn(id)
2594
2595 // Hide money?
2596 if (get_pcvar_num(cvar_removemoney))
2597 set_task(0.4, "task_hide_money", id+TASK_SPAWN)
2598
2599 // Respawn player if he dies because of a worldspawn kill?
2600 if (get_pcvar_num(cvar_respawnworldspawnkill))
2601 set_task(2.0, "respawn_player_check_task", id+TASK_SPAWN)
2602
2603 // Spawn as zombie?
2604 if (g_respawn_as_zombie[id] && !g_newround)
2605 {
2606 reset_vars(id, 0) // reset player vars
2607 zombieme(id, 0, 0, 0, 0, 0) // make him zombie right away
2608 return;
2609 }
2610
2611 // Reset player vars
2612 reset_vars(id, 0)
2613 g_buytime[id] = get_gametime()
2614
2615 // Show custom buy menu?
2616 if (get_pcvar_num(cvar_buycustom))
2617 set_task(0.2, "show_menu_buy1", id+TASK_SPAWN)
2618
2619 // Set health and gravity
2620 fm_set_user_health(id, get_pcvar_num(cvar_humanhp))
2621 set_pev(id, pev_gravity, get_pcvar_float(cvar_humangravity))
2622
2623 // Set human maxspeed
2624 ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
2625
2626 // Switch to CT if spawning mid-round
2627 if (!g_newround && fm_cs_get_user_team(id) != FM_CS_TEAM_CT) // need to change team?
2628 {
2629 remove_task(id+TASK_TEAM)
2630 fm_cs_set_user_team(id, FM_CS_TEAM_CT)
2631 fm_user_team_update(id)
2632 }
2633
2634 // Custom models stuff
2635 static currentmodel[32], tempmodel[32], already_has_model, i, iRand, size
2636 already_has_model = false
2637
2638 if (g_handle_models_on_separate_ent)
2639 {
2640 // Set the right model
2641 if (get_pcvar_num(cvar_adminmodelshuman) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
2642 {
2643 iRand = random_num(0, ArraySize(model_admin_human) - 1)
2644 ArrayGetString(model_admin_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
2645 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_human, iRand))
2646 }
2647 else
2648 {
2649 iRand = random_num(0, ArraySize(model_human) - 1)
2650 ArrayGetString(model_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
2651 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_human, iRand))
2652 }
2653
2654 // Set model on player model entity
2655 fm_set_playermodel_ent(id)
2656
2657 // Remove glow on player model entity
2658 fm_set_rendering(g_ent_playermodel[id])
2659 }
2660 else
2661 {
2662 // Get current model for comparing it with the current one
2663 fm_cs_get_user_model(id, currentmodel, charsmax(currentmodel))
2664
2665 // Set the right model, after checking that we don't already have it
2666 if (get_pcvar_num(cvar_adminmodelshuman) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
2667 {
2668 size = ArraySize(model_admin_human)
2669 for (i = 0; i < size; i++)
2670 {
2671 ArrayGetString(model_admin_human, i, tempmodel, charsmax(tempmodel))
2672 if (equal(currentmodel, tempmodel)) already_has_model = true
2673 }
2674
2675 if (!already_has_model)
2676 {
2677 iRand = random_num(0, size - 1)
2678 ArrayGetString(model_admin_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
2679 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_human, iRand))
2680 }
2681 }
2682 else
2683 {
2684 size = ArraySize(model_human)
2685 for (i = 0; i < size; i++)
2686 {
2687 ArrayGetString(model_human, i, tempmodel, charsmax(tempmodel))
2688 if (equal(currentmodel, tempmodel)) already_has_model = true
2689 }
2690
2691 if (!already_has_model)
2692 {
2693 iRand = random_num(0, size - 1)
2694 ArrayGetString(model_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
2695 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_human, iRand))
2696 }
2697 }
2698
2699 // Need to change the model?
2700 if (!already_has_model)
2701 {
2702 // An additional delay is offset at round start
2703 // since SVC_BAD is more likely to be triggered there
2704 if (g_newround)
2705 set_task(5.0 * g_modelchange_delay, "fm_user_model_update", id+TASK_MODEL)
2706 else
2707 fm_user_model_update(id+TASK_MODEL)
2708 }
2709
2710 // Remove glow
2711 fm_set_rendering(id)
2712 }
2713
2714 // Bots stuff
2715 if (g_isbot[id])
2716 {
2717 // Turn off NVG for bots
2718 cs_set_user_nvg(id, 0)
2719
2720 // Automatically buy extra items/weapons after first zombie is chosen
2721 if (get_pcvar_num(cvar_extraitems))
2722 {
2723 if (g_newround) set_task(10.0 + get_pcvar_float(cvar_warmup), "bot_buy_extras", id+TASK_SPAWN)
2724 else set_task(10.0, "bot_buy_extras", id+TASK_SPAWN)
2725 }
2726 }
2727
2728 // Enable spawn protection for humans spawning mid-round
2729 if (!g_newround && get_pcvar_float(cvar_spawnprotection) > 0.0)
2730 {
2731 // Do not take damage
2732 g_nodamage[id] = true
2733
2734 // Make temporarily invisible
2735 set_pev(id, pev_effects, pev(id, pev_effects) | EF_NODRAW)
2736
2737 // Set task to remove it
2738 set_task(get_pcvar_float(cvar_spawnprotection), "remove_spawn_protection", id+TASK_SPAWN)
2739 }
2740
2741 // Turn off his flashlight (prevents double flashlight bug/exploit)
2742 turn_off_flashlight(id)
2743
2744 // Set the flashlight charge task to update battery status
2745 if (g_cached_customflash)
2746 set_task(1.0, "flashlight_charge", id+TASK_CHARGE, _, _, "b")
2747
2748 // Replace weapon models (bugfix)
2749 static weapon_ent
2750 weapon_ent = fm_cs_get_current_weapon_ent(id)
2751 if (pev_valid(weapon_ent)) replace_weapon_models(id, cs_get_weapon_id(weapon_ent))
2752
2753 // Last Zombie Check
2754 fnCheckLastZombie()
2755}
2756
2757// Ham Player Killed Forward
2758public fw_PlayerKilled(victim, attacker, shouldgib)
2759{
2760 // Player killed
2761 g_isalive[victim] = false
2762 // Disable nodamage mode after we die to prevent spectator nightvision using zombie madness colors bug
2763 g_nodamage[victim] = false
2764
2765 // Enable dead players nightvision
2766 set_task(0.1, "spec_nvision", victim)
2767
2768 // Disable nightvision when killed (bugfix)
2769 if (get_pcvar_num(cvar_nvggive) == 0 && g_nvision[victim])
2770 {
2771 if (get_pcvar_num(cvar_customnvg)) remove_task(victim+TASK_NVISION)
2772 else if (g_nvisionenabled[victim]) set_user_gnvision(victim, 0)
2773 g_nvision[victim] = false
2774 g_nvisionenabled[victim] = false
2775 }
2776
2777 // Turn off nightvision when killed (bugfix)
2778 if (get_pcvar_num(cvar_nvggive) == 2 && g_nvision[victim] && g_nvisionenabled[victim])
2779 {
2780 if (get_pcvar_num(cvar_customnvg)) remove_task(victim+TASK_NVISION)
2781 else set_user_gnvision(victim, 0)
2782 g_nvisionenabled[victim] = false
2783 }
2784
2785 // Turn off custom flashlight when killed
2786 if (g_cached_customflash)
2787 {
2788 // Turn it off
2789 g_flashlight[victim] = false
2790 g_flashbattery[victim] = 100
2791
2792 // Remove previous tasks
2793 remove_task(victim+TASK_CHARGE)
2794 remove_task(victim+TASK_FLASH)
2795 }
2796
2797 // Stop bleeding/burning/aura when killed
2798 if (g_zombie[victim])
2799 {
2800 remove_task(victim+TASK_BLOOD)
2801 remove_task(victim+TASK_AURA)
2802 remove_task(victim+TASK_BURN)
2803 }
2804
2805 // Nemesis/Assassins explodes!
2806 if (g_nemesis[victim] || g_assassin[victim])
2807 SetHamParamInteger(3, 2)
2808
2809 // Get deathmatch mode status and whether the player killed himself
2810 static selfkill
2811 selfkill = (victim == attacker || !is_user_valid_connected(attacker)) ? true : false
2812
2813 // Make sure that the player was not killed by a non-player entity or through self killing
2814 if (!selfkill)
2815 {
2816 // When killed by a Sniper victim explodes
2817 if (g_sniper[attacker] && (g_currentweapon[attacker] == CSW_AWP))
2818 {
2819 // Cut him into pieces
2820 SetHamParamInteger(3, 2)
2821
2822 // Get his origin
2823 static origin[3]
2824 get_user_origin(victim, origin)
2825
2826 // Make some blood in the air
2827 message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
2828 write_byte(TE_LAVASPLASH) // TE id
2829 write_coord(origin[0]) // origin x
2830 write_coord(origin[1]) // origin y
2831 write_coord(origin[2] - 26) // origin z
2832 message_end()
2833 }
2834 else if (g_assassin[attacker])
2835 SetHamParamInteger(3, 2)
2836 }
2837
2838 // Killed by a non-player entity or self killed
2839 if (selfkill) return;
2840
2841 // Ignore Nemesis/Survivor Frags?
2842 if ((g_nemesis[attacker] && get_pcvar_num(cvar_nemignorefrags)) || (g_assassin[attacker] && get_pcvar_num(cvar_assaignorefrags)) || (g_survivor[attacker] && get_pcvar_num(cvar_survignorefrags)) || (g_sniper[attacker] && get_pcvar_num(cvar_snipignorefrags)))
2843 RemoveFrags(attacker, victim)
2844
2845 // Zombie/nemesis/assassin killed human, reward ammo packs
2846 if (g_zombie[attacker] && (!g_nemesis[attacker] || !get_pcvar_num(cvar_nemignoreammo)) && (!g_assassin[attacker] || !get_pcvar_num(cvar_assaignoreammo)))
2847 g_ammopacks[attacker] += get_pcvar_num(cvar_ammoinfect)
2848
2849 // Human killed zombie, add up the extra frags for kill
2850 if (!g_zombie[attacker] && get_pcvar_num(cvar_fragskill) > 1)
2851 UpdateFrags(attacker, victim, get_pcvar_num(cvar_fragskill) - 1, 0, 0)
2852
2853 // Zombie killed human, add up the extra frags for kill
2854 if (g_zombie[attacker] && get_pcvar_num(cvar_fragsinfect) > 1)
2855 UpdateFrags(attacker, victim, get_pcvar_num(cvar_fragsinfect) - 1, 0, 0)
2856}
2857
2858// Ham Player Killed Post Forward
2859public fw_PlayerKilled_Post(victim, attacker, shouldgib)
2860{
2861 // Last Zombie Check
2862 fnCheckLastZombie()
2863
2864 // Determine whether the player killed himself
2865 static selfkill
2866 selfkill = (victim == attacker || !is_user_valid_connected(attacker)) ? true : false
2867
2868 // Respawn if deathmatch is enabled
2869 if (get_pcvar_num(cvar_deathmatch))
2870 {
2871 // Respawn on suicide?
2872 if (selfkill && !get_pcvar_num(cvar_respawnonsuicide))
2873 return;
2874
2875 // Respawn if human/zombie/nemesis/survivor?
2876 if ((g_zombie[victim] && !g_nemesis[victim] && !g_assassin[victim] && !get_pcvar_num(cvar_respawnzomb)) || (!g_zombie[victim] && !g_survivor[victim] && !g_sniper[victim] && !get_pcvar_num(cvar_respawnhum)) || (g_nemesis[victim] && !get_pcvar_num(cvar_respawnnem)) || (g_assassin[victim] && !get_pcvar_num(cvar_respawnassa)) || (g_survivor[victim] && !get_pcvar_num(cvar_respawnsurv)) || (g_sniper[victim] && !get_pcvar_num(cvar_respawnsni)))
2877 return;
2878
2879 // Set the respawn task
2880 set_task(get_pcvar_float(cvar_spawndelay), "respawn_player_task", victim+TASK_SPAWN)
2881 }
2882}
2883
2884// Ham Take Damage Forward
2885public fw_TakeDamage(victim, inflictor, attacker, Float:damage, damage_type)
2886{
2887 // Non-player damage or self damage
2888 if (victim == attacker || !is_user_valid_connected(attacker))
2889 return HAM_IGNORED;
2890
2891 // New round starting or round ended
2892 if (g_newround || g_endround)
2893 return HAM_SUPERCEDE;
2894
2895 // Victim shouldn't take damage or victim is frozen
2896 if (g_nodamage[victim] || g_frozen[victim])
2897 return HAM_SUPERCEDE;
2898
2899 // Prevent friendly fire
2900 if (g_zombie[attacker] == g_zombie[victim])
2901 return HAM_SUPERCEDE;
2902
2903 // Attacker is human...
2904 if (!g_zombie[attacker])
2905 {
2906 // Armor multiplier for the final damage on normal zombies
2907 if (!g_nemesis[victim] && !g_assassin[victim] && !g_sniper[attacker])
2908 {
2909 damage *= get_pcvar_float(cvar_zombiearmor)
2910 SetHamParamFloat(4, damage)
2911 }
2912
2913 // Reward ammo packs to humans for damaging zombies?
2914 if ((get_pcvar_num(cvar_ammodamage_human) > 0) && (!g_survivor[attacker] || !get_pcvar_num(cvar_survignoreammo)) && (!g_sniper[attacker] || !get_pcvar_num(cvar_snipignoreammo)))
2915 {
2916 // Store damage dealt
2917 g_damagedealt_human[attacker] += floatround(damage)
2918
2919 // Reward ammo packs for every [ammo damage] dealt
2920 while (g_damagedealt_human[attacker] > get_pcvar_num(cvar_ammodamage_human))
2921 {
2922 g_ammopacks[attacker]++
2923 g_damagedealt_human[attacker] -= get_pcvar_num(cvar_ammodamage_human)
2924 }
2925 }
2926
2927 // set sniper dmg
2928 if (g_sniper[attacker] && g_currentweapon[attacker] == CSW_AWP)
2929 SetHamParamFloat(4, get_pcvar_float(cvar_snidamage))
2930
2931 return HAM_IGNORED;
2932 }
2933
2934 // Attacker is zombie...
2935
2936 // Prevent infection/damage by HE grenade (bugfix)
2937 if (damage_type & DMG_HEGRENADE)
2938 return HAM_SUPERCEDE;
2939
2940 // Nemesis?
2941 if (g_nemesis[attacker])
2942 {
2943 // Ignore nemesis damage override if damage comes from a 3rd party entity
2944 // (to prevent this from affecting a sub-plugin's rockets e.g.)
2945 if (inflictor == attacker)
2946 {
2947 // Set nemesis damage
2948 SetHamParamFloat(4, get_pcvar_float(cvar_nemdamage))
2949 }
2950
2951 return HAM_IGNORED;
2952 }
2953 else if (g_assassin[attacker])
2954 {
2955 // Ignore assassin damage override if damage comes from a 3rd party entity
2956 // (to prevent this from affecting a sub-plugin's rockets e.g.)
2957 if (inflictor == attacker)
2958 {
2959 // Set assassin damage
2960 SetHamParamFloat(4, get_pcvar_float(cvar_assadamage))
2961 }
2962
2963 return HAM_IGNORED;
2964 }
2965
2966 // Reward ammo packs to zombies for damaging humans?
2967 if (get_pcvar_num(cvar_ammodamage_zombie) > 0)
2968 {
2969 // Store damage dealt
2970 g_damagedealt_zombie[attacker] += floatround(damage)
2971
2972 // Reward ammo packs for every [ammo damage] dealt
2973 while (g_damagedealt_zombie[attacker] > get_pcvar_num(cvar_ammodamage_zombie))
2974 {
2975 g_ammopacks[attacker]++
2976 g_damagedealt_zombie[attacker] -= get_pcvar_num(cvar_ammodamage_zombie)
2977 }
2978 }
2979
2980 // Last human or not an infection round
2981 if (g_survround || g_sniround || g_nemround || g_assaround || g_swarmround || g_plagueround || g_armageround || g_apocround || g_nightround || fnGetHumans() == 1)
2982 return HAM_IGNORED; // human is killed
2983
2984 // Does human armor need to be reduced before infecting?
2985 if (get_pcvar_num(cvar_humanarmor))
2986 {
2987 // Get victim armor
2988 static Float:armor
2989 pev(victim, pev_armorvalue, armor)
2990
2991 // If he has some, block the infection and reduce armor instead
2992 if (armor > 0.0)
2993 {
2994 emit_sound(victim, CHAN_BODY, sound_armorhit, 1.0, ATTN_NORM, 0, PITCH_NORM)
2995 if (armor - damage > 0.0)
2996 set_pev(victim, pev_armorvalue, armor - damage)
2997 else
2998 cs_set_user_armor(victim, 0, CS_ARMOR_NONE)
2999 return HAM_SUPERCEDE;
3000 }
3001 }
3002
3003 // Infection allowed
3004 zombieme(victim, attacker, 0, 0, 0, 1) // turn into zombie
3005 return HAM_SUPERCEDE;
3006}
3007
3008// Ham Take Damage Post Forward
3009public fw_TakeDamage_Post(victim)
3010{
3011 // --- Check if victim should be Pain Shock Free ---
3012
3013 // Check if proper CVARs are enabled
3014 if (g_zombie[victim])
3015 {
3016 if (g_nemesis[victim])
3017 {
3018 if (!get_pcvar_num(cvar_nempainfree)) return;
3019 }
3020 else if (g_assassin[victim])
3021 {
3022 if (!get_pcvar_num(cvar_assapainfree)) return;
3023 }
3024 else
3025 {
3026 switch (get_pcvar_num(cvar_zombiepainfree))
3027 {
3028 case 0: return;
3029 case 2: if (!g_lastzombie[victim]) return;
3030 case 3: if (!g_firstzombie[victim]) return;
3031 }
3032 }
3033 }
3034 else
3035 {
3036 if (g_survivor[victim])
3037 {
3038 if (!get_pcvar_num(cvar_survpainfree)) return;
3039 }
3040 else if (g_sniper[victim])
3041 {
3042 if (!get_pcvar_num(cvar_snipainfree)) return;
3043 }
3044
3045 else return;
3046 }
3047
3048 // Prevent server crash if entity's private data not initalized
3049 if (pev_valid(victim) != PDATA_SAFE)
3050 return;
3051
3052 // Set pain shock free offset
3053 set_pdata_float(victim, OFFSET_PAINSHOCK, 1.0, OFFSET_LINUX)
3054}
3055
3056// Ham Trace Attack Forward
3057public fw_TraceAttack(victim, attacker, Float:damage, Float:direction[3], tracehandle, damage_type)
3058{
3059 // Non-player damage or self damage
3060 if (victim == attacker || !is_user_valid_connected(attacker))
3061 return HAM_IGNORED;
3062
3063 // New round starting or round ended
3064 if (g_newround || g_endround)
3065 return HAM_SUPERCEDE;
3066
3067 // Victim shouldn't take damage or victim is frozen
3068 if (g_nodamage[victim] || (g_frozen[victim] && get_pcvar_num(cvar_dmg_while_freeze)))
3069 return HAM_SUPERCEDE;
3070
3071 // Prevent friendly fire
3072 if (g_zombie[attacker] == g_zombie[victim])
3073 return HAM_SUPERCEDE;
3074
3075 // Victim isn't a zombie or not bullet damage, nothing else to do here
3076 if (!g_zombie[victim] || !(damage_type & DMG_BULLET))
3077 return HAM_IGNORED;
3078
3079 // If zombie hitzones are enabled, check whether we hit an allowed one
3080 if (get_pcvar_num(cvar_hitzones) && !g_nemesis[victim] && !g_assassin[victim] && !(get_pcvar_num(cvar_hitzones) & (1<<get_tr2(tracehandle, TR_iHitgroup))))
3081 return HAM_SUPERCEDE;
3082
3083 // Knockback disabled, nothing else to do here
3084 if (!get_pcvar_num(cvar_knockback))
3085 return HAM_IGNORED;
3086
3087 // Nemesis knockback disabled, nothing else to do here
3088 if (g_nemesis[victim] && get_pcvar_float(cvar_nemknockback) == 0.0)
3089 return HAM_IGNORED;
3090
3091 // Assassin knockback disabled, nothing else to do here
3092 if (g_assassin[victim] && get_pcvar_float(cvar_assaknockback) == 0.0)
3093 return HAM_IGNORED;
3094
3095 // Get whether the victim is in a crouch state
3096 static ducking
3097 ducking = pev(victim, pev_flags) & (FL_DUCKING | FL_ONGROUND) == (FL_DUCKING | FL_ONGROUND)
3098
3099 // Zombie knockback when ducking disabled
3100 if (ducking && get_pcvar_float(cvar_knockbackducking) == 0.0)
3101 return HAM_IGNORED;
3102
3103 // Get distance between players
3104 static origin1[3], origin2[3]
3105 get_user_origin(victim, origin1)
3106 get_user_origin(attacker, origin2)
3107
3108 // Max distance exceeded
3109 if (get_distance(origin1, origin2) > get_pcvar_num(cvar_knockbackdist))
3110 return HAM_IGNORED;
3111
3112 // Get victim's velocity
3113 static Float:velocity[3]
3114 pev(victim, pev_velocity, velocity)
3115
3116 // Use damage on knockback calculation
3117 if (get_pcvar_num(cvar_knockbackdamage))
3118 xs_vec_mul_scalar(direction, damage, direction)
3119
3120 // Use weapon power on knockback calculation
3121 if (get_pcvar_num(cvar_knockbackpower) && kb_weapon_power[g_currentweapon[attacker]] > 0.0)
3122 xs_vec_mul_scalar(direction, kb_weapon_power[g_currentweapon[attacker]], direction)
3123
3124 // Apply ducking knockback multiplier
3125 if (ducking)
3126 xs_vec_mul_scalar(direction, get_pcvar_float(cvar_knockbackducking), direction)
3127
3128 // Apply zombie class/nemesis knockback multiplier
3129 if (g_nemesis[victim])
3130 xs_vec_mul_scalar(direction, get_pcvar_float(cvar_nemknockback), direction)
3131 else if (g_assassin[victim])
3132 xs_vec_mul_scalar(direction, get_pcvar_float(cvar_assaknockback), direction)
3133 else
3134 xs_vec_mul_scalar(direction, g_zombie_knockback[victim], direction)
3135
3136 // Add up the new vector
3137 xs_vec_add(velocity, direction, direction)
3138
3139 // Should knockback also affect vertical velocity?
3140 if (!get_pcvar_num(cvar_knockbackzvel))
3141 direction[2] = velocity[2]
3142
3143 // Set the knockback'd victim's velocity
3144 set_pev(victim, pev_velocity, direction)
3145
3146 return HAM_IGNORED;
3147}
3148
3149// Ham Reset MaxSpeed Post Forward
3150public fw_ResetMaxSpeed_Post(id)
3151{
3152 // Freezetime active or player not alive
3153 if (g_freezetime || !g_isalive[id])
3154 return;
3155
3156 set_player_maxspeed(id)
3157}
3158
3159// Ham Use Stationary Gun Forward
3160public fw_UseStationary(entity, caller, activator, use_type)
3161{
3162 // Prevent zombies from using stationary guns
3163 if (use_type == USE_USING && is_user_valid_connected(caller) && g_zombie[caller])
3164 return HAM_SUPERCEDE;
3165
3166 return HAM_IGNORED;
3167}
3168
3169// Ham Use Stationary Gun Post Forward
3170public fw_UseStationary_Post(entity, caller, activator, use_type)
3171{
3172 // Someone stopped using a stationary gun
3173 if (use_type == USE_STOPPED && is_user_valid_connected(caller))
3174 replace_weapon_models(caller, g_currentweapon[caller]) // replace weapon models (bugfix)
3175}
3176
3177// Ham Use Pushable Forward
3178public fw_UsePushable()
3179{
3180 // Prevent speed bug with pushables?
3181 if (get_pcvar_num(cvar_blockpushables))
3182 return HAM_SUPERCEDE;
3183
3184 return HAM_IGNORED;
3185}
3186
3187// Ham Weapon Touch Forward
3188public fw_TouchWeapon(weapon, id)
3189{
3190 // Not a player
3191 if (!is_user_valid_connected(id))
3192 return HAM_IGNORED;
3193
3194 // Dont pickup weapons if zombie or survivor (+PODBot MM fix)
3195 if (g_zombie[id] || g_isbot[id] || ((g_survivor[id] || g_sniper[id]) && (g_isbot[id] || g_isalive[id])))
3196 return HAM_SUPERCEDE;
3197
3198 return HAM_IGNORED;
3199}
3200
3201// Ham Weapon Pickup Forward
3202public fw_AddPlayerItem(id, weapon_ent)
3203{
3204 // HACK: Retrieve our custom extra ammo from the weapon
3205 static extra_ammo
3206 extra_ammo = pev(weapon_ent, PEV_ADDITIONAL_AMMO)
3207
3208 // If present
3209 if (extra_ammo)
3210 {
3211 // Get weapon's id
3212 static weaponid
3213 weaponid = cs_get_weapon_id(weapon_ent)
3214
3215 // Add to player's bpammo
3216 ExecuteHamB(Ham_GiveAmmo, id, extra_ammo, AMMOTYPE[weaponid], MAXBPAMMO[weaponid])
3217 set_pev(weapon_ent, PEV_ADDITIONAL_AMMO, 0)
3218 }
3219}
3220
3221// Ham Weapon Deploy Forward
3222public fw_Item_Deploy_Post(weapon_ent)
3223{
3224 // Get weapon's owner
3225 static owner
3226 owner = fm_cs_get_weapon_ent_owner(weapon_ent)
3227
3228 // Valid owner?
3229 if (!pev_valid(owner))
3230 return;
3231
3232 // Get weapon's id
3233 static weaponid
3234 weaponid = cs_get_weapon_id(weapon_ent)
3235
3236 // Store current weapon's id for reference
3237 g_currentweapon[owner] = weaponid
3238
3239 // Replace weapon models with custom ones
3240 replace_weapon_models(owner, weaponid)
3241
3242 // Zombie not holding an allowed weapon for some reason
3243 if (g_zombie[owner] && !((1<<weaponid) & ZOMBIE_ALLOWED_WEAPONS_BITSUM))
3244 {
3245 // Switch to knife
3246 g_currentweapon[owner] = CSW_KNIFE
3247 engclient_cmd(owner, "weapon_knife")
3248 }
3249}
3250
3251// WeaponMod bugfix
3252//forward wpn_gi_reset_weapon(id);
3253public wpn_gi_reset_weapon(id)
3254{
3255 // Replace knife model
3256 replace_weapon_models(id, CSW_KNIFE)
3257}
3258
3259// Client joins the game
3260public client_putinserver(id)
3261{
3262 // Plugin disabled?
3263 if (!g_pluginenabled) return;
3264
3265 // Player joined
3266 g_isconnected[id] = true
3267
3268 // Cache player's name
3269 get_user_name(id, g_playername[id], charsmax(g_playername[]))
3270
3271 // Initialize player vars
3272 reset_vars(id, 1)
3273
3274 // Load player stats?
3275 if (get_pcvar_num(cvar_statssave)) load_stats(id)
3276
3277 // Set some tasks for humans only
3278 if (!is_user_bot(id))
3279 {
3280 // Set the custom HUD display task if enabled
3281 if (get_pcvar_num(cvar_huddisplay))
3282 set_task(1.0, "ShowHUD", id+TASK_SHOWHUD, _, _, "b")
3283
3284 // Disable minmodels for clients to see zombies properly
3285 set_task(5.0, "disable_minmodels", id)
3286 }
3287 else
3288 {
3289 // Set bot flag
3290 g_isbot[id] = true
3291
3292 // CZ bots seem to use a different "classtype" for player entities
3293 // (or something like that) which needs to be hooked separately
3294 if (!g_hamczbots && cvar_botquota)
3295 {
3296 // Set a task to let the private data initialize
3297 set_task(0.1, "register_ham_czbots", id)
3298 }
3299 }
3300}
3301
3302// Client leaving
3303public fw_ClientDisconnect(id)
3304{
3305 // Check that we still have both humans and zombies to keep the round going
3306 if (g_isalive[id]) check_round(id)
3307
3308 // Temporarily save player stats?
3309 if (get_pcvar_num(cvar_statssave)) save_stats(id)
3310
3311 // Remove previous tasks
3312 remove_task(id+TASK_TEAM)
3313 remove_task(id+TASK_MODEL)
3314 remove_task(id+TASK_FLASH)
3315 remove_task(id+TASK_CHARGE)
3316 remove_task(id+TASK_SPAWN)
3317 remove_task(id+TASK_BLOOD)
3318 remove_task(id+TASK_AURA)
3319 remove_task(id+TASK_BURN)
3320 remove_task(id+TASK_NVISION)
3321 remove_task(id+TASK_SHOWHUD)
3322
3323 if (g_handle_models_on_separate_ent)
3324 {
3325 // Remove custom model entities
3326 fm_remove_model_ents(id)
3327 }
3328
3329 // Player left, clear cached flags
3330 g_isconnected[id] = false
3331 g_isbot[id] = false
3332 g_isalive[id] = false
3333}
3334
3335// Client left
3336public fw_ClientDisconnect_Post()
3337{
3338 // Last Zombie Check
3339 fnCheckLastZombie()
3340}
3341
3342// Client Kill Forward
3343public fw_ClientKill()
3344{
3345 // Prevent players from killing themselves?
3346 if (get_pcvar_num(cvar_blocksuicide))
3347 return FMRES_SUPERCEDE;
3348
3349 return FMRES_IGNORED;
3350}
3351
3352// Emit Sound Forward
3353public fw_EmitSound(id, channel, const sample[], Float:volume, Float:attn, flags, pitch)
3354{
3355 // Block all those unneeeded hostage sounds
3356 if (sample[0] == 'h' && sample[1] == 'o' && sample[2] == 's' && sample[3] == 't' && sample[4] == 'a' && sample[5] == 'g' && sample[6] == 'e')
3357 return FMRES_SUPERCEDE;
3358
3359 // Replace these next sounds for zombies only
3360 if (!is_user_valid_connected(id) || !g_zombie[id])
3361 return FMRES_IGNORED;
3362
3363 static sound[64]
3364
3365 // Zombie being hit
3366 if (sample[7] == 'b' && sample[8] == 'h' && sample[9] == 'i' && sample[10] == 't')
3367 {
3368 if (g_nemesis[id])
3369 {
3370 ArrayGetString(nemesis_pain, random_num(0, ArraySize(nemesis_pain) - 1), sound, charsmax(sound))
3371 emit_sound(id, channel, sound, volume, attn, flags, pitch)
3372 }
3373 else if (g_assassin[id])
3374 {
3375 ArrayGetString(assassin_pain, random_num(0, ArraySize(assassin_pain) - 1), sound, charsmax(sound))
3376 emit_sound(id, channel, sound, volume, attn, flags, pitch)
3377 }
3378 else
3379 {
3380 ArrayGetString(zombie_pain, random_num(0, ArraySize(zombie_pain) - 1), sound, charsmax(sound))
3381 emit_sound(id, channel, sound, volume, attn, flags, pitch)
3382 }
3383 return FMRES_SUPERCEDE;
3384 }
3385
3386 // Zombie attacks with knife
3387 if (sample[8] == 'k' && sample[9] == 'n' && sample[10] == 'i')
3388 {
3389 if (sample[14] == 's' && sample[15] == 'l' && sample[16] == 'a') // slash
3390 {
3391 ArrayGetString(zombie_miss_slash, random_num(0, ArraySize(zombie_miss_slash) - 1), sound, charsmax(sound))
3392 emit_sound(id, channel, sound, volume, attn, flags, pitch)
3393 return FMRES_SUPERCEDE;
3394 }
3395 if (sample[14] == 'h' && sample[15] == 'i' && sample[16] == 't') // hit
3396 {
3397 if (sample[17] == 'w') // wall
3398 {
3399 ArrayGetString(zombie_miss_wall, random_num(0, ArraySize(zombie_miss_wall) - 1), sound, charsmax(sound))
3400 emit_sound(id, channel, sound, volume, attn, flags, pitch)
3401 return FMRES_SUPERCEDE;
3402 }
3403 else
3404 {
3405 ArrayGetString(zombie_hit_normal, random_num(0, ArraySize(zombie_hit_normal) - 1), sound, charsmax(sound))
3406 emit_sound(id, channel, sound, volume, attn, flags, pitch)
3407 return FMRES_SUPERCEDE;
3408 }
3409 }
3410 if (sample[14] == 's' && sample[15] == 't' && sample[16] == 'a') // stab
3411 {
3412 ArrayGetString(zombie_hit_stab, random_num(0, ArraySize(zombie_hit_stab) - 1), sound, charsmax(sound))
3413 emit_sound(id, channel, sound, volume, attn, flags, pitch)
3414 return FMRES_SUPERCEDE;
3415 }
3416 }
3417
3418 // Zombie dies
3419 if (sample[7] == 'd' && ((sample[8] == 'i' && sample[9] == 'e') || (sample[8] == 'e' && sample[9] == 'a')))
3420 {
3421 ArrayGetString(zombie_die, random_num(0, ArraySize(zombie_die) - 1), sound, charsmax(sound))
3422 emit_sound(id, channel, sound, volume, attn, flags, pitch)
3423 return FMRES_SUPERCEDE;
3424 }
3425
3426 // Zombie falls off
3427 if (sample[10] == 'f' && sample[11] == 'a' && sample[12] == 'l' && sample[13] == 'l')
3428 {
3429 ArrayGetString(zombie_fall, random_num(0, ArraySize(zombie_fall) - 1), sound, charsmax(sound))
3430 emit_sound(id, channel, sound, volume, attn, flags, pitch)
3431 return FMRES_SUPERCEDE;
3432 }
3433
3434 return FMRES_IGNORED;
3435}
3436
3437// Forward Set ClientKey Value -prevent CS from changing player models-
3438public fw_SetClientKeyValue(id, const infobuffer[], const key[])
3439{
3440 // Block CS model changes
3441 if (key[0] == 'm' && key[1] == 'o' && key[2] == 'd' && key[3] == 'e' && key[4] == 'l')
3442 return FMRES_SUPERCEDE;
3443
3444 return FMRES_IGNORED;
3445}
3446
3447// Forward Client User Info Changed -prevent players from changing models-
3448public fw_ClientUserInfoChanged(id)
3449{
3450 // Cache player's name
3451 get_user_name(id, g_playername[id], charsmax(g_playername[]))
3452
3453 if (!g_handle_models_on_separate_ent)
3454 {
3455 // Get current model
3456 static currentmodel[32]
3457 fm_cs_get_user_model(id, currentmodel, charsmax(currentmodel))
3458
3459 // If they're different, set model again
3460 if (!equal(currentmodel, g_playermodel[id]) && !task_exists(id+TASK_MODEL))
3461 fm_cs_set_user_model(id+TASK_MODEL)
3462 }
3463}
3464
3465// Forward Get Game Description
3466public fw_GetGameDescription()
3467{
3468 // Return the mod name so it can be easily identified
3469 forward_return(FMV_STRING, g_modname)
3470
3471 return FMRES_SUPERCEDE;
3472}
3473
3474// Forward Set Model
3475public fw_SetModel(entity, const model[])
3476{
3477 // We don't care
3478 if (strlen(model) < 8)
3479 return;
3480
3481 // Remove weapons?
3482 if (get_pcvar_float(cvar_removedropped) > 0.0)
3483 {
3484 // Get entity's classname
3485 static classname[10]
3486 pev(entity, pev_classname, classname, charsmax(classname))
3487
3488 // Check if it's a weapon box
3489 if (equal(classname, "weaponbox"))
3490 {
3491 // They get automatically removed when thinking
3492 set_pev(entity, pev_nextthink, get_gametime() + get_pcvar_float(cvar_removedropped))
3493 return;
3494 }
3495 }
3496
3497 // Narrow down our matches a bit
3498 if (model[7] != 'w' || model[8] != '_')
3499 return;
3500
3501 // Get damage time of grenade
3502 static Float:dmgtime
3503 pev(entity, pev_dmgtime, dmgtime)
3504
3505 // Grenade not yet thrown
3506 if (dmgtime == 0.0)
3507 return;
3508
3509 // Get whether grenade's owner is a zombie
3510 if (g_zombie[pev(entity, pev_owner)])
3511 {
3512 if (model[9] == 'h' && model[10] == 'e' && get_pcvar_num(cvar_extrainfbomb)) // Infection Bomb
3513 {
3514 // Give it a glow
3515 fm_set_rendering(entity, kRenderFxGlowShell, 0, 200, 0, kRenderNormal, 16);
3516
3517 // And a colored trail
3518 message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
3519 write_byte(TE_BEAMFOLLOW) // TE id
3520 write_short(entity) // entity
3521 write_short(g_trailSpr) // sprite
3522 write_byte(10) // life
3523 write_byte(10) // width
3524 write_byte(0) // r
3525 write_byte(200) // g
3526 write_byte(0) // b
3527 write_byte(200) // brightness
3528 message_end()
3529
3530 // Set grenade type on the thrown grenade entity
3531 set_pev(entity, PEV_NADE_TYPE, NADE_TYPE_INFECTION)
3532 }
3533 }
3534 else if (model[9] == 'h' && model[10] == 'e' && get_pcvar_num(cvar_firegrenades)) // Napalm Grenade
3535 {
3536 // Give it a glow
3537 fm_set_rendering(entity, kRenderFxGlowShell, 200, 0, 0, kRenderNormal, 16);
3538
3539 // And a colored trail
3540 message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
3541 write_byte(TE_BEAMFOLLOW) // TE id
3542 write_short(entity) // entity
3543 write_short(g_trailSpr) // sprite
3544 write_byte(10) // life
3545 write_byte(10) // width
3546 write_byte(200) // r
3547 write_byte(0) // g
3548 write_byte(0) // b
3549 write_byte(200) // brightness
3550 message_end()
3551
3552 // Set grenade type on the thrown grenade entity
3553 set_pev(entity, PEV_NADE_TYPE, NADE_TYPE_NAPALM)
3554 }
3555 else if (model[9] == 'f' && model[10] == 'l' && get_pcvar_num(cvar_frostgrenades)) // Frost Grenade
3556 {
3557 // Give it a glow
3558 fm_set_rendering(entity, kRenderFxGlowShell, 0, 100, 200, kRenderNormal, 16);
3559
3560 // And a colored trail
3561 message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
3562 write_byte(TE_BEAMFOLLOW) // TE id
3563 write_short(entity) // entity
3564 write_short(g_trailSpr) // sprite
3565 write_byte(10) // life
3566 write_byte(10) // width
3567 write_byte(0) // r
3568 write_byte(100) // g
3569 write_byte(200) // b
3570 write_byte(200) // brightness
3571 message_end()
3572
3573 // Set grenade type on the thrown grenade entity
3574 set_pev(entity, PEV_NADE_TYPE, NADE_TYPE_FROST)
3575 }
3576 else if (model[9] == 's' && model[10] == 'm' && get_pcvar_num(cvar_flaregrenades)) // Flare
3577 {
3578 // Build flare's color
3579 static rgb[3]
3580 switch (get_pcvar_num(cvar_flarecolor))
3581 {
3582 case 0: // white
3583 {
3584 rgb[0] = 255 // r
3585 rgb[1] = 255 // g
3586 rgb[2] = 255 // b
3587 }
3588 case 1: // red
3589 {
3590 rgb[0] = random_num(50,255) // r
3591 rgb[1] = 0 // g
3592 rgb[2] = 0 // b
3593 }
3594 case 2: // green
3595 {
3596 rgb[0] = 0 // r
3597 rgb[1] = random_num(50,255) // g
3598 rgb[2] = 0 // b
3599 }
3600 case 3: // blue
3601 {
3602 rgb[0] = 0 // r
3603 rgb[1] = 0 // g
3604 rgb[2] = random_num(50,255) // b
3605 }
3606 case 4: // random (all colors)
3607 {
3608 rgb[0] = random_num(50,200) // r
3609 rgb[1] = random_num(50,200) // g
3610 rgb[2] = random_num(50,200) // b
3611 }
3612 case 5: // random (r,g,b)
3613 {
3614 switch (random_num(1, 3))
3615 {
3616 case 1: // red
3617 {
3618 rgb[0] = random_num(50,255) // r
3619 rgb[1] = 0 // g
3620 rgb[2] = 0 // b
3621 }
3622 case 2: // green
3623 {
3624 rgb[0] = 0 // r
3625 rgb[1] = random_num(50,255) // g
3626 rgb[2] = 0 // b
3627 }
3628 case 3: // blue
3629 {
3630 rgb[0] = 0 // r
3631 rgb[1] = 0 // g
3632 rgb[2] = random_num(50,255) // b
3633 }
3634 }
3635 }
3636 }
3637
3638 // Give it a glow
3639 fm_set_rendering(entity, kRenderFxGlowShell, rgb[0], rgb[1], rgb[2], kRenderNormal, 16);
3640
3641 // And a colored trail
3642 message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
3643 write_byte(TE_BEAMFOLLOW) // TE id
3644 write_short(entity) // entity
3645 write_short(g_trailSpr) // sprite
3646 write_byte(10) // life
3647 write_byte(10) // width
3648 write_byte(rgb[0]) // r
3649 write_byte(rgb[1]) // g
3650 write_byte(rgb[2]) // b
3651 write_byte(200) // brightness
3652 message_end()
3653
3654 // Set grenade type on the thrown grenade entity
3655 set_pev(entity, PEV_NADE_TYPE, NADE_TYPE_FLARE)
3656
3657 // Set flare color on the thrown grenade entity
3658 set_pev(entity, PEV_FLARE_COLOR, rgb)
3659 }
3660}
3661
3662// Ham Grenade Think Forward
3663public fw_ThinkGrenade(entity)
3664{
3665 // Invalid entity
3666 if (!pev_valid(entity)) return HAM_IGNORED;
3667
3668 // Get damage time of grenade
3669 static Float:dmgtime, Float:current_time
3670 pev(entity, pev_dmgtime, dmgtime)
3671 current_time = get_gametime()
3672
3673 // Check if it's time to go off
3674 if (dmgtime > current_time)
3675 return HAM_IGNORED;
3676
3677 // Check if it's one of our custom nades
3678 switch (pev(entity, PEV_NADE_TYPE))
3679 {
3680 case NADE_TYPE_INFECTION: // Infection Bomb
3681 {
3682 infection_explode(entity)
3683 return HAM_SUPERCEDE;
3684 }
3685 case NADE_TYPE_NAPALM: // Napalm Grenade
3686 {
3687 fire_explode(entity)
3688 return HAM_SUPERCEDE;
3689 }
3690 case NADE_TYPE_FROST: // Frost Grenade
3691 {
3692 frost_explode(entity)
3693 return HAM_SUPERCEDE;
3694 }
3695 case NADE_TYPE_FLARE: // Flare
3696 {
3697 // Get its duration
3698 static duration
3699 duration = pev(entity, PEV_FLARE_DURATION)
3700
3701 // Already went off, do lighting loop for the duration of PEV_FLARE_DURATION
3702 if (duration > 0)
3703 {
3704 // Check whether this is the last loop
3705 if (duration == 1)
3706 {
3707 // Get rid of the flare entity
3708 engfunc(EngFunc_RemoveEntity, entity)
3709 return HAM_SUPERCEDE;
3710 }
3711
3712 // Light it up!
3713 flare_lighting(entity, duration)
3714
3715 // Set time for next loop
3716 set_pev(entity, PEV_FLARE_DURATION, --duration)
3717 set_pev(entity, pev_dmgtime, current_time + 2.0)
3718 }
3719 // Light up when it's stopped on ground
3720 else if ((pev(entity, pev_flags) & FL_ONGROUND) && fm_get_speed(entity) < 10)
3721 {
3722 // Flare sound
3723 static sound[64]
3724 ArrayGetString(grenade_flare, random_num(0, ArraySize(grenade_flare) - 1), sound, charsmax(sound))
3725 emit_sound(entity, CHAN_WEAPON, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
3726
3727 // Set duration and start lightning loop on next think
3728 set_pev(entity, PEV_FLARE_DURATION, 1 + get_pcvar_num(cvar_flareduration)/2)
3729 set_pev(entity, pev_dmgtime, current_time + 0.1)
3730 }
3731 else
3732 {
3733 // Delay explosion until we hit ground
3734 set_pev(entity, pev_dmgtime, current_time + 0.5)
3735 }
3736 }
3737 }
3738
3739 return HAM_IGNORED;
3740}
3741
3742// Forward CmdStart
3743public fw_CmdStart(id, handle)
3744{
3745 // Not alive
3746 if (!g_isalive[id])
3747 return;
3748
3749 // This logic looks kinda weird, but it should work in theory...
3750 // p = g_zombie[id], q = g_survivor[id], r = g_cached_customflash
3751 // ¬(p v q v (¬p ^ r)) <==> ¬p ^ ¬q ^ (p v ¬r)
3752 if (!g_zombie[id] && !g_survivor[id] && !g_sniper[id] && (g_zombie[id] || !g_cached_customflash))
3753 return;
3754
3755 // Check if it's a flashlight impulse
3756 if (get_uc(handle, UC_Impulse) != IMPULSE_FLASHLIGHT)
3757 return;
3758
3759 // Block it I say!
3760 set_uc(handle, UC_Impulse, 0)
3761
3762 // Should human's custom flashlight be turned on?
3763 if (!g_zombie[id] && !g_survivor[id] && !g_sniper[id] && g_flashbattery[id] > 2 && get_gametime() - g_lastflashtime[id] > 1.2)
3764 {
3765 // Prevent calling flashlight too quickly (bugfix)
3766 g_lastflashtime[id] = get_gametime()
3767
3768 // Toggle custom flashlight
3769 g_flashlight[id] = !(g_flashlight[id])
3770
3771 // Play flashlight toggle sound
3772 emit_sound(id, CHAN_ITEM, sound_flashlight, 1.0, ATTN_NORM, 0, PITCH_NORM)
3773
3774 // Update flashlight status on the HUD
3775 message_begin(MSG_ONE, g_msgFlashlight, _, id)
3776 write_byte(g_flashlight[id]) // toggle
3777 write_byte(g_flashbattery[id]) // battery
3778 message_end()
3779
3780 // Remove previous tasks
3781 remove_task(id+TASK_CHARGE)
3782 remove_task(id+TASK_FLASH)
3783
3784 // Set the flashlight charge task
3785 set_task(1.0, "flashlight_charge", id+TASK_CHARGE, _, _, "b")
3786
3787 // Call our custom flashlight task if enabled
3788 if (g_flashlight[id]) set_task(0.1, "set_user_flashlight", id+TASK_FLASH, _, _, "b")
3789 }
3790}
3791
3792// Forward Player PreThink
3793public fw_PlayerPreThink(id)
3794{
3795 // Not alive
3796 if (!g_isalive[id])
3797 return;
3798
3799 // Enable custom buyzone for player during buytime, unless zombie or survivor or time expired
3800 if (g_cached_buytime > 0.0 && !g_zombie[id] && !g_survivor[id] && (get_gametime() < g_buytime[id] + g_cached_buytime))
3801 {
3802 if (pev_valid(g_buyzone_ent))
3803 dllfunc(DLLFunc_Touch, g_buyzone_ent, id)
3804 }
3805
3806 // Silent footsteps for zombies?
3807 if (g_cached_zombiesilent && g_zombie[id] && !g_nemesis[id] && g_assassin[id])
3808 set_pev(id, pev_flTimeStepSound, STEPTIME_SILENT)
3809
3810 // Player frozen?
3811 if (g_frozen[id])
3812 {
3813 set_pev(id, pev_velocity, Float:{0.0,0.0,0.0}) // stop motion
3814 return; // shouldn't leap while frozen
3815 }
3816
3817 // --- Check if player should leap ---
3818
3819 // Don't allow leap during freezetime
3820 if (g_freezetime)
3821 return;
3822
3823 // Check if proper CVARs are enabled and retrieve leap settings
3824 static Float:cooldown, Float:current_time
3825 if (g_zombie[id])
3826 {
3827 if (g_nemesis[id])
3828 {
3829 if (!g_cached_leapnemesis) return;
3830 cooldown = g_cached_leapnemesiscooldown
3831 }
3832 else if (g_assassin[id])
3833 {
3834 if (!g_cached_leapassassin) return;
3835 cooldown = g_cached_leapassassincooldown
3836 }
3837 else
3838 {
3839 switch (g_cached_leapzombies)
3840 {
3841 case 0: return;
3842 case 2: if (!g_firstzombie[id]) return;
3843 case 3: if (!g_lastzombie[id]) return;
3844 }
3845 cooldown = g_cached_leapzombiescooldown
3846 }
3847 }
3848 else
3849 {
3850 if (g_survivor[id])
3851 {
3852 if (!g_cached_leapsurvivor) return;
3853 cooldown = g_cached_leapsurvivorcooldown
3854 }
3855 else if (g_sniper[id])
3856 {
3857 if (!g_cached_leapsniper) return;
3858 cooldown = g_cached_leapsnipercooldown
3859 }
3860 else return;
3861 }
3862
3863 current_time = get_gametime()
3864
3865 // Cooldown not over yet
3866 if (current_time - g_lastleaptime[id] < cooldown)
3867 return;
3868
3869 // Not doing a longjump (don't perform check for bots, they leap automatically)
3870 if (!g_isbot[id] && !(pev(id, pev_button) & (IN_JUMP | IN_DUCK) == (IN_JUMP | IN_DUCK)))
3871 return;
3872
3873 // Not on ground or not enough speed
3874 if (!(pev(id, pev_flags) & FL_ONGROUND) || fm_get_speed(id) < 80)
3875 return;
3876
3877 static Float:velocity[3]
3878
3879 // Make velocity vector
3880 velocity_by_aim(id, g_survivor[id] ? get_pcvar_num(cvar_leapsurvivorforce) : g_sniper[id] ? get_pcvar_num(cvar_leapsniperforce) : g_nemesis[id] ? get_pcvar_num(cvar_leapnemesisforce) : g_assassin[id] ? get_pcvar_num(cvar_leapassassinforce) : get_pcvar_num(cvar_leapzombiesforce), velocity)
3881
3882 // Set custom height
3883 velocity[2] = g_survivor[id] ? get_pcvar_float(cvar_leapsurvivorheight) : g_sniper[id] ? get_pcvar_float(cvar_leapsniperheight) : g_nemesis[id] ? get_pcvar_float(cvar_leapnemesisheight) : g_assassin[id] ? get_pcvar_float(cvar_leapassassinheight) : get_pcvar_float(cvar_leapzombiesheight)
3884
3885 // Apply the new velocity
3886 set_pev(id, pev_velocity, velocity)
3887
3888 // Update last leap time
3889 g_lastleaptime[id] = current_time
3890}
3891
3892/*================================================================================
3893 [Client Commands]
3894=================================================================================*/
3895
3896// Say "/zpmenu"
3897public clcmd_saymenu(id)
3898{
3899 show_menu_game(id) // show game menu
3900}
3901
3902// Say "/unstuck"
3903public clcmd_sayunstuck(id)
3904{
3905 menu_game(id, 3) // try to get unstuck
3906}
3907
3908// Nightvision toggle
3909public clcmd_nightvision(id)
3910{
3911 // Nightvision available to player?
3912 if (g_nvision[id] || (g_isalive[id] && cs_get_user_nvg(id)))
3913 {
3914 // Enable-disable
3915 g_nvisionenabled[id] = !(g_nvisionenabled[id])
3916
3917 // Custom nvg?
3918 if (get_pcvar_num(cvar_customnvg))
3919 {
3920 remove_task(id+TASK_NVISION)
3921 if (g_nvisionenabled[id]) set_task(0.1, "set_user_nvision", id+TASK_NVISION, _, _, "b")
3922 }
3923 else
3924 set_user_gnvision(id, g_nvisionenabled[id])
3925 }
3926
3927 return PLUGIN_HANDLED;
3928}
3929
3930// Weapon Drop
3931public clcmd_drop(id)
3932{
3933 // Survivor should stick with its weapon
3934 if (g_survivor[id] || g_sniper[id])
3935 return PLUGIN_HANDLED;
3936
3937 return PLUGIN_CONTINUE;
3938}
3939
3940// Buy BP Ammo
3941public clcmd_buyammo(id)
3942{
3943 // Not alive or infinite ammo setting enabled
3944 if (!g_isalive[id] || get_pcvar_num(cvar_infammo))
3945 return PLUGIN_HANDLED;
3946
3947 // Not human
3948 if (g_zombie[id])
3949 {
3950 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_HUMAN_ONLY")
3951 return PLUGIN_HANDLED;
3952 }
3953
3954 // Custom buytime enabled and human player standing in buyzone, allow buying weapon's ammo normally instead
3955 if (g_cached_buytime > 0.0 && !g_survivor[id] && !g_sniper[id] && (get_gametime() < g_buytime[id] + g_cached_buytime) && cs_get_user_buyzone(id))
3956 return PLUGIN_CONTINUE;
3957
3958 // Not enough ammo packs
3959 if (g_ammopacks[id] < 1)
3960 {
3961 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "NOT_ENOUGH_AMMO")
3962 return PLUGIN_HANDLED;
3963 }
3964
3965 // Get user weapons
3966 static weapons[32], num, i, currentammo, weaponid, refilled
3967 num = 0 // reset passed weapons count (bugfix)
3968 refilled = false
3969 get_user_weapons(id, weapons, num)
3970
3971 // Loop through them and give the right ammo type
3972 for (i = 0; i < num; i++)
3973 {
3974 // Prevents re-indexing the array
3975 weaponid = weapons[i]
3976
3977 // Primary and secondary only
3978 if (MAXBPAMMO[weaponid] > 2)
3979 {
3980 // Get current ammo of the weapon
3981 currentammo = cs_get_user_bpammo(id, weaponid)
3982
3983 // Give additional ammo
3984 ExecuteHamB(Ham_GiveAmmo, id, BUYAMMO[weaponid], AMMOTYPE[weaponid], MAXBPAMMO[weaponid])
3985
3986 // Check whether we actually refilled the weapon's ammo
3987 if (cs_get_user_bpammo(id, weaponid) - currentammo > 0) refilled = true
3988 }
3989 }
3990
3991 // Weapons already have full ammo
3992 if (!refilled) return PLUGIN_HANDLED;
3993
3994 // Deduce ammo packs, play clip purchase sound, and notify player
3995 g_ammopacks[id]--
3996 emit_sound(id, CHAN_ITEM, sound_buyammo, 1.0, ATTN_NORM, 0, PITCH_NORM)
3997 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "AMMO_BOUGHT")
3998
3999 return PLUGIN_HANDLED;
4000}
4001
4002// Block Team Change
4003public clcmd_changeteam(id)
4004{
4005 static team
4006 team = fm_cs_get_user_team(id)
4007
4008 // Unless it's a spectator joining the game
4009 if (team == FM_CS_TEAM_SPECTATOR || team == FM_CS_TEAM_UNASSIGNED)
4010 return PLUGIN_CONTINUE;
4011
4012 // Pressing 'M' (chooseteam) ingame should show the main menu instead
4013 show_menu_game(id)
4014 return PLUGIN_HANDLED;
4015}
4016
4017/*================================================================================
4018 [Menus]
4019=================================================================================*/
4020
4021// Game Menu
4022show_menu_game(id)
4023{
4024 // Player disconnected?
4025 if (!g_isconnected[id])
4026 return;
4027
4028 static menu[250], len, userflags
4029 len = 0
4030 userflags = get_user_flags(id)
4031
4032 // Title
4033 len += formatex(menu[len], charsmax(menu) - len, "\y%s^n^n", g_modname)
4034
4035 // 1. Buy weapons
4036 if (get_pcvar_num(cvar_buycustom))
4037 len += formatex(menu[len], charsmax(menu) - len, "\r1.\w %L^n", id, "MENU_BUY")
4038 else
4039 len += formatex(menu[len], charsmax(menu) - len, "\d1. %L^n", id, "MENU_BUY")
4040
4041 // 2. Extra items
4042 if (get_pcvar_num(cvar_extraitems) && g_isalive[id])
4043 len += formatex(menu[len], charsmax(menu) - len, "\r2.\w %L^n", id, "MENU_EXTRABUY")
4044 else
4045 len += formatex(menu[len], charsmax(menu) - len, "\d2. %L^n", id, "MENU_EXTRABUY")
4046
4047 // 3. Zombie class
4048 if (get_pcvar_num(cvar_zclasses))
4049 len += formatex(menu[len], charsmax(menu) - len, "\r3.\w %L^n", id,"MENU_ZCLASS")
4050 else
4051 len += formatex(menu[len], charsmax(menu) - len, "\d3. %L^n", id,"MENU_ZCLASS")
4052
4053 // 4. Unstuck
4054 if (g_isalive[id])
4055 len += formatex(menu[len], charsmax(menu) - len, "\r4.\w %L^n", id, "MENU_UNSTUCK")
4056 else
4057 len += formatex(menu[len], charsmax(menu) - len, "\d4. %L^n", id, "MENU_UNSTUCK")
4058
4059 // 5. Help
4060 len += formatex(menu[len], charsmax(menu) - len, "\r5.\w %L^n^n", id, "MENU_INFO")
4061
4062 // 6. Join spec
4063 if (!g_isalive[id] || !get_pcvar_num(cvar_blocksuicide) || (userflags & g_access_flag[ACCESS_ADMIN_MENU]))
4064 len += formatex(menu[len], charsmax(menu) - len, "\r6.\w %L^n^n", id, "MENU_SPECTATOR")
4065 else
4066 len += formatex(menu[len], charsmax(menu) - len, "\d6. %L^n^n", id, "MENU_SPECTATOR")
4067
4068 // 9. Admin menu
4069 if (userflags & g_access_flag[ACCESS_ADMIN_MENU])
4070 len += formatex(menu[len], charsmax(menu) - len, "\r9.\w %L", id, "MENU_ADMIN")
4071 else
4072 len += formatex(menu[len], charsmax(menu) - len, "\d9. %L", id, "MENU_ADMIN")
4073
4074 // 0. Exit
4075 len += formatex(menu[len], charsmax(menu) - len, "^n^n\r0.\w %L", id, "MENU_EXIT")
4076
4077 // Fix for AMXX custom menus
4078 if (pev_valid(id) == PDATA_SAFE)
4079 set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
4080
4081 show_menu(id, KEYSMENU, menu, -1, "Game Menu")
4082}
4083
4084// Buy Menu 1
4085public show_menu_buy1(taskid)
4086{
4087 // Get player's id
4088 static id
4089 (taskid > g_maxplayers) ? (id = ID_SPAWN) : (id = taskid);
4090
4091 // Player dead?
4092 if (!g_isalive[id])
4093 return;
4094
4095 // Zombies or survivors get no guns
4096 if (g_zombie[id] || g_survivor[id] || g_sniper[id])
4097 return;
4098
4099 // Bots pick their weapons randomly / Random weapons setting enabled
4100 if (get_pcvar_num(cvar_randweapons) || g_isbot[id])
4101 {
4102 buy_primary_weapon(id, random_num(0, ArraySize(g_primary_items) - 1))
4103 menu_buy2(id, random_num(0, ArraySize(g_secondary_items) - 1))
4104 return;
4105 }
4106
4107 // Automatic selection enabled for player and menu called on spawn event
4108 if (WPN_AUTO_ON && taskid > g_maxplayers)
4109 {
4110 buy_primary_weapon(id, WPN_AUTO_PRI)
4111 menu_buy2(id, WPN_AUTO_SEC)
4112 return;
4113 }
4114
4115 static menu[300], len, weap, maxloops
4116 len = 0
4117 maxloops = min(WPN_STARTID+7, WPN_MAXIDS)
4118
4119 // Title
4120 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))
4121
4122 // 1-7. Weapon List
4123 for (weap = WPN_STARTID; weap < maxloops; weap++)
4124 len += formatex(menu[len], charsmax(menu) - len, "\r%d.\w %s^n", weap-WPN_STARTID+1, WEAPONNAMES[ArrayGetCell(g_primary_weaponids, weap)])
4125
4126 // 8. Auto Select
4127 len += formatex(menu[len], charsmax(menu) - len, "^n\r8.\w %L \y[%L]", id, "MENU_AUTOSELECT", id, (WPN_AUTO_ON) ? "MOTD_ENABLED" : "MOTD_DISABLED")
4128
4129 // 9. Next/Back - 0. Exit
4130 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")
4131
4132 // Fix for AMXX custom menus
4133 if (pev_valid(id) == PDATA_SAFE)
4134 set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
4135
4136 show_menu(id, KEYSMENU, menu, -1, "Buy Menu 1")
4137}
4138
4139// Buy Menu 2
4140show_menu_buy2(id)
4141{
4142 // Player dead?
4143 if (!g_isalive[id])
4144 return;
4145
4146 static menu[250], len, weap, maxloops
4147 len = 0
4148 maxloops = ArraySize(g_secondary_items)
4149
4150 // Title
4151 len += formatex(menu[len], charsmax(menu) - len, "\y%L^n", id, "MENU_BUY2_TITLE")
4152
4153 // 1-6. Weapon List
4154 for (weap = 0; weap < maxloops; weap++)
4155 len += formatex(menu[len], charsmax(menu) - len, "^n\r%d.\w %s", weap+1, WEAPONNAMES[ArrayGetCell(g_secondary_weaponids, weap)])
4156
4157 // 8. Auto Select
4158 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")
4159
4160 // 0. Exit
4161 len += formatex(menu[len], charsmax(menu) - len, "^n^n\r0.\w %L", id, "MENU_EXIT")
4162
4163 // Fix for AMXX custom menus
4164 if (pev_valid(id) == PDATA_SAFE)
4165 set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
4166
4167 show_menu(id, KEYSMENU, menu, -1, "Buy Menu 2")
4168}
4169
4170// Extra Items Menu
4171show_menu_extras(id)
4172{
4173 // Player dead?
4174 if (!g_isalive[id])
4175 return;
4176
4177 static menuid, menu[128], item, team, buffer[32]
4178
4179 // Title
4180 formatex(menu, charsmax(menu), "%L [%L]\r", id, "MENU_EXTRA_TITLE", id, g_nemesis[id] ? "CLASS_NEMESIS" : g_assassin[id] ? "CLASS_ASSASSIN" : g_zombie[id] ? "CLASS_ZOMBIE" : g_survivor[id] ? "CLASS_SURVIVOR" : g_sniper[id] ? "CLASS_SNIPER" : "CLASS_HUMAN")
4181 menuid = menu_create(menu, "menu_extras")
4182
4183 // Item List
4184 for (item = 0; item < g_extraitem_i; item++)
4185 {
4186 // Retrieve item's team
4187 team = ArrayGetCell(g_extraitem_team, item)
4188
4189 // Item not available to player's team/class
4190 if ((g_zombie[id] && !g_nemesis[id] && !g_assassin[id] && !(team & ZP_TEAM_ZOMBIE)) || (!g_zombie[id] && !g_survivor[id] && !g_sniper[id] && !(team & ZP_TEAM_HUMAN)) || (g_nemesis[id] && !(team & ZP_TEAM_NEMESIS)) || (g_assassin[id] && !(team & ZP_TEAM_ASSASSIN)) || (g_survivor[id] && !(team & ZP_TEAM_SURVIVOR)) || (g_sniper[id] && !(team & ZP_TEAM_SNIPER)))
4191 continue;
4192
4193 // Check if it's one of the hardcoded items, check availability, set translated caption
4194 switch (item)
4195 {
4196 case EXTRA_NVISION:
4197 {
4198 if (!get_pcvar_num(cvar_extranvision)) continue;
4199 formatex(buffer, charsmax(buffer), "%L", id, "MENU_EXTRA1")
4200 }
4201 case EXTRA_ANTIDOTE:
4202 {
4203 if (!get_pcvar_num(cvar_extraantidote) || g_antidotecounter >= get_pcvar_num(cvar_antidotelimit)) continue;
4204 formatex(buffer, charsmax(buffer), "%L", id, "MENU_EXTRA2")
4205 }
4206 case EXTRA_MADNESS:
4207 {
4208 if (!get_pcvar_num(cvar_extramadness) || g_madnesscounter >= get_pcvar_num(cvar_madnesslimit)) continue;
4209 formatex(buffer, charsmax(buffer), "%L", id, "MENU_EXTRA3")
4210 }
4211 case EXTRA_INFBOMB:
4212 {
4213 if (!get_pcvar_num(cvar_extrainfbomb) || g_infbombcounter >= get_pcvar_num(cvar_infbomblimit)) continue;
4214 formatex(buffer, charsmax(buffer), "%L", id, "MENU_EXTRA4")
4215 }
4216 default:
4217 {
4218 if (item >= EXTRA_WEAPONS_STARTID && item <= EXTRAS_CUSTOM_STARTID-1 && !get_pcvar_num(cvar_extraweapons)) continue;
4219 ArrayGetString(g_extraitem_name, item, buffer, charsmax(buffer))
4220 }
4221 }
4222
4223 // Add Item Name and Cost
4224 formatex(menu, charsmax(menu), "%s \y%d %L", buffer, ArrayGetCell(g_extraitem_cost, item), id, "AMMO_PACKS2")
4225 buffer[0] = item
4226 buffer[1] = 0
4227 menu_additem(menuid, menu, buffer)
4228 }
4229
4230 // No items to display?
4231 if (menu_items(menuid) <= 0)
4232 {
4233 zp_colored_print(id, "^x04[ZP]^x01 %L", id ,"CMD_NOT_EXTRAS")
4234 menu_destroy(menuid)
4235 return;
4236 }
4237
4238 // Back - Next - Exit
4239 formatex(menu, charsmax(menu), "%L", id, "MENU_BACK")
4240 menu_setprop(menuid, MPROP_BACKNAME, menu)
4241 formatex(menu, charsmax(menu), "%L", id, "MENU_NEXT")
4242 menu_setprop(menuid, MPROP_NEXTNAME, menu)
4243 formatex(menu, charsmax(menu), "%L", id, "MENU_EXIT")
4244 menu_setprop(menuid, MPROP_EXITNAME, menu)
4245
4246 // If remembered page is greater than number of pages, clamp down the value
4247 MENU_PAGE_EXTRAS = min(MENU_PAGE_EXTRAS, menu_pages(menuid)-1)
4248
4249 // Fix for AMXX custom menus
4250 if (pev_valid(id) == PDATA_SAFE)
4251 set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
4252
4253 menu_display(id, menuid, MENU_PAGE_EXTRAS)
4254}
4255
4256// Zombie Class Menu
4257public show_menu_zclass(id)
4258{
4259 // Player disconnected
4260 if (!g_isconnected[id])
4261 return;
4262
4263 // Bots pick their zombie class randomly
4264 if (g_isbot[id])
4265 {
4266 g_zombieclassnext[id] = random_num(0, g_zclass_i - 1)
4267 return;
4268 }
4269
4270 static menuid, menu[128], class, buffer[32], buffer2[32]
4271
4272 // Title
4273 formatex(menu, charsmax(menu), "%L\r", id, "MENU_ZCLASS_TITLE")
4274 menuid = menu_create(menu, "menu_zclass")
4275
4276 // Class List
4277 for (class = 0; class < g_zclass_i; class++)
4278 {
4279 // Retrieve name and info
4280 ArrayGetString(g_zclass_name, class, buffer, charsmax(buffer))
4281 ArrayGetString(g_zclass_info, class, buffer2, charsmax(buffer2))
4282
4283 // Add to menu
4284 if (class == g_zombieclassnext[id])
4285 formatex(menu, charsmax(menu), "\d%s %s", buffer, buffer2)
4286 else
4287 formatex(menu, charsmax(menu), "%s \y%s", buffer, buffer2)
4288
4289 buffer[0] = class
4290 buffer[1] = 0
4291 menu_additem(menuid, menu, buffer)
4292 }
4293
4294 // Back - Next - Exit
4295 formatex(menu, charsmax(menu), "%L", id, "MENU_BACK")
4296 menu_setprop(menuid, MPROP_BACKNAME, menu)
4297 formatex(menu, charsmax(menu), "%L", id, "MENU_NEXT")
4298 menu_setprop(menuid, MPROP_NEXTNAME, menu)
4299 formatex(menu, charsmax(menu), "%L", id, "MENU_EXIT")
4300 menu_setprop(menuid, MPROP_EXITNAME, menu)
4301
4302 // If remembered page is greater than number of pages, clamp down the value
4303 MENU_PAGE_ZCLASS = min(MENU_PAGE_ZCLASS, menu_pages(menuid)-1)
4304
4305 // Fix for AMXX custom menus
4306 if (pev_valid(id) == PDATA_SAFE)
4307 set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
4308
4309 menu_display(id, menuid, MENU_PAGE_ZCLASS)
4310}
4311
4312// Help Menu
4313show_menu_info(id)
4314{
4315 // Player disconnected?
4316 if (!g_isconnected[id])
4317 return;
4318
4319 static menu[150]
4320
4321 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")
4322
4323 // Fix for AMXX custom menus
4324 if (pev_valid(id) == PDATA_SAFE)
4325 set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
4326
4327 show_menu(id, KEYSMENU, menu, -1, "Mod Info")
4328}
4329
4330// Admin Menu
4331show_menu_admin(id)
4332{
4333 // Player disconnected?
4334 if (!g_isconnected[id])
4335 return;
4336
4337 static menu[250], len, userflags
4338 len = 0
4339 userflags = get_user_flags(id)
4340
4341 // Title
4342 len += formatex(menu[len], charsmax(menu) - len, "\y%L^n^n", id, "MENU_ADMIN_TITLE")
4343
4344 // 1. Zombiefy/Humanize command
4345 if (userflags & (g_access_flag[ACCESS_MODE_INFECTION] | g_access_flag[ACCESS_MAKE_ZOMBIE] | g_access_flag[ACCESS_MAKE_HUMAN]))
4346 len += formatex(menu[len], charsmax(menu) - len, "\r1.\w %L^n", id, "MENU_ADMIN1")
4347 else
4348 len += formatex(menu[len], charsmax(menu) - len, "\d1. %L^n", id, "MENU_ADMIN1")
4349
4350 // 2. Nemesis command
4351 if (userflags & (g_access_flag[ACCESS_MODE_NEMESIS] | g_access_flag[ACCESS_MAKE_NEMESIS]))
4352 len += formatex(menu[len], charsmax(menu) - len, "\r2.\w %L^n", id, "MENU_ADMIN2")
4353 else
4354 len += formatex(menu[len], charsmax(menu) - len, "\d2. %L^n", id, "MENU_ADMIN2")
4355
4356 // 3. Assassin command
4357 if (userflags & (g_access_flag[ACCESS_MODE_ASSASSIN] | g_access_flag[ACCESS_MAKE_ASSASSIN]))
4358 len += formatex(menu[len], charsmax(menu) - len, "\r3.\w %L^n", id, "MENU_ADMIN9")
4359 else
4360 len += formatex(menu[len], charsmax(menu) - len, "\d3. %L^n", id, "MENU_ADMIN9")
4361
4362 // 4. Survivor command
4363 if (userflags & (g_access_flag[ACCESS_MODE_SURVIVOR] | g_access_flag[ACCESS_MAKE_SURVIVOR]))
4364 len += formatex(menu[len], charsmax(menu) - len, "\r4.\w %L^n", id, "MENU_ADMIN3")
4365 else
4366 len += formatex(menu[len], charsmax(menu) - len, "\d4. %L^n", id, "MENU_ADMIN3")
4367
4368 // 5. Sniper command
4369 if (userflags & (g_access_flag[ACCESS_MODE_SNIPER] | g_access_flag[ACCESS_MAKE_SNIPER]))
4370 len += formatex(menu[len], charsmax(menu) - len, "\r5.\w %L^n", id, "MENU_ADMIN8")
4371 else
4372 len += formatex(menu[len], charsmax(menu) - len, "\d5. %L^n", id, "MENU_ADMIN8")
4373
4374 // 6. Respawn command
4375 if (userflags & g_access_flag[ACCESS_RESPAWN_PLAYERS])
4376 len += formatex(menu[len], charsmax(menu) - len, "\r6.\w %L^n", id, "MENU_ADMIN4")
4377 else
4378 len += formatex(menu[len], charsmax(menu) - len, "\d6. %L^n", id, "MENU_ADMIN4")
4379
4380 // 7. Admin modes command
4381 if (userflags & g_access_flag[ACCESS_ADMIN_MODES_MENU])
4382 len += formatex(menu[len], charsmax(menu) - len, "\r7.\w %L^n", id, "MENU_ADMIN10")
4383 else
4384 len += formatex(menu[len], charsmax(menu) - len, "\d7. %L^n", id, "MENU_ADMIN10")
4385
4386 // 0. Exit
4387 len += formatex(menu[len], charsmax(menu) - len, "^n\r0.\w %L", id, "MENU_EXIT")
4388
4389 // Fix for AMXX custom menus
4390 if (pev_valid(id) == PDATA_SAFE)
4391 set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
4392
4393 show_menu(id, KEYSMENU, menu, -1, "Admin Menu")
4394}
4395
4396// Admin Modes Menu
4397show_menu_modes_admin(id)
4398{
4399 static menu[250], len, userflags
4400 len = 0
4401 userflags = get_user_flags(id)
4402
4403 // Title
4404 len += formatex(menu[len], charsmax(menu) - len, "\y%L^n^n", id, "MENU_ADMIN_MODES_TITLE")
4405
4406 // 1. Swarm mode command
4407 if ((userflags & g_access_flag[ACCESS_MODE_SWARM]) && allowed_swarm())
4408 len += formatex(menu[len], charsmax(menu) - len, "\r1.\w %L^n", id, "MENU_ADMIN5")
4409 else
4410 len += formatex(menu[len], charsmax(menu) - len, "\d1. %L^n", id, "MENU_ADMIN5")
4411
4412 // 2. Multi infection command
4413 if ((userflags & g_access_flag[ACCESS_MODE_MULTI]) && allowed_multi())
4414 len += formatex(menu[len], charsmax(menu) - len, "\r2.\w %L^n", id, "MENU_ADMIN6")
4415 else
4416 len += formatex(menu[len], charsmax(menu) - len, "\d2. %L^n", id, "MENU_ADMIN6")
4417
4418 // 3. Plague mode command
4419 if ((userflags & g_access_flag[ACCESS_MODE_PLAGUE]) && allowed_plague())
4420 len += formatex(menu[len], charsmax(menu) - len, "\r3.\w %L^n", id, "MENU_ADMIN7")
4421 else
4422 len += formatex(menu[len], charsmax(menu) - len, "\d3. %L^n", id, "MENU_ADMIN7")
4423
4424 // 4. Armageddon mode command
4425 if ((userflags & g_access_flag[ACCESS_MODE_ARMAGEDDON]) && allowed_armageddon())
4426 len += formatex(menu[len], charsmax(menu) - len, "\r4.\w %L^n", id, "MENU_ADMIN11")
4427 else
4428 len += formatex(menu[len], charsmax(menu) - len, "\d4. %L^n", id, "MENU_ADMIN11")
4429
4430 // 5. Apocalypse mode command
4431 if ((userflags & g_access_flag[ACCESS_MODE_APOCALYPSE]) && allowed_apocalypse())
4432 len += formatex(menu[len], charsmax(menu) - len, "\r5.\w %L^n", id, "MENU_ADMIN12")
4433 else
4434 len += formatex(menu[len], charsmax(menu) - len, "\d5. %L^n", id, "MENU_ADMIN12")
4435
4436 // 6. Nightmare mode command
4437 if ((userflags & g_access_flag[ACCESS_MODE_NIGHTMARE]) && allowed_nightmare())
4438 len += formatex(menu[len], charsmax(menu) - len, "\r6.\w %L^n", id, "MENU_ADMIN13")
4439 else
4440 len += formatex(menu[len], charsmax(menu) - len, "\d6. %L^n", id, "MENU_ADMIN13")
4441
4442 // 0. Exit
4443 len += formatex(menu[len], charsmax(menu) - len, "^n\r0. \wExit")
4444
4445 show_menu(id, KEYSMENU, menu, -1, "Admin Modes Menu")
4446}
4447
4448// Player List Menu
4449show_menu_player_list(id)
4450{
4451 // Player disconnected?
4452 if (!g_isconnected[id])
4453 return;
4454
4455 static menuid, menu[128], player, userflags, buffer[2]
4456 userflags = get_user_flags(id)
4457
4458 // Title
4459 switch (PL_ACTION)
4460 {
4461 case ACTION_ZOMBIEFY_HUMANIZE: formatex(menu, charsmax(menu), "%L\r", id, "MENU_ADMIN1")
4462 case ACTION_MAKE_NEMESIS: formatex(menu, charsmax(menu), "%L\r", id, "MENU_ADMIN2")
4463 case ACTION_MAKE_ASSASSIN: formatex(menu, charsmax(menu), "%L\r", id, "MENU_ADMIN9")
4464 case ACTION_MAKE_SURVIVOR: formatex(menu, charsmax(menu), "%L\r", id, "MENU_ADMIN3")
4465 case ACTION_MAKE_SNIPER: formatex(menu, charsmax(menu), "%L\r", id, "MENU_ADMIN8")
4466 case ACTION_RESPAWN_PLAYER: formatex(menu, charsmax(menu), "%L\r", id, "MENU_ADMIN4")
4467 }
4468 menuid = menu_create(menu, "menu_player_list")
4469
4470 // Player List
4471 for (player = 0; player <= g_maxplayers; player++)
4472 {
4473 // Skip if not connected
4474 if (!g_isconnected[player])
4475 continue;
4476
4477 // Format text depending on the action to take
4478 switch (PL_ACTION)
4479 {
4480 case ACTION_ZOMBIEFY_HUMANIZE: // Zombiefy/Humanize command
4481 {
4482 if (g_zombie[player])
4483 {
4484 if (allowed_human(player) && (userflags & g_access_flag[ACCESS_MAKE_HUMAN]))
4485 formatex(menu, charsmax(menu), "%s \r[%L]", g_playername[player], id, g_nemesis[player] ? "CLASS_NEMESIS" : "CLASS_ZOMBIE")
4486 else
4487 formatex(menu, charsmax(menu), "\d%s [%L]", g_playername[player], id, g_nemesis[player] ? "CLASS_NEMESIS" : "CLASS_ZOMBIE")
4488 }
4489 else
4490 {
4491 if (allowed_zombie(player) && (g_newround ? (userflags & g_access_flag[ACCESS_MODE_INFECTION]) : (userflags & g_access_flag[ACCESS_MAKE_ZOMBIE])))
4492 formatex(menu, charsmax(menu), "%s \y[%L]", g_playername[player], id, g_survivor[player] ? "CLASS_SURVIVOR" : "CLASS_HUMAN")
4493 else
4494 formatex(menu, charsmax(menu), "\d%s [%L]", g_playername[player], id, g_survivor[player] ? "CLASS_SURVIVOR" : "CLASS_HUMAN")
4495 }
4496 }
4497 case ACTION_MAKE_NEMESIS: // Nemesis command
4498 {
4499 if (allowed_nemesis(player) && (g_newround ? (userflags & g_access_flag[ACCESS_MODE_NEMESIS]) : (userflags & g_access_flag[ACCESS_MAKE_NEMESIS])))
4500 {
4501 if (g_zombie[player])
4502 formatex(menu, charsmax(menu), "%s \r[%L]", g_playername[player], id, g_nemesis[player] ? "CLASS_NEMESIS" : "CLASS_ZOMBIE")
4503 else
4504 formatex(menu, charsmax(menu), "%s \y[%L]", g_playername[player], id, g_survivor[player] ? "CLASS_SURVIVOR" : "CLASS_HUMAN")
4505 }
4506 else
4507 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")
4508 }
4509 case ACTION_MAKE_ASSASSIN: // Assassin command
4510 {
4511 if (allowed_assassin(player) && (g_newround ? (userflags & g_access_flag[ACCESS_MODE_ASSASSIN]) : (userflags & g_access_flag[ACCESS_MAKE_ASSASSIN])))
4512 {
4513 if (g_zombie[player])
4514 formatex(menu, charsmax(menu), "%s \r[%L]", g_playername[player], id, g_nemesis[player] ? "CLASS_NEMESIS" : g_assassin[player] ? "CLASS_ASSASSIN" : "CLASS_ZOMBIE")
4515 else
4516 formatex(menu, charsmax(menu), "%s \y[%L]", g_playername[player], id, g_survivor[player] ? "CLASS_SURVIVOR" : g_sniper[player] ? "CLASS_SNIPER" : "CLASS_HUMAN")
4517 }
4518 else
4519 formatex(menu, charsmax(menu), "\d%s [%L]", g_playername[player], id, g_zombie[player] ? g_nemesis[player] ? "CLASS_NEMESIS" : g_assassin[player] ? "CLASS_ASSASSIN" : "CLASS_ZOMBIE" : g_survivor[player] ? "CLASS_SURVIVOR" : g_sniper[player] ? "CLASS_SNIPER" : "CLASS_HUMAN")
4520 }
4521 case ACTION_MAKE_SURVIVOR: // Survivor command
4522 {
4523 if (allowed_survivor(player) && (g_newround ? (userflags & g_access_flag[ACCESS_MODE_SURVIVOR]) : (userflags & g_access_flag[ACCESS_MAKE_SURVIVOR])))
4524 {
4525 if (g_zombie[player])
4526 formatex(menu, charsmax(menu), "%s \r[%L]", g_playername[player], id, g_nemesis[player] ? "CLASS_NEMESIS" : "CLASS_ZOMBIE")
4527 else
4528 formatex(menu, charsmax(menu), "%s \y[%L]", g_playername[player], id, g_survivor[player] ? "CLASS_SURVIVOR" : "CLASS_HUMAN")
4529 }
4530 else
4531 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")
4532 }
4533 case ACTION_MAKE_SNIPER: // Sniper command
4534 {
4535 if (allowed_sniper(player) && (g_newround ? (userflags & g_access_flag[ACCESS_MODE_SNIPER]) : (userflags & g_access_flag[ACCESS_MAKE_SNIPER])))
4536 {
4537 if (g_zombie[player])
4538 formatex(menu, charsmax(menu), "%s \r[%L]", g_playername[player], id, g_nemesis[player] ? "CLASS_NEMESIS" : g_assassin[player] ? "CLASS_ASSASSIN" : "CLASS_ZOMBIE")
4539 else
4540 formatex(menu, charsmax(menu), "%s \y[%L]", g_playername[player], id, g_survivor[player] ? "CLASS_SURVIVOR" : g_sniper[player] ? "CLASS_SNIPER" : "CLASS_HUMAN")
4541 }
4542 else
4543 formatex(menu, charsmax(menu), "\d%s [%L]", g_playername[player], id, g_zombie[player] ? g_nemesis[player] ? "CLASS_NEMESIS" : g_assassin[player] ? "CLASS_ASSASSIN" : "CLASS_ZOMBIE" : g_survivor[player] ? "CLASS_SURVIVOR" : g_sniper[player] ? "CLASS_SNIPER" : "CLASS_HUMAN")
4544 }
4545 case ACTION_RESPAWN_PLAYER: // Respawn command
4546 {
4547 if (allowed_respawn(player) && (userflags & g_access_flag[ACCESS_RESPAWN_PLAYERS]))
4548 formatex(menu, charsmax(menu), "%s", g_playername[player])
4549 else
4550 formatex(menu, charsmax(menu), "\d%s", g_playername[player])
4551 }
4552 }
4553
4554 // Add player
4555 buffer[0] = player
4556 buffer[1] = 0
4557 menu_additem(menuid, menu, buffer)
4558 }
4559
4560 // Back - Next - Exit
4561 formatex(menu, charsmax(menu), "%L", id, "MENU_BACK")
4562 menu_setprop(menuid, MPROP_BACKNAME, menu)
4563 formatex(menu, charsmax(menu), "%L", id, "MENU_NEXT")
4564 menu_setprop(menuid, MPROP_NEXTNAME, menu)
4565 formatex(menu, charsmax(menu), "%L", id, "MENU_EXIT")
4566 menu_setprop(menuid, MPROP_EXITNAME, menu)
4567
4568 // If remembered page is greater than number of pages, clamp down the value
4569 MENU_PAGE_PLAYERS = min(MENU_PAGE_PLAYERS, menu_pages(menuid)-1)
4570
4571 // Fix for AMXX custom menus
4572 if (pev_valid(id) == PDATA_SAFE)
4573 set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
4574
4575 menu_display(id, menuid, MENU_PAGE_PLAYERS)
4576}
4577
4578/*================================================================================
4579 [Menu Handlers]
4580=================================================================================*/
4581
4582// Game Menu
4583public menu_game(id, key)
4584{
4585 // Player disconnected?
4586 if (!g_isconnected[id])
4587 return PLUGIN_HANDLED;
4588
4589 switch (key)
4590 {
4591 case 0: // Buy Weapons
4592 {
4593 // Custom buy menus enabled?
4594 if (get_pcvar_num(cvar_buycustom))
4595 {
4596 // Disable the remember selection setting
4597 WPN_AUTO_ON = 0
4598 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "BUY_ENABLED")
4599
4600 // Show menu if player hasn't yet bought anything
4601 if (g_canbuy[id]) show_menu_buy1(id)
4602 }
4603 else
4604 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
4605 }
4606 case 1: // Extra Items
4607 {
4608 // Extra items enabled?
4609 if (get_pcvar_num(cvar_extraitems))
4610 {
4611 // Check whether the player is able to buy anything
4612 if (g_isalive[id])
4613 show_menu_extras(id)
4614 else
4615 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
4616 }
4617 else
4618 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_EXTRAS")
4619 }
4620 case 2: // Zombie Classes
4621 {
4622 // Zombie classes enabled?
4623 if (get_pcvar_num(cvar_zclasses))
4624 show_menu_zclass(id)
4625 else
4626 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ZCLASSES")
4627 }
4628 case 3: // Unstuck
4629 {
4630 // Check if player is stuck
4631 if (g_isalive[id])
4632 {
4633 if (is_player_stuck(id))
4634 {
4635 // Move to an initial spawn
4636 if (get_pcvar_num(cvar_randspawn))
4637 do_random_spawn(id) // random spawn (including CSDM)
4638 else
4639 do_random_spawn(id, 1) // regular spawn
4640 }
4641 else
4642 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_STUCK")
4643 }
4644 else
4645 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
4646 }
4647 case 4: // Help Menu
4648 {
4649 show_menu_info(id)
4650 }
4651 case 5: // Join Spectator
4652 {
4653 // Player alive?
4654 if (g_isalive[id])
4655 {
4656 // Prevent abuse by non-admins if block suicide setting is enabled
4657 if (get_pcvar_num(cvar_blocksuicide) && !(get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MENU]))
4658 {
4659 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
4660 return PLUGIN_HANDLED;
4661 }
4662
4663 // Check that we still have both humans and zombies to keep the round going
4664 check_round(id)
4665
4666 // Kill him before he switches team
4667 dllfunc(DLLFunc_ClientKill, id)
4668 }
4669
4670 // Temporarily save player stats?
4671 if (get_pcvar_num(cvar_statssave)) save_stats(id)
4672
4673 // Remove previous tasks
4674 remove_task(id+TASK_TEAM)
4675 remove_task(id+TASK_MODEL)
4676 remove_task(id+TASK_FLASH)
4677 remove_task(id+TASK_CHARGE)
4678 remove_task(id+TASK_SPAWN)
4679 remove_task(id+TASK_BLOOD)
4680 remove_task(id+TASK_AURA)
4681 remove_task(id+TASK_BURN)
4682
4683 // Then move him to the spectator team
4684 fm_cs_set_user_team(id, FM_CS_TEAM_SPECTATOR)
4685 fm_user_team_update(id)
4686 }
4687 case 8: // Admin Menu
4688 {
4689 // Check if player has the required access
4690 if (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MENU])
4691 show_menu_admin(id)
4692 else
4693 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
4694 }
4695 }
4696
4697 return PLUGIN_HANDLED;
4698}
4699
4700// Buy Menu 1
4701public menu_buy1(id, key)
4702{
4703 // Player dead?
4704 if (!g_isalive[id])
4705 return PLUGIN_HANDLED;
4706
4707 // Zombies or survivors get no guns
4708 if (g_zombie[id] || g_survivor[id] || g_sniper[id])
4709 return PLUGIN_HANDLED;
4710
4711 // Special keys / weapon list exceeded
4712 if (key >= MENU_KEY_AUTOSELECT || WPN_SELECTION >= WPN_MAXIDS)
4713 {
4714 switch (key)
4715 {
4716 case MENU_KEY_AUTOSELECT: // toggle auto select
4717 {
4718 WPN_AUTO_ON = 1 - WPN_AUTO_ON
4719 }
4720 case MENU_KEY_NEXT: // next/back
4721 {
4722 if (WPN_STARTID+7 < WPN_MAXIDS)
4723 WPN_STARTID += 7
4724 else
4725 WPN_STARTID = 0
4726 }
4727 case MENU_KEY_EXIT: // exit
4728 {
4729 return PLUGIN_HANDLED;
4730 }
4731 }
4732
4733 // Show buy menu again
4734 show_menu_buy1(id)
4735 return PLUGIN_HANDLED;
4736 }
4737
4738 // Store selected weapon id
4739 WPN_AUTO_PRI = WPN_SELECTION
4740
4741 // Buy primary weapon
4742 buy_primary_weapon(id, WPN_AUTO_PRI)
4743
4744 // Show pistols menu
4745 show_menu_buy2(id)
4746
4747 return PLUGIN_HANDLED;
4748}
4749
4750// Buy Primary Weapon
4751buy_primary_weapon(id, selection)
4752{
4753 // Drop previous weapons
4754 drop_weapons(id, 1)
4755 drop_weapons(id, 2)
4756
4757 // Strip off from weapons
4758 fm_strip_user_weapons(id)
4759 fm_give_item(id, "weapon_knife")
4760
4761 // Get weapon's id and name
4762 static weaponid, wname[32]
4763 weaponid = ArrayGetCell(g_primary_weaponids, selection)
4764 ArrayGetString(g_primary_items, selection, wname, charsmax(wname))
4765
4766 // Give the new weapon and full ammo
4767 fm_give_item(id, wname)
4768 ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[weaponid], AMMOTYPE[weaponid], MAXBPAMMO[weaponid])
4769
4770 // Weapons bought
4771 g_canbuy[id] = false
4772
4773 // Give additional items
4774 static i
4775 for (i = 0; i < ArraySize(g_additional_items); i++)
4776 {
4777 ArrayGetString(g_additional_items, i, wname, charsmax(wname))
4778 fm_give_item(id, wname)
4779 }
4780}
4781
4782// Buy Menu 2
4783public menu_buy2(id, key)
4784{
4785 // Player dead?
4786 if (!g_isalive[id])
4787 return PLUGIN_HANDLED;
4788
4789 // Zombies or survivors get no guns
4790 if (g_zombie[id] || g_survivor[id] || g_sniper[id])
4791 return PLUGIN_HANDLED;
4792
4793 // Special keys / weapon list exceeded
4794 if (key >= ArraySize(g_secondary_items))
4795 {
4796 // Toggle autoselect
4797 if (key == MENU_KEY_AUTOSELECT)
4798 WPN_AUTO_ON = 1 - WPN_AUTO_ON
4799
4800 // Reshow menu unless user exited
4801 if (key != MENU_KEY_EXIT)
4802 show_menu_buy2(id)
4803
4804 return PLUGIN_HANDLED;
4805 }
4806
4807 // Store selected weapon
4808 WPN_AUTO_SEC = key
4809
4810 // Drop secondary gun again, in case we picked another (bugfix)
4811 drop_weapons(id, 2)
4812
4813 // Get weapon's id
4814 static weaponid, wname[32]
4815 weaponid = ArrayGetCell(g_secondary_weaponids, key)
4816 ArrayGetString(g_secondary_items, key, wname, charsmax(wname))
4817
4818 // Give the new weapon and full ammo
4819 fm_give_item(id, wname)
4820 ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[weaponid], AMMOTYPE[weaponid], MAXBPAMMO[weaponid])
4821
4822 return PLUGIN_HANDLED;
4823}
4824
4825// Extra Items Menu
4826public menu_extras(id, menuid, item)
4827{
4828 // Player disconnected?
4829 if (!is_user_connected(id))
4830 {
4831 menu_destroy(menuid)
4832 return PLUGIN_HANDLED;
4833 }
4834
4835 // Remember player's menu page
4836 static menudummy
4837 player_menu_info(id, menudummy, menudummy, MENU_PAGE_EXTRAS)
4838
4839 // Menu was closed
4840 if (item == MENU_EXIT)
4841 {
4842 menu_destroy(menuid)
4843 return PLUGIN_HANDLED;
4844 }
4845
4846 // Dead players are not allowed to buy items
4847 if (!g_isalive[id])
4848 {
4849 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
4850 menu_destroy(menuid)
4851 return PLUGIN_HANDLED;
4852 }
4853
4854 // Retrieve extra item id
4855 static buffer[2], dummy, itemid
4856 menu_item_getinfo(menuid, item, dummy, buffer, charsmax(buffer), _, _, dummy)
4857 itemid = buffer[0]
4858
4859 // Attempt to buy the item
4860 buy_extra_item(id, itemid)
4861 menu_destroy(menuid)
4862 return PLUGIN_HANDLED;
4863}
4864
4865// Buy Extra Item
4866buy_extra_item(id, itemid, ignorecost = 0)
4867{
4868 // Retrieve item's team
4869 static team
4870 team = ArrayGetCell(g_extraitem_team, itemid)
4871
4872 // Check for team/class specific items
4873 if ((g_zombie[id] && !g_nemesis[id] && !g_assassin && !(team & ZP_TEAM_ZOMBIE)) || (!g_zombie[id] && !g_survivor[id] && !g_sniper[id] && !(team & ZP_TEAM_HUMAN)) || (g_nemesis[id] && !(team & ZP_TEAM_NEMESIS)) || (g_assassin[id] && !(team & ZP_TEAM_ASSASSIN)) || (g_survivor[id] && !(team & ZP_TEAM_SURVIVOR)) || (g_sniper[id] && !(team & ZP_TEAM_SNIPER)))
4874 {
4875 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
4876 return;
4877 }
4878
4879 // Check for unavailable items
4880 if ((itemid == EXTRA_NVISION && !get_pcvar_num(cvar_extranvision))
4881 || (itemid == EXTRA_ANTIDOTE && (!get_pcvar_num(cvar_extraantidote) || g_antidotecounter >= get_pcvar_num(cvar_antidotelimit)))
4882 || (itemid == EXTRA_MADNESS && (!get_pcvar_num(cvar_extramadness) || g_madnesscounter >= get_pcvar_num(cvar_madnesslimit)))
4883 || (itemid == EXTRA_INFBOMB && (!get_pcvar_num(cvar_extrainfbomb) || g_infbombcounter >= get_pcvar_num(cvar_infbomblimit)))
4884 || (itemid >= EXTRA_WEAPONS_STARTID && itemid <= EXTRAS_CUSTOM_STARTID-1 && !get_pcvar_num(cvar_extraweapons)))
4885 {
4886 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
4887 return;
4888 }
4889
4890 // Check for hard coded items with special conditions
4891 if ((itemid == EXTRA_ANTIDOTE && (g_endround || g_swarmround || g_nemround || g_assaround || g_survround || g_sniround || g_plagueround || g_armageround || g_apocround || g_nightround || fnGetZombies() <= 1 || (get_pcvar_num(cvar_deathmatch) && !get_pcvar_num(cvar_respawnafterlast) && fnGetHumans() == 1)))
4892 || (itemid == EXTRA_MADNESS && g_nodamage[id]) || (itemid == EXTRA_INFBOMB && (g_endround || g_swarmround || g_nemround || g_assaround || g_survround || g_sniround || g_plagueround || g_armageround || g_apocround || g_nightround)))
4893 {
4894 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_CANTUSE")
4895 return;
4896 }
4897
4898 // Ignore item's cost?
4899 if (!ignorecost)
4900 {
4901 // Check that we have enough ammo packs
4902 if (g_ammopacks[id] < ArrayGetCell(g_extraitem_cost, itemid))
4903 {
4904 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "NOT_ENOUGH_AMMO")
4905 return;
4906 }
4907
4908 // Deduce item cost
4909 g_ammopacks[id] -= ArrayGetCell(g_extraitem_cost, itemid)
4910 }
4911
4912 // Check which kind of item we're buying
4913 switch (itemid)
4914 {
4915 case EXTRA_NVISION: // Night Vision
4916 {
4917 g_nvision[id] = true
4918
4919 if (!g_isbot[id])
4920 {
4921 g_nvisionenabled[id] = true
4922
4923 // Custom nvg?
4924 if (get_pcvar_num(cvar_customnvg))
4925 {
4926 remove_task(id+TASK_NVISION)
4927 set_task(0.1, "set_user_nvision", id+TASK_NVISION, _, _, "b")
4928 }
4929 else
4930 set_user_gnvision(id, 1)
4931 }
4932 else
4933 cs_set_user_nvg(id, 1)
4934 }
4935 case EXTRA_ANTIDOTE: // Antidote
4936 {
4937 // Increase antidote purchase count for this round
4938 g_antidotecounter++
4939
4940 humanme(id, 0, 0, 0)
4941 }
4942 case EXTRA_MADNESS: // Zombie Madness
4943 {
4944 // Increase madness purchase count for this round
4945 g_madnesscounter++
4946
4947 g_nodamage[id] = true
4948 set_task(0.1, "zombie_aura", id+TASK_AURA, _, _, "b")
4949 set_task(get_pcvar_float(cvar_madnessduration), "madness_over", id+TASK_BLOOD)
4950
4951 static sound[64]
4952 ArrayGetString(zombie_madness, random_num(0, ArraySize(zombie_madness) - 1), sound, charsmax(sound))
4953 emit_sound(id, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
4954 }
4955 case EXTRA_INFBOMB: // Infection Bomb
4956 {
4957 // Increase infection bomb purchase count for this round
4958 g_infbombcounter++
4959
4960 // Already own one
4961 if (user_has_weapon(id, CSW_HEGRENADE))
4962 {
4963 // Increase BP ammo on it instead
4964 cs_set_user_bpammo(id, CSW_HEGRENADE, cs_get_user_bpammo(id, CSW_HEGRENADE) + 1)
4965
4966 // Flash ammo in hud
4967 message_begin(MSG_ONE_UNRELIABLE, g_msgAmmoPickup, _, id)
4968 write_byte(AMMOID[CSW_HEGRENADE]) // ammo id
4969 write_byte(1) // ammo amount
4970 message_end()
4971
4972 // Play clip purchase sound
4973 emit_sound(id, CHAN_ITEM, sound_buyammo, 1.0, ATTN_NORM, 0, PITCH_NORM)
4974
4975 return; // stop here
4976 }
4977
4978 // Give weapon to the player
4979 fm_give_item(id, "weapon_hegrenade")
4980 }
4981 default:
4982 {
4983 if (itemid >= EXTRA_WEAPONS_STARTID && itemid <= EXTRAS_CUSTOM_STARTID-1) // Weapons
4984 {
4985 // Get weapon's id and name
4986 static weaponid, wname[32]
4987 ArrayGetString(g_extraweapon_items, itemid - EXTRA_WEAPONS_STARTID, wname, charsmax(wname))
4988 weaponid = cs_weapon_name_to_id(wname)
4989
4990 // If we are giving a primary/secondary weapon
4991 if (MAXBPAMMO[weaponid] > 2)
4992 {
4993 // Make user drop the previous one
4994 if ((1<<weaponid) & PRIMARY_WEAPONS_BIT_SUM)
4995 drop_weapons(id, 1)
4996 else
4997 drop_weapons(id, 2)
4998
4999 // Give full BP ammo for the new one
5000 ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[weaponid], AMMOTYPE[weaponid], MAXBPAMMO[weaponid])
5001 }
5002 // If we are giving a grenade which the user already owns
5003 else if (user_has_weapon(id, weaponid))
5004 {
5005 // Increase BP ammo on it instead
5006 cs_set_user_bpammo(id, weaponid, cs_get_user_bpammo(id, weaponid) + 1)
5007
5008 // Flash ammo in hud
5009 message_begin(MSG_ONE_UNRELIABLE, g_msgAmmoPickup, _, id)
5010 write_byte(AMMOID[weaponid]) // ammo id
5011 write_byte(1) // ammo amount
5012 message_end()
5013
5014 // Play clip purchase sound
5015 emit_sound(id, CHAN_ITEM, sound_buyammo, 1.0, ATTN_NORM, 0, PITCH_NORM)
5016
5017 return; // stop here
5018 }
5019
5020 // Give weapon to the player
5021 fm_give_item(id, wname)
5022 }
5023 else // Custom additions
5024 {
5025 // Item selected forward
5026 ExecuteForward(g_fwExtraItemSelected, g_fwDummyResult, id, itemid);
5027
5028 // Item purchase blocked, restore buyer's ammo packs
5029 if (g_fwDummyResult >= ZP_PLUGIN_HANDLED && !ignorecost)
5030 g_ammopacks[id] += ArrayGetCell(g_extraitem_cost, itemid)
5031 }
5032 }
5033 }
5034}
5035
5036// Zombie Class Menu
5037public menu_zclass(id, menuid, item)
5038{
5039 // Player disconnected?
5040 if (!is_user_connected(id))
5041 {
5042 menu_destroy(menuid)
5043 return PLUGIN_HANDLED;
5044 }
5045
5046 // Remember player's menu page
5047 static menudummy
5048 player_menu_info(id, menudummy, menudummy, MENU_PAGE_ZCLASS)
5049
5050 // Menu was closed
5051 if (item == MENU_EXIT)
5052 {
5053 menu_destroy(menuid)
5054 return PLUGIN_HANDLED;
5055 }
5056
5057 // Retrieve zombie class id
5058 static buffer[2], dummy, classid
5059 menu_item_getinfo(menuid, item, dummy, buffer, charsmax(buffer), _, _, dummy)
5060 classid = buffer[0]
5061
5062 // Store selection for the next infection
5063 g_zombieclassnext[id] = classid
5064
5065 static name[32]
5066 ArrayGetString(g_zclass_name, g_zombieclassnext[id], name, charsmax(name))
5067
5068 // Show selected zombie class info and stats
5069 zp_colored_print(id, "^x04[ZP]^x01 %L^x01:^x04 %s", id, "ZOMBIE_SELECT", name)
5070 zp_colored_print(id, "^x04[ZP]^x01 %L^x01:^x04 %d^x01 |^x01 %L^x01:^x04 %d^x01 |^x01 %L^x01:^x04 %d^x01 |^x01 %L^x01:^x04 %d%%", id, "ZOMBIE_ATTRIB1", ArrayGetCell(g_zclass_hp, g_zombieclassnext[id]), id, "ZOMBIE_ATTRIB2", ArrayGetCell(g_zclass_spd, g_zombieclassnext[id]),
5071 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))
5072
5073 menu_destroy(menuid)
5074 return PLUGIN_HANDLED;
5075}
5076
5077// Info Menu
5078public menu_info(id, key)
5079{
5080 // Player disconnected?
5081 if (!g_isconnected[id])
5082 return PLUGIN_HANDLED;
5083
5084 static motd[1500], len
5085 len = 0
5086
5087 switch (key)
5088 {
5089 case 0: // General
5090 {
5091 static weather, lighting[2]
5092 weather = 0
5093 get_pcvar_string(cvar_lighting, lighting, charsmax(lighting))
5094 strtolower(lighting)
5095
5096 len += formatex(motd[len], charsmax(motd) - len, "%L ", id, "MOTD_INFO11", "Zombie Plague", PLUGIN_VERSION, "MeRcyLeZZ and Bakir")
5097 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO12")
5098 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_A")
5099
5100 if (g_ambience_fog)
5101 {
5102 len += formatex(motd[len], charsmax(motd) - len, (weather < 1) ? " %L" : ". %L", id, "MOTD_FOG")
5103 weather++
5104 }
5105 if (g_ambience_rain)
5106 {
5107 len += formatex(motd[len], charsmax(motd) - len, (weather < 1) ? " %L" : ". %L", id, "MOTD_RAIN")
5108 weather++
5109 }
5110 if (g_ambience_snow)
5111 {
5112 len += formatex(motd[len], charsmax(motd) - len, (weather < 1) ? " %L" : ". %L", id, "MOTD_SNOW")
5113 weather++
5114 }
5115 if (weather < 1) len += formatex(motd[len], charsmax(motd) - len, " %L", id, "MOTD_DISABLED")
5116
5117 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_B", lighting)
5118 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_C", id, get_pcvar_num(cvar_triggered) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5119 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)))
5120 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")
5121 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")
5122 if (get_pcvar_num(cvar_deathmatch)) len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_G", floatround(get_pcvar_float(cvar_spawnprotection)))
5123 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_H", id, get_pcvar_num(cvar_randspawn) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5124 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_I", id, get_pcvar_num(cvar_extraitems) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5125 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_J", id, get_pcvar_num(cvar_zclasses) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5126 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_K", id, get_pcvar_num(cvar_customnvg) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5127 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_L", id, g_cached_customflash ? "MOTD_ENABLED" : "MOTD_DISABLED")
5128
5129 show_motd(id, motd)
5130 }
5131 case 1: // Humans
5132 {
5133 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2")
5134 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_A", get_pcvar_num(cvar_humanhp))
5135 if (get_pcvar_num(cvar_humanlasthp) > 0) len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_B", get_pcvar_num(cvar_humanlasthp))
5136 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_C", get_pcvar_num(cvar_humanspd))
5137 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_D", floatround(get_pcvar_float(cvar_humangravity) * 800.0))
5138 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")
5139 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_F", get_pcvar_num(cvar_ammodamage_human))
5140 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_G", id, get_pcvar_num(cvar_firegrenades) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5141 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_H", id, get_pcvar_num(cvar_frostgrenades) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5142 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_I", id, get_pcvar_num(cvar_flaregrenades) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5143 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_J", id, get_pcvar_num(cvar_knockback) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5144
5145 show_motd(id, motd)
5146 }
5147 case 2: // Zombies
5148 {
5149 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3")
5150 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_A", ArrayGetCell(g_zclass_hp, 0))
5151 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_B", floatround(float(ArrayGetCell(g_zclass_hp, 0)) * get_pcvar_float(cvar_zombiefirsthp)))
5152 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_C", floatround(get_pcvar_float(cvar_zombiearmor) * 100.0))
5153 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_D", ArrayGetCell(g_zclass_spd, 0))
5154 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_E", floatround(Float:ArrayGetCell(g_zclass_grav, 0) * 800.0))
5155 if (get_pcvar_num(cvar_zombiebonushp)) len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_F", get_pcvar_num(cvar_zombiebonushp))
5156 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")
5157 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_H", id, get_pcvar_num(cvar_zombiebleeding) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5158 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_I", get_pcvar_num(cvar_ammoinfect))
5159
5160 show_motd(id, motd)
5161 }
5162 case 3: // Gameplay Modes
5163 {
5164 static nemhp[5], survhp[5], snihp[5], assahp[5]
5165
5166 // Get nemesis and survivor health
5167 num_to_str(get_pcvar_num(cvar_nemhp), nemhp, charsmax(nemhp))
5168 num_to_str(get_pcvar_num(cvar_survhp), survhp, charsmax(survhp))
5169 num_to_str(get_pcvar_num(cvar_snihp), snihp, charsmax(snihp))
5170 num_to_str(get_pcvar_num(cvar_assahp), assahp, charsmax(assahp))
5171
5172 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4")
5173
5174 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_A", id, get_pcvar_num(cvar_nem) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5175 if (get_pcvar_num(cvar_nem))
5176 {
5177 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_B", get_pcvar_num(cvar_nemchance))
5178 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_C", get_pcvar_num(cvar_nemhp) > 0 ? nemhp : "[Auto]")
5179 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_D", get_pcvar_num(cvar_nemspd))
5180 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_E", floatround(get_pcvar_float(cvar_nemgravity) * 800.0))
5181 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_F", id, g_cached_leapnemesis ? "MOTD_ENABLED" : "MOTD_DISABLED")
5182 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_G", id, get_pcvar_num(cvar_nempainfree) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5183 }
5184 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_H", id, get_pcvar_num(cvar_surv) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5185 if (get_pcvar_num(cvar_surv))
5186 {
5187 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_I", get_pcvar_num(cvar_survchance))
5188 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_J", get_pcvar_num(cvar_survhp) > 0 ? survhp : "[Auto]")
5189 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_K", get_pcvar_num(cvar_survspd))
5190 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_L", floatround(get_pcvar_float(cvar_survgravity) * 800.0))
5191 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_M", id, g_cached_leapsurvivor ? "MOTD_ENABLED" : "MOTD_DISABLED")
5192 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_N", id, get_pcvar_num(cvar_survpainfree) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5193 }
5194
5195 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_O", id, get_pcvar_num(cvar_swarm) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5196 if (get_pcvar_num(cvar_swarm)) len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_P", get_pcvar_num(cvar_swarmchance))
5197
5198 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_Q", id, get_pcvar_num(cvar_multi) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5199 if (get_pcvar_num(cvar_multi))
5200 {
5201 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_R", get_pcvar_num(cvar_multichance))
5202 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_S", floatround(get_pcvar_float(cvar_multiratio) * 100.0))
5203 }
5204
5205 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_T", id, get_pcvar_num(cvar_plague) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5206 if (get_pcvar_num(cvar_plague))
5207 {
5208 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_U", get_pcvar_num(cvar_plaguechance))
5209 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_V", floatround(get_pcvar_float(cvar_plagueratio) * 100.0))
5210 }
5211
5212 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO5_A", id, get_pcvar_num(cvar_sni) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5213 if (get_pcvar_num(cvar_sni))
5214 {
5215 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO5_B", get_pcvar_num(cvar_snichance))
5216 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO5_C", get_pcvar_num(cvar_snihp) > 0 ? snihp : "[Auto]")
5217 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO5_E", floatround(get_pcvar_float(cvar_snigravity) * 800.0))
5218 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO5_F", id, g_cached_leapsniper ? "MOTD_ENABLED" : "MOTD_DISABLED")
5219 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO5_G", id, get_pcvar_num(cvar_snipainfree) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5220 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO5_H", floatround(get_pcvar_float(cvar_snidamage)))
5221 }
5222
5223 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_A", id, get_pcvar_num(cvar_assa) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5224 if (get_pcvar_num(cvar_assa))
5225 {
5226 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_B", get_pcvar_num(cvar_assachance))
5227 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_C", get_pcvar_num(cvar_assahp) > 0 ? assahp : "[Auto]")
5228 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_D", get_pcvar_num(cvar_assaspd))
5229 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_E", floatround(get_pcvar_float(cvar_assagravity) * 800.0))
5230 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_F", id, g_cached_leapassassin ? "MOTD_ENABLED" : "MOTD_DISABLED")
5231 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_G", id, get_pcvar_num(cvar_assapainfree) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5232 }
5233
5234 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_H", id, get_pcvar_num(cvar_armage) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5235 if (get_pcvar_num(cvar_armage))
5236 {
5237 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_I", get_pcvar_num(cvar_armagechance))
5238 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_J", floatround(get_pcvar_float(cvar_armageratio) * 100.0))
5239 }
5240
5241 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO7_H", id, get_pcvar_num(cvar_apoc) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5242 if (get_pcvar_num(cvar_apoc))
5243 {
5244 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO7_I", get_pcvar_num(cvar_apocchance))
5245 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO7_J", floatround(get_pcvar_float(cvar_apocratio ) * 100.0))
5246 }
5247
5248 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO8_H", id, get_pcvar_num(cvar_night) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5249 if (get_pcvar_num(cvar_night))
5250 {
5251 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO8_I", get_pcvar_num(cvar_nightchance))
5252 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO8_J", floatround(get_pcvar_float(cvar_nightratio) * 100.0))
5253 }
5254
5255 show_motd(id, motd)
5256 }
5257 default: return PLUGIN_HANDLED;
5258 }
5259
5260 // Show help menu again if user wishes to read another topic
5261 show_menu_info(id)
5262
5263 return PLUGIN_HANDLED;
5264}
5265
5266// Admin Menu
5267public menu_admin(id, key)
5268{
5269 // Player disconnected?
5270 if (!g_isconnected[id])
5271 return PLUGIN_HANDLED;
5272
5273 static userflags
5274 userflags = get_user_flags(id)
5275
5276 switch (key)
5277 {
5278 case ACTION_ZOMBIEFY_HUMANIZE: // Zombiefy/Humanize command
5279 {
5280 if (userflags & (g_access_flag[ACCESS_MODE_INFECTION] | g_access_flag[ACCESS_MAKE_ZOMBIE] | g_access_flag[ACCESS_MAKE_HUMAN]))
5281 {
5282 // Show player list for admin to pick a target
5283 PL_ACTION = ACTION_ZOMBIEFY_HUMANIZE
5284 show_menu_player_list(id)
5285 }
5286 else
5287 {
5288 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5289 show_menu_admin(id)
5290 }
5291 }
5292 case ACTION_MAKE_NEMESIS: // Nemesis command
5293 {
5294 if (userflags & (g_access_flag[ACCESS_MODE_NEMESIS] | g_access_flag[ACCESS_MAKE_NEMESIS]))
5295 {
5296 // Show player list for admin to pick a target
5297 PL_ACTION = ACTION_MAKE_NEMESIS
5298 show_menu_player_list(id)
5299 }
5300 else
5301 {
5302 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5303 show_menu_admin(id)
5304 }
5305 }
5306 case ACTION_MAKE_ASSASSIN: // Assassin command
5307 {
5308 if (userflags & (g_access_flag[ACCESS_MODE_ASSASSIN] | g_access_flag[ACCESS_MAKE_ASSASSIN]))
5309 {
5310 // Show player list for admin to pick a target
5311 PL_ACTION = ACTION_MAKE_ASSASSIN
5312 show_menu_player_list(id)
5313 }
5314 else
5315 {
5316 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5317 show_menu_admin(id)
5318 }
5319 }
5320 case ACTION_MAKE_SURVIVOR: // Survivor command
5321 {
5322 if (userflags & (g_access_flag[ACCESS_MODE_SURVIVOR] | g_access_flag[ACCESS_MAKE_SURVIVOR]))
5323 {
5324 // Show player list for admin to pick a target
5325 PL_ACTION = ACTION_MAKE_SURVIVOR
5326 show_menu_player_list(id)
5327 }
5328 else
5329 {
5330 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5331 show_menu_admin(id)
5332 }
5333 }
5334 case ACTION_MAKE_SNIPER: // Sniper command
5335 {
5336 if (userflags & (g_access_flag[ACCESS_MODE_SNIPER] | g_access_flag[ACCESS_MAKE_SNIPER]))
5337 {
5338 // Show player list for admin to pick a target
5339 PL_ACTION = ACTION_MAKE_SNIPER
5340 show_menu_player_list(id)
5341 }
5342 else
5343 {
5344 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5345 show_menu_admin(id)
5346 }
5347 }
5348 case ACTION_RESPAWN_PLAYER: // Respawn command
5349 {
5350 if (userflags & g_access_flag[ACCESS_RESPAWN_PLAYERS])
5351 {
5352 // Show player list for admin to pick a target
5353 PL_ACTION = ACTION_RESPAWN_PLAYER
5354 show_menu_player_list(id)
5355 }
5356 else
5357 {
5358 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5359 show_menu_admin(id)
5360 }
5361 }
5362 case ACTION_MODES_MENU: // Admin Modes command
5363 {
5364 if (userflags & g_access_flag[ACCESS_ADMIN_MODES_MENU])
5365 show_menu_modes_admin(id)
5366 else
5367 {
5368 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5369 show_menu_admin(id)
5370 }
5371 }
5372 }
5373
5374 return PLUGIN_HANDLED;
5375}
5376
5377// Admin Modes Menu
5378public menu_modes_admin(id, key)
5379{
5380 static userflags
5381 userflags = get_user_flags(id)
5382
5383 switch (key)
5384 {
5385 case ACTION_MODE_SWARM: // Swarm Mode command
5386 {
5387 if (userflags & g_access_flag[ACCESS_MODE_SWARM])
5388 {
5389 if (allowed_swarm())
5390 command_swarm(id)
5391 else
5392 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5393 }
5394 else
5395 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5396
5397 show_menu_modes_admin(id)
5398 }
5399 case ACTION_MODE_MULTI: // Multiple Infection command
5400 {
5401 if (userflags & g_access_flag[ACCESS_MODE_MULTI])
5402 {
5403 if (allowed_multi())
5404 command_multi(id)
5405 else
5406 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5407 }
5408 else
5409 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5410
5411 show_menu_modes_admin(id)
5412 }
5413 case ACTION_MODE_PLAGUE: // Plague Mode command
5414 {
5415 if (userflags & g_access_flag[ACCESS_MODE_PLAGUE])
5416 {
5417 if (allowed_plague())
5418 command_plague(id)
5419 else
5420 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5421 }
5422 else
5423 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5424
5425 show_menu_modes_admin(id)
5426 }
5427 case ACTION_MODE_ARMAGEDDON: // Armageddon Mode command
5428 {
5429 if (userflags & g_access_flag[ACCESS_MODE_ARMAGEDDON])
5430 {
5431 if (allowed_armageddon())
5432 command_armageddon(id)
5433 else
5434 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5435 }
5436 else
5437 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5438
5439 show_menu_modes_admin(id)
5440 }
5441 case ACTION_MODE_APOCALYPSE: // Apocalypse Mode command
5442 {
5443 if (userflags & g_access_flag[ACCESS_MODE_APOCALYPSE])
5444 {
5445 if (allowed_apocalypse())
5446 command_apocalypse(id)
5447 else
5448 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5449 }
5450 else
5451 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5452
5453 show_menu_modes_admin(id)
5454 }
5455 case ACTION_MODE_NIGHTMARE: // Nightmare Mode command
5456 {
5457 if (userflags & g_access_flag[ACCESS_MODE_NIGHTMARE])
5458 {
5459 if (allowed_nightmare())
5460 command_nightmare(id)
5461 else
5462 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5463 }
5464 else
5465 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5466
5467 show_menu_modes_admin(id)
5468 }
5469 }
5470
5471 return PLUGIN_HANDLED;
5472}
5473
5474// Player List Menu
5475public menu_player_list(id, menuid, item)
5476{
5477 // Player disconnected?
5478 if (!is_user_connected(id))
5479 {
5480 menu_destroy(menuid)
5481 return PLUGIN_HANDLED;
5482 }
5483
5484 // Remember player's menu page
5485 static menudummy
5486 player_menu_info(id, menudummy, menudummy, MENU_PAGE_PLAYERS)
5487
5488 // Menu was closed
5489 if (item == MENU_EXIT)
5490 {
5491 menu_destroy(menuid)
5492 show_menu_admin(id)
5493 return PLUGIN_HANDLED;
5494 }
5495
5496 // Retrieve player id
5497 static buffer[2], dummy, playerid
5498 menu_item_getinfo(menuid, item, dummy, buffer, charsmax(buffer), _, _, dummy)
5499 playerid = buffer[0]
5500
5501 // Perform action on player
5502
5503 // Get admin flags
5504 static userflags
5505 userflags = get_user_flags(id)
5506
5507 // Make sure it's still connected
5508 if (g_isconnected[playerid])
5509 {
5510 // Perform the right action if allowed
5511 switch (PL_ACTION)
5512 {
5513 case ACTION_ZOMBIEFY_HUMANIZE: // Zombiefy/Humanize command
5514 {
5515 if (g_zombie[playerid])
5516 {
5517 if (userflags & g_access_flag[ACCESS_MAKE_HUMAN])
5518 {
5519 if (allowed_human(playerid))
5520 command_human(id, playerid)
5521 else
5522 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5523 }
5524 else
5525 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5526 }
5527 else
5528 {
5529 if (g_newround ? (userflags & g_access_flag[ACCESS_MODE_INFECTION]) : (userflags & g_access_flag[ACCESS_MAKE_ZOMBIE]))
5530 {
5531 if (allowed_zombie(playerid))
5532 command_zombie(id, playerid)
5533 else
5534 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5535 }
5536 else
5537 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5538 }
5539 }
5540 case ACTION_MAKE_NEMESIS: // Nemesis command
5541 {
5542 if (g_newround ? (userflags & g_access_flag[ACCESS_MODE_NEMESIS]) : (userflags & g_access_flag[ACCESS_MAKE_NEMESIS]))
5543 {
5544 if (allowed_nemesis(playerid))
5545 command_nemesis(id, playerid)
5546 else
5547 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5548 }
5549 else
5550 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5551 }
5552 case ACTION_MAKE_ASSASSIN: // Assassin command
5553 {
5554 if (g_newround ? (userflags & g_access_flag[ACCESS_MODE_ASSASSIN]) : (userflags & g_access_flag[ACCESS_MAKE_ASSASSIN]))
5555 {
5556 if (allowed_assassin(playerid))
5557 command_assassin(id, playerid)
5558 else
5559 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5560 }
5561 else
5562 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5563 }
5564 case ACTION_MAKE_SURVIVOR: // Survivor command
5565 {
5566 if (g_newround ? (userflags & g_access_flag[ACCESS_MODE_SURVIVOR]) : (userflags & g_access_flag[ACCESS_MAKE_SURVIVOR]))
5567 {
5568 if (allowed_survivor(playerid))
5569 command_survivor(id, playerid)
5570 else
5571 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5572 }
5573 else
5574 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5575 }
5576 case ACTION_MAKE_SNIPER: // Sniper command
5577 {
5578 if (g_newround ? (userflags & g_access_flag[ACCESS_MODE_SNIPER]) : (userflags & g_access_flag[ACCESS_MAKE_SNIPER]))
5579 {
5580 if (allowed_sniper(playerid))
5581 command_sniper(id, playerid)
5582 else
5583 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5584 }
5585 else
5586 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5587 }
5588 case ACTION_RESPAWN_PLAYER: // Respawn command
5589 {
5590 if (userflags & g_access_flag[ACCESS_RESPAWN_PLAYERS])
5591 {
5592 if (allowed_respawn(playerid))
5593 command_respawn(id, playerid)
5594 else
5595 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5596 }
5597 else
5598 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5599 }
5600 }
5601 }
5602 else
5603 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5604
5605 menu_destroy(menuid)
5606 show_menu_player_list(id)
5607 return PLUGIN_HANDLED;
5608}
5609
5610// CS Buy Menus
5611public menu_cs_buy(id, key)
5612{
5613 // Prevent buying if zombie/survivor (bugfix)
5614 if (g_zombie[id] || g_survivor[id] || g_sniper[id])
5615 return PLUGIN_HANDLED;
5616
5617 return PLUGIN_CONTINUE;
5618}
5619
5620/*================================================================================
5621 [Admin Commands]
5622=================================================================================*/
5623
5624// zp_toggle [1/0]
5625public cmd_toggle(id, level, cid)
5626{
5627 // Check for access flag - Enable/Disable Mod
5628 if (!cmd_access(id, g_access_flag[ACCESS_ENABLE_MOD], cid, 2))
5629 return PLUGIN_HANDLED;
5630
5631 // Retrieve arguments
5632 new arg[2]
5633 read_argv(1, arg, charsmax(arg))
5634
5635 // Mod already enabled/disabled
5636 if (str_to_num(arg) == g_pluginenabled)
5637 return PLUGIN_HANDLED;
5638
5639 // Set toggle cvar
5640 set_pcvar_num(cvar_toggle, str_to_num(arg))
5641 client_print(id, print_console, "Zombie Plague %L.", id, str_to_num(arg) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5642
5643 // Retrieve map name
5644 new mapname[32]
5645 get_mapname(mapname, charsmax(mapname))
5646
5647 // Restart current map
5648 server_cmd("changelevel %s", mapname)
5649
5650 return PLUGIN_HANDLED;
5651}
5652
5653// zp_zombie [target]
5654public cmd_zombie(id, level, cid)
5655{
5656 // Check for access flag depending on the resulting action
5657 if (g_newround)
5658 {
5659 // Start Mode Infection
5660 if (!cmd_access(id, g_access_flag[ACCESS_MODE_INFECTION], cid, 2))
5661 return PLUGIN_HANDLED;
5662 }
5663 else
5664 {
5665 // Make Zombie
5666 if (!cmd_access(id, g_access_flag[ACCESS_MAKE_ZOMBIE], cid, 2))
5667 return PLUGIN_HANDLED;
5668 }
5669
5670 // Retrieve arguments
5671 static arg[32], player
5672 read_argv(1, arg, charsmax(arg))
5673 player = cmd_target(id, arg, (CMDTARGET_ONLY_ALIVE | CMDTARGET_ALLOW_SELF))
5674
5675 // Invalid target
5676 if (!player) return PLUGIN_HANDLED;
5677
5678 // Target not allowed to be zombie
5679 if (!allowed_zombie(player))
5680 {
5681 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5682 return PLUGIN_HANDLED
5683 }
5684
5685 command_zombie(id, player)
5686
5687 return PLUGIN_HANDLED;
5688}
5689
5690// zp_human [target]
5691public cmd_human(id, level, cid)
5692{
5693 // Check for access flag - Make Human
5694 if (!cmd_access(id, g_access_flag[ACCESS_MAKE_HUMAN], cid, 2))
5695 return PLUGIN_HANDLED;
5696
5697 // Retrieve arguments
5698 static arg[32], player
5699 read_argv(1, arg, charsmax(arg))
5700 player = cmd_target(id, arg, (CMDTARGET_ONLY_ALIVE | CMDTARGET_ALLOW_SELF))
5701
5702 // Invalid target
5703 if (!player) return PLUGIN_HANDLED;
5704
5705 // Target not allowed to be human
5706 if (!allowed_human(player))
5707 {
5708 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5709 return PLUGIN_HANDLED;
5710 }
5711
5712 command_human(id, player)
5713
5714 return PLUGIN_HANDLED;
5715}
5716
5717// zp_survivor [target]
5718public cmd_survivor(id, level, cid)
5719{
5720 // Check for access flag depending on the resulting action
5721 if (g_newround)
5722 {
5723 // Start Mode Survivor
5724 if (!cmd_access(id, g_access_flag[ACCESS_MODE_SURVIVOR], cid, 2))
5725 return PLUGIN_HANDLED;
5726 }
5727 else
5728 {
5729 // Make Survivor
5730 if (!cmd_access(id, g_access_flag[ACCESS_MAKE_SURVIVOR], cid, 2))
5731 return PLUGIN_HANDLED;
5732 }
5733
5734 // Retrieve arguments
5735 static arg[32], player
5736 read_argv(1, arg, charsmax(arg))
5737 player = cmd_target(id, arg, (CMDTARGET_ONLY_ALIVE | CMDTARGET_ALLOW_SELF))
5738
5739 // Invalid target
5740 if (!player) return PLUGIN_HANDLED;
5741
5742 // Target not allowed to be survivor
5743 if (!allowed_survivor(player))
5744 {
5745 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5746 return PLUGIN_HANDLED;
5747 }
5748
5749 command_survivor(id, player)
5750
5751 return PLUGIN_HANDLED;
5752}
5753
5754// zp_sniper [target]
5755public cmd_sniper(id, level, cid)
5756{
5757 // Check for access flag depending on the resulting action
5758 if (g_newround)
5759 {
5760 // Start Mode Sniper
5761 if (!cmd_access(id, g_access_flag[ACCESS_MODE_SNIPER], cid, 2))
5762 return PLUGIN_HANDLED;
5763 }
5764 else
5765 {
5766 // Make Sniper
5767 if (!cmd_access(id, g_access_flag[ACCESS_MAKE_SNIPER], cid, 2))
5768 return PLUGIN_HANDLED;
5769 }
5770
5771 // Retrieve arguments
5772 static arg[32], player
5773 read_argv(1, arg, charsmax(arg))
5774 player = cmd_target(id, arg, (CMDTARGET_ONLY_ALIVE | CMDTARGET_ALLOW_SELF))
5775
5776 // Invalid target
5777 if (!player) return PLUGIN_HANDLED;
5778
5779 // Target not allowed to be sniper
5780 if (!allowed_sniper(player))
5781 {
5782 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5783 return PLUGIN_HANDLED;
5784 }
5785
5786 command_sniper(id, player)
5787
5788 return PLUGIN_HANDLED;
5789}
5790
5791// zp_nemesis [target]
5792public cmd_nemesis(id, level, cid)
5793{
5794 // Check for access flag depending on the resulting action
5795 if (g_newround)
5796 {
5797 // Start Mode Nemesis
5798 if (!cmd_access(id, g_access_flag[ACCESS_MODE_NEMESIS], cid, 2))
5799 return PLUGIN_HANDLED;
5800 }
5801 else
5802 {
5803 // Make Nemesis
5804 if (!cmd_access(id, g_access_flag[ACCESS_MAKE_NEMESIS], cid, 2))
5805 return PLUGIN_HANDLED;
5806 }
5807
5808 // Retrieve arguments
5809 static arg[32], player
5810 read_argv(1, arg, charsmax(arg))
5811 player = cmd_target(id, arg, (CMDTARGET_ONLY_ALIVE | CMDTARGET_ALLOW_SELF))
5812
5813 // Invalid target
5814 if (!player) return PLUGIN_HANDLED;
5815
5816 // Target not allowed to be nemesis
5817 if (!allowed_nemesis(player))
5818 {
5819 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5820 return PLUGIN_HANDLED;
5821 }
5822
5823 command_nemesis(id, player)
5824
5825 return PLUGIN_HANDLED;
5826}
5827
5828// zp_assassin [target]
5829public cmd_assassin(id, level, cid)
5830{
5831 // Check for access flag depending on the resulting action
5832 if (g_newround)
5833 {
5834 // Start Mode Assassin
5835 if (!cmd_access(id, g_access_flag[ACCESS_MODE_ASSASSIN], cid, 2))
5836 return PLUGIN_HANDLED;
5837 }
5838 else
5839 {
5840 // Make Assassin
5841 if (!cmd_access(id, g_access_flag[ACCESS_MAKE_ASSASSIN], cid, 2))
5842 return PLUGIN_HANDLED;
5843 }
5844
5845 // Retrieve arguments
5846 static arg[32], player
5847 read_argv(1, arg, charsmax(arg))
5848 player = cmd_target(id, arg, (CMDTARGET_ONLY_ALIVE | CMDTARGET_ALLOW_SELF))
5849
5850 // Invalid target
5851 if (!player) return PLUGIN_HANDLED;
5852
5853 // Target not allowed to be assassin
5854 if (!allowed_assassin(player))
5855 {
5856 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5857 return PLUGIN_HANDLED;
5858 }
5859
5860 command_assassin(id, player)
5861
5862 return PLUGIN_HANDLED;
5863}
5864
5865// zp_respawn [target]
5866public cmd_respawn(id, level, cid)
5867{
5868 // Check for access flag - Respawn
5869 if (!cmd_access(id, g_access_flag[ACCESS_RESPAWN_PLAYERS], cid, 2))
5870 return PLUGIN_HANDLED;
5871
5872 // Retrieve arguments
5873 static arg[32], player
5874 read_argv(1, arg, charsmax(arg))
5875 player = cmd_target(id, arg, CMDTARGET_ALLOW_SELF)
5876
5877 // Invalid target
5878 if (!player) return PLUGIN_HANDLED;
5879
5880 // Target not allowed to be respawned
5881 if (!allowed_respawn(player))
5882 {
5883 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5884 return PLUGIN_HANDLED;
5885 }
5886
5887 command_respawn(id, player)
5888
5889 return PLUGIN_HANDLED;
5890}
5891
5892// zp_swarm
5893public cmd_swarm(id, level, cid)
5894{
5895 // Check for access flag - Mode Swarm
5896 if (!cmd_access(id, g_access_flag[ACCESS_MODE_SWARM], cid, 1))
5897 return PLUGIN_HANDLED;
5898
5899 // Swarm mode not allowed
5900 if (!allowed_swarm())
5901 {
5902 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5903 return PLUGIN_HANDLED;
5904 }
5905
5906 command_swarm(id)
5907
5908 return PLUGIN_HANDLED;
5909}
5910
5911// zp_multi
5912public cmd_multi(id, level, cid)
5913{
5914 // Check for access flag - Mode Multi
5915 if (!cmd_access(id, g_access_flag[ACCESS_MODE_MULTI], cid, 1))
5916 return PLUGIN_HANDLED;
5917
5918 // Multi infection mode not allowed
5919 if (!allowed_multi())
5920 {
5921 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5922 return PLUGIN_HANDLED;
5923 }
5924
5925 command_multi(id)
5926
5927 return PLUGIN_HANDLED;
5928}
5929
5930// zp_plague
5931public cmd_plague(id, level, cid)
5932{
5933 // Check for access flag - Mode Plague
5934 if (!cmd_access(id, g_access_flag[ACCESS_MODE_PLAGUE], cid, 1))
5935 return PLUGIN_HANDLED;
5936
5937 // Plague mode not allowed
5938 if (!allowed_plague())
5939 {
5940 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5941 return PLUGIN_HANDLED;
5942 }
5943
5944 command_plague(id)
5945
5946 return PLUGIN_HANDLED;
5947}
5948
5949// zp_armageddon
5950public cmd_armageddon(id, level, cid)
5951{
5952 // Check for access flag - Mode Armageddon
5953 if (!cmd_access(id, g_access_flag[ACCESS_MODE_ARMAGEDDON], cid, 1))
5954 return PLUGIN_HANDLED;
5955
5956 // Armageddon mode not allowed
5957 if (!allowed_armageddon())
5958 {
5959 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5960 return PLUGIN_HANDLED;
5961 }
5962
5963 command_armageddon(id)
5964
5965 return PLUGIN_HANDLED;
5966}
5967
5968// zp_apocalypse
5969public cmd_apocalypse(id, level, cid)
5970{
5971 // Check for access flag - Mode Apocalypse
5972 if (!cmd_access(id, g_access_flag[ACCESS_MODE_APOCALYPSE], cid, 1))
5973 return PLUGIN_HANDLED;
5974
5975 // Apocalypse mode not allowed
5976 if (!allowed_apocalypse())
5977 {
5978 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5979 return PLUGIN_HANDLED;
5980 }
5981
5982 command_apocalypse(id)
5983
5984 return PLUGIN_HANDLED;
5985}
5986
5987// zp_nightmare
5988public cmd_nightmare(id, level, cid)
5989{
5990 // Check for access flag - Mode Nightmare
5991 if (!cmd_access(id, g_access_flag[ACCESS_MODE_NIGHTMARE], cid, 1))
5992 return PLUGIN_HANDLED;
5993
5994 // Nightmare mode not allowed
5995 if (!allowed_nightmare())
5996 {
5997 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5998 return PLUGIN_HANDLED;
5999 }
6000
6001 command_nightmare(id)
6002
6003 return PLUGIN_HANDLED;
6004}
6005
6006/*================================================================================
6007 [Message Hooks]
6008=================================================================================*/
6009
6010// Current Weapon info
6011public message_cur_weapon(msg_id, msg_dest, msg_entity)
6012{
6013 // Not alive or zombie
6014 if (!g_isalive[msg_entity] || g_zombie[msg_entity])
6015 return;
6016
6017 // Not an active weapon
6018 if (get_msg_arg_int(1) != 1)
6019 return;
6020
6021 // Unlimited clip disabled for class
6022 if (g_survivor[msg_entity] ? get_pcvar_num(cvar_survinfammo) <= 1 : g_sniper[msg_entity] ? get_pcvar_num(cvar_sniinfammo) <= 1 : get_pcvar_num(cvar_infammo) <= 1)
6023 return;
6024
6025 // Get weapon's id
6026 static weapon
6027 weapon = get_msg_arg_int(2)
6028
6029 // Unlimited Clip Ammo for this weapon?
6030 if (MAXBPAMMO[weapon] > 2)
6031 {
6032 // Max out clip ammo
6033 static weapon_ent
6034 weapon_ent = fm_cs_get_current_weapon_ent(msg_entity)
6035 if (pev_valid(weapon_ent)) cs_set_weapon_ammo(weapon_ent, MAXCLIP[weapon])
6036
6037 // HUD should show full clip all the time
6038 set_msg_arg_int(3, get_msg_argtype(3), MAXCLIP[weapon])
6039 }
6040}
6041
6042// Take off player's money
6043public message_money(msg_id, msg_dest, msg_entity)
6044{
6045 // Remove money setting enabled?
6046 if (!get_pcvar_num(cvar_removemoney))
6047 return PLUGIN_CONTINUE;
6048
6049 fm_cs_set_user_money(msg_entity, 0)
6050 return PLUGIN_HANDLED;
6051}
6052
6053// Fix for the HL engine bug when HP is multiples of 256
6054public message_health(msg_id, msg_dest, msg_entity)
6055{
6056 // Get player's health
6057 static health
6058 health = get_msg_arg_int(1)
6059
6060 // Don't bother
6061 if (health < 256) return;
6062
6063 // Check if we need to fix it
6064 if (health % 256 == 0)
6065 fm_set_user_health(msg_entity, pev(msg_entity, pev_health) + 1)
6066
6067 // HUD can only show as much as 255 hp
6068 set_msg_arg_int(1, get_msg_argtype(1), 255)
6069}
6070
6071// Block flashlight battery messages if custom flashlight is enabled instead
6072public message_flashbat()
6073{
6074 if (g_cached_customflash)
6075 return PLUGIN_HANDLED;
6076
6077 return PLUGIN_CONTINUE;
6078}
6079
6080// Flashbangs should only affect zombies
6081public message_screenfade(msg_id, msg_dest, msg_entity)
6082{
6083 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)
6084 return PLUGIN_CONTINUE;
6085
6086 // Nemesis shouldn't be FBed
6087 if (g_zombie[msg_entity] && !g_nemesis[msg_entity] && !g_assassin[msg_entity])
6088 {
6089 // Set flash color to nighvision's
6090 set_msg_arg_int(4, get_msg_argtype(4), get_pcvar_num(cvar_nvgcolor[0]))
6091 set_msg_arg_int(5, get_msg_argtype(5), get_pcvar_num(cvar_nvgcolor[1]))
6092 set_msg_arg_int(6, get_msg_argtype(6), get_pcvar_num(cvar_nvgcolor[2]))
6093 return PLUGIN_CONTINUE;
6094 }
6095
6096 return PLUGIN_HANDLED;
6097}
6098
6099// Prevent spectators' nightvision from being turned off when switching targets, etc.
6100public message_nvgtoggle()
6101{
6102 return PLUGIN_HANDLED;
6103}
6104
6105// Set correct model on player corpses
6106public message_clcorpse()
6107{
6108 set_msg_arg_string(1, g_playermodel[get_msg_arg_int(12)])
6109}
6110
6111// Prevent zombies from seeing any weapon pickup icon
6112public message_weappickup(msg_id, msg_dest, msg_entity)
6113{
6114 if (g_zombie[msg_entity])
6115 return PLUGIN_HANDLED;
6116
6117 return PLUGIN_CONTINUE;
6118}
6119
6120// Prevent zombies from seeing any ammo pickup icon
6121public message_ammopickup(msg_id, msg_dest, msg_entity)
6122{
6123 if (g_zombie[msg_entity])
6124 return PLUGIN_HANDLED;
6125
6126 return PLUGIN_CONTINUE;
6127}
6128
6129// Block hostage HUD display
6130public message_scenario()
6131{
6132 if (get_msg_args() > 1)
6133 {
6134 static sprite[8]
6135 get_msg_arg_string(2, sprite, charsmax(sprite))
6136
6137 if (equal(sprite, "hostage"))
6138 return PLUGIN_HANDLED;
6139 }
6140
6141 return PLUGIN_CONTINUE;
6142}
6143
6144// Block hostages from appearing on radar
6145public message_hostagepos()
6146{
6147 return PLUGIN_HANDLED;
6148}
6149
6150// Block some text messages
6151public message_textmsg()
6152{
6153 static textmsg[22]
6154 get_msg_arg_string(2, textmsg, charsmax(textmsg))
6155
6156 // Game restarting, reset scores and call round end to balance the teams
6157 if (equal(textmsg, "#Game_will_restart_in"))
6158 {
6159 logevent_round_end()
6160 g_scorehumans = 0
6161 g_scorezombies = 0
6162 }
6163 // Game commencing, reset scores only (round end is automatically triggered)
6164 else if (equal(textmsg, "#Game_Commencing"))
6165 {
6166 g_gamecommencing = true
6167 g_scorehumans = 0
6168 g_scorezombies = 0
6169 }
6170 // Block round end related messages
6171 else if (equal(textmsg, "#Hostages_Not_Rescued") || equal(textmsg, "#Round_Draw") || equal(textmsg, "#Terrorists_Win") || equal(textmsg, "#CTs_Win"))
6172 {
6173 return PLUGIN_HANDLED;
6174 }
6175
6176 return PLUGIN_CONTINUE;
6177}
6178
6179// Block CS round win audio messages, since we're playing our own instead
6180public message_sendaudio()
6181{
6182 static audio[17]
6183 get_msg_arg_string(2, audio, charsmax(audio))
6184
6185 if(equal(audio[7], "terwin") || equal(audio[7], "ctwin") || equal(audio[7], "rounddraw"))
6186 return PLUGIN_HANDLED;
6187
6188 return PLUGIN_CONTINUE;
6189}
6190
6191// Send actual team scores (T = zombies // CT = humans)
6192public message_teamscore()
6193{
6194 static team[2]
6195 get_msg_arg_string(1, team, charsmax(team))
6196
6197 switch (team[0])
6198 {
6199 // CT
6200 case 'C': set_msg_arg_int(2, get_msg_argtype(2), g_scorehumans)
6201 // Terrorist
6202 case 'T': set_msg_arg_int(2, get_msg_argtype(2), g_scorezombies)
6203 }
6204}
6205
6206// Team Switch (or player joining a team for first time)
6207public message_teaminfo(msg_id, msg_dest)
6208{
6209 // Only hook global messages
6210 if (msg_dest != MSG_ALL && msg_dest != MSG_BROADCAST) return;
6211
6212 // Don't pick up our own TeamInfo messages for this player (bugfix)
6213 if (g_switchingteam) return;
6214
6215 // Get player's id
6216 static id
6217 id = get_msg_arg_int(1)
6218
6219 // Invalid player id? (bugfix)
6220 if (!(1 <= id <= g_maxplayers)) return;
6221
6222 // Enable spectators' nightvision if not spawning right away
6223 set_task(0.2, "spec_nvision", id)
6224
6225 // Round didn't start yet, nothing to worry about
6226 if (g_newround) return;
6227
6228 // Get his new team
6229 static team[2]
6230 get_msg_arg_string(2, team, charsmax(team))
6231
6232 // Perform some checks to see if they should join a different team instead
6233 switch (team[0])
6234 {
6235 case 'C': // CT
6236 {
6237 if ((g_survround && fnGetHumans()) || (g_sniround && fnGetHumans())) // survivor/sniper alive --> switch to T and spawn as zombie
6238 {
6239 g_respawn_as_zombie[id] = true;
6240 remove_task(id+TASK_TEAM)
6241 fm_cs_set_user_team(id, FM_CS_TEAM_T)
6242 set_msg_arg_string(2, "TERRORIST")
6243 }
6244 else if (!fnGetZombies()) // no zombies alive --> switch to T and spawn as zombie
6245 {
6246 g_respawn_as_zombie[id] = true;
6247 remove_task(id+TASK_TEAM)
6248 fm_cs_set_user_team(id, FM_CS_TEAM_T)
6249 set_msg_arg_string(2, "TERRORIST")
6250 }
6251 }
6252 case 'T': // Terrorist
6253 {
6254 if ((g_swarmround || g_survround || g_sniround) && fnGetHumans()) // survivor alive or swarm round w/ humans --> spawn as zombie
6255 {
6256 g_respawn_as_zombie[id] = true;
6257 }
6258 else if (fnGetZombies()) // zombies alive --> switch to CT
6259 {
6260 remove_task(id+TASK_TEAM)
6261 fm_cs_set_user_team(id, FM_CS_TEAM_CT)
6262 set_msg_arg_string(2, "CT")
6263 }
6264 }
6265 }
6266}
6267
6268/*================================================================================
6269 [Main Functions]
6270=================================================================================*/
6271
6272// Make Zombie Task
6273public make_zombie_task()
6274{
6275 // Call make a zombie with no specific mode
6276 make_a_zombie(MODE_NONE, 0)
6277}
6278
6279// Make a Zombie Function
6280make_a_zombie(mode, id)
6281{
6282 // Get alive players count
6283 static iPlayersnum
6284 iPlayersnum = fnGetAlive()
6285
6286 // Not enough players, come back later!
6287 if (iPlayersnum < 1)
6288 {
6289 set_task(2.0, "make_zombie_task", TASK_MAKEZOMBIE)
6290 return;
6291 }
6292
6293 // Round started!
6294 g_newround = false
6295
6296 // Set up some common vars
6297 static forward_id, sound[64], iZombies, iMaxZombies
6298
6299 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)
6300 {
6301 // Survivor Mode
6302 g_survround = true
6303 g_lastmode = MODE_SURVIVOR
6304
6305 // Choose player randomly?
6306 if (mode == MODE_NONE)
6307 id = fnGetRandomAlive(random_num(1, iPlayersnum))
6308
6309 // Remember id for calling our forward later
6310 forward_id = id
6311
6312 // Turn player into a survivor
6313 humanme(id, 1, 0, 0)
6314
6315 // Turn the remaining players into zombies
6316 for (id = 1; id <= g_maxplayers; id++)
6317 {
6318 // Not alive
6319 if (!g_isalive[id])
6320 continue;
6321
6322 // Survivor or already a zombie
6323 if (g_survivor[id] || g_zombie[id])
6324 continue;
6325
6326 // Turn into a zombie
6327 zombieme(id, 0, 0, 0, 1, 0)
6328 }
6329
6330 // Play survivor sound
6331 ArrayGetString(sound_survivor, random_num(0, ArraySize(sound_survivor) - 1), sound, charsmax(sound))
6332 PlaySound(sound);
6333
6334 // Show Survivor HUD notice
6335 set_hudmessage(20, 20, 255, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
6336 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_SURVIVOR", g_playername[forward_id])
6337
6338 // Mode fully started!
6339 g_modestarted = true
6340
6341 // Round start forward
6342 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_SURVIVOR, forward_id);
6343 }
6344 else if ((mode == MODE_NONE && (!get_pcvar_num(cvar_preventconsecutive) || g_lastmode != MODE_SNIPER) && random_num(1, get_pcvar_num(cvar_snichance)) == get_pcvar_num(cvar_sni) && iPlayersnum >= get_pcvar_num(cvar_sniminplayers)) || mode == MODE_SNIPER)
6345 {
6346 // Sniper Mode
6347 g_sniround = true
6348 g_lastmode = MODE_SNIPER
6349
6350 // Choose player randomly?
6351 if (mode == MODE_NONE)
6352 id = fnGetRandomAlive(random_num(1, iPlayersnum))
6353
6354 // Remember id for calling our forward later
6355 forward_id = id
6356
6357 // Turn player into a sniper
6358 humanme(id, 0, 1, 0)
6359
6360 // Turn the remaining players into zombies
6361 for (id = 1; id <= g_maxplayers; id++)
6362 {
6363 // Not alive
6364 if (!g_isalive[id])
6365 continue;
6366
6367 // Sniper or already a zombie
6368 if (g_sniper[id] || g_zombie[id])
6369 continue;
6370
6371 // Turn into a zombie
6372 zombieme(id, 0, 0, 0, 1, 0)
6373 }
6374
6375 // Play sniper sound
6376 ArrayGetString(sound_sniper, random_num(0, ArraySize(sound_sniper) - 1), sound, charsmax(sound))
6377 PlaySound(sound);
6378
6379 // Show Sniper HUD notice
6380 set_hudmessage(20, 20, 255, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
6381 ShowSyncHudMsg(0, g_MsgSync, "%s is Sniper !!!", g_playername[forward_id])
6382
6383 // Mode fully started!
6384 g_modestarted = true
6385
6386 // Round start forward
6387 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_SNIPER, forward_id);
6388 }
6389 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)
6390 {
6391 // Swarm Mode
6392 g_swarmround = true
6393 g_lastmode = MODE_SWARM
6394
6395 // Make sure there are alive players on both teams (BUGFIX)
6396 if (!fnGetAliveTs())
6397 {
6398 // Move random player to T team
6399 id = fnGetRandomAlive(random_num(1, iPlayersnum))
6400 remove_task(id+TASK_TEAM)
6401 fm_cs_set_user_team(id, FM_CS_TEAM_T)
6402 fm_user_team_update(id)
6403 }
6404 else if (!fnGetAliveCTs())
6405 {
6406 // Move random player to CT team
6407 id = fnGetRandomAlive(random_num(1, iPlayersnum))
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 // Turn every T into a zombie
6414 for (id = 1; id <= g_maxplayers; id++)
6415 {
6416 // Not alive
6417 if (!g_isalive[id])
6418 continue;
6419
6420 // Not a Terrorist
6421 if (fm_cs_get_user_team(id) != FM_CS_TEAM_T)
6422 continue;
6423
6424 // Turn into a zombie
6425 zombieme(id, 0, 0, 0, 1, 0)
6426 }
6427
6428 // Play swarm sound
6429 ArrayGetString(sound_swarm, random_num(0, ArraySize(sound_swarm) - 1), sound, charsmax(sound))
6430 PlaySound(sound);
6431
6432 // Show Swarm HUD notice
6433 set_hudmessage(20, 255, 20, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
6434 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_SWARM")
6435
6436 // Mode fully started!
6437 g_modestarted = true
6438
6439 // Round start forward
6440 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_SWARM, 0);
6441 }
6442 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)
6443 {
6444 // Multi Infection Mode
6445 g_lastmode = MODE_MULTI
6446
6447 // iMaxZombies is rounded up, in case there aren't enough players
6448 iMaxZombies = floatround(iPlayersnum*get_pcvar_float(cvar_multiratio), floatround_ceil)
6449 iZombies = 0
6450
6451 // Randomly turn iMaxZombies players into zombies
6452 while (iZombies < iMaxZombies)
6453 {
6454 // Keep looping through all players
6455 if (++id > g_maxplayers) id = 1
6456
6457 // Dead or already a zombie
6458 if (!g_isalive[id] || g_zombie[id])
6459 continue;
6460
6461 // Random chance
6462 if (random_num(0, 1))
6463 {
6464 // Turn into a zombie
6465 zombieme(id, 0, 0, 0, 1, 0)
6466 iZombies++
6467 }
6468 }
6469
6470 // Turn the remaining players into humans
6471 for (id = 1; id <= g_maxplayers; id++)
6472 {
6473 // Only those of them who aren't zombies
6474 if (!g_isalive[id] || g_zombie[id])
6475 continue;
6476
6477 // Switch to CT
6478 if (fm_cs_get_user_team(id) != FM_CS_TEAM_CT) // need to change team?
6479 {
6480 remove_task(id+TASK_TEAM)
6481 fm_cs_set_user_team(id, FM_CS_TEAM_CT)
6482 fm_user_team_update(id)
6483 }
6484 }
6485
6486 // Play multi infection sound
6487 ArrayGetString(sound_multi, random_num(0, ArraySize(sound_multi) - 1), sound, charsmax(sound))
6488 PlaySound(sound);
6489
6490 // Show Multi Infection HUD notice
6491 set_hudmessage(200, 50, 0, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
6492 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_MULTI")
6493
6494 // Mode fully started!
6495 g_modestarted = true
6496
6497 // Round start forward
6498 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_MULTI, 0);
6499 }
6500 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
6501 && 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)
6502 {
6503 // Plague Mode
6504 g_plagueround = true
6505 g_lastmode = MODE_PLAGUE
6506
6507 // Turn specified amount of players into Survivors
6508 static iSurvivors, iMaxSurvivors
6509 iMaxSurvivors = get_pcvar_num(cvar_plaguesurvnum)
6510 iSurvivors = 0
6511
6512 while (iSurvivors < iMaxSurvivors)
6513 {
6514 // Choose random guy
6515 id = fnGetRandomAlive(random_num(1, iPlayersnum))
6516
6517 // Already a survivor?
6518 if (g_survivor[id])
6519 continue;
6520
6521 // If not, turn him into one
6522 humanme(id, 1, 0, 0)
6523 iSurvivors++
6524
6525 // Apply survivor health multiplier
6526 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_plaguesurvhpmulti)))
6527 }
6528
6529 // Turn specified amount of players into Nemesis
6530 static iNemesis, iMaxNemesis
6531 iMaxNemesis = get_pcvar_num(cvar_plaguenemnum)
6532 iNemesis = 0
6533
6534 while (iNemesis < iMaxNemesis)
6535 {
6536 // Choose random guy
6537 id = fnGetRandomAlive(random_num(1, iPlayersnum))
6538
6539 // Already a survivor or nemesis?
6540 if (g_survivor[id] || g_nemesis[id])
6541 continue;
6542
6543 // If not, turn him into one
6544 zombieme(id, 0, 1, 0, 0, 0)
6545 iNemesis++
6546
6547 // Apply nemesis health multiplier
6548 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_plaguenemhpmulti)))
6549 }
6550
6551 // iMaxZombies is rounded up, in case there aren't enough players
6552 iMaxZombies = floatround((iPlayersnum-(get_pcvar_num(cvar_plaguenemnum)+get_pcvar_num(cvar_plaguesurvnum)))*get_pcvar_float(cvar_plagueratio), floatround_ceil)
6553 iZombies = 0
6554
6555 // Randomly turn iMaxZombies players into zombies
6556 while (iZombies < iMaxZombies)
6557 {
6558 // Keep looping through all players
6559 if (++id > g_maxplayers) id = 1
6560
6561 // Dead or already a zombie or survivor
6562 if (!g_isalive[id] || g_zombie[id] || g_survivor[id])
6563 continue;
6564
6565 // Random chance
6566 if (random_num(0, 1))
6567 {
6568 // Turn into a zombie
6569 zombieme(id, 0, 0, 0, 1, 0)
6570 iZombies++
6571 }
6572 }
6573
6574 // Turn the remaining players into humans
6575 for (id = 1; id <= g_maxplayers; id++)
6576 {
6577 // Only those of them who arent zombies or survivor
6578 if (!g_isalive[id] || g_zombie[id] || g_survivor[id])
6579 continue;
6580
6581 // Switch to CT
6582 if (fm_cs_get_user_team(id) != FM_CS_TEAM_CT) // need to change team?
6583 {
6584 remove_task(id+TASK_TEAM)
6585 fm_cs_set_user_team(id, FM_CS_TEAM_CT)
6586 fm_user_team_update(id)
6587 }
6588 }
6589
6590 // Play plague sound
6591 ArrayGetString(sound_plague, random_num(0, ArraySize(sound_plague) - 1), sound, charsmax(sound))
6592 PlaySound(sound);
6593
6594 // Show Plague HUD notice
6595 set_hudmessage(0, 50, 200, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
6596 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_PLAGUE")
6597
6598 // Mode fully started!
6599 g_modestarted = true
6600
6601 // Round start forward
6602 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_PLAGUE, 0);
6603 }
6604 else if ((mode == MODE_NONE && (!get_pcvar_num(cvar_preventconsecutive) || g_lastmode != MODE_ARMAGEDDON) && random_num(1, get_pcvar_num(cvar_armagechance)) == get_pcvar_num(cvar_armage) && iPlayersnum >= get_pcvar_num(cvar_armageminplayers) && iPlayersnum >= 2) || mode == MODE_ARMAGEDDON)
6605 {
6606 // Armageddon Mode
6607 g_armageround = true
6608 g_lastmode = MODE_ARMAGEDDON
6609
6610 // iMaxZombies is rounded up, in case there aren't enough players
6611 iMaxZombies = floatround((iPlayersnum * get_pcvar_float(cvar_armageratio)), floatround_ceil)
6612 iZombies = 0
6613
6614 // Randomly turn iMaxZombies players into Nemesis
6615 while (iZombies < iMaxZombies)
6616 {
6617 // Keep looping through all players
6618 if (++id > g_maxplayers) id = 1
6619
6620 // Dead or already a zombie or survivor
6621 if (!g_isalive[id] || g_zombie[id] || g_survivor[id])
6622 continue;
6623
6624 // Random chance
6625 if (random_num(0, 1))
6626 {
6627 // Turn into a Nemesis
6628 zombieme(id, 0, 1, 0, 0, 0)
6629 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_armagenemhpmulti)))
6630 iZombies++
6631 }
6632 }
6633
6634 // Turn the remaining players into survivors
6635 for (id = 1; id <= g_maxplayers; id++)
6636 {
6637 // Only those of them who arent zombies or survivor
6638 if (!g_isalive[id] || g_zombie[id]|| g_survivor[id])
6639 continue;
6640
6641 // Turn into a Survivor
6642 humanme(id, 1, 0, 0)
6643 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_armagesurvhpmulti)))
6644 }
6645
6646 // Play armageddon sound
6647 ArrayGetString(sound_armageddon, random_num(0, ArraySize(sound_armageddon) - 1), sound, charsmax(sound))
6648 PlaySound(sound);
6649
6650 // Show Armageddon HUD notice
6651 set_hudmessage(181, 62, 244, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
6652 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_ARMAGEDDON")
6653
6654 // Mode fully started!
6655 g_modestarted = true
6656
6657 // Round start forward
6658 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_ARMAGEDDON, 0);
6659 }
6660 else if ((mode == MODE_NONE && (!get_pcvar_num(cvar_preventconsecutive) || g_lastmode != MODE_APOCALYPSE) && random_num(1, get_pcvar_num(cvar_apocchance)) == get_pcvar_num(cvar_apoc) && iPlayersnum >= get_pcvar_num(cvar_apocminplayers) && iPlayersnum >= 2) || mode == MODE_APOCALYPSE)
6661 {
6662 // Apocalypse Mode
6663 g_apocround = true
6664 g_lastmode = MODE_APOCALYPSE
6665
6666 // iMaxZombies is rounded up, in case there aren't enough players
6667 iMaxZombies = floatround((iPlayersnum * get_pcvar_float(cvar_apocratio)), floatround_ceil)
6668 iZombies = 0
6669
6670 // Randomly turn iMaxZombies players into Assassin
6671 while (iZombies < iMaxZombies)
6672 {
6673 // Keep looping through all players
6674 if (++id > g_maxplayers) id = 1
6675
6676 // Dead or already a zombie or sniper
6677 if (!g_isalive[id] || g_zombie[id] || g_sniper[id])
6678 continue;
6679
6680 // Random chance
6681 if (random_num(0, 1))
6682 {
6683 // Turn into a Assassin
6684 zombieme(id, 0, 0, 1, 0, 0)
6685 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_apocassahpmulti)))
6686 iZombies++
6687 }
6688 }
6689
6690 // Turn the remaining players into snipers
6691 for (id = 1; id <= g_maxplayers; id++)
6692 {
6693 // Only those of them who arent zombies or sniper
6694 if (!g_isalive[id] || g_zombie[id]|| g_sniper[id])
6695 continue;
6696
6697 // Turn into a Sniper
6698 humanme(id, 0, 1, 0)
6699 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_apocsniphpmulti)))
6700 }
6701
6702 // Play apocalypse sound
6703 ArrayGetString(sound_apocalypse, random_num(0, ArraySize(sound_apocalypse) - 1), sound, charsmax(sound))
6704 PlaySound(sound);
6705
6706 // Show Apocalypse HUD notice
6707 set_hudmessage(181, 62, 244, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
6708 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_APOCALYPSE")
6709
6710 // Mode fully started!
6711 g_modestarted = true
6712
6713 // Round start forward
6714 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_APOCALYPSE, 0);
6715 }
6716 else if ((mode == MODE_NONE && (!get_pcvar_num(cvar_preventconsecutive) || g_lastmode != MODE_NIGHTMARE) && random_num(1, get_pcvar_num(cvar_nightchance)) == get_pcvar_num(cvar_night) && iPlayersnum >= get_pcvar_num(cvar_nightminplayers) && iPlayersnum >= 4) || mode == MODE_NIGHTMARE)
6717 {
6718 // Nightmare mode
6719 g_nightround = true
6720 g_lastmode = MODE_NIGHTMARE
6721
6722 iMaxZombies = floatround((iPlayersnum * 0.25), floatround_ceil)
6723 iZombies = 0
6724
6725 while (iZombies < iMaxZombies)
6726 {
6727 if ((++id) > g_maxplayers) id = 1
6728
6729 if (!g_isalive[id])
6730 continue;
6731
6732 if (random_num(1, 5) == 1)
6733 {
6734 zombieme(id, 0, 0, 1, 0, 0)
6735 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_nightassahpmulti)))
6736 iZombies++
6737 }
6738 }
6739
6740 iZombies = 0
6741
6742 while (iZombies < iMaxZombies)
6743 {
6744 if ((++id) > g_maxplayers) id = 1
6745
6746 if (!g_isalive[id] || g_assassin[id])
6747 continue;
6748
6749 if (random_num(1, 5) == 1)
6750 {
6751 zombieme(id, 0, 1, 0, 0, 0)
6752 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_nightnemhpmulti)))
6753 iZombies++
6754 }
6755 }
6756
6757 iZombies = 0
6758
6759 while (iZombies < iMaxZombies)
6760 {
6761 if ((++id) > g_maxplayers) id = 1
6762
6763 if (!g_isalive[id] || g_assassin[id] || g_nemesis[id])
6764 continue;
6765
6766 if (random_num(1, 5) == 1)
6767 {
6768 humanme(id, 1, 0, 0)
6769 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_nightsurvhpmulti)))
6770 iZombies++
6771 }
6772 }
6773
6774 for (id = 1; id <= g_maxplayers; id++)
6775 {
6776 if (!g_isalive[id] || g_assassin[id] || g_nemesis[id] || g_survivor[id])
6777 continue;
6778
6779 humanme(id, 0, 1, 0)
6780 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_nightsniphpmulti)))
6781 }
6782
6783 // Play nightmare sound
6784 ArrayGetString(sound_nightmare, random_num(0, ArraySize(sound_nightmare) - 1), sound, charsmax(sound))
6785 PlaySound(sound);
6786
6787 // Show Nightmare HUD notice
6788 set_hudmessage(181, 62, 244, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
6789 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_NIGHTMARE")
6790
6791 // Mode fully started!
6792 g_modestarted = true
6793
6794 // Round start forward
6795 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_NIGHTMARE, 0);
6796 }
6797 else
6798 {
6799 // Single Infection Mode or Nemesis Mode
6800
6801 // Choose player randomly?
6802 if (mode == MODE_NONE)
6803 id = fnGetRandomAlive(random_num(1, iPlayersnum))
6804
6805 // Remember id for calling our forward later
6806 forward_id = id
6807
6808 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)
6809 {
6810 // Nemesis Mode
6811 g_nemround = true
6812 g_lastmode = MODE_NEMESIS
6813
6814 // Turn player into nemesis
6815 zombieme(id, 0, 1, 0, 0, 0)
6816 }
6817 else if ((mode == MODE_NONE && (!get_pcvar_num(cvar_preventconsecutive) || g_lastmode != MODE_ASSASSIN) && random_num(1, get_pcvar_num(cvar_assachance)) == get_pcvar_num(cvar_assa) && iPlayersnum >= get_pcvar_num(cvar_assaminplayers)) || mode == MODE_ASSASSIN)
6818 {
6819 // Assassin Mode
6820 g_assaround = true
6821 g_lastmode = MODE_ASSASSIN
6822
6823 // Turn player into assassin
6824 zombieme(id, 0, 0, 1, 0, 0)
6825 }
6826 else
6827 {
6828 // Single Infection Mode
6829 g_lastmode = MODE_INFECTION
6830
6831 // Turn player into the first zombie
6832 zombieme(id, 0, 0, 0, 0, 0)
6833 }
6834
6835 // Remaining players should be humans (CTs)
6836 for (id = 1; id <= g_maxplayers; id++)
6837 {
6838 // Not alive
6839 if (!g_isalive[id])
6840 continue;
6841
6842 // First zombie/nemesis
6843 if (g_zombie[id])
6844 continue;
6845
6846 // Switch to CT
6847 if (fm_cs_get_user_team(id) != FM_CS_TEAM_CT) // need to change team?
6848 {
6849 remove_task(id+TASK_TEAM)
6850 fm_cs_set_user_team(id, FM_CS_TEAM_CT)
6851 fm_user_team_update(id)
6852 }
6853 }
6854
6855 if (g_nemround)
6856 {
6857 // Play Nemesis sound
6858 ArrayGetString(sound_nemesis, random_num(0, ArraySize(sound_nemesis) - 1), sound, charsmax(sound))
6859 PlaySound(sound);
6860
6861 // Show Nemesis HUD notice
6862 set_hudmessage(255, 20, 20, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
6863 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_NEMESIS", g_playername[forward_id])
6864
6865 // Mode fully started!
6866 g_modestarted = true
6867
6868 // Round start forward
6869 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_NEMESIS, forward_id);
6870 }
6871 else if (g_assaround)
6872 {
6873 // Play Assassin sound
6874 ArrayGetString(sound_assassin, random_num(0, ArraySize(sound_assassin) - 1), sound, charsmax(sound))
6875 PlaySound(sound);
6876
6877 // Show Assassin HUD notice
6878 set_hudmessage(255, 255, 20, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
6879 ShowSyncHudMsg(0, g_MsgSync, "%s is Assassin !!!", g_playername[forward_id])
6880
6881 // Mode fully started!
6882 g_modestarted = true
6883
6884 // Round start forward
6885 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_ASSASSIN, forward_id);
6886 }
6887 else
6888 {
6889 // Show First Zombie HUD notice
6890 set_hudmessage(255, 0, 0, HUD_EVENT_X, HUD_EVENT_Y, 0, 0.0, 5.0, 1.0, 1.0, -1)
6891 ShowSyncHudMsg(0, g_MsgSync, "%L",LANG_PLAYER, "NOTICE_FIRST", g_playername[forward_id])
6892
6893 // Mode fully started!
6894 g_modestarted = true
6895
6896 // Round start forward
6897 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_INFECTION, forward_id);
6898 }
6899 }
6900
6901 // Start ambience sounds after a mode begins
6902 if ((g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS] && g_nemround) || (g_ambience_sounds[AMBIENCE_SOUNDS_ASSASSIN] && g_assaround) || (g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR] && g_survround) || (g_ambience_sounds[AMBIENCE_SOUNDS_SNIPER] && g_sniround) || (g_ambience_sounds[AMBIENCE_SOUNDS_SWARM] && g_swarmround) || (g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE] && g_plagueround || (g_ambience_sounds[AMBIENCE_SOUNDS_ARMAGEDDON] && g_armageround)
6903 || (g_ambience_sounds[AMBIENCE_SOUNDS_APOCALYPSE] && g_apocround) || (g_ambience_sounds[AMBIENCE_SOUNDS_NIGHTMARE] && g_nightround) || (g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION] && !g_nemround && !g_assaround && !g_survround && !g_sniround && !g_swarmround && !g_plagueround && !g_armageround && !g_apocround && !g_nightround)))
6904 {
6905 remove_task(TASK_AMBIENCESOUNDS)
6906 set_task(2.0, "ambience_sound_effects", TASK_AMBIENCESOUNDS)
6907 }
6908}
6909
6910// Zombie Me Function (player id, infector, turn into a nemesis, silent mode, deathmsg and rewards)
6911zombieme(id, infector, nemesis, assassin, silentmode, rewards)
6912{
6913 // User infect attempt forward
6914 ExecuteForward(g_fwUserInfect_attempt, g_fwDummyResult, id, infector, nemesis)
6915
6916 // One or more plugins blocked the infection. Only allow this after making sure it's
6917 // not going to leave us with no zombies. Take into account a last player leaving case.
6918 // BUGFIX: only allow after a mode has started, to prevent blocking first zombie e.g.
6919 if (g_fwDummyResult >= ZP_PLUGIN_HANDLED && g_modestarted && fnGetZombies() > g_lastplayerleaving)
6920 return;
6921
6922 // Pre user infect forward
6923 ExecuteForward(g_fwUserInfected_pre, g_fwDummyResult, id, infector, nemesis)
6924
6925 // Show zombie class menu if they haven't chosen any (e.g. just connected)
6926 if (g_zombieclassnext[id] == ZCLASS_NONE && get_pcvar_num(cvar_zclasses))
6927 set_task(0.2, "show_menu_zclass", id)
6928
6929 // Set selected zombie class
6930 g_zombieclass[id] = g_zombieclassnext[id]
6931 // If no class selected yet, use the first (default) one
6932 if (g_zombieclass[id] == ZCLASS_NONE) g_zombieclass[id] = 0
6933
6934 // Way to go...
6935 g_zombie[id] = true
6936 g_nemesis[id] = false
6937 g_assassin[id] = false
6938 g_survivor[id] = false
6939 g_sniper[id] = false
6940 g_firstzombie[id] = false
6941
6942 // Remove survivor's aura (bugfix)
6943 set_pev(id, pev_effects, pev(id, pev_effects) &~ EF_BRIGHTLIGHT)
6944
6945 // Remove spawn protection (bugfix)
6946 g_nodamage[id] = false
6947 set_pev(id, pev_effects, pev(id, pev_effects) &~ EF_NODRAW)
6948
6949 // Reset burning duration counter (bugfix)
6950 g_burning_duration[id] = 0
6951
6952 // Show deathmsg and reward infector?
6953 if (rewards && infector)
6954 {
6955 // Send death notice and fix the "dead" attrib on scoreboard
6956 SendDeathMsg(infector, id)
6957 FixDeadAttrib(id)
6958
6959 // Reward frags, deaths, health, and ammo packs
6960 UpdateFrags(infector, id, get_pcvar_num(cvar_fragsinfect), 1, 1)
6961 g_ammopacks[infector] += get_pcvar_num(cvar_ammoinfect)
6962 fm_set_user_health(infector, pev(infector, pev_health) + get_pcvar_num(cvar_zombiebonushp))
6963 }
6964
6965 // Cache speed, knockback, and name for player's class
6966 g_zombie_spd[id] = float(ArrayGetCell(g_zclass_spd, g_zombieclass[id]))
6967 g_zombie_knockback[id] = Float:ArrayGetCell(g_zclass_kb, g_zombieclass[id])
6968 ArrayGetString(g_zclass_name, g_zombieclass[id], g_zombie_classname[id], charsmax(g_zombie_classname[]))
6969
6970 // Set zombie attributes based on the mode
6971 static sound[64]
6972 if (!silentmode)
6973 {
6974 if (nemesis)
6975 {
6976 // Nemesis
6977 g_nemesis[id] = true
6978
6979 // Set health [0 = auto]
6980 if (get_pcvar_num(cvar_nemhp) == 0)
6981 {
6982 if (get_pcvar_num(cvar_nembasehp) == 0)
6983 fm_set_user_health(id, ArrayGetCell(g_zclass_hp, 0) * fnGetAlive())
6984 else
6985 fm_set_user_health(id, get_pcvar_num(cvar_nembasehp) * fnGetAlive())
6986 }
6987 else
6988 fm_set_user_health(id, get_pcvar_num(cvar_nemhp))
6989
6990 // Set gravity, if frozen set the restore gravity value instead
6991 if (!g_frozen[id]) set_pev(id, pev_gravity, get_pcvar_float(cvar_nemgravity))
6992 else g_frozen_gravity[id] = get_pcvar_float(cvar_nemgravity)
6993
6994 // Set nemesis maxspeed
6995 ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
6996 }
6997 else if (assassin)
6998 {
6999 // Assassin
7000 g_assassin[id] = true
7001
7002 // Set health [0 = auto]
7003 if (get_pcvar_num(cvar_assahp) == 0)
7004 {
7005 if (get_pcvar_num(cvar_assabasehp) == 0)
7006 fm_set_user_health(id, ArrayGetCell(g_zclass_hp, 0) * fnGetAlive())
7007 else
7008 fm_set_user_health(id, get_pcvar_num(cvar_assabasehp) * fnGetAlive())
7009 }
7010 else
7011 fm_set_user_health(id, get_pcvar_num(cvar_assahp))
7012
7013 // Set gravity, if frozen set the restore gravity value instead
7014 if (!g_frozen[id]) set_pev(id, pev_gravity, get_pcvar_float(cvar_assagravity))
7015 else g_frozen_gravity[id] = get_pcvar_float(cvar_assagravity)
7016
7017 // Set assassin maxspeed
7018 ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
7019 }
7020 else if (fnGetZombies() == 1)
7021 {
7022 // First zombie
7023 g_firstzombie[id] = true
7024
7025 // Set health
7026 fm_set_user_health(id, floatround(float(ArrayGetCell(g_zclass_hp, g_zombieclass[id])) * get_pcvar_float(cvar_zombiefirsthp)))
7027
7028 // Set gravity, if frozen set the restore gravity value instead
7029 if (!g_frozen[id]) set_pev(id, pev_gravity, Float:ArrayGetCell(g_zclass_grav, g_zombieclass[id]))
7030 else g_frozen_gravity[id] = Float:ArrayGetCell(g_zclass_grav, g_zombieclass[id])
7031
7032 // Set zombie maxspeed
7033 ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
7034
7035 // Infection sound
7036 ArrayGetString(zombie_infect, random_num(0, ArraySize(zombie_infect) - 1), sound, charsmax(sound))
7037 emit_sound(id, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
7038 }
7039 else
7040 {
7041 // Infected by someone
7042
7043 // Set health
7044 fm_set_user_health(id, ArrayGetCell(g_zclass_hp, g_zombieclass[id]))
7045
7046 // Set gravity, if frozen set the restore gravity value instead
7047 if (!g_frozen[id]) set_pev(id, pev_gravity, Float:ArrayGetCell(g_zclass_grav, g_zombieclass[id]))
7048 else g_frozen_gravity[id] = Float:ArrayGetCell(g_zclass_grav, g_zombieclass[id])
7049
7050 // Set zombie maxspeed
7051 ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
7052
7053 // Infection sound
7054 ArrayGetString(zombie_infect, random_num(0, ArraySize(zombie_infect) - 1), sound, charsmax(sound))
7055 emit_sound(id, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
7056
7057 // Show Infection HUD notice
7058 set_hudmessage(255, 0, 0, HUD_INFECT_X, HUD_INFECT_Y, 0, 0.0, 5.0, 1.0, 1.0, -1)
7059
7060 if (infector) // infected by someone?
7061 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_INFECT2", g_playername[id], g_playername[infector])
7062 else
7063 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_INFECT", g_playername[id])
7064 }
7065 }
7066 else
7067 {
7068 // Silent mode, no HUD messages, no infection sounds
7069
7070 // Set health
7071 fm_set_user_health(id, ArrayGetCell(g_zclass_hp, g_zombieclass[id]))
7072
7073 // Set gravity, if frozen set the restore gravity value instead
7074 if (!g_frozen[id]) set_pev(id, pev_gravity, Float:ArrayGetCell(g_zclass_grav, g_zombieclass[id]))
7075 else g_frozen_gravity[id] = Float:ArrayGetCell(g_zclass_grav, g_zombieclass[id])
7076
7077 // Set zombie maxspeed
7078 ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
7079 }
7080
7081 // Remove previous tasks
7082 remove_task(id+TASK_MODEL)
7083 remove_task(id+TASK_BLOOD)
7084 remove_task(id+TASK_AURA)
7085 remove_task(id+TASK_BURN)
7086
7087 // Switch to T
7088 if (fm_cs_get_user_team(id) != FM_CS_TEAM_T) // need to change team?
7089 {
7090 remove_task(id+TASK_TEAM)
7091 fm_cs_set_user_team(id, FM_CS_TEAM_T)
7092 fm_user_team_update(id)
7093 }
7094
7095 // Custom models stuff
7096 static currentmodel[32], tempmodel[32], already_has_model, i, iRand, size
7097 already_has_model = false
7098
7099 if (g_handle_models_on_separate_ent)
7100 {
7101 // Set the right model
7102 if (g_nemesis[id])
7103 {
7104 iRand = random_num(0, ArraySize(model_nemesis) - 1)
7105 ArrayGetString(model_nemesis, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7106 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_nemesis, iRand))
7107 }
7108 else if (g_assassin[id])
7109 {
7110 iRand = random_num(0, ArraySize(model_assassin) - 1)
7111 ArrayGetString(model_assassin, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7112 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_assassin, iRand))
7113 }
7114 else
7115 {
7116 if (get_pcvar_num(cvar_adminmodelszombie) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
7117 {
7118 iRand = random_num(0, ArraySize(model_admin_zombie) - 1)
7119 ArrayGetString(model_admin_zombie, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7120 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_zombie, iRand))
7121 }
7122 else
7123 {
7124 iRand = random_num(ArrayGetCell(g_zclass_modelsstart, g_zombieclass[id]), ArrayGetCell(g_zclass_modelsend, g_zombieclass[id]) - 1)
7125 ArrayGetString(g_zclass_playermodel, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7126 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_zclass_modelindex, iRand))
7127 }
7128 }
7129
7130 // Set model on player model entity
7131 fm_set_playermodel_ent(id)
7132
7133 // Nemesis glow / remove glow on player model entity, unless frozen
7134 if (!g_frozen[id])
7135 {
7136 if (g_nemesis[id] && get_pcvar_num(cvar_nemglow))
7137 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 250, 0 , 0, kRenderNormal, 25)
7138 else if (g_nemesis[id] && !(get_pcvar_num(cvar_nemglow)))
7139 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 0, 0 , 0, kRenderNormal, 25)
7140 else if (g_assassin[id] && get_pcvar_num(cvar_assaglow))
7141 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 255, 255, 0, kRenderNormal, 25)
7142 else
7143 fm_set_rendering(g_ent_playermodel[id])
7144 }
7145 }
7146 else
7147 {
7148 // Get current model for comparing it with the current one
7149 fm_cs_get_user_model(id, currentmodel, charsmax(currentmodel))
7150
7151 // Set the right model, after checking that we don't already have it
7152 if (g_nemesis[id])
7153 {
7154 size = ArraySize(model_nemesis)
7155 for (i = 0; i < size; i++)
7156 {
7157 ArrayGetString(model_nemesis, i, tempmodel, charsmax(tempmodel))
7158 if (equal(currentmodel, tempmodel)) already_has_model = true
7159 }
7160
7161 if (!already_has_model)
7162 {
7163 iRand = random_num(0, size - 1)
7164 ArrayGetString(model_nemesis, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7165 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_nemesis, iRand))
7166 }
7167 }
7168 else if (g_assassin[id])
7169 {
7170 size = ArraySize(model_assassin)
7171 for (i = 0; i < size; i++)
7172 {
7173 ArrayGetString(model_assassin, i, tempmodel, charsmax(tempmodel))
7174 if (equal(currentmodel, tempmodel)) already_has_model = true
7175 }
7176
7177 if (!already_has_model)
7178 {
7179 iRand = random_num(0, size - 1)
7180 ArrayGetString(model_assassin, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7181 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_assassin, iRand))
7182 }
7183 }
7184 else
7185 {
7186 if (get_pcvar_num(cvar_adminmodelszombie) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
7187 {
7188 size = ArraySize(model_admin_zombie)
7189 for (i = 0; i < size; i++)
7190 {
7191 ArrayGetString(model_admin_zombie, i, tempmodel, charsmax(tempmodel))
7192 if (equal(currentmodel, tempmodel)) already_has_model = true
7193 }
7194
7195 if (!already_has_model)
7196 {
7197 iRand = random_num(0, size - 1)
7198 ArrayGetString(model_admin_zombie, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7199 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_zombie, iRand))
7200 }
7201 }
7202 else
7203 {
7204 for (i = ArrayGetCell(g_zclass_modelsstart, g_zombieclass[id]); i < ArrayGetCell(g_zclass_modelsend, g_zombieclass[id]); i++)
7205 {
7206 ArrayGetString(g_zclass_playermodel, i, tempmodel, charsmax(tempmodel))
7207 if (equal(currentmodel, tempmodel)) already_has_model = true
7208 }
7209
7210 if (!already_has_model)
7211 {
7212 iRand = random_num(ArrayGetCell(g_zclass_modelsstart, g_zombieclass[id]), ArrayGetCell(g_zclass_modelsend, g_zombieclass[id]) - 1)
7213 ArrayGetString(g_zclass_playermodel, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7214 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_zclass_modelindex, iRand))
7215 }
7216 }
7217 }
7218
7219 // Need to change the model?
7220 if (!already_has_model)
7221 {
7222 // An additional delay is offset at round start
7223 // since SVC_BAD is more likely to be triggered there
7224 if (g_newround)
7225 set_task(5.0 * g_modelchange_delay, "fm_user_model_update", id+TASK_MODEL)
7226 else
7227 fm_user_model_update(id+TASK_MODEL)
7228 }
7229
7230 // Nemesis glow / remove glow, unless frozen
7231 if (!g_frozen[id])
7232 {
7233 if (g_nemesis[id] && get_pcvar_num(cvar_nemglow))
7234 fm_set_rendering(id, kRenderFxGlowShell, 250, 0, 0, kRenderNormal, 25)
7235 else if (g_nemesis[id] && !(get_pcvar_num(cvar_nemglow)))
7236 fm_set_rendering(id, kRenderFxGlowShell, 0, 0, 0, kRenderNormal, 25)
7237 if (g_assassin[id] && get_pcvar_num(cvar_assaglow))
7238 fm_set_rendering(id, kRenderFxGlowShell, 255, 255, 0, kRenderNormal, 25)
7239
7240 else if (!g_assassin[id] && !g_nemesis[id])
7241 fm_set_rendering(id)
7242 }
7243 }
7244
7245 // Remove any zoom (bugfix)
7246 cs_set_user_zoom(id, CS_RESET_ZOOM, 1)
7247
7248 // Remove armor
7249 cs_set_user_armor(id, 0, CS_ARMOR_NONE)
7250
7251 // Drop weapons when infected
7252 drop_weapons(id, 1)
7253 drop_weapons(id, 2)
7254
7255 // Strip zombies from guns and give them a knife
7256 fm_strip_user_weapons(id)
7257 fm_give_item(id, "weapon_knife")
7258
7259 // Fancy effects
7260 infection_effects(id)
7261
7262 // Nemesis aura task
7263 if (g_nemesis[id] && get_pcvar_num(cvar_nemaura))
7264 set_task(0.1, "zombie_aura", id+TASK_AURA, _, _, "b")
7265
7266 // Assassin aura task
7267 if (g_assassin[id] && get_pcvar_num(cvar_assaaura))
7268 set_task(0.1, "zombie_aura", id+TASK_AURA, _, _, "b")
7269
7270 // Remove CS nightvision if player owns one (bugfix)
7271 if (cs_get_user_nvg(id))
7272 {
7273 cs_set_user_nvg(id, 0)
7274 if (get_pcvar_num(cvar_customnvg)) remove_task(id+TASK_NVISION)
7275 else if (g_nvisionenabled[id]) set_user_gnvision(id, 0)
7276 }
7277
7278 // Give Zombies Night Vision?
7279 if (get_pcvar_num(cvar_nvggive))
7280 {
7281 g_nvision[id] = true
7282
7283 if (!g_isbot[id])
7284 {
7285 // Turn on Night Vision automatically?
7286 if (get_pcvar_num(cvar_nvggive) == 1)
7287 {
7288 g_nvisionenabled[id] = true
7289
7290 // Custom nvg?
7291 if (get_pcvar_num(cvar_customnvg))
7292 {
7293 remove_task(id+TASK_NVISION)
7294 set_task(0.1, "set_user_nvision", id+TASK_NVISION, _, _, "b")
7295 }
7296 else
7297 set_user_gnvision(id, 1)
7298 }
7299 // Turn off nightvision when infected (bugfix)
7300 else if (g_nvisionenabled[id])
7301 {
7302 if (get_pcvar_num(cvar_customnvg)) remove_task(id+TASK_NVISION)
7303 else set_user_gnvision(id, 0)
7304 g_nvisionenabled[id] = false
7305 }
7306 }
7307 else
7308 cs_set_user_nvg(id, 1); // turn on NVG for bots
7309 }
7310 // Disable nightvision when infected (bugfix)
7311 else if (g_nvision[id])
7312 {
7313 if (get_pcvar_num(cvar_customnvg)) remove_task(id+TASK_NVISION)
7314 else if (g_nvisionenabled[id]) set_user_gnvision(id, 0)
7315 g_nvision[id] = false
7316 g_nvisionenabled[id] = false
7317 }
7318
7319 // Set custom FOV?
7320 if (get_pcvar_num(cvar_zombiefov) != 90 && get_pcvar_num(cvar_zombiefov) != 0)
7321 {
7322 message_begin(MSG_ONE, g_msgSetFOV, _, id)
7323 write_byte(get_pcvar_num(cvar_zombiefov)) // fov angle
7324 message_end()
7325 }
7326
7327 // Call the bloody task
7328 if (!g_nemesis[id] && !g_nemesis[id] && get_pcvar_num(cvar_zombiebleeding))
7329 set_task(0.7, "make_blood", id+TASK_BLOOD, _, _, "b")
7330
7331 // Idle sounds task
7332 if (!g_nemesis[id] && !g_assassin[id])
7333 set_task(random_float(50.0, 70.0), "zombie_play_idle", id+TASK_BLOOD, _, _, "b")
7334
7335 // Turn off zombie's flashlight
7336 turn_off_flashlight(id)
7337
7338 // Post user infect forward
7339 ExecuteForward(g_fwUserInfected_post, g_fwDummyResult, id, infector, nemesis)
7340
7341 // Last Zombie Check
7342 fnCheckLastZombie()
7343}
7344
7345// Function Human Me (player id, turn into a survivor, silent mode)
7346humanme(id, survivor, sniper, silentmode)
7347{
7348 // User humanize attempt forward
7349 ExecuteForward(g_fwUserHumanize_attempt, g_fwDummyResult, id, survivor)
7350
7351 // One or more plugins blocked the "humanization". Only allow this after making sure it's
7352 // not going to leave us with no humans. Take into account a last player leaving case.
7353 // BUGFIX: only allow after a mode has started, to prevent blocking first survivor e.g.
7354 if (g_fwDummyResult >= ZP_PLUGIN_HANDLED && g_modestarted && fnGetHumans() > g_lastplayerleaving)
7355 return;
7356
7357 // Pre user humanize forward
7358 ExecuteForward(g_fwUserHumanized_pre, g_fwDummyResult, id, survivor)
7359
7360 // Remove previous tasks
7361 remove_task(id+TASK_MODEL)
7362 remove_task(id+TASK_BLOOD)
7363 remove_task(id+TASK_AURA)
7364 remove_task(id+TASK_BURN)
7365 remove_task(id+TASK_NVISION)
7366
7367 // Reset some vars
7368 g_zombie[id] = false
7369 g_nemesis[id] = false
7370 g_assassin[id] = false
7371 g_survivor[id] = false
7372 g_sniper[id] = false
7373 g_firstzombie[id] = false
7374 g_canbuy[id] = true
7375 g_buytime[id] = get_gametime()
7376
7377 // Remove survivor's aura (bugfix)
7378 set_pev(id, pev_effects, pev(id, pev_effects) &~ EF_BRIGHTLIGHT)
7379
7380 // Remove spawn protection (bugfix)
7381 g_nodamage[id] = false
7382 set_pev(id, pev_effects, pev(id, pev_effects) &~ EF_NODRAW)
7383
7384 // Reset burning duration counter (bugfix)
7385 g_burning_duration[id] = 0
7386
7387 // Remove CS nightvision if player owns one (bugfix)
7388 if (cs_get_user_nvg(id))
7389 {
7390 cs_set_user_nvg(id, 0)
7391 if (get_pcvar_num(cvar_customnvg)) remove_task(id+TASK_NVISION)
7392 else if (g_nvisionenabled[id]) set_user_gnvision(id, 0)
7393 }
7394
7395 // Drop previous weapons
7396 drop_weapons(id, 1)
7397 drop_weapons(id, 2)
7398
7399 // Strip off from weapons
7400 fm_strip_user_weapons(id)
7401 fm_give_item(id, "weapon_knife")
7402
7403 // Set human attributes based on the mode
7404 if (survivor)
7405 {
7406 // Survivor
7407 g_survivor[id] = true
7408
7409 // Set Health [0 = auto]
7410 if (get_pcvar_num(cvar_survhp) == 0)
7411 {
7412 if (get_pcvar_num(cvar_survbasehp) == 0)
7413 fm_set_user_health(id, get_pcvar_num(cvar_humanhp) * fnGetAlive())
7414 else
7415 fm_set_user_health(id, get_pcvar_num(cvar_survbasehp) * fnGetAlive())
7416 }
7417 else
7418 fm_set_user_health(id, get_pcvar_num(cvar_survhp))
7419
7420 // Set gravity, if frozen set the restore gravity value instead
7421 if (!g_frozen[id]) set_pev(id, pev_gravity, get_pcvar_float(cvar_survgravity))
7422 else g_frozen_gravity[id] = get_pcvar_float(cvar_survgravity)
7423
7424 // Set survivor maxspeed
7425 ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
7426
7427 // Give survivor his own weapon
7428 fm_give_item(id, "weapon_xm1014")
7429 fm_give_item(id, "weapon_ak47")
7430 fm_give_item(id, "weapon_m4a1")
7431 ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[CSW_XM1014], AMMOTYPE[CSW_XM1014], MAXBPAMMO[CSW_XM1014])
7432 ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[CSW_AK47], AMMOTYPE[CSW_AK47], MAXBPAMMO[CSW_AK47])
7433 ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[CSW_M4A1], AMMOTYPE[CSW_M4A1], MAXBPAMMO[CSW_M4A1])
7434
7435 // Turn off his flashlight
7436 turn_off_flashlight(id)
7437
7438 // Give the survivor a bright light
7439 if (get_pcvar_num(cvar_survaura)) set_pev(id, pev_effects, pev(id, pev_effects) | EF_BRIGHTLIGHT)
7440
7441 // Survivor bots will also need nightvision to see in the dark
7442 if (g_isbot[id])
7443 {
7444 g_nvision[id] = true
7445 cs_set_user_nvg(id, 1)
7446 }
7447 }
7448 else if (sniper)
7449 {
7450 // Sniper
7451 g_sniper[id] = true
7452
7453 // Set Health [0 = auto]
7454 if (get_pcvar_num(cvar_snihp) == 0)
7455 {
7456 if (get_pcvar_num(cvar_snibasehp) == 0)
7457 fm_set_user_health(id, get_pcvar_num(cvar_humanhp) * fnGetAlive())
7458 else
7459 fm_set_user_health(id, get_pcvar_num(cvar_snibasehp) * fnGetAlive())
7460 }
7461 else
7462 fm_set_user_health(id, get_pcvar_num(cvar_snihp))
7463
7464 // Set gravity, unless frozen
7465 if (!g_frozen[id]) set_pev(id, pev_gravity, get_pcvar_float(cvar_snigravity))
7466
7467 // Give sniper his own weapon
7468 fm_give_item(id, "weapon_awp")
7469 ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[CSW_AWP], AMMOTYPE[CSW_AWP], MAXBPAMMO[CSW_AWP])
7470
7471 // Turn off his flashlight
7472 turn_off_flashlight(id)
7473
7474 // Give the sniper a bright light
7475 if (get_pcvar_num(cvar_sniaura)) set_pev(id, pev_effects, pev(id, pev_effects) | EF_BRIGHTLIGHT)
7476
7477 // Sniper bots will also need nightvision to see in the dark
7478 if (g_isbot[id])
7479 {
7480 g_nvision[id] = true
7481 cs_set_user_nvg(id, 1)
7482 }
7483 }
7484 else
7485 {
7486 // Human taking an antidote
7487
7488 // Set health
7489 fm_set_user_health(id, get_pcvar_num(cvar_humanhp))
7490
7491 // Set gravity, if frozen set the restore gravity value instead
7492 if (!g_frozen[id]) set_pev(id, pev_gravity, get_pcvar_float(cvar_humangravity))
7493 else g_frozen_gravity[id] = get_pcvar_float(cvar_humangravity)
7494
7495 // Set human maxspeed
7496 ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
7497
7498 // Show custom buy menu?
7499 if (get_pcvar_num(cvar_buycustom))
7500 set_task(0.2, "show_menu_buy1", id+TASK_SPAWN)
7501
7502 // Silent mode = no HUD messages, no antidote sound
7503 if (!silentmode)
7504 {
7505 // Antidote sound
7506 static sound[64]
7507 ArrayGetString(sound_antidote, random_num(0, ArraySize(sound_antidote) - 1), sound, charsmax(sound))
7508 emit_sound(id, CHAN_ITEM, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
7509
7510 // Show Antidote HUD notice
7511 set_hudmessage(0, 0, 255, HUD_INFECT_X, HUD_INFECT_Y, 0, 0.0, 5.0, 1.0, 1.0, -1)
7512 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_ANTIDOTE", g_playername[id])
7513 }
7514 }
7515
7516 remove_freeze(id);
7517
7518 // Switch to CT
7519 if (fm_cs_get_user_team(id) != FM_CS_TEAM_CT) // need to change team?
7520 {
7521 remove_task(id+TASK_TEAM)
7522 fm_cs_set_user_team(id, FM_CS_TEAM_CT)
7523 fm_user_team_update(id)
7524 }
7525
7526 // Custom models stuff
7527 static currentmodel[32], tempmodel[32], already_has_model, i, iRand, size
7528 already_has_model = false
7529
7530 if (g_handle_models_on_separate_ent)
7531 {
7532 // Set the right model
7533 if (g_survivor[id])
7534 {
7535 iRand = random_num(0, ArraySize(model_survivor) - 1)
7536 ArrayGetString(model_survivor, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7537 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_survivor, iRand))
7538 }
7539 else if (g_sniper[id])
7540 {
7541 iRand = random_num(0, ArraySize(model_sniper) - 1)
7542 ArrayGetString(model_sniper, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7543 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_sniper, iRand))
7544 }
7545 else
7546 {
7547 if (get_pcvar_num(cvar_adminmodelshuman) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
7548 {
7549 iRand = random_num(0, ArraySize(model_admin_human) - 1)
7550 ArrayGetString(model_admin_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7551 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_human, iRand))
7552 }
7553 else
7554 {
7555 iRand = random_num(0, ArraySize(model_human) - 1)
7556 ArrayGetString(model_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7557 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_human, iRand))
7558 }
7559 }
7560
7561 // Set model on player model entity
7562 fm_set_playermodel_ent(id)
7563
7564 // Set survivor glow / remove glow on player model entity, unless frozen
7565 if (!g_frozen[id])
7566 {
7567 if (g_survivor[id] && get_pcvar_num(cvar_survglow))
7568 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 0, 0, 255, kRenderNormal, 25)
7569 else if (g_sniper[id] && get_pcvar_num(cvar_sniglow))
7570 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 0, 255, 0, kRenderNormal, 25)
7571 else
7572 fm_set_rendering(g_ent_playermodel[id])
7573 }
7574 }
7575 else
7576 {
7577 // Get current model for comparing it with the current one
7578 fm_cs_get_user_model(id, currentmodel, charsmax(currentmodel))
7579
7580 // Set the right model, after checking that we don't already have it
7581 if (g_survivor[id])
7582 {
7583 size = ArraySize(model_survivor)
7584 for (i = 0; i < size; i++)
7585 {
7586 ArrayGetString(model_survivor, i, tempmodel, charsmax(tempmodel))
7587 if (equal(currentmodel, tempmodel)) already_has_model = true
7588 }
7589
7590 if (!already_has_model)
7591 {
7592 iRand = random_num(0, size - 1)
7593 ArrayGetString(model_survivor, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7594 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_survivor, iRand))
7595 }
7596 }
7597 else if (g_sniper[id])
7598 {
7599 size = ArraySize(model_sniper)
7600 for (i = 0; i < size; i++)
7601 {
7602 ArrayGetString(model_sniper, i, tempmodel, charsmax(tempmodel))
7603 if (equal(currentmodel, tempmodel)) already_has_model = true
7604 }
7605
7606 if (!already_has_model)
7607 {
7608 iRand = random_num(0, size - 1)
7609 ArrayGetString(model_sniper, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7610 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_sniper, iRand))
7611 }
7612 }
7613 else
7614 {
7615 if (get_pcvar_num(cvar_adminmodelshuman) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
7616 {
7617 size = ArraySize(model_admin_human)
7618 for (i = 0; i < size; i++)
7619 {
7620 ArrayGetString(model_admin_human, i, tempmodel, charsmax(tempmodel))
7621 if (equal(currentmodel, tempmodel)) already_has_model = true
7622 }
7623
7624 if (!already_has_model)
7625 {
7626 iRand = random_num(0, size - 1)
7627 ArrayGetString(model_admin_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7628 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_human, iRand))
7629 }
7630 }
7631 else
7632 {
7633 size = ArraySize(model_human)
7634 for (i = 0; i < size; i++)
7635 {
7636 ArrayGetString(model_human, i, tempmodel, charsmax(tempmodel))
7637 if (equal(currentmodel, tempmodel)) already_has_model = true
7638 }
7639
7640 if (!already_has_model)
7641 {
7642 iRand = random_num(0, size - 1)
7643 ArrayGetString(model_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7644 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_human, iRand))
7645 }
7646 }
7647 }
7648
7649 // Need to change the model?
7650 if (!already_has_model)
7651 {
7652 // An additional delay is offset at round start
7653 // since SVC_BAD is more likely to be triggered there
7654 if (g_newround)
7655 set_task(5.0 * g_modelchange_delay, "fm_user_model_update", id+TASK_MODEL)
7656 else
7657 fm_user_model_update(id+TASK_MODEL)
7658 }
7659
7660 // Set survivor glow / remove glow, unless frozen
7661 if (!g_frozen[id])
7662 {
7663 if (g_survivor[id] && get_pcvar_num(cvar_survglow))
7664 fm_set_rendering(id, kRenderFxGlowShell, 0, 0, 255, kRenderNormal, 25)
7665 else if (g_sniper[id] && get_pcvar_num(cvar_sniglow))
7666 fm_set_rendering(id, kRenderFxGlowShell, 0, 255, 0, kRenderNormal, 25)
7667 else
7668 fm_set_rendering(id)
7669 }
7670 }
7671
7672 // Restore FOV?
7673 if (get_pcvar_num(cvar_zombiefov) != 90 && get_pcvar_num(cvar_zombiefov) != 0)
7674 {
7675 message_begin(MSG_ONE, g_msgSetFOV, _, id)
7676 write_byte(90) // angle
7677 message_end()
7678 }
7679
7680 // Disable nightvision when turning into human/survivor (bugfix)
7681 if (g_nvision[id])
7682 {
7683 if (get_pcvar_num(cvar_customnvg)) remove_task(id+TASK_NVISION)
7684 else if (g_nvisionenabled[id]) set_user_gnvision(id, 0)
7685 g_nvision[id] = false
7686 g_nvisionenabled[id] = false
7687 }
7688
7689 // Post user humanize forward
7690 ExecuteForward(g_fwUserHumanized_post, g_fwDummyResult, id, survivor)
7691
7692 // Last Zombie Check
7693 fnCheckLastZombie()
7694}
7695
7696/*================================================================================
7697 [Other Functions and Tasks]
7698=================================================================================*/
7699
7700public cache_cvars()
7701{
7702 g_cached_zombiesilent = get_pcvar_num(cvar_zombiesilent)
7703 g_cached_customflash = get_pcvar_num(cvar_customflash)
7704 g_cached_leapzombies = get_pcvar_num(cvar_leapzombies)
7705 g_cached_leapzombiescooldown = get_pcvar_float(cvar_leapzombiescooldown)
7706 g_cached_leapnemesis = get_pcvar_num(cvar_leapnemesis)
7707 g_cached_leapnemesiscooldown = get_pcvar_float(cvar_leapnemesiscooldown)
7708 g_cached_leapassassin = get_pcvar_num(cvar_leapassassin)
7709 g_cached_leapassassincooldown = get_pcvar_float(cvar_leapassassincooldown)
7710 g_cached_leapsurvivor = get_pcvar_num(cvar_leapsurvivor)
7711 g_cached_leapsurvivorcooldown = get_pcvar_float(cvar_leapsurvivorcooldown)
7712 g_cached_leapsniper = get_pcvar_num(cvar_leapsniper)
7713 g_cached_leapsnipercooldown = get_pcvar_float(cvar_leapsnipercooldown)
7714 g_cached_buytime = get_pcvar_float(cvar_buyzonetime)
7715}
7716
7717load_customization_from_files()
7718{
7719 // Build customization file path
7720 new path[64]
7721 get_configsdir(path, charsmax(path))
7722 format(path, charsmax(path), "%s/%s", path, ZP_CUSTOMIZATION_FILE)
7723
7724 // File not present
7725 if (!file_exists(path))
7726 {
7727 new error[100]
7728 formatex(error, charsmax(error), "Cannot load customization file %s!", path)
7729 set_fail_state(error)
7730 return;
7731 }
7732
7733 // Set up some vars to hold parsing info
7734 new linedata[1024], key[64], value[960], section, teams
7735
7736 // Open customization file for reading
7737 new file = fopen(path, "rt")
7738
7739 while (file && !feof(file))
7740 {
7741 // Read one line at a time
7742 fgets(file, linedata, charsmax(linedata))
7743
7744 // Replace newlines with a null character to prevent headaches
7745 replace(linedata, charsmax(linedata), "^n", "")
7746
7747 // Blank line or comment
7748 if (!linedata[0] || linedata[0] == ';') continue;
7749
7750 // New section starting
7751 if (linedata[0] == '[')
7752 {
7753 section++
7754 continue;
7755 }
7756
7757 // Get key and value(s)
7758 strtok(linedata, key, charsmax(key), value, charsmax(value), '=')
7759
7760 // Trim spaces
7761 trim(key)
7762 trim(value)
7763
7764 switch (section)
7765 {
7766 case SECTION_ACCESS_FLAGS:
7767 {
7768 if (equal(key, "ENABLE/DISABLE MOD"))
7769 g_access_flag[ACCESS_ENABLE_MOD] = read_flags(value)
7770 else if (equal(key, "ADMIN MENU"))
7771 g_access_flag[ACCESS_ADMIN_MENU] = read_flags(value)
7772 else if (equal(key, "ADMIN MODES MENU"))
7773 g_access_flag[ACCESS_ADMIN_MODES_MENU] = read_flags(value)
7774 else if (equal(key, "START MODE INFECTION"))
7775 g_access_flag[ACCESS_MODE_INFECTION] = read_flags(value)
7776 else if (equal(key, "START MODE NEMESIS"))
7777 g_access_flag[ACCESS_MODE_NEMESIS] = read_flags(value)
7778 else if (equal(key, "START MODE ASSASSIN"))
7779 g_access_flag[ACCESS_MODE_ASSASSIN] = read_flags(value)
7780 else if (equal(key, "START MODE SURVIVOR"))
7781 g_access_flag[ACCESS_MODE_SURVIVOR] = read_flags(value)
7782 else if (equal(key, "START MODE SNIPER"))
7783 g_access_flag[ACCESS_MODE_SNIPER] = read_flags(value)
7784 else if (equal(key, "START MODE SWARM"))
7785 g_access_flag[ACCESS_MODE_SWARM] = read_flags(value)
7786 else if (equal(key, "START MODE MULTI"))
7787 g_access_flag[ACCESS_MODE_MULTI] = read_flags(value)
7788 else if (equal(key, "START MODE PLAGUE"))
7789 g_access_flag[ACCESS_MODE_PLAGUE] = read_flags(value)
7790 else if (equal(key, "START MODE ARMAGEDDON"))
7791 g_access_flag[ACCESS_MODE_ARMAGEDDON] = read_flags(value)
7792 else if (equal(key, "START MODE APOCALYPSE"))
7793 g_access_flag[ACCESS_MODE_APOCALYPSE] = read_flags(value)
7794 else if (equal(key, "START MODE NIGHTMARE"))
7795 g_access_flag[ACCESS_MODE_NIGHTMARE] = read_flags(value)
7796 else if (equal(key, "MAKE ZOMBIE"))
7797 g_access_flag[ACCESS_MAKE_ZOMBIE] = read_flags(value)
7798 else if (equal(key, "MAKE HUMAN"))
7799 g_access_flag[ACCESS_MAKE_HUMAN] = read_flags(value)
7800 else if (equal(key, "MAKE NEMESIS"))
7801 g_access_flag[ACCESS_MAKE_NEMESIS] = read_flags(value)
7802 else if (equal(key, "MAKE ASSASSIN"))
7803 g_access_flag[ACCESS_MAKE_ASSASSIN] = read_flags(value)
7804 else if (equal(key, "MAKE SURVIVOR"))
7805 g_access_flag[ACCESS_MAKE_SURVIVOR] = read_flags(value)
7806 else if (equal(key, "MAKE SNIPER"))
7807 g_access_flag[ACCESS_MAKE_SNIPER] = read_flags(value)
7808 else if (equal(key, "RESPAWN PLAYERS"))
7809 g_access_flag[ACCESS_RESPAWN_PLAYERS] = read_flags(value)
7810 else if (equal(key, "ADMIN MODELS"))
7811 g_access_flag[ACCESS_ADMIN_MODELS] = read_flags(value)
7812 }
7813 case SECTION_PLAYER_MODELS:
7814 {
7815 if (equal(key, "HUMAN"))
7816 {
7817 // Parse models
7818 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
7819 {
7820 // Trim spaces
7821 trim(key)
7822 trim(value)
7823
7824 // Add to models array
7825 ArrayPushString(model_human, key)
7826 }
7827 }
7828 else if (equal(key, "NEMESIS"))
7829 {
7830 // Parse models
7831 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
7832 {
7833 // Trim spaces
7834 trim(key)
7835 trim(value)
7836
7837 // Add to models array
7838 ArrayPushString(model_nemesis, key)
7839 }
7840 }
7841 else if (equal(key, "ASSASSIN"))
7842 {
7843 // Parse models
7844 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
7845 {
7846 // Trim spaces
7847 trim(key)
7848 trim(value)
7849
7850 // Add to models array
7851 ArrayPushString(model_assassin, key)
7852 }
7853 }
7854 else if (equal(key, "SURVIVOR"))
7855 {
7856 // Parse models
7857 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
7858 {
7859 // Trim spaces
7860 trim(key)
7861 trim(value)
7862
7863 // Add to models array
7864 ArrayPushString(model_survivor, key)
7865 }
7866 }
7867 else if (equal(key, "SNIPER"))
7868 {
7869 // Parse models
7870 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
7871 {
7872 // Trim spaces
7873 trim(key)
7874 trim(value)
7875
7876 // Add to models array
7877 ArrayPushString(model_sniper, key)
7878 }
7879 }
7880 else if (equal(key, "ADMIN ZOMBIE"))
7881 {
7882 // Parse models
7883 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
7884 {
7885 // Trim spaces
7886 trim(key)
7887 trim(value)
7888
7889 // Add to models array
7890 ArrayPushString(model_admin_zombie, key)
7891 }
7892 }
7893 else if (equal(key, "ADMIN HUMAN"))
7894 {
7895 // Parse models
7896 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
7897 {
7898 // Trim spaces
7899 trim(key)
7900 trim(value)
7901
7902 // Add to models array
7903 ArrayPushString(model_admin_human, key)
7904 }
7905 }
7906 else if (equal(key, "FORCE CONSISTENCY"))
7907 g_force_consistency = str_to_num(value)
7908 else if (equal(key, "SAME MODELS FOR ALL"))
7909 g_same_models_for_all = str_to_num(value)
7910 else if (g_same_models_for_all && equal(key, "ZOMBIE"))
7911 {
7912 // Parse models
7913 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
7914 {
7915 // Trim spaces
7916 trim(key)
7917 trim(value)
7918
7919 // Add to models array
7920 ArrayPushString(g_zclass_playermodel, key)
7921
7922 // Precache model and retrieve its modelindex
7923 formatex(linedata, charsmax(linedata), "models/player/%s/%s.mdl", key, key)
7924 ArrayPushCell(g_zclass_modelindex, engfunc(EngFunc_PrecacheModel, linedata))
7925 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, linedata)
7926 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, linedata)
7927 // Precache modelT.mdl files too
7928 copy(linedata[strlen(linedata)-4], charsmax(linedata) - (strlen(linedata)-4), "T.mdl")
7929 if (file_exists(linedata)) engfunc(EngFunc_PrecacheModel, linedata)
7930 }
7931 }
7932 }
7933 case SECTION_WEAPON_MODELS:
7934 {
7935 if (equal(key, "V_KNIFE HUMAN"))
7936 copy(model_vknife_human, charsmax(model_vknife_human), value)
7937 else if (equal(key, "V_KNIFE NEMESIS"))
7938 copy(model_vknife_nemesis, charsmax(model_vknife_nemesis), value)
7939 else if (equal(key, "V_KNIFE ASSASSIN"))
7940 copy(model_vknife_assassin, charsmax(model_vknife_assassin), value)
7941 else if (equal(key, "V_M249 SURVIVOR")) // backwards compatibility with old configs
7942 copy(model_vweapon_survivor, charsmax(model_vweapon_survivor), value)
7943 else if (equal(key, "V_WEAPON SURVIVOR"))
7944 copy(model_vweapon_survivor, charsmax(model_vweapon_survivor), value)
7945 else if (equal(key, "V_AWP SNIPER"))
7946 copy(model_vawp_sniper, charsmax(model_vawp_sniper), value)
7947 else if (equal(key, "P_AWP SNIPER"))
7948 copy(model_pawp_sniper, charsmax(model_pawp_sniper), value)
7949 else if (equal(key, "GRENADE INFECT"))
7950 copy(model_grenade_infect, charsmax(model_grenade_infect), value)
7951 else if (equal(key, "GRENADE FIRE"))
7952 copy(model_grenade_fire, charsmax(model_grenade_fire), value)
7953 else if (equal(key, "GRENADE FROST"))
7954 copy(model_grenade_frost, charsmax(model_grenade_frost), value)
7955 else if (equal(key, "GRENADE FLARE"))
7956 copy(model_grenade_flare, charsmax(model_grenade_flare), value)
7957 else if (equal(key, "V_KNIFE ADMIN HUMAN"))
7958 copy(model_vknife_admin_human, charsmax(model_vknife_admin_human), value)
7959 else if (equal(key, "V_KNIFE ADMIN ZOMBIE"))
7960 copy(model_vknife_admin_zombie, charsmax(model_vknife_admin_zombie), value)
7961 }
7962 case SECTION_GRENADE_SPRITES:
7963 {
7964 if (equal(key, "TRAIL"))
7965 copy(sprite_grenade_trail, charsmax(sprite_grenade_trail), value)
7966 else if (equal(key, "RING"))
7967 copy(sprite_grenade_ring, charsmax(sprite_grenade_ring), value)
7968 else if (equal(key, "FIRE"))
7969 copy(sprite_grenade_fire, charsmax(sprite_grenade_fire), value)
7970 else if (equal(key, "SMOKE"))
7971 copy(sprite_grenade_smoke, charsmax(sprite_grenade_smoke), value)
7972 else if (equal(key, "GLASS"))
7973 copy(sprite_grenade_glass, charsmax(sprite_grenade_glass), value)
7974 }
7975 case SECTION_SOUNDS:
7976 {
7977 if (equal(key, "WIN ZOMBIES"))
7978 {
7979 // Parse sounds
7980 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
7981 {
7982 // Trim spaces
7983 trim(key)
7984 trim(value)
7985
7986 // Add to sounds array
7987 ArrayPushString(sound_win_zombies, key)
7988 ArrayPushCell(sound_win_zombies_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
7989 }
7990 }
7991 else if (equal(key, "WIN HUMANS"))
7992 {
7993 // Parse sounds
7994 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
7995 {
7996 // Trim spaces
7997 trim(key)
7998 trim(value)
7999
8000 // Add to sounds array
8001 ArrayPushString(sound_win_humans, key)
8002 ArrayPushCell(sound_win_humans_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8003 }
8004 }
8005 else if (equal(key, "WIN NO ONE"))
8006 {
8007 // Parse sounds
8008 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8009 {
8010 // Trim spaces
8011 trim(key)
8012 trim(value)
8013
8014 // Add to sounds array
8015 ArrayPushString(sound_win_no_one, key)
8016 ArrayPushCell(sound_win_no_one_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8017 }
8018 }
8019 else if (equal(key, "ZOMBIE INFECT"))
8020 {
8021 // Parse sounds
8022 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8023 {
8024 // Trim spaces
8025 trim(key)
8026 trim(value)
8027
8028 // Add to sounds array
8029 ArrayPushString(zombie_infect, key)
8030 }
8031 }
8032 else if (equal(key, "ZOMBIE PAIN"))
8033 {
8034 // Parse sounds
8035 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8036 {
8037 // Trim spaces
8038 trim(key)
8039 trim(value)
8040
8041 // Add to sounds array
8042 ArrayPushString(zombie_pain, key)
8043 }
8044 }
8045 else if (equal(key, "NEMESIS PAIN"))
8046 {
8047 // Parse sounds
8048 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8049 {
8050 // Trim spaces
8051 trim(key)
8052 trim(value)
8053
8054 // Add to sounds array
8055 ArrayPushString(nemesis_pain, key)
8056 }
8057 }
8058 else if (equal(key, "ASSASSIN PAIN"))
8059 {
8060 // Parse sounds
8061 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8062 {
8063 // Trim spaces
8064 trim(key)
8065 trim(value)
8066
8067 // Add to sounds array
8068 ArrayPushString(assassin_pain, key)
8069 }
8070 }
8071 else if (equal(key, "ZOMBIE DIE"))
8072 {
8073 // Parse sounds
8074 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8075 {
8076 // Trim spaces
8077 trim(key)
8078 trim(value)
8079
8080 // Add to sounds array
8081 ArrayPushString(zombie_die, key)
8082 }
8083 }
8084 else if (equal(key, "ZOMBIE FALL"))
8085 {
8086 // Parse sounds
8087 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8088 {
8089 // Trim spaces
8090 trim(key)
8091 trim(value)
8092
8093 // Add to sounds array
8094 ArrayPushString(zombie_fall, key)
8095 }
8096 }
8097 else if (equal(key, "ZOMBIE MISS SLASH"))
8098 {
8099 // Parse sounds
8100 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8101 {
8102 // Trim spaces
8103 trim(key)
8104 trim(value)
8105
8106 // Add to sounds array
8107 ArrayPushString(zombie_miss_slash, key)
8108 }
8109 }
8110 else if (equal(key, "ZOMBIE MISS WALL"))
8111 {
8112 // Parse sounds
8113 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8114 {
8115 // Trim spaces
8116 trim(key)
8117 trim(value)
8118
8119 // Add to sounds array
8120 ArrayPushString(zombie_miss_wall, key)
8121 }
8122 }
8123 else if (equal(key, "ZOMBIE HIT NORMAL"))
8124 {
8125 // Parse sounds
8126 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8127 {
8128 // Trim spaces
8129 trim(key)
8130 trim(value)
8131
8132 // Add to sounds array
8133 ArrayPushString(zombie_hit_normal, key)
8134 }
8135 }
8136 else if (equal(key, "ZOMBIE HIT STAB"))
8137 {
8138 // Parse sounds
8139 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8140 {
8141 // Trim spaces
8142 trim(key)
8143 trim(value)
8144
8145 // Add to sounds array
8146 ArrayPushString(zombie_hit_stab, key)
8147 }
8148 }
8149 else if (equal(key, "ZOMBIE IDLE"))
8150 {
8151 // Parse sounds
8152 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8153 {
8154 // Trim spaces
8155 trim(key)
8156 trim(value)
8157
8158 // Add to sounds array
8159 ArrayPushString(zombie_idle, key)
8160 }
8161 }
8162 else if (equal(key, "ZOMBIE IDLE LAST"))
8163 {
8164 // Parse sounds
8165 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8166 {
8167 // Trim spaces
8168 trim(key)
8169 trim(value)
8170
8171 // Add to sounds array
8172 ArrayPushString(zombie_idle_last, key)
8173 }
8174 }
8175 else if (equal(key, "ZOMBIE MADNESS"))
8176 {
8177 // Parse sounds
8178 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8179 {
8180 // Trim spaces
8181 trim(key)
8182 trim(value)
8183
8184 // Add to sounds array
8185 ArrayPushString(zombie_madness, key)
8186 }
8187 }
8188 else if (equal(key, "ROUND NEMESIS"))
8189 {
8190 // Parse sounds
8191 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8192 {
8193 // Trim spaces
8194 trim(key)
8195 trim(value)
8196
8197 // Add to sounds array
8198 ArrayPushString(sound_nemesis, key)
8199 }
8200 }
8201 else if (equal(key, "ROUND ASSASSIN"))
8202 {
8203 // Parse sounds
8204 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8205 {
8206 // Trim spaces
8207 trim(key)
8208 trim(value)
8209
8210 // Add to sounds array
8211 ArrayPushString(sound_assassin, key)
8212 }
8213 }
8214 else if (equal(key, "ROUND SURVIVOR"))
8215 {
8216 // Parse sounds
8217 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8218 {
8219 // Trim spaces
8220 trim(key)
8221 trim(value)
8222
8223 // Add to sounds array
8224 ArrayPushString(sound_survivor, key)
8225 }
8226 }
8227 else if (equal(key, "ROUND SNIPER"))
8228 {
8229 // Parse sounds
8230 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8231 {
8232 // Trim spaces
8233 trim(key)
8234 trim(value)
8235
8236 // Add to sounds array
8237 ArrayPushString(sound_sniper, key)
8238 }
8239 }
8240 else if (equal(key, "ROUND SWARM"))
8241 {
8242 // Parse sounds
8243 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8244 {
8245 // Trim spaces
8246 trim(key)
8247 trim(value)
8248
8249 // Add to sounds array
8250 ArrayPushString(sound_swarm, key)
8251 }
8252 }
8253 else if (equal(key, "ROUND MULTI"))
8254 {
8255 // Parse sounds
8256 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8257 {
8258 // Trim spaces
8259 trim(key)
8260 trim(value)
8261
8262 // Add to sounds array
8263 ArrayPushString(sound_multi, key)
8264 }
8265 }
8266 else if (equal(key, "ROUND PLAGUE"))
8267 {
8268 // Parse sounds
8269 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8270 {
8271 // Trim spaces
8272 trim(key)
8273 trim(value)
8274
8275 // Add to sounds array
8276 ArrayPushString(sound_plague, key)
8277 }
8278 }
8279 else if (equal(key, "ROUND ARMAGEDDON"))
8280 {
8281 // Parse sounds
8282 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8283 {
8284 // Trim spaces
8285 trim(key)
8286 trim(value)
8287
8288 // Add to sounds array
8289 ArrayPushString(sound_armageddon, key)
8290 }
8291 }
8292 else if (equal(key, "ROUND APOCALYPSE"))
8293 {
8294 // Parse sounds
8295 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8296 {
8297 // Trim spaces
8298 trim(key)
8299 trim(value)
8300
8301 // Add to sounds array
8302 ArrayPushString(sound_apocalypse, key)
8303 }
8304 }
8305 else if (equal(key, "ROUND NIGHTMARE"))
8306 {
8307 // Parse sounds
8308 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8309 {
8310 // Trim spaces
8311 trim(key)
8312 trim(value)
8313
8314 // Add to sounds array
8315 ArrayPushString(sound_nightmare, key)
8316 }
8317 }
8318 else if (equal(key, "GRENADE INFECT EXPLODE"))
8319 {
8320 // Parse sounds
8321 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8322 {
8323 // Trim spaces
8324 trim(key)
8325 trim(value)
8326
8327 // Add to sounds array
8328 ArrayPushString(grenade_infect, key)
8329 }
8330 }
8331 else if (equal(key, "GRENADE INFECT PLAYER"))
8332 {
8333 // Parse sounds
8334 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8335 {
8336 // Trim spaces
8337 trim(key)
8338 trim(value)
8339
8340 // Add to sounds array
8341 ArrayPushString(grenade_infect_player, key)
8342 }
8343 }
8344 else if (equal(key, "GRENADE FIRE EXPLODE"))
8345 {
8346 // Parse sounds
8347 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8348 {
8349 // Trim spaces
8350 trim(key)
8351 trim(value)
8352
8353 // Add to sounds array
8354 ArrayPushString(grenade_fire, key)
8355 }
8356 }
8357 else if (equal(key, "GRENADE FIRE PLAYER"))
8358 {
8359 // Parse sounds
8360 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8361 {
8362 // Trim spaces
8363 trim(key)
8364 trim(value)
8365
8366 // Add to sounds array
8367 ArrayPushString(grenade_fire_player, key)
8368 }
8369 }
8370 else if (equal(key, "GRENADE FROST EXPLODE"))
8371 {
8372 // Parse sounds
8373 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8374 {
8375 // Trim spaces
8376 trim(key)
8377 trim(value)
8378
8379 // Add to sounds array
8380 ArrayPushString(grenade_frost, key)
8381 }
8382 }
8383 else if (equal(key, "GRENADE FROST PLAYER"))
8384 {
8385 // Parse sounds
8386 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8387 {
8388 // Trim spaces
8389 trim(key)
8390 trim(value)
8391
8392 // Add to sounds array
8393 ArrayPushString(grenade_frost_player, key)
8394 }
8395 }
8396 else if (equal(key, "GRENADE FROST BREAK"))
8397 {
8398 // Parse sounds
8399 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8400 {
8401 // Trim spaces
8402 trim(key)
8403 trim(value)
8404
8405 // Add to sounds array
8406 ArrayPushString(grenade_frost_break, key)
8407 }
8408 }
8409 else if (equal(key, "GRENADE FLARE"))
8410 {
8411 // Parse sounds
8412 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8413 {
8414 // Trim spaces
8415 trim(key)
8416 trim(value)
8417
8418 // Add to sounds array
8419 ArrayPushString(grenade_flare, key)
8420 }
8421 }
8422 else if (equal(key, "ANTIDOTE"))
8423 {
8424 // Parse sounds
8425 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8426 {
8427 // Trim spaces
8428 trim(key)
8429 trim(value)
8430
8431 // Add to sounds array
8432 ArrayPushString(sound_antidote, key)
8433 }
8434 }
8435 else if (equal(key, "THUNDER"))
8436 {
8437 // Parse sounds
8438 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8439 {
8440 // Trim spaces
8441 trim(key)
8442 trim(value)
8443
8444 // Add to sounds array
8445 ArrayPushString(sound_thunder, key)
8446 }
8447 }
8448 }
8449 case SECTION_AMBIENCE_SOUNDS:
8450 {
8451 if (equal(key, "INFECTION ENABLE"))
8452 g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION] = str_to_num(value)
8453 else if (g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION] && equal(key, "INFECTION SOUNDS"))
8454 {
8455 // Parse sounds
8456 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8457 {
8458 // Trim spaces
8459 trim(key)
8460 trim(value)
8461
8462 // Add to sounds array
8463 ArrayPushString(sound_ambience1, key)
8464 ArrayPushCell(sound_ambience1_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8465 }
8466 }
8467 else if (g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION] && equal(key, "INFECTION DURATIONS"))
8468 {
8469 // Parse sounds
8470 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8471 {
8472 // Trim spaces
8473 trim(key)
8474 trim(value)
8475
8476 // Add to sounds array
8477 ArrayPushCell(sound_ambience1_duration, str_to_num(key))
8478 }
8479 }
8480 else if (equal(key, "NEMESIS ENABLE"))
8481 g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS] = str_to_num(value)
8482 else if (g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS] && equal(key, "NEMESIS SOUNDS"))
8483 {
8484 // Parse sounds
8485 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8486 {
8487 // Trim spaces
8488 trim(key)
8489 trim(value)
8490
8491 // Add to sounds array
8492 ArrayPushString(sound_ambience2, key)
8493 ArrayPushCell(sound_ambience2_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8494 }
8495 }
8496 else if (g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS] && equal(key, "NEMESIS DURATIONS"))
8497 {
8498 // Parse sounds
8499 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8500 {
8501 // Trim spaces
8502 trim(key)
8503 trim(value)
8504
8505 // Add to sounds array
8506 ArrayPushCell(sound_ambience2_duration, str_to_num(key))
8507 }
8508 }
8509 else if (equal(key, "ASSASSIN ENABLE"))
8510 g_ambience_sounds[AMBIENCE_SOUNDS_ASSASSIN] = str_to_num(value)
8511 else if (g_ambience_sounds[AMBIENCE_SOUNDS_ASSASSIN] && equal(key, "ASSASSIN SOUNDS"))
8512 {
8513 // Parse sounds
8514 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8515 {
8516 // Trim spaces
8517 trim(key)
8518 trim(value)
8519
8520 // Add to sounds array
8521 ArrayPushString(sound_ambience6, key)
8522 ArrayPushCell(sound_ambience6_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8523 }
8524 }
8525 else if (g_ambience_sounds[AMBIENCE_SOUNDS_ASSASSIN] && equal(key, "ASSASSIN DURATIONS"))
8526 {
8527 // Parse sounds
8528 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8529 {
8530 // Trim spaces
8531 trim(key)
8532 trim(value)
8533
8534 // Add to sounds array
8535 ArrayPushCell(sound_ambience6_duration, str_to_num(key))
8536 }
8537 }
8538 else if (equal(key, "SURVIVOR ENABLE"))
8539 g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR] = str_to_num(value)
8540 else if (g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR] && equal(key, "SURVIVOR SOUNDS"))
8541 {
8542 // Parse sounds
8543 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8544 {
8545 // Trim spaces
8546 trim(key)
8547 trim(value)
8548
8549 // Add to sounds array
8550 ArrayPushString(sound_ambience3, key)
8551 ArrayPushCell(sound_ambience3_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8552 }
8553 }
8554 else if (g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR] && equal(key, "SURVIVOR DURATIONS"))
8555 {
8556 // Parse sounds
8557 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8558 {
8559 // Trim spaces
8560 trim(key)
8561 trim(value)
8562
8563 // Add to sounds array
8564 ArrayPushCell(sound_ambience3_duration, str_to_num(key))
8565 }
8566 }
8567 else if (equal(key, "SNIPER ENABLE"))
8568 g_ambience_sounds[AMBIENCE_SOUNDS_SNIPER] = str_to_num(value)
8569 else if (g_ambience_sounds[AMBIENCE_SOUNDS_SNIPER] && equal(key, "SNIPER SOUNDS"))
8570 {
8571 // Parse sounds
8572 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8573 {
8574 // Trim spaces
8575 trim(key)
8576 trim(value)
8577
8578 // Add to sounds array
8579 ArrayPushString(sound_ambience7, key)
8580 ArrayPushCell(sound_ambience7_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8581 }
8582 }
8583 else if (g_ambience_sounds[AMBIENCE_SOUNDS_SNIPER] && equal(key, "SNIPER DURATIONS"))
8584 {
8585 // Parse sounds
8586 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8587 {
8588 // Trim spaces
8589 trim(key)
8590 trim(value)
8591
8592 // Add to sounds array
8593 ArrayPushCell(sound_ambience7_duration, str_to_num(key))
8594 }
8595 }
8596 else if (equal(key, "SWARM ENABLE"))
8597 g_ambience_sounds[AMBIENCE_SOUNDS_SWARM] = str_to_num(value)
8598 else if (g_ambience_sounds[AMBIENCE_SOUNDS_SWARM] && equal(key, "SWARM SOUNDS"))
8599 {
8600 // Parse sounds
8601 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8602 {
8603 // Trim spaces
8604 trim(key)
8605 trim(value)
8606
8607 // Add to sounds array
8608 ArrayPushString(sound_ambience4, key)
8609 ArrayPushCell(sound_ambience4_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8610 }
8611 }
8612 else if (g_ambience_sounds[AMBIENCE_SOUNDS_SWARM] && equal(key, "SWARM DURATIONS"))
8613 {
8614 // Parse sounds
8615 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8616 {
8617 // Trim spaces
8618 trim(key)
8619 trim(value)
8620
8621 // Add to sounds array
8622 ArrayPushCell(sound_ambience4_duration, str_to_num(key))
8623 }
8624 }
8625 else if (equal(key, "PLAGUE ENABLE"))
8626 g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE] = str_to_num(value)
8627 else if (g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE] && equal(key, "PLAGUE SOUNDS"))
8628 {
8629 // Parse sounds
8630 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8631 {
8632 // Trim spaces
8633 trim(key)
8634 trim(value)
8635
8636 // Add to sounds array
8637 ArrayPushString(sound_ambience5, key)
8638 ArrayPushCell(sound_ambience5_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8639 }
8640 }
8641 else if (g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE] && equal(key, "PLAGUE DURATIONS"))
8642 {
8643 // Parse sounds
8644 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8645 {
8646 // Trim spaces
8647 trim(key)
8648 trim(value)
8649
8650 // Add to sounds array
8651 ArrayPushCell(sound_ambience5_duration, str_to_num(key))
8652 }
8653 }
8654 else if (equal(key, "ARMAGEDDON ENABLE"))
8655 g_ambience_sounds[AMBIENCE_SOUNDS_ARMAGEDDON] = str_to_num(value)
8656 else if (g_ambience_sounds[AMBIENCE_SOUNDS_ARMAGEDDON] && equal(key, "ARMAGEDDON SOUNDS"))
8657 {
8658 // Parse sounds
8659 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8660 {
8661 // Trim spaces
8662 trim(key)
8663 trim(value)
8664
8665 // Add to sounds array
8666 ArrayPushString(sound_ambience8, key)
8667 ArrayPushCell(sound_ambience8_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8668 }
8669 }
8670 else if (g_ambience_sounds[AMBIENCE_SOUNDS_ARMAGEDDON] && equal(key, "ARMAGEDDON DURATIONS"))
8671 {
8672 // Parse sounds
8673 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8674 {
8675 // Trim spaces
8676 trim(key)
8677 trim(value)
8678
8679 // Add to sounds array
8680 ArrayPushCell(sound_ambience8_duration, str_to_num(key))
8681 }
8682 }
8683 else if (equal(key, "APOCALYPSE ENABLE"))
8684 g_ambience_sounds[AMBIENCE_SOUNDS_APOCALYPSE] = str_to_num(value)
8685 else if (g_ambience_sounds[AMBIENCE_SOUNDS_APOCALYPSE] && equal(key, "APOCALYPSE SOUNDS"))
8686 {
8687 // Parse sounds
8688 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8689 {
8690 // Trim spaces
8691 trim(key)
8692 trim(value)
8693
8694 // Add to sounds array
8695 ArrayPushString(sound_ambience9, key)
8696 ArrayPushCell(sound_ambience9_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8697 }
8698 }
8699 else if (g_ambience_sounds[AMBIENCE_SOUNDS_APOCALYPSE] && equal(key, "APOCALYPSE DURATIONS"))
8700 {
8701 // Parse sounds
8702 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8703 {
8704 // Trim spaces
8705 trim(key)
8706 trim(value)
8707
8708 // Add to sounds array
8709 ArrayPushCell(sound_ambience9_duration, str_to_num(key))
8710 }
8711 }
8712 else if (equal(key, "NIGHTMARE ENABLE"))
8713 g_ambience_sounds[AMBIENCE_SOUNDS_NIGHTMARE] = str_to_num(value)
8714 else if (g_ambience_sounds[AMBIENCE_SOUNDS_NIGHTMARE] && equal(key, "NIGHTMARE SOUNDS"))
8715 {
8716 // Parse sounds
8717 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8718 {
8719 // Trim spaces
8720 trim(key)
8721 trim(value)
8722
8723 // Add to sounds array
8724 ArrayPushString(sound_ambience10, key)
8725 ArrayPushCell(sound_ambience10_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8726 }
8727 }
8728 else if (g_ambience_sounds[AMBIENCE_SOUNDS_NIGHTMARE] && equal(key, "NIGHTMARE DURATIONS"))
8729 {
8730 // Parse sounds
8731 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8732 {
8733 // Trim spaces
8734 trim(key)
8735 trim(value)
8736
8737 // Add to sounds array
8738 ArrayPushCell(sound_ambience10_duration, str_to_num(key))
8739 }
8740 }
8741 }
8742 case SECTION_BUY_MENU_WEAPONS:
8743 {
8744 if (equal(key, "PRIMARY"))
8745 {
8746 // Parse weapons
8747 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8748 {
8749 // Trim spaces
8750 trim(key)
8751 trim(value)
8752
8753 // Add to weapons array
8754 ArrayPushString(g_primary_items, key)
8755 ArrayPushCell(g_primary_weaponids, cs_weapon_name_to_id(key))
8756 }
8757 }
8758 else if (equal(key, "SECONDARY"))
8759 {
8760 // Parse weapons
8761 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8762 {
8763 // Trim spaces
8764 trim(key)
8765 trim(value)
8766
8767 // Add to weapons array
8768 ArrayPushString(g_secondary_items, key)
8769 ArrayPushCell(g_secondary_weaponids, cs_weapon_name_to_id(key))
8770 }
8771 }
8772 else if (equal(key, "ADDITIONAL ITEMS"))
8773 {
8774 // Parse weapons
8775 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8776 {
8777 // Trim spaces
8778 trim(key)
8779 trim(value)
8780
8781 // Add to weapons array
8782 ArrayPushString(g_additional_items, key)
8783 }
8784 }
8785 }
8786 case SECTION_EXTRA_ITEMS_WEAPONS:
8787 {
8788 if (equal(key, "NAMES"))
8789 {
8790 // Parse weapon items
8791 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8792 {
8793 // Trim spaces
8794 trim(key)
8795 trim(value)
8796
8797 // Add to weapons array
8798 ArrayPushString(g_extraweapon_names, key)
8799 }
8800 }
8801 else if (equal(key, "ITEMS"))
8802 {
8803 // Parse weapon items
8804 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8805 {
8806 // Trim spaces
8807 trim(key)
8808 trim(value)
8809
8810 // Add to weapons array
8811 ArrayPushString(g_extraweapon_items, key)
8812 }
8813 }
8814 else if (equal(key, "COSTS"))
8815 {
8816 // Parse weapon items
8817 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8818 {
8819 // Trim spaces
8820 trim(key)
8821 trim(value)
8822
8823 // Add to weapons array
8824 ArrayPushCell(g_extraweapon_costs, str_to_num(key))
8825 }
8826 }
8827 }
8828 case SECTION_HARD_CODED_ITEMS_COSTS:
8829 {
8830 if (equal(key, "NIGHT VISION"))
8831 g_extra_costs2[EXTRA_NVISION] = str_to_num(value)
8832 else if (equal(key, "ANTIDOTE"))
8833 g_extra_costs2[EXTRA_ANTIDOTE] = str_to_num(value)
8834 else if (equal(key, "ZOMBIE MADNESS"))
8835 g_extra_costs2[EXTRA_MADNESS] = str_to_num(value)
8836 else if (equal(key, "INFECTION BOMB"))
8837 g_extra_costs2[EXTRA_INFBOMB] = str_to_num(value)
8838 }
8839 case SECTION_WEATHER_EFFECTS:
8840 {
8841 if (equal(key, "RAIN"))
8842 g_ambience_rain = str_to_num(value)
8843 else if (equal(key, "SNOW"))
8844 g_ambience_snow = str_to_num(value)
8845 else if (equal(key, "FOG"))
8846 g_ambience_fog = str_to_num(value)
8847 else if (equal(key, "FOG DENSITY"))
8848 copy(g_fog_density, charsmax(g_fog_density), value)
8849 else if (equal(key, "FOG COLOR"))
8850 copy(g_fog_color, charsmax(g_fog_color), value)
8851 }
8852 case SECTION_SKY:
8853 {
8854 if (equal(key, "ENABLE"))
8855 g_sky_enable = str_to_num(value)
8856 else if (equal(key, "SKY NAMES"))
8857 {
8858 // Parse sky names
8859 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8860 {
8861 // Trim spaces
8862 trim(key)
8863 trim(value)
8864
8865 // Add to skies array
8866 ArrayPushString(g_sky_names, key)
8867
8868 // Preache custom sky files
8869 formatex(linedata, charsmax(linedata), "gfx/env/%sbk.tga", key)
8870 engfunc(EngFunc_PrecacheGeneric, linedata)
8871 formatex(linedata, charsmax(linedata), "gfx/env/%sdn.tga", key)
8872 engfunc(EngFunc_PrecacheGeneric, linedata)
8873 formatex(linedata, charsmax(linedata), "gfx/env/%sft.tga", key)
8874 engfunc(EngFunc_PrecacheGeneric, linedata)
8875 formatex(linedata, charsmax(linedata), "gfx/env/%slf.tga", key)
8876 engfunc(EngFunc_PrecacheGeneric, linedata)
8877 formatex(linedata, charsmax(linedata), "gfx/env/%srt.tga", key)
8878 engfunc(EngFunc_PrecacheGeneric, linedata)
8879 formatex(linedata, charsmax(linedata), "gfx/env/%sup.tga", key)
8880 engfunc(EngFunc_PrecacheGeneric, linedata)
8881 }
8882 }
8883 }
8884 case SECTION_LIGHTNING:
8885 {
8886 if (equal(key, "LIGHTS"))
8887 {
8888 // Parse lights
8889 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8890 {
8891 // Trim spaces
8892 trim(key)
8893 trim(value)
8894
8895 // Add to lightning array
8896 ArrayPushString(lights_thunder, key)
8897 }
8898 }
8899 }
8900 case SECTION_ZOMBIE_DECALS:
8901 {
8902 if (equal(key, "DECALS"))
8903 {
8904 // Parse decals
8905 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8906 {
8907 // Trim spaces
8908 trim(key)
8909 trim(value)
8910
8911 // Add to zombie decals array
8912 ArrayPushCell(zombie_decals, str_to_num(key))
8913 }
8914 }
8915 }
8916 case SECTION_KNOCKBACK:
8917 {
8918 // Format weapon entity name
8919 strtolower(key)
8920 format(key, charsmax(key), "weapon_%s", key)
8921
8922 // Add value to knockback power array
8923 kb_weapon_power[cs_weapon_name_to_id(key)] = str_to_float(value)
8924 }
8925 case SECTION_OBJECTIVE_ENTS:
8926 {
8927 if (equal(key, "CLASSNAMES"))
8928 {
8929 // Parse classnames
8930 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8931 {
8932 // Trim spaces
8933 trim(key)
8934 trim(value)
8935
8936 // Add to objective ents array
8937 ArrayPushString(g_objective_ents, key)
8938 }
8939 }
8940 }
8941 case SECTION_SVC_BAD:
8942 {
8943 if (equal(key, "MODELCHANGE DELAY"))
8944 g_modelchange_delay = str_to_float(value)
8945 else if (equal(key, "HANDLE MODELS ON SEPARATE ENT"))
8946 g_handle_models_on_separate_ent = str_to_num(value)
8947 else if (equal(key, "SET MODELINDEX OFFSET"))
8948 g_set_modelindex_offset = str_to_num(value)
8949 }
8950 }
8951 }
8952 if (file) fclose(file)
8953
8954 // Build zombie classes file path
8955 get_configsdir(path, charsmax(path))
8956 format(path, charsmax(path), "%s/%s", path, ZP_ZOMBIECLASSES_FILE)
8957
8958 // Parse if present
8959 if (file_exists(path))
8960 {
8961 // Open zombie classes file for reading
8962 file = fopen(path, "rt")
8963
8964 while (file && !feof(file))
8965 {
8966 // Read one line at a time
8967 fgets(file, linedata, charsmax(linedata))
8968
8969 // Replace newlines with a null character to prevent headaches
8970 replace(linedata, charsmax(linedata), "^n", "")
8971
8972 // Blank line or comment
8973 if (!linedata[0] || linedata[0] == ';') continue;
8974
8975 // New class starting
8976 if (linedata[0] == '[')
8977 {
8978 // Remove first and last characters (braces)
8979 linedata[strlen(linedata) - 1] = 0
8980 copy(linedata, charsmax(linedata), linedata[1])
8981
8982 // Store its real name for future reference
8983 ArrayPushString(g_zclass2_realname, linedata)
8984 continue;
8985 }
8986
8987 // Get key and value(s)
8988 strtok(linedata, key, charsmax(key), value, charsmax(value), '=')
8989
8990 // Trim spaces
8991 trim(key)
8992 trim(value)
8993
8994 if (equal(key, "NAME"))
8995 ArrayPushString(g_zclass2_name, value)
8996 else if (equal(key, "INFO"))
8997 ArrayPushString(g_zclass2_info, value)
8998 else if (equal(key, "MODELS"))
8999 {
9000 // Set models start index
9001 ArrayPushCell(g_zclass2_modelsstart, ArraySize(g_zclass2_playermodel))
9002
9003 // Parse class models
9004 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
9005 {
9006 // Trim spaces
9007 trim(key)
9008 trim(value)
9009
9010 // Add to class models array
9011 ArrayPushString(g_zclass2_playermodel, key)
9012 ArrayPushCell(g_zclass2_modelindex, -1)
9013 }
9014
9015 // Set models end index
9016 ArrayPushCell(g_zclass2_modelsend, ArraySize(g_zclass2_playermodel))
9017 }
9018 else if (equal(key, "CLAWMODEL"))
9019 ArrayPushString(g_zclass2_clawmodel, value)
9020 else if (equal(key, "HEALTH"))
9021 ArrayPushCell(g_zclass2_hp, str_to_num(value))
9022 else if (equal(key, "SPEED"))
9023 ArrayPushCell(g_zclass2_spd, str_to_num(value))
9024 else if (equal(key, "GRAVITY"))
9025 ArrayPushCell(g_zclass2_grav, str_to_float(value))
9026 else if (equal(key, "KNOCKBACK"))
9027 ArrayPushCell(g_zclass2_kb, str_to_float(value))
9028 }
9029 if (file) fclose(file)
9030 }
9031
9032 // Build extra items file path
9033 get_configsdir(path, charsmax(path))
9034 format(path, charsmax(path), "%s/%s", path, ZP_EXTRAITEMS_FILE)
9035
9036 // Parse if present
9037 if (file_exists(path))
9038 {
9039 // Open extra items file for reading
9040 file = fopen(path, "rt")
9041
9042 while (file && !feof(file))
9043 {
9044 // Read one line at a time
9045 fgets(file, linedata, charsmax(linedata))
9046
9047 // Replace newlines with a null character to prevent headaches
9048 replace(linedata, charsmax(linedata), "^n", "")
9049
9050 // Blank line or comment
9051 if (!linedata[0] || linedata[0] == ';') continue;
9052
9053 // New item starting
9054 if (linedata[0] == '[')
9055 {
9056 // Remove first and last characters (braces)
9057 linedata[strlen(linedata) - 1] = 0
9058 copy(linedata, charsmax(linedata), linedata[1])
9059
9060 // Store its real name for future reference
9061 ArrayPushString(g_extraitem2_realname, linedata)
9062 continue;
9063 }
9064
9065 // Get key and value(s)
9066 strtok(linedata, key, charsmax(key), value, charsmax(value), '=')
9067
9068 // Trim spaces
9069 trim(key)
9070 trim(value)
9071
9072 if (equal(key, "NAME"))
9073 ArrayPushString(g_extraitem2_name, value)
9074 else if (equal(key, "COST"))
9075 ArrayPushCell(g_extraitem2_cost, str_to_num(value))
9076 else if (equal(key, "TEAMS"))
9077 {
9078 // Clear teams bitsum
9079 teams = 0
9080
9081 // Parse teams
9082 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
9083 {
9084 // Trim spaces
9085 trim(key)
9086 trim(value)
9087
9088 if (equal(key, ZP_TEAM_NAMES[ZP_TEAM_ZOMBIE]))
9089 teams |= ZP_TEAM_ZOMBIE
9090 else if (equal(key, ZP_TEAM_NAMES[ZP_TEAM_HUMAN]))
9091 teams |= ZP_TEAM_HUMAN
9092 else if (equal(key, ZP_TEAM_NAMES[ZP_TEAM_NEMESIS]))
9093 teams |= ZP_TEAM_NEMESIS
9094 else if (equal(key, ZP_TEAM_NAMES[ZP_TEAM_ASSASSIN]))
9095 teams |= ZP_TEAM_ASSASSIN
9096 else if (equal(key, ZP_TEAM_NAMES[ZP_TEAM_SURVIVOR]))
9097 teams |= ZP_TEAM_SURVIVOR
9098 else if (equal(key, ZP_TEAM_NAMES[ZP_TEAM_SNIPER]))
9099 teams |= ZP_TEAM_SNIPER
9100 }
9101
9102 // Add to teams array
9103 ArrayPushCell(g_extraitem2_team, teams)
9104 }
9105 }
9106 if (file) fclose(file)
9107 }
9108}
9109
9110save_customization()
9111{
9112 new i, k, buffer[512]
9113
9114 // Build zombie classes file path
9115 new path[64]
9116 get_configsdir(path, charsmax(path))
9117 format(path, charsmax(path), "%s/%s", path, ZP_ZOMBIECLASSES_FILE)
9118
9119 // Open zombie classes file for appending data
9120 new file = fopen(path, "at"), size = ArraySize(g_zclass_name)
9121
9122 // Add any new zombie classes data at the end if needed
9123 for (i = 0; i < size; i++)
9124 {
9125 if (ArrayGetCell(g_zclass_new, i))
9126 {
9127 // Add real name
9128 ArrayGetString(g_zclass_name, i, buffer, charsmax(buffer))
9129 format(buffer, charsmax(buffer), "^n[%s]", buffer)
9130 fputs(file, buffer)
9131
9132 // Add caption
9133 ArrayGetString(g_zclass_name, i, buffer, charsmax(buffer))
9134 format(buffer, charsmax(buffer), "^nNAME = %s", buffer)
9135 fputs(file, buffer)
9136
9137 // Add info
9138 ArrayGetString(g_zclass_info, i, buffer, charsmax(buffer))
9139 format(buffer, charsmax(buffer), "^nINFO = %s", buffer)
9140 fputs(file, buffer)
9141
9142 // Add models
9143 for (k = ArrayGetCell(g_zclass_modelsstart, i); k < ArrayGetCell(g_zclass_modelsend, i); k++)
9144 {
9145 if (k == ArrayGetCell(g_zclass_modelsstart, i))
9146 {
9147 // First model, overwrite buffer
9148 ArrayGetString(g_zclass_playermodel, k, buffer, charsmax(buffer))
9149 }
9150 else
9151 {
9152 // Successive models, append to buffer
9153 ArrayGetString(g_zclass_playermodel, k, path, charsmax(path))
9154 format(buffer, charsmax(buffer), "%s , %s", buffer, path)
9155 }
9156 }
9157 format(buffer, charsmax(buffer), "^nMODELS = %s", buffer)
9158 fputs(file, buffer)
9159
9160 // Add clawmodel
9161 ArrayGetString(g_zclass_clawmodel, i, buffer, charsmax(buffer))
9162 format(buffer, charsmax(buffer), "^nCLAWMODEL = %s", buffer)
9163 fputs(file, buffer)
9164
9165 // Add health
9166 formatex(buffer, charsmax(buffer), "^nHEALTH = %d", ArrayGetCell(g_zclass_hp, i))
9167 fputs(file, buffer)
9168
9169 // Add speed
9170 formatex(buffer, charsmax(buffer), "^nSPEED = %d", ArrayGetCell(g_zclass_spd, i))
9171 fputs(file, buffer)
9172
9173 // Add gravity
9174 formatex(buffer, charsmax(buffer), "^nGRAVITY = %.2f", Float:ArrayGetCell(g_zclass_grav, i))
9175 fputs(file, buffer)
9176
9177 // Add knockback
9178 formatex(buffer, charsmax(buffer), "^nKNOCKBACK = %.2f^n", Float:ArrayGetCell(g_zclass_kb, i))
9179 fputs(file, buffer)
9180 }
9181 }
9182 fclose(file)
9183
9184 // Build extra items file path
9185 get_configsdir(path, charsmax(path))
9186 format(path, charsmax(path), "%s/%s", path, ZP_EXTRAITEMS_FILE)
9187
9188 // Open extra items file for appending data
9189 file = fopen(path, "at")
9190 size = ArraySize(g_extraitem_name)
9191
9192 // Add any new extra items data at the end if needed
9193 for (i = EXTRAS_CUSTOM_STARTID; i < size; i++)
9194 {
9195 if (ArrayGetCell(g_extraitem_new, i))
9196 {
9197 // Add real name
9198 ArrayGetString(g_extraitem_name, i, buffer, charsmax(buffer))
9199 format(buffer, charsmax(buffer), "^n[%s]", buffer)
9200 fputs(file, buffer)
9201
9202 // Add caption
9203 ArrayGetString(g_extraitem_name, i, buffer, charsmax(buffer))
9204 format(buffer, charsmax(buffer), "^nNAME = %s", buffer)
9205 fputs(file, buffer)
9206
9207 // Add cost
9208 formatex(buffer, charsmax(buffer), "^nCOST = %d", ArrayGetCell(g_extraitem_cost, i))
9209 fputs(file, buffer)
9210
9211 // Add team
9212 formatex(buffer, charsmax(buffer), "^nTEAMS = %s^n", ZP_TEAM_NAMES[ArrayGetCell(g_extraitem_team, i)])
9213 fputs(file, buffer)
9214 }
9215 }
9216 fclose(file)
9217
9218 // Free arrays containing class/item overrides
9219 ArrayDestroy(g_zclass2_realname)
9220 ArrayDestroy(g_zclass2_name)
9221 ArrayDestroy(g_zclass2_info)
9222 ArrayDestroy(g_zclass2_modelsstart)
9223 ArrayDestroy(g_zclass2_modelsend)
9224 ArrayDestroy(g_zclass2_playermodel)
9225 ArrayDestroy(g_zclass2_modelindex)
9226 ArrayDestroy(g_zclass2_clawmodel)
9227 ArrayDestroy(g_zclass2_hp)
9228 ArrayDestroy(g_zclass2_spd)
9229 ArrayDestroy(g_zclass2_grav)
9230 ArrayDestroy(g_zclass2_kb)
9231 ArrayDestroy(g_zclass_new)
9232 ArrayDestroy(g_extraitem2_realname)
9233 ArrayDestroy(g_extraitem2_name)
9234 ArrayDestroy(g_extraitem2_cost)
9235 ArrayDestroy(g_extraitem2_team)
9236 ArrayDestroy(g_extraitem_new)
9237}
9238
9239// Register Ham Forwards for CZ bots
9240public register_ham_czbots(id)
9241{
9242 // Make sure it's a CZ bot and it's still connected
9243 if (g_hamczbots || !g_isconnected[id] || !get_pcvar_num(cvar_botquota))
9244 return;
9245
9246 RegisterHamFromEntity(Ham_Spawn, id, "fw_PlayerSpawn_Post", 1)
9247 RegisterHamFromEntity(Ham_Killed, id, "fw_PlayerKilled")
9248 RegisterHamFromEntity(Ham_Killed, id, "fw_PlayerKilled_Post", 1)
9249 RegisterHamFromEntity(Ham_TakeDamage, id, "fw_TakeDamage")
9250 RegisterHamFromEntity(Ham_TakeDamage, id, "fw_TakeDamage_Post", 1)
9251 RegisterHamFromEntity(Ham_TraceAttack, id, "fw_TraceAttack")
9252 RegisterHamFromEntity(Ham_Player_ResetMaxSpeed, id, "fw_ResetMaxSpeed_Post", 1)
9253
9254 // Ham forwards for CZ bots succesfully registered
9255 g_hamczbots = true
9256
9257 // If the bot has already spawned, call the forward manually for him
9258 if (is_user_alive(id)) fw_PlayerSpawn_Post(id)
9259}
9260
9261// Disable minmodels task
9262public disable_minmodels(id)
9263{
9264 if (!g_isconnected[id]) return;
9265 client_cmd(id, "cl_minmodels 0")
9266}
9267
9268// Bots automatically buy extra items
9269public bot_buy_extras(taskid)
9270{
9271 // Nemesis or Survivor bots have nothing to buy by default
9272 if (!g_isalive[ID_SPAWN] || g_survivor[ID_SPAWN] || g_sniper[ID_SPAWN] || g_nemesis[ID_SPAWN] || g_assassin[ID_SPAWN])
9273 return;
9274
9275 if (!g_zombie[ID_SPAWN]) // human bots
9276 {
9277 // Attempt to buy Night Vision
9278 buy_extra_item(ID_SPAWN, EXTRA_NVISION)
9279
9280 // Attempt to buy a weapon
9281 buy_extra_item(ID_SPAWN, random_num(EXTRA_WEAPONS_STARTID, EXTRAS_CUSTOM_STARTID-1))
9282 }
9283 else // zombie bots
9284 {
9285 // Attempt to buy an Antidote
9286 buy_extra_item(ID_SPAWN, EXTRA_ANTIDOTE)
9287 }
9288}
9289
9290// Refill BP Ammo Task
9291public refill_bpammo(const args[], id)
9292{
9293 // Player died or turned into a zombie
9294 if (!g_isalive[id] || g_zombie[id])
9295 return;
9296
9297 set_msg_block(g_msgAmmoPickup, BLOCK_ONCE)
9298 ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[REFILL_WEAPONID], AMMOTYPE[REFILL_WEAPONID], MAXBPAMMO[REFILL_WEAPONID])
9299}
9300
9301// Balance Teams Task
9302balance_teams()
9303{
9304 // Get amount of users playing
9305 static iPlayersnum
9306 iPlayersnum = fnGetPlaying()
9307
9308 // No players, don't bother
9309 if (iPlayersnum < 1) return;
9310
9311 // Split players evenly
9312 static iTerrors, iMaxTerrors, id, team[33]
9313 iMaxTerrors = iPlayersnum/2
9314 iTerrors = 0
9315
9316 // First, set everyone to CT
9317 for (id = 1; id <= g_maxplayers; id++)
9318 {
9319 // Skip if not connected
9320 if (!g_isconnected[id])
9321 continue;
9322
9323 team[id] = fm_cs_get_user_team(id)
9324
9325 // Skip if not playing
9326 if (team[id] == FM_CS_TEAM_SPECTATOR || team[id] == FM_CS_TEAM_UNASSIGNED)
9327 continue;
9328
9329 // Set team
9330 remove_task(id+TASK_TEAM)
9331 fm_cs_set_user_team(id, FM_CS_TEAM_CT)
9332 team[id] = FM_CS_TEAM_CT
9333 }
9334
9335 // Then randomly set half of the players to Terrorists
9336 while (iTerrors < iMaxTerrors)
9337 {
9338 // Keep looping through all players
9339 if (++id > g_maxplayers) id = 1
9340
9341 // Skip if not connected
9342 if (!g_isconnected[id])
9343 continue;
9344
9345 // Skip if not playing or already a Terrorist
9346 if (team[id] != FM_CS_TEAM_CT)
9347 continue;
9348
9349 // Random chance
9350 if (random_num(0, 1))
9351 {
9352 fm_cs_set_user_team(id, FM_CS_TEAM_T)
9353 team[id] = FM_CS_TEAM_T
9354 iTerrors++
9355 }
9356 }
9357}
9358
9359// Welcome Message Task
9360public welcome_msg()
9361{
9362 // Show mod info
9363 zp_colored_print(0, "^x01**** ^x04%s^x01 ****", g_modname)
9364 zp_colored_print(0, "^x04[ZP]^x01 %L", LANG_PLAYER, "NOTICE_INFO1")
9365 if (!get_pcvar_num(cvar_infammo)) zp_colored_print(0, "^x04[ZP]^x01 %L", LANG_PLAYER, "NOTICE_INFO2")
9366
9367 // Show T-virus HUD notice
9368 set_hudmessage(0, 125, 200, HUD_EVENT_X, HUD_EVENT_Y, 0, 0.0, 3.0, 2.0, 1.0, -1)
9369 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_VIRUS_FREE")
9370}
9371
9372// Respawn Player Task (deathmatch)
9373public respawn_player_task(taskid)
9374{
9375 // Already alive or round ended
9376 if (g_isalive[ID_SPAWN] || g_endround)
9377 return;
9378
9379 // Get player's team
9380 static team
9381 team = fm_cs_get_user_team(ID_SPAWN)
9382
9383 // Player moved to spectators
9384 if (team == FM_CS_TEAM_SPECTATOR || team == FM_CS_TEAM_UNASSIGNED)
9385 return;
9386
9387 // Respawn player automatically if allowed on current round
9388 if ((!g_survround || get_pcvar_num(cvar_allowrespawnsurv))
9389 && (!g_sniround || get_pcvar_num(cvar_allowrespawnsni))
9390 && (!g_swarmround || get_pcvar_num(cvar_allowrespawnswarm))
9391 && (!g_nemround || get_pcvar_num(cvar_allowrespawnnem))
9392 && (!g_assaround || get_pcvar_num(cvar_allowrespawnassa))
9393 && (!g_plagueround || get_pcvar_num(cvar_allowrespawnplague))
9394 && (!g_armageround || get_pcvar_num(cvar_allowrespawnarmage))
9395 && (!g_apocround || get_pcvar_num(cvar_allowrespawnapoc))
9396 && (!g_nightround || get_pcvar_num(cvar_allowrespawnnight)))
9397 {
9398
9399 // Infection rounds = none of the above
9400 if (!get_pcvar_num(cvar_allowrespawninfection) && !g_survround && !g_sniround && !g_nemround && !g_assaround && !g_swarmround && !g_plagueround && !g_armageround && !g_apocround && !g_nightround)
9401 return;
9402
9403 // Respawn if only the last human is left? (ignore this setting on survivor rounds)
9404 if (!g_survround && !g_sniround && !get_pcvar_num(cvar_respawnafterlast) && fnGetHumans() <= 1)
9405 return;
9406
9407 // Respawn as zombie?
9408 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))
9409 g_respawn_as_zombie[ID_SPAWN] = true
9410
9411 // Override respawn as zombie setting on nemesis and survivor rounds
9412 if (g_survround || g_sniround) g_respawn_as_zombie[ID_SPAWN] = true
9413 else if (g_nemround || g_assaround) g_respawn_as_zombie[ID_SPAWN] = false
9414
9415 respawn_player_manually(ID_SPAWN)
9416 }
9417}
9418
9419// Respawn Player Check Task (if killed by worldspawn)
9420public respawn_player_check_task(taskid)
9421{
9422 // Successfully spawned or round ended
9423 if (g_isalive[ID_SPAWN] || g_endround)
9424 return;
9425
9426 // Get player's team
9427 static team
9428 team = fm_cs_get_user_team(ID_SPAWN)
9429
9430 // Player moved to spectators
9431 if (team == FM_CS_TEAM_SPECTATOR || team == FM_CS_TEAM_UNASSIGNED)
9432 return;
9433
9434 // If player was being spawned as a zombie, set the flag again
9435 if (g_zombie[ID_SPAWN]) g_respawn_as_zombie[ID_SPAWN] = true
9436 else g_respawn_as_zombie[ID_SPAWN] = false
9437
9438 respawn_player_manually(ID_SPAWN)
9439}
9440
9441// Respawn Player Manually (called after respawn checks are done)
9442respawn_player_manually(id)
9443{
9444 // Set proper team before respawning, so that the TeamInfo message that's sent doesn't confuse PODBots
9445 if (g_respawn_as_zombie[id])
9446 fm_cs_set_user_team(id, FM_CS_TEAM_T)
9447 else
9448 fm_cs_set_user_team(id, FM_CS_TEAM_CT)
9449
9450 // Respawning a player has never been so easy
9451 ExecuteHamB(Ham_CS_RoundRespawn, id)
9452}
9453
9454// Check Round Task -check that we still have both zombies and humans on a round-
9455check_round(leaving_player)
9456{
9457 // Round ended or make_a_zombie task still active
9458 if (g_endround || task_exists(TASK_MAKEZOMBIE))
9459 return;
9460
9461 // Get alive players count
9462 static iPlayersnum, id
9463 iPlayersnum = fnGetAlive()
9464
9465 // Last alive player, don't bother
9466 if (iPlayersnum < 2)
9467 return;
9468
9469 // Last zombie disconnecting
9470 if (g_zombie[leaving_player] && fnGetZombies() == 1)
9471 {
9472 // Only one CT left, don't bother
9473 if (fnGetHumans() == 1 && fnGetCTs() == 1)
9474 return;
9475
9476 // Pick a random one to take his place
9477 while ((id = fnGetRandomAlive(random_num(1, iPlayersnum))) == leaving_player ) { /* keep looping */ }
9478
9479 // Show last zombie left notice
9480 zp_colored_print(0, "^x04[ZP]^x01 %L", LANG_PLAYER, "LAST_ZOMBIE_LEFT", g_playername[id])
9481
9482 // Set player leaving flag
9483 g_lastplayerleaving = true
9484
9485 // Turn into a Nemesis or just a zombie?
9486 if (g_nemesis[leaving_player])
9487 zombieme(id, 0, 1, 0, 0, 0)
9488 else if (g_assassin[leaving_player])
9489 zombieme(id, 0, 0, 1, 0, 0)
9490 else
9491 zombieme(id, 0, 0, 0, 0, 0)
9492
9493 // Remove player leaving flag
9494 g_lastplayerleaving = false
9495
9496 // If Nemesis, set chosen player's health to that of the one who's leaving
9497 if (get_pcvar_num(cvar_keephealthondisconnect) && g_nemesis[leaving_player])
9498 fm_set_user_health(id, pev(leaving_player, pev_health))
9499
9500 // If Assassin, set chosen player's health to that of the one who's leaving
9501 if (get_pcvar_num(cvar_keephealthondisconnect) && g_assassin[leaving_player])
9502 fm_set_user_health(id, pev(leaving_player, pev_health))
9503 }
9504
9505 // Last human disconnecting
9506 else if (!g_zombie[leaving_player] && fnGetHumans() == 1)
9507 {
9508 // Only one T left, don't bother
9509 if (fnGetZombies() == 1 && fnGetTs() == 1)
9510 return;
9511
9512 // Pick a random one to take his place
9513 while ((id = fnGetRandomAlive(random_num(1, iPlayersnum))) == leaving_player ) { /* keep looping */ }
9514
9515 // Show last human left notice
9516 zp_colored_print(0, "^x04[ZP]^x01 %L", LANG_PLAYER, "LAST_HUMAN_LEFT", g_playername[id])
9517
9518 // Set player leaving flag
9519 g_lastplayerleaving = true
9520
9521 // Turn into a Survivor or just a human?
9522 if (g_survivor[leaving_player])
9523 humanme(id, 1, 0, 0)
9524 else if (g_sniper[leaving_player])
9525 humanme(id, 0, 1, 0)
9526 else
9527 humanme(id, 0, 0, 0)
9528
9529 // Remove player leaving flag
9530 g_lastplayerleaving = false
9531
9532 // If Survivor, set chosen player's health to that of the one who's leaving
9533 if (get_pcvar_num(cvar_keephealthondisconnect) && g_survivor[leaving_player])
9534 fm_set_user_health(id, pev(leaving_player, pev_health))
9535
9536 // If Sniper, set chosen player's health to that of the one who's leaving
9537 if (get_pcvar_num(cvar_keephealthondisconnect) && g_sniper[leaving_player])
9538 fm_set_user_health(id, pev(leaving_player, pev_health))
9539 }
9540}
9541
9542// Lighting Effects Task
9543public lighting_effects()
9544{
9545 // Cache some CVAR values at every 5 secs
9546 cache_cvars()
9547
9548 // Get lighting style
9549 static lighting[2]
9550 get_pcvar_string(cvar_lighting, lighting, charsmax(lighting))
9551 strtolower(lighting)
9552
9553 // Lighting disabled? ["0"]
9554 if (lighting[0] == '0')
9555 return;
9556
9557 // Darkest light settings?
9558 if (lighting[0] >= 'a' && lighting[0] <= 'd')
9559 {
9560 static thunderclap_in_progress, Float:thunder
9561 thunderclap_in_progress = task_exists(TASK_THUNDER)
9562 thunder = get_pcvar_float(cvar_thunder)
9563
9564 // Set thunderclap tasks if not existant
9565 if (thunder > 0.0 && !task_exists(TASK_THUNDER_PRE) && !thunderclap_in_progress)
9566 {
9567 g_lights_i = 0
9568 ArrayGetString(lights_thunder, random_num(0, ArraySize(lights_thunder) - 1), g_lights_cycle, charsmax(g_lights_cycle))
9569 g_lights_cycle_len = strlen(g_lights_cycle)
9570 set_task(thunder, "thunderclap", TASK_THUNDER_PRE)
9571 }
9572
9573 // Set lighting only when no thunderclaps are going on
9574 if (!thunderclap_in_progress) engfunc(EngFunc_LightStyle, 0, g_assaround ? "a" : lighting) // no lighting in assassin round
9575 }
9576 else
9577 {
9578 // Remove thunderclap tasks
9579 remove_task(TASK_THUNDER_PRE)
9580 remove_task(TASK_THUNDER)
9581
9582 // Set lighting
9583 engfunc(EngFunc_LightStyle, 0, g_assaround ? "a" : lighting) // no lighting in assassin round
9584 }
9585}
9586
9587// Thunderclap task
9588public thunderclap()
9589{
9590 // Play thunder sound
9591 if (g_lights_i == 0)
9592 {
9593 static sound[64]
9594 ArrayGetString(sound_thunder, random_num(0, ArraySize(sound_thunder) - 1), sound, charsmax(sound))
9595 PlaySound(sound)
9596 }
9597
9598 // Set lighting
9599 static light[2]
9600 light[0] = g_lights_cycle[g_lights_i]
9601 engfunc(EngFunc_LightStyle, 0, light)
9602
9603 g_lights_i++
9604
9605 // Lighting cycle end?
9606 if (g_lights_i >= g_lights_cycle_len)
9607 {
9608 remove_task(TASK_THUNDER)
9609 lighting_effects()
9610 }
9611 // Lighting cycle start?
9612 else if (!task_exists(TASK_THUNDER))
9613 set_task(0.1, "thunderclap", TASK_THUNDER, _, _, "b")
9614}
9615
9616// Ambience Sound Effects Task
9617public ambience_sound_effects(taskid)
9618{
9619 // Play a random sound depending on the round
9620 static sound[64], iRand, duration
9621
9622 if (g_nemround) // Nemesis Mode
9623 {
9624 iRand = random_num(0, ArraySize(sound_ambience2) - 1)
9625 ArrayGetString(sound_ambience2, iRand, sound, charsmax(sound))
9626 duration = ArrayGetCell(sound_ambience2_duration, iRand)
9627 }
9628 if (g_assaround) // Assassin Mode
9629 {
9630 iRand = random_num(0, ArraySize(sound_ambience6) - 1)
9631 ArrayGetString(sound_ambience6, iRand, sound, charsmax(sound))
9632 duration = ArrayGetCell(sound_ambience6_duration, iRand)
9633 }
9634 else if (g_survround) // Survivor Mode
9635 {
9636 iRand = random_num(0, ArraySize(sound_ambience3) - 1)
9637 ArrayGetString(sound_ambience3, iRand, sound, charsmax(sound))
9638 duration = ArrayGetCell(sound_ambience3_duration, iRand)
9639 }
9640 else if (g_sniround) // Sniper Mode
9641 {
9642 iRand = random_num(0, ArraySize(sound_ambience7) - 1)
9643 ArrayGetString(sound_ambience7, iRand, sound, charsmax(sound))
9644 duration = ArrayGetCell(sound_ambience7_duration, iRand)
9645 }
9646 else if (g_swarmround) // Swarm Mode
9647 {
9648 iRand = random_num(0, ArraySize(sound_ambience4) - 1)
9649 ArrayGetString(sound_ambience4, iRand, sound, charsmax(sound))
9650 duration = ArrayGetCell(sound_ambience4_duration, iRand)
9651 }
9652 else if (g_plagueround) // Plague Mode
9653 {
9654 iRand = random_num(0, ArraySize(sound_ambience5) - 1)
9655 ArrayGetString(sound_ambience5, iRand, sound, charsmax(sound))
9656 duration = ArrayGetCell(sound_ambience5_duration, iRand)
9657 }
9658 else if (g_armageround) // Armageddon Mode
9659 {
9660 iRand = random_num(0, ArraySize(sound_ambience8) - 1)
9661 ArrayGetString(sound_ambience8, iRand, sound, charsmax(sound))
9662 duration = ArrayGetCell(sound_ambience8_duration, iRand)
9663 }
9664 else if (g_apocround) // Apocalypse Mode
9665 {
9666 iRand = random_num(0, ArraySize(sound_ambience9) - 1)
9667 ArrayGetString(sound_ambience9, iRand, sound, charsmax(sound))
9668 duration = ArrayGetCell(sound_ambience9_duration, iRand)
9669 }
9670 else if (g_nightround) // Nightmare Mode
9671 {
9672 iRand = random_num(0, ArraySize(sound_ambience10) - 1)
9673 ArrayGetString(sound_ambience10, iRand, sound, charsmax(sound))
9674 duration = ArrayGetCell(sound_ambience10_duration, iRand)
9675 }
9676 else // Infection Mode
9677 {
9678 iRand = random_num(0, ArraySize(sound_ambience1) - 1)
9679 ArrayGetString(sound_ambience1, iRand, sound, charsmax(sound))
9680 duration = ArrayGetCell(sound_ambience1_duration, iRand)
9681 }
9682
9683 // Play it on clients
9684 PlaySound(sound)
9685
9686 // Set the task for when the sound is done playing
9687 set_task(float(duration), "ambience_sound_effects", TASK_AMBIENCESOUNDS)
9688}
9689
9690// Ambience Sounds Stop Task
9691ambience_sound_stop()
9692{
9693 client_cmd(0, "mp3 stop; stopsound")
9694}
9695
9696// Flashlight Charge Task
9697public flashlight_charge(taskid)
9698{
9699 // Drain or charge?
9700 if (g_flashlight[ID_CHARGE])
9701 g_flashbattery[ID_CHARGE] -= get_pcvar_num(cvar_flashdrain)
9702 else
9703 g_flashbattery[ID_CHARGE] += get_pcvar_num(cvar_flashcharge)
9704
9705 // Battery fully charged
9706 if (g_flashbattery[ID_CHARGE] >= 100)
9707 {
9708 // Don't exceed 100%
9709 g_flashbattery[ID_CHARGE] = 100
9710
9711 // Update flashlight battery on HUD
9712 message_begin(MSG_ONE, g_msgFlashBat, _, ID_CHARGE)
9713 write_byte(100) // battery
9714 message_end()
9715
9716 // Task not needed anymore
9717 remove_task(taskid);
9718 return;
9719 }
9720
9721 // Battery depleted
9722 if (g_flashbattery[ID_CHARGE] <= 0)
9723 {
9724 // Turn it off
9725 g_flashlight[ID_CHARGE] = false
9726 g_flashbattery[ID_CHARGE] = 0
9727
9728 // Play flashlight toggle sound
9729 emit_sound(ID_CHARGE, CHAN_ITEM, sound_flashlight, 1.0, ATTN_NORM, 0, PITCH_NORM)
9730
9731 // Update flashlight status on HUD
9732 message_begin(MSG_ONE, g_msgFlashlight, _, ID_CHARGE)
9733 write_byte(0) // toggle
9734 write_byte(0) // battery
9735 message_end()
9736
9737 // Remove flashlight task for this player
9738 remove_task(ID_CHARGE+TASK_FLASH)
9739 }
9740 else
9741 {
9742 // Update flashlight battery on HUD
9743 message_begin(MSG_ONE_UNRELIABLE, g_msgFlashBat, _, ID_CHARGE)
9744 write_byte(g_flashbattery[ID_CHARGE]) // battery
9745 message_end()
9746 }
9747}
9748
9749// Remove Spawn Protection Task
9750public remove_spawn_protection(taskid)
9751{
9752 // Not alive
9753 if (!g_isalive[ID_SPAWN])
9754 return;
9755
9756 // Remove spawn protection
9757 g_nodamage[ID_SPAWN] = false
9758 set_pev(ID_SPAWN, pev_effects, pev(ID_SPAWN, pev_effects) & ~EF_NODRAW)
9759}
9760
9761// Hide Player's Money Task
9762public task_hide_money(taskid)
9763{
9764 // Not alive
9765 if (!g_isalive[ID_SPAWN])
9766 return;
9767
9768 // Hide money
9769 message_begin(MSG_ONE, g_msgHideWeapon, _, ID_SPAWN)
9770 write_byte(HIDE_MONEY) // what to hide bitsum
9771 message_end()
9772
9773 // Hide the HL crosshair that's drawn
9774 message_begin(MSG_ONE, g_msgCrosshair, _, ID_SPAWN)
9775 write_byte(0) // toggle
9776 message_end()
9777}
9778
9779// Turn Off Flashlight and Restore Batteries
9780turn_off_flashlight(id)
9781{
9782 // Restore batteries for the next use
9783 fm_cs_set_user_batteries(id, 100)
9784
9785 // Check if flashlight is on
9786 if (pev(id, pev_effects) & EF_DIMLIGHT)
9787 {
9788 // Turn it off
9789 set_pev(id, pev_impulse, IMPULSE_FLASHLIGHT)
9790 }
9791 else
9792 {
9793 // Clear any stored flashlight impulse (bugfix)
9794 set_pev(id, pev_impulse, 0)
9795 }
9796
9797 // Turn off custom flashlight
9798 if (g_cached_customflash)
9799 {
9800 // Turn it off
9801 g_flashlight[id] = false
9802 g_flashbattery[id] = 100
9803
9804 // Update flashlight HUD
9805 message_begin(MSG_ONE, g_msgFlashlight, _, id)
9806 write_byte(0) // toggle
9807 write_byte(100) // battery
9808 message_end()
9809
9810 // Remove previous tasks
9811 remove_task(id+TASK_CHARGE)
9812 remove_task(id+TASK_FLASH)
9813 }
9814}
9815
9816// Infection Bomb Explosion
9817infection_explode(ent)
9818{
9819 // Round ended (bugfix)
9820 if (g_endround) return;
9821
9822 // Get origin
9823 static Float:originF[3]
9824 pev(ent, pev_origin, originF)
9825
9826 // Make the explosion
9827 create_blast(originF)
9828
9829 // Infection nade explode sound
9830 static sound[64]
9831 ArrayGetString(grenade_infect, random_num(0, ArraySize(grenade_infect) - 1), sound, charsmax(sound))
9832 emit_sound(ent, CHAN_WEAPON, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
9833
9834 // Get attacker
9835 static attacker
9836 attacker = pev(ent, pev_owner)
9837
9838 // Infection bomb owner disconnected? (bugfix)
9839 if (!is_user_valid_connected(attacker))
9840 {
9841 // Get rid of the grenade
9842 engfunc(EngFunc_RemoveEntity, ent)
9843 return;
9844 }
9845
9846 // Collisions
9847 static victim
9848 victim = -1
9849
9850 while ((victim = engfunc(EngFunc_FindEntityInSphere, victim, originF, NADE_EXPLOSION_RADIUS)) != 0)
9851 {
9852 // Only effect alive non-spawnprotected humans
9853 if (!is_user_valid_alive(victim) || g_zombie[victim] || g_nodamage[victim])
9854 continue;
9855
9856 // Last human is killed
9857 if (fnGetHumans() == 1)
9858 {
9859 ExecuteHamB(Ham_Killed, victim, attacker, 0)
9860 continue;
9861 }
9862
9863 // Infected victim's sound
9864 ArrayGetString(grenade_infect_player, random_num(0, ArraySize(grenade_infect_player) - 1), sound, charsmax(sound))
9865 emit_sound(victim, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
9866
9867 // Turn into zombie
9868 zombieme(victim, attacker, 0, 0, 1, 1)
9869 }
9870
9871 // Get rid of the grenade
9872 engfunc(EngFunc_RemoveEntity, ent)
9873}
9874
9875// Fire Grenade Explosion
9876fire_explode(ent)
9877{
9878 // Get origin
9879 static Float:originF[3]
9880 pev(ent, pev_origin, originF)
9881
9882 // Make the explosion
9883 create_blast2(originF)
9884
9885 // Fire nade explode sound
9886 static sound[64]
9887 ArrayGetString(grenade_fire, random_num(0, ArraySize(grenade_fire) - 1), sound, charsmax(sound))
9888 emit_sound(ent, CHAN_WEAPON, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
9889
9890 // Collisions
9891 static victim
9892 victim = -1
9893
9894 while ((victim = engfunc(EngFunc_FindEntityInSphere, victim, originF, NADE_EXPLOSION_RADIUS)) != 0)
9895 {
9896 // Only effect alive zombies
9897 if (!is_user_valid_alive(victim) || !g_zombie[victim] || g_nodamage[victim])
9898 continue;
9899
9900 // Heat icon?
9901 if (get_pcvar_num(cvar_hudicons))
9902 {
9903 message_begin(MSG_ONE_UNRELIABLE, g_msgDamage, _, victim)
9904 write_byte(0) // damage save
9905 write_byte(0) // damage take
9906 write_long(DMG_BURN) // damage type
9907 write_coord(0) // x
9908 write_coord(0) // y
9909 write_coord(0) // z
9910 message_end()
9911 }
9912
9913 if (g_nemesis[victim] || g_assassin[victim]) // fire duration (nemesis is fire resistant)
9914 g_burning_duration[victim] += get_pcvar_num(cvar_fireduration)
9915 else
9916 g_burning_duration[victim] += get_pcvar_num(cvar_fireduration) * 5
9917
9918 // Set burning task on victim if not present
9919 if (!task_exists(victim+TASK_BURN))
9920 set_task(0.2, "burning_flame", victim+TASK_BURN, _, _, "b")
9921 }
9922
9923 // Get rid of the grenade
9924 engfunc(EngFunc_RemoveEntity, ent)
9925}
9926
9927// Frost Grenade Explosion
9928frost_explode(ent)
9929{
9930 // Get origin
9931 static Float:originF[3]
9932 pev(ent, pev_origin, originF)
9933
9934 // Make the explosion
9935 create_blast3(originF)
9936
9937 // Frost nade explode sound
9938 static sound[64]
9939 ArrayGetString(grenade_frost, random_num(0, ArraySize(grenade_frost) - 1), sound, charsmax(sound))
9940 emit_sound(ent, CHAN_WEAPON, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
9941
9942 // Collisions
9943 static victim
9944 victim = -1
9945
9946 while ((victim = engfunc(EngFunc_FindEntityInSphere, victim, originF, NADE_EXPLOSION_RADIUS)) != 0)
9947 {
9948 // Only effect alive unfrozen zombies
9949 if (!is_user_valid_alive(victim) || !g_zombie[victim] || g_frozen[victim] || g_nodamage[victim])
9950 continue;
9951
9952 // Nemesis shouldn't be frozen
9953 if (g_nemesis[victim] || g_assassin[victim])
9954 {
9955 // Get player's origin
9956 static origin2[3]
9957 get_user_origin(victim, origin2)
9958
9959 // Broken glass sound
9960 ArrayGetString(grenade_frost_break, random_num(0, ArraySize(grenade_frost_break) - 1), sound, charsmax(sound))
9961 emit_sound(victim, CHAN_BODY, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
9962
9963 // Glass shatter
9964 message_begin(MSG_PVS, SVC_TEMPENTITY, origin2)
9965 write_byte(TE_BREAKMODEL) // TE id
9966 write_coord(origin2[0]) // x
9967 write_coord(origin2[1]) // y
9968 write_coord(origin2[2]+24) // z
9969 write_coord(16) // size x
9970 write_coord(16) // size y
9971 write_coord(16) // size z
9972 write_coord(random_num(-50, 50)) // velocity x
9973 write_coord(random_num(-50, 50)) // velocity y
9974 write_coord(25) // velocity z
9975 write_byte(10) // random velocity
9976 write_short(g_glassSpr) // model
9977 write_byte(10) // count
9978 write_byte(25) // life
9979 write_byte(BREAK_GLASS) // flags
9980 message_end()
9981
9982 continue;
9983 }
9984
9985 // Freeze icon?
9986 if (get_pcvar_num(cvar_hudicons))
9987 {
9988 message_begin(MSG_ONE_UNRELIABLE, g_msgDamage, _, victim)
9989 write_byte(0) // damage save
9990 write_byte(0) // damage take
9991 write_long(DMG_DROWN) // damage type - DMG_FREEZE
9992 write_coord(0) // x
9993 write_coord(0) // y
9994 write_coord(0) // z
9995 message_end()
9996 }
9997
9998 // Light blue glow while frozen
9999 if (g_handle_models_on_separate_ent)
10000 fm_set_rendering(g_ent_playermodel[victim], kRenderFxGlowShell, 0, 100, 200, kRenderNormal, 25)
10001 else
10002 fm_set_rendering(victim, kRenderFxGlowShell, 0, 100, 200, kRenderNormal, 25)
10003
10004 // Freeze sound
10005 ArrayGetString(grenade_frost_player, random_num(0, ArraySize(grenade_frost_player) - 1), sound, charsmax(sound))
10006 emit_sound(victim, CHAN_BODY, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
10007
10008 // Add a blue tint to their screen
10009 message_begin(MSG_ONE, g_msgScreenFade, _, victim)
10010 write_short(0) // duration
10011 write_short(0) // hold time
10012 write_short(FFADE_STAYOUT) // fade type
10013 write_byte(0) // red
10014 write_byte(50) // green
10015 write_byte(200) // blue
10016 write_byte(100) // alpha
10017 message_end()
10018
10019 // Set the frozen flag
10020 g_frozen[victim] = true
10021
10022 // Save player's old gravity (bugfix)
10023 pev(victim, pev_gravity, g_frozen_gravity[victim])
10024
10025 // Prevent from jumping
10026 if (pev(victim, pev_flags) & FL_ONGROUND)
10027 set_pev(victim, pev_gravity, 999999.9) // set really high
10028 else
10029 set_pev(victim, pev_gravity, 0.000001) // no gravity
10030
10031 // Prevent from moving
10032 ExecuteHamB(Ham_Player_ResetMaxSpeed, victim)
10033
10034 // Set a task to remove the freeze
10035 set_task(get_pcvar_float(cvar_freezeduration), "remove_freeze", victim)
10036 }
10037
10038 // Get rid of the grenade
10039 engfunc(EngFunc_RemoveEntity, ent)
10040}
10041
10042// Remove freeze task
10043public remove_freeze(id)
10044{
10045 // Not alive or not frozen anymore
10046 if (!g_isalive[id] || !g_frozen[id])
10047 return;
10048
10049 // Unfreeze
10050 g_frozen[id] = false;
10051
10052 // Restore gravity and maxspeed (bugfix)
10053 set_pev(id, pev_gravity, g_frozen_gravity[id])
10054 ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
10055
10056 // Restore rendering
10057 if (g_handle_models_on_separate_ent)
10058 {
10059 // Nemesis or Survivor glow / remove glow on player model entity
10060 if (g_nemesis[id] && get_pcvar_num(cvar_nemglow))
10061 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 250, 0, 0, kRenderNormal, 25)
10062 else if (g_nemesis[id] && !(get_pcvar_num(cvar_nemglow)))
10063 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 0, 0, 0, kRenderNormal, 25)
10064 else if (g_assassin[id] && get_pcvar_num(cvar_assaglow))
10065 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 255, 255, 0, kRenderNormal, 25)
10066 else if (g_survivor[id] && get_pcvar_num(cvar_survglow))
10067 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 0, 0, 255, kRenderNormal, 25)
10068 else if (g_sniper[id] && get_pcvar_num(cvar_sniglow))
10069 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 0, 255, 0, kRenderNormal, 25)
10070 else
10071 fm_set_rendering(g_ent_playermodel[id])
10072 }
10073 else
10074 {
10075 // Nemesis or Survivor glow / remove glow
10076 if (g_nemesis[id] && get_pcvar_num(cvar_nemglow))
10077 fm_set_rendering(id, kRenderFxGlowShell, 250, 0, 0, kRenderNormal, 25)
10078 else if (g_nemesis[id] && !(get_pcvar_num(cvar_nemglow)))
10079 fm_set_rendering(id, kRenderFxGlowShell, 0, 0, 0, kRenderNormal, 25)
10080 else if (g_assassin[id] && get_pcvar_num(cvar_assaglow))
10081 fm_set_rendering(id, kRenderFxGlowShell, 255, 255, 0, kRenderNormal, 25)
10082 else if (g_survivor[id] && get_pcvar_num(cvar_survglow))
10083 fm_set_rendering(id, kRenderFxGlowShell, 0, 0, 255, kRenderNormal, 25)
10084 else if (g_sniper[id] && get_pcvar_num(cvar_sniglow))
10085 fm_set_rendering(id, kRenderFxGlowShell, 0, 255, 0, kRenderNormal, 25)
10086 else
10087 fm_set_rendering(id)
10088 }
10089
10090 // Gradually remove screen's blue tint
10091 message_begin(MSG_ONE, g_msgScreenFade, _, id)
10092 write_short(UNIT_SECOND) // duration
10093 write_short(0) // hold time
10094 write_short(FFADE_IN) // fade type
10095 write_byte(0) // red
10096 write_byte(50) // green
10097 write_byte(200) // blue
10098 write_byte(100) // alpha
10099 message_end()
10100
10101 // Broken glass sound
10102 static sound[64]
10103 ArrayGetString(grenade_frost_break, random_num(0, ArraySize(grenade_frost_break) - 1), sound, charsmax(sound))
10104 emit_sound(id, CHAN_BODY, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
10105
10106 // Get player's origin
10107 static origin2[3]
10108 get_user_origin(id, origin2)
10109
10110 // Glass shatter
10111 message_begin(MSG_PVS, SVC_TEMPENTITY, origin2)
10112 write_byte(TE_BREAKMODEL) // TE id
10113 write_coord(origin2[0]) // x
10114 write_coord(origin2[1]) // y
10115 write_coord(origin2[2]+24) // z
10116 write_coord(16) // size x
10117 write_coord(16) // size y
10118 write_coord(16) // size z
10119 write_coord(random_num(-50, 50)) // velocity x
10120 write_coord(random_num(-50, 50)) // velocity y
10121 write_coord(25) // velocity z
10122 write_byte(10) // random velocity
10123 write_short(g_glassSpr) // model
10124 write_byte(10) // count
10125 write_byte(25) // life
10126 write_byte(BREAK_GLASS) // flags
10127 message_end()
10128
10129 ExecuteForward(g_fwUserUnfrozen, g_fwDummyResult, id);
10130}
10131
10132// Remove Stuff Task
10133public remove_stuff()
10134{
10135 static ent
10136
10137 // Remove rotating doors
10138 if (get_pcvar_num(cvar_removedoors) > 0)
10139 {
10140 ent = -1;
10141 while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "func_door_rotating")) != 0)
10142 engfunc(EngFunc_SetOrigin, ent, Float:{8192.0 ,8192.0 ,8192.0})
10143 }
10144
10145 // Remove all doors
10146 if (get_pcvar_num(cvar_removedoors) > 1)
10147 {
10148 ent = -1;
10149 while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "func_door")) != 0)
10150 engfunc(EngFunc_SetOrigin, ent, Float:{8192.0 ,8192.0 ,8192.0})
10151 }
10152
10153 // Triggered lights
10154 if (!get_pcvar_num(cvar_triggered))
10155 {
10156 ent = -1
10157 while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "light")) != 0)
10158 {
10159 dllfunc(DLLFunc_Use, ent, 0); // turn off the light
10160 set_pev(ent, pev_targetname, 0) // prevent it from being triggered
10161 }
10162 }
10163}
10164
10165// Set Custom Weapon Models
10166replace_weapon_models(id, weaponid)
10167{
10168 switch (weaponid)
10169 {
10170 case CSW_KNIFE: // Custom knife models
10171 {
10172 if (g_zombie[id])
10173 {
10174 if (g_nemesis[id]) // Nemesis
10175 {
10176 set_pev(id, pev_viewmodel2, model_vknife_nemesis)
10177 set_pev(id, pev_weaponmodel2, "")
10178 }
10179 else if (g_assassin[id]) // Assassins
10180 {
10181 set_pev(id, pev_viewmodel2, model_vknife_assassin)
10182 set_pev(id, pev_weaponmodel2, "")
10183 }
10184 else // Zombies
10185 {
10186 // Admin knife models?
10187 if (get_pcvar_num(cvar_adminknifemodelszombie) && get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS])
10188 {
10189 set_pev(id, pev_viewmodel2, model_vknife_admin_zombie)
10190 set_pev(id, pev_weaponmodel2, "")
10191 }
10192 else
10193 {
10194 static clawmodel[100]
10195 ArrayGetString(g_zclass_clawmodel, g_zombieclass[id], clawmodel, charsmax(clawmodel))
10196 format(clawmodel, charsmax(clawmodel), "models/zombie_plague/%s", clawmodel)
10197 set_pev(id, pev_viewmodel2, clawmodel)
10198 set_pev(id, pev_weaponmodel2, "")
10199 }
10200 }
10201 }
10202 else // Humans
10203 {
10204 // Admin knife models?
10205 if (get_pcvar_num(cvar_adminknifemodelshuman) && get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS])
10206 {
10207 set_pev(id, pev_viewmodel2, model_vknife_admin_human)
10208 set_pev(id, pev_weaponmodel2, "models/p_knife.mdl")
10209 }
10210 else
10211 {
10212 set_pev(id, pev_viewmodel2, model_vknife_human)
10213 set_pev(id, pev_weaponmodel2, "models/p_knife.mdl")
10214 }
10215 }
10216 }
10217 case CSW_AWP: // Sniper's AWP
10218 {
10219 if (g_sniper[id])
10220 {
10221 set_pev(id, pev_viewmodel2, model_vawp_sniper)
10222 set_pev(id, pev_weaponmodel2, model_pawp_sniper)
10223 }
10224 }
10225 case CSW_HEGRENADE: // Infection bomb or fire grenade
10226 {
10227 if (g_zombie[id])
10228 set_pev(id, pev_viewmodel2, model_grenade_infect)
10229 else
10230 set_pev(id, pev_viewmodel2, model_grenade_fire)
10231 }
10232 case CSW_FLASHBANG: // Frost grenade
10233 {
10234 set_pev(id, pev_viewmodel2, model_grenade_frost)
10235 }
10236 case CSW_SMOKEGRENADE: // Flare grenade
10237 {
10238 set_pev(id, pev_viewmodel2, model_grenade_flare)
10239 }
10240 }
10241
10242 // Update model on weaponmodel ent
10243 if (g_handle_models_on_separate_ent) fm_set_weaponmodel_ent(id)
10244}
10245
10246// Reset Player Vars
10247reset_vars(id, resetall)
10248{
10249 g_zombie[id] = false
10250 g_nemesis[id] = false
10251 g_assassin[id] = false
10252 g_survivor[id] = false
10253 g_sniper[id] = false
10254 g_firstzombie[id] = false
10255 g_lastzombie[id] = false
10256 g_lasthuman[id] = false
10257 g_frozen[id] = false
10258 g_nodamage[id] = false
10259 g_respawn_as_zombie[id] = false
10260 g_nvision[id] = false
10261 g_nvisionenabled[id] = false
10262 g_flashlight[id] = false
10263 g_flashbattery[id] = 100
10264 g_canbuy[id] = true
10265 g_burning_duration[id] = 0
10266
10267 if (resetall)
10268 {
10269 g_ammopacks[id] = get_pcvar_num(cvar_startammopacks)
10270 g_zombieclass[id] = ZCLASS_NONE
10271 g_zombieclassnext[id] = ZCLASS_NONE
10272 g_damagedealt_human[id] = 0
10273 g_damagedealt_zombie[id] = 0
10274 WPN_AUTO_ON = 0
10275 WPN_STARTID = 0
10276 PL_ACTION = 0
10277 MENU_PAGE_ZCLASS = 0
10278 MENU_PAGE_EXTRAS = 0
10279 MENU_PAGE_PLAYERS = 0
10280 }
10281}
10282
10283// Set spectators nightvision
10284public spec_nvision(id)
10285{
10286 // Not connected, alive, or bot
10287 if (!g_isconnected[id] || g_isalive[id] || g_isbot[id])
10288 return;
10289
10290 // Give Night Vision?
10291 if (get_pcvar_num(cvar_nvggive))
10292 {
10293 g_nvision[id] = true
10294
10295 // Turn on Night Vision automatically?
10296 if (get_pcvar_num(cvar_nvggive) == 1)
10297 {
10298 g_nvisionenabled[id] = true
10299
10300 // Custom nvg?
10301 if (get_pcvar_num(cvar_customnvg))
10302 {
10303 remove_task(id+TASK_NVISION)
10304 set_task(0.1, "set_user_nvision", id+TASK_NVISION, _, _, "b")
10305 }
10306 else
10307 set_user_gnvision(id, 1)
10308 }
10309 }
10310}
10311
10312// Show HUD Task
10313public ShowHUD(taskid)
10314{
10315 static id
10316 id = ID_SHOWHUD;
10317
10318 // Player died?
10319 if (!g_isalive[id])
10320 {
10321 // Get spectating target
10322 id = pev(id, PEV_SPEC_TARGET)
10323
10324 // Target not alive
10325 if (!g_isalive[id]) return;
10326 }
10327
10328 // Format classname
10329 static class[32], red, green, blue
10330
10331 if (g_zombie[id]) // zombies
10332 {
10333 red = 200
10334 green = 250
10335 blue = 0
10336
10337 if (g_nemesis[id])
10338 formatex(class, charsmax(class), "%L", ID_SHOWHUD, "CLASS_NEMESIS")
10339 else if (g_assassin[id])
10340 formatex(class, charsmax(class), "%L", ID_SHOWHUD, "CLASS_ASSASSIN")
10341 else
10342 copy(class, charsmax(class), g_zombie_classname[id])
10343 }
10344 else // humans
10345 {
10346 red = 20
10347 green = 135
10348 blue = 255
10349
10350 if (g_survivor[id])
10351 formatex(class, charsmax(class), "%L", ID_SHOWHUD, "CLASS_SURVIVOR")
10352 else if (g_sniper[id])
10353 formatex(class, charsmax(class), "%L", ID_SHOWHUD, "CLASS_SNIPER")
10354 else
10355 formatex(class, charsmax(class), "%L", ID_SHOWHUD, "CLASS_HUMAN")
10356 }
10357
10358 // Spectating someone else?
10359 if (id != ID_SHOWHUD)
10360 {
10361 // Show name, health, class, and ammo packs
10362 set_hudmessage(20, 184, 62, HUD_SPECT_X, HUD_SPECT_Y, 0, 6.0, 1.1, 0.0, 0.0, -1)
10363 ShowSyncHudMsg(ID_SHOWHUD, g_MsgSync2, "%L %s^nHP: %d - %L %s - %L %d - Armor: %d", ID_SHOWHUD, "SPECTATING", g_playername[id], pev(id, pev_health), ID_SHOWHUD, "CLASS_CLASS", class, ID_SHOWHUD, "AMMO_PACKS1", g_ammopacks[id], pev(id, pev_armorvalue))
10364 }
10365 else
10366 {
10367 // Show health, class and ammo packs
10368 set_hudmessage(red, green, blue, HUD_STATS_X, HUD_STATS_Y, 0, 6.0, 1.1, 0.0, 0.0, -1)
10369 ShowSyncHudMsg(ID_SHOWHUD, g_MsgSync2, "[%L : %d] ^n[%L : %s] ^n[%L : %d] ^n[%L : %d] ^n[discord.me/rbegaming]", id, "ZOMBIE_ATTRIB1", pev(ID_SHOWHUD, pev_health), ID_SHOWHUD, "CLASS_CLASS", class, ID_SHOWHUD, "AMMO_PACKS1", g_ammopacks[ID_SHOWHUD], ID_SHOWHUD, "ARMOR", pev(ID_SHOWHUD, pev_armorvalue))
10370 }
10371}
10372
10373// Play idle zombie sounds
10374public zombie_play_idle(taskid)
10375{
10376 // Round ended/new one starting
10377 if (g_endround || g_newround)
10378 return;
10379
10380 static sound[64]
10381
10382 // Last zombie?
10383 if (g_lastzombie[ID_BLOOD])
10384 {
10385 ArrayGetString(zombie_idle_last, random_num(0, ArraySize(zombie_idle_last) - 1), sound, charsmax(sound))
10386 emit_sound(ID_BLOOD, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
10387 }
10388 else
10389 {
10390 ArrayGetString(zombie_idle, random_num(0, ArraySize(zombie_idle) - 1), sound, charsmax(sound))
10391 emit_sound(ID_BLOOD, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
10392 }
10393}
10394
10395// Madness Over Task
10396public madness_over(taskid)
10397{
10398 g_nodamage[ID_BLOOD] = false
10399}
10400
10401// Place user at a random spawn
10402do_random_spawn(id, regularspawns = 0)
10403{
10404 static hull, sp_index, i
10405
10406 // Get whether the player is crouching
10407 hull = (pev(id, pev_flags) & FL_DUCKING) ? HULL_HEAD : HULL_HUMAN
10408
10409 // Use regular spawns?
10410 if (!regularspawns)
10411 {
10412 // No spawns?
10413 if (!g_spawnCount)
10414 return;
10415
10416 // Choose random spawn to start looping at
10417 sp_index = random_num(0, g_spawnCount - 1)
10418
10419 // Try to find a clear spawn
10420 for (i = sp_index + 1; /*no condition*/; i++)
10421 {
10422 // Start over when we reach the end
10423 if (i >= g_spawnCount) i = 0
10424
10425 // Free spawn space?
10426 if (is_hull_vacant(g_spawns[i], hull))
10427 {
10428 // Engfunc_SetOrigin is used so ent's mins and maxs get updated instantly
10429 engfunc(EngFunc_SetOrigin, id, g_spawns[i])
10430 break;
10431 }
10432
10433 // Loop completed, no free space found
10434 if (i == sp_index) break;
10435 }
10436 }
10437 else
10438 {
10439 // No spawns?
10440 if (!g_spawnCount2)
10441 return;
10442
10443 // Choose random spawn to start looping at
10444 sp_index = random_num(0, g_spawnCount2 - 1)
10445
10446 // Try to find a clear spawn
10447 for (i = sp_index + 1; /*no condition*/; i++)
10448 {
10449 // Start over when we reach the end
10450 if (i >= g_spawnCount2) i = 0
10451
10452 // Free spawn space?
10453 if (is_hull_vacant(g_spawns2[i], hull))
10454 {
10455 // Engfunc_SetOrigin is used so ent's mins and maxs get updated instantly
10456 engfunc(EngFunc_SetOrigin, id, g_spawns2[i])
10457 break;
10458 }
10459
10460 // Loop completed, no free space found
10461 if (i == sp_index) break;
10462 }
10463 }
10464}
10465
10466// Get Zombies -returns alive zombies number-
10467fnGetZombies()
10468{
10469 static iZombies, id
10470 iZombies = 0
10471
10472 for (id = 1; id <= g_maxplayers; id++)
10473 {
10474 if (g_isalive[id] && g_zombie[id])
10475 iZombies++
10476 }
10477
10478 return iZombies;
10479}
10480
10481// Get Humans -returns alive humans number-
10482fnGetHumans()
10483{
10484 static iHumans, id
10485 iHumans = 0
10486
10487 for (id = 1; id <= g_maxplayers; id++)
10488 {
10489 if (g_isalive[id] && !g_zombie[id])
10490 iHumans++
10491 }
10492
10493 return iHumans;
10494}
10495
10496// Get Nemesis -returns alive nemesis number-
10497fnGetNemesis()
10498{
10499 static iNemesis, id
10500 iNemesis = 0
10501
10502 for (id = 1; id <= g_maxplayers; id++)
10503 {
10504 if (g_isalive[id] && g_nemesis[id])
10505 iNemesis++
10506 }
10507
10508 return iNemesis;
10509}
10510
10511// Get Assassin -returns alive assassin number-
10512fnGetAssassin()
10513{
10514 static iAssassin, id
10515 iAssassin = 0
10516
10517 for (id = 1; id <= g_maxplayers; id++)
10518 {
10519 if (g_isalive[id] && g_assassin[id])
10520 iAssassin++
10521 }
10522
10523 return iAssassin;
10524}
10525
10526// Get Survivors -returns alive survivors number-
10527fnGetSurvivors()
10528{
10529 static iSurvivors, id
10530 iSurvivors = 0
10531
10532 for (id = 1; id <= g_maxplayers; id++)
10533 {
10534 if (g_isalive[id] && g_survivor[id])
10535 iSurvivors++
10536 }
10537
10538 return iSurvivors;
10539}
10540
10541// Get Snipers -returns alive snipers number-
10542fnGetSnipers()
10543{
10544 static iSnipers, id
10545 iSnipers = 0
10546
10547 for (id = 1; id <= g_maxplayers; id++)
10548 {
10549 if (g_isalive[id] && g_sniper[id])
10550 iSnipers++
10551 }
10552
10553 return iSnipers;
10554}
10555
10556// Get Alive -returns alive players number-
10557fnGetAlive()
10558{
10559 static iAlive, id
10560 iAlive = 0
10561
10562 for (id = 1; id <= g_maxplayers; id++)
10563 {
10564 if (g_isalive[id])
10565 iAlive++
10566 }
10567
10568 return iAlive;
10569}
10570
10571// Get Random Alive -returns index of alive player number n -
10572fnGetRandomAlive(n)
10573{
10574 static iAlive, id
10575 iAlive = 0
10576
10577 for (id = 1; id <= g_maxplayers; id++)
10578 {
10579 if (g_isalive[id])
10580 iAlive++
10581
10582 if (iAlive == n)
10583 return id;
10584 }
10585
10586 return -1;
10587}
10588
10589// Get Playing -returns number of users playing-
10590fnGetPlaying()
10591{
10592 static iPlaying, id, team
10593 iPlaying = 0
10594
10595 for (id = 1; id <= g_maxplayers; id++)
10596 {
10597 if (g_isconnected[id])
10598 {
10599 team = fm_cs_get_user_team(id)
10600
10601 if (team != FM_CS_TEAM_SPECTATOR && team != FM_CS_TEAM_UNASSIGNED)
10602 iPlaying++
10603 }
10604 }
10605
10606 return iPlaying;
10607}
10608
10609// Get CTs -returns number of CTs connected-
10610fnGetCTs()
10611{
10612 static iCTs, id
10613 iCTs = 0
10614
10615 for (id = 1; id <= g_maxplayers; id++)
10616 {
10617 if (g_isconnected[id])
10618 {
10619 if (fm_cs_get_user_team(id) == FM_CS_TEAM_CT)
10620 iCTs++
10621 }
10622 }
10623
10624 return iCTs;
10625}
10626
10627// Get Ts -returns number of Ts connected-
10628fnGetTs()
10629{
10630 static iTs, id
10631 iTs = 0
10632
10633 for (id = 1; id <= g_maxplayers; id++)
10634 {
10635 if (g_isconnected[id])
10636 {
10637 if (fm_cs_get_user_team(id) == FM_CS_TEAM_T)
10638 iTs++
10639 }
10640 }
10641
10642 return iTs;
10643}
10644
10645// Get Alive CTs -returns number of CTs alive-
10646fnGetAliveCTs()
10647{
10648 static iCTs, id
10649 iCTs = 0
10650
10651 for (id = 1; id <= g_maxplayers; id++)
10652 {
10653 if (g_isalive[id])
10654 {
10655 if (fm_cs_get_user_team(id) == FM_CS_TEAM_CT)
10656 iCTs++
10657 }
10658 }
10659
10660 return iCTs;
10661}
10662
10663// Get Alive Ts -returns number of Ts alive-
10664fnGetAliveTs()
10665{
10666 static iTs, id
10667 iTs = 0
10668
10669 for (id = 1; id <= g_maxplayers; id++)
10670 {
10671 if (g_isalive[id])
10672 {
10673 if (fm_cs_get_user_team(id) == FM_CS_TEAM_T)
10674 iTs++
10675 }
10676 }
10677
10678 return iTs;
10679}
10680
10681// Last Zombie Check -check for last zombie and set its flag-
10682fnCheckLastZombie()
10683{
10684 static id
10685 for (id = 1; id <= g_maxplayers; id++)
10686 {
10687 // Last zombie
10688 if (g_isalive[id] && g_zombie[id] && !g_nemesis[id] && !g_assassin[id] && fnGetZombies() == 1)
10689 {
10690 if (!g_lastzombie[id])
10691 {
10692 // Last zombie forward
10693 ExecuteForward(g_fwUserLastZombie, g_fwDummyResult, id);
10694 }
10695 g_lastzombie[id] = true
10696 }
10697 else
10698 g_lastzombie[id] = false
10699
10700 // Last human
10701 if (g_isalive[id] && !g_zombie[id] && !g_survivor[id] && !g_sniper[id] && fnGetHumans() == 1)
10702 {
10703 if (!g_lasthuman[id])
10704 {
10705 // Last human forward
10706 ExecuteForward(g_fwUserLastHuman, g_fwDummyResult, id);
10707
10708 // Reward extra hp
10709 fm_set_user_health(id, pev(id, pev_health) + get_pcvar_num(cvar_humanlasthp))
10710 }
10711 g_lasthuman[id] = true
10712 }
10713 else
10714 g_lasthuman[id] = false
10715 }
10716}
10717
10718// Save player's stats to database
10719save_stats(id)
10720{
10721 // Check whether there is another record already in that slot
10722 if (db_name[id][0] && !equal(g_playername[id], db_name[id]))
10723 {
10724 // If DB size is exceeded, write over old records
10725 if (db_slot_i >= sizeof db_name)
10726 db_slot_i = g_maxplayers+1
10727
10728 // Move previous record onto an additional save slot
10729 copy(db_name[db_slot_i], charsmax(db_name[]), db_name[id])
10730 db_ammopacks[db_slot_i] = db_ammopacks[id]
10731 db_zombieclass[db_slot_i] = db_zombieclass[id]
10732 db_slot_i++
10733 }
10734
10735 // Now save the current player stats
10736 copy(db_name[id], charsmax(db_name[]), g_playername[id]) // name
10737 db_ammopacks[id] = g_ammopacks[id] // ammo packs
10738 db_zombieclass[id] = g_zombieclassnext[id] // zombie class
10739}
10740
10741// Load player's stats from database (if a record is found)
10742load_stats(id)
10743{
10744 // Look for a matching record
10745 static i
10746 for (i = 0; i < sizeof db_name; i++)
10747 {
10748 if (equal(g_playername[id], db_name[i]))
10749 {
10750 // Bingo!
10751 g_ammopacks[id] = db_ammopacks[i]
10752 g_zombieclass[id] = db_zombieclass[i]
10753 g_zombieclassnext[id] = db_zombieclass[i]
10754 return;
10755 }
10756 }
10757}
10758
10759// Checks if a player is allowed to be zombie
10760allowed_zombie(id)
10761{
10762 if ((g_zombie[id] && !g_nemesis[id] && !g_assassin[id]) || g_endround || !g_isalive[id] || task_exists(TASK_WELCOMEMSG) || (!g_newround && !g_zombie[id] && fnGetHumans() == 1))
10763 return false;
10764
10765 return true;
10766}
10767
10768// Checks if a player is allowed to be human
10769allowed_human(id)
10770{
10771 if ((!g_zombie[id] && !g_survivor[id] && !g_sniper[id]) || g_endround || !g_isalive[id] || task_exists(TASK_WELCOMEMSG) || (!g_newround && g_zombie[id] && fnGetZombies() == 1))
10772 return false;
10773
10774 return true;
10775}
10776
10777// Checks if a player is allowed to be survivor
10778allowed_survivor(id)
10779{
10780 if (g_endround || g_survivor[id] || !g_isalive[id] || task_exists(TASK_WELCOMEMSG) || (!g_newround && g_zombie[id] && fnGetZombies() == 1))
10781 return false;
10782
10783 return true;
10784}
10785
10786// Checks if a player is allowed to be sniper
10787allowed_sniper(id)
10788{
10789 if (g_endround || g_sniper[id] || !g_isalive[id] || task_exists(TASK_WELCOMEMSG) || (!g_newround && g_zombie[id] && fnGetZombies() == 1))
10790 return false;
10791
10792 return true;
10793}
10794
10795// Checks if a player is allowed to be nemesis
10796allowed_nemesis(id)
10797{
10798 if (g_endround || g_nemesis[id] || !g_isalive[id] || task_exists(TASK_WELCOMEMSG) || (!g_newround && !g_zombie[id] && fnGetHumans() == 1))
10799 return false;
10800
10801 return true;
10802}
10803
10804// Checks if a player is allowed to be assassin
10805allowed_assassin(id)
10806{
10807 if (g_endround || g_assassin[id] || !g_isalive[id] || task_exists(TASK_WELCOMEMSG) || (!g_newround && !g_zombie[id] && fnGetHumans() == 1))
10808 return false;
10809
10810 return true;
10811}
10812
10813// Checks if a player is allowed to respawn
10814allowed_respawn(id)
10815{
10816 static team
10817 team = fm_cs_get_user_team(id)
10818
10819 if (g_endround || team == FM_CS_TEAM_SPECTATOR || team == FM_CS_TEAM_UNASSIGNED || g_isalive[id])
10820 return false;
10821
10822 return true;
10823}
10824
10825// Checks if swarm mode is allowed
10826allowed_swarm()
10827{
10828 if (g_endround || !g_newround || task_exists(TASK_WELCOMEMSG))
10829 return false;
10830
10831 return true;
10832}
10833
10834// Checks if multi infection mode is allowed
10835allowed_multi()
10836{
10837 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())
10838 return false;
10839
10840 return true;
10841}
10842
10843// Checks if plague mode is allowed
10844allowed_plague()
10845{
10846 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
10847 || 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)
10848 return false;
10849
10850 return true;
10851}
10852
10853// Checks if armageddon mode is allowed
10854allowed_armageddon()
10855{
10856 if (g_endround || !g_newround || task_exists(TASK_WELCOMEMSG) || floatround(fnGetAlive()*get_pcvar_float(cvar_armageratio), floatround_ceil) < 2 || floatround(fnGetAlive()*get_pcvar_float(cvar_armageratio), floatround_ceil) >= fnGetAlive())
10857 return false;
10858
10859 return true;
10860}
10861
10862// Checks if apocalypse mode is allowed
10863allowed_apocalypse()
10864{
10865 if (g_endround || !g_newround || task_exists(TASK_WELCOMEMSG) || floatround(fnGetAlive()*get_pcvar_float(cvar_apocratio), floatround_ceil) < 2 || floatround(fnGetAlive()*get_pcvar_float(cvar_apocratio), floatround_ceil) >= fnGetAlive())
10866 return false;
10867
10868 return true;
10869}
10870
10871// Checks if nightmare mode is allowed
10872allowed_nightmare()
10873{
10874 if (g_endround || !g_newround || task_exists(TASK_WELCOMEMSG) || floatround(fnGetAlive()*get_pcvar_float(cvar_nightratio), floatround_ceil) < 2 || floatround(fnGetAlive()*get_pcvar_float(cvar_nightratio), floatround_ceil) >= fnGetAlive())
10875 return false;
10876
10877 return true;
10878}
10879
10880// Admin Command. zp_zombie
10881command_zombie(id, player)
10882{
10883 // Show activity?
10884 switch (get_pcvar_num(cvar_showactivity))
10885 {
10886 case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_INFECT")
10887 case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_INFECT")
10888 }
10889
10890 // Log to Zombie Plague log file?
10891 if (get_pcvar_num(cvar_logcommands))
10892 {
10893 static logdata[100], authid[32], ip[16]
10894 get_user_authid(id, authid, charsmax(authid))
10895 get_user_ip(id, ip, charsmax(ip), 1)
10896 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)
10897 log_to_file("zombieplague.log", logdata)
10898 }
10899
10900 // New round?
10901 if (g_newround)
10902 {
10903 // Set as first zombie
10904 remove_task(TASK_MAKEZOMBIE)
10905 make_a_zombie(MODE_INFECTION, player)
10906 }
10907 else
10908 {
10909 // Just infect
10910 zombieme(player, 0, 0, 0, 0, 0)
10911 }
10912}
10913
10914// Admin Command. zp_human
10915command_human(id, player)
10916{
10917 // Show activity?
10918 switch (get_pcvar_num(cvar_showactivity))
10919 {
10920 case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_DISINFECT")
10921 case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_DISINFECT")
10922 }
10923
10924 // Log to Zombie Plague log file?
10925 if (get_pcvar_num(cvar_logcommands))
10926 {
10927 static logdata[100], authid[32], ip[16]
10928 get_user_authid(id, authid, charsmax(authid))
10929 get_user_ip(id, ip, charsmax(ip), 1)
10930 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)
10931 log_to_file("zombieplague.log", logdata)
10932 }
10933
10934 // Turn to human
10935 humanme(player, 0, 0, 0)
10936}
10937
10938// Admin Command. zp_survivor
10939command_survivor(id, player)
10940{
10941 // Show activity?
10942 switch (get_pcvar_num(cvar_showactivity))
10943 {
10944 case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_SURVIVAL")
10945 case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_SURVIVAL")
10946 }
10947
10948 // Log to Zombie Plague log file?
10949 if (get_pcvar_num(cvar_logcommands))
10950 {
10951 static logdata[100], authid[32], ip[16]
10952 get_user_authid(id, authid, charsmax(authid))
10953 get_user_ip(id, ip, charsmax(ip), 1)
10954 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)
10955 log_to_file("zombieplague.log", logdata)
10956 }
10957
10958 // New round?
10959 if (g_newround)
10960 {
10961 // Set as first survivor
10962 remove_task(TASK_MAKEZOMBIE)
10963 make_a_zombie(MODE_SURVIVOR, player)
10964 }
10965 else
10966 {
10967 // Turn player into a Survivor
10968 humanme(player, 1, 0, 0)
10969 }
10970}
10971
10972// Admin Command. zp_sniper
10973command_sniper(id, player)
10974{
10975 // Show activity?
10976 switch (get_pcvar_num(cvar_showactivity))
10977 {
10978 case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_SNIPER")
10979 case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_SNIPER")
10980 }
10981
10982 // Log to Zombie Plague log file?
10983 if (get_pcvar_num(cvar_logcommands))
10984 {
10985 static logdata[100], authid[32], ip[16]
10986 get_user_authid(id, authid, charsmax(authid))
10987 get_user_ip(id, ip, charsmax(ip), 1)
10988 formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %s %L (Players: %d/%d)", g_playername[id], authid, ip, g_playername[player], LANG_SERVER,"CMD_SNIPER", fnGetPlaying(), g_maxplayers)
10989 log_to_file("zombieplague.log", logdata)
10990 }
10991
10992 // New round?
10993 if (g_newround)
10994 {
10995 // Set as first sniper
10996 remove_task(TASK_MAKEZOMBIE)
10997 make_a_zombie(MODE_SNIPER, player)
10998 }
10999 else
11000 {
11001 // Turn player into a Sniper
11002 humanme(player, 0, 1, 0)
11003 }
11004}
11005
11006// Admin Command. zp_nemesis
11007command_nemesis(id, player)
11008{
11009 // Show activity?
11010 switch (get_pcvar_num(cvar_showactivity))
11011 {
11012 case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_NEMESIS")
11013 case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_NEMESIS")
11014 }
11015
11016 // Log to Zombie Plague log file?
11017 if (get_pcvar_num(cvar_logcommands))
11018 {
11019 static logdata[100], authid[32], ip[16]
11020 get_user_authid(id, authid, charsmax(authid))
11021 get_user_ip(id, ip, charsmax(ip), 1)
11022 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)
11023 log_to_file("zombieplague.log", logdata)
11024 }
11025
11026 // New round?
11027 if (g_newround)
11028 {
11029 // Set as first nemesis
11030 remove_task(TASK_MAKEZOMBIE)
11031 make_a_zombie(MODE_NEMESIS, player)
11032 }
11033 else
11034 {
11035 // Turn player into a Nemesis
11036 zombieme(player, 0, 1, 0, 0, 0)
11037 }
11038}
11039
11040// Admin Command. zp_assassin
11041command_assassin(id, player)
11042{
11043 // Show activity?
11044 switch (get_pcvar_num(cvar_showactivity))
11045 {
11046 case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_ASSASSIN")
11047 case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_ASSASSIN")
11048 }
11049
11050 // Log to Zombie Plague log file?
11051 if (get_pcvar_num(cvar_logcommands))
11052 {
11053 static logdata[100], authid[32], ip[16]
11054 get_user_authid(id, authid, charsmax(authid))
11055 get_user_ip(id, ip, charsmax(ip), 1)
11056 formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %s %L (Players: %d/%d)", g_playername[id], authid, ip, g_playername[player], LANG_SERVER,"CMD_ASSASSIN", fnGetPlaying(), g_maxplayers)
11057 log_to_file("zombieplague.log", logdata)
11058 }
11059
11060 // New round?
11061 if (g_newround)
11062 {
11063 // Set as first assassin
11064 remove_task(TASK_MAKEZOMBIE)
11065 make_a_zombie(MODE_ASSASSIN, player)
11066 }
11067 else
11068 {
11069 // Turn player into a Assassin
11070 zombieme(player, 0, 0, 1, 0, 0)
11071 }
11072}
11073
11074// Admin Command. zp_respawn
11075command_respawn(id, player)
11076{
11077 // Show activity?
11078 switch (get_pcvar_num(cvar_showactivity))
11079 {
11080 case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_RESPAWN")
11081 case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_RESPAWN")
11082 }
11083
11084 // Log to Zombie Plague log file?
11085 if (get_pcvar_num(cvar_logcommands))
11086 {
11087 static logdata[100], authid[32], ip[16]
11088 get_user_authid(id, authid, charsmax(authid))
11089 get_user_ip(id, ip, charsmax(ip), 1)
11090 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)
11091 log_to_file("zombieplague.log", logdata)
11092 }
11093
11094 // Respawn as zombie?
11095 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))
11096 g_respawn_as_zombie[player] = true
11097
11098 // Override respawn as zombie setting on nemesis and survivor rounds
11099 if (g_survround) g_respawn_as_zombie[player] = true
11100 else if (g_nemround) g_respawn_as_zombie[player] = false
11101
11102 respawn_player_manually(player);
11103}
11104
11105// Admin Command. zp_swarm
11106command_swarm(id)
11107{
11108 // Show activity?
11109 switch (get_pcvar_num(cvar_showactivity))
11110 {
11111 case 1: client_print(0, print_chat, "ADMIN - %L", LANG_PLAYER, "CMD_SWARM")
11112 case 2: client_print(0, print_chat, "ADMIN %s - %L", g_playername[id], LANG_PLAYER, "CMD_SWARM")
11113 }
11114
11115 // Log to Zombie Plague log file?
11116 if (get_pcvar_num(cvar_logcommands))
11117 {
11118 static logdata[100], authid[32], ip[16]
11119 get_user_authid(id, authid, charsmax(authid))
11120 get_user_ip(id, ip, charsmax(ip), 1)
11121 formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %L (Players: %d/%d)", g_playername[id], authid, ip, LANG_SERVER, "CMD_SWARM", fnGetPlaying(), g_maxplayers)
11122 log_to_file("zombieplague.log", logdata)
11123 }
11124
11125 // Call Swarm Mode
11126 remove_task(TASK_MAKEZOMBIE)
11127 make_a_zombie(MODE_SWARM, 0)
11128}
11129
11130// Admin Command. zp_multi
11131command_multi(id)
11132{
11133 // Show activity?
11134 switch (get_pcvar_num(cvar_showactivity))
11135 {
11136 case 1: client_print(0, print_chat, "ADMIN - %L", LANG_PLAYER, "CMD_MULTI")
11137 case 2: client_print(0, print_chat, "ADMIN %s - %L", g_playername[id], LANG_PLAYER, "CMD_MULTI")
11138 }
11139
11140 // Log to Zombie Plague log file?
11141 if (get_pcvar_num(cvar_logcommands))
11142 {
11143 static logdata[100], authid[32], ip[16]
11144 get_user_authid(id, authid, charsmax(authid))
11145 get_user_ip(id, ip, charsmax(ip), 1)
11146 formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %L (Players: %d/%d)", g_playername[id], authid, ip, LANG_SERVER,"CMD_MULTI", fnGetPlaying(), g_maxplayers)
11147 log_to_file("zombieplague.log", logdata)
11148 }
11149
11150 // Call Multi Infection
11151 remove_task(TASK_MAKEZOMBIE)
11152 make_a_zombie(MODE_MULTI, 0)
11153}
11154
11155// Admin Command. zp_plague
11156command_plague(id)
11157{
11158 // Show activity?
11159 switch (get_pcvar_num(cvar_showactivity))
11160 {
11161 case 1: client_print(0, print_chat, "ADMIN - %L", LANG_PLAYER, "CMD_PLAGUE")
11162 case 2: client_print(0, print_chat, "ADMIN %s - %L", g_playername[id], LANG_PLAYER, "CMD_PLAGUE")
11163 }
11164
11165 // Log to Zombie Plague log file?
11166 if (get_pcvar_num(cvar_logcommands))
11167 {
11168 static logdata[100], authid[32], ip[16]
11169 get_user_authid(id, authid, charsmax(authid))
11170 get_user_ip(id, ip, charsmax(ip), 1)
11171 formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %L (Players: %d/%d)", g_playername[id], authid, ip, LANG_SERVER,"CMD_PLAGUE", fnGetPlaying(), g_maxplayers)
11172 log_to_file("zombieplague.log", logdata)
11173 }
11174
11175 // Call Plague Mode
11176 remove_task(TASK_MAKEZOMBIE)
11177 make_a_zombie(MODE_PLAGUE, 0)
11178}
11179
11180// Admin Command. zp_armageddon
11181command_armageddon(id)
11182{
11183 // Show activity?
11184 switch (get_pcvar_num(cvar_showactivity))
11185 {
11186 case 1: client_print(0, print_chat, "ADMIN - %L", LANG_PLAYER, "CMD_ARMAGEDDON")
11187 case 2: client_print(0, print_chat, "ADMIN %s - %L", g_playername[id], LANG_PLAYER, "CMD_ARMAGEDDON")
11188 }
11189
11190 // Log to Zombie Plague log file?
11191 if (get_pcvar_num(cvar_logcommands))
11192 {
11193 static logdata[100], authid[32], ip[16]
11194 get_user_authid(id, authid, charsmax(authid))
11195 get_user_ip(id, ip, charsmax(ip), 1)
11196 formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %L (Players: %d/%d)", g_playername[id], authid, ip, LANG_SERVER,"CMD_ARMAGEDDON", fnGetPlaying(), g_maxplayers)
11197 log_to_file("zombieplague.log", logdata)
11198 }
11199
11200 // Call Armageddon Mode
11201 remove_task(TASK_MAKEZOMBIE)
11202 make_a_zombie(MODE_ARMAGEDDON, 0)
11203}
11204
11205// Admin Command. zp_apocalypse
11206command_apocalypse(id)
11207{
11208 // Show activity?
11209 switch (get_pcvar_num(cvar_showactivity))
11210 {
11211 case 1: client_print(0, print_chat, "ADMIN - %L", LANG_PLAYER, "CMD_APOCALYPSE")
11212 case 2: client_print(0, print_chat, "ADMIN %s - %L", g_playername[id], LANG_PLAYER, "CMD_APOCALYPSE")
11213 }
11214
11215 // Log to Zombie Plague log file?
11216 if (get_pcvar_num(cvar_logcommands))
11217 {
11218 static logdata[100], authid[32], ip[16]
11219 get_user_authid(id, authid, charsmax(authid))
11220 get_user_ip(id, ip, charsmax(ip), 1)
11221 formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %L (Players: %d/%d)", g_playername[id], authid, ip, LANG_SERVER,"CMD_APOCALYPSE", fnGetPlaying(), g_maxplayers)
11222 log_to_file("zombieplague.log", logdata)
11223 }
11224
11225 // Call Apocalypse Mode
11226 remove_task(TASK_MAKEZOMBIE)
11227 make_a_zombie(MODE_APOCALYPSE, 0)
11228}
11229
11230// Admin Command. zp_nightmare
11231command_nightmare(id)
11232{
11233 // Show activity?
11234 switch (get_pcvar_num(cvar_showactivity))
11235 {
11236 case 1: client_print(0, print_chat, "ADMIN - %L", LANG_PLAYER, "CMD_NIGHTMARE")
11237 case 2: client_print(0, print_chat, "ADMIN %s - %L", g_playername[id], LANG_PLAYER, "CMD_NIGHTMARE")
11238 }
11239
11240 // Log to Zombie Plague log file?
11241 if (get_pcvar_num(cvar_logcommands))
11242 {
11243 static logdata[100], authid[32], ip[16]
11244 get_user_authid(id, authid, charsmax(authid))
11245 get_user_ip(id, ip, charsmax(ip), 1)
11246 formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %L (Players: %d/%d)", g_playername[id], authid, ip, LANG_SERVER,"CMD_NIGHTMARE", fnGetPlaying(), g_maxplayers)
11247 log_to_file("zombieplague.log", logdata)
11248 }
11249
11250 // Call Nightmare Mode
11251 remove_task(TASK_MAKEZOMBIE)
11252 make_a_zombie(MODE_NIGHTMARE, 0)
11253}
11254
11255// Set proper maxspeed for player
11256set_player_maxspeed(id)
11257{
11258 // If frozen, prevent from moving
11259 if (g_frozen[id])
11260 {
11261 set_pev(id, pev_maxspeed, 1.0)
11262 }
11263 // Otherwise, set maxspeed directly
11264 else
11265 {
11266 if (g_zombie[id])
11267 {
11268 if (g_nemesis[id])
11269 set_pev(id, pev_maxspeed, get_pcvar_float(cvar_nemspd))
11270 else if (g_assassin[id])
11271 set_pev(id, pev_maxspeed, get_pcvar_float(cvar_assaspd))
11272 else
11273 set_pev(id, pev_maxspeed, g_zombie_spd[id])
11274 }
11275 else
11276 {
11277 if (g_survivor[id])
11278 set_pev(id, pev_maxspeed, get_pcvar_float(cvar_survspd))
11279 else if (g_sniper[id])
11280 set_pev(id, pev_maxspeed, get_pcvar_float(cvar_snispd))
11281 else if (get_pcvar_float(cvar_humanspd) > 0.0)
11282 set_pev(id, pev_maxspeed, get_pcvar_float(cvar_humanspd))
11283 }
11284 }
11285}
11286
11287/*================================================================================
11288 [Custom Natives]
11289=================================================================================*/
11290
11291// Native: zp_get_user_zombie
11292public native_get_user_zombie(id)
11293{
11294 if (!is_user_valid(id))
11295 {
11296 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11297 return -1;
11298 }
11299
11300 return g_zombie[id];
11301}
11302
11303// Native: zp_get_user_nemesis
11304public native_get_user_nemesis(id)
11305{
11306 if (!is_user_valid(id))
11307 {
11308 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11309 return -1;
11310 }
11311
11312 return g_nemesis[id];
11313}
11314
11315// Native: zp_get_user_assassin
11316public native_get_user_assassin(id)
11317{
11318 if (!is_user_valid(id))
11319 {
11320 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11321 return -1;
11322 }
11323
11324 return g_assassin[id];
11325}
11326
11327// Native: zp_get_user_survivor
11328public native_get_user_survivor(id)
11329{
11330 if (!is_user_valid(id))
11331 {
11332 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11333 return -1;
11334 }
11335
11336 return g_survivor[id];
11337}
11338
11339// Native: zp_get_user_sniper
11340public native_get_user_sniper(id)
11341{
11342 if (!is_user_valid(id))
11343 {
11344 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11345 return -1;
11346 }
11347
11348 return g_sniper[id];
11349}
11350
11351public native_get_user_first_zombie(id)
11352{
11353 if (!is_user_valid(id))
11354 {
11355 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11356 return -1;
11357 }
11358
11359 return g_firstzombie[id];
11360}
11361
11362// Native: zp_get_user_last_zombie
11363public native_get_user_last_zombie(id)
11364{
11365 if (!is_user_valid(id))
11366 {
11367 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11368 return -1;
11369 }
11370
11371 return g_lastzombie[id];
11372}
11373
11374// Native: zp_get_user_last_human
11375public native_get_user_last_human(id)
11376{
11377 if (!is_user_valid(id))
11378 {
11379 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11380 return -1;
11381 }
11382
11383 return g_lasthuman[id];
11384}
11385
11386// Native: zp_get_user_zombie_class
11387public native_get_user_zombie_class(id)
11388{
11389 if (!is_user_valid(id))
11390 {
11391 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11392 return -1;
11393 }
11394
11395 return g_zombieclass[id];
11396}
11397
11398// Native: zp_get_user_next_class
11399public native_get_user_next_class(id)
11400{
11401 if (!is_user_valid(id))
11402 {
11403 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11404 return -1;
11405 }
11406
11407 return g_zombieclassnext[id];
11408}
11409
11410// Native: zp_set_user_zombie_class
11411public native_set_user_zombie_class(id, classid)
11412{
11413 if (!is_user_valid(id))
11414 {
11415 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11416 return false;
11417 }
11418
11419 if (classid < 0 || classid >= g_zclass_i)
11420 {
11421 log_error(AMX_ERR_NATIVE, "[ZP] Invalid zombie class id (%d)", classid)
11422 return false;
11423 }
11424
11425 g_zombieclassnext[id] = classid
11426 return true;
11427}
11428
11429// Native: zp_get_user_ammo_packs
11430public native_get_user_ammo_packs(id)
11431{
11432 if (!is_user_valid(id))
11433 {
11434 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11435 return -1;
11436 }
11437
11438 return g_ammopacks[id];
11439}
11440
11441// Native: zp_set_user_ammo_packs
11442public native_set_user_ammo_packs(id, amount)
11443{
11444 if (!is_user_valid(id))
11445 {
11446 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11447 return false;
11448 }
11449
11450 g_ammopacks[id] = amount;
11451 return true;
11452}
11453
11454// Native: zp_get_zombie_maxhealth
11455public native_get_zombie_maxhealth(id)
11456{
11457 // ZP disabled
11458 if (!g_pluginenabled)
11459 return -1;
11460
11461 if (!is_user_valid(id))
11462 {
11463 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11464 return -1;
11465 }
11466
11467 if (!g_zombie[id] || g_nemesis[id])
11468 {
11469 log_error(AMX_ERR_NATIVE, "[ZP] Player not a normal zombie (%d)", id)
11470 return -1;
11471 }
11472
11473 if (g_firstzombie[id])
11474 return floatround(float(ArrayGetCell(g_zclass_hp, g_zombieclass[id])) * get_pcvar_float(cvar_zombiefirsthp));
11475
11476 return ArrayGetCell(g_zclass_hp, g_zombieclass[id]);
11477}
11478
11479// Native: zp_get_user_batteries
11480public native_get_user_batteries(id)
11481{
11482 if (!is_user_valid(id))
11483 {
11484 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11485 return -1;
11486 }
11487
11488 return g_flashbattery[id];
11489}
11490
11491// Native: zp_set_user_batteries
11492public native_set_user_batteries(id, value)
11493{
11494 // ZP disabled
11495 if (!g_pluginenabled)
11496 return false;
11497
11498 if (!is_user_valid_connected(id))
11499 {
11500 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11501 return false;
11502 }
11503
11504 g_flashbattery[id] = clamp(value, 0, 100);
11505
11506 if (g_cached_customflash)
11507 {
11508 // Set the flashlight charge task to update battery status
11509 remove_task(id+TASK_CHARGE)
11510 set_task(1.0, "flashlight_charge", id+TASK_CHARGE, _, _, "b")
11511 }
11512 return true;
11513}
11514
11515// Native: zp_get_user_nightvision
11516public native_get_user_nightvision(id)
11517{
11518 if (!is_user_valid(id))
11519 {
11520 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11521 return -1;
11522 }
11523
11524 return g_nvision[id];
11525}
11526
11527// Native: zp_set_user_nightvision
11528public native_set_user_nightvision(id, set)
11529{
11530 // ZP disabled
11531 if (!g_pluginenabled)
11532 return false;
11533
11534 if (!is_user_valid_connected(id))
11535 {
11536 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11537 return false;
11538 }
11539
11540 if (set)
11541 {
11542 g_nvision[id] = true
11543
11544 if (!g_isbot[id])
11545 {
11546 g_nvisionenabled[id] = true
11547
11548 // Custom nvg?
11549 if (get_pcvar_num(cvar_customnvg))
11550 {
11551 remove_task(id+TASK_NVISION)
11552 set_task(0.1, "set_user_nvision", id+TASK_NVISION, _, _, "b")
11553 }
11554 else
11555 set_user_gnvision(id, 1)
11556 }
11557 else
11558 cs_set_user_nvg(id, 1)
11559 }
11560 else
11561 {
11562 // Remove CS nightvision if player owns one (bugfix)
11563 cs_set_user_nvg(id, 0)
11564
11565 if (get_pcvar_num(cvar_customnvg)) remove_task(id+TASK_NVISION)
11566 else if (g_nvisionenabled[id]) set_user_gnvision(id, 0)
11567 g_nvision[id] = false
11568 g_nvisionenabled[id] = false
11569 }
11570 return true;
11571}
11572
11573// Native: zp_infect_user
11574public native_infect_user(id, infector, silent, rewards)
11575{
11576 // ZP disabled
11577 if (!g_pluginenabled)
11578 return false;
11579
11580 if (!is_user_valid_alive(id))
11581 {
11582 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11583 return false;
11584 }
11585
11586 // Not allowed to be zombie
11587 if (!allowed_zombie(id))
11588 return false;
11589
11590 // New round?
11591 if (g_newround)
11592 {
11593 // Set as first zombie
11594 remove_task(TASK_MAKEZOMBIE)
11595 make_a_zombie(MODE_INFECTION, id)
11596 }
11597 else
11598 {
11599 // Just infect (plus some checks)
11600 zombieme(id, is_user_valid_alive(infector) ? infector : 0, 0, 0, (silent == 1) ? 1 : 0, (rewards == 1) ? 1 : 0)
11601 }
11602 return true;
11603}
11604
11605// Native: zp_disinfect_user
11606public native_disinfect_user(id, silent)
11607{
11608 // ZP disabled
11609 if (!g_pluginenabled)
11610 return false;
11611
11612 if (!is_user_valid_alive(id))
11613 {
11614 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11615 return false;
11616 }
11617
11618 // Not allowed to be human
11619 if (!allowed_human(id))
11620 return false;
11621
11622 // Turn to human
11623 humanme(id, 0, 0, (silent == 1) ? 1 : 0)
11624 return true;
11625}
11626
11627// Native: zp_make_user_nemesis
11628public native_make_user_nemesis(id)
11629{
11630 // ZP disabled
11631 if (!g_pluginenabled)
11632 return false;
11633
11634 if (!is_user_valid_alive(id))
11635 {
11636 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11637 return false;
11638 }
11639
11640 // Not allowed to be nemesis
11641 if (!allowed_nemesis(id))
11642 return false;
11643
11644 // New round?
11645 if (g_newround)
11646 {
11647 // Set as first nemesis
11648 remove_task(TASK_MAKEZOMBIE)
11649 make_a_zombie(MODE_NEMESIS, id)
11650 }
11651 else
11652 {
11653 // Turn player into a Nemesis
11654 zombieme(id, 0, 1, 0, 0, 0)
11655 }
11656 return true;
11657}
11658
11659// Native: zp_make_user_assassin
11660public native_make_user_assassin(id)
11661{
11662 // ZP disabled
11663 if (!g_pluginenabled)
11664 return false;
11665
11666 if (!is_user_valid_alive(id))
11667 {
11668 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11669 return false;
11670 }
11671
11672 // Not allowed to be assassin
11673 if (!allowed_assassin(id))
11674 return false;
11675
11676 // New round?
11677 if (g_newround)
11678 {
11679 // Set as first assassin
11680 remove_task(TASK_MAKEZOMBIE)
11681 make_a_zombie(MODE_ASSASSIN, id)
11682 }
11683 else
11684 {
11685 // Turn player into a Assassin
11686 zombieme(id, 0, 0, 1, 0, 0)
11687 }
11688 return true;
11689}
11690
11691// Native: zp_make_user_survivor
11692public native_make_user_survivor(id)
11693{
11694 // ZP disabled
11695 if (!g_pluginenabled)
11696 return false;
11697
11698 if (!is_user_valid_alive(id))
11699 {
11700 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11701 return false;
11702 }
11703
11704 // Not allowed to be survivor
11705 if (!allowed_survivor(id))
11706 return false;
11707
11708 // New round?
11709 if (g_newround)
11710 {
11711 // Set as first survivor
11712 remove_task(TASK_MAKEZOMBIE)
11713 make_a_zombie(MODE_SURVIVOR, id)
11714 }
11715 else
11716 {
11717 // Turn player into a Survivor
11718 humanme(id, 1, 0, 0)
11719 }
11720
11721 return true;
11722}
11723
11724// Native: zp_make_user_sniper
11725public native_make_user_sniper(id)
11726{
11727 // ZP disabled
11728 if (!g_pluginenabled)
11729 return false;
11730
11731 if (!is_user_valid_alive(id))
11732 {
11733 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11734 return false;
11735 }
11736
11737 // Not allowed to be sniper
11738 if (!allowed_sniper(id))
11739 return false;
11740
11741 // New round?
11742 if (g_newround)
11743 {
11744 // Set as first sniper
11745 remove_task(TASK_MAKEZOMBIE)
11746 make_a_zombie(MODE_SNIPER, id)
11747 }
11748 else
11749 {
11750 // Turn player into a Sniper
11751 humanme(id, 0, 1, 0)
11752 }
11753
11754 return true;
11755}
11756
11757// Native: zp_respawn_user
11758public native_respawn_user(id, team)
11759{
11760 // ZP disabled
11761 if (!g_pluginenabled)
11762 return false;
11763
11764 if (!is_user_valid_connected(id))
11765 {
11766 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11767 return false;
11768 }
11769
11770 // Respawn not allowed
11771 if (!allowed_respawn(id))
11772 return false;
11773
11774 // Respawn as zombie?
11775 g_respawn_as_zombie[id] = (team == ZP_TEAM_ZOMBIE) ? true : false
11776
11777 // Respawnish!
11778 respawn_player_manually(id)
11779 return true;
11780}
11781
11782// Native: zp_force_buy_extra_item
11783public native_force_buy_extra_item(id, itemid, ignorecost)
11784{
11785 // ZP disabled
11786 if (!g_pluginenabled)
11787 return false;
11788
11789 if (!is_user_valid_alive(id))
11790 {
11791 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11792 return false;
11793 }
11794
11795 if (itemid < 0 || itemid >= g_extraitem_i)
11796 {
11797 log_error(AMX_ERR_NATIVE, "[ZP] Invalid extra item id (%d)", itemid)
11798 return false;
11799 }
11800
11801 buy_extra_item(id, itemid, ignorecost)
11802 return true;
11803}
11804
11805// Native: zp_override_user_model
11806public native_override_user_model(id, const newmodel[], modelindex)
11807{
11808 // ZP disabled
11809 if (!g_pluginenabled)
11810 return false;
11811
11812 if (!is_user_valid_connected(id))
11813 {
11814 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11815 return false;
11816 }
11817
11818 // Strings passed byref
11819 param_convert(2)
11820
11821 // Remove previous tasks
11822 remove_task(id+TASK_MODEL)
11823
11824 // Custom models stuff
11825 static currentmodel[32]
11826
11827 if (g_handle_models_on_separate_ent)
11828 {
11829 // Set the right model
11830 copy(g_playermodel[id], charsmax(g_playermodel[]), newmodel)
11831 if (g_set_modelindex_offset && modelindex) fm_cs_set_user_model_index(id, modelindex)
11832
11833 // Set model on player model entity
11834 fm_set_playermodel_ent(id)
11835 }
11836 else
11837 {
11838 // Get current model for comparing it with the current one
11839 fm_cs_get_user_model(id, currentmodel, charsmax(currentmodel))
11840
11841 // Set the right model, after checking that we don't already have it
11842 if (!equal(currentmodel, newmodel))
11843 {
11844 copy(g_playermodel[id], charsmax(g_playermodel[]), newmodel)
11845 if (g_set_modelindex_offset && modelindex) fm_cs_set_user_model_index(id, modelindex)
11846
11847 // An additional delay is offset at round start
11848 // since SVC_BAD is more likely to be triggered there
11849 if (g_newround)
11850 set_task(5.0 * g_modelchange_delay, "fm_user_model_update", id+TASK_MODEL)
11851 else
11852 fm_user_model_update(id+TASK_MODEL)
11853 }
11854 }
11855 return true;
11856}
11857
11858// Native: zp_get_user_model
11859public native_get_user_model(plugin_id, param_nums)
11860{
11861 // ZPA disabled
11862 if (!g_pluginenabled)
11863 return -1;
11864
11865 // Insufficient number of arguments
11866 if (param_nums != 3)
11867 return -1;
11868
11869 // Retrieve the player's index
11870 static id; id = get_param(1)
11871
11872 // Not an alive player or invalid player
11873 if (!is_user_valid_alive(id))
11874 return 0;
11875
11876 // Retrieve the player's current model
11877 static current_model[32]
11878 fm_cs_get_user_model(id, current_model, charsmax(current_model))
11879
11880 // Copy the model name into the array passed
11881 set_string(2, current_model, get_param(3))
11882
11883 return 1;
11884}
11885
11886// Native: zp_set_user_model
11887public native_set_user_model(id, const model[])
11888{
11889 // ZPA disabled
11890 if (!g_pluginenabled)
11891 return -1;
11892
11893 // Not an alive player or invalid player
11894 if (!is_user_valid_alive(id))
11895 return -1;
11896
11897 // Strings passed byref
11898 param_convert(2)
11899
11900 // Retrieve the player's current model
11901 static current_model[32]
11902 fm_cs_get_user_model(id, current_model, charsmax(current_model))
11903
11904 // Check whether we already have the model set on the player
11905 if (equal(current_model, model))
11906 return 0;
11907
11908 // Update player's model
11909 copy(g_playermodel[id], charsmax(g_playermodel[]), model)
11910
11911 // Set the right model for the player
11912 if (g_handle_models_on_separate_ent) fm_set_playermodel_ent(id)
11913 else fm_user_model_update(id+TASK_MODEL)
11914
11915 return 1;
11916}
11917
11918// Native: zp_has_round_started
11919public native_has_round_started()
11920{
11921 if (g_newround) return 0; // not started
11922 if (g_modestarted) return 1; // started
11923 return 2; // starting
11924}
11925
11926// Native: zp_is_nemesis_round
11927public native_is_nemesis_round()
11928{
11929 return g_nemround;
11930}
11931
11932// Native: zp_is_assassin_round
11933public native_is_assassin_round()
11934{
11935 return g_assaround;
11936}
11937
11938// Native: zp_is_survivor_round
11939public native_is_survivor_round()
11940{
11941 return g_survround;
11942}
11943
11944// Native: zp_is_sniper_round
11945public native_is_sniper_round()
11946{
11947 return g_sniround;
11948}
11949
11950// Native: zp_is_swarm_round
11951public native_is_swarm_round()
11952{
11953 return g_swarmround;
11954}
11955
11956// Native: zp_is_plague_round
11957public native_is_plague_round()
11958{
11959 return g_plagueround;
11960}
11961
11962// Native: zp_is_armageddon_round
11963public native_is_armageddon_round()
11964{
11965 return g_armageround;
11966}
11967
11968// Native: zp_is_apocalypse_round
11969public native_is_apocalypse_round()
11970{
11971 return g_apocround;
11972}
11973
11974// Native: zp_is_nightmare_round
11975public native_is_nightmare_round()
11976{
11977 return g_nightround;
11978}
11979
11980// Native: zp_get_zombie_count
11981public native_get_zombie_count()
11982{
11983 return fnGetZombies();
11984}
11985
11986// Native: zp_get_human_count
11987public native_get_human_count()
11988{
11989 return fnGetHumans();
11990}
11991
11992// Native: zp_get_nemesis_count
11993public native_get_nemesis_count()
11994{
11995 return fnGetNemesis();
11996}
11997
11998// Native: zp_get_assassin_count
11999public native_get_assassin_count()
12000{
12001 return fnGetAssassin();
12002}
12003
12004// Native: zp_get_survivor_count
12005public native_get_survivor_count()
12006{
12007 return fnGetSurvivors();
12008}
12009
12010// Native: zp_get_sniper_count
12011public native_get_sniper_count()
12012{
12013 return fnGetSnipers();
12014}
12015
12016// Native: zp_register_extra_item
12017public native_register_extra_item(const name[], cost, team)
12018{
12019 // ZP disabled
12020 if (!g_pluginenabled)
12021 return -1;
12022
12023 // Strings passed byref
12024 param_convert(1)
12025
12026 // Arrays not yet initialized
12027 if (!g_arrays_created)
12028 {
12029 log_error(AMX_ERR_NATIVE, "[ZP] Can't register extra item yet (%s)", name)
12030 return -1;
12031 }
12032
12033 if (strlen(name) < 1)
12034 {
12035 log_error(AMX_ERR_NATIVE, "[ZP] Can't register extra item with an empty name")
12036 return -1;
12037 }
12038
12039 new index, extraitem_name[32]
12040 for (index = 0; index < g_extraitem_i; index++)
12041 {
12042 ArrayGetString(g_extraitem_name, index, extraitem_name, charsmax(extraitem_name))
12043 if (equali(name, extraitem_name))
12044 {
12045 log_error(AMX_ERR_NATIVE, "[ZP] Extra item already registered (%s)", name)
12046 return -1;
12047 }
12048 }
12049
12050 // For backwards compatibility
12051 if (team == ZP_TEAM_ANY)
12052 team = (ZP_TEAM_ZOMBIE|ZP_TEAM_HUMAN)
12053
12054 // Add the item
12055 ArrayPushString(g_extraitem_name, name)
12056 ArrayPushCell(g_extraitem_cost, cost)
12057 ArrayPushCell(g_extraitem_team, team)
12058
12059 // Set temporary new item flag
12060 ArrayPushCell(g_extraitem_new, 1)
12061
12062 // Override extra items data with our customizations
12063 new i, buffer[32], size = ArraySize(g_extraitem2_realname)
12064 for (i = 0; i < size; i++)
12065 {
12066 ArrayGetString(g_extraitem2_realname, i, buffer, charsmax(buffer))
12067
12068 // Check if this is the intended item to override
12069 if (!equal(name, buffer))
12070 continue;
12071
12072 // Remove new item flag
12073 ArraySetCell(g_extraitem_new, g_extraitem_i, 0)
12074
12075 // Replace caption
12076 ArrayGetString(g_extraitem2_name, i, buffer, charsmax(buffer))
12077 ArraySetString(g_extraitem_name, g_extraitem_i, buffer)
12078
12079 // Replace cost
12080 buffer[0] = ArrayGetCell(g_extraitem2_cost, i)
12081 ArraySetCell(g_extraitem_cost, g_extraitem_i, buffer[0])
12082
12083 // Replace team
12084 buffer[0] = ArrayGetCell(g_extraitem2_team, i)
12085 ArraySetCell(g_extraitem_team, g_extraitem_i, buffer[0])
12086 }
12087
12088 // Increase registered items counter
12089 g_extraitem_i++
12090
12091 // Return id under which we registered the item
12092 return g_extraitem_i-1;
12093}
12094
12095// Function: zp_register_extra_item (to be used within this plugin only)
12096native_register_extra_item2(const name[], cost, team)
12097{
12098 // Add the item
12099 ArrayPushString(g_extraitem_name, name)
12100 ArrayPushCell(g_extraitem_cost, cost)
12101 ArrayPushCell(g_extraitem_team, team)
12102
12103 // Set temporary new item flag
12104 ArrayPushCell(g_extraitem_new, 1)
12105
12106 // Increase registered items counter
12107 g_extraitem_i++
12108}
12109
12110// Native: zp_register_zombie_class
12111public native_register_zombie_class(const name[], const info[], const model[], const clawmodel[], hp, speed, Float:gravity, Float:knockback)
12112{
12113 // ZP disabled
12114 if (!g_pluginenabled)
12115 return -1;
12116
12117 // Strings passed byref
12118 param_convert(1)
12119 param_convert(2)
12120 param_convert(3)
12121 param_convert(4)
12122
12123 // Arrays not yet initialized
12124 if (!g_arrays_created)
12125 {
12126 log_error(AMX_ERR_NATIVE, "[ZP] Can't register zombie class yet (%s)", name)
12127 return -1;
12128 }
12129
12130 if (strlen(name) < 1)
12131 {
12132 log_error(AMX_ERR_NATIVE, "[ZP] Can't register zombie class with an empty name")
12133 return -1;
12134 }
12135
12136 new index, zombieclass_name[32]
12137 for (index = 0; index < g_zclass_i; index++)
12138 {
12139 ArrayGetString(g_zclass_name, index, zombieclass_name, charsmax(zombieclass_name))
12140 if (equali(name, zombieclass_name))
12141 {
12142 log_error(AMX_ERR_NATIVE, "[ZP] Zombie class already registered (%s)", name)
12143 return -1;
12144 }
12145 }
12146
12147 // Add the class
12148 ArrayPushString(g_zclass_name, name)
12149 ArrayPushString(g_zclass_info, info)
12150
12151 // Using same zombie models for all classes?
12152 if (g_same_models_for_all)
12153 {
12154 ArrayPushCell(g_zclass_modelsstart, 0)
12155 ArrayPushCell(g_zclass_modelsend, ArraySize(g_zclass_playermodel))
12156 }
12157 else
12158 {
12159 ArrayPushCell(g_zclass_modelsstart, ArraySize(g_zclass_playermodel))
12160 ArrayPushString(g_zclass_playermodel, model)
12161 ArrayPushCell(g_zclass_modelsend, ArraySize(g_zclass_playermodel))
12162 ArrayPushCell(g_zclass_modelindex, -1)
12163 }
12164
12165 ArrayPushString(g_zclass_clawmodel, clawmodel)
12166 ArrayPushCell(g_zclass_hp, hp)
12167 ArrayPushCell(g_zclass_spd, speed)
12168 ArrayPushCell(g_zclass_grav, gravity)
12169 ArrayPushCell(g_zclass_kb, knockback)
12170
12171 // Set temporary new class flag
12172 ArrayPushCell(g_zclass_new, 1)
12173
12174 // Override zombie classes data with our customizations
12175 new i, k, buffer[32], Float:buffer2, nummodels_custom, nummodels_default, prec_mdl[100], size = ArraySize(g_zclass2_realname)
12176 for (i = 0; i < size; i++)
12177 {
12178 ArrayGetString(g_zclass2_realname, i, buffer, charsmax(buffer))
12179
12180 // Check if this is the intended class to override
12181 if (!equal(name, buffer))
12182 continue;
12183
12184 // Remove new class flag
12185 ArraySetCell(g_zclass_new, g_zclass_i, 0)
12186
12187 // Replace caption
12188 ArrayGetString(g_zclass2_name, i, buffer, charsmax(buffer))
12189 ArraySetString(g_zclass_name, g_zclass_i, buffer)
12190
12191 // Replace info
12192 ArrayGetString(g_zclass2_info, i, buffer, charsmax(buffer))
12193 ArraySetString(g_zclass_info, g_zclass_i, buffer)
12194
12195 // Replace models, unless using same models for all classes
12196 if (!g_same_models_for_all)
12197 {
12198 nummodels_custom = ArrayGetCell(g_zclass2_modelsend, i) - ArrayGetCell(g_zclass2_modelsstart, i)
12199 nummodels_default = ArrayGetCell(g_zclass_modelsend, g_zclass_i) - ArrayGetCell(g_zclass_modelsstart, g_zclass_i)
12200
12201 // Replace each player model and model index
12202 for (k = 0; k < min(nummodels_custom, nummodels_default); k++)
12203 {
12204 ArrayGetString(g_zclass2_playermodel, ArrayGetCell(g_zclass2_modelsstart, i) + k, buffer, charsmax(buffer))
12205 ArraySetString(g_zclass_playermodel, ArrayGetCell(g_zclass_modelsstart, g_zclass_i) + k, buffer)
12206
12207 // Precache player model and replace its modelindex with the real one
12208 formatex(prec_mdl, charsmax(prec_mdl), "models/player/%s/%s.mdl", buffer, buffer)
12209 ArraySetCell(g_zclass_modelindex, ArrayGetCell(g_zclass_modelsstart, g_zclass_i) + k, engfunc(EngFunc_PrecacheModel, prec_mdl))
12210 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, prec_mdl)
12211 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, prec_mdl)
12212 // Precache modelT.mdl files too
12213 copy(prec_mdl[strlen(prec_mdl)-4], charsmax(prec_mdl) - (strlen(prec_mdl)-4), "T.mdl")
12214 if (file_exists(prec_mdl)) engfunc(EngFunc_PrecacheModel, prec_mdl)
12215 }
12216
12217 // We have more custom models than what we can accommodate,
12218 // Let's make some space...
12219 if (nummodels_custom > nummodels_default)
12220 {
12221 for (k = nummodels_default; k < nummodels_custom; k++)
12222 {
12223 ArrayGetString(g_zclass2_playermodel, ArrayGetCell(g_zclass2_modelsstart, i) + k, buffer, charsmax(buffer))
12224 ArrayInsertStringAfter(g_zclass_playermodel, ArrayGetCell(g_zclass_modelsstart, g_zclass_i) + k - 1, buffer)
12225
12226 // Precache player model and retrieve its modelindex
12227 formatex(prec_mdl, charsmax(prec_mdl), "models/player/%s/%s.mdl", buffer, buffer)
12228 ArrayInsertCellAfter(g_zclass_modelindex, ArrayGetCell(g_zclass_modelsstart, g_zclass_i) + k - 1, engfunc(EngFunc_PrecacheModel, prec_mdl))
12229 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, prec_mdl)
12230 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, prec_mdl)
12231 // Precache modelT.mdl files too
12232 copy(prec_mdl[strlen(prec_mdl)-4], charsmax(prec_mdl) - (strlen(prec_mdl)-4), "T.mdl")
12233 if (file_exists(prec_mdl)) engfunc(EngFunc_PrecacheModel, prec_mdl)
12234 }
12235
12236 // Fix models end index for this class
12237 ArraySetCell(g_zclass_modelsend, g_zclass_i, ArrayGetCell(g_zclass_modelsend, g_zclass_i) + (nummodels_custom - nummodels_default))
12238 }
12239
12240 /* --- Not needed since classes can't have more than 1 default model for now ---
12241 // We have less custom models than what this class has by default,
12242 // Get rid of those extra entries...
12243 if (nummodels_custom < nummodels_default)
12244 {
12245 for (k = nummodels_custom; k < nummodels_default; k++)
12246 {
12247 ArrayDeleteItem(g_zclass_playermodel, ArrayGetCell(g_zclass_modelsstart, g_zclass_i) + nummodels_custom)
12248 }
12249
12250 // Fix models end index for this class
12251 ArraySetCell(g_zclass_modelsend, g_zclass_i, ArrayGetCell(g_zclass_modelsend, g_zclass_i) - (nummodels_default - nummodels_custom))
12252 }
12253 */
12254 }
12255
12256 // Replace clawmodel
12257 ArrayGetString(g_zclass2_clawmodel, i, buffer, charsmax(buffer))
12258 ArraySetString(g_zclass_clawmodel, g_zclass_i, buffer)
12259
12260 // Precache clawmodel
12261 formatex(prec_mdl, charsmax(prec_mdl), "models/zombie_plague/%s", buffer)
12262 engfunc(EngFunc_PrecacheModel, prec_mdl)
12263
12264 // Replace health
12265 buffer[0] = ArrayGetCell(g_zclass2_hp, i)
12266 ArraySetCell(g_zclass_hp, g_zclass_i, buffer[0])
12267
12268 // Replace speed
12269 buffer[0] = ArrayGetCell(g_zclass2_spd, i)
12270 ArraySetCell(g_zclass_spd, g_zclass_i, buffer[0])
12271
12272 // Replace gravity
12273 buffer2 = Float:ArrayGetCell(g_zclass2_grav, i)
12274 ArraySetCell(g_zclass_grav, g_zclass_i, buffer2)
12275
12276 // Replace knockback
12277 buffer2 = Float:ArrayGetCell(g_zclass2_kb, i)
12278 ArraySetCell(g_zclass_kb, g_zclass_i, buffer2)
12279 }
12280
12281 // If class was not overriden with customization data
12282 if (ArrayGetCell(g_zclass_new, g_zclass_i))
12283 {
12284 // If not using same models for all classes
12285 if (!g_same_models_for_all)
12286 {
12287 // Precache default class model and replace modelindex with the real one
12288 formatex(prec_mdl, charsmax(prec_mdl), "models/player/%s/%s.mdl", model, model)
12289 ArraySetCell(g_zclass_modelindex, ArrayGetCell(g_zclass_modelsstart, g_zclass_i), engfunc(EngFunc_PrecacheModel, prec_mdl))
12290 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, prec_mdl)
12291 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, prec_mdl)
12292 // Precache modelT.mdl files too
12293 copy(prec_mdl[strlen(prec_mdl)-4], charsmax(prec_mdl) - (strlen(prec_mdl)-4), "T.mdl")
12294 if (file_exists(prec_mdl)) engfunc(EngFunc_PrecacheModel, prec_mdl)
12295 }
12296
12297 // Precache default clawmodel
12298 formatex(prec_mdl, charsmax(prec_mdl), "models/zombie_plague/%s", clawmodel)
12299 engfunc(EngFunc_PrecacheModel, prec_mdl)
12300 }
12301
12302 // Increase registered classes counter
12303 g_zclass_i++
12304
12305 // Return id under which we registered the class
12306 return g_zclass_i-1;
12307}
12308
12309// Native: zp_get_extra_item_id
12310public native_get_extra_item_id(const name[])
12311{
12312 // ZP disabled
12313 if (!g_pluginenabled)
12314 return -1;
12315
12316 // Strings passed byref
12317 param_convert(1)
12318
12319 // Loop through every item (not using Tries since ZP should work on AMXX 1.8.0)
12320 static i, item_name[32]
12321 for (i = 0; i < g_extraitem_i; i++)
12322 {
12323 ArrayGetString(g_extraitem_name, i, item_name, charsmax(item_name))
12324
12325 // Check if this is the item to retrieve
12326 if (equali(name, item_name))
12327 return i;
12328 }
12329
12330 return -1;
12331}
12332
12333// Native: zp_get_zombie_class_id
12334public native_get_zombie_class_id(const name[])
12335{
12336 // ZP disabled
12337 if (!g_pluginenabled)
12338 return -1;
12339
12340 // Strings passed byref
12341 param_convert(1)
12342
12343 // Loop through every class (not using Tries since ZP should work on AMXX 1.8.0)
12344 static i, class_name[32]
12345 for (i = 0; i < g_zclass_i; i++)
12346 {
12347 ArrayGetString(g_zclass_name, i, class_name, charsmax(class_name))
12348
12349 // Check if this is the class to retrieve
12350 if (equali(name, class_name))
12351 return i;
12352 }
12353
12354 return -1;
12355}
12356
12357// Native: zp_get_zombie_class_info
12358public native_get_zombie_class_info(classid, info[], len)
12359{
12360 // ZP disabled
12361 if (!g_pluginenabled)
12362 return false;
12363
12364 // Invalid class
12365 if (classid < 0 || classid >= g_zclass_i)
12366 {
12367 log_error(AMX_ERR_NATIVE, "[ZP] Invalid zombie class id (%d)", classid)
12368 return false;
12369 }
12370
12371 // Strings passed byref
12372 param_convert(2)
12373
12374 // Fetch zombie class info
12375 ArrayGetString(g_zclass_info, classid, info, len)
12376 return true;
12377}
12378
12379/*================================================================================
12380 [Custom Messages]
12381=================================================================================*/
12382
12383// Custom Night Vision
12384public set_user_nvision(taskid)
12385{
12386 // Get player's origin
12387 static origin[3]
12388 get_user_origin(ID_NVISION, origin)
12389
12390 // Nightvision message
12391 message_begin(MSG_ONE_UNRELIABLE, SVC_TEMPENTITY, _, ID_NVISION)
12392 write_byte(TE_DLIGHT) // TE id
12393 write_coord(origin[0]) // x
12394 write_coord(origin[1]) // y
12395 write_coord(origin[2]) // z
12396 write_byte(get_pcvar_num(cvar_nvgsize)) // radius
12397
12398 // Nemesis / Madness / Spectator in nemesis round
12399 if (g_nemesis[ID_NVISION] || (g_zombie[ID_NVISION] && g_nodamage[ID_NVISION]) || (!g_isalive[ID_NVISION] && g_nemround))
12400 {
12401 write_byte(get_pcvar_num(cvar_nemnvgcolor[0])) // r
12402 write_byte(get_pcvar_num(cvar_nemnvgcolor[1])) // g
12403 write_byte(get_pcvar_num(cvar_nemnvgcolor[2])) // b
12404 }
12405 // Assassin / Spectator in assassin round
12406 else if (g_assassin[ID_NVISION] || (!g_isalive[ID_NVISION] && g_assaround))
12407 {
12408 write_byte(get_pcvar_num(cvar_assanvgcolor[0])) // r
12409 write_byte(get_pcvar_num(cvar_assanvgcolor[1])) // g
12410 write_byte(get_pcvar_num(cvar_assanvgcolor[2])) // b
12411 }
12412 // Human / Spectator in normal round
12413 else if (!g_zombie[ID_NVISION] || !g_isalive[ID_NVISION])
12414 {
12415 write_byte(get_pcvar_num(cvar_humnvgcolor[0])) // r
12416 write_byte(get_pcvar_num(cvar_humnvgcolor[1])) // g
12417 write_byte(get_pcvar_num(cvar_humnvgcolor[2])) // b
12418 }
12419 // Zombie
12420 else
12421 {
12422 write_byte(get_pcvar_num(cvar_nvgcolor[0])) // r
12423 write_byte(get_pcvar_num(cvar_nvgcolor[1])) // g
12424 write_byte(get_pcvar_num(cvar_nvgcolor[2])) // b
12425 }
12426
12427 write_byte(2) // life
12428 write_byte(0) // decay rate
12429 message_end()
12430}
12431
12432// Game Nightvision
12433set_user_gnvision(id, toggle)
12434{
12435 // Toggle NVG message
12436 message_begin(MSG_ONE, g_msgNVGToggle, _, id)
12437 write_byte(toggle) // toggle
12438 message_end()
12439}
12440
12441// Custom Flashlight
12442public set_user_flashlight(taskid)
12443{
12444 // Get player and aiming origins
12445 static Float:originF[3], Float:destoriginF[3]
12446 pev(ID_FLASH, pev_origin, originF)
12447 fm_get_aim_origin(ID_FLASH, destoriginF)
12448
12449 // Max distance check
12450 if (get_distance_f(originF, destoriginF) > get_pcvar_float(cvar_flashdist))
12451 return;
12452
12453 // Send to all players?
12454 if (get_pcvar_num(cvar_flashshowall))
12455 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, destoriginF, 0)
12456 else
12457 message_begin(MSG_ONE_UNRELIABLE, SVC_TEMPENTITY, _, ID_FLASH)
12458
12459 // Flashlight
12460 write_byte(TE_DLIGHT) // TE id
12461 engfunc(EngFunc_WriteCoord, destoriginF[0]) // x
12462 engfunc(EngFunc_WriteCoord, destoriginF[1]) // y
12463 engfunc(EngFunc_WriteCoord, destoriginF[2]) // z
12464 write_byte(get_pcvar_num(cvar_flashsize)) // radius
12465 write_byte(get_pcvar_num(cvar_flashcolor[0])) // r
12466 write_byte(get_pcvar_num(cvar_flashcolor[1])) // g
12467 write_byte(get_pcvar_num(cvar_flashcolor[2])) // b
12468 write_byte(3) // life
12469 write_byte(0) // decay rate
12470 message_end()
12471}
12472
12473// Infection special effects
12474infection_effects(id)
12475{
12476 // Screen fade? (unless frozen)
12477 if (!g_frozen[id] && get_pcvar_num(cvar_infectionscreenfade))
12478 {
12479 message_begin(MSG_ONE_UNRELIABLE, g_msgScreenFade, _, id)
12480 write_short(UNIT_SECOND) // duration
12481 write_short(0) // hold time
12482 write_short(FFADE_IN) // fade type
12483 if (g_nemesis[id])
12484 {
12485 write_byte(get_pcvar_num(cvar_nemnvgcolor[0])) // r
12486 write_byte(get_pcvar_num(cvar_nemnvgcolor[1])) // g
12487 write_byte(get_pcvar_num(cvar_nemnvgcolor[2])) // b
12488 }
12489 else if (g_assassin[id])
12490 {
12491 write_byte(get_pcvar_num(cvar_assanvgcolor[0])) // r
12492 write_byte(get_pcvar_num(cvar_assanvgcolor[1])) // g
12493 write_byte(get_pcvar_num(cvar_assanvgcolor[2])) // b
12494 }
12495 else
12496 {
12497 write_byte(get_pcvar_num(cvar_nvgcolor[0])) // r
12498 write_byte(get_pcvar_num(cvar_nvgcolor[1])) // g
12499 write_byte(get_pcvar_num(cvar_nvgcolor[2])) // b
12500 }
12501 write_byte (255) // alpha
12502 message_end()
12503 }
12504
12505 // Screen shake?
12506 if (get_pcvar_num(cvar_infectionscreenshake))
12507 {
12508 message_begin(MSG_ONE_UNRELIABLE, g_msgScreenShake, _, id)
12509 write_short(UNIT_SECOND*4) // amplitude
12510 write_short(UNIT_SECOND*2) // duration
12511 write_short(UNIT_SECOND*10) // frequency
12512 message_end()
12513 }
12514
12515 // Infection icon?
12516 if (get_pcvar_num(cvar_hudicons))
12517 {
12518 message_begin(MSG_ONE_UNRELIABLE, g_msgDamage, _, id)
12519 write_byte(0) // damage save
12520 write_byte(0) // damage take
12521 write_long(DMG_NERVEGAS) // damage type - DMG_RADIATION
12522 write_coord(0) // x
12523 write_coord(0) // y
12524 write_coord(0) // z
12525 message_end()
12526 }
12527
12528 // Get player's origin
12529 static origin[3]
12530 get_user_origin(id, origin)
12531
12532 // Tracers?
12533 if (get_pcvar_num(cvar_infectiontracers))
12534 {
12535 message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
12536 write_byte(TE_IMPLOSION) // TE id
12537 write_coord(origin[0]) // x
12538 write_coord(origin[1]) // y
12539 write_coord(origin[2]) // z
12540 write_byte(128) // radius
12541 write_byte(20) // count
12542 write_byte(3) // duration
12543 message_end()
12544 }
12545
12546 // Particle burst?
12547 if (get_pcvar_num(cvar_infectionparticles))
12548 {
12549 message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
12550 write_byte(TE_PARTICLEBURST) // TE id
12551 write_coord(origin[0]) // x
12552 write_coord(origin[1]) // y
12553 write_coord(origin[2]) // z
12554 write_short(50) // radius
12555 write_byte(70) // color
12556 write_byte(3) // duration (will be randomized a bit)
12557 message_end()
12558 }
12559
12560 // Light sparkle?
12561 if (get_pcvar_num(cvar_infectionsparkle))
12562 {
12563 message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
12564 write_byte(TE_DLIGHT) // TE id
12565 write_coord(origin[0]) // x
12566 write_coord(origin[1]) // y
12567 write_coord(origin[2]) // z
12568 write_byte(20) // radius
12569 write_byte(get_pcvar_num(cvar_nvgcolor[0])) // r
12570 write_byte(get_pcvar_num(cvar_nvgcolor[1])) // g
12571 write_byte(get_pcvar_num(cvar_nvgcolor[2])) // b
12572 write_byte(2) // life
12573 write_byte(0) // decay rate
12574 message_end()
12575 }
12576}
12577
12578// Nemesis/madness aura task
12579public zombie_aura(taskid)
12580{
12581 // Not nemesis, not assassin, not in zombie madness
12582 if (!g_nemesis[ID_AURA] && !g_assassin[ID_AURA] && !g_nodamage[ID_AURA])
12583 {
12584 // Task not needed anymore
12585 remove_task(taskid);
12586 return;
12587 }
12588
12589 // Get player's origin
12590 static origin[3]
12591 get_user_origin(ID_AURA, origin)
12592
12593 // Colored Aura
12594 message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
12595 write_byte(TE_DLIGHT) // TE id
12596 write_coord(origin[0]) // x
12597 write_coord(origin[1]) // y
12598 write_coord(origin[2]) // z
12599 write_byte(20) // radius
12600
12601 if (g_assassin[ID_AURA])
12602 {
12603 write_byte(get_pcvar_num(cvar_assanvgcolor[0])) // r
12604 write_byte(get_pcvar_num(cvar_assanvgcolor[1])) // g
12605 write_byte(get_pcvar_num(cvar_assanvgcolor[2])) // b
12606 }
12607 else
12608 {
12609 write_byte(get_pcvar_num(cvar_nemnvgcolor[0])) // r
12610 write_byte(get_pcvar_num(cvar_nemnvgcolor[1])) // g
12611 write_byte(get_pcvar_num(cvar_nemnvgcolor[2])) // b
12612 }
12613
12614 write_byte(2) // life
12615 write_byte(0) // decay rate
12616 message_end()
12617}
12618
12619// Make zombies leave footsteps and bloodstains on the floor
12620public make_blood(taskid)
12621{
12622 // Only bleed when moving on ground
12623 if (!(pev(ID_BLOOD, pev_flags) & FL_ONGROUND) || fm_get_speed(ID_BLOOD) < 80)
12624 return;
12625
12626 // Get user origin
12627 static Float:originF[3]
12628 pev(ID_BLOOD, pev_origin, originF)
12629
12630 // If ducking set a little lower
12631 if (pev(ID_BLOOD, pev_bInDuck))
12632 originF[2] -= 18.0
12633 else
12634 originF[2] -= 36.0
12635
12636 // Send the decal message
12637 engfunc(EngFunc_MessageBegin, MSG_PAS, SVC_TEMPENTITY, originF, 0)
12638 write_byte(TE_WORLDDECAL) // TE id
12639 engfunc(EngFunc_WriteCoord, originF[0]) // x
12640 engfunc(EngFunc_WriteCoord, originF[1]) // y
12641 engfunc(EngFunc_WriteCoord, originF[2]) // z
12642 write_byte(ArrayGetCell(zombie_decals, random_num(0, ArraySize(zombie_decals) - 1)) + (g_czero * 12)) // random decal number (offsets +12 for CZ)
12643 message_end()
12644}
12645
12646// Flare Lighting Effects
12647flare_lighting(entity, duration)
12648{
12649 // Get origin and color
12650 static Float:originF[3], color[3]
12651 pev(entity, pev_origin, originF)
12652 pev(entity, PEV_FLARE_COLOR, color)
12653
12654 // Lighting
12655 engfunc(EngFunc_MessageBegin, MSG_PAS, SVC_TEMPENTITY, originF, 0)
12656 write_byte(TE_DLIGHT) // TE id
12657 engfunc(EngFunc_WriteCoord, originF[0]) // x
12658 engfunc(EngFunc_WriteCoord, originF[1]) // y
12659 engfunc(EngFunc_WriteCoord, originF[2]) // z
12660 write_byte(get_pcvar_num(cvar_flaresize)) // radius
12661 write_byte(color[0]) // r
12662 write_byte(color[1]) // g
12663 write_byte(color[2]) // b
12664 write_byte(21) //life
12665 write_byte((duration < 2) ? 3 : 0) //decay rate
12666 message_end()
12667
12668 // Sparks
12669 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12670 write_byte(TE_SPARKS) // TE id
12671 engfunc(EngFunc_WriteCoord, originF[0]) // x
12672 engfunc(EngFunc_WriteCoord, originF[1]) // y
12673 engfunc(EngFunc_WriteCoord, originF[2]) // z
12674 message_end()
12675}
12676
12677// Burning Flames
12678public burning_flame(taskid)
12679{
12680 // Get player origin and flags
12681 static origin[3], flags
12682 get_user_origin(ID_BURN, origin)
12683 flags = pev(ID_BURN, pev_flags)
12684
12685 // Madness mode - in water - burning stopped
12686 if (g_nodamage[ID_BURN] || (flags & FL_INWATER) || g_burning_duration[ID_BURN] < 1)
12687 {
12688 // Smoke sprite
12689 message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
12690 write_byte(TE_SMOKE) // TE id
12691 write_coord(origin[0]) // x
12692 write_coord(origin[1]) // y
12693 write_coord(origin[2]-50) // z
12694 write_short(g_smokeSpr) // sprite
12695 write_byte(random_num(15, 20)) // scale
12696 write_byte(random_num(10, 20)) // framerate
12697 message_end()
12698
12699 // Task not needed anymore
12700 remove_task(taskid);
12701 return;
12702 }
12703
12704 // Randomly play burning zombie scream sounds (not for nemesis)
12705 if (!g_nemesis[ID_BURN] && !g_assassin[ID_BURN] && !random_num(0, 20))
12706 {
12707 static sound[64]
12708 ArrayGetString(grenade_fire_player, random_num(0, ArraySize(grenade_fire_player) - 1), sound, charsmax(sound))
12709 emit_sound(ID_BURN, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
12710 }
12711
12712 // Fire slow down, unless nemesis
12713 if (!g_nemesis[ID_BURN] && !g_assassin[ID_BURN] && (flags & FL_ONGROUND) && get_pcvar_float(cvar_fireslowdown) > 0.0)
12714 {
12715 static Float:velocity[3]
12716 pev(ID_BURN, pev_velocity, velocity)
12717 xs_vec_mul_scalar(velocity, get_pcvar_float(cvar_fireslowdown), velocity)
12718 set_pev(ID_BURN, pev_velocity, velocity)
12719 }
12720
12721 // Get player's health
12722 static health
12723 health = pev(ID_BURN, pev_health)
12724
12725 // Take damage from the fire
12726 if (health - floatround(get_pcvar_float(cvar_firedamage), floatround_ceil) > 0)
12727 fm_set_user_health(ID_BURN, health - floatround(get_pcvar_float(cvar_firedamage), floatround_ceil))
12728
12729 // Flame sprite
12730 message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
12731 write_byte(TE_SPRITE) // TE id
12732 write_coord(origin[0]+random_num(-5, 5)) // x
12733 write_coord(origin[1]+random_num(-5, 5)) // y
12734 write_coord(origin[2]+random_num(-10, 10)) // z
12735 write_short(g_flameSpr) // sprite
12736 write_byte(random_num(5, 10)) // scale
12737 write_byte(200) // brightness
12738 message_end()
12739
12740 // Decrease burning duration counter
12741 g_burning_duration[ID_BURN]--
12742}
12743
12744// Infection Bomb: Green Blast
12745create_blast(const Float:originF[3])
12746{
12747 // Smallest ring
12748 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12749 write_byte(TE_BEAMCYLINDER) // TE id
12750 engfunc(EngFunc_WriteCoord, originF[0]) // x
12751 engfunc(EngFunc_WriteCoord, originF[1]) // y
12752 engfunc(EngFunc_WriteCoord, originF[2]) // z
12753 engfunc(EngFunc_WriteCoord, originF[0]) // x axis
12754 engfunc(EngFunc_WriteCoord, originF[1]) // y axis
12755 engfunc(EngFunc_WriteCoord, originF[2]+385.0) // z axis
12756 write_short(g_exploSpr) // sprite
12757 write_byte(0) // startframe
12758 write_byte(0) // framerate
12759 write_byte(4) // life
12760 write_byte(60) // width
12761 write_byte(0) // noise
12762 write_byte(0) // red
12763 write_byte(200) // green
12764 write_byte(0) // blue
12765 write_byte(200) // brightness
12766 write_byte(0) // speed
12767 message_end()
12768
12769 // Medium ring
12770 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12771 write_byte(TE_BEAMCYLINDER) // TE id
12772 engfunc(EngFunc_WriteCoord, originF[0]) // x
12773 engfunc(EngFunc_WriteCoord, originF[1]) // y
12774 engfunc(EngFunc_WriteCoord, originF[2]) // z
12775 engfunc(EngFunc_WriteCoord, originF[0]) // x axis
12776 engfunc(EngFunc_WriteCoord, originF[1]) // y axis
12777 engfunc(EngFunc_WriteCoord, originF[2]+470.0) // z axis
12778 write_short(g_exploSpr) // sprite
12779 write_byte(0) // startframe
12780 write_byte(0) // framerate
12781 write_byte(4) // life
12782 write_byte(60) // width
12783 write_byte(0) // noise
12784 write_byte(0) // red
12785 write_byte(200) // green
12786 write_byte(0) // blue
12787 write_byte(200) // brightness
12788 write_byte(0) // speed
12789 message_end()
12790
12791 // Largest ring
12792 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12793 write_byte(TE_BEAMCYLINDER) // TE id
12794 engfunc(EngFunc_WriteCoord, originF[0]) // x
12795 engfunc(EngFunc_WriteCoord, originF[1]) // y
12796 engfunc(EngFunc_WriteCoord, originF[2]) // z
12797 engfunc(EngFunc_WriteCoord, originF[0]) // x axis
12798 engfunc(EngFunc_WriteCoord, originF[1]) // y axis
12799 engfunc(EngFunc_WriteCoord, originF[2]+555.0) // z axis
12800 write_short(g_exploSpr) // sprite
12801 write_byte(0) // startframe
12802 write_byte(0) // framerate
12803 write_byte(4) // life
12804 write_byte(60) // width
12805 write_byte(0) // noise
12806 write_byte(0) // red
12807 write_byte(200) // green
12808 write_byte(0) // blue
12809 write_byte(200) // brightness
12810 write_byte(0) // speed
12811 message_end()
12812}
12813
12814// Fire Grenade: Fire Blast
12815create_blast2(const Float:originF[3])
12816{
12817 // Smallest ring
12818 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12819 write_byte(TE_BEAMCYLINDER) // TE id
12820 engfunc(EngFunc_WriteCoord, originF[0]) // x
12821 engfunc(EngFunc_WriteCoord, originF[1]) // y
12822 engfunc(EngFunc_WriteCoord, originF[2]) // z
12823 engfunc(EngFunc_WriteCoord, originF[0]) // x axis
12824 engfunc(EngFunc_WriteCoord, originF[1]) // y axis
12825 engfunc(EngFunc_WriteCoord, originF[2]+385.0) // z axis
12826 write_short(g_exploSpr) // sprite
12827 write_byte(0) // startframe
12828 write_byte(0) // framerate
12829 write_byte(4) // life
12830 write_byte(60) // width
12831 write_byte(0) // noise
12832 write_byte(200) // red
12833 write_byte(100) // green
12834 write_byte(0) // blue
12835 write_byte(200) // brightness
12836 write_byte(0) // speed
12837 message_end()
12838
12839 // Medium ring
12840 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12841 write_byte(TE_BEAMCYLINDER) // TE id
12842 engfunc(EngFunc_WriteCoord, originF[0]) // x
12843 engfunc(EngFunc_WriteCoord, originF[1]) // y
12844 engfunc(EngFunc_WriteCoord, originF[2]) // z
12845 engfunc(EngFunc_WriteCoord, originF[0]) // x axis
12846 engfunc(EngFunc_WriteCoord, originF[1]) // y axis
12847 engfunc(EngFunc_WriteCoord, originF[2]+470.0) // z axis
12848 write_short(g_exploSpr) // sprite
12849 write_byte(0) // startframe
12850 write_byte(0) // framerate
12851 write_byte(4) // life
12852 write_byte(60) // width
12853 write_byte(0) // noise
12854 write_byte(200) // red
12855 write_byte(50) // green
12856 write_byte(0) // blue
12857 write_byte(200) // brightness
12858 write_byte(0) // speed
12859 message_end()
12860
12861 // Largest ring
12862 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12863 write_byte(TE_BEAMCYLINDER) // TE id
12864 engfunc(EngFunc_WriteCoord, originF[0]) // x
12865 engfunc(EngFunc_WriteCoord, originF[1]) // y
12866 engfunc(EngFunc_WriteCoord, originF[2]) // z
12867 engfunc(EngFunc_WriteCoord, originF[0]) // x axis
12868 engfunc(EngFunc_WriteCoord, originF[1]) // y axis
12869 engfunc(EngFunc_WriteCoord, originF[2]+555.0) // z axis
12870 write_short(g_exploSpr) // sprite
12871 write_byte(0) // startframe
12872 write_byte(0) // framerate
12873 write_byte(4) // life
12874 write_byte(60) // width
12875 write_byte(0) // noise
12876 write_byte(200) // red
12877 write_byte(0) // green
12878 write_byte(0) // blue
12879 write_byte(200) // brightness
12880 write_byte(0) // speed
12881 message_end()
12882}
12883
12884// Frost Grenade: Freeze Blast
12885create_blast3(const Float:originF[3])
12886{
12887 // Smallest ring
12888 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12889 write_byte(TE_BEAMCYLINDER) // TE id
12890 engfunc(EngFunc_WriteCoord, originF[0]) // x
12891 engfunc(EngFunc_WriteCoord, originF[1]) // y
12892 engfunc(EngFunc_WriteCoord, originF[2]) // z
12893 engfunc(EngFunc_WriteCoord, originF[0]) // x axis
12894 engfunc(EngFunc_WriteCoord, originF[1]) // y axis
12895 engfunc(EngFunc_WriteCoord, originF[2]+385.0) // z axis
12896 write_short(g_exploSpr) // sprite
12897 write_byte(0) // startframe
12898 write_byte(0) // framerate
12899 write_byte(4) // life
12900 write_byte(60) // width
12901 write_byte(0) // noise
12902 write_byte(0) // red
12903 write_byte(100) // green
12904 write_byte(200) // blue
12905 write_byte(200) // brightness
12906 write_byte(0) // speed
12907 message_end()
12908
12909 // Medium ring
12910 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12911 write_byte(TE_BEAMCYLINDER) // TE id
12912 engfunc(EngFunc_WriteCoord, originF[0]) // x
12913 engfunc(EngFunc_WriteCoord, originF[1]) // y
12914 engfunc(EngFunc_WriteCoord, originF[2]) // z
12915 engfunc(EngFunc_WriteCoord, originF[0]) // x axis
12916 engfunc(EngFunc_WriteCoord, originF[1]) // y axis
12917 engfunc(EngFunc_WriteCoord, originF[2]+470.0) // z axis
12918 write_short(g_exploSpr) // sprite
12919 write_byte(0) // startframe
12920 write_byte(0) // framerate
12921 write_byte(4) // life
12922 write_byte(60) // width
12923 write_byte(0) // noise
12924 write_byte(0) // red
12925 write_byte(100) // green
12926 write_byte(200) // blue
12927 write_byte(200) // brightness
12928 write_byte(0) // speed
12929 message_end()
12930
12931 // Largest ring
12932 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12933 write_byte(TE_BEAMCYLINDER) // TE id
12934 engfunc(EngFunc_WriteCoord, originF[0]) // x
12935 engfunc(EngFunc_WriteCoord, originF[1]) // y
12936 engfunc(EngFunc_WriteCoord, originF[2]) // z
12937 engfunc(EngFunc_WriteCoord, originF[0]) // x axis
12938 engfunc(EngFunc_WriteCoord, originF[1]) // y axis
12939 engfunc(EngFunc_WriteCoord, originF[2]+555.0) // z axis
12940 write_short(g_exploSpr) // sprite
12941 write_byte(0) // startframe
12942 write_byte(0) // framerate
12943 write_byte(4) // life
12944 write_byte(60) // width
12945 write_byte(0) // noise
12946 write_byte(0) // red
12947 write_byte(100) // green
12948 write_byte(200) // blue
12949 write_byte(200) // brightness
12950 write_byte(0) // speed
12951 message_end()
12952}
12953
12954// Fix Dead Attrib on scoreboard
12955FixDeadAttrib(id)
12956{
12957 message_begin(MSG_BROADCAST, g_msgScoreAttrib)
12958 write_byte(id) // id
12959 write_byte(0) // attrib
12960 message_end()
12961}
12962
12963// Send Death Message for infections
12964SendDeathMsg(attacker, victim)
12965{
12966 message_begin(MSG_BROADCAST, g_msgDeathMsg)
12967 write_byte(attacker) // killer
12968 write_byte(victim) // victim
12969 write_byte(1) // headshot flag
12970 write_string("infection") // killer's weapon
12971 message_end()
12972}
12973
12974// Update Player Frags and Deaths
12975UpdateFrags(attacker, victim, frags, deaths, scoreboard)
12976{
12977 // Set attacker frags
12978 set_pev(attacker, pev_frags, float(pev(attacker, pev_frags) + frags))
12979
12980 // Set victim deaths
12981 fm_cs_set_user_deaths(victim, cs_get_user_deaths(victim) + deaths)
12982
12983 // Update scoreboard with attacker and victim info
12984 if (scoreboard)
12985 {
12986 message_begin(MSG_BROADCAST, g_msgScoreInfo)
12987 write_byte(attacker) // id
12988 write_short(pev(attacker, pev_frags)) // frags
12989 write_short(cs_get_user_deaths(attacker)) // deaths
12990 write_short(0) // class?
12991 write_short(fm_cs_get_user_team(attacker)) // team
12992 message_end()
12993
12994 message_begin(MSG_BROADCAST, g_msgScoreInfo)
12995 write_byte(victim) // id
12996 write_short(pev(victim, pev_frags)) // frags
12997 write_short(cs_get_user_deaths(victim)) // deaths
12998 write_short(0) // class?
12999 write_short(fm_cs_get_user_team(victim)) // team
13000 message_end()
13001 }
13002}
13003
13004// Remove Player Frags (when Nemesis/Survivor ignore_frags cvar is enabled)
13005RemoveFrags(attacker, victim)
13006{
13007 // Remove attacker frags
13008 set_pev(attacker, pev_frags, float(pev(attacker, pev_frags) - 1))
13009
13010 // Remove victim deaths
13011 fm_cs_set_user_deaths(victim, cs_get_user_deaths(victim) - 1)
13012}
13013
13014// Plays a sound on clients
13015PlaySound(const sound[])
13016{
13017 if (equal(sound[strlen(sound)-4], ".mp3"))
13018 client_cmd(0, "mp3 play ^"sound/%s^"", sound)
13019 else
13020 client_cmd(0, "spk ^"%s^"", sound)
13021}
13022
13023// Prints a colored message to target (use 0 for everyone), supports ML formatting.
13024// Note: I still need to make something like gungame's LANG_PLAYER_C to avoid unintended
13025// argument replacement when a function passes -1 (it will be considered a LANG_PLAYER)
13026zp_colored_print(target, const message[], any:...)
13027{
13028 static buffer[512], i, argscount
13029 argscount = numargs()
13030
13031 // Send to everyone
13032 if (!target)
13033 {
13034 static player
13035 for (player = 1; player <= g_maxplayers; player++)
13036 {
13037 // Not connected
13038 if (!g_isconnected[player])
13039 continue;
13040
13041 // Remember changed arguments
13042 static changed[5], changedcount // [5] = max LANG_PLAYER occurencies
13043 changedcount = 0
13044
13045 // Replace LANG_PLAYER with player id
13046 for (i = 2; i < argscount; i++)
13047 {
13048 if (getarg(i) == LANG_PLAYER)
13049 {
13050 setarg(i, 0, player)
13051 changed[changedcount] = i
13052 changedcount++
13053 }
13054 }
13055
13056 // Format message for player
13057 vformat(buffer, charsmax(buffer), message, 3)
13058
13059 // Send it
13060 message_begin(MSG_ONE_UNRELIABLE, g_msgSayText, _, player)
13061 write_byte(player)
13062 write_string(buffer)
13063 message_end()
13064
13065 // Replace back player id's with LANG_PLAYER
13066 for (i = 0; i < changedcount; i++)
13067 setarg(changed[i], 0, LANG_PLAYER)
13068 }
13069 }
13070 // Send to specific target
13071 else
13072 {
13073 /*
13074 // Not needed since you should set the ML argument
13075 // to the player's id for a targeted print message
13076
13077 // Replace LANG_PLAYER with player id
13078 for (i = 2; i < argscount; i++)
13079 {
13080 if (getarg(i) == LANG_PLAYER)
13081 setarg(i, 0, target)
13082 }
13083 */
13084
13085 // Format message for player
13086 vformat(buffer, charsmax(buffer), message, 3)
13087
13088 // Send it
13089 message_begin(MSG_ONE, g_msgSayText, _, target)
13090 write_byte(target)
13091 write_string(buffer)
13092 message_end()
13093 }
13094}
13095
13096/*================================================================================
13097 [Stocks]
13098=================================================================================*/
13099
13100// Set an entity's key value (from fakemeta_util)
13101stock fm_set_kvd(entity, const key[], const value[], const classname[])
13102{
13103 set_kvd(0, KV_ClassName, classname)
13104 set_kvd(0, KV_KeyName, key)
13105 set_kvd(0, KV_Value, value)
13106 set_kvd(0, KV_fHandled, 0)
13107
13108 dllfunc(DLLFunc_KeyValue, entity, 0)
13109}
13110
13111// Set entity's rendering type (from fakemeta_util)
13112stock fm_set_rendering(entity, fx = kRenderFxNone, r = 255, g = 255, b = 255, render = kRenderNormal, amount = 16)
13113{
13114 static Float:color[3]
13115 color[0] = float(r)
13116 color[1] = float(g)
13117 color[2] = float(b)
13118
13119 set_pev(entity, pev_renderfx, fx)
13120 set_pev(entity, pev_rendercolor, color)
13121 set_pev(entity, pev_rendermode, render)
13122 set_pev(entity, pev_renderamt, float(amount))
13123}
13124
13125// Get entity's speed (from fakemeta_util)
13126stock fm_get_speed(entity)
13127{
13128 static Float:velocity[3]
13129 pev(entity, pev_velocity, velocity)
13130
13131 return floatround(vector_length(velocity));
13132}
13133
13134// Get entity's aim origins (from fakemeta_util)
13135stock fm_get_aim_origin(id, Float:origin[3])
13136{
13137 static Float:origin1F[3], Float:origin2F[3]
13138 pev(id, pev_origin, origin1F)
13139 pev(id, pev_view_ofs, origin2F)
13140 xs_vec_add(origin1F, origin2F, origin1F)
13141
13142 pev(id, pev_v_angle, origin2F);
13143 engfunc(EngFunc_MakeVectors, origin2F)
13144 global_get(glb_v_forward, origin2F)
13145 xs_vec_mul_scalar(origin2F, 9999.0, origin2F)
13146 xs_vec_add(origin1F, origin2F, origin2F)
13147
13148 engfunc(EngFunc_TraceLine, origin1F, origin2F, 0, id, 0)
13149 get_tr2(0, TR_vecEndPos, origin)
13150}
13151
13152// Find entity by its owner (from fakemeta_util)
13153stock fm_find_ent_by_owner(entity, const classname[], owner)
13154{
13155 while ((entity = engfunc(EngFunc_FindEntityByString, entity, "classname", classname)) && pev(entity, pev_owner) != owner) { /* keep looping */ }
13156 return entity;
13157}
13158
13159// Set player's health (from fakemeta_util)
13160stock fm_set_user_health(id, health)
13161{
13162 (health > 0) ? set_pev(id, pev_health, float(health)) : dllfunc(DLLFunc_ClientKill, id);
13163}
13164
13165// Give an item to a player (from fakemeta_util)
13166stock fm_give_item(id, const item[])
13167{
13168 static ent
13169 ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, item))
13170 if (!pev_valid(ent)) return;
13171
13172 static Float:originF[3]
13173 pev(id, pev_origin, originF)
13174 set_pev(ent, pev_origin, originF)
13175 set_pev(ent, pev_spawnflags, pev(ent, pev_spawnflags) | SF_NORESPAWN)
13176 dllfunc(DLLFunc_Spawn, ent)
13177
13178 static save
13179 save = pev(ent, pev_solid)
13180 dllfunc(DLLFunc_Touch, ent, id)
13181 if (pev(ent, pev_solid) != save)
13182 return;
13183
13184 engfunc(EngFunc_RemoveEntity, ent)
13185}
13186
13187// Strip user weapons (from fakemeta_util)
13188stock fm_strip_user_weapons(id)
13189{
13190 static ent
13191 ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "player_weaponstrip"))
13192 if (!pev_valid(ent)) return;
13193
13194 dllfunc(DLLFunc_Spawn, ent)
13195 dllfunc(DLLFunc_Use, ent, id)
13196 engfunc(EngFunc_RemoveEntity, ent)
13197}
13198
13199// Collect random spawn points
13200stock load_spawns()
13201{
13202 // Check for CSDM spawns of the current map
13203 new cfgdir[32], mapname[32], filepath[100], linedata[64]
13204 get_configsdir(cfgdir, charsmax(cfgdir))
13205 get_mapname(mapname, charsmax(mapname))
13206 formatex(filepath, charsmax(filepath), "%s/csdm/%s.spawns.cfg", cfgdir, mapname)
13207
13208 // Load CSDM spawns if present
13209 if (file_exists(filepath))
13210 {
13211 new csdmdata[10][6], file = fopen(filepath,"rt")
13212
13213 while (file && !feof(file))
13214 {
13215 fgets(file, linedata, charsmax(linedata))
13216
13217 // invalid spawn
13218 if(!linedata[0] || str_count(linedata,' ') < 2) continue;
13219
13220 // get spawn point data
13221 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)
13222
13223 // origin
13224 g_spawns[g_spawnCount][0] = floatstr(csdmdata[0])
13225 g_spawns[g_spawnCount][1] = floatstr(csdmdata[1])
13226 g_spawns[g_spawnCount][2] = floatstr(csdmdata[2])
13227
13228 // increase spawn count
13229 g_spawnCount++
13230 if (g_spawnCount >= sizeof g_spawns) break;
13231 }
13232 if (file) fclose(file)
13233 }
13234 else
13235 {
13236 // Collect regular spawns
13237 collect_spawns_ent("info_player_start")
13238 collect_spawns_ent("info_player_deathmatch")
13239 }
13240
13241 // Collect regular spawns for non-random spawning unstuck
13242 collect_spawns_ent2("info_player_start")
13243 collect_spawns_ent2("info_player_deathmatch")
13244}
13245
13246// Collect spawn points from entity origins
13247stock collect_spawns_ent(const classname[])
13248{
13249 new ent = -1
13250 while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", classname)) != 0)
13251 {
13252 // get origin
13253 new Float:originF[3]
13254 pev(ent, pev_origin, originF)
13255 g_spawns[g_spawnCount][0] = originF[0]
13256 g_spawns[g_spawnCount][1] = originF[1]
13257 g_spawns[g_spawnCount][2] = originF[2]
13258
13259 // increase spawn count
13260 g_spawnCount++
13261 if (g_spawnCount >= sizeof g_spawns) break;
13262 }
13263}
13264
13265// Collect spawn points from entity origins
13266stock collect_spawns_ent2(const classname[])
13267{
13268 new ent = -1
13269 while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", classname)) != 0)
13270 {
13271 // get origin
13272 new Float:originF[3]
13273 pev(ent, pev_origin, originF)
13274 g_spawns2[g_spawnCount2][0] = originF[0]
13275 g_spawns2[g_spawnCount2][1] = originF[1]
13276 g_spawns2[g_spawnCount2][2] = originF[2]
13277
13278 // increase spawn count
13279 g_spawnCount2++
13280 if (g_spawnCount2 >= sizeof g_spawns2) break;
13281 }
13282}
13283
13284// Drop primary/secondary weapons
13285stock drop_weapons(id, dropwhat)
13286{
13287 // Get user weapons
13288 static weapons[32], num, i, weaponid
13289 num = 0 // reset passed weapons count (bugfix)
13290 get_user_weapons(id, weapons, num)
13291
13292 // Loop through them and drop primaries or secondaries
13293 for (i = 0; i < num; i++)
13294 {
13295 // Prevent re-indexing the array
13296 weaponid = weapons[i]
13297
13298 if ((dropwhat == 1 && ((1<<weaponid) & PRIMARY_WEAPONS_BIT_SUM)) || (dropwhat == 2 && ((1<<weaponid) & SECONDARY_WEAPONS_BIT_SUM)))
13299 {
13300 // Get weapon entity
13301 static wname[32], weapon_ent
13302 get_weaponname(weaponid, wname, charsmax(wname))
13303 weapon_ent = fm_find_ent_by_owner(-1, wname, id)
13304
13305 // Hack: store weapon bpammo on PEV_ADDITIONAL_AMMO
13306 set_pev(weapon_ent, PEV_ADDITIONAL_AMMO, cs_get_user_bpammo(id, weaponid))
13307
13308 // Player drops the weapon and looses his bpammo
13309 engclient_cmd(id, "drop", wname)
13310 cs_set_user_bpammo(id, weaponid, 0)
13311 }
13312 }
13313}
13314
13315// Stock by (probably) Twilight Suzuka -counts number of chars in a string
13316stock str_count(const str[], searchchar)
13317{
13318 new count, i, len = strlen(str)
13319
13320 for (i = 0; i <= len; i++)
13321 {
13322 if(str[i] == searchchar)
13323 count++
13324 }
13325
13326 return count;
13327}
13328
13329// Checks if a space is vacant (credits to VEN)
13330stock is_hull_vacant(Float:origin[3], hull)
13331{
13332 engfunc(EngFunc_TraceHull, origin, origin, 0, hull, 0, 0)
13333
13334 if (!get_tr2(0, TR_StartSolid) && !get_tr2(0, TR_AllSolid) && get_tr2(0, TR_InOpen))
13335 return true;
13336
13337 return false;
13338}
13339
13340// Check if a player is stuck (credits to VEN)
13341stock is_player_stuck(id)
13342{
13343 static Float:originF[3]
13344 pev(id, pev_origin, originF)
13345
13346 engfunc(EngFunc_TraceHull, originF, originF, 0, (pev(id, pev_flags) & FL_DUCKING) ? HULL_HEAD : HULL_HUMAN, id, 0)
13347
13348 if (get_tr2(0, TR_StartSolid) || get_tr2(0, TR_AllSolid) || !get_tr2(0, TR_InOpen))
13349 return true;
13350
13351 return false;
13352}
13353
13354// Simplified get_weaponid (CS only)
13355stock cs_weapon_name_to_id(const weapon[])
13356{
13357 static i
13358 for (i = 0; i < sizeof WEAPONENTNAMES; i++)
13359 {
13360 if (equal(weapon, WEAPONENTNAMES[i]))
13361 return i;
13362 }
13363
13364 return 0;
13365}
13366
13367// Get User Current Weapon Entity
13368stock fm_cs_get_current_weapon_ent(id)
13369{
13370 // Prevent server crash if entity's private data not initalized
13371 if (pev_valid(id) != PDATA_SAFE)
13372 return -1;
13373
13374 return get_pdata_cbase(id, OFFSET_ACTIVE_ITEM, OFFSET_LINUX);
13375}
13376
13377// Get Weapon Entity's Owner
13378stock fm_cs_get_weapon_ent_owner(ent)
13379{
13380 // Prevent server crash if entity's private data not initalized
13381 if (pev_valid(ent) != PDATA_SAFE)
13382 return -1;
13383
13384 return get_pdata_cbase(ent, OFFSET_WEAPONOWNER, OFFSET_LINUX_WEAPONS);
13385}
13386
13387// Set User Deaths
13388stock fm_cs_set_user_deaths(id, value)
13389{
13390 // Prevent server crash if entity's private data not initalized
13391 if (pev_valid(id) != PDATA_SAFE)
13392 return;
13393
13394 set_pdata_int(id, OFFSET_CSDEATHS, value, OFFSET_LINUX)
13395}
13396
13397// Get User Team
13398stock fm_cs_get_user_team(id)
13399{
13400 // Prevent server crash if entity's private data not initalized
13401 if (pev_valid(id) != PDATA_SAFE)
13402 return FM_CS_TEAM_UNASSIGNED;
13403
13404 return get_pdata_int(id, OFFSET_CSTEAMS, OFFSET_LINUX);
13405}
13406
13407// Set a Player's Team
13408stock fm_cs_set_user_team(id, team)
13409{
13410 // Prevent server crash if entity's private data not initalized
13411 if (pev_valid(id) != PDATA_SAFE)
13412 return;
13413
13414 set_pdata_int(id, OFFSET_CSTEAMS, team, OFFSET_LINUX)
13415}
13416
13417// Set User Money
13418stock fm_cs_set_user_money(id, value)
13419{
13420 // Prevent server crash if entity's private data not initalized
13421 if (pev_valid(id) != PDATA_SAFE)
13422 return;
13423
13424 set_pdata_int(id, OFFSET_CSMONEY, value, OFFSET_LINUX)
13425}
13426
13427// Set User Flashlight Batteries
13428stock fm_cs_set_user_batteries(id, value)
13429{
13430 // Prevent server crash if entity's private data not initalized
13431 if (pev_valid(id) != PDATA_SAFE)
13432 return;
13433
13434 set_pdata_int(id, OFFSET_FLASHLIGHT_BATTERY, value, OFFSET_LINUX)
13435}
13436
13437// Update Player's Team on all clients (adding needed delays)
13438stock fm_user_team_update(id)
13439{
13440 static Float:current_time
13441 current_time = get_gametime()
13442
13443 if (current_time - g_teams_targettime >= 0.1)
13444 {
13445 set_task(0.1, "fm_cs_set_user_team_msg", id+TASK_TEAM)
13446 g_teams_targettime = current_time + 0.1
13447 }
13448 else
13449 {
13450 set_task((g_teams_targettime + 0.1) - current_time, "fm_cs_set_user_team_msg", id+TASK_TEAM)
13451 g_teams_targettime = g_teams_targettime + 0.1
13452 }
13453}
13454
13455// Send User Team Message
13456public fm_cs_set_user_team_msg(taskid)
13457{
13458 // Note to self: this next message can now be received by other plugins
13459
13460 // Set the switching team flag
13461 g_switchingteam = true
13462
13463 // Tell everyone my new team
13464 emessage_begin(MSG_ALL, g_msgTeamInfo)
13465 ewrite_byte(ID_TEAM) // player
13466 ewrite_string(CS_TEAM_NAMES[fm_cs_get_user_team(ID_TEAM)]) // team
13467 emessage_end()
13468
13469 // Done switching team
13470 g_switchingteam = false
13471}
13472
13473// Set the precached model index (updates hitboxes server side)
13474stock fm_cs_set_user_model_index(id, value)
13475{
13476 // Prevent server crash if entity's private data not initalized
13477 if (pev_valid(id) != PDATA_SAFE)
13478 return;
13479
13480 set_pdata_int(id, OFFSET_MODELINDEX, value, OFFSET_LINUX)
13481}
13482
13483// Set Player Model on Entity
13484stock fm_set_playermodel_ent(id)
13485{
13486 // Make original player entity invisible without hiding shadows or firing effects
13487 fm_set_rendering(id, kRenderFxNone, 255, 255, 255, kRenderTransTexture, 1)
13488
13489 // Format model string
13490 static model[100]
13491 formatex(model, charsmax(model), "models/player/%s/%s.mdl", g_playermodel[id], g_playermodel[id])
13492
13493 // Set model on entity or make a new one if unexistant
13494 if (!pev_valid(g_ent_playermodel[id]))
13495 {
13496 g_ent_playermodel[id] = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "info_target"))
13497 if (!pev_valid(g_ent_playermodel[id])) return;
13498
13499 set_pev(g_ent_playermodel[id], pev_classname, MODEL_ENT_CLASSNAME)
13500 set_pev(g_ent_playermodel[id], pev_movetype, MOVETYPE_FOLLOW)
13501 set_pev(g_ent_playermodel[id], pev_aiment, id)
13502 set_pev(g_ent_playermodel[id], pev_owner, id)
13503 }
13504
13505 engfunc(EngFunc_SetModel, g_ent_playermodel[id], model)
13506}
13507
13508// Set Weapon Model on Entity
13509stock fm_set_weaponmodel_ent(id)
13510{
13511 // Get player's p_ weapon model
13512 static model[100]
13513 pev(id, pev_weaponmodel2, model, charsmax(model))
13514
13515 // Set model on entity or make a new one if unexistant
13516 if (!pev_valid(g_ent_weaponmodel[id]))
13517 {
13518 g_ent_weaponmodel[id] = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "info_target"))
13519 if (!pev_valid(g_ent_weaponmodel[id])) return;
13520
13521 set_pev(g_ent_weaponmodel[id], pev_classname, WEAPON_ENT_CLASSNAME)
13522 set_pev(g_ent_weaponmodel[id], pev_movetype, MOVETYPE_FOLLOW)
13523 set_pev(g_ent_weaponmodel[id], pev_aiment, id)
13524 set_pev(g_ent_weaponmodel[id], pev_owner, id)
13525 }
13526
13527 engfunc(EngFunc_SetModel, g_ent_weaponmodel[id], model)
13528}
13529
13530// Remove Custom Model Entities
13531stock fm_remove_model_ents(id)
13532{
13533 // Remove "playermodel" ent if present
13534 if (pev_valid(g_ent_playermodel[id]))
13535 {
13536 engfunc(EngFunc_RemoveEntity, g_ent_playermodel[id])
13537 g_ent_playermodel[id] = 0
13538 }
13539 // Remove "weaponmodel" ent if present
13540 if (pev_valid(g_ent_weaponmodel[id]))
13541 {
13542 engfunc(EngFunc_RemoveEntity, g_ent_weaponmodel[id])
13543 g_ent_weaponmodel[id] = 0
13544 }
13545}
13546
13547// Set User Model
13548public fm_cs_set_user_model(taskid)
13549{
13550 set_user_info(ID_MODEL, "model", g_playermodel[ID_MODEL])
13551}
13552
13553// Get User Model -model passed byref-
13554stock fm_cs_get_user_model(player, model[], len)
13555{
13556 get_user_info(player, "model", model, len)
13557}
13558
13559// Update Player's Model on all clients (adding needed delays)
13560public fm_user_model_update(taskid)
13561{
13562 static Float:current_time
13563 current_time = get_gametime()
13564
13565 if (current_time - g_models_targettime >= g_modelchange_delay)
13566 {
13567 fm_cs_set_user_model(taskid)
13568 g_models_targettime = current_time
13569 }
13570 else
13571 {
13572 set_task((g_models_targettime + g_modelchange_delay) - current_time, "fm_cs_set_user_model", taskid)
13573 g_models_targettime = g_models_targettime + g_modelchange_delay
13574 }
13575}