2 Copyright (C) 1996-1997 Id Software, Inc.
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.
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.
13 See the GNU General Public License for more details.
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.
20 // cl_tent.c -- client side temporary entities
24 int num_temp_entities;
25 entity_t cl_temp_entities[MAX_TEMP_ENTITIES];
26 beam_t cl_beams[MAX_BEAMS];
29 sfx_t *cl_sfx_knighthit;
41 void CL_InitTEnts (void)
43 cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav");
44 cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav");
45 cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav");
46 cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav");
47 cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav");
48 cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav");
49 cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav");
57 void CL_ParseBeam (model_t *m)
64 ent = MSG_ReadShort ();
66 start[0] = MSG_ReadCoord ();
67 start[1] = MSG_ReadCoord ();
68 start[2] = MSG_ReadCoord ();
70 end[0] = MSG_ReadCoord ();
71 end[1] = MSG_ReadCoord ();
72 end[2] = MSG_ReadCoord ();
74 // override any beam with the same entity
75 for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
80 b->endtime = cl.time + 0.2;
81 VectorCopy (start, b->start);
82 VectorCopy (end, b->end);
87 for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
89 if (!b->model || b->endtime < cl.time)
93 b->endtime = cl.time + 0.2;
94 VectorCopy (start, b->start);
95 VectorCopy (end, b->end);
99 Con_Printf ("beam list overflow!\n");
102 //void R_BlastParticles(vec3_t org, vec_t radius, vec_t power);
103 void R_BloodShower (vec3_t mins, vec3_t maxs, float velspeed, int count);
104 void R_ParticleCube (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorbase, int gravity, int randomvel);
105 void R_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorbase, int type);
112 void CL_ParseTEnt (void)
120 int colorStart, colorLength, count;
124 type = MSG_ReadByte ();
127 case TE_WIZSPIKE: // spike hitting wall
128 pos[0] = MSG_ReadCoord ();
129 pos[1] = MSG_ReadCoord ();
130 pos[2] = MSG_ReadCoord ();
131 R_RunParticleEffect (pos, vec3_origin, 20, 30);
132 S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1);
135 case TE_KNIGHTSPIKE: // spike hitting wall
136 pos[0] = MSG_ReadCoord ();
137 pos[1] = MSG_ReadCoord ();
138 pos[2] = MSG_ReadCoord ();
139 R_RunParticleEffect (pos, vec3_origin, 226, 20);
140 S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1);
143 case TE_SPIKE: // spike hitting wall
144 pos[0] = MSG_ReadCoord ();
145 pos[1] = MSG_ReadCoord ();
146 pos[2] = MSG_ReadCoord ();
147 // LordHavoc: changed to spark shower
148 R_SparkShower(pos, vec3_origin, 15);
149 //R_RunParticleEffect (pos, vec3_origin, 0, 10);
151 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
156 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
158 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
160 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
163 case TE_SPIKEQUAD: // quad spike hitting wall
164 pos[0] = MSG_ReadCoord ();
165 pos[1] = MSG_ReadCoord ();
166 pos[2] = MSG_ReadCoord ();
167 // LordHavoc: changed to spark shower
168 R_SparkShower(pos, vec3_origin, 15);
169 //R_RunParticleEffect (pos, vec3_origin, 0, 10);
170 dl = CL_AllocDlight (0);
171 VectorCopy (pos, dl->origin);
173 dl->die = cl.time + 0.2;
175 dl->color[0] = 0.05;dl->color[1] = 0.05;dl->color[2] = 0.8;
176 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
178 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
183 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
185 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
187 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
190 case TE_SUPERSPIKE: // super spike hitting wall
191 pos[0] = MSG_ReadCoord ();
192 pos[1] = MSG_ReadCoord ();
193 pos[2] = MSG_ReadCoord ();
194 // LordHavoc: changed to dust shower
195 R_SparkShower(pos, vec3_origin, 30);
196 //R_RunParticleEffect (pos, vec3_origin, 0, 20);
198 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
203 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
205 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
207 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
210 case TE_SUPERSPIKEQUAD: // quad super spike hitting wall
211 pos[0] = MSG_ReadCoord ();
212 pos[1] = MSG_ReadCoord ();
213 pos[2] = MSG_ReadCoord ();
214 // LordHavoc: changed to dust shower
215 R_SparkShower(pos, vec3_origin, 30);
216 //R_RunParticleEffect (pos, vec3_origin, 0, 20);
217 dl = CL_AllocDlight (0);
218 VectorCopy (pos, dl->origin);
220 dl->die = cl.time + 0.2;
222 dl->color[0] = 0.05;dl->color[1] = 0.05;dl->color[2] = 0.8;
224 S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
229 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
231 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
233 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
236 // LordHavoc: added for improved blood splatters
237 case TE_BLOOD: // blood puff
238 pos[0] = MSG_ReadCoord ();
239 pos[1] = MSG_ReadCoord ();
240 pos[2] = MSG_ReadCoord ();
241 dir[0] = MSG_ReadChar ();
242 dir[1] = MSG_ReadChar ();
243 dir[2] = MSG_ReadChar ();
244 count = MSG_ReadByte (); // amount of particles
247 case TE_BLOOD2: // blood puff
248 pos[0] = MSG_ReadCoord ();
249 pos[1] = MSG_ReadCoord ();
250 pos[2] = MSG_ReadCoord ();
253 case TE_SPARK: // spark shower
254 pos[0] = MSG_ReadCoord ();
255 pos[1] = MSG_ReadCoord ();
256 pos[2] = MSG_ReadCoord ();
257 dir[0] = MSG_ReadChar ();
258 dir[1] = MSG_ReadChar ();
259 dir[2] = MSG_ReadChar ();
260 count = MSG_ReadByte (); // amount of particles
261 R_SparkShower(pos, dir, count);
263 // LordHavoc: added for improved gore
264 case TE_BLOODSHOWER: // vaporized body
265 pos[0] = MSG_ReadCoord (); // mins
266 pos[1] = MSG_ReadCoord ();
267 pos[2] = MSG_ReadCoord ();
268 dir[0] = MSG_ReadCoord (); // maxs
269 dir[1] = MSG_ReadCoord ();
270 dir[2] = MSG_ReadCoord ();
271 velspeed = MSG_ReadCoord (); // speed
272 count = MSG_ReadShort (); // number of particles
273 R_BloodShower(pos, dir, velspeed, count);
275 case TE_PARTICLECUBE: // general purpose particle effect
276 pos[0] = MSG_ReadCoord (); // mins
277 pos[1] = MSG_ReadCoord ();
278 pos[2] = MSG_ReadCoord ();
279 pos2[0] = MSG_ReadCoord (); // maxs
280 pos2[1] = MSG_ReadCoord ();
281 pos2[2] = MSG_ReadCoord ();
282 dir[0] = MSG_ReadCoord (); // dir
283 dir[1] = MSG_ReadCoord ();
284 dir[2] = MSG_ReadCoord ();
285 count = MSG_ReadShort (); // number of particles
286 colorStart = MSG_ReadByte (); // color
287 colorLength = MSG_ReadByte (); // gravity (1 or 0)
288 velspeed = MSG_ReadCoord (); // randomvel
289 R_ParticleCube(pos, pos2, dir, count, colorStart, colorLength, velspeed);
292 case TE_PARTICLERAIN: // general purpose particle effect
293 pos[0] = MSG_ReadCoord (); // mins
294 pos[1] = MSG_ReadCoord ();
295 pos[2] = MSG_ReadCoord ();
296 pos2[0] = MSG_ReadCoord (); // maxs
297 pos2[1] = MSG_ReadCoord ();
298 pos2[2] = MSG_ReadCoord ();
299 dir[0] = MSG_ReadCoord (); // dir
300 dir[1] = MSG_ReadCoord ();
301 dir[2] = MSG_ReadCoord ();
302 count = MSG_ReadShort (); // number of particles
303 colorStart = MSG_ReadByte (); // color
304 R_ParticleRain(pos, pos2, dir, count, colorStart, 0);
307 case TE_PARTICLESNOW: // general purpose particle effect
308 pos[0] = MSG_ReadCoord (); // mins
309 pos[1] = MSG_ReadCoord ();
310 pos[2] = MSG_ReadCoord ();
311 pos2[0] = MSG_ReadCoord (); // maxs
312 pos2[1] = MSG_ReadCoord ();
313 pos2[2] = MSG_ReadCoord ();
314 dir[0] = MSG_ReadCoord (); // dir
315 dir[1] = MSG_ReadCoord ();
316 dir[2] = MSG_ReadCoord ();
317 count = MSG_ReadShort (); // number of particles
318 colorStart = MSG_ReadByte (); // color
319 R_ParticleRain(pos, pos2, dir, count, colorStart, 1);
322 case TE_GUNSHOT: // bullet hitting wall
323 pos[0] = MSG_ReadCoord ();
324 pos[1] = MSG_ReadCoord ();
325 pos[2] = MSG_ReadCoord ();
326 // LordHavoc: changed to dust shower
327 R_SparkShower(pos, vec3_origin, 15);
328 //R_RunParticleEffect (pos, vec3_origin, 0, 20);
331 case TE_GUNSHOTQUAD: // quad bullet hitting wall
332 pos[0] = MSG_ReadCoord ();
333 pos[1] = MSG_ReadCoord ();
334 pos[2] = MSG_ReadCoord ();
335 R_SparkShower(pos, vec3_origin, 15);
336 dl = CL_AllocDlight (0);
337 VectorCopy (pos, dl->origin);
339 dl->die = cl.time + 0.2;
341 dl->color[0] = 0.05;dl->color[1] = 0.05;dl->color[2] = 0.8;
344 case TE_EXPLOSION: // rocket explosion
345 pos[0] = MSG_ReadCoord ();
346 pos[1] = MSG_ReadCoord ();
347 pos[2] = MSG_ReadCoord ();
348 R_ParticleExplosion (pos, false);
349 // R_BlastParticles (pos, 120, 120);
350 dl = CL_AllocDlight (0);
351 VectorCopy (pos, dl->origin);
353 dl->die = cl.time + 0.5;
355 dl->color[0] = 1.0;dl->color[1] = 0.8;dl->color[2] = 0.4;
356 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
359 case TE_EXPLOSIONQUAD: // quad rocket explosion
360 pos[0] = MSG_ReadCoord ();
361 pos[1] = MSG_ReadCoord ();
362 pos[2] = MSG_ReadCoord ();
363 R_ParticleExplosion (pos, false);
364 // R_BlastParticles (pos, 120, 480);
365 dl = CL_AllocDlight (0);
366 VectorCopy (pos, dl->origin);
368 dl->die = cl.time + 0.5;
370 dl->color[0] = 0.5;dl->color[1] = 0.4;dl->color[2] = 1.0;
371 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
375 case TE_SMOKEEXPLOSION: // rocket explosion with a cloud of smoke
376 pos[0] = MSG_ReadCoord ();
377 pos[1] = MSG_ReadCoord ();
378 pos[2] = MSG_ReadCoord ();
379 R_ParticleExplosion (pos, true);
380 dl = CL_AllocDlight (0);
381 VectorCopy (pos, dl->origin);
383 dl->die = cl.time + 0.5;
385 dl->color[0] = 1.0;dl->color[1] = 0.8;dl->color[2] = 0.4;
386 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
390 case TE_EXPLOSION3: // Nehahra movie colored lighting explosion
391 pos[0] = MSG_ReadCoord ();
392 pos[1] = MSG_ReadCoord ();
393 pos[2] = MSG_ReadCoord ();
394 R_ParticleExplosion (pos, false);
395 // R_BlastParticles (pos, 120, 120);
396 dl = CL_AllocDlight (0);
397 VectorCopy (pos, dl->origin);
399 dl->die = cl.time + 0.5;
401 dl->color[0] = MSG_ReadCoord();dl->color[1] = MSG_ReadCoord();dl->color[2] = MSG_ReadCoord();
402 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
405 case TE_EXPLOSIONRGB: // colored lighting explosion
406 pos[0] = MSG_ReadCoord ();
407 pos[1] = MSG_ReadCoord ();
408 pos[2] = MSG_ReadCoord ();
409 R_ParticleExplosion (pos, false);
410 // R_BlastParticles (pos, 120, 120);
411 dl = CL_AllocDlight (0);
412 VectorCopy (pos, dl->origin);
414 dl->die = cl.time + 0.5;
416 dl->color[0] = MSG_ReadByte() * (1.0 / 255.0);dl->color[1] = MSG_ReadByte() * (1.0 / 255.0);dl->color[2] = MSG_ReadByte() * (1.0 / 255.0);
417 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
420 case TE_TAREXPLOSION: // tarbaby explosion
421 pos[0] = MSG_ReadCoord ();
422 pos[1] = MSG_ReadCoord ();
423 pos[2] = MSG_ReadCoord ();
424 R_BlobExplosion (pos);
425 // R_BlastParticles (pos, 120, 120);
427 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
428 dl = CL_AllocDlight (0);
429 VectorCopy (pos, dl->origin);
431 dl->die = cl.time + 0.5;
433 dl->color[0] = 0.8;dl->color[1] = 0.4;dl->color[2] = 1.0;
434 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
437 case TE_LIGHTNING1: // lightning bolts
438 CL_ParseBeam (Mod_ForName("progs/bolt.mdl", true));
441 case TE_LIGHTNING2: // lightning bolts
442 CL_ParseBeam (Mod_ForName("progs/bolt2.mdl", true));
445 case TE_LIGHTNING3: // lightning bolts
446 CL_ParseBeam (Mod_ForName("progs/bolt3.mdl", true));
450 case TE_BEAM: // grappling hook beam
451 CL_ParseBeam (Mod_ForName("progs/beam.mdl", true));
455 // LordHavoc: for compatibility with the Nehahra movie...
456 case TE_LIGHTNING4NEH:
457 CL_ParseBeam (Mod_ForName(MSG_ReadString(), true));
461 pos[0] = MSG_ReadCoord ();
462 pos[1] = MSG_ReadCoord ();
463 pos[2] = MSG_ReadCoord ();
468 pos[0] = MSG_ReadCoord ();
469 pos[1] = MSG_ReadCoord ();
470 pos[2] = MSG_ReadCoord ();
471 R_TeleportSplash (pos);
474 case TE_EXPLOSION2: // color mapped explosion
475 pos[0] = MSG_ReadCoord ();
476 pos[1] = MSG_ReadCoord ();
477 pos[2] = MSG_ReadCoord ();
478 colorStart = MSG_ReadByte ();
479 colorLength = MSG_ReadByte ();
480 R_ParticleExplosion2 (pos, colorStart, colorLength);
481 // R_BlastParticles (pos, 80, 80);
482 dl = CL_AllocDlight (0);
483 VectorCopy (pos, dl->origin);
485 dl->die = cl.time + 0.5;
487 tempcolor = (byte *)&d_8to24table[(rand()%colorLength) + colorStart];
488 dl->color[0] = tempcolor[0] * (1.0f / 255.0f);dl->color[1] = tempcolor[1] * (1.0f / 255.0f);dl->color[2] = tempcolor[2] * (1.0f / 255.0f);
489 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
493 Host_Error ("CL_ParseTEnt: bad type %d", type);
503 entity_t *CL_NewTempEntity (void)
507 if (cl_numvisedicts == MAX_VISEDICTS)
509 if (num_temp_entities == MAX_TEMP_ENTITIES)
511 ent = &cl_temp_entities[num_temp_entities];
512 memset (ent, 0, sizeof(*ent));
514 cl_visedicts[cl_numvisedicts] = ent;
517 // ent->colormap = vid.colormap;
521 ent->colormod[0] = ent->colormod[1] = ent->colormod[2] = 1;
531 void CL_UpdateTEnts (void)
542 num_temp_entities = 0;
545 for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
547 if (!b->model || b->endtime < cl.time)
550 // if coming from the player, update the start position
551 if (b->entity == cl.viewentity)
553 VectorCopy (cl_entities[cl.viewentity].origin, b->start);
556 // calculate pitch and yaw
557 VectorSubtract (b->end, b->start, dist);
559 if (dist[1] == 0 && dist[0] == 0)
569 yaw = (int) (atan2(dist[1], dist[0]) * 180 / M_PI);
573 forward = sqrt (dist[0]*dist[0] + dist[1]*dist[1]);
574 pitch = (int) (atan2(dist[2], forward) * 180 / M_PI);
579 // add new entities for the lightning
580 VectorCopy (b->start, org);
581 d = VectorNormalizeLength(dist);
584 ent = CL_NewTempEntity ();
587 VectorCopy (org, ent->origin);
588 ent->model = b->model;
589 ent->effects = EF_FULLBRIGHT;
590 ent->angles[0] = pitch;
591 ent->angles[1] = yaw;
592 ent->angles[2] = rand()%360;
594 dl = CL_AllocDlight (0);
595 VectorCopy (ent->origin, dl->origin);
596 dl->radius = 100 + (rand()&31);
597 dl->die = cl.time + 0.001;
598 dl->color[0] = 1;dl->color[1] = 1;dl->color[2] = 1;
600 VectorMA(org, 30, dist, org);