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

1.1     ! root        1: // g_sphere.c
        !             2: // pmack
        !             3: // april 1998
        !             4: 
        !             5: // defender - actively finds and shoots at enemies
        !             6: // hunter - waits until < 25% health and vore ball tracks person who hurt you
        !             7: // vengeance - kills person who killed you.
        !             8: 
        !             9: #include "g_local.h"
        !            10: 
        !            11: #define DEFENDER_LIFESPAN      30
        !            12: #define HUNTER_LIFESPAN                30
        !            13: #define VENGEANCE_LIFESPAN     30
        !            14: #define MINIMUM_FLY_TIME       15
        !            15: //#define MINIMUM_FLY_TIME     30
        !            16: 
        !            17: // FIXME - do we need to be calling ED_NewString at all?
        !            18: extern char *ED_NewString (char *string);
        !            19: void LookAtKiller (edict_t *self, edict_t *inflictor, edict_t *attacker);
        !            20: 
        !            21: 
        !            22: void defender_think (edict_t *self);
        !            23: void hunter_think (edict_t *self);
        !            24: void vengeance_think (edict_t *self);
        !            25: void vengeance_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf);
        !            26: void hunter_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf);
        !            27: 
        !            28: // *************************
        !            29: // General Sphere Code
        !            30: // *************************
        !            31: 
        !            32: // =================
        !            33: // =================
        !            34: void sphere_think_explode (edict_t *self)
        !            35: {
        !            36:        if(self->owner && self->owner->client)
        !            37:        {
        !            38:                self->owner->client->owned_sphere = NULL;
        !            39:        }
        !            40:        BecomeExplosion1 (self);
        !            41: }
        !            42: 
        !            43: // =================
        !            44: // sphere_explode
        !            45: // =================
        !            46: void sphere_explode (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
        !            47: {
        !            48: //     if(self->owner && self->owner->client)
        !            49: //             gi.cprintf(self->owner, PRINT_HIGH, "Sphere timed out\n");
        !            50: //     gi.dprintf("player died, blowing up\n");
        !            51:        sphere_think_explode (self);
        !            52: }
        !            53: 
        !            54: // =================
        !            55: // sphere_if_idle_die - if the sphere is not currently attacking, blow up.
        !            56: // =================
        !            57: void sphere_if_idle_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
        !            58: {
        !            59:        if(!self->enemy)
        !            60:        {
        !            61: //             gi.dprintf("player died, blowing up\n");
        !            62:                sphere_think_explode(self);
        !            63:        }
        !            64: }
        !            65: 
        !            66: // *************************
        !            67: // Sphere Movement
        !            68: // *************************
        !            69: 
        !            70: // =================
        !            71: // =================
        !            72: void sphere_fly (edict_t *self)
        !            73: {
        !            74:        vec3_t  dest;
        !            75:        vec3_t  dir;
        !            76: 
        !            77:        if(level.time >= self->wait)
        !            78:        {
        !            79: //             gi.dprintf("fly: timed out\n");
        !            80:                sphere_think_explode(self);
        !            81:                return;
        !            82:        }
        !            83: 
        !            84:        VectorCopy (self->owner->s.origin, dest);
        !            85:        dest[2] = self->owner->absmax[2] + 4;
        !            86: 
        !            87:        if(level.time == (float)(int)level.time)
        !            88:        {
        !            89:                if(!visible(self, self->owner))
        !            90:                {
        !            91:                        VectorCopy(dest, self->s.origin);
        !            92:                        gi.linkentity(self);
        !            93:                        return;
        !            94:                }
        !            95:        }
        !            96: 
        !            97:        VectorSubtract (dest, self->s.origin, dir);
        !            98:        VectorScale (dir, 5, self->velocity);
        !            99: }
        !           100: 
        !           101: // =================
        !           102: // =================
        !           103: void sphere_chase (edict_t *self, int stupidChase)
        !           104: {
        !           105:        vec3_t  dest;
        !           106:        vec3_t  dir;
        !           107:        float   dist;
        !           108: 
        !           109:        if(level.time >= self->wait || (self->enemy && self->enemy->health < 1))
        !           110:        {
        !           111:                sphere_think_explode(self);
        !           112:                return;
        !           113:        }
        !           114: 
        !           115:        VectorCopy (self->enemy->s.origin, dest);
        !           116:        if(self->enemy->client)
        !           117:                dest[2] += self->enemy->viewheight;
        !           118: 
        !           119:        if(visible(self, self->enemy) || stupidChase)
        !           120:        {
        !           121:                VectorSubtract (dest, self->s.origin, dir);
        !           122:                VectorNormalize (dir);
        !           123:                vectoangles2(dir, self->s.angles);
        !           124:                VectorScale (dir, 500, self->velocity);
        !           125:                VectorCopy(dest, self->monsterinfo.saved_goal);
        !           126:        }
        !           127:        else if (VectorCompare (self->monsterinfo.saved_goal, vec3_origin))
        !           128:        {
        !           129:                VectorClear (self->velocity);
        !           130:        }
        !           131:        else
        !           132:        {
        !           133:                VectorSubtract(self->monsterinfo.saved_goal, self->s.origin, dir);
        !           134:                dist = VectorNormalize(dir);
        !           135:                vectoangles2(dir, self->s.angles);
        !           136:                if(dist)
        !           137:                {
        !           138:                        if(dist > 500)                  
        !           139:                                VectorScale(dir, 500, self->velocity);
        !           140:                        else
        !           141:                                VectorScale(dir, dist, self->velocity);
        !           142:                }
        !           143:                else
        !           144:                        VectorClear(self->velocity);
        !           145:        }
        !           146: }
        !           147: 
        !           148: // *************************
        !           149: // Attack related stuff
        !           150: // *************************
        !           151: 
        !           152: // =================
        !           153: // =================
        !           154: void sphere_fire (edict_t *self, edict_t *enemy)
        !           155: {
        !           156:        vec3_t  dest;
        !           157:        vec3_t  dir;
        !           158: 
        !           159:        if(level.time >= self->wait || !enemy)
        !           160:        {
        !           161:                sphere_think_explode(self);
        !           162:                return;
        !           163:        }
        !           164: 
        !           165:        VectorCopy (enemy->s.origin, dest);
        !           166:        self->s.effects |= EF_ROCKET;
        !           167: 
        !           168:        VectorSubtract (dest, self->s.origin, dir);
        !           169:        VectorNormalize (dir);
        !           170:        vectoangles2 ( dir, self->s.angles );
        !           171:        VectorScale (dir, 1000, self->velocity);
        !           172: 
        !           173:        self->touch = vengeance_touch;
        !           174:        self->think = sphere_think_explode;
        !           175:        self->nextthink = self->wait;
        !           176: }
        !           177: 
        !           178: // =================
        !           179: // =================
        !           180: void sphere_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf, int mod)
        !           181: {
        !           182:        if(self->spawnflags & SPHERE_DOPPLEGANGER)
        !           183:        {
        !           184:                if (other == self->teammaster)
        !           185:                        return;
        !           186: 
        !           187:                self->takedamage = DAMAGE_NO;
        !           188:                self->owner = self->teammaster;
        !           189:                self->teammaster = NULL;
        !           190:        }
        !           191:        else
        !           192:        {
        !           193:                if (other == self->owner)
        !           194:                        return;
        !           195:                // PMM - don't blow up on bodies
        !           196:                if (!strcmp(other->classname, "bodyque"))
        !           197:                        return;
        !           198:        }
        !           199: 
        !           200:        if (surf && (surf->flags & SURF_SKY))
        !           201:        {
        !           202:                G_FreeEdict (self);
        !           203:                return;
        !           204:        }
        !           205: 
        !           206:        if (other->takedamage)
        !           207:        {
        !           208:                T_Damage (other, self, self->owner, self->velocity, self->s.origin, plane->normal,
        !           209:                        10000, 1, DAMAGE_DESTROY_ARMOR, mod);
        !           210:        }
        !           211:        else
        !           212:        {
        !           213:                T_RadiusDamage (self, self->owner, 512, self->owner, 256, mod);
        !           214:        }
        !           215: 
        !           216:        sphere_think_explode (self);
        !           217: }
        !           218: 
        !           219: // =================
        !           220: // =================
        !           221: void vengeance_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
        !           222: {
        !           223:        if(self->spawnflags & SPHERE_DOPPLEGANGER)
        !           224:                sphere_touch (self, other, plane, surf, MOD_DOPPLE_VENGEANCE);
        !           225:        else
        !           226:                sphere_touch (self, other, plane, surf, MOD_VENGEANCE_SPHERE);
        !           227: }
        !           228: 
        !           229: // =================
        !           230: // =================
        !           231: void hunter_touch (edict_t *self, edict_t *other, cplane_t *plane, csurface_t *surf)
        !           232: {
        !           233:        edict_t *owner;
        !           234: 
        !           235:        // don't blow up if you hit the world.... sheesh.
        !           236:        if(other==world)
        !           237:                return;
        !           238: 
        !           239:        if(self->owner)
        !           240:        {
        !           241:                // if owner is flying with us, make sure they stop too.
        !           242:                owner=self->owner;
        !           243:                if(owner->flags & FL_SAM_RAIMI)
        !           244:                {
        !           245:                        VectorClear(owner->velocity);
        !           246:                        owner->movetype = MOVETYPE_NONE;
        !           247:                        gi.linkentity(owner);
        !           248:                }
        !           249:        }
        !           250: 
        !           251:        if(self->spawnflags & SPHERE_DOPPLEGANGER)
        !           252:                sphere_touch (self, other, plane, surf, MOD_DOPPLE_HUNTER);
        !           253:        else
        !           254:                sphere_touch (self, other, plane, surf, MOD_HUNTER_SPHERE);
        !           255: }
        !           256: 
        !           257: // =================
        !           258: // =================
        !           259: void defender_shoot (edict_t *self, edict_t *enemy)
        !           260: {
        !           261:        vec3_t  dir;
        !           262:        vec3_t  start;
        !           263: 
        !           264:        if(!(enemy->inuse) || enemy->health <= 0)
        !           265:                return;
        !           266: 
        !           267:        if(enemy == self->owner)
        !           268:                return;
        !           269: 
        !           270:        VectorSubtract (enemy->s.origin, self->s.origin, dir);
        !           271:        VectorNormalize (dir);
        !           272: 
        !           273:        if(self->monsterinfo.attack_finished > level.time)
        !           274:                return;
        !           275: 
        !           276:        if(!visible(self, self->enemy))
        !           277:                return;
        !           278: 
        !           279:        VectorCopy(self->s.origin, start);
        !           280:        start[2] += 2;
        !           281:        fire_blaster2 (self->owner, start, dir, 10, 1000, EF_BLASTER, 0);
        !           282: 
        !           283:        self->monsterinfo.attack_finished = level.time + 0.4;
        !           284: }
        !           285: 
        !           286: // *************************
        !           287: // Activation Related Stuff
        !           288: // *************************
        !           289: 
        !           290: // =================
        !           291: // =================
        !           292: void body_gib (edict_t *self)
        !           293: {
        !           294:        int             n;
        !           295: 
        !           296:        gi.sound (self, CHAN_BODY, gi.soundindex ("misc/udeath.wav"), 1, ATTN_NORM, 0);
        !           297:        for (n= 0; n < 4; n++)
        !           298:                ThrowGib (self, "models/objects/gibs/sm_meat/tris.md2", 50, GIB_ORGANIC);
        !           299:        ThrowGib (self, "models/objects/gibs/skull/tris.md2", 50, GIB_ORGANIC);
        !           300: }
        !           301: 
        !           302: // =================
        !           303: // =================
        !           304: void hunter_pain (edict_t *self, edict_t *other, float kick, int damage)
        !           305: {
        !           306:        edict_t *owner;
        !           307:        float   dist;
        !           308:        vec3_t  dir;
        !           309: 
        !           310:        if(self->enemy)
        !           311:                return;
        !           312: 
        !           313:        owner = self->owner;
        !           314: 
        !           315:        if(!(self->spawnflags & SPHERE_DOPPLEGANGER))
        !           316:        {
        !           317:                if(owner && (owner->health > 0))
        !           318:                        return;
        !           319: 
        !           320:                //PMM
        !           321:                if(other == owner)
        !           322:                {
        !           323: //                     if ((g_showlogic) && (g_showlogic->value))
        !           324: //                             gi.dprintf ("hunter: won't get mad at my owner!\n");
        !           325:                        return;
        !           326:                }
        !           327:                //pmm
        !           328:        }
        !           329:        else
        !           330:        {
        !           331:                // if fired by a doppleganger, set it to 10 second timeout
        !           332:                self->wait = level.time + MINIMUM_FLY_TIME;
        !           333:        }
        !           334: 
        !           335:        if((self->wait - level.time) < MINIMUM_FLY_TIME)
        !           336:                self->wait = level.time + MINIMUM_FLY_TIME;
        !           337:        self->s.effects |= EF_BLASTER | EF_TRACKER;
        !           338:        self->touch = hunter_touch;
        !           339:        self->enemy = other;
        !           340: 
        !           341:        if(g_showlogic && g_showlogic->value)
        !           342:                gi.dprintf("hunter_pain: mad at %s\n", other->classname);
        !           343: 
        !           344:        // if we're not owned by a player, no sam raimi
        !           345:        // if we're spawned by a doppleganger, no sam raimi
        !           346:        if((self->spawnflags & SPHERE_DOPPLEGANGER)  || !(owner && owner->client))              
        !           347:                return;
        !           348: 
        !           349:        // sam raimi cam is disabled if FORCE_RESPAWN is set.
        !           350:        // sam raimi cam is also disabled if huntercam->value is 0.
        !           351:        if(!((int)dmflags->value & DF_FORCE_RESPAWN) && (huntercam && (huntercam->value)))
        !           352:        {
        !           353:                VectorSubtract(other->s.origin, self->s.origin, dir);
        !           354:                dist=VectorLength(dir);
        !           355: 
        !           356:                if(owner && (dist >= 192))
        !           357:                {
        !           358:                        // detach owner from body and send him flying
        !           359:                        owner->movetype = MOVETYPE_FLYMISSILE;
        !           360: 
        !           361:                        // gib like we just died, even though we didn't, really.
        !           362:                        body_gib(owner);
        !           363: 
        !           364:                        // move the sphere to the owner's current viewpoint.
        !           365:                        // we know it's a valid spot (or will be momentarily)
        !           366:                        VectorCopy(owner->s.origin, self->s.origin);
        !           367:                        self->s.origin[2] += owner->viewheight;
        !           368: 
        !           369:                        // move the player's origin to the sphere's new origin
        !           370:                        VectorCopy(self->s.origin, owner->s.origin);
        !           371:                        VectorCopy(self->s.angles, owner->s.angles);
        !           372:                        VectorCopy(self->s.angles, owner->client->v_angle);
        !           373:                        VectorClear(owner->mins);
        !           374:                        VectorClear(owner->maxs);
        !           375:                        VectorSet(owner->mins, -5, -5, -5);
        !           376:                        VectorSet(owner->maxs, 5, 5, 5);
        !           377:                        owner->client->ps.fov = 140;
        !           378:                        owner->s.modelindex = 0;
        !           379:                        owner->s.modelindex2 = 0;
        !           380:                        owner->viewheight = 8;
        !           381:                        owner->solid = SOLID_NOT;
        !           382:                        owner->flags |= FL_SAM_RAIMI;
        !           383:                        gi.linkentity(owner);
        !           384: 
        !           385:                        // PMM - set bounding box so we don't clip out of world
        !           386: //                     VectorSet(self->mins, -5, -5, -5);
        !           387: //                     VectorSet(self->maxs, 5, 5, 5);
        !           388:                        self->solid = SOLID_BBOX;
        !           389:                        gi.linkentity (self);
        !           390:                }
        !           391: //             else
        !           392: //                     gi.dprintf("too close for sam raimi cam\n");
        !           393:        }
        !           394: }
        !           395: 
        !           396: // =================
        !           397: // =================
        !           398: void defender_pain (edict_t *self, edict_t *other, float kick, int damage)
        !           399: {
        !           400:        //PMM
        !           401:        if(other == self->owner)
        !           402:        {
        !           403: //             if ((g_showlogic) && (g_showlogic->value))
        !           404: //                     gi.dprintf ("defender: won't get mad at my owner!\n");
        !           405:                return;
        !           406:        }
        !           407:        //pmm
        !           408:        self->enemy = other;
        !           409: }
        !           410: 
        !           411: // =================
        !           412: // =================
        !           413: void vengeance_pain (edict_t *self, edict_t *other, float kick, int damage)
        !           414: {
        !           415:        if(self->enemy)
        !           416:                return;
        !           417: 
        !           418:        if(!(self->spawnflags & SPHERE_DOPPLEGANGER))
        !           419:        {
        !           420:                if(self->owner->health >= 25)
        !           421:                        return;
        !           422: 
        !           423:                //PMM
        !           424:                if(other == self->owner)
        !           425:                {
        !           426:        //              if ((g_showlogic) && (g_showlogic->value))
        !           427:        //                      gi.dprintf ("vengeance: won't get mad at my owner!\n");
        !           428:                        return;
        !           429:                }
        !           430:                //pmm
        !           431:        }
        !           432:        else
        !           433:        {
        !           434:                self->wait = level.time + MINIMUM_FLY_TIME;
        !           435:        }
        !           436: 
        !           437:        if((self->wait - level.time) < MINIMUM_FLY_TIME)
        !           438:                self->wait = level.time + MINIMUM_FLY_TIME;
        !           439:        self->s.effects |= EF_ROCKET;
        !           440:        self->touch = vengeance_touch;
        !           441:        self->enemy = other;
        !           442: }
        !           443: 
        !           444: // *************************
        !           445: // Think Functions
        !           446: // *************************
        !           447: 
        !           448: // ===================
        !           449: // ===================
        !           450: void defender_think (edict_t *self)
        !           451: {
        !           452:        if(!self->owner)
        !           453:        {
        !           454: //             gi.dprintf("think: no owner\n");
        !           455:                G_FreeEdict(self);
        !           456:                return;
        !           457:        }
        !           458: 
        !           459:        if(self->owner->health <=0)
        !           460:        {
        !           461:                sphere_think_explode(self);
        !           462:                return;
        !           463:        }
        !           464: 
        !           465:        if(level.time - self->timestamp > 1)
        !           466:        {
        !           467:                gi.sound (self, CHAN_VOICE, gi.soundindex ("powerup/dsphere.wav"), 0.6, ATTN_NORM, 0);
        !           468:                self->timestamp = level.time;
        !           469:        }
        !           470: 
        !           471:        self->s.frame++;
        !           472:        if(self->s.frame>19)
        !           473:                self->s.frame = 0;
        !           474: 
        !           475:        if(self->enemy)
        !           476:        {
        !           477:                if(self->enemy->health > 0)
        !           478:                {
        !           479: //                     gi.dprintf( "shooting at %s\n", self->enemy->classname);
        !           480:                        defender_shoot (self, self->enemy);
        !           481:                }
        !           482:                else
        !           483:                        self->enemy = NULL;
        !           484:        }
        !           485: //     else
        !           486: //     {
        !           487: //             self->ideal_yaw+=3;
        !           488: //             M_ChangeYaw (self);
        !           489: //     }
        !           490: 
        !           491:        sphere_fly (self);
        !           492: 
        !           493:        if(self->inuse)
        !           494:                self->nextthink = level.time + 0.1;
        !           495: }
        !           496: 
        !           497: // =================
        !           498: // =================
        !           499: void hunter_think (edict_t *self)
        !           500: {
        !           501:        edict_t *owner;
        !           502:        vec3_t  dir, ang;
        !           503: 
        !           504: 
        !           505:        owner = self->owner;
        !           506:        if(!owner && !(self->spawnflags & SPHERE_DOPPLEGANGER))
        !           507:        {
        !           508: //             gi.dprintf("think: no owner\n");
        !           509:                G_FreeEdict(self);
        !           510:                return;
        !           511:        }
        !           512: 
        !           513:        if(owner)
        !           514:                self->ideal_yaw = owner->s.angles[YAW];
        !           515:        else if(self->enemy)            // fired by doppleganger
        !           516:        {
        !           517:                VectorSubtract(self->enemy->s.origin, self->s.origin, dir);
        !           518:                vectoangles2(dir, ang);
        !           519:                self->ideal_yaw = ang[YAW];
        !           520:        }
        !           521: 
        !           522:        M_ChangeYaw(self);
        !           523: 
        !           524:        if(level.time - self->timestamp > 1)
        !           525:        {
        !           526:                gi.sound (self, CHAN_VOICE, gi.soundindex ("powerup/hsphere.wav"), 0.5, ATTN_NORM, 0);
        !           527:                self->timestamp = level.time;
        !           528:        }
        !           529: 
        !           530:        if(self->enemy)
        !           531:        {
        !           532:                sphere_chase (self, 0);
        !           533: 
        !           534:                // deal with sam raimi cam
        !           535:                if(owner && (owner->flags & FL_SAM_RAIMI)) 
        !           536:                {
        !           537:                        if(self->inuse)
        !           538:                        {
        !           539:                                owner->movetype = MOVETYPE_FLYMISSILE;
        !           540: //                             VectorCopy(self->s.angles, owner->s.angles);
        !           541: //                             VectorCopy(self->s.angles, owner->client->v_angle);
        !           542:                                LookAtKiller (owner, self, self->enemy);
        !           543: //                             owner->viewheight = 22;
        !           544: 
        !           545: //                             owner->client->v_angle[YAW]+=5;
        !           546:                                // owner is flying with us, move him too
        !           547:                                owner->movetype = MOVETYPE_FLYMISSILE;
        !           548:                                owner->viewheight = self->s.origin[2] - owner->s.origin[2];
        !           549: //                             VectorCopy(self->s.angles, owner->s.angles);
        !           550: //                             VectorCopy(self->s.angles, owner->client->v_angle);
        !           551:                                VectorCopy(self->s.origin, owner->s.origin);
        !           552:                                VectorCopy(self->velocity, owner->velocity);
        !           553:                                VectorClear(owner->mins);
        !           554:                                VectorClear(owner->maxs);
        !           555:                                gi.linkentity(owner);
        !           556:                        }
        !           557:                        else    // sphere timed out
        !           558:                        {
        !           559:                                VectorClear(owner->velocity);
        !           560:                                owner->movetype = MOVETYPE_NONE;
        !           561:                                gi.linkentity(owner);
        !           562:                        }
        !           563:                }
        !           564:        }
        !           565:        else 
        !           566:        {
        !           567: //             self->ideal_yaw+=3;
        !           568: //             M_ChangeYaw (self);
        !           569:                sphere_fly (self);
        !           570:        }
        !           571: 
        !           572:        if(self->inuse)
        !           573:                self->nextthink = level.time + 0.1;
        !           574: }
        !           575: 
        !           576: // =================
        !           577: // =================
        !           578: void vengeance_think (edict_t *self)
        !           579: {
        !           580:        if(!(self->owner) && !(self->spawnflags & SPHERE_DOPPLEGANGER))
        !           581:        {
        !           582: //             gi.dprintf("think: no owner\n");
        !           583:                G_FreeEdict(self);
        !           584:                return;
        !           585:        }
        !           586: 
        !           587:        if(level.time - self->timestamp > 1)
        !           588:        {
        !           589:                gi.sound (self, CHAN_VOICE, gi.soundindex ("powerup/vsphere.wav"), 0.5, ATTN_NORM, 0);
        !           590:                self->timestamp = level.time;
        !           591:        }
        !           592: 
        !           593:        if(self->enemy)
        !           594:        {
        !           595: //             sphere_fire (self, self->owner->enemy);
        !           596:                sphere_chase (self, 1);
        !           597:        }
        !           598:        else
        !           599:                sphere_fly (self);
        !           600: 
        !           601:        if(self->inuse)
        !           602:                self->nextthink = level.time + 0.1;
        !           603: }
        !           604: 
        !           605: // *************************
        !           606: // Spawning / Creation
        !           607: // *************************
        !           608: 
        !           609: // monsterinfo_t
        !           610: // =================
        !           611: // =================
        !           612: edict_t *Sphere_Spawn (edict_t *owner, int spawnflags)
        !           613: {
        !           614:        edict_t *sphere;
        !           615: 
        !           616:        sphere = G_Spawn();
        !           617:        VectorCopy(owner->s.origin, sphere->s.origin);
        !           618:        sphere->s.origin[2] = owner->absmax[2];
        !           619:        sphere->s.angles[YAW] = owner->s.angles[YAW];
        !           620:        sphere->solid = SOLID_BBOX;
        !           621:        sphere->clipmask = MASK_SHOT;
        !           622:        sphere->s.renderfx = RF_FULLBRIGHT | RF_IR_VISIBLE;
        !           623:        sphere->movetype = MOVETYPE_FLYMISSILE;
        !           624: 
        !           625:        if(spawnflags & SPHERE_DOPPLEGANGER)
        !           626:                sphere->teammaster = owner->teammaster;
        !           627:        else
        !           628:                sphere->owner = owner;
        !           629:        
        !           630:        sphere->classname = "sphere";
        !           631:        sphere->yaw_speed = 40;
        !           632:        sphere->monsterinfo.attack_finished = 0;
        !           633:        sphere->spawnflags = spawnflags;                // need this for the HUD to recognize sphere
        !           634:        //PMM
        !           635:        sphere->takedamage = DAMAGE_NO;
        !           636: 
        !           637:        switch(spawnflags & SPHERE_TYPE)
        !           638:        {
        !           639:                case SPHERE_DEFENDER:
        !           640:                        sphere->s.modelindex = gi.modelindex("models/items/defender/tris.md2");
        !           641:                        sphere->s.modelindex2 = gi.modelindex("models/items/shell/tris.md2") | 0x80;
        !           642:                        sphere->pain = defender_pain;
        !           643:                        sphere->wait = level.time + DEFENDER_LIFESPAN;
        !           644:                        sphere->die = sphere_explode;
        !           645:                        sphere->think = defender_think;
        !           646:                        break;
        !           647:                case SPHERE_HUNTER:
        !           648:                        sphere->s.modelindex = gi.modelindex("models/items/hunter/tris.md2");
        !           649:                        sphere->wait = level.time + HUNTER_LIFESPAN;
        !           650:                        sphere->pain = hunter_pain;
        !           651:                        sphere->die = sphere_if_idle_die;
        !           652:                        sphere->think = hunter_think;
        !           653:                        break;
        !           654:                case SPHERE_VENGEANCE:
        !           655:                        sphere->s.modelindex = gi.modelindex("models/items/vengnce/tris.md2");
        !           656:                        sphere->wait = level.time + VENGEANCE_LIFESPAN;
        !           657:                        sphere->pain = vengeance_pain;
        !           658:                        sphere->die = sphere_if_idle_die;
        !           659:                        sphere->think = vengeance_think;
        !           660:                        VectorSet (sphere->avelocity, 30, 30, 0);
        !           661:                        break;
        !           662:                default:
        !           663:                        gi.dprintf("Tried to create an invalid sphere\n");
        !           664:                        G_FreeEdict(sphere);
        !           665:                        return NULL;
        !           666:        }
        !           667:        
        !           668:        sphere->nextthink = level.time + 0.1;
        !           669: 
        !           670:        gi.linkentity (sphere);
        !           671: 
        !           672:        return sphere;
        !           673: }
        !           674: 
        !           675: // =================
        !           676: // Own_Sphere - attach the sphere to the client so we can 
        !           677: //             directly access it later
        !           678: // =================
        !           679: void Own_Sphere (edict_t *self, edict_t *sphere)
        !           680: {
        !           681:        if(!sphere)
        !           682:                return;
        !           683: 
        !           684:        // ownership only for players   
        !           685:        if(self->client)
        !           686:        {
        !           687:                // if they don't have one
        !           688:                if(!(self->client->owned_sphere))
        !           689:                {
        !           690:                        self->client->owned_sphere = sphere;
        !           691:                }
        !           692:                // they already have one, take care of the old one
        !           693:                else
        !           694:                {
        !           695:                        if(self->client->owned_sphere->inuse)
        !           696:                        {
        !           697:                                G_FreeEdict(self->client->owned_sphere);
        !           698:                                self->client->owned_sphere = sphere;
        !           699:                        }
        !           700:                        else
        !           701:                        {
        !           702:                                self->client->owned_sphere = sphere;
        !           703:                        }
        !           704:                }
        !           705:        }
        !           706: }
        !           707: 
        !           708: // =================
        !           709: // =================
        !           710: void Defender_Launch (edict_t *self)
        !           711: {
        !           712:        edict_t         *sphere;
        !           713: 
        !           714:        sphere = Sphere_Spawn (self, SPHERE_DEFENDER);  
        !           715:        Own_Sphere (self, sphere);
        !           716: }
        !           717: 
        !           718: // =================
        !           719: // =================
        !           720: void Hunter_Launch (edict_t *self)
        !           721: {
        !           722:        edict_t         *sphere;
        !           723: 
        !           724:        sphere = Sphere_Spawn (self, SPHERE_HUNTER);    
        !           725:        Own_Sphere (self, sphere);
        !           726: }
        !           727: 
        !           728: // =================
        !           729: // =================
        !           730: void Vengeance_Launch (edict_t *self)
        !           731: {
        !           732:        edict_t         *sphere;
        !           733: 
        !           734:        sphere = Sphere_Spawn (self, SPHERE_VENGEANCE); 
        !           735:        Own_Sphere (self, sphere);
        !           736: }

unix.superglobalmegacorp.com

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