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

1.1     ! root        1: // g_turret.c
        !             2: 
        !             3: #include "g_local.h"
        !             4: 
        !             5: void SpawnTargetingSystem (edict_t *turret);   // PGM
        !             6: 
        !             7: void AnglesNormalize(vec3_t vec)
        !             8: {
        !             9:        while(vec[0] > 360)
        !            10:                vec[0] -= 360;
        !            11:        while(vec[0] < 0)
        !            12:                vec[0] += 360;
        !            13:        while(vec[1] > 360)
        !            14:                vec[1] -= 360;
        !            15:        while(vec[1] < 0)
        !            16:                vec[1] += 360;
        !            17: }
        !            18: 
        !            19: float SnapToEights(float x)
        !            20: {
        !            21:        x *= 8.0;
        !            22:        if (x > 0.0)
        !            23:                x += 0.5;
        !            24:        else
        !            25:                x -= 0.5;
        !            26:        return 0.125 * (int)x;
        !            27: }
        !            28: 
        !            29: 
        !            30: void turret_blocked(edict_t *self, edict_t *other)
        !            31: {
        !            32:        edict_t *attacker;
        !            33: 
        !            34:        if (other->takedamage)
        !            35:        {
        !            36:                if (self->teammaster->owner)
        !            37:                        attacker = self->teammaster->owner;
        !            38:                else
        !            39:                        attacker = self->teammaster;
        !            40:                T_Damage (other, self, attacker, vec3_origin, other->s.origin, vec3_origin, self->teammaster->dmg, 10, 0, MOD_CRUSH);
        !            41:        }
        !            42: }
        !            43: 
        !            44: /*QUAKED turret_breach (0 0 0) ?
        !            45: This portion of the turret can change both pitch and yaw.
        !            46: The model  should be made with a flat pitch.
        !            47: It (and the associated base) need to be oriented towards 0.
        !            48: Use "angle" to set the starting angle.
        !            49: 
        !            50: "speed"                default 50
        !            51: "dmg"          default 10
        !            52: "angle"                point this forward
        !            53: "target"       point this at an info_notnull at the muzzle tip
        !            54: "minpitch"     min acceptable pitch angle : default -30
        !            55: "maxpitch"     max acceptable pitch angle : default 30
        !            56: "minyaw"       min acceptable yaw angle   : default 0
        !            57: "maxyaw"       max acceptable yaw angle   : default 360
        !            58: */
        !            59: 
        !            60: void turret_breach_fire (edict_t *self)
        !            61: {
        !            62:        vec3_t  f, r, u;
        !            63:        vec3_t  start;
        !            64:        int             damage;
        !            65:        int             speed;
        !            66: 
        !            67:        AngleVectors (self->s.angles, f, r, u);
        !            68:        VectorMA (self->s.origin, self->move_origin[0], f, start);
        !            69:        VectorMA (start, self->move_origin[1], r, start);
        !            70:        VectorMA (start, self->move_origin[2], u, start);
        !            71: 
        !            72:        damage = 100 + random() * 50;
        !            73:        speed = 550 + 50 * skill->value;
        !            74:        fire_rocket (self->teammaster->owner, start, f, damage, speed, 150, damage);
        !            75:        gi.positioned_sound (start, self, CHAN_WEAPON, gi.soundindex("weapons/rocklf1a.wav"), 1, ATTN_NORM, 0);
        !            76: }
        !            77: 
        !            78: void turret_breach_think (edict_t *self)
        !            79: {
        !            80:        edict_t *ent;
        !            81:        vec3_t  current_angles;
        !            82:        vec3_t  delta;
        !            83: 
        !            84:        VectorCopy (self->s.angles, current_angles);
        !            85:        AnglesNormalize(current_angles);
        !            86: 
        !            87:        AnglesNormalize(self->move_angles);
        !            88:        if (self->move_angles[PITCH] > 180)
        !            89:                self->move_angles[PITCH] -= 360;
        !            90: 
        !            91:        // clamp angles to mins & maxs
        !            92:        if (self->move_angles[PITCH] > self->pos1[PITCH])
        !            93:                self->move_angles[PITCH] = self->pos1[PITCH];
        !            94:        else if (self->move_angles[PITCH] < self->pos2[PITCH])
        !            95:                self->move_angles[PITCH] = self->pos2[PITCH];
        !            96: 
        !            97:        if ((self->move_angles[YAW] < self->pos1[YAW]) || (self->move_angles[YAW] > self->pos2[YAW]))
        !            98:        {
        !            99:                float   dmin, dmax;
        !           100: 
        !           101:                dmin = fabs(self->pos1[YAW] - self->move_angles[YAW]);
        !           102:                if (dmin < -180)
        !           103:                        dmin += 360;
        !           104:                else if (dmin > 180)
        !           105:                        dmin -= 360;
        !           106:                dmax = fabs(self->pos2[YAW] - self->move_angles[YAW]);
        !           107:                if (dmax < -180)
        !           108:                        dmax += 360;
        !           109:                else if (dmax > 180)
        !           110:                        dmax -= 360;
        !           111:                if (fabs(dmin) < fabs(dmax))
        !           112:                        self->move_angles[YAW] = self->pos1[YAW];
        !           113:                else
        !           114:                        self->move_angles[YAW] = self->pos2[YAW];
        !           115:        }
        !           116: 
        !           117:        VectorSubtract (self->move_angles, current_angles, delta);
        !           118:        if (delta[0] < -180)
        !           119:                delta[0] += 360;
        !           120:        else if (delta[0] > 180)
        !           121:                delta[0] -= 360;
        !           122:        if (delta[1] < -180)
        !           123:                delta[1] += 360;
        !           124:        else if (delta[1] > 180)
        !           125:                delta[1] -= 360;
        !           126:        delta[2] = 0;
        !           127: 
        !           128:        if (delta[0] > self->speed * FRAMETIME)
        !           129:                delta[0] = self->speed * FRAMETIME;
        !           130:        if (delta[0] < -1 * self->speed * FRAMETIME)
        !           131:                delta[0] = -1 * self->speed * FRAMETIME;
        !           132:        if (delta[1] > self->speed * FRAMETIME)
        !           133:                delta[1] = self->speed * FRAMETIME;
        !           134:        if (delta[1] < -1 * self->speed * FRAMETIME)
        !           135:                delta[1] = -1 * self->speed * FRAMETIME;
        !           136: 
        !           137:        VectorScale (delta, 1.0/FRAMETIME, self->avelocity);
        !           138: 
        !           139:        self->nextthink = level.time + FRAMETIME;
        !           140: 
        !           141:        for (ent = self->teammaster; ent; ent = ent->teamchain)
        !           142:                ent->avelocity[1] = self->avelocity[1];
        !           143: 
        !           144:        // if we have adriver, adjust his velocities
        !           145:        if (self->owner)
        !           146:        {
        !           147:                float   angle;
        !           148:                float   target_z;
        !           149:                float   diff;
        !           150:                vec3_t  target;
        !           151:                vec3_t  dir;
        !           152: 
        !           153:                // angular is easy, just copy ours
        !           154:                self->owner->avelocity[0] = self->avelocity[0];
        !           155:                self->owner->avelocity[1] = self->avelocity[1];
        !           156: 
        !           157:                // x & y
        !           158:                angle = self->s.angles[1] + self->owner->move_origin[1];
        !           159:                angle *= (M_PI*2 / 360);
        !           160:                target[0] = SnapToEights(self->s.origin[0] + cos(angle) * self->owner->move_origin[0]);
        !           161:                target[1] = SnapToEights(self->s.origin[1] + sin(angle) * self->owner->move_origin[0]);
        !           162:                target[2] = self->owner->s.origin[2];
        !           163: 
        !           164:                VectorSubtract (target, self->owner->s.origin, dir);
        !           165:                self->owner->velocity[0] = dir[0] * 1.0 / FRAMETIME;
        !           166:                self->owner->velocity[1] = dir[1] * 1.0 / FRAMETIME;
        !           167: 
        !           168:                // z
        !           169:                angle = self->s.angles[PITCH] * (M_PI*2 / 360);
        !           170:                target_z = SnapToEights(self->s.origin[2] + self->owner->move_origin[0] * tan(angle) + self->owner->move_origin[2]);
        !           171: 
        !           172:                diff = target_z - self->owner->s.origin[2];
        !           173:                self->owner->velocity[2] = diff * 1.0 / FRAMETIME;
        !           174: 
        !           175:                if (self->spawnflags & 65536)
        !           176:                {
        !           177:                        turret_breach_fire (self);
        !           178:                        self->spawnflags &= ~65536;
        !           179:                }
        !           180:        }
        !           181: }
        !           182: 
        !           183: void turret_breach_finish_init (edict_t *self)
        !           184: {
        !           185:        // get and save info for muzzle location
        !           186:        if (!self->target)
        !           187:        {
        !           188:                gi.dprintf("%s at %s needs a target\n", self->classname, vtos(self->s.origin));
        !           189:        }
        !           190:        else
        !           191:        {
        !           192:                self->target_ent = G_PickTarget (self->target);
        !           193:                if(self->target_ent)
        !           194:                {
        !           195:                        VectorSubtract (self->target_ent->s.origin, self->s.origin, self->move_origin);
        !           196:                        G_FreeEdict(self->target_ent);
        !           197:                }
        !           198:                else
        !           199:                        gi.dprintf("could not find target entity for %s at %s\n", self->classname, vtos(self->s.origin));
        !           200:        }
        !           201: 
        !           202:        self->teammaster->dmg = self->dmg;
        !           203:        self->think = turret_breach_think;
        !           204:        self->think (self);
        !           205: }
        !           206: 
        !           207: void SP_turret_breach (edict_t *self)
        !           208: {
        !           209:        self->solid = SOLID_BSP;
        !           210:        self->movetype = MOVETYPE_PUSH;
        !           211:        gi.setmodel (self, self->model);
        !           212: 
        !           213:        if (!self->speed)
        !           214:                self->speed = 50;
        !           215:        if (!self->dmg)
        !           216:                self->dmg = 10;
        !           217: 
        !           218:        if (!st.minpitch)
        !           219:                st.minpitch = -30;
        !           220:        if (!st.maxpitch)
        !           221:                st.maxpitch = 30;
        !           222:        if (!st.maxyaw)
        !           223:                st.maxyaw = 360;
        !           224: 
        !           225:        self->pos1[PITCH] = -1 * st.minpitch;
        !           226:        self->pos1[YAW]   = st.minyaw;
        !           227:        self->pos2[PITCH] = -1 * st.maxpitch;
        !           228:        self->pos2[YAW]   = st.maxyaw;
        !           229: 
        !           230:        self->ideal_yaw = self->s.angles[YAW];
        !           231:        self->move_angles[YAW] = self->ideal_yaw;
        !           232: 
        !           233:        self->blocked = turret_blocked;
        !           234: 
        !           235:        self->think = turret_breach_finish_init;
        !           236:        self->nextthink = level.time + FRAMETIME;
        !           237:        gi.linkentity (self);
        !           238: }
        !           239: 
        !           240: 
        !           241: /*QUAKED turret_base (0 0 0) ?
        !           242: This portion of the turret changes yaw only.
        !           243: MUST be teamed with a turret_breach.
        !           244: */
        !           245: 
        !           246: void SP_turret_base (edict_t *self)
        !           247: {
        !           248:        self->solid = SOLID_BSP;
        !           249:        self->movetype = MOVETYPE_PUSH;
        !           250:        gi.setmodel (self, self->model);
        !           251:        self->blocked = turret_blocked;
        !           252:        gi.linkentity (self);
        !           253: }
        !           254: 
        !           255: 
        !           256: /*QUAKED turret_driver (1 .5 0) (-16 -16 -24) (16 16 32)
        !           257: Must NOT be on the team with the rest of the turret parts.
        !           258: Instead it must target the turret_breach.
        !           259: */
        !           260: 
        !           261: void infantry_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage);
        !           262: void infantry_stand (edict_t *self);
        !           263: void monster_use (edict_t *self, edict_t *other, edict_t *activator);
        !           264: 
        !           265: void turret_driver_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
        !           266: {
        !           267:        edict_t *ent;
        !           268: 
        !           269:        // level the gun
        !           270:        self->target_ent->move_angles[0] = 0;
        !           271: 
        !           272:        // remove the driver from the end of them team chain
        !           273:        for (ent = self->target_ent->teammaster; ent->teamchain != self; ent = ent->teamchain)
        !           274:                ;
        !           275:        ent->teamchain = NULL;
        !           276:        self->teammaster = NULL;
        !           277:        self->flags &= ~FL_TEAMSLAVE;
        !           278: 
        !           279:        self->target_ent->owner = NULL;
        !           280:        self->target_ent->teammaster->owner = NULL;
        !           281: 
        !           282:        infantry_die (self, inflictor, attacker, damage);
        !           283: }
        !           284: 
        !           285: qboolean FindTarget (edict_t *self);
        !           286: 
        !           287: void turret_driver_think (edict_t *self)
        !           288: {
        !           289:        vec3_t  target;
        !           290:        vec3_t  dir;
        !           291:        float   reaction_time;
        !           292: 
        !           293:        self->nextthink = level.time + FRAMETIME;
        !           294: 
        !           295:        if (self->enemy && (!self->enemy->inuse || self->enemy->health <= 0))
        !           296:                self->enemy = NULL;
        !           297: 
        !           298:        if (!self->enemy)
        !           299:        {
        !           300:                if (!FindTarget (self))
        !           301:                        return;
        !           302:                self->monsterinfo.trail_time = level.time;
        !           303:                self->monsterinfo.aiflags &= ~AI_LOST_SIGHT;
        !           304:        }
        !           305:        else
        !           306:        {
        !           307:                if (visible (self, self->enemy))
        !           308:                {
        !           309:                        if (self->monsterinfo.aiflags & AI_LOST_SIGHT)
        !           310:                        {
        !           311:                                self->monsterinfo.trail_time = level.time;
        !           312:                                self->monsterinfo.aiflags &= ~AI_LOST_SIGHT;
        !           313:                        }
        !           314:                }
        !           315:                else
        !           316:                {
        !           317:                        self->monsterinfo.aiflags |= AI_LOST_SIGHT;
        !           318:                        return;
        !           319:                }
        !           320:        }
        !           321: 
        !           322:        // let the turret know where we want it to aim
        !           323:        VectorCopy (self->enemy->s.origin, target);
        !           324:        target[2] += self->enemy->viewheight;
        !           325:        VectorSubtract (target, self->target_ent->s.origin, dir);
        !           326:        vectoangles (dir, self->target_ent->move_angles);
        !           327: 
        !           328:        // decide if we should shoot
        !           329:        if (level.time < self->monsterinfo.attack_finished)
        !           330:                return;
        !           331: 
        !           332:        reaction_time = (3 - skill->value) * 1.0;
        !           333:        if ((level.time - self->monsterinfo.trail_time) < reaction_time)
        !           334:                return;
        !           335: 
        !           336:        self->monsterinfo.attack_finished = level.time + reaction_time + 1.0;
        !           337:        //FIXME how do we really want to pass this along?
        !           338:        self->target_ent->spawnflags |= 65536;
        !           339: }
        !           340: 
        !           341: void turret_driver_link (edict_t *self)
        !           342: {
        !           343:        vec3_t  vec;
        !           344:        edict_t *ent;
        !           345: 
        !           346:        self->think = turret_driver_think;
        !           347:        self->nextthink = level.time + FRAMETIME;
        !           348: 
        !           349:        self->target_ent = G_PickTarget (self->target);
        !           350:        self->target_ent->owner = self;
        !           351:        self->target_ent->teammaster->owner = self;
        !           352:        VectorCopy (self->target_ent->s.angles, self->s.angles);
        !           353: 
        !           354:        vec[0] = self->target_ent->s.origin[0] - self->s.origin[0];
        !           355:        vec[1] = self->target_ent->s.origin[1] - self->s.origin[1];
        !           356:        vec[2] = 0;
        !           357:        self->move_origin[0] = VectorLength(vec);
        !           358: 
        !           359:        VectorSubtract (self->s.origin, self->target_ent->s.origin, vec);
        !           360:        vectoangles (vec, vec);
        !           361:        AnglesNormalize(vec);
        !           362:        self->move_origin[1] = vec[1];
        !           363: 
        !           364:        self->move_origin[2] = self->s.origin[2] - self->target_ent->s.origin[2];
        !           365: 
        !           366:        // add the driver to the end of them team chain
        !           367:        for (ent = self->target_ent->teammaster; ent->teamchain; ent = ent->teamchain)
        !           368:                ;
        !           369:        ent->teamchain = self;
        !           370:        self->teammaster = self->target_ent->teammaster;
        !           371:        self->flags |= FL_TEAMSLAVE;
        !           372: }
        !           373: 
        !           374: void SP_turret_driver (edict_t *self)
        !           375: {
        !           376:        if (deathmatch->value)
        !           377:        {
        !           378:                G_FreeEdict (self);
        !           379:                return;
        !           380:        }
        !           381: 
        !           382:        self->movetype = MOVETYPE_PUSH;
        !           383:        self->solid = SOLID_BBOX;
        !           384:        self->s.modelindex = gi.modelindex("models/monsters/infantry/tris.md2");
        !           385:        VectorSet (self->mins, -16, -16, -24);
        !           386:        VectorSet (self->maxs, 16, 16, 32);
        !           387: 
        !           388:        self->health = 100;
        !           389:        self->gib_health = 0;
        !           390:        self->mass = 200;
        !           391:        self->viewheight = 24;
        !           392: 
        !           393:        self->die = turret_driver_die;
        !           394:        self->monsterinfo.stand = infantry_stand;
        !           395: 
        !           396:        self->flags |= FL_NO_KNOCKBACK;
        !           397: 
        !           398:        level.total_monsters++;
        !           399: 
        !           400:        self->svflags |= SVF_MONSTER;
        !           401:        self->s.renderfx |= RF_FRAMELERP;
        !           402:        self->takedamage = DAMAGE_AIM;
        !           403:        self->use = monster_use;
        !           404:        self->clipmask = MASK_MONSTERSOLID;
        !           405:        VectorCopy (self->s.origin, self->s.old_origin);
        !           406:        self->monsterinfo.aiflags |= AI_STAND_GROUND|AI_DUCKED;
        !           407: 
        !           408:        if (st.item)
        !           409:        {
        !           410:                self->item = FindItemByClassname (st.item);
        !           411:                if (!self->item)
        !           412:                        gi.dprintf("%s at %s has bad item: %s\n", self->classname, vtos(self->s.origin), st.item);
        !           413:        }
        !           414: 
        !           415:        self->think = turret_driver_link;
        !           416:        self->nextthink = level.time + FRAMETIME;
        !           417: 
        !           418:        gi.linkentity (self);
        !           419: }
        !           420: 
        !           421: //============
        !           422: // ROGUE
        !           423: 
        !           424: // invisible turret drivers so we can have unmanned turrets.
        !           425: // originally designed to shoot at func_trains and such, so they
        !           426: // fire at the center of the bounding box, rather than the entity's
        !           427: // origin.
        !           428: 
        !           429: void turret_brain_think (edict_t *self)
        !           430: {
        !           431:        vec3_t  target;
        !           432:        vec3_t  dir;
        !           433:        vec3_t  endpos;
        !           434:        float   reaction_time;
        !           435:        trace_t trace;
        !           436: 
        !           437:        self->nextthink = level.time + FRAMETIME;
        !           438: 
        !           439:        if (self->enemy)
        !           440:        {
        !           441:                if(!self->enemy->inuse)
        !           442:                        self->enemy = NULL;
        !           443:                else if(self->enemy->takedamage && self->enemy->health <= 0)
        !           444:                        self->enemy = NULL;
        !           445:        }
        !           446: 
        !           447:        if (!self->enemy)
        !           448:        {
        !           449:                if (!FindTarget (self))
        !           450:                        return;
        !           451:                self->monsterinfo.trail_time = level.time;
        !           452:                self->monsterinfo.aiflags &= ~AI_LOST_SIGHT;
        !           453:        }
        !           454:        else
        !           455:        {
        !           456:                VectorAdd (self->enemy->absmax, self->enemy->absmin, endpos);
        !           457:                VectorScale (endpos, 0.5, endpos);
        !           458: 
        !           459:                trace = gi.trace (self->target_ent->s.origin, vec3_origin, vec3_origin, endpos, self->target_ent, MASK_SHOT);
        !           460:                if(trace.fraction == 1 || trace.ent == self->enemy)
        !           461:                {
        !           462:                        if (self->monsterinfo.aiflags & AI_LOST_SIGHT)
        !           463:                        {
        !           464:                                self->monsterinfo.trail_time = level.time;
        !           465:                                self->monsterinfo.aiflags &= ~AI_LOST_SIGHT;
        !           466:                        }
        !           467:                }
        !           468:                else
        !           469:                {
        !           470:                        self->monsterinfo.aiflags |= AI_LOST_SIGHT;
        !           471:                        return;
        !           472:                }
        !           473:        }
        !           474: 
        !           475:        // let the turret know where we want it to aim
        !           476:        VectorCopy (endpos, target);
        !           477:        VectorSubtract (target, self->target_ent->s.origin, dir);
        !           478:        vectoangles (dir, self->target_ent->move_angles);
        !           479: 
        !           480:        // decide if we should shoot
        !           481:        if (level.time < self->monsterinfo.attack_finished)
        !           482:                return;
        !           483: 
        !           484:        if(self->delay)
        !           485:                reaction_time = self->delay;
        !           486:        else
        !           487:                reaction_time = (3 - skill->value) * 1.0;
        !           488:        if ((level.time - self->monsterinfo.trail_time) < reaction_time)
        !           489:                return;
        !           490: 
        !           491:        self->monsterinfo.attack_finished = level.time + reaction_time + 1.0;
        !           492:        //FIXME how do we really want to pass this along?
        !           493:        self->target_ent->spawnflags |= 65536;
        !           494: }
        !           495: 
        !           496: // =================
        !           497: // =================
        !           498: void turret_brain_link (edict_t *self)
        !           499: {
        !           500:        vec3_t  vec;
        !           501:        edict_t *ent;
        !           502: 
        !           503:        if (self->killtarget)
        !           504:        {
        !           505:                self->enemy = G_PickTarget (self->killtarget);
        !           506:        }
        !           507: 
        !           508:        self->think = turret_brain_think;
        !           509:        self->nextthink = level.time + FRAMETIME;
        !           510: 
        !           511:        self->target_ent = G_PickTarget (self->target);
        !           512:        self->target_ent->owner = self;
        !           513:        self->target_ent->teammaster->owner = self;
        !           514:        VectorCopy (self->target_ent->s.angles, self->s.angles);
        !           515: 
        !           516:        vec[0] = self->target_ent->s.origin[0] - self->s.origin[0];
        !           517:        vec[1] = self->target_ent->s.origin[1] - self->s.origin[1];
        !           518:        vec[2] = 0;
        !           519:        self->move_origin[0] = VectorLength(vec);
        !           520: 
        !           521:        VectorSubtract (self->s.origin, self->target_ent->s.origin, vec);
        !           522:        vectoangles (vec, vec);
        !           523:        AnglesNormalize(vec);
        !           524:        self->move_origin[1] = vec[1];
        !           525: 
        !           526:        self->move_origin[2] = self->s.origin[2] - self->target_ent->s.origin[2];
        !           527: 
        !           528:        // add the driver to the end of them team chain
        !           529:        for (ent = self->target_ent->teammaster; ent->teamchain; ent = ent->teamchain)
        !           530:                ;
        !           531:        ent->teamchain = self;
        !           532:        self->teammaster = self->target_ent->teammaster;
        !           533:        self->flags |= FL_TEAMSLAVE;
        !           534: }
        !           535: 
        !           536: // =================
        !           537: // =================
        !           538: void turret_brain_deactivate (edict_t *self, edict_t *other, edict_t *activator)
        !           539: {
        !           540:        self->think = NULL;
        !           541:        self->nextthink = 0;
        !           542: }
        !           543: 
        !           544: // =================
        !           545: // =================
        !           546: void turret_brain_activate (edict_t *self, edict_t *other, edict_t *activator)
        !           547: {
        !           548:        if (!self->enemy)
        !           549:        {
        !           550:                self->enemy = activator;
        !           551:        }
        !           552: 
        !           553:        // wait at least 3 seconds to fire.
        !           554:        self->monsterinfo.attack_finished = level.time + 3;
        !           555:        self->use = turret_brain_deactivate;
        !           556: 
        !           557:        self->think = turret_brain_link;
        !           558:        self->nextthink = level.time + FRAMETIME;
        !           559: }
        !           560: 
        !           561: /*QUAKED turret_invisible_brain (1 .5 0) (-16 -16 -16) (16 16 16)
        !           562: Invisible brain to drive the turret.
        !           563: 
        !           564: Does not search for targets. If targeted, can only be turned on once
        !           565: and then off once. After that they are completely disabled.
        !           566: 
        !           567: "delay" the delay between firing (default ramps for skill level)
        !           568: "Target" the turret breach
        !           569: "Killtarget" the item you want it to attack.
        !           570: Target the brain if you want it activated later, instead of immediately. It will wait 3 seconds
        !           571: before firing to acquire the target.
        !           572: */
        !           573: void SP_turret_invisible_brain (edict_t *self)
        !           574: {
        !           575:        if (!self->killtarget)
        !           576:        {
        !           577:                gi.dprintf("turret_invisible_brain with no killtarget!\n");
        !           578:                G_FreeEdict (self);
        !           579:                return;
        !           580:        }
        !           581:        if (!self->target)
        !           582:        {
        !           583:                gi.dprintf("turret_invisible_brain with no target!\n");
        !           584:                G_FreeEdict (self);
        !           585:                return;
        !           586:        }
        !           587: 
        !           588:        if (self->targetname)
        !           589:        {
        !           590:                self->use = turret_brain_activate;
        !           591:        }
        !           592:        else
        !           593:        {
        !           594:                self->think = turret_brain_link;
        !           595:                self->nextthink = level.time + FRAMETIME;
        !           596:        }
        !           597: 
        !           598:        self->movetype = MOVETYPE_PUSH;
        !           599:        gi.linkentity (self);
        !           600: }
        !           601: 
        !           602: // ROGUE
        !           603: //============

unix.superglobalmegacorp.com

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