Annotation of quake2/rogue/g_sphere.c, revision 1.1.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.