1 /*
2 Copyright (C) 1997-2001 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 "client.h"
23
24 typedef enum
25 {
26 ex_free, ex_explosion, ex_misc, ex_flash, ex_mflash, ex_poly, ex_poly2
27 } exptype_t;
28
29 typedef struct
30 {
31 exptype_t type;
32 entity_t ent;
33
34 int frames;
35 float light;
36 vec3_t lightcolor;
37 float start;
38 int baseframe;
39 } explosion_t;
40
41
42
43 #define MAX_EXPLOSIONS 32
44 explosion_t cl_explosions[MAX_EXPLOSIONS];
45
46
47 #define MAX_BEAMS 32
48 typedef struct
49 {
50 int entity;
51 int dest_entity;
52 struct model_s *model;
53 int endtime;
54 vec3_t offset;
55 vec3_t start, end;
56 } beam_t;
57 beam_t cl_beams[MAX_BEAMS];
58 //PMM - added this for player-linked beams. Currently only used by the plasma beam
59 beam_t cl_playerbeams[MAX_BEAMS];
60
61
62 #define MAX_LASERS 32
63 typedef struct
64 {
65 entity_t ent;
66 int endtime;
67 } laser_t;
68 laser_t cl_lasers[MAX_LASERS];
69
70 //ROGUE
71 cl_sustain_t cl_sustains[MAX_SUSTAINS];
72 //ROGUE
73
74 //PGM
75 extern void CL_TeleportParticles (vec3_t org);
76 //PGM
77
78 #ifdef QMAX
79 void CL_BloodHit (vec3_t org, vec3_t dir);
80 void CL_BlasterParticles (vec3_t org, vec3_t dir, int count);
81 void CL_ParticleEffectSparks (vec3_t org, vec3_t dir, vec3_t color, int count);
82 #else
83 void CL_BlasterParticles (vec3_t org, vec3_t dir);
84 #endif
85 void CL_BFGExplosionParticles (vec3_t org);
86 // RAFAEL
87 void CL_BlueBlasterParticles (vec3_t org, vec3_t dir);
88
89 #ifdef QMAX
90 void CL_Explosion_Particle (vec3_t org, float scale, qboolean large, qboolean rocket);
91 //void CL_ExplosionParticles (vec3_t org, float alpha);
92 void CL_ExplosionParticles (vec3_t org);
93 #define EXPLOSION_PARTICLES(x) CL_ExplosionParticles((x));
94 #else
95 void CL_ExplosionParticles (vec3_t org);
96 void CL_Explosion_Particle (vec3_t org, float size, qboolean large, qboolean rocket);
97 #define EXPLOSION_PARTICLES(x) CL_ExplosionParticles((x));
98 #endif
99
100 struct sfx_s *cl_sfx_ric1;
101 struct sfx_s *cl_sfx_ric2;
102 struct sfx_s *cl_sfx_ric3;
103 struct sfx_s *cl_sfx_lashit;
104 struct sfx_s *cl_sfx_spark5;
105 struct sfx_s *cl_sfx_spark6;
106 struct sfx_s *cl_sfx_spark7;
107 struct sfx_s *cl_sfx_railg;
108 struct sfx_s *cl_sfx_rockexp;
109 struct sfx_s *cl_sfx_grenexp;
110 struct sfx_s *cl_sfx_watrexp;
111 // RAFAEL
112 struct sfx_s *cl_sfx_plasexp;
113 struct sfx_s *cl_sfx_footsteps[4];
114
115 struct model_s *cl_mod_explode;
116 struct model_s *cl_mod_smoke;
117 struct model_s *cl_mod_flash;
118 struct model_s *cl_mod_parasite_segment;
119 struct model_s *cl_mod_grapple_cable;
120 struct model_s *cl_mod_parasite_tip;
121 struct model_s *cl_mod_explo4;
122 struct model_s *cl_mod_bfg_explo;
123 struct model_s *cl_mod_powerscreen;
124 // RAFAEL
125 struct model_s *cl_mod_plasmaexplo;
126
127 //ROGUE
128 struct sfx_s *cl_sfx_lightning;
129 struct sfx_s *cl_sfx_disrexp;
130 struct model_s *cl_mod_lightning;
131 struct model_s *cl_mod_heatbeam;
132 struct model_s *cl_mod_monster_heatbeam;
133 struct model_s *cl_mod_explo4_big;
134
135 //ROGUE
136 /*
137 =================
138 CL_RegisterTEntSounds
139 =================
140 */
CL_RegisterTEntSounds(void)141 void CL_RegisterTEntSounds (void)
142 {
143 int i;
144 char name[MAX_QPATH];
145
146 // PMM - version stuff
147 // Com_Printf ("%s\n", ROGUE_VERSION_STRING);
148 // PMM
149 cl_sfx_ric1 = S_RegisterSound ("world/ric1.wav");
150 cl_sfx_ric2 = S_RegisterSound ("world/ric2.wav");
151 cl_sfx_ric3 = S_RegisterSound ("world/ric3.wav");
152 cl_sfx_lashit = S_RegisterSound("weapons/lashit.wav");
153 cl_sfx_spark5 = S_RegisterSound ("world/spark5.wav");
154 cl_sfx_spark6 = S_RegisterSound ("world/spark6.wav");
155 cl_sfx_spark7 = S_RegisterSound ("world/spark7.wav");
156 cl_sfx_railg = S_RegisterSound ("weapons/railgf1a.wav");
157 cl_sfx_rockexp = S_RegisterSound ("weapons/rocklx1a.wav");
158 cl_sfx_grenexp = S_RegisterSound ("weapons/grenlx1a.wav");
159 cl_sfx_watrexp = S_RegisterSound ("weapons/xpld_wat.wav");
160 // RAFAEL
161 // cl_sfx_plasexp = S_RegisterSound ("weapons/plasexpl.wav");
162 S_RegisterSound ("player/land1.wav");
163
164 S_RegisterSound ("player/fall2.wav");
165 S_RegisterSound ("player/fall1.wav");
166
167 for (i=0 ; i<4 ; i++)
168 {
169 Com_sprintf (name, sizeof(name), "player/step%i.wav", i+1);
170 cl_sfx_footsteps[i] = S_RegisterSound (name);
171 }
172
173 //PGM
174 cl_sfx_lightning = S_RegisterSound ("weapons/tesla.wav");
175 cl_sfx_disrexp = S_RegisterSound ("weapons/disrupthit.wav");
176 // version stuff
177 // sprintf (name, "weapons/sound%d.wav", ROGUE_VERSION_ID);
178 // if (name[0] == 'w')
179 // name[0] = 'W';
180 //PGM
181 }
182
183 /*
184 =================
185 CL_RegisterTEntModels
186 =================
187 */
CL_RegisterTEntModels(void)188 void CL_RegisterTEntModels (void)
189 {
190 cl_mod_explode = re.RegisterModel ("models/objects/explode/tris.md2");
191 cl_mod_smoke = re.RegisterModel ("models/objects/smoke/tris.md2");
192 cl_mod_flash = re.RegisterModel ("models/objects/flash/tris.md2");
193 cl_mod_parasite_segment = re.RegisterModel ("models/monsters/parasite/segment/tris.md2");
194 cl_mod_grapple_cable = re.RegisterModel ("models/ctf/segment/tris.md2");
195 cl_mod_parasite_tip = re.RegisterModel ("models/monsters/parasite/tip/tris.md2");
196 cl_mod_explo4 = re.RegisterModel ("models/objects/r_explode/tris.md2");
197 cl_mod_bfg_explo = re.RegisterModel ("sprites/s_bfg2.sp2");
198 cl_mod_powerscreen = re.RegisterModel ("models/items/armor/effect/tris.md2");
199
200 re.RegisterModel ("models/objects/laser/tris.md2");
201 re.RegisterModel ("models/objects/grenade2/tris.md2");
202 re.RegisterModel ("models/weapons/v_machn/tris.md2");
203 re.RegisterModel ("models/weapons/v_handgr/tris.md2");
204 re.RegisterModel ("models/weapons/v_shotg2/tris.md2");
205 re.RegisterModel ("models/objects/gibs/bone/tris.md2");
206 re.RegisterModel ("models/objects/gibs/sm_meat/tris.md2");
207 re.RegisterModel ("models/objects/gibs/bone2/tris.md2");
208 // RAFAEL
209 // re.RegisterModel ("models/objects/blaser/tris.md2");
210
211 re.RegisterPic ("w_machinegun");
212 re.RegisterPic ("a_bullets");
213 re.RegisterPic ("i_health");
214 re.RegisterPic ("a_grenades");
215
216 //ROGUE
217 cl_mod_explo4_big = re.RegisterModel ("models/objects/r_explode2/tris.md2");
218 cl_mod_lightning = re.RegisterModel ("models/proj/lightning/tris.md2");
219 cl_mod_heatbeam = re.RegisterModel ("models/proj/beam/tris.md2");
220 cl_mod_monster_heatbeam = re.RegisterModel ("models/proj/widowbeam/tris.md2");
221 //ROGUE
222 }
223
224 /*
225 =================
226 CL_ClearTEnts
227 =================
228 */
CL_ClearTEnts(void)229 void CL_ClearTEnts (void)
230 {
231 memset (cl_beams, 0, sizeof(cl_beams));
232 memset (cl_explosions, 0, sizeof(cl_explosions));
233 memset (cl_lasers, 0, sizeof(cl_lasers));
234
235 //ROGUE
236 memset (cl_playerbeams, 0, sizeof(cl_playerbeams));
237 memset (cl_sustains, 0, sizeof(cl_sustains));
238 //ROGUE
239 }
240
241 #ifdef QMAX
242 #define EXP_DIST 10
CL_R_Explode_SP(vec3_t origin)243 void CL_R_Explode_SP (vec3_t origin)
244 {
245 CL_Explosion_Particle (origin, 0, true, true);
246 }
247
CL_G_Explode_SP(vec3_t origin)248 void CL_G_Explode_SP (vec3_t origin)
249 {
250 CL_Explosion_Particle (origin, 0, true, false);
251 }
252 #endif
253
254 /*
255 =================
256 CL_AllocExplosion
257 =================
258 */
CL_AllocExplosion(void)259 explosion_t *CL_AllocExplosion (void)
260 {
261 int i;
262 int time;
263 int index;
264
265 for (i=0 ; i<MAX_EXPLOSIONS ; i++)
266 {
267 if (cl_explosions[i].type == ex_free)
268 {
269 memset (&cl_explosions[i], 0, sizeof (cl_explosions[i]));
270 return &cl_explosions[i];
271 }
272 }
273 // find the oldest explosion
274 time = cl.time;
275 index = 0;
276
277 for (i=0 ; i<MAX_EXPLOSIONS ; i++)
278 if (cl_explosions[i].start < time)
279 {
280 time = cl_explosions[i].start;
281 index = i;
282 }
283 memset (&cl_explosions[index], 0, sizeof (cl_explosions[index]));
284 return &cl_explosions[index];
285 }
286
287 /*
288 =================
289 CL_SmokeAndFlash
290 =================
291 */
CL_SmokeAndFlash(vec3_t origin)292 void CL_SmokeAndFlash(vec3_t origin)
293 {
294 explosion_t *ex;
295
296 ex = CL_AllocExplosion ();
297 VectorCopy (origin, ex->ent.origin);
298 ex->type = ex_misc;
299 ex->frames = 4;
300 ex->ent.flags = RF_TRANSLUCENT;
301 ex->start = cl.frame.servertime - 100;
302 ex->ent.model = cl_mod_smoke;
303
304 ex = CL_AllocExplosion ();
305 VectorCopy (origin, ex->ent.origin);
306 ex->type = ex_flash;
307 ex->ent.flags = RF_FULLBRIGHT;
308 ex->frames = 2;
309 ex->start = cl.frame.servertime - 100;
310 ex->ent.model = cl_mod_flash;
311 }
312
313 /*
314 =================
315 CL_ParseParticles
316 =================
317 */
CL_ParseParticles(void)318 void CL_ParseParticles (void)
319 {
320 int color, count;
321 vec3_t pos, dir;
322
323 MSG_ReadPos (&net_message, pos);
324 MSG_ReadDir (&net_message, dir);
325
326 color = MSG_ReadByte (&net_message);
327
328 count = MSG_ReadByte (&net_message);
329
330 CL_ParticleEffect (pos, dir, color, count);
331 }
332
333 /*
334 =================
335 CL_ParseBeam
336 =================
337 */
CL_ParseBeam(struct model_s * model)338 int CL_ParseBeam (struct model_s *model)
339 {
340 int ent;
341 vec3_t start, end;
342 beam_t *b;
343 int i;
344
345 ent = MSG_ReadShort (&net_message);
346
347 MSG_ReadPos (&net_message, start);
348 MSG_ReadPos (&net_message, end);
349
350 // override any beam with the same entity
351 for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
352 if (b->entity == ent)
353 {
354 b->entity = ent;
355 b->model = model;
356 b->endtime = cl.time + 200;
357 VectorCopy (start, b->start);
358 VectorCopy (end, b->end);
359 VectorClear (b->offset);
360 return ent;
361 }
362
363 // find a free beam
364 for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
365 {
366 if (!b->model || b->endtime < cl.time)
367 {
368 b->entity = ent;
369 b->model = model;
370 b->endtime = cl.time + 200;
371 VectorCopy (start, b->start);
372 VectorCopy (end, b->end);
373 VectorClear (b->offset);
374 return ent;
375 }
376 }
377 Com_Printf ("beam list overflow!\n");
378 return ent;
379 }
380
381 /*
382 =================
383 CL_ParseBeam2
384 =================
385 */
CL_ParseBeam2(struct model_s * model)386 int CL_ParseBeam2 (struct model_s *model)
387 {
388 int ent;
389 vec3_t start, end, offset;
390 beam_t *b;
391 int i;
392
393 ent = MSG_ReadShort (&net_message);
394
395 MSG_ReadPos (&net_message, start);
396 MSG_ReadPos (&net_message, end);
397 MSG_ReadPos (&net_message, offset);
398
399 // Com_Printf ("end- %f %f %f\n", end[0], end[1], end[2]);
400
401 // override any beam with the same entity
402
403 for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
404 if (b->entity == ent)
405 {
406 b->entity = ent;
407 b->model = model;
408 b->endtime = cl.time + 200;
409 VectorCopy (start, b->start);
410 VectorCopy (end, b->end);
411 VectorCopy (offset, b->offset);
412 return ent;
413 }
414
415 // find a free beam
416 for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
417 {
418 if (!b->model || b->endtime < cl.time)
419 {
420 b->entity = ent;
421 b->model = model;
422 b->endtime = cl.time + 200;
423 VectorCopy (start, b->start);
424 VectorCopy (end, b->end);
425 VectorCopy (offset, b->offset);
426 return ent;
427 }
428 }
429 Com_Printf ("beam list overflow!\n");
430 return ent;
431 }
432
433 // ROGUE
434 /*
435 =================
436 CL_ParsePlayerBeam
437 - adds to the cl_playerbeam array instead of the cl_beams array
438 =================
439 */
CL_ParsePlayerBeam(struct model_s * model)440 int CL_ParsePlayerBeam (struct model_s *model)
441 {
442 int ent;
443 vec3_t start, end, offset;
444 beam_t *b;
445 int i;
446
447 ent = MSG_ReadShort (&net_message);
448
449 MSG_ReadPos (&net_message, start);
450 MSG_ReadPos (&net_message, end);
451 // PMM - network optimization
452 if (model == cl_mod_heatbeam)
453 VectorSet(offset, 2, 7, -3);
454 else if (model == cl_mod_monster_heatbeam)
455 {
456 model = cl_mod_heatbeam;
457 VectorSet(offset, 0, 0, 0);
458 }
459 else
460 MSG_ReadPos (&net_message, offset);
461
462 // Com_Printf ("end- %f %f %f\n", end[0], end[1], end[2]);
463
464 // override any beam with the same entity
465 // PMM - For player beams, we only want one per player (entity) so..
466 for (i=0, b=cl_playerbeams ; i< MAX_BEAMS ; i++, b++)
467 {
468 if (b->entity == ent)
469 {
470 b->entity = ent;
471 b->model = model;
472 b->endtime = cl.time + 200;
473 VectorCopy (start, b->start);
474 VectorCopy (end, b->end);
475 VectorCopy (offset, b->offset);
476 return ent;
477 }
478 }
479
480 // find a free beam
481 for (i=0, b=cl_playerbeams ; i< MAX_BEAMS ; i++, b++)
482 {
483 if (!b->model || b->endtime < cl.time)
484 {
485 b->entity = ent;
486 b->model = model;
487 b->endtime = cl.time + 100; // PMM - this needs to be 100 to prevent multiple heatbeams
488 VectorCopy (start, b->start);
489 VectorCopy (end, b->end);
490 VectorCopy (offset, b->offset);
491 return ent;
492 }
493 }
494 Com_Printf ("beam list overflow!\n");
495 return ent;
496 }
497 //rogue
498
499 /*
500 =================
501 CL_ParseLightning
502 =================
503 */
CL_ParseLightning(struct model_s * model)504 int CL_ParseLightning (struct model_s *model)
505 {
506 int srcEnt, destEnt;
507 vec3_t start, end;
508 beam_t *b;
509 int i;
510
511 srcEnt = MSG_ReadShort (&net_message);
512 destEnt = MSG_ReadShort (&net_message);
513
514 MSG_ReadPos (&net_message, start);
515 MSG_ReadPos (&net_message, end);
516
517 // override any beam with the same source AND destination entities
518 for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
519 if (b->entity == srcEnt && b->dest_entity == destEnt)
520 {
521 // Com_Printf("%d: OVERRIDE %d -> %d\n", cl.time, srcEnt, destEnt);
522 b->entity = srcEnt;
523 b->dest_entity = destEnt;
524 b->model = model;
525 b->endtime = cl.time + 200;
526 VectorCopy (start, b->start);
527 VectorCopy (end, b->end);
528 VectorClear (b->offset);
529 return srcEnt;
530 }
531
532 // find a free beam
533 for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
534 {
535 if (!b->model || b->endtime < cl.time)
536 {
537 // Com_Printf("%d: NORMAL %d -> %d\n", cl.time, srcEnt, destEnt);
538 b->entity = srcEnt;
539 b->dest_entity = destEnt;
540 b->model = model;
541 b->endtime = cl.time + 200;
542 VectorCopy (start, b->start);
543 VectorCopy (end, b->end);
544 VectorClear (b->offset);
545 return srcEnt;
546 }
547 }
548 Com_Printf ("beam list overflow!\n");
549 return srcEnt;
550 }
551
552 /*
553 =================
554 CL_ParseLaser
555 =================
556 */
CL_ParseLaser(int colors)557 void CL_ParseLaser (int colors)
558 {
559 vec3_t start;
560 vec3_t end;
561 laser_t *l;
562 int i;
563
564 MSG_ReadPos (&net_message, start);
565 MSG_ReadPos (&net_message, end);
566
567 for (i=0, l=cl_lasers ; i< MAX_LASERS ; i++, l++)
568 {
569 if (l->endtime < cl.time)
570 {
571 l->ent.flags = RF_TRANSLUCENT | RF_BEAM;
572 VectorCopy (start, l->ent.origin);
573 VectorCopy (end, l->ent.oldorigin);
574 l->ent.alpha = 0.30;
575 l->ent.skinnum = (colors >> ((rand() % 4)*8)) & 0xff;
576 l->ent.model = NULL;
577 l->ent.frame = 4;
578 l->endtime = cl.time + 100;
579 return;
580 }
581 }
582 }
583
584 #ifdef QMAX
CL_GunSmokeEffect(vec3_t org,vec3_t dir)585 void CL_GunSmokeEffect (vec3_t org, vec3_t dir)
586 {
587 vec3_t velocity, origin;
588 int j;
589
590 for (j=0 ; j<3 ; j++)
591 {
592 origin[j] = org[j] + dir[j]*10;
593 velocity[j] = 10*dir[j];
594 }
595 velocity[2] = 10;
596
597 CL_ParticleSmokeEffect (origin, velocity, 0, 10, 10);
598
599 }
600 #endif
601 //=============
602 //ROGUE
CL_ParseSteam(void)603 void CL_ParseSteam (void)
604 {
605 vec3_t pos, dir;
606 int id, i;
607 int r;
608 int cnt;
609 int color;
610 int magnitude;
611 cl_sustain_t *s, *free_sustain;
612
613 id = MSG_ReadShort (&net_message); // an id of -1 is an instant effect
614 if (id != -1) // sustains
615 {
616 // Com_Printf ("Sustain effect id %d\n", id);
617 free_sustain = NULL;
618 for (i=0, s=cl_sustains; i<MAX_SUSTAINS; i++, s++)
619 {
620 if (s->id == 0)
621 {
622 free_sustain = s;
623 break;
624 }
625 }
626 if (free_sustain)
627 {
628 s->id = id;
629 s->count = MSG_ReadByte (&net_message);
630 MSG_ReadPos (&net_message, s->org);
631 MSG_ReadDir (&net_message, s->dir);
632 r = MSG_ReadByte (&net_message);
633 s->color = r & 0xff;
634 s->magnitude = MSG_ReadShort (&net_message);
635 s->endtime = cl.time + MSG_ReadLong (&net_message);
636 s->think = CL_ParticleSteamEffect2;
637 s->thinkinterval = 100;
638 s->nextthink = cl.time;
639 }
640 else
641 {
642 // Com_Printf ("No free sustains!\n");
643 // FIXME - read the stuff anyway
644 cnt = MSG_ReadByte (&net_message);
645 MSG_ReadPos (&net_message, pos);
646 MSG_ReadDir (&net_message, dir);
647 r = MSG_ReadByte (&net_message);
648 magnitude = MSG_ReadShort (&net_message);
649 magnitude = MSG_ReadLong (&net_message); // really interval
650 }
651 }
652 else // instant
653 {
654 cnt = MSG_ReadByte (&net_message);
655 MSG_ReadPos (&net_message, pos);
656 MSG_ReadDir (&net_message, dir);
657 r = MSG_ReadByte (&net_message);
658 magnitude = MSG_ReadShort (&net_message);
659 color = r & 0xff;
660 CL_ParticleSteamEffect (pos, dir, color, cnt, magnitude);
661 // S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
662 }
663 }
664
CL_ParseWidow(void)665 void CL_ParseWidow (void)
666 {
667 vec3_t pos;
668 int id, i;
669 cl_sustain_t *s, *free_sustain;
670
671 id = MSG_ReadShort (&net_message);
672
673 free_sustain = NULL;
674 for (i=0, s=cl_sustains; i<MAX_SUSTAINS; i++, s++)
675 {
676 if (s->id == 0)
677 {
678 free_sustain = s;
679 break;
680 }
681 }
682 if (free_sustain)
683 {
684 s->id = id;
685 MSG_ReadPos (&net_message, s->org);
686 s->endtime = cl.time + 2100;
687 s->think = CL_Widowbeamout;
688 s->thinkinterval = 1;
689 s->nextthink = cl.time;
690 }
691 else // no free sustains
692 {
693 // FIXME - read the stuff anyway
694 MSG_ReadPos (&net_message, pos);
695 }
696 }
697
CL_ParseNuke(void)698 void CL_ParseNuke (void)
699 {
700 vec3_t pos;
701 int i;
702 cl_sustain_t *s, *free_sustain;
703
704 free_sustain = NULL;
705 for (i=0, s=cl_sustains; i<MAX_SUSTAINS; i++, s++)
706 {
707 if (s->id == 0)
708 {
709 free_sustain = s;
710 break;
711 }
712 }
713 if (free_sustain)
714 {
715 s->id = 21000;
716 MSG_ReadPos (&net_message, s->org);
717 s->endtime = cl.time + 1000;
718 s->think = CL_Nukeblast;
719 s->thinkinterval = 1;
720 s->nextthink = cl.time;
721 }
722 else // no free sustains
723 {
724 // FIXME - read the stuff anyway
725 MSG_ReadPos (&net_message, pos);
726 }
727 }
728
729 //ROGUE
730 //=============
731
732
733 /*
734 =================
735 CL_ParseTEnt
736 =================
737 */
738 static byte splash_color[] = {0x00, 0xe0, 0xb0, 0x50, 0xd0, 0xe0, 0xe8};
739
CL_ParseTEnt(void)740 void CL_ParseTEnt (void)
741 {
742 int type;
743 vec3_t pos, pos2, dir;
744 explosion_t *ex;
745 int cnt;
746 int color;
747 int r;
748 int ent;
749 int magnitude;
750
751 type = MSG_ReadByte (&net_message);
752
753 switch (type)
754 {
755 case TE_BLOOD: // bullet hitting flesh
756 MSG_ReadPos (&net_message, pos);
757 MSG_ReadDir (&net_message, dir);
758 #ifdef QMAX
759 CL_BloodHit (pos, dir);
760 #else
761 CL_ParticleEffect (pos, dir, 0xe8, 60);
762 #endif
763 break;
764
765 case TE_GUNSHOT: // bullet hitting wall
766 case TE_SPARKS:
767 case TE_BULLET_SPARKS:
768 MSG_ReadPos (&net_message, pos);
769 MSG_ReadDir (&net_message, dir);
770 #ifdef QMAX
771 if (type != TE_SPARKS)
772 {
773 CL_GunSmokeEffect (pos, dir);
774 re.AddStain(pos, 5, -175, -175, -175);
775 }
776
777 if (type == TE_BULLET_SPARKS)
778 {
779 VectorScale(dir, 1.1, dir);
780 }
781 #else
782 if (type == TE_GUNSHOT)
783 CL_ParticleEffect (pos, dir, 0, 40);
784 else
785 CL_ParticleEffect (pos, dir, 0xe0, 6);
786 #endif
787 if (type != TE_SPARKS)
788 {
789 #ifndef QMAX
790 CL_SmokeAndFlash(pos);
791 #endif
792 // impact sound
793 cnt = rand()&15;
794 if (cnt == 1)
795 S_StartSound (pos, 0, 0, cl_sfx_ric1, 1, ATTN_NORM, 0);
796 else if (cnt == 2)
797 S_StartSound (pos, 0, 0, cl_sfx_ric2, 1, ATTN_NORM, 0);
798 else if (cnt == 3)
799 S_StartSound (pos, 0, 0, cl_sfx_ric3, 1, ATTN_NORM, 0);
800 }
801 #ifdef QMAX
802 //adding sparks
803 {
804 vec3_t color = { 255, 125, 10 };
805 CL_ParticleEffectSparks (pos, dir, color, (type == TE_GUNSHOT)? 5 : 10);
806 }
807 #endif
808 break;
809
810 case TE_SCREEN_SPARKS:
811 case TE_SHIELD_SPARKS:
812 MSG_ReadPos (&net_message, pos);
813 MSG_ReadDir (&net_message, dir);
814 if (type == TE_SCREEN_SPARKS)
815 CL_ParticleEffect (pos, dir, 0xd0, 40);
816 else
817 CL_ParticleEffect (pos, dir, 0xb0, 40);
818 //FIXME : replace or remove this sound
819 S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
820 break;
821
822 case TE_SHOTGUN: // bullet hitting wall
823 MSG_ReadPos (&net_message, pos);
824 MSG_ReadDir (&net_message, dir);
825 #ifdef QMAX
826 CL_GunSmokeEffect (pos, dir);
827 {
828 vec3_t color = { 200, 100, 10 };
829 CL_ParticleEffectSparks (pos, dir, color, 8);
830 }
831 re.AddStain(pos, 7, -175, -175, -175);
832 #else
833 CL_ParticleEffect (pos, dir, 0, 20);
834 CL_SmokeAndFlash(pos);
835 #endif
836 break;
837
838 case TE_SPLASH: // bullet hitting water
839 cnt = MSG_ReadByte (&net_message);
840 MSG_ReadPos (&net_message, pos);
841 MSG_ReadDir (&net_message, dir);
842 r = MSG_ReadByte (&net_message);
843 if (r > 6)
844 color = 0x00;
845 else
846 color = splash_color[r];
847 CL_ParticleEffect (pos, dir, color, cnt);
848
849 if (r == SPLASH_SPARKS)
850 {
851 r = rand() & 3;
852 if (r == 0)
853 S_StartSound (pos, 0, 0, cl_sfx_spark5, 1, ATTN_STATIC, 0);
854 else if (r == 1)
855 S_StartSound (pos, 0, 0, cl_sfx_spark6, 1, ATTN_STATIC, 0);
856 else
857 S_StartSound (pos, 0, 0, cl_sfx_spark7, 1, ATTN_STATIC, 0);
858 }
859 break;
860
861 case TE_LASER_SPARKS:
862 cnt = MSG_ReadByte (&net_message);
863 MSG_ReadPos (&net_message, pos);
864 MSG_ReadDir (&net_message, dir);
865 color = MSG_ReadByte (&net_message);
866 CL_ParticleEffect2 (pos, dir, color, cnt);
867 break;
868
869 // RAFAEL
870 case TE_BLUEHYPERBLASTER:
871 MSG_ReadPos (&net_message, pos);
872 MSG_ReadPos (&net_message, dir);
873 #ifdef QMAX
874 CL_BlasterParticles (pos, dir, 40);
875 #else
876 CL_BlasterParticles (pos, dir);
877 #endif
878 break;
879
880 case TE_BLASTER: // blaster hitting wall
881 MSG_ReadPos (&net_message, pos);
882 MSG_ReadDir (&net_message, dir);
883 #ifdef QMAX
884 CL_BlasterParticles (pos, dir, 40);
885 #else
886 CL_BlasterParticles (pos, dir);
887
888 ex = CL_AllocExplosion ();
889 VectorCopy (pos, ex->ent.origin);
890 ex->ent.angles[0] = acos(dir[2])/M_PI*180;
891 // PMM - fixed to correct for pitch of 0
892 if (dir[0])
893 ex->ent.angles[1] = atan2(dir[1], dir[0])/M_PI*180;
894 else if (dir[1] > 0)
895 ex->ent.angles[1] = 90;
896 else if (dir[1] < 0)
897 ex->ent.angles[1] = 270;
898 else
899 ex->ent.angles[1] = 0;
900
901 ex->type = ex_misc;
902 ex->ent.flags = RF_FULLBRIGHT|RF_TRANSLUCENT;
903 ex->start = cl.frame.servertime - 100;
904 ex->light = 150;
905 ex->lightcolor[0] = 1;
906 ex->lightcolor[1] = 1;
907 ex->ent.model = cl_mod_explode;
908 ex->frames = 4;
909 #endif
910 S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
911 break;
912
913 case TE_RAILTRAIL: // railgun effect
914 MSG_ReadPos (&net_message, pos);
915 MSG_ReadPos (&net_message, pos2);
916 CL_RailTrail (pos, pos2);
917 S_StartSound (pos2, 0, 0, cl_sfx_railg, 1, ATTN_NORM, 0);
918 break;
919
920 case TE_EXPLOSION2:
921 case TE_GRENADE_EXPLOSION:
922 case TE_GRENADE_EXPLOSION_WATER:
923 MSG_ReadPos (&net_message, pos);
924 #ifdef QMAX
925 CL_G_Explode_SP(pos);
926
927 // if (type!=TE_GRENADE_EXPLOSION_WATER)
928 // CL_Radius_Explode_SP(pos, 1.25);
929 // CL_ExplosionParticles (pos,1.25);
930 CL_ExplosionParticles (pos);
931 #else
932 ex = CL_AllocExplosion ();
933 VectorCopy (pos, ex->ent.origin);
934 ex->type = ex_poly;
935 ex->ent.flags = RF_FULLBRIGHT|RF_NOSHADOW;
936 ex->start = cl.frame.servertime - 100;
937 ex->light = 350;
938 ex->lightcolor[0] = 1.0;
939 ex->lightcolor[1] = 0.5;
940 ex->lightcolor[2] = 0.5;
941 ex->ent.model = cl_mod_explo4;
942 ex->frames = 19;
943 ex->baseframe = 30;
944 ex->ent.angles[1] = rand() % 360;
945 EXPLOSION_PARTICLES (pos);
946 #endif
947 if (type == TE_GRENADE_EXPLOSION_WATER)
948 S_StartSound (pos, 0, 0, cl_sfx_watrexp, 1, ATTN_NORM, 0);
949 else
950 S_StartSound (pos, 0, 0, cl_sfx_grenexp, 1, ATTN_NORM, 0);
951 break;
952
953 // RAFAEL
954 case TE_PLASMA_EXPLOSION:
955 MSG_ReadPos (&net_message, pos);
956 #ifdef QMAX
957 CL_R_Explode_SP(pos);
958 // CL_ExplosionParticles (pos, 1);
959 // CL_ExplosionParticles (pos);
960
961 #else
962 ex = CL_AllocExplosion ();
963 VectorCopy (pos, ex->ent.origin);
964 ex->type = ex_poly;
965 ex->ent.flags = RF_FULLBRIGHT|RF_NOSHADOW;
966 ex->start = cl.frame.servertime - 100;
967 ex->light = 350;
968 ex->lightcolor[0] = 1.0;
969 ex->lightcolor[1] = 0.5;
970 ex->lightcolor[2] = 0.5;
971 ex->ent.angles[1] = rand() % 360;
972 ex->ent.model = cl_mod_explo4;
973 if (frand() < 0.5)
974 ex->baseframe = 15;
975 ex->frames = 15;
976 EXPLOSION_PARTICLES (pos);
977 #endif
978 S_StartSound (pos, 0, 0, cl_sfx_rockexp, 1, ATTN_NORM, 0);
979 break;
980
981 case TE_EXPLOSION1_BIG:
982 #ifdef QMAX
983 // PMM
984 MSG_ReadPos (&net_message, pos);
985 // /*
986 // if (modType("dday"))
987 // {
988 // CL_Explosion_Particle (pos, 250, true, true);
989 // CL_ExplosionParticles (pos, 5);
990 // CL_Radius_Explode_SP(pos, 5);
991 // }
992 // else
993 // {
994 CL_Explosion_Particle (pos, 100, true, true);
995 //CL_ExplosionParticles (pos, 2);
996 CL_ExplosionParticles (pos);
997 // CL_Radius_Explode_SP(pos, 2);
998 // }
999 S_StartSound (pos, 0, 0, cl_sfx_rockexp, 1, ATTN_NORM, 0);
1000 break;
1001 #endif
1002 case TE_EXPLOSION1_NP: // PMM
1003 #ifdef QMAX
1004 MSG_ReadPos (&net_message, pos);
1005 CL_Explosion_Particle (pos, 50, true, true);
1006 CL_ExplosionParticles (pos);
1007 // CL_ExplosionParticles (pos, 0.6666666);
1008 // CL_Radius_Explode_SP(pos, 0.6666666);
1009
1010 S_StartSound (pos, 0, 0, cl_sfx_grenexp, 1, ATTN_NORM, 0);
1011 break;
1012 #endif
1013 case TE_EXPLOSION1:
1014 case TE_ROCKET_EXPLOSION:
1015 case TE_ROCKET_EXPLOSION_WATER:
1016 MSG_ReadPos (&net_message, pos);
1017 #ifdef QMAX
1018 CL_R_Explode_SP(pos);
1019 // CL_ExplosionParticles (pos, 1);
1020 CL_ExplosionParticles (pos);
1021 #else
1022 ex = CL_AllocExplosion ();
1023 VectorCopy (pos, ex->ent.origin);
1024 ex->type = ex_poly;
1025 ex->ent.flags = RF_FULLBRIGHT|RF_NOSHADOW;
1026 ex->start = cl.frame.servertime - 100;
1027 ex->light = 350;
1028 ex->lightcolor[0] = 1.0;
1029 ex->lightcolor[1] = 0.5;
1030 ex->lightcolor[2] = 0.5;
1031 ex->ent.angles[1] = rand() % 360;
1032 if (type != TE_EXPLOSION1_BIG) // PMM
1033 ex->ent.model = cl_mod_explo4; // PMM
1034 else
1035 ex->ent.model = cl_mod_explo4_big;
1036 if (frand() < 0.5)
1037 ex->baseframe = 15;
1038 ex->frames = 15;
1039 if ((type != TE_EXPLOSION1_BIG) && (type != TE_EXPLOSION1_NP)) // PMM
1040 EXPLOSION_PARTICLES (pos); // PMM
1041 #endif
1042 if (type == TE_ROCKET_EXPLOSION_WATER)
1043 S_StartSound (pos, 0, 0, cl_sfx_watrexp, 1, ATTN_NORM, 0);
1044 else
1045 S_StartSound (pos, 0, 0, cl_sfx_rockexp, 1, ATTN_NORM, 0);
1046 break;
1047
1048 case TE_BFG_EXPLOSION:
1049 MSG_ReadPos (&net_message, pos);
1050 ex = CL_AllocExplosion ();
1051 VectorCopy (pos, ex->ent.origin);
1052 ex->type = ex_poly;
1053 ex->ent.flags = RF_FULLBRIGHT|RF_NOSHADOW;
1054 ex->start = cl.frame.servertime - 100;
1055 ex->light = 350;
1056 ex->lightcolor[0] = 0.0;
1057 ex->lightcolor[1] = 1.0;
1058 ex->lightcolor[2] = 0.0;
1059 ex->ent.model = cl_mod_bfg_explo;
1060 ex->ent.flags |= RF_TRANSLUCENT;
1061 ex->ent.alpha = 0.30;
1062 ex->frames = 4;
1063 break;
1064
1065 case TE_BFG_BIGEXPLOSION:
1066 MSG_ReadPos (&net_message, pos);
1067 CL_BFGExplosionParticles (pos);
1068 break;
1069
1070 case TE_BFG_LASER:
1071 CL_ParseLaser (0xd0d1d2d3);
1072 break;
1073
1074 case TE_BUBBLETRAIL:
1075 MSG_ReadPos (&net_message, pos);
1076 MSG_ReadPos (&net_message, pos2);
1077 CL_BubbleTrail (pos, pos2);
1078 break;
1079
1080 case TE_PARASITE_ATTACK:
1081 case TE_MEDIC_CABLE_ATTACK:
1082 ent = CL_ParseBeam (cl_mod_parasite_segment);
1083 break;
1084
1085 case TE_BOSSTPORT: // boss teleporting to station
1086 MSG_ReadPos (&net_message, pos);
1087 CL_BigTeleportParticles (pos);
1088 S_StartSound (pos, 0, 0, S_RegisterSound ("misc/bigtele.wav"), 1, ATTN_NONE, 0);
1089 break;
1090
1091 case TE_GRAPPLE_CABLE:
1092 ent = CL_ParseBeam2 (cl_mod_grapple_cable);
1093 break;
1094
1095 // RAFAEL
1096 case TE_WELDING_SPARKS:
1097 cnt = MSG_ReadByte (&net_message);
1098 MSG_ReadPos (&net_message, pos);
1099 MSG_ReadDir (&net_message, dir);
1100 color = MSG_ReadByte (&net_message);
1101 CL_ParticleEffect2 (pos, dir, color, cnt);
1102
1103 ex = CL_AllocExplosion ();
1104 VectorCopy (pos, ex->ent.origin);
1105 ex->type = ex_flash;
1106 // note to self
1107 // we need a better no draw flag
1108 ex->ent.flags = RF_BEAM;
1109 ex->start = cl.frame.servertime - 0.1;
1110 ex->light = 100 + (rand()%75);
1111 ex->lightcolor[0] = 1.0;
1112 ex->lightcolor[1] = 1.0;
1113 ex->lightcolor[2] = 0.3;
1114 ex->ent.model = cl_mod_flash;
1115 ex->frames = 2;
1116 break;
1117
1118 case TE_GREENBLOOD:
1119 MSG_ReadPos (&net_message, pos);
1120 MSG_ReadDir (&net_message, dir);
1121 CL_ParticleEffect2 (pos, dir, 0xdf, 30);
1122 break;
1123
1124 // RAFAEL
1125 case TE_TUNNEL_SPARKS:
1126 cnt = MSG_ReadByte (&net_message);
1127 MSG_ReadPos (&net_message, pos);
1128 MSG_ReadDir (&net_message, dir);
1129 color = MSG_ReadByte (&net_message);
1130 CL_ParticleEffect3 (pos, dir, color, cnt);
1131 break;
1132
1133 //=============
1134 //PGM
1135 // PMM -following code integrated for flechette (different color)
1136 case TE_BLASTER2: // green blaster hitting wall
1137 case TE_FLECHETTE: // flechette
1138 MSG_ReadPos (&net_message, pos);
1139 MSG_ReadDir (&net_message, dir);
1140
1141 // PMM
1142 if (type == TE_BLASTER2)
1143 CL_BlasterParticles2 (pos, dir, 0xd0);
1144 else
1145 CL_BlasterParticles2 (pos, dir, 0x6f); // 75
1146
1147 ex = CL_AllocExplosion ();
1148 VectorCopy (pos, ex->ent.origin);
1149 ex->ent.angles[0] = acos(dir[2])/M_PI*180;
1150 // PMM - fixed to correct for pitch of 0
1151 if (dir[0])
1152 ex->ent.angles[1] = atan2(dir[1], dir[0])/M_PI*180;
1153 else if (dir[1] > 0)
1154 ex->ent.angles[1] = 90;
1155 else if (dir[1] < 0)
1156 ex->ent.angles[1] = 270;
1157 else
1158 ex->ent.angles[1] = 0;
1159
1160 ex->type = ex_misc;
1161 ex->ent.flags = RF_FULLBRIGHT|RF_TRANSLUCENT;
1162
1163 // PMM
1164 if (type == TE_BLASTER2)
1165 ex->ent.skinnum = 1;
1166 else // flechette
1167 ex->ent.skinnum = 2;
1168
1169 ex->start = cl.frame.servertime - 100;
1170 ex->light = 150;
1171 // PMM
1172 if (type == TE_BLASTER2)
1173 ex->lightcolor[1] = 1;
1174 else // flechette
1175 {
1176 ex->lightcolor[0] = 0.19;
1177 ex->lightcolor[1] = 0.41;
1178 ex->lightcolor[2] = 0.75;
1179 }
1180 ex->ent.model = cl_mod_explode;
1181 ex->frames = 4;
1182 S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
1183 break;
1184
1185
1186 case TE_LIGHTNING:
1187 #ifdef QMAX
1188 ent = CL_ParseLightning (10);
1189 #else
1190 ent = CL_ParseLightning (cl_mod_lightning);
1191 #endif
1192 S_StartSound (NULL, ent, CHAN_WEAPON, cl_sfx_lightning, 1, ATTN_NORM, 0);
1193 break;
1194
1195 case TE_DEBUGTRAIL:
1196 MSG_ReadPos (&net_message, pos);
1197 MSG_ReadPos (&net_message, pos2);
1198 CL_DebugTrail (pos, pos2);
1199 break;
1200
1201 case TE_PLAIN_EXPLOSION:
1202 MSG_ReadPos (&net_message, pos);
1203
1204 ex = CL_AllocExplosion ();
1205 VectorCopy (pos, ex->ent.origin);
1206 ex->type = ex_poly;
1207 ex->ent.flags = RF_FULLBRIGHT|RF_NOSHADOW;
1208 ex->start = cl.frame.servertime - 100;
1209 ex->light = 350;
1210 ex->lightcolor[0] = 1.0;
1211 ex->lightcolor[1] = 0.5;
1212 ex->lightcolor[2] = 0.5;
1213 ex->ent.angles[1] = rand() % 360;
1214 ex->ent.model = cl_mod_explo4;
1215 if (frand() < 0.5)
1216 ex->baseframe = 15;
1217 ex->frames = 15;
1218 if (type == TE_ROCKET_EXPLOSION_WATER)
1219 S_StartSound (pos, 0, 0, cl_sfx_watrexp, 1, ATTN_NORM, 0);
1220 else
1221 S_StartSound (pos, 0, 0, cl_sfx_rockexp, 1, ATTN_NORM, 0);
1222 break;
1223
1224 case TE_FLASHLIGHT:
1225 MSG_ReadPos(&net_message, pos);
1226 ent = MSG_ReadShort(&net_message);
1227 CL_Flashlight(ent, pos);
1228 break;
1229
1230 case TE_FORCEWALL:
1231 MSG_ReadPos(&net_message, pos);
1232 MSG_ReadPos(&net_message, pos2);
1233 color = MSG_ReadByte (&net_message);
1234 CL_ForceWall(pos, pos2, color);
1235 break;
1236
1237 case TE_HEATBEAM:
1238 ent = CL_ParsePlayerBeam (cl_mod_heatbeam);
1239 break;
1240
1241 case TE_MONSTER_HEATBEAM:
1242 ent = CL_ParsePlayerBeam (cl_mod_monster_heatbeam);
1243 break;
1244
1245 case TE_HEATBEAM_SPARKS:
1246 // cnt = MSG_ReadByte (&net_message);
1247 cnt = 50;
1248 MSG_ReadPos (&net_message, pos);
1249 MSG_ReadDir (&net_message, dir);
1250 // r = MSG_ReadByte (&net_message);
1251 // magnitude = MSG_ReadShort (&net_message);
1252 r = 8;
1253 magnitude = 60;
1254 color = r & 0xff;
1255 CL_ParticleSteamEffect (pos, dir, color, cnt, magnitude);
1256 S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
1257 break;
1258
1259 case TE_HEATBEAM_STEAM:
1260 // cnt = MSG_ReadByte (&net_message);
1261 cnt = 20;
1262 MSG_ReadPos (&net_message, pos);
1263 MSG_ReadDir (&net_message, dir);
1264 // r = MSG_ReadByte (&net_message);
1265 // magnitude = MSG_ReadShort (&net_message);
1266 // color = r & 0xff;
1267 color = 0xe0;
1268 magnitude = 60;
1269 CL_ParticleSteamEffect (pos, dir, color, cnt, magnitude);
1270 S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
1271 break;
1272
1273 case TE_STEAM:
1274 CL_ParseSteam();
1275 break;
1276
1277 case TE_BUBBLETRAIL2:
1278 // cnt = MSG_ReadByte (&net_message);
1279 cnt = 8;
1280 MSG_ReadPos (&net_message, pos);
1281 MSG_ReadPos (&net_message, pos2);
1282 CL_BubbleTrail2 (pos, pos2, cnt);
1283 S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
1284 break;
1285
1286 case TE_MOREBLOOD:
1287 MSG_ReadPos (&net_message, pos);
1288 MSG_ReadDir (&net_message, dir);
1289 CL_ParticleEffect (pos, dir, 0xe8, 250);
1290 break;
1291
1292 case TE_CHAINFIST_SMOKE:
1293 dir[0]=0; dir[1]=0; dir[2]=1;
1294 MSG_ReadPos(&net_message, pos);
1295 CL_ParticleSmokeEffect (pos, dir, 0, 20, 20);
1296 break;
1297
1298 case TE_ELECTRIC_SPARKS:
1299 MSG_ReadPos (&net_message, pos);
1300 MSG_ReadDir (&net_message, dir);
1301 // CL_ParticleEffect (pos, dir, 109, 40);
1302 CL_ParticleEffect (pos, dir, 0x75, 40);
1303 //FIXME : replace or remove this sound
1304 S_StartSound (pos, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
1305 break;
1306
1307 case TE_TRACKER_EXPLOSION:
1308 MSG_ReadPos (&net_message, pos);
1309 CL_ColorFlash (pos, 0, 150, -1, -1, -1);
1310 CL_ColorExplosionParticles (pos, 0, 1);
1311 // CL_Tracker_Explode (pos);
1312 S_StartSound (pos, 0, 0, cl_sfx_disrexp, 1, ATTN_NORM, 0);
1313 break;
1314
1315 case TE_TELEPORT_EFFECT:
1316 case TE_DBALL_GOAL:
1317 MSG_ReadPos (&net_message, pos);
1318 CL_TeleportParticles (pos);
1319 break;
1320
1321 case TE_WIDOWBEAMOUT:
1322 CL_ParseWidow ();
1323 break;
1324
1325 case TE_NUKEBLAST:
1326 CL_ParseNuke ();
1327 break;
1328
1329 case TE_WIDOWSPLASH:
1330 MSG_ReadPos (&net_message, pos);
1331 CL_WidowSplash (pos);
1332 break;
1333 #if 0
1334 //NEW CUSTOM TEMP EVENTS
1335
1336 case TE_LIGHTNINGFLARE: //-psychospaz
1337 {
1338 int num, entity;
1339
1340 entity = MSG_ReadShort (&net_message);
1341 num = MSG_ReadShort (&net_message);
1342 MSG_ReadPos (&net_message, pos);
1343
1344 //double up for opacity endurance
1345 CL_LightningFlare(pos, entity, 2*num);
1346 CL_LightningFlare(pos, entity, 2*num+1);
1347 }
1348 break;
1349 case TE_SMOKEPUFF: //hahaha server declared stains biotch - psychospaz
1350 {
1351 float size;
1352
1353 MSG_ReadPos (&net_message, pos);
1354 MSG_ReadPos (&net_message, dir);
1355 size = MSG_ReadFloat(&net_message);
1356
1357 CL_ParticleSmokeEffect (pos, dir, size);
1358 }
1359 break;
1360 case TE_STAIN: //hahaha server declared stains biotch - psychospaz
1361 {
1362 float intens;
1363 int i, color[3];
1364
1365 MSG_ReadPos (&net_message, pos);
1366 intens = MSG_ReadFloat(&net_message);
1367 for (i=0;i<3;i++)
1368 color[i] = -MSG_ReadByte(&net_message);
1369
1370 re.AddStain(pos, intens,
1371 color[0],
1372 color[1],
1373 color[2]);
1374 }
1375 break;
1376 case TE_FOOTPRINT:
1377 {
1378 float size;
1379 vec3_t color, angle;
1380
1381 MSG_ReadPos (&net_message, pos);
1382 MSG_ReadPos (&net_message, dir);
1383 MSG_ReadPos (&net_message, color);
1384 size = MSG_ReadFloat(&net_message);
1385
1386 angle[0] = anglemod(dir[0] + 180);
1387 angle[1] = anglemod(dir[1]);
1388 angle[2] = anglemod(dir[2]);
1389
1390 CL_ParticleFootPrint (pos, angle, size, color);
1391 }
1392 break;
1393 case TE_FLAMEBURST:
1394 {
1395 float size;
1396
1397 MSG_ReadPos (&net_message, pos);
1398 size = MSG_ReadFloat(&net_message);
1399
1400 CL_FlameBurst (pos, size);
1401 }
1402 break;
1403 case TE_LASERSTUN:
1404 {
1405 int i;
1406 float size;
1407 vec3_t color;
1408
1409 MSG_ReadPos (&net_message, pos);
1410 MSG_ReadPos (&net_message, dir);
1411 size = MSG_ReadFloat(&net_message);
1412 for (i=0;i<3;i++)
1413 color[i] = (float)MSG_ReadByte(&net_message);
1414
1415 CL_LaserStun (pos, dir, color, size);
1416 }
1417 break;
1418 case TE_STUNBLAST:
1419 {
1420 int i;
1421 float size;
1422 vec3_t color;
1423
1424 MSG_ReadPos (&net_message, pos);
1425 size = MSG_ReadFloat(&net_message);
1426 for (i=0;i<3;i++)
1427 color[i] = (float)MSG_ReadByte(&net_message);
1428
1429 CL_StunBlast (pos, color, size);
1430 }
1431 break;
1432 case TE_DISRUPTOR_EXPLOSION:
1433 {
1434 float size;
1435
1436 MSG_ReadPos (&net_message, pos);
1437 size = MSG_ReadFloat(&net_message);
1438
1439 CL_Disruptor_Explosion_Particle (pos, size);
1440
1441 S_StartSound (pos, 0, 0, cl_sfx_rockexp, 1, ATTN_NORM, 0);
1442 }
1443 break;
1444 case TE_DISINTEGRATE:
1445 {
1446 ent = MSG_ReadByte(&net_message);
1447 MSG_ReadPos (&net_message, pos);
1448 CL_Disintegrate (pos, ent);
1449 }
1450 break;
1451 case TE_LENSFLARE:
1452 {
1453 float size, time;
1454
1455 MSG_ReadPos (&net_message, pos);
1456 MSG_ReadPos (&net_message, dir);
1457 size = MSG_ReadFloat (&net_message);
1458 time = MSG_ReadFloat (&net_message);
1459
1460 CL_LensFlare(pos, dir, size, time);
1461 }
1462 break;
1463 case TE_WEATHERFX:
1464 {
1465 vec3_t color;
1466 int type;
1467 float size, time;
1468
1469 MSG_ReadPos (&net_message, pos);
1470 MSG_ReadPos (&net_message, dir);
1471 MSG_ReadPos (&net_message, color);
1472 type = MSG_ReadByte (&net_message);
1473 size = MSG_ReadFloat (&net_message);
1474 time = MSG_ReadFloat (&net_message);
1475
1476 CL_WeatherFx(pos, dir, color, type, size, time);
1477 }
1478 break;
1479
1480 #endif
1481 //PGM
1482 //==============
1483
1484 default:
1485 Com_Error (ERR_DROP, "CL_ParseTEnt: bad type");
1486 }
1487 }
1488
1489 /*
1490 =================
1491 CL_AddBeams
1492 =================
1493 */
CL_AddBeams(void)1494 void CL_AddBeams (void)
1495 {
1496 int i,j;
1497 beam_t *b;
1498 vec3_t dist, org;
1499 float d;
1500 entity_t ent;
1501 float yaw, pitch;
1502 float forward;
1503 float len, steps;
1504 float model_length;
1505
1506 // update beams
1507 for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
1508 {
1509 if (!b->model || b->endtime < cl.time)
1510 continue;
1511
1512 // if coming from the player, update the start position
1513 if (b->entity == cl.playernum+1) // entity 0 is the world
1514 {
1515 VectorCopy (cl.refdef.vieworg, b->start);
1516 b->start[2] -= 22; // adjust for view height
1517 }
1518 VectorAdd (b->start, b->offset, org);
1519
1520 // calculate pitch and yaw
1521 VectorSubtract (b->end, org, dist);
1522
1523 if (dist[1] == 0 && dist[0] == 0)
1524 {
1525 yaw = 0;
1526 if (dist[2] > 0)
1527 pitch = 90;
1528 else
1529 pitch = 270;
1530 }
1531 else
1532 {
1533 // PMM - fixed to correct for pitch of 0
1534 if (dist[0])
1535 yaw = (atan2(dist[1], dist[0]) * 180 / M_PI);
1536 else if (dist[1] > 0)
1537 yaw = 90;
1538 else
1539 yaw = 270;
1540 if (yaw < 0)
1541 yaw += 360;
1542
1543 forward = sqrt (dist[0]*dist[0] + dist[1]*dist[1]);
1544 pitch = (atan2(dist[2], forward) * -180.0 / M_PI);
1545 if (pitch < 0)
1546 pitch += 360.0;
1547 }
1548
1549 // add new entities for the beams
1550 d = VectorNormalize(dist);
1551
1552 memset (&ent, 0, sizeof(ent));
1553 if (b->model == cl_mod_lightning)
1554 {
1555 model_length = 35.0;
1556 d-= 20.0; // correction so it doesn't end in middle of tesla
1557 }
1558 else
1559 {
1560 model_length = 30.0;
1561 }
1562 steps = ceil(d/model_length);
1563 len = (d-model_length)/(steps-1);
1564
1565 // PMM - special case for lightning model .. if the real length is shorter than the model,
1566 // flip it around & draw it from the end to the start. This prevents the model from going
1567 // through the tesla mine (instead it goes through the target)
1568 if ((b->model == cl_mod_lightning) && (d <= model_length))
1569 {
1570 // Com_Printf ("special case\n");
1571 VectorCopy (b->end, ent.origin);
1572 // offset to push beam outside of tesla model (negative because dist is from end to start
1573 // for this beam)
1574 // for (j=0 ; j<3 ; j++)
1575 // ent.origin[j] -= dist[j]*10.0;
1576 ent.model = b->model;
1577 ent.flags = RF_FULLBRIGHT;
1578 ent.angles[0] = pitch;
1579 ent.angles[1] = yaw;
1580 ent.angles[2] = rand()%360;
1581 V_AddEntity (&ent);
1582 return;
1583 }
1584 while (d > 0)
1585 {
1586 VectorCopy (org, ent.origin);
1587 ent.model = b->model;
1588 if (b->model == cl_mod_lightning)
1589 {
1590 ent.flags = RF_FULLBRIGHT;
1591 ent.angles[0] = -pitch;
1592 ent.angles[1] = yaw + 180.0;
1593 ent.angles[2] = rand()%360;
1594 }
1595 else
1596 {
1597 ent.angles[0] = pitch;
1598 ent.angles[1] = yaw;
1599 ent.angles[2] = rand()%360;
1600 }
1601
1602 // Com_Printf("B: %d -> %d\n", b->entity, b->dest_entity);
1603 V_AddEntity (&ent);
1604
1605 for (j=0 ; j<3 ; j++)
1606 org[j] += dist[j]*len;
1607 d -= model_length;
1608 }
1609 }
1610 }
1611
1612
1613 /*
1614 // Com_Printf ("Endpoint: %f %f %f\n", b->end[0], b->end[1], b->end[2]);
1615 // Com_Printf ("Pred View Angles: %f %f %f\n", cl.predicted_angles[0], cl.predicted_angles[1], cl.predicted_angles[2]);
1616 // Com_Printf ("Act View Angles: %f %f %f\n", cl.refdef.viewangles[0], cl.refdef.viewangles[1], cl.refdef.viewangles[2]);
1617 // VectorCopy (cl.predicted_origin, b->start);
1618 // b->start[2] += 22; // adjust for view height
1619 // if (fabs(cl.refdef.vieworg[2] - b->start[2]) >= 10) {
1620 // b->start[2] = cl.refdef.vieworg[2];
1621 // }
1622
1623 // Com_Printf ("Time: %d %d %f\n", cl.time, cls.realtime, cls.frametime);
1624 */
1625
1626 extern cvar_t *hand;
1627
1628 /*
1629 =================
1630 ROGUE - draw player locked beams
1631 CL_AddPlayerBeams
1632 =================
1633 */
CL_AddPlayerBeams(void)1634 void CL_AddPlayerBeams (void)
1635 {
1636 int i,j;
1637 beam_t *b;
1638 vec3_t dist, org;
1639 float d;
1640 entity_t ent;
1641 float yaw, pitch;
1642 float forward;
1643 float len, steps;
1644 int framenum;
1645 float model_length;
1646
1647 float hand_multiplier;
1648 frame_t *oldframe;
1649 player_state_t *ps, *ops;
1650
1651 framenum = 0;
1652
1653 //PMM
1654 if (hand)
1655 {
1656 if (hand->value == 2)
1657 hand_multiplier = 0;
1658 else if (hand->value == 1)
1659 hand_multiplier = -1;
1660 else
1661 hand_multiplier = 1;
1662 }
1663 else
1664 {
1665 hand_multiplier = 1;
1666 }
1667 //PMM
1668
1669 // update beams
1670 for (i=0, b=cl_playerbeams ; i< MAX_BEAMS ; i++, b++)
1671 {
1672 vec3_t f,r,u;
1673 if (!b->model || b->endtime < cl.time)
1674 continue;
1675
1676 if(cl_mod_heatbeam && (b->model == cl_mod_heatbeam))
1677 {
1678
1679 // if coming from the player, update the start position
1680 if (b->entity == cl.playernum+1) // entity 0 is the world
1681 {
1682 // set up gun position
1683 // code straight out of CL_AddViewWeapon
1684 ps = &cl.frame.playerstate;
1685 j = (cl.frame.serverframe - 1) & UPDATE_MASK;
1686 oldframe = &cl.frames[j];
1687 if (oldframe->serverframe != cl.frame.serverframe-1 || !oldframe->valid)
1688 oldframe = &cl.frame; // previous frame was dropped or involid
1689 ops = &oldframe->playerstate;
1690 for (j=0 ; j<3 ; j++)
1691 {
1692 b->start[j] = cl.refdef.vieworg[j] + ops->gunoffset[j]
1693 + cl.lerpfrac * (ps->gunoffset[j] - ops->gunoffset[j]);
1694 }
1695 VectorMA (b->start, (hand_multiplier * b->offset[0]), cl.v_right, org);
1696 VectorMA ( org, b->offset[1], cl.v_forward, org);
1697 VectorMA ( org, b->offset[2], cl.v_up, org);
1698 if ((hand) && (hand->value == 2)) {
1699 VectorMA (org, -1, cl.v_up, org);
1700 }
1701 // FIXME - take these out when final
1702 VectorCopy (cl.v_right, r);
1703 VectorCopy (cl.v_forward, f);
1704 VectorCopy (cl.v_up, u);
1705
1706 }
1707 else
1708 VectorCopy (b->start, org);
1709 }
1710 else
1711 {
1712 // if coming from the player, update the start position
1713 if (b->entity == cl.playernum+1) // entity 0 is the world
1714 {
1715 VectorCopy (cl.refdef.vieworg, b->start);
1716 b->start[2] -= 22; // adjust for view height
1717 }
1718 VectorAdd (b->start, b->offset, org);
1719 }
1720
1721 // calculate pitch and yaw
1722 VectorSubtract (b->end, org, dist);
1723
1724 //PMM
1725 if(cl_mod_heatbeam && (b->model == cl_mod_heatbeam) && (b->entity == cl.playernum+1))
1726 {
1727 vec_t len;
1728
1729 len = VectorLength (dist);
1730 VectorScale (f, len, dist);
1731 VectorMA (dist, (hand_multiplier * b->offset[0]), r, dist);
1732 VectorMA (dist, b->offset[1], f, dist);
1733 VectorMA (dist, b->offset[2], u, dist);
1734 if ((hand) && (hand->value == 2)) {
1735 VectorMA (org, -1, cl.v_up, org);
1736 }
1737 }
1738 //PMM
1739
1740 if (dist[1] == 0 && dist[0] == 0)
1741 {
1742 yaw = 0;
1743 if (dist[2] > 0)
1744 pitch = 90;
1745 else
1746 pitch = 270;
1747 }
1748 else
1749 {
1750 // PMM - fixed to correct for pitch of 0
1751 if (dist[0])
1752 yaw = (atan2(dist[1], dist[0]) * 180 / M_PI);
1753 else if (dist[1] > 0)
1754 yaw = 90;
1755 else
1756 yaw = 270;
1757 if (yaw < 0)
1758 yaw += 360;
1759
1760 forward = sqrt (dist[0]*dist[0] + dist[1]*dist[1]);
1761 pitch = (atan2(dist[2], forward) * -180.0 / M_PI);
1762 if (pitch < 0)
1763 pitch += 360.0;
1764 }
1765
1766 if (cl_mod_heatbeam && (b->model == cl_mod_heatbeam))
1767 {
1768 if (b->entity != cl.playernum+1)
1769 {
1770 framenum = 2;
1771 // Com_Printf ("Third person\n");
1772 ent.angles[0] = -pitch;
1773 ent.angles[1] = yaw + 180.0;
1774 ent.angles[2] = 0;
1775 // Com_Printf ("%f %f - %f %f %f\n", -pitch, yaw+180.0, b->offset[0], b->offset[1], b->offset[2]);
1776 AngleVectors(ent.angles, f, r, u);
1777
1778 // if it's a non-origin offset, it's a player, so use the hardcoded player offset
1779 if (!VectorCompare (b->offset, vec3_origin))
1780 {
1781 VectorMA (org, -(b->offset[0])+1, r, org);
1782 VectorMA (org, -(b->offset[1]), f, org);
1783 VectorMA (org, -(b->offset[2])-10, u, org);
1784 }
1785 else
1786 {
1787 // if it's a monster, do the particle effect
1788 CL_MonsterPlasma_Shell(b->start);
1789 }
1790 }
1791 else
1792 {
1793 framenum = 1;
1794 }
1795 }
1796
1797 // if it's the heatbeam, draw the particle effect
1798 if ((cl_mod_heatbeam && (b->model == cl_mod_heatbeam) && (b->entity == cl.playernum+1)))
1799 {
1800 CL_Heatbeam (org, dist);
1801 }
1802
1803 // add new entities for the beams
1804 d = VectorNormalize(dist);
1805
1806 memset (&ent, 0, sizeof(ent));
1807 if (b->model == cl_mod_heatbeam)
1808 {
1809 model_length = 32.0;
1810 }
1811 else if (b->model == cl_mod_lightning)
1812 {
1813 model_length = 35.0;
1814 d-= 20.0; // correction so it doesn't end in middle of tesla
1815 }
1816 else
1817 {
1818 model_length = 30.0;
1819 }
1820 steps = ceil(d/model_length);
1821 len = (d-model_length)/(steps-1);
1822
1823 // PMM - special case for lightning model .. if the real length is shorter than the model,
1824 // flip it around & draw it from the end to the start. This prevents the model from going
1825 // through the tesla mine (instead it goes through the target)
1826 if ((b->model == cl_mod_lightning) && (d <= model_length))
1827 {
1828 // Com_Printf ("special case\n");
1829 VectorCopy (b->end, ent.origin);
1830 // offset to push beam outside of tesla model (negative because dist is from end to start
1831 // for this beam)
1832 // for (j=0 ; j<3 ; j++)
1833 // ent.origin[j] -= dist[j]*10.0;
1834 ent.model = b->model;
1835 ent.flags = RF_FULLBRIGHT;
1836 ent.angles[0] = pitch;
1837 ent.angles[1] = yaw;
1838 ent.angles[2] = rand()%360;
1839 V_AddEntity (&ent);
1840 return;
1841 }
1842 while (d > 0)
1843 {
1844 VectorCopy (org, ent.origin);
1845 ent.model = b->model;
1846 if(cl_mod_heatbeam && (b->model == cl_mod_heatbeam))
1847 {
1848 // ent.flags = RF_FULLBRIGHT|RF_TRANSLUCENT;
1849 // ent.alpha = 0.3;
1850 ent.flags = RF_FULLBRIGHT;
1851 ent.angles[0] = -pitch;
1852 ent.angles[1] = yaw + 180.0;
1853 ent.angles[2] = (cl.time) % 360;
1854 // ent.angles[2] = rand()%360;
1855 ent.frame = framenum;
1856 }
1857 else if (b->model == cl_mod_lightning)
1858 {
1859 ent.flags = RF_FULLBRIGHT;
1860 ent.angles[0] = -pitch;
1861 ent.angles[1] = yaw + 180.0;
1862 ent.angles[2] = rand()%360;
1863 }
1864 else
1865 {
1866 ent.angles[0] = pitch;
1867 ent.angles[1] = yaw;
1868 ent.angles[2] = rand()%360;
1869 }
1870
1871 // Com_Printf("B: %d -> %d\n", b->entity, b->dest_entity);
1872 V_AddEntity (&ent);
1873
1874 for (j=0 ; j<3 ; j++)
1875 org[j] += dist[j]*len;
1876 d -= model_length;
1877 }
1878 }
1879 }
1880
1881 /*
1882 =================
1883 CL_AddExplosions
1884 =================
1885 */
CL_AddExplosions(void)1886 void CL_AddExplosions (void)
1887 {
1888 entity_t *ent;
1889 int i;
1890 explosion_t *ex;
1891 float frac;
1892 int f;
1893
1894 memset (&ent, 0, sizeof(ent));
1895
1896 for (i=0, ex=cl_explosions ; i< MAX_EXPLOSIONS ; i++, ex++)
1897 {
1898 if (ex->type == ex_free)
1899 continue;
1900 frac = (cl.time - ex->start)/100.0;
1901 f = floor(frac);
1902
1903 ent = &ex->ent;
1904
1905 switch (ex->type)
1906 {
1907 case ex_mflash:
1908 if (f >= ex->frames-1)
1909 ex->type = ex_free;
1910 break;
1911 case ex_misc:
1912 if (f >= ex->frames-1)
1913 {
1914 ex->type = ex_free;
1915 break;
1916 }
1917 ent->alpha = 1.0 - frac/(ex->frames-1);
1918 break;
1919 case ex_flash:
1920 if (f >= 1)
1921 {
1922 ex->type = ex_free;
1923 break;
1924 }
1925 ent->alpha = 1.0;
1926 break;
1927 case ex_poly:
1928 if (f >= ex->frames-1)
1929 {
1930 ex->type = ex_free;
1931 break;
1932 }
1933
1934 ent->alpha = (16.0 - (float)f)/16.0;
1935
1936 if (f < 10)
1937 {
1938 ent->skinnum = (f>>1);
1939 if (ent->skinnum < 0)
1940 ent->skinnum = 0;
1941 }
1942 else
1943 {
1944 ent->flags |= RF_TRANSLUCENT;
1945 if (f < 13)
1946 ent->skinnum = 5;
1947 else
1948 ent->skinnum = 6;
1949 }
1950 break;
1951 case ex_poly2:
1952 if (f >= ex->frames-1)
1953 {
1954 ex->type = ex_free;
1955 break;
1956 }
1957
1958 ent->alpha = (5.0 - (float)f)/5.0;
1959 ent->skinnum = 0;
1960 ent->flags |= RF_TRANSLUCENT;
1961 break;
1962 default:
1963 break;
1964 }
1965
1966 if (ex->type == ex_free)
1967 continue;
1968 if (ex->light)
1969 {
1970 V_AddLight (ent->origin, ex->light*ent->alpha,
1971 ex->lightcolor[0], ex->lightcolor[1], ex->lightcolor[2]);
1972 }
1973
1974 VectorCopy (ent->origin, ent->oldorigin);
1975
1976 if (f < 0)
1977 f = 0;
1978 ent->frame = ex->baseframe + f + 1;
1979 ent->oldframe = ex->baseframe + f;
1980 ent->backlerp = 1.0 - cl.lerpfrac;
1981
1982 V_AddEntity (ent);
1983 }
1984 }
1985
1986
1987 /*
1988 =================
1989 CL_AddLasers
1990 =================
1991 */
CL_AddLasers(void)1992 void CL_AddLasers (void)
1993 {
1994 laser_t *l;
1995 int i;
1996
1997 for (i=0, l=cl_lasers ; i< MAX_LASERS ; i++, l++)
1998 {
1999 if (l->endtime >= cl.time)
2000 V_AddEntity (&l->ent);
2001 }
2002 }
2003
2004 /* PMM - CL_Sustains */
CL_ProcessSustain()2005 void CL_ProcessSustain ()
2006 {
2007 cl_sustain_t *s;
2008 int i;
2009
2010 for (i=0, s=cl_sustains; i< MAX_SUSTAINS; i++, s++)
2011 {
2012 if (s->id) {
2013 if ((s->endtime >= cl.time) && (cl.time >= s->nextthink))
2014 {
2015 // Com_Printf ("think %d %d %d\n", cl.time, s->nextthink, s->thinkinterval);
2016 s->think (s);
2017 }
2018 else if (s->endtime < cl.time)
2019 s->id = 0;
2020 }
2021 }
2022 }
2023
2024 /*
2025 =================
2026 CL_AddTEnts
2027 =================
2028 */
CL_AddTEnts(void)2029 void CL_AddTEnts (void)
2030 {
2031 CL_AddBeams ();
2032 // PMM - draw plasma beams
2033 CL_AddPlayerBeams ();
2034 CL_AddExplosions ();
2035 CL_AddLasers ();
2036 // PMM - set up sustain
2037 CL_ProcessSustain();
2038 }
2039