home *** CD-ROM | disk | FTP | other *** search
/ Quake 'em / QUAKEEM.BIN / quake / graphics / torgo / fight.qc < prev    next >
Encoding:
Text File  |  1996-08-05  |  7.5 KB  |  411 lines

  1.  
  2. /*
  3.  
  4. A monster is in fight mode if it thinks it can effectively attack its
  5. enemy.
  6.  
  7. When it decides it can't attack, it goes into hunt mode.
  8.  
  9. */
  10.  
  11. float(float v) anglemod;
  12.  
  13. void() knight_atk1;
  14. void() knight_runatk1;
  15. void() ogre_smash1;
  16. void() ogre_swing1;
  17.  
  18. void() sham_smash1;
  19. void() sham_swingr1;
  20. void() sham_swingl1;
  21.  
  22. float()    DemonCheckAttack;
  23. void(float side)    Demon_Melee;
  24.  
  25. void(vector dest) ChooseTurn;
  26.  
  27. void() ai_face;
  28.  
  29.  
  30. float    enemy_vis, enemy_infront, enemy_range;
  31. float    enemy_yaw;
  32.  
  33.  
  34. void() knight_attack =
  35. {
  36.     local float        len;
  37.     
  38. // decide if now is a good swing time
  39.     len = vlen(self.enemy.origin+self.enemy.view_ofs - (self.origin+self.view_ofs));
  40.     
  41.     if (len<80)
  42.         knight_atk1 ();
  43.     else
  44.         knight_runatk1 ();
  45. };
  46.  
  47.  
  48. //=============================================================================
  49.  
  50. /*
  51. ===========
  52. CheckAttack
  53.  
  54. The player is in view, so decide to move or launch an attack
  55. Returns FALSE if movement should continue
  56. ============
  57. */
  58. float() CheckAttack =
  59. {
  60.     local vector    spot1, spot2;    
  61.     local entity    targ;
  62.     local float        chance;
  63.  
  64.     targ = self.enemy;
  65.     
  66. // see if any entities are in the way of the shot
  67.     spot1 = self.origin + self.view_ofs;
  68.     spot2 = targ.origin + targ.view_ofs;
  69.  
  70.     traceline (spot1, spot2, FALSE, self);
  71.  
  72.     if (trace_ent != targ)
  73.         return FALSE;        // don't have a clear shot
  74.             
  75.     if (trace_inopen && trace_inwater)
  76.         return FALSE;            // sight line crossed contents
  77.  
  78.     if (enemy_range == RANGE_MELEE)
  79.     {    // melee attack
  80.         if (self.th_melee)
  81.         {
  82.             if (self.classname == "monster_knight")
  83.                 knight_attack ();
  84.                         else
  85.                 self.th_melee ();
  86.             return TRUE;
  87.         }
  88.     }
  89.     
  90. // missile attack
  91.     if (!self.th_missile)
  92.         return FALSE;
  93.         
  94.     if (time < self.attack_finished)
  95.         return FALSE;
  96.         
  97.     if (enemy_range == RANGE_FAR)
  98.         return FALSE;
  99.         
  100.     if (enemy_range == RANGE_MELEE)
  101.     {
  102.         chance = 0.9;
  103.         self.attack_finished = 0;
  104.     }
  105.     else if (enemy_range == RANGE_NEAR)
  106.     {
  107.         if (self.th_melee)
  108.             chance = 0.2;
  109.         else
  110.             chance = 0.4;
  111.     }
  112.     else if (enemy_range == RANGE_MID)
  113.     {
  114.         if (self.th_melee)
  115.             chance = 0.05;
  116.         else
  117.             chance = 0.1;
  118.     }
  119.     else
  120.         chance = 0;
  121.  
  122.     if (random () < chance)
  123.     {
  124.         self.th_missile ();
  125.         SUB_AttackFinished (2*random());
  126.         return TRUE;
  127.     }
  128.  
  129.     return FALSE;
  130. };
  131.  
  132.  
  133. /*
  134. =============
  135. ai_face
  136.  
  137. Stay facing the enemy
  138. =============
  139. */
  140. void() ai_face =
  141. {
  142.     self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin);
  143.     ChangeYaw ();
  144. };
  145.  
  146. /*
  147. =============
  148. ai_charge
  149.  
  150. The monster is in a melee attack, so get as close as possible to .enemy
  151. =============
  152. */
  153. float (entity targ) visible;
  154. float(entity targ) infront;
  155. float(entity targ) range;
  156.  
  157. void(float d) ai_charge =
  158. {
  159.     ai_face ();    
  160.     movetogoal (d);        // done in C code...
  161. };
  162.  
  163. void() ai_charge_side =
  164. {
  165.     local    vector    dtemp;
  166.     local    float    heading;
  167.     
  168. // aim to the left of the enemy for a flyby
  169.  
  170.     self.ideal_yaw = vectoyaw(self.enemy.origin - self.origin);
  171.     ChangeYaw ();
  172.  
  173.     makevectors (self.angles);
  174.     dtemp = self.enemy.origin - 30*v_right;
  175.     heading = vectoyaw(dtemp - self.origin);
  176.     
  177.     walkmove(heading, 20);
  178. };
  179.  
  180.  
  181. /*
  182. =============
  183. ai_melee
  184.  
  185. =============
  186. */
  187. void() ai_melee =
  188. {
  189.     local vector    delta;
  190.     local float     ldmg;
  191.  
  192.     if (!self.enemy)
  193.         return;        // removed before stroke
  194.         
  195.     delta = self.enemy.origin - self.origin;
  196.  
  197.     if (vlen(delta) > 60)
  198.         return;
  199.         
  200.     ldmg = (random() + random() + random()) * 3;
  201.     T_Damage (self.enemy, self, self, ldmg);
  202. };
  203.  
  204.  
  205. void() ai_melee_side =
  206. {
  207.     local vector    delta;
  208.     local float     ldmg;
  209.  
  210.     if (!self.enemy)
  211.         return;        // removed before stroke
  212.         
  213.     ai_charge_side();
  214.     
  215.     delta = self.enemy.origin - self.origin;
  216.  
  217.     if (vlen(delta) > 60)
  218.         return;
  219.     if (!CanDamage (self.enemy, self))
  220.         return;
  221.     ldmg = (random() + random() + random()) * 3;
  222.     T_Damage (self.enemy, self, self, ldmg);
  223. };
  224.  
  225.  
  226. //=============================================================================
  227.  
  228. /*
  229. ===========
  230. SoldierCheckAttack
  231.  
  232. The player is in view, so decide to move or launch an attack
  233. Returns FALSE if movement should continue
  234. ============
  235. */
  236. float() SoldierCheckAttack =
  237. {
  238.     local vector    spot1, spot2;    
  239.     local entity    targ;
  240.     local float        chance;
  241.  
  242.     targ = self.enemy;
  243.     
  244. // see if any entities are in the way of the shot
  245.     spot1 = self.origin + self.view_ofs;
  246.     spot2 = targ.origin + targ.view_ofs;
  247.  
  248.     traceline (spot1, spot2, FALSE, self);
  249.  
  250.     if (trace_inopen && trace_inwater)
  251.         return FALSE;            // sight line crossed contents
  252.  
  253.     if (trace_ent != targ)
  254.         return FALSE;    // don't have a clear shot
  255.             
  256.     
  257. // missile attack
  258.     if (time < self.attack_finished)
  259.         return FALSE;
  260.         
  261.     if (enemy_range == RANGE_FAR)
  262.         return FALSE;
  263.         
  264.     if (enemy_range == RANGE_MELEE)
  265.         chance = 0.9;
  266.     else if (enemy_range == RANGE_NEAR)
  267.         chance = 0.4;
  268.     else if (enemy_range == RANGE_MID)
  269.         chance = 0.05;
  270.     else
  271.         chance = 0;
  272.  
  273.     if (random () < chance)
  274.     {
  275.         self.th_missile ();
  276.         SUB_AttackFinished (1 + random());
  277.         if (random() < 0.3)
  278.             self.lefty = !self.lefty;
  279.  
  280.         return TRUE;
  281.     }
  282.  
  283.     return FALSE;
  284. };
  285. //=============================================================================
  286.  
  287. /*
  288. ===========
  289. ShamCheckAttack
  290.  
  291. The player is in view, so decide to move or launch an attack
  292. Returns FALSE if movement should continue
  293. ============
  294. */
  295. float() ShamCheckAttack =
  296. {
  297.     local vector    spot1, spot2;    
  298.     local entity    targ;
  299.     local float        chance;
  300.     local float        enemy_yaw;
  301.  
  302.     if (enemy_range == RANGE_MELEE)
  303.     {
  304.         if (CanDamage (self.enemy, self))
  305.         {
  306.             self.attack_state = AS_MELEE;
  307.             return TRUE;
  308.         }
  309.     }
  310.  
  311.     if (time < self.attack_finished)
  312.         return FALSE;
  313.     
  314.     if (!enemy_vis)
  315.         return FALSE;
  316.         
  317.     targ = self.enemy;
  318.     
  319. // see if any entities are in the way of the shot
  320.     spot1 = self.origin + self.view_ofs;
  321.     spot2 = targ.origin + targ.view_ofs;
  322.  
  323.     if (vlen(spot1 - spot2) > 600)
  324.         return FALSE;
  325.  
  326.     traceline (spot1, spot2, FALSE, self);
  327.  
  328.     if (trace_inopen && trace_inwater)
  329.         return FALSE;            // sight line crossed contents
  330.  
  331.     if (trace_ent != targ)
  332.     {
  333.         return FALSE;    // don't have a clear shot
  334.     }
  335.             
  336. // missile attack
  337.     if (enemy_range == RANGE_FAR)
  338.         return FALSE;
  339.         
  340.     self.attack_state = AS_MISSILE;
  341.     SUB_AttackFinished (2 + 2*random());
  342.     return TRUE;
  343. };
  344.  
  345. //============================================================================
  346.  
  347. /*
  348. ===========
  349. OgreCheckAttack
  350.  
  351. The player is in view, so decide to move or launch an attack
  352. Returns FALSE if movement should continue
  353. ============
  354. */
  355. float() OgreCheckAttack =
  356. {
  357.     local vector    spot1, spot2;    
  358.     local entity    targ;
  359.     local float        chance;
  360.  
  361.     if (enemy_range == RANGE_MELEE)
  362.     {
  363.         if (CanDamage (self.enemy, self))
  364.         {
  365.             self.attack_state = AS_MELEE;
  366.             return TRUE;
  367.         }
  368.     }
  369.  
  370.     if (time < self.attack_finished)
  371.         return FALSE;
  372.     
  373.     if (!enemy_vis)
  374.         return FALSE;
  375.         
  376.     targ = self.enemy;
  377.     
  378. // see if any entities are in the way of the shot
  379.     spot1 = self.origin + self.view_ofs;
  380.     spot2 = targ.origin + targ.view_ofs;
  381.  
  382.     traceline (spot1, spot2, FALSE, self);
  383.  
  384.     if (trace_inopen && trace_inwater)
  385.         return FALSE;            // sight line crossed contents
  386.  
  387.     if (trace_ent != targ)
  388.     {
  389.         return FALSE;    // don't have a clear shot
  390.     }
  391.             
  392. // missile attack
  393.     if (time < self.attack_finished)
  394.         return FALSE;
  395.         
  396.     if (enemy_range == RANGE_FAR)
  397.         return FALSE;
  398.         
  399.     else if (enemy_range == RANGE_NEAR)
  400.         chance = 0.10;
  401.     else if (enemy_range == RANGE_MID)
  402.         chance = 0.05;
  403.     else
  404.         chance = 0;
  405.  
  406.     self.attack_state = AS_MISSILE;
  407.     SUB_AttackFinished (1 + 2*random());
  408.     return TRUE;
  409. };
  410.  
  411.