#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); }