-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathl4dinfectedbots.sp
5087 lines (4534 loc) · 167 KB
/
l4dinfectedbots.sp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/********************************************************************************************
* Plugin : L4D/L4D2 InfectedBots (Versus Coop/Coop Versus)
* Version : 2.0.1
* Game : Left 4 Dead 1 & 2
* Author : djromero (SkyDavid, David) and MI 5
* Testers : Myself, MI 5
* Website : www.sky.zebgames.com
*
* Purpose : This plugin spawns infected bots in L4D1, and gives greater control of the infected bots in L4D1/L4D2.
*
* WARNING : Please use sourcemod's latest 1.3 branch snapshot.
*
* Version 2.0.1
* - Fixed convar error for L4D1
*
* Version 2.0.0
* - Fixed error that would occur on OnPluginEnd
*
* Version 1.9.9
* - Fixed bug where the plugin would break under the new DLC
*
* Version 1.9.8
*
* Cvars Renamed:
* - l4d_infectedbots_infected_team_joinable has been renamed to l4d_infectedbots_coop_versus
* - l4d_infectedbots_admins_only has been renamed to l4d_infectedbots_admin_coop_versus
* - l4d_infectedbots_jointeams_announce has been renamed to l4d_infectedbots_coop_versus_announce
* - l4d_infectedbots_human_coop_survival_limit has been renamed to l4d_infectedbots_coop_versus_human_limit
* - l4d_infectedbots_coop_survival_tank_playable has been renamed to l4d_infectedbots_coop_versus_tank_playable
*
* - Added l4d_infectedbots_versus_coop cvar, forces all players onto the infected side in versus against survivor bots
* - Changed the Round Start event trigger
* - l4d_infectedbots_adjust_spawn_times cvar added, if set to 1, it adjusts the spawn timers depending on the gamemode (depends on infected players in versus, survivors in coop)
* - Enhanced Jockey and Spitter AI for versus (Removed delay between jockey jumps, and spitter now attacks the moment she recharges)
* - Director class limits for survival that are changed using an server config at startup will no longer reset to their defaults
* - l4d_infectedbots_admin_coop_versus and l4d_infectedbots_coop_versus_announce is now defaulted to 0 (off)
* - Fixed bug in scavenge where bots would not spawn
*
* Version 1.9.7
* - Added compatibilty for Four Swordsmen, Hard Eight, Healthapocalypse and Gib Fest
* - Fixed bug created by Valve that would ghost the tank if there was an infected player in coop/survival
* - Removed l4d_infectedbots_instant_spawns cvar and replaced it with l4d_infectedbots_initial_spawn_timer
* - Changed how the cheat command found valid clients
*
* Version 1.9.6
* - Fixed bug in L4D 1 where the map would restart after completion
* - Added Tank spawning to the plugin with cvar l4d_infectedbots_tank_limit
* - Added support for Versus Survival
* - Plugin class limits no longer affect director spawn limits due to the director not obeying the limits (ie: l4d_infectedbots_boomer_limit no longer affects z_boomer_limit)
*
* Version 1.9.5
* - Removed incorrect gamemode message, plugin will assume unknown gamemodes/mutations are based on coop
* - Fixed spitter acid glitch
* - Compatible with "Headshot!" mutation
* - Added cvar l4d_infectedbots_spawns_disabled_tank: disables infected bot spawning when a tank is in play
*
* Version 1.9.4
* - Compatible with new mutations: Last Man On Earth, Chainsaw Massacre and Room for One
*
* Version 1.9.3
* - Added support for chainsaws gamemode
* - Changed how the plugin detected dead/alive players
* - Changed code that used GetEntData/SetEntData to GetEntProp/SetEntProp
* - Fixed typo in detecting the game
* - Fixed an error caused by line 4300
*
* Version 1.9.2
* - Fixed bug with clients joining infected automatically when l4d_infectedbots_admins_only was set to 1
* - Fixed some error messages that pop up from certain events
* - Re-added feature: Bots in versus or scavenger will now ghost before they spawn completely
* - Added cvar: l4d_infectedbots_ghost_time
* - Renamed cvar: l4d_infectedbots_idle_time_before_slay to l4d_infectedbots_lifespan
* - Removed cvar: l4d_infectedbots_timer_hurt_before_slay (it's now apart of l4d_infectedbots_lifespan)
* - l4d_infectedbots_lifespan timer now kicks instead of slaying the infected
* - If an infected sees the survivors when his lifespan timer is up, the timer will be made anew (prevents infected being kicked while they are attacking or nearby)
* - (for coop/survival only) When a tank spawns and then kicked for a player to take over, there is now a check to see if the tank for the player to take over actually spawned successfully
* - Plugin is now compatible with the new mutation gamemode and any further mutations
*
* Version 1.9.1 V3
* - Fixed bug with bot spawns (especially with 4+ infected bots)
* - Fixed an error that was caused when the plugin was unloaded
*
* Version 1.9.1 V2
* - Fixed bug with server hibernation that was caused by rewrite of round start code (thanks Lexantis)
*
* Version 1.9.1
* - Changed Round start code which fixed a bug with survival (and possibly other gamemodes)
* - Changed how the class limit cvars work, they can now be used to alter director spawning cvars (z_smoker_limit, z_hunter_limit, etc.)
* - l4d_infectedbots_hunter_limit cvar added to L4D
* - Added cvar l4d_infectedbots_instant_spawns, allows the plugin to instantly spawn the infected at the start of a map and the start of finales
* - Fixed bug where survivors were slayed for no reason
* - Fixed bug where Valve's bots would still spawn on certain maps
* - Added cvar l4d_infectedbots_human_coop_survival_limit
* - Added cvar l4d_infectedbots_admins_only
* - Changed how the "!js" function worked, no longer uses jointeam (NEW GAMEDATA FILE BECAUSE OF THIS)
* - Class limit cvars by this plugin no longer affect z_versus class player limits (l4d_infectedbots_smoker_limit for example no longer affects z_versus_smoker_limit)
* - Altered descriptions of the class limit cvars
*
* Version 1.9.0
* - Workaround implemented to get around Coop Limit (L4D2)
* - REALLY fixed the 4+1 bug now
* - REALLY fixed the survivor bots running out of the safe room bug
* - Fixed bug where setting l4d_infectedbots_spawn_time to 5 or below would not spawn bots
* - Removed cvar l4d_infectedbots_spawn_time and added cvars l4d_infectedbots_spawn_max_time and l4dinfectedbots_spawn_min_time
* - Changed code on how the game is detected on startup
* - Removed FCVAR_NOTIFY from all cvars except the version cvar
* - If l4d_infectedbots_infected_team_joinable is 0, plugin will not set sb_all_bot_team to 1
* - Infected HUD can now display multiple tanks on fire along with the tank's health
* - Coop tank takeover now supports multiple tanks
* - Fixed bug where some players would not ghost in coop when they first spawn in a map
* - Removed most instances where the plugin would cause a BotType error
* - L4D bot spawning changed, now random like L4D2 instead of prioritized classes
* - Fixed bug where players would be stuck at READY and never spawn
*
* Version 1.8.9
* - Gamedata file uses Signatures instead of offsets
* - Enabling Director Spawning in Versus will activate Valve's bots
* - Reverted back to original way of joining survivors (jointeam instead of sb_takecontrol)
* - Bots no longer run out of the safe room before a player joins into the game
* - Fixed bug when a tank spawned and its special infected taken over by a bot, would be able to spawn again if it died such as 4+1 bot
*
* Version 1.8.8
* - Disables Valve's versus bots automatically
* - Based on AtomicStryker's version (fixes z_spawn bug along with gamemode bug)
* - Removed L4D seperate plugin, this one plugin supports both
* - Fixed strange ghost speed bug
* - Added Flashlights and FreeSpawning for both L4D and L4D2 without resorting to changing gamemodes
* - Now efficiently unlocks a versus start door when there are no players on infected (L4D 1 only)
*
* Version 1.8.7
* - Fixed Infected players not spawning correctly
*
* Version 1.8.6
* - Added a timer to the Gamemode ConVarHook to ensure compatitbilty with other gamemode changing plugins
* - Fight or die code added by AtomicStryker (kills idle bots, very useful for coordination cvar) along with two new cvars: l4d2_infectedbots_idle_time_before_slay and l4d2_infectedbots_timer_hurt_before_slay
* - Fixed bug where the plugin would return the BotType error even though the sum of the class limits matched that of the cvar max specials
* - When the plugin is unloaded, it resets the convars that it changed
* - Fixed bug where if Free Spawning and Director Spawning were on, it would cause the gamemode to stay on versus
*
* Version 1.8.5
* - Optimizations by AtomicStryker
* - Removed "Multiple tanks" code from plugin
* - Redone tank kicking code
* - Redone tank health fix (Thanks AtomicStryker!)
*
* Version 1.8.4
* - Adapted plugin to new gamemode "teamversus" (4x4 versus matchmaking)
* - Fixed bug where Survivor bots didn't have their health bonuses count
* - Added FCVAR_SPONLY to cvars to prevent clients from changing server cvars
*
* Version 1.8.3
* - Enhanced Hunter AI (Hunter bots pounce farther, versus only)
* - Model detection methods have been replaced with class detections (Compatible with Character Select Menu)
* - Fixed VersusDoorUnlocker not working on the second round
* - Added cvar l4d_infectedbots_coordination (bots will wait until all other bot spawn timers are 0 and then spawn at once)
*
* Version 1.8.2
* - Added Flashlights to the infected
* - Prevented additional music from playing when spawning as an infected
* - Redid the free spawning system, more robust and effective
* - Fixed bug where human tanks would break z_max_player_zombies (Now prevents players from joining a full infected team in versus when a tank spawns)
* - Redid the VersusDoorUnlocker, now activates without restrictions
* - Fixed bug where tanks would keep spawning over and over
* - Fixed bug where the HUD would display the tank on fire even though it's not
* - Increased default spawn time to 30 seconds
*
* Version 1.8.1 Fix V1
* - Changed safe room detection (fixes Crash Course and custom maps) (Thanks AtomicStryker!)
*
* Version 1.8.1
* - Reverted back to the old kicking system
* - Fixed Tank on fire timer for survival
* - Survivor players can no longer join a full infected team in versus when theres a tank in play
* - When a tank spawns in coop, they are not taken over by a player instantly; instead they are stationary until the tank moves, and then a player takes over (Thanks AtomicStryker!)
*
* Version 1.8.0
* - Fixed bug where the sphere bubbles would come back after the player dies
* - Fixed additional bugs coming from the "mp_gamemode/server.cfg" bug
* - Now checks if the admincheats plugin is installed and adapts
* - Fixed Free spawn bug that prevent players from spawning as ghosts on the third map (or higher) on a campaign
* - Fixed bug with spawn restrictions (was counting dead players as alive)
* - Added ConVarHooks to Infected HUD cvars (will take effect immediately after being changed)
* - Survivor Bots won't move out of the safe room until the player is fully in game
* - Bots will not be shown on the infected HUD when they are not supposed to be (being replaced by a player on director spawn mode, or a tank being kicked for a player tank to take over)
*
* Version 1.7.9
* - Fixed a rare bug where if a map changed and director spawning is on, it would not allow the infected to be playable
* - Removed Sphere bubbles for infected and spectators
* - Modified Spawn restriction system
* - Fixed bug where changing class limits on the spot would not take effect immediately
* - Removed infected bot ghosts in versus, caused too many bugs
* - Director spawn can now be changed in-game without a restart
* - The Gamemode being changed no longer needs a restart
* - Fixed bug where if admincheats is installed and an admin picked to spawn infected did not have root, would not spawn the infected
* - Fixed bug where players could not spawn as ghosts in versus if the gamemode was set in a server.cfg instead of the l4d dedicated server tool (which still has adverse effects, plugin or not)
*
* Version 1.7.8
* - Removed The Dedibots, Director and The Spawner, from spec, the bots still spawn and is still compatible with admincheats (fixes 7/8 human limit reached problem)
* - Changed the format of some of the announcements
* - Reduced size of HUD
* - HUD will NOT show infected players unless there are more than 5 infected players on the team (Versus only)
* - KillInfected function now only applies to survival at round start
* - Fixed Tank turning into hunter problem
* - Fixed Special Smoker bug and other ghost related problems
* - Fixed music glitch where certain pieces of music would keep playing over and over
* - Fixed bug when a SI bot dies in versus with director spawning on, it would keep spawning that bot
* - Fixed 1 health point bug in director spawning mode
* - Fixed Ghost spawning bug in director spawning mode where all ghosts would spawn at once
* - Fixed Coop Tank lottery starting for versus
* - Fixed Client 0 error with the Versus door unlocker
* - Added cvar: l4d_infectedbots_jointeams_announce
*
* Version 1.7.7
* - Support for admincheats (Thanks Whosat for this!)
* - Reduced Versus checkpoint door unlocker timer to 10 seconds (no longer shows the message)
* - Redone Versus door buster, now it simply unlocks the door
* - Fixed Director Spawning bug when free spawn is turned on
* - Added spawn timer to Director Spawning mode to prevent one player from taking all the bots
* - Now shows respawn timers for bots in Versus
* - When a player takes over a tank in coop/survival, the SI no longer disappears
* - Redone Tank Lottery (Thanks AtomicStryker!)
* - There is no limit on player tanks now
* - Entity errors should be fixed, valid checks implemented
* - Cvars that were changed by the plugin can now be changed with a server.cfg
* - Director Spawning now works correctly when the value is changed from being 0 or 1
* - Infected HUD now shows the health of the infected, rather than saying "ALIVE"
* - Fixed Ghost bug on Survival start after a round (Kills all ghosts)
* - Tank Health now shown properly in infected HUD
* - Changed details of the infected HUD when Director Spawning is on
* - Reduced the chances of the stats board appearing
*
* Version 1.7.6
* - Finale Glitch is fixed completely, no longer runs on timers
* - Fixed bug with spawning when Director Spawning is on
* - Added cvar: l4d_infectedbots_stats_board, can turn the stats board on or off after an infected dies
* - Optimizations here and there
* - Added a random system where the tank can go to anyone, rather than to the first person on the infected team
* - Fixed bug where 4 specials would spawn when the tank is playable and on the field
* - Fixed Free spawn bug where laggy players would not be ghosted
* - Errors related to "SetEntData" have been fixed
* - MaxSpecials is no longer linked to Director Spawning
*
* Version 1.7.5
* - Added command to join survivors (!js)
* - Removed cvars: l4d_infectedbots_allow_boomer, l4d_infectedbots_allow_smoker and l4d_infectedbots_allow_hunter (redundent with new cvars)
* - Added cvars: l4d_infectedbots_boomer_limit and l4d_infectedbots_smoker_limit
* - Added cvar: l4d_infectedbots_infected_team_joinable, cvar that can either allow or disallow players from joining the infected team on coop/survival
* - Cvars renamed: l4d_infectedbots_max_player_zombies to l4d_infectedbots_max_specials, l4d_infectedbots_tank_playable to l4d_infectedbots_coop_survival_tank_playable
* - Bug fix with l4d_infectedbots_max_specials and l4d_infectedbots_director_spawn not setting correctly when the server first starts up
* - Improved Boomer AI in versus (no longer sits there for a second when he is seen)
* - Autoconfig (was applied in 1.7.4, just wasn't shown in the changelog) Be sure to delete your old one
* - Reduced the chances of the director misplacing a bot
* - If the tank is playable in coop or survival, a player will be picked as the tank, regardless of the player's status
* - Fixed bug where the plugin may return "[L4D] Infected Bots: CreateFakeClient returned 0 -- Infected bot was not spawned"
* - Removed giving health to infected when they spawn, they no longer need this as Valve fixed this bug
* - Tank_killed game event was not firing due to the tank not being spawned by the director, this has been fixed by setting it in the player_death event and checking to see if it was a tank
* - Fixed human infected players causing problems with infected bot spawning
* - Added cvar: l4d_infectedbots_free_spawn which allows the spawning in coop/survival to be like versus (Thanks AtomicStryker for using some of your code from your infected ghost everywhere plugin!)
* - If there is only one survivor player in versus, the safe room door will be UTTERLY DESTROYED.
* - Open slots will be available to tanks by automatically increasing the max infected limit and decreasing when the tanks are killed
* - Bots were not spawning during a finale. This bug has been fixed.
* - Fixed Survivor death finale glitch which would cause all player infected to freeze and not spawn
* - Added a HUD that shows stats about Infected Players of when they spawn (from Durzel's Infected HUD plugin)
* - Priority system added to the spawning in coop/survival, no longer does the first infected player always get the first infected bot that spawns
* - Modified Spawn Restrictions
* - Infected bots in versus now spawn as ghosts, and fully spawn two seconds later
* - Removed commands that kicked with ServerCommand, this was causing crashes
* - Added a check in coop/survival to put players on infected when they first join if the survivor team is full
* - Removed cvar: l4d_infectedbots_hunter_limit
*
* Version 1.7.4
* - Fixed bots spawning too fast
* - Completely fixed Ghost bug (Ghosts will stay ghosts until the play spawns them)
* - New cvar "l4d_infectedbots_tank_playable" that allows tanks to be playable on coop/survival
*
* Version 1.7.3
* - Removed timers altogether and implemented the "old" system
* - Fixed server hibernation problem
* - Fixed error messages saying "Could not use ent_fire without cheats"
* - Fixed Ghost spawning infront of survivors
* - Set the spawn time to 25 seconds as default
* - Fixed Checking bot mechanism
*
* Version 1.7.2a
* - Fixed bots not spawning after a checkpoint
* - Fixed handle error
*
* Version 1.7.2
* - Removed autoconfig for plugin (delete your autoconfig for this plugin if you have one)
* - Reintroduced coop/survival playable spawns
* - spawns at conistent intervals of 20 seconds
* - Overhauled coop special infected cvar dectection, use z_versus_boomer_limit, z_versus_smoker_limit, and l4d_infectedbots_versus_hunter_limit to alter amount of SI in coop (DO NOT USE THESE CVARS IF THE DIRECTOR IS SPAWNING THE BOTS! USE THE STANDARD COOP CVARS)
* - Timers implemented for preventing the SI from spawning right at the start
* - Fixed bug in 1.7.1 where the improved SI AI would reset to old after a map change
* - Added a check on game start to prevent survivor bots from leaving the safe room too early when a player connects
* - Added cvar to control the spawn time of the infected bots (can change at anytime and will take effect at the moment of change)
* - Added cvar to have the director control the spawns (much better coop experience when max zombie players is set above 4), this however removes the option to play as those spawned infected
* - Removed l4d_infectedbots_coop_enabled cvar, l4d_infectedbots_director_spawn now replaces it. You can still use l4d_infectedbots_max_players_zombies
* - New kicking mechanism added, there shouldn't be a problem with bots going over the limit
* - Easier to join infected in coop/survival with the sm command "!ji"
* - Introduced a new kicking mechanism, there shouldn't be more than the max infected unless there is a tank
*
* Version 1.7.1
* - Fixed Hunter AI where the hunter would run away and around in circles after getting hit
* - Fixed Hunter Spawning where the hunter would spawn normally for 5 minutes into the map and then suddenly won't respawn at all
* - An all Survivor Bot team can now pass the areas where they got stuck in (they can move throughout the map on their own now)
* - Changed l4d_versus_hunter_limit to l4d_infectedbots_versus_hunter_limit with a new default of 4
* - It is now possible to change l4d_infectedbots_versus_hunter_limit and l4d_infectedbots_max_player_zombies in-game, just be sure to restart the map after change
* - Overhauled the plugin, removed coop/survival infected spawn code, code clean up
*
* Version 1.7.0
* - Fixed sb_all_bot_team 1 is now set at all times until there are no players in the server.
* - Survival/Coop now have playable Special Infected spawns.
* - l4d_infectedbots_enabled_on_coop cvar created for those who want control over the plugin during coop/survival maps.
* - Able to spectate AI Special Infected in Coop/Survival.
* - Better AI (Smoker and Boomer don't sit there for a second and then attack a survivor when its within range).
* - Set the number of VS team changes to 99 if its survival or coop, 2 for versus
* - Safe Room timer added to coop/survival
* - l4d_versus_hunter_limit added to control the amount of hunters in versus
* - l4d_infectedbots_max_player_zombies added to increase the max special infected on the map (Bots and players)
* - Autoexec created for this plugin
*
* Version 1.6.1
* - Changed some routines to prevent crash on round end.
*
* Version 1.6
* - Finally fixed issue of server hanging on mapchange or when last player leaves.
* Thx to AcidTester for his help testing this.
* - Added cvar to disable infected bots HUD
*
* Version 1.6
* - Fixed issue of HUD's timer not beign killed after each round.
* Version 1.5.8
* - Removed the "kickallbots" routine. Used a different method.
*
* Version 1.5.6
* - Rollback on method for detecting if map is VS
*
* Version 1.5.5
* - Fixed some issues with infected boomer bots spawning just after human boomer is killed.
* - Changed method of detecting VS maps to allow non-vs maps to use this plugin.
*
* Version 1.5.4
* - Fixed (now) issue when all players leave and server would keep playing with only
* survivor/infected bots.
*
* Version 1.5.3
* - Fixed issue when boomer/smoker bots would spawn just after human boomer/smoker was
* killed. (I had to hook the player_death event as pre, instead of post to be able to
* check for some info).
* - Added new cvar to control the way you want infected spawn times handled:
* l4d_infectedbots_normalize_spawntime:
* 0 (default): Human zombies will use default spawn times (min time if less
* than 3 players in team) (min default is 20)
* 1 : Bots and human zombies will have the same spawn time.
* (max default is 30).
* - Fixed issue when all players leave and server would keep playing with only
* survivor/infected bots.
*
* Version 1.5.2
* - Normalized spawn times for human zombies (min = max).
* - Fixed spawn of extra bot when someone dead becomes a tank. If player was alive, his
* bot will still remain if he gets a tank.
* - Added 2 new cvars to disallow boomer and/or smoker bots:
* l4d_infectedbots_allow_boomer = 1 (allow, default) / 0 (disallow)
* l4d_infectedbots_allow_smoker = 1 (allow, default) / 0 (disallow)
*
* Version 1.5.1
* - Major bug fixes that caused server to hang (infite loops and threading problems).
*
* Version 1.5
* - Added HUD panel for infected bots. Original idea from: Durzel's Infected HUD plugin.
* - Added validations so that boomers and smokers do not spawn too often. A boomer can
* only spawn (as a bot) after XX seconds have elapsed since the last one died.
* - Added/fixed some routines/validations to prevent memory leaks.
*
* Version 1.4
* - Infected bots can spawn when a real player is dead or in ghost mode without forcing
* them (real players) to spawn.
* - Since real players won't be forced to spawn, they won't spawn outside the map or
* in places they can't get out (where only bots can get out).
*
* Version 1.3
* - No infected bots are spawned if at least one player is in ghost mode. If a bot is
* scheduled to spawn but a player is in ghost mode, the bot will spawn no more than
* 5 seconds after the player leaves ghost mode (spawns).
* - Infected bots won't stay AFK if they spawn far away. They will always search for
* survivors even if they're far from them.
* - Allows survivor's team to be all bots, since we can have all bots on infected's team.
*
* Version 1.2
* - Fixed several bugs while counting players.
* - Added chat message to inform infected players (only) that a new bot has been spawned
*
* Version 1.1.2
* - Fixed crash when counting
*
* Version 1.1.1
* - Fixed survivor's quick HUD refresh when spawning infected bots
*
* Version 1.1
* - Implemented "give health" command to fix infected's hud & pounce (hunter) when spawns
*
* Version 1.0
* - Initial release.
*
*
**********************************************************************************************/
#include <sourcemod>
#include <sdktools>
#pragma semicolon 1
#define PLUGIN_VERSION "2.0.1"
#define DEBUGSERVER 0
#define DEBUGCLIENTS 0
#define DEBUGTANK 0
#define DEBUGHUD 0
#define DEVELOPER 0
#define TEAM_SPECTATOR 1
#define TEAM_SURVIVORS 2
#define TEAM_INFECTED 3
#define COOP 1
#define VERSUS 2
#define SURVIVAL 3
#define ZOMBIECLASS_SMOKER 1
#define ZOMBIECLASS_BOOMER 2
#define ZOMBIECLASS_HUNTER 3
#define ZOMBIECLASS_SPITTER 4
#define ZOMBIECLASS_JOCKEY 5
#define ZOMBIECLASS_CHARGER 6
// Variables
static InfectedRealCount; // Holds the amount of real infected players
static InfectedBotCount; // Holds the amount of infected bots in any gamemode
static InfectedBotQueue; // Holds the amount of bots that are going to spawn
static GameMode; // Holds the GameMode, 1 for coop and realism, 2 for versus, teamversus, scavenge and teamscavenge, 3 for survival
static TanksPlaying; // Holds the amount of tanks on the playing field
static BoomerLimit; // Sets the Boomer Limit, related to the boomer limit cvar
static SmokerLimit; // Sets the Smoker Limit, related to the smoker limit cvar
static HunterLimit; // Sets the Hunter Limit, related to the hunter limit cvar
static SpitterLimit; // Sets the Spitter Limit, related to the Spitter limit cvar
static JockeyLimit; // Sets the Jockey Limit, related to the Jockey limit cvar
static ChargerLimit; // Sets the Charger Limit, related to the Charger limit cvar
static MaxPlayerZombies; // Holds the amount of the maximum amount of special zombies on the field
static MaxPlayerTank; // Used for setting an additional slot for each tank that spawns
static BotReady; // Used to determine how many bots are ready, used only for the coordination feature
static ZOMBIECLASS_TANK; // This value varies depending on which L4D game it is, holds the the tank class value
static GetSpawnTime[MAXPLAYERS+1]; // Used for the HUD on getting spawn times of players
static PlayersInServer;
// Booleans
static bool:b_HasRoundStarted; // Used to state if the round started or not
static bool:b_HasRoundEnded; // States if the round has ended or not
static bool:b_LeftSaveRoom; // States if the survivors have left the safe room
static bool:canSpawnBoomer; // States if we can spawn a boomer (releated to spawn restrictions)
static bool:canSpawnSmoker; // States if we can spawn a smoker (releated to spawn restrictions)
static bool:canSpawnHunter; // States if we can spawn a hunter (releated to spawn restrictions)
static bool:canSpawnSpitter; // States if we can spawn a spitter (releated to spawn restrictions)
static bool:canSpawnJockey; // States if we can spawn a jockey (releated to spawn restrictions)
static bool:canSpawnCharger; // States if we can spawn a charger (releated to spawn restrictions)
static bool:DirectorSpawn; // Can allow either the director to spawn the infected (normal l4d behavior), or allow the plugin to spawn them
static bool:SpecialHalt; // Loop Breaker, prevents specials spawning, while Director is spawning, from spawning again
static bool:TankFrustStop; // Prevents the tank frustration event from firing as it counts as a tank spawn
static bool:FinaleStarted; // States whether the finale has started or not
static bool:WillBeTank[MAXPLAYERS+1]; // States whether that player will be the tank
//new bool:TankHalt; // Loop Breaker, prevents player tanks from spawning over and over
static bool:TankWasSeen[MAXPLAYERS+1]; // Used only in coop, prevents the Sound hook event from triggering over and over again
static bool:PlayerLifeState[MAXPLAYERS+1]; // States whether that player has the lifestate changed from switching the gamemode
static bool:InitialSpawn; // Related to the coordination feature, tells the plugin to let the infected spawn when the survivors leave the safe room
static bool:g_bIsL4D2; // Holds the version of L4D; false if its L4D, true if its L4D2
static bool:FreeSpawnReset[MAXPLAYERS+1]; // Tells the plugin to reset the FreeSpawn convar, used for the finale glitch only
static bool:TempBotSpawned; // Tells the plugin that the tempbot has spawned
static bool:AlreadyGhosted[MAXPLAYERS+1]; // Loop Breaker, prevents a player from spawning into a ghost over and over again
static bool:AlreadyGhostedBot[MAXPLAYERS+1]; // Prevents bots taking over a player from ghosting
static bool:SurvivalVersus;
static bool:DirectorCvarsModified; // Prevents reseting the director class limit cvars if the server or admin modifed them
static bool:DisallowTankFunction;
static bool:PlayerHasEnteredStart[MAXPLAYERS+1];
static bool:AfterInitialRound;
// Handles
static Handle:h_BoomerLimit; // Related to the Boomer limit cvar
static Handle:h_SmokerLimit; // Related to the Smoker limit cvar
static Handle:h_HunterLimit; // Related to the Hunter limit cvar
static Handle:h_SpitterLimit; // Related to the Spitter limit cvar
static Handle:h_JockeyLimit; // Related to the Jockey limit cvar
static Handle:h_ChargerLimit; // Related to the Charger limit cvar
static Handle:h_MaxPlayerZombies; // Related to the max specials cvar
static Handle:h_InfectedSpawnTimeMax; // Related to the spawn time cvar
static Handle:h_InfectedSpawnTimeMin; // Related to the spawn time cvar
static Handle:h_DirectorSpawn; // yeah you're getting the idea
static Handle:h_CoopPlayableTank; // yup, same thing again
static Handle:h_GameMode; // uh huh
static Handle:h_JoinableTeams; // Can you guess this one?
static Handle:h_FreeSpawn; // We're done now, so be excited
static Handle:h_StatsBoard; // Oops, now we are
static Handle:h_Difficulty; // Ok, maybe not
static Handle:h_JoinableTeamsAnnounce;
static Handle:h_Coordination;
static Handle:h_idletime_b4slay;
static Handle:h_InitialSpawn;
static Handle:h_HumanCoopLimit;
static Handle:h_AdminJoinInfected;
static Handle:FightOrDieTimer[MAXPLAYERS+1]; // kill idle bots
static Handle:h_BotGhostTime;
static Handle:h_DisableSpawnsTank;
static Handle:h_TankLimit;
static Handle:h_VersusCoop;
static Handle:h_AdjustSpawnTimes;
// Stuff related to Durzel's HUD (Panel was redone)
static respawnDelay[MAXPLAYERS+1]; // Used to store individual player respawn delays after death
static hudDisabled[MAXPLAYERS+1]; // Stores the client preference for whether HUD is shown
static clientGreeted[MAXPLAYERS+1]; // Stores whether or not client has been shown the mod commands/announce
static zombieHP[7]; // Stores special infected max HP
static Handle:cvarZombieHP[7]; // Array of handles to the 4 cvars we have to hook to monitor HP changes
static bool:isTankOnFire[MAXPLAYERS+1] = false; // Used to store whether tank is on fire
static burningTankTimeLeft[MAXPLAYERS+1] = 0; // Stores number of seconds Tank has left before he dies
static bool:roundInProgress = false; // Flag that marks whether or not a round is currently in progress
static Handle:infHUDTimer = INVALID_HANDLE; // The main HUD refresh timer
static Handle:respawnTimer = INVALID_HANDLE; // Respawn countdown timer
static Handle:doomedTankTimer = INVALID_HANDLE; // "Tank on Fire" countdown timer
static Handle:delayedDmgTimer = INVALID_HANDLE; // Delayed damage update timer
static Handle:pInfHUD = INVALID_HANDLE; // The panel shown to all infected users
static Handle:usrHUDPref = INVALID_HANDLE; // Stores the client HUD preferences persistently
// Console commands
static Handle:h_InfHUD = INVALID_HANDLE;
static Handle:h_Announce = INVALID_HANDLE;
public Plugin:myinfo =
{
name = "[L4D/L4D2] Infected Bots (Versus Coop/Coop Versus)",
author = "djromero (SkyDavid), MI 5",
description = "Spawns infected bots in versus, allows playable special infected in coop/survival, and changable z_max_player_zombies limit",
version = PLUGIN_VERSION,
url = "http://forums.alliedmods.net/showthread.php?p=893938#post893938"
}
////////////////
//PLUGIN START//
////////////////
public APLRes:AskPluginLoad2(Handle:myself, bool:late, String:error[], err_max)
{
// Checks to see if the game is a L4D game. If it is, check if its the sequel. L4DVersion is L4D if false, L4D2 if true.
decl String:GameName[64];
GetGameFolderName(GameName, sizeof(GameName));
if (StrContains(GameName, "left4dead", false) == -1)
return APLRes_Failure;
else if (StrEqual(GameName, "left4dead2", false))
g_bIsL4D2 = true;
return APLRes_Success;
}
public OnPluginStart()
{
// Tank Class value is different in L4D2
if (g_bIsL4D2)
ZOMBIECLASS_TANK = 8;
else
ZOMBIECLASS_TANK = 5;
// Notes on the offsets: altough m_isGhost is used to check or set a player's ghost status, for some weird reason this disallowed the player from spawning.
// So I found and used m_isCulling to allow the player to press use and spawn as a ghost (which in this case, I forced the client to press use)
// m_lifeState is an alternative to the "switching to spectator and back" method when a bot spawns. This was used to prevent players from taking over those bots, but
// this provided weird movements when a player was spectating on the infected team.
// ScrimmageType is interesting as it was used in the beta. The scrimmage code was abanonded and replaced with versus, but some of it is still left over in the final.
// In the previous versions of this plugin (or not using this plugin at all), you might have seen giant bubbles or spheres around the map. Those are scrimmage spawn
// spheres that were used to prevent infected from spawning within there. It was bothering me, and a whole lot of people who saw them. Thanks to AtomicStryker who
// URGED me to remove the spheres, I began looking for a solution. He told me to use various source handles like m_scrimmageType and others. I experimented with it,
// and found out that it removed the spheres, and implemented it into the plugin. The spheres are no longer shown, and they were useless anyway as infected still spawn
// within it.
// Notes on the sourcemod commands:
// JoinSpectator is actually a developer command I used to see if the bots spawn correctly with and without a player. It was incredibly useful for this purpose, but it
// will not be in the final versions.
// Add a sourcemod command so players can easily join infected in coop/survival
RegConsoleCmd("sm_ji", JoinInfected);
RegConsoleCmd("sm_js", JoinSurvivors);
#if DEVELOPER
RegConsoleCmd("sm_sp", JoinSpectator);
RegConsoleCmd("sm_gamemode", CheckGameMode);
RegConsoleCmd("sm_count", CheckQueue);
#endif
// Hook "say" so clients can toggle HUD on/off for themselves
RegConsoleCmd("sm_infhud", Command_Say);
// We register the version cvar
CreateConVar("l4d_infectedbots_version", PLUGIN_VERSION, "Version of L4D Infected Bots", FCVAR_PLUGIN|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD);
h_GameMode = FindConVar("mp_gamemode");
h_Difficulty = FindConVar("z_difficulty");
// console variables
h_BoomerLimit = CreateConVar("l4d_infectedbots_boomer_limit", "1", "Sets the limit for boomers spawned by the plugin", FCVAR_PLUGIN|FCVAR_SPONLY);
h_SmokerLimit = CreateConVar("l4d_infectedbots_smoker_limit", "1", "Sets the limit for smokers spawned by the plugin", FCVAR_PLUGIN|FCVAR_SPONLY);
h_TankLimit = CreateConVar("l4d_infectedbots_tank_limit", "0", "Sets the limit for tanks spawned by the plugin (does not affect director tanks)", FCVAR_PLUGIN|FCVAR_SPONLY);
if (g_bIsL4D2)
{
h_SpitterLimit = CreateConVar("l4d_infectedbots_spitter_limit", "1", "Sets the limit for spitters spawned by the plugin", FCVAR_PLUGIN|FCVAR_SPONLY);
h_JockeyLimit = CreateConVar("l4d_infectedbots_jockey_limit", "1", "Sets the limit for jockeys spawned by the plugin", FCVAR_PLUGIN|FCVAR_SPONLY);
h_ChargerLimit = CreateConVar("l4d_infectedbots_charger_limit", "1", "Sets the limit for chargers spawned by the plugin", FCVAR_PLUGIN|FCVAR_SPONLY);
h_HunterLimit = CreateConVar("l4d_infectedbots_hunter_limit", "1", "Sets the limit for hunters spawned by the plugin", FCVAR_PLUGIN|FCVAR_SPONLY);
}
else
{
h_HunterLimit = CreateConVar("l4d_infectedbots_hunter_limit", "2", "Sets the limit for hunters spawned by the plugin", FCVAR_PLUGIN|FCVAR_SPONLY);
}
h_MaxPlayerZombies = CreateConVar("l4d_infectedbots_max_specials", "4", "Defines how many special infected can be on the map on all gamemodes", FCVAR_PLUGIN|FCVAR_SPONLY);
h_InfectedSpawnTimeMax = CreateConVar("l4d_infectedbots_spawn_time_max", "30", "Sets the max spawn time for special infected spawned by the plugin in seconds", FCVAR_PLUGIN|FCVAR_SPONLY);
h_InfectedSpawnTimeMin = CreateConVar("l4d_infectedbots_spawn_time_min", "25", "Sets the minimum spawn time for special infected spawned by the plugin in seconds", FCVAR_PLUGIN|FCVAR_SPONLY);
h_DirectorSpawn = CreateConVar("l4d_infectedbots_director_spawn", "0", "If 1, the plugin will use the director's timing of the spawns, if the game is L4D2 and versus, it will activate Valve's bots", FCVAR_PLUGIN|FCVAR_SPONLY, true, 0.0, true, 1.0);
h_CoopPlayableTank = CreateConVar("l4d_infectedbots_coop_versus_tank_playable", "0", "If 1, tank will be playable in coop/survival", FCVAR_PLUGIN|FCVAR_NOTIFY|FCVAR_SPONLY, true, 0.0, true, 1.0);
h_JoinableTeams = CreateConVar("l4d_infectedbots_coop_versus", "0", "If 1, players can join the infected team in coop/survival (!ji in chat to join infected, !js to join survivors)", FCVAR_PLUGIN|FCVAR_SPONLY, true, 0.0, true, 1.0);
if (!g_bIsL4D2)
{
h_StatsBoard = CreateConVar("l4d_infectedbots_stats_board", "1", "If 1, the stats board will show up after an infected player dies (L4D1 ONLY)", FCVAR_PLUGIN|FCVAR_SPONLY, true, 0.0, true, 1.0);
}
h_FreeSpawn = CreateConVar("l4d_infectedbots_free_spawn", "0", "If 1, infected players in coop/survival will spawn as ghosts", FCVAR_PLUGIN|FCVAR_SPONLY, true, 0.0, true, 1.0);
h_JoinableTeamsAnnounce = CreateConVar("l4d_infectedbots_coop_versus_announce", "0", "If 1, clients will be announced to on how to join the infected team", FCVAR_PLUGIN|FCVAR_SPONLY, true, 0.0, true, 1.0);
h_Coordination = CreateConVar("l4d_infectedbots_coordination", "0", "If 1, bots will only spawn when all other bot spawn timers are at zero", FCVAR_PLUGIN|FCVAR_SPONLY, true, 0.0, true, 1.0);
h_InfHUD = CreateConVar("l4d_infectedbots_infhud_enable", "1", "Toggle whether Infected HUD is active or not.", FCVAR_PLUGIN|FCVAR_SPONLY, true, 0.0, true, 1.0);
h_Announce = CreateConVar("l4d_infectedbots_infhud_announce", "1", "Toggle whether Infected HUD announces itself to clients.", FCVAR_PLUGIN|FCVAR_SPONLY, true, 0.0, true, 1.0);
h_idletime_b4slay = CreateConVar("l4d_infectedbots_lifespan", "40", "Amount of seconds before a special infected bot is kicked", FCVAR_PLUGIN|FCVAR_SPONLY);
h_InitialSpawn = CreateConVar("l4d_infectedbots_initial_spawn_timer", "1", "The spawn timer in seconds used when infected bots are spawned for the first time in a map", FCVAR_PLUGIN|FCVAR_SPONLY);
h_HumanCoopLimit = CreateConVar("l4d_infectedbots_coop_versus_human_limit", "4", "Sets the limit for the amount of humans that can join the infected team in coop/survival", FCVAR_PLUGIN|FCVAR_SPONLY);
h_AdminJoinInfected = CreateConVar("l4d_infectedbots_admin_coop_versus", "0", "If 1, only admins can join the infected team in coop/survival", FCVAR_PLUGIN|FCVAR_SPONLY, true, 0.0, true, 1.0);
h_BotGhostTime = CreateConVar("l4d_infectedbots_ghost_time", "2", "If higher than zero, the plugin will ghost bots before they fully spawn on versus/scavenge", FCVAR_PLUGIN|FCVAR_SPONLY);
h_DisableSpawnsTank = CreateConVar("l4d_infectedbots_spawns_disabled_tank", "0", "If 1, Plugin will disable spawning when a tank is on the field", FCVAR_PLUGIN|FCVAR_SPONLY, true, 0.0, true, 1.0);
h_VersusCoop = CreateConVar("l4d_infectedbots_versus_coop", "0", "If 1, The plugin will force all players to the infected side against the survivor AI for every round and map in versus/scavenge", FCVAR_PLUGIN|FCVAR_SPONLY, true, 0.0, true, 1.0);
h_AdjustSpawnTimes = CreateConVar("l4d_infectedbots_adjust_spawn_times", "0", "If 1, The plugin will adjust spawn timers depending on the gamemode, adjusts spawn timers based on number of survivor players in coop and based on amount of infected players in versus/scavenge", FCVAR_PLUGIN|FCVAR_SPONLY, true, 0.0, true, 1.0);
HookConVarChange(h_BoomerLimit, ConVarBoomerLimit);
BoomerLimit = GetConVarInt(h_BoomerLimit);
HookConVarChange(h_SmokerLimit, ConVarSmokerLimit);
SmokerLimit = GetConVarInt(h_SmokerLimit);
HookConVarChange(h_HunterLimit, ConVarHunterLimit);
HunterLimit = GetConVarInt(h_HunterLimit);
if (g_bIsL4D2)
{
HookConVarChange(h_SpitterLimit, ConVarSpitterLimit);
SpitterLimit = GetConVarInt(h_SpitterLimit);
HookConVarChange(h_JockeyLimit, ConVarJockeyLimit);
JockeyLimit = GetConVarInt(h_JockeyLimit);
HookConVarChange(h_ChargerLimit, ConVarChargerLimit);
ChargerLimit = GetConVarInt(h_ChargerLimit);
}
HookConVarChange(h_MaxPlayerZombies, ConVarMaxPlayerZombies);
MaxPlayerZombies = GetConVarInt(h_MaxPlayerZombies);
HookConVarChange(h_DirectorSpawn, ConVarDirectorSpawn);
DirectorSpawn = GetConVarBool(h_DirectorSpawn);
HookConVarChange(h_GameMode, ConVarGameMode);
HookConVarChange(h_Difficulty, ConVarDifficulty);
HookConVarChange(h_VersusCoop, ConVarVersusCoop);
HookConVarChange(h_JoinableTeams, ConVarCoopVersus);
// If the admin wanted to change the director class limits with director spawning on, the plugin will not reset those cvars to their defaults upon startup.
HookConVarChange(FindConVar("z_hunter_limit"), ConVarDirectorCvarChanged);
if (!g_bIsL4D2)
{
HookConVarChange(FindConVar("z_gas_limit"), ConVarDirectorCvarChanged);
HookConVarChange(FindConVar("z_exploding_limit"), ConVarDirectorCvarChanged);
HookConVarChange(FindConVar("holdout_max_boomers"), ConVarDirectorCvarChanged);
HookConVarChange(FindConVar("holdout_max_smokers"), ConVarDirectorCvarChanged);
HookConVarChange(FindConVar("holdout_max_hunters"), ConVarDirectorCvarChanged);
HookConVarChange(FindConVar("holdout_max_specials"), ConVarDirectorCvarChanged);
}
else
{
HookConVarChange(FindConVar("z_smoker_limit"), ConVarDirectorCvarChanged);
HookConVarChange(FindConVar("z_boomer_limit"), ConVarDirectorCvarChanged);
HookConVarChange(FindConVar("z_jockey_limit"), ConVarDirectorCvarChanged);
HookConVarChange(FindConVar("z_spitter_limit"), ConVarDirectorCvarChanged);
HookConVarChange(FindConVar("z_charger_limit"), ConVarDirectorCvarChanged);
HookConVarChange(FindConVar("survival_max_boomers"), ConVarDirectorCvarChanged);
HookConVarChange(FindConVar("survival_max_smokers"), ConVarDirectorCvarChanged);
HookConVarChange(FindConVar("survival_max_hunters"), ConVarDirectorCvarChanged);
HookConVarChange(FindConVar("survival_max_jockeys"), ConVarDirectorCvarChanged);
HookConVarChange(FindConVar("survival_max_spitters"), ConVarDirectorCvarChanged);
HookConVarChange(FindConVar("survival_max_chargers"), ConVarDirectorCvarChanged);
HookConVarChange(FindConVar("survival_max_specials"), ConVarDirectorCvarChanged);
}
// Some of these events are being used multiple times. Although I copied Durzel's code, I felt this would make it more organized as there is a ton of code in events
// Such as PlayerDeath, PlayerSpawn and others.
HookEvent("round_start", evtRoundStart);
HookEvent("round_end", evtRoundEnd, EventHookMode_Pre);
// We hook some events ...
HookEvent("player_death", evtPlayerDeath, EventHookMode_Pre);
HookEvent("player_team", evtPlayerTeam);
HookEvent("player_spawn", evtPlayerSpawn);
HookEvent("create_panic_event", evtSurvivalStart);
HookEvent("tank_frustrated", evtTankFrustrated);
HookEvent("finale_start", evtFinaleStart);
HookEvent("mission_lost", evtMissionLost);
HookEvent("player_death", evtInfectedDeath);
HookEvent("player_spawn", evtInfectedSpawn);
HookEvent("player_hurt", evtInfectedHurt);
HookEvent("player_team", evtTeamSwitch);
HookEvent("player_death", evtInfectedWaitSpawn);
HookEvent("ghost_spawn_time", evtInfectedWaitSpawn);
HookEvent("spawner_give_item", evtUnlockVersusDoor);
HookEvent("player_bot_replace", evtBotReplacedPlayer);
HookEvent("player_first_spawn", evtPlayerFirstSpawned);
HookEvent("player_entered_start_area", evtPlayerFirstSpawned);
HookEvent("player_entered_checkpoint", evtPlayerFirstSpawned);
HookEvent("player_transitioned", evtPlayerFirstSpawned);
HookEvent("player_left_start_area", evtPlayerFirstSpawned);
HookEvent("player_left_checkpoint", evtPlayerFirstSpawned);
// Hook a sound for coop tank function
AddNormalSoundHook(NormalSHook:HookSound_Callback);
//AddNormalSoundHook(NormalSHook:HookSound_Callback2);
// We set some variables
b_HasRoundStarted = false;
b_HasRoundEnded = false;
//Autoconfig for plugin
AutoExecConfig(true, "l4dinfectedbots");
//----- Zombie HP hooks ---------------------
//We store the special infected max HP values in an array and then hook the cvars used to modify them
//just in case another plugin (or an admin) decides to modify them. Whilst unlikely if we don't do
//this then the HP percentages on the HUD will end up screwy, and since it's a one-time initialisation
//when the plugin loads there's a trivial overhead.
cvarZombieHP[0] = FindConVar("z_hunter_health");
cvarZombieHP[1] = FindConVar("z_gas_health");
cvarZombieHP[2] = FindConVar("z_exploding_health");
if (g_bIsL4D2)
{
cvarZombieHP[3] = FindConVar("z_spitter_health");
cvarZombieHP[4] = FindConVar("z_jockey_health");
cvarZombieHP[5] = FindConVar("z_charger_health");
}
cvarZombieHP[6] = FindConVar("z_tank_health");
zombieHP[0] = 250; // Hunter default HP
if (cvarZombieHP[0] != INVALID_HANDLE)
{
zombieHP[0] = GetConVarInt(cvarZombieHP[0]);
HookConVarChange(cvarZombieHP[0], cvarZombieHPChanged);
}
zombieHP[1] = 250; // Smoker default HP
if (cvarZombieHP[1] != INVALID_HANDLE)
{
zombieHP[1] = GetConVarInt(cvarZombieHP[1]);
HookConVarChange(cvarZombieHP[1], cvarZombieHPChanged);
}
zombieHP[2] = 50; // Boomer default HP
if (cvarZombieHP[2] != INVALID_HANDLE)
{
zombieHP[2] = GetConVarInt(cvarZombieHP[2]);
HookConVarChange(cvarZombieHP[2], cvarZombieHPChanged);
}
if (g_bIsL4D2)
{
zombieHP[3] = 100; // Spitter default HP
if (cvarZombieHP[3] != INVALID_HANDLE)
{
zombieHP[3] = GetConVarInt(cvarZombieHP[3]);
HookConVarChange(cvarZombieHP[3], cvarZombieHPChanged);
}
zombieHP[4] = 325; // Jockey default HP
if (cvarZombieHP[4] != INVALID_HANDLE)
{
zombieHP[4] = GetConVarInt(cvarZombieHP[4]);
HookConVarChange(cvarZombieHP[4], cvarZombieHPChanged);
}
zombieHP[5] = 600; // Charger default HP
if (cvarZombieHP[5] != INVALID_HANDLE)
{
zombieHP[5] = GetConVarInt(cvarZombieHP[5]);
HookConVarChange(cvarZombieHP[5], cvarZombieHPChanged);
}
}
// Create persistent storage for client HUD preferences
usrHUDPref = CreateTrie();
}
////////////////
//CONVAR HOOKS//
////////////////
public ConVarBoomerLimit(Handle:convar, const String:oldValue[], const String:newValue[])
{
BoomerLimit = GetConVarInt(h_BoomerLimit);
}
public ConVarSmokerLimit(Handle:convar, const String:oldValue[], const String:newValue[])
{
SmokerLimit = GetConVarInt(h_SmokerLimit);
}
public ConVarHunterLimit(Handle:convar, const String:oldValue[], const String:newValue[])
{
HunterLimit = GetConVarInt(h_HunterLimit);
}
public ConVarSpitterLimit(Handle:convar, const String:oldValue[], const String:newValue[])
{
SpitterLimit = GetConVarInt(h_SpitterLimit);
}
public ConVarJockeyLimit(Handle:convar, const String:oldValue[], const String:newValue[])
{
JockeyLimit = GetConVarInt(h_JockeyLimit);
}
public ConVarChargerLimit(Handle:convar, const String:oldValue[], const String:newValue[])
{
ChargerLimit = GetConVarInt(h_ChargerLimit);
}
public ConVarDirectorCvarChanged(Handle:convar, const String:oldValue[], const String:newValue[])
{
DirectorCvarsModified = true;
}
public ConVarMaxPlayerZombies(Handle:convar, const String:oldValue[], const String:newValue[])
{
MaxPlayerZombies = GetConVarInt(h_MaxPlayerZombies);
CreateTimer(0.1, MaxSpecialsSet);
}
public ConVarDirectorSpawn(Handle:convar, const String:oldValue[], const String:newValue[])
{
DirectorSpawn = GetConVarBool(h_DirectorSpawn);
if (!DirectorSpawn)
{
//ResetCvars();
TweakSettings();
CheckIfBotsNeeded(true, false);
}
else
{
//ResetCvarsDirector();
DirectorStuff();
}
}
public ConVarGameMode(Handle:convar, const String:oldValue[], const String:newValue[])
{
GameModeCheck();
if (!DirectorSpawn)
{
//ResetCvars();
TweakSettings();
}
else
{
//ResetCvarsDirector();
DirectorStuff();
}
}
public ConVarDifficulty(Handle:convar, const String:oldValue[], const String:newValue[])
{
TankHealthCheck();
}
public ConVarVersusCoop(Handle:convar, const String:oldValue[], const String:newValue[])
{
if (GetConVarBool(h_VersusCoop))
{
SetConVarInt(FindConVar("vs_max_team_switches"), 0);
if (g_bIsL4D2)
{
SetConVarInt(FindConVar("sb_all_bot_game"), 1);
SetConVarInt(FindConVar("allow_all_bot_survivor_team"), 1);
}
else
SetConVarInt(FindConVar("sb_all_bot_team"), 1);
}
else
{
SetConVarInt(FindConVar("vs_max_team_switches"), 1);
if (g_bIsL4D2)
{
SetConVarInt(FindConVar("sb_all_bot_game"), 0);
SetConVarInt(FindConVar("allow_all_bot_survivor_team"), 0);
}
else
SetConVarInt(FindConVar("sb_all_bot_team"), 0);
}
}
public ConVarCoopVersus(Handle:convar, const String:oldValue[], const String:newValue[])
{
if (GetConVarBool(h_JoinableTeams))
{
if (g_bIsL4D2)
{
SetConVarInt(FindConVar("sb_all_bot_game"), 1);
SetConVarInt(FindConVar("allow_all_bot_survivor_team"), 1);
}
else
SetConVarInt(FindConVar("sb_all_bot_team"), 1);
}
else
{
if (g_bIsL4D2)
{
SetConVarInt(FindConVar("sb_all_bot_game"), 0);
SetConVarInt(FindConVar("allow_all_bot_survivor_team"), 0);
}
else
SetConVarInt(FindConVar("sb_all_bot_team"), 0);
}
}
////////////////
//EVENTS////////
////////////////
public Action:evtRoundStart(Handle:event, const String:name[], bool:dontBroadcast)
{
// If round has started ...
if (b_HasRoundStarted)
return;
b_LeftSaveRoom = false;
b_HasRoundEnded = false;
b_HasRoundStarted = true;
//Check the GameMode
GameModeCheck();
if (GameMode == 0)
return;
#if DEBUGCLIENTS
PrintToChatAll("Round Started");
#endif
#if DEBUGSERVER
LogMessage("Round Started");
#endif
// Removes the boundaries for z_max_player_zombies and notify flag
new flags = GetConVarFlags(FindConVar("z_max_player_zombies"));
SetConVarBounds(FindConVar("z_max_player_zombies"), ConVarBound_Upper, false);
SetConVarFlags(FindConVar("z_max_player_zombies"), flags & ~FCVAR_NOTIFY);
// When the game starts, stop the bots till a player joins
if (!b_LeftSaveRoom)
SetConVarInt(FindConVar("sb_stop"), 1);
// Added a delay to setting MaxSpecials so that it would set correctly when the server first starts up
CreateTimer(0.4, MaxSpecialsSet);
if (AfterInitialRound)
{
#if DEBUGCLIENTS
PrintToChatAll("Another Round has started");
#endif
// This little part is needed because some events just can't execute when another round starts.
SetConVarInt(FindConVar("sb_stop"), 0);
if (GameMode == VERSUS && GetConVarBool(h_VersusCoop))
{
for (new i=1; i<=MaxClients; i++)
{
// We check if player is in game
if (!IsClientInGame(i)) continue;
// Check if client is survivor ...
if (GetClientTeam(i)==TEAM_SURVIVORS)
{
// If player is a real player ...
if (!IsFakeClient(i))
{
ChangeClientTeam(i, TEAM_INFECTED);
}
}
}