· 6 years ago · Mar 30, 2020, 08:14 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#include <dhudmessage>
415
416native bool:get_user_gasmask(index);
417native set_user_gasmask(index, bool:value);
418
419/*================================================================================
420 [Constants, Offsets, Macros]
421=================================================================================*/
422
423// Plugin Version
424new const PLUGIN_VERSION[] = "4.3"
425
426// Customization file sections
427enum
428{
429 SECTION_NONE = 0,
430 SECTION_ACCESS_FLAGS,
431 SECTION_PLAYER_MODELS,
432 SECTION_WEAPON_MODELS,
433 SECTION_GRENADE_SPRITES,
434 SECTION_SOUNDS,
435 SECTION_AMBIENCE_SOUNDS,
436 SECTION_BUY_MENU_WEAPONS,
437 SECTION_EXTRA_ITEMS_WEAPONS,
438 SECTION_HARD_CODED_ITEMS_COSTS,
439 SECTION_WEATHER_EFFECTS,
440 SECTION_SKY,
441 SECTION_LIGHTNING,
442 SECTION_ZOMBIE_DECALS,
443 SECTION_KNOCKBACK,
444 SECTION_OBJECTIVE_ENTS,
445 SECTION_SVC_BAD
446}
447
448// Access flags
449enum
450{
451 ACCESS_ENABLE_MOD = 0,
452 ACCESS_ADMIN_MENU,
453 ACCESS_ADMIN_MODES_MENU,
454 ACCESS_MODE_INFECTION,
455 ACCESS_MODE_NEMESIS,
456 ACCESS_MODE_ASSASSIN,
457 ACCESS_MODE_SURVIVOR,
458 ACCESS_MODE_SNIPER,
459 ACCESS_MODE_SWARM,
460 ACCESS_MODE_MULTI,
461 ACCESS_MODE_PLAGUE,
462 ACCESS_MODE_ARMAGEDDON,
463 ACCESS_MODE_APOCALYPSE,
464 ACCESS_MODE_NIGHTMARE,
465 ACCESS_MAKE_ZOMBIE,
466 ACCESS_MAKE_HUMAN,
467 ACCESS_MAKE_NEMESIS,
468 ACCESS_MAKE_ASSASSIN,
469 ACCESS_MAKE_SURVIVOR,
470 ACCESS_MAKE_SNIPER,
471 ACCESS_RESPAWN_PLAYERS,
472 ACCESS_ADMIN_MODELS,
473 MAX_ACCESS_FLAGS
474}
475
476// Task offsets
477enum (+= 100)
478{
479 TASK_MODEL = 2000,
480 TASK_TEAM,
481 TASK_SPAWN,
482 TASK_BLOOD,
483 TASK_AURA,
484 TASK_BURN,
485 TASK_NVISION,
486 TASK_FLASH,
487 TASK_CHARGE,
488 TASK_SHOWHUD,
489 TASK_MAKEZOMBIE,
490 TASK_WELCOMEMSG,
491 TASK_THUNDER_PRE,
492 TASK_THUNDER,
493 TASK_AMBIENCESOUNDS
494}
495
496// IDs inside tasks
497#define ID_MODEL (taskid - TASK_MODEL)
498#define ID_TEAM (taskid - TASK_TEAM)
499#define ID_SPAWN (taskid - TASK_SPAWN)
500#define ID_BLOOD (taskid - TASK_BLOOD)
501#define ID_AURA (taskid - TASK_AURA)
502#define ID_BURN (taskid - TASK_BURN)
503#define ID_NVISION (taskid - TASK_NVISION)
504#define ID_FLASH (taskid - TASK_FLASH)
505#define ID_CHARGE (taskid - TASK_CHARGE)
506#define ID_SHOWHUD (taskid - TASK_SHOWHUD)
507
508// BP Ammo Refill task
509#define REFILL_WEAPONID args[0]
510
511// For weapon buy menu handlers
512#define WPN_STARTID g_menu_data[id][1]
513#define WPN_MAXIDS ArraySize(g_primary_items)
514#define WPN_SELECTION (g_menu_data[id][1]+key)
515#define WPN_AUTO_ON g_menu_data[id][2]
516#define WPN_AUTO_PRI g_menu_data[id][3]
517#define WPN_AUTO_SEC g_menu_data[id][4]
518
519// For player list menu handlers
520#define PL_ACTION g_menu_data[id][0]
521
522// For remembering menu pages
523#define MENU_PAGE_ZCLASS g_menu_data[id][5]
524#define MENU_PAGE_EXTRAS g_menu_data[id][6]
525#define MENU_PAGE_PLAYERS g_menu_data[id][7]
526
527// For extra items menu handlers
528#define EXTRAS_CUSTOM_STARTID (EXTRA_WEAPONS_STARTID + ArraySize(g_extraweapon_names))
529
530// Menu selections
531const MENU_KEY_AUTOSELECT = 7
532const MENU_KEY_BACK = 7
533const MENU_KEY_NEXT = 8
534const MENU_KEY_EXIT = 9
535
536// Hard coded extra items
537enum
538{
539 EXTRA_NVISION = 0,
540 EXTRA_ANTIDOTE,
541 EXTRA_MADNESS,
542 EXTRA_INFBOMB,
543 EXTRA_WEAPONS_STARTID
544}
545
546// Game modes
547enum
548{
549 MODE_NONE = 0,
550 MODE_INFECTION,
551 MODE_NEMESIS,
552 MODE_ASSASSIN,
553 MODE_SURVIVOR,
554 MODE_SNIPER,
555 MODE_SWARM,
556 MODE_MULTI,
557 MODE_PLAGUE,
558 MODE_ARMAGEDDON,
559 MODE_APOCALYPSE,
560 MODE_NIGHTMARE
561}
562
563// ZP Teams
564const ZP_TEAM_NO_ONE = 0
565const ZP_TEAM_ANY = 0
566const ZP_TEAM_ZOMBIE = (1<<0)
567const ZP_TEAM_HUMAN = (1<<1)
568const ZP_TEAM_NEMESIS = (1<<2)
569const ZP_TEAM_ASSASSIN = (1<<3)
570const ZP_TEAM_SURVIVOR = (1<<4)
571const ZP_TEAM_SNIPER = (1<<5)
572new const ZP_TEAM_NAMES[][] =
573{
574 "ZOMBIE , HUMAN",
575 "ZOMBIE",
576 "HUMAN",
577 "ZOMBIE , HUMAN",
578 "NEMESIS",
579 "ZOMBIE , NEMESIS",
580 "HUMAN , NEMESIS",
581 "ZOMBIE , HUMAN , NEMESIS",
582 "ASSASSIN",
583 "ZOMBIE , ASSASSIN",
584 "HUMAN , ASSASSIN",
585 "ZOMBIE, HUMAN, ASSASSIN",
586 "NEMESIS , ASSASSIN",
587 "ZOMBIE , NEMESIS , ASSASSIN",
588 "HUMAN, NEMESIS, ASSASSIN",
589 "ZOMBIE , HUMAN , NEMESIS , ASSASSIN",
590 "SURVIVOR",
591 "ZOMBIE, SURVIVOR",
592 "HUMAN, SURVIVOR",
593 "ZOMBIE, HUMAN, SURVIVOR",
594 "NEMESIS , SURVIVOR",
595 "ZOMBIE , NEMESIS , SURVIVOR",
596 "HUMAN , NEMESIS , SURVIVOR",
597 "ZOMBIE , HUMAN , NEMESIS , SURVIVOR",
598 "ASSASSIN, SURVIVOR",
599 "ZOMBIE, ASSASSIN, SURVIVOR",
600 "HUMAN, ASSASSIN, SURVIVOR",
601 "ZOMBIE, HUMAN, ASSASSIN, SURVIVOR",
602 "NEMESIS, ASSASSIN, SURVIVOR",
603 "ZOMBIE, NEMESIS, ASSASSIN, SURVIVOR",
604 "HUMAN, NEMESIS, ASSASSIN, SURVIVOR",
605 "ZOMBIE, HUMAN, NEMESIS, ASSASSIN, SURVIVOR",
606 "SNIPER",
607 "ZOMBIE, SNIPER",
608 "HUMAN, SNIPER",
609 "ZOMBIE, HUMAN, SNIPER",
610 "NEMESIS, SNIPER",
611 "ZOMBIE, NEMESIS, SNIPER",
612 "HUMAN, NEMESIS, SNIPER",
613 "ZOMBIE, HUMAN, NEMESIS, SNIPER",
614 "ASSASSIN, SNIPER",
615 "ZOMBIE, ASSASSIN, SNIPER",
616 "HUMAN, ASSASSIN, SNIPER",
617 "ZOMBIE, HUMAN, ASSASSIN, SNIPER",
618 "NEMESIS, ASSASSIN, SNIPER",
619 "ZOMBIE, NEMESIS, ASSASSIN, SNIPER",
620 "HUMAN, NEMESIS, ASSASSIN, SNIPER",
621 "ZOMBIE, HUMAN, NEMESIS, ASSASSIN, SNIPER",
622 "SURVIVOR, SNIPER",
623 "ZOMBIE, SURVIVOR, SNIPER",
624 "HUMAN, SURVIVOR, SNIPER",
625 "ZOMBIE, HUMAN, SURVIVOR, SNIPER",
626 "NEMESIS, SURVIVOR, SNIPER",
627 "ZOMBIE, NEMESIS, SURVIVOR, SNIPER",
628 "HUMAN, NEMESIS, SURVIVOR, SNIPER",
629 "ZOMBIE, HUMAN, NEMESIS, SURVIVOR, SNIPER",
630 "ASSASSIN, SURVIVOR, SNIPER",
631 "ZOMBIE, ASSASSIN, SURVIVOR, SNIPER",
632 "HUMAN, ASSASSIN, SURVIVOR, SNIPER",
633 "ZOMBIE, HUMAN, ASSASSIN, SURVIVOR, SNIPER",
634 "NEMESIS, ASSASSIN, SURVIVOR, SNIPER",
635 "ZOMBIE, NEMESIS, ASSASSIN, SURVIVOR, SNIPER",
636 "HUMAN, NEMESIS, ASSASSIN, SURVIVOR, SNIPER",
637 "ZOMBIE, HUMAN, NEMESIS, ASSASSIN, SURVIVOR, SNIPER"
638}
639
640// Zombie classes
641const ZCLASS_NONE = -1
642
643// HUD messages
644const Float:HUD_EVENT_X = -1.0
645const Float:HUD_EVENT_Y = 0.17
646const Float:HUD_INFECT_X = 0.05
647const Float:HUD_INFECT_Y = 0.45
648const Float:HUD_SPECT_X = -1.0
649const Float:HUD_SPECT_Y = 0.8
650const Float:HUD_STATS_X = 0.02
651const Float:HUD_STATS_Y = 0.9
652
653// Hack to be able to use Ham_Player_ResetMaxSpeed (by joaquimandrade)
654new Ham:Ham_Player_ResetMaxSpeed = Ham_Item_PreFrame
655
656// CS Player PData Offsets (win32)
657const PDATA_SAFE = 2
658const OFFSET_PAINSHOCK = 108 // ConnorMcLeod
659const OFFSET_CSTEAMS = 114
660const OFFSET_CSMONEY = 115
661const OFFSET_CSMENUCODE = 205
662const OFFSET_FLASHLIGHT_BATTERY = 244
663const OFFSET_CSDEATHS = 444
664const OFFSET_MODELINDEX = 491 // Orangutanz
665
666// CS Player CBase Offsets (win32)
667const OFFSET_ACTIVE_ITEM = 373
668
669// CS Weapon CBase Offsets (win32)
670const OFFSET_WEAPONOWNER = 41
671
672// Linux diff's
673const OFFSET_LINUX = 5 // offsets 5 higher in Linux builds
674const OFFSET_LINUX_WEAPONS = 4 // weapon offsets are only 4 steps higher on Linux
675
676// CS Teams
677enum
678{
679 FM_CS_TEAM_UNASSIGNED = 0,
680 FM_CS_TEAM_T,
681 FM_CS_TEAM_CT,
682 FM_CS_TEAM_SPECTATOR
683}
684new const CS_TEAM_NAMES[][] = { "UNASSIGNED", "TERRORIST", "CT", "SPECTATOR" }
685
686// Some constants
687const HIDE_MONEY = (1<<5)
688const UNIT_SECOND = (1<<12)
689const DMG_HEGRENADE = (1<<24)
690const IMPULSE_FLASHLIGHT = 100
691const USE_USING = 2
692const USE_STOPPED = 0
693const STEPTIME_SILENT = 999
694const BREAK_GLASS = 0x01
695const FFADE_IN = 0x0000
696const FFADE_STAYOUT = 0x0004
697const PEV_SPEC_TARGET = pev_iuser2
698
699// Max BP ammo for weapons
700new const MAXBPAMMO[] = { -1, 52, -1, 90, 1, 32, 1, 100, 90, 1, 120, 100, 100, 90, 90, 90, 100, 120,
701 30, 120, 200, 32, 90, 120, 90, 2, 35, 90, 90, -1, 100 }
702
703// Max Clip for weapons
704new const MAXCLIP[] = { -1, 13, -1, 10, -1, 7, -1, 30, 30, -1, 30, 20, 25, 30, 35, 25, 12, 20,
705 10, 30, 100, 8, 30, 30, 20, -1, 7, 30, 30, -1, 50 }
706
707// Amount of ammo to give when buying additional clips for weapons
708new const BUYAMMO[] = { -1, 13, -1, 30, -1, 8, -1, 12, 30, -1, 30, 50, 12, 30, 30, 30, 12, 30,
709 10, 30, 30, 8, 30, 30, 30, -1, 7, 30, 30, -1, 50 }
710
711// Ammo IDs for weapons
712new const AMMOID[] = { -1, 9, -1, 2, 12, 5, 14, 6, 4, 13, 10, 7, 6, 4, 4, 4, 6, 10,
713 1, 10, 3, 5, 4, 10, 2, 11, 8, 4, 2, -1, 7 }
714
715// Ammo Type Names for weapons
716new const AMMOTYPE[][] = { "", "357sig", "", "762nato", "", "buckshot", "", "45acp", "556nato", "", "9mm", "57mm", "45acp",
717 "556nato", "556nato", "556nato", "45acp", "9mm", "338magnum", "9mm", "556natobox", "buckshot",
718 "556nato", "9mm", "762nato", "", "50ae", "556nato", "762nato", "", "57mm" }
719
720// Weapon IDs for ammo types
721new const AMMOWEAPON[] = { 0, CSW_AWP, CSW_SCOUT, CSW_M249, CSW_AUG, CSW_XM1014, CSW_MAC10, CSW_FIVESEVEN, CSW_DEAGLE,
722 CSW_P228, CSW_ELITE, CSW_FLASHBANG, CSW_HEGRENADE, CSW_SMOKEGRENADE, CSW_C4 }
723
724// Primary and Secondary Weapon Names
725new const WEAPONNAMES[][] = { "", "P228 Compact", "", "Schmidt Scout", "", "XM1014 M4", "", "Ingram MAC-10", "Steyr AUG A1",
726 "", "Dual Elite Berettas", "FiveseveN", "UMP 45", "SG-550 Auto-Sniper", "IMI Galil", "Famas",
727 "USP .45 ACP Tactical", "Glock 18C", "AWP Magnum Sniper", "MP5 Navy", "M249 Para Machinegun",
728 "M3 Super 90", "M4A1 Carbine", "Schmidt TMP", "G3SG1 Auto-Sniper", "", "Desert Eagle .50 AE",
729 "SG-552 Commando", "AK-47 Kalashnikov", "", "ES P90" }
730
731// Weapon entity names
732new const WEAPONENTNAMES[][] = { "", "weapon_p228", "", "weapon_scout", "weapon_hegrenade", "weapon_xm1014", "weapon_c4", "weapon_mac10",
733 "weapon_aug", "weapon_smokegrenade", "weapon_elite", "weapon_fiveseven", "weapon_ump45", "weapon_sg550",
734 "weapon_galil", "weapon_famas", "weapon_usp", "weapon_glock18", "weapon_awp", "weapon_mp5navy", "weapon_m249",
735 "weapon_m3", "weapon_m4a1", "weapon_tmp", "weapon_g3sg1", "weapon_flashbang", "weapon_deagle", "weapon_sg552",
736 "weapon_ak47", "weapon_knife", "weapon_p90" }
737
738// CS sounds
739new const sound_flashlight[] = "items/flashlight1.wav"
740new const sound_buyammo[] = "items/9mmclip1.wav"
741new const sound_armorhit[] = "player/bhit_helmet-1.wav"
742
743// Explosion radius for custom grenades
744const Float:NADE_EXPLOSION_RADIUS = 240.0
745
746// HACK: pev_ field used to store additional ammo on weapons
747const PEV_ADDITIONAL_AMMO = pev_iuser1
748
749// HACK: pev_ field used to store custom nade types and their values
750const PEV_NADE_TYPE = pev_flTimeStepSound
751const NADE_TYPE_INFECTION = 1111
752const NADE_TYPE_NAPALM = 2222
753const NADE_TYPE_FROST = 3333
754const NADE_TYPE_FLARE = 4444
755const PEV_FLARE_COLOR = pev_punchangle
756const PEV_FLARE_DURATION = pev_flSwimTime
757
758// Weapon bitsums
759const 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)
760const SECONDARY_WEAPONS_BIT_SUM = (1<<CSW_P228)|(1<<CSW_ELITE)|(1<<CSW_FIVESEVEN)|(1<<CSW_USP)|(1<<CSW_GLOCK18)|(1<<CSW_DEAGLE)
761
762// Allowed weapons for zombies (added grenades/bomb for sub-plugin support, since they shouldn't be getting them anyway)
763const ZOMBIE_ALLOWED_WEAPONS_BITSUM = (1<<CSW_KNIFE)|(1<<CSW_HEGRENADE)|(1<<CSW_FLASHBANG)|(1<<CSW_SMOKEGRENADE)|(1<<CSW_C4)
764
765// Classnames for separate model entities
766new const MODEL_ENT_CLASSNAME[] = "player_model"
767new const WEAPON_ENT_CLASSNAME[] = "weapon_model"
768
769// Menu keys
770const 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
771
772// Ambience Sounds
773enum
774{
775 AMBIENCE_SOUNDS_INFECTION = 0,
776 AMBIENCE_SOUNDS_NEMESIS,
777 AMBIENCE_SOUNDS_ASSASSIN,
778 AMBIENCE_SOUNDS_SURVIVOR,
779 AMBIENCE_SOUNDS_SNIPER,
780 AMBIENCE_SOUNDS_SWARM,
781 AMBIENCE_SOUNDS_PLAGUE,
782 AMBIENCE_SOUNDS_ARMAGEDDON,
783 AMBIENCE_SOUNDS_APOCALYPSE,
784 AMBIENCE_SOUNDS_NIGHTMARE,
785 MAX_AMBIENCE_SOUNDS
786}
787
788// Admin menu actions
789enum
790{
791 ACTION_ZOMBIEFY_HUMANIZE = 0,
792 ACTION_MAKE_NEMESIS,
793 ACTION_MAKE_ASSASSIN,
794 ACTION_MAKE_SURVIVOR,
795 ACTION_MAKE_SNIPER,
796 ACTION_RESPAWN_PLAYER,
797 ACTION_MODES_MENU
798
799}
800
801// Admin modes menu actions
802enum
803{
804 ACTION_MODE_SWARM,
805 ACTION_MODE_MULTI,
806 ACTION_MODE_PLAGUE,
807 ACTION_MODE_ARMAGEDDON,
808 ACTION_MODE_APOCALYPSE,
809 ACTION_MODE_NIGHTMARE
810}
811
812// Custom forward return values
813const ZP_PLUGIN_HANDLED = 97
814
815/*================================================================================
816 [Global Variables]
817=================================================================================*/
818
819// Player vars
820new g_zombie[33] // is zombie
821new g_nemesis[33] // is nemesis
822new g_assassin[33] // is assassin
823new g_survivor[33] // is survivor
824new g_sniper[33] // is assassin
825new g_firstzombie[33] // is first zombie
826new g_lastzombie[33] // is last zombie
827new g_lasthuman[33] // is last human
828new g_frozen[33] // is frozen (can't move)
829new Float:g_frozen_gravity[33] // store previous gravity when frozen
830new g_nodamage[33] // has spawn protection/zombie madness
831new g_respawn_as_zombie[33] // should respawn as zombie
832new g_nvision[33] // has night vision
833new g_nvisionenabled[33] // has night vision turned on
834new g_zombieclass[33] // zombie class
835new g_zombieclassnext[33] // zombie class for next infection
836new g_flashlight[33] // has custom flashlight turned on
837new g_flashbattery[33] = { 100, ... } // custom flashlight battery
838new g_canbuy[33] // is allowed to buy a new weapon through the menu
839new g_ammopacks[33] // ammo pack count
840new g_damagedealt_human[33] // damage dealt as human (used to calculate ammo packs reward)
841new g_damagedealt_zombie[33] // damage dealt as zombie (used to calculate ammo packs reward)
842new Float:g_lastleaptime[33] // time leap was last used
843new Float:g_lastflashtime[33] // time flashlight was last toggled
844new g_playermodel[33][32] // current model's short name [player][model]
845new g_menu_data[33][8] // data for some menu handlers
846new g_ent_playermodel[33] // player model entity
847new g_ent_weaponmodel[33] // weapon model entity
848new g_burning_duration[33] // burning task duration
849new Float:g_buytime[33] // used to calculate custom buytime
850
851// Game vars
852new g_pluginenabled // ZP enabled
853new g_newround // new round starting
854new g_endround // round ended
855new g_nemround // nemesis round
856new g_assaround // assassin round
857new g_survround // survivor round
858new g_sniround // sniper round
859new g_swarmround // swarm round
860new g_plagueround // plague round
861new g_armageround // armageddon round
862new g_apocround // apocalypse round
863new g_nightround // nightmare round
864new g_modestarted // mode fully started
865new g_lastmode // last played mode
866new g_scorezombies, g_scorehumans, g_gamecommencing // team scores
867new g_spawnCount, g_spawnCount2 // available spawn points counter
868new Float:g_spawns[MAX_CSDM_SPAWNS][3], Float:g_spawns2[MAX_CSDM_SPAWNS][3] // spawn points data
869new g_lights_i // lightning current lights counter
870new g_lights_cycle[32] // current lightning cycle
871new g_lights_cycle_len // lightning cycle length
872new Float:g_models_targettime // for adding delays between Model Change messages
873new Float:g_teams_targettime // for adding delays between Team Change messages
874new g_MsgSync, g_MsgSync2, g_MsgSync3 // message sync objects
875new g_trailSpr, g_exploSpr, g_flameSpr, g_smokeSpr, g_glassSpr // grenade sprites
876new g_modname[32] // for formatting the mod name
877new g_freezetime // whether CS's freeze time is on
878new g_maxplayers // max players counter
879new g_czero // whether we are running on a CZ server
880new g_hamczbots // whether ham forwards are registered for CZ bots
881new g_fwSpawn, g_fwPrecacheSound // spawn and precache sound forward handles
882new g_infbombcounter, g_antidotecounter, g_madnesscounter // to limit buying some items
883new g_arrays_created // to prevent stuff from being registered before initializing arrays
884new g_lastplayerleaving // flag for whenever a player leaves and another takes his place
885new g_switchingteam // flag for whenever a player's team change emessage is sent
886new g_buyzone_ent // custom buyzone entity
887
888// Message IDs vars
889new g_msgScoreInfo, g_msgNVGToggle, g_msgScoreAttrib, g_msgAmmoPickup, g_msgScreenFade,
890g_msgDeathMsg, g_msgSetFOV, g_msgFlashlight, g_msgFlashBat, g_msgTeamInfo, g_msgDamage,
891g_msgHideWeapon, g_msgCrosshair, g_msgSayText, g_msgScreenShake, g_msgCurWeapon
892
893// Some forward handlers
894new g_fwRoundStart, g_fwRoundEnd, g_fwUserInfected_pre, g_fwUserInfected_post,
895g_fwUserHumanized_pre, g_fwUserHumanized_post, g_fwUserInfect_attempt,
896g_fwUserHumanize_attempt, g_fwExtraItemSelected, g_fwUserUnfrozen,
897g_fwUserLastZombie, g_fwUserLastHuman, g_fwDummyResult
898
899// Temporary Database vars (used to restore players stats in case they get disconnected)
900new db_name[MAX_STATS_SAVED][32] // player name
901new db_ammopacks[MAX_STATS_SAVED] // ammo pack count
902new db_zombieclass[MAX_STATS_SAVED] // zombie class
903new db_slot_i // additional saved slots counter (should start on maxplayers+1)
904
905// Extra Items vars
906new Array:g_extraitem_name // caption
907new Array:g_extraitem_cost // cost
908new Array:g_extraitem_team // team
909new g_extraitem_i // loaded extra items counter
910
911// For extra items file parsing
912new Array:g_extraitem2_realname, Array:g_extraitem2_name, Array:g_extraitem2_cost,
913Array:g_extraitem2_team, Array:g_extraitem_new
914
915// Zombie Classes vars
916new Array:g_zclass_name // caption
917new Array:g_zclass_info // description
918new Array:g_zclass_modelsstart // start position in models array
919new Array:g_zclass_modelsend // end position in models array
920new Array:g_zclass_playermodel // player models array
921new Array:g_zclass_modelindex // model indices array
922new Array:g_zclass_clawmodel // claw model
923new Array:g_zclass_hp // health
924new Array:g_zclass_spd // speed
925new Array:g_zclass_grav // gravity
926new Array:g_zclass_kb // knockback
927new g_zclass_i // loaded zombie classes counter
928
929// For zombie classes file parsing
930new Array:g_zclass2_realname, Array:g_zclass2_name, Array:g_zclass2_info,
931Array:g_zclass2_modelsstart, Array:g_zclass2_modelsend, Array:g_zclass2_playermodel,
932Array:g_zclass2_modelindex, Array:g_zclass2_clawmodel, Array:g_zclass2_hp,
933Array:g_zclass2_spd, Array:g_zclass2_grav, Array:g_zclass2_kb, Array:g_zclass_new
934
935// Customization vars
936new g_access_flag[MAX_ACCESS_FLAGS], Array:model_nemesis, Array:model_survivor, Array:model_human,
937Array:model_admin_zombie, Array:model_admin_human, Array:g_modelindex_human,
938Array:g_modelindex_nemesis, Array:g_modelindex_survivor, g_same_models_for_all,
939Array:g_modelindex_admin_zombie, Array:g_modelindex_admin_human, model_vknife_human[64],
940model_vknife_nemesis[64], model_vweapon_survivor[64], model_grenade_infect[64],
941model_grenade_fire[64], model_grenade_frost[64], model_grenade_flare[64],
942model_vknife_admin_human[64], model_vknife_admin_zombie[64],
943sprite_grenade_trail[64], sprite_grenade_ring[64], sprite_grenade_fire[64],
944sprite_grenade_smoke[64], sprite_grenade_glass[64], Array:sound_win_zombies,
945Array:sound_win_humans, Array:sound_win_no_one, Array:sound_win_zombies_ismp3,
946Array:sound_win_humans_ismp3, Array:sound_win_no_one_ismp3, Array:zombie_infect,
947Array:zombie_idle, Array:zombie_pain, Array:nemesis_pain, Array:zombie_die, Array:zombie_fall,
948Array:zombie_miss_wall, Array:zombie_hit_normal, Array:zombie_hit_stab, g_ambience_rain,
949Array:zombie_idle_last, Array:zombie_madness, Array:sound_nemesis, Array:sound_survivor,
950Array:sound_swarm, Array:sound_multi, Array:sound_plague, Array:grenade_infect,
951Array:grenade_infect_player, Array:grenade_fire, Array:grenade_fire_player,
952Array:grenade_frost, Array:grenade_frost_player, Array:grenade_frost_break,
953Array:grenade_flare, Array:sound_antidote, Array:sound_thunder, g_ambience_sounds[MAX_AMBIENCE_SOUNDS],
954Array:sound_ambience1, Array:sound_ambience2, Array:sound_ambience3, Array:sound_ambience4,
955Array:sound_ambience5, Array:sound_ambience1_duration, Array:sound_ambience2_duration,
956Array:sound_ambience3_duration, Array:sound_ambience4_duration,
957Array:sound_ambience5_duration, Array:sound_ambience1_ismp3, Array:sound_ambience2_ismp3,
958Array:sound_ambience3_ismp3, Array:sound_ambience4_ismp3, Array:sound_ambience5_ismp3,
959Array:g_primary_items, Array:g_secondary_items, Array:g_additional_items,
960Array:g_primary_weaponids, Array:g_secondary_weaponids, Array:g_extraweapon_names,
961Array:g_extraweapon_items, Array:g_extraweapon_costs, g_extra_costs2[EXTRA_WEAPONS_STARTID],
962g_ambience_snow, g_ambience_fog, g_fog_density[10], g_fog_color[12], g_sky_enable,
963Array:g_sky_names, Array:lights_thunder, Array:zombie_decals, Array:g_objective_ents,
964Float:g_modelchange_delay, g_set_modelindex_offset, g_handle_models_on_separate_ent,
965Float:kb_weapon_power[31] = { -1.0, ... }, Array:zombie_miss_slash, g_force_consistency,
966Array:model_assassin, Array:model_sniper, Array:g_modelindex_assassin, Array:g_modelindex_sniper, model_vknife_assassin[64],
967model_vawp_sniper[64], model_pawp_sniper[64], Array:assassin_pain, Array:sound_assassin, Array:sound_sniper, Array:sound_ambience6,
968Array:sound_ambience6_duration, Array:sound_ambience6_ismp3, Array:sound_ambience7, Array:sound_ambience7_duration, Array:sound_ambience7_ismp3,
969Array: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,
970Array:sound_ambience8_ismp3, Array:sound_ambience8, Array:sound_ambience8_duration
971
972
973// CVAR pointers
974new cvar_lighting, cvar_zombiefov, cvar_plague, cvar_plaguechance, cvar_zombiefirsthp,
975cvar_removemoney, cvar_thunder, cvar_zombiebonushp, cvar_nemhp, cvar_nem, cvar_surv,
976cvar_nemchance, cvar_deathmatch, cvar_nemglow, cvar_customnvg, cvar_hitzones, cvar_humanhp,
977cvar_nemgravity, cvar_flashsize, cvar_ammodamage_human, cvar_ammodamage_zombie,
978cvar_zombiearmor, cvar_survpainfree, cvar_nempainfree, cvar_nemspd, cvar_survchance,
979cvar_survhp, cvar_survspd, cvar_humanspd, cvar_swarmchance, cvar_flashdrain,
980cvar_zombiebleeding, cvar_removedoors, cvar_customflash, cvar_randspawn, cvar_multi,
981cvar_multichance, cvar_infammo, cvar_swarm, cvar_ammoinfect, cvar_toggle,
982cvar_knockbackpower, cvar_freezeduration, cvar_triggered, cvar_flashcharge,
983cvar_firegrenades, cvar_frostgrenades, cvar_survgravity, cvar_logcommands, cvar_survglow,
984cvar_humangravity, cvar_spawnprotection, cvar_nvgsize, cvar_flareduration, cvar_zclasses,
985cvar_extraitems, cvar_showactivity, cvar_humanlasthp, cvar_nemignorefrags, cvar_warmup,
986cvar_flashdist, cvar_flarecolor, cvar_survignorefrags, cvar_fireduration, cvar_firedamage,
987cvar_flaregrenades, cvar_knockbackducking, cvar_knockbackdamage, cvar_knockbackzvel,
988cvar_multiratio, cvar_flaresize, cvar_spawndelay, cvar_extraantidote, cvar_extramadness,
989cvar_extraweapons, cvar_extranvision, cvar_nvggive, cvar_preventconsecutive, cvar_botquota,
990cvar_buycustom, cvar_zombiepainfree, cvar_fireslowdown, cvar_survbasehp, cvar_survaura,
991cvar_nemignoreammo, cvar_survignoreammo, cvar_nemaura, cvar_extrainfbomb, cvar_knockback,
992cvar_fragsinfect, cvar_fragskill, cvar_humanarmor, cvar_zombiesilent, cvar_removedropped,
993cvar_plagueratio, cvar_blocksuicide, cvar_knockbackdist, cvar_nemdamage, cvar_leapzombies,
994cvar_leapzombiesforce, cvar_leapzombiesheight, cvar_leapzombiescooldown, cvar_leapnemesis,
995cvar_leapnemesisforce, cvar_leapnemesisheight, cvar_leapnemesiscooldown, cvar_leapsurvivor,
996cvar_leapsurvivorforce, cvar_leapsurvivorheight, cvar_nemminplayers, cvar_survminplayers,
997cvar_respawnonsuicide, cvar_respawnafterlast, cvar_leapsurvivorcooldown, cvar_statssave,
998cvar_swarmminplayers, cvar_multiminplayers, cvar_plagueminplayers, cvar_adminmodelshuman,
999cvar_adminmodelszombie, cvar_nembasehp, cvar_blockpushables, cvar_respawnworldspawnkill,
1000cvar_madnessduration, cvar_plaguenemnum, cvar_plaguenemhpmulti, cvar_plaguesurvhpmulti,
1001cvar_plaguesurvnum, cvar_infectionscreenfade, cvar_infectionscreenshake,
1002cvar_infectionsparkle, cvar_infectiontracers, cvar_infectionparticles, cvar_infbomblimit,
1003cvar_allowrespawnsurv, cvar_flashshowall, cvar_allowrespawninfection, cvar_allowrespawnnem,
1004cvar_allowrespawnswarm, cvar_allowrespawnplague, cvar_survinfammo, cvar_nemknockback,
1005cvar_nvgcolor[3], cvar_nemnvgcolor[3], cvar_humnvgcolor[3], cvar_flashcolor[3],
1006cvar_hudicons, cvar_respawnzomb, cvar_respawnhum, cvar_respawnnem, cvar_respawnsurv,
1007cvar_startammopacks, cvar_randweapons, cvar_antidotelimit, cvar_madnesslimit,
1008cvar_adminknifemodelshuman, cvar_adminknifemodelszombie, cvar_keephealthondisconnect,
1009cvar_buyzonetime, cvar_huddisplay, cvar_leapsniper, cvar_leapsniperforce, cvar_leapsniperheight,
1010cvar_leapsnipercooldown, cvar_sniminplayers, cvar_leapassassin, cvar_leapassassinforce, cvar_leapassassinheight,
1011cvar_leapassassincooldown, cvar_sni, cvar_snipainfree, cvar_snichance, cvar_snihp, cvar_snispd,
1012cvar_snigravity, cvar_sniglow, cvar_assahp, cvar_assa, cvar_assachance, cvar_assagravity, cvar_assaglow,
1013cvar_assapainfree, cvar_assaspd, cvar_assadamage, cvar_snibasehp, cvar_sniaura, cvar_assaminplayers,
1014cvar_assabasehp, cvar_allowrespawnassa, cvar_assaknockback, cvar_assanvgcolor[3], cvar_respawnassa, cvar_snidamage, cvar_allowrespawnsni,
1015cvar_sniinfammo, cvar_respawnsni, cvar_assaaura, cvar_assaignoreammo, cvar_assaignorefrags, cvar_snipignorefrags, cvar_snipignoreammo,
1016cvar_armage, cvar_armagechance, cvar_armageminplayers, cvar_armageratio, cvar_armagenemhpmulti, cvar_armagesurvhpmulti, cvar_apoc, cvar_apocchance,
1017cvar_apocminplayers, cvar_apocratio, cvar_apocassahpmulti, cvar_apocsniphpmulti, cvar_night, cvar_nightchance, cvar_nightminplayers, cvar_nightratio,
1018cvar_nightassahpmulti, cvar_nightsniphpmulti, cvar_nightnemhpmulti, cvar_nightsurvhpmulti, cvar_allowrespawnarmage, cvar_allowrespawnapoc, cvar_allowrespawnnight, cvar_aiminfo, cvar_dmg_while_freeze
1019
1020// Cached stuff for players
1021new g_isconnected[33] // whether player is connected
1022new g_isalive[33] // whether player is alive
1023new g_isbot[33] // whether player is a bot
1024new g_currentweapon[33] // player's current weapon id
1025new g_playername[33][32] // player's name
1026new Float:g_zombie_spd[33] // zombie class speed
1027new Float:g_zombie_knockback[33] // zombie class knockback
1028new g_zombie_classname[33][32] // zombie class name
1029#define is_user_valid_connected(%1) (1 <= %1 <= g_maxplayers && g_isconnected[%1])
1030#define is_user_valid_alive(%1) (1 <= %1 <= g_maxplayers && g_isalive[%1])
1031#define is_user_valid(%1) (1 <= %1 <= g_maxplayers)
1032
1033// Cached CVARs
1034new g_cached_customflash, g_cached_zombiesilent, g_cached_leapzombies, g_cached_leapnemesis,
1035g_cached_leapsurvivor, Float:g_cached_leapzombiescooldown, Float:g_cached_leapnemesiscooldown, g_cached_leapassassin, Float:g_cached_leapassassincooldown,
1036Float:g_cached_leapsurvivorcooldown, Float:g_cached_buytime, g_cached_leapsniper, Float:g_cached_leapsnipercooldown
1037
1038
1039/*================================================================================
1040 [Natives, Precache and Init]
1041=================================================================================*/
1042
1043public plugin_natives()
1044{
1045 // Player specific natives
1046 register_native("zp_get_user_zombie", "native_get_user_zombie", 1)
1047 register_native("zp_get_user_nemesis", "native_get_user_nemesis", 1)
1048 register_native("zp_get_user_assassin", "native_get_user_assassin", 1)
1049 register_native("zp_get_user_survivor", "native_get_user_survivor", 1)
1050 register_native("zp_get_user_sniper", "native_get_user_sniper", 1)
1051 register_native("zp_get_user_first_zombie", "native_get_user_first_zombie", 1)
1052 register_native("zp_get_user_last_zombie", "native_get_user_last_zombie", 1)
1053 register_native("zp_get_user_last_human", "native_get_user_last_human", 1)
1054 register_native("zp_get_user_zombie_class", "native_get_user_zombie_class", 1)
1055 register_native("zp_get_user_next_class", "native_get_user_next_class", 1)
1056 register_native("zp_set_user_zombie_class", "native_set_user_zombie_class", 1)
1057 register_native("zp_get_user_ammo_packs", "native_get_user_ammo_packs", 1)
1058 register_native("zp_set_user_ammo_packs", "native_set_user_ammo_packs", 1)
1059 register_native("zp_get_zombie_maxhealth", "native_get_zombie_maxhealth", 1)
1060 register_native("zp_get_user_batteries", "native_get_user_batteries", 1)
1061 register_native("zp_set_user_batteries", "native_set_user_batteries", 1)
1062 register_native("zp_get_user_nightvision", "native_get_user_nightvision", 1)
1063 register_native("zp_set_user_nightvision", "native_set_user_nightvision", 1)
1064 register_native("zp_infect_user", "native_infect_user", 1)
1065 register_native("zp_disinfect_user", "native_disinfect_user", 1)
1066 register_native("zp_make_user_nemesis", "native_make_user_nemesis", 1)
1067 register_native("zp_make_user_assassin", "native_make_user_assassin", 1)
1068 register_native("zp_make_user_survivor", "native_make_user_survivor", 1)
1069 register_native("zp_make_user_sniper", "native_make_user_sniper", 1)
1070 register_native("zp_respawn_user", "native_respawn_user", 1)
1071 register_native("zp_force_buy_extra_item", "native_force_buy_extra_item", 1)
1072 register_native("zp_override_user_model", "native_override_user_model", 1)
1073
1074 // new natives
1075 register_native("zp_get_user_model", "native_get_user_model", 0)
1076 register_native("zp_set_user_model", "native_set_user_model", 1)
1077
1078 // Round natives
1079 register_native("zp_has_round_started", "native_has_round_started", 1)
1080 register_native("zp_is_nemesis_round", "native_is_nemesis_round", 1)
1081 register_native("zp_is_assassin_round", "native_is_assassin_round", 1)
1082 register_native("zp_is_survivor_round", "native_is_survivor_round", 1)
1083 register_native("zp_is_sniper_round", "native_is_sniper_round", 1)
1084 register_native("zp_is_swarm_round", "native_is_swarm_round", 1)
1085 register_native("zp_is_plague_round", "native_is_plague_round", 1)
1086 register_native("zp_is_armageddon_round", "native_is_armageddon_round", 1)
1087 register_native("zp_is_apocalypse_round", "native_is_apocalypse_round", 1)
1088 register_native("zp_is_nightmare_round", "native_is_nightmare_round", 1)
1089 register_native("zp_get_zombie_count", "native_get_zombie_count", 1)
1090 register_native("zp_get_human_count", "native_get_human_count", 1)
1091 register_native("zp_get_nemesis_count", "native_get_nemesis_count", 1)
1092 register_native("zp_get_assassin_count", "native_get_assassin_count", 1)
1093 register_native("zp_get_survivor_count", "native_get_survivor_count", 1)
1094 register_native("zp_get_sniper_count", "native_get_sniper_count", 1)
1095
1096 // External additions natives
1097 register_native("zp_register_extra_item", "native_register_extra_item", 1)
1098 register_native("zp_register_zombie_class", "native_register_zombie_class", 1)
1099 register_native("zp_get_extra_item_id", "native_get_extra_item_id", 1)
1100 register_native("zp_get_zombie_class_id", "native_get_zombie_class_id", 1)
1101 register_native("zp_get_zombie_class_info", "native_get_zombie_class_info", 1)
1102}
1103
1104public plugin_precache()
1105{
1106 // Register earlier to show up in plugins list properly after plugin disable/error at loading
1107 register_plugin("Zombie Plague", PLUGIN_VERSION, "MeRcyLeZZ")
1108
1109 // To switch plugin on/off
1110 register_concmd("zp_toggle", "cmd_toggle", _, "<1/0> - Enable/Disable Zombie Plague (will restart the current map)", 0)
1111 cvar_toggle = register_cvar("zp_on", "1")
1112
1113 // Plugin disabled?
1114 if (!get_pcvar_num(cvar_toggle)) return;
1115 g_pluginenabled = true
1116
1117 // Initialize a few dynamically sized arrays (alright, maybe more than just a few...)
1118 model_human = ArrayCreate(32, 1)
1119 model_nemesis = ArrayCreate(32, 1)
1120 model_assassin = ArrayCreate(32, 1)
1121 model_survivor = ArrayCreate(32, 1)
1122 model_sniper = ArrayCreate(32, 1)
1123 model_admin_human = ArrayCreate(32, 1)
1124 model_admin_zombie = ArrayCreate(32, 1)
1125 g_modelindex_human = ArrayCreate(1, 1)
1126 g_modelindex_nemesis = ArrayCreate(1, 1)
1127 g_modelindex_assassin = ArrayCreate(1, 1)
1128 g_modelindex_survivor = ArrayCreate(1, 1)
1129 g_modelindex_sniper = ArrayCreate(1, 1)
1130 g_modelindex_admin_human = ArrayCreate(1, 1)
1131 g_modelindex_admin_zombie = ArrayCreate(1, 1)
1132 sound_win_zombies = ArrayCreate(64, 1)
1133 sound_win_zombies_ismp3 = ArrayCreate(1, 1)
1134 sound_win_humans = ArrayCreate(64, 1)
1135 sound_win_humans_ismp3 = ArrayCreate(1, 1)
1136 sound_win_no_one = ArrayCreate(64, 1)
1137 sound_win_no_one_ismp3 = ArrayCreate(1, 1)
1138 zombie_infect = ArrayCreate(64, 1)
1139 zombie_pain = ArrayCreate(64, 1)
1140 nemesis_pain = ArrayCreate(64, 1)
1141 assassin_pain = ArrayCreate(64, 1)
1142 zombie_die = ArrayCreate(64, 1)
1143 zombie_fall = ArrayCreate(64, 1)
1144 zombie_miss_slash = ArrayCreate(64, 1)
1145 zombie_miss_wall = ArrayCreate(64, 1)
1146 zombie_hit_normal = ArrayCreate(64, 1)
1147 zombie_hit_stab = ArrayCreate(64, 1)
1148 zombie_idle = ArrayCreate(64, 1)
1149 zombie_idle_last = ArrayCreate(64, 1)
1150 zombie_madness = ArrayCreate(64, 1)
1151 sound_nemesis = ArrayCreate(64, 1)
1152 sound_assassin = ArrayCreate(64, 1)
1153 sound_survivor = ArrayCreate(64, 1)
1154 sound_sniper = ArrayCreate(64, 1)
1155 sound_swarm = ArrayCreate(64, 1)
1156 sound_multi = ArrayCreate(64, 1)
1157 sound_plague = ArrayCreate(64, 1)
1158 sound_armageddon = ArrayCreate(64, 1)
1159 sound_apocalypse = ArrayCreate(64, 1)
1160 sound_nightmare = ArrayCreate(64, 1)
1161 grenade_infect = ArrayCreate(64, 1)
1162 grenade_infect_player = ArrayCreate(64, 1)
1163 grenade_fire = ArrayCreate(64, 1)
1164 grenade_fire_player = ArrayCreate(64, 1)
1165 grenade_frost = ArrayCreate(64, 1)
1166 grenade_frost_player = ArrayCreate(64, 1)
1167 grenade_frost_break = ArrayCreate(64, 1)
1168 grenade_flare = ArrayCreate(64, 1)
1169 sound_antidote = ArrayCreate(64, 1)
1170 sound_thunder = ArrayCreate(64, 1)
1171 sound_ambience1 = ArrayCreate(64, 1)
1172 sound_ambience2 = ArrayCreate(64, 1)
1173 sound_ambience3 = ArrayCreate(64, 1)
1174 sound_ambience4 = ArrayCreate(64, 1)
1175 sound_ambience5 = ArrayCreate(64, 1)
1176 sound_ambience6 = ArrayCreate(64, 1)
1177 sound_ambience7 = ArrayCreate(64, 1)
1178 sound_ambience8 = ArrayCreate(64, 1)
1179 sound_ambience9 = ArrayCreate(64, 1)
1180 sound_ambience10 = ArrayCreate(64, 1)
1181 sound_ambience1_duration = ArrayCreate(1, 1)
1182 sound_ambience2_duration = ArrayCreate(1, 1)
1183 sound_ambience3_duration = ArrayCreate(1, 1)
1184 sound_ambience4_duration = ArrayCreate(1, 1)
1185 sound_ambience5_duration = ArrayCreate(1, 1)
1186 sound_ambience6_duration = ArrayCreate(1, 1)
1187 sound_ambience7_duration = ArrayCreate(1, 1)
1188 sound_ambience8_duration = ArrayCreate(1, 1)
1189 sound_ambience9_duration = ArrayCreate(1, 1)
1190 sound_ambience10_duration = ArrayCreate(1, 1)
1191 sound_ambience1_ismp3 = ArrayCreate(1, 1)
1192 sound_ambience2_ismp3 = ArrayCreate(1, 1)
1193 sound_ambience3_ismp3 = ArrayCreate(1, 1)
1194 sound_ambience4_ismp3 = ArrayCreate(1, 1)
1195 sound_ambience5_ismp3 = ArrayCreate(1, 1)
1196 sound_ambience6_ismp3 = ArrayCreate(1, 1)
1197 sound_ambience7_ismp3 = ArrayCreate(1, 1)
1198 sound_ambience8_ismp3 = ArrayCreate(1, 1)
1199 sound_ambience9_ismp3 = ArrayCreate(1, 1)
1200 sound_ambience10_ismp3 = ArrayCreate(1, 1)
1201 g_primary_items = ArrayCreate(32, 1)
1202 g_secondary_items = ArrayCreate(32, 1)
1203 g_additional_items = ArrayCreate(32, 1)
1204 g_primary_weaponids = ArrayCreate(1, 1)
1205 g_secondary_weaponids = ArrayCreate(1, 1)
1206 g_extraweapon_names = ArrayCreate(32, 1)
1207 g_extraweapon_items = ArrayCreate(32, 1)
1208 g_extraweapon_costs = ArrayCreate(1, 1)
1209 g_sky_names = ArrayCreate(32, 1)
1210 lights_thunder = ArrayCreate(32, 1)
1211 zombie_decals = ArrayCreate(1, 1)
1212 g_objective_ents = ArrayCreate(32, 1)
1213 g_extraitem_name = ArrayCreate(32, 1)
1214 g_extraitem_cost = ArrayCreate(1, 1)
1215 g_extraitem_team = ArrayCreate(1, 1)
1216 g_extraitem2_realname = ArrayCreate(32, 1)
1217 g_extraitem2_name = ArrayCreate(32, 1)
1218 g_extraitem2_cost = ArrayCreate(1, 1)
1219 g_extraitem2_team = ArrayCreate(1, 1)
1220 g_extraitem_new = ArrayCreate(1, 1)
1221 g_zclass_name = ArrayCreate(32, 1)
1222 g_zclass_info = ArrayCreate(32, 1)
1223 g_zclass_modelsstart = ArrayCreate(1, 1)
1224 g_zclass_modelsend = ArrayCreate(1, 1)
1225 g_zclass_playermodel = ArrayCreate(32, 1)
1226 g_zclass_modelindex = ArrayCreate(1, 1)
1227 g_zclass_clawmodel = ArrayCreate(32, 1)
1228 g_zclass_hp = ArrayCreate(1, 1)
1229 g_zclass_spd = ArrayCreate(1, 1)
1230 g_zclass_grav = ArrayCreate(1, 1)
1231 g_zclass_kb = ArrayCreate(1, 1)
1232 g_zclass2_realname = ArrayCreate(32, 1)
1233 g_zclass2_name = ArrayCreate(32, 1)
1234 g_zclass2_info = ArrayCreate(32, 1)
1235 g_zclass2_modelsstart = ArrayCreate(1, 1)
1236 g_zclass2_modelsend = ArrayCreate(1, 1)
1237 g_zclass2_playermodel = ArrayCreate(32, 1)
1238 g_zclass2_modelindex = ArrayCreate(1, 1)
1239 g_zclass2_clawmodel = ArrayCreate(32, 1)
1240 g_zclass2_hp = ArrayCreate(1, 1)
1241 g_zclass2_spd = ArrayCreate(1, 1)
1242 g_zclass2_grav = ArrayCreate(1, 1)
1243 g_zclass2_kb = ArrayCreate(1, 1)
1244 g_zclass_new = ArrayCreate(1, 1)
1245
1246 // Allow registering stuff now
1247 g_arrays_created = true
1248
1249 // Load customization data
1250 load_customization_from_files()
1251
1252 new i, buffer[100]
1253
1254 // Load up the hard coded extra items
1255 native_register_extra_item2("NightVision", g_extra_costs2[EXTRA_NVISION], ZP_TEAM_HUMAN)
1256 native_register_extra_item2("T-Virus Antidote", g_extra_costs2[EXTRA_ANTIDOTE], ZP_TEAM_ZOMBIE)
1257 native_register_extra_item2("Zombie Madness", g_extra_costs2[EXTRA_MADNESS], ZP_TEAM_ZOMBIE)
1258 native_register_extra_item2("Infection Bomb", g_extra_costs2[EXTRA_INFBOMB], ZP_TEAM_ZOMBIE)
1259
1260 // Extra weapons
1261 for (i = 0; i < ArraySize(g_extraweapon_names); i++)
1262 {
1263 ArrayGetString(g_extraweapon_names, i, buffer, charsmax(buffer))
1264 native_register_extra_item2(buffer, ArrayGetCell(g_extraweapon_costs, i), ZP_TEAM_HUMAN)
1265 }
1266
1267 // Custom player models
1268 for (i = 0; i < ArraySize(model_human); i++)
1269 {
1270 ArrayGetString(model_human, i, buffer, charsmax(buffer))
1271 format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
1272 ArrayPushCell(g_modelindex_human, engfunc(EngFunc_PrecacheModel, buffer))
1273 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
1274 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
1275 // Precache modelT.mdl files too
1276 copy(buffer[strlen(buffer)-4], charsmax(buffer) - (strlen(buffer)-4), "T.mdl")
1277 if (file_exists(buffer)) engfunc(EngFunc_PrecacheModel, buffer)
1278 }
1279 for (i = 0; i < ArraySize(model_nemesis); i++)
1280 {
1281 ArrayGetString(model_nemesis, i, buffer, charsmax(buffer))
1282 format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
1283 ArrayPushCell(g_modelindex_nemesis, engfunc(EngFunc_PrecacheModel, buffer))
1284 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
1285 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
1286 // Precache modelT.mdl files too
1287 copy(buffer[strlen(buffer)-4], charsmax(buffer) - (strlen(buffer)-4), "T.mdl")
1288 if (file_exists(buffer)) engfunc(EngFunc_PrecacheModel, buffer)
1289 }
1290 for (i = 0; i < ArraySize(model_assassin); i++)
1291 {
1292 ArrayGetString(model_assassin, i, buffer, charsmax(buffer))
1293 format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
1294 ArrayPushCell(g_modelindex_assassin, engfunc(EngFunc_PrecacheModel, buffer))
1295 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
1296 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
1297 }
1298 for (i = 0; i < ArraySize(model_survivor); i++)
1299 {
1300 ArrayGetString(model_survivor, i, buffer, charsmax(buffer))
1301 format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
1302 ArrayPushCell(g_modelindex_survivor, engfunc(EngFunc_PrecacheModel, buffer))
1303 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
1304 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
1305 // Precache modelT.mdl files too
1306 copy(buffer[strlen(buffer)-4], charsmax(buffer) - (strlen(buffer)-4), "T.mdl")
1307 if (file_exists(buffer)) engfunc(EngFunc_PrecacheModel, buffer)
1308 }
1309 for (i = 0; i < ArraySize(model_sniper); i++)
1310 {
1311 ArrayGetString(model_sniper, i, buffer, charsmax(buffer))
1312 format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
1313 ArrayPushCell(g_modelindex_sniper, engfunc(EngFunc_PrecacheModel, buffer))
1314 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
1315 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
1316 }
1317 for (i = 0; i < ArraySize(model_admin_zombie); i++)
1318 {
1319 ArrayGetString(model_admin_zombie, i, buffer, charsmax(buffer))
1320 format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
1321 ArrayPushCell(g_modelindex_admin_zombie, engfunc(EngFunc_PrecacheModel, buffer))
1322 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
1323 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
1324 // Precache modelT.mdl files too
1325 copy(buffer[strlen(buffer)-4], charsmax(buffer) - (strlen(buffer)-4), "T.mdl")
1326 if (file_exists(buffer)) engfunc(EngFunc_PrecacheModel, buffer)
1327 }
1328 for (i = 0; i < ArraySize(model_admin_human); i++)
1329 {
1330 ArrayGetString(model_admin_human, i, buffer, charsmax(buffer))
1331 format(buffer, charsmax(buffer), "models/player/%s/%s.mdl", buffer, buffer)
1332 ArrayPushCell(g_modelindex_admin_human, engfunc(EngFunc_PrecacheModel, buffer))
1333 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, buffer)
1334 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, buffer)
1335 // Precache modelT.mdl files too
1336 copy(buffer[strlen(buffer)-4], charsmax(buffer) - (strlen(buffer)-4), "T.mdl")
1337 if (file_exists(buffer)) engfunc(EngFunc_PrecacheModel, buffer)
1338 }
1339
1340 // Custom weapon models
1341 engfunc(EngFunc_PrecacheModel, model_vknife_human)
1342 engfunc(EngFunc_PrecacheModel, model_vknife_nemesis)
1343 engfunc(EngFunc_PrecacheModel, model_vknife_assassin)
1344 engfunc(EngFunc_PrecacheModel, model_vweapon_survivor)
1345 engfunc(EngFunc_PrecacheModel, model_vawp_sniper)
1346 engfunc(EngFunc_PrecacheModel, model_pawp_sniper)
1347 engfunc(EngFunc_PrecacheModel, model_grenade_infect)
1348 engfunc(EngFunc_PrecacheModel, model_grenade_fire)
1349 engfunc(EngFunc_PrecacheModel, model_grenade_frost)
1350 engfunc(EngFunc_PrecacheModel, model_grenade_flare)
1351 engfunc(EngFunc_PrecacheModel, model_vknife_admin_human)
1352 engfunc(EngFunc_PrecacheModel, model_vknife_admin_zombie)
1353
1354 // Custom sprites for grenades
1355 g_trailSpr = engfunc(EngFunc_PrecacheModel, sprite_grenade_trail)
1356 g_exploSpr = engfunc(EngFunc_PrecacheModel, sprite_grenade_ring)
1357 g_flameSpr = engfunc(EngFunc_PrecacheModel, sprite_grenade_fire)
1358 g_smokeSpr = engfunc(EngFunc_PrecacheModel, sprite_grenade_smoke)
1359 g_glassSpr = engfunc(EngFunc_PrecacheModel, sprite_grenade_glass)
1360
1361 // Custom sounds
1362 for (i = 0; i < ArraySize(sound_win_zombies); i++)
1363 {
1364 ArrayGetString(sound_win_zombies, i, buffer, charsmax(buffer))
1365 if (ArrayGetCell(sound_win_zombies_ismp3, i))
1366 {
1367 format(buffer, charsmax(buffer), "sound/%s", buffer)
1368 engfunc(EngFunc_PrecacheGeneric, buffer)
1369 }
1370 else
1371 {
1372 engfunc(EngFunc_PrecacheSound, buffer)
1373 }
1374 }
1375 for (i = 0; i < ArraySize(sound_win_humans); i++)
1376 {
1377 ArrayGetString(sound_win_humans, i, buffer, charsmax(buffer))
1378 if (ArrayGetCell(sound_win_humans_ismp3, i))
1379 {
1380 format(buffer, charsmax(buffer), "sound/%s", buffer)
1381 engfunc(EngFunc_PrecacheGeneric, buffer)
1382 }
1383 else
1384 {
1385 engfunc(EngFunc_PrecacheSound, buffer)
1386 }
1387 }
1388 for (i = 0; i < ArraySize(sound_win_no_one); i++)
1389 {
1390 ArrayGetString(sound_win_no_one, i, buffer, charsmax(buffer))
1391 if (ArrayGetCell(sound_win_no_one_ismp3, i))
1392 {
1393 format(buffer, charsmax(buffer), "sound/%s", buffer)
1394 engfunc(EngFunc_PrecacheGeneric, buffer)
1395 }
1396 else
1397 {
1398 engfunc(EngFunc_PrecacheSound, buffer)
1399 }
1400 }
1401 for (i = 0; i < ArraySize(zombie_infect); i++)
1402 {
1403 ArrayGetString(zombie_infect, i, buffer, charsmax(buffer))
1404 engfunc(EngFunc_PrecacheSound, buffer)
1405 }
1406 for (i = 0; i < ArraySize(zombie_pain); i++)
1407 {
1408 ArrayGetString(zombie_pain, i, buffer, charsmax(buffer))
1409 engfunc(EngFunc_PrecacheSound, buffer)
1410 }
1411 for (i = 0; i < ArraySize(nemesis_pain); i++)
1412 {
1413 ArrayGetString(nemesis_pain, i, buffer, charsmax(buffer))
1414 engfunc(EngFunc_PrecacheSound, buffer)
1415 }
1416 for (i = 0; i < ArraySize(assassin_pain); i++)
1417 {
1418 ArrayGetString(assassin_pain, i, buffer, charsmax(buffer))
1419 engfunc(EngFunc_PrecacheSound, buffer)
1420 }
1421 for (i = 0; i < ArraySize(zombie_die); i++)
1422 {
1423 ArrayGetString(zombie_die, i, buffer, charsmax(buffer))
1424 engfunc(EngFunc_PrecacheSound, buffer)
1425 }
1426 for (i = 0; i < ArraySize(zombie_fall); i++)
1427 {
1428 ArrayGetString(zombie_fall, i, buffer, charsmax(buffer))
1429 engfunc(EngFunc_PrecacheSound, buffer)
1430 }
1431 for (i = 0; i < ArraySize(zombie_miss_slash); i++)
1432 {
1433 ArrayGetString(zombie_miss_slash, i, buffer, charsmax(buffer))
1434 engfunc(EngFunc_PrecacheSound, buffer)
1435 }
1436 for (i = 0; i < ArraySize(zombie_miss_wall); i++)
1437 {
1438 ArrayGetString(zombie_miss_wall, i, buffer, charsmax(buffer))
1439 engfunc(EngFunc_PrecacheSound, buffer)
1440 }
1441 for (i = 0; i < ArraySize(zombie_hit_normal); i++)
1442 {
1443 ArrayGetString(zombie_hit_normal, i, buffer, charsmax(buffer))
1444 engfunc(EngFunc_PrecacheSound, buffer)
1445 }
1446 for (i = 0; i < ArraySize(zombie_hit_stab); i++)
1447 {
1448 ArrayGetString(zombie_hit_stab, i, buffer, charsmax(buffer))
1449 engfunc(EngFunc_PrecacheSound, buffer)
1450 }
1451 for (i = 0; i < ArraySize(zombie_idle); i++)
1452 {
1453 ArrayGetString(zombie_idle, i, buffer, charsmax(buffer))
1454 engfunc(EngFunc_PrecacheSound, buffer)
1455 }
1456 for (i = 0; i < ArraySize(zombie_idle_last); i++)
1457 {
1458 ArrayGetString(zombie_idle_last, i, buffer, charsmax(buffer))
1459 engfunc(EngFunc_PrecacheSound, buffer)
1460 }
1461 for (i = 0; i < ArraySize(zombie_madness); i++)
1462 {
1463 ArrayGetString(zombie_madness, i, buffer, charsmax(buffer))
1464 engfunc(EngFunc_PrecacheSound, buffer)
1465 }
1466 for (i = 0; i < ArraySize(sound_nemesis); i++)
1467 {
1468 ArrayGetString(sound_nemesis, i, buffer, charsmax(buffer))
1469 engfunc(EngFunc_PrecacheSound, buffer)
1470 }
1471 for (i = 0; i < ArraySize(sound_assassin); i++)
1472 {
1473 ArrayGetString(sound_assassin, i, buffer, charsmax(buffer))
1474 engfunc(EngFunc_PrecacheSound, buffer)
1475 }
1476 for (i = 0; i < ArraySize(sound_survivor); i++)
1477 {
1478 ArrayGetString(sound_survivor, i, buffer, charsmax(buffer))
1479 engfunc(EngFunc_PrecacheSound, buffer)
1480 }
1481 for (i = 0; i < ArraySize(sound_sniper); i++)
1482 {
1483 ArrayGetString(sound_sniper, i, buffer, charsmax(buffer))
1484 engfunc(EngFunc_PrecacheSound, buffer)
1485 }
1486 for (i = 0; i < ArraySize(sound_swarm); i++)
1487 {
1488 ArrayGetString(sound_swarm, i, buffer, charsmax(buffer))
1489 engfunc(EngFunc_PrecacheSound, buffer)
1490 }
1491 for (i = 0; i < ArraySize(sound_multi); i++)
1492 {
1493 ArrayGetString(sound_multi, i, buffer, charsmax(buffer))
1494 engfunc(EngFunc_PrecacheSound, buffer)
1495 }
1496 for (i = 0; i < ArraySize(sound_plague); i++)
1497 {
1498 ArrayGetString(sound_plague, i, buffer, charsmax(buffer))
1499 engfunc(EngFunc_PrecacheSound, buffer)
1500 }
1501 for (i = 0; i < ArraySize(sound_armageddon); i++)
1502 {
1503 ArrayGetString(sound_armageddon, i, buffer, charsmax(buffer))
1504 engfunc(EngFunc_PrecacheSound, buffer)
1505 }
1506 for (i = 0; i < ArraySize(sound_apocalypse); i++)
1507 {
1508 ArrayGetString(sound_apocalypse, i, buffer, charsmax(buffer))
1509 engfunc(EngFunc_PrecacheSound, buffer)
1510 }
1511 for (i = 0; i < ArraySize(sound_nightmare); i++)
1512 {
1513 ArrayGetString(sound_nightmare, i, buffer, charsmax(buffer))
1514 engfunc(EngFunc_PrecacheSound, buffer)
1515 }
1516 for (i = 0; i < ArraySize(grenade_infect); i++)
1517 {
1518 ArrayGetString(grenade_infect, i, buffer, charsmax(buffer))
1519 engfunc(EngFunc_PrecacheSound, buffer)
1520 }
1521 for (i = 0; i < ArraySize(grenade_infect_player); i++)
1522 {
1523 ArrayGetString(grenade_infect_player, i, buffer, charsmax(buffer))
1524 engfunc(EngFunc_PrecacheSound, buffer)
1525 }
1526 for (i = 0; i < ArraySize(grenade_fire); i++)
1527 {
1528 ArrayGetString(grenade_fire, i, buffer, charsmax(buffer))
1529 engfunc(EngFunc_PrecacheSound, buffer)
1530 }
1531 for (i = 0; i < ArraySize(grenade_fire_player); i++)
1532 {
1533 ArrayGetString(grenade_fire_player, i, buffer, charsmax(buffer))
1534 engfunc(EngFunc_PrecacheSound, buffer)
1535 }
1536 for (i = 0; i < ArraySize(grenade_frost); i++)
1537 {
1538 ArrayGetString(grenade_frost, i, buffer, charsmax(buffer))
1539 engfunc(EngFunc_PrecacheSound, buffer)
1540 }
1541 for (i = 0; i < ArraySize(grenade_frost_player); i++)
1542 {
1543 ArrayGetString(grenade_frost_player, i, buffer, charsmax(buffer))
1544 engfunc(EngFunc_PrecacheSound, buffer)
1545 }
1546 for (i = 0; i < ArraySize(grenade_frost_break); i++)
1547 {
1548 ArrayGetString(grenade_frost_break, i, buffer, charsmax(buffer))
1549 engfunc(EngFunc_PrecacheSound, buffer)
1550 }
1551 for (i = 0; i < ArraySize(grenade_flare); i++)
1552 {
1553 ArrayGetString(grenade_flare, i, buffer, charsmax(buffer))
1554 engfunc(EngFunc_PrecacheSound, buffer)
1555 }
1556 for (i = 0; i < ArraySize(sound_antidote); i++)
1557 {
1558 ArrayGetString(sound_antidote, i, buffer, charsmax(buffer))
1559 engfunc(EngFunc_PrecacheSound, buffer)
1560 }
1561 for (i = 0; i < ArraySize(sound_thunder); i++)
1562 {
1563 ArrayGetString(sound_thunder, i, buffer, charsmax(buffer))
1564 engfunc(EngFunc_PrecacheSound, buffer)
1565 }
1566
1567 // Ambience Sounds
1568 if (g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION])
1569 {
1570 for (i = 0; i < ArraySize(sound_ambience1); i++)
1571 {
1572 ArrayGetString(sound_ambience1, i, buffer, charsmax(buffer))
1573
1574 if (ArrayGetCell(sound_ambience1_ismp3, i))
1575 {
1576 format(buffer, charsmax(buffer), "sound/%s", buffer)
1577 engfunc(EngFunc_PrecacheGeneric, buffer)
1578 }
1579 else
1580 {
1581 engfunc(EngFunc_PrecacheSound, buffer)
1582 }
1583 }
1584 }
1585 if (g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS])
1586 {
1587 for (i = 0; i < ArraySize(sound_ambience2); i++)
1588 {
1589 ArrayGetString(sound_ambience2, i, buffer, charsmax(buffer))
1590
1591 if (ArrayGetCell(sound_ambience2_ismp3, i))
1592 {
1593 format(buffer, charsmax(buffer), "sound/%s", buffer)
1594 engfunc(EngFunc_PrecacheGeneric, buffer)
1595 }
1596 else
1597 {
1598 engfunc(EngFunc_PrecacheSound, buffer)
1599 }
1600 }
1601 }
1602 if (g_ambience_sounds[AMBIENCE_SOUNDS_ASSASSIN])
1603 {
1604 for (i = 0; i < ArraySize(sound_ambience6); i++)
1605 {
1606 ArrayGetString(sound_ambience6, i, buffer, charsmax(buffer))
1607
1608 if (ArrayGetCell(sound_ambience6_ismp3, i))
1609 {
1610 format(buffer, charsmax(buffer), "sound/%s", buffer)
1611 engfunc(EngFunc_PrecacheGeneric, buffer)
1612 }
1613 else
1614 {
1615 engfunc(EngFunc_PrecacheSound, buffer)
1616 }
1617 }
1618 }
1619 if (g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR])
1620 {
1621 for (i = 0; i < ArraySize(sound_ambience3); i++)
1622 {
1623 ArrayGetString(sound_ambience3, i, buffer, charsmax(buffer))
1624
1625 if (ArrayGetCell(sound_ambience3_ismp3, i))
1626 {
1627 format(buffer, charsmax(buffer), "sound/%s", buffer)
1628 engfunc(EngFunc_PrecacheGeneric, buffer)
1629 }
1630 else
1631 {
1632 engfunc(EngFunc_PrecacheSound, buffer)
1633 }
1634 }
1635 }
1636 if (g_ambience_sounds[AMBIENCE_SOUNDS_SNIPER])
1637 {
1638 for (i = 0; i < ArraySize(sound_ambience5); i++)
1639 {
1640 ArrayGetString(sound_ambience5, i, buffer, charsmax(buffer))
1641
1642 if (ArrayGetCell(sound_ambience5_ismp3, i))
1643 {
1644 format(buffer, charsmax(buffer), "sound/%s", buffer)
1645 engfunc(EngFunc_PrecacheGeneric, buffer)
1646 }
1647 else
1648 {
1649 engfunc(EngFunc_PrecacheSound, buffer)
1650 }
1651 }
1652 }
1653 if (g_ambience_sounds[AMBIENCE_SOUNDS_SWARM])
1654 {
1655 for (i = 0; i < ArraySize(sound_ambience4); i++)
1656 {
1657 ArrayGetString(sound_ambience4, i, buffer, charsmax(buffer))
1658
1659 if (ArrayGetCell(sound_ambience4_ismp3, i))
1660 {
1661 format(buffer, charsmax(buffer), "sound/%s", buffer)
1662 engfunc(EngFunc_PrecacheGeneric, buffer)
1663 }
1664 else
1665 {
1666 engfunc(EngFunc_PrecacheSound, buffer)
1667 }
1668 }
1669 }
1670 if (g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE])
1671 {
1672 for (i = 0; i < ArraySize(sound_ambience5); i++)
1673 {
1674 ArrayGetString(sound_ambience5, i, buffer, charsmax(buffer))
1675
1676 if (ArrayGetCell(sound_ambience5_ismp3, i))
1677 {
1678 format(buffer, charsmax(buffer), "sound/%s", buffer)
1679 engfunc(EngFunc_PrecacheGeneric, buffer)
1680 }
1681 else
1682 {
1683 engfunc(EngFunc_PrecacheSound, buffer)
1684 }
1685 }
1686 }
1687 if (g_ambience_sounds[AMBIENCE_SOUNDS_ARMAGEDDON])
1688 {
1689 for (i = 0; i < ArraySize(sound_ambience8); i++)
1690 {
1691 ArrayGetString(sound_ambience8, i, buffer, charsmax(buffer))
1692
1693 if (ArrayGetCell(sound_ambience8_ismp3, i))
1694 {
1695 format(buffer, charsmax(buffer), "sound/%s", buffer)
1696 engfunc(EngFunc_PrecacheGeneric, buffer)
1697 }
1698 else
1699 {
1700 engfunc(EngFunc_PrecacheSound, buffer)
1701 }
1702 }
1703 }
1704 if (g_ambience_sounds[AMBIENCE_SOUNDS_APOCALYPSE])
1705 {
1706 for (i = 0; i < ArraySize(sound_ambience9); i++)
1707 {
1708 ArrayGetString(sound_ambience9, i, buffer, charsmax(buffer))
1709
1710 if (ArrayGetCell(sound_ambience9_ismp3, i))
1711 {
1712 format(buffer, charsmax(buffer), "sound/%s", buffer)
1713 engfunc(EngFunc_PrecacheGeneric, buffer)
1714 }
1715 else
1716 {
1717 engfunc(EngFunc_PrecacheSound, buffer)
1718 }
1719 }
1720 }
1721 if (g_ambience_sounds[AMBIENCE_SOUNDS_NIGHTMARE])
1722 {
1723 for (i = 0; i < ArraySize(sound_ambience10); i++)
1724 {
1725 ArrayGetString(sound_ambience10, i, buffer, charsmax(buffer))
1726
1727 if (ArrayGetCell(sound_ambience10_ismp3, i))
1728 {
1729 format(buffer, charsmax(buffer), "sound/%s", buffer)
1730 engfunc(EngFunc_PrecacheGeneric, buffer)
1731 }
1732 else
1733 {
1734 engfunc(EngFunc_PrecacheSound, buffer)
1735 }
1736 }
1737 }
1738
1739 // CS sounds (just in case)
1740 engfunc(EngFunc_PrecacheSound, sound_flashlight)
1741 engfunc(EngFunc_PrecacheSound, sound_buyammo)
1742 engfunc(EngFunc_PrecacheSound, sound_armorhit)
1743
1744 new ent
1745
1746 // Fake Hostage (to force round ending)
1747 ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "hostage_entity"))
1748 if (pev_valid(ent))
1749 {
1750 engfunc(EngFunc_SetOrigin, ent, Float:{8192.0,8192.0,8192.0})
1751 dllfunc(DLLFunc_Spawn, ent)
1752 }
1753
1754 // Weather/ambience effects
1755 if (g_ambience_fog)
1756 {
1757 ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "env_fog"))
1758 if (pev_valid(ent))
1759 {
1760 fm_set_kvd(ent, "density", g_fog_density, "env_fog")
1761 fm_set_kvd(ent, "rendercolor", g_fog_color, "env_fog")
1762 }
1763 }
1764 if (g_ambience_rain) engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "env_rain"))
1765 if (g_ambience_snow) engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "env_snow"))
1766
1767 // Custom buyzone for all players
1768 g_buyzone_ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "func_buyzone"))
1769 if (pev_valid(g_buyzone_ent))
1770 {
1771 dllfunc(DLLFunc_Spawn, g_buyzone_ent)
1772 set_pev(g_buyzone_ent, pev_solid, SOLID_NOT)
1773 }
1774
1775 // Prevent some entities from spawning
1776 g_fwSpawn = register_forward(FM_Spawn, "fw_Spawn")
1777
1778 // Prevent hostage sounds from being precached
1779 g_fwPrecacheSound = register_forward(FM_PrecacheSound, "fw_PrecacheSound")
1780}
1781
1782public plugin_init()
1783{
1784 // Plugin disabled?
1785 if (!g_pluginenabled) return;
1786
1787 // No zombie classes?
1788 if (!g_zclass_i) set_fail_state("No zombie classes loaded!")
1789
1790 // Language files
1791 register_dictionary("zombie_plague.txt")
1792
1793 // Events
1794 register_event("HLTV", "event_round_start", "a", "1=0", "2=0")
1795 register_event("StatusValue", "event_show_status", "be", "1=2", "2!0")
1796 register_event("StatusValue", "event_hide_status", "be", "1=1", "2=0")
1797 register_logevent("logevent_round_start",2, "1=Round_Start")
1798 register_logevent("logevent_round_end", 2, "1=Round_End")
1799 register_event("AmmoX", "event_ammo_x", "be")
1800 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]
1801 || 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])
1802 register_event("30", "event_intermission", "a")
1803
1804 // HAM Forwards
1805 RegisterHam(Ham_Spawn, "player", "fw_PlayerSpawn_Post", 1)
1806 RegisterHam(Ham_Killed, "player", "fw_PlayerKilled")
1807 RegisterHam(Ham_Killed, "player", "fw_PlayerKilled_Post", 1)
1808 RegisterHam(Ham_TakeDamage, "player", "fw_TakeDamage")
1809 RegisterHam(Ham_TakeDamage, "player", "fw_TakeDamage_Post", 1)
1810 RegisterHam(Ham_TraceAttack, "player", "fw_TraceAttack")
1811 RegisterHam(Ham_Player_ResetMaxSpeed, "player", "fw_ResetMaxSpeed_Post", 1)
1812 RegisterHam(Ham_Use, "func_tank", "fw_UseStationary")
1813 RegisterHam(Ham_Use, "func_tankmortar", "fw_UseStationary")
1814 RegisterHam(Ham_Use, "func_tankrocket", "fw_UseStationary")
1815 RegisterHam(Ham_Use, "func_tanklaser", "fw_UseStationary")
1816 RegisterHam(Ham_Use, "func_tank", "fw_UseStationary_Post", 1)
1817 RegisterHam(Ham_Use, "func_tankmortar", "fw_UseStationary_Post", 1)
1818 RegisterHam(Ham_Use, "func_tankrocket", "fw_UseStationary_Post", 1)
1819 RegisterHam(Ham_Use, "func_tanklaser", "fw_UseStationary_Post", 1)
1820 RegisterHam(Ham_Use, "func_pushable", "fw_UsePushable")
1821 RegisterHam(Ham_Touch, "weaponbox", "fw_TouchWeapon")
1822 RegisterHam(Ham_Touch, "armoury_entity", "fw_TouchWeapon")
1823 RegisterHam(Ham_Touch, "weapon_shield", "fw_TouchWeapon")
1824 RegisterHam(Ham_AddPlayerItem, "player", "fw_AddPlayerItem")
1825 for (new i = 1; i < sizeof WEAPONENTNAMES; i++)
1826 if (WEAPONENTNAMES[i][0]) RegisterHam(Ham_Item_Deploy, WEAPONENTNAMES[i], "fw_Item_Deploy_Post", 1)
1827
1828 // FM Forwards
1829 register_forward(FM_ClientDisconnect, "fw_ClientDisconnect")
1830 register_forward(FM_ClientDisconnect, "fw_ClientDisconnect_Post", 1)
1831 register_forward(FM_ClientKill, "fw_ClientKill")
1832 register_forward(FM_EmitSound, "fw_EmitSound")
1833 if (!g_handle_models_on_separate_ent) register_forward(FM_SetClientKeyValue, "fw_SetClientKeyValue")
1834 register_forward(FM_ClientUserInfoChanged, "fw_ClientUserInfoChanged")
1835 register_forward(FM_GetGameDescription, "fw_GetGameDescription")
1836 register_forward(FM_SetModel, "fw_SetModel")
1837 RegisterHam(Ham_Think, "grenade", "fw_ThinkGrenade")
1838 register_forward(FM_CmdStart, "fw_CmdStart")
1839 register_forward(FM_PlayerPreThink, "fw_PlayerPreThink")
1840 unregister_forward(FM_Spawn, g_fwSpawn)
1841 unregister_forward(FM_PrecacheSound, g_fwPrecacheSound)
1842
1843 // Client commands
1844 register_clcmd("say zpmenu", "clcmd_saymenu")
1845 register_clcmd("say /zpmenu", "clcmd_saymenu")
1846 register_clcmd("say unstuck", "clcmd_sayunstuck")
1847 register_clcmd("say /unstuck", "clcmd_sayunstuck")
1848 register_clcmd("nightvision", "clcmd_nightvision")
1849 register_clcmd("drop", "clcmd_drop")
1850 register_clcmd("buyammo1", "clcmd_buyammo")
1851 register_clcmd("buyammo2", "clcmd_buyammo")
1852 register_clcmd("chooseteam", "clcmd_changeteam")
1853 register_clcmd("jointeam", "clcmd_changeteam")
1854
1855 // Menus
1856 register_menu("Game Menu", KEYSMENU, "menu_game")
1857 register_menu("Buy Menu 1", KEYSMENU, "menu_buy1")
1858 register_menu("Buy Menu 2", KEYSMENU, "menu_buy2")
1859 register_menu("Mod Info", KEYSMENU, "menu_info")
1860 register_menu("Admin Menu", KEYSMENU, "menu_admin")
1861 register_menu("Admin Modes Menu", KEYSMENU, "menu_modes_admin")
1862
1863 // CS Buy Menus (to prevent zombies/survivor from buying)
1864 register_menucmd(register_menuid("#Buy", 1), 511, "menu_cs_buy")
1865 register_menucmd(register_menuid("BuyPistol", 1), 511, "menu_cs_buy")
1866 register_menucmd(register_menuid("BuyShotgun", 1), 511, "menu_cs_buy")
1867 register_menucmd(register_menuid("BuySub", 1), 511, "menu_cs_buy")
1868 register_menucmd(register_menuid("BuyRifle", 1), 511, "menu_cs_buy")
1869 register_menucmd(register_menuid("BuyMachine", 1), 511, "menu_cs_buy")
1870 register_menucmd(register_menuid("BuyItem", 1), 511, "menu_cs_buy")
1871 register_menucmd(-28, 511, "menu_cs_buy")
1872 register_menucmd(-29, 511, "menu_cs_buy")
1873 register_menucmd(-30, 511, "menu_cs_buy")
1874 register_menucmd(-32, 511, "menu_cs_buy")
1875 register_menucmd(-31, 511, "menu_cs_buy")
1876 register_menucmd(-33, 511, "menu_cs_buy")
1877 register_menucmd(-34, 511, "menu_cs_buy")
1878
1879 // Admin commands
1880 register_concmd("zp_zombie", "cmd_zombie", _, "<target> - Turn someone into a Zombie", 0)
1881 register_concmd("zp_human", "cmd_human", _, "<target> - Turn someone back to Human", 0)
1882 register_concmd("zp_nemesis", "cmd_nemesis", _, "<target> - Turn someone into a Nemesis", 0)
1883 register_concmd("zp_assassin", "cmd_assassin", _, "<target> - Turn someone into an Assassin", 0)
1884 register_concmd("zp_survivor", "cmd_survivor", _, "<target> - Turn someone into a Survivor", 0)
1885 register_concmd("zp_sniper", "cmd_sniper", _, "<target> - Turn someone into a Sniper", 0)
1886 register_concmd("zp_respawn", "cmd_respawn", _, "<target> - Respawn someone", 0)
1887 register_concmd("zp_swarm", "cmd_swarm", _, " - Start Swarm Mode", 0)
1888 register_concmd("zp_multi", "cmd_multi", _, " - Start Multi Infection", 0)
1889 register_concmd("zp_plague", "cmd_plague", _, " - Start Plague Mode", 0)
1890 register_concmd("zp_armageddon", "cmd_armageddon", _, " - Start Armageddon Mode", 0)
1891 register_concmd("zp_apocalypse", "cmd_apocalypse", _, " - Start Apocalypse Mode", 0)
1892 register_concmd("zp_nightmare", "cmd_nightmare", _, " - Start Nightmare Mode", 0)
1893
1894 // Message IDs
1895 g_msgScoreInfo = get_user_msgid("ScoreInfo")
1896 g_msgTeamInfo = get_user_msgid("TeamInfo")
1897 g_msgDeathMsg = get_user_msgid("DeathMsg")
1898 g_msgScoreAttrib = get_user_msgid("ScoreAttrib")
1899 g_msgSetFOV = get_user_msgid("SetFOV")
1900 g_msgScreenFade = get_user_msgid("ScreenFade")
1901 g_msgScreenShake = get_user_msgid("ScreenShake")
1902 g_msgNVGToggle = get_user_msgid("NVGToggle")
1903 g_msgFlashlight = get_user_msgid("Flashlight")
1904 g_msgFlashBat = get_user_msgid("FlashBat")
1905 g_msgAmmoPickup = get_user_msgid("AmmoPickup")
1906 g_msgDamage = get_user_msgid("Damage")
1907 g_msgHideWeapon = get_user_msgid("HideWeapon")
1908 g_msgCrosshair = get_user_msgid("Crosshair")
1909 g_msgSayText = get_user_msgid("SayText")
1910 g_msgCurWeapon = get_user_msgid("CurWeapon")
1911
1912 // Message hooks
1913 register_message(g_msgCurWeapon, "message_cur_weapon")
1914 register_message(get_user_msgid("Money"), "message_money")
1915 register_message(get_user_msgid("Health"), "message_health")
1916 register_message(g_msgFlashBat, "message_flashbat")
1917 register_message(g_msgScreenFade, "message_screenfade")
1918 register_message(g_msgNVGToggle, "message_nvgtoggle")
1919 if (g_handle_models_on_separate_ent) register_message(get_user_msgid("ClCorpse"), "message_clcorpse")
1920 register_message(get_user_msgid("WeapPickup"), "message_weappickup")
1921 register_message(g_msgAmmoPickup, "message_ammopickup")
1922 register_message(get_user_msgid("Scenario"), "message_scenario")
1923 register_message(get_user_msgid("HostagePos"), "message_hostagepos")
1924 register_message(get_user_msgid("TextMsg"), "message_textmsg")
1925 register_message(get_user_msgid("SendAudio"), "message_sendaudio")
1926 register_message(get_user_msgid("TeamScore"), "message_teamscore")
1927 register_message(g_msgTeamInfo, "message_teaminfo")
1928
1929 // CVARS - General Purpose
1930 cvar_warmup = register_cvar("zp_delay", "10")
1931 cvar_lighting = register_cvar("zp_lighting", "a")
1932 cvar_thunder = register_cvar("zp_thunderclap", "90")
1933 cvar_triggered = register_cvar("zp_triggered_lights", "1")
1934 cvar_removedoors = register_cvar("zp_remove_doors", "0")
1935 cvar_blockpushables = register_cvar("zp_blockuse_pushables", "1")
1936 cvar_blocksuicide = register_cvar("zp_block_suicide", "1")
1937 cvar_randspawn = register_cvar("zp_random_spawn", "1")
1938 cvar_respawnworldspawnkill = register_cvar("zp_respawn_on_worldspawn_kill", "1")
1939 cvar_removedropped = register_cvar("zp_remove_dropped", "0")
1940 cvar_removemoney = register_cvar("zp_remove_money", "1")
1941 cvar_buycustom = register_cvar("zp_buy_custom", "1")
1942 cvar_buyzonetime = register_cvar("zp_buyzone_time", "0.0")
1943 cvar_randweapons = register_cvar("zp_random_weapons", "0")
1944 cvar_adminmodelshuman = register_cvar("zp_admin_models_human", "1")
1945 cvar_adminknifemodelshuman = register_cvar("zp_admin_knife_models_human", "0")
1946 cvar_adminmodelszombie = register_cvar("zp_admin_models_zombie", "1")
1947 cvar_adminknifemodelszombie = register_cvar("zp_admin_knife_models_zombie", "0")
1948 cvar_zclasses = register_cvar("zp_zombie_classes", "1")
1949 cvar_statssave = register_cvar("zp_stats_save", "1")
1950 cvar_startammopacks = register_cvar("zp_starting_ammo_packs", "5")
1951 cvar_preventconsecutive = register_cvar("zp_prevent_consecutive_modes", "1")
1952 cvar_keephealthondisconnect = register_cvar("zp_keep_health_on_disconnect", "1")
1953 cvar_huddisplay = register_cvar("zp_hud_display", "1")
1954 cvar_aiminfo = register_cvar("zp_aim_info", "1")
1955 cvar_dmg_while_freeze = register_cvar("zp_dmg_while_frost", "1")
1956
1957 // CVARS - Deathmatch
1958 cvar_deathmatch = register_cvar("zp_deathmatch", "0")
1959 cvar_spawndelay = register_cvar("zp_spawn_delay", "5")
1960 cvar_spawnprotection = register_cvar("zp_spawn_protection", "5")
1961 cvar_respawnonsuicide = register_cvar("zp_respawn_on_suicide", "0")
1962 cvar_respawnafterlast = register_cvar("zp_respawn_after_last_human", "1")
1963 cvar_allowrespawninfection = register_cvar("zp_infection_allow_respawn", "1")
1964 cvar_allowrespawnnem = register_cvar("zp_nem_allow_respawn", "0")
1965 cvar_allowrespawnassa = register_cvar("zp_assa_allow_respawn", "0")
1966 cvar_allowrespawnsurv = register_cvar("zp_surv_allow_respawn", "0")
1967 cvar_allowrespawnsni = register_cvar("zp_sni_allow_respawn", "0")
1968 cvar_allowrespawnswarm = register_cvar("zp_swarm_allow_respawn", "0")
1969 cvar_allowrespawnplague = register_cvar("zp_plague_allow_respawn", "0")
1970 cvar_allowrespawnarmage = register_cvar("zp_armageddon_allow_respawn", "0")
1971 cvar_allowrespawnapoc = register_cvar("zp_apocalypse_allow_respawn", "0")
1972 cvar_allowrespawnnight = register_cvar("zp_nightmare_allow_respawn", "0")
1973 cvar_respawnzomb = register_cvar("zp_respawn_zombies", "1")
1974 cvar_respawnhum = register_cvar("zp_respawn_humans", "1")
1975 cvar_respawnnem = register_cvar("zp_respawn_nemesis", "1")
1976 cvar_respawnassa = register_cvar("zp_respawn_assassins", "0")
1977 cvar_respawnsurv = register_cvar("zp_respawn_survivors", "1")
1978 cvar_respawnsni = register_cvar("zp_respawn_snipers", "0")
1979
1980 // CVARS - Extra Items
1981 cvar_extraitems = register_cvar("zp_extra_items", "1")
1982 cvar_extraweapons = register_cvar("zp_extra_weapons", "1")
1983 cvar_extranvision = register_cvar("zp_extra_nvision", "1")
1984 cvar_extraantidote = register_cvar("zp_extra_antidote", "1")
1985 cvar_antidotelimit = register_cvar("zp_extra_antidote_limit", "999")
1986 cvar_extramadness = register_cvar("zp_extra_madness", "1")
1987 cvar_madnesslimit = register_cvar("zp_extra_madness_limit", "999")
1988 cvar_madnessduration = register_cvar("zp_extra_madness_duration", "5.0")
1989 cvar_extrainfbomb = register_cvar("zp_extra_infbomb", "1")
1990 cvar_infbomblimit = register_cvar("zp_extra_infbomb_limit", "999")
1991
1992 // CVARS - Flashlight and Nightvision
1993 cvar_nvggive = register_cvar("zp_nvg_give", "1")
1994 cvar_customnvg = register_cvar("zp_nvg_custom", "1")
1995 cvar_nvgsize = register_cvar("zp_nvg_size", "80")
1996 cvar_nvgcolor[0] = register_cvar("zp_nvg_color_R", "0")
1997 cvar_nvgcolor[1] = register_cvar("zp_nvg_color_G", "150")
1998 cvar_nvgcolor[2] = register_cvar("zp_nvg_color_B", "0")
1999 cvar_humnvgcolor[0] = register_cvar("zp_nvg_hum_color_R", "0")
2000 cvar_humnvgcolor[1] = register_cvar("zp_nvg_hum_color_G", "150")
2001 cvar_humnvgcolor[2] = register_cvar("zp_nvg_hum_color_B", "0")
2002 cvar_nemnvgcolor[0] = register_cvar("zp_nvg_nem_color_R", "150")
2003 cvar_nemnvgcolor[1] = register_cvar("zp_nvg_nem_color_G", "0")
2004 cvar_nemnvgcolor[2] = register_cvar("zp_nvg_nem_color_B", "0")
2005 cvar_assanvgcolor[0] = register_cvar("zp_nvg_assa_color_R", "0")
2006 cvar_assanvgcolor[1] = register_cvar("zp_nvg_assa_color_G", "150")
2007 cvar_assanvgcolor[2] = register_cvar("zp_nvg_assa_color_B", "90")
2008 cvar_customflash = register_cvar("zp_flash_custom", "0")
2009 cvar_flashsize = register_cvar("zp_flash_size", "10")
2010 cvar_flashdrain = register_cvar("zp_flash_drain", "1")
2011 cvar_flashcharge = register_cvar("zp_flash_charge", "5")
2012 cvar_flashdist = register_cvar("zp_flash_distance", "1000")
2013 cvar_flashcolor[0] = register_cvar("zp_flash_color_R", "100")
2014 cvar_flashcolor[1] = register_cvar("zp_flash_color_G", "100")
2015 cvar_flashcolor[2] = register_cvar("zp_flash_color_B", "100")
2016 cvar_flashshowall = register_cvar("zp_flash_show_all", "1")
2017
2018 // CVARS - Knockback
2019 cvar_knockback = register_cvar("zp_knockback", "0")
2020 cvar_knockbackdamage = register_cvar("zp_knockback_damage", "1")
2021 cvar_knockbackpower = register_cvar("zp_knockback_power", "1")
2022 cvar_knockbackzvel = register_cvar("zp_knockback_zvel", "0")
2023 cvar_knockbackducking = register_cvar("zp_knockback_ducking", "0.25")
2024 cvar_knockbackdist = register_cvar("zp_knockback_distance", "500")
2025 cvar_nemknockback = register_cvar("zp_knockback_nemesis", "0.25")
2026 cvar_assaknockback = register_cvar("zp_knockback_assassin", "0.7")
2027
2028 // CVARS - Leap
2029 cvar_leapzombies = register_cvar("zp_leap_zombies", "0")
2030 cvar_leapzombiesforce = register_cvar("zp_leap_zombies_force", "500")
2031 cvar_leapzombiesheight = register_cvar("zp_leap_zombies_height", "300")
2032 cvar_leapzombiescooldown = register_cvar("zp_leap_zombies_cooldown", "5.0")
2033 cvar_leapnemesis = register_cvar("zp_leap_nemesis", "1")
2034 cvar_leapnemesisforce = register_cvar("zp_leap_nemesis_force", "500")
2035 cvar_leapnemesisheight = register_cvar("zp_leap_nemesis_height", "300")
2036 cvar_leapnemesiscooldown = register_cvar("zp_leap_nemesis_cooldown", "5.0")
2037 cvar_leapassassin = register_cvar("zp_leap_assassin", "0")
2038 cvar_leapassassinforce = register_cvar("zp_leap_assassin_force", "500")
2039 cvar_leapassassinheight = register_cvar("zp_leap_assassin_height", "300")
2040 cvar_leapassassincooldown = register_cvar("zp_leap_assassin_cooldown", "5.0")
2041 cvar_leapsurvivor = register_cvar("zp_leap_survivor", "0")
2042 cvar_leapsurvivorforce = register_cvar("zp_leap_survivor_force", "500")
2043 cvar_leapsurvivorheight = register_cvar("zp_leap_survivor_height", "300")
2044 cvar_leapsurvivorcooldown = register_cvar("zp_leap_survivor_cooldown", "5.0")
2045 cvar_leapsniper = register_cvar("zp_leap_sniper", "0")
2046 cvar_leapsniperforce = register_cvar("zp_leap_sniper_force", "500")
2047 cvar_leapsniperheight = register_cvar("zp_leap_sniper_height", "300")
2048 cvar_leapsnipercooldown = register_cvar("zp_leap_sniper_cooldown", "5.0")
2049
2050 // CVARS - Humans
2051 cvar_humanhp = register_cvar("zp_human_health", "100")
2052 cvar_humanlasthp = register_cvar("zp_human_last_extrahp", "0")
2053 cvar_humanspd = register_cvar("zp_human_speed", "240")
2054 cvar_humangravity = register_cvar("zp_human_gravity", "1.0")
2055 cvar_humanarmor = register_cvar("zp_human_armor_protect", "1")
2056 cvar_infammo = register_cvar("zp_human_unlimited_ammo", "0")
2057 cvar_ammodamage_human = register_cvar("zp_human_damage_reward", "500")
2058 cvar_fragskill = register_cvar("zp_human_frags_for_kill", "1")
2059
2060 // CVARS - Custom Grenades
2061 cvar_firegrenades = register_cvar("zp_fire_grenades", "1")
2062 cvar_fireduration = register_cvar("zp_fire_duration", "10")
2063 cvar_firedamage = register_cvar("zp_fire_damage", "5")
2064 cvar_fireslowdown = register_cvar("zp_fire_slowdown", "0.5")
2065 cvar_frostgrenades = register_cvar("zp_frost_grenades", "1")
2066 cvar_freezeduration = register_cvar("zp_frost_duration", "3")
2067 cvar_flaregrenades = register_cvar("zp_flare_grenades","1")
2068 cvar_flareduration = register_cvar("zp_flare_duration", "60")
2069 cvar_flaresize = register_cvar("zp_flare_size", "25")
2070 cvar_flarecolor = register_cvar("zp_flare_color", "0")
2071
2072 // CVARS - Zombies
2073 cvar_zombiefirsthp = register_cvar("zp_zombie_first_hp", "2.0")
2074 cvar_zombiearmor = register_cvar("zp_zombie_armor", "0.75")
2075 cvar_hitzones = register_cvar("zp_zombie_hitzones", "0")
2076 cvar_zombiebonushp = register_cvar("zp_zombie_infect_health", "100")
2077 cvar_zombiefov = register_cvar("zp_zombie_fov", "110")
2078 cvar_zombiesilent = register_cvar("zp_zombie_silent", "1")
2079 cvar_zombiepainfree = register_cvar("zp_zombie_painfree", "2")
2080 cvar_zombiebleeding = register_cvar("zp_zombie_bleeding", "1")
2081 cvar_ammoinfect = register_cvar("zp_zombie_infect_reward", "1")
2082 cvar_ammodamage_zombie = register_cvar("zp_zombie_damage_reward", "0")
2083 cvar_fragsinfect = register_cvar("zp_zombie_frags_for_infect", "1")
2084
2085 // CVARS - Special Effects
2086 cvar_infectionscreenfade = register_cvar("zp_infection_screenfade", "1")
2087 cvar_infectionscreenshake = register_cvar("zp_infection_screenshake", "1")
2088 cvar_infectionsparkle = register_cvar("zp_infection_sparkle", "1")
2089 cvar_infectiontracers = register_cvar("zp_infection_tracers", "1")
2090 cvar_infectionparticles = register_cvar("zp_infection_particles", "1")
2091 cvar_hudicons = register_cvar("zp_hud_icons", "1")
2092
2093 // CVARS - Nemesis
2094 cvar_nem = register_cvar("zp_nem_enabled", "1")
2095 cvar_nemchance = register_cvar("zp_nem_chance", "20")
2096 cvar_nemminplayers = register_cvar("zp_nem_min_players", "0")
2097 cvar_nemhp = register_cvar("zp_nem_health", "0")
2098 cvar_nembasehp = register_cvar("zp_nem_base_health", "0")
2099 cvar_nemspd = register_cvar("zp_nem_speed", "250")
2100 cvar_nemgravity = register_cvar("zp_nem_gravity", "0.5")
2101 cvar_nemdamage = register_cvar("zp_nem_damage", "250")
2102 cvar_nemglow = register_cvar("zp_nem_glow", "1")
2103 cvar_nemaura = register_cvar("zp_nem_aura", "1")
2104 cvar_nempainfree = register_cvar("zp_nem_painfree", "0")
2105 cvar_nemignorefrags = register_cvar("zp_nem_ignore_frags", "1")
2106 cvar_nemignoreammo = register_cvar("zp_nem_ignore_rewards", "1")
2107
2108 // CVARS - Assassin
2109 cvar_assa = register_cvar("zp_assa_enabled", "1")
2110 cvar_assachance = register_cvar("zp_assa_chance", "50")
2111 cvar_assaminplayers = register_cvar("zp_assa_min_players", "0")
2112 cvar_assahp = register_cvar("zp_assa_health", "25000")
2113 cvar_assabasehp = register_cvar("zp_assa_base_health", "0")
2114 cvar_assaspd = register_cvar("zp_assa_speed", "650")
2115 cvar_assagravity = register_cvar("zp_assa_gravity", "0.5")
2116 cvar_assadamage = register_cvar("zp_assa_damage", "250")
2117 cvar_assaglow = register_cvar("zp_assa_glow", "0")
2118 cvar_assaaura = register_cvar("zp_assa_aura", "0")
2119 cvar_assapainfree = register_cvar("zp_assa_painfree", "0")
2120 cvar_assaignorefrags = register_cvar("zp_assassin_ignore_frags", "1")
2121 cvar_assaignoreammo = register_cvar("zp_assassin_ignore_rewards", "1")
2122
2123 // CVARS - Survivor
2124 cvar_surv = register_cvar("zp_surv_enabled", "1")
2125 cvar_survchance = register_cvar("zp_surv_chance", "20")
2126 cvar_survminplayers = register_cvar("zp_surv_min_players", "0")
2127 cvar_survhp = register_cvar("zp_surv_health", "0")
2128 cvar_survbasehp = register_cvar("zp_surv_base_health", "0")
2129 cvar_survspd = register_cvar("zp_surv_speed", "230")
2130 cvar_survgravity = register_cvar("zp_surv_gravity", "1.25")
2131 cvar_survglow = register_cvar("zp_surv_glow", "1")
2132 cvar_survaura = register_cvar("zp_surv_aura", "1")
2133 cvar_survpainfree = register_cvar("zp_surv_painfree", "1")
2134 cvar_survignorefrags = register_cvar("zp_surv_ignore_frags", "1")
2135 cvar_survignoreammo = register_cvar("zp_surv_ignore_rewards", "1")
2136 cvar_survinfammo = register_cvar("zp_surv_unlimited_ammo", "2")
2137
2138 // CVARS - Sniper
2139 cvar_sni = register_cvar("zp_sni_enabled", "1")
2140 cvar_snichance = register_cvar("zp_sni_chance", "250")
2141 cvar_sniminplayers = register_cvar("zp_sni_min_players", "0")
2142 cvar_snihp = register_cvar("zp_sni_health", "3000")
2143 cvar_snibasehp = register_cvar("zp_sni_base_health", "0")
2144 cvar_snispd = register_cvar("zp_sni_speed", "230")
2145 cvar_snigravity = register_cvar("zp_sni_gravity", "1.25")
2146 cvar_sniglow = register_cvar("zp_sni_glow", "1")
2147 cvar_sniaura = register_cvar("zp_sni_aura", "0")
2148 cvar_snipainfree = register_cvar("zp_sni_painfree", "0")
2149 cvar_snipignorefrags = register_cvar("zp_sniper_ignore_frags", "1")
2150 cvar_snipignoreammo = register_cvar("zp_sniper_ignore_rewards", "1")
2151 cvar_snidamage = register_cvar("zp_sni_damage", "4500")
2152 cvar_sniinfammo = register_cvar("zp_sni_unlimited_ammo", "1")
2153
2154 // CVARS - Swarm Mode
2155 cvar_swarm = register_cvar("zp_swarm_enabled", "1")
2156 cvar_swarmchance = register_cvar("zp_swarm_chance", "20")
2157 cvar_swarmminplayers = register_cvar("zp_swarm_min_players", "0")
2158
2159 // CVARS - Multi Infection
2160 cvar_multi = register_cvar("zp_multi_enabled", "1")
2161 cvar_multichance = register_cvar("zp_multi_chance", "20")
2162 cvar_multiminplayers = register_cvar("zp_multi_min_players", "0")
2163 cvar_multiratio = register_cvar("zp_multi_ratio", "0.15")
2164
2165 // CVARS - Plague Mode
2166 cvar_plague = register_cvar("zp_plague_enabled", "1")
2167 cvar_plaguechance = register_cvar("zp_plague_chance", "30")
2168 cvar_plagueminplayers = register_cvar("zp_plague_min_players", "0")
2169 cvar_plagueratio = register_cvar("zp_plague_ratio", "0.5")
2170 cvar_plaguenemnum = register_cvar("zp_plague_nem_number", "1")
2171 cvar_plaguenemhpmulti = register_cvar("zp_plague_nem_hp_multi", "0.5")
2172 cvar_plaguesurvnum = register_cvar("zp_plague_surv_number", "1")
2173 cvar_plaguesurvhpmulti = register_cvar("zp_plague_surv_hp_multi", "0.5")
2174
2175 // CVARS - Armageddon Mode
2176 cvar_armage = register_cvar("zp_armageddon_enabled", "1")
2177 cvar_armagechance = register_cvar("zp_armageddon_chance", "25")
2178 cvar_armageminplayers = register_cvar("zp_armageddon_min_players", "0")
2179 cvar_armageratio = register_cvar("zp_armageddon_ratio", "0.5")
2180 cvar_armagenemhpmulti = register_cvar("zp_armageddon_nemesis_hp_multi", "0.5")
2181 cvar_armagesurvhpmulti = register_cvar("zp_armageddon_survivor_hp_multi", "0.5")
2182
2183 // CVARS - Apocalypse Mode
2184 cvar_apoc = register_cvar("zp_apocalypse_enabled", "1")
2185 cvar_apocchance = register_cvar("zp_apocalypse_chance", "25")
2186 cvar_apocminplayers = register_cvar("zp_apocalypse_min_players", "0")
2187 cvar_apocratio = register_cvar("zp_apocalypse_ratio", "0.5")
2188 cvar_apocassahpmulti = register_cvar("zp_apocalypse_assassin_hp_multi", "0.5")
2189 cvar_apocsniphpmulti = register_cvar("zp_apocalypse_sniper_hp_multi", "0.5")
2190
2191 // CVARS - Nightmare Mode
2192 cvar_night = register_cvar("zp_nightmare_enabled", "1")
2193 cvar_nightchance = register_cvar("zp_nightmare_chance", "25")
2194 cvar_nightminplayers = register_cvar("zp_nightmare_min_players", "0")
2195 cvar_nightratio = register_cvar("zp_nightmare_ratio", "0.5")
2196 cvar_nightassahpmulti = register_cvar("zp_nightmare_assassin_hp_multi", "0.5")
2197 cvar_nightsniphpmulti = register_cvar("zp_nightmare_sniper_hp_multi", "0.5")
2198 cvar_nightnemhpmulti = register_cvar("zp_nightmare_nemesis_hp_multi", "0.5")
2199 cvar_nightsurvhpmulti = register_cvar("zp_nightmare_survivor_hp_multi", "0.5")
2200
2201 // CVARS - Others
2202 cvar_logcommands = register_cvar("zp_logcommands", "1")
2203 cvar_showactivity = get_cvar_pointer("amx_show_activity")
2204 cvar_botquota = get_cvar_pointer("bot_quota")
2205 register_cvar("zp_version", PLUGIN_VERSION, FCVAR_SERVER|FCVAR_SPONLY)
2206 set_cvar_string("zp_version", PLUGIN_VERSION)
2207
2208 // Custom Forwards
2209 g_fwRoundStart = CreateMultiForward("zp_round_started", ET_IGNORE, FP_CELL, FP_CELL)
2210 g_fwRoundEnd = CreateMultiForward("zp_round_ended", ET_IGNORE, FP_CELL)
2211 g_fwUserInfected_pre = CreateMultiForward("zp_user_infected_pre", ET_IGNORE, FP_CELL, FP_CELL, FP_CELL)
2212 g_fwUserInfected_post = CreateMultiForward("zp_user_infected_post", ET_IGNORE, FP_CELL, FP_CELL, FP_CELL)
2213 g_fwUserHumanized_pre = CreateMultiForward("zp_user_humanized_pre", ET_IGNORE, FP_CELL, FP_CELL)
2214 g_fwUserHumanized_post = CreateMultiForward("zp_user_humanized_post", ET_IGNORE, FP_CELL, FP_CELL)
2215 g_fwUserInfect_attempt = CreateMultiForward("zp_user_infect_attempt", ET_CONTINUE, FP_CELL, FP_CELL, FP_CELL)
2216 g_fwUserHumanize_attempt = CreateMultiForward("zp_user_humanize_attempt", ET_CONTINUE, FP_CELL, FP_CELL)
2217 g_fwExtraItemSelected = CreateMultiForward("zp_extra_item_selected", ET_CONTINUE, FP_CELL, FP_CELL)
2218 g_fwUserUnfrozen = CreateMultiForward("zp_user_unfrozen", ET_IGNORE, FP_CELL)
2219 g_fwUserLastZombie = CreateMultiForward("zp_user_last_zombie", ET_IGNORE, FP_CELL)
2220 g_fwUserLastHuman = CreateMultiForward("zp_user_last_human", ET_IGNORE, FP_CELL)
2221
2222 // Collect random spawn points
2223 load_spawns()
2224
2225 // Set a random skybox?
2226 if (g_sky_enable)
2227 {
2228 new sky[32]
2229 ArrayGetString(g_sky_names, random_num(0, ArraySize(g_sky_names) - 1), sky, charsmax(sky))
2230 set_cvar_string("sv_skyname", sky)
2231 }
2232
2233 // Disable sky lighting so it doesn't mess with our custom lighting
2234 set_cvar_num("sv_skycolor_r", 0)
2235 set_cvar_num("sv_skycolor_g", 0)
2236 set_cvar_num("sv_skycolor_b", 0)
2237
2238 // Create the HUD Sync Objects
2239 g_MsgSync = CreateHudSyncObj()
2240 g_MsgSync2 = CreateHudSyncObj()
2241 g_MsgSync3 = CreateHudSyncObj()
2242
2243 // Format mod name
2244 formatex(g_modname, charsmax(g_modname), "Zombie Plague %s", PLUGIN_VERSION)
2245
2246 // Get Max Players
2247 g_maxplayers = get_maxplayers()
2248
2249 // Reserved saving slots starts on maxplayers+1
2250 db_slot_i = g_maxplayers+1
2251
2252 // Check if it's a CZ server
2253 new mymod[6]
2254 get_modname(mymod, charsmax(mymod))
2255 if (equal(mymod, "czero")) g_czero = 1
2256}
2257
2258public plugin_cfg()
2259{
2260 // Plugin disabled?
2261 if (!g_pluginenabled) return;
2262
2263 // Get configs dir
2264 new cfgdir[32]
2265 get_configsdir(cfgdir, charsmax(cfgdir))
2266
2267 // Execute config file (zombieplague.cfg)
2268 server_cmd("exec %s/zombieplague.cfg", cfgdir)
2269
2270 // Prevent any more stuff from registering
2271 g_arrays_created = false
2272
2273 // Save customization data
2274 save_customization()
2275
2276 // Lighting task
2277 set_task(5.0, "lighting_effects", _, _, _, "b")
2278
2279 // Cache CVARs after configs are loaded / call roundstart manually
2280 set_task(0.5, "cache_cvars")
2281 set_task(0.5, "event_round_start")
2282 set_task(0.5, "logevent_round_start")
2283}
2284
2285// Some one aimed at someone
2286public event_show_status(id)
2287{
2288 // Not a bot and is still connected
2289 if (!g_isbot[id] && g_isconnected[id] && get_pcvar_num(cvar_aiminfo))
2290 {
2291 // Retrieve the aimed player's id
2292 static aimid
2293 aimid = read_data(2)
2294
2295 // Only show friends status ?
2296 if (g_zombie[id] == g_zombie[aimid])
2297 {
2298 static class[32], red, blue
2299
2300 // Format the class name according to the player's team
2301 if (g_zombie[id])
2302 {
2303 red = 255
2304 blue = 0
2305
2306 if (g_nemesis[aimid])
2307 formatex(class, charsmax(class), "%L %L", id, "CLASS_CLASS", id, "CLASS_NEMESIS")
2308 else if (g_assassin[aimid])
2309 formatex(class, charsmax(class), "%L %L", id, "CLASS_CLASS", id, "CLASS_ASSASSIN")
2310 else
2311 formatex(class, charsmax(class), "%L %s", id, "CLASS_CLASS", g_zombie_classname[aimid])
2312 }
2313 else
2314 {
2315 red = 0
2316 blue = 255
2317
2318 if (g_survivor[aimid])
2319 formatex(class, charsmax(class), "%L %L", id, "CLASS_CLASS", id, "CLASS_SURVIVOR")
2320 else if (g_sniper[aimid])
2321 formatex(class, charsmax(class), "%L %L", id, "CLASS_CLASS", id, "CLASS_SNIPER")
2322 else
2323 formatex(class, charsmax(class), "%L %L", id, "CLASS_CLASS", id, "CLASS_HUMAN")
2324 }
2325
2326 // Show the notice
2327 set_hudmessage(red, 50, blue, -1.0, 0.70, 1, 0.01, 3.0, 0.01, 0.01, -1)
2328 ShowSyncHudMsg(id, g_MsgSync3,"%L", id, "AIM_INFO", g_playername[aimid], class, pev(aimid, pev_health), pev(aimid, pev_armorvalue), g_ammopacks[aimid])
2329 }
2330 }
2331}
2332
2333// Remove the aim-info message
2334public event_hide_status(id)
2335{
2336 ClearSyncHud(id, g_MsgSync3)
2337}
2338
2339/*================================================================================
2340 [Main Events]
2341=================================================================================*/
2342
2343// Event Round Start
2344public event_round_start()
2345{
2346 // Remove doors/lights?
2347 set_task(0.1, "remove_stuff")
2348
2349 // New round starting
2350 g_newround = true
2351 g_endround = false
2352 g_survround = false
2353 g_sniround = false
2354 g_nemround = false
2355 g_assaround = false
2356 g_swarmround = false
2357 g_plagueround = false
2358 g_armageround = false
2359 g_apocround = false
2360 g_nightround = false
2361 g_modestarted = false
2362
2363 // Reset bought infection bombs counter
2364 g_infbombcounter = 0
2365 g_antidotecounter = 0
2366 g_madnesscounter = 0
2367
2368 // Freezetime begins
2369 g_freezetime = true
2370
2371 // Show welcome message and T-Virus notice
2372 remove_task(TASK_WELCOMEMSG)
2373 set_task(2.0, "welcome_msg", TASK_WELCOMEMSG)
2374
2375 // Set a new "Make Zombie Task"
2376 remove_task(TASK_MAKEZOMBIE)
2377 set_task(2.0 + get_pcvar_float(cvar_warmup), "make_zombie_task", TASK_MAKEZOMBIE)
2378}
2379
2380// Log Event Round Start
2381public logevent_round_start()
2382{
2383 // Freezetime ends
2384 g_freezetime = false
2385
2386 #define ForPlayers(%1) for(new %1 = 1; %1 <= 32; %1++)
2387
2388 ForPlayers(i)
2389 {
2390 if(!is_user_connected(i) || !get_user_gasmask(i))
2391 {
2392 continue;
2393 }
2394
2395 set_user_gasmask(i, false);
2396 }
2397}
2398
2399// Log Event Round End
2400public logevent_round_end()
2401{
2402 // Prevent this from getting called twice when restarting (bugfix)
2403 static Float:lastendtime, Float:current_time
2404 current_time = get_gametime()
2405 if (current_time - lastendtime < 0.5) return;
2406 lastendtime = current_time
2407
2408 // Temporarily save player stats?
2409 if (get_pcvar_num(cvar_statssave))
2410 {
2411 static id, team
2412 for (id = 1; id <= g_maxplayers; id++)
2413 {
2414 // Not connected
2415 if (!g_isconnected[id])
2416 continue;
2417
2418 team = fm_cs_get_user_team(id)
2419
2420 // Not playing
2421 if (team == FM_CS_TEAM_SPECTATOR || team == FM_CS_TEAM_UNASSIGNED)
2422 continue;
2423
2424 save_stats(id)
2425 }
2426 }
2427
2428 // Round ended
2429 g_endround = true
2430
2431 // Stop old tasks (if any)
2432 remove_task(TASK_WELCOMEMSG)
2433 remove_task(TASK_MAKEZOMBIE)
2434
2435 // Stop ambience sounds
2436 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)
2437 || (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))
2438 {
2439 remove_task(TASK_AMBIENCESOUNDS)
2440 ambience_sound_stop()
2441 }
2442
2443 // Show HUD notice, play win sound, update team scores...
2444 static sound[64]
2445 if (!fnGetZombies())
2446 {
2447 // Human team wins
2448 set_dhudmessage(0, 0, 200, HUD_EVENT_X, HUD_EVENT_Y, 0, 0.0, 3.0, 2.0, 1.0)
2449 show_dhudmessage(0, "%L", LANG_PLAYER, "WIN_HUMAN")
2450
2451 // Play win sound and increase score, unless game commencing
2452 ArrayGetString(sound_win_humans, random_num(0, ArraySize(sound_win_humans) - 1), sound, charsmax(sound))
2453 PlaySound(sound)
2454 if (!g_gamecommencing) g_scorehumans++
2455
2456 // Round end forward
2457 ExecuteForward(g_fwRoundEnd, g_fwDummyResult, ZP_TEAM_HUMAN);
2458 }
2459 else if (!fnGetHumans())
2460 {
2461 // Zombie team wins
2462 set_dhudmessage(200, 0, 0, HUD_EVENT_X, HUD_EVENT_Y, 0, 0.0, 3.0, 2.0, 1.0)
2463 show_dhudmessage(0, "%L", LANG_PLAYER, "WIN_ZOMBIE")
2464
2465 // Play win sound and increase score, unless game commencing
2466 ArrayGetString(sound_win_zombies, random_num(0, ArraySize(sound_win_zombies) - 1), sound, charsmax(sound))
2467 PlaySound(sound)
2468 if (!g_gamecommencing) g_scorezombies++
2469
2470 // Round end forward
2471 ExecuteForward(g_fwRoundEnd, g_fwDummyResult, ZP_TEAM_ZOMBIE);
2472 }
2473 else
2474 {
2475 // No one wins
2476 set_hudmessage(0, 200, 0, HUD_EVENT_X, HUD_EVENT_Y, 0, 0.0, 3.0, 2.0, 1.0, -1)
2477 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "WIN_NO_ONE")
2478
2479 // Play win sound
2480 ArrayGetString(sound_win_no_one, random_num(0, ArraySize(sound_win_no_one) - 1), sound, charsmax(sound))
2481 PlaySound(sound)
2482
2483 // Round end forward
2484 ExecuteForward(g_fwRoundEnd, g_fwDummyResult, ZP_TEAM_NO_ONE);
2485 }
2486
2487 // Game commencing triggers round end
2488 g_gamecommencing = false
2489
2490 // Balance the teams
2491 balance_teams()
2492}
2493
2494// Event Map Ended
2495public event_intermission()
2496{
2497 // Remove ambience sounds task
2498 remove_task(TASK_AMBIENCESOUNDS)
2499}
2500
2501// BP Ammo update
2502public event_ammo_x(id)
2503{
2504 // Humans only
2505 if (g_zombie[id])
2506 return;
2507
2508 // Get ammo type
2509 static type
2510 type = read_data(1)
2511
2512 // Unknown ammo type
2513 if (type >= sizeof AMMOWEAPON)
2514 return;
2515
2516 // Get weapon's id
2517 static weapon
2518 weapon = AMMOWEAPON[type]
2519
2520 // Primary and secondary only
2521 if (MAXBPAMMO[weapon] <= 2)
2522 return;
2523
2524 // Get ammo amount
2525 static amount
2526 amount = read_data(2)
2527
2528 // Unlimited BP Ammo?
2529 if (g_survivor[id] ? get_pcvar_num(cvar_survinfammo) : g_sniper[id] ? get_pcvar_num(cvar_sniinfammo) : get_pcvar_num(cvar_infammo))
2530 {
2531 if (amount < MAXBPAMMO[weapon])
2532 {
2533 // The BP Ammo refill code causes the engine to send a message, but we
2534 // can't have that in this forward or we risk getting some recursion bugs.
2535 // For more info see: https://bugs.alliedmods.net/show_bug.cgi?id=3664
2536 static args[1]
2537 args[0] = weapon
2538 set_task(0.1, "refill_bpammo", id, args, sizeof args)
2539 }
2540 }
2541 // Bots automatically buy ammo when needed
2542 else if (g_isbot[id] && amount <= BUYAMMO[weapon])
2543 {
2544 // Task needed for the same reason as above
2545 set_task(0.1, "clcmd_buyammo", id)
2546 }
2547}
2548
2549/*================================================================================
2550 [Main Forwards]
2551=================================================================================*/
2552
2553// Entity Spawn Forward
2554public fw_Spawn(entity)
2555{
2556 // Invalid entity
2557 if (!pev_valid(entity)) return FMRES_IGNORED;
2558
2559 // Get classname
2560 new classname[32], objective[32], size = ArraySize(g_objective_ents)
2561 pev(entity, pev_classname, classname, charsmax(classname))
2562
2563 // Check whether it needs to be removed
2564 for (new i = 0; i < size; i++)
2565 {
2566 ArrayGetString(g_objective_ents, i, objective, charsmax(objective))
2567
2568 if (equal(classname, objective))
2569 {
2570 engfunc(EngFunc_RemoveEntity, entity)
2571 return FMRES_SUPERCEDE;
2572 }
2573 }
2574
2575 return FMRES_IGNORED;
2576}
2577
2578// Sound Precache Forward
2579public fw_PrecacheSound(const sound[])
2580{
2581 // Block all those unneeeded hostage sounds
2582 if (equal(sound, "hostage", 7))
2583 return FMRES_SUPERCEDE;
2584
2585 return FMRES_IGNORED;
2586}
2587
2588// Ham Player Spawn Post Forward
2589public fw_PlayerSpawn_Post(id)
2590{
2591 // Not alive or didn't join a team yet
2592 if (!is_user_alive(id) || !fm_cs_get_user_team(id))
2593 return;
2594
2595 // Player spawned
2596 g_isalive[id] = true
2597
2598 // Remove previous tasks
2599 remove_task(id+TASK_SPAWN)
2600 remove_task(id+TASK_MODEL)
2601 remove_task(id+TASK_BLOOD)
2602 remove_task(id+TASK_AURA)
2603 remove_task(id+TASK_BURN)
2604 remove_task(id+TASK_CHARGE)
2605 remove_task(id+TASK_FLASH)
2606 remove_task(id+TASK_NVISION)
2607
2608 // Spawn at a random location?
2609 if (get_pcvar_num(cvar_randspawn)) do_random_spawn(id)
2610
2611 // Hide money?
2612 if (get_pcvar_num(cvar_removemoney))
2613 set_task(0.4, "task_hide_money", id+TASK_SPAWN)
2614
2615 // Respawn player if he dies because of a worldspawn kill?
2616 if (get_pcvar_num(cvar_respawnworldspawnkill))
2617 set_task(2.0, "respawn_player_check_task", id+TASK_SPAWN)
2618
2619 // Spawn as zombie?
2620 if (g_respawn_as_zombie[id] && !g_newround)
2621 {
2622 reset_vars(id, 0) // reset player vars
2623 zombieme(id, 0, 0, 0, 0, 0) // make him zombie right away
2624 return;
2625 }
2626
2627 // Reset player vars
2628 reset_vars(id, 0)
2629 g_buytime[id] = get_gametime()
2630
2631 // Show custom buy menu?
2632 if (get_pcvar_num(cvar_buycustom))
2633 set_task(0.2, "show_menu_buy1", id+TASK_SPAWN)
2634
2635 // Set health and gravity
2636 fm_set_user_health(id, get_pcvar_num(cvar_humanhp))
2637 set_pev(id, pev_gravity, get_pcvar_float(cvar_humangravity))
2638
2639 // Set human maxspeed
2640 ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
2641
2642 // Switch to CT if spawning mid-round
2643 if (!g_newround && fm_cs_get_user_team(id) != FM_CS_TEAM_CT) // need to change team?
2644 {
2645 remove_task(id+TASK_TEAM)
2646 fm_cs_set_user_team(id, FM_CS_TEAM_CT)
2647 fm_user_team_update(id)
2648 }
2649
2650 // Custom models stuff
2651 static currentmodel[32], tempmodel[32], already_has_model, i, iRand, size
2652 already_has_model = false
2653
2654 if (g_handle_models_on_separate_ent)
2655 {
2656 // Set the right model
2657 if (get_pcvar_num(cvar_adminmodelshuman) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
2658 {
2659 iRand = random_num(0, ArraySize(model_admin_human) - 1)
2660 ArrayGetString(model_admin_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
2661 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_human, iRand))
2662 }
2663 else
2664 {
2665 iRand = random_num(0, ArraySize(model_human) - 1)
2666 ArrayGetString(model_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
2667 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_human, iRand))
2668 }
2669
2670 // Set model on player model entity
2671 fm_set_playermodel_ent(id)
2672
2673 // Remove glow on player model entity
2674 fm_set_rendering(g_ent_playermodel[id])
2675 }
2676 else
2677 {
2678 // Get current model for comparing it with the current one
2679 fm_cs_get_user_model(id, currentmodel, charsmax(currentmodel))
2680
2681 // Set the right model, after checking that we don't already have it
2682 if (get_pcvar_num(cvar_adminmodelshuman) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
2683 {
2684 size = ArraySize(model_admin_human)
2685 for (i = 0; i < size; i++)
2686 {
2687 ArrayGetString(model_admin_human, i, tempmodel, charsmax(tempmodel))
2688 if (equal(currentmodel, tempmodel)) already_has_model = true
2689 }
2690
2691 if (!already_has_model)
2692 {
2693 iRand = random_num(0, size - 1)
2694 ArrayGetString(model_admin_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
2695 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_human, iRand))
2696 }
2697 }
2698 else
2699 {
2700 size = ArraySize(model_human)
2701 for (i = 0; i < size; i++)
2702 {
2703 ArrayGetString(model_human, i, tempmodel, charsmax(tempmodel))
2704 if (equal(currentmodel, tempmodel)) already_has_model = true
2705 }
2706
2707 if (!already_has_model)
2708 {
2709 iRand = random_num(0, size - 1)
2710 ArrayGetString(model_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
2711 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_human, iRand))
2712 }
2713 }
2714
2715 // Need to change the model?
2716 if (!already_has_model)
2717 {
2718 // An additional delay is offset at round start
2719 // since SVC_BAD is more likely to be triggered there
2720 if (g_newround)
2721 set_task(5.0 * g_modelchange_delay, "fm_user_model_update", id+TASK_MODEL)
2722 else
2723 fm_user_model_update(id+TASK_MODEL)
2724 }
2725
2726 // Remove glow
2727 fm_set_rendering(id)
2728 }
2729
2730 // Bots stuff
2731 if (g_isbot[id])
2732 {
2733 // Turn off NVG for bots
2734 cs_set_user_nvg(id, 0)
2735
2736 // Automatically buy extra items/weapons after first zombie is chosen
2737 if (get_pcvar_num(cvar_extraitems))
2738 {
2739 if (g_newround) set_task(10.0 + get_pcvar_float(cvar_warmup), "bot_buy_extras", id+TASK_SPAWN)
2740 else set_task(10.0, "bot_buy_extras", id+TASK_SPAWN)
2741 }
2742 }
2743
2744 // Enable spawn protection for humans spawning mid-round
2745 if (!g_newround && get_pcvar_float(cvar_spawnprotection) > 0.0)
2746 {
2747 // Do not take damage
2748 g_nodamage[id] = true
2749
2750 // Make temporarily invisible
2751 set_pev(id, pev_effects, pev(id, pev_effects) | EF_NODRAW)
2752
2753 // Set task to remove it
2754 set_task(get_pcvar_float(cvar_spawnprotection), "remove_spawn_protection", id+TASK_SPAWN)
2755 }
2756
2757 // Turn off his flashlight (prevents double flashlight bug/exploit)
2758 turn_off_flashlight(id)
2759
2760 // Set the flashlight charge task to update battery status
2761 if (g_cached_customflash)
2762 set_task(1.0, "flashlight_charge", id+TASK_CHARGE, _, _, "b")
2763
2764 // Replace weapon models (bugfix)
2765 static weapon_ent
2766 weapon_ent = fm_cs_get_current_weapon_ent(id)
2767 if (pev_valid(weapon_ent)) replace_weapon_models(id, cs_get_weapon_id(weapon_ent))
2768
2769 // Last Zombie Check
2770 fnCheckLastZombie()
2771}
2772
2773// Ham Player Killed Forward
2774public fw_PlayerKilled(victim, attacker, shouldgib)
2775{
2776 // Player killed
2777 g_isalive[victim] = false
2778 // Disable nodamage mode after we die to prevent spectator nightvision using zombie madness colors bug
2779 g_nodamage[victim] = false
2780
2781 // Enable dead players nightvision
2782 set_task(0.1, "spec_nvision", victim)
2783
2784 // Disable nightvision when killed (bugfix)
2785 if (get_pcvar_num(cvar_nvggive) == 0 && g_nvision[victim])
2786 {
2787 if (get_pcvar_num(cvar_customnvg)) remove_task(victim+TASK_NVISION)
2788 else if (g_nvisionenabled[victim]) set_user_gnvision(victim, 0)
2789 g_nvision[victim] = false
2790 g_nvisionenabled[victim] = false
2791 }
2792
2793 // Turn off nightvision when killed (bugfix)
2794 if (get_pcvar_num(cvar_nvggive) == 2 && g_nvision[victim] && g_nvisionenabled[victim])
2795 {
2796 if (get_pcvar_num(cvar_customnvg)) remove_task(victim+TASK_NVISION)
2797 else set_user_gnvision(victim, 0)
2798 g_nvisionenabled[victim] = false
2799 }
2800
2801 // Turn off custom flashlight when killed
2802 if (g_cached_customflash)
2803 {
2804 // Turn it off
2805 g_flashlight[victim] = false
2806 g_flashbattery[victim] = 100
2807
2808 // Remove previous tasks
2809 remove_task(victim+TASK_CHARGE)
2810 remove_task(victim+TASK_FLASH)
2811 }
2812
2813 // Stop bleeding/burning/aura when killed
2814 if (g_zombie[victim])
2815 {
2816 remove_task(victim+TASK_BLOOD)
2817 remove_task(victim+TASK_AURA)
2818 remove_task(victim+TASK_BURN)
2819 }
2820
2821 // Nemesis/Assassins explodes!
2822 if (g_nemesis[victim] || g_assassin[victim])
2823 SetHamParamInteger(3, 2)
2824
2825 // Get deathmatch mode status and whether the player killed himself
2826 static selfkill
2827 selfkill = (victim == attacker || !is_user_valid_connected(attacker)) ? true : false
2828
2829 // Make sure that the player was not killed by a non-player entity or through self killing
2830 if (!selfkill)
2831 {
2832 // When killed by a Sniper victim explodes
2833 if (g_sniper[attacker] && (g_currentweapon[attacker] == CSW_AWP))
2834 {
2835 // Cut him into pieces
2836 SetHamParamInteger(3, 2)
2837
2838 // Get his origin
2839 static origin[3]
2840 get_user_origin(victim, origin)
2841
2842 // Make some blood in the air
2843 message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
2844 write_byte(TE_LAVASPLASH) // TE id
2845 write_coord(origin[0]) // origin x
2846 write_coord(origin[1]) // origin y
2847 write_coord(origin[2] - 26) // origin z
2848 message_end()
2849 }
2850 else if (g_assassin[attacker])
2851 SetHamParamInteger(3, 2)
2852 }
2853
2854 // Killed by a non-player entity or self killed
2855 if (selfkill) return;
2856
2857 // Ignore Nemesis/Survivor Frags?
2858 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)))
2859 RemoveFrags(attacker, victim)
2860
2861 // Zombie/nemesis/assassin killed human, reward ammo packs
2862 if (g_zombie[attacker] && (!g_nemesis[attacker] || !get_pcvar_num(cvar_nemignoreammo)) && (!g_assassin[attacker] || !get_pcvar_num(cvar_assaignoreammo)))
2863 g_ammopacks[attacker] += get_pcvar_num(cvar_ammoinfect)
2864
2865 // Human killed zombie, add up the extra frags for kill
2866 if (!g_zombie[attacker] && get_pcvar_num(cvar_fragskill) > 1)
2867 UpdateFrags(attacker, victim, get_pcvar_num(cvar_fragskill) - 1, 0, 0)
2868
2869 // Zombie killed human, add up the extra frags for kill
2870 if (g_zombie[attacker] && get_pcvar_num(cvar_fragsinfect) > 1)
2871 UpdateFrags(attacker, victim, get_pcvar_num(cvar_fragsinfect) - 1, 0, 0)
2872}
2873
2874// Ham Player Killed Post Forward
2875public fw_PlayerKilled_Post(victim, attacker, shouldgib)
2876{
2877 // Last Zombie Check
2878 fnCheckLastZombie()
2879
2880 // Determine whether the player killed himself
2881 static selfkill
2882 selfkill = (victim == attacker || !is_user_valid_connected(attacker)) ? true : false
2883
2884 // Respawn if deathmatch is enabled
2885 if (get_pcvar_num(cvar_deathmatch))
2886 {
2887 // Respawn on suicide?
2888 if (selfkill && !get_pcvar_num(cvar_respawnonsuicide))
2889 return;
2890
2891 // Respawn if human/zombie/nemesis/survivor?
2892 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)))
2893 return;
2894
2895 // Set the respawn task
2896 set_task(get_pcvar_float(cvar_spawndelay), "respawn_player_task", victim+TASK_SPAWN)
2897 }
2898}
2899
2900// Ham Take Damage Forward
2901public fw_TakeDamage(victim, inflictor, attacker, Float:damage, damage_type)
2902{
2903 // Non-player damage or self damage
2904 if (victim == attacker || !is_user_valid_connected(attacker))
2905 return HAM_IGNORED;
2906
2907 // New round starting or round ended
2908 if (g_newround || g_endround)
2909 return HAM_SUPERCEDE;
2910
2911 // Victim shouldn't take damage or victim is frozen
2912 if (g_nodamage[victim] || g_frozen[victim])
2913 return HAM_SUPERCEDE;
2914
2915 // Prevent friendly fire
2916 if (g_zombie[attacker] == g_zombie[victim])
2917 return HAM_SUPERCEDE;
2918
2919 // Attacker is human...
2920 if (!g_zombie[attacker])
2921 {
2922 // Armor multiplier for the final damage on normal zombies
2923 if (!g_nemesis[victim] && !g_assassin[victim] && !g_sniper[attacker])
2924 {
2925 damage *= get_pcvar_float(cvar_zombiearmor)
2926 SetHamParamFloat(4, damage)
2927 }
2928
2929 // Reward ammo packs to humans for damaging zombies?
2930 if ((get_pcvar_num(cvar_ammodamage_human) > 0) && (!g_survivor[attacker] || !get_pcvar_num(cvar_survignoreammo)) && (!g_sniper[attacker] || !get_pcvar_num(cvar_snipignoreammo)))
2931 {
2932 // Store damage dealt
2933 g_damagedealt_human[attacker] += floatround(damage)
2934
2935 // Reward ammo packs for every [ammo damage] dealt
2936 while (g_damagedealt_human[attacker] > get_pcvar_num(cvar_ammodamage_human))
2937 {
2938 g_ammopacks[attacker]++
2939 g_damagedealt_human[attacker] -= get_pcvar_num(cvar_ammodamage_human)
2940 }
2941 }
2942
2943 // set sniper dmg
2944 if (g_sniper[attacker] && g_currentweapon[attacker] == CSW_AWP)
2945 SetHamParamFloat(4, get_pcvar_float(cvar_snidamage))
2946
2947 return HAM_IGNORED;
2948 }
2949
2950 // Attacker is zombie...
2951
2952 // Prevent infection/damage by HE grenade (bugfix)
2953 if (damage_type & DMG_HEGRENADE)
2954 return HAM_SUPERCEDE;
2955
2956 // Nemesis?
2957 if (g_nemesis[attacker])
2958 {
2959 // Ignore nemesis damage override if damage comes from a 3rd party entity
2960 // (to prevent this from affecting a sub-plugin's rockets e.g.)
2961 if (inflictor == attacker)
2962 {
2963 // Set nemesis damage
2964 SetHamParamFloat(4, get_pcvar_float(cvar_nemdamage))
2965 }
2966
2967 return HAM_IGNORED;
2968 }
2969 else if (g_assassin[attacker])
2970 {
2971 // Ignore assassin damage override if damage comes from a 3rd party entity
2972 // (to prevent this from affecting a sub-plugin's rockets e.g.)
2973 if (inflictor == attacker)
2974 {
2975 // Set assassin damage
2976 SetHamParamFloat(4, get_pcvar_float(cvar_assadamage))
2977 }
2978
2979 return HAM_IGNORED;
2980 }
2981
2982 // Reward ammo packs to zombies for damaging humans?
2983 if (get_pcvar_num(cvar_ammodamage_zombie) > 0)
2984 {
2985 // Store damage dealt
2986 g_damagedealt_zombie[attacker] += floatround(damage)
2987
2988 // Reward ammo packs for every [ammo damage] dealt
2989 while (g_damagedealt_zombie[attacker] > get_pcvar_num(cvar_ammodamage_zombie))
2990 {
2991 g_ammopacks[attacker]++
2992 g_damagedealt_zombie[attacker] -= get_pcvar_num(cvar_ammodamage_zombie)
2993 }
2994 }
2995
2996 // Last human or not an infection round
2997 if (g_survround || g_sniround || g_nemround || g_assaround || g_swarmround || g_plagueround || g_armageround || g_apocround || g_nightround || fnGetHumans() == 1)
2998 return HAM_IGNORED; // human is killed
2999
3000 // Does human armor need to be reduced before infecting?
3001 if (get_pcvar_num(cvar_humanarmor))
3002 {
3003 // Get victim armor
3004 static Float:armor
3005 pev(victim, pev_armorvalue, armor)
3006
3007 // If he has some, block the infection and reduce armor instead
3008 if (armor > 0.0)
3009 {
3010 emit_sound(victim, CHAN_BODY, sound_armorhit, 1.0, ATTN_NORM, 0, PITCH_NORM)
3011 if (armor - damage > 0.0)
3012 set_pev(victim, pev_armorvalue, armor - damage)
3013 else
3014 cs_set_user_armor(victim, 0, CS_ARMOR_NONE)
3015 return HAM_SUPERCEDE;
3016 }
3017 }
3018
3019 // Infection allowed
3020 zombieme(victim, attacker, 0, 0, 0, 1) // turn into zombie
3021 return HAM_SUPERCEDE;
3022}
3023
3024// Ham Take Damage Post Forward
3025public fw_TakeDamage_Post(victim)
3026{
3027 // --- Check if victim should be Pain Shock Free ---
3028
3029 // Check if proper CVARs are enabled
3030 if (g_zombie[victim])
3031 {
3032 if (g_nemesis[victim])
3033 {
3034 if (!get_pcvar_num(cvar_nempainfree)) return;
3035 }
3036 else if (g_assassin[victim])
3037 {
3038 if (!get_pcvar_num(cvar_assapainfree)) return;
3039 }
3040 else
3041 {
3042 switch (get_pcvar_num(cvar_zombiepainfree))
3043 {
3044 case 0: return;
3045 case 2: if (!g_lastzombie[victim]) return;
3046 case 3: if (!g_firstzombie[victim]) return;
3047 }
3048 }
3049 }
3050 else
3051 {
3052 if (g_survivor[victim])
3053 {
3054 if (!get_pcvar_num(cvar_survpainfree)) return;
3055 }
3056 else if (g_sniper[victim])
3057 {
3058 if (!get_pcvar_num(cvar_snipainfree)) return;
3059 }
3060
3061 else return;
3062 }
3063
3064 // Prevent server crash if entity's private data not initalized
3065 if (pev_valid(victim) != PDATA_SAFE)
3066 return;
3067
3068 // Set pain shock free offset
3069 set_pdata_float(victim, OFFSET_PAINSHOCK, 1.0, OFFSET_LINUX)
3070}
3071
3072// Ham Trace Attack Forward
3073public fw_TraceAttack(victim, attacker, Float:damage, Float:direction[3], tracehandle, damage_type)
3074{
3075 // Non-player damage or self damage
3076 if (victim == attacker || !is_user_valid_connected(attacker))
3077 return HAM_IGNORED;
3078
3079 // New round starting or round ended
3080 if (g_newround || g_endround)
3081 return HAM_SUPERCEDE;
3082
3083 // Victim shouldn't take damage or victim is frozen
3084 if (g_nodamage[victim] || (g_frozen[victim] && get_pcvar_num(cvar_dmg_while_freeze)))
3085 return HAM_SUPERCEDE;
3086
3087 // Prevent friendly fire
3088 if (g_zombie[attacker] == g_zombie[victim])
3089 return HAM_SUPERCEDE;
3090
3091 // Victim isn't a zombie or not bullet damage, nothing else to do here
3092 if (!g_zombie[victim] || !(damage_type & DMG_BULLET))
3093 return HAM_IGNORED;
3094
3095 // If zombie hitzones are enabled, check whether we hit an allowed one
3096 if (get_pcvar_num(cvar_hitzones) && !g_nemesis[victim] && !g_assassin[victim] && !(get_pcvar_num(cvar_hitzones) & (1<<get_tr2(tracehandle, TR_iHitgroup))))
3097 return HAM_SUPERCEDE;
3098
3099 // Knockback disabled, nothing else to do here
3100 if (!get_pcvar_num(cvar_knockback))
3101 return HAM_IGNORED;
3102
3103 // Nemesis knockback disabled, nothing else to do here
3104 if (g_nemesis[victim] && get_pcvar_float(cvar_nemknockback) == 0.0)
3105 return HAM_IGNORED;
3106
3107 // Assassin knockback disabled, nothing else to do here
3108 if (g_assassin[victim] && get_pcvar_float(cvar_assaknockback) == 0.0)
3109 return HAM_IGNORED;
3110
3111 // Get whether the victim is in a crouch state
3112 static ducking
3113 ducking = pev(victim, pev_flags) & (FL_DUCKING | FL_ONGROUND) == (FL_DUCKING | FL_ONGROUND)
3114
3115 // Zombie knockback when ducking disabled
3116 if (ducking && get_pcvar_float(cvar_knockbackducking) == 0.0)
3117 return HAM_IGNORED;
3118
3119 // Get distance between players
3120 static origin1[3], origin2[3]
3121 get_user_origin(victim, origin1)
3122 get_user_origin(attacker, origin2)
3123
3124 // Max distance exceeded
3125 if (get_distance(origin1, origin2) > get_pcvar_num(cvar_knockbackdist))
3126 return HAM_IGNORED;
3127
3128 // Get victim's velocity
3129 static Float:velocity[3]
3130 pev(victim, pev_velocity, velocity)
3131
3132 // Use damage on knockback calculation
3133 if (get_pcvar_num(cvar_knockbackdamage))
3134 xs_vec_mul_scalar(direction, damage, direction)
3135
3136 // Use weapon power on knockback calculation
3137 if (get_pcvar_num(cvar_knockbackpower) && kb_weapon_power[g_currentweapon[attacker]] > 0.0)
3138 xs_vec_mul_scalar(direction, kb_weapon_power[g_currentweapon[attacker]], direction)
3139
3140 // Apply ducking knockback multiplier
3141 if (ducking)
3142 xs_vec_mul_scalar(direction, get_pcvar_float(cvar_knockbackducking), direction)
3143
3144 // Apply zombie class/nemesis knockback multiplier
3145 if (g_nemesis[victim])
3146 xs_vec_mul_scalar(direction, get_pcvar_float(cvar_nemknockback), direction)
3147 else if (g_assassin[victim])
3148 xs_vec_mul_scalar(direction, get_pcvar_float(cvar_assaknockback), direction)
3149 else
3150 xs_vec_mul_scalar(direction, g_zombie_knockback[victim], direction)
3151
3152 // Add up the new vector
3153 xs_vec_add(velocity, direction, direction)
3154
3155 // Should knockback also affect vertical velocity?
3156 if (!get_pcvar_num(cvar_knockbackzvel))
3157 direction[2] = velocity[2]
3158
3159 // Set the knockback'd victim's velocity
3160 set_pev(victim, pev_velocity, direction)
3161
3162 return HAM_IGNORED;
3163}
3164
3165// Ham Reset MaxSpeed Post Forward
3166public fw_ResetMaxSpeed_Post(id)
3167{
3168 // Freezetime active or player not alive
3169 if (g_freezetime || !g_isalive[id])
3170 return;
3171
3172 set_player_maxspeed(id)
3173}
3174
3175// Ham Use Stationary Gun Forward
3176public fw_UseStationary(entity, caller, activator, use_type)
3177{
3178 // Prevent zombies from using stationary guns
3179 if (use_type == USE_USING && is_user_valid_connected(caller) && g_zombie[caller])
3180 return HAM_SUPERCEDE;
3181
3182 return HAM_IGNORED;
3183}
3184
3185// Ham Use Stationary Gun Post Forward
3186public fw_UseStationary_Post(entity, caller, activator, use_type)
3187{
3188 // Someone stopped using a stationary gun
3189 if (use_type == USE_STOPPED && is_user_valid_connected(caller))
3190 replace_weapon_models(caller, g_currentweapon[caller]) // replace weapon models (bugfix)
3191}
3192
3193// Ham Use Pushable Forward
3194public fw_UsePushable()
3195{
3196 // Prevent speed bug with pushables?
3197 if (get_pcvar_num(cvar_blockpushables))
3198 return HAM_SUPERCEDE;
3199
3200 return HAM_IGNORED;
3201}
3202
3203// Ham Weapon Touch Forward
3204public fw_TouchWeapon(weapon, id)
3205{
3206 // Not a player
3207 if (!is_user_valid_connected(id))
3208 return HAM_IGNORED;
3209
3210 // Dont pickup weapons if zombie or survivor (+PODBot MM fix)
3211 if (g_zombie[id] || g_isbot[id] || ((g_survivor[id] || g_sniper[id]) && (g_isbot[id] || g_isalive[id])))
3212 return HAM_SUPERCEDE;
3213
3214 return HAM_IGNORED;
3215}
3216
3217// Ham Weapon Pickup Forward
3218public fw_AddPlayerItem(id, weapon_ent)
3219{
3220 // HACK: Retrieve our custom extra ammo from the weapon
3221 static extra_ammo
3222 extra_ammo = pev(weapon_ent, PEV_ADDITIONAL_AMMO)
3223
3224 // If present
3225 if (extra_ammo)
3226 {
3227 // Get weapon's id
3228 static weaponid
3229 weaponid = cs_get_weapon_id(weapon_ent)
3230
3231 // Add to player's bpammo
3232 ExecuteHamB(Ham_GiveAmmo, id, extra_ammo, AMMOTYPE[weaponid], MAXBPAMMO[weaponid])
3233 set_pev(weapon_ent, PEV_ADDITIONAL_AMMO, 0)
3234 }
3235}
3236
3237// Ham Weapon Deploy Forward
3238public fw_Item_Deploy_Post(weapon_ent)
3239{
3240 // Get weapon's owner
3241 static owner
3242 owner = fm_cs_get_weapon_ent_owner(weapon_ent)
3243
3244 // Valid owner?
3245 if (!pev_valid(owner))
3246 return;
3247
3248 // Get weapon's id
3249 static weaponid
3250 weaponid = cs_get_weapon_id(weapon_ent)
3251
3252 // Store current weapon's id for reference
3253 g_currentweapon[owner] = weaponid
3254
3255 // Replace weapon models with custom ones
3256 replace_weapon_models(owner, weaponid)
3257
3258 // Zombie not holding an allowed weapon for some reason
3259 if (g_zombie[owner] && !((1<<weaponid) & ZOMBIE_ALLOWED_WEAPONS_BITSUM))
3260 {
3261 // Switch to knife
3262 g_currentweapon[owner] = CSW_KNIFE
3263 engclient_cmd(owner, "weapon_knife")
3264 }
3265}
3266
3267// WeaponMod bugfix
3268//forward wpn_gi_reset_weapon(id);
3269public wpn_gi_reset_weapon(id)
3270{
3271 // Replace knife model
3272 replace_weapon_models(id, CSW_KNIFE)
3273}
3274
3275// Client joins the game
3276public client_putinserver(id)
3277{
3278 // Plugin disabled?
3279 if (!g_pluginenabled) return;
3280
3281 // Player joined
3282 g_isconnected[id] = true
3283
3284 // Cache player's name
3285 get_user_name(id, g_playername[id], charsmax(g_playername[]))
3286
3287 // Initialize player vars
3288 reset_vars(id, 1)
3289
3290 // Load player stats?
3291 if (get_pcvar_num(cvar_statssave)) load_stats(id)
3292
3293 // Set some tasks for humans only
3294 if (!is_user_bot(id))
3295 {
3296 // Set the custom HUD display task if enabled
3297 if (get_pcvar_num(cvar_huddisplay))
3298 set_task(1.0, "ShowHUD", id+TASK_SHOWHUD, _, _, "b")
3299
3300 // Disable minmodels for clients to see zombies properly
3301 set_task(5.0, "disable_minmodels", id)
3302 }
3303 else
3304 {
3305 // Set bot flag
3306 g_isbot[id] = true
3307
3308 // CZ bots seem to use a different "classtype" for player entities
3309 // (or something like that) which needs to be hooked separately
3310 if (!g_hamczbots && cvar_botquota)
3311 {
3312 // Set a task to let the private data initialize
3313 set_task(0.1, "register_ham_czbots", id)
3314 }
3315 }
3316}
3317
3318// Client leaving
3319public fw_ClientDisconnect(id)
3320{
3321 // Check that we still have both humans and zombies to keep the round going
3322 if (g_isalive[id]) check_round(id)
3323
3324 // Temporarily save player stats?
3325 if (get_pcvar_num(cvar_statssave)) save_stats(id)
3326
3327 // Remove previous tasks
3328 remove_task(id+TASK_TEAM)
3329 remove_task(id+TASK_MODEL)
3330 remove_task(id+TASK_FLASH)
3331 remove_task(id+TASK_CHARGE)
3332 remove_task(id+TASK_SPAWN)
3333 remove_task(id+TASK_BLOOD)
3334 remove_task(id+TASK_AURA)
3335 remove_task(id+TASK_BURN)
3336 remove_task(id+TASK_NVISION)
3337 remove_task(id+TASK_SHOWHUD)
3338
3339 if (g_handle_models_on_separate_ent)
3340 {
3341 // Remove custom model entities
3342 fm_remove_model_ents(id)
3343 }
3344
3345 // Player left, clear cached flags
3346 g_isconnected[id] = false
3347 g_isbot[id] = false
3348 g_isalive[id] = false
3349}
3350
3351// Client left
3352public fw_ClientDisconnect_Post()
3353{
3354 // Last Zombie Check
3355 fnCheckLastZombie()
3356}
3357
3358// Client Kill Forward
3359public fw_ClientKill()
3360{
3361 // Prevent players from killing themselves?
3362 if (get_pcvar_num(cvar_blocksuicide))
3363 return FMRES_SUPERCEDE;
3364
3365 return FMRES_IGNORED;
3366}
3367
3368// Emit Sound Forward
3369public fw_EmitSound(id, channel, const sample[], Float:volume, Float:attn, flags, pitch)
3370{
3371 // Block all those unneeeded hostage sounds
3372 if (sample[0] == 'h' && sample[1] == 'o' && sample[2] == 's' && sample[3] == 't' && sample[4] == 'a' && sample[5] == 'g' && sample[6] == 'e')
3373 return FMRES_SUPERCEDE;
3374
3375 // Replace these next sounds for zombies only
3376 if (!is_user_valid_connected(id) || !g_zombie[id])
3377 return FMRES_IGNORED;
3378
3379 static sound[64]
3380
3381 // Zombie being hit
3382 if (sample[7] == 'b' && sample[8] == 'h' && sample[9] == 'i' && sample[10] == 't')
3383 {
3384 if (g_nemesis[id])
3385 {
3386 ArrayGetString(nemesis_pain, random_num(0, ArraySize(nemesis_pain) - 1), sound, charsmax(sound))
3387 emit_sound(id, channel, sound, volume, attn, flags, pitch)
3388 }
3389 else if (g_assassin[id])
3390 {
3391 ArrayGetString(assassin_pain, random_num(0, ArraySize(assassin_pain) - 1), sound, charsmax(sound))
3392 emit_sound(id, channel, sound, volume, attn, flags, pitch)
3393 }
3394 else
3395 {
3396 ArrayGetString(zombie_pain, random_num(0, ArraySize(zombie_pain) - 1), sound, charsmax(sound))
3397 emit_sound(id, channel, sound, volume, attn, flags, pitch)
3398 }
3399 return FMRES_SUPERCEDE;
3400 }
3401
3402 // Zombie attacks with knife
3403 if (sample[8] == 'k' && sample[9] == 'n' && sample[10] == 'i')
3404 {
3405 if (sample[14] == 's' && sample[15] == 'l' && sample[16] == 'a') // slash
3406 {
3407 ArrayGetString(zombie_miss_slash, random_num(0, ArraySize(zombie_miss_slash) - 1), sound, charsmax(sound))
3408 emit_sound(id, channel, sound, volume, attn, flags, pitch)
3409 return FMRES_SUPERCEDE;
3410 }
3411 if (sample[14] == 'h' && sample[15] == 'i' && sample[16] == 't') // hit
3412 {
3413 if (sample[17] == 'w') // wall
3414 {
3415 ArrayGetString(zombie_miss_wall, random_num(0, ArraySize(zombie_miss_wall) - 1), sound, charsmax(sound))
3416 emit_sound(id, channel, sound, volume, attn, flags, pitch)
3417 return FMRES_SUPERCEDE;
3418 }
3419 else
3420 {
3421 ArrayGetString(zombie_hit_normal, random_num(0, ArraySize(zombie_hit_normal) - 1), sound, charsmax(sound))
3422 emit_sound(id, channel, sound, volume, attn, flags, pitch)
3423 return FMRES_SUPERCEDE;
3424 }
3425 }
3426 if (sample[14] == 's' && sample[15] == 't' && sample[16] == 'a') // stab
3427 {
3428 ArrayGetString(zombie_hit_stab, random_num(0, ArraySize(zombie_hit_stab) - 1), sound, charsmax(sound))
3429 emit_sound(id, channel, sound, volume, attn, flags, pitch)
3430 return FMRES_SUPERCEDE;
3431 }
3432 }
3433
3434 // Zombie dies
3435 if (sample[7] == 'd' && ((sample[8] == 'i' && sample[9] == 'e') || (sample[8] == 'e' && sample[9] == 'a')))
3436 {
3437 ArrayGetString(zombie_die, random_num(0, ArraySize(zombie_die) - 1), sound, charsmax(sound))
3438 emit_sound(id, channel, sound, volume, attn, flags, pitch)
3439 return FMRES_SUPERCEDE;
3440 }
3441
3442 // Zombie falls off
3443 if (sample[10] == 'f' && sample[11] == 'a' && sample[12] == 'l' && sample[13] == 'l')
3444 {
3445 ArrayGetString(zombie_fall, random_num(0, ArraySize(zombie_fall) - 1), sound, charsmax(sound))
3446 emit_sound(id, channel, sound, volume, attn, flags, pitch)
3447 return FMRES_SUPERCEDE;
3448 }
3449
3450 return FMRES_IGNORED;
3451}
3452
3453// Forward Set ClientKey Value -prevent CS from changing player models-
3454public fw_SetClientKeyValue(id, const infobuffer[], const key[])
3455{
3456 // Block CS model changes
3457 if (key[0] == 'm' && key[1] == 'o' && key[2] == 'd' && key[3] == 'e' && key[4] == 'l')
3458 return FMRES_SUPERCEDE;
3459
3460 return FMRES_IGNORED;
3461}
3462
3463// Forward Client User Info Changed -prevent players from changing models-
3464public fw_ClientUserInfoChanged(id)
3465{
3466 // Cache player's name
3467 get_user_name(id, g_playername[id], charsmax(g_playername[]))
3468
3469 if (!g_handle_models_on_separate_ent)
3470 {
3471 // Get current model
3472 static currentmodel[32]
3473 fm_cs_get_user_model(id, currentmodel, charsmax(currentmodel))
3474
3475 // If they're different, set model again
3476 if (!equal(currentmodel, g_playermodel[id]) && !task_exists(id+TASK_MODEL))
3477 fm_cs_set_user_model(id+TASK_MODEL)
3478 }
3479}
3480
3481// Forward Get Game Description
3482public fw_GetGameDescription()
3483{
3484 // Return the mod name so it can be easily identified
3485 forward_return(FMV_STRING, g_modname)
3486
3487 return FMRES_SUPERCEDE;
3488}
3489
3490// Forward Set Model
3491public fw_SetModel(entity, const model[])
3492{
3493 // We don't care
3494 if (strlen(model) < 8)
3495 return;
3496
3497 // Remove weapons?
3498 if (get_pcvar_float(cvar_removedropped) > 0.0)
3499 {
3500 // Get entity's classname
3501 static classname[10]
3502 pev(entity, pev_classname, classname, charsmax(classname))
3503
3504 // Check if it's a weapon box
3505 if (equal(classname, "weaponbox"))
3506 {
3507 // They get automatically removed when thinking
3508 set_pev(entity, pev_nextthink, get_gametime() + get_pcvar_float(cvar_removedropped))
3509 return;
3510 }
3511 }
3512
3513 // Narrow down our matches a bit
3514 if (model[7] != 'w' || model[8] != '_')
3515 return;
3516
3517 // Get damage time of grenade
3518 static Float:dmgtime
3519 pev(entity, pev_dmgtime, dmgtime)
3520
3521 // Grenade not yet thrown
3522 if (dmgtime == 0.0)
3523 return;
3524
3525 // Get whether grenade's owner is a zombie
3526 if (g_zombie[pev(entity, pev_owner)])
3527 {
3528 if (model[9] == 'h' && model[10] == 'e' && get_pcvar_num(cvar_extrainfbomb)) // Infection Bomb
3529 {
3530 // Give it a glow
3531 fm_set_rendering(entity, kRenderFxGlowShell, 0, 200, 0, kRenderNormal, 16);
3532
3533 // And a colored trail
3534 message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
3535 write_byte(TE_BEAMFOLLOW) // TE id
3536 write_short(entity) // entity
3537 write_short(g_trailSpr) // sprite
3538 write_byte(10) // life
3539 write_byte(10) // width
3540 write_byte(0) // r
3541 write_byte(200) // g
3542 write_byte(0) // b
3543 write_byte(200) // brightness
3544 message_end()
3545
3546 // Set grenade type on the thrown grenade entity
3547 set_pev(entity, PEV_NADE_TYPE, NADE_TYPE_INFECTION)
3548 }
3549 }
3550 else if (model[9] == 'h' && model[10] == 'e' && get_pcvar_num(cvar_firegrenades)) // Napalm Grenade
3551 {
3552 // Give it a glow
3553 fm_set_rendering(entity, kRenderFxGlowShell, 200, 0, 0, kRenderNormal, 16);
3554
3555 // And a colored trail
3556 message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
3557 write_byte(TE_BEAMFOLLOW) // TE id
3558 write_short(entity) // entity
3559 write_short(g_trailSpr) // sprite
3560 write_byte(10) // life
3561 write_byte(10) // width
3562 write_byte(200) // r
3563 write_byte(0) // g
3564 write_byte(0) // b
3565 write_byte(200) // brightness
3566 message_end()
3567
3568 // Set grenade type on the thrown grenade entity
3569 set_pev(entity, PEV_NADE_TYPE, NADE_TYPE_NAPALM)
3570 }
3571 else if (model[9] == 'f' && model[10] == 'l' && get_pcvar_num(cvar_frostgrenades)) // Frost Grenade
3572 {
3573 // Give it a glow
3574 fm_set_rendering(entity, kRenderFxGlowShell, 0, 100, 200, kRenderNormal, 16);
3575
3576 // And a colored trail
3577 message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
3578 write_byte(TE_BEAMFOLLOW) // TE id
3579 write_short(entity) // entity
3580 write_short(g_trailSpr) // sprite
3581 write_byte(10) // life
3582 write_byte(10) // width
3583 write_byte(0) // r
3584 write_byte(100) // g
3585 write_byte(200) // b
3586 write_byte(200) // brightness
3587 message_end()
3588
3589 // Set grenade type on the thrown grenade entity
3590 set_pev(entity, PEV_NADE_TYPE, NADE_TYPE_FROST)
3591 }
3592 else if (model[9] == 's' && model[10] == 'm' && get_pcvar_num(cvar_flaregrenades)) // Flare
3593 {
3594 // Build flare's color
3595 static rgb[3]
3596 switch (get_pcvar_num(cvar_flarecolor))
3597 {
3598 case 0: // white
3599 {
3600 rgb[0] = 255 // r
3601 rgb[1] = 255 // g
3602 rgb[2] = 255 // b
3603 }
3604 case 1: // red
3605 {
3606 rgb[0] = random_num(50,255) // r
3607 rgb[1] = 0 // g
3608 rgb[2] = 0 // b
3609 }
3610 case 2: // green
3611 {
3612 rgb[0] = 0 // r
3613 rgb[1] = random_num(50,255) // g
3614 rgb[2] = 0 // b
3615 }
3616 case 3: // blue
3617 {
3618 rgb[0] = 0 // r
3619 rgb[1] = 0 // g
3620 rgb[2] = random_num(50,255) // b
3621 }
3622 case 4: // random (all colors)
3623 {
3624 rgb[0] = random_num(50,200) // r
3625 rgb[1] = random_num(50,200) // g
3626 rgb[2] = random_num(50,200) // b
3627 }
3628 case 5: // random (r,g,b)
3629 {
3630 switch (random_num(1, 3))
3631 {
3632 case 1: // red
3633 {
3634 rgb[0] = random_num(50,255) // r
3635 rgb[1] = 0 // g
3636 rgb[2] = 0 // b
3637 }
3638 case 2: // green
3639 {
3640 rgb[0] = 0 // r
3641 rgb[1] = random_num(50,255) // g
3642 rgb[2] = 0 // b
3643 }
3644 case 3: // blue
3645 {
3646 rgb[0] = 0 // r
3647 rgb[1] = 0 // g
3648 rgb[2] = random_num(50,255) // b
3649 }
3650 }
3651 }
3652 }
3653
3654 // Give it a glow
3655 fm_set_rendering(entity, kRenderFxGlowShell, rgb[0], rgb[1], rgb[2], kRenderNormal, 16);
3656
3657 // And a colored trail
3658 message_begin(MSG_BROADCAST, SVC_TEMPENTITY)
3659 write_byte(TE_BEAMFOLLOW) // TE id
3660 write_short(entity) // entity
3661 write_short(g_trailSpr) // sprite
3662 write_byte(10) // life
3663 write_byte(10) // width
3664 write_byte(rgb[0]) // r
3665 write_byte(rgb[1]) // g
3666 write_byte(rgb[2]) // b
3667 write_byte(200) // brightness
3668 message_end()
3669
3670 // Set grenade type on the thrown grenade entity
3671 set_pev(entity, PEV_NADE_TYPE, NADE_TYPE_FLARE)
3672
3673 // Set flare color on the thrown grenade entity
3674 set_pev(entity, PEV_FLARE_COLOR, rgb)
3675 }
3676}
3677
3678// Ham Grenade Think Forward
3679public fw_ThinkGrenade(entity)
3680{
3681 // Invalid entity
3682 if (!pev_valid(entity)) return HAM_IGNORED;
3683
3684 // Get damage time of grenade
3685 static Float:dmgtime, Float:current_time
3686 pev(entity, pev_dmgtime, dmgtime)
3687 current_time = get_gametime()
3688
3689 // Check if it's time to go off
3690 if (dmgtime > current_time)
3691 return HAM_IGNORED;
3692
3693 // Check if it's one of our custom nades
3694 switch (pev(entity, PEV_NADE_TYPE))
3695 {
3696 case NADE_TYPE_INFECTION: // Infection Bomb
3697 {
3698 infection_explode(entity)
3699 return HAM_SUPERCEDE;
3700 }
3701 case NADE_TYPE_NAPALM: // Napalm Grenade
3702 {
3703 fire_explode(entity)
3704 return HAM_SUPERCEDE;
3705 }
3706 case NADE_TYPE_FROST: // Frost Grenade
3707 {
3708 frost_explode(entity)
3709 return HAM_SUPERCEDE;
3710 }
3711 case NADE_TYPE_FLARE: // Flare
3712 {
3713 // Get its duration
3714 static duration
3715 duration = pev(entity, PEV_FLARE_DURATION)
3716
3717 // Already went off, do lighting loop for the duration of PEV_FLARE_DURATION
3718 if (duration > 0)
3719 {
3720 // Check whether this is the last loop
3721 if (duration == 1)
3722 {
3723 // Get rid of the flare entity
3724 engfunc(EngFunc_RemoveEntity, entity)
3725 return HAM_SUPERCEDE;
3726 }
3727
3728 // Light it up!
3729 flare_lighting(entity, duration)
3730
3731 // Set time for next loop
3732 set_pev(entity, PEV_FLARE_DURATION, --duration)
3733 set_pev(entity, pev_dmgtime, current_time + 2.0)
3734 }
3735 // Light up when it's stopped on ground
3736 else if ((pev(entity, pev_flags) & FL_ONGROUND) && fm_get_speed(entity) < 10)
3737 {
3738 // Flare sound
3739 static sound[64]
3740 ArrayGetString(grenade_flare, random_num(0, ArraySize(grenade_flare) - 1), sound, charsmax(sound))
3741 emit_sound(entity, CHAN_WEAPON, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
3742
3743 // Set duration and start lightning loop on next think
3744 set_pev(entity, PEV_FLARE_DURATION, 1 + get_pcvar_num(cvar_flareduration)/2)
3745 set_pev(entity, pev_dmgtime, current_time + 0.1)
3746 }
3747 else
3748 {
3749 // Delay explosion until we hit ground
3750 set_pev(entity, pev_dmgtime, current_time + 0.5)
3751 }
3752 }
3753 }
3754
3755 return HAM_IGNORED;
3756}
3757
3758// Forward CmdStart
3759public fw_CmdStart(id, handle)
3760{
3761 // Not alive
3762 if (!g_isalive[id])
3763 return;
3764
3765 // This logic looks kinda weird, but it should work in theory...
3766 // p = g_zombie[id], q = g_survivor[id], r = g_cached_customflash
3767 // ?p v q v (? ^ r)) <==> ? ^ ? ^ (p v ?)
3768 if (!g_zombie[id] && !g_survivor[id] && !g_sniper[id] && (g_zombie[id] || !g_cached_customflash))
3769 return;
3770
3771 // Check if it's a flashlight impulse
3772 if (get_uc(handle, UC_Impulse) != IMPULSE_FLASHLIGHT)
3773 return;
3774
3775 // Block it I say!
3776 set_uc(handle, UC_Impulse, 0)
3777
3778 // Should human's custom flashlight be turned on?
3779 if (!g_zombie[id] && !g_survivor[id] && !g_sniper[id] && g_flashbattery[id] > 2 && get_gametime() - g_lastflashtime[id] > 1.2)
3780 {
3781 // Prevent calling flashlight too quickly (bugfix)
3782 g_lastflashtime[id] = get_gametime()
3783
3784 // Toggle custom flashlight
3785 g_flashlight[id] = !(g_flashlight[id])
3786
3787 // Play flashlight toggle sound
3788 emit_sound(id, CHAN_ITEM, sound_flashlight, 1.0, ATTN_NORM, 0, PITCH_NORM)
3789
3790 // Update flashlight status on the HUD
3791 message_begin(MSG_ONE, g_msgFlashlight, _, id)
3792 write_byte(g_flashlight[id]) // toggle
3793 write_byte(g_flashbattery[id]) // battery
3794 message_end()
3795
3796 // Remove previous tasks
3797 remove_task(id+TASK_CHARGE)
3798 remove_task(id+TASK_FLASH)
3799
3800 // Set the flashlight charge task
3801 set_task(1.0, "flashlight_charge", id+TASK_CHARGE, _, _, "b")
3802
3803 // Call our custom flashlight task if enabled
3804 if (g_flashlight[id]) set_task(0.1, "set_user_flashlight", id+TASK_FLASH, _, _, "b")
3805 }
3806}
3807
3808// Forward Player PreThink
3809public fw_PlayerPreThink(id)
3810{
3811 // Not alive
3812 if (!g_isalive[id])
3813 return;
3814
3815 // Enable custom buyzone for player during buytime, unless zombie or survivor or time expired
3816 if (g_cached_buytime > 0.0 && !g_zombie[id] && !g_survivor[id] && (get_gametime() < g_buytime[id] + g_cached_buytime))
3817 {
3818 if (pev_valid(g_buyzone_ent))
3819 dllfunc(DLLFunc_Touch, g_buyzone_ent, id)
3820 }
3821
3822 // Silent footsteps for zombies?
3823 if (g_cached_zombiesilent && g_zombie[id] && !g_nemesis[id] && g_assassin[id])
3824 set_pev(id, pev_flTimeStepSound, STEPTIME_SILENT)
3825
3826 // Player frozen?
3827 if (g_frozen[id])
3828 {
3829 set_pev(id, pev_velocity, Float:{0.0,0.0,0.0}) // stop motion
3830 return; // shouldn't leap while frozen
3831 }
3832
3833 // --- Check if player should leap ---
3834
3835 // Don't allow leap during freezetime
3836 if (g_freezetime)
3837 return;
3838
3839 // Check if proper CVARs are enabled and retrieve leap settings
3840 static Float:cooldown, Float:current_time
3841 if (g_zombie[id])
3842 {
3843 if (g_nemesis[id])
3844 {
3845 if (!g_cached_leapnemesis) return;
3846 cooldown = g_cached_leapnemesiscooldown
3847 }
3848 else if (g_assassin[id])
3849 {
3850 if (!g_cached_leapassassin) return;
3851 cooldown = g_cached_leapassassincooldown
3852 }
3853 else
3854 {
3855 switch (g_cached_leapzombies)
3856 {
3857 case 0: return;
3858 case 2: if (!g_firstzombie[id]) return;
3859 case 3: if (!g_lastzombie[id]) return;
3860 }
3861 cooldown = g_cached_leapzombiescooldown
3862 }
3863 }
3864 else
3865 {
3866 if (g_survivor[id])
3867 {
3868 if (!g_cached_leapsurvivor) return;
3869 cooldown = g_cached_leapsurvivorcooldown
3870 }
3871 else if (g_sniper[id])
3872 {
3873 if (!g_cached_leapsniper) return;
3874 cooldown = g_cached_leapsnipercooldown
3875 }
3876 else return;
3877 }
3878
3879 current_time = get_gametime()
3880
3881 // Cooldown not over yet
3882 if (current_time - g_lastleaptime[id] < cooldown)
3883 return;
3884
3885 // Not doing a longjump (don't perform check for bots, they leap automatically)
3886 if (!g_isbot[id] && !(pev(id, pev_button) & (IN_JUMP | IN_DUCK) == (IN_JUMP | IN_DUCK)))
3887 return;
3888
3889 // Not on ground or not enough speed
3890 if (!(pev(id, pev_flags) & FL_ONGROUND) || fm_get_speed(id) < 80)
3891 return;
3892
3893 static Float:velocity[3]
3894
3895 // Make velocity vector
3896 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)
3897
3898 // Set custom height
3899 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)
3900
3901 // Apply the new velocity
3902 set_pev(id, pev_velocity, velocity)
3903
3904 // Update last leap time
3905 g_lastleaptime[id] = current_time
3906}
3907
3908/*================================================================================
3909 [Client Commands]
3910=================================================================================*/
3911
3912// Say "/zpmenu"
3913public clcmd_saymenu(id)
3914{
3915 show_menu_game(id) // show game menu
3916}
3917
3918// Say "/unstuck"
3919public clcmd_sayunstuck(id)
3920{
3921 menu_game(id, 3) // try to get unstuck
3922}
3923
3924// Nightvision toggle
3925public clcmd_nightvision(id)
3926{
3927 // Nightvision available to player?
3928 if (g_nvision[id] || (g_isalive[id] && cs_get_user_nvg(id)))
3929 {
3930 // Enable-disable
3931 g_nvisionenabled[id] = !(g_nvisionenabled[id])
3932
3933 // Custom nvg?
3934 if (get_pcvar_num(cvar_customnvg))
3935 {
3936 remove_task(id+TASK_NVISION)
3937 if (g_nvisionenabled[id]) set_task(0.1, "set_user_nvision", id+TASK_NVISION, _, _, "b")
3938 }
3939 else
3940 set_user_gnvision(id, g_nvisionenabled[id])
3941 }
3942
3943 return PLUGIN_HANDLED;
3944}
3945
3946// Weapon Drop
3947public clcmd_drop(id)
3948{
3949 // Survivor should stick with its weapon
3950 if (g_survivor[id] || g_sniper[id])
3951 return PLUGIN_HANDLED;
3952
3953 return PLUGIN_CONTINUE;
3954}
3955
3956// Buy BP Ammo
3957public clcmd_buyammo(id)
3958{
3959 // Not alive or infinite ammo setting enabled
3960 if (!g_isalive[id] || get_pcvar_num(cvar_infammo))
3961 return PLUGIN_HANDLED;
3962
3963 // Not human
3964 if (g_zombie[id])
3965 {
3966 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_HUMAN_ONLY")
3967 return PLUGIN_HANDLED;
3968 }
3969
3970 // Custom buytime enabled and human player standing in buyzone, allow buying weapon's ammo normally instead
3971 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))
3972 return PLUGIN_CONTINUE;
3973
3974 // Not enough ammo packs
3975 if (g_ammopacks[id] < 1)
3976 {
3977 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "NOT_ENOUGH_AMMO")
3978 return PLUGIN_HANDLED;
3979 }
3980
3981 // Get user weapons
3982 static weapons[32], num, i, currentammo, weaponid, refilled
3983 num = 0 // reset passed weapons count (bugfix)
3984 refilled = false
3985 get_user_weapons(id, weapons, num)
3986
3987 // Loop through them and give the right ammo type
3988 for (i = 0; i < num; i++)
3989 {
3990 // Prevents re-indexing the array
3991 weaponid = weapons[i]
3992
3993 // Primary and secondary only
3994 if (MAXBPAMMO[weaponid] > 2)
3995 {
3996 // Get current ammo of the weapon
3997 currentammo = cs_get_user_bpammo(id, weaponid)
3998
3999 // Give additional ammo
4000 ExecuteHamB(Ham_GiveAmmo, id, BUYAMMO[weaponid], AMMOTYPE[weaponid], MAXBPAMMO[weaponid])
4001
4002 // Check whether we actually refilled the weapon's ammo
4003 if (cs_get_user_bpammo(id, weaponid) - currentammo > 0) refilled = true
4004 }
4005 }
4006
4007 // Weapons already have full ammo
4008 if (!refilled) return PLUGIN_HANDLED;
4009
4010 // Deduce ammo packs, play clip purchase sound, and notify player
4011 g_ammopacks[id]--
4012 emit_sound(id, CHAN_ITEM, sound_buyammo, 1.0, ATTN_NORM, 0, PITCH_NORM)
4013 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "AMMO_BOUGHT")
4014
4015 return PLUGIN_HANDLED;
4016}
4017
4018// Block Team Change
4019public clcmd_changeteam(id)
4020{
4021 static team
4022 team = fm_cs_get_user_team(id)
4023
4024 // Unless it's a spectator joining the game
4025 if (team == FM_CS_TEAM_SPECTATOR || team == FM_CS_TEAM_UNASSIGNED)
4026 return PLUGIN_CONTINUE;
4027
4028 // Pressing 'M' (chooseteam) ingame should show the main menu instead
4029 show_menu_game(id)
4030 return PLUGIN_HANDLED;
4031}
4032
4033/*================================================================================
4034 [Menus]
4035=================================================================================*/
4036
4037// Game Menu
4038show_menu_game(id)
4039{
4040 // Player disconnected?
4041 if (!g_isconnected[id])
4042 return;
4043
4044 static menu[250], len, userflags
4045 len = 0
4046 userflags = get_user_flags(id)
4047
4048 // Title
4049 len += formatex(menu[len], charsmax(menu) - len, "\y%s^n^n", g_modname)
4050
4051 // 1. Buy weapons
4052 if (get_pcvar_num(cvar_buycustom))
4053 len += formatex(menu[len], charsmax(menu) - len, "\r1.\w %L^n", id, "MENU_BUY")
4054 else
4055 len += formatex(menu[len], charsmax(menu) - len, "\d1. %L^n", id, "MENU_BUY")
4056
4057 // 2. Extra items
4058 if (get_pcvar_num(cvar_extraitems) && g_isalive[id])
4059 len += formatex(menu[len], charsmax(menu) - len, "\r2.\w %L^n", id, "MENU_EXTRABUY")
4060 else
4061 len += formatex(menu[len], charsmax(menu) - len, "\d2. %L^n", id, "MENU_EXTRABUY")
4062
4063 // 3. Zombie class
4064 if (get_pcvar_num(cvar_zclasses))
4065 len += formatex(menu[len], charsmax(menu) - len, "\r3.\w %L^n", id,"MENU_ZCLASS")
4066 else
4067 len += formatex(menu[len], charsmax(menu) - len, "\d3. %L^n", id,"MENU_ZCLASS")
4068
4069 // 4. Unstuck
4070 if (g_isalive[id])
4071 len += formatex(menu[len], charsmax(menu) - len, "\r4.\w %L^n", id, "MENU_UNSTUCK")
4072 else
4073 len += formatex(menu[len], charsmax(menu) - len, "\d4. %L^n", id, "MENU_UNSTUCK")
4074
4075 // 5. Help
4076 len += formatex(menu[len], charsmax(menu) - len, "\r5.\w %L^n^n", id, "MENU_INFO")
4077
4078 // 6. Join spec
4079 if (!g_isalive[id] || !get_pcvar_num(cvar_blocksuicide) || (userflags & g_access_flag[ACCESS_ADMIN_MENU]))
4080 len += formatex(menu[len], charsmax(menu) - len, "\r6.\w %L^n^n", id, "MENU_SPECTATOR")
4081 else
4082 len += formatex(menu[len], charsmax(menu) - len, "\d6. %L^n^n", id, "MENU_SPECTATOR")
4083
4084 // 9. Admin menu
4085 if (userflags & g_access_flag[ACCESS_ADMIN_MENU])
4086 len += formatex(menu[len], charsmax(menu) - len, "\r9.\w %L", id, "MENU_ADMIN")
4087 else
4088 len += formatex(menu[len], charsmax(menu) - len, "\d9. %L", id, "MENU_ADMIN")
4089
4090 // 0. Exit
4091 len += formatex(menu[len], charsmax(menu) - len, "^n^n\r0.\w %L", id, "MENU_EXIT")
4092
4093 // Fix for AMXX custom menus
4094 if (pev_valid(id) == PDATA_SAFE)
4095 set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
4096
4097 show_menu(id, KEYSMENU, menu, -1, "Game Menu")
4098}
4099
4100// Buy Menu 1
4101public show_menu_buy1(taskid)
4102{
4103 // Get player's id
4104 static id
4105 (taskid > g_maxplayers) ? (id = ID_SPAWN) : (id = taskid);
4106
4107 // Player dead?
4108 if (!g_isalive[id])
4109 return;
4110
4111 // Zombies or survivors get no guns
4112 if (g_zombie[id] || g_survivor[id] || g_sniper[id])
4113 return;
4114
4115 // Bots pick their weapons randomly / Random weapons setting enabled
4116 if (get_pcvar_num(cvar_randweapons) || g_isbot[id])
4117 {
4118 buy_primary_weapon(id, random_num(0, ArraySize(g_primary_items) - 1))
4119 menu_buy2(id, random_num(0, ArraySize(g_secondary_items) - 1))
4120 return;
4121 }
4122
4123 // Automatic selection enabled for player and menu called on spawn event
4124 if (WPN_AUTO_ON && taskid > g_maxplayers)
4125 {
4126 buy_primary_weapon(id, WPN_AUTO_PRI)
4127 menu_buy2(id, WPN_AUTO_SEC)
4128 return;
4129 }
4130
4131 static menu[300], len, weap, maxloops
4132 len = 0
4133 maxloops = min(WPN_STARTID+7, WPN_MAXIDS)
4134
4135 // Title
4136 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))
4137
4138 // 1-7. Weapon List
4139 for (weap = WPN_STARTID; weap < maxloops; weap++)
4140 len += formatex(menu[len], charsmax(menu) - len, "\r%d.\w %s^n", weap-WPN_STARTID+1, WEAPONNAMES[ArrayGetCell(g_primary_weaponids, weap)])
4141
4142 // 8. Auto Select
4143 len += formatex(menu[len], charsmax(menu) - len, "^n\r8.\w %L \y[%L]", id, "MENU_AUTOSELECT", id, (WPN_AUTO_ON) ? "MOTD_ENABLED" : "MOTD_DISABLED")
4144
4145 // 9. Next/Back - 0. Exit
4146 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")
4147
4148 // Fix for AMXX custom menus
4149 if (pev_valid(id) == PDATA_SAFE)
4150 set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
4151
4152 show_menu(id, KEYSMENU, menu, -1, "Buy Menu 1")
4153}
4154
4155// Buy Menu 2
4156show_menu_buy2(id)
4157{
4158 // Player dead?
4159 if (!g_isalive[id])
4160 return;
4161
4162 static menu[250], len, weap, maxloops
4163 len = 0
4164 maxloops = ArraySize(g_secondary_items)
4165
4166 // Title
4167 len += formatex(menu[len], charsmax(menu) - len, "\y%L^n", id, "MENU_BUY2_TITLE")
4168
4169 // 1-6. Weapon List
4170 for (weap = 0; weap < maxloops; weap++)
4171 len += formatex(menu[len], charsmax(menu) - len, "^n\r%d.\w %s", weap+1, WEAPONNAMES[ArrayGetCell(g_secondary_weaponids, weap)])
4172
4173 // 8. Auto Select
4174 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")
4175
4176 // 0. Exit
4177 len += formatex(menu[len], charsmax(menu) - len, "^n^n\r0.\w %L", id, "MENU_EXIT")
4178
4179 // Fix for AMXX custom menus
4180 if (pev_valid(id) == PDATA_SAFE)
4181 set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
4182
4183 show_menu(id, KEYSMENU, menu, -1, "Buy Menu 2")
4184}
4185
4186// Extra Items Menu
4187show_menu_extras(id)
4188{
4189 // Player dead?
4190 if (!g_isalive[id])
4191 return;
4192
4193 static menuid, menu[128], item, team, buffer[32]
4194
4195 // Title
4196 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")
4197 menuid = menu_create(menu, "menu_extras")
4198
4199 // Item List
4200 for (item = 0; item < g_extraitem_i; item++)
4201 {
4202 // Retrieve item's team
4203 team = ArrayGetCell(g_extraitem_team, item)
4204
4205 // Item not available to player's team/class
4206 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)))
4207 continue;
4208
4209 // Check if it's one of the hardcoded items, check availability, set translated caption
4210 switch (item)
4211 {
4212 case EXTRA_NVISION:
4213 {
4214 if (!get_pcvar_num(cvar_extranvision)) continue;
4215 formatex(buffer, charsmax(buffer), "%L", id, "MENU_EXTRA1")
4216 }
4217 case EXTRA_ANTIDOTE:
4218 {
4219 if (!get_pcvar_num(cvar_extraantidote) || g_antidotecounter >= get_pcvar_num(cvar_antidotelimit)) continue;
4220 formatex(buffer, charsmax(buffer), "%L", id, "MENU_EXTRA2")
4221 }
4222 case EXTRA_MADNESS:
4223 {
4224 if (!get_pcvar_num(cvar_extramadness) || g_madnesscounter >= get_pcvar_num(cvar_madnesslimit)) continue;
4225 formatex(buffer, charsmax(buffer), "%L", id, "MENU_EXTRA3")
4226 }
4227 case EXTRA_INFBOMB:
4228 {
4229 if (!get_pcvar_num(cvar_extrainfbomb) || g_infbombcounter >= get_pcvar_num(cvar_infbomblimit)) continue;
4230 formatex(buffer, charsmax(buffer), "%L", id, "MENU_EXTRA4")
4231 }
4232 default:
4233 {
4234 if (item >= EXTRA_WEAPONS_STARTID && item <= EXTRAS_CUSTOM_STARTID-1 && !get_pcvar_num(cvar_extraweapons)) continue;
4235 ArrayGetString(g_extraitem_name, item, buffer, charsmax(buffer))
4236 }
4237 }
4238
4239 // Add Item Name and Cost
4240 formatex(menu, charsmax(menu), "%s \y%d %L", buffer, ArrayGetCell(g_extraitem_cost, item), id, "AMMO_PACKS2")
4241 buffer[0] = item
4242 buffer[1] = 0
4243 menu_additem(menuid, menu, buffer)
4244 }
4245
4246 // No items to display?
4247 if (menu_items(menuid) <= 0)
4248 {
4249 zp_colored_print(id, "^x04[ZP]^x01 %L", id ,"CMD_NOT_EXTRAS")
4250 menu_destroy(menuid)
4251 return;
4252 }
4253
4254 // Back - Next - Exit
4255 formatex(menu, charsmax(menu), "%L", id, "MENU_BACK")
4256 menu_setprop(menuid, MPROP_BACKNAME, menu)
4257 formatex(menu, charsmax(menu), "%L", id, "MENU_NEXT")
4258 menu_setprop(menuid, MPROP_NEXTNAME, menu)
4259 formatex(menu, charsmax(menu), "%L", id, "MENU_EXIT")
4260 menu_setprop(menuid, MPROP_EXITNAME, menu)
4261
4262 // If remembered page is greater than number of pages, clamp down the value
4263 MENU_PAGE_EXTRAS = min(MENU_PAGE_EXTRAS, menu_pages(menuid)-1)
4264
4265 // Fix for AMXX custom menus
4266 if (pev_valid(id) == PDATA_SAFE)
4267 set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
4268
4269 menu_display(id, menuid, 0)
4270}
4271
4272// Zombie Class Menu
4273public show_menu_zclass(id)
4274{
4275 // Player disconnected
4276 if (!g_isconnected[id])
4277 return;
4278
4279 // Bots pick their zombie class randomly
4280 if (g_isbot[id])
4281 {
4282 g_zombieclassnext[id] = random_num(0, g_zclass_i - 1)
4283 return;
4284 }
4285
4286 static menuid, menu[128], class, buffer[32], buffer2[32]
4287
4288 // Title
4289 formatex(menu, charsmax(menu), "%L\r", id, "MENU_ZCLASS_TITLE")
4290 menuid = menu_create(menu, "menu_zclass")
4291
4292 // Class List
4293 for (class = 0; class < g_zclass_i; class++)
4294 {
4295 // Retrieve name and info
4296 ArrayGetString(g_zclass_name, class, buffer, charsmax(buffer))
4297 ArrayGetString(g_zclass_info, class, buffer2, charsmax(buffer2))
4298
4299 // Add to menu
4300 if (class == g_zombieclassnext[id])
4301 formatex(menu, charsmax(menu), "\d%s %s", buffer, buffer2)
4302 else
4303 formatex(menu, charsmax(menu), "%s \y%s", buffer, buffer2)
4304
4305 buffer[0] = class
4306 buffer[1] = 0
4307 menu_additem(menuid, menu, buffer)
4308 }
4309
4310 // Back - Next - Exit
4311 formatex(menu, charsmax(menu), "%L", id, "MENU_BACK")
4312 menu_setprop(menuid, MPROP_BACKNAME, menu)
4313 formatex(menu, charsmax(menu), "%L", id, "MENU_NEXT")
4314 menu_setprop(menuid, MPROP_NEXTNAME, menu)
4315 formatex(menu, charsmax(menu), "%L", id, "MENU_EXIT")
4316 menu_setprop(menuid, MPROP_EXITNAME, menu)
4317
4318 // If remembered page is greater than number of pages, clamp down the value
4319 MENU_PAGE_ZCLASS = min(MENU_PAGE_ZCLASS, menu_pages(menuid)-1)
4320
4321 // Fix for AMXX custom menus
4322 if (pev_valid(id) == PDATA_SAFE)
4323 set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
4324
4325 menu_display(id, menuid, 0)
4326}
4327
4328// Help Menu
4329show_menu_info(id)
4330{
4331 // Player disconnected?
4332 if (!g_isconnected[id])
4333 return;
4334
4335 static menu[150]
4336
4337 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")
4338
4339 // Fix for AMXX custom menus
4340 if (pev_valid(id) == PDATA_SAFE)
4341 set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
4342
4343 show_menu(id, KEYSMENU, menu, -1, "Mod Info")
4344}
4345
4346// Admin Menu
4347show_menu_admin(id)
4348{
4349 // Player disconnected?
4350 if (!g_isconnected[id])
4351 return;
4352
4353 static menu[250], len, userflags
4354 len = 0
4355 userflags = get_user_flags(id)
4356
4357 // Title
4358 len += formatex(menu[len], charsmax(menu) - len, "\y%L^n^n", id, "MENU_ADMIN_TITLE")
4359
4360 // 1. Zombiefy/Humanize command
4361 if (userflags & (g_access_flag[ACCESS_MODE_INFECTION] | g_access_flag[ACCESS_MAKE_ZOMBIE] | g_access_flag[ACCESS_MAKE_HUMAN]))
4362 len += formatex(menu[len], charsmax(menu) - len, "\r1.\w %L^n", id, "MENU_ADMIN1")
4363 else
4364 len += formatex(menu[len], charsmax(menu) - len, "\d1. %L^n", id, "MENU_ADMIN1")
4365
4366 // 2. Nemesis command
4367 if (userflags & (g_access_flag[ACCESS_MODE_NEMESIS] | g_access_flag[ACCESS_MAKE_NEMESIS]))
4368 len += formatex(menu[len], charsmax(menu) - len, "\r2.\w %L^n", id, "MENU_ADMIN2")
4369 else
4370 len += formatex(menu[len], charsmax(menu) - len, "\d2. %L^n", id, "MENU_ADMIN2")
4371
4372 // 3. Assassin command
4373 if (userflags & (g_access_flag[ACCESS_MODE_ASSASSIN] | g_access_flag[ACCESS_MAKE_ASSASSIN]))
4374 len += formatex(menu[len], charsmax(menu) - len, "\r3.\w %L^n", id, "MENU_ADMIN9")
4375 else
4376 len += formatex(menu[len], charsmax(menu) - len, "\d3. %L^n", id, "MENU_ADMIN9")
4377
4378 // 4. Survivor command
4379 if (userflags & (g_access_flag[ACCESS_MODE_SURVIVOR] | g_access_flag[ACCESS_MAKE_SURVIVOR]))
4380 len += formatex(menu[len], charsmax(menu) - len, "\r4.\w %L^n", id, "MENU_ADMIN3")
4381 else
4382 len += formatex(menu[len], charsmax(menu) - len, "\d4. %L^n", id, "MENU_ADMIN3")
4383
4384 // 5. Sniper command
4385 if (userflags & (g_access_flag[ACCESS_MODE_SNIPER] | g_access_flag[ACCESS_MAKE_SNIPER]))
4386 len += formatex(menu[len], charsmax(menu) - len, "\r5.\w %L^n", id, "MENU_ADMIN8")
4387 else
4388 len += formatex(menu[len], charsmax(menu) - len, "\d5. %L^n", id, "MENU_ADMIN8")
4389
4390 // 6. Respawn command
4391 if (userflags & g_access_flag[ACCESS_RESPAWN_PLAYERS])
4392 len += formatex(menu[len], charsmax(menu) - len, "\r6.\w %L^n", id, "MENU_ADMIN4")
4393 else
4394 len += formatex(menu[len], charsmax(menu) - len, "\d6. %L^n", id, "MENU_ADMIN4")
4395
4396 // 7. Admin modes command
4397 if (userflags & g_access_flag[ACCESS_ADMIN_MODES_MENU])
4398 len += formatex(menu[len], charsmax(menu) - len, "\r7.\w %L^n", id, "MENU_ADMIN10")
4399 else
4400 len += formatex(menu[len], charsmax(menu) - len, "\d7. %L^n", id, "MENU_ADMIN10")
4401
4402 // 0. Exit
4403 len += formatex(menu[len], charsmax(menu) - len, "^n\r0.\w %L", id, "MENU_EXIT")
4404
4405 // Fix for AMXX custom menus
4406 if (pev_valid(id) == PDATA_SAFE)
4407 set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
4408
4409 show_menu(id, KEYSMENU, menu, -1, "Admin Menu")
4410}
4411
4412// Admin Modes Menu
4413show_menu_modes_admin(id)
4414{
4415 static menu[250], len, userflags
4416 len = 0
4417 userflags = get_user_flags(id)
4418
4419 // Title
4420 len += formatex(menu[len], charsmax(menu) - len, "\y%L^n^n", id, "MENU_ADMIN_MODES_TITLE")
4421
4422 // 1. Swarm mode command
4423 if ((userflags & g_access_flag[ACCESS_MODE_SWARM]) && allowed_swarm())
4424 len += formatex(menu[len], charsmax(menu) - len, "\r1.\w %L^n", id, "MENU_ADMIN5")
4425 else
4426 len += formatex(menu[len], charsmax(menu) - len, "\d1. %L^n", id, "MENU_ADMIN5")
4427
4428 // 2. Multi infection command
4429 if ((userflags & g_access_flag[ACCESS_MODE_MULTI]) && allowed_multi())
4430 len += formatex(menu[len], charsmax(menu) - len, "\r2.\w %L^n", id, "MENU_ADMIN6")
4431 else
4432 len += formatex(menu[len], charsmax(menu) - len, "\d2. %L^n", id, "MENU_ADMIN6")
4433
4434 // 3. Plague mode command
4435 if ((userflags & g_access_flag[ACCESS_MODE_PLAGUE]) && allowed_plague())
4436 len += formatex(menu[len], charsmax(menu) - len, "\r3.\w %L^n", id, "MENU_ADMIN7")
4437 else
4438 len += formatex(menu[len], charsmax(menu) - len, "\d3. %L^n", id, "MENU_ADMIN7")
4439
4440 // 4. Armageddon mode command
4441 if ((userflags & g_access_flag[ACCESS_MODE_ARMAGEDDON]) && allowed_armageddon())
4442 len += formatex(menu[len], charsmax(menu) - len, "\r4.\w %L^n", id, "MENU_ADMIN11")
4443 else
4444 len += formatex(menu[len], charsmax(menu) - len, "\d4. %L^n", id, "MENU_ADMIN11")
4445
4446 // 5. Apocalypse mode command
4447 if ((userflags & g_access_flag[ACCESS_MODE_APOCALYPSE]) && allowed_apocalypse())
4448 len += formatex(menu[len], charsmax(menu) - len, "\r5.\w %L^n", id, "MENU_ADMIN12")
4449 else
4450 len += formatex(menu[len], charsmax(menu) - len, "\d5. %L^n", id, "MENU_ADMIN12")
4451
4452 // 6. Nightmare mode command
4453 if ((userflags & g_access_flag[ACCESS_MODE_NIGHTMARE]) && allowed_nightmare())
4454 len += formatex(menu[len], charsmax(menu) - len, "\r6.\w %L^n", id, "MENU_ADMIN13")
4455 else
4456 len += formatex(menu[len], charsmax(menu) - len, "\d6. %L^n", id, "MENU_ADMIN13")
4457
4458 // 0. Exit
4459 len += formatex(menu[len], charsmax(menu) - len, "^n\r0. \wExit")
4460
4461 show_menu(id, KEYSMENU, menu, -1, "Admin Modes Menu")
4462}
4463
4464// Player List Menu
4465show_menu_player_list(id)
4466{
4467 // Player disconnected?
4468 if (!g_isconnected[id])
4469 return;
4470
4471 static menuid, menu[128], player, userflags, buffer[2]
4472 userflags = get_user_flags(id)
4473
4474 // Title
4475 switch (PL_ACTION)
4476 {
4477 case ACTION_ZOMBIEFY_HUMANIZE: formatex(menu, charsmax(menu), "%L\r", id, "MENU_ADMIN1")
4478 case ACTION_MAKE_NEMESIS: formatex(menu, charsmax(menu), "%L\r", id, "MENU_ADMIN2")
4479 case ACTION_MAKE_ASSASSIN: formatex(menu, charsmax(menu), "%L\r", id, "MENU_ADMIN9")
4480 case ACTION_MAKE_SURVIVOR: formatex(menu, charsmax(menu), "%L\r", id, "MENU_ADMIN3")
4481 case ACTION_MAKE_SNIPER: formatex(menu, charsmax(menu), "%L\r", id, "MENU_ADMIN8")
4482 case ACTION_RESPAWN_PLAYER: formatex(menu, charsmax(menu), "%L\r", id, "MENU_ADMIN4")
4483 }
4484 menuid = menu_create(menu, "menu_player_list")
4485
4486 // Player List
4487 for (player = 0; player <= g_maxplayers; player++)
4488 {
4489 // Skip if not connected
4490 if (!g_isconnected[player])
4491 continue;
4492
4493 // Format text depending on the action to take
4494 switch (PL_ACTION)
4495 {
4496 case ACTION_ZOMBIEFY_HUMANIZE: // Zombiefy/Humanize command
4497 {
4498 if (g_zombie[player])
4499 {
4500 if (allowed_human(player) && (userflags & g_access_flag[ACCESS_MAKE_HUMAN]))
4501 formatex(menu, charsmax(menu), "%s \r[%L]", g_playername[player], id, g_nemesis[player] ? "CLASS_NEMESIS" : "CLASS_ZOMBIE")
4502 else
4503 formatex(menu, charsmax(menu), "\d%s [%L]", g_playername[player], id, g_nemesis[player] ? "CLASS_NEMESIS" : "CLASS_ZOMBIE")
4504 }
4505 else
4506 {
4507 if (allowed_zombie(player) && (g_newround ? (userflags & g_access_flag[ACCESS_MODE_INFECTION]) : (userflags & g_access_flag[ACCESS_MAKE_ZOMBIE])))
4508 formatex(menu, charsmax(menu), "%s \y[%L]", g_playername[player], id, g_survivor[player] ? "CLASS_SURVIVOR" : "CLASS_HUMAN")
4509 else
4510 formatex(menu, charsmax(menu), "\d%s [%L]", g_playername[player], id, g_survivor[player] ? "CLASS_SURVIVOR" : "CLASS_HUMAN")
4511 }
4512 }
4513 case ACTION_MAKE_NEMESIS: // Nemesis command
4514 {
4515 if (allowed_nemesis(player) && (g_newround ? (userflags & g_access_flag[ACCESS_MODE_NEMESIS]) : (userflags & g_access_flag[ACCESS_MAKE_NEMESIS])))
4516 {
4517 if (g_zombie[player])
4518 formatex(menu, charsmax(menu), "%s \r[%L]", g_playername[player], id, g_nemesis[player] ? "CLASS_NEMESIS" : "CLASS_ZOMBIE")
4519 else
4520 formatex(menu, charsmax(menu), "%s \y[%L]", g_playername[player], id, g_survivor[player] ? "CLASS_SURVIVOR" : "CLASS_HUMAN")
4521 }
4522 else
4523 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")
4524 }
4525 case ACTION_MAKE_ASSASSIN: // Assassin command
4526 {
4527 if (allowed_assassin(player) && (g_newround ? (userflags & g_access_flag[ACCESS_MODE_ASSASSIN]) : (userflags & g_access_flag[ACCESS_MAKE_ASSASSIN])))
4528 {
4529 if (g_zombie[player])
4530 formatex(menu, charsmax(menu), "%s \r[%L]", g_playername[player], id, g_nemesis[player] ? "CLASS_NEMESIS" : g_assassin[player] ? "CLASS_ASSASSIN" : "CLASS_ZOMBIE")
4531 else
4532 formatex(menu, charsmax(menu), "%s \y[%L]", g_playername[player], id, g_survivor[player] ? "CLASS_SURVIVOR" : g_sniper[player] ? "CLASS_SNIPER" : "CLASS_HUMAN")
4533 }
4534 else
4535 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")
4536 }
4537 case ACTION_MAKE_SURVIVOR: // Survivor command
4538 {
4539 if (allowed_survivor(player) && (g_newround ? (userflags & g_access_flag[ACCESS_MODE_SURVIVOR]) : (userflags & g_access_flag[ACCESS_MAKE_SURVIVOR])))
4540 {
4541 if (g_zombie[player])
4542 formatex(menu, charsmax(menu), "%s \r[%L]", g_playername[player], id, g_nemesis[player] ? "CLASS_NEMESIS" : "CLASS_ZOMBIE")
4543 else
4544 formatex(menu, charsmax(menu), "%s \y[%L]", g_playername[player], id, g_survivor[player] ? "CLASS_SURVIVOR" : "CLASS_HUMAN")
4545 }
4546 else
4547 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")
4548 }
4549 case ACTION_MAKE_SNIPER: // Sniper command
4550 {
4551 if (allowed_sniper(player) && (g_newround ? (userflags & g_access_flag[ACCESS_MODE_SNIPER]) : (userflags & g_access_flag[ACCESS_MAKE_SNIPER])))
4552 {
4553 if (g_zombie[player])
4554 formatex(menu, charsmax(menu), "%s \r[%L]", g_playername[player], id, g_nemesis[player] ? "CLASS_NEMESIS" : g_assassin[player] ? "CLASS_ASSASSIN" : "CLASS_ZOMBIE")
4555 else
4556 formatex(menu, charsmax(menu), "%s \y[%L]", g_playername[player], id, g_survivor[player] ? "CLASS_SURVIVOR" : g_sniper[player] ? "CLASS_SNIPER" : "CLASS_HUMAN")
4557 }
4558 else
4559 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")
4560 }
4561 case ACTION_RESPAWN_PLAYER: // Respawn command
4562 {
4563 if (allowed_respawn(player) && (userflags & g_access_flag[ACCESS_RESPAWN_PLAYERS]))
4564 formatex(menu, charsmax(menu), "%s", g_playername[player])
4565 else
4566 formatex(menu, charsmax(menu), "\d%s", g_playername[player])
4567 }
4568 }
4569
4570 // Add player
4571 buffer[0] = player
4572 buffer[1] = 0
4573 menu_additem(menuid, menu, buffer)
4574 }
4575
4576 // Back - Next - Exit
4577 formatex(menu, charsmax(menu), "%L", id, "MENU_BACK")
4578 menu_setprop(menuid, MPROP_BACKNAME, menu)
4579 formatex(menu, charsmax(menu), "%L", id, "MENU_NEXT")
4580 menu_setprop(menuid, MPROP_NEXTNAME, menu)
4581 formatex(menu, charsmax(menu), "%L", id, "MENU_EXIT")
4582 menu_setprop(menuid, MPROP_EXITNAME, menu)
4583
4584 // If remembered page is greater than number of pages, clamp down the value
4585 MENU_PAGE_PLAYERS = min(MENU_PAGE_PLAYERS, menu_pages(menuid)-1)
4586
4587 // Fix for AMXX custom menus
4588 if (pev_valid(id) == PDATA_SAFE)
4589 set_pdata_int(id, OFFSET_CSMENUCODE, 0, OFFSET_LINUX)
4590
4591 menu_display(id, menuid, MENU_PAGE_PLAYERS)
4592}
4593
4594/*================================================================================
4595 [Menu Handlers]
4596=================================================================================*/
4597
4598// Game Menu
4599public menu_game(id, key)
4600{
4601 // Player disconnected?
4602 if (!g_isconnected[id])
4603 return PLUGIN_HANDLED;
4604
4605 switch (key)
4606 {
4607 case 0: // Buy Weapons
4608 {
4609 // Custom buy menus enabled?
4610 if (get_pcvar_num(cvar_buycustom))
4611 {
4612 // Disable the remember selection setting
4613 WPN_AUTO_ON = 0
4614 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "BUY_ENABLED")
4615
4616 // Show menu if player hasn't yet bought anything
4617 if (g_canbuy[id]) show_menu_buy1(id)
4618 }
4619 else
4620 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
4621 }
4622 case 1: // Extra Items
4623 {
4624 // Extra items enabled?
4625 if (get_pcvar_num(cvar_extraitems))
4626 {
4627 // Check whether the player is able to buy anything
4628 if (g_isalive[id])
4629 show_menu_extras(id)
4630 else
4631 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
4632 }
4633 else
4634 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_EXTRAS")
4635 }
4636 case 2: // Zombie Classes
4637 {
4638 // Zombie classes enabled?
4639 if (get_pcvar_num(cvar_zclasses))
4640 show_menu_zclass(id)
4641 else
4642 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ZCLASSES")
4643 }
4644 case 3: // Unstuck
4645 {
4646 // Check if player is stuck
4647 if (g_isalive[id])
4648 {
4649 if (is_player_stuck(id))
4650 {
4651 // Move to an initial spawn
4652 if (get_pcvar_num(cvar_randspawn))
4653 do_random_spawn(id) // random spawn (including CSDM)
4654 else
4655 do_random_spawn(id, 1) // regular spawn
4656 }
4657 else
4658 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_STUCK")
4659 }
4660 else
4661 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
4662 }
4663 case 4: // Help Menu
4664 {
4665 show_menu_info(id)
4666 }
4667 case 5: // Join Spectator
4668 {
4669 // Player alive?
4670 if (g_isalive[id])
4671 {
4672 // Prevent abuse by non-admins if block suicide setting is enabled
4673 if (get_pcvar_num(cvar_blocksuicide) && !(get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MENU]))
4674 {
4675 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
4676 return PLUGIN_HANDLED;
4677 }
4678
4679 // Check that we still have both humans and zombies to keep the round going
4680 check_round(id)
4681
4682 // Kill him before he switches team
4683 dllfunc(DLLFunc_ClientKill, id)
4684 }
4685
4686 // Temporarily save player stats?
4687 if (get_pcvar_num(cvar_statssave)) save_stats(id)
4688
4689 // Remove previous tasks
4690 remove_task(id+TASK_TEAM)
4691 remove_task(id+TASK_MODEL)
4692 remove_task(id+TASK_FLASH)
4693 remove_task(id+TASK_CHARGE)
4694 remove_task(id+TASK_SPAWN)
4695 remove_task(id+TASK_BLOOD)
4696 remove_task(id+TASK_AURA)
4697 remove_task(id+TASK_BURN)
4698
4699 // Then move him to the spectator team
4700 fm_cs_set_user_team(id, FM_CS_TEAM_SPECTATOR)
4701 fm_user_team_update(id)
4702 }
4703 case 8: // Admin Menu
4704 {
4705 // Check if player has the required access
4706 if (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MENU])
4707 show_menu_admin(id)
4708 else
4709 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
4710 }
4711 }
4712
4713 return PLUGIN_HANDLED;
4714}
4715
4716// Buy Menu 1
4717public menu_buy1(id, key)
4718{
4719 // Player dead?
4720 if (!g_isalive[id])
4721 return PLUGIN_HANDLED;
4722
4723 // Zombies or survivors get no guns
4724 if (g_zombie[id] || g_survivor[id] || g_sniper[id])
4725 return PLUGIN_HANDLED;
4726
4727 // Special keys / weapon list exceeded
4728 if (key >= MENU_KEY_AUTOSELECT || WPN_SELECTION >= WPN_MAXIDS)
4729 {
4730 switch (key)
4731 {
4732 case MENU_KEY_AUTOSELECT: // toggle auto select
4733 {
4734 WPN_AUTO_ON = 1 - WPN_AUTO_ON
4735 }
4736 case MENU_KEY_NEXT: // next/back
4737 {
4738 if (WPN_STARTID+7 < WPN_MAXIDS)
4739 WPN_STARTID += 7
4740 else
4741 WPN_STARTID = 0
4742 }
4743 case MENU_KEY_EXIT: // exit
4744 {
4745 return PLUGIN_HANDLED;
4746 }
4747 }
4748
4749 // Show buy menu again
4750 show_menu_buy1(id)
4751 return PLUGIN_HANDLED;
4752 }
4753
4754 // Store selected weapon id
4755 WPN_AUTO_PRI = WPN_SELECTION
4756
4757 // Buy primary weapon
4758 buy_primary_weapon(id, WPN_AUTO_PRI)
4759
4760 // Show pistols menu
4761 show_menu_buy2(id)
4762
4763 return PLUGIN_HANDLED;
4764}
4765
4766// Buy Primary Weapon
4767buy_primary_weapon(id, selection)
4768{
4769 // Drop previous weapons
4770 drop_weapons(id, 1)
4771 drop_weapons(id, 2)
4772
4773 // Strip off from weapons
4774 fm_strip_user_weapons(id)
4775 fm_give_item(id, "weapon_knife")
4776
4777 // Get weapon's id and name
4778 static weaponid, wname[32]
4779 weaponid = ArrayGetCell(g_primary_weaponids, selection)
4780 ArrayGetString(g_primary_items, selection, wname, charsmax(wname))
4781
4782 // Give the new weapon and full ammo
4783 fm_give_item(id, wname)
4784 ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[weaponid], AMMOTYPE[weaponid], MAXBPAMMO[weaponid])
4785
4786 // Weapons bought
4787 g_canbuy[id] = false
4788
4789 // Give additional items
4790 static i
4791 for (i = 0; i < ArraySize(g_additional_items); i++)
4792 {
4793 ArrayGetString(g_additional_items, i, wname, charsmax(wname))
4794 fm_give_item(id, wname)
4795 }
4796}
4797
4798// Buy Menu 2
4799public menu_buy2(id, key)
4800{
4801 // Player dead?
4802 if (!g_isalive[id])
4803 return PLUGIN_HANDLED;
4804
4805 // Zombies or survivors get no guns
4806 if (g_zombie[id] || g_survivor[id] || g_sniper[id])
4807 return PLUGIN_HANDLED;
4808
4809 // Special keys / weapon list exceeded
4810 if (key >= ArraySize(g_secondary_items))
4811 {
4812 // Toggle autoselect
4813 if (key == MENU_KEY_AUTOSELECT)
4814 WPN_AUTO_ON = 1 - WPN_AUTO_ON
4815
4816 // Reshow menu unless user exited
4817 if (key != MENU_KEY_EXIT)
4818 show_menu_buy2(id)
4819
4820 return PLUGIN_HANDLED;
4821 }
4822
4823 // Store selected weapon
4824 WPN_AUTO_SEC = key
4825
4826 // Drop secondary gun again, in case we picked another (bugfix)
4827 drop_weapons(id, 2)
4828
4829 // Get weapon's id
4830 static weaponid, wname[32]
4831 weaponid = ArrayGetCell(g_secondary_weaponids, key)
4832 ArrayGetString(g_secondary_items, key, wname, charsmax(wname))
4833
4834 // Give the new weapon and full ammo
4835 fm_give_item(id, wname)
4836 ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[weaponid], AMMOTYPE[weaponid], MAXBPAMMO[weaponid])
4837
4838 return PLUGIN_HANDLED;
4839}
4840
4841// Extra Items Menu
4842public menu_extras(id, menuid, item)
4843{
4844 // Player disconnected?
4845 if (!is_user_connected(id))
4846 {
4847 menu_destroy(menuid)
4848 return PLUGIN_HANDLED;
4849 }
4850
4851 // Remember player's menu page
4852 static menudummy
4853 player_menu_info(id, menudummy, menudummy, MENU_PAGE_EXTRAS)
4854
4855 // Menu was closed
4856 if (item == MENU_EXIT)
4857 {
4858 menu_destroy(menuid)
4859 return PLUGIN_HANDLED;
4860 }
4861
4862 // Dead players are not allowed to buy items
4863 if (!g_isalive[id])
4864 {
4865 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
4866 menu_destroy(menuid)
4867 return PLUGIN_HANDLED;
4868 }
4869
4870 // Retrieve extra item id
4871 static buffer[2], dummy, itemid
4872 menu_item_getinfo(menuid, item, dummy, buffer, charsmax(buffer), _, _, dummy)
4873 itemid = buffer[0]
4874
4875 // Attempt to buy the item
4876 buy_extra_item(id, itemid)
4877 menu_destroy(menuid)
4878 return PLUGIN_HANDLED;
4879}
4880
4881// Buy Extra Item
4882buy_extra_item(id, itemid, ignorecost = 0)
4883{
4884 // Retrieve item's team
4885 static team
4886 team = ArrayGetCell(g_extraitem_team, itemid)
4887
4888 // Check for team/class specific items
4889 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)))
4890 {
4891 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
4892 return;
4893 }
4894
4895 // Check for unavailable items
4896 if ((itemid == EXTRA_NVISION && !get_pcvar_num(cvar_extranvision))
4897 || (itemid == EXTRA_ANTIDOTE && (!get_pcvar_num(cvar_extraantidote) || g_antidotecounter >= get_pcvar_num(cvar_antidotelimit)))
4898 || (itemid == EXTRA_MADNESS && (!get_pcvar_num(cvar_extramadness) || g_madnesscounter >= get_pcvar_num(cvar_madnesslimit)))
4899 || (itemid == EXTRA_INFBOMB && (!get_pcvar_num(cvar_extrainfbomb) || g_infbombcounter >= get_pcvar_num(cvar_infbomblimit)))
4900 || (itemid >= EXTRA_WEAPONS_STARTID && itemid <= EXTRAS_CUSTOM_STARTID-1 && !get_pcvar_num(cvar_extraweapons)))
4901 {
4902 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
4903 return;
4904 }
4905
4906 // Check for hard coded items with special conditions
4907 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)))
4908 || (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)))
4909 {
4910 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_CANTUSE")
4911 return;
4912 }
4913
4914 // Ignore item's cost?
4915 if (!ignorecost)
4916 {
4917 // Check that we have enough ammo packs
4918 if (g_ammopacks[id] < ArrayGetCell(g_extraitem_cost, itemid))
4919 {
4920 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "NOT_ENOUGH_AMMO")
4921 return;
4922 }
4923
4924 // Deduce item cost
4925 g_ammopacks[id] -= ArrayGetCell(g_extraitem_cost, itemid)
4926 }
4927
4928 // Check which kind of item we're buying
4929 switch (itemid)
4930 {
4931 case EXTRA_NVISION: // Night Vision
4932 {
4933 g_nvision[id] = true
4934
4935 if (!g_isbot[id])
4936 {
4937 g_nvisionenabled[id] = true
4938
4939 // Custom nvg?
4940 if (get_pcvar_num(cvar_customnvg))
4941 {
4942 remove_task(id+TASK_NVISION)
4943 set_task(0.1, "set_user_nvision", id+TASK_NVISION, _, _, "b")
4944 }
4945 else
4946 set_user_gnvision(id, 1)
4947 }
4948 else
4949 cs_set_user_nvg(id, 1)
4950 }
4951 case EXTRA_ANTIDOTE: // Antidote
4952 {
4953 // Increase antidote purchase count for this round
4954 g_antidotecounter++
4955
4956 humanme(id, 0, 0, 0)
4957 }
4958 case EXTRA_MADNESS: // Zombie Madness
4959 {
4960 // Increase madness purchase count for this round
4961 g_madnesscounter++
4962
4963 g_nodamage[id] = true
4964 set_task(0.1, "zombie_aura", id+TASK_AURA, _, _, "b")
4965 set_task(get_pcvar_float(cvar_madnessduration), "madness_over", id+TASK_BLOOD)
4966
4967 static sound[64]
4968 ArrayGetString(zombie_madness, random_num(0, ArraySize(zombie_madness) - 1), sound, charsmax(sound))
4969 emit_sound(id, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
4970 }
4971 case EXTRA_INFBOMB: // Infection Bomb
4972 {
4973 // Increase infection bomb purchase count for this round
4974 g_infbombcounter++
4975
4976 // Already own one
4977 if (user_has_weapon(id, CSW_HEGRENADE))
4978 {
4979 // Increase BP ammo on it instead
4980 cs_set_user_bpammo(id, CSW_HEGRENADE, cs_get_user_bpammo(id, CSW_HEGRENADE) + 1)
4981
4982 // Flash ammo in hud
4983 message_begin(MSG_ONE_UNRELIABLE, g_msgAmmoPickup, _, id)
4984 write_byte(AMMOID[CSW_HEGRENADE]) // ammo id
4985 write_byte(1) // ammo amount
4986 message_end()
4987
4988 // Play clip purchase sound
4989 emit_sound(id, CHAN_ITEM, sound_buyammo, 1.0, ATTN_NORM, 0, PITCH_NORM)
4990
4991 return; // stop here
4992 }
4993
4994 // Give weapon to the player
4995 fm_give_item(id, "weapon_hegrenade")
4996 }
4997 default:
4998 {
4999 if (itemid >= EXTRA_WEAPONS_STARTID && itemid <= EXTRAS_CUSTOM_STARTID-1) // Weapons
5000 {
5001 // Get weapon's id and name
5002 static weaponid, wname[32]
5003 ArrayGetString(g_extraweapon_items, itemid - EXTRA_WEAPONS_STARTID, wname, charsmax(wname))
5004 weaponid = cs_weapon_name_to_id(wname)
5005
5006 // If we are giving a primary/secondary weapon
5007 if (MAXBPAMMO[weaponid] > 2)
5008 {
5009 // Make user drop the previous one
5010 if ((1<<weaponid) & PRIMARY_WEAPONS_BIT_SUM)
5011 drop_weapons(id, 1)
5012 else
5013 drop_weapons(id, 2)
5014
5015 // Give full BP ammo for the new one
5016 ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[weaponid], AMMOTYPE[weaponid], MAXBPAMMO[weaponid])
5017 }
5018 // If we are giving a grenade which the user already owns
5019 else if (user_has_weapon(id, weaponid))
5020 {
5021 // Increase BP ammo on it instead
5022 cs_set_user_bpammo(id, weaponid, cs_get_user_bpammo(id, weaponid) + 1)
5023
5024 // Flash ammo in hud
5025 message_begin(MSG_ONE_UNRELIABLE, g_msgAmmoPickup, _, id)
5026 write_byte(AMMOID[weaponid]) // ammo id
5027 write_byte(1) // ammo amount
5028 message_end()
5029
5030 // Play clip purchase sound
5031 emit_sound(id, CHAN_ITEM, sound_buyammo, 1.0, ATTN_NORM, 0, PITCH_NORM)
5032
5033 return; // stop here
5034 }
5035
5036 // Give weapon to the player
5037 fm_give_item(id, wname)
5038 }
5039 else // Custom additions
5040 {
5041 // Item selected forward
5042 ExecuteForward(g_fwExtraItemSelected, g_fwDummyResult, id, itemid);
5043
5044 // Item purchase blocked, restore buyer's ammo packs
5045 if (g_fwDummyResult >= ZP_PLUGIN_HANDLED && !ignorecost)
5046 g_ammopacks[id] += ArrayGetCell(g_extraitem_cost, itemid)
5047 }
5048 }
5049 }
5050}
5051
5052// Zombie Class Menu
5053public menu_zclass(id, menuid, item)
5054{
5055 // Player disconnected?
5056 if (!is_user_connected(id))
5057 {
5058 menu_destroy(menuid)
5059 return PLUGIN_HANDLED;
5060 }
5061
5062 // Remember player's menu page
5063 static menudummy
5064 player_menu_info(id, menudummy, menudummy, MENU_PAGE_ZCLASS)
5065
5066 // Menu was closed
5067 if (item == MENU_EXIT)
5068 {
5069 menu_destroy(menuid)
5070 return PLUGIN_HANDLED;
5071 }
5072
5073 // Retrieve zombie class id
5074 static buffer[2], dummy, classid
5075 menu_item_getinfo(menuid, item, dummy, buffer, charsmax(buffer), _, _, dummy)
5076 classid = buffer[0]
5077
5078 // Store selection for the next infection
5079 g_zombieclassnext[id] = classid
5080
5081 static name[32]
5082 ArrayGetString(g_zclass_name, g_zombieclassnext[id], name, charsmax(name))
5083
5084 // Show selected zombie class info and stats
5085 zp_colored_print(id, "^x04[ZP]^x01 %L^x01:^x04 %s", id, "ZOMBIE_SELECT", name)
5086 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]),
5087 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))
5088
5089 menu_destroy(menuid)
5090 return PLUGIN_HANDLED;
5091}
5092
5093// Info Menu
5094public menu_info(id, key)
5095{
5096 // Player disconnected?
5097 if (!g_isconnected[id])
5098 return PLUGIN_HANDLED;
5099
5100 static motd[1500], len
5101 len = 0
5102
5103 switch (key)
5104 {
5105 case 0: // General
5106 {
5107 static weather, lighting[2]
5108 weather = 0
5109 get_pcvar_string(cvar_lighting, lighting, charsmax(lighting))
5110 strtolower(lighting)
5111
5112 len += formatex(motd[len], charsmax(motd) - len, "%L ", id, "MOTD_INFO11", "Zombie Plague", PLUGIN_VERSION, "MeRcyLeZZ and Bakir")
5113 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO12")
5114 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_A")
5115
5116 if (g_ambience_fog)
5117 {
5118 len += formatex(motd[len], charsmax(motd) - len, (weather < 1) ? " %L" : ". %L", id, "MOTD_FOG")
5119 weather++
5120 }
5121 if (g_ambience_rain)
5122 {
5123 len += formatex(motd[len], charsmax(motd) - len, (weather < 1) ? " %L" : ". %L", id, "MOTD_RAIN")
5124 weather++
5125 }
5126 if (g_ambience_snow)
5127 {
5128 len += formatex(motd[len], charsmax(motd) - len, (weather < 1) ? " %L" : ". %L", id, "MOTD_SNOW")
5129 weather++
5130 }
5131 if (weather < 1) len += formatex(motd[len], charsmax(motd) - len, " %L", id, "MOTD_DISABLED")
5132
5133 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_B", lighting)
5134 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_C", id, get_pcvar_num(cvar_triggered) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5135 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)))
5136 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")
5137 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")
5138 if (get_pcvar_num(cvar_deathmatch)) len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_G", floatround(get_pcvar_float(cvar_spawnprotection)))
5139 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_H", id, get_pcvar_num(cvar_randspawn) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5140 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_I", id, get_pcvar_num(cvar_extraitems) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5141 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_J", id, get_pcvar_num(cvar_zclasses) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5142 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_K", id, get_pcvar_num(cvar_customnvg) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5143 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO1_L", id, g_cached_customflash ? "MOTD_ENABLED" : "MOTD_DISABLED")
5144
5145 show_motd(id, motd)
5146 }
5147 case 1: // Humans
5148 {
5149 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2")
5150 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_A", get_pcvar_num(cvar_humanhp))
5151 if (get_pcvar_num(cvar_humanlasthp) > 0) len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_B", get_pcvar_num(cvar_humanlasthp))
5152 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_C", get_pcvar_num(cvar_humanspd))
5153 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_D", floatround(get_pcvar_float(cvar_humangravity) * 800.0))
5154 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")
5155 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_F", get_pcvar_num(cvar_ammodamage_human))
5156 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_G", id, get_pcvar_num(cvar_firegrenades) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5157 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_H", id, get_pcvar_num(cvar_frostgrenades) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5158 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_I", id, get_pcvar_num(cvar_flaregrenades) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5159 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO2_J", id, get_pcvar_num(cvar_knockback) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5160
5161 show_motd(id, motd)
5162 }
5163 case 2: // Zombies
5164 {
5165 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3")
5166 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_A", ArrayGetCell(g_zclass_hp, 0))
5167 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_B", floatround(float(ArrayGetCell(g_zclass_hp, 0)) * get_pcvar_float(cvar_zombiefirsthp)))
5168 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_C", floatround(get_pcvar_float(cvar_zombiearmor) * 100.0))
5169 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_D", ArrayGetCell(g_zclass_spd, 0))
5170 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_E", floatround(Float:ArrayGetCell(g_zclass_grav, 0) * 800.0))
5171 if (get_pcvar_num(cvar_zombiebonushp)) len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_F", get_pcvar_num(cvar_zombiebonushp))
5172 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")
5173 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_H", id, get_pcvar_num(cvar_zombiebleeding) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5174 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO3_I", get_pcvar_num(cvar_ammoinfect))
5175
5176 show_motd(id, motd)
5177 }
5178 case 3: // Gameplay Modes
5179 {
5180 static nemhp[5], survhp[5], snihp[5], assahp[5]
5181
5182 // Get nemesis and survivor health
5183 num_to_str(get_pcvar_num(cvar_nemhp), nemhp, charsmax(nemhp))
5184 num_to_str(get_pcvar_num(cvar_survhp), survhp, charsmax(survhp))
5185 num_to_str(get_pcvar_num(cvar_snihp), snihp, charsmax(snihp))
5186 num_to_str(get_pcvar_num(cvar_assahp), assahp, charsmax(assahp))
5187
5188 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4")
5189
5190 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_A", id, get_pcvar_num(cvar_nem) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5191 if (get_pcvar_num(cvar_nem))
5192 {
5193 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_B", get_pcvar_num(cvar_nemchance))
5194 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_C", get_pcvar_num(cvar_nemhp) > 0 ? nemhp : "[Auto]")
5195 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_D", get_pcvar_num(cvar_nemspd))
5196 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_E", floatround(get_pcvar_float(cvar_nemgravity) * 800.0))
5197 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_F", id, g_cached_leapnemesis ? "MOTD_ENABLED" : "MOTD_DISABLED")
5198 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_G", id, get_pcvar_num(cvar_nempainfree) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5199 }
5200 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_H", id, get_pcvar_num(cvar_surv) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5201 if (get_pcvar_num(cvar_surv))
5202 {
5203 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_I", get_pcvar_num(cvar_survchance))
5204 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_J", get_pcvar_num(cvar_survhp) > 0 ? survhp : "[Auto]")
5205 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_K", get_pcvar_num(cvar_survspd))
5206 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_L", floatround(get_pcvar_float(cvar_survgravity) * 800.0))
5207 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_M", id, g_cached_leapsurvivor ? "MOTD_ENABLED" : "MOTD_DISABLED")
5208 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_N", id, get_pcvar_num(cvar_survpainfree) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5209 }
5210
5211 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_O", id, get_pcvar_num(cvar_swarm) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5212 if (get_pcvar_num(cvar_swarm)) len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_P", get_pcvar_num(cvar_swarmchance))
5213
5214 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_Q", id, get_pcvar_num(cvar_multi) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5215 if (get_pcvar_num(cvar_multi))
5216 {
5217 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_R", get_pcvar_num(cvar_multichance))
5218 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_S", floatround(get_pcvar_float(cvar_multiratio) * 100.0))
5219 }
5220
5221 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_T", id, get_pcvar_num(cvar_plague) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5222 if (get_pcvar_num(cvar_plague))
5223 {
5224 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_U", get_pcvar_num(cvar_plaguechance))
5225 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO4_V", floatround(get_pcvar_float(cvar_plagueratio) * 100.0))
5226 }
5227
5228 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO5_A", id, get_pcvar_num(cvar_sni) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5229 if (get_pcvar_num(cvar_sni))
5230 {
5231 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO5_B", get_pcvar_num(cvar_snichance))
5232 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO5_C", get_pcvar_num(cvar_snihp) > 0 ? snihp : "[Auto]")
5233 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO5_E", floatround(get_pcvar_float(cvar_snigravity) * 800.0))
5234 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO5_F", id, g_cached_leapsniper ? "MOTD_ENABLED" : "MOTD_DISABLED")
5235 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO5_G", id, get_pcvar_num(cvar_snipainfree) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5236 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO5_H", floatround(get_pcvar_float(cvar_snidamage)))
5237 }
5238
5239 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_A", id, get_pcvar_num(cvar_assa) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5240 if (get_pcvar_num(cvar_assa))
5241 {
5242 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_B", get_pcvar_num(cvar_assachance))
5243 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_C", get_pcvar_num(cvar_assahp) > 0 ? assahp : "[Auto]")
5244 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_D", get_pcvar_num(cvar_assaspd))
5245 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_E", floatround(get_pcvar_float(cvar_assagravity) * 800.0))
5246 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_F", id, g_cached_leapassassin ? "MOTD_ENABLED" : "MOTD_DISABLED")
5247 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_G", id, get_pcvar_num(cvar_assapainfree) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5248 }
5249
5250 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_H", id, get_pcvar_num(cvar_armage) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5251 if (get_pcvar_num(cvar_armage))
5252 {
5253 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_I", get_pcvar_num(cvar_armagechance))
5254 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO6_J", floatround(get_pcvar_float(cvar_armageratio) * 100.0))
5255 }
5256
5257 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO7_H", id, get_pcvar_num(cvar_apoc) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5258 if (get_pcvar_num(cvar_apoc))
5259 {
5260 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO7_I", get_pcvar_num(cvar_apocchance))
5261 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO7_J", floatround(get_pcvar_float(cvar_apocratio ) * 100.0))
5262 }
5263
5264 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO8_H", id, get_pcvar_num(cvar_night) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5265 if (get_pcvar_num(cvar_night))
5266 {
5267 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO8_I", get_pcvar_num(cvar_nightchance))
5268 len += formatex(motd[len], charsmax(motd) - len, "%L", id, "MOTD_INFO8_J", floatround(get_pcvar_float(cvar_nightratio) * 100.0))
5269 }
5270
5271 show_motd(id, motd)
5272 }
5273 default: return PLUGIN_HANDLED;
5274 }
5275
5276 // Show help menu again if user wishes to read another topic
5277 show_menu_info(id)
5278
5279 return PLUGIN_HANDLED;
5280}
5281
5282// Admin Menu
5283public menu_admin(id, key)
5284{
5285 // Player disconnected?
5286 if (!g_isconnected[id])
5287 return PLUGIN_HANDLED;
5288
5289 static userflags
5290 userflags = get_user_flags(id)
5291
5292 switch (key)
5293 {
5294 case ACTION_ZOMBIEFY_HUMANIZE: // Zombiefy/Humanize command
5295 {
5296 if (userflags & (g_access_flag[ACCESS_MODE_INFECTION] | g_access_flag[ACCESS_MAKE_ZOMBIE] | g_access_flag[ACCESS_MAKE_HUMAN]))
5297 {
5298 // Show player list for admin to pick a target
5299 PL_ACTION = ACTION_ZOMBIEFY_HUMANIZE
5300 show_menu_player_list(id)
5301 }
5302 else
5303 {
5304 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5305 show_menu_admin(id)
5306 }
5307 }
5308 case ACTION_MAKE_NEMESIS: // Nemesis command
5309 {
5310 if (userflags & (g_access_flag[ACCESS_MODE_NEMESIS] | g_access_flag[ACCESS_MAKE_NEMESIS]))
5311 {
5312 // Show player list for admin to pick a target
5313 PL_ACTION = ACTION_MAKE_NEMESIS
5314 show_menu_player_list(id)
5315 }
5316 else
5317 {
5318 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5319 show_menu_admin(id)
5320 }
5321 }
5322 case ACTION_MAKE_ASSASSIN: // Assassin command
5323 {
5324 if (userflags & (g_access_flag[ACCESS_MODE_ASSASSIN] | g_access_flag[ACCESS_MAKE_ASSASSIN]))
5325 {
5326 // Show player list for admin to pick a target
5327 PL_ACTION = ACTION_MAKE_ASSASSIN
5328 show_menu_player_list(id)
5329 }
5330 else
5331 {
5332 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5333 show_menu_admin(id)
5334 }
5335 }
5336 case ACTION_MAKE_SURVIVOR: // Survivor command
5337 {
5338 if (userflags & (g_access_flag[ACCESS_MODE_SURVIVOR] | g_access_flag[ACCESS_MAKE_SURVIVOR]))
5339 {
5340 // Show player list for admin to pick a target
5341 PL_ACTION = ACTION_MAKE_SURVIVOR
5342 show_menu_player_list(id)
5343 }
5344 else
5345 {
5346 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5347 show_menu_admin(id)
5348 }
5349 }
5350 case ACTION_MAKE_SNIPER: // Sniper command
5351 {
5352 if (userflags & (g_access_flag[ACCESS_MODE_SNIPER] | g_access_flag[ACCESS_MAKE_SNIPER]))
5353 {
5354 // Show player list for admin to pick a target
5355 PL_ACTION = ACTION_MAKE_SNIPER
5356 show_menu_player_list(id)
5357 }
5358 else
5359 {
5360 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5361 show_menu_admin(id)
5362 }
5363 }
5364 case ACTION_RESPAWN_PLAYER: // Respawn command
5365 {
5366 if (userflags & g_access_flag[ACCESS_RESPAWN_PLAYERS])
5367 {
5368 // Show player list for admin to pick a target
5369 PL_ACTION = ACTION_RESPAWN_PLAYER
5370 show_menu_player_list(id)
5371 }
5372 else
5373 {
5374 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5375 show_menu_admin(id)
5376 }
5377 }
5378 case ACTION_MODES_MENU: // Admin Modes command
5379 {
5380 if (userflags & g_access_flag[ACCESS_ADMIN_MODES_MENU])
5381 show_menu_modes_admin(id)
5382 else
5383 {
5384 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5385 show_menu_admin(id)
5386 }
5387 }
5388 }
5389
5390 return PLUGIN_HANDLED;
5391}
5392
5393// Admin Modes Menu
5394public menu_modes_admin(id, key)
5395{
5396 static userflags
5397 userflags = get_user_flags(id)
5398
5399 switch (key)
5400 {
5401 case ACTION_MODE_SWARM: // Swarm Mode command
5402 {
5403 if (userflags & g_access_flag[ACCESS_MODE_SWARM])
5404 {
5405 if (allowed_swarm())
5406 command_swarm(id)
5407 else
5408 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5409 }
5410 else
5411 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5412
5413 show_menu_modes_admin(id)
5414 }
5415 case ACTION_MODE_MULTI: // Multiple Infection command
5416 {
5417 if (userflags & g_access_flag[ACCESS_MODE_MULTI])
5418 {
5419 if (allowed_multi())
5420 command_multi(id)
5421 else
5422 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5423 }
5424 else
5425 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5426
5427 show_menu_modes_admin(id)
5428 }
5429 case ACTION_MODE_PLAGUE: // Plague Mode command
5430 {
5431 if (userflags & g_access_flag[ACCESS_MODE_PLAGUE])
5432 {
5433 if (allowed_plague())
5434 command_plague(id)
5435 else
5436 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5437 }
5438 else
5439 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5440
5441 show_menu_modes_admin(id)
5442 }
5443 case ACTION_MODE_ARMAGEDDON: // Armageddon Mode command
5444 {
5445 if (userflags & g_access_flag[ACCESS_MODE_ARMAGEDDON])
5446 {
5447 if (allowed_armageddon())
5448 command_armageddon(id)
5449 else
5450 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5451 }
5452 else
5453 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5454
5455 show_menu_modes_admin(id)
5456 }
5457 case ACTION_MODE_APOCALYPSE: // Apocalypse Mode command
5458 {
5459 if (userflags & g_access_flag[ACCESS_MODE_APOCALYPSE])
5460 {
5461 if (allowed_apocalypse())
5462 command_apocalypse(id)
5463 else
5464 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5465 }
5466 else
5467 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5468
5469 show_menu_modes_admin(id)
5470 }
5471 case ACTION_MODE_NIGHTMARE: // Nightmare Mode command
5472 {
5473 if (userflags & g_access_flag[ACCESS_MODE_NIGHTMARE])
5474 {
5475 if (allowed_nightmare())
5476 command_nightmare(id)
5477 else
5478 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5479 }
5480 else
5481 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5482
5483 show_menu_modes_admin(id)
5484 }
5485 }
5486
5487 return PLUGIN_HANDLED;
5488}
5489
5490// Player List Menu
5491public menu_player_list(id, menuid, item)
5492{
5493 // Player disconnected?
5494 if (!is_user_connected(id))
5495 {
5496 menu_destroy(menuid)
5497 return PLUGIN_HANDLED;
5498 }
5499
5500 // Remember player's menu page
5501 static menudummy
5502 player_menu_info(id, menudummy, menudummy, MENU_PAGE_PLAYERS)
5503
5504 // Menu was closed
5505 if (item == MENU_EXIT)
5506 {
5507 menu_destroy(menuid)
5508 show_menu_admin(id)
5509 return PLUGIN_HANDLED;
5510 }
5511
5512 // Retrieve player id
5513 static buffer[2], dummy, playerid
5514 menu_item_getinfo(menuid, item, dummy, buffer, charsmax(buffer), _, _, dummy)
5515 playerid = buffer[0]
5516
5517 // Perform action on player
5518
5519 // Get admin flags
5520 static userflags
5521 userflags = get_user_flags(id)
5522
5523 // Make sure it's still connected
5524 if (g_isconnected[playerid])
5525 {
5526 // Perform the right action if allowed
5527 switch (PL_ACTION)
5528 {
5529 case ACTION_ZOMBIEFY_HUMANIZE: // Zombiefy/Humanize command
5530 {
5531 if (g_zombie[playerid])
5532 {
5533 if (userflags & g_access_flag[ACCESS_MAKE_HUMAN])
5534 {
5535 if (allowed_human(playerid))
5536 command_human(id, playerid)
5537 else
5538 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5539 }
5540 else
5541 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5542 }
5543 else
5544 {
5545 if (g_newround ? (userflags & g_access_flag[ACCESS_MODE_INFECTION]) : (userflags & g_access_flag[ACCESS_MAKE_ZOMBIE]))
5546 {
5547 if (allowed_zombie(playerid))
5548 command_zombie(id, playerid)
5549 else
5550 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5551 }
5552 else
5553 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5554 }
5555 }
5556 case ACTION_MAKE_NEMESIS: // Nemesis command
5557 {
5558 if (g_newround ? (userflags & g_access_flag[ACCESS_MODE_NEMESIS]) : (userflags & g_access_flag[ACCESS_MAKE_NEMESIS]))
5559 {
5560 if (allowed_nemesis(playerid))
5561 command_nemesis(id, playerid)
5562 else
5563 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5564 }
5565 else
5566 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5567 }
5568 case ACTION_MAKE_ASSASSIN: // Assassin command
5569 {
5570 if (g_newround ? (userflags & g_access_flag[ACCESS_MODE_ASSASSIN]) : (userflags & g_access_flag[ACCESS_MAKE_ASSASSIN]))
5571 {
5572 if (allowed_assassin(playerid))
5573 command_assassin(id, playerid)
5574 else
5575 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5576 }
5577 else
5578 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5579 }
5580 case ACTION_MAKE_SURVIVOR: // Survivor command
5581 {
5582 if (g_newround ? (userflags & g_access_flag[ACCESS_MODE_SURVIVOR]) : (userflags & g_access_flag[ACCESS_MAKE_SURVIVOR]))
5583 {
5584 if (allowed_survivor(playerid))
5585 command_survivor(id, playerid)
5586 else
5587 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5588 }
5589 else
5590 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5591 }
5592 case ACTION_MAKE_SNIPER: // Sniper command
5593 {
5594 if (g_newround ? (userflags & g_access_flag[ACCESS_MODE_SNIPER]) : (userflags & g_access_flag[ACCESS_MAKE_SNIPER]))
5595 {
5596 if (allowed_sniper(playerid))
5597 command_sniper(id, playerid)
5598 else
5599 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5600 }
5601 else
5602 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5603 }
5604 case ACTION_RESPAWN_PLAYER: // Respawn command
5605 {
5606 if (userflags & g_access_flag[ACCESS_RESPAWN_PLAYERS])
5607 {
5608 if (allowed_respawn(playerid))
5609 command_respawn(id, playerid)
5610 else
5611 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5612 }
5613 else
5614 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT_ACCESS")
5615 }
5616 }
5617 }
5618 else
5619 zp_colored_print(id, "^x04[ZP]^x01 %L", id, "CMD_NOT")
5620
5621 menu_destroy(menuid)
5622 show_menu_player_list(id)
5623 return PLUGIN_HANDLED;
5624}
5625
5626// CS Buy Menus
5627public menu_cs_buy(id, key)
5628{
5629 // Prevent buying if zombie/survivor (bugfix)
5630 if (g_zombie[id] || g_survivor[id] || g_sniper[id])
5631 return PLUGIN_HANDLED;
5632
5633 return PLUGIN_CONTINUE;
5634}
5635
5636/*================================================================================
5637 [Admin Commands]
5638=================================================================================*/
5639
5640// zp_toggle [1/0]
5641public cmd_toggle(id, level, cid)
5642{
5643 // Check for access flag - Enable/Disable Mod
5644 if (!cmd_access(id, g_access_flag[ACCESS_ENABLE_MOD], cid, 2))
5645 return PLUGIN_HANDLED;
5646
5647 // Retrieve arguments
5648 new arg[2]
5649 read_argv(1, arg, charsmax(arg))
5650
5651 // Mod already enabled/disabled
5652 if (str_to_num(arg) == g_pluginenabled)
5653 return PLUGIN_HANDLED;
5654
5655 // Set toggle cvar
5656 set_pcvar_num(cvar_toggle, str_to_num(arg))
5657 client_print(id, print_console, "Zombie Plague %L.", id, str_to_num(arg) ? "MOTD_ENABLED" : "MOTD_DISABLED")
5658
5659 // Retrieve map name
5660 new mapname[32]
5661 get_mapname(mapname, charsmax(mapname))
5662
5663 // Restart current map
5664 server_cmd("changelevel %s", mapname)
5665
5666 return PLUGIN_HANDLED;
5667}
5668
5669// zp_zombie [target]
5670public cmd_zombie(id, level, cid)
5671{
5672 // Check for access flag depending on the resulting action
5673 if (g_newround)
5674 {
5675 // Start Mode Infection
5676 if (!cmd_access(id, g_access_flag[ACCESS_MODE_INFECTION], cid, 2))
5677 return PLUGIN_HANDLED;
5678 }
5679 else
5680 {
5681 // Make Zombie
5682 if (!cmd_access(id, g_access_flag[ACCESS_MAKE_ZOMBIE], cid, 2))
5683 return PLUGIN_HANDLED;
5684 }
5685
5686 // Retrieve arguments
5687 static arg[32], player
5688 read_argv(1, arg, charsmax(arg))
5689 player = cmd_target(id, arg, (CMDTARGET_ONLY_ALIVE | CMDTARGET_ALLOW_SELF))
5690
5691 // Invalid target
5692 if (!player) return PLUGIN_HANDLED;
5693
5694 // Target not allowed to be zombie
5695 if (!allowed_zombie(player))
5696 {
5697 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5698 return PLUGIN_HANDLED
5699 }
5700
5701 command_zombie(id, player)
5702
5703 return PLUGIN_HANDLED;
5704}
5705
5706// zp_human [target]
5707public cmd_human(id, level, cid)
5708{
5709 // Check for access flag - Make Human
5710 if (!cmd_access(id, g_access_flag[ACCESS_MAKE_HUMAN], cid, 2))
5711 return PLUGIN_HANDLED;
5712
5713 // Retrieve arguments
5714 static arg[32], player
5715 read_argv(1, arg, charsmax(arg))
5716 player = cmd_target(id, arg, (CMDTARGET_ONLY_ALIVE | CMDTARGET_ALLOW_SELF))
5717
5718 // Invalid target
5719 if (!player) return PLUGIN_HANDLED;
5720
5721 // Target not allowed to be human
5722 if (!allowed_human(player))
5723 {
5724 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5725 return PLUGIN_HANDLED;
5726 }
5727
5728 command_human(id, player)
5729
5730 return PLUGIN_HANDLED;
5731}
5732
5733// zp_survivor [target]
5734public cmd_survivor(id, level, cid)
5735{
5736 // Check for access flag depending on the resulting action
5737 if (g_newround)
5738 {
5739 // Start Mode Survivor
5740 if (!cmd_access(id, g_access_flag[ACCESS_MODE_SURVIVOR], cid, 2))
5741 return PLUGIN_HANDLED;
5742 }
5743 else
5744 {
5745 // Make Survivor
5746 if (!cmd_access(id, g_access_flag[ACCESS_MAKE_SURVIVOR], cid, 2))
5747 return PLUGIN_HANDLED;
5748 }
5749
5750 // Retrieve arguments
5751 static arg[32], player
5752 read_argv(1, arg, charsmax(arg))
5753 player = cmd_target(id, arg, (CMDTARGET_ONLY_ALIVE | CMDTARGET_ALLOW_SELF))
5754
5755 // Invalid target
5756 if (!player) return PLUGIN_HANDLED;
5757
5758 // Target not allowed to be survivor
5759 if (!allowed_survivor(player))
5760 {
5761 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5762 return PLUGIN_HANDLED;
5763 }
5764
5765 command_survivor(id, player)
5766
5767 return PLUGIN_HANDLED;
5768}
5769
5770// zp_sniper [target]
5771public cmd_sniper(id, level, cid)
5772{
5773 // Check for access flag depending on the resulting action
5774 if (g_newround)
5775 {
5776 // Start Mode Sniper
5777 if (!cmd_access(id, g_access_flag[ACCESS_MODE_SNIPER], cid, 2))
5778 return PLUGIN_HANDLED;
5779 }
5780 else
5781 {
5782 // Make Sniper
5783 if (!cmd_access(id, g_access_flag[ACCESS_MAKE_SNIPER], cid, 2))
5784 return PLUGIN_HANDLED;
5785 }
5786
5787 // Retrieve arguments
5788 static arg[32], player
5789 read_argv(1, arg, charsmax(arg))
5790 player = cmd_target(id, arg, (CMDTARGET_ONLY_ALIVE | CMDTARGET_ALLOW_SELF))
5791
5792 // Invalid target
5793 if (!player) return PLUGIN_HANDLED;
5794
5795 // Target not allowed to be sniper
5796 if (!allowed_sniper(player))
5797 {
5798 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5799 return PLUGIN_HANDLED;
5800 }
5801
5802 command_sniper(id, player)
5803
5804 return PLUGIN_HANDLED;
5805}
5806
5807// zp_nemesis [target]
5808public cmd_nemesis(id, level, cid)
5809{
5810 // Check for access flag depending on the resulting action
5811 if (g_newround)
5812 {
5813 // Start Mode Nemesis
5814 if (!cmd_access(id, g_access_flag[ACCESS_MODE_NEMESIS], cid, 2))
5815 return PLUGIN_HANDLED;
5816 }
5817 else
5818 {
5819 // Make Nemesis
5820 if (!cmd_access(id, g_access_flag[ACCESS_MAKE_NEMESIS], cid, 2))
5821 return PLUGIN_HANDLED;
5822 }
5823
5824 // Retrieve arguments
5825 static arg[32], player
5826 read_argv(1, arg, charsmax(arg))
5827 player = cmd_target(id, arg, (CMDTARGET_ONLY_ALIVE | CMDTARGET_ALLOW_SELF))
5828
5829 // Invalid target
5830 if (!player) return PLUGIN_HANDLED;
5831
5832 // Target not allowed to be nemesis
5833 if (!allowed_nemesis(player))
5834 {
5835 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5836 return PLUGIN_HANDLED;
5837 }
5838
5839 command_nemesis(id, player)
5840
5841 return PLUGIN_HANDLED;
5842}
5843
5844// zp_assassin [target]
5845public cmd_assassin(id, level, cid)
5846{
5847 // Check for access flag depending on the resulting action
5848 if (g_newround)
5849 {
5850 // Start Mode Assassin
5851 if (!cmd_access(id, g_access_flag[ACCESS_MODE_ASSASSIN], cid, 2))
5852 return PLUGIN_HANDLED;
5853 }
5854 else
5855 {
5856 // Make Assassin
5857 if (!cmd_access(id, g_access_flag[ACCESS_MAKE_ASSASSIN], cid, 2))
5858 return PLUGIN_HANDLED;
5859 }
5860
5861 // Retrieve arguments
5862 static arg[32], player
5863 read_argv(1, arg, charsmax(arg))
5864 player = cmd_target(id, arg, (CMDTARGET_ONLY_ALIVE | CMDTARGET_ALLOW_SELF))
5865
5866 // Invalid target
5867 if (!player) return PLUGIN_HANDLED;
5868
5869 // Target not allowed to be assassin
5870 if (!allowed_assassin(player))
5871 {
5872 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5873 return PLUGIN_HANDLED;
5874 }
5875
5876 command_assassin(id, player)
5877
5878 return PLUGIN_HANDLED;
5879}
5880
5881// zp_respawn [target]
5882public cmd_respawn(id, level, cid)
5883{
5884 // Check for access flag - Respawn
5885 if (!cmd_access(id, g_access_flag[ACCESS_RESPAWN_PLAYERS], cid, 2))
5886 return PLUGIN_HANDLED;
5887
5888 // Retrieve arguments
5889 static arg[32], player
5890 read_argv(1, arg, charsmax(arg))
5891 player = cmd_target(id, arg, CMDTARGET_ALLOW_SELF)
5892
5893 // Invalid target
5894 if (!player) return PLUGIN_HANDLED;
5895
5896 // Target not allowed to be respawned
5897 if (!allowed_respawn(player))
5898 {
5899 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5900 return PLUGIN_HANDLED;
5901 }
5902
5903 command_respawn(id, player)
5904
5905 return PLUGIN_HANDLED;
5906}
5907
5908// zp_swarm
5909public cmd_swarm(id, level, cid)
5910{
5911 // Check for access flag - Mode Swarm
5912 if (!cmd_access(id, g_access_flag[ACCESS_MODE_SWARM], cid, 1))
5913 return PLUGIN_HANDLED;
5914
5915 // Swarm mode not allowed
5916 if (!allowed_swarm())
5917 {
5918 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5919 return PLUGIN_HANDLED;
5920 }
5921
5922 command_swarm(id)
5923
5924 return PLUGIN_HANDLED;
5925}
5926
5927// zp_multi
5928public cmd_multi(id, level, cid)
5929{
5930 // Check for access flag - Mode Multi
5931 if (!cmd_access(id, g_access_flag[ACCESS_MODE_MULTI], cid, 1))
5932 return PLUGIN_HANDLED;
5933
5934 // Multi infection mode not allowed
5935 if (!allowed_multi())
5936 {
5937 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5938 return PLUGIN_HANDLED;
5939 }
5940
5941 command_multi(id)
5942
5943 return PLUGIN_HANDLED;
5944}
5945
5946// zp_plague
5947public cmd_plague(id, level, cid)
5948{
5949 // Check for access flag - Mode Plague
5950 if (!cmd_access(id, g_access_flag[ACCESS_MODE_PLAGUE], cid, 1))
5951 return PLUGIN_HANDLED;
5952
5953 // Plague mode not allowed
5954 if (!allowed_plague())
5955 {
5956 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5957 return PLUGIN_HANDLED;
5958 }
5959
5960 command_plague(id)
5961
5962 return PLUGIN_HANDLED;
5963}
5964
5965// zp_armageddon
5966public cmd_armageddon(id, level, cid)
5967{
5968 // Check for access flag - Mode Armageddon
5969 if (!cmd_access(id, g_access_flag[ACCESS_MODE_ARMAGEDDON], cid, 1))
5970 return PLUGIN_HANDLED;
5971
5972 // Armageddon mode not allowed
5973 if (!allowed_armageddon())
5974 {
5975 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5976 return PLUGIN_HANDLED;
5977 }
5978
5979 command_armageddon(id)
5980
5981 return PLUGIN_HANDLED;
5982}
5983
5984// zp_apocalypse
5985public cmd_apocalypse(id, level, cid)
5986{
5987 // Check for access flag - Mode Apocalypse
5988 if (!cmd_access(id, g_access_flag[ACCESS_MODE_APOCALYPSE], cid, 1))
5989 return PLUGIN_HANDLED;
5990
5991 // Apocalypse mode not allowed
5992 if (!allowed_apocalypse())
5993 {
5994 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
5995 return PLUGIN_HANDLED;
5996 }
5997
5998 command_apocalypse(id)
5999
6000 return PLUGIN_HANDLED;
6001}
6002
6003// zp_nightmare
6004public cmd_nightmare(id, level, cid)
6005{
6006 // Check for access flag - Mode Nightmare
6007 if (!cmd_access(id, g_access_flag[ACCESS_MODE_NIGHTMARE], cid, 1))
6008 return PLUGIN_HANDLED;
6009
6010 // Nightmare mode not allowed
6011 if (!allowed_nightmare())
6012 {
6013 client_print(id, print_console, "[ZP] %L", id, "CMD_NOT")
6014 return PLUGIN_HANDLED;
6015 }
6016
6017 command_nightmare(id)
6018
6019 return PLUGIN_HANDLED;
6020}
6021
6022/*================================================================================
6023 [Message Hooks]
6024=================================================================================*/
6025
6026// Current Weapon info
6027public message_cur_weapon(msg_id, msg_dest, msg_entity)
6028{
6029 // Not alive or zombie
6030 if (!g_isalive[msg_entity] || g_zombie[msg_entity])
6031 return;
6032
6033 // Not an active weapon
6034 if (get_msg_arg_int(1) != 1)
6035 return;
6036
6037 // Unlimited clip disabled for class
6038 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)
6039 return;
6040
6041 // Get weapon's id
6042 static weapon
6043 weapon = get_msg_arg_int(2)
6044
6045 // Unlimited Clip Ammo for this weapon?
6046 if (MAXBPAMMO[weapon] > 2)
6047 {
6048 // Max out clip ammo
6049 static weapon_ent
6050 weapon_ent = fm_cs_get_current_weapon_ent(msg_entity)
6051 if (pev_valid(weapon_ent)) cs_set_weapon_ammo(weapon_ent, MAXCLIP[weapon])
6052
6053 // HUD should show full clip all the time
6054 set_msg_arg_int(3, get_msg_argtype(3), MAXCLIP[weapon])
6055 }
6056}
6057
6058// Take off player's money
6059public message_money(msg_id, msg_dest, msg_entity)
6060{
6061 // Remove money setting enabled?
6062 if (!get_pcvar_num(cvar_removemoney))
6063 return PLUGIN_CONTINUE;
6064
6065 fm_cs_set_user_money(msg_entity, 0)
6066 return PLUGIN_HANDLED;
6067}
6068
6069// Fix for the HL engine bug when HP is multiples of 256
6070public message_health(msg_id, msg_dest, msg_entity)
6071{
6072 // Get player's health
6073 static health
6074 health = get_msg_arg_int(1)
6075
6076 // Don't bother
6077 if (health < 256) return;
6078
6079 // Check if we need to fix it
6080 if (health % 256 == 0)
6081 fm_set_user_health(msg_entity, pev(msg_entity, pev_health) + 1)
6082
6083 // HUD can only show as much as 255 hp
6084 set_msg_arg_int(1, get_msg_argtype(1), 255)
6085}
6086
6087// Block flashlight battery messages if custom flashlight is enabled instead
6088public message_flashbat()
6089{
6090 if (g_cached_customflash)
6091 return PLUGIN_HANDLED;
6092
6093 return PLUGIN_CONTINUE;
6094}
6095
6096// Flashbangs should only affect zombies
6097public message_screenfade(msg_id, msg_dest, msg_entity)
6098{
6099 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)
6100 return PLUGIN_CONTINUE;
6101
6102 // Nemesis shouldn't be FBed
6103 if (g_zombie[msg_entity] && !g_nemesis[msg_entity] && !g_assassin[msg_entity])
6104 {
6105 // Set flash color to nighvision's
6106 set_msg_arg_int(4, get_msg_argtype(4), get_pcvar_num(cvar_nvgcolor[0]))
6107 set_msg_arg_int(5, get_msg_argtype(5), get_pcvar_num(cvar_nvgcolor[1]))
6108 set_msg_arg_int(6, get_msg_argtype(6), get_pcvar_num(cvar_nvgcolor[2]))
6109 return PLUGIN_CONTINUE;
6110 }
6111
6112 return PLUGIN_HANDLED;
6113}
6114
6115// Prevent spectators' nightvision from being turned off when switching targets, etc.
6116public message_nvgtoggle()
6117{
6118 return PLUGIN_HANDLED;
6119}
6120
6121// Set correct model on player corpses
6122public message_clcorpse()
6123{
6124 set_msg_arg_string(1, g_playermodel[get_msg_arg_int(12)])
6125}
6126
6127// Prevent zombies from seeing any weapon pickup icon
6128public message_weappickup(msg_id, msg_dest, msg_entity)
6129{
6130 if (g_zombie[msg_entity])
6131 return PLUGIN_HANDLED;
6132
6133 return PLUGIN_CONTINUE;
6134}
6135
6136// Prevent zombies from seeing any ammo pickup icon
6137public message_ammopickup(msg_id, msg_dest, msg_entity)
6138{
6139 if (g_zombie[msg_entity])
6140 return PLUGIN_HANDLED;
6141
6142 return PLUGIN_CONTINUE;
6143}
6144
6145// Block hostage HUD display
6146public message_scenario()
6147{
6148 if (get_msg_args() > 1)
6149 {
6150 static sprite[8]
6151 get_msg_arg_string(2, sprite, charsmax(sprite))
6152
6153 if (equal(sprite, "hostage"))
6154 return PLUGIN_HANDLED;
6155 }
6156
6157 return PLUGIN_CONTINUE;
6158}
6159
6160// Block hostages from appearing on radar
6161public message_hostagepos()
6162{
6163 return PLUGIN_HANDLED;
6164}
6165
6166// Block some text messages
6167public message_textmsg()
6168{
6169 static textmsg[22]
6170 get_msg_arg_string(2, textmsg, charsmax(textmsg))
6171
6172 // Game restarting, reset scores and call round end to balance the teams
6173 if (equal(textmsg, "#Game_will_restart_in"))
6174 {
6175 logevent_round_end()
6176 g_scorehumans = 0
6177 g_scorezombies = 0
6178 }
6179 // Game commencing, reset scores only (round end is automatically triggered)
6180 else if (equal(textmsg, "#Game_Commencing"))
6181 {
6182 g_gamecommencing = true
6183 g_scorehumans = 0
6184 g_scorezombies = 0
6185 }
6186 // Block round end related messages
6187 else if (equal(textmsg, "#Hostages_Not_Rescued") || equal(textmsg, "#Round_Draw") || equal(textmsg, "#Terrorists_Win") || equal(textmsg, "#CTs_Win"))
6188 {
6189 return PLUGIN_HANDLED;
6190 }
6191
6192 return PLUGIN_CONTINUE;
6193}
6194
6195// Block CS round win audio messages, since we're playing our own instead
6196public message_sendaudio()
6197{
6198 static audio[17]
6199 get_msg_arg_string(2, audio, charsmax(audio))
6200
6201 if(equal(audio[7], "terwin") || equal(audio[7], "ctwin") || equal(audio[7], "rounddraw"))
6202 return PLUGIN_HANDLED;
6203
6204 return PLUGIN_CONTINUE;
6205}
6206
6207// Send actual team scores (T = zombies // CT = humans)
6208public message_teamscore()
6209{
6210 static team[2]
6211 get_msg_arg_string(1, team, charsmax(team))
6212
6213 switch (team[0])
6214 {
6215 // CT
6216 case 'C': set_msg_arg_int(2, get_msg_argtype(2), g_scorehumans)
6217 // Terrorist
6218 case 'T': set_msg_arg_int(2, get_msg_argtype(2), g_scorezombies)
6219 }
6220}
6221
6222// Team Switch (or player joining a team for first time)
6223public message_teaminfo(msg_id, msg_dest)
6224{
6225 // Only hook global messages
6226 if (msg_dest != MSG_ALL && msg_dest != MSG_BROADCAST) return;
6227
6228 // Don't pick up our own TeamInfo messages for this player (bugfix)
6229 if (g_switchingteam) return;
6230
6231 // Get player's id
6232 static id
6233 id = get_msg_arg_int(1)
6234
6235 // Invalid player id? (bugfix)
6236 if (!(1 <= id <= g_maxplayers)) return;
6237
6238 // Enable spectators' nightvision if not spawning right away
6239 set_task(0.2, "spec_nvision", id)
6240
6241 // Round didn't start yet, nothing to worry about
6242 if (g_newround) return;
6243
6244 // Get his new team
6245 static team[2]
6246 get_msg_arg_string(2, team, charsmax(team))
6247
6248 // Perform some checks to see if they should join a different team instead
6249 switch (team[0])
6250 {
6251 case 'C': // CT
6252 {
6253 if ((g_survround && fnGetHumans()) || (g_sniround && fnGetHumans())) // survivor/sniper alive --> switch to T and spawn as zombie
6254 {
6255 g_respawn_as_zombie[id] = true;
6256 remove_task(id+TASK_TEAM)
6257 fm_cs_set_user_team(id, FM_CS_TEAM_T)
6258 set_msg_arg_string(2, "TERRORIST")
6259 }
6260 else if (!fnGetZombies()) // no zombies alive --> switch to T and spawn as zombie
6261 {
6262 g_respawn_as_zombie[id] = true;
6263 remove_task(id+TASK_TEAM)
6264 fm_cs_set_user_team(id, FM_CS_TEAM_T)
6265 set_msg_arg_string(2, "TERRORIST")
6266 }
6267 }
6268 case 'T': // Terrorist
6269 {
6270 if ((g_swarmround || g_survround || g_sniround) && fnGetHumans()) // survivor alive or swarm round w/ humans --> spawn as zombie
6271 {
6272 g_respawn_as_zombie[id] = true;
6273 }
6274 else if (fnGetZombies()) // zombies alive --> switch to CT
6275 {
6276 remove_task(id+TASK_TEAM)
6277 fm_cs_set_user_team(id, FM_CS_TEAM_CT)
6278 set_msg_arg_string(2, "CT")
6279 }
6280 }
6281 }
6282}
6283
6284/*================================================================================
6285 [Main Functions]
6286=================================================================================*/
6287
6288// Make Zombie Task
6289public make_zombie_task()
6290{
6291 // Call make a zombie with no specific mode
6292 make_a_zombie(MODE_NONE, 0)
6293}
6294
6295// Make a Zombie Function
6296make_a_zombie(mode, id)
6297{
6298 // Get alive players count
6299 static iPlayersnum
6300 iPlayersnum = fnGetAlive()
6301
6302 // Not enough players, come back later!
6303 if (iPlayersnum < 1)
6304 {
6305 set_task(2.0, "make_zombie_task", TASK_MAKEZOMBIE)
6306 return;
6307 }
6308
6309 // Round started!
6310 g_newround = false
6311
6312 // Set up some common vars
6313 static forward_id, sound[64], iZombies, iMaxZombies
6314
6315 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)
6316 {
6317 // Survivor Mode
6318 g_survround = true
6319 g_lastmode = MODE_SURVIVOR
6320
6321 // Choose player randomly?
6322 if (mode == MODE_NONE)
6323 id = fnGetRandomAlive(random_num(1, iPlayersnum))
6324
6325 // Remember id for calling our forward later
6326 forward_id = id
6327
6328 // Turn player into a survivor
6329 humanme(id, 1, 0, 0)
6330
6331 // Turn the remaining players into zombies
6332 for (id = 1; id <= g_maxplayers; id++)
6333 {
6334 // Not alive
6335 if (!g_isalive[id])
6336 continue;
6337
6338 // Survivor or already a zombie
6339 if (g_survivor[id] || g_zombie[id])
6340 continue;
6341
6342 // Turn into a zombie
6343 zombieme(id, 0, 0, 0, 1, 0)
6344 }
6345
6346 // Play survivor sound
6347 ArrayGetString(sound_survivor, random_num(0, ArraySize(sound_survivor) - 1), sound, charsmax(sound))
6348 PlaySound(sound);
6349
6350 // Show Survivor HUD notice
6351 set_dhudmessage(0, 10, 255, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0)
6352 show_dhudmessage(0, "%L", LANG_PLAYER, "NOTICE_SURVIVOR", g_playername[forward_id])
6353
6354 // Mode fully started!
6355 g_modestarted = true
6356
6357 // Round start forward
6358 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_SURVIVOR, forward_id);
6359 }
6360 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)
6361 {
6362 // Sniper Mode
6363 g_sniround = true
6364 g_lastmode = MODE_SNIPER
6365
6366 // Choose player randomly?
6367 if (mode == MODE_NONE)
6368 id = fnGetRandomAlive(random_num(1, iPlayersnum))
6369
6370 // Remember id for calling our forward later
6371 forward_id = id
6372
6373 // Turn player into a sniper
6374 humanme(id, 0, 1, 0)
6375
6376 // Turn the remaining players into zombies
6377 for (id = 1; id <= g_maxplayers; id++)
6378 {
6379 // Not alive
6380 if (!g_isalive[id])
6381 continue;
6382
6383 // Sniper or already a zombie
6384 if (g_sniper[id] || g_zombie[id])
6385 continue;
6386
6387 // Turn into a zombie
6388 zombieme(id, 0, 0, 0, 1, 0)
6389 }
6390
6391 // Play sniper sound
6392 ArrayGetString(sound_sniper, random_num(0, ArraySize(sound_sniper) - 1), sound, charsmax(sound))
6393 PlaySound(sound);
6394
6395 // Show Sniper HUD notice
6396 set_dhudmessage(0 , 250, 250, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0)
6397 show_dhudmessage(0, "%L", LANG_PLAYER, "NOTICE_SNIPER", g_playername[forward_id])
6398
6399 // Mode fully started!
6400 g_modestarted = true
6401
6402 // Round start forward
6403 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_SNIPER, forward_id);
6404 }
6405 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)
6406 {
6407 // Swarm Mode
6408 g_swarmround = true
6409 g_lastmode = MODE_SWARM
6410
6411 // Make sure there are alive players on both teams (BUGFIX)
6412 if (!fnGetAliveTs())
6413 {
6414 // Move random player to T team
6415 id = fnGetRandomAlive(random_num(1, iPlayersnum))
6416 remove_task(id+TASK_TEAM)
6417 fm_cs_set_user_team(id, FM_CS_TEAM_T)
6418 fm_user_team_update(id)
6419 }
6420 else if (!fnGetAliveCTs())
6421 {
6422 // Move random player to CT team
6423 id = fnGetRandomAlive(random_num(1, iPlayersnum))
6424 remove_task(id+TASK_TEAM)
6425 fm_cs_set_user_team(id, FM_CS_TEAM_CT)
6426 fm_user_team_update(id)
6427 }
6428
6429 // Turn every T into a zombie
6430 for (id = 1; id <= g_maxplayers; id++)
6431 {
6432 // Not alive
6433 if (!g_isalive[id])
6434 continue;
6435
6436 // Not a Terrorist
6437 if (fm_cs_get_user_team(id) != FM_CS_TEAM_T)
6438 continue;
6439
6440 // Turn into a zombie
6441 zombieme(id, 0, 0, 0, 1, 0)
6442 }
6443
6444 // Play swarm sound
6445 ArrayGetString(sound_swarm, random_num(0, ArraySize(sound_swarm) - 1), sound, charsmax(sound))
6446 PlaySound(sound);
6447
6448 // Show Swarm HUD notice
6449 set_dhudmessage(20, 255, 20, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0)
6450 show_dhudmessage(0, "%L", LANG_PLAYER, "NOTICE_SWARM")
6451
6452 // Mode fully started!
6453 g_modestarted = true
6454
6455 // Round start forward
6456 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_SWARM, 0);
6457 }
6458 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)
6459 {
6460 // Multi Infection Mode
6461 g_lastmode = MODE_MULTI
6462
6463 // iMaxZombies is rounded up, in case there aren't enough players
6464 iMaxZombies = floatround(iPlayersnum*get_pcvar_float(cvar_multiratio), floatround_ceil)
6465 iZombies = 0
6466
6467 // Randomly turn iMaxZombies players into zombies
6468 while (iZombies < iMaxZombies)
6469 {
6470 // Keep looping through all players
6471 if (++id > g_maxplayers) id = 1
6472
6473 // Dead or already a zombie
6474 if (!g_isalive[id] || g_zombie[id])
6475 continue;
6476
6477 // Random chance
6478 if (random_num(0, 1))
6479 {
6480 // Turn into a zombie
6481 zombieme(id, 0, 0, 0, 1, 0)
6482 iZombies++
6483 }
6484 }
6485
6486 // Turn the remaining players into humans
6487 for (id = 1; id <= g_maxplayers; id++)
6488 {
6489 // Only those of them who aren't zombies
6490 if (!g_isalive[id] || g_zombie[id])
6491 continue;
6492
6493 // Switch to CT
6494 if (fm_cs_get_user_team(id) != FM_CS_TEAM_CT) // need to change team?
6495 {
6496 remove_task(id+TASK_TEAM)
6497 fm_cs_set_user_team(id, FM_CS_TEAM_CT)
6498 fm_user_team_update(id)
6499 }
6500 }
6501
6502 // Play multi infection sound
6503 ArrayGetString(sound_multi, random_num(0, ArraySize(sound_multi) - 1), sound, charsmax(sound))
6504 PlaySound(sound);
6505
6506 // Show Multi Infection HUD notice
6507 set_dhudmessage(200, 50, 0, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0)
6508 show_dhudmessage(0, "%L", LANG_PLAYER, "NOTICE_MULTI")
6509
6510 // Mode fully started!
6511 g_modestarted = true
6512
6513 // Round start forward
6514 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_MULTI, 0);
6515 }
6516 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
6517 && 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)
6518 {
6519 // Plague Mode
6520 g_plagueround = true
6521 g_lastmode = MODE_PLAGUE
6522
6523 // Turn specified amount of players into Survivors
6524 static iSurvivors, iMaxSurvivors
6525 iMaxSurvivors = get_pcvar_num(cvar_plaguesurvnum)
6526 iSurvivors = 0
6527
6528 while (iSurvivors < iMaxSurvivors)
6529 {
6530 // Choose random guy
6531 id = fnGetRandomAlive(random_num(1, iPlayersnum))
6532
6533 // Already a survivor?
6534 if (g_survivor[id])
6535 continue;
6536
6537 // If not, turn him into one
6538 humanme(id, 1, 0, 0)
6539 iSurvivors++
6540
6541 // Apply survivor health multiplier
6542 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_plaguesurvhpmulti)))
6543 }
6544
6545 // Turn specified amount of players into Nemesis
6546 static iNemesis, iMaxNemesis
6547 iMaxNemesis = get_pcvar_num(cvar_plaguenemnum)
6548 iNemesis = 0
6549
6550 while (iNemesis < iMaxNemesis)
6551 {
6552 // Choose random guy
6553 id = fnGetRandomAlive(random_num(1, iPlayersnum))
6554
6555 // Already a survivor or nemesis?
6556 if (g_survivor[id] || g_nemesis[id])
6557 continue;
6558
6559 // If not, turn him into one
6560 zombieme(id, 0, 1, 0, 0, 0)
6561 iNemesis++
6562
6563 // Apply nemesis health multiplier
6564 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_plaguenemhpmulti)))
6565 }
6566
6567 // iMaxZombies is rounded up, in case there aren't enough players
6568 iMaxZombies = floatround((iPlayersnum-(get_pcvar_num(cvar_plaguenemnum)+get_pcvar_num(cvar_plaguesurvnum)))*get_pcvar_float(cvar_plagueratio), floatround_ceil)
6569 iZombies = 0
6570
6571 // Randomly turn iMaxZombies players into zombies
6572 while (iZombies < iMaxZombies)
6573 {
6574 // Keep looping through all players
6575 if (++id > g_maxplayers) id = 1
6576
6577 // Dead or already a zombie or survivor
6578 if (!g_isalive[id] || g_zombie[id] || g_survivor[id])
6579 continue;
6580
6581 // Random chance
6582 if (random_num(0, 1))
6583 {
6584 // Turn into a zombie
6585 zombieme(id, 0, 0, 0, 1, 0)
6586 iZombies++
6587 }
6588 }
6589
6590 // Turn the remaining players into humans
6591 for (id = 1; id <= g_maxplayers; id++)
6592 {
6593 // Only those of them who arent zombies or survivor
6594 if (!g_isalive[id] || g_zombie[id] || g_survivor[id])
6595 continue;
6596
6597 // Switch to CT
6598 if (fm_cs_get_user_team(id) != FM_CS_TEAM_CT) // need to change team?
6599 {
6600 remove_task(id+TASK_TEAM)
6601 fm_cs_set_user_team(id, FM_CS_TEAM_CT)
6602 fm_user_team_update(id)
6603 }
6604 }
6605
6606 // Play plague sound
6607 ArrayGetString(sound_plague, random_num(0, ArraySize(sound_plague) - 1), sound, charsmax(sound))
6608 PlaySound(sound);
6609
6610 // Show Plague HUD notice
6611 set_dhudmessage(0, 50, 200, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0)
6612 show_dhudmessage(0, "%L", LANG_PLAYER, "NOTICE_PLAGUE")
6613
6614 // Mode fully started!
6615 g_modestarted = true
6616
6617 // Round start forward
6618 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_PLAGUE, 0);
6619 }
6620 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)
6621 {
6622 // Armageddon Mode
6623 g_armageround = true
6624 g_lastmode = MODE_ARMAGEDDON
6625
6626 // iMaxZombies is rounded up, in case there aren't enough players
6627 iMaxZombies = floatround((iPlayersnum * get_pcvar_float(cvar_armageratio)), floatround_ceil)
6628 iZombies = 0
6629
6630 // Randomly turn iMaxZombies players into Nemesis
6631 while (iZombies < iMaxZombies)
6632 {
6633 // Keep looping through all players
6634 if (++id > g_maxplayers) id = 1
6635
6636 // Dead or already a zombie or survivor
6637 if (!g_isalive[id] || g_zombie[id] || g_survivor[id])
6638 continue;
6639
6640 // Random chance
6641 if (random_num(0, 1))
6642 {
6643 // Turn into a Nemesis
6644 zombieme(id, 0, 1, 0, 0, 0)
6645 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_armagenemhpmulti)))
6646 iZombies++
6647 }
6648 }
6649
6650 // Turn the remaining players into survivors
6651 for (id = 1; id <= g_maxplayers; id++)
6652 {
6653 // Only those of them who arent zombies or survivor
6654 if (!g_isalive[id] || g_zombie[id]|| g_survivor[id])
6655 continue;
6656
6657 // Turn into a Survivor
6658 humanme(id, 1, 0, 0)
6659 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_armagesurvhpmulti)))
6660 }
6661
6662 // Play armageddon sound
6663 ArrayGetString(sound_armageddon, random_num(0, ArraySize(sound_armageddon) - 1), sound, charsmax(sound))
6664 PlaySound(sound);
6665
6666 // Show Armageddon HUD notice
6667 set_dhudmessage(181 , 62, 244, -1.0, 0.17, 1, 0.0, 5.0, 1.0, 1.0)
6668 show_dhudmessage(0, "%L", LANG_PLAYER, "NOTICE_ARMAGEDDON")
6669
6670 // Mode fully started!
6671 g_modestarted = true
6672
6673 // Round start forward
6674 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_ARMAGEDDON, 0);
6675 }
6676 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)
6677 {
6678 // Apocalypse Mode
6679 g_apocround = true
6680 g_lastmode = MODE_APOCALYPSE
6681
6682 // iMaxZombies is rounded up, in case there aren't enough players
6683 iMaxZombies = floatround((iPlayersnum * get_pcvar_float(cvar_apocratio)), floatround_ceil)
6684 iZombies = 0
6685
6686 // Randomly turn iMaxZombies players into Assassin
6687 while (iZombies < iMaxZombies)
6688 {
6689 // Keep looping through all players
6690 if (++id > g_maxplayers) id = 1
6691
6692 // Dead or already a zombie or sniper
6693 if (!g_isalive[id] || g_zombie[id] || g_sniper[id])
6694 continue;
6695
6696 // Random chance
6697 if (random_num(0, 1))
6698 {
6699 // Turn into a Assassin
6700 zombieme(id, 0, 0, 1, 0, 0)
6701 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_apocassahpmulti)))
6702 iZombies++
6703 }
6704 }
6705
6706 // Turn the remaining players into snipers
6707 for (id = 1; id <= g_maxplayers; id++)
6708 {
6709 // Only those of them who arent zombies or sniper
6710 if (!g_isalive[id] || g_zombie[id]|| g_sniper[id])
6711 continue;
6712
6713 // Turn into a Sniper
6714 humanme(id, 0, 1, 0)
6715 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_apocsniphpmulti)))
6716 }
6717
6718 // Play apocalypse sound
6719 ArrayGetString(sound_apocalypse, random_num(0, ArraySize(sound_apocalypse) - 1), sound, charsmax(sound))
6720 PlaySound(sound);
6721
6722 // Show Apocalypse HUD notice
6723 set_dhudmessage(181 , 62, 244, -1.0, 0.17, 1, 0.0, 5.0, 1.0, 1.0)
6724 show_dhudmessage(0, "%L", LANG_PLAYER, "NOTICE_APOCALYPSE")
6725
6726 // Mode fully started!
6727 g_modestarted = true
6728
6729 // Round start forward
6730 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_APOCALYPSE, 0);
6731 }
6732 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)
6733 {
6734 // Nightmare mode
6735 g_nightround = true
6736 g_lastmode = MODE_NIGHTMARE
6737
6738 iMaxZombies = floatround((iPlayersnum * 0.25), floatround_ceil)
6739 iZombies = 0
6740
6741 while (iZombies < iMaxZombies)
6742 {
6743 if ((++id) > g_maxplayers) id = 1
6744
6745 if (!g_isalive[id])
6746 continue;
6747
6748 if (random_num(1, 5) == 1)
6749 {
6750 zombieme(id, 0, 0, 1, 0, 0)
6751 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_nightassahpmulti)))
6752 iZombies++
6753 }
6754 }
6755
6756 iZombies = 0
6757
6758 while (iZombies < iMaxZombies)
6759 {
6760 if ((++id) > g_maxplayers) id = 1
6761
6762 if (!g_isalive[id] || g_assassin[id])
6763 continue;
6764
6765 if (random_num(1, 5) == 1)
6766 {
6767 zombieme(id, 0, 1, 0, 0, 0)
6768 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_nightnemhpmulti)))
6769 iZombies++
6770 }
6771 }
6772
6773 iZombies = 0
6774
6775 while (iZombies < iMaxZombies)
6776 {
6777 if ((++id) > g_maxplayers) id = 1
6778
6779 if (!g_isalive[id] || g_assassin[id] || g_nemesis[id])
6780 continue;
6781
6782 if (random_num(1, 5) == 1)
6783 {
6784 humanme(id, 1, 0, 0)
6785 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_nightsurvhpmulti)))
6786 iZombies++
6787 }
6788 }
6789
6790 for (id = 1; id <= g_maxplayers; id++)
6791 {
6792 if (!g_isalive[id] || g_assassin[id] || g_nemesis[id] || g_survivor[id])
6793 continue;
6794
6795 humanme(id, 0, 1, 0)
6796 fm_set_user_health(id, floatround(float(pev(id, pev_health)) * get_pcvar_float(cvar_nightsniphpmulti)))
6797 }
6798
6799 // Play nightmare sound
6800 ArrayGetString(sound_nightmare, random_num(0, ArraySize(sound_nightmare) - 1), sound, charsmax(sound))
6801 PlaySound(sound);
6802
6803 // Show Nightmare HUD notice
6804 set_dhudmessage(181 , 62, 244, -1.0, 0.17, 1, 0.0, 5.0, 1.0, 1.0)
6805 show_dhudmessage(0, "%L", LANG_PLAYER, "NOTICE_NIGHTMARE")
6806
6807 // Mode fully started!
6808 g_modestarted = true
6809
6810 // Round start forward
6811 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_NIGHTMARE, 0);
6812 }
6813 else
6814 {
6815 // Single Infection Mode or Nemesis Mode
6816
6817 // Choose player randomly?
6818 if (mode == MODE_NONE)
6819 id = fnGetRandomAlive(random_num(1, iPlayersnum))
6820
6821 // Remember id for calling our forward later
6822 forward_id = id
6823
6824 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)
6825 {
6826 // Nemesis Mode
6827 g_nemround = true
6828 g_lastmode = MODE_NEMESIS
6829
6830 // Turn player into nemesis
6831 zombieme(id, 0, 1, 0, 0, 0)
6832 }
6833 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)
6834 {
6835 // Assassin Mode
6836 g_assaround = true
6837 g_lastmode = MODE_ASSASSIN
6838
6839 // Turn player into assassin
6840 zombieme(id, 0, 0, 1, 0, 0)
6841 }
6842 else
6843 {
6844 // Single Infection Mode
6845 g_lastmode = MODE_INFECTION
6846
6847 // Turn player into the first zombie
6848 zombieme(id, 0, 0, 0, 0, 0)
6849 }
6850
6851 // Remaining players should be humans (CTs)
6852 for (id = 1; id <= g_maxplayers; id++)
6853 {
6854 // Not alive
6855 if (!g_isalive[id])
6856 continue;
6857
6858 // First zombie/nemesis
6859 if (g_zombie[id])
6860 continue;
6861
6862 // Switch to CT
6863 if (fm_cs_get_user_team(id) != FM_CS_TEAM_CT) // need to change team?
6864 {
6865 remove_task(id+TASK_TEAM)
6866 fm_cs_set_user_team(id, FM_CS_TEAM_CT)
6867 fm_user_team_update(id)
6868 }
6869 }
6870
6871 if (g_nemround)
6872 {
6873 // Play Nemesis sound
6874 ArrayGetString(sound_nemesis, random_num(0, ArraySize(sound_nemesis) - 1), sound, charsmax(sound))
6875 PlaySound(sound);
6876
6877 // Show Nemesis HUD notice
6878 set_dhudmessage(255, 20, 20, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0)
6879 show_dhudmessage(0, "%L", LANG_PLAYER, "NOTICE_NEMESIS", g_playername[forward_id])
6880
6881 // Mode fully started!
6882 g_modestarted = true
6883
6884 // Round start forward
6885 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_NEMESIS, forward_id);
6886 }
6887 else if (g_assaround)
6888 {
6889 // Play Assassin sound
6890 ArrayGetString(sound_assassin, random_num(0, ArraySize(sound_assassin) - 1), sound, charsmax(sound))
6891 PlaySound(sound);
6892
6893 // Show Assassin HUD notice
6894 set_dhudmessage(255, 150, 20, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 5.0, 1.0, 1.0)
6895 show_dhudmessage(0, "%L", LANG_PLAYER, "NOTICE_ASSASSIN", g_playername[forward_id])
6896
6897 // Mode fully started!
6898 g_modestarted = true
6899
6900 // Round start forward
6901 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_ASSASSIN, forward_id);
6902 }
6903 else
6904 {
6905 // Show First Zombie HUD notice
6906 set_dhudmessage(255, 0, 0, HUD_EVENT_X, HUD_EVENT_Y, 0, 0.0, 5.0, 1.0, 1.0)
6907 show_dhudmessage(0, "%L",LANG_PLAYER, "NOTICE_FIRST", g_playername[forward_id])
6908
6909 // Mode fully started!
6910 g_modestarted = true
6911
6912 // Round start forward
6913 ExecuteForward(g_fwRoundStart, g_fwDummyResult, MODE_INFECTION, forward_id);
6914 }
6915 }
6916
6917 // Start ambience sounds after a mode begins
6918 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)
6919 || (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)))
6920 {
6921 remove_task(TASK_AMBIENCESOUNDS)
6922 set_task(2.0, "ambience_sound_effects", TASK_AMBIENCESOUNDS)
6923 }
6924}
6925
6926// Zombie Me Function (player id, infector, turn into a nemesis, silent mode, deathmsg and rewards)
6927zombieme(id, infector, nemesis, assassin, silentmode, rewards)
6928{
6929 // User infect attempt forward
6930 ExecuteForward(g_fwUserInfect_attempt, g_fwDummyResult, id, infector, nemesis)
6931
6932 // One or more plugins blocked the infection. Only allow this after making sure it's
6933 // not going to leave us with no zombies. Take into account a last player leaving case.
6934 // BUGFIX: only allow after a mode has started, to prevent blocking first zombie e.g.
6935 if (g_fwDummyResult >= ZP_PLUGIN_HANDLED && g_modestarted && fnGetZombies() > g_lastplayerleaving)
6936 return;
6937
6938 // Pre user infect forward
6939 ExecuteForward(g_fwUserInfected_pre, g_fwDummyResult, id, infector, nemesis)
6940
6941 // Show zombie class menu if they haven't chosen any (e.g. just connected)
6942 if (g_zombieclassnext[id] == ZCLASS_NONE && get_pcvar_num(cvar_zclasses))
6943 set_task(0.2, "show_menu_zclass", id)
6944
6945 // Set selected zombie class
6946 g_zombieclass[id] = g_zombieclassnext[id]
6947 // If no class selected yet, use the first (default) one
6948 if (g_zombieclass[id] == ZCLASS_NONE) g_zombieclass[id] = 0
6949
6950 // Way to go...
6951 g_zombie[id] = true
6952 g_nemesis[id] = false
6953 g_assassin[id] = false
6954 g_survivor[id] = false
6955 g_sniper[id] = false
6956 g_firstzombie[id] = false
6957
6958 // Remove survivor's aura (bugfix)
6959 set_pev(id, pev_effects, pev(id, pev_effects) &~ EF_BRIGHTLIGHT)
6960
6961 // Remove spawn protection (bugfix)
6962 g_nodamage[id] = false
6963 set_pev(id, pev_effects, pev(id, pev_effects) &~ EF_NODRAW)
6964
6965 // Reset burning duration counter (bugfix)
6966 g_burning_duration[id] = 0
6967
6968 // Show deathmsg and reward infector?
6969 if (rewards && infector)
6970 {
6971 // Send death notice and fix the "dead" attrib on scoreboard
6972 SendDeathMsg(infector, id)
6973 FixDeadAttrib(id)
6974
6975 // Reward frags, deaths, health, and ammo packs
6976 UpdateFrags(infector, id, get_pcvar_num(cvar_fragsinfect), 1, 1)
6977 g_ammopacks[infector] += get_pcvar_num(cvar_ammoinfect)
6978 fm_set_user_health(infector, pev(infector, pev_health) + get_pcvar_num(cvar_zombiebonushp))
6979 }
6980
6981 // Cache speed, knockback, and name for player's class
6982 g_zombie_spd[id] = float(ArrayGetCell(g_zclass_spd, g_zombieclass[id]))
6983 g_zombie_knockback[id] = Float:ArrayGetCell(g_zclass_kb, g_zombieclass[id])
6984 ArrayGetString(g_zclass_name, g_zombieclass[id], g_zombie_classname[id], charsmax(g_zombie_classname[]))
6985
6986 // Set zombie attributes based on the mode
6987 static sound[64]
6988 if (!silentmode)
6989 {
6990 if (nemesis)
6991 {
6992 // Nemesis
6993 g_nemesis[id] = true
6994
6995 // Set health [0 = auto]
6996 if (get_pcvar_num(cvar_nemhp) == 0)
6997 {
6998 if (get_pcvar_num(cvar_nembasehp) == 0)
6999 fm_set_user_health(id, ArrayGetCell(g_zclass_hp, 0) * fnGetAlive())
7000 else
7001 fm_set_user_health(id, get_pcvar_num(cvar_nembasehp) * fnGetAlive())
7002 }
7003 else
7004 fm_set_user_health(id, get_pcvar_num(cvar_nemhp))
7005
7006 // Set gravity, if frozen set the restore gravity value instead
7007 if (!g_frozen[id]) set_pev(id, pev_gravity, get_pcvar_float(cvar_nemgravity))
7008 else g_frozen_gravity[id] = get_pcvar_float(cvar_nemgravity)
7009
7010 // Set nemesis maxspeed
7011 ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
7012 }
7013 else if (assassin)
7014 {
7015 // Assassin
7016 g_assassin[id] = true
7017
7018 // Set health [0 = auto]
7019 if (get_pcvar_num(cvar_assahp) == 0)
7020 {
7021 if (get_pcvar_num(cvar_assabasehp) == 0)
7022 fm_set_user_health(id, ArrayGetCell(g_zclass_hp, 0) * fnGetAlive())
7023 else
7024 fm_set_user_health(id, get_pcvar_num(cvar_assabasehp) * fnGetAlive())
7025 }
7026 else
7027 fm_set_user_health(id, get_pcvar_num(cvar_assahp))
7028
7029 // Set gravity, if frozen set the restore gravity value instead
7030 if (!g_frozen[id]) set_pev(id, pev_gravity, get_pcvar_float(cvar_assagravity))
7031 else g_frozen_gravity[id] = get_pcvar_float(cvar_assagravity)
7032
7033 // Set assassin maxspeed
7034 ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
7035 }
7036 else if (fnGetZombies() == 1)
7037 {
7038 // First zombie
7039 g_firstzombie[id] = true
7040
7041 // Set health
7042 fm_set_user_health(id, floatround(float(ArrayGetCell(g_zclass_hp, g_zombieclass[id])) * get_pcvar_float(cvar_zombiefirsthp)))
7043
7044 // Set gravity, if frozen set the restore gravity value instead
7045 if (!g_frozen[id]) set_pev(id, pev_gravity, Float:ArrayGetCell(g_zclass_grav, g_zombieclass[id]))
7046 else g_frozen_gravity[id] = Float:ArrayGetCell(g_zclass_grav, g_zombieclass[id])
7047
7048 // Set zombie maxspeed
7049 ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
7050
7051 // Infection sound
7052 ArrayGetString(zombie_infect, random_num(0, ArraySize(zombie_infect) - 1), sound, charsmax(sound))
7053 emit_sound(id, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
7054 }
7055 else
7056 {
7057 // Infected by someone
7058
7059 // Set health
7060 fm_set_user_health(id, ArrayGetCell(g_zclass_hp, g_zombieclass[id]))
7061
7062 // Set gravity, if frozen set the restore gravity value instead
7063 if (!g_frozen[id]) set_pev(id, pev_gravity, Float:ArrayGetCell(g_zclass_grav, g_zombieclass[id]))
7064 else g_frozen_gravity[id] = Float:ArrayGetCell(g_zclass_grav, g_zombieclass[id])
7065
7066 // Set zombie maxspeed
7067 ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
7068
7069 // Infection sound
7070 ArrayGetString(zombie_infect, random_num(0, ArraySize(zombie_infect) - 1), sound, charsmax(sound))
7071 emit_sound(id, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
7072
7073 // Show Infection HUD notice
7074 set_hudmessage(255, 0, 0, HUD_INFECT_X, HUD_INFECT_Y, 0, 0.0, 5.0, 1.0, 1.0, -1)
7075
7076 if (infector) // infected by someone?
7077 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_INFECT2", g_playername[id], g_playername[infector])
7078 else
7079 ShowSyncHudMsg(0, g_MsgSync, "%L", LANG_PLAYER, "NOTICE_INFECT", g_playername[id])
7080 }
7081 }
7082 else
7083 {
7084 // Silent mode, no HUD messages, no infection sounds
7085
7086 // Set health
7087 fm_set_user_health(id, ArrayGetCell(g_zclass_hp, g_zombieclass[id]))
7088
7089 // Set gravity, if frozen set the restore gravity value instead
7090 if (!g_frozen[id]) set_pev(id, pev_gravity, Float:ArrayGetCell(g_zclass_grav, g_zombieclass[id]))
7091 else g_frozen_gravity[id] = Float:ArrayGetCell(g_zclass_grav, g_zombieclass[id])
7092
7093 // Set zombie maxspeed
7094 ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
7095 }
7096
7097 // Remove previous tasks
7098 remove_task(id+TASK_MODEL)
7099 remove_task(id+TASK_BLOOD)
7100 remove_task(id+TASK_AURA)
7101 remove_task(id+TASK_BURN)
7102
7103 // Switch to T
7104 if (fm_cs_get_user_team(id) != FM_CS_TEAM_T) // need to change team?
7105 {
7106 remove_task(id+TASK_TEAM)
7107 fm_cs_set_user_team(id, FM_CS_TEAM_T)
7108 fm_user_team_update(id)
7109 }
7110
7111 // Custom models stuff
7112 static currentmodel[32], tempmodel[32], already_has_model, i, iRand, size
7113 already_has_model = false
7114
7115 if (g_handle_models_on_separate_ent)
7116 {
7117 // Set the right model
7118 if (g_nemesis[id])
7119 {
7120 iRand = random_num(0, ArraySize(model_nemesis) - 1)
7121 ArrayGetString(model_nemesis, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7122 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_nemesis, iRand))
7123 }
7124 else if (g_assassin[id])
7125 {
7126 iRand = random_num(0, ArraySize(model_assassin) - 1)
7127 ArrayGetString(model_assassin, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7128 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_assassin, iRand))
7129 }
7130 else
7131 {
7132 if (get_pcvar_num(cvar_adminmodelszombie) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
7133 {
7134 iRand = random_num(0, ArraySize(model_admin_zombie) - 1)
7135 ArrayGetString(model_admin_zombie, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7136 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_zombie, iRand))
7137 }
7138 else
7139 {
7140 iRand = random_num(ArrayGetCell(g_zclass_modelsstart, g_zombieclass[id]), ArrayGetCell(g_zclass_modelsend, g_zombieclass[id]) - 1)
7141 ArrayGetString(g_zclass_playermodel, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7142 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_zclass_modelindex, iRand))
7143 }
7144 }
7145
7146 // Set model on player model entity
7147 fm_set_playermodel_ent(id)
7148
7149 // Nemesis glow / remove glow on player model entity, unless frozen
7150 if (!g_frozen[id])
7151 {
7152 if (g_nemesis[id] && get_pcvar_num(cvar_nemglow))
7153 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 250, 0 , 0, kRenderNormal, 25)
7154 else if (g_nemesis[id] && !(get_pcvar_num(cvar_nemglow)))
7155 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 0, 0 , 0, kRenderNormal, 25)
7156 else if (g_assassin[id] && get_pcvar_num(cvar_assaglow))
7157 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 255, 255, 0, kRenderNormal, 25)
7158 else
7159 fm_set_rendering(g_ent_playermodel[id])
7160 }
7161 }
7162 else
7163 {
7164 // Get current model for comparing it with the current one
7165 fm_cs_get_user_model(id, currentmodel, charsmax(currentmodel))
7166
7167 // Set the right model, after checking that we don't already have it
7168 if (g_nemesis[id])
7169 {
7170 size = ArraySize(model_nemesis)
7171 for (i = 0; i < size; i++)
7172 {
7173 ArrayGetString(model_nemesis, i, tempmodel, charsmax(tempmodel))
7174 if (equal(currentmodel, tempmodel)) already_has_model = true
7175 }
7176
7177 if (!already_has_model)
7178 {
7179 iRand = random_num(0, size - 1)
7180 ArrayGetString(model_nemesis, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7181 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_nemesis, iRand))
7182 }
7183 }
7184 else if (g_assassin[id])
7185 {
7186 size = ArraySize(model_assassin)
7187 for (i = 0; i < size; i++)
7188 {
7189 ArrayGetString(model_assassin, i, tempmodel, charsmax(tempmodel))
7190 if (equal(currentmodel, tempmodel)) already_has_model = true
7191 }
7192
7193 if (!already_has_model)
7194 {
7195 iRand = random_num(0, size - 1)
7196 ArrayGetString(model_assassin, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7197 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_assassin, iRand))
7198 }
7199 }
7200 else
7201 {
7202 if (get_pcvar_num(cvar_adminmodelszombie) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
7203 {
7204 size = ArraySize(model_admin_zombie)
7205 for (i = 0; i < size; i++)
7206 {
7207 ArrayGetString(model_admin_zombie, i, tempmodel, charsmax(tempmodel))
7208 if (equal(currentmodel, tempmodel)) already_has_model = true
7209 }
7210
7211 if (!already_has_model)
7212 {
7213 iRand = random_num(0, size - 1)
7214 ArrayGetString(model_admin_zombie, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7215 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_zombie, iRand))
7216 }
7217 }
7218 else
7219 {
7220 for (i = ArrayGetCell(g_zclass_modelsstart, g_zombieclass[id]); i < ArrayGetCell(g_zclass_modelsend, g_zombieclass[id]); i++)
7221 {
7222 ArrayGetString(g_zclass_playermodel, i, tempmodel, charsmax(tempmodel))
7223 if (equal(currentmodel, tempmodel)) already_has_model = true
7224 }
7225
7226 if (!already_has_model)
7227 {
7228 iRand = random_num(ArrayGetCell(g_zclass_modelsstart, g_zombieclass[id]), ArrayGetCell(g_zclass_modelsend, g_zombieclass[id]) - 1)
7229 ArrayGetString(g_zclass_playermodel, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7230 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_zclass_modelindex, iRand))
7231 }
7232 }
7233 }
7234
7235 // Need to change the model?
7236 if (!already_has_model)
7237 {
7238 // An additional delay is offset at round start
7239 // since SVC_BAD is more likely to be triggered there
7240 if (g_newround)
7241 set_task(5.0 * g_modelchange_delay, "fm_user_model_update", id+TASK_MODEL)
7242 else
7243 fm_user_model_update(id+TASK_MODEL)
7244 }
7245
7246 // Nemesis glow / remove glow, unless frozen
7247 if (!g_frozen[id])
7248 {
7249 if (g_nemesis[id] && get_pcvar_num(cvar_nemglow))
7250 fm_set_rendering(id, kRenderFxGlowShell, 250, 0, 0, kRenderNormal, 25)
7251 else if (g_nemesis[id] && !(get_pcvar_num(cvar_nemglow)))
7252 fm_set_rendering(id, kRenderFxGlowShell, 0, 0, 0, kRenderNormal, 25)
7253 if (g_assassin[id] && get_pcvar_num(cvar_assaglow))
7254 fm_set_rendering(id, kRenderFxGlowShell, 255, 255, 0, kRenderNormal, 25)
7255
7256 else if (!g_assassin[id] && !g_nemesis[id])
7257 fm_set_rendering(id)
7258 }
7259 }
7260
7261 // Remove any zoom (bugfix)
7262 cs_set_user_zoom(id, CS_RESET_ZOOM, 1)
7263
7264 // Remove armor
7265 cs_set_user_armor(id, 0, CS_ARMOR_NONE)
7266
7267 // Drop weapons when infected
7268 drop_weapons(id, 1)
7269 drop_weapons(id, 2)
7270
7271 // Strip zombies from guns and give them a knife
7272 fm_strip_user_weapons(id)
7273 fm_give_item(id, "weapon_knife")
7274
7275 // Fancy effects
7276 infection_effects(id)
7277
7278 // Nemesis aura task
7279 if (g_nemesis[id] && get_pcvar_num(cvar_nemaura))
7280 set_task(0.1, "zombie_aura", id+TASK_AURA, _, _, "b")
7281
7282 // Assassin aura task
7283 if (g_assassin[id] && get_pcvar_num(cvar_assaaura))
7284 set_task(0.1, "zombie_aura", id+TASK_AURA, _, _, "b")
7285
7286 // Remove CS nightvision if player owns one (bugfix)
7287 if (cs_get_user_nvg(id))
7288 {
7289 cs_set_user_nvg(id, 0)
7290 if (get_pcvar_num(cvar_customnvg)) remove_task(id+TASK_NVISION)
7291 else if (g_nvisionenabled[id]) set_user_gnvision(id, 0)
7292 }
7293
7294 // Give Zombies Night Vision?
7295 if (get_pcvar_num(cvar_nvggive))
7296 {
7297 g_nvision[id] = true
7298
7299 if (!g_isbot[id])
7300 {
7301 // Turn on Night Vision automatically?
7302 if (get_pcvar_num(cvar_nvggive) == 1)
7303 {
7304 g_nvisionenabled[id] = true
7305
7306 // Custom nvg?
7307 if (get_pcvar_num(cvar_customnvg))
7308 {
7309 remove_task(id+TASK_NVISION)
7310 set_task(0.1, "set_user_nvision", id+TASK_NVISION, _, _, "b")
7311 }
7312 else
7313 set_user_gnvision(id, 1)
7314 }
7315 // Turn off nightvision when infected (bugfix)
7316 else if (g_nvisionenabled[id])
7317 {
7318 if (get_pcvar_num(cvar_customnvg)) remove_task(id+TASK_NVISION)
7319 else set_user_gnvision(id, 0)
7320 g_nvisionenabled[id] = false
7321 }
7322 }
7323 else
7324 cs_set_user_nvg(id, 1); // turn on NVG for bots
7325 }
7326 // Disable nightvision when infected (bugfix)
7327 else if (g_nvision[id])
7328 {
7329 if (get_pcvar_num(cvar_customnvg)) remove_task(id+TASK_NVISION)
7330 else if (g_nvisionenabled[id]) set_user_gnvision(id, 0)
7331 g_nvision[id] = false
7332 g_nvisionenabled[id] = false
7333 }
7334
7335 // Set custom FOV?
7336 if (get_pcvar_num(cvar_zombiefov) != 90 && get_pcvar_num(cvar_zombiefov) != 0)
7337 {
7338 message_begin(MSG_ONE, g_msgSetFOV, _, id)
7339 write_byte(get_pcvar_num(cvar_zombiefov)) // fov angle
7340 message_end()
7341 }
7342
7343 // Call the bloody task
7344 if (!g_nemesis[id] && !g_nemesis[id] && get_pcvar_num(cvar_zombiebleeding))
7345 set_task(0.7, "make_blood", id+TASK_BLOOD, _, _, "b")
7346
7347 // Idle sounds task
7348 if (!g_nemesis[id] && !g_assassin[id])
7349 set_task(random_float(50.0, 70.0), "zombie_play_idle", id+TASK_BLOOD, _, _, "b")
7350
7351 // Turn off zombie's flashlight
7352 turn_off_flashlight(id)
7353
7354 // Post user infect forward
7355 ExecuteForward(g_fwUserInfected_post, g_fwDummyResult, id, infector, nemesis)
7356
7357 // Last Zombie Check
7358 fnCheckLastZombie()
7359}
7360
7361// Function Human Me (player id, turn into a survivor, silent mode)
7362humanme(id, survivor, sniper, silentmode)
7363{
7364 // User humanize attempt forward
7365 ExecuteForward(g_fwUserHumanize_attempt, g_fwDummyResult, id, survivor)
7366
7367 // One or more plugins blocked the "humanization". Only allow this after making sure it's
7368 // not going to leave us with no humans. Take into account a last player leaving case.
7369 // BUGFIX: only allow after a mode has started, to prevent blocking first survivor e.g.
7370 if (g_fwDummyResult >= ZP_PLUGIN_HANDLED && g_modestarted && fnGetHumans() > g_lastplayerleaving)
7371 return;
7372
7373 // Pre user humanize forward
7374 ExecuteForward(g_fwUserHumanized_pre, g_fwDummyResult, id, survivor)
7375
7376 // Remove previous tasks
7377 remove_task(id+TASK_MODEL)
7378 remove_task(id+TASK_BLOOD)
7379 remove_task(id+TASK_AURA)
7380 remove_task(id+TASK_BURN)
7381 remove_task(id+TASK_NVISION)
7382
7383 // Reset some vars
7384 g_zombie[id] = false
7385 g_nemesis[id] = false
7386 g_assassin[id] = false
7387 g_survivor[id] = false
7388 g_sniper[id] = false
7389 g_firstzombie[id] = false
7390 g_canbuy[id] = true
7391 g_buytime[id] = get_gametime()
7392
7393 // Remove survivor's aura (bugfix)
7394 set_pev(id, pev_effects, pev(id, pev_effects) &~ EF_BRIGHTLIGHT)
7395
7396 // Remove spawn protection (bugfix)
7397 g_nodamage[id] = false
7398 set_pev(id, pev_effects, pev(id, pev_effects) &~ EF_NODRAW)
7399
7400 // Reset burning duration counter (bugfix)
7401 g_burning_duration[id] = 0
7402
7403 // Remove CS nightvision if player owns one (bugfix)
7404 if (cs_get_user_nvg(id))
7405 {
7406 cs_set_user_nvg(id, 0)
7407 if (get_pcvar_num(cvar_customnvg)) remove_task(id+TASK_NVISION)
7408 else if (g_nvisionenabled[id]) set_user_gnvision(id, 0)
7409 }
7410
7411 // Drop previous weapons
7412 drop_weapons(id, 1)
7413 drop_weapons(id, 2)
7414
7415 // Strip off from weapons
7416 fm_strip_user_weapons(id)
7417 fm_give_item(id, "weapon_knife")
7418
7419 // Set human attributes based on the mode
7420 if (survivor)
7421 {
7422 // Survivor
7423 g_survivor[id] = true
7424
7425 // Set Health [0 = auto]
7426 if (get_pcvar_num(cvar_survhp) == 0)
7427 {
7428 if (get_pcvar_num(cvar_survbasehp) == 0)
7429 fm_set_user_health(id, get_pcvar_num(cvar_humanhp) * fnGetAlive())
7430 else
7431 fm_set_user_health(id, get_pcvar_num(cvar_survbasehp) * fnGetAlive())
7432 }
7433 else
7434 fm_set_user_health(id, get_pcvar_num(cvar_survhp))
7435
7436 // Set gravity, if frozen set the restore gravity value instead
7437 if (!g_frozen[id]) set_pev(id, pev_gravity, get_pcvar_float(cvar_survgravity))
7438 else g_frozen_gravity[id] = get_pcvar_float(cvar_survgravity)
7439
7440 // Set survivor maxspeed
7441 ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
7442
7443 // Give survivor his own weapon
7444 fm_give_item(id, "weapon_ak47")
7445 ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[CSW_AK47], AMMOTYPE[CSW_AK47], MAXBPAMMO[CSW_AK47])
7446
7447 // Turn off his flashlight
7448 turn_off_flashlight(id)
7449
7450 // Give the survivor a bright light
7451 if (get_pcvar_num(cvar_survaura)) set_pev(id, pev_effects, pev(id, pev_effects) | EF_BRIGHTLIGHT)
7452
7453 // Survivor bots will also need nightvision to see in the dark
7454 if (g_isbot[id])
7455 {
7456 g_nvision[id] = true
7457 cs_set_user_nvg(id, 1)
7458 }
7459 }
7460 else if (sniper)
7461 {
7462 // Sniper
7463 g_sniper[id] = true
7464
7465 // Set Health [0 = auto]
7466 if (get_pcvar_num(cvar_snihp) == 0)
7467 {
7468 if (get_pcvar_num(cvar_snibasehp) == 0)
7469 fm_set_user_health(id, get_pcvar_num(cvar_humanhp) * fnGetAlive())
7470 else
7471 fm_set_user_health(id, get_pcvar_num(cvar_snibasehp) * fnGetAlive())
7472 }
7473 else
7474 fm_set_user_health(id, get_pcvar_num(cvar_snihp))
7475
7476 // Set gravity, unless frozen
7477 if (!g_frozen[id]) set_pev(id, pev_gravity, get_pcvar_float(cvar_snigravity))
7478
7479 // Give sniper his own weapon
7480 fm_give_item(id, "weapon_awp")
7481 ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[CSW_AWP], AMMOTYPE[CSW_AWP], MAXBPAMMO[CSW_AWP])
7482
7483 // Turn off his flashlight
7484 turn_off_flashlight(id)
7485
7486 // Give the sniper a bright light
7487 if (get_pcvar_num(cvar_sniaura)) set_pev(id, pev_effects, pev(id, pev_effects) | EF_BRIGHTLIGHT)
7488
7489 // Sniper bots will also need nightvision to see in the dark
7490 if (g_isbot[id])
7491 {
7492 g_nvision[id] = true
7493 cs_set_user_nvg(id, 1)
7494 }
7495 }
7496 else
7497 {
7498 // Human taking an antidote
7499
7500 // Set health
7501 fm_set_user_health(id, get_pcvar_num(cvar_humanhp))
7502
7503 // Set gravity, if frozen set the restore gravity value instead
7504 if (!g_frozen[id]) set_pev(id, pev_gravity, get_pcvar_float(cvar_humangravity))
7505 else g_frozen_gravity[id] = get_pcvar_float(cvar_humangravity)
7506
7507 // Set human maxspeed
7508 ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
7509
7510 // Show custom buy menu?
7511 if (get_pcvar_num(cvar_buycustom))
7512 set_task(0.2, "show_menu_buy1", id+TASK_SPAWN)
7513
7514 // Silent mode = no HUD messages, no antidote sound
7515 if (!silentmode)
7516 {
7517 // Antidote sound
7518 static sound[64]
7519 ArrayGetString(sound_antidote, random_num(0, ArraySize(sound_antidote) - 1), sound, charsmax(sound))
7520 emit_sound(id, CHAN_ITEM, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
7521
7522 // Show Antidote HUD notice
7523 set_dhudmessage(10, 255, 235, HUD_INFECT_X, HUD_INFECT_Y, 1, 0.0, 5.0, 1.0, 1.0)
7524 show_dhudmessage(0, "%L", LANG_PLAYER, "NOTICE_ANTIDOTE", g_playername[id])
7525 }
7526 }
7527
7528 remove_freeze(id);
7529
7530 // Switch to CT
7531 if (fm_cs_get_user_team(id) != FM_CS_TEAM_CT) // need to change team?
7532 {
7533 remove_task(id+TASK_TEAM)
7534 fm_cs_set_user_team(id, FM_CS_TEAM_CT)
7535 fm_user_team_update(id)
7536 }
7537
7538 // Custom models stuff
7539 static currentmodel[32], tempmodel[32], already_has_model, i, iRand, size
7540 already_has_model = false
7541
7542 if (g_handle_models_on_separate_ent)
7543 {
7544 // Set the right model
7545 if (g_survivor[id])
7546 {
7547 iRand = random_num(0, ArraySize(model_survivor) - 1)
7548 ArrayGetString(model_survivor, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7549 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_survivor, iRand))
7550 }
7551 else if (g_sniper[id])
7552 {
7553 iRand = random_num(0, ArraySize(model_sniper) - 1)
7554 ArrayGetString(model_sniper, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7555 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_sniper, iRand))
7556 }
7557 else
7558 {
7559 if (get_pcvar_num(cvar_adminmodelshuman) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
7560 {
7561 iRand = random_num(0, ArraySize(model_admin_human) - 1)
7562 ArrayGetString(model_admin_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7563 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_human, iRand))
7564 }
7565 else
7566 {
7567 iRand = random_num(0, ArraySize(model_human) - 1)
7568 ArrayGetString(model_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7569 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_human, iRand))
7570 }
7571 }
7572
7573 // Set model on player model entity
7574 fm_set_playermodel_ent(id)
7575
7576 // Set survivor glow / remove glow on player model entity, unless frozen
7577 if (!g_frozen[id])
7578 {
7579 if (g_survivor[id] && get_pcvar_num(cvar_survglow))
7580 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 0, 0, 255, kRenderNormal, 25)
7581 else if (g_sniper[id] && get_pcvar_num(cvar_sniglow))
7582 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 0, 255, 0, kRenderNormal, 25)
7583 else
7584 fm_set_rendering(g_ent_playermodel[id])
7585 }
7586 }
7587 else
7588 {
7589 // Get current model for comparing it with the current one
7590 fm_cs_get_user_model(id, currentmodel, charsmax(currentmodel))
7591
7592 // Set the right model, after checking that we don't already have it
7593 if (g_survivor[id])
7594 {
7595 size = ArraySize(model_survivor)
7596 for (i = 0; i < size; i++)
7597 {
7598 ArrayGetString(model_survivor, i, tempmodel, charsmax(tempmodel))
7599 if (equal(currentmodel, tempmodel)) already_has_model = true
7600 }
7601
7602 if (!already_has_model)
7603 {
7604 iRand = random_num(0, size - 1)
7605 ArrayGetString(model_survivor, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7606 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_survivor, iRand))
7607 }
7608 }
7609 else if (g_sniper[id])
7610 {
7611 size = ArraySize(model_sniper)
7612 for (i = 0; i < size; i++)
7613 {
7614 ArrayGetString(model_sniper, i, tempmodel, charsmax(tempmodel))
7615 if (equal(currentmodel, tempmodel)) already_has_model = true
7616 }
7617
7618 if (!already_has_model)
7619 {
7620 iRand = random_num(0, size - 1)
7621 ArrayGetString(model_sniper, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7622 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_sniper, iRand))
7623 }
7624 }
7625 else
7626 {
7627 if (get_pcvar_num(cvar_adminmodelshuman) && (get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS]))
7628 {
7629 size = ArraySize(model_admin_human)
7630 for (i = 0; i < size; i++)
7631 {
7632 ArrayGetString(model_admin_human, i, tempmodel, charsmax(tempmodel))
7633 if (equal(currentmodel, tempmodel)) already_has_model = true
7634 }
7635
7636 if (!already_has_model)
7637 {
7638 iRand = random_num(0, size - 1)
7639 ArrayGetString(model_admin_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7640 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_admin_human, iRand))
7641 }
7642 }
7643 else
7644 {
7645 size = ArraySize(model_human)
7646 for (i = 0; i < size; i++)
7647 {
7648 ArrayGetString(model_human, i, tempmodel, charsmax(tempmodel))
7649 if (equal(currentmodel, tempmodel)) already_has_model = true
7650 }
7651
7652 if (!already_has_model)
7653 {
7654 iRand = random_num(0, size - 1)
7655 ArrayGetString(model_human, iRand, g_playermodel[id], charsmax(g_playermodel[]))
7656 if (g_set_modelindex_offset) fm_cs_set_user_model_index(id, ArrayGetCell(g_modelindex_human, iRand))
7657 }
7658 }
7659 }
7660
7661 // Need to change the model?
7662 if (!already_has_model)
7663 {
7664 // An additional delay is offset at round start
7665 // since SVC_BAD is more likely to be triggered there
7666 if (g_newround)
7667 set_task(5.0 * g_modelchange_delay, "fm_user_model_update", id+TASK_MODEL)
7668 else
7669 fm_user_model_update(id+TASK_MODEL)
7670 }
7671
7672 // Set survivor glow / remove glow, unless frozen
7673 if (!g_frozen[id])
7674 {
7675 if (g_survivor[id] && get_pcvar_num(cvar_survglow))
7676 fm_set_rendering(id, kRenderFxGlowShell, 0, 0, 255, kRenderNormal, 25)
7677 else if (g_sniper[id] && get_pcvar_num(cvar_sniglow))
7678 fm_set_rendering(id, kRenderFxGlowShell, 0, 255, 0, kRenderNormal, 25)
7679 else
7680 fm_set_rendering(id)
7681 }
7682 }
7683
7684 // Restore FOV?
7685 if (get_pcvar_num(cvar_zombiefov) != 90 && get_pcvar_num(cvar_zombiefov) != 0)
7686 {
7687 message_begin(MSG_ONE, g_msgSetFOV, _, id)
7688 write_byte(90) // angle
7689 message_end()
7690 }
7691
7692 // Disable nightvision when turning into human/survivor (bugfix)
7693 if (g_nvision[id])
7694 {
7695 if (get_pcvar_num(cvar_customnvg)) remove_task(id+TASK_NVISION)
7696 else if (g_nvisionenabled[id]) set_user_gnvision(id, 0)
7697 g_nvision[id] = false
7698 g_nvisionenabled[id] = false
7699 }
7700
7701 // Post user humanize forward
7702 ExecuteForward(g_fwUserHumanized_post, g_fwDummyResult, id, survivor)
7703
7704 // Last Zombie Check
7705 fnCheckLastZombie()
7706}
7707
7708/*================================================================================
7709 [Other Functions and Tasks]
7710=================================================================================*/
7711
7712public cache_cvars()
7713{
7714 g_cached_zombiesilent = get_pcvar_num(cvar_zombiesilent)
7715 g_cached_customflash = get_pcvar_num(cvar_customflash)
7716 g_cached_leapzombies = get_pcvar_num(cvar_leapzombies)
7717 g_cached_leapzombiescooldown = get_pcvar_float(cvar_leapzombiescooldown)
7718 g_cached_leapnemesis = get_pcvar_num(cvar_leapnemesis)
7719 g_cached_leapnemesiscooldown = get_pcvar_float(cvar_leapnemesiscooldown)
7720 g_cached_leapassassin = get_pcvar_num(cvar_leapassassin)
7721 g_cached_leapassassincooldown = get_pcvar_float(cvar_leapassassincooldown)
7722 g_cached_leapsurvivor = get_pcvar_num(cvar_leapsurvivor)
7723 g_cached_leapsurvivorcooldown = get_pcvar_float(cvar_leapsurvivorcooldown)
7724 g_cached_leapsniper = get_pcvar_num(cvar_leapsniper)
7725 g_cached_leapsnipercooldown = get_pcvar_float(cvar_leapsnipercooldown)
7726 g_cached_buytime = get_pcvar_float(cvar_buyzonetime)
7727}
7728
7729load_customization_from_files()
7730{
7731 // Build customization file path
7732 new path[64]
7733 get_configsdir(path, charsmax(path))
7734 format(path, charsmax(path), "%s/%s", path, ZP_CUSTOMIZATION_FILE)
7735
7736 // File not present
7737 if (!file_exists(path))
7738 {
7739 new error[100]
7740 formatex(error, charsmax(error), "Cannot load customization file %s!", path)
7741 set_fail_state(error)
7742 return;
7743 }
7744
7745 // Set up some vars to hold parsing info
7746 new linedata[1024], key[64], value[960], section, teams
7747
7748 // Open customization file for reading
7749 new file = fopen(path, "rt")
7750
7751 while (file && !feof(file))
7752 {
7753 // Read one line at a time
7754 fgets(file, linedata, charsmax(linedata))
7755
7756 // Replace newlines with a null character to prevent headaches
7757 replace(linedata, charsmax(linedata), "^n", "")
7758
7759 // Blank line or comment
7760 if (!linedata[0] || linedata[0] == ';') continue;
7761
7762 // New section starting
7763 if (linedata[0] == '[')
7764 {
7765 section++
7766 continue;
7767 }
7768
7769 // Get key and value(s)
7770 strtok(linedata, key, charsmax(key), value, charsmax(value), '=')
7771
7772 // Trim spaces
7773 trim(key)
7774 trim(value)
7775
7776 switch (section)
7777 {
7778 case SECTION_ACCESS_FLAGS:
7779 {
7780 if (equal(key, "ENABLE/DISABLE MOD"))
7781 g_access_flag[ACCESS_ENABLE_MOD] = read_flags(value)
7782 else if (equal(key, "ADMIN MENU"))
7783 g_access_flag[ACCESS_ADMIN_MENU] = read_flags(value)
7784 else if (equal(key, "ADMIN MODES MENU"))
7785 g_access_flag[ACCESS_ADMIN_MODES_MENU] = read_flags(value)
7786 else if (equal(key, "START MODE INFECTION"))
7787 g_access_flag[ACCESS_MODE_INFECTION] = read_flags(value)
7788 else if (equal(key, "START MODE NEMESIS"))
7789 g_access_flag[ACCESS_MODE_NEMESIS] = read_flags(value)
7790 else if (equal(key, "START MODE ASSASSIN"))
7791 g_access_flag[ACCESS_MODE_ASSASSIN] = read_flags(value)
7792 else if (equal(key, "START MODE SURVIVOR"))
7793 g_access_flag[ACCESS_MODE_SURVIVOR] = read_flags(value)
7794 else if (equal(key, "START MODE SNIPER"))
7795 g_access_flag[ACCESS_MODE_SNIPER] = read_flags(value)
7796 else if (equal(key, "START MODE SWARM"))
7797 g_access_flag[ACCESS_MODE_SWARM] = read_flags(value)
7798 else if (equal(key, "START MODE MULTI"))
7799 g_access_flag[ACCESS_MODE_MULTI] = read_flags(value)
7800 else if (equal(key, "START MODE PLAGUE"))
7801 g_access_flag[ACCESS_MODE_PLAGUE] = read_flags(value)
7802 else if (equal(key, "START MODE ARMAGEDDON"))
7803 g_access_flag[ACCESS_MODE_ARMAGEDDON] = read_flags(value)
7804 else if (equal(key, "START MODE APOCALYPSE"))
7805 g_access_flag[ACCESS_MODE_APOCALYPSE] = read_flags(value)
7806 else if (equal(key, "START MODE NIGHTMARE"))
7807 g_access_flag[ACCESS_MODE_NIGHTMARE] = read_flags(value)
7808 else if (equal(key, "MAKE ZOMBIE"))
7809 g_access_flag[ACCESS_MAKE_ZOMBIE] = read_flags(value)
7810 else if (equal(key, "MAKE HUMAN"))
7811 g_access_flag[ACCESS_MAKE_HUMAN] = read_flags(value)
7812 else if (equal(key, "MAKE NEMESIS"))
7813 g_access_flag[ACCESS_MAKE_NEMESIS] = read_flags(value)
7814 else if (equal(key, "MAKE ASSASSIN"))
7815 g_access_flag[ACCESS_MAKE_ASSASSIN] = read_flags(value)
7816 else if (equal(key, "MAKE SURVIVOR"))
7817 g_access_flag[ACCESS_MAKE_SURVIVOR] = read_flags(value)
7818 else if (equal(key, "MAKE SNIPER"))
7819 g_access_flag[ACCESS_MAKE_SNIPER] = read_flags(value)
7820 else if (equal(key, "RESPAWN PLAYERS"))
7821 g_access_flag[ACCESS_RESPAWN_PLAYERS] = read_flags(value)
7822 else if (equal(key, "ADMIN MODELS"))
7823 g_access_flag[ACCESS_ADMIN_MODELS] = read_flags(value)
7824 }
7825 case SECTION_PLAYER_MODELS:
7826 {
7827 if (equal(key, "HUMAN"))
7828 {
7829 // Parse models
7830 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
7831 {
7832 // Trim spaces
7833 trim(key)
7834 trim(value)
7835
7836 // Add to models array
7837 ArrayPushString(model_human, key)
7838 }
7839 }
7840 else if (equal(key, "NEMESIS"))
7841 {
7842 // Parse models
7843 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
7844 {
7845 // Trim spaces
7846 trim(key)
7847 trim(value)
7848
7849 // Add to models array
7850 ArrayPushString(model_nemesis, key)
7851 }
7852 }
7853 else if (equal(key, "ASSASSIN"))
7854 {
7855 // Parse models
7856 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
7857 {
7858 // Trim spaces
7859 trim(key)
7860 trim(value)
7861
7862 // Add to models array
7863 ArrayPushString(model_assassin, key)
7864 }
7865 }
7866 else if (equal(key, "SURVIVOR"))
7867 {
7868 // Parse models
7869 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
7870 {
7871 // Trim spaces
7872 trim(key)
7873 trim(value)
7874
7875 // Add to models array
7876 ArrayPushString(model_survivor, key)
7877 }
7878 }
7879 else if (equal(key, "SNIPER"))
7880 {
7881 // Parse models
7882 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
7883 {
7884 // Trim spaces
7885 trim(key)
7886 trim(value)
7887
7888 // Add to models array
7889 ArrayPushString(model_sniper, key)
7890 }
7891 }
7892 else if (equal(key, "ADMIN ZOMBIE"))
7893 {
7894 // Parse models
7895 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
7896 {
7897 // Trim spaces
7898 trim(key)
7899 trim(value)
7900
7901 // Add to models array
7902 ArrayPushString(model_admin_zombie, key)
7903 }
7904 }
7905 else if (equal(key, "ADMIN HUMAN"))
7906 {
7907 // Parse models
7908 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
7909 {
7910 // Trim spaces
7911 trim(key)
7912 trim(value)
7913
7914 // Add to models array
7915 ArrayPushString(model_admin_human, key)
7916 }
7917 }
7918 else if (equal(key, "FORCE CONSISTENCY"))
7919 g_force_consistency = str_to_num(value)
7920 else if (equal(key, "SAME MODELS FOR ALL"))
7921 g_same_models_for_all = str_to_num(value)
7922 else if (g_same_models_for_all && equal(key, "ZOMBIE"))
7923 {
7924 // Parse models
7925 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
7926 {
7927 // Trim spaces
7928 trim(key)
7929 trim(value)
7930
7931 // Add to models array
7932 ArrayPushString(g_zclass_playermodel, key)
7933
7934 // Precache model and retrieve its modelindex
7935 formatex(linedata, charsmax(linedata), "models/player/%s/%s.mdl", key, key)
7936 ArrayPushCell(g_zclass_modelindex, engfunc(EngFunc_PrecacheModel, linedata))
7937 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, linedata)
7938 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, linedata)
7939 // Precache modelT.mdl files too
7940 copy(linedata[strlen(linedata)-4], charsmax(linedata) - (strlen(linedata)-4), "T.mdl")
7941 if (file_exists(linedata)) engfunc(EngFunc_PrecacheModel, linedata)
7942 }
7943 }
7944 }
7945 case SECTION_WEAPON_MODELS:
7946 {
7947 if (equal(key, "V_KNIFE HUMAN"))
7948 copy(model_vknife_human, charsmax(model_vknife_human), value)
7949 else if (equal(key, "V_KNIFE NEMESIS"))
7950 copy(model_vknife_nemesis, charsmax(model_vknife_nemesis), value)
7951 else if (equal(key, "V_KNIFE ASSASSIN"))
7952 copy(model_vknife_assassin, charsmax(model_vknife_assassin), value)
7953 else if (equal(key, "V_M249 SURVIVOR")) // backwards compatibility with old configs
7954 copy(model_vweapon_survivor, charsmax(model_vweapon_survivor), value)
7955 else if (equal(key, "V_WEAPON SURVIVOR"))
7956 copy(model_vweapon_survivor, charsmax(model_vweapon_survivor), value)
7957 else if (equal(key, "V_AWP SNIPER"))
7958 copy(model_vawp_sniper, charsmax(model_vawp_sniper), value)
7959 else if (equal(key, "P_AWP SNIPER"))
7960 copy(model_pawp_sniper, charsmax(model_pawp_sniper), value)
7961 else if (equal(key, "GRENADE INFECT"))
7962 copy(model_grenade_infect, charsmax(model_grenade_infect), value)
7963 else if (equal(key, "GRENADE FIRE"))
7964 copy(model_grenade_fire, charsmax(model_grenade_fire), value)
7965 else if (equal(key, "GRENADE FROST"))
7966 copy(model_grenade_frost, charsmax(model_grenade_frost), value)
7967 else if (equal(key, "GRENADE FLARE"))
7968 copy(model_grenade_flare, charsmax(model_grenade_flare), value)
7969 else if (equal(key, "V_KNIFE ADMIN HUMAN"))
7970 copy(model_vknife_admin_human, charsmax(model_vknife_admin_human), value)
7971 else if (equal(key, "V_KNIFE ADMIN ZOMBIE"))
7972 copy(model_vknife_admin_zombie, charsmax(model_vknife_admin_zombie), value)
7973 }
7974 case SECTION_GRENADE_SPRITES:
7975 {
7976 if (equal(key, "TRAIL"))
7977 copy(sprite_grenade_trail, charsmax(sprite_grenade_trail), value)
7978 else if (equal(key, "RING"))
7979 copy(sprite_grenade_ring, charsmax(sprite_grenade_ring), value)
7980 else if (equal(key, "FIRE"))
7981 copy(sprite_grenade_fire, charsmax(sprite_grenade_fire), value)
7982 else if (equal(key, "SMOKE"))
7983 copy(sprite_grenade_smoke, charsmax(sprite_grenade_smoke), value)
7984 else if (equal(key, "GLASS"))
7985 copy(sprite_grenade_glass, charsmax(sprite_grenade_glass), value)
7986 }
7987 case SECTION_SOUNDS:
7988 {
7989 if (equal(key, "WIN ZOMBIES"))
7990 {
7991 // Parse sounds
7992 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
7993 {
7994 // Trim spaces
7995 trim(key)
7996 trim(value)
7997
7998 // Add to sounds array
7999 ArrayPushString(sound_win_zombies, key)
8000 ArrayPushCell(sound_win_zombies_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8001 }
8002 }
8003 else if (equal(key, "WIN HUMANS"))
8004 {
8005 // Parse sounds
8006 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8007 {
8008 // Trim spaces
8009 trim(key)
8010 trim(value)
8011
8012 // Add to sounds array
8013 ArrayPushString(sound_win_humans, key)
8014 ArrayPushCell(sound_win_humans_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8015 }
8016 }
8017 else if (equal(key, "WIN NO ONE"))
8018 {
8019 // Parse sounds
8020 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8021 {
8022 // Trim spaces
8023 trim(key)
8024 trim(value)
8025
8026 // Add to sounds array
8027 ArrayPushString(sound_win_no_one, key)
8028 ArrayPushCell(sound_win_no_one_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8029 }
8030 }
8031 else if (equal(key, "ZOMBIE INFECT"))
8032 {
8033 // Parse sounds
8034 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8035 {
8036 // Trim spaces
8037 trim(key)
8038 trim(value)
8039
8040 // Add to sounds array
8041 ArrayPushString(zombie_infect, key)
8042 }
8043 }
8044 else if (equal(key, "ZOMBIE PAIN"))
8045 {
8046 // Parse sounds
8047 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8048 {
8049 // Trim spaces
8050 trim(key)
8051 trim(value)
8052
8053 // Add to sounds array
8054 ArrayPushString(zombie_pain, key)
8055 }
8056 }
8057 else if (equal(key, "NEMESIS PAIN"))
8058 {
8059 // Parse sounds
8060 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8061 {
8062 // Trim spaces
8063 trim(key)
8064 trim(value)
8065
8066 // Add to sounds array
8067 ArrayPushString(nemesis_pain, key)
8068 }
8069 }
8070 else if (equal(key, "ASSASSIN PAIN"))
8071 {
8072 // Parse sounds
8073 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8074 {
8075 // Trim spaces
8076 trim(key)
8077 trim(value)
8078
8079 // Add to sounds array
8080 ArrayPushString(assassin_pain, key)
8081 }
8082 }
8083 else if (equal(key, "ZOMBIE DIE"))
8084 {
8085 // Parse sounds
8086 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8087 {
8088 // Trim spaces
8089 trim(key)
8090 trim(value)
8091
8092 // Add to sounds array
8093 ArrayPushString(zombie_die, key)
8094 }
8095 }
8096 else if (equal(key, "ZOMBIE FALL"))
8097 {
8098 // Parse sounds
8099 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8100 {
8101 // Trim spaces
8102 trim(key)
8103 trim(value)
8104
8105 // Add to sounds array
8106 ArrayPushString(zombie_fall, key)
8107 }
8108 }
8109 else if (equal(key, "ZOMBIE MISS SLASH"))
8110 {
8111 // Parse sounds
8112 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8113 {
8114 // Trim spaces
8115 trim(key)
8116 trim(value)
8117
8118 // Add to sounds array
8119 ArrayPushString(zombie_miss_slash, key)
8120 }
8121 }
8122 else if (equal(key, "ZOMBIE MISS WALL"))
8123 {
8124 // Parse sounds
8125 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8126 {
8127 // Trim spaces
8128 trim(key)
8129 trim(value)
8130
8131 // Add to sounds array
8132 ArrayPushString(zombie_miss_wall, key)
8133 }
8134 }
8135 else if (equal(key, "ZOMBIE HIT NORMAL"))
8136 {
8137 // Parse sounds
8138 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8139 {
8140 // Trim spaces
8141 trim(key)
8142 trim(value)
8143
8144 // Add to sounds array
8145 ArrayPushString(zombie_hit_normal, key)
8146 }
8147 }
8148 else if (equal(key, "ZOMBIE HIT STAB"))
8149 {
8150 // Parse sounds
8151 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8152 {
8153 // Trim spaces
8154 trim(key)
8155 trim(value)
8156
8157 // Add to sounds array
8158 ArrayPushString(zombie_hit_stab, key)
8159 }
8160 }
8161 else if (equal(key, "ZOMBIE IDLE"))
8162 {
8163 // Parse sounds
8164 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8165 {
8166 // Trim spaces
8167 trim(key)
8168 trim(value)
8169
8170 // Add to sounds array
8171 ArrayPushString(zombie_idle, key)
8172 }
8173 }
8174 else if (equal(key, "ZOMBIE IDLE LAST"))
8175 {
8176 // Parse sounds
8177 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8178 {
8179 // Trim spaces
8180 trim(key)
8181 trim(value)
8182
8183 // Add to sounds array
8184 ArrayPushString(zombie_idle_last, key)
8185 }
8186 }
8187 else if (equal(key, "ZOMBIE MADNESS"))
8188 {
8189 // Parse sounds
8190 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8191 {
8192 // Trim spaces
8193 trim(key)
8194 trim(value)
8195
8196 // Add to sounds array
8197 ArrayPushString(zombie_madness, key)
8198 }
8199 }
8200 else if (equal(key, "ROUND NEMESIS"))
8201 {
8202 // Parse sounds
8203 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8204 {
8205 // Trim spaces
8206 trim(key)
8207 trim(value)
8208
8209 // Add to sounds array
8210 ArrayPushString(sound_nemesis, key)
8211 }
8212 }
8213 else if (equal(key, "ROUND ASSASSIN"))
8214 {
8215 // Parse sounds
8216 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8217 {
8218 // Trim spaces
8219 trim(key)
8220 trim(value)
8221
8222 // Add to sounds array
8223 ArrayPushString(sound_assassin, key)
8224 }
8225 }
8226 else if (equal(key, "ROUND SURVIVOR"))
8227 {
8228 // Parse sounds
8229 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8230 {
8231 // Trim spaces
8232 trim(key)
8233 trim(value)
8234
8235 // Add to sounds array
8236 ArrayPushString(sound_survivor, key)
8237 }
8238 }
8239 else if (equal(key, "ROUND SNIPER"))
8240 {
8241 // Parse sounds
8242 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8243 {
8244 // Trim spaces
8245 trim(key)
8246 trim(value)
8247
8248 // Add to sounds array
8249 ArrayPushString(sound_sniper, key)
8250 }
8251 }
8252 else if (equal(key, "ROUND SWARM"))
8253 {
8254 // Parse sounds
8255 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8256 {
8257 // Trim spaces
8258 trim(key)
8259 trim(value)
8260
8261 // Add to sounds array
8262 ArrayPushString(sound_swarm, key)
8263 }
8264 }
8265 else if (equal(key, "ROUND MULTI"))
8266 {
8267 // Parse sounds
8268 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8269 {
8270 // Trim spaces
8271 trim(key)
8272 trim(value)
8273
8274 // Add to sounds array
8275 ArrayPushString(sound_multi, key)
8276 }
8277 }
8278 else if (equal(key, "ROUND PLAGUE"))
8279 {
8280 // Parse sounds
8281 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8282 {
8283 // Trim spaces
8284 trim(key)
8285 trim(value)
8286
8287 // Add to sounds array
8288 ArrayPushString(sound_plague, key)
8289 }
8290 }
8291 else if (equal(key, "ROUND ARMAGEDDON"))
8292 {
8293 // Parse sounds
8294 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8295 {
8296 // Trim spaces
8297 trim(key)
8298 trim(value)
8299
8300 // Add to sounds array
8301 ArrayPushString(sound_armageddon, key)
8302 }
8303 }
8304 else if (equal(key, "ROUND APOCALYPSE"))
8305 {
8306 // Parse sounds
8307 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8308 {
8309 // Trim spaces
8310 trim(key)
8311 trim(value)
8312
8313 // Add to sounds array
8314 ArrayPushString(sound_apocalypse, key)
8315 }
8316 }
8317 else if (equal(key, "ROUND NIGHTMARE"))
8318 {
8319 // Parse sounds
8320 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8321 {
8322 // Trim spaces
8323 trim(key)
8324 trim(value)
8325
8326 // Add to sounds array
8327 ArrayPushString(sound_nightmare, key)
8328 }
8329 }
8330 else if (equal(key, "GRENADE INFECT EXPLODE"))
8331 {
8332 // Parse sounds
8333 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8334 {
8335 // Trim spaces
8336 trim(key)
8337 trim(value)
8338
8339 // Add to sounds array
8340 ArrayPushString(grenade_infect, key)
8341 }
8342 }
8343 else if (equal(key, "GRENADE INFECT PLAYER"))
8344 {
8345 // Parse sounds
8346 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8347 {
8348 // Trim spaces
8349 trim(key)
8350 trim(value)
8351
8352 // Add to sounds array
8353 ArrayPushString(grenade_infect_player, key)
8354 }
8355 }
8356 else if (equal(key, "GRENADE FIRE EXPLODE"))
8357 {
8358 // Parse sounds
8359 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8360 {
8361 // Trim spaces
8362 trim(key)
8363 trim(value)
8364
8365 // Add to sounds array
8366 ArrayPushString(grenade_fire, key)
8367 }
8368 }
8369 else if (equal(key, "GRENADE FIRE PLAYER"))
8370 {
8371 // Parse sounds
8372 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8373 {
8374 // Trim spaces
8375 trim(key)
8376 trim(value)
8377
8378 // Add to sounds array
8379 ArrayPushString(grenade_fire_player, key)
8380 }
8381 }
8382 else if (equal(key, "GRENADE FROST EXPLODE"))
8383 {
8384 // Parse sounds
8385 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8386 {
8387 // Trim spaces
8388 trim(key)
8389 trim(value)
8390
8391 // Add to sounds array
8392 ArrayPushString(grenade_frost, key)
8393 }
8394 }
8395 else if (equal(key, "GRENADE FROST PLAYER"))
8396 {
8397 // Parse sounds
8398 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8399 {
8400 // Trim spaces
8401 trim(key)
8402 trim(value)
8403
8404 // Add to sounds array
8405 ArrayPushString(grenade_frost_player, key)
8406 }
8407 }
8408 else if (equal(key, "GRENADE FROST BREAK"))
8409 {
8410 // Parse sounds
8411 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8412 {
8413 // Trim spaces
8414 trim(key)
8415 trim(value)
8416
8417 // Add to sounds array
8418 ArrayPushString(grenade_frost_break, key)
8419 }
8420 }
8421 else if (equal(key, "GRENADE FLARE"))
8422 {
8423 // Parse sounds
8424 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8425 {
8426 // Trim spaces
8427 trim(key)
8428 trim(value)
8429
8430 // Add to sounds array
8431 ArrayPushString(grenade_flare, key)
8432 }
8433 }
8434 else if (equal(key, "ANTIDOTE"))
8435 {
8436 // Parse sounds
8437 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8438 {
8439 // Trim spaces
8440 trim(key)
8441 trim(value)
8442
8443 // Add to sounds array
8444 ArrayPushString(sound_antidote, key)
8445 }
8446 }
8447 else if (equal(key, "THUNDER"))
8448 {
8449 // Parse sounds
8450 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8451 {
8452 // Trim spaces
8453 trim(key)
8454 trim(value)
8455
8456 // Add to sounds array
8457 ArrayPushString(sound_thunder, key)
8458 }
8459 }
8460 }
8461 case SECTION_AMBIENCE_SOUNDS:
8462 {
8463 if (equal(key, "INFECTION ENABLE"))
8464 g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION] = str_to_num(value)
8465 else if (g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION] && equal(key, "INFECTION SOUNDS"))
8466 {
8467 // Parse sounds
8468 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8469 {
8470 // Trim spaces
8471 trim(key)
8472 trim(value)
8473
8474 // Add to sounds array
8475 ArrayPushString(sound_ambience1, key)
8476 ArrayPushCell(sound_ambience1_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8477 }
8478 }
8479 else if (g_ambience_sounds[AMBIENCE_SOUNDS_INFECTION] && equal(key, "INFECTION DURATIONS"))
8480 {
8481 // Parse sounds
8482 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8483 {
8484 // Trim spaces
8485 trim(key)
8486 trim(value)
8487
8488 // Add to sounds array
8489 ArrayPushCell(sound_ambience1_duration, str_to_num(key))
8490 }
8491 }
8492 else if (equal(key, "NEMESIS ENABLE"))
8493 g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS] = str_to_num(value)
8494 else if (g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS] && equal(key, "NEMESIS SOUNDS"))
8495 {
8496 // Parse sounds
8497 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8498 {
8499 // Trim spaces
8500 trim(key)
8501 trim(value)
8502
8503 // Add to sounds array
8504 ArrayPushString(sound_ambience2, key)
8505 ArrayPushCell(sound_ambience2_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8506 }
8507 }
8508 else if (g_ambience_sounds[AMBIENCE_SOUNDS_NEMESIS] && equal(key, "NEMESIS DURATIONS"))
8509 {
8510 // Parse sounds
8511 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8512 {
8513 // Trim spaces
8514 trim(key)
8515 trim(value)
8516
8517 // Add to sounds array
8518 ArrayPushCell(sound_ambience2_duration, str_to_num(key))
8519 }
8520 }
8521 else if (equal(key, "ASSASSIN ENABLE"))
8522 g_ambience_sounds[AMBIENCE_SOUNDS_ASSASSIN] = str_to_num(value)
8523 else if (g_ambience_sounds[AMBIENCE_SOUNDS_ASSASSIN] && equal(key, "ASSASSIN SOUNDS"))
8524 {
8525 // Parse sounds
8526 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8527 {
8528 // Trim spaces
8529 trim(key)
8530 trim(value)
8531
8532 // Add to sounds array
8533 ArrayPushString(sound_ambience6, key)
8534 ArrayPushCell(sound_ambience6_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8535 }
8536 }
8537 else if (g_ambience_sounds[AMBIENCE_SOUNDS_ASSASSIN] && equal(key, "ASSASSIN DURATIONS"))
8538 {
8539 // Parse sounds
8540 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8541 {
8542 // Trim spaces
8543 trim(key)
8544 trim(value)
8545
8546 // Add to sounds array
8547 ArrayPushCell(sound_ambience6_duration, str_to_num(key))
8548 }
8549 }
8550 else if (equal(key, "SURVIVOR ENABLE"))
8551 g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR] = str_to_num(value)
8552 else if (g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR] && equal(key, "SURVIVOR SOUNDS"))
8553 {
8554 // Parse sounds
8555 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8556 {
8557 // Trim spaces
8558 trim(key)
8559 trim(value)
8560
8561 // Add to sounds array
8562 ArrayPushString(sound_ambience3, key)
8563 ArrayPushCell(sound_ambience3_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8564 }
8565 }
8566 else if (g_ambience_sounds[AMBIENCE_SOUNDS_SURVIVOR] && equal(key, "SURVIVOR DURATIONS"))
8567 {
8568 // Parse sounds
8569 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8570 {
8571 // Trim spaces
8572 trim(key)
8573 trim(value)
8574
8575 // Add to sounds array
8576 ArrayPushCell(sound_ambience3_duration, str_to_num(key))
8577 }
8578 }
8579 else if (equal(key, "SNIPER ENABLE"))
8580 g_ambience_sounds[AMBIENCE_SOUNDS_SNIPER] = str_to_num(value)
8581 else if (g_ambience_sounds[AMBIENCE_SOUNDS_SNIPER] && equal(key, "SNIPER SOUNDS"))
8582 {
8583 // Parse sounds
8584 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8585 {
8586 // Trim spaces
8587 trim(key)
8588 trim(value)
8589
8590 // Add to sounds array
8591 ArrayPushString(sound_ambience7, key)
8592 ArrayPushCell(sound_ambience7_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8593 }
8594 }
8595 else if (g_ambience_sounds[AMBIENCE_SOUNDS_SNIPER] && equal(key, "SNIPER DURATIONS"))
8596 {
8597 // Parse sounds
8598 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8599 {
8600 // Trim spaces
8601 trim(key)
8602 trim(value)
8603
8604 // Add to sounds array
8605 ArrayPushCell(sound_ambience7_duration, str_to_num(key))
8606 }
8607 }
8608 else if (equal(key, "SWARM ENABLE"))
8609 g_ambience_sounds[AMBIENCE_SOUNDS_SWARM] = str_to_num(value)
8610 else if (g_ambience_sounds[AMBIENCE_SOUNDS_SWARM] && equal(key, "SWARM SOUNDS"))
8611 {
8612 // Parse sounds
8613 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8614 {
8615 // Trim spaces
8616 trim(key)
8617 trim(value)
8618
8619 // Add to sounds array
8620 ArrayPushString(sound_ambience4, key)
8621 ArrayPushCell(sound_ambience4_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8622 }
8623 }
8624 else if (g_ambience_sounds[AMBIENCE_SOUNDS_SWARM] && equal(key, "SWARM DURATIONS"))
8625 {
8626 // Parse sounds
8627 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8628 {
8629 // Trim spaces
8630 trim(key)
8631 trim(value)
8632
8633 // Add to sounds array
8634 ArrayPushCell(sound_ambience4_duration, str_to_num(key))
8635 }
8636 }
8637 else if (equal(key, "PLAGUE ENABLE"))
8638 g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE] = str_to_num(value)
8639 else if (g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE] && equal(key, "PLAGUE SOUNDS"))
8640 {
8641 // Parse sounds
8642 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8643 {
8644 // Trim spaces
8645 trim(key)
8646 trim(value)
8647
8648 // Add to sounds array
8649 ArrayPushString(sound_ambience5, key)
8650 ArrayPushCell(sound_ambience5_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8651 }
8652 }
8653 else if (g_ambience_sounds[AMBIENCE_SOUNDS_PLAGUE] && equal(key, "PLAGUE DURATIONS"))
8654 {
8655 // Parse sounds
8656 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8657 {
8658 // Trim spaces
8659 trim(key)
8660 trim(value)
8661
8662 // Add to sounds array
8663 ArrayPushCell(sound_ambience5_duration, str_to_num(key))
8664 }
8665 }
8666 else if (equal(key, "ARMAGEDDON ENABLE"))
8667 g_ambience_sounds[AMBIENCE_SOUNDS_ARMAGEDDON] = str_to_num(value)
8668 else if (g_ambience_sounds[AMBIENCE_SOUNDS_ARMAGEDDON] && equal(key, "ARMAGEDDON SOUNDS"))
8669 {
8670 // Parse sounds
8671 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8672 {
8673 // Trim spaces
8674 trim(key)
8675 trim(value)
8676
8677 // Add to sounds array
8678 ArrayPushString(sound_ambience8, key)
8679 ArrayPushCell(sound_ambience8_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8680 }
8681 }
8682 else if (g_ambience_sounds[AMBIENCE_SOUNDS_ARMAGEDDON] && equal(key, "ARMAGEDDON DURATIONS"))
8683 {
8684 // Parse sounds
8685 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8686 {
8687 // Trim spaces
8688 trim(key)
8689 trim(value)
8690
8691 // Add to sounds array
8692 ArrayPushCell(sound_ambience8_duration, str_to_num(key))
8693 }
8694 }
8695 else if (equal(key, "APOCALYPSE ENABLE"))
8696 g_ambience_sounds[AMBIENCE_SOUNDS_APOCALYPSE] = str_to_num(value)
8697 else if (g_ambience_sounds[AMBIENCE_SOUNDS_APOCALYPSE] && equal(key, "APOCALYPSE SOUNDS"))
8698 {
8699 // Parse sounds
8700 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8701 {
8702 // Trim spaces
8703 trim(key)
8704 trim(value)
8705
8706 // Add to sounds array
8707 ArrayPushString(sound_ambience9, key)
8708 ArrayPushCell(sound_ambience9_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8709 }
8710 }
8711 else if (g_ambience_sounds[AMBIENCE_SOUNDS_APOCALYPSE] && equal(key, "APOCALYPSE DURATIONS"))
8712 {
8713 // Parse sounds
8714 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8715 {
8716 // Trim spaces
8717 trim(key)
8718 trim(value)
8719
8720 // Add to sounds array
8721 ArrayPushCell(sound_ambience9_duration, str_to_num(key))
8722 }
8723 }
8724 else if (equal(key, "NIGHTMARE ENABLE"))
8725 g_ambience_sounds[AMBIENCE_SOUNDS_NIGHTMARE] = str_to_num(value)
8726 else if (g_ambience_sounds[AMBIENCE_SOUNDS_NIGHTMARE] && equal(key, "NIGHTMARE SOUNDS"))
8727 {
8728 // Parse sounds
8729 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8730 {
8731 // Trim spaces
8732 trim(key)
8733 trim(value)
8734
8735 // Add to sounds array
8736 ArrayPushString(sound_ambience10, key)
8737 ArrayPushCell(sound_ambience10_ismp3, equal(key[strlen(key)-4], ".mp3") ? 1 : 0)
8738 }
8739 }
8740 else if (g_ambience_sounds[AMBIENCE_SOUNDS_NIGHTMARE] && equal(key, "NIGHTMARE DURATIONS"))
8741 {
8742 // Parse sounds
8743 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8744 {
8745 // Trim spaces
8746 trim(key)
8747 trim(value)
8748
8749 // Add to sounds array
8750 ArrayPushCell(sound_ambience10_duration, str_to_num(key))
8751 }
8752 }
8753 }
8754 case SECTION_BUY_MENU_WEAPONS:
8755 {
8756 if (equal(key, "PRIMARY"))
8757 {
8758 // Parse weapons
8759 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8760 {
8761 // Trim spaces
8762 trim(key)
8763 trim(value)
8764
8765 // Add to weapons array
8766 ArrayPushString(g_primary_items, key)
8767 ArrayPushCell(g_primary_weaponids, cs_weapon_name_to_id(key))
8768 }
8769 }
8770 else if (equal(key, "SECONDARY"))
8771 {
8772 // Parse weapons
8773 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8774 {
8775 // Trim spaces
8776 trim(key)
8777 trim(value)
8778
8779 // Add to weapons array
8780 ArrayPushString(g_secondary_items, key)
8781 ArrayPushCell(g_secondary_weaponids, cs_weapon_name_to_id(key))
8782 }
8783 }
8784 else if (equal(key, "ADDITIONAL ITEMS"))
8785 {
8786 // Parse weapons
8787 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8788 {
8789 // Trim spaces
8790 trim(key)
8791 trim(value)
8792
8793 // Add to weapons array
8794 ArrayPushString(g_additional_items, key)
8795 }
8796 }
8797 }
8798 case SECTION_EXTRA_ITEMS_WEAPONS:
8799 {
8800 if (equal(key, "NAMES"))
8801 {
8802 // Parse weapon items
8803 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8804 {
8805 // Trim spaces
8806 trim(key)
8807 trim(value)
8808
8809 // Add to weapons array
8810 ArrayPushString(g_extraweapon_names, key)
8811 }
8812 }
8813 else if (equal(key, "ITEMS"))
8814 {
8815 // Parse weapon items
8816 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8817 {
8818 // Trim spaces
8819 trim(key)
8820 trim(value)
8821
8822 // Add to weapons array
8823 ArrayPushString(g_extraweapon_items, key)
8824 }
8825 }
8826 else if (equal(key, "COSTS"))
8827 {
8828 // Parse weapon items
8829 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8830 {
8831 // Trim spaces
8832 trim(key)
8833 trim(value)
8834
8835 // Add to weapons array
8836 ArrayPushCell(g_extraweapon_costs, str_to_num(key))
8837 }
8838 }
8839 }
8840 case SECTION_HARD_CODED_ITEMS_COSTS:
8841 {
8842 if (equal(key, "NIGHT VISION"))
8843 g_extra_costs2[EXTRA_NVISION] = str_to_num(value)
8844 else if (equal(key, "ANTIDOTE"))
8845 g_extra_costs2[EXTRA_ANTIDOTE] = str_to_num(value)
8846 else if (equal(key, "ZOMBIE MADNESS"))
8847 g_extra_costs2[EXTRA_MADNESS] = str_to_num(value)
8848 else if (equal(key, "INFECTION BOMB"))
8849 g_extra_costs2[EXTRA_INFBOMB] = str_to_num(value)
8850 }
8851 case SECTION_WEATHER_EFFECTS:
8852 {
8853 if (equal(key, "RAIN"))
8854 g_ambience_rain = str_to_num(value)
8855 else if (equal(key, "SNOW"))
8856 g_ambience_snow = str_to_num(value)
8857 else if (equal(key, "FOG"))
8858 g_ambience_fog = str_to_num(value)
8859 else if (equal(key, "FOG DENSITY"))
8860 copy(g_fog_density, charsmax(g_fog_density), value)
8861 else if (equal(key, "FOG COLOR"))
8862 copy(g_fog_color, charsmax(g_fog_color), value)
8863 }
8864 case SECTION_SKY:
8865 {
8866 if (equal(key, "ENABLE"))
8867 g_sky_enable = str_to_num(value)
8868 else if (equal(key, "SKY NAMES"))
8869 {
8870 // Parse sky names
8871 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8872 {
8873 // Trim spaces
8874 trim(key)
8875 trim(value)
8876
8877 // Add to skies array
8878 ArrayPushString(g_sky_names, key)
8879
8880 // Preache custom sky files
8881 formatex(linedata, charsmax(linedata), "gfx/env/%sbk.tga", key)
8882 engfunc(EngFunc_PrecacheGeneric, linedata)
8883 formatex(linedata, charsmax(linedata), "gfx/env/%sdn.tga", key)
8884 engfunc(EngFunc_PrecacheGeneric, linedata)
8885 formatex(linedata, charsmax(linedata), "gfx/env/%sft.tga", key)
8886 engfunc(EngFunc_PrecacheGeneric, linedata)
8887 formatex(linedata, charsmax(linedata), "gfx/env/%slf.tga", key)
8888 engfunc(EngFunc_PrecacheGeneric, linedata)
8889 formatex(linedata, charsmax(linedata), "gfx/env/%srt.tga", key)
8890 engfunc(EngFunc_PrecacheGeneric, linedata)
8891 formatex(linedata, charsmax(linedata), "gfx/env/%sup.tga", key)
8892 engfunc(EngFunc_PrecacheGeneric, linedata)
8893 }
8894 }
8895 }
8896 case SECTION_LIGHTNING:
8897 {
8898 if (equal(key, "LIGHTS"))
8899 {
8900 // Parse lights
8901 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8902 {
8903 // Trim spaces
8904 trim(key)
8905 trim(value)
8906
8907 // Add to lightning array
8908 ArrayPushString(lights_thunder, key)
8909 }
8910 }
8911 }
8912 case SECTION_ZOMBIE_DECALS:
8913 {
8914 if (equal(key, "DECALS"))
8915 {
8916 // Parse decals
8917 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8918 {
8919 // Trim spaces
8920 trim(key)
8921 trim(value)
8922
8923 // Add to zombie decals array
8924 ArrayPushCell(zombie_decals, str_to_num(key))
8925 }
8926 }
8927 }
8928 case SECTION_KNOCKBACK:
8929 {
8930 // Format weapon entity name
8931 strtolower(key)
8932 format(key, charsmax(key), "weapon_%s", key)
8933
8934 // Add value to knockback power array
8935 kb_weapon_power[cs_weapon_name_to_id(key)] = str_to_float(value)
8936 }
8937 case SECTION_OBJECTIVE_ENTS:
8938 {
8939 if (equal(key, "CLASSNAMES"))
8940 {
8941 // Parse classnames
8942 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
8943 {
8944 // Trim spaces
8945 trim(key)
8946 trim(value)
8947
8948 // Add to objective ents array
8949 ArrayPushString(g_objective_ents, key)
8950 }
8951 }
8952 }
8953 case SECTION_SVC_BAD:
8954 {
8955 if (equal(key, "MODELCHANGE DELAY"))
8956 g_modelchange_delay = str_to_float(value)
8957 else if (equal(key, "HANDLE MODELS ON SEPARATE ENT"))
8958 g_handle_models_on_separate_ent = str_to_num(value)
8959 else if (equal(key, "SET MODELINDEX OFFSET"))
8960 g_set_modelindex_offset = str_to_num(value)
8961 }
8962 }
8963 }
8964 if (file) fclose(file)
8965
8966 // Build zombie classes file path
8967 get_configsdir(path, charsmax(path))
8968 format(path, charsmax(path), "%s/%s", path, ZP_ZOMBIECLASSES_FILE)
8969
8970 // Parse if present
8971 if (file_exists(path))
8972 {
8973 // Open zombie classes file for reading
8974 file = fopen(path, "rt")
8975
8976 while (file && !feof(file))
8977 {
8978 // Read one line at a time
8979 fgets(file, linedata, charsmax(linedata))
8980
8981 // Replace newlines with a null character to prevent headaches
8982 replace(linedata, charsmax(linedata), "^n", "")
8983
8984 // Blank line or comment
8985 if (!linedata[0] || linedata[0] == ';') continue;
8986
8987 // New class starting
8988 if (linedata[0] == '[')
8989 {
8990 // Remove first and last characters (braces)
8991 linedata[strlen(linedata) - 1] = 0
8992 copy(linedata, charsmax(linedata), linedata[1])
8993
8994 // Store its real name for future reference
8995 ArrayPushString(g_zclass2_realname, linedata)
8996 continue;
8997 }
8998
8999 // Get key and value(s)
9000 strtok(linedata, key, charsmax(key), value, charsmax(value), '=')
9001
9002 // Trim spaces
9003 trim(key)
9004 trim(value)
9005
9006 if (equal(key, "NAME"))
9007 ArrayPushString(g_zclass2_name, value)
9008 else if (equal(key, "INFO"))
9009 ArrayPushString(g_zclass2_info, value)
9010 else if (equal(key, "MODELS"))
9011 {
9012 // Set models start index
9013 ArrayPushCell(g_zclass2_modelsstart, ArraySize(g_zclass2_playermodel))
9014
9015 // Parse class models
9016 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
9017 {
9018 // Trim spaces
9019 trim(key)
9020 trim(value)
9021
9022 // Add to class models array
9023 ArrayPushString(g_zclass2_playermodel, key)
9024 ArrayPushCell(g_zclass2_modelindex, -1)
9025 }
9026
9027 // Set models end index
9028 ArrayPushCell(g_zclass2_modelsend, ArraySize(g_zclass2_playermodel))
9029 }
9030 else if (equal(key, "CLAWMODEL"))
9031 ArrayPushString(g_zclass2_clawmodel, value)
9032 else if (equal(key, "HEALTH"))
9033 ArrayPushCell(g_zclass2_hp, str_to_num(value))
9034 else if (equal(key, "SPEED"))
9035 ArrayPushCell(g_zclass2_spd, str_to_num(value))
9036 else if (equal(key, "GRAVITY"))
9037 ArrayPushCell(g_zclass2_grav, str_to_float(value))
9038 else if (equal(key, "KNOCKBACK"))
9039 ArrayPushCell(g_zclass2_kb, str_to_float(value))
9040 }
9041 if (file) fclose(file)
9042 }
9043
9044 // Build extra items file path
9045 get_configsdir(path, charsmax(path))
9046 format(path, charsmax(path), "%s/%s", path, ZP_EXTRAITEMS_FILE)
9047
9048 // Parse if present
9049 if (file_exists(path))
9050 {
9051 // Open extra items file for reading
9052 file = fopen(path, "rt")
9053
9054 while (file && !feof(file))
9055 {
9056 // Read one line at a time
9057 fgets(file, linedata, charsmax(linedata))
9058
9059 // Replace newlines with a null character to prevent headaches
9060 replace(linedata, charsmax(linedata), "^n", "")
9061
9062 // Blank line or comment
9063 if (!linedata[0] || linedata[0] == ';') continue;
9064
9065 // New item starting
9066 if (linedata[0] == '[')
9067 {
9068 // Remove first and last characters (braces)
9069 linedata[strlen(linedata) - 1] = 0
9070 copy(linedata, charsmax(linedata), linedata[1])
9071
9072 // Store its real name for future reference
9073 ArrayPushString(g_extraitem2_realname, linedata)
9074 continue;
9075 }
9076
9077 // Get key and value(s)
9078 strtok(linedata, key, charsmax(key), value, charsmax(value), '=')
9079
9080 // Trim spaces
9081 trim(key)
9082 trim(value)
9083
9084 if (equal(key, "NAME"))
9085 ArrayPushString(g_extraitem2_name, value)
9086 else if (equal(key, "COST"))
9087 ArrayPushCell(g_extraitem2_cost, str_to_num(value))
9088 else if (equal(key, "TEAMS"))
9089 {
9090 // Clear teams bitsum
9091 teams = 0
9092
9093 // Parse teams
9094 while (value[0] != 0 && strtok(value, key, charsmax(key), value, charsmax(value), ','))
9095 {
9096 // Trim spaces
9097 trim(key)
9098 trim(value)
9099
9100 if (equal(key, ZP_TEAM_NAMES[ZP_TEAM_ZOMBIE]))
9101 teams |= ZP_TEAM_ZOMBIE
9102 else if (equal(key, ZP_TEAM_NAMES[ZP_TEAM_HUMAN]))
9103 teams |= ZP_TEAM_HUMAN
9104 else if (equal(key, ZP_TEAM_NAMES[ZP_TEAM_NEMESIS]))
9105 teams |= ZP_TEAM_NEMESIS
9106 else if (equal(key, ZP_TEAM_NAMES[ZP_TEAM_ASSASSIN]))
9107 teams |= ZP_TEAM_ASSASSIN
9108 else if (equal(key, ZP_TEAM_NAMES[ZP_TEAM_SURVIVOR]))
9109 teams |= ZP_TEAM_SURVIVOR
9110 else if (equal(key, ZP_TEAM_NAMES[ZP_TEAM_SNIPER]))
9111 teams |= ZP_TEAM_SNIPER
9112 }
9113
9114 // Add to teams array
9115 ArrayPushCell(g_extraitem2_team, teams)
9116 }
9117 }
9118 if (file) fclose(file)
9119 }
9120}
9121
9122save_customization()
9123{
9124 new i, k, buffer[512]
9125
9126 // Build zombie classes file path
9127 new path[64]
9128 get_configsdir(path, charsmax(path))
9129 format(path, charsmax(path), "%s/%s", path, ZP_ZOMBIECLASSES_FILE)
9130
9131 // Open zombie classes file for appending data
9132 new file = fopen(path, "at"), size = ArraySize(g_zclass_name)
9133
9134 // Add any new zombie classes data at the end if needed
9135 for (i = 0; i < size; i++)
9136 {
9137 if (ArrayGetCell(g_zclass_new, i))
9138 {
9139 // Add real name
9140 ArrayGetString(g_zclass_name, i, buffer, charsmax(buffer))
9141 format(buffer, charsmax(buffer), "^n[%s]", buffer)
9142 fputs(file, buffer)
9143
9144 // Add caption
9145 ArrayGetString(g_zclass_name, i, buffer, charsmax(buffer))
9146 format(buffer, charsmax(buffer), "^nNAME = %s", buffer)
9147 fputs(file, buffer)
9148
9149 // Add info
9150 ArrayGetString(g_zclass_info, i, buffer, charsmax(buffer))
9151 format(buffer, charsmax(buffer), "^nINFO = %s", buffer)
9152 fputs(file, buffer)
9153
9154 // Add models
9155 for (k = ArrayGetCell(g_zclass_modelsstart, i); k < ArrayGetCell(g_zclass_modelsend, i); k++)
9156 {
9157 if (k == ArrayGetCell(g_zclass_modelsstart, i))
9158 {
9159 // First model, overwrite buffer
9160 ArrayGetString(g_zclass_playermodel, k, buffer, charsmax(buffer))
9161 }
9162 else
9163 {
9164 // Successive models, append to buffer
9165 ArrayGetString(g_zclass_playermodel, k, path, charsmax(path))
9166 format(buffer, charsmax(buffer), "%s , %s", buffer, path)
9167 }
9168 }
9169 format(buffer, charsmax(buffer), "^nMODELS = %s", buffer)
9170 fputs(file, buffer)
9171
9172 // Add clawmodel
9173 ArrayGetString(g_zclass_clawmodel, i, buffer, charsmax(buffer))
9174 format(buffer, charsmax(buffer), "^nCLAWMODEL = %s", buffer)
9175 fputs(file, buffer)
9176
9177 // Add health
9178 formatex(buffer, charsmax(buffer), "^nHEALTH = %d", ArrayGetCell(g_zclass_hp, i))
9179 fputs(file, buffer)
9180
9181 // Add speed
9182 formatex(buffer, charsmax(buffer), "^nSPEED = %d", ArrayGetCell(g_zclass_spd, i))
9183 fputs(file, buffer)
9184
9185 // Add gravity
9186 formatex(buffer, charsmax(buffer), "^nGRAVITY = %.2f", Float:ArrayGetCell(g_zclass_grav, i))
9187 fputs(file, buffer)
9188
9189 // Add knockback
9190 formatex(buffer, charsmax(buffer), "^nKNOCKBACK = %.2f^n", Float:ArrayGetCell(g_zclass_kb, i))
9191 fputs(file, buffer)
9192 }
9193 }
9194 fclose(file)
9195
9196 // Build extra items file path
9197 get_configsdir(path, charsmax(path))
9198 format(path, charsmax(path), "%s/%s", path, ZP_EXTRAITEMS_FILE)
9199
9200 // Open extra items file for appending data
9201 file = fopen(path, "at")
9202 size = ArraySize(g_extraitem_name)
9203
9204 // Add any new extra items data at the end if needed
9205 for (i = EXTRAS_CUSTOM_STARTID; i < size; i++)
9206 {
9207 if (ArrayGetCell(g_extraitem_new, i))
9208 {
9209 // Add real name
9210 ArrayGetString(g_extraitem_name, i, buffer, charsmax(buffer))
9211 format(buffer, charsmax(buffer), "^n[%s]", buffer)
9212 fputs(file, buffer)
9213
9214 // Add caption
9215 ArrayGetString(g_extraitem_name, i, buffer, charsmax(buffer))
9216 format(buffer, charsmax(buffer), "^nNAME = %s", buffer)
9217 fputs(file, buffer)
9218
9219 // Add cost
9220 formatex(buffer, charsmax(buffer), "^nCOST = %d", ArrayGetCell(g_extraitem_cost, i))
9221 fputs(file, buffer)
9222
9223 // Add team
9224 formatex(buffer, charsmax(buffer), "^nTEAMS = %s^n", ZP_TEAM_NAMES[ArrayGetCell(g_extraitem_team, i)])
9225 fputs(file, buffer)
9226 }
9227 }
9228 fclose(file)
9229
9230 // Free arrays containing class/item overrides
9231 ArrayDestroy(g_zclass2_realname)
9232 ArrayDestroy(g_zclass2_name)
9233 ArrayDestroy(g_zclass2_info)
9234 ArrayDestroy(g_zclass2_modelsstart)
9235 ArrayDestroy(g_zclass2_modelsend)
9236 ArrayDestroy(g_zclass2_playermodel)
9237 ArrayDestroy(g_zclass2_modelindex)
9238 ArrayDestroy(g_zclass2_clawmodel)
9239 ArrayDestroy(g_zclass2_hp)
9240 ArrayDestroy(g_zclass2_spd)
9241 ArrayDestroy(g_zclass2_grav)
9242 ArrayDestroy(g_zclass2_kb)
9243 ArrayDestroy(g_zclass_new)
9244 ArrayDestroy(g_extraitem2_realname)
9245 ArrayDestroy(g_extraitem2_name)
9246 ArrayDestroy(g_extraitem2_cost)
9247 ArrayDestroy(g_extraitem2_team)
9248 ArrayDestroy(g_extraitem_new)
9249}
9250
9251// Register Ham Forwards for CZ bots
9252public register_ham_czbots(id)
9253{
9254 // Make sure it's a CZ bot and it's still connected
9255 if (g_hamczbots || !g_isconnected[id] || !get_pcvar_num(cvar_botquota))
9256 return;
9257
9258 RegisterHamFromEntity(Ham_Spawn, id, "fw_PlayerSpawn_Post", 1)
9259 RegisterHamFromEntity(Ham_Killed, id, "fw_PlayerKilled")
9260 RegisterHamFromEntity(Ham_Killed, id, "fw_PlayerKilled_Post", 1)
9261 RegisterHamFromEntity(Ham_TakeDamage, id, "fw_TakeDamage")
9262 RegisterHamFromEntity(Ham_TakeDamage, id, "fw_TakeDamage_Post", 1)
9263 RegisterHamFromEntity(Ham_TraceAttack, id, "fw_TraceAttack")
9264 RegisterHamFromEntity(Ham_Player_ResetMaxSpeed, id, "fw_ResetMaxSpeed_Post", 1)
9265
9266 // Ham forwards for CZ bots succesfully registered
9267 g_hamczbots = true
9268
9269 // If the bot has already spawned, call the forward manually for him
9270 if (is_user_alive(id)) fw_PlayerSpawn_Post(id)
9271}
9272
9273// Disable minmodels task
9274public disable_minmodels(id)
9275{
9276 if (!g_isconnected[id]) return;
9277 client_cmd(id, "cl_minmodels 0")
9278}
9279
9280// Bots automatically buy extra items
9281public bot_buy_extras(taskid)
9282{
9283 // Nemesis or Survivor bots have nothing to buy by default
9284 if (!g_isalive[ID_SPAWN] || g_survivor[ID_SPAWN] || g_sniper[ID_SPAWN] || g_nemesis[ID_SPAWN] || g_assassin[ID_SPAWN])
9285 return;
9286
9287 if (!g_zombie[ID_SPAWN]) // human bots
9288 {
9289 // Attempt to buy Night Vision
9290 buy_extra_item(ID_SPAWN, EXTRA_NVISION)
9291
9292 // Attempt to buy a weapon
9293 buy_extra_item(ID_SPAWN, random_num(EXTRA_WEAPONS_STARTID, EXTRAS_CUSTOM_STARTID-1))
9294 }
9295 else // zombie bots
9296 {
9297 // Attempt to buy an Antidote
9298 buy_extra_item(ID_SPAWN, EXTRA_ANTIDOTE)
9299 }
9300}
9301
9302// Refill BP Ammo Task
9303public refill_bpammo(const args[], id)
9304{
9305 // Player died or turned into a zombie
9306 if (!g_isalive[id] || g_zombie[id])
9307 return;
9308
9309 set_msg_block(g_msgAmmoPickup, BLOCK_ONCE)
9310 ExecuteHamB(Ham_GiveAmmo, id, MAXBPAMMO[REFILL_WEAPONID], AMMOTYPE[REFILL_WEAPONID], MAXBPAMMO[REFILL_WEAPONID])
9311}
9312
9313// Balance Teams Task
9314balance_teams()
9315{
9316 // Get amount of users playing
9317 static iPlayersnum
9318 iPlayersnum = fnGetPlaying()
9319
9320 // No players, don't bother
9321 if (iPlayersnum < 1) return;
9322
9323 // Split players evenly
9324 static iTerrors, iMaxTerrors, id, team[33]
9325 iMaxTerrors = iPlayersnum/2
9326 iTerrors = 0
9327
9328 // First, set everyone to CT
9329 for (id = 1; id <= g_maxplayers; id++)
9330 {
9331 // Skip if not connected
9332 if (!g_isconnected[id])
9333 continue;
9334
9335 team[id] = fm_cs_get_user_team(id)
9336
9337 // Skip if not playing
9338 if (team[id] == FM_CS_TEAM_SPECTATOR || team[id] == FM_CS_TEAM_UNASSIGNED)
9339 continue;
9340
9341 // Set team
9342 remove_task(id+TASK_TEAM)
9343 fm_cs_set_user_team(id, FM_CS_TEAM_CT)
9344 team[id] = FM_CS_TEAM_CT
9345 }
9346
9347 // Then randomly set half of the players to Terrorists
9348 while (iTerrors < iMaxTerrors)
9349 {
9350 // Keep looping through all players
9351 if (++id > g_maxplayers) id = 1
9352
9353 // Skip if not connected
9354 if (!g_isconnected[id])
9355 continue;
9356
9357 // Skip if not playing or already a Terrorist
9358 if (team[id] != FM_CS_TEAM_CT)
9359 continue;
9360
9361 // Random chance
9362 if (random_num(0, 1))
9363 {
9364 fm_cs_set_user_team(id, FM_CS_TEAM_T)
9365 team[id] = FM_CS_TEAM_T
9366 iTerrors++
9367 }
9368 }
9369}
9370
9371// Welcome Message Task
9372public welcome_msg()
9373{
9374 // Show mod info
9375 zp_colored_print(0, "^x01**** ^x04%s^x01 ****", g_modname)
9376 zp_colored_print(0, "^x04[ZP]^x01 %L", LANG_PLAYER, "NOTICE_INFO1")
9377 if (!get_pcvar_num(cvar_infammo)) zp_colored_print(0, "^x04[ZP]^x01 %L", LANG_PLAYER, "NOTICE_INFO2")
9378
9379 // Show T-virus HUD notice
9380 set_dhudmessage(0, 125, 200, HUD_EVENT_X, HUD_EVENT_Y, 1, 0.0, 3.0, 2.0, 1.0)
9381 show_dhudmessage(0, "%L", LANG_PLAYER, "NOTICE_VIRUS_FREE")
9382}
9383
9384// Respawn Player Task (deathmatch)
9385public respawn_player_task(taskid)
9386{
9387 // Already alive or round ended
9388 if (g_isalive[ID_SPAWN] || g_endround)
9389 return;
9390
9391 // Get player's team
9392 static team
9393 team = fm_cs_get_user_team(ID_SPAWN)
9394
9395 // Player moved to spectators
9396 if (team == FM_CS_TEAM_SPECTATOR || team == FM_CS_TEAM_UNASSIGNED)
9397 return;
9398
9399 // Respawn player automatically if allowed on current round
9400 if ((!g_survround || get_pcvar_num(cvar_allowrespawnsurv))
9401 && (!g_sniround || get_pcvar_num(cvar_allowrespawnsni))
9402 && (!g_swarmround || get_pcvar_num(cvar_allowrespawnswarm))
9403 && (!g_nemround || get_pcvar_num(cvar_allowrespawnnem))
9404 && (!g_assaround || get_pcvar_num(cvar_allowrespawnassa))
9405 && (!g_plagueround || get_pcvar_num(cvar_allowrespawnplague))
9406 && (!g_armageround || get_pcvar_num(cvar_allowrespawnarmage))
9407 && (!g_apocround || get_pcvar_num(cvar_allowrespawnapoc))
9408 && (!g_nightround || get_pcvar_num(cvar_allowrespawnnight)))
9409 {
9410
9411 // Infection rounds = none of the above
9412 if (!get_pcvar_num(cvar_allowrespawninfection) && !g_survround && !g_sniround && !g_nemround && !g_assaround && !g_swarmround && !g_plagueround && !g_armageround && !g_apocround && !g_nightround)
9413 return;
9414
9415 // Respawn if only the last human is left? (ignore this setting on survivor rounds)
9416 if (!g_survround && !g_sniround && !get_pcvar_num(cvar_respawnafterlast) && fnGetHumans() <= 1)
9417 return;
9418
9419 // Respawn as zombie?
9420 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))
9421 g_respawn_as_zombie[ID_SPAWN] = true
9422
9423 // Override respawn as zombie setting on nemesis and survivor rounds
9424 if (g_survround || g_sniround) g_respawn_as_zombie[ID_SPAWN] = true
9425 else if (g_nemround || g_assaround) g_respawn_as_zombie[ID_SPAWN] = false
9426
9427 respawn_player_manually(ID_SPAWN)
9428 }
9429}
9430
9431// Respawn Player Check Task (if killed by worldspawn)
9432public respawn_player_check_task(taskid)
9433{
9434 // Successfully spawned or round ended
9435 if (g_isalive[ID_SPAWN] || g_endround)
9436 return;
9437
9438 // Get player's team
9439 static team
9440 team = fm_cs_get_user_team(ID_SPAWN)
9441
9442 // Player moved to spectators
9443 if (team == FM_CS_TEAM_SPECTATOR || team == FM_CS_TEAM_UNASSIGNED)
9444 return;
9445
9446 // If player was being spawned as a zombie, set the flag again
9447 if (g_zombie[ID_SPAWN]) g_respawn_as_zombie[ID_SPAWN] = true
9448 else g_respawn_as_zombie[ID_SPAWN] = false
9449
9450 respawn_player_manually(ID_SPAWN)
9451}
9452
9453// Respawn Player Manually (called after respawn checks are done)
9454respawn_player_manually(id)
9455{
9456 // Set proper team before respawning, so that the TeamInfo message that's sent doesn't confuse PODBots
9457 if (g_respawn_as_zombie[id])
9458 fm_cs_set_user_team(id, FM_CS_TEAM_T)
9459 else
9460 fm_cs_set_user_team(id, FM_CS_TEAM_CT)
9461
9462 // Respawning a player has never been so easy
9463 ExecuteHamB(Ham_CS_RoundRespawn, id)
9464}
9465
9466// Check Round Task -check that we still have both zombies and humans on a round-
9467check_round(leaving_player)
9468{
9469 // Round ended or make_a_zombie task still active
9470 if (g_endround || task_exists(TASK_MAKEZOMBIE))
9471 return;
9472
9473 // Get alive players count
9474 static iPlayersnum, id
9475 iPlayersnum = fnGetAlive()
9476
9477 // Last alive player, don't bother
9478 if (iPlayersnum < 2)
9479 return;
9480
9481 // Last zombie disconnecting
9482 if (g_zombie[leaving_player] && fnGetZombies() == 1)
9483 {
9484 // Only one CT left, don't bother
9485 if (fnGetHumans() == 1 && fnGetCTs() == 1)
9486 return;
9487
9488 // Pick a random one to take his place
9489 while ((id = fnGetRandomAlive(random_num(1, iPlayersnum))) == leaving_player ) { /* keep looping */ }
9490
9491 // Show last zombie left notice
9492 zp_colored_print(0, "^x04[ZP]^x01 %L", LANG_PLAYER, "LAST_ZOMBIE_LEFT", g_playername[id])
9493
9494 // Set player leaving flag
9495 g_lastplayerleaving = true
9496
9497 // Turn into a Nemesis or just a zombie?
9498 if (g_nemesis[leaving_player])
9499 zombieme(id, 0, 1, 0, 0, 0)
9500 else if (g_assassin[leaving_player])
9501 zombieme(id, 0, 0, 1, 0, 0)
9502 else
9503 zombieme(id, 0, 0, 0, 0, 0)
9504
9505 // Remove player leaving flag
9506 g_lastplayerleaving = false
9507
9508 // If Nemesis, set chosen player's health to that of the one who's leaving
9509 if (get_pcvar_num(cvar_keephealthondisconnect) && g_nemesis[leaving_player])
9510 fm_set_user_health(id, pev(leaving_player, pev_health))
9511
9512 // If Assassin, set chosen player's health to that of the one who's leaving
9513 if (get_pcvar_num(cvar_keephealthondisconnect) && g_assassin[leaving_player])
9514 fm_set_user_health(id, pev(leaving_player, pev_health))
9515 }
9516
9517 // Last human disconnecting
9518 else if (!g_zombie[leaving_player] && fnGetHumans() == 1)
9519 {
9520 // Only one T left, don't bother
9521 if (fnGetZombies() == 1 && fnGetTs() == 1)
9522 return;
9523
9524 // Pick a random one to take his place
9525 while ((id = fnGetRandomAlive(random_num(1, iPlayersnum))) == leaving_player ) { /* keep looping */ }
9526
9527 // Show last human left notice
9528 zp_colored_print(0, "^x04[ZP]^x01 %L", LANG_PLAYER, "LAST_HUMAN_LEFT", g_playername[id])
9529
9530 // Set player leaving flag
9531 g_lastplayerleaving = true
9532
9533 // Turn into a Survivor or just a human?
9534 if (g_survivor[leaving_player])
9535 humanme(id, 1, 0, 0)
9536 else if (g_sniper[leaving_player])
9537 humanme(id, 0, 1, 0)
9538 else
9539 humanme(id, 0, 0, 0)
9540
9541 // Remove player leaving flag
9542 g_lastplayerleaving = false
9543
9544 // If Survivor, set chosen player's health to that of the one who's leaving
9545 if (get_pcvar_num(cvar_keephealthondisconnect) && g_survivor[leaving_player])
9546 fm_set_user_health(id, pev(leaving_player, pev_health))
9547
9548 // If Sniper, set chosen player's health to that of the one who's leaving
9549 if (get_pcvar_num(cvar_keephealthondisconnect) && g_sniper[leaving_player])
9550 fm_set_user_health(id, pev(leaving_player, pev_health))
9551 }
9552}
9553
9554// Lighting Effects Task
9555public lighting_effects()
9556{
9557 // Cache some CVAR values at every 5 secs
9558 cache_cvars()
9559
9560 // Get lighting style
9561 static lighting[2]
9562 get_pcvar_string(cvar_lighting, lighting, charsmax(lighting))
9563 strtolower(lighting)
9564
9565 // Lighting disabled? ["0"]
9566 if (lighting[0] == '0')
9567 return;
9568
9569 // Darkest light settings?
9570 if (lighting[0] >= 'a' && lighting[0] <= 'd')
9571 {
9572 static thunderclap_in_progress, Float:thunder
9573 thunderclap_in_progress = task_exists(TASK_THUNDER)
9574 thunder = get_pcvar_float(cvar_thunder)
9575
9576 // Set thunderclap tasks if not existant
9577 if (thunder > 0.0 && !task_exists(TASK_THUNDER_PRE) && !thunderclap_in_progress)
9578 {
9579 g_lights_i = 0
9580 ArrayGetString(lights_thunder, random_num(0, ArraySize(lights_thunder) - 1), g_lights_cycle, charsmax(g_lights_cycle))
9581 g_lights_cycle_len = strlen(g_lights_cycle)
9582 set_task(thunder, "thunderclap", TASK_THUNDER_PRE)
9583 }
9584
9585 // Set lighting only when no thunderclaps are going on
9586 if (!thunderclap_in_progress) engfunc(EngFunc_LightStyle, 0, g_assaround ? "a" : lighting) // no lighting in assassin round
9587 }
9588 else
9589 {
9590 // Remove thunderclap tasks
9591 remove_task(TASK_THUNDER_PRE)
9592 remove_task(TASK_THUNDER)
9593
9594 // Set lighting
9595 engfunc(EngFunc_LightStyle, 0, g_assaround ? "a" : lighting) // no lighting in assassin round
9596 }
9597}
9598
9599// Thunderclap task
9600public thunderclap()
9601{
9602 // Play thunder sound
9603 if (g_lights_i == 0)
9604 {
9605 static sound[64]
9606 ArrayGetString(sound_thunder, random_num(0, ArraySize(sound_thunder) - 1), sound, charsmax(sound))
9607 PlaySound(sound)
9608 }
9609
9610 // Set lighting
9611 static light[2]
9612 light[0] = g_lights_cycle[g_lights_i]
9613 engfunc(EngFunc_LightStyle, 0, light)
9614
9615 g_lights_i++
9616
9617 // Lighting cycle end?
9618 if (g_lights_i >= g_lights_cycle_len)
9619 {
9620 remove_task(TASK_THUNDER)
9621 lighting_effects()
9622 }
9623 // Lighting cycle start?
9624 else if (!task_exists(TASK_THUNDER))
9625 set_task(0.1, "thunderclap", TASK_THUNDER, _, _, "b")
9626}
9627
9628// Ambience Sound Effects Task
9629public ambience_sound_effects(taskid)
9630{
9631 // Play a random sound depending on the round
9632 static sound[64], iRand, duration
9633
9634 if (g_nemround) // Nemesis Mode
9635 {
9636 iRand = random_num(0, ArraySize(sound_ambience2) - 1)
9637 ArrayGetString(sound_ambience2, iRand, sound, charsmax(sound))
9638 duration = ArrayGetCell(sound_ambience2_duration, iRand)
9639 }
9640 if (g_assaround) // Assassin Mode
9641 {
9642 iRand = random_num(0, ArraySize(sound_ambience6) - 1)
9643 ArrayGetString(sound_ambience6, iRand, sound, charsmax(sound))
9644 duration = ArrayGetCell(sound_ambience6_duration, iRand)
9645 }
9646 else if (g_survround) // Survivor Mode
9647 {
9648 iRand = random_num(0, ArraySize(sound_ambience3) - 1)
9649 ArrayGetString(sound_ambience3, iRand, sound, charsmax(sound))
9650 duration = ArrayGetCell(sound_ambience3_duration, iRand)
9651 }
9652 else if (g_sniround) // Sniper Mode
9653 {
9654 iRand = random_num(0, ArraySize(sound_ambience7) - 1)
9655 ArrayGetString(sound_ambience7, iRand, sound, charsmax(sound))
9656 duration = ArrayGetCell(sound_ambience7_duration, iRand)
9657 }
9658 else if (g_swarmround) // Swarm Mode
9659 {
9660 iRand = random_num(0, ArraySize(sound_ambience4) - 1)
9661 ArrayGetString(sound_ambience4, iRand, sound, charsmax(sound))
9662 duration = ArrayGetCell(sound_ambience4_duration, iRand)
9663 }
9664 else if (g_plagueround) // Plague Mode
9665 {
9666 iRand = random_num(0, ArraySize(sound_ambience5) - 1)
9667 ArrayGetString(sound_ambience5, iRand, sound, charsmax(sound))
9668 duration = ArrayGetCell(sound_ambience5_duration, iRand)
9669 }
9670 else if (g_armageround) // Armageddon Mode
9671 {
9672 iRand = random_num(0, ArraySize(sound_ambience8) - 1)
9673 ArrayGetString(sound_ambience8, iRand, sound, charsmax(sound))
9674 duration = ArrayGetCell(sound_ambience8_duration, iRand)
9675 }
9676 else if (g_apocround) // Apocalypse Mode
9677 {
9678 iRand = random_num(0, ArraySize(sound_ambience9) - 1)
9679 ArrayGetString(sound_ambience9, iRand, sound, charsmax(sound))
9680 duration = ArrayGetCell(sound_ambience9_duration, iRand)
9681 }
9682 else if (g_nightround) // Nightmare Mode
9683 {
9684 iRand = random_num(0, ArraySize(sound_ambience10) - 1)
9685 ArrayGetString(sound_ambience10, iRand, sound, charsmax(sound))
9686 duration = ArrayGetCell(sound_ambience10_duration, iRand)
9687 }
9688 else // Infection Mode
9689 {
9690 iRand = random_num(0, ArraySize(sound_ambience1) - 1)
9691 ArrayGetString(sound_ambience1, iRand, sound, charsmax(sound))
9692 duration = ArrayGetCell(sound_ambience1_duration, iRand)
9693 }
9694
9695 // Play it on clients
9696 PlaySound(sound)
9697
9698 // Set the task for when the sound is done playing
9699 set_task(float(duration), "ambience_sound_effects", TASK_AMBIENCESOUNDS)
9700}
9701
9702// Ambience Sounds Stop Task
9703ambience_sound_stop()
9704{
9705 client_cmd(0, "mp3 stop; stopsound")
9706}
9707
9708// Flashlight Charge Task
9709public flashlight_charge(taskid)
9710{
9711 // Drain or charge?
9712 if (g_flashlight[ID_CHARGE])
9713 g_flashbattery[ID_CHARGE] -= get_pcvar_num(cvar_flashdrain)
9714 else
9715 g_flashbattery[ID_CHARGE] += get_pcvar_num(cvar_flashcharge)
9716
9717 // Battery fully charged
9718 if (g_flashbattery[ID_CHARGE] >= 100)
9719 {
9720 // Don't exceed 100%
9721 g_flashbattery[ID_CHARGE] = 100
9722
9723 // Update flashlight battery on HUD
9724 message_begin(MSG_ONE, g_msgFlashBat, _, ID_CHARGE)
9725 write_byte(100) // battery
9726 message_end()
9727
9728 // Task not needed anymore
9729 remove_task(taskid);
9730 return;
9731 }
9732
9733 // Battery depleted
9734 if (g_flashbattery[ID_CHARGE] <= 0)
9735 {
9736 // Turn it off
9737 g_flashlight[ID_CHARGE] = false
9738 g_flashbattery[ID_CHARGE] = 0
9739
9740 // Play flashlight toggle sound
9741 emit_sound(ID_CHARGE, CHAN_ITEM, sound_flashlight, 1.0, ATTN_NORM, 0, PITCH_NORM)
9742
9743 // Update flashlight status on HUD
9744 message_begin(MSG_ONE, g_msgFlashlight, _, ID_CHARGE)
9745 write_byte(0) // toggle
9746 write_byte(0) // battery
9747 message_end()
9748
9749 // Remove flashlight task for this player
9750 remove_task(ID_CHARGE+TASK_FLASH)
9751 }
9752 else
9753 {
9754 // Update flashlight battery on HUD
9755 message_begin(MSG_ONE_UNRELIABLE, g_msgFlashBat, _, ID_CHARGE)
9756 write_byte(g_flashbattery[ID_CHARGE]) // battery
9757 message_end()
9758 }
9759}
9760
9761// Remove Spawn Protection Task
9762public remove_spawn_protection(taskid)
9763{
9764 // Not alive
9765 if (!g_isalive[ID_SPAWN])
9766 return;
9767
9768 // Remove spawn protection
9769 g_nodamage[ID_SPAWN] = false
9770 set_pev(ID_SPAWN, pev_effects, pev(ID_SPAWN, pev_effects) & ~EF_NODRAW)
9771}
9772
9773// Hide Player's Money Task
9774public task_hide_money(taskid)
9775{
9776 // Not alive
9777 if (!g_isalive[ID_SPAWN])
9778 return;
9779
9780 // Hide money
9781 message_begin(MSG_ONE, g_msgHideWeapon, _, ID_SPAWN)
9782 write_byte(HIDE_MONEY) // what to hide bitsum
9783 message_end()
9784
9785 // Hide the HL crosshair that's drawn
9786 message_begin(MSG_ONE, g_msgCrosshair, _, ID_SPAWN)
9787 write_byte(0) // toggle
9788 message_end()
9789}
9790
9791// Turn Off Flashlight and Restore Batteries
9792turn_off_flashlight(id)
9793{
9794 // Restore batteries for the next use
9795 fm_cs_set_user_batteries(id, 100)
9796
9797 // Check if flashlight is on
9798 if (pev(id, pev_effects) & EF_DIMLIGHT)
9799 {
9800 // Turn it off
9801 set_pev(id, pev_impulse, IMPULSE_FLASHLIGHT)
9802 }
9803 else
9804 {
9805 // Clear any stored flashlight impulse (bugfix)
9806 set_pev(id, pev_impulse, 0)
9807 }
9808
9809 // Turn off custom flashlight
9810 if (g_cached_customflash)
9811 {
9812 // Turn it off
9813 g_flashlight[id] = false
9814 g_flashbattery[id] = 100
9815
9816 // Update flashlight HUD
9817 message_begin(MSG_ONE, g_msgFlashlight, _, id)
9818 write_byte(0) // toggle
9819 write_byte(100) // battery
9820 message_end()
9821
9822 // Remove previous tasks
9823 remove_task(id+TASK_CHARGE)
9824 remove_task(id+TASK_FLASH)
9825 }
9826}
9827
9828// Infection Bomb Explosion
9829infection_explode(ent)
9830{
9831 // Round ended (bugfix)
9832 if (g_endround) return;
9833
9834 // Get origin
9835 static Float:originF[3]
9836 pev(ent, pev_origin, originF)
9837
9838 // Make the explosion
9839 create_blast(originF)
9840
9841 // Infection nade explode sound
9842 static sound[64]
9843 ArrayGetString(grenade_infect, random_num(0, ArraySize(grenade_infect) - 1), sound, charsmax(sound))
9844 emit_sound(ent, CHAN_WEAPON, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
9845
9846 // Get attacker
9847 static attacker
9848 attacker = pev(ent, pev_owner)
9849
9850 // Infection bomb owner disconnected? (bugfix)
9851 if (!is_user_valid_connected(attacker))
9852 {
9853 // Get rid of the grenade
9854 engfunc(EngFunc_RemoveEntity, ent)
9855 return;
9856 }
9857
9858 // Collisions
9859 static victim
9860 victim = -1
9861
9862 while ((victim = engfunc(EngFunc_FindEntityInSphere, victim, originF, NADE_EXPLOSION_RADIUS)) != 0)
9863 {
9864 // Only effect alive non-spawnprotected humans
9865 if(!is_user_valid_alive(victim) || g_zombie[victim] || g_nodamage[victim])
9866 {
9867 continue;
9868 }
9869
9870 if(get_user_gasmask(victim))
9871 {
9872 continue;
9873 }
9874
9875 // Last human is killed
9876 if (fnGetHumans() == 1)
9877 {
9878 ExecuteHamB(Ham_Killed, victim, attacker, 0);
9879
9880 continue;
9881 }
9882
9883 // Infected victim's sound
9884 ArrayGetString(grenade_infect_player, random_num(0, ArraySize(grenade_infect_player) - 1), sound, charsmax(sound))
9885 emit_sound(victim, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
9886
9887 // Turn into zombie
9888 zombieme(victim, attacker, 0, 0, 1, 1)
9889 }
9890
9891 // Get rid of the grenade
9892 engfunc(EngFunc_RemoveEntity, ent)
9893}
9894
9895// Fire Grenade Explosion
9896fire_explode(ent)
9897{
9898 // Get origin
9899 static Float:originF[3]
9900 pev(ent, pev_origin, originF)
9901
9902 // Make the explosion
9903 create_blast2(originF)
9904
9905 // Fire nade explode sound
9906 static sound[64]
9907 ArrayGetString(grenade_fire, random_num(0, ArraySize(grenade_fire) - 1), sound, charsmax(sound))
9908 emit_sound(ent, CHAN_WEAPON, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
9909
9910 // Collisions
9911 static victim
9912 victim = -1
9913
9914 while ((victim = engfunc(EngFunc_FindEntityInSphere, victim, originF, NADE_EXPLOSION_RADIUS)) != 0)
9915 {
9916 // Only effect alive zombies
9917 if (!is_user_valid_alive(victim) || !g_zombie[victim] || g_nodamage[victim])
9918 continue;
9919
9920 // Heat icon?
9921 if (get_pcvar_num(cvar_hudicons))
9922 {
9923 message_begin(MSG_ONE_UNRELIABLE, g_msgDamage, _, victim)
9924 write_byte(0) // damage save
9925 write_byte(0) // damage take
9926 write_long(DMG_BURN) // damage type
9927 write_coord(0) // x
9928 write_coord(0) // y
9929 write_coord(0) // z
9930 message_end()
9931 }
9932
9933 if (g_nemesis[victim] || g_assassin[victim]) // fire duration (nemesis is fire resistant)
9934 g_burning_duration[victim] += get_pcvar_num(cvar_fireduration)
9935 else
9936 g_burning_duration[victim] += get_pcvar_num(cvar_fireduration) * 5
9937
9938 // Set burning task on victim if not present
9939 if (!task_exists(victim+TASK_BURN))
9940 set_task(0.2, "burning_flame", victim+TASK_BURN, _, _, "b")
9941 }
9942
9943 // Get rid of the grenade
9944 engfunc(EngFunc_RemoveEntity, ent)
9945}
9946
9947// Frost Grenade Explosion
9948frost_explode(ent)
9949{
9950 // Get origin
9951 static Float:originF[3]
9952 pev(ent, pev_origin, originF)
9953
9954 // Make the explosion
9955 create_blast3(originF)
9956
9957 // Frost nade explode sound
9958 static sound[64]
9959 ArrayGetString(grenade_frost, random_num(0, ArraySize(grenade_frost) - 1), sound, charsmax(sound))
9960 emit_sound(ent, CHAN_WEAPON, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
9961
9962 // Collisions
9963 static victim
9964 victim = -1
9965
9966 while ((victim = engfunc(EngFunc_FindEntityInSphere, victim, originF, NADE_EXPLOSION_RADIUS)) != 0)
9967 {
9968 // Only effect alive unfrozen zombies
9969 if (!is_user_valid_alive(victim) || !g_zombie[victim] || g_frozen[victim] || g_nodamage[victim])
9970 continue;
9971
9972 // Nemesis shouldn't be frozen
9973 if (g_nemesis[victim] || g_assassin[victim])
9974 {
9975 // Get player's origin
9976 static origin2[3]
9977 get_user_origin(victim, origin2)
9978
9979 // Broken glass sound
9980 ArrayGetString(grenade_frost_break, random_num(0, ArraySize(grenade_frost_break) - 1), sound, charsmax(sound))
9981 emit_sound(victim, CHAN_BODY, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
9982
9983 // Glass shatter
9984 message_begin(MSG_PVS, SVC_TEMPENTITY, origin2)
9985 write_byte(TE_BREAKMODEL) // TE id
9986 write_coord(origin2[0]) // x
9987 write_coord(origin2[1]) // y
9988 write_coord(origin2[2]+24) // z
9989 write_coord(16) // size x
9990 write_coord(16) // size y
9991 write_coord(16) // size z
9992 write_coord(random_num(-50, 50)) // velocity x
9993 write_coord(random_num(-50, 50)) // velocity y
9994 write_coord(25) // velocity z
9995 write_byte(10) // random velocity
9996 write_short(g_glassSpr) // model
9997 write_byte(10) // count
9998 write_byte(25) // life
9999 write_byte(BREAK_GLASS) // flags
10000 message_end()
10001
10002 continue;
10003 }
10004
10005 // Freeze icon?
10006 if (get_pcvar_num(cvar_hudicons))
10007 {
10008 message_begin(MSG_ONE_UNRELIABLE, g_msgDamage, _, victim)
10009 write_byte(0) // damage save
10010 write_byte(0) // damage take
10011 write_long(DMG_DROWN) // damage type - DMG_FREEZE
10012 write_coord(0) // x
10013 write_coord(0) // y
10014 write_coord(0) // z
10015 message_end()
10016 }
10017
10018 // Light blue glow while frozen
10019 if (g_handle_models_on_separate_ent)
10020 fm_set_rendering(g_ent_playermodel[victim], kRenderFxGlowShell, 0, 100, 200, kRenderNormal, 25)
10021 else
10022 fm_set_rendering(victim, kRenderFxGlowShell, 0, 100, 200, kRenderNormal, 25)
10023
10024 // Freeze sound
10025 ArrayGetString(grenade_frost_player, random_num(0, ArraySize(grenade_frost_player) - 1), sound, charsmax(sound))
10026 emit_sound(victim, CHAN_BODY, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
10027
10028 // Add a blue tint to their screen
10029 message_begin(MSG_ONE, g_msgScreenFade, _, victim)
10030 write_short(0) // duration
10031 write_short(0) // hold time
10032 write_short(FFADE_STAYOUT) // fade type
10033 write_byte(0) // red
10034 write_byte(50) // green
10035 write_byte(200) // blue
10036 write_byte(100) // alpha
10037 message_end()
10038
10039 // Set the frozen flag
10040 g_frozen[victim] = true
10041
10042 // Save player's old gravity (bugfix)
10043 pev(victim, pev_gravity, g_frozen_gravity[victim])
10044
10045 // Prevent from jumping
10046 if (pev(victim, pev_flags) & FL_ONGROUND)
10047 set_pev(victim, pev_gravity, 999999.9) // set really high
10048 else
10049 set_pev(victim, pev_gravity, 0.000001) // no gravity
10050
10051 // Prevent from moving
10052 ExecuteHamB(Ham_Player_ResetMaxSpeed, victim)
10053
10054 // Set a task to remove the freeze
10055 set_task(get_pcvar_float(cvar_freezeduration), "remove_freeze", victim)
10056 }
10057
10058 // Get rid of the grenade
10059 engfunc(EngFunc_RemoveEntity, ent)
10060}
10061
10062// Remove freeze task
10063public remove_freeze(id)
10064{
10065 // Not alive or not frozen anymore
10066 if (!g_isalive[id] || !g_frozen[id])
10067 return;
10068
10069 // Unfreeze
10070 g_frozen[id] = false;
10071
10072 // Restore gravity and maxspeed (bugfix)
10073 set_pev(id, pev_gravity, g_frozen_gravity[id])
10074 ExecuteHamB(Ham_Player_ResetMaxSpeed, id)
10075
10076 // Restore rendering
10077 if (g_handle_models_on_separate_ent)
10078 {
10079 // Nemesis or Survivor glow / remove glow on player model entity
10080 if (g_nemesis[id] && get_pcvar_num(cvar_nemglow))
10081 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 250, 0, 0, kRenderNormal, 25)
10082 else if (g_nemesis[id] && !(get_pcvar_num(cvar_nemglow)))
10083 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 0, 0, 0, kRenderNormal, 25)
10084 else if (g_assassin[id] && get_pcvar_num(cvar_assaglow))
10085 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 255, 255, 0, kRenderNormal, 25)
10086 else if (g_survivor[id] && get_pcvar_num(cvar_survglow))
10087 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 0, 0, 255, kRenderNormal, 25)
10088 else if (g_sniper[id] && get_pcvar_num(cvar_sniglow))
10089 fm_set_rendering(g_ent_playermodel[id], kRenderFxGlowShell, 0, 255, 0, kRenderNormal, 25)
10090 else
10091 fm_set_rendering(g_ent_playermodel[id])
10092 }
10093 else
10094 {
10095 // Nemesis or Survivor glow / remove glow
10096 if (g_nemesis[id] && get_pcvar_num(cvar_nemglow))
10097 fm_set_rendering(id, kRenderFxGlowShell, 250, 0, 0, kRenderNormal, 25)
10098 else if (g_nemesis[id] && !(get_pcvar_num(cvar_nemglow)))
10099 fm_set_rendering(id, kRenderFxGlowShell, 0, 0, 0, kRenderNormal, 25)
10100 else if (g_assassin[id] && get_pcvar_num(cvar_assaglow))
10101 fm_set_rendering(id, kRenderFxGlowShell, 255, 255, 0, kRenderNormal, 25)
10102 else if (g_survivor[id] && get_pcvar_num(cvar_survglow))
10103 fm_set_rendering(id, kRenderFxGlowShell, 0, 0, 255, kRenderNormal, 25)
10104 else if (g_sniper[id] && get_pcvar_num(cvar_sniglow))
10105 fm_set_rendering(id, kRenderFxGlowShell, 0, 255, 0, kRenderNormal, 25)
10106 else
10107 fm_set_rendering(id)
10108 }
10109
10110 // Gradually remove screen's blue tint
10111 message_begin(MSG_ONE, g_msgScreenFade, _, id)
10112 write_short(UNIT_SECOND) // duration
10113 write_short(0) // hold time
10114 write_short(FFADE_IN) // fade type
10115 write_byte(0) // red
10116 write_byte(50) // green
10117 write_byte(200) // blue
10118 write_byte(100) // alpha
10119 message_end()
10120
10121 // Broken glass sound
10122 static sound[64]
10123 ArrayGetString(grenade_frost_break, random_num(0, ArraySize(grenade_frost_break) - 1), sound, charsmax(sound))
10124 emit_sound(id, CHAN_BODY, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
10125
10126 // Get player's origin
10127 static origin2[3]
10128 get_user_origin(id, origin2)
10129
10130 // Glass shatter
10131 message_begin(MSG_PVS, SVC_TEMPENTITY, origin2)
10132 write_byte(TE_BREAKMODEL) // TE id
10133 write_coord(origin2[0]) // x
10134 write_coord(origin2[1]) // y
10135 write_coord(origin2[2]+24) // z
10136 write_coord(16) // size x
10137 write_coord(16) // size y
10138 write_coord(16) // size z
10139 write_coord(random_num(-50, 50)) // velocity x
10140 write_coord(random_num(-50, 50)) // velocity y
10141 write_coord(25) // velocity z
10142 write_byte(10) // random velocity
10143 write_short(g_glassSpr) // model
10144 write_byte(10) // count
10145 write_byte(25) // life
10146 write_byte(BREAK_GLASS) // flags
10147 message_end()
10148
10149 ExecuteForward(g_fwUserUnfrozen, g_fwDummyResult, id);
10150}
10151
10152// Remove Stuff Task
10153public remove_stuff()
10154{
10155 static ent
10156
10157 // Remove rotating doors
10158 if (get_pcvar_num(cvar_removedoors) > 0)
10159 {
10160 ent = -1;
10161 while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "func_door_rotating")) != 0)
10162 engfunc(EngFunc_SetOrigin, ent, Float:{8192.0 ,8192.0 ,8192.0})
10163 }
10164
10165 // Remove all doors
10166 if (get_pcvar_num(cvar_removedoors) > 1)
10167 {
10168 ent = -1;
10169 while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "func_door")) != 0)
10170 engfunc(EngFunc_SetOrigin, ent, Float:{8192.0 ,8192.0 ,8192.0})
10171 }
10172
10173 // Triggered lights
10174 if (!get_pcvar_num(cvar_triggered))
10175 {
10176 ent = -1
10177 while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", "light")) != 0)
10178 {
10179 dllfunc(DLLFunc_Use, ent, 0); // turn off the light
10180 set_pev(ent, pev_targetname, 0) // prevent it from being triggered
10181 }
10182 }
10183}
10184
10185// Set Custom Weapon Models
10186replace_weapon_models(id, weaponid)
10187{
10188 switch (weaponid)
10189 {
10190 case CSW_KNIFE: // Custom knife models
10191 {
10192 if (g_zombie[id])
10193 {
10194 if (g_nemesis[id]) // Nemesis
10195 {
10196 set_pev(id, pev_viewmodel2, model_vknife_nemesis)
10197 set_pev(id, pev_weaponmodel2, "")
10198 }
10199 else if (g_assassin[id]) // Assassins
10200 {
10201 set_pev(id, pev_viewmodel2, model_vknife_assassin)
10202 set_pev(id, pev_weaponmodel2, "")
10203 }
10204 else // Zombies
10205 {
10206 // Admin knife models?
10207 if (get_pcvar_num(cvar_adminknifemodelszombie) && get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS])
10208 {
10209 set_pev(id, pev_viewmodel2, model_vknife_admin_zombie)
10210 set_pev(id, pev_weaponmodel2, "")
10211 }
10212 else
10213 {
10214 static clawmodel[100]
10215 ArrayGetString(g_zclass_clawmodel, g_zombieclass[id], clawmodel, charsmax(clawmodel))
10216 format(clawmodel, charsmax(clawmodel), "models/zombie_plague/%s", clawmodel)
10217 set_pev(id, pev_viewmodel2, clawmodel)
10218 set_pev(id, pev_weaponmodel2, "")
10219 }
10220 }
10221 }
10222 else // Humans
10223 {
10224 // Admin knife models?
10225 if (get_pcvar_num(cvar_adminknifemodelshuman) && get_user_flags(id) & g_access_flag[ACCESS_ADMIN_MODELS])
10226 {
10227 set_pev(id, pev_viewmodel2, model_vknife_admin_human)
10228 set_pev(id, pev_weaponmodel2, "models/p_knife.mdl")
10229 }
10230 else
10231 {
10232 set_pev(id, pev_viewmodel2, model_vknife_human)
10233 set_pev(id, pev_weaponmodel2, "models/p_knife.mdl")
10234 }
10235 }
10236 }
10237 case CSW_AWP: // Sniper's AWP
10238 {
10239 if (g_sniper[id])
10240 {
10241 set_pev(id, pev_viewmodel2, model_vawp_sniper)
10242 set_pev(id, pev_weaponmodel2, model_pawp_sniper)
10243 }
10244 }
10245 case CSW_HEGRENADE: // Infection bomb or fire grenade
10246 {
10247 if (g_zombie[id])
10248 set_pev(id, pev_viewmodel2, model_grenade_infect)
10249 else
10250 set_pev(id, pev_viewmodel2, model_grenade_fire)
10251 }
10252 case CSW_FLASHBANG: // Frost grenade
10253 {
10254 set_pev(id, pev_viewmodel2, model_grenade_frost)
10255 }
10256 case CSW_SMOKEGRENADE: // Flare grenade
10257 {
10258 set_pev(id, pev_viewmodel2, model_grenade_flare)
10259 }
10260 }
10261
10262 // Update model on weaponmodel ent
10263 if (g_handle_models_on_separate_ent) fm_set_weaponmodel_ent(id)
10264}
10265
10266// Reset Player Vars
10267reset_vars(id, resetall)
10268{
10269 g_zombie[id] = false
10270 g_nemesis[id] = false
10271 g_assassin[id] = false
10272 g_survivor[id] = false
10273 g_sniper[id] = false
10274 g_firstzombie[id] = false
10275 g_lastzombie[id] = false
10276 g_lasthuman[id] = false
10277 g_frozen[id] = false
10278 g_nodamage[id] = false
10279 g_respawn_as_zombie[id] = false
10280 g_nvision[id] = false
10281 g_nvisionenabled[id] = false
10282 g_flashlight[id] = false
10283 g_flashbattery[id] = 100
10284 g_canbuy[id] = true
10285 g_burning_duration[id] = 0
10286
10287 if (resetall)
10288 {
10289 g_ammopacks[id] = get_pcvar_num(cvar_startammopacks)
10290 g_zombieclass[id] = ZCLASS_NONE
10291 g_zombieclassnext[id] = ZCLASS_NONE
10292 g_damagedealt_human[id] = 0
10293 g_damagedealt_zombie[id] = 0
10294 WPN_AUTO_ON = 0
10295 WPN_STARTID = 0
10296 PL_ACTION = 0
10297 MENU_PAGE_ZCLASS = 0
10298 MENU_PAGE_EXTRAS = 0
10299 MENU_PAGE_PLAYERS = 0
10300 }
10301}
10302
10303// Set spectators nightvision
10304public spec_nvision(id)
10305{
10306 // Not connected, alive, or bot
10307 if (!g_isconnected[id] || g_isalive[id] || g_isbot[id])
10308 return;
10309
10310 // Give Night Vision?
10311 if (get_pcvar_num(cvar_nvggive))
10312 {
10313 g_nvision[id] = true
10314
10315 // Turn on Night Vision automatically?
10316 if (get_pcvar_num(cvar_nvggive) == 1)
10317 {
10318 g_nvisionenabled[id] = true
10319
10320 // Custom nvg?
10321 if (get_pcvar_num(cvar_customnvg))
10322 {
10323 remove_task(id+TASK_NVISION)
10324 set_task(0.1, "set_user_nvision", id+TASK_NVISION, _, _, "b")
10325 }
10326 else
10327 set_user_gnvision(id, 1)
10328 }
10329 }
10330}
10331
10332// Show HUD Task
10333public ShowHUD(taskid)
10334{
10335 static id
10336 id = ID_SHOWHUD;
10337
10338 // Player died?
10339 if (!g_isalive[id])
10340 {
10341 // Get spectating target
10342 id = pev(id, PEV_SPEC_TARGET)
10343
10344 // Target not alive
10345 if (!g_isalive[id]) return;
10346 }
10347
10348 // Format classname
10349 static class[32], red, green, blue
10350
10351 if (g_zombie[id]) // zombies
10352 {
10353 red = 200
10354 green = 250
10355 blue = 0
10356
10357 if (g_nemesis[id])
10358 formatex(class, charsmax(class), "%L", ID_SHOWHUD, "CLASS_NEMESIS")
10359 else if (g_assassin[id])
10360 formatex(class, charsmax(class), "%L", ID_SHOWHUD, "CLASS_ASSASSIN")
10361 else
10362 copy(class, charsmax(class), g_zombie_classname[id])
10363 }
10364 else // humans
10365 {
10366 red = 20
10367 green = 135
10368 blue = 255
10369
10370 if (g_survivor[id])
10371 formatex(class, charsmax(class), "%L", ID_SHOWHUD, "CLASS_SURVIVOR")
10372 else if (g_sniper[id])
10373 formatex(class, charsmax(class), "%L", ID_SHOWHUD, "CLASS_SNIPER")
10374 else
10375 formatex(class, charsmax(class), "%L", ID_SHOWHUD, "CLASS_HUMAN")
10376 }
10377
10378 // Spectating someone else?
10379 if (id != ID_SHOWHUD)
10380 {
10381 // Show name, health, class, and ammo packs
10382 set_hudmessage(20, 184, 62, HUD_SPECT_X, HUD_SPECT_Y, 0, 6.0, 1.1, 0.0, 0.0, -1)
10383 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))
10384 }
10385 else
10386 {
10387 // Show health, class and ammo packs
10388 set_hudmessage(red, green, blue, 0.02, 0.18, 0, 6.0, 1.1, 0.0, 0.0, -1)
10389 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))
10390 }
10391}
10392
10393// Play idle zombie sounds
10394public zombie_play_idle(taskid)
10395{
10396 // Round ended/new one starting
10397 if (g_endround || g_newround)
10398 return;
10399
10400 static sound[64]
10401
10402 // Last zombie?
10403 if (g_lastzombie[ID_BLOOD])
10404 {
10405 ArrayGetString(zombie_idle_last, random_num(0, ArraySize(zombie_idle_last) - 1), sound, charsmax(sound))
10406 emit_sound(ID_BLOOD, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
10407 }
10408 else
10409 {
10410 ArrayGetString(zombie_idle, random_num(0, ArraySize(zombie_idle) - 1), sound, charsmax(sound))
10411 emit_sound(ID_BLOOD, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
10412 }
10413}
10414
10415// Madness Over Task
10416public madness_over(taskid)
10417{
10418 g_nodamage[ID_BLOOD] = false
10419}
10420
10421// Place user at a random spawn
10422do_random_spawn(id, regularspawns = 0)
10423{
10424 static hull, sp_index, i
10425
10426 // Get whether the player is crouching
10427 hull = (pev(id, pev_flags) & FL_DUCKING) ? HULL_HEAD : HULL_HUMAN
10428
10429 // Use regular spawns?
10430 if (!regularspawns)
10431 {
10432 // No spawns?
10433 if (!g_spawnCount)
10434 return;
10435
10436 // Choose random spawn to start looping at
10437 sp_index = random_num(0, g_spawnCount - 1)
10438
10439 // Try to find a clear spawn
10440 for (i = sp_index + 1; /*no condition*/; i++)
10441 {
10442 // Start over when we reach the end
10443 if (i >= g_spawnCount) i = 0
10444
10445 // Free spawn space?
10446 if (is_hull_vacant(g_spawns[i], hull))
10447 {
10448 // Engfunc_SetOrigin is used so ent's mins and maxs get updated instantly
10449 engfunc(EngFunc_SetOrigin, id, g_spawns[i])
10450 break;
10451 }
10452
10453 // Loop completed, no free space found
10454 if (i == sp_index) break;
10455 }
10456 }
10457 else
10458 {
10459 // No spawns?
10460 if (!g_spawnCount2)
10461 return;
10462
10463 // Choose random spawn to start looping at
10464 sp_index = random_num(0, g_spawnCount2 - 1)
10465
10466 // Try to find a clear spawn
10467 for (i = sp_index + 1; /*no condition*/; i++)
10468 {
10469 // Start over when we reach the end
10470 if (i >= g_spawnCount2) i = 0
10471
10472 // Free spawn space?
10473 if (is_hull_vacant(g_spawns2[i], hull))
10474 {
10475 // Engfunc_SetOrigin is used so ent's mins and maxs get updated instantly
10476 engfunc(EngFunc_SetOrigin, id, g_spawns2[i])
10477 break;
10478 }
10479
10480 // Loop completed, no free space found
10481 if (i == sp_index) break;
10482 }
10483 }
10484}
10485
10486// Get Zombies -returns alive zombies number-
10487fnGetZombies()
10488{
10489 static iZombies, id
10490 iZombies = 0
10491
10492 for (id = 1; id <= g_maxplayers; id++)
10493 {
10494 if (g_isalive[id] && g_zombie[id])
10495 iZombies++
10496 }
10497
10498 return iZombies;
10499}
10500
10501// Get Humans -returns alive humans number-
10502fnGetHumans()
10503{
10504 static iHumans, id
10505 iHumans = 0
10506
10507 for (id = 1; id <= g_maxplayers; id++)
10508 {
10509 if (g_isalive[id] && !g_zombie[id])
10510 iHumans++
10511 }
10512
10513 return iHumans;
10514}
10515
10516// Get Nemesis -returns alive nemesis number-
10517fnGetNemesis()
10518{
10519 static iNemesis, id
10520 iNemesis = 0
10521
10522 for (id = 1; id <= g_maxplayers; id++)
10523 {
10524 if (g_isalive[id] && g_nemesis[id])
10525 iNemesis++
10526 }
10527
10528 return iNemesis;
10529}
10530
10531// Get Assassin -returns alive assassin number-
10532fnGetAssassin()
10533{
10534 static iAssassin, id
10535 iAssassin = 0
10536
10537 for (id = 1; id <= g_maxplayers; id++)
10538 {
10539 if (g_isalive[id] && g_assassin[id])
10540 iAssassin++
10541 }
10542
10543 return iAssassin;
10544}
10545
10546// Get Survivors -returns alive survivors number-
10547fnGetSurvivors()
10548{
10549 static iSurvivors, id
10550 iSurvivors = 0
10551
10552 for (id = 1; id <= g_maxplayers; id++)
10553 {
10554 if (g_isalive[id] && g_survivor[id])
10555 iSurvivors++
10556 }
10557
10558 return iSurvivors;
10559}
10560
10561// Get Snipers -returns alive snipers number-
10562fnGetSnipers()
10563{
10564 static iSnipers, id
10565 iSnipers = 0
10566
10567 for (id = 1; id <= g_maxplayers; id++)
10568 {
10569 if (g_isalive[id] && g_sniper[id])
10570 iSnipers++
10571 }
10572
10573 return iSnipers;
10574}
10575
10576// Get Alive -returns alive players number-
10577fnGetAlive()
10578{
10579 static iAlive, id
10580 iAlive = 0
10581
10582 for (id = 1; id <= g_maxplayers; id++)
10583 {
10584 if (g_isalive[id])
10585 iAlive++
10586 }
10587
10588 return iAlive;
10589}
10590
10591// Get Random Alive -returns index of alive player number n -
10592fnGetRandomAlive(n)
10593{
10594 static iAlive, id
10595 iAlive = 0
10596
10597 for (id = 1; id <= g_maxplayers; id++)
10598 {
10599 if (g_isalive[id])
10600 iAlive++
10601
10602 if (iAlive == n)
10603 return id;
10604 }
10605
10606 return -1;
10607}
10608
10609// Get Playing -returns number of users playing-
10610fnGetPlaying()
10611{
10612 static iPlaying, id, team
10613 iPlaying = 0
10614
10615 for (id = 1; id <= g_maxplayers; id++)
10616 {
10617 if (g_isconnected[id])
10618 {
10619 team = fm_cs_get_user_team(id)
10620
10621 if (team != FM_CS_TEAM_SPECTATOR && team != FM_CS_TEAM_UNASSIGNED)
10622 iPlaying++
10623 }
10624 }
10625
10626 return iPlaying;
10627}
10628
10629// Get CTs -returns number of CTs connected-
10630fnGetCTs()
10631{
10632 static iCTs, id
10633 iCTs = 0
10634
10635 for (id = 1; id <= g_maxplayers; id++)
10636 {
10637 if (g_isconnected[id])
10638 {
10639 if (fm_cs_get_user_team(id) == FM_CS_TEAM_CT)
10640 iCTs++
10641 }
10642 }
10643
10644 return iCTs;
10645}
10646
10647// Get Ts -returns number of Ts connected-
10648fnGetTs()
10649{
10650 static iTs, id
10651 iTs = 0
10652
10653 for (id = 1; id <= g_maxplayers; id++)
10654 {
10655 if (g_isconnected[id])
10656 {
10657 if (fm_cs_get_user_team(id) == FM_CS_TEAM_T)
10658 iTs++
10659 }
10660 }
10661
10662 return iTs;
10663}
10664
10665// Get Alive CTs -returns number of CTs alive-
10666fnGetAliveCTs()
10667{
10668 static iCTs, id
10669 iCTs = 0
10670
10671 for (id = 1; id <= g_maxplayers; id++)
10672 {
10673 if (g_isalive[id])
10674 {
10675 if (fm_cs_get_user_team(id) == FM_CS_TEAM_CT)
10676 iCTs++
10677 }
10678 }
10679
10680 return iCTs;
10681}
10682
10683// Get Alive Ts -returns number of Ts alive-
10684fnGetAliveTs()
10685{
10686 static iTs, id
10687 iTs = 0
10688
10689 for (id = 1; id <= g_maxplayers; id++)
10690 {
10691 if (g_isalive[id])
10692 {
10693 if (fm_cs_get_user_team(id) == FM_CS_TEAM_T)
10694 iTs++
10695 }
10696 }
10697
10698 return iTs;
10699}
10700
10701// Last Zombie Check -check for last zombie and set its flag-
10702fnCheckLastZombie()
10703{
10704 static id
10705 for (id = 1; id <= g_maxplayers; id++)
10706 {
10707 // Last zombie
10708 if (g_isalive[id] && g_zombie[id] && !g_nemesis[id] && !g_assassin[id] && fnGetZombies() == 1)
10709 {
10710 if (!g_lastzombie[id])
10711 {
10712 // Last zombie forward
10713 ExecuteForward(g_fwUserLastZombie, g_fwDummyResult, id);
10714 }
10715 g_lastzombie[id] = true
10716 }
10717 else
10718 g_lastzombie[id] = false
10719
10720 // Last human
10721 if (g_isalive[id] && !g_zombie[id] && !g_survivor[id] && !g_sniper[id] && fnGetHumans() == 1)
10722 {
10723 if (!g_lasthuman[id])
10724 {
10725 // Last human forward
10726 ExecuteForward(g_fwUserLastHuman, g_fwDummyResult, id);
10727
10728 // Reward extra hp
10729 fm_set_user_health(id, pev(id, pev_health) + get_pcvar_num(cvar_humanlasthp))
10730 }
10731 g_lasthuman[id] = true
10732 }
10733 else
10734 g_lasthuman[id] = false
10735 }
10736}
10737
10738// Save player's stats to database
10739save_stats(id)
10740{
10741 // Check whether there is another record already in that slot
10742 if (db_name[id][0] && !equal(g_playername[id], db_name[id]))
10743 {
10744 // If DB size is exceeded, write over old records
10745 if (db_slot_i >= sizeof db_name)
10746 db_slot_i = g_maxplayers+1
10747
10748 // Move previous record onto an additional save slot
10749 copy(db_name[db_slot_i], charsmax(db_name[]), db_name[id])
10750 db_ammopacks[db_slot_i] = db_ammopacks[id]
10751 db_zombieclass[db_slot_i] = db_zombieclass[id]
10752 db_slot_i++
10753 }
10754
10755 // Now save the current player stats
10756 copy(db_name[id], charsmax(db_name[]), g_playername[id]) // name
10757 db_ammopacks[id] = g_ammopacks[id] // ammo packs
10758 db_zombieclass[id] = g_zombieclassnext[id] // zombie class
10759}
10760
10761// Load player's stats from database (if a record is found)
10762load_stats(id)
10763{
10764 // Look for a matching record
10765 static i
10766 for (i = 0; i < sizeof db_name; i++)
10767 {
10768 if (equal(g_playername[id], db_name[i]))
10769 {
10770 // Bingo!
10771 g_ammopacks[id] = db_ammopacks[i]
10772 g_zombieclass[id] = db_zombieclass[i]
10773 g_zombieclassnext[id] = db_zombieclass[i]
10774 return;
10775 }
10776 }
10777}
10778
10779// Checks if a player is allowed to be zombie
10780allowed_zombie(id)
10781{
10782 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))
10783 return false;
10784
10785 return true;
10786}
10787
10788// Checks if a player is allowed to be human
10789allowed_human(id)
10790{
10791 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))
10792 return false;
10793
10794 return true;
10795}
10796
10797// Checks if a player is allowed to be survivor
10798allowed_survivor(id)
10799{
10800 if (g_endround || g_survivor[id] || !g_isalive[id] || task_exists(TASK_WELCOMEMSG) || (!g_newround && g_zombie[id] && fnGetZombies() == 1))
10801 return false;
10802
10803 return true;
10804}
10805
10806// Checks if a player is allowed to be sniper
10807allowed_sniper(id)
10808{
10809 if (g_endround || g_sniper[id] || !g_isalive[id] || task_exists(TASK_WELCOMEMSG) || (!g_newround && g_zombie[id] && fnGetZombies() == 1))
10810 return false;
10811
10812 return true;
10813}
10814
10815// Checks if a player is allowed to be nemesis
10816allowed_nemesis(id)
10817{
10818 if (g_endround || g_nemesis[id] || !g_isalive[id] || task_exists(TASK_WELCOMEMSG) || (!g_newround && !g_zombie[id] && fnGetHumans() == 1))
10819 return false;
10820
10821 return true;
10822}
10823
10824// Checks if a player is allowed to be assassin
10825allowed_assassin(id)
10826{
10827 if (g_endround || g_assassin[id] || !g_isalive[id] || task_exists(TASK_WELCOMEMSG) || (!g_newround && !g_zombie[id] && fnGetHumans() == 1))
10828 return false;
10829
10830 return true;
10831}
10832
10833// Checks if a player is allowed to respawn
10834allowed_respawn(id)
10835{
10836 static team
10837 team = fm_cs_get_user_team(id)
10838
10839 if (g_endround || team == FM_CS_TEAM_SPECTATOR || team == FM_CS_TEAM_UNASSIGNED || g_isalive[id])
10840 return false;
10841
10842 return true;
10843}
10844
10845// Checks if swarm mode is allowed
10846allowed_swarm()
10847{
10848 if (g_endround || !g_newround || task_exists(TASK_WELCOMEMSG))
10849 return false;
10850
10851 return true;
10852}
10853
10854// Checks if multi infection mode is allowed
10855allowed_multi()
10856{
10857 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())
10858 return false;
10859
10860 return true;
10861}
10862
10863// Checks if plague mode is allowed
10864allowed_plague()
10865{
10866 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
10867 || 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)
10868 return false;
10869
10870 return true;
10871}
10872
10873// Checks if armageddon mode is allowed
10874allowed_armageddon()
10875{
10876 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())
10877 return false;
10878
10879 return true;
10880}
10881
10882// Checks if apocalypse mode is allowed
10883allowed_apocalypse()
10884{
10885 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())
10886 return false;
10887
10888 return true;
10889}
10890
10891// Checks if nightmare mode is allowed
10892allowed_nightmare()
10893{
10894 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())
10895 return false;
10896
10897 return true;
10898}
10899
10900// Admin Command. zp_zombie
10901command_zombie(id, player)
10902{
10903 // Show activity?
10904 switch (get_pcvar_num(cvar_showactivity))
10905 {
10906 case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_INFECT")
10907 case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_INFECT")
10908 }
10909
10910 // Log to Zombie Plague log file?
10911 if (get_pcvar_num(cvar_logcommands))
10912 {
10913 static logdata[100], authid[32], ip[16]
10914 get_user_authid(id, authid, charsmax(authid))
10915 get_user_ip(id, ip, charsmax(ip), 1)
10916 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)
10917 log_to_file("zombieplague.log", logdata)
10918 }
10919
10920 // New round?
10921 if (g_newround)
10922 {
10923 // Set as first zombie
10924 remove_task(TASK_MAKEZOMBIE)
10925 make_a_zombie(MODE_INFECTION, player)
10926 }
10927 else
10928 {
10929 // Just infect
10930 zombieme(player, 0, 0, 0, 0, 0)
10931 }
10932}
10933
10934// Admin Command. zp_human
10935command_human(id, player)
10936{
10937 // Show activity?
10938 switch (get_pcvar_num(cvar_showactivity))
10939 {
10940 case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_DISINFECT")
10941 case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_DISINFECT")
10942 }
10943
10944 // Log to Zombie Plague log file?
10945 if (get_pcvar_num(cvar_logcommands))
10946 {
10947 static logdata[100], authid[32], ip[16]
10948 get_user_authid(id, authid, charsmax(authid))
10949 get_user_ip(id, ip, charsmax(ip), 1)
10950 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)
10951 log_to_file("zombieplague.log", logdata)
10952 }
10953
10954 // Turn to human
10955 humanme(player, 0, 0, 0)
10956}
10957
10958// Admin Command. zp_survivor
10959command_survivor(id, player)
10960{
10961 // Show activity?
10962 switch (get_pcvar_num(cvar_showactivity))
10963 {
10964 case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_SURVIVAL")
10965 case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_SURVIVAL")
10966 }
10967
10968 // Log to Zombie Plague log file?
10969 if (get_pcvar_num(cvar_logcommands))
10970 {
10971 static logdata[100], authid[32], ip[16]
10972 get_user_authid(id, authid, charsmax(authid))
10973 get_user_ip(id, ip, charsmax(ip), 1)
10974 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)
10975 log_to_file("zombieplague.log", logdata)
10976 }
10977
10978 // New round?
10979 if (g_newround)
10980 {
10981 // Set as first survivor
10982 remove_task(TASK_MAKEZOMBIE)
10983 make_a_zombie(MODE_SURVIVOR, player)
10984 }
10985 else
10986 {
10987 // Turn player into a Survivor
10988 humanme(player, 1, 0, 0)
10989 }
10990}
10991
10992// Admin Command. zp_sniper
10993command_sniper(id, player)
10994{
10995 // Show activity?
10996 switch (get_pcvar_num(cvar_showactivity))
10997 {
10998 case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_SNIPER")
10999 case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_SNIPER")
11000 }
11001
11002 // Log to Zombie Plague log file?
11003 if (get_pcvar_num(cvar_logcommands))
11004 {
11005 static logdata[100], authid[32], ip[16]
11006 get_user_authid(id, authid, charsmax(authid))
11007 get_user_ip(id, ip, charsmax(ip), 1)
11008 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)
11009 log_to_file("zombieplague.log", logdata)
11010 }
11011
11012 // New round?
11013 if (g_newround)
11014 {
11015 // Set as first sniper
11016 remove_task(TASK_MAKEZOMBIE)
11017 make_a_zombie(MODE_SNIPER, player)
11018 }
11019 else
11020 {
11021 // Turn player into a Sniper
11022 humanme(player, 0, 1, 0)
11023 }
11024}
11025
11026// Admin Command. zp_nemesis
11027command_nemesis(id, player)
11028{
11029 // Show activity?
11030 switch (get_pcvar_num(cvar_showactivity))
11031 {
11032 case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_NEMESIS")
11033 case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_NEMESIS")
11034 }
11035
11036 // Log to Zombie Plague log file?
11037 if (get_pcvar_num(cvar_logcommands))
11038 {
11039 static logdata[100], authid[32], ip[16]
11040 get_user_authid(id, authid, charsmax(authid))
11041 get_user_ip(id, ip, charsmax(ip), 1)
11042 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)
11043 log_to_file("zombieplague.log", logdata)
11044 }
11045
11046 // New round?
11047 if (g_newround)
11048 {
11049 // Set as first nemesis
11050 remove_task(TASK_MAKEZOMBIE)
11051 make_a_zombie(MODE_NEMESIS, player)
11052 }
11053 else
11054 {
11055 // Turn player into a Nemesis
11056 zombieme(player, 0, 1, 0, 0, 0)
11057 }
11058}
11059
11060// Admin Command. zp_assassin
11061command_assassin(id, player)
11062{
11063 // Show activity?
11064 switch (get_pcvar_num(cvar_showactivity))
11065 {
11066 case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_ASSASSIN")
11067 case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_ASSASSIN")
11068 }
11069
11070 // Log to Zombie Plague log file?
11071 if (get_pcvar_num(cvar_logcommands))
11072 {
11073 static logdata[100], authid[32], ip[16]
11074 get_user_authid(id, authid, charsmax(authid))
11075 get_user_ip(id, ip, charsmax(ip), 1)
11076 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)
11077 log_to_file("zombieplague.log", logdata)
11078 }
11079
11080 // New round?
11081 if (g_newround)
11082 {
11083 // Set as first assassin
11084 remove_task(TASK_MAKEZOMBIE)
11085 make_a_zombie(MODE_ASSASSIN, player)
11086 }
11087 else
11088 {
11089 // Turn player into a Assassin
11090 zombieme(player, 0, 0, 1, 0, 0)
11091 }
11092}
11093
11094// Admin Command. zp_respawn
11095command_respawn(id, player)
11096{
11097 // Show activity?
11098 switch (get_pcvar_num(cvar_showactivity))
11099 {
11100 case 1: client_print(0, print_chat, "ADMIN - %s %L", g_playername[player], LANG_PLAYER, "CMD_RESPAWN")
11101 case 2: client_print(0, print_chat, "ADMIN %s - %s %L", g_playername[id], g_playername[player], LANG_PLAYER, "CMD_RESPAWN")
11102 }
11103
11104 // Log to Zombie Plague log file?
11105 if (get_pcvar_num(cvar_logcommands))
11106 {
11107 static logdata[100], authid[32], ip[16]
11108 get_user_authid(id, authid, charsmax(authid))
11109 get_user_ip(id, ip, charsmax(ip), 1)
11110 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)
11111 log_to_file("zombieplague.log", logdata)
11112 }
11113
11114 // Respawn as zombie?
11115 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))
11116 g_respawn_as_zombie[player] = true
11117
11118 // Override respawn as zombie setting on nemesis and survivor rounds
11119 if (g_survround) g_respawn_as_zombie[player] = true
11120 else if (g_nemround) g_respawn_as_zombie[player] = false
11121
11122 respawn_player_manually(player);
11123}
11124
11125// Admin Command. zp_swarm
11126command_swarm(id)
11127{
11128 // Show activity?
11129 switch (get_pcvar_num(cvar_showactivity))
11130 {
11131 case 1: client_print(0, print_chat, "ADMIN - %L", LANG_PLAYER, "CMD_SWARM")
11132 case 2: client_print(0, print_chat, "ADMIN %s - %L", g_playername[id], LANG_PLAYER, "CMD_SWARM")
11133 }
11134
11135 // Log to Zombie Plague log file?
11136 if (get_pcvar_num(cvar_logcommands))
11137 {
11138 static logdata[100], authid[32], ip[16]
11139 get_user_authid(id, authid, charsmax(authid))
11140 get_user_ip(id, ip, charsmax(ip), 1)
11141 formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %L (Players: %d/%d)", g_playername[id], authid, ip, LANG_SERVER, "CMD_SWARM", fnGetPlaying(), g_maxplayers)
11142 log_to_file("zombieplague.log", logdata)
11143 }
11144
11145 // Call Swarm Mode
11146 remove_task(TASK_MAKEZOMBIE)
11147 make_a_zombie(MODE_SWARM, 0)
11148}
11149
11150// Admin Command. zp_multi
11151command_multi(id)
11152{
11153 // Show activity?
11154 switch (get_pcvar_num(cvar_showactivity))
11155 {
11156 case 1: client_print(0, print_chat, "ADMIN - %L", LANG_PLAYER, "CMD_MULTI")
11157 case 2: client_print(0, print_chat, "ADMIN %s - %L", g_playername[id], LANG_PLAYER, "CMD_MULTI")
11158 }
11159
11160 // Log to Zombie Plague log file?
11161 if (get_pcvar_num(cvar_logcommands))
11162 {
11163 static logdata[100], authid[32], ip[16]
11164 get_user_authid(id, authid, charsmax(authid))
11165 get_user_ip(id, ip, charsmax(ip), 1)
11166 formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %L (Players: %d/%d)", g_playername[id], authid, ip, LANG_SERVER,"CMD_MULTI", fnGetPlaying(), g_maxplayers)
11167 log_to_file("zombieplague.log", logdata)
11168 }
11169
11170 // Call Multi Infection
11171 remove_task(TASK_MAKEZOMBIE)
11172 make_a_zombie(MODE_MULTI, 0)
11173}
11174
11175// Admin Command. zp_plague
11176command_plague(id)
11177{
11178 // Show activity?
11179 switch (get_pcvar_num(cvar_showactivity))
11180 {
11181 case 1: client_print(0, print_chat, "ADMIN - %L", LANG_PLAYER, "CMD_PLAGUE")
11182 case 2: client_print(0, print_chat, "ADMIN %s - %L", g_playername[id], LANG_PLAYER, "CMD_PLAGUE")
11183 }
11184
11185 // Log to Zombie Plague log file?
11186 if (get_pcvar_num(cvar_logcommands))
11187 {
11188 static logdata[100], authid[32], ip[16]
11189 get_user_authid(id, authid, charsmax(authid))
11190 get_user_ip(id, ip, charsmax(ip), 1)
11191 formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %L (Players: %d/%d)", g_playername[id], authid, ip, LANG_SERVER,"CMD_PLAGUE", fnGetPlaying(), g_maxplayers)
11192 log_to_file("zombieplague.log", logdata)
11193 }
11194
11195 // Call Plague Mode
11196 remove_task(TASK_MAKEZOMBIE)
11197 make_a_zombie(MODE_PLAGUE, 0)
11198}
11199
11200// Admin Command. zp_armageddon
11201command_armageddon(id)
11202{
11203 // Show activity?
11204 switch (get_pcvar_num(cvar_showactivity))
11205 {
11206 case 1: client_print(0, print_chat, "ADMIN - %L", LANG_PLAYER, "CMD_ARMAGEDDON")
11207 case 2: client_print(0, print_chat, "ADMIN %s - %L", g_playername[id], LANG_PLAYER, "CMD_ARMAGEDDON")
11208 }
11209
11210 // Log to Zombie Plague log file?
11211 if (get_pcvar_num(cvar_logcommands))
11212 {
11213 static logdata[100], authid[32], ip[16]
11214 get_user_authid(id, authid, charsmax(authid))
11215 get_user_ip(id, ip, charsmax(ip), 1)
11216 formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %L (Players: %d/%d)", g_playername[id], authid, ip, LANG_SERVER,"CMD_ARMAGEDDON", fnGetPlaying(), g_maxplayers)
11217 log_to_file("zombieplague.log", logdata)
11218 }
11219
11220 // Call Armageddon Mode
11221 remove_task(TASK_MAKEZOMBIE)
11222 make_a_zombie(MODE_ARMAGEDDON, 0)
11223}
11224
11225// Admin Command. zp_apocalypse
11226command_apocalypse(id)
11227{
11228 // Show activity?
11229 switch (get_pcvar_num(cvar_showactivity))
11230 {
11231 case 1: client_print(0, print_chat, "ADMIN - %L", LANG_PLAYER, "CMD_APOCALYPSE")
11232 case 2: client_print(0, print_chat, "ADMIN %s - %L", g_playername[id], LANG_PLAYER, "CMD_APOCALYPSE")
11233 }
11234
11235 // Log to Zombie Plague log file?
11236 if (get_pcvar_num(cvar_logcommands))
11237 {
11238 static logdata[100], authid[32], ip[16]
11239 get_user_authid(id, authid, charsmax(authid))
11240 get_user_ip(id, ip, charsmax(ip), 1)
11241 formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %L (Players: %d/%d)", g_playername[id], authid, ip, LANG_SERVER,"CMD_APOCALYPSE", fnGetPlaying(), g_maxplayers)
11242 log_to_file("zombieplague.log", logdata)
11243 }
11244
11245 // Call Apocalypse Mode
11246 remove_task(TASK_MAKEZOMBIE)
11247 make_a_zombie(MODE_APOCALYPSE, 0)
11248}
11249
11250// Admin Command. zp_nightmare
11251command_nightmare(id)
11252{
11253 // Show activity?
11254 switch (get_pcvar_num(cvar_showactivity))
11255 {
11256 case 1: client_print(0, print_chat, "ADMIN - %L", LANG_PLAYER, "CMD_NIGHTMARE")
11257 case 2: client_print(0, print_chat, "ADMIN %s - %L", g_playername[id], LANG_PLAYER, "CMD_NIGHTMARE")
11258 }
11259
11260 // Log to Zombie Plague log file?
11261 if (get_pcvar_num(cvar_logcommands))
11262 {
11263 static logdata[100], authid[32], ip[16]
11264 get_user_authid(id, authid, charsmax(authid))
11265 get_user_ip(id, ip, charsmax(ip), 1)
11266 formatex(logdata, charsmax(logdata), "ADMIN %s <%s><%s> - %L (Players: %d/%d)", g_playername[id], authid, ip, LANG_SERVER,"CMD_NIGHTMARE", fnGetPlaying(), g_maxplayers)
11267 log_to_file("zombieplague.log", logdata)
11268 }
11269
11270 // Call Nightmare Mode
11271 remove_task(TASK_MAKEZOMBIE)
11272 make_a_zombie(MODE_NIGHTMARE, 0)
11273}
11274
11275// Set proper maxspeed for player
11276set_player_maxspeed(id)
11277{
11278 // If frozen, prevent from moving
11279 if (g_frozen[id])
11280 {
11281 set_pev(id, pev_maxspeed, 1.0)
11282 }
11283 // Otherwise, set maxspeed directly
11284 else
11285 {
11286 if (g_zombie[id])
11287 {
11288 if (g_nemesis[id])
11289 set_pev(id, pev_maxspeed, get_pcvar_float(cvar_nemspd))
11290 else if (g_assassin[id])
11291 set_pev(id, pev_maxspeed, get_pcvar_float(cvar_assaspd))
11292 else
11293 set_pev(id, pev_maxspeed, g_zombie_spd[id])
11294 }
11295 else
11296 {
11297 if (g_survivor[id])
11298 set_pev(id, pev_maxspeed, get_pcvar_float(cvar_survspd))
11299 else if (g_sniper[id])
11300 set_pev(id, pev_maxspeed, get_pcvar_float(cvar_snispd))
11301 else if (get_pcvar_float(cvar_humanspd) > 0.0)
11302 set_pev(id, pev_maxspeed, get_pcvar_float(cvar_humanspd))
11303 }
11304 }
11305}
11306
11307/*================================================================================
11308 [Custom Natives]
11309=================================================================================*/
11310
11311// Native: zp_get_user_zombie
11312public native_get_user_zombie(id)
11313{
11314 if (!is_user_valid(id))
11315 {
11316 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11317 return -1;
11318 }
11319
11320 return g_zombie[id];
11321}
11322
11323// Native: zp_get_user_nemesis
11324public native_get_user_nemesis(id)
11325{
11326 if (!is_user_valid(id))
11327 {
11328 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11329 return -1;
11330 }
11331
11332 return g_nemesis[id];
11333}
11334
11335// Native: zp_get_user_assassin
11336public native_get_user_assassin(id)
11337{
11338 if (!is_user_valid(id))
11339 {
11340 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11341 return -1;
11342 }
11343
11344 return g_assassin[id];
11345}
11346
11347// Native: zp_get_user_survivor
11348public native_get_user_survivor(id)
11349{
11350 if (!is_user_valid(id))
11351 {
11352 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11353 return -1;
11354 }
11355
11356 return g_survivor[id];
11357}
11358
11359// Native: zp_get_user_sniper
11360public native_get_user_sniper(id)
11361{
11362 if (!is_user_valid(id))
11363 {
11364 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11365 return -1;
11366 }
11367
11368 return g_sniper[id];
11369}
11370
11371public native_get_user_first_zombie(id)
11372{
11373 if (!is_user_valid(id))
11374 {
11375 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11376 return -1;
11377 }
11378
11379 return g_firstzombie[id];
11380}
11381
11382// Native: zp_get_user_last_zombie
11383public native_get_user_last_zombie(id)
11384{
11385 if (!is_user_valid(id))
11386 {
11387 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11388 return -1;
11389 }
11390
11391 return g_lastzombie[id];
11392}
11393
11394// Native: zp_get_user_last_human
11395public native_get_user_last_human(id)
11396{
11397 if (!is_user_valid(id))
11398 {
11399 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11400 return -1;
11401 }
11402
11403 return g_lasthuman[id];
11404}
11405
11406// Native: zp_get_user_zombie_class
11407public native_get_user_zombie_class(id)
11408{
11409 if (!is_user_valid(id))
11410 {
11411 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11412 return -1;
11413 }
11414
11415 return g_zombieclass[id];
11416}
11417
11418// Native: zp_get_user_next_class
11419public native_get_user_next_class(id)
11420{
11421 if (!is_user_valid(id))
11422 {
11423 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11424 return -1;
11425 }
11426
11427 return g_zombieclassnext[id];
11428}
11429
11430// Native: zp_set_user_zombie_class
11431public native_set_user_zombie_class(id, classid)
11432{
11433 if (!is_user_valid(id))
11434 {
11435 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11436 return false;
11437 }
11438
11439 if (classid < 0 || classid >= g_zclass_i)
11440 {
11441 log_error(AMX_ERR_NATIVE, "[ZP] Invalid zombie class id (%d)", classid)
11442 return false;
11443 }
11444
11445 g_zombieclassnext[id] = classid
11446 return true;
11447}
11448
11449// Native: zp_get_user_ammo_packs
11450public native_get_user_ammo_packs(id)
11451{
11452 if (!is_user_valid(id))
11453 {
11454 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11455 return -1;
11456 }
11457
11458 return g_ammopacks[id];
11459}
11460
11461// Native: zp_set_user_ammo_packs
11462public native_set_user_ammo_packs(id, amount)
11463{
11464 if (!is_user_valid(id))
11465 {
11466 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11467 return false;
11468 }
11469
11470 g_ammopacks[id] = amount;
11471 return true;
11472}
11473
11474// Native: zp_get_zombie_maxhealth
11475public native_get_zombie_maxhealth(id)
11476{
11477 // ZP disabled
11478 if (!g_pluginenabled)
11479 return -1;
11480
11481 if (!is_user_valid(id))
11482 {
11483 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11484 return -1;
11485 }
11486
11487 if (!g_zombie[id] || g_nemesis[id])
11488 {
11489 log_error(AMX_ERR_NATIVE, "[ZP] Player not a normal zombie (%d)", id)
11490 return -1;
11491 }
11492
11493 if (g_firstzombie[id])
11494 return floatround(float(ArrayGetCell(g_zclass_hp, g_zombieclass[id])) * get_pcvar_float(cvar_zombiefirsthp));
11495
11496 return ArrayGetCell(g_zclass_hp, g_zombieclass[id]);
11497}
11498
11499// Native: zp_get_user_batteries
11500public native_get_user_batteries(id)
11501{
11502 if (!is_user_valid(id))
11503 {
11504 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11505 return -1;
11506 }
11507
11508 return g_flashbattery[id];
11509}
11510
11511// Native: zp_set_user_batteries
11512public native_set_user_batteries(id, value)
11513{
11514 // ZP disabled
11515 if (!g_pluginenabled)
11516 return false;
11517
11518 if (!is_user_valid_connected(id))
11519 {
11520 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11521 return false;
11522 }
11523
11524 g_flashbattery[id] = clamp(value, 0, 100);
11525
11526 if (g_cached_customflash)
11527 {
11528 // Set the flashlight charge task to update battery status
11529 remove_task(id+TASK_CHARGE)
11530 set_task(1.0, "flashlight_charge", id+TASK_CHARGE, _, _, "b")
11531 }
11532 return true;
11533}
11534
11535// Native: zp_get_user_nightvision
11536public native_get_user_nightvision(id)
11537{
11538 if (!is_user_valid(id))
11539 {
11540 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11541 return -1;
11542 }
11543
11544 return g_nvision[id];
11545}
11546
11547// Native: zp_set_user_nightvision
11548public native_set_user_nightvision(id, set)
11549{
11550 // ZP disabled
11551 if (!g_pluginenabled)
11552 return false;
11553
11554 if (!is_user_valid_connected(id))
11555 {
11556 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11557 return false;
11558 }
11559
11560 if (set)
11561 {
11562 g_nvision[id] = true
11563
11564 if (!g_isbot[id])
11565 {
11566 g_nvisionenabled[id] = true
11567
11568 // Custom nvg?
11569 if (get_pcvar_num(cvar_customnvg))
11570 {
11571 remove_task(id+TASK_NVISION)
11572 set_task(0.1, "set_user_nvision", id+TASK_NVISION, _, _, "b")
11573 }
11574 else
11575 set_user_gnvision(id, 1)
11576 }
11577 else
11578 cs_set_user_nvg(id, 1)
11579 }
11580 else
11581 {
11582 // Remove CS nightvision if player owns one (bugfix)
11583 cs_set_user_nvg(id, 0)
11584
11585 if (get_pcvar_num(cvar_customnvg)) remove_task(id+TASK_NVISION)
11586 else if (g_nvisionenabled[id]) set_user_gnvision(id, 0)
11587 g_nvision[id] = false
11588 g_nvisionenabled[id] = false
11589 }
11590 return true;
11591}
11592
11593// Native: zp_infect_user
11594public native_infect_user(id, infector, silent, rewards)
11595{
11596 // ZP disabled
11597 if (!g_pluginenabled)
11598 return false;
11599
11600 if (!is_user_valid_alive(id))
11601 {
11602 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11603 return false;
11604 }
11605
11606 // Not allowed to be zombie
11607 if (!allowed_zombie(id))
11608 return false;
11609
11610 // New round?
11611 if (g_newround)
11612 {
11613 // Set as first zombie
11614 remove_task(TASK_MAKEZOMBIE)
11615 make_a_zombie(MODE_INFECTION, id)
11616 }
11617 else
11618 {
11619 // Just infect (plus some checks)
11620 zombieme(id, is_user_valid_alive(infector) ? infector : 0, 0, 0, (silent == 1) ? 1 : 0, (rewards == 1) ? 1 : 0)
11621 }
11622 return true;
11623}
11624
11625// Native: zp_disinfect_user
11626public native_disinfect_user(id, silent)
11627{
11628 // ZP disabled
11629 if (!g_pluginenabled)
11630 return false;
11631
11632 if (!is_user_valid_alive(id))
11633 {
11634 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11635 return false;
11636 }
11637
11638 // Not allowed to be human
11639 if (!allowed_human(id))
11640 return false;
11641
11642 // Turn to human
11643 humanme(id, 0, 0, (silent == 1) ? 1 : 0)
11644 return true;
11645}
11646
11647// Native: zp_make_user_nemesis
11648public native_make_user_nemesis(id)
11649{
11650 // ZP disabled
11651 if (!g_pluginenabled)
11652 return false;
11653
11654 if (!is_user_valid_alive(id))
11655 {
11656 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11657 return false;
11658 }
11659
11660 // Not allowed to be nemesis
11661 if (!allowed_nemesis(id))
11662 return false;
11663
11664 // New round?
11665 if (g_newround)
11666 {
11667 // Set as first nemesis
11668 remove_task(TASK_MAKEZOMBIE)
11669 make_a_zombie(MODE_NEMESIS, id)
11670 }
11671 else
11672 {
11673 // Turn player into a Nemesis
11674 zombieme(id, 0, 1, 0, 0, 0)
11675 }
11676 return true;
11677}
11678
11679// Native: zp_make_user_assassin
11680public native_make_user_assassin(id)
11681{
11682 // ZP disabled
11683 if (!g_pluginenabled)
11684 return false;
11685
11686 if (!is_user_valid_alive(id))
11687 {
11688 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11689 return false;
11690 }
11691
11692 // Not allowed to be assassin
11693 if (!allowed_assassin(id))
11694 return false;
11695
11696 // New round?
11697 if (g_newround)
11698 {
11699 // Set as first assassin
11700 remove_task(TASK_MAKEZOMBIE)
11701 make_a_zombie(MODE_ASSASSIN, id)
11702 }
11703 else
11704 {
11705 // Turn player into a Assassin
11706 zombieme(id, 0, 0, 1, 0, 0)
11707 }
11708 return true;
11709}
11710
11711// Native: zp_make_user_survivor
11712public native_make_user_survivor(id)
11713{
11714 // ZP disabled
11715 if (!g_pluginenabled)
11716 return false;
11717
11718 if (!is_user_valid_alive(id))
11719 {
11720 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11721 return false;
11722 }
11723
11724 // Not allowed to be survivor
11725 if (!allowed_survivor(id))
11726 return false;
11727
11728 // New round?
11729 if (g_newround)
11730 {
11731 // Set as first survivor
11732 remove_task(TASK_MAKEZOMBIE)
11733 make_a_zombie(MODE_SURVIVOR, id)
11734 }
11735 else
11736 {
11737 // Turn player into a Survivor
11738 humanme(id, 1, 0, 0)
11739 }
11740
11741 return true;
11742}
11743
11744// Native: zp_make_user_sniper
11745public native_make_user_sniper(id)
11746{
11747 // ZP disabled
11748 if (!g_pluginenabled)
11749 return false;
11750
11751 if (!is_user_valid_alive(id))
11752 {
11753 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11754 return false;
11755 }
11756
11757 // Not allowed to be sniper
11758 if (!allowed_sniper(id))
11759 return false;
11760
11761 // New round?
11762 if (g_newround)
11763 {
11764 // Set as first sniper
11765 remove_task(TASK_MAKEZOMBIE)
11766 make_a_zombie(MODE_SNIPER, id)
11767 }
11768 else
11769 {
11770 // Turn player into a Sniper
11771 humanme(id, 0, 1, 0)
11772 }
11773
11774 return true;
11775}
11776
11777// Native: zp_respawn_user
11778public native_respawn_user(id, team)
11779{
11780 // ZP disabled
11781 if (!g_pluginenabled)
11782 return false;
11783
11784 if (!is_user_valid_connected(id))
11785 {
11786 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11787 return false;
11788 }
11789
11790 // Respawn not allowed
11791 if (!allowed_respawn(id))
11792 return false;
11793
11794 // Respawn as zombie?
11795 g_respawn_as_zombie[id] = (team == ZP_TEAM_ZOMBIE) ? true : false
11796
11797 // Respawnish!
11798 respawn_player_manually(id)
11799 return true;
11800}
11801
11802// Native: zp_force_buy_extra_item
11803public native_force_buy_extra_item(id, itemid, ignorecost)
11804{
11805 // ZP disabled
11806 if (!g_pluginenabled)
11807 return false;
11808
11809 if (!is_user_valid_alive(id))
11810 {
11811 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11812 return false;
11813 }
11814
11815 if (itemid < 0 || itemid >= g_extraitem_i)
11816 {
11817 log_error(AMX_ERR_NATIVE, "[ZP] Invalid extra item id (%d)", itemid)
11818 return false;
11819 }
11820
11821 buy_extra_item(id, itemid, ignorecost)
11822 return true;
11823}
11824
11825// Native: zp_override_user_model
11826public native_override_user_model(id, const newmodel[], modelindex)
11827{
11828 // ZP disabled
11829 if (!g_pluginenabled)
11830 return false;
11831
11832 if (!is_user_valid_connected(id))
11833 {
11834 log_error(AMX_ERR_NATIVE, "[ZP] Invalid Player (%d)", id)
11835 return false;
11836 }
11837
11838 // Strings passed byref
11839 param_convert(2)
11840
11841 // Remove previous tasks
11842 remove_task(id+TASK_MODEL)
11843
11844 // Custom models stuff
11845 static currentmodel[32]
11846
11847 if (g_handle_models_on_separate_ent)
11848 {
11849 // Set the right model
11850 copy(g_playermodel[id], charsmax(g_playermodel[]), newmodel)
11851 if (g_set_modelindex_offset && modelindex) fm_cs_set_user_model_index(id, modelindex)
11852
11853 // Set model on player model entity
11854 fm_set_playermodel_ent(id)
11855 }
11856 else
11857 {
11858 // Get current model for comparing it with the current one
11859 fm_cs_get_user_model(id, currentmodel, charsmax(currentmodel))
11860
11861 // Set the right model, after checking that we don't already have it
11862 if (!equal(currentmodel, newmodel))
11863 {
11864 copy(g_playermodel[id], charsmax(g_playermodel[]), newmodel)
11865 if (g_set_modelindex_offset && modelindex) fm_cs_set_user_model_index(id, modelindex)
11866
11867 // An additional delay is offset at round start
11868 // since SVC_BAD is more likely to be triggered there
11869 if (g_newround)
11870 set_task(5.0 * g_modelchange_delay, "fm_user_model_update", id+TASK_MODEL)
11871 else
11872 fm_user_model_update(id+TASK_MODEL)
11873 }
11874 }
11875 return true;
11876}
11877
11878// Native: zp_get_user_model
11879public native_get_user_model(plugin_id, param_nums)
11880{
11881 // ZPA disabled
11882 if (!g_pluginenabled)
11883 return -1;
11884
11885 // Insufficient number of arguments
11886 if (param_nums != 3)
11887 return -1;
11888
11889 // Retrieve the player's index
11890 static id; id = get_param(1)
11891
11892 // Not an alive player or invalid player
11893 if (!is_user_valid_alive(id))
11894 return 0;
11895
11896 // Retrieve the player's current model
11897 static current_model[32]
11898 fm_cs_get_user_model(id, current_model, charsmax(current_model))
11899
11900 // Copy the model name into the array passed
11901 set_string(2, current_model, get_param(3))
11902
11903 return 1;
11904}
11905
11906// Native: zp_set_user_model
11907public native_set_user_model(id, const model[])
11908{
11909 // ZPA disabled
11910 if (!g_pluginenabled)
11911 return -1;
11912
11913 // Not an alive player or invalid player
11914 if (!is_user_valid_alive(id))
11915 return -1;
11916
11917 // Strings passed byref
11918 param_convert(2)
11919
11920 // Retrieve the player's current model
11921 static current_model[32]
11922 fm_cs_get_user_model(id, current_model, charsmax(current_model))
11923
11924 // Check whether we already have the model set on the player
11925 if (equal(current_model, model))
11926 return 0;
11927
11928 // Update player's model
11929 copy(g_playermodel[id], charsmax(g_playermodel[]), model)
11930
11931 // Set the right model for the player
11932 if (g_handle_models_on_separate_ent) fm_set_playermodel_ent(id)
11933 else fm_user_model_update(id+TASK_MODEL)
11934
11935 return 1;
11936}
11937
11938// Native: zp_has_round_started
11939public native_has_round_started()
11940{
11941 if (g_newround) return 0; // not started
11942 if (g_modestarted) return 1; // started
11943 return 2; // starting
11944}
11945
11946// Native: zp_is_nemesis_round
11947public native_is_nemesis_round()
11948{
11949 return g_nemround;
11950}
11951
11952// Native: zp_is_assassin_round
11953public native_is_assassin_round()
11954{
11955 return g_assaround;
11956}
11957
11958// Native: zp_is_survivor_round
11959public native_is_survivor_round()
11960{
11961 return g_survround;
11962}
11963
11964// Native: zp_is_sniper_round
11965public native_is_sniper_round()
11966{
11967 return g_sniround;
11968}
11969
11970// Native: zp_is_swarm_round
11971public native_is_swarm_round()
11972{
11973 return g_swarmround;
11974}
11975
11976// Native: zp_is_plague_round
11977public native_is_plague_round()
11978{
11979 return g_plagueround;
11980}
11981
11982// Native: zp_is_armageddon_round
11983public native_is_armageddon_round()
11984{
11985 return g_armageround;
11986}
11987
11988// Native: zp_is_apocalypse_round
11989public native_is_apocalypse_round()
11990{
11991 return g_apocround;
11992}
11993
11994// Native: zp_is_nightmare_round
11995public native_is_nightmare_round()
11996{
11997 return g_nightround;
11998}
11999
12000// Native: zp_get_zombie_count
12001public native_get_zombie_count()
12002{
12003 return fnGetZombies();
12004}
12005
12006// Native: zp_get_human_count
12007public native_get_human_count()
12008{
12009 return fnGetHumans();
12010}
12011
12012// Native: zp_get_nemesis_count
12013public native_get_nemesis_count()
12014{
12015 return fnGetNemesis();
12016}
12017
12018// Native: zp_get_assassin_count
12019public native_get_assassin_count()
12020{
12021 return fnGetAssassin();
12022}
12023
12024// Native: zp_get_survivor_count
12025public native_get_survivor_count()
12026{
12027 return fnGetSurvivors();
12028}
12029
12030// Native: zp_get_sniper_count
12031public native_get_sniper_count()
12032{
12033 return fnGetSnipers();
12034}
12035
12036// Native: zp_register_extra_item
12037public native_register_extra_item(const name[], cost, team)
12038{
12039 // ZP disabled
12040 if (!g_pluginenabled)
12041 return -1;
12042
12043 // Strings passed byref
12044 param_convert(1)
12045
12046 // Arrays not yet initialized
12047 if (!g_arrays_created)
12048 {
12049 log_error(AMX_ERR_NATIVE, "[ZP] Can't register extra item yet (%s)", name)
12050 return -1;
12051 }
12052
12053 if (strlen(name) < 1)
12054 {
12055 log_error(AMX_ERR_NATIVE, "[ZP] Can't register extra item with an empty name")
12056 return -1;
12057 }
12058
12059 new index, extraitem_name[32]
12060 for (index = 0; index < g_extraitem_i; index++)
12061 {
12062 ArrayGetString(g_extraitem_name, index, extraitem_name, charsmax(extraitem_name))
12063 if (equali(name, extraitem_name))
12064 {
12065 log_error(AMX_ERR_NATIVE, "[ZP] Extra item already registered (%s)", name)
12066 return -1;
12067 }
12068 }
12069
12070 // For backwards compatibility
12071 if (team == ZP_TEAM_ANY)
12072 team = (ZP_TEAM_ZOMBIE|ZP_TEAM_HUMAN)
12073
12074 // Add the item
12075 ArrayPushString(g_extraitem_name, name)
12076 ArrayPushCell(g_extraitem_cost, cost)
12077 ArrayPushCell(g_extraitem_team, team)
12078
12079 // Set temporary new item flag
12080 ArrayPushCell(g_extraitem_new, 1)
12081
12082 // Override extra items data with our customizations
12083 new i, buffer[32], size = ArraySize(g_extraitem2_realname)
12084 for (i = 0; i < size; i++)
12085 {
12086 ArrayGetString(g_extraitem2_realname, i, buffer, charsmax(buffer))
12087
12088 // Check if this is the intended item to override
12089 if (!equal(name, buffer))
12090 continue;
12091
12092 // Remove new item flag
12093 ArraySetCell(g_extraitem_new, g_extraitem_i, 0)
12094
12095 // Replace caption
12096 ArrayGetString(g_extraitem2_name, i, buffer, charsmax(buffer))
12097 ArraySetString(g_extraitem_name, g_extraitem_i, buffer)
12098
12099 // Replace cost
12100 buffer[0] = ArrayGetCell(g_extraitem2_cost, i)
12101 ArraySetCell(g_extraitem_cost, g_extraitem_i, buffer[0])
12102
12103 // Replace team
12104 buffer[0] = ArrayGetCell(g_extraitem2_team, i)
12105 ArraySetCell(g_extraitem_team, g_extraitem_i, buffer[0])
12106 }
12107
12108 // Increase registered items counter
12109 g_extraitem_i++
12110
12111 // Return id under which we registered the item
12112 return g_extraitem_i-1;
12113}
12114
12115// Function: zp_register_extra_item (to be used within this plugin only)
12116native_register_extra_item2(const name[], cost, team)
12117{
12118 // Add the item
12119 ArrayPushString(g_extraitem_name, name)
12120 ArrayPushCell(g_extraitem_cost, cost)
12121 ArrayPushCell(g_extraitem_team, team)
12122
12123 // Set temporary new item flag
12124 ArrayPushCell(g_extraitem_new, 1)
12125
12126 // Increase registered items counter
12127 g_extraitem_i++
12128}
12129
12130// Native: zp_register_zombie_class
12131public native_register_zombie_class(const name[], const info[], const model[], const clawmodel[], hp, speed, Float:gravity, Float:knockback)
12132{
12133 // ZP disabled
12134 if (!g_pluginenabled)
12135 return -1;
12136
12137 // Strings passed byref
12138 param_convert(1)
12139 param_convert(2)
12140 param_convert(3)
12141 param_convert(4)
12142
12143 // Arrays not yet initialized
12144 if (!g_arrays_created)
12145 {
12146 log_error(AMX_ERR_NATIVE, "[ZP] Can't register zombie class yet (%s)", name)
12147 return -1;
12148 }
12149
12150 if (strlen(name) < 1)
12151 {
12152 log_error(AMX_ERR_NATIVE, "[ZP] Can't register zombie class with an empty name")
12153 return -1;
12154 }
12155
12156 new index, zombieclass_name[32]
12157 for (index = 0; index < g_zclass_i; index++)
12158 {
12159 ArrayGetString(g_zclass_name, index, zombieclass_name, charsmax(zombieclass_name))
12160 if (equali(name, zombieclass_name))
12161 {
12162 log_error(AMX_ERR_NATIVE, "[ZP] Zombie class already registered (%s)", name)
12163 return -1;
12164 }
12165 }
12166
12167 // Add the class
12168 ArrayPushString(g_zclass_name, name)
12169 ArrayPushString(g_zclass_info, info)
12170
12171 // Using same zombie models for all classes?
12172 if (g_same_models_for_all)
12173 {
12174 ArrayPushCell(g_zclass_modelsstart, 0)
12175 ArrayPushCell(g_zclass_modelsend, ArraySize(g_zclass_playermodel))
12176 }
12177 else
12178 {
12179 ArrayPushCell(g_zclass_modelsstart, ArraySize(g_zclass_playermodel))
12180 ArrayPushString(g_zclass_playermodel, model)
12181 ArrayPushCell(g_zclass_modelsend, ArraySize(g_zclass_playermodel))
12182 ArrayPushCell(g_zclass_modelindex, -1)
12183 }
12184
12185 ArrayPushString(g_zclass_clawmodel, clawmodel)
12186 ArrayPushCell(g_zclass_hp, hp)
12187 ArrayPushCell(g_zclass_spd, speed)
12188 ArrayPushCell(g_zclass_grav, gravity)
12189 ArrayPushCell(g_zclass_kb, knockback)
12190
12191 // Set temporary new class flag
12192 ArrayPushCell(g_zclass_new, 1)
12193
12194 // Override zombie classes data with our customizations
12195 new i, k, buffer[32], Float:buffer2, nummodels_custom, nummodels_default, prec_mdl[100], size = ArraySize(g_zclass2_realname)
12196 for (i = 0; i < size; i++)
12197 {
12198 ArrayGetString(g_zclass2_realname, i, buffer, charsmax(buffer))
12199
12200 // Check if this is the intended class to override
12201 if (!equal(name, buffer))
12202 continue;
12203
12204 // Remove new class flag
12205 ArraySetCell(g_zclass_new, g_zclass_i, 0)
12206
12207 // Replace caption
12208 ArrayGetString(g_zclass2_name, i, buffer, charsmax(buffer))
12209 ArraySetString(g_zclass_name, g_zclass_i, buffer)
12210
12211 // Replace info
12212 ArrayGetString(g_zclass2_info, i, buffer, charsmax(buffer))
12213 ArraySetString(g_zclass_info, g_zclass_i, buffer)
12214
12215 // Replace models, unless using same models for all classes
12216 if (!g_same_models_for_all)
12217 {
12218 nummodels_custom = ArrayGetCell(g_zclass2_modelsend, i) - ArrayGetCell(g_zclass2_modelsstart, i)
12219 nummodels_default = ArrayGetCell(g_zclass_modelsend, g_zclass_i) - ArrayGetCell(g_zclass_modelsstart, g_zclass_i)
12220
12221 // Replace each player model and model index
12222 for (k = 0; k < min(nummodels_custom, nummodels_default); k++)
12223 {
12224 ArrayGetString(g_zclass2_playermodel, ArrayGetCell(g_zclass2_modelsstart, i) + k, buffer, charsmax(buffer))
12225 ArraySetString(g_zclass_playermodel, ArrayGetCell(g_zclass_modelsstart, g_zclass_i) + k, buffer)
12226
12227 // Precache player model and replace its modelindex with the real one
12228 formatex(prec_mdl, charsmax(prec_mdl), "models/player/%s/%s.mdl", buffer, buffer)
12229 ArraySetCell(g_zclass_modelindex, ArrayGetCell(g_zclass_modelsstart, g_zclass_i) + k, engfunc(EngFunc_PrecacheModel, prec_mdl))
12230 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, prec_mdl)
12231 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, prec_mdl)
12232 // Precache modelT.mdl files too
12233 copy(prec_mdl[strlen(prec_mdl)-4], charsmax(prec_mdl) - (strlen(prec_mdl)-4), "T.mdl")
12234 if (file_exists(prec_mdl)) engfunc(EngFunc_PrecacheModel, prec_mdl)
12235 }
12236
12237 // We have more custom models than what we can accommodate,
12238 // Let's make some space...
12239 if (nummodels_custom > nummodels_default)
12240 {
12241 for (k = nummodels_default; k < nummodels_custom; k++)
12242 {
12243 ArrayGetString(g_zclass2_playermodel, ArrayGetCell(g_zclass2_modelsstart, i) + k, buffer, charsmax(buffer))
12244 ArrayInsertStringAfter(g_zclass_playermodel, ArrayGetCell(g_zclass_modelsstart, g_zclass_i) + k - 1, buffer)
12245
12246 // Precache player model and retrieve its modelindex
12247 formatex(prec_mdl, charsmax(prec_mdl), "models/player/%s/%s.mdl", buffer, buffer)
12248 ArrayInsertCellAfter(g_zclass_modelindex, ArrayGetCell(g_zclass_modelsstart, g_zclass_i) + k - 1, engfunc(EngFunc_PrecacheModel, prec_mdl))
12249 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, prec_mdl)
12250 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, prec_mdl)
12251 // Precache modelT.mdl files too
12252 copy(prec_mdl[strlen(prec_mdl)-4], charsmax(prec_mdl) - (strlen(prec_mdl)-4), "T.mdl")
12253 if (file_exists(prec_mdl)) engfunc(EngFunc_PrecacheModel, prec_mdl)
12254 }
12255
12256 // Fix models end index for this class
12257 ArraySetCell(g_zclass_modelsend, g_zclass_i, ArrayGetCell(g_zclass_modelsend, g_zclass_i) + (nummodels_custom - nummodels_default))
12258 }
12259
12260 /* --- Not needed since classes can't have more than 1 default model for now ---
12261 // We have less custom models than what this class has by default,
12262 // Get rid of those extra entries...
12263 if (nummodels_custom < nummodels_default)
12264 {
12265 for (k = nummodels_custom; k < nummodels_default; k++)
12266 {
12267 ArrayDeleteItem(g_zclass_playermodel, ArrayGetCell(g_zclass_modelsstart, g_zclass_i) + nummodels_custom)
12268 }
12269
12270 // Fix models end index for this class
12271 ArraySetCell(g_zclass_modelsend, g_zclass_i, ArrayGetCell(g_zclass_modelsend, g_zclass_i) - (nummodels_default - nummodels_custom))
12272 }
12273 */
12274 }
12275
12276 // Replace clawmodel
12277 ArrayGetString(g_zclass2_clawmodel, i, buffer, charsmax(buffer))
12278 ArraySetString(g_zclass_clawmodel, g_zclass_i, buffer)
12279
12280 // Precache clawmodel
12281 formatex(prec_mdl, charsmax(prec_mdl), "models/zombie_plague/%s", buffer)
12282 engfunc(EngFunc_PrecacheModel, prec_mdl)
12283
12284 // Replace health
12285 buffer[0] = ArrayGetCell(g_zclass2_hp, i)
12286 ArraySetCell(g_zclass_hp, g_zclass_i, buffer[0])
12287
12288 // Replace speed
12289 buffer[0] = ArrayGetCell(g_zclass2_spd, i)
12290 ArraySetCell(g_zclass_spd, g_zclass_i, buffer[0])
12291
12292 // Replace gravity
12293 buffer2 = Float:ArrayGetCell(g_zclass2_grav, i)
12294 ArraySetCell(g_zclass_grav, g_zclass_i, buffer2)
12295
12296 // Replace knockback
12297 buffer2 = Float:ArrayGetCell(g_zclass2_kb, i)
12298 ArraySetCell(g_zclass_kb, g_zclass_i, buffer2)
12299 }
12300
12301 // If class was not overriden with customization data
12302 if (ArrayGetCell(g_zclass_new, g_zclass_i))
12303 {
12304 // If not using same models for all classes
12305 if (!g_same_models_for_all)
12306 {
12307 // Precache default class model and replace modelindex with the real one
12308 formatex(prec_mdl, charsmax(prec_mdl), "models/player/%s/%s.mdl", model, model)
12309 ArraySetCell(g_zclass_modelindex, ArrayGetCell(g_zclass_modelsstart, g_zclass_i), engfunc(EngFunc_PrecacheModel, prec_mdl))
12310 if (g_force_consistency == 1) force_unmodified(force_model_samebounds, {0,0,0}, {0,0,0}, prec_mdl)
12311 if (g_force_consistency == 2) force_unmodified(force_exactfile, {0,0,0}, {0,0,0}, prec_mdl)
12312 // Precache modelT.mdl files too
12313 copy(prec_mdl[strlen(prec_mdl)-4], charsmax(prec_mdl) - (strlen(prec_mdl)-4), "T.mdl")
12314 if (file_exists(prec_mdl)) engfunc(EngFunc_PrecacheModel, prec_mdl)
12315 }
12316
12317 // Precache default clawmodel
12318 formatex(prec_mdl, charsmax(prec_mdl), "models/zombie_plague/%s", clawmodel)
12319 engfunc(EngFunc_PrecacheModel, prec_mdl)
12320 }
12321
12322 // Increase registered classes counter
12323 g_zclass_i++
12324
12325 // Return id under which we registered the class
12326 return g_zclass_i-1;
12327}
12328
12329// Native: zp_get_extra_item_id
12330public native_get_extra_item_id(const name[])
12331{
12332 // ZP disabled
12333 if (!g_pluginenabled)
12334 return -1;
12335
12336 // Strings passed byref
12337 param_convert(1)
12338
12339 // Loop through every item (not using Tries since ZP should work on AMXX 1.8.0)
12340 static i, item_name[32]
12341 for (i = 0; i < g_extraitem_i; i++)
12342 {
12343 ArrayGetString(g_extraitem_name, i, item_name, charsmax(item_name))
12344
12345 // Check if this is the item to retrieve
12346 if (equali(name, item_name))
12347 return i;
12348 }
12349
12350 return -1;
12351}
12352
12353// Native: zp_get_zombie_class_id
12354public native_get_zombie_class_id(const name[])
12355{
12356 // ZP disabled
12357 if (!g_pluginenabled)
12358 return -1;
12359
12360 // Strings passed byref
12361 param_convert(1)
12362
12363 // Loop through every class (not using Tries since ZP should work on AMXX 1.8.0)
12364 static i, class_name[32]
12365 for (i = 0; i < g_zclass_i; i++)
12366 {
12367 ArrayGetString(g_zclass_name, i, class_name, charsmax(class_name))
12368
12369 // Check if this is the class to retrieve
12370 if (equali(name, class_name))
12371 return i;
12372 }
12373
12374 return -1;
12375}
12376
12377// Native: zp_get_zombie_class_info
12378public native_get_zombie_class_info(classid, info[], len)
12379{
12380 // ZP disabled
12381 if (!g_pluginenabled)
12382 return false;
12383
12384 // Invalid class
12385 if (classid < 0 || classid >= g_zclass_i)
12386 {
12387 log_error(AMX_ERR_NATIVE, "[ZP] Invalid zombie class id (%d)", classid)
12388 return false;
12389 }
12390
12391 // Strings passed byref
12392 param_convert(2)
12393
12394 // Fetch zombie class info
12395 ArrayGetString(g_zclass_info, classid, info, len)
12396 return true;
12397}
12398
12399/*================================================================================
12400 [Custom Messages]
12401=================================================================================*/
12402
12403// Custom Night Vision
12404public set_user_nvision(taskid)
12405{
12406 // Get player's origin
12407 static origin[3]
12408 get_user_origin(ID_NVISION, origin)
12409
12410 // Nightvision message
12411 message_begin(MSG_ONE_UNRELIABLE, SVC_TEMPENTITY, _, ID_NVISION)
12412 write_byte(TE_DLIGHT) // TE id
12413 write_coord(origin[0]) // x
12414 write_coord(origin[1]) // y
12415 write_coord(origin[2]) // z
12416 write_byte(get_pcvar_num(cvar_nvgsize)) // radius
12417
12418 // Nemesis / Madness / Spectator in nemesis round
12419 if (g_nemesis[ID_NVISION] || (g_zombie[ID_NVISION] && g_nodamage[ID_NVISION]) || (!g_isalive[ID_NVISION] && g_nemround))
12420 {
12421 write_byte(get_pcvar_num(cvar_nemnvgcolor[0])) // r
12422 write_byte(get_pcvar_num(cvar_nemnvgcolor[1])) // g
12423 write_byte(get_pcvar_num(cvar_nemnvgcolor[2])) // b
12424 }
12425 // Assassin / Spectator in assassin round
12426 else if (g_assassin[ID_NVISION] || (!g_isalive[ID_NVISION] && g_assaround))
12427 {
12428 write_byte(get_pcvar_num(cvar_assanvgcolor[0])) // r
12429 write_byte(get_pcvar_num(cvar_assanvgcolor[1])) // g
12430 write_byte(get_pcvar_num(cvar_assanvgcolor[2])) // b
12431 }
12432 // Human / Spectator in normal round
12433 else if (!g_zombie[ID_NVISION] || !g_isalive[ID_NVISION])
12434 {
12435 write_byte(get_pcvar_num(cvar_humnvgcolor[0])) // r
12436 write_byte(get_pcvar_num(cvar_humnvgcolor[1])) // g
12437 write_byte(get_pcvar_num(cvar_humnvgcolor[2])) // b
12438 }
12439 // Zombie
12440 else
12441 {
12442 write_byte(get_pcvar_num(cvar_nvgcolor[0])) // r
12443 write_byte(get_pcvar_num(cvar_nvgcolor[1])) // g
12444 write_byte(get_pcvar_num(cvar_nvgcolor[2])) // b
12445 }
12446
12447 write_byte(2) // life
12448 write_byte(0) // decay rate
12449 message_end()
12450}
12451
12452// Game Nightvision
12453set_user_gnvision(id, toggle)
12454{
12455 // Toggle NVG message
12456 message_begin(MSG_ONE, g_msgNVGToggle, _, id)
12457 write_byte(toggle) // toggle
12458 message_end()
12459}
12460
12461// Custom Flashlight
12462public set_user_flashlight(taskid)
12463{
12464 // Get player and aiming origins
12465 static Float:originF[3], Float:destoriginF[3]
12466 pev(ID_FLASH, pev_origin, originF)
12467 fm_get_aim_origin(ID_FLASH, destoriginF)
12468
12469 // Max distance check
12470 if (get_distance_f(originF, destoriginF) > get_pcvar_float(cvar_flashdist))
12471 return;
12472
12473 // Send to all players?
12474 if (get_pcvar_num(cvar_flashshowall))
12475 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, destoriginF, 0)
12476 else
12477 message_begin(MSG_ONE_UNRELIABLE, SVC_TEMPENTITY, _, ID_FLASH)
12478
12479 // Flashlight
12480 write_byte(TE_DLIGHT) // TE id
12481 engfunc(EngFunc_WriteCoord, destoriginF[0]) // x
12482 engfunc(EngFunc_WriteCoord, destoriginF[1]) // y
12483 engfunc(EngFunc_WriteCoord, destoriginF[2]) // z
12484 write_byte(get_pcvar_num(cvar_flashsize)) // radius
12485 write_byte(get_pcvar_num(cvar_flashcolor[0])) // r
12486 write_byte(get_pcvar_num(cvar_flashcolor[1])) // g
12487 write_byte(get_pcvar_num(cvar_flashcolor[2])) // b
12488 write_byte(3) // life
12489 write_byte(0) // decay rate
12490 message_end()
12491}
12492
12493// Infection special effects
12494infection_effects(id)
12495{
12496 // Screen fade? (unless frozen)
12497 if (!g_frozen[id] && get_pcvar_num(cvar_infectionscreenfade))
12498 {
12499 message_begin(MSG_ONE_UNRELIABLE, g_msgScreenFade, _, id)
12500 write_short(UNIT_SECOND) // duration
12501 write_short(0) // hold time
12502 write_short(FFADE_IN) // fade type
12503 if (g_nemesis[id])
12504 {
12505 write_byte(get_pcvar_num(cvar_nemnvgcolor[0])) // r
12506 write_byte(get_pcvar_num(cvar_nemnvgcolor[1])) // g
12507 write_byte(get_pcvar_num(cvar_nemnvgcolor[2])) // b
12508 }
12509 else if (g_assassin[id])
12510 {
12511 write_byte(get_pcvar_num(cvar_assanvgcolor[0])) // r
12512 write_byte(get_pcvar_num(cvar_assanvgcolor[1])) // g
12513 write_byte(get_pcvar_num(cvar_assanvgcolor[2])) // b
12514 }
12515 else
12516 {
12517 write_byte(get_pcvar_num(cvar_nvgcolor[0])) // r
12518 write_byte(get_pcvar_num(cvar_nvgcolor[1])) // g
12519 write_byte(get_pcvar_num(cvar_nvgcolor[2])) // b
12520 }
12521 write_byte (255) // alpha
12522 message_end()
12523 }
12524
12525 // Screen shake?
12526 if (get_pcvar_num(cvar_infectionscreenshake))
12527 {
12528 message_begin(MSG_ONE_UNRELIABLE, g_msgScreenShake, _, id)
12529 write_short(UNIT_SECOND*4) // amplitude
12530 write_short(UNIT_SECOND*2) // duration
12531 write_short(UNIT_SECOND*10) // frequency
12532 message_end()
12533 }
12534
12535 // Infection icon?
12536 if (get_pcvar_num(cvar_hudicons))
12537 {
12538 message_begin(MSG_ONE_UNRELIABLE, g_msgDamage, _, id)
12539 write_byte(0) // damage save
12540 write_byte(0) // damage take
12541 write_long(DMG_NERVEGAS) // damage type - DMG_RADIATION
12542 write_coord(0) // x
12543 write_coord(0) // y
12544 write_coord(0) // z
12545 message_end()
12546 }
12547
12548 // Get player's origin
12549 static origin[3]
12550 get_user_origin(id, origin)
12551
12552 // Tracers?
12553 if (get_pcvar_num(cvar_infectiontracers))
12554 {
12555 message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
12556 write_byte(TE_IMPLOSION) // TE id
12557 write_coord(origin[0]) // x
12558 write_coord(origin[1]) // y
12559 write_coord(origin[2]) // z
12560 write_byte(128) // radius
12561 write_byte(20) // count
12562 write_byte(3) // duration
12563 message_end()
12564 }
12565
12566 // Particle burst?
12567 if (get_pcvar_num(cvar_infectionparticles))
12568 {
12569 message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
12570 write_byte(TE_PARTICLEBURST) // TE id
12571 write_coord(origin[0]) // x
12572 write_coord(origin[1]) // y
12573 write_coord(origin[2]) // z
12574 write_short(50) // radius
12575 write_byte(70) // color
12576 write_byte(3) // duration (will be randomized a bit)
12577 message_end()
12578 }
12579
12580 // Light sparkle?
12581 if (get_pcvar_num(cvar_infectionsparkle))
12582 {
12583 message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
12584 write_byte(TE_DLIGHT) // TE id
12585 write_coord(origin[0]) // x
12586 write_coord(origin[1]) // y
12587 write_coord(origin[2]) // z
12588 write_byte(20) // radius
12589 write_byte(get_pcvar_num(cvar_nvgcolor[0])) // r
12590 write_byte(get_pcvar_num(cvar_nvgcolor[1])) // g
12591 write_byte(get_pcvar_num(cvar_nvgcolor[2])) // b
12592 write_byte(2) // life
12593 write_byte(0) // decay rate
12594 message_end()
12595 }
12596}
12597
12598// Nemesis/madness aura task
12599public zombie_aura(taskid)
12600{
12601 // Not nemesis, not assassin, not in zombie madness
12602 if (!g_nemesis[ID_AURA] && !g_assassin[ID_AURA] && !g_nodamage[ID_AURA])
12603 {
12604 // Task not needed anymore
12605 remove_task(taskid);
12606 return;
12607 }
12608
12609 // Get player's origin
12610 static origin[3]
12611 get_user_origin(ID_AURA, origin)
12612
12613 // Colored Aura
12614 message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
12615 write_byte(TE_DLIGHT) // TE id
12616 write_coord(origin[0]) // x
12617 write_coord(origin[1]) // y
12618 write_coord(origin[2]) // z
12619 write_byte(20) // radius
12620
12621 if (g_assassin[ID_AURA])
12622 {
12623 write_byte(get_pcvar_num(cvar_assanvgcolor[0])) // r
12624 write_byte(get_pcvar_num(cvar_assanvgcolor[1])) // g
12625 write_byte(get_pcvar_num(cvar_assanvgcolor[2])) // b
12626 }
12627 else
12628 {
12629 write_byte(get_pcvar_num(cvar_nemnvgcolor[0])) // r
12630 write_byte(get_pcvar_num(cvar_nemnvgcolor[1])) // g
12631 write_byte(get_pcvar_num(cvar_nemnvgcolor[2])) // b
12632 }
12633
12634 write_byte(2) // life
12635 write_byte(0) // decay rate
12636 message_end()
12637}
12638
12639// Make zombies leave footsteps and bloodstains on the floor
12640public make_blood(taskid)
12641{
12642 // Only bleed when moving on ground
12643 if (!(pev(ID_BLOOD, pev_flags) & FL_ONGROUND) || fm_get_speed(ID_BLOOD) < 80)
12644 return;
12645
12646 // Get user origin
12647 static Float:originF[3]
12648 pev(ID_BLOOD, pev_origin, originF)
12649
12650 // If ducking set a little lower
12651 if (pev(ID_BLOOD, pev_bInDuck))
12652 originF[2] -= 18.0
12653 else
12654 originF[2] -= 36.0
12655
12656 // Send the decal message
12657 engfunc(EngFunc_MessageBegin, MSG_PAS, SVC_TEMPENTITY, originF, 0)
12658 write_byte(TE_WORLDDECAL) // TE id
12659 engfunc(EngFunc_WriteCoord, originF[0]) // x
12660 engfunc(EngFunc_WriteCoord, originF[1]) // y
12661 engfunc(EngFunc_WriteCoord, originF[2]) // z
12662 write_byte(ArrayGetCell(zombie_decals, random_num(0, ArraySize(zombie_decals) - 1)) + (g_czero * 12)) // random decal number (offsets +12 for CZ)
12663 message_end()
12664}
12665
12666// Flare Lighting Effects
12667flare_lighting(entity, duration)
12668{
12669 // Get origin and color
12670 static Float:originF[3], color[3]
12671 pev(entity, pev_origin, originF)
12672 pev(entity, PEV_FLARE_COLOR, color)
12673
12674 // Lighting
12675 engfunc(EngFunc_MessageBegin, MSG_PAS, SVC_TEMPENTITY, originF, 0)
12676 write_byte(TE_DLIGHT) // TE id
12677 engfunc(EngFunc_WriteCoord, originF[0]) // x
12678 engfunc(EngFunc_WriteCoord, originF[1]) // y
12679 engfunc(EngFunc_WriteCoord, originF[2]) // z
12680 write_byte(get_pcvar_num(cvar_flaresize)) // radius
12681 write_byte(color[0]) // r
12682 write_byte(color[1]) // g
12683 write_byte(color[2]) // b
12684 write_byte(21) //life
12685 write_byte((duration < 2) ? 3 : 0) //decay rate
12686 message_end()
12687
12688 // Sparks
12689 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12690 write_byte(TE_SPARKS) // TE id
12691 engfunc(EngFunc_WriteCoord, originF[0]) // x
12692 engfunc(EngFunc_WriteCoord, originF[1]) // y
12693 engfunc(EngFunc_WriteCoord, originF[2]) // z
12694 message_end()
12695}
12696
12697// Burning Flames
12698public burning_flame(taskid)
12699{
12700 // Get player origin and flags
12701 static origin[3], flags
12702 get_user_origin(ID_BURN, origin)
12703 flags = pev(ID_BURN, pev_flags)
12704
12705 // Madness mode - in water - burning stopped
12706 if (g_nodamage[ID_BURN] || (flags & FL_INWATER) || g_burning_duration[ID_BURN] < 1)
12707 {
12708 // Smoke sprite
12709 message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
12710 write_byte(TE_SMOKE) // TE id
12711 write_coord(origin[0]) // x
12712 write_coord(origin[1]) // y
12713 write_coord(origin[2]-50) // z
12714 write_short(g_smokeSpr) // sprite
12715 write_byte(random_num(15, 20)) // scale
12716 write_byte(random_num(10, 20)) // framerate
12717 message_end()
12718
12719 // Task not needed anymore
12720 remove_task(taskid);
12721 return;
12722 }
12723
12724 // Randomly play burning zombie scream sounds (not for nemesis)
12725 if (!g_nemesis[ID_BURN] && !g_assassin[ID_BURN] && !random_num(0, 20))
12726 {
12727 static sound[64]
12728 ArrayGetString(grenade_fire_player, random_num(0, ArraySize(grenade_fire_player) - 1), sound, charsmax(sound))
12729 emit_sound(ID_BURN, CHAN_VOICE, sound, 1.0, ATTN_NORM, 0, PITCH_NORM)
12730 }
12731
12732 // Fire slow down, unless nemesis
12733 if (!g_nemesis[ID_BURN] && !g_assassin[ID_BURN] && (flags & FL_ONGROUND) && get_pcvar_float(cvar_fireslowdown) > 0.0)
12734 {
12735 static Float:velocity[3]
12736 pev(ID_BURN, pev_velocity, velocity)
12737 xs_vec_mul_scalar(velocity, get_pcvar_float(cvar_fireslowdown), velocity)
12738 set_pev(ID_BURN, pev_velocity, velocity)
12739 }
12740
12741 // Get player's health
12742 static health
12743 health = pev(ID_BURN, pev_health)
12744
12745 // Take damage from the fire
12746 if (health - floatround(get_pcvar_float(cvar_firedamage), floatround_ceil) > 0)
12747 fm_set_user_health(ID_BURN, health - floatround(get_pcvar_float(cvar_firedamage), floatround_ceil))
12748
12749 // Flame sprite
12750 message_begin(MSG_PVS, SVC_TEMPENTITY, origin)
12751 write_byte(TE_SPRITE) // TE id
12752 write_coord(origin[0]+random_num(-5, 5)) // x
12753 write_coord(origin[1]+random_num(-5, 5)) // y
12754 write_coord(origin[2]+random_num(-10, 10)) // z
12755 write_short(g_flameSpr) // sprite
12756 write_byte(random_num(5, 10)) // scale
12757 write_byte(200) // brightness
12758 message_end()
12759
12760 // Decrease burning duration counter
12761 g_burning_duration[ID_BURN]--
12762}
12763
12764// Infection Bomb: Green Blast
12765create_blast(const Float:originF[3])
12766{
12767 // Smallest ring
12768 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12769 write_byte(TE_BEAMCYLINDER) // TE id
12770 engfunc(EngFunc_WriteCoord, originF[0]) // x
12771 engfunc(EngFunc_WriteCoord, originF[1]) // y
12772 engfunc(EngFunc_WriteCoord, originF[2]) // z
12773 engfunc(EngFunc_WriteCoord, originF[0]) // x axis
12774 engfunc(EngFunc_WriteCoord, originF[1]) // y axis
12775 engfunc(EngFunc_WriteCoord, originF[2]+385.0) // z axis
12776 write_short(g_exploSpr) // sprite
12777 write_byte(0) // startframe
12778 write_byte(0) // framerate
12779 write_byte(4) // life
12780 write_byte(60) // width
12781 write_byte(0) // noise
12782 write_byte(0) // red
12783 write_byte(200) // green
12784 write_byte(0) // blue
12785 write_byte(200) // brightness
12786 write_byte(0) // speed
12787 message_end()
12788
12789 // Medium ring
12790 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12791 write_byte(TE_BEAMCYLINDER) // TE id
12792 engfunc(EngFunc_WriteCoord, originF[0]) // x
12793 engfunc(EngFunc_WriteCoord, originF[1]) // y
12794 engfunc(EngFunc_WriteCoord, originF[2]) // z
12795 engfunc(EngFunc_WriteCoord, originF[0]) // x axis
12796 engfunc(EngFunc_WriteCoord, originF[1]) // y axis
12797 engfunc(EngFunc_WriteCoord, originF[2]+470.0) // z axis
12798 write_short(g_exploSpr) // sprite
12799 write_byte(0) // startframe
12800 write_byte(0) // framerate
12801 write_byte(4) // life
12802 write_byte(60) // width
12803 write_byte(0) // noise
12804 write_byte(0) // red
12805 write_byte(200) // green
12806 write_byte(0) // blue
12807 write_byte(200) // brightness
12808 write_byte(0) // speed
12809 message_end()
12810
12811 // Largest ring
12812 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12813 write_byte(TE_BEAMCYLINDER) // TE id
12814 engfunc(EngFunc_WriteCoord, originF[0]) // x
12815 engfunc(EngFunc_WriteCoord, originF[1]) // y
12816 engfunc(EngFunc_WriteCoord, originF[2]) // z
12817 engfunc(EngFunc_WriteCoord, originF[0]) // x axis
12818 engfunc(EngFunc_WriteCoord, originF[1]) // y axis
12819 engfunc(EngFunc_WriteCoord, originF[2]+555.0) // z axis
12820 write_short(g_exploSpr) // sprite
12821 write_byte(0) // startframe
12822 write_byte(0) // framerate
12823 write_byte(4) // life
12824 write_byte(60) // width
12825 write_byte(0) // noise
12826 write_byte(0) // red
12827 write_byte(200) // green
12828 write_byte(0) // blue
12829 write_byte(200) // brightness
12830 write_byte(0) // speed
12831 message_end()
12832}
12833
12834// Fire Grenade: Fire Blast
12835create_blast2(const Float:originF[3])
12836{
12837 // Smallest ring
12838 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12839 write_byte(TE_BEAMCYLINDER) // TE id
12840 engfunc(EngFunc_WriteCoord, originF[0]) // x
12841 engfunc(EngFunc_WriteCoord, originF[1]) // y
12842 engfunc(EngFunc_WriteCoord, originF[2]) // z
12843 engfunc(EngFunc_WriteCoord, originF[0]) // x axis
12844 engfunc(EngFunc_WriteCoord, originF[1]) // y axis
12845 engfunc(EngFunc_WriteCoord, originF[2]+385.0) // z axis
12846 write_short(g_exploSpr) // sprite
12847 write_byte(0) // startframe
12848 write_byte(0) // framerate
12849 write_byte(4) // life
12850 write_byte(60) // width
12851 write_byte(0) // noise
12852 write_byte(200) // red
12853 write_byte(100) // green
12854 write_byte(0) // blue
12855 write_byte(200) // brightness
12856 write_byte(0) // speed
12857 message_end()
12858
12859 // Medium ring
12860 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12861 write_byte(TE_BEAMCYLINDER) // TE id
12862 engfunc(EngFunc_WriteCoord, originF[0]) // x
12863 engfunc(EngFunc_WriteCoord, originF[1]) // y
12864 engfunc(EngFunc_WriteCoord, originF[2]) // z
12865 engfunc(EngFunc_WriteCoord, originF[0]) // x axis
12866 engfunc(EngFunc_WriteCoord, originF[1]) // y axis
12867 engfunc(EngFunc_WriteCoord, originF[2]+470.0) // z axis
12868 write_short(g_exploSpr) // sprite
12869 write_byte(0) // startframe
12870 write_byte(0) // framerate
12871 write_byte(4) // life
12872 write_byte(60) // width
12873 write_byte(0) // noise
12874 write_byte(200) // red
12875 write_byte(50) // green
12876 write_byte(0) // blue
12877 write_byte(200) // brightness
12878 write_byte(0) // speed
12879 message_end()
12880
12881 // Largest ring
12882 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12883 write_byte(TE_BEAMCYLINDER) // TE id
12884 engfunc(EngFunc_WriteCoord, originF[0]) // x
12885 engfunc(EngFunc_WriteCoord, originF[1]) // y
12886 engfunc(EngFunc_WriteCoord, originF[2]) // z
12887 engfunc(EngFunc_WriteCoord, originF[0]) // x axis
12888 engfunc(EngFunc_WriteCoord, originF[1]) // y axis
12889 engfunc(EngFunc_WriteCoord, originF[2]+555.0) // z axis
12890 write_short(g_exploSpr) // sprite
12891 write_byte(0) // startframe
12892 write_byte(0) // framerate
12893 write_byte(4) // life
12894 write_byte(60) // width
12895 write_byte(0) // noise
12896 write_byte(200) // red
12897 write_byte(0) // green
12898 write_byte(0) // blue
12899 write_byte(200) // brightness
12900 write_byte(0) // speed
12901 message_end()
12902}
12903
12904// Frost Grenade: Freeze Blast
12905create_blast3(const Float:originF[3])
12906{
12907 // Smallest ring
12908 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12909 write_byte(TE_BEAMCYLINDER) // TE id
12910 engfunc(EngFunc_WriteCoord, originF[0]) // x
12911 engfunc(EngFunc_WriteCoord, originF[1]) // y
12912 engfunc(EngFunc_WriteCoord, originF[2]) // z
12913 engfunc(EngFunc_WriteCoord, originF[0]) // x axis
12914 engfunc(EngFunc_WriteCoord, originF[1]) // y axis
12915 engfunc(EngFunc_WriteCoord, originF[2]+385.0) // z axis
12916 write_short(g_exploSpr) // sprite
12917 write_byte(0) // startframe
12918 write_byte(0) // framerate
12919 write_byte(4) // life
12920 write_byte(60) // width
12921 write_byte(0) // noise
12922 write_byte(0) // red
12923 write_byte(100) // green
12924 write_byte(200) // blue
12925 write_byte(200) // brightness
12926 write_byte(0) // speed
12927 message_end()
12928
12929 // Medium ring
12930 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12931 write_byte(TE_BEAMCYLINDER) // TE id
12932 engfunc(EngFunc_WriteCoord, originF[0]) // x
12933 engfunc(EngFunc_WriteCoord, originF[1]) // y
12934 engfunc(EngFunc_WriteCoord, originF[2]) // z
12935 engfunc(EngFunc_WriteCoord, originF[0]) // x axis
12936 engfunc(EngFunc_WriteCoord, originF[1]) // y axis
12937 engfunc(EngFunc_WriteCoord, originF[2]+470.0) // z axis
12938 write_short(g_exploSpr) // sprite
12939 write_byte(0) // startframe
12940 write_byte(0) // framerate
12941 write_byte(4) // life
12942 write_byte(60) // width
12943 write_byte(0) // noise
12944 write_byte(0) // red
12945 write_byte(100) // green
12946 write_byte(200) // blue
12947 write_byte(200) // brightness
12948 write_byte(0) // speed
12949 message_end()
12950
12951 // Largest ring
12952 engfunc(EngFunc_MessageBegin, MSG_PVS, SVC_TEMPENTITY, originF, 0)
12953 write_byte(TE_BEAMCYLINDER) // TE id
12954 engfunc(EngFunc_WriteCoord, originF[0]) // x
12955 engfunc(EngFunc_WriteCoord, originF[1]) // y
12956 engfunc(EngFunc_WriteCoord, originF[2]) // z
12957 engfunc(EngFunc_WriteCoord, originF[0]) // x axis
12958 engfunc(EngFunc_WriteCoord, originF[1]) // y axis
12959 engfunc(EngFunc_WriteCoord, originF[2]+555.0) // z axis
12960 write_short(g_exploSpr) // sprite
12961 write_byte(0) // startframe
12962 write_byte(0) // framerate
12963 write_byte(4) // life
12964 write_byte(60) // width
12965 write_byte(0) // noise
12966 write_byte(0) // red
12967 write_byte(100) // green
12968 write_byte(200) // blue
12969 write_byte(200) // brightness
12970 write_byte(0) // speed
12971 message_end()
12972}
12973
12974// Fix Dead Attrib on scoreboard
12975FixDeadAttrib(id)
12976{
12977 message_begin(MSG_BROADCAST, g_msgScoreAttrib)
12978 write_byte(id) // id
12979 write_byte(0) // attrib
12980 message_end()
12981}
12982
12983// Send Death Message for infections
12984SendDeathMsg(attacker, victim)
12985{
12986 message_begin(MSG_BROADCAST, g_msgDeathMsg)
12987 write_byte(attacker) // killer
12988 write_byte(victim) // victim
12989 write_byte(1) // headshot flag
12990 write_string("infection") // killer's weapon
12991 message_end()
12992}
12993
12994// Update Player Frags and Deaths
12995UpdateFrags(attacker, victim, frags, deaths, scoreboard)
12996{
12997 // Set attacker frags
12998 set_pev(attacker, pev_frags, float(pev(attacker, pev_frags) + frags))
12999
13000 // Set victim deaths
13001 fm_cs_set_user_deaths(victim, cs_get_user_deaths(victim) + deaths)
13002
13003 // Update scoreboard with attacker and victim info
13004 if (scoreboard)
13005 {
13006 message_begin(MSG_BROADCAST, g_msgScoreInfo)
13007 write_byte(attacker) // id
13008 write_short(pev(attacker, pev_frags)) // frags
13009 write_short(cs_get_user_deaths(attacker)) // deaths
13010 write_short(0) // class?
13011 write_short(fm_cs_get_user_team(attacker)) // team
13012 message_end()
13013
13014 message_begin(MSG_BROADCAST, g_msgScoreInfo)
13015 write_byte(victim) // id
13016 write_short(pev(victim, pev_frags)) // frags
13017 write_short(cs_get_user_deaths(victim)) // deaths
13018 write_short(0) // class?
13019 write_short(fm_cs_get_user_team(victim)) // team
13020 message_end()
13021 }
13022}
13023
13024// Remove Player Frags (when Nemesis/Survivor ignore_frags cvar is enabled)
13025RemoveFrags(attacker, victim)
13026{
13027 // Remove attacker frags
13028 set_pev(attacker, pev_frags, float(pev(attacker, pev_frags) - 1))
13029
13030 // Remove victim deaths
13031 fm_cs_set_user_deaths(victim, cs_get_user_deaths(victim) - 1)
13032}
13033
13034// Plays a sound on clients
13035PlaySound(const sound[])
13036{
13037 if (equal(sound[strlen(sound)-4], ".mp3"))
13038 client_cmd(0, "mp3 play ^"sound/%s^"", sound)
13039 else
13040 client_cmd(0, "spk ^"%s^"", sound)
13041}
13042
13043// Prints a colored message to target (use 0 for everyone), supports ML formatting.
13044// Note: I still need to make something like gungame's LANG_PLAYER_C to avoid unintended
13045// argument replacement when a function passes -1 (it will be considered a LANG_PLAYER)
13046zp_colored_print(target, const message[], any:...)
13047{
13048 static buffer[512], i, argscount
13049 argscount = numargs()
13050
13051 // Send to everyone
13052 if (!target)
13053 {
13054 static player
13055 for (player = 1; player <= g_maxplayers; player++)
13056 {
13057 // Not connected
13058 if (!g_isconnected[player])
13059 continue;
13060
13061 // Remember changed arguments
13062 static changed[5], changedcount // [5] = max LANG_PLAYER occurencies
13063 changedcount = 0
13064
13065 // Replace LANG_PLAYER with player id
13066 for (i = 2; i < argscount; i++)
13067 {
13068 if (getarg(i) == LANG_PLAYER)
13069 {
13070 setarg(i, 0, player)
13071 changed[changedcount] = i
13072 changedcount++
13073 }
13074 }
13075
13076 // Format message for player
13077 vformat(buffer, charsmax(buffer), message, 3)
13078
13079 // Send it
13080 message_begin(MSG_ONE_UNRELIABLE, g_msgSayText, _, player)
13081 write_byte(player)
13082 write_string(buffer)
13083 message_end()
13084
13085 // Replace back player id's with LANG_PLAYER
13086 for (i = 0; i < changedcount; i++)
13087 setarg(changed[i], 0, LANG_PLAYER)
13088 }
13089 }
13090 // Send to specific target
13091 else
13092 {
13093 /*
13094 // Not needed since you should set the ML argument
13095 // to the player's id for a targeted print message
13096
13097 // Replace LANG_PLAYER with player id
13098 for (i = 2; i < argscount; i++)
13099 {
13100 if (getarg(i) == LANG_PLAYER)
13101 setarg(i, 0, target)
13102 }
13103 */
13104
13105 // Format message for player
13106 vformat(buffer, charsmax(buffer), message, 3)
13107
13108 // Send it
13109 message_begin(MSG_ONE, g_msgSayText, _, target)
13110 write_byte(target)
13111 write_string(buffer)
13112 message_end()
13113 }
13114}
13115
13116/*================================================================================
13117 [Stocks]
13118=================================================================================*/
13119
13120// Set an entity's key value (from fakemeta_util)
13121stock fm_set_kvd(entity, const key[], const value[], const classname[])
13122{
13123 set_kvd(0, KV_ClassName, classname)
13124 set_kvd(0, KV_KeyName, key)
13125 set_kvd(0, KV_Value, value)
13126 set_kvd(0, KV_fHandled, 0)
13127
13128 dllfunc(DLLFunc_KeyValue, entity, 0)
13129}
13130
13131// Set entity's rendering type (from fakemeta_util)
13132stock fm_set_rendering(entity, fx = kRenderFxNone, r = 255, g = 255, b = 255, render = kRenderNormal, amount = 16)
13133{
13134 static Float:color[3]
13135 color[0] = float(r)
13136 color[1] = float(g)
13137 color[2] = float(b)
13138
13139 set_pev(entity, pev_renderfx, fx)
13140 set_pev(entity, pev_rendercolor, color)
13141 set_pev(entity, pev_rendermode, render)
13142 set_pev(entity, pev_renderamt, float(amount))
13143}
13144
13145// Get entity's speed (from fakemeta_util)
13146stock fm_get_speed(entity)
13147{
13148 static Float:velocity[3]
13149 pev(entity, pev_velocity, velocity)
13150
13151 return floatround(vector_length(velocity));
13152}
13153
13154// Get entity's aim origins (from fakemeta_util)
13155stock fm_get_aim_origin(id, Float:origin[3])
13156{
13157 static Float:origin1F[3], Float:origin2F[3]
13158 pev(id, pev_origin, origin1F)
13159 pev(id, pev_view_ofs, origin2F)
13160 xs_vec_add(origin1F, origin2F, origin1F)
13161
13162 pev(id, pev_v_angle, origin2F);
13163 engfunc(EngFunc_MakeVectors, origin2F)
13164 global_get(glb_v_forward, origin2F)
13165 xs_vec_mul_scalar(origin2F, 9999.0, origin2F)
13166 xs_vec_add(origin1F, origin2F, origin2F)
13167
13168 engfunc(EngFunc_TraceLine, origin1F, origin2F, 0, id, 0)
13169 get_tr2(0, TR_vecEndPos, origin)
13170}
13171
13172// Find entity by its owner (from fakemeta_util)
13173stock fm_find_ent_by_owner(entity, const classname[], owner)
13174{
13175 while ((entity = engfunc(EngFunc_FindEntityByString, entity, "classname", classname)) && pev(entity, pev_owner) != owner) { /* keep looping */ }
13176 return entity;
13177}
13178
13179// Set player's health (from fakemeta_util)
13180stock fm_set_user_health(id, health)
13181{
13182 (health > 0) ? set_pev(id, pev_health, float(health)) : dllfunc(DLLFunc_ClientKill, id);
13183}
13184
13185// Give an item to a player (from fakemeta_util)
13186stock fm_give_item(id, const item[])
13187{
13188 static ent
13189 ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, item))
13190 if (!pev_valid(ent)) return;
13191
13192 static Float:originF[3]
13193 pev(id, pev_origin, originF)
13194 set_pev(ent, pev_origin, originF)
13195 set_pev(ent, pev_spawnflags, pev(ent, pev_spawnflags) | SF_NORESPAWN)
13196 dllfunc(DLLFunc_Spawn, ent)
13197
13198 static save
13199 save = pev(ent, pev_solid)
13200 dllfunc(DLLFunc_Touch, ent, id)
13201 if (pev(ent, pev_solid) != save)
13202 return;
13203
13204 engfunc(EngFunc_RemoveEntity, ent)
13205}
13206
13207// Strip user weapons (from fakemeta_util)
13208stock fm_strip_user_weapons(id)
13209{
13210 static ent
13211 ent = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "player_weaponstrip"))
13212 if (!pev_valid(ent)) return;
13213
13214 dllfunc(DLLFunc_Spawn, ent)
13215 dllfunc(DLLFunc_Use, ent, id)
13216 engfunc(EngFunc_RemoveEntity, ent)
13217}
13218
13219// Collect random spawn points
13220stock load_spawns()
13221{
13222 // Check for CSDM spawns of the current map
13223 new cfgdir[32], mapname[32], filepath[100], linedata[64]
13224 get_configsdir(cfgdir, charsmax(cfgdir))
13225 get_mapname(mapname, charsmax(mapname))
13226 formatex(filepath, charsmax(filepath), "%s/csdm/%s.spawns.cfg", cfgdir, mapname)
13227
13228 // Load CSDM spawns if present
13229 if (file_exists(filepath))
13230 {
13231 new csdmdata[10][6], file = fopen(filepath,"rt")
13232
13233 while (file && !feof(file))
13234 {
13235 fgets(file, linedata, charsmax(linedata))
13236
13237 // invalid spawn
13238 if(!linedata[0] || str_count(linedata,' ') < 2) continue;
13239
13240 // get spawn point data
13241 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)
13242
13243 // origin
13244 g_spawns[g_spawnCount][0] = floatstr(csdmdata[0])
13245 g_spawns[g_spawnCount][1] = floatstr(csdmdata[1])
13246 g_spawns[g_spawnCount][2] = floatstr(csdmdata[2])
13247
13248 // increase spawn count
13249 g_spawnCount++
13250 if (g_spawnCount >= sizeof g_spawns) break;
13251 }
13252 if (file) fclose(file)
13253 }
13254 else
13255 {
13256 // Collect regular spawns
13257 collect_spawns_ent("info_player_start")
13258 collect_spawns_ent("info_player_deathmatch")
13259 }
13260
13261 // Collect regular spawns for non-random spawning unstuck
13262 collect_spawns_ent2("info_player_start")
13263 collect_spawns_ent2("info_player_deathmatch")
13264}
13265
13266// Collect spawn points from entity origins
13267stock collect_spawns_ent(const classname[])
13268{
13269 new ent = -1
13270 while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", classname)) != 0)
13271 {
13272 // get origin
13273 new Float:originF[3]
13274 pev(ent, pev_origin, originF)
13275 g_spawns[g_spawnCount][0] = originF[0]
13276 g_spawns[g_spawnCount][1] = originF[1]
13277 g_spawns[g_spawnCount][2] = originF[2]
13278
13279 // increase spawn count
13280 g_spawnCount++
13281 if (g_spawnCount >= sizeof g_spawns) break;
13282 }
13283}
13284
13285// Collect spawn points from entity origins
13286stock collect_spawns_ent2(const classname[])
13287{
13288 new ent = -1
13289 while ((ent = engfunc(EngFunc_FindEntityByString, ent, "classname", classname)) != 0)
13290 {
13291 // get origin
13292 new Float:originF[3]
13293 pev(ent, pev_origin, originF)
13294 g_spawns2[g_spawnCount2][0] = originF[0]
13295 g_spawns2[g_spawnCount2][1] = originF[1]
13296 g_spawns2[g_spawnCount2][2] = originF[2]
13297
13298 // increase spawn count
13299 g_spawnCount2++
13300 if (g_spawnCount2 >= sizeof g_spawns2) break;
13301 }
13302}
13303
13304// Drop primary/secondary weapons
13305stock drop_weapons(id, dropwhat)
13306{
13307 // Get user weapons
13308 static weapons[32], num, i, weaponid
13309 num = 0 // reset passed weapons count (bugfix)
13310 get_user_weapons(id, weapons, num)
13311
13312 // Loop through them and drop primaries or secondaries
13313 for (i = 0; i < num; i++)
13314 {
13315 // Prevent re-indexing the array
13316 weaponid = weapons[i]
13317
13318 if ((dropwhat == 1 && ((1<<weaponid) & PRIMARY_WEAPONS_BIT_SUM)) || (dropwhat == 2 && ((1<<weaponid) & SECONDARY_WEAPONS_BIT_SUM)))
13319 {
13320 // Get weapon entity
13321 static wname[32], weapon_ent
13322 get_weaponname(weaponid, wname, charsmax(wname))
13323 weapon_ent = fm_find_ent_by_owner(-1, wname, id)
13324
13325 // Hack: store weapon bpammo on PEV_ADDITIONAL_AMMO
13326 set_pev(weapon_ent, PEV_ADDITIONAL_AMMO, cs_get_user_bpammo(id, weaponid))
13327
13328 // Player drops the weapon and looses his bpammo
13329 engclient_cmd(id, "drop", wname)
13330 cs_set_user_bpammo(id, weaponid, 0)
13331 }
13332 }
13333}
13334
13335// Stock by (probably) Twilight Suzuka -counts number of chars in a string
13336stock str_count(const str[], searchchar)
13337{
13338 new count, i, len = strlen(str)
13339
13340 for (i = 0; i <= len; i++)
13341 {
13342 if(str[i] == searchchar)
13343 count++
13344 }
13345
13346 return count;
13347}
13348
13349// Checks if a space is vacant (credits to VEN)
13350stock is_hull_vacant(Float:origin[3], hull)
13351{
13352 engfunc(EngFunc_TraceHull, origin, origin, 0, hull, 0, 0)
13353
13354 if (!get_tr2(0, TR_StartSolid) && !get_tr2(0, TR_AllSolid) && get_tr2(0, TR_InOpen))
13355 return true;
13356
13357 return false;
13358}
13359
13360// Check if a player is stuck (credits to VEN)
13361stock is_player_stuck(id)
13362{
13363 static Float:originF[3]
13364 pev(id, pev_origin, originF)
13365
13366 engfunc(EngFunc_TraceHull, originF, originF, 0, (pev(id, pev_flags) & FL_DUCKING) ? HULL_HEAD : HULL_HUMAN, id, 0)
13367
13368 if (get_tr2(0, TR_StartSolid) || get_tr2(0, TR_AllSolid) || !get_tr2(0, TR_InOpen))
13369 return true;
13370
13371 return false;
13372}
13373
13374// Simplified get_weaponid (CS only)
13375stock cs_weapon_name_to_id(const weapon[])
13376{
13377 static i
13378 for (i = 0; i < sizeof WEAPONENTNAMES; i++)
13379 {
13380 if (equal(weapon, WEAPONENTNAMES[i]))
13381 return i;
13382 }
13383
13384 return 0;
13385}
13386
13387// Get User Current Weapon Entity
13388stock fm_cs_get_current_weapon_ent(id)
13389{
13390 // Prevent server crash if entity's private data not initalized
13391 if (pev_valid(id) != PDATA_SAFE)
13392 return -1;
13393
13394 return get_pdata_cbase(id, OFFSET_ACTIVE_ITEM, OFFSET_LINUX);
13395}
13396
13397// Get Weapon Entity's Owner
13398stock fm_cs_get_weapon_ent_owner(ent)
13399{
13400 // Prevent server crash if entity's private data not initalized
13401 if (pev_valid(ent) != PDATA_SAFE)
13402 return -1;
13403
13404 return get_pdata_cbase(ent, OFFSET_WEAPONOWNER, OFFSET_LINUX_WEAPONS);
13405}
13406
13407// Set User Deaths
13408stock fm_cs_set_user_deaths(id, value)
13409{
13410 // Prevent server crash if entity's private data not initalized
13411 if (pev_valid(id) != PDATA_SAFE)
13412 return;
13413
13414 set_pdata_int(id, OFFSET_CSDEATHS, value, OFFSET_LINUX)
13415}
13416
13417// Get User Team
13418stock fm_cs_get_user_team(id)
13419{
13420 // Prevent server crash if entity's private data not initalized
13421 if (pev_valid(id) != PDATA_SAFE)
13422 return FM_CS_TEAM_UNASSIGNED;
13423
13424 return get_pdata_int(id, OFFSET_CSTEAMS, OFFSET_LINUX);
13425}
13426
13427// Set a Player's Team
13428stock fm_cs_set_user_team(id, team)
13429{
13430 // Prevent server crash if entity's private data not initalized
13431 if (pev_valid(id) != PDATA_SAFE)
13432 return;
13433
13434 set_pdata_int(id, OFFSET_CSTEAMS, team, OFFSET_LINUX)
13435}
13436
13437// Set User Money
13438stock fm_cs_set_user_money(id, value)
13439{
13440 // Prevent server crash if entity's private data not initalized
13441 if (pev_valid(id) != PDATA_SAFE)
13442 return;
13443
13444 set_pdata_int(id, OFFSET_CSMONEY, value, OFFSET_LINUX)
13445}
13446
13447// Set User Flashlight Batteries
13448stock fm_cs_set_user_batteries(id, value)
13449{
13450 // Prevent server crash if entity's private data not initalized
13451 if (pev_valid(id) != PDATA_SAFE)
13452 return;
13453
13454 set_pdata_int(id, OFFSET_FLASHLIGHT_BATTERY, value, OFFSET_LINUX)
13455}
13456
13457// Update Player's Team on all clients (adding needed delays)
13458stock fm_user_team_update(id)
13459{
13460 static Float:current_time
13461 current_time = get_gametime()
13462
13463 if (current_time - g_teams_targettime >= 0.1)
13464 {
13465 set_task(0.1, "fm_cs_set_user_team_msg", id+TASK_TEAM)
13466 g_teams_targettime = current_time + 0.1
13467 }
13468 else
13469 {
13470 set_task((g_teams_targettime + 0.1) - current_time, "fm_cs_set_user_team_msg", id+TASK_TEAM)
13471 g_teams_targettime = g_teams_targettime + 0.1
13472 }
13473}
13474
13475// Send User Team Message
13476public fm_cs_set_user_team_msg(taskid)
13477{
13478 // Note to self: this next message can now be received by other plugins
13479
13480 // Set the switching team flag
13481 g_switchingteam = true
13482
13483 // Tell everyone my new team
13484 emessage_begin(MSG_ALL, g_msgTeamInfo)
13485 ewrite_byte(ID_TEAM) // player
13486 ewrite_string(CS_TEAM_NAMES[fm_cs_get_user_team(ID_TEAM)]) // team
13487 emessage_end()
13488
13489 // Done switching team
13490 g_switchingteam = false
13491}
13492
13493// Set the precached model index (updates hitboxes server side)
13494stock fm_cs_set_user_model_index(id, value)
13495{
13496 // Prevent server crash if entity's private data not initalized
13497 if (pev_valid(id) != PDATA_SAFE)
13498 return;
13499
13500 set_pdata_int(id, OFFSET_MODELINDEX, value, OFFSET_LINUX)
13501}
13502
13503// Set Player Model on Entity
13504stock fm_set_playermodel_ent(id)
13505{
13506 // Make original player entity invisible without hiding shadows or firing effects
13507 fm_set_rendering(id, kRenderFxNone, 255, 255, 255, kRenderTransTexture, 1)
13508
13509 // Format model string
13510 static model[100]
13511 formatex(model, charsmax(model), "models/player/%s/%s.mdl", g_playermodel[id], g_playermodel[id])
13512
13513 // Set model on entity or make a new one if unexistant
13514 if (!pev_valid(g_ent_playermodel[id]))
13515 {
13516 g_ent_playermodel[id] = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "info_target"))
13517 if (!pev_valid(g_ent_playermodel[id])) return;
13518
13519 set_pev(g_ent_playermodel[id], pev_classname, MODEL_ENT_CLASSNAME)
13520 set_pev(g_ent_playermodel[id], pev_movetype, MOVETYPE_FOLLOW)
13521 set_pev(g_ent_playermodel[id], pev_aiment, id)
13522 set_pev(g_ent_playermodel[id], pev_owner, id)
13523 }
13524
13525 engfunc(EngFunc_SetModel, g_ent_playermodel[id], model)
13526}
13527
13528// Set Weapon Model on Entity
13529stock fm_set_weaponmodel_ent(id)
13530{
13531 // Get player's p_ weapon model
13532 static model[100]
13533 pev(id, pev_weaponmodel2, model, charsmax(model))
13534
13535 // Set model on entity or make a new one if unexistant
13536 if (!pev_valid(g_ent_weaponmodel[id]))
13537 {
13538 g_ent_weaponmodel[id] = engfunc(EngFunc_CreateNamedEntity, engfunc(EngFunc_AllocString, "info_target"))
13539 if (!pev_valid(g_ent_weaponmodel[id])) return;
13540
13541 set_pev(g_ent_weaponmodel[id], pev_classname, WEAPON_ENT_CLASSNAME)
13542 set_pev(g_ent_weaponmodel[id], pev_movetype, MOVETYPE_FOLLOW)
13543 set_pev(g_ent_weaponmodel[id], pev_aiment, id)
13544 set_pev(g_ent_weaponmodel[id], pev_owner, id)
13545 }
13546
13547 engfunc(EngFunc_SetModel, g_ent_weaponmodel[id], model)
13548}
13549
13550// Remove Custom Model Entities
13551stock fm_remove_model_ents(id)
13552{
13553 // Remove "playermodel" ent if present
13554 if (pev_valid(g_ent_playermodel[id]))
13555 {
13556 engfunc(EngFunc_RemoveEntity, g_ent_playermodel[id])
13557 g_ent_playermodel[id] = 0
13558 }
13559 // Remove "weaponmodel" ent if present
13560 if (pev_valid(g_ent_weaponmodel[id]))
13561 {
13562 engfunc(EngFunc_RemoveEntity, g_ent_weaponmodel[id])
13563 g_ent_weaponmodel[id] = 0
13564 }
13565}
13566
13567// Set User Model
13568public fm_cs_set_user_model(taskid)
13569{
13570 set_user_info(ID_MODEL, "model", g_playermodel[ID_MODEL])
13571}
13572
13573// Get User Model -model passed byref-
13574stock fm_cs_get_user_model(player, model[], len)
13575{
13576 get_user_info(player, "model", model, len)
13577}
13578
13579// Update Player's Model on all clients (adding needed delays)
13580public fm_user_model_update(taskid)
13581{
13582 static Float:current_time
13583 current_time = get_gametime()
13584
13585 if (current_time - g_models_targettime >= g_modelchange_delay)
13586 {
13587 fm_cs_set_user_model(taskid)
13588 g_models_targettime = current_time
13589 }
13590 else
13591 {
13592 set_task((g_models_targettime + g_modelchange_delay) - current_time, "fm_cs_set_user_model", taskid)
13593 g_models_targettime = g_models_targettime + g_modelchange_delay
13594 }
13595}