Annotation of quake2/game/g_turret.c, revision 1.1

1.1     ! root        1: // g_turret.c
        !             2: 
        !             3: #include "g_local.h"
        !             4: 
        !             5: 
        !             6: void AnglesNormalize(vec3_t vec)
        !             7: {
        !             8:        while(vec[0] > 360)
        !             9:                vec[0] -= 360;
        !            10:        while(vec[0] < 0)
        !            11:                vec[0] += 360;
        !            12:        while(vec[1] > 360)
        !            13:                vec[1] -= 360;
        !            14:        while(vec[1] < 0)
        !            15:                vec[1] += 360;
        !            16: }
        !            17: 
        !            18: float SnapToEights(float x)
        !            19: {
        !            20:        x *= 8.0;
        !            21:        if (x > 0.0)
        !            22:                x += 0.5;
        !            23:        else
        !            24:                x -= 0.5;
        !            25:        return 0.125 * (int)x;
        !            26: }
        !            27: 
        !            28: 
        !            29: void turret_blocked(edict_t *self, edict_t *other)
        !            30: {
        !            31:        edict_t *attacker;
        !            32: 
        !            33:        if (other->takedamage)
        !            34:        {
        !            35:                if (self->teammaster->owner)
        !            36:                        attacker = self->teammaster->owner;
        !            37:                else
        !            38:                        attacker = self->teammaster;
        !            39:                T_Damage (other, self, attacker, vec3_origin, other->s.origin, vec3_origin, self->teammaster->dmg, 10, 0, MOD_CRUSH);
        !            40:        }
        !            41: }
        !            42: 
        !            43: /*QUAKED turret_breach (0 0 0) ?
        !            44: This portion of the turret can change both pitch and yaw.
        !            45: The model  should be made with a flat pitch.
        !            46: It (and the associated base) need to be oriented towards 0.
        !            47: Use "angle" to set the starting angle.
        !            48: 
        !            49: "speed"                default 50
        !            50: "dmg"          default 10
        !            51: "angle"                point this forward
        !            52: "target"       point this at an info_notnull at the muzzle tip
        !            53: "minpitch"     min acceptable pitch angle : default -30
        !            54: "maxpitch"     max acceptable pitch angle : default 30
        !            55: "minyaw"       min acceptable yaw angle   : default 0
        !            56: "maxyaw"       max acceptable yaw angle   : default 360
        !            57: */
        !            58: 
        !            59: void turret_breach_fire (edict_t *self)
        !            60: {
        !            61:        vec3_t  f, r, u;
        !            62:        vec3_t  start;
        !            63:        int             damage;
        !            64:        int             speed;
        !            65: 
        !            66:        AngleVectors (self->s.angles, f, r, u);
        !            67:        VectorMA (self->s.origin, self->move_origin[0], f, start);
        !            68:        VectorMA (start, self->move_origin[1], r, start);
        !            69:        VectorMA (start, self->move_origin[2], u, start);
        !            70: 
        !            71:        damage = 100 + random() * 50;
        !            72:        speed = 550 + 50 * skill->value;
        !            73:        fire_rocket (self->teammaster->owner, start, f, damage, speed, 150, damage);
        !            74:        gi.positioned_sound (start, self, CHAN_WEAPON, gi.soundindex("weapons/rocklf1a.wav"), 1, ATTN_NORM, 0);
        !            75: }
        !            76: 
        !            77: void turret_breach_think (edict_t *self)
        !            78: {
        !            79:        edict_t *ent;
        !            80:        vec3_t  current_angles;
        !            81:        vec3_t  delta;
        !            82: 
        !            83:        VectorCopy (self->s.angles, current_angles);
        !            84:        AnglesNormalize(current_angles);
        !            85: 
        !            86:        AnglesNormalize(self->move_angles);
        !            87:        if (self->move_angles[PITCH] > 180)
        !            88:                self->move_angles[PITCH] -= 360;
        !            89: 
        !            90:        // clamp angles to mins & maxs
        !            91:        if (self->move_angles[PITCH] > self->pos1[PITCH])
        !            92:                self->move_angles[PITCH] = self->pos1[PITCH];
        !            93:        else if (self->move_angles[PITCH] < self->pos2[PITCH])
        !            94:                self->move_angles[PITCH] = self->pos2[PITCH];
        !            95: 
        !            96:        if ((self->move_angles[YAW] < self->pos1[YAW]) || (self->move_angles[YAW] > self->pos2[YAW]))
        !            97:        {
        !            98:                float   dmin, dmax;
        !            99: 
        !           100:                dmin = fabs(self->pos1[YAW] - self->move_angles[YAW]);
        !           101:                if (dmin < -180)
        !           102:                        dmin += 360;
        !           103:                else if (dmin > 180)
        !           104:                        dmin -= 360;
        !           105:                dmax = fabs(self->pos2[YAW] - self->move_angles[YAW]);
        !           106:                if (dmax < -180)
        !           107:                        dmax += 360;
        !           108:                else if (dmax > 180)
        !           109:                        dmax -= 360;
        !           110:                if (fabs(dmin) < fabs(dmax))
        !           111:                        self->move_angles[YAW] = self->pos1[YAW];
        !           112:                else
        !           113:                        self->move_angles[YAW] = self->pos2[YAW];
        !           114:        }
        !           115: 
        !           116:        VectorSubtract (self->move_angles, current_angles, delta);
        !           117:        if (delta[0] < -180)
        !           118:                delta[0] += 360;
        !           119:        else if (delta[0] > 180)
        !           120:                delta[0] -= 360;
        !           121:        if (delta[1] < -180)
        !           122:                delta[1] += 360;
        !           123:        else if (delta[1] > 180)
        !           124:                delta[1] -= 360;
        !           125:        delta[2] = 0;
        !           126: 
        !           127:        if (delta[0] > self->speed * FRAMETIME)
        !           128:                delta[0] = self->speed * FRAMETIME;
        !           129:        if (delta[0] < -1 * self->speed * FRAMETIME)
        !           130:                delta[0] = -1 * self->speed * FRAMETIME;
        !           131:        if (delta[1] > self->speed * FRAMETIME)
        !           132:                delta[1] = self->speed * FRAMETIME;
        !           133:        if (delta[1] < -1 * self->speed * FRAMETIME)
        !           134:                delta[1] = -1 * self->speed * FRAMETIME;
        !           135: 
        !           136:        VectorScale (delta, 1.0/FRAMETIME, self->avelocity);
        !           137: 
        !           138:        self->nextthink = level.time + FRAMETIME;
        !           139: 
        !           140:        for (ent = self->teammaster; ent; ent = ent->teamchain)
        !           141:                ent->avelocity[1] = self->avelocity[1];
        !           142: 
        !           143:        // if we have adriver, adjust his velocities
        !           144:        if (self->owner)
        !           145:        {
        !           146:                float   angle;
        !           147:                float   target_z;
        !           148:                float   diff;
        !           149:                vec3_t  target;
        !           150:                vec3_t  dir;
        !           151: 
        !           152:                // angular is easy, just copy ours
        !           153:                self->owner->avelocity[0] = self->avelocity[0];
        !           154:                self->owner->avelocity[1] = self->avelocity[1];
        !           155: 
        !           156:                // x & y
        !           157:                angle = self->s.angles[1] + self->owner->move_origin[1];
        !           158:                angle *= (M_PI*2 / 360);
        !           159:                target[0] = SnapToEights(self->s.origin[0] + cos(angle) * self->owner->move_origin[0]);
        !           160:                target[1] = SnapToEights(self->s.origin[1] + sin(angle) * self->owner->move_origin[0]);
        !           161:                target[2] = self->owner->s.origin[2];
        !           162: 
        !           163:                VectorSubtract (target, self->owner->s.origin, dir);
        !           164:                self->owner->velocity[0] = dir[0] * 1.0 / FRAMETIME;
        !           165:                self->owner->velocity[1] = dir[1] * 1.0 / FRAMETIME;
        !           166: 
        !           167:                // z
        !           168:                angle = self->s.angles[PITCH] * (M_PI*2 / 360);
        !           169:                target_z = SnapToEights(self->s.origin[2] + self->owner->move_origin[0] * tan(angle) + self->owner->move_origin[2]);
        !           170: 
        !           171:                diff = target_z - self->owner->s.origin[2];
        !           172:                self->owner->velocity[2] = diff * 1.0 / FRAMETIME;
        !           173: 
        !           174:                if (self->spawnflags & 65536)
        !           175:                {
        !           176:                        turret_breach_fire (self);
        !           177:                        self->spawnflags &= ~65536;
        !           178:                }
        !           179:        }
        !           180: }
        !           181: 
        !           182: void turret_breach_finish_init (edict_t *self)
        !           183: {
        !           184:        // get and save info for muzzle location
        !           185:        if (!self->target)
        !           186:        {
        !           187:                gi.dprintf("%s at %s needs a target\n", self->classname, vtos(self->s.origin));
        !           188:        }
        !           189:        else
        !           190:        {
        !           191:                self->target_ent = G_PickTarget (self->target);
        !           192:                VectorSubtract (self->target_ent->s.origin, self->s.origin, self->move_origin);
        !           193:                G_FreeEdict(self->target_ent);
        !           194:        }
        !           195: 
        !           196:        self->teammaster->dmg = self->dmg;
        !           197:        self->think = turret_breach_think;
        !           198:        self->think (self);
        !           199: }
        !           200: 
        !           201: void SP_turret_breach (edict_t *self)
        !           202: {
        !           203:        self->solid = SOLID_BSP;
        !           204:        self->movetype = MOVETYPE_PUSH;
        !           205:        gi.setmodel (self, self->model);
        !           206: 
        !           207:        if (!self->speed)
        !           208:                self->speed = 50;
        !           209:        if (!self->dmg)
        !           210:                self->dmg = 10;
        !           211: 
        !           212:        if (!st.minpitch)
        !           213:                st.minpitch = -30;
        !           214:        if (!st.maxpitch)
        !           215:                st.maxpitch = 30;
        !           216:        if (!st.maxyaw)
        !           217:                st.maxyaw = 360;
        !           218: 
        !           219:        self->pos1[PITCH] = -1 * st.minpitch;
        !           220:        self->pos1[YAW]   = st.minyaw;
        !           221:        self->pos2[PITCH] = -1 * st.maxpitch;
        !           222:        self->pos2[YAW]   = st.maxyaw;
        !           223: 
        !           224:        self->ideal_yaw = self->s.angles[YAW];
        !           225:        self->move_angles[YAW] = self->ideal_yaw;
        !           226: 
        !           227:        self->blocked = turret_blocked;
        !           228: 
        !           229:        self->think = turret_breach_finish_init;
        !           230:        self->nextthink = level.time + FRAMETIME;
        !           231:        gi.linkentity (self);
        !           232: }
        !           233: 
        !           234: 
        !           235: /*QUAKED turret_base (0 0 0) ?
        !           236: This portion of the turret changes yaw only.
        !           237: MUST be teamed with a turret_breach.
        !           238: */
        !           239: 
        !           240: void SP_turret_base (edict_t *self)
        !           241: {
        !           242:        self->solid = SOLID_BSP;
        !           243:        self->movetype = MOVETYPE_PUSH;
        !           244:        gi.setmodel (self, self->model);
        !           245:        self->blocked = turret_blocked;
        !           246:        gi.linkentity (self);
        !           247: }
        !           248: 
        !           249: 
        !           250: /*QUAKED turret_driver (1 .5 0) (-16 -16 -24) (16 16 32)
        !           251: Must NOT be on the team with the rest of the turret parts.
        !           252: Instead it must target the turret_breach.
        !           253: */
        !           254: 
        !           255: void infantry_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage);
        !           256: void infantry_stand (edict_t *self);
        !           257: void monster_use (edict_t *self, edict_t *other, edict_t *activator);
        !           258: 
        !           259: void turret_driver_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
        !           260: {
        !           261:        edict_t *ent;
        !           262: 
        !           263:        // level the gun
        !           264:        self->target_ent->move_angles[0] = 0;
        !           265: 
        !           266:        // remove the driver from the end of them team chain
        !           267:        for (ent = self->target_ent->teammaster; ent->teamchain != self; ent = ent->teamchain)
        !           268:                ;
        !           269:        ent->teamchain = NULL;
        !           270:        self->teammaster = NULL;
        !           271:        self->flags &= ~FL_TEAMSLAVE;
        !           272: 
        !           273:        self->target_ent->owner = NULL;
        !           274:        self->target_ent->teammaster->owner = NULL;
        !           275: 
        !           276:        infantry_die (self, inflictor, attacker, damage);
        !           277: }
        !           278: 
        !           279: qboolean FindTarget (edict_t *self);
        !           280: 
        !           281: void turret_driver_think (edict_t *self)
        !           282: {
        !           283:        vec3_t  target;
        !           284:        vec3_t  dir;
        !           285:        float   reaction_time;
        !           286: 
        !           287:        self->nextthink = level.time + FRAMETIME;
        !           288: 
        !           289:        if (self->enemy && (!self->enemy->inuse || self->enemy->health <= 0))
        !           290:                self->enemy = NULL;
        !           291: 
        !           292:        if (!self->enemy)
        !           293:        {
        !           294:                if (!FindTarget (self))
        !           295:                        return;
        !           296:                self->monsterinfo.trail_time = level.time;
        !           297:                self->monsterinfo.aiflags &= ~AI_LOST_SIGHT;
        !           298:        }
        !           299:        else
        !           300:        {
        !           301:                if (visible (self, self->enemy))
        !           302:                {
        !           303:                        if (self->monsterinfo.aiflags & AI_LOST_SIGHT)
        !           304:                        {
        !           305:                                self->monsterinfo.trail_time = level.time;
        !           306:                                self->monsterinfo.aiflags &= ~AI_LOST_SIGHT;
        !           307:                        }
        !           308:                }
        !           309:                else
        !           310:                {
        !           311:                        self->monsterinfo.aiflags |= AI_LOST_SIGHT;
        !           312:                        return;
        !           313:                }
        !           314:        }
        !           315: 
        !           316:        // let the turret know where we want it to aim
        !           317:        VectorCopy (self->enemy->s.origin, target);
        !           318:        target[2] += self->enemy->viewheight;
        !           319:        VectorSubtract (target, self->target_ent->s.origin, dir);
        !           320:        vectoangles (dir, self->target_ent->move_angles);
        !           321: 
        !           322:        // decide if we should shoot
        !           323:        if (level.time < self->monsterinfo.attack_finished)
        !           324:                return;
        !           325: 
        !           326:        reaction_time = (3 - skill->value) * 1.0;
        !           327:        if ((level.time - self->monsterinfo.trail_time) < reaction_time)
        !           328:                return;
        !           329: 
        !           330:        self->monsterinfo.attack_finished = level.time + reaction_time + 1.0;
        !           331:        //FIXME how do we really want to pass this along?
        !           332:        self->target_ent->spawnflags |= 65536;
        !           333: }
        !           334: 
        !           335: void turret_driver_link (edict_t *self)
        !           336: {
        !           337:        vec3_t  vec;
        !           338:        edict_t *ent;
        !           339: 
        !           340:        self->think = turret_driver_think;
        !           341:        self->nextthink = level.time + FRAMETIME;
        !           342: 
        !           343:        self->target_ent = G_PickTarget (self->target);
        !           344:        self->target_ent->owner = self;
        !           345:        self->target_ent->teammaster->owner = self;
        !           346:        VectorCopy (self->target_ent->s.angles, self->s.angles);
        !           347: 
        !           348:        vec[0] = self->target_ent->s.origin[0] - self->s.origin[0];
        !           349:        vec[1] = self->target_ent->s.origin[1] - self->s.origin[1];
        !           350:        vec[2] = 0;
        !           351:        self->move_origin[0] = VectorLength(vec);
        !           352: 
        !           353:        VectorSubtract (self->s.origin, self->target_ent->s.origin, vec);
        !           354:        vectoangles (vec, vec);
        !           355:        AnglesNormalize(vec);
        !           356:        self->move_origin[1] = vec[1];
        !           357: 
        !           358:        self->move_origin[2] = self->s.origin[2] - self->target_ent->s.origin[2];
        !           359: 
        !           360:        // add the driver to the end of them team chain
        !           361:        for (ent = self->target_ent->teammaster; ent->teamchain; ent = ent->teamchain)
        !           362:                ;
        !           363:        ent->teamchain = self;
        !           364:        self->teammaster = self->target_ent->teammaster;
        !           365:        self->flags |= FL_TEAMSLAVE;
        !           366: }
        !           367: 
        !           368: void SP_turret_driver (edict_t *self)
        !           369: {
        !           370:        if (deathmatch->value)
        !           371:        {
        !           372:                G_FreeEdict (self);
        !           373:                return;
        !           374:        }
        !           375: 
        !           376:        self->movetype = MOVETYPE_PUSH;
        !           377:        self->solid = SOLID_BBOX;
        !           378:        self->s.modelindex = gi.modelindex("models/monsters/infantry/tris.md2");
        !           379:        VectorSet (self->mins, -16, -16, -24);
        !           380:        VectorSet (self->maxs, 16, 16, 32);
        !           381: 
        !           382:        self->health = 100;
        !           383:        self->gib_health = 0;
        !           384:        self->mass = 200;
        !           385:        self->viewheight = 24;
        !           386: 
        !           387:        self->die = turret_driver_die;
        !           388:        self->monsterinfo.stand = infantry_stand;
        !           389: 
        !           390:        self->flags |= FL_NO_KNOCKBACK;
        !           391: 
        !           392:        level.total_monsters++;
        !           393: 
        !           394:        self->svflags |= SVF_MONSTER;
        !           395:        self->s.renderfx |= RF_FRAMELERP;
        !           396:        self->takedamage = DAMAGE_AIM;
        !           397:        self->use = monster_use;
        !           398:        self->clipmask = MASK_MONSTERSOLID;
        !           399:        VectorCopy (self->s.origin, self->s.old_origin);
        !           400:        self->monsterinfo.aiflags |= AI_STAND_GROUND|AI_DUCKED;
        !           401: 
        !           402:        if (st.item)
        !           403:        {
        !           404:                self->item = FindItemByClassname (st.item);
        !           405:                if (!self->item)
        !           406:                        gi.dprintf("%s at %s has bad item: %s\n", self->classname, vtos(self->s.origin), st.item);
        !           407:        }
        !           408: 
        !           409:        self->think = turret_driver_link;
        !           410:        self->nextthink = level.time + FRAMETIME;
        !           411: 
        !           412:        gi.linkentity (self);
        !           413: }

unix.superglobalmegacorp.com

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