1 /* KJL 14:50:53 10/13/97 -
2  *
3  *	Experimental particle system
4  *
5  */
6 
7 #include "3dc.h"
8 #include "inline.h"
9 #include "module.h"
10 #include "stratdef.h"
11 #include "gamedef.h"
12 #include "bh_types.h"
13 #include "dynblock.h"
14 #include "dynamics.h"
15 #include "particle.h"
16 #include "kshape.h"
17 #include "sfx.h"
18 #include "d3d_render.h"
19 #include "psndproj.h"
20 #include "lighting.h"
21 #include "bh_light.h"
22 #include "bh_xeno.h"
23 #include "pvisible.h"
24 #include "sphere.h"
25 #include "bh_rubberduck.h"
26 #include "bh_weap.h"
27 #include "weapons.h"
28 #include "decal.h"
29 #include "avpview.h"
30 #include "pldghost.h"
31 #include "detaillevels.h"
32 #include "psnd.h"
33 #include "kzsort.h"
34 #include "avp_userprofile.h"
35 #define UseLocalAssert Yes
36 #include "ourasert.h"
37 #include "savegame.h"
38 #include "los.h"
39 #include "chnkload.h"
40 #include "maths.h"
41 
42 #include <math.h>
43 
44 #define RGBALIGHT_MAKE(r,g,b,a) RGBA_MAKE(r,g,b,a)
45 
46 #define MAX_NO_OF_PHEROMONE_TRAILS 500
47 #define MAX_NO_OF_PARTICLES 5000
48 #define MAX_NO_OF_EXPLOSIONS 10
49 
50 #define TRAIL_DECAY_SPEED (51*65536*5)
51 
52 static PHEROMONE_TRAIL TrailStorage[MAX_NO_OF_PHEROMONE_TRAILS];
53 static PARTICLE ParticleStorage[MAX_NO_OF_PARTICLES];
54 static VOLUMETRIC_EXPLOSION ExplosionStorage[MAX_NO_OF_EXPLOSIONS];
55 
56 static int NumActiveTrails;
57 static int NumActiveParticles;
58 static int CurrentExplosionIndex;
59 
60 extern int NormalFrameTime;
61 extern int PrevNormalFrameTime;
62 extern int CloakingPhase;
63 
64 int NumberOfBloodParticles;
65 int NumberOfFlaresActive;
66 
67 extern SOUND3DDATA PredPistolExplosion_SoundData;
68 extern MODULE *playerPherModule;
69 
70 static void InitialiseVolumetricExplosions(void);
71 void DoFlareCorona(DISPLAYBLOCK *objectPtr);
72 void InitialiseRainDrops(void);
73 void HandleRipples(void);
74 void AddRipple(int x,int z,int amplitude);
75 void MakeMolotovExplosionAt(VECTORCH *positionPtr,int seed);
76 static void HandleVolumetricExplosion(VOLUMETRIC_EXPLOSION *expPtr);
77 void DrawXenoborgMainLaserbeam(LASER_BEAM_DESC *laserPtr);
78 void HandlePheromoneTrails(void);
79 void RenderTrailSegment(PHEROMONE_TRAIL *trailPtr);
80 
81 PARTICLE_DESC ParticleDescription[MAX_NO_OF_PARTICLE_IDS] =
82 {
83 	/* PARTICLE_PREDATOR_BLOOD */
84 	{
85 		//int StartU;
86 		0<<16,
87 		//int StartV;
88 		64<<16,
89 		//int EndU;
90 		63<<16,
91 		//int EndV;
92 		127<<16,
93 		//unsigned int Size;
94 		200,
95 
96 		//enum TRANSLUCENCY_TYPE TranslucencyType;
97 		TRANSLUCENCY_GLOWING,
98 
99 		//unsigned char Alpha;
100 		128,
101 		//unsigned char RedScale;
102 		{0,		0,		255,	255,	255},
103 		//unsigned char GreenScale;
104 		{255,	255,	255,	255,	0},
105 		//unsigned char BlueScale;
106 		{0,		0,		255,	255,	0},
107 
108 		//unsigned char IsLit:1;
109 		0,
110 		//IsDrawnInFront:1;
111 		0,
112 		//IsDrawnAtBack:1;
113 		0,
114 
115 	},
116 	/* PARTICLE_ALIEN_BLOOD */
117 	{
118 #if 0
119 		//int StartU;
120 		1<<16,
121 		//int StartV;
122 		248<<16,
123 		//int EndU;
124 		8<<16,
125 		//int EndV;
126 		256<<16,
127 #else
128 		//int StartU;
129 		0<<16,
130 		//int StartV;
131 		64<<16,
132 		//int EndU;
133 		63<<16,
134 		//int EndV;
135 		127<<16,
136 #endif
137 		//unsigned int Size;
138 		50,
139 
140 		//enum TRANSLUCENCY_TYPE TranslucencyType;
141 		TRANSLUCENCY_GLOWING,
142 
143 		//unsigned char Alpha;
144 		128,
145 		//unsigned char RedScale;
146 		{255,	255,	0,		16,		255},
147 		//unsigned char GreenScale;
148 		{255,	255,	255,	0,		255},
149 		//unsigned char BlueScale;
150 		{0,		0,		0,		255,	255},
151 
152 		//unsigned char IsLit:1;
153 		1,
154 		//IsDrawnInFront:1;
155 		0,
156 		//IsDrawnAtBack:1;
157 		0,
158 
159 	},
160 	/* PARTICLE_HUMAN_BLOOD */
161 	{
162 		//int StartU;
163 		0<<16,
164 		//int StartV;
165 		63<<16,
166 		//int EndU;
167 		63<<16,
168 		//int EndV;
169 		127<<16,
170 		//unsigned int Size;
171 		50,
172 
173 		//enum TRANSLUCENCY_TYPE TranslucencyType;
174 		TRANSLUCENCY_INVCOLOUR,
175 
176 		//unsigned char Alpha;
177 		255,
178 		//unsigned char RedScale;
179 		{0,			0,		0,		0 ,	0},
180 		//unsigned char GreenScale;
181 		{255,		255,	64,		64,	255},
182 		//unsigned char BlueScale;
183 		{255,		255,	0,		64,	255},
184 
185 		//unsigned char IsLit:1;
186 		0,
187 		//IsDrawnInFront:1;
188 		0,
189 		//IsDrawnAtBack:1;
190 		0,
191 	},
192 	/* PARTICLE_ANDROID_BLOOD */
193 	{
194 		//int StartU;
195 		0<<16,
196 		//int StartV;
197 		63<<16,
198 		//int EndU;
199 		63<<16,
200 		//int EndV;
201 		127<<16,
202 		//unsigned int Size;
203 		50,
204 
205 		//enum TRANSLUCENCY_TYPE TranslucencyType;
206 		TRANSLUCENCY_GLOWING,
207 
208 		//unsigned char Alpha;
209 		255,
210 		//unsigned char RedScale;
211 		{255,		255,  	255,	255,	255},
212 		//unsigned char GreenScale;
213 		{255,		255,	255,	255,	255},
214 		//unsigned char BlueScale;
215 		{255,		255,	255,	255,	255},
216 
217 		//unsigned char IsLit:1;
218 		1,
219 		//IsDrawnInFront:1;
220 		0,
221 		//IsDrawnAtBack:1;
222 		0,
223 	},
224 	/* PARTICLE_MUZZLEFLASH */
225 	{
226 		//int StartU;
227 		64<<16,
228 		//int StartV;
229 		64<<16,
230 		//int EndU;
231 		127<<16,
232 		//int EndV;
233 		127<<16,
234 		//unsigned int Size;
235 		200,
236 
237 		//enum TRANSLUCENCY_TYPE TranslucencyType;
238 		TRANSLUCENCY_GLOWING,
239 
240 		//unsigned char Alpha;
241 		255,
242 		//unsigned char RedScale;
243 		{255,	255,	255,	255,	255},
244 		//unsigned char GreenScale;
245 		{192,	255,	255,	0  ,	255},
246 		//unsigned char BlueScale;
247 		{128,	255,	255,	0  ,	0},
248 
249 		//unsigned char IsLit:1;
250 		0,
251 		//IsDrawnInFront:1;
252 		0,
253 		//IsDrawnAtBack:1;
254 		0,
255 	},
256 	/* PARTICLE_SMARTGUNMUZZLEFLASH */
257 	{
258 		//int StartU;
259 		64<<16,
260 		//int StartV;
261 	   	0<<16,
262 		//int EndU;
263 		127<<16,
264 		//int EndV;
265 		63<<16,
266 		//unsigned int Size;
267 		800,
268 
269 		//enum TRANSLUCENCY_TYPE TranslucencyType;
270 		TRANSLUCENCY_GLOWING,
271 
272 		//unsigned char Alpha;
273 		255,
274 		//unsigned char RedScale;
275 		{255,	255,	255,	255,	255},
276 		//unsigned char GreenScale;
277 		{255,	255,	255,	0,		255},
278 		//unsigned char BlueScale;
279 		{255,	255,	255,	0,		0},
280 
281 		//unsigned char IsLit:1;
282 		0,
283 		//IsDrawnInFront:1;
284 		0,
285 		//IsDrawnAtBack:1;
286 		0,
287 	},
288 	/* PARTICLE_WATERSPRAY */
289 	{
290 		//int StartU;
291 		0<<16,
292 		//int StartV;
293 	   	64<<16,
294 		//int EndU;
295 		63<<16,
296 		//int EndV;
297 		127<<16,
298 		//unsigned int Size;
299 		80,
300 
301 		//enum TRANSLUCENCY_TYPE TranslucencyType;
302 		TRANSLUCENCY_GLOWING,
303 
304 		//unsigned char Alpha;
305 		64,
306 		//unsigned char RedScale;
307 		{200,	200,	0,		0},
308 		//unsigned char GreenScale;
309 		{230,	230,	240,	0},
310 		//unsigned char BlueScale;
311 		{255,	255,	0,		120},
312 
313 		//unsigned char IsLit:1;
314 		1,
315 		//IsDrawnInFront:1;
316 		0,
317 		//IsDrawnAtBack:1;
318 		0,
319 	},
320 	/* PARTICLE_WATERFALLSPRAY */
321 	{
322 		//int StartU;
323 		0<<16,
324 		//int StartV;
325 	   	64<<16,
326 		//int EndU;
327 		63<<16,
328 		//int EndV;
329 		127<<16,
330 		//unsigned int Size;
331 		1600,//200,
332 
333 		//enum TRANSLUCENCY_TYPE TranslucencyType;
334 		TRANSLUCENCY_GLOWING,
335 
336 		//unsigned char Alpha;
337 		32,
338 		//unsigned char RedScale;
339 		{100,	200,	240,	120,	120,	120},
340 		//unsigned char GreenScale;
341 		{130,	230,	240,	120,	120,	120},
342 		//unsigned char BlueScale;
343 		{255,	255,	240,	120,	120,	120},
344 
345 		//unsigned char IsLit:1;
346 		0,
347 		//IsDrawnInFront:1;
348 		0,
349 		//IsDrawnAtBack:1;
350 		0,
351 	},
352 	/* PARTICLE_BLACKSMOKE */
353 	{
354 		//int StartU;
355 		0<<16,
356 		//int StartV;
357 	   	130<<16,
358 		//int EndU;
359 		28<<16,
360 		//int EndV;
361 		157<<16,
362 		//unsigned int Size;
363 		200,
364 
365 		//enum TRANSLUCENCY_TYPE TranslucencyType;
366 		TRANSLUCENCY_INVCOLOUR,
367 
368 		//unsigned char Alpha;
369 		255,
370 		//unsigned char RedScale;
371 		{64,	64,		64,		64,		64},
372 		//unsigned char GreenScale;
373 		{64,	64,		64,		64,		64},
374 		//unsigned char BlueScale;
375 		{64,	64,		64,		64,		64},
376 
377 		//unsigned char IsLit:1;
378 		0,
379 		//IsDrawnInFront:1;
380 		0,
381 		//IsDrawnAtBack:1;
382 		0,
383 	},
384 	/* PARTICLE_FLARESMOKE */
385 	{
386 		#if 0
387 		//int StartU;
388 		0<<16,
389 		//int StartV;
390 	   	130<<16,
391 		//int EndU;
392 		28<<16,
393 		//int EndV;
394 		157<<16,
395 		#else
396 		//int StartU;
397 		128<<16,
398 		//int StartV;
399 	   	0<<16,
400 		//int EndU;
401 		195<<16,
402 		//int EndV;
403 		63<<16,
404 		#endif
405 		//unsigned int Size;
406 		200,
407 
408 		//enum TRANSLUCENCY_TYPE TranslucencyType;
409 		TRANSLUCENCY_GLOWING,
410 
411 		//unsigned char Alpha;
412 		64,
413 		//unsigned char RedScale;
414 		{255,	255,	255,	255,		64},
415 		//unsigned char GreenScale;
416 		{255,	255,	255,	0,		64},
417 		//unsigned char BlueScale;
418 		{255,	255,	255,	64,		0},
419 
420 		//unsigned char IsLit:1;
421 		0,
422 		//IsDrawnInFront:1;
423 		0,
424 		//IsDrawnAtBack:1;
425 		0,
426 	},
427 	/* PARTICLE_STEAM */
428 	{
429 		//int StartU;
430 		0<<16,
431 		//int StartV;
432 	   	130<<16,
433 		//int EndU;
434 		28<<16,
435 		//int EndV;
436 		157<<16,
437 		//unsigned int Size;
438 		100,
439 
440 		//enum TRANSLUCENCY_TYPE TranslucencyType;
441 		TRANSLUCENCY_GLOWING,
442 
443 		//unsigned char Alpha;
444 		64,
445 		//unsigned char RedScale;
446 		{128,	128,	128,	128,		64},
447 		//unsigned char GreenScale;
448 		{128,	128,	128,	128,		64},
449 		//unsigned char BlueScale;
450 		{128,	128,	128,	128,		0},
451 
452 		//unsigned char IsLit:1;
453 		0,
454 		//IsDrawnInFront:1;
455 		0,
456 		//IsDrawnAtBack:1;
457 		0,
458 	},
459 	/* PARTICLE_IMPACTSMOKE */
460 	{
461 		//int StartU;
462 		0<<16,
463 		//int StartV;
464 	   	130<<16,
465 		//int EndU;
466 		28<<16,
467 		//int EndV;
468 		157<<16,
469 		//unsigned int Size;
470 		100,
471 
472 		//enum TRANSLUCENCY_TYPE TranslucencyType;
473 		TRANSLUCENCY_INVCOLOUR,
474 
475 		//unsigned char Alpha;
476 		255,
477 		//unsigned char RedScale;
478 		{64,	64,		64,		64,		64},
479 		//unsigned char GreenScale;
480 		{64,	64,		64,		64,		64},
481 		//unsigned char BlueScale;
482 		{64,	64,		64,		64,		64},
483 
484 		//unsigned char IsLit:1;
485 		0,
486 		//IsDrawnInFront:1;
487 		0,
488 		//IsDrawnAtBack:1;
489 		0,
490 	},
491 	/* PARTICLE_GUNMUZZLE_SMOKE */
492 	{
493 		//int StartU;
494 		128<<16,
495 		//int StartV;
496 	   	0<<16,
497 		//int EndU;
498 		195<<16,
499 		//int EndV;
500 		63<<16,
501 		//unsigned int Size;
502 		32,
503 
504 		//enum TRANSLUCENCY_TYPE TranslucencyType;
505 		TRANSLUCENCY_GLOWING,
506 
507 		//unsigned char Alpha;
508 		64,
509 		//unsigned char RedScale;
510 		{255,	255,	255,	255,	64},
511 		//unsigned char GreenScale;
512 		{255,	255,	255,	0,		64},
513 		//unsigned char BlueScale;
514 		{255,	255,	255,	64,		0},
515 
516 		//unsigned char IsLit:1;
517 		1,
518 		//IsDrawnInFront:1;
519 		0,
520 		//IsDrawnAtBack:1;
521 		0,
522 	},
523 	/* PARTICLE_FLAME */
524 	{
525 		#if 0
526 		//int StartU;
527 		0<<16,
528 		//int StartV;
529 	   	0<<16,
530 		//int EndU;
531 		63<<16,
532 		//int EndV;
533 		63<<16,
534 		#else
535 		//int StartU;
536 		64<<16,
537 		//int StartV;
538 	   	0<<16,
539 		//int EndU;
540 		(64+127)<<16,
541 		//int EndV;
542 		63<<16,
543 		#endif
544 		//unsigned int Size;
545 		0,
546 
547 		//enum TRANSLUCENCY_TYPE TranslucencyType;
548 		TRANSLUCENCY_GLOWING,
549 
550 		//unsigned char Alpha;
551 		64,
552 		//unsigned char RedScale;
553 		{255,	255,	255,	128,	128,	0},
554 		//unsigned char GreenScale;
555 		{128,	128,	255,	64,		64,		128},
556 		//unsigned char BlueScale;
557 		{64,	64,		255,	255,	0,		0},
558 
559 		//unsigned char IsLit:1;
560 		0,
561 		//IsDrawnInFront:1;
562 		0,
563 		//IsDrawnAtBack:1;
564 		0,
565 	},
566 	/* PARTICLE_NONCOLLIDINGFLAME */
567 	{
568 		#if 0
569 		//int StartU;
570 		0<<16,
571 		//int StartV;
572 	   	0<<16,
573 		//int EndU;
574 		63<<16,
575 		//int EndV;
576 		63<<16,
577 		#else
578 		//int StartU;
579 		64<<16,
580 		//int StartV;
581 	   	0<<16,
582 		//int EndU;
583 		(64+127)<<16,
584 		//int EndV;
585 		63<<16,
586 		#endif
587 		//unsigned int Size;
588 		0,
589 
590 		//enum TRANSLUCENCY_TYPE TranslucencyType;
591 		TRANSLUCENCY_GLOWING,
592 
593 		//unsigned char Alpha;
594 		64,
595 		//unsigned char RedScale;
596 		{255,	255,	255,	128,	128,	0},
597 		//unsigned char GreenScale;
598 		{128,	128,	255,	64,		64,		128},
599 		//unsigned char BlueScale;
600 		{64,	64,		255,	255,	0,		0},
601 
602 		//unsigned char IsLit:1;
603 		0,
604 		//IsDrawnInFront:1;
605 		0,
606 		//IsDrawnAtBack:1;
607 		0,
608 	},
609 	/* PARTICLE_NONDAMAGINGFLAME */
610 	{
611 		#if 0
612 		//int StartU;
613 		0<<16,
614 		//int StartV;
615 	   	0<<16,
616 		//int EndU;
617 		63<<16,
618 		//int EndV;
619 		63<<16,
620 		#else
621 		//int StartU;
622 		64<<16,
623 		//int StartV;
624 	   	0<<16,
625 		//int EndU;
626 		(64+127)<<16,
627 		//int EndV;
628 		63<<16,
629 		#endif
630 		//unsigned int Size;
631 		0,
632 
633 		//enum TRANSLUCENCY_TYPE TranslucencyType;
634 		TRANSLUCENCY_GLOWING,
635 
636 		//unsigned char Alpha;
637 		64,
638 		//unsigned char RedScale;
639 		{255,	255,	255,	128,	128,	0},
640 		//unsigned char GreenScale;
641 		{128,	128,	255,	64,		64,		128},
642 		//unsigned char BlueScale;
643 		{64,	64,		255,	255,	0,		0},
644 
645 		//unsigned char IsLit:1;
646 		0,
647 		//IsDrawnInFront:1;
648 		0,
649 		//IsDrawnAtBack:1;
650 		0,
651 	},
652 	/* PARTICLE_FIRE */
653 	{
654 	   	#if 1
655 	   	//int StartU;
656 		0<<16,
657 		//int StartV;
658 	   	0<<16,
659 		//int EndU;
660 		63<<16,
661 		//int EndV;
662 		63<<16,
663 		#else
664 		//int StartU;
665 		64<<16,
666 		//int StartV;
667 	   	0<<16,
668 		//int EndU;
669 		(64+127)<<16,
670 		//int EndV;
671 		63<<16,
672 		#endif
673 
674 		//unsigned int Size;
675 		0,
676 
677 		//enum TRANSLUCENCY_TYPE TranslucencyType;
678 		TRANSLUCENCY_GLOWING,
679 
680 		//unsigned char Alpha;
681 		64,
682 		//unsigned char RedScale;
683 		{255,	255,	255,	128,	128,	0},
684 		//unsigned char GreenScale;
685 		{128,	128,	255,	64,		64,		128},
686 		//unsigned char BlueScale;
687 		{64,	64,		255,	255,	0,		0},
688 
689 		//unsigned char IsLit:1;
690 		0,
691 		//IsDrawnInFront:1;
692 		0,
693 		//IsDrawnAtBack:1;
694 		0,
695 	},
696 	/* PARTICLE_EXPLOSIONFIRE */
697 	{
698 		#if 0
699 		//int StartU;
700 		128<<16,
701 		//int StartV;
702 	   	0<<16,
703 		//int EndU;
704 		192<<16,
705 		//int EndV;
706 		63<<16,
707 		#else
708 		//int StartU;
709 		0<<16,
710 		//int StartV;
711 	   	0<<16,
712 		//int EndU;
713 		48<<16,
714 		//int EndV;
715 		63<<16,
716 		#endif
717 		//unsigned int Size;
718 		800,
719 
720 		//enum TRANSLUCENCY_TYPE TranslucencyType;
721 		TRANSLUCENCY_GLOWING,
722 
723 		//unsigned char Alpha;
724 		255,
725 		//unsigned char RedScale;
726 		{255,	255,	255,	128,	128,	0},
727 		//unsigned char GreenScale;
728 		{128,	128,	255,	64,		64,		128},
729 		//unsigned char BlueScale;
730 		{64,	64,		255,	255,	0,		0},
731 
732 		//unsigned char IsLit:1;
733 		0,
734 		//IsDrawnInFront:1;
735 		0,
736 		//IsDrawnAtBack:1;
737 		0,
738 	},
739 	/* PARTICLE_MOLOTOVFLAME */
740 	{
741 		//int StartU;
742 		64<<16,
743 		//int StartV;
744 	   	0<<16,
745 		//int EndU;
746 		(64+127)<<16,
747 		//int EndV;
748 		63<<16,
749 		//unsigned int Size;
750 		800,
751 
752 		//enum TRANSLUCENCY_TYPE TranslucencyType;
753 		TRANSLUCENCY_GLOWING,
754 
755 		//unsigned char Alpha;
756 		255,
757 		//unsigned char RedScale;
758 		{255,	255,	255,	128,	128,	0},
759 		//unsigned char GreenScale;
760 		{128,	128,	255,	64,		64,		128},
761 		//unsigned char BlueScale;
762 		{64,	64,		255,	255,	0,		0},
763 
764 		//unsigned char IsLit:1;
765 		0,
766 		//IsDrawnInFront:1;
767 		0,
768 		//IsDrawnAtBack:1;
769 		0,
770 	},
771 	/* PARTICLE_MOLOTOVFLAME_NONDAMAGING */
772 	{
773 		//int StartU;
774 		64<<16,
775 		//int StartV;
776 	   	0<<16,
777 		//int EndU;
778 		(64+127)<<16,
779 		//int EndV;
780 		63<<16,
781 		//unsigned int Size;
782 		800,
783 
784 		//enum TRANSLUCENCY_TYPE TranslucencyType;
785 		TRANSLUCENCY_GLOWING,
786 
787 		//unsigned char Alpha;
788 		255,
789 		//unsigned char RedScale;
790 		{255,	255,	255,	128,	128,	0},
791 		//unsigned char GreenScale;
792 		{128,	128,	255,	64,		64,		128},
793 		//unsigned char BlueScale;
794 		{64,	64,		255,	255,	0,		0},
795 
796 		//unsigned char IsLit:1;
797 		0,
798 		//IsDrawnInFront:1;
799 		0,
800 		//IsDrawnAtBack:1;
801 		0,
802 	},
803 	/* PARTICLE_SPARK */
804 	{
805 		//int StartU;
806 		1<<16,
807 		//int StartV;
808 	   	1<<16,
809 		//int EndU;
810 		64<<16,
811 		//int EndV;
812 		64<<16,
813 		//unsigned int Size;
814 		200/8,
815 
816 		//enum TRANSLUCENCY_TYPE TranslucencyType;
817 		TRANSLUCENCY_GLOWING,
818 
819 		//unsigned char Alpha;
820 		64,
821 		//unsigned char RedScale;
822 		{255,	255,	255,	255,	255},
823 		//unsigned char GreenScale;
824 		{128,	128,	255,	0,		255},
825 		//unsigned char BlueScale;
826 		{64,	64,		255,	0,		0},
827 
828 		//unsigned char IsLit:1;
829 		0,
830 		//IsDrawnInFront:1;
831 		0,
832 		//IsDrawnAtBack:1;
833 		0,
834 	},
835 	/* PARTICLE_RICOCHET_SPARK */
836 	{
837 		//int StartU;
838 		1<<16,
839 		//int StartV;
840 	   	1<<16,
841 		//int EndU;
842 		64<<16,
843 		//int EndV;
844 		64<<16,
845 		//unsigned int Size;
846 		200/8,
847 
848 		//enum TRANSLUCENCY_TYPE TranslucencyType;
849 		TRANSLUCENCY_GLOWING,
850 
851 		//unsigned char Alpha;
852 		64,
853 		//unsigned char RedScale;
854 		{255,	255,	255,	255,	255},
855 		//unsigned char GreenScale;
856 		{128,	128,	255,	0,		255},
857 		//unsigned char BlueScale;
858 		{64,	64,		255,	0,		255},
859 
860 		//unsigned char IsLit:1;
861 		0,
862 		//IsDrawnInFront:1;
863 		0,
864 		//IsDrawnAtBack:1;
865 		0,
866 	},
867 	/* PARTICLE_ORANGE_SPARK */
868 	{
869 		//int StartU;
870 		224<<16,
871 		//int StartV;
872 	   	192<<16,
873 		//int EndU;
874 		255<<16,
875 		//int EndV;
876 		223<<16,
877 		//unsigned int Size;
878 		50,
879 
880 		//enum TRANSLUCENCY_TYPE TranslucencyType;
881 		TRANSLUCENCY_GLOWING,
882 
883 		//unsigned char Alpha;
884 		255,
885 		//unsigned char RedScale;
886 		{255,	64,		64,		64,		64},
887 		//unsigned char GreenScale;
888 		{255,	64,		64,		64,		64},
889 		//unsigned char BlueScale;
890 		{255,	64,		64,		64,		64},
891 
892 		//unsigned char IsLit:1;
893 		0,
894 		//IsDrawnInFront:1;
895 		0,
896 		//IsDrawnAtBack:1;
897 		0,
898 	},
899 	/* PARTICLE_ORANGE_PLASMA */
900 	{
901 		//int StartU;
902 		224<<16,
903 		//int StartV;
904 	   	192<<16,
905 		//int EndU;
906 		255<<16,
907 		//int EndV;
908 		223<<16,
909 		//unsigned int Size;
910 		50,
911 
912 		//enum TRANSLUCENCY_TYPE TranslucencyType;
913 		TRANSLUCENCY_GLOWING,
914 
915 		//unsigned char Alpha;
916 		255,
917 		//unsigned char RedScale;
918 		{255,	64,		64,		64,		64,		0},
919 		//unsigned char GreenScale;
920 		{255,	64,		64,		64,		64,		64},
921 		//unsigned char BlueScale;
922 		{255,	64,		64,		64,		64,		0},
923 
924 		//unsigned char IsLit:1;
925 		0,
926 		//IsDrawnInFront:1;
927 		0,
928 		//IsDrawnAtBack:1;
929 		0,
930 	},
931 
932 	/* PARTICLE_PLASMATRAIL */
933 	{
934 		//int StartU;
935 		64<<16,
936 		//int StartV;
937 		64<<16,
938 		//int EndU;
939 		127<<16,
940 		//int EndV;
941 		127<<16,
942 		//unsigned int Size;
943 		200/4,
944 
945 		//enum TRANSLUCENCY_TYPE TranslucencyType;
946 		TRANSLUCENCY_GLOWING,
947 
948 		//unsigned char Alpha;
949 		64,
950 		//unsigned char RedScale;
951 		{255,	255,	255,	255,	255,	0},
952 		//unsigned char GreenScale;
953 		{128,	128,	255,	0,		255,	255},
954 		//unsigned char BlueScale;
955 		{64,	64,		255,	0,		0,		0},
956 
957 		//unsigned char IsLit:1;
958 		0,
959 		//IsDrawnInFront:1;
960 		0,
961 		//IsDrawnAtBack:1;
962 		0,
963 	},
964 	/* PARTICLE_LASERBEAM */
965 	{
966 		//int StartU;
967 		32<<16,
968 		//int StartV;
969 	   	0<<16,
970 		//int EndU;
971 		32<<16,
972 		//int EndV;
973 		63<<16,
974 		//unsigned int Size;
975 		50,
976 
977 		//enum TRANSLUCENCY_TYPE TranslucencyType;
978 		TRANSLUCENCY_GLOWING,
979 
980 		//unsigned char Alpha;
981 		64,
982 		//unsigned char RedScale;
983 		{255,	255,	255,	255,	255,	0},
984 		//unsigned char GreenScale;
985 		{128,	128,	255,	0,		255,	255},
986 		//unsigned char BlueScale;
987 		{64,	64,		255,	0,		0,		0},
988 
989 		//unsigned char IsLit:1;
990 		0,
991 		//IsDrawnInFront:1;
992 		0,
993 		//IsDrawnAtBack:1;
994 		0,
995 	},
996 	/* PARTICLE_PLASMABEAM */
997 	{
998 		//int StartU;
999 		192<<16,
1000 		//int StartV;
1001 	   	224<<16,
1002 		//int EndU;
1003 		223<<16,
1004 		//int EndV;
1005 		255<<16,
1006 		//unsigned int Size;
1007 		50,
1008 
1009 		//enum TRANSLUCENCY_TYPE TranslucencyType;
1010 		TRANSLUCENCY_GLOWING,
1011 
1012 		//unsigned char Alpha;
1013 		64,
1014 		//unsigned char RedScale;
1015 		{255,	255,	255,	255,	255,	0},
1016 		//unsigned char GreenScale;
1017 		{128,	128,	255,	0,		255,	255},
1018 		//unsigned char BlueScale;
1019 		{64,	64,		255,	0,		0,		0},
1020 
1021 		//unsigned char IsLit:1;
1022 		0,
1023 		//IsDrawnInFront:1;
1024 		0,
1025 		//IsDrawnAtBack:1;
1026 		0,
1027 	},
1028 	/* PARTICLE_TRACER */
1029 	{
1030 		//int StartU;
1031 		32<<16,
1032 		//int StartV;
1033 	   	0<<16,
1034 		//int EndU;
1035 		32<<16,
1036 		//int EndV;
1037 		63<<16,
1038 		//unsigned int Size;
1039 		16,
1040 
1041 		//enum TRANSLUCENCY_TYPE TranslucencyType;
1042 		TRANSLUCENCY_GLOWING,
1043 
1044 		//unsigned char Alpha;
1045 		64,
1046 		//unsigned char RedScale;
1047 		{255,	255,	255,	255,	255},
1048 		//unsigned char GreenScale;
1049 		{255,	128,	255,	0,		255},
1050 		//unsigned char BlueScale;
1051 		{64,	64,		255,	0,		0},
1052 
1053 		//unsigned char IsLit:1;
1054 		0,
1055 		//IsDrawnInFront:1;
1056 		0,
1057 		//IsDrawnAtBack:1;
1058 		0,
1059 	},
1060 
1061 
1062 
1063 	/* PARTICLE_LIGHTFLARE */
1064 	{
1065 		//int StartU;
1066 		64<<16,
1067 		//int StartV;
1068 		64<<16,
1069 		//int EndU;
1070 		127<<16,
1071 		//int EndV;
1072 		127<<16,
1073 		//unsigned int Size;
1074 		200,
1075 
1076 		//enum TRANSLUCENCY_TYPE TranslucencyType;
1077 		TRANSLUCENCY_GLOWING,
1078 
1079 		//unsigned char Alpha;
1080 		255,
1081 		//unsigned char RedScale;
1082 		{255,	255,	255,	255,	255,	0},
1083 		//unsigned char GreenScale;
1084 		{255,	255,	255,	0,		255,	255},
1085 		//unsigned char BlueScale;
1086 		{255,	255,	255,	0,		0,		0},
1087 
1088 		//unsigned char IsLit:1;
1089 		0,
1090 		//IsDrawnInFront:1;
1091 		1,
1092 		//IsDrawnAtBack:1;
1093 		0,
1094 	},
1095 	/* PARTICLE_STAR */
1096 	{
1097 		//int StartU;
1098 		64<<16,
1099 		//int StartV;
1100 		64<<16,
1101 		//int EndU;
1102 		127<<16,
1103 		//int EndV;
1104 		127<<16,
1105 		//unsigned int Size;
1106 		200,
1107 
1108 		//enum TRANSLUCENCY_TYPE TranslucencyType;
1109 		TRANSLUCENCY_GLOWING,
1110 
1111 		//unsigned char Alpha;
1112 		255,
1113 		//unsigned char RedScale;
1114 		{255,	255,	255,	255,	255,	0},
1115 		//unsigned char GreenScale;
1116 		{255,	255,	255,	0,		255,	255},
1117 		//unsigned char BlueScale;
1118 		{255,	255,	255,	0,		0,		0},
1119 
1120 		//unsigned char IsLit:1;
1121 		0,
1122 		//IsDrawnInFront:1;
1123 		0,
1124 		//IsDrawnAtBack:1;
1125 		1,
1126 	},
1127 	/* PARTICLE_FLECHETTE */
1128 	{
1129 		//int StartU;
1130 		64<<16,
1131 		//int StartV;
1132 		64<<16,
1133 		//int EndU;
1134 		127<<16,
1135 		//int EndV;
1136 		127<<16,
1137 		//unsigned int Size;
1138 		100,
1139 
1140 		//enum TRANSLUCENCY_TYPE TranslucencyType;
1141 		TRANSLUCENCY_NORMAL,
1142 
1143 		//unsigned char Alpha;
1144 		255,
1145 		//unsigned char RedScale;
1146 		{255,	255,	255,	255,	255,	0},
1147 		//unsigned char GreenScale;
1148 		{255,	255,	255,	0,		255,	255},
1149 		//unsigned char BlueScale;
1150 		{255,	255,	255,	0,		0,		0},
1151 
1152 		//unsigned char IsLit:1;
1153 		0,
1154 		//IsDrawnInFront:1;
1155 		0,
1156 		//IsDrawnAtBack:1;
1157 		0,
1158 	},
1159 	/* PARTICLE_SMOKECLOUD */
1160 	{
1161 		//int StartU;
1162 		128<<16,
1163 		//int StartV;
1164 	   	64<<16,
1165 		//int EndU;
1166 		191<<16,
1167 		//int EndV;
1168 		127<<16,
1169 		//unsigned int Size;
1170 		1000,
1171 
1172 		//enum TRANSLUCENCY_TYPE TranslucencyType;
1173 		TRANSLUCENCY_GLOWING,
1174 
1175 		//unsigned char Alpha;
1176 		255,
1177 		//unsigned char RedScale;
1178 		{128,	64,		64,		64,		0},
1179 		//unsigned char GreenScale;
1180 		{128,	64,		64,		64,		64},
1181 		//unsigned char BlueScale;
1182 		{128,	64,		64,		64,		0},
1183 
1184 		//unsigned char IsLit:1;
1185 		1,
1186 		//IsDrawnInFront:1;
1187 		0,
1188 		//IsDrawnAtBack:1;
1189 		0,
1190 	},
1191 	/* PARTICLE_BLUEPLASMASPHERE */
1192 	{
1193 		//int StartU;
1194 		224<<16,
1195 		//int StartV;
1196 	   	160<<16,
1197 		//int EndU;
1198 		255<<16,
1199 		//int EndV;
1200 		191<<16,
1201 		//unsigned int Size;
1202 		500,
1203 
1204 		//enum TRANSLUCENCY_TYPE TranslucencyType;
1205 		TRANSLUCENCY_GLOWING,
1206 
1207 		//unsigned char Alpha;
1208 		255,
1209 		//unsigned char RedScale;
1210 		{255,	64,		64,		64,		64,		0},
1211 		//unsigned char GreenScale;
1212 		{255,	64,		64,		64,		64,		255},
1213 		//unsigned char BlueScale;
1214 		{255,	64,		64,		64,		0,		0},
1215 
1216 		//unsigned char IsLit:1;
1217 		0,
1218 		//IsDrawnInFront:1;
1219 		0,
1220 		//IsDrawnAtBack:1;
1221 		0,
1222 	},
1223 	/* PARTICLE_ELECTRICALPLASMASPHERE */
1224 	{
1225 		//int StartU;
1226 		64<<16,
1227 		//int StartV;
1228 	   	128<<16,
1229 		//int EndU;
1230 		127<<16,
1231 		//int EndV;
1232 		191<<16,
1233 		//unsigned int Size;
1234 		2000,
1235 
1236 		//enum TRANSLUCENCY_TYPE TranslucencyType;
1237 		TRANSLUCENCY_GLOWING,
1238 
1239 		//unsigned char Alpha;
1240 		255,
1241 		//unsigned char RedScale;
1242 		{255,	64,		64,		64,		64,		0},
1243 		//unsigned char GreenScale;
1244 		{255,	64,		64,		64,		64,		255},
1245 		//unsigned char BlueScale;
1246 		{255,	64,		64,		64,		0,		0},
1247 
1248 		//unsigned char IsLit:1;
1249 		0,
1250 		//IsDrawnInFront:1;
1251 		0,
1252 		//IsDrawnAtBack:1;
1253 		0,
1254 	},
1255 	/* PARTICLE_PREDPISTOL_FLECHETTE */
1256 	{
1257 		//int StartU;
1258 		1<<16,
1259 		//int StartV;
1260 	   	1<<16,
1261 		//int EndU;
1262 		64<<16,
1263 		//int EndV;
1264 		64<<16,
1265 		//unsigned int Size;
1266 		200/8,
1267 
1268 		//enum TRANSLUCENCY_TYPE TranslucencyType;
1269 		TRANSLUCENCY_GLOWING,
1270 
1271 		//unsigned char Alpha;
1272 		64,
1273 		//unsigned char RedScale;
1274 		{255,	255,	255,	255,	255,	0},
1275 		//unsigned char GreenScale;
1276 		{128,	128,	255,	0,		255,	255},
1277 		//unsigned char BlueScale;
1278 		{64,	64,		255,	0,		0,		0},
1279 
1280 		//unsigned char IsLit:1;
1281 		0,
1282 		//IsDrawnInFront:1;
1283 		0,
1284 		//IsDrawnAtBack:1;
1285 		0,
1286 	},
1287 	/* PARTICLE_PREDPISTOL_FLECHETTE_NONDAMAGING */
1288 	{
1289 		//int StartU;
1290 		1<<16,
1291 		//int StartV;
1292 	   	1<<16,
1293 		//int EndU;
1294 		64<<16,
1295 		//int EndV;
1296 		64<<16,
1297 		//unsigned int Size;
1298 		200/8,
1299 
1300 		//enum TRANSLUCENCY_TYPE TranslucencyType;
1301 		TRANSLUCENCY_GLOWING,
1302 
1303 		//unsigned char Alpha;
1304 		64,
1305 		//unsigned char RedScale;
1306 		{255,	255,	255,	255,	255,	0},
1307 		//unsigned char GreenScale;
1308 		{128,	128,	255,	0,		255,	255},
1309 		//unsigned char BlueScale;
1310 		{64,	64,		255,	0,		0,		0},
1311 
1312 		//unsigned char IsLit:1;
1313 		0,
1314 		//IsDrawnInFront:1;
1315 		0,
1316 		//IsDrawnAtBack:1;
1317 		0,
1318 	},
1319 	/* PARTICLE_FLECHETTE_NONDAMAGING */
1320 	{
1321 		//int StartU;
1322 		64<<16,
1323 		//int StartV;
1324 		64<<16,
1325 		//int EndU;
1326 		127<<16,
1327 		//int EndV;
1328 		127<<16,
1329 		//unsigned int Size;
1330 		100,
1331 
1332 		//enum TRANSLUCENCY_TYPE TranslucencyType;
1333 		TRANSLUCENCY_NORMAL,
1334 
1335 		//unsigned char Alpha;
1336 		255,
1337 		//unsigned char RedScale;
1338 		{255,	255,	255,	255,	255,	0},
1339 		//unsigned char GreenScale;
1340 		{255,	255,	255,	0,		255,	255},
1341 		//unsigned char BlueScale;
1342 		{255,	255,	255,	0,		0,		0},
1343 
1344 		//unsigned char IsLit:1;
1345 		0,
1346 		//IsDrawnInFront:1;
1347 		0,
1348 		//IsDrawnAtBack:1;
1349 		0,
1350 	},
1351 	/* PARTICLE_DEWLINE */
1352 	{
1353 		//int StartU;
1354 		64<<16,
1355 		//int StartV;
1356 		64<<16,
1357 		//int EndU;
1358 		127<<16,
1359 		//int EndV;
1360 		127<<16,
1361 		//unsigned int Size;
1362 		200/4,
1363 
1364 		//enum TRANSLUCENCY_TYPE TranslucencyType;
1365 		TRANSLUCENCY_GLOWING,
1366 
1367 		//unsigned char Alpha;
1368 		64,
1369 		//unsigned char RedScale;
1370 		{255,	255,	255,	255,	255,	0},
1371 		//unsigned char GreenScale;
1372 		{128,	128,	255,	0,		255,	255},
1373 		//unsigned char BlueScale;
1374 		{64,	64,		255,	0,		0,		0},
1375 
1376 		//unsigned char IsLit:1;
1377 		0,
1378 		//IsDrawnInFront:1;
1379 		0,
1380 		//IsDrawnAtBack:1;
1381 		0,
1382 	},
1383 	/* PARTICLE_PARGEN_FLAME */
1384 	{
1385 		//int StartU;
1386 		64<<16,
1387 		//int StartV;
1388 	   	0<<16,
1389 		//int EndU;
1390 		(64+127)<<16,
1391 		//int EndV;
1392 		63<<16,
1393 		//unsigned int Size;
1394 		0,
1395 
1396 		//enum TRANSLUCENCY_TYPE TranslucencyType;
1397 		TRANSLUCENCY_GLOWING,
1398 
1399 		//unsigned char Alpha;
1400 		64,
1401 		//unsigned char RedScale;
1402 		{255,	255,	255,	128,	128,	0},
1403 		//unsigned char GreenScale;
1404 		{128,	128,	255,	64,		64,		128},
1405 		//unsigned char BlueScale;
1406 		{64,	64,		255,	255,	0,		0},
1407 
1408 		//unsigned char IsLit:1;
1409 		0,
1410 		//IsDrawnInFront:1;
1411 		0,
1412 		//IsDrawnAtBack:1;
1413 		0,
1414 	},
1415 
1416 };
1417 
1418 
1419 static PARTICLE* AllocateParticle(void);
1420 static void DeallocateParticle(PARTICLE *particlePtr);
1421 static PHEROMONE_TRAIL* AllocatePheromoneTrail(void);
1422 static void DeallocatePheromoneTrail(PHEROMONE_TRAIL *trailPtr);
1423 
1424 
1425 
1426 
InitialiseParticleSystem(void)1427 void InitialiseParticleSystem(void)
1428 {
1429  	NumActiveParticles = 0;
1430 	NumberOfBloodParticles = 0;
1431 
1432  	NumActiveTrails = 0;
1433 
1434 	InitialiseVolumetricExplosions();
1435 	InitialiseRainDrops();
1436 	InitialiseDecalSystem();
1437 	InitForceField();
1438 	Generate_Sphere();
1439 
1440 	{
1441 		NumberOfFlaresActive=0;
1442 	}
1443 }
1444 
AllocateParticle(void)1445 static PARTICLE* AllocateParticle(void)
1446 {
1447 	PARTICLE *particlePtr = 0; /* Default to null ptr */
1448 
1449 	if (NumActiveParticles != MAX_NO_OF_PARTICLES)
1450 	{
1451 		particlePtr = &ParticleStorage[NumActiveParticles];
1452 		NumActiveParticles++;
1453 	}
1454 	else
1455 	{
1456 		/* unable to allocate a particle */
1457 	}
1458 
1459 	return particlePtr;
1460 }
DeallocateParticle(PARTICLE * particlePtr)1461 static void DeallocateParticle(PARTICLE *particlePtr)
1462 {
1463 	/* is pointer within array? */
1464 	LOCALASSERT(particlePtr>=ParticleStorage);
1465 	LOCALASSERT(particlePtr<=&ParticleStorage[MAX_NO_OF_PARTICLES-1]);
1466 
1467 	NumActiveParticles--;
1468 	*particlePtr = ParticleStorage[NumActiveParticles];
1469 }
1470 
AllocatePheromoneTrail(void)1471 static PHEROMONE_TRAIL* AllocatePheromoneTrail(void)
1472 {
1473 	PHEROMONE_TRAIL *trailPtr = 0; /* Default to null ptr */
1474 
1475 	if (NumActiveTrails != MAX_NO_OF_PHEROMONE_TRAILS)
1476 	{
1477 		trailPtr = &TrailStorage[NumActiveTrails];
1478 		NumActiveTrails++;
1479 	}
1480 	else
1481 	{
1482 		/* unable to allocate a trail */
1483 	}
1484 
1485 	return trailPtr;
1486 }
DeallocatePheromoneTrail(PHEROMONE_TRAIL * trailPtr)1487 static void DeallocatePheromoneTrail(PHEROMONE_TRAIL *trailPtr)
1488 {
1489 	/* is pointer within array? */
1490 	LOCALASSERT(trailPtr>=TrailStorage);
1491 	LOCALASSERT(trailPtr<=&TrailStorage[MAX_NO_OF_PHEROMONE_TRAILS-1]);
1492 
1493 	NumActiveTrails--;
1494 	*trailPtr = TrailStorage[NumActiveTrails];
1495 }
1496 
InitialiseVolumetricExplosions(void)1497 static void InitialiseVolumetricExplosions(void)
1498 {
1499 	int i;
1500 	for(i=0; i<MAX_NO_OF_EXPLOSIONS; i++)
1501 	{
1502 		ExplosionStorage[i].LifeTime = 0;
1503 	}
1504 	CurrentExplosionIndex = 0;
1505 }
AllocateVolumetricExplosion(void)1506 static VOLUMETRIC_EXPLOSION* AllocateVolumetricExplosion(void)
1507 {
1508 	VOLUMETRIC_EXPLOSION *explosionPtr = 0; /* Default to null ptr */
1509 
1510 	explosionPtr = &ExplosionStorage[CurrentExplosionIndex];
1511 
1512 	CurrentExplosionIndex++;
1513 	if (CurrentExplosionIndex>=MAX_NO_OF_EXPLOSIONS)
1514 	{
1515 		CurrentExplosionIndex=0;
1516 	}
1517 
1518 	LOCALASSERT(explosionPtr);
1519 	return explosionPtr;
1520 }
1521 
1522 
MakeParticle(VECTORCH * positionPtr,VECTORCH * velocityPtr,enum PARTICLE_ID particleID)1523 void MakeParticle(VECTORCH *positionPtr, VECTORCH *velocityPtr, enum PARTICLE_ID particleID)
1524 {
1525 	PARTICLE *particlePtr;
1526 
1527 	if( (particleID == PARTICLE_ALIEN_BLOOD) || (particleID == PARTICLE_PREDATOR_BLOOD) || (particleID == PARTICLE_HUMAN_BLOOD)|| (particleID == PARTICLE_ANDROID_BLOOD))
1528 		if (NumberOfBloodParticles>MAX_NO_OF_BLOOD_PARTICLES)
1529 			return;
1530 
1531 	particlePtr = AllocateParticle();
1532 	/* were we able to allocate a particle? */
1533 	if (particlePtr)
1534 	{
1535 		PARTICLE_DESC *particleDescPtr = &ParticleDescription[particleID];
1536 		particlePtr->Position = *positionPtr;
1537 		particlePtr->Velocity = *velocityPtr;
1538 
1539 		particlePtr->ParticleID = particleID;
1540 
1541 		particlePtr->Colour = RGBALIGHT_MAKE
1542 							  (
1543 							  	particleDescPtr->RedScale[CurrentVisionMode],
1544 							  	particleDescPtr->GreenScale[CurrentVisionMode],
1545 							  	particleDescPtr->BlueScale[CurrentVisionMode],
1546 							  	particleDescPtr->Alpha
1547 							  );
1548 		particlePtr->Size = particleDescPtr->Size;
1549 
1550 		switch(particlePtr->ParticleID)
1551 		{
1552 			case PARTICLE_PREDATOR_BLOOD:
1553 			case PARTICLE_ALIEN_BLOOD:
1554 			case PARTICLE_HUMAN_BLOOD:
1555 			case PARTICLE_ANDROID_BLOOD:
1556 			{
1557 				particlePtr->Offset = particlePtr->Position;
1558 				particlePtr->LifeTime = ONE_FIXED;
1559 				NumberOfBloodParticles++;
1560 				break;
1561 			}
1562 			case PARTICLE_BLACKSMOKE:
1563 			{
1564 				particlePtr->LifeTime = ONE_FIXED+(FastRandom()&32767);
1565 				particlePtr->Offset.vx = ((FastRandom()&1023) - 512)*2;
1566 				particlePtr->Offset.vz = ((FastRandom()&1023) - 512)*2;
1567 				break;
1568 			}
1569 			case PARTICLE_WATERSPRAY:
1570 			{
1571 				particlePtr->LifeTime = ONE_FIXED/2;
1572 				break;
1573 			}
1574 			case PARTICLE_WATERFALLSPRAY:
1575 			{
1576 				particlePtr->LifeTime = ONE_FIXED*10;
1577 				break;
1578 			}
1579 
1580 			case PARTICLE_FLARESMOKE:
1581 			case PARTICLE_STEAM:
1582 			{
1583 				particlePtr->LifeTime = (ONE_FIXED*1)/2+(FastRandom()&32767);
1584 				particlePtr->Offset.vx = ((FastRandom()&8191) - 4096);
1585 				particlePtr->Offset.vz = ((FastRandom()&8191) - 4096);
1586 				break;
1587 			}
1588 			case PARTICLE_IMPACTSMOKE:
1589 			{
1590 				particlePtr->LifeTime = ONE_FIXED+(FastRandom()&32767);
1591 				particlePtr->Offset.vx = ((FastRandom()&1023) - 512)*2;
1592 				particlePtr->Offset.vz = ((FastRandom()&1023) - 512)*2;
1593 				break;
1594 			}
1595 			case PARTICLE_GUNMUZZLE_SMOKE:
1596 			{
1597 				particlePtr->LifeTime = ONE_FIXED/2+(FastRandom()&32767);
1598 				particlePtr->Offset.vx = ((FastRandom()&1023) - 512);
1599 				particlePtr->Offset.vz = ((FastRandom()&1023) - 512);
1600 				break;
1601 			}
1602 
1603 			case PARTICLE_SPARK:
1604 			{
1605 				particlePtr->LifeTime = ONE_FIXED;
1606 				break;
1607 			}
1608 			case PARTICLE_RICOCHET_SPARK:
1609 			case PARTICLE_ORANGE_SPARK:
1610 			{
1611 				particlePtr->LifeTime = ONE_FIXED/4;
1612 				break;
1613 			}
1614 
1615 			case PARTICLE_ORANGE_PLASMA:
1616 			{
1617 				particlePtr->LifeTime = ONE_FIXED/8;
1618 				break;
1619 			}
1620 
1621 			case PARTICLE_PLASMATRAIL:
1622 			{
1623 				particlePtr->LifeTime = ONE_FIXED/2;
1624 				particlePtr->Offset=particlePtr->Position;
1625 				break;
1626 			}
1627 			case PARTICLE_DEWLINE:
1628 			{
1629 				particlePtr->LifeTime = ONE_FIXED; // /2
1630 				particlePtr->Offset=particlePtr->Position;
1631 				break;
1632 			}
1633 
1634 			case PARTICLE_FLAME:
1635 			case PARTICLE_NONCOLLIDINGFLAME:
1636 			case PARTICLE_NONDAMAGINGFLAME:
1637 			case PARTICLE_PARGEN_FLAME:
1638 			{
1639 				particlePtr->Offset.vx = (FastRandom()&4095);
1640 				particlePtr->Offset.vy = ((FastRandom()&32767) - 16384);
1641 
1642 				particlePtr->LifeTime = ONE_FIXED/2;
1643 				break;
1644 			}
1645 			case PARTICLE_FIRE:
1646 			{
1647 				particlePtr->LifeTime = ONE_FIXED/2+(FastRandom()&16383);
1648 				break;
1649 			}
1650 			case PARTICLE_EXPLOSIONFIRE:
1651 			{
1652 				particlePtr->LifeTime = ONE_FIXED/4;
1653 				particlePtr->Offset = particlePtr->Position;
1654 //	 			particlePtr->Position.vx += particlePtr->Velocity.vx;
1655 //	 			particlePtr->Position.vy += particlePtr->Velocity.vy;
1656 //	 			particlePtr->Position.vz += particlePtr->Velocity.vz;
1657 				break;
1658 			}
1659 			case PARTICLE_MOLOTOVFLAME:
1660 			{
1661 				particlePtr->LifeTime = ONE_FIXED*2-(FastRandom()&32767);
1662 				break;
1663 			}
1664 
1665 			case PARTICLE_FLECHETTE:
1666 			case PARTICLE_FLECHETTE_NONDAMAGING:
1667 			{
1668 				particlePtr->LifeTime = ONE_FIXED*8;
1669 				{
1670 					particlePtr->Offset.vy = 1;
1671 				}
1672 				break;
1673 			}
1674 
1675 			case PARTICLE_SMOKECLOUD:
1676 			{
1677 				particlePtr->LifeTime = ONE_FIXED*16-1;
1678 				particlePtr->Offset.vx = (FastRandom()&4095);
1679 				particlePtr->Offset.vy = ((FastRandom()&16383) - 8192);
1680 				break;
1681 			}
1682 			case PARTICLE_BLUEPLASMASPHERE:
1683 			{
1684 				particlePtr->LifeTime = 0;
1685 				break;
1686 			}
1687 			case PARTICLE_ELECTRICALPLASMASPHERE:
1688 			{
1689 				particlePtr->LifeTime = 32767;
1690 				break;
1691 			}
1692 			case PARTICLE_PREDPISTOL_FLECHETTE:
1693 			case PARTICLE_PREDPISTOL_FLECHETTE_NONDAMAGING:
1694 			{
1695 				particlePtr->LifeTime = ONE_FIXED;
1696 				break;
1697 			}
1698 			case PARTICLE_TRACER:
1699 			{
1700 				particlePtr->Position = *positionPtr;
1701 				particlePtr->Offset = *velocityPtr;
1702 				particlePtr->LifeTime = 0;
1703 				break;
1704 			}
1705 
1706 			default:
1707 			{
1708 				/* particle initialised wrongly */
1709 				DeallocateParticle(particlePtr);
1710 				LOCALASSERT(0);
1711 				break;
1712 			}
1713 		}
1714 
1715 	}
1716 }
1717 
HandleParticleSystem(void)1718 void HandleParticleSystem(void)
1719 {
1720 	int i;
1721 	PARTICLE *particlePtr;
1722 	HandleRipples();
1723 //	D3D_DrawWaterTest();
1724 
1725 	HandleDecalSystem();
1726 	D3D_DecalSystem_End();
1727 
1728 
1729 
1730 //	textprint("Particles Active: %d\n",i);
1731 //	D3D_DecalSystem_Setup();
1732 	i = NumActiveParticles;
1733 	particlePtr = ParticleStorage;
1734 
1735 	while(i--)
1736 	{
1737 		PARTICLE_DESC *particleDescPtr = &ParticleDescription[particlePtr->ParticleID];
1738 
1739 		particlePtr->NotYetRendered = 1;
1740 		switch(particlePtr->ParticleID)
1741 		{
1742 			case PARTICLE_ALIEN_BLOOD:
1743 			case PARTICLE_PREDATOR_BLOOD:
1744 			case PARTICLE_HUMAN_BLOOD:
1745 			case PARTICLE_ANDROID_BLOOD:
1746 			{
1747 				particlePtr->Size = 64-(FastRandom()&31);
1748 				particlePtr->Offset	= particlePtr->Position;
1749 				particlePtr->Offset.vx += particlePtr->Velocity.vx>>4;
1750 				particlePtr->Offset.vy += particlePtr->Velocity.vy>>4;
1751 				particlePtr->Offset.vz += particlePtr->Velocity.vz>>4;
1752 				break;
1753 			}
1754 			case PARTICLE_FLARESMOKE:
1755 			{
1756 //				particlePtr->Position.vy -= MUL_FIXED(1000+(FastRandom()&511),NormalFrameTime);
1757 				particlePtr->Position.vy += MUL_FIXED(particlePtr->Velocity.vy,NormalFrameTime);
1758 
1759 				if (particlePtr->Velocity.vy > -1300)
1760 					particlePtr->Velocity.vy -= MUL_FIXED(4000,NormalFrameTime);
1761 
1762 				if (particlePtr->Velocity.vx > 0)
1763 				{
1764 					particlePtr->Velocity.vx -= MUL_FIXED(2000,NormalFrameTime);
1765 					if (particlePtr->Velocity.vx < 0) particlePtr->Velocity.vx = 0;
1766 				}
1767 				else if (particlePtr->Velocity.vx < 0)
1768 				{
1769 					particlePtr->Velocity.vx += MUL_FIXED(2000,NormalFrameTime);
1770 					if (particlePtr->Velocity.vx > 0) particlePtr->Velocity.vx = 0;
1771 				}
1772 
1773 				if (particlePtr->Velocity.vz > 0)
1774 				{
1775 					particlePtr->Velocity.vz -= MUL_FIXED(2000,NormalFrameTime);
1776 					if (particlePtr->Velocity.vz < 0) particlePtr->Velocity.vz = 0;
1777 				}
1778 				else if (particlePtr->Velocity.vz < 0)
1779 				{
1780 					particlePtr->Velocity.vz += MUL_FIXED(2000,NormalFrameTime);
1781 					if (particlePtr->Velocity.vz > 0) particlePtr->Velocity.vz = 0;
1782 				}
1783 
1784 
1785 				particlePtr->Position.vx += MUL_FIXED
1786 											(
1787 												particlePtr->Velocity.vx+
1788 												MUL_FIXED
1789 												(
1790 													-GetSin((particlePtr->Position.vz+particlePtr->Position.vy)&4095)/4,
1791 													particlePtr->Offset.vx
1792 												),
1793 												NormalFrameTime
1794 
1795 											);
1796 
1797 				particlePtr->Position.vz += MUL_FIXED
1798 											(
1799 												particlePtr->Velocity.vz+
1800 												MUL_FIXED
1801 												(
1802 													GetCos((particlePtr->Position.vx+particlePtr->Position.vy)&4095)/4,
1803 													particlePtr->Offset.vz
1804 												),
1805 												NormalFrameTime
1806 
1807 											);
1808 
1809 				particlePtr->Colour = RGBALIGHT_MAKE
1810 									  (
1811 									  	particleDescPtr->RedScale[CurrentVisionMode],
1812 									  	particleDescPtr->GreenScale[CurrentVisionMode],
1813 									  	particleDescPtr->BlueScale[CurrentVisionMode],
1814 									  	(particlePtr->LifeTime>>10)
1815 									  );
1816 				particlePtr->Size = MUL_FIXED(ONE_FIXED-particlePtr->LifeTime,200)+50;
1817 
1818 				break;
1819 			}
1820 			case PARTICLE_STEAM:
1821 			{
1822 //				particlePtr->Position.vy -= MUL_FIXED(1000+(FastRandom()&511),NormalFrameTime);
1823 				particlePtr->Position.vy += MUL_FIXED(particlePtr->Velocity.vy,NormalFrameTime);
1824 
1825 				if (particlePtr->Velocity.vy > -1300)
1826 					particlePtr->Velocity.vy -= MUL_FIXED(4000,NormalFrameTime);
1827 
1828 				if (particlePtr->Velocity.vx > 0)
1829 				{
1830 					particlePtr->Velocity.vx -= MUL_FIXED(2000,NormalFrameTime);
1831 					if (particlePtr->Velocity.vx < 0) particlePtr->Velocity.vx = 0;
1832 				}
1833 				else if (particlePtr->Velocity.vx < 0)
1834 				{
1835 					particlePtr->Velocity.vx += MUL_FIXED(2000,NormalFrameTime);
1836 					if (particlePtr->Velocity.vx > 0) particlePtr->Velocity.vx = 0;
1837 				}
1838 
1839 				if (particlePtr->Velocity.vz > 0)
1840 				{
1841 					particlePtr->Velocity.vz -= MUL_FIXED(2000,NormalFrameTime);
1842 					if (particlePtr->Velocity.vz < 0) particlePtr->Velocity.vz = 0;
1843 				}
1844 				else if (particlePtr->Velocity.vz < 0)
1845 				{
1846 					particlePtr->Velocity.vz += MUL_FIXED(2000,NormalFrameTime);
1847 					if (particlePtr->Velocity.vz > 0) particlePtr->Velocity.vz = 0;
1848 				}
1849 
1850 
1851 				particlePtr->Position.vx += MUL_FIXED
1852 											(
1853 												particlePtr->Velocity.vx+
1854 												MUL_FIXED
1855 												(
1856 													-GetSin((particlePtr->Position.vz+particlePtr->Position.vy)&4095)/4,
1857 													particlePtr->Offset.vx
1858 												),
1859 												NormalFrameTime
1860 
1861 											);
1862 
1863 				particlePtr->Position.vz += MUL_FIXED
1864 											(
1865 												particlePtr->Velocity.vz+
1866 												MUL_FIXED
1867 												(
1868 													GetCos((particlePtr->Position.vx+particlePtr->Position.vy)&4095)/4,
1869 													particlePtr->Offset.vz
1870 												),
1871 												NormalFrameTime
1872 
1873 											);
1874 				particlePtr->Colour = RGBALIGHT_MAKE
1875 									  (
1876 									  	particleDescPtr->RedScale[CurrentVisionMode],
1877 									  	particleDescPtr->GreenScale[CurrentVisionMode],
1878 									  	particleDescPtr->BlueScale[CurrentVisionMode],
1879 										(particlePtr->LifeTime>>14)+17
1880 									  );
1881 				break;
1882 			}
1883 
1884 			case PARTICLE_BLACKSMOKE:
1885 			case PARTICLE_IMPACTSMOKE:
1886 			{
1887 //				particlePtr->Position.vy -= MUL_FIXED(1000+(FastRandom()&511),NormalFrameTime);
1888 				particlePtr->Position.vy += MUL_FIXED(particlePtr->Velocity.vy,NormalFrameTime);
1889 
1890 				if (particlePtr->Velocity.vy > -1300)
1891 					particlePtr->Velocity.vy -= MUL_FIXED(3000,NormalFrameTime);
1892 
1893 				if (particlePtr->Velocity.vx > 0)
1894 				{
1895 					particlePtr->Velocity.vx -= MUL_FIXED(2000,NormalFrameTime);
1896 					if (particlePtr->Velocity.vx < 0) particlePtr->Velocity.vx = 0;
1897 				}
1898 				else if (particlePtr->Velocity.vx < 0)
1899 				{
1900 					particlePtr->Velocity.vx += MUL_FIXED(2000,NormalFrameTime);
1901 					if (particlePtr->Velocity.vx > 0) particlePtr->Velocity.vx = 0;
1902 				}
1903 
1904 				if (particlePtr->Velocity.vz > 0)
1905 				{
1906 					particlePtr->Velocity.vz -= MUL_FIXED(2000,NormalFrameTime);
1907 					if (particlePtr->Velocity.vz < 0) particlePtr->Velocity.vz = 0;
1908 				}
1909 				else if (particlePtr->Velocity.vz < 0)
1910 				{
1911 					particlePtr->Velocity.vz += MUL_FIXED(2000,NormalFrameTime);
1912 					if (particlePtr->Velocity.vz > 0) particlePtr->Velocity.vz = 0;
1913 				}
1914 
1915 
1916 				particlePtr->Position.vx += MUL_FIXED
1917 											(
1918 												particlePtr->Velocity.vx+
1919 												MUL_FIXED
1920 												(
1921 													-GetSin((particlePtr->Position.vz+particlePtr->Position.vy)&4095)/4,
1922 													particlePtr->Offset.vx
1923 												),
1924 												NormalFrameTime
1925 
1926 											);
1927 
1928 				particlePtr->Position.vz += MUL_FIXED
1929 											(
1930 												particlePtr->Velocity.vz+
1931 												MUL_FIXED
1932 												(
1933 													GetCos((particlePtr->Position.vx+particlePtr->Position.vy)&4095)/4,
1934 													particlePtr->Offset.vz
1935 												),
1936 												NormalFrameTime
1937 
1938 											);
1939 
1940 				{
1941 					int colour = particlePtr->LifeTime>>11;
1942 		  			particlePtr->Colour = RGBALIGHT_MAKE(colour,colour,colour,255);
1943 				}
1944 
1945 				break;
1946 			}
1947 			case PARTICLE_GUNMUZZLE_SMOKE:
1948 			{
1949 //				particlePtr->Position.vy -= MUL_FIXED(1000+(FastRandom()&511),NormalFrameTime);
1950 				particlePtr->Position.vy += MUL_FIXED(particlePtr->Velocity.vy,NormalFrameTime);
1951 				#if 1
1952 				if (particlePtr->Velocity.vy > -1300)
1953 					particlePtr->Velocity.vy -= MUL_FIXED(1024,NormalFrameTime);
1954 
1955 				if (particlePtr->Velocity.vx > 0)
1956 				{
1957 					particlePtr->Velocity.vx -= MUL_FIXED(1024,NormalFrameTime);
1958 					if (particlePtr->Velocity.vx < 0) particlePtr->Velocity.vx = 0;
1959 				}
1960 				else if (particlePtr->Velocity.vx < 0)
1961 				{
1962 					particlePtr->Velocity.vx += MUL_FIXED(1024,NormalFrameTime);
1963 					if (particlePtr->Velocity.vx > 0) particlePtr->Velocity.vx = 0;
1964 				}
1965 
1966 				if (particlePtr->Velocity.vz > 0)
1967 				{
1968 					particlePtr->Velocity.vz -= MUL_FIXED(1024,NormalFrameTime);
1969 					if (particlePtr->Velocity.vz < 0) particlePtr->Velocity.vz = 0;
1970 				}
1971 				else if (particlePtr->Velocity.vz < 0)
1972 				{
1973 					particlePtr->Velocity.vz += MUL_FIXED(1024,NormalFrameTime);
1974 					if (particlePtr->Velocity.vz > 0) particlePtr->Velocity.vz = 0;
1975 				}
1976 				#endif
1977 
1978 				particlePtr->Position.vx += MUL_FIXED
1979 											(
1980 												particlePtr->Velocity.vx+
1981 												MUL_FIXED
1982 												(
1983 													-GetSin(((particlePtr->Position.vz+particlePtr->Position.vy)*16)&4095)/4,
1984 													particlePtr->Offset.vx
1985 												),
1986 												NormalFrameTime
1987 
1988 											);
1989 
1990 				particlePtr->Position.vz += MUL_FIXED
1991 											(
1992 												particlePtr->Velocity.vz+
1993 												MUL_FIXED
1994 												(
1995 													GetCos(((particlePtr->Position.vx+particlePtr->Position.vy)*16)&4095)/4,
1996 													particlePtr->Offset.vz
1997 												),
1998 												NormalFrameTime
1999 
2000 											);
2001 
2002 				particlePtr->Size = MUL_FIXED(ONE_FIXED-particlePtr->LifeTime,48);
2003 				{
2004 					int colour = particlePtr->LifeTime>>11;
2005 		  			particlePtr->Colour = RGBALIGHT_MAKE(32,32,32,colour);
2006 				}
2007 
2008 				break;
2009 			}
2010 			case PARTICLE_FLAME:
2011 			case PARTICLE_NONDAMAGINGFLAME:
2012 			case PARTICLE_PARGEN_FLAME:
2013 			{
2014 				particlePtr->Size = 20+(ONE_FIXED/2-particlePtr->LifeTime)/64;
2015 				if (particlePtr->LifeTime==ONE_FIXED/2)
2016 				{
2017 					switch (CurrentVisionMode)
2018 					{
2019 						default:
2020 						case VISION_MODE_NORMAL:
2021 						{
2022 							particlePtr->Colour = RGBALIGHT_MAKE(16,16,128,(particlePtr->LifeTime>>8)|9);
2023 							break;
2024 						}
2025 						case VISION_MODE_IMAGEINTENSIFIER:
2026 						{
2027 							particlePtr->Colour = RGBALIGHT_MAKE(0,32,0,(particlePtr->LifeTime>>8)|9);
2028 							break;
2029 						}
2030 						case VISION_MODE_PRED_THERMAL:
2031 						{
2032 							particlePtr->Colour = RGBALIGHT_MAKE(0,0,128,(particlePtr->LifeTime>>8)|9);
2033 						  	break;
2034 						}
2035 						case VISION_MODE_PRED_SEEALIENS:
2036 						case VISION_MODE_PRED_SEEPREDTECH:
2037 						{
2038 							particlePtr->Colour = RGBALIGHT_MAKE(192,128,32,(particlePtr->LifeTime>>8)|9);
2039 						  	break;
2040 						}
2041 					}
2042 				}
2043 				else
2044 				{
2045 					particlePtr->Colour = RGBALIGHT_MAKE
2046 										  (
2047 										  	particleDescPtr->RedScale[CurrentVisionMode],
2048 										  	particleDescPtr->GreenScale[CurrentVisionMode],
2049 										  	particleDescPtr->BlueScale[CurrentVisionMode],
2050 											(particlePtr->LifeTime>>8)|9
2051 										  );
2052 				}
2053 
2054 
2055 				break;
2056 			}
2057 			case PARTICLE_FIRE:
2058 			{
2059 				particlePtr->Size = 300-(FastRandom()&127);
2060 				break;
2061 			}
2062 			case PARTICLE_EXPLOSIONFIRE:
2063 			{
2064 				VECTORCH obstacleNormal;
2065 				int moduleIndex;
2066 
2067 				if(ParticleDynamics(particlePtr,&obstacleNormal,&moduleIndex) && !(FastRandom()&15))
2068 				{
2069 					MakeDecal(DECAL_SCORCHED,&obstacleNormal,&(particlePtr->Position),moduleIndex);
2070 					particlePtr->LifeTime=0;
2071 				}
2072 				break;
2073 			}
2074 			case PARTICLE_MOLOTOVFLAME:
2075 			{
2076 				VECTORCH obstacleNormal;
2077 				int moduleIndex;
2078 
2079 				particlePtr->Colour = RGBALIGHT_MAKE
2080 									  (
2081 									  	particleDescPtr->RedScale[CurrentVisionMode],
2082 									  	particleDescPtr->GreenScale[CurrentVisionMode],
2083 									  	particleDescPtr->BlueScale[CurrentVisionMode],
2084 										(particlePtr->LifeTime>>10)|9
2085 									  );
2086 
2087 				particlePtr->Velocity.vy += MUL_FIXED(8000,NormalFrameTime);
2088 				if(ParticleDynamics(particlePtr,&obstacleNormal,&moduleIndex))
2089 				{
2090 					#if 0
2091 					int magOfPerpImp = DotProduct(&obstacleNormal,&(particlePtr->Velocity));
2092 					particlePtr->Velocity.vx -= MUL_FIXED(obstacleNormal.vx, magOfPerpImp);
2093 					particlePtr->Velocity.vy -= MUL_FIXED(obstacleNormal.vy, magOfPerpImp);
2094 					particlePtr->Velocity.vz -= MUL_FIXED(obstacleNormal.vz, magOfPerpImp);
2095 					#endif
2096 				}
2097 				particlePtr->Size = 800-(FastRandom()&255);
2098 				break;
2099 			}
2100 
2101 
2102 			case PARTICLE_NONCOLLIDINGFLAME:
2103 			{
2104 				particlePtr->Size = 20+(ONE_FIXED/2-particlePtr->LifeTime)/64;
2105 				break;
2106 			}
2107 			case PARTICLE_ORANGE_SPARK:
2108 			{
2109 				particlePtr->Offset = particlePtr->Position;
2110 
2111 				particlePtr->Position.vx += MUL_FIXED(particlePtr->Velocity.vx,NormalFrameTime);
2112 				particlePtr->Velocity.vx -= MUL_FIXED(particlePtr->Velocity.vx,NormalFrameTime);
2113 				particlePtr->Position.vy += MUL_FIXED(particlePtr->Velocity.vy,NormalFrameTime);
2114 				particlePtr->Velocity.vy -= MUL_FIXED(particlePtr->Velocity.vy,NormalFrameTime);
2115 				particlePtr->Position.vz += MUL_FIXED(particlePtr->Velocity.vz,NormalFrameTime);
2116 				particlePtr->Velocity.vz -= MUL_FIXED(particlePtr->Velocity.vz,NormalFrameTime);
2117 
2118 				{
2119 					int l = particlePtr->LifeTime*8;
2120 					l = MUL_FIXED(255,l);
2121 
2122 					if (l>255)
2123 					{
2124 						switch (CurrentVisionMode)
2125 						{
2126 							default:
2127 							case VISION_MODE_NORMAL:
2128 							{
2129 			  					particlePtr->Colour = RGBALIGHT_MAKE(255,255,l-255,255);
2130 								break;
2131 							}
2132 							case VISION_MODE_IMAGEINTENSIFIER:
2133 							{
2134 			  					particlePtr->Colour = RGBALIGHT_MAKE(l/2,l/2,l/2,255);
2135 								break;
2136 							}
2137 							case VISION_MODE_PRED_THERMAL:
2138 							case VISION_MODE_PRED_SEEALIENS:
2139 							case VISION_MODE_PRED_SEEPREDTECH:
2140 							{
2141 			  					particlePtr->Colour = RGBALIGHT_MAKE(l-255,255,255,255);
2142 							  	break;
2143 							}
2144 						}
2145 					}
2146 					else
2147 					{
2148 						switch (CurrentVisionMode)
2149 						{
2150 							default:
2151 							case VISION_MODE_NORMAL:
2152 							{
2153 			  					particlePtr->Colour = RGBALIGHT_MAKE(255,l,0,l);
2154 								break;
2155 							}
2156 							case VISION_MODE_IMAGEINTENSIFIER:
2157 							{
2158 			  					particlePtr->Colour = RGBALIGHT_MAKE(l/2,l/2,128,l);
2159 								break;
2160 							}
2161 							case VISION_MODE_PRED_THERMAL:
2162 							case VISION_MODE_PRED_SEEALIENS:
2163 							case VISION_MODE_PRED_SEEPREDTECH:
2164 							{
2165 			  					particlePtr->Colour = RGBALIGHT_MAKE(0,l,l,l);
2166 							  	break;
2167 							}
2168 						}
2169 					}
2170 				}
2171 
2172 				break;
2173 			}
2174 			case PARTICLE_ORANGE_PLASMA:
2175 			{
2176 				particlePtr->Offset = particlePtr->Position;
2177 
2178 				particlePtr->Position.vx += MUL_FIXED(particlePtr->Velocity.vx,NormalFrameTime);
2179 				particlePtr->Velocity.vx -= MUL_FIXED(particlePtr->Velocity.vx,NormalFrameTime);
2180 				particlePtr->Position.vy += MUL_FIXED(particlePtr->Velocity.vy,NormalFrameTime);
2181 				particlePtr->Velocity.vy -= MUL_FIXED(particlePtr->Velocity.vy,NormalFrameTime);
2182 				particlePtr->Position.vz += MUL_FIXED(particlePtr->Velocity.vz,NormalFrameTime);
2183 				particlePtr->Velocity.vz -= MUL_FIXED(particlePtr->Velocity.vz,NormalFrameTime);
2184 
2185 				{
2186 					int l = particlePtr->LifeTime*16;
2187 					l = MUL_FIXED(255,l);
2188 
2189 					if (l>255)
2190 					{
2191 						switch (CurrentVisionMode)
2192 						{
2193 							default:
2194 							case VISION_MODE_NORMAL:
2195 							{
2196 			  					particlePtr->Colour = RGBALIGHT_MAKE(255,255,l-255,255);
2197 								break;
2198 							}
2199 							case VISION_MODE_IMAGEINTENSIFIER:
2200 							{
2201 			  					particlePtr->Colour = RGBALIGHT_MAKE(l/2,l/2,l/2,255);
2202 								break;
2203 							}
2204 							case VISION_MODE_PRED_THERMAL:
2205 							case VISION_MODE_PRED_SEEALIENS:
2206 							case VISION_MODE_PRED_SEEPREDTECH:
2207 							{
2208 			  					particlePtr->Colour = RGBALIGHT_MAKE(l-255,255,255,255);
2209 							  	break;
2210 							}
2211 						}
2212 					}
2213 					else
2214 					{
2215 						switch (CurrentVisionMode)
2216 						{
2217 							default:
2218 							case VISION_MODE_NORMAL:
2219 							{
2220 			  					particlePtr->Colour = RGBALIGHT_MAKE(255,l,0,l);
2221 								break;
2222 							}
2223 							case VISION_MODE_IMAGEINTENSIFIER:
2224 							{
2225 			  					particlePtr->Colour = RGBALIGHT_MAKE(l/2,l/2,128,l);
2226 								break;
2227 							}
2228 							case VISION_MODE_PRED_THERMAL:
2229 							case VISION_MODE_PRED_SEEALIENS:
2230 							case VISION_MODE_PRED_SEEPREDTECH:
2231 							{
2232 			  					particlePtr->Colour = RGBALIGHT_MAKE(0,l,l,l);
2233 							  	break;
2234 							}
2235 						}
2236 					}
2237 				}
2238 
2239 				break;
2240 			}
2241 			case PARTICLE_RICOCHET_SPARK:
2242 			{
2243 				particlePtr->Offset = particlePtr->Position;
2244 
2245 				particlePtr->Position.vx += MUL_FIXED(particlePtr->Velocity.vx,NormalFrameTime);
2246 				particlePtr->Velocity.vx -= MUL_FIXED(particlePtr->Velocity.vx,NormalFrameTime);
2247 				particlePtr->Position.vy += MUL_FIXED(particlePtr->Velocity.vy,NormalFrameTime);
2248 				particlePtr->Velocity.vy -= MUL_FIXED(particlePtr->Velocity.vy,NormalFrameTime);
2249 				particlePtr->Position.vz += MUL_FIXED(particlePtr->Velocity.vz,NormalFrameTime);
2250 				particlePtr->Velocity.vz -= MUL_FIXED(particlePtr->Velocity.vz,NormalFrameTime);
2251 
2252 				{
2253 					int l = particlePtr->LifeTime*8;
2254 					l = MUL_FIXED(255,l);
2255 
2256 					if (l>255)
2257 					{
2258 						switch (CurrentVisionMode)
2259 						{
2260 							default:
2261 							case VISION_MODE_NORMAL:
2262 							{
2263 			  					particlePtr->Colour = RGBALIGHT_MAKE(255,255,l-255,255);
2264 								break;
2265 							}
2266 							case VISION_MODE_IMAGEINTENSIFIER:
2267 							{
2268 			  					particlePtr->Colour = RGBALIGHT_MAKE(l/2,l/2,l/2,255);
2269 								break;
2270 							}
2271 							case VISION_MODE_PRED_THERMAL:
2272 							{
2273 			  					particlePtr->Colour = RGBALIGHT_MAKE(l-255,255,255,255);
2274 							  	break;
2275 							}
2276 							case VISION_MODE_PRED_SEEALIENS:
2277 							case VISION_MODE_PRED_SEEPREDTECH:
2278 							{
2279 			  					particlePtr->Colour = RGBALIGHT_MAKE(255,255,l-255,255);
2280 							  	break;
2281 							}
2282 						}
2283 					}
2284 					else
2285 					{
2286 						switch (CurrentVisionMode)
2287 						{
2288 							default:
2289 							case VISION_MODE_NORMAL:
2290 							{
2291 			  					particlePtr->Colour = RGBALIGHT_MAKE(255,l,0,l);
2292 								break;
2293 							}
2294 							case VISION_MODE_IMAGEINTENSIFIER:
2295 							{
2296 			  					particlePtr->Colour = RGBALIGHT_MAKE(l/2,l/2,128,l);
2297 								break;
2298 							}
2299 							case VISION_MODE_PRED_THERMAL:
2300 							{
2301 			  					particlePtr->Colour = RGBALIGHT_MAKE(0,l,l,l);
2302 							  	break;
2303 							}
2304 							case VISION_MODE_PRED_SEEALIENS:
2305 							case VISION_MODE_PRED_SEEPREDTECH:
2306 							{
2307 			  					particlePtr->Colour = RGBALIGHT_MAKE(l,l,0,l);
2308 							  	break;
2309 							}
2310 
2311 						}
2312 					}
2313 				}
2314 
2315 				break;
2316 			}
2317 
2318 			case PARTICLE_SPARK:
2319 			{
2320 				particlePtr->Offset = particlePtr->Position;
2321 
2322 				particlePtr->Position.vx += MUL_FIXED(particlePtr->Velocity.vx,NormalFrameTime);
2323 				particlePtr->Velocity.vx -= MUL_FIXED(particlePtr->Velocity.vx,NormalFrameTime);
2324 				particlePtr->Position.vy += MUL_FIXED(particlePtr->Velocity.vy,NormalFrameTime);
2325 				particlePtr->Velocity.vy += MUL_FIXED(5000,NormalFrameTime);
2326 				particlePtr->Position.vz += MUL_FIXED(particlePtr->Velocity.vz,NormalFrameTime);
2327 				particlePtr->Velocity.vz -= MUL_FIXED(particlePtr->Velocity.vz,NormalFrameTime);
2328 
2329 				{
2330 					int l = particlePtr->LifeTime*2;
2331 					l = MUL_FIXED(255,l);
2332 
2333 					if (l>255)
2334 					{
2335 						switch (CurrentVisionMode)
2336 						{
2337 							default:
2338 							case VISION_MODE_NORMAL:
2339 							{
2340 			  					particlePtr->Colour = RGBALIGHT_MAKE(l/2,l/2,255,255);
2341 								break;
2342 							}
2343 							case VISION_MODE_IMAGEINTENSIFIER:
2344 							{
2345 			  					particlePtr->Colour = RGBALIGHT_MAKE(l/2,l/2,l/2,255);
2346 								break;
2347 							}
2348 							case VISION_MODE_PRED_THERMAL:
2349 							{
2350 			  					particlePtr->Colour = RGBALIGHT_MAKE(l-255,255,255,255);
2351 							  	break;
2352 							}
2353 							case VISION_MODE_PRED_SEEALIENS:
2354 							case VISION_MODE_PRED_SEEPREDTECH:
2355 							{
2356 			  					particlePtr->Colour = RGBALIGHT_MAKE(255,255,l-255,255);
2357 							  	break;
2358 							}
2359 						}
2360 					}
2361 					else
2362 					{
2363 						switch (CurrentVisionMode)
2364 						{
2365 							default:
2366 							case VISION_MODE_NORMAL:
2367 							{
2368 			  					particlePtr->Colour = RGBALIGHT_MAKE(l/2,l/2,l,l);
2369 								break;
2370 							}
2371 							case VISION_MODE_IMAGEINTENSIFIER:
2372 							{
2373 			  					particlePtr->Colour = RGBALIGHT_MAKE(l/2,l/2,128,l);
2374 								break;
2375 							}
2376 							case VISION_MODE_PRED_THERMAL:
2377 							{
2378 			  					particlePtr->Colour = RGBALIGHT_MAKE(0,l,l,l);
2379 							  	break;
2380 							}
2381 							case VISION_MODE_PRED_SEEALIENS:
2382 							case VISION_MODE_PRED_SEEPREDTECH:
2383 							{
2384 			  					particlePtr->Colour = RGBALIGHT_MAKE(l,l,0,l);
2385 							  	break;
2386 							}
2387 						}
2388 					}
2389 				}
2390 				break;
2391 			}
2392 
2393 			case PARTICLE_DEWLINE:
2394 			{
2395 				int l = (particlePtr->LifeTime)/64/4;
2396 				if (l>255)
2397 				{
2398 					switch (CurrentVisionMode)
2399 					{
2400 						default:
2401 						case VISION_MODE_NORMAL:
2402 						{
2403 							particlePtr->Colour = RGBALIGHT_MAKE(255,255,255,255);
2404 							break;
2405 						}
2406 						case VISION_MODE_IMAGEINTENSIFIER:
2407 						{
2408 							particlePtr->Colour = RGBALIGHT_MAKE(0,255,0,255);
2409 							break;
2410 						}
2411 						case VISION_MODE_PRED_THERMAL:
2412 						{
2413 							particlePtr->Colour = RGBALIGHT_MAKE(255,0,0,255);
2414 						  	break;
2415 						}
2416 						case VISION_MODE_PRED_SEEALIENS:
2417 						case VISION_MODE_PRED_SEEPREDTECH:
2418 						{
2419 							particlePtr->Colour = RGBALIGHT_MAKE(255,128,64,255);
2420 						  	break;
2421 						}
2422 					}
2423 				}
2424 				else
2425 				{
2426 			 		particlePtr->Position.vx += MUL_FIXED(particlePtr->Velocity.vx,NormalFrameTime);
2427 			 		particlePtr->Position.vy += MUL_FIXED(particlePtr->Velocity.vy,NormalFrameTime);
2428 			 		particlePtr->Position.vz += MUL_FIXED(particlePtr->Velocity.vz,NormalFrameTime);
2429 					switch (CurrentVisionMode)
2430 					{
2431 						default:
2432 						case VISION_MODE_NORMAL:
2433 						{
2434 							particlePtr->Colour = RGBALIGHT_MAKE(255,128+(l/2),64+((3*l)/4),l);
2435 							break;
2436 						}
2437 						case VISION_MODE_IMAGEINTENSIFIER:
2438 						{
2439 							particlePtr->Colour = RGBALIGHT_MAKE(l/2,l/2,l/2,l);
2440 							break;
2441 						}
2442 						case VISION_MODE_PRED_THERMAL:
2443 						{
2444 							particlePtr->Colour = RGBALIGHT_MAKE(255,l/2,l/2,l);
2445 						  	break;
2446 						}
2447 						case VISION_MODE_PRED_SEEALIENS:
2448 						case VISION_MODE_PRED_SEEPREDTECH:
2449 						{
2450 							particlePtr->Colour = RGBALIGHT_MAKE(255,l/2,l/4,l);
2451 						  	break;
2452 						}
2453 					}
2454 					particlePtr->Size = 32+(FastRandom()&31);
2455 				}
2456 
2457 				break;
2458 			}
2459 			case PARTICLE_PLASMATRAIL:
2460 			{
2461 				int l = (particlePtr->LifeTime)/64/4;
2462 				if (l>255)
2463 				{
2464 					switch (CurrentVisionMode)
2465 					{
2466 						default:
2467 						case VISION_MODE_NORMAL:
2468 						{
2469 							particlePtr->Colour = RGBALIGHT_MAKE(0,0,255,255);
2470 							break;
2471 						}
2472 						case VISION_MODE_IMAGEINTENSIFIER:
2473 						{
2474 							particlePtr->Colour = RGBALIGHT_MAKE(0,255,0,255);
2475 							break;
2476 						}
2477 						case VISION_MODE_PRED_THERMAL:
2478 						{
2479 							particlePtr->Colour = RGBALIGHT_MAKE(0,0,255,255);
2480 						  	break;
2481 						}
2482 						case VISION_MODE_PRED_SEEALIENS:
2483 						case VISION_MODE_PRED_SEEPREDTECH:
2484 						{
2485 							particlePtr->Colour = RGBALIGHT_MAKE(255,128,64,255);
2486 						  	break;
2487 						}
2488 					}
2489 				}
2490 				else
2491 				{
2492 			 		particlePtr->Position.vx += MUL_FIXED(particlePtr->Velocity.vx,NormalFrameTime);
2493 			 		particlePtr->Position.vy += MUL_FIXED(particlePtr->Velocity.vy,NormalFrameTime);
2494 			 		particlePtr->Position.vz += MUL_FIXED(particlePtr->Velocity.vz,NormalFrameTime);
2495 					switch (CurrentVisionMode)
2496 					{
2497 						default:
2498 						case VISION_MODE_NORMAL:
2499 						{
2500 							particlePtr->Colour = RGBALIGHT_MAKE(l/4,l/2,255,l);
2501 							break;
2502 						}
2503 						case VISION_MODE_IMAGEINTENSIFIER:
2504 						{
2505 							particlePtr->Colour = RGBALIGHT_MAKE(l/2,l/2,l/2,l);
2506 							break;
2507 						}
2508 						case VISION_MODE_PRED_THERMAL:
2509 						{
2510 							particlePtr->Colour = RGBALIGHT_MAKE(l/4,l/2,255,l);
2511 						  	break;
2512 						}
2513 						case VISION_MODE_PRED_SEEALIENS:
2514 						case VISION_MODE_PRED_SEEPREDTECH:
2515 						{
2516 							particlePtr->Colour = RGBALIGHT_MAKE(255,l/2,l/4,l);
2517 						  	break;
2518 						}
2519 					}
2520 					particlePtr->Size = 32+(FastRandom()&31);
2521 				}
2522 
2523 				break;
2524 			}
2525 
2526 			case PARTICLE_WATERSPRAY:
2527 			{
2528 				particlePtr->Colour = RGBALIGHT_MAKE
2529 									  (
2530 									  	particleDescPtr->RedScale[CurrentVisionMode],
2531 									  	particleDescPtr->GreenScale[CurrentVisionMode],
2532 									  	particleDescPtr->BlueScale[CurrentVisionMode],
2533 									  	particleDescPtr->Alpha
2534 									  );
2535 				particlePtr->Position.vx += MUL_FIXED(particlePtr->Velocity.vx,NormalFrameTime);
2536 				particlePtr->Position.vy += MUL_FIXED(particlePtr->Velocity.vy,NormalFrameTime);
2537 				particlePtr->Position.vz += MUL_FIXED(particlePtr->Velocity.vz,NormalFrameTime);
2538 				particlePtr->Velocity.vy += MUL_FIXED(10000,NormalFrameTime);
2539 
2540 				break;
2541 			}
2542 			case PARTICLE_WATERFALLSPRAY:
2543 			{
2544 				extern int WaterFallBase;
2545 				int y = particlePtr->Position.vy;
2546 				particlePtr->Colour = RGBALIGHT_MAKE
2547 									  (
2548 									  	particleDescPtr->RedScale[CurrentVisionMode],
2549 									  	particleDescPtr->GreenScale[CurrentVisionMode],
2550 									  	particleDescPtr->BlueScale[CurrentVisionMode],
2551 									  	particleDescPtr->Alpha
2552 									  );
2553 
2554 				particlePtr->Position.vx += MUL_FIXED(particlePtr->Velocity.vx,NormalFrameTime);
2555 				particlePtr->Position.vy += MUL_FIXED(particlePtr->Velocity.vy,NormalFrameTime);
2556 				particlePtr->Position.vz += MUL_FIXED(particlePtr->Velocity.vz,NormalFrameTime);
2557 
2558 				particlePtr->Velocity.vy += MUL_FIXED(10000+(FastRandom()&511),NormalFrameTime);
2559 
2560 				if(particlePtr->Position.vz < 54885 && particlePtr->Position.vx < 179427)
2561 				{
2562 					if (y<4742 && particlePtr->Position.vy>4742)
2563 					{
2564 						particlePtr->Position.vy=4742;
2565 						particlePtr->Velocity.vy=-MUL_FIXED(particlePtr->Velocity.vy,ONE_FIXED/2-(FastRandom()&16384));
2566 					}
2567 				}
2568 				else if (particlePtr->Position.vz < 58600)
2569 				{
2570 					int l = DIV_FIXED(particlePtr->Position.vz - 54885,58600-54885);
2571 
2572 					if (particlePtr->Position.vx < 179427 - MUL_FIXED(l,179427-175545))
2573 					{
2574 						int yThreshold = 4742 + MUL_FIXED(l,8635-4742);
2575 						if (y<yThreshold && particlePtr->Position.vy>yThreshold)
2576 						{
2577 							particlePtr->Position.vy=yThreshold;
2578 							particlePtr->Velocity.vy=-MUL_FIXED(particlePtr->Velocity.vy,ONE_FIXED/2-(FastRandom()&16384));
2579 						}
2580 					}
2581 				}
2582 
2583 				particlePtr->Offset.vx = particlePtr->Position.vx - particlePtr->Velocity.vx/4;
2584 				particlePtr->Offset.vy = particlePtr->Position.vy - particlePtr->Velocity.vy/4;
2585 				particlePtr->Offset.vz = particlePtr->Position.vz - particlePtr->Velocity.vz/4;
2586 
2587 				if (particlePtr->Position.vy>WaterFallBase)
2588 				{
2589 					particlePtr->LifeTime = 0;
2590 				}
2591 
2592 				break;
2593 			}
2594 			case PARTICLE_FLECHETTE:
2595 			case PARTICLE_FLECHETTE_NONDAMAGING:
2596 			{
2597 				{
2598 					int l = particlePtr->LifeTime/4;
2599 					l = MUL_FIXED(255,l);
2600 
2601 					if (l>255)
2602 					{
2603 						switch (CurrentVisionMode)
2604 						{
2605 							default:
2606 							case VISION_MODE_NORMAL:
2607 							{
2608 			  					particlePtr->Colour = RGBALIGHT_MAKE((l-255)/2+32,0,0,255);
2609 								break;
2610 							}
2611 							case VISION_MODE_IMAGEINTENSIFIER:
2612 							{
2613 			  					particlePtr->Colour = RGBALIGHT_MAKE(l/2,l/2,l/2,255);
2614 								break;
2615 							}
2616 							case VISION_MODE_PRED_THERMAL:
2617 							case VISION_MODE_PRED_SEEALIENS:
2618 							case VISION_MODE_PRED_SEEPREDTECH:
2619 							{
2620 			  					particlePtr->Colour = RGBALIGHT_MAKE(l-255,255,255,255);
2621 							  	break;
2622 							}
2623 						}
2624 					}
2625 					else
2626 					{
2627 						switch (CurrentVisionMode)
2628 						{
2629 							default:
2630 							case VISION_MODE_NORMAL:
2631 							{
2632 			  					particlePtr->Colour = RGBALIGHT_MAKE(32,0,0,l);
2633 								break;
2634 							}
2635 							case VISION_MODE_IMAGEINTENSIFIER:
2636 							{
2637 			  					particlePtr->Colour = RGBALIGHT_MAKE(l/2,l/2,l/2,l);
2638 								break;
2639 							}
2640 							case VISION_MODE_PRED_THERMAL:
2641 							case VISION_MODE_PRED_SEEALIENS:
2642 							case VISION_MODE_PRED_SEEPREDTECH:
2643 							{
2644 			  					particlePtr->Colour = RGBALIGHT_MAKE(0,l,l,l);
2645 							  	break;
2646 							}
2647 						}
2648 					}
2649 				}
2650 
2651 				if (particlePtr->Offset.vy)//particlePtr->Velocity.vx || particlePtr->Velocity.vy || particlePtr->Velocity.vz)
2652 				{
2653 					VECTORCH obstacleNormal;
2654 					int moduleIndex;
2655 					VECTORCH velocityBackup = particlePtr->Velocity;
2656 
2657 					if(ParticleDynamics(particlePtr,&obstacleNormal,&moduleIndex))
2658 					{
2659 						if(moduleIndex==-1)
2660 						{
2661 							particlePtr->LifeTime=0;
2662 						}
2663 						else
2664 						{
2665 							particlePtr->Offset.vy = 0;
2666 							particlePtr->Velocity = velocityBackup;
2667 							particlePtr->Position.vx += particlePtr->Velocity.vx>>10;
2668 							particlePtr->Position.vy += particlePtr->Velocity.vy>>10;
2669 							particlePtr->Position.vz += particlePtr->Velocity.vz>>10;
2670 						}
2671 					}
2672 				}
2673 
2674 				break;
2675 			}
2676 			case PARTICLE_SMOKECLOUD:
2677 			{
2678 				if (particlePtr->LifeTime<ONE_FIXED*8)
2679 				{
2680 					int colour = (particlePtr->LifeTime/(8*256*4));
2681 		  			particlePtr->Colour = RGBALIGHT_MAKE(255,255,255,colour);
2682 				}
2683 				else
2684 				{
2685 		  			particlePtr->Colour = RGBALIGHT_MAKE(255,255,255,64);
2686 				}
2687 				particlePtr->Size = 1000+500-(particlePtr->LifeTime>>10);
2688 
2689 				AddEffectsOfForceGenerators(&particlePtr->Position,&particlePtr->Velocity,32*64);
2690 
2691 				break;
2692 			}
2693 			case PARTICLE_BLUEPLASMASPHERE:
2694 			{
2695 				break;
2696 			}
2697 			case PARTICLE_ELECTRICALPLASMASPHERE:
2698 			{
2699 				{
2700 					int colour = (particlePtr->LifeTime/128);
2701 					particlePtr->Size = 200+(ONE_FIXED-particlePtr->LifeTime)/16;
2702 		  			particlePtr->Colour = RGBALIGHT_MAKE(255,255,255,colour);
2703 				}
2704 				break;
2705 			}
2706 			case PARTICLE_PREDPISTOL_FLECHETTE:
2707 			case PARTICLE_PREDPISTOL_FLECHETTE_NONDAMAGING:
2708 			{
2709 				/* CDF 7/12/98 Placeholder till Kevin gets better. */
2710 
2711 				/* Based on PARTICLE_SPARK for vision... */
2712 				particlePtr->Offset = particlePtr->Position;
2713 
2714 				{
2715 					int l = particlePtr->LifeTime*2;
2716 					l = MUL_FIXED(255,l);
2717 
2718 					if (l>255)
2719 					{
2720 						switch (CurrentVisionMode)
2721 						{
2722 							default:
2723 							case VISION_MODE_NORMAL:
2724 							{
2725 			  					particlePtr->Colour = RGBALIGHT_MAKE(l/2,l/2,255,255);
2726 								break;
2727 							}
2728 							case VISION_MODE_IMAGEINTENSIFIER:
2729 							{
2730 			  					particlePtr->Colour = RGBALIGHT_MAKE(l/2,l/2,l/2,255);
2731 								break;
2732 							}
2733 							case VISION_MODE_PRED_THERMAL:
2734 							{
2735 			  					particlePtr->Colour = RGBALIGHT_MAKE(l-255,255,255,255);
2736 							  	break;
2737 							}
2738 							case VISION_MODE_PRED_SEEALIENS:
2739 							case VISION_MODE_PRED_SEEPREDTECH:
2740 							{
2741 			  					particlePtr->Colour = RGBALIGHT_MAKE(255,255,l-255,255);
2742 							  	break;
2743 							}
2744 						}
2745 					}
2746 					else
2747 					{
2748 						switch (CurrentVisionMode)
2749 						{
2750 							default:
2751 							case VISION_MODE_NORMAL:
2752 							{
2753 			  					particlePtr->Colour = RGBALIGHT_MAKE(l/2,l/2,l,l);
2754 								break;
2755 							}
2756 							case VISION_MODE_IMAGEINTENSIFIER:
2757 							{
2758 			  					particlePtr->Colour = RGBALIGHT_MAKE(l/2,l/2,128,l);
2759 								break;
2760 							}
2761 							case VISION_MODE_PRED_THERMAL:
2762 							{
2763 			  					particlePtr->Colour = RGBALIGHT_MAKE(0,l,l,l);
2764 							  	break;
2765 							}
2766 							case VISION_MODE_PRED_SEEALIENS:
2767 							case VISION_MODE_PRED_SEEPREDTECH:
2768 							{
2769 			  					particlePtr->Colour = RGBALIGHT_MAKE(l,l,0,l);
2770 							  	break;
2771 							}
2772 						}
2773 					}
2774 				}
2775 
2776 				{
2777 					VECTORCH obstacleNormal;
2778 					int moduleIndex;
2779 
2780 					if(ParticleDynamics(particlePtr,&obstacleNormal,&moduleIndex))
2781 					{
2782 						if (moduleIndex!=-1)
2783 						{
2784 							MakeDecal(DECAL_SCORCHED,&obstacleNormal,&(particlePtr->Position),moduleIndex);
2785 						}
2786 						particlePtr->LifeTime=0;
2787 					}
2788 				}
2789 				break;
2790 			}
2791 			case PARTICLE_TRACER:
2792 			{
2793 				break;
2794 			}
2795 			default:
2796 			{
2797 				/* particle initialised wrongly */
2798 				LOCALASSERT(0);
2799 				break;
2800 			}
2801 		}
2802 		particlePtr++;
2803 	}
2804 
2805 	//
2806 	PostLandscapeRendering();
2807 	D3D_DecalSystem_Setup();
2808 	OutputTranslucentPolyList();
2809 
2810 	i = NumActiveParticles;
2811 	particlePtr = ParticleStorage;
2812 	while(i--)
2813 	{
2814 		particlePtr->LifeTime -= NormalFrameTime;
2815 
2816 		if (particlePtr->LifeTime<=0)
2817 		{
2818 			enum PARTICLE_ID particleID = particlePtr->ParticleID;
2819 			if( (particleID == PARTICLE_ALIEN_BLOOD) || (particleID == PARTICLE_PREDATOR_BLOOD) || (particleID==PARTICLE_HUMAN_BLOOD) || (particleID == PARTICLE_ANDROID_BLOOD))
2820 			{
2821 				NumberOfBloodParticles--;
2822 				LOCALASSERT(NumberOfBloodParticles>=0);
2823 			}
2824 
2825 			if ((particleID == PARTICLE_NONCOLLIDINGFLAME) && (FastRandom()&65535)<4096)
2826 			{
2827 				VECTORCH zero = {0,0,0};
2828 				MakeParticle(&(particlePtr->Position),&zero,PARTICLE_IMPACTSMOKE);
2829 			}
2830 			else if ((particleID == PARTICLE_MOLOTOVFLAME) && (FastRandom()&65535)<4096)
2831 			{
2832 				VECTORCH zero = {0,0,0};
2833 				MakeParticle(&(particlePtr->Position),&zero,PARTICLE_IMPACTSMOKE);
2834 			}
2835 
2836 
2837 			DeallocateParticle(particlePtr);
2838 		}
2839 		else
2840 		{
2841 			particlePtr++;
2842 		}
2843 	}
2844 
2845 	{
2846 		extern int NumOnScreenBlocks;
2847 		extern DISPLAYBLOCK *OnScreenBlockList[];
2848 		int numOfObjects = NumOnScreenBlocks;
2849 		while(numOfObjects)
2850 		{
2851 			DISPLAYBLOCK *objectPtr = OnScreenBlockList[--numOfObjects];
2852 			STRATEGYBLOCK *sbPtr = objectPtr->ObStrategyBlock;
2853 
2854 			if (!objectPtr->ObShape && objectPtr->SfxPtr)
2855 			{
2856 				DrawSfxObject(objectPtr);
2857 			}
2858 			if (objectPtr->HModelControlBlock)
2859 			{
2860 				SECTION_DATA *firstSectionPtr=objectPtr->HModelControlBlock->section_data;
2861 				ScanHModelForDecals(objectPtr,firstSectionPtr);
2862 			}
2863 			if (sbPtr)
2864 			{
2865 				switch(sbPtr->I_SBtype)
2866 				{
2867 					case I_BehaviourPlacedLight:
2868 					{
2869 						PLACED_LIGHT_BEHAV_BLOCK* pl_bhv = sbPtr->SBdataptr;
2870 					   	GLOBALASSERT(pl_bhv);
2871 						GLOBALASSERT(sbPtr->containingModule);
2872 
2873 	  					if (LocalDetailLevels.DrawLightCoronas
2874 	  						&& pl_bhv->has_corona
2875 	  						&& pl_bhv->light->LightBright
2876 	  						&& (ModuleCurrVisArray[sbPtr->containingModule->m_index]==2)
2877 	  						&& (pl_bhv->light->RedScale
2878 							 || pl_bhv->light->GreenScale
2879 	  					     || pl_bhv->light->BlueScale)
2880 	  						)
2881 						{
2882 							VECTORCH position=pl_bhv->corona_location;
2883 							RotateVector(&position,&objectPtr->ObMat);
2884 							position.vx += objectPtr->ObWorld.vx;
2885 							position.vy += objectPtr->ObWorld.vy;
2886 							position.vz += objectPtr->ObWorld.vz;
2887 
2888 							if (CameraCanSeeThisPosition_WithIgnore(objectPtr,&position))
2889 							{
2890 								LIGHTBLOCK *lPtr = pl_bhv->light;
2891 								int colour;
2892 								switch (CurrentVisionMode)
2893 								{
2894 									default:
2895 									case VISION_MODE_NORMAL:
2896 									{
2897 										int r = MUL_FIXED(lPtr->RedScale,lPtr->LightBright)>>8;
2898 										int g = MUL_FIXED(lPtr->GreenScale,lPtr->LightBright)>>8;
2899 										int b = MUL_FIXED(lPtr->BlueScale,lPtr->LightBright)>>8;
2900 										if (r>255) r=255;
2901 										if (g>255) g=255;
2902 										if (b>255) b=255;
2903 										colour = 0xff000000+(r<<16)+(g<<8)+(b);
2904 										break;
2905 									}
2906 									case VISION_MODE_IMAGEINTENSIFIER:
2907 									{
2908 										colour = 0xffffffff;
2909 										break;
2910 									}
2911 									case VISION_MODE_PRED_THERMAL:
2912 									case VISION_MODE_PRED_SEEALIENS:
2913 									case VISION_MODE_PRED_SEEPREDTECH:
2914 									{
2915 										int b = MUL_FIXED
2916 												(
2917 													lPtr->RedScale+lPtr->GreenScale+lPtr->BlueScale,
2918 													lPtr->LightBright
2919 												)>>10;
2920 										if (b>255) b=255;
2921 
2922 										colour = 0xff000000+(b<<16)+((b>>1)<<8);
2923 									  	break;
2924 									}
2925 								}
2926 								RenderLightFlare(&position,colour);
2927 							}
2928 						}
2929 
2930 						break;
2931 					}
2932 					case I_BehaviourFlareGrenade:
2933 					{
2934 						if (LocalDetailLevels.DrawLightCoronas)
2935 						{
2936 							DoFlareCorona(objectPtr);
2937 						}
2938 						break;
2939 					}
2940 					case I_BehaviourNetGhost:
2941 					{
2942 			   			NETGHOSTDATABLOCK *ghostDataPtr = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
2943 
2944 						if (ghostDataPtr->type==I_BehaviourFlareGrenade && LocalDetailLevels.DrawLightCoronas)
2945 						{
2946 							DoFlareCorona(objectPtr);
2947 						}
2948 						else if (ghostDataPtr->type==I_BehaviourFrisbee)
2949 						{
2950 							if (sbPtr->DynPtr)
2951 							{
2952 								if (CameraCanSeeThisPosition_WithIgnore(objectPtr,&(sbPtr->DynPtr->Position)))
2953 								{
2954 									int colour;
2955 									switch (CurrentVisionMode)
2956 									{
2957 										default:
2958 										case VISION_MODE_NORMAL:
2959 										{
2960 											colour = 0x40ffffff;
2961 											break;
2962 										}
2963 										case VISION_MODE_IMAGEINTENSIFIER:
2964 										{
2965 											colour = 0x40ffffff;
2966 											break;
2967 										}
2968 										case VISION_MODE_PRED_THERMAL:
2969 										case VISION_MODE_PRED_SEEALIENS:
2970 										case VISION_MODE_PRED_SEEPREDTECH:
2971 										{
2972 											colour = 0x40ff8000;
2973 										  	break;
2974 										}
2975 									}
2976 									RenderLightFlare(&(sbPtr->DynPtr->Position),colour);
2977 								}
2978 							}
2979 						}
2980 						break;
2981 					}
2982 					/* CDF 21/7/99 Frisbee Laser? */
2983 					case I_BehaviourFrisbee:
2984 					{
2985 						if (sbPtr->DynPtr)
2986 						{
2987 							if (CameraCanSeeThisPosition_WithIgnore(objectPtr,&(sbPtr->DynPtr->Position)))
2988 							{
2989 								int colour;
2990 								switch (CurrentVisionMode)
2991 								{
2992 									default:
2993 									case VISION_MODE_NORMAL:
2994 									{
2995 										colour = 0x40ffffff;
2996 										break;
2997 									}
2998 									case VISION_MODE_IMAGEINTENSIFIER:
2999 									{
3000 										colour = 0x40ffffff;
3001 										break;
3002 									}
3003 									case VISION_MODE_PRED_THERMAL:
3004 									case VISION_MODE_PRED_SEEALIENS:
3005 									case VISION_MODE_PRED_SEEPREDTECH:
3006 									{
3007 										colour = 0x40ff8000;
3008 									  	break;
3009 									}
3010 								}
3011 								RenderLightFlare(&(sbPtr->DynPtr->Position),colour);
3012 							}
3013 						}
3014 						break;
3015 					}
3016 					/* CDF 21/7/99 Frisbee Laser? */
3017 					case I_BehaviourXenoborg:
3018 					{
3019 						XENO_STATUS_BLOCK *statusPtr = (XENO_STATUS_BLOCK *)sbPtr->SBdataptr;
3020 						LASER_BEAM_DESC *laserPtr = statusPtr->TargetingLaser;
3021 						int i = 2;
3022 						do
3023 						{
3024 							if (laserPtr->BeamIsOn)
3025 							{
3026 								if (laserPtr->BeamHasHitPlayer)
3027 								{
3028 									int colour;
3029 									switch (CurrentVisionMode)
3030 									{
3031 										default:
3032 										case VISION_MODE_NORMAL:
3033 										{
3034 											colour = 0xffff0000;
3035 											break;
3036 										}
3037 										case VISION_MODE_IMAGEINTENSIFIER:
3038 										{
3039 											colour = 0xffffffff;
3040 											break;
3041 										}
3042 										case VISION_MODE_PRED_THERMAL:
3043 										case VISION_MODE_PRED_SEEALIENS:
3044 										case VISION_MODE_PRED_SEEPREDTECH:
3045 										{
3046 											colour = 0xffff8000;
3047 										  	break;
3048 										}
3049 									}
3050 									RenderLightFlare(&(laserPtr->SourcePosition),colour);
3051 								}
3052 								else
3053 								{
3054 									PARTICLE particle;
3055 									switch (CurrentVisionMode)
3056 									{
3057 										default:
3058 										case VISION_MODE_NORMAL:
3059 										{
3060 											particle.Colour = RGBALIGHT_MAKE(255,0,0,255);
3061 											break;
3062 										}
3063 										case VISION_MODE_IMAGEINTENSIFIER:
3064 										{
3065 						  					particle.Colour = RGBALIGHT_MAKE(255,255,255,255);
3066 											break;
3067 										}
3068 										case VISION_MODE_PRED_THERMAL:
3069 										case VISION_MODE_PRED_SEEALIENS:
3070 										case VISION_MODE_PRED_SEEPREDTECH:
3071 										{
3072 						  					particle.Colour = RGBALIGHT_MAKE(255,128,0,255);
3073 										  	break;
3074 										}
3075 									}
3076 									particle.ParticleID = PARTICLE_LASERBEAM;
3077 									particle.Position = laserPtr->SourcePosition;
3078 									particle.Offset = laserPtr->TargetPosition;
3079 									particle.Size = 20;
3080 									RenderParticle(&particle);
3081 								}
3082 							}
3083 							laserPtr++;
3084 						}
3085 						while(i--);
3086 
3087 						if (statusPtr->LeftMainBeam.BeamIsOn)
3088 						{
3089 							DrawXenoborgMainLaserbeam(&statusPtr->LeftMainBeam);
3090 						}
3091 						if (statusPtr->RightMainBeam.BeamIsOn)
3092 						{
3093 							DrawXenoborgMainLaserbeam(&statusPtr->RightMainBeam);
3094 						}
3095 						break;
3096 					}
3097 					case I_BehaviourSpeargunBolt:
3098 					{
3099 					    SPEAR_BEHAV_BLOCK *bbPtr = (SPEAR_BEHAV_BLOCK * ) sbPtr->SBdataptr;
3100 
3101 						if (bbPtr->SpearThroughFragment)
3102 						{
3103 							DISPLAYBLOCK displayblock;
3104 							displayblock.ObWorld.vx=bbPtr->Position.vx+sbPtr->DynPtr->Position.vx;
3105 							displayblock.ObWorld.vy=bbPtr->Position.vy+sbPtr->DynPtr->Position.vy;
3106 							displayblock.ObWorld.vz=bbPtr->Position.vz+sbPtr->DynPtr->Position.vz;
3107 							displayblock.ObMat=bbPtr->Orient;
3108 							displayblock.ObShape=GetLoadedShapeMSL("spear");
3109 							displayblock.ObShapeData=GetShapeData(displayblock.ObShape);
3110 
3111 							displayblock.name=NULL;
3112 							displayblock.ObEuler.EulerX=0;
3113 							displayblock.ObEuler.EulerY=0;
3114 							displayblock.ObEuler.EulerZ=0;
3115 							displayblock.ObFlags=0;
3116 							displayblock.ObFlags2=0;
3117 							displayblock.ObFlags3=0;
3118 							displayblock.ObNumLights=0;
3119 							displayblock.ObRadius=0;
3120 							displayblock.ObMaxX=0;
3121 							displayblock.ObMinX=0;
3122 							displayblock.ObMaxY=0;
3123 							displayblock.ObMinY=0;
3124 							displayblock.ObMaxZ=0;
3125 							displayblock.ObMinZ=0;
3126 							displayblock.ObTxAnimCtrlBlks=NULL;
3127 							displayblock.ObEIDPtr=NULL;
3128 							displayblock.ObMorphCtrl=NULL;
3129 							displayblock.ObStrategyBlock=NULL;
3130 							displayblock.ShapeAnimControlBlock=NULL;
3131 							displayblock.HModelControlBlock=NULL;
3132 							displayblock.ObMyModule=NULL;
3133 							displayblock.SpecialFXFlags = 0;
3134 							displayblock.SfxPtr=0;
3135 
3136 							MakeVector(&displayblock.ObWorld, &Global_VDB_Ptr->VDB_World, &displayblock.ObView);
3137 							RotateVector(&displayblock.ObView, &Global_VDB_Ptr->VDB_Mat);
3138 							RenderThisDisplayblock(&displayblock);
3139 
3140 						}
3141 						break;
3142 					}
3143 					default:
3144 					{
3145 						/* KJL 19:17:48 31/07/98 - check for hmodels */
3146 						break;
3147 					}
3148 				}
3149 			}
3150 		}
3151 	}
3152 	HandlePheromoneTrails();
3153 	{
3154 		int i;
3155 		for(i=0; i<MAX_NO_OF_EXPLOSIONS; i++)
3156 		{
3157 			if (ExplosionStorage[i].LifeTime)
3158 				HandleVolumetricExplosion(&ExplosionStorage[i]);
3159 		}
3160 	}
3161 	//RenderBoom();
3162    	//RenderFog();
3163 	D3D_DecalSystem_End();
3164 
3165 }
3166 
RenderAllParticlesFurtherAwayThan(int zThreshold)3167 void RenderAllParticlesFurtherAwayThan(int zThreshold)
3168 {
3169 	/* now render particles */
3170 	int i = NumActiveParticles;
3171 	PARTICLE *particlePtr = ParticleStorage;
3172 	while(i--)
3173 	{
3174 		if (particlePtr->NotYetRendered)
3175 		{
3176 			VECTORCH position = particlePtr->Position;
3177 			TranslatePointIntoViewspace(&position);
3178 
3179 			if (position.vz>zThreshold)
3180 			{
3181 				particlePtr->NotYetRendered = 0;
3182 				switch(particlePtr->ParticleID)
3183 				{
3184 					case PARTICLE_ALIEN_BLOOD:
3185 					{
3186 						RenderParticle(particlePtr);
3187 						{
3188 							VECTORCH obstacleNormal;
3189 							int moduleIndex;
3190 							#if 1
3191 							if(ParticleDynamics(particlePtr,&obstacleNormal,&moduleIndex))
3192 							{
3193 								if(moduleIndex!=-1)
3194 								{
3195 									#if 1
3196 									int i = 1;
3197 									MATRIXCH orientation;
3198 									MakeMatrixFromDirection(&obstacleNormal,&orientation);
3199 									while(i--)
3200 									{
3201 										VECTORCH velocity;
3202 										velocity.vx = ((FastRandom()&1023) - 512);
3203 										velocity.vy = ((FastRandom()&1023) - 512);
3204 										velocity.vz = (255+(FastRandom()&255));
3205 										RotateVector(&velocity,&orientation);
3206 										MakeParticle(&(particlePtr->Position),&(velocity),PARTICLE_IMPACTSMOKE);
3207 									}
3208 									#endif
3209 						 			MakeDecal(DECAL_SCORCHED,&obstacleNormal,&(particlePtr->Position),moduleIndex);
3210 								}
3211 								particlePtr->LifeTime = 0;
3212 							}
3213 							#endif
3214 						}
3215 
3216 						particlePtr->Velocity.vy += MUL_FIXED(10000,NormalFrameTime);
3217 						AddEffectsOfForceGenerators(&particlePtr->Position,&particlePtr->Velocity,32*16);
3218 
3219 						break;
3220 					}
3221 					case PARTICLE_PREDATOR_BLOOD:
3222 					{
3223 						RenderParticle(particlePtr);
3224 						{
3225 							VECTORCH obstacleNormal;
3226 							int moduleIndex;
3227 
3228 							if(ParticleDynamics(particlePtr,&obstacleNormal,&moduleIndex))//&& !(FastRandom()&15))
3229 							{
3230 								if(moduleIndex!=-1)
3231 								{
3232 									MakeDecal(DECAL_PREDATOR_BLOOD,&obstacleNormal,&(particlePtr->Position),moduleIndex);
3233 								}
3234 								particlePtr->LifeTime = 0;
3235 							}
3236 						}
3237 
3238 						particlePtr->Velocity.vy += MUL_FIXED(10000,NormalFrameTime);
3239 						AddEffectsOfForceGenerators(&particlePtr->Position,&particlePtr->Velocity,32*16);
3240 						break;
3241 
3242 					}
3243 					case PARTICLE_HUMAN_BLOOD:
3244 					{
3245 						RenderParticle(particlePtr);
3246 						{
3247 							VECTORCH obstacleNormal;
3248 							int moduleIndex;
3249 
3250 							if(ParticleDynamics(particlePtr,&obstacleNormal,&moduleIndex))//&& !(FastRandom()&15))
3251 							{
3252 								if(moduleIndex!=-1)
3253 								{
3254 									MakeDecal(DECAL_HUMAN_BLOOD,&obstacleNormal,&(particlePtr->Position),moduleIndex);
3255 								}
3256 								particlePtr->LifeTime = 0;
3257 							}
3258 						}
3259 
3260 						particlePtr->Velocity.vy += MUL_FIXED(10000,NormalFrameTime);
3261 						AddEffectsOfForceGenerators(&particlePtr->Position,&particlePtr->Velocity,32*16);
3262 						break;
3263 					}
3264 					case PARTICLE_ANDROID_BLOOD:
3265 					{
3266 						RenderParticle(particlePtr);
3267 						{
3268 							VECTORCH obstacleNormal;
3269 							int moduleIndex;
3270 
3271 							if(ParticleDynamics(particlePtr,&obstacleNormal,&moduleIndex))//&& !(FastRandom()&15))
3272 							{
3273 								if(moduleIndex!=-1)
3274 								{
3275 									MakeDecal(DECAL_ANDROID_BLOOD,&obstacleNormal,&(particlePtr->Position),moduleIndex);
3276 								}
3277 								particlePtr->LifeTime = 0;
3278 							}
3279 						}
3280 
3281 						particlePtr->Velocity.vy += MUL_FIXED(10000,NormalFrameTime);
3282 						AddEffectsOfForceGenerators(&particlePtr->Position,&particlePtr->Velocity,32*16);
3283 						break;
3284 					}
3285 					case PARTICLE_FLARESMOKE:
3286 					{
3287 					 	RenderParticle(particlePtr);
3288 						{
3289 							VECTORCH impulse={0,0,0};
3290 							int t = MUL_FIXED(NormalFrameTime,NormalFrameTime*4);
3291 							AddEffectsOfForceGenerators(&particlePtr->Position,&impulse,8);
3292 							particlePtr->Position.vx += MUL_FIXED(impulse.vx,t);
3293 							particlePtr->Position.vy += MUL_FIXED(impulse.vy,t);
3294 							particlePtr->Position.vz += MUL_FIXED(impulse.vz,t);
3295 
3296 						}
3297 						break;
3298 					}
3299 					case PARTICLE_FLAME:
3300 					case PARTICLE_NONDAMAGINGFLAME:
3301 					case PARTICLE_PARGEN_FLAME:
3302 					{
3303 					   	RenderParticle(particlePtr);
3304 						{
3305 							VECTORCH obstacleNormal;
3306 							int moduleIndex;
3307 
3308 							if(ParticleDynamics(particlePtr,&obstacleNormal,&moduleIndex) && !(FastRandom()&15))
3309 							{
3310 								if (particlePtr->ParticleID!=PARTICLE_NONDAMAGINGFLAME) {
3311 									if(moduleIndex!=-1)
3312 									{
3313 										MakeDecal(DECAL_SCORCHED,&obstacleNormal,&(particlePtr->Position),moduleIndex);
3314 									}
3315 								}
3316 							}
3317 						}
3318 						particlePtr->Velocity.vy -= MUL_FIXED(8000,NormalFrameTime);
3319 						break;
3320 					}
3321 					case PARTICLE_FIRE:
3322 					{
3323 						RenderParticle(particlePtr);
3324 
3325 						particlePtr->Position.vx += MUL_FIXED(particlePtr->Velocity.vx,NormalFrameTime);
3326 						particlePtr->Position.vy += MUL_FIXED(particlePtr->Velocity.vy,NormalFrameTime);
3327 						particlePtr->Position.vz += MUL_FIXED(particlePtr->Velocity.vz,NormalFrameTime);
3328 						particlePtr->Velocity.vy -= MUL_FIXED(4000,NormalFrameTime);
3329 
3330 						break;
3331 					}
3332 					case PARTICLE_NONCOLLIDINGFLAME:
3333 					{
3334 					   	RenderParticle(particlePtr);
3335 
3336 						particlePtr->Position.vx += MUL_FIXED(particlePtr->Velocity.vx,NormalFrameTime);
3337 						particlePtr->Position.vy += MUL_FIXED(particlePtr->Velocity.vy,NormalFrameTime);
3338 						particlePtr->Position.vz += MUL_FIXED(particlePtr->Velocity.vz,NormalFrameTime);
3339 						particlePtr->Velocity.vy -= MUL_FIXED(8000,NormalFrameTime);
3340 						break;
3341 					}
3342 					case PARTICLE_FLECHETTE:
3343 					case PARTICLE_FLECHETTE_NONDAMAGING:
3344 					{
3345 						RenderFlechetteParticle(particlePtr);
3346 						break;
3347 					}
3348 					case PARTICLE_STEAM:
3349 					case PARTICLE_BLACKSMOKE:
3350 					case PARTICLE_IMPACTSMOKE:
3351 					case PARTICLE_GUNMUZZLE_SMOKE:
3352 					case PARTICLE_EXPLOSIONFIRE:
3353 					case PARTICLE_MOLOTOVFLAME:
3354 					case PARTICLE_ORANGE_SPARK:
3355 					case PARTICLE_ORANGE_PLASMA:
3356 					case PARTICLE_RICOCHET_SPARK:
3357 					case PARTICLE_SPARK:
3358 					case PARTICLE_PLASMATRAIL:
3359 					case PARTICLE_DEWLINE:
3360 					case PARTICLE_WATERSPRAY:
3361 					case PARTICLE_WATERFALLSPRAY:
3362 					case PARTICLE_SMOKECLOUD:
3363 					case PARTICLE_BLUEPLASMASPHERE:
3364 					case PARTICLE_ELECTRICALPLASMASPHERE:
3365 					case PARTICLE_PREDPISTOL_FLECHETTE:
3366 					case PARTICLE_PREDPISTOL_FLECHETTE_NONDAMAGING:
3367 					case PARTICLE_TRACER:
3368 					{
3369 						RenderParticle(particlePtr);
3370 						break;
3371 					}
3372 					default:
3373 					{
3374 						/* particle initialised wrongly */
3375 						LOCALASSERT(0);
3376 						break;
3377 					}
3378 				}
3379 			}
3380 		}
3381 		particlePtr++;
3382 	}
3383 }
DoFlareCorona(DISPLAYBLOCK * objectPtr)3384 void DoFlareCorona(DISPLAYBLOCK *objectPtr)
3385 {
3386 	VECTORCH position=objectPtr->ObWorld;
3387 
3388 	if (CameraCanSeeThisPosition_WithIgnore(objectPtr,&position))
3389 	{
3390 		LIGHTBLOCK *lPtr = objectPtr->ObLights[0];
3391 		int a = lPtr->LightBright>>8;
3392 		int colour;
3393 
3394 		if (a>255) a=255;
3395 
3396 		switch (CurrentVisionMode)
3397 		{
3398 			default:
3399 			case VISION_MODE_NORMAL:
3400 			{
3401 				colour = 0xffc8ff + (a<<24);
3402 				break;
3403 			}
3404 			case VISION_MODE_IMAGEINTENSIFIER:
3405 			{
3406 				colour = 0xffffffff;
3407 				break;
3408 			}
3409 			case VISION_MODE_PRED_THERMAL:
3410 			case VISION_MODE_PRED_SEEALIENS:
3411 			case VISION_MODE_PRED_SEEPREDTECH:
3412 			{
3413 				int b = MUL_FIXED
3414 						(
3415 							lPtr->RedScale+lPtr->GreenScale+lPtr->BlueScale,
3416 							lPtr->LightBright
3417 						)>>10;
3418 				if (b>255) b=255;
3419 
3420 				colour = 0xff000000+(b<<16)+((b>>1)<<8);
3421 			  	break;
3422 			}
3423 		}
3424 		RenderLightFlare(&position,colour);
3425 	}
3426 }
3427 #define MAX_RAINDROPS 1000
3428 static PARTICLE RainDropStorage[MAX_RAINDROPS];
3429 #define MAX_NO_OF_RIPPLES 100
3430 RIPPLE RippleStorage[MAX_NO_OF_RIPPLES];
3431 int ActiveRippleNumber;
InitialiseRainDrops(void)3432 void InitialiseRainDrops(void)
3433 {
3434 	{
3435 		int i = MAX_RAINDROPS;
3436 		PARTICLE *particlePtr = RainDropStorage;
3437 		do
3438 		{
3439 			particlePtr->Position.vy = 0x7fffffff;
3440 			particlePtr->LifeTime = 0;
3441 			particlePtr++;
3442 		}
3443 		while(--i);
3444 	}
3445 	{
3446 		int i = MAX_NO_OF_RIPPLES;
3447 		RIPPLE *ripplePtr = RippleStorage;
3448 		do
3449 		{
3450 			ripplePtr->Active = 0;
3451 			ripplePtr++;
3452 		}
3453 		while(--i);
3454 		ActiveRippleNumber=0;
3455 	}
3456 }
3457 
HandleRainDrops(MODULE * modulePtr,int numberOfRaindrops)3458 void HandleRainDrops(MODULE *modulePtr,int numberOfRaindrops)
3459 {
3460 	int i = numberOfRaindrops;
3461 
3462 	PARTICLE *particlePtr = RainDropStorage;
3463 	LOCALASSERT(i<MAX_RAINDROPS);
3464 	do
3465 	{
3466 		if((particlePtr->Position.vy > modulePtr->m_world.vy+modulePtr->m_maxy-500)
3467 		 ||(particlePtr->Position.vx < modulePtr->m_world.vx+modulePtr->m_minx)
3468 		 ||(particlePtr->Position.vx > modulePtr->m_world.vx+modulePtr->m_maxx)
3469 		 ||(particlePtr->Position.vz < modulePtr->m_world.vz+modulePtr->m_minz)
3470 		 ||(particlePtr->Position.vz > modulePtr->m_world.vz+modulePtr->m_maxz))
3471 		{
3472 			AddRipple(particlePtr->Position.vx,particlePtr->Position.vz,400);
3473 			particlePtr->Position.vy = modulePtr->m_world.vy+modulePtr->m_miny;
3474 			particlePtr->Position.vx = modulePtr->m_world.vx+modulePtr->m_minx+(FastRandom()%(modulePtr->m_maxz-modulePtr->m_minx));
3475 			particlePtr->Position.vz = modulePtr->m_world.vz+modulePtr->m_minz+(FastRandom()%(modulePtr->m_maxz-modulePtr->m_minz));
3476   //		particlePtr->Velocity.vy = (FastRandom()&8191)+15000;
3477   //		particlePtr->Velocity.vx = (FastRandom()&255)+5000;
3478  //			particlePtr->Velocity.vz = (FastRandom()&255)-128;
3479 			particlePtr->Velocity.vy = (FastRandom()&8191)+15000;
3480 			particlePtr->Velocity.vx = (FastRandom()&255)-128;
3481 			particlePtr->Velocity.vz = (FastRandom()&255)-128;
3482 			{
3483 				particlePtr->Offset.vx = -particlePtr->Velocity.vz;
3484 				particlePtr->Offset.vy = 0;
3485 				particlePtr->Offset.vz = particlePtr->Velocity.vx;
3486 				Normalise(&(particlePtr->Offset));
3487 //				particlePtr->Offset.vx = MUL_FIXED(particlePtr->Offset.vx,20);
3488 //				particlePtr->Offset.vz = MUL_FIXED(particlePtr->Offset.vz,20);
3489 				particlePtr->Offset.vx = MUL_FIXED(particlePtr->Offset.vx,50);
3490 				particlePtr->Offset.vz = MUL_FIXED(particlePtr->Offset.vz,50);
3491 			}
3492 		}
3493 		{
3494 			VECTORCH prevPosition = particlePtr->Position;
3495 
3496 			#if 0
3497 			ParticleDynamics(particlePtr);
3498 			#else
3499 			particlePtr->Position.vx += MUL_FIXED(particlePtr->Velocity.vx,NormalFrameTime);
3500 			particlePtr->Position.vy += MUL_FIXED(particlePtr->Velocity.vy,NormalFrameTime);
3501 			particlePtr->Position.vz += MUL_FIXED(particlePtr->Velocity.vz,NormalFrameTime);
3502 			#endif
3503 			if (particlePtr->Position.vy>modulePtr->m_world.vy+modulePtr->m_maxy-500)
3504 				particlePtr->Position.vy=modulePtr->m_world.vy+modulePtr->m_maxy-495;
3505 			D3D_DrawParticle_Rain(particlePtr,&prevPosition);
3506 		}
3507 		particlePtr++;
3508 	}
3509 	while(--i);
3510 
3511 }
3512 #if 0
3513 void HandleRain(MODULE *modulePtr,int numberOfRaindrops)
3514 {
3515 	int i = numberOfRaindrops;
3516 	/* KJL 15:23:37 12/8/97 - this is written to work with the yard in genshd1 */
3517 
3518 	PARTICLE *particlePtr = RainDropStorage;
3519 	LOCALASSERT(i<MAX_RAINDROPS);
3520 	do
3521 	{
3522 		int killDrop=0;
3523 
3524 		if((particlePtr->Position.vx > -10418)
3525 		 &&(particlePtr->Position.vy > -4030)
3526 		 &&(particlePtr->Position.vz < 35070)
3527 		 &&(particlePtr->Position.vz > -11600))
3528 		{
3529 			killDrop=1;
3530 		}
3531 
3532 		if((particlePtr->Position.vy > 3000)
3533 		 ||(particlePtr->Position.vx < modulePtr->m_world.vx+modulePtr->m_minx)
3534 		 ||(particlePtr->Position.vx > modulePtr->m_world.vx+modulePtr->m_maxx)
3535 		 ||(particlePtr->Position.vz < -50655)//modulePtr->m_world.vz+modulePtr->m_minz)
3536 		 ||(particlePtr->Position.vz > modulePtr->m_world.vz+modulePtr->m_maxz))
3537 		{
3538 			killDrop=1;
3539 		}
3540 
3541 		if (killDrop)
3542 		{
3543 			particlePtr->Position.vy = modulePtr->m_world.vy+modulePtr->m_miny;
3544 			particlePtr->Position.vx = modulePtr->m_world.vx+modulePtr->m_minx+(FastRandom()%(modulePtr->m_maxz-modulePtr->m_minx));
3545 			particlePtr->Position.vz = -50655/*+modulePtr->m_minz*/+(FastRandom()%(modulePtr->m_maxz+50655));//-modulePtr->m_minz));
3546 	  		particlePtr->Velocity.vy = (FastRandom()&8191)+15000;
3547   			particlePtr->Velocity.vx = (FastRandom()&255)+5000;
3548  			particlePtr->Velocity.vz = (FastRandom()&255)-128;
3549 			{
3550 				particlePtr->Offset.vx = -particlePtr->Velocity.vz;
3551 				particlePtr->Offset.vy = 0;
3552 				particlePtr->Offset.vz = particlePtr->Velocity.vx;
3553 				Normalise(&(particlePtr->Offset));
3554 				particlePtr->Offset.vx = MUL_FIXED(particlePtr->Offset.vx,20);
3555 				particlePtr->Offset.vz = MUL_FIXED(particlePtr->Offset.vz,20);
3556 			}
3557 		}
3558 		{
3559 			VECTORCH prevPosition = particlePtr->Position;
3560 
3561 			#if 0
3562 			ParticleDynamics(particlePtr);
3563 			#else
3564 			particlePtr->Position.vx += MUL_FIXED(particlePtr->Velocity.vx,NormalFrameTime);
3565 			particlePtr->Position.vy += MUL_FIXED(particlePtr->Velocity.vy,NormalFrameTime);
3566 			particlePtr->Position.vz += MUL_FIXED(particlePtr->Velocity.vz,NormalFrameTime);
3567 			#endif
3568 			D3D_DrawParticle_Rain(particlePtr,&prevPosition);
3569 		}
3570 		particlePtr++;
3571 	}
3572 	while(--i);
3573 
3574 }
3575 #endif
HandleRain(int numberOfRaindrops)3576 void HandleRain(int numberOfRaindrops)
3577 {
3578 	int i = numberOfRaindrops;
3579 	/* KJL 15:23:37 12/8/97 - this is written to work with the yard in genshd1 */
3580 
3581 	PARTICLE *particlePtr = RainDropStorage;
3582 	LOCALASSERT(i<MAX_RAINDROPS);
3583 	do
3584 	{
3585 		int killDrop=0;
3586 
3587 		if((particlePtr->Position.vx > -10418)
3588 		 &&(particlePtr->Position.vy > -4030)
3589 		 &&(particlePtr->Position.vz < 35070)
3590 		 &&(particlePtr->Position.vz > -11600))
3591 		{
3592 			killDrop=1;
3593 		}
3594 		if((particlePtr->Position.vx > -45486)
3595 		 &&(particlePtr->Position.vx < -29901)
3596 		 &&(particlePtr->Position.vy > -6000)
3597 		 &&(particlePtr->Position.vz < -50656)
3598 		 &&(particlePtr->Position.vz > -70130))
3599 		{
3600 			killDrop=1;
3601 		}
3602 
3603 		if((particlePtr->Position.vy > 3000)
3604 		 ||(particlePtr->Position.vx < -77000)
3605 		 ||(particlePtr->Position.vx > 134000)
3606 		 ||(particlePtr->Position.vz < -145000)//modulePtr->m_world.vz+modulePtr->m_minz)
3607 		 ||(particlePtr->Position.vz > 48706))
3608 		{
3609 			killDrop=1;
3610 		}
3611 
3612 		if (killDrop)
3613 		{
3614 			particlePtr->Position.vy = -10000;
3615 			particlePtr->Position.vx = -77000+(FastRandom()%(211000));
3616 			particlePtr->Position.vz = -145000+(FastRandom()%(145000+49000));
3617 	  		particlePtr->Velocity.vy = (FastRandom()&8191)+15000;
3618   			particlePtr->Velocity.vx = (FastRandom()&255)+5000;
3619  			particlePtr->Velocity.vz = (FastRandom()&255)-128;
3620 			{
3621 				particlePtr->Offset.vx = -particlePtr->Velocity.vz;
3622 				particlePtr->Offset.vy = 0;
3623 				particlePtr->Offset.vz = particlePtr->Velocity.vx;
3624 				Normalise(&(particlePtr->Offset));
3625 				particlePtr->Offset.vx = MUL_FIXED(particlePtr->Offset.vx,20);
3626 				particlePtr->Offset.vz = MUL_FIXED(particlePtr->Offset.vz,20);
3627 			}
3628 		}
3629 		{
3630 			VECTORCH prevPosition = particlePtr->Position;
3631 
3632 			#if 0
3633 			ParticleDynamics(particlePtr);
3634 			#else
3635 			particlePtr->Position.vx += MUL_FIXED(particlePtr->Velocity.vx,NormalFrameTime);
3636 			particlePtr->Position.vy += MUL_FIXED(particlePtr->Velocity.vy,NormalFrameTime);
3637 			particlePtr->Position.vz += MUL_FIXED(particlePtr->Velocity.vz,NormalFrameTime);
3638 			#endif
3639 			D3D_DrawParticle_Rain(particlePtr,&prevPosition);
3640 		}
3641 		particlePtr++;
3642 	}
3643 	while(--i);
3644 
3645 }
HandleRainInTrench(int numberOfRaindrops)3646 void HandleRainInTrench(int numberOfRaindrops)
3647 {
3648 	int i = numberOfRaindrops;
3649 	/* KJL 15:23:37 12/8/97 - this is written to work with the yard in genshd1 */
3650 
3651 	PARTICLE *particlePtr = RainDropStorage;
3652 	LOCALASSERT(i<MAX_RAINDROPS);
3653 	do
3654 	{
3655 		int killDrop=0;
3656 		/*
3657 		if((particlePtr->Position.vx > -10418)
3658 		 &&(particlePtr->Position.vy > -4030)
3659 		 &&(particlePtr->Position.vz < 35070)
3660 		 &&(particlePtr->Position.vz > -11600))
3661 		{
3662 			killDrop=1;
3663 		}
3664 		*/
3665 		if((particlePtr->Position.vy > 3000)
3666 		 ||(particlePtr->Position.vx < 13500)
3667 		 ||(particlePtr->Position.vx > -50000)
3668 		 ||(particlePtr->Position.vz < -150655)
3669 		 ||(particlePtr->Position.vz > -50655))
3670 		{
3671 			killDrop=1;
3672 		}
3673 
3674 		if (killDrop)
3675 		{
3676 			particlePtr->Position.vy = -16000;
3677 			particlePtr->Position.vx = -50000+(FastRandom()%(63500));
3678 			particlePtr->Position.vz = -150655+(FastRandom()%(100000));
3679 	  		particlePtr->Velocity.vy = (FastRandom()&8191)+15000;
3680   			particlePtr->Velocity.vx = (FastRandom()&255)+5000;
3681  			particlePtr->Velocity.vz = (FastRandom()&255)-128;
3682 			{
3683 				particlePtr->Offset.vx = -particlePtr->Velocity.vz;
3684 				particlePtr->Offset.vy = 0;
3685 				particlePtr->Offset.vz = particlePtr->Velocity.vx;
3686 				Normalise(&(particlePtr->Offset));
3687 				particlePtr->Offset.vx = MUL_FIXED(particlePtr->Offset.vx,20);
3688 				particlePtr->Offset.vz = MUL_FIXED(particlePtr->Offset.vz,20);
3689 			}
3690 		}
3691 		{
3692 			VECTORCH prevPosition = particlePtr->Position;
3693 
3694 			#if 0
3695 			ParticleDynamics(particlePtr);
3696 			#else
3697 			particlePtr->Position.vx += MUL_FIXED(particlePtr->Velocity.vx,NormalFrameTime);
3698 			particlePtr->Position.vy += MUL_FIXED(particlePtr->Velocity.vy,NormalFrameTime);
3699 			particlePtr->Position.vz += MUL_FIXED(particlePtr->Velocity.vz,NormalFrameTime);
3700 			#endif
3701 			D3D_DrawParticle_Rain(particlePtr,&prevPosition);
3702 		}
3703 		particlePtr++;
3704 	}
3705 	while(--i);
3706 
3707 }
3708 
HandleRainShaft(MODULE * modulePtr,int bottomY,int topY,int numberOfRaindrops)3709 void HandleRainShaft(MODULE *modulePtr, int bottomY, int topY, int numberOfRaindrops)
3710 {
3711 	int i = numberOfRaindrops;
3712 	PARTICLE_DESC *particleDescPtr = &ParticleDescription[PARTICLE_WATERFALLSPRAY];
3713 
3714 	PARTICLE *particlePtr = RainDropStorage;
3715 	LOCALASSERT(i<MAX_RAINDROPS);
3716 	do
3717 	{
3718 		if((particlePtr->Position.vx < modulePtr->m_world.vx+modulePtr->m_minx)
3719 		 ||(particlePtr->Position.vx > modulePtr->m_world.vx+modulePtr->m_maxx)
3720 		 ||(particlePtr->Position.vz < modulePtr->m_world.vz+modulePtr->m_minz)
3721 		 ||(particlePtr->Position.vz > modulePtr->m_world.vz+modulePtr->m_maxz))
3722 		{
3723 			particlePtr->LifeTime=0;
3724 		}
3725 		else if(particlePtr->Position.vy > bottomY)
3726 		{
3727 			particlePtr->Position.vy = bottomY;
3728 	  		particlePtr->Velocity.vy = -particlePtr->Velocity.vy;
3729   			particlePtr->Velocity.vx = particlePtr->Velocity.vx;
3730  			particlePtr->Velocity.vz = particlePtr->Velocity.vz;
3731 			particlePtr->LifeTime = 1;
3732 			particlePtr->Size = 100;
3733 			AddRipple(particlePtr->Position.vx,particlePtr->Position.vz,100);
3734 		}
3735 
3736 		if (particlePtr->LifeTime<=0)
3737 		{
3738 			particlePtr->Position.vy = topY;
3739 			particlePtr->Position.vx = modulePtr->m_world.vx+modulePtr->m_minx+(FastRandom()%(modulePtr->m_maxz-modulePtr->m_minx));
3740 			particlePtr->Position.vz = modulePtr->m_world.vz+modulePtr->m_minz+(FastRandom()%(modulePtr->m_maxz-modulePtr->m_minz));
3741 	  		particlePtr->Velocity.vy = (FastRandom()&8191)+15000;
3742   			particlePtr->Velocity.vx = (FastRandom()&1023)-512;
3743  			particlePtr->Velocity.vz = (FastRandom()&1023)-512;
3744 			particlePtr->LifeTime = 100*ONE_FIXED;
3745 			particlePtr->ParticleID = PARTICLE_WATERFALLSPRAY;
3746 			particlePtr->Colour = RGBALIGHT_MAKE
3747 								  (
3748 								  	particleDescPtr->RedScale[CurrentVisionMode],
3749 								  	particleDescPtr->GreenScale[CurrentVisionMode],
3750 								  	particleDescPtr->BlueScale[CurrentVisionMode],
3751 								  	particleDescPtr->Alpha
3752 								  );
3753 			particlePtr->Size = 20;
3754 		}
3755 		else
3756 		{
3757 			particlePtr->LifeTime -= NormalFrameTime;
3758 		}
3759 
3760 		{
3761 			particlePtr->Position.vx += MUL_FIXED(particlePtr->Velocity.vx,NormalFrameTime);
3762 			particlePtr->Position.vy += MUL_FIXED(particlePtr->Velocity.vy,NormalFrameTime);
3763 			particlePtr->Position.vz += MUL_FIXED(particlePtr->Velocity.vz,NormalFrameTime);
3764 #if 0
3765 			D3D_DrawParticle_Rain(particlePtr,&prevPosition);
3766 #else
3767 			particlePtr->Offset.vx = particlePtr->Position.vx - particlePtr->Velocity.vx/16;
3768 			particlePtr->Offset.vy = particlePtr->Position.vy - particlePtr->Velocity.vy/16;
3769 			particlePtr->Offset.vz = particlePtr->Position.vz - particlePtr->Velocity.vz/16;
3770 
3771 			RenderParticle(particlePtr);
3772 #endif
3773 		}
3774 		particlePtr++;
3775 	}
3776 	while(--i);
3777 
3778 }
3779 
HandleRipples(void)3780 void HandleRipples(void)
3781 {
3782 	int i;
3783 
3784 	for(i=0; i<MAX_NO_OF_RIPPLES; i++)
3785 	{
3786 		if (RippleStorage[i].Active)
3787 		{
3788 			RippleStorage[i].Radius	+= MUL_FIXED(2400,NormalFrameTime);
3789 			RippleStorage[i].InvRadius = DIV_FIXED(4090,RippleStorage[i].Radius);
3790 			RippleStorage[i].Amplitude -= MUL_FIXED(50,NormalFrameTime);
3791 
3792 			if (RippleStorage[i].Amplitude<0)
3793 			{
3794 				RippleStorage[i].Active = 0;
3795 			}
3796 		}
3797 	}
3798 }
3799 
EffectOfRipples(VECTORCH * point)3800 int EffectOfRipples(VECTORCH *point)
3801 {
3802 	int offset;
3803 	int i;
3804  	offset = GetSin((point->vx+point->vz+CloakingPhase)&4095)>>11;
3805  	offset += GetSin((point->vx-point->vz*2+CloakingPhase/2)&4095)>>12;
3806 
3807 	for(i=0; i<MAX_NO_OF_RIPPLES; i++)
3808 	{
3809 		if (RippleStorage[i].Active)
3810 		{
3811 			int dx=point->vx-RippleStorage[i].X;
3812 			int dz=point->vz-RippleStorage[i].Z;
3813 
3814 			if (dx<0) dx = -dx;
3815 			if (dz<0) dz = -dz;
3816 			{
3817 				int a;
3818 
3819 				if (dx>dz)
3820 				{
3821 					a = dx+(dz>>1);
3822 				}
3823 				else
3824 				{
3825 					a = dz+(dx>>1);
3826 				}
3827 
3828 				if (a<RippleStorage[i].Radius)
3829 				{
3830 					a = MUL_FIXED(a,RippleStorage[i].InvRadius);
3831 
3832 					offset+= MUL_FIXED
3833 							 (
3834 							 	RippleStorage[i].Amplitude,
3835 							 	GetSin(a)
3836 							 );
3837 				}
3838 			}
3839 		}
3840 	}
3841 
3842 	if (offset>256) offset = 256;
3843 	else if (offset<-256) offset = -256;
3844 	return offset;
3845 }
3846 
3847 
AddRipple(int x,int z,int amplitude)3848 void AddRipple(int x,int z,int amplitude)
3849 {
3850 	RippleStorage[ActiveRippleNumber].Active=1;
3851 	RippleStorage[ActiveRippleNumber].X = x;
3852 	RippleStorage[ActiveRippleNumber].Z = z;
3853 	RippleStorage[ActiveRippleNumber].Radius = 200;
3854 	RippleStorage[ActiveRippleNumber].Amplitude = amplitude;
3855 
3856 	ActiveRippleNumber++;
3857 	if (ActiveRippleNumber == MAX_NO_OF_RIPPLES) ActiveRippleNumber=0;
3858 
3859 }
3860 
3861 
CheckForObjectsInWater(int minX,int maxX,int minZ,int maxZ,int averageY)3862 void CheckForObjectsInWater(int minX, int maxX, int minZ, int maxZ, int averageY)
3863 {
3864    	extern int NumActiveBlocks;
3865 	extern DISPLAYBLOCK* ActiveBlockList[];
3866    	int numberOfObjects = NumActiveBlocks;
3867 
3868    	while (numberOfObjects--)
3869 	{
3870 		DISPLAYBLOCK* objectPtr = ActiveBlockList[numberOfObjects];
3871 
3872 		if(objectPtr->ObStrategyBlock)
3873 		{
3874 			DYNAMICSBLOCK *dynPtr = objectPtr->ObStrategyBlock->DynPtr;
3875 
3876 
3877 			if (dynPtr)
3878 			{
3879 				int overlapInY=0;
3880 				int overlapInX=0;
3881 				int overlapInZ=0;
3882 
3883 				/* floating objects are ignored to avoid positive feedback */
3884 				if(dynPtr->IsFloating) continue;
3885 				#if 1
3886 				if ( (dynPtr->Position.vx==dynPtr->PrevPosition.vx)
3887 				   &&(dynPtr->Position.vy==dynPtr->PrevPosition.vy)
3888 				   &&(dynPtr->Position.vz==dynPtr->PrevPosition.vz) )
3889 				   continue;
3890 				#endif
3891 
3892 				if (dynPtr->Position.vy>dynPtr->PrevPosition.vy)
3893 				{
3894 					if ((dynPtr->Position.vy+objectPtr->ObRadius > averageY)
3895 					  &&(dynPtr->PrevPosition.vy-objectPtr->ObRadius < averageY))
3896 					{
3897 						overlapInY=1;
3898 					}
3899 				}
3900 				else
3901 				{
3902 					if ((dynPtr->PrevPosition.vy+objectPtr->ObRadius > averageY)
3903 					  &&(dynPtr->Position.vy-objectPtr->ObRadius < averageY))
3904 					{
3905 						overlapInY=1;
3906 					}
3907 				}
3908 
3909 				if (!overlapInY) continue;
3910 
3911 				if (dynPtr->Position.vx>dynPtr->PrevPosition.vx)
3912 				{
3913 					if ((dynPtr->Position.vx+objectPtr->ObRadius > minX)
3914 					  &&(dynPtr->PrevPosition.vx-objectPtr->ObRadius < maxX))
3915 					{
3916 						overlapInX=1;
3917 					}
3918 				}
3919 				else
3920 				{
3921 					if ((dynPtr->PrevPosition.vx+objectPtr->ObRadius > minX)
3922 					  &&(dynPtr->Position.vx-objectPtr->ObRadius < maxX))
3923 					{
3924 						overlapInX=1;
3925 					}
3926 				}
3927 
3928 				if (!overlapInX) continue;
3929 
3930 				if (dynPtr->Position.vz>dynPtr->PrevPosition.vz)
3931 				{
3932 					if ((dynPtr->Position.vz+objectPtr->ObRadius > minZ)
3933 					  &&(dynPtr->PrevPosition.vz-objectPtr->ObRadius < maxZ))
3934 					{
3935 						overlapInZ=1;
3936 					}
3937 				}
3938 				else
3939 				{
3940 					if ((dynPtr->PrevPosition.vz+objectPtr->ObRadius > minZ)
3941 					  &&(dynPtr->Position.vz-objectPtr->ObRadius < maxZ))
3942 					{
3943 						overlapInZ=1;
3944 					}
3945 				}
3946 
3947 				if (!overlapInZ) continue;
3948 
3949 				/* we have an overlap */
3950 
3951 				/* KJL 16:37:29 27/08/98 - if object is on fire its now put out */
3952 				objectPtr->ObStrategyBlock->SBDamageBlock.IsOnFire=0;
3953 
3954 				if (objectPtr->ObStrategyBlock->I_SBtype == I_BehaviourFlareGrenade)
3955 				{
3956 					VECTORCH upwards = {0,-65536,0};
3957 					dynPtr->IsFloating = 1;
3958 					dynPtr->GravityOn = 0;
3959 					dynPtr->Elasticity = 0;
3960 					MakeMatrixFromDirection(&upwards,&(dynPtr->OrientMat));
3961 				}
3962 				else if (objectPtr == Player)
3963 				{
3964 					PLAYER_STATUS *playerStatusPtr = (PLAYER_STATUS *)(objectPtr->ObStrategyBlock->SBdataptr);
3965 			    	LOCALASSERT(playerStatusPtr);
3966 
3967 					playerStatusPtr->IsMovingInWater = 1;
3968 				}
3969 				{
3970 
3971 					AddRipple(dynPtr->Position.vx,dynPtr->Position.vz,100);
3972 					#if 0
3973 					{
3974 						int i;
3975 						for (i=0; i<10; i++)
3976 						{
3977 							VECTORCH velocity;
3978 							velocity.vy = (-(FastRandom()%(magnitude)))*8;
3979 							velocity.vx = ((FastRandom()&1023)-512)*8;
3980 							velocity.vz = ((FastRandom()&1023)-512)*8;
3981 							MakeParticle(&(dynPtr->Position), &velocity, PARTICLE_WATERSPRAY);
3982 						}
3983 					}
3984 					#endif
3985 				}
3986 			}
3987 		}
3988 	}
3989 }
3990 
DrawMuzzleFlash(VECTORCH * positionPtr,VECTORCH * directionPtr,enum MUZZLE_FLASH_ID muzzleFlashID)3991 void DrawMuzzleFlash(VECTORCH *positionPtr,VECTORCH *directionPtr, enum MUZZLE_FLASH_ID muzzleFlashID)
3992 {
3993 	PARTICLE particle;
3994 	particle.Position = *positionPtr;
3995 
3996 	D3D_DecalSystem_Setup();
3997 
3998 	switch (muzzleFlashID)
3999 	{
4000 		case MUZZLE_FLASH_SMARTGUN:
4001 		{
4002 			#if 0
4003 			PARTICLE_DESC *particleDescPtr;
4004 			particle.ParticleID=PARTICLE_SMARTGUNMUZZLEFLASH;
4005 			particleDescPtr = &ParticleDescription[particle.ParticleID];
4006 
4007 			particle.Colour = RGBALIGHT_MAKE(particleDescPtr->RedScale[CurrentVisionMode],particleDescPtr->GreenScale[CurrentVisionMode],particleDescPtr->BlueScale[CurrentVisionMode],particleDescPtr->Alpha);
4008 			particle.Size = particleDescPtr->Size;
4009 
4010 			particle.Position.vx += MUL_FIXED(100,directionPtr->vx);
4011 			particle.Position.vy += MUL_FIXED(100,directionPtr->vy);
4012 			particle.Position.vz += MUL_FIXED(100,directionPtr->vz);
4013 			RenderParticle(&particle);
4014 			#else
4015 			PARTICLE_DESC *particleDescPtr=&ParticleDescription[PARTICLE_MUZZLEFLASH];
4016 			MATRIXCH muzzleMatrix;
4017 			MATRIXCH rotmat;
4018 			MakeMatrixFromDirection(directionPtr,&muzzleMatrix);
4019 			{
4020 		   		int angle = 4096/12;
4021 		 	  	int cos = GetCos(angle);
4022 		 	  	int sin = GetSin(angle);
4023 		 	  	rotmat.mat11 = cos;
4024 		 	  	rotmat.mat12 = sin;
4025 		 	  	rotmat.mat13 = 0;
4026 		 	  	rotmat.mat21 = -sin;
4027 		 	  	rotmat.mat22 = cos;
4028 		 	  	rotmat.mat23 = 0;
4029 		 	  	rotmat.mat31 = 0;
4030 		 	  	rotmat.mat32 = 0;
4031 		 	  	rotmat.mat33 = 65536;
4032 			}
4033 			#if 1
4034 			{
4035 				int i = 16;
4036 				PARTICLE particle;
4037 
4038 				particle.Position = *positionPtr;
4039 				particle.Position.vx += MUL_FIXED(100 - (FastRandom()&15),directionPtr->vx);
4040 				particle.Position.vy += MUL_FIXED(100 - (FastRandom()&15),directionPtr->vy);
4041 				particle.Position.vz += MUL_FIXED(100 - (FastRandom()&15),directionPtr->vz);
4042 
4043 				particle.ParticleID=PARTICLE_MUZZLEFLASH;
4044 
4045 				particle.Colour = RGBALIGHT_MAKE(particleDescPtr->RedScale[CurrentVisionMode],particleDescPtr->GreenScale[CurrentVisionMode],particleDescPtr->BlueScale[CurrentVisionMode],particleDescPtr->Alpha);
4046 				particle.Size = 200;
4047 
4048 				while(i--)
4049 				{
4050 					RenderParticle(&particle);
4051 					particle.Position.vx += MUL_FIXED(50 - (FastRandom()&15),directionPtr->vx);
4052 					particle.Position.vy += MUL_FIXED(50 - (FastRandom()&15),directionPtr->vy);
4053 					particle.Position.vz += MUL_FIXED(50 - (FastRandom()&15),directionPtr->vz);
4054 					particle.Size -= (FastRandom()&3)+3;
4055 				}
4056 
4057 			}
4058 			#endif
4059 			{
4060 				int a;
4061 				for (a=0; a<12;a++)
4062 				{
4063 					int i=8;
4064 					PARTICLE particle;
4065 
4066 					particle.Position = *positionPtr;
4067 					particle.Position.vx += -MUL_FIXED(200,directionPtr->vx) + MUL_FIXED(50,muzzleMatrix.mat21);
4068 					particle.Position.vy += -MUL_FIXED(200,directionPtr->vy) + MUL_FIXED(50,muzzleMatrix.mat22);
4069 					particle.Position.vz += -MUL_FIXED(200,directionPtr->vz) + MUL_FIXED(50,muzzleMatrix.mat23);
4070 
4071 					particle.ParticleID=PARTICLE_MUZZLEFLASH;
4072 
4073 					particle.Colour = RGBALIGHT_MAKE(particleDescPtr->RedScale[CurrentVisionMode],particleDescPtr->GreenScale[CurrentVisionMode],particleDescPtr->BlueScale[CurrentVisionMode],particleDescPtr->Alpha);
4074 					particle.Size = 50;
4075 
4076 					if (!(a&1)) i+=8;
4077 
4078 					while(i--)
4079 					{
4080 						RenderParticle(&particle);
4081 						particle.Position.vx += MUL_FIXED((FastRandom()&31)+16,muzzleMatrix.mat21);
4082 						particle.Position.vy += MUL_FIXED((FastRandom()&31)+16,muzzleMatrix.mat22);
4083 						particle.Position.vz += MUL_FIXED((FastRandom()&31)+16,muzzleMatrix.mat23);
4084 						particle.Size += (FastRandom()&15);
4085 					}
4086 
4087 					MatrixMultiply(&muzzleMatrix,&rotmat,&muzzleMatrix);
4088 				}
4089 
4090 			}
4091 			#endif
4092 			break;
4093 		}
4094 		case MUZZLE_FLASH_AMORPHOUS:
4095 		{
4096 			PARTICLE_DESC *particleDescPtr;
4097 			particle.ParticleID=PARTICLE_MUZZLEFLASH;
4098 			particleDescPtr = &ParticleDescription[particle.ParticleID];
4099 
4100 			particle.Colour = RGBALIGHT_MAKE(particleDescPtr->RedScale[CurrentVisionMode],particleDescPtr->GreenScale[CurrentVisionMode],particleDescPtr->BlueScale[CurrentVisionMode],particleDescPtr->Alpha);
4101 			particle.Size = particleDescPtr->Size;
4102 
4103 			RenderParticle(&particle);
4104 			particle.Position.vx += MUL_FIXED(100,directionPtr->vx);
4105 			particle.Position.vy += MUL_FIXED(100,directionPtr->vy);
4106 			particle.Position.vz += MUL_FIXED(100,directionPtr->vz);
4107 			RenderParticle(&particle);
4108 			particle.Position.vx += MUL_FIXED(100,directionPtr->vx);
4109 			particle.Position.vy += MUL_FIXED(100,directionPtr->vy);
4110 			particle.Position.vz += MUL_FIXED(100,directionPtr->vz);
4111 			RenderParticle(&particle);
4112 			{
4113 				int i = 16;
4114 				particle.Size = 20;
4115 
4116 				while(i--)
4117 				{
4118 					RenderParticle(&particle);
4119 					particle.Position.vx = positionPtr->vx + MUL_FIXED(100,directionPtr->vx) + (FastRandom()&127)-64;
4120 					particle.Position.vy = positionPtr->vy + MUL_FIXED(100,directionPtr->vy) + (FastRandom()&127)-64;
4121 					particle.Position.vz = positionPtr->vz + MUL_FIXED(100,directionPtr->vz) + (FastRandom()&127)-64;
4122 				}
4123 
4124 			}
4125 			break;
4126 		}
4127 		case MUZZLE_FLASH_SKEETER:
4128 		{
4129 			PARTICLE_DESC *particleDescPtr;
4130 			particle.ParticleID=PARTICLE_MUZZLEFLASH;
4131 			particleDescPtr = &ParticleDescription[particle.ParticleID];
4132 
4133 			particle.Colour = RGBALIGHT_MAKE(particleDescPtr->RedScale[CurrentVisionMode],particleDescPtr->GreenScale[CurrentVisionMode],particleDescPtr->BlueScale[CurrentVisionMode],particleDescPtr->Alpha);
4134 			particle.Size = particleDescPtr->Size;
4135 
4136 			RenderParticle(&particle);
4137 			particle.Position.vx += MUL_FIXED(20,directionPtr->vx);
4138 			particle.Position.vy += MUL_FIXED(20,directionPtr->vy);
4139 			particle.Position.vz += MUL_FIXED(20,directionPtr->vz);
4140 			RenderParticle(&particle);
4141 			particle.Position.vx += MUL_FIXED(20,directionPtr->vx);
4142 			particle.Position.vy += MUL_FIXED(20,directionPtr->vy);
4143 			particle.Position.vz += MUL_FIXED(20,directionPtr->vz);
4144 			RenderParticle(&particle);
4145 			{
4146 				int i = 16;
4147 				particle.Size = 20;
4148 
4149 				while(i--)
4150 				{
4151 					RenderParticle(&particle);
4152 					particle.Position.vx = positionPtr->vx + MUL_FIXED(100,directionPtr->vx) + (FastRandom()&127)-64;
4153 					particle.Position.vy = positionPtr->vy + MUL_FIXED(100,directionPtr->vy) + (FastRandom()&127)-64;
4154 					particle.Position.vz = positionPtr->vz + MUL_FIXED(100,directionPtr->vz) + (FastRandom()&127)-64;
4155 				}
4156 
4157 			}
4158 			break;
4159 		}
4160 		default:
4161 		{
4162 			LOCALASSERT(0);
4163 			return;
4164 		}
4165 	}
4166 	D3D_DecalSystem_End();
4167 
4168 }
4169 
DrawFrisbeePlasmaBolt(VECTORCH * positionPtr,VECTORCH * directionPtr)4170 void DrawFrisbeePlasmaBolt(VECTORCH *positionPtr,VECTORCH *directionPtr)
4171 {
4172 	int i = 16;
4173 	PARTICLE particle;
4174 
4175 	particle.Position = *positionPtr;
4176 
4177 	particle.ParticleID=PARTICLE_MUZZLEFLASH;
4178 
4179 	particle.Colour = RGBALIGHT_MAKE(255,255,255,255);
4180 	particle.Size = 200;
4181 
4182 	while(i--)
4183 	{
4184 		RenderParticle(&particle);
4185 		particle.Position.vx -= MUL_FIXED(50,directionPtr->vx);
4186 		particle.Position.vy -= MUL_FIXED(50,directionPtr->vy);
4187 		particle.Position.vz -= MUL_FIXED(50,directionPtr->vz);
4188 		particle.Size -= 10;
4189 	}
4190 
4191 }
4192 
DrawPredatorPlasmaBolt(VECTORCH * positionPtr,VECTORCH * directionPtr)4193 void DrawPredatorPlasmaBolt(VECTORCH *positionPtr,VECTORCH *directionPtr)
4194 {
4195 	int i = 16;
4196 	PARTICLE particle;
4197 
4198 	particle.Position = *positionPtr;
4199 
4200 	particle.ParticleID=PARTICLE_MUZZLEFLASH;
4201 
4202 	particle.Colour = RGBALIGHT_MAKE(50,255,255,255);
4203 	particle.Size = 200;
4204 
4205 	while(i--)
4206 	{
4207 		RenderParticle(&particle);
4208 		particle.Position.vx -= MUL_FIXED(50,directionPtr->vx);
4209 		particle.Position.vy -= MUL_FIXED(50,directionPtr->vy);
4210 		particle.Position.vz -= MUL_FIXED(50,directionPtr->vz);
4211 		particle.Size -= 10;
4212 	}
4213 
4214 }
4215 
DrawSmallPredatorPlasmaBolt(VECTORCH * positionPtr,VECTORCH * directionPtr)4216 void DrawSmallPredatorPlasmaBolt(VECTORCH *positionPtr,VECTORCH *directionPtr)
4217 {
4218 	#if 0
4219 	int i = 16;
4220 	PARTICLE particle;
4221 
4222 	particle.Position = *positionPtr;
4223 
4224 	particle.ParticleID=PARTICLE_MUZZLEFLASH;
4225 
4226 	particle.Colour = RGBALIGHT_MAKE(50,255,255,255);
4227 	particle.Size = 100;
4228 
4229 	while(i--)
4230 	{
4231 		RenderParticle(&particle);
4232 		particle.Position.vx -= MUL_FIXED(25,directionPtr->vx);
4233 		particle.Position.vy -= MUL_FIXED(25,directionPtr->vy);
4234 		particle.Position.vz -= MUL_FIXED(25,directionPtr->vz);
4235 		particle.Size -= 5;
4236 	}
4237 	#else
4238 	PARTICLE particle;
4239 
4240 	particle.Position = *positionPtr;
4241 
4242 	particle.ParticleID=PARTICLE_ELECTRICALPLASMASPHERE;
4243 
4244 	particle.Colour = RGBALIGHT_MAKE(255,255,255,128);
4245 	particle.Size = 200;
4246 
4247 	RenderParticle(&particle);
4248 	particle.ParticleID=PARTICLE_MUZZLEFLASH;
4249 	particle.Colour = RGBALIGHT_MAKE(255,255,255,64);
4250 	particle.Size = 1000;
4251 	RenderParticle(&particle);
4252 	RenderParticle(&particle);
4253 
4254 	#endif
4255 
4256 }
4257 
4258 
4259 
MakeFlareParticle(DYNAMICSBLOCK * dynPtr)4260 void MakeFlareParticle(DYNAMICSBLOCK *dynPtr)
4261 {
4262 //	int i = MUL_FIXED(4,density);
4263 //	while(i--)
4264 	{
4265 		VECTORCH velocity;
4266 		velocity.vx = ((FastRandom()&2047) - 1024);
4267 		velocity.vy = ((FastRandom()&2047) - 1024);
4268 		velocity.vz = (1000+(FastRandom()&255))*2;
4269 		RotateVector(&velocity,&(dynPtr->OrientMat));
4270 		MakeParticle(&(dynPtr->Position),&(velocity),PARTICLE_FLARESMOKE);
4271 	}
4272 }
MakeRocketTrailParticles(VECTORCH * prevPositionPtr,VECTORCH * positionPtr)4273 void MakeRocketTrailParticles(VECTORCH *prevPositionPtr, VECTORCH *positionPtr)
4274 {
4275 	VECTORCH disp;
4276 
4277 	disp.vx = positionPtr->vx - prevPositionPtr->vx;
4278 	disp.vy = positionPtr->vy - prevPositionPtr->vy;
4279 	disp.vz = positionPtr->vz - prevPositionPtr->vz;
4280 
4281 	if (disp.vx!=0 || disp.vy!=0 || disp.vz!=0)
4282 	{
4283 		int i=16;
4284 		do
4285 		{
4286 			{
4287 				VECTORCH position;
4288 				VECTORCH velocity;
4289 				velocity.vx = (FastRandom()&1023) - 512;
4290 				velocity.vy = (FastRandom()&1023) - 512;
4291 				velocity.vz = (FastRandom()&1023) - 512;
4292 
4293 				position.vx = prevPositionPtr->vx + (disp.vx*i)/16;
4294 				position.vy = prevPositionPtr->vy + (disp.vy*i)/16;
4295 				position.vz = prevPositionPtr->vz + (disp.vz*i)/16;
4296 
4297 				MakeParticle(&position,&(velocity),PARTICLE_BLACKSMOKE);
4298 			}
4299 		}
4300 		while(i--);
4301 	}
4302 }
MakeGrenadeTrailParticles(VECTORCH * prevPositionPtr,VECTORCH * positionPtr)4303 void MakeGrenadeTrailParticles(VECTORCH *prevPositionPtr, VECTORCH *positionPtr)
4304 {
4305 	VECTORCH disp;
4306 
4307 	disp.vx = positionPtr->vx - prevPositionPtr->vx;
4308 	disp.vy = positionPtr->vy - prevPositionPtr->vy;
4309 	disp.vz = positionPtr->vz - prevPositionPtr->vz;
4310 
4311 	if (!(disp.vx==0 && disp.vy==0 && disp.vz==0))
4312 	{
4313 		int i=8;
4314 		do
4315 		{
4316 			{
4317 				VECTORCH position;
4318 				VECTORCH velocity;
4319 				velocity.vx = (FastRandom()&1023) - 512;
4320 				velocity.vy = (FastRandom()&1023) - 512;
4321 				velocity.vz = (FastRandom()&1023) - 512;
4322 
4323 				position.vx = prevPositionPtr->vx + (disp.vx*i)/16;
4324 				position.vy = prevPositionPtr->vy + (disp.vy*i)/16;
4325 				position.vz = prevPositionPtr->vz + (disp.vz*i)/16;
4326 
4327 				MakeParticle(&position,&(velocity),PARTICLE_FLARESMOKE);
4328 			}
4329 		}
4330 		while(i--);
4331 	}
4332 }
4333 
MakeImpactSmoke(MATRIXCH * orientationPtr,VECTORCH * positionPtr)4334 void MakeImpactSmoke(MATRIXCH *orientationPtr, VECTORCH *positionPtr)
4335 {
4336 	int i = 5;
4337 	while(i--)
4338 	{
4339 		VECTORCH velocity;
4340 		velocity.vx = ((FastRandom()&1023) - 512);
4341 		velocity.vy = ((FastRandom()&1023) - 512);
4342 		velocity.vz = (255+(FastRandom()&255));
4343 		RotateVector(&velocity,orientationPtr);
4344 		MakeParticle(positionPtr,&(velocity),PARTICLE_IMPACTSMOKE);
4345 	}
4346 }
4347 
MakeImpactSparks(VECTORCH * incidentPtr,VECTORCH * normalPtr,VECTORCH * positionPtr)4348 void MakeImpactSparks(VECTORCH *incidentPtr, VECTORCH *normalPtr, VECTORCH *positionPtr)
4349 {
4350 	int noOfSparks = 5;
4351 	VECTORCH velocity;
4352 	int d = -2*DotProduct(incidentPtr,normalPtr);
4353 	velocity.vx = (incidentPtr->vx + MUL_FIXED(d,normalPtr->vx))>>3;
4354 	velocity.vy = (incidentPtr->vy + MUL_FIXED(d,normalPtr->vy))>>3;
4355 	velocity.vz = (incidentPtr->vz + MUL_FIXED(d,normalPtr->vz))>>3;
4356 
4357 	do
4358 	{
4359 
4360 //		VECTORCH velocity;
4361 		velocity.vx = velocity.vx + (FastRandom()&2047)-1024;
4362 		velocity.vy = velocity.vy + (FastRandom()&2047)-1024;
4363 		velocity.vz = velocity.vz + (FastRandom()&2047)-1024;
4364 		MakeParticle(positionPtr,&velocity,PARTICLE_RICOCHET_SPARK);
4365 	}
4366 	while(--noOfSparks);
4367 	MakeRicochetSound(positionPtr);
4368 }
4369 
MakeSprayOfSparks(MATRIXCH * orientationPtr,VECTORCH * positionPtr)4370 void MakeSprayOfSparks(MATRIXCH *orientationPtr, VECTORCH *positionPtr)
4371 {
4372 	int noOfSparks = 15;
4373 	do
4374 	{
4375 
4376 		VECTORCH velocity;
4377 		velocity.vx = (FastRandom()&2047)-1024;
4378 		velocity.vy = (FastRandom()&2047);
4379 		velocity.vz = -(FastRandom()&2047)-1024;
4380 		RotateVector(&velocity,orientationPtr);
4381 		MakeParticle(positionPtr,&velocity,PARTICLE_SPARK);
4382 	}
4383 	while(--noOfSparks);
4384 
4385 	MakeLightElement(positionPtr,LIGHTELEMENT_ELECTRICAL_SPARKS);
4386 }
4387 
MakeVolumetricExplosionAt(VECTORCH * positionPtr,enum EXPLOSION_ID explosionID)4388 void MakeVolumetricExplosionAt(VECTORCH *positionPtr, enum EXPLOSION_ID explosionID)
4389 {
4390 	switch (explosionID)
4391 	{
4392 		case EXPLOSION_HUGE:
4393 		case EXPLOSION_HUGE_NOCOLLISIONS:
4394 		{
4395 			VOLUMETRIC_EXPLOSION *expPtr;
4396 			int i;
4397 			int r;
4398 
4399 			/* KJL 11:49:25 19/08/98 - check to see if explosion is inside environment */
4400 			{
4401 				MODULE *module = ModuleFromPosition(positionPtr, (MODULE*)NULL);
4402 				if (!module) return;
4403 			}
4404 
4405 			expPtr = AllocateVolumetricExplosion();
4406 			r = (FastRandom()&7)+1;
4407 
4408 			if (explosionID == EXPLOSION_HUGE_NOCOLLISIONS)
4409 			{
4410 				expPtr->UseCollisions = 0;
4411 			}
4412 			else
4413 			{
4414 				expPtr->UseCollisions = 1;
4415 			}
4416 
4417 			for(i=0; i<SPHERE_VERTICES; i++)
4418 			{
4419 				expPtr->Position[i] = *positionPtr;
4420 				expPtr->Velocity[i].vx = SphereVertex[i].vx;
4421 				expPtr->Velocity[i].vy = SphereVertex[i].vy;
4422 				expPtr->Velocity[i].vz = SphereVertex[i].vz;
4423 				expPtr->BeenStopped[i] = 0;
4424 				expPtr->RipplePhase[i] = FastRandom()&4095;
4425 				expPtr->NumberVerticesMoving=SPHERE_VERTICES;
4426 			}
4427 			expPtr->LifeTime = ONE_FIXED-1;
4428 			expPtr->ExplosionPhase = 1;
4429 
4430 			for(i=0; i<r; i++)
4431 			{
4432 				CreateFlamingDebris(positionPtr,&SphereVertex[FastRandom()%SPHERE_VERTICES]);
4433 			}
4434 			if ((positionPtr->vx!=Player->ObWorld.vx)
4435 		      ||(positionPtr->vy!=Player->ObWorld.vy)
4436 			  ||(positionPtr->vz!=Player->ObWorld.vz))
4437 			{
4438 				MakeLightElement(positionPtr, LIGHTELEMENT_EXPLOSION);
4439 			}
4440 
4441 			#if 1
4442 			for (i=0; i<LocalDetailLevels.NumberOfSmokeParticlesFromLargeExplosion; i++)
4443 			{
4444 				VECTORCH position = *positionPtr;
4445 				position.vx += (FastRandom()&2047)-1024;
4446 				position.vy += (FastRandom()&2047)-1024;
4447 				position.vz += (FastRandom()&2047)-1024;
4448 				MakeParticle(&position, positionPtr, PARTICLE_SMOKECLOUD);
4449 			}
4450 			#endif
4451 			break;
4452 		}
4453 		case EXPLOSION_MOLOTOV:
4454 		{
4455 			MakeMolotovExplosionAt(positionPtr,0);
4456 			break;
4457 		}
4458 		case EXPLOSION_PULSEGRENADE:
4459 		case EXPLOSION_SMALL_NOCOLLISIONS:
4460 		{
4461 			VOLUMETRIC_EXPLOSION *expPtr;
4462 			int i;
4463 			int r;
4464 
4465 			/* KJL 11:49:25 19/08/98 - check to see if explosion is inside environment */
4466 			{
4467 				MODULE *module = ModuleFromPosition(positionPtr, (MODULE*)NULL);
4468 				if (!module) return;
4469 			}
4470 			#if 1
4471 			expPtr = AllocateVolumetricExplosion();
4472 
4473 			if (explosionID == EXPLOSION_SMALL_NOCOLLISIONS)
4474 			{
4475 				expPtr->UseCollisions = 0;
4476 			}
4477 			else
4478 			{
4479 				expPtr->UseCollisions = 1;
4480 			}
4481 			r = (FastRandom()&7)+1;
4482 
4483 			for(i=0; i<SPHERE_VERTICES; i++)
4484 			{
4485 				expPtr->Position[i] = *positionPtr;
4486 				expPtr->Velocity[i].vx = SphereVertex[i].vx;
4487 				expPtr->Velocity[i].vy = SphereVertex[i].vy;
4488 				expPtr->Velocity[i].vz = SphereVertex[i].vz;
4489 				expPtr->BeenStopped[i] = 0;
4490 				expPtr->RipplePhase[i] = FastRandom()&4095;
4491 				expPtr->NumberVerticesMoving=SPHERE_VERTICES;
4492 			}
4493 			expPtr->LifeTime = ONE_FIXED/2;
4494 			expPtr->ExplosionPhase = 1;
4495 			#endif
4496 			#if 0
4497 			for(i=0; i<r; i++)
4498 			{
4499 				CreateFlamingDebris(positionPtr,&SphereVertex[FastRandom()%SPHERE_VERTICES]);
4500 			}
4501 			#endif
4502 			if ((positionPtr->vx!=Player->ObWorld.vx)
4503 		      ||(positionPtr->vy!=Player->ObWorld.vy)
4504 			  ||(positionPtr->vz!=Player->ObWorld.vz))
4505 			{
4506 				MakeLightElement(positionPtr, LIGHTELEMENT_EXPLOSION);
4507 //				MakeLightElement(positionPtr, LIGHTELEMENT_ELECTRICAL_EXPLOSION);
4508 			}
4509 
4510 			#if 1
4511 			for (i=0; i<LocalDetailLevels.NumberOfSmokeParticlesFromSmallExplosion; i++)
4512 			{
4513 				VECTORCH position = *positionPtr;
4514 				position.vx += (FastRandom()&1023)-512;
4515 				position.vy += (FastRandom()&1023)-512;
4516 				position.vz += (FastRandom()&1023)-512;
4517 				MakeParticle(&position, positionPtr, PARTICLE_SMOKECLOUD);
4518 			}
4519 			#endif
4520 			break;
4521 		}
4522 		case EXPLOSION_PREDATORPISTOL:
4523 		{
4524 			MakeElectricalExplosion(positionPtr);
4525 			break;
4526 		}
4527 		default:
4528 			break;
4529 	}
4530 }
4531 
4532 
MakeFlechetteExplosionAt(VECTORCH * positionPtr,int seed)4533 void MakeFlechetteExplosionAt(VECTORCH *positionPtr,int seed)
4534 {
4535 	extern SOUND3DDATA Explosion_SoundData;
4536 	int i;
4537 	enum PARTICLE_ID particle_to_use;
4538 
4539     Explosion_SoundData.position=*positionPtr;
4540     Sound_Play(SID_FRAG_RICOCHETS,"n",&Explosion_SoundData);
4541 
4542     if(!seed)
4543 	{
4544 		//need to get a random number seed for this explosion
4545 		while(!seed) seed=FastRandom();
4546 
4547 		//explosion originated on this computer , so use damaging type
4548 		particle_to_use=PARTICLE_FLECHETTE;
4549 
4550 		//if in a network game , send explosion to other players
4551 		if(AvP.Network!=I_No_Network)
4552 		{
4553 			AddNetMsg_MakeFlechetteExplosion(positionPtr,seed);
4554 		}
4555 	}
4556 	else
4557 	{
4558 		//explosion passed across the network
4559 		//use the nondamaging flechette
4560 		particle_to_use=PARTICLE_FLECHETTE_NONDAMAGING;
4561 	}
4562 	SetSeededFastRandom(seed);
4563 
4564 	/* KJL 11:49:25 19/08/98 - check to see if explosion is inside environment */
4565 	{
4566 		MODULE *module = ModuleFromPosition(positionPtr, (MODULE*)NULL);
4567 		if (!module) return;
4568 	}
4569 	#if 0
4570 	for(i=0; i<SPHERE_VERTICES; i++)
4571 	{
4572 		if (SphereVertex[i].vy<0) MakeParticle(positionPtr,&SphereVertex[i],PARTICLE_FLECHETTE);
4573 	}
4574 	#else
4575 	for (i=0; i<100; i++)
4576 	{
4577 		VECTORCH velocity;
4578 		int phi = SeededFastRandom()&4095;
4579 
4580 		velocity.vy = -(SeededFastRandom()&65535);
4581 		{
4582 			float y = ((float)velocity.vy)/65536.0;
4583 			y = sqrt(1-y*y);
4584 
4585 			f2i(velocity.vx,(float)GetCos(phi)*y);
4586 			f2i(velocity.vz,(float)GetSin(phi)*y);
4587 		}
4588 
4589 		MakeParticle(positionPtr, &velocity, particle_to_use);
4590 	}
4591 	#endif
4592 	MakeLightElement(positionPtr, LIGHTELEMENT_EXPLOSION);
4593 }
MakeMolotovExplosionAt(VECTORCH * positionPtr,int seed)4594 void MakeMolotovExplosionAt(VECTORCH *positionPtr,int seed)
4595 {
4596 	int i;
4597 	enum PARTICLE_ID particle_to_use;
4598 
4599     if(!seed)
4600 	{
4601 		//need to get a random number seed for this explosion
4602 		while(!seed) seed=FastRandom();
4603 
4604 		//explosion originated on this computer , so use damaging type
4605 		particle_to_use=PARTICLE_MOLOTOVFLAME;
4606 
4607 		//if in a network game , send explosion to other players
4608 		if(AvP.Network!=I_No_Network)
4609 		{
4610   //			AddNetMsg_MakeFlechetteExplosion(positionPtr,seed);
4611 		}
4612 	}
4613 	else
4614 	{
4615 		//explosion passed across the network
4616 		//use the nondamaging flechette
4617  //		particle_to_use=PARTICLE_FLECHETTE_NONDAMAGING;
4618 	}
4619 	SetSeededFastRandom(seed);
4620 
4621 	/* KJL 11:49:25 19/08/98 - check to see if explosion is inside environment */
4622 	{
4623 		MODULE *module = ModuleFromPosition(positionPtr, (MODULE*)NULL);
4624 		if (!module) return;
4625 	}
4626 	for (i=0; i<100; i++)
4627 	{
4628 		VECTORCH velocity;
4629 		int phi = SeededFastRandom()&4095;
4630 
4631 		velocity.vy = -(SeededFastRandom()&65535);
4632 		{
4633 			float y = ((float)velocity.vy)/65536.0;
4634 			y = sqrt(1-y*y);
4635 
4636 			f2i(velocity.vx,(float)GetCos(phi)*y);
4637 			f2i(velocity.vz,(float)GetSin(phi)*y);
4638 		}
4639 		velocity.vx /= 8;
4640 		velocity.vy /= 16;
4641 		velocity.vz /= 8;
4642 
4643 		MakeParticle(positionPtr, &velocity, particle_to_use);
4644 	}
4645    //	MakeLightElement(positionPtr, LIGHTELEMENT_EXPLOSION);
4646 }
4647 
4648 
HandleVolumetricExplosion(VOLUMETRIC_EXPLOSION * expPtr)4649 static void HandleVolumetricExplosion(VOLUMETRIC_EXPLOSION *expPtr)
4650 {
4651 	int i;
4652 	PARTICLE particle;
4653 	int velocityModifier;
4654 	particle.ParticleID = PARTICLE_EXPLOSIONFIRE;
4655 
4656 	if (!expPtr->LifeTime) return;
4657 	RenderExplosionSurface(expPtr);
4658 
4659 	if (expPtr->ExplosionPhase)
4660 	{
4661 		{
4662 			int v = (DIV_FIXED(SPHERE_VERTICES,expPtr->NumberVerticesMoving+1)+ONE_FIXED);
4663 			velocityModifier = MUL_FIXED(GetSin(expPtr->LifeTime/64)/16,v);
4664 		}
4665 
4666 		for(i=0; i<SPHERE_VERTICES; i++)
4667 		{
4668 			int v;
4669 			VECTORCH obstacleNormal = {0,0,0};
4670 			int moduleIndex;
4671 			if ((expPtr->Velocity[i].vx==0)
4672 			   &&(expPtr->Velocity[i].vy==0)
4673 			   &&(expPtr->Velocity[i].vz==0))
4674 			 continue;
4675 			particle.Velocity = expPtr->Velocity[i];
4676 			#if 1
4677 			{
4678 				v = GetSin((CloakingPhase*4+expPtr->RipplePhase[i])&4095)/4;
4679 				v = velocityModifier+MUL_FIXED(v,velocityModifier);
4680 			}
4681 			#endif
4682 			particle.Velocity.vx = MUL_FIXED(particle.Velocity.vx,v);
4683 			particle.Velocity.vy = MUL_FIXED(particle.Velocity.vy,v);
4684 			particle.Velocity.vz = MUL_FIXED(particle.Velocity.vz,v);
4685 
4686 
4687 			particle.Position = expPtr->Position[i];
4688 
4689 			if(LocalDetailLevels.ExplosionsDeformToEnvironment && expPtr->UseCollisions)
4690 			{
4691 				if(ParticleDynamics(&particle,&obstacleNormal,&moduleIndex))
4692 				{
4693 					int magOfPerpImp = DotProduct(&obstacleNormal,&(expPtr->Velocity[i]));
4694 					expPtr->Velocity[i].vx -= MUL_FIXED(obstacleNormal.vx, magOfPerpImp);
4695 					expPtr->Velocity[i].vy -= MUL_FIXED(obstacleNormal.vy, magOfPerpImp);
4696 					expPtr->Velocity[i].vz -= MUL_FIXED(obstacleNormal.vz, magOfPerpImp);
4697 
4698 					if(!expPtr->BeenStopped[i])
4699 					{
4700 						expPtr->BeenStopped[i] = 1;
4701 						expPtr->NumberVerticesMoving--;
4702 					}
4703 				}
4704 			}
4705 			else
4706 			{
4707 				particle.Position.vx += MUL_FIXED(particle.Velocity.vx,NormalFrameTime);
4708 				particle.Position.vy += MUL_FIXED(particle.Velocity.vy,NormalFrameTime);
4709 				particle.Position.vz += MUL_FIXED(particle.Velocity.vz,NormalFrameTime);
4710 			}
4711 			expPtr->Position[i] = particle.Position;
4712 		}
4713 
4714 
4715 		expPtr->LifeTime -= NormalFrameTime;
4716 
4717 		if (expPtr->LifeTime<=0)
4718 		{
4719 			expPtr->LifeTime=0;
4720 		}
4721 	}
4722 }
4723 
MakeOldVolumetricExplosionAt(VECTORCH * positionPtr)4724 void MakeOldVolumetricExplosionAt(VECTORCH *positionPtr)
4725 {
4726 	int noRequired = 32;//MUL_FIXED(2500,NormalFrameTime);
4727 	int i;
4728 //	VECTORCH zero={0,0,0};
4729 	for (i=0; i<noRequired; i++)
4730 	{
4731 		VECTORCH velocity;
4732 		int phi = FastRandom()&4095;
4733 		int speed = 6000*4+(FastRandom()&4095);
4734 
4735 		velocity.vz = (FastRandom()&131071) - ONE_FIXED;
4736 		{
4737 			float z = ((float)velocity.vz)/65536.0;
4738 			z = sqrt(1-z*z);
4739 
4740 			f2i(velocity.vx,(float)GetCos(phi)*z);
4741 			f2i(velocity.vy,(float)GetSin(phi)*z);
4742 		}
4743 
4744 		velocity.vx = MUL_FIXED(velocity.vx,speed);
4745 		velocity.vy = MUL_FIXED(velocity.vy,speed);
4746 		velocity.vz = MUL_FIXED(velocity.vz,speed);
4747 
4748 		MakeParticle(positionPtr, &velocity, PARTICLE_EXPLOSIONFIRE);
4749 	}
4750 
4751 	MakeLightElement(positionPtr, LIGHTELEMENT_EXPLOSION);
4752 }
4753 
MakePlasmaExplosion(VECTORCH * positionPtr,VECTORCH * fromPositionPtr,enum EXPLOSION_ID explosionID)4754 extern void MakePlasmaExplosion(VECTORCH *positionPtr, VECTORCH *fromPositionPtr, enum EXPLOSION_ID explosionID)
4755 {
4756 	switch (explosionID)
4757 	{
4758 		case EXPLOSION_DISSIPATINGPLASMA:
4759 		{
4760 			MakeParticle(positionPtr,positionPtr,PARTICLE_BLUEPLASMASPHERE);
4761 			MakeLightElement(positionPtr,LIGHTELEMENT_PLASMACASTERHIT);
4762 			MakeBloodExplosion(fromPositionPtr, 127, positionPtr, 200, PARTICLE_ORANGE_SPARK);
4763 			Sound_Play(SID_PLASMABOLT_DISSIPATE,"d",positionPtr);
4764 			break;
4765 		}
4766 		case EXPLOSION_FOCUSEDPLASMA:
4767 		{
4768 			MakeParticle(positionPtr,positionPtr,PARTICLE_BLUEPLASMASPHERE);
4769 			MakeLightElement(positionPtr,LIGHTELEMENT_PLASMACASTERHIT);
4770 			MakeFocusedExplosion(fromPositionPtr, positionPtr, 100, PARTICLE_ORANGE_PLASMA);
4771 			Sound_Play(SID_PLASMABOLT_HIT,"d",positionPtr);
4772 			break;
4773 		}
4774 		default:
4775 			break;
4776 	}
4777 }
MakeElectricalExplosion(VECTORCH * positionPtr)4778 extern void MakeElectricalExplosion(VECTORCH *positionPtr)
4779 {
4780 	{
4781 		PredPistolExplosion_SoundData.position=*positionPtr;
4782 		Sound_Play(SID_WIL_PRED_PISTOL_EXPLOSION,"n",&PredPistolExplosion_SoundData);
4783    	}
4784 	//Sound_Play(SID_WIL_PRED_PISTOL_EXPLOSION,"d",positionPtr);
4785 	MakeParticle(positionPtr,positionPtr,PARTICLE_ELECTRICALPLASMASPHERE);
4786 	MakeLightElement(positionPtr, LIGHTELEMENT_ELECTRICAL_EXPLOSION);
4787 }
4788 
MakeBloodExplosion(VECTORCH * originPtr,int creationRadius,VECTORCH * blastPositionPtr,int noOfParticles,enum PARTICLE_ID particleID)4789 void MakeBloodExplosion(VECTORCH *originPtr, int creationRadius, VECTORCH *blastPositionPtr, int noOfParticles, enum PARTICLE_ID particleID)
4790 {
4791 	VECTORCH blastDir;
4792 	int i;
4793 
4794 	/* Dividing by zero can be bad for your health */
4795 	LOCALASSERT(creationRadius!=0);
4796 
4797 	blastDir.vx = originPtr->vx - blastPositionPtr->vx;
4798 	blastDir.vy = originPtr->vy - blastPositionPtr->vy;
4799 	blastDir.vz = originPtr->vz - blastPositionPtr->vz;
4800 
4801 	for (i=0; i<noOfParticles; i++)
4802 	{
4803 		VECTORCH velocity;
4804 		VECTORCH position;
4805 		int phi = FastRandom()&4095;
4806 		int speed = 6000+(FastRandom()&4095);
4807 		int r;
4808 		//speed = FastRandom()&2047;
4809 
4810 		velocity.vz = (FastRandom()&131071) - ONE_FIXED;
4811 		{
4812 			float z = ((float)velocity.vz)/65536.0;
4813 			z = sqrt(1-z*z);
4814 
4815 			f2i(velocity.vx,(float)GetCos(phi)*z);
4816 			f2i(velocity.vy,(float)GetSin(phi)*z);
4817 		}
4818 
4819 		if (DotProduct(&velocity,&blastDir)<0)
4820 		{
4821 			velocity.vx = -velocity.vx;
4822 			velocity.vy = -velocity.vy;
4823 			velocity.vz = -velocity.vz;
4824 		}
4825 
4826 		r = FastRandom()%creationRadius;
4827 		position.vx = originPtr->vx + MUL_FIXED(velocity.vx,r);
4828 		position.vy = originPtr->vy + MUL_FIXED(velocity.vy,r);
4829 		position.vz = originPtr->vz + MUL_FIXED(velocity.vz,r);
4830 
4831 		velocity.vx = MUL_FIXED(velocity.vx,speed);
4832 		velocity.vy = MUL_FIXED(velocity.vy,speed);
4833 		velocity.vz = MUL_FIXED(velocity.vz,speed);
4834 
4835 
4836 		MakeParticle(&position, &velocity, particleID);
4837 	}
4838 }
4839 
4840 
MakeFocusedExplosion(VECTORCH * originPtr,VECTORCH * blastPositionPtr,int noOfParticles,enum PARTICLE_ID particleID)4841 void MakeFocusedExplosion(VECTORCH *originPtr, VECTORCH *blastPositionPtr, int noOfParticles, enum PARTICLE_ID particleID)
4842 {
4843 	VECTORCH blastDir;
4844 	int i;
4845 
4846 	blastDir.vx = originPtr->vx - blastPositionPtr->vx;
4847 	blastDir.vy = originPtr->vy - blastPositionPtr->vy;
4848 	blastDir.vz = originPtr->vz - blastPositionPtr->vz;
4849 
4850 	for (i=0; i<noOfParticles; i++)
4851 	{
4852 		VECTORCH velocity,position;
4853 		int phi = FastRandom()&4095;
4854 		int speed = 6000+(FastRandom()&4095);
4855 		int r;
4856 		speed = FastRandom()&2047;
4857 
4858 		velocity.vz = (FastRandom()&131071) - ONE_FIXED;
4859 		{
4860 			float z = ((float)velocity.vz)/65536.0;
4861 			z = sqrt(1-z*z);
4862 
4863 			f2i(velocity.vx,(float)GetCos(phi)*z);
4864 			f2i(velocity.vy,(float)GetSin(phi)*z);
4865 		}
4866 
4867 		if (DotProduct(&velocity,&blastDir)<0)
4868 		{
4869 			velocity.vx = -velocity.vx;
4870 			velocity.vy = -velocity.vy;
4871 			velocity.vz = -velocity.vz;
4872 		}
4873 		r = FastRandom()%127;
4874 		position.vx = originPtr->vx + MUL_FIXED(velocity.vx,r);
4875 		position.vy = originPtr->vy + MUL_FIXED(velocity.vy,r);
4876 		position.vz = originPtr->vz + MUL_FIXED(velocity.vz,r);
4877 
4878 		velocity.vx = MUL_FIXED(velocity.vx,speed);
4879 		velocity.vy = MUL_FIXED(velocity.vy,speed);
4880 		velocity.vz = MUL_FIXED(velocity.vz,speed);
4881 
4882 
4883 		MakeParticle(&position, &velocity, particleID);
4884 	}
4885 }
4886 
4887 
4888 
4889 
MakePlasmaTrailParticles(DYNAMICSBLOCK * dynPtr,int number)4890 void MakePlasmaTrailParticles(DYNAMICSBLOCK *dynPtr, int number)
4891 {
4892 
4893 	VECTORCH disp;
4894 
4895 	disp.vx = dynPtr->Position.vx - dynPtr->PrevPosition.vx;
4896 	disp.vy = dynPtr->Position.vy - dynPtr->PrevPosition.vy;
4897 	disp.vz = dynPtr->Position.vz - dynPtr->PrevPosition.vz;
4898 
4899   //	if (disp.vx!=0 || disp.vy!=0 || disp.vz!=0)
4900 	{
4901 		int i=number;
4902 		do
4903 		{
4904 			VECTORCH velocity;
4905 			VECTORCH position;
4906 			#if 1
4907 
4908 			int phi = FastRandom()&4095;
4909 			int speed = 512;
4910 
4911 			velocity.vz = (FastRandom()&131071) - ONE_FIXED;
4912 			{
4913 				float z = ((float)velocity.vz)/65536.0;
4914 				z = sqrt(1-z*z);
4915 
4916 				f2i(velocity.vx,(float)GetCos(phi)*z);
4917 				f2i(velocity.vy,(float)GetSin(phi)*z);
4918 			}
4919 
4920 			velocity.vx = MUL_FIXED(velocity.vx,speed);//+dynPtr->LinVelocity.vx/32;
4921 			velocity.vy = MUL_FIXED(velocity.vy,speed);//+dynPtr->LinVelocity.vy/32;
4922 			velocity.vz = MUL_FIXED(velocity.vz,speed);//+dynPtr->LinVelocity.vz/32;
4923 			#else
4924 			velocity.vx = dynPtr->LinVelocity.vx;
4925 			velocity.vy = dynPtr->LinVelocity.vy;
4926 			velocity.vz = dynPtr->LinVelocity.vz;
4927 			#endif
4928 			position.vx = dynPtr->PrevPosition.vx + (disp.vx*i)/number;
4929 			position.vy = dynPtr->PrevPosition.vy + (disp.vy*i)/number;
4930 			position.vz = dynPtr->PrevPosition.vz + (disp.vz*i)/number;
4931 
4932 			MakeParticle(&position, &velocity, PARTICLE_PLASMATRAIL);
4933 		}
4934 		while(i--);
4935 	}
4936 }
4937 
MakeDewlineTrailParticles(DYNAMICSBLOCK * dynPtr,int number)4938 void MakeDewlineTrailParticles(DYNAMICSBLOCK *dynPtr, int number)
4939 {
4940 
4941 	VECTORCH disp;
4942 
4943 	disp.vx = dynPtr->Position.vx - dynPtr->PrevPosition.vx;
4944 	disp.vy = dynPtr->Position.vy - dynPtr->PrevPosition.vy;
4945 	disp.vz = dynPtr->Position.vz - dynPtr->PrevPosition.vz;
4946 
4947   //	if (disp.vx!=0 || disp.vy!=0 || disp.vz!=0)
4948 	{
4949 		int i=number;
4950 		do
4951 		{
4952 			VECTORCH velocity;
4953 			VECTORCH position;
4954 			#if 1
4955 
4956 			int phi = FastRandom()&4095;
4957 			int speed = 256; //512
4958 
4959 			velocity.vz = (FastRandom()&131071) - ONE_FIXED;
4960 			{
4961 				float z = ((float)velocity.vz)/65536.0;
4962 				z = sqrt(1-z*z);
4963 
4964 				f2i(velocity.vx,(float)GetCos(phi)*z);
4965 				f2i(velocity.vy,(float)GetSin(phi)*z);
4966 			}
4967 
4968 			velocity.vx = MUL_FIXED(velocity.vx,speed);//+dynPtr->LinVelocity.vx/32;
4969 			velocity.vy = MUL_FIXED(velocity.vy,speed);//+dynPtr->LinVelocity.vy/32;
4970 			velocity.vz = MUL_FIXED(velocity.vz,speed);//+dynPtr->LinVelocity.vz/32;
4971 			#else
4972 			velocity.vx = dynPtr->LinVelocity.vx;
4973 			velocity.vy = dynPtr->LinVelocity.vy;
4974 			velocity.vz = dynPtr->LinVelocity.vz;
4975 			#endif
4976 			position.vx = dynPtr->PrevPosition.vx + (disp.vx*i)/number;
4977 			position.vy = dynPtr->PrevPosition.vy + (disp.vy*i)/number;
4978 			position.vz = dynPtr->PrevPosition.vz + (disp.vz*i)/number;
4979 
4980 			MakeParticle(&position, &velocity, PARTICLE_DEWLINE);
4981 		}
4982 		while(i--);
4983 	}
4984 }
4985 
DrawXenoborgMainLaserbeam(LASER_BEAM_DESC * laserPtr)4986 void DrawXenoborgMainLaserbeam(LASER_BEAM_DESC *laserPtr)
4987 {
4988 	if (laserPtr->BeamHasHitPlayer)
4989 	{
4990 		int colour;
4991 		switch (CurrentVisionMode)
4992 		{
4993 			default:
4994 			case VISION_MODE_NORMAL:
4995 			{
4996 				colour = 0xff0000ff;
4997 				break;
4998 			}
4999 			case VISION_MODE_IMAGEINTENSIFIER:
5000 			{
5001 				colour = 0xffffffff;
5002 				break;
5003 			}
5004 			case VISION_MODE_PRED_THERMAL:
5005 			case VISION_MODE_PRED_SEEALIENS:
5006 			case VISION_MODE_PRED_SEEPREDTECH:
5007 			{
5008 				colour = 0xffff8000;
5009 			  	break;
5010 			}
5011 		}
5012 		RenderLightFlare(&(laserPtr->SourcePosition),colour);
5013 		RenderLightFlare(&(laserPtr->SourcePosition),0xffffffff);
5014 	}
5015 	else
5016 	{
5017 		PARTICLE particle;
5018 		switch (CurrentVisionMode)
5019 		{
5020 			default:
5021 			case VISION_MODE_NORMAL:
5022 			{
5023 				particle.Colour = RGBALIGHT_MAKE(0,0,255,255);
5024 				break;
5025 			}
5026 			case VISION_MODE_IMAGEINTENSIFIER:
5027 			{
5028 				particle.Colour = RGBALIGHT_MAKE(255,255,255,255);
5029 				break;
5030 			}
5031 			case VISION_MODE_PRED_THERMAL:
5032 			case VISION_MODE_PRED_SEEALIENS:
5033 			case VISION_MODE_PRED_SEEPREDTECH:
5034 			{
5035 				particle.Colour = RGBALIGHT_MAKE(255,128,0,255);
5036 			  	break;
5037 			}
5038 		}
5039 	 	particle.Colour = RGBALIGHT_MAKE(255,255,255,255);
5040 		particle.ParticleID = PARTICLE_PLASMABEAM;
5041 		particle.Position = laserPtr->SourcePosition;
5042 		particle.Offset = laserPtr->TargetPosition;
5043 		particle.Size = 32;
5044 		RenderParticle(&particle);
5045 	 //	particle.Colour = RGBALIGHT_MAKE(255,255,255,255);
5046 	 //	particle.Size = 20;
5047 	 //	RenderParticle(&particle);
5048 
5049 	}
5050 }
5051 /* KJL 16:37:03 20/06/98 - stupid but quick implementation */
5052 #define NO_OF_VERTICES_IN_TRAIL 300
5053 PHEROMONE_TRAIL Trail[NO_OF_VERTICES_IN_TRAIL];
5054 
NewTrailPoint(DYNAMICSBLOCK * dynPtr)5055 void NewTrailPoint(DYNAMICSBLOCK *dynPtr)
5056 {
5057  	PHEROMONE_TRAIL *trailPtr = AllocatePheromoneTrail();
5058 	if (!trailPtr) return;
5059 
5060  	GLOBALASSERT(dynPtr);
5061 	trailPtr->Vertex[0] = dynPtr->Position;
5062    //	trailPtr->Vertex[0].vy -=1000;
5063 
5064 	trailPtr->Perp[0] = *((VECTORCH*)&(dynPtr->OrientMat.mat11));
5065 	trailPtr->Size[0] = 127*65536;
5066 
5067 	trailPtr->Vertex[1] = dynPtr->PrevPosition;
5068    //	trailPtr->Vertex[1].vy -=1000;
5069 	trailPtr->Perp[1] = *((VECTORCH*)&(dynPtr->PrevOrientMat.mat11));
5070 	trailPtr->Size[1] = 127*65536-MUL_FIXED(TRAIL_DECAY_SPEED,PrevNormalFrameTime);
5071 }
5072 
5073 VECTORCH PlayerPheromoneTrailPerp = {0,0,0};
PlayerPheromoneTrail(DYNAMICSBLOCK * dynPtr)5074 void PlayerPheromoneTrail(DYNAMICSBLOCK *dynPtr)
5075 {
5076  	PHEROMONE_TRAIL *trailPtr = AllocatePheromoneTrail();
5077 	VECTORCH disp;
5078 	if (!trailPtr) return;
5079 
5080 	disp.vx = dynPtr->Position.vx-dynPtr->PrevPosition.vx;
5081 	disp.vy = dynPtr->Position.vy-dynPtr->PrevPosition.vy;
5082 	disp.vz = dynPtr->Position.vz-dynPtr->PrevPosition.vz;
5083 
5084 	trailPtr->Vertex[0] = dynPtr->Position;
5085 	#if 1
5086 	trailPtr->Vertex[0].vx -= dynPtr->OrientMat.mat21>>6;
5087 	trailPtr->Vertex[0].vy -= dynPtr->OrientMat.mat22>>6;
5088 	trailPtr->Vertex[0].vz -= dynPtr->OrientMat.mat23>>6;
5089 	#endif
5090  //	trailPtr->Vertex[0].vy -= 500;
5091 
5092 	trailPtr->Perp[0] = *((VECTORCH*)&(dynPtr->OrientMat.mat11));
5093 #if 0
5094 	trailPtr->Perp[0].vx = disp.vz - disp.vy;
5095 	trailPtr->Perp[0].vy = disp.vx - disp.vz;
5096 	trailPtr->Perp[0].vz = disp.vy - disp.vx;
5097 	if (trailPtr->Perp[0].vx!=0 || trailPtr->Perp[0].vy !=0 || trailPtr->Perp[0].vz!=0)
5098 	{
5099 		Normalise(&trailPtr->Perp[0]);
5100 	}
5101 	else
5102 	{
5103 		trailPtr->Perp[0] = PlayerPheromoneTrailPerp;
5104 	}
5105 #endif
5106 	trailPtr->Size[0] = 127*65536*4;
5107 
5108 	trailPtr->Vertex[1] = dynPtr->PrevPosition;
5109 	#if 1
5110 	trailPtr->Vertex[1].vx -= dynPtr->PrevOrientMat.mat21>>6;
5111 	trailPtr->Vertex[1].vy -= dynPtr->PrevOrientMat.mat22>>6;
5112 	trailPtr->Vertex[1].vz -= dynPtr->PrevOrientMat.mat23>>6;
5113 	#endif
5114  //	trailPtr->Vertex[1].vy -= 500;
5115 
5116 
5117   trailPtr->Perp[1] = *((VECTORCH*)&(dynPtr->PrevOrientMat.mat11));
5118 //	trailPtr->Perp[1] = PlayerPheromoneTrailPerp;
5119 //	PlayerPheromoneTrailPerp = trailPtr->Perp[0];
5120 
5121 	trailPtr->Size[1] = 127*65536*4-MUL_FIXED(TRAIL_DECAY_SPEED,PrevNormalFrameTime);
5122 }
5123 
HandlePheromoneTrails(void)5124 void HandlePheromoneTrails(void)
5125 {
5126 	int i;
5127 	PHEROMONE_TRAIL *trailPtr;
5128 	int decayDelta;
5129 
5130 	i = NumActiveTrails;
5131 	trailPtr = TrailStorage;
5132 	//textprint("Pheromone Segments active:%d\n",NumActiveTrails);
5133 
5134 	decayDelta = MUL_FIXED(TRAIL_DECAY_SPEED,NormalFrameTime);
5135 
5136 #if 0
5137 	if (TICKERTAPE_CHEATMODE)
5138 	{
5139 		decayDelta/=4;
5140 	}
5141 #endif
5142 	while(i--)
5143 	{
5144 
5145 		trailPtr->Size[0] -= decayDelta;
5146 		trailPtr->Size[1] -= decayDelta;
5147 		if (trailPtr->Size[1]<0) trailPtr->Size[1]=0;
5148 		if (trailPtr->Size[0]<0)
5149 		{
5150 			DeallocatePheromoneTrail(trailPtr);
5151 		}
5152 		else
5153 		{
5154 			RenderTrailSegment(trailPtr);
5155 			trailPtr++;
5156 		}
5157 
5158 	}
5159 }
5160 #include "frustum.h"
RenderTrailSegment(PHEROMONE_TRAIL * trailPtr)5161 void RenderTrailSegment(PHEROMONE_TRAIL *trailPtr)
5162 {
5163  	POLYHEADER fakeHeader;
5164 	VECTORCH temp;
5165 	int Uoffset = GetCos(CloakingPhase&4095)*128;
5166 	int Voffset	= GetSin(CloakingPhase&4095)*128;
5167 
5168 	temp.vx = trailPtr->Vertex[0].vx - MUL_FIXED(trailPtr->Perp[0].vx,trailPtr->Size[0]/65536);
5169 	temp.vy = trailPtr->Vertex[0].vy - MUL_FIXED(trailPtr->Perp[0].vy,trailPtr->Size[0]/65536);
5170 	temp.vz	= trailPtr->Vertex[0].vz - MUL_FIXED(trailPtr->Perp[0].vz,trailPtr->Size[0]/65536);
5171 	VerticesBuffer[0].U = (temp.vx+temp.vz)*8192+Uoffset;
5172 	VerticesBuffer[0].V = (temp.vy+temp.vz)*8192+Voffset;
5173 	TranslatePointIntoViewspace(&temp);
5174 	VerticesBuffer[0].X = temp.vx;
5175 	VerticesBuffer[0].Y = temp.vy;
5176 	VerticesBuffer[0].Z	= temp.vz;
5177 //	VerticesBuffer[0].U = ParticleDescription[PARTICLE_PLASMABEAM].StartU/2;
5178 //	VerticesBuffer[0].V = ParticleDescription[PARTICLE_PLASMABEAM].StartV/2;
5179 
5180 	temp.vx = trailPtr->Vertex[0].vx + MUL_FIXED(trailPtr->Perp[0].vx,trailPtr->Size[0]/65536);
5181 	temp.vy = trailPtr->Vertex[0].vy + MUL_FIXED(trailPtr->Perp[0].vy,trailPtr->Size[0]/65536);
5182 	temp.vz	= trailPtr->Vertex[0].vz + MUL_FIXED(trailPtr->Perp[0].vz,trailPtr->Size[0]/65536);
5183 	VerticesBuffer[1].U = (temp.vx+temp.vz)*8192+Uoffset;
5184 	VerticesBuffer[1].V = (temp.vy+temp.vz)*8192+Voffset;
5185 	TranslatePointIntoViewspace(&temp);
5186 	VerticesBuffer[1].X = temp.vx;
5187 	VerticesBuffer[1].Y = temp.vy;
5188 	VerticesBuffer[1].Z	= temp.vz;
5189 //	VerticesBuffer[1].U = ParticleDescription[PARTICLE_PLASMABEAM].StartU/2;
5190 //	VerticesBuffer[1].V = ParticleDescription[PARTICLE_PLASMABEAM].EndV/2;
5191 
5192 
5193 	temp.vx = trailPtr->Vertex[1].vx + MUL_FIXED(trailPtr->Perp[1].vx,trailPtr->Size[1]/65536);
5194 	temp.vy = trailPtr->Vertex[1].vy + MUL_FIXED(trailPtr->Perp[1].vy,trailPtr->Size[1]/65536);
5195 	temp.vz	= trailPtr->Vertex[1].vz + MUL_FIXED(trailPtr->Perp[1].vz,trailPtr->Size[1]/65536);
5196 	VerticesBuffer[2].U = (temp.vx+temp.vz)*8192+Uoffset;
5197 	VerticesBuffer[2].V = (temp.vy+temp.vz)*8192+Voffset;
5198 	TranslatePointIntoViewspace(&temp);
5199 	VerticesBuffer[2].X = temp.vx;
5200 	VerticesBuffer[2].Y = temp.vy;
5201 	VerticesBuffer[2].Z	= temp.vz;
5202 //	VerticesBuffer[2].U = ParticleDescription[PARTICLE_PLASMABEAM].EndU/2;
5203 //	VerticesBuffer[2].V = ParticleDescription[PARTICLE_PLASMABEAM].EndV/2;
5204 
5205 	temp.vx = trailPtr->Vertex[1].vx - MUL_FIXED(trailPtr->Perp[1].vx,trailPtr->Size[1]/65536);
5206 	temp.vy = trailPtr->Vertex[1].vy - MUL_FIXED(trailPtr->Perp[1].vy,trailPtr->Size[1]/65536);
5207 	temp.vz	= trailPtr->Vertex[1].vz - MUL_FIXED(trailPtr->Perp[1].vz,trailPtr->Size[1]/65536);
5208 	VerticesBuffer[3].U = (temp.vx+temp.vz)*8192+Uoffset;
5209 	VerticesBuffer[3].V = (temp.vy+temp.vz)*8192+Voffset;
5210 	TranslatePointIntoViewspace(&temp);
5211 	VerticesBuffer[3].X = temp.vx;
5212 	VerticesBuffer[3].Y = temp.vy;
5213 	VerticesBuffer[3].Z	= temp.vz;
5214 //	VerticesBuffer[3].U = ParticleDescription[PARTICLE_PLASMABEAM].EndU/2;
5215 //	VerticesBuffer[3].V = ParticleDescription[PARTICLE_PLASMABEAM].StartV/2;
5216 
5217 	{
5218 		extern int SpecialFXImageNumber;
5219 		extern int CloudyImageNumber;
5220 		fakeHeader.PolyFlags = iflag_transparent;
5221 		fakeHeader.PolyColour = SpecialFXImageNumber;
5222 		fakeHeader.PolyColour = CloudyImageNumber;
5223 	}
5224 	RenderPolygon.TranslucencyMode = TRANSLUCENCY_GLOWING;
5225 
5226 
5227  	{
5228 		int i;
5229 		for (i=0; i<4; i++)
5230 		{
5231 			VerticesBuffer[i].A = trailPtr->Size[i/2]/65536;
5232 
5233 
5234 			VerticesBuffer[i].R = 255;
5235 			VerticesBuffer[i].G	= 255;
5236 			VerticesBuffer[i].B = 255;
5237 			VerticesBuffer[i].SpecularR = 0;
5238 			VerticesBuffer[i].SpecularG = 0;
5239 			VerticesBuffer[i].SpecularB = 0;
5240 
5241 		}
5242 		RenderPolygon.NumberOfVertices=4;
5243 	}
5244 
5245 	GouraudTexturedPolygon_ClipWithZ();
5246 	if(RenderPolygon.NumberOfVertices<3) return;
5247 	GouraudTexturedPolygon_ClipWithNegativeX();
5248 	if(RenderPolygon.NumberOfVertices<3) return;
5249 	GouraudTexturedPolygon_ClipWithPositiveY();
5250 	if(RenderPolygon.NumberOfVertices<3) return;
5251 	GouraudTexturedPolygon_ClipWithNegativeY();
5252 	if(RenderPolygon.NumberOfVertices<3) return;
5253 	GouraudTexturedPolygon_ClipWithPositiveX();
5254 	if(RenderPolygon.NumberOfVertices<3) return;
5255 	D3D_ZBufferedGouraudTexturedPolygon_Output(&fakeHeader,RenderPolygon.Vertices);
5256 }
5257 
RenderParticlesInMirror(void)5258 extern void RenderParticlesInMirror(void)
5259 {
5260 	/* now render particles */
5261 	int i = NumActiveParticles;
5262 	PARTICLE *particlePtr = ParticleStorage;
5263 
5264 //  	RenderPlayersImageInMirror();
5265 
5266 	D3D_DecalSystem_Setup();
5267 	while(i--)
5268 	{
5269 		switch(particlePtr->ParticleID)
5270 		{
5271 			case PARTICLE_FLARESMOKE:
5272 			case PARTICLE_STEAM:
5273 			case PARTICLE_BLACKSMOKE:
5274 			case PARTICLE_IMPACTSMOKE:
5275 			case PARTICLE_SMOKECLOUD:
5276 			{
5277 				particlePtr->Position.vx = MirroringAxis - particlePtr->Position.vx;
5278 				RenderParticle(particlePtr);
5279 				particlePtr->Position.vx = MirroringAxis - particlePtr->Position.vx;
5280 				break;
5281 			}
5282 			default:
5283 				break;
5284 		}
5285 		particlePtr++;
5286 	}
5287 //			DrawingAReflection=1;
5288 //			DrawingAReflection=0;
5289 
5290 	{
5291 		extern int NumOnScreenBlocks;
5292 		extern DISPLAYBLOCK *OnScreenBlockList[];
5293 		int numOfObjects = NumOnScreenBlocks;
5294 		while(numOfObjects)
5295 		{
5296 			DISPLAYBLOCK *objectPtr = OnScreenBlockList[--numOfObjects];
5297 
5298 			if (!objectPtr->ObShape && objectPtr->SfxPtr)
5299 			{
5300 				DrawSfxObject(objectPtr);
5301 			}
5302 		}
5303 	}
5304 	D3D_DecalSystem_End();
5305 
5306 }
5307 
5308 
5309 
5310 #if 0
5311 
5312 int FogNotSetupYet=1;
5313 int Fog_Phi[256];
5314 int Fog_Theta[256];
5315 int Fog_Radius[256];
5316 int	Fog_PhiDelta[256];
5317 int Fog_ThetaDelta[256];
5318 int Fog_RadiusDelta[256];
5319 
5320 void RenderFog(void)
5321 {
5322 	int i;
5323 	if (FogNotSetupYet)
5324 	{
5325 		FogNotSetupYet=0;
5326 		for (i=0; i<256; i++)
5327 		{
5328 			Fog_Phi[i] = FastRandom()&2047;
5329 			Fog_Theta[i] = FastRandom()&4095;
5330 			Fog_Radius[i] = (FastRandom()&8191)-4096;
5331 			Fog_PhiDelta[i] = (FastRandom()&1023)-512;
5332 			Fog_ThetaDelta[i] = (FastRandom()&1023)-512;
5333 			Fog_RadiusDelta[i] = (FastRandom()&255)+255;
5334 		}
5335 
5336 	}
5337 	for (i=0; i<255; i++)
5338 	{
5339 		int phi = Fog_Phi[i];
5340 		int theta = Fog_Theta[i];
5341 		int radius = Fog_Radius[i];
5342 
5343 		{
5344 			PARTICLE particle;
5345 			particle.ParticleID = PARTICLE_NONCOLLIDINGFLAME;
5346 			particle.Position.vx = MUL_FIXED(MUL_FIXED(GetCos(phi),GetSin(theta)),radius);
5347 			particle.Position.vy = MUL_FIXED(MUL_FIXED(GetSin(phi),GetSin(theta)),radius);
5348 			if (particle.Position.vy<0)particle.Position.vy=-particle.Position.vy;
5349 			particle.Position.vz = MUL_FIXED(GetCos(theta),radius);
5350 			particle.Colour = RGBA_MAKE(255,255,255,255);
5351 			particle.Size = 100;
5352 			RenderParticle(&particle);
5353 	  	}
5354 		Fog_Phi[i]+=	MUL_FIXED(Fog_PhiDelta[i],NormalFrameTime);
5355 		Fog_Theta[i]+=	MUL_FIXED(Fog_ThetaDelta[i],NormalFrameTime);
5356 		Fog_Phi[i]&=2047;
5357 		Fog_Theta[i]&=4095;
5358 		if (Fog_Radius[i]>4096)
5359 		{
5360 			Fog_Radius[i]-=	MUL_FIXED(Fog_RadiusDelta[i],NormalFrameTime);
5361 		}
5362 		else
5363 		{
5364 			Fog_Radius[i]+=	MUL_FIXED(Fog_RadiusDelta[i],NormalFrameTime);
5365 		}
5366 
5367 	}
5368 
5369 }
5370 #endif
5371 
5372 
5373 
5374 
5375 
5376 
5377 
5378 
5379 #if 1
TimeScaleThingy()5380 void TimeScaleThingy()
5381 {
5382 	extern int NumActiveBlocks;
5383 	extern DISPLAYBLOCK *ActiveBlockList[];
5384 	extern int TimeScale;
5385 	int DesiredTimeScale=ONE_FIXED;
5386 	extern int RealFrameTime;
5387 
5388 	int i;
5389 
5390 	for(i=0;i<NumActiveBlocks;i++)
5391 	{
5392 		STRATEGYBLOCK* sbPtr = ActiveBlockList[i]->ObStrategyBlock;
5393 		if(sbPtr)
5394 		{
5395 			switch(sbPtr->I_SBtype)
5396 			{
5397 				case I_BehaviourAlien:
5398 				case I_BehaviourQueenAlien :
5399 				case I_BehaviourFaceHugger :
5400 				case I_BehaviourPredator :
5401 				case I_BehaviourXenoborg :
5402 				case I_BehaviourMarine :
5403 				case I_BehaviourSeal :
5404 				case I_BehaviourPredatorAlien :
5405 				case I_BehaviourAutoGun :
5406 					DesiredTimeScale=MUL_FIXED(DesiredTimeScale,ONE_FIXED*.8);
5407 					break;
5408 
5409 				case I_BehaviourGrenade :
5410 				case I_BehaviourRocket :
5411 				case I_BehaviourFrisbee:
5412 				case I_BehaviourPulseGrenade :
5413 				case I_BehaviourMolotov :
5414 					DesiredTimeScale=MUL_FIXED(DesiredTimeScale,ONE_FIXED*.7);
5415 					break;
5416 
5417 				default: ;
5418 			}
5419 		}
5420 	}
5421 
5422 	for(i=0; i<MAX_NO_OF_EXPLOSIONS; i++)
5423 	{
5424 		if (ExplosionStorage[i].LifeTime)
5425 		{
5426 			DesiredTimeScale=MUL_FIXED(DesiredTimeScale,ONE_FIXED*.5);
5427 		}
5428 	}
5429 
5430 	if(DesiredTimeScale<ONE_FIXED) DesiredTimeScale=MUL_FIXED(DesiredTimeScale,ONE_FIXED*.8);
5431 
5432 	if(DesiredTimeScale<ONE_FIXED/10) DesiredTimeScale=ONE_FIXED/10;
5433 
5434 
5435 	if(TimeScale<DesiredTimeScale)
5436 	{
5437 		TimeScale+=RealFrameTime/8;
5438 		if(TimeScale>DesiredTimeScale) TimeScale=DesiredTimeScale;
5439 	}
5440 	else if (TimeScale>DesiredTimeScale)
5441 	{
5442 		TimeScale-=RealFrameTime;
5443 		if(TimeScale<DesiredTimeScale) TimeScale=DesiredTimeScale;
5444 	}
5445 }
5446 #else
TimeScaleThingy()5447 void TimeScaleThingy()
5448 {
5449 	static int time=0;
5450 	extern int TimeScale;
5451 	extern int RealFrameTime;
5452 	int ts;
5453 
5454 	time += RealFrameTime;
5455 
5456 	ts = GetSin((time/64)&4095);
5457 	ts = MUL_FIXED(ts,ts)/2;
5458 
5459 	TimeScale = 32678 + ts;
5460 }
5461 #endif
5462 
5463 
5464 
5465 
5466 /*----------------------**
5467 **  Load/Save particles **
5468 **----------------------*/
5469 
5470 typedef struct particle_save_block_header
5471 {
5472 	SAVE_BLOCK_HEADER header;
5473 
5474 	int NumActiveParticles;
5475 	int NumberOfBloodParticles;
5476 
5477 	//followed by paricle array after this block
5478 
5479 }PARTICLE_SAVE_BLOCK_HEADER;
5480 
Load_Particles(SAVE_BLOCK_HEADER * header)5481 void Load_Particles(SAVE_BLOCK_HEADER* header)
5482 {
5483 	PARTICLE_SAVE_BLOCK_HEADER* block = (PARTICLE_SAVE_BLOCK_HEADER*) header;
5484 	PARTICLE* saved_particle = (PARTICLE*)(block+1);
5485 	int expected_size;
5486 	int i;
5487 
5488 	//make sure the block is the correct size
5489 	expected_size = sizeof(*block);
5490 	expected_size += sizeof(PARTICLE) * block->NumActiveParticles;
5491 	if(header->size != expected_size) return;
5492 
5493 	//right copy the stuff then
5494 	NumActiveParticles = block->NumActiveParticles;
5495 	NumberOfBloodParticles = block->NumberOfBloodParticles;
5496 
5497 	for(i=0;i<NumActiveParticles;i++)
5498 	{
5499 		ParticleStorage[i] = *saved_particle++;
5500 	}
5501 }
5502 
Save_Particles()5503 void Save_Particles()
5504 {
5505 	PARTICLE_SAVE_BLOCK_HEADER* block;
5506 	int i;
5507 
5508 	if(!NumActiveParticles) return;
5509 
5510 	//get memory for header
5511 	GET_SAVE_BLOCK_POINTER(block);
5512 
5513 	//fill in header
5514 	block->header.type = SaveBlock_Particles;
5515 	block->header.size = sizeof(*block) + NumActiveParticles * sizeof(PARTICLE);
5516 
5517 	block->NumActiveParticles = NumActiveParticles;
5518 	block->NumberOfBloodParticles = NumberOfBloodParticles;
5519 
5520 
5521 	//now save the particles
5522 	for(i=0;i<NumActiveParticles;i++)
5523 	{
5524 		PARTICLE* particle = GetPointerForSaveBlock(sizeof(PARTICLE));
5525 		*particle = ParticleStorage[i];
5526 	}
5527 }
5528 
5529 /*----------------------**
5530 ** Load/Save Explosions **
5531 **----------------------*/
5532 
5533 typedef struct explosion_save_block_header
5534 {
5535 	SAVE_BLOCK_HEADER header;
5536 
5537 	int NumActiveExplosions;
5538 	//followed by explosion array after this block
5539 
5540 }EXPLOSION_SAVE_BLOCK_HEADER;
5541 
5542 
5543 
Load_VolumetricExplosions(SAVE_BLOCK_HEADER * header)5544 void Load_VolumetricExplosions(SAVE_BLOCK_HEADER* header)
5545 {
5546 	int i;
5547 	EXPLOSION_SAVE_BLOCK_HEADER* block = (EXPLOSION_SAVE_BLOCK_HEADER*) header;
5548 	VOLUMETRIC_EXPLOSION* saved_explosion = (VOLUMETRIC_EXPLOSION*) (block+1);
5549 	int expected_size;
5550 
5551 	//make sure the block is the correct size
5552 	expected_size = sizeof(*block);
5553 	expected_size += sizeof(VOLUMETRIC_EXPLOSION) * block->NumActiveExplosions;
5554 	if(header->size != expected_size) return;
5555 
5556 	for(i=0;i<block->NumActiveExplosions;i++)
5557 	{
5558 		VOLUMETRIC_EXPLOSION* explosion = AllocateVolumetricExplosion();
5559 		if(explosion)
5560 		{
5561 			*explosion = *saved_explosion++;
5562 		}
5563 	}
5564 
5565 }
5566 
Save_VolumetricExplosions()5567 void Save_VolumetricExplosions()
5568 {
5569 	int i;
5570 	EXPLOSION_SAVE_BLOCK_HEADER* block;
5571 	int NumActiveExplosions = 0;
5572 
5573 	//first find the number of explosions currently active
5574 	for(i=0;i<MAX_NO_OF_EXPLOSIONS;i++)
5575 	{
5576 		if(ExplosionStorage[i].LifeTime) NumActiveExplosions++;
5577 	}
5578 
5579 	//don's save if there aren't any
5580 	if(!NumActiveExplosions) return;
5581 
5582 	//get memory for header
5583 	GET_SAVE_BLOCK_POINTER(block);
5584 
5585 	//fill in header
5586 	block->header.type = SaveBlock_VolumetricExplosions;
5587 	block->header.size = sizeof(*block) + NumActiveExplosions * sizeof(VOLUMETRIC_EXPLOSION);
5588 
5589 	block->NumActiveExplosions = NumActiveExplosions;
5590 
5591 	//now save the explosions
5592 	for(i=0;i<MAX_NO_OF_EXPLOSIONS;i++)
5593 	{
5594 		if(ExplosionStorage[i].LifeTime)
5595 		{
5596 			VOLUMETRIC_EXPLOSION* explosion = GetPointerForSaveBlock(sizeof(VOLUMETRIC_EXPLOSION));
5597 			*explosion = ExplosionStorage[i];
5598 		}
5599 	}
5600 }
5601 
5602 
5603 /*----------------------------**
5604 ** Load/Save pheromone trails **
5605 **----------------------------*/
5606 
5607 typedef struct pheromone_save_block_header
5608 {
5609 	SAVE_BLOCK_HEADER header;
5610 
5611 	int NumActiveTrails;
5612 	//followed by pheromone array after this block
5613 
5614 }PHEROMONE_SAVE_BLOCK_HEADER;
5615 
5616 
5617 
Load_PheromoneTrails(SAVE_BLOCK_HEADER * header)5618 void Load_PheromoneTrails(SAVE_BLOCK_HEADER* header)
5619 {
5620 	int i;
5621 	PHEROMONE_SAVE_BLOCK_HEADER* block = (PHEROMONE_SAVE_BLOCK_HEADER*) header;
5622 	PHEROMONE_TRAIL* saved_trail = (PHEROMONE_TRAIL*) (block+1);
5623 	int expected_size;
5624 
5625 	//make sure the block is the correct size
5626 	expected_size = sizeof(*block);
5627 	expected_size += sizeof(PHEROMONE_TRAIL) * block->NumActiveTrails;
5628 	if(header->size != expected_size) return;
5629 
5630 	for(i=0;i<block->NumActiveTrails;i++)
5631 	{
5632 		PHEROMONE_TRAIL* trail = AllocatePheromoneTrail();
5633 		if(trail)
5634 		{
5635 			*trail = *saved_trail++;
5636 		}
5637 	}
5638 
5639 }
5640 
Save_PheromoneTrails()5641 void Save_PheromoneTrails()
5642 {
5643 	PHEROMONE_SAVE_BLOCK_HEADER* block;
5644 	int i;
5645 
5646 	if(!NumActiveTrails) return;
5647 
5648 	//get memory for header
5649 	GET_SAVE_BLOCK_POINTER(block);
5650 
5651 	//fill in header
5652 	block->header.type = SaveBlock_PheromoneTrail;
5653 	block->header.size = sizeof(*block) + NumActiveTrails * sizeof(PHEROMONE_TRAIL);
5654 
5655 	block->NumActiveTrails = NumActiveTrails;
5656 
5657 
5658 	//now save the trails
5659 	for(i=0;i<NumActiveTrails;i++)
5660 	{
5661 		PHEROMONE_TRAIL* trail = GET_SAVE_BLOCK_POINTER(trail);
5662 		*trail = TrailStorage[i];
5663 	}
5664 
5665 }
5666