quake2-zaero/z_trigger.c

257 lines
5.5 KiB
C

#include "g_local.h"
/*QUAKED sound_echo (1 0 0) (-16 -16 -16) (16 16 16)
Echo any sounds that are played within "dmg_radius" radius.
"delay" "x" where x is the delay between echo's.
"wait" "x" where x is the sound volume decay percent per echo (eg. 0.1 = %10)
"dmg_radius" "x" where x is the max distance that affects sounds
*/
void SP_sound_echo (edict_t *self)
{
G_FreeEdict(self);
}
/*QUAKED load_mirrorlevel (1 0 0) (-16 -16 -16) (16 16 16)
"target" the mapname of the mirror map to this one.
*/
void SP_load_mirrorlevel (edict_t *self)
{
G_FreeEdict(self);
}
#ifdef CACHE_SOUND
int (*actual_soundindex) (char *name);
list_t *soundList;
unsigned int soundNumRejected;
typedef struct
{
char *name;
} modelsound;
void initSoundList()
{
soundList = gi.TagMalloc (sizeof(list_t), TAG_LEVEL);
initializeList(soundList);
soundNumRejected = 0;
}
int internalSoundIndex(char *name)
{
int idx = 0;
int numSounds = listLength(soundList);
modelsound *sound;
int i = 0;
// convert name to lowercase
for (i = 0; i < strlen(name); i++)
name[i] = tolower(name[i]);
// do we already have this sound?
for (i = 0; i < numSounds; i++)
{
sound = (modelsound *)getItem(soundList, i);
if(strcmp(sound->name, name) == 0)
{
return (*actual_soundindex)(name);
}
}
// ok, do we have too many sounds?
if (numSounds >= MAX_SOUNDS-1)
{
soundNumRejected++;
// ok, we cannot precache anymore
if (printSoundRejects->value)
gi.dprintf("%s precache rejected\n", name);
return 0;
}
idx = (*actual_soundindex)(name);
if (idx == 0)
return 0;
sound = gi.TagMalloc (sizeof(modelsound), TAG_LEVEL);
sound->name = gi.TagMalloc (strlen(name) + 1, TAG_LEVEL);
strcpy(sound->name, name);
addTail(soundList, sound);
//gi.dprintf("numSounds = %i\n", listLength(&soundList));
return idx;
}
void printSoundNum()
{
int numSounds = listLength(soundList);
gi.dprintf("%i precached sounds\n", numSounds);
if (printSoundRejects->value)
gi.dprintf("%i sounds rejected\n", soundNumRejected);
}
#endif
/********************************************
trigger_laser
*/
/*QUAKED trigger_laser (1 0 0) (-16 -16 -16) (16 16 16) TRIGGER_MULTIPLE
Laser-type trigger
"wait" "x" where x is the delay before reactivation
"target" target to trigger
"message" message to center print
"delay" delay before trigger
*/
#define TRIGGER_MULTIPLE 1
void trigger_laser_on (edict_t *self);
void trigger_laser_think (edict_t *self)
{
vec3_t start;
vec3_t end;
trace_t tr;
int count = 8;
self->nextthink = level.time + FRAMETIME;
VectorCopy (self->s.origin, start);
VectorMA (start, 2048, self->movedir, end);
tr = gi.trace (start, NULL, NULL, end, self, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_DEADMONSTER);
if (!tr.ent)
return;
// if we hit something that's not a monster or player
if (!(tr.ent->svflags & SVF_MONSTER) && (!tr.ent->client))
{
if (self->spawnflags & 0x80000000)
{
self->spawnflags &= ~0x80000000;
gi.WriteByte (svc_temp_entity);
gi.WriteByte (TE_LASER_SPARKS);
gi.WriteByte (count);
gi.WritePosition (tr.endpos);
gi.WriteDir (tr.plane.normal);
gi.WriteByte (self->s.skinnum);
gi.multicast (tr.endpos, MULTICAST_PVS);
}
}
else
{
// trigger
G_UseTargets (self, tr.ent);
if (self->spawnflags & TRIGGER_MULTIPLE)
{
// hide for a time
self->svflags |= SVF_NOCLIENT;
self->nextthink = level.time + self->wait;
self->think = trigger_laser_on;
}
else
{
// remove self
G_FreeEdict(self);
}
}
VectorCopy (tr.endpos, self->s.old_origin);
}
void trigger_laser_on (edict_t *self)
{
self->svflags &= ~SVF_NOCLIENT;
self->think = trigger_laser_think;
trigger_laser_think(self);
}
void SP_trigger_laser(edict_t *self)
{
// if no target
if (!self->target)
{
gi.dprintf("trigger_laser without target\n");
G_FreeEdict(self);
return;
}
// if no wait, set default
if (!self->wait)
{
self->wait = 4;
}
G_SetMovedir (self->s.angles, self->movedir);
self->s.skinnum = 0xf2f2f0f0; // colour
self->s.frame = 2; // diameter
self->movetype = MOVETYPE_NONE;
self->solid = SOLID_NOT;
self->s.renderfx |= RF_BEAM|RF_TRANSLUCENT;
self->s.modelindex = 1;
self->spawnflags |= 0x80000000;
self->think = trigger_laser_on;
self->nextthink = level.time + 0.1;
self->svflags |= SVF_NOCLIENT;
gi.linkentity (self);
}
/*QUAKED misc_commdish (0 .5 .8) (-16 -16 0) (16 16 40)
*/
void Anim_CommDish(edict_t *self)
{
self->s.frame++;
if(self->s.frame >= 98)
{
self->s.frame = 98;
}
else
{
self->nextthink = level.time + FRAMETIME;
}
}
void Use_CommDish (edict_t *ent, edict_t *other, edict_t *activator)
{
ent->nextthink = level.time + FRAMETIME;
ent->think = Anim_CommDish;
ent->use = NULL;
gi.sound (ent, CHAN_AUTO, gi.soundindex ("misc/commdish.wav"), 1, ATTN_NORM, 0);
}
void SP_misc_commdish (edict_t *self)
{
if (deathmatch->value)
{ // auto-remove for deathmatch
G_FreeEdict (self);
return;
}
self->solid = SOLID_BBOX;
self->movetype = MOVETYPE_STEP;
self->model = "models/objects/satdish/tris.md2";
self->s.modelindex = gi.modelindex (self->model);
VectorSet (self->mins, -100, -100, 0);
VectorSet (self->maxs, 100, 100, 275);
self->monsterinfo.aiflags = AI_NOSTEP;
self->think = M_droptofloor;
self->nextthink = level.time + 2 * FRAMETIME;
self->use = Use_CommDish;
gi.linkentity (self);
}