Annotation of quake2/rogue/g_newdm.c, revision 1.1.1.1

1.1       root        1: // g_newdm.c
                      2: // pmack
                      3: // june 1998
                      4: 
                      5: #include "g_local.h"
                      6: #include "m_player.h"
                      7: 
                      8: dm_game_rt     DMGame;
                      9: 
                     10: // ****************************
                     11: // General DM Stuff
                     12: // ****************************
                     13: 
                     14: void InitGameRules(void)
                     15: {
                     16:        int             gameNum;
                     17: 
                     18:        // clear out the game rule structure before we start
                     19:        memset(&DMGame, 0, sizeof(dm_game_rt));
                     20: 
                     21:        if(gamerules && gamerules->value)
                     22:        {
                     23:                gameNum = gamerules->value;
                     24:                switch(gameNum)
                     25:                {
                     26:                        case RDM_TAG:
                     27:                                DMGame.GameInit = Tag_GameInit;
                     28:                                DMGame.PostInitSetup = Tag_PostInitSetup;
                     29:                                DMGame.PlayerDeath = Tag_PlayerDeath;
                     30:                                DMGame.Score = Tag_Score;
                     31:                                DMGame.PlayerEffects = Tag_PlayerEffects;
                     32:                                DMGame.DogTag = Tag_DogTag;
                     33:                                DMGame.PlayerDisconnect = Tag_PlayerDisconnect;
                     34:                                DMGame.ChangeDamage = Tag_ChangeDamage;
                     35:                                break;
                     36: /*
                     37:                        case RDM_DEATHBALL:
                     38:                                DMGame.GameInit = DBall_GameInit;
                     39:                                DMGame.ChangeKnockback = DBall_ChangeKnockback;
                     40:                                DMGame.ChangeDamage = DBall_ChangeDamage;
                     41:                                DMGame.ClientBegin = DBall_ClientBegin;
                     42:                                DMGame.SelectSpawnPoint = DBall_SelectSpawnPoint;
                     43:                                DMGame.PostInitSetup = DBall_PostInitSetup;
                     44:                                DMGame.CheckDMRules = DBall_CheckDMRules;
                     45:                                break;
                     46: */
                     47:                        // reset gamerules if it's not a valid number
                     48:                        default:
                     49:                                gamerules->value = 0;
                     50:                                break;
                     51:                }
                     52:        }
                     53: 
                     54:        // if we're set up to play, initialize the game as needed.
                     55:        if(DMGame.GameInit)
                     56:                DMGame.GameInit();
                     57: }
                     58: 
                     59: //=================
                     60: //=================
                     61: #define IT_TYPE_MASK   (IT_WEAPON|IT_AMMO|IT_POWERUP|IT_ARMOR|IT_KEY)
                     62: 
                     63: extern void ED_CallSpawn (edict_t *ent);
                     64: extern qboolean Pickup_Health (edict_t *ent, edict_t *other);
                     65: extern qboolean Pickup_Adrenaline (edict_t *ent, edict_t *other);
                     66: extern qboolean Pickup_Armor (edict_t *ent, edict_t *other);
                     67: extern qboolean Pickup_PowerArmor (edict_t *ent, edict_t *other);
                     68: 
                     69: char *FindSubstituteItem (edict_t *ent)
                     70: {
                     71:        int             i;
                     72:        int             itflags, myflags;
                     73:        float   rnd;
                     74:        int             count;
                     75:        int             pick;
                     76:        gitem_t *it;
                     77: 
                     78:        // there are only two classes of power armor, and we don't want
                     79:        // to give out power screens. therefore, power shields should
                     80:        // remain power shields. (powerscreens shouldn't be there at all...)
                     81:        if (ent->item->pickup == Pickup_PowerArmor)
                     82:                return NULL;
                     83: 
                     84:        // health is special case
                     85:        if ((ent->item->pickup == Pickup_Health) ||     (ent->item->pickup == Pickup_Adrenaline))
                     86:        {
                     87:                // health pellets stay health pellets
                     88:                if(!strcmp(ent->classname, "item_health_small"))
                     89:                        return NULL;
                     90: 
                     91:                rnd = random();
                     92:                if(rnd < 0.6)
                     93:                        return "item_health";
                     94:                else if(rnd < 0.9)
                     95:                        return "item_health_large";
                     96:                else if(rnd < 0.99)
                     97:                        return "item_adrenaline";
                     98:                else
                     99:                        return "item_health_mega";
                    100:        }
                    101:        // armor is also special case
                    102:        else if(ent->item->pickup == Pickup_Armor)
                    103:        {
                    104:                // armor shards stay armor shards
                    105:                if (ent->item->tag == ARMOR_SHARD)
                    106:                        return NULL;
                    107: 
                    108:                rnd = random();
                    109:                if(rnd < 0.6)
                    110:                        return "item_armor_jacket";
                    111:                else if(rnd < 0.9)
                    112:                        return "item_armor_combat";
                    113:                else
                    114:                        return "item_armor_body";
                    115:        }
                    116: 
                    117: 
                    118:        // we want to stay within the item class
                    119:        myflags = ent->item->flags & IT_TYPE_MASK;
                    120:        if ((myflags & IT_AMMO) && (myflags & IT_WEAPON))
                    121:                        myflags = IT_AMMO;
                    122: 
                    123:        count = 0;
                    124: 
                    125:        // first pass, count the matching items
                    126:        it = itemlist;
                    127:        for (i=0 ; i<game.num_items ; i++, it++)
                    128:        {
                    129:                itflags = it->flags;
                    130:                
                    131:                if (!itflags || (itflags & IT_NOT_GIVEABLE))
                    132:                        continue;
                    133: 
                    134:                // prox,grenades,etc should count as ammo.
                    135:                if ((itflags & IT_AMMO) && (itflags & IT_WEAPON))
                    136:                        itflags = IT_AMMO;
                    137: 
                    138:                if ( ((int)dmflags->value & DF_NO_NUKES) && !strcmp(ent->classname, "ammo_nuke") )
                    139:                        continue;
                    140: 
                    141:                if ( ((int)dmflags->value & DF_NO_MINES) && 
                    142:                                (!strcmp(ent->classname, "ammo_prox") || !strcmp(ent->classname, "ammo_tesla")))
                    143:                        continue;
                    144: 
                    145:                if ((itflags & IT_TYPE_MASK) == (myflags & IT_TYPE_MASK))
                    146:                        count++;
                    147:        }
                    148: 
                    149:        if(!count)
                    150:                return NULL;
                    151: 
                    152:        pick = ceil(random() * count);
                    153:        count = 0;
                    154: 
                    155:        // second pass, pick one.
                    156:        it = itemlist;
                    157:        for (i=0 ; i<game.num_items ; i++, it++)
                    158:        {
                    159:                itflags = it->flags;
                    160:                
                    161:                if (!itflags || (itflags & IT_NOT_GIVEABLE))
                    162:                        continue;
                    163: 
                    164:                // prox,grenades,etc should count as ammo.
                    165:                if ((itflags & IT_AMMO) && (itflags & IT_WEAPON))
                    166:                        itflags = IT_AMMO;
                    167: 
                    168:                if ( ((int)dmflags->value & DF_NO_NUKES) && !strcmp(ent->classname, "ammo_nuke") )
                    169:                        continue;
                    170: 
                    171:                if ( ((int)dmflags->value & DF_NO_MINES) && 
                    172:                                (!strcmp(ent->classname, "ammo_prox") || !strcmp(ent->classname, "ammo_tesla")))
                    173:                        continue;
                    174: 
                    175:                if ((itflags & IT_TYPE_MASK) == (myflags & IT_TYPE_MASK))
                    176:                {
                    177:                        count++;
                    178:                        if(pick == count)
                    179:                                return it->classname;
                    180:                }
                    181:        }
                    182: 
                    183:        return NULL;
                    184: }
                    185: 
                    186: //=================
                    187: //=================
                    188: edict_t *DoRandomRespawn (edict_t *ent)
                    189: {
                    190:        edict_t *newEnt;
                    191:        char    *classname;
                    192:        
                    193:        classname = FindSubstituteItem (ent);
                    194:        if (classname == NULL)
                    195:                return NULL;
                    196: 
                    197:        gi.unlinkentity (ent);
                    198: 
                    199:        newEnt = G_Spawn();
                    200:        newEnt->classname = classname;
                    201:        VectorCopy (ent->s.origin, newEnt->s.origin);
                    202:        VectorCopy (ent->s.old_origin, newEnt->s.old_origin);
                    203:        VectorCopy (ent->mins, newEnt->mins);
                    204:        VectorCopy (ent->maxs, newEnt->maxs);
                    205:        
                    206:        VectorSet (newEnt->gravityVector, 0, 0, -1);
                    207: 
                    208:        ED_CallSpawn (newEnt);
                    209: 
                    210:        newEnt->s.renderfx |= RF_IR_VISIBLE;
                    211: 
                    212:        return newEnt;
                    213: }
                    214: 
                    215: //=================
                    216: //=================
                    217: void PrecacheForRandomRespawn (void)
                    218: {
                    219:        gitem_t *it;
                    220:        int             i;
                    221:        int             itflags;
                    222: 
                    223:        it = itemlist;
                    224:        for (i=0 ; i<game.num_items ; i++, it++)
                    225:        {
                    226:                itflags = it->flags;
                    227:                
                    228:                if (!itflags || (itflags & IT_NOT_GIVEABLE))
                    229:                        continue;
                    230: 
                    231:                PrecacheItem(it);
                    232:        }
                    233: }
                    234: 
                    235: // ***************************
                    236: //  DOPPLEGANGER
                    237: // ***************************
                    238: 
                    239: extern edict_t *Sphere_Spawn (edict_t *owner, int spawnflags);
                    240: 
                    241: void fire_doppleganger (edict_t *ent, vec3_t start, vec3_t aimdir);
                    242: void doppleganger_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point);
                    243: 
                    244: void doppleganger_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
                    245: {
                    246:        edict_t *sphere;
                    247:        float   dist;
                    248:        vec3_t  dir;
                    249: 
                    250:        if((self->enemy) && (self->enemy != self->teammaster))
                    251:        {
                    252:                VectorSubtract(self->enemy->s.origin, self->s.origin, dir);
                    253:                dist = VectorLength(dir);
                    254: 
                    255:                if(dist > 768)
                    256:                {
                    257:                        sphere = Sphere_Spawn (self, SPHERE_HUNTER | SPHERE_DOPPLEGANGER);
                    258:                        sphere->pain(sphere, attacker, 0, 0);
                    259:                }
                    260:                else //if(dist > 256)
                    261:                {
                    262:                        sphere = Sphere_Spawn (self, SPHERE_VENGEANCE | SPHERE_DOPPLEGANGER);
                    263:                        sphere->pain(sphere, attacker, 0, 0);
                    264:                }
                    265: //             else
                    266: //             {
                    267: //                     T_RadiusClassDamage (self, self->teammaster, 175, "doppleganger", 384, MOD_DOPPLE_EXPLODE);
                    268: //             }
                    269:        }
                    270: 
                    271:        if(self->teamchain)
                    272:                BecomeExplosion1(self->teamchain);
                    273:        BecomeExplosion1(self);
                    274: }
                    275: 
                    276: void doppleganger_pain (edict_t *self, edict_t *other, float kick, int damage)
                    277: {
                    278:        self->enemy = other;
                    279: }
                    280: 
                    281: void doppleganger_timeout (edict_t *self)
                    282: {
                    283: //     T_RadiusClassDamage (self, self->teammaster, 140, "doppleganger", 256, MOD_DOPPLE_EXPLODE);
                    284: 
                    285:        if(self->teamchain)
                    286:                BecomeExplosion1(self->teamchain);
                    287:        BecomeExplosion1(self);
                    288: }
                    289: 
                    290: void body_think (edict_t *self)
                    291: {
                    292:        float r;
                    293: 
                    294:        if(abs(self->ideal_yaw - anglemod(self->s.angles[YAW])) < 2)
                    295:        {
                    296:                if(self->timestamp < level.time)
                    297:                {
                    298:                        r = random();
                    299:                        if(r < 0.10)
                    300:                        {
                    301:                                self->ideal_yaw = random() * 350.0;
                    302:                                self->timestamp = level.time + 1;
                    303:                        }
                    304:                }
                    305:        }
                    306:        else
                    307:                M_ChangeYaw(self);
                    308: 
                    309:        self->s.frame ++;
                    310:        if (self->s.frame > FRAME_stand40)
                    311:                self->s.frame = FRAME_stand01;
                    312: 
                    313:        self->nextthink = level.time + 0.1;
                    314: }
                    315: 
                    316: void fire_doppleganger (edict_t *ent, vec3_t start, vec3_t aimdir)
                    317: {
                    318:        edict_t         *base;
                    319:        edict_t         *body;
                    320:        vec3_t          dir;
                    321:        vec3_t          forward, right, up;
                    322:        int                     number;
                    323: 
                    324:        vectoangles2 (aimdir, dir);
                    325:        AngleVectors (dir, forward, right, up);
                    326: 
                    327:        base = G_Spawn();
                    328:        VectorCopy (start, base->s.origin);
                    329:        VectorCopy (dir, base->s.angles);
                    330:        VectorClear (base->velocity);
                    331:        VectorClear (base->avelocity);
                    332:        base->movetype = MOVETYPE_TOSS;
                    333:        base->solid = SOLID_BBOX;
                    334:        base->s.renderfx |= RF_IR_VISIBLE;
                    335:        base->s.angles[PITCH]=0;
                    336:        VectorSet (base->mins, -16, -16, -24);
                    337:        VectorSet (base->maxs, 16, 16, 32);
                    338: //     base->s.modelindex = gi.modelindex ("models/objects/dopplebase/tris.md2");
                    339:        base->s.modelindex = 0;
                    340:        base->teammaster = ent;
                    341:        base->svflags |= SVF_DAMAGEABLE;
                    342:        base->takedamage = DAMAGE_AIM;
                    343:        base->health = 30;
                    344:        base->pain = doppleganger_pain;
                    345:        base->die = doppleganger_die;
                    346: 
                    347:        // FIXME - remove with style
                    348:        base->nextthink = level.time + 30;
                    349:        base->think = doppleganger_timeout;
                    350: 
                    351:        base->classname = "doppleganger";
                    352: 
                    353:        gi.linkentity (base);
                    354: 
                    355:        body = G_Spawn();
                    356:        number = body->s.number;
                    357:        body->s = ent->s;
                    358:        body->s.sound = 0;
                    359:        body->s.event = 0;
                    360: //     body->s.modelindex2 = 0;                // no attached items (CTF flag, etc)
                    361:        body->s.number = number;
                    362:        body->yaw_speed = 30;
                    363:        body->ideal_yaw = 0;
                    364:        VectorCopy (start, body->s.origin);
                    365:        body->s.origin[2] += 8;
                    366:        body->think = body_think;
                    367:        body->nextthink = level.time + FRAMETIME;
                    368:        gi.linkentity (body);
                    369: 
                    370:        base->teamchain = body;
                    371:        body->teammaster = base;
                    372: }
                    373: 

unix.superglobalmegacorp.com

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