home *** CD-ROM | disk | FTP | other *** search
/ PC Gamer 3.2 / 1997-05_Disc_3.2.iso / QUAKECTF / SRC / CTF / COMBAT.QC < prev    next >
Text File  |  1997-01-23  |  8KB  |  334 lines

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