home *** CD-ROM | disk | FTP | other *** search
/ Quake 'em / QUAKEEM.BIN / quake / programs / mhfsv22 / combat.qc < prev    next >
Encoding:
Text File  |  1996-08-23  |  7.2 KB  |  316 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.     if ( (teamplay == 4) && (attacker.team == targ.team) )
  83.         attacker.frags = attacker.frags - 2;
  84.         
  85.     if (teamplay == 5) 
  86.         if ((targ.skin > 0) && (attacker.skin > 0))
  87.             if (targ.skin == attacker.skin)
  88.                 attacker.frags = attacker.frags - 2;
  89.     
  90.     if ( (teamplay == 6) && ( ( attacker.skin == targ.skin) || (attacker.team == targ.team) ) )
  91.         attacker.frags == attacker.frags - 2;
  92.  
  93.     ClientObituary(self, attacker);
  94.     
  95.     self.takedamage = DAMAGE_NO;
  96.     self.touch = SUB_Null;
  97.  
  98.     monster_death_use();
  99.     self.th_die ();
  100.     
  101.     self = oself;
  102. };
  103.  
  104.  
  105. /*
  106. ============
  107. T_Damage
  108.  
  109. The damage is coming from inflictor, but get mad at attacker
  110. This should be the only function that ever reduces health.
  111. ============
  112. */
  113. void(entity targ, entity inflictor, entity attacker, float damage) T_Damage=
  114. {
  115.     local    vector    dir;
  116.     local    entity    oldself;
  117.     local    float    save;
  118.     local    float    take;
  119.  
  120.     if (!targ.takedamage)
  121.         return;
  122.  
  123. // used by buttons and triggers to set activator for target firing
  124.     damage_attacker = attacker;
  125.  
  126. // check for quad damage powerup on the attacker
  127.     if (attacker.super_damage_finished > time)
  128.         damage = damage * 4;
  129.  
  130. // check for admin god quad damage
  131.     if ((attacker.admin_god == 1) && (attacker.super_damage_finished < time))
  132.         damage = damage * 4;
  133.  
  134. // save damage based on the target's armor level
  135.  
  136.     save = ceil(targ.armortype*damage);
  137.     if (save >= targ.armorvalue)
  138.     {
  139.         save = targ.armorvalue;
  140.         targ.armortype = 0;    // lost all armor
  141.         targ.items = targ.items - (targ.items & (IT_ARMOR1 | IT_ARMOR2 | IT_ARMOR3));
  142.     }
  143.     
  144.     targ.armorvalue = targ.armorvalue - save;
  145.     take = ceil(damage-save);
  146.  
  147. // add to the damage total for clients, which will be sent as a single
  148. // message at the end of the frame
  149. // FIXME: remove after combining shotgun blasts?
  150.     if (targ.flags & FL_CLIENT)
  151.     {
  152.         targ.dmg_take = targ.dmg_take + take;
  153.         targ.dmg_save = targ.dmg_save + save;
  154.         targ.dmg_inflictor = inflictor;
  155.     }
  156.  
  157. // figure momentum add
  158.     if ( (inflictor != world) && (targ.movetype == MOVETYPE_WALK) )
  159.     {
  160.         dir = targ.origin - (inflictor.absmin + inflictor.absmax) * 0.5;
  161.         dir = normalize(dir);
  162.         targ.velocity = targ.velocity + dir*damage*8;
  163.     }
  164.  
  165. // check for godmode or invincibility
  166.     if (targ.flags & FL_GODMODE)
  167.         return;
  168.     if (targ.invincible_finished >= time)
  169.     {
  170.         if (self.invincible_sound < time)
  171.         {
  172.             sound (targ, CHAN_ITEM, "items/protect3.wav", 1, ATTN_NORM);
  173.             self.invincible_sound = time + 2;
  174.         }
  175.         return;
  176.     }
  177.  
  178. // Optimized: Thanx foobar...
  179. // team play damage avoidance
  180.     if ( (teamplay == 1) && (targ.team == attacker.team) )
  181.         return;
  182.         
  183. // Teamplay for multiskins on (ignoring pants color)
  184.     if (teamplay == 2) 
  185.         if ((targ.skin > 0) && (attacker.skin > 0))
  186.             if (targ.skin == attacker.skin)
  187.                 return;
  188.  
  189. // Teamplay for multiskins and/or pants colour
  190.     if (teamplay == 3)
  191.         if (targ.team == attacker.team)
  192.             return;
  193.         if ((targ.skin > 0) && (attacker.skin > 0))
  194.             if (targ.skin == attacker.skin)
  195.                 return;
  196.         
  197. // do the damage
  198.     targ.health = targ.health - take;
  199.             
  200.     if (targ.health <= 0)
  201.     {
  202.         Killed (targ, attacker);
  203.         return;
  204.     }
  205.  
  206. // react to the damage
  207.     oldself = self;
  208.     self = targ;
  209.  
  210.     if ( (self.flags & FL_MONSTER) && attacker != world)
  211.     {
  212.     // get mad unless of the same class (except for soldiers)
  213.         if (self != attacker && attacker != self.enemy)
  214.         {
  215.             if ( (self.classname != attacker.classname) 
  216.             || (self.classname == "monster_army" ) )
  217.             {
  218.                 if (self.enemy.classname == "player")
  219.                     self.oldenemy = self.enemy;
  220.                 self.enemy = attacker;
  221.                 FoundTarget ();
  222.             }
  223.         }
  224.     }
  225.  
  226.     if (self.th_pain)
  227.     {
  228.         self.th_pain (attacker, take);
  229.     // nightmare mode monsters don't go into pain frames often
  230.         if (skill == 3)
  231.             self.pain_finished = time + 5;        
  232.     }
  233.  
  234.     self = oldself;
  235. };
  236.  
  237. /*
  238. ============
  239. T_RadiusDamage
  240. ============
  241. */
  242. void(entity inflictor, entity attacker, float damage, entity ignore) T_RadiusDamage =
  243. {
  244.     local    float     points;
  245.     local    entity    head;
  246.     local    vector    org;
  247.  
  248.     head = findradius(inflictor.origin, damage+40);
  249.     
  250.     while (head)
  251.     {
  252.         if (head != ignore)
  253.         {
  254.             if (head.takedamage)
  255.             {
  256.                 org = head.origin + (head.mins + head.maxs)*0.5;
  257.                 points = 0.5*vlen (inflictor.origin - org);
  258.                 if (points < 0)
  259.                     points = 0;
  260.                 points = damage - points;
  261.                 if (head == attacker)
  262.                     points = points * 0.5;
  263.                 if (points > 0)
  264.                 {
  265.                     if (CanDamage (head, inflictor))
  266.                     {    // shambler takes half damage from all explosions
  267.                         if (head.classname == "monster_shambler")                        
  268.                             T_Damage (head, inflictor, attacker, points*0.5);
  269.                         else
  270.                             T_Damage (head, inflictor, attacker, points);
  271.                     }
  272.                 }
  273.             }
  274.         }
  275.         head = head.chain;
  276.     }
  277. };
  278.  
  279. /*
  280. ============
  281. T_BeamDamage
  282. ============
  283. */
  284. void(entity attacker, float damage) T_BeamDamage =
  285. {
  286.     local    float     points;
  287.     local    entity    head;
  288.     
  289.     head = findradius(attacker.origin, damage+40);
  290.     
  291.     while (head)
  292.     {
  293.         if (head.takedamage)
  294.         {
  295.             points = 0.5*vlen (attacker.origin - head.origin);
  296.             if (points < 0)
  297.                 points = 0;
  298.             points = damage - points;
  299.             if (head == attacker)
  300.                 points = points * 0.5;
  301.             if (points > 0)
  302.             {
  303.                 if (CanDamage (head, attacker))
  304.                 {
  305.                     if (head.classname == "monster_shambler")                        
  306.                         T_Damage (head, attacker, attacker, points*0.5);
  307.                     else
  308.                         T_Damage (head, attacker, attacker, points);
  309.                 }
  310.             }
  311.         }
  312.         head = head.chain;
  313.     }
  314. };
  315.  
  316.