home *** CD-ROM | disk | FTP | other *** search
/ Superpower (Alt) / SUPERPOWER.iso / q / patch / mbq111 / src / botai.qc < prev    next >
Encoding:
Text File  |  1996-09-03  |  22.1 KB  |  709 lines

  1. /*
  2. ==============================================================================
  3.                                                         
  4. BG BOT AI
  5.  
  6. ==============================================================================
  7. */
  8.  
  9. // Prototypes
  10.  
  11. float   ()                                              BotFindTarget;
  12. float   ()                                              BotFindStuff;
  13. void    ()                                              bot_ai_stand;
  14. void    (entity attacker, float damage)                 bot_pain;
  15. void    ()                                              bot_die;
  16. void    ()                                              BotFoundTarget;
  17. void    ()                                              BotHuntTarget;
  18. void    ()                                              BotFoundStuff;
  19. void    ()                                              BotHuntStuff;
  20. void    (float dist)                                    bot_ai_walk;
  21. void    (float dist)                                    bot_ai_run;
  22. void    (float dist)                                    bot_ai_stuff;
  23. void    (void () thinkst)                               BotCheckRefire;
  24. void    ()                                              BotSelfDeActivate;
  25. void    ()                                              bot_fire;
  26. void    ()                                              bot_fire2;
  27. void    (vector org, vector dir)                        launch_spike;
  28. void    ()                                              spike_touch; 
  29. // Frame macros
  30.  
  31. $cd /raid/quake/id1/models/player_4
  32. $origin 0 -6 24
  33. $base base        
  34. $skin skin
  35.  
  36. $frame axrun1 axrun2 axrun3 axrun4 axrun5 axrun6
  37.  
  38. $frame rockrun1 rockrun2 rockrun3 rockrun4 rockrun5 rockrun6
  39.  
  40. //
  41. // standing
  42. //
  43. $frame stand1 stand2 stand3 stand4 stand5
  44.  
  45. $frame axstnd1 axstnd2 axstnd3 axstnd4 axstnd5 axstnd6
  46. $frame axstnd7 axstnd8 axstnd9 axstnd10 axstnd11 axstnd12
  47.  
  48.  
  49. //
  50. // pain
  51. //
  52. $frame axpain1 axpain2 axpain3 axpain4 axpain5 axpain6
  53.  
  54. $frame pain1 pain2 pain3 pain4 pain5 pain6
  55.  
  56.  
  57. //
  58. // death
  59. //
  60.  
  61. $frame axdeth1 axdeth2 axdeth3 axdeth4 axdeth5 axdeth6
  62. $frame axdeth7 axdeth8 axdeth9
  63.  
  64. $frame deatha1 deatha2 deatha3 deatha4 deatha5 deatha6 deatha7 deatha8
  65. $frame deatha9 deatha10 deatha11
  66.  
  67. $frame deathb1 deathb2 deathb3 deathb4 deathb5 deathb6 deathb7 deathb8
  68. $frame deathb9
  69.  
  70. $frame deathc1 deathc2 deathc3 deathc4 deathc5 deathc6 deathc7 deathc8
  71. $frame deathc9 deathc10 deathc11 deathc12 deathc13 deathc14 deathc15
  72.  
  73. $frame deathd1 deathd2 deathd3 deathd4 deathd5 deathd6 deathd7
  74. $frame deathd8 deathd9
  75.  
  76. $frame deathe1 deathe2 deathe3 deathe4 deathe5 deathe6 deathe7
  77. $frame deathe8 deathe9
  78.  
  79. //
  80. // attacks
  81. //
  82. $frame nailatt1 nailatt2
  83.  
  84. $frame light1 light2
  85.  
  86. $frame rockatt1 rockatt2 rockatt3 rockatt4 rockatt5 rockatt6
  87.  
  88. $frame shotatt1 shotatt2 shotatt3 shotatt4 shotatt5 shotatt6
  89.  
  90. $frame axatt1 axatt2 axatt3 axatt4 axatt5 axatt6
  91.  
  92. $frame axattb1 axattb2 axattb3 axattb4 axattb5 axattb6
  93.  
  94. $frame axattc1 axattc2 axattc3 axattc4 axattc5 axattc6
  95.  
  96. $frame axattd1 axattd2 axattd3 axattd4 axattd5 axattd6
  97.  
  98.  
  99. void()    bot_stand1    =[    $stand1,    bot_stand2    ] {bot_ai_stand();};
  100. void()    bot_stand2    =[    $stand2,    bot_stand3    ] {bot_ai_stand();};
  101. void()    bot_stand3    =[    $stand3,    bot_stand4    ] {bot_ai_stand();};
  102. void()    bot_stand4    =[    $stand4,    bot_stand5    ] {bot_ai_stand();};
  103. void()  bot_stand5      =[      $stand5,        bot_stand1      ] {bot_ai_stand();};
  104.  
  105. void()  bot_walk1       =[      $rockrun1,        bot_walk2       ] {bot_ai_walk(14);};
  106. void()  bot_walk2       =[      $rockrun2,        bot_walk3       ] {bot_ai_walk(12);};
  107. void()  bot_walk3       =[      $rockrun3,        bot_walk4       ] {bot_ai_walk(15);};
  108. void()  bot_walk4       =[      $rockrun4,        bot_walk5       ] {bot_ai_walk(10);};
  109. void()  bot_walk5       =[      $rockrun5,        bot_walk6       ] {bot_ai_walk(19);};
  110. void()  bot_walk6       =[      $rockrun6,        bot_walk7       ] {bot_ai_walk(14);};
  111. void()  bot_walk7       =[      $rockrun1,        bot_walk8       ] {bot_ai_walk(13);};
  112. void()  bot_walk8       =[      $rockrun2,        bot_walk9       ] {bot_ai_walk(17);};
  113. void()  bot_walk9       =[      $rockrun3,        bot_walk10      ] {bot_ai_walk(12);};
  114. void()  bot_walk10      =[      $rockrun4,        bot_walk11      ] {bot_ai_walk(20);};
  115. void()  bot_walk11      =[      $rockrun5,        bot_walk12      ] {bot_ai_walk(10);};
  116. void()  bot_walk12      =[      $rockrun6,        bot_walk1      ] {bot_ai_walk(14);};
  117.  
  118. void()  bot_run1        =[      $rockrun1,        bot_run2        ] {bot_ai_run(18);};
  119. void()  bot_run2        =[      $rockrun2,        bot_run3        ] {bot_ai_run(14);};
  120. void()  bot_run3        =[      $rockrun3,        bot_run4        ] {bot_ai_run(9);};
  121. void()  bot_run4        =[      $rockrun4,        bot_run5        ] {bot_ai_run(12);};
  122. void()  bot_run5        =[      $rockrun5,        bot_run6        ] {bot_ai_run(14);};
  123. void()  bot_run6        =[      $rockrun6,        bot_run1        ] {bot_ai_run(20);};
  124.  
  125. void()  bot_stuff1        =[      $rockrun1,        bot_stuff2        ] {bot_ai_stuff(18);};
  126. void()  bot_stuff2        =[      $rockrun2,        bot_stuff3        ] {bot_ai_stuff(14);};
  127. void()  bot_stuff3        =[      $rockrun3,        bot_stuff4        ] {bot_ai_stuff(7);};
  128. void()  bot_stuff4        =[      $rockrun4,        bot_stuff5        ] {bot_ai_stuff(12);};
  129. void()  bot_stuff5        =[      $rockrun5,        bot_stuff6        ] {bot_ai_stuff(14);};
  130. void()  bot_stuff6        =[      $rockrun6,        bot_walk1         ] {bot_ai_stuff(11);};
  131.  
  132. void()  bot_atk1        =[      $rockatt1,       bot_atk2        ] {ai_face();};
  133. void()  bot_atk2        =[      $rockatt2,       bot_atk3        ] {ai_face();};
  134. void()  bot_atk3        =[      $rockatt3,       bot_atk4        ] {ai_face();};
  135. void()  bot_atk4        =[      $rockatt4,       bot_atk5        ] {bot_attack();};
  136. void()  bot_atk5        =[      $rockatt5,       bot_atk6        ] {ai_face();};
  137. void()  bot_atk6        =[      $rockatt6,       bot_run1        ]
  138. {
  139.     ai_face();
  140.     BotCheckRefire (bot_atk1);
  141. };
  142.  
  143. void()  bot_pain1      =[      $pain1   ,        bot_pain2      ] {};
  144. void()  bot_pain2      =[      $pain2   ,        bot_pain3      ] {};
  145. void()  bot_pain3      =[      $pain4   ,        bot_pain4      ] {ai_painforward(2);};
  146. void()  bot_pain4      =[      $pain3   ,        bot_pain5      ] {};
  147. void()  bot_pain5      =[      $pain4   ,        bot_pain6      ] {ai_pain(1);};
  148. void()  bot_pain6      =[      $pain6   ,        bot_run1       ] {};
  149.  
  150. void()  bot_die1        =[      $deatha1,        bot_die2        ] {};
  151. void()  bot_die2        =[      $deatha2,        bot_die3        ] {};
  152. void()  bot_die3        =[      $deatha3,        bot_die4        ]
  153. {
  154.     self.solid = SOLID_NOT;
  155.     DropBackpack();
  156. };
  157. void()  bot_die4        =[      $deatha4,       bot_die5        ] {ai_forward(14);};
  158. void()  bot_die5        =[      $deatha5,       bot_die6        ] {ai_forward(2);};
  159. void()  bot_die6        =[      $deatha6,       bot_die7        ] {};
  160. void()  bot_die7        =[      $deatha7,       bot_die7        ] {BotSelfDeActivate();};
  161.  
  162. void()  bot_fdie1       =[      $deathd1,       bot_fdie2       ] {};
  163. void()  bot_fdie2       =[      $deathd2,       bot_fdie3       ] {};
  164. void()  bot_fdie3       =[      $deathd3,       bot_fdie4       ] 
  165. {
  166.     self.solid = SOLID_NOT;
  167.     DropBackpack();
  168. };
  169. void()  bot_fdie4       =[      $deathd4,       bot_fdie5       ] {};
  170. void()  bot_fdie5       =[      $deathd5,       bot_fdie6       ] {};
  171. void()  bot_fdie6       =[      $deathd6,       bot_fdie7       ] {};
  172. void()  bot_fdie7       =[      $deathd7,       bot_fdie8       ] {};
  173. void()  bot_fdie8       =[      $deathd8,       bot_fdie9       ] {};
  174. void()  bot_fdie9       =[      $deathd9,       bot_fdie9       ] {BotSelfDeActivate();};
  175.  
  176.  
  177. float() BotFindTarget =
  178. {
  179.         local entity head, selected;
  180.     local float dist;
  181.     dist = 1500;    // awareness radius of bot, increasing it slows down game
  182.     selected = world;
  183.  
  184.     head = findradius(self.origin, 1500);
  185.     while(head)
  186.     {
  187.                 if (((deathmatch) && (!(head.flags & FL_NOTARGET) && ((head.flags & FL_CLIENT) || (head.flags & FL_MONSTER)))) ||
  188.                    ((!deathmatch) && (!(head.flags & FL_NOTARGET) && (head.flags & FL_MONSTER))))
  189.                 if (((teamplay) &&  (head.team != self.team)) || (!teamplay))
  190.                 if ((head.health > 1) && (head != self))
  191.                 if (visible(head))
  192.                 if (trace_plane_dist < dist)
  193.                 if ((head.health > 0) && (head !=self))
  194.                    {
  195.                         selected = head;
  196.                         dist = trace_plane_dist;
  197.                    }
  198.         head = head.chain;
  199.     }
  200.     self.enemy = selected;
  201.         
  202.     if (self.enemy == world)
  203.         return FALSE;
  204.         else
  205.         {
  206.         BotFoundTarget();
  207.         return TRUE;
  208.     }
  209. };
  210.  
  211. // BG Bot - begin hack to check for items
  212. float() BotFindStuff =
  213. {
  214.         local entity head, selected;
  215.     local float dist;
  216.         dist = 200; 
  217.     selected = world;
  218.  
  219.         head = findradius(self.origin, 200);
  220.     while(head)
  221.     {
  222.                 if ((head.classname == "weapon_supernailgun") ||
  223.                    (head.classname == "weapon_supershotgun") || 
  224.                    (head.classname == "weapon_rocketlauncher") || 
  225.                    (head.classname == "weapon_nailgun") ||
  226.                    (head.classname == "backpack") ||
  227.                    ((self.ammo_shells < 100) && (head.classname == "botshells")) ||
  228.                    ((self.ammo_nails < 200) && (head.classname == "botnails")) ||
  229.                    ((self.ammo_rockets < 100) && (head.classname == "botrock")) ||
  230.                    (head.classname == "item_armor1") ||
  231.                    (head.classname == "item_armor2") ||
  232.                    (head.classname == "item_armorInv") ||
  233.                    ((head.healtype == 1) && (self.health < 100)) ||
  234.                    ((head.healtype == 2) && (self.health < 100))) 
  235.                 if (visible(head))
  236.                 if (trace_plane_dist < dist)
  237.                    {
  238.                         selected = head;
  239.                         dist = trace_plane_dist;
  240.                    }
  241.         head = head.chain;
  242.     }
  243.         self.stuff = selected;
  244.         
  245.         if (self.stuff == world)
  246.         return FALSE;
  247.         else
  248.         {
  249.                 BotFoundStuff();
  250.         return TRUE;
  251.     }
  252. };
  253. // BG Bot - end hack to check for items
  254.  
  255. //=============================================================
  256. // bot_ai_stand - bot stands in place until target acquired,
  257. // and starts to walk if pausetime has expired
  258. //=============================================================
  259. void() bot_ai_stand =
  260. {
  261.         if (BotFindTarget ())
  262.                 return;
  263.     
  264.         if (BotFindStuff ())
  265.                 return;
  266.  
  267.         self.th_walk ();
  268. };
  269.  
  270.  
  271. //=============================================================
  272. // bot_pain
  273. //=============================================================
  274. void(entity attacker, float damage)    bot_pain =
  275. {
  276.     local float r;
  277.     local entity oldself;
  278.  
  279.         r = rint((random() * 5) + 1);
  280.     if (self.pain_finished > time)
  281.         return;
  282.  
  283.     
  284.         if (r == 1)
  285.                 sound (self, CHAN_VOICE, "player/pain1.wav", 1, ATTN_NORM);
  286.         else if (r == 2)
  287.                 sound (self, CHAN_VOICE, "player/pain2.wav", 1, ATTN_NORM);
  288.         else if (r == 3)
  289.                 sound (self, CHAN_VOICE, "player/pain3.wav", 1, ATTN_NORM);
  290.         else if (r == 4)
  291.                 sound (self, CHAN_VOICE, "player/pain4.wav", 1, ATTN_NORM);
  292.         else if (r == 5)
  293.                 sound (self, CHAN_VOICE, "player/pain5.wav", 1, ATTN_NORM);
  294.     else
  295.                 sound (self, CHAN_VOICE, "player/pain6.wav", 1, ATTN_NORM);
  296.  
  297.         self.pain_finished = time + 1;
  298.         bot_pain1 ();
  299.  
  300. };
  301.  
  302. //=============================================================
  303. // bot_die
  304. //=============================================================
  305. void() bot_die =
  306. {
  307.         sound (self, CHAN_VOICE, "player/death1.wav", 1, ATTN_NORM);
  308.     if (random() > 0.5)
  309.         bot_die1 ();
  310.     else
  311.         bot_fdie1 ();
  312.  
  313. // death frame sequence includes bot deactivation    
  314. };
  315.  
  316. //=============================================================
  317. // BotHuntTarget
  318. //=============================================================
  319. void() BotHuntTarget =
  320. {
  321.     self.goalentity = self.enemy;
  322.     self.think = self.th_run;
  323.     self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin);
  324.     self.nextthink = time + 0.1;
  325.         SUB_AttackFinished (0.1);       // wait a while before first attack
  326. };
  327.  
  328. //=============================================================
  329. // BotHuntStuff - Look for items
  330. //=============================================================
  331. void() BotHuntStuff =
  332. {
  333.         self.goalentity = self.stuff;
  334.         self.think = self.th_stuff;
  335.         self.ideal_yaw = vectoyaw(self.stuff.origin - self.origin);
  336.     self.nextthink = time + 0.1;
  337. };
  338.  
  339.  
  340. //=============================================================
  341. // BotFoundTarget
  342. //=============================================================
  343. void() BotFoundTarget =
  344. {
  345.     local float f_dist;
  346.     local string s_dist;
  347.     f_dist = vlen (self.enemy.origin - self.origin);
  348.     s_dist = ftos (f_dist);
  349.  
  350.     self.show_hostile = time + 1;        // wake up other monsters
  351.     
  352.     BotHuntTarget ();
  353. };
  354.  
  355. //=============================================================
  356. // BotFoundStuff - Items
  357. //=============================================================
  358. void() BotFoundStuff =
  359. {
  360.         local float f_dist;
  361.         local string s_dist;
  362.         f_dist = vlen (self.stuff.origin - self.origin);
  363.         s_dist = ftos (f_dist);
  364.  
  365.         BotHuntStuff ();
  366. };
  367.  
  368.  
  369. //=============================================================
  370. // bot_ai_walk - bot is walking, looking for enemies
  371. //=============================================================
  372. void(float dist) bot_ai_walk =
  373. {
  374.         if (BotFindTarget ())
  375.                 return;
  376.  
  377.         if (BotFindStuff ())
  378.         return;
  379.         traceline (self.origin, self.origin + '0 20 0', FALSE, self);
  380.         if (trace_plane_dist < 0.02)
  381.         {
  382. //                self.ideal_yaw = self.ideal_yaw - 11.5;
  383.                 self.angles_y = self.angles_y - 11.5;
  384.         }
  385.         movetogoal (dist);
  386. };
  387.  
  388. //=============================================================
  389. // bot_ai_run - still needs a little work
  390. //=============================================================
  391. void(float dist) bot_ai_run =
  392. {
  393.     local    vector    delta;
  394.     local    float    axis;
  395.     local    float    direct, ang_rint, ang_floor, ang_ceil;
  396.     
  397.     movedist = dist;
  398.  
  399.     if (self.enemy.health <= 0)
  400.     {
  401.         self.enemy = world;
  402.         if (self.oldenemy.health > 0)
  403.         {
  404.             self.enemy = self.oldenemy;
  405.             BotHuntTarget ();
  406.         }
  407.         else
  408.         {
  409.             if (BotFindTarget())
  410.                 return;
  411.             else
  412.             {
  413.                 self.th_walk ();
  414.                 return;
  415.             }
  416.         }
  417.     }
  418.  
  419.     enemy_vis = visible(self.enemy);
  420.     if (enemy_vis)
  421.         self.search_time = time + 5;
  422.  
  423.     enemy_infront = infront(self.enemy);
  424.     enemy_range = range(self.enemy);
  425.     enemy_yaw = vectoyaw(self.enemy.origin - self.origin);
  426.     
  427.     if (self.attack_state == AS_MISSILE)
  428.     {
  429.         ai_run_missile ();
  430.         return;
  431.     }
  432.     if (self.attack_state == AS_MELEE)
  433.     {
  434.         ai_run_melee ();
  435.         return;
  436.     }
  437.  
  438.     if (CheckAnyAttack ())
  439.         return;                    // beginning an attack
  440.         
  441.     if (self.attack_state == AS_SLIDING)
  442.     {
  443.         ai_run_slide ();
  444.         return;
  445.     }
  446.         
  447.     movetogoal (dist);        // done in C code...
  448. };
  449.  
  450. //=============================================================
  451. // bot_ai_stuff - crappy hack
  452. //=============================================================
  453. void(float dist) bot_ai_stuff =
  454. {
  455.         local   vector  delta;
  456.         local   float   axis;
  457.         local   float   direct, ang_rint, ang_floor, ang_ceil;
  458.     
  459.     movedist = dist;
  460.  
  461.         enemy_vis = visible(self.stuff);
  462.         if (enemy_vis)
  463.         self.search_time = time + 5;
  464.  
  465.         enemy_infront = infront(self.stuff);
  466.         enemy_range = range(self.stuff);
  467.         enemy_yaw = vectoyaw(self.stuff.origin - self.origin);
  468.         
  469.     movetogoal (dist);        // done in C code...
  470. };
  471.  
  472.  
  473. //=============================================================
  474. // BotCheckRefire
  475. //=============================================================
  476. void (void () thinkst) BotCheckRefire =
  477. {
  478.     if (!visible (self.enemy) || (self.enemy.health <= 0))
  479.         return;
  480.  
  481.     self.think = thinkst;
  482. };
  483.  
  484.  
  485. //=============================================================
  486. // BotSelfDeActivate - Bot deactivates itself
  487. //=============================================================
  488. void () BotSelfDeActivate =
  489. {
  490.  
  491.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  492.     WriteByte (MSG_BROADCAST, TE_TELEPORT);
  493.     WriteCoord (MSG_BROADCAST, self.origin_x);
  494.     WriteCoord (MSG_BROADCAST, self.origin_y);
  495.     WriteCoord (MSG_BROADCAST, self.origin_z);
  496.     remove (self);
  497. };
  498.  
  499. //=============================================================
  500. // BG Bot Weapons Hack - still needs a lot of work
  501. //=============================================================
  502. void() bot_FireShotgun =
  503. {
  504.     local vector dir;
  505.  
  506.     self.currentammo = self.ammo_shells = self.ammo_shells - 1;
  507.     sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM);    
  508.     self.effects = self.effects | EF_MUZZLEFLASH;
  509.         dir = self.enemy.origin - self.origin;
  510.         dir = normalize(dir);
  511.     FireBullets (6, dir, '0.04 0.04 0');
  512. };
  513.  
  514. void() bot_FireSuperShotgun =
  515. {
  516.     local vector dir;
  517.  
  518.     if (self.currentammo == 1)
  519.     {
  520.                 bot_FireShotgun ();
  521.         return;
  522.     }
  523.         
  524.     self.currentammo = self.ammo_shells = self.ammo_shells - 2;
  525.     self.effects = self.effects | EF_MUZZLEFLASH;
  526.     sound (self ,CHAN_WEAPON, "weapons/shotgn2.wav", 1, ATTN_NORM);    
  527.         dir = self.enemy.origin - self.origin;
  528.         dir = normalize(dir);
  529.     FireBullets (14, dir, '0.14 0.08 0');
  530. };
  531.  
  532. void() bot_FireRocket =
  533. {
  534.     local    entity missile, mpuff;
  535.     
  536.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  537.     
  538.     sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
  539.     missile = spawn ();
  540.     missile.owner = self;
  541.     missile.movetype = MOVETYPE_FLYMISSILE;
  542.     missile.solid = SOLID_BBOX;
  543.         makevectors (self.angles);
  544.         missile.velocity = self.enemy.origin - self.origin;
  545.         missile.velocity = normalize(missile.velocity);
  546.     missile.velocity = missile.velocity * 1000;
  547.     missile.angles = vectoangles(missile.velocity);
  548.     missile.touch = T_MissileTouch;
  549.     missile.nextthink = time + 5;
  550.     missile.think = SUB_Remove;
  551.     setmodel (missile, "progs/missile.mdl");
  552.     setsize (missile, '0 0 0', '0 0 0');        
  553.         setorigin (missile, self.origin + '0 0 16');
  554. };
  555.  
  556. void () bot_fire =
  557. {
  558.     local vector org;
  559.         local vector dir;
  560.         local float ox;
  561.         
  562.         ox = 4;
  563.  
  564.     self.effects = self.effects | EF_MUZZLEFLASH;
  565.     makevectors (self.angles);
  566.     sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
  567.     self.currentammo = self.ammo_nails = self.ammo_nails - 1;
  568.         org = self.origin + v_forward * 30 + v_right*ox + '0 0 16';
  569.         dir = self.enemy.origin - self.origin;
  570.         dir = normalize(dir);
  571.         launch_spike(org, dir);
  572. };
  573.  
  574. void () bot_fire2 =
  575. {
  576.     local vector    dir;
  577.         local vector    org;
  578.     
  579.     self.effects = self.effects | EF_MUZZLEFLASH;
  580.     makevectors (self.angles);
  581.     sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
  582.     self.currentammo = self.ammo_nails = self.ammo_nails - 2;
  583.         org = self.origin + '0 0 16';
  584.         dir = self.enemy.origin - self.origin;
  585.         dir = normalize(dir);
  586.         launch_spike (org, dir);
  587.     newmis.touch = superspike_touch;
  588.     setmodel (newmis, "progs/s_spike.mdl");
  589.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);        
  590. };
  591.  
  592. void() bot_SetCurrentAmmo =
  593. {
  594.     self.items = self.items - ( self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS) );
  595.     
  596.         if (self.weapon == IT_SHOTGUN)
  597.     {
  598.         self.currentammo = self.ammo_shells;
  599.         self.items = self.items | IT_SHELLS;
  600.     }
  601.     else if (self.weapon == IT_SUPER_SHOTGUN)
  602.     {
  603.         self.currentammo = self.ammo_shells;
  604.         self.items = self.items | IT_SHELLS;
  605.     }
  606.     else if (self.weapon == IT_NAILGUN)
  607.     {
  608.         self.currentammo = self.ammo_nails;
  609.         self.items = self.items | IT_NAILS;
  610.     }
  611.     else if (self.weapon == IT_SUPER_NAILGUN)
  612.     {
  613.         self.currentammo = self.ammo_nails;
  614.         self.items = self.items | IT_NAILS;
  615.     }
  616.     else if (self.weapon == IT_ROCKET_LAUNCHER)
  617.     {
  618.         self.currentammo = self.ammo_rockets;
  619.         self.items = self.items | IT_ROCKETS;
  620.     }
  621.     else
  622.     {
  623.         self.currentammo = 0;
  624.         self.weaponmodel = "";
  625.         self.weaponframe = 0;
  626.     }
  627. };
  628. /*
  629. ====================================================
  630. bot_bestweapon - AI to choose which weapon is best
  631. ====================================================
  632. */
  633. float () bot_bestweapon =
  634. {
  635.     local    float    it;
  636.     
  637.     it = self.items;
  638.  
  639.         if(self.ammo_rockets >= 1 && (it & IT_ROCKET_LAUNCHER) )
  640.         return IT_ROCKET_LAUNCHER;
  641.     else if(self.ammo_nails >= 2 && (it & IT_SUPER_NAILGUN) )
  642.         return IT_SUPER_NAILGUN;
  643.     else if(self.ammo_shells >= 2 && (it & IT_SUPER_SHOTGUN) )
  644.         return IT_SUPER_SHOTGUN;
  645.     else if(self.ammo_nails >= 1 && (it & IT_NAILGUN) )
  646.         return IT_NAILGUN;
  647.  
  648.         return IT_SHOTGUN;
  649.  
  650. };
  651. /*
  652. ===============================================
  653. bot_CheckNoAmmo - checks to see if he has ammo 
  654. ===============================================
  655. */
  656. float() bot_CheckNoAmmo =
  657. {
  658.     if (self.currentammo > 0)
  659.         return TRUE;
  660.  
  661.         self.weapon = bot_bestweapon ();
  662.  
  663.         bot_SetCurrentAmmo ();
  664.     
  665.     return FALSE;
  666. };
  667. /*
  668. ==========================
  669. bot_attack - fires weapon
  670. ==========================
  671. */
  672. void() bot_attack =
  673. {
  674.     local    float    r;
  675.  
  676.         if (!visible (self.enemy) || (self.enemy.health <= 0))
  677.                 return;
  678.  
  679.         if (!bot_CheckNoAmmo ())
  680.         return;
  681.  
  682.         makevectors     (self.angles);     
  683.     self.show_hostile = time + 1;    // wake monsters up
  684.  
  685.         if (self.weapon == IT_SHOTGUN)
  686.     {
  687.                 bot_FireShotgun ();
  688.     }
  689.     else if (self.weapon == IT_SUPER_SHOTGUN)
  690.     {
  691.                 bot_FireSuperShotgun ();
  692.     }
  693.     else if (self.weapon == IT_NAILGUN)
  694.     {
  695.                 bot_fire ();
  696.                 bot_fire ();
  697.                 bot_fire ();
  698.     }
  699.     else if (self.weapon == IT_SUPER_NAILGUN)
  700.     {
  701.                 bot_fire2 ();
  702.                 bot_fire2 ();
  703.     }
  704.     else if (self.weapon == IT_ROCKET_LAUNCHER)
  705.     {
  706.                 bot_FireRocket();
  707.     }
  708. };
  709.