00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 .float ai_time;
00011 void bot_attack();
00012 vector realorigin (entity ent)
00013 {
00014 return (ent.absmin + ent.absmax) * 0.5;
00015 }
00016
00017
00018
00019
00020 float KickABotClientCheck()
00021 {
00022 local float pclients;
00023
00024 pclients = stof(infokey(world, "bots_padclients"));
00025
00026 if( infokey(world, "bots_clientcontrol") == "1" )
00027 {
00028 if( CountPlayers() > pclients )
00029 return 1;
00030 else
00031 sprint(self, PRINT_HIGH, "Can't remove bots that are there to pad player slots!\n");
00032 }
00033 else
00034 sprint(self, PRINT_HIGH, "Clients not allowed to add/kick bots on this server!\n");
00035
00036 return 0;
00037 }
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048 void KickABotDM(float clientcalled)
00049 {
00050 if( clientcalled )
00051 if( !KickABotClientCheck )
00052 return 2;
00053
00054 entity pkick;
00055 pkick = find(world, classname, "player");
00056 while( pkick != world )
00057 {
00058 if( infokey(pkick, "isbot") == "1" )
00059 {
00060 stuffcmd(pkick, "disconnect\n");
00061 pkick = world;
00062 }
00063 else
00064 {
00065 pkick = find(pkick, classname, "player");
00066 }
00067 }
00068
00069
00070 }
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081 float KickABotTeam(float bteam, float clientcalled)
00082 {
00083
00084
00085
00086
00087
00088
00089
00090 local string isbot;
00091 local string found_ent_team;
00092 local string bot_team, s_bot_team;
00093 local float retval;
00094
00095 retval = 1;
00096
00097 if( clientcalled )
00098 if( !KickABotClientCheck() )
00099 return 2;
00100
00101
00102 bot_team = snap_misc_nameforteamnum(bteam);
00103 s_bot_team = strzone(bot_team);
00104
00105 entity pkick;
00106 pkick = find(world, classname, "player");
00107 while( pkick != world )
00108 {
00109 found_ent_team = infokey(pkick, "team");
00110 isbot = infokey(pkick, "isbot");
00111
00112 if( isbot == "1" && found_ent_team == s_bot_team )
00113 {
00114 stuffcmd(pkick, "disconnect\n");
00115 pkick = world;
00116 retval = 0;
00117 }
00118 else
00119 {
00120 pkick = find(pkick, classname, "player");
00121 }
00122 }
00123
00124 strunzone(s_bot_team);
00125 return retval;
00126
00127
00128 }
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 void bot_jump1();
00223 void respawn_bot();
00224 void bot_check_ammo();
00225
00226
00227
00228
00229
00230 void bot_search_for_items()
00231
00232 {
00233 local entity item;
00234
00235
00236 if (time > self.search_time && self.goalentity != world)
00237 {
00238 self.goalentity.search_time = time + 30;
00239 self.goalentity = world;
00240 }
00241
00242 if (self.goalentity != world)
00243 return;
00244
00245
00246 item = findradius(self.origin, 1500);
00247
00248 while(item)
00249 {
00250 if ( (item.flags & FL_ITEM) && visible(item) && item.model != string_null && time > item.search_time)
00251 {
00252 self.search_time = time + 30;
00253 self.goalentity = item;
00254 }
00255 item = item.chain;
00256 }
00257
00258 };
00259
00260
00261
00262 void bot_grab_items()
00263
00264 {
00265
00266
00267
00268 if (self.goalentity == world)
00269 return;
00270
00271 if (vlen(self.origin - self.goalentity.origin) <= 70)
00272 {
00273 self.goalentity.search_time = time + 60;
00274 self.goalentity.solid = SOLID_NOT;
00275 self.goalentity.model = string_null;
00276 self.goalentity.nextthink = time + 20;
00277 self.goalentity.think = SUB_regen;
00278 if (self.goalentity.healamount)
00279 sound (self, CHAN_ITEM, "items/health1.wav", 1, ATTN_NORM);
00280 else if (self.goalentity.weapon)
00281 sound (self, CHAN_ITEM, "weapons/pkup.wav", 1, ATTN_NORM);
00282 else
00283 sound(self, CHAN_ITEM, "items/armor1.wav", 1, ATTN_NORM);
00284 self.goalentity = world;
00285 }
00286
00287 };
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297 void jump_forward()
00298
00299 {
00300
00301
00302 if (!(self.flags & FL_ONGROUND))
00303 return;
00304
00305 self.flags = self.flags - (self.flags & FL_ONGROUND);
00306 makevectors(self.angles);
00307 self.velocity = self.velocity + (v_forward * 250);
00308 self.velocity_z = self.velocity_z + 250;
00309
00310 };
00311
00312
00313
00314 void check_for_water()
00315
00316 {
00317 local float p;
00318
00319
00320
00321 makevectors(self.angles);
00322 p = pointcontents(self.origin + v_forward*16);
00323 if (p != CONTENT_WATER && p != CONTENT_SLIME && p != CONTENT_LAVA)
00324 return;
00325
00326 if (p == CONTENT_WATER && time > self.pain_finished)
00327 {
00328 T_Damage (self, world, world, 5);
00329 self.pain_finished = time + 2;
00330 sound (self, CHAN_VOICE, "player/gasp2.wav", 1, ATTN_NORM);
00331 }
00332 if (p == CONTENT_SLIME && time > self.pain_finished)
00333 {
00334 T_Damage (self, world, world, 10);
00335 self.pain_finished = time + 1;
00336 sound (self, CHAN_VOICE, "player/lburn2.wav", 1, ATTN_NORM);
00337 }
00338 if (p == CONTENT_LAVA && time > self.pain_finished)
00339 {
00340 T_Damage (self, world, world, 20);
00341 self.pain_finished = time + 0.5;
00342 sound (self, CHAN_VOICE, "player/lburn1.wav", 1, ATTN_NORM);
00343 }
00344
00345 self.flags = self.flags - (self.flags & FL_ONGROUND);
00346
00347
00348 self.velocity = self.velocity + (v_forward * 200);
00349 self.velocity_z = self.velocity_z + 200;
00350 if (random() < 0.4)
00351 self.velocity_x = self.velocity_x + 100;
00352 else if (random() > 0.8)
00353 self.velocity_y = self.velocity_y + 100;
00354
00355 };
00356
00357
00358
00359
00360
00361 void check_for_ledge()
00362
00363 {
00364 local vector spot;
00365
00366
00367
00368
00369 if (random() < 0.80)
00370 return;
00371
00372 if (!(self.flags & FL_ONGROUND))
00373 return;
00374
00375
00376 self.flags = self.flags - (self.flags & FL_ONGROUND);
00377 makevectors(self.angles);
00378 self.velocity = self.velocity + (v_forward * 250);
00379 self.velocity_z = self.velocity_z + 250;
00380
00381
00382
00383
00384
00385
00386 };
00387
00388
00389
00390
00391
00392
00393 float bot_look_for_players()
00394
00395 {
00396 local entity client;
00397 local float r;
00398
00399
00400
00401 client = checkclient ();
00402 if (!client)
00403 return false;
00404
00405 if( coop )
00406 {
00407 local entity favent;
00408
00409
00410 client = findradius(self.origin, 1000);
00411 while( client )
00412 {
00413 if( client.flags & FL_MONSTER
00414 && client.health > 0
00415 && visible(client) )
00416 favent = client;
00417
00418 client = client.chain;
00419 }
00420
00421 client = favent;
00422 }
00423
00424
00425
00426
00427
00428
00429
00430 if (teamplay)
00431 {
00432 local string myteam, theirteam;
00433 myteam = infokey(self, "team");
00434 theirteam = infokey(client, "team");
00435 if (myteam == theirteam && myteam != "")
00436 return false;
00437 }
00438
00439 if (client.netname == "observer")
00440 return false;
00441
00442 if (client == self.enemy)
00443 return false;
00444
00445 if (client.flags & FL_NOTARGET)
00446 return false;
00447 if (client.items & IT_INVISIBILITY)
00448 return false;
00449
00450 r = range (client);
00451 if (r == RANGE_FAR)
00452 return false;
00453
00454 if (!visible (client))
00455 return false;
00456
00457 if (r == RANGE_NEAR)
00458 {
00459 if (client.show_hostile < time && !infront (client))
00460 return false;
00461 }
00462 else if (r == RANGE_MID)
00463 {
00464 if (!infront (client))
00465 return false;
00466 }
00467
00468 self.enemy = client;
00469
00470
00471 self.goalentity = client;
00472
00473
00474 return true;
00475 };
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523 void bot_face()
00524
00525 {
00526 if(self.enemy != world) {
00527 vector viewangles;
00528
00529
00530 self.angles_y = vectoyaw(self.enemy.origin - self.origin);
00531 viewangles = vectoangles(self.enemy.origin - self.origin);
00532 self.v_angle_x = viewangles_x;
00533 self.v_angle_y = viewangles_y;
00534
00535 if (self.v_angle_x > 180)
00536 self.v_angle_x = self.v_angle_x - 360;
00537
00538 self.v_angle_x = self.v_angle_x * -1;
00539
00540 if (self.v_angle_x > 80)
00541 self.v_angle_x = 80;
00542
00543 if (self.v_angle_x < -80)
00544 self.v_angle_x = -80;
00545 }
00546 }
00547
00548
00549 void bot_stand()
00550
00551 {
00552
00553
00554
00555
00556
00557 bot_look_for_players();
00558 check_for_water();
00559
00560 if (time > self.pausetime)
00561 {
00562 self.th_walk();
00563 return;
00564 }
00565
00566
00567 if (random() < 0.1)
00568 self.angles_y = self.angles_y - 45;
00569 else if (random() > 0.9)
00570 self.angles_y = self.angles_y + 15;
00571 };
00572
00573
00574
00575
00576
00577 void coffee_move()
00578
00579 {
00580
00581
00582
00583
00584
00585
00586
00587 if (walkmove (self.angles_y, 20) == false)
00588 if (walkmove (self.angles_y + self.button1, 20) == false)
00589 self.angles_y = self.angles_y + (self.button1 / 2);
00590
00591
00592
00593 if (random() <= 0.02)
00594 if (self.button1 == 90)
00595 self.button1 = -90;
00596 else self.button1 = 90;
00597
00598 };
00599
00600
00601
00602 void bot_walk()
00603
00604 {
00605
00606
00607
00608
00609 if (!(self.flags & FL_ONGROUND))
00610 return;
00611
00612
00613
00614 bot_look_for_players();
00615
00616
00617
00618 check_for_ledge();
00619 check_for_water();
00620
00621
00622
00623
00624
00625
00626 if (self.goalentity != world)
00627 movetogoal(20);
00628 else coffee_move();
00629
00630
00631
00632 };
00633
00634
00635
00636
00637
00638
00639 void bot_run_slide()
00640
00641 {
00642 local float ofs;
00643
00644
00645
00646 if (self.lefty)
00647 ofs = 90;
00648 else
00649 ofs = -90;
00650
00651 if (walkmove (self.angles_y + ofs, 20))
00652 return;
00653
00654 self.lefty = 1 - self.lefty;
00655
00656 walkmove (self.angles_y - ofs, 20);
00657 };
00658
00659
00660
00661
00662
00663 void bot_strafe()
00664
00665 {
00666
00667
00668
00669 bot_check_ammo();
00670
00671 if (!visible(self.enemy))
00672 {
00673 movetogoal(20);
00674 return;
00675 }
00676
00677 bot_face();
00678
00679
00680
00681 if (self.weapon == IT_ROCKET_LAUNCHER)
00682 {
00683 if (walkmove (self.angles_y - 180, 20) == false)
00684 bot_run_slide();
00685 }
00686
00687
00688 else if (self.weapon == IT_SUPER_SHOTGUN)
00689 movetogoal(20);
00690
00691
00692 else if (self.weapon == IT_LIGHTNING)
00693 return;
00694
00695 else
00696 {
00697
00698
00699
00700
00701 local float skill;
00702 skill = stof(infokey(self, "bskill"));
00703 if (skill == 1)
00704 {
00705 if( self.weapon != IT_ROCKET_LAUNCHER )
00706 if( self.weapon != IT_GRENADE_LAUNCHER )
00707 {
00708 movetogoal(20);
00709 }
00710 }
00711 else if (skill == 2)
00712 {
00713 bot_run_slide();
00714 }
00715
00716 }
00717 };
00718
00719
00720
00721 void bot_run()
00722
00723 {
00724
00725
00726
00727
00728 if (!(self.flags & FL_ONGROUND))
00729 return;
00730
00731 check_for_water();
00732
00733 if (visible(self.enemy))
00734 self.search_time = time + 6;
00735
00736 if (time > self.search_time || self.enemy.health <= 0)
00737 {
00738 self.goalentity = world;
00739 self.enemy = world;
00740 self.pausetime = time + 4;
00741
00742
00743 return;
00744 }
00745
00746 bot_strafe();
00747
00748
00749 bot_face();
00750
00751 if (visible(self.enemy) && time > self.attack_finished)
00752 bot_attack();
00753
00754
00755 };
00756
00757
00758
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797 void bot_run1();
00798
00799
00800
00801 void bot_drop_pack()
00802
00803 {
00804 if (random () < 0.5)
00805 DropBackpack();
00806 };
00807
00808
00809
00810 void give_random_weapon(entity targ)
00811
00812 {
00813 local float it;
00814
00815 it = floor(random() * 6);
00816
00817 if (it == 0)
00818 {
00819 targ.items = targ.items | IT_SUPER_SHOTGUN;
00820 targ.currentammo = targ.ammo_shells = targ.ammo_shells + 25;
00821 targ.weapon = IT_SUPER_SHOTGUN;
00822 }
00823 else if (it == 1)
00824 {
00825 targ.items = targ.items | IT_NAILGUN;
00826 targ.currentammo = targ.ammo_nails = targ.ammo_nails + 50;
00827 targ.weapon = IT_NAILGUN;
00828 }
00829 else if (it == 2)
00830 {
00831 targ.items = targ.items | IT_LIGHTNING;
00832 targ.currentammo = targ.ammo_cells = targ.ammo_cells + 50;
00833 targ.weapon = IT_LIGHTNING;
00834 }
00835 else if (it == 3)
00836 {
00837 targ.items = targ.items | IT_GRENADE_LAUNCHER;
00838 targ.currentammo = targ.ammo_rockets = targ.ammo_rockets + 5;
00839 targ.weapon = IT_GRENADE_LAUNCHER;
00840 }
00841 else if (it == 4)
00842 {
00843 targ.items = targ.items | IT_ROCKET_LAUNCHER;
00844 targ.currentammo = targ.ammo_rockets = targ.ammo_rockets + 5;
00845 targ.weapon = IT_ROCKET_LAUNCHER;
00846 }
00847 else
00848 {
00849 targ.items = targ.items | IT_SUPER_NAILGUN;
00850 targ.currentammo = targ.ammo_nails = targ.ammo_nails + 50;
00851 targ.weapon = IT_SUPER_NAILGUN;
00852 }
00853
00854 };
00855
00856
00857
00858
00859
00860
00861 float bot_bestweapon()
00862
00863 {
00864 local float it;
00865
00866 it = self.items;
00867
00868 if (self.ammo_rockets >= 1 && (it & IT_ROCKET_LAUNCHER) )
00869 return IT_ROCKET_LAUNCHER;
00870 else if (self.ammo_cells >= 2 && (it & IT_LIGHTNING) )
00871 return IT_LIGHTNING;
00872 else if (self.ammo_nails >= 2 && (it & IT_SUPER_NAILGUN) )
00873 return IT_SUPER_NAILGUN;
00874 else if (self.ammo_rockets >= 1 && (it & IT_GRENADE_LAUNCHER) )
00875 return IT_GRENADE_LAUNCHER;
00876 else if (self.ammo_shells >= 2 && (it & IT_SUPER_SHOTGUN) )
00877 return IT_SUPER_SHOTGUN;
00878 else if (self.ammo_nails >= 1 && (it & IT_NAILGUN) )
00879 return IT_NAILGUN;
00880
00881 return IT_SHOTGUN;
00882
00883 };
00884
00885
00886
00887
00888 void bot_set_currentammo()
00889
00890 {
00891 self.items = self.items - ( self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS) );
00892
00893 if (self.weapon == IT_SHOTGUN)
00894 {
00895 self.currentammo = self.ammo_shells;
00896 self.items = self.items | IT_SHELLS;
00897 }
00898 else if (self.weapon == IT_SUPER_SHOTGUN)
00899 {
00900 self.currentammo = self.ammo_shells;
00901 self.items = self.items | IT_SHELLS;
00902 }
00903 else if (self.weapon == IT_NAILGUN)
00904 {
00905 self.currentammo = self.ammo_nails;
00906 self.items = self.items | IT_NAILS;
00907 }
00908 else if (self.weapon == IT_SUPER_NAILGUN)
00909 {
00910 self.currentammo = self.ammo_nails;
00911 self.items = self.items | IT_NAILS;
00912 }
00913 else if (self.weapon == IT_ROCKET_LAUNCHER)
00914 {
00915 self.currentammo = self.ammo_rockets;
00916 self.items = self.items | IT_ROCKETS;
00917 }
00918 else if (self.weapon == IT_LIGHTNING)
00919 {
00920 self.currentammo = self.ammo_cells;
00921 self.items = self.items | IT_CELLS;
00922 }
00923 else
00924 {
00925 self.currentammo = 0;
00926 self.weaponmodel = "";
00927 self.weaponframe = 0;
00928 }
00929 };
00930
00931
00932
00933 void bot_check_ammo()
00934
00935 {
00936 local float chance;
00937
00938 if (self.currentammo > 0)
00939 return;
00940
00941 if (self.weapon == IT_SHOTGUN)
00942 return;
00943
00944 self.weapon = bot_bestweapon();
00945
00946 bot_set_currentammo();
00947
00948
00949
00950 };
00951
00952
00953
00954
00955 vector() bot_aim_at_enemy =
00956
00957 {
00958
00959 return normalize(self.enemy.origin - self.origin);
00960
00961 };
00962
00963
00964
00965 void bot_fire_supershotgun()
00966
00967 {
00968 local vector dir;
00969
00970 self.currentammo = self.ammo_shells = self.ammo_shells - 2;
00971 bot_face();
00972 sound (self ,CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM);
00973
00974 dir = bot_aim_at_enemy();
00975 FireBullets (18, dir, '0.14 0.1 0');
00976 };
00977
00978
00979
00980
00981 void bot_fire_shotgun()
00982
00983 {
00984 local vector dir;
00985
00986 if (self.weapon == IT_SUPER_SHOTGUN)
00987 {
00988 bot_fire_supershotgun();
00989 return;
00990 }
00991
00992 bot_face();
00993
00994 sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM);
00995
00996
00997 dir = bot_aim_at_enemy();
00998 FireBullets (6, dir, '0.04 0.04 0');
00999
01000 };
01001
01002
01003
01004
01005
01006 void bot_fire_supernailgun()
01007
01008 {
01009 local vector dir;
01010
01011 self.currentammo = self.ammo_nails = self.ammo_nails - 1;
01012 sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
01013
01014 dir = bot_aim_at_enemy();
01015 launch_spike (self.origin + '0 6 16', dir);
01016 newmis.touch = superspike_touch;
01017 setmodel (newmis, "progs/s_spike.mdl");
01018 setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);
01019 };
01020
01021
01022
01023 void bot_fire_nailgun()
01024
01025 {
01026 local vector dir;
01027
01028 if (self.weapon == IT_SUPER_NAILGUN)
01029 {
01030 bot_fire_supernailgun();
01031 return;
01032 }
01033
01034 self.currentammo = self.ammo_nails = self.ammo_nails - 1;
01035 makevectors (self.v_angle);
01036 sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
01037
01038 dir = bot_aim_at_enemy();
01039 launch_spike (self.origin + '0 6 16', dir);
01040
01041 };
01042
01043
01044
01045 void bot_fire_grenade()
01046
01047 {
01048 local entity missile;
01049
01050 self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
01051
01052 sound (self, CHAN_WEAPON, "weapons/grenade.wav", 1, ATTN_NORM);
01053
01054 missile = spawn ();
01055 missile.owner = self;
01056 missile.movetype = MOVETYPE_BOUNCE;
01057 missile.solid = SOLID_BBOX;
01058
01059
01060 makevectors (self.v_angle);
01061
01062 missile.velocity = bot_aim_at_enemy();
01063 missile.velocity = missile.velocity * 500;
01064 missile.velocity_z = 300;
01065
01066 missile.avelocity = '300 300 300';
01067
01068 missile.angles = vectoangles(missile.velocity);
01069
01070 missile.touch = GrenadeTouch;
01071
01072
01073 missile.nextthink = time + 2.5;
01074 missile.think = GrenadeExplode;
01075
01076 setmodel (missile, "progs/grenade.mdl");
01077 setsize (missile, '0 0 0', '0 0 0');
01078 setorigin (missile, self.origin);
01079
01080 };
01081
01082
01083
01084
01085 void bot_fire_rocket()
01086
01087 {
01088 local entity missile;
01089
01090 if (self.weapon == IT_GRENADE_LAUNCHER)
01091 {
01092 bot_fire_grenade();
01093 return;
01094 }
01095
01096 self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
01097 sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
01098
01099 missile = spawn ();
01100 missile.owner = self;
01101 missile.movetype = MOVETYPE_FLYMISSILE;
01102 missile.solid = SOLID_BBOX;
01103 missile.classname = "missile";
01104
01105 missile.velocity = bot_aim_at_enemy() * 1000;
01106
01107 missile.angles = vectoangles(missile.velocity);
01108 missile.touch = T_MissileTouch;
01109 missile.nextthink = time + 5;
01110 missile.think = SUB_Remove;
01111
01112 setmodel (missile, "progs/missile.mdl");
01113 setsize (missile, '-1 -1 -1', '1 1 1');
01114 setorigin (missile, self.origin + v_forward*8 + '0 0 16');
01115 };
01116
01117
01118
01119
01120
01121
01122
01123 void bot_lightning()
01124
01125 {
01126 local vector org, dir;
01127
01128
01129
01130 bot_face();
01131
01132
01133 makevectors(self.angles);
01134 org = self.origin + '0 0 8' + (v_forward * 8);
01135
01136 dir = bot_aim_at_enemy();
01137
01138 traceline (org, self.origin + dir*600, true, self);
01139
01140 WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
01141 WriteByte (MSG_BROADCAST, TE_LIGHTNING1);
01142 WriteEntity (MSG_BROADCAST, self);
01143 WriteCoord (MSG_BROADCAST, org_x);
01144 WriteCoord (MSG_BROADCAST, org_y);
01145 WriteCoord (MSG_BROADCAST, org_z);
01146 WriteCoord (MSG_BROADCAST, trace_endpos_x);
01147 WriteCoord (MSG_BROADCAST, trace_endpos_y);
01148 WriteCoord (MSG_BROADCAST, trace_endpos_z);
01149
01150 LightningDamage (org, trace_endpos, self, 10);
01151
01152 sound (self, CHAN_WEAPON, "weapons/lhit.wav", 1, ATTN_NORM);
01153 self.currentammo = self.ammo_cells = self.ammo_cells - 1;
01154 };
01155
01156
01157
01158
01159
01160
01161
01162
01163
01164
01165
01166
01167
01168
01169
01170
01171
01172
01173
01174
01175
01176
01177
01178
01179
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314
01315
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339
01340
01341
01342
01343
01344
01345
01346
01347
01348
01349
01350
01351
01352
01353
01354
01355
01356
01357
01358
01359
01360
01361
01362
01363
01364
01365
01366
01367
01368
01369
01370
01371
01372
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400
01401
01402
01403
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414
01415
01416
01417
01418
01419
01420
01421
01422
01423
01424
01425
01426
01427
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515
01516
01517
01518
01519
01520
01521
01522
01523
01524
01525
01526
01527
01528
01529
01530
01531
01532
01533
01534
01535
01536
01537
01538
01539
01540
01541
01542
01543
01544
01545
01546
01547
01548
01549
01550
01551
01552
01553
01554
01555
01556
01557
01558
01559 vector weapon_range (float wep)
01560 {
01561 if (wep == IT_AXE)
01562 return '48 0 64';
01563 else if (wep == IT_SHOTGUN)
01564 return '128 0 99999';
01565 else if (wep == IT_SUPER_SHOTGUN)
01566 return '128 0 99999';
01567 else if (wep == IT_NAILGUN)
01568 return '180 0 3000';
01569 else if (wep == IT_SUPER_NAILGUN)
01570 return '180 0 3000';
01571 else if (wep == IT_GRENADE_LAUNCHER)
01572 return '180 48 3000';
01573 else if (wep == IT_ROCKET_LAUNCHER)
01574 return '180 48 3000';
01575 else if (wep == IT_LIGHTNING)
01576 return '350 0 512';
01577 }
01578
01579
01580
01581 void bot_attack()
01582
01583 {
01584 vector dir, org, range;
01585 float foedist;
01586
01587 bot_check_ammo();
01588
01589
01590
01591 org = realorigin(self.enemy);
01592 makevectors(self.v_angle);
01593 foedist = vlen(org - self.origin);
01594 range = weapon_range(self.weapon);
01595 traceline (self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * range_z, false, self);
01596
01597 if (vlen(trace_endpos - (self.origin + self.view_ofs)) >= range_y)
01598 self.button0 = true;
01599 }
01600
01601
01602
01603 string() bot_name =
01604
01605 {
01606 local float n;
01607 n = floor(random() * 16);
01608 if (n == 0) return "Obliterator";
01609 else if (n == 1) return "Obelisk";
01610 else if (n == 2) return "Obscure";
01611 else if (n == 3) return "Obtuse";
01612 else if (n == 4) return "Obe";
01613 else if (n == 5) return "Obsidian";
01614 else if (n == 6) return "Obstructor";
01615 else if (n == 7) return "Obi";
01616 else if (n == 8) return "Obstinate";
01617 else if (n == 9) return "Objector";
01618 else if (n ==10) return "Oberon";
01619 else if (n ==11) return "Obveela";
01620 else if (n ==12) return "Obate";
01621 else if (n ==13) return "Obruge";
01622 else if (n ==14) return "Obete";
01623 else return "Oblivion";
01624
01625
01626
01627
01628
01629
01630
01631
01632
01633
01634
01635 };
01636
01637
01638
01639
01640
01641
01642
01643
01644
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661
01662
01663
01664
01665
01666
01667
01668
01669
01670
01671
01672
01673
01674
01675
01676
01677
01678
01679
01680
01681
01682
01683
01684
01685
01686
01687
01688
01689
01690
01691
01692
01693
01694
01695
01696
01697
01698
01699
01700
01701
01702
01703
01704
01705
01706
01707
01708
01709
01710
01711
01712
01713
01714
01715
01716
01717
01718
01719
01720
01721
01722
01723
01724
01725
01726
01727
01728
01729
01730
01731
01732
01733
01734
01735
01736
01737
01738
01739
01740
01741
01742
01743
01744
01745
01746
01747
01748
01749
01750
01751
01752 void create_bot(float bottom, float top, string bteam, float clientcalled)
01753
01754 {
01755 entity bot;
01756 local string s_bteam;
01757 local string skill, tmp;
01758
01759 s_bteam = strzone(bteam);
01760
01761
01762
01763
01764
01765
01766
01767
01768 if( clientcalled )
01769 if (!stof(infokey(world, "bots_clientcontrol")))
01770 {
01771 sprint(self, PRINT_HIGH, "Clients not allowed to add/kick bots on this server!\n");
01772 strunzone(s_bteam);
01773
01774 return;
01775 }
01776
01777
01778 skill = infokey(world, "bots_skill");
01779 if( !skill || stof(skill) < 0 || stof(skill) > 2 )
01780 {
01781 sprint(self, PRINT_HIGH, "Can't add a bot - server admin has not set bots_skill to 0, 1 or 2!\n");
01782 strunzone(s_bteam);
01783 return;
01784 }
01785
01786
01787 bot = testbot("tutorbot");
01788 if (!bot)
01789 {
01790 sprint(self, PRINT_HIGH, "Can't connect any more bots - server is full!\n");
01791 strunzone(s_bteam);
01792 return;
01793 }
01794
01795
01796 setinfo (bot, "team", s_bteam);
01797
01798
01799 strunzone(s_bteam);
01800
01801
01802 tmp = ftos(bottom);
01803 setinfo (bot, "bottomcolor", tmp);
01804 tmp = ftos(top);
01805 setinfo (bot, "topcolor", tmp);
01806
01807
01808
01809
01810
01811 bot.speed = 320;
01812
01813
01814 bot.netname = bot_name();
01815 setinfo (bot, "name", bot.netname);
01816
01817
01818
01819
01820 bot.button1 = 90;
01821
01822
01823
01824 setinfo(bot, "isbot", "1");
01825 if( clientcalled )
01826 setinfo(bot, "cab", "1");
01827 setinfo(bot, "bskill", skill);
01828 }
01829
01830
01831 void BotConnect ()
01832 {
01833 ClientConnect ();
01834 }
01835
01836
01837 void BotDisconnect ()
01838 {
01839 ClientDisconnect ();
01840 }
01841
01842
01843 void BotPreThink ()
01844 {
01845
01846 if (self.health < 1)
01847 {
01848 self.button0 = false;
01849 self.button2 = floor(random() * 2);
01850 self.enemy = self.goalentity = world;
01851 if (self.deadflag == DEAD_DEAD)
01852 {
01853 self.deadflag = DEAD_RESPAWNABLE;
01854 respawn();
01855 }
01856 return;
01857 }
01858
01859 if (self.ai_time > time) {
01860
01861 } else {
01862 self.ai_time = time + 0.1;
01863 if(self.enemy == world || self.enemy == self) {
01864 self.button0 = false;
01865
01866
01867 if (time > self.pausetime) {
01868 bot_walk();
01869 } else {
01870 bot_stand();
01871 }
01872 } else if (self.health > 0) {
01873 bot_run();
01874 }
01875 }
01876
01877 PlayerPreThink ();
01878 }
01879
01880
01881 void BotPostThink ()
01882 {
01883 PlayerPostThink ();
01884 }
01885
01886