home *** CD-ROM | disk | FTP | other *** search
/ PC PowerPlay 11 / PCPP11.iso / patch / quake2 / combat.qc < prev    next >
Encoding:
Text File  |  1996-12-13  |  6.1 KB  |  297 lines

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