heretic2-sdk/Toolkit/Programming/GameCode/game/g_waterfx.c

397 lines
9.7 KiB
C
Raw Normal View History

1998-11-24 00:00:00 +00:00
// Water related fx, including
// 1. Fountain
#include "g_local.h"
#include "fx.h"
#include "random.h"
#include "vector.h"
#define OBJ_INVULNERABLE 1
#define OBJ_ANIMATE 2
#define OBJ_EXPLODING 4
#define OBJ_NOPUSH 8
void BboxYawAndScale(edict_t *self);
void waterdrip_go(edict_t *self)
{
byte frame;
frame = 0;
if(self->spawnflags & 1)
{
frame = 1;
}
self->PersistantCFX = gi.CreatePersistantEffect(&self->s, FX_DRIPPER, CEF_BROADCAST,
self->s.origin, "bb", self->count, frame);
self->think = NULL;
}
void waterdrip_use (edict_t *self, edict_t *other, edict_t *activator)
{
if (!self->PersistantCFX)
waterdrip_go(self);
else
{
gi.RemoveEffects(&self->s,0);
self->PersistantCFX = 0;
}
}
/*QUAKED env_water_drip (1 .5 0) (-4 -4 0) (4 4 4) YELLOW
Spawns a drip of water which falls straight down
---- SPAWN FLAGS ------
if YELLOW set.. uses a yellow drip
------- KEYS ----------
count - drips per minute (default 20)
*/
// This really ought to be sent over as a flag
// but its a persistant effect, so not critical
void SP_env_water_drip(edict_t *self)
{
if(!self->count)
{
self->count = 20;
}
self->use = waterdrip_use;
self->solid = SOLID_NOT;
self->s.effects |= EF_NODRAW_ALWAYS_SEND;
gi.linkentity(self);
self->think = waterdrip_go;
self->nextthink = level.time + 4;
}
#define FOUNTAIN_OFF 32
void fountain_use (edict_t *self, edict_t *other, edict_t *activator)
{
byte frame;
short drop;
drop = -self->delay * 8.0;
frame = 0;
if (self->spawnflags & FOUNTAIN_OFF)
{
self->PersistantCFX = gi.CreatePersistantEffect(&self->s, FX_FOUNTAIN, CEF_BROADCAST, self->s.origin, "vsb", self->s.angles, drop, frame);
self->s.sound = gi.soundindex("ambient/fountainloop.wav");
self->s.sound_data = (255 & ENT_VOL_MASK) | ATTN_STATIC;
self->spawnflags &= ~FOUNTAIN_OFF;
}
else
{
1999-03-18 00:00:00 +00:00
if (self->PersistantCFX)
{
gi.RemovePersistantEffect(self->PersistantCFX, REMOVE_WATER);
self->PersistantCFX = 0;
}
1998-11-24 00:00:00 +00:00
gi.RemoveEffects(&self->s, FX_FOUNTAIN);
self->spawnflags |= FOUNTAIN_OFF;
self->s.sound = 0;
}
}
/*QUAKED env_water_fountain (1 .5 0) (-4 -4 0) (4 4 4) RED GREEN BLUE DARK DARKER START_OFF
-------SPAWN FLAGS--------
START_OFF - fountain will be off until triggered
--------KEYS-----------
angles - xyz velocity of spawned particles
delay - the distance from emitter to ground (128 is Okay, max is 256)
If targeted it can be turned on/off but it will start on unless START_OFF
*/
// At the time of creation of this effect, I thought +ve z was down
// Hence the MINUS sign for the distance to fall
void SP_env_water_fountain(edict_t *self)
{
byte frame;
short drop;
if (self->targetname)
{
self->use = fountain_use;
}
self->s.effects |= EF_NODRAW_ALWAYS_SEND|EF_ALWAYS_ADD_EFFECTS;
gi.linkentity(self);
if (self->spawnflags & FOUNTAIN_OFF) // Start off
{
return;
}
drop = -self->delay * 8.0;
frame = 0;
self->PersistantCFX = gi.CreatePersistantEffect(&self->s, FX_FOUNTAIN, CEF_BROADCAST, self->s.origin, "vsb", self->s.angles, drop, frame);
self->s.sound = gi.soundindex("ambient/fountainloop.wav");
self->s.sound_data = (255 & ENT_VOL_MASK) | ATTN_STATIC;
}
void SpawnDripper(edict_t *self, vec3_t offset)
{
vec3_t origin;
VectorAdd(self->s.origin, offset, origin);
gi.CreatePersistantEffect(NULL, FX_DRIPPER, 0, origin, "bb", self->count, 2);
}
/*QUAKED env_waterfall_base (1 1 0) (-8 -8 -8) (8 8 8)
angles - this first field is the x radius
second is the yaw
third is the y radius
*/
void SP_env_waterfall_base(edict_t *self)
{
short xrad, yrad;
byte yaw;
self->s.effects |= EF_NODRAW_ALWAYS_SEND|EF_ALWAYS_ADD_EFFECTS;
self->svflags = 0;
xrad = Q_ftol(self->s.angles[0]);
yrad = Q_ftol(self->s.angles[2]);
yaw = Q_ftol((self->s.angles[1] * 256.0) / 360.0);
gi.linkentity(self);
gi.CreatePersistantEffect(&self->s, FX_WATERFALLBASE, CEF_BROADCAST, self->s.origin, "bbb", xrad, yrad, yaw);
}
/*QUAKED obj_fishhead1 (1 .5 0) (0 -76 -86) (136 76 86) NODRIP
Large fish head fountain. No teeth in mouth and the fins on top are connected. Also spawns 4 drips frame 0
------- FIELDS ------------------
NODRIP - won't drip
-----------------------------------
*/
void SP_obj_fishhead1 (edict_t *self)
{
vec3_t offset;
if (!(self->spawnflags & 1))
{
if(!self->count)
self->count = 20;
VectorSet(offset, -20, -60, -50);
SpawnDripper(self, offset);
VectorSet(offset, 55, 30, -70);
SpawnDripper(self, offset);
VectorSet(offset, 0, 60, -70);
SpawnDripper(self, offset);
VectorSet(offset, 65, -7, -60);
SpawnDripper(self, offset);
}
self->spawnflags |= OBJ_INVULNERABLE; // Always indestructible
self->spawnflags |= OBJ_NOPUSH; // Cant push it
VectorSet(self->mins, 0, -76, -86);
VectorSet(self->maxs, 136, 76, 86);
self->s.modelindex = gi.modelindex("models/objects/fishheads/fishhead1/tris.fm");
ObjectInit(self,100,500,MAT_GREYSTONE,SOLID_BBOX);
}
/*QUAKED obj_fishhead2 (1 .5 0) (0 -110 -118) (136 110 118) NODRIP
Large fish head fountain. The mouth has teeth. The fins on top are not conntected. Also spawns 4 drips frame 0
------- FIELDS ------------------
NODRIP - won't drip
-----------------------------------
*/
void SP_obj_fishhead2 (edict_t *self)
{
vec3_t offset;
if (!(self->spawnflags & 1))
{
if(!self->count)
self->count = 20;
VectorSet(offset, -20, -60, -50);
SpawnDripper(self, offset);
VectorSet(offset, 55, 30, -70);
SpawnDripper(self, offset);
VectorSet(offset, 0, 60, -70);
SpawnDripper(self, offset);
VectorSet(offset, 65, -7, -60);
SpawnDripper(self, offset);
}
VectorSet(self->mins, 0, -110, -118);
VectorSet(self->maxs, 136, 110, 118);
self->s.modelindex = gi.modelindex("models/objects/fishheads/fishhead2/tris.fm");
self->spawnflags |= OBJ_INVULNERABLE; // Always indestructible
self->spawnflags |= OBJ_NOPUSH; // Cant push it
self->takedamage = DAMAGE_NO;
self->movetype = PHYSICSTYPE_NONE;
self->solid = SOLID_BBOX;
self->takedamage = DAMAGE_NO;
self->clipmask = MASK_MONSTERSOLID;
BboxYawAndScale(self);
gi.linkentity(self);
// ObjectInit(self,100,500,MAT_GREYSTONE,SOLID_BBOX);
}
/*QUAK-ED obj_stalactite1 (1 .5 0) (-24 -24 -99) (24 24 99) DRIP DARKSKIN
A big long thick stalactite. These point down.
DARKSKIN - if checked it uses the dark skin
Also spawns a drip at the end
Use the "count" field as number of drips per min
*/
void SP_obj_stalactite1(edict_t *self)
{
vec3_t origin;
if(self->spawnflags & 1)
{
if(!self->count)
self->count = 20;
VectorCopy(self->s.origin, origin);
origin[2] += 200.0F;
self->PersistantCFX = gi.CreatePersistantEffect(NULL, FX_DRIPPER, 0, origin, "bb", self->count, 2);
}
self->movetype = PHYSICSTYPE_NONE;
self->solid = SOLID_BBOX;
VectorSet(self->mins, -24, -24, -99);
VectorSet(self->maxs, 24, 24, 99);
self->s.modelindex = gi.modelindex("models/objects/stalactite/stalact1/tris.fm");
if (self->spawnflags & 2)
self->s.skinnum = 1;
gi.linkentity(self);
}
/*QUAK-ED obj_stalactite2 (1 .5 0) (-60 -60 -64) (60 60 64) DRIP DARKSKIN
A big short stalactite. These point down.
DARKSKIN - if checked it uses the dark skin
Also spawns a drip at the end
Use the "count" field as number of drips per min
*/
void SP_obj_stalactite2(edict_t *self)
{
vec3_t origin;
if(self->spawnflags & 1)
{
if(!self->count)
self->count = 20;
VectorCopy(self->s.origin, origin);
origin[2] += 128.0F;
self->PersistantCFX = gi.CreatePersistantEffect(NULL, FX_DRIPPER, 0, origin, "bb", self->count, 2);
}
self->movetype = PHYSICSTYPE_NONE;
self->solid = SOLID_BBOX;
VectorSet(self->mins,-60,-60,-64);
VectorSet(self->maxs,60,60,64);
self->s.modelindex = gi.modelindex("models/objects/stalactite/stalact2/tris.fm");
if (self->spawnflags & 2)
self->s.skinnum = 1;
gi.linkentity(self);
}
/*QUAK-ED obj_stalactite3 (1 .5 0) (-23 -23 -98) (23 23 98) DRIP DARKSKIN
A long pointy stalactite. These point down.
DARKSKIN - if checked it uses the dark skin
Also spawns a drip at the end
Use the "count" field as number of drips per min
*/
void SP_obj_stalactite3(edict_t *self)
{
vec3_t origin;
if(self->spawnflags & 1)
{
if(!self->count)
self->count = 20;
VectorCopy(self->s.origin, origin);
origin[2] += 200.0F;
self->PersistantCFX = gi.CreatePersistantEffect(NULL, FX_DRIPPER, 0, origin, "bb", self->count, 2);
}
self->movetype = PHYSICSTYPE_NONE;
self->solid = SOLID_BBOX;
VectorSet(self->mins, -23, -23, -98);
VectorSet(self->maxs, 23, 23, 98);
self->s.modelindex = gi.modelindex("models/objects/stalactite/stalact3/tris.fm");
if (self->spawnflags & 2)
self->s.skinnum = 1;
gi.linkentity(self);
}
/*QUAKED env_mist (1 .5 0) (-64 -1 -32) (64 1 32)
scale sets the scale
*/
void SP_env_mist(edict_t *self)
{
byte scale;
self->s.effects |= EF_ALWAYS_ADD_EFFECTS;
scale = Q_ftol(self->s.scale * 10.0);
VectorSet(self->mins, -5, -5, -5);
VectorSet(self->maxs, 5, 5, 5);
gi.CreatePersistantEffect(&self->s, FX_MIST, CEF_BROADCAST, self->s.origin, "b", scale);
gi.linkentity(self);
}
/*QUAKED env_bubbler (1 .5 0) (-4 -4 0) (4 4 4)
Makes bubbles
---------KEYS--------
count - bubbles spawned per minute
*/
void SP_env_bubbler(edict_t *self)
{
if(!self->count)
self->count = 120;
VectorSet(self->mins, -5, -5, -5);
VectorSet(self->maxs, 5, 5, 5);
self->s.effects |= EF_ALWAYS_ADD_EFFECTS;
gi.CreatePersistantEffect(&self->s, FX_BUBBLER, CEF_BROADCAST, self->s.origin, "b", self->count);
gi.linkentity(self);
}
// end