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