1 #define DB_LEVEL 2
2 
3 #include "3dc.h"
4 #include "inline.h"
5 #include "module.h"
6 
7 #include "list_tem.hpp"
8 #include "chnkload.hpp"
9 #include "projload.hpp"
10 #include "gamedef.h"
11 #include "shpchunk.hpp"
12 #include "envchunk.hpp"
13 #include "obchunk.hpp"
14 #include "chunkpal.hpp"
15 #include "bmpnames.hpp"
16 #include "chnktexi.h"
17 #include "strachnk.hpp"
18 #include "animchnk.hpp"
19 #include "ltchunk.hpp"
20 #include "avpchunk.hpp"
21 #include "pathchnk.hpp"
22 
23 #include "objsetup.hpp"
24 #include "npcsetup.h"
25 #include "sprchunk.hpp"
26 #include "pcmenus.h"
27 #include <math.h>
28 #include "wpchunk.hpp"
29 #include "hierchnk.hpp"
30 #include "animobs.hpp"
31 #include "sequnces.h"
32 #include "fragchnk.hpp"
33 #include "hierplace.hpp"
34 
35 #include "pfarlocs.h"
36 #include "progress_bar.h"
37 #include "stratdef.h"
38 #include "equipmnt.h"
39 #include "bh_ais.h"
40 #include "bh_types.h"
41 #include "bh_plachier.h"
42 #include "bh_marin.h"
43 #include "pvisible.h"
44 #include "psndplat.h"
45 #include "jsndsup.h"
46 #include "avpreg.hpp"
47 #include "ffstdio.h"
48 
49 #include "decal.h"
50 #include "mempool.h"
51 #include "db.h"
52 #include "pldnet.h"
53 
54 extern "C" {
55 #include "inventry.h"
56 
57 extern int VideoMode;
58 extern int ScanDrawMode;
59 extern int ZBufferMode;
60 extern unsigned char *PaletteRemapTable;
61 extern unsigned char **PaletteShadingTableArray;
62 extern int HWAccel;
63 
64 extern VECTORCH PlayerStartLocation;
65 extern MATRIXCH PlayerStartMat;
66 
67 extern FARENTRYPOINTSHEADER *FALLP_EntryPoints;
68 
69 extern RIFFHANDLE env_rif;
70 
71 extern void NewOnScreenMessage(char *messagePtr);
72 
73 extern BOOL KeepMainRifFile;
74 
75 BOOL LevelHasStars;
76 
77 };
78 
79 // these are to link with chnkimag.cpp
80 const char * ToolsTex_Directory = "\\\\Kate\\Kate Share\\avp\\ToolsTex\\";
81 const char * GenTex_Directory = "\\\\Kate\\Kate Share\\avp\\GenG-Tex\\";
82 const char * SubShps_Directory = "SubShps\\All\\";
83 // const char * GenTex_Directory = 0;
84 const char * FixTex_Directory = "\\\\Kate\\Kate Share\\avp\\Fix-Tex\\";
85 const char * GameTex_Directory = "\\\\Kate\\Kate Share\\avp\\game-tex\\";
86 // new directories for new-style graphics - to be determined properly
87 char const * FirstTex_Directory = "Graphics"; // currently relative to cwd
88 char const * SecondTex_Directory = 0; // will be the src safe shadow for development builds
89 								//used for cd graphics directory in final version
90 
91 char* Rif_Sound_Directory=0;//set for the main level rif
92 
93 static char * light_set_name = "NORMALLT";
94 
95 static Object_Chunk * * o_chunk_array;
96 static int * aimodule_indeces; //array parallel to o_chunk_array
97 
98 extern void setup_placed_hierarchies(Environment_Data_Chunk * envd);
99 void setup_preplaced_decals(File_Chunk* fc,Environment_Data_Chunk* edc);
100 /////////////////////////////////////////
101 // Functions which operate on RIFFHANDLEs
102 /////////////////////////////////////////
103 
setup_start_position(RIFFHANDLE h)104 void setup_start_position(RIFFHANDLE h)
105 {
106 	Chunk * pChunk = h->envd->lookup_single_child("SPECLOBJ");
107 	AVP_Player_Start_Chunk* start_chunk=0;
108 	if(pChunk)
109 	{
110 		List<Chunk*> start_list;
111 		((Chunk_With_Children*)pChunk)->lookup_child("AVPSTART",start_list);
112 
113 		if(start_list.size())
114 			start_chunk=(AVP_Player_Start_Chunk*)start_list.first_entry();
115 
116 	}
117 	if(start_chunk)
118 	{
119 		PlayerStartLocation.vx=(int)(start_chunk->location.x*local_scale);
120 		PlayerStartLocation.vy=(int)(start_chunk->location.y*local_scale);
121 		PlayerStartLocation.vz=(int)(start_chunk->location.z*local_scale);
122 
123 		PlayerStartMat.mat11=start_chunk->orientation.mat11;
124 		PlayerStartMat.mat12=start_chunk->orientation.mat12;
125 		PlayerStartMat.mat13=start_chunk->orientation.mat13;
126 		PlayerStartMat.mat21=start_chunk->orientation.mat21;
127 		PlayerStartMat.mat22=start_chunk->orientation.mat22;
128 		PlayerStartMat.mat23=start_chunk->orientation.mat23;
129 		PlayerStartMat.mat31=start_chunk->orientation.mat31;
130 		PlayerStartMat.mat32=start_chunk->orientation.mat32;
131 		PlayerStartMat.mat33=start_chunk->orientation.mat33;
132 	}
133 	else
134 	{
135 		PlayerStartLocation.vx=0;
136 		PlayerStartLocation.vy=0;
137 		PlayerStartLocation.vz=0;
138 
139 		PlayerStartMat.mat11=65536;
140 		PlayerStartMat.mat12=0;
141 		PlayerStartMat.mat13=0;
142 		PlayerStartMat.mat21=0;
143 		PlayerStartMat.mat22=65536;
144 		PlayerStartMat.mat23=0;
145 		PlayerStartMat.mat31=0;
146 		PlayerStartMat.mat32=0;
147 		PlayerStartMat.mat33=65536;
148 	}
149 }
150 
setup_paths(RIFFHANDLE h)151 void setup_paths(RIFFHANDLE h)
152 {
153 	PathArraySize=0;
154 	PathArray=0;
155 
156 	Chunk * pChunk = h->envd->lookup_single_child("SPECLOBJ");
157 	if(!pChunk) return;
158 
159 	List<Chunk*> pathlist;
160 	((Chunk_With_Children*)pChunk)->lookup_child("AVPPATH2",pathlist);
161 
162 	if(!pathlist.size()) return;
163 
164 	//find the highest path index
165 	LIF<Chunk*> plif(&pathlist);
166 
167 	for(; !plif.done(); plif.next())
168 	{
169 		AVP_Path_Chunk* apc=(AVP_Path_Chunk*) plif();
170 		PathArraySize=max(PathArraySize,apc->PathID+1);
171 	}
172 
173 	PathArray=(PATHHEADER*)PoolAllocateMem(sizeof(PATHHEADER)*PathArraySize);
174 	for(int i=0;i<PathArraySize;i++)
175 	{
176 		PathArray[i].path_length=0;
177 		PathArray[i].modules_in_path=0;
178 	}
179 
180 	for(plif.restart();!plif.done();plif.next())
181 	{
182 		AVP_Path_Chunk* apc=(AVP_Path_Chunk*) plif();
183 		if(!apc->PathLength) continue;
184 
185 		PATHHEADER* path=&PathArray[apc->PathID];
186 
187 		int length=apc->PathLength;
188 		if(apc->flags & PathFlag_BackAndForth)
189 		{
190 			length=max(length,(length-1)*2);
191 		}
192 
193 		path->modules_in_path=(AIMODULE**)PoolAllocateMem(sizeof(AIMODULE*)*length);
194 
195 		for(int i=0;i<apc->PathLength;i++)
196 		{
197 			Object_Chunk* path_object=h->fc->get_object_by_index(apc->Path[i].module_index);
198 			if(!path_object)continue;
199 			if(path_object->program_object_index==-1) continue;
200 			AIMODULE* path_module=&AIModuleArray[aimodule_indeces[path_object->program_object_index]];
201 
202 			//if this ai module is the same as the previous one in the path , ignore it
203 			if(path->path_length)
204 			{
205 				if(path_module==path->modules_in_path[path->path_length-1])continue;
206 			}
207 
208 			path->modules_in_path[path->path_length]=path_module;
209 			path->path_length++;
210 		}
211 
212 		if(apc->flags & PathFlag_BackAndForth)
213 		{
214 			for(int i=path->path_length-2;i>0;i--)
215 			{
216 				path->modules_in_path[path->path_length]=path->modules_in_path[i];
217 				path->path_length++;
218 			}
219 		}
220 	}
221 
222 }
223 
224 extern "C"
225 {
226 extern int SkyColour_R;
227 extern int SkyColour_G;
228 extern int SkyColour_B;
229 };
230 
set_environment_properties(Environment_Data_Chunk * edc)231 void set_environment_properties(Environment_Data_Chunk* edc)
232 {
233 	GLOBALASSERT(edc);
234 	AVP_Environment_Settings_Chunk* env_set=GetAVPEnvironmentSettings(edc);
235 	GLOBALASSERT(env_set);
236 
237 //set sky colour
238 	SkyColour_R=env_set->settings->sky_colour_red;
239 	SkyColour_G=env_set->settings->sky_colour_green;
240 	SkyColour_B=env_set->settings->sky_colour_blue;
241 
242 	LevelHasStars=env_set->settings->stars_in_sky;
243 
244 //get starting equipment data
245 	StartingEquipment.marine_jetpack=env_set->settings->marine_jetpack;
246 
247 	StartingEquipment.predator_pistol=env_set->settings->predator_pistol;
248 	StartingEquipment.predator_plasmacaster=env_set->settings->predator_plasmacaster;
249 	StartingEquipment.predator_disc=env_set->settings->predator_disc;
250 	StartingEquipment.predator_medicomp=env_set->settings->predator_medicomp;
251 	StartingEquipment.predator_grappling_hook=env_set->settings->predator_grappling_hook;
252 	StartingEquipment.predator_num_spears=env_set->settings->predator_num_spears;
253 
254 	if(AvP.Network != I_No_Network)
255 	{
256 		StartingEquipment.predator_pistol=netGameData.allowPistol;
257 		StartingEquipment.predator_plasmacaster=netGameData.allowPlasmaCaster;
258 		StartingEquipment.predator_disc=netGameData.allowDisc;
259 		StartingEquipment.predator_medicomp=netGameData.allowMedicomp;
260 
261 		if(!netGameData.allowSpeargun)
262 		{
263 			StartingEquipment.predator_num_spears=0;
264 		}
265 	}
266 
267 }
268 
269 
270 
ConvertObjectIndexToPathIndex(int path_index,int object_index)271 int ConvertObjectIndexToPathIndex(int path_index,int object_index)
272 {
273 	if(path_index<0 || path_index>=PathArraySize)
274 	{
275 		return -1; //path doesn't exist
276 	}
277 
278 	Object_Chunk* oc=env_rif->fc->get_object_by_index(object_index);
279 	if(!oc)
280 	{
281 		return -1; //object doesn't exist
282 	}
283 	int module_index=oc->program_object_index;
284 	if(module_index==-1)
285 	{
286 		return -1; //object isn't a module
287 	}
288 	int aimodule_index=aimodule_indeces[module_index];
289 
290 
291 	PATHHEADER* path=&PathArray[path_index];
292 
293 	for(int i=0;i<path->path_length;i++)
294 	{
295 		if(path->modules_in_path[i]==&AIModuleArray[aimodule_index])
296 		{
297 			return i; //found the module in the path
298 		}
299 	}
300 
301 	return -1; //module isn't in path
302 
303 }
304 
305 
pre_process_shape(RIFFHANDLE,ChunkShape & cs,Chunk_With_Children * shape_chunk,int)306 void pre_process_shape (RIFFHANDLE, ChunkShape & cs, Chunk_With_Children * shape_chunk, int /*flags*/)
307 {
308 	Shape_Merge_Data_Chunk * smdc = 0;
309 
310 	Chunk * pChunk = shape_chunk->lookup_single_child("SHPMRGDT");
311 	if (pChunk)
312 	{
313 		smdc = (Shape_Merge_Data_Chunk *) pChunk;
314 	}
315 
316 	if (smdc)
317 		merge_polygons_in_chunkshape (cs,smdc);
318 }
319 
set_local_scale(RIFFHANDLE h,int)320 void set_local_scale(RIFFHANDLE h, int /*flags*/)
321 {
322 	local_scale = GlobalScale;
323 
324 	if (h->envd)
325 	{
326 		Chunk * pChunk = h->envd->lookup_single_child ("ENVSDSCL");
327 		if (pChunk)
328 			local_scale *= ((Environment_Scale_Chunk *)pChunk)->scale;
329 	}
330 }
331 
332 ////////////////////////////////////////////////////////////////////////////////////////////
333 //placed hierarchy stuff
334 
335 extern LOADED_SOUND const * GetSoundFromSoundPath(char* wavname);
336 
337 
338 extern void add_placed_hierarchy(Placed_Hierarchy_Chunk* phc,const char* fname,const char* hname);
339 
340 struct LoadedPlacedHierarchy
341 {
342 	void load_rif();
343 	void unload();
344 
345 	const char* file_name;
346 	const char* hier_name;
347 	RIFFHANDLE placed_rif;
348 };
349 
350 #define NumPlacedHierarchy 3
351 LoadedPlacedHierarchy PlacedHierarchyArray[NumPlacedHierarchy]=
352 {
353 	{ "dropship","dropship",INVALID_RIFFHANDLE },
354 	{ "pred ship fury","pred ship fury",INVALID_RIFFHANDLE },
355 	{ "pred ship ob","pred ship ob",INVALID_RIFFHANDLE },
356 };
357 
358 
load_rif()359 void LoadedPlacedHierarchy::load_rif()
360 {
361 	if(placed_rif!=INVALID_RIFFHANDLE) return;
362 	char file_path[100];
363 
364 	sprintf(file_path,"avp_huds/%s.rif",file_name);
365 
366 	placed_rif=avp_load_rif_non_env(file_path);
367 	if(placed_rif!=INVALID_RIFFHANDLE)
368 	{
369 		#if MaxImageGroups>1
370 		SetCurrentImageGroup(2); // load into environment image group
371 		#endif
372 		copy_rif_data(placed_rif,CCF_IMAGEGROUPSET + CCF_LOAD_AS_HIERARCHY_IF_EXISTS+CCF_DONT_INITIALISE_TEXTURES,0,0);
373 		unload_rif(placed_rif);
374 	}
375 }
unload()376 void LoadedPlacedHierarchy::unload()
377 {
378 	if(placed_rif!=INVALID_RIFFHANDLE)
379 	{
380 		avp_undo_rif_load(placed_rif); // destroys copied shapes
381 	}
382 	placed_rif=INVALID_RIFFHANDLE;
383 }
384 
385 
386 
setup_placed_hierarchies(Environment_Data_Chunk * envd)387 void setup_placed_hierarchies(Environment_Data_Chunk * envd)
388 {
389 	GLOBALASSERT(envd);
390 	Special_Objects_Chunk* soc=(Special_Objects_Chunk*)envd->lookup_single_child("SPECLOBJ");
391 	if(!soc) return;
392 
393 	List<Chunk*> chlist;
394 	soc->lookup_child("PLACHIER",chlist);
395 
396 	for(LIF<Chunk*> chlif(&chlist);!chlif.done();chlif.next())
397 	{
398 		Placed_Hierarchy_Chunk* phc=(Placed_Hierarchy_Chunk*)chlif();
399 		Placed_Hierarchy_Data_Chunk* phdc=phc->get_data_chunk();
400 
401 		if(phdc->hierarchy_index<0 || phdc->hierarchy_index>=NumPlacedHierarchy) continue;
402 
403 		//need to store the current sound directory , since it will get altered when loading the
404 		//hierarchy rif file.
405 		char* Temp_Rif_Sound_Directory = Rif_Sound_Directory;
406 
407 		PlacedHierarchyArray[phdc->hierarchy_index].load_rif();
408 
409 		//restore the sound directory
410 		Rif_Sound_Directory = Temp_Rif_Sound_Directory;
411 
412 		add_placed_hierarchy(phc,PlacedHierarchyArray[phdc->hierarchy_index].file_name,PlacedHierarchyArray[phdc->hierarchy_index].hier_name);
413 
414 	}
415 }
416 
unload_placed_hierarchies()417 void unload_placed_hierarchies()
418 {
419 	for(int i=0;i<NumPlacedHierarchy;i++)
420 	{
421 		PlacedHierarchyArray[i].unload();
422 	}
423 }
424 
425 
426 
427 
428 ///////////////////////////////////////////////////////////////////////////////
429 // stuff for handling hierarchies
430 
431 extern int GetSequenceID(int sequence_type,int sub_sequence);
432 extern "C" void MulQuat(QUAT *q1,QUAT *q2,QUAT *output);
433 
434 
435 List <Global_Hierarchy_Store *> Global_Hierarchy_Library;
436 List<Hierarchy_ID_Time_Pair*> Global_Hierarchy_Store::time_list;
437 
Global_Hierarchy_Store(RIFFHANDLE h)438 Global_Hierarchy_Store::Global_Hierarchy_Store (RIFFHANDLE h)
439 {
440 	GLOBALASSERT (h->envd);
441 
442 	Chunk * pChunk = h->envd->lookup_single_child ("RIFFNAME");
443 
444 	RIF_Name_Chunk * rnc = (RIF_Name_Chunk *) pChunk;
445 
446 	GLOBALASSERT (rnc);
447 
448 	riffname = (char*) PoolAllocateMem(strlen (rnc->rif_name)+1);
449 	strcpy (riffname, rnc->rif_name);
450 
451 	rif_hand=h;
452 
453 	sound_array=0;
454 
455 	//load the sounds used by this file
456 	List<Chunk*> chlist;
457 	h->fc->lookup_child("INDSOUND",chlist);
458 
459 	//find the highest sound index
460 	int max_index=-1;
461 	LIF<Chunk*> chlif(&chlist);
462 
463 	for(; !chlif.done(); chlif.next())
464 	{
465 		Indexed_Sound_Chunk* isc=(Indexed_Sound_Chunk*)chlif();
466 		max_index=max(max_index,isc->index);
467 	}
468 	//now create a large enough array , and fill it in
469    	num_sounds=max_index+1;
470 	if(max_index>=0)
471 	{
472 		//find this rif's sound directory
473 		Sound_Directory_Chunk* dir_chunk=(Sound_Directory_Chunk*) h->envd->lookup_single_child("SOUNDDIR");
474 		char wavname[200];
475 
476 		VECTORCH ZeroVector={0,0,0};
477 
478 		sound_array=(HIERARCHY_SOUND*) PoolAllocateMem(sizeof(HIERARCHY_SOUND)*(max_index+1));
479 		for(int i=0;i<=max_index;i++)
480 		{
481 			sound_array[i].sound_loaded=0;
482 		}
483 
484 		for(chlif.restart();!chlif.done();chlif.next())
485 		{
486 			Indexed_Sound_Chunk* isc=(Indexed_Sound_Chunk*)chlif();
487 			int index=isc->index;
488 
489 			GLOBALASSERT(sound_array[index].sound_loaded==0);
490 
491 			sound_array[index].s3d.inner_range=(int)(isc->inner_range*local_scale);
492 			sound_array[index].s3d.outer_range=(int)(isc->outer_range*local_scale);
493 			sound_array[index].s3d.velocity=ZeroVector;
494 			sound_array[index].s3d.position=ZeroVector;
495 
496 			sound_array[index].pitch=isc->pitch;
497 			sound_array[index].volume=isc->max_volume;
498 			if(dir_chunk)
499 			{
500 				sprintf(wavname,"%s\\%s",dir_chunk->directory,isc->wav_name);
501 				sound_array[index].sound_loaded=GetSound(wavname);
502 			}
503 			else
504 			{
505 				sound_array[index].sound_loaded=GetSound(isc->wav_name);
506 			}
507 			if(sound_array[index].sound_loaded)
508 			{
509 				sound_array[index].sound_index=(SOUNDINDEX)sound_array[index].sound_loaded->sound_num;
510 			}
511 		}
512 	}
513 }
514 
515 
~Global_Hierarchy_Store()516 Global_Hierarchy_Store::~Global_Hierarchy_Store()
517 {
518 	#if !USE_LEVEL_MEMORY_POOL
519 	if (riffname)
520 	{
521 		DeallocateMem(riffname);
522 	}
523 
524 
525 	while (hierarchy_list.size())
526 	{
527 		Hierarchy_Descriptor * hd = hierarchy_list.first_entry();
528 
529 
530 		if (hd->hierarchy_name)
531 			DeallocateMem (hd->hierarchy_name);
532 
533 		if (hd->hierarchy_root)
534 			delete_section (hd->hierarchy_root);
535 
536 		DeallocateMem (hd);
537 
538 		hierarchy_list.delete_first_entry();
539 	}
540 
541 	while(alternate_shape_set_list.size())
542 	{
543 		Hierarchy_Alternate_Shape_Set* hass=alternate_shape_set_list.first_entry();
544 		HIERARCHY_SHAPE_REPLACEMENT* hsr=hass->replaced_shapes;
545 
546 		while(hsr->replaced_section_name)
547 		{
548 			DeallocateMem (hsr->replaced_section_name);
549 			hsr++;
550 		}
551 
552 		DeallocateMem (hass->replaced_shapes);
553 		DeallocateMem (hass->shape_set_name);
554 		DeallocateMem (hass);
555 		alternate_shape_set_list.delete_first_entry();
556 	}
557 
558 	if(shape_collections)
559 	{
560 		for(int i=0;i<num_shape_collections;i++)
561 		{
562 			DeallocateMem (shape_collections[i].replacements);
563 		}
564 		DeallocateMem (shape_collections);
565 	}
566 	#else
567 	while (hierarchy_list.size())
568 	{
569 		hierarchy_list.delete_first_entry();
570 	}
571 	while(alternate_shape_set_list.size())
572 	{
573 		alternate_shape_set_list.delete_first_entry();
574 	}
575 	#endif
576 
577 	//get rid of any loaded sounds
578 	#if !NEW_DEALLOCATION_ORDER
579 	if(sound_array)
580 	{
581 		for(int i=0;i<num_sounds;i++)
582 		{
583 			if(sound_array[i].sound_loaded)
584 			{
585 				LoseSound(sound_array[i].sound_loaded);
586 			}
587 		}
588 		#if !USE_LEVEL_MEMORY_POOL
589 		DeallocateMem (sound_array);
590 		#endif
591 	}
592 	#endif
593 }
594 
add_hierarchy(List<Object_ShapeNum_Pair * > & osnp_lst,Object_Hierarchy_Chunk * ohc)595 void Global_Hierarchy_Store::add_hierarchy (List <Object_ShapeNum_Pair *> & osnp_lst, Object_Hierarchy_Chunk * ohc)
596 {
597 	List <Object_Hierarchy_Chunk *> ohcl = ohc->list_h_children();
598 
599 	GLOBALASSERT (ohcl.size() == 1);
600 
601 
602 	//check to see if this hierarchy has any sequences
603 	{
604 		Object_Hierarchy_Chunk* ohc=(Object_Hierarchy_Chunk*) ohcl.first_entry();
605 		if(!Get_Object_Animation_All_Sequence_Chunk(ohc))
606 		{
607 			List <Object_Animation_Sequence_Chunk *> seql;
608 			Chunk * pChunk = ohc->lookup_single_child ("OBANSEQS");
609 			if (pChunk)
610 			{
611 				((Object_Animation_Sequences_Chunk *)pChunk)->list_sequences(&seql);
612 			}
613 			if(!seql.size()) return;
614 		}
615 	}
616 
617 
618 	Hierarchy_Descriptor * hd =(Hierarchy_Descriptor*) PoolAllocateMem(sizeof(Hierarchy_Descriptor));
619 
620 	Object_Hierarchy_Name_Chunk * ohnc = ohc->get_name();
621 	if (ohnc)
622 	{
623 		hd->hierarchy_name = (char*)PoolAllocateMem(strlen (ohnc->hierarchy_name) + 1);
624 		strcpy (hd->hierarchy_name, ohnc->hierarchy_name);
625 	}
626 	else
627 	{ // throw back from old system, no new hierarchies should be created with no name
628 		hd->hierarchy_name = (char*) PoolAllocateMem(strlen ("Template") + 1);
629 		strcpy (hd->hierarchy_name, "Template");
630 	}
631 
632 
633 	build_time_list(ohcl.first_entry());
634 	hd->hierarchy_root = build_hierarchy (ohcl.first_entry(),hd->hierarchy_name);
635 	while(time_list.size())
636 	{
637 		delete time_list.first_entry();
638 		time_list.delete_first_entry();
639 	}
640 
641 	hd->hierarchy_root->flags |= section_is_master_root;
642 
643 
644 	hierarchy_list.add_entry (hd);
645 
646 	Preprocess_HModel (hd->hierarchy_root ,riffname);
647 }
648 
649 static List<int> random_marine_texturings;
650 static List<int> random_civilian_texturings;
651 
setup_alternate_shape_sets(List<Object_ShapeNum_Pair * > & osnp_lst,File_Chunk * fc)652 void Global_Hierarchy_Store::setup_alternate_shape_sets(List <Object_ShapeNum_Pair *> & osnp_lst, File_Chunk * fc)
653 {
654 	List<Chunk*> chlist;
655 	fc->lookup_child("OBHALTSH",chlist);
656 
657 	LIF<Chunk*> chlif(&chlist);
658 	for(; !chlif.done(); chlif.next())
659 	{
660 		Object_Hierarchy_Alternate_Shape_Set_Chunk* ohassc=(Object_Hierarchy_Alternate_Shape_Set_Chunk*) chlif();
661 
662 		Hierarchy_Alternate_Shape_Set* hass=(Hierarchy_Alternate_Shape_Set*) PoolAllocateMem(sizeof(Hierarchy_Alternate_Shape_Set));
663 
664 		hass->shape_set_name=(char*) PoolAllocateMem(strlen(ohassc->Shape_Set_Name)+1);
665 		hass->index=ohassc->Shape_Set_Num;
666 		hass->num_replaced_shapes=ohassc->Replaced_Shape_List.size();
667 		strcpy(hass->shape_set_name,ohassc->Shape_Set_Name);
668 
669 		hass->flags=ohassc->flags;
670 
671 		hass->replaced_shapes=(HIERARCHY_SHAPE_REPLACEMENT*) PoolAllocateMem(sizeof(HIERARCHY_SHAPE_REPLACEMENT)*(ohassc->Replaced_Shape_List.size()+1));
672 
673 		HIERARCHY_SHAPE_REPLACEMENT* hsr=hass->replaced_shapes;
674 		for(LIF<Replaced_Shape_Details*> rlif(&ohassc->Replaced_Shape_List);!rlif.done();rlif.next(),hsr++)
675 		{
676 			hsr->replaced_section_name=(char*) PoolAllocateMem(strlen(rlif()->old_object_name)+1);
677 			strcpy(hsr->replaced_section_name,rlif()->old_object_name);
678 
679 			hsr->replacement_id = 0;
680 
681 			//find the shape num for the new shape
682 			LIF<Object_ShapeNum_Pair*> olif(&osnp_lst);
683 
684 			for(; !olif.done(); olif.next())
685 			{
686 				if(!strcmp(olif()->ob->object_data.o_name,rlif()->new_object_name))
687 				{
688 					hsr->replacement_shape=mainshapelist[olif()->sh_num];
689 					hsr->replacement_shape_index=olif()->sh_num;
690 					break;
691 				}
692 			}
693 			if(olif.done())
694 			{
695 				//alternate shape set removes this object
696 				hsr->replacement_shape=0;
697 				hsr->replacement_shape_index=0;
698 			}
699 
700 		}
701 		hsr->replaced_section_name=0;
702 		hsr->replacement_shape=0;
703 
704 		alternate_shape_set_list.add_entry(hass);
705 	}
706 
707 
708 	num_shape_collections=0;
709 	shape_collections=0;
710 
711 	//now set up the shape set collections
712 	List_Hierarchy_Shape_Set_Collection_Chunk(fc,chlist);
713 
714 	//find the highest index
715 	int max_index=-1;
716 	for(chlif.restart();!chlif.done();chlif.next())
717 	{
718 		Hierarchy_Shape_Set_Collection_Chunk* coll=(Hierarchy_Shape_Set_Collection_Chunk*)chlif();
719 		max_index=max(max_index,coll->Set_Collection_Num);
720 	}
721 
722 	if(max_index==-1) return;
723 
724 	//allocate array for shape sets and initialise to zero
725 	num_shape_collections=max_index+1;
726 	shape_collections=(HIERARCHY_VARIANT_DATA*) PoolAllocateMem(sizeof(HIERARCHY_VARIANT_DATA)*num_shape_collections);
727 	for(int i=0;i<num_shape_collections;i++)
728 	{
729 		shape_collections[i].replacements=0;
730 		shape_collections[i].voice=0;
731 		shape_collections[i].female=0;
732 
733 	}
734 	//find the collections that can be randomly generated
735 	List<int>* ran_list=0;
736 	if(!_stricmp(riffname,"hnpcmarine"))
737 	{
738 		if(random_marine_texturings.size()) ran_list=&random_marine_texturings;
739 	}
740 	else if(!_stricmp(riffname,"hnpc_civvie"))
741 	{
742 		if(random_civilian_texturings.size()) ran_list=&random_civilian_texturings;
743 	}
744 
745 	if(!ran_list || ran_list->contains(1))
746 		random_shape_colls.add_entry(1);
747 
748 	//now go through the list of shape set collections again
749 	Hierarchy_Alternate_Shape_Set* found_sets[20];
750 	int num_found_sets;
751 	int num_shapes_to_replace;
752 	LIF<Hierarchy_Alternate_Shape_Set*> alt_lif(&alternate_shape_set_list);
753 	for(chlif.restart();!chlif.done();chlif.next())
754 	{
755 		Hierarchy_Shape_Set_Collection_Chunk* coll=(Hierarchy_Shape_Set_Collection_Chunk*)chlif();
756 		GLOBALASSERT(coll->Index_List.size()<20);
757 		//locate the sets that this collections is using
758 		num_found_sets=0;
759 		num_shapes_to_replace=0;
760 		int combined_flags=0;
761 
762 		for(LIF<int> ind_lif(&coll->Index_List);!ind_lif.done();ind_lif.next())
763 		{
764 			for(alt_lif.restart();!alt_lif.done();alt_lif.next())
765 			{
766 				if(ind_lif()==alt_lif()->index)
767 				{
768 					found_sets[num_found_sets]=alt_lif();
769 					num_found_sets++;
770 					num_shapes_to_replace+=alt_lif()->num_replaced_shapes;
771 					combined_flags|=alt_lif()->flags;
772 					break;
773 				}
774 			}
775 		}
776 
777 		if(num_found_sets)
778 		{
779 			HIERARCHY_SHAPE_REPLACEMENT* hsr=(HIERARCHY_SHAPE_REPLACEMENT*) PoolAllocateMem(sizeof(HIERARCHY_SHAPE_REPLACEMENT)*(num_shapes_to_replace+1));
780 			shape_collections[coll->Set_Collection_Num].replacements=(struct hierarchy_shape_replacement*)hsr;
781 
782 			if(combined_flags & Avp_ShapeSet_Flag_Female)
783 				shape_collections[coll->Set_Collection_Num].female=1;
784 
785 			shape_collections[coll->Set_Collection_Num].voice=coll->TypeIndex;
786 
787 
788 			int pos=0;
789 			for(int i=0;i<num_found_sets;i++)
790 			{
791 				Hierarchy_Alternate_Shape_Set* hass=found_sets[i];
792 				for(int j=0;j<hass->num_replaced_shapes;j++)
793 				{
794 					//just take a straight copy since the shape set collections won't deallocate the names
795 					hsr[pos]=hass->replaced_shapes[j];
796 					hsr[pos].replacement_id = coll->Set_Collection_Num;
797 					pos++;
798 				}
799 
800 			}
801 			hsr[pos].replaced_section_name=0;
802 			hsr[pos].replacement_shape=0;
803 		}
804 
805 		//see if this collection can appear randomly
806 		if(!ran_list || ran_list->contains(coll->Set_Collection_Num))
807 		{
808 			random_shape_colls.add_entry(coll->Set_Collection_Num);
809 		}
810 	}
811 }
812 
delete_section(SECTION * s2d)813 void Global_Hierarchy_Store::delete_section(SECTION * s2d)
814 {
815 	#if !USE_LEVEL_MEMORY_POOL
816 	SECTION ** csp = &s2d->Children[0];
817 	if (csp)
818 	{
819 		while (*csp)
820 		{
821 			delete_section (*csp);
822 			csp ++;
823 		}
824 		DeallocateMem ((void *)s2d->Children);
825 
826 	}
827 
828 	for (int i=0; i<s2d->num_sequences; i++)
829 	{
830 		DeallocateMem (s2d->sequence_array[i].first_frame);
831 	}
832 
833 	DeallocateMem ((void *)s2d->sequence_array);
834 
835 	if (s2d->Section_Name)
836 	{
837 		DeallocateMem ((void *)s2d->Section_Name);
838 	}
839 
840 	if (s2d->ShapeName)
841 	{
842 		DeallocateMem ((void *)s2d->ShapeName);
843 	}
844 
845 	DeallocateMem ((void *)s2d);
846   	#endif
847 }
848 
849 
build_hierarchy(Object_Hierarchy_Chunk * ohc,char * hierarchy_name)850 SECTION * Global_Hierarchy_Store::build_hierarchy (Object_Hierarchy_Chunk * ohc,char* hierarchy_name)
851 {
852 	// iterative bit
853 	// should be called with the root node
854 	// containing an object
855 
856 
857 
858 
859 	Object_Hierarchy_Data_Chunk * ohdc = ohc->get_data();
860 
861 	GLOBALASSERT (ohdc);
862 	GLOBALASSERT (ohdc->ob_name);
863 
864 
865 	// make a section
866 
867 	SECTION * currsection = (SECTION *)PoolAllocateMem (sizeof (SECTION));
868 
869 	currsection->flags = 0;
870 	currsection->ShapeName = 0;
871 	currsection->Hierarchy_Name=hierarchy_name;
872 	currsection->Rif_Name=riffname;
873 
874 	currsection->Section_Name = (char *)PoolAllocateMem (strlen (ohdc->ob_name) + 1);
875 	strcpy (currsection->Section_Name, ohdc->ob_name);
876 
877 	if (ohdc->object)
878 	{
879 		GLOBALASSERT(ohdc->object->program_object_index!=-1);
880 		currsection->ShapeNum = ohdc->object->program_object_index;
881 		currsection->Shape = mainshapelist[ohdc->object->program_object_index];
882 	}
883 	else
884 	{
885 		currsection->ShapeNum = -1;
886 		currsection->Shape = 0;
887 	}
888 
889 	Object_Animation_All_Sequence_Chunk* all_seq=Get_Object_Animation_All_Sequence_Chunk(ohc);
890 	if(all_seq)
891 	{
892 		currsection->num_sequences=all_seq->num_sequences;
893 		currsection->sequence_array = 0;
894 		if(all_seq->num_sequences)
895 		{
896 			currsection->sequence_array = (SEQUENCE *)PoolAllocateMem (sizeof(SEQUENCE) * all_seq->num_sequences);
897 			SEQUENCE * seqa_p = currsection->sequence_array;
898 
899 			for(int i=0;i<all_seq->num_sequences;i++)
900 			{
901 				KEYFRAME_DATA ** next_frame_ptr=&seqa_p->first_frame;
902 				KEYFRAME_DATA * delta_frame=0;
903 
904 				Object_Animation_Sequence* seq=&all_seq->sequences[i];
905 
906 				seqa_p->sequence_id = GetSequenceID (seq->sequence_number, seq->sub_sequence_number);
907 				seqa_p->Time = (seq->sequence_time*ONE_FIXED)/1000;
908 
909 
910 				KEYFRAME_DATA * kfd=0;
911 
912 
913 				for(unsigned int frame_no=0;frame_no<seq->num_frames;)
914 				{
915 					Object_Animation_Frame* frame=&seq->frames[frame_no];
916 
917 					int flags=0;
918 					HIERARCHY_SOUND* sound=0;
919 
920 					//see if there are any flags or sounds on this frame
921 					flags=frame->flags & HierarchyFrame_FlagMask;
922 					int sound_index=frame->get_sound_index();
923 					if(sound_index>0 && sound_index<num_sounds)
924 					{
925 						if(sound_array[sound_index].sound_loaded)
926 						{
927 							sound=&sound_array[sound_index];
928 						}
929 					}
930 
931 					if(flags || sound)
932 					{
933 						//need to use extended keyframe
934 						KEYFRAME_DATA_EXTENDED* kfd_extended=(KEYFRAME_DATA_EXTENDED*) PoolAllocateMem(sizeof(KEYFRAME_DATA_EXTENDED));
935 						kfd=(KEYFRAME_DATA*) kfd_extended;
936 
937 						kfd->frame_has_extended_data=1;
938 						kfd_extended->sound=sound;
939 						kfd_extended->flags=flags;
940 
941 
942 					}
943 					else
944 					{
945 						//use standard keyframe
946 						kfd =(KEYFRAME_DATA*) PoolAllocateMem(sizeof(KEYFRAME_DATA));
947 
948 						kfd->frame_has_extended_data=0;
949 					}
950 
951 					kfd->last_frame=0; //if this is in fact the last frame , then this will be changed later
952 
953 					//set up previous frames next pointer
954 					*next_frame_ptr=kfd;
955 					next_frame_ptr=&kfd->Next_Frame;
956 
957 
958 					if(frame->flags & HierarchyFrameFlag_DeltaFrame)
959 					{
960 						GLOBALASSERT(delta_frame==0); //should only be one frame with this flag
961 						delta_frame=kfd;
962 					}
963 
964 					VECTORCH offset;
965 
966 					offset.vx = (int)(frame->transform.x * local_scale);
967 					offset.vy = (int)(frame->transform.y * local_scale);
968 					offset.vz = (int)(frame->transform.z * local_scale);
969 
970 					SetKeyFrameOffset(kfd,&offset);
971 
972 					QUAT q;
973 
974 					q.quatx = (int) -(frame->orientation.x*ONE_FIXED);
975 					q.quaty = (int) -(frame->orientation.y*ONE_FIXED);
976 					q.quatz = (int) -(frame->orientation.z*ONE_FIXED);
977 					q.quatw = (int) (frame->orientation.w*ONE_FIXED);
978 
979 					CopyIntQuatToShort(&q,&kfd->QOrient);
980 
981 
982 					int this_frame_no = frame->at_frame_no;
983 
984 
985 
986 					frame_no++;
987 
988 					if (frame_no<seq->num_frames)
989 					{
990 						//calculate sequence length , making sure it doesn't overflow an unsigned short
991 						kfd->Sequence_Length =(unsigned short) min(seq->frames[frame_no].at_frame_no - this_frame_no,65535);
992 					}
993 					else
994 					{
995 						kfd->Sequence_Length =(unsigned short) min(65536 - this_frame_no,65535);
996 					}
997 
998 				}
999 				//sort out some settings for the last frame
1000 				kfd->last_frame=1;
1001 				if(kfd->Sequence_Length<=6)
1002 				{
1003 					//this sequence doesn't loop
1004 					kfd->Next_Frame=kfd;
1005 				}
1006 				else
1007 				{
1008 					//this sequence loops
1009 					kfd->Next_Frame=seqa_p->first_frame;
1010 				}
1011 
1012 				seqa_p->last_frame = kfd;
1013 
1014 
1015 
1016 				if(delta_frame)
1017 				{
1018 					//this sequence is a delta sequence , so convert all frames to deltas relative
1019 					//to delta_frame
1020 
1021 					QUAT inverse_delta;
1022 
1023 					CopyShortQuatToInt(&delta_frame->QOrient,&inverse_delta);
1024 
1025 					VECTORCH inverse_offset;
1026 					GetKeyFrameOffset(delta_frame,&inverse_offset);
1027 
1028 					inverse_delta.quatx = -inverse_delta.quatx;
1029 					inverse_delta.quaty = -inverse_delta.quaty;
1030 					inverse_delta.quatz = -inverse_delta.quatz;
1031 
1032 					inverse_offset.vx = -inverse_offset.vx;
1033 					inverse_offset.vy = -inverse_offset.vy;
1034 					inverse_offset.vz = -inverse_offset.vz;
1035 
1036 					kfd = seqa_p->first_frame;
1037 
1038 					while (1)
1039 					{
1040 						// do deltas
1041 						QUAT q;
1042 
1043 						CopyShortQuatToInt(&kfd->QOrient,&q);
1044 
1045 						MulQuat (&q, &inverse_delta, &q);
1046 						CopyIntQuatToShort(&q,&kfd->QOrient);
1047 
1048 						VECTORCH offset;
1049 						GetKeyFrameOffset(kfd,&offset);
1050 
1051 						offset.vx += inverse_offset.vx;
1052 						offset.vy += inverse_offset.vy;
1053 						offset.vz += inverse_offset.vz;
1054 
1055 						SetKeyFrameOffset(kfd,&offset);
1056 
1057 						if(kfd->last_frame) break;
1058 
1059 						kfd = kfd->Next_Frame;
1060 					}
1061 
1062 
1063 				}
1064 
1065 
1066 				seqa_p ++;
1067 			}
1068 
1069 		}
1070 	}
1071 	else
1072 	{
1073 		List <Object_Animation_Sequence_Chunk *> seql;
1074 
1075 		Chunk * pChunk = ohc->lookup_single_child ("OBANSEQS");
1076 
1077 		if (pChunk)
1078 		{
1079 			((Object_Animation_Sequences_Chunk *)pChunk)->list_sequences(&seql);
1080 		}
1081 
1082 		currsection->num_sequences = seql.size();
1083 		currsection->sequence_array = 0;
1084 
1085 		// fill in sequences
1086 
1087 
1088 		if (seql.size())
1089 		{
1090 			currsection->sequence_array = (SEQUENCE *)PoolAllocateMem (sizeof(SEQUENCE) * seql.size());
1091 			SEQUENCE * seqa_p = currsection->sequence_array;
1092 
1093 			for (LIF<Object_Animation_Sequence_Chunk *> seqi(&seql); !seqi.done(); seqi.next())
1094 			{
1095 
1096 				Object_Animation_Sequence_Header_Chunk * oashc = seqi()->get_header();
1097 				GLOBALASSERT (oashc);
1098 
1099 				seqa_p->sequence_id = GetSequenceID (oashc->sequence_number, oashc->sub_sequence_number);
1100 				seqa_p->Time = get_time_from_sequence_id(seqa_p->sequence_id);
1101 
1102 				List <Object_Animation_Sequence_Frame_Chunk	*> f_list;
1103 				seqi()->get_frames(&f_list);
1104 
1105 				GLOBALASSERT (f_list.size());
1106 
1107 				int num_frames=f_list.size();
1108 				Object_Animation_Sequence_Frame_Chunk ** frame_array= new Object_Animation_Sequence_Frame_Chunk*[num_frames];
1109 
1110 				LIF<Object_Animation_Sequence_Frame_Chunk *> fli(&f_list);
1111 
1112 
1113 				for (; !fli.done(); fli.next())
1114 				{
1115 					GLOBALASSERT(fli()->frame_ref_no<num_frames);
1116 					frame_array[fli()->frame_ref_no]=fli();
1117 
1118 				}
1119 				KEYFRAME_DATA ** next_frame_ptr=&seqa_p->first_frame;
1120 				KEYFRAME_DATA * delta_frame=0;
1121 
1122 				KEYFRAME_DATA * kfd=0;
1123 
1124 
1125 				for(int frame_no=0;frame_no<num_frames;)
1126 				{
1127 					Object_Animation_Sequence_Frame_Chunk* frame=frame_array[frame_no];
1128 
1129 					int flags=0;
1130 					HIERARCHY_SOUND* sound=0;
1131 
1132 					//see if there are any flags or sounds on this frame
1133 					flags=frame->flags & HierarchyFrame_FlagMask;
1134 					int sound_index=frame->get_sound_index();
1135 					if(sound_index>0 && sound_index<num_sounds)
1136 					{
1137 						if(sound_array[sound_index].sound_loaded)
1138 						{
1139 							sound=&sound_array[sound_index];
1140 						}
1141 					}
1142 
1143 					if(flags || sound)
1144 					{
1145 						//need to use extended keyframe
1146 						KEYFRAME_DATA_EXTENDED* kfd_extended=(KEYFRAME_DATA_EXTENDED*) PoolAllocateMem(sizeof(KEYFRAME_DATA_EXTENDED));
1147 						kfd=(KEYFRAME_DATA*) kfd_extended;
1148 
1149 						kfd->frame_has_extended_data=1;
1150 						kfd_extended->sound=sound;
1151 						kfd_extended->flags=flags;
1152 
1153 					}
1154 					else
1155 					{
1156 						//use standard keyframe
1157 						kfd =(KEYFRAME_DATA*) PoolAllocateMem(sizeof(KEYFRAME_DATA));
1158 
1159 						kfd->frame_has_extended_data=0;
1160 
1161 					}
1162 					kfd->last_frame=0; //if this is in fact the last frame , then this will be changed later
1163 
1164 					//set up previous frames next pointer
1165 					*next_frame_ptr=kfd;
1166 					next_frame_ptr=&kfd->Next_Frame;
1167 
1168 					if(frame->flags & HierarchyFrameFlag_DeltaFrame)
1169 					{
1170 						GLOBALASSERT(delta_frame==0); //should only be one frame with this flag
1171 						delta_frame=kfd;
1172 					}
1173 
1174 					VECTORCH offset;
1175 
1176 					offset.vx = (int)(frame->transform.x * local_scale);
1177 					offset.vy = (int)(frame->transform.y * local_scale);
1178 					offset.vz = (int)(frame->transform.z * local_scale);
1179 
1180 					SetKeyFrameOffset(kfd,&offset);
1181 
1182 					QUAT q;
1183 
1184 					q.quatx = (int) -(frame->orientation.x*ONE_FIXED);
1185 					q.quaty = (int) -(frame->orientation.y*ONE_FIXED);
1186 					q.quatz = (int) -(frame->orientation.z*ONE_FIXED);
1187 					q.quatw = (int) (frame->orientation.w*ONE_FIXED);
1188 
1189 
1190 					CopyIntQuatToShort(&q,&kfd->QOrient);
1191 
1192 					int this_frame_no = frame->at_frame_no;
1193 
1194 					frame_no++;
1195 
1196 					if (frame_no<num_frames)
1197 					{
1198 						//calculate sequence length , making sure it doesn't overflow an unsigned short
1199 						kfd->Sequence_Length =(unsigned short) min(frame_array[frame_no]->at_frame_no - this_frame_no,65535);
1200 					}
1201 					else
1202 					{
1203 						kfd->Sequence_Length =(unsigned short) min(65536 - this_frame_no , 65535);
1204 					}
1205 				}
1206 				//sort out some settings for the last frame
1207 				kfd->last_frame=1;
1208 				if(kfd->Sequence_Length<=6)
1209 				{
1210 					//this sequence doesn't loop
1211 					kfd->Next_Frame=kfd;
1212 				}
1213 				else
1214 				{
1215 					//this sequence loops
1216 					kfd->Next_Frame=seqa_p->first_frame;
1217 				}
1218 				seqa_p->last_frame = kfd;
1219 
1220 				delete [] frame_array;
1221 
1222 
1223 				if(delta_frame)
1224 				{
1225 					//this sequence is a delta sequence , so convert all frames to deltas relative
1226 					//to the frame delta_frame
1227 
1228 					QUAT inverse_delta;
1229 					CopyShortQuatToInt(&delta_frame->QOrient,&inverse_delta);
1230 
1231 					VECTORCH inverse_offset;
1232 					GetKeyFrameOffset(delta_frame,&inverse_offset);
1233 
1234 
1235 					inverse_delta.quatx = -inverse_delta.quatx;
1236 					inverse_delta.quaty = -inverse_delta.quaty;
1237 					inverse_delta.quatz = -inverse_delta.quatz;
1238 
1239 					inverse_offset.vx = -inverse_offset.vx;
1240 					inverse_offset.vy = -inverse_offset.vy;
1241 					inverse_offset.vz = -inverse_offset.vz;
1242 
1243 					kfd = seqa_p->first_frame;
1244 
1245 					while (1)
1246 					{
1247 						// do deltas
1248 						QUAT q;
1249 
1250 						CopyShortQuatToInt(&kfd->QOrient,&q);
1251 
1252 						MulQuat (&q, &inverse_delta, &q);
1253 						CopyIntQuatToShort(&q,&kfd->QOrient);
1254 
1255 						VECTORCH offset;
1256 						GetKeyFrameOffset(kfd,&offset);
1257 
1258 						offset.vx += inverse_offset.vx;
1259 						offset.vy += inverse_offset.vy;
1260 						offset.vz += inverse_offset.vz;
1261 
1262 						SetKeyFrameOffset(kfd,&offset);
1263 
1264 						if(kfd->last_frame) break;
1265 
1266 						kfd = kfd->Next_Frame;
1267 					}
1268 
1269 				}
1270 
1271 
1272 				seqa_p ++;
1273 			}
1274 		}
1275 	}
1276 
1277 	currsection->Children = 0;
1278 
1279 	List <Object_Hierarchy_Chunk *> h_children = ohc->list_h_children();
1280 
1281 	if (h_children.size())
1282 	{
1283 		currsection->Children = (SECTION **)PoolAllocateMem (sizeof (SECTION *) * (h_children.size()+1));
1284 
1285 		int i = 0;
1286 
1287 		for (LIF<Object_Hierarchy_Chunk *> hci(&h_children); !hci.done(); hci.next())
1288 		{
1289 			if ((currsection->Children[i++] = build_hierarchy (hci(),hierarchy_name)) == 0)
1290 				return 0;
1291 		}
1292 		currsection->Children[i] = 0;
1293 	}
1294 
1295 
1296 	return(currsection);
1297 
1298 }
1299 
build_time_list(Object_Hierarchy_Chunk * ohc)1300 void Global_Hierarchy_Store::build_time_list(Object_Hierarchy_Chunk* ohc)
1301 {
1302 	List <Object_Animation_Sequence_Chunk *> seql;
1303 	Chunk * pChunk = ohc->lookup_single_child ("OBANSEQS");
1304 	if (pChunk)
1305 	{
1306 		((Object_Animation_Sequences_Chunk *)pChunk)->list_sequences(&seql);
1307 	}
1308 
1309 	for (LIF<Object_Animation_Sequence_Chunk *> seqi(&seql); !seqi.done(); seqi.next())
1310 	{
1311 		Object_Animation_Sequence_Header_Chunk * oashc = seqi()->get_header();
1312 		GLOBALASSERT (oashc);
1313 
1314 		int id=GetSequenceID (oashc->sequence_number, oashc->sub_sequence_number);
1315 		int time=(seqi()->get_sequence_time()*ONE_FIXED)/1000;
1316 		if(time)
1317 		{
1318 			Hierarchy_ID_Time_Pair* id_time = new Hierarchy_ID_Time_Pair;
1319 			id_time->id=id;
1320 			id_time->time=time;
1321 			time_list.add_entry(id_time);
1322 		}
1323 	}
1324 }
1325 
get_time_from_sequence_id(int id)1326 int Global_Hierarchy_Store::get_time_from_sequence_id(int id)
1327 {
1328 	for(LIF<Hierarchy_ID_Time_Pair*> tlif(&time_list);!tlif.done();tlif.next())
1329 	{
1330 		if(tlif()->id==id)
1331 		{
1332 			return tlif()->time;
1333 		}
1334 	}
1335 	return 0;
1336 }
1337 
1338 
copy_rif_data_as_hierarchy(RIFFHANDLE h,int flags,int progress_start,int progress_interval)1339 static BOOL copy_rif_data_as_hierarchy (RIFFHANDLE h, int flags,int progress_start,int progress_interval)
1340 {
1341  //////////////////////////
1342  // Sort out local scale //
1343  //////////////////////////
1344 	int i;
1345 	set_local_scale(h,flags);
1346 
1347 	Set_Progress_Bar_Position(progress_start);
1348 
1349 	//SelectGenTexDirectory(ITI_TEXTURE);
1350 
1351 	#if 0 //disable the multiple image group stuff
1352 	if(!(flags & CCF_DONT_INITIALISE_TEXTURES))
1353 	{
1354 		InitialiseTextures();
1355 	}
1356 	#endif
1357 
1358 	/*find this rif's sound directory*/
1359 	Rif_Sound_Directory=0;
1360 	Sound_Directory_Chunk* dir_chunk=(Sound_Directory_Chunk*)h->envd->lookup_single_child("SOUNDDIR");
1361 	if(dir_chunk)
1362 	{
1363 		Rif_Sound_Directory=dir_chunk->directory;
1364 	}
1365 
1366 
1367 	load_rif_bitmaps(h,flags);
1368 
1369 	List <Object_ShapeNum_Pair *> osnp_list;
1370 	List <Object_ShapeNum_Pair *> low_osnp_list;
1371 	List <Object_Chunk *> obl;
1372 	h->fc->list_objects(&obl);
1373 
1374  	int NumObjectsToLoad=obl.size(); //for progress_bar
1375  	int NumObjectsLoaded=0;
1376 
1377 	for (LIF<Object_Chunk *> oli(&obl); !oli.done(); oli.next())
1378 	{
1379 		if((NumObjectsLoaded &0xf)==0)
1380 		{
1381 			//update bar every 16 objects
1382 			Set_Progress_Bar_Position((int)(progress_start+progress_interval*((.5*NumObjectsLoaded)/NumObjectsToLoad)));
1383 		}
1384 		NumObjectsLoaded++;
1385 
1386 
1387 		Shape_Chunk * tmpshp = oli()->get_assoc_shape();
1388 		//ChunkShape cs = tmpshp->shape_data;
1389 
1390 		CTM_ReturnType rt_temp = copy_to_mainshapelist(h,tmpshp,flags);
1391 		Object_ShapeNum_Pair * osnp = new Object_ShapeNum_Pair;
1392 
1393 		osnp->sh_num = rt_temp.main_list_pos;
1394 		osnp->ob = oli();
1395 		const char* ob_name=osnp->ob->object_data.o_name;
1396 		if(ob_name[0]=='L' && ob_name[1] && ob_name[2]=='#')
1397 		{
1398 			low_osnp_list.add_entry(osnp);
1399 		}
1400 		else
1401 		{
1402 			osnp_list.add_entry (osnp);
1403 		}
1404 
1405 		osnp->ob->program_object_index=osnp->sh_num;
1406 
1407 
1408 		//add the prelighting data to the shape
1409 
1410 		Shape_Vertex_Intensities_Chunk * svic = 0;
1411 
1412 		List<Chunk *> cl;
1413 		osnp->ob->lookup_child ("SHPVTINT",cl);
1414 
1415 		for (LIF<Chunk *> svici(&cl); !svici.done(); svici.next())
1416 		{
1417 			Shape_Vertex_Intensities_Chunk * temp_svic = (Shape_Vertex_Intensities_Chunk *) svici();
1418 			if (!strncmp(temp_svic->light_set_name, ::light_set_name, 8))
1419 			{
1420 				svic = temp_svic;
1421 				break;
1422 			}
1423 
1424 		}
1425 
1426 		if (svic)
1427 		{
1428 
1429 			mainshapelist[osnp->sh_num]->sh_extraitemdata = (EXTRAITEMDATA *)PoolAllocateMem(12 * svic->num_vertices);
1430 			if (!mainshapelist[osnp->sh_num]->sh_extraitemdata)
1431 			{
1432 				memoryInitialisationFailure = 1;
1433 				return FALSE;
1434 			}
1435 
1436 			for (int vn = 0; vn < svic->num_vertices; vn++)
1437 			{
1438 				//convert coloured light to a brightness value
1439 				int ir=svic->intensity_array[vn]>>16;
1440 			 	int ig=svic->intensity_array[vn]>>8 &0xff;
1441 			 	int ib=svic->intensity_array[vn] &0xff;
1442 			 	int mag = (int)sqrt((ir*ir+ig*ig+ib*ib)/3.0);
1443 
1444 			 	mainshapelist[osnp->sh_num]->sh_extraitemdata[vn].EID_VertexI = svic->intensity_array[vn] + (mag<<24);
1445 
1446 			}
1447 
1448 			mainshapelist[osnp->sh_num]->shapeflags |= ShapeFlag_PreLit;
1449 
1450 		}
1451 
1452 	}
1453 	/*-----------------------------**
1454 	** Load shapes with no objects **
1455 	**-----------------------------*/
1456 
1457 	//don't want these to be scaled with the level
1458 	double temp_scale=local_scale;
1459 	local_scale=GlobalScale;
1460 
1461 	List<Chunk *> shps;
1462 	h->fc->lookup_child ("REBSHAPE",shps);
1463 
1464 	for (LIF<Chunk *> shplst(&shps) ; !shplst.done() ; shplst.next())
1465 	{
1466 
1467  		Shape_Chunk * tmpshp = (Shape_Chunk *)shplst();
1468 
1469 		if ( ! tmpshp->list_assoc_objs().size() )
1470 		{
1471 		//	ChunkShape cs = tmpshp->shape_data;
1472 			copy_to_mainshapelist(h,tmpshp,flags);
1473 		}
1474 
1475 	}
1476 	local_scale=temp_scale;
1477 
1478 	if(!(flags & CCF_DONT_INITIALISE_TEXTURES))
1479 	{
1480 		//currently on the occasions this flag is used , the textures are shared with the level rif.
1481 		//therefore only clear the fast files if the flag is not set.
1482 		ffclose_almost_all();
1483 	}
1484 	/*-----------------------------**
1485 	** set up hierarchy related stuff **
1486 	**-----------------------------*/
1487 
1488 
1489 	Set_Progress_Bar_Position((int)(progress_start+progress_interval*.5));
1490 	//get the distances at which the various detail levels should be used
1491 	int* distance_array=0;
1492 	Hierarchy_Degradation_Distance_Chunk* hddc=(Hierarchy_Degradation_Distance_Chunk*)h->fc->lookup_single_child("HIDEGDIS");
1493 	if(hddc)
1494 	{
1495 		GLOBALASSERT(hddc->num_detail_levels==10);
1496 		distance_array=hddc->distance_array;
1497 	}
1498 
1499 	//sort out the arrays of low detail shapes
1500 	SHAPEHEADER* low_detail_array[10];
1501 	for(LIF<Object_ShapeNum_Pair *> osnp_lif(&osnp_list);!osnp_lif.done();osnp_lif.next())
1502 	{
1503 		if(!low_osnp_list.size()) break;
1504 
1505 		for(i=0;i<10;i++)
1506 		{
1507 			low_detail_array[i]=0;
1508 		}
1509 		int num_detail_level=0;
1510 
1511 		Object_ShapeNum_Pair* osnp=osnp_lif();
1512 		//find all the low detail shapes for this shape;
1513 		for(LIF<Object_ShapeNum_Pair *> low_osnp_lif(&low_osnp_list);!low_osnp_lif.done();)
1514 		{
1515 			Object_ShapeNum_Pair* low_osnp=low_osnp_lif();
1516 			if(!strcmp(&low_osnp->ob->object_data.o_name[3],osnp->ob->object_data.o_name))
1517 			{
1518 				low_osnp_lif.delete_current();
1519 				int detail=low_osnp->ob->object_data.o_name[1]-'0';
1520 				if(detail>=1 && detail <=9)
1521 				{
1522 					low_detail_array[detail]=mainshapelist[low_osnp->sh_num];
1523 					num_detail_level++;
1524 				}
1525 				delete low_osnp;
1526 			}
1527 			else
1528 			{
1529 				low_osnp_lif.next();
1530 			}
1531 
1532 		}
1533 
1534 		if(num_detail_level)//we have some lower detail shapes
1535 		{
1536 			SHAPEHEADER* main_shape=mainshapelist[osnp->sh_num];
1537 			low_detail_array[0]=main_shape; //detail level 0 is the original shape
1538 			num_detail_level++;
1539 
1540 			main_shape->shape_degradation_array=(ADAPTIVE_DEGRADATION_DESC*)PoolAllocateMem(sizeof(ADAPTIVE_DEGRADATION_DESC)*num_detail_level);
1541 
1542 			ADAPTIVE_DEGRADATION_DESC* deg_ptr=main_shape->shape_degradation_array;
1543 			for(i=9;i>=0;i--) //shapes are entered in ascending order of detail.
1544 			{
1545 				if(low_detail_array[i])
1546 				{
1547 					if(distance_array)
1548 						deg_ptr->distance=distance_array[i];
1549 					else
1550 						deg_ptr->distance=i*10000;
1551 					deg_ptr->shape=low_detail_array[i];
1552 
1553 					if (i!=9)
1554 					{
1555 						deg_ptr->shapeCanBeUsedCloseUp = 1;
1556 					}
1557 					else
1558 					{
1559 						deg_ptr->shapeCanBeUsedCloseUp = 0;
1560 					}
1561 					deg_ptr++;
1562 				}
1563 			}
1564 
1565 
1566 		}
1567 
1568 	}
1569 	//at this point low_osnp_list ought to be empty , but delete the rest anyway
1570 	while(low_osnp_list.size())
1571 	{
1572 		delete low_osnp_list.first_entry();
1573 		low_osnp_list.delete_first_entry();
1574 	}
1575 
1576 
1577 	List <Chunk *> cl;
1578 	h->fc->lookup_child ("OBJCHIER",cl);
1579 
1580 	GLOBALASSERT (cl.size());
1581 
1582 	Global_Hierarchy_Store * ghs = new Global_Hierarchy_Store (h);
1583 
1584 	int NumHierToLoad=cl.size();
1585 	int NumHierLoaded=0;
1586 
1587 	for (LIF<Chunk *> cli (&cl); !cli.done(); cli.next())
1588 	{
1589 		Set_Progress_Bar_Position((int)(progress_start+progress_interval*(.7+(.2*NumHierLoaded)/NumHierToLoad)));
1590 		NumHierLoaded++;
1591 
1592 		Object_Hierarchy_Chunk * ohc = (Object_Hierarchy_Chunk *)cli();
1593 
1594 		ghs->add_hierarchy (osnp_list, ohc);
1595 	}
1596 
1597 	ghs->setup_alternate_shape_sets(osnp_list,h->fc);
1598 
1599 
1600 	while (osnp_list.size())
1601 	{
1602 		delete osnp_list.first_entry();
1603 		osnp_list.delete_first_entry();
1604 	}
1605 
1606 	Global_Hierarchy_Library.add_entry(ghs);
1607 
1608 	Set_Progress_Bar_Position((int)(progress_start+progress_interval*.9));
1609 
1610 	//reset the sound directory
1611 	Rif_Sound_Directory=0;
1612 
1613 	return(1);
1614 
1615 
1616 }
1617 
1618 ///////////////////////////////////////////////////////////////////////////////
1619 // Library management functions
1620 
1621 extern "C"
1622 {
1623 
1624 SECTION * GetNamedHierarchyFromLibrary(const char * rif_name, const char * hier_name);
1625 
GetHierarchyFromLibrary(const char * rif_name)1626 SECTION * GetHierarchyFromLibrary(const char * rif_name)
1627 {
1628 	return (GetNamedHierarchyFromLibrary(rif_name, "Template"));
1629 }
1630 
GetNamedHierarchyFromLibrary(const char * rif_name,const char * hier_name)1631 SECTION * GetNamedHierarchyFromLibrary(const char * rif_name, const char * hier_name)
1632 {
1633 	for (LIF<Global_Hierarchy_Store *> ghli(&Global_Hierarchy_Library); !ghli.done(); ghli.next())
1634 	{
1635 		if (!_stricmp (ghli()->riffname, rif_name))
1636 		{
1637 			for (LIF<Hierarchy_Descriptor *> hdi (&ghli()->hierarchy_list); !hdi.done(); hdi.next())
1638 			{
1639 				if (!strcmp (hdi()->hierarchy_name, hier_name))
1640 				{
1641 					return(hdi()->hierarchy_root);
1642 				}
1643 			}
1644 
1645 		}
1646 	}
1647 	return(0);
1648 }
1649 
GetHierarchyAlternateShapeSetFromLibrary(const char * rif_name,const char * shape_set_name)1650 HIERARCHY_SHAPE_REPLACEMENT* GetHierarchyAlternateShapeSetFromLibrary(const char* rif_name,const char* shape_set_name)
1651 {
1652 	for (LIF<Global_Hierarchy_Store *> ghli(&Global_Hierarchy_Library); !ghli.done(); ghli.next())
1653 	{
1654 		if (!_stricmp (ghli()->riffname, rif_name))
1655 		{
1656 			for(LIF<Hierarchy_Alternate_Shape_Set*> hlif(&ghli()->alternate_shape_set_list);!hlif.done();hlif.next())
1657 			{
1658 				if(!_stricmp(hlif()->shape_set_name,shape_set_name))
1659 				{
1660 					return hlif()->replaced_shapes;
1661 				}
1662 			}
1663 			return 0;
1664 		}
1665 	}
1666 	return(0);
1667 }
GetHierarchyAlternateShapeSetCollectionFromLibrary(const char * rif_name,int collection_index)1668 HIERARCHY_VARIANT_DATA* GetHierarchyAlternateShapeSetCollectionFromLibrary(const char* rif_name,int collection_index)
1669 {
1670 	for (LIF<Global_Hierarchy_Store *> ghli(&Global_Hierarchy_Library); !ghli.done(); ghli.next())
1671 	{
1672 
1673 		if (!_stricmp (ghli()->riffname, rif_name))
1674 		{
1675 			//found the appropriate hierarchy library
1676 			Global_Hierarchy_Store * hier=ghli();
1677 
1678 			if(hier->num_shape_collections==0) return 0;
1679 
1680 			if(collection_index<=0)
1681 			{
1682 				if(hier->random_shape_colls.size()==0) return 0;
1683 
1684 				//pick a collection at random.
1685 				int random=FastRandom() % hier->random_shape_colls.size();
1686 				collection_index=hier->random_shape_colls[random];
1687 			}
1688 
1689 			collection_index%=hier->num_shape_collections;
1690 			GLOBALASSERT(hier->shape_collections);
1691 			return &hier->shape_collections[collection_index];
1692 		}
1693 	}
1694 	return(0);
1695 }
1696 
GetHierarchyAlternateShapeFromId(const char * rif_name,int replacement_id,char * section_name)1697 HIERARCHY_SHAPE_REPLACEMENT* GetHierarchyAlternateShapeFromId(const char* rif_name,int replacement_id,char* section_name)
1698 {
1699 	int collection_index = replacement_id;
1700 	if(collection_index == 0 ) return NULL;
1701 
1702 	for (LIF<Global_Hierarchy_Store *> ghli(&Global_Hierarchy_Library); !ghli.done(); ghli.next())
1703 	{
1704 
1705 		if (!_stricmp (ghli()->riffname, rif_name))
1706 		{
1707 			//found the appropriate hierarchy library
1708 			Global_Hierarchy_Store * hier=ghli();
1709 
1710 			if(collection_index<0 || collection_index>=hier->num_shape_collections) return NULL;
1711 
1712 			HIERARCHY_VARIANT_DATA* variant = &hier->shape_collections[collection_index];
1713 			HIERARCHY_SHAPE_REPLACEMENT* replacement =(HIERARCHY_SHAPE_REPLACEMENT*) variant->replacements;
1714 			HIERARCHY_SHAPE_REPLACEMENT* returnval = NULL;
1715 
1716 			/*
1717 			Search through the list of replacements for the desired shape.
1718 			We need to find the last replacement for a given shape. (One shape may be replaced twice)
1719 			*/
1720 
1721 			while(replacement->replaced_section_name)
1722 			{
1723 				if(!strcmp(replacement->replaced_section_name,section_name))
1724 				{
1725 					//found a replacement for this shape
1726 					returnval = replacement;
1727 				}
1728 				replacement++;
1729 			}
1730 
1731 			return returnval;
1732 		}
1733 	}
1734 	return(0);
1735 }
1736 
1737 
EmptyHierarchyLibrary()1738 void EmptyHierarchyLibrary ()
1739 {
1740 	while (Global_Hierarchy_Library.size())
1741 	{
1742 		delete Global_Hierarchy_Library.first_entry();
1743 		Global_Hierarchy_Library.delete_first_entry();
1744 	}
1745 }
1746 
DeleteHierarchyLibraryEntry(RIFFHANDLE h)1747 void DeleteHierarchyLibraryEntry(RIFFHANDLE h)
1748 {
1749 	for (LIF<Global_Hierarchy_Store *> ghli(&Global_Hierarchy_Library); !ghli.done(); ghli.next())
1750 	{
1751 		if(ghli()->rif_hand==h)
1752 		{
1753 			delete ghli();
1754 			ghli.delete_current();
1755 			break;
1756 		}
1757 	}
1758 }
1759 
1760 
1761 };
1762 ///////////////////////////////////////////////////////////////////////////////
1763 
1764 
1765 extern void SetupFragmentType(Fragment_Type_Chunk* ftc);
1766 
1767 struct Adjacent_AIModule_EP
1768 {
1769 	VECTORCH entry_point;
1770 	int aimodule_index;
1771 	unsigned int alien_only :1;
1772 };
1773 
1774 // copies all shapes and objects etc
copy_rif_data(RIFFHANDLE h,int flags,int progress_start,int progress_interval)1775 BOOL copy_rif_data (RIFFHANDLE h, int flags,int progress_start,int progress_interval)
1776 {
1777 	/*close all fastfiles so we don't end up with too many open at once*/
1778 	if(!(flags & CCF_DONT_INITIALISE_TEXTURES))
1779 	{
1780 		//currently on the occasions this flag is used , the textures are shared with the level rif.
1781 		//therefore only clear the fast files if the flag is not set.
1782 		ffclose_almost_all();
1783 	}
1784 
1785 	#if 0 //disable the multiple image group stuff
1786 	if (!(flags & CCF_IMAGEGROUPSET))
1787 	{
1788 		GLOBALASSERT(flags & CCF_ENVIRONMENT); //image group should be set for everything else
1789 		#ifdef MaxImageGroups
1790 		#if MaxImageGroups > 2
1791 		SetCurrentImageGroup(flags & CCF_ENVIRONMENT ? 2 : 0);
1792 		#else
1793 		if (flags & CCF_ENVIRONMENT)
1794 			GLOBALASSERT(0=="Requires MaxImageGroups to be > 2 (system.h)");
1795 		#endif
1796 		#else
1797 		if (flags & CCF_ENVIRONMENT)
1798 			GLOBALASSERT(0=="Requires MaxImageGroups to be defined > 2 (system.h)");
1799 		#endif
1800 	}
1801 	#endif
1802 
1803 	if (INVALID_RIFFHANDLE == h || !h->fc) return(FALSE);
1804 
1805 	if (flags & CCF_LOAD_AS_HIERARCHY_IF_EXISTS)
1806 	{
1807 		if (h->fc->count_children("OBJCHIER"))
1808 			return(copy_rif_data_as_hierarchy (h,flags,progress_start,progress_interval));
1809 	}
1810 
1811  //////////////////////////
1812  // Sort out local scale //
1813  //////////////////////////
1814 
1815 	set_local_scale(h,flags);
1816 
1817 	/*find this rif's sound directory*/
1818 	Rif_Sound_Directory=0;
1819 	Sound_Directory_Chunk* dir_chunk=(Sound_Directory_Chunk*)h->envd->lookup_single_child("SOUNDDIR");
1820 	if(dir_chunk)
1821 	{
1822 		Rif_Sound_Directory=dir_chunk->directory;
1823 	}
1824 
1825 /*---------------**
1826 ** Load Textures **
1827 **---------------*/
1828 
1829 	//SelectGenTexDirectory(ITI_TEXTURE);
1830 
1831 	#if 0 //disable the multiple image group stuff
1832 	if(!(flags & CCF_DONT_INITIALISE_TEXTURES))
1833 	{
1834 		InitialiseTextures();
1835 	}
1836 	#endif
1837 
1838 	if (flags & CCF_ENVIRONMENT)
1839 	{
1840 		load_rif_bitmaps(h,flags);
1841 
1842 		// Load in the palette, tlt, and set up lookup table for coloured polys
1843 
1844 		PaletteMapTable = 0;
1845 
1846 		if (h->envd)
1847 		{
1848 			set_quantization_event (h,flags);
1849 
1850 			copy_rif_palette (h,flags);
1851 
1852 			copy_rif_tlt (h,flags);
1853 
1854 			get_rif_palette_remap_table (h,flags);
1855 
1856 		}
1857 
1858 		/*find the default sound settings */
1859 		float env_reverb=-1;
1860 		int env_sound_type=0;
1861 		Environment_Acoustics_Chunk* env_ac=(Environment_Acoustics_Chunk*)h->envd->lookup_single_child("ENVACOUS");
1862 		if(env_ac)
1863 		{
1864 			if(env_ac->reverb<=1) env_reverb=env_ac->reverb;
1865 			env_sound_type=env_ac->env_index;
1866 		}
1867 
1868 
1869 	/*-------------------------------------**
1870 	** Load in shapes to the mainshapelist **
1871 	**-------------------------------------*/
1872 
1873 	/*-----------------------------------**
1874 	** Set up arrays of modules          **
1875 	**                                   **
1876 	** There should be two arrays,       **
1877 	** one array of modules and a        **
1878 	** pointer to an array of modules    **
1879 	**-----------------------------------*/
1880 
1881 
1882 		//count the modules
1883 		int num_modules=0;
1884 		{
1885 			List<Object_Chunk*> object_list;
1886 			h->fc->list_objects(&object_list);
1887 			for(LIF<Object_Chunk*> oblif(&object_list);!oblif.done();oblif.next())
1888 			{
1889 				if(!(oblif()->get_header()->flags & OBJECT_FLAG_PLACED_OBJECT))
1890 				{
1891 					num_modules++;
1892 				}
1893 			}
1894 
1895 		}
1896 		// One module per object at the moment
1897 
1898 		MainScene.sm_module = (MODULE *) PoolAllocateMem (sizeof(MODULE) * (num_modules + 3));
1899 		if (!MainScene.sm_module)
1900 		{
1901 			memoryInitialisationFailure = 1;
1902 			return FALSE;
1903 		}
1904 
1905 		MainScene.sm_marray = (MODULE **) PoolAllocateMem (sizeof(MODULE) * (num_modules + 3));
1906 		if (!MainScene.sm_marray)
1907 		{
1908 			memoryInitialisationFailure = 1;
1909 			return FALSE;
1910 		}
1911 
1912 		// putting an infinite module at the beginning - followed by a term
1913 		// by cheating
1914 
1915 		MODULE * sm_module_start = MainScene.sm_module;
1916 		MODULE ** sm_marray_start = MainScene.sm_marray;
1917 
1918 		MainScene.sm_module += 2;
1919 		MainScene.sm_marray += 1;
1920 
1921 		int i;
1922 		for (i=0; i<num_modules; i++)
1923 		{
1924 			MainScene.sm_module[i] = Empty_Module;
1925 			MainScene.sm_marray[i] = &MainScene.sm_module[i];
1926 
1927 			MainScene.sm_module[i].m_sound_reverb=env_reverb;
1928 			MainScene.sm_module[i].m_sound_env_index=env_sound_type;
1929 
1930 		}
1931 
1932 		MainScene.sm_module[i] = Term_Module;
1933 
1934 		AIModuleArraySize=0;
1935 
1936 		// we'll set the rest up later !!!
1937 
1938 	/*-------------------------------------**
1939 	** Load in shapes to the mainshapelist **
1940 	**-------------------------------------*/
1941 		o_chunk_array = new Object_Chunk * [num_modules];
1942 		aimodule_indeces=new int[num_modules];
1943 
1944 		int mod_pos = 0;
1945 
1946 
1947 		List<Shape_Chunk*> shape_list;
1948 		List<Object_Chunk*> object_list;
1949 		h->fc->list_shapes(&shape_list);
1950 
1951 		int NumShapesToLoad=shape_list.size(); //for progress_bar
1952 		int NumShapesLoaded=0;
1953 
1954 		for(LIF<Shape_Chunk*> shplif(&shape_list);!shplif.done();shplif.next())
1955 		{
1956 
1957 			if((NumShapesLoaded & 0xf)==0)
1958 			{
1959 				//update bar every 16 objects
1960 				Set_Progress_Bar_Position((int)(progress_start+progress_interval*((.6*NumShapesLoaded)/NumShapesToLoad)));
1961 			}
1962 
1963 			NumShapesLoaded++;
1964 
1965 			object_list=shplif()->list_assoc_objs();
1966 			if(object_list.size())
1967 			{
1968 				if(shplif()->get_header()->flags & SHAPE_FLAG_EXTERNALFILE)
1969 				{
1970 					//only create one copy of the shape for imported objects
1971 
1972 					#if SupportMorphing && LOAD_MORPH_SHAPES
1973 					db_logf3(("Copying shape to shape list"));
1974 					CTM_ReturnType rt_temp = copy_to_mainshapelist(h,shplif(),flags,0);
1975 					int start_shape_no = rt_temp.start_list_pos;
1976 					int list_pos = rt_temp.main_list_pos;
1977 					db_logf3(("Shape copied to %d",list_pos));
1978 					#else
1979 					int list_pos = copy_to_mainshapelist(h,shplif(),flags,&ob->object_data);
1980 					int start_shape_no = list_pos;
1981 					#endif
1982 
1983 					int AnimationShape=-1;
1984 					if (shplif()->lookup_single_child("TEXTANIM"))
1985 					{
1986 						AnimationShape=list_pos;
1987 					}
1988 
1989 					for(LIF<Object_Chunk*> oblif(&object_list);!oblif.done();oblif.next())
1990 					{
1991 						Object_Chunk* ob=oblif();
1992 						if (ob->get_header()->flags & OBJECT_FLAG_PLACED_OBJECT)
1993 						{
1994 							deal_with_placed_object(ob, start_shape_no, AnimationShape);
1995 						}
1996 						else
1997 						{
1998 							GLOBALASSERT(0=="Shouldn't be any modules using imported shapes");
1999 						}
2000 					}
2001 
2002 				}
2003 				else
2004 				{
2005 					//create one shape per object
2006 					for(LIF<Object_Chunk*> oblif(&object_list);!oblif.done();oblif.next())
2007 					{
2008 						Object_Chunk* ob=oblif();
2009 						#if SupportMorphing && LOAD_MORPH_SHAPES
2010 						db_logf3(("Copying shape for object %s",ob->object_data.o_name));
2011 						CTM_ReturnType rt_temp = copy_to_mainshapelist(h,shplif(),flags,&ob->object_data);
2012 						int start_shape_no = rt_temp.start_list_pos;
2013 						int list_pos = rt_temp.main_list_pos;
2014 						db_logf3(("Shape copied to %d",list_pos));
2015 						MORPHCTRL * mc = rt_temp.mc;
2016 						#else
2017 						int list_pos = copy_to_mainshapelist(h,shplif(),flags,&ob->object_data);
2018 						int start_shape_no = list_pos;
2019 						#endif
2020 
2021 						//see if object has prelighting data
2022 						Shape_Vertex_Intensities_Chunk * svic = 0;
2023 
2024 						List<Chunk *> cl;
2025 						ob->lookup_child ("SHPVTINT",cl);
2026 
2027 						for (LIF<Chunk *> svici(&cl); !svici.done(); svici.next())
2028 						{
2029 							Shape_Vertex_Intensities_Chunk * temp_svic = (Shape_Vertex_Intensities_Chunk *) svici();
2030 							if (!strncmp(temp_svic->light_set_name, ::light_set_name, 8))
2031 							{
2032 								svic = temp_svic;
2033 								break;
2034 							}
2035 
2036 						}
2037 
2038 						if (svic)
2039 						{
2040 							//this object has prelighting , so set up extra item data
2041 							mainshapelist[list_pos]->sh_extraitemdata = (EXTRAITEMDATA *)PoolAllocateMem(12 * svic->num_vertices);
2042 							if (!mainshapelist[list_pos]->sh_extraitemdata)
2043 							{
2044 								memoryInitialisationFailure = 1;
2045 								return FALSE;
2046 							}
2047 
2048 							for (int vn = 0; vn < svic->num_vertices; vn++)
2049 							{
2050 								//convert coloured light to a brightness value
2051 								int ir=svic->intensity_array[vn]>>16;
2052 							 	int ig=svic->intensity_array[vn]>>8 &0xff;
2053 							 	int ib=svic->intensity_array[vn] &0xff;
2054 							 	int mag =(int)sqrt((ir*ir+ig*ig+ib*ib)/3.0);
2055 
2056 							 	mainshapelist[list_pos]->sh_extraitemdata[vn].EID_VertexI = svic->intensity_array[vn] + (mag<<24);
2057 
2058 							}
2059 
2060 							mainshapelist[list_pos]->shapeflags |= ShapeFlag_PreLit;
2061 
2062 						}
2063 						#if 1
2064 						int AnimationShape=-1;
2065 						if (shplif()->lookup_single_child("TEXTANIM"))
2066 						{
2067 							AnimationShape=list_pos;
2068 						}
2069 						#endif
2070 
2071 						if (ob->get_header()->flags & OBJECT_FLAG_PLACED_OBJECT)
2072 						{
2073 
2074 							deal_with_placed_object(ob, start_shape_no, AnimationShape);
2075 						}
2076 						else
2077 						{
2078 
2079 							copy_to_module (ob, mod_pos, start_shape_no);
2080 
2081 							int shape2 = -1;
2082 							if (mc)
2083 							{
2084 								if(mc->ObMorphHeader)
2085 								{
2086 									if(mc->ObMorphHeader->mph_frames)
2087 									{
2088 										shape2 = mc->ObMorphHeader->mph_frames[0].mf_shape2;
2089 										DeallocateMem (mc->ObMorphHeader->mph_frames);
2090 									}
2091 									DeallocateMem(mc->ObMorphHeader);
2092 								}
2093 								DeallocateMem (mc);
2094 								mc = 0;
2095 							}
2096 							deal_with_module_object (ob, start_shape_no, AnimationShape, shape2, &MainScene.sm_module[mod_pos]);
2097 
2098 						   	Object_Module_Data_Chunk* omdc=(Object_Module_Data_Chunk*)ob->lookup_single_child("MODULEDT");
2099 						   	if(omdc)
2100 							{
2101 						   		if(!omdc->lookup_single_child("AIMODSLA"))
2102 						   			AIModuleArraySize++;
2103 							}
2104 							else
2105 			   					AIModuleArraySize++;
2106 							o_chunk_array[mod_pos] = ob; //for finding object_chunk from module
2107 							ob->program_object_index=mod_pos; //for finding module from object_chunk
2108 							aimodule_indeces[mod_pos]=-1;
2109 							mod_pos ++;
2110 						}
2111 					}
2112 				}
2113 			}
2114 			else
2115 			{
2116 				//shape has no objects , load it , but don't scale it
2117 				double temp_scale=local_scale;
2118 				local_scale=GlobalScale;
2119 
2120 				copy_to_mainshapelist(h,shplif(),flags);
2121 
2122 				local_scale=temp_scale;
2123 			}
2124 		}
2125 		GLOBALASSERT(num_modules==mod_pos);
2126 	/*--------------**
2127 	** Module Stuff **
2128 	**--------------*/
2129 
2130 		if (flags & CCF_ENVIRONMENT)
2131 		{
2132 			Set_Progress_Bar_Position((int)(progress_start+progress_interval*.6));
2133 		}
2134 		MainScene.sm_module[mod_pos] = Term_Module;
2135 		MainScene.sm_marray[mod_pos] = 0;
2136 
2137 		AIModuleArraySize++;
2138 		AIModuleArray=(AIMODULE*)PoolAllocateMem(sizeof(AIMODULE)*AIModuleArraySize);
2139 
2140 		AIModuleArray[0].m_link_ptrs=0;
2141 		AIModuleArray[0].m_module_ptrs=0;
2142 		AIModuleArray[0].m_waypoints=0;
2143 		AIModuleArray[0].m_index=0;
2144 
2145 
2146 		List<Adjacent_AIModule_EP*>* entry_points=new List<Adjacent_AIModule_EP*>[AIModuleArraySize];
2147 
2148 		int ai_mod_pos=1;
2149 
2150 		//setup aimodules and the aimodule conversion array
2151 		for(i=0;i<mod_pos;i++)
2152 		{
2153 	   		Object_Module_Data_Chunk * omdc =(Object_Module_Data_Chunk*) o_chunk_array[i]->lookup_single_child("MODULEDT");
2154 			AI_Module_Master_Chunk* ammc=0;
2155 			if(omdc)
2156 			{
2157 				if(omdc->lookup_single_child("AIMODSLA"))continue;
2158 				ammc=(AI_Module_Master_Chunk*)omdc->lookup_single_child("AIMODMAS");
2159 
2160 			}
2161 
2162 			AIMODULE* aim=&AIModuleArray[ai_mod_pos];
2163 			aim->m_index=ai_mod_pos;
2164 			aim->m_world=o_chunk_array[i]->object_data.location*local_scale;
2165 
2166 			aim->m_link_ptrs=0;
2167 			if(ammc)
2168 			{
2169 				aim->m_module_ptrs=(MODULE**)PoolAllocateMem(sizeof(MODULE*)*(2+ammc->ModuleList.size()));
2170 				aim->m_module_ptrs[0]=&MainScene.sm_module[i];
2171 				MainScene.sm_module[i].m_aimodule=aim;
2172 				aimodule_indeces[i]=ai_mod_pos;
2173 
2174 				int pos=1;
2175 				for(LIF<Object_Chunk*> modlif(&ammc->ModuleList);!modlif.done();modlif.next())
2176 				{
2177 				  	for(int obj=0;obj<mod_pos;obj++)
2178 				  	{
2179 						if(o_chunk_array[obj]==modlif())
2180 						{
2181 							aim->m_module_ptrs[pos++]=&MainScene.sm_module[obj];
2182 							MainScene.sm_module[obj].m_aimodule=aim;
2183 							aimodule_indeces[obj]=ai_mod_pos;
2184 							break;
2185 						}
2186 
2187 					}
2188 
2189 				}
2190 				aim->m_module_ptrs[pos++]=0;
2191 			}
2192 			else
2193 			{
2194 				aim->m_module_ptrs=(MODULE**)PoolAllocateMem(2*sizeof(MODULE*));
2195 
2196 				aim->m_module_ptrs[0]=&MainScene.sm_module[i];
2197 				MainScene.sm_module[i].m_aimodule=aim;
2198 				aimodule_indeces[i]=ai_mod_pos;
2199 
2200 				aim->m_module_ptrs[1]=0;
2201 			}
2202 
2203 			ai_mod_pos++;
2204 		}
2205 
2206 		FALLP_EntryPoints = (FARENTRYPOINTSHEADER *)AllocateMem(AIModuleArraySize*sizeof(FARENTRYPOINTSHEADER));
2207 		if(!FALLP_EntryPoints)
2208 		{
2209 			memoryInitialisationFailure = 1;
2210 			return FALSE;
2211 		}
2212 		for(i=0;i<AIModuleArraySize;i++)
2213 		{
2214 			FALLP_EntryPoints[i].entryPointsList=0;
2215 			FALLP_EntryPoints[i].numEntryPoints=0;
2216 		}
2217 
2218 		if (flags & CCF_ENVIRONMENT)
2219 		{
2220 			Set_Progress_Bar_Position((int)(progress_start+progress_interval*.7));
2221 		}
2222 
2223 		for (i=0; i<mod_pos; i++)
2224 		{
2225 
2226 			Object_Module_Data_Chunk * omdc = 0;
2227 			Adjacent_Module_Entry_Points_Chunk * amc = 0;
2228 			VModule_Array_Chunk * vmac = 0;
2229 			Module_Flag_Chunk * mfc=0;
2230 			Module_Waypoint_Chunk* mwc=0;
2231 
2232 			//fill in module position and extents
2233 			{
2234 				MODULE* mod=&MainScene.sm_module[i];
2235 				Object_Chunk* oc=o_chunk_array[i];
2236 				Shape_Chunk* sc=oc->get_assoc_shape();
2237 
2238 				mod->m_world=oc->object_data.location*local_scale;
2239 
2240 				//extents calculated in this way so that if there are no gaps in the extents when stored as doubles ,
2241 				//there shouldn't be any gaps after they have been converted to ints.
2242 				VECTORCH world_min=(oc->object_data.location+sc->shape_data.min)*local_scale;
2243 				VECTORCH world_max=(oc->object_data.location+sc->shape_data.max)*local_scale;
2244 
2245 				mod->m_maxx=world_max.vx-mod->m_world.vx;
2246 				mod->m_maxy=world_max.vy-mod->m_world.vy;
2247 				mod->m_maxz=world_max.vz-mod->m_world.vz;
2248 
2249 				mod->m_minx=world_min.vx-mod->m_world.vx;
2250 				mod->m_miny=world_min.vy-mod->m_world.vy;
2251 				mod->m_minz=world_min.vz-mod->m_world.vz;
2252 			}
2253 
2254 			Chunk * pChunk = o_chunk_array[i]->lookup_single_child ("MODULEDT");
2255 			if (pChunk)
2256 			{
2257 				omdc = (Object_Module_Data_Chunk *) pChunk;
2258 			}
2259 
2260 			if (omdc)
2261 			{
2262 				pChunk = omdc->lookup_single_child("VMDARRAY");
2263 
2264 				if (pChunk)
2265 				{
2266 					vmac = (VModule_Array_Chunk *) pChunk;
2267 				}
2268 
2269 
2270 				amc=(Adjacent_Module_Entry_Points_Chunk*) omdc->lookup_single_child("ADJMDLEP");
2271 
2272 				if(omdc->lookup_single_child("ADJMDLST"))
2273 				{
2274 					GLOBALASSERT(0=="Please load this file into module adjacency so that entry points can be calculated.");
2275 				}
2276 
2277 				pChunk = omdc->lookup_single_child("MODFLAGS");
2278 				if(pChunk)
2279 				{
2280 					mfc = (Module_Flag_Chunk*)pChunk;
2281 				}
2282 
2283 				pChunk = omdc->lookup_single_child("WAYPOINT");
2284 				if(pChunk)
2285 				{
2286 					mwc = (Module_Waypoint_Chunk*)pChunk;
2287 				}
2288 
2289 				/*see if this module has its own sound settings*/
2290 				Module_Acoustics_Chunk* mod_ac=(Module_Acoustics_Chunk*)omdc->lookup_single_child("MODACOUS");
2291 				if(mod_ac)
2292 				{
2293 					if(mod_ac->env_index>=0)
2294 					{
2295 						MainScene.sm_module[i].m_sound_env_index=mod_ac->env_index;
2296 					}
2297 					if(mod_ac->reverb>=0)
2298 					{
2299 						if(mod_ac->reverb>1)
2300 							MainScene.sm_module[i].m_sound_reverb=-1;//reverb depends on distance (I think)
2301 						else
2302 							MainScene.sm_module[i].m_sound_reverb=mod_ac->reverb;
2303 					}
2304 				}
2305 
2306 			}
2307 
2308 			//Deal with module linking
2309 			if (vmac)
2310 			{
2311 				if(KeepMainRifFile)
2312 				{
2313 					//use standard memory allocation , since this may need to be deallocated when updating module linking
2314 					MainScene.sm_module[i].m_vmptr = (VMODULE *)AllocateMem(sizeof(VMODULE) * (vmac->num_array_items+1));
2315 				}
2316 				else
2317 				{
2318 					MainScene.sm_module[i].m_vmptr = (VMODULE *)PoolAllocateMem(sizeof(VMODULE) * (vmac->num_array_items+1));
2319 				}
2320 				if (!MainScene.sm_module[i].m_vmptr)
2321 				{
2322 					memoryInitialisationFailure = 1;
2323 					return FALSE;
2324 				}
2325 
2326 				int vmac_no = 0;
2327 				int vmod_no = 0;
2328 				while (vmac_no < vmac->num_array_items)
2329 				{
2330 					Object_Chunk* linked_module=h->fc->get_object_by_index(vmac->vmod_array[vmac_no].object_index);
2331 
2332 					if (linked_module && linked_module->program_object_index!=-1)
2333 					{
2334 
2335 						MainScene.sm_module[i].m_vmptr[vmod_no].vmod_type = vmtype_vmodule;
2336 						*((int *)MainScene.sm_module[i].m_vmptr[vmod_no].vmod_name) = vmac_no;
2337 						if (vmac->vmod_array[vmac_no].branch_no)
2338 						{
2339 							MainScene.sm_module[i].m_vmptr[vmod_no].vmod_instr = vmodi_bra_vc;
2340 
2341 							#if (StandardStrategyAndCollisions || IntermediateSSACM)
2342 							MainScene.sm_module[j].m_mapptr->MapStrategy = StrategyI_DoorPROX;
2343 							#endif //(StandardStrategyAndCollisions || IntermediateSSACM)
2344 						}
2345 						else
2346 						{
2347 							MainScene.sm_module[i].m_vmptr[vmod_no].vmod_instr = vmodi_null;
2348 						}
2349 
2350 						MainScene.sm_module[i].m_vmptr[vmod_no].vmod_data.vmodidata = vmac->vmod_array[vmac_no].branch_no;
2351 
2352 						MainScene.sm_module[i].m_vmptr[vmod_no].vmod_mref.mref_ptr = &MainScene.sm_module[linked_module->program_object_index];
2353 						MainScene.sm_module[i].m_vmptr[vmod_no].vmod_dir.vx = 0;
2354 						MainScene.sm_module[i].m_vmptr[vmod_no].vmod_dir.vy = 0;
2355 						MainScene.sm_module[i].m_vmptr[vmod_no].vmod_dir.vz = 0;
2356 
2357 						MainScene.sm_module[i].m_vmptr[vmod_no].vmod_angle = 0;
2358 		   				MainScene.sm_module[i].m_vmptr[vmod_no].vmod_flags = vmac->vmod_array[vmac_no].flags;
2359 						vmod_no ++;
2360 					}
2361 
2362 					vmac_no ++;
2363 
2364 				}
2365 				MainScene.sm_module[i].m_vmptr[vmod_no].vmod_type = vmtype_term;
2366 				*((int *)MainScene.sm_module[i].m_vmptr[vmod_no].vmod_name) = vmac_no;
2367 			}
2368 			else
2369 			{
2370 				MainScene.sm_module[i].m_vmptr = (VMODULE *)PoolAllocateMem(sizeof(VMODULE) * (2));
2371 				if (!MainScene.sm_module[i].m_vmptr)
2372 				{
2373 					memoryInitialisationFailure = 1;
2374 					return FALSE;
2375 				}
2376 
2377 				MainScene.sm_module[i].m_vmptr[0].vmod_type = vmtype_vmodule;
2378 				*((int *)MainScene.sm_module[i].m_vmptr[0].vmod_name) = 0;
2379 				MainScene.sm_module[i].m_vmptr[0].vmod_instr = vmodi_null;
2380 				MainScene.sm_module[i].m_vmptr[0].vmod_data.vmodidata = 0;
2381 
2382 				MainScene.sm_module[i].m_vmptr[0].vmod_mref.mref_ptr = &MainScene.sm_module[i];
2383 				MainScene.sm_module[i].m_vmptr[0].vmod_dir.vx = 0;
2384 				MainScene.sm_module[i].m_vmptr[0].vmod_dir.vy = 0;
2385 				MainScene.sm_module[i].m_vmptr[0].vmod_dir.vz = 0;
2386 
2387 				MainScene.sm_module[i].m_vmptr[0].vmod_angle = 0;
2388 		   		MainScene.sm_module[i].m_vmptr[0].vmod_flags = 0;
2389 
2390 				MainScene.sm_module[i].m_vmptr[1].vmod_type = vmtype_term;
2391 				*((int *)MainScene.sm_module[i].m_vmptr[1].vmod_name) = 1;
2392 			}
2393 			MainScene.sm_module[i].m_link_ptrs=0;
2394 
2395 			if(mfc)
2396 			{
2397 				MainScene.sm_module[i].m_flags|=mfc->Flags;
2398 			}
2399 
2400 			AI_Module_Master_Chunk* ammc=0;
2401 			if(omdc)
2402 			{
2403 				if(omdc->lookup_single_child("AIMODSLA"))continue;
2404 				ammc=(AI_Module_Master_Chunk*)omdc->lookup_single_child("AIMODMAS");
2405 			}
2406 
2407 			int this_ai_module_index=aimodule_indeces[i];
2408 			AIMODULE* aim=&AIModuleArray[this_ai_module_index];
2409 
2410 
2411 			//build list of adjacent ai_modules
2412 			List<int> adjacent_aimodule_list;
2413 
2414 			if (amc)
2415 			{
2416 
2417 				for (LIF<Adjacent_Module> ami(&amc->adjacent_modules_list); !ami.done(); ami.next())
2418 				{
2419 					Object_Chunk* adjacent_module=h->fc->get_object_by_index(ami().object_index);
2420 
2421 					if (adjacent_module && adjacent_module->program_object_index!=-1)
2422 					{
2423 						int adj_ai_module=aimodule_indeces[adjacent_module->program_object_index];
2424 						if(adj_ai_module!=this_ai_module_index)
2425 						{
2426 							//make sure not already in list
2427 							LIF<int> adjlif(&adjacent_aimodule_list);
2428 							for(; !adjlif.done();adjlif.next())
2429 							{
2430 								if(adjlif()==adj_ai_module) break;
2431 							}
2432 							if(adjlif.done())
2433 							{
2434 								if(ami().flags & AdjacentModuleFlag_InsideAdjacentModule)
2435 								{
2436 									continue;
2437 								}
2438 								if(ami().flags & AdjacentModuleFlag_AdjacentModuleInsideMe)
2439 								{
2440 									continue;
2441 
2442 								}
2443 								Adjacent_AIModule_EP* ad_aim=new Adjacent_AIModule_EP;
2444 								ad_aim->entry_point=ami().entry_point*local_scale;
2445 								ad_aim->aimodule_index=this_ai_module_index;
2446 								ad_aim->alien_only=(ami().flags & AdjacentModuleFlag_Vertical)!=0;
2447 
2448 								entry_points[adj_ai_module].add_entry(ad_aim);
2449 								adjacent_aimodule_list.add_entry(adj_ai_module);
2450 
2451 							}
2452 
2453 						}
2454 					}
2455 
2456 				}
2457 
2458 
2459 			}
2460 
2461 			if(ammc)
2462 			{
2463 				for(LIF<Object_Chunk*> oblif(&ammc->ModuleList);!oblif.done();oblif.next())
2464 				{
2465 					Object_Module_Data_Chunk* omdc2=(Object_Module_Data_Chunk*)oblif()->lookup_single_child("MODULEDT");
2466 					if(!omdc2)continue;
2467 					amc=(Adjacent_Module_Entry_Points_Chunk*)omdc2->lookup_single_child("ADJMDLEP");
2468 					if(amc)
2469 					{
2470 						for (LIF<Adjacent_Module> ami(&amc->adjacent_modules_list); !ami.done(); ami.next())
2471 						{
2472 							Object_Chunk* adjacent_module=h->fc->get_object_by_index(ami().object_index);
2473 
2474 							if (adjacent_module && adjacent_module->program_object_index!=-1)
2475 							{
2476 								int adj_ai_module=aimodule_indeces[adjacent_module->program_object_index];
2477 								if(adj_ai_module!=this_ai_module_index)
2478 								{
2479 									//make sure not already in list
2480 									LIF<int> adjlif(&adjacent_aimodule_list);
2481 									for(; !adjlif.done();adjlif.next())
2482 									{
2483 										if(adjlif()==adj_ai_module) break;
2484 									}
2485 									if(adjlif.done())
2486 									{
2487 										if(ami().flags & AdjacentModuleFlag_InsideAdjacentModule)
2488 										{
2489 											continue;
2490 										}
2491 										if(ami().flags & AdjacentModuleFlag_AdjacentModuleInsideMe)
2492 										{
2493 											continue;
2494 
2495 										}
2496 
2497 										Adjacent_AIModule_EP* ad_aim=new Adjacent_AIModule_EP;
2498 										ad_aim->entry_point=(ami().entry_point)*local_scale;
2499 										ad_aim->aimodule_index=this_ai_module_index;
2500 										ad_aim->alien_only=(ami().flags & AdjacentModuleFlag_Vertical)!=0;
2501 
2502 										entry_points[adj_ai_module].add_entry(ad_aim);
2503 										adjacent_aimodule_list.add_entry(adj_ai_module);
2504 									}
2505 
2506 								}
2507 							}
2508 
2509 						}
2510 					}
2511 				}
2512 			}
2513 
2514 			//setup adjacent modules
2515 			int adj_pos=0;
2516 			aim->m_link_ptrs=(AIMODULE**)PoolAllocateMem(sizeof(AIMODULE*)*(1+adjacent_aimodule_list.size()));
2517 			if(adjacent_aimodule_list.size())
2518 			{
2519 
2520 				while(adjacent_aimodule_list.size())
2521 				{
2522 					aim->m_link_ptrs[adj_pos]=&AIModuleArray[adjacent_aimodule_list.first_entry()];
2523 					adj_pos++;
2524 					adjacent_aimodule_list.delete_first_entry();
2525 
2526 				}
2527 			}
2528 			aim->m_link_ptrs[adj_pos]=0;
2529 
2530 
2531 
2532 
2533 			//Deal with waypoints
2534 			if(mwc && mwc->NumAlienWaypoints)
2535 			{
2536 				WAYPOINT_HEADER* wh=(WAYPOINT_HEADER*)PoolAllocateMem(sizeof(WAYPOINT_HEADER));
2537 				aim->m_waypoints=wh;
2538 			   	MainScene.sm_module[i].m_waypoints=wh;//temporary
2539 
2540 				wh->num_waypoints=mwc->NumAlienWaypoints;
2541 
2542 				wh->first_waypoint=(WAYPOINT_VOLUME*)PoolAllocateMem(sizeof(WAYPOINT_VOLUME)*wh->num_waypoints);
2543 				for(int j=0;j<wh->num_waypoints;j++)
2544 				{
2545 					WAYPOINT_VOLUME* wv=&wh->first_waypoint[j];
2546 					ChunkWaypoint* cw=&mwc->AlienWaypoints[j];
2547 
2548 					VECTORCH ObCentre=o_chunk_array[i]->object_data.location*local_scale;
2549 					wv->centre=cw->centre*local_scale;
2550 					wv->min_extents=cw->min*local_scale;
2551 					SubVector(&wv->centre,&wv->min_extents);
2552 					wv->max_extents=cw->max*local_scale;
2553 					SubVector(&wv->centre,&wv->max_extents);
2554 					wv->max_extents.vx--;
2555 					wv->max_extents.vy--;
2556 					wv->max_extents.vz--;
2557 					SubVector(&ObCentre,&wv->centre);
2558 					wv->flags=cw->flags;
2559 					wv->num_links=cw->NumWPLinks;
2560 					if(wv->num_links)
2561 						wv->first_link=(WAYPOINT_LINK*)PoolAllocateMem(sizeof(WAYPOINT_LINK)*wv->num_links);
2562 					else
2563 						wv->first_link=0;
2564 					for(int k=0;k<wv->num_links;k++)
2565 					{
2566 						wv->first_link[k].link_flags=cw->WayLinks[k].flags;
2567 						wv->first_link[k].link_target_index=cw->WayLinks[k].index;
2568 					}
2569 					wv->workspace=0;
2570 					wv->weighting=5;
2571 				}
2572 
2573 			}
2574 			else
2575 			{
2576 				aim->m_waypoints=0;
2577 			}
2578 
2579 
2580 		}
2581 
2582 		if (flags & CCF_ENVIRONMENT)
2583 		{
2584 			Set_Progress_Bar_Position((int)(progress_start+progress_interval*.8));
2585 		}
2586 		//setup entry points
2587 		for(i=0;i<AIModuleArraySize;i++)
2588 		{
2589 			int num_ep=entry_points[i].size();
2590 			if(num_ep)
2591 			{
2592 				FALLP_EntryPoints[i].entryPointsList=(FARENTRYPOINT*)AllocateMem(sizeof(FARENTRYPOINT)*num_ep);
2593 				FALLP_EntryPoints[i].numEntryPoints=num_ep;
2594 
2595 				int adj_pos=0;
2596 				while(entry_points[i].size())
2597 				{
2598 					Adjacent_AIModule_EP* ad_aim=entry_points[i].first_entry();
2599 
2600 					FALLP_EntryPoints[i].entryPointsList[adj_pos].position=ad_aim->entry_point;
2601 					SubVector(&AIModuleArray[i].m_world,&FALLP_EntryPoints[i].entryPointsList[adj_pos].position);
2602 					FALLP_EntryPoints[i].entryPointsList[adj_pos].donorIndex=ad_aim->aimodule_index;
2603 					FALLP_EntryPoints[i].entryPointsList[adj_pos].alien_only=ad_aim->alien_only;
2604 
2605 					#if 0
2606 					//test
2607 					{
2608 						VECTORCH loc=FALLP_EntryPoints[i].entryPointsList[adj_pos].position;
2609 
2610 						MODULE* mod=AIModuleArray[i].m_module_ptrs[0];
2611 						SHAPEHEADER* shp=mainshapelist[mod->m_mapptr->MapShape];
2612 
2613 						if(loc.vx< shp->shapeminx||
2614 						   loc.vy< shp->shapeminy||
2615 						   loc.vz< shp->shapeminz||
2616 						   loc.vx> shp->shapemaxx||
2617 						   loc.vy> shp->shapemaxy||
2618 						   loc.vz> shp->shapemaxz)
2619 						{
2620 							GLOBALASSERT(0=="The entry points probably need to be recalculated");
2621 						}
2622 					}
2623 					#endif
2624 					adj_pos++;
2625 					entry_points[i].delete_first_entry();
2626 					delete ad_aim;
2627 				}
2628 			}
2629 		}
2630 		delete [] entry_points;
2631 
2632 
2633 		// putting an infinite module at the beginning - followed by a term
2634 		// and setting the arrays back to point at them !!
2635 
2636 		MainScene.sm_module = sm_module_start;
2637 		MainScene.sm_marray = sm_marray_start;
2638 
2639 		MainScene.sm_module[0] = Empty_Module;
2640 		MainScene.sm_module[0].m_flags |= m_flag_infinite;
2641 		MainScene.sm_module[0].m_vptr.mref_ptr = &MainScene.sm_module[2];
2642 		*((int *)MainScene.sm_module[0].m_name) = 1;
2643 		MainScene.sm_module[0].m_vmptr = (VMODULE *)PoolAllocateMem(sizeof(VMODULE) * (mod_pos+1));
2644 		if (!MainScene.sm_module[0].m_vmptr)
2645 		{
2646 			memoryInitialisationFailure = 1;
2647 			return FALSE;
2648 		}
2649 
2650 		for (i=0; i<mod_pos; i++)
2651 		{
2652 			MainScene.sm_module[0].m_vmptr[i].vmod_type = vmtype_vmodule;
2653 			*((int *)MainScene.sm_module[0].m_vmptr[i].vmod_name) = i + 1000;
2654 			MainScene.sm_module[0].m_vmptr[i].vmod_instr = vmodi_null;
2655 			MainScene.sm_module[0].m_vmptr[i].vmod_data.vmodidata = 0;
2656 			MainScene.sm_module[0].m_vmptr[i].vmod_mref.mref_ptr = &MainScene.sm_module[i+2];
2657 			MainScene.sm_module[0].m_vmptr[i].vmod_dir.vx = 0;
2658 			MainScene.sm_module[0].m_vmptr[i].vmod_dir.vy = 0;
2659 			MainScene.sm_module[0].m_vmptr[i].vmod_dir.vz = 0;
2660 			MainScene.sm_module[0].m_vmptr[i].vmod_angle = 0;
2661 			MainScene.sm_module[0].m_vmptr[i].vmod_flags = 0;
2662 
2663 		  //	MainScene.sm_module[i]->m_flags|=m_flag_gotptrs;
2664 		}
2665 
2666 		MainScene.sm_module[0].m_vmptr[i].vmod_type = vmtype_term;
2667 		*((int *)MainScene.sm_module[0].m_vmptr[i].vmod_name) = i + 1000;
2668 
2669 		MainScene.sm_marray[0] = &MainScene.sm_module[0];
2670 
2671 
2672 		MainScene.sm_module[1] = Term_Module;
2673 		*((int *)MainScene.sm_module[1].m_name) = 2;
2674 
2675 		setup_start_position(h);
2676 
2677 		//setup ai paths
2678 		setup_paths(h);
2679 
2680 		setup_placed_hierarchies(h->envd);
2681 
2682 
2683 		//alien power cables
2684 		setup_cables(h->envd);
2685 
2686 		//particle generators
2687 		setup_particle_generators(h->envd);
2688 
2689 		// External lifts / airlocks
2690 		DealWithExternalObjectStategies (h->envd);
2691 
2692 		setup_sounds (h->envd);
2693 
2694 		setup_preplaced_decals(h->fc,h->envd);
2695 
2696 	//	create_strategies_from_list(); //now called later
2697 
2698 		//set sky colour , and other envionmental properties
2699 		set_environment_properties(h->envd);
2700 
2701 
2702 
2703 		Set_Progress_Bar_Position((int)(progress_start+progress_interval*.9));
2704 	}
2705 	else
2706 	{
2707 		//not the environment rif , so just load shapes without objects
2708 		//don't want these to be scaled with the level
2709 		double temp_scale=local_scale;
2710 		local_scale=GlobalScale;
2711 
2712 		List<Chunk *> shps;
2713 		h->fc->lookup_child ("REBSHAPE",shps);
2714 
2715 		for (LIF<Chunk *> shplst(&shps) ; !shplst.done() ; shplst.next())
2716 		{
2717 
2718  			Shape_Chunk * tmpshp = (Shape_Chunk *)shplst();
2719 
2720 			if ( ! tmpshp->list_assoc_objs().size() )
2721 			{
2722 		  //		ChunkShape cs = tmpshp->shape_data;
2723 				copy_to_mainshapelist(h,tmpshp,flags);
2724 			}
2725 
2726 		}
2727 		local_scale=temp_scale;
2728 	}
2729 
2730 /*--------------**
2731 ** Load sprites **
2732 **--------------*/
2733 	//SelectGenTexDirectory(ITI_SPRITE);
2734 
2735 	Chunk * pChunk = h->fc->lookup_single_child ("RSPRITES");
2736 	if (pChunk)
2737 	{
2738 		List<Chunk *> sprs;
2739 		((Chunk_With_Children *)pChunk)->lookup_child("SPRIHEAD",sprs);
2740 		for (LIF<Chunk *> sprlst(&sprs) ; !sprlst.done() ; sprlst.next())
2741 		{
2742 			Sprite_Header_Chunk* shc=(Sprite_Header_Chunk*)sprlst();
2743 
2744 			RIF_Name_Chunk * rnc = 0;
2745 
2746 			pChunk = shc->lookup_single_child("RIFFNAME");
2747 			if (pChunk)
2748 			{
2749 				rnc = (RIF_Name_Chunk *) pChunk;
2750 			}
2751 			else
2752 			{
2753 				GLOBALASSERT(0=="RIF name not found in sprite");
2754 			}
2755 
2756 
2757 			copy_sprite_to_mainshapelist(h,shc,flags);
2758 		}
2759 
2760 	}
2761 
2762 	//setup shape fragments;
2763 	{
2764 		List<Chunk*> chlist;
2765 		h->envd->lookup_child("FRAGTYPE",chlist);
2766 		for(LIF<Chunk*> chlif(&chlist);!chlif.done();chlif.next())
2767 		{
2768 			SetupFragmentType((Fragment_Type_Chunk*)chlif());
2769 		}
2770 	}
2771 
2772 	if (flags & CCF_ENVIRONMENT)
2773 	{
2774 		SetUpRunTimeLights();
2775 		// setup_generators ,and load hierarchies
2776 		//take copy of scale since it is changed by InitNPCs
2777 		setup_generators (h->envd);
2778 
2779 		delete[] o_chunk_array;
2780 		delete[] aimodule_indeces;
2781 
2782 		//find the marine/civvie types that can be randomly generated
2783 		List<Chunk*> rlist;
2784 		h->envd->lookup_child("RANTEXID",rlist);
2785 		for(LIF<Chunk*> rlif(&rlist);!rlif.done();rlif.next())
2786 		{
2787 			Random_Texture_ID_Chunk* ran_chunk=(Random_Texture_ID_Chunk*)rlif();
2788 			if(!_stricmp(ran_chunk->name,"hnpcmarine"))
2789 			{
2790 				random_marine_texturings=ran_chunk->random_types;
2791 			}
2792 			else if(!_stricmp(ran_chunk->name,"hnpc_civvie"))
2793 			{
2794 				random_civilian_texturings=ran_chunk->random_types;
2795 			}
2796 		}
2797 
2798 		double env_scale=local_scale;
2799 		InitNPCs(h);
2800 		local_scale=env_scale;
2801 
2802 		while (random_marine_texturings.size())random_marine_texturings.delete_first_entry();
2803 		while (random_civilian_texturings.size())random_civilian_texturings.delete_first_entry();
2804 	}
2805 
2806 	//reset sound diretory pointer
2807 	Rif_Sound_Directory=0;
2808 
2809 	return TRUE;
2810 }
2811 
2812 // hook to load a bitmap - so you can load them from test directories, etc. should return tex index
load_rif_bitmap(char const * fname,BMPN_Flags flags)2813 int load_rif_bitmap (char const * fname, BMPN_Flags flags)
2814 {
2815 	return CL_LoadImageOnce
2816 		(
2817 			fname,
2818 			(ScanDrawDirectDraw == ScanDrawMode ? LIO_CHIMAGE : LIO_D3DTEXTURE)
2819 			|(flags & ChunkBMPFlag_IFF ? LIO_RELATIVEPATH : LIO_RIFFPATH)
2820 			|(flags & ChunkBMPFlag_UsesTransparency ? LIO_TRANSPARENT : LIO_NONTRANSP)
2821 			|(flags & (cl_pszGameMode ?
2822 				ChunkBMPFlag_RequireGameMipMaps
2823 				: ChunkBMPFlag_RequireToolsMipMaps)
2824 				? LIO_LOADMIPMAPS : LIO_NOMIPMAPS)
2825 			|LIO_RESTORABLE
2826 		);
2827 }
2828 
2829 ////////////////////////////////////////////////////////////////////////
2830 // Functions which do not operate on RIFFHANDLEs and may become obsolete
2831 ////////////////////////////////////////////////////////////////////////
2832 
2833 // these functions work on the current rif; they only remain for historical reasons
2834 // copies all shapes and objects etc
copy_chunks_from_environment(int flags)2835 BOOL copy_chunks_from_environment(int flags)
2836 {
2837 	return copy_rif_data(current_rif_handle,flags,0,0);
2838 }
2839 
2840 /////////////////////////////////////////////
2841 // Functions for handling the main shape list
2842 /////////////////////////////////////////////
2843 
2844 static SHAPEHEADER null_shape; // static to ensure it is initialized to 0s
2845 
2846 #define FREE_SHAPE (&null_shape)
2847 
2848 int start_of_loaded_shapes;
2849 static int msl_term_pos;
2850 static int first_free_pos = GLS_NOTINLIST;
2851 
2852 // reserves the next avaialbe position in the main shape list and returns it
GetMSLPos(void)2853 int GetMSLPos(void)
2854 {
2855 	int pos;
2856 
2857 	if (GLS_NOTINLIST == first_free_pos)
2858 		first_free_pos = msl_term_pos = start_of_loaded_shapes = load_precompiled_shapes();
2859 
2860 	for (pos = first_free_pos; pos < msl_term_pos && FREE_SHAPE != mainshapelist[pos]; ++pos)
2861 		;
2862 
2863 	first_free_pos = pos+1;
2864 	if (pos >= msl_term_pos)
2865 	{
2866 		msl_term_pos = first_free_pos;
2867 		if(msl_term_pos>=maxshapes)
2868 		{
2869 			//alocate another 50 slots on the mainshapelist
2870 			mainshapelist=(SHAPEHEADER**)realloc(mainshapelist,sizeof(SHAPEHEADER*)*(maxshapes+50));
2871 			LOCALASSERT(mainshapelist);
2872 			if(!mainshapelist)
2873 			{
2874 	   			ReleaseDirect3D();
2875 				exit(0x74363);
2876 			}
2877 			for(int i=maxshapes;i<maxshapes+50;i++)
2878 			{
2879 				mainshapelist[i]=0;
2880 			}
2881 			maxshapes+=50;
2882 
2883 		}
2884 		mainshapelist[msl_term_pos]=0;
2885 	}
2886 
2887 	return pos;
2888 }
2889 
2890 // frees a position in the main shape list
FreeMSLPos(int pos)2891 void FreeMSLPos(int pos)
2892 {
2893 	mainshapelist[pos] = FREE_SHAPE;
2894 
2895 	if (first_free_pos > pos) first_free_pos = pos;
2896 
2897 	if (pos+1 == msl_term_pos)
2898 	{
2899 		while (msl_term_pos > 0 && FREE_SHAPE == mainshapelist[msl_term_pos-1])
2900 		{
2901 			mainshapelist[--msl_term_pos] = 0;
2902 		}
2903 	}
2904 }
2905 
2906 ////////////////////////////////////////////////
2907 // Functions retrieving data about loaded shapes
2908 ////////////////////////////////////////////////
2909 
2910 //////////////////////////////////////////////////////////////////////////////
2911 // Initializing, deallocating of shapes, mainly hooks for project specific fns
2912 //////////////////////////////////////////////////////////////////////////////
2913 
2914 // hook to perhaps scale the uv coordinates - should return new value
ProcessUVCoord(RIFFHANDLE,UVCOORDTYPE uvct,int uv_value,int)2915 int ProcessUVCoord(RIFFHANDLE,UVCOORDTYPE uvct,int uv_value,int /*image_num*/)
2916 {
2917 //	return (int)(uv_value*GetUVScale(UVC_SPRITE_U==uvct||UVC_SPRITE_V==uvct ? ITI_SPRITE : ITI_TEXTURE));
2918 	return uv_value;
2919 }
2920 
2921 
2922 // perform initial post processing on shape just after loading
2923 // note that the copy named shape functions will not call this
post_process_shape(SHAPEHEADER * shp)2924 void post_process_shape (SHAPEHEADER * shp)
2925 {
2926 	for (int i=0; i<shp->numitems; i++)
2927 	{
2928 		switch (shp->items[i][0])
2929 		{
2930 			case I_Polygon:
2931 				if (!(shp->items[i][2] & iflag_nolight))
2932 					shp->items[i][0] = I_GouraudPolygon;
2933 				break;
2934 			case I_3dTexturedPolygon:
2935 			case I_2dTexturedPolygon:
2936 			case I_Gouraud3dTexturedPolygon:
2937 			case I_Gouraud2dTexturedPolygon:
2938 				if (shp->shapeflags & ShapeFlag_Sprite)
2939 				{
2940 					shp->items[i][0] = I_2dTexturedPolygon;
2941 					shp->items[i][2] &= ~iflag_tx2dor3d;
2942 				}
2943 				else
2944 				{
2945 					shp->items[i][0] = I_Gouraud3dTexturedPolygon;
2946 					shp->items[i][2] |= iflag_tx2dor3d;
2947 				}
2948 		}
2949 		shp->items[i][2] |= iflag_gsort_ptest | iflag_linear_s;
2950 		//shp->items[i][2] &= ~iflag_transparent; // this causes _translucency_ on direct 3d
2951 		//shp->items[i][2] &= ~iflag_drawtx3das2d;
2952 
2953 		#if SupportZBuffering
2954 		if (ZBufferOn==ZBufferMode)
2955 		{
2956 			switch (shp->items[i][0])
2957 			{
2958 				case I_Polygon:
2959 					shp->items[i][0] = I_ZB_Polygon;
2960 					break;
2961 				case I_GouraudPolygon:
2962 					shp->items[i][0] = I_ZB_GouraudPolygon;
2963 					break;
2964 				case I_PhongPolygon:
2965 					shp->items[i][0] = I_ZB_PhongPolygon;
2966 					break;
2967 				case I_2dTexturedPolygon:
2968 					shp->items[i][0] = I_ZB_2dTexturedPolygon;
2969 					break;
2970 				case I_Gouraud2dTexturedPolygon:
2971 					shp->items[i][0] = I_ZB_Gouraud2dTexturedPolygon;
2972 					break;
2973 				case I_3dTexturedPolygon:
2974 					shp->items[i][0] = I_ZB_3dTexturedPolygon;
2975 					break;
2976 				case I_Gouraud3dTexturedPolygon:
2977 					shp->items[i][0] = I_ZB_Gouraud3dTexturedPolygon;
2978 					break;
2979 			}
2980 		}
2981 		#endif
2982 	}
2983 
2984 	shp->shapeflags |= ShapeFlag_AugZ | ShapeFlag_AugZ_Lite;
2985 }
2986 
2987 // your function could perform any extra tidying up you need
DeallocateLoadedShapeheader(SHAPEHEADER * shp)2988 void DeallocateLoadedShapeheader(SHAPEHEADER * shp)
2989 {
2990 	#if !NEW_DEALLOCATION_ORDER
2991 	DeallocateRifLoadedShapeheader(shp);
2992 	#endif
2993 }
2994 
2995 
DeallocateModules()2996 void DeallocateModules()
2997 {
2998 	#if !USE_LEVEL_MEMORY_POOL
2999 	MODULE ** m_arrayPtr = MainScene.sm_marray;
3000 
3001 	while (*m_arrayPtr)
3002 	{
3003 		List<Light_Chunk *> lights_for_this_module;
3004 
3005 		MODULE * this_mod = *m_arrayPtr++;
3006 
3007 		if(this_mod->m_mapptr) DeallocateMem(this_mod->m_mapptr);
3008 		this_mod->m_mapptr=0;
3009 		if(this_mod->name) DeallocateMem(this_mod->name);
3010 		this_mod->name=0;
3011 		if(this_mod->m_vmptr) DeallocateMem(this_mod->m_vmptr);
3012 		this_mod->m_vmptr=0;
3013 		if(this_mod->m_lightarray) DeallocateMem(this_mod->m_lightarray);
3014 		this_mod->m_lightarray=0;
3015 	}
3016 	if(MainScene.sm_module)DeallocateMem(MainScene.sm_module);
3017 	if(MainScene.sm_marray)DeallocateMem(MainScene.sm_marray);
3018 	#endif
3019 	MainScene.sm_module=0;
3020 	MainScene.sm_marray=0;
3021 
3022 
3023 	#if !USE_LEVEL_MEMORY_POOL
3024 	for(int i=0;i<AIModuleArraySize;i++)
3025 	{
3026 		AIMODULE* aim=&AIModuleArray[i];
3027 		if(aim->m_link_ptrs) DeallocateMem(aim->m_link_ptrs);
3028 		if(aim->m_module_ptrs) DeallocateMem(aim->m_module_ptrs);
3029 		if(aim->m_waypoints)
3030 		{
3031 			WAYPOINT_HEADER* wh=aim->m_waypoints;
3032 			for(int j=0;j<wh->num_waypoints;j++)
3033 			{
3034 				WAYPOINT_VOLUME* wv=&wh->first_waypoint[j];
3035 				if(wv->first_link)DeallocateMem(wv->first_link);
3036 			}
3037 			if(wh->first_waypoint)DeallocateMem(wh->first_waypoint);
3038 			DeallocateMem(wh);
3039   		}
3040 	}
3041 	DeallocateMem(AIModuleArray);
3042 	#endif
3043 	AIModuleArray=0;
3044 
3045 	//delete any paths
3046 	#if !USE_LEVEL_MEMORY_POOL
3047 	if(PathArray)
3048 	{
3049 		for(int i=0;i<PathArraySize;i++)
3050 		{
3051 			if(PathArray[i].modules_in_path)
3052 			{
3053 				DeallocateMem(PathArray[i].modules_in_path);
3054 			}
3055 		}
3056 		DeallocateMem(PathArray);
3057 	}
3058 	#endif
3059 
3060 	PathArray=0;
3061 	PathArraySize=0;
3062 
3063 	//may as well unload hierarchies for placed objects here as well
3064 	unload_placed_hierarchies();
3065 
3066 	//and get rid of the strategy lists
3067 	deallocate_behaviour_list();
3068 }
3069 
avp_undo_rif_load(RIFFHANDLE h)3070 void avp_undo_rif_load(RIFFHANDLE h)
3071 {
3072 	DeleteHierarchyLibraryEntry(h);
3073    	undo_rif_load(h);
3074 }
3075 
avp_load_rif(const char * fname)3076 RIFFHANDLE avp_load_rif (const char * fname)
3077 {
3078 	//see if there is a local copy of the rif file
3079 	FILE* rifFile = OpenGameFile(fname, FILEMODE_READONLY, FILETYPE_PERM);
3080 
3081 /* TODO: Let's find a better method */
3082 	if (!rifFile && AvpCDPath)
3083 	{
3084 		//try and load rif file from cd instead
3085 		char RifName[200];
3086 		sprintf(RifName, "%s%s", AvpCDPath, fname);
3087 		return load_rif(RifName);
3088 
3089 	}
3090 	if (rifFile)
3091 		fclose(rifFile);
3092 	return load_rif(fname);
3093 }
3094 
avp_load_rif_non_env(const char * fname)3095 RIFFHANDLE avp_load_rif_non_env (const char * fname)
3096 {
3097 	//see if there is a local copy of the rif file
3098 	FILE* rifFile = OpenGameFile(fname, FILEMODE_READONLY, FILETYPE_PERM);
3099 
3100 /* TODO: Let's find a better method */
3101 	if (!rifFile && AvpCDPath)
3102 	{
3103 		//try and load rif file from cd instead
3104 		char RifName[200];
3105 		sprintf(RifName, "%s%s", AvpCDPath, fname);
3106 		return load_rif_non_env(RifName);
3107 
3108 	}
3109 	if (rifFile)
3110 		fclose(rifFile);
3111 
3112 	return load_rif_non_env(fname);
3113 }
3114 
3115 
3116 
3117 #if debug
3118 extern "C"{
3119  extern VIEWDESCRIPTORBLOCK *Global_VDB_Ptr;
3120 }
LoadModuleData()3121 void LoadModuleData()
3122 {
3123  	GLOBALASSERT(env_rif);
3124 
3125 /* TODO: dir separator */
3126  	HANDLE file = CreateFile ("avp_rifs/module.bbb", GENERIC_WRITE, 0, 0, CREATE_ALWAYS,
3127  					FILE_FLAG_RANDOM_ACCESS, 0);
3128 	unsigned long byteswritten;
3129 	WriteFile(file,&Global_VDB_Ptr->VDB_World,sizeof(VECTORCH),&byteswritten,0);
3130 	WriteFile(file,&Global_VDB_Ptr->VDB_Mat,sizeof(MATRIXCH),&byteswritten,0);
3131 
3132  	CloseHandle(file);
3133 
3134 /* TODO: dir separator */
3135  	file = CreateFile ("avp_rifs/module.aaa", GENERIC_READ, 0, 0, OPEN_EXISTING,
3136  					FILE_FLAG_RANDOM_ACCESS, 0);
3137 
3138 	if(file==INVALID_HANDLE_VALUE) return;
3139 
3140 	if(!env_rif->fc)
3141 	{
3142 	 	CloseHandle(file);
3143 		NewOnScreenMessage("MODULE UPDATING REQUIRES -KEEPRIF OPTION.");
3144 		return;
3145 	}
3146 
3147 	int file_size=GetFileSize(file,0);
3148 	GLOBALASSERT((file_size % 4)==0);
3149 	int pos=0;
3150 	unsigned long bytesread;
3151 	{
3152 		char name[60];
3153 		ReadFile(file,name,60,&bytesread,0);
3154 
3155 		int i=0;
3156 		char* name1=&name[0];
3157 		while(name[i])
3158 		{
3159 			if(name[i]=='\\' || name[i]==':' /* || name[i]=='/' */)
3160 			{
3161 				name1=&name[i+1];
3162 			}
3163 			i++;
3164 		}
3165 		i=0;
3166 		char* name2=&env_rif->fc->filename[0];
3167 		while(env_rif->fc->filename[i])
3168 		{
3169 			if(env_rif->fc->filename[i]=='\\' || env_rif->fc->filename[i]==':')
3170 			{
3171 				name2=&env_rif->fc->filename[i+1];
3172 			}
3173 			i++;
3174 		}
3175 
3176 		if(_stricmp(name1,name2))
3177 		{
3178 			CloseHandle(file);
3179 			DeleteFile("avp_rifs\\module.aaa");
3180 			return;
3181 		}
3182 
3183 	}
3184 	pos+=60;
3185 
3186 
3187 	while(pos<file_size)
3188 	{
3189 		int obj_index;
3190 		ReadFile(file,&obj_index,4,&bytesread,0);
3191 		pos+=4;
3192 
3193 		Object_Chunk* obj=env_rif->fc->get_object_by_index(obj_index);
3194 		GLOBALASSERT(obj);
3195 		GLOBALASSERT(obj->program_object_index!=-1);
3196 		MODULE* this_mod=&MainScene.sm_module[obj->program_object_index+2];
3197 
3198 		int numlinks;
3199 		ReadFile(file,&numlinks,4,&bytesread,0);
3200 		pos+=4;
3201 
3202 		if(!numlinks) continue;
3203 
3204 		if(this_mod->m_vmptr)
3205 			DeallocateMem(this_mod->m_vmptr);
3206 
3207 		this_mod->m_vmptr = (VMODULE *)AllocateMem(sizeof(VMODULE) * (numlinks+1));
3208 
3209 
3210 		int vmac_no = 0;
3211 		int vmod_no = 0;
3212 		while (vmac_no < numlinks)
3213 		{
3214 			int linked_index;
3215 			int branch_no;
3216 			ReadFile(file,&linked_index,4,&bytesread,0);
3217 			ReadFile(file,&branch_no,4,&bytesread,0);
3218 			pos+=8;
3219 
3220 			Object_Chunk* linked_module=env_rif->fc->get_object_by_index(linked_index);
3221 
3222 			GLOBALASSERT(linked_module);
3223 			if (linked_module && linked_module->program_object_index!=-1)
3224 			{
3225 
3226 				this_mod->m_vmptr[vmod_no].vmod_type = vmtype_vmodule;
3227 				*((int *)this_mod->m_vmptr[vmod_no].vmod_name) = vmac_no;
3228 				if (branch_no)
3229 				{
3230 					this_mod->m_vmptr[vmod_no].vmod_instr = vmodi_bra_vc;
3231 				}
3232 				else
3233 				{
3234 					this_mod->m_vmptr[vmod_no].vmod_instr = vmodi_null;
3235 				}
3236 
3237 				this_mod->m_vmptr[vmod_no].vmod_data.vmodidata = branch_no;
3238 
3239 
3240 				this_mod->m_vmptr[vmod_no].vmod_mref.mref_ptr = &MainScene.sm_module[linked_module->program_object_index+2];
3241 				this_mod->m_vmptr[vmod_no].vmod_dir.vx = 0;
3242 				this_mod->m_vmptr[vmod_no].vmod_dir.vy = 0;
3243 				this_mod->m_vmptr[vmod_no].vmod_dir.vz = 0;
3244 
3245 				this_mod->m_vmptr[vmod_no].vmod_angle = 0;
3246 		 		this_mod->m_vmptr[vmod_no].vmod_flags = 0;
3247 				vmod_no ++;
3248 			}
3249 
3250 			vmac_no ++;
3251 
3252 		}
3253 		for(int j=0;j<vmac_no;j++)
3254 		{
3255 			if(this_mod->m_vmptr[j].vmod_data.vmodidata)
3256 			{
3257 				int k;
3258 
3259 				for(k=j+1;k<vmod_no;k++)
3260 				{
3261 					if(*((int *)this_mod->m_vmptr[k].vmod_name)>=this_mod->m_vmptr[j].vmod_data.vmodidata)
3262 					{
3263 						this_mod->m_vmptr[j].vmod_data.vmodidata_ptr=&this_mod->m_vmptr[k];
3264 						break;
3265 					}
3266 				}
3267 				if(k==vmod_no)
3268 				{
3269 					this_mod->m_vmptr[j].vmod_data.vmodidata_ptr=&this_mod->m_vmptr[k];
3270 				}
3271 			}
3272 		}
3273 		this_mod->m_vmptr[vmod_no].vmod_type = vmtype_term;
3274 		*((int *)this_mod->m_vmptr[vmod_no].vmod_name) = vmac_no;
3275 	}
3276 
3277 	CloseHandle(file);
3278 	DeleteFile("avp_rifs\\module.aaa");
3279 }
3280 #endif
3281 
3282 
3283 
3284 
3285 
3286 
setup_preplaced_decals(File_Chunk * fc,Environment_Data_Chunk * edc)3287 void setup_preplaced_decals(File_Chunk* fc,Environment_Data_Chunk* edc)
3288 {
3289 	NumFixedDecals=0;
3290 	CurrentFixedDecalIndex=0;
3291 
3292 	GLOBALASSERT(edc);
3293 	GLOBALASSERT(fc);
3294 
3295 	Special_Objects_Chunk* soc=(Special_Objects_Chunk*) edc->lookup_single_child("SPECLOBJ");
3296 	if(!soc) return;
3297 
3298 	AVP_Decal_Chunk* decal_chunk=(AVP_Decal_Chunk*) soc->lookup_single_child("AVPDECAL");
3299 	if(!decal_chunk) return;
3300 
3301 	GLOBALASSERT(decal_chunk->decals);
3302 
3303 	NumFixedDecals=0;
3304 
3305 
3306 	for(int i=0;i<decal_chunk->num_decals;i++)
3307 	{
3308 		FIXED_DECAL* fd=&FixedDecalStorage[NumFixedDecals];
3309 		AVP_Decal * ad=&decal_chunk->decals[i];
3310 
3311 		//find the decal's module
3312 		Object_Chunk* module=fc->get_object_by_index(ad->object_index) ;
3313 		if(!module) continue; //module not found
3314 		if(module->program_object_index==-1) continue;
3315 
3316 		fd->DecalID=(DECAL_ID)ad->DecalID;
3317 		for(int j=0;j<4;j++)
3318 		{
3319 			fd->Vertices[j].vx=ad->Vertices[j].x;
3320 			fd->Vertices[j].vy=ad->Vertices[j].y;
3321 			fd->Vertices[j].vz=ad->Vertices[j].z;
3322 		}
3323 
3324 		fd->UOffset=ad->UOffset;
3325 		fd->ModuleIndex=module->program_object_index+2;
3326 
3327 		NumFixedDecals++;
3328 	}
3329 
3330 
3331 	CurrentFixedDecalIndex=NumFixedDecals;
3332 
3333 }
3334 
get_object_index_from_module_index(List<Object_Chunk * > & ob_list,int index)3335 int get_object_index_from_module_index(List<Object_Chunk*>& ob_list,int index)
3336 {
3337 	for(LIF<Object_Chunk*> ob_lif(&ob_list);!ob_lif.done();ob_lif.next())
3338 	{
3339 		if(ob_lif()->program_object_index==index)
3340 		{
3341 			return ob_lif()->object_data.index_num;
3342 		}
3343 	}
3344 	return -1;
3345 }
3346 
3347 
3348 static BOOL WarnedAboutDiskSpace=FALSE;
MakeBackupFile(File_Chunk * fc)3349 static void MakeBackupFile(File_Chunk* fc)
3350 {
3351 	unsigned long spc,bps,numclust,total;
3352 	if(GetDiskFreeSpace(0,&spc,&bps,&numclust,&total))
3353 	{
3354 		unsigned int freespace=spc*bps*numclust;
3355 		if(freespace<40000000)
3356 		{
3357 			if(!WarnedAboutDiskSpace)
3358 			{
3359 				WarnedAboutDiskSpace=TRUE;
3360 				NewOnScreenMessage("LESS THAN 40MB FREE DISC SPACE");
3361 				NewOnScreenMessage("NO BACKUP WILL BE MADE");
3362 			}
3363 			return;
3364 		}
3365 	}
3366 	WarnedAboutDiskSpace=FALSE;
3367 
3368 	CreateDirectory("avp_rifs\\Backup",0);
3369 	int length=strlen(fc->filename);
3370 	int pos=length;
3371 	while(pos>=0 && fc->filename[pos]!='\\')pos--;
3372 	char* filename=&fc->filename[pos+1];
3373 	length=strlen(filename)-4;
3374 
3375 	char* Name1=new char[length+30];
3376 	char* Name2=new char[length+30];
3377 	strncpy(Name1,"avp_rifs\\Backup\\",16);
3378 	strncpy(&Name1[16],filename,length);
3379 	length+=16;
3380 	strncpy(Name2,Name1,length);
3381 	strncpy(&Name1[length],"B0.rif",7);
3382 	strncpy(&Name2[length],"B1.rif",7);
3383 
3384 	DeleteFile(Name1);
3385 
3386 	for (int i=0;i<9;i++)
3387 	{
3388 		Name1[length+1]=i+'0';
3389 		Name2[length+1]=i+'1';
3390 		MoveFile(Name2,Name1);
3391 	}
3392 	Name2[length+1]='9';
3393 	CopyFile(fc->filename,Name2,FALSE);
3394 
3395 	delete [] Name1;
3396 	delete [] Name2;
3397 }
3398 extern "C"
3399 {
3400 
3401 
save_preplaced_decals()3402 void save_preplaced_decals()
3403 {
3404 
3405 	GLOBALASSERT(env_rif);
3406 	if(!env_rif->fc)
3407 	{
3408 		NewOnScreenMessage("CAN'T SAVE DECALS. USE -KEEPRIF");
3409 		return;
3410 	}
3411 
3412 	{
3413 
3414 		DWORD attributes = GetFileAttributes(env_rif->fc->filename);
3415 		if (0xffffffff!=attributes)
3416 		{
3417 			if (attributes & FILE_ATTRIBUTE_READONLY)
3418 			{
3419 				NewOnScreenMessage("CAN'T SAVE DECALS.");
3420 				NewOnScreenMessage("FILE IS READ ONLY");
3421 				return;
3422 			}
3423 		}
3424 	}
3425 	MakeBackupFile(env_rif->fc);
3426 
3427 	Environment_Data_Chunk* edc = env_rif->envd;
3428 	GLOBALASSERT(edc);
3429 
3430 	Special_Objects_Chunk* soc=(Special_Objects_Chunk*) edc->lookup_single_child("SPECLOBJ");
3431 	if(!soc) soc=new Special_Objects_Chunk(edc);
3432 
3433 	//delete the old decal chunk
3434 	delete soc->lookup_single_child("AVPDECAL");
3435 
3436 	if(NumFixedDecals)
3437 	{
3438 		List<Object_Chunk*> ob_list;
3439 		env_rif->fc->list_objects(&ob_list);
3440 
3441 
3442 		AVP_Decal_Chunk* decal_chunk=new AVP_Decal_Chunk(soc,NumFixedDecals);
3443 		for(int i=0;i<decal_chunk->num_decals;i++)
3444 		{
3445 			FIXED_DECAL* fd=&FixedDecalStorage[i];
3446 			AVP_Decal * ad=&decal_chunk->decals[i];
3447 
3448 			ad->DecalID=(int)fd->DecalID;
3449 			for(int j=0;j<4;j++)
3450 			{
3451 				ad->Vertices[j].x=fd->Vertices[j].vx;
3452 				ad->Vertices[j].y=fd->Vertices[j].vy;
3453 				ad->Vertices[j].z=fd->Vertices[j].vz;
3454 
3455 			}
3456 
3457 			ad->UOffset=fd->UOffset;
3458 
3459 			ad->object_index=get_object_index_from_module_index(ob_list,fd->ModuleIndex-2);
3460 		}
3461 
3462 	}
3463 
3464 	if(!env_rif->fc->update_file())
3465 	{
3466 		NewOnScreenMessage("ERROR SAVING DECALS!!!!!!");
3467 	}
3468 	else
3469 	{
3470 		NewOnScreenMessage("DECALS SAVED.");
3471 
3472 	}
3473 }
3474 
3475 
check_preplaced_decal_modules()3476 void check_preplaced_decal_modules()
3477 {
3478 /*-------------------------------------------------------------------------------**
3479 ** 	go through the list of decals and make sure their module indeces are correct **
3480 **-------------------------------------------------------------------------------*/
3481 
3482 	for(int index=0;index<NumFixedDecals;index++)
3483 	{
3484 		FIXED_DECAL* fd=&FixedDecalStorage[index];
3485 
3486 		MODULE* mod=MainScene.sm_marray[fd->ModuleIndex];
3487 		mod=ModuleFromPosition(&fd->Vertices[0],mod);
3488 
3489 		if(mod)
3490 		{
3491 			fd->ModuleIndex=mod->m_index;
3492 		}
3493 	}
3494 }
3495 
3496 };
3497 
3498 
3499 extern void DeallocateAllFragments();
3500 extern void LoseAllNonCommonSounds();
3501 extern void deallocate_behaviour_list();
3502 extern void PurgeMSLShapeList();
3503 
3504 extern "C"
3505 {
DeallocateSoundsAndPoolAllocatedMemory()3506 void DeallocateSoundsAndPoolAllocatedMemory()
3507 {
3508 	deallocate_behaviour_list();
3509 
3510 	ClearMemoryPool();
3511 
3512 	LoseAllNonCommonSounds();
3513 
3514 	DeallocateAllFragments();
3515 
3516 	DeallocateAllImages();
3517 
3518 	PurgeMSLShapeList();
3519 
3520 }
3521 };
3522