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 
21 #include "quakedef.h"
22 #include "r_local.h"
23 #include "te_scripts.h"
24 
25 #define MAX_PARTICLES			2048	// default max # of particles at one
26 										//  time
27 #define MAX_EMITTERS			256		// maximum number of particle emitters
28 #define ABSOLUTE_MIN_PARTICLES	512		// no fewer than this no matter what's
29 										//  on the command line
30 
31 typedef struct particleemitter_s {
32 	ParticleEffect_t *effect; //what to spawn?
33 	float die;				  //when to die?
34 	float tick;				  //time between spawns
35 	float nexttick;			  //time of next tick
36 	int	count;				  //how many to spawn on tick
37 	vec3_t	origin;			  //where to spawn
38 	vec3_t	vel;			  //velocity to base on
39 	struct particleemitter_s* next;
40 } ParticleEmitter_t;
41 
42 int		ramp1[8] = {0x6f, 0x6d, 0x6b, 0x69, 0x67, 0x65, 0x63, 0x61};
43 int		ramp2[8] = {0x6f, 0x6e, 0x6d, 0x6c, 0x6b, 0x6a, 0x68, 0x66};
44 int		ramp3[8] = {0x6d, 0x6b, 6, 5, 4, 3};
45 
46 particle_t	*active_particles, *free_particles;
47 
48 particle_t	*particles;
49 int			r_numparticles;
50 
51 ParticleEmitter_t *emitters, *active_emitters, *free_emitters;
52 ParticleEffect_t *particleEffects;
53 
54 vec3_t			r_pright, r_pup, r_ppn;
55 
56 // <AWE> missing prototypes
57 extern qboolean SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace);
58 
59 
60 ParticleEffect_t *ParticleEffectDefinedForName(const char *name);
61 ParticleEffect_t *ParticleEffectForName(const char *name);
62 
63 //fill an effect with default values
DefaultEffect(ParticleEffect_t * eff)64 void DefaultEffect(ParticleEffect_t *eff) {
65 
66 	int i;
67 
68 	strcpy(eff->name,"noname");
69 	for (i=0; i<3; i++) {
70 		eff->emmiterParams1[i] = -16;
71 		eff->emmiterParams2[i] = 16;
72 		eff->endcolormax[i] = 1;
73 		eff->endcolormin[i] = 1;
74 		eff->startcolormax[i] = 1;
75 		eff->startcolormin[i] = 1;
76 		eff->gravity[i] = 0;
77 		eff->velocitymax[i] = 0;
78 		eff->velocitymin[i] = 0;
79 		eff->drag[i] = 1;
80 	}
81 
82 	eff->emmiterType = emt_box; //currently only box is supported
83 	eff->lifemin = 1;
84 	eff->lifemax = 1;
85 	eff->rotmin = 0;
86 	eff->rotmax = 0;
87 	eff->growmin = 0;
88 	eff->growmax = 0;
89 	eff->sizemin = 10;
90 	eff->sizemax = 10;
91 	eff->srcblend = GL_ONE;
92 	eff->dstblend = GL_ONE;
93 	eff->numbounces = 1;
94 	eff->texture = 0;
95 	eff->align = align_view;
96 	eff->next = 0;
97 	eff->velscale = 1/64;
98 	eff->spawn = NULL;
99 }
100 /*
101 =====================
102 R_InitParticleEffects
103 
104   Parse the particle effects out of the script file
105 =====================
106 */
R_AddEffectsScript(const char * filename)107 void R_AddEffectsScript(const char *filename) {
108 
109 	FILE *fin;
110     int token, var, i;
111     ParticleEffect_t *effect;
112 	char *buffer;
113 	//char	newname[256];
114 	char* str;
115 
116 	buffer = COM_LoadTempFile (filename);
117 
118 	if (!buffer) {
119 		Con_Printf("\002Can't load particle effects from: %s\n",filename);
120 		return;
121 	}
122 
123 	SC_Start(buffer,strlen(buffer));
124 
125 	Con_Printf("Loading particle effects from: %s\n",filename);
126 
127     while ( (token = SC_ParseToken()) != TOK_FILE_END) {
128 
129 		if (token == TOK_PARTICLE) {
130     		str = SC_ParseIdent();
131 
132 			//if it already exists just overwrite the old one...
133 			effect = ParticleEffectDefinedForName(str);
134 			if (!effect) {
135 				effect = (ParticleEffect_t *)Hunk_Alloc(sizeof(ParticleEffect_t));
136   				DefaultEffect(effect);
137 				effect->next = particleEffects;
138 				particleEffects = effect;
139 				strcpy(effect->name,str);
140 				//Con_Printf("effect %s\n",effect->name);
141 			} else {
142 				//Con_Printf("redifinition %s\n",effect->name);
143 			}
144 
145     		if (SC_ParseToken() != '{') PARSERERROR("'{' expected");
146 
147   			while ((var = SC_ParseToken()) != '}' && (var != TOK_FILE_END) ) {
148   				switch (var) {
149 					case TOK_EMITTER:
150 						//parse emmiter shape
151 						str = SC_ParseIdent();
152 
153 						if (!strcmp(str,"box")) {
154 							effect->emmiterType = emt_box;
155 						} else {
156 							PARSERERROR("Unknown emmiter shape");
157 						}
158 
159 						//parse emmiter values
160 						for (i=0; i<3; i++)
161 							effect->emmiterParams1[i] = SC_ParseFloat();
162 
163 						for (i=0; i<3; i++)
164 							effect->emmiterParams2[i] = SC_ParseFloat();
165 					break;
166 					case TOK_VELOCITY:
167 						//parse velocity mins maxs
168 						for (i=0; i<3; i++)
169 							effect->velocitymin[i] = SC_ParseFloat();
170 						for (i=0; i<3; i++)
171 							effect->velocitymax[i] = SC_ParseFloat();
172 					break;
173 					case TOK_STARTCOLOR:
174 						//parse color mins maxs
175 						for (i=0; i<3; i++)
176 							effect->startcolormin[i] = SC_ParseFloat();
177 						for (i=0; i<3; i++)
178 							effect->startcolormax[i] = SC_ParseFloat();
179 					break;
180 					case TOK_ENDCOLOR:
181 						//parse color mins maxs
182 						for (i=0; i<3; i++)
183 							effect->endcolormin[i] = SC_ParseFloat();
184 						for (i=0; i<3; i++)
185 							effect->endcolormax[i] = SC_ParseFloat();
186 					break;
187 					case TOK_LIFETIME:
188 						//parse lifetime mins maxs
189 						effect->lifemin = SC_ParseFloat();
190 						effect->lifemax = SC_ParseFloat();
191 					break;
192 					case TOK_FLAGS:
193 						str = SC_ParseIdent();
194 					break;
195 					case TOK_GRAVITY:
196 						for (i=0; i<3; i++)
197 							effect->gravity[i] = SC_ParseFloat();
198 					break;
199 					case TOK_ROTATION:
200 						effect->rotmin = SC_ParseFloat();
201 						effect->rotmax = SC_ParseFloat();
202 					break;
203 					case TOK_GROW:
204 						effect->growmin = SC_ParseFloat();
205 						effect->growmax = SC_ParseFloat();
206 					break;
207 					case TOK_SIZE:
208 						effect->sizemin = SC_ParseFloat();
209 						effect->sizemax = SC_ParseFloat();
210 					break;
211 					case TOK_DRAG:
212 						for (i=0; i<3; i++)
213 							effect->drag[i] = SC_ParseFloat();
214 					break;
215 					case TOK_BLENDFUNC:
216 						effect->srcblend = SC_BlendModeForName(SC_ParseIdent());
217 						effect->dstblend = SC_BlendModeForName(SC_ParseIdent());
218 					break;
219 					case TOK_BOUNCES:
220 						effect->numbounces = (int)SC_ParseFloat();
221 					break;
222 					case TOK_MAP:
223 						effect->texture = EasyTgaLoad(SC_ParseString());
224 						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
225 						glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
226 					break;
227 					case TOK_ORIENTATION:
228 						str = SC_ParseIdent();
229 						if (!strcmp(str,"view")) {
230 							effect->align = align_view;
231 						} else if (!strcmp(str,"vel")) {
232 							//Con_Printf("Velocity aligned\n");
233 							effect->align = align_vel;
234 							effect->velscale = SC_ParseFloat();
235 						} else if (!strcmp(str,"surface")) {
236 							//Con_Printf("Velocity aligned\n");
237 							effect->align = align_surf;
238 						} else {
239 							Con_Printf("\002Script error at line %i: Unknown orientation type %s\n",line_num,str);
240 						}
241 					break;
242 					case TOK_ONHIT:
243 						str = SC_ParseIdent();
244 						effect->spawn = ParticleEffectForName(str);
245 						if (!effect->spawn)
246 							printf("\002Script error at line %i: Particle %s not defined yet \n",line_num,str);
247 					break;
248 					default:
249 						Con_Printf("\002Script error at line %i: Unknown field (id%i/%s) for particle definition\n",line_num,var,str);
250 				}
251   			}
252 		} else if (token == TOK_DECAL) {
253   			while ((var = yylex()) != '}') {
254 			//do nothing yet...
255   			}
256 		} else {
257 			Con_Printf("\002Script error at line %i: Expected definiton (found id%i/%s)\n",line_num,var,str);
258 		}
259     }
260 
261 	SC_End();
262 }
263 
R_InitParticleEffects()264 void R_InitParticleEffects() {
265 	//clear list
266 	particleEffects = NULL;
267 	//load all scripts
268 	COM_FindAllExt("particles","particle",R_AddEffectsScript);
269 }
270 
ParticleEffectDefinedForName(const char * name)271 ParticleEffect_t *ParticleEffectDefinedForName(const char *name) {
272 
273 	ParticleEffect_t *current;
274 
275 	current = particleEffects;
276 
277 	while (current) {
278 		if (!strcmp(current->name,name)) {
279 			return current;
280 		}
281 		current = current->next;
282 	}
283 	return NULL;
284 }
285 
ParticleEffectForName(const char * name)286 ParticleEffect_t *ParticleEffectForName(const char *name) {
287 
288 	ParticleEffect_t *current;
289 
290 	current = ParticleEffectDefinedForName(name);
291 	if (!current) Con_Printf("Effect not defined: %s\n",name);
292 	return current;
293 }
294 
295 
RandomMinMax(float min,float max)296 float RandomMinMax(float min, float max) {
297 	return min+((rand()%10000)/10000.0)*(max-min);
298 }
299 
InitParticleFromEffect(ParticleEffect_t * effect,vec3_t org)300 particle_t *InitParticleFromEffect(ParticleEffect_t *effect, vec3_t org) {
301 
302 	particle_t *p;
303 	int i;
304 
305 	if (!effect) return NULL;
306 
307 	if (effect->align == align_surf) {
308 		//we can't spawn them here since we need extra information like the surface normal and such...
309 		return NULL;
310 	}
311 
312 	//allocate it
313 	if (!free_particles)
314 		return NULL;
315 	p = free_particles;
316 	free_particles = p->next;
317 	p->next = active_particles;
318 	active_particles = p;
319 
320 	//initialize the fields
321 	p->lifetime = RandomMinMax(effect->lifemin,effect->lifemax);
322 	p->die = cl.time + p->lifetime;
323 	for (i=0; i<3; i++) {
324 		p->vel[i] = RandomMinMax(effect->velocitymin[i],effect->velocitymax[i]);
325 		p->startcolor[i] = RandomMinMax(effect->startcolormin[i],effect->startcolormax[i]);
326 		p->endcolor[i] = RandomMinMax(effect->endcolormin[i],effect->endcolormax[i]);
327 		p->org[i] = RandomMinMax(effect->emmiterParams1[i],effect->emmiterParams2[i])+org[i];
328 	}
329 
330 	p->numbounces = effect->numbounces;
331 	p->srcblend = effect->srcblend;
332 	p->dstblend = effect->dstblend;
333 	p->rspeed = RandomMinMax(effect->rotmin,effect->rotmax);
334 	p->growspeed = RandomMinMax(effect->growmin,effect->growmax);
335 	p->size = RandomMinMax(effect->sizemin,effect->sizemax);
336 	if (effect->align == align_vel) {
337 		p->velaligned = true;
338 	} else {
339 		p->velaligned = false;
340 	}
341 	p->velscale = effect->velscale;
342 	p->texture = effect->texture;
343 	p->spawn = effect->spawn;
344 	VectorCopy(effect->gravity,p->gravity);
345 	VectorCopy(effect->drag,p->drag);
346 	return p;
347 }
348 
349 /*
350 ===============
351 R_InitParticles
352 ===============
353 */
R_InitParticles(void)354 void R_InitParticles (void)
355 {
356 	int		i;
357 
358 	i = COM_CheckParm ("-particles");
359 
360 	if (i)
361 	{
362 		r_numparticles = (int)(Q_atoi(com_argv[i+1]));
363 		if (r_numparticles < ABSOLUTE_MIN_PARTICLES)
364 			r_numparticles = ABSOLUTE_MIN_PARTICLES;
365 	}
366 	else
367 	{
368 		r_numparticles = MAX_PARTICLES;
369 	}
370 
371 	particles = (particle_t *)
372 			Hunk_AllocName (r_numparticles * sizeof(particle_t), "particles");
373 
374 	emitters = (ParticleEmitter_t *)
375 			Hunk_AllocName (MAX_EMITTERS * sizeof(ParticleEmitter_t), "emitters");
376 }
377 
378 /*
379 ===============
380 R_ParseBasicEmitter
381 
382 Parse an emitter out of the server message
383 Basic emitters don't actually spawn an emitter...
384 ===============
385 */
R_ParseBasicEmitter(void)386 void R_ParseBasicEmitter (void)
387 {
388 	vec3_t		org;
389 	int			i, count;
390 	char		*name;
391 	ParticleEffect_t *eff;
392 	particle_t		*p;
393 
394 	//Con_Printf("Particle effect!!\n");
395 	//origin to spawn on
396 	for (i=0 ; i<3 ; i++)
397 		org[i] = MSG_ReadCoord ();
398 
399 	//number of particles to spawn
400 	count = MSG_ReadByte ();
401 
402 	//name of effect to spawn
403 	name = MSG_ReadString();
404 
405 	eff = ParticleEffectForName(name);
406 	if (!eff) return;
407 
408 	for (i=0; i<count; i++) {
409 		p = InitParticleFromEffect(eff,org);
410 	}
411 }
412 
R_ParseExtendedEmitter(void)413 void R_ParseExtendedEmitter (void)
414 {
415 	vec3_t		org, vel;
416 	int			i, count;
417 	char		*name;
418 	ParticleEffect_t *eff;
419 	ParticleEmitter_t *emt;
420 	float		lifetime, tick;
421 
422 	//Con_Printf("Particle effect22!!\n");
423 	//origin to spawn on
424 	for (i=0 ; i<3 ; i++)
425 		org[i] = MSG_ReadCoord ();
426 
427 	//velocity to spawn on
428 	for (i=0 ; i<3 ; i++)
429 		vel[i] = MSG_ReadCoord ();
430 
431 	//number of particles to spawn
432 	count = MSG_ReadByte ();
433 
434 	//duration to live
435 	lifetime = MSG_ReadLong () / 100.0;
436 
437 	//animation time
438 	tick = MSG_ReadLong () / 100.0;
439 
440 	//name of effect to spawn
441 	name = MSG_ReadString();
442 
443 	eff = ParticleEffectForName(name);
444 	if (!eff) return;
445 
446 	//allocate it
447 	if (!free_emitters)
448 		return;
449 	emt = free_emitters;
450 	free_emitters = emt->next;
451 	emt->next = active_emitters;
452 	active_emitters = emt;
453 
454 	emt->effect = eff;
455 	VectorCopy(org,emt->origin);
456 	VectorCopy(vel,emt->vel);
457 	emt->die = cl.time+lifetime;
458 	emt->tick = tick;
459 	emt->count = count;
460 	emt->nexttick = 0;
461 }
462 
463 
464 
465 
466 
467 
468 
469 
470 /*
471 ===============
472 R_EntityParticles
473 ===============
474 */
475 
476 #define NUMVERTEXNORMALS	162
477 extern	float	r_avertexnormals[NUMVERTEXNORMALS][3];
478 vec3_t	avelocities[NUMVERTEXNORMALS];
479 float	beamlength = 16;
480 vec3_t	avelocity = {23, 7, 3};
481 float	partstep = 0.01;
482 float	timescale = 0.01;
483 
R_EntityParticles(entity_t * ent)484 void R_EntityParticles (entity_t *ent)
485 {
486 	int			count;
487 	int			i;
488 	particle_t	*p;
489 	float		angle;
490 	float		sr, sp, sy, cr, cp, cy;
491 	vec3_t		forward;
492 	float		dist;
493 	ParticleEffect_t *eff;
494 
495 	dist = 64;
496 	count = 50;
497 
498 if (!avelocities[0][0])
499 {
500 for (i=0 ; i<NUMVERTEXNORMALS*3 ; i++)
501 avelocities[0][i] = (rand()&255) * 0.01;
502 }
503 
504 
505 	eff = ParticleEffectForName("pt_entityparticles");
506 	if (!eff) return;
507 
508 	for (i=0 ; i<NUMVERTEXNORMALS ; i++)
509 	{
510 		angle = cl.time * avelocities[i][0];
511 		sy = sin(angle);
512 		cy = cos(angle);
513 		angle = cl.time * avelocities[i][1];
514 		sp = sin(angle);
515 		cp = cos(angle);
516 		angle = cl.time * avelocities[i][2];
517 		sr = sin(angle);
518 		cr = cos(angle);
519 
520 		forward[0] = cp*cy;
521 		forward[1] = cp*sy;
522 		forward[2] = -sp;
523 
524 		p = InitParticleFromEffect(eff,ent->origin);
525 		if (!p) return;
526 
527 		p->org[0] = ent->origin[0] + r_avertexnormals[i][0]*dist + forward[0]*beamlength;
528 		p->org[1] = ent->origin[1] + r_avertexnormals[i][1]*dist + forward[1]*beamlength;
529 		p->org[2] = ent->origin[2] + r_avertexnormals[i][2]*dist + forward[2]*beamlength;
530 	}
531 }
532 
533 
534 /*
535 ===============
536 R_ClearParticles
537 ===============
538 */
R_ClearParticles(void)539 void R_ClearParticles (void)
540 {
541 	int		i;
542 
543 	//remove all particles
544 	free_particles = &particles[0];
545 	active_particles = NULL;
546 
547 	for (i=0 ;i<r_numparticles ; i++)
548 		particles[i].next = &particles[i+1];
549 	particles[r_numparticles-1].next = NULL;
550 
551 	//remove all emitters
552 	free_emitters = &emitters[0];
553 	active_emitters = NULL;
554 
555 	for (i=0 ;i<MAX_EMITTERS ; i++)
556 		emitters[i].next = &emitters[i+1];
557 	emitters[MAX_EMITTERS-1].next = NULL;
558 }
559 
560 
R_ReadPointFile_f(void)561 void R_ReadPointFile_f (void)
562 {
563 	FILE	*f;
564 	vec3_t	org;
565 	int		r;
566 	int		c;
567 	particle_t	*p;
568 	char	name[MAX_OSPATH];
569 	ParticleEffect_t *eff;
570 
571 	sprintf (name,"maps/%s.pts", sv.name);
572 
573 	COM_FOpenFile (name, &f);
574 	if (!f)
575 	{
576 		Con_Printf ("couldn't open %s\n", name);
577 		return;
578 	}
579 
580 	eff = ParticleEffectForName("pt_pointfile");
581 	if (!eff) return;
582 
583 	Con_Printf ("Reading %s...\n", name);
584 	c = 0;
585 	for ( ;; )
586 	{
587 		r = fscanf (f,"%f %f %f\n", &org[0], &org[1], &org[2]);
588 		if (r != 3)
589 			break;
590 		c++;
591 
592 		p = InitParticleFromEffect(eff,org);
593 		if (!p) return;
594 		VectorCopy (vec3_origin, p->vel);
595 	}
596 
597 	fclose (f);
598 	Con_Printf ("%i points read\n", c);
599 }
600 
601 /*
602 ===============
603 R_ParseParticleEffect
604 
605 Parse an effect out of the server message
606 ===============
607 */
R_ParseParticleEffect(void)608 void R_ParseParticleEffect (void)
609 {
610 	vec3_t		org, dir;
611 	int			i, count, msgcount, color;
612 
613 	for (i=0 ; i<3 ; i++)
614 		org[i] = MSG_ReadCoord ();
615 	for (i=0 ; i<3 ; i++)
616 		dir[i] = MSG_ReadChar () * (1.0/16);
617 	msgcount = MSG_ReadByte ();
618 	color = MSG_ReadByte ();
619 
620 if (msgcount == 255)
621 	count = 1024;
622 else
623 	count = msgcount;
624 
625 	R_RunParticleEffect (org, dir, color, count);
626 }
627 
628 /*
629 ===============
630 R_ParticleGunHits
631 
632 PENTA: When a gun hits the wall
633 ===============
634 */
R_ParticleGunHits(vec3_t org,int type)635 void R_ParticleGunHits (vec3_t org, int type)
636 {
637 	int			i, j;
638 	particle_t	*p;
639 	ParticleEffect_t *eff;
640 /*
641 #define	TE_SPIKE			0
642 #define	TE_SUPERSPIKE		1
643 
644 #define	TE_EXPLOSION		3
645 #define	TE_TAREXPLOSION		4
646 #define	TE_LIGHTNING1		5
647 #define	TE_LIGHTNING2		6
648 #define	TE_WIZSPIKE			7
649 #define	TE_KNIGHTSPIKE		8
650 #define	TE_LIGHTNING3		9
651 #define	TE_LAVASPLASH		10
652 #define	TE_TELEPORT			11
653 #define TE_EXPLOSION2		12
654 */
655 	switch (type) {
656 
657 	//Shotgun hitting wall
658 	case TE_GUNSHOT:
659 
660 		eff = ParticleEffectForName("pt_gunshot");
661 		for (i=0; i<2; i++) {
662 			InitParticleFromEffect(eff,org);
663 		}
664 
665 		eff = ParticleEffectForName("pt_gunshotsmoke");
666 		for (i=0; i<1; i++) {
667 			InitParticleFromEffect(eff,org);
668 		}
669 		break;
670 	//Nails hitting wall
671 	case TE_SPIKE:
672 	case TE_SUPERSPIKE:
673 		for (i=0 ; i<6 ; i++)
674 		{
675 
676 			eff = ParticleEffectForName("pt_spike");
677 			for (i=0; i<6; i++) {
678 				InitParticleFromEffect(eff,org);
679 			}
680 		}
681 		break;
682 	//lightining hitting wall
683 	case TE_LIGHTNING1:
684 	case TE_LIGHTNING2:
685 	case TE_LIGHTNING3:
686 			eff = ParticleEffectForName("pt_lightning");
687 			for (i=0; i<6; i++) {
688 				InitParticleFromEffect(eff,org);
689 			}
690 		break;
691 	default:
692 		break;
693 	}
694 }
695 
696 /*
697 ===============
698 R_ParticleHitBlood
699 
700 PENTA: Changes
701 ===============
702 */
R_ParticleHitBlood(vec3_t org,int color)703 void R_ParticleHitBlood (vec3_t org, int color)
704 {
705 	int			i, j;
706 	particle_t	*p;
707 	ParticleEffect_t *eff;
708 
709 	//Con_Printf("blood\n");
710 
711 
712 	eff = ParticleEffectForName("pt_hitblood1");
713 	for (i=0 ; i<1 ; i++)
714 	{
715 		InitParticleFromEffect(eff,org);
716 	}
717 
718 	eff = ParticleEffectForName("pt_hitblood2");
719 	for (i=0 ; i<2 ; i++)
720 	{
721 		InitParticleFromEffect(eff,org);
722 	}
723 }
724 /*
725 ===============
726 R_ParticleExplosion
727 
728 PENTA: Changes
729 ===============
730 */
R_ParticleExplosion(vec3_t org)731 void R_ParticleExplosion (vec3_t org)
732 {
733 	int			i, j;
734 	particle_t	*p;
735 	ParticleEffect_t *eff;
736 
737 	eff = ParticleEffectForName("pt_explosion1");
738 	for (i=0 ; i<128 ; i++)
739 	{
740 		InitParticleFromEffect(eff,org);
741 	}
742 
743 	eff = ParticleEffectForName("pt_explosion2");
744 	for (i=0 ; i<128 ; i++)
745 	{
746 		InitParticleFromEffect(eff,org);
747 	}
748 }
749 
750 /*
751 ===============
752 R_ParticleExplosion2
753 
754 ===============
755 */
R_ParticleExplosion2(vec3_t org,int colorStart,int colorLength)756 void R_ParticleExplosion2 (vec3_t org, int colorStart, int colorLength)
757 {
758 	int			i, j;
759 	particle_t	*p;
760 	int			colorMod = 0;
761 	ParticleEffect_t *eff;
762 
763 	eff = ParticleEffectForName("pt_explosion1");
764 	for (i=0 ; i<64 ; i++)
765 	{
766 		InitParticleFromEffect(eff,org);
767 	}
768 
769 }
770 
771 /*
772 ===============
773 R_BlobExplosion
774 
775 ===============
776 */
R_BlobExplosion(vec3_t org)777 void R_BlobExplosion (vec3_t org)
778 {
779 	int			i, j;
780 	particle_t	*p;
781 	ParticleEffect_t *eff;
782 
783 	eff = ParticleEffectForName("pt_voreexplosion1");
784 	for (i=0 ; i<64 ; i++)
785 	{
786 		InitParticleFromEffect(eff,org);
787 	}
788 
789 	eff = ParticleEffectForName("pt_voreexplosion2");
790 	for (i=0 ; i<64 ; i++)
791 	{
792 		InitParticleFromEffect(eff,org);
793 	}
794 }
795 
796 /*
797 ===============
798 R_RunParticleEffect
799 
800 ===============
801 */
R_RunParticleEffect(vec3_t org,vec3_t dir,int color,int count)802 void R_RunParticleEffect (vec3_t org, vec3_t dir, int color, int count)
803 {
804 	int			i, j;
805 	particle_t	*p;
806 	ParticleEffect_t *eff;
807 
808 	if ((color == 225) || (color == 73)) {
809 		R_ParticleHitBlood (org, color);
810 		return;
811 	}
812 
813 	if (count == 1024) {
814 		R_ParticleExplosion(org);
815 	}
816 
817 	eff = ParticleEffectForName("pt_genericsmoke");
818 	for (i=0; i<count; i++) {
819 		InitParticleFromEffect(eff,org);
820 	}
821 }
822 
823 
824 /*
825 ===============
826 R_LavaSplash
827 
828 ===============
829 */
R_LavaSplash(vec3_t org)830 void R_LavaSplash (vec3_t org)
831 {
832 	int			i, j, k;
833 	particle_t	*p;
834 	float		vel;
835 	vec3_t		dir;
836 	ParticleEffect_t *eff;
837 
838 	eff = ParticleEffectForName("pt_lavasplash");
839 	for (i=-16 ; i<16 ; i++)
840 		for (j=-16 ; j<16 ; j++)
841 			for (k=0 ; k<1 ; k++)
842 			{
843 				p = InitParticleFromEffect(eff,org);
844 				if (!p) return;
845 
846 				dir[0] = j*8 + (rand()&7);
847 				dir[1] = i*8 + (rand()&7);
848 				dir[2] = 256;
849 
850 				p->org[0] = org[0] + dir[0];
851 				p->org[1] = org[1] + dir[1];
852 				p->org[2] = org[2] + (rand()&63);
853 
854 				VectorNormalize (dir);
855 				vel = 50 + (rand()&63);
856 				VectorScale (dir, vel, p->vel);
857 			}
858 }
859 
860 /*
861 ===============
862 R_TeleportSplash
863 
864 ===============
865 */
R_TeleportSplash(vec3_t org)866 void R_TeleportSplash (vec3_t org)
867 {
868 	int			i, j, k;
869 	particle_t	*p;
870 	float		vel;
871 	vec3_t		dir;
872 	ParticleEffect_t *eff;
873 
874 	eff = ParticleEffectForName("teleportsplash");
875 	for (i=-16 ; i<16 ; i+=4)
876 		for (j=-16 ; j<16 ; j+=4)
877 			for (k=-24 ; k<32 ; k+=4)
878 			{
879 				p = InitParticleFromEffect(eff,org);
880 				if (!p) return;
881 
882 				dir[0] = j*8;
883 				dir[1] = i*8;
884 				dir[2] = k*8;
885 
886 				p->org[0] = org[0] + i + (rand()&3);
887 				p->org[1] = org[1] + j + (rand()&3);
888 				p->org[2] = org[2] + k + (rand()&3);
889 
890 				VectorNormalize (dir);
891 				vel = 50 + (rand()&63);
892 				VectorScale (dir, vel, p->vel);
893 			}
894 }
895 
R_RocketTrail(vec3_t start,vec3_t end,int type)896 void R_RocketTrail (vec3_t start, vec3_t end, int type)
897 {
898 	vec3_t		vec;
899 	float		len;
900 	int			j;
901 	particle_t	*p;
902 	int			dec;
903 	static int	tracercount;
904 	ParticleEffect_t *eff;
905 
906 	VectorSubtract (end, start, vec);
907 	len = VectorNormalize (vec);
908 	if (type < 128)
909 
910 		if ((type == 6) || (type == 5))
911 			dec = 1;
912 		else
913 			dec = 10;
914 	else
915 	{
916 		Con_Printf("ypt\n");
917 		dec = 1;
918 		type -= 128;
919 	}
920 
921 
922 	switch (type)
923 	{
924 		case 0:	// rocket trail
925 			eff = ParticleEffectForName("pt_rockettrail");
926 			break;
927 		case 1:	// smoke smoke
928 			eff = ParticleEffectForName("pt_smoke");
929 			break;
930 		case 2:	// blood
931 			eff = ParticleEffectForName("pt_bloodtrail");
932 			break;
933 		case 4:	// slight blood
934 			eff = ParticleEffectForName("pt_bloodtrail");
935 			break;
936 		case 3:
937 			eff = ParticleEffectForName("pt_wizzardtrail");
938 			break;
939 		case 5:	// tracer
940 			eff = ParticleEffectForName("pt_hknighttrail");
941 			break;
942 		case 6:	// voor trail
943 			eff = ParticleEffectForName("pt_voretrail");
944 			break;
945 		default:
946 			eff = ParticleEffectForName("pt_genericsmoke");
947 			break;
948 		}
949 
950 
951 	while (len > 0)
952 	{
953 		len -= dec;
954 
955 		p = InitParticleFromEffect(eff,start);
956 		if (!p) return;
957 
958 		switch (type)
959 		{
960 			case 0:	// rocket trail
961 				for (j=0 ; j<3 ; j++)
962 					p->org[j] = start[j] + ((rand()%6)-3);
963 				break;
964 			case 1:	// smoke smoke
965 				for (j=0 ; j<3 ; j++)
966 					p->org[j] = start[j] + ((rand()%6)-3);
967 				break;
968 			case 2:	// blood
969 			case 4:	// slight blood
970 				for (j=0 ; j<3 ; j++)
971 					p->org[j] = start[j] + ((rand()%6)-3);
972 				break;
973 			case 6:	// voor trail
974 				for (j=0 ; j<3 ; j++) {
975 					p->org[j] = start[j] + ((rand()%8)-4);
976 				}
977 				break;
978 		}
979 
980 		VectorAdd (start, vec, start);
981 	}
982 }
983 
984 
985 /*
986 ===============
987 R_DrawParticles
988 ===============
989 
990 extern	cvar_t	sv_gravity;
991 
992 void R_DrawParticles (void)
993 {
994 	particle_t		*p, *kill;
995 	float			grav;
996 	int				i;
997 	float			time2, time3;
998 	float			time1;
999 	float			dvel;
1000 	float			frametime;
1001 
1002 #ifdef GLQUAKE
1003 	vec3_t			up, right, neworg;
1004 	float			scale, sscale;
1005 
1006 	glFogfv(GL_FOG_COLOR, color_black); //Done in actual function now (stops "triangle effect") - Eradicator
1007 	glEnable (GL_BLEND);
1008 	glBlendFunc (GL_ONE, GL_ONE);
1009 	glEnable(GL_ALPHA_TEST);
1010 	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1011 	glDepthMask(0);
1012 
1013 	VectorScale (vup, 1, up);
1014 	VectorScale (vright, 1, right);
1015 	glMatrixMode(GL_TEXTURE);
1016 #else
1017 	D_StartParticles ();
1018 
1019 	VectorScale (vright, xscaleshrink, r_pright);
1020 	VectorScale (vup, yscaleshrink, r_pup);
1021 	VectorCopy (vpn, r_ppn);
1022 #endif
1023 	frametime = cl.time - cl.oldtime;
1024 	time3 = frametime * 15;
1025 	time2 = frametime * 10; // 15;
1026 	time1 = frametime * 5;
1027 	grav = frametime * sv_gravity.value * 0.05;
1028 	dvel = 4*frametime;
1029 
1030 	for ( ;; )
1031 	{
1032 		kill = active_particles;
1033 		if (kill && kill->die < cl.time)
1034 		{
1035 			active_particles = kill->next;
1036 			kill->next = free_particles;
1037 			free_particles = kill;
1038 			continue;
1039 		}
1040 		break;
1041 	}
1042 
1043 	for (p=active_particles ; p ; p=p->next)
1044 	{
1045 		for ( ;; )
1046 		{
1047 			kill = p->next;
1048 			//XYZ
1049 			if (kill && ((kill->die < cl.time) || (kill->numbounces <= 0)))
1050 			{
1051 				p->next = kill->next;
1052 				kill->next = free_particles;
1053 				free_particles = kill;
1054 				continue;
1055 			}
1056 			break;
1057 		}
1058 
1059 #ifdef GLQUAKE
1060 		// hack a scale up to keep particles from disapearing
1061 
1062 		//scale = (p->org[0] - r_origin[0])*vpn[0] + (p->org[1] - r_origin[1])*vpn[1]
1063 		//	+ (p->org[2] - r_origin[2])*vpn[2];
1064 		//if (scale < 20)
1065 		//	scale = 1;
1066 		//else
1067 		//	scale = 1 + scale * 0.004;
1068 		//
1069 		scale = 10;
1070 
1071 		if ((p->die - cl.time) < 0.5) {
1072 			byte *c = (byte *)&d_8to24table[(int)p->color];
1073 			float scale = 2*(p->die - cl.time);
1074 			glColor3ub((byte)(c[0]*scale), (byte)(c[1]*scale), (byte)(c[2]*scale));
1075 		} else {
1076 			glColor3ubv ((byte *)&d_8to24table[(int)p->color]);
1077 		}
1078 
1079 		GL_Bind(p->texture);
1080 
1081 		if ((p->texture ==  particletexture_smoke) ||
1082 		   (p->texture ==  particletexture_blood) ) scale = 50;
1083 
1084 		if (p->blendfunc == pb_add) {
1085 			glBlendFunc (GL_ONE, GL_ONE);
1086 		} else {
1087 			glBlendFunc (GL_ZERO, GL_ONE_MINUS_SRC_COLOR);
1088 		}
1089 		//XYZ
1090 		if ((p->texture ==  particletexture_glow) ||
1091 		    (p->texture ==  particletexture_dirblood)){
1092 			float lscale;
1093 			VectorCopy (p->vel, up);
1094 			VectorNormalize(up);
1095 			CrossProduct(vpn,up,right);
1096 			lscale = (Length(p->vel)/64);
1097 			VectorScale(up,lscale,up);
1098 		} else {
1099 			VectorCopy (vup, up);
1100 			VectorCopy (vright, right);
1101 		}
1102 
1103 		glLoadIdentity();
1104 		glTranslatef(0.5,0.5,0);
1105 		glRotatef(p->rot,0,0,1);
1106 		glTranslatef(-0.5,-0.5,0);
1107 
1108 		glBegin(GL_TRIANGLES);
1109 		glTexCoord2f (0,0);
1110 
1111 		sscale = -scale/4;
1112 		VectorMA(p->org,sscale,up,neworg);
1113 		VectorMA(neworg,sscale,right,neworg);
1114 
1115 		glVertex3fv (neworg);
1116 		glTexCoord2f (2,0);
1117 		glVertex3f (neworg[0] + up[0]*scale, neworg[1] + up[1]*scale, neworg[2] + up[2]*scale);
1118 		glTexCoord2f (0,2);
1119 		glVertex3f (neworg[0] + right[0]*scale, neworg[1] + right[1]*scale, neworg[2] + right[2]*scale);
1120 		glEnd();
1121 #else
1122 		D_DrawParticle (p);
1123 #endif
1124 
1125 		neworg[0] = p->org[0]+p->vel[0]*frametime;
1126 		neworg[1] = p->org[1]+p->vel[1]*frametime;
1127 		neworg[2] = p->org[2]+p->vel[2]*frametime;
1128 		p->rot = p->rot+p->rspeed*frametime;
1129 
1130 		{
1131 			trace_t	trace;
1132 			float	d;
1133 
1134 			memset (&trace, 0, sizeof(trace));
1135 			trace.fraction = 1;
1136 			SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, p->org, neworg, &trace);
1137 
1138 			if (trace.fraction < 1) {
1139 				vec3_t tangent;
1140 				//calc reflection vector
1141 				d = DotProduct (p->vel, trace.plane.normal);
1142 				VectorMA (p->vel, -2*d, trace.plane.normal, p->vel);
1143 				VectorScale(p->vel,0.33,p->vel);
1144 				VectorCopy(trace.endpos,p->org);
1145 				//XYZ
1146 				p->numbounces--;
1147 
1148 				CrossProduct(trace.plane.normal,p->vel,tangent);
1149 				R_SpawnDecal(trace.endpos, trace.plane.normal, tangent, dt_blood);
1150 			} else {
1151 				VectorCopy(neworg,p->org);
1152 			}
1153 		}
1154 
1155 
1156 
1157 		switch (p->type)
1158 		{
1159 		case pt_static:
1160 			break;
1161 		case pt_fire:
1162 			p->ramp += time1;
1163 			if (p->ramp >= 6)
1164 				p->die = -1;
1165 			else
1166 				p->color = ramp3[(int)p->ramp];
1167 			p->vel[2] += grav;
1168 			break;
1169 
1170 		case pt_explode:
1171 			p->ramp += time2;
1172 			if (p->ramp >=8)
1173 				p->die = -1;
1174 			else
1175 				p->color = ramp1[(int)p->ramp];
1176 			for (i=0 ; i<3 ; i++)
1177 				p->vel[i] += p->vel[i]*dvel;
1178 			p->vel[2] -= grav;
1179 			break;
1180 
1181 		case pt_explode2:
1182 			p->ramp += time3;
1183 			if (p->ramp >=8)
1184 				p->die = -1;
1185 			else
1186 				p->color = ramp2[(int)p->ramp];
1187 			for (i=0 ; i<3 ; i++)
1188 				p->vel[i] -= p->vel[i]*frametime;
1189 			p->vel[2] -= grav;
1190 			break;
1191 
1192 		case pt_blob:
1193 			for (i=0 ; i<3 ; i++)
1194 				p->vel[i] += p->vel[i]*dvel;
1195 			p->vel[2] -= grav;
1196 			break;
1197 
1198 		case pt_blob2:
1199 			for (i=0 ; i<2 ; i++)
1200 				p->vel[i] -= p->vel[i]*dvel;
1201 			p->vel[2] -= grav;
1202 			break;
1203 
1204 		case pt_grav:
1205 #ifdef QUAKE2
1206 			p->vel[2] -= grav * 20;
1207 			break;
1208 #endif
1209 		case pt_slowgrav:
1210 			p->vel[2] -= grav*6;
1211 			break;
1212 		}
1213 	}
1214 
1215 #ifdef GLQUAKE
1216 	glDepthMask(1);
1217 	glDisable (GL_BLEND);
1218 	glDisable(GL_ALPHA_TEST);
1219 	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1220 	//XYZ
1221 	glLoadIdentity();
1222 	glMatrixMode(GL_MODELVIEW);
1223 	glFogfv(GL_FOG_COLOR, fog_color); //Done in actual function now (stops "triangle effect") - Eradicator
1224 #else
1225 	D_EndParticles ();
1226 #endif
1227 }
1228 
1229 */
1230 extern	cvar_t	sv_gravity;
1231 
R_DrawParticles(void)1232 void R_DrawParticles (void)
1233 {
1234 	particle_t		*p, *kill;
1235 	float			grav;
1236 	int				i;
1237 	float			time2, time3;
1238 	float			time1;
1239 	float			dvel, blend, blend1;
1240 	float			frametime;
1241 	vec3_t			up, right, neworg;
1242 	float			scale, sscale;
1243 	ParticleEmitter_t *ekill, *emt;
1244 
1245 	if (gl_wireframe.value)
1246 		return;
1247 
1248 	glFogfv(GL_FOG_COLOR, color_black); //Done in actual function now (stops "triangle effect") - Eradicator
1249 	glEnable (GL_BLEND);
1250 	glBlendFunc (GL_ONE, GL_ONE);
1251 	glEnable(GL_ALPHA_TEST);
1252 	glAlphaFunc(GL_GREATER,0.01);
1253 	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
1254 	glDepthMask(0);
1255 
1256 	VectorScale (vup, 1, up);
1257 	VectorScale (vright, 1, right);
1258 	glMatrixMode(GL_TEXTURE);
1259 
1260 	frametime = cl.time - cl.oldtime;
1261 	time3 = frametime * 15;
1262 	time2 = frametime * 10; // 15;
1263 	time1 = frametime * 5;
1264 	grav = frametime * sv_gravity.value * 0.05;
1265 	dvel = 4*frametime;
1266 
1267 	//remove expired emitters
1268 	for ( ;; )
1269 	{
1270 		ekill = active_emitters;
1271 		if (ekill && ekill->die < cl.time)
1272 		{
1273 			active_emitters = ekill->next;
1274 			ekill->next = free_emitters;
1275 			free_emitters = ekill;
1276 			continue;
1277 		}
1278 		break;
1279 	}
1280 
1281 	//Do the particle logic/drawing
1282 	for (emt=active_emitters ; emt ; emt=emt->next)
1283 	{
1284 		for ( ;; )
1285 		{
1286 			ekill = emt->next;
1287 			//XYZ
1288 			if (ekill && (ekill->die < cl.time))
1289 			{
1290 				emt->next = ekill->next;
1291 				ekill->next = free_emitters;
1292 				free_emitters = ekill;
1293 				continue;
1294 			}
1295 			break;
1296 		}
1297 
1298 		if (emt->nexttick < cl.time) {
1299 			vec3_t length;
1300 			VectorSubtract(emt->origin, r_refdef.vieworg, length);
1301 			//dont emit if we are to far away to see it
1302 			if (Length(length) < 600.0f) {
1303 				for (i=0; i<emt->count; i++) {
1304 					InitParticleFromEffect(emt->effect,emt->origin);
1305 				}
1306 			}
1307 			emt->nexttick = cl.time + emt->tick;
1308 		}
1309 	}
1310 
1311 	//remove expired particles
1312 	for ( ;; )
1313 	{
1314 		kill = active_particles;
1315 		if (kill && kill->die < cl.time)
1316 		{
1317 			active_particles = kill->next;
1318 			kill->next = free_particles;
1319 			free_particles = kill;
1320 			continue;
1321 		}
1322 		break;
1323 	}
1324 
1325 	//Do the particle logic/drawing
1326 	for (p=active_particles ; p ; p=p->next)
1327 	{
1328 		for ( ;; )
1329 		{
1330 			kill = p->next;
1331 			//XYZ
1332 			if (kill && ((kill->die < cl.time) || (kill->numbounces <= 0)))
1333 			{
1334 				p->next = kill->next;
1335 				kill->next = free_particles;
1336 				free_particles = kill;
1337 				continue;
1338 			}
1339 			break;
1340 		}
1341 
1342 		scale = p->size;
1343 		p->size += p->growspeed*frametime;
1344 
1345 		//calculate color based on life ...
1346 		blend = (p->die-cl.time)/p->lifetime;
1347 		blend1 = 1-blend;
1348 		for (i=0; i<3; i++) {
1349 			p->color[i] = p->startcolor[i] * blend + p->endcolor[i] * blend1;
1350 		}
1351 
1352 		if ((p->die - cl.time) < 0.5) {
1353 			float fade = 2*(p->die - cl.time);
1354 			glColor4f(p->color[0]*fade, p->color[1]*fade, p->color[2]*fade, fade);
1355 		} else {
1356 			glColor3fv(&p->color[0]);
1357 		}
1358 
1359 		GL_Bind(p->texture);
1360 		glBlendFunc (p->srcblend, p->dstblend);
1361 
1362 		//Align with velocity
1363 		if (p->velaligned){
1364 			float lscale;
1365 			VectorCopy (p->vel, up);
1366 			VectorNormalize(up);
1367 			CrossProduct(vpn,up,right);
1368 			VectorNormalize(right);
1369 			lscale = (Length(p->vel)*p->velscale);
1370 			VectorScale(up,lscale,up);
1371 		} else {
1372 			VectorCopy (vup, up);
1373 			VectorCopy (vright, right);
1374 		}
1375 
1376 		glLoadIdentity();
1377 		glTranslatef(0.5,0.5,0);
1378 		glRotatef(p->rot,0,0,1);
1379 		glTranslatef(-0.5,-0.5,0);
1380 
1381 		sscale = -scale/4;
1382 		VectorMA(p->org,sscale,up,neworg);
1383 		VectorMA(neworg,sscale,right,neworg);
1384 
1385                 // draw the particle as two triangles
1386                 scale /= 2;
1387 		glBegin(GL_TRIANGLE_FAN);
1388 		glTexCoord2f (0,0);
1389 		glVertex3fv (neworg);
1390 		glTexCoord2f (0,1);
1391 		glVertex3f (neworg[0] + up[0]*scale, neworg[1] + up[1]*scale,
1392                             neworg[2] + up[2]*scale);
1393 		glTexCoord2f (1,1);
1394 		glVertex3f (neworg[0] + up[0]*scale + right[0]*scale, neworg[1] + up[1]*scale + right[1]*scale,
1395                             neworg[2] + up[2]*scale + right[2]*scale);
1396 		glTexCoord2f (1,0);
1397 		glVertex3f (neworg[0] + right[0]*scale, neworg[1] + right[1]*scale,
1398                             neworg[2] + right[2]*scale);
1399 		glEnd();
1400                 scale *= 2;
1401 
1402 		//calculate new position/rotation
1403 		neworg[0] = p->org[0]+p->vel[0]*frametime;
1404 		neworg[1] = p->org[1]+p->vel[1]*frametime;
1405 		neworg[2] = p->org[2]+p->vel[2]*frametime;
1406 		p->rot = p->rot+p->rspeed*frametime;
1407 
1408 		//do collision detection
1409 		{
1410 			trace_t	trace;
1411 			float	d;
1412 
1413 			memset (&trace, 0, sizeof(trace));
1414 			trace.fraction = 1;
1415 			SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, p->org, neworg, &trace);
1416 
1417 			if (trace.fraction < 1) {
1418 				vec3_t tangent;
1419 				//calc reflection vector
1420 				d = DotProduct (p->vel, trace.plane.normal);
1421 				VectorMA (p->vel, -2*d, trace.plane.normal, p->vel);
1422 				VectorScale(p->vel,0.33,p->vel);
1423 				VectorCopy(trace.endpos,p->org);
1424 				//XYZ
1425 				p->numbounces--;
1426 
1427 				if (p->spawn) {
1428 					CrossProduct(trace.plane.normal,p->vel,tangent);
1429 					if (p->spawn->align == align_surf) {
1430 						R_SpawnDecal(p->org, trace.plane.normal, tangent, p->spawn);
1431 					} else {
1432 						InitParticleFromEffect(p->spawn, p->org);
1433 					}
1434 				}
1435 			} else {
1436 				VectorCopy(neworg,p->org);
1437 			}
1438 		}
1439 
1440 		for (i=0; i<3; i++) {
1441 			p->vel[i] += p->gravity[i]*frametime;
1442 		}
1443 
1444 		for (i=0; i<3; i++) {
1445 			p->vel[i] *= p->drag[i];
1446 		}
1447 	}
1448 
1449 	glDepthMask(1);
1450 	glDisable (GL_BLEND);
1451 	glDisable(GL_ALPHA_TEST);
1452 	glAlphaFunc(GL_GREATER,0.666);
1453 	glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
1454 	//XYZ
1455 	glLoadIdentity();
1456 	glMatrixMode(GL_MODELVIEW);
1457 	glFogfv(GL_FOG_COLOR, fog_color); //Done in actual function now (stops "triangle effect") - Eradicator
1458 }
1459