· 6 years ago · Jan 13, 2020, 07:10 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
415native bool:get_user_gasmask(index);
416native set_user_gasmask(index, bool:value);
417
418/*================================================================================
419 [Constants, Offsets, Macros]
420=================================================================================*/
421
422// Plugin Version
423new const PLUGIN_VERSION[] = "4.3 Fix5a"
424
425// Customization file sections
426enum
427{
428 SECTION_NONE = 0,
429 SECTION_ACCESS_FLAGS,
430 SECTION_PLAYER_MODELS,
431 SECTION_WEAPON_MODELS,
432 SECTION_GRENADE_SPRITES,
433 SECTION_SOUNDS,
434 SECTION_AMBIENCE_SOUNDS,
435 SECTION_BUY_MENU_WEAPONS,
436 SECTION_EXTRA_ITEMS_WEAPONS,
437 SECTION_HARD_CODED_ITEMS_COSTS,
438 SECTION_WEATHER_EFFECTS,
439 SECTION_SKY,
440 SECTION_LIGHTNING,
441 SECTION_ZOMBIE_DECALS,
442 SECTION_KNOCKBACK,
443 SECTION_OBJECTIVE_ENTS,
444 SECTION_SVC_BAD
445}
446
447// Access flags
448enum
449{
450 ACCESS_ENABLE_MOD = 0,
451 ACCESS_ADMIN_MENU,
452 ACCESS_ADMIN_MODES_MENU,
453 ACCESS_MODE_INFECTION,
454 ACCESS_MODE_NEMESIS,
455 ACCESS_MODE_ASSASSIN,
456 ACCESS_MODE_SURVIVOR,
457 ACCESS_MODE_SNIPER,
458 ACCESS_MODE_SWARM,
459 ACCESS_MODE_MULTI,
460 ACCESS_MODE_PLAGUE,
461 ACCESS_MODE_ARMAGEDDON,
462 ACCESS_MODE_APOCALYPSE,
463 ACCESS_MODE_NIGHTMARE,
464 ACCESS_MAKE_ZOMBIE,
465 ACCESS_MAKE_HUMAN,
466 ACCESS_MAKE_NEMESIS,
467 ACCESS_MAKE_ASSASSIN,
468 ACCESS_MAKE_SURVIVOR,
469 ACCESS_MAKE_SNIPER,
470 ACCESS_RESPAWN_PLAYERS,
471 ACCESS_ADMIN_MODELS,
472 MAX_ACCESS_FLAGS
473}
474
475// Task offsets
476enum (+= 100)
477{
478 TASK_MODEL = 2000,
479 TASK_TEAM,
480 TASK_SPAWN,
481 TASK_BLOOD,
482 TASK_AURA,
483 TASK_BURN,
484 TASK_NVISION,
485 TASK_FLASH,
486 TASK_CHARGE,
487 TASK_SHOWHUD,
488 TASK_MAKEZOMBIE,
489 TASK_WELCOMEMSG,
490 TASK_THUNDER_PRE,
491 TASK_THUNDER,
492 TASK_AMBIENCESOUNDS
493}
494
495// IDs inside tasks
496#define ID_MODEL (taskid - TASK_MODEL)
497#define ID_TEAM (taskid - TASK_TEAM)
498#define ID_SPAWN (taskid - TASK_SPAWN)
499#define ID_BLOOD (taskid - TASK_BLOOD)
500#define ID_AURA (taskid - TASK_AURA)
501#define ID_BURN (taskid - TASK_BURN)
502#define ID_NVISION (taskid - TASK_NVISION)
503#define ID_FLASH (taskid - TASK_FLASH)
504#define ID_CHARGE (taskid - TASK_CHARGE)
505#define ID_SHOWHUD (taskid - TASK_SHOWHUD)
506
507// BP Ammo Refill task
508#define REFILL_WEAPONID args[0]
509
510// For weapon buy menu handlers
511#define WPN_STARTID g_menu_data[id][1]
512#define WPN_MAXIDS ArraySize(g_primary_items)
513#define WPN_SELECTION (g_menu_data[id][1]+key)
514#define WPN_AUTO_ON g_menu_data[id][2]
515#define WPN_AUTO_PRI g_menu_data[id][3]
516#define WPN_AUTO_SEC g_menu_data[id][4]
517
518// For player list menu handlers
519#define PL_ACTION g_menu_data[id][0]
520
521// For remembering menu pages
522#define MENU_PAGE_ZCLASS g_menu_data[id][5]
523#define MENU_PAGE_EXTRAS g_menu_data[id][6]
524#define MENU_PAGE_PLAYERS g_menu_data[id][7]
525
526// For extra items menu handlers
527#define EXTRAS_CUSTOM_STARTID (EXTRA_WEAPONS_STARTID + ArraySize(g_extraweapon_names))
528
529// Menu selections
530const MENU_KEY_AUTOSELECT = 7
531const MENU_KEY_BACK = 7
532const MENU_KEY_NEXT = 8
533const MENU_KEY_EXIT = 9
534
535// Hard coded extra items
536enum
537{
538 EXTRA_NVISION = 0,
539 EXTRA_ANTIDOTE,
540 EXTRA_MADNESS,
541 EXTRA_INFBOMB,
542 EXTRA_WEAPONS_STARTID
543}
544
545// Game modes
546enum
547{
548 MODE_NONE = 0,
549 MODE_INFECTION,
550 MODE_NEMESIS,
551 MODE_ASSASSIN,
552 MODE_SURVIVOR,
553 MODE_SNIPER,
554 MODE_SWARM,
555 MODE_MULTI,
556 MODE_PLAGUE,
557 MODE_ARMAGEDDON,
558 MODE_APOCALYPSE,
559 MODE_NIGHTMARE
560}
561
562// ZP Teams
563const ZP_TEAM_NO_ONE = 0
564const ZP_TEAM_ANY = 0
565const ZP_TEAM_ZOMBIE = (1<<0)
566const ZP_TEAM_HUMAN = (1<<1)
567const ZP_TEAM_NEMESIS = (1<<2)
568const ZP_TEAM_ASSASSIN = (1<<3)
569const ZP_TEAM_SURVIVOR = (1<<4)
570const ZP_TEAM_SNIPER = (1<<5)
571new const ZP_TEAM_NAMES[][] =
572{
573 "ZOMBIE , HUMAN",
574 "ZOMBIE",
575 "HUMAN",
576 "ZOMBIE , HUMAN",
577 "NEMESIS",
578 "ZOMBIE , NEMESIS",
579 "HUMAN , NEMESIS",
580 "ZOMBIE , HUMAN , NEMESIS",
581 "ASSASSIN",
582 "ZOMBIE , ASSASSIN",
583 "HUMAN , ASSASSIN",
584 "ZOMBIE, HUMAN, ASSASSIN",
585 "NEMESIS , ASSASSIN",
586 "ZOMBIE , NEMESIS , ASSASSIN",
587 "HUMAN, NEMESIS, ASSASSIN",
588 "ZOMBIE , HUMAN , NEMESIS , ASSASSIN",
589 "SURVIVOR",
590 "ZOMBIE, SURVIVOR",
591 "HUMAN, SURVIVOR",
592 "ZOMBIE, HUMAN, SURVIVOR",
593 "NEMESIS , SURVIVOR",
594 "ZOMBIE , NEMESIS , SURVIVOR",
595 "HUMAN , NEMESIS , SURVIVOR",
596 "ZOMBIE , HUMAN , NEMESIS , SURVIVOR",
597 "ASSASSIN, SURVIVOR",
598 "ZOMBIE, ASSASSIN, SURVIVOR",
599 "HUMAN, ASSASSIN, SURVIVOR",
600 "ZOMBIE, HUMAN, ASSASSIN, SURVIVOR",
601 "NEMESIS, ASSASSIN, SURVIVOR",
602 "ZOMBIE, NEMESIS, ASSASSIN, SURVIVOR",
603 "HUMAN, NEMESIS, ASSASSIN, SURVIVOR",
604 "ZOMBIE, HUMAN, NEMESIS, ASSASSIN, SURVIVOR",
605 "SNIPER",
606 "ZOMBIE, SNIPER",
607 "HUMAN, SNIPER",
608 "ZOMBIE, HUMAN, SNIPER",
609 "NEMESIS, SNIPER",
610 "ZOMBIE, NEMESIS, SNIPER",
611 "HUMAN, NEMESIS, SNIPER",
612 "ZOMBIE, HUMAN, NEMESIS, SNIPER",
613 "ASSASSIN, SNIPER",
614 "ZOMBIE, ASSASSIN, SNIPER",
615 "HUMAN, ASSASSIN, SNIPER",
616 "ZOMBIE, HUMAN, ASSASSIN, SNIPER",
617 "NEMESIS, ASSASSIN, SNIPER",
618 "ZOMBIE, NEMESIS, ASSASSIN, SNIPER",
619 "HUMAN, NEMESIS, ASSASSIN, SNIPER",
620 "ZOMBIE, HUMAN, NEMESIS, ASSASSIN, SNIPER",
621 "SURVIVOR, SNIPER",
622 "ZOMBIE, SURVIVOR, SNIPER",
623 "HUMAN, SURVIVOR, SNIPER",
624 "ZOMBIE, HUMAN, SURVIVOR, SNIPER",
625 "NEMESIS, SURVIVOR, SNIPER",
626 "ZOMBIE, NEMESIS, SURVIVOR, SNIPER",
627 "HUMAN, NEMESIS, SURVIVOR, SNIPER",
628 "ZOMBIE, HUMAN, NEMESIS, SURVIVOR, SNIPER",
629 "ASSASSIN, SURVIVOR, SNIPER",
630 "ZOMBIE, ASSASSIN, SURVIVOR, SNIPER",
631 "HUMAN, ASSASSIN, SURVIVOR, SNIPER",
632 "ZOMBIE, HUMAN, ASSASSIN, SURVIVOR, SNIPER",
633 "NEMESIS, ASSASSIN, SURVIVOR, SNIPER",
634 "ZOMBIE, NEMESIS, ASSASSIN, SURVIVOR, SNIPER",
635 "HUMAN, NEMESIS, ASSASSIN, SURVIVOR, SNIPER",
636 "ZOMBIE, HUMAN, NEMESIS, ASSASSIN, SURVIVOR, SNIPER"
637}
638
639// Zombie classes
640const ZCLASS_NONE = -1
641
642// HUD messages
643const Float:HUD_EVENT_X = -1.0
644const Float:HUD_EVENT_Y = 0.17
645const Float:HUD_INFECT_X = 0.05
646const Float:HUD_INFECT_Y = 0.45
647const Float:HUD_SPECT_X = -1.0
648const Float:HUD_SPECT_Y = 0.8
649const Float:HUD_STATS_X = 0.02
650const Float:HUD_STATS_Y = 0.9
651
652// Hack to be able to use Ham_Player_ResetMaxSpeed (by joaquimandrade)
653new Ham:Ham_Player_ResetMaxSpeed = Ham_Item_PreFrame
654
655// CS Player PData Offsets (win32)
656const PDATA_SAFE = 2
657const OFFSET_PAINSHOCK = 108 // ConnorMcLeod
658const OFFSET_CSTEAMS = 114
659const OFFSET_CSMONEY = 115
660const OFFSET_CSMENUCODE = 205
661const OFFSET_FLASHLIGHT_BATTERY = 244
662const OFFSET_CSDEATHS = 444
663const OFFSET_MODELINDEX = 491 // Orangutanz
664
665// CS Player CBase Offsets (win32)
666const OFFSET_ACTIVE_ITEM = 373
667
668// CS Weapon CBase Offsets (win32)
669const OFFSET_WEAPONOWNER = 41
670
671// Linux diff's
672const OFFSET_LINUX = 5 // offsets 5 higher in Linux builds
673const OFFSET_LINUX_WEAPONS = 4 // weapon offsets are only 4 steps higher on Linux
674
675// CS Teams
676enum
677{
678 FM_CS_TEAM_UNASSIGNED = 0,
679 FM_CS_TEAM_T,
680 FM_CS_TEAM_CT,
681 FM_CS_TEAM_SPECTATOR
682}
683new const CS_TEAM_NAMES[][] = { "UNASSIGNED", "TERRORIST", "CT", "SPECTATOR" }
684
685// Some constants
686const HIDE_MONEY = (1<<5)
687const UNIT_SECOND = (1<<12)
688const DMG_HEGRENADE = (1<<24)
689const IMPULSE_FLASHLIGHT = 100
690const USE_USING = 2
691const USE_STOPPED = 0
692const STEPTIME_SILENT = 999
693const BREAK_GLASS = 0x01
694const FFADE_IN = 0x0000
695const FFADE_STAYOUT = 0x0004
696const PEV_SPEC_TARGET = pev_iuser2
697
698// Max BP ammo for weapons
699new const MAXBPAMMO[] = { -1, 52, -1, 90, 1, 32, 1, 100, 90, 1, 120, 100, 100, 90, 90, 90, 100, 120,
700 30, 120, 200, 32, 90, 120, 90, 2, 35, 90, 90, -1, 100 }
701
702// Max Clip for weapons
703new const MAXCLIP[] = { -1, 13, -1, 10, -1, 7, -1, 30, 30, -1, 30, 20, 25, 30, 35, 25, 12, 20,
704 10, 30, 100, 8, 30, 30, 20, -1, 7, 30, 30, -1, 50 }
705
706// Amount of ammo to give when buying additional clips for weapons
707new const BUYAMMO[] = { -1, 13, -1, 30, -1, 8, -1, 12, 30, -1, 30, 50, 12, 30, 30, 30, 12, 30,
708 10, 30, 30, 8, 30, 30, 30, -1, 7, 30, 30, -1, 50 }
709
710// Ammo IDs for weapons
711new const AMMOID[] = { -1, 9, -1, 2, 12, 5, 14, 6, 4, 13, 10, 7, 6, 4, 4, 4, 6, 10,
712 1, 10, 3, 5, 4, 10, 2, 11, 8, 4, 2, -1, 7 }
713
714// Ammo Type Names for weapons
715new const AMMOTYPE[][] = { "", "357sig", "", "762nato", "", "buckshot", "", "45acp", "556nato", "", "9mm", "57mm", "45acp",
716 "556nato", "556nato", "556nato", "45acp", "9mm", "338magnum", "9mm", "556natobox", "buckshot",
717 "556nato", "9mm", "762nato", "", "50ae", "556nato", "762nato", "", "57mm" }
718
719// Weapon IDs for ammo types
720new const AMMOWEAPON[] = { 0, CSW_AWP, CSW_SCOUT, CSW_M249, CSW_AUG, CSW_XM1014, CSW_MAC10, CSW_FIVESEVEN, CSW_DEAGLE,
721 CSW_P228, CSW_ELITE, CSW_FLASHBANG, CSW_HEGRENADE, CSW_SMOKEGRENADE, CSW_C4 }
722
723// Primary and Secondary Weapon Names
724new const WEAPONNAMES[][] = { "", "P228 Compact", "", "Schmidt Scout", "", "XM1014 M4", "", "Ingram MAC-10", "Steyr AUG A1",
725 "", "Dual Elite Berettas", "FiveseveN", "UMP 45", "SG-550 Auto-Sniper", "IMI Galil", "Famas",
726 "USP .45 ACP Tactical", "Glock 18C", "AWP Magnum Sniper", "MP5 Navy", "M249 Para Machinegun",
727 "M3 Super 90", "M4A1 Carbine", "Schmidt TMP", "G3SG1 Auto-Sniper", "", "Desert Eagle .50 AE",
728 "SG-552 Commando", "AK-47 Kalashnikov", "", "ES P90" }
729
730// Weapon entity names
731new const WEAPONENTNAMES[][] = { "", "weapon_p228", "", "weapon_scout", "weapon_hegrenade", "weapon_xm1014", "weapon_c4", "weapon_mac10",
732 "weapon_aug", "weapon_smokegrenade", "weapon_elite", "weapon_fiveseven", "weapon_ump45", "weapon_sg550",
733 "weapon_galil", "weapon_famas", "weapon_usp", "weapon_glock18", "weapon_awp", "weapon_mp5navy", "weapon_m249",
734 "weapon_m3", "weapon_m4a1", "weapon_tmp", "weapon_g3sg1", "weapon_flashbang", "weapon_deagle", "weapon_sg552",
735 "weapon_ak47", "weapon_knife", "weapon_p90" }
736
737// CS sounds
738new const sound_flashlight[] = "items/flashlight1.wav"
739new const sound_buyammo[] = "items/9mmclip1.wav"
740new const sound_armorhit[] = "player/bhit_helmet-1.wav"
741
742// Explosion radius for custom grenades
743const Float:NADE_EXPLOSION_RADIUS = 240.0
744
745// HACK: pev_ field used to store additional ammo on weapons
746const PEV_ADDITIONAL_AMMO = pev_iuser1
747
748// HACK: pev_ field used to store custom nade types and their values
749const PEV_NADE_TYPE = pev_flTimeStepSound
750const NADE_TYPE_INFECTION = 1111
751const NADE_TYPE_NAPALM = 2222
752const NADE_TYPE_FROST = 3333
753const NADE_TYPE_FLARE = 4444
754const PEV_FLARE_COLOR = pev_punchangle
755const PEV_FLARE_DURATION = pev_flSwimTime
756
757// Weapon bitsums
758const 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)
759const SECONDARY_WEAPONS_BIT_SUM = (1<<CSW_P228)|(1<<CSW_ELITE)|(1<<CSW_FIVESEVEN)|(1<<CSW_USP)|(1<<CSW_GLOCK18)|(1<<CSW_DEAGLE)
760
761// Allowed weapons for zombies (added grenades/bomb for sub-plugin support, since they shouldn't be getting them anyway)
762const ZOMBIE_ALLOWED_WEAPONS_BITSUM = (1<<CSW_KNIFE)|(1<<CSW_HEGRENADE)|(1<<CSW_FLASHBANG)|(1<<CSW_SMOKEGRENADE)|(1<<CSW_C4)
763
764// Classnames for separate model entities
765new const MODEL_ENT_CLASSNAME[] = "player_model"
766new const WEAPON_ENT_CLASSNAME[] = "weapon_model"
767
768// Menu keys
769const 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
770
771// Ambience Sounds
772enum
773{
774 AMBIENCE_SOUNDS_INFECTION = 0,
775 AMBIENCE_SOUNDS_NEMESIS,
776 AMBIENCE_SOUNDS_ASSASSIN,
777 AMBIENCE_SOUNDS_SURVIVOR,
778 AMBIENCE_SOUNDS_SNIPER,
779 AMBIENCE_SOUNDS_SWARM,
780 AMBIENCE_SOUNDS_PLAGUE,
781 AMBIENCE_SOUNDS_ARMAGEDDON,
782 AMBIENCE_SOUNDS_APOCALYPSE,
783 AMBIENCE_SOUNDS_NIGHTMARE,
784 MAX_AMBIENCE_SOUNDS
785}
786
787// Admin menu actions
788enum
789{
790 ACTION_ZOMBIEFY_HUMANIZE = 0,
791 ACTION_MAKE_NEMESIS,
792 ACTION_MAKE_ASSASSIN,
793 ACTION_MAKE_SURVIVOR,
794 ACTION_MAKE_SNIPER,
795 ACTION_RESPAWN_PLAYER,
796 ACTION_MODES_MENU
797
798}
799
800// Admin modes menu actions
801enum
802{
803 ACTION_MODE_SWARM,
804 ACTION_MODE_MULTI,
805 ACTION_MODE_PLAGUE,
806 ACTION_MODE_ARMAGEDDON,
807 ACTION_MODE_APOCALYPSE,
808 ACTION_MODE_NIGHTMARE
809}
810
811// Custom forward return values
812const ZP_PLUGIN_HANDLED = 97
813
814/*================================================================================
815 [Global Variables]
816=================================================================================*/
817
818// Player vars
819new g_zombie[33] // is zombie
820new g_nemesis[33] // is nemesis
821new g_assassin[33] // is assassin
822new g_survivor[33] // is survivor
823new g_sniper[33] // is assassin
824new g_firstzombie[33] // is first zombie
825new g_lastzombie[33] // is last zombie
826new g_lasthuman[33] // is last human
827new g_frozen[33] // is frozen (can't move)
828new Float:g_frozen_gravity[33] // store previous gravity when frozen
829new g_nodamage[33] // has spawn protection/zombie madness
830new g_respawn_as_zombie[33] // should respawn as zombie
831new g_nvision[33] // has night vision
832new g_nvisionenabled[33] // has night vision turned on
833new g_zombieclass[33] // zombie class
834new g_zombieclassnext[33] // zombie class for next infection
835new g_flashlight[33] // has custom flashlight turned on
836new g_flashbattery[33] = { 100, ... } // custom flashlight battery
837new g_canbuy[33] // is allowed to buy a new weapon through the menu
838new g_ammopacks[33] // ammo pack count
839new g_damagedealt_human[33] // damage dealt as human (used to calculate ammo packs reward)
840new g_damagedealt_zombie[33] // damage dealt as zombie (used to calculate ammo packs reward)
841new Float:g_lastleaptime[33] // time leap was last used
842new Float:g_lastflashtime[33] // time flashlight was last toggled
843new g_playermodel[33][32] // current model's short name [player][model]
844new g_menu_data[33][8] // data for some menu handlers
845new g_ent_playermodel[33] // player model entity
846new g_ent_weaponmodel[33] // weapon model entity
847new g_burning_duration[33] // burning task duration
848new Float:g_buytime[33] // used to calculate custom buytime
849
850// Game vars
851new g_pluginenabled // ZP enabled
852new g_newround // new round starting
853new g_endround // round ended
854new g_nemround // nemesis round
855new g_assaround // assassin round
856new g_survround // survivor round
857new g_sniround // sniper round
858new g_swarmround // swarm round
859new g_plagueround // plague round
860new g_armageround // armageddon round
861new g_apocround // apocalypse round
862new g_nightround // nightmare round
863new g_modestarted // mode fully started
864new g_lastmode // last played mode
865new g_scorezombies, g_scorehumans, g_gamecommencing // team scores
866new g_spawnCount, g_spawnCount2 // available spawn points counter
867new Float:g_spawns[MAX_CSDM_SPAWNS][3], Float:g_spawns2[MAX_CSDM_SPAWNS][3] // spawn points data
868new g_lights_i // lightning current lights counter
869new g_lights_cycle[32] // current lightning cycle
870new g_lights_cycle_len // lightning cycle length
871new Float:g_models_targettime // for adding delays between Model Change messages
872new Float:g_teams_targettime // for adding delays between Team Change messages
873new g_MsgSync, g_MsgSync2, g_MsgSync3 // message sync objects
874new g_trailSpr, g_exploSpr, g_flameSpr, g_smokeSpr, g_glassSpr // grenade sprites
875new g_modname[32] // for formatting the mod name
876new g_freezetime // whether CS's freeze time is on
877new g_maxplayers // max players counter
878new g_czero // whether we are running on a CZ server
879new g_hamczbots // whether ham forwards are registered for CZ bots
880new g_fwSpawn, g_fwPrecacheSound // spawn and precache sound forward handles
881new g_infbombcounter, g_antidotecounter, g_madnesscounter // to limit buying some items
882new g_arrays_created // to prevent stuff from being registered before initializing arrays
883new g_lastplayerleaving // flag for whenever a player leaves and another takes his place
884new g_switchingteam // flag for whenever a player's team change emessage is sent
885new g_buyzone_ent // custom buyzone entity
886
887// Message IDs vars
888new g_msgScoreInfo, g_msgNVGToggle, g_msgScoreAttrib, g_msgAmmoPickup, g_msgScreenFade,
889g_msgDeathMsg, g_msgSetFOV, g_msgFlashlight, g_msgFlashBat, g_msgTeamInfo, g_msgDamage,
890g_msgHideWeapon, g_msgCrosshair, g_msgSayText, g_msgScreenShake, g_msgCurWeapon
891
892// Some forward handlers
893new g_fwRoundStart, g_fwRoundEnd, g_fwUserInfected_pre, g_fwUserInfected_post,
894g_fwUserHumanized_pre, g_fwUserHumanized_post, g_fwUserInfect_attempt,
895g_fwUserHumanize_attempt, g_fwExtraItemSelected, g_fwUserUnfrozen,
896g_fwUserLastZombie, g_fwUserLastHuman, g_fwDummyResult
897
898// Temporary Database vars (used to restore players stats in case they get disconnected)
899new db_name[MAX_STATS_SAVED][32] // player name
900new db_ammopacks[MAX_STATS_SAVED] // ammo pack count
901new db_zombieclass[MAX_STATS_SAVED] // zombie class
902new db_slot_i // additional saved slots counter (should start on maxplayers+1)
903
904// Extra Items vars
905new Array:g_extraitem_name // caption
906new Array:g_extraitem_cost // cost
907new Array:g_extraitem_team // team
908new g_extraitem_i // loaded extra items counter
909
910// For extra items file parsing
911new Array:g_extraitem2_realname, Array:g_extraitem2_name, Array:g_extraitem2_cost,
912Array:g_extraitem2_team, Array:g_extraitem_new
913
914// Zombie Classes vars
915new Array:g_zclass_name // caption
916new Array:g_zclass_info // description
917new Array:g_zclass_modelsstart // start position in models array
918new Array:g_zclass_modelsend // end position in models array
919new Array:g_zclass_playermodel // player models array
920new Array:g_zclass_modelindex // model indices array
921new Array:g_zclass_clawmodel // claw model
922new Array:g_zclass_hp // health
923new Array:g_zclass_spd // speed
924new Array:g_zclass_grav // gravity
925new Array:g_zclass_kb // knockback
926new g_zclass_i // loaded zombie classes counter
927
928// For zombie classes file parsing
929new Array:g_zclass2_realname, Array:g_zclass2_name, Array:g_zclass2_info,
930Array:g_zclass2_modelsstart, Array:g_zclass2_modelsend, Array:g_zclass2_playermodel,
931Array:g_zclass2_modelindex, Array:g_zclass2_clawmodel, Array:g_zclass2_hp,
932Array:g_zclass2_spd, Array:g_zclass2_grav, Array:g_zclass2_kb, Array:g_zclass_new
933
934// Customization vars
935new g_access_flag[MAX_ACCESS_FLAGS], Array:model_nemesis, Array:model_survivor, Array:model_human,
936Array:model_admin_zombie, Array:model_admin_human, Array:g_modelindex_human,
937Array:g_modelindex_nemesis, Array:g_modelindex_survivor, g_same_models_for_all,
938Array:g_modelindex_admin_zombie, Array:g_modelindex_admin_human, model_vknife_human[64],
939model_vknife_nemesis[64], model_vweapon_survivor[64], model_grenade_infect[64],
940model_grenade_fire[64], model_grenade_frost[64], model_grenade_flare[64],
941model_vknife_admin_human[64], model_vknife_admin_zombie[64],
942sprite_grenade_trail[64], sprite_grenade_ring[64], sprite_grenade_fire[64],
943sprite_grenade_smoke[64], sprite_grenade_glass[64], Array:sound_win_zombies,
944Array:sound_win_humans, Array:sound_win_no_one, Array:sound_win_zombies_ismp3,
945Array:sound_win_humans_ismp3, Array:sound_win_no_one_ismp3, Array:zombie_infect,
946Array:zombie_idle, Array:zombie_pain, Array:nemesis_pain, Array:zombie_die, Array:zombie_fall,
947Array:zombie_miss_wall, Array:zombie_hit_normal, Array:zombie_hit_stab, g_ambience_rain,
948Array:zombie_idle_last, Array:zombie_madness, Array:sound_nemesis, Array:sound_survivor,
949Array:sound_swarm, Array:sound_multi, Array:sound_plague, Array:grenade_infect,
950Array:grenade_infect_player, Array:grenade_fire, Array:grenade_fire_player,
951Array:grenade_frost, Array:grenade_frost_player, Array:grenade_frost_break,
952Array:grenade_flare, Array:sound_antidote, Array:sound_thunder, g_ambience_sounds[MAX_AMBIENCE_SOUNDS],
953Array:sound_ambience1, Array:sound_ambience2, Array:sound_ambience3, Array:sound_ambience4,
954Array:sound_ambience5, Array:sound_ambience1_duration, Array:sound_ambience2_duration,
955Array:sound_ambience3_duration, Array:sound_ambience4_duration,
956Array:sound_ambience5_duration, Array:sound_ambience1_ismp3, Array:sound_ambience2_ismp3,
957Array:sound_ambience3_ismp3, Array:sound_ambience4_ismp3, Array:sound_ambience5_ismp3,
958Array:g_primary_items, Array:g_secondary_items, Array:g_additional_items,
959Array:g_primary_weaponids, Array:g_secondary_weaponids, Array:g_extraweapon_names,
960Array:g_extraweapon_items, Array:g_extraweapon_costs, g_extra_costs2[EXTRA_WEAPONS_STARTID],
961g_ambience_snow, g_ambience_fog, g_fog_density[10], g_fog_color[12], g_sky_enable,
962Array:g_sky_names, Array:lights_thunder, Array:zombie_decals, Array:g_objective_ents,
963Float:g_modelchange_delay, g_set_modelindex_offset, g_handle_models_on_separate_ent,
964Float:kb_weapon_power[31] = { -1.0, ... }, Array:zombie_miss_slash, g_force_consistency,
965Array:model_assassin, Array:model_sniper, Array:g_modelindex_assassin, Array:g_modelindex_sniper, model_vknife_assassin[64],
966model_vawp_sniper[64], model_pawp_sniper[64], Array:assassin_pain, Array:sound_assassin, Array:sound_sniper, Array:sound_ambience6,
967Array:sound_ambience6_duration, Array:sound_ambience6_ismp3, Array:sound_ambience7, Array:sound_ambience7_duration, Array:sound_ambience7_ismp3,
968Array: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,
969Array:sound_ambience8_ismp3, Array:sound_ambience8, Array:sound_ambience8_duration
970
971
972// CVAR pointers
973new cvar_lighting, cvar_zombiefov, cvar_plague, cvar_plaguechance, cvar_zombiefirsthp,
974cvar_removemoney, cvar_thunder, cvar_zombiebonushp, cvar_nemhp, cvar_nem, cvar_surv,
975cvar_nemchance, cvar_deathmatch, cvar_nemglow, cvar_customnvg, cvar_hitzones, cvar_humanhp,
976cvar_nemgravity, cvar_flashsize, cvar_ammodamage_human, cvar_ammodamage_zombie,
977cvar_zombiearmor, cvar_survpainfree, cvar_nempainfree, cvar_nemspd, cvar_survchance,
978cvar_survhp, cvar_survspd, cvar_humanspd, cvar_swarmchance, cvar_flashdrain,
979cvar_zombiebleeding, cvar_removedoors, cvar_customflash, cvar_randspawn, cvar_multi,
980cvar_multichance, cvar_infammo, cvar_swarm, cvar_ammoinfect, cvar_toggle,
981cvar_knockbackpower, cvar_freezeduration, cvar_triggered, cvar_flashcharge,
982cvar_firegrenades, cvar_frostgrenades, cvar_survgravity, cvar_logcommands, cvar_survglow,
983cvar_humangravity, cvar_spawnprotection, cvar_nvgsize, cvar_flareduration, cvar_zclasses,
984cvar_extraitems, cvar_showactivity, cvar_humanlasthp, cvar_nemignorefrags, cvar_warmup,
985cvar_flashdist, cvar_flarecolor, cvar_survignorefrags, cvar_fireduration, cvar_firedamage,
986cvar_flaregrenades, cvar_knockbackducking, cvar_knockbackdamage, cvar_knockbackzvel,
987cvar_multiratio, cvar_flaresize, cvar_spawndelay, cvar_extraantidote, cvar_extramadness,
988cvar_extraweapons, cvar_extranvision, cvar_nvggive, cvar_preventconsecutive, cvar_botquota,
989cvar_buycustom, cvar_zombiepainfree, cvar_fireslowdown, cvar_survbasehp, cvar_survaura,
990cvar_nemignoreammo, cvar_survignoreammo, cvar_nemaura, cvar_extrainfbomb, cvar_knockback,
991cvar_fragsinfect, cvar_fragskill, cvar_humanarmor, cvar_zombiesilent, cvar_removedropped,
992cvar_plagueratio, cvar_blocksuicide, cvar_knockbackdist, cvar_nemdamage, cvar_leapzombies,
993cvar_leapzombiesforce, cvar_leapzombiesheight, cvar_leapzombiescooldown, cvar_leapnemesis,
994cvar_leapnemesisforce, cvar_leapnemesisheight, cvar_leapnemesiscooldown, cvar_leapsurvivor,
995cvar_leapsurvivorforce, cvar_leapsurvivorheight, cvar_nemminplayers, cvar_survminplayers,
996cvar_respawnonsuicide, cvar_respawnafterlast, cvar_leapsurvivorcooldown, cvar_statssave,
997cvar_swarmminplayers, cvar_multiminplayers, cvar_plagueminplayers, cvar_adminmodelshuman,
998cvar_adminmodelszombie, cvar_nembasehp, cvar_blockpushables, cvar_respawnworldspawnkill,
999cvar_madnessduration, cvar_plaguenemnum, cvar_plaguenemhpmulti, cvar_plaguesurvhpmulti,
1000cvar_plaguesurvnum, cvar_infectionscreenfade, cvar_infectionscreenshake,
1001cvar_infectionsparkle, cvar_infectiontracers, cvar_infectionparticles, cvar_infbomblimit,
1002cvar_allowrespawnsurv, cvar_flashshowall, cvar_allowrespawninfection, cvar_allowrespawnnem,
1003cvar_allowrespawnswarm, cvar_allowrespawnplague, cvar_survinfammo, cvar_nemknockback,
1004cvar_nvgcolor[3], cvar_nemnvgcolor[3], cvar_humnvgcolor[3], cvar_flashcolor[3],
1005cvar_hudicons, cvar_respawnzomb, cvar_respawnhum, cvar_respawnnem, cvar_respawnsurv,
1006cvar_startammopacks, cvar_randweapons, cvar_antidotelimit, cvar_madnesslimit,
1007cvar_adminknifemodelshuman, cvar_adminknifemodelszombie, cvar_keephealthondisconnect,
1008cvar_buyzonetime, cvar_huddisplay, cvar_leapsniper, cvar_leapsniperforce, cvar_leapsniperheight,
1009cvar_leapsnipercooldown, cvar_sniminplayers, cvar_leapassassin, cvar_leapassassinforce, cvar_leapassassinheight,
1010cvar_leapassassincooldown, cvar_sni, cvar_snipainfree, cvar_snichance, cvar_snihp, cvar_snispd,
1011cvar_snigravity, cvar_sniglow, cvar_assahp, cvar_assa, cvar_assachance, cvar_assagravity, cvar_assaglow,
1012cvar_assapainfree, cvar_assaspd, cvar_assadamage, cvar_snibasehp, cvar_sniaura, cvar_assaminplayers,
1013cvar_assabasehp, cvar_allowrespawnassa, cvar_assaknockback, cvar_assanvgcolor[3], cvar_respawnassa, cvar_snidamage, cvar_allowrespawnsni,
1014cvar_sniinfammo, cvar_respawnsni, cvar_assaaura, cvar_assaignoreammo, cvar_assaignorefrags, cvar_snipignorefrags, cvar_snipignoreammo,
1015cvar_armage, cvar_armagechance, cvar_armageminplayers, cvar_armageratio, cvar_armagenemhpmulti, cvar_armagesurvhpmulti, cvar_apoc, cvar_apocchance,
1016cvar_apocminplayers, cvar_apocratio, cvar_apocassahpmulti, cvar_apocsniphpmulti, cvar_night, cvar_nightchance, cvar_nightminplayers, cvar_nightratio,
1017cvar_nightassahpmulti, cvar_nightsniphpmulti, cvar_nightnemhpmulti, cvar_nightsurvhpmulti, cvar_allowrespawnarmage, cvar_allowrespawnapoc, cvar_allowrespawnnight, cvar_aiminfo, cvar_dmg_while_freeze
1018
1019// Cached stuff for players
1020new g_isconnected[33] // whether player is connected
1021new g_isalive[33] // whether player is alive
1022new g_isbot[33] // whether player is a bot
1023new g_currentweapon[33] // player's current weapon id
1024new g_playername[33][32] // player's name
1025new Float:g_zombie_spd[33] // zombie class speed
1026new Float:g_zombie_knockback[33] // zombie class knockback
1027new g_zombie_classname[33][32] // zombie class name
1028#define is_user_valid_connected(%1) (1 <= %1 <= g_maxplayers && g_isconnected[%1])
1029#define is_user_valid_alive(%1) (1 <= %1 <= g_maxplayers && g_isalive[%1])
1030#define is_user_valid(%1) (1 <= %1 <= g_maxplayers)
1031
1032// Cached CVARs
1033new g_cached_customflash, g_cached_zombiesilent, g_cached_leapzombies, g_cached_leapnemesis,
1034g_cached_leapsurvivor, Float:g_cached_leapzombiescooldown, Float:g_cached_leapnemesiscooldown, g_cached_leapassassin, Float:g_cached_leapassassincooldown,
1035Float:g_cached_leapsurvivorcooldown, Float:g_cached_buytime, g_cached_leapsniper, Float:g_cached_leapsnipercooldown
1036
1037
1038/*================================================================================
1039 [Natives, Precache and Init]
1040=================================================================================*/
1041
1042public plugin_natives()
1043{
1044 // Player specific natives
1045 register_native("zp_get_user_zombie", "native_get_user_zombie", 1)
1046 register_native("zp_get_user_nemesis", "native_get_user_nemesis", 1)
1047 register_native("zp_get_user_assassin", "native_get_user_assassin", 1)
1048 register_native("zp_get_user_survivor", "native_get_user_survivor", 1)
1049 register_native("zp_get_user_sniper", "native_get_user_sniper", 1)
1050 register_native("zp_get_user_first_zombie", "native_get_user_first_zombie", 1)
1051 register_native("zp_get_user_last_zombie", "native_get_user_last_zombie", 1)
1052 register_native("zp_get_user_last_human", "native_get_user_last_human", 1)
1053 register_native("zp_get_user_zombie_class", "native_get_user_zombie_class", 1)
1054 register_native("zp_get_user_next_class", "native_get_user_next_class", 1)
1055 register_native("zp_set_user_zombie_class", "native_set_user_zombie_class", 1)
1056 register_native("zp_get_user_ammo_packs", "native_get_user_ammo_packs", 1)
1057 register_native("zp_set_user_ammo_packs", "native_set_user_ammo_packs", 1)
1058 register_native("zp_get_zombie_maxhealth", "native_get_zombie_maxhealth", 1)
1059 register_native("zp_get_user_batteries", "native_get_user_batteries", 1)
1060 register_native("zp_set_user_batteries", "native_set_user_batteries", 1)
1061 register_native("zp_get_user_nightvision", "native_get_user_nightvision", 1)
1062 register_native("zp_set_user_nightvision", "native_set_user_nightvision", 1)
1063 register_native("zp_infect_user", "native_infect_user", 1)
1064 register_native("zp_disinfect_user", "native_disinfect_user", 1)
1065 register_native("zp_make_user_nemesis", "native_make_user_nemesis", 1)
1066 register_native("zp_make_user_assassin", "native_make_user_assassin", 1)
1067 register_native("zp_make_user_survivor", "native_make_user_survivor", 1)
1068 register_native("zp_make_user_sniper", "native_make_user_sniper", 1)
1069 register_native("zp_respawn_user", "native_respawn_user", 1)
1070 register_native("zp_force_buy_extra_item", "native_force_buy_extra_item", 1)
1071 register_native("zp_override_user_model", "native_override_user_model", 1)
1072
1073 // new natives
1074 register_native("zp_get_user_model", "native_get_user_model", 0)
1075 register_native("zp_set_user_model", "native_set_user_model", 1)
1076
1077 // Round natives
1078 register_native("zp_has_round_started", "native_has_round_started", 1)
1079 register_native("zp_is_nemesis_round", "native_is_nemesis_round", 1)
1080 register_native("zp_is_assassin_round", "native_is_assassin_round", 1)
1081 register_native("zp_is_survivor_round", "native_is_survivor_round", 1)
1082 register_native("zp_is_sniper_round", "native_is_sniper_round", 1)
1083 register_native("zp_is_swarm_round", "native_is_swarm_round", 1)
1084 register_native("zp_is_plague_round", "native_is_plague_round", 1)
1085 register_native("zp_is_armageddon_round", "native_is_armageddon_round", 1)
1086 register_native("zp_is_apocalypse_round", "native_is_apocalypse_round", 1)
1087 register_native("zp_is_nightmare_round", "native_is_nightmare_round", 1)
1088 register_native("zp_get_zombie_count", "native_get_zombie_count", 1)
1089 register_native("zp_get_human_count", "native_get_human_count", 1)
1090 register_native("zp_get_nemesis_count", "native_get_nemesis_count", 1)
1091 register_native("zp_get_assassin_count", "native_get_assassin_count", 1)
1092 register_native("zp_get_survivor_count", "native_get_survivor_count", 1)
1093 register_native("zp_get_sniper_count", "native_get_sniper_count", 1)
1094
1095 // External additions natives
1096 register_native("zp_register_extra_item", "native_register_extra_item", 1)
1097 register_native("zp_register_zombie_class", "native_register_zombie_class", 1)
1098 register_native("zp_get_extra_item_id", "native_get_extra_item_id", 1)
1099 register_native("zp_get_zombie_class_id", "native_get_zombie_class_id", 1)
1100 register_native("zp_get_zombie_class_info", "native_get_zombie_class_info", 1)
1101}
1102
1103public plugin_precache()
1104{
1105 // Register earlier to show up in plugins list properly after plugin disable/error at loading
1106 register_plugin("Zombie Plague", PLUGIN_VERSION, "MeRcyLeZZ")
1107
1108 // To switch plugin on/off
1109 register_concmd("zp_toggle", "cmd_toggle", _, "<1/0> - Enable/Disable Zombie Plague (will restart the current map)", 0)
1110 cvar_toggle = register_cvar("zp_on", "1")
1111
1112 // Plugin disabled?
1113 if (!get_pcvar_num(cvar_toggle)) return;
1114 g_pluginenabled = true
1115
1116 // Initialize a few dynamically sized arrays (alright, maybe more than just a few...)
1117 model_human = ArrayCreate(32, 1)
1118 model_nemesis = ArrayCreate(32, 1)
1119 model_assassin = ArrayCreate(32, 1)
1120 model_survivor = ArrayCreate(32, 1)
1121 model_sniper = ArrayCreate(32, 1)
1122 model_admin_human = ArrayCreate(32, 1)
1123 model_admin_zombie = ArrayCreate(32, 1)
1124 g_modelindex_human = ArrayCreate(1, 1)
1125 g_modelindex_nemesis = ArrayCreate(1, 1)
1126 g_modelindex_assassin = ArrayCreate(1, 1)
1127 g_modelindex_survivor = ArrayCreate(1, 1)
1128 g_modelindex_sniper = ArrayCreate(1, 1)
1129 g_modelindex_admin_human = ArrayCreate(1, 1)
1130 g_modelindex_admin_zombie = ArrayCreate(1, 1)
1131 sound_win_zombies = ArrayCreate(64, 1)
1132 sound_win_zombies_ismp3 = ArrayCreate(1, 1)
1133 sound_win_humans = ArrayCreate(64, 1)
1134 sound_win_humans_ismp3 = ArrayCreate(1, 1)
1135 sound_win_no_one = ArrayCreate(64, 1)
1136 sound_win_no_one_ismp3 = ArrayCreate(1, 1)
1137 zombie_infect = ArrayCreate(64, 1)
1138 zombie_pain = ArrayCreate(64, 1)
1139 nemesis_pain = ArrayCreate(64, 1)
1140 assassin_pain = ArrayCreate(64, 1)
1141 zombie_die = ArrayCreate(64, 1)
1142 zombie_fall = ArrayCreate(64, 1)
1143 zombie_miss_slash = ArrayCreate(64, 1)
1144 zombie_miss_wall = ArrayCreate(64, 1)
1145 zombie_hit_normal = ArrayCreate(64, 1)
1146 zombie_hit_stab = ArrayCreate(64, 1)
1147 zombie_idle = ArrayCreate(64, 1)
1148 zombie_idle_last = ArrayCreate(64, 1)
1149 zombie_madness = ArrayCreate(64, 1)
1150 sound_nemesis = ArrayCreate(64, 1)
1151 sound_assassin = ArrayCreate(64, 1)
1152 sound_survivor = ArrayCreate(64, 1)
1153 sound_sniper = ArrayCreate(64, 1)
1154 sound_swarm = ArrayCreate(64, 1)
1155 sound_multi = ArrayCreate(64, 1)
1156 sound_plague = ArrayCreate(64, 1)
1157 sound_armageddon = ArrayCreate(64, 1)
1158 sound_apocalypse = ArrayCreate(64, 1)
1159 sound_nightmare = ArrayCreate(64, 1)
1160 grenade_infect = ArrayCreate(64, 1)
1161 grenade_infect_player = ArrayCreate(64, 1)
1162 grenade_fire = ArrayCreate(64, 1)
1163 grenade_fire_player = ArrayCreate(64, 1)
1164 grenade_frost = ArrayCreate(64, 1)
1165 grenade_frost_player = ArrayCreate(64, 1)
1166 grenade_frost_break = ArrayCreate(64, 1)
1167 grenade_flare = ArrayCreate(64, 1)
1168 sound_antidote = ArrayCreate(64, 1)
1169 sound_thunder = ArrayCreate(64, 1)
1170 sound_ambience1 = ArrayCreate(64, 1)
1171 sound_ambience2 = ArrayCreate(64, 1)
1172 sound_ambience3 = ArrayCreate(64, 1)
1173 sound_ambience4 = ArrayCreate(64, 1)
1174 sound_ambience5 = ArrayCreate(64, 1)
1175 sound_ambience6 = ArrayCreate(64, 1)
1176 sound_ambience7 = ArrayCreate(64, 1)
1177 sound_ambience8 = ArrayCreate(64, 1)
1178 sound_ambience9 = ArrayCreate(64, 1)
1179 sound_ambience10 = ArrayCreate(64, 1)
1180 sound_ambience1_duration = ArrayCreate(1, 1)
1181 sound_ambience2_duration = ArrayCreate(1, 1)
1182 sound_ambience3_duration = ArrayCreate(1, 1)
1183 sound_ambience4_duration = ArrayCreate(1, 1)
1184 sound_ambience5_duration = ArrayCreate(1, 1)
1185 sound_ambience6_duration = ArrayCreate(1, 1)
1186 sound_ambience7_duration = ArrayCreate(1, 1)
1187 sound_ambience8_duration = ArrayCreate(1, 1)
1188 sound_ambience9_duration = ArrayCreate(1, 1)
1189 sound_ambience10_duration = ArrayCreate(1, 1)
1190 sound_ambience1_ismp3 = ArrayCreate(1, 1)
1191 sound_ambience2_ismp3 = ArrayCreate(1, 1)
1192 sound_ambience3_ismp3 = ArrayCreate(1, 1)
1193 sound_ambience4_ismp3 = ArrayCreate(1, 1)
1194 sound_ambience5_ismp3 = ArrayCreate(1, 1)
1195 sound_ambience6_ismp3 = ArrayCreate(1, 1)
1196 sound_ambience7_ismp3 = ArrayCreate(1, 1)
1197 sound_ambience8_ismp3 = ArrayCreate(1, 1)
1198 sound_ambience9_ismp3 = ArrayCreate(1, 1)
1199 sound_ambience10_ismp3 = ArrayCreate(1, 1)
1200 g_primary_items = ArrayCreate(32, 1)
1201 g_secondary_items = ArrayCreate(32, 1)
1202 g_additional_items = ArrayCreate(32, 1)
1203 g_primary_weaponids = ArrayCreate(1, 1)
1204 g_secondary_weaponids = ArrayCreate(1, 1)
1205 g_extraweapon_names = ArrayCreate(32, 1)
1206 g_extraweapon_items = ArrayCreate(32, 1)
1207 g_extraweapon_costs = ArrayCreate(1, 1)
1208 g_sky_names = ArrayCreate(32, 1)
1209 lights_thunder = ArrayCreate(32, 1)
1210 zombie_decals = ArrayCreate(1, 1)
1211 g_objective_ents = ArrayCreate(32, 1)
1212 g_extraitem_name = ArrayCreate(32, 1)
1213 g_extraitem_cost = ArrayCreate(1, 1)
1214 g_extraitem_team = ArrayCreate(1, 1)
1215 g_extraitem2_realname = ArrayCreate(32, 1)
1216 g_extraitem2_name = ArrayCreate(32, 1)
1217 g_extraitem2_cost = ArrayCreate(1, 1)
1218 g_extraitem2_team = ArrayCreate(1, 1)
1219 g_extraitem_new = ArrayCreate(1, 1)
1220 g_zclass_name = ArrayCreate(32, 1)
1221 g_zclass_info = ArrayCreate(32, 1)
1222 g_zclass_modelsstart = ArrayCreate(1, 1)
1223 g_zclass_modelsend = ArrayCreate(1, 1)
1224 g_zclass_playermodel = ArrayCreate(32, 1)
1225 g_zclass_modelindex = ArrayCreate(1, 1)
1226 g_zclass_clawmodel = ArrayCreate(32, 1)
1227 g_zclass_hp = ArrayCreate(1, 1)
1228 g_zclass_spd = ArrayCreate(1, 1)
1229 g_zclass_grav = ArrayCreate(1, 1)
1230 g_zclass_kb = ArrayCreate(1, 1)
1231 g_zclass2_realname = ArrayCreate(32, 1)
1232 g_zclass2_name = ArrayCreate(32, 1)
1233 g_zclass2_info = ArrayCreate(32, 1)
1234 g_zclass2_modelsstart = ArrayCreate(1, 1)
1235 g_zclass2_modelsend = ArrayCreate(1, 1)
1236 g_zclass2_playermodel = ArrayCreate(32, 1)
1237 g_zclass2_modelindex = ArrayCreate(1, 1)
1238 g_zclass2_clawmodel = ArrayCreate(32, 1)
1239 g_zclass2_hp = ArrayCreate(1, 1)
1240 g_zclass2_spd = ArrayCreate(1, 1)
1241 g_zclass2_grav = ArrayCreate(1, 1)
1242 g_zclass2_kb = ArrayCreate(1, 1)
1243 g_zclass_new = ArrayCreate(1, 1)
1244
1245 // Allow registering stuff now
1246 g_arrays_created = true
1247
1248 // Load customization data
1249 load_customization_from_files()
1250
1251 new i, buffer[100]
1252
1253 // Load up the hard coded extra items
1254 native_register_extra_item2("NightVision", g_extra_costs2[EXTRA_NVISION], ZP_TEAM_HUMAN)
1255 native_register_extra_item2("T-Virus Antidote", g_extra_costs2[EXTRA_ANTIDOTE], ZP_TEAM_ZOMBIE)
1256 native_register_extra_item2("Zombie Madness", g_extra_costs2[EXTRA_MADNESS], ZP_TEAM_ZOMBIE)
1257 native_register_extra_item2("Infection Bomb", g_extra_costs2[EXTRA_INFBOMB], ZP_TEAM_ZOMBIE)
1258
1259 // Extra weapons
1260 for (i = 0; i < ArraySize(g_extraweapon_names); i++)
1261 {
1262 ArrayGetString(g_extraweapon_names, i, buffer, charsmax(buffer))
1263 native_register_extra_item2(buffer, ArrayGetCell(g_extraweapon_costs, i), ZP_TEAM_HUMAN)
1264 }
1265
1266 // Custom player models
1267 for (i = 0; i < ArraySize(model_human); i++)
1268 {
1269 ArrayGetString(model_human, i, buffer, charsmax(buffer))
1270 format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
1271 ArrayPushCell(g_modelindex_human, engfunc(EngFunc_PrecacheModel, buffer))
1272 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
1273 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
1274 // Precache modelT.mdl files too
1275 copy(buffer[strlen(buffer)-4], charsmax(buffer) - (strlen(buffer)-4), "T.mdl")
1276 if (file_exists(buffer)) engfunc(EngFunc_PrecacheModel, buffer)
1277 }
1278 for (i = 0; i < ArraySize(model_nemesis); i++)
1279 {
1280 ArrayGetString(model_nemesis, i, buffer, charsmax(buffer))
1281 format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
1282 ArrayPushCell(g_modelindex_nemesis, engfunc(EngFunc_PrecacheModel, buffer))
1283 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
1284 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
1285 // Precache modelT.mdl files too
1286 copy(buffer[strlen(buffer)-4], charsmax(buffer) - (strlen(buffer)-4), "T.mdl")
1287 if (file_exists(buffer)) engfunc(EngFunc_PrecacheModel, buffer)
1288 }
1289 for (i = 0; i < ArraySize(model_assassin); i++)
1290 {
1291 ArrayGetString(model_assassin, i, buffer, charsmax(buffer))
1292 format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
1293 ArrayPushCell(g_modelindex_assassin, engfunc(EngFunc_PrecacheModel, buffer))
1294 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
1295 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
1296 }
1297 for (i = 0; i < ArraySize(model_survivor); i++)
1298 {
1299 ArrayGetString(model_survivor, i, buffer, charsmax(buffer))
1300 format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
1301 ArrayPushCell(g_modelindex_survivor, engfunc(EngFunc_PrecacheModel, buffer))
1302 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
1303 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
1304 // Precache modelT.mdl files too
1305 copy(buffer[strlen(buffer)-4], charsmax(buffer) - (strlen(buffer)-4), "T.mdl")
1306 if (file_exists(buffer)) engfunc(EngFunc_PrecacheModel, buffer)
1307 }
1308 for (i = 0; i < ArraySize(model_sniper); i++)
1309 {
1310 ArrayGetString(model_sniper, i, buffer, charsmax(buffer))
1311 format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
1312 ArrayPushCell(g_modelindex_sniper, engfunc(EngFunc_PrecacheModel, buffer))
1313 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
1314 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
1315 }
1316 for (i = 0; i < ArraySize(model_admin_zombie); i++)
1317 {
1318 ArrayGetString(model_admin_zombie, i, buffer, charsmax(buffer))
1319 format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
1320 ArrayPushCell(g_modelindex_admin_zombie, engfunc(EngFunc_PrecacheModel, buffer))
1321 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
1322 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
1323 // Precache modelT.mdl files too
1324 copy(buffer[strlen(buffer)-4], charsmax(buffer) - (strlen(buffer)-4), "T.mdl")
1325 if (file_exists(buffer)) engfunc(EngFunc_PrecacheModel, buffer)
1326 }
1327 for (i = 0; i < ArraySize(model_admin_human); i++)
1328 {
1329 ArrayGetString(model_admin_human, i, buffer, charsmax(buffer))
1330 format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
1331 ArrayPushCell(g_modelindex_admin_human, engfunc(EngFunc_PrecacheModel, buffer))
1332 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
1333 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
1334 // Precache modelT.mdl files too
1335 copy(buffer[strlen(buffer)-4], charsmax(buffer) - (strlen(buffer)-4), "T.mdl")
1336 if (file_exists(buffer)) engfunc(EngFunc_PrecacheModel, buffer)
1337 }
1338
1339 // Custom weapon models
1340 engfunc(EngFunc_PrecacheModel, model_vknife_human)
1341 engfunc(EngFunc_PrecacheModel, model_vknife_nemesis)
1342 engfunc(EngFunc_PrecacheModel, model_vknife_assassin)
1343 engfunc(EngFunc_PrecacheModel, model_vweapon_survivor)
1344 engfunc(EngFunc_PrecacheModel, model_vawp_sniper)
1345 engfunc(EngFunc_PrecacheModel, model_pawp_sniper)
1346 engfunc(EngFunc_PrecacheModel, model_grenade_infect)
1347 engfunc(EngFunc_PrecacheModel, model_grenade_fire)
1348 engfunc(EngFunc_PrecacheModel, model_grenade_frost)
1349 engfunc(EngFunc_PrecacheModel, model_grenade_flare)
1350 engfunc(EngFunc_PrecacheModel, model_vknife_admin_human)
1351 engfunc(EngFunc_PrecacheModel, model_vknife_admin_zombie)
1352
1353 // Custom sprites for grenades
1354 g_trailSpr = engfunc(EngFunc_PrecacheModel, sprite_grenade_trail)
1355 g_exploSpr = engfunc(EngFunc_PrecacheModel, sprite_grenade_ring)
1356 g_flameSpr = engfunc(EngFunc_PrecacheModel, sprite_grenade_fire)
1357 g_smokeSpr = engfunc(EngFunc_PrecacheModel, sprite_grenade_smoke)
1358 g_glassSpr = engfunc(EngFunc_PrecacheModel, sprite_grenade_glass)
1359
1360 // Custom sounds
1361 for (i = 0; i < ArraySize(sound_win_zombies); i++)
1362 {
1363 ArrayGetString(sound_win_zombies, i, buffer, charsmax(buffer))
1364 if (ArrayGetCell(sound_win_zombies_ismp3, i))
1365 {
1366 format(buffer, charsmax(buffer), "sound/%s", buffer)
1367 engfunc(EngFunc_PrecacheGeneric, buffer)
1368 }
1369 else
1370 {
1371 engfunc(EngFunc_PrecacheSound, buffer)
1372 }
1373 }
1374 for (i = 0; i < ArraySize(sound_win_humans); i++)
1375 {
1376 ArrayGetString(sound_win_humans, i, buffer, charsmax(buffer))
1377 if (ArrayGetCell(sound_win_humans_ismp3, i))
1378 {
1379 format(buffer, charsmax(buffer), "sound/%s", buffer)
1380 engfunc(EngFunc_PrecacheGeneric, buffer)
1381 }
1382 else
1383 {
1384 engfunc(EngFunc_PrecacheSound, buffer)
1385 }
1386 }
1387 for (i = 0; i < ArraySize(sound_win_no_one); i++)
1388 {
1389 ArrayGetString(sound_win_no_one, i, buffer, charsmax(buffer))
1390 if (ArrayGetCell(sound_win_no_one_ismp3, i))
1391 {
1392 format(buffer, charsmax(buffer), "sound/%s", buffer)
1393 engfunc(EngFunc_PrecacheGeneric, buffer)
1394 }
1395 else
1396 {
1397 engfunc(EngFunc_PrecacheSound, buffer)
1398 }
1399 }
1400 for (i = 0; i < ArraySize(zombie_infect); i++)
1401 {
1402 ArrayGetString(zombie_infect, i, buffer, charsmax(buffer))
1403 engfunc(EngFunc_PrecacheSound, buffer)
1404 }
1405 for (i = 0; i < ArraySize(zombie_pain); i++)
1406 {
1407 ArrayGetString(zombie_pain, i, buffer, charsmax(buffer))
1408 engfunc(EngFunc_PrecacheSound, buffer)
1409 }
1410 for (i = 0; i < ArraySize(nemesis_pain); i++)
1411 {
1412 ArrayGetString(nemesis_pain, i, buffer, charsmax(buffer))
1413 engfunc(EngFunc_PrecacheSound, buffer)
1414 }
1415 for (i = 0; i < ArraySize(assassin_pain); i++)
1416 {
1417 ArrayGetString(assassin_pain, i, buffer, charsmax(buffer))
1418 engfunc(EngFunc_PrecacheSound, buffer)
1419 }
1420 for (i = 0; i < ArraySize(zombie_die); i++)
1421 {
1422 ArrayGetString(zombie_die, i, buffer, charsmax(buffer))
1423 engfunc(EngFunc_PrecacheSound, buffer)
1424 }
1425 for (i = 0; i < ArraySize(zombie_fall); i++)
1426 {
1427 ArrayGetString(zombie_fall, i, buffer, charsmax(buffer))
1428 engfunc(EngFunc_PrecacheSound, buffer)
1429 }
1430 for (i = 0; i < ArraySize(zombie_miss_slash); i++)
1431 {
1432 ArrayGetString(zombie_miss_slash, i, buffer, charsmax(buffer))
1433 engfunc(EngFunc_PrecacheSound, buffer)
1434 }
1435 for (i = 0; i < ArraySize(zombie_miss_wall); i++)
1436 {
1437 ArrayGetString(zombie_miss_wall, i, buffer, charsmax(buffer))
1438 engfunc(EngFunc_PrecacheSound, buffer)
1439 }
1440 for (i = 0; i < ArraySize(zombie_hit_normal); i++)
1441 {
1442 ArrayGetString(zombie_hit_normal, i, buffer, charsmax(buffer))
1443 engfunc(EngFunc_PrecacheSound, buffer)
1444 }
1445 for (i = 0; i < ArraySize(zombie_hit_stab); i++)
1446 {
1447 ArrayGetString(zombie_hit_stab, i, buffer, charsmax(buffer))
1448 engfunc(EngFunc_PrecacheSound, buffer)
1449 }
1450 for (i = 0; i < ArraySize(zombie_idle); i++)
1451 {
1452 ArrayGetString(zombie_idle, i, buffer, charsmax(buffer))
1453 engfunc(EngFunc_PrecacheSound, buffer)
1454 }
1455 for (i = 0; i < ArraySize(zombie_idle_last); i++)
1456 {
1457 ArrayGetString(zombie_idle_last, i, buffer, charsmax(buffer))
1458 engfunc(EngFunc_PrecacheSound, buffer)
1459 }
1460 for (i = 0; i < ArraySize(zombie_madness); i++)
1461 {
1462 ArrayGetString(zombie_madness, i, buffer, charsmax(buffer))
1463 engfunc(EngFunc_PrecacheSound, buffer)
1464 }
1465 for (i = 0; i < ArraySize(sound_nemesis); i++)
1466 {
1467 ArrayGetString(sound_nemesis, i, buffer, charsmax(buffer))
1468 engfunc(EngFunc_PrecacheSound, buffer)
1469 }
1470 for (i = 0; i < ArraySize(sound_assassin); i++)
1471 {
1472 ArrayGetString(sound_assassin, i, buffer, charsmax(buffer))
1473 engfunc(EngFunc_PrecacheSound, buffer)
1474 }
1475 for (i = 0; i < ArraySize(sound_survivor); i++)
1476 {
1477 ArrayGetString(sound_survivor, i, buffer, charsmax(buffer))
1478 engfunc(EngFunc_PrecacheSound, buffer)
1479 }
1480 for (i = 0; i < ArraySize(sound_sniper); i++)
1481 {
1482 ArrayGetString(sound_sniper, i, buffer, charsmax(buffer))
1483 engfunc(EngFunc_PrecacheSound, buffer)
1484 }
1485 for (i = 0; i < ArraySize(sound_swarm); i++)
1486 {
1487 ArrayGetString(sound_swarm, i, buffer, charsmax(buffer))
1488 engfunc(EngFunc_PrecacheSound, buffer)
1489 }
1490 for (i = 0; i < ArraySize(sound_multi); i++)
1491 {
1492 ArrayGetString(sound_multi, i, buffer, charsmax(buffer))
1493 engfunc(EngFunc_PrecacheSound, buffer)
1494 }
1495 for (i = 0; i < ArraySize(sound_plague); i++)
1496 {
1497 ArrayGetString(sound_plague, i, buffer, charsmax(buffer))
1498 engfunc(EngFunc_PrecacheSound, buffer)
1499 }
1500 for (i = 0; i < ArraySize(sound_armageddon); i++)
1501 {
1502 ArrayGetString(sound_armageddon, i, buffer, charsmax(buffer))
1503 engfunc(EngFunc_PrecacheSound, buffer)
1504 }
1505 for (i = 0; i < ArraySize(sound_apocalypse); i++)
1506 {
1507 ArrayGetString(sound_apocalypse, i, buffer, charsmax(buffer))
1508 engfunc(EngFunc_PrecacheSound, buffer)
1509 }
1510 for (i = 0; i < ArraySize(sound_nightmare); i++)
1511 {
1512 ArrayGetString(sound_nightmare, i, buffer, charsmax(buffer))
1513 engfunc(EngFunc_PrecacheSound, buffer)
1514 }
1515 for (i = 0; i < ArraySize(grenade_infect); i++)
1516 {
1517 ArrayGetString(grenade_infect, i, buffer, charsmax(buffer))
1518 engfunc(EngFunc_PrecacheSound, buffer)
1519 }
1520 for (i = 0; i < ArraySize(grenade_infect_player); i++)
1521 {
1522 ArrayGetString(grenade_infect_player, i, buffer, charsmax(buffer))
1523 engfunc(EngFunc_PrecacheSound, buffer)
1524 }
1525 for (i = 0; i < ArraySize(grenade_fire); i++)
1526 {
1527 ArrayGetString(grenade_fire, i, buffer, charsmax(buffer))
1528 engfunc(EngFunc_PrecacheSound, buffer)
1529 }
1530 for (i = 0; i < ArraySize(grenade_fire_player); i++)
1531 {
1532 ArrayGetString(grenade_fire_player, i, buffer, charsmax(buffer))
1533 engfunc(EngFunc_PrecacheSound, buffer)
1534 }
1535 for (i = 0; i < ArraySize(grenade_frost); i++)
1536 {
1537 ArrayGetString(grenade_frost, i, buffer, charsmax(buffer))
1538 engfunc(EngFunc_PrecacheSound, buffer)
1539 }
1540 for (i = 0; i < ArraySize(grenade_frost_player); i++)
1541 {
1542 ArrayGetString(grenade_frost_player, i, buffer, charsmax(buffer))
1543 engfunc(EngFunc_PrecacheSound, buffer)
1544 }
1545 for (i = 0; i < ArraySize(grenade_frost_break); i++)
1546 {
1547 ArrayGetString(grenade_frost_break, i, buffer, charsmax(buffer))
1548 engfunc(EngFunc_PrecacheSound, buffer)
1549 }
1550 for (i = 0; i < ArraySize(grenade_flare); i++)
1551 {
1552 ArrayGetString(grenade_flare, i, buffer, charsmax(buffer))
1553 engfunc(EngFunc_PrecacheSound, buffer)
1554 }
1555 for (i = 0; i < ArraySize(sound_antidote); i++)
1556 {
1557 ArrayGetString(sound_antidote, i, buffer, charsmax(buffer))
1558 engfunc(EngFunc_PrecacheSound, buffer)
1559 }
1560 for (i = 0; i < ArraySize(sound_thunder); i++)
1561 {
1562 ArrayGetString(sound_thunder, i, buffer, charsmax(buffer))
1563 engfunc(EngFunc_PrecacheSound, buffer)
1564 }
1565
1566 // Ambience Sounds
1567 if (g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION])
1568 {
1569 for (i = 0; i < ArraySize(sound_ambience1); i++)
1570 {
1571 ArrayGetString(sound_ambience1, i, buffer, charsmax(buffer))
1572
1573 if (ArrayGetCell(sound_ambience1_ismp3, i))
1574 {
1575 format(buffer, charsmax(buffer), "sound/%s", buffer)
1576 engfunc(EngFunc_PrecacheGeneric, buffer)
1577 }
1578 else
1579 {
1580 engfunc(EngFunc_PrecacheSound, buffer)
1581 }
1582 }
1583 }
1584 if (g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS])
1585 {
1586 for (i = 0; i < ArraySize(sound_ambience2); i++)
1587 {
1588 ArrayGetString(sound_ambience2, i, buffer, charsmax(buffer))
1589
1590 if (ArrayGetCell(sound_ambience2_ismp3, i))
1591 {
1592 format(buffer, charsmax(buffer), "sound/%s", buffer)
1593 engfunc(EngFunc_PrecacheGeneric, buffer)
1594 }
1595 else
1596 {
1597 engfunc(EngFunc_PrecacheSound, buffer)
1598 }
1599 }
1600 }
1601 if (g_ambience_sounds[AMBIENCE_SOUNDS_ASSASSIN])
1602 {
1603 for (i = 0; i < ArraySize(sound_ambience6); i++)
1604 {
1605 ArrayGetString(sound_ambience6, i, buffer, charsmax(buffer))
1606
1607 if (ArrayGetCell(sound_ambience6_ismp3, i))
1608 {
1609 format(buffer, charsmax(buffer), "sound/%s", buffer)
1610 engfunc(EngFunc_PrecacheGeneric, buffer)
1611 }
1612 else
1613 {
1614 engfunc(EngFunc_PrecacheSound, buffer)
1615 }
1616 }
1617 }
1618 if (g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR])
1619 {
1620 for (i = 0; i < ArraySize(sound_ambience3); i++)
1621 {
1622 ArrayGetString(sound_ambience3, i, buffer, charsmax(buffer))
1623
1624 if (ArrayGetCell(sound_ambience3_ismp3, i))
1625 {
1626 format(buffer, charsmax(buffer), "sound/%s", buffer)
1627 engfunc(EngFunc_PrecacheGeneric, buffer)
1628 }
1629 else
1630 {
1631 engfunc(EngFunc_PrecacheSound, buffer)
1632 }
1633 }
1634 }
1635 if (g_ambience_sounds[AMBIENCE_SOUNDS_SNIPER])
1636 {
1637 for (i = 0; i < ArraySize(sound_ambience5); i++)
1638 {
1639 ArrayGetString(sound_ambience5, i, buffer, charsmax(buffer))
1640
1641 if (ArrayGetCell(sound_ambience5_ismp3, i))
1642 {
1643 format(buffer, charsmax(buffer), "sound/%s", buffer)
1644 engfunc(EngFunc_PrecacheGeneric, buffer)
1645 }
1646 else
1647 {
1648 engfunc(EngFunc_PrecacheSound, buffer)
1649 }
1650 }
1651 }
1652 if (g_ambience_sounds[AMBIENCE_SOUNDS_SWARM])
1653 {
1654 for (i = 0; i < ArraySize(sound_ambience4); i++)
1655 {
1656 ArrayGetString(sound_ambience4, i, buffer, charsmax(buffer))
1657
1658 if (ArrayGetCell(sound_ambience4_ismp3, i))
1659 {
1660 format(buffer, charsmax(buffer), "sound/%s", buffer)
1661 engfunc(EngFunc_PrecacheGeneric, buffer)
1662 }
1663 else
1664 {
1665 engfunc(EngFunc_PrecacheSound, buffer)
1666 }
1667 }
1668 }
1669 if (g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE])
1670 {
1671 for (i = 0; i < ArraySize(sound_ambience5); i++)
1672 {
1673 ArrayGetString(sound_ambience5, i, buffer, charsmax(buffer))
1674
1675 if (ArrayGetCell(sound_ambience5_ismp3, i))
1676 {
1677 format(buffer, charsmax(buffer), "sound/%s", buffer)
1678 engfunc(EngFunc_PrecacheGeneric, buffer)
1679 }
1680 else
1681 {
1682 engfunc(EngFunc_PrecacheSound, buffer)
1683 }
1684 }
1685 }
1686 if (g_ambience_sounds[AMBIENCE_SOUNDS_ARMAGEDDON])
1687 {
1688 for (i = 0; i < ArraySize(sound_ambience8); i++)
1689 {
1690 ArrayGetString(sound_ambience8, i, buffer, charsmax(buffer))
1691
1692 if (ArrayGetCell(sound_ambience8_ismp3, i))
1693 {
1694 format(buffer, charsmax(buffer), "sound/%s", buffer)
1695 engfunc(EngFunc_PrecacheGeneric, buffer)
1696 }
1697 else
1698 {
1699 engfunc(EngFunc_PrecacheSound, buffer)
1700 }
1701 }
1702 }
1703 if (g_ambience_sounds[AMBIENCE_SOUNDS_APOCALYPSE])
1704 {
1705 for (i = 0; i < ArraySize(sound_ambience9); i++)
1706 {
1707 ArrayGetString(sound_ambience9, i, buffer, charsmax(buffer))
1708
1709 if (ArrayGetCell(sound_ambience9_ismp3, i))
1710 {
1711 format(buffer, charsmax(buffer), "sound/%s", buffer)
1712 engfunc(EngFunc_PrecacheGeneric, buffer)
1713 }
1714 else
1715 {
1716 engfunc(EngFunc_PrecacheSound, buffer)
1717 }
1718 }
1719 }
1720 if (g_ambience_sounds[AMBIENCE_SOUNDS_NIGHTMARE])
1721 {
1722 for (i = 0; i < ArraySize(sound_ambience10); i++)
1723 {
1724 ArrayGetString(sound_ambience10, i, buffer, charsmax(buffer))
1725
1726 if (ArrayGetCell(sound_ambience10_ismp3, i))
1727 {
1728 format(buffer, charsmax(buffer), "sound/%s", buffer)
1729 engfunc(EngFunc_PrecacheGeneric, buffer)
1730 }
1731 else
1732 {
1733 engfunc(EngFunc_PrecacheSound, buffer)
1734 }
1735 }
1736 }
1737
1738 // CS sounds (just in case)
1739 engfunc(EngFunc_PrecacheSound, sound_flashlight)
1740 engfunc(EngFunc_PrecacheSound, sound_buyammo)
1741 engfunc(EngFunc_PrecacheSound, sound_armorhit)
1742
1743 new ent
1744
1745 // Fake Hostage (to force round ending)
1746 ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "hostage_entity"))
1747 if (pev_valid(ent))
1748 {
1749 engfunc(EngFunc_SetOrigin, ent, Float:{8192.0,8192.0,8192.0})
1750 dllfunc(DLLFunc_Spawn, ent)
1751 }
1752
1753 // Weather/ambience effects
1754 if (g_ambience_fog)
1755 {
1756 ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "env_fog"))
1757 if (pev_valid(ent))
1758 {
1759 fm_set_kvd(ent, "density", g_fog_density, "env_fog")
1760 fm_set_kvd(ent, "rendercolor", g_fog_color, "env_fog")
1761 }
1762 }
1763 if (g_ambience_rain) engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "env_rain"))
1764 if (g_ambience_snow) engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "env_snow"))
1765
1766 // Custom buyzone for all players
1767 g_buyzone_ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "func_buyzone"))
1768 if (pev_valid(g_buyzone_ent))
1769 {
1770 dllfunc(DLLFunc_Spawn, g_buyzone_ent)
1771 set_pev(g_buyzone_ent, pev_solid, SOLID_NOT)
1772 }
1773
1774 // Prevent some entities from spawning
1775 g_fwSpawn = register_forward(FM_Spawn, "fw_Spawn")
1776
1777 // Prevent hostage sounds from being precached
1778 g_fwPrecacheSound = register_forward(FM_PrecacheSound, "fw_PrecacheSound")
1779}
1780
1781public plugin_init()
1782{
1783 // Plugin disabled?
1784 if (!g_pluginenabled) return;
1785
1786 // No zombie classes?
1787 if (!g_zclass_i) set_fail_state("No zombie classes loaded!")
1788
1789 // Language files
1790 register_dictionary("zombie_plague.txt")
1791
1792 // Events
1793 register_event("HLTV", "event_round_start", "a", "1=0", "2=0")
1794 register_event("StatusValue", "event_show_status", "be", "1=2", "2!0")
1795 register_event("StatusValue", "event_hide_status", "be", "1=1", "2=0")
1796 register_logevent("logevent_round_start",2, "1=Round_Start")
1797 register_logevent("logevent_round_end", 2, "1=Round_End")
1798 register_event("AmmoX", "event_ammo_x", "be")
1799 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]
1800 || 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])
1801 register_event("30", "event_intermission", "a")
1802
1803 // HAM Forwards
1804 RegisterHam(Ham_Spawn, "player", "fw_PlayerSpawn_Post", 1)
1805 RegisterHam(Ham_Killed, "player", "fw_PlayerKilled")
1806 RegisterHam(Ham_Killed, "player", "fw_PlayerKilled_Post", 1)
1807 RegisterHam(Ham_TakeDamage, "player", "fw_TakeDamage")
1808 RegisterHam(Ham_TakeDamage, "player", "fw_TakeDamage_Post", 1)
1809 RegisterHam(Ham_TraceAttack, "player", "fw_TraceAttack")
1810 RegisterHam(Ham_Player_ResetMaxSpeed, "player", "fw_ResetMaxSpeed_Post", 1)
1811 RegisterHam(Ham_Use, "func_tank", "fw_UseStationary")
1812 RegisterHam(Ham_Use, "func_tankmortar", "fw_UseStationary")
1813 RegisterHam(Ham_Use, "func_tankrocket", "fw_UseStationary")
1814 RegisterHam(Ham_Use, "func_tanklaser", "fw_UseStationary")
1815 RegisterHam(Ham_Use, "func_tank", "fw_UseStationary_Post", 1)
1816 RegisterHam(Ham_Use, "func_tankmortar", "fw_UseStationary_Post", 1)
1817 RegisterHam(Ham_Use, "func_tankrocket", "fw_UseStationary_Post", 1)
1818 RegisterHam(Ham_Use, "func_tanklaser", "fw_UseStationary_Post", 1)
1819 RegisterHam(Ham_Use, "func_pushable", "fw_UsePushable")
1820 RegisterHam(Ham_Touch, "weaponbox", "fw_TouchWeapon")
1821 RegisterHam(Ham_Touch, "armoury_entity", "fw_TouchWeapon")
1822 RegisterHam(Ham_Touch, "weapon_shield", "fw_TouchWeapon")
1823 RegisterHam(Ham_AddPlayerItem, "player", "fw_AddPlayerItem")
1824 for (new i = 1; i < sizeof WEAPONENTNAMES; i++)
1825 if (WEAPONENTNAMES[i][0]) RegisterHam(Ham_Item_Deploy, WEAPONENTNAMES[i], "fw_Item_Deploy_Post", 1)
1826
1827 // FM Forwards
1828 register_forward(FM_ClientDisconnect, "fw_ClientDisconnect")
1829 register_forward(FM_ClientDisconnect, "fw_ClientDisconnect_Post", 1)
1830 register_forward(FM_ClientKill, "fw_ClientKill")
1831 register_forward(FM_EmitSound, "fw_EmitSound")
1832 if (!g_handle_models_on_separate_ent) register_forward(FM_SetClientKeyValue, "fw_SetClientKeyValue")
1833 register_forward(FM_ClientUserInfoChanged, "fw_ClientUserInfoChanged")
1834 register_forward(FM_GetGameDescription, "fw_GetGameDescription")
1835 register_forward(FM_SetModel, "fw_SetModel")
1836 RegisterHam(Ham_Think, "grenade", "fw_ThinkGrenade")
1837 register_forward(FM_CmdStart, "fw_CmdStart")
1838 register_forward(FM_PlayerPreThink, "fw_PlayerPreThink")
1839 unregister_forward(FM_Spawn, g_fwSpawn)
1840 unregister_forward(FM_PrecacheSound, g_fwPrecacheSound)
1841
1842 // Client commands
1843 register_clcmd("say zpmenu", "clcmd_saymenu")
1844 register_clcmd("say /zpmenu", "clcmd_saymenu")
1845 register_clcmd("say unstuck", "clcmd_sayunstuck")
1846 register_clcmd("say /unstuck", "clcmd_sayunstuck")
1847 register_clcmd("nightvision", "clcmd_nightvision")
1848 register_clcmd("drop", "clcmd_drop")
1849 register_clcmd("buyammo1", "clcmd_buyammo")
1850 register_clcmd("buyammo2", "clcmd_buyammo")
1851 register_clcmd("chooseteam", "clcmd_changeteam")
1852 register_clcmd("jointeam", "clcmd_changeteam")
1853
1854 // Menus
1855 register_menu("Game Menu", KEYSMENU, "menu_game")
1856 register_menu("Buy Menu 1", KEYSMENU, "menu_buy1")
1857 register_menu("Buy Menu 2", KEYSMENU, "menu_buy2")
1858 register_menu("Mod Info", KEYSMENU, "menu_info")
1859 register_menu("Admin Menu", KEYSMENU, "menu_admin")
1860 register_menu("Admin Modes Menu", KEYSMENU, "menu_modes_admin")
1861
1862 // CS Buy Menus (to prevent zombies/survivor from buying)
1863 register_menucmd(register_menuid("#Buy", 1), 511, "menu_cs_buy")
1864 register_menucmd(register_menuid("BuyPistol", 1), 511, "menu_cs_buy")
1865 register_menucmd(register_menuid("BuyShotgun", 1), 511, "menu_cs_buy")
1866 register_menucmd(register_menuid("BuySub", 1), 511, "menu_cs_buy")
1867 register_menucmd(register_menuid("BuyRifle", 1), 511, "menu_cs_buy")
1868 register_menucmd(register_menuid("BuyMachine", 1), 511, "menu_cs_buy")
1869 register_menucmd(register_menuid("BuyItem", 1), 511, "menu_cs_buy")
1870 register_menucmd(-28, 511, "menu_cs_buy")
1871 register_menucmd(-29, 511, "menu_cs_buy")
1872 register_menucmd(-30, 511, "menu_cs_buy")
1873 register_menucmd(-32, 511, "menu_cs_buy")
1874 register_menucmd(-31, 511, "menu_cs_buy")
1875 register_menucmd(-33, 511, "menu_cs_buy")
1876 register_menucmd(-34, 511, "menu_cs_buy")
1877
1878 // Admin commands
1879 register_concmd("zp_zombie", "cmd_zombie", _, "<target> - Turn someone into a Zombie", 0)
1880 register_concmd("zp_human", "cmd_human", _, "<target> - Turn someone back to Human", 0)
1881 register_concmd("zp_nemesis", "cmd_nemesis", _, "<target> - Turn someone into a Nemesis", 0)
1882 register_concmd("zp_assassin", "cmd_assassin", _, "<target> - Turn someone into an Assassin", 0)
1883 register_concmd("zp_survivor", "cmd_survivor", _, "<target> - Turn someone into a Survivor", 0)
1884 register_concmd("zp_sniper", "cmd_sniper", _, "<target> - Turn someone into a Sniper", 0)
1885 register_concmd("zp_respawn", "cmd_respawn", _, "<target> - Respawn someone", 0)
1886 register_concmd("zp_swarm", "cmd_swarm", _, " - Start Swarm Mode", 0)
1887 register_concmd("zp_multi", "cmd_multi", _, " - Start Multi Infection", 0)
1888 register_concmd("zp_plague", "cmd_plague", _, " - Start Plague Mode", 0)
1889 register_concmd("zp_armageddon", "cmd_armageddon", _, " - Start Armageddon Mode", 0)
1890 register_concmd("zp_apocalypse", "cmd_apocalypse", _, " - Start Apocalypse Mode", 0)
1891 register_concmd("zp_nightmare", "cmd_nightmare", _, " - Start Nightmare Mode", 0)
1892
1893 // Message IDs
1894 g_msgScoreInfo = get_user_msgid("ScoreInfo")
1895 g_msgTeamInfo = get_user_msgid("TeamInfo")
1896 g_msgDeathMsg = get_user_msgid("DeathMsg")
1897 g_msgScoreAttrib = get_user_msgid("ScoreAttrib")
1898 g_msgSetFOV = get_user_msgid("SetFOV")
1899 g_msgScreenFade = get_user_msgid("ScreenFade")
1900 g_msgScreenShake = get_user_msgid("ScreenShake")
1901 g_msgNVGToggle = get_user_msgid("NVGToggle")
1902 g_msgFlashlight = get_user_msgid("Flashlight")
1903 g_msgFlashBat = get_user_msgid("FlashBat")
1904 g_msgAmmoPickup = get_user_msgid("AmmoPickup")
1905 g_msgDamage = get_user_msgid("Damage")
1906 g_msgHideWeapon = get_user_msgid("HideWeapon")
1907 g_msgCrosshair = get_user_msgid("Crosshair")
1908 g_msgSayText = get_user_msgid("SayText")
1909 g_msgCurWeapon = get_user_msgid("CurWeapon")
1910
1911 // Message hooks
1912 register_message(g_msgCurWeapon, "message_cur_weapon")
1913 register_message(get_user_msgid("Money"), "message_money")
1914 register_message(get_user_msgid("Health"), "message_health")
1915 register_message(g_msgFlashBat, "message_flashbat")
1916 register_message(g_msgScreenFade, "message_screenfade")
1917 register_message(g_msgNVGToggle, "message_nvgtoggle")
1918 if (g_handle_models_on_separate_ent) register_message(get_user_msgid("ClCorpse"), "message_clcorpse")
1919 register_message(get_user_msgid("WeapPickup"), "message_weappickup")
1920 register_message(g_msgAmmoPickup, "message_ammopickup")
1921 register_message(get_user_msgid("Scenario"), "message_scenario")
1922 register_message(get_user_msgid("HostagePos"), "message_hostagepos")
1923 register_message(get_user_msgid("TextMsg"), "message_textmsg")
1924 register_message(get_user_msgid("SendAudio"), "message_sendaudio")
1925 register_message(get_user_msgid("TeamScore"), "message_teamscore")
1926 register_message(g_msgTeamInfo, "message_teaminfo")
1927
1928 // CVARS - General Purpose
1929 cvar_warmup = register_cvar("zp_delay", "10")
1930 cvar_lighting = register_cvar("zp_lighting", "a")
1931 cvar_thunder = register_cvar("zp_thunderclap", "90")
1932 cvar_triggered = register_cvar("zp_triggered_lights", "1")
1933 cvar_removedoors = register_cvar("zp_remove_doors", "0")
1934 cvar_blockpushables = register_cvar("zp_blockuse_pushables", "1")
1935 cvar_blocksuicide = register_cvar("zp_block_suicide", "1")
1936 cvar_randspawn = register_cvar("zp_random_spawn", "1")
1937 cvar_respawnworldspawnkill = register_cvar("zp_respawn_on_worldspawn_kill", "1")
1938 cvar_removedropped = register_cvar("zp_remove_dropped", "0")
1939 cvar_removemoney = register_cvar("zp_remove_money", "1")
1940 cvar_buycustom = register_cvar("zp_buy_custom", "1")
1941 cvar_buyzonetime = register_cvar("zp_buyzone_time", "0.0")
1942 cvar_randweapons = register_cvar("zp_random_weapons", "0")
1943 cvar_adminmodelshuman = register_cvar("zp_admin_models_human", "1")
1944 cvar_adminknifemodelshuman = register_cvar("zp_admin_knife_models_human", "0")
1945 cvar_adminmodelszombie = register_cvar("zp_admin_models_zombie", "1")
1946 cvar_adminknifemodelszombie = register_cvar("zp_admin_knife_models_zombie", "0")
1947 cvar_zclasses = register_cvar("zp_zombie_classes", "1")
1948 cvar_statssave = register_cvar("zp_stats_save", "1")
1949 cvar_startammopacks = register_cvar("zp_starting_ammo_packs", "5")
1950 cvar_preventconsecutive = register_cvar("zp_prevent_consecutive_modes", "1")
1951 cvar_keephealthondisconnect = register_cvar("zp_keep_health_on_disconnect", "1")
1952 cvar_huddisplay = register_cvar("zp_hud_display", "1")
1953 cvar_aiminfo = register_cvar("zp_aim_info", "1")
1954 cvar_dmg_while_freeze = register_cvar("zp_dmg_while_frost", "1")
1955
1956 // CVARS - Deathmatch
1957 cvar_deathmatch = register_cvar("zp_deathmatch", "0")
1958 cvar_spawndelay = register_cvar("zp_spawn_delay", "5")
1959 cvar_spawnprotection = register_cvar("zp_spawn_protection", "5")
1960 cvar_respawnonsuicide = register_cvar("zp_respawn_on_suicide", "0")
1961 cvar_respawnafterlast = register_cvar("zp_respawn_after_last_human", "1")
1962 cvar_allowrespawninfection = register_cvar("zp_infection_allow_respawn", "1")
1963 cvar_allowrespawnnem = register_cvar("zp_nem_allow_respawn", "0")
1964 cvar_allowrespawnassa = register_cvar("zp_assa_allow_respawn", "0")
1965 cvar_allowrespawnsurv = register_cvar("zp_surv_allow_respawn", "0")
1966 cvar_allowrespawnsni = register_cvar("zp_sni_allow_respawn", "0")
1967 cvar_allowrespawnswarm = register_cvar("zp_swarm_allow_respawn", "0")
1968 cvar_allowrespawnplague = register_cvar("zp_plague_allow_respawn", "0")
1969 cvar_allowrespawnarmage = register_cvar("zp_armageddon_allow_respawn", "0")
1970 cvar_allowrespawnapoc = register_cvar("zp_apocalypse_allow_respawn", "0")
1971 cvar_allowrespawnnight = register_cvar("zp_nightmare_allow_respawn", "0")
1972 cvar_respawnzomb = register_cvar("zp_respawn_zombies", "1")
1973 cvar_respawnhum = register_cvar("zp_respawn_humans", "1")
1974 cvar_respawnnem = register_cvar("zp_respawn_nemesis", "1")
1975 cvar_respawnassa = register_cvar("zp_respawn_assassins", "0")
1976 cvar_respawnsurv = register_cvar("zp_respawn_survivors", "1")
1977 cvar_respawnsni = register_cvar("zp_respawn_snipers", "0")
1978
1979 // CVARS - Extra Items
1980 cvar_extraitems = register_cvar("zp_extra_items", "1")
1981 cvar_extraweapons = register_cvar("zp_extra_weapons", "1")
1982 cvar_extranvision = register_cvar("zp_extra_nvision", "1")
1983 cvar_extraantidote = register_cvar("zp_extra_antidote", "1")
1984 cvar_antidotelimit = register_cvar("zp_extra_antidote_limit", "999")
1985 cvar_extramadness = register_cvar("zp_extra_madness", "1")
1986 cvar_madnesslimit = register_cvar("zp_extra_madness_limit", "999")
1987 cvar_madnessduration = register_cvar("zp_extra_madness_duration", "5.0")
1988 cvar_extrainfbomb = register_cvar("zp_extra_infbomb", "1")
1989 cvar_infbomblimit = register_cvar("zp_extra_infbomb_limit", "999")
1990
1991 // CVARS - Flashlight and Nightvision
1992 cvar_nvggive = register_cvar("zp_nvg_give", "1")
1993 cvar_customnvg = register_cvar("zp_nvg_custom", "1")
1994 cvar_nvgsize = register_cvar("zp_nvg_size", "80")
1995 cvar_nvgcolor[0] = register_cvar("zp_nvg_color_R", "0")
1996 cvar_nvgcolor[1] = register_cvar("zp_nvg_color_G", "150")
1997 cvar_nvgcolor[2] = register_cvar("zp_nvg_color_B", "0")
1998 cvar_humnvgcolor[0] = register_cvar("zp_nvg_hum_color_R", "0")
1999 cvar_humnvgcolor[1] = register_cvar("zp_nvg_hum_color_G", "150")
2000 cvar_humnvgcolor[2] = register_cvar("zp_nvg_hum_color_B", "0")
2001 cvar_nemnvgcolor[0] = register_cvar("zp_nvg_nem_color_R", "150")
2002 cvar_nemnvgcolor[1] = register_cvar("zp_nvg_nem_color_G", "0")
2003 cvar_nemnvgcolor[2] = register_cvar("zp_nvg_nem_color_B", "0")
2004 cvar_assanvgcolor[0] = register_cvar("zp_nvg_assa_color_R", "0")
2005 cvar_assanvgcolor[1] = register_cvar("zp_nvg_assa_color_G", "150")
2006 cvar_assanvgcolor[2] = register_cvar("zp_nvg_assa_color_B", "90")
2007 cvar_customflash = register_cvar("zp_flash_custom", "0")
2008 cvar_flashsize = register_cvar("zp_flash_size", "10")
2009 cvar_flashdrain = register_cvar("zp_flash_drain", "1")
2010 cvar_flashcharge = register_cvar("zp_flash_charge", "5")
2011 cvar_flashdist = register_cvar("zp_flash_distance", "1000")
2012 cvar_flashcolor[0] = register_cvar("zp_flash_color_R", "100")
2013 cvar_flashcolor[1] = register_cvar("zp_flash_color_G", "100")
2014 cvar_flashcolor[2] = register_cvar("zp_flash_color_B", "100")
2015 cvar_flashshowall = register_cvar("zp_flash_show_all", "1")
2016
2017 // CVARS - Knockback
2018 cvar_knockback = register_cvar("zp_knockback", "0")
2019 cvar_knockbackdamage = register_cvar("zp_knockback_damage", "1")
2020 cvar_knockbackpower = register_cvar("zp_knockback_power", "1")
2021 cvar_knockbackzvel = register_cvar("zp_knockback_zvel", "0")
2022 cvar_knockbackducking = register_cvar("zp_knockback_ducking", "0.25")
2023 cvar_knockbackdist = register_cvar("zp_knockback_distance", "500")
2024 cvar_nemknockback = register_cvar("zp_knockback_nemesis", "0.25")
2025 cvar_assaknockback = register_cvar("zp_knockback_assassin", "0.7")
2026
2027 // CVARS - Leap
2028 cvar_leapzombies = register_cvar("zp_leap_zombies", "0")
2029 cvar_leapzombiesforce = register_cvar("zp_leap_zombies_force", "500")
2030 cvar_leapzombiesheight = register_cvar("zp_leap_zombies_height", "300")
2031 cvar_leapzombiescooldown = register_cvar("zp_leap_zombies_cooldown", "5.0")
2032 cvar_leapnemesis = register_cvar("zp_leap_nemesis", "1")
2033 cvar_leapnemesisforce = register_cvar("zp_leap_nemesis_force", "500")
2034 cvar_leapnemesisheight = register_cvar("zp_leap_nemesis_height", "300")
2035 cvar_leapnemesiscooldown = register_cvar("zp_leap_nemesis_cooldown", "5.0")
2036 cvar_leapassassin = register_cvar("zp_leap_assassin", "0")
2037 cvar_leapassassinforce = register_cvar("zp_leap_assassin_force", "500")
2038 cvar_leapassassinheight = register_cvar("zp_leap_assassin_height", "300")
2039 cvar_leapassassincooldown = register_cvar("zp_leap_assassin_cooldown", "5.0")
2040 cvar_leapsurvivor = register_cvar("zp_leap_survivor", "0")
2041 cvar_leapsurvivorforce = register_cvar("zp_leap_survivor_force", "500")
2042 cvar_leapsurvivorheight = register_cvar("zp_leap_survivor_height", "300")
2043 cvar_leapsurvivorcooldown = register_cvar("zp_leap_survivor_cooldown", "5.0")
2044 cvar_leapsniper = register_cvar("zp_leap_sniper", "0")
2045 cvar_leapsniperforce = register_cvar("zp_leap_sniper_force", "500")
2046 cvar_leapsniperheight = register_cvar("zp_leap_sniper_height", "300")
2047 cvar_leapsnipercooldown = register_cvar("zp_leap_sniper_cooldown", "5.0")
2048
2049 // CVARS - Humans
2050 cvar_humanhp = register_cvar("zp_human_health", "100")
2051 cvar_humanlasthp = register_cvar("zp_human_last_extrahp", "0")
2052 cvar_humanspd = register_cvar("zp_human_speed", "240")
2053 cvar_humangravity = register_cvar("zp_human_gravity", "1.0")
2054 cvar_humanarmor = register_cvar("zp_human_armor_protect", "1")
2055 cvar_infammo = register_cvar("zp_human_unlimited_ammo", "0")
2056 cvar_ammodamage_human = register_cvar("zp_human_damage_reward", "500")
2057 cvar_fragskill = register_cvar("zp_human_frags_for_kill", "1")
2058
2059 // CVARS - Custom Grenades
2060 cvar_firegrenades = register_cvar("zp_fire_grenades", "1")
2061 cvar_fireduration = register_cvar("zp_fire_duration", "10")
2062 cvar_firedamage = register_cvar("zp_fire_damage", "5")
2063 cvar_fireslowdown = register_cvar("zp_fire_slowdown", "0.5")
2064 cvar_frostgrenades = register_cvar("zp_frost_grenades", "1")
2065 cvar_freezeduration = register_cvar("zp_frost_duration", "3")
2066 cvar_flaregrenades = register_cvar("zp_flare_grenades","1")
2067 cvar_flareduration = register_cvar("zp_flare_duration", "60")
2068 cvar_flaresize = register_cvar("zp_flare_size", "25")
2069 cvar_flarecolor = register_cvar("zp_flare_color", "0")
2070
2071 // CVARS - Zombies
2072 cvar_zombiefirsthp = register_cvar("zp_zombie_first_hp", "2.0")
2073 cvar_zombiearmor = register_cvar("zp_zombie_armor", "0.75")
2074 cvar_hitzones = register_cvar("zp_zombie_hitzones", "0")
2075 cvar_zombiebonushp = register_cvar("zp_zombie_infect_health", "100")
2076 cvar_zombiefov = register_cvar("zp_zombie_fov", "110")
2077 cvar_zombiesilent = register_cvar("zp_zombie_silent", "1")
2078 cvar_zombiepainfree = register_cvar("zp_zombie_painfree", "2")
2079 cvar_zombiebleeding = register_cvar("zp_zombie_bleeding", "1")
2080 cvar_ammoinfect = register_cvar("zp_zombie_infect_reward", "1")
2081 cvar_ammodamage_zombie = register_cvar("zp_zombie_damage_reward", "0")
2082 cvar_fragsinfect = register_cvar("zp_zombie_frags_for_infect", "1")
2083
2084 // CVARS - Special Effects
2085 cvar_infectionscreenfade = register_cvar("zp_infection_screenfade", "1")
2086 cvar_infectionscreenshake = register_cvar("zp_infection_screenshake", "1")
2087 cvar_infectionsparkle = register_cvar("zp_infection_sparkle", "1")
2088 cvar_infectiontracers = register_cvar("zp_infection_tracers", "1")
2089 cvar_infectionparticles = register_cvar("zp_infection_particles", "1")
2090 cvar_hudicons = register_cvar("zp_hud_icons", "1")
2091
2092 // CVARS - Nemesis
2093 cvar_nem = register_cvar("zp_nem_enabled", "1")
2094 cvar_nemchance = register_cvar("zp_nem_chance", "20")
2095 cvar_nemminplayers = register_cvar("zp_nem_min_players", "0")
2096 cvar_nemhp = register_cvar("zp_nem_health", "0")
2097 cvar_nembasehp = register_cvar("zp_nem_base_health", "0")
2098 cvar_nemspd = register_cvar("zp_nem_speed", "250")
2099 cvar_nemgravity = register_cvar("zp_nem_gravity", "0.5")
2100 cvar_nemdamage = register_cvar("zp_nem_damage", "250")
2101 cvar_nemglow = register_cvar("zp_nem_glow", "1")
2102 cvar_nemaura = register_cvar("zp_nem_aura", "1")
2103 cvar_nempainfree = register_cvar("zp_nem_painfree", "0")
2104 cvar_nemignorefrags = register_cvar("zp_nem_ignore_frags", "1")
2105 cvar_nemignoreammo = register_cvar("zp_nem_ignore_rewards", "1")
2106
2107 // CVARS - Assassin
2108 cvar_assa = register_cvar("zp_assa_enabled", "1")
2109 cvar_assachance = register_cvar("zp_assa_chance", "50")
2110 cvar_assaminplayers = register_cvar("zp_assa_min_players", "0")
2111 cvar_assahp = register_cvar("zp_assa_health", "25000")
2112 cvar_assabasehp = register_cvar("zp_assa_base_health", "0")
2113 cvar_assaspd = register_cvar("zp_assa_speed", "650")
2114 cvar_assagravity = register_cvar("zp_assa_gravity", "0.5")
2115 cvar_assadamage = register_cvar("zp_assa_damage", "250")
2116 cvar_assaglow = register_cvar("zp_assa_glow", "0")
2117 cvar_assaaura = register_cvar("zp_assa_aura", "0")
2118 cvar_assapainfree = register_cvar("zp_assa_painfree", "0")
2119 cvar_assaignorefrags = register_cvar("zp_assassin_ignore_frags", "1")
2120 cvar_assaignoreammo = register_cvar("zp_assassin_ignore_rewards", "1")
2121
2122 // CVARS - Survivor
2123 cvar_surv = register_cvar("zp_surv_enabled", "1")
2124 cvar_survchance = register_cvar("zp_surv_chance", "20")
2125 cvar_survminplayers = register_cvar("zp_surv_min_players", "0")
2126 cvar_survhp = register_cvar("zp_surv_health", "0")
2127 cvar_survbasehp = register_cvar("zp_surv_base_health", "0")
2128 cvar_survspd = register_cvar("zp_surv_speed", "230")
2129 cvar_survgravity = register_cvar("zp_surv_gravity", "1.25")
2130 cvar_survglow = register_cvar("zp_surv_glow", "1")
2131 cvar_survaura = register_cvar("zp_surv_aura", "1")
2132 cvar_survpainfree = register_cvar("zp_surv_painfree", "1")
2133 cvar_survignorefrags = register_cvar("zp_surv_ignore_frags", "1")
2134 cvar_survignoreammo = register_cvar("zp_surv_ignore_rewards", "1")
2135 cvar_survinfammo = register_cvar("zp_surv_unlimited_ammo", "2")
2136
2137 // CVARS - Sniper
2138 cvar_sni = register_cvar("zp_sni_enabled", "1")
2139 cvar_snichance = register_cvar("zp_sni_chance", "250")
2140 cvar_sniminplayers = register_cvar("zp_sni_min_players", "0")
2141 cvar_snihp = register_cvar("zp_sni_health", "3000")
2142 cvar_snibasehp = register_cvar("zp_sni_base_health", "0")
2143 cvar_snispd = register_cvar("zp_sni_speed", "230")
2144 cvar_snigravity = register_cvar("zp_sni_gravity", "1.25")
2145 cvar_sniglow = register_cvar("zp_sni_glow", "1")
2146 cvar_sniaura = register_cvar("zp_sni_aura", "0")
2147 cvar_snipainfree = register_cvar("zp_sni_painfree", "0")
2148 cvar_snipignorefrags = register_cvar("zp_sniper_ignore_frags", "1")
2149 cvar_snipignoreammo = register_cvar("zp_sniper_ignore_rewards", "1")
2150 cvar_snidamage = register_cvar("zp_sni_damage", "4500")
2151 cvar_sniinfammo = register_cvar("zp_sni_unlimited_ammo", "1")
2152
2153 // CVARS - Swarm Mode
2154 cvar_swarm = register_cvar("zp_swarm_enabled", "1")
2155 cvar_swarmchance = register_cvar("zp_swarm_chance", "20")
2156 cvar_swarmminplayers = register_cvar("zp_swarm_min_players", "0")
2157
2158 // CVARS - Multi Infection
2159 cvar_multi = register_cvar("zp_multi_enabled", "1")
2160 cvar_multichance = register_cvar("zp_multi_chance", "20")
2161 cvar_multiminplayers = register_cvar("zp_multi_min_players", "0")
2162 cvar_multiratio = register_cvar("zp_multi_ratio", "0.15")
2163
2164 // CVARS - Plague Mode
2165 cvar_plague = register_cvar("zp_plague_enabled", "1")
2166 cvar_plaguechance = register_cvar("zp_plague_chance", "30")
2167 cvar_plagueminplayers = register_cvar("zp_plague_min_players", "0")
2168 cvar_plagueratio = register_cvar("zp_plague_ratio", "0.5")
2169 cvar_plaguenemnum = register_cvar("zp_plague_nem_number", "1")
2170 cvar_plaguenemhpmulti = register_cvar("zp_plague_nem_hp_multi", "0.5")
2171 cvar_plaguesurvnum = register_cvar("zp_plague_surv_number", "1")
2172 cvar_plaguesurvhpmulti = register_cvar("zp_plague_surv_hp_multi", "0.5")
2173
2174 // CVARS - Armageddon Mode
2175 cvar_armage = register_cvar("zp_armageddon_enabled", "1")
2176 cvar_armagechance = register_cvar("zp_armageddon_chance", "25")
2177 cvar_armageminplayers = register_cvar("zp_armageddon_min_players", "0")
2178 cvar_armageratio = register_cvar("zp_armageddon_ratio", "0.5")
2179 cvar_armagenemhpmulti = register_cvar("zp_armageddon_nemesis_hp_multi", "0.5")
2180 cvar_armagesurvhpmulti = register_cvar("zp_armageddon_survivor_hp_multi", "0.5")
2181
2182 // CVARS - Apocalypse Mode
2183 cvar_apoc = register_cvar("zp_apocalypse_enabled", "1")
2184 cvar_apocchance = register_cvar("zp_apocalypse_chance", "25")
2185 cvar_apocminplayers = register_cvar("zp_apocalypse_min_players", "0")
2186 cvar_apocratio = register_cvar("zp_apocalypse_ratio", "0.5")
2187 cvar_apocassahpmulti = register_cvar("zp_apocalypse_assassin_hp_multi", "0.5")
2188 cvar_apocsniphpmulti = register_cvar("zp_apocalypse_sniper_hp_multi", "0.5")
2189
2190 // CVARS - Nightmare Mode
2191 cvar_night = register_cvar("zp_nightmare_enabled", "1")
2192 cvar_nightchance = register_cvar("zp_nightmare_chance", "25")
2193 cvar_nightminplayers = register_cvar("zp_nightmare_min_players", "0")
2194 cvar_nightratio = register_cvar("zp_nightmare_ratio", "0.5")
2195 cvar_nightassahpmulti = register_cvar("zp_nightmare_assassin_hp_multi", "0.5")
2196 cvar_nightsniphpmulti = register_cvar("zp_nightmare_sniper_hp_multi", "0.5")
2197 cvar_nightnemhpmulti = register_cvar("zp_nightmare_nemesis_hp_multi", "0.5")
2198 cvar_nightsurvhpmulti = register_cvar("zp_nightmare_survivor_hp_multi", "0.5")
2199
2200 // CVARS - Others
2201 cvar_logcommands = register_cvar("zp_logcommands", "1")
2202 cvar_showactivity = get_cvar_pointer("amx_show_activity")
2203 cvar_botquota = get_cvar_pointer("bot_quota")
2204 register_cvar("zp_version", PLUGIN_VERSION, FCVAR_SERVER|FCVAR_SPONLY)
2205 set_cvar_string("zp_version", PLUGIN_VERSION)
2206
2207 // Custom Forwards
2208 g_fwRoundStart = CreateMultiForward("zp_round_started", ET_IGNORE, FP_CELL, FP_CELL)
2209 g_fwRoundEnd = CreateMultiForward("zp_round_ended", ET_IGNORE, FP_CELL)
2210 g_fwUserInfected_pre = CreateMultiForward("zp_user_infected_pre", ET_IGNORE, FP_CELL, FP_CELL, FP_CELL)
2211 g_fwUserInfected_post = CreateMultiForward("zp_user_infected_post", ET_IGNORE, FP_CELL, FP_CELL, FP_CELL)
2212 g_fwUserHumanized_pre = CreateMultiForward("zp_user_humanized_pre", ET_IGNORE, FP_CELL, FP_CELL)
2213 g_fwUserHumanized_post = CreateMultiForward("zp_user_humanized_post", ET_IGNORE, FP_CELL, FP_CELL)
2214 g_fwUserInfect_attempt = CreateMultiForward("zp_user_infect_attempt", ET_CONTINUE, FP_CELL, FP_CELL, FP_CELL)
2215 g_fwUserHumanize_attempt = CreateMultiForward("zp_user_humanize_attempt", ET_CONTINUE, FP_CELL, FP_CELL)
2216 g_fwExtraItemSelected = CreateMultiForward("zp_extra_item_selected", ET_CONTINUE, FP_CELL, FP_CELL)
2217 g_fwUserUnfrozen = CreateMultiForward("zp_user_unfrozen", ET_IGNORE, FP_CELL)
2218 g_fwUserLastZombie = CreateMultiForward("zp_user_last_zombie", ET_IGNORE, FP_CELL)
2219 g_fwUserLastHuman = CreateMultiForward("zp_user_last_human", ET_IGNORE, FP_CELL)
2220
2221 // Collect random spawn points
2222 load_spawns()
2223
2224 // Set a random skybox?
2225 if (g_sky_enable)
2226 {
2227 new sky[32]
2228 ArrayGetString(g_sky_names, random_num(0, ArraySize(g_sky_names) - 1), sky, charsmax(sky))
2229 set_cvar_string("sv_skyname", sky)
2230 }
2231
2232 // Disable sky lighting so it doesn't mess with our custom lighting
2233 set_cvar_num("sv_skycolor_r", 0)
2234 set_cvar_num("sv_skycolor_g", 0)
2235 set_cvar_num("sv_skycolor_b", 0)
2236
2237 // Create the HUD Sync Objects
2238 g_MsgSync = CreateHudSyncObj()
2239 g_MsgSync2 = CreateHudSyncObj()
2240 g_MsgSync3 = CreateHudSyncObj()
2241
2242 // Format mod name
2243 formatex(g_modname, charsmax(g_modname), "Zombie Plague %s", PLUGIN_VERSION)
2244
2245 // Get Max Players
2246 g_maxplayers = get_maxplayers()
2247
2248 // Reserved saving slots starts on maxplayers+1
2249 db_slot_i = g_maxplayers+1
2250
2251 // Check if it's a CZ server
2252 new mymod[6]
2253 get_modname(mymod, charsmax(mymod))
2254 if (equal(mymod, "czero")) g_czero = 1
2255}
2256
2257public plugin_cfg()
2258{
2259 // Plugin disabled?
2260 if (!g_pluginenabled) return;
2261
2262 // Get configs dir
2263 new cfgdir[32]
2264 get_configsdir(cfgdir, charsmax(cfgdir))
2265
2266 // Execute config file (zombieplague.cfg)
2267 server_cmd("exec %s/zombieplague.cfg", cfgdir)
2268
2269 // Prevent any more stuff from registering
2270 g_arrays_created = false
2271
2272 // Save customization data
2273 save_customization()
2274
2275 // Lighting task
2276 set_task(5.0, "lighting_effects", _, _, _, "b")
2277
2278 // Cache CVARs after configs are loaded / call roundstart manually
2279 set_task(0.5, "cache_cvars")
2280 set_task(0.5, "event_round_start")
2281 set_task(0.5, "logevent_round_start")
2282}
2283
2284// Some one aimed at someone
2285public event_show_status(id)
2286{
2287 // Not a bot and is still connected
2288 if (!g_isbot[id] && g_isconnected[id] && get_pcvar_num(cvar_aiminfo))
2289 {
2290 // Retrieve the aimed player's id
2291 static aimid
2292 aimid = read_data(2)
2293
2294 // Only show friends status ?
2295 if (g_zombie[id] == g_zombie[aimid])
2296 {
2297 static class[32], red, blue
2298
2299 // Format the class name according to the player's team
2300 if (g_zombie[id])
2301 {
2302 red = 255
2303 blue = 0
2304
2305 if (g_nemesis[aimid])
2306 formatex(class, charsmax(class), "%L %L", id, "CLASS_CLASS", id, "CLASS_NEMESIS")
2307 else if (g_assassin[aimid])
2308 formatex(class, charsmax(class), "%L %L", id, "CLASS_CLASS", id, "CLASS_ASSASSIN")
2309 else
2310 formatex(class, charsmax(class), "%L %s", id, "CLASS_CLASS", g_zombie_classname[aimid])
2311 }
2312 else
2313 {
2314 red = 0
2315 blue = 255
2316
2317 if (g_survivor[aimid])
2318 formatex(class, charsmax(class), "%L %L", id, "CLASS_CLASS", id, "CLASS_SURVIVOR")
2319 else if (g_sniper[aimid])
2320 formatex(class, charsmax(class), "%L %L", id, "CLASS_CLASS", id, "CLASS_SNIPER")
2321 else
2322 formatex(class, charsmax(class), "%L %L", id, "CLASS_CLASS", id, "CLASS_HUMAN")
2323 }
2324
2325 // Show the notice
2326 set_hudmessage(red, 50, blue, -1.0, 0.60, 1, 0.01, 3.0, 0.01, 0.01, -1)
2327 ShowSyncHudMsg(id, g_MsgSync3,"%L", id, "AIM_INFO", g_playername[aimid], class, pev(aimid, pev_health), pev(aimid, pev_armorvalue), g_ammopacks[aimid])
2328 }
2329 }
2330}
2331
2332// Remove the aim-info message
2333public event_hide_status(id)
2334{
2335 ClearSyncHud(id, g_MsgSync3)
2336}
2337
2338/*================================================================================
2339 [Main Events]
2340=================================================================================*/
2341
2342// Event Round Start
2343public event_round_start()
2344{
2345 // Remove doors/lights?
2346 set_task(0.1, "remove_stuff")
2347
2348 // New round starting
2349 g_newround = true
2350 g_endround = false
2351 g_survround = false
2352 g_sniround = false
2353 g_nemround = false
2354 g_assaround = false
2355 g_swarmround = false
2356 g_plagueround = false
2357 g_armageround = false
2358 g_apocround = false
2359 g_nightround = false
2360 g_modestarted = false
2361
2362 // Reset bought infection bombs counter
2363 g_infbombcounter = 0
2364 g_antidotecounter = 0
2365 g_madnesscounter = 0
2366
2367 // Freezetime begins
2368 g_freezetime = true
2369
2370 // Show welcome message and T-Virus notice
2371 remove_task(TASK_WELCOMEMSG)
2372 set_task(2.0, "welcome_msg", TASK_WELCOMEMSG)
2373
2374 // Set a new "Make Zombie Task"
2375 remove_task(TASK_MAKEZOMBIE)
2376 set_task(2.0 + get_pcvar_float(cvar_warmup), "make_zombie_task", TASK_MAKEZOMBIE)
2377}
2378
2379// Log Event Round Start
2380public logevent_round_start()
2381{
2382 // Freezetime ends
2383 g_freezetime = false
2384
2385 #define ForPlayers(%1) for(new %1 = 1; %1 <= 32; %1++)
2386
2387 ForPlayers(i)
2388 {
2389 if(!is_user_connected(i) || !get_user_gasmask(i))
2390 {
2391 continue;
2392 }
2393
2394 set_user_gasmask(i, false);
2395 }
2396}
2397
2398// Log Event Round End
2399public logevent_round_end()
2400{
2401 // Prevent this from getting called twice when restarting (bugfix)
2402 static Float:lastendtime, Float:current_time
2403 current_time = get_gametime()
2404 if (current_time - lastendtime < 0.5) return;
2405 lastendtime = current_time
2406
2407 // Temporarily save player stats?
2408 if (get_pcvar_num(cvar_statssave))
2409 {
2410 static id, team
2411 for (id = 1; id <= g_maxplayers; id++)
2412 {
2413 // Not connected
2414 if (!g_isconnected[id])
2415 continue;
2416
2417 team = fm_cs_get_user_team(id)
2418
2419 // Not playing
2420 if (team == FM_CS_TEAM_SPECTATOR || team == FM_CS_TEAM_UNASSIGNED)
2421 continue;
2422
2423 save_stats(id)
2424 }
2425 }
2426
2427 // Round ended
2428 g_endround = true
2429
2430 // Stop old tasks (if any)
2431 remove_task(TASK_WELCOMEMSG)
2432 remove_task(TASK_MAKEZOMBIE)
2433
2434 // Stop ambience sounds
2435 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)
2436 || (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))
2437 {
2438 remove_task(TASK_AMBIENCESOUNDS)
2439 ambience_sound_stop()
2440 }
2441
2442 // Show HUD notice, play win sound, update team scores...
2443 static sound[64]
2444 if (!fnGetZombies())
2445 {
2446 // Human team wins
2447 set_hudmessage(0, 0, 200, HUD_EVENT_X, HUD_EVENT_Y, 0, 0.0, 3.0, 2.0, 1.0, -1)
2448 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "WIN_HUMAN")
2449
2450 // Play win sound and increase score, unless game commencing
2451 ArrayGetString(sound_win_humans, random_num(0, ArraySize(sound_win_humans) - 1), sound, charsmax(sound))
2452 PlaySound(sound)
2453 if (!g_gamecommencing) g_scorehumans++
2454
2455 // Round end forward
2456 ExecuteForward(g_fwRoundEnd, g_fwDummyResult, ZP_TEAM_HUMAN);
2457 }
2458 else if (!fnGetHumans())
2459 {
2460 // Zombie team wins
2461 set_hudmessage(200, 0, 0, HUD_EVENT_X, HUD_EVENT_Y, 0, 0.0, 3.0, 2.0, 1.0, -1)
2462 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "WIN_ZOMBIE")
2463
2464 // Play win sound and increase score, unless game commencing
2465 ArrayGetString(sound_win_zombies, random_num(0, ArraySize(sound_win_zombies) - 1), sound, charsmax(sound))
2466 PlaySound(sound)
2467 if (!g_gamecommencing) g_scorezombies++
2468
2469 // Round end forward
2470 ExecuteForward(g_fwRoundEnd, g_fwDummyResult, ZP_TEAM_ZOMBIE);
2471 }
2472 else
2473 {
2474 // No one wins
2475 set_hudmessage(0, 200, 0, HUD_EVENT_X, HUD_EVENT_Y, 0, 0.0, 3.0, 2.0, 1.0, -1)
2476 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "WIN_NO_ONE")
2477
2478 // Play win sound
2479 ArrayGetString(sound_win_no_one, random_num(0, ArraySize(sound_win_no_one) - 1), sound, charsmax(sound))
2480 PlaySound(sound)
2481
2482 // Round end forward
2483 ExecuteForward(g_fwRoundEnd, g_fwDummyResult, ZP_TEAM_NO_ONE);
2484 }
2485
2486 // Game commencing triggers round end
2487 g_gamecommencing = false
2488
2489 // Balance the teams
2490 balance_teams()
2491}
2492
2493// Event Map Ended
2494public event_intermission()
2495{
2496 // Remove ambience sounds task
2497 remove_task(TASK_AMBIENCESOUNDS)
2498}
2499
2500// BP Ammo update
2501public event_ammo_x(id)
2502{
2503 // Humans only
2504 if (g_zombie[id])
2505 return;
2506
2507 // Get ammo type
2508 static type
2509 type = read_data(1)
2510
2511 // Unknown ammo type
2512 if (type >= sizeof AMMOWEAPON)
2513 return;
2514
2515 // Get weapon's id
2516 static weapon
2517 weapon = AMMOWEAPON[type]
2518
2519 // Primary and secondary only
2520 if (MAXBPAMMO[weapon] <= 2)
2521 return;
2522
2523 // Get ammo amount
2524 static amount
2525 amount = read_data(2)
2526
2527 // Unlimited BP Ammo?
2528 if (g_survivor[id] ? get_pcvar_num(cvar_survinfammo) : g_sniper[id] ? get_pcvar_num(cvar_sniinfammo) : get_pcvar_num(cvar_infammo))
2529 {
2530 if (amount < MAXBPAMMO[weapon])
2531 {
2532 // The BP Ammo refill code causes the engine to send a message, but we
2533 // can't have that in this forward or we risk getting some recursion bugs.
2534 // For more info see: https://bugs.alliedmods.net/show_bug.cgi?id=3664
2535 static args[1]
2536 args[0] = weapon
2537 set_task(0.1, "refill_bpammo", id, args, sizeof args)
2538 }
2539 }
2540 // Bots automatically buy ammo when needed
2541 else if (g_isbot[id] && amount <= BUYAMMO[weapon])
2542 {
2543 // Task needed for the same reason as above
2544 set_task(0.1, "clcmd_buyammo", id)
2545 }
2546}
2547
2548/*================================================================================
2549 [Main Forwards]
2550=================================================================================*/
2551
2552// Entity Spawn Forward
2553public fw_Spawn(entity)
2554{
2555 // Invalid entity
2556 if (!pev_valid(entity)) return FMRES_IGNORED;
2557
2558 // Get classname
2559 new classname[32], objective[32], size = ArraySize(g_objective_ents)
2560 pev(entity, pev_classname, classname, charsmax(classname))
2561
2562 // Check whether it needs to be removed
2563 for (new i = 0; i < size; i++)
2564 {
2565 ArrayGetString(g_objective_ents, i, objective, charsmax(objective))
2566
2567 if (equal(classname, objective))
2568 {
2569 engfunc(EngFunc_RemoveEntity, entity)
2570 return FMRES_SUPERCEDE;
2571 }
2572 }
2573
2574 return FMRES_IGNORED;
2575}
2576
2577// Sound Precache Forward
2578public fw_PrecacheSound(const sound[])
2579{
2580 // Block all those unneeeded hostage sounds
2581 if (equal(sound, "hostage", 7))
2582 return FMRES_SUPERCEDE;
2583
2584 return FMRES_IGNORED;
2585}
2586
2587// Ham Player Spawn Post Forward
2588public fw_PlayerSpawn_Post(id)
2589{
2590 // Not alive or didn't join a team yet
2591 if (!is_user_alive(id) || !fm_cs_get_user_team(id))
2592 return;
2593
2594 // Player spawned
2595 g_isalive[id] = true
2596
2597 // Remove previous tasks
2598 remove_task(id+TASK_SPAWN)
2599 remove_task(id+TASK_MODEL)
2600 remove_task(id+TASK_BLOOD)
2601 remove_task(id+TASK_AURA)
2602 remove_task(id+TASK_BURN)
2603 remove_task(id+TASK_CHARGE)
2604 remove_task(id+TASK_FLASH)
2605 remove_task(id+TASK_NVISION)
2606
2607 // Spawn at a random location?
2608 if (get_pcvar_num(cvar_randspawn)) do_random_spawn(id)
2609
2610 // Hide money?
2611 if (get_pcvar_num(cvar_removemoney))
2612 set_task(0.4, "task_hide_money", id+TASK_SPAWN)
2613
2614 // Respawn player if he dies because of a worldspawn kill?
2615 if (get_pcvar_num(cvar_respawnworldspawnkill))
2616 set_task(2.0, "respawn_player_check_task", id+TASK_SPAWN)
2617
2618 // Spawn as zombie?
2619 if (g_respawn_as_zombie[id] && !g_newround)
2620 {
2621 reset_vars(id, 0) // reset player vars
2622 zombieme(id, 0, 0, 0, 0, 0) // make him zombie right away
2623 return;
2624 }
2625
2626 // Reset player vars
2627 reset_vars(id, 0)
2628 g_buytime[id] = get_gametime()
2629
2630 // Show custom buy menu?
2631 if (get_pcvar_num(cvar_buycustom))
2632 set_task(0.2, "show_menu_buy1", id+TASK_SPAWN)
2633
2634 // Set health and gravity
2635 fm_set_user_health(id, get_pcvar_num(cvar_humanhp))
2636 set_pev(id, pev_gravity, get_pcvar_float(cvar_humangravity))
2637
2638 // Set human maxspeed
2639 ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
2640
2641 // Switch to CT if spawning mid-round
2642 if (!g_newround && fm_cs_get_user_team(id) != FM_CS_TEAM_CT) // need to change team?
2643 {
2644 remove_task(id+TASK_TEAM)
2645 fm_cs_set_user_team(id, FM_CS_TEAM_CT)
2646 fm_user_team_update(id)
2647 }
2648
2649 // Custom models stuff
2650 static currentmodel[32], tempmodel[32], already_has_model, i, iRand, size
2651 already_has_model = false
2652
2653 if (g_handle_models_on_separate_ent)
2654 {
2655 // Set the right model
2656 if (get_pcvar_num(cvar_adminmodelshuman) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
2657 {
2658 iRand = random_num(0, ArraySize(model_admin_human) - 1)
2659 ArrayGetString(model_admin_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
2660 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_human, iRand))
2661 }
2662 else
2663 {
2664 iRand = random_num(0, ArraySize(model_human) - 1)
2665 ArrayGetString(model_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
2666 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_human, iRand))
2667 }
2668
2669 // Set model on player model entity
2670 fm_set_playermodel_ent(id)
2671
2672 // Remove glow on player model entity
2673 fm_set_rendering(g_ent_playermodel[id])
2674 }
2675 else
2676 {
2677 // Get current model for comparing it with the current one
2678 fm_cs_get_user_model(id, currentmodel, charsmax(currentmodel))
2679
2680 // Set the right model, after checking that we don't already have it
2681 if (get_pcvar_num(cvar_adminmodelshuman) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
2682 {
2683 size = ArraySize(model_admin_human)
2684 for (i = 0; i < size; i++)
2685 {
2686 ArrayGetString(model_admin_human, i, tempmodel, charsmax(tempmodel))
2687 if (equal(currentmodel, tempmodel)) already_has_model = true
2688 }
2689
2690 if (!already_has_model)
2691 {
2692 iRand = random_num(0, size - 1)
2693 ArrayGetString(model_admin_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
2694 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_human, iRand))
2695 }
2696 }
2697 else
2698 {
2699 size = ArraySize(model_human)
2700 for (i = 0; i < size; i++)
2701 {
2702 ArrayGetString(model_human, i, tempmodel, charsmax(tempmodel))
2703 if (equal(currentmodel, tempmodel)) already_has_model = true
2704 }
2705
2706 if (!already_has_model)
2707 {
2708 iRand = random_num(0, size - 1)
2709 ArrayGetString(model_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
2710 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_human, iRand))
2711 }
2712 }
2713
2714 // Need to change the model?
2715 if (!already_has_model)
2716 {
2717 // An additional delay is offset at round start
2718 // since SVC_BAD is more likely to be triggered there
2719 if (g_newround)
2720 set_task(5.0 * g_modelchange_delay, "fm_user_model_update", id+TASK_MODEL)
2721 else
2722 fm_user_model_update(id+TASK_MODEL)
2723 }
2724
2725 // Remove glow
2726 fm_set_rendering(id)
2727 }
2728
2729 // Bots stuff
2730 if (g_isbot[id])
2731 {
2732 // Turn off NVG for bots
2733 cs_set_user_nvg(id, 0)
2734
2735 // Automatically buy extra items/weapons after first zombie is chosen
2736 if (get_pcvar_num(cvar_extraitems))
2737 {
2738 if (g_newround) set_task(10.0 + get_pcvar_float(cvar_warmup), "bot_buy_extras", id+TASK_SPAWN)
2739 else set_task(10.0, "bot_buy_extras", id+TASK_SPAWN)
2740 }
2741 }
2742
2743 // Enable spawn protection for humans spawning mid-round
2744 if (!g_newround && get_pcvar_float(cvar_spawnprotection) > 0.0)
2745 {
2746 // Do not take damage
2747 g_nodamage[id] = true
2748
2749 // Make temporarily invisible
2750 set_pev(id, pev_effects, pev(id, pev_effects) | EF_NODRAW)
2751
2752 // Set task to remove it
2753 set_task(get_pcvar_float(cvar_spawnprotection), "remove_spawn_protection", id+TASK_SPAWN)
2754 }
2755
2756 // Turn off his flashlight (prevents double flashlight bug/exploit)
2757 turn_off_flashlight(id)
2758
2759 // Set the flashlight charge task to update battery status
2760 if (g_cached_customflash)
2761 set_task(1.0, "flashlight_charge", id+TASK_CHARGE, _, _, "b")
2762
2763 // Replace weapon models (bugfix)
2764 static weapon_ent
2765 weapon_ent = fm_cs_get_current_weapon_ent(id)
2766 if (pev_valid(weapon_ent)) replace_weapon_models(id, cs_get_weapon_id(weapon_ent))
2767
2768 // Last Zombie Check
2769 fnCheckLastZombie()
2770}
2771
2772// Ham Player Killed Forward
2773public fw_PlayerKilled(victim, attacker, shouldgib)
2774{
2775 // Player killed
2776 g_isalive[victim] = false
2777 // Disable nodamage mode after we die to prevent spectator nightvision using zombie madness colors bug
2778 g_nodamage[victim] = false
2779
2780 // Enable dead players nightvision
2781 set_task(0.1, "spec_nvision", victim)
2782
2783 // Disable nightvision when killed (bugfix)
2784 if (get_pcvar_num(cvar_nvggive) == 0 && g_nvision[victim])
2785 {
2786 if (get_pcvar_num(cvar_customnvg)) remove_task(victim+TASK_NVISION)
2787 else if (g_nvisionenabled[victim]) set_user_gnvision(victim, 0)
2788 g_nvision[victim] = false
2789 g_nvisionenabled[victim] = false
2790 }
2791
2792 // Turn off nightvision when killed (bugfix)
2793 if (get_pcvar_num(cvar_nvggive) == 2 && g_nvision[victim] && g_nvisionenabled[victim])
2794 {
2795 if (get_pcvar_num(cvar_customnvg)) remove_task(victim+TASK_NVISION)
2796 else set_user_gnvision(victim, 0)
2797 g_nvisionenabled[victim] = false
2798 }
2799
2800 // Turn off custom flashlight when killed
2801 if (g_cached_customflash)
2802 {
2803 // Turn it off
2804 g_flashlight[victim] = false
2805 g_flashbattery[victim] = 100
2806
2807 // Remove previous tasks
2808 remove_task(victim+TASK_CHARGE)
2809 remove_task(victim+TASK_FLASH)
2810 }
2811
2812 // Stop bleeding/burning/aura when killed
2813 if (g_zombie[victim])
2814 {
2815 remove_task(victim+TASK_BLOOD)
2816 remove_task(victim+TASK_AURA)
2817 remove_task(victim+TASK_BURN)
2818 }
2819
2820 // Nemesis/Assassins explodes!
2821 if (g_nemesis[victim] || g_assassin[victim])
2822 SetHamParamInteger(3, 2)
2823
2824 // Get deathmatch mode status and whether the player killed himself
2825 static selfkill
2826 selfkill = (victim == attacker || !is_user_valid_connected(attacker)) ? true : false
2827
2828 // Make sure that the player was not killed by a non-player entity or through self killing
2829 if (!selfkill)
2830 {
2831 // When killed by a Sniper victim explodes
2832 if (g_sniper[attacker] && (g_currentweapon[attacker] == CSW_AWP))
2833 {
2834 // Cut him into pieces
2835 SetHamParamInteger(3, 2)
2836
2837 // Get his origin
2838 static origin[3]
2839 get_user_origin(victim, origin)
2840
2841 // Make some blood in the air
2842 message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
2843 write_byte(TE_LAVASPLASH) // TE id
2844 write_coord(origin[0]) // origin x
2845 write_coord(origin[1]) // origin y
2846 write_coord(origin[2] - 26) // origin z
2847 message_end()
2848 }
2849 else if (g_assassin[attacker])
2850 SetHamParamInteger(3, 2)
2851 }
2852
2853 // Killed by a non-player entity or self killed
2854 if (selfkill) return;
2855
2856 // Ignore Nemesis/Survivor Frags?
2857 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)))
2858 RemoveFrags(attacker, victim)
2859
2860 // Zombie/nemesis/assassin killed human, reward ammo packs
2861 if (g_zombie[attacker] && (!g_nemesis[attacker] || !get_pcvar_num(cvar_nemignoreammo)) && (!g_assassin[attacker] || !get_pcvar_num(cvar_assaignoreammo)))
2862 g_ammopacks[attacker] += get_pcvar_num(cvar_ammoinfect)
2863
2864 // Human killed zombie, add up the extra frags for kill
2865 if (!g_zombie[attacker] && get_pcvar_num(cvar_fragskill) > 1)
2866 UpdateFrags(attacker, victim, get_pcvar_num(cvar_fragskill) - 1, 0, 0)
2867
2868 // Zombie killed human, add up the extra frags for kill
2869 if (g_zombie[attacker] && get_pcvar_num(cvar_fragsinfect) > 1)
2870 UpdateFrags(attacker, victim, get_pcvar_num(cvar_fragsinfect) - 1, 0, 0)
2871}
2872
2873// Ham Player Killed Post Forward
2874public fw_PlayerKilled_Post(victim, attacker, shouldgib)
2875{
2876 // Last Zombie Check
2877 fnCheckLastZombie()
2878
2879 // Determine whether the player killed himself
2880 static selfkill
2881 selfkill = (victim == attacker || !is_user_valid_connected(attacker)) ? true : false
2882
2883 // Respawn if deathmatch is enabled
2884 if (get_pcvar_num(cvar_deathmatch))
2885 {
2886 // Respawn on suicide?
2887 if (selfkill && !get_pcvar_num(cvar_respawnonsuicide))
2888 return;
2889
2890 // Respawn if human/zombie/nemesis/survivor?
2891 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)))
2892 return;
2893
2894 // Set the respawn task
2895 set_task(get_pcvar_float(cvar_spawndelay), "respawn_player_task", victim+TASK_SPAWN)
2896 }
2897}
2898
2899// Ham Take Damage Forward
2900public fw_TakeDamage(victim, inflictor, attacker, Float:damage, damage_type)
2901{
2902 // Non-player damage or self damage
2903 if (victim == attacker || !is_user_valid_connected(attacker))
2904 return HAM_IGNORED;
2905
2906 // New round starting or round ended
2907 if (g_newround || g_endround)
2908 return HAM_SUPERCEDE;
2909
2910 // Victim shouldn't take damage or victim is frozen
2911 if (g_nodamage[victim] || g_frozen[victim])
2912 return HAM_SUPERCEDE;
2913
2914 // Prevent friendly fire
2915 if (g_zombie[attacker] == g_zombie[victim])
2916 return HAM_SUPERCEDE;
2917
2918 // Attacker is human...
2919 if (!g_zombie[attacker])
2920 {
2921 // Armor multiplier for the final damage on normal zombies
2922 if (!g_nemesis[victim] && !g_assassin[victim] && !g_sniper[attacker])
2923 {
2924 damage *= get_pcvar_float(cvar_zombiearmor)
2925 SetHamParamFloat(4, damage)
2926 }
2927
2928 // Reward ammo packs to humans for damaging zombies?
2929 if ((get_pcvar_num(cvar_ammodamage_human) > 0) && (!g_survivor[attacker] || !get_pcvar_num(cvar_survignoreammo)) && (!g_sniper[attacker] || !get_pcvar_num(cvar_snipignoreammo)))
2930 {
2931 // Store damage dealt
2932 g_damagedealt_human[attacker] += floatround(damage)
2933
2934 // Reward ammo packs for every [ammo damage] dealt
2935 while (g_damagedealt_human[attacker] > get_pcvar_num(cvar_ammodamage_human))
2936 {
2937 g_ammopacks[attacker]++
2938 g_damagedealt_human[attacker] -= get_pcvar_num(cvar_ammodamage_human)
2939 }
2940 }
2941
2942 // set sniper dmg
2943 if (g_sniper[attacker] && g_currentweapon[attacker] == CSW_AWP)
2944 SetHamParamFloat(4, get_pcvar_float(cvar_snidamage))
2945
2946 return HAM_IGNORED;
2947 }
2948
2949 // Attacker is zombie...
2950
2951 // Prevent infection/damage by HE grenade (bugfix)
2952 if (damage_type & DMG_HEGRENADE)
2953 return HAM_SUPERCEDE;
2954
2955 // Nemesis?
2956 if (g_nemesis[attacker])
2957 {
2958 // Ignore nemesis damage override if damage comes from a 3rd party entity
2959 // (to prevent this from affecting a sub-plugin's rockets e.g.)
2960 if (inflictor == attacker)
2961 {
2962 // Set nemesis damage
2963 SetHamParamFloat(4, get_pcvar_float(cvar_nemdamage))
2964 }
2965
2966 return HAM_IGNORED;
2967 }
2968 else if (g_assassin[attacker])
2969 {
2970 // Ignore assassin damage override if damage comes from a 3rd party entity
2971 // (to prevent this from affecting a sub-plugin's rockets e.g.)
2972 if (inflictor == attacker)
2973 {
2974 // Set assassin damage
2975 SetHamParamFloat(4, get_pcvar_float(cvar_assadamage))
2976 }
2977
2978 return HAM_IGNORED;
2979 }
2980
2981 // Reward ammo packs to zombies for damaging humans?
2982 if (get_pcvar_num(cvar_ammodamage_zombie) > 0)
2983 {
2984 // Store damage dealt
2985 g_damagedealt_zombie[attacker] += floatround(damage)
2986
2987 // Reward ammo packs for every [ammo damage] dealt
2988 while (g_damagedealt_zombie[attacker] > get_pcvar_num(cvar_ammodamage_zombie))
2989 {
2990 g_ammopacks[attacker]++
2991 g_damagedealt_zombie[attacker] -= get_pcvar_num(cvar_ammodamage_zombie)
2992 }
2993 }
2994
2995 // Last human or not an infection round
2996 if (g_survround || g_sniround || g_nemround || g_assaround || g_swarmround || g_plagueround || g_armageround || g_apocround || g_nightround || fnGetHumans() == 1)
2997 return HAM_IGNORED; // human is killed
2998
2999 // Does human armor need to be reduced before infecting?
3000 if (get_pcvar_num(cvar_humanarmor))
3001 {
3002 // Get victim armor
3003 static Float:armor
3004 pev(victim, pev_armorvalue, armor)
3005
3006 // If he has some, block the infection and reduce armor instead
3007 if (armor > 0.0)
3008 {
3009 emit_sound(victim, CHAN_BODY, sound_armorhit, 1.0, ATTN_NORM, 0, PITCH_NORM)
3010 if (armor - damage > 0.0)
3011 set_pev(victim, pev_armorvalue, armor - damage)
3012 else
3013 cs_set_user_armor(victim, 0, CS_ARMOR_NONE)
3014 return HAM_SUPERCEDE;
3015 }
3016 }
3017
3018 // Infection allowed
3019 zombieme(victim, attacker, 0, 0, 0, 1) // turn into zombie
3020 return HAM_SUPERCEDE;
3021}
3022
3023// Ham Take Damage Post Forward
3024public fw_TakeDamage_Post(victim)
3025{
3026 // --- Check if victim should be Pain Shock Free ---
3027
3028 // Check if proper CVARs are enabled
3029 if (g_zombie[victim])
3030 {
3031 if (g_nemesis[victim])
3032 {
3033 if (!get_pcvar_num(cvar_nempainfree)) return;
3034 }
3035 else if (g_assassin[victim])
3036 {
3037 if (!get_pcvar_num(cvar_assapainfree)) return;
3038 }
3039 else
3040 {
3041 switch (get_pcvar_num(cvar_zombiepainfree))
3042 {
3043 case 0: return;
3044 case 2: if (!g_lastzombie[victim]) return;
3045 case 3: if (!g_firstzombie[victim]) return;
3046 }
3047 }
3048 }
3049 else
3050 {
3051 if (g_survivor[victim])
3052 {
3053 if (!get_pcvar_num(cvar_survpainfree)) return;
3054 }
3055 else if (g_sniper[victim])
3056 {
3057 if (!get_pcvar_num(cvar_snipainfree)) return;
3058 }
3059
3060 else return;
3061 }
3062
3063 // Prevent server crash if entity's private data not initalized
3064 if (pev_valid(victim) != PDATA_SAFE)
3065 return;
3066
3067 // Set pain shock free offset
3068 set_pdata_float(victim, OFFSET_PAINSHOCK, 1.0, OFFSET_LINUX)
3069}
3070
3071// Ham Trace Attack Forward
3072public fw_TraceAttack(victim, attacker, Float:damage, Float:direction[3], tracehandle, damage_type)
3073{
3074 // Non-player damage or self damage
3075 if (victim == attacker || !is_user_valid_connected(attacker))
3076 return HAM_IGNORED;
3077
3078 // New round starting or round ended
3079 if (g_newround || g_endround)
3080 return HAM_SUPERCEDE;
3081
3082 // Victim shouldn't take damage or victim is frozen
3083 if (g_nodamage[victim] || (g_frozen[victim] && get_pcvar_num(cvar_dmg_while_freeze)))
3084 return HAM_SUPERCEDE;
3085
3086 // Prevent friendly fire
3087 if (g_zombie[attacker] == g_zombie[victim])
3088 return HAM_SUPERCEDE;
3089
3090 // Victim isn't a zombie or not bullet damage, nothing else to do here
3091 if (!g_zombie[victim] || !(damage_type & DMG_BULLET))
3092 return HAM_IGNORED;
3093
3094 // If zombie hitzones are enabled, check whether we hit an allowed one
3095 if (get_pcvar_num(cvar_hitzones) && !g_nemesis[victim] && !g_assassin[victim] && !(get_pcvar_num(cvar_hitzones) & (1<<get_tr2(tracehandle, TR_iHitgroup))))
3096 return HAM_SUPERCEDE;
3097
3098 // Knockback disabled, nothing else to do here
3099 if (!get_pcvar_num(cvar_knockback))
3100 return HAM_IGNORED;
3101
3102 // Nemesis knockback disabled, nothing else to do here
3103 if (g_nemesis[victim] && get_pcvar_float(cvar_nemknockback) == 0.0)
3104 return HAM_IGNORED;
3105
3106 // Assassin knockback disabled, nothing else to do here
3107 if (g_assassin[victim] && get_pcvar_float(cvar_assaknockback) == 0.0)
3108 return HAM_IGNORED;
3109
3110 // Get whether the victim is in a crouch state
3111 static ducking
3112 ducking = pev(victim, pev_flags) & (FL_DUCKING | FL_ONGROUND) == (FL_DUCKING | FL_ONGROUND)
3113
3114 // Zombie knockback when ducking disabled
3115 if (ducking && get_pcvar_float(cvar_knockbackducking) == 0.0)
3116 return HAM_IGNORED;
3117
3118 // Get distance between players
3119 static origin1[3], origin2[3]
3120 get_user_origin(victim, origin1)
3121 get_user_origin(attacker, origin2)
3122
3123 // Max distance exceeded
3124 if (get_distance(origin1, origin2) > get_pcvar_num(cvar_knockbackdist))
3125 return HAM_IGNORED;
3126
3127 // Get victim's velocity
3128 static Float:velocity[3]
3129 pev(victim, pev_velocity, velocity)
3130
3131 // Use damage on knockback calculation
3132 if (get_pcvar_num(cvar_knockbackdamage))
3133 xs_vec_mul_scalar(direction, damage, direction)
3134
3135 // Use weapon power on knockback calculation
3136 if (get_pcvar_num(cvar_knockbackpower) && kb_weapon_power[g_currentweapon[attacker]] > 0.0)
3137 xs_vec_mul_scalar(direction, kb_weapon_power[g_currentweapon[attacker]], direction)
3138
3139 // Apply ducking knockback multiplier
3140 if (ducking)
3141 xs_vec_mul_scalar(direction, get_pcvar_float(cvar_knockbackducking), direction)
3142
3143 // Apply zombie class/nemesis knockback multiplier
3144 if (g_nemesis[victim])
3145 xs_vec_mul_scalar(direction, get_pcvar_float(cvar_nemknockback), direction)
3146 else if (g_assassin[victim])
3147 xs_vec_mul_scalar(direction, get_pcvar_float(cvar_assaknockback), direction)
3148 else
3149 xs_vec_mul_scalar(direction, g_zombie_knockback[victim], direction)
3150
3151 // Add up the new vector
3152 xs_vec_add(velocity, direction, direction)
3153
3154 // Should knockback also affect vertical velocity?
3155 if (!get_pcvar_num(cvar_knockbackzvel))
3156 direction[2] = velocity[2]
3157
3158 // Set the knockback'd victim's velocity
3159 set_pev(victim, pev_velocity, direction)
3160
3161 return HAM_IGNORED;
3162}
3163
3164// Ham Reset MaxSpeed Post Forward
3165public fw_ResetMaxSpeed_Post(id)
3166{
3167 // Freezetime active or player not alive
3168 if (g_freezetime || !g_isalive[id])
3169 return;
3170
3171 set_player_maxspeed(id)
3172}
3173
3174// Ham Use Stationary Gun Forward
3175public fw_UseStationary(entity, caller, activator, use_type)
3176{
3177 // Prevent zombies from using stationary guns
3178 if (use_type == USE_USING && is_user_valid_connected(caller) && g_zombie[caller])
3179 return HAM_SUPERCEDE;
3180
3181 return HAM_IGNORED;
3182}
3183
3184// Ham Use Stationary Gun Post Forward
3185public fw_UseStationary_Post(entity, caller, activator, use_type)
3186{
3187 // Someone stopped using a stationary gun
3188 if (use_type == USE_STOPPED && is_user_valid_connected(caller))
3189 replace_weapon_models(caller, g_currentweapon[caller]) // replace weapon models (bugfix)
3190}
3191
3192// Ham Use Pushable Forward
3193public fw_UsePushable()
3194{
3195 // Prevent speed bug with pushables?
3196 if (get_pcvar_num(cvar_blockpushables))
3197 return HAM_SUPERCEDE;
3198
3199 return HAM_IGNORED;
3200}
3201
3202// Ham Weapon Touch Forward
3203public fw_TouchWeapon(weapon, id)
3204{
3205 // Not a player
3206 if (!is_user_valid_connected(id))
3207 return HAM_IGNORED;
3208
3209 // Dont pickup weapons if zombie or survivor (+PODBot MM fix)
3210 if (g_zombie[id] || g_isbot[id] || ((g_survivor[id] || g_sniper[id]) && (g_isbot[id] || g_isalive[id])))
3211 return HAM_SUPERCEDE;
3212
3213 return HAM_IGNORED;
3214}
3215
3216// Ham Weapon Pickup Forward
3217public fw_AddPlayerItem(id, weapon_ent)
3218{
3219 // HACK: Retrieve our custom extra ammo from the weapon
3220 static extra_ammo
3221 extra_ammo = pev(weapon_ent, PEV_ADDITIONAL_AMMO)
3222
3223 // If present
3224 if (extra_ammo)
3225 {
3226 // Get weapon's id
3227 static weaponid
3228 weaponid = cs_get_weapon_id(weapon_ent)
3229
3230 // Add to player's bpammo
3231 ExecuteHamB(Ham_GiveAmmo, id, extra_ammo, AMMOTYPE[weaponid], MAXBPAMMO[weaponid])
3232 set_pev(weapon_ent, PEV_ADDITIONAL_AMMO, 0)
3233 }
3234}
3235
3236// Ham Weapon Deploy Forward
3237public fw_Item_Deploy_Post(weapon_ent)
3238{
3239 // Get weapon's owner
3240 static owner
3241 owner = fm_cs_get_weapon_ent_owner(weapon_ent)
3242
3243 // Valid owner?
3244 if (!pev_valid(owner))
3245 return;
3246
3247 // Get weapon's id
3248 static weaponid
3249 weaponid = cs_get_weapon_id(weapon_ent)
3250
3251 // Store current weapon's id for reference
3252 g_currentweapon[owner] = weaponid
3253
3254 // Replace weapon models with custom ones
3255 replace_weapon_models(owner, weaponid)
3256
3257 // Zombie not holding an allowed weapon for some reason
3258 if (g_zombie[owner] && !((1<<weaponid) & ZOMBIE_ALLOWED_WEAPONS_BITSUM))
3259 {
3260 // Switch to knife
3261 g_currentweapon[owner] = CSW_KNIFE
3262 engclient_cmd(owner, "weapon_knife")
3263 }
3264}
3265
3266// WeaponMod bugfix
3267//forward wpn_gi_reset_weapon(id);
3268public wpn_gi_reset_weapon(id)
3269{
3270 // Replace knife model
3271 replace_weapon_models(id, CSW_KNIFE)
3272}
3273
3274// Client joins the game
3275public client_putinserver(id)
3276{
3277 // Plugin disabled?
3278 if (!g_pluginenabled) return;
3279
3280 // Player joined
3281 g_isconnected[id] = true
3282
3283 // Cache player's name
3284 get_user_name(id, g_playername[id], charsmax(g_playername[]))
3285
3286 // Initialize player vars
3287 reset_vars(id, 1)
3288
3289 // Load player stats?
3290 if (get_pcvar_num(cvar_statssave)) load_stats(id)
3291
3292 // Set some tasks for humans only
3293 if (!is_user_bot(id))
3294 {
3295 // Set the custom HUD display task if enabled
3296 if (get_pcvar_num(cvar_huddisplay))
3297 set_task(1.0, "ShowHUD", id+TASK_SHOWHUD, _, _, "b")
3298
3299 // Disable minmodels for clients to see zombies properly
3300 set_task(5.0, "disable_minmodels", id)
3301 }
3302 else
3303 {
3304 // Set bot flag
3305 g_isbot[id] = true
3306
3307 // CZ bots seem to use a different "classtype" for player entities
3308 // (or something like that) which needs to be hooked separately
3309 if (!g_hamczbots && cvar_botquota)
3310 {
3311 // Set a task to let the private data initialize
3312 set_task(0.1, "register_ham_czbots", id)
3313 }
3314 }
3315}
3316
3317// Client leaving
3318public fw_ClientDisconnect(id)
3319{
3320 // Check that we still have both humans and zombies to keep the round going
3321 if (g_isalive[id]) check_round(id)
3322
3323 // Temporarily save player stats?
3324 if (get_pcvar_num(cvar_statssave)) save_stats(id)
3325
3326 // Remove previous tasks
3327 remove_task(id+TASK_TEAM)
3328 remove_task(id+TASK_MODEL)
3329 remove_task(id+TASK_FLASH)
3330 remove_task(id+TASK_CHARGE)
3331 remove_task(id+TASK_SPAWN)
3332 remove_task(id+TASK_BLOOD)
3333 remove_task(id+TASK_AURA)
3334 remove_task(id+TASK_BURN)
3335 remove_task(id+TASK_NVISION)
3336 remove_task(id+TASK_SHOWHUD)
3337
3338 if (g_handle_models_on_separate_ent)
3339 {
3340 // Remove custom model entities
3341 fm_remove_model_ents(id)
3342 }
3343
3344 // Player left, clear cached flags
3345 g_isconnected[id] = false
3346 g_isbot[id] = false
3347 g_isalive[id] = false
3348}
3349
3350// Client left
3351public fw_ClientDisconnect_Post()
3352{
3353 // Last Zombie Check
3354 fnCheckLastZombie()
3355}
3356
3357// Client Kill Forward
3358public fw_ClientKill()
3359{
3360 // Prevent players from killing themselves?
3361 if (get_pcvar_num(cvar_blocksuicide))
3362 return FMRES_SUPERCEDE;
3363
3364 return FMRES_IGNORED;
3365}
3366
3367// Emit Sound Forward
3368public fw_EmitSound(id, channel, const sample[], Float:volume, Float:attn, flags, pitch)
3369{
3370 // Block all those unneeeded hostage sounds
3371 if (sample[0] == 'h' && sample[1] == 'o' && sample[2] == 's' && sample[3] == 't' && sample[4] == 'a' && sample[5] == 'g' && sample[6] == 'e')
3372 return FMRES_SUPERCEDE;
3373
3374 // Replace these next sounds for zombies only
3375 if (!is_user_valid_connected(id) || !g_zombie[id])
3376 return FMRES_IGNORED;
3377
3378 static sound[64]
3379
3380 // Zombie being hit
3381 if (sample[7] == 'b' && sample[8] == 'h' && sample[9] == 'i' && sample[10] == 't')
3382 {
3383 if (g_nemesis[id])
3384 {
3385 ArrayGetString(nemesis_pain, random_num(0, ArraySize(nemesis_pain) - 1), sound, charsmax(sound))
3386 emit_sound(id, channel, sound, volume, attn, flags, pitch)
3387 }
3388 else if (g_assassin[id])
3389 {
3390 ArrayGetString(assassin_pain, random_num(0, ArraySize(assassin_pain) - 1), sound, charsmax(sound))
3391 emit_sound(id, channel, sound, volume, attn, flags, pitch)
3392 }
3393 else
3394 {
3395 ArrayGetString(zombie_pain, random_num(0, ArraySize(zombie_pain) - 1), sound, charsmax(sound))
3396 emit_sound(id, channel, sound, volume, attn, flags, pitch)
3397 }
3398 return FMRES_SUPERCEDE;
3399 }
3400
3401 // Zombie attacks with knife
3402 if (sample[8] == 'k' && sample[9] == 'n' && sample[10] == 'i')
3403 {
3404 if (sample[14] == 's' && sample[15] == 'l' && sample[16] == 'a') // slash
3405 {
3406 ArrayGetString(zombie_miss_slash, random_num(0, ArraySize(zombie_miss_slash) - 1), sound, charsmax(sound))
3407 emit_sound(id, channel, sound, volume, attn, flags, pitch)
3408 return FMRES_SUPERCEDE;
3409 }
3410 if (sample[14] == 'h' && sample[15] == 'i' && sample[16] == 't') // hit
3411 {
3412 if (sample[17] == 'w') // wall
3413 {
3414 ArrayGetString(zombie_miss_wall, random_num(0, ArraySize(zombie_miss_wall) - 1), sound, charsmax(sound))
3415 emit_sound(id, channel, sound, volume, attn, flags, pitch)
3416 return FMRES_SUPERCEDE;
3417 }
3418 else
3419 {
3420 ArrayGetString(zombie_hit_normal, random_num(0, ArraySize(zombie_hit_normal) - 1), sound, charsmax(sound))
3421 emit_sound(id, channel, sound, volume, attn, flags, pitch)
3422 return FMRES_SUPERCEDE;
3423 }
3424 }
3425 if (sample[14] == 's' && sample[15] == 't' && sample[16] == 'a') // stab
3426 {
3427 ArrayGetString(zombie_hit_stab, random_num(0, ArraySize(zombie_hit_stab) - 1), sound, charsmax(sound))
3428 emit_sound(id, channel, sound, volume, attn, flags, pitch)
3429 return FMRES_SUPERCEDE;
3430 }
3431 }
3432
3433 // Zombie dies
3434 if (sample[7] == 'd' && ((sample[8] == 'i' && sample[9] == 'e') || (sample[8] == 'e' && sample[9] == 'a')))
3435 {
3436 ArrayGetString(zombie_die, random_num(0, ArraySize(zombie_die) - 1), sound, charsmax(sound))
3437 emit_sound(id, channel, sound, volume, attn, flags, pitch)
3438 return FMRES_SUPERCEDE;
3439 }
3440
3441 // Zombie falls off
3442 if (sample[10] == 'f' && sample[11] == 'a' && sample[12] == 'l' && sample[13] == 'l')
3443 {
3444 ArrayGetString(zombie_fall, random_num(0, ArraySize(zombie_fall) - 1), sound, charsmax(sound))
3445 emit_sound(id, channel, sound, volume, attn, flags, pitch)
3446 return FMRES_SUPERCEDE;
3447 }
3448
3449 return FMRES_IGNORED;
3450}
3451
3452// Forward Set ClientKey Value -prevent CS from changing player models-
3453public fw_SetClientKeyValue(id, const infobuffer[], const key[])
3454{
3455 // Block CS model changes
3456 if (key[0] == 'm' && key[1] == 'o' && key[2] == 'd' && key[3] == 'e' && key[4] == 'l')
3457 return FMRES_SUPERCEDE;
3458
3459 return FMRES_IGNORED;
3460}
3461
3462// Forward Client User Info Changed -prevent players from changing models-
3463public fw_ClientUserInfoChanged(id)
3464{
3465 // Cache player's name
3466 get_user_name(id, g_playername[id], charsmax(g_playername[]))
3467
3468 if (!g_handle_models_on_separate_ent)
3469 {
3470 // Get current model
3471 static currentmodel[32]
3472 fm_cs_get_user_model(id, currentmodel, charsmax(currentmodel))
3473
3474 // If they're different, set model again
3475 if (!equal(currentmodel, g_playermodel[id]) && !task_exists(id+TASK_MODEL))
3476 fm_cs_set_user_model(id+TASK_MODEL)
3477 }
3478}
3479
3480// Forward Get Game Description
3481public fw_GetGameDescription()
3482{
3483 // Return the mod name so it can be easily identified
3484 forward_return(FMV_STRING, g_modname)
3485
3486 return FMRES_SUPERCEDE;
3487}
3488
3489// Forward Set Model
3490public fw_SetModel(entity, const model[])
3491{
3492 // We don't care
3493 if (strlen(model) < 8)
3494 return;
3495
3496 // Remove weapons?
3497 if (get_pcvar_float(cvar_removedropped) > 0.0)
3498 {
3499 // Get entity's classname
3500 static classname[10]
3501 pev(entity, pev_classname, classname, charsmax(classname))
3502
3503 // Check if it's a weapon box
3504 if (equal(classname, "weaponbox"))
3505 {
3506 // They get automatically removed when thinking
3507 set_pev(entity, pev_nextthink, get_gametime() + get_pcvar_float(cvar_removedropped))
3508 return;
3509 }
3510 }
3511
3512 // Narrow down our matches a bit
3513 if (model[7] != 'w' || model[8] != '_')
3514 return;
3515
3516 // Get damage time of grenade
3517 static Float:dmgtime
3518 pev(entity, pev_dmgtime, dmgtime)
3519
3520 // Grenade not yet thrown
3521 if (dmgtime == 0.0)
3522 return;
3523
3524 // Get whether grenade's owner is a zombie
3525 if (g_zombie[pev(entity, pev_owner)])
3526 {
3527 if (model[9] == 'h' && model[10] == 'e' && get_pcvar_num(cvar_extrainfbomb)) // Infection Bomb
3528 {
3529 // Give it a glow
3530 fm_set_rendering(entity, kRenderFxGlowShell, 0, 200, 0, kRenderNormal, 16);
3531
3532 // And a colored trail
3533 message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
3534 write_byte(TE_BEAMFOLLOW) // TE id
3535 write_short(entity) // entity
3536 write_short(g_trailSpr) // sprite
3537 write_byte(10) // life
3538 write_byte(10) // width
3539 write_byte(0) // r
3540 write_byte(200) // g
3541 write_byte(0) // b
3542 write_byte(200) // brightness
3543 message_end()
3544
3545 // Set grenade type on the thrown grenade entity
3546 set_pev(entity, PEV_NADE_TYPE, NADE_TYPE_INFECTION)
3547 }
3548 }
3549 else if (model[9] == 'h' && model[10] == 'e' && get_pcvar_num(cvar_firegrenades)) // Napalm Grenade
3550 {
3551 // Give it a glow
3552 fm_set_rendering(entity, kRenderFxGlowShell, 200, 0, 0, kRenderNormal, 16);
3553
3554 // And a colored trail
3555 message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
3556 write_byte(TE_BEAMFOLLOW) // TE id
3557 write_short(entity) // entity
3558 write_short(g_trailSpr) // sprite
3559 write_byte(10) // life
3560 write_byte(10) // width
3561 write_byte(200) // r
3562 write_byte(0) // g
3563 write_byte(0) // b
3564 write_byte(200) // brightness
3565 message_end()
3566
3567 // Set grenade type on the thrown grenade entity
3568 set_pev(entity, PEV_NADE_TYPE, NADE_TYPE_NAPALM)
3569 }
3570 else if (model[9] == 'f' && model[10] == 'l' && get_pcvar_num(cvar_frostgrenades)) // Frost Grenade
3571 {
3572 // Give it a glow
3573 fm_set_rendering(entity, kRenderFxGlowShell, 0, 100, 200, kRenderNormal, 16);
3574
3575 // And a colored trail
3576 message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
3577 write_byte(TE_BEAMFOLLOW) // TE id
3578 write_short(entity) // entity
3579 write_short(g_trailSpr) // sprite
3580 write_byte(10) // life
3581 write_byte(10) // width
3582 write_byte(0) // r
3583 write_byte(100) // g
3584 write_byte(200) // b
3585 write_byte(200) // brightness
3586 message_end()
3587
3588 // Set grenade type on the thrown grenade entity
3589 set_pev(entity, PEV_NADE_TYPE, NADE_TYPE_FROST)
3590 }
3591 else if (model[9] == 's' && model[10] == 'm' && get_pcvar_num(cvar_flaregrenades)) // Flare
3592 {
3593 // Build flare's color
3594 static rgb[3]
3595 switch (get_pcvar_num(cvar_flarecolor))
3596 {
3597 case 0: // white
3598 {
3599 rgb[0] = 255 // r
3600 rgb[1] = 255 // g
3601 rgb[2] = 255 // b
3602 }
3603 case 1: // red
3604 {
3605 rgb[0] = random_num(50,255) // r
3606 rgb[1] = 0 // g
3607 rgb[2] = 0 // b
3608 }
3609 case 2: // green
3610 {
3611 rgb[0] = 0 // r
3612 rgb[1] = random_num(50,255) // g
3613 rgb[2] = 0 // b
3614 }
3615 case 3: // blue
3616 {
3617 rgb[0] = 0 // r
3618 rgb[1] = 0 // g
3619 rgb[2] = random_num(50,255) // b
3620 }
3621 case 4: // random (all colors)
3622 {
3623 rgb[0] = random_num(50,200) // r
3624 rgb[1] = random_num(50,200) // g
3625 rgb[2] = random_num(50,200) // b
3626 }
3627 case 5: // random (r,g,b)
3628 {
3629 switch (random_num(1, 3))
3630 {
3631 case 1: // red
3632 {
3633 rgb[0] = random_num(50,255) // r
3634 rgb[1] = 0 // g
3635 rgb[2] = 0 // b
3636 }
3637 case 2: // green
3638 {
3639 rgb[0] = 0 // r
3640 rgb[1] = random_num(50,255) // g
3641 rgb[2] = 0 // b
3642 }
3643 case 3: // blue
3644 {
3645 rgb[0] = 0 // r
3646 rgb[1] = 0 // g
3647 rgb[2] = random_num(50,255) // b
3648 }
3649 }
3650 }
3651 }
3652
3653 // Give it a glow
3654 fm_set_rendering(entity, kRenderFxGlowShell, rgb[0], rgb[1], rgb[2], kRenderNormal, 16);
3655
3656 // And a colored trail
3657 message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
3658 write_byte(TE_BEAMFOLLOW) // TE id
3659 write_short(entity) // entity
3660 write_short(g_trailSpr) // sprite
3661 write_byte(10) // life
3662 write_byte(10) // width
3663 write_byte(rgb[0]) // r
3664 write_byte(rgb[1]) // g
3665 write_byte(rgb[2]) // b
3666 write_byte(200) // brightness
3667 message_end()
3668
3669 // Set grenade type on the thrown grenade entity
3670 set_pev(entity, PEV_NADE_TYPE, NADE_TYPE_FLARE)
3671
3672 // Set flare color on the thrown grenade entity
3673 set_pev(entity, PEV_FLARE_COLOR, rgb)
3674 }
3675}
3676
3677// Ham Grenade Think Forward
3678public fw_ThinkGrenade(entity)
3679{
3680 // Invalid entity
3681 if (!pev_valid(entity)) return HAM_IGNORED;
3682
3683 // Get damage time of grenade
3684 static Float:dmgtime, Float:current_time
3685 pev(entity, pev_dmgtime, dmgtime)
3686 current_time = get_gametime()
3687
3688 // Check if it's time to go off
3689 if (dmgtime > current_time)
3690 return HAM_IGNORED;
3691
3692 // Check if it's one of our custom nades
3693 switch (pev(entity, PEV_NADE_TYPE))
3694 {
3695 case NADE_TYPE_INFECTION: // Infection Bomb
3696 {
3697 infection_explode(entity)
3698 return HAM_SUPERCEDE;
3699 }
3700 case NADE_TYPE_NAPALM: // Napalm Grenade
3701 {
3702 fire_explode(entity)
3703 return HAM_SUPERCEDE;
3704 }
3705 case NADE_TYPE_FROST: // Frost Grenade
3706 {
3707 frost_explode(entity)
3708 return HAM_SUPERCEDE;
3709 }
3710 case NADE_TYPE_FLARE: // Flare
3711 {
3712 // Get its duration
3713 static duration
3714 duration = pev(entity, PEV_FLARE_DURATION)
3715
3716 // Already went off, do lighting loop for the duration of PEV_FLARE_DURATION
3717 if (duration > 0)
3718 {
3719 // Check whether this is the last loop
3720 if (duration == 1)
3721 {
3722 // Get rid of the flare entity
3723 engfunc(EngFunc_RemoveEntity, entity)
3724 return HAM_SUPERCEDE;
3725 }
3726
3727 // Light it up!
3728 flare_lighting(entity, duration)
3729
3730 // Set time for next loop
3731 set_pev(entity, PEV_FLARE_DURATION, --duration)
3732 set_pev(entity, pev_dmgtime, current_time + 2.0)
3733 }
3734 // Light up when it's stopped on ground
3735 else if ((pev(entity, pev_flags) & FL_ONGROUND) && fm_get_speed(entity) < 10)
3736 {
3737 // Flare sound
3738 static sound[64]
3739 ArrayGetString(grenade_flare, random_num(0, ArraySize(grenade_flare) - 1), sound, charsmax(sound))
3740 emit_sound(entity, CHAN_WEAPON, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
3741
3742 // Set duration and start lightning loop on next think
3743 set_pev(entity, PEV_FLARE_DURATION, 1 + get_pcvar_num(cvar_flareduration)/2)
3744 set_pev(entity, pev_dmgtime, current_time + 0.1)
3745 }
3746 else
3747 {
3748 // Delay explosion until we hit ground
3749 set_pev(entity, pev_dmgtime, current_time + 0.5)
3750 }
3751 }
3752 }
3753
3754 return HAM_IGNORED;
3755}
3756
3757// Forward CmdStart
3758public fw_CmdStart(id, handle)
3759{
3760 // Not alive
3761 if (!g_isalive[id])
3762 return;
3763
3764 // This logic looks kinda weird, but it should work in theory...
3765 // p = g_zombie[id], q = g_survivor[id], r = g_cached_customflash
3766 // ?p v q v (? ^ r)) <==> ? ^ ? ^ (p v ?)
3767 if (!g_zombie[id] && !g_survivor[id] && !g_sniper[id] && (g_zombie[id] || !g_cached_customflash))
3768 return;
3769
3770 // Check if it's a flashlight impulse
3771 if (get_uc(handle, UC_Impulse) != IMPULSE_FLASHLIGHT)
3772 return;
3773
3774 // Block it I say!
3775 set_uc(handle, UC_Impulse, 0)
3776
3777 // Should human's custom flashlight be turned on?
3778 if (!g_zombie[id] && !g_survivor[id] && !g_sniper[id] && g_flashbattery[id] > 2 && get_gametime() - g_lastflashtime[id] > 1.2)
3779 {
3780 // Prevent calling flashlight too quickly (bugfix)
3781 g_lastflashtime[id] = get_gametime()
3782
3783 // Toggle custom flashlight
3784 g_flashlight[id] = !(g_flashlight[id])
3785
3786 // Play flashlight toggle sound
3787 emit_sound(id, CHAN_ITEM, sound_flashlight, 1.0, ATTN_NORM, 0, PITCH_NORM)
3788
3789 // Update flashlight status on the HUD
3790 message_begin(MSG_ONE, g_msgFlashlight, _, id)
3791 write_byte(g_flashlight[id]) // toggle
3792 write_byte(g_flashbattery[id]) // battery
3793 message_end()
3794
3795 // Remove previous tasks
3796 remove_task(id+TASK_CHARGE)
3797 remove_task(id+TASK_FLASH)
3798
3799 // Set the flashlight charge task
3800 set_task(1.0, "flashlight_charge", id+TASK_CHARGE, _, _, "b")
3801
3802 // Call our custom flashlight task if enabled
3803 if (g_flashlight[id]) set_task(0.1, "set_user_flashlight", id+TASK_FLASH, _, _, "b")
3804 }
3805}
3806
3807// Forward Player PreThink
3808public fw_PlayerPreThink(id)
3809{
3810 // Not alive
3811 if (!g_isalive[id])
3812 return;
3813
3814 // Enable custom buyzone for player during buytime, unless zombie or survivor or time expired
3815 if (g_cached_buytime > 0.0 && !g_zombie[id] && !g_survivor[id] && (get_gametime() < g_buytime[id] + g_cached_buytime))
3816 {
3817 if (pev_valid(g_buyzone_ent))
3818 dllfunc(DLLFunc_Touch, g_buyzone_ent, id)
3819 }
3820
3821 // Silent footsteps for zombies?
3822 if (g_cached_zombiesilent && g_zombie[id] && !g_nemesis[id] && g_assassin[id])
3823 set_pev(id, pev_flTimeStepSound, STEPTIME_SILENT)
3824
3825 // Player frozen?
3826 if (g_frozen[id])
3827 {
3828 set_pev(id, pev_velocity, Float:{0.0,0.0,0.0}) // stop motion
3829 return; // shouldn't leap while frozen
3830 }
3831
3832 // --- Check if player should leap ---
3833
3834 // Don't allow leap during freezetime
3835 if (g_freezetime)
3836 return;
3837
3838 // Check if proper CVARs are enabled and retrieve leap settings
3839 static Float:cooldown, Float:current_time
3840 if (g_zombie[id])
3841 {
3842 if (g_nemesis[id])
3843 {
3844 if (!g_cached_leapnemesis) return;
3845 cooldown = g_cached_leapnemesiscooldown
3846 }
3847 else if (g_assassin[id])
3848 {
3849 if (!g_cached_leapassassin) return;
3850 cooldown = g_cached_leapassassincooldown
3851 }
3852 else
3853 {
3854 switch (g_cached_leapzombies)
3855 {
3856 case 0: return;
3857 case 2: if (!g_firstzombie[id]) return;
3858 case 3: if (!g_lastzombie[id]) return;
3859 }
3860 cooldown = g_cached_leapzombiescooldown
3861 }
3862 }
3863 else
3864 {
3865 if (g_survivor[id])
3866 {
3867 if (!g_cached_leapsurvivor) return;
3868 cooldown = g_cached_leapsurvivorcooldown
3869 }
3870 else if (g_sniper[id])
3871 {
3872 if (!g_cached_leapsniper) return;
3873 cooldown = g_cached_leapsnipercooldown
3874 }
3875 else return;
3876 }
3877
3878 current_time = get_gametime()
3879
3880 // Cooldown not over yet
3881 if (current_time - g_lastleaptime[id] < cooldown)
3882 return;
3883
3884 // Not doing a longjump (don't perform check for bots, they leap automatically)
3885 if (!g_isbot[id] && !(pev(id, pev_button) & (IN_JUMP | IN_DUCK) == (IN_JUMP | IN_DUCK)))
3886 return;
3887
3888 // Not on ground or not enough speed
3889 if (!(pev(id, pev_flags) & FL_ONGROUND) || fm_get_speed(id) < 80)
3890 return;
3891
3892 static Float:velocity[3]
3893
3894 // Make velocity vector
3895 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)
3896
3897 // Set custom height
3898 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)
3899
3900 // Apply the new velocity
3901 set_pev(id, pev_velocity, velocity)
3902
3903 // Update last leap time
3904 g_lastleaptime[id] = current_time
3905}
3906
3907/*================================================================================
3908 [Client Commands]
3909=================================================================================*/
3910
3911// Say "/zpmenu"
3912public clcmd_saymenu(id)
3913{
3914 show_menu_game(id) // show game menu
3915}
3916
3917// Say "/unstuck"
3918public clcmd_sayunstuck(id)
3919{
3920 menu_game(id, 3) // try to get unstuck
3921}
3922
3923// Nightvision toggle
3924public clcmd_nightvision(id)
3925{
3926 // Nightvision available to player?
3927 if (g_nvision[id] || (g_isalive[id] && cs_get_user_nvg(id)))
3928 {
3929 // Enable-disable
3930 g_nvisionenabled[id] = !(g_nvisionenabled[id])
3931
3932 // Custom nvg?
3933 if (get_pcvar_num(cvar_customnvg))
3934 {
3935 remove_task(id+TASK_NVISION)
3936 if (g_nvisionenabled[id]) set_task(0.1, "set_user_nvision", id+TASK_NVISION, _, _, "b")
3937 }
3938 else
3939 set_user_gnvision(id, g_nvisionenabled[id])
3940 }
3941
3942 return PLUGIN_HANDLED;
3943}
3944
3945// Weapon Drop
3946public clcmd_drop(id)
3947{
3948 // Survivor should stick with its weapon
3949 if (g_survivor[id] || g_sniper[id])
3950 return PLUGIN_HANDLED;
3951
3952 return PLUGIN_CONTINUE;
3953}
3954
3955// Buy BP Ammo
3956public clcmd_buyammo(id)
3957{
3958 // Not alive or infinite ammo setting enabled
3959 if (!g_isalive[id] || get_pcvar_num(cvar_infammo))
3960 return PLUGIN_HANDLED;
3961
3962 // Not human
3963 if (g_zombie[id])
3964 {
3965 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_HUMAN_ONLY")
3966 return PLUGIN_HANDLED;
3967 }
3968
3969 // Custom buytime enabled and human player standing in buyzone, allow buying weapon's ammo normally instead
3970 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))
3971 return PLUGIN_CONTINUE;
3972
3973 // Not enough ammo packs
3974 if (g_ammopacks[id] < 1)
3975 {
3976 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "NOT_ENOUGH_AMMO")
3977 return PLUGIN_HANDLED;
3978 }
3979
3980 // Get user weapons
3981 static weapons[32], num, i, currentammo, weaponid, refilled
3982 num = 0 // reset passed weapons count (bugfix)
3983 refilled = false
3984 get_user_weapons(id, weapons, num)
3985
3986 // Loop through them and give the right ammo type
3987 for (i = 0; i < num; i++)
3988 {
3989 // Prevents re-indexing the array
3990 weaponid = weapons[i]
3991
3992 // Primary and secondary only
3993 if (MAXBPAMMO[weaponid] > 2)
3994 {
3995 // Get current ammo of the weapon
3996 currentammo = cs_get_user_bpammo(id, weaponid)
3997
3998 // Give additional ammo
3999 ExecuteHamB(Ham_GiveAmmo, id, BUYAMMO[weaponid], AMMOTYPE[weaponid], MAXBPAMMO[weaponid])
4000
4001 // Check whether we actually refilled the weapon's ammo
4002 if (cs_get_user_bpammo(id, weaponid) - currentammo > 0) refilled = true
4003 }
4004 }
4005
4006 // Weapons already have full ammo
4007 if (!refilled) return PLUGIN_HANDLED;
4008
4009 // Deduce ammo packs, play clip purchase sound, and notify player
4010 g_ammopacks[id]--
4011 emit_sound(id, CHAN_ITEM, sound_buyammo, 1.0, ATTN_NORM, 0, PITCH_NORM)
4012 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "AMMO_BOUGHT")
4013
4014 return PLUGIN_HANDLED;
4015}
4016
4017// Block Team Change
4018public clcmd_changeteam(id)
4019{
4020 static team
4021 team = fm_cs_get_user_team(id)
4022
4023 // Unless it's a spectator joining the game
4024 if (team == FM_CS_TEAM_SPECTATOR || team == FM_CS_TEAM_UNASSIGNED)
4025 return PLUGIN_CONTINUE;
4026
4027 // Pressing 'M' (chooseteam) ingame should show the main menu instead
4028 show_menu_game(id)
4029 return PLUGIN_HANDLED;
4030}
4031
4032/*================================================================================
4033 [Menus]
4034=================================================================================*/
4035
4036// Game Menu
4037show_menu_game(id)
4038{
4039 // Player disconnected?
4040 if (!g_isconnected[id])
4041 return;
4042
4043 static menu[250], len, userflags
4044 len = 0
4045 userflags = get_user_flags(id)
4046
4047 // Title
4048 len += formatex(menu[len], charsmax(menu) - len, "\y%s^n^n", g_modname)
4049
4050 // 1. Buy weapons
4051 if (get_pcvar_num(cvar_buycustom))
4052 len += formatex(menu[len], charsmax(menu) - len, "\r1.\w %L^n", id, "MENU_BUY")
4053 else
4054 len += formatex(menu[len], charsmax(menu) - len, "\d1. %L^n", id, "MENU_BUY")
4055
4056 // 2. Extra items
4057 if (get_pcvar_num(cvar_extraitems) && g_isalive[id])
4058 len += formatex(menu[len], charsmax(menu) - len, "\r2.\w %L^n", id, "MENU_EXTRABUY")
4059 else
4060 len += formatex(menu[len], charsmax(menu) - len, "\d2. %L^n", id, "MENU_EXTRABUY")
4061
4062 // 3. Zombie class
4063 if (get_pcvar_num(cvar_zclasses))
4064 len += formatex(menu[len], charsmax(menu) - len, "\r3.\w %L^n", id,"MENU_ZCLASS")
4065 else
4066 len += formatex(menu[len], charsmax(menu) - len, "\d3. %L^n", id,"MENU_ZCLASS")
4067
4068 // 4. Unstuck
4069 if (g_isalive[id])
4070 len += formatex(menu[len], charsmax(menu) - len, "\r4.\w %L^n", id, "MENU_UNSTUCK")
4071 else
4072 len += formatex(menu[len], charsmax(menu) - len, "\d4. %L^n", id, "MENU_UNSTUCK")
4073
4074 // 5. Help
4075 len += formatex(menu[len], charsmax(menu) - len, "\r5.\w %L^n^n", id, "MENU_INFO")
4076
4077 // 6. Join spec
4078 if (!g_isalive[id] || !get_pcvar_num(cvar_blocksuicide) || (userflags & g_access_flag[ACCESS_ADMIN_MENU]))
4079 len += formatex(menu[len], charsmax(menu) - len, "\r6.\w %L^n^n", id, "MENU_SPECTATOR")
4080 else
4081 len += formatex(menu[len], charsmax(menu) - len, "\d6. %L^n^n", id, "MENU_SPECTATOR")
4082
4083 // 9. Admin menu
4084 if (userflags & g_access_flag[ACCESS_ADMIN_MENU])
4085 len += formatex(menu[len], charsmax(menu) - len, "\r9.\w %L", id, "MENU_ADMIN")
4086 else
4087 len += formatex(menu[len], charsmax(menu) - len, "\d9. %L", id, "MENU_ADMIN")
4088
4089 // 0. Exit
4090 len += formatex(menu[len], charsmax(menu) - len, "^n^n\r0.\w %L", id, "MENU_EXIT")
4091
4092 // Fix for AMXX custom menus
4093 if (pev_valid(id) == PDATA_SAFE)
4094 set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
4095
4096 show_menu(id, KEYSMENU, menu, -1, "Game Menu")
4097}
4098
4099// Buy Menu 1
4100public show_menu_buy1(taskid)
4101{
4102 // Get player's id
4103 static id
4104 (taskid > g_maxplayers) ? (id = ID_SPAWN) : (id = taskid);
4105
4106 // Player dead?
4107 if (!g_isalive[id])
4108 return;
4109
4110 // Zombies or survivors get no guns
4111 if (g_zombie[id] || g_survivor[id] || g_sniper[id])
4112 return;
4113
4114 // Bots pick their weapons randomly / Random weapons setting enabled
4115 if (get_pcvar_num(cvar_randweapons) || g_isbot[id])
4116 {
4117 buy_primary_weapon(id, random_num(0, ArraySize(g_primary_items) - 1))
4118 menu_buy2(id, random_num(0, ArraySize(g_secondary_items) - 1))
4119 return;
4120 }
4121
4122 // Automatic selection enabled for player and menu called on spawn event
4123 if (WPN_AUTO_ON && taskid > g_maxplayers)
4124 {
4125 buy_primary_weapon(id, WPN_AUTO_PRI)
4126 menu_buy2(id, WPN_AUTO_SEC)
4127 return;
4128 }
4129
4130 static menu[300], len, weap, maxloops
4131 len = 0
4132 maxloops = min(WPN_STARTID+7, WPN_MAXIDS)
4133
4134 // Title
4135 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))
4136
4137 // 1-7. Weapon List
4138 for (weap = WPN_STARTID; weap < maxloops; weap++)
4139 len += formatex(menu[len], charsmax(menu) - len, "\r%d.\w %s^n", weap-WPN_STARTID+1, WEAPONNAMES[ArrayGetCell(g_primary_weaponids, weap)])
4140
4141 // 8. Auto Select
4142 len += formatex(menu[len], charsmax(menu) - len, "^n\r8.\w %L \y[%L]", id, "MENU_AUTOSELECT", id, (WPN_AUTO_ON) ? "MOTD_ENABLED" : "MOTD_DISABLED")
4143
4144 // 9. Next/Back - 0. Exit
4145 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")
4146
4147 // Fix for AMXX custom menus
4148 if (pev_valid(id) == PDATA_SAFE)
4149 set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
4150
4151 show_menu(id, KEYSMENU, menu, -1, "Buy Menu 1")
4152}
4153
4154// Buy Menu 2
4155show_menu_buy2(id)
4156{
4157 // Player dead?
4158 if (!g_isalive[id])
4159 return;
4160
4161 static menu[250], len, weap, maxloops
4162 len = 0
4163 maxloops = ArraySize(g_secondary_items)
4164
4165 // Title
4166 len += formatex(menu[len], charsmax(menu) - len, "\y%L^n", id, "MENU_BUY2_TITLE")
4167
4168 // 1-6. Weapon List
4169 for (weap = 0; weap < maxloops; weap++)
4170 len += formatex(menu[len], charsmax(menu) - len, "^n\r%d.\w %s", weap+1, WEAPONNAMES[ArrayGetCell(g_secondary_weaponids, weap)])
4171
4172 // 8. Auto Select
4173 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")
4174
4175 // 0. Exit
4176 len += formatex(menu[len], charsmax(menu) - len, "^n^n\r0.\w %L", id, "MENU_EXIT")
4177
4178 // Fix for AMXX custom menus
4179 if (pev_valid(id) == PDATA_SAFE)
4180 set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
4181
4182 show_menu(id, KEYSMENU, menu, -1, "Buy Menu 2")
4183}
4184
4185// Extra Items Menu
4186show_menu_extras(id)
4187{
4188 // Player dead?
4189 if (!g_isalive[id])
4190 return;
4191
4192 static menuid, menu[128], item, team, buffer[32]
4193
4194 // Title
4195 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")
4196 menuid = menu_create(menu, "menu_extras")
4197
4198 // Item List
4199 for (item = 0; item < g_extraitem_i; item++)
4200 {
4201 // Retrieve item's team
4202 team = ArrayGetCell(g_extraitem_team, item)
4203
4204 // Item not available to player's team/class
4205 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)))
4206 continue;
4207
4208 // Check if it's one of the hardcoded items, check availability, set translated caption
4209 switch (item)
4210 {
4211 case EXTRA_NVISION:
4212 {
4213 if (!get_pcvar_num(cvar_extranvision)) continue;
4214 formatex(buffer, charsmax(buffer), "%L", id, "MENU_EXTRA1")
4215 }
4216 case EXTRA_ANTIDOTE:
4217 {
4218 if (!get_pcvar_num(cvar_extraantidote) || g_antidotecounter >= get_pcvar_num(cvar_antidotelimit)) continue;
4219 formatex(buffer, charsmax(buffer), "%L", id, "MENU_EXTRA2")
4220 }
4221 case EXTRA_MADNESS:
4222 {
4223 if (!get_pcvar_num(cvar_extramadness) || g_madnesscounter >= get_pcvar_num(cvar_madnesslimit)) continue;
4224 formatex(buffer, charsmax(buffer), "%L", id, "MENU_EXTRA3")
4225 }
4226 case EXTRA_INFBOMB:
4227 {
4228 if (!get_pcvar_num(cvar_extrainfbomb) || g_infbombcounter >= get_pcvar_num(cvar_infbomblimit)) continue;
4229 formatex(buffer, charsmax(buffer), "%L", id, "MENU_EXTRA4")
4230 }
4231 default:
4232 {
4233 if (item >= EXTRA_WEAPONS_STARTID && item <= EXTRAS_CUSTOM_STARTID-1 && !get_pcvar_num(cvar_extraweapons)) continue;
4234 ArrayGetString(g_extraitem_name, item, buffer, charsmax(buffer))
4235 }
4236 }
4237
4238 // Add Item Name and Cost
4239 formatex(menu, charsmax(menu), "%s \y%d %L", buffer, ArrayGetCell(g_extraitem_cost, item), id, "AMMO_PACKS2")
4240 buffer[0] = item
4241 buffer[1] = 0
4242 menu_additem(menuid, menu, buffer)
4243 }
4244
4245 // No items to display?
4246 if (menu_items(menuid) <= 0)
4247 {
4248 zp_colored_print(id, "^x04[ZP]^x01 %L", id ,"CMD_NOT_EXTRAS")
4249 menu_destroy(menuid)
4250 return;
4251 }
4252
4253 // Back - Next - Exit
4254 formatex(menu, charsmax(menu), "%L", id, "MENU_BACK")
4255 menu_setprop(menuid, MPROP_BACKNAME, menu)
4256 formatex(menu, charsmax(menu), "%L", id, "MENU_NEXT")
4257 menu_setprop(menuid, MPROP_NEXTNAME, menu)
4258 formatex(menu, charsmax(menu), "%L", id, "MENU_EXIT")
4259 menu_setprop(menuid, MPROP_EXITNAME, menu)
4260
4261 // If remembered page is greater than number of pages, clamp down the value
4262 MENU_PAGE_EXTRAS = min(MENU_PAGE_EXTRAS, menu_pages(menuid)-1)
4263
4264 // Fix for AMXX custom menus
4265 if (pev_valid(id) == PDATA_SAFE)
4266 set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
4267
4268 menu_display(id, menuid, 0)
4269}
4270
4271// Zombie Class Menu
4272public show_menu_zclass(id)
4273{
4274 // Player disconnected
4275 if (!g_isconnected[id])
4276 return;
4277
4278 // Bots pick their zombie class randomly
4279 if (g_isbot[id])
4280 {
4281 g_zombieclassnext[id] = random_num(0, g_zclass_i - 1)
4282 return;
4283 }
4284
4285 static menuid, menu[128], class, buffer[32], buffer2[32]
4286
4287 // Title
4288 formatex(menu, charsmax(menu), "%L\r", id, "MENU_ZCLASS_TITLE")
4289 menuid = menu_create(menu, "menu_zclass")
4290
4291 // Class List
4292 for (class = 0; class < g_zclass_i; class++)
4293 {
4294 // Retrieve name and info
4295 ArrayGetString(g_zclass_name, class, buffer, charsmax(buffer))
4296 ArrayGetString(g_zclass_info, class, buffer2, charsmax(buffer2))
4297
4298 // Add to menu
4299 if (class == g_zombieclassnext[id])
4300 formatex(menu, charsmax(menu), "\d%s %s", buffer, buffer2)
4301 else
4302 formatex(menu, charsmax(menu), "%s \y%s", buffer, buffer2)
4303
4304 buffer[0] = class
4305 buffer[1] = 0
4306 menu_additem(menuid, menu, buffer)
4307 }
4308
4309 // Back - Next - Exit
4310 formatex(menu, charsmax(menu), "%L", id, "MENU_BACK")
4311 menu_setprop(menuid, MPROP_BACKNAME, menu)
4312 formatex(menu, charsmax(menu), "%L", id, "MENU_NEXT")
4313 menu_setprop(menuid, MPROP_NEXTNAME, menu)
4314 formatex(menu, charsmax(menu), "%L", id, "MENU_EXIT")
4315 menu_setprop(menuid, MPROP_EXITNAME, menu)
4316
4317 // If remembered page is greater than number of pages, clamp down the value
4318 MENU_PAGE_ZCLASS = min(MENU_PAGE_ZCLASS, menu_pages(menuid)-1)
4319
4320 // Fix for AMXX custom menus
4321 if (pev_valid(id) == PDATA_SAFE)
4322 set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
4323
4324 menu_display(id, menuid, 0)
4325}
4326
4327// Help Menu
4328show_menu_info(id)
4329{
4330 // Player disconnected?
4331 if (!g_isconnected[id])
4332 return;
4333
4334 static menu[150]
4335
4336 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")
4337
4338 // Fix for AMXX custom menus
4339 if (pev_valid(id) == PDATA_SAFE)
4340 set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
4341
4342 show_menu(id, KEYSMENU, menu, -1, "Mod Info")
4343}
4344
4345// Admin Menu
4346show_menu_admin(id)
4347{
4348 // Player disconnected?
4349 if (!g_isconnected[id])
4350 return;
4351
4352 static menu[250], len, userflags
4353 len = 0
4354 userflags = get_user_flags(id)
4355
4356 // Title
4357 len += formatex(menu[len], charsmax(menu) - len, "\y%L^n^n", id, "MENU_ADMIN_TITLE")
4358
4359 // 1. Zombiefy/Humanize command
4360 if (userflags & (g_access_flag[ACCESS_MODE_INFECTION] | g_access_flag[ACCESS_MAKE_ZOMBIE] | g_access_flag[ACCESS_MAKE_HUMAN]))
4361 len += formatex(menu[len], charsmax(menu) - len, "\r1.\w %L^n", id, "MENU_ADMIN1")
4362 else
4363 len += formatex(menu[len], charsmax(menu) - len, "\d1. %L^n", id, "MENU_ADMIN1")
4364
4365 // 2. Nemesis command
4366 if (userflags & (g_access_flag[ACCESS_MODE_NEMESIS] | g_access_flag[ACCESS_MAKE_NEMESIS]))
4367 len += formatex(menu[len], charsmax(menu) - len, "\r2.\w %L^n", id, "MENU_ADMIN2")
4368 else
4369 len += formatex(menu[len], charsmax(menu) - len, "\d2. %L^n", id, "MENU_ADMIN2")
4370
4371 // 3. Assassin command
4372 if (userflags & (g_access_flag[ACCESS_MODE_ASSASSIN] | g_access_flag[ACCESS_MAKE_ASSASSIN]))
4373 len += formatex(menu[len], charsmax(menu) - len, "\r3.\w %L^n", id, "MENU_ADMIN9")
4374 else
4375 len += formatex(menu[len], charsmax(menu) - len, "\d3. %L^n", id, "MENU_ADMIN9")
4376
4377 // 4. Survivor command
4378 if (userflags & (g_access_flag[ACCESS_MODE_SURVIVOR] | g_access_flag[ACCESS_MAKE_SURVIVOR]))
4379 len += formatex(menu[len], charsmax(menu) - len, "\r4.\w %L^n", id, "MENU_ADMIN3")
4380 else
4381 len += formatex(menu[len], charsmax(menu) - len, "\d4. %L^n", id, "MENU_ADMIN3")
4382
4383 // 5. Sniper command
4384 if (userflags & (g_access_flag[ACCESS_MODE_SNIPER] | g_access_flag[ACCESS_MAKE_SNIPER]))
4385 len += formatex(menu[len], charsmax(menu) - len, "\r5.\w %L^n", id, "MENU_ADMIN8")
4386 else
4387 len += formatex(menu[len], charsmax(menu) - len, "\d5. %L^n", id, "MENU_ADMIN8")
4388
4389 // 6. Respawn command
4390 if (userflags & g_access_flag[ACCESS_RESPAWN_PLAYERS])
4391 len += formatex(menu[len], charsmax(menu) - len, "\r6.\w %L^n", id, "MENU_ADMIN4")
4392 else
4393 len += formatex(menu[len], charsmax(menu) - len, "\d6. %L^n", id, "MENU_ADMIN4")
4394
4395 // 7. Admin modes command
4396 if (userflags & g_access_flag[ACCESS_ADMIN_MODES_MENU])
4397 len += formatex(menu[len], charsmax(menu) - len, "\r7.\w %L^n", id, "MENU_ADMIN10")
4398 else
4399 len += formatex(menu[len], charsmax(menu) - len, "\d7. %L^n", id, "MENU_ADMIN10")
4400
4401 // 0. Exit
4402 len += formatex(menu[len], charsmax(menu) - len, "^n\r0.\w %L", id, "MENU_EXIT")
4403
4404 // Fix for AMXX custom menus
4405 if (pev_valid(id) == PDATA_SAFE)
4406 set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
4407
4408 show_menu(id, KEYSMENU, menu, -1, "Admin Menu")
4409}
4410
4411// Admin Modes Menu
4412show_menu_modes_admin(id)
4413{
4414 static menu[250], len, userflags
4415 len = 0
4416 userflags = get_user_flags(id)
4417
4418 // Title
4419 len += formatex(menu[len], charsmax(menu) - len, "\y%L^n^n", id, "MENU_ADMIN_MODES_TITLE")
4420
4421 // 1. Swarm mode command
4422 if ((userflags & g_access_flag[ACCESS_MODE_SWARM]) && allowed_swarm())
4423 len += formatex(menu[len], charsmax(menu) - len, "\r1.\w %L^n", id, "MENU_ADMIN5")
4424 else
4425 len += formatex(menu[len], charsmax(menu) - len, "\d1. %L^n", id, "MENU_ADMIN5")
4426
4427 // 2. Multi infection command
4428 if ((userflags & g_access_flag[ACCESS_MODE_MULTI]) && allowed_multi())
4429 len += formatex(menu[len], charsmax(menu) - len, "\r2.\w %L^n", id, "MENU_ADMIN6")
4430 else
4431 len += formatex(menu[len], charsmax(menu) - len, "\d2. %L^n", id, "MENU_ADMIN6")
4432
4433 // 3. Plague mode command
4434 if ((userflags & g_access_flag[ACCESS_MODE_PLAGUE]) && allowed_plague())
4435 len += formatex(menu[len], charsmax(menu) - len, "\r3.\w %L^n", id, "MENU_ADMIN7")
4436 else
4437 len += formatex(menu[len], charsmax(menu) - len, "\d3. %L^n", id, "MENU_ADMIN7")
4438
4439 // 4. Armageddon mode command
4440 if ((userflags & g_access_flag[ACCESS_MODE_ARMAGEDDON]) && allowed_armageddon())
4441 len += formatex(menu[len], charsmax(menu) - len, "\r4.\w %L^n", id, "MENU_ADMIN11")
4442 else
4443 len += formatex(menu[len], charsmax(menu) - len, "\d4. %L^n", id, "MENU_ADMIN11")
4444
4445 // 5. Apocalypse mode command
4446 if ((userflags & g_access_flag[ACCESS_MODE_APOCALYPSE]) && allowed_apocalypse())
4447 len += formatex(menu[len], charsmax(menu) - len, "\r5.\w %L^n", id, "MENU_ADMIN12")
4448 else
4449 len += formatex(menu[len], charsmax(menu) - len, "\d5. %L^n", id, "MENU_ADMIN12")
4450
4451 // 6. Nightmare mode command
4452 if ((userflags & g_access_flag[ACCESS_MODE_NIGHTMARE]) && allowed_nightmare())
4453 len += formatex(menu[len], charsmax(menu) - len, "\r6.\w %L^n", id, "MENU_ADMIN13")
4454 else
4455 len += formatex(menu[len], charsmax(menu) - len, "\d6. %L^n", id, "MENU_ADMIN13")
4456
4457 // 0. Exit
4458 len += formatex(menu[len], charsmax(menu) - len, "^n\r0. \wExit")
4459
4460 show_menu(id, KEYSMENU, menu, -1, "Admin Modes Menu")
4461}
4462
4463// Player List Menu
4464show_menu_player_list(id)
4465{
4466 // Player disconnected?
4467 if (!g_isconnected[id])
4468 return;
4469
4470 static menuid, menu[128], player, userflags, buffer[2]
4471 userflags = get_user_flags(id)
4472
4473 // Title
4474 switch (PL_ACTION)
4475 {
4476 case ACTION_ZOMBIEFY_HUMANIZE: formatex(menu, charsmax(menu), "%L\r", id, "MENU_ADMIN1")
4477 case ACTION_MAKE_NEMESIS: formatex(menu, charsmax(menu), "%L\r", id, "MENU_ADMIN2")
4478 case ACTION_MAKE_ASSASSIN: formatex(menu, charsmax(menu), "%L\r", id, "MENU_ADMIN9")
4479 case ACTION_MAKE_SURVIVOR: formatex(menu, charsmax(menu), "%L\r", id, "MENU_ADMIN3")
4480 case ACTION_MAKE_SNIPER: formatex(menu, charsmax(menu), "%L\r", id, "MENU_ADMIN8")
4481 case ACTION_RESPAWN_PLAYER: formatex(menu, charsmax(menu), "%L\r", id, "MENU_ADMIN4")
4482 }
4483 menuid = menu_create(menu, "menu_player_list")
4484
4485 // Player List
4486 for (player = 0; player <= g_maxplayers; player++)
4487 {
4488 // Skip if not connected
4489 if (!g_isconnected[player])
4490 continue;
4491
4492 // Format text depending on the action to take
4493 switch (PL_ACTION)
4494 {
4495 case ACTION_ZOMBIEFY_HUMANIZE: // Zombiefy/Humanize command
4496 {
4497 if (g_zombie[player])
4498 {
4499 if (allowed_human(player) && (userflags & g_access_flag[ACCESS_MAKE_HUMAN]))
4500 formatex(menu, charsmax(menu), "%s \r[%L]", g_playername[player], id, g_nemesis[player] ? "CLASS_NEMESIS" : "CLASS_ZOMBIE")
4501 else
4502 formatex(menu, charsmax(menu), "\d%s [%L]", g_playername[player], id, g_nemesis[player] ? "CLASS_NEMESIS" : "CLASS_ZOMBIE")
4503 }
4504 else
4505 {
4506 if (allowed_zombie(player) && (g_newround ? (userflags & g_access_flag[ACCESS_MODE_INFECTION]) : (userflags & g_access_flag[ACCESS_MAKE_ZOMBIE])))
4507 formatex(menu, charsmax(menu), "%s \y[%L]", g_playername[player], id, g_survivor[player] ? "CLASS_SURVIVOR" : "CLASS_HUMAN")
4508 else
4509 formatex(menu, charsmax(menu), "\d%s [%L]", g_playername[player], id, g_survivor[player] ? "CLASS_SURVIVOR" : "CLASS_HUMAN")
4510 }
4511 }
4512 case ACTION_MAKE_NEMESIS: // Nemesis command
4513 {
4514 if (allowed_nemesis(player) && (g_newround ? (userflags & g_access_flag[ACCESS_MODE_NEMESIS]) : (userflags & g_access_flag[ACCESS_MAKE_NEMESIS])))
4515 {
4516 if (g_zombie[player])
4517 formatex(menu, charsmax(menu), "%s \r[%L]", g_playername[player], id, g_nemesis[player] ? "CLASS_NEMESIS" : "CLASS_ZOMBIE")
4518 else
4519 formatex(menu, charsmax(menu), "%s \y[%L]", g_playername[player], id, g_survivor[player] ? "CLASS_SURVIVOR" : "CLASS_HUMAN")
4520 }
4521 else
4522 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")
4523 }
4524 case ACTION_MAKE_ASSASSIN: // Assassin command
4525 {
4526 if (allowed_assassin(player) && (g_newround ? (userflags & g_access_flag[ACCESS_MODE_ASSASSIN]) : (userflags & g_access_flag[ACCESS_MAKE_ASSASSIN])))
4527 {
4528 if (g_zombie[player])
4529 formatex(menu, charsmax(menu), "%s \r[%L]", g_playername[player], id, g_nemesis[player] ? "CLASS_NEMESIS" : g_assassin[player] ? "CLASS_ASSASSIN" : "CLASS_ZOMBIE")
4530 else
4531 formatex(menu, charsmax(menu), "%s \y[%L]", g_playername[player], id, g_survivor[player] ? "CLASS_SURVIVOR" : g_sniper[player] ? "CLASS_SNIPER" : "CLASS_HUMAN")
4532 }
4533 else
4534 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")
4535 }
4536 case ACTION_MAKE_SURVIVOR: // Survivor command
4537 {
4538 if (allowed_survivor(player) && (g_newround ? (userflags & g_access_flag[ACCESS_MODE_SURVIVOR]) : (userflags & g_access_flag[ACCESS_MAKE_SURVIVOR])))
4539 {
4540 if (g_zombie[player])
4541 formatex(menu, charsmax(menu), "%s \r[%L]", g_playername[player], id, g_nemesis[player] ? "CLASS_NEMESIS" : "CLASS_ZOMBIE")
4542 else
4543 formatex(menu, charsmax(menu), "%s \y[%L]", g_playername[player], id, g_survivor[player] ? "CLASS_SURVIVOR" : "CLASS_HUMAN")
4544 }
4545 else
4546 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")
4547 }
4548 case ACTION_MAKE_SNIPER: // Sniper command
4549 {
4550 if (allowed_sniper(player) && (g_newround ? (userflags & g_access_flag[ACCESS_MODE_SNIPER]) : (userflags & g_access_flag[ACCESS_MAKE_SNIPER])))
4551 {
4552 if (g_zombie[player])
4553 formatex(menu, charsmax(menu), "%s \r[%L]", g_playername[player], id, g_nemesis[player] ? "CLASS_NEMESIS" : g_assassin[player] ? "CLASS_ASSASSIN" : "CLASS_ZOMBIE")
4554 else
4555 formatex(menu, charsmax(menu), "%s \y[%L]", g_playername[player], id, g_survivor[player] ? "CLASS_SURVIVOR" : g_sniper[player] ? "CLASS_SNIPER" : "CLASS_HUMAN")
4556 }
4557 else
4558 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")
4559 }
4560 case ACTION_RESPAWN_PLAYER: // Respawn command
4561 {
4562 if (allowed_respawn(player) && (userflags & g_access_flag[ACCESS_RESPAWN_PLAYERS]))
4563 formatex(menu, charsmax(menu), "%s", g_playername[player])
4564 else
4565 formatex(menu, charsmax(menu), "\d%s", g_playername[player])
4566 }
4567 }
4568
4569 // Add player
4570 buffer[0] = player
4571 buffer[1] = 0
4572 menu_additem(menuid, menu, buffer)
4573 }
4574
4575 // Back - Next - Exit
4576 formatex(menu, charsmax(menu), "%L", id, "MENU_BACK")
4577 menu_setprop(menuid, MPROP_BACKNAME, menu)
4578 formatex(menu, charsmax(menu), "%L", id, "MENU_NEXT")
4579 menu_setprop(menuid, MPROP_NEXTNAME, menu)
4580 formatex(menu, charsmax(menu), "%L", id, "MENU_EXIT")
4581 menu_setprop(menuid, MPROP_EXITNAME, menu)
4582
4583 // If remembered page is greater than number of pages, clamp down the value
4584 MENU_PAGE_PLAYERS = min(MENU_PAGE_PLAYERS, menu_pages(menuid)-1)
4585
4586 // Fix for AMXX custom menus
4587 if (pev_valid(id) == PDATA_SAFE)
4588 set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
4589
4590 menu_display(id, menuid, MENU_PAGE_PLAYERS)
4591}
4592
4593/*================================================================================
4594 [Menu Handlers]
4595=================================================================================*/
4596
4597// Game Menu
4598public menu_game(id, key)
4599{
4600 // Player disconnected?
4601 if (!g_isconnected[id])
4602 return PLUGIN_HANDLED;
4603
4604 switch (key)
4605 {
4606 case 0: // Buy Weapons
4607 {
4608 // Custom buy menus enabled?
4609 if (get_pcvar_num(cvar_buycustom))
4610 {
4611 // Disable the remember selection setting
4612 WPN_AUTO_ON = 0
4613 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "BUY_ENABLED")
4614
4615 // Show menu if player hasn't yet bought anything
4616 if (g_canbuy[id]) show_menu_buy1(id)
4617 }
4618 else
4619 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
4620 }
4621 case 1: // Extra Items
4622 {
4623 // Extra items enabled?
4624 if (get_pcvar_num(cvar_extraitems))
4625 {
4626 // Check whether the player is able to buy anything
4627 if (g_isalive[id])
4628 show_menu_extras(id)
4629 else
4630 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
4631 }
4632 else
4633 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_EXTRAS")
4634 }
4635 case 2: // Zombie Classes
4636 {
4637 // Zombie classes enabled?
4638 if (get_pcvar_num(cvar_zclasses))
4639 show_menu_zclass(id)
4640 else
4641 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ZCLASSES")
4642 }
4643 case 3: // Unstuck
4644 {
4645 // Check if player is stuck
4646 if (g_isalive[id])
4647 {
4648 if (is_player_stuck(id))
4649 {
4650 // Move to an initial spawn
4651 if (get_pcvar_num(cvar_randspawn))
4652 do_random_spawn(id) // random spawn (including CSDM)
4653 else
4654 do_random_spawn(id, 1) // regular spawn
4655 }
4656 else
4657 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_STUCK")
4658 }
4659 else
4660 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
4661 }
4662 case 4: // Help Menu
4663 {
4664 show_menu_info(id)
4665 }
4666 case 5: // Join Spectator
4667 {
4668 // Player alive?
4669 if (g_isalive[id])
4670 {
4671 // Prevent abuse by non-admins if block suicide setting is enabled
4672 if (get_pcvar_num(cvar_blocksuicide) && !(get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MENU]))
4673 {
4674 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
4675 return PLUGIN_HANDLED;
4676 }
4677
4678 // Check that we still have both humans and zombies to keep the round going
4679 check_round(id)
4680
4681 // Kill him before he switches team
4682 dllfunc(DLLFunc_ClientKill, id)
4683 }
4684
4685 // Temporarily save player stats?
4686 if (get_pcvar_num(cvar_statssave)) save_stats(id)
4687
4688 // Remove previous tasks
4689 remove_task(id+TASK_TEAM)
4690 remove_task(id+TASK_MODEL)
4691 remove_task(id+TASK_FLASH)
4692 remove_task(id+TASK_CHARGE)
4693 remove_task(id+TASK_SPAWN)
4694 remove_task(id+TASK_BLOOD)
4695 remove_task(id+TASK_AURA)
4696 remove_task(id+TASK_BURN)
4697
4698 // Then move him to the spectator team
4699 fm_cs_set_user_team(id, FM_CS_TEAM_SPECTATOR)
4700 fm_user_team_update(id)
4701 }
4702 case 8: // Admin Menu
4703 {
4704 // Check if player has the required access
4705 if (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MENU])
4706 show_menu_admin(id)
4707 else
4708 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
4709 }
4710 }
4711
4712 return PLUGIN_HANDLED;
4713}
4714
4715// Buy Menu 1
4716public menu_buy1(id, key)
4717{
4718 // Player dead?
4719 if (!g_isalive[id])
4720 return PLUGIN_HANDLED;
4721
4722 // Zombies or survivors get no guns
4723 if (g_zombie[id] || g_survivor[id] || g_sniper[id])
4724 return PLUGIN_HANDLED;
4725
4726 // Special keys / weapon list exceeded
4727 if (key >= MENU_KEY_AUTOSELECT || WPN_SELECTION >= WPN_MAXIDS)
4728 {
4729 switch (key)
4730 {
4731 case MENU_KEY_AUTOSELECT: // toggle auto select
4732 {
4733 WPN_AUTO_ON = 1 - WPN_AUTO_ON
4734 }
4735 case MENU_KEY_NEXT: // next/back
4736 {
4737 if (WPN_STARTID+7 < WPN_MAXIDS)
4738 WPN_STARTID += 7
4739 else
4740 WPN_STARTID = 0
4741 }
4742 case MENU_KEY_EXIT: // exit
4743 {
4744 return PLUGIN_HANDLED;
4745 }
4746 }
4747
4748 // Show buy menu again
4749 show_menu_buy1(id)
4750 return PLUGIN_HANDLED;
4751 }
4752
4753 // Store selected weapon id
4754 WPN_AUTO_PRI = WPN_SELECTION
4755
4756 // Buy primary weapon
4757 buy_primary_weapon(id, WPN_AUTO_PRI)
4758
4759 // Show pistols menu
4760 show_menu_buy2(id)
4761
4762 return PLUGIN_HANDLED;
4763}
4764
4765// Buy Primary Weapon
4766buy_primary_weapon(id, selection)
4767{
4768 // Drop previous weapons
4769 drop_weapons(id, 1)
4770 drop_weapons(id, 2)
4771
4772 // Strip off from weapons
4773 fm_strip_user_weapons(id)
4774 fm_give_item(id, "weapon_knife")
4775
4776 // Get weapon's id and name
4777 static weaponid, wname[32]
4778 weaponid = ArrayGetCell(g_primary_weaponids, selection)
4779 ArrayGetString(g_primary_items, selection, wname, charsmax(wname))
4780
4781 // Give the new weapon and full ammo
4782 fm_give_item(id, wname)
4783 ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[weaponid], AMMOTYPE[weaponid], MAXBPAMMO[weaponid])
4784
4785 // Weapons bought
4786 g_canbuy[id] = false
4787
4788 // Give additional items
4789 static i
4790 for (i = 0; i < ArraySize(g_additional_items); i++)
4791 {
4792 ArrayGetString(g_additional_items, i, wname, charsmax(wname))
4793 fm_give_item(id, wname)
4794 }
4795}
4796
4797// Buy Menu 2
4798public menu_buy2(id, key)
4799{
4800 // Player dead?
4801 if (!g_isalive[id])
4802 return PLUGIN_HANDLED;
4803
4804 // Zombies or survivors get no guns
4805 if (g_zombie[id] || g_survivor[id] || g_sniper[id])
4806 return PLUGIN_HANDLED;
4807
4808 // Special keys / weapon list exceeded
4809 if (key >= ArraySize(g_secondary_items))
4810 {
4811 // Toggle autoselect
4812 if (key == MENU_KEY_AUTOSELECT)
4813 WPN_AUTO_ON = 1 - WPN_AUTO_ON
4814
4815 // Reshow menu unless user exited
4816 if (key != MENU_KEY_EXIT)
4817 show_menu_buy2(id)
4818
4819 return PLUGIN_HANDLED;
4820 }
4821
4822 // Store selected weapon
4823 WPN_AUTO_SEC = key
4824
4825 // Drop secondary gun again, in case we picked another (bugfix)
4826 drop_weapons(id, 2)
4827
4828 // Get weapon's id
4829 static weaponid, wname[32]
4830 weaponid = ArrayGetCell(g_secondary_weaponids, key)
4831 ArrayGetString(g_secondary_items, key, wname, charsmax(wname))
4832
4833 // Give the new weapon and full ammo
4834 fm_give_item(id, wname)
4835 ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[weaponid], AMMOTYPE[weaponid], MAXBPAMMO[weaponid])
4836
4837 return PLUGIN_HANDLED;
4838}
4839
4840// Extra Items Menu
4841public menu_extras(id, menuid, item)
4842{
4843 // Player disconnected?
4844 if (!is_user_connected(id))
4845 {
4846 menu_destroy(menuid)
4847 return PLUGIN_HANDLED;
4848 }
4849
4850 // Remember player's menu page
4851 static menudummy
4852 player_menu_info(id, menudummy, menudummy, MENU_PAGE_EXTRAS)
4853
4854 // Menu was closed
4855 if (item == MENU_EXIT)
4856 {
4857 menu_destroy(menuid)
4858 return PLUGIN_HANDLED;
4859 }
4860
4861 // Dead players are not allowed to buy items
4862 if (!g_isalive[id])
4863 {
4864 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
4865 menu_destroy(menuid)
4866 return PLUGIN_HANDLED;
4867 }
4868
4869 // Retrieve extra item id
4870 static buffer[2], dummy, itemid
4871 menu_item_getinfo(menuid, item, dummy, buffer, charsmax(buffer), _, _, dummy)
4872 itemid = buffer[0]
4873
4874 // Attempt to buy the item
4875 buy_extra_item(id, itemid)
4876 menu_destroy(menuid)
4877 return PLUGIN_HANDLED;
4878}
4879
4880// Buy Extra Item
4881buy_extra_item(id, itemid, ignorecost = 0)
4882{
4883 // Retrieve item's team
4884 static team
4885 team = ArrayGetCell(g_extraitem_team, itemid)
4886
4887 // Check for team/class specific items
4888 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)))
4889 {
4890 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
4891 return;
4892 }
4893
4894 // Check for unavailable items
4895 if ((itemid == EXTRA_NVISION && !get_pcvar_num(cvar_extranvision))
4896 || (itemid == EXTRA_ANTIDOTE && (!get_pcvar_num(cvar_extraantidote) || g_antidotecounter >= get_pcvar_num(cvar_antidotelimit)))
4897 || (itemid == EXTRA_MADNESS && (!get_pcvar_num(cvar_extramadness) || g_madnesscounter >= get_pcvar_num(cvar_madnesslimit)))
4898 || (itemid == EXTRA_INFBOMB && (!get_pcvar_num(cvar_extrainfbomb) || g_infbombcounter >= get_pcvar_num(cvar_infbomblimit)))
4899 || (itemid >= EXTRA_WEAPONS_STARTID && itemid <= EXTRAS_CUSTOM_STARTID-1 && !get_pcvar_num(cvar_extraweapons)))
4900 {
4901 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
4902 return;
4903 }
4904
4905 // Check for hard coded items with special conditions
4906 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)))
4907 || (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)))
4908 {
4909 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_CANTUSE")
4910 return;
4911 }
4912
4913 // Ignore item's cost?
4914 if (!ignorecost)
4915 {
4916 // Check that we have enough ammo packs
4917 if (g_ammopacks[id] < ArrayGetCell(g_extraitem_cost, itemid))
4918 {
4919 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "NOT_ENOUGH_AMMO")
4920 return;
4921 }
4922
4923 // Deduce item cost
4924 g_ammopacks[id] -= ArrayGetCell(g_extraitem_cost, itemid)
4925 }
4926
4927 // Check which kind of item we're buying
4928 switch (itemid)
4929 {
4930 case EXTRA_NVISION: // Night Vision
4931 {
4932 g_nvision[id] = true
4933
4934 if (!g_isbot[id])
4935 {
4936 g_nvisionenabled[id] = true
4937
4938 // Custom nvg?
4939 if (get_pcvar_num(cvar_customnvg))
4940 {
4941 remove_task(id+TASK_NVISION)
4942 set_task(0.1, "set_user_nvision", id+TASK_NVISION, _, _, "b")
4943 }
4944 else
4945 set_user_gnvision(id, 1)
4946 }
4947 else
4948 cs_set_user_nvg(id, 1)
4949 }
4950 case EXTRA_ANTIDOTE: // Antidote
4951 {
4952 // Increase antidote purchase count for this round
4953 g_antidotecounter++
4954
4955 humanme(id, 0, 0, 0)
4956 }
4957 case EXTRA_MADNESS: // Zombie Madness
4958 {
4959 // Increase madness purchase count for this round
4960 g_madnesscounter++
4961
4962 g_nodamage[id] = true
4963 set_task(0.1, "zombie_aura", id+TASK_AURA, _, _, "b")
4964 set_task(get_pcvar_float(cvar_madnessduration), "madness_over", id+TASK_BLOOD)
4965
4966 static sound[64]
4967 ArrayGetString(zombie_madness, random_num(0, ArraySize(zombie_madness) - 1), sound, charsmax(sound))
4968 emit_sound(id, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
4969 }
4970 case EXTRA_INFBOMB: // Infection Bomb
4971 {
4972 // Increase infection bomb purchase count for this round
4973 g_infbombcounter++
4974
4975 // Already own one
4976 if (user_has_weapon(id, CSW_HEGRENADE))
4977 {
4978 // Increase BP ammo on it instead
4979 cs_set_user_bpammo(id, CSW_HEGRENADE, cs_get_user_bpammo(id, CSW_HEGRENADE) + 1)
4980
4981 // Flash ammo in hud
4982 message_begin(MSG_ONE_UNRELIABLE, g_msgAmmoPickup, _, id)
4983 write_byte(AMMOID[CSW_HEGRENADE]) // ammo id
4984 write_byte(1) // ammo amount
4985 message_end()
4986
4987 // Play clip purchase sound
4988 emit_sound(id, CHAN_ITEM, sound_buyammo, 1.0, ATTN_NORM, 0, PITCH_NORM)
4989
4990 return; // stop here
4991 }
4992
4993 // Give weapon to the player
4994 fm_give_item(id, "weapon_hegrenade")
4995 }
4996 default:
4997 {
4998 if (itemid >= EXTRA_WEAPONS_STARTID && itemid <= EXTRAS_CUSTOM_STARTID-1) // Weapons
4999 {
5000 // Get weapon's id and name
5001 static weaponid, wname[32]
5002 ArrayGetString(g_extraweapon_items, itemid - EXTRA_WEAPONS_STARTID, wname, charsmax(wname))
5003 weaponid = cs_weapon_name_to_id(wname)
5004
5005 // If we are giving a primary/secondary weapon
5006 if (MAXBPAMMO[weaponid] > 2)
5007 {
5008 // Make user drop the previous one
5009 if ((1<<weaponid) & PRIMARY_WEAPONS_BIT_SUM)
5010 drop_weapons(id, 1)
5011 else
5012 drop_weapons(id, 2)
5013
5014 // Give full BP ammo for the new one
5015 ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[weaponid], AMMOTYPE[weaponid], MAXBPAMMO[weaponid])
5016 }
5017 // If we are giving a grenade which the user already owns
5018 else if (user_has_weapon(id, weaponid))
5019 {
5020 // Increase BP ammo on it instead
5021 cs_set_user_bpammo(id, weaponid, cs_get_user_bpammo(id, weaponid) + 1)
5022
5023 // Flash ammo in hud
5024 message_begin(MSG_ONE_UNRELIABLE, g_msgAmmoPickup, _, id)
5025 write_byte(AMMOID[weaponid]) // ammo id
5026 write_byte(1) // ammo amount
5027 message_end()
5028
5029 // Play clip purchase sound
5030 emit_sound(id, CHAN_ITEM, sound_buyammo, 1.0, ATTN_NORM, 0, PITCH_NORM)
5031
5032 return; // stop here
5033 }
5034
5035 // Give weapon to the player
5036 fm_give_item(id, wname)
5037 }
5038 else // Custom additions
5039 {
5040 // Item selected forward
5041 ExecuteForward(g_fwExtraItemSelected, g_fwDummyResult, id, itemid);
5042
5043 // Item purchase blocked, restore buyer's ammo packs
5044 if (g_fwDummyResult >= ZP_PLUGIN_HANDLED && !ignorecost)
5045 g_ammopacks[id] += ArrayGetCell(g_extraitem_cost, itemid)
5046 }
5047 }
5048 }
5049}
5050
5051// Zombie Class Menu
5052public menu_zclass(id, menuid, item)
5053{
5054 // Player disconnected?
5055 if (!is_user_connected(id))
5056 {
5057 menu_destroy(menuid)
5058 return PLUGIN_HANDLED;
5059 }
5060
5061 // Remember player's menu page
5062 static menudummy
5063 player_menu_info(id, menudummy, menudummy, MENU_PAGE_ZCLASS)
5064
5065 // Menu was closed
5066 if (item == MENU_EXIT)
5067 {
5068 menu_destroy(menuid)
5069 return PLUGIN_HANDLED;
5070 }
5071
5072 // Retrieve zombie class id
5073 static buffer[2], dummy, classid
5074 menu_item_getinfo(menuid, item, dummy, buffer, charsmax(buffer), _, _, dummy)
5075 classid = buffer[0]
5076
5077 // Store selection for the next infection
5078 g_zombieclassnext[id] = classid
5079
5080 static name[32]
5081 ArrayGetString(g_zclass_name, g_zombieclassnext[id], name, charsmax(name))
5082
5083 // Show selected zombie class info and stats
5084 zp_colored_print(id, "^x04[ZP]^x01 %L^x01:^x04 %s", id, "ZOMBIE_SELECT", name)
5085 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]),
5086 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))
5087
5088 menu_destroy(menuid)
5089 return PLUGIN_HANDLED;
5090}
5091
5092// Info Menu
5093public menu_info(id, key)
5094{
5095 // Player disconnected?
5096 if (!g_isconnected[id])
5097 return PLUGIN_HANDLED;
5098
5099 static motd[1500], len
5100 len = 0
5101
5102 switch (key)
5103 {
5104 case 0: // General
5105 {
5106 static weather, lighting[2]
5107 weather = 0
5108 get_pcvar_string(cvar_lighting, lighting, charsmax(lighting))
5109 strtolower(lighting)
5110
5111 len += formatex(motd[len], charsmax(motd) - len, "%L ", id, "MOTD_INFO11", "Zombie Plague", PLUGIN_VERSION, "MeRcyLeZZ and Bakir")
5112 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO12")
5113 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_A")
5114
5115 if (g_ambience_fog)
5116 {
5117 len += formatex(motd[len], charsmax(motd) - len, (weather < 1) ? " %L" : ". %L", id, "MOTD_FOG")
5118 weather++
5119 }
5120 if (g_ambience_rain)
5121 {
5122 len += formatex(motd[len], charsmax(motd) - len, (weather < 1) ? " %L" : ". %L", id, "MOTD_RAIN")
5123 weather++
5124 }
5125 if (g_ambience_snow)
5126 {
5127 len += formatex(motd[len], charsmax(motd) - len, (weather < 1) ? " %L" : ". %L", id, "MOTD_SNOW")
5128 weather++
5129 }
5130 if (weather < 1) len += formatex(motd[len], charsmax(motd) - len, " %L", id, "MOTD_DISABLED")
5131
5132 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_B", lighting)
5133 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_C", id, get_pcvar_num(cvar_triggered) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5134 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)))
5135 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")
5136 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")
5137 if (get_pcvar_num(cvar_deathmatch)) len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_G", floatround(get_pcvar_float(cvar_spawnprotection)))
5138 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_H", id, get_pcvar_num(cvar_randspawn) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5139 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_I", id, get_pcvar_num(cvar_extraitems) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5140 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_J", id, get_pcvar_num(cvar_zclasses) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5141 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_K", id, get_pcvar_num(cvar_customnvg) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5142 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_L", id, g_cached_customflash ? "MOTD_ENABLED" : "MOTD_DISABLED")
5143
5144 show_motd(id, motd)
5145 }
5146 case 1: // Humans
5147 {
5148 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2")
5149 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_A", get_pcvar_num(cvar_humanhp))
5150 if (get_pcvar_num(cvar_humanlasthp) > 0) len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_B", get_pcvar_num(cvar_humanlasthp))
5151 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_C", get_pcvar_num(cvar_humanspd))
5152 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_D", floatround(get_pcvar_float(cvar_humangravity) * 800.0))
5153 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")
5154 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_F", get_pcvar_num(cvar_ammodamage_human))
5155 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_G", id, get_pcvar_num(cvar_firegrenades) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5156 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_H", id, get_pcvar_num(cvar_frostgrenades) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5157 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_I", id, get_pcvar_num(cvar_flaregrenades) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5158 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_J", id, get_pcvar_num(cvar_knockback) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5159
5160 show_motd(id, motd)
5161 }
5162 case 2: // Zombies
5163 {
5164 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3")
5165 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_A", ArrayGetCell(g_zclass_hp, 0))
5166 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_B", floatround(float(ArrayGetCell(g_zclass_hp, 0)) * get_pcvar_float(cvar_zombiefirsthp)))
5167 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_C", floatround(get_pcvar_float(cvar_zombiearmor) * 100.0))
5168 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_D", ArrayGetCell(g_zclass_spd, 0))
5169 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_E", floatround(Float:ArrayGetCell(g_zclass_grav, 0) * 800.0))
5170 if (get_pcvar_num(cvar_zombiebonushp)) len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_F", get_pcvar_num(cvar_zombiebonushp))
5171 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")
5172 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_H", id, get_pcvar_num(cvar_zombiebleeding) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5173 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_I", get_pcvar_num(cvar_ammoinfect))
5174
5175 show_motd(id, motd)
5176 }
5177 case 3: // Gameplay Modes
5178 {
5179 static nemhp[5], survhp[5], snihp[5], assahp[5]
5180
5181 // Get nemesis and survivor health
5182 num_to_str(get_pcvar_num(cvar_nemhp), nemhp, charsmax(nemhp))
5183 num_to_str(get_pcvar_num(cvar_survhp), survhp, charsmax(survhp))
5184 num_to_str(get_pcvar_num(cvar_snihp), snihp, charsmax(snihp))
5185 num_to_str(get_pcvar_num(cvar_assahp), assahp, charsmax(assahp))
5186
5187 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4")
5188
5189 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_A", id, get_pcvar_num(cvar_nem) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5190 if (get_pcvar_num(cvar_nem))
5191 {
5192 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_B", get_pcvar_num(cvar_nemchance))
5193 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_C", get_pcvar_num(cvar_nemhp) > 0 ? nemhp : "[Auto]")
5194 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_D", get_pcvar_num(cvar_nemspd))
5195 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_E", floatround(get_pcvar_float(cvar_nemgravity) * 800.0))
5196 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_F", id, g_cached_leapnemesis ? "MOTD_ENABLED" : "MOTD_DISABLED")
5197 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_G", id, get_pcvar_num(cvar_nempainfree) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5198 }
5199 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_H", id, get_pcvar_num(cvar_surv) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5200 if (get_pcvar_num(cvar_surv))
5201 {
5202 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_I", get_pcvar_num(cvar_survchance))
5203 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_J", get_pcvar_num(cvar_survhp) > 0 ? survhp : "[Auto]")
5204 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_K", get_pcvar_num(cvar_survspd))
5205 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_L", floatround(get_pcvar_float(cvar_survgravity) * 800.0))
5206 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_M", id, g_cached_leapsurvivor ? "MOTD_ENABLED" : "MOTD_DISABLED")
5207 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_N", id, get_pcvar_num(cvar_survpainfree) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5208 }
5209
5210 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_O", id, get_pcvar_num(cvar_swarm) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5211 if (get_pcvar_num(cvar_swarm)) len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_P", get_pcvar_num(cvar_swarmchance))
5212
5213 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_Q", id, get_pcvar_num(cvar_multi) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5214 if (get_pcvar_num(cvar_multi))
5215 {
5216 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_R", get_pcvar_num(cvar_multichance))
5217 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_S", floatround(get_pcvar_float(cvar_multiratio) * 100.0))
5218 }
5219
5220 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_T", id, get_pcvar_num(cvar_plague) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5221 if (get_pcvar_num(cvar_plague))
5222 {
5223 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_U", get_pcvar_num(cvar_plaguechance))
5224 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_V", floatround(get_pcvar_float(cvar_plagueratio) * 100.0))
5225 }
5226
5227 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO5_A", id, get_pcvar_num(cvar_sni) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5228 if (get_pcvar_num(cvar_sni))
5229 {
5230 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO5_B", get_pcvar_num(cvar_snichance))
5231 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO5_C", get_pcvar_num(cvar_snihp) > 0 ? snihp : "[Auto]")
5232 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO5_E", floatround(get_pcvar_float(cvar_snigravity) * 800.0))
5233 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO5_F", id, g_cached_leapsniper ? "MOTD_ENABLED" : "MOTD_DISABLED")
5234 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO5_G", id, get_pcvar_num(cvar_snipainfree) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5235 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO5_H", floatround(get_pcvar_float(cvar_snidamage)))
5236 }
5237
5238 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_A", id, get_pcvar_num(cvar_assa) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5239 if (get_pcvar_num(cvar_assa))
5240 {
5241 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_B", get_pcvar_num(cvar_assachance))
5242 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_C", get_pcvar_num(cvar_assahp) > 0 ? assahp : "[Auto]")
5243 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_D", get_pcvar_num(cvar_assaspd))
5244 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_E", floatround(get_pcvar_float(cvar_assagravity) * 800.0))
5245 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_F", id, g_cached_leapassassin ? "MOTD_ENABLED" : "MOTD_DISABLED")
5246 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_G", id, get_pcvar_num(cvar_assapainfree) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5247 }
5248
5249 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_H", id, get_pcvar_num(cvar_armage) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5250 if (get_pcvar_num(cvar_armage))
5251 {
5252 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_I", get_pcvar_num(cvar_armagechance))
5253 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_J", floatround(get_pcvar_float(cvar_armageratio) * 100.0))
5254 }
5255
5256 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO7_H", id, get_pcvar_num(cvar_apoc) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5257 if (get_pcvar_num(cvar_apoc))
5258 {
5259 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO7_I", get_pcvar_num(cvar_apocchance))
5260 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO7_J", floatround(get_pcvar_float(cvar_apocratio ) * 100.0))
5261 }
5262
5263 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO8_H", id, get_pcvar_num(cvar_night) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5264 if (get_pcvar_num(cvar_night))
5265 {
5266 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO8_I", get_pcvar_num(cvar_nightchance))
5267 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO8_J", floatround(get_pcvar_float(cvar_nightratio) * 100.0))
5268 }
5269
5270 show_motd(id, motd)
5271 }
5272 default: return PLUGIN_HANDLED;
5273 }
5274
5275 // Show help menu again if user wishes to read another topic
5276 show_menu_info(id)
5277
5278 return PLUGIN_HANDLED;
5279}
5280
5281// Admin Menu
5282public menu_admin(id, key)
5283{
5284 // Player disconnected?
5285 if (!g_isconnected[id])
5286 return PLUGIN_HANDLED;
5287
5288 static userflags
5289 userflags = get_user_flags(id)
5290
5291 switch (key)
5292 {
5293 case ACTION_ZOMBIEFY_HUMANIZE: // Zombiefy/Humanize command
5294 {
5295 if (userflags & (g_access_flag[ACCESS_MODE_INFECTION] | g_access_flag[ACCESS_MAKE_ZOMBIE] | g_access_flag[ACCESS_MAKE_HUMAN]))
5296 {
5297 // Show player list for admin to pick a target
5298 PL_ACTION = ACTION_ZOMBIEFY_HUMANIZE
5299 show_menu_player_list(id)
5300 }
5301 else
5302 {
5303 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5304 show_menu_admin(id)
5305 }
5306 }
5307 case ACTION_MAKE_NEMESIS: // Nemesis command
5308 {
5309 if (userflags & (g_access_flag[ACCESS_MODE_NEMESIS] | g_access_flag[ACCESS_MAKE_NEMESIS]))
5310 {
5311 // Show player list for admin to pick a target
5312 PL_ACTION = ACTION_MAKE_NEMESIS
5313 show_menu_player_list(id)
5314 }
5315 else
5316 {
5317 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5318 show_menu_admin(id)
5319 }
5320 }
5321 case ACTION_MAKE_ASSASSIN: // Assassin command
5322 {
5323 if (userflags & (g_access_flag[ACCESS_MODE_ASSASSIN] | g_access_flag[ACCESS_MAKE_ASSASSIN]))
5324 {
5325 // Show player list for admin to pick a target
5326 PL_ACTION = ACTION_MAKE_ASSASSIN
5327 show_menu_player_list(id)
5328 }
5329 else
5330 {
5331 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5332 show_menu_admin(id)
5333 }
5334 }
5335 case ACTION_MAKE_SURVIVOR: // Survivor command
5336 {
5337 if (userflags & (g_access_flag[ACCESS_MODE_SURVIVOR] | g_access_flag[ACCESS_MAKE_SURVIVOR]))
5338 {
5339 // Show player list for admin to pick a target
5340 PL_ACTION = ACTION_MAKE_SURVIVOR
5341 show_menu_player_list(id)
5342 }
5343 else
5344 {
5345 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5346 show_menu_admin(id)
5347 }
5348 }
5349 case ACTION_MAKE_SNIPER: // Sniper command
5350 {
5351 if (userflags & (g_access_flag[ACCESS_MODE_SNIPER] | g_access_flag[ACCESS_MAKE_SNIPER]))
5352 {
5353 // Show player list for admin to pick a target
5354 PL_ACTION = ACTION_MAKE_SNIPER
5355 show_menu_player_list(id)
5356 }
5357 else
5358 {
5359 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5360 show_menu_admin(id)
5361 }
5362 }
5363 case ACTION_RESPAWN_PLAYER: // Respawn command
5364 {
5365 if (userflags & g_access_flag[ACCESS_RESPAWN_PLAYERS])
5366 {
5367 // Show player list for admin to pick a target
5368 PL_ACTION = ACTION_RESPAWN_PLAYER
5369 show_menu_player_list(id)
5370 }
5371 else
5372 {
5373 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5374 show_menu_admin(id)
5375 }
5376 }
5377 case ACTION_MODES_MENU: // Admin Modes command
5378 {
5379 if (userflags & g_access_flag[ACCESS_ADMIN_MODES_MENU])
5380 show_menu_modes_admin(id)
5381 else
5382 {
5383 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5384 show_menu_admin(id)
5385 }
5386 }
5387 }
5388
5389 return PLUGIN_HANDLED;
5390}
5391
5392// Admin Modes Menu
5393public menu_modes_admin(id, key)
5394{
5395 static userflags
5396 userflags = get_user_flags(id)
5397
5398 switch (key)
5399 {
5400 case ACTION_MODE_SWARM: // Swarm Mode command
5401 {
5402 if (userflags & g_access_flag[ACCESS_MODE_SWARM])
5403 {
5404 if (allowed_swarm())
5405 command_swarm(id)
5406 else
5407 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5408 }
5409 else
5410 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5411
5412 show_menu_modes_admin(id)
5413 }
5414 case ACTION_MODE_MULTI: // Multiple Infection command
5415 {
5416 if (userflags & g_access_flag[ACCESS_MODE_MULTI])
5417 {
5418 if (allowed_multi())
5419 command_multi(id)
5420 else
5421 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5422 }
5423 else
5424 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5425
5426 show_menu_modes_admin(id)
5427 }
5428 case ACTION_MODE_PLAGUE: // Plague Mode command
5429 {
5430 if (userflags & g_access_flag[ACCESS_MODE_PLAGUE])
5431 {
5432 if (allowed_plague())
5433 command_plague(id)
5434 else
5435 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5436 }
5437 else
5438 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5439
5440 show_menu_modes_admin(id)
5441 }
5442 case ACTION_MODE_ARMAGEDDON: // Armageddon Mode command
5443 {
5444 if (userflags & g_access_flag[ACCESS_MODE_ARMAGEDDON])
5445 {
5446 if (allowed_armageddon())
5447 command_armageddon(id)
5448 else
5449 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5450 }
5451 else
5452 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5453
5454 show_menu_modes_admin(id)
5455 }
5456 case ACTION_MODE_APOCALYPSE: // Apocalypse Mode command
5457 {
5458 if (userflags & g_access_flag[ACCESS_MODE_APOCALYPSE])
5459 {
5460 if (allowed_apocalypse())
5461 command_apocalypse(id)
5462 else
5463 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5464 }
5465 else
5466 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5467
5468 show_menu_modes_admin(id)
5469 }
5470 case ACTION_MODE_NIGHTMARE: // Nightmare Mode command
5471 {
5472 if (userflags & g_access_flag[ACCESS_MODE_NIGHTMARE])
5473 {
5474 if (allowed_nightmare())
5475 command_nightmare(id)
5476 else
5477 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5478 }
5479 else
5480 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5481
5482 show_menu_modes_admin(id)
5483 }
5484 }
5485
5486 return PLUGIN_HANDLED;
5487}
5488
5489// Player List Menu
5490public menu_player_list(id, menuid, item)
5491{
5492 // Player disconnected?
5493 if (!is_user_connected(id))
5494 {
5495 menu_destroy(menuid)
5496 return PLUGIN_HANDLED;
5497 }
5498
5499 // Remember player's menu page
5500 static menudummy
5501 player_menu_info(id, menudummy, menudummy, MENU_PAGE_PLAYERS)
5502
5503 // Menu was closed
5504 if (item == MENU_EXIT)
5505 {
5506 menu_destroy(menuid)
5507 show_menu_admin(id)
5508 return PLUGIN_HANDLED;
5509 }
5510
5511 // Retrieve player id
5512 static buffer[2], dummy, playerid
5513 menu_item_getinfo(menuid, item, dummy, buffer, charsmax(buffer), _, _, dummy)
5514 playerid = buffer[0]
5515
5516 // Perform action on player
5517
5518 // Get admin flags
5519 static userflags
5520 userflags = get_user_flags(id)
5521
5522 // Make sure it's still connected
5523 if (g_isconnected[playerid])
5524 {
5525 // Perform the right action if allowed
5526 switch (PL_ACTION)
5527 {
5528 case ACTION_ZOMBIEFY_HUMANIZE: // Zombiefy/Humanize command
5529 {
5530 if (g_zombie[playerid])
5531 {
5532 if (userflags & g_access_flag[ACCESS_MAKE_HUMAN])
5533 {
5534 if (allowed_human(playerid))
5535 command_human(id, playerid)
5536 else
5537 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5538 }
5539 else
5540 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5541 }
5542 else
5543 {
5544 if (g_newround ? (userflags & g_access_flag[ACCESS_MODE_INFECTION]) : (userflags & g_access_flag[ACCESS_MAKE_ZOMBIE]))
5545 {
5546 if (allowed_zombie(playerid))
5547 command_zombie(id, playerid)
5548 else
5549 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5550 }
5551 else
5552 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5553 }
5554 }
5555 case ACTION_MAKE_NEMESIS: // Nemesis command
5556 {
5557 if (g_newround ? (userflags & g_access_flag[ACCESS_MODE_NEMESIS]) : (userflags & g_access_flag[ACCESS_MAKE_NEMESIS]))
5558 {
5559 if (allowed_nemesis(playerid))
5560 command_nemesis(id, playerid)
5561 else
5562 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5563 }
5564 else
5565 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5566 }
5567 case ACTION_MAKE_ASSASSIN: // Assassin command
5568 {
5569 if (g_newround ? (userflags & g_access_flag[ACCESS_MODE_ASSASSIN]) : (userflags & g_access_flag[ACCESS_MAKE_ASSASSIN]))
5570 {
5571 if (allowed_assassin(playerid))
5572 command_assassin(id, playerid)
5573 else
5574 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5575 }
5576 else
5577 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5578 }
5579 case ACTION_MAKE_SURVIVOR: // Survivor command
5580 {
5581 if (g_newround ? (userflags & g_access_flag[ACCESS_MODE_SURVIVOR]) : (userflags & g_access_flag[ACCESS_MAKE_SURVIVOR]))
5582 {
5583 if (allowed_survivor(playerid))
5584 command_survivor(id, playerid)
5585 else
5586 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5587 }
5588 else
5589 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5590 }
5591 case ACTION_MAKE_SNIPER: // Sniper command
5592 {
5593 if (g_newround ? (userflags & g_access_flag[ACCESS_MODE_SNIPER]) : (userflags & g_access_flag[ACCESS_MAKE_SNIPER]))
5594 {
5595 if (allowed_sniper(playerid))
5596 command_sniper(id, playerid)
5597 else
5598 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5599 }
5600 else
5601 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5602 }
5603 case ACTION_RESPAWN_PLAYER: // Respawn command
5604 {
5605 if (userflags & g_access_flag[ACCESS_RESPAWN_PLAYERS])
5606 {
5607 if (allowed_respawn(playerid))
5608 command_respawn(id, playerid)
5609 else
5610 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5611 }
5612 else
5613 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5614 }
5615 }
5616 }
5617 else
5618 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5619
5620 menu_destroy(menuid)
5621 show_menu_player_list(id)
5622 return PLUGIN_HANDLED;
5623}
5624
5625// CS Buy Menus
5626public menu_cs_buy(id, key)
5627{
5628 // Prevent buying if zombie/survivor (bugfix)
5629 if (g_zombie[id] || g_survivor[id] || g_sniper[id])
5630 return PLUGIN_HANDLED;
5631
5632 return PLUGIN_CONTINUE;
5633}
5634
5635/*================================================================================
5636 [Admin Commands]
5637=================================================================================*/
5638
5639// zp_toggle [1/0]
5640public cmd_toggle(id, level, cid)
5641{
5642 // Check for access flag - Enable/Disable Mod
5643 if (!cmd_access(id, g_access_flag[ACCESS_ENABLE_MOD], cid, 2))
5644 return PLUGIN_HANDLED;
5645
5646 // Retrieve arguments
5647 new arg[2]
5648 read_argv(1, arg, charsmax(arg))
5649
5650 // Mod already enabled/disabled
5651 if (str_to_num(arg) == g_pluginenabled)
5652 return PLUGIN_HANDLED;
5653
5654 // Set toggle cvar
5655 set_pcvar_num(cvar_toggle, str_to_num(arg))
5656 client_print(id, print_console, "Zombie Plague %L.", id, str_to_num(arg) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5657
5658 // Retrieve map name
5659 new mapname[32]
5660 get_mapname(mapname, charsmax(mapname))
5661
5662 // Restart current map
5663 server_cmd("changelevel %s", mapname)
5664
5665 return PLUGIN_HANDLED;
5666}
5667
5668// zp_zombie [target]
5669public cmd_zombie(id, level, cid)
5670{
5671 // Check for access flag depending on the resulting action
5672 if (g_newround)
5673 {
5674 // Start Mode Infection
5675 if (!cmd_access(id, g_access_flag[ACCESS_MODE_INFECTION], cid, 2))
5676 return PLUGIN_HANDLED;
5677 }
5678 else
5679 {
5680 // Make Zombie
5681 if (!cmd_access(id, g_access_flag[ACCESS_MAKE_ZOMBIE], cid, 2))
5682 return PLUGIN_HANDLED;
5683 }
5684
5685 // Retrieve arguments
5686 static arg[32], player
5687 read_argv(1, arg, charsmax(arg))
5688 player = cmd_target(id, arg, (CMDTARGET_ONLY_ALIVE | CMDTARGET_ALLOW_SELF))
5689
5690 // Invalid target
5691 if (!player) return PLUGIN_HANDLED;
5692
5693 // Target not allowed to be zombie
5694 if (!allowed_zombie(player))
5695 {
5696 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5697 return PLUGIN_HANDLED
5698 }
5699
5700 command_zombie(id, player)
5701
5702 return PLUGIN_HANDLED;
5703}
5704
5705// zp_human [target]
5706public cmd_human(id, level, cid)
5707{
5708 // Check for access flag - Make Human
5709 if (!cmd_access(id, g_access_flag[ACCESS_MAKE_HUMAN], cid, 2))
5710 return PLUGIN_HANDLED;
5711
5712 // Retrieve arguments
5713 static arg[32], player
5714 read_argv(1, arg, charsmax(arg))
5715 player = cmd_target(id, arg, (CMDTARGET_ONLY_ALIVE | CMDTARGET_ALLOW_SELF))
5716
5717 // Invalid target
5718 if (!player) return PLUGIN_HANDLED;
5719
5720 // Target not allowed to be human
5721 if (!allowed_human(player))
5722 {
5723 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5724 return PLUGIN_HANDLED;
5725 }
5726
5727 command_human(id, player)
5728
5729 return PLUGIN_HANDLED;
5730}
5731
5732// zp_survivor [target]
5733public cmd_survivor(id, level, cid)
5734{
5735 // Check for access flag depending on the resulting action
5736 if (g_newround)
5737 {
5738 // Start Mode Survivor
5739 if (!cmd_access(id, g_access_flag[ACCESS_MODE_SURVIVOR], cid, 2))
5740 return PLUGIN_HANDLED;
5741 }
5742 else
5743 {
5744 // Make Survivor
5745 if (!cmd_access(id, g_access_flag[ACCESS_MAKE_SURVIVOR], cid, 2))
5746 return PLUGIN_HANDLED;
5747 }
5748
5749 // Retrieve arguments
5750 static arg[32], player
5751 read_argv(1, arg, charsmax(arg))
5752 player = cmd_target(id, arg, (CMDTARGET_ONLY_ALIVE | CMDTARGET_ALLOW_SELF))
5753
5754 // Invalid target
5755 if (!player) return PLUGIN_HANDLED;
5756
5757 // Target not allowed to be survivor
5758 if (!allowed_survivor(player))
5759 {
5760 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5761 return PLUGIN_HANDLED;
5762 }
5763
5764 command_survivor(id, player)
5765
5766 return PLUGIN_HANDLED;
5767}
5768
5769// zp_sniper [target]
5770public cmd_sniper(id, level, cid)
5771{
5772 // Check for access flag depending on the resulting action
5773 if (g_newround)
5774 {
5775 // Start Mode Sniper
5776 if (!cmd_access(id, g_access_flag[ACCESS_MODE_SNIPER], cid, 2))
5777 return PLUGIN_HANDLED;
5778 }
5779 else
5780 {
5781 // Make Sniper
5782 if (!cmd_access(id, g_access_flag[ACCESS_MAKE_SNIPER], cid, 2))
5783 return PLUGIN_HANDLED;
5784 }
5785
5786 // Retrieve arguments
5787 static arg[32], player
5788 read_argv(1, arg, charsmax(arg))
5789 player = cmd_target(id, arg, (CMDTARGET_ONLY_ALIVE | CMDTARGET_ALLOW_SELF))
5790
5791 // Invalid target
5792 if (!player) return PLUGIN_HANDLED;
5793
5794 // Target not allowed to be sniper
5795 if (!allowed_sniper(player))
5796 {
5797 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5798 return PLUGIN_HANDLED;
5799 }
5800
5801 command_sniper(id, player)
5802
5803 return PLUGIN_HANDLED;
5804}
5805
5806// zp_nemesis [target]
5807public cmd_nemesis(id, level, cid)
5808{
5809 // Check for access flag depending on the resulting action
5810 if (g_newround)
5811 {
5812 // Start Mode Nemesis
5813 if (!cmd_access(id, g_access_flag[ACCESS_MODE_NEMESIS], cid, 2))
5814 return PLUGIN_HANDLED;
5815 }
5816 else
5817 {
5818 // Make Nemesis
5819 if (!cmd_access(id, g_access_flag[ACCESS_MAKE_NEMESIS], cid, 2))
5820 return PLUGIN_HANDLED;
5821 }
5822
5823 // Retrieve arguments
5824 static arg[32], player
5825 read_argv(1, arg, charsmax(arg))
5826 player = cmd_target(id, arg, (CMDTARGET_ONLY_ALIVE | CMDTARGET_ALLOW_SELF))
5827
5828 // Invalid target
5829 if (!player) return PLUGIN_HANDLED;
5830
5831 // Target not allowed to be nemesis
5832 if (!allowed_nemesis(player))
5833 {
5834 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5835 return PLUGIN_HANDLED;
5836 }
5837
5838 command_nemesis(id, player)
5839
5840 return PLUGIN_HANDLED;
5841}
5842
5843// zp_assassin [target]
5844public cmd_assassin(id, level, cid)
5845{
5846 // Check for access flag depending on the resulting action
5847 if (g_newround)
5848 {
5849 // Start Mode Assassin
5850 if (!cmd_access(id, g_access_flag[ACCESS_MODE_ASSASSIN], cid, 2))
5851 return PLUGIN_HANDLED;
5852 }
5853 else
5854 {
5855 // Make Assassin
5856 if (!cmd_access(id, g_access_flag[ACCESS_MAKE_ASSASSIN], cid, 2))
5857 return PLUGIN_HANDLED;
5858 }
5859
5860 // Retrieve arguments
5861 static arg[32], player
5862 read_argv(1, arg, charsmax(arg))
5863 player = cmd_target(id, arg, (CMDTARGET_ONLY_ALIVE | CMDTARGET_ALLOW_SELF))
5864
5865 // Invalid target
5866 if (!player) return PLUGIN_HANDLED;
5867
5868 // Target not allowed to be assassin
5869 if (!allowed_assassin(player))
5870 {
5871 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5872 return PLUGIN_HANDLED;
5873 }
5874
5875 command_assassin(id, player)
5876
5877 return PLUGIN_HANDLED;
5878}
5879
5880// zp_respawn [target]
5881public cmd_respawn(id, level, cid)
5882{
5883 // Check for access flag - Respawn
5884 if (!cmd_access(id, g_access_flag[ACCESS_RESPAWN_PLAYERS], cid, 2))
5885 return PLUGIN_HANDLED;
5886
5887 // Retrieve arguments
5888 static arg[32], player
5889 read_argv(1, arg, charsmax(arg))
5890 player = cmd_target(id, arg, CMDTARGET_ALLOW_SELF)
5891
5892 // Invalid target
5893 if (!player) return PLUGIN_HANDLED;
5894
5895 // Target not allowed to be respawned
5896 if (!allowed_respawn(player))
5897 {
5898 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5899 return PLUGIN_HANDLED;
5900 }
5901
5902 command_respawn(id, player)
5903
5904 return PLUGIN_HANDLED;
5905}
5906
5907// zp_swarm
5908public cmd_swarm(id, level, cid)
5909{
5910 // Check for access flag - Mode Swarm
5911 if (!cmd_access(id, g_access_flag[ACCESS_MODE_SWARM], cid, 1))
5912 return PLUGIN_HANDLED;
5913
5914 // Swarm mode not allowed
5915 if (!allowed_swarm())
5916 {
5917 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5918 return PLUGIN_HANDLED;
5919 }
5920
5921 command_swarm(id)
5922
5923 return PLUGIN_HANDLED;
5924}
5925
5926// zp_multi
5927public cmd_multi(id, level, cid)
5928{
5929 // Check for access flag - Mode Multi
5930 if (!cmd_access(id, g_access_flag[ACCESS_MODE_MULTI], cid, 1))
5931 return PLUGIN_HANDLED;
5932
5933 // Multi infection mode not allowed
5934 if (!allowed_multi())
5935 {
5936 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5937 return PLUGIN_HANDLED;
5938 }
5939
5940 command_multi(id)
5941
5942 return PLUGIN_HANDLED;
5943}
5944
5945// zp_plague
5946public cmd_plague(id, level, cid)
5947{
5948 // Check for access flag - Mode Plague
5949 if (!cmd_access(id, g_access_flag[ACCESS_MODE_PLAGUE], cid, 1))
5950 return PLUGIN_HANDLED;
5951
5952 // Plague mode not allowed
5953 if (!allowed_plague())
5954 {
5955 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5956 return PLUGIN_HANDLED;
5957 }
5958
5959 command_plague(id)
5960
5961 return PLUGIN_HANDLED;
5962}
5963
5964// zp_armageddon
5965public cmd_armageddon(id, level, cid)
5966{
5967 // Check for access flag - Mode Armageddon
5968 if (!cmd_access(id, g_access_flag[ACCESS_MODE_ARMAGEDDON], cid, 1))
5969 return PLUGIN_HANDLED;
5970
5971 // Armageddon mode not allowed
5972 if (!allowed_armageddon())
5973 {
5974 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5975 return PLUGIN_HANDLED;
5976 }
5977
5978 command_armageddon(id)
5979
5980 return PLUGIN_HANDLED;
5981}
5982
5983// zp_apocalypse
5984public cmd_apocalypse(id, level, cid)
5985{
5986 // Check for access flag - Mode Apocalypse
5987 if (!cmd_access(id, g_access_flag[ACCESS_MODE_APOCALYPSE], cid, 1))
5988 return PLUGIN_HANDLED;
5989
5990 // Apocalypse mode not allowed
5991 if (!allowed_apocalypse())
5992 {
5993 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5994 return PLUGIN_HANDLED;
5995 }
5996
5997 command_apocalypse(id)
5998
5999 return PLUGIN_HANDLED;
6000}
6001
6002// zp_nightmare
6003public cmd_nightmare(id, level, cid)
6004{
6005 // Check for access flag - Mode Nightmare
6006 if (!cmd_access(id, g_access_flag[ACCESS_MODE_NIGHTMARE], cid, 1))
6007 return PLUGIN_HANDLED;
6008
6009 // Nightmare mode not allowed
6010 if (!allowed_nightmare())
6011 {
6012 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
6013 return PLUGIN_HANDLED;
6014 }
6015
6016 command_nightmare(id)
6017
6018 return PLUGIN_HANDLED;
6019}
6020
6021/*================================================================================
6022 [Message Hooks]
6023=================================================================================*/
6024
6025// Current Weapon info
6026public message_cur_weapon(msg_id, msg_dest, msg_entity)
6027{
6028 // Not alive or zombie
6029 if (!g_isalive[msg_entity] || g_zombie[msg_entity])
6030 return;
6031
6032 // Not an active weapon
6033 if (get_msg_arg_int(1) != 1)
6034 return;
6035
6036 // Unlimited clip disabled for class
6037 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)
6038 return;
6039
6040 // Get weapon's id
6041 static weapon
6042 weapon = get_msg_arg_int(2)
6043
6044 // Unlimited Clip Ammo for this weapon?
6045 if (MAXBPAMMO[weapon] > 2)
6046 {
6047 // Max out clip ammo
6048 static weapon_ent
6049 weapon_ent = fm_cs_get_current_weapon_ent(msg_entity)
6050 if (pev_valid(weapon_ent)) cs_set_weapon_ammo(weapon_ent, MAXCLIP[weapon])
6051
6052 // HUD should show full clip all the time
6053 set_msg_arg_int(3, get_msg_argtype(3), MAXCLIP[weapon])
6054 }
6055}
6056
6057// Take off player's money
6058public message_money(msg_id, msg_dest, msg_entity)
6059{
6060 // Remove money setting enabled?
6061 if (!get_pcvar_num(cvar_removemoney))
6062 return PLUGIN_CONTINUE;
6063
6064 fm_cs_set_user_money(msg_entity, 0)
6065 return PLUGIN_HANDLED;
6066}
6067
6068// Fix for the HL engine bug when HP is multiples of 256
6069public message_health(msg_id, msg_dest, msg_entity)
6070{
6071 // Get player's health
6072 static health
6073 health = get_msg_arg_int(1)
6074
6075 // Don't bother
6076 if (health < 256) return;
6077
6078 // Check if we need to fix it
6079 if (health % 256 == 0)
6080 fm_set_user_health(msg_entity, pev(msg_entity, pev_health) + 1)
6081
6082 // HUD can only show as much as 255 hp
6083 set_msg_arg_int(1, get_msg_argtype(1), 255)
6084}
6085
6086// Block flashlight battery messages if custom flashlight is enabled instead
6087public message_flashbat()
6088{
6089 if (g_cached_customflash)
6090 return PLUGIN_HANDLED;
6091
6092 return PLUGIN_CONTINUE;
6093}
6094
6095// Flashbangs should only affect zombies
6096public message_screenfade(msg_id, msg_dest, msg_entity)
6097{
6098 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)
6099 return PLUGIN_CONTINUE;
6100
6101 // Nemesis shouldn't be FBed
6102 if (g_zombie[msg_entity] && !g_nemesis[msg_entity] && !g_assassin[msg_entity])
6103 {
6104 // Set flash color to nighvision's
6105 set_msg_arg_int(4, get_msg_argtype(4), get_pcvar_num(cvar_nvgcolor[0]))
6106 set_msg_arg_int(5, get_msg_argtype(5), get_pcvar_num(cvar_nvgcolor[1]))
6107 set_msg_arg_int(6, get_msg_argtype(6), get_pcvar_num(cvar_nvgcolor[2]))
6108 return PLUGIN_CONTINUE;
6109 }
6110
6111 return PLUGIN_HANDLED;
6112}
6113
6114// Prevent spectators' nightvision from being turned off when switching targets, etc.
6115public message_nvgtoggle()
6116{
6117 return PLUGIN_HANDLED;
6118}
6119
6120// Set correct model on player corpses
6121public message_clcorpse()
6122{
6123 set_msg_arg_string(1, g_playermodel[get_msg_arg_int(12)])
6124}
6125
6126// Prevent zombies from seeing any weapon pickup icon
6127public message_weappickup(msg_id, msg_dest, msg_entity)
6128{
6129 if (g_zombie[msg_entity])
6130 return PLUGIN_HANDLED;
6131
6132 return PLUGIN_CONTINUE;
6133}
6134
6135// Prevent zombies from seeing any ammo pickup icon
6136public message_ammopickup(msg_id, msg_dest, msg_entity)
6137{
6138 if (g_zombie[msg_entity])
6139 return PLUGIN_HANDLED;
6140
6141 return PLUGIN_CONTINUE;
6142}
6143
6144// Block hostage HUD display
6145public message_scenario()
6146{
6147 if (get_msg_args() > 1)
6148 {
6149 static sprite[8]
6150 get_msg_arg_string(2, sprite, charsmax(sprite))
6151
6152 if (equal(sprite, "hostage"))
6153 return PLUGIN_HANDLED;
6154 }
6155
6156 return PLUGIN_CONTINUE;
6157}
6158
6159// Block hostages from appearing on radar
6160public message_hostagepos()
6161{
6162 return PLUGIN_HANDLED;
6163}
6164
6165// Block some text messages
6166public message_textmsg()
6167{
6168 static textmsg[22]
6169 get_msg_arg_string(2, textmsg, charsmax(textmsg))
6170
6171 // Game restarting, reset scores and call round end to balance the teams
6172 if (equal(textmsg, "#Game_will_restart_in"))
6173 {
6174 logevent_round_end()
6175 g_scorehumans = 0
6176 g_scorezombies = 0
6177 }
6178 // Game commencing, reset scores only (round end is automatically triggered)
6179 else if (equal(textmsg, "#Game_Commencing"))
6180 {
6181 g_gamecommencing = true
6182 g_scorehumans = 0
6183 g_scorezombies = 0
6184 }
6185 // Block round end related messages
6186 else if (equal(textmsg, "#Hostages_Not_Rescued") || equal(textmsg, "#Round_Draw") || equal(textmsg, "#Terrorists_Win") || equal(textmsg, "#CTs_Win"))
6187 {
6188 return PLUGIN_HANDLED;
6189 }
6190
6191 return PLUGIN_CONTINUE;
6192}
6193
6194// Block CS round win audio messages, since we're playing our own instead
6195public message_sendaudio()
6196{
6197 static audio[17]
6198 get_msg_arg_string(2, audio, charsmax(audio))
6199
6200 if(equal(audio[7], "terwin") || equal(audio[7], "ctwin") || equal(audio[7], "rounddraw"))
6201 return PLUGIN_HANDLED;
6202
6203 return PLUGIN_CONTINUE;
6204}
6205
6206// Send actual team scores (T = zombies // CT = humans)
6207public message_teamscore()
6208{
6209 static team[2]
6210 get_msg_arg_string(1, team, charsmax(team))
6211
6212 switch (team[0])
6213 {
6214 // CT
6215 case 'C': set_msg_arg_int(2, get_msg_argtype(2), g_scorehumans)
6216 // Terrorist
6217 case 'T': set_msg_arg_int(2, get_msg_argtype(2), g_scorezombies)
6218 }
6219}
6220
6221// Team Switch (or player joining a team for first time)
6222public message_teaminfo(msg_id, msg_dest)
6223{
6224 // Only hook global messages
6225 if (msg_dest != MSG_ALL && msg_dest != MSG_BROADCAST) return;
6226
6227 // Don't pick up our own TeamInfo messages for this player (bugfix)
6228 if (g_switchingteam) return;
6229
6230 // Get player's id
6231 static id
6232 id = get_msg_arg_int(1)
6233
6234 // Invalid player id? (bugfix)
6235 if (!(1 <= id <= g_maxplayers)) return;
6236
6237 // Enable spectators' nightvision if not spawning right away
6238 set_task(0.2, "spec_nvision", id)
6239
6240 // Round didn't start yet, nothing to worry about
6241 if (g_newround) return;
6242
6243 // Get his new team
6244 static team[2]
6245 get_msg_arg_string(2, team, charsmax(team))
6246
6247 // Perform some checks to see if they should join a different team instead
6248 switch (team[0])
6249 {
6250 case 'C': // CT
6251 {
6252 if ((g_survround && fnGetHumans()) || (g_sniround && fnGetHumans())) // survivor/sniper alive --> switch to T and spawn as zombie
6253 {
6254 g_respawn_as_zombie[id] = true;
6255 remove_task(id+TASK_TEAM)
6256 fm_cs_set_user_team(id, FM_CS_TEAM_T)
6257 set_msg_arg_string(2, "TERRORIST")
6258 }
6259 else if (!fnGetZombies()) // no zombies alive --> switch to T and spawn as zombie
6260 {
6261 g_respawn_as_zombie[id] = true;
6262 remove_task(id+TASK_TEAM)
6263 fm_cs_set_user_team(id, FM_CS_TEAM_T)
6264 set_msg_arg_string(2, "TERRORIST")
6265 }
6266 }
6267 case 'T': // Terrorist
6268 {
6269 if ((g_swarmround || g_survround || g_sniround) && fnGetHumans()) // survivor alive or swarm round w/ humans --> spawn as zombie
6270 {
6271 g_respawn_as_zombie[id] = true;
6272 }
6273 else if (fnGetZombies()) // zombies alive --> switch to CT
6274 {
6275 remove_task(id+TASK_TEAM)
6276 fm_cs_set_user_team(id, FM_CS_TEAM_CT)
6277 set_msg_arg_string(2, "CT")
6278 }
6279 }
6280 }
6281}
6282
6283/*================================================================================
6284 [Main Functions]
6285=================================================================================*/
6286
6287// Make Zombie Task
6288public make_zombie_task()
6289{
6290 // Call make a zombie with no specific mode
6291 make_a_zombie(MODE_NONE, 0)
6292}
6293
6294// Make a Zombie Function
6295make_a_zombie(mode, id)
6296{
6297 // Get alive players count
6298 static iPlayersnum
6299 iPlayersnum = fnGetAlive()
6300
6301 // Not enough players, come back later!
6302 if (iPlayersnum < 1)
6303 {
6304 set_task(2.0, "make_zombie_task", TASK_MAKEZOMBIE)
6305 return;
6306 }
6307
6308 // Round started!
6309 g_newround = false
6310
6311 // Set up some common vars
6312 static forward_id, sound[64], iZombies, iMaxZombies
6313
6314 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)
6315 {
6316 // Survivor Mode
6317 g_survround = true
6318 g_lastmode = MODE_SURVIVOR
6319
6320 // Choose player randomly?
6321 if (mode == MODE_NONE)
6322 id = fnGetRandomAlive(random_num(1, iPlayersnum))
6323
6324 // Remember id for calling our forward later
6325 forward_id = id
6326
6327 // Turn player into a survivor
6328 humanme(id, 1, 0, 0)
6329
6330 // Turn the remaining players into zombies
6331 for (id = 1; id <= g_maxplayers; id++)
6332 {
6333 // Not alive
6334 if (!g_isalive[id])
6335 continue;
6336
6337 // Survivor or already a zombie
6338 if (g_survivor[id] || g_zombie[id])
6339 continue;
6340
6341 // Turn into a zombie
6342 zombieme(id, 0, 0, 0, 1, 0)
6343 }
6344
6345 // Play survivor sound
6346 ArrayGetString(sound_survivor, random_num(0, ArraySize(sound_survivor) - 1), sound, charsmax(sound))
6347 PlaySound(sound);
6348
6349 // Show Survivor HUD notice
6350 set_hudmessage(20, 20, 255, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
6351 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_SURVIVOR", g_playername[forward_id])
6352
6353 // Mode fully started!
6354 g_modestarted = true
6355
6356 // Round start forward
6357 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_SURVIVOR, forward_id);
6358 }
6359 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)
6360 {
6361 // Sniper Mode
6362 g_sniround = true
6363 g_lastmode = MODE_SNIPER
6364
6365 // Choose player randomly?
6366 if (mode == MODE_NONE)
6367 id = fnGetRandomAlive(random_num(1, iPlayersnum))
6368
6369 // Remember id for calling our forward later
6370 forward_id = id
6371
6372 // Turn player into a sniper
6373 humanme(id, 0, 1, 0)
6374
6375 // Turn the remaining players into zombies
6376 for (id = 1; id <= g_maxplayers; id++)
6377 {
6378 // Not alive
6379 if (!g_isalive[id])
6380 continue;
6381
6382 // Sniper or already a zombie
6383 if (g_sniper[id] || g_zombie[id])
6384 continue;
6385
6386 // Turn into a zombie
6387 zombieme(id, 0, 0, 0, 1, 0)
6388 }
6389
6390 // Play sniper sound
6391 ArrayGetString(sound_sniper, random_num(0, ArraySize(sound_sniper) - 1), sound, charsmax(sound))
6392 PlaySound(sound);
6393
6394 // Show Sniper HUD notice
6395 set_hudmessage(20, 20, 255, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
6396 ShowSyncHudMsg(0, g_MsgSync, "%s is Sniper !!!", g_playername[forward_id])
6397
6398 // Mode fully started!
6399 g_modestarted = true
6400
6401 // Round start forward
6402 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_SNIPER, forward_id);
6403 }
6404 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)
6405 {
6406 // Swarm Mode
6407 g_swarmround = true
6408 g_lastmode = MODE_SWARM
6409
6410 // Make sure there are alive players on both teams (BUGFIX)
6411 if (!fnGetAliveTs())
6412 {
6413 // Move random player to T team
6414 id = fnGetRandomAlive(random_num(1, iPlayersnum))
6415 remove_task(id+TASK_TEAM)
6416 fm_cs_set_user_team(id, FM_CS_TEAM_T)
6417 fm_user_team_update(id)
6418 }
6419 else if (!fnGetAliveCTs())
6420 {
6421 // Move random player to CT team
6422 id = fnGetRandomAlive(random_num(1, iPlayersnum))
6423 remove_task(id+TASK_TEAM)
6424 fm_cs_set_user_team(id, FM_CS_TEAM_CT)
6425 fm_user_team_update(id)
6426 }
6427
6428 // Turn every T into a zombie
6429 for (id = 1; id <= g_maxplayers; id++)
6430 {
6431 // Not alive
6432 if (!g_isalive[id])
6433 continue;
6434
6435 // Not a Terrorist
6436 if (fm_cs_get_user_team(id) != FM_CS_TEAM_T)
6437 continue;
6438
6439 // Turn into a zombie
6440 zombieme(id, 0, 0, 0, 1, 0)
6441 }
6442
6443 // Play swarm sound
6444 ArrayGetString(sound_swarm, random_num(0, ArraySize(sound_swarm) - 1), sound, charsmax(sound))
6445 PlaySound(sound);
6446
6447 // Show Swarm HUD notice
6448 set_hudmessage(20, 255, 20, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
6449 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_SWARM")
6450
6451 // Mode fully started!
6452 g_modestarted = true
6453
6454 // Round start forward
6455 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_SWARM, 0);
6456 }
6457 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)
6458 {
6459 // Multi Infection Mode
6460 g_lastmode = MODE_MULTI
6461
6462 // iMaxZombies is rounded up, in case there aren't enough players
6463 iMaxZombies = floatround(iPlayersnum*get_pcvar_float(cvar_multiratio), floatround_ceil)
6464 iZombies = 0
6465
6466 // Randomly turn iMaxZombies players into zombies
6467 while (iZombies < iMaxZombies)
6468 {
6469 // Keep looping through all players
6470 if (++id > g_maxplayers) id = 1
6471
6472 // Dead or already a zombie
6473 if (!g_isalive[id] || g_zombie[id])
6474 continue;
6475
6476 // Random chance
6477 if (random_num(0, 1))
6478 {
6479 // Turn into a zombie
6480 zombieme(id, 0, 0, 0, 1, 0)
6481 iZombies++
6482 }
6483 }
6484
6485 // Turn the remaining players into humans
6486 for (id = 1; id <= g_maxplayers; id++)
6487 {
6488 // Only those of them who aren't zombies
6489 if (!g_isalive[id] || g_zombie[id])
6490 continue;
6491
6492 // Switch to CT
6493 if (fm_cs_get_user_team(id) != FM_CS_TEAM_CT) // need to change team?
6494 {
6495 remove_task(id+TASK_TEAM)
6496 fm_cs_set_user_team(id, FM_CS_TEAM_CT)
6497 fm_user_team_update(id)
6498 }
6499 }
6500
6501 // Play multi infection sound
6502 ArrayGetString(sound_multi, random_num(0, ArraySize(sound_multi) - 1), sound, charsmax(sound))
6503 PlaySound(sound);
6504
6505 // Show Multi Infection HUD notice
6506 set_hudmessage(200, 50, 0, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
6507 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_MULTI")
6508
6509 // Mode fully started!
6510 g_modestarted = true
6511
6512 // Round start forward
6513 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_MULTI, 0);
6514 }
6515 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
6516 && 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)
6517 {
6518 // Plague Mode
6519 g_plagueround = true
6520 g_lastmode = MODE_PLAGUE
6521
6522 // Turn specified amount of players into Survivors
6523 static iSurvivors, iMaxSurvivors
6524 iMaxSurvivors = get_pcvar_num(cvar_plaguesurvnum)
6525 iSurvivors = 0
6526
6527 while (iSurvivors < iMaxSurvivors)
6528 {
6529 // Choose random guy
6530 id = fnGetRandomAlive(random_num(1, iPlayersnum))
6531
6532 // Already a survivor?
6533 if (g_survivor[id])
6534 continue;
6535
6536 // If not, turn him into one
6537 humanme(id, 1, 0, 0)
6538 iSurvivors++
6539
6540 // Apply survivor health multiplier
6541 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_plaguesurvhpmulti)))
6542 }
6543
6544 // Turn specified amount of players into Nemesis
6545 static iNemesis, iMaxNemesis
6546 iMaxNemesis = get_pcvar_num(cvar_plaguenemnum)
6547 iNemesis = 0
6548
6549 while (iNemesis < iMaxNemesis)
6550 {
6551 // Choose random guy
6552 id = fnGetRandomAlive(random_num(1, iPlayersnum))
6553
6554 // Already a survivor or nemesis?
6555 if (g_survivor[id] || g_nemesis[id])
6556 continue;
6557
6558 // If not, turn him into one
6559 zombieme(id, 0, 1, 0, 0, 0)
6560 iNemesis++
6561
6562 // Apply nemesis health multiplier
6563 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_plaguenemhpmulti)))
6564 }
6565
6566 // iMaxZombies is rounded up, in case there aren't enough players
6567 iMaxZombies = floatround((iPlayersnum-(get_pcvar_num(cvar_plaguenemnum)+get_pcvar_num(cvar_plaguesurvnum)))*get_pcvar_float(cvar_plagueratio), floatround_ceil)
6568 iZombies = 0
6569
6570 // Randomly turn iMaxZombies players into zombies
6571 while (iZombies < iMaxZombies)
6572 {
6573 // Keep looping through all players
6574 if (++id > g_maxplayers) id = 1
6575
6576 // Dead or already a zombie or survivor
6577 if (!g_isalive[id] || g_zombie[id] || g_survivor[id])
6578 continue;
6579
6580 // Random chance
6581 if (random_num(0, 1))
6582 {
6583 // Turn into a zombie
6584 zombieme(id, 0, 0, 0, 1, 0)
6585 iZombies++
6586 }
6587 }
6588
6589 // Turn the remaining players into humans
6590 for (id = 1; id <= g_maxplayers; id++)
6591 {
6592 // Only those of them who arent zombies or survivor
6593 if (!g_isalive[id] || g_zombie[id] || g_survivor[id])
6594 continue;
6595
6596 // Switch to CT
6597 if (fm_cs_get_user_team(id) != FM_CS_TEAM_CT) // need to change team?
6598 {
6599 remove_task(id+TASK_TEAM)
6600 fm_cs_set_user_team(id, FM_CS_TEAM_CT)
6601 fm_user_team_update(id)
6602 }
6603 }
6604
6605 // Play plague sound
6606 ArrayGetString(sound_plague, random_num(0, ArraySize(sound_plague) - 1), sound, charsmax(sound))
6607 PlaySound(sound);
6608
6609 // Show Plague HUD notice
6610 set_hudmessage(0, 50, 200, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
6611 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_PLAGUE")
6612
6613 // Mode fully started!
6614 g_modestarted = true
6615
6616 // Round start forward
6617 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_PLAGUE, 0);
6618 }
6619 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)
6620 {
6621 // Armageddon Mode
6622 g_armageround = true
6623 g_lastmode = MODE_ARMAGEDDON
6624
6625 // iMaxZombies is rounded up, in case there aren't enough players
6626 iMaxZombies = floatround((iPlayersnum * get_pcvar_float(cvar_armageratio)), floatround_ceil)
6627 iZombies = 0
6628
6629 // Randomly turn iMaxZombies players into Nemesis
6630 while (iZombies < iMaxZombies)
6631 {
6632 // Keep looping through all players
6633 if (++id > g_maxplayers) id = 1
6634
6635 // Dead or already a zombie or survivor
6636 if (!g_isalive[id] || g_zombie[id] || g_survivor[id])
6637 continue;
6638
6639 // Random chance
6640 if (random_num(0, 1))
6641 {
6642 // Turn into a Nemesis
6643 zombieme(id, 0, 1, 0, 0, 0)
6644 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_armagenemhpmulti)))
6645 iZombies++
6646 }
6647 }
6648
6649 // Turn the remaining players into survivors
6650 for (id = 1; id <= g_maxplayers; id++)
6651 {
6652 // Only those of them who arent zombies or survivor
6653 if (!g_isalive[id] || g_zombie[id]|| g_survivor[id])
6654 continue;
6655
6656 // Turn into a Survivor
6657 humanme(id, 1, 0, 0)
6658 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_armagesurvhpmulti)))
6659 }
6660
6661 // Play armageddon sound
6662 ArrayGetString(sound_armageddon, random_num(0, ArraySize(sound_armageddon) - 1), sound, charsmax(sound))
6663 PlaySound(sound);
6664
6665 // Show Armageddon HUD notice
6666 set_hudmessage(181, 62, 244, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
6667 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_ARMAGEDDON")
6668
6669 // Mode fully started!
6670 g_modestarted = true
6671
6672 // Round start forward
6673 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_ARMAGEDDON, 0);
6674 }
6675 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)
6676 {
6677 // Apocalypse Mode
6678 g_apocround = true
6679 g_lastmode = MODE_APOCALYPSE
6680
6681 // iMaxZombies is rounded up, in case there aren't enough players
6682 iMaxZombies = floatround((iPlayersnum * get_pcvar_float(cvar_apocratio)), floatround_ceil)
6683 iZombies = 0
6684
6685 // Randomly turn iMaxZombies players into Assassin
6686 while (iZombies < iMaxZombies)
6687 {
6688 // Keep looping through all players
6689 if (++id > g_maxplayers) id = 1
6690
6691 // Dead or already a zombie or sniper
6692 if (!g_isalive[id] || g_zombie[id] || g_sniper[id])
6693 continue;
6694
6695 // Random chance
6696 if (random_num(0, 1))
6697 {
6698 // Turn into a Assassin
6699 zombieme(id, 0, 0, 1, 0, 0)
6700 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_apocassahpmulti)))
6701 iZombies++
6702 }
6703 }
6704
6705 // Turn the remaining players into snipers
6706 for (id = 1; id <= g_maxplayers; id++)
6707 {
6708 // Only those of them who arent zombies or sniper
6709 if (!g_isalive[id] || g_zombie[id]|| g_sniper[id])
6710 continue;
6711
6712 // Turn into a Sniper
6713 humanme(id, 0, 1, 0)
6714 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_apocsniphpmulti)))
6715 }
6716
6717 // Play apocalypse sound
6718 ArrayGetString(sound_apocalypse, random_num(0, ArraySize(sound_apocalypse) - 1), sound, charsmax(sound))
6719 PlaySound(sound);
6720
6721 // Show Apocalypse HUD notice
6722 set_hudmessage(181, 62, 244, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
6723 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_APOCALYPSE")
6724
6725 // Mode fully started!
6726 g_modestarted = true
6727
6728 // Round start forward
6729 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_APOCALYPSE, 0);
6730 }
6731 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)
6732 {
6733 // Nightmare mode
6734 g_nightround = true
6735 g_lastmode = MODE_NIGHTMARE
6736
6737 iMaxZombies = floatround((iPlayersnum * 0.25), floatround_ceil)
6738 iZombies = 0
6739
6740 while (iZombies < iMaxZombies)
6741 {
6742 if ((++id) > g_maxplayers) id = 1
6743
6744 if (!g_isalive[id])
6745 continue;
6746
6747 if (random_num(1, 5) == 1)
6748 {
6749 zombieme(id, 0, 0, 1, 0, 0)
6750 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_nightassahpmulti)))
6751 iZombies++
6752 }
6753 }
6754
6755 iZombies = 0
6756
6757 while (iZombies < iMaxZombies)
6758 {
6759 if ((++id) > g_maxplayers) id = 1
6760
6761 if (!g_isalive[id] || g_assassin[id])
6762 continue;
6763
6764 if (random_num(1, 5) == 1)
6765 {
6766 zombieme(id, 0, 1, 0, 0, 0)
6767 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_nightnemhpmulti)))
6768 iZombies++
6769 }
6770 }
6771
6772 iZombies = 0
6773
6774 while (iZombies < iMaxZombies)
6775 {
6776 if ((++id) > g_maxplayers) id = 1
6777
6778 if (!g_isalive[id] || g_assassin[id] || g_nemesis[id])
6779 continue;
6780
6781 if (random_num(1, 5) == 1)
6782 {
6783 humanme(id, 1, 0, 0)
6784 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_nightsurvhpmulti)))
6785 iZombies++
6786 }
6787 }
6788
6789 for (id = 1; id <= g_maxplayers; id++)
6790 {
6791 if (!g_isalive[id] || g_assassin[id] || g_nemesis[id] || g_survivor[id])
6792 continue;
6793
6794 humanme(id, 0, 1, 0)
6795 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_nightsniphpmulti)))
6796 }
6797
6798 // Play nightmare sound
6799 ArrayGetString(sound_nightmare, random_num(0, ArraySize(sound_nightmare) - 1), sound, charsmax(sound))
6800 PlaySound(sound);
6801
6802 // Show Nightmare HUD notice
6803 set_hudmessage(181, 62, 244, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
6804 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_NIGHTMARE")
6805
6806 // Mode fully started!
6807 g_modestarted = true
6808
6809 // Round start forward
6810 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_NIGHTMARE, 0);
6811 }
6812 else
6813 {
6814 // Single Infection Mode or Nemesis Mode
6815
6816 // Choose player randomly?
6817 if (mode == MODE_NONE)
6818 id = fnGetRandomAlive(random_num(1, iPlayersnum))
6819
6820 // Remember id for calling our forward later
6821 forward_id = id
6822
6823 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)
6824 {
6825 // Nemesis Mode
6826 g_nemround = true
6827 g_lastmode = MODE_NEMESIS
6828
6829 // Turn player into nemesis
6830 zombieme(id, 0, 1, 0, 0, 0)
6831 }
6832 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)
6833 {
6834 // Assassin Mode
6835 g_assaround = true
6836 g_lastmode = MODE_ASSASSIN
6837
6838 // Turn player into assassin
6839 zombieme(id, 0, 0, 1, 0, 0)
6840 }
6841 else
6842 {
6843 // Single Infection Mode
6844 g_lastmode = MODE_INFECTION
6845
6846 // Turn player into the first zombie
6847 zombieme(id, 0, 0, 0, 0, 0)
6848 }
6849
6850 // Remaining players should be humans (CTs)
6851 for (id = 1; id <= g_maxplayers; id++)
6852 {
6853 // Not alive
6854 if (!g_isalive[id])
6855 continue;
6856
6857 // First zombie/nemesis
6858 if (g_zombie[id])
6859 continue;
6860
6861 // Switch to CT
6862 if (fm_cs_get_user_team(id) != FM_CS_TEAM_CT) // need to change team?
6863 {
6864 remove_task(id+TASK_TEAM)
6865 fm_cs_set_user_team(id, FM_CS_TEAM_CT)
6866 fm_user_team_update(id)
6867 }
6868 }
6869
6870 if (g_nemround)
6871 {
6872 // Play Nemesis sound
6873 ArrayGetString(sound_nemesis, random_num(0, ArraySize(sound_nemesis) - 1), sound, charsmax(sound))
6874 PlaySound(sound);
6875
6876 // Show Nemesis HUD notice
6877 set_hudmessage(255, 20, 20, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
6878 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_NEMESIS", g_playername[forward_id])
6879
6880 // Mode fully started!
6881 g_modestarted = true
6882
6883 // Round start forward
6884 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_NEMESIS, forward_id);
6885 }
6886 else if (g_assaround)
6887 {
6888 // Play Assassin sound
6889 ArrayGetString(sound_assassin, random_num(0, ArraySize(sound_assassin) - 1), sound, charsmax(sound))
6890 PlaySound(sound);
6891
6892 // Show Assassin HUD notice
6893 set_hudmessage(255, 255, 20, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0, -1)
6894 ShowSyncHudMsg(0, g_MsgSync, "%s is Assassin !!!", g_playername[forward_id])
6895
6896 // Mode fully started!
6897 g_modestarted = true
6898
6899 // Round start forward
6900 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_ASSASSIN, forward_id);
6901 }
6902 else
6903 {
6904 // Show First Zombie HUD notice
6905 set_hudmessage(255, 0, 0, HUD_EVENT_X, HUD_EVENT_Y, 0, 0.0, 5.0, 1.0, 1.0, -1)
6906 ShowSyncHudMsg(0, g_MsgSync, "%L",LANG_PLAYER, "NOTICE_FIRST", g_playername[forward_id])
6907
6908 // Mode fully started!
6909 g_modestarted = true
6910
6911 // Round start forward
6912 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_INFECTION, forward_id);
6913 }
6914 }
6915
6916 // Start ambience sounds after a mode begins
6917 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)
6918 || (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)))
6919 {
6920 remove_task(TASK_AMBIENCESOUNDS)
6921 set_task(2.0, "ambience_sound_effects", TASK_AMBIENCESOUNDS)
6922 }
6923}
6924
6925// Zombie Me Function (player id, infector, turn into a nemesis, silent mode, deathmsg and rewards)
6926zombieme(id, infector, nemesis, assassin, silentmode, rewards)
6927{
6928 // User infect attempt forward
6929 ExecuteForward(g_fwUserInfect_attempt, g_fwDummyResult, id, infector, nemesis)
6930
6931 // One or more plugins blocked the infection. Only allow this after making sure it's
6932 // not going to leave us with no zombies. Take into account a last player leaving case.
6933 // BUGFIX: only allow after a mode has started, to prevent blocking first zombie e.g.
6934 if (g_fwDummyResult >= ZP_PLUGIN_HANDLED && g_modestarted && fnGetZombies() > g_lastplayerleaving)
6935 return;
6936
6937 // Pre user infect forward
6938 ExecuteForward(g_fwUserInfected_pre, g_fwDummyResult, id, infector, nemesis)
6939
6940 // Show zombie class menu if they haven't chosen any (e.g. just connected)
6941 if (g_zombieclassnext[id] == ZCLASS_NONE && get_pcvar_num(cvar_zclasses))
6942 set_task(0.2, "show_menu_zclass", id)
6943
6944 // Set selected zombie class
6945 g_zombieclass[id] = g_zombieclassnext[id]
6946 // If no class selected yet, use the first (default) one
6947 if (g_zombieclass[id] == ZCLASS_NONE) g_zombieclass[id] = 0
6948
6949 // Way to go...
6950 g_zombie[id] = true
6951 g_nemesis[id] = false
6952 g_assassin[id] = false
6953 g_survivor[id] = false
6954 g_sniper[id] = false
6955 g_firstzombie[id] = false
6956
6957 // Remove survivor's aura (bugfix)
6958 set_pev(id, pev_effects, pev(id, pev_effects) &~ EF_BRIGHTLIGHT)
6959
6960 // Remove spawn protection (bugfix)
6961 g_nodamage[id] = false
6962 set_pev(id, pev_effects, pev(id, pev_effects) &~ EF_NODRAW)
6963
6964 // Reset burning duration counter (bugfix)
6965 g_burning_duration[id] = 0
6966
6967 // Show deathmsg and reward infector?
6968 if (rewards && infector)
6969 {
6970 // Send death notice and fix the "dead" attrib on scoreboard
6971 SendDeathMsg(infector, id)
6972 FixDeadAttrib(id)
6973
6974 // Reward frags, deaths, health, and ammo packs
6975 UpdateFrags(infector, id, get_pcvar_num(cvar_fragsinfect), 1, 1)
6976 g_ammopacks[infector] += get_pcvar_num(cvar_ammoinfect)
6977 fm_set_user_health(infector, pev(infector, pev_health) + get_pcvar_num(cvar_zombiebonushp))
6978 }
6979
6980 // Cache speed, knockback, and name for player's class
6981 g_zombie_spd[id] = float(ArrayGetCell(g_zclass_spd, g_zombieclass[id]))
6982 g_zombie_knockback[id] = Float:ArrayGetCell(g_zclass_kb, g_zombieclass[id])
6983 ArrayGetString(g_zclass_name, g_zombieclass[id], g_zombie_classname[id], charsmax(g_zombie_classname[]))
6984
6985 // Set zombie attributes based on the mode
6986 static sound[64]
6987 if (!silentmode)
6988 {
6989 if (nemesis)
6990 {
6991 // Nemesis
6992 g_nemesis[id] = true
6993
6994 // Set health [0 = auto]
6995 if (get_pcvar_num(cvar_nemhp) == 0)
6996 {
6997 if (get_pcvar_num(cvar_nembasehp) == 0)
6998 fm_set_user_health(id, ArrayGetCell(g_zclass_hp, 0) * fnGetAlive())
6999 else
7000 fm_set_user_health(id, get_pcvar_num(cvar_nembasehp) * fnGetAlive())
7001 }
7002 else
7003 fm_set_user_health(id, get_pcvar_num(cvar_nemhp))
7004
7005 // Set gravity, if frozen set the restore gravity value instead
7006 if (!g_frozen[id]) set_pev(id, pev_gravity, get_pcvar_float(cvar_nemgravity))
7007 else g_frozen_gravity[id] = get_pcvar_float(cvar_nemgravity)
7008
7009 // Set nemesis maxspeed
7010 ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
7011 }
7012 else if (assassin)
7013 {
7014 // Assassin
7015 g_assassin[id] = true
7016
7017 // Set health [0 = auto]
7018 if (get_pcvar_num(cvar_assahp) == 0)
7019 {
7020 if (get_pcvar_num(cvar_assabasehp) == 0)
7021 fm_set_user_health(id, ArrayGetCell(g_zclass_hp, 0) * fnGetAlive())
7022 else
7023 fm_set_user_health(id, get_pcvar_num(cvar_assabasehp) * fnGetAlive())
7024 }
7025 else
7026 fm_set_user_health(id, get_pcvar_num(cvar_assahp))
7027
7028 // Set gravity, if frozen set the restore gravity value instead
7029 if (!g_frozen[id]) set_pev(id, pev_gravity, get_pcvar_float(cvar_assagravity))
7030 else g_frozen_gravity[id] = get_pcvar_float(cvar_assagravity)
7031
7032 // Set assassin maxspeed
7033 ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
7034 }
7035 else if (fnGetZombies() == 1)
7036 {
7037 // First zombie
7038 g_firstzombie[id] = true
7039
7040 // Set health
7041 fm_set_user_health(id, floatround(float(ArrayGetCell(g_zclass_hp, g_zombieclass[id])) * get_pcvar_float(cvar_zombiefirsthp)))
7042
7043 // Set gravity, if frozen set the restore gravity value instead
7044 if (!g_frozen[id]) set_pev(id, pev_gravity, Float:ArrayGetCell(g_zclass_grav, g_zombieclass[id]))
7045 else g_frozen_gravity[id] = Float:ArrayGetCell(g_zclass_grav, g_zombieclass[id])
7046
7047 // Set zombie maxspeed
7048 ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
7049
7050 // Infection sound
7051 ArrayGetString(zombie_infect, random_num(0, ArraySize(zombie_infect) - 1), sound, charsmax(sound))
7052 emit_sound(id, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
7053 }
7054 else
7055 {
7056 // Infected by someone
7057
7058 // Set health
7059 fm_set_user_health(id, ArrayGetCell(g_zclass_hp, g_zombieclass[id]))
7060
7061 // Set gravity, if frozen set the restore gravity value instead
7062 if (!g_frozen[id]) set_pev(id, pev_gravity, Float:ArrayGetCell(g_zclass_grav, g_zombieclass[id]))
7063 else g_frozen_gravity[id] = Float:ArrayGetCell(g_zclass_grav, g_zombieclass[id])
7064
7065 // Set zombie maxspeed
7066 ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
7067
7068 // Infection sound
7069 ArrayGetString(zombie_infect, random_num(0, ArraySize(zombie_infect) - 1), sound, charsmax(sound))
7070 emit_sound(id, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
7071
7072 // Show Infection HUD notice
7073 set_hudmessage(255, 0, 0, HUD_INFECT_X, HUD_INFECT_Y, 0, 0.0, 5.0, 1.0, 1.0, -1)
7074
7075 if (infector) // infected by someone?
7076 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_INFECT2", g_playername[id], g_playername[infector])
7077 else
7078 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_INFECT", g_playername[id])
7079 }
7080 }
7081 else
7082 {
7083 // Silent mode, no HUD messages, no infection sounds
7084
7085 // Set health
7086 fm_set_user_health(id, ArrayGetCell(g_zclass_hp, g_zombieclass[id]))
7087
7088 // Set gravity, if frozen set the restore gravity value instead
7089 if (!g_frozen[id]) set_pev(id, pev_gravity, Float:ArrayGetCell(g_zclass_grav, g_zombieclass[id]))
7090 else g_frozen_gravity[id] = Float:ArrayGetCell(g_zclass_grav, g_zombieclass[id])
7091
7092 // Set zombie maxspeed
7093 ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
7094 }
7095
7096 // Remove previous tasks
7097 remove_task(id+TASK_MODEL)
7098 remove_task(id+TASK_BLOOD)
7099 remove_task(id+TASK_AURA)
7100 remove_task(id+TASK_BURN)
7101
7102 // Switch to T
7103 if (fm_cs_get_user_team(id) != FM_CS_TEAM_T) // need to change team?
7104 {
7105 remove_task(id+TASK_TEAM)
7106 fm_cs_set_user_team(id, FM_CS_TEAM_T)
7107 fm_user_team_update(id)
7108 }
7109
7110 // Custom models stuff
7111 static currentmodel[32], tempmodel[32], already_has_model, i, iRand, size
7112 already_has_model = false
7113
7114 if (g_handle_models_on_separate_ent)
7115 {
7116 // Set the right model
7117 if (g_nemesis[id])
7118 {
7119 iRand = random_num(0, ArraySize(model_nemesis) - 1)
7120 ArrayGetString(model_nemesis, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7121 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_nemesis, iRand))
7122 }
7123 else if (g_assassin[id])
7124 {
7125 iRand = random_num(0, ArraySize(model_assassin) - 1)
7126 ArrayGetString(model_assassin, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7127 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_assassin, iRand))
7128 }
7129 else
7130 {
7131 if (get_pcvar_num(cvar_adminmodelszombie) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
7132 {
7133 iRand = random_num(0, ArraySize(model_admin_zombie) - 1)
7134 ArrayGetString(model_admin_zombie, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7135 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_zombie, iRand))
7136 }
7137 else
7138 {
7139 iRand = random_num(ArrayGetCell(g_zclass_modelsstart, g_zombieclass[id]), ArrayGetCell(g_zclass_modelsend, g_zombieclass[id]) - 1)
7140 ArrayGetString(g_zclass_playermodel, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7141 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_zclass_modelindex, iRand))
7142 }
7143 }
7144
7145 // Set model on player model entity
7146 fm_set_playermodel_ent(id)
7147
7148 // Nemesis glow / remove glow on player model entity, unless frozen
7149 if (!g_frozen[id])
7150 {
7151 if (g_nemesis[id] && get_pcvar_num(cvar_nemglow))
7152 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 250, 0 , 0, kRenderNormal, 25)
7153 else if (g_nemesis[id] && !(get_pcvar_num(cvar_nemglow)))
7154 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 0, 0 , 0, kRenderNormal, 25)
7155 else if (g_assassin[id] && get_pcvar_num(cvar_assaglow))
7156 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 255, 255, 0, kRenderNormal, 25)
7157 else
7158 fm_set_rendering(g_ent_playermodel[id])
7159 }
7160 }
7161 else
7162 {
7163 // Get current model for comparing it with the current one
7164 fm_cs_get_user_model(id, currentmodel, charsmax(currentmodel))
7165
7166 // Set the right model, after checking that we don't already have it
7167 if (g_nemesis[id])
7168 {
7169 size = ArraySize(model_nemesis)
7170 for (i = 0; i < size; i++)
7171 {
7172 ArrayGetString(model_nemesis, i, tempmodel, charsmax(tempmodel))
7173 if (equal(currentmodel, tempmodel)) already_has_model = true
7174 }
7175
7176 if (!already_has_model)
7177 {
7178 iRand = random_num(0, size - 1)
7179 ArrayGetString(model_nemesis, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7180 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_nemesis, iRand))
7181 }
7182 }
7183 else if (g_assassin[id])
7184 {
7185 size = ArraySize(model_assassin)
7186 for (i = 0; i < size; i++)
7187 {
7188 ArrayGetString(model_assassin, i, tempmodel, charsmax(tempmodel))
7189 if (equal(currentmodel, tempmodel)) already_has_model = true
7190 }
7191
7192 if (!already_has_model)
7193 {
7194 iRand = random_num(0, size - 1)
7195 ArrayGetString(model_assassin, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7196 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_assassin, iRand))
7197 }
7198 }
7199 else
7200 {
7201 if (get_pcvar_num(cvar_adminmodelszombie) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
7202 {
7203 size = ArraySize(model_admin_zombie)
7204 for (i = 0; i < size; i++)
7205 {
7206 ArrayGetString(model_admin_zombie, 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(0, size - 1)
7213 ArrayGetString(model_admin_zombie, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7214 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_zombie, iRand))
7215 }
7216 }
7217 else
7218 {
7219 for (i = ArrayGetCell(g_zclass_modelsstart, g_zombieclass[id]); i < ArrayGetCell(g_zclass_modelsend, g_zombieclass[id]); i++)
7220 {
7221 ArrayGetString(g_zclass_playermodel, i, tempmodel, charsmax(tempmodel))
7222 if (equal(currentmodel, tempmodel)) already_has_model = true
7223 }
7224
7225 if (!already_has_model)
7226 {
7227 iRand = random_num(ArrayGetCell(g_zclass_modelsstart, g_zombieclass[id]), ArrayGetCell(g_zclass_modelsend, g_zombieclass[id]) - 1)
7228 ArrayGetString(g_zclass_playermodel, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7229 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_zclass_modelindex, iRand))
7230 }
7231 }
7232 }
7233
7234 // Need to change the model?
7235 if (!already_has_model)
7236 {
7237 // An additional delay is offset at round start
7238 // since SVC_BAD is more likely to be triggered there
7239 if (g_newround)
7240 set_task(5.0 * g_modelchange_delay, "fm_user_model_update", id+TASK_MODEL)
7241 else
7242 fm_user_model_update(id+TASK_MODEL)
7243 }
7244
7245 // Nemesis glow / remove glow, unless frozen
7246 if (!g_frozen[id])
7247 {
7248 if (g_nemesis[id] && get_pcvar_num(cvar_nemglow))
7249 fm_set_rendering(id, kRenderFxGlowShell, 250, 0, 0, kRenderNormal, 25)
7250 else if (g_nemesis[id] && !(get_pcvar_num(cvar_nemglow)))
7251 fm_set_rendering(id, kRenderFxGlowShell, 0, 0, 0, kRenderNormal, 25)
7252 if (g_assassin[id] && get_pcvar_num(cvar_assaglow))
7253 fm_set_rendering(id, kRenderFxGlowShell, 255, 255, 0, kRenderNormal, 25)
7254
7255 else if (!g_assassin[id] && !g_nemesis[id])
7256 fm_set_rendering(id)
7257 }
7258 }
7259
7260 // Remove any zoom (bugfix)
7261 cs_set_user_zoom(id, CS_RESET_ZOOM, 1)
7262
7263 // Remove armor
7264 cs_set_user_armor(id, 0, CS_ARMOR_NONE)
7265
7266 // Drop weapons when infected
7267 drop_weapons(id, 1)
7268 drop_weapons(id, 2)
7269
7270 // Strip zombies from guns and give them a knife
7271 fm_strip_user_weapons(id)
7272 fm_give_item(id, "weapon_knife")
7273
7274 // Fancy effects
7275 infection_effects(id)
7276
7277 // Nemesis aura task
7278 if (g_nemesis[id] && get_pcvar_num(cvar_nemaura))
7279 set_task(0.1, "zombie_aura", id+TASK_AURA, _, _, "b")
7280
7281 // Assassin aura task
7282 if (g_assassin[id] && get_pcvar_num(cvar_assaaura))
7283 set_task(0.1, "zombie_aura", id+TASK_AURA, _, _, "b")
7284
7285 // Remove CS nightvision if player owns one (bugfix)
7286 if (cs_get_user_nvg(id))
7287 {
7288 cs_set_user_nvg(id, 0)
7289 if (get_pcvar_num(cvar_customnvg)) remove_task(id+TASK_NVISION)
7290 else if (g_nvisionenabled[id]) set_user_gnvision(id, 0)
7291 }
7292
7293 // Give Zombies Night Vision?
7294 if (get_pcvar_num(cvar_nvggive))
7295 {
7296 g_nvision[id] = true
7297
7298 if (!g_isbot[id])
7299 {
7300 // Turn on Night Vision automatically?
7301 if (get_pcvar_num(cvar_nvggive) == 1)
7302 {
7303 g_nvisionenabled[id] = true
7304
7305 // Custom nvg?
7306 if (get_pcvar_num(cvar_customnvg))
7307 {
7308 remove_task(id+TASK_NVISION)
7309 set_task(0.1, "set_user_nvision", id+TASK_NVISION, _, _, "b")
7310 }
7311 else
7312 set_user_gnvision(id, 1)
7313 }
7314 // Turn off nightvision when infected (bugfix)
7315 else if (g_nvisionenabled[id])
7316 {
7317 if (get_pcvar_num(cvar_customnvg)) remove_task(id+TASK_NVISION)
7318 else set_user_gnvision(id, 0)
7319 g_nvisionenabled[id] = false
7320 }
7321 }
7322 else
7323 cs_set_user_nvg(id, 1); // turn on NVG for bots
7324 }
7325 // Disable nightvision when infected (bugfix)
7326 else if (g_nvision[id])
7327 {
7328 if (get_pcvar_num(cvar_customnvg)) remove_task(id+TASK_NVISION)
7329 else if (g_nvisionenabled[id]) set_user_gnvision(id, 0)
7330 g_nvision[id] = false
7331 g_nvisionenabled[id] = false
7332 }
7333
7334 // Set custom FOV?
7335 if (get_pcvar_num(cvar_zombiefov) != 90 && get_pcvar_num(cvar_zombiefov) != 0)
7336 {
7337 message_begin(MSG_ONE, g_msgSetFOV, _, id)
7338 write_byte(get_pcvar_num(cvar_zombiefov)) // fov angle
7339 message_end()
7340 }
7341
7342 // Call the bloody task
7343 if (!g_nemesis[id] && !g_nemesis[id] && get_pcvar_num(cvar_zombiebleeding))
7344 set_task(0.7, "make_blood", id+TASK_BLOOD, _, _, "b")
7345
7346 // Idle sounds task
7347 if (!g_nemesis[id] && !g_assassin[id])
7348 set_task(random_float(50.0, 70.0), "zombie_play_idle", id+TASK_BLOOD, _, _, "b")
7349
7350 // Turn off zombie's flashlight
7351 turn_off_flashlight(id)
7352
7353 // Post user infect forward
7354 ExecuteForward(g_fwUserInfected_post, g_fwDummyResult, id, infector, nemesis)
7355
7356 // Last Zombie Check
7357 fnCheckLastZombie()
7358}
7359
7360// Function Human Me (player id, turn into a survivor, silent mode)
7361humanme(id, survivor, sniper, silentmode)
7362{
7363 // User humanize attempt forward
7364 ExecuteForward(g_fwUserHumanize_attempt, g_fwDummyResult, id, survivor)
7365
7366 // One or more plugins blocked the "humanization". Only allow this after making sure it's
7367 // not going to leave us with no humans. Take into account a last player leaving case.
7368 // BUGFIX: only allow after a mode has started, to prevent blocking first survivor e.g.
7369 if (g_fwDummyResult >= ZP_PLUGIN_HANDLED && g_modestarted && fnGetHumans() > g_lastplayerleaving)
7370 return;
7371
7372 // Pre user humanize forward
7373 ExecuteForward(g_fwUserHumanized_pre, g_fwDummyResult, id, survivor)
7374
7375 // Remove previous tasks
7376 remove_task(id+TASK_MODEL)
7377 remove_task(id+TASK_BLOOD)
7378 remove_task(id+TASK_AURA)
7379 remove_task(id+TASK_BURN)
7380 remove_task(id+TASK_NVISION)
7381
7382 // Reset some vars
7383 g_zombie[id] = false
7384 g_nemesis[id] = false
7385 g_assassin[id] = false
7386 g_survivor[id] = false
7387 g_sniper[id] = false
7388 g_firstzombie[id] = false
7389 g_canbuy[id] = true
7390 g_buytime[id] = get_gametime()
7391
7392 // Remove survivor's aura (bugfix)
7393 set_pev(id, pev_effects, pev(id, pev_effects) &~ EF_BRIGHTLIGHT)
7394
7395 // Remove spawn protection (bugfix)
7396 g_nodamage[id] = false
7397 set_pev(id, pev_effects, pev(id, pev_effects) &~ EF_NODRAW)
7398
7399 // Reset burning duration counter (bugfix)
7400 g_burning_duration[id] = 0
7401
7402 // Remove CS nightvision if player owns one (bugfix)
7403 if (cs_get_user_nvg(id))
7404 {
7405 cs_set_user_nvg(id, 0)
7406 if (get_pcvar_num(cvar_customnvg)) remove_task(id+TASK_NVISION)
7407 else if (g_nvisionenabled[id]) set_user_gnvision(id, 0)
7408 }
7409
7410 // Drop previous weapons
7411 drop_weapons(id, 1)
7412 drop_weapons(id, 2)
7413
7414 // Strip off from weapons
7415 fm_strip_user_weapons(id)
7416 fm_give_item(id, "weapon_knife")
7417
7418 // Set human attributes based on the mode
7419 if (survivor)
7420 {
7421 // Survivor
7422 g_survivor[id] = true
7423
7424 // Set Health [0 = auto]
7425 if (get_pcvar_num(cvar_survhp) == 0)
7426 {
7427 if (get_pcvar_num(cvar_survbasehp) == 0)
7428 fm_set_user_health(id, get_pcvar_num(cvar_humanhp) * fnGetAlive())
7429 else
7430 fm_set_user_health(id, get_pcvar_num(cvar_survbasehp) * fnGetAlive())
7431 }
7432 else
7433 fm_set_user_health(id, get_pcvar_num(cvar_survhp))
7434
7435 // Set gravity, if frozen set the restore gravity value instead
7436 if (!g_frozen[id]) set_pev(id, pev_gravity, get_pcvar_float(cvar_survgravity))
7437 else g_frozen_gravity[id] = get_pcvar_float(cvar_survgravity)
7438
7439 // Set survivor maxspeed
7440 ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
7441
7442 // Give survivor his own weapon
7443 fm_give_item(id, "weapon_xm1014")
7444 fm_give_item(id, "weapon_ak47")
7445 fm_give_item(id, "weapon_m4a1")
7446 ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[CSW_XM1014], AMMOTYPE[CSW_XM1014], MAXBPAMMO[CSW_XM1014])
7447 ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[CSW_AK47], AMMOTYPE[CSW_AK47], MAXBPAMMO[CSW_AK47])
7448 ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[CSW_M4A1], AMMOTYPE[CSW_M4A1], MAXBPAMMO[CSW_M4A1])
7449
7450 // Turn off his flashlight
7451 turn_off_flashlight(id)
7452
7453 // Give the survivor a bright light
7454 if (get_pcvar_num(cvar_survaura)) set_pev(id, pev_effects, pev(id, pev_effects) | EF_BRIGHTLIGHT)
7455
7456 // Survivor bots will also need nightvision to see in the dark
7457 if (g_isbot[id])
7458 {
7459 g_nvision[id] = true
7460 cs_set_user_nvg(id, 1)
7461 }
7462 }
7463 else if (sniper)
7464 {
7465 // Sniper
7466 g_sniper[id] = true
7467
7468 // Set Health [0 = auto]
7469 if (get_pcvar_num(cvar_snihp) == 0)
7470 {
7471 if (get_pcvar_num(cvar_snibasehp) == 0)
7472 fm_set_user_health(id, get_pcvar_num(cvar_humanhp) * fnGetAlive())
7473 else
7474 fm_set_user_health(id, get_pcvar_num(cvar_snibasehp) * fnGetAlive())
7475 }
7476 else
7477 fm_set_user_health(id, get_pcvar_num(cvar_snihp))
7478
7479 // Set gravity, unless frozen
7480 if (!g_frozen[id]) set_pev(id, pev_gravity, get_pcvar_float(cvar_snigravity))
7481
7482 // Give sniper his own weapon
7483 fm_give_item(id, "weapon_awp")
7484 ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[CSW_AWP], AMMOTYPE[CSW_AWP], MAXBPAMMO[CSW_AWP])
7485
7486 // Turn off his flashlight
7487 turn_off_flashlight(id)
7488
7489 // Give the sniper a bright light
7490 if (get_pcvar_num(cvar_sniaura)) set_pev(id, pev_effects, pev(id, pev_effects) | EF_BRIGHTLIGHT)
7491
7492 // Sniper bots will also need nightvision to see in the dark
7493 if (g_isbot[id])
7494 {
7495 g_nvision[id] = true
7496 cs_set_user_nvg(id, 1)
7497 }
7498 }
7499 else
7500 {
7501 // Human taking an antidote
7502
7503 // Set health
7504 fm_set_user_health(id, get_pcvar_num(cvar_humanhp))
7505
7506 // Set gravity, if frozen set the restore gravity value instead
7507 if (!g_frozen[id]) set_pev(id, pev_gravity, get_pcvar_float(cvar_humangravity))
7508 else g_frozen_gravity[id] = get_pcvar_float(cvar_humangravity)
7509
7510 // Set human maxspeed
7511 ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
7512
7513 // Show custom buy menu?
7514 if (get_pcvar_num(cvar_buycustom))
7515 set_task(0.2, "show_menu_buy1", id+TASK_SPAWN)
7516
7517 // Silent mode = no HUD messages, no antidote sound
7518 if (!silentmode)
7519 {
7520 // Antidote sound
7521 static sound[64]
7522 ArrayGetString(sound_antidote, random_num(0, ArraySize(sound_antidote) - 1), sound, charsmax(sound))
7523 emit_sound(id, CHAN_ITEM, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
7524
7525 // Show Antidote HUD notice
7526 set_hudmessage(0, 0, 255, HUD_INFECT_X, HUD_INFECT_Y, 0, 0.0, 5.0, 1.0, 1.0, -1)
7527 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_ANTIDOTE", g_playername[id])
7528 }
7529 }
7530
7531 remove_freeze(id);
7532
7533 // Switch to CT
7534 if (fm_cs_get_user_team(id) != FM_CS_TEAM_CT) // need to change team?
7535 {
7536 remove_task(id+TASK_TEAM)
7537 fm_cs_set_user_team(id, FM_CS_TEAM_CT)
7538 fm_user_team_update(id)
7539 }
7540
7541 // Custom models stuff
7542 static currentmodel[32], tempmodel[32], already_has_model, i, iRand, size
7543 already_has_model = false
7544
7545 if (g_handle_models_on_separate_ent)
7546 {
7547 // Set the right model
7548 if (g_survivor[id])
7549 {
7550 iRand = random_num(0, ArraySize(model_survivor) - 1)
7551 ArrayGetString(model_survivor, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7552 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_survivor, iRand))
7553 }
7554 else if (g_sniper[id])
7555 {
7556 iRand = random_num(0, ArraySize(model_sniper) - 1)
7557 ArrayGetString(model_sniper, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7558 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_sniper, iRand))
7559 }
7560 else
7561 {
7562 if (get_pcvar_num(cvar_adminmodelshuman) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
7563 {
7564 iRand = random_num(0, ArraySize(model_admin_human) - 1)
7565 ArrayGetString(model_admin_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7566 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_human, iRand))
7567 }
7568 else
7569 {
7570 iRand = random_num(0, ArraySize(model_human) - 1)
7571 ArrayGetString(model_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7572 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_human, iRand))
7573 }
7574 }
7575
7576 // Set model on player model entity
7577 fm_set_playermodel_ent(id)
7578
7579 // Set survivor glow / remove glow on player model entity, unless frozen
7580 if (!g_frozen[id])
7581 {
7582 if (g_survivor[id] && get_pcvar_num(cvar_survglow))
7583 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 0, 0, 255, kRenderNormal, 25)
7584 else if (g_sniper[id] && get_pcvar_num(cvar_sniglow))
7585 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 0, 255, 0, kRenderNormal, 25)
7586 else
7587 fm_set_rendering(g_ent_playermodel[id])
7588 }
7589 }
7590 else
7591 {
7592 // Get current model for comparing it with the current one
7593 fm_cs_get_user_model(id, currentmodel, charsmax(currentmodel))
7594
7595 // Set the right model, after checking that we don't already have it
7596 if (g_survivor[id])
7597 {
7598 size = ArraySize(model_survivor)
7599 for (i = 0; i < size; i++)
7600 {
7601 ArrayGetString(model_survivor, i, tempmodel, charsmax(tempmodel))
7602 if (equal(currentmodel, tempmodel)) already_has_model = true
7603 }
7604
7605 if (!already_has_model)
7606 {
7607 iRand = random_num(0, size - 1)
7608 ArrayGetString(model_survivor, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7609 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_survivor, iRand))
7610 }
7611 }
7612 else if (g_sniper[id])
7613 {
7614 size = ArraySize(model_sniper)
7615 for (i = 0; i < size; i++)
7616 {
7617 ArrayGetString(model_sniper, i, tempmodel, charsmax(tempmodel))
7618 if (equal(currentmodel, tempmodel)) already_has_model = true
7619 }
7620
7621 if (!already_has_model)
7622 {
7623 iRand = random_num(0, size - 1)
7624 ArrayGetString(model_sniper, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7625 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_sniper, iRand))
7626 }
7627 }
7628 else
7629 {
7630 if (get_pcvar_num(cvar_adminmodelshuman) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
7631 {
7632 size = ArraySize(model_admin_human)
7633 for (i = 0; i < size; i++)
7634 {
7635 ArrayGetString(model_admin_human, i, tempmodel, charsmax(tempmodel))
7636 if (equal(currentmodel, tempmodel)) already_has_model = true
7637 }
7638
7639 if (!already_has_model)
7640 {
7641 iRand = random_num(0, size - 1)
7642 ArrayGetString(model_admin_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7643 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_human, iRand))
7644 }
7645 }
7646 else
7647 {
7648 size = ArraySize(model_human)
7649 for (i = 0; i < size; i++)
7650 {
7651 ArrayGetString(model_human, i, tempmodel, charsmax(tempmodel))
7652 if (equal(currentmodel, tempmodel)) already_has_model = true
7653 }
7654
7655 if (!already_has_model)
7656 {
7657 iRand = random_num(0, size - 1)
7658 ArrayGetString(model_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7659 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_human, iRand))
7660 }
7661 }
7662 }
7663
7664 // Need to change the model?
7665 if (!already_has_model)
7666 {
7667 // An additional delay is offset at round start
7668 // since SVC_BAD is more likely to be triggered there
7669 if (g_newround)
7670 set_task(5.0 * g_modelchange_delay, "fm_user_model_update", id+TASK_MODEL)
7671 else
7672 fm_user_model_update(id+TASK_MODEL)
7673 }
7674
7675 // Set survivor glow / remove glow, unless frozen
7676 if (!g_frozen[id])
7677 {
7678 if (g_survivor[id] && get_pcvar_num(cvar_survglow))
7679 fm_set_rendering(id, kRenderFxGlowShell, 0, 0, 255, kRenderNormal, 25)
7680 else if (g_sniper[id] && get_pcvar_num(cvar_sniglow))
7681 fm_set_rendering(id, kRenderFxGlowShell, 0, 255, 0, kRenderNormal, 25)
7682 else
7683 fm_set_rendering(id)
7684 }
7685 }
7686
7687 // Restore FOV?
7688 if (get_pcvar_num(cvar_zombiefov) != 90 && get_pcvar_num(cvar_zombiefov) != 0)
7689 {
7690 message_begin(MSG_ONE, g_msgSetFOV, _, id)
7691 write_byte(90) // angle
7692 message_end()
7693 }
7694
7695 // Disable nightvision when turning into human/survivor (bugfix)
7696 if (g_nvision[id])
7697 {
7698 if (get_pcvar_num(cvar_customnvg)) remove_task(id+TASK_NVISION)
7699 else if (g_nvisionenabled[id]) set_user_gnvision(id, 0)
7700 g_nvision[id] = false
7701 g_nvisionenabled[id] = false
7702 }
7703
7704 // Post user humanize forward
7705 ExecuteForward(g_fwUserHumanized_post, g_fwDummyResult, id, survivor)
7706
7707 // Last Zombie Check
7708 fnCheckLastZombie()
7709}
7710
7711/*================================================================================
7712 [Other Functions and Tasks]
7713=================================================================================*/
7714
7715public cache_cvars()
7716{
7717 g_cached_zombiesilent = get_pcvar_num(cvar_zombiesilent)
7718 g_cached_customflash = get_pcvar_num(cvar_customflash)
7719 g_cached_leapzombies = get_pcvar_num(cvar_leapzombies)
7720 g_cached_leapzombiescooldown = get_pcvar_float(cvar_leapzombiescooldown)
7721 g_cached_leapnemesis = get_pcvar_num(cvar_leapnemesis)
7722 g_cached_leapnemesiscooldown = get_pcvar_float(cvar_leapnemesiscooldown)
7723 g_cached_leapassassin = get_pcvar_num(cvar_leapassassin)
7724 g_cached_leapassassincooldown = get_pcvar_float(cvar_leapassassincooldown)
7725 g_cached_leapsurvivor = get_pcvar_num(cvar_leapsurvivor)
7726 g_cached_leapsurvivorcooldown = get_pcvar_float(cvar_leapsurvivorcooldown)
7727 g_cached_leapsniper = get_pcvar_num(cvar_leapsniper)
7728 g_cached_leapsnipercooldown = get_pcvar_float(cvar_leapsnipercooldown)
7729 g_cached_buytime = get_pcvar_float(cvar_buyzonetime)
7730}
7731
7732load_customization_from_files()
7733{
7734 // Build customization file path
7735 new path[64]
7736 get_configsdir(path, charsmax(path))
7737 format(path, charsmax(path), "%s/%s", path, ZP_CUSTOMIZATION_FILE)
7738
7739 // File not present
7740 if (!file_exists(path))
7741 {
7742 new error[100]
7743 formatex(error, charsmax(error), "Cannot load customization file %s!", path)
7744 set_fail_state(error)
7745 return;
7746 }
7747
7748 // Set up some vars to hold parsing info
7749 new linedata[1024], key[64], value[960], section, teams
7750
7751 // Open customization file for reading
7752 new file = fopen(path, "rt")
7753
7754 while (file && !feof(file))
7755 {
7756 // Read one line at a time
7757 fgets(file, linedata, charsmax(linedata))
7758
7759 // Replace newlines with a null character to prevent headaches
7760 replace(linedata, charsmax(linedata), "^n", "")
7761
7762 // Blank line or comment
7763 if (!linedata[0] || linedata[0] == ';') continue;
7764
7765 // New section starting
7766 if (linedata[0] == '[')
7767 {
7768 section++
7769 continue;
7770 }
7771
7772 // Get key and value(s)
7773 strtok(linedata, key, charsmax(key), value, charsmax(value), '=')
7774
7775 // Trim spaces
7776 trim(key)
7777 trim(value)
7778
7779 switch (section)
7780 {
7781 case SECTION_ACCESS_FLAGS:
7782 {
7783 if (equal(key, "ENABLE/DISABLE MOD"))
7784 g_access_flag[ACCESS_ENABLE_MOD] = read_flags(value)
7785 else if (equal(key, "ADMIN MENU"))
7786 g_access_flag[ACCESS_ADMIN_MENU] = read_flags(value)
7787 else if (equal(key, "ADMIN MODES MENU"))
7788 g_access_flag[ACCESS_ADMIN_MODES_MENU] = read_flags(value)
7789 else if (equal(key, "START MODE INFECTION"))
7790 g_access_flag[ACCESS_MODE_INFECTION] = read_flags(value)
7791 else if (equal(key, "START MODE NEMESIS"))
7792 g_access_flag[ACCESS_MODE_NEMESIS] = read_flags(value)
7793 else if (equal(key, "START MODE ASSASSIN"))
7794 g_access_flag[ACCESS_MODE_ASSASSIN] = read_flags(value)
7795 else if (equal(key, "START MODE SURVIVOR"))
7796 g_access_flag[ACCESS_MODE_SURVIVOR] = read_flags(value)
7797 else if (equal(key, "START MODE SNIPER"))
7798 g_access_flag[ACCESS_MODE_SNIPER] = read_flags(value)
7799 else if (equal(key, "START MODE SWARM"))
7800 g_access_flag[ACCESS_MODE_SWARM] = read_flags(value)
7801 else if (equal(key, "START MODE MULTI"))
7802 g_access_flag[ACCESS_MODE_MULTI] = read_flags(value)
7803 else if (equal(key, "START MODE PLAGUE"))
7804 g_access_flag[ACCESS_MODE_PLAGUE] = read_flags(value)
7805 else if (equal(key, "START MODE ARMAGEDDON"))
7806 g_access_flag[ACCESS_MODE_ARMAGEDDON] = read_flags(value)
7807 else if (equal(key, "START MODE APOCALYPSE"))
7808 g_access_flag[ACCESS_MODE_APOCALYPSE] = read_flags(value)
7809 else if (equal(key, "START MODE NIGHTMARE"))
7810 g_access_flag[ACCESS_MODE_NIGHTMARE] = read_flags(value)
7811 else if (equal(key, "MAKE ZOMBIE"))
7812 g_access_flag[ACCESS_MAKE_ZOMBIE] = read_flags(value)
7813 else if (equal(key, "MAKE HUMAN"))
7814 g_access_flag[ACCESS_MAKE_HUMAN] = read_flags(value)
7815 else if (equal(key, "MAKE NEMESIS"))
7816 g_access_flag[ACCESS_MAKE_NEMESIS] = read_flags(value)
7817 else if (equal(key, "MAKE ASSASSIN"))
7818 g_access_flag[ACCESS_MAKE_ASSASSIN] = read_flags(value)
7819 else if (equal(key, "MAKE SURVIVOR"))
7820 g_access_flag[ACCESS_MAKE_SURVIVOR] = read_flags(value)
7821 else if (equal(key, "MAKE SNIPER"))
7822 g_access_flag[ACCESS_MAKE_SNIPER] = read_flags(value)
7823 else if (equal(key, "RESPAWN PLAYERS"))
7824 g_access_flag[ACCESS_RESPAWN_PLAYERS] = read_flags(value)
7825 else if (equal(key, "ADMIN MODELS"))
7826 g_access_flag[ACCESS_ADMIN_MODELS] = read_flags(value)
7827 }
7828 case SECTION_PLAYER_MODELS:
7829 {
7830 if (equal(key, "HUMAN"))
7831 {
7832 // Parse models
7833 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
7834 {
7835 // Trim spaces
7836 trim(key)
7837 trim(value)
7838
7839 // Add to models array
7840 ArrayPushString(model_human, key)
7841 }
7842 }
7843 else if (equal(key, "NEMESIS"))
7844 {
7845 // Parse models
7846 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
7847 {
7848 // Trim spaces
7849 trim(key)
7850 trim(value)
7851
7852 // Add to models array
7853 ArrayPushString(model_nemesis, key)
7854 }
7855 }
7856 else if (equal(key, "ASSASSIN"))
7857 {
7858 // Parse models
7859 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
7860 {
7861 // Trim spaces
7862 trim(key)
7863 trim(value)
7864
7865 // Add to models array
7866 ArrayPushString(model_assassin, key)
7867 }
7868 }
7869 else if (equal(key, "SURVIVOR"))
7870 {
7871 // Parse models
7872 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
7873 {
7874 // Trim spaces
7875 trim(key)
7876 trim(value)
7877
7878 // Add to models array
7879 ArrayPushString(model_survivor, key)
7880 }
7881 }
7882 else if (equal(key, "SNIPER"))
7883 {
7884 // Parse models
7885 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
7886 {
7887 // Trim spaces
7888 trim(key)
7889 trim(value)
7890
7891 // Add to models array
7892 ArrayPushString(model_sniper, key)
7893 }
7894 }
7895 else if (equal(key, "ADMIN ZOMBIE"))
7896 {
7897 // Parse models
7898 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
7899 {
7900 // Trim spaces
7901 trim(key)
7902 trim(value)
7903
7904 // Add to models array
7905 ArrayPushString(model_admin_zombie, key)
7906 }
7907 }
7908 else if (equal(key, "ADMIN HUMAN"))
7909 {
7910 // Parse models
7911 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
7912 {
7913 // Trim spaces
7914 trim(key)
7915 trim(value)
7916
7917 // Add to models array
7918 ArrayPushString(model_admin_human, key)
7919 }
7920 }
7921 else if (equal(key, "FORCE CONSISTENCY"))
7922 g_force_consistency = str_to_num(value)
7923 else if (equal(key, "SAME MODELS FOR ALL"))
7924 g_same_models_for_all = str_to_num(value)
7925 else if (g_same_models_for_all && equal(key, "ZOMBIE"))
7926 {
7927 // Parse models
7928 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
7929 {
7930 // Trim spaces
7931 trim(key)
7932 trim(value)
7933
7934 // Add to models array
7935 ArrayPushString(g_zclass_playermodel, key)
7936
7937 // Precache model and retrieve its modelindex
7938 formatex(linedata, charsmax(linedata), "models/player/%s/%s.mdl", key, key)
7939 ArrayPushCell(g_zclass_modelindex, engfunc(EngFunc_PrecacheModel, linedata))
7940 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, linedata)
7941 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, linedata)
7942 // Precache modelT.mdl files too
7943 copy(linedata[strlen(linedata)-4], charsmax(linedata) - (strlen(linedata)-4), "T.mdl")
7944 if (file_exists(linedata)) engfunc(EngFunc_PrecacheModel, linedata)
7945 }
7946 }
7947 }
7948 case SECTION_WEAPON_MODELS:
7949 {
7950 if (equal(key, "V_KNIFE HUMAN"))
7951 copy(model_vknife_human, charsmax(model_vknife_human), value)
7952 else if (equal(key, "V_KNIFE NEMESIS"))
7953 copy(model_vknife_nemesis, charsmax(model_vknife_nemesis), value)
7954 else if (equal(key, "V_KNIFE ASSASSIN"))
7955 copy(model_vknife_assassin, charsmax(model_vknife_assassin), value)
7956 else if (equal(key, "V_M249 SURVIVOR")) // backwards compatibility with old configs
7957 copy(model_vweapon_survivor, charsmax(model_vweapon_survivor), value)
7958 else if (equal(key, "V_WEAPON SURVIVOR"))
7959 copy(model_vweapon_survivor, charsmax(model_vweapon_survivor), value)
7960 else if (equal(key, "V_AWP SNIPER"))
7961 copy(model_vawp_sniper, charsmax(model_vawp_sniper), value)
7962 else if (equal(key, "P_AWP SNIPER"))
7963 copy(model_pawp_sniper, charsmax(model_pawp_sniper), value)
7964 else if (equal(key, "GRENADE INFECT"))
7965 copy(model_grenade_infect, charsmax(model_grenade_infect), value)
7966 else if (equal(key, "GRENADE FIRE"))
7967 copy(model_grenade_fire, charsmax(model_grenade_fire), value)
7968 else if (equal(key, "GRENADE FROST"))
7969 copy(model_grenade_frost, charsmax(model_grenade_frost), value)
7970 else if (equal(key, "GRENADE FLARE"))
7971 copy(model_grenade_flare, charsmax(model_grenade_flare), value)
7972 else if (equal(key, "V_KNIFE ADMIN HUMAN"))
7973 copy(model_vknife_admin_human, charsmax(model_vknife_admin_human), value)
7974 else if (equal(key, "V_KNIFE ADMIN ZOMBIE"))
7975 copy(model_vknife_admin_zombie, charsmax(model_vknife_admin_zombie), value)
7976 }
7977 case SECTION_GRENADE_SPRITES:
7978 {
7979 if (equal(key, "TRAIL"))
7980 copy(sprite_grenade_trail, charsmax(sprite_grenade_trail), value)
7981 else if (equal(key, "RING"))
7982 copy(sprite_grenade_ring, charsmax(sprite_grenade_ring), value)
7983 else if (equal(key, "FIRE"))
7984 copy(sprite_grenade_fire, charsmax(sprite_grenade_fire), value)
7985 else if (equal(key, "SMOKE"))
7986 copy(sprite_grenade_smoke, charsmax(sprite_grenade_smoke), value)
7987 else if (equal(key, "GLASS"))
7988 copy(sprite_grenade_glass, charsmax(sprite_grenade_glass), value)
7989 }
7990 case SECTION_SOUNDS:
7991 {
7992 if (equal(key, "WIN ZOMBIES"))
7993 {
7994 // Parse sounds
7995 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
7996 {
7997 // Trim spaces
7998 trim(key)
7999 trim(value)
8000
8001 // Add to sounds array
8002 ArrayPushString(sound_win_zombies, key)
8003 ArrayPushCell(sound_win_zombies_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8004 }
8005 }
8006 else if (equal(key, "WIN HUMANS"))
8007 {
8008 // Parse sounds
8009 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8010 {
8011 // Trim spaces
8012 trim(key)
8013 trim(value)
8014
8015 // Add to sounds array
8016 ArrayPushString(sound_win_humans, key)
8017 ArrayPushCell(sound_win_humans_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8018 }
8019 }
8020 else if (equal(key, "WIN NO ONE"))
8021 {
8022 // Parse sounds
8023 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8024 {
8025 // Trim spaces
8026 trim(key)
8027 trim(value)
8028
8029 // Add to sounds array
8030 ArrayPushString(sound_win_no_one, key)
8031 ArrayPushCell(sound_win_no_one_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8032 }
8033 }
8034 else if (equal(key, "ZOMBIE INFECT"))
8035 {
8036 // Parse sounds
8037 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8038 {
8039 // Trim spaces
8040 trim(key)
8041 trim(value)
8042
8043 // Add to sounds array
8044 ArrayPushString(zombie_infect, key)
8045 }
8046 }
8047 else if (equal(key, "ZOMBIE PAIN"))
8048 {
8049 // Parse sounds
8050 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8051 {
8052 // Trim spaces
8053 trim(key)
8054 trim(value)
8055
8056 // Add to sounds array
8057 ArrayPushString(zombie_pain, key)
8058 }
8059 }
8060 else if (equal(key, "NEMESIS PAIN"))
8061 {
8062 // Parse sounds
8063 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8064 {
8065 // Trim spaces
8066 trim(key)
8067 trim(value)
8068
8069 // Add to sounds array
8070 ArrayPushString(nemesis_pain, key)
8071 }
8072 }
8073 else if (equal(key, "ASSASSIN PAIN"))
8074 {
8075 // Parse sounds
8076 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8077 {
8078 // Trim spaces
8079 trim(key)
8080 trim(value)
8081
8082 // Add to sounds array
8083 ArrayPushString(assassin_pain, key)
8084 }
8085 }
8086 else if (equal(key, "ZOMBIE DIE"))
8087 {
8088 // Parse sounds
8089 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8090 {
8091 // Trim spaces
8092 trim(key)
8093 trim(value)
8094
8095 // Add to sounds array
8096 ArrayPushString(zombie_die, key)
8097 }
8098 }
8099 else if (equal(key, "ZOMBIE FALL"))
8100 {
8101 // Parse sounds
8102 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8103 {
8104 // Trim spaces
8105 trim(key)
8106 trim(value)
8107
8108 // Add to sounds array
8109 ArrayPushString(zombie_fall, key)
8110 }
8111 }
8112 else if (equal(key, "ZOMBIE MISS SLASH"))
8113 {
8114 // Parse sounds
8115 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8116 {
8117 // Trim spaces
8118 trim(key)
8119 trim(value)
8120
8121 // Add to sounds array
8122 ArrayPushString(zombie_miss_slash, key)
8123 }
8124 }
8125 else if (equal(key, "ZOMBIE MISS WALL"))
8126 {
8127 // Parse sounds
8128 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8129 {
8130 // Trim spaces
8131 trim(key)
8132 trim(value)
8133
8134 // Add to sounds array
8135 ArrayPushString(zombie_miss_wall, key)
8136 }
8137 }
8138 else if (equal(key, "ZOMBIE HIT NORMAL"))
8139 {
8140 // Parse sounds
8141 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8142 {
8143 // Trim spaces
8144 trim(key)
8145 trim(value)
8146
8147 // Add to sounds array
8148 ArrayPushString(zombie_hit_normal, key)
8149 }
8150 }
8151 else if (equal(key, "ZOMBIE HIT STAB"))
8152 {
8153 // Parse sounds
8154 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8155 {
8156 // Trim spaces
8157 trim(key)
8158 trim(value)
8159
8160 // Add to sounds array
8161 ArrayPushString(zombie_hit_stab, key)
8162 }
8163 }
8164 else if (equal(key, "ZOMBIE IDLE"))
8165 {
8166 // Parse sounds
8167 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8168 {
8169 // Trim spaces
8170 trim(key)
8171 trim(value)
8172
8173 // Add to sounds array
8174 ArrayPushString(zombie_idle, key)
8175 }
8176 }
8177 else if (equal(key, "ZOMBIE IDLE LAST"))
8178 {
8179 // Parse sounds
8180 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8181 {
8182 // Trim spaces
8183 trim(key)
8184 trim(value)
8185
8186 // Add to sounds array
8187 ArrayPushString(zombie_idle_last, key)
8188 }
8189 }
8190 else if (equal(key, "ZOMBIE MADNESS"))
8191 {
8192 // Parse sounds
8193 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8194 {
8195 // Trim spaces
8196 trim(key)
8197 trim(value)
8198
8199 // Add to sounds array
8200 ArrayPushString(zombie_madness, key)
8201 }
8202 }
8203 else if (equal(key, "ROUND NEMESIS"))
8204 {
8205 // Parse sounds
8206 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8207 {
8208 // Trim spaces
8209 trim(key)
8210 trim(value)
8211
8212 // Add to sounds array
8213 ArrayPushString(sound_nemesis, key)
8214 }
8215 }
8216 else if (equal(key, "ROUND ASSASSIN"))
8217 {
8218 // Parse sounds
8219 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8220 {
8221 // Trim spaces
8222 trim(key)
8223 trim(value)
8224
8225 // Add to sounds array
8226 ArrayPushString(sound_assassin, key)
8227 }
8228 }
8229 else if (equal(key, "ROUND SURVIVOR"))
8230 {
8231 // Parse sounds
8232 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8233 {
8234 // Trim spaces
8235 trim(key)
8236 trim(value)
8237
8238 // Add to sounds array
8239 ArrayPushString(sound_survivor, key)
8240 }
8241 }
8242 else if (equal(key, "ROUND SNIPER"))
8243 {
8244 // Parse sounds
8245 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8246 {
8247 // Trim spaces
8248 trim(key)
8249 trim(value)
8250
8251 // Add to sounds array
8252 ArrayPushString(sound_sniper, key)
8253 }
8254 }
8255 else if (equal(key, "ROUND SWARM"))
8256 {
8257 // Parse sounds
8258 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8259 {
8260 // Trim spaces
8261 trim(key)
8262 trim(value)
8263
8264 // Add to sounds array
8265 ArrayPushString(sound_swarm, key)
8266 }
8267 }
8268 else if (equal(key, "ROUND MULTI"))
8269 {
8270 // Parse sounds
8271 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8272 {
8273 // Trim spaces
8274 trim(key)
8275 trim(value)
8276
8277 // Add to sounds array
8278 ArrayPushString(sound_multi, key)
8279 }
8280 }
8281 else if (equal(key, "ROUND PLAGUE"))
8282 {
8283 // Parse sounds
8284 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8285 {
8286 // Trim spaces
8287 trim(key)
8288 trim(value)
8289
8290 // Add to sounds array
8291 ArrayPushString(sound_plague, key)
8292 }
8293 }
8294 else if (equal(key, "ROUND ARMAGEDDON"))
8295 {
8296 // Parse sounds
8297 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8298 {
8299 // Trim spaces
8300 trim(key)
8301 trim(value)
8302
8303 // Add to sounds array
8304 ArrayPushString(sound_armageddon, key)
8305 }
8306 }
8307 else if (equal(key, "ROUND APOCALYPSE"))
8308 {
8309 // Parse sounds
8310 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8311 {
8312 // Trim spaces
8313 trim(key)
8314 trim(value)
8315
8316 // Add to sounds array
8317 ArrayPushString(sound_apocalypse, key)
8318 }
8319 }
8320 else if (equal(key, "ROUND NIGHTMARE"))
8321 {
8322 // Parse sounds
8323 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8324 {
8325 // Trim spaces
8326 trim(key)
8327 trim(value)
8328
8329 // Add to sounds array
8330 ArrayPushString(sound_nightmare, key)
8331 }
8332 }
8333 else if (equal(key, "GRENADE INFECT EXPLODE"))
8334 {
8335 // Parse sounds
8336 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8337 {
8338 // Trim spaces
8339 trim(key)
8340 trim(value)
8341
8342 // Add to sounds array
8343 ArrayPushString(grenade_infect, key)
8344 }
8345 }
8346 else if (equal(key, "GRENADE INFECT PLAYER"))
8347 {
8348 // Parse sounds
8349 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8350 {
8351 // Trim spaces
8352 trim(key)
8353 trim(value)
8354
8355 // Add to sounds array
8356 ArrayPushString(grenade_infect_player, key)
8357 }
8358 }
8359 else if (equal(key, "GRENADE FIRE EXPLODE"))
8360 {
8361 // Parse sounds
8362 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8363 {
8364 // Trim spaces
8365 trim(key)
8366 trim(value)
8367
8368 // Add to sounds array
8369 ArrayPushString(grenade_fire, key)
8370 }
8371 }
8372 else if (equal(key, "GRENADE FIRE PLAYER"))
8373 {
8374 // Parse sounds
8375 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8376 {
8377 // Trim spaces
8378 trim(key)
8379 trim(value)
8380
8381 // Add to sounds array
8382 ArrayPushString(grenade_fire_player, key)
8383 }
8384 }
8385 else if (equal(key, "GRENADE FROST EXPLODE"))
8386 {
8387 // Parse sounds
8388 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8389 {
8390 // Trim spaces
8391 trim(key)
8392 trim(value)
8393
8394 // Add to sounds array
8395 ArrayPushString(grenade_frost, key)
8396 }
8397 }
8398 else if (equal(key, "GRENADE FROST PLAYER"))
8399 {
8400 // Parse sounds
8401 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8402 {
8403 // Trim spaces
8404 trim(key)
8405 trim(value)
8406
8407 // Add to sounds array
8408 ArrayPushString(grenade_frost_player, key)
8409 }
8410 }
8411 else if (equal(key, "GRENADE FROST BREAK"))
8412 {
8413 // Parse sounds
8414 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8415 {
8416 // Trim spaces
8417 trim(key)
8418 trim(value)
8419
8420 // Add to sounds array
8421 ArrayPushString(grenade_frost_break, key)
8422 }
8423 }
8424 else if (equal(key, "GRENADE FLARE"))
8425 {
8426 // Parse sounds
8427 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8428 {
8429 // Trim spaces
8430 trim(key)
8431 trim(value)
8432
8433 // Add to sounds array
8434 ArrayPushString(grenade_flare, key)
8435 }
8436 }
8437 else if (equal(key, "ANTIDOTE"))
8438 {
8439 // Parse sounds
8440 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8441 {
8442 // Trim spaces
8443 trim(key)
8444 trim(value)
8445
8446 // Add to sounds array
8447 ArrayPushString(sound_antidote, key)
8448 }
8449 }
8450 else if (equal(key, "THUNDER"))
8451 {
8452 // Parse sounds
8453 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8454 {
8455 // Trim spaces
8456 trim(key)
8457 trim(value)
8458
8459 // Add to sounds array
8460 ArrayPushString(sound_thunder, key)
8461 }
8462 }
8463 }
8464 case SECTION_AMBIENCE_SOUNDS:
8465 {
8466 if (equal(key, "INFECTION ENABLE"))
8467 g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION] = str_to_num(value)
8468 else if (g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION] && equal(key, "INFECTION SOUNDS"))
8469 {
8470 // Parse sounds
8471 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8472 {
8473 // Trim spaces
8474 trim(key)
8475 trim(value)
8476
8477 // Add to sounds array
8478 ArrayPushString(sound_ambience1, key)
8479 ArrayPushCell(sound_ambience1_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8480 }
8481 }
8482 else if (g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION] && equal(key, "INFECTION DURATIONS"))
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 ArrayPushCell(sound_ambience1_duration, str_to_num(key))
8493 }
8494 }
8495 else if (equal(key, "NEMESIS ENABLE"))
8496 g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS] = str_to_num(value)
8497 else if (g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS] && equal(key, "NEMESIS SOUNDS"))
8498 {
8499 // Parse sounds
8500 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8501 {
8502 // Trim spaces
8503 trim(key)
8504 trim(value)
8505
8506 // Add to sounds array
8507 ArrayPushString(sound_ambience2, key)
8508 ArrayPushCell(sound_ambience2_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8509 }
8510 }
8511 else if (g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS] && equal(key, "NEMESIS DURATIONS"))
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 ArrayPushCell(sound_ambience2_duration, str_to_num(key))
8522 }
8523 }
8524 else if (equal(key, "ASSASSIN ENABLE"))
8525 g_ambience_sounds[AMBIENCE_SOUNDS_ASSASSIN] = str_to_num(value)
8526 else if (g_ambience_sounds[AMBIENCE_SOUNDS_ASSASSIN] && equal(key, "ASSASSIN SOUNDS"))
8527 {
8528 // Parse sounds
8529 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8530 {
8531 // Trim spaces
8532 trim(key)
8533 trim(value)
8534
8535 // Add to sounds array
8536 ArrayPushString(sound_ambience6, key)
8537 ArrayPushCell(sound_ambience6_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8538 }
8539 }
8540 else if (g_ambience_sounds[AMBIENCE_SOUNDS_ASSASSIN] && equal(key, "ASSASSIN DURATIONS"))
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 ArrayPushCell(sound_ambience6_duration, str_to_num(key))
8551 }
8552 }
8553 else if (equal(key, "SURVIVOR ENABLE"))
8554 g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR] = str_to_num(value)
8555 else if (g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR] && equal(key, "SURVIVOR SOUNDS"))
8556 {
8557 // Parse sounds
8558 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8559 {
8560 // Trim spaces
8561 trim(key)
8562 trim(value)
8563
8564 // Add to sounds array
8565 ArrayPushString(sound_ambience3, key)
8566 ArrayPushCell(sound_ambience3_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8567 }
8568 }
8569 else if (g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR] && equal(key, "SURVIVOR DURATIONS"))
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 ArrayPushCell(sound_ambience3_duration, str_to_num(key))
8580 }
8581 }
8582 else if (equal(key, "SNIPER ENABLE"))
8583 g_ambience_sounds[AMBIENCE_SOUNDS_SNIPER] = str_to_num(value)
8584 else if (g_ambience_sounds[AMBIENCE_SOUNDS_SNIPER] && equal(key, "SNIPER SOUNDS"))
8585 {
8586 // Parse sounds
8587 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8588 {
8589 // Trim spaces
8590 trim(key)
8591 trim(value)
8592
8593 // Add to sounds array
8594 ArrayPushString(sound_ambience7, key)
8595 ArrayPushCell(sound_ambience7_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8596 }
8597 }
8598 else if (g_ambience_sounds[AMBIENCE_SOUNDS_SNIPER] && equal(key, "SNIPER DURATIONS"))
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 ArrayPushCell(sound_ambience7_duration, str_to_num(key))
8609 }
8610 }
8611 else if (equal(key, "SWARM ENABLE"))
8612 g_ambience_sounds[AMBIENCE_SOUNDS_SWARM] = str_to_num(value)
8613 else if (g_ambience_sounds[AMBIENCE_SOUNDS_SWARM] && equal(key, "SWARM SOUNDS"))
8614 {
8615 // Parse sounds
8616 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8617 {
8618 // Trim spaces
8619 trim(key)
8620 trim(value)
8621
8622 // Add to sounds array
8623 ArrayPushString(sound_ambience4, key)
8624 ArrayPushCell(sound_ambience4_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8625 }
8626 }
8627 else if (g_ambience_sounds[AMBIENCE_SOUNDS_SWARM] && equal(key, "SWARM DURATIONS"))
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 ArrayPushCell(sound_ambience4_duration, str_to_num(key))
8638 }
8639 }
8640 else if (equal(key, "PLAGUE ENABLE"))
8641 g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE] = str_to_num(value)
8642 else if (g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE] && equal(key, "PLAGUE SOUNDS"))
8643 {
8644 // Parse sounds
8645 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8646 {
8647 // Trim spaces
8648 trim(key)
8649 trim(value)
8650
8651 // Add to sounds array
8652 ArrayPushString(sound_ambience5, key)
8653 ArrayPushCell(sound_ambience5_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8654 }
8655 }
8656 else if (g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE] && equal(key, "PLAGUE DURATIONS"))
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 ArrayPushCell(sound_ambience5_duration, str_to_num(key))
8667 }
8668 }
8669 else if (equal(key, "ARMAGEDDON ENABLE"))
8670 g_ambience_sounds[AMBIENCE_SOUNDS_ARMAGEDDON] = str_to_num(value)
8671 else if (g_ambience_sounds[AMBIENCE_SOUNDS_ARMAGEDDON] && equal(key, "ARMAGEDDON SOUNDS"))
8672 {
8673 // Parse sounds
8674 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8675 {
8676 // Trim spaces
8677 trim(key)
8678 trim(value)
8679
8680 // Add to sounds array
8681 ArrayPushString(sound_ambience8, key)
8682 ArrayPushCell(sound_ambience8_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8683 }
8684 }
8685 else if (g_ambience_sounds[AMBIENCE_SOUNDS_ARMAGEDDON] && equal(key, "ARMAGEDDON DURATIONS"))
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 ArrayPushCell(sound_ambience8_duration, str_to_num(key))
8696 }
8697 }
8698 else if (equal(key, "APOCALYPSE ENABLE"))
8699 g_ambience_sounds[AMBIENCE_SOUNDS_APOCALYPSE] = str_to_num(value)
8700 else if (g_ambience_sounds[AMBIENCE_SOUNDS_APOCALYPSE] && equal(key, "APOCALYPSE SOUNDS"))
8701 {
8702 // Parse sounds
8703 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8704 {
8705 // Trim spaces
8706 trim(key)
8707 trim(value)
8708
8709 // Add to sounds array
8710 ArrayPushString(sound_ambience9, key)
8711 ArrayPushCell(sound_ambience9_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8712 }
8713 }
8714 else if (g_ambience_sounds[AMBIENCE_SOUNDS_APOCALYPSE] && equal(key, "APOCALYPSE DURATIONS"))
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 ArrayPushCell(sound_ambience9_duration, str_to_num(key))
8725 }
8726 }
8727 else if (equal(key, "NIGHTMARE ENABLE"))
8728 g_ambience_sounds[AMBIENCE_SOUNDS_NIGHTMARE] = str_to_num(value)
8729 else if (g_ambience_sounds[AMBIENCE_SOUNDS_NIGHTMARE] && equal(key, "NIGHTMARE SOUNDS"))
8730 {
8731 // Parse sounds
8732 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8733 {
8734 // Trim spaces
8735 trim(key)
8736 trim(value)
8737
8738 // Add to sounds array
8739 ArrayPushString(sound_ambience10, key)
8740 ArrayPushCell(sound_ambience10_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8741 }
8742 }
8743 else if (g_ambience_sounds[AMBIENCE_SOUNDS_NIGHTMARE] && equal(key, "NIGHTMARE DURATIONS"))
8744 {
8745 // Parse sounds
8746 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8747 {
8748 // Trim spaces
8749 trim(key)
8750 trim(value)
8751
8752 // Add to sounds array
8753 ArrayPushCell(sound_ambience10_duration, str_to_num(key))
8754 }
8755 }
8756 }
8757 case SECTION_BUY_MENU_WEAPONS:
8758 {
8759 if (equal(key, "PRIMARY"))
8760 {
8761 // Parse weapons
8762 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8763 {
8764 // Trim spaces
8765 trim(key)
8766 trim(value)
8767
8768 // Add to weapons array
8769 ArrayPushString(g_primary_items, key)
8770 ArrayPushCell(g_primary_weaponids, cs_weapon_name_to_id(key))
8771 }
8772 }
8773 else if (equal(key, "SECONDARY"))
8774 {
8775 // Parse weapons
8776 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8777 {
8778 // Trim spaces
8779 trim(key)
8780 trim(value)
8781
8782 // Add to weapons array
8783 ArrayPushString(g_secondary_items, key)
8784 ArrayPushCell(g_secondary_weaponids, cs_weapon_name_to_id(key))
8785 }
8786 }
8787 else if (equal(key, "ADDITIONAL ITEMS"))
8788 {
8789 // Parse weapons
8790 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8791 {
8792 // Trim spaces
8793 trim(key)
8794 trim(value)
8795
8796 // Add to weapons array
8797 ArrayPushString(g_additional_items, key)
8798 }
8799 }
8800 }
8801 case SECTION_EXTRA_ITEMS_WEAPONS:
8802 {
8803 if (equal(key, "NAMES"))
8804 {
8805 // Parse weapon items
8806 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8807 {
8808 // Trim spaces
8809 trim(key)
8810 trim(value)
8811
8812 // Add to weapons array
8813 ArrayPushString(g_extraweapon_names, key)
8814 }
8815 }
8816 else if (equal(key, "ITEMS"))
8817 {
8818 // Parse weapon items
8819 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8820 {
8821 // Trim spaces
8822 trim(key)
8823 trim(value)
8824
8825 // Add to weapons array
8826 ArrayPushString(g_extraweapon_items, key)
8827 }
8828 }
8829 else if (equal(key, "COSTS"))
8830 {
8831 // Parse weapon items
8832 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8833 {
8834 // Trim spaces
8835 trim(key)
8836 trim(value)
8837
8838 // Add to weapons array
8839 ArrayPushCell(g_extraweapon_costs, str_to_num(key))
8840 }
8841 }
8842 }
8843 case SECTION_HARD_CODED_ITEMS_COSTS:
8844 {
8845 if (equal(key, "NIGHT VISION"))
8846 g_extra_costs2[EXTRA_NVISION] = str_to_num(value)
8847 else if (equal(key, "ANTIDOTE"))
8848 g_extra_costs2[EXTRA_ANTIDOTE] = str_to_num(value)
8849 else if (equal(key, "ZOMBIE MADNESS"))
8850 g_extra_costs2[EXTRA_MADNESS] = str_to_num(value)
8851 else if (equal(key, "INFECTION BOMB"))
8852 g_extra_costs2[EXTRA_INFBOMB] = str_to_num(value)
8853 }
8854 case SECTION_WEATHER_EFFECTS:
8855 {
8856 if (equal(key, "RAIN"))
8857 g_ambience_rain = str_to_num(value)
8858 else if (equal(key, "SNOW"))
8859 g_ambience_snow = str_to_num(value)
8860 else if (equal(key, "FOG"))
8861 g_ambience_fog = str_to_num(value)
8862 else if (equal(key, "FOG DENSITY"))
8863 copy(g_fog_density, charsmax(g_fog_density), value)
8864 else if (equal(key, "FOG COLOR"))
8865 copy(g_fog_color, charsmax(g_fog_color), value)
8866 }
8867 case SECTION_SKY:
8868 {
8869 if (equal(key, "ENABLE"))
8870 g_sky_enable = str_to_num(value)
8871 else if (equal(key, "SKY NAMES"))
8872 {
8873 // Parse sky names
8874 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8875 {
8876 // Trim spaces
8877 trim(key)
8878 trim(value)
8879
8880 // Add to skies array
8881 ArrayPushString(g_sky_names, key)
8882
8883 // Preache custom sky files
8884 formatex(linedata, charsmax(linedata), "gfx/env/%sbk.tga", key)
8885 engfunc(EngFunc_PrecacheGeneric, linedata)
8886 formatex(linedata, charsmax(linedata), "gfx/env/%sdn.tga", key)
8887 engfunc(EngFunc_PrecacheGeneric, linedata)
8888 formatex(linedata, charsmax(linedata), "gfx/env/%sft.tga", key)
8889 engfunc(EngFunc_PrecacheGeneric, linedata)
8890 formatex(linedata, charsmax(linedata), "gfx/env/%slf.tga", key)
8891 engfunc(EngFunc_PrecacheGeneric, linedata)
8892 formatex(linedata, charsmax(linedata), "gfx/env/%srt.tga", key)
8893 engfunc(EngFunc_PrecacheGeneric, linedata)
8894 formatex(linedata, charsmax(linedata), "gfx/env/%sup.tga", key)
8895 engfunc(EngFunc_PrecacheGeneric, linedata)
8896 }
8897 }
8898 }
8899 case SECTION_LIGHTNING:
8900 {
8901 if (equal(key, "LIGHTS"))
8902 {
8903 // Parse lights
8904 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8905 {
8906 // Trim spaces
8907 trim(key)
8908 trim(value)
8909
8910 // Add to lightning array
8911 ArrayPushString(lights_thunder, key)
8912 }
8913 }
8914 }
8915 case SECTION_ZOMBIE_DECALS:
8916 {
8917 if (equal(key, "DECALS"))
8918 {
8919 // Parse decals
8920 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8921 {
8922 // Trim spaces
8923 trim(key)
8924 trim(value)
8925
8926 // Add to zombie decals array
8927 ArrayPushCell(zombie_decals, str_to_num(key))
8928 }
8929 }
8930 }
8931 case SECTION_KNOCKBACK:
8932 {
8933 // Format weapon entity name
8934 strtolower(key)
8935 format(key, charsmax(key), "weapon_%s", key)
8936
8937 // Add value to knockback power array
8938 kb_weapon_power[cs_weapon_name_to_id(key)] = str_to_float(value)
8939 }
8940 case SECTION_OBJECTIVE_ENTS:
8941 {
8942 if (equal(key, "CLASSNAMES"))
8943 {
8944 // Parse classnames
8945 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8946 {
8947 // Trim spaces
8948 trim(key)
8949 trim(value)
8950
8951 // Add to objective ents array
8952 ArrayPushString(g_objective_ents, key)
8953 }
8954 }
8955 }
8956 case SECTION_SVC_BAD:
8957 {
8958 if (equal(key, "MODELCHANGE DELAY"))
8959 g_modelchange_delay = str_to_float(value)
8960 else if (equal(key, "HANDLE MODELS ON SEPARATE ENT"))
8961 g_handle_models_on_separate_ent = str_to_num(value)
8962 else if (equal(key, "SET MODELINDEX OFFSET"))
8963 g_set_modelindex_offset = str_to_num(value)
8964 }
8965 }
8966 }
8967 if (file) fclose(file)
8968
8969 // Build zombie classes file path
8970 get_configsdir(path, charsmax(path))
8971 format(path, charsmax(path), "%s/%s", path, ZP_ZOMBIECLASSES_FILE)
8972
8973 // Parse if present
8974 if (file_exists(path))
8975 {
8976 // Open zombie classes file for reading
8977 file = fopen(path, "rt")
8978
8979 while (file && !feof(file))
8980 {
8981 // Read one line at a time
8982 fgets(file, linedata, charsmax(linedata))
8983
8984 // Replace newlines with a null character to prevent headaches
8985 replace(linedata, charsmax(linedata), "^n", "")
8986
8987 // Blank line or comment
8988 if (!linedata[0] || linedata[0] == ';') continue;
8989
8990 // New class starting
8991 if (linedata[0] == '[')
8992 {
8993 // Remove first and last characters (braces)
8994 linedata[strlen(linedata) - 1] = 0
8995 copy(linedata, charsmax(linedata), linedata[1])
8996
8997 // Store its real name for future reference
8998 ArrayPushString(g_zclass2_realname, linedata)
8999 continue;
9000 }
9001
9002 // Get key and value(s)
9003 strtok(linedata, key, charsmax(key), value, charsmax(value), '=')
9004
9005 // Trim spaces
9006 trim(key)
9007 trim(value)
9008
9009 if (equal(key, "NAME"))
9010 ArrayPushString(g_zclass2_name, value)
9011 else if (equal(key, "INFO"))
9012 ArrayPushString(g_zclass2_info, value)
9013 else if (equal(key, "MODELS"))
9014 {
9015 // Set models start index
9016 ArrayPushCell(g_zclass2_modelsstart, ArraySize(g_zclass2_playermodel))
9017
9018 // Parse class models
9019 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
9020 {
9021 // Trim spaces
9022 trim(key)
9023 trim(value)
9024
9025 // Add to class models array
9026 ArrayPushString(g_zclass2_playermodel, key)
9027 ArrayPushCell(g_zclass2_modelindex, -1)
9028 }
9029
9030 // Set models end index
9031 ArrayPushCell(g_zclass2_modelsend, ArraySize(g_zclass2_playermodel))
9032 }
9033 else if (equal(key, "CLAWMODEL"))
9034 ArrayPushString(g_zclass2_clawmodel, value)
9035 else if (equal(key, "HEALTH"))
9036 ArrayPushCell(g_zclass2_hp, str_to_num(value))
9037 else if (equal(key, "SPEED"))
9038 ArrayPushCell(g_zclass2_spd, str_to_num(value))
9039 else if (equal(key, "GRAVITY"))
9040 ArrayPushCell(g_zclass2_grav, str_to_float(value))
9041 else if (equal(key, "KNOCKBACK"))
9042 ArrayPushCell(g_zclass2_kb, str_to_float(value))
9043 }
9044 if (file) fclose(file)
9045 }
9046
9047 // Build extra items file path
9048 get_configsdir(path, charsmax(path))
9049 format(path, charsmax(path), "%s/%s", path, ZP_EXTRAITEMS_FILE)
9050
9051 // Parse if present
9052 if (file_exists(path))
9053 {
9054 // Open extra items file for reading
9055 file = fopen(path, "rt")
9056
9057 while (file && !feof(file))
9058 {
9059 // Read one line at a time
9060 fgets(file, linedata, charsmax(linedata))
9061
9062 // Replace newlines with a null character to prevent headaches
9063 replace(linedata, charsmax(linedata), "^n", "")
9064
9065 // Blank line or comment
9066 if (!linedata[0] || linedata[0] == ';') continue;
9067
9068 // New item starting
9069 if (linedata[0] == '[')
9070 {
9071 // Remove first and last characters (braces)
9072 linedata[strlen(linedata) - 1] = 0
9073 copy(linedata, charsmax(linedata), linedata[1])
9074
9075 // Store its real name for future reference
9076 ArrayPushString(g_extraitem2_realname, linedata)
9077 continue;
9078 }
9079
9080 // Get key and value(s)
9081 strtok(linedata, key, charsmax(key), value, charsmax(value), '=')
9082
9083 // Trim spaces
9084 trim(key)
9085 trim(value)
9086
9087 if (equal(key, "NAME"))
9088 ArrayPushString(g_extraitem2_name, value)
9089 else if (equal(key, "COST"))
9090 ArrayPushCell(g_extraitem2_cost, str_to_num(value))
9091 else if (equal(key, "TEAMS"))
9092 {
9093 // Clear teams bitsum
9094 teams = 0
9095
9096 // Parse teams
9097 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
9098 {
9099 // Trim spaces
9100 trim(key)
9101 trim(value)
9102
9103 if (equal(key, ZP_TEAM_NAMES[ZP_TEAM_ZOMBIE]))
9104 teams |= ZP_TEAM_ZOMBIE
9105 else if (equal(key, ZP_TEAM_NAMES[ZP_TEAM_HUMAN]))
9106 teams |= ZP_TEAM_HUMAN
9107 else if (equal(key, ZP_TEAM_NAMES[ZP_TEAM_NEMESIS]))
9108 teams |= ZP_TEAM_NEMESIS
9109 else if (equal(key, ZP_TEAM_NAMES[ZP_TEAM_ASSASSIN]))
9110 teams |= ZP_TEAM_ASSASSIN
9111 else if (equal(key, ZP_TEAM_NAMES[ZP_TEAM_SURVIVOR]))
9112 teams |= ZP_TEAM_SURVIVOR
9113 else if (equal(key, ZP_TEAM_NAMES[ZP_TEAM_SNIPER]))
9114 teams |= ZP_TEAM_SNIPER
9115 }
9116
9117 // Add to teams array
9118 ArrayPushCell(g_extraitem2_team, teams)
9119 }
9120 }
9121 if (file) fclose(file)
9122 }
9123}
9124
9125save_customization()
9126{
9127 new i, k, buffer[512]
9128
9129 // Build zombie classes file path
9130 new path[64]
9131 get_configsdir(path, charsmax(path))
9132 format(path, charsmax(path), "%s/%s", path, ZP_ZOMBIECLASSES_FILE)
9133
9134 // Open zombie classes file for appending data
9135 new file = fopen(path, "at"), size = ArraySize(g_zclass_name)
9136
9137 // Add any new zombie classes data at the end if needed
9138 for (i = 0; i < size; i++)
9139 {
9140 if (ArrayGetCell(g_zclass_new, i))
9141 {
9142 // Add real name
9143 ArrayGetString(g_zclass_name, i, buffer, charsmax(buffer))
9144 format(buffer, charsmax(buffer), "^n[%s]", buffer)
9145 fputs(file, buffer)
9146
9147 // Add caption
9148 ArrayGetString(g_zclass_name, i, buffer, charsmax(buffer))
9149 format(buffer, charsmax(buffer), "^nNAME = %s", buffer)
9150 fputs(file, buffer)
9151
9152 // Add info
9153 ArrayGetString(g_zclass_info, i, buffer, charsmax(buffer))
9154 format(buffer, charsmax(buffer), "^nINFO = %s", buffer)
9155 fputs(file, buffer)
9156
9157 // Add models
9158 for (k = ArrayGetCell(g_zclass_modelsstart, i); k < ArrayGetCell(g_zclass_modelsend, i); k++)
9159 {
9160 if (k == ArrayGetCell(g_zclass_modelsstart, i))
9161 {
9162 // First model, overwrite buffer
9163 ArrayGetString(g_zclass_playermodel, k, buffer, charsmax(buffer))
9164 }
9165 else
9166 {
9167 // Successive models, append to buffer
9168 ArrayGetString(g_zclass_playermodel, k, path, charsmax(path))
9169 format(buffer, charsmax(buffer), "%s , %s", buffer, path)
9170 }
9171 }
9172 format(buffer, charsmax(buffer), "^nMODELS = %s", buffer)
9173 fputs(file, buffer)
9174
9175 // Add clawmodel
9176 ArrayGetString(g_zclass_clawmodel, i, buffer, charsmax(buffer))
9177 format(buffer, charsmax(buffer), "^nCLAWMODEL = %s", buffer)
9178 fputs(file, buffer)
9179
9180 // Add health
9181 formatex(buffer, charsmax(buffer), "^nHEALTH = %d", ArrayGetCell(g_zclass_hp, i))
9182 fputs(file, buffer)
9183
9184 // Add speed
9185 formatex(buffer, charsmax(buffer), "^nSPEED = %d", ArrayGetCell(g_zclass_spd, i))
9186 fputs(file, buffer)
9187
9188 // Add gravity
9189 formatex(buffer, charsmax(buffer), "^nGRAVITY = %.2f", Float:ArrayGetCell(g_zclass_grav, i))
9190 fputs(file, buffer)
9191
9192 // Add knockback
9193 formatex(buffer, charsmax(buffer), "^nKNOCKBACK = %.2f^n", Float:ArrayGetCell(g_zclass_kb, i))
9194 fputs(file, buffer)
9195 }
9196 }
9197 fclose(file)
9198
9199 // Build extra items file path
9200 get_configsdir(path, charsmax(path))
9201 format(path, charsmax(path), "%s/%s", path, ZP_EXTRAITEMS_FILE)
9202
9203 // Open extra items file for appending data
9204 file = fopen(path, "at")
9205 size = ArraySize(g_extraitem_name)
9206
9207 // Add any new extra items data at the end if needed
9208 for (i = EXTRAS_CUSTOM_STARTID; i < size; i++)
9209 {
9210 if (ArrayGetCell(g_extraitem_new, i))
9211 {
9212 // Add real name
9213 ArrayGetString(g_extraitem_name, i, buffer, charsmax(buffer))
9214 format(buffer, charsmax(buffer), "^n[%s]", buffer)
9215 fputs(file, buffer)
9216
9217 // Add caption
9218 ArrayGetString(g_extraitem_name, i, buffer, charsmax(buffer))
9219 format(buffer, charsmax(buffer), "^nNAME = %s", buffer)
9220 fputs(file, buffer)
9221
9222 // Add cost
9223 formatex(buffer, charsmax(buffer), "^nCOST = %d", ArrayGetCell(g_extraitem_cost, i))
9224 fputs(file, buffer)
9225
9226 // Add team
9227 formatex(buffer, charsmax(buffer), "^nTEAMS = %s^n", ZP_TEAM_NAMES[ArrayGetCell(g_extraitem_team, i)])
9228 fputs(file, buffer)
9229 }
9230 }
9231 fclose(file)
9232
9233 // Free arrays containing class/item overrides
9234 ArrayDestroy(g_zclass2_realname)
9235 ArrayDestroy(g_zclass2_name)
9236 ArrayDestroy(g_zclass2_info)
9237 ArrayDestroy(g_zclass2_modelsstart)
9238 ArrayDestroy(g_zclass2_modelsend)
9239 ArrayDestroy(g_zclass2_playermodel)
9240 ArrayDestroy(g_zclass2_modelindex)
9241 ArrayDestroy(g_zclass2_clawmodel)
9242 ArrayDestroy(g_zclass2_hp)
9243 ArrayDestroy(g_zclass2_spd)
9244 ArrayDestroy(g_zclass2_grav)
9245 ArrayDestroy(g_zclass2_kb)
9246 ArrayDestroy(g_zclass_new)
9247 ArrayDestroy(g_extraitem2_realname)
9248 ArrayDestroy(g_extraitem2_name)
9249 ArrayDestroy(g_extraitem2_cost)
9250 ArrayDestroy(g_extraitem2_team)
9251 ArrayDestroy(g_extraitem_new)
9252}
9253
9254// Register Ham Forwards for CZ bots
9255public register_ham_czbots(id)
9256{
9257 // Make sure it's a CZ bot and it's still connected
9258 if (g_hamczbots || !g_isconnected[id] || !get_pcvar_num(cvar_botquota))
9259 return;
9260
9261 RegisterHamFromEntity(Ham_Spawn, id, "fw_PlayerSpawn_Post", 1)
9262 RegisterHamFromEntity(Ham_Killed, id, "fw_PlayerKilled")
9263 RegisterHamFromEntity(Ham_Killed, id, "fw_PlayerKilled_Post", 1)
9264 RegisterHamFromEntity(Ham_TakeDamage, id, "fw_TakeDamage")
9265 RegisterHamFromEntity(Ham_TakeDamage, id, "fw_TakeDamage_Post", 1)
9266 RegisterHamFromEntity(Ham_TraceAttack, id, "fw_TraceAttack")
9267 RegisterHamFromEntity(Ham_Player_ResetMaxSpeed, id, "fw_ResetMaxSpeed_Post", 1)
9268
9269 // Ham forwards for CZ bots succesfully registered
9270 g_hamczbots = true
9271
9272 // If the bot has already spawned, call the forward manually for him
9273 if (is_user_alive(id)) fw_PlayerSpawn_Post(id)
9274}
9275
9276// Disable minmodels task
9277public disable_minmodels(id)
9278{
9279 if (!g_isconnected[id]) return;
9280 client_cmd(id, "cl_minmodels 0")
9281}
9282
9283// Bots automatically buy extra items
9284public bot_buy_extras(taskid)
9285{
9286 // Nemesis or Survivor bots have nothing to buy by default
9287 if (!g_isalive[ID_SPAWN] || g_survivor[ID_SPAWN] || g_sniper[ID_SPAWN] || g_nemesis[ID_SPAWN] || g_assassin[ID_SPAWN])
9288 return;
9289
9290 if (!g_zombie[ID_SPAWN]) // human bots
9291 {
9292 // Attempt to buy Night Vision
9293 buy_extra_item(ID_SPAWN, EXTRA_NVISION)
9294
9295 // Attempt to buy a weapon
9296 buy_extra_item(ID_SPAWN, random_num(EXTRA_WEAPONS_STARTID, EXTRAS_CUSTOM_STARTID-1))
9297 }
9298 else // zombie bots
9299 {
9300 // Attempt to buy an Antidote
9301 buy_extra_item(ID_SPAWN, EXTRA_ANTIDOTE)
9302 }
9303}
9304
9305// Refill BP Ammo Task
9306public refill_bpammo(const args[], id)
9307{
9308 // Player died or turned into a zombie
9309 if (!g_isalive[id] || g_zombie[id])
9310 return;
9311
9312 set_msg_block(g_msgAmmoPickup, BLOCK_ONCE)
9313 ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[REFILL_WEAPONID], AMMOTYPE[REFILL_WEAPONID], MAXBPAMMO[REFILL_WEAPONID])
9314}
9315
9316// Balance Teams Task
9317balance_teams()
9318{
9319 // Get amount of users playing
9320 static iPlayersnum
9321 iPlayersnum = fnGetPlaying()
9322
9323 // No players, don't bother
9324 if (iPlayersnum < 1) return;
9325
9326 // Split players evenly
9327 static iTerrors, iMaxTerrors, id, team[33]
9328 iMaxTerrors = iPlayersnum/2
9329 iTerrors = 0
9330
9331 // First, set everyone to CT
9332 for (id = 1; id <= g_maxplayers; id++)
9333 {
9334 // Skip if not connected
9335 if (!g_isconnected[id])
9336 continue;
9337
9338 team[id] = fm_cs_get_user_team(id)
9339
9340 // Skip if not playing
9341 if (team[id] == FM_CS_TEAM_SPECTATOR || team[id] == FM_CS_TEAM_UNASSIGNED)
9342 continue;
9343
9344 // Set team
9345 remove_task(id+TASK_TEAM)
9346 fm_cs_set_user_team(id, FM_CS_TEAM_CT)
9347 team[id] = FM_CS_TEAM_CT
9348 }
9349
9350 // Then randomly set half of the players to Terrorists
9351 while (iTerrors < iMaxTerrors)
9352 {
9353 // Keep looping through all players
9354 if (++id > g_maxplayers) id = 1
9355
9356 // Skip if not connected
9357 if (!g_isconnected[id])
9358 continue;
9359
9360 // Skip if not playing or already a Terrorist
9361 if (team[id] != FM_CS_TEAM_CT)
9362 continue;
9363
9364 // Random chance
9365 if (random_num(0, 1))
9366 {
9367 fm_cs_set_user_team(id, FM_CS_TEAM_T)
9368 team[id] = FM_CS_TEAM_T
9369 iTerrors++
9370 }
9371 }
9372}
9373
9374// Welcome Message Task
9375public welcome_msg()
9376{
9377 // Show mod info
9378 zp_colored_print(0, "^x01**** ^x04%s^x01 ****", g_modname)
9379 zp_colored_print(0, "^x04[ZP]^x01 %L", LANG_PLAYER, "NOTICE_INFO1")
9380 if (!get_pcvar_num(cvar_infammo)) zp_colored_print(0, "^x04[ZP]^x01 %L", LANG_PLAYER, "NOTICE_INFO2")
9381
9382 // Show T-virus HUD notice
9383 set_hudmessage(0, 125, 200, HUD_EVENT_X, HUD_EVENT_Y, 0, 0.0, 3.0, 2.0, 1.0, -1)
9384 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_VIRUS_FREE")
9385}
9386
9387// Respawn Player Task (deathmatch)
9388public respawn_player_task(taskid)
9389{
9390 // Already alive or round ended
9391 if (g_isalive[ID_SPAWN] || g_endround)
9392 return;
9393
9394 // Get player's team
9395 static team
9396 team = fm_cs_get_user_team(ID_SPAWN)
9397
9398 // Player moved to spectators
9399 if (team == FM_CS_TEAM_SPECTATOR || team == FM_CS_TEAM_UNASSIGNED)
9400 return;
9401
9402 // Respawn player automatically if allowed on current round
9403 if ((!g_survround || get_pcvar_num(cvar_allowrespawnsurv))
9404 && (!g_sniround || get_pcvar_num(cvar_allowrespawnsni))
9405 && (!g_swarmround || get_pcvar_num(cvar_allowrespawnswarm))
9406 && (!g_nemround || get_pcvar_num(cvar_allowrespawnnem))
9407 && (!g_assaround || get_pcvar_num(cvar_allowrespawnassa))
9408 && (!g_plagueround || get_pcvar_num(cvar_allowrespawnplague))
9409 && (!g_armageround || get_pcvar_num(cvar_allowrespawnarmage))
9410 && (!g_apocround || get_pcvar_num(cvar_allowrespawnapoc))
9411 && (!g_nightround || get_pcvar_num(cvar_allowrespawnnight)))
9412 {
9413
9414 // Infection rounds = none of the above
9415 if (!get_pcvar_num(cvar_allowrespawninfection) && !g_survround && !g_sniround && !g_nemround && !g_assaround && !g_swarmround && !g_plagueround && !g_armageround && !g_apocround && !g_nightround)
9416 return;
9417
9418 // Respawn if only the last human is left? (ignore this setting on survivor rounds)
9419 if (!g_survround && !g_sniround && !get_pcvar_num(cvar_respawnafterlast) && fnGetHumans() <= 1)
9420 return;
9421
9422 // Respawn as zombie?
9423 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))
9424 g_respawn_as_zombie[ID_SPAWN] = true
9425
9426 // Override respawn as zombie setting on nemesis and survivor rounds
9427 if (g_survround || g_sniround) g_respawn_as_zombie[ID_SPAWN] = true
9428 else if (g_nemround || g_assaround) g_respawn_as_zombie[ID_SPAWN] = false
9429
9430 respawn_player_manually(ID_SPAWN)
9431 }
9432}
9433
9434// Respawn Player Check Task (if killed by worldspawn)
9435public respawn_player_check_task(taskid)
9436{
9437 // Successfully spawned or round ended
9438 if (g_isalive[ID_SPAWN] || g_endround)
9439 return;
9440
9441 // Get player's team
9442 static team
9443 team = fm_cs_get_user_team(ID_SPAWN)
9444
9445 // Player moved to spectators
9446 if (team == FM_CS_TEAM_SPECTATOR || team == FM_CS_TEAM_UNASSIGNED)
9447 return;
9448
9449 // If player was being spawned as a zombie, set the flag again
9450 if (g_zombie[ID_SPAWN]) g_respawn_as_zombie[ID_SPAWN] = true
9451 else g_respawn_as_zombie[ID_SPAWN] = false
9452
9453 respawn_player_manually(ID_SPAWN)
9454}
9455
9456// Respawn Player Manually (called after respawn checks are done)
9457respawn_player_manually(id)
9458{
9459 // Set proper team before respawning, so that the TeamInfo message that's sent doesn't confuse PODBots
9460 if (g_respawn_as_zombie[id])
9461 fm_cs_set_user_team(id, FM_CS_TEAM_T)
9462 else
9463 fm_cs_set_user_team(id, FM_CS_TEAM_CT)
9464
9465 // Respawning a player has never been so easy
9466 ExecuteHamB(Ham_CS_RoundRespawn, id)
9467}
9468
9469// Check Round Task -check that we still have both zombies and humans on a round-
9470check_round(leaving_player)
9471{
9472 // Round ended or make_a_zombie task still active
9473 if (g_endround || task_exists(TASK_MAKEZOMBIE))
9474 return;
9475
9476 // Get alive players count
9477 static iPlayersnum, id
9478 iPlayersnum = fnGetAlive()
9479
9480 // Last alive player, don't bother
9481 if (iPlayersnum < 2)
9482 return;
9483
9484 // Last zombie disconnecting
9485 if (g_zombie[leaving_player] && fnGetZombies() == 1)
9486 {
9487 // Only one CT left, don't bother
9488 if (fnGetHumans() == 1 && fnGetCTs() == 1)
9489 return;
9490
9491 // Pick a random one to take his place
9492 while ((id = fnGetRandomAlive(random_num(1, iPlayersnum))) == leaving_player ) { /* keep looping */ }
9493
9494 // Show last zombie left notice
9495 zp_colored_print(0, "^x04[ZP]^x01 %L", LANG_PLAYER, "LAST_ZOMBIE_LEFT", g_playername[id])
9496
9497 // Set player leaving flag
9498 g_lastplayerleaving = true
9499
9500 // Turn into a Nemesis or just a zombie?
9501 if (g_nemesis[leaving_player])
9502 zombieme(id, 0, 1, 0, 0, 0)
9503 else if (g_assassin[leaving_player])
9504 zombieme(id, 0, 0, 1, 0, 0)
9505 else
9506 zombieme(id, 0, 0, 0, 0, 0)
9507
9508 // Remove player leaving flag
9509 g_lastplayerleaving = false
9510
9511 // If Nemesis, set chosen player's health to that of the one who's leaving
9512 if (get_pcvar_num(cvar_keephealthondisconnect) && g_nemesis[leaving_player])
9513 fm_set_user_health(id, pev(leaving_player, pev_health))
9514
9515 // If Assassin, set chosen player's health to that of the one who's leaving
9516 if (get_pcvar_num(cvar_keephealthondisconnect) && g_assassin[leaving_player])
9517 fm_set_user_health(id, pev(leaving_player, pev_health))
9518 }
9519
9520 // Last human disconnecting
9521 else if (!g_zombie[leaving_player] && fnGetHumans() == 1)
9522 {
9523 // Only one T left, don't bother
9524 if (fnGetZombies() == 1 && fnGetTs() == 1)
9525 return;
9526
9527 // Pick a random one to take his place
9528 while ((id = fnGetRandomAlive(random_num(1, iPlayersnum))) == leaving_player ) { /* keep looping */ }
9529
9530 // Show last human left notice
9531 zp_colored_print(0, "^x04[ZP]^x01 %L", LANG_PLAYER, "LAST_HUMAN_LEFT", g_playername[id])
9532
9533 // Set player leaving flag
9534 g_lastplayerleaving = true
9535
9536 // Turn into a Survivor or just a human?
9537 if (g_survivor[leaving_player])
9538 humanme(id, 1, 0, 0)
9539 else if (g_sniper[leaving_player])
9540 humanme(id, 0, 1, 0)
9541 else
9542 humanme(id, 0, 0, 0)
9543
9544 // Remove player leaving flag
9545 g_lastplayerleaving = false
9546
9547 // If Survivor, set chosen player's health to that of the one who's leaving
9548 if (get_pcvar_num(cvar_keephealthondisconnect) && g_survivor[leaving_player])
9549 fm_set_user_health(id, pev(leaving_player, pev_health))
9550
9551 // If Sniper, set chosen player's health to that of the one who's leaving
9552 if (get_pcvar_num(cvar_keephealthondisconnect) && g_sniper[leaving_player])
9553 fm_set_user_health(id, pev(leaving_player, pev_health))
9554 }
9555}
9556
9557// Lighting Effects Task
9558public lighting_effects()
9559{
9560 // Cache some CVAR values at every 5 secs
9561 cache_cvars()
9562
9563 // Get lighting style
9564 static lighting[2]
9565 get_pcvar_string(cvar_lighting, lighting, charsmax(lighting))
9566 strtolower(lighting)
9567
9568 // Lighting disabled? ["0"]
9569 if (lighting[0] == '0')
9570 return;
9571
9572 // Darkest light settings?
9573 if (lighting[0] >= 'a' && lighting[0] <= 'd')
9574 {
9575 static thunderclap_in_progress, Float:thunder
9576 thunderclap_in_progress = task_exists(TASK_THUNDER)
9577 thunder = get_pcvar_float(cvar_thunder)
9578
9579 // Set thunderclap tasks if not existant
9580 if (thunder > 0.0 && !task_exists(TASK_THUNDER_PRE) && !thunderclap_in_progress)
9581 {
9582 g_lights_i = 0
9583 ArrayGetString(lights_thunder, random_num(0, ArraySize(lights_thunder) - 1), g_lights_cycle, charsmax(g_lights_cycle))
9584 g_lights_cycle_len = strlen(g_lights_cycle)
9585 set_task(thunder, "thunderclap", TASK_THUNDER_PRE)
9586 }
9587
9588 // Set lighting only when no thunderclaps are going on
9589 if (!thunderclap_in_progress) engfunc(EngFunc_LightStyle, 0, g_assaround ? "a" : lighting) // no lighting in assassin round
9590 }
9591 else
9592 {
9593 // Remove thunderclap tasks
9594 remove_task(TASK_THUNDER_PRE)
9595 remove_task(TASK_THUNDER)
9596
9597 // Set lighting
9598 engfunc(EngFunc_LightStyle, 0, g_assaround ? "a" : lighting) // no lighting in assassin round
9599 }
9600}
9601
9602// Thunderclap task
9603public thunderclap()
9604{
9605 // Play thunder sound
9606 if (g_lights_i == 0)
9607 {
9608 static sound[64]
9609 ArrayGetString(sound_thunder, random_num(0, ArraySize(sound_thunder) - 1), sound, charsmax(sound))
9610 PlaySound(sound)
9611 }
9612
9613 // Set lighting
9614 static light[2]
9615 light[0] = g_lights_cycle[g_lights_i]
9616 engfunc(EngFunc_LightStyle, 0, light)
9617
9618 g_lights_i++
9619
9620 // Lighting cycle end?
9621 if (g_lights_i >= g_lights_cycle_len)
9622 {
9623 remove_task(TASK_THUNDER)
9624 lighting_effects()
9625 }
9626 // Lighting cycle start?
9627 else if (!task_exists(TASK_THUNDER))
9628 set_task(0.1, "thunderclap", TASK_THUNDER, _, _, "b")
9629}
9630
9631// Ambience Sound Effects Task
9632public ambience_sound_effects(taskid)
9633{
9634 // Play a random sound depending on the round
9635 static sound[64], iRand, duration
9636
9637 if (g_nemround) // Nemesis Mode
9638 {
9639 iRand = random_num(0, ArraySize(sound_ambience2) - 1)
9640 ArrayGetString(sound_ambience2, iRand, sound, charsmax(sound))
9641 duration = ArrayGetCell(sound_ambience2_duration, iRand)
9642 }
9643 if (g_assaround) // Assassin Mode
9644 {
9645 iRand = random_num(0, ArraySize(sound_ambience6) - 1)
9646 ArrayGetString(sound_ambience6, iRand, sound, charsmax(sound))
9647 duration = ArrayGetCell(sound_ambience6_duration, iRand)
9648 }
9649 else if (g_survround) // Survivor Mode
9650 {
9651 iRand = random_num(0, ArraySize(sound_ambience3) - 1)
9652 ArrayGetString(sound_ambience3, iRand, sound, charsmax(sound))
9653 duration = ArrayGetCell(sound_ambience3_duration, iRand)
9654 }
9655 else if (g_sniround) // Sniper Mode
9656 {
9657 iRand = random_num(0, ArraySize(sound_ambience7) - 1)
9658 ArrayGetString(sound_ambience7, iRand, sound, charsmax(sound))
9659 duration = ArrayGetCell(sound_ambience7_duration, iRand)
9660 }
9661 else if (g_swarmround) // Swarm Mode
9662 {
9663 iRand = random_num(0, ArraySize(sound_ambience4) - 1)
9664 ArrayGetString(sound_ambience4, iRand, sound, charsmax(sound))
9665 duration = ArrayGetCell(sound_ambience4_duration, iRand)
9666 }
9667 else if (g_plagueround) // Plague Mode
9668 {
9669 iRand = random_num(0, ArraySize(sound_ambience5) - 1)
9670 ArrayGetString(sound_ambience5, iRand, sound, charsmax(sound))
9671 duration = ArrayGetCell(sound_ambience5_duration, iRand)
9672 }
9673 else if (g_armageround) // Armageddon Mode
9674 {
9675 iRand = random_num(0, ArraySize(sound_ambience8) - 1)
9676 ArrayGetString(sound_ambience8, iRand, sound, charsmax(sound))
9677 duration = ArrayGetCell(sound_ambience8_duration, iRand)
9678 }
9679 else if (g_apocround) // Apocalypse Mode
9680 {
9681 iRand = random_num(0, ArraySize(sound_ambience9) - 1)
9682 ArrayGetString(sound_ambience9, iRand, sound, charsmax(sound))
9683 duration = ArrayGetCell(sound_ambience9_duration, iRand)
9684 }
9685 else if (g_nightround) // Nightmare Mode
9686 {
9687 iRand = random_num(0, ArraySize(sound_ambience10) - 1)
9688 ArrayGetString(sound_ambience10, iRand, sound, charsmax(sound))
9689 duration = ArrayGetCell(sound_ambience10_duration, iRand)
9690 }
9691 else // Infection Mode
9692 {
9693 iRand = random_num(0, ArraySize(sound_ambience1) - 1)
9694 ArrayGetString(sound_ambience1, iRand, sound, charsmax(sound))
9695 duration = ArrayGetCell(sound_ambience1_duration, iRand)
9696 }
9697
9698 // Play it on clients
9699 PlaySound(sound)
9700
9701 // Set the task for when the sound is done playing
9702 set_task(float(duration), "ambience_sound_effects", TASK_AMBIENCESOUNDS)
9703}
9704
9705// Ambience Sounds Stop Task
9706ambience_sound_stop()
9707{
9708 client_cmd(0, "mp3 stop; stopsound")
9709}
9710
9711// Flashlight Charge Task
9712public flashlight_charge(taskid)
9713{
9714 // Drain or charge?
9715 if (g_flashlight[ID_CHARGE])
9716 g_flashbattery[ID_CHARGE] -= get_pcvar_num(cvar_flashdrain)
9717 else
9718 g_flashbattery[ID_CHARGE] += get_pcvar_num(cvar_flashcharge)
9719
9720 // Battery fully charged
9721 if (g_flashbattery[ID_CHARGE] >= 100)
9722 {
9723 // Don't exceed 100%
9724 g_flashbattery[ID_CHARGE] = 100
9725
9726 // Update flashlight battery on HUD
9727 message_begin(MSG_ONE, g_msgFlashBat, _, ID_CHARGE)
9728 write_byte(100) // battery
9729 message_end()
9730
9731 // Task not needed anymore
9732 remove_task(taskid);
9733 return;
9734 }
9735
9736 // Battery depleted
9737 if (g_flashbattery[ID_CHARGE] <= 0)
9738 {
9739 // Turn it off
9740 g_flashlight[ID_CHARGE] = false
9741 g_flashbattery[ID_CHARGE] = 0
9742
9743 // Play flashlight toggle sound
9744 emit_sound(ID_CHARGE, CHAN_ITEM, sound_flashlight, 1.0, ATTN_NORM, 0, PITCH_NORM)
9745
9746 // Update flashlight status on HUD
9747 message_begin(MSG_ONE, g_msgFlashlight, _, ID_CHARGE)
9748 write_byte(0) // toggle
9749 write_byte(0) // battery
9750 message_end()
9751
9752 // Remove flashlight task for this player
9753 remove_task(ID_CHARGE+TASK_FLASH)
9754 }
9755 else
9756 {
9757 // Update flashlight battery on HUD
9758 message_begin(MSG_ONE_UNRELIABLE, g_msgFlashBat, _, ID_CHARGE)
9759 write_byte(g_flashbattery[ID_CHARGE]) // battery
9760 message_end()
9761 }
9762}
9763
9764// Remove Spawn Protection Task
9765public remove_spawn_protection(taskid)
9766{
9767 // Not alive
9768 if (!g_isalive[ID_SPAWN])
9769 return;
9770
9771 // Remove spawn protection
9772 g_nodamage[ID_SPAWN] = false
9773 set_pev(ID_SPAWN, pev_effects, pev(ID_SPAWN, pev_effects) & ~EF_NODRAW)
9774}
9775
9776// Hide Player's Money Task
9777public task_hide_money(taskid)
9778{
9779 // Not alive
9780 if (!g_isalive[ID_SPAWN])
9781 return;
9782
9783 // Hide money
9784 message_begin(MSG_ONE, g_msgHideWeapon, _, ID_SPAWN)
9785 write_byte(HIDE_MONEY) // what to hide bitsum
9786 message_end()
9787
9788 // Hide the HL crosshair that's drawn
9789 message_begin(MSG_ONE, g_msgCrosshair, _, ID_SPAWN)
9790 write_byte(0) // toggle
9791 message_end()
9792}
9793
9794// Turn Off Flashlight and Restore Batteries
9795turn_off_flashlight(id)
9796{
9797 // Restore batteries for the next use
9798 fm_cs_set_user_batteries(id, 100)
9799
9800 // Check if flashlight is on
9801 if (pev(id, pev_effects) & EF_DIMLIGHT)
9802 {
9803 // Turn it off
9804 set_pev(id, pev_impulse, IMPULSE_FLASHLIGHT)
9805 }
9806 else
9807 {
9808 // Clear any stored flashlight impulse (bugfix)
9809 set_pev(id, pev_impulse, 0)
9810 }
9811
9812 // Turn off custom flashlight
9813 if (g_cached_customflash)
9814 {
9815 // Turn it off
9816 g_flashlight[id] = false
9817 g_flashbattery[id] = 100
9818
9819 // Update flashlight HUD
9820 message_begin(MSG_ONE, g_msgFlashlight, _, id)
9821 write_byte(0) // toggle
9822 write_byte(100) // battery
9823 message_end()
9824
9825 // Remove previous tasks
9826 remove_task(id+TASK_CHARGE)
9827 remove_task(id+TASK_FLASH)
9828 }
9829}
9830
9831// Infection Bomb Explosion
9832infection_explode(ent)
9833{
9834 // Round ended (bugfix)
9835 if (g_endround) return;
9836
9837 // Get origin
9838 static Float:originF[3]
9839 pev(ent, pev_origin, originF)
9840
9841 // Make the explosion
9842 create_blast(originF)
9843
9844 // Infection nade explode sound
9845 static sound[64]
9846 ArrayGetString(grenade_infect, random_num(0, ArraySize(grenade_infect) - 1), sound, charsmax(sound))
9847 emit_sound(ent, CHAN_WEAPON, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
9848
9849 // Get attacker
9850 static attacker
9851 attacker = pev(ent, pev_owner)
9852
9853 // Infection bomb owner disconnected? (bugfix)
9854 if (!is_user_valid_connected(attacker))
9855 {
9856 // Get rid of the grenade
9857 engfunc(EngFunc_RemoveEntity, ent)
9858 return;
9859 }
9860
9861 // Collisions
9862 static victim
9863 victim = -1
9864
9865 while ((victim = engfunc(EngFunc_FindEntityInSphere, victim, originF, NADE_EXPLOSION_RADIUS)) != 0)
9866 {
9867 // Only effect alive non-spawnprotected humans
9868 if(!is_user_valid_alive(victim) || g_zombie[victim] || g_nodamage[victim])
9869 {
9870 continue;
9871 }
9872
9873 if(get_user_gasmask(victim))
9874 {
9875 continue;
9876 }
9877
9878 // Last human is killed
9879 if (fnGetHumans() == 1)
9880 {
9881 ExecuteHamB(Ham_Killed, victim, attacker, 0);
9882
9883 continue;
9884 }
9885
9886 // Infected victim's sound
9887 ArrayGetString(grenade_infect_player, random_num(0, ArraySize(grenade_infect_player) - 1), sound, charsmax(sound))
9888 emit_sound(victim, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
9889
9890 // Turn into zombie
9891 zombieme(victim, attacker, 0, 0, 1, 1)
9892 }
9893
9894 // Get rid of the grenade
9895 engfunc(EngFunc_RemoveEntity, ent)
9896}
9897
9898// Fire Grenade Explosion
9899fire_explode(ent)
9900{
9901 // Get origin
9902 static Float:originF[3]
9903 pev(ent, pev_origin, originF)
9904
9905 // Make the explosion
9906 create_blast2(originF)
9907
9908 // Fire nade explode sound
9909 static sound[64]
9910 ArrayGetString(grenade_fire, random_num(0, ArraySize(grenade_fire) - 1), sound, charsmax(sound))
9911 emit_sound(ent, CHAN_WEAPON, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
9912
9913 // Collisions
9914 static victim
9915 victim = -1
9916
9917 while ((victim = engfunc(EngFunc_FindEntityInSphere, victim, originF, NADE_EXPLOSION_RADIUS)) != 0)
9918 {
9919 // Only effect alive zombies
9920 if (!is_user_valid_alive(victim) || !g_zombie[victim] || g_nodamage[victim])
9921 continue;
9922
9923 // Heat icon?
9924 if (get_pcvar_num(cvar_hudicons))
9925 {
9926 message_begin(MSG_ONE_UNRELIABLE, g_msgDamage, _, victim)
9927 write_byte(0) // damage save
9928 write_byte(0) // damage take
9929 write_long(DMG_BURN) // damage type
9930 write_coord(0) // x
9931 write_coord(0) // y
9932 write_coord(0) // z
9933 message_end()
9934 }
9935
9936 if (g_nemesis[victim] || g_assassin[victim]) // fire duration (nemesis is fire resistant)
9937 g_burning_duration[victim] += get_pcvar_num(cvar_fireduration)
9938 else
9939 g_burning_duration[victim] += get_pcvar_num(cvar_fireduration) * 5
9940
9941 // Set burning task on victim if not present
9942 if (!task_exists(victim+TASK_BURN))
9943 set_task(0.2, "burning_flame", victim+TASK_BURN, _, _, "b")
9944 }
9945
9946 // Get rid of the grenade
9947 engfunc(EngFunc_RemoveEntity, ent)
9948}
9949
9950// Frost Grenade Explosion
9951frost_explode(ent)
9952{
9953 // Get origin
9954 static Float:originF[3]
9955 pev(ent, pev_origin, originF)
9956
9957 // Make the explosion
9958 create_blast3(originF)
9959
9960 // Frost nade explode sound
9961 static sound[64]
9962 ArrayGetString(grenade_frost, random_num(0, ArraySize(grenade_frost) - 1), sound, charsmax(sound))
9963 emit_sound(ent, CHAN_WEAPON, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
9964
9965 // Collisions
9966 static victim
9967 victim = -1
9968
9969 while ((victim = engfunc(EngFunc_FindEntityInSphere, victim, originF, NADE_EXPLOSION_RADIUS)) != 0)
9970 {
9971 // Only effect alive unfrozen zombies
9972 if (!is_user_valid_alive(victim) || !g_zombie[victim] || g_frozen[victim] || g_nodamage[victim])
9973 continue;
9974
9975 // Nemesis shouldn't be frozen
9976 if (g_nemesis[victim] || g_assassin[victim])
9977 {
9978 // Get player's origin
9979 static origin2[3]
9980 get_user_origin(victim, origin2)
9981
9982 // Broken glass sound
9983 ArrayGetString(grenade_frost_break, random_num(0, ArraySize(grenade_frost_break) - 1), sound, charsmax(sound))
9984 emit_sound(victim, CHAN_BODY, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
9985
9986 // Glass shatter
9987 message_begin(MSG_PVS, SVC_TEMPENTITY, origin2)
9988 write_byte(TE_BREAKMODEL) // TE id
9989 write_coord(origin2[0]) // x
9990 write_coord(origin2[1]) // y
9991 write_coord(origin2[2]+24) // z
9992 write_coord(16) // size x
9993 write_coord(16) // size y
9994 write_coord(16) // size z
9995 write_coord(random_num(-50, 50)) // velocity x
9996 write_coord(random_num(-50, 50)) // velocity y
9997 write_coord(25) // velocity z
9998 write_byte(10) // random velocity
9999 write_short(g_glassSpr) // model
10000 write_byte(10) // count
10001 write_byte(25) // life
10002 write_byte(BREAK_GLASS) // flags
10003 message_end()
10004
10005 continue;
10006 }
10007
10008 // Freeze icon?
10009 if (get_pcvar_num(cvar_hudicons))
10010 {
10011 message_begin(MSG_ONE_UNRELIABLE, g_msgDamage, _, victim)
10012 write_byte(0) // damage save
10013 write_byte(0) // damage take
10014 write_long(DMG_DROWN) // damage type - DMG_FREEZE
10015 write_coord(0) // x
10016 write_coord(0) // y
10017 write_coord(0) // z
10018 message_end()
10019 }
10020
10021 // Light blue glow while frozen
10022 if (g_handle_models_on_separate_ent)
10023 fm_set_rendering(g_ent_playermodel[victim], kRenderFxGlowShell, 0, 100, 200, kRenderNormal, 25)
10024 else
10025 fm_set_rendering(victim, kRenderFxGlowShell, 0, 100, 200, kRenderNormal, 25)
10026
10027 // Freeze sound
10028 ArrayGetString(grenade_frost_player, random_num(0, ArraySize(grenade_frost_player) - 1), sound, charsmax(sound))
10029 emit_sound(victim, CHAN_BODY, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
10030
10031 // Add a blue tint to their screen
10032 message_begin(MSG_ONE, g_msgScreenFade, _, victim)
10033 write_short(0) // duration
10034 write_short(0) // hold time
10035 write_short(FFADE_STAYOUT) // fade type
10036 write_byte(0) // red
10037 write_byte(50) // green
10038 write_byte(200) // blue
10039 write_byte(100) // alpha
10040 message_end()
10041
10042 // Set the frozen flag
10043 g_frozen[victim] = true
10044
10045 // Save player's old gravity (bugfix)
10046 pev(victim, pev_gravity, g_frozen_gravity[victim])
10047
10048 // Prevent from jumping
10049 if (pev(victim, pev_flags) & FL_ONGROUND)
10050 set_pev(victim, pev_gravity, 999999.9) // set really high
10051 else
10052 set_pev(victim, pev_gravity, 0.000001) // no gravity
10053
10054 // Prevent from moving
10055 ExecuteHamB(Ham_Player_ResetMaxSpeed, victim)
10056
10057 // Set a task to remove the freeze
10058 set_task(get_pcvar_float(cvar_freezeduration), "remove_freeze", victim)
10059 }
10060
10061 // Get rid of the grenade
10062 engfunc(EngFunc_RemoveEntity, ent)
10063}
10064
10065// Remove freeze task
10066public remove_freeze(id)
10067{
10068 // Not alive or not frozen anymore
10069 if (!g_isalive[id] || !g_frozen[id])
10070 return;
10071
10072 // Unfreeze
10073 g_frozen[id] = false;
10074
10075 // Restore gravity and maxspeed (bugfix)
10076 set_pev(id, pev_gravity, g_frozen_gravity[id])
10077 ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
10078
10079 // Restore rendering
10080 if (g_handle_models_on_separate_ent)
10081 {
10082 // Nemesis or Survivor glow / remove glow on player model entity
10083 if (g_nemesis[id] && get_pcvar_num(cvar_nemglow))
10084 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 250, 0, 0, kRenderNormal, 25)
10085 else if (g_nemesis[id] && !(get_pcvar_num(cvar_nemglow)))
10086 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 0, 0, 0, kRenderNormal, 25)
10087 else if (g_assassin[id] && get_pcvar_num(cvar_assaglow))
10088 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 255, 255, 0, kRenderNormal, 25)
10089 else if (g_survivor[id] && get_pcvar_num(cvar_survglow))
10090 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 0, 0, 255, kRenderNormal, 25)
10091 else if (g_sniper[id] && get_pcvar_num(cvar_sniglow))
10092 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 0, 255, 0, kRenderNormal, 25)
10093 else
10094 fm_set_rendering(g_ent_playermodel[id])
10095 }
10096 else
10097 {
10098 // Nemesis or Survivor glow / remove glow
10099 if (g_nemesis[id] && get_pcvar_num(cvar_nemglow))
10100 fm_set_rendering(id, kRenderFxGlowShell, 250, 0, 0, kRenderNormal, 25)
10101 else if (g_nemesis[id] && !(get_pcvar_num(cvar_nemglow)))
10102 fm_set_rendering(id, kRenderFxGlowShell, 0, 0, 0, kRenderNormal, 25)
10103 else if (g_assassin[id] && get_pcvar_num(cvar_assaglow))
10104 fm_set_rendering(id, kRenderFxGlowShell, 255, 255, 0, kRenderNormal, 25)
10105 else if (g_survivor[id] && get_pcvar_num(cvar_survglow))
10106 fm_set_rendering(id, kRenderFxGlowShell, 0, 0, 255, kRenderNormal, 25)
10107 else if (g_sniper[id] && get_pcvar_num(cvar_sniglow))
10108 fm_set_rendering(id, kRenderFxGlowShell, 0, 255, 0, kRenderNormal, 25)
10109 else
10110 fm_set_rendering(id)
10111 }
10112
10113 // Gradually remove screen's blue tint
10114 message_begin(MSG_ONE, g_msgScreenFade, _, id)
10115 write_short(UNIT_SECOND) // duration
10116 write_short(0) // hold time
10117 write_short(FFADE_IN) // fade type
10118 write_byte(0) // red
10119 write_byte(50) // green
10120 write_byte(200) // blue
10121 write_byte(100) // alpha
10122 message_end()
10123
10124 // Broken glass sound
10125 static sound[64]
10126 ArrayGetString(grenade_frost_break, random_num(0, ArraySize(grenade_frost_break) - 1), sound, charsmax(sound))
10127 emit_sound(id, CHAN_BODY, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
10128
10129 // Get player's origin
10130 static origin2[3]
10131 get_user_origin(id, origin2)
10132
10133 // Glass shatter
10134 message_begin(MSG_PVS, SVC_TEMPENTITY, origin2)
10135 write_byte(TE_BREAKMODEL) // TE id
10136 write_coord(origin2[0]) // x
10137 write_coord(origin2[1]) // y
10138 write_coord(origin2[2]+24) // z
10139 write_coord(16) // size x
10140 write_coord(16) // size y
10141 write_coord(16) // size z
10142 write_coord(random_num(-50, 50)) // velocity x
10143 write_coord(random_num(-50, 50)) // velocity y
10144 write_coord(25) // velocity z
10145 write_byte(10) // random velocity
10146 write_short(g_glassSpr) // model
10147 write_byte(10) // count
10148 write_byte(25) // life
10149 write_byte(BREAK_GLASS) // flags
10150 message_end()
10151
10152 ExecuteForward(g_fwUserUnfrozen, g_fwDummyResult, id);
10153}
10154
10155// Remove Stuff Task
10156public remove_stuff()
10157{
10158 static ent
10159
10160 // Remove rotating doors
10161 if (get_pcvar_num(cvar_removedoors) > 0)
10162 {
10163 ent = -1;
10164 while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "func_door_rotating")) != 0)
10165 engfunc(EngFunc_SetOrigin, ent, Float:{8192.0 ,8192.0 ,8192.0})
10166 }
10167
10168 // Remove all doors
10169 if (get_pcvar_num(cvar_removedoors) > 1)
10170 {
10171 ent = -1;
10172 while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "func_door")) != 0)
10173 engfunc(EngFunc_SetOrigin, ent, Float:{8192.0 ,8192.0 ,8192.0})
10174 }
10175
10176 // Triggered lights
10177 if (!get_pcvar_num(cvar_triggered))
10178 {
10179 ent = -1
10180 while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "light")) != 0)
10181 {
10182 dllfunc(DLLFunc_Use, ent, 0); // turn off the light
10183 set_pev(ent, pev_targetname, 0) // prevent it from being triggered
10184 }
10185 }
10186}
10187
10188// Set Custom Weapon Models
10189replace_weapon_models(id, weaponid)
10190{
10191 switch (weaponid)
10192 {
10193 case CSW_KNIFE: // Custom knife models
10194 {
10195 if (g_zombie[id])
10196 {
10197 if (g_nemesis[id]) // Nemesis
10198 {
10199 set_pev(id, pev_viewmodel2, model_vknife_nemesis)
10200 set_pev(id, pev_weaponmodel2, "")
10201 }
10202 else if (g_assassin[id]) // Assassins
10203 {
10204 set_pev(id, pev_viewmodel2, model_vknife_assassin)
10205 set_pev(id, pev_weaponmodel2, "")
10206 }
10207 else // Zombies
10208 {
10209 // Admin knife models?
10210 if (get_pcvar_num(cvar_adminknifemodelszombie) && get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS])
10211 {
10212 set_pev(id, pev_viewmodel2, model_vknife_admin_zombie)
10213 set_pev(id, pev_weaponmodel2, "")
10214 }
10215 else
10216 {
10217 static clawmodel[100]
10218 ArrayGetString(g_zclass_clawmodel, g_zombieclass[id], clawmodel, charsmax(clawmodel))
10219 format(clawmodel, charsmax(clawmodel), "models/zombie_plague/%s", clawmodel)
10220 set_pev(id, pev_viewmodel2, clawmodel)
10221 set_pev(id, pev_weaponmodel2, "")
10222 }
10223 }
10224 }
10225 else // Humans
10226 {
10227 // Admin knife models?
10228 if (get_pcvar_num(cvar_adminknifemodelshuman) && get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS])
10229 {
10230 set_pev(id, pev_viewmodel2, model_vknife_admin_human)
10231 set_pev(id, pev_weaponmodel2, "models/p_knife.mdl")
10232 }
10233 else
10234 {
10235 set_pev(id, pev_viewmodel2, model_vknife_human)
10236 set_pev(id, pev_weaponmodel2, "models/p_knife.mdl")
10237 }
10238 }
10239 }
10240 case CSW_AWP: // Sniper's AWP
10241 {
10242 if (g_sniper[id])
10243 {
10244 set_pev(id, pev_viewmodel2, model_vawp_sniper)
10245 set_pev(id, pev_weaponmodel2, model_pawp_sniper)
10246 }
10247 }
10248 case CSW_HEGRENADE: // Infection bomb or fire grenade
10249 {
10250 if (g_zombie[id])
10251 set_pev(id, pev_viewmodel2, model_grenade_infect)
10252 else
10253 set_pev(id, pev_viewmodel2, model_grenade_fire)
10254 }
10255 case CSW_FLASHBANG: // Frost grenade
10256 {
10257 set_pev(id, pev_viewmodel2, model_grenade_frost)
10258 }
10259 case CSW_SMOKEGRENADE: // Flare grenade
10260 {
10261 set_pev(id, pev_viewmodel2, model_grenade_flare)
10262 }
10263 }
10264
10265 // Update model on weaponmodel ent
10266 if (g_handle_models_on_separate_ent) fm_set_weaponmodel_ent(id)
10267}
10268
10269// Reset Player Vars
10270reset_vars(id, resetall)
10271{
10272 g_zombie[id] = false
10273 g_nemesis[id] = false
10274 g_assassin[id] = false
10275 g_survivor[id] = false
10276 g_sniper[id] = false
10277 g_firstzombie[id] = false
10278 g_lastzombie[id] = false
10279 g_lasthuman[id] = false
10280 g_frozen[id] = false
10281 g_nodamage[id] = false
10282 g_respawn_as_zombie[id] = false
10283 g_nvision[id] = false
10284 g_nvisionenabled[id] = false
10285 g_flashlight[id] = false
10286 g_flashbattery[id] = 100
10287 g_canbuy[id] = true
10288 g_burning_duration[id] = 0
10289
10290 if (resetall)
10291 {
10292 g_ammopacks[id] = get_pcvar_num(cvar_startammopacks)
10293 g_zombieclass[id] = ZCLASS_NONE
10294 g_zombieclassnext[id] = ZCLASS_NONE
10295 g_damagedealt_human[id] = 0
10296 g_damagedealt_zombie[id] = 0
10297 WPN_AUTO_ON = 0
10298 WPN_STARTID = 0
10299 PL_ACTION = 0
10300 MENU_PAGE_ZCLASS = 0
10301 MENU_PAGE_EXTRAS = 0
10302 MENU_PAGE_PLAYERS = 0
10303 }
10304}
10305
10306// Set spectators nightvision
10307public spec_nvision(id)
10308{
10309 // Not connected, alive, or bot
10310 if (!g_isconnected[id] || g_isalive[id] || g_isbot[id])
10311 return;
10312
10313 // Give Night Vision?
10314 if (get_pcvar_num(cvar_nvggive))
10315 {
10316 g_nvision[id] = true
10317
10318 // Turn on Night Vision automatically?
10319 if (get_pcvar_num(cvar_nvggive) == 1)
10320 {
10321 g_nvisionenabled[id] = true
10322
10323 // Custom nvg?
10324 if (get_pcvar_num(cvar_customnvg))
10325 {
10326 remove_task(id+TASK_NVISION)
10327 set_task(0.1, "set_user_nvision", id+TASK_NVISION, _, _, "b")
10328 }
10329 else
10330 set_user_gnvision(id, 1)
10331 }
10332 }
10333}
10334
10335// Show HUD Task
10336public ShowHUD(taskid)
10337{
10338 static id
10339 id = ID_SHOWHUD;
10340
10341 // Player died?
10342 if (!g_isalive[id])
10343 {
10344 // Get spectating target
10345 id = pev(id, PEV_SPEC_TARGET)
10346
10347 // Target not alive
10348 if (!g_isalive[id]) return;
10349 }
10350
10351 // Format classname
10352 static class[32], red, green, blue
10353
10354 if (g_zombie[id]) // zombies
10355 {
10356 red = 200
10357 green = 250
10358 blue = 0
10359
10360 if (g_nemesis[id])
10361 formatex(class, charsmax(class), "%L", ID_SHOWHUD, "CLASS_NEMESIS")
10362 else if (g_assassin[id])
10363 formatex(class, charsmax(class), "%L", ID_SHOWHUD, "CLASS_ASSASSIN")
10364 else
10365 copy(class, charsmax(class), g_zombie_classname[id])
10366 }
10367 else // humans
10368 {
10369 red = 20
10370 green = 135
10371 blue = 255
10372
10373 if (g_survivor[id])
10374 formatex(class, charsmax(class), "%L", ID_SHOWHUD, "CLASS_SURVIVOR")
10375 else if (g_sniper[id])
10376 formatex(class, charsmax(class), "%L", ID_SHOWHUD, "CLASS_SNIPER")
10377 else
10378 formatex(class, charsmax(class), "%L", ID_SHOWHUD, "CLASS_HUMAN")
10379 }
10380
10381 // Spectating someone else?
10382 if (id != ID_SHOWHUD)
10383 {
10384 // Show name, health, class, and ammo packs
10385 set_hudmessage(20, 184, 62, HUD_SPECT_X, HUD_SPECT_Y, 0, 6.0, 1.1, 0.0, 0.0, -1)
10386 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))
10387 }
10388 else
10389 {
10390 // Show health, class and ammo packs
10391 set_hudmessage(red, green, blue, 0.02, 0.18, 0, 6.0, 1.1, 0.0, 0.0, -1)
10392 ShowSyncHudMsg(ID_SHOWHUD, g_MsgSync2, "[%L: %d] ^n[%L %s] ^n[%L %d] ^n[%L %d]", 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))
10393 }
10394}
10395
10396// Play idle zombie sounds
10397public zombie_play_idle(taskid)
10398{
10399 // Round ended/new one starting
10400 if (g_endround || g_newround)
10401 return;
10402
10403 static sound[64]
10404
10405 // Last zombie?
10406 if (g_lastzombie[ID_BLOOD])
10407 {
10408 ArrayGetString(zombie_idle_last, random_num(0, ArraySize(zombie_idle_last) - 1), sound, charsmax(sound))
10409 emit_sound(ID_BLOOD, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
10410 }
10411 else
10412 {
10413 ArrayGetString(zombie_idle, random_num(0, ArraySize(zombie_idle) - 1), sound, charsmax(sound))
10414 emit_sound(ID_BLOOD, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
10415 }
10416}
10417
10418// Madness Over Task
10419public madness_over(taskid)
10420{
10421 g_nodamage[ID_BLOOD] = false
10422}
10423
10424// Place user at a random spawn
10425do_random_spawn(id, regularspawns = 0)
10426{
10427 static hull, sp_index, i
10428
10429 // Get whether the player is crouching
10430 hull = (pev(id, pev_flags) & FL_DUCKING) ? HULL_HEAD : HULL_HUMAN
10431
10432 // Use regular spawns?
10433 if (!regularspawns)
10434 {
10435 // No spawns?
10436 if (!g_spawnCount)
10437 return;
10438
10439 // Choose random spawn to start looping at
10440 sp_index = random_num(0, g_spawnCount - 1)
10441
10442 // Try to find a clear spawn
10443 for (i = sp_index + 1; /*no condition*/; i++)
10444 {
10445 // Start over when we reach the end
10446 if (i >= g_spawnCount) i = 0
10447
10448 // Free spawn space?
10449 if (is_hull_vacant(g_spawns[i], hull))
10450 {
10451 // Engfunc_SetOrigin is used so ent's mins and maxs get updated instantly
10452 engfunc(EngFunc_SetOrigin, id, g_spawns[i])
10453 break;
10454 }
10455
10456 // Loop completed, no free space found
10457 if (i == sp_index) break;
10458 }
10459 }
10460 else
10461 {
10462 // No spawns?
10463 if (!g_spawnCount2)
10464 return;
10465
10466 // Choose random spawn to start looping at
10467 sp_index = random_num(0, g_spawnCount2 - 1)
10468
10469 // Try to find a clear spawn
10470 for (i = sp_index + 1; /*no condition*/; i++)
10471 {
10472 // Start over when we reach the end
10473 if (i >= g_spawnCount2) i = 0
10474
10475 // Free spawn space?
10476 if (is_hull_vacant(g_spawns2[i], hull))
10477 {
10478 // Engfunc_SetOrigin is used so ent's mins and maxs get updated instantly
10479 engfunc(EngFunc_SetOrigin, id, g_spawns2[i])
10480 break;
10481 }
10482
10483 // Loop completed, no free space found
10484 if (i == sp_index) break;
10485 }
10486 }
10487}
10488
10489// Get Zombies -returns alive zombies number-
10490fnGetZombies()
10491{
10492 static iZombies, id
10493 iZombies = 0
10494
10495 for (id = 1; id <= g_maxplayers; id++)
10496 {
10497 if (g_isalive[id] && g_zombie[id])
10498 iZombies++
10499 }
10500
10501 return iZombies;
10502}
10503
10504// Get Humans -returns alive humans number-
10505fnGetHumans()
10506{
10507 static iHumans, id
10508 iHumans = 0
10509
10510 for (id = 1; id <= g_maxplayers; id++)
10511 {
10512 if (g_isalive[id] && !g_zombie[id])
10513 iHumans++
10514 }
10515
10516 return iHumans;
10517}
10518
10519// Get Nemesis -returns alive nemesis number-
10520fnGetNemesis()
10521{
10522 static iNemesis, id
10523 iNemesis = 0
10524
10525 for (id = 1; id <= g_maxplayers; id++)
10526 {
10527 if (g_isalive[id] && g_nemesis[id])
10528 iNemesis++
10529 }
10530
10531 return iNemesis;
10532}
10533
10534// Get Assassin -returns alive assassin number-
10535fnGetAssassin()
10536{
10537 static iAssassin, id
10538 iAssassin = 0
10539
10540 for (id = 1; id <= g_maxplayers; id++)
10541 {
10542 if (g_isalive[id] && g_assassin[id])
10543 iAssassin++
10544 }
10545
10546 return iAssassin;
10547}
10548
10549// Get Survivors -returns alive survivors number-
10550fnGetSurvivors()
10551{
10552 static iSurvivors, id
10553 iSurvivors = 0
10554
10555 for (id = 1; id <= g_maxplayers; id++)
10556 {
10557 if (g_isalive[id] && g_survivor[id])
10558 iSurvivors++
10559 }
10560
10561 return iSurvivors;
10562}
10563
10564// Get Snipers -returns alive snipers number-
10565fnGetSnipers()
10566{
10567 static iSnipers, id
10568 iSnipers = 0
10569
10570 for (id = 1; id <= g_maxplayers; id++)
10571 {
10572 if (g_isalive[id] && g_sniper[id])
10573 iSnipers++
10574 }
10575
10576 return iSnipers;
10577}
10578
10579// Get Alive -returns alive players number-
10580fnGetAlive()
10581{
10582 static iAlive, id
10583 iAlive = 0
10584
10585 for (id = 1; id <= g_maxplayers; id++)
10586 {
10587 if (g_isalive[id])
10588 iAlive++
10589 }
10590
10591 return iAlive;
10592}
10593
10594// Get Random Alive -returns index of alive player number n -
10595fnGetRandomAlive(n)
10596{
10597 static iAlive, id
10598 iAlive = 0
10599
10600 for (id = 1; id <= g_maxplayers; id++)
10601 {
10602 if (g_isalive[id])
10603 iAlive++
10604
10605 if (iAlive == n)
10606 return id;
10607 }
10608
10609 return -1;
10610}
10611
10612// Get Playing -returns number of users playing-
10613fnGetPlaying()
10614{
10615 static iPlaying, id, team
10616 iPlaying = 0
10617
10618 for (id = 1; id <= g_maxplayers; id++)
10619 {
10620 if (g_isconnected[id])
10621 {
10622 team = fm_cs_get_user_team(id)
10623
10624 if (team != FM_CS_TEAM_SPECTATOR && team != FM_CS_TEAM_UNASSIGNED)
10625 iPlaying++
10626 }
10627 }
10628
10629 return iPlaying;
10630}
10631
10632// Get CTs -returns number of CTs connected-
10633fnGetCTs()
10634{
10635 static iCTs, id
10636 iCTs = 0
10637
10638 for (id = 1; id <= g_maxplayers; id++)
10639 {
10640 if (g_isconnected[id])
10641 {
10642 if (fm_cs_get_user_team(id) == FM_CS_TEAM_CT)
10643 iCTs++
10644 }
10645 }
10646
10647 return iCTs;
10648}
10649
10650// Get Ts -returns number of Ts connected-
10651fnGetTs()
10652{
10653 static iTs, id
10654 iTs = 0
10655
10656 for (id = 1; id <= g_maxplayers; id++)
10657 {
10658 if (g_isconnected[id])
10659 {
10660 if (fm_cs_get_user_team(id) == FM_CS_TEAM_T)
10661 iTs++
10662 }
10663 }
10664
10665 return iTs;
10666}
10667
10668// Get Alive CTs -returns number of CTs alive-
10669fnGetAliveCTs()
10670{
10671 static iCTs, id
10672 iCTs = 0
10673
10674 for (id = 1; id <= g_maxplayers; id++)
10675 {
10676 if (g_isalive[id])
10677 {
10678 if (fm_cs_get_user_team(id) == FM_CS_TEAM_CT)
10679 iCTs++
10680 }
10681 }
10682
10683 return iCTs;
10684}
10685
10686// Get Alive Ts -returns number of Ts alive-
10687fnGetAliveTs()
10688{
10689 static iTs, id
10690 iTs = 0
10691
10692 for (id = 1; id <= g_maxplayers; id++)
10693 {
10694 if (g_isalive[id])
10695 {
10696 if (fm_cs_get_user_team(id) == FM_CS_TEAM_T)
10697 iTs++
10698 }
10699 }
10700
10701 return iTs;
10702}
10703
10704// Last Zombie Check -check for last zombie and set its flag-
10705fnCheckLastZombie()
10706{
10707 static id
10708 for (id = 1; id <= g_maxplayers; id++)
10709 {
10710 // Last zombie
10711 if (g_isalive[id] && g_zombie[id] && !g_nemesis[id] && !g_assassin[id] && fnGetZombies() == 1)
10712 {
10713 if (!g_lastzombie[id])
10714 {
10715 // Last zombie forward
10716 ExecuteForward(g_fwUserLastZombie, g_fwDummyResult, id);
10717 }
10718 g_lastzombie[id] = true
10719 }
10720 else
10721 g_lastzombie[id] = false
10722
10723 // Last human
10724 if (g_isalive[id] && !g_zombie[id] && !g_survivor[id] && !g_sniper[id] && fnGetHumans() == 1)
10725 {
10726 if (!g_lasthuman[id])
10727 {
10728 // Last human forward
10729 ExecuteForward(g_fwUserLastHuman, g_fwDummyResult, id);
10730
10731 // Reward extra hp
10732 fm_set_user_health(id, pev(id, pev_health) + get_pcvar_num(cvar_humanlasthp))
10733 }
10734 g_lasthuman[id] = true
10735 }
10736 else
10737 g_lasthuman[id] = false
10738 }
10739}
10740
10741// Save player's stats to database
10742save_stats(id)
10743{
10744 // Check whether there is another record already in that slot
10745 if (db_name[id][0] && !equal(g_playername[id], db_name[id]))
10746 {
10747 // If DB size is exceeded, write over old records
10748 if (db_slot_i >= sizeof db_name)
10749 db_slot_i = g_maxplayers+1
10750
10751 // Move previous record onto an additional save slot
10752 copy(db_name[db_slot_i], charsmax(db_name[]), db_name[id])
10753 db_ammopacks[db_slot_i] = db_ammopacks[id]
10754 db_zombieclass[db_slot_i] = db_zombieclass[id]
10755 db_slot_i++
10756 }
10757
10758 // Now save the current player stats
10759 copy(db_name[id], charsmax(db_name[]), g_playername[id]) // name
10760 db_ammopacks[id] = g_ammopacks[id] // ammo packs
10761 db_zombieclass[id] = g_zombieclassnext[id] // zombie class
10762}
10763
10764// Load player's stats from database (if a record is found)
10765load_stats(id)
10766{
10767 // Look for a matching record
10768 static i
10769 for (i = 0; i < sizeof db_name; i++)
10770 {
10771 if (equal(g_playername[id], db_name[i]))
10772 {
10773 // Bingo!
10774 g_ammopacks[id] = db_ammopacks[i]
10775 g_zombieclass[id] = db_zombieclass[i]
10776 g_zombieclassnext[id] = db_zombieclass[i]
10777 return;
10778 }
10779 }
10780}
10781
10782// Checks if a player is allowed to be zombie
10783allowed_zombie(id)
10784{
10785 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))
10786 return false;
10787
10788 return true;
10789}
10790
10791// Checks if a player is allowed to be human
10792allowed_human(id)
10793{
10794 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))
10795 return false;
10796
10797 return true;
10798}
10799
10800// Checks if a player is allowed to be survivor
10801allowed_survivor(id)
10802{
10803 if (g_endround || g_survivor[id] || !g_isalive[id] || task_exists(TASK_WELCOMEMSG) || (!g_newround && g_zombie[id] && fnGetZombies() == 1))
10804 return false;
10805
10806 return true;
10807}
10808
10809// Checks if a player is allowed to be sniper
10810allowed_sniper(id)
10811{
10812 if (g_endround || g_sniper[id] || !g_isalive[id] || task_exists(TASK_WELCOMEMSG) || (!g_newround && g_zombie[id] && fnGetZombies() == 1))
10813 return false;
10814
10815 return true;
10816}
10817
10818// Checks if a player is allowed to be nemesis
10819allowed_nemesis(id)
10820{
10821 if (g_endround || g_nemesis[id] || !g_isalive[id] || task_exists(TASK_WELCOMEMSG) || (!g_newround && !g_zombie[id] && fnGetHumans() == 1))
10822 return false;
10823
10824 return true;
10825}
10826
10827// Checks if a player is allowed to be assassin
10828allowed_assassin(id)
10829{
10830 if (g_endround || g_assassin[id] || !g_isalive[id] || task_exists(TASK_WELCOMEMSG) || (!g_newround && !g_zombie[id] && fnGetHumans() == 1))
10831 return false;
10832
10833 return true;
10834}
10835
10836// Checks if a player is allowed to respawn
10837allowed_respawn(id)
10838{
10839 static team
10840 team = fm_cs_get_user_team(id)
10841
10842 if (g_endround || team == FM_CS_TEAM_SPECTATOR || team == FM_CS_TEAM_UNASSIGNED || g_isalive[id])
10843 return false;
10844
10845 return true;
10846}
10847
10848// Checks if swarm mode is allowed
10849allowed_swarm()
10850{
10851 if (g_endround || !g_newround || task_exists(TASK_WELCOMEMSG))
10852 return false;
10853
10854 return true;
10855}
10856
10857// Checks if multi infection mode is allowed
10858allowed_multi()
10859{
10860 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())
10861 return false;
10862
10863 return true;
10864}
10865
10866// Checks if plague mode is allowed
10867allowed_plague()
10868{
10869 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
10870 || 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)
10871 return false;
10872
10873 return true;
10874}
10875
10876// Checks if armageddon mode is allowed
10877allowed_armageddon()
10878{
10879 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())
10880 return false;
10881
10882 return true;
10883}
10884
10885// Checks if apocalypse mode is allowed
10886allowed_apocalypse()
10887{
10888 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())
10889 return false;
10890
10891 return true;
10892}
10893
10894// Checks if nightmare mode is allowed
10895allowed_nightmare()
10896{
10897 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())
10898 return false;
10899
10900 return true;
10901}
10902
10903// Admin Command. zp_zombie
10904command_zombie(id, player)
10905{
10906 // Show activity?
10907 switch (get_pcvar_num(cvar_showactivity))
10908 {
10909 case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_INFECT")
10910 case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_INFECT")
10911 }
10912
10913 // Log to Zombie Plague log file?
10914 if (get_pcvar_num(cvar_logcommands))
10915 {
10916 static logdata[100], authid[32], ip[16]
10917 get_user_authid(id, authid, charsmax(authid))
10918 get_user_ip(id, ip, charsmax(ip), 1)
10919 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)
10920 log_to_file("zombieplague.log", logdata)
10921 }
10922
10923 // New round?
10924 if (g_newround)
10925 {
10926 // Set as first zombie
10927 remove_task(TASK_MAKEZOMBIE)
10928 make_a_zombie(MODE_INFECTION, player)
10929 }
10930 else
10931 {
10932 // Just infect
10933 zombieme(player, 0, 0, 0, 0, 0)
10934 }
10935}
10936
10937// Admin Command. zp_human
10938command_human(id, player)
10939{
10940 // Show activity?
10941 switch (get_pcvar_num(cvar_showactivity))
10942 {
10943 case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_DISINFECT")
10944 case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_DISINFECT")
10945 }
10946
10947 // Log to Zombie Plague log file?
10948 if (get_pcvar_num(cvar_logcommands))
10949 {
10950 static logdata[100], authid[32], ip[16]
10951 get_user_authid(id, authid, charsmax(authid))
10952 get_user_ip(id, ip, charsmax(ip), 1)
10953 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)
10954 log_to_file("zombieplague.log", logdata)
10955 }
10956
10957 // Turn to human
10958 humanme(player, 0, 0, 0)
10959}
10960
10961// Admin Command. zp_survivor
10962command_survivor(id, player)
10963{
10964 // Show activity?
10965 switch (get_pcvar_num(cvar_showactivity))
10966 {
10967 case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_SURVIVAL")
10968 case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_SURVIVAL")
10969 }
10970
10971 // Log to Zombie Plague log file?
10972 if (get_pcvar_num(cvar_logcommands))
10973 {
10974 static logdata[100], authid[32], ip[16]
10975 get_user_authid(id, authid, charsmax(authid))
10976 get_user_ip(id, ip, charsmax(ip), 1)
10977 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)
10978 log_to_file("zombieplague.log", logdata)
10979 }
10980
10981 // New round?
10982 if (g_newround)
10983 {
10984 // Set as first survivor
10985 remove_task(TASK_MAKEZOMBIE)
10986 make_a_zombie(MODE_SURVIVOR, player)
10987 }
10988 else
10989 {
10990 // Turn player into a Survivor
10991 humanme(player, 1, 0, 0)
10992 }
10993}
10994
10995// Admin Command. zp_sniper
10996command_sniper(id, player)
10997{
10998 // Show activity?
10999 switch (get_pcvar_num(cvar_showactivity))
11000 {
11001 case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_SNIPER")
11002 case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_SNIPER")
11003 }
11004
11005 // Log to Zombie Plague log file?
11006 if (get_pcvar_num(cvar_logcommands))
11007 {
11008 static logdata[100], authid[32], ip[16]
11009 get_user_authid(id, authid, charsmax(authid))
11010 get_user_ip(id, ip, charsmax(ip), 1)
11011 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)
11012 log_to_file("zombieplague.log", logdata)
11013 }
11014
11015 // New round?
11016 if (g_newround)
11017 {
11018 // Set as first sniper
11019 remove_task(TASK_MAKEZOMBIE)
11020 make_a_zombie(MODE_SNIPER, player)
11021 }
11022 else
11023 {
11024 // Turn player into a Sniper
11025 humanme(player, 0, 1, 0)
11026 }
11027}
11028
11029// Admin Command. zp_nemesis
11030command_nemesis(id, player)
11031{
11032 // Show activity?
11033 switch (get_pcvar_num(cvar_showactivity))
11034 {
11035 case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_NEMESIS")
11036 case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_NEMESIS")
11037 }
11038
11039 // Log to Zombie Plague log file?
11040 if (get_pcvar_num(cvar_logcommands))
11041 {
11042 static logdata[100], authid[32], ip[16]
11043 get_user_authid(id, authid, charsmax(authid))
11044 get_user_ip(id, ip, charsmax(ip), 1)
11045 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)
11046 log_to_file("zombieplague.log", logdata)
11047 }
11048
11049 // New round?
11050 if (g_newround)
11051 {
11052 // Set as first nemesis
11053 remove_task(TASK_MAKEZOMBIE)
11054 make_a_zombie(MODE_NEMESIS, player)
11055 }
11056 else
11057 {
11058 // Turn player into a Nemesis
11059 zombieme(player, 0, 1, 0, 0, 0)
11060 }
11061}
11062
11063// Admin Command. zp_assassin
11064command_assassin(id, player)
11065{
11066 // Show activity?
11067 switch (get_pcvar_num(cvar_showactivity))
11068 {
11069 case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_ASSASSIN")
11070 case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_ASSASSIN")
11071 }
11072
11073 // Log to Zombie Plague log file?
11074 if (get_pcvar_num(cvar_logcommands))
11075 {
11076 static logdata[100], authid[32], ip[16]
11077 get_user_authid(id, authid, charsmax(authid))
11078 get_user_ip(id, ip, charsmax(ip), 1)
11079 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)
11080 log_to_file("zombieplague.log", logdata)
11081 }
11082
11083 // New round?
11084 if (g_newround)
11085 {
11086 // Set as first assassin
11087 remove_task(TASK_MAKEZOMBIE)
11088 make_a_zombie(MODE_ASSASSIN, player)
11089 }
11090 else
11091 {
11092 // Turn player into a Assassin
11093 zombieme(player, 0, 0, 1, 0, 0)
11094 }
11095}
11096
11097// Admin Command. zp_respawn
11098command_respawn(id, player)
11099{
11100 // Show activity?
11101 switch (get_pcvar_num(cvar_showactivity))
11102 {
11103 case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_RESPAWN")
11104 case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_RESPAWN")
11105 }
11106
11107 // Log to Zombie Plague log file?
11108 if (get_pcvar_num(cvar_logcommands))
11109 {
11110 static logdata[100], authid[32], ip[16]
11111 get_user_authid(id, authid, charsmax(authid))
11112 get_user_ip(id, ip, charsmax(ip), 1)
11113 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)
11114 log_to_file("zombieplague.log", logdata)
11115 }
11116
11117 // Respawn as zombie?
11118 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))
11119 g_respawn_as_zombie[player] = true
11120
11121 // Override respawn as zombie setting on nemesis and survivor rounds
11122 if (g_survround) g_respawn_as_zombie[player] = true
11123 else if (g_nemround) g_respawn_as_zombie[player] = false
11124
11125 respawn_player_manually(player);
11126}
11127
11128// Admin Command. zp_swarm
11129command_swarm(id)
11130{
11131 // Show activity?
11132 switch (get_pcvar_num(cvar_showactivity))
11133 {
11134 case 1: client_print(0, print_chat, "ADMIN - %L", LANG_PLAYER, "CMD_SWARM")
11135 case 2: client_print(0, print_chat, "ADMIN %s - %L", g_playername[id], LANG_PLAYER, "CMD_SWARM")
11136 }
11137
11138 // Log to Zombie Plague log file?
11139 if (get_pcvar_num(cvar_logcommands))
11140 {
11141 static logdata[100], authid[32], ip[16]
11142 get_user_authid(id, authid, charsmax(authid))
11143 get_user_ip(id, ip, charsmax(ip), 1)
11144 formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %L (Players: %d/%d)", g_playername[id], authid, ip, LANG_SERVER, "CMD_SWARM", fnGetPlaying(), g_maxplayers)
11145 log_to_file("zombieplague.log", logdata)
11146 }
11147
11148 // Call Swarm Mode
11149 remove_task(TASK_MAKEZOMBIE)
11150 make_a_zombie(MODE_SWARM, 0)
11151}
11152
11153// Admin Command. zp_multi
11154command_multi(id)
11155{
11156 // Show activity?
11157 switch (get_pcvar_num(cvar_showactivity))
11158 {
11159 case 1: client_print(0, print_chat, "ADMIN - %L", LANG_PLAYER, "CMD_MULTI")
11160 case 2: client_print(0, print_chat, "ADMIN %s - %L", g_playername[id], LANG_PLAYER, "CMD_MULTI")
11161 }
11162
11163 // Log to Zombie Plague log file?
11164 if (get_pcvar_num(cvar_logcommands))
11165 {
11166 static logdata[100], authid[32], ip[16]
11167 get_user_authid(id, authid, charsmax(authid))
11168 get_user_ip(id, ip, charsmax(ip), 1)
11169 formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %L (Players: %d/%d)", g_playername[id], authid, ip, LANG_SERVER,"CMD_MULTI", fnGetPlaying(), g_maxplayers)
11170 log_to_file("zombieplague.log", logdata)
11171 }
11172
11173 // Call Multi Infection
11174 remove_task(TASK_MAKEZOMBIE)
11175 make_a_zombie(MODE_MULTI, 0)
11176}
11177
11178// Admin Command. zp_plague
11179command_plague(id)
11180{
11181 // Show activity?
11182 switch (get_pcvar_num(cvar_showactivity))
11183 {
11184 case 1: client_print(0, print_chat, "ADMIN - %L", LANG_PLAYER, "CMD_PLAGUE")
11185 case 2: client_print(0, print_chat, "ADMIN %s - %L", g_playername[id], LANG_PLAYER, "CMD_PLAGUE")
11186 }
11187
11188 // Log to Zombie Plague log file?
11189 if (get_pcvar_num(cvar_logcommands))
11190 {
11191 static logdata[100], authid[32], ip[16]
11192 get_user_authid(id, authid, charsmax(authid))
11193 get_user_ip(id, ip, charsmax(ip), 1)
11194 formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %L (Players: %d/%d)", g_playername[id], authid, ip, LANG_SERVER,"CMD_PLAGUE", fnGetPlaying(), g_maxplayers)
11195 log_to_file("zombieplague.log", logdata)
11196 }
11197
11198 // Call Plague Mode
11199 remove_task(TASK_MAKEZOMBIE)
11200 make_a_zombie(MODE_PLAGUE, 0)
11201}
11202
11203// Admin Command. zp_armageddon
11204command_armageddon(id)
11205{
11206 // Show activity?
11207 switch (get_pcvar_num(cvar_showactivity))
11208 {
11209 case 1: client_print(0, print_chat, "ADMIN - %L", LANG_PLAYER, "CMD_ARMAGEDDON")
11210 case 2: client_print(0, print_chat, "ADMIN %s - %L", g_playername[id], LANG_PLAYER, "CMD_ARMAGEDDON")
11211 }
11212
11213 // Log to Zombie Plague log file?
11214 if (get_pcvar_num(cvar_logcommands))
11215 {
11216 static logdata[100], authid[32], ip[16]
11217 get_user_authid(id, authid, charsmax(authid))
11218 get_user_ip(id, ip, charsmax(ip), 1)
11219 formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %L (Players: %d/%d)", g_playername[id], authid, ip, LANG_SERVER,"CMD_ARMAGEDDON", fnGetPlaying(), g_maxplayers)
11220 log_to_file("zombieplague.log", logdata)
11221 }
11222
11223 // Call Armageddon Mode
11224 remove_task(TASK_MAKEZOMBIE)
11225 make_a_zombie(MODE_ARMAGEDDON, 0)
11226}
11227
11228// Admin Command. zp_apocalypse
11229command_apocalypse(id)
11230{
11231 // Show activity?
11232 switch (get_pcvar_num(cvar_showactivity))
11233 {
11234 case 1: client_print(0, print_chat, "ADMIN - %L", LANG_PLAYER, "CMD_APOCALYPSE")
11235 case 2: client_print(0, print_chat, "ADMIN %s - %L", g_playername[id], LANG_PLAYER, "CMD_APOCALYPSE")
11236 }
11237
11238 // Log to Zombie Plague log file?
11239 if (get_pcvar_num(cvar_logcommands))
11240 {
11241 static logdata[100], authid[32], ip[16]
11242 get_user_authid(id, authid, charsmax(authid))
11243 get_user_ip(id, ip, charsmax(ip), 1)
11244 formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %L (Players: %d/%d)", g_playername[id], authid, ip, LANG_SERVER,"CMD_APOCALYPSE", fnGetPlaying(), g_maxplayers)
11245 log_to_file("zombieplague.log", logdata)
11246 }
11247
11248 // Call Apocalypse Mode
11249 remove_task(TASK_MAKEZOMBIE)
11250 make_a_zombie(MODE_APOCALYPSE, 0)
11251}
11252
11253// Admin Command. zp_nightmare
11254command_nightmare(id)
11255{
11256 // Show activity?
11257 switch (get_pcvar_num(cvar_showactivity))
11258 {
11259 case 1: client_print(0, print_chat, "ADMIN - %L", LANG_PLAYER, "CMD_NIGHTMARE")
11260 case 2: client_print(0, print_chat, "ADMIN %s - %L", g_playername[id], LANG_PLAYER, "CMD_NIGHTMARE")
11261 }
11262
11263 // Log to Zombie Plague log file?
11264 if (get_pcvar_num(cvar_logcommands))
11265 {
11266 static logdata[100], authid[32], ip[16]
11267 get_user_authid(id, authid, charsmax(authid))
11268 get_user_ip(id, ip, charsmax(ip), 1)
11269 formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %L (Players: %d/%d)", g_playername[id], authid, ip, LANG_SERVER,"CMD_NIGHTMARE", fnGetPlaying(), g_maxplayers)
11270 log_to_file("zombieplague.log", logdata)
11271 }
11272
11273 // Call Nightmare Mode
11274 remove_task(TASK_MAKEZOMBIE)
11275 make_a_zombie(MODE_NIGHTMARE, 0)
11276}
11277
11278// Set proper maxspeed for player
11279set_player_maxspeed(id)
11280{
11281 // If frozen, prevent from moving
11282 if (g_frozen[id])
11283 {
11284 set_pev(id, pev_maxspeed, 1.0)
11285 }
11286 // Otherwise, set maxspeed directly
11287 else
11288 {
11289 if (g_zombie[id])
11290 {
11291 if (g_nemesis[id])
11292 set_pev(id, pev_maxspeed, get_pcvar_float(cvar_nemspd))
11293 else if (g_assassin[id])
11294 set_pev(id, pev_maxspeed, get_pcvar_float(cvar_assaspd))
11295 else
11296 set_pev(id, pev_maxspeed, g_zombie_spd[id])
11297 }
11298 else
11299 {
11300 if (g_survivor[id])
11301 set_pev(id, pev_maxspeed, get_pcvar_float(cvar_survspd))
11302 else if (g_sniper[id])
11303 set_pev(id, pev_maxspeed, get_pcvar_float(cvar_snispd))
11304 else if (get_pcvar_float(cvar_humanspd) > 0.0)
11305 set_pev(id, pev_maxspeed, get_pcvar_float(cvar_humanspd))
11306 }
11307 }
11308}
11309
11310/*================================================================================
11311 [Custom Natives]
11312=================================================================================*/
11313
11314// Native: zp_get_user_zombie
11315public native_get_user_zombie(id)
11316{
11317 if (!is_user_valid(id))
11318 {
11319 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11320 return -1;
11321 }
11322
11323 return g_zombie[id];
11324}
11325
11326// Native: zp_get_user_nemesis
11327public native_get_user_nemesis(id)
11328{
11329 if (!is_user_valid(id))
11330 {
11331 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11332 return -1;
11333 }
11334
11335 return g_nemesis[id];
11336}
11337
11338// Native: zp_get_user_assassin
11339public native_get_user_assassin(id)
11340{
11341 if (!is_user_valid(id))
11342 {
11343 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11344 return -1;
11345 }
11346
11347 return g_assassin[id];
11348}
11349
11350// Native: zp_get_user_survivor
11351public native_get_user_survivor(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_survivor[id];
11360}
11361
11362// Native: zp_get_user_sniper
11363public native_get_user_sniper(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_sniper[id];
11372}
11373
11374public native_get_user_first_zombie(id)
11375{
11376 if (!is_user_valid(id))
11377 {
11378 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11379 return -1;
11380 }
11381
11382 return g_firstzombie[id];
11383}
11384
11385// Native: zp_get_user_last_zombie
11386public native_get_user_last_zombie(id)
11387{
11388 if (!is_user_valid(id))
11389 {
11390 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11391 return -1;
11392 }
11393
11394 return g_lastzombie[id];
11395}
11396
11397// Native: zp_get_user_last_human
11398public native_get_user_last_human(id)
11399{
11400 if (!is_user_valid(id))
11401 {
11402 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11403 return -1;
11404 }
11405
11406 return g_lasthuman[id];
11407}
11408
11409// Native: zp_get_user_zombie_class
11410public native_get_user_zombie_class(id)
11411{
11412 if (!is_user_valid(id))
11413 {
11414 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11415 return -1;
11416 }
11417
11418 return g_zombieclass[id];
11419}
11420
11421// Native: zp_get_user_next_class
11422public native_get_user_next_class(id)
11423{
11424 if (!is_user_valid(id))
11425 {
11426 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11427 return -1;
11428 }
11429
11430 return g_zombieclassnext[id];
11431}
11432
11433// Native: zp_set_user_zombie_class
11434public native_set_user_zombie_class(id, classid)
11435{
11436 if (!is_user_valid(id))
11437 {
11438 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11439 return false;
11440 }
11441
11442 if (classid < 0 || classid >= g_zclass_i)
11443 {
11444 log_error(AMX_ERR_NATIVE, "[ZP] Invalid zombie class id (%d)", classid)
11445 return false;
11446 }
11447
11448 g_zombieclassnext[id] = classid
11449 return true;
11450}
11451
11452// Native: zp_get_user_ammo_packs
11453public native_get_user_ammo_packs(id)
11454{
11455 if (!is_user_valid(id))
11456 {
11457 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11458 return -1;
11459 }
11460
11461 return g_ammopacks[id];
11462}
11463
11464// Native: zp_set_user_ammo_packs
11465public native_set_user_ammo_packs(id, amount)
11466{
11467 if (!is_user_valid(id))
11468 {
11469 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11470 return false;
11471 }
11472
11473 g_ammopacks[id] = amount;
11474 return true;
11475}
11476
11477// Native: zp_get_zombie_maxhealth
11478public native_get_zombie_maxhealth(id)
11479{
11480 // ZP disabled
11481 if (!g_pluginenabled)
11482 return -1;
11483
11484 if (!is_user_valid(id))
11485 {
11486 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11487 return -1;
11488 }
11489
11490 if (!g_zombie[id] || g_nemesis[id])
11491 {
11492 log_error(AMX_ERR_NATIVE, "[ZP] Player not a normal zombie (%d)", id)
11493 return -1;
11494 }
11495
11496 if (g_firstzombie[id])
11497 return floatround(float(ArrayGetCell(g_zclass_hp, g_zombieclass[id])) * get_pcvar_float(cvar_zombiefirsthp));
11498
11499 return ArrayGetCell(g_zclass_hp, g_zombieclass[id]);
11500}
11501
11502// Native: zp_get_user_batteries
11503public native_get_user_batteries(id)
11504{
11505 if (!is_user_valid(id))
11506 {
11507 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11508 return -1;
11509 }
11510
11511 return g_flashbattery[id];
11512}
11513
11514// Native: zp_set_user_batteries
11515public native_set_user_batteries(id, value)
11516{
11517 // ZP disabled
11518 if (!g_pluginenabled)
11519 return false;
11520
11521 if (!is_user_valid_connected(id))
11522 {
11523 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11524 return false;
11525 }
11526
11527 g_flashbattery[id] = clamp(value, 0, 100);
11528
11529 if (g_cached_customflash)
11530 {
11531 // Set the flashlight charge task to update battery status
11532 remove_task(id+TASK_CHARGE)
11533 set_task(1.0, "flashlight_charge", id+TASK_CHARGE, _, _, "b")
11534 }
11535 return true;
11536}
11537
11538// Native: zp_get_user_nightvision
11539public native_get_user_nightvision(id)
11540{
11541 if (!is_user_valid(id))
11542 {
11543 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11544 return -1;
11545 }
11546
11547 return g_nvision[id];
11548}
11549
11550// Native: zp_set_user_nightvision
11551public native_set_user_nightvision(id, set)
11552{
11553 // ZP disabled
11554 if (!g_pluginenabled)
11555 return false;
11556
11557 if (!is_user_valid_connected(id))
11558 {
11559 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11560 return false;
11561 }
11562
11563 if (set)
11564 {
11565 g_nvision[id] = true
11566
11567 if (!g_isbot[id])
11568 {
11569 g_nvisionenabled[id] = true
11570
11571 // Custom nvg?
11572 if (get_pcvar_num(cvar_customnvg))
11573 {
11574 remove_task(id+TASK_NVISION)
11575 set_task(0.1, "set_user_nvision", id+TASK_NVISION, _, _, "b")
11576 }
11577 else
11578 set_user_gnvision(id, 1)
11579 }
11580 else
11581 cs_set_user_nvg(id, 1)
11582 }
11583 else
11584 {
11585 // Remove CS nightvision if player owns one (bugfix)
11586 cs_set_user_nvg(id, 0)
11587
11588 if (get_pcvar_num(cvar_customnvg)) remove_task(id+TASK_NVISION)
11589 else if (g_nvisionenabled[id]) set_user_gnvision(id, 0)
11590 g_nvision[id] = false
11591 g_nvisionenabled[id] = false
11592 }
11593 return true;
11594}
11595
11596// Native: zp_infect_user
11597public native_infect_user(id, infector, silent, rewards)
11598{
11599 // ZP disabled
11600 if (!g_pluginenabled)
11601 return false;
11602
11603 if (!is_user_valid_alive(id))
11604 {
11605 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11606 return false;
11607 }
11608
11609 // Not allowed to be zombie
11610 if (!allowed_zombie(id))
11611 return false;
11612
11613 // New round?
11614 if (g_newround)
11615 {
11616 // Set as first zombie
11617 remove_task(TASK_MAKEZOMBIE)
11618 make_a_zombie(MODE_INFECTION, id)
11619 }
11620 else
11621 {
11622 // Just infect (plus some checks)
11623 zombieme(id, is_user_valid_alive(infector) ? infector : 0, 0, 0, (silent == 1) ? 1 : 0, (rewards == 1) ? 1 : 0)
11624 }
11625 return true;
11626}
11627
11628// Native: zp_disinfect_user
11629public native_disinfect_user(id, silent)
11630{
11631 // ZP disabled
11632 if (!g_pluginenabled)
11633 return false;
11634
11635 if (!is_user_valid_alive(id))
11636 {
11637 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11638 return false;
11639 }
11640
11641 // Not allowed to be human
11642 if (!allowed_human(id))
11643 return false;
11644
11645 // Turn to human
11646 humanme(id, 0, 0, (silent == 1) ? 1 : 0)
11647 return true;
11648}
11649
11650// Native: zp_make_user_nemesis
11651public native_make_user_nemesis(id)
11652{
11653 // ZP disabled
11654 if (!g_pluginenabled)
11655 return false;
11656
11657 if (!is_user_valid_alive(id))
11658 {
11659 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11660 return false;
11661 }
11662
11663 // Not allowed to be nemesis
11664 if (!allowed_nemesis(id))
11665 return false;
11666
11667 // New round?
11668 if (g_newround)
11669 {
11670 // Set as first nemesis
11671 remove_task(TASK_MAKEZOMBIE)
11672 make_a_zombie(MODE_NEMESIS, id)
11673 }
11674 else
11675 {
11676 // Turn player into a Nemesis
11677 zombieme(id, 0, 1, 0, 0, 0)
11678 }
11679 return true;
11680}
11681
11682// Native: zp_make_user_assassin
11683public native_make_user_assassin(id)
11684{
11685 // ZP disabled
11686 if (!g_pluginenabled)
11687 return false;
11688
11689 if (!is_user_valid_alive(id))
11690 {
11691 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11692 return false;
11693 }
11694
11695 // Not allowed to be assassin
11696 if (!allowed_assassin(id))
11697 return false;
11698
11699 // New round?
11700 if (g_newround)
11701 {
11702 // Set as first assassin
11703 remove_task(TASK_MAKEZOMBIE)
11704 make_a_zombie(MODE_ASSASSIN, id)
11705 }
11706 else
11707 {
11708 // Turn player into a Assassin
11709 zombieme(id, 0, 0, 1, 0, 0)
11710 }
11711 return true;
11712}
11713
11714// Native: zp_make_user_survivor
11715public native_make_user_survivor(id)
11716{
11717 // ZP disabled
11718 if (!g_pluginenabled)
11719 return false;
11720
11721 if (!is_user_valid_alive(id))
11722 {
11723 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11724 return false;
11725 }
11726
11727 // Not allowed to be survivor
11728 if (!allowed_survivor(id))
11729 return false;
11730
11731 // New round?
11732 if (g_newround)
11733 {
11734 // Set as first survivor
11735 remove_task(TASK_MAKEZOMBIE)
11736 make_a_zombie(MODE_SURVIVOR, id)
11737 }
11738 else
11739 {
11740 // Turn player into a Survivor
11741 humanme(id, 1, 0, 0)
11742 }
11743
11744 return true;
11745}
11746
11747// Native: zp_make_user_sniper
11748public native_make_user_sniper(id)
11749{
11750 // ZP disabled
11751 if (!g_pluginenabled)
11752 return false;
11753
11754 if (!is_user_valid_alive(id))
11755 {
11756 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11757 return false;
11758 }
11759
11760 // Not allowed to be sniper
11761 if (!allowed_sniper(id))
11762 return false;
11763
11764 // New round?
11765 if (g_newround)
11766 {
11767 // Set as first sniper
11768 remove_task(TASK_MAKEZOMBIE)
11769 make_a_zombie(MODE_SNIPER, id)
11770 }
11771 else
11772 {
11773 // Turn player into a Sniper
11774 humanme(id, 0, 1, 0)
11775 }
11776
11777 return true;
11778}
11779
11780// Native: zp_respawn_user
11781public native_respawn_user(id, team)
11782{
11783 // ZP disabled
11784 if (!g_pluginenabled)
11785 return false;
11786
11787 if (!is_user_valid_connected(id))
11788 {
11789 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11790 return false;
11791 }
11792
11793 // Respawn not allowed
11794 if (!allowed_respawn(id))
11795 return false;
11796
11797 // Respawn as zombie?
11798 g_respawn_as_zombie[id] = (team == ZP_TEAM_ZOMBIE) ? true : false
11799
11800 // Respawnish!
11801 respawn_player_manually(id)
11802 return true;
11803}
11804
11805// Native: zp_force_buy_extra_item
11806public native_force_buy_extra_item(id, itemid, ignorecost)
11807{
11808 // ZP disabled
11809 if (!g_pluginenabled)
11810 return false;
11811
11812 if (!is_user_valid_alive(id))
11813 {
11814 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11815 return false;
11816 }
11817
11818 if (itemid < 0 || itemid >= g_extraitem_i)
11819 {
11820 log_error(AMX_ERR_NATIVE, "[ZP] Invalid extra item id (%d)", itemid)
11821 return false;
11822 }
11823
11824 buy_extra_item(id, itemid, ignorecost)
11825 return true;
11826}
11827
11828// Native: zp_override_user_model
11829public native_override_user_model(id, const newmodel[], modelindex)
11830{
11831 // ZP disabled
11832 if (!g_pluginenabled)
11833 return false;
11834
11835 if (!is_user_valid_connected(id))
11836 {
11837 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11838 return false;
11839 }
11840
11841 // Strings passed byref
11842 param_convert(2)
11843
11844 // Remove previous tasks
11845 remove_task(id+TASK_MODEL)
11846
11847 // Custom models stuff
11848 static currentmodel[32]
11849
11850 if (g_handle_models_on_separate_ent)
11851 {
11852 // Set the right model
11853 copy(g_playermodel[id], charsmax(g_playermodel[]), newmodel)
11854 if (g_set_modelindex_offset && modelindex) fm_cs_set_user_model_index(id, modelindex)
11855
11856 // Set model on player model entity
11857 fm_set_playermodel_ent(id)
11858 }
11859 else
11860 {
11861 // Get current model for comparing it with the current one
11862 fm_cs_get_user_model(id, currentmodel, charsmax(currentmodel))
11863
11864 // Set the right model, after checking that we don't already have it
11865 if (!equal(currentmodel, newmodel))
11866 {
11867 copy(g_playermodel[id], charsmax(g_playermodel[]), newmodel)
11868 if (g_set_modelindex_offset && modelindex) fm_cs_set_user_model_index(id, modelindex)
11869
11870 // An additional delay is offset at round start
11871 // since SVC_BAD is more likely to be triggered there
11872 if (g_newround)
11873 set_task(5.0 * g_modelchange_delay, "fm_user_model_update", id+TASK_MODEL)
11874 else
11875 fm_user_model_update(id+TASK_MODEL)
11876 }
11877 }
11878 return true;
11879}
11880
11881// Native: zp_get_user_model
11882public native_get_user_model(plugin_id, param_nums)
11883{
11884 // ZPA disabled
11885 if (!g_pluginenabled)
11886 return -1;
11887
11888 // Insufficient number of arguments
11889 if (param_nums != 3)
11890 return -1;
11891
11892 // Retrieve the player's index
11893 static id; id = get_param(1)
11894
11895 // Not an alive player or invalid player
11896 if (!is_user_valid_alive(id))
11897 return 0;
11898
11899 // Retrieve the player's current model
11900 static current_model[32]
11901 fm_cs_get_user_model(id, current_model, charsmax(current_model))
11902
11903 // Copy the model name into the array passed
11904 set_string(2, current_model, get_param(3))
11905
11906 return 1;
11907}
11908
11909// Native: zp_set_user_model
11910public native_set_user_model(id, const model[])
11911{
11912 // ZPA disabled
11913 if (!g_pluginenabled)
11914 return -1;
11915
11916 // Not an alive player or invalid player
11917 if (!is_user_valid_alive(id))
11918 return -1;
11919
11920 // Strings passed byref
11921 param_convert(2)
11922
11923 // Retrieve the player's current model
11924 static current_model[32]
11925 fm_cs_get_user_model(id, current_model, charsmax(current_model))
11926
11927 // Check whether we already have the model set on the player
11928 if (equal(current_model, model))
11929 return 0;
11930
11931 // Update player's model
11932 copy(g_playermodel[id], charsmax(g_playermodel[]), model)
11933
11934 // Set the right model for the player
11935 if (g_handle_models_on_separate_ent) fm_set_playermodel_ent(id)
11936 else fm_user_model_update(id+TASK_MODEL)
11937
11938 return 1;
11939}
11940
11941// Native: zp_has_round_started
11942public native_has_round_started()
11943{
11944 if (g_newround) return 0; // not started
11945 if (g_modestarted) return 1; // started
11946 return 2; // starting
11947}
11948
11949// Native: zp_is_nemesis_round
11950public native_is_nemesis_round()
11951{
11952 return g_nemround;
11953}
11954
11955// Native: zp_is_assassin_round
11956public native_is_assassin_round()
11957{
11958 return g_assaround;
11959}
11960
11961// Native: zp_is_survivor_round
11962public native_is_survivor_round()
11963{
11964 return g_survround;
11965}
11966
11967// Native: zp_is_sniper_round
11968public native_is_sniper_round()
11969{
11970 return g_sniround;
11971}
11972
11973// Native: zp_is_swarm_round
11974public native_is_swarm_round()
11975{
11976 return g_swarmround;
11977}
11978
11979// Native: zp_is_plague_round
11980public native_is_plague_round()
11981{
11982 return g_plagueround;
11983}
11984
11985// Native: zp_is_armageddon_round
11986public native_is_armageddon_round()
11987{
11988 return g_armageround;
11989}
11990
11991// Native: zp_is_apocalypse_round
11992public native_is_apocalypse_round()
11993{
11994 return g_apocround;
11995}
11996
11997// Native: zp_is_nightmare_round
11998public native_is_nightmare_round()
11999{
12000 return g_nightround;
12001}
12002
12003// Native: zp_get_zombie_count
12004public native_get_zombie_count()
12005{
12006 return fnGetZombies();
12007}
12008
12009// Native: zp_get_human_count
12010public native_get_human_count()
12011{
12012 return fnGetHumans();
12013}
12014
12015// Native: zp_get_nemesis_count
12016public native_get_nemesis_count()
12017{
12018 return fnGetNemesis();
12019}
12020
12021// Native: zp_get_assassin_count
12022public native_get_assassin_count()
12023{
12024 return fnGetAssassin();
12025}
12026
12027// Native: zp_get_survivor_count
12028public native_get_survivor_count()
12029{
12030 return fnGetSurvivors();
12031}
12032
12033// Native: zp_get_sniper_count
12034public native_get_sniper_count()
12035{
12036 return fnGetSnipers();
12037}
12038
12039// Native: zp_register_extra_item
12040public native_register_extra_item(const name[], cost, team)
12041{
12042 // ZP disabled
12043 if (!g_pluginenabled)
12044 return -1;
12045
12046 // Strings passed byref
12047 param_convert(1)
12048
12049 // Arrays not yet initialized
12050 if (!g_arrays_created)
12051 {
12052 log_error(AMX_ERR_NATIVE, "[ZP] Can't register extra item yet (%s)", name)
12053 return -1;
12054 }
12055
12056 if (strlen(name) < 1)
12057 {
12058 log_error(AMX_ERR_NATIVE, "[ZP] Can't register extra item with an empty name")
12059 return -1;
12060 }
12061
12062 new index, extraitem_name[32]
12063 for (index = 0; index < g_extraitem_i; index++)
12064 {
12065 ArrayGetString(g_extraitem_name, index, extraitem_name, charsmax(extraitem_name))
12066 if (equali(name, extraitem_name))
12067 {
12068 log_error(AMX_ERR_NATIVE, "[ZP] Extra item already registered (%s)", name)
12069 return -1;
12070 }
12071 }
12072
12073 // For backwards compatibility
12074 if (team == ZP_TEAM_ANY)
12075 team = (ZP_TEAM_ZOMBIE|ZP_TEAM_HUMAN)
12076
12077 // Add the item
12078 ArrayPushString(g_extraitem_name, name)
12079 ArrayPushCell(g_extraitem_cost, cost)
12080 ArrayPushCell(g_extraitem_team, team)
12081
12082 // Set temporary new item flag
12083 ArrayPushCell(g_extraitem_new, 1)
12084
12085 // Override extra items data with our customizations
12086 new i, buffer[32], size = ArraySize(g_extraitem2_realname)
12087 for (i = 0; i < size; i++)
12088 {
12089 ArrayGetString(g_extraitem2_realname, i, buffer, charsmax(buffer))
12090
12091 // Check if this is the intended item to override
12092 if (!equal(name, buffer))
12093 continue;
12094
12095 // Remove new item flag
12096 ArraySetCell(g_extraitem_new, g_extraitem_i, 0)
12097
12098 // Replace caption
12099 ArrayGetString(g_extraitem2_name, i, buffer, charsmax(buffer))
12100 ArraySetString(g_extraitem_name, g_extraitem_i, buffer)
12101
12102 // Replace cost
12103 buffer[0] = ArrayGetCell(g_extraitem2_cost, i)
12104 ArraySetCell(g_extraitem_cost, g_extraitem_i, buffer[0])
12105
12106 // Replace team
12107 buffer[0] = ArrayGetCell(g_extraitem2_team, i)
12108 ArraySetCell(g_extraitem_team, g_extraitem_i, buffer[0])
12109 }
12110
12111 // Increase registered items counter
12112 g_extraitem_i++
12113
12114 // Return id under which we registered the item
12115 return g_extraitem_i-1;
12116}
12117
12118// Function: zp_register_extra_item (to be used within this plugin only)
12119native_register_extra_item2(const name[], cost, team)
12120{
12121 // Add the item
12122 ArrayPushString(g_extraitem_name, name)
12123 ArrayPushCell(g_extraitem_cost, cost)
12124 ArrayPushCell(g_extraitem_team, team)
12125
12126 // Set temporary new item flag
12127 ArrayPushCell(g_extraitem_new, 1)
12128
12129 // Increase registered items counter
12130 g_extraitem_i++
12131}
12132
12133// Native: zp_register_zombie_class
12134public native_register_zombie_class(const name[], const info[], const model[], const clawmodel[], hp, speed, Float:gravity, Float:knockback)
12135{
12136 // ZP disabled
12137 if (!g_pluginenabled)
12138 return -1;
12139
12140 // Strings passed byref
12141 param_convert(1)
12142 param_convert(2)
12143 param_convert(3)
12144 param_convert(4)
12145
12146 // Arrays not yet initialized
12147 if (!g_arrays_created)
12148 {
12149 log_error(AMX_ERR_NATIVE, "[ZP] Can't register zombie class yet (%s)", name)
12150 return -1;
12151 }
12152
12153 if (strlen(name) < 1)
12154 {
12155 log_error(AMX_ERR_NATIVE, "[ZP] Can't register zombie class with an empty name")
12156 return -1;
12157 }
12158
12159 new index, zombieclass_name[32]
12160 for (index = 0; index < g_zclass_i; index++)
12161 {
12162 ArrayGetString(g_zclass_name, index, zombieclass_name, charsmax(zombieclass_name))
12163 if (equali(name, zombieclass_name))
12164 {
12165 log_error(AMX_ERR_NATIVE, "[ZP] Zombie class already registered (%s)", name)
12166 return -1;
12167 }
12168 }
12169
12170 // Add the class
12171 ArrayPushString(g_zclass_name, name)
12172 ArrayPushString(g_zclass_info, info)
12173
12174 // Using same zombie models for all classes?
12175 if (g_same_models_for_all)
12176 {
12177 ArrayPushCell(g_zclass_modelsstart, 0)
12178 ArrayPushCell(g_zclass_modelsend, ArraySize(g_zclass_playermodel))
12179 }
12180 else
12181 {
12182 ArrayPushCell(g_zclass_modelsstart, ArraySize(g_zclass_playermodel))
12183 ArrayPushString(g_zclass_playermodel, model)
12184 ArrayPushCell(g_zclass_modelsend, ArraySize(g_zclass_playermodel))
12185 ArrayPushCell(g_zclass_modelindex, -1)
12186 }
12187
12188 ArrayPushString(g_zclass_clawmodel, clawmodel)
12189 ArrayPushCell(g_zclass_hp, hp)
12190 ArrayPushCell(g_zclass_spd, speed)
12191 ArrayPushCell(g_zclass_grav, gravity)
12192 ArrayPushCell(g_zclass_kb, knockback)
12193
12194 // Set temporary new class flag
12195 ArrayPushCell(g_zclass_new, 1)
12196
12197 // Override zombie classes data with our customizations
12198 new i, k, buffer[32], Float:buffer2, nummodels_custom, nummodels_default, prec_mdl[100], size = ArraySize(g_zclass2_realname)
12199 for (i = 0; i < size; i++)
12200 {
12201 ArrayGetString(g_zclass2_realname, i, buffer, charsmax(buffer))
12202
12203 // Check if this is the intended class to override
12204 if (!equal(name, buffer))
12205 continue;
12206
12207 // Remove new class flag
12208 ArraySetCell(g_zclass_new, g_zclass_i, 0)
12209
12210 // Replace caption
12211 ArrayGetString(g_zclass2_name, i, buffer, charsmax(buffer))
12212 ArraySetString(g_zclass_name, g_zclass_i, buffer)
12213
12214 // Replace info
12215 ArrayGetString(g_zclass2_info, i, buffer, charsmax(buffer))
12216 ArraySetString(g_zclass_info, g_zclass_i, buffer)
12217
12218 // Replace models, unless using same models for all classes
12219 if (!g_same_models_for_all)
12220 {
12221 nummodels_custom = ArrayGetCell(g_zclass2_modelsend, i) - ArrayGetCell(g_zclass2_modelsstart, i)
12222 nummodels_default = ArrayGetCell(g_zclass_modelsend, g_zclass_i) - ArrayGetCell(g_zclass_modelsstart, g_zclass_i)
12223
12224 // Replace each player model and model index
12225 for (k = 0; k < min(nummodels_custom, nummodels_default); k++)
12226 {
12227 ArrayGetString(g_zclass2_playermodel, ArrayGetCell(g_zclass2_modelsstart, i) + k, buffer, charsmax(buffer))
12228 ArraySetString(g_zclass_playermodel, ArrayGetCell(g_zclass_modelsstart, g_zclass_i) + k, buffer)
12229
12230 // Precache player model and replace its modelindex with the real one
12231 formatex(prec_mdl, charsmax(prec_mdl), "models/player/%s/%s.mdl", buffer, buffer)
12232 ArraySetCell(g_zclass_modelindex, ArrayGetCell(g_zclass_modelsstart, g_zclass_i) + k, engfunc(EngFunc_PrecacheModel, prec_mdl))
12233 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, prec_mdl)
12234 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, prec_mdl)
12235 // Precache modelT.mdl files too
12236 copy(prec_mdl[strlen(prec_mdl)-4], charsmax(prec_mdl) - (strlen(prec_mdl)-4), "T.mdl")
12237 if (file_exists(prec_mdl)) engfunc(EngFunc_PrecacheModel, prec_mdl)
12238 }
12239
12240 // We have more custom models than what we can accommodate,
12241 // Let's make some space...
12242 if (nummodels_custom > nummodels_default)
12243 {
12244 for (k = nummodels_default; k < nummodels_custom; k++)
12245 {
12246 ArrayGetString(g_zclass2_playermodel, ArrayGetCell(g_zclass2_modelsstart, i) + k, buffer, charsmax(buffer))
12247 ArrayInsertStringAfter(g_zclass_playermodel, ArrayGetCell(g_zclass_modelsstart, g_zclass_i) + k - 1, buffer)
12248
12249 // Precache player model and retrieve its modelindex
12250 formatex(prec_mdl, charsmax(prec_mdl), "models/player/%s/%s.mdl", buffer, buffer)
12251 ArrayInsertCellAfter(g_zclass_modelindex, ArrayGetCell(g_zclass_modelsstart, g_zclass_i) + k - 1, engfunc(EngFunc_PrecacheModel, prec_mdl))
12252 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, prec_mdl)
12253 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, prec_mdl)
12254 // Precache modelT.mdl files too
12255 copy(prec_mdl[strlen(prec_mdl)-4], charsmax(prec_mdl) - (strlen(prec_mdl)-4), "T.mdl")
12256 if (file_exists(prec_mdl)) engfunc(EngFunc_PrecacheModel, prec_mdl)
12257 }
12258
12259 // Fix models end index for this class
12260 ArraySetCell(g_zclass_modelsend, g_zclass_i, ArrayGetCell(g_zclass_modelsend, g_zclass_i) + (nummodels_custom - nummodels_default))
12261 }
12262
12263 /* --- Not needed since classes can't have more than 1 default model for now ---
12264 // We have less custom models than what this class has by default,
12265 // Get rid of those extra entries...
12266 if (nummodels_custom < nummodels_default)
12267 {
12268 for (k = nummodels_custom; k < nummodels_default; k++)
12269 {
12270 ArrayDeleteItem(g_zclass_playermodel, ArrayGetCell(g_zclass_modelsstart, g_zclass_i) + nummodels_custom)
12271 }
12272
12273 // Fix models end index for this class
12274 ArraySetCell(g_zclass_modelsend, g_zclass_i, ArrayGetCell(g_zclass_modelsend, g_zclass_i) - (nummodels_default - nummodels_custom))
12275 }
12276 */
12277 }
12278
12279 // Replace clawmodel
12280 ArrayGetString(g_zclass2_clawmodel, i, buffer, charsmax(buffer))
12281 ArraySetString(g_zclass_clawmodel, g_zclass_i, buffer)
12282
12283 // Precache clawmodel
12284 formatex(prec_mdl, charsmax(prec_mdl), "models/zombie_plague/%s", buffer)
12285 engfunc(EngFunc_PrecacheModel, prec_mdl)
12286
12287 // Replace health
12288 buffer[0] = ArrayGetCell(g_zclass2_hp, i)
12289 ArraySetCell(g_zclass_hp, g_zclass_i, buffer[0])
12290
12291 // Replace speed
12292 buffer[0] = ArrayGetCell(g_zclass2_spd, i)
12293 ArraySetCell(g_zclass_spd, g_zclass_i, buffer[0])
12294
12295 // Replace gravity
12296 buffer2 = Float:ArrayGetCell(g_zclass2_grav, i)
12297 ArraySetCell(g_zclass_grav, g_zclass_i, buffer2)
12298
12299 // Replace knockback
12300 buffer2 = Float:ArrayGetCell(g_zclass2_kb, i)
12301 ArraySetCell(g_zclass_kb, g_zclass_i, buffer2)
12302 }
12303
12304 // If class was not overriden with customization data
12305 if (ArrayGetCell(g_zclass_new, g_zclass_i))
12306 {
12307 // If not using same models for all classes
12308 if (!g_same_models_for_all)
12309 {
12310 // Precache default class model and replace modelindex with the real one
12311 formatex(prec_mdl, charsmax(prec_mdl), "models/player/%s/%s.mdl", model, model)
12312 ArraySetCell(g_zclass_modelindex, ArrayGetCell(g_zclass_modelsstart, g_zclass_i), engfunc(EngFunc_PrecacheModel, prec_mdl))
12313 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, prec_mdl)
12314 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, prec_mdl)
12315 // Precache modelT.mdl files too
12316 copy(prec_mdl[strlen(prec_mdl)-4], charsmax(prec_mdl) - (strlen(prec_mdl)-4), "T.mdl")
12317 if (file_exists(prec_mdl)) engfunc(EngFunc_PrecacheModel, prec_mdl)
12318 }
12319
12320 // Precache default clawmodel
12321 formatex(prec_mdl, charsmax(prec_mdl), "models/zombie_plague/%s", clawmodel)
12322 engfunc(EngFunc_PrecacheModel, prec_mdl)
12323 }
12324
12325 // Increase registered classes counter
12326 g_zclass_i++
12327
12328 // Return id under which we registered the class
12329 return g_zclass_i-1;
12330}
12331
12332// Native: zp_get_extra_item_id
12333public native_get_extra_item_id(const name[])
12334{
12335 // ZP disabled
12336 if (!g_pluginenabled)
12337 return -1;
12338
12339 // Strings passed byref
12340 param_convert(1)
12341
12342 // Loop through every item (not using Tries since ZP should work on AMXX 1.8.0)
12343 static i, item_name[32]
12344 for (i = 0; i < g_extraitem_i; i++)
12345 {
12346 ArrayGetString(g_extraitem_name, i, item_name, charsmax(item_name))
12347
12348 // Check if this is the item to retrieve
12349 if (equali(name, item_name))
12350 return i;
12351 }
12352
12353 return -1;
12354}
12355
12356// Native: zp_get_zombie_class_id
12357public native_get_zombie_class_id(const name[])
12358{
12359 // ZP disabled
12360 if (!g_pluginenabled)
12361 return -1;
12362
12363 // Strings passed byref
12364 param_convert(1)
12365
12366 // Loop through every class (not using Tries since ZP should work on AMXX 1.8.0)
12367 static i, class_name[32]
12368 for (i = 0; i < g_zclass_i; i++)
12369 {
12370 ArrayGetString(g_zclass_name, i, class_name, charsmax(class_name))
12371
12372 // Check if this is the class to retrieve
12373 if (equali(name, class_name))
12374 return i;
12375 }
12376
12377 return -1;
12378}
12379
12380// Native: zp_get_zombie_class_info
12381public native_get_zombie_class_info(classid, info[], len)
12382{
12383 // ZP disabled
12384 if (!g_pluginenabled)
12385 return false;
12386
12387 // Invalid class
12388 if (classid < 0 || classid >= g_zclass_i)
12389 {
12390 log_error(AMX_ERR_NATIVE, "[ZP] Invalid zombie class id (%d)", classid)
12391 return false;
12392 }
12393
12394 // Strings passed byref
12395 param_convert(2)
12396
12397 // Fetch zombie class info
12398 ArrayGetString(g_zclass_info, classid, info, len)
12399 return true;
12400}
12401
12402/*================================================================================
12403 [Custom Messages]
12404=================================================================================*/
12405
12406// Custom Night Vision
12407public set_user_nvision(taskid)
12408{
12409 // Get player's origin
12410 static origin[3]
12411 get_user_origin(ID_NVISION, origin)
12412
12413 // Nightvision message
12414 message_begin(MSG_ONE_UNRELIABLE, SVC_TEMPENTITY, _, ID_NVISION)
12415 write_byte(TE_DLIGHT) // TE id
12416 write_coord(origin[0]) // x
12417 write_coord(origin[1]) // y
12418 write_coord(origin[2]) // z
12419 write_byte(get_pcvar_num(cvar_nvgsize)) // radius
12420
12421 // Nemesis / Madness / Spectator in nemesis round
12422 if (g_nemesis[ID_NVISION] || (g_zombie[ID_NVISION] && g_nodamage[ID_NVISION]) || (!g_isalive[ID_NVISION] && g_nemround))
12423 {
12424 write_byte(get_pcvar_num(cvar_nemnvgcolor[0])) // r
12425 write_byte(get_pcvar_num(cvar_nemnvgcolor[1])) // g
12426 write_byte(get_pcvar_num(cvar_nemnvgcolor[2])) // b
12427 }
12428 // Assassin / Spectator in assassin round
12429 else if (g_assassin[ID_NVISION] || (!g_isalive[ID_NVISION] && g_assaround))
12430 {
12431 write_byte(get_pcvar_num(cvar_assanvgcolor[0])) // r
12432 write_byte(get_pcvar_num(cvar_assanvgcolor[1])) // g
12433 write_byte(get_pcvar_num(cvar_assanvgcolor[2])) // b
12434 }
12435 // Human / Spectator in normal round
12436 else if (!g_zombie[ID_NVISION] || !g_isalive[ID_NVISION])
12437 {
12438 write_byte(get_pcvar_num(cvar_humnvgcolor[0])) // r
12439 write_byte(get_pcvar_num(cvar_humnvgcolor[1])) // g
12440 write_byte(get_pcvar_num(cvar_humnvgcolor[2])) // b
12441 }
12442 // Zombie
12443 else
12444 {
12445 write_byte(get_pcvar_num(cvar_nvgcolor[0])) // r
12446 write_byte(get_pcvar_num(cvar_nvgcolor[1])) // g
12447 write_byte(get_pcvar_num(cvar_nvgcolor[2])) // b
12448 }
12449
12450 write_byte(2) // life
12451 write_byte(0) // decay rate
12452 message_end()
12453}
12454
12455// Game Nightvision
12456set_user_gnvision(id, toggle)
12457{
12458 // Toggle NVG message
12459 message_begin(MSG_ONE, g_msgNVGToggle, _, id)
12460 write_byte(toggle) // toggle
12461 message_end()
12462}
12463
12464// Custom Flashlight
12465public set_user_flashlight(taskid)
12466{
12467 // Get player and aiming origins
12468 static Float:originF[3], Float:destoriginF[3]
12469 pev(ID_FLASH, pev_origin, originF)
12470 fm_get_aim_origin(ID_FLASH, destoriginF)
12471
12472 // Max distance check
12473 if (get_distance_f(originF, destoriginF) > get_pcvar_float(cvar_flashdist))
12474 return;
12475
12476 // Send to all players?
12477 if (get_pcvar_num(cvar_flashshowall))
12478 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, destoriginF, 0)
12479 else
12480 message_begin(MSG_ONE_UNRELIABLE, SVC_TEMPENTITY, _, ID_FLASH)
12481
12482 // Flashlight
12483 write_byte(TE_DLIGHT) // TE id
12484 engfunc(EngFunc_WriteCoord, destoriginF[0]) // x
12485 engfunc(EngFunc_WriteCoord, destoriginF[1]) // y
12486 engfunc(EngFunc_WriteCoord, destoriginF[2]) // z
12487 write_byte(get_pcvar_num(cvar_flashsize)) // radius
12488 write_byte(get_pcvar_num(cvar_flashcolor[0])) // r
12489 write_byte(get_pcvar_num(cvar_flashcolor[1])) // g
12490 write_byte(get_pcvar_num(cvar_flashcolor[2])) // b
12491 write_byte(3) // life
12492 write_byte(0) // decay rate
12493 message_end()
12494}
12495
12496// Infection special effects
12497infection_effects(id)
12498{
12499 // Screen fade? (unless frozen)
12500 if (!g_frozen[id] && get_pcvar_num(cvar_infectionscreenfade))
12501 {
12502 message_begin(MSG_ONE_UNRELIABLE, g_msgScreenFade, _, id)
12503 write_short(UNIT_SECOND) // duration
12504 write_short(0) // hold time
12505 write_short(FFADE_IN) // fade type
12506 if (g_nemesis[id])
12507 {
12508 write_byte(get_pcvar_num(cvar_nemnvgcolor[0])) // r
12509 write_byte(get_pcvar_num(cvar_nemnvgcolor[1])) // g
12510 write_byte(get_pcvar_num(cvar_nemnvgcolor[2])) // b
12511 }
12512 else if (g_assassin[id])
12513 {
12514 write_byte(get_pcvar_num(cvar_assanvgcolor[0])) // r
12515 write_byte(get_pcvar_num(cvar_assanvgcolor[1])) // g
12516 write_byte(get_pcvar_num(cvar_assanvgcolor[2])) // b
12517 }
12518 else
12519 {
12520 write_byte(get_pcvar_num(cvar_nvgcolor[0])) // r
12521 write_byte(get_pcvar_num(cvar_nvgcolor[1])) // g
12522 write_byte(get_pcvar_num(cvar_nvgcolor[2])) // b
12523 }
12524 write_byte (255) // alpha
12525 message_end()
12526 }
12527
12528 // Screen shake?
12529 if (get_pcvar_num(cvar_infectionscreenshake))
12530 {
12531 message_begin(MSG_ONE_UNRELIABLE, g_msgScreenShake, _, id)
12532 write_short(UNIT_SECOND*4) // amplitude
12533 write_short(UNIT_SECOND*2) // duration
12534 write_short(UNIT_SECOND*10) // frequency
12535 message_end()
12536 }
12537
12538 // Infection icon?
12539 if (get_pcvar_num(cvar_hudicons))
12540 {
12541 message_begin(MSG_ONE_UNRELIABLE, g_msgDamage, _, id)
12542 write_byte(0) // damage save
12543 write_byte(0) // damage take
12544 write_long(DMG_NERVEGAS) // damage type - DMG_RADIATION
12545 write_coord(0) // x
12546 write_coord(0) // y
12547 write_coord(0) // z
12548 message_end()
12549 }
12550
12551 // Get player's origin
12552 static origin[3]
12553 get_user_origin(id, origin)
12554
12555 // Tracers?
12556 if (get_pcvar_num(cvar_infectiontracers))
12557 {
12558 message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
12559 write_byte(TE_IMPLOSION) // TE id
12560 write_coord(origin[0]) // x
12561 write_coord(origin[1]) // y
12562 write_coord(origin[2]) // z
12563 write_byte(128) // radius
12564 write_byte(20) // count
12565 write_byte(3) // duration
12566 message_end()
12567 }
12568
12569 // Particle burst?
12570 if (get_pcvar_num(cvar_infectionparticles))
12571 {
12572 message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
12573 write_byte(TE_PARTICLEBURST) // TE id
12574 write_coord(origin[0]) // x
12575 write_coord(origin[1]) // y
12576 write_coord(origin[2]) // z
12577 write_short(50) // radius
12578 write_byte(70) // color
12579 write_byte(3) // duration (will be randomized a bit)
12580 message_end()
12581 }
12582
12583 // Light sparkle?
12584 if (get_pcvar_num(cvar_infectionsparkle))
12585 {
12586 message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
12587 write_byte(TE_DLIGHT) // TE id
12588 write_coord(origin[0]) // x
12589 write_coord(origin[1]) // y
12590 write_coord(origin[2]) // z
12591 write_byte(20) // radius
12592 write_byte(get_pcvar_num(cvar_nvgcolor[0])) // r
12593 write_byte(get_pcvar_num(cvar_nvgcolor[1])) // g
12594 write_byte(get_pcvar_num(cvar_nvgcolor[2])) // b
12595 write_byte(2) // life
12596 write_byte(0) // decay rate
12597 message_end()
12598 }
12599}
12600
12601// Nemesis/madness aura task
12602public zombie_aura(taskid)
12603{
12604 // Not nemesis, not assassin, not in zombie madness
12605 if (!g_nemesis[ID_AURA] && !g_assassin[ID_AURA] && !g_nodamage[ID_AURA])
12606 {
12607 // Task not needed anymore
12608 remove_task(taskid);
12609 return;
12610 }
12611
12612 // Get player's origin
12613 static origin[3]
12614 get_user_origin(ID_AURA, origin)
12615
12616 // Colored Aura
12617 message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
12618 write_byte(TE_DLIGHT) // TE id
12619 write_coord(origin[0]) // x
12620 write_coord(origin[1]) // y
12621 write_coord(origin[2]) // z
12622 write_byte(20) // radius
12623
12624 if (g_assassin[ID_AURA])
12625 {
12626 write_byte(get_pcvar_num(cvar_assanvgcolor[0])) // r
12627 write_byte(get_pcvar_num(cvar_assanvgcolor[1])) // g
12628 write_byte(get_pcvar_num(cvar_assanvgcolor[2])) // b
12629 }
12630 else
12631 {
12632 write_byte(get_pcvar_num(cvar_nemnvgcolor[0])) // r
12633 write_byte(get_pcvar_num(cvar_nemnvgcolor[1])) // g
12634 write_byte(get_pcvar_num(cvar_nemnvgcolor[2])) // b
12635 }
12636
12637 write_byte(2) // life
12638 write_byte(0) // decay rate
12639 message_end()
12640}
12641
12642// Make zombies leave footsteps and bloodstains on the floor
12643public make_blood(taskid)
12644{
12645 // Only bleed when moving on ground
12646 if (!(pev(ID_BLOOD, pev_flags) & FL_ONGROUND) || fm_get_speed(ID_BLOOD) < 80)
12647 return;
12648
12649 // Get user origin
12650 static Float:originF[3]
12651 pev(ID_BLOOD, pev_origin, originF)
12652
12653 // If ducking set a little lower
12654 if (pev(ID_BLOOD, pev_bInDuck))
12655 originF[2] -= 18.0
12656 else
12657 originF[2] -= 36.0
12658
12659 // Send the decal message
12660 engfunc(EngFunc_MessageBegin, MSG_PAS, SVC_TEMPENTITY, originF, 0)
12661 write_byte(TE_WORLDDECAL) // TE id
12662 engfunc(EngFunc_WriteCoord, originF[0]) // x
12663 engfunc(EngFunc_WriteCoord, originF[1]) // y
12664 engfunc(EngFunc_WriteCoord, originF[2]) // z
12665 write_byte(ArrayGetCell(zombie_decals, random_num(0, ArraySize(zombie_decals) - 1)) + (g_czero * 12)) // random decal number (offsets +12 for CZ)
12666 message_end()
12667}
12668
12669// Flare Lighting Effects
12670flare_lighting(entity, duration)
12671{
12672 // Get origin and color
12673 static Float:originF[3], color[3]
12674 pev(entity, pev_origin, originF)
12675 pev(entity, PEV_FLARE_COLOR, color)
12676
12677 // Lighting
12678 engfunc(EngFunc_MessageBegin, MSG_PAS, SVC_TEMPENTITY, originF, 0)
12679 write_byte(TE_DLIGHT) // TE id
12680 engfunc(EngFunc_WriteCoord, originF[0]) // x
12681 engfunc(EngFunc_WriteCoord, originF[1]) // y
12682 engfunc(EngFunc_WriteCoord, originF[2]) // z
12683 write_byte(get_pcvar_num(cvar_flaresize)) // radius
12684 write_byte(color[0]) // r
12685 write_byte(color[1]) // g
12686 write_byte(color[2]) // b
12687 write_byte(21) //life
12688 write_byte((duration < 2) ? 3 : 0) //decay rate
12689 message_end()
12690
12691 // Sparks
12692 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12693 write_byte(TE_SPARKS) // TE id
12694 engfunc(EngFunc_WriteCoord, originF[0]) // x
12695 engfunc(EngFunc_WriteCoord, originF[1]) // y
12696 engfunc(EngFunc_WriteCoord, originF[2]) // z
12697 message_end()
12698}
12699
12700// Burning Flames
12701public burning_flame(taskid)
12702{
12703 // Get player origin and flags
12704 static origin[3], flags
12705 get_user_origin(ID_BURN, origin)
12706 flags = pev(ID_BURN, pev_flags)
12707
12708 // Madness mode - in water - burning stopped
12709 if (g_nodamage[ID_BURN] || (flags & FL_INWATER) || g_burning_duration[ID_BURN] < 1)
12710 {
12711 // Smoke sprite
12712 message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
12713 write_byte(TE_SMOKE) // TE id
12714 write_coord(origin[0]) // x
12715 write_coord(origin[1]) // y
12716 write_coord(origin[2]-50) // z
12717 write_short(g_smokeSpr) // sprite
12718 write_byte(random_num(15, 20)) // scale
12719 write_byte(random_num(10, 20)) // framerate
12720 message_end()
12721
12722 // Task not needed anymore
12723 remove_task(taskid);
12724 return;
12725 }
12726
12727 // Randomly play burning zombie scream sounds (not for nemesis)
12728 if (!g_nemesis[ID_BURN] && !g_assassin[ID_BURN] && !random_num(0, 20))
12729 {
12730 static sound[64]
12731 ArrayGetString(grenade_fire_player, random_num(0, ArraySize(grenade_fire_player) - 1), sound, charsmax(sound))
12732 emit_sound(ID_BURN, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
12733 }
12734
12735 // Fire slow down, unless nemesis
12736 if (!g_nemesis[ID_BURN] && !g_assassin[ID_BURN] && (flags & FL_ONGROUND) && get_pcvar_float(cvar_fireslowdown) > 0.0)
12737 {
12738 static Float:velocity[3]
12739 pev(ID_BURN, pev_velocity, velocity)
12740 xs_vec_mul_scalar(velocity, get_pcvar_float(cvar_fireslowdown), velocity)
12741 set_pev(ID_BURN, pev_velocity, velocity)
12742 }
12743
12744 // Get player's health
12745 static health
12746 health = pev(ID_BURN, pev_health)
12747
12748 // Take damage from the fire
12749 if (health - floatround(get_pcvar_float(cvar_firedamage), floatround_ceil) > 0)
12750 fm_set_user_health(ID_BURN, health - floatround(get_pcvar_float(cvar_firedamage), floatround_ceil))
12751
12752 // Flame sprite
12753 message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
12754 write_byte(TE_SPRITE) // TE id
12755 write_coord(origin[0]+random_num(-5, 5)) // x
12756 write_coord(origin[1]+random_num(-5, 5)) // y
12757 write_coord(origin[2]+random_num(-10, 10)) // z
12758 write_short(g_flameSpr) // sprite
12759 write_byte(random_num(5, 10)) // scale
12760 write_byte(200) // brightness
12761 message_end()
12762
12763 // Decrease burning duration counter
12764 g_burning_duration[ID_BURN]--
12765}
12766
12767// Infection Bomb: Green Blast
12768create_blast(const Float:originF[3])
12769{
12770 // Smallest ring
12771 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12772 write_byte(TE_BEAMCYLINDER) // TE id
12773 engfunc(EngFunc_WriteCoord, originF[0]) // x
12774 engfunc(EngFunc_WriteCoord, originF[1]) // y
12775 engfunc(EngFunc_WriteCoord, originF[2]) // z
12776 engfunc(EngFunc_WriteCoord, originF[0]) // x axis
12777 engfunc(EngFunc_WriteCoord, originF[1]) // y axis
12778 engfunc(EngFunc_WriteCoord, originF[2]+385.0) // z axis
12779 write_short(g_exploSpr) // sprite
12780 write_byte(0) // startframe
12781 write_byte(0) // framerate
12782 write_byte(4) // life
12783 write_byte(60) // width
12784 write_byte(0) // noise
12785 write_byte(0) // red
12786 write_byte(200) // green
12787 write_byte(0) // blue
12788 write_byte(200) // brightness
12789 write_byte(0) // speed
12790 message_end()
12791
12792 // Medium ring
12793 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12794 write_byte(TE_BEAMCYLINDER) // TE id
12795 engfunc(EngFunc_WriteCoord, originF[0]) // x
12796 engfunc(EngFunc_WriteCoord, originF[1]) // y
12797 engfunc(EngFunc_WriteCoord, originF[2]) // z
12798 engfunc(EngFunc_WriteCoord, originF[0]) // x axis
12799 engfunc(EngFunc_WriteCoord, originF[1]) // y axis
12800 engfunc(EngFunc_WriteCoord, originF[2]+470.0) // z axis
12801 write_short(g_exploSpr) // sprite
12802 write_byte(0) // startframe
12803 write_byte(0) // framerate
12804 write_byte(4) // life
12805 write_byte(60) // width
12806 write_byte(0) // noise
12807 write_byte(0) // red
12808 write_byte(200) // green
12809 write_byte(0) // blue
12810 write_byte(200) // brightness
12811 write_byte(0) // speed
12812 message_end()
12813
12814 // Largest ring
12815 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12816 write_byte(TE_BEAMCYLINDER) // TE id
12817 engfunc(EngFunc_WriteCoord, originF[0]) // x
12818 engfunc(EngFunc_WriteCoord, originF[1]) // y
12819 engfunc(EngFunc_WriteCoord, originF[2]) // z
12820 engfunc(EngFunc_WriteCoord, originF[0]) // x axis
12821 engfunc(EngFunc_WriteCoord, originF[1]) // y axis
12822 engfunc(EngFunc_WriteCoord, originF[2]+555.0) // z axis
12823 write_short(g_exploSpr) // sprite
12824 write_byte(0) // startframe
12825 write_byte(0) // framerate
12826 write_byte(4) // life
12827 write_byte(60) // width
12828 write_byte(0) // noise
12829 write_byte(0) // red
12830 write_byte(200) // green
12831 write_byte(0) // blue
12832 write_byte(200) // brightness
12833 write_byte(0) // speed
12834 message_end()
12835}
12836
12837// Fire Grenade: Fire Blast
12838create_blast2(const Float:originF[3])
12839{
12840 // Smallest ring
12841 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12842 write_byte(TE_BEAMCYLINDER) // TE id
12843 engfunc(EngFunc_WriteCoord, originF[0]) // x
12844 engfunc(EngFunc_WriteCoord, originF[1]) // y
12845 engfunc(EngFunc_WriteCoord, originF[2]) // z
12846 engfunc(EngFunc_WriteCoord, originF[0]) // x axis
12847 engfunc(EngFunc_WriteCoord, originF[1]) // y axis
12848 engfunc(EngFunc_WriteCoord, originF[2]+385.0) // z axis
12849 write_short(g_exploSpr) // sprite
12850 write_byte(0) // startframe
12851 write_byte(0) // framerate
12852 write_byte(4) // life
12853 write_byte(60) // width
12854 write_byte(0) // noise
12855 write_byte(200) // red
12856 write_byte(100) // green
12857 write_byte(0) // blue
12858 write_byte(200) // brightness
12859 write_byte(0) // speed
12860 message_end()
12861
12862 // Medium ring
12863 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12864 write_byte(TE_BEAMCYLINDER) // TE id
12865 engfunc(EngFunc_WriteCoord, originF[0]) // x
12866 engfunc(EngFunc_WriteCoord, originF[1]) // y
12867 engfunc(EngFunc_WriteCoord, originF[2]) // z
12868 engfunc(EngFunc_WriteCoord, originF[0]) // x axis
12869 engfunc(EngFunc_WriteCoord, originF[1]) // y axis
12870 engfunc(EngFunc_WriteCoord, originF[2]+470.0) // z axis
12871 write_short(g_exploSpr) // sprite
12872 write_byte(0) // startframe
12873 write_byte(0) // framerate
12874 write_byte(4) // life
12875 write_byte(60) // width
12876 write_byte(0) // noise
12877 write_byte(200) // red
12878 write_byte(50) // green
12879 write_byte(0) // blue
12880 write_byte(200) // brightness
12881 write_byte(0) // speed
12882 message_end()
12883
12884 // Largest ring
12885 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12886 write_byte(TE_BEAMCYLINDER) // TE id
12887 engfunc(EngFunc_WriteCoord, originF[0]) // x
12888 engfunc(EngFunc_WriteCoord, originF[1]) // y
12889 engfunc(EngFunc_WriteCoord, originF[2]) // z
12890 engfunc(EngFunc_WriteCoord, originF[0]) // x axis
12891 engfunc(EngFunc_WriteCoord, originF[1]) // y axis
12892 engfunc(EngFunc_WriteCoord, originF[2]+555.0) // z axis
12893 write_short(g_exploSpr) // sprite
12894 write_byte(0) // startframe
12895 write_byte(0) // framerate
12896 write_byte(4) // life
12897 write_byte(60) // width
12898 write_byte(0) // noise
12899 write_byte(200) // red
12900 write_byte(0) // green
12901 write_byte(0) // blue
12902 write_byte(200) // brightness
12903 write_byte(0) // speed
12904 message_end()
12905}
12906
12907// Frost Grenade: Freeze Blast
12908create_blast3(const Float:originF[3])
12909{
12910 // Smallest ring
12911 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12912 write_byte(TE_BEAMCYLINDER) // TE id
12913 engfunc(EngFunc_WriteCoord, originF[0]) // x
12914 engfunc(EngFunc_WriteCoord, originF[1]) // y
12915 engfunc(EngFunc_WriteCoord, originF[2]) // z
12916 engfunc(EngFunc_WriteCoord, originF[0]) // x axis
12917 engfunc(EngFunc_WriteCoord, originF[1]) // y axis
12918 engfunc(EngFunc_WriteCoord, originF[2]+385.0) // z axis
12919 write_short(g_exploSpr) // sprite
12920 write_byte(0) // startframe
12921 write_byte(0) // framerate
12922 write_byte(4) // life
12923 write_byte(60) // width
12924 write_byte(0) // noise
12925 write_byte(0) // red
12926 write_byte(100) // green
12927 write_byte(200) // blue
12928 write_byte(200) // brightness
12929 write_byte(0) // speed
12930 message_end()
12931
12932 // Medium ring
12933 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12934 write_byte(TE_BEAMCYLINDER) // TE id
12935 engfunc(EngFunc_WriteCoord, originF[0]) // x
12936 engfunc(EngFunc_WriteCoord, originF[1]) // y
12937 engfunc(EngFunc_WriteCoord, originF[2]) // z
12938 engfunc(EngFunc_WriteCoord, originF[0]) // x axis
12939 engfunc(EngFunc_WriteCoord, originF[1]) // y axis
12940 engfunc(EngFunc_WriteCoord, originF[2]+470.0) // z axis
12941 write_short(g_exploSpr) // sprite
12942 write_byte(0) // startframe
12943 write_byte(0) // framerate
12944 write_byte(4) // life
12945 write_byte(60) // width
12946 write_byte(0) // noise
12947 write_byte(0) // red
12948 write_byte(100) // green
12949 write_byte(200) // blue
12950 write_byte(200) // brightness
12951 write_byte(0) // speed
12952 message_end()
12953
12954 // Largest ring
12955 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12956 write_byte(TE_BEAMCYLINDER) // TE id
12957 engfunc(EngFunc_WriteCoord, originF[0]) // x
12958 engfunc(EngFunc_WriteCoord, originF[1]) // y
12959 engfunc(EngFunc_WriteCoord, originF[2]) // z
12960 engfunc(EngFunc_WriteCoord, originF[0]) // x axis
12961 engfunc(EngFunc_WriteCoord, originF[1]) // y axis
12962 engfunc(EngFunc_WriteCoord, originF[2]+555.0) // z axis
12963 write_short(g_exploSpr) // sprite
12964 write_byte(0) // startframe
12965 write_byte(0) // framerate
12966 write_byte(4) // life
12967 write_byte(60) // width
12968 write_byte(0) // noise
12969 write_byte(0) // red
12970 write_byte(100) // green
12971 write_byte(200) // blue
12972 write_byte(200) // brightness
12973 write_byte(0) // speed
12974 message_end()
12975}
12976
12977// Fix Dead Attrib on scoreboard
12978FixDeadAttrib(id)
12979{
12980 message_begin(MSG_BROADCAST, g_msgScoreAttrib)
12981 write_byte(id) // id
12982 write_byte(0) // attrib
12983 message_end()
12984}
12985
12986// Send Death Message for infections
12987SendDeathMsg(attacker, victim)
12988{
12989 message_begin(MSG_BROADCAST, g_msgDeathMsg)
12990 write_byte(attacker) // killer
12991 write_byte(victim) // victim
12992 write_byte(1) // headshot flag
12993 write_string("infection") // killer's weapon
12994 message_end()
12995}
12996
12997// Update Player Frags and Deaths
12998UpdateFrags(attacker, victim, frags, deaths, scoreboard)
12999{
13000 // Set attacker frags
13001 set_pev(attacker, pev_frags, float(pev(attacker, pev_frags) + frags))
13002
13003 // Set victim deaths
13004 fm_cs_set_user_deaths(victim, cs_get_user_deaths(victim) + deaths)
13005
13006 // Update scoreboard with attacker and victim info
13007 if (scoreboard)
13008 {
13009 message_begin(MSG_BROADCAST, g_msgScoreInfo)
13010 write_byte(attacker) // id
13011 write_short(pev(attacker, pev_frags)) // frags
13012 write_short(cs_get_user_deaths(attacker)) // deaths
13013 write_short(0) // class?
13014 write_short(fm_cs_get_user_team(attacker)) // team
13015 message_end()
13016
13017 message_begin(MSG_BROADCAST, g_msgScoreInfo)
13018 write_byte(victim) // id
13019 write_short(pev(victim, pev_frags)) // frags
13020 write_short(cs_get_user_deaths(victim)) // deaths
13021 write_short(0) // class?
13022 write_short(fm_cs_get_user_team(victim)) // team
13023 message_end()
13024 }
13025}
13026
13027// Remove Player Frags (when Nemesis/Survivor ignore_frags cvar is enabled)
13028RemoveFrags(attacker, victim)
13029{
13030 // Remove attacker frags
13031 set_pev(attacker, pev_frags, float(pev(attacker, pev_frags) - 1))
13032
13033 // Remove victim deaths
13034 fm_cs_set_user_deaths(victim, cs_get_user_deaths(victim) - 1)
13035}
13036
13037// Plays a sound on clients
13038PlaySound(const sound[])
13039{
13040 if (equal(sound[strlen(sound)-4], ".mp3"))
13041 client_cmd(0, "mp3 play ^"sound/%s^"", sound)
13042 else
13043 client_cmd(0, "spk ^"%s^"", sound)
13044}
13045
13046// Prints a colored message to target (use 0 for everyone), supports ML formatting.
13047// Note: I still need to make something like gungame's LANG_PLAYER_C to avoid unintended
13048// argument replacement when a function passes -1 (it will be considered a LANG_PLAYER)
13049zp_colored_print(target, const message[], any:...)
13050{
13051 static buffer[512], i, argscount
13052 argscount = numargs()
13053
13054 // Send to everyone
13055 if (!target)
13056 {
13057 static player
13058 for (player = 1; player <= g_maxplayers; player++)
13059 {
13060 // Not connected
13061 if (!g_isconnected[player])
13062 continue;
13063
13064 // Remember changed arguments
13065 static changed[5], changedcount // [5] = max LANG_PLAYER occurencies
13066 changedcount = 0
13067
13068 // Replace LANG_PLAYER with player id
13069 for (i = 2; i < argscount; i++)
13070 {
13071 if (getarg(i) == LANG_PLAYER)
13072 {
13073 setarg(i, 0, player)
13074 changed[changedcount] = i
13075 changedcount++
13076 }
13077 }
13078
13079 // Format message for player
13080 vformat(buffer, charsmax(buffer), message, 3)
13081
13082 // Send it
13083 message_begin(MSG_ONE_UNRELIABLE, g_msgSayText, _, player)
13084 write_byte(player)
13085 write_string(buffer)
13086 message_end()
13087
13088 // Replace back player id's with LANG_PLAYER
13089 for (i = 0; i < changedcount; i++)
13090 setarg(changed[i], 0, LANG_PLAYER)
13091 }
13092 }
13093 // Send to specific target
13094 else
13095 {
13096 /*
13097 // Not needed since you should set the ML argument
13098 // to the player's id for a targeted print message
13099
13100 // Replace LANG_PLAYER with player id
13101 for (i = 2; i < argscount; i++)
13102 {
13103 if (getarg(i) == LANG_PLAYER)
13104 setarg(i, 0, target)
13105 }
13106 */
13107
13108 // Format message for player
13109 vformat(buffer, charsmax(buffer), message, 3)
13110
13111 // Send it
13112 message_begin(MSG_ONE, g_msgSayText, _, target)
13113 write_byte(target)
13114 write_string(buffer)
13115 message_end()
13116 }
13117}
13118
13119/*================================================================================
13120 [Stocks]
13121=================================================================================*/
13122
13123// Set an entity's key value (from fakemeta_util)
13124stock fm_set_kvd(entity, const key[], const value[], const classname[])
13125{
13126 set_kvd(0, KV_ClassName, classname)
13127 set_kvd(0, KV_KeyName, key)
13128 set_kvd(0, KV_Value, value)
13129 set_kvd(0, KV_fHandled, 0)
13130
13131 dllfunc(DLLFunc_KeyValue, entity, 0)
13132}
13133
13134// Set entity's rendering type (from fakemeta_util)
13135stock fm_set_rendering(entity, fx = kRenderFxNone, r = 255, g = 255, b = 255, render = kRenderNormal, amount = 16)
13136{
13137 static Float:color[3]
13138 color[0] = float(r)
13139 color[1] = float(g)
13140 color[2] = float(b)
13141
13142 set_pev(entity, pev_renderfx, fx)
13143 set_pev(entity, pev_rendercolor, color)
13144 set_pev(entity, pev_rendermode, render)
13145 set_pev(entity, pev_renderamt, float(amount))
13146}
13147
13148// Get entity's speed (from fakemeta_util)
13149stock fm_get_speed(entity)
13150{
13151 static Float:velocity[3]
13152 pev(entity, pev_velocity, velocity)
13153
13154 return floatround(vector_length(velocity));
13155}
13156
13157// Get entity's aim origins (from fakemeta_util)
13158stock fm_get_aim_origin(id, Float:origin[3])
13159{
13160 static Float:origin1F[3], Float:origin2F[3]
13161 pev(id, pev_origin, origin1F)
13162 pev(id, pev_view_ofs, origin2F)
13163 xs_vec_add(origin1F, origin2F, origin1F)
13164
13165 pev(id, pev_v_angle, origin2F);
13166 engfunc(EngFunc_MakeVectors, origin2F)
13167 global_get(glb_v_forward, origin2F)
13168 xs_vec_mul_scalar(origin2F, 9999.0, origin2F)
13169 xs_vec_add(origin1F, origin2F, origin2F)
13170
13171 engfunc(EngFunc_TraceLine, origin1F, origin2F, 0, id, 0)
13172 get_tr2(0, TR_vecEndPos, origin)
13173}
13174
13175// Find entity by its owner (from fakemeta_util)
13176stock fm_find_ent_by_owner(entity, const classname[], owner)
13177{
13178 while ((entity = engfunc(EngFunc_FindEntityByString, entity, "classname", classname)) && pev(entity, pev_owner) != owner) { /* keep looping */ }
13179 return entity;
13180}
13181
13182// Set player's health (from fakemeta_util)
13183stock fm_set_user_health(id, health)
13184{
13185 (health > 0) ? set_pev(id, pev_health, float(health)) : dllfunc(DLLFunc_ClientKill, id);
13186}
13187
13188// Give an item to a player (from fakemeta_util)
13189stock fm_give_item(id, const item[])
13190{
13191 static ent
13192 ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, item))
13193 if (!pev_valid(ent)) return;
13194
13195 static Float:originF[3]
13196 pev(id, pev_origin, originF)
13197 set_pev(ent, pev_origin, originF)
13198 set_pev(ent, pev_spawnflags, pev(ent, pev_spawnflags) | SF_NORESPAWN)
13199 dllfunc(DLLFunc_Spawn, ent)
13200
13201 static save
13202 save = pev(ent, pev_solid)
13203 dllfunc(DLLFunc_Touch, ent, id)
13204 if (pev(ent, pev_solid) != save)
13205 return;
13206
13207 engfunc(EngFunc_RemoveEntity, ent)
13208}
13209
13210// Strip user weapons (from fakemeta_util)
13211stock fm_strip_user_weapons(id)
13212{
13213 static ent
13214 ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "player_weaponstrip"))
13215 if (!pev_valid(ent)) return;
13216
13217 dllfunc(DLLFunc_Spawn, ent)
13218 dllfunc(DLLFunc_Use, ent, id)
13219 engfunc(EngFunc_RemoveEntity, ent)
13220}
13221
13222// Collect random spawn points
13223stock load_spawns()
13224{
13225 // Check for CSDM spawns of the current map
13226 new cfgdir[32], mapname[32], filepath[100], linedata[64]
13227 get_configsdir(cfgdir, charsmax(cfgdir))
13228 get_mapname(mapname, charsmax(mapname))
13229 formatex(filepath, charsmax(filepath), "%s/csdm/%s.spawns.cfg", cfgdir, mapname)
13230
13231 // Load CSDM spawns if present
13232 if (file_exists(filepath))
13233 {
13234 new csdmdata[10][6], file = fopen(filepath,"rt")
13235
13236 while (file && !feof(file))
13237 {
13238 fgets(file, linedata, charsmax(linedata))
13239
13240 // invalid spawn
13241 if(!linedata[0] || str_count(linedata,' ') < 2) continue;
13242
13243 // get spawn point data
13244 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)
13245
13246 // origin
13247 g_spawns[g_spawnCount][0] = floatstr(csdmdata[0])
13248 g_spawns[g_spawnCount][1] = floatstr(csdmdata[1])
13249 g_spawns[g_spawnCount][2] = floatstr(csdmdata[2])
13250
13251 // increase spawn count
13252 g_spawnCount++
13253 if (g_spawnCount >= sizeof g_spawns) break;
13254 }
13255 if (file) fclose(file)
13256 }
13257 else
13258 {
13259 // Collect regular spawns
13260 collect_spawns_ent("info_player_start")
13261 collect_spawns_ent("info_player_deathmatch")
13262 }
13263
13264 // Collect regular spawns for non-random spawning unstuck
13265 collect_spawns_ent2("info_player_start")
13266 collect_spawns_ent2("info_player_deathmatch")
13267}
13268
13269// Collect spawn points from entity origins
13270stock collect_spawns_ent(const classname[])
13271{
13272 new ent = -1
13273 while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", classname)) != 0)
13274 {
13275 // get origin
13276 new Float:originF[3]
13277 pev(ent, pev_origin, originF)
13278 g_spawns[g_spawnCount][0] = originF[0]
13279 g_spawns[g_spawnCount][1] = originF[1]
13280 g_spawns[g_spawnCount][2] = originF[2]
13281
13282 // increase spawn count
13283 g_spawnCount++
13284 if (g_spawnCount >= sizeof g_spawns) break;
13285 }
13286}
13287
13288// Collect spawn points from entity origins
13289stock collect_spawns_ent2(const classname[])
13290{
13291 new ent = -1
13292 while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", classname)) != 0)
13293 {
13294 // get origin
13295 new Float:originF[3]
13296 pev(ent, pev_origin, originF)
13297 g_spawns2[g_spawnCount2][0] = originF[0]
13298 g_spawns2[g_spawnCount2][1] = originF[1]
13299 g_spawns2[g_spawnCount2][2] = originF[2]
13300
13301 // increase spawn count
13302 g_spawnCount2++
13303 if (g_spawnCount2 >= sizeof g_spawns2) break;
13304 }
13305}
13306
13307// Drop primary/secondary weapons
13308stock drop_weapons(id, dropwhat)
13309{
13310 // Get user weapons
13311 static weapons[32], num, i, weaponid
13312 num = 0 // reset passed weapons count (bugfix)
13313 get_user_weapons(id, weapons, num)
13314
13315 // Loop through them and drop primaries or secondaries
13316 for (i = 0; i < num; i++)
13317 {
13318 // Prevent re-indexing the array
13319 weaponid = weapons[i]
13320
13321 if ((dropwhat == 1 && ((1<<weaponid) & PRIMARY_WEAPONS_BIT_SUM)) || (dropwhat == 2 && ((1<<weaponid) & SECONDARY_WEAPONS_BIT_SUM)))
13322 {
13323 // Get weapon entity
13324 static wname[32], weapon_ent
13325 get_weaponname(weaponid, wname, charsmax(wname))
13326 weapon_ent = fm_find_ent_by_owner(-1, wname, id)
13327
13328 // Hack: store weapon bpammo on PEV_ADDITIONAL_AMMO
13329 set_pev(weapon_ent, PEV_ADDITIONAL_AMMO, cs_get_user_bpammo(id, weaponid))
13330
13331 // Player drops the weapon and looses his bpammo
13332 engclient_cmd(id, "drop", wname)
13333 cs_set_user_bpammo(id, weaponid, 0)
13334 }
13335 }
13336}
13337
13338// Stock by (probably) Twilight Suzuka -counts number of chars in a string
13339stock str_count(const str[], searchchar)
13340{
13341 new count, i, len = strlen(str)
13342
13343 for (i = 0; i <= len; i++)
13344 {
13345 if(str[i] == searchchar)
13346 count++
13347 }
13348
13349 return count;
13350}
13351
13352// Checks if a space is vacant (credits to VEN)
13353stock is_hull_vacant(Float:origin[3], hull)
13354{
13355 engfunc(EngFunc_TraceHull, origin, origin, 0, hull, 0, 0)
13356
13357 if (!get_tr2(0, TR_StartSolid) && !get_tr2(0, TR_AllSolid) && get_tr2(0, TR_InOpen))
13358 return true;
13359
13360 return false;
13361}
13362
13363// Check if a player is stuck (credits to VEN)
13364stock is_player_stuck(id)
13365{
13366 static Float:originF[3]
13367 pev(id, pev_origin, originF)
13368
13369 engfunc(EngFunc_TraceHull, originF, originF, 0, (pev(id, pev_flags) & FL_DUCKING) ? HULL_HEAD : HULL_HUMAN, id, 0)
13370
13371 if (get_tr2(0, TR_StartSolid) || get_tr2(0, TR_AllSolid) || !get_tr2(0, TR_InOpen))
13372 return true;
13373
13374 return false;
13375}
13376
13377// Simplified get_weaponid (CS only)
13378stock cs_weapon_name_to_id(const weapon[])
13379{
13380 static i
13381 for (i = 0; i < sizeof WEAPONENTNAMES; i++)
13382 {
13383 if (equal(weapon, WEAPONENTNAMES[i]))
13384 return i;
13385 }
13386
13387 return 0;
13388}
13389
13390// Get User Current Weapon Entity
13391stock fm_cs_get_current_weapon_ent(id)
13392{
13393 // Prevent server crash if entity's private data not initalized
13394 if (pev_valid(id) != PDATA_SAFE)
13395 return -1;
13396
13397 return get_pdata_cbase(id, OFFSET_ACTIVE_ITEM, OFFSET_LINUX);
13398}
13399
13400// Get Weapon Entity's Owner
13401stock fm_cs_get_weapon_ent_owner(ent)
13402{
13403 // Prevent server crash if entity's private data not initalized
13404 if (pev_valid(ent) != PDATA_SAFE)
13405 return -1;
13406
13407 return get_pdata_cbase(ent, OFFSET_WEAPONOWNER, OFFSET_LINUX_WEAPONS);
13408}
13409
13410// Set User Deaths
13411stock fm_cs_set_user_deaths(id, value)
13412{
13413 // Prevent server crash if entity's private data not initalized
13414 if (pev_valid(id) != PDATA_SAFE)
13415 return;
13416
13417 set_pdata_int(id, OFFSET_CSDEATHS, value, OFFSET_LINUX)
13418}
13419
13420// Get User Team
13421stock fm_cs_get_user_team(id)
13422{
13423 // Prevent server crash if entity's private data not initalized
13424 if (pev_valid(id) != PDATA_SAFE)
13425 return FM_CS_TEAM_UNASSIGNED;
13426
13427 return get_pdata_int(id, OFFSET_CSTEAMS, OFFSET_LINUX);
13428}
13429
13430// Set a Player's Team
13431stock fm_cs_set_user_team(id, team)
13432{
13433 // Prevent server crash if entity's private data not initalized
13434 if (pev_valid(id) != PDATA_SAFE)
13435 return;
13436
13437 set_pdata_int(id, OFFSET_CSTEAMS, team, OFFSET_LINUX)
13438}
13439
13440// Set User Money
13441stock fm_cs_set_user_money(id, value)
13442{
13443 // Prevent server crash if entity's private data not initalized
13444 if (pev_valid(id) != PDATA_SAFE)
13445 return;
13446
13447 set_pdata_int(id, OFFSET_CSMONEY, value, OFFSET_LINUX)
13448}
13449
13450// Set User Flashlight Batteries
13451stock fm_cs_set_user_batteries(id, value)
13452{
13453 // Prevent server crash if entity's private data not initalized
13454 if (pev_valid(id) != PDATA_SAFE)
13455 return;
13456
13457 set_pdata_int(id, OFFSET_FLASHLIGHT_BATTERY, value, OFFSET_LINUX)
13458}
13459
13460// Update Player's Team on all clients (adding needed delays)
13461stock fm_user_team_update(id)
13462{
13463 static Float:current_time
13464 current_time = get_gametime()
13465
13466 if (current_time - g_teams_targettime >= 0.1)
13467 {
13468 set_task(0.1, "fm_cs_set_user_team_msg", id+TASK_TEAM)
13469 g_teams_targettime = current_time + 0.1
13470 }
13471 else
13472 {
13473 set_task((g_teams_targettime + 0.1) - current_time, "fm_cs_set_user_team_msg", id+TASK_TEAM)
13474 g_teams_targettime = g_teams_targettime + 0.1
13475 }
13476}
13477
13478// Send User Team Message
13479public fm_cs_set_user_team_msg(taskid)
13480{
13481 // Note to self: this next message can now be received by other plugins
13482
13483 // Set the switching team flag
13484 g_switchingteam = true
13485
13486 // Tell everyone my new team
13487 emessage_begin(MSG_ALL, g_msgTeamInfo)
13488 ewrite_byte(ID_TEAM) // player
13489 ewrite_string(CS_TEAM_NAMES[fm_cs_get_user_team(ID_TEAM)]) // team
13490 emessage_end()
13491
13492 // Done switching team
13493 g_switchingteam = false
13494}
13495
13496// Set the precached model index (updates hitboxes server side)
13497stock fm_cs_set_user_model_index(id, value)
13498{
13499 // Prevent server crash if entity's private data not initalized
13500 if (pev_valid(id) != PDATA_SAFE)
13501 return;
13502
13503 set_pdata_int(id, OFFSET_MODELINDEX, value, OFFSET_LINUX)
13504}
13505
13506// Set Player Model on Entity
13507stock fm_set_playermodel_ent(id)
13508{
13509 // Make original player entity invisible without hiding shadows or firing effects
13510 fm_set_rendering(id, kRenderFxNone, 255, 255, 255, kRenderTransTexture, 1)
13511
13512 // Format model string
13513 static model[100]
13514 formatex(model, charsmax(model), "models/player/%s/%s.mdl", g_playermodel[id], g_playermodel[id])
13515
13516 // Set model on entity or make a new one if unexistant
13517 if (!pev_valid(g_ent_playermodel[id]))
13518 {
13519 g_ent_playermodel[id] = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "info_target"))
13520 if (!pev_valid(g_ent_playermodel[id])) return;
13521
13522 set_pev(g_ent_playermodel[id], pev_classname, MODEL_ENT_CLASSNAME)
13523 set_pev(g_ent_playermodel[id], pev_movetype, MOVETYPE_FOLLOW)
13524 set_pev(g_ent_playermodel[id], pev_aiment, id)
13525 set_pev(g_ent_playermodel[id], pev_owner, id)
13526 }
13527
13528 engfunc(EngFunc_SetModel, g_ent_playermodel[id], model)
13529}
13530
13531// Set Weapon Model on Entity
13532stock fm_set_weaponmodel_ent(id)
13533{
13534 // Get player's p_ weapon model
13535 static model[100]
13536 pev(id, pev_weaponmodel2, model, charsmax(model))
13537
13538 // Set model on entity or make a new one if unexistant
13539 if (!pev_valid(g_ent_weaponmodel[id]))
13540 {
13541 g_ent_weaponmodel[id] = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "info_target"))
13542 if (!pev_valid(g_ent_weaponmodel[id])) return;
13543
13544 set_pev(g_ent_weaponmodel[id], pev_classname, WEAPON_ENT_CLASSNAME)
13545 set_pev(g_ent_weaponmodel[id], pev_movetype, MOVETYPE_FOLLOW)
13546 set_pev(g_ent_weaponmodel[id], pev_aiment, id)
13547 set_pev(g_ent_weaponmodel[id], pev_owner, id)
13548 }
13549
13550 engfunc(EngFunc_SetModel, g_ent_weaponmodel[id], model)
13551}
13552
13553// Remove Custom Model Entities
13554stock fm_remove_model_ents(id)
13555{
13556 // Remove "playermodel" ent if present
13557 if (pev_valid(g_ent_playermodel[id]))
13558 {
13559 engfunc(EngFunc_RemoveEntity, g_ent_playermodel[id])
13560 g_ent_playermodel[id] = 0
13561 }
13562 // Remove "weaponmodel" ent if present
13563 if (pev_valid(g_ent_weaponmodel[id]))
13564 {
13565 engfunc(EngFunc_RemoveEntity, g_ent_weaponmodel[id])
13566 g_ent_weaponmodel[id] = 0
13567 }
13568}
13569
13570// Set User Model
13571public fm_cs_set_user_model(taskid)
13572{
13573 set_user_info(ID_MODEL, "model", g_playermodel[ID_MODEL])
13574}
13575
13576// Get User Model -model passed byref-
13577stock fm_cs_get_user_model(player, model[], len)
13578{
13579 get_user_info(player, "model", model, len)
13580}
13581
13582// Update Player's Model on all clients (adding needed delays)
13583public fm_user_model_update(taskid)
13584{
13585 static Float:current_time
13586 current_time = get_gametime()
13587
13588 if (current_time - g_models_targettime >= g_modelchange_delay)
13589 {
13590 fm_cs_set_user_model(taskid)
13591 g_models_targettime = current_time
13592 }
13593 else
13594 {
13595 set_task((g_models_targettime + g_modelchange_delay) - current_time, "fm_cs_set_user_model", taskid)
13596 g_models_targettime = g_models_targettime + g_modelchange_delay
13597 }
13598}