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

  1. /*
  2. ==============================================================================
  3.                                                         
  4. 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    ()                                              BotSightSound;
  17. void    ()                                              BotFoundTarget;
  18. void    ()                                              BotHuntTarget;
  19. void    ()                                              BotFoundStuff;
  20. void    ()                                              BotHuntStuff;
  21. void    ()                                              bot_ai_turn;
  22. void    (float dist)                                    bot_ai_run;
  23. void    (float dist)                                    bot_ai_stuff;
  24. void    (void () thinkst)                               BotCheckRefire;
  25. void    ()                                              BotSelfDeActivate;
  26. void    ()                                              bot_fire;
  27. void    ()                                              bot_fire2;
  28. void    (vector org, vector dir)                        launch_spike;
  29. void    ()                                              spike_touch; 
  30.  
  31. // Frame macros
  32.  
  33. $cd /raid/quake/id1/models/enforcer
  34. $origin 0 -6 24
  35. $base base        
  36. $skin skin
  37.  
  38. $frame stand1 stand2 stand3 stand4 stand5 stand6 stand7
  39.  
  40. $frame walk1 walk2 walk3 walk4 walk5 walk6 walk7 walk8 walk9 walk10
  41. $frame walk11 walk12 walk13 walk14 walk15 walk16
  42.  
  43. $frame run1 run2 run3 run4 run5 run6 run7 run8
  44.  
  45. $frame attack1 attack2 attack3 attack4 attack5 attack6
  46. $frame attack7 attack8 attack9 attack10
  47.  
  48. $frame death1 death2 death3 death4 death5 death6 death7 death8
  49. $frame death9 death10 death11 death12 death13 death14
  50.  
  51. $frame fdeath1 fdeath2 fdeath3 fdeath4 fdeath5 fdeath6 fdeath7 fdeath8
  52. $frame fdeath9 fdeath10 fdeath11
  53.  
  54. $frame paina1 paina2 paina3 paina4
  55.  
  56. $frame painb1 painb2 painb3 painb4 painb5
  57.  
  58. $frame painc1 painc2 painc3 painc4 painc5 painc6 painc7 painc8
  59.  
  60. $frame paind1 paind2 paind3 paind4 paind5 paind6 paind7 paind8
  61. $frame paind9 paind10 paind11 paind12 paind13 paind14 paind15 paind16
  62. $frame paind17 paind18 paind19
  63.  
  64. void()    bot_stand1    =[    $stand1,    bot_stand2    ] {bot_ai_stand();};
  65. void()    bot_stand2    =[    $stand2,    bot_stand3    ] {bot_ai_stand();};
  66. void()    bot_stand3    =[    $stand3,    bot_stand4    ] {bot_ai_stand();};
  67. void()    bot_stand4    =[    $stand4,    bot_stand5    ] {bot_ai_stand();};
  68. void()    bot_stand5    =[    $stand5,    bot_stand6    ] {bot_ai_stand();};
  69. void()    bot_stand6    =[    $stand6,    bot_stand7    ] {bot_ai_stand();};
  70. void()    bot_stand7    =[    $stand7,    bot_stand1    ] {bot_ai_stand();};
  71.  
  72. void()    bot_walk1    =[    $walk1 ,    bot_walk2    ]
  73. {
  74.     if (random() < 0.2)
  75.         sound (self, CHAN_VOICE, "enforcer/idle1.wav", 1, ATTN_IDLE);
  76.     bot_ai_roam(4);
  77. };
  78. void()    bot_walk2    =[    $walk2 ,    bot_walk3    ] {bot_ai_roam(8);};
  79. void()    bot_walk3    =[    $walk3 ,    bot_walk4    ] {bot_ai_roam(8);};
  80. void()    bot_walk4    =[    $walk4 ,    bot_walk5    ] {bot_ai_roam(6);};
  81. void()      bot_walk5   =[    $walk5 ,    bot_walk6    ] {bot_ai_roam(8);};
  82. void()      bot_walk6   =[    $walk6 ,    bot_walk7    ] {bot_ai_roam(8);};
  83. void()    bot_walk7    =[    $walk7 ,    bot_walk8    ] {bot_ai_roam(4);};
  84. void()    bot_walk8    =[    $walk8 ,    bot_walk9    ] {bot_ai_roam(2);};
  85. void()    bot_walk9    =[    $walk9 ,    bot_walk10    ] {bot_ai_roam(4);};
  86. void()      bot_walk10  =[    $walk10,    bot_walk11    ] {bot_ai_roam(6);};
  87. void()      bot_walk11  =[    $walk11,    bot_walk12    ] {bot_ai_roam(4);};
  88. void()    bot_walk12    =[    $walk12,    bot_walk13    ] {bot_ai_roam(2);};
  89. void()    bot_walk13    =[    $walk13,    bot_walk14    ] {bot_ai_roam(4);};
  90. void()      bot_walk14  =[    $walk14,    bot_walk15    ] {bot_ai_roam(2);};
  91. void()    bot_walk15    =[    $walk15,    bot_walk16    ] {bot_ai_roam(8);};
  92. void()    bot_walk16    =[    $walk16,    bot_walk1    ] {bot_ai_roam(4);};
  93.  
  94. void()    bot_run1    =[    $run1  ,    bot_run2    ]
  95. {
  96.     if (random() < 0.2)
  97.         sound (self, CHAN_VOICE, "enforcer/idle1.wav", 1, ATTN_IDLE);
  98.     bot_ai_run(18);
  99. };
  100. void()    bot_run2    =[    $run2  ,    bot_run3    ] {bot_ai_run(14);};
  101. void()    bot_run3    =[    $run3  ,    bot_run4    ] {bot_ai_run(7);};
  102. void()    bot_run4    =[    $run4  ,    bot_run5    ] {bot_ai_run(12);};
  103. void()    bot_run5    =[    $run5  ,    bot_run6    ] {bot_ai_run(14);};
  104. void()    bot_run6    =[    $run6  ,    bot_run7    ] {bot_ai_run(14);};
  105. void()    bot_run7    =[    $run7  ,    bot_run8    ] {bot_ai_run(7);};
  106. void()    bot_run8    =[    $run8  ,    bot_run1    ] {bot_ai_run(11);};
  107.  
  108. //***********
  109. void()    bot_runa1    =[    $run1  ,    bot_runa2    ]
  110. {
  111.     if (random() < 0.1)
  112.         sound (self, CHAN_VOICE, "enforcer/idle1.wav", 1, ATTN_IDLE);
  113.     bot_ai_roam(18);
  114. };
  115. void()    bot_runa2    =[    $run2  ,    bot_runa3    ] {bot_ai_roam(14);};
  116. void()    bot_runa3    =[    $run3  ,    bot_runa4    ] {bot_ai_roam(7);};
  117. void()    bot_runa4    =[    $run4  ,    bot_runa5    ] {bot_ai_roam(12);};
  118. void()    bot_runa5    =[    $run5  ,    bot_runa6    ] {bot_ai_roam(14);};
  119. void()    bot_runa6    =[    $run6  ,    bot_runa7    ] {bot_ai_roam(14);};
  120. void()    bot_runa7    =[    $run7  ,    bot_runa8    ] {bot_ai_roam(7);};
  121. void()    bot_runa8   =[    $run8  ,    bot_runa1   ] {bot_ai_roam(11);};
  122. //***********
  123.  
  124. void()    bot_stuff1  =[    $run1  ,    bot_stuff2  ]
  125. {
  126.     if (random() < 0.2)
  127.         sound (self, CHAN_VOICE, "enforcer/idle1.wav", 1, ATTN_IDLE);
  128.         bot_ai_stuff(18);
  129. };
  130. void()  bot_stuff2        =[      $run2  ,        bot_stuff3        ] {bot_ai_stuff(14);};
  131. void()  bot_stuff3        =[      $run3  ,        bot_stuff4        ] {bot_ai_stuff(7);};
  132. void()  bot_stuff4        =[      $run4  ,        bot_stuff5        ] {bot_ai_stuff(12);};
  133. void()  bot_stuff5        =[      $run5  ,        bot_stuff6        ] {bot_ai_stuff(14);};
  134. void()  bot_stuff6        =[      $run6  ,        bot_stuff7        ] {bot_ai_stuff(14);};
  135. void()  bot_stuff7        =[      $run7  ,        bot_stuff8        ] {bot_ai_stuff(7);};
  136. void()  bot_stuff8        =[      $run8  ,        bot_runa1         ] {bot_ai_stuff(11);};
  137.  
  138. void()  bot_atk1        =[      $attack1,        bot_atk2    ] {ai_face();};
  139. void()  bot_atk2        =[      $attack2,        bot_atk3    ] {ai_face();};
  140. void()  bot_atk3        =[      $attack3,     bot_atk4    ] {bot_attack();};
  141. void()  bot_atk4        =[      $attack4,        bot_atk5    ] {ai_face();};
  142. void()  bot_atk5        =[      $attack5,        bot_atk6    ] {ai_face();};
  143. void()  bot_atk6        =[      $attack6,       bot_atk7    ] {bot_attack();};
  144. void()  bot_atk7        =[      $attack6,       bot_atk8    ] {ai_face();};
  145. void()  bot_atk8        =[      $attack5,       bot_atk9    ] {ai_face();};
  146. void()  bot_atk9        =[      $attack6,       bot_atk10   ] {ai_face();};
  147. void()  bot_atk10       =[      $attack5,       bot_atk11   ] {bot_attack();};
  148. void()  bot_atk11       =[      $attack6,       bot_atk12   ] {ai_face();};
  149. void()  bot_atk12       =[      $attack5,       bot_atk13   ] {ai_face();};
  150. void()  bot_atk13       =[      $attack6,       bot_atk14   ] {bot_attack();};
  151. void()  bot_atk14       =[      $attack5,       bot_atk15   ] {ai_face();};
  152. void()  bot_atk15       =[      $attack6,       bot_atk16   ] {ai_face();};
  153. void()  bot_atk16       =[      $attack5,       bot_atk17   ] {ai_face();};
  154. void()  bot_atk17       =[      $attack6,       bot_atk18   ] {bot_attack();};
  155. void()  bot_atk18       =[      $attack7,       bot_atk19   ] {ai_face();};
  156. void()  bot_atk19       =[      $attack8,       bot_atk20   ] {ai_face();};
  157. void()  bot_atk20       =[      $attack9,       bot_atk21   ] {ai_face();};
  158. void()  bot_atk21       =[      $attack10,bot_run1    ]
  159. {
  160.     ai_face();
  161.     BotCheckRefire (bot_atk1);
  162. };
  163.  
  164. void()    bot_paina1    =[    $paina1,    bot_paina2    ] {};
  165. void()    bot_paina2    =[    $paina2,    bot_paina3    ] {};
  166. void()    bot_paina3    =[    $paina3,    bot_paina4    ] {};
  167. void()    bot_paina4    =[    $paina4,    bot_run1    ] {};
  168.  
  169. void()    bot_painb1    =[    $painb1,    bot_painb2    ] {};
  170. void()    bot_painb2    =[    $painb2,    bot_painb3    ] {};
  171. void()    bot_painb3    =[    $painb3,    bot_painb4    ] {};
  172. void()    bot_painb4    =[    $painb4,    bot_painb5    ] {};
  173. void()    bot_painb5    =[    $painb5,    bot_run1    ] {};
  174.  
  175. void()    bot_painc1    =[    $painc1,    bot_painc2    ] {};
  176. void()    bot_painc2    =[    $painc2,    bot_painc3    ] {};
  177. void()    bot_painc3    =[    $painc3,    bot_painc4    ] {};
  178. void()    bot_painc4    =[    $painc4,    bot_painc5    ] {};
  179. void()    bot_painc5    =[    $painc5,    bot_painc6    ] {};
  180. void()    bot_painc6    =[    $painc6,    bot_painc7    ] {};
  181. void()    bot_painc7    =[    $painc7,    bot_painc8    ] {};
  182. void()    bot_painc8    =[    $painc8,    bot_run1    ] {};
  183.  
  184. void()    bot_paind1    =[    $paind1,    bot_paind2    ] {};
  185. void()    bot_paind2    =[    $paind2,    bot_paind3    ] {};
  186. void()    bot_paind3    =[    $paind3,    bot_paind4    ] {};
  187. void()    bot_paind4    =[    $paind4,    bot_paind5    ] {ai_painforward(2);};
  188. void()    bot_paind5    =[    $paind5,    bot_paind6    ] {ai_painforward(1);};
  189. void()    bot_paind6    =[    $paind6,    bot_paind7    ] {};
  190. void()    bot_paind7    =[    $paind7,    bot_paind8    ] {};
  191. void()    bot_paind8    =[    $paind8,    bot_paind9    ] {};
  192. void()    bot_paind9    =[    $paind9,    bot_paind10    ] {};
  193. void()    bot_paind10    =[    $paind10,    bot_paind11    ] {};
  194. void()    bot_paind11    =[    $paind11,    bot_paind12    ] {ai_painforward(1);};
  195. void()    bot_paind12    =[    $paind12,    bot_paind13    ] {ai_painforward(1);};
  196. void()    bot_paind13    =[    $paind13,    bot_paind14    ] {ai_painforward(1);};
  197. void()    bot_paind14    =[    $paind14,    bot_paind15    ] {};
  198. void()    bot_paind15    =[    $paind15,    bot_paind16    ] {};
  199. void()    bot_paind16    =[    $paind16,    bot_paind17    ] {ai_pain(1);};
  200. void()    bot_paind17    =[    $paind17,    bot_paind18    ] {ai_pain(1);};
  201. void()    bot_paind18    =[    $paind18,    bot_paind19    ] {};
  202. void()    bot_paind19    =[    $paind19,    bot_run1    ] {};
  203.  
  204. void()    bot_die1    =[    $death1,    bot_die2    ] {};
  205. void()    bot_die2    =[    $death2,    bot_die3    ] {};
  206. void()    bot_die3    =[    $death3,    bot_die4    ]
  207. {
  208.     self.solid = SOLID_NOT;
  209.     self.ammo_cells = 5;
  210.     DropBackpack();
  211. };
  212. void()    bot_die4    =[    $death4,    bot_die5    ] {ai_forward(14);};
  213. void()    bot_die5    =[    $death5,    bot_die6    ] {ai_forward(2);};
  214. void()    bot_die6    =[    $death6,    bot_die7    ] {};
  215. void()    bot_die7    =[    $death7,    bot_die8    ] {};
  216. void()    bot_die8    =[    $death8,    bot_die9    ] {};
  217. void()    bot_die9    =[    $death9,    bot_die10    ] {ai_forward(3);};
  218. void()    bot_die10    =[    $death10,    bot_die11    ] {ai_forward(5);};
  219. void()    bot_die11    =[    $death11,    bot_die12    ] {ai_forward(5);};
  220. void()    bot_die12    =[    $death12,    bot_die13    ] {ai_forward(5);};
  221. void()    bot_die13    =[    $death13,    bot_die14    ] {};
  222. void()    bot_die14    =[    $death14,    bot_die14    ] {BotSelfDeActivate();};
  223.  
  224. void()    bot_fdie1    =[    $fdeath1,    bot_fdie2    ] {};
  225. void()    bot_fdie2    =[    $fdeath2,    bot_fdie3    ] {};
  226. void()    bot_fdie3    =[    $fdeath3,    bot_fdie4    ] 
  227. {
  228.     self.solid = SOLID_NOT;
  229.     self.ammo_cells = 5;
  230.     DropBackpack();
  231. };
  232. void()    bot_fdie4    =[    $fdeath4,    bot_fdie5    ] {};
  233. void()    bot_fdie5    =[    $fdeath5,    bot_fdie6    ] {};
  234. void()    bot_fdie6    =[    $fdeath6,    bot_fdie7    ] {};
  235. void()    bot_fdie7    =[    $fdeath7,    bot_fdie8    ] {};
  236. void()    bot_fdie8    =[    $fdeath8,    bot_fdie9    ] {};
  237. void()    bot_fdie9    =[    $fdeath9,    bot_fdie10    ] {};
  238. void()    bot_fdie10    =[    $fdeath10,    bot_fdie11    ] {};
  239. void()    bot_fdie11    =[    $fdeath11,    bot_fdie11    ] {BotSelfDeActivate();};
  240.  
  241. //===============================================================================
  242.  
  243. float() BotFindTarget =
  244. {
  245.       local entity head, selected;
  246.     local float dist;
  247.     dist = 1200;    // awareness radius of bot, increasing it slows down game
  248.     selected = world;
  249.  
  250.     head = findradius(self.origin, dist);
  251.     head = findradius(self.origin, 1500);
  252.     while(head)
  253.     {
  254.                 if(!(head.flags & FL_NOTARGET) && ((head.flags & FL_CLIENT) || (head.flags & FL_MONSTER) || (head.classname == "bot")))
  255.                 if (((teamplay) &&  (head.team != self.owner.team)) || (!teamplay))
  256.                 if ((head.health > 1) && (head != self))
  257.                 if (visible(head))
  258.                 if (trace_plane_dist < dist)
  259.                 if ((head.health > 0) && (head !=self))
  260.                    {
  261.                         selected = head;
  262.                         dist = trace_plane_dist;
  263.                    }
  264.         head = head.chain;
  265.     }
  266.     self.enemy = selected;
  267.         
  268.     if (self.enemy == world)
  269.         return FALSE;
  270.       else
  271.       {
  272.         BotFoundTarget();
  273.         return TRUE;
  274.     }
  275. };
  276.  
  277. float() BotFindStuff =
  278. {
  279.       local entity head, selected;
  280.     local float dist,stuff_vis;
  281.       dist = 300; 
  282.     selected = world;
  283.  
  284.       head = findradius(self.origin, 200);
  285.     while(head)
  286.     {
  287.             if ((head.classname == "weapon_supernailgun") ||
  288.             (head.classname == "weapon_supershotgun") || 
  289.             (head.classname == "weapon_rocketlauncher") || 
  290.             (head.classname == "weapon_nailgun") ||
  291.             (head.classname == "backpack") ||
  292.             (head.classname == "botammo") ||
  293.             (head.classname == "item_armor1") ||
  294.             (head.classname == "item_armor2") ||
  295.             (head.classname == "item_armorInv") ||
  296.             ((head.healtype == 1) && (self.health < 100)) ||
  297.             ((head.healtype == 2) && (self.health < 100))) 
  298.             {
  299.                   selected = head;
  300.                 dist = trace_plane_dist;
  301.             }
  302.         head = head.chain;
  303.     }
  304.       self.stuff = selected;
  305.  
  306. //***********
  307.     stuff_vis = visible(self.stuff);
  308.       if ((self.stuff == world) || !(stuff_vis))
  309.     {
  310. //        if (!(stuff_vis)) bprint("Item not visible...\n");
  311. //***********
  312.         return FALSE;
  313.     }
  314.       else
  315.       {
  316.             BotFoundStuff();
  317.         return TRUE;
  318.     }
  319. };
  320.  
  321. //=============================================================
  322. // bot_ai_stand - bot stands in place until target acquired,
  323. // and starts to walk if pausetime has expired
  324. //=============================================================
  325. void() bot_ai_stand =
  326. {
  327.       if (BotFindTarget ())
  328.         return;
  329.     
  330.       if (BotFindStuff ())
  331.         return;
  332.  
  333.     if (time > self.pausetime)
  334.     {
  335.         self.th_walk ();
  336.         return;
  337.     }
  338. };
  339.  
  340.  
  341. //=============================================================
  342. // bot_pain
  343. //=============================================================
  344. void(entity attacker, float damage)    bot_pain =
  345. {
  346.     local float r;
  347.     local entity oldself;
  348.  
  349.     r = random ();
  350.     if (self.pain_finished > time)
  351.         return;
  352.     
  353.     if (r < 0.5)
  354.         sound (self, CHAN_VOICE, "enforcer/pain1.wav", 1, ATTN_NORM);
  355.     else
  356.         sound (self, CHAN_VOICE, "enforcer/pain2.wav", 1, ATTN_NORM);
  357.  
  358.     if (r < 0.2)
  359.     {
  360.         self.pain_finished = time + 0.5;
  361.         bot_paina1 ();
  362.     }
  363.     else if (r < 0.4)
  364.     {
  365.         self.pain_finished = time + 0.5;
  366.         bot_painb1 ();
  367.     }
  368.     else if (r < 0.7)
  369.     {
  370.         self.pain_finished = time + 0.5;
  371.         bot_painc1 ();
  372.     }
  373.     else
  374.     {
  375.         self.pain_finished = time + 1;
  376.         bot_paind1 ();
  377.     }
  378.  
  379. };
  380.  
  381. //=============================================================
  382. // bot_die
  383. //=============================================================
  384. void() bot_die =
  385. {
  386.     sound (self, CHAN_VOICE, "enforcer/death1.wav", 1, ATTN_NORM);
  387.  
  388. //***********
  389.     self.fl_lead = FALSE;
  390. //***********
  391.  
  392.     if (random() > 0.5)
  393.         bot_die1 ();
  394.     else
  395.         bot_fdie1 ();
  396.  
  397. // death frame sequence includes bot deactivation    
  398. };
  399.  
  400.  
  401. //=============================================================
  402. // BotSightSound
  403. //=============================================================
  404. void() BotSightSound =
  405. {
  406.     local float    rsnd;
  407.  
  408.     rsnd = rint(random() * 3);            
  409.     if (rsnd == 1)
  410.         sound (self, CHAN_VOICE, "enforcer/sight1.wav", 1, ATTN_NORM);
  411.     else if (rsnd == 2)
  412.         sound (self, CHAN_VOICE, "enforcer/sight2.wav", 1, ATTN_NORM);
  413.     else if (rsnd == 0)
  414.         sound (self, CHAN_VOICE, "enforcer/sight3.wav", 1, ATTN_NORM);
  415.     else
  416.         sound (self, CHAN_VOICE, "enforcer/sight4.wav", 1, ATTN_NORM);
  417. };
  418.  
  419.  
  420. //=============================================================
  421. // BotHuntTarget
  422. //=============================================================
  423. void() BotHuntTarget =
  424. {
  425.     self.goalentity = self.enemy;
  426.     self.think = self.th_run;
  427.     self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin);
  428.     self.nextthink = time + 0.1;
  429.       SUB_AttackFinished (0.1);       // wait a while before first attack
  430. };
  431.  
  432. //=============================================================
  433. // BotHuntStuff
  434. //=============================================================
  435. void() BotHuntStuff =
  436. {
  437.       self.goalentity = self.stuff;
  438.       self.think = self.th_stuff;
  439.       self.ideal_yaw = vectoyaw(self.stuff.origin - self.origin);
  440.     self.nextthink = time + 0.1;
  441. };
  442.  
  443. //=============================================================
  444. // BotFoundTarget
  445. //=============================================================
  446. void() BotFoundTarget =
  447. {
  448.     local float f_dist;
  449.     local string s_dist;
  450.     f_dist = vlen (self.enemy.origin - self.origin);
  451.     s_dist = ftos (f_dist);
  452.  
  453.     self.show_hostile = time + 1;        // wake up other monsters
  454.     
  455.     BotSightSound ();
  456.     BotHuntTarget ();
  457. };
  458.  
  459. //=============================================================
  460. // BotFoundStuff - Items
  461. //=============================================================
  462. void() BotFoundStuff =
  463. {
  464.     local float f_dist;
  465.     local string s_dist;
  466.     f_dist = vlen (self.stuff.origin - self.origin);
  467.     s_dist = ftos (f_dist);
  468.  
  469.     BotHuntStuff ();
  470. };
  471.  
  472. //=============================================================
  473. // bot_ai_turn - turn towards ideal_yaw if no enemy sighted
  474. //=============================================================
  475. void() bot_ai_turn =
  476. {
  477.     if (BotFindTarget ())
  478.         return;
  479.  
  480.     if (BotFindStuff ())
  481.         return;
  482.  
  483.     ChangeYaw ();
  484. };
  485.  
  486.  
  487. //=============================================================
  488. // bot_ai_run - still needs a little work
  489. //=============================================================
  490. void(float dist) bot_ai_run =
  491. {
  492.     local    vector    delta;
  493.     local    float        axis;
  494.     local    float        direct, ang_rint, ang_floor, ang_ceil;
  495.     
  496.     movedist = dist;
  497.  
  498. //***********
  499.     enemy_vis = visible(self.enemy);
  500.     if (enemy_vis)
  501.         self.search_time = time + 5;
  502.  
  503.     if ((self.enemy.health) <= 0 || (self.search_time < time))
  504. //***********
  505.     {
  506.         self.enemy = world;
  507.         if (self.oldenemy.health > 0)
  508.         {
  509.             self.enemy = self.oldenemy;
  510.             BotHuntTarget();
  511.         }
  512.         else
  513.         {
  514.             if (BotFindTarget())
  515.                 return;
  516.             else
  517.             {
  518.                 self.th_walk ();
  519.                 return;
  520.             }
  521.         }
  522.     }
  523.  
  524.     self.show_hostile = time + 1;        // wake up other monsters
  525.  
  526.     enemy_infront = infront(self.enemy);
  527.     enemy_range = range(self.enemy);
  528.     enemy_yaw = vectoyaw(self.enemy.origin - self.origin);
  529.     
  530.     if (self.attack_state == AS_MISSILE)
  531.     {
  532.         ai_run_missile ();
  533.         return;
  534.     }
  535.     if (self.attack_state == AS_MELEE)
  536.     {
  537.         ai_run_melee ();
  538.         return;
  539.     }
  540.  
  541.     if (CheckAnyAttack ())
  542.         return;                    // beginning an attack
  543.         
  544.     if (self.attack_state == AS_SLIDING)
  545.     {
  546.         ai_run_slide ();
  547.         return;
  548.     }
  549.         
  550.     movetogoal (dist);
  551. };
  552.  
  553. //=============================================================
  554. // bot_ai_stuff
  555. //=============================================================
  556. void(float dist) bot_ai_stuff =
  557. {
  558.     local    vector    delta;
  559.     local    float        axis;
  560.     local    float        direct, ang_rint, ang_floor, ang_ceil;
  561.     
  562.     movedist = dist;
  563.  
  564.       enemy_vis = visible(self.stuff);
  565.     if (enemy_vis)
  566.         self.search_time = time + 3;
  567.  
  568.       enemy_infront = infront(self.stuff);
  569.       enemy_range = range(self.stuff);
  570.       enemy_yaw = vectoyaw(self.stuff.origin - self.origin);
  571.  
  572.     movetogoal (dist);
  573. };
  574.  
  575.  
  576. //=============================================================
  577. // BotCheckRefire
  578. //=============================================================
  579. void (void () thinkst) BotCheckRefire =
  580. {
  581.     if (!visible (self.enemy) || (self.enemy.health <= 0))
  582.         return;
  583.     self.think = thinkst;
  584. };
  585.  
  586. //=============================================================
  587. // BotSelfDeActivate - Bot deactivates itself
  588. //=============================================================
  589. void () BotSelfDeActivate =
  590. {
  591.     WriteByte (MSG_BROADCAST, SVC_TEMPENTITY);
  592.     WriteByte (MSG_BROADCAST, TE_TELEPORT);
  593.     WriteCoord (MSG_BROADCAST, self.origin_x);
  594.     WriteCoord (MSG_BROADCAST, self.origin_y);
  595.     WriteCoord (MSG_BROADCAST, self.origin_z);
  596.     remove (self);
  597. };
  598.  
  599. //=============================================================
  600. // Bot Weapons
  601. //=============================================================
  602. void() bot_FireShotgun =
  603. {
  604.     local vector dir;
  605.  
  606.     sound (self, CHAN_WEAPON, "weapons/guncock.wav", 1, ATTN_NORM);    
  607.  
  608.     self.currentammo = self.ammo_shells = self.ammo_shells - 1;
  609.       dir = self.enemy.origin - self.origin;
  610.       dir = normalize(dir);
  611.     FireBullets (6, dir, '0.04 0.04 0');
  612.     eject_shell (self.origin + '0 0 16' + v_forward*3,dir); //eject shell
  613. };
  614.  
  615. void() bot_FireSuperShotgun =
  616. {
  617.     local vector dir;
  618.  
  619.     if (self.currentammo == 1)
  620.     {
  621.             bot_FireShotgun ();
  622.         return;
  623.     }
  624.         
  625.     sound (self, CHAN_AUTO, "weapons/shotgn2.wav", 1, ATTN_NORM);    
  626.  
  627.     self.currentammo = self.ammo_shells = self.ammo_shells - 2;
  628.       dir = self.enemy.origin - self.origin;
  629.       dir = normalize(dir);
  630.     FireBullets (14, dir, '0.14 0.08 0');
  631.     eject_shell (self.origin + '0 0 16' + v_forward*3,dir); //eject shell
  632.     eject_shell (self.origin + '0 0 16' + v_forward*3,dir); //eject shell
  633. };
  634.  
  635. void() bot_FireRocket =
  636. {
  637.     local    entity missile, mpuff;
  638.     
  639.     self.currentammo = self.ammo_rockets = self.ammo_rockets - 1;
  640.     
  641.     sound (self, CHAN_WEAPON, "weapons/sgun1.wav", 1, ATTN_NORM);
  642.     
  643.     missile = spawn ();
  644.     missile.owner = self;
  645.     missile.movetype = MOVETYPE_FLYMISSILE;
  646.     missile.solid = SOLID_BBOX;
  647.       makevectors (self.angles);
  648.       missile.velocity = self.enemy.origin - self.origin;
  649.       missile.velocity = normalize(missile.velocity);
  650.     missile.velocity = missile.velocity * 1000;
  651.     missile.angles = vectoangles(missile.velocity);
  652.     missile.touch = T_MissileTouch;
  653.     missile.nextthink = time + 5;
  654.     missile.think = SUB_Remove;
  655.     setmodel (missile, "progs/missile.mdl");
  656.     setsize (missile, '0 0 0', '0 0 0');        
  657.       setorigin (missile, self.origin + '0 0 16');
  658. };
  659.  
  660. void () bot_fire =
  661. {
  662.     local vector org;
  663.       local vector dir;
  664.       local float ox;
  665.         
  666.       ox = 4;
  667.  
  668.     self.effects = self.effects | EF_MUZZLEFLASH;
  669.     makevectors (self.angles);
  670.     sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
  671.     self.currentammo = self.ammo_nails = self.ammo_nails - 1;
  672.       org = self.origin + v_forward * 30 + v_right*ox + '0 0 16';
  673.       dir = self.enemy.origin - self.origin;
  674.       dir = normalize(dir);
  675.       launch_spike(org, dir);
  676. };
  677.  
  678. void () bot_fire2 =
  679. {
  680.     local vector    dir;
  681.        local vector    org;
  682.     
  683.     self.effects = self.effects | EF_MUZZLEFLASH;
  684.     makevectors (self.angles);
  685.     sound (self, CHAN_WEAPON, "weapons/spike2.wav", 1, ATTN_NORM);
  686.     self.currentammo = self.ammo_nails = self.ammo_nails - 2;
  687.       org = self.origin + '0 0 16';
  688.       dir = self.enemy.origin - self.origin;
  689.       dir = normalize(dir);
  690.       launch_spike (org, dir);
  691.     newmis.touch = superspike_touch;
  692.     setmodel (newmis, "progs/s_spike.mdl");
  693.     setsize (newmis, VEC_ORIGIN, VEC_ORIGIN);        
  694. };
  695.  
  696. /* OLD TM BOT CODE
  697. void(vector offset) benforcer_fire =
  698. {
  699.     local vector org;
  700.       local vector dir;
  701.       local float ox;
  702.         
  703.       ox = 4;
  704.  
  705.     self.effects = self.effects | EF_MUZZLEFLASH;
  706.     makevectors (self.angles);
  707.     sound (self, CHAN_WEAPON, "weapons/rocket1i.wav", 1, ATTN_NORM);
  708.     
  709.       org = self.origin + v_forward * 30 + v_right*ox + '0 0 16';
  710.       dir = self.enemy.origin - self.origin;
  711.       dir = normalize(dir);
  712.       launch_spike(org, dir);
  713.       org = org + offset;
  714.       launch_spike(org, dir);
  715. }; */
  716. /*
  717. ====================================================
  718. bot_SetCurrentAmmo
  719. ====================================================
  720. */
  721. void() bot_SetCurrentAmmo =
  722. {
  723.     self.items = self.items - ( self.items & (IT_SHELLS | IT_NAILS | IT_ROCKETS | IT_CELLS) );
  724.     
  725.       if (self.weapon == IT_SHOTGUN)
  726.     {
  727.         self.currentammo = self.ammo_shells;
  728.         self.items = self.items | IT_SHELLS;
  729.     }
  730.     else if (self.weapon == IT_SUPER_SHOTGUN)
  731.     {
  732.         self.currentammo = self.ammo_shells;
  733.         self.items = self.items | IT_SHELLS;
  734.     }
  735.     else if (self.weapon == IT_NAILGUN)
  736.     {
  737.         self.currentammo = self.ammo_nails;
  738.         self.items = self.items | IT_NAILS;
  739.     }
  740.     else if (self.weapon == IT_SUPER_NAILGUN)
  741.     {
  742.         self.currentammo = self.ammo_nails;
  743.         self.items = self.items | IT_NAILS;
  744.     }
  745.     else if (self.weapon == IT_ROCKET_LAUNCHER)
  746.     {
  747.         self.currentammo = self.ammo_rockets;
  748.         self.items = self.items | IT_ROCKETS;
  749.     }
  750.     else
  751.     {
  752.         self.currentammo = 0;
  753.         self.weaponmodel = "";
  754.         self.weaponframe = 0;
  755.     }
  756. };
  757. /*
  758. ====================================================
  759. bot_bestweapon - AI to choose which weapon is best
  760. ====================================================
  761. */
  762. float () bot_bestweapon =
  763. {
  764.     local    float    it;
  765.     
  766.     it = self.items;
  767.  
  768.       if(self.ammo_rockets >= 1 && (it & IT_ROCKET_LAUNCHER) )
  769.         return IT_ROCKET_LAUNCHER;
  770.     else if(self.ammo_nails >= 2 && (it & IT_SUPER_NAILGUN) )
  771.         return IT_SUPER_NAILGUN;
  772.     else if(self.ammo_shells >= 2 && (it & IT_SUPER_SHOTGUN) )
  773.         return IT_SUPER_SHOTGUN;
  774.     else if(self.ammo_nails >= 1 && (it & IT_NAILGUN) )
  775.         return IT_NAILGUN;
  776.  
  777.       return IT_SHOTGUN;
  778.  
  779. };
  780. /*
  781. ===============================================
  782. bot_CheckNoAmmo - checks to see if he has ammo 
  783. ===============================================
  784. */
  785. float() bot_CheckNoAmmo =
  786. {
  787.     if (self.currentammo > 0)
  788.         return TRUE;
  789.  
  790.       self.weapon = bot_bestweapon ();
  791.  
  792.       bot_SetCurrentAmmo ();
  793.     
  794.     return FALSE;
  795. };
  796. /*
  797. ==========================
  798. bot_attack - fires weapon
  799. ==========================
  800. */
  801. void() bot_attack =
  802. {
  803.     local    float    r;
  804.  
  805.       if (!visible (self.enemy) || (self.enemy.health <= 0))
  806.         return;
  807.  
  808.       if (!bot_CheckNoAmmo ())
  809.         return;
  810.  
  811.       makevectors (self.angles);     
  812.     self.show_hostile = time + 1;    // wake monsters up
  813.  
  814.       if (self.weapon == IT_SHOTGUN)
  815.     {
  816.                 bot_FireShotgun ();
  817.     }
  818.     else if (self.weapon == IT_SUPER_SHOTGUN)
  819.     {
  820.                 bot_FireSuperShotgun ();
  821.     }
  822.     else if (self.weapon == IT_NAILGUN)
  823.     {
  824.                 bot_fire ();
  825.     }
  826.     else if (self.weapon == IT_SUPER_NAILGUN)
  827.     {
  828.                 bot_fire2 ();
  829.     }
  830.     else if (self.weapon == IT_ROCKET_LAUNCHER)
  831.     {
  832.                 bot_FireRocket();
  833.     }
  834. };
  835.