]> de.git.xonotic.org Git - xonotic/darkplaces.git/blob - cl_tent.c
1046cbc66337345d721392b9bfac6b4e2f2b7175
[xonotic/darkplaces.git] / cl_tent.c
1 /*
2 Copyright (C) 1996-1997 Id Software, Inc.
3
4 This program is free software; you can redistribute it and/or
5 modify it under the terms of the GNU General Public License
6 as published by the Free Software Foundation; either version 2
7 of the License, or (at your option) any later version.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
12
13 See the GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 */
20 // cl_tent.c -- client side temporary entities
21
22 #include "quakedef.h"
23
24 cvar_t r_glowinglightning = {"r_glowinglightning", "1", true};
25
26 int                     num_temp_entities;
27 entity_t        cl_temp_entities[MAX_TEMP_ENTITIES];
28 beam_t          cl_beams[MAX_BEAMS];
29
30 sfx_t                   *cl_sfx_wizhit;
31 sfx_t                   *cl_sfx_knighthit;
32 sfx_t                   *cl_sfx_tink1;
33 sfx_t                   *cl_sfx_ric1;
34 sfx_t                   *cl_sfx_ric2;
35 sfx_t                   *cl_sfx_ric3;
36 sfx_t                   *cl_sfx_r_exp3;
37
38 /*
39 =================
40 CL_ParseTEnt
41 =================
42 */
43 void CL_InitTEnts (void)
44 {
45         Cvar_RegisterVariable(&r_glowinglightning);
46         cl_sfx_wizhit = S_PrecacheSound ("wizard/hit.wav");
47         cl_sfx_knighthit = S_PrecacheSound ("hknight/hit.wav");
48         cl_sfx_tink1 = S_PrecacheSound ("weapons/tink1.wav");
49         cl_sfx_ric1 = S_PrecacheSound ("weapons/ric1.wav");
50         cl_sfx_ric2 = S_PrecacheSound ("weapons/ric2.wav");
51         cl_sfx_ric3 = S_PrecacheSound ("weapons/ric3.wav");
52         cl_sfx_r_exp3 = S_PrecacheSound ("weapons/r_exp3.wav");
53 }
54
55 /*
56 =================
57 CL_ParseBeam
58 =================
59 */
60 void CL_ParseBeam (model_t *m)
61 {
62         int             ent;
63         vec3_t  start, end;
64         beam_t  *b;
65         int             i;
66         
67         ent = MSG_ReadShort ();
68         MSG_ReadVector(start);
69         MSG_ReadVector(end);
70
71 // override any beam with the same entity
72         for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
73                 if (b->entity == ent)
74                 {
75                         b->entity = ent;
76                         b->model = m;
77                         b->endtime = cl.time + 0.2;
78                         VectorCopy (start, b->start);
79                         VectorCopy (end, b->end);
80                         return;
81                 }
82
83 // find a free beam
84         for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
85         {
86                 if (!b->model || b->endtime < cl.time)
87                 {
88                         b->entity = ent;
89                         b->model = m;
90                         b->endtime = cl.time + 0.2;
91                         VectorCopy (start, b->start);
92                         VectorCopy (end, b->end);
93                         return;
94                 }
95         }
96         Con_Printf ("beam list overflow!\n");   
97 }
98
99 //void R_BlastParticles(vec3_t org, vec_t radius, vec_t power);
100 void R_BloodShower (vec3_t mins, vec3_t maxs, float velspeed, int count);
101 void R_ParticleCube (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorbase, int gravity, int randomvel);
102 void R_ParticleRain (vec3_t mins, vec3_t maxs, vec3_t dir, int count, int colorbase, int type);
103
104 // attempts to find the nearest non-solid location, used for explosions mainly
105 void FindNonSolidLocation(vec3_t pos)
106 {
107         if (SV_HullPointContents (cl.worldmodel->hulls, 0, pos) != CONTENTS_SOLID) return;
108         pos[0]-=1;if (SV_HullPointContents (cl.worldmodel->hulls, 0, pos) != CONTENTS_SOLID) return;
109         pos[0]+=2;if (SV_HullPointContents (cl.worldmodel->hulls, 0, pos) != CONTENTS_SOLID) return;
110         pos[0]-=1;
111         pos[1]-=1;if (SV_HullPointContents (cl.worldmodel->hulls, 0, pos) != CONTENTS_SOLID) return;
112         pos[1]+=2;if (SV_HullPointContents (cl.worldmodel->hulls, 0, pos) != CONTENTS_SOLID) return;
113         pos[1]-=1;
114         pos[2]-=1;if (SV_HullPointContents (cl.worldmodel->hulls, 0, pos) != CONTENTS_SOLID) return;
115         pos[2]+=2;if (SV_HullPointContents (cl.worldmodel->hulls, 0, pos) != CONTENTS_SOLID) return;
116         pos[2]-=1;
117 }
118
119 /*
120 =================
121 CL_ParseTEnt
122 =================
123 */
124 void CL_ParseTEnt (void)
125 {
126         int             type;
127         vec3_t  pos;
128         vec3_t  dir;
129         vec3_t  pos2;
130         dlight_t        *dl;
131         int             rnd;
132         int             colorStart, colorLength, count;
133         float   velspeed;
134         byte *tempcolor;
135
136         type = MSG_ReadByte ();
137         switch (type)
138         {
139         case TE_WIZSPIKE:                       // spike hitting wall
140                 MSG_ReadVector(pos);
141                 R_RunParticleEffect (pos, vec3_origin, 20, 30);
142                 S_StartSound (-1, 0, cl_sfx_wizhit, pos, 1, 1);
143                 break;
144                 
145         case TE_KNIGHTSPIKE:                    // spike hitting wall
146                 MSG_ReadVector(pos);
147                 R_RunParticleEffect (pos, vec3_origin, 226, 20);
148                 S_StartSound (-1, 0, cl_sfx_knighthit, pos, 1, 1);
149                 break;
150                 
151         case TE_SPIKE:                  // spike hitting wall
152                 MSG_ReadVector(pos);
153                 // LordHavoc: changed to spark shower
154                 R_SparkShower(pos, vec3_origin, 15);
155                 //R_RunParticleEffect (pos, vec3_origin, 0, 10);
156                 if ( rand() % 5 )
157                         S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
158                 else
159                 {
160                         rnd = rand() & 3;
161                         if (rnd == 1)
162                                 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
163                         else if (rnd == 2)
164                                 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
165                         else
166                                 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
167                 }
168                 break;
169         case TE_SPIKEQUAD:                      // quad spike hitting wall
170                 MSG_ReadVector(pos);
171                 // LordHavoc: changed to spark shower
172                 R_SparkShower(pos, vec3_origin, 15);
173                 //R_RunParticleEffect (pos, vec3_origin, 0, 10);
174                 dl = CL_AllocDlight (0);
175                 VectorCopy (pos, dl->origin);
176                 dl->radius = 200;
177                 dl->die = cl.time + 0.2;
178                 dl->decay = 1000;
179                 dl->color[0] = 0.05;dl->color[1] = 0.05;dl->color[2] = 0.8;
180                 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
181                 if ( rand() % 5 )
182                         S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
183                 else
184                 {
185                         rnd = rand() & 3;
186                         if (rnd == 1)
187                                 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
188                         else if (rnd == 2)
189                                 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
190                         else
191                                 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
192                 }
193                 break;
194         case TE_SUPERSPIKE:                     // super spike hitting wall
195                 MSG_ReadVector(pos);
196                 // LordHavoc: changed to dust shower
197                 R_SparkShower(pos, vec3_origin, 30);
198                 //R_RunParticleEffect (pos, vec3_origin, 0, 20);
199                 if ( rand() % 5 )
200                         S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
201                 else
202                 {
203                         rnd = rand() & 3;
204                         if (rnd == 1)
205                                 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
206                         else if (rnd == 2)
207                                 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
208                         else
209                                 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
210                 }
211                 break;
212         case TE_SUPERSPIKEQUAD:                 // quad super spike hitting wall
213                 MSG_ReadVector(pos);
214                 // LordHavoc: changed to dust shower
215                 R_SparkShower(pos, vec3_origin, 30);
216                 //R_RunParticleEffect (pos, vec3_origin, 0, 20);
217                 dl = CL_AllocDlight (0);
218                 VectorCopy (pos, dl->origin);
219                 dl->radius = 200;
220                 dl->die = cl.time + 0.2;
221                 dl->decay = 1000;
222                 dl->color[0] = 0.05;dl->color[1] = 0.05;dl->color[2] = 0.8;
223                 if ( rand() % 5 )
224                         S_StartSound (-1, 0, cl_sfx_tink1, pos, 1, 1);
225                 else
226                 {
227                         rnd = rand() & 3;
228                         if (rnd == 1)
229                                 S_StartSound (-1, 0, cl_sfx_ric1, pos, 1, 1);
230                         else if (rnd == 2)
231                                 S_StartSound (-1, 0, cl_sfx_ric2, pos, 1, 1);
232                         else
233                                 S_StartSound (-1, 0, cl_sfx_ric3, pos, 1, 1);
234                 }
235                 break;
236                 // LordHavoc: added for improved blood splatters
237         case TE_BLOOD:  // blood puff
238                 MSG_ReadVector(pos);
239                 dir[0] = MSG_ReadChar ();
240                 dir[1] = MSG_ReadChar ();
241                 dir[2] = MSG_ReadChar ();
242                 count = MSG_ReadByte (); // amount of particles
243                 R_BloodPuff(pos, dir, count);
244                 break;
245         case TE_BLOOD2: // blood puff
246                 MSG_ReadVector(pos);
247                 R_BloodPuff(pos, vec3_origin, 10);
248                 break;
249         case TE_SPARK:  // spark shower
250                 MSG_ReadVector(pos);
251                 dir[0] = MSG_ReadChar ();
252                 dir[1] = MSG_ReadChar ();
253                 dir[2] = MSG_ReadChar ();
254                 count = MSG_ReadByte (); // amount of particles
255                 R_SparkShower(pos, dir, count);
256                 break;
257                 // LordHavoc: added for improved gore
258         case TE_BLOODSHOWER:    // vaporized body
259                 MSG_ReadVector(pos); // mins
260                 MSG_ReadVector(pos2); // maxs
261                 velspeed = MSG_ReadCoord (); // speed
262                 count = MSG_ReadShort (); // number of particles
263                 R_BloodShower(pos, pos2, velspeed, count);
264                 break;
265         case TE_PARTICLECUBE:   // general purpose particle effect
266                 MSG_ReadVector(pos); // mins
267                 MSG_ReadVector(pos2); // maxs
268                 MSG_ReadVector(dir); // dir
269                 count = MSG_ReadShort (); // number of particles
270                 colorStart = MSG_ReadByte (); // color
271                 colorLength = MSG_ReadByte (); // gravity (1 or 0)
272                 velspeed = MSG_ReadCoord (); // randomvel
273                 R_ParticleCube(pos, pos2, dir, count, colorStart, colorLength, velspeed);
274                 break;
275
276         case TE_PARTICLERAIN:   // general purpose particle effect
277                 MSG_ReadVector(pos); // mins
278                 MSG_ReadVector(pos2); // maxs
279                 MSG_ReadVector(dir); // dir
280                 count = MSG_ReadShort (); // number of particles
281                 colorStart = MSG_ReadByte (); // color
282                 R_ParticleRain(pos, pos2, dir, count, colorStart, 0);
283                 break;
284
285         case TE_PARTICLESNOW:   // general purpose particle effect
286                 MSG_ReadVector(pos); // mins
287                 MSG_ReadVector(pos2); // maxs
288                 MSG_ReadVector(dir); // dir
289                 count = MSG_ReadShort (); // number of particles
290                 colorStart = MSG_ReadByte (); // color
291                 R_ParticleRain(pos, pos2, dir, count, colorStart, 1);
292                 break;
293
294         case TE_GUNSHOT:                        // bullet hitting wall
295                 MSG_ReadVector(pos);
296                 // LordHavoc: changed to dust shower
297                 R_SparkShower(pos, vec3_origin, 15);
298                 //R_RunParticleEffect (pos, vec3_origin, 0, 20);
299                 break;
300
301         case TE_GUNSHOTQUAD:                    // quad bullet hitting wall
302                 MSG_ReadVector(pos);
303                 R_SparkShower(pos, vec3_origin, 15);
304                 dl = CL_AllocDlight (0);
305                 VectorCopy (pos, dl->origin);
306                 dl->radius = 200;
307                 dl->die = cl.time + 0.2;
308                 dl->decay = 1000;
309                 dl->color[0] = 0.05;dl->color[1] = 0.05;dl->color[2] = 0.8;
310                 break;
311
312         case TE_EXPLOSION:                      // rocket explosion
313                 MSG_ReadVector(pos);
314                 FindNonSolidLocation(pos);
315                 R_ParticleExplosion (pos, false);
316 //              R_BlastParticles (pos, 120, 120);
317                 dl = CL_AllocDlight (0);
318                 VectorCopy (pos, dl->origin);
319                 dl->radius = 350;
320                 dl->die = cl.time + 0.5;
321                 dl->decay = 700;
322                 dl->color[0] = 1.0;dl->color[1] = 0.8;dl->color[2] = 0.4;
323                 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
324                 break;
325
326         case TE_EXPLOSIONQUAD:                  // quad rocket explosion
327                 MSG_ReadVector(pos);
328                 FindNonSolidLocation(pos);
329                 R_ParticleExplosion (pos, false);
330 //              R_BlastParticles (pos, 120, 480);
331                 dl = CL_AllocDlight (0);
332                 VectorCopy (pos, dl->origin);
333                 dl->radius = 600;
334                 dl->die = cl.time + 0.5;
335                 dl->decay = 1200;
336                 dl->color[0] = 0.5;dl->color[1] = 0.4;dl->color[2] = 1.0;
337                 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
338                 break;
339
340                 /*
341         case TE_SMOKEEXPLOSION:                 // rocket explosion with a cloud of smoke
342                 MSG_ReadVector(pos);
343                 FindNonSolidLocation(pos);
344                 R_ParticleExplosion (pos, true);
345                 dl = CL_AllocDlight (0);
346                 VectorCopy (pos, dl->origin);
347                 dl->radius = 350;
348                 dl->die = cl.time + 0.5;
349                 dl->decay = 300;
350                 dl->color[0] = 1.0;dl->color[1] = 0.8;dl->color[2] = 0.4;
351                 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
352                 break;
353                 */
354
355         case TE_EXPLOSION3:                             // Nehahra movie colored lighting explosion
356                 MSG_ReadVector(pos);
357                 FindNonSolidLocation(pos);
358                 R_ParticleExplosion (pos, false);
359 //              R_BlastParticles (pos, 120, 120);
360                 dl = CL_AllocDlight (0);
361                 VectorCopy (pos, dl->origin);
362                 dl->radius = 350;
363                 dl->die = cl.time + 0.5;
364                 dl->decay = 700;
365                 dl->color[0] = MSG_ReadCoord();dl->color[1] = MSG_ReadCoord();dl->color[2] = MSG_ReadCoord();
366                 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
367                 break;
368
369         case TE_EXPLOSIONRGB:                   // colored lighting explosion
370                 MSG_ReadVector(pos);
371                 FindNonSolidLocation(pos);
372                 R_ParticleExplosion (pos, false);
373 //              R_BlastParticles (pos, 120, 120);
374                 dl = CL_AllocDlight (0);
375                 VectorCopy (pos, dl->origin);
376                 dl->radius = 350;
377                 dl->die = cl.time + 0.5;
378                 dl->decay = 700;
379                 dl->color[0] = MSG_ReadByte() * (1.0 / 255.0);dl->color[1] = MSG_ReadByte() * (1.0 / 255.0);dl->color[2] = MSG_ReadByte() * (1.0 / 255.0);
380                 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
381                 break;
382
383         case TE_TAREXPLOSION:                   // tarbaby explosion
384                 MSG_ReadVector(pos);
385                 FindNonSolidLocation(pos);
386                 R_BlobExplosion (pos);
387 //              R_BlastParticles (pos, 120, 120);
388
389                 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
390                 dl = CL_AllocDlight (0);
391                 VectorCopy (pos, dl->origin);
392                 dl->radius = 600;
393                 dl->die = cl.time + 0.5;
394                 dl->decay = 1200;
395                 dl->color[0] = 0.8;dl->color[1] = 0.4;dl->color[2] = 1.0;
396                 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
397                 break;
398
399         case TE_SMALLFLASH:
400                 MSG_ReadVector(pos);
401                 FindNonSolidLocation(pos);
402                 dl = CL_AllocDlight (0);
403                 VectorCopy (pos, dl->origin);
404                 dl->radius = 200;
405                 dl->die = cl.time + 0.2;
406                 dl->decay = 1000;
407                 dl->color[0] = dl->color[1] = dl->color[2] = 1;
408                 break;
409
410         case TE_CUSTOMFLASH:
411                 MSG_ReadVector(pos);
412                 FindNonSolidLocation(pos);
413                 dl = CL_AllocDlight (0);
414                 VectorCopy (pos, dl->origin);
415                 dl->radius = MSG_ReadByte() * 8;
416                 velspeed = (MSG_ReadByte() + 1) * (1.0 / 256.0);
417                 dl->die = cl.time + velspeed;
418                 dl->decay = dl->radius / velspeed;
419                 dl->color[0] = MSG_ReadByte() * (1.0 / 255.0);dl->color[1] = MSG_ReadByte() * (1.0 / 255.0);dl->color[2] = MSG_ReadByte() * (1.0 / 255.0);
420                 break;
421
422         case TE_FLAMEJET:
423                 MSG_ReadVector(pos);
424                 MSG_ReadVector(dir);
425                 count = MSG_ReadByte();
426                 R_Flames(pos, dir, count);
427                 break;
428
429         case TE_LIGHTNING1:                             // lightning bolts
430                 CL_ParseBeam (Mod_ForName("progs/bolt.mdl", true));
431                 break;
432         
433         case TE_LIGHTNING2:                             // lightning bolts
434                 CL_ParseBeam (Mod_ForName("progs/bolt2.mdl", true));
435                 break;
436         
437         case TE_LIGHTNING3:                             // lightning bolts
438                 CL_ParseBeam (Mod_ForName("progs/bolt3.mdl", true));
439                 break;
440
441 // PGM 01/21/97 
442         case TE_BEAM:                           // grappling hook beam
443                 CL_ParseBeam (Mod_ForName("progs/beam.mdl", true));
444                 break;
445 // PGM 01/21/97
446
447 // LordHavoc: for compatibility with the Nehahra movie...
448         case TE_LIGHTNING4NEH:
449                 CL_ParseBeam (Mod_ForName(MSG_ReadString(), true));
450                 break;
451
452         case TE_LAVASPLASH:     
453                 pos[0] = MSG_ReadCoord ();
454                 pos[1] = MSG_ReadCoord ();
455                 pos[2] = MSG_ReadCoord ();
456                 R_LavaSplash (pos);
457                 break;
458         
459         case TE_TELEPORT:
460                 pos[0] = MSG_ReadCoord ();
461                 pos[1] = MSG_ReadCoord ();
462                 pos[2] = MSG_ReadCoord ();
463                 R_TeleportSplash (pos);
464                 break;
465                 
466         case TE_EXPLOSION2:                             // color mapped explosion
467                 MSG_ReadVector(pos);
468                 FindNonSolidLocation(pos);
469                 colorStart = MSG_ReadByte ();
470                 colorLength = MSG_ReadByte ();
471                 R_ParticleExplosion2 (pos, colorStart, colorLength);
472 //              R_BlastParticles (pos, 80, 80);
473                 dl = CL_AllocDlight (0);
474                 VectorCopy (pos, dl->origin);
475                 dl->radius = 350;
476                 dl->die = cl.time + 0.5;
477                 dl->decay = 700;
478                 tempcolor = (byte *)&d_8to24table[(rand()%colorLength) + colorStart];
479                 dl->color[0] = tempcolor[0] * (1.0f / 255.0f);dl->color[1] = tempcolor[1] * (1.0f / 255.0f);dl->color[2] = tempcolor[2] * (1.0f / 255.0f);
480                 S_StartSound (-1, 0, cl_sfx_r_exp3, pos, 1, 1);
481                 break;
482                 
483         default:
484                 Host_Error ("CL_ParseTEnt: bad type %d", type);
485         }
486 }
487
488
489 /*
490 =================
491 CL_NewTempEntity
492 =================
493 */
494 entity_t *CL_NewTempEntity (void)
495 {
496         entity_t        *ent;
497
498         if (cl_numvisedicts >= MAX_VISEDICTS)
499                 return NULL;
500         if (num_temp_entities >= MAX_TEMP_ENTITIES)
501                 return NULL;
502         ent = &cl_temp_entities[num_temp_entities++];
503         memset (ent, 0, sizeof(*ent));
504         cl_visedicts[cl_numvisedicts++] = ent;
505
506         ent->colormap = -1; // no special coloring
507         ent->scale = 1;
508         ent->alpha = 1;
509         ent->colormod[0] = ent->colormod[1] = ent->colormod[2] = 1;
510         return ent;
511 }
512
513
514 /*
515 =================
516 CL_UpdateTEnts
517 =================
518 */
519 void CL_UpdateTEnts (void)
520 {
521         int                     i;
522         beam_t          *b;
523         vec3_t          dist, org;
524         float           d;
525         entity_t        *ent;
526         float           yaw, pitch;
527         float           forward;
528         dlight_t        *dl;
529
530         num_temp_entities = 0;
531
532 // update lightning
533         for (i=0, b=cl_beams ; i< MAX_BEAMS ; i++, b++)
534         {
535                 if (!b->model || b->endtime < cl.time)
536                         continue;
537
538         // if coming from the player, update the start position
539                 if (b->entity == cl.viewentity)
540                 {
541                         VectorCopy (cl_entities[cl.viewentity].origin, b->start);
542                 }
543
544         // calculate pitch and yaw
545                 VectorSubtract (b->end, b->start, dist);
546
547                 if (dist[1] == 0 && dist[0] == 0)
548                 {
549                         yaw = 0;
550                         if (dist[2] > 0)
551                                 pitch = 90;
552                         else
553                                 pitch = 270;
554                 }
555                 else
556                 {
557                         yaw = (int) (atan2(dist[1], dist[0]) * 180 / M_PI);
558                         if (yaw < 0)
559                                 yaw += 360;
560         
561                         forward = sqrt (dist[0]*dist[0] + dist[1]*dist[1]);
562                         pitch = (int) (atan2(dist[2], forward) * 180 / M_PI);
563                         if (pitch < 0)
564                                 pitch += 360;
565                 }
566
567         // add new entities for the lightning
568                 VectorCopy (b->start, org);
569                 d = VectorNormalizeLength(dist);
570                 while (d > 0)
571                 {
572                         ent = CL_NewTempEntity ();
573                         if (!ent)
574                                 return;
575                         VectorCopy (org, ent->origin);
576                         ent->model = b->model;
577                         ent->effects = EF_FULLBRIGHT;
578                         ent->angles[0] = pitch;
579                         ent->angles[1] = yaw;
580                         ent->angles[2] = rand()%360;
581
582                         if (r_glowinglightning.value)
583                         {
584                                 dl = CL_AllocDlight (0);
585                                 VectorCopy (ent->origin,  dl->origin);
586                                 dl->radius = 100 + (rand()&31);
587                                 dl->die = cl.time + 0.001;
588                                 dl->color[0] = dl->color[1] = dl->color[2] = r_glowinglightning.value * 0.25f;
589                         }
590
591                         VectorMA(org, 30, dist, org);
592                         d -= 30;
593                 }
594         }
595         
596 }
597
598