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

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