Annotation of quakeworld/progs/combat.qc, revision 1.1

1.1     ! root        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: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.