Cleanup g_newdm.c and add sanity checks.

This commit is contained in:
Yamagi Burmeister 2014-01-26 15:58:17 +01:00
parent 2d2c7e8222
commit 579b6cc413

View file

@ -1,27 +1,39 @@
// g_newdm.c /*
// pmack * =======================================================================
// june 1998 *
* Rogue specific deathmatch stuff.
*
* =======================================================================
*/
#include "header/local.h" #include "header/local.h"
#include "monster/misc/player.h" #include "monster/misc/player.h"
dm_game_rt DMGame; #define IT_TYPE_MASK (IT_WEAPON | IT_AMMO | IT_POWERUP | IT_ARMOR | IT_KEY)
// **************************** dm_game_rt DMGame;
// General DM Stuff
// **************************** extern qboolean Pickup_Health(edict_t *ent, edict_t *other);
extern qboolean Pickup_Adrenaline(edict_t *ent, edict_t *other);
void InitGameRules(void) extern qboolean Pickup_Armor(edict_t *ent, edict_t *other);
extern qboolean Pickup_PowerArmor(edict_t *ent, edict_t *other);
extern edict_t *Sphere_Spawn(edict_t *owner, int spawnflags);
extern void ED_CallSpawn(edict_t *ent);
void fire_doppleganger(edict_t *ent, vec3_t start, vec3_t aimdir);
void
InitGameRules(void)
{ {
int gameNum; int gameNum;
// clear out the game rule structure before we start /* clear out the game rule structure before we start */
memset(&DMGame, 0, sizeof(dm_game_rt)); memset(&DMGame, 0, sizeof(dm_game_rt));
if(gamerules && gamerules->value) if (gamerules && gamerules->value)
{ {
gameNum = gamerules->value; gameNum = gamerules->value;
switch(gameNum)
switch (gameNum)
{ {
case RDM_TAG: case RDM_TAG:
DMGame.GameInit = Tag_GameInit; DMGame.GameInit = Tag_GameInit;
@ -34,261 +46,326 @@ void InitGameRules(void)
DMGame.ChangeDamage = Tag_ChangeDamage; DMGame.ChangeDamage = Tag_ChangeDamage;
break; break;
// reset gamerules if it's not a valid number /* reset gamerules if it's not a valid number */
default: default:
gamerules->value = 0; gamerules->value = 0;
break; break;
} }
} }
// if we're set up to play, initialize the game as needed. /* if we're set up to play, initialize the game as needed. */
if(DMGame.GameInit) if (DMGame.GameInit)
{
DMGame.GameInit(); DMGame.GameInit();
}
} }
//================= char *
#define IT_TYPE_MASK (IT_WEAPON|IT_AMMO|IT_POWERUP|IT_ARMOR|IT_KEY) FindSubstituteItem(edict_t *ent)
extern void ED_CallSpawn (edict_t *ent);
extern qboolean Pickup_Health (edict_t *ent, edict_t *other);
extern qboolean Pickup_Adrenaline (edict_t *ent, edict_t *other);
extern qboolean Pickup_Armor (edict_t *ent, edict_t *other);
extern qboolean Pickup_PowerArmor (edict_t *ent, edict_t *other);
char *FindSubstituteItem (edict_t *ent)
{ {
int i; int i;
int itflags, myflags; int itflags, myflags;
float rnd; float rnd;
int count; int count;
int pick; int pick;
gitem_t *it; gitem_t *it;
// there are only two classes of power armor, and we don't want /* there are only two classes of power armor, and we don't want
// to give out power screens. therefore, power shields should to give out power screens. therefore, power shields should
// remain power shields. (powerscreens shouldn't be there at all...) remain power shields. (powerscreens shouldn't be there at all...) */
if (ent->item->pickup == Pickup_PowerArmor) if (ent->item->pickup == Pickup_PowerArmor)
{
return NULL; return NULL;
}
// health is special case /* health is special case */
if ((ent->item->pickup == Pickup_Health) || (ent->item->pickup == Pickup_Adrenaline)) if ((ent->item->pickup == Pickup_Health) ||
(ent->item->pickup == Pickup_Adrenaline))
{ {
// health pellets stay health pellets /* health pellets stay health pellets */
if(!strcmp(ent->classname, "item_health_small")) if (!strcmp(ent->classname, "item_health_small"))
{
return NULL; return NULL;
}
rnd = random(); rnd = random();
if(rnd < 0.6)
if (rnd < 0.6)
{
return "item_health"; return "item_health";
else if(rnd < 0.9) }
else if (rnd < 0.9)
{
return "item_health_large"; return "item_health_large";
else if(rnd < 0.99) }
else if (rnd < 0.99)
{
return "item_adrenaline"; return "item_adrenaline";
}
else else
{
return "item_health_mega"; return "item_health_mega";
}
} }
// armor is also special case /* armor is also special case */
else if(ent->item->pickup == Pickup_Armor) else if (ent->item->pickup == Pickup_Armor)
{ {
// armor shards stay armor shards /* armor shards stay armor shards */
if (ent->item->tag == ARMOR_SHARD) if (ent->item->tag == ARMOR_SHARD)
{
return NULL; return NULL;
}
rnd = random(); rnd = random();
if(rnd < 0.6)
if (rnd < 0.6)
{
return "item_armor_jacket"; return "item_armor_jacket";
else if(rnd < 0.9) }
else if (rnd < 0.9)
{
return "item_armor_combat"; return "item_armor_combat";
}
else else
{
return "item_armor_body"; return "item_armor_body";
}
} }
/* we want to stay within the item class */
// we want to stay within the item class
myflags = ent->item->flags & IT_TYPE_MASK; myflags = ent->item->flags & IT_TYPE_MASK;
if ((myflags & IT_AMMO) && (myflags & IT_WEAPON)) if ((myflags & IT_AMMO) && (myflags & IT_WEAPON))
myflags = IT_AMMO; {
myflags = IT_AMMO;
}
count = 0; count = 0;
// first pass, count the matching items /* first pass, count the matching items */
it = itemlist; it = itemlist;
for (i=0 ; i<game.num_items ; i++, it++)
for (i = 0; i < game.num_items; i++, it++)
{ {
itflags = it->flags; itflags = it->flags;
if (!itflags || (itflags & IT_NOT_GIVEABLE)) if (!itflags || (itflags & IT_NOT_GIVEABLE))
continue;
// prox,grenades,etc should count as ammo.
if ((itflags & IT_AMMO) && (itflags & IT_WEAPON))
itflags = IT_AMMO;
// don't respawn spheres if they're dmflag disabled.
if ( (int)dmflags->value & DF_NO_SPHERES )
{ {
if (!strcmp (ent->classname, "item_sphere_vengeance") || continue;
!strcmp (ent->classname, "item_sphere_hunter") || }
!strcmp (ent->classname, "item_spehre_defender"))
/* prox,grenades,etc should count as ammo. */
if ((itflags & IT_AMMO) && (itflags & IT_WEAPON))
{
itflags = IT_AMMO;
}
/* don't respawn spheres if they're dmflag disabled. */
if ((int)dmflags->value & DF_NO_SPHERES)
{
if (!strcmp(ent->classname, "item_sphere_vengeance") ||
!strcmp(ent->classname, "item_sphere_hunter") ||
!strcmp(ent->classname, "item_spehre_defender"))
{ {
continue; continue;
} }
} }
if ( ((int)dmflags->value & DF_NO_NUKES) && !strcmp(ent->classname, "ammo_nuke") ) if (((int)dmflags->value & DF_NO_NUKES) &&
!strcmp(ent->classname, "ammo_nuke"))
{
continue; continue;
}
if ( ((int)dmflags->value & DF_NO_MINES) && if (((int)dmflags->value & DF_NO_MINES) &&
(!strcmp(ent->classname, "ammo_prox") || !strcmp(ent->classname, "ammo_tesla"))) (!strcmp(ent->classname, "ammo_prox") || !strcmp(ent->classname, "ammo_tesla")))
continue; {
if ((itflags & IT_TYPE_MASK) == (myflags & IT_TYPE_MASK))
count++;
}
if(!count)
return NULL;
pick = ceil(random() * count);
count = 0;
// second pass, pick one.
it = itemlist;
for (i=0 ; i<game.num_items ; i++, it++)
{
itflags = it->flags;
if (!itflags || (itflags & IT_NOT_GIVEABLE))
continue;
// prox,grenades,etc should count as ammo.
if ((itflags & IT_AMMO) && (itflags & IT_WEAPON))
itflags = IT_AMMO;
if ( ((int)dmflags->value & DF_NO_NUKES) && !strcmp(ent->classname, "ammo_nuke") )
continue;
if ( ((int)dmflags->value & DF_NO_MINES) &&
(!strcmp(ent->classname, "ammo_prox") || !strcmp(ent->classname, "ammo_tesla")))
continue; continue;
}
if ((itflags & IT_TYPE_MASK) == (myflags & IT_TYPE_MASK)) if ((itflags & IT_TYPE_MASK) == (myflags & IT_TYPE_MASK))
{ {
count++; count++;
if(pick == count) }
}
if (!count)
{
return NULL;
}
pick = ceil(random() * count);
count = 0;
/* second pass, pick one. */
it = itemlist;
for (i = 0; i < game.num_items; i++, it++)
{
itflags = it->flags;
if (!itflags || (itflags & IT_NOT_GIVEABLE))
{
continue;
}
/* prox,grenades,etc should count as ammo. */
if ((itflags & IT_AMMO) && (itflags & IT_WEAPON))
{
itflags = IT_AMMO;
}
if (((int)dmflags->value & DF_NO_NUKES) &&
!strcmp(ent->classname, "ammo_nuke"))
{
continue;
}
if (((int)dmflags->value & DF_NO_MINES) &&
(!strcmp(ent->classname, "ammo_prox") || !strcmp(ent->classname, "ammo_tesla")))
{
continue;
}
if ((itflags & IT_TYPE_MASK) == (myflags & IT_TYPE_MASK))
{
count++;
if (pick == count)
{
return it->classname; return it->classname;
}
} }
} }
return NULL; return NULL;
} }
//================= edict_t *
edict_t *DoRandomRespawn (edict_t *ent) DoRandomRespawn(edict_t *ent)
{ {
edict_t *newEnt; edict_t *newEnt;
char *classname; char *classname;
classname = FindSubstituteItem (ent); if (!ent)
if (classname == NULL) {
return NULL; return NULL;
}
classname = FindSubstituteItem(ent);
gi.unlinkentity (ent); if (classname == NULL)
{
return NULL;
}
gi.unlinkentity(ent);
newEnt = G_Spawn(); newEnt = G_Spawn();
newEnt->classname = classname; newEnt->classname = classname;
VectorCopy (ent->s.origin, newEnt->s.origin); VectorCopy(ent->s.origin, newEnt->s.origin);
VectorCopy (ent->s.old_origin, newEnt->s.old_origin); VectorCopy(ent->s.old_origin, newEnt->s.old_origin);
VectorCopy (ent->mins, newEnt->mins); VectorCopy(ent->mins, newEnt->mins);
VectorCopy (ent->maxs, newEnt->maxs); VectorCopy(ent->maxs, newEnt->maxs);
VectorSet (newEnt->gravityVector, 0, 0, -1);
ED_CallSpawn (newEnt); VectorSet(newEnt->gravityVector, 0, 0, -1);
ED_CallSpawn(newEnt);
newEnt->s.renderfx |= RF_IR_VISIBLE; newEnt->s.renderfx |= RF_IR_VISIBLE;
return newEnt; return newEnt;
} }
//================= void
void PrecacheForRandomRespawn (void) PrecacheForRandomRespawn(void)
{ {
gitem_t *it; gitem_t *it;
int i; int i;
int itflags; int itflags;
it = itemlist; it = itemlist;
for (i=0 ; i<game.num_items ; i++, it++)
for (i = 0; i < game.num_items; i++, it++)
{ {
itflags = it->flags; itflags = it->flags;
if (!itflags || (itflags & IT_NOT_GIVEABLE)) if (!itflags || (itflags & IT_NOT_GIVEABLE))
{
continue; continue;
}
PrecacheItem(it); PrecacheItem(it);
} }
} }
// *************************** void
// DOPPLEGANGER doppleganger_die(edict_t *self, edict_t *inflictor /* unused */, edict_t *attacker,
// *************************** int damage, vec3_t point)
extern edict_t *Sphere_Spawn (edict_t *owner, int spawnflags);
void fire_doppleganger (edict_t *ent, vec3_t start, vec3_t aimdir);
void doppleganger_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point);
void doppleganger_die (edict_t *self, edict_t *inflictor, edict_t *attacker, int damage, vec3_t point)
{ {
edict_t *sphere; edict_t *sphere;
float dist; float dist;
vec3_t dir; vec3_t dir;
if((self->enemy) && (self->enemy != self->teammaster)) if (!self || !attacker)
{
return;
}
if ((self->enemy) && (self->enemy != self->teammaster))
{ {
VectorSubtract(self->enemy->s.origin, self->s.origin, dir); VectorSubtract(self->enemy->s.origin, self->s.origin, dir);
dist = VectorLength(dir); dist = VectorLength(dir);
if(dist > 768) if (dist > 768)
{ {
sphere = Sphere_Spawn (self, SPHERE_HUNTER | SPHERE_DOPPLEGANGER); sphere = Sphere_Spawn(self, SPHERE_HUNTER | SPHERE_DOPPLEGANGER);
sphere->pain(sphere, attacker, 0, 0); sphere->pain(sphere, attacker, 0, 0);
} }
else else
{ {
sphere = Sphere_Spawn (self, SPHERE_VENGEANCE | SPHERE_DOPPLEGANGER); sphere = Sphere_Spawn(self, SPHERE_VENGEANCE | SPHERE_DOPPLEGANGER);
sphere->pain(sphere, attacker, 0, 0); sphere->pain(sphere, attacker, 0, 0);
} }
} }
if(self->teamchain) if (self->teamchain)
{
BecomeExplosion1(self->teamchain); BecomeExplosion1(self->teamchain);
}
BecomeExplosion1(self); BecomeExplosion1(self);
} }
void doppleganger_pain (edict_t *self, edict_t *other, float kick, int damage) void
doppleganger_pain(edict_t *self, edict_t *other, float kick, int damage)
{ {
self->enemy = other; self->enemy = other;
} }
void doppleganger_timeout (edict_t *self) void
doppleganger_timeout(edict_t *self)
{ {
if(self->teamchain) if (self->teamchain)
{
BecomeExplosion1(self->teamchain); BecomeExplosion1(self->teamchain);
}
BecomeExplosion1(self); BecomeExplosion1(self);
} }
void body_think (edict_t *self) void
body_think(edict_t *self)
{ {
float r; float r;
if(abs(self->ideal_yaw - anglemod(self->s.angles[YAW])) < 2) if (abs(self->ideal_yaw - anglemod(self->s.angles[YAW])) < 2)
{ {
if(self->timestamp < level.time) if (self->timestamp < level.time)
{ {
r = random(); r = random();
if(r < 0.10)
if (r < 0.10)
{ {
self->ideal_yaw = random() * 350.0; self->ideal_yaw = random() * 350.0;
self->timestamp = level.time + 1; self->timestamp = level.time + 1;
@ -296,37 +373,48 @@ void body_think (edict_t *self)
} }
} }
else else
{
M_ChangeYaw(self); M_ChangeYaw(self);
}
self->s.frame++;
self->s.frame ++;
if (self->s.frame > FRAME_stand40) if (self->s.frame > FRAME_stand40)
{
self->s.frame = FRAME_stand01; self->s.frame = FRAME_stand01;
}
self->nextthink = level.time + 0.1; self->nextthink = level.time + 0.1;
} }
void fire_doppleganger (edict_t *ent, vec3_t start, vec3_t aimdir) void
fire_doppleganger(edict_t *ent, vec3_t start, vec3_t aimdir)
{ {
edict_t *base; edict_t *base;
edict_t *body; edict_t *body;
vec3_t dir; vec3_t dir;
vec3_t forward, right, up; vec3_t forward, right, up;
int number; int number;
vectoangles2 (aimdir, dir); if (!ent)
AngleVectors (dir, forward, right, up); {
return;
}
vectoangles2(aimdir, dir);
AngleVectors(dir, forward, right, up);
base = G_Spawn(); base = G_Spawn();
VectorCopy (start, base->s.origin); VectorCopy(start, base->s.origin);
VectorCopy (dir, base->s.angles); VectorCopy(dir, base->s.angles);
VectorClear (base->velocity); VectorClear(base->velocity);
VectorClear (base->avelocity); VectorClear(base->avelocity);
base->movetype = MOVETYPE_TOSS; base->movetype = MOVETYPE_TOSS;
base->solid = SOLID_BBOX; base->solid = SOLID_BBOX;
base->s.renderfx |= RF_IR_VISIBLE; base->s.renderfx |= RF_IR_VISIBLE;
base->s.angles[PITCH]=0; base->s.angles[PITCH] = 0;
VectorSet (base->mins, -16, -16, -24); VectorSet(base->mins, -16, -16, -24);
VectorSet (base->maxs, 16, 16, 32); VectorSet(base->maxs, 16, 16, 32);
base->s.modelindex = 0; base->s.modelindex = 0;
base->teammaster = ent; base->teammaster = ent;
base->svflags |= SVF_DAMAGEABLE; base->svflags |= SVF_DAMAGEABLE;
@ -335,13 +423,11 @@ void fire_doppleganger (edict_t *ent, vec3_t start, vec3_t aimdir)
base->pain = doppleganger_pain; base->pain = doppleganger_pain;
base->die = doppleganger_die; base->die = doppleganger_die;
// FIXME - remove with style
base->nextthink = level.time + 30; base->nextthink = level.time + 30;
base->think = doppleganger_timeout; base->think = doppleganger_timeout;
base->classname = "doppleganger"; base->classname = "doppleganger";
gi.linkentity (base); gi.linkentity(base);
body = G_Spawn(); body = G_Spawn();
number = body->s.number; number = body->s.number;
@ -351,13 +437,12 @@ void fire_doppleganger (edict_t *ent, vec3_t start, vec3_t aimdir)
body->s.number = number; body->s.number = number;
body->yaw_speed = 30; body->yaw_speed = 30;
body->ideal_yaw = 0; body->ideal_yaw = 0;
VectorCopy (start, body->s.origin); VectorCopy(start, body->s.origin);
body->s.origin[2] += 8; body->s.origin[2] += 8;
body->think = body_think; body->think = body_think;
body->nextthink = level.time + FRAMETIME; body->nextthink = level.time + FRAMETIME;
gi.linkentity (body); gi.linkentity(body);
base->teamchain = body; base->teamchain = body;
body->teammaster = base; body->teammaster = base;
} }