Quake II RTX doxygen  1.0 dev
tent.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 Copyright (C) 2019, NVIDIA CORPORATION. All rights reserved.
4 
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9 
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19 // cl_tent.c -- client side temporary entities
20 
21 #include "client.h"
22 #include "refresh/models.h"
23 
24 qhandle_t cl_sfx_ric1;
25 qhandle_t cl_sfx_ric2;
26 qhandle_t cl_sfx_ric3;
27 qhandle_t cl_sfx_lashit;
28 qhandle_t cl_sfx_flare;
29 qhandle_t cl_sfx_spark5;
30 qhandle_t cl_sfx_spark6;
31 qhandle_t cl_sfx_spark7;
32 qhandle_t cl_sfx_railg;
33 qhandle_t cl_sfx_rockexp;
34 qhandle_t cl_sfx_grenexp;
35 qhandle_t cl_sfx_watrexp;
36 qhandle_t cl_sfx_footsteps[4];
37 
38 qhandle_t cl_sfx_lightning;
39 qhandle_t cl_sfx_disrexp;
40 
41 qhandle_t cl_mod_explode;
42 qhandle_t cl_mod_smoke;
43 qhandle_t cl_mod_flash;
46 qhandle_t cl_mod_explo4;
47 qhandle_t cl_mod_bfg_explo;
49 qhandle_t cl_mod_laser;
50 qhandle_t cl_mod_dmspot;
51 qhandle_t cl_mod_explosions[4];
52 
53 qhandle_t cl_mod_lightning;
54 qhandle_t cl_mod_heatbeam;
56 
57 extern cvar_t* cvar_pt_particle_emissive;
58 
59 /*
60 =================
61 CL_RegisterTEntSounds
62 =================
63 */
65 {
66  int i;
67  char name[MAX_QPATH];
68 
69  cl_sfx_ric1 = S_RegisterSound("world/ric1.wav");
70  cl_sfx_ric2 = S_RegisterSound("world/ric2.wav");
71  cl_sfx_ric3 = S_RegisterSound("world/ric3.wav");
72  cl_sfx_lashit = S_RegisterSound("weapons/lashit.wav");
73  cl_sfx_flare = S_RegisterSound("weapons/flare.wav");
74  cl_sfx_spark5 = S_RegisterSound("world/spark5.wav");
75  cl_sfx_spark6 = S_RegisterSound("world/spark6.wav");
76  cl_sfx_spark7 = S_RegisterSound("world/spark7.wav");
77  cl_sfx_railg = S_RegisterSound("weapons/railgf1a.wav");
78  cl_sfx_rockexp = S_RegisterSound("weapons/rocklx1a.wav");
79  cl_sfx_grenexp = S_RegisterSound("weapons/grenlx1a.wav");
80  cl_sfx_watrexp = S_RegisterSound("weapons/xpld_wat.wav");
81 
82  S_RegisterSound("player/land1.wav");
83  S_RegisterSound("player/fall2.wav");
84  S_RegisterSound("player/fall1.wav");
85 
86  for (i = 0; i < 4; i++) {
87  Q_snprintf(name, sizeof(name), "player/step%i.wav", i + 1);
89  }
90 
91  cl_sfx_lightning = S_RegisterSound("weapons/tesla.wav");
92  cl_sfx_disrexp = S_RegisterSound("weapons/disrupthit.wav");
93 }
94 
95 /*
96 =================
97 CL_RegisterTEntModels
98 =================
99 */
101 {
102  cl_mod_explode = R_RegisterModel("models/objects/explode/tris.md2");
103  cl_mod_smoke = R_RegisterModel("models/objects/smoke/tris.md2");
104  cl_mod_flash = R_RegisterModel("models/objects/flash/tris.md2");
105  cl_mod_parasite_segment = R_RegisterModel("models/monsters/parasite/segment/tris.md2");
106  cl_mod_grapple_cable = R_RegisterModel("models/ctf/segment/tris.md2");
107  cl_mod_explo4 = R_RegisterModel("models/objects/r_explode/tris.md2");
108  cl_mod_explosions[0] = R_RegisterModel("sprites/rocket_0.sp2");
109  cl_mod_explosions[1] = R_RegisterModel("sprites/rocket_1.sp2");
110  cl_mod_explosions[2] = R_RegisterModel("sprites/rocket_5.sp2");
111  cl_mod_explosions[3] = R_RegisterModel("sprites/rocket_6.sp2");
112  cl_mod_bfg_explo = R_RegisterModel("sprites/s_bfg2.sp2");
113  cl_mod_powerscreen = R_RegisterModel("models/items/armor/effect/tris.md2");
114  cl_mod_laser = R_RegisterModel("models/objects/laser/tris.md2");
115  cl_mod_dmspot = R_RegisterModel("models/objects/dmspot/tris.md2");
116 
117  cl_mod_lightning = R_RegisterModel("models/proj/lightning/tris.md2");
118  cl_mod_heatbeam = R_RegisterModel("models/proj/beam/tris.md2");
119  cl_mod_explo4_big = R_RegisterModel("models/objects/r_explode2/tris.md2");
120 
121  for (int i = 0; i < sizeof(cl_mod_explosions) / sizeof(*cl_mod_explosions); i++)
122  {
123  model_t* model = MOD_ForHandle(cl_mod_explosions[i]);
124  model->sprite_vertical = qtrue;
125  }
126 }
127 
128 /*
129 ==============================================================
130 
131 EXPLOSION MANAGEMENT
132 
133 ==============================================================
134 */
135 
137 
138 static void CL_ClearExplosions(void)
139 {
140  memset(cl_explosions, 0, sizeof(cl_explosions));
141 }
142 
144 {
145  explosion_t *e, *oldest;
146  int i;
147  int time;
148 
149  for (i = 0, e = cl_explosions; i < MAX_EXPLOSIONS; i++, e++) {
150  if (e->type == ex_free) {
151  memset(e, 0, sizeof(*e));
152  return e;
153  }
154  }
155 // find the oldest explosion
156  time = cl.time;
157  oldest = cl_explosions;
158 
159  for (i = 0, e = cl_explosions; i < MAX_EXPLOSIONS; i++, e++) {
160  if (e->start < time) {
161  time = e->start;
162  oldest = e;
163  }
164  }
165  memset(oldest, 0, sizeof(*oldest));
166  return oldest;
167 }
168 
169 static explosion_t *CL_PlainExplosion(qboolean big)
170 {
171  explosion_t *ex;
172 
173  ex = CL_AllocExplosion();
174  VectorCopy(te.pos1, ex->ent.origin);
175  ex->type = ex_poly;
176  ex->ent.flags = RF_FULLBRIGHT;
178  ex->light = 350;
179  VectorSet(ex->lightcolor, 1.0, 0.5, 0.5);
180  ex->ent.angles[1] = rand() % 360;
181 
182  int model_idx = rand() % (sizeof(cl_mod_explosions) / sizeof(*cl_mod_explosions));
183  model_t* sprite_model = MOD_ForHandle(cl_mod_explosions[model_idx]);
184 
185  if (cl_explosion_sprites->integer && !big && sprite_model)
186  {
187  ex->ent.model = cl_mod_explosions[model_idx];
188  ex->frames = sprite_model->numframes;
189  ex->frametime = cl_explosion_frametime->integer;
190  }
191  else
192  {
193  ex->ent.model = big ? cl_mod_explo4_big : cl_mod_explo4;
194  if (frand() < 0.5)
195  ex->baseframe = 15;
196  ex->frames = 15;
197  }
198 
199  return ex;
200 }
201 
202 /*
203 =================
204 CL_SmokeAndFlash
205 =================
206 */
208 {
209  explosion_t *ex;
210 
211  ex = CL_AllocExplosion();
212  VectorCopy(origin, ex->ent.origin);
213  ex->type = ex_misc;
214  ex->frames = 4;
215  ex->ent.flags = RF_TRANSLUCENT | RF_NOSHADOW;
217  ex->ent.model = cl_mod_smoke;
218 
219  ex = CL_AllocExplosion();
220  VectorCopy(origin, ex->ent.origin);
221  ex->type = ex_flash;
222  ex->ent.flags = RF_FULLBRIGHT;
223  ex->frames = 2;
225  ex->ent.model = cl_mod_flash;
226 }
227 
228 #define LENGTH(a) ((sizeof (a)) / (sizeof(*(a))))
229 
230 typedef struct light_curve_s {
231  vec3_t color;
232  float radius;
233  float offset;
234 } light_curve_t;
235 
237  { { 0.4f, 0.2f, 0.02f }, 12.5f, 20.00f },
238  { { 0.351563f, 0.175781f, 0.017578f }, 15.0f, 23.27f },
239  { { 0.30625f, 0.153125f, 0.015312f }, 20.0f, 24.95f },
240  { { 0.264062f, 0.132031f, 0.013203f }, 22.5f, 25.01f },
241  { { 0.225f, 0.1125f, 0.01125f }, 25.0f, 27.53f },
242  { { 0.189063f, 0.094531f, 0.009453f }, 27.5f, 28.55f },
243  { { 0.15625f, 0.078125f, 0.007813f }, 30.0f, 30.80f },
244  { { 0.126563f, 0.063281f, 0.006328f }, 27.5f, 40.43f },
245  { { 0.1f, 0.05f, 0.005f }, 25.0f, 49.02f },
246  { { 0.076563f, 0.038281f, 0.003828f }, 22.5f, 58.15f },
247  { { 0.05625f, 0.028125f, 0.002812f }, 20.0f, 61.03f },
248  { { 0.039063f, 0.019531f, 0.001953f }, 17.5f, 63.59f },
249  { { 0.025f, 0.0125f, 0.00125f }, 15.0f, 66.47f },
250  { { 0.014063f, 0.007031f, 0.000703f }, 12.5f, 71.34f },
251  { { 0.f, 0.f, 0.f }, 10.0f, 72.00f }
252 };
253 
255  { { 0.04f, 0.02f, 0.0f }, 5.f, 15.00f },
256  { { 0.2f, 0.15f, 0.01f }, 15.f, 15.00f },
257  { { 0.04f, 0.02f, 0.0f }, 5.f, 15.00f },
258 };
259 
260 static void CL_AddExplosionLight(explosion_t *ex, float phase)
261 {
262  int curve_size;
263  light_curve_t* curve;
264 
265  switch (ex->type)
266  {
267  case ex_poly:
268  curve = ex_poly_light;
269  curve_size = LENGTH(ex_poly_light);
270  break;
271  case ex_blaster:
272  curve = ex_blaster_light;
273  curve_size = LENGTH(ex_blaster_light);
274  break;
275  default:
276  return;
277  }
278 
279  float timeAlpha = ((float)(curve_size - 1)) * phase;
280  int baseSample = (int)floorf(timeAlpha);
281  baseSample = max(0, min(curve_size - 2, baseSample));
282 
283  float w1 = timeAlpha - (float)(baseSample);
284  float w0 = 1.f - w1;
285 
286  light_curve_t* s0 = curve + baseSample;
287  light_curve_t* s1 = curve + baseSample + 1;
288 
289  float offset = w0 * s0->offset + w1 * s1->offset;
290  float radius = w0 * s0->radius + w1 * s1->radius;
291 
292  vec3_t origin;
293  vec3_t up;
294  AngleVectors(ex->ent.angles, NULL, NULL, up);
295  VectorMA(ex->ent.origin, offset, up, origin);
296 
297  vec3_t color;
298  VectorClear(color);
299  VectorMA(color, w0, s0->color, color);
300  VectorMA(color, w1, s1->color, color);
301 
302  V_AddLightEx(origin, 500.f, color[0], color[1], color[2], radius);
303 }
304 
305 static void CL_AddExplosions(void)
306 {
307  entity_t *ent;
308  int i;
309  explosion_t *ex;
310  float frac;
311  int f;
312 
313  memset(&ent, 0, sizeof(ent));
314 
315  for (i = 0, ex = cl_explosions; i < MAX_EXPLOSIONS; i++, ex++) {
316  if (ex->type == ex_free)
317  continue;
318  float inv_frametime = ex->frametime ? 1.f / (float)ex->frametime : BASE_1_FRAMETIME;
319  frac = (cl.time - ex->start) * inv_frametime;
320  f = floor(frac);
321 
322  ent = &ex->ent;
323 
324  switch (ex->type) {
325  case ex_mflash:
326  if (f >= ex->frames - 1)
327  ex->type = ex_free;
328  break;
329  case ex_misc:
330  case ex_blaster:
331  case ex_flare:
332  case ex_light:
333  if (f >= ex->frames - 1) {
334  ex->type = ex_free;
335  break;
336  }
337  ent->alpha = 1.0 - frac / (ex->frames - 1);
338  break;
339  case ex_flash:
340  if (f >= 1) {
341  ex->type = ex_free;
342  break;
343  }
344  ent->alpha = 1.0;
345  break;
346  case ex_poly:
347  if (f >= ex->frames - 1) {
348  ex->type = ex_free;
349  break;
350  }
351 
352  ent->alpha = ((float)ex->frames - (float)f) / (float)ex->frames;
353  ent->alpha = max(0.f, min(1.f, ent->alpha));
354  ent->alpha = ent->alpha * ent->alpha * (3.f - 2.f * ent->alpha); // smoothstep
355 
356  if (f < 10) {
357  ent->skinnum = (f >> 1);
358  if (ent->skinnum < 0)
359  ent->skinnum = 0;
360  } else {
361  ent->flags |= RF_TRANSLUCENT;
362  if (f < 13)
363  ent->skinnum = 5;
364  else
365  ent->skinnum = 6;
366  }
367  break;
368  case ex_poly2:
369  if (f >= ex->frames - 1) {
370  ex->type = ex_free;
371  break;
372  }
373 
374  ent->alpha = (5.0 - (float)f) / 5.0;
375  ent->skinnum = 0;
376  ent->flags |= RF_TRANSLUCENT;
377  break;
378  default:
379  break;
380  }
381 
382  if (ex->type == ex_free)
383  continue;
384 
385  if (vid_rtx->integer)
386  CL_AddExplosionLight(ex, frac / (ex->frames - 1));
387  else
388  {
389  if (ex->light)
390  V_AddLight(ent->origin, ex->light * ent->alpha,
391  ex->lightcolor[0], ex->lightcolor[1], ex->lightcolor[2]);
392  }
393 
394  if (ex->type != ex_light) {
395  VectorCopy(ent->origin, ent->oldorigin);
396 
397  if (f < 0)
398  f = 0;
399  ent->frame = ex->baseframe + f + 1;
400  ent->oldframe = ex->baseframe + f;
401  ent->backlerp = 1.0 - (frac - f);
402 
403  V_AddEntity(ent);
404  }
405  }
406 }
407 
408 /*
409 ==============================================================
410 
411 LASER MANAGEMENT
412 
413 ==============================================================
414 */
415 
416 #define MAX_LASERS 32
417 
418 typedef struct {
419  vec3_t start;
420  vec3_t end;
421  int color;
422  color_t rgba;
423  int width;
424  int lifetime, starttime;
425 } laser_t;
426 
428 
429 static void CL_ClearLasers(void)
430 {
431  memset(cl_lasers, 0, sizeof(cl_lasers));
432 }
433 
434 static laser_t *CL_AllocLaser(void)
435 {
436  laser_t *l;
437  int i;
438 
439  for (i = 0, l = cl_lasers; i < MAX_LASERS; i++, l++) {
440  if (cl.time - l->starttime >= l->lifetime) {
441  memset(l, 0, sizeof(*l));
442  l->starttime = cl.time;
443  return l;
444  }
445  }
446 
447  return NULL;
448 }
449 
450 static void CL_AddLasers(void)
451 {
452  laser_t *l;
453  entity_t ent;
454  int i;
455  int time;
456 
457  memset(&ent, 0, sizeof(ent));
458 
459  for (i = 0, l = cl_lasers; i < MAX_LASERS; i++, l++) {
460  time = l->lifetime - (cl.time - l->starttime);
461  if (time < 0) {
462  continue;
463  }
464 
465  if (l->color == -1) {
466  float f = (float)time / (float)l->lifetime;
467 
468  ent.rgba.u8[0] = l->rgba.u8[0];
469  ent.rgba.u8[1] = l->rgba.u8[1];
470  ent.rgba.u8[2] = l->rgba.u8[2];
471  ent.rgba.u8[3] = l->rgba.u8[3] * f;
472  ent.alpha = f;
473  } else {
474  ent.alpha = 0.30f;
475  }
476 
477  ent.skinnum = l->color;
478  ent.flags = RF_TRANSLUCENT | RF_BEAM;
479  VectorCopy(l->start, ent.origin);
480  VectorCopy(l->end, ent.oldorigin);
481  ent.frame = l->width;
482 
483  V_AddEntity(&ent);
484  }
485 }
486 
487 static void CL_ParseLaser(int colors)
488 {
489  laser_t *l;
490 
491  l = CL_AllocLaser();
492  if (!l)
493  return;
494 
495  VectorCopy(te.pos1, l->start);
496  VectorCopy(te.pos2, l->end);
497  l->lifetime = 100;
498  l->color = (colors >> ((rand() % 4) * 8)) & 0xff;
499  l->width = 4;
500 }
501 
502 /*
503 ==============================================================
504 
505 BEAM MANAGEMENT
506 
507 ==============================================================
508 */
509 
510 #define MAX_BEAMS 32
511 
512 typedef struct {
513  int entity;
515  qhandle_t model;
516  int endtime;
517  vec3_t offset;
518  vec3_t start, end;
519 } beam_t;
520 
523 
524 static void CL_ClearBeams(void)
525 {
526  memset(cl_beams, 0, sizeof(cl_beams));
527  memset(cl_playerbeams, 0, sizeof(cl_playerbeams));
528 }
529 
530 static void CL_ParseBeam(qhandle_t model)
531 {
532  beam_t *b;
533  int i;
534 
535 // override any beam with the same source AND destination entities
536  for (i = 0, b = cl_beams; i < MAX_BEAMS; i++, b++)
537  if (b->entity == te.entity1 && b->dest_entity == te.entity2)
538  goto override;
539 
540 // find a free beam
541  for (i = 0, b = cl_beams; i < MAX_BEAMS; i++, b++) {
542  if (!b->model || b->endtime < cl.time) {
543 override:
544  b->entity = te.entity1;
545  b->dest_entity = te.entity2;
546  b->model = model;
547  b->endtime = cl.time + 200;
548  VectorCopy(te.pos1, b->start);
549  VectorCopy(te.pos2, b->end);
550  VectorCopy(te.offset, b->offset);
551  return;
552  }
553  }
554 }
555 
556 static void CL_ParsePlayerBeam(qhandle_t model)
557 {
558  beam_t *b;
559  int i;
560 
561 // override any beam with the same entity
562  for (i = 0, b = cl_playerbeams; i < MAX_BEAMS; i++, b++) {
563  if (b->entity == te.entity1) {
564  b->entity = te.entity1;
565  b->model = model;
566  b->endtime = cl.time + 200;
567  VectorCopy(te.pos1, b->start);
568  VectorCopy(te.pos2, b->end);
569  VectorCopy(te.offset, b->offset);
570  return;
571  }
572  }
573 
574 // find a free beam
575  for (i = 0, b = cl_playerbeams; i < MAX_BEAMS; i++, b++) {
576  if (!b->model || b->endtime < cl.time) {
577  b->entity = te.entity1;
578  b->model = model;
579  b->endtime = cl.time + 100; // PMM - this needs to be 100 to prevent multiple heatbeams
580  VectorCopy(te.pos1, b->start);
581  VectorCopy(te.pos2, b->end);
582  VectorCopy(te.offset, b->offset);
583  return;
584  }
585  }
586 
587 }
588 
589 /*
590 =================
591 CL_AddBeams
592 =================
593 */
594 static void CL_AddBeams(void)
595 {
596  int i, j;
597  beam_t *b;
598  vec3_t dist, org;
599  float d;
600  entity_t ent;
601  vec3_t angles;
602  float len, steps;
603  float model_length;
604 
605 // update beams
606  for (i = 0, b = cl_beams; i < MAX_BEAMS; i++, b++) {
607  if (!b->model || b->endtime < cl.time)
608  continue;
609 
610  // if coming from the player, update the start position
611  if (b->entity == cl.frame.clientNum + 1)
612  VectorAdd(cl.playerEntityOrigin, b->offset, org);
613  else
614  VectorAdd(b->start, b->offset, org);
615 
616  // calculate pitch and yaw
617  VectorSubtract(b->end, org, dist);
618  vectoangles2(dist, angles);
619 
620  // add new entities for the beams
621  d = VectorNormalize(dist);
622  if (b->model == cl_mod_lightning) {
623  model_length = 35.0;
624  d -= 20.0; // correction so it doesn't end in middle of tesla
625  } else {
626  model_length = 30.0;
627  }
628  steps = ceil(d / model_length);
629  len = (d - model_length) / (steps - 1);
630 
631  memset(&ent, 0, sizeof(ent));
632  ent.model = b->model;
633 
634  // PMM - special case for lightning model .. if the real length is shorter than the model,
635  // flip it around & draw it from the end to the start. This prevents the model from going
636  // through the tesla mine (instead it goes through the target)
637  if ((b->model == cl_mod_lightning) && (d <= model_length)) {
638  VectorCopy(b->end, ent.origin);
639  ent.flags = RF_FULLBRIGHT;
640  ent.angles[0] = angles[0];
641  ent.angles[1] = angles[1];
642  ent.angles[2] = rand() % 360;
643  V_AddEntity(&ent);
644  return;
645  }
646 
647  while (d > 0) {
648  VectorCopy(org, ent.origin);
649  if (b->model == cl_mod_lightning) {
650  ent.flags = RF_FULLBRIGHT;
651  ent.angles[0] = -angles[0];
652  ent.angles[1] = angles[1] + 180.0;
653  ent.angles[2] = rand() % 360;
654  } else {
655  ent.angles[0] = angles[0];
656  ent.angles[1] = angles[1];
657  ent.angles[2] = rand() % 360;
658  }
659 
660  V_AddEntity(&ent);
661 
662  for (j = 0; j < 3; j++)
663  org[j] += dist[j] * len;
664  d -= model_length;
665  }
666  }
667 }
668 
669 /*
670 =================
671 CL_AddPlayerBeams
672 
673 Draw player locked beams. Currently only used by the plasma beam.
674 =================
675 */
676 static void CL_AddPlayerBeams(void)
677 {
678  int i, j;
679  beam_t *b;
680  vec3_t dist, org;
681  float d;
682  entity_t ent;
683  vec3_t angles;
684  float len, steps;
685  int framenum;
686  float model_length;
687  float hand_multiplier;
688  player_state_t *ps, *ops;
689 
690  if (info_hand->integer == 2)
691  hand_multiplier = 0;
692  else if (info_hand->integer == 1)
693  hand_multiplier = -1;
694  else
695  hand_multiplier = 1;
696 
697 // update beams
698  for (i = 0, b = cl_playerbeams; i < MAX_BEAMS; i++, b++) {
699  if (!b->model || b->endtime < cl.time)
700  continue;
701 
702  // if coming from the player, update the start position
703  if (b->entity == cl.frame.clientNum + 1) {
704  // set up gun position
705  ps = CL_KEYPS;
706  ops = CL_OLDKEYPS;
707 
708  for (j = 0; j < 3; j++)
709  b->start[j] = cl.refdef.vieworg[j] + ops->gunoffset[j] +
710  CL_KEYLERPFRAC * (ps->gunoffset[j] - ops->gunoffset[j]);
711 
712  VectorMA(b->start, (hand_multiplier * b->offset[0]), cl.v_right, org);
713  VectorMA(org, b->offset[1], cl.v_forward, org);
714  VectorMA(org, b->offset[2], cl.v_up, org);
715  if (info_hand->integer == 2)
716  VectorMA(org, -1, cl.v_up, org);
717 
718  // calculate pitch and yaw
719  VectorSubtract(b->end, org, dist);
720 
721  // FIXME: don't add offset twice?
722  d = VectorLength(dist);
723  VectorScale(cl.v_forward, d, dist);
724  VectorMA(dist, (hand_multiplier * b->offset[0]), cl.v_right, dist);
725  VectorMA(dist, b->offset[1], cl.v_forward, dist);
726  VectorMA(dist, b->offset[2], cl.v_up, dist);
727  if (info_hand->integer == 2)
728  VectorMA(org, -1, cl.v_up, org);
729 
730  // FIXME: use cl.refdef.viewangles?
731  vectoangles2(dist, angles);
732 
733  // if it's the heatbeam, draw the particle effect
734  CL_Heatbeam(org, dist);
735 
736  framenum = 1;
737  } else {
738  VectorCopy(b->start, org);
739 
740  // calculate pitch and yaw
741  VectorSubtract(b->end, org, dist);
742  vectoangles2(dist, angles);
743 
744  // if it's a non-origin offset, it's a player, so use the hardcoded player offset
745  if (!VectorCompare(b->offset, vec3_origin)) {
746  vec3_t tmp, f, r, u;
747 
748  tmp[0] = angles[0];
749  tmp[1] = angles[1] + 180.0;
750  tmp[2] = 0;
751  AngleVectors(tmp, f, r, u);
752 
753  VectorMA(org, -b->offset[0] + 1, r, org);
754  VectorMA(org, -b->offset[1], f, org);
755  VectorMA(org, -b->offset[2] - 10, u, org);
756  } else {
757  // if it's a monster, do the particle effect
759  }
760 
761  framenum = 2;
762  }
763 
764  // add new entities for the beams
765  d = VectorNormalize(dist);
766  model_length = 32.0;
767  steps = ceil(d / model_length);
768  len = (d - model_length) / (steps - 1);
769 
770  memset(&ent, 0, sizeof(ent));
771  ent.model = b->model;
772  ent.frame = framenum;
773  ent.flags = RF_FULLBRIGHT;
774  ent.angles[0] = -angles[0];
775  ent.angles[1] = angles[1] + 180.0;
776  ent.angles[2] = cl.time % 360;
777 
778  while (d > 0) {
779  VectorCopy(org, ent.origin);
780 
781  V_AddEntity(&ent);
782 
783  for (j = 0; j < 3; j++)
784  org[j] += dist[j] * len;
785  d -= model_length;
786  }
787  }
788 }
789 
790 
791 /*
792 ==============================================================
793 
794 SUSTAIN MANAGEMENT
795 
796 ==============================================================
797 */
798 
799 #define MAX_SUSTAINS 32
800 
802 
803 static void CL_ClearSustains(void)
804 {
805  memset(cl_sustains, 0, sizeof(cl_sustains));
806 }
807 
809 {
810  cl_sustain_t *s;
811  int i;
812 
813  for (i = 0, s = cl_sustains; i < MAX_SUSTAINS; i++, s++) {
814  if (s->id == 0)
815  return s;
816  }
817 
818  return NULL;
819 }
820 
821 static void CL_ProcessSustain(void)
822 {
823  cl_sustain_t *s;
824  int i;
825 
826  for (i = 0, s = cl_sustains; i < MAX_SUSTAINS; i++, s++) {
827  if (s->id) {
828  if ((s->endtime >= cl.time) && (cl.time >= s->nextthink))
829  s->think(s);
830  else if (s->endtime < cl.time)
831  s->id = 0;
832  }
833  }
834 }
835 
836 static void CL_ParseSteam(void)
837 {
838  cl_sustain_t *s;
839 
840  if (te.entity1 == -1) {
842  return;
843  }
844 
845  s = CL_AllocSustain();
846  if (!s)
847  return;
848 
849  s->id = te.entity1;
850  s->count = te.count;
851  VectorCopy(te.pos1, s->org);
852  VectorCopy(te.dir, s->dir);
853  s->color = te.color & 0xff;
854  s->magnitude = te.entity2;
855  s->endtime = cl.time + te.time;
857  s->thinkinterval = 100;
858  s->nextthink = cl.time;
859 }
860 
861 static void CL_ParseWidow(void)
862 {
863  cl_sustain_t *s;
864 
865  s = CL_AllocSustain();
866  if (!s)
867  return;
868 
869  s->id = te.entity1;
870  VectorCopy(te.pos1, s->org);
871  s->endtime = cl.time + 2100;
872  s->think = CL_Widowbeamout;
873  s->thinkinterval = 1;
874  s->nextthink = cl.time;
875 }
876 
877 static void CL_ParseNuke(void)
878 {
879  cl_sustain_t *s;
880 
881  s = CL_AllocSustain();
882  if (!s)
883  return;
884 
885  s->id = 21000;
886  VectorCopy(te.pos1, s->org);
887  s->endtime = cl.time + 1000;
888  s->think = CL_Nukeblast;
889  s->thinkinterval = 1;
890  s->nextthink = cl.time;
891 }
892 
893 //==============================================================
894 
895 static color_t railcore_color;
896 static color_t railspiral_color;
897 
898 static cvar_t *cl_railtrail_type;
899 static cvar_t *cl_railtrail_time;
900 static cvar_t *cl_railcore_color;
901 static cvar_t *cl_railcore_width;
902 static cvar_t *cl_railspiral_color;
903 static cvar_t *cl_railspiral_radius;
904 
905 static void cl_railcore_color_changed(cvar_t *self)
906 {
907  if (!SCR_ParseColor(self->string, &railcore_color)) {
908  Com_WPrintf("Invalid value '%s' for '%s'\n", self->string, self->name);
909  Cvar_Reset(self);
910  railcore_color.u32 = U32_RED;
911  }
912 }
913 
914 static void cl_railspiral_color_changed(cvar_t *self)
915 {
916  if (!SCR_ParseColor(self->string, &railspiral_color)) {
917  Com_WPrintf("Invalid value '%s' for '%s'\n", self->string, self->name);
918  Cvar_Reset(self);
919  railspiral_color.u32 = U32_BLUE;
920  }
921 }
922 
923 static void CL_RailCore(void)
924 {
925  laser_t *l;
926 
927  l = CL_AllocLaser();
928  if (!l)
929  return;
930 
931  VectorCopy(te.pos1, l->start);
932  VectorCopy(te.pos2, l->end);
933  l->color = -1;
934  l->lifetime = 1000 * cl_railtrail_time->value;
935  l->width = cl_railcore_width->integer;
936  l->rgba.u32 = railcore_color.u32;
937 }
938 
939 static void CL_RailSpiral(void)
940 {
941  vec3_t move;
942  vec3_t vec;
943  float len;
944  int j;
945  cparticle_t *p;
946  vec3_t right, up;
947  int i;
948  float d, c, s;
949  vec3_t dir;
950 
951  VectorCopy(te.pos1, move);
952  VectorSubtract(te.pos2, te.pos1, vec);
953  len = VectorNormalize(vec);
954 
955  MakeNormalVectors(vec, right, up);
956 
957  for (i = 0; i < len; i++) {
958  p = CL_AllocParticle();
959  if (!p)
960  return;
961 
962  p->time = cl.time;
963  VectorClear(p->accel);
964 
965  d = i * 0.1;
966  c = cos(d);
967  s = sin(d);
968 
969  VectorScale(right, c, dir);
970  VectorMA(dir, s, up, dir);
971 
972  p->alpha = 1.0;
973  p->alphavel = -1.0 / (cl_railtrail_time->value + frand() * 0.2);
974  p->color = -1;
975  p->rgba.u32 = railspiral_color.u32;
977  for (j = 0; j < 3; j++) {
978  p->org[j] = move[j] + dir[j] * cl_railspiral_radius->value;
979  p->vel[j] = dir[j] * 6;
980  }
981 
982  VectorAdd(move, vec, move);
983  }
984 }
985 
986 static void CL_RailLights(color_t color)
987 {
988  vec3_t fcolor;
989  fcolor[0] = (float)color.u8[0] / 255.f;
990  fcolor[1] = (float)color.u8[1] / 255.f;
991  fcolor[2] = (float)color.u8[2] / 255.f;
992 
993  vec3_t move;
994  vec3_t vec;
995  float len;
996 
997  VectorCopy(te.pos1, move);
998  VectorSubtract(te.pos2, te.pos1, vec);
999  len = VectorNormalize(vec);
1000 
1001  float num_segments = ceilf(len / 100.f);
1002  float segment_size = len / num_segments;
1003 
1004  for (float segment = 0; segment < num_segments; segment++)
1005  {
1006  float offset = (segment + 0.25f) * segment_size;
1007  vec3_t pos;
1008  VectorMA(move, offset, vec, pos);
1009 
1010  cdlight_t* dl = CL_AllocDlight(0);
1011  VectorScale(fcolor, 0.25f, dl->color);
1012  VectorCopy(pos, dl->origin);
1013  dl->radius = 400;
1014  dl->decay = 400;
1015  dl->die = cl.time + 1000;
1016  VectorScale(vec, segment_size * 0.5f, dl->velosity);
1017  }
1018 }
1019 
1020 extern uint32_t d_8to24table[256];
1021 extern cvar_t* cvar_pt_beam_lights;
1022 
1023 static void CL_RailTrail(void)
1024 {
1025  color_t rail_color;
1026 
1027  if (!cl_railtrail_type->integer)
1028  {
1029  rail_color.u32 = d_8to24table[0x74];
1030 
1031  CL_OldRailTrail();
1032  }
1033  else
1034  {
1035  rail_color = railcore_color;
1036 
1037  CL_RailCore();
1038  if (cl_railtrail_type->integer > 1) {
1039  CL_RailSpiral();
1040  }
1041  }
1042 
1043  if (!cl_railtrail_type->integer || cvar_pt_beam_lights->value <= 0)
1044  {
1045  CL_RailLights(rail_color);
1046  }
1047 }
1048 
1049 static void dirtoangles(vec3_t angles)
1050 {
1051  angles[0] = acos(te.dir[2]) / M_PI * 180;
1052  if (te.dir[0])
1053  angles[1] = atan2(te.dir[1], te.dir[0]) / M_PI * 180;
1054  else if (te.dir[1] > 0)
1055  angles[1] = 90;
1056  else if (te.dir[1] < 0)
1057  angles[1] = 270;
1058  else
1059  angles[1] = 0;
1060 }
1061 
1062 /*
1063 =================
1064 CL_ParseTEnt
1065 =================
1066 */
1067 static const byte splash_color[] = {0x00, 0xe0, 0xb0, 0x50, 0xd0, 0xe0, 0xe8};
1068 
1069 void CL_ParseTEnt(void)
1070 {
1071  explosion_t *ex;
1072  int r;
1073 
1074  switch (te.type) {
1075  case TE_BLOOD: // bullet hitting flesh
1076  if (!(cl_disable_particles->integer & NOPART_BLOOD))
1077  {
1078  // CL_ParticleEffect(te.pos1, te.dir, 0xe8, 60);
1079  CL_BloodParticleEffect(te.pos1, te.dir, 0xe8, 1000);
1080  }
1081  break;
1082 
1083  case TE_GUNSHOT: // bullet hitting wall
1084  case TE_SPARKS:
1085  case TE_BULLET_SPARKS:
1086  if (te.type == TE_GUNSHOT)
1087  CL_ParticleEffect(te.pos1, te.dir, 0, 40);
1088  else
1089  CL_ParticleEffect(te.pos1, te.dir, 0xe0, 6);
1090 
1091  if (te.type != TE_SPARKS) {
1093 
1094  // impact sound
1095  r = rand() & 15;
1096  if (r == 1)
1097  S_StartSound(te.pos1, 0, 0, cl_sfx_ric1, 1, ATTN_NORM, 0);
1098  else if (r == 2)
1099  S_StartSound(te.pos1, 0, 0, cl_sfx_ric2, 1, ATTN_NORM, 0);
1100  else if (r == 3)
1101  S_StartSound(te.pos1, 0, 0, cl_sfx_ric3, 1, ATTN_NORM, 0);
1102  }
1103  break;
1104 
1105  case TE_SCREEN_SPARKS:
1106  case TE_SHIELD_SPARKS:
1107  if (te.type == TE_SCREEN_SPARKS)
1108  CL_ParticleEffect(te.pos1, te.dir, 0xd0, 40);
1109  else
1110  CL_ParticleEffect(te.pos1, te.dir, 0xb0, 40);
1111  //FIXME : replace or remove this sound
1112  S_StartSound(te.pos1, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
1113  break;
1114 
1115  case TE_SHOTGUN: // bullet hitting wall
1116  CL_ParticleEffect(te.pos1, te.dir, 0, 20);
1118  break;
1119 
1120  case TE_SPLASH: // bullet hitting water
1121  if (te.color < 0 || te.color > 6)
1122  r = 0x00;
1123  else
1124  r = splash_color[te.color];
1126 
1127  if (te.color == SPLASH_SPARKS) {
1128  r = rand() & 3;
1129  if (r == 0)
1130  S_StartSound(te.pos1, 0, 0, cl_sfx_spark5, 1, ATTN_STATIC, 0);
1131  else if (r == 1)
1132  S_StartSound(te.pos1, 0, 0, cl_sfx_spark6, 1, ATTN_STATIC, 0);
1133  else
1134  S_StartSound(te.pos1, 0, 0, cl_sfx_spark7, 1, ATTN_STATIC, 0);
1135  }
1136  break;
1137 
1138  case TE_LASER_SPARKS:
1140  break;
1141 
1142  case TE_BLUEHYPERBLASTER:
1144  break;
1145 
1146  case TE_BLASTER: // blaster hitting wall
1147  case TE_BLASTER2: // green blaster hitting wall
1148  case TE_FLECHETTE: // flechette
1149  case TE_FLARE: // flare
1150  ex = CL_AllocExplosion();
1151  VectorCopy(te.pos1, ex->ent.origin);
1152  dirtoangles(ex->ent.angles);
1153  ex->type = ex_blaster;
1154  ex->ent.flags = RF_FULLBRIGHT | RF_TRANSLUCENT;
1155  ex->ent.tent_type = te.type;
1156  switch (te.type) {
1157  case TE_BLASTER:
1159  ex->lightcolor[0] = 1;
1160  ex->lightcolor[1] = 1;
1161  break;
1162  case TE_BLASTER2:
1163  CL_BlasterParticles2(te.pos1, te.dir, 0xd0);
1164  ex->ent.skinnum = 1;
1165  ex->lightcolor[1] = 1;
1166  break;
1167  case TE_FLECHETTE:
1168  CL_BlasterParticles2(te.pos1, te.dir, 0x6f); // 75
1169  ex->ent.skinnum = 2;
1170  ex->lightcolor[0] = 0.19;
1171  ex->lightcolor[1] = 0.41;
1172  ex->lightcolor[2] = 0.75;
1173  break;
1174  case TE_FLARE:
1175  CL_BlasterParticles2(te.pos1, te.dir, 0xd0);
1176  ex->lightcolor[0] = 1;
1177  ex->lightcolor[1] = 1;
1178  ex->type = ex_flare;
1179  break;
1180  }
1181  ex->start = cl.servertime - CL_FRAMETIME;
1182  ex->light = 150;
1183  ex->ent.model = cl_mod_explode;
1184  ex->frames = 4;
1185 
1186  if (te.type != TE_FLARE)
1187  {
1188  S_StartSound(te.pos1, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
1189  }
1190  else
1191  {
1192  // te.count is set to 1 on the first tick of the flare, 0 afterwards
1193  if (te.count!=0)
1194  S_StartSound(NULL, te.entity1, 0, cl_sfx_flare, 0.5, ATTN_NORM, 0);
1195  }
1196  break;
1197 
1198  case TE_RAILTRAIL: // railgun effect
1199  CL_RailTrail();
1200  S_StartSound(te.pos2, 0, 0, cl_sfx_railg, 1, ATTN_NORM, 0);
1201  break;
1202 
1203  case TE_GRENADE_EXPLOSION:
1204  case TE_GRENADE_EXPLOSION_WATER:
1205  ex = CL_PlainExplosion(qfalse);
1206  if (!cl_explosion_sprites->integer)
1207  {
1208  ex->frames = 19;
1209  ex->baseframe = 30;
1210  }
1211  if (cl_disable_explosions->integer & NOEXP_GRENADE)
1212  ex->type = ex_light;
1213 
1216 
1217  if (te.type == TE_GRENADE_EXPLOSION_WATER)
1218  S_StartSound(te.pos1, 0, 0, cl_sfx_watrexp, 1, ATTN_NORM, 0);
1219  else
1220  S_StartSound(te.pos1, 0, 0, cl_sfx_grenexp, 1, ATTN_NORM, 0);
1221  break;
1222 
1223  case TE_EXPLOSION2:
1224  ex = CL_PlainExplosion(qfalse);
1225  if (!cl_explosion_sprites->integer)
1226  {
1227  ex->frames = 19;
1228  ex->baseframe = 30;
1229  }
1231  S_StartSound(te.pos1, 0, 0, cl_sfx_grenexp, 1, ATTN_NORM, 0);
1232  break;
1233 
1234  case TE_PLASMA_EXPLOSION:
1235  CL_PlainExplosion(qfalse);
1237  S_StartSound(te.pos1, 0, 0, cl_sfx_rockexp, 1, ATTN_NORM, 0);
1238  break;
1239 
1240  case TE_ROCKET_EXPLOSION:
1241  case TE_ROCKET_EXPLOSION_WATER:
1242  ex = CL_PlainExplosion(qfalse);
1243  if (cl_disable_explosions->integer & NOEXP_ROCKET)
1244  ex->type = ex_light;
1245 
1248 
1249  if (te.type == TE_ROCKET_EXPLOSION_WATER)
1250  S_StartSound(te.pos1, 0, 0, cl_sfx_watrexp, 1, ATTN_NORM, 0);
1251  else
1252  S_StartSound(te.pos1, 0, 0, cl_sfx_rockexp, 1, ATTN_NORM, 0);
1253  break;
1254 
1255  case TE_EXPLOSION1:
1256  CL_PlainExplosion(qfalse);
1258  S_StartSound(te.pos1, 0, 0, cl_sfx_rockexp, 1, ATTN_NORM, 0);
1259  break;
1260 
1261  case TE_EXPLOSION1_NP:
1262  CL_PlainExplosion(qfalse);
1263  S_StartSound(te.pos1, 0, 0, cl_sfx_rockexp, 1, ATTN_NORM, 0);
1264  break;
1265 
1266  case TE_EXPLOSION1_BIG:
1267  ex = CL_PlainExplosion(qtrue);
1268  S_StartSound(te.pos1, 0, 0, cl_sfx_rockexp, 1, ATTN_NORM, 0);
1269  break;
1270 
1271  case TE_BFG_EXPLOSION:
1272  ex = CL_AllocExplosion();
1273  VectorCopy(te.pos1, ex->ent.origin);
1274  ex->type = ex_poly;
1275  ex->ent.flags = RF_FULLBRIGHT;
1276  ex->start = cl.servertime - CL_FRAMETIME;
1277  ex->light = 350;
1278  ex->lightcolor[0] = 0.0;
1279  ex->lightcolor[1] = 1.0;
1280  ex->lightcolor[2] = 0.0;
1281  ex->ent.model = cl_mod_bfg_explo;
1282  ex->ent.flags |= RF_TRANSLUCENT;
1283  ex->ent.alpha = 0.80;
1284  ex->frames = 4;
1285  break;
1286 
1287  case TE_BFG_BIGEXPLOSION:
1289  break;
1290 
1291  case TE_BFG_LASER:
1292  CL_ParseLaser(0xd0d1d2d3);
1293  break;
1294 
1295  case TE_BUBBLETRAIL:
1297  break;
1298 
1299  case TE_PARASITE_ATTACK:
1300  case TE_MEDIC_CABLE_ATTACK:
1301  VectorClear(te.offset);
1302  te.entity2 = 0;
1304  break;
1305 
1306  case TE_BOSSTPORT: // boss teleporting to station
1308  S_StartSound(te.pos1, 0, 0, S_RegisterSound("misc/bigtele.wav"), 1, ATTN_NONE, 0);
1309  break;
1310 
1311  case TE_GRAPPLE_CABLE:
1312  te.entity2 = 0;
1314  break;
1315 
1316  case TE_WELDING_SPARKS:
1318 
1319  ex = CL_AllocExplosion();
1320  VectorCopy(te.pos1, ex->ent.origin);
1321  ex->type = ex_flash;
1322  // note to self
1323  // we need a better no draw flag
1324  ex->ent.flags = RF_BEAM;
1325  ex->start = cl.servertime - CL_FRAMETIME;
1326  ex->light = 100 + (rand() % 75);
1327  ex->lightcolor[0] = 1.0;
1328  ex->lightcolor[1] = 1.0;
1329  ex->lightcolor[2] = 0.3;
1330  ex->ent.model = cl_mod_flash;
1331  ex->frames = 2;
1332  break;
1333 
1334  case TE_GREENBLOOD:
1335  CL_ParticleEffect2(te.pos1, te.dir, 0xdf, 30);
1336  break;
1337 
1338  case TE_TUNNEL_SPARKS:
1340  break;
1341 
1342  case TE_LIGHTNING:
1343  S_StartSound(NULL, te.entity1, CHAN_WEAPON, cl_sfx_lightning, 1, ATTN_NORM, 0);
1344  VectorClear(te.offset);
1346  break;
1347 
1348  case TE_DEBUGTRAIL:
1350  break;
1351 
1352  case TE_PLAIN_EXPLOSION:
1353  CL_PlainExplosion(qfalse);
1354  break;
1355 
1356  case TE_FLASHLIGHT:
1357 #if USE_DLIGHTS
1358  CL_Flashlight(te.entity1, te.pos1);
1359 #endif
1360  break;
1361 
1362  case TE_FORCEWALL:
1364  break;
1365 
1366  case TE_HEATBEAM:
1367  VectorSet(te.offset, 2, 7, -3);
1369  break;
1370 
1371  case TE_MONSTER_HEATBEAM:
1372  VectorClear(te.offset);
1374  break;
1375 
1376  case TE_HEATBEAM_SPARKS:
1377  CL_ParticleSteamEffect(te.pos1, te.dir, 0x8, 50, 60);
1378  S_StartSound(te.pos1, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
1379  break;
1380 
1381  case TE_HEATBEAM_STEAM:
1382  CL_ParticleSteamEffect(te.pos1, te.dir, 0xE0, 20, 60);
1383  S_StartSound(te.pos1, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
1384  break;
1385 
1386  case TE_STEAM:
1387  CL_ParseSteam();
1388  break;
1389 
1390  case TE_BUBBLETRAIL2:
1391  CL_BubbleTrail2(te.pos1, te.pos2, 8);
1392  S_StartSound(te.pos1, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
1393  break;
1394 
1395  case TE_MOREBLOOD:
1396  CL_ParticleEffect(te.pos1, te.dir, 0xe8, 250);
1397  break;
1398 
1399  case TE_CHAINFIST_SMOKE:
1400  VectorSet(te.dir, 0, 0, 1);
1401  CL_ParticleSmokeEffect(te.pos1, te.dir, 0, 20, 20);
1402  break;
1403 
1404  case TE_ELECTRIC_SPARKS:
1405  CL_ParticleEffect(te.pos1, te.dir, 0x75, 40);
1406  //FIXME : replace or remove this sound
1407  S_StartSound(te.pos1, 0, 0, cl_sfx_lashit, 1, ATTN_NORM, 0);
1408  break;
1409 
1410  case TE_TRACKER_EXPLOSION:
1411 #if USE_DLIGHTS
1412  CL_ColorFlash(te.pos1, 0, 150, -1, -1, -1);
1413 #endif
1415  S_StartSound(te.pos1, 0, 0, cl_sfx_disrexp, 1, ATTN_NORM, 0);
1416  break;
1417 
1418  case TE_TELEPORT_EFFECT:
1419  case TE_DBALL_GOAL:
1421  break;
1422 
1423  case TE_WIDOWBEAMOUT:
1424  CL_ParseWidow();
1425  break;
1426 
1427  case TE_NUKEBLAST:
1428  CL_ParseNuke();
1429  break;
1430 
1431  case TE_WIDOWSPLASH:
1432  CL_WidowSplash();
1433  break;
1434 
1435  default:
1436  Com_Error(ERR_DROP, "%s: bad type", __func__);
1437  }
1438 }
1439 
1440 /*
1441 =================
1442 CL_AddTEnts
1443 =================
1444 */
1445 void CL_AddTEnts(void)
1446 {
1447  CL_AddBeams();
1449  CL_AddExplosions();
1451  CL_AddLasers();
1452 }
1453 
1454 /*
1455 =================
1456 CL_ClearTEnts
1457 =================
1458 */
1459 void CL_ClearTEnts(void)
1460 {
1461  CL_ClearBeams();
1463  CL_ClearLasers();
1464  CL_ClearSustains();
1465 }
1466 
1467 void CL_InitTEnts(void)
1468 {
1469  cl_railtrail_type = Cvar_Get("cl_railtrail_type", "0", 0);
1470  cl_railtrail_time = Cvar_Get("cl_railtrail_time", "1.0", 0);
1471  cl_railcore_color = Cvar_Get("cl_railcore_color", "red", 0);
1473  cl_railcore_color->generator = Com_Color_g;
1475  cl_railcore_width = Cvar_Get("cl_railcore_width", "2", 0);
1476  cl_railspiral_color = Cvar_Get("cl_railspiral_color", "blue", 0);
1478  cl_railspiral_color->generator = Com_Color_g;
1480  cl_railspiral_radius = Cvar_Get("cl_railspiral_radius", "3", 0);
1481 }
1482 
client_state_s::frame
server_frame_t frame
Definition: client.h:212
NOPART_BLOOD
#define NOPART_BLOOD
Definition: client.h:499
laser_t::starttime
int starttime
Definition: tent.c:424
tent_params_t::time
int time
Definition: client.h:669
cl_railcore_color
static cvar_t * cl_railcore_color
Definition: tent.c:900
CL_AddTEnts
void CL_AddTEnts(void)
Definition: tent.c:1445
tent_params_t::offset
vec3_t offset
Definition: client.h:663
CL_ParsePlayerBeam
static void CL_ParsePlayerBeam(qhandle_t model)
Definition: tent.c:556
NOEXP_GRENADE
#define NOEXP_GRENADE
Definition: client.h:501
tent_params_t::pos1
vec3_t pos1
Definition: client.h:661
CL_ParticleEffect
void CL_ParticleEffect(vec3_t org, vec3_t dir, int color, int count)
Definition: effects.c:877
client_state_s::servertime
int servertime
Definition: client.h:214
CL_ClearExplosions
static void CL_ClearExplosions(void)
Definition: tent.c:138
cl_disable_explosions
cvar_t * cl_disable_explosions
Definition: main.c:52
cl_mod_explo4_big
qhandle_t cl_mod_explo4_big
Definition: tent.c:55
cl_sustain_s
Definition: client.h:741
MAX_EXPLOSIONS
#define MAX_EXPLOSIONS
Definition: client.h:58
cl_sustain_s::count
int count
Definition: client.h:750
CL_AddLasers
static void CL_AddLasers(void)
Definition: tent.c:450
beam_t::endtime
int endtime
Definition: tent.c:516
CL_Widowbeamout
void CL_Widowbeamout(cl_sustain_t *self)
Definition: newfx.c:520
CL_ParseBeam
static void CL_ParseBeam(qhandle_t model)
Definition: tent.c:530
d_8to24table
uint32_t d_8to24table[256]
Definition: images.c:654
Q_snprintf
size_t Q_snprintf(char *dest, size_t size, const char *fmt,...)
Definition: shared.c:846
explosion_t::type
enum explosion_t::@0 type
S_RegisterSound
qhandle_t S_RegisterSound(const char *name)
Definition: main.c:391
cl_sfx_ric3
qhandle_t cl_sfx_ric3
Definition: tent.c:26
cparticle_s
Definition: client.h:780
MOD_ForHandle
model_t * MOD_ForHandle(qhandle_t h)
Definition: models.c:430
client_state_s::v_forward
vec3_t v_forward
Definition: client.h:258
light_curve_s::offset
float offset
Definition: tent.c:233
tent_params_t::entity1
int entity1
Definition: client.h:667
railcore_color
static color_t railcore_color
Definition: tent.c:895
cparticle_s::brightness
float brightness
Definition: client.h:792
laser_t::start
vec3_t start
Definition: tent.c:419
tent_params_t::dir
vec3_t dir
Definition: client.h:664
cl_railtrail_type
static cvar_t * cl_railtrail_type
Definition: tent.c:898
Cvar_Get
cvar_t * Cvar_Get(const char *var_name, const char *var_value, int flags)
Definition: cvar.c:257
CL_AllocExplosion
static explosion_t * CL_AllocExplosion(void)
Definition: tent.c:143
cl_explosions
explosion_t cl_explosions[MAX_EXPLOSIONS]
Definition: tent.c:136
cl_sustain_s::thinkinterval
int thinkinterval
Definition: client.h:746
laser_t::rgba
color_t rgba
Definition: tent.c:422
CL_KEYLERPFRAC
#define CL_KEYLERPFRAC
Definition: client.h:167
cl_sfx_grenexp
qhandle_t cl_sfx_grenexp
Definition: tent.c:34
ex_poly_light
static light_curve_t ex_poly_light[]
Definition: tent.c:236
cl_sfx_watrexp
qhandle_t cl_sfx_watrexp
Definition: tent.c:35
cl_sfx_flare
qhandle_t cl_sfx_flare
Definition: tent.c:28
cparticle_s::vel
vec3_t vel
Definition: client.h:786
cparticle_s::accel
vec3_t accel
Definition: client.h:787
cl_sfx_lightning
qhandle_t cl_sfx_lightning
Definition: tent.c:38
CL_RailTrail
static void CL_RailTrail(void)
Definition: tent.c:1023
CL_AddPlayerBeams
static void CL_AddPlayerBeams(void)
Definition: tent.c:676
explosion_t::baseframe
int baseframe
Definition: client.h:79
beam_t::dest_entity
int dest_entity
Definition: tent.c:514
cl_sfx_spark7
qhandle_t cl_sfx_spark7
Definition: tent.c:31
cl_disable_particles
cvar_t * cl_disable_particles
Definition: main.c:51
CL_ParseWidow
static void CL_ParseWidow(void)
Definition: tent.c:861
CL_Nukeblast
void CL_Nukeblast(cl_sustain_t *self)
Definition: newfx.c:551
cl_sfx_ric1
qhandle_t cl_sfx_ric1
Definition: tent.c:24
client_state_s::v_up
vec3_t v_up
Definition: client.h:258
NOPART_GRENADE_EXPLOSION
#define NOPART_GRENADE_EXPLOSION
Definition: client.h:495
cl_sfx_lashit
qhandle_t cl_sfx_lashit
Definition: tent.c:27
cl_sustain_s::nextthink
int nextthink
Definition: client.h:745
cl_sfx_railg
qhandle_t cl_sfx_railg
Definition: tent.c:32
cl_mod_explo4
qhandle_t cl_mod_explo4
Definition: tent.c:46
explosion_t
Definition: client.h:60
CL_OldRailTrail
void CL_OldRailTrail(void)
Definition: effects.c:1632
explosion_t::lightcolor
vec3_t lightcolor
Definition: client.h:77
cl_sfx_disrexp
qhandle_t cl_sfx_disrexp
Definition: tent.c:39
V_AddEntity
void V_AddEntity(entity_t *ent)
Definition: view.c:91
cl_mod_flash
qhandle_t cl_mod_flash
Definition: tent.c:43
tent_params_t::entity2
int entity2
Definition: client.h:668
cl_explosion_frametime
cvar_t * cl_explosion_frametime
Definition: main.c:57
CL_ParseNuke
static void CL_ParseNuke(void)
Definition: tent.c:877
CL_ParticleSmokeEffect
void CL_ParticleSmokeEffect(vec3_t org, vec3_t dir, int color, int count, int magnitude)
Definition: newfx.c:721
CL_AddBeams
static void CL_AddBeams(void)
Definition: tent.c:594
vec3_origin
vec3_t vec3_origin
Definition: shared.c:21
cl_sustain_s::org
vec3_t org
Definition: client.h:747
CL_BlasterParticles
void CL_BlasterParticles(vec3_t org, vec3_t dir)
Definition: effects.c:1300
MAX_BEAMS
#define MAX_BEAMS
Definition: tent.c:510
info_hand
cvar_t * info_hand
Definition: main.c:86
beam_t
Definition: tent.c:512
cl_sustain_s::dir
vec3_t dir
Definition: client.h:748
cparticle_s::alphavel
float alphavel
Definition: client.h:790
laser_t::lifetime
int lifetime
Definition: tent.c:424
beam_t::end
vec3_t end
Definition: tent.c:518
CL_PlainExplosion
static explosion_t * CL_PlainExplosion(qboolean big)
Definition: tent.c:169
cl_sustain_s::id
int id
Definition: client.h:742
CL_ClearSustains
static void CL_ClearSustains(void)
Definition: tent.c:803
cparticle_s::rgba
color_t rgba
Definition: client.h:791
client_state_s::refdef
refdef_t refdef
Definition: client.h:253
Com_Error
void Com_Error(error_type_t type, const char *fmt,...)
Definition: g_main.c:258
R_RegisterModel
qhandle_t R_RegisterModel(const char *name)
Definition: models.c:305
client_state_s::playerEntityOrigin
vec3_t playerEntityOrigin
Definition: client.h:263
CL_ForceWall
void CL_ForceWall(vec3_t start, vec3_t end, int color)
Definition: newfx.c:143
CL_DebugTrail
void CL_DebugTrail(vec3_t start, vec3_t end)
Definition: newfx.c:63
CL_ExplosionParticles
void CL_ExplosionParticles(vec3_t org)
Definition: effects.c:1221
cl_playerbeams
static beam_t cl_playerbeams[MAX_BEAMS]
Definition: tent.c:522
explosion_t::start
float start
Definition: client.h:78
CL_WidowSplash
void CL_WidowSplash(void)
Definition: newfx.c:582
cl_mod_explosions
qhandle_t cl_mod_explosions[4]
Definition: tent.c:51
CL_ParticleEffect2
void CL_ParticleEffect2(vec3_t org, vec3_t dir, int color, int count)
Definition: effects.c:1060
beam_t::entity
int entity
Definition: tent.c:513
light_curve_t
struct light_curve_s light_curve_t
light_curve_s::radius
float radius
Definition: tent.c:232
laser_t
Definition: tent.c:418
cl_sfx_footsteps
qhandle_t cl_sfx_footsteps[4]
Definition: tent.c:36
cparticle_s::org
vec3_t org
Definition: client.h:785
railspiral_color
static color_t railspiral_color
Definition: tent.c:896
CL_ClearTEnts
void CL_ClearTEnts(void)
Definition: tent.c:1459
origin
static vec3_t origin
Definition: mesh.c:27
cl_sustain_s::magnitude
int magnitude
Definition: client.h:751
AngleVectors
void AngleVectors(vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
Definition: shared.c:23
client_state_s::time
int time
Definition: client.h:244
CL_OLDKEYPS
#define CL_OLDKEYPS
Definition: client.h:166
CL_MonsterPlasma_Shell
void CL_MonsterPlasma_Shell(vec3_t origin)
Definition: newfx.c:493
explosion_t::ent
entity_t ent
Definition: client.h:74
NOPART_ROCKET_EXPLOSION
#define NOPART_ROCKET_EXPLOSION
Definition: client.h:497
laser_t::end
vec3_t end
Definition: tent.c:420
cl_mod_dmspot
qhandle_t cl_mod_dmspot
Definition: tent.c:50
CL_ParseLaser
static void CL_ParseLaser(int colors)
Definition: tent.c:487
cl_sustain_s::endtime
int endtime
Definition: client.h:744
cl_mod_bfg_explo
qhandle_t cl_mod_bfg_explo
Definition: tent.c:47
cl_railspiral_color_changed
static void cl_railspiral_color_changed(cvar_t *self)
Definition: tent.c:914
V_AddLight
#define V_AddLight(org, intensity, r, g, b)
Definition: client.h:728
CL_RailLights
static void CL_RailLights(color_t color)
Definition: tent.c:986
CL_ParseTEnt
void CL_ParseTEnt(void)
Definition: tent.c:1069
LENGTH
#define LENGTH(a)
Definition: tent.c:228
NOEXP_ROCKET
#define NOEXP_ROCKET
Definition: client.h:502
cl_mod_powerscreen
qhandle_t cl_mod_powerscreen
Definition: tent.c:48
cvar_pt_particle_emissive
cvar_t * cvar_pt_particle_emissive
Definition: effects.c:835
CL_BlasterParticles2
void CL_BlasterParticles2(vec3_t org, vec3_t dir, unsigned int color)
Definition: newfx.c:761
cl_railcore_color_changed
static void cl_railcore_color_changed(cvar_t *self)
Definition: tent.c:905
laser_t::color
int color
Definition: tent.c:421
cl_mod_smoke
qhandle_t cl_mod_smoke
Definition: tent.c:42
MAX_SUSTAINS
#define MAX_SUSTAINS
Definition: tent.c:799
CL_BloodParticleEffect
void CL_BloodParticleEffect(vec3_t org, vec3_t dir, int color, int count)
Definition: effects.c:1006
CL_RailCore
static void CL_RailCore(void)
Definition: tent.c:923
cl
client_state_t cl
Definition: main.c:99
server_frame_t::clientNum
int clientNum
Definition: client.h:138
dirtoangles
static void dirtoangles(vec3_t angles)
Definition: tent.c:1049
CL_ClearLasers
static void CL_ClearLasers(void)
Definition: tent.c:429
CL_SmokeAndFlash
void CL_SmokeAndFlash(vec3_t origin)
Definition: tent.c:207
c
statCounters_t c
Definition: main.c:30
cparticle_s::color
int color
Definition: client.h:788
CL_ParticleSteamEffect2
void CL_ParticleSteamEffect2(cl_sustain_t *self)
Definition: newfx.c:375
cl_railspiral_radius
static cvar_t * cl_railspiral_radius
Definition: tent.c:903
CL_Heatbeam
void CL_Heatbeam(vec3_t start, vec3_t end)
Definition: newfx.c:266
cl_mod_parasite_segment
qhandle_t cl_mod_parasite_segment
Definition: tent.c:44
V_AddLightEx
#define V_AddLightEx(org, intensity, r, g, b, radius)
Definition: client.h:729
cl_mod_laser
qhandle_t cl_mod_laser
Definition: tent.c:49
cl_mod_explode
qhandle_t cl_mod_explode
Definition: tent.c:41
CL_ClearBeams
static void CL_ClearBeams(void)
Definition: tent.c:524
client_state_s::v_right
vec3_t v_right
Definition: client.h:258
cl_mod_lightning
qhandle_t cl_mod_lightning
Definition: tent.c:53
CL_RailSpiral
static void CL_RailSpiral(void)
Definition: tent.c:939
up
static vec3_t up
Definition: p_view.c:27
cl_sustains
static cl_sustain_t cl_sustains[MAX_SUSTAINS]
Definition: tent.c:801
right
static vec3_t right
Definition: p_view.c:27
light_curve_s::color
vec3_t color
Definition: tent.c:231
CL_TeleportParticles
void CL_TeleportParticles(vec3_t org)
Definition: effects.c:1942
beam_t::offset
vec3_t offset
Definition: tent.c:517
CL_FRAMETIME
#define CL_FRAMETIME
Definition: client.h:161
cvar_pt_beam_lights
cvar_t * cvar_pt_beam_lights
Definition: transparency.c:97
laser_t::width
int width
Definition: tent.c:423
te
tent_params_t te
Definition: parse.c:655
CL_AddExplosionLight
static void CL_AddExplosionLight(explosion_t *ex, float phase)
Definition: tent.c:260
client.h
ex_blaster_light
static light_curve_t ex_blaster_light[]
Definition: tent.c:254
cl_mod_grapple_cable
qhandle_t cl_mod_grapple_cable
Definition: tent.c:45
CL_BFGExplosionParticles
void CL_BFGExplosionParticles(vec3_t org)
Definition: effects.c:1905
CL_ParticleEffectWaterSplash
void CL_ParticleEffectWaterSplash(vec3_t org, vec3_t dir, int color, int count)
Definition: effects.c:959
CL_InitTEnts
void CL_InitTEnts(void)
Definition: tent.c:1467
CL_BubbleTrail
void CL_BubbleTrail(vec3_t start, vec3_t end)
Definition: effects.c:1718
cl_sustain_s::color
int color
Definition: client.h:749
CL_RegisterTEntModels
void CL_RegisterTEntModels(void)
Definition: tent.c:100
CL_KEYPS
#define CL_KEYPS
Definition: client.h:165
color
static vec4_t color
Definition: mesh.c:33
cl_sfx_ric2
qhandle_t cl_sfx_ric2
Definition: tent.c:25
CL_ColorExplosionParticles
void CL_ColorExplosionParticles(vec3_t org, int color, int run)
Definition: newfx.c:690
splash_color
static const byte splash_color[]
Definition: tent.c:1067
cparticle_s::time
float time
Definition: client.h:783
vid_rtx
cvar_t * vid_rtx
Definition: refresh.c:30
tent_params_t::type
int type
Definition: client.h:660
explosion_t::frametime
int frametime
Definition: client.h:80
CL_BubbleTrail2
void CL_BubbleTrail2(vec3_t start, vec3_t end, int dist)
Definition: newfx.c:228
SCR_ParseColor
qboolean SCR_ParseColor(const char *s, color_t *color)
Definition: screen.c:215
cl_lasers
static laser_t cl_lasers[MAX_LASERS]
Definition: tent.c:427
light_curve_s
Definition: tent.c:230
cl_railtrail_time
static cvar_t * cl_railtrail_time
Definition: tent.c:899
int
CONST PIXELFORMATDESCRIPTOR int
Definition: wgl.c:26
CL_ProcessSustain
static void CL_ProcessSustain(void)
Definition: tent.c:821
S_StartSound
void S_StartSound(const vec3_t origin, int entnum, int entchannel, qhandle_t hSfx, float vol, float attenuation, float timeofs)
Definition: main.c:824
CL_RegisterTEntSounds
void CL_RegisterTEntSounds(void)
Definition: tent.c:64
cl_sfx_spark5
qhandle_t cl_sfx_spark5
Definition: tent.c:29
cl_sfx_spark6
qhandle_t cl_sfx_spark6
Definition: tent.c:30
CL_ParticleSteamEffect
void CL_ParticleSteamEffect(vec3_t org, vec3_t dir, int color, int count, int magnitude)
Definition: newfx.c:341
cparticle_s::alpha
float alpha
Definition: client.h:789
cl_beams
static beam_t cl_beams[MAX_BEAMS]
Definition: tent.c:521
cl_sfx_rockexp
qhandle_t cl_sfx_rockexp
Definition: tent.c:33
tent_params_t::count
int count
Definition: client.h:665
CL_ParticleEffect3
void CL_ParticleEffect3(vec3_t org, vec3_t dir, int color, int count)
Definition: newfx.c:989
tent_params_t::color
int color
Definition: client.h:666
cl_railspiral_color
static cvar_t * cl_railspiral_color
Definition: tent.c:902
cl_explosion_sprites
cvar_t * cl_explosion_sprites
Definition: main.c:56
explosion_t::frames
int frames
Definition: client.h:75
CL_BigTeleportParticles
void CL_BigTeleportParticles(vec3_t org)
Definition: effects.c:1256
beam_t::start
vec3_t start
Definition: tent.c:518
cl_railcore_width
static cvar_t * cl_railcore_width
Definition: tent.c:901
CL_AllocSustain
static cl_sustain_t * CL_AllocSustain(void)
Definition: tent.c:808
tent_params_t::pos2
vec3_t pos2
Definition: client.h:662
MAX_LASERS
#define MAX_LASERS
Definition: tent.c:416
VectorNormalize
vec_t VectorNormalize(vec3_t v)
Definition: shared.c:55
CL_AllocParticle
cparticle_t * CL_AllocParticle(void)
Definition: effects.c:856
CL_ParseSteam
static void CL_ParseSteam(void)
Definition: tent.c:836
beam_t::model
qhandle_t model
Definition: tent.c:515
cl_sustain_s::think
void(* think)(struct cl_sustain_s *self)
Definition: client.h:752
cl_mod_heatbeam
qhandle_t cl_mod_heatbeam
Definition: tent.c:54
explosion_t::light
float light
Definition: client.h:76
CL_AllocLaser
static laser_t * CL_AllocLaser(void)
Definition: tent.c:434
CL_AddExplosions
static void CL_AddExplosions(void)
Definition: tent.c:305