home *** CD-ROM | disk | FTP | other *** search
/ Superpower (Alt) / SUPERPOWER.iso / q / patch / mbq089 / combat.qc < prev    next >
Encoding:
Text File  |  1996-08-15  |  8.6 KB  |  386 lines

  1.  
  2. void() T_MissileTouch;
  3. void() info_player_start;
  4. void(entity targ, entity attacker) ClientObituary;
  5.  
  6. void() monster_death_use;
  7.  
  8. //============================================================================
  9.  
  10. /*
  11. ============
  12. CanDamage
  13.  
  14. Returns true if the inflictor can directly damage the target.  Used for
  15. explosions and melee attacks.
  16. ============
  17. */
  18. float(entity targ, entity inflictor) CanDamage =
  19. {
  20. // bmodels need special checking because their origin is 0,0,0
  21.     if (targ.movetype == MOVETYPE_PUSH)
  22.     {
  23.         traceline(inflictor.origin, 0.5 * (targ.absmin + targ.absmax), TRUE, self);
  24.         if (trace_fraction == 1)
  25.             return TRUE;
  26.         if (trace_ent == targ)
  27.             return TRUE;
  28.         return FALSE;
  29.     }
  30.     
  31.     traceline(inflictor.origin, targ.origin, TRUE, self);
  32.     if (trace_fraction == 1)
  33.         return TRUE;
  34.     traceline(inflictor.origin, targ.origin + '15 15 0', TRUE, self);
  35.     if (trace_fraction == 1)
  36.         return TRUE;
  37.     traceline(inflictor.origin, targ.origin + '-15 -15 0', TRUE, self);
  38.     if (trace_fraction == 1)
  39.         return TRUE;
  40.     traceline(inflictor.origin, targ.origin + '-15 15 0', TRUE, self);
  41.     if (trace_fraction == 1)
  42.         return TRUE;
  43.     traceline(inflictor.origin, targ.origin + '15 -15 0', TRUE, self);
  44.     if (trace_fraction == 1)
  45.         return TRUE;
  46.  
  47.     return FALSE;
  48. };
  49.  
  50.  
  51. /*
  52. ============
  53. Killed
  54. ============
  55. */
  56. void(entity targ, entity attacker) Killed =
  57. {
  58.     local entity oself;
  59.  
  60.     oself = self;
  61.     self = targ;
  62.     
  63.     if (self.health < -99)
  64.         self.health = -99;        // don't let sbar look bad if a player
  65.  
  66.     if (self.movetype == MOVETYPE_PUSH || self.movetype == MOVETYPE_NONE)
  67.     {    // doors, triggers, etc
  68.         self.th_die ();
  69.         self = oself;
  70.         return;
  71.     }
  72.  
  73.     self.enemy = attacker;
  74.  
  75. // bump the monster counter
  76.     if (self.flags & FL_MONSTER)
  77.     {
  78.         killed_monsters = killed_monsters + 1;
  79.         WriteByte (MSG_ALL, SVC_KILLEDMONSTER);
  80.     }
  81.  
  82.     ClientObituary(self, attacker);
  83.     
  84.     self.takedamage = DAMAGE_NO;
  85.     self.touch = SUB_Null;
  86.  
  87.     monster_death_use();
  88.     self.th_die ();
  89.     
  90.     self = oself;
  91. };
  92.  
  93.  
  94. /*
  95. ============
  96. T_Damage
  97.  
  98. The damage is coming from inflictor, but get mad at attacker
  99. This should be the only function that ever reduces health.
  100. ============
  101. */
  102. void(entity targ, entity inflictor, entity attacker, float damage) T_Damage=
  103. {
  104.     local    vector    dir;
  105.     local    entity    oldself;
  106.     local    float    save;
  107.     local    float    take;
  108.  
  109.     if (!targ.takedamage)
  110.         return;
  111.  
  112. // used by buttons and triggers to set activator for target firing
  113.     damage_attacker = attacker;
  114.  
  115. // check for quad damage powerup on the attacker
  116.     if (attacker.super_damage_finished > time)
  117.         damage = damage * 4;
  118.  
  119. // save damage based on the target's armor level
  120.  
  121.     save = ceil(targ.armortype*damage);
  122.     if (save >= targ.armorvalue)
  123.     {
  124.         save = targ.armorvalue;
  125.         targ.armortype = 0;    // lost all armor
  126.         targ.items = targ.items - (targ.items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3));
  127.     }
  128.     
  129.     targ.armorvalue = targ.armorvalue - save;
  130.     take = ceil(damage-save);
  131.  
  132. // add to the damage total for clients, which will be sent as a single
  133. // message at the end of the frame
  134. // FIXME: remove after combining shotgun blasts?
  135.     if (targ.flags & FL_CLIENT)
  136.     {
  137.         targ.dmg_take = targ.dmg_take + take;
  138.         targ.dmg_save = targ.dmg_save + save;
  139.         targ.dmg_inflictor = inflictor;
  140.     }
  141.  
  142. // figure momentum add
  143.     if ( (inflictor != world) && (targ.movetype == MOVETYPE_WALK) )
  144.     {
  145.         dir = targ.origin - (inflictor.absmin + inflictor.absmax) * 0.5;
  146.         dir = normalize(dir);
  147.         targ.velocity = targ.velocity + dir*damage*8;
  148.     }
  149.  
  150. // check for godmode or invincibility
  151.     if (targ.flags & FL_GODMODE)
  152.         return;
  153.     if (targ.invincible_finished >= time)
  154.     {
  155.         if (self.invincible_sound < time)
  156.         {
  157.             sound (targ, CHAN_ITEM, "items/protect3.wav", 1, ATTN_NORM);
  158.             self.invincible_sound = time + 2;
  159.         }
  160.         return;
  161.     }
  162.  
  163. // team play damage avoidance
  164.     if ( (teamplay == 1) && (targ.team > 0)&&(targ.team == attacker.team) )
  165.         return;
  166.         
  167. // do the damage
  168.     targ.health = targ.health - take;
  169.             
  170.     if (targ.health <= 0)
  171.     {
  172.         Killed (targ, attacker);
  173.         return;
  174.     }
  175.  
  176. // react to the damage
  177.     oldself = self;
  178.     self = targ;
  179.  
  180.     if ( (self.flags & FL_MONSTER) && attacker != world)
  181.     {
  182.     // get mad unless of the same class (except for soldiers)
  183.         if (self != attacker && attacker != self.enemy)
  184.         {
  185.             if ( (self.classname != attacker.classname) 
  186.             || (self.classname == "monster_army" ) )
  187.             {
  188.                 if (self.enemy.classname == "player")
  189.                     self.oldenemy = self.enemy;
  190.                 self.enemy = attacker;
  191.                 FoundTarget ();
  192.             }
  193.         }
  194.     }
  195.  
  196.     if (self.th_pain)
  197.     {
  198.         self.th_pain (attacker, take);
  199.     // nightmare mode monsters don't go into pain frames often
  200.         if (skill == 3)
  201.             self.pain_finished = time + 5;        
  202.     }
  203.  
  204.     self = oldself;
  205. };
  206. /*
  207. ============
  208. S_Damage  <---Used With Sniper Rifle
  209. ============
  210. */
  211.  
  212. void(entity targ, entity inflictor, entity attacker, float damage) S_Damage=
  213. {
  214.     local    vector    dir;
  215.     local    entity    oldself;
  216.     local    float    save;
  217.     local    float    take;
  218.  
  219.     if (!targ.takedamage)
  220.         return;
  221.  
  222. // used by buttons and triggers to set activator for target firing
  223.     damage_attacker = attacker;
  224.  
  225. // check for quad damage powerup on the attacker
  226.     if (attacker.super_damage_finished > time)
  227.         damage = damage * 4;
  228.                 save = 0;
  229.                 take = damage;
  230.  
  231. // add to the damage total for clients, which will be sent as a single
  232. // message at the end of the frame
  233. // FIXME: remove after combining shotgun blasts?
  234.     if (targ.flags & FL_CLIENT)
  235.     {
  236.         targ.dmg_take = targ.dmg_take + take;
  237.         targ.dmg_save = targ.dmg_save + save;
  238.         targ.dmg_inflictor = inflictor;
  239.     }
  240.  
  241. // figure momentum add
  242.     if ( (inflictor != world) && (targ.movetype == MOVETYPE_WALK) )
  243.     {
  244.         dir = targ.origin - (inflictor.absmin + inflictor.absmax) * 0.5;
  245.         dir = normalize(dir);
  246.         targ.velocity = targ.velocity + dir*damage*8;
  247.     }
  248.  
  249. // check for godmode or invincibility
  250.     if (targ.flags & FL_GODMODE)
  251.         return;
  252.     if (targ.invincible_finished >= time)
  253.     {
  254.         if (self.invincible_sound < time)
  255.         {
  256.             sound (targ, CHAN_ITEM, "items/protect3.wav", 1, ATTN_NORM);
  257.             self.invincible_sound = time + 2;
  258.         }
  259.         return;
  260.     }
  261.  
  262. // team play damage avoidance
  263.     if ( (teamplay == 1) && (targ.team > 0)&&(targ.team == attacker.team) )
  264.         return;
  265.         
  266. // do the damage
  267.     targ.health = targ.health - take;
  268.             
  269.     if (targ.health <= 0)
  270.     {
  271.         Killed (targ, attacker);
  272.         return;
  273.     }
  274.  
  275. // react to the damage
  276.     oldself = self;
  277.     self = targ;
  278.  
  279.     if ( (self.flags & FL_MONSTER) && attacker != world)
  280.     {
  281.     // get mad unless of the same class (except for soldiers)
  282.         if (self != attacker && attacker != self.enemy)
  283.         {
  284.             if ( (self.classname != attacker.classname) 
  285.             || (self.classname == "monster_army" ) )
  286.             {
  287.                 if (self.enemy.classname == "player")
  288.                     self.oldenemy = self.enemy;
  289.                 self.enemy = attacker;
  290.                 FoundTarget ();
  291.             }
  292.         }
  293.     }
  294.  
  295.     if (self.th_pain)
  296.     {
  297.         self.th_pain (attacker, take);
  298.     // nightmare mode monsters don't go into pain frames often
  299.         if (skill == 3)
  300.             self.pain_finished = time + 5;        
  301.     }
  302.  
  303.     self = oldself;
  304. };
  305.  
  306.  
  307. /*
  308. ============
  309. T_RadiusDamage
  310. ============
  311. */
  312. void(entity inflictor, entity attacker, float damage, entity ignore) T_RadiusDamage =
  313. {
  314.     local    float     points;
  315.     local    entity    head;
  316.     local    vector    org;
  317.  
  318.     head = findradius(inflictor.origin, damage+40);
  319.     
  320.     while (head)
  321.     {
  322.         if (head != ignore)
  323.         {
  324.             if (head.takedamage)
  325.             {
  326.                 org = head.origin + (head.mins + head.maxs)*0.5;
  327.                 points = 0.5*vlen (inflictor.origin - org);
  328.                 if (points < 0)
  329.                     points = 0;
  330.                 points = damage - points;
  331.                 if (head == attacker)
  332.                     points = points * 0.5;
  333.                 if (points > 0)
  334.                 {
  335.                     if (CanDamage (head, inflictor))
  336.                     {    // shambler takes half damage from all explosions
  337.                         if (head.classname == "monster_shambler")                        
  338.                             T_Damage (head, inflictor, attacker, points*0.5);
  339.                         else
  340.                             T_Damage (head, inflictor, attacker, points);
  341.                     }
  342.                 }
  343.             }
  344.         }
  345.         head = head.chain;
  346.     }
  347. };
  348.  
  349. /*
  350. ============
  351. T_BeamDamage
  352. ============
  353. */
  354. void(entity attacker, float damage) T_BeamDamage =
  355. {
  356.     local    float     points;
  357.     local    entity    head;
  358.     
  359.     head = findradius(attacker.origin, damage+40);
  360.     
  361.     while (head)
  362.     {
  363.         if (head.takedamage)
  364.         {
  365.             points = 0.5*vlen (attacker.origin - head.origin);
  366.             if (points < 0)
  367.                 points = 0;
  368.             points = damage - points;
  369.             if (head == attacker)
  370.                 points = points * 0.5;
  371.             if (points > 0)
  372.             {
  373.                 if (CanDamage (head, attacker))
  374.                 {
  375.                     if (head.classname == "monster_shambler")                        
  376.                         T_Damage (head, attacker, attacker, points*0.5);
  377.                     else
  378.                         T_Damage (head, attacker, attacker, points);
  379.                 }
  380.             }
  381.         }
  382.         head = head.chain;
  383.     }
  384. };
  385.  
  386.