1 /*KJL***************************************************
2 * lighting.c - a lighting interface for simple effects *
3 ***************************************************KJL*/
4 
5 #include "3dc.h"
6 
7 #include "inline.h"
8 #include "module.h"
9 #include "stratdef.h"
10 #include "gamedef.h"
11 #include "bh_types.h"
12 #include "bh_weap.h"
13 
14 #include "lighting.h"
15 #include "particle.h"
16 #include "dynamics.h"
17 #define UseLocalAssert Yes
18 #include "ourasert.h"
19 
20 static VECTORCH RotatingLightPosition;
21 extern int CloakingPhase;
22 extern int NormalFrameTime;
23 extern VIEWDESCRIPTORBLOCK *Global_VDB_Ptr;
24 extern int LightScale;
25 
AddLightingEffectToObject(DISPLAYBLOCK * objectPtr,enum LIGHTING_EFFECTS_ID lfxID)26 void AddLightingEffectToObject(DISPLAYBLOCK *objectPtr, enum LIGHTING_EFFECTS_ID lfxID)
27 {
28 	LIGHTBLOCK *lightPtr;
29 
30 	lightPtr = AddLightBlock(objectPtr, NULL);
31 
32 	if (!lightPtr) return;
33 
34 	switch(lfxID)
35 	{
36 		case LFX_EXPLOSION:
37 		{
38 			/* brightness */
39 			lightPtr->LightBright = ONE_FIXED*4;
40 			/* flags */
41 			lightPtr->LightFlags = LFlag_Omni;
42 			/* lightblock light type */
43 			lightPtr->LightType = LightType_PerVertex;
44 			/* range */
45 			lightPtr->LightRange = EXPLOSION_LIGHT_RANGE;
46 
47 			lightPtr->RedScale=255*256;
48 			lightPtr->GreenScale=120*256;
49 			lightPtr->BlueScale=0;
50 
51 			break;
52 		}
53 		case LFX_BIGEXPLOSION:
54 		{
55 			/* brightness */
56 			lightPtr->LightBright = ONE_FIXED << 2;
57 			/* flags */
58 			lightPtr->LightFlags = LFlag_Omni;
59 			/* lightblock light type */
60 			lightPtr->LightType = LightType_PerVertex;
61 			/* range */
62 			lightPtr->LightRange = EXPLOSION_LIGHT_RANGE;
63 
64 			lightPtr->RedScale=255*256;
65 			lightPtr->GreenScale=120*256;
66 			lightPtr->BlueScale=0;
67 
68 			break;
69 		}
70 
71 		case LFX_MUZZLEFLASH:
72 		{
73 			/* brightness */
74 			lightPtr->LightBright = 65536 - (FastRandom()&32767);
75 			/* flags */
76 			lightPtr->LightFlags = LFlag_Omni|LFlag_Deallocate;
77 			/* lightblock light type */
78 			lightPtr->LightType = LightType_PerVertex;
79 			/* range */
80 			#if 0
81 			lightPtr->LightRange = 5000; /* ? */
82 
83 			lightPtr->RedScale=255*256;
84 			lightPtr->GreenScale=192*256;
85 			lightPtr->BlueScale=128*256;
86 			#else
87 			lightPtr->LightRange = 10000; /* ? */
88 			lightPtr->RedScale=255*256;
89 			lightPtr->GreenScale=230*256;
90 			lightPtr->BlueScale=200*256;
91 			#endif
92 
93 			break;
94 		}
95 		case LFX_PARTICLECANNON:
96 		{
97 			/* brightness */
98 			lightPtr->LightBright = 65536 - (FastRandom()&32767);
99 			/* flags */
100 			lightPtr->LightFlags = LFlag_Omni|LFlag_Deallocate;
101 			/* lightblock light type */
102 			lightPtr->LightType = LightType_PerVertex;
103 			/* range */
104 			lightPtr->LightRange = 10000; /* ? */
105 
106 			lightPtr->RedScale=255*256;
107 			lightPtr->GreenScale=32*256;
108 			lightPtr->BlueScale=0;
109 			break;
110 		}
111 		case LFX_ROCKETJET:
112 		{
113 			/* brightness */
114 			lightPtr->LightBright = ONE_FIXED*3/4;
115 			/* flags */
116 			lightPtr->LightFlags = LFlag_Omni|LFlag_CosAtten;
117 			/* lightblock light type */
118 			lightPtr->LightType = LightType_PerVertex;
119 			/* range */
120 			lightPtr->LightRange = 5000; /* ? */
121 
122 			lightPtr->RedScale=255*256;
123 			lightPtr->GreenScale=255*256;
124 			lightPtr->BlueScale=128*256;
125 
126 			break;
127 		}
128 		case LFX_FLARE:
129 		{
130 			/* brightness */
131 			lightPtr->LightBright = 0;
132 			/* flags */
133 			lightPtr->LightFlags = LFlag_Omni;
134 			/* lightblock light type */
135 			lightPtr->LightType = LightType_PerVertex;
136 			/* range */
137 			lightPtr->LightRange = 10000; /* ? */
138 
139 			lightPtr->RedScale=255*256;
140 			lightPtr->GreenScale=200*256;
141 			lightPtr->BlueScale=255*256;
142 
143 			break;
144 		}
145 		case LFX_XENO_FIRING:
146 		{
147 			/* brightness */
148 			lightPtr->LightBright = 226100;
149 			/* flags */
150 			lightPtr->LightFlags = LFlag_Omni|LFlag_Deallocate;
151 			/* lightblock light type */
152 			lightPtr->LightType = LightType_PerVertex;
153 			/* range */
154 			lightPtr->LightRange = 5000; /* ? */
155 
156 			lightPtr->RedScale=255*256;
157 			lightPtr->GreenScale=64*256;
158 			lightPtr->BlueScale=255*256;
159 
160 			break;
161 		}
162 		case LFX_PLASMA_BOLT:
163 		{
164 			/* brightness */
165 			lightPtr->LightBright = ONE_FIXED/4;
166 			/* flags */
167 			lightPtr->LightFlags = LFlag_Omni|LFlag_CosAtten;
168 			/* lightblock light type */
169 			lightPtr->LightType = LightType_PerVertex;
170 			/* range */
171 			lightPtr->LightRange = 10000;
172 
173 			lightPtr->RedScale=200*256;
174 			lightPtr->GreenScale=255*256;
175 			lightPtr->BlueScale=255*256;
176 
177 			break;
178 		}
179 		case LFX_OBJECTONFIRE:
180 		{
181 			/* brightness */
182 			lightPtr->LightBright = 16484 - (FastRandom()&4095);
183 			/* flags */
184 			lightPtr->LightFlags = LFlag_Omni|LFlag_Deallocate|LFlag_Thermal;
185 			/* lightblock light type */
186 			lightPtr->LightType = LightType_PerVertex;
187 			/* range */
188 			lightPtr->LightRange = 10000;
189 			lightPtr->RedScale=255*256;
190 			lightPtr->GreenScale=110*256;
191 			lightPtr->BlueScale=50*256;
192 
193 			break;
194 		}
195 		case LFX_SPEARGUNBOLT:
196 		{
197 			/* Just an experiment. */
198 			/* brightness */
199 			lightPtr->LightBright = ONE_FIXED/4;
200 			/* flags */
201 			lightPtr->LightFlags = LFlag_Omni|LFlag_CosAtten;
202 			/* lightblock light type */
203 			lightPtr->LightType = LightType_PerVertex;
204 			/* range */
205 			lightPtr->LightRange = 10000;
206 
207 			lightPtr->RedScale=255*256;
208 			lightPtr->GreenScale=255*256;
209 			lightPtr->BlueScale=255*256;
210 
211 			break;
212 		}
213 	}
214 }
215 
216 
217 
LightBlockDeallocation(void)218 void LightBlockDeallocation(void)
219 {
220 	extern int NumActiveBlocks;
221 	extern DISPLAYBLOCK *ActiveBlockList[];
222 	int numblocks = NumActiveBlocks;
223 
224 	while(numblocks)
225 	{
226 		DISPLAYBLOCK *dptr = ActiveBlockList[--numblocks];
227 
228 		int numlights = dptr->ObNumLights;
229 		while(numlights)
230 		{
231 			LIGHTBLOCK *lightPtr = dptr->ObLights[--numlights];
232 			if(lightPtr->LightFlags & LFlag_Deallocate)
233 				DeleteLightBlock(lightPtr, dptr);
234 		}
235 	}
236 
237 }
238 
239 /*KJL******************************
240 *                                 *
241 *      LIGHT ELEMENT CODE         *
242 * 								  *
243 ******************************KJL*/
244 #define MAX_NO_OF_LIGHTELEMENTS 500
245 LIGHTELEMENT LightElementStorage[MAX_NO_OF_LIGHTELEMENTS];
246 int NumActiveLightElements;
247 
InitialiseLightElementSystem(void)248 void InitialiseLightElementSystem(void)
249 {
250 	NumActiveLightElements = 0;
251 }
252 
AllocateLightElement(void)253 static LIGHTELEMENT* AllocateLightElement(void)
254 {
255 	LIGHTELEMENT *lightElementPtr = 0; /* Default to null ptr */
256 
257 	if (NumActiveLightElements != MAX_NO_OF_LIGHTELEMENTS)
258 	{
259 		lightElementPtr = &LightElementStorage[NumActiveLightElements];
260 		NumActiveLightElements++;
261 	}
262 	else
263 	{
264 		/* unable to allocate a lightElement */
265 	}
266 
267 	return lightElementPtr;
268 }
DeallocateLightElement(LIGHTELEMENT * lightElementPtr)269 static void DeallocateLightElement(LIGHTELEMENT *lightElementPtr)
270 {
271 	/* is pointer within array? */
272 	LOCALASSERT(lightElementPtr>=LightElementStorage);
273 	LOCALASSERT(lightElementPtr<=&LightElementStorage[MAX_NO_OF_LIGHTELEMENTS-1]);
274 
275 	NumActiveLightElements--;
276 	*lightElementPtr = LightElementStorage[NumActiveLightElements];
277 }
278 
279 
MakeLightElement(VECTORCH * positionPtr,enum LIGHTELEMENT_BEHAVIOUR_ID behaviourID)280 void MakeLightElement(VECTORCH *positionPtr, enum LIGHTELEMENT_BEHAVIOUR_ID behaviourID)
281 {
282 	LIGHTELEMENT *lightElementPtr = AllocateLightElement();
283 	LIGHTBLOCK *lightPtr = &(lightElementPtr->LightBlock);
284 
285 	/* if we failed to make an element, get the hell out of here */
286 	if (!lightElementPtr) return;
287 
288 	lightElementPtr->BehaviourID = behaviourID;
289 	lightElementPtr->LightBlock.LightWorld = *positionPtr;
290 	lightElementPtr->LifeTime=ONE_FIXED;
291 
292 	switch (behaviourID)
293 	{
294 		case LIGHTELEMENT_ROTATING:
295 		{
296 			RotatingLightPosition = *positionPtr;
297 			break;
298 		}
299 		case LIGHTELEMENT_ALIEN_TEETH:
300 		{
301 			lightPtr->LightBright = ONE_FIXED/2;
302 			/* flags */
303 			lightPtr->LightFlags = LFlag_Omni;
304 			/* lightblock light type */
305 			lightPtr->LightType = LightType_PerVertex;
306 			/* range */
307 			lightPtr->LightRange = 200;
308 
309 			lightPtr->RedScale=	  ONE_FIXED;
310 			lightPtr->GreenScale= ONE_FIXED;
311 			lightPtr->BlueScale=  ONE_FIXED;
312 
313 			{
314 				VECTORCH position;
315 			   	position.vx = MUL_FIXED(200,GetSin((CloakingPhase)&4095));
316 			   	position.vy = MUL_FIXED(200,GetCos((CloakingPhase)&4095));
317 			   	position.vz = 80+MUL_FIXED(50,GetCos((CloakingPhase/2)&4095));
318 			   	{
319 			   		MATRIXCH myMat = Global_VDB_Ptr->VDB_Mat;
320 			   		TransposeMatrixCH(&myMat);
321 			   		RotateVector(&(position), &(myMat));
322 			   		position.vx += Global_VDB_Ptr->VDB_World.vx;
323 			   		position.vy += Global_VDB_Ptr->VDB_World.vy;
324 			   		position.vz += Global_VDB_Ptr->VDB_World.vz;
325 			   	}
326 				lightElementPtr->LightBlock.LightWorld = position;
327 			}
328 			lightElementPtr->LifeTime = 0;
329 			break;
330 		}
331 		case LIGHTELEMENT_ALIEN_TEETH2:
332 		{
333 			lightPtr->LightBright = ONE_FIXED/2;
334 			/* flags */
335 			lightPtr->LightFlags = LFlag_Omni;
336 			/* lightblock light type */
337 			lightPtr->LightType = LightType_PerVertex;
338 			/* range */
339 			lightPtr->LightRange = 200;
340 
341 			lightPtr->RedScale=	  ONE_FIXED;
342 			lightPtr->GreenScale= ONE_FIXED;
343 			lightPtr->BlueScale=  ONE_FIXED;
344 
345 			{
346 				VECTORCH position;
347 			   	position.vx = MUL_FIXED(200,GetSin((CloakingPhase/3+2048)&4095));
348 			   	position.vy = MUL_FIXED(200,GetCos((CloakingPhase/3+2048)&4095));
349 			   	position.vz = 80+MUL_FIXED(50,GetCos((CloakingPhase/2+2048)&4095));
350 			   	{
351 			   		MATRIXCH myMat = Global_VDB_Ptr->VDB_Mat;
352 			   		TransposeMatrixCH(&myMat);
353 			   		RotateVector(&(position), &(myMat));
354 			   		position.vx += Global_VDB_Ptr->VDB_World.vx;
355 			   		position.vy += Global_VDB_Ptr->VDB_World.vy;
356 			   		position.vz += Global_VDB_Ptr->VDB_World.vz;
357 			   	}
358 				lightElementPtr->LightBlock.LightWorld = position;
359 			}
360 			lightElementPtr->LifeTime = 0;
361 			break;
362 		}
363 		default: ;
364 	}
365 }
366 
367 
HandleLightElementSystem(void)368 void HandleLightElementSystem(void)
369 {
370 	int i = NumActiveLightElements;
371 	LIGHTELEMENT *lightElementPtr = LightElementStorage;
372 
373 	while(i--)
374 	{
375 		LIGHTBLOCK *lightPtr = &(lightElementPtr->LightBlock);
376 
377 		switch(lightElementPtr->BehaviourID)
378 		{
379 			case LIGHTELEMENT_MOLTENMETAL:
380 			{
381 
382 				lightPtr->LightBright = ONE_FIXED/4;
383 				/* flags */
384 				lightPtr->LightFlags = LFlag_Omni;
385 				/* lightblock light type */
386 				lightPtr->LightType = LightType_PerVertex;
387 				/* range */
388 				lightPtr->LightRange = EXPLOSION_LIGHT_RANGE;
389 
390 				lightPtr->RedScale=	  255*256;
391 				lightPtr->GreenScale= 120*256;
392 				lightPtr->BlueScale=  0;
393 
394 				break;
395 			}
396 			case LIGHTELEMENT_PLASMACASTERHIT:
397 			{
398 				/* flags */
399 				lightPtr->LightFlags = LFlag_Omni;
400 				/* lightblock light type */
401 				lightPtr->LightType = LightType_PerVertex;
402 				/* range */
403 				lightPtr->LightRange = EXPLOSION_LIGHT_RANGE;
404 
405 				if (lightElementPtr->LifeTime==ONE_FIXED)
406 				{
407 					lightPtr->LightBright = ONE_FIXED*4;
408 
409 					lightPtr->RedScale=	  0*256;
410 					lightPtr->GreenScale= 255*256;
411 					lightPtr->BlueScale=  255*256;
412 				}
413 				else
414 				{
415 					lightPtr->LightBright = lightElementPtr->LifeTime/2;
416 					lightPtr->LightRange = 1+MUL_FIXED(EXPLOSION_LIGHT_RANGE,lightElementPtr->LifeTime);
417 
418 					lightPtr->RedScale=	  255*256;
419 					lightPtr->GreenScale= 120*256;
420 					lightPtr->BlueScale=  0*256;
421 				}
422 
423 				lightElementPtr->LifeTime-=NormalFrameTime*4;
424 
425 				break;
426 			}case LIGHTELEMENT_FROMFMV:
427 			{
428 				extern int FmvColourRed;
429 				extern int FmvColourGreen;
430 				extern int FmvColourBlue;
431 
432 				lightPtr->LightBright = ONE_FIXED*4;
433 				/* flags */
434 				lightPtr->LightFlags = LFlag_Omni;
435 				/* lightblock light type */
436 				lightPtr->LightType = LightType_PerVertex;
437 				/* range */
438 				lightPtr->LightRange = 15000;
439 
440 				lightPtr->RedScale=	  FmvColourRed;
441 				lightPtr->GreenScale= FmvColourGreen;
442 				lightPtr->BlueScale=  FmvColourBlue;
443 
444 				break;
445 			}
446 			case LIGHTELEMENT_EXPLOSION:
447 			{
448 
449 				/* flags */
450 				lightPtr->LightFlags = LFlag_Omni;
451 				/* lightblock light type */
452 				lightPtr->LightType = LightType_PerVertex;
453 
454 				lightPtr->RedScale=255*256;
455 				lightPtr->GreenScale=120*256;
456 				lightPtr->BlueScale=0;
457 				{
458 					int scale = lightElementPtr->LifeTime*4;
459 
460 					if (scale < ONE_FIXED)
461 					{
462 						lightPtr->LightRange = 1+MUL_FIXED(EXPLOSION_LIGHT_RANGE,scale);
463 						lightPtr->LightBright = scale*8;
464 					}
465 					else
466 					{
467 						lightPtr->LightRange = EXPLOSION_LIGHT_RANGE;
468 						lightPtr->LightBright = ONE_FIXED*8;
469 					}
470 				}
471 
472 
473 				{
474 					PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
475 
476 					if (playerStatusPtr->IsAlive)
477 					{
478 						VECTORCH d = lightElementPtr->LightBlock.LightWorld;
479 						int m;
480 						d.vx -= Global_VDB_Ptr->VDB_World.vx;
481 						d.vy -= Global_VDB_Ptr->VDB_World.vy;
482 						d.vz -= Global_VDB_Ptr->VDB_World.vz;
483 						m = Approximate3dMagnitude(&d);
484 
485 						if (m<ONE_FIXED)
486 						{
487 							int maxTilt = MUL_FIXED((ONE_FIXED-m)>>9,lightElementPtr->LifeTime);
488 							int halfTilt = maxTilt/2;
489 							if (maxTilt)
490 							{
491 								HeadOrientation.EulerX = (FastRandom()%maxTilt)-halfTilt;
492 								HeadOrientation.EulerY = (FastRandom()%maxTilt)-halfTilt;
493 								HeadOrientation.EulerZ = (FastRandom()%maxTilt)-halfTilt;
494 
495 								if (HeadOrientation.EulerX < 0) HeadOrientation.EulerX += 4096;
496 								if (HeadOrientation.EulerY < 0) HeadOrientation.EulerY += 4096;
497 								if (HeadOrientation.EulerZ < 0) HeadOrientation.EulerZ += 4096;
498 							}
499 						}
500 					}
501 				}
502 				lightElementPtr->LifeTime-=NormalFrameTime;
503 				break;
504 			}
505 			case LIGHTELEMENT_ELECTRICAL_EXPLOSION:
506 			{
507 				int scale = ONE_FIXED*5/4-lightElementPtr->LifeTime;
508 
509 				/* flags */
510 				lightPtr->LightFlags = LFlag_Omni|LFlag_Electrical;
511 				/* lightblock light type */
512 				lightPtr->LightType = LightType_PerVertex;
513 
514 				if (scale>65536) scale = 65536;
515 				scale = ONE_FIXED - scale;
516 
517 				lightPtr->RedScale= scale;
518 				lightPtr->GreenScale=ONE_FIXED;
519 				lightPtr->BlueScale=ONE_FIXED;
520 				lightPtr->LightRange = EXPLOSION_LIGHT_RANGE;// 1+MUL_FIXED(EXPLOSION_LIGHT_RANGE,scale);
521 				lightPtr->LightBright = scale*16;
522 
523 				lightElementPtr->LifeTime-=NormalFrameTime;
524 				break;
525 			}
526 			case LIGHTELEMENT_ELECTRICAL_SPARKS:
527 			{
528 				int scale = lightElementPtr->LifeTime;
529 
530 				/* flags */
531 				lightPtr->LightFlags = LFlag_Omni|LFlag_Electrical;
532 				/* lightblock light type */
533 				lightPtr->LightType = LightType_PerVertex;
534 
535 				if (scale == ONE_FIXED)
536 				{
537 					lightPtr->RedScale=ONE_FIXED;
538 					lightPtr->GreenScale=ONE_FIXED;
539 					lightPtr->BlueScale=ONE_FIXED;
540 				}
541 				else
542 				{
543 					lightPtr->RedScale= 0;
544 					lightPtr->GreenScale= scale/2;
545 					lightPtr->BlueScale= scale;
546 				}
547 				lightPtr->LightRange = 4000;// 1+MUL_FIXED(EXPLOSION_LIGHT_RANGE,scale);
548 				lightPtr->LightBright = scale;
549 
550 				lightElementPtr->LifeTime-=NormalFrameTime*2;
551 				break;
552 			}
553 
554 			case LIGHTELEMENT_ROTATING:
555 			{
556 
557 				lightPtr->LightBright = ONE_FIXED/2;
558 				/* flags */
559 				lightPtr->LightFlags = LFlag_Omni;
560 				/* lightblock light type */
561 				lightPtr->LightType = LightType_PerVertex;
562 				/* range */
563 				lightPtr->LightRange = 10000;
564 
565 				lightPtr->RedScale=	  ONE_FIXED;
566 				lightPtr->GreenScale= ONE_FIXED;
567 				lightPtr->BlueScale=  ONE_FIXED;
568 
569 				lightElementPtr->LightBlock.LightWorld = Player->ObWorld;//RotatingLightPosition;
570 //				lightElementPtr->LightBlock.LightWorld.vx += MUL_FIXED(2000,GetCos((CloakingPhase/2)&4095));
571 				lightElementPtr->LightBlock.LightWorld.vy -= 2200;
572 //				lightElementPtr->LightBlock.LightWorld.vz += MUL_FIXED(2000,GetSin((CloakingPhase/2)&4095));
573 				#if 0
574 				{
575 
576 					VECTORCH zero = {0,0,0};
577 					MakeParticle(&(lightElementPtr->LightBlock.LightWorld),&zero,PARTICLE_SPARK);
578 				}
579 				#endif
580 				break;
581 			}
582 			case LIGHTELEMENT_ALIEN_TEETH:
583 			case LIGHTELEMENT_ALIEN_TEETH2:
584 			{
585 				break;
586 			}
587 
588 			case LIGHTELEMENT_PARGEN_FLAME :
589 			{
590 				if(lightElementPtr->LifeTime == ONE_FIXED)
591 				{
592 					lightElementPtr->LifeTime = 1;
593 
594 					/* flags */
595 					lightPtr->LightFlags = LFlag_Omni;
596 					/* lightblock light type */
597 					lightPtr->LightType = LightType_PerVertex;
598 
599 					//lightPtr->RedScale=	  255*256;
600 					//lightPtr->GreenScale= 120*256;
601 					lightPtr->RedScale=	  255*(200+(CloakingPhase%56));
602 					lightPtr->GreenScale= 120*(200+((CloakingPhase/8)%56));
603 					lightPtr->BlueScale=  0;
604 
605 					lightPtr->LightRange = 6000;
606 					lightPtr->LightBright = ONE_FIXED;
607 
608 				}
609 				else
610 				{
611 					lightElementPtr->LifeTime = 0;
612 				}
613 			}
614 			break;
615 
616 			default:
617 				break;
618 		}
619 
620 		lightPtr->BrightnessOverRange = DIV_FIXED(MUL_FIXED(lightPtr->LightBright,LightScale),lightPtr->LightRange);
621 
622 		if (lightElementPtr->LifeTime<=0)
623 		{
624 			DeallocateLightElement(lightElementPtr);
625 		}
626 		else
627 		{
628 			lightElementPtr++;
629 		}
630 	}
631 }
632 
633 
634 /*--------------------------**
635 ** Load/Save Light Elements **
636 **--------------------------*/
637 #include "savegame.h"
638 
639 typedef struct light_element_save_block_header
640 {
641 	SAVE_BLOCK_HEADER header;
642 
643 	int NumActiveLightElements;
644 
645 	//followed by array of light elements
646 }LIGHT_ELEMENT_SAVE_BLOCK_HEADER;
647 
Load_LightElements(SAVE_BLOCK_HEADER * header)648 void Load_LightElements(SAVE_BLOCK_HEADER* header)
649 {
650 	int i;
651 	LIGHT_ELEMENT_SAVE_BLOCK_HEADER* block = (LIGHT_ELEMENT_SAVE_BLOCK_HEADER*) header;
652 	LIGHTELEMENT* saved_light_element = (LIGHTELEMENT*) (block+1);
653 	int expected_size;
654 
655 	//make sure the block is the correct size
656 	expected_size = sizeof(*block);
657 	expected_size += sizeof(LIGHTELEMENT) * block->NumActiveLightElements;
658 	if(header->size != expected_size) return;
659 
660 
661 	for(i=0;i<block->NumActiveLightElements;i++)
662 	{
663 		LIGHTELEMENT* light_element = AllocateLightElement();
664 		if(light_element)
665 		{
666 			*light_element = *saved_light_element++;
667 		}
668 	}
669 
670 }
671 
Save_LightElements()672 void Save_LightElements()
673 {
674 	LIGHT_ELEMENT_SAVE_BLOCK_HEADER* block;
675 	int i;
676 
677 	if(!NumActiveLightElements) return;
678 
679 	//get memory for header
680 	GET_SAVE_BLOCK_POINTER(block);
681 
682 	//fill in header
683 	block->header.type = SaveBlock_LightElements;
684 	block->header.size = sizeof(*block) + NumActiveLightElements * sizeof(LIGHTELEMENT);
685 
686 	block->NumActiveLightElements = NumActiveLightElements;
687 
688 
689 	//now save the light elements
690 	for(i=0;i<NumActiveLightElements;i++)
691 	{
692 		LIGHTELEMENT* light = GET_SAVE_BLOCK_POINTER(light);
693 		*light = LightElementStorage[i];
694 	}
695 
696 }
697