Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5131 | clevermous | 1 | /* |
2 | Copyright (C) 1996-1997 Id Software, Inc. |
||
3 | |||
4 | This program is free software; you can redistribute it and/or |
||
5 | modify it under the terms of the GNU General Public License |
||
6 | as published by the Free Software Foundation; either version 2 |
||
7 | of the License, or (at your option) any later version. |
||
8 | |||
9 | This program is distributed in the hope that it will be useful, |
||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
||
12 | |||
13 | See the GNU General Public License for more details. |
||
14 | |||
15 | You should have received a copy of the GNU General Public License |
||
16 | along with this program; if not, write to the Free Software |
||
17 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
||
18 | |||
19 | */ |
||
20 | // cl_tent.c -- client side temporary entities |
||
21 | |||
22 | #include "quakedef.h" |
||
23 | |||
24 | int num_temp_entities; |
||
25 | entity_t cl_temp_entities[MAX_TEMP_ENTITIES]; |
||
26 | beam_t cl_beams[MAX_BEAMS]; |
||
27 | |||
28 | sfx_t *cl_sfx_wizhit; |
||
29 | sfx_t *cl_sfx_knighthit; |
||
30 | sfx_t *cl_sfx_tink1; |
||
31 | sfx_t *cl_sfx_ric1; |
||
32 | sfx_t *cl_sfx_ric2; |
||
33 | sfx_t *cl_sfx_ric3; |
||
34 | sfx_t *cl_sfx_r_exp3; |
||
35 | #ifdef QUAKE2 |
||
36 | sfx_t *cl_sfx_imp; |
||
37 | sfx_t *cl_sfx_rail; |
||
38 | #endif |
||
39 | |||
40 | /* |
||
41 | ================= |
||
42 | CL_ParseTEnt |
||
43 | ================= |
||
44 | */ |
||
45 | void CL_InitTEnts (void) |
||
46 | { |
||
47 | cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav"); |
||
48 | cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav"); |
||
49 | cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav"); |
||
50 | cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav"); |
||
51 | cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav"); |
||
52 | cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav"); |
||
53 | cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav"); |
||
54 | #ifdef QUAKE2 |
||
55 | cl_sfx_imp = S_PrecacheSound ("shambler/sattck1.wav"); |
||
56 | cl_sfx_rail = S_PrecacheSound ("weapons/lstart.wav"); |
||
57 | #endif |
||
58 | } |
||
59 | |||
60 | /* |
||
61 | ================= |
||
62 | CL_ParseBeam |
||
63 | ================= |
||
64 | */ |
||
65 | void CL_ParseBeam (model_t *m) |
||
66 | { |
||
67 | int ent; |
||
68 | vec3_t start, end; |
||
69 | beam_t *b; |
||
70 | int i; |
||
71 | |||
72 | ent = MSG_ReadShort (); |
||
73 | |||
74 | start[0] = MSG_ReadCoord (); |
||
75 | start[1] = MSG_ReadCoord (); |
||
76 | start[2] = MSG_ReadCoord (); |
||
77 | |||
78 | end[0] = MSG_ReadCoord (); |
||
79 | end[1] = MSG_ReadCoord (); |
||
80 | end[2] = MSG_ReadCoord (); |
||
81 | |||
82 | // override any beam with the same entity |
||
83 | for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++) |
||
84 | if (b->entity == ent) |
||
85 | { |
||
86 | b->entity = ent; |
||
87 | b->model = m; |
||
88 | b->endtime = cl.time + 0.2; |
||
89 | VectorCopy (start, b->start); |
||
90 | VectorCopy (end, b->end); |
||
91 | return; |
||
92 | } |
||
93 | |||
94 | // find a free beam |
||
95 | for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++) |
||
96 | { |
||
97 | if (!b->model || b->endtime < cl.time) |
||
98 | { |
||
99 | b->entity = ent; |
||
100 | b->model = m; |
||
101 | b->endtime = cl.time + 0.2; |
||
102 | VectorCopy (start, b->start); |
||
103 | VectorCopy (end, b->end); |
||
104 | return; |
||
105 | } |
||
106 | } |
||
107 | Con_Printf ("beam list overflow!\n"); |
||
108 | } |
||
109 | |||
110 | /* |
||
111 | ================= |
||
112 | CL_ParseTEnt |
||
113 | ================= |
||
114 | */ |
||
115 | void CL_ParseTEnt (void) |
||
116 | { |
||
117 | int type; |
||
118 | vec3_t pos; |
||
119 | #ifdef QUAKE2 |
||
120 | vec3_t endpos; |
||
121 | #endif |
||
122 | dlight_t *dl; |
||
123 | int rnd; |
||
124 | int colorStart, colorLength; |
||
125 | |||
126 | type = MSG_ReadByte (); |
||
127 | switch (type) |
||
128 | { |
||
129 | case TE_WIZSPIKE: // spike hitting wall |
||
130 | pos[0] = MSG_ReadCoord (); |
||
131 | pos[1] = MSG_ReadCoord (); |
||
132 | pos[2] = MSG_ReadCoord (); |
||
133 | R_RunParticleEffect (pos, vec3_origin, 20, 30); |
||
134 | S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1); |
||
135 | break; |
||
136 | |||
137 | case TE_KNIGHTSPIKE: // spike hitting wall |
||
138 | pos[0] = MSG_ReadCoord (); |
||
139 | pos[1] = MSG_ReadCoord (); |
||
140 | pos[2] = MSG_ReadCoord (); |
||
141 | R_RunParticleEffect (pos, vec3_origin, 226, 20); |
||
142 | S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1); |
||
143 | break; |
||
144 | |||
145 | case TE_SPIKE: // spike hitting wall |
||
146 | pos[0] = MSG_ReadCoord (); |
||
147 | pos[1] = MSG_ReadCoord (); |
||
148 | pos[2] = MSG_ReadCoord (); |
||
149 | #ifdef GLTEST |
||
150 | Test_Spawn (pos); |
||
151 | #else |
||
152 | R_RunParticleEffect (pos, vec3_origin, 0, 10); |
||
153 | #endif |
||
154 | if ( rand() % 5 ) |
||
155 | S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1); |
||
156 | else |
||
157 | { |
||
158 | rnd = rand() & 3; |
||
159 | if (rnd == 1) |
||
160 | S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1); |
||
161 | else if (rnd == 2) |
||
162 | S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1); |
||
163 | else |
||
164 | S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1); |
||
165 | } |
||
166 | break; |
||
167 | case TE_SUPERSPIKE: // super spike hitting wall |
||
168 | pos[0] = MSG_ReadCoord (); |
||
169 | pos[1] = MSG_ReadCoord (); |
||
170 | pos[2] = MSG_ReadCoord (); |
||
171 | R_RunParticleEffect (pos, vec3_origin, 0, 20); |
||
172 | |||
173 | if ( rand() % 5 ) |
||
174 | S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1); |
||
175 | else |
||
176 | { |
||
177 | rnd = rand() & 3; |
||
178 | if (rnd == 1) |
||
179 | S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1); |
||
180 | else if (rnd == 2) |
||
181 | S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1); |
||
182 | else |
||
183 | S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1); |
||
184 | } |
||
185 | break; |
||
186 | |||
187 | case TE_GUNSHOT: // bullet hitting wall |
||
188 | pos[0] = MSG_ReadCoord (); |
||
189 | pos[1] = MSG_ReadCoord (); |
||
190 | pos[2] = MSG_ReadCoord (); |
||
191 | R_RunParticleEffect (pos, vec3_origin, 0, 20); |
||
192 | break; |
||
193 | |||
194 | case TE_EXPLOSION: // rocket explosion |
||
195 | pos[0] = MSG_ReadCoord (); |
||
196 | pos[1] = MSG_ReadCoord (); |
||
197 | pos[2] = MSG_ReadCoord (); |
||
198 | R_ParticleExplosion (pos); |
||
199 | dl = CL_AllocDlight (0); |
||
200 | VectorCopy (pos, dl->origin); |
||
201 | dl->radius = 350; |
||
202 | dl->die = cl.time + 0.5; |
||
203 | dl->decay = 300; |
||
204 | S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); |
||
205 | break; |
||
206 | |||
207 | case TE_TAREXPLOSION: // tarbaby explosion |
||
208 | pos[0] = MSG_ReadCoord (); |
||
209 | pos[1] = MSG_ReadCoord (); |
||
210 | pos[2] = MSG_ReadCoord (); |
||
211 | R_BlobExplosion (pos); |
||
212 | |||
213 | S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); |
||
214 | break; |
||
215 | |||
216 | case TE_LIGHTNING1: // lightning bolts |
||
217 | CL_ParseBeam (Mod_ForName("progs/bolt.mdl", true)); |
||
218 | break; |
||
219 | |||
220 | case TE_LIGHTNING2: // lightning bolts |
||
221 | CL_ParseBeam (Mod_ForName("progs/bolt2.mdl", true)); |
||
222 | break; |
||
223 | |||
224 | case TE_LIGHTNING3: // lightning bolts |
||
225 | CL_ParseBeam (Mod_ForName("progs/bolt3.mdl", true)); |
||
226 | break; |
||
227 | |||
228 | // PGM 01/21/97 |
||
229 | case TE_BEAM: // grappling hook beam |
||
230 | CL_ParseBeam (Mod_ForName("progs/beam.mdl", true)); |
||
231 | break; |
||
232 | // PGM 01/21/97 |
||
233 | |||
234 | case TE_LAVASPLASH: |
||
235 | pos[0] = MSG_ReadCoord (); |
||
236 | pos[1] = MSG_ReadCoord (); |
||
237 | pos[2] = MSG_ReadCoord (); |
||
238 | R_LavaSplash (pos); |
||
239 | break; |
||
240 | |||
241 | case TE_TELEPORT: |
||
242 | pos[0] = MSG_ReadCoord (); |
||
243 | pos[1] = MSG_ReadCoord (); |
||
244 | pos[2] = MSG_ReadCoord (); |
||
245 | R_TeleportSplash (pos); |
||
246 | break; |
||
247 | |||
248 | case TE_EXPLOSION2: // color mapped explosion |
||
249 | pos[0] = MSG_ReadCoord (); |
||
250 | pos[1] = MSG_ReadCoord (); |
||
251 | pos[2] = MSG_ReadCoord (); |
||
252 | colorStart = MSG_ReadByte (); |
||
253 | colorLength = MSG_ReadByte (); |
||
254 | R_ParticleExplosion2 (pos, colorStart, colorLength); |
||
255 | dl = CL_AllocDlight (0); |
||
256 | VectorCopy (pos, dl->origin); |
||
257 | dl->radius = 350; |
||
258 | dl->die = cl.time + 0.5; |
||
259 | dl->decay = 300; |
||
260 | S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1); |
||
261 | break; |
||
262 | |||
263 | #ifdef QUAKE2 |
||
264 | case TE_IMPLOSION: |
||
265 | pos[0] = MSG_ReadCoord (); |
||
266 | pos[1] = MSG_ReadCoord (); |
||
267 | pos[2] = MSG_ReadCoord (); |
||
268 | S_StartSound (-1, 0, cl_sfx_imp, pos, 1, 1); |
||
269 | break; |
||
270 | |||
271 | case TE_RAILTRAIL: |
||
272 | pos[0] = MSG_ReadCoord (); |
||
273 | pos[1] = MSG_ReadCoord (); |
||
274 | pos[2] = MSG_ReadCoord (); |
||
275 | endpos[0] = MSG_ReadCoord (); |
||
276 | endpos[1] = MSG_ReadCoord (); |
||
277 | endpos[2] = MSG_ReadCoord (); |
||
278 | S_StartSound (-1, 0, cl_sfx_rail, pos, 1, 1); |
||
279 | S_StartSound (-1, 1, cl_sfx_r_exp3, endpos, 1, 1); |
||
280 | R_RocketTrail (pos, endpos, 0+128); |
||
281 | R_ParticleExplosion (endpos); |
||
282 | dl = CL_AllocDlight (-1); |
||
283 | VectorCopy (endpos, dl->origin); |
||
284 | dl->radius = 350; |
||
285 | dl->die = cl.time + 0.5; |
||
286 | dl->decay = 300; |
||
287 | break; |
||
288 | #endif |
||
289 | |||
290 | default: |
||
291 | Sys_Error ("CL_ParseTEnt: bad type"); |
||
292 | } |
||
293 | } |
||
294 | |||
295 | |||
296 | /* |
||
297 | ================= |
||
298 | CL_NewTempEntity |
||
299 | ================= |
||
300 | */ |
||
301 | entity_t *CL_NewTempEntity (void) |
||
302 | { |
||
303 | entity_t *ent; |
||
304 | |||
305 | if (cl_numvisedicts == MAX_VISEDICTS) |
||
306 | return NULL; |
||
307 | if (num_temp_entities == MAX_TEMP_ENTITIES) |
||
308 | return NULL; |
||
309 | ent = &cl_temp_entities[num_temp_entities]; |
||
310 | memset (ent, 0, sizeof(*ent)); |
||
311 | num_temp_entities++; |
||
312 | cl_visedicts[cl_numvisedicts] = ent; |
||
313 | cl_numvisedicts++; |
||
314 | |||
315 | ent->colormap = vid.colormap; |
||
316 | return ent; |
||
317 | } |
||
318 | |||
319 | |||
320 | /* |
||
321 | ================= |
||
322 | CL_UpdateTEnts |
||
323 | ================= |
||
324 | */ |
||
325 | void CL_UpdateTEnts (void) |
||
326 | { |
||
327 | int i; |
||
328 | beam_t *b; |
||
329 | vec3_t dist, org; |
||
330 | float d; |
||
331 | entity_t *ent; |
||
332 | float yaw, pitch; |
||
333 | float forward; |
||
334 | |||
335 | num_temp_entities = 0; |
||
336 | |||
337 | // update lightning |
||
338 | for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++) |
||
339 | { |
||
340 | if (!b->model || b->endtime < cl.time) |
||
341 | continue; |
||
342 | |||
343 | // if coming from the player, update the start position |
||
344 | if (b->entity == cl.viewentity) |
||
345 | { |
||
346 | VectorCopy (cl_entities[cl.viewentity].origin, b->start); |
||
347 | } |
||
348 | |||
349 | // calculate pitch and yaw |
||
350 | VectorSubtract (b->end, b->start, dist); |
||
351 | |||
352 | if (dist[1] == 0 && dist[0] == 0) |
||
353 | { |
||
354 | yaw = 0; |
||
355 | if (dist[2] > 0) |
||
356 | pitch = 90; |
||
357 | else |
||
358 | pitch = 270; |
||
359 | } |
||
360 | else |
||
361 | { |
||
362 | yaw = (int) (atan2(dist[1], dist[0]) * 180 / M_PI); |
||
363 | if (yaw < 0) |
||
364 | yaw += 360; |
||
365 | |||
366 | forward = sqrt (dist[0]*dist[0] + dist[1]*dist[1]); |
||
367 | pitch = (int) (atan2(dist[2], forward) * 180 / M_PI); |
||
368 | if (pitch < 0) |
||
369 | pitch += 360; |
||
370 | } |
||
371 | |||
372 | // add new entities for the lightning |
||
373 | VectorCopy (b->start, org); |
||
374 | d = VectorNormalize(dist); |
||
375 | while (d > 0) |
||
376 | { |
||
377 | ent = CL_NewTempEntity (); |
||
378 | if (!ent) |
||
379 | return; |
||
380 | VectorCopy (org, ent->origin); |
||
381 | ent->model = b->model; |
||
382 | ent->angles[0] = pitch; |
||
383 | ent->angles[1] = yaw; |
||
384 | ent->angles[2] = rand()%360; |
||
385 | |||
386 | for (i=0 ; i<3 ; i++) |
||
387 | org[i] += dist[i]*30; |
||
388 | d -= 30; |
||
389 | } |
||
390 | } |
||
391 | |||
392 | }3>>>>>>>> |
||
393 |