mirror of
https://github.com/yquake2/rogue.git
synced 2024-11-26 06:00:50 +00:00
Cleanup g_newtarg.c and add sanity checks
This commit is contained in:
parent
4816a3ae03
commit
b81736eece
1 changed files with 278 additions and 196 deletions
474
src/g_newtarg.c
474
src/g_newtarg.c
|
@ -1,123 +1,164 @@
|
|||
/*
|
||||
* =======================================================================
|
||||
*
|
||||
* Rogue specific targets.
|
||||
*
|
||||
* =======================================================================
|
||||
*/
|
||||
|
||||
#include "header/local.h"
|
||||
|
||||
//==========================================================
|
||||
|
||||
/*QUAKED target_steam (1 0 0) (-8 -8 -8) (8 8 8)
|
||||
Creates a steam effect (particles w/ velocity in a line).
|
||||
|
||||
speed = velocity of particles (default 50)
|
||||
count = number of particles (default 32)
|
||||
sounds = color of particles (default 8 for steam)
|
||||
the color range is from this color to this color + 6
|
||||
wait = seconds to run before stopping (overrides default
|
||||
value derived from func_timer)
|
||||
|
||||
best way to use this is to tie it to a func_timer that "pokes"
|
||||
it every second (or however long you set the wait time, above)
|
||||
|
||||
note that the width of the base is proportional to the speed
|
||||
good colors to use:
|
||||
6-9 - varying whites (darker to brighter)
|
||||
224 - sparks
|
||||
176 - blue water
|
||||
80 - brown water
|
||||
208 - slime
|
||||
232 - blood
|
||||
*/
|
||||
|
||||
void use_target_steam (edict_t *self, edict_t *other, edict_t *activator)
|
||||
/*
|
||||
* QUAKED target_steam (1 0 0) (-8 -8 -8) (8 8 8)
|
||||
* Creates a steam effect (particles w/ velocity in a line).
|
||||
*
|
||||
* speed = velocity of particles (default 50)
|
||||
* count = number of particles (default 32)
|
||||
* sounds = color of particles (default 8 for steam)
|
||||
* the color range is from this color to this color + 6
|
||||
* wait = seconds to run before stopping (overrides default
|
||||
* value derived from func_timer)
|
||||
*
|
||||
* best way to use this is to tie it to a func_timer that "pokes"
|
||||
* it every second (or however long you set the wait time, above)
|
||||
*
|
||||
* note that the width of the base is proportional to the speed
|
||||
* good colors to use:
|
||||
* 6-9 - varying whites (darker to brighter)
|
||||
* 224 - sparks
|
||||
* 176 - blue water
|
||||
* 80 - brown water
|
||||
* 208 - slime
|
||||
* 232 - blood
|
||||
*/
|
||||
void
|
||||
use_target_steam(edict_t *self, edict_t *other, edict_t *activator /* unused */)
|
||||
{
|
||||
// FIXME - this needs to be a global
|
||||
static int nextid;
|
||||
vec3_t point;
|
||||
|
||||
static int nextid;
|
||||
vec3_t point;
|
||||
|
||||
if (!self || !other)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (nextid > 20000)
|
||||
nextid = nextid %20000;
|
||||
{
|
||||
nextid = nextid % 20000;
|
||||
}
|
||||
|
||||
nextid++;
|
||||
|
||||
// automagically set wait from func_timer unless they set it already, or
|
||||
// default to 1000 if not called by a func_timer (eek!)
|
||||
|
||||
/* automagically set wait from func_timer unless they set it
|
||||
already, or default to 1000 if not called by a func_timer */
|
||||
if (!self->wait)
|
||||
{
|
||||
if (other)
|
||||
{
|
||||
self->wait = other->wait * 1000;
|
||||
}
|
||||
else
|
||||
{
|
||||
self->wait = 1000;
|
||||
}
|
||||
}
|
||||
|
||||
if (self->enemy)
|
||||
{
|
||||
VectorMA (self->enemy->absmin, 0.5, self->enemy->size, point);
|
||||
VectorSubtract (point, self->s.origin, self->movedir);
|
||||
VectorNormalize (self->movedir);
|
||||
VectorMA(self->enemy->absmin, 0.5, self->enemy->size, point);
|
||||
VectorSubtract(point, self->s.origin, self->movedir);
|
||||
VectorNormalize(self->movedir);
|
||||
}
|
||||
|
||||
VectorMA (self->s.origin, self->plat2flags*0.5, self->movedir, point);
|
||||
VectorMA(self->s.origin, self->plat2flags * 0.5, self->movedir, point);
|
||||
|
||||
if (self->wait > 100)
|
||||
{
|
||||
gi.WriteByte (svc_temp_entity);
|
||||
gi.WriteByte (TE_STEAM);
|
||||
gi.WriteShort (nextid);
|
||||
gi.WriteByte (self->count);
|
||||
gi.WritePosition (self->s.origin);
|
||||
gi.WriteDir (self->movedir);
|
||||
gi.WriteByte (self->sounds&0xff);
|
||||
gi.WriteShort ( (short int)(self->plat2flags) );
|
||||
gi.WriteLong ( (int)(self->wait) );
|
||||
gi.multicast (self->s.origin, MULTICAST_PVS);
|
||||
gi.WriteByte(svc_temp_entity);
|
||||
gi.WriteByte(TE_STEAM);
|
||||
gi.WriteShort(nextid);
|
||||
gi.WriteByte(self->count);
|
||||
gi.WritePosition(self->s.origin);
|
||||
gi.WriteDir(self->movedir);
|
||||
gi.WriteByte(self->sounds & 0xff);
|
||||
gi.WriteShort((short int)(self->plat2flags));
|
||||
gi.WriteLong((int)(self->wait));
|
||||
gi.multicast(self->s.origin, MULTICAST_PVS);
|
||||
}
|
||||
else
|
||||
{
|
||||
gi.WriteByte (svc_temp_entity);
|
||||
gi.WriteByte (TE_STEAM);
|
||||
gi.WriteShort ((short int)-1);
|
||||
gi.WriteByte (self->count);
|
||||
gi.WritePosition (self->s.origin);
|
||||
gi.WriteDir (self->movedir);
|
||||
gi.WriteByte (self->sounds&0xff);
|
||||
gi.WriteShort ( (short int)(self->plat2flags) );
|
||||
gi.multicast (self->s.origin, MULTICAST_PVS);
|
||||
gi.WriteByte(svc_temp_entity);
|
||||
gi.WriteByte(TE_STEAM);
|
||||
gi.WriteShort((short int)-1);
|
||||
gi.WriteByte(self->count);
|
||||
gi.WritePosition(self->s.origin);
|
||||
gi.WriteDir(self->movedir);
|
||||
gi.WriteByte(self->sounds & 0xff);
|
||||
gi.WriteShort((short int)(self->plat2flags));
|
||||
gi.multicast(self->s.origin, MULTICAST_PVS);
|
||||
}
|
||||
}
|
||||
|
||||
void target_steam_start (edict_t *self)
|
||||
void
|
||||
target_steam_start(edict_t *self)
|
||||
{
|
||||
edict_t *ent;
|
||||
|
||||
edict_t *ent;
|
||||
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self->use = use_target_steam;
|
||||
|
||||
if (self->target)
|
||||
{
|
||||
ent = G_Find (NULL, FOFS(targetname), self->target);
|
||||
ent = G_Find(NULL, FOFS(targetname), self->target);
|
||||
|
||||
if (!ent)
|
||||
gi.dprintf ("%s at %s: %s is a bad target\n", self->classname, vtos(self->s.origin), self->target);
|
||||
{
|
||||
gi.dprintf("%s at %s: %s is a bad target\n", self->classname,
|
||||
vtos(self->s.origin), self->target);
|
||||
}
|
||||
|
||||
self->enemy = ent;
|
||||
}
|
||||
else
|
||||
{
|
||||
G_SetMovedir (self->s.angles, self->movedir);
|
||||
G_SetMovedir(self->s.angles, self->movedir);
|
||||
}
|
||||
|
||||
if (!self->count)
|
||||
{
|
||||
self->count = 32;
|
||||
if (!self->plat2flags)
|
||||
self->plat2flags = 75;
|
||||
if (!self->sounds)
|
||||
self->sounds = 8;
|
||||
if (self->wait)
|
||||
self->wait *= 1000; // we want it in milliseconds, not seconds
|
||||
}
|
||||
|
||||
// paranoia is good
|
||||
if (!self->plat2flags)
|
||||
{
|
||||
self->plat2flags = 75;
|
||||
}
|
||||
|
||||
if (!self->sounds)
|
||||
{
|
||||
self->sounds = 8;
|
||||
}
|
||||
|
||||
if (self->wait)
|
||||
{
|
||||
self->wait *= 1000; /* we want it in milliseconds, not seconds */
|
||||
}
|
||||
|
||||
/* paranoia is good */
|
||||
self->sounds &= 0xff;
|
||||
self->count &= 0xff;
|
||||
|
||||
self->svflags = SVF_NOCLIENT;
|
||||
|
||||
gi.linkentity (self);
|
||||
gi.linkentity(self);
|
||||
}
|
||||
|
||||
void SP_target_steam (edict_t *self)
|
||||
void
|
||||
SP_target_steam(edict_t *self)
|
||||
{
|
||||
self->plat2flags = self->speed;
|
||||
|
||||
|
@ -127,35 +168,39 @@ void SP_target_steam (edict_t *self)
|
|||
self->nextthink = level.time + 1;
|
||||
}
|
||||
else
|
||||
target_steam_start (self);
|
||||
{
|
||||
target_steam_start(self);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==========================================================
|
||||
// target_anger
|
||||
//==========================================================
|
||||
|
||||
void target_anger_use (edict_t *self, edict_t *other, edict_t *activator)
|
||||
void
|
||||
target_anger_use(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */)
|
||||
{
|
||||
edict_t *target;
|
||||
edict_t *t;
|
||||
|
||||
edict_t *target;
|
||||
edict_t *t;
|
||||
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
t = NULL;
|
||||
target = G_Find (t, FOFS(targetname), self->killtarget);
|
||||
target = G_Find(t, FOFS(targetname), self->killtarget);
|
||||
|
||||
if (target && self->target)
|
||||
{
|
||||
// Make whatever a "good guy" so the monster will try to kill it!
|
||||
/* Make whatever a "good guy" so the monster will try to kill it! */
|
||||
target->monsterinfo.aiflags |= AI_GOOD_GUY;
|
||||
target->svflags |= SVF_MONSTER;
|
||||
target->health = 300;
|
||||
|
||||
t = NULL;
|
||||
while ((t = G_Find (t, FOFS(targetname), self->target)))
|
||||
|
||||
while ((t = G_Find(t, FOFS(targetname), self->target)))
|
||||
{
|
||||
if (t == self)
|
||||
{
|
||||
gi.dprintf ("WARNING: entity used itself.\n");
|
||||
gi.dprintf("WARNING: entity used itself.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -165,11 +210,13 @@ void target_anger_use (edict_t *self, edict_t *other, edict_t *activator)
|
|||
{
|
||||
return;
|
||||
}
|
||||
|
||||
t->enemy = target;
|
||||
t->monsterinfo.aiflags |= AI_TARGET_ANGER;
|
||||
FoundTarget (t);
|
||||
FoundTarget(t);
|
||||
}
|
||||
}
|
||||
|
||||
if (!self->inuse)
|
||||
{
|
||||
gi.dprintf("entity was removed while using targets\n");
|
||||
|
@ -177,28 +224,36 @@ void target_anger_use (edict_t *self, edict_t *other, edict_t *activator)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*QUAKED target_anger (1 0 0) (-8 -8 -8) (8 8 8)
|
||||
This trigger will cause an entity to be angry at another entity when a player touches it. Target the
|
||||
entity you want to anger, and killtarget the entity you want it to be angry at.
|
||||
|
||||
target - entity to piss off
|
||||
killtarget - entity to be pissed off at
|
||||
*/
|
||||
void SP_target_anger (edict_t *self)
|
||||
{
|
||||
/*
|
||||
* QUAKED target_anger (1 0 0) (-8 -8 -8) (8 8 8)
|
||||
*
|
||||
* This trigger will cause an entity to be angry at another entity when a player touches it.
|
||||
* Target the entity you want to anger, and killtarget the entity you want it to be angry at.
|
||||
*
|
||||
* target - entity to piss off
|
||||
* killtarget - entity to be pissed off at
|
||||
*/
|
||||
void
|
||||
SP_target_anger(edict_t *self)
|
||||
{
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!self->target)
|
||||
{
|
||||
gi.dprintf("target_anger without target!\n");
|
||||
G_FreeEdict (self);
|
||||
G_FreeEdict(self);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!self->killtarget)
|
||||
{
|
||||
gi.dprintf("target_anger without killtarget!\n");
|
||||
G_FreeEdict (self);
|
||||
G_FreeEdict(self);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -206,145 +261,172 @@ void SP_target_anger (edict_t *self)
|
|||
self->svflags = SVF_NOCLIENT;
|
||||
}
|
||||
|
||||
// ================
|
||||
// target_spawn
|
||||
// ================
|
||||
/*
|
||||
extern edict_t *CreateMonster(vec3_t origin, vec3_t angles, char *classname);
|
||||
|
||||
void target_spawn_use (edict_t *self, edict_t *other, edict_t *activator)
|
||||
void
|
||||
target_killplayers_use(edict_t *self, edict_t *other /* unused */, edict_t *activator /* unused */)
|
||||
{
|
||||
edict_t *newEnt;
|
||||
|
||||
newEnt = CreateMonster (self->s.origin, self->s.angles, "monster_infantry");
|
||||
if(newEnt)
|
||||
newEnt->enemy = other;
|
||||
}
|
||||
*/
|
||||
|
||||
/*Q U AKED target_spawn (1 0 0) (-32 -32 -24) (32 32 72)
|
||||
*/
|
||||
/*
|
||||
void SP_target_spawn (edict_t *self)
|
||||
{
|
||||
self->use = target_spawn_use;
|
||||
self->svflags = SVF_NOCLIENT;
|
||||
}
|
||||
*/
|
||||
|
||||
// ***********************************
|
||||
// target_killplayers
|
||||
// ***********************************
|
||||
|
||||
void target_killplayers_use (edict_t *self, edict_t *other, edict_t *activator)
|
||||
{
|
||||
int i;
|
||||
edict_t *ent, *player;
|
||||
|
||||
// kill the players
|
||||
for (i=0 ; i<game.maxclients ; i++)
|
||||
int i;
|
||||
edict_t *ent, *player;
|
||||
|
||||
if (!self)
|
||||
{
|
||||
player = &g_edicts[1+i];
|
||||
if (!player->inuse)
|
||||
continue;
|
||||
return;
|
||||
}
|
||||
|
||||
/* kill the players */
|
||||
for (i = 0; i < game.maxclients; i++)
|
||||
{
|
||||
player = &g_edicts[1 + i];
|
||||
|
||||
// nail it
|
||||
T_Damage (player, self, self, vec3_origin, self->s.origin, vec3_origin, 100000, 0, DAMAGE_NO_PROTECTION, MOD_TELEFRAG);
|
||||
if (!player->inuse)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
/* nail it */
|
||||
T_Damage(player, self, self, vec3_origin, self->s.origin, vec3_origin,
|
||||
100000, 0, DAMAGE_NO_PROTECTION, MOD_TELEFRAG);
|
||||
}
|
||||
|
||||
// kill any visible monsters
|
||||
for (ent = g_edicts; ent < &g_edicts[globals.num_edicts] ; ent++)
|
||||
/* kill any visible monsters */
|
||||
for (ent = g_edicts; ent < &g_edicts[globals.num_edicts]; ent++)
|
||||
{
|
||||
if (!ent->inuse)
|
||||
continue;
|
||||
if (ent->health < 1)
|
||||
continue;
|
||||
if (!ent->takedamage)
|
||||
continue;
|
||||
|
||||
for(i=0;i<game.maxclients ; i++)
|
||||
{
|
||||
player = &g_edicts[1+i];
|
||||
if(!player->inuse)
|
||||
continue;
|
||||
|
||||
if(visible(player, ent))
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ent->health < 1)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!ent->takedamage)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
for (i = 0; i < game.maxclients; i++)
|
||||
{
|
||||
player = &g_edicts[1 + i];
|
||||
|
||||
if (!player->inuse)
|
||||
{
|
||||
T_Damage (ent, self, self, vec3_origin, ent->s.origin, vec3_origin,
|
||||
ent->health, 0, DAMAGE_NO_PROTECTION, MOD_TELEFRAG);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (visible(player, ent))
|
||||
{
|
||||
T_Damage(ent, self, self, vec3_origin, ent->s.origin, vec3_origin,
|
||||
ent->health, 0, DAMAGE_NO_PROTECTION, MOD_TELEFRAG);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*QUAKED target_killplayers (1 0 0) (-8 -8 -8) (8 8 8)
|
||||
When triggered, this will kill all the players on the map.
|
||||
*/
|
||||
void SP_target_killplayers (edict_t *self)
|
||||
{
|
||||
/*
|
||||
* QUAKED target_killplayers (1 0 0) (-8 -8 -8) (8 8 8)
|
||||
*
|
||||
* When triggered, this will kill all the players on the map.
|
||||
*/
|
||||
void
|
||||
SP_target_killplayers(edict_t *self)
|
||||
{
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self->use = target_killplayers_use;
|
||||
self->svflags = SVF_NOCLIENT;
|
||||
}
|
||||
|
||||
/*QUAKED target_blacklight (1 0 1) (-16 -16 -24) (16 16 24)
|
||||
Pulsing black light with sphere in the center
|
||||
*/
|
||||
void blacklight_think (edict_t *self)
|
||||
{
|
||||
self->s.angles[0] = rand()%360;
|
||||
self->s.angles[1] = rand()%360;
|
||||
self->s.angles[2] = rand()%360;
|
||||
/*
|
||||
* QUAKED target_blacklight (1 0 1) (-16 -16 -24) (16 16 24)
|
||||
*
|
||||
* Pulsing black light with sphere in the center
|
||||
*/
|
||||
void
|
||||
blacklight_think(edict_t *self)
|
||||
{
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self->s.angles[0] = rand() % 360;
|
||||
self->s.angles[1] = rand() % 360;
|
||||
self->s.angles[2] = rand() % 360;
|
||||
self->nextthink = level.time + 0.1;
|
||||
}
|
||||
|
||||
void SP_target_blacklight(edict_t *ent)
|
||||
{
|
||||
void
|
||||
SP_target_blacklight(edict_t *ent)
|
||||
{
|
||||
if (!ent)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (deathmatch->value)
|
||||
{ // auto-remove for deathmatch
|
||||
G_FreeEdict (ent);
|
||||
{
|
||||
/* auto-remove for deathmatch */
|
||||
G_FreeEdict(ent);
|
||||
return;
|
||||
}
|
||||
|
||||
VectorClear (ent->mins);
|
||||
VectorClear (ent->maxs);
|
||||
VectorClear(ent->mins);
|
||||
VectorClear(ent->maxs);
|
||||
|
||||
ent->s.effects |= (EF_TRACKERTRAIL|EF_TRACKER);
|
||||
ent->s.effects |= (EF_TRACKERTRAIL | EF_TRACKER);
|
||||
ent->think = blacklight_think;
|
||||
ent->s.modelindex = gi.modelindex ("models/items/spawngro2/tris.md2");
|
||||
ent->s.modelindex = gi.modelindex("models/items/spawngro2/tris.md2");
|
||||
ent->s.frame = 1;
|
||||
ent->nextthink = level.time + 0.1;
|
||||
gi.linkentity (ent);
|
||||
gi.linkentity(ent);
|
||||
}
|
||||
|
||||
/*QUAKED target_orb (1 0 1) (-16 -16 -24) (16 16 24)
|
||||
Translucent pulsing orb with speckles
|
||||
*/
|
||||
void orb_think (edict_t *self)
|
||||
{
|
||||
self->s.angles[0] = rand()%360;
|
||||
self->s.angles[1] = rand()%360;
|
||||
self->s.angles[2] = rand()%360;
|
||||
/*
|
||||
* QUAKED target_orb (1 0 1) (-16 -16 -24) (16 16 24)
|
||||
*
|
||||
* Translucent pulsing orb with speckles
|
||||
*/
|
||||
void
|
||||
orb_think(edict_t *self)
|
||||
{
|
||||
if (!self)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
self->s.angles[0] = rand() % 360;
|
||||
self->s.angles[1] = rand() % 360;
|
||||
self->s.angles[2] = rand() % 360;
|
||||
self->nextthink = level.time + 0.1;
|
||||
}
|
||||
|
||||
void SP_target_orb(edict_t *ent)
|
||||
{
|
||||
void
|
||||
SP_target_orb(edict_t *ent)
|
||||
{
|
||||
if (!ent)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (deathmatch->value)
|
||||
{ // auto-remove for deathmatch
|
||||
G_FreeEdict (ent);
|
||||
{
|
||||
/* auto-remove for deathmatch */
|
||||
G_FreeEdict(ent);
|
||||
return;
|
||||
}
|
||||
|
||||
VectorClear (ent->mins);
|
||||
VectorClear (ent->maxs);
|
||||
VectorClear(ent->mins);
|
||||
VectorClear(ent->maxs);
|
||||
|
||||
ent->think = orb_think;
|
||||
ent->nextthink = level.time + 0.1;
|
||||
ent->s.modelindex = gi.modelindex ("models/items/spawngro2/tris.md2");
|
||||
ent->s.modelindex = gi.modelindex("models/items/spawngro2/tris.md2");
|
||||
ent->s.frame = 2;
|
||||
ent->s.effects |= EF_SPHERETRANS;
|
||||
gi.linkentity (ent);
|
||||
gi.linkentity(ent);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue