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