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