|
|
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:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.