home *** CD-ROM | disk | FTP | other *** search
/ Magazyn Amiga 14 / MA_Cover_14.iso / source / c / q1source_amy / qw / progs / combat.qc < prev    next >
Encoding:
Text File  |  1998-08-26  |  7.5 KB  |  325 lines

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