1 #include "g_local.h"
2 
3 
4 /*QUAKED sound_echo (1 0 0) (-16 -16 -16) (16 16 16)
5 Echo any sounds that are played within "dmg_radius" radius.
6 "delay"      "x" where x is the delay between echo's.
7 "wait"       "x" where x is the sound volume decay percent per echo (eg. 0.1 = %10)
8 "dmg_radius" "x" where x is the max distance that affects sounds
9 */
10 
SP_sound_echo(edict_t * self)11 void SP_sound_echo (edict_t *self)
12 {
13 	G_FreeEdict(self);
14 }
15 
16 /*QUAKED load_mirrorlevel (1 0 0) (-16 -16 -16) (16 16 16)
17  "target" the mapname of the mirror map to this one.
18 */
19 
SP_load_mirrorlevel(edict_t * self)20 void SP_load_mirrorlevel (edict_t *self)
21 {
22 	G_FreeEdict(self);
23 }
24 
25 #ifdef CACHE_SOUND
26 int	(*actual_soundindex) (char *name);
27 
28 list_t *soundList;
29 unsigned int soundNumRejected;
30 
31 typedef struct
32 {
33   char *name;
34 
35 } modelsound;
36 
initSoundList()37 void initSoundList()
38 {
39 	soundList = gi.TagMalloc (sizeof(list_t), TAG_LEVEL);
40 	initializeList(soundList);
41 	soundNumRejected = 0;
42 }
43 
internalSoundIndex(char * name)44 int internalSoundIndex(char *name)
45 {
46 	int idx = 0;
47 	int numSounds = listLength(soundList);
48 	modelsound *sound;
49 	int i = 0;
50 
51 	// convert name to lowercase
52 	for (i = 0; i < strlen(name); i++)
53 		name[i] = tolower(name[i]);
54 
55 	// do we already have this sound?
56 	for (i = 0; i < numSounds; i++)
57 	{
58 		sound = (modelsound *)getItem(soundList, i);
59 		if(strcmp(sound->name, name) == 0)
60 		{
61 			return (*actual_soundindex)(name);
62 		}
63 	}
64 
65 	// ok, do we have too many sounds?
66 	if (numSounds >= MAX_SOUNDS-1)
67 	{
68 		soundNumRejected++;
69 		// ok, we cannot precache anymore
70 		if (printSoundRejects->value)
71 			gi.dprintf("%s precache rejected\n", name);
72 		return 0;
73 	}
74 
75 	idx = (*actual_soundindex)(name);
76 	if (idx == 0)
77 		return 0;
78 
79 	sound = gi.TagMalloc (sizeof(modelsound), TAG_LEVEL);
80 	sound->name = gi.TagMalloc (strlen(name) + 1, TAG_LEVEL);
81 	strcpy(sound->name, name);
82 
83 	addTail(soundList, sound);
84 	//gi.dprintf("numSounds = %i\n", listLength(&soundList));
85 
86 	return idx;
87 }
88 
printSoundNum()89 void printSoundNum()
90 {
91 	int numSounds = listLength(soundList);
92 	gi.dprintf("%i precached sounds\n", numSounds);
93 	if (printSoundRejects->value)
94 		gi.dprintf("%i sounds rejected\n", soundNumRejected);
95 }
96 #endif
97 
98 
99 /********************************************
100 	trigger_laser
101 */
102 
103 /*QUAKED trigger_laser (1 0 0) (-16 -16 -16) (16 16 16) TRIGGER_MULTIPLE
104 Laser-type trigger
105 "wait"       "x" where x is the delay before reactivation
106 "target"     target to trigger
107 "message"    message to center print
108 "delay"      delay before trigger
109 */
110 
111 #define TRIGGER_MULTIPLE	1
112 void trigger_laser_on (edict_t *self);
trigger_laser_think(edict_t * self)113 void trigger_laser_think (edict_t *self)
114 {
115 	vec3_t	start;
116 	vec3_t	end;
117 	trace_t	tr;
118 	int		count = 8;
119 
120 	self->nextthink = level.time + FRAMETIME;
121 
122 	VectorCopy (self->s.origin, start);
123 	VectorMA (start, 2048, self->movedir, end);
124 	tr = gi.trace (start, NULL, NULL, end, self, CONTENTS_SOLID|CONTENTS_MONSTER|CONTENTS_DEADMONSTER);
125 
126 	if (!tr.ent)
127 		return;
128 
129 	// if we hit something that's not a monster or player
130 	if (!(tr.ent->svflags & SVF_MONSTER) && (!tr.ent->client))
131 	{
132 		if (self->spawnflags & 0x80000000)
133 		{
134 			self->spawnflags &= ~0x80000000;
135 			gi.WriteByte (svc_temp_entity);
136 			gi.WriteByte (TE_LASER_SPARKS);
137 			gi.WriteByte (count);
138 			gi.WritePosition (tr.endpos);
139 			gi.WriteDir (tr.plane.normal);
140 			gi.WriteByte (self->s.skinnum);
141 			gi.multicast (tr.endpos, MULTICAST_PVS);
142 		}
143 	}
144 	else
145 	{
146 		// trigger
147 		G_UseTargets (self, tr.ent);
148 
149 		if (self->spawnflags & TRIGGER_MULTIPLE)
150 		{
151 			// hide for a time
152 			self->svflags |= SVF_NOCLIENT;
153 			self->nextthink = level.time + self->wait;
154 			self->think = trigger_laser_on;
155 		}
156 		else
157 		{
158 			// remove self
159 			G_FreeEdict(self);
160 		}
161 	}
162 
163 	VectorCopy (tr.endpos, self->s.old_origin);
164 }
165 
trigger_laser_on(edict_t * self)166 void trigger_laser_on (edict_t *self)
167 {
168 	self->svflags &= ~SVF_NOCLIENT;
169 	self->think = trigger_laser_think;
170 	trigger_laser_think(self);
171 }
172 
SP_trigger_laser(edict_t * self)173 void SP_trigger_laser(edict_t *self)
174 {
175 	// if no target
176 	if (!self->target)
177 	{
178 		gi.dprintf("trigger_laser without target\n");
179 		G_FreeEdict(self);
180 		return;
181 	}
182 
183 	// if no wait, set default
184 	if (!self->wait)
185 	{
186 		self->wait = 4;
187 	}
188 
189 	G_SetMovedir (self->s.angles, self->movedir);
190 	self->s.skinnum = 0xf2f2f0f0;	// colour
191 	self->s.frame = 2;				// diameter
192 	self->movetype = MOVETYPE_NONE;
193 	self->solid = SOLID_NOT;
194 	self->s.renderfx |= RF_BEAM|RF_TRANSLUCENT;
195 	self->s.modelindex = 1;
196 	self->spawnflags |= 0x80000000;
197 	self->think = trigger_laser_on;
198 	self->nextthink = level.time + 0.1;
199 	self->svflags |= SVF_NOCLIENT;
200 	gi.linkentity (self);
201 }
202 
203 
204 
205 
206 
207 
208 /*QUAKED misc_commdish (0 .5 .8) (-16 -16 0) (16 16 40)
209 */
210 
Anim_CommDish(edict_t * self)211 void Anim_CommDish(edict_t *self)
212 {
213 	self->s.frame++;
214 
215   if(self->s.frame >= 98)
216   {
217     self->s.frame = 98;
218   }
219   else
220   {
221     self->nextthink = level.time + FRAMETIME;
222   }
223 }
224 
Use_CommDish(edict_t * ent,edict_t * other,edict_t * activator)225 void Use_CommDish (edict_t *ent, edict_t *other, edict_t *activator)
226 {
227   ent->nextthink = level.time + FRAMETIME;
228 	ent->think = Anim_CommDish;
229   ent->use = NULL;
230 	gi.sound (ent, CHAN_AUTO, gi.soundindex ("misc/commdish.wav"), 1, ATTN_NORM, 0);
231 }
232 
SP_misc_commdish(edict_t * self)233 void SP_misc_commdish (edict_t *self)
234 {
235 	if (deathmatch->value)
236 	{	// auto-remove for deathmatch
237 		G_FreeEdict (self);
238 		return;
239 	}
240 
241 	self->solid = SOLID_BBOX;
242 	self->movetype = MOVETYPE_STEP;
243 
244 	self->model = "models/objects/satdish/tris.md2";
245 	self->s.modelindex = gi.modelindex (self->model);
246 	VectorSet (self->mins, -100, -100, 0);
247 	VectorSet (self->maxs, 100, 100, 275);
248 
249 	self->monsterinfo.aiflags = AI_NOSTEP;
250 
251 	self->think = M_droptofloor;
252 	self->nextthink = level.time + 2 * FRAMETIME;
253 	self->use = Use_CommDish;
254 
255 	gi.linkentity (self);
256 }
257