1 #define DB_LEVEL 1
2 
3 #include <stdlib.h>
4 
5 #include "list_tem.hpp"
6 #include "chnkload.hpp"
7 #include "stratdef.h"
8 #include "gamedef.h"
9 #include "bh_types.h"
10 #include "envchunk.hpp"
11 #include "obchunk.hpp"
12 #include "ltchunk.hpp"
13 #include "avpchunk.hpp"
14 #include "strachnk.hpp"
15 #include "sndchunk.hpp"
16 #include "pvisible.h"
17 #include "objsetup.hpp"
18 #include "hierplace.hpp"
19 
20 #include "bh_gener.h"
21 #include "bh_swdor.h"
22 #include "bh_ldoor.h"
23 #include "bh_plift.h"
24 #include "bh_pred.h"
25 #include "bh_fhug.h"
26 #include "bh_marin.h"
27 #include "bh_paq.h"
28 #include "bh_queen.h"
29 #include "bh_alien.h"
30 #include "bh_xeno.h"
31 #include "bh_binsw.h"
32 #include "bh_lnksw.h"
33 #include "bh_spcl.h"
34 #include "bh_agun.h"
35 #include "bh_lift.h"
36 #include "bh_ltfx.h"
37 #include "bh_snds.h"
38 #include "bh_mission.h"
39 #include "bh_track.h"
40 #include "bh_fan.h"
41 #include "bh_light.h"
42 #include "bh_plachier.h"
43 #include "bh_cable.h"
44 #include "bh_deathvol.h"
45 #include "bh_selfdest.h"
46 #include "bh_pargen.h"
47 #include "bh_videoscreen.h"
48 #include "missions.hpp"
49 #include "track.h"
50 #include "psndplat.h"
51 
52 #include "dxlog.h"
53 #include "mempool.h"
54 #include "db.h"
55 
56 #include "pldnet.h"
57 
58 extern "C" {
59 #include "3dc.h"
60 extern MAPSETVDB chnk_playcam_vdb;
61 extern int GlobalAmbience;
62 extern VIEWDESCRIPTORBLOCK *ActiveVDBList[];
63 extern VIEWDESCRIPTORBLOCK *Global_VDB_Ptr;
64 };
65 
66 static void get_marine_facing_point(VECTORCH& pos,EULER& euler,VECTORCH& facing_point);
67 
68 //if this number is non-negative , use this value for all random location dierolls
69 extern "C"
70 {
71 int QuantumObjectDieRollOveride=-1;
72 };
73 
74 struct BehaviourBlockData
75 {
76 	AVP_BEHAVIOUR_TYPE sb_type;
77 	ObjectID id;
78 	int shapeindex;
79 	void *bhdata;
80 	char* name;
81 
82 	unsigned int diff_easy :1;
83 	unsigned int diff_medium :1;
84 	unsigned int diff_hard :1;
85 
86 	//alternative locations for 'quantum objects'
87 	int num_locations;
88 	int location_group;
89 	VECTORCH* alt_vector;
90 	EULER* alt_euler;
91 };
92 
93 struct LocationGroupDieRoll
94 {
95 	int group;
96 	int roll;
97 };
98 
99 static List <BehaviourBlockData*> Behav_List;
100 static List <LocationGroupDieRoll*> DieRoll_List;
101 
102 const char * light_set_name = "NORMALLT";
103 
104 BOOL Xenoborg_Morph_Thingy = 0;
105 XENO_MORPH_ROOM_TOOLS_TEMPLATE xmrtt;
106 
107 
108 extern char* Rif_Sound_Directory;
109 
GetSoundForMainRif(const char * wav_name)110 LOADED_SOUND const * GetSoundForMainRif(const char* wav_name)
111 {
112 	static char filename[200];
113 	if(Rif_Sound_Directory)
114 	{
115 		sprintf(filename,"%s\\%s",Rif_Sound_Directory,wav_name);
116 		return GetSound(filename);
117 	}
118 	else
119 	{
120 		return GetSound(wav_name);
121 	}
122 
123 }
124 
setup_track_sound(Indexed_Sound_Chunk * s_chunk,TRACK_SOUND ** ts)125 void setup_track_sound(Indexed_Sound_Chunk* s_chunk,TRACK_SOUND** ts)
126 {
127 	*ts=0;
128 	if(!s_chunk) return;
129 
130 
131 	LOADED_SOUND const * ls=GetSoundForMainRif(s_chunk->wav_name);
132 	if(ls)
133 	{
134 		TRACK_SOUND* sound=(TRACK_SOUND*)PoolAllocateMem(sizeof(TRACK_SOUND));
135 
136 		sound->sound_loaded=ls;
137 		sound->inner_range=(unsigned)(s_chunk->inner_range*local_scale);
138 		sound->outer_range=(unsigned)(s_chunk->outer_range*local_scale);
139 		sound->pitch=s_chunk->pitch;
140 		sound->max_volume=s_chunk->max_volume;
141 		sound->activ_no=SOUND_NOACTIVEINDEX;
142 		sound->playing=0;
143 
144 		if(s_chunk->flags & IndexedSoundFlag_Loop)
145 			sound->loop=1;
146 		else
147 			sound->loop=0;
148 
149 		*ts=sound;
150 	}
151 }
152 
setup_track_sound(Object_Chunk * oc,TRACK_SOUND ** start_sound,TRACK_SOUND ** mid_sound,TRACK_SOUND ** end_sound)153 void setup_track_sound(Object_Chunk* oc,TRACK_SOUND** start_sound,TRACK_SOUND** mid_sound,TRACK_SOUND** end_sound)
154 {
155 	if(start_sound)*start_sound=0;
156 	if(mid_sound)*mid_sound=0;
157 	if(end_sound)*end_sound=0;
158 
159 	db_logf3(("Setting up track sound"));
160 
161 	List<Chunk*> chlist;
162 	oc->lookup_child("TRAKSOUN",chlist);
163 	for(LIF<Chunk*> chlif(&chlist);!chlif.done();chlif.next())
164 	{
165 		Object_Track_Sound_Chunk* otsc=(Object_Track_Sound_Chunk*)chlif();
166 		TRACK_SOUND** sound_ptr;
167 
168 		switch(otsc->index)
169 		{
170 			case 0:
171 				sound_ptr=mid_sound;
172 				break;
173 			case 1:
174 				sound_ptr=start_sound;
175 				break;
176 			case 2:
177 				sound_ptr=end_sound;
178 				break;
179 		}
180 		if(!sound_ptr) continue;
181 		if(*sound_ptr) continue;
182 
183 
184 		db_logf3(("Getting %s",otsc->wav_name));
185 		LOADED_SOUND const * ls=GetSoundForMainRif(otsc->wav_name);
186 		db_logf3(("Finished getting %s",otsc->wav_name));
187 		if(ls)
188 		{
189 
190 			TRACK_SOUND* sound=(TRACK_SOUND*)PoolAllocateMem(sizeof(TRACK_SOUND));
191 
192 			sound->sound_loaded=ls;
193 			sound->inner_range=(unsigned)(otsc->inner_range*local_scale);
194 			sound->outer_range=(unsigned)(otsc->outer_range*local_scale);
195 			sound->pitch=otsc->pitch;
196 			sound->max_volume=otsc->max_volume;
197 			sound->activ_no=SOUND_NOACTIVEINDEX;
198 			sound->playing=0;
199 
200 			if(otsc->flags & TrackSoundFlag_Loop)
201 				sound->loop=1;
202 			else
203 				sound->loop=0;
204 
205 			*sound_ptr=sound;
206 		}
207 
208 	}
209 }
210 
setup_track_controller(Object_Chunk * oc)211 TRACK_CONTROLLER* setup_track_controller(Object_Chunk* oc)
212 {
213 	Object_Track_Chunk2* otc=(Object_Track_Chunk2*)oc->lookup_single_child("OBJTRAK2");
214 	if(!otc) return 0;
215 
216 
217 
218 	TRACK_CONTROLLER* tc=(TRACK_CONTROLLER*)PoolAllocateMem(sizeof(TRACK_CONTROLLER));
219 
220 	tc->sbptr=0;
221 	tc->playing=0;
222 	tc->playing_start_sound=0;
223 	tc->reverse=0;
224 	tc->loop=0;
225 	tc->loop_backandforth=0;
226 	tc->no_rotation=1;
227 	tc->timer=otc->timer_start;
228 	tc->current_section=0;
229 	tc->use_speed_mult=0;
230 	tc->speed_mult=0;
231 
232 	GLOBALASSERT(otc->num_sections);
233 
234 	tc->num_sections=otc->num_sections;
235 
236 	tc->sections=(TRACK_SECTION_DATA*)PoolAllocateMem(sizeof(TRACK_SECTION_DATA)*otc->num_sections);
237 
238 	QUAT quat_start;
239 	quat_start.quatx=(int)-(otc->sections[0].quat_start.x*ONE_FIXED);
240 	quat_start.quaty=(int)-(otc->sections[0].quat_start.x*ONE_FIXED);
241 	quat_start.quatz=(int)-(otc->sections[0].quat_start.x*ONE_FIXED);
242 	quat_start.quatw=(int)(otc->sections[0].quat_start.x*ONE_FIXED);
243 
244 	for(int i=0;i<tc->num_sections;i++)
245 	{
246 		TRACK_SECTION_DATA* tsd=&tc->sections[i];
247 		ChunkTrackSection* cts=&otc->sections[i];
248 
249 		tsd->quat_start.quatx=(int)-(cts->quat_start.x*ONE_FIXED);
250 		tsd->quat_start.quaty=(int)-(cts->quat_start.y*ONE_FIXED);
251 		tsd->quat_start.quatz=(int)-(cts->quat_start.z*ONE_FIXED);
252 		tsd->quat_start.quatw=(int)(cts->quat_start.w*ONE_FIXED);
253 
254 		tsd->quat_end.quatx=(int)-(cts->quat_end.x*ONE_FIXED);
255 		tsd->quat_end.quaty=(int)-(cts->quat_end.y*ONE_FIXED);
256 		tsd->quat_end.quatz=(int)-(cts->quat_end.z*ONE_FIXED);
257 		tsd->quat_end.quatw=(int)(cts->quat_end.w*ONE_FIXED);
258 
259 		if(tsd->quat_start.quatx!=quat_start.quatx||
260 		   tsd->quat_start.quaty!=quat_start.quaty||
261 		   tsd->quat_start.quatz!=quat_start.quatz||
262 		   tsd->quat_start.quatw!=quat_start.quatw)
263 		{
264 			tc->no_rotation=0;
265 		}
266 		if(tsd->quat_end.quatx!=quat_start.quatx||
267 		   tsd->quat_end.quaty!=quat_start.quaty||
268 		   tsd->quat_end.quatz!=quat_start.quatz||
269 		   tsd->quat_end.quatw!=quat_start.quatw)
270 		{
271 			tc->no_rotation=0;
272 		}
273 
274 
275 
276 		tsd->pivot_start=cts->pivot_start*local_scale;
277 		tsd->pivot_travel=(cts->pivot_end-cts->pivot_start)*local_scale;
278 		tsd->object_offset=cts->object_offset*local_scale;
279 
280 		tsd->time_for_section=cts->time_for_section;
281 	}
282 
283    	if(otc->flags & TrackFlag_Loop)
284    		tc->loop=1;
285    	else if(otc->flags & TrackFlag_LoopBackAndForth)
286    		tc->loop_backandforth=1;
287 
288 
289 	if(otc->flags & TrackFlag_PlayingAtStart)
290 		tc->playing=1;
291 
292 
293 	setup_track_sound(oc,&tc->start_sound,&tc->sound,&tc->end_sound);
294 
295 	if(tc->sound)
296 	{
297 		tc->sound->playing=tc->playing;
298 	}
299 
300 	/* KJL 14:29:09 24/03/98 - addition for smooth tracks */
301 	if(otc->flags & TrackFlag_UseTrackSmoothing && tc->num_sections>=3)
302 		tc->use_smoothing = 1;
303 	else
304 		tc->use_smoothing = 0;
305 
306 	Preprocess_Track_Controller(tc);
307 
308 	//set the initial state entries
309 	tc->initial_state_timer=tc->timer;
310 	tc->initial_state_playing=tc->playing;
311 	tc->initial_state_reverse=tc->reverse;
312 
313 
314 	return tc;
315 
316 }
317 
get_location_group_die_roll(int group)318 static int get_location_group_die_roll(int group)
319 {
320 	//see if a vaule has already been rolled for this group
321 	for(LIF<LocationGroupDieRoll*> dlif(&DieRoll_List);!dlif.done();dlif.next())
322 	{
323 		if(dlif()->group==group)
324 		{
325 			//found the group , so return its roll
326 			return dlif()->roll;
327 		}
328 	}
329 	//need to roll a new value for this group
330 	LocationGroupDieRoll* loc_group=new LocationGroupDieRoll;
331 	loc_group->group=group;
332 	loc_group->roll=FastRandom() & 0xffff;
333 	DieRoll_List.add_entry(loc_group);
334 
335 	return loc_group->roll;
336 }
337 
clear_location_group_die_roll_list()338 static void clear_location_group_die_roll_list()
339 {
340 	while(DieRoll_List.size())
341 	{
342 		delete DieRoll_List.first_entry();
343 		DieRoll_List.delete_first_entry();
344 	}
345 }
346 
347 
348 
select_alternate_location(BehaviourBlockData * bbd)349 static void select_alternate_location(BehaviourBlockData* bbd)
350 {
351 	GLOBALASSERT (bbd);
352 	if(bbd->num_locations<2) return;
353 
354 	int dieroll=0;
355 	if(QuantumObjectDieRollOveride>=0)
356 	{
357 		dieroll=QuantumObjectDieRollOveride;
358 	}
359 	else
360 	{
361 		if(bbd->location_group)
362 		{
363 			dieroll=get_location_group_die_roll(bbd->location_group);
364 		}
365 		else
366 		{
367 			dieroll=FastRandom() & 0xffff;
368 		}
369 	}
370 
371 	dieroll=dieroll%bbd->num_locations;
372 
373 	VECTORCH* chosen_pos=&bbd->alt_vector[dieroll];
374 	EULER* chosen_euler=&bbd->alt_euler[dieroll];
375 
376 	switch(bbd->sb_type)
377 	{
378 		case I_BehaviourInanimateObject :
379 		{
380 			TOOLS_DATA_INANIMATEOBJECT* tdio=(TOOLS_DATA_INANIMATEOBJECT*) bbd->bhdata;
381 			tdio->position=*chosen_pos;
382 			tdio->orientation=*chosen_euler;
383 			break;
384 		}
385 
386 		case I_BehaviourVideoScreen :
387 		{
388 			TOOLS_DATA_VIDEO_SCREEN* tdvs=(TOOLS_DATA_VIDEO_SCREEN*) bbd->bhdata;
389 			tdvs->position=*chosen_pos;
390 			tdvs->orientation=*chosen_euler;
391 			break;
392 		}
393 
394 
395 		case I_BehaviourPlacedSound :
396 		{
397 			SOUND_TOOLS_TEMPLATE* stt=(SOUND_TOOLS_TEMPLATE*) bbd->bhdata;
398 			stt->position = *chosen_pos;
399 			break;
400 		}
401 
402 		case I_BehaviourGenerator :
403 		{
404 			GENERATOR_BLOCK* tdg =(GENERATOR_BLOCK*) bbd->bhdata;
405 			tdg->Position=*chosen_pos;
406 			break;
407 		}
408 
409 		case I_BehaviourAlien :
410 		{
411 			TOOLS_DATA_ALIEN* tda=(TOOLS_DATA_ALIEN*) bbd->bhdata;
412 			tda->position=*chosen_pos;
413 			tda->starteuler=*chosen_euler;
414 			break;
415 		}
416 
417 		case I_BehaviourMarine :
418 		{
419 			TOOLS_DATA_MARINE* tdm=(TOOLS_DATA_MARINE*) bbd->bhdata;
420 			tdm->position=*chosen_pos;
421 			get_marine_facing_point(*chosen_pos,*chosen_euler,tdm->facing_point);
422 			break;
423 		}
424 
425 		case I_BehaviourDormantPredator :
426 		case I_BehaviourPredator :
427 		{
428 			TOOLS_DATA_PREDATOR* tdp=(TOOLS_DATA_PREDATOR*) bbd->bhdata;
429 			tdp->position=*chosen_pos;
430 			break;
431 		}
432 
433 		case I_BehaviourQueenAlien :
434 		{
435 			TOOLS_DATA_QUEEN* tdq=(TOOLS_DATA_QUEEN*) bbd->bhdata;
436 			tdq->position=*chosen_pos;
437 			break;
438 		}
439 
440 		case I_BehaviourFaceHugger :
441 		{
442 			TOOLS_DATA_FACEHUGGER* tdf=(TOOLS_DATA_FACEHUGGER*) bbd->bhdata;
443 			tdf->position=*chosen_pos;
444 			break;
445 		}
446 
447 		case I_BehaviourAutoGun :
448 		{
449 			AUTOGUN_TOOLS_TEMPLATE* tda=(AUTOGUN_TOOLS_TEMPLATE*) bbd->bhdata;
450 			tda->position=*chosen_pos;
451 			tda->orientation=*chosen_euler;
452 			break;
453 		}
454 
455 		case I_BehaviourXenoborg :
456 		{
457 			TOOLS_DATA_XENO* tdx=(TOOLS_DATA_XENO*) bbd->bhdata;
458 			tdx->position=*chosen_pos;
459 			tdx->starteuler=*chosen_euler;
460 			break;
461 		}
462 
463 		case I_BehaviourParticleGenerator :
464 		{
465 			PARTICLE_GENERATOR_TOOLS_TEMPLATE* part_temp=(PARTICLE_GENERATOR_TOOLS_TEMPLATE*) bbd->bhdata;
466 			part_temp->position=*chosen_pos;
467 			MATRIXCH m;
468 			CreateEulerMatrix(chosen_euler,&m);
469 			TransposeMatrixCH(&m);
470 
471 			part_temp->orientation=m;
472 			break;
473 		}
474 
475 		default:
476 			break;
477 	}
478 }
479 
create_strategies_from_list()480 void create_strategies_from_list ()
481 {
482 	for(LIF<BehaviourBlockData*> blif(&Behav_List);!blif.done();blif.next())
483 	{
484 		BehaviourBlockData* bbd=blif();
485 
486 		//is the strategy required by the current difficulty level?
487 		switch(AvP.Difficulty)
488 		{
489 			case I_Easy :
490 				if(!bbd->diff_easy) continue;
491 				break;
492 			case I_Medium :
493 				if(!bbd->diff_medium) continue;
494 				break;
495 			case I_Hard :
496 			case I_Impossible :
497 				if(!bbd->diff_hard) continue;
498 				break;
499 			default:
500 				break;
501 		}
502 
503 		if(AvP.Network != I_No_Network && !AvP.NetworkAIServer)
504 		{
505 			//if this is a network game , and we aren't the	ai host , then we shouldn't set up
506 			//any aliens
507 			if(bbd->sb_type==I_BehaviourAlien) continue;
508 		}
509 
510 		//if this is a quantum object , need to select location
511 		select_alternate_location(bbd);
512 
513 		STRATEGYBLOCK * sbPtr;
514 		sbPtr = CreateActiveStrategyBlock();
515 
516 		if(!sbPtr)
517 		{
518 			GLOBALASSERT(0=="Run out of strategy blocks");
519 		}
520 
521 		InitialiseSBValues(sbPtr);
522 		sbPtr->I_SBtype = bbd->sb_type;
523 		sbPtr->shapeIndex=bbd->shapeindex;
524 		sbPtr->SBflags.preserve_until_end_of_level=1;
525 		if(bbd->name)
526 		{
527 			sbPtr->name=bbd->name;
528 		}
529 		*(ObjectID*)&sbPtr->SBname[0]=bbd->id;
530 
531 		EnableBehaviourType(sbPtr, bbd->sb_type, bbd->bhdata );
532 
533 	}
534 	//get rid of stored list of rolls for quantum object groups
535 	clear_location_group_die_roll_list();
536 }
537 
AddToBehaviourList(const char * name,const ObjectID & ID,AVP_BEHAVIOUR_TYPE sb_type,void * bhdata,int shapeindex=-1,Object_Alternate_Locations_Chunk * loc_chunk=0,int flags=0)538 void AddToBehaviourList(const char* name,const ObjectID &ID,AVP_BEHAVIOUR_TYPE sb_type,void* bhdata,int shapeindex=-1,Object_Alternate_Locations_Chunk* loc_chunk=0,int flags=0)
539 {
540 	BehaviourBlockData* bbd=(BehaviourBlockData*) PoolAllocateMem(sizeof(BehaviourBlockData));
541 	bbd->sb_type=sb_type;
542 	bbd->bhdata=bhdata;
543 	bbd->id=ID;
544 	bbd->shapeindex=shapeindex;
545 
546 	bbd->diff_easy=1;
547 	bbd->diff_medium=1;
548 	bbd->diff_hard=1;
549 
550 	if(name)
551 	{
552 		bbd->name=(char*) PoolAllocateMem(strlen(name)+1);
553 		strcpy(bbd->name,name);
554 	}
555 	else
556 	{
557 		bbd->name=0;
558 	}
559 
560 	if(loc_chunk && loc_chunk->num_locations>=2)
561 	{
562 		bbd->num_locations=loc_chunk->num_locations;
563 		bbd->location_group=loc_chunk->group;
564 		bbd->alt_vector=(VECTORCH*) PoolAllocateMem(bbd->num_locations*sizeof(VECTORCH));
565 		bbd->alt_euler=(EULER*) PoolAllocateMem(bbd->num_locations*sizeof(EULER));
566 		for(int i=0;i<loc_chunk->num_locations;i++)
567 		{
568 			bbd->alt_vector[i]=loc_chunk->locations[i].position*local_scale;
569 
570 			QUAT q;
571 
572 			q.quatx = (int) -(loc_chunk->locations[i].orientation.x*ONE_FIXED);
573 			q.quaty = (int) -(loc_chunk->locations[i].orientation.y*ONE_FIXED);
574 			q.quatz = (int) -(loc_chunk->locations[i].orientation.z*ONE_FIXED);
575 			q.quatw = (int)  (loc_chunk->locations[i].orientation.w*ONE_FIXED);
576 
577 
578 			MATRIXCH m;
579 
580 			QuatToMat (&q, &m);
581 
582 			MatrixToEuler(&m, &bbd->alt_euler[i]);
583 		}
584 	}
585 	else
586 	{
587 		bbd->num_locations=0;
588 		bbd->location_group=0;
589 		bbd->alt_vector=0;
590 		bbd->alt_euler=0;
591 	}
592 
593 	if(flags)
594 	{
595 		//see which difficulty levels this object is used for
596 		bbd->diff_easy=(flags & OBJECT_FLAG_NOTDIFFICULTY1)==0;
597 		bbd->diff_medium=(flags & OBJECT_FLAG_NOTDIFFICULTY2)==0;
598 		bbd->diff_hard=(flags & OBJECT_FLAG_NOTDIFFICULTY3)==0;
599 	}
600 
601 	Behav_List.add_entry(bbd);
602 }
603 
deallocate_behaviour_list()604 void deallocate_behaviour_list()
605 {
606 	while(Behav_List.size())
607 	{
608 		BehaviourBlockData* bbd=Behav_List.first_entry();
609 
610 		switch(bbd->sb_type)
611 		{
612 			case I_BehaviourMissionComplete :
613 				{
614 					MISSION_COMPLETE_TOOLS_TEMPLATE* mctt=(MISSION_COMPLETE_TOOLS_TEMPLATE*)bbd->bhdata;
615 					if(mctt->mission_objective_ptr)
616 					{
617 						delete (MissionObjective *)(mctt->mission_objective_ptr);
618 					}
619 
620 				}
621 				break;
622 			#if !NEW_DEALLOCATION_ORDER
623 			case I_BehaviourLinkSwitch:
624 				{
625 					LINK_SWITCH_TOOLS_TEMPLATE* lstt=(LINK_SWITCH_TOOLS_TEMPLATE*)bbd->bhdata;
626 					if(lstt->track)
627 					{
628 						Deallocate_Track(lstt->track);
629 					}
630 					#if !USE_LEVEL_MEMORY_POOL
631 					DeallocateMem (lstt->targets);
632 					if(lstt->switchIDs)
633 					{
634 						DeallocateMem (lstt->switchIDs);
635 					}
636 					#endif
637 				}
638 				break;
639 
640 			case I_BehaviourBinarySwitch :
641 				{
642 					BIN_SWITCH_TOOLS_TEMPLATE* bstt=(BIN_SWITCH_TOOLS_TEMPLATE*)bbd->bhdata;
643 					#if !USE_LEVEL_MEMORY_POOL
644 					DeallocateMem(bstt->target_names);
645 					DeallocateMem(bstt->request_messages);
646 					#endif
647 
648 					if(bstt->track)
649 					{
650 						Deallocate_Track(bstt->track);
651 					}
652 				}
653 				break;
654 
655 			case I_BehaviourPlacedSound :
656 				{
657 					SOUND_TOOLS_TEMPLATE* stt=(SOUND_TOOLS_TEMPLATE*)bbd->bhdata;
658 					#if !USE_LEVEL_MEMORY_POOL
659 					DeallocateMem(stt->sound_name);
660 					#endif
661 					if(stt->sound_loaded)
662 					{
663 						LoseSound(stt->sound_loaded);
664 					}
665 				}
666 				break;
667 
668 			case I_BehaviourTrackObject :
669 				{
670 					TRACK_OBJECT_TOOLS_TEMPLATE* tott=(TRACK_OBJECT_TOOLS_TEMPLATE*)bbd->bhdata;
671 					if(tott->track)
672 					{
673 						Deallocate_Track(tott->track);
674 					}
675 					#if !USE_LEVEL_MEMORY_POOL
676 					if(tott->special_track_points)
677 					{
678 						int i;
679 						for(i=0;i<tott->num_special_track_points;i++)
680 						{
681 							if(tott->special_track_points[i].targets)
682 								DeallocateMem(tott->special_track_points[i].targets);
683 						}
684 						DeallocateMem(tott->special_track_points);
685 					}
686 					#endif
687 				}
688 				break;
689 
690 			case I_BehaviourFan :
691 				{
692 					FAN_TOOLS_TEMPLATE* ftt=(FAN_TOOLS_TEMPLATE*)bbd->bhdata;
693 					if(ftt->track)
694 					{
695 						Deallocate_Track(ftt->track);
696 					}
697 				}
698 				break;
699 
700 
701 			case I_BehaviourPlatform :
702 				{
703 					PLATFORMLIFT_TOOLS_TEMPLATE* pltt=(PLATFORMLIFT_TOOLS_TEMPLATE*)bbd->bhdata;
704 					if(pltt->start_sound)
705 					{
706 						Deallocate_Track_Sound(pltt->start_sound);
707 					}
708 					if(pltt->sound)
709 					{
710 						Deallocate_Track_Sound(pltt->sound);
711 					}
712 					if(pltt->end_sound)
713 					{
714 						Deallocate_Track_Sound(pltt->end_sound);
715 					}
716 				}
717 				break;
718 
719 			case I_BehaviourParticleGenerator :
720 				{
721 					PARTICLE_GENERATOR_TOOLS_TEMPLATE* pgtt=(PARTICLE_GENERATOR_TOOLS_TEMPLATE*)bbd->bhdata;
722 					if(pgtt->sound)
723 					{
724 						Deallocate_Track_Sound(pgtt->sound);
725 					}
726 				}
727 				break;
728 
729 
730 			#if !USE_LEVEL_MEMORY_POOL
731 			case I_BehaviourPlacedLight :
732 				{
733 					TOOLS_DATA_PLACEDLIGHT * pltt=(TOOLS_DATA_PLACEDLIGHT*)bbd->bhdata;
734 					if(pltt->light)
735 					{
736 						DeallocateMem(pltt->light);
737 					}
738 				}
739 				break;
740 			#endif
741 
742 			case I_BehaviourPlacedHierarchy :
743 				{
744 					PLACED_HIERARCHY_TOOLS_TEMPLATE* phtt=(PLACED_HIERARCHY_TOOLS_TEMPLATE*)bbd->bhdata;
745 					int i;
746 					#if !USE_LEVEL_MEMORY_POOL
747 					if(phtt->num_sequences)
748 					{
749 						for(i=0;i<phtt->num_sequences;i++)
750 						{
751 							if(phtt->sequences[i].sound_times)
752 							{
753 								DeallocateMem(phtt->sequences[i].sound_times);
754 							}
755 						}
756 						DeallocateMem(phtt->sequences);
757 					}
758 					#endif
759 					for(i=0;i<phtt->num_sounds;i++)
760 					{
761 						if(phtt->sounds[i].sound_loaded)
762 						{
763 							LoseSound(phtt->sounds[i].sound_loaded);
764 						}
765 					}
766 					#if !USE_LEVEL_MEMORY_POOL
767 					if(phtt->sounds)
768 					{
769 						DeallocateMem(phtt->sounds);
770 					}
771 
772 					if(phtt->special_track_points)
773 					{
774 						int i;
775 						for(i=0;i<phtt->num_special_track_points;i++)
776 						{
777 							if(phtt->special_track_points[i].targets)
778 								DeallocateMem(phtt->special_track_points[i].targets);
779 						}
780 						DeallocateMem(phtt->special_track_points);
781 					}
782 					#endif
783 
784 				}
785 				#endif //!NEW_DEALLOCATION_ORDER
786 
787 			default:
788 				break;
789 		}
790 
791 		#if !USE_LEVEL_MEMORY_POOL
792 		if(bbd->alt_vector) DeallocateMem(bbd->alt_vector);
793 		if(bbd->alt_euler) DeallocateMem(bbd->alt_euler);
794 		if(bbd->name) DeallocateMem(bbd->name);
795 		DeallocateMem(bbd->bhdata);
796 		DeallocateMem(bbd);
797 		#endif
798 		Behav_List.delete_first_entry();
799 	}
800 }
801 
add_simple_animation(Object_Chunk * ob,int list_pos,MODULE * mod)802 static void add_simple_animation (Object_Chunk * ob, int list_pos, MODULE * mod)
803 {
804 	SIMPLE_ANIM_TOOLS_TEMPLATE * satt =(SIMPLE_ANIM_TOOLS_TEMPLATE*) PoolAllocateMem(sizeof(SIMPLE_ANIM_TOOLS_TEMPLATE));
805 
806 	satt->shape_num = list_pos;
807 	if (mod)
808 	{
809 		*((int *)satt->my_module.mref_name) = *((int *)mod->m_name);
810 	}
811 	else
812 	{
813 		*((int *)satt->my_module.mref_name) = 0;
814 	}
815 	*((ObjectID *)satt->nameID) = ob->object_data.ID;
816 
817 	AddToBehaviourList(ob->object_data.o_name,ob->object_data.ID, I_BehaviourSimpleAnimation, (void*)satt,list_pos);
818 }
819 
820 
add_default_object(Object_Chunk * ob,int list_pos)821 static void add_default_object(Object_Chunk * ob, int list_pos)
822 {
823 
824 	TOOLS_DATA_INANIMATEOBJECT* tdio =(TOOLS_DATA_INANIMATEOBJECT*) PoolAllocateMem(sizeof(TOOLS_DATA_INANIMATEOBJECT));
825 
826 	tdio->position.vx = (int)(ob->object_data.location.x * local_scale);
827 	tdio->position.vy = (int)(ob->object_data.location.y * local_scale);
828 	tdio->position.vz = (int)(ob->object_data.location.z * local_scale);
829 
830 	QUAT q;
831 
832 	q.quatx = (int) -(ob->object_data.orientation.x*ONE_FIXED);
833 	q.quaty = (int) -(ob->object_data.orientation.y*ONE_FIXED);
834 	q.quatz = (int) -(ob->object_data.orientation.z*ONE_FIXED);
835 	q.quatw = (int) (ob->object_data.orientation.w*ONE_FIXED);
836 
837 
838 	MATRIXCH m;
839 
840 	QuatToMat (&q, &m);
841 
842 	MatrixToEuler(&m, &tdio->orientation);
843 
844 	tdio->triggering_event=0;
845 	tdio->typeId = IOT_Furniture;
846 	tdio->subType = 0;
847 	tdio->shapeIndex = list_pos;
848 	tdio->mass=5;
849 	tdio->integrity=2;
850 	tdio->explosionType=0;
851 
852 	AddToBehaviourList(ob->object_data.o_name,ob->object_data.ID, I_BehaviourInanimateObject, (void*)tdio,list_pos,0,ob->get_header()->flags);
853 }
854 
add_trackobject(Object_Chunk * ob,int list_pos,AVP_Strategy_Chunk * asc)855 static void add_trackobject(Object_Chunk* ob, int list_pos,AVP_Strategy_Chunk* asc)
856 {
857 
858 	TRACK_CONTROLLER* track=setup_track_controller(ob);
859 	if(!track)
860 	{
861 		LOGDXFMT(("%s has no track\n",ob->object_data.o_name));
862 	 	GLOBALASSERT(track);
863 	}
864 
865 	TrackStrategy* ts=(TrackStrategy*) asc->Strategy;
866 
867 	TRACK_OBJECT_TOOLS_TEMPLATE* tott=(TRACK_OBJECT_TOOLS_TEMPLATE*) PoolAllocateMem(sizeof(TRACK_OBJECT_TOOLS_TEMPLATE));
868 
869 	*(ObjectID*)&tott->nameID[0]=ob->object_data.ID;
870 
871 	tott->position.vx = (int)(ob->object_data.location.x * local_scale);
872 	tott->position.vy = (int)(ob->object_data.location.y * local_scale);
873 	tott->position.vz = (int)(ob->object_data.location.z * local_scale);
874 
875 	QUAT q;
876 
877 	q.quatx = (int) -(ob->object_data.orientation.x*ONE_FIXED);
878 	q.quaty = (int) -(ob->object_data.orientation.y*ONE_FIXED);
879 	q.quatz = (int) -(ob->object_data.orientation.z*ONE_FIXED);
880 	q.quatw = (int) (ob->object_data.orientation.w*ONE_FIXED);
881 
882 
883 	MATRIXCH m;
884 
885 	QuatToMat (&q, &m);
886 
887 	MatrixToEuler(&m, &tott->orientation);
888 
889 	tott->shape_num = list_pos;
890 
891 	tott->track=track;
892 
893 	tott->num_special_track_points=ts->num_point_effects;
894 	if(ts->num_point_effects)
895 	{
896 		tott->special_track_points=(SPECIAL_TRACK_POINT*)PoolAllocateMem(sizeof(SPECIAL_TRACK_POINT)*ts->num_point_effects);
897 		for(int i=0;i<ts->num_point_effects;i++)
898 		{
899 			SPECIAL_TRACK_POINT* stp=&tott->special_track_points[i];
900 			TrackPointEffect* tpe=ts->point_effects[i];
901 
902 			stp->track_point_no=tpe->point_no;
903 			stp->num_targets=tpe->num_targets;
904 
905 			if(stp->num_targets)
906 			{
907 				stp->targets=(TRACK_POINT_TARGET*)PoolAllocateMem(sizeof(TRACK_POINT_TARGET)*stp->num_targets);
908 				for(int j=0;j<stp->num_targets;j++)
909 				{
910 					stp->targets[j].request=tpe->targets[j].request;
911 					stp->targets[j].flags=tpe->targets[j].flags;
912 					*(ObjectID*)&stp->targets[j].target_name[0]=tpe->targets[j].targetID;
913 				}
914 
915 			}
916 			else
917 				stp->targets=0;
918 		}
919 	}
920 	else
921 		tott->special_track_points=0;
922 
923 	if(ts->StrategyType==StratTrackDestruct)
924 	{
925 		TrackDestructStrategy* tds=(TrackDestructStrategy*)ts;
926 		tott->integrity=tds->integrity;
927 		tott->destruct_target_request=tds->target_request;
928 		*(ObjectID*)tott->destruct_target_ID=tds->targetID;
929 	}
930 	else
931 	{
932 		tott->integrity=21;
933 		tott->destruct_target_request=0;
934 		ObjectID ID0={0,0};
935 		*(ObjectID*)tott->destruct_target_ID=ID0;
936 	}
937 
938 	AddToBehaviourList(ob->object_data.o_name,ob->object_data.ID, I_BehaviourTrackObject, (void*)tott,list_pos);
939 
940 }
941 
add_placed_hierarchy(Placed_Hierarchy_Chunk * phc,const char * fname,const char * hname)942 void add_placed_hierarchy(Placed_Hierarchy_Chunk* phc,const char* fname,const char* hname)
943 {
944 	int i;
945 	PLACED_HIERARCHY_TOOLS_TEMPLATE* phtt=(PLACED_HIERARCHY_TOOLS_TEMPLATE*) PoolAllocateMem(sizeof(PLACED_HIERARCHY_TOOLS_TEMPLATE));
946 
947 	//first setup the sounds
948 	phtt->sounds=0;
949 
950 	List<Chunk*> chlist;
951 	phc->lookup_child("INDSOUND",chlist);
952 	phtt->num_sounds=0;
953 
954 	//find the highest index
955 	LIF<Chunk*> chlif(&chlist);
956 	for(; !chlif.done(); chlif.next())
957 	{
958 		Indexed_Sound_Chunk* isc=(Indexed_Sound_Chunk*)chlif();
959 		phtt->num_sounds=max(phtt->num_sounds,isc->index+1);
960 	}
961 
962 	if(phtt->num_sounds)
963 	{
964 		phtt->sounds=(PLACED_HIERARCHY_SOUND*)PoolAllocateMem(sizeof(PLACED_HIERARCHY_SOUND)*phtt->num_sounds);
965 		for(i=0;i<phtt->num_sounds;i++)
966 		{
967 			phtt->sounds[i].sound_loaded=0;
968 			phtt->sounds[i].activ_no=SOUND_NOACTIVEINDEX;
969 		}
970 
971 		for(chlif.restart();!chlif.done();chlif.next())
972 		{
973 			Indexed_Sound_Chunk* isc=(Indexed_Sound_Chunk*)chlif();
974 			PLACED_HIERARCHY_SOUND* phs=&phtt->sounds[isc->index];
975 
976 			phs->inner_range=(unsigned)(isc->inner_range*local_scale);
977 			phs->outer_range=(unsigned)(isc->outer_range*local_scale);
978 			phs->pitch=isc->pitch;
979 			phs->max_volume=isc->max_volume;
980 			phs->playing=0;
981 			phs->loop=((isc->flags & IndexedSoundFlag_Loop)!=0);
982 			phs->sound_loaded=GetSoundForMainRif(isc->wav_name);
983 		}
984 	}
985 
986 	//now setup the sequences
987 	phc->lookup_child("PLHISEQU",chlist);
988 	phtt->num_sequences=0;
989 	//find the highest sequence index
990 	for(chlif.restart();!chlif.done();chlif.next())
991 	{
992 		Placed_Hierarchy_Sequence_Chunk* phsc=(Placed_Hierarchy_Sequence_Chunk*)chlif();
993 		phtt->num_sequences=max(phtt->num_sequences,phsc->index+1);
994 	}
995 
996 	GLOBALASSERT(phtt->num_sequences);
997 
998 	phtt->sequences=(PLACED_HIERARCHY_SEQUENCE*)PoolAllocateMem(sizeof(PLACED_HIERARCHY_SEQUENCE)*phtt->num_sequences);
999 	for(i=0;i<phtt->num_sequences;i++)
1000 	{
1001 		phtt->sequences[i].sequence_no=-1;
1002 	}
1003 	phtt->first_sequence=&phtt->sequences[0];
1004 	phtt->playing=0;
1005 
1006 	for(chlif.restart();!chlif.done();chlif.next())
1007 	{
1008 		Placed_Hierarchy_Sequence_Chunk* phsc=(Placed_Hierarchy_Sequence_Chunk*)chlif();
1009 		PLACED_HIERARCHY_SEQUENCE* ph_seq=&phtt->sequences[phsc->index];
1010 
1011 		ph_seq->sequence_no=phsc->sequence;
1012 		ph_seq->sub_sequence_no=phsc->sub_sequence;
1013 		ph_seq->time=(int)(((float)phsc->time*(float)ONE_FIXED)/1000.0);
1014 		ph_seq->loop=((phsc->flags & HierarchySequenceFlag_Loop)!=0);
1015 
1016 		if(phsc->flags & HierarchySequenceFlag_InitialSequence)
1017 		{
1018 			phtt->first_sequence=ph_seq;
1019 			if(phsc->flags & HierarchySequenceFlag_Playing)
1020 			{
1021 				phtt->playing=0;
1022 			}
1023 		}
1024 
1025 		ph_seq->num_sound_times=phsc->sound_list_size;
1026 		if(ph_seq->num_sound_times)
1027 		{
1028 			ph_seq->sound_times=(PLACED_HIERARCHY_SOUND_TIMES*)PoolAllocateMem(sizeof(PLACED_HIERARCHY_SOUND_TIMES)*ph_seq->num_sound_times);
1029 			for(i=0;i<ph_seq->num_sound_times;i++)
1030 			{
1031 				ph_seq->sound_times[i].start_time=phsc->sound_list[i].start_time;
1032 				ph_seq->sound_times[i].end_time=phsc->sound_list[i].end_time;
1033 
1034 				int sound_index=phsc->sound_list[i].sound_index;
1035 				if(sound_index>=0 && sound_index<phtt->num_sounds)
1036 				{
1037 					ph_seq->sound_times[i].sound=&phtt->sounds[sound_index];
1038 				}
1039 				else
1040 				{
1041 					ph_seq->sound_times[i].sound=0;
1042 				}
1043 
1044 			}
1045 		}
1046 		else
1047 		{
1048 			ph_seq->sound_times=0;
1049 		}
1050 
1051 	}
1052 
1053 	phtt->num_special_track_points=0;
1054 	phtt->special_track_points=0;
1055 	AVP_Strategy_Chunk* asc=(AVP_Strategy_Chunk*) phc->lookup_single_child("AVPSTRAT");
1056 	if(asc && asc->Strategy)
1057 	{
1058 		GLOBALASSERT(asc->Strategy->StrategyType==StratHierarchy);
1059 		HierarchyStrategy* hs=(HierarchyStrategy*) asc->Strategy;
1060 
1061 		phtt->num_special_track_points=hs->num_point_effects;
1062 		if(hs->num_point_effects)
1063 		{
1064 			phtt->special_track_points=(SPECIAL_TRACK_POINT*)PoolAllocateMem(sizeof(SPECIAL_TRACK_POINT)*hs->num_point_effects);
1065 			for(int i=0;i<hs->num_point_effects;i++)
1066 			{
1067 				SPECIAL_TRACK_POINT* stp=&phtt->special_track_points[i];
1068 				TrackPointEffect* tpe=hs->point_effects[i];
1069 
1070 				stp->track_point_no=1<<tpe->point_no;
1071 				stp->num_targets=tpe->num_targets;
1072 
1073 				if(stp->num_targets)
1074 				{
1075 					stp->targets=(TRACK_POINT_TARGET*)PoolAllocateMem(sizeof(TRACK_POINT_TARGET)*stp->num_targets);
1076 					for(int j=0;j<stp->num_targets;j++)
1077 					{
1078 						stp->targets[j].request=tpe->targets[j].request;
1079 						stp->targets[j].flags=tpe->targets[j].flags;
1080 						*(ObjectID*)&stp->targets[j].target_name[0]=tpe->targets[j].targetID;
1081 					}
1082 
1083 				}
1084 				else
1085 					stp->targets=0;
1086 			}
1087 		}
1088 		else
1089 			phtt->special_track_points=0;
1090 
1091 	}
1092 
1093 	Placed_Hierarchy_Data_Chunk* data=phc->get_data_chunk();
1094 
1095 
1096 	*(ObjectID*) &phtt->nameID[0]=data->id;
1097 
1098 	phtt->position.vx = (int)(data->location.x * local_scale);
1099 	phtt->position.vy = (int)(data->location.y * local_scale);
1100 	phtt->position.vz = (int)(data->location.z * local_scale);
1101 
1102 	QUAT q;
1103 
1104 	q.quatx = (int) -(data->orientation.x*ONE_FIXED);
1105 	q.quaty = (int) -(data->orientation.y*ONE_FIXED);
1106 	q.quatz = (int) -(data->orientation.z*ONE_FIXED);
1107 	q.quatw = (int) (data->orientation.w*ONE_FIXED);
1108 
1109 
1110 	MATRIXCH m;
1111 
1112 	QuatToMat (&q, &m);
1113 
1114 	MatrixToEuler(&m, &phtt->orientation);
1115 
1116 	phtt->hier_name=hname;
1117 	phtt->file_name=fname;
1118 
1119 	AddToBehaviourList(0,data->id, I_BehaviourPlacedHierarchy, (void *) phtt,0);
1120 }
1121 
1122 
GetFanWindDirection(QUAT * q1,QUAT * q2,VECTORCH * dir)1123 static void GetFanWindDirection(QUAT *q1, QUAT *q2, VECTORCH* dir)
1124 
1125 {
1126 
1127 	//calulate q1 inverse * q2 , and then take axis of rotation
1128 	int temp1, temp2, temp3, temp4, temp5, temp6, temp7, temp8;
1129 	int S, T;
1130 
1131 	temp1 = MUL_FIXED((q1->quatz - q1->quaty), (q2->quaty - q2->quatz));
1132 	temp2 = MUL_FIXED((-q1->quatw + q1->quatx), (q2->quatw + q2->quatx));
1133 	temp3 = MUL_FIXED((-q1->quatw - q1->quatx), (q2->quaty + q2->quatz));
1134 	temp4 = MUL_FIXED((q1->quatz + q1->quaty), (q2->quatw - q2->quatx));
1135 	temp5 = MUL_FIXED((q1->quatz - q1->quatx), (q2->quatx - q2->quaty));
1136 	temp6 = MUL_FIXED((q1->quatz + q1->quatx), (q2->quatx + q2->quaty));
1137 	temp7 = MUL_FIXED((-q1->quatw + q1->quaty), (q2->quatw - q2->quatz));
1138 	temp8 = MUL_FIXED((-q1->quatw - q1->quaty), (q2->quatw + q2->quatz));
1139 
1140 	S = temp6 + temp7 + temp8;
1141 
1142 	T = (temp5 + S) / 2;
1143 
1144 	dir->vx = temp2 + T - S;
1145 	dir->vy = temp3 + T - temp8;
1146 	dir->vz = temp4 + T - temp7;
1147 
1148 	if(temp1 + T - temp6 > 0)
1149 	{
1150 		dir->vx=-dir->vx;
1151 		dir->vy=-dir->vy;
1152 		dir->vz=-dir->vz;
1153 	}
1154 
1155 	Normalise(dir);
1156 
1157 }
1158 
add_fan(Object_Chunk * ob,int list_pos,AVP_Strategy_Chunk * asc)1159 static void add_fan(Object_Chunk* ob, int list_pos,AVP_Strategy_Chunk* asc)
1160 {
1161 
1162 	TRACK_CONTROLLER* track=setup_track_controller(ob);
1163 	GLOBALASSERT(track);
1164 
1165 	FanStrategy* fs=(FanStrategy*) asc->Strategy;
1166 
1167 	FAN_TOOLS_TEMPLATE* ftt=(FAN_TOOLS_TEMPLATE*) PoolAllocateMem(sizeof(FAN_TOOLS_TEMPLATE));
1168 
1169 	*(ObjectID*)&ftt->nameID[0]=ob->object_data.ID;
1170 
1171 	ftt->position.vx = (int)(ob->object_data.location.x * local_scale);
1172 	ftt->position.vy = (int)(ob->object_data.location.y * local_scale);
1173 	ftt->position.vz = (int)(ob->object_data.location.z * local_scale);
1174 
1175 	QUAT q;
1176 
1177 	q.quatx = (int) -(ob->object_data.orientation.x*ONE_FIXED);
1178 	q.quaty = (int) -(ob->object_data.orientation.y*ONE_FIXED);
1179 	q.quatz = (int) -(ob->object_data.orientation.z*ONE_FIXED);
1180 	q.quatw = (int) (ob->object_data.orientation.w*ONE_FIXED);
1181 
1182 
1183 	MATRIXCH m;
1184 
1185 	QuatToMat (&q, &m);
1186 
1187 	MatrixToEuler(&m, &ftt->orientation);
1188 
1189 	ftt->shape_num = list_pos;
1190 	ftt->track=track;
1191 	ftt->speed_up_mult=DIV_FIXED(ONE_FIXED,fs->speed_up_time);
1192 	ftt->slow_down_mult=DIV_FIXED(ONE_FIXED,fs->slow_down_time);
1193 
1194 	GetFanWindDirection(&track->sections[0].quat_start,&track->sections[0].quat_end,&ftt->fan_wind_direction);
1195 
1196 	if(fs->fan_wind_strength>=-1000 && fs->fan_wind_strength<=1000)
1197 		ftt->fan_wind_strength=(fs->fan_wind_strength*ONE_FIXED)/100;
1198 	else
1199 		ftt->fan_wind_strength=ONE_FIXED;
1200 	//if the wind strength is negative , then the wind goes in the opposite direction
1201 	if(ftt->fan_wind_strength<0)
1202 	{
1203 		ftt->fan_wind_strength=-ftt->fan_wind_strength;
1204 		ftt->fan_wind_direction.vx=-ftt->fan_wind_direction.vx;
1205 		ftt->fan_wind_direction.vy=-ftt->fan_wind_direction.vy;
1206 		ftt->fan_wind_direction.vz=-ftt->fan_wind_direction.vz;
1207 	}
1208 
1209 	AddToBehaviourList(ob->object_data.o_name,ob->object_data.ID, I_BehaviourFan, (void*)ftt,list_pos,0,ob->get_header()->flags);
1210 }
1211 
1212 
add_linkswitch(const char * name,AVP_Strategy_Chunk * asc,const ObjectID & ID,Object_Chunk * oc=0,int list_pos=-1)1213 static void add_linkswitch(const char* name,AVP_Strategy_Chunk* asc,const ObjectID& ID,Object_Chunk* oc=0,int list_pos=-1)
1214 {
1215 
1216 	LinkSwitchStrategy * lss = (LinkSwitchStrategy *)asc->Strategy;
1217 
1218 	LINK_SWITCH_TOOLS_TEMPLATE* lstt=(LINK_SWITCH_TOOLS_TEMPLATE*) PoolAllocateMem(sizeof(LINK_SWITCH_TOOLS_TEMPLATE));
1219 
1220 	lstt->trigger_volume_min.vx=lstt->trigger_volume_max.vx=0;
1221 	lstt->trigger_volume_min.vy=lstt->trigger_volume_max.vy=0;
1222 	lstt->trigger_volume_min.vz=lstt->trigger_volume_max.vz=0;
1223 	lstt->switch_flags=0;
1224 
1225 	if(oc) //switch has a shape
1226 	{
1227 		lstt->position.vx = (int)(oc->object_data.location.x * local_scale);
1228 		lstt->position.vy = (int)(oc->object_data.location.y * local_scale);
1229 		lstt->position.vz = (int)(oc->object_data.location.z * local_scale);
1230 
1231 
1232 		QUAT q;
1233 
1234 		q.quatx = (int) -(oc->object_data.orientation.x*ONE_FIXED);
1235 		q.quaty = (int) -(oc->object_data.orientation.y*ONE_FIXED);
1236 		q.quatz = (int) -(oc->object_data.orientation.z*ONE_FIXED);
1237 		q.quatw = (int) (oc->object_data.orientation.w*ONE_FIXED);
1238 
1239 
1240 		MATRIXCH m;
1241 
1242 		QuatToMat (&q, &m);
1243 
1244 		MatrixToEuler(&m, &lstt->orientation);
1245 
1246 		lstt->track=setup_track_controller(oc);
1247 		if(lstt->track)
1248 		{
1249 			lstt->track->loop=FALSE;
1250 			lstt->track->loop_backandforth=FALSE;
1251 			lstt->track->playing=FALSE;
1252 			lstt->track->initial_state_playing=FALSE;
1253 			lstt->track->timer=0;
1254 			lstt->track->initial_state_timer=0;
1255 		}
1256 		lstt->switch_always_on=0;
1257 	}
1258 	else //switch has no shape
1259 	{
1260 		lstt->position.vx = 0;
1261 		lstt->position.vy = 0;
1262 		lstt->position.vz = 0;
1263 
1264 		lstt->track=0;
1265 
1266 		lstt->orientation.EulerX=lstt->orientation.EulerY=lstt->orientation.EulerZ=0;
1267 		lstt->switch_always_on=1;
1268 	}
1269 
1270 
1271 	lstt->rest_state = ((lss->flags & BinSwitchFlag_StartsOn)!=0);
1272 	lstt->mode = lss->Mode;
1273 	lstt->time_for_reset = lss->Time;
1274 	lstt->security_clearance = lss->Security;
1275 	lstt->shape_num = list_pos;
1276 	*((ObjectID *)lstt->nameID) =ID;
1277 
1278 
1279 	lstt->switch_off_message_same = ((lss->flags & BinSwitchFlag_OffMessageSame)!=0);
1280 	lstt->switch_off_message_none = ((lss->flags & BinSwitchFlag_OffMessageNone)!=0);
1281 
1282 	LINK_SWITCH_TARGET* ls_target=(LINK_SWITCH_TARGET*) PoolAllocateMem (sizeof(LINK_SWITCH_TARGET));
1283 
1284 	*(ObjectID*)ls_target->name=lss->Target.ID;
1285 	ls_target->request_message=1|lss->Target.request;
1286 	ls_target->sbptr=0;
1287 
1288 	lstt->num_targets=1;
1289 	lstt->targets=ls_target;
1290 
1291 	if(lss->NumLinks)
1292 	  		lstt->switchIDs=(SBNAMEBLOCK*) PoolAllocateMem(lss->NumLinks*sizeof(SBNAMEBLOCK));
1293 	else
1294 		lstt->switchIDs=0;
1295 
1296 	lstt->num_linked_switches=lss->NumLinks;
1297 	for (int i=0; i<lss->NumLinks; i++)
1298 	{
1299 		*((ObjectID *)lstt->switchIDs[i].name) = lss->LinkedSwitches[i];
1300 	}
1301 
1302 	AddToBehaviourList(name,ID, I_BehaviourLinkSwitch, (void*)lstt,list_pos);
1303 
1304 }
add_multitarget_linkswitch(const char * name,AVP_Strategy_Chunk * asc,const ObjectID & ID,Object_Chunk * oc=0,int list_pos=-1)1305 static void add_multitarget_linkswitch(const char* name,AVP_Strategy_Chunk* asc,const ObjectID& ID,Object_Chunk* oc=0,int list_pos=-1)
1306 {
1307 	MultiSwitchStrategy * mss = (MultiSwitchStrategy *)asc->Strategy;
1308 
1309 	LINK_SWITCH_TOOLS_TEMPLATE* lstt=(LINK_SWITCH_TOOLS_TEMPLATE*) PoolAllocateMem(sizeof(LINK_SWITCH_TOOLS_TEMPLATE));
1310 
1311 	if(oc) //switch has a shape
1312 	{
1313 		lstt->position.vx = (int)(oc->object_data.location.x * local_scale);
1314 		lstt->position.vy = (int)(oc->object_data.location.y * local_scale);
1315 		lstt->position.vz = (int)(oc->object_data.location.z * local_scale);
1316 
1317 
1318 		QUAT q;
1319 
1320 		q.quatx = (int) -(oc->object_data.orientation.x*ONE_FIXED);
1321 		q.quaty = (int) -(oc->object_data.orientation.y*ONE_FIXED);
1322 		q.quatz = (int) -(oc->object_data.orientation.z*ONE_FIXED);
1323 		q.quatw = (int) (oc->object_data.orientation.w*ONE_FIXED);
1324 
1325 
1326 		MATRIXCH m;
1327 
1328 		QuatToMat (&q, &m);
1329 
1330 		MatrixToEuler(&m, &lstt->orientation);
1331 
1332 		lstt->track=setup_track_controller(oc);
1333 		if(lstt->track)
1334 		{
1335 			lstt->track->loop=FALSE;
1336 			lstt->track->loop_backandforth=FALSE;
1337 			lstt->track->playing=FALSE;
1338 			lstt->track->initial_state_playing=FALSE;
1339 			lstt->track->timer=0;
1340 			lstt->track->initial_state_timer=0;
1341 		}
1342 	}
1343 	else //switch has no shape
1344 	{
1345 		lstt->position.vx = 0;
1346 		lstt->position.vy = 0;
1347 		lstt->position.vz = 0;
1348 
1349 		lstt->track=0;
1350 
1351 		lstt->orientation.EulerX=lstt->orientation.EulerY=lstt->orientation.EulerZ=0;
1352 	}
1353 
1354 	if(mss->StrategyType==StratAreaSwitch)
1355 	{
1356 		//switch can be triggered by walking into a ceartain area
1357 		AreaSwitchStrategy* ass=(AreaSwitchStrategy*)mss;
1358 		lstt->trigger_volume_min=ass->trigger_min*local_scale;
1359 		lstt->trigger_volume_max=ass->trigger_max*local_scale;
1360 		lstt->switch_flags=SwitchFlag_UseTriggerVolume;
1361 	}
1362 	else
1363 	{
1364 		lstt->trigger_volume_min.vx=lstt->trigger_volume_max.vx=0;
1365 		lstt->trigger_volume_min.vy=lstt->trigger_volume_max.vy=0;
1366 		lstt->trigger_volume_min.vz=lstt->trigger_volume_max.vz=0;
1367 		lstt->switch_flags=0;
1368 	}
1369 
1370 	lstt->switch_off_message_same = ((mss->flags & BinSwitchFlag_OffMessageSame)!=0);
1371 	lstt->switch_off_message_none = ((mss->flags & BinSwitchFlag_OffMessageNone)!=0);
1372 	lstt->rest_state = mss->RestState;
1373 
1374 	lstt->mode = mss->Mode;
1375 	if(lstt->mode>I_lswitch_toggle)
1376 	{
1377 		lstt->mode=I_lswitch_timer;
1378 	}
1379 	lstt->time_for_reset = mss->Time;
1380 	lstt->security_clearance = mss->Security;
1381 	lstt->shape_num = list_pos;
1382 	*((ObjectID *)lstt->nameID) =ID;
1383 
1384 	int i;
1385 
1386 	lstt->num_targets=mss->NumTargets;
1387 	if(mss->NumTargets)
1388 	{
1389 		lstt->targets=(LINK_SWITCH_TARGET*) PoolAllocateMem(mss->NumTargets * sizeof(LINK_SWITCH_TARGET));
1390 		for(i=0;i<mss->NumTargets;i++)
1391 		{
1392 			*(ObjectID*)lstt->targets[i].name=mss->Targets[i].ID;
1393 			lstt->targets[i].request_message=mss->Targets[i].request;
1394 			lstt->targets[i].sbptr=0;
1395 		}
1396 	}
1397 	else
1398 	{
1399 		lstt->targets=0;
1400 	}
1401 
1402 
1403 
1404 	if(mss->NumLinks)
1405 		lstt->switchIDs=(SBNAMEBLOCK*) PoolAllocateMem(mss->NumLinks * sizeof(SBNAMEBLOCK));
1406 	else
1407 		lstt->switchIDs=0;
1408 
1409 	lstt->num_linked_switches=mss->NumLinks;
1410 	for (i=0; i<mss->NumLinks; i++)
1411 	{
1412 		*((ObjectID *)lstt->switchIDs[i].name) = mss->LinkedSwitches[i];
1413 	}
1414 	lstt->switch_always_on=0;
1415 
1416 
1417 	AddToBehaviourList(name,ID, I_BehaviourLinkSwitch, (void*)lstt,list_pos);
1418 
1419 }
1420 
add_binswitch(const char * name,AVP_Strategy_Chunk * asc,const ObjectID & ID,Object_Chunk * oc=0,int list_pos=-1)1421 static void add_binswitch (const char* name,AVP_Strategy_Chunk* asc,const ObjectID& ID,Object_Chunk* oc=0,int list_pos=-1)
1422 {
1423 	BinSwitchStrategy * bss = (BinSwitchStrategy *)asc->Strategy;
1424 
1425 	BIN_SWITCH_TOOLS_TEMPLATE* bstt=(BIN_SWITCH_TOOLS_TEMPLATE*) PoolAllocateMem(sizeof(BIN_SWITCH_TOOLS_TEMPLATE));
1426 
1427 	if(oc)//switch has a shape
1428 	{
1429 		bstt->position.vx = (int)(oc->object_data.location.x * local_scale);
1430 		bstt->position.vy = (int)(oc->object_data.location.y * local_scale);
1431 		bstt->position.vz = (int)(oc->object_data.location.z * local_scale);
1432 
1433 
1434 		bstt->trigger_volume_min.vx=bstt->trigger_volume_max.vx=0;
1435 		bstt->trigger_volume_min.vy=bstt->trigger_volume_max.vy=0;
1436 		bstt->trigger_volume_min.vz=bstt->trigger_volume_max.vz=0;
1437 		bstt->switch_flags=0;
1438 
1439 
1440 		QUAT q;
1441 
1442 		q.quatx = (int) -(oc->object_data.orientation.x*ONE_FIXED);
1443 		q.quaty = (int) -(oc->object_data.orientation.y*ONE_FIXED);
1444 		q.quatz = (int) -(oc->object_data.orientation.z*ONE_FIXED);
1445 		q.quatw = (int) (oc->object_data.orientation.w*ONE_FIXED);
1446 
1447 
1448 		MATRIXCH m;
1449 
1450 		QuatToMat (&q, &m);
1451 
1452 		MatrixToEuler(&m, &bstt->orientation);
1453 
1454 		bstt->track=setup_track_controller(oc);
1455 		if(bstt->track)
1456 		{
1457 			bstt->track->loop=FALSE;
1458 			bstt->track->loop_backandforth=FALSE;
1459 			bstt->track->playing=FALSE;
1460 			bstt->track->initial_state_playing=FALSE;
1461 			bstt->track->timer=0;
1462 			bstt->track->initial_state_timer=0;
1463 		}
1464 	}
1465 	else	//switch has no shape
1466 	{
1467 		bstt->position.vx = 0;
1468 		bstt->position.vy = 0;
1469 		bstt->position.vz = 0;
1470 
1471 		bstt->track=0;
1472 
1473 		bstt->trigger_volume_min.vx=bstt->trigger_volume_max.vx=0;
1474 		bstt->trigger_volume_min.vy=bstt->trigger_volume_max.vy=0;
1475 		bstt->trigger_volume_min.vz=bstt->trigger_volume_max.vz=0;
1476 		bstt->switch_flags=0;
1477 
1478 		bstt->orientation.EulerX=bstt->orientation.EulerY=bstt->orientation.EulerZ=0;
1479 
1480 	}
1481 
1482 	bstt->starts_on = ((bss->flags & BinSwitchFlag_StartsOn)!=0);
1483 	bstt->switch_off_message_same = ((bss->flags & BinSwitchFlag_OffMessageSame)!=0);
1484 	bstt->switch_off_message_none = ((bss->flags & BinSwitchFlag_OffMessageNone)!=0);
1485 
1486 	bstt->mode = bss->Mode;
1487 	bstt->time_for_reset = bss->Time;
1488 	bstt->security_clearance = bss->Security;
1489 
1490 	bstt->num_targets = 1;
1491 
1492 	int* request_message=(int*) PoolAllocateMem(sizeof(int));
1493 	request_message[0]=1|bss->Target.request;
1494 	bstt->request_messages=request_message;
1495 
1496 	SBNAMEBLOCK* snb =(SBNAMEBLOCK*) PoolAllocateMem(sizeof(SBNAMEBLOCK));
1497 	*((ObjectID *)snb->name) = bss->Target.ID;
1498 	bstt->target_names = snb;
1499 
1500 	bstt->shape_num = list_pos;
1501 	*((ObjectID *)bstt->nameID) = ID;
1502 
1503 	AddToBehaviourList(name,ID, I_BehaviourBinarySwitch, (void*)bstt,list_pos);
1504 
1505 }
1506 
add_multiswitch(const char * name,AVP_Strategy_Chunk * asc,const ObjectID & ID,Object_Chunk * oc=0,int list_pos=-1)1507 static void add_multiswitch (const char* name,AVP_Strategy_Chunk* asc,const ObjectID& ID,Object_Chunk* oc=0,int list_pos=-1)
1508 {
1509 	MultiSwitchStrategy * mss = (MultiSwitchStrategy *)asc->Strategy;
1510 	if(mss->NumLinks)
1511 	{
1512 		add_multitarget_linkswitch(name,asc,ID,oc,list_pos);
1513 		return;
1514 	}
1515 
1516 	BIN_SWITCH_TOOLS_TEMPLATE* bstt=(BIN_SWITCH_TOOLS_TEMPLATE*) PoolAllocateMem(sizeof(BIN_SWITCH_TOOLS_TEMPLATE));
1517 
1518 	if(oc) //switch has a shape
1519 	{
1520 		bstt->position.vx = (int)(oc->object_data.location.x * local_scale);
1521 		bstt->position.vy = (int)(oc->object_data.location.y * local_scale);
1522 		bstt->position.vz = (int)(oc->object_data.location.z * local_scale);
1523 
1524 
1525 		QUAT q;
1526 
1527 		q.quatx = (int) -(oc->object_data.orientation.x*ONE_FIXED);
1528 		q.quaty = (int) -(oc->object_data.orientation.y*ONE_FIXED);
1529 		q.quatz = (int) -(oc->object_data.orientation.z*ONE_FIXED);
1530 		q.quatw = (int) (oc->object_data.orientation.w*ONE_FIXED);
1531 
1532 
1533 		MATRIXCH m;
1534 
1535 		QuatToMat (&q, &m);
1536 
1537 		MatrixToEuler(&m, &bstt->orientation);
1538 
1539 		bstt->track=setup_track_controller(oc);
1540 		if(bstt->track)
1541 		{
1542 			bstt->track->loop=FALSE;
1543 			bstt->track->loop_backandforth=FALSE;
1544 			bstt->track->playing=FALSE;
1545 			bstt->track->initial_state_playing=FALSE;
1546 			bstt->track->timer=0;
1547 			bstt->track->initial_state_timer=0;
1548 		}
1549 	}
1550 	else //switch has no shapes
1551 	{
1552 		bstt->position.vx = 0;
1553 		bstt->position.vy = 0;
1554 		bstt->position.vz = 0;
1555 
1556 		bstt->track=0;
1557 		bstt->orientation.EulerX=bstt->orientation.EulerY=bstt->orientation.EulerZ=0;
1558 	}
1559 
1560 	if(mss->StrategyType==StratAreaSwitch)
1561 	{
1562 		//switch can be triggered by walking into a ceartain area
1563 		AreaSwitchStrategy* ass=(AreaSwitchStrategy*)mss;
1564 		bstt->trigger_volume_min=ass->trigger_min*local_scale;
1565 		bstt->trigger_volume_max=ass->trigger_max*local_scale;
1566 		bstt->switch_flags=SwitchFlag_UseTriggerVolume;
1567 	}
1568 	else
1569 	{
1570 		bstt->trigger_volume_min.vx=bstt->trigger_volume_max.vx=0;
1571 		bstt->trigger_volume_min.vy=bstt->trigger_volume_max.vy=0;
1572 		bstt->trigger_volume_min.vz=bstt->trigger_volume_max.vz=0;
1573 		bstt->switch_flags=0;
1574 	}
1575 
1576 
1577 	bstt->starts_on = mss->RestState;
1578 	bstt->switch_off_message_same = ((mss->flags & MultiSwitchFlag_OffMessageSame)!=0);
1579 	bstt->switch_off_message_none = ((mss->flags & MultiSwitchFlag_OffMessageNone)!=0);
1580 
1581 	bstt->mode = mss->Mode;
1582 	bstt->time_for_reset = mss->Time;
1583 	bstt->security_clearance = mss->Security;
1584 
1585 	bstt->num_targets = mss->NumTargets;
1586 
1587 
1588 	SBNAMEBLOCK * snb = (SBNAMEBLOCK*) PoolAllocateMem(sizeof(SBNAMEBLOCK)*mss->NumTargets);
1589 
1590 	int* request_messages=(int*) PoolAllocateMem(sizeof(int) * mss->NumTargets);
1591 	for (int i=0; i<mss->NumTargets; i++)
1592 	{
1593 		*((ObjectID *)snb[i].name) = mss->Targets[i].ID;
1594 		request_messages[i]=mss->Targets[i].request;
1595 	}
1596 
1597 	bstt->request_messages=request_messages;
1598 
1599 	bstt->target_names = snb;
1600 
1601 	bstt->shape_num = list_pos;
1602 	*((ObjectID *)bstt->nameID) = ID;
1603 
1604 
1605 	AddToBehaviourList(name,ID, I_BehaviourBinarySwitch, (void*)bstt,list_pos);
1606 
1607 }
1608 
1609 
add_platlift(Object_Chunk * ob,int list_pos,AVP_Strategy_Chunk * asc)1610 static void add_platlift (Object_Chunk * ob, int list_pos, AVP_Strategy_Chunk * asc)
1611 {
1612 	PlatLiftStrategy* pls=(PlatLiftStrategy*)asc->Strategy;
1613 
1614 	PLATFORMLIFT_TOOLS_TEMPLATE* ptt=(PLATFORMLIFT_TOOLS_TEMPLATE*) PoolAllocateMem(sizeof(PLATFORMLIFT_TOOLS_TEMPLATE));
1615 
1616 	ptt->position.vx = (int)(ob->object_data.location.x * local_scale);
1617 	ptt->position.vy = (int)(ob->object_data.location.y * local_scale);
1618 	ptt->position.vz = (int)(ob->object_data.location.z * local_scale);
1619 
1620 	QUAT q;
1621 
1622 	q.quatx = (int) -(ob->object_data.orientation.x*ONE_FIXED);
1623 	q.quaty = (int) -(ob->object_data.orientation.y*ONE_FIXED);
1624 	q.quatz = (int) -(ob->object_data.orientation.z*ONE_FIXED);
1625 	q.quatw = (int) (ob->object_data.orientation.w*ONE_FIXED);
1626 
1627 
1628 	MATRIXCH m;
1629 
1630 	QuatToMat (&q, &m);
1631 
1632 	MatrixToEuler(&m, &ptt->orientation);
1633 
1634 	ptt->shapeIndex = list_pos;
1635 	*((ObjectID *)ptt->nameID) = ob->object_data.ID;
1636 	ptt->travel=0;
1637 
1638 	Object_Track_Chunk2* otc=(Object_Track_Chunk2*)ob->lookup_single_child("OBJTRAK2");
1639 	if(otc)
1640 	{
1641 		if(otc->num_sections==1)
1642 		{
1643 			ptt->travel=(int)((otc->sections[0].pivot_end.y-otc->sections[0].pivot_start.y)*local_scale);
1644 		}
1645 	}
1646 	else
1647 	{
1648 		GLOBALASSERT(0=="Platform lift must have a track");
1649 	}
1650 
1651 	setup_track_sound(ob,&ptt->start_sound,&ptt->sound,&ptt->end_sound);
1652 
1653 	if(pls->flags & PlatformLiftFlags_Disabled)
1654 		ptt->Enabled=FALSE;
1655 	else
1656 		ptt->Enabled=TRUE;
1657 
1658 	if(pls->flags & PlatformLiftFlags_OneUse)
1659 		ptt->OneUse=TRUE;
1660 	else
1661 		ptt->OneUse=FALSE;
1662 
1663 	AddToBehaviourList(ob->object_data.o_name,ob->object_data.ID, I_BehaviourPlatform, (void*)ptt,list_pos,0,ob->get_header()->flags);
1664 
1665 }
1666 
add_deathvolume(const char * name,AVP_Strategy_Chunk * asc,ObjectID ID)1667 static void add_deathvolume(const char* name,AVP_Strategy_Chunk* asc,ObjectID ID)
1668 {
1669 	DeathVolumeStrategy* dvs=(DeathVolumeStrategy*)asc->Strategy;
1670 
1671 	DEATH_VOLUME_TOOLS_TEMPLATE* dvtt=(DEATH_VOLUME_TOOLS_TEMPLATE*) PoolAllocateMem(sizeof(DEATH_VOLUME_TOOLS_TEMPLATE));
1672 
1673 	dvtt->volume_min=dvs->volume_min*local_scale;
1674 	dvtt->volume_max=dvs->volume_max*local_scale;
1675 	if(dvs->flags & DeathVolumeFlag_StartsOn)
1676 		dvtt->active=1;
1677 	else
1678 		dvtt->active=0;
1679 
1680 	if(dvs->flags & DeathVolumeFlag_CollisionNotRequired)
1681 		dvtt->collision_required=0;
1682 	else
1683 		dvtt->collision_required=1;
1684 
1685 	dvtt->damage_per_second = dvs->damage;
1686 
1687 	*(ObjectID*)&dvtt->nameID[0]=ID;
1688 
1689 
1690 	AddToBehaviourList(name,ID, I_BehaviourDeathVolume, (void*)dvtt);
1691 }
1692 
add_selfdestruct(const char * name,AVP_Strategy_Chunk * asc,ObjectID ID)1693 static void add_selfdestruct(const char* name,AVP_Strategy_Chunk* asc,ObjectID ID)
1694 {
1695 	SelfDestructStrategy* sds=(SelfDestructStrategy*)asc->Strategy;
1696 
1697 	SELF_DESTRUCT_TOOLS_TEMPLATE* sdtt=(SELF_DESTRUCT_TOOLS_TEMPLATE*) PoolAllocateMem(sizeof(SELF_DESTRUCT_TOOLS_TEMPLATE));
1698 
1699 	sdtt->timer=sds->timer<<16;
1700 
1701 	*(ObjectID*)&sdtt->nameID[0]=ID;
1702 
1703 
1704 	AddToBehaviourList(name,ID, I_BehaviourSelfDestruct, (void*)sdtt);
1705 }
1706 
add_message_strategy(const char * name,AVP_Strategy_Chunk * asc,ObjectID ID)1707 static void add_message_strategy(const char* name,AVP_Strategy_Chunk* asc,ObjectID ID)
1708 {
1709 	TextMessageStrategy* tms=(TextMessageStrategy*)asc->Strategy;
1710 	assert (tms->message_string>0 && tms->message_string<450);
1711 
1712 	MESSAGE_TOOLS_TEMPLATE* mtt=(MESSAGE_TOOLS_TEMPLATE*) PoolAllocateMem(sizeof(MESSAGE_TOOLS_TEMPLATE));
1713 
1714 	mtt->string_no=(TEXTSTRING_ID)((tms->message_string-1)+TEXTSTRING_LEVELMSG_001);
1715 	*(ObjectID*)&mtt->nameID[0]=ID;
1716 
1717 	if(tms->flags & TextMessageFlag_NotActiveAtStart)
1718 		mtt->active=FALSE;
1719 	else
1720 		mtt->active=TRUE;
1721 
1722 
1723 
1724 	AddToBehaviourList(name,ID, I_BehaviourMessage, (void*)mtt);
1725 
1726 }
1727 
1728 void setup_placed_light_data (LIGHTBLOCK * lPtr, Placed_Object_Light_Chunk * lc);
1729 
add_placed_light(Object_Chunk * ob,int list_pos,AVP_Strategy_Chunk * asc)1730 static void add_placed_light(Object_Chunk* ob,int list_pos,AVP_Strategy_Chunk* asc)
1731 {
1732 	SimpleStrategy * ss = (SimpleStrategy *)asc->Strategy;
1733 
1734 
1735 
1736 	TOOLS_DATA_PLACEDLIGHT* pltd=(TOOLS_DATA_PLACEDLIGHT*) PoolAllocateMem(sizeof(TOOLS_DATA_PLACEDLIGHT));
1737 
1738 	pltd->position.vx = (int)(ob->object_data.location.x * local_scale);
1739 	pltd->position.vy = (int)(ob->object_data.location.y * local_scale);
1740 	pltd->position.vz = (int)(ob->object_data.location.z * local_scale);
1741 
1742 	QUAT q;
1743 
1744 	q.quatx = (int) -(ob->object_data.orientation.x*ONE_FIXED);
1745 	q.quaty = (int) -(ob->object_data.orientation.y*ONE_FIXED);
1746 	q.quatz = (int) -(ob->object_data.orientation.z*ONE_FIXED);
1747 	q.quatw = (int) (ob->object_data.orientation.w*ONE_FIXED);
1748 
1749 
1750 	MATRIXCH m;
1751 
1752 	QuatToMat (&q, &m);
1753 
1754 	MatrixToEuler(&m, &pltd->orientation);
1755 
1756 	pltd->shapeIndex = list_pos;
1757 	pltd->mass = ss->mass/10;
1758 	if (!pltd->mass) pltd->mass = 1;
1759 	pltd->integrity = ss->integrity & 0xff;
1760 	*((ObjectID *)pltd->nameID) = ob->object_data.ID;
1761 
1762 	Placed_Object_Light_Chunk* lchunk=(Placed_Object_Light_Chunk*)ob->lookup_single_child("PLOBJLIT");
1763 	GLOBALASSERT(lchunk);
1764 
1765 	pltd->light=(LIGHTBLOCK*) PoolAllocateMem(sizeof(LIGHTBLOCK));
1766 
1767 	setup_placed_light_data(pltd->light,lchunk);
1768 
1769 	pltd->colour_red=((lchunk->light.up_colour>>16)&0xff)*257;
1770 	pltd->colour_green=((lchunk->light.up_colour>>8)&0xff)*257;
1771 	pltd->colour_blue=((lchunk->light.up_colour)&0xff)*257;
1772 	pltd->colour_diff_red=((lchunk->light.down_colour>>16)&0xff)*257;
1773 	pltd->colour_diff_green=((lchunk->light.down_colour>>8)&0xff)*257;
1774 	pltd->colour_diff_blue=((lchunk->light.down_colour)&0xff)*257;
1775 
1776 	pltd->colour_diff_red-=pltd->colour_red;
1777 	pltd->colour_diff_green-=pltd->colour_green;
1778 	pltd->colour_diff_blue-=pltd->colour_blue;
1779 
1780 	pltd->fade_up_time=(max(lchunk->light.fade_up_time,1)*ONE_FIXED)/1000;
1781 	pltd->fade_down_time=(max(lchunk->light.fade_down_time,1)*ONE_FIXED)/1000;
1782 	pltd->up_time=(max(lchunk->light.up_time,1)*ONE_FIXED)/1000;
1783 	pltd->down_time=(max(lchunk->light.down_time,1)*ONE_FIXED)/1000;
1784 	pltd->timer=(max(lchunk->light.start_time,1)*ONE_FIXED)/1000;
1785 
1786 	pltd->type=(LIGHT_TYPE)lchunk->light.light_type;
1787 	pltd->on_off_type=(LIGHT_ON_OFF_TYPE)lchunk->light.on_off_type;
1788 
1789 	if(lchunk->light.flags & PlacedLightFlag_On)
1790 	{
1791 		pltd->sequence=1;
1792 		pltd->on_off_state=Light_OnOff_On;
1793 
1794 	}
1795 	else
1796 	{
1797 		pltd->sequence=0;
1798 		pltd->on_off_state=Light_OnOff_Off;
1799 		//pltd->light->LightBright=0;
1800 	}
1801 
1802 	if(lchunk->light.flags & PlacedLightFlag_SwapColourBright)
1803 		pltd->swap_colour_and_brightness_alterations=1;
1804 	else
1805 		pltd->swap_colour_and_brightness_alterations=0;
1806 
1807 
1808 	if(pltd->type==Light_Type_Strobe)
1809 		pltd->state=Light_State_StrobeUp;
1810 	else if(pltd->type==Light_Type_Flicker)
1811 		pltd->state=Light_State_Flicker;
1812 	else
1813 		pltd->state=Light_State_Standard;
1814 
1815    	pltd->destruct_target_request=ss->target_request;
1816    	*(ObjectID*)pltd->destruct_target_ID=ss->targetID;
1817 
1818 	pltd->static_light=1;
1819 
1820 
1821 	AddToBehaviourList(ob->object_data.o_name,ob->object_data.ID, I_BehaviourPlacedLight, (void *) pltd,list_pos,0,ob->get_header()->flags);
1822 }
1823 
add_prox_door(Object_Chunk * ob,int shp1,int shp2,MODULE * mod,AVP_Strategy_Chunk * asc)1824 static void add_prox_door (Object_Chunk * ob, int shp1, int shp2, MODULE * mod,AVP_Strategy_Chunk* asc)
1825 {
1826 
1827 	PROX_DOOR_TOOLS_TEMPLATE * pdtt =(PROX_DOOR_TOOLS_TEMPLATE *) PoolAllocateMem(sizeof(PROX_DOOR_TOOLS_TEMPLATE));
1828 
1829 	pdtt->has_lock_target = No;
1830 	pdtt->door_opening_speed=1<<16;
1831 	pdtt->door_closing_speed=1<<17;
1832 	if(asc)
1833 	{
1834 		DoorStrategy * ds = (DoorStrategy *)asc->Strategy;
1835 		if(ds->DoorFlags & DoorFlag_Locked)
1836 			pdtt->door_is_locked=Yes;
1837 		else
1838 			pdtt->door_is_locked=No;
1839 
1840 		if(ds->DoorFlags & DoorFlag_Horizontal)
1841 		{
1842 			mod->m_flags|=MODULEFLAG_HORIZONTALDOOR;
1843 		}
1844 		if(ds->TimeToOpen)
1845 		{
1846 			pdtt->door_opening_speed=655360/ds->TimeToOpen;
1847 		}
1848 		if(ds->TimeToClose)
1849 		{
1850 			pdtt->door_closing_speed=655360/ds->TimeToClose;
1851 		}
1852 
1853 	}
1854 	else pdtt->door_is_locked=No;
1855 	pdtt->shape_open = shp1;
1856 	pdtt->shape_closed = shp2;
1857 	*((int *)pdtt->my_module.mref_name) = *((int *) mod->m_name);
1858 	*((ObjectID *)pdtt->nameID) = ob->object_data.ID;
1859 
1860 	AddToBehaviourList(ob->object_data.o_name,ob->object_data.ID, I_BehaviourProximityDoor, (void*)pdtt,shp1);
1861 
1862 
1863 
1864 }
1865 
1866 
add_lift_door(Object_Chunk * ob,int shape1,int shape2,MODULE * mod,AVP_Strategy_Chunk * asc)1867 static void add_lift_door (Object_Chunk * ob, int shape1, int shape2, MODULE * mod, AVP_Strategy_Chunk * asc)
1868 {
1869 
1870 	DoorStrategy * ds = (DoorStrategy *)asc->Strategy;
1871 
1872 	LIFT_DOOR_TOOLS_TEMPLATE * ldtt =(LIFT_DOOR_TOOLS_TEMPLATE *) PoolAllocateMem(sizeof( LIFT_DOOR_TOOLS_TEMPLATE));
1873 
1874 	ldtt->state = (ds->DoorFlags & DoorFlag_Open) ? I_door_open : I_door_closed;
1875 	*((int *)ldtt->my_module.mref_name) = *((int *)mod->m_name);
1876 	*((ObjectID *)ldtt->nameID) = ob->object_data.ID;
1877 	ldtt->shape_open = shape1;
1878 	ldtt->shape_closed = shape2;
1879 
1880 	if(ds->TimeToOpen)
1881 		ldtt->door_opening_speed=655360/ds->TimeToOpen;
1882 	else
1883 		ldtt->door_opening_speed=1<<16;
1884 
1885 	if(ds->TimeToClose)
1886 	 	ldtt->door_closing_speed=655360/ds->TimeToClose;
1887 	else
1888 		ldtt->door_closing_speed=1<<17;
1889 
1890 	AddToBehaviourList(ob->object_data.o_name,ob->object_data.ID, I_BehaviourLiftDoor, (void*)ldtt,shape1);
1891 
1892 }
1893 
1894 
1895 
add_switch_door(Object_Chunk * ob,int shape1,int shape2,MODULE * mod,AVP_Strategy_Chunk * asc)1896 static void add_switch_door (Object_Chunk * ob, int shape1, int shape2, MODULE * mod, AVP_Strategy_Chunk * asc)
1897 {
1898 
1899 	SwitchDoorStrategy * sds = (SwitchDoorStrategy*)asc->Strategy;
1900 
1901 	SWITCH_DOOR_TOOLS_TEMPLATE * sdtt =(SWITCH_DOOR_TOOLS_TEMPLATE *) PoolAllocateMem(sizeof(SWITCH_DOOR_TOOLS_TEMPLATE));
1902 
1903 	sdtt->state =I_door_closed;
1904 	*((int *)sdtt->myModule.mref_name) = *((int *)mod->m_name);
1905 	*((ObjectID *)sdtt->nameID) = ob->object_data.ID;
1906 	sdtt->shapeOpen = shape1;
1907 	sdtt->shapeClosed = shape2;
1908 	*(ObjectID*)sdtt->linkedDoorName=sds->AssocDoor;
1909 
1910 	AddToBehaviourList(ob->object_data.o_name,ob->object_data.ID, I_BehaviourSwitchDoor, (void*)sdtt,shape1);
1911 
1912 }
1913 
add_door(Object_Chunk * ob,int shape1,int shape2,MODULE * mod,AVP_Strategy_Chunk * asc)1914 static void add_door (Object_Chunk * ob, int shape1, int shape2, MODULE * mod, AVP_Strategy_Chunk * asc)
1915 {
1916 
1917 	DoorStrategy * ds = (DoorStrategy *)asc->Strategy;
1918 
1919 	if (ds->DoorFlags & DoorFlag_Lift)
1920 	{
1921 		add_lift_door (ob, shape1, shape2, mod, asc);
1922 	}
1923 	else if (ds->DoorFlags & DoorFlag_Proximity)
1924 	{
1925 		add_prox_door (ob, shape1, shape2, mod, asc);
1926 	}
1927 }
1928 
add_lift_object(Object_Chunk * ob,int list_pos,MODULE * mod,AVP_Strategy_Chunk * asc)1929 static void add_lift_object (Object_Chunk * ob, int list_pos, MODULE * mod, AVP_Strategy_Chunk * asc)
1930 {
1931 	LiftStrategy * ls = (LiftStrategy *)asc->Strategy;
1932 
1933 	ObjectID ControlID=ob->object_data.ID;
1934 	for(int i=0;i<ls->NumAssocLifts;i++)
1935 	{
1936 		ControlID=Minimum(ControlID,ls->AssocLifts[i]);
1937 	}
1938 	LIFT_TOOLS_TEMPLATE * ltt =(LIFT_TOOLS_TEMPLATE *) PoolAllocateMem(sizeof(LIFT_TOOLS_TEMPLATE));
1939 
1940 	*((ObjectID *)ltt->my_module_name) = ob->object_data.ID;
1941 	*((ObjectID *)ltt->call_switch_name) = ls->AssocCallSwitch;
1942 	*((ObjectID *)ltt->lift_door_name) = ls->AssocDoor;
1943 	*((ObjectID *)ltt->lift_floor_switch_name) = ls->AssocFloorSwitch;
1944 
1945 	ltt->environment = AvP.CurrentEnv;
1946 
1947 	ltt->num_floor = ls->Floor;
1948 
1949 	*((ObjectID *)ltt->control_sb_name)=ControlID;
1950 
1951 	ltt->controller = (ControlID==ob->object_data.ID);
1952 
1953 	ltt->num_stations = ls->NumAssocLifts +ls->NumExternalLifts +1;
1954 
1955 	ltt->lift_flags=ls->LiftFlags;
1956 
1957 	*((int *)ltt->my_module.mref_name) = *((int *)mod->m_name);
1958 	*((ObjectID *)ltt->nameID) = ob->object_data.ID;
1959 
1960 	ltt->orient=ls->Facing;
1961 
1962 	AddToBehaviourList(ob->object_data.o_name,ob->object_data.ID, I_BehaviourLift, (void*)ltt,list_pos);
1963 
1964 }
1965 
1966 
add_light_fx(Object_Chunk * ob,int list_pos,MODULE * mod,AVP_Strategy_Chunk * asc)1967 static void add_light_fx (Object_Chunk * ob,int list_pos, MODULE * mod, AVP_Strategy_Chunk * asc)
1968 {
1969 	LightingStrategy * ls = (LightingStrategy *)asc->Strategy;
1970 
1971 	LIGHT_FX_TOOLS_TEMPLATE * lfxtt =(LIGHT_FX_TOOLS_TEMPLATE *) PoolAllocateMem(sizeof(LIGHT_FX_TOOLS_TEMPLATE));
1972 
1973 	lfxtt->light_data = ls->LightData;
1974 
1975 	*((ObjectID *)lfxtt->nameID) = ob->object_data.ID;
1976 	*((int *)lfxtt->my_module.mref_name) = *((int *)mod->m_name);
1977 
1978 	AddToBehaviourList(ob->object_data.o_name,ob->object_data.ID, I_BehaviourLightFX, (void*)lfxtt,list_pos);
1979 
1980 }
1981 
deal_with_module_object(Object_Chunk * ob,int shape1,int AnimationShape,int shape2,MODULE * mod)1982 void deal_with_module_object(Object_Chunk * ob, int shape1, int AnimationShape, int shape2, MODULE * mod)
1983 {
1984 	Chunk * pChunk = ob->lookup_single_child("OBJPRJDT");
1985 
1986 	AVP_Strategy_Chunk * asc = 0;
1987 
1988 	Object_Project_Data_Chunk * opdc = 0;
1989 
1990 	if (pChunk)
1991 	{
1992 		opdc = (Object_Project_Data_Chunk *)pChunk;
1993 
1994 		pChunk = opdc->lookup_single_child("AVPSTRAT");
1995 
1996 		if (pChunk)
1997 		{
1998 			asc = (AVP_Strategy_Chunk *)pChunk;
1999 		}
2000 	}
2001 
2002 	if (asc)
2003 	{
2004 		assert (asc->Strategy != 0);
2005 
2006 		switch (asc->Strategy->StrategyType)
2007 		{
2008 			case StratLift:
2009 				add_lift_object(ob, shape1, mod, asc);
2010 				break;
2011 
2012 			case StratDoor:
2013 				if (shape2 != -1)
2014 				{
2015 					add_door (ob, shape1, shape2, mod, asc);
2016 				}
2017 				break;
2018 			case StratSwitchDoor:
2019 				if (shape2 != -1)
2020 				{
2021 					add_switch_door (ob, shape1, shape2, mod, asc);
2022 				}
2023 				break;
2024 
2025 			case StratLighting:
2026 			{
2027 				add_light_fx (ob,shape1, mod, asc);
2028 				break;
2029 			}
2030 
2031 			default:
2032 				assert (0); // Strategy not recognised
2033 				break;
2034 		}
2035 	}
2036 	else
2037 	{
2038 
2039 		if (shape2 != -1)
2040 		{
2041 			add_prox_door (ob, shape1, shape2, mod,0);
2042 		}
2043 		else if(AnimationShape!=-1)
2044 		{
2045 			add_simple_animation (ob, AnimationShape, mod);
2046 		}
2047 
2048 	}
2049 }
2050 
2051 
add_videoscreen(Object_Chunk * ob,int list_pos,AVP_Strategy_Chunk * asc)2052 static void add_videoscreen(Object_Chunk * ob, int list_pos, AVP_Strategy_Chunk * asc)
2053 {
2054 	SimpleStrategy * ss = (SimpleStrategy *)asc->Strategy;
2055 
2056 	TOOLS_DATA_VIDEO_SCREEN* tdvs=(TOOLS_DATA_VIDEO_SCREEN*) PoolAllocateMem(sizeof(TOOLS_DATA_VIDEO_SCREEN));
2057 
2058 	tdvs->position.vx = (int)(ob->object_data.location.x * local_scale);
2059 	tdvs->position.vy = (int)(ob->object_data.location.y * local_scale);
2060 	tdvs->position.vz = (int)(ob->object_data.location.z * local_scale);
2061 
2062 	QUAT q;
2063 
2064 	q.quatx = (int) -(ob->object_data.orientation.x*ONE_FIXED);
2065 	q.quaty = (int) -(ob->object_data.orientation.y*ONE_FIXED);
2066 	q.quatz = (int) -(ob->object_data.orientation.z*ONE_FIXED);
2067 	q.quatw = (int) (ob->object_data.orientation.w*ONE_FIXED);
2068 
2069 
2070 	MATRIXCH m;
2071 
2072 	QuatToMat (&q, &m);
2073 
2074 	MatrixToEuler(&m, &tdvs->orientation);
2075 
2076 	tdvs->shapeIndex = list_pos;
2077 	tdvs->integrity = ss->integrity & 0xff;
2078 	*((ObjectID *)tdvs->nameID) = ob->object_data.ID;
2079 
2080    	//copy destruction target info
2081    	tdvs->destruct_target_request=ss->target_request;
2082    	*(ObjectID*)tdvs->destruct_target_ID=ss->targetID;
2083 
2084 
2085 	Object_Alternate_Locations_Chunk* loc_chunk = (Object_Alternate_Locations_Chunk*) ob->lookup_single_child("ALTLOCAT");
2086 
2087 	AddToBehaviourList(ob->object_data.o_name,ob->object_data.ID, I_BehaviourVideoScreen, (void *) tdvs,list_pos,loc_chunk,ob->get_header()->flags);
2088 }
2089 
add_newsimpleobject(Object_Chunk * ob,int list_pos,AVP_Strategy_Chunk * asc)2090 static void add_newsimpleobject(Object_Chunk * ob, int list_pos, AVP_Strategy_Chunk * asc)
2091 {
2092 // test for video screen which is type ReservedForJohn
2093 
2094 	SimpleStrategy * ss = (SimpleStrategy *)asc->Strategy;
2095 
2096 	if (ss->Type == IOT_ReservedForJohn)
2097 	{
2098 		add_videoscreen (ob, list_pos, asc);
2099 		return;
2100 	}
2101 
2102 	if(ob->lookup_single_child("PLOBJLIT"))
2103 	{
2104 		add_placed_light(ob,list_pos,asc);
2105 		return;
2106 	}
2107 
2108 
2109 	TOOLS_DATA_INANIMATEOBJECT* tdio=(TOOLS_DATA_INANIMATEOBJECT*) PoolAllocateMem(sizeof(TOOLS_DATA_INANIMATEOBJECT));
2110 
2111 	tdio->position.vx = (int)(ob->object_data.location.x * local_scale);
2112 	tdio->position.vy = (int)(ob->object_data.location.y * local_scale);
2113 	tdio->position.vz = (int)(ob->object_data.location.z * local_scale);
2114 
2115 	QUAT q;
2116 
2117 	q.quatx = (int) -(ob->object_data.orientation.x*ONE_FIXED);
2118 	q.quaty = (int) -(ob->object_data.orientation.y*ONE_FIXED);
2119 	q.quatz = (int) -(ob->object_data.orientation.z*ONE_FIXED);
2120 	q.quatw = (int) (ob->object_data.orientation.w*ONE_FIXED);
2121 
2122 
2123 	MATRIXCH m;
2124 
2125 	QuatToMat (&q, &m);
2126 
2127 	MatrixToEuler(&m, &tdio->orientation);
2128 
2129 	tdio->typeId = (INANIMATEOBJECT_TYPE)ss->Type;
2130 	tdio->subType = ss->ExtraData;
2131 	tdio->shapeIndex = list_pos;
2132 	tdio->mass = ss->mass/10;
2133 	if (!tdio->mass) tdio->mass = 1;
2134 	tdio->integrity = ss->integrity & 0xff;
2135 	*((ObjectID *)tdio->nameID) = ob->object_data.ID;
2136 
2137 
2138 
2139 	tdio->explosionType=(ss->flags & SimStratFlag_ExplosionMask)>>SimStratFlag_ExplosionShift;
2140 
2141 
2142 	if(ss->targetID.id1 || ss->targetID.id2)
2143 	{
2144    		tdio->triggering_event=ss->flags;
2145    		tdio->event_request=ss->target_request;
2146    		*(ObjectID*)tdio->event_target_ID=ss->targetID;
2147 	}
2148 	else
2149 	{
2150 		tdio->triggering_event=0;
2151 	}
2152 
2153 	if(tdio->typeId==IOT_Ammo)
2154 	{
2155 		//need to convert the subtype number
2156 		switch(tdio->subType)
2157 		{
2158 			case 0:
2159 				tdio->subType=AMMO_10MM_CULW;
2160 				break;
2161 			case 2:
2162 				tdio->subType=AMMO_SMARTGUN;
2163 				break;
2164 			case 3:
2165 				tdio->subType=AMMO_FLAMETHROWER;
2166 				break;
2167 			case 5:
2168 				tdio->subType=AMMO_SADAR_TOW;
2169 				break;
2170 			case 6:
2171 				tdio->subType=AMMO_GRENADE;
2172 				break;
2173 			case 7:
2174 				tdio->subType=AMMO_MINIGUN;
2175 				break;
2176 			case 8:
2177 				tdio->subType=AMMO_PULSE_GRENADE;
2178 				break;
2179 			case 9:
2180 				tdio->subType=AMMO_PRED_RIFLE;
2181 				break;
2182 		}
2183 	}
2184 
2185 	Object_Alternate_Locations_Chunk* loc_chunk = (Object_Alternate_Locations_Chunk*) ob->lookup_single_child("ALTLOCAT");
2186 
2187 	AddToBehaviourList(ob->object_data.o_name,ob->object_data.ID, I_BehaviourInanimateObject, (void *) tdio,list_pos,loc_chunk,ob->get_header()->flags);
2188 
2189 }
2190 
add_simpleobject(Object_Chunk * ob,int list_pos,AVP_Strategy_Chunk * asc)2191 static void add_simpleobject(Object_Chunk * ob, int list_pos, AVP_Strategy_Chunk * asc)
2192 {
2193 // test for sentry gun which is type ReservedForJohn
2194 
2195 	if (asc->Strategy->Type == IOT_ReservedForJohn)
2196 	{
2197 		//add_autogun (ob, list_pos, asc->Strategy->ExtraData);
2198 		return;
2199 	}
2200 
2201 
2202 	TOOLS_DATA_INANIMATEOBJECT* tdio=(TOOLS_DATA_INANIMATEOBJECT*) PoolAllocateMem(sizeof(TOOLS_DATA_INANIMATEOBJECT));
2203 
2204 	tdio->position.vx = (int)(ob->object_data.location.x * local_scale);
2205 	tdio->position.vy = (int)(ob->object_data.location.y * local_scale);
2206 	tdio->position.vz = (int)(ob->object_data.location.z * local_scale);
2207 
2208 	QUAT q;
2209 
2210 	q.quatx = (int) -(ob->object_data.orientation.x*ONE_FIXED);
2211 	q.quaty = (int) -(ob->object_data.orientation.y*ONE_FIXED);
2212 	q.quatz = (int) -(ob->object_data.orientation.z*ONE_FIXED);
2213 	q.quatw = (int) (ob->object_data.orientation.w*ONE_FIXED);
2214 
2215 
2216 	MATRIXCH m;
2217 
2218 	QuatToMat (&q, &m);
2219 
2220 	MatrixToEuler(&m, &tdio->orientation);
2221 
2222 	tdio->typeId = (INANIMATEOBJECT_TYPE)asc->Strategy->Type;
2223 	tdio->subType = asc->Strategy->ExtraData;
2224 	tdio->shapeIndex = list_pos;
2225 	tdio->mass = 5;
2226 	tdio->integrity = DEFAULT_OBJECT_INTEGRITY;
2227 	tdio->explosionType=0;
2228 	*((ObjectID *)tdio->nameID) = ob->object_data.ID;
2229 
2230 	Object_Alternate_Locations_Chunk* loc_chunk = (Object_Alternate_Locations_Chunk*) ob->lookup_single_child("ALTLOCAT");
2231 
2232 	AddToBehaviourList(ob->object_data.o_name,ob->object_data.ID, I_BehaviourInanimateObject, (void *) tdio,list_pos,loc_chunk,ob->get_header()->flags);
2233 
2234 }
2235 
deal_with_placed_object(Object_Chunk * ob,int shape1,int)2236 void deal_with_placed_object(Object_Chunk * ob, int shape1, int /*AnimationShape*/)
2237 {
2238 	db_logf3(("Dealing with object %s , shape %d",ob->object_data.o_name,shape1));
2239 	Chunk * pChunk = ob->lookup_single_child("OBJPRJDT");
2240 
2241 	AVP_Strategy_Chunk * asc = 0;
2242 
2243 	Object_Project_Data_Chunk * opdc = 0;
2244 
2245 	if (pChunk)
2246 	{
2247 		opdc = (Object_Project_Data_Chunk *)pChunk;
2248 
2249 		pChunk = opdc->lookup_single_child("AVPSTRAT");
2250 
2251 		if (pChunk)
2252 		{
2253 			asc = (AVP_Strategy_Chunk *)pChunk;
2254 		}
2255 	}
2256 
2257 	int obflags=ob->get_header()->flags;
2258 	if (asc)
2259 	{
2260 		assert (asc->Strategy != 0);
2261 
2262 		switch (asc->Strategy->StrategyType)
2263 		{
2264 			case StratBinSwitch:
2265 				add_binswitch (ob->object_data.o_name,asc,ob->object_data.ID,ob,shape1);
2266 				break;
2267 
2268 			case StratAreaSwitch: //(Area Switch derived from Multi Switch)
2269 			case StratMultiSwitch:
2270 				add_multiswitch (ob->object_data.o_name,asc,ob->object_data.ID,ob,shape1);
2271 				break;
2272 
2273 			case StratLinkSwitch:
2274 				add_linkswitch (ob->object_data.o_name,asc,ob->object_data.ID,ob,shape1);
2275 				break;
2276 
2277 			case StratPlatLift :
2278 				add_platlift(ob,shape1,asc);
2279 				break;
2280 
2281 			case StratSimpleObject:
2282 		 		if(obflags & OBJECT_FLAG_PCLOAD)
2283 				{
2284 					if((AvP.PlayerType==I_Marine && (obflags & OBJECT_FLAG_AVPGAMEMODEMARINE))||
2285 					   (AvP.PlayerType==I_Predator && (obflags & OBJECT_FLAG_AVPGAMEMODEPREDATOR))||
2286 					   (AvP.PlayerType==I_Alien && (obflags & OBJECT_FLAG_AVPGAMEMODEALIEN)))
2287 					{
2288 						add_simpleobject (ob, shape1,asc);
2289 					}
2290 		 		}
2291 				break;
2292 
2293 			case StratNewSimpleObject:
2294 		 		if(obflags & OBJECT_FLAG_PCLOAD)
2295 				{
2296 					if((AvP.PlayerType==I_Marine && (obflags & OBJECT_FLAG_AVPGAMEMODEMARINE))||
2297 					   (AvP.PlayerType==I_Predator && (obflags & OBJECT_FLAG_AVPGAMEMODEPREDATOR))||
2298 					   (AvP.PlayerType==I_Alien && (obflags & OBJECT_FLAG_AVPGAMEMODEALIEN)))
2299 					{
2300 						add_newsimpleobject (ob, shape1,asc);
2301 					}
2302 		 		}
2303 				break;
2304 
2305 
2306 			case StratTrack :
2307 			case StratTrackDestruct :
2308 				add_trackobject(ob,shape1,asc);
2309 				break;
2310 
2311 			case StratFan :
2312 				add_fan(ob,shape1,asc);
2313 				break;
2314 
2315 			default:
2316 				assert (0); // Strategy not recognised
2317 				break;
2318 		}
2319 	}
2320 	else
2321 	{
2322 #if 0
2323 		if(AnimationShape!=-1)
2324 		{
2325 			add_simple_animation (ob, AnimationShape, 0);
2326 		}
2327 		else
2328 #endif
2329 		{
2330 		 	if(obflags & OBJECT_FLAG_PCLOAD)
2331 			{
2332 				if((AvP.PlayerType==I_Marine && (obflags & OBJECT_FLAG_AVPGAMEMODEMARINE))||
2333 				   (AvP.PlayerType==I_Predator && (obflags & OBJECT_FLAG_AVPGAMEMODEPREDATOR))||
2334 				   (AvP.PlayerType==I_Alien && (obflags & OBJECT_FLAG_AVPGAMEMODEALIEN)))
2335 				{
2336 					add_default_object(ob,shape1);
2337 				}
2338 		 	}
2339 		}
2340 	}
2341 	db_logf3(("Finished with object %s , shape %d",ob->object_data.o_name,shape1));
2342 }
2343 
add_alien(AVP_Generator_Chunk * agc)2344 static void add_alien(AVP_Generator_Chunk * agc)
2345 {
2346 
2347 	TOOLS_DATA_ALIEN* tda=(TOOLS_DATA_ALIEN*) PoolAllocateMem(sizeof(TOOLS_DATA_ALIEN));
2348 	tda->position.vx = (int)(agc->location.x * local_scale);
2349 	tda->position.vy = (int)(agc->location.y * local_scale);
2350 	tda->position.vz = (int)(agc->location.z * local_scale);
2351 
2352 	//tda->shapeIndex = GetLoadedShapeMSL("Alien");
2353 	tda->shapeIndex = 0;
2354 
2355 	tda->start_inactive=(agc->flags & AVPGENFLAG_GENERATORINACTIVE)!=0;
2356 
2357 	tda->starteuler.EulerX=0;
2358 	tda->starteuler.EulerY=agc->orientation & 4095;
2359 	tda->starteuler.EulerZ=0;
2360 
2361 
2362 	switch (agc->type)
2363 	{
2364 		case 1:
2365 			tda->type=AT_Standard;
2366 			break;
2367 
2368 		case 5:
2369 			tda->type=AT_Predalien;
2370 			break;
2371 
2372 		case 8:
2373 			tda->type=AT_Praetorian;
2374 			break;
2375 
2376 		default :
2377 			tda->type=AT_Standard;
2378 	}
2379 
2380 	//look for extra strategy stuff
2381 	for(int i=0;i<SB_NAME_LENGTH;i++) tda->death_target_ID[i]=0;
2382 	AVP_Generator_Extra_Data_Chunk* agedc=agc->get_extra_data_chunk();
2383 	AVP_Strategy_Chunk* asc=0;
2384 	if(agedc)
2385 	{
2386 		Chunk * pChunk = agedc->lookup_single_child("AVPSTRAT");
2387 		if(pChunk)
2388 		{
2389 			asc=(AVP_Strategy_Chunk*) pChunk;
2390 
2391 			if(asc->Strategy)
2392 			{
2393 				switch(asc->Strategy->StrategyType)
2394 				{
2395 					case StratEnemy :
2396 						{
2397 							EnemyStrategy* es=(EnemyStrategy*)asc->Strategy;
2398 
2399 							*(ObjectID*)&tda->death_target_ID[0]=es->DeathTarget;
2400 						}
2401 						break;
2402 
2403 				}
2404 			}
2405 		}
2406 	}
2407 
2408 
2409 	ObjectID ID=agc->CalculateID();
2410 	*(ObjectID*)&tda->nameID[0]=ID;
2411 
2412 	AddToBehaviourList(agc->name,ID, I_BehaviourAlien, (void *) tda,0,agc->get_alternate_locations_chunk(),agc->flags);
2413 }
2414 
2415 extern int ConvertObjectIndexToPathIndex(int path_index,int object_index);
2416 
2417 
add_marine(AVP_Generator_Chunk * agc)2418 static void add_marine(AVP_Generator_Chunk * agc)
2419 {
2420 	TOOLS_DATA_MARINE* tdm=(TOOLS_DATA_MARINE*) PoolAllocateMem(sizeof(TOOLS_DATA_MARINE));
2421 
2422 	tdm->position.vx = (int)(agc->location.x * local_scale);
2423 	tdm->position.vy = (int)(agc->location.y * local_scale);
2424 	tdm->position.vz = (int)(agc->location.z * local_scale);
2425 
2426 	EULER euler;
2427 	euler.EulerX=0;
2428 	euler.EulerY=agc->orientation & 4095;
2429 	euler.EulerZ=0;
2430 
2431 	get_marine_facing_point(tdm->position,euler,tdm->facing_point);
2432 
2433 
2434 	tdm->shapeIndex = 0;
2435 
2436 	tdm->textureID=agc->textureID;
2437 
2438 
2439 	ObjectID ID=agc->CalculateID();
2440 	*(ObjectID*)&tdm->nameID[0]=ID;
2441 
2442 	tdm->Mission=MM_Wait_Then_Wander;
2443 	tdm->path=-1;
2444  	tdm->stepnumber=-1;
2445 
2446 	//look for extra strategy stuff
2447 	for(int i=0;i<SB_NAME_LENGTH;i++) tdm->death_target_ID[i]=0;
2448 	AVP_Generator_Extra_Data_Chunk* agedc=agc->get_extra_data_chunk();
2449 	AVP_Strategy_Chunk* asc=0;
2450 
2451 	if(agedc)
2452 	{
2453 		Chunk * pChunk = agedc->lookup_single_child("AVPSTRAT");
2454 		if(pChunk)
2455 		{
2456 			asc=(AVP_Strategy_Chunk*) pChunk;
2457 
2458 			if(asc->Strategy)
2459 			{
2460 				switch(asc->Strategy->StrategyType)
2461 				{
2462 					case StratEnemy :
2463 						{
2464 							EnemyStrategy* es=(EnemyStrategy*)asc->Strategy;
2465 
2466 							switch (es->MissionType)
2467 							{
2468 								case 1:
2469 									tdm->Mission=MM_Wander;
2470 									break;
2471 								case 2:
2472 									tdm->Mission=MM_Guard;
2473 									break;
2474 								case 3:
2475 									tdm->Mission=MM_NonCom;
2476 									break;
2477 								case 4:
2478 									tdm->Mission=MM_LocalGuard;
2479 									break;
2480 								case 5:
2481 									tdm->Mission=MM_Pathfinder;
2482 									tdm->path=es->ExtraMissionData &0xffff;
2483 									tdm->stepnumber=ConvertObjectIndexToPathIndex(tdm->path,es->ExtraMissionData>>16);
2484 									if(tdm->stepnumber==-1)
2485 									{
2486 										LOGDXFMT(("Error setting up path for marine %s\n",agc->name));
2487 										GLOBALASSERT(0);
2488 									}
2489 									break;
2490 							}
2491 
2492 							*(ObjectID*)&tdm->death_target_ID[0]=es->DeathTarget;
2493 
2494 							tdm->death_target_request=es->target_request;
2495 
2496 						}
2497 						break;
2498 				}
2499 			}
2500 		}
2501 	}
2502 
2503 	switch (agc->sub_type)
2504 	{
2505 		case 0:	//pulse rifle
2506 			tdm->marine_type=MNPCW_PulseRifle;
2507 			break;
2508 
2509 		case 5:	//pistol marine
2510 			tdm->marine_type=MNPCW_PistolMarine;
2511 			break;
2512 
2513 		case 10: //smartgun
2514 			tdm->marine_type=MNPCW_Smartgun;
2515 			break;
2516 
2517 		case 20://grenade launcher
2518 			tdm->marine_type=MNPCW_GrenadeLauncher;
2519 			break;
2520 
2521 		case 30://shotgun 1
2522 		case 31://shotgun 2
2523 		case 32://shotgun 3
2524 			tdm->marine_type=MNPCW_MShotgun;
2525 			break;
2526 
2527 		case 80://Molotov
2528 			tdm->marine_type=MNPCW_MMolotov;
2529 			break;
2530 
2531 		case 40://pistol 1
2532 		case 41://pistol 2
2533 		case 90://Scientist1
2534 		case 91://Scientist2
2535 			tdm->marine_type=MNPCW_MPistol;
2536 			break;
2537 
2538 		case 50://flamethrower
2539 			tdm->marine_type=MNPCW_Flamethrower;
2540 			break;
2541 
2542 		case 60://sadar
2543 			tdm->marine_type=MNPCW_SADAR;
2544 			break;
2545 
2546 		case 70://Minigun
2547 			tdm->marine_type=MNPCW_Minigun;
2548 	   		break;
2549 
2550 		case 100://Civilian flamer
2551 			tdm->marine_type=MNPCW_MFlamer;
2552 			break;
2553 
2554 		case 110://Civilian unarmed
2555 			tdm->marine_type=MNPCW_MUnarmed;
2556 			break;
2557 
2558 		case 120://android
2559 			tdm->marine_type=MNPCW_Android;
2560 			break;
2561 
2562 		default:
2563 			tdm->marine_type=MNPCW_PulseRifle;
2564 			break;
2565 	}
2566 
2567 
2568 	AddToBehaviourList(agc->name,ID, I_BehaviourMarine, (void *) tdm,0,agc->get_alternate_locations_chunk(),agc->flags);
2569 }
2570 
2571 
add_predator(AVP_Generator_Chunk * agc)2572 static void add_predator(AVP_Generator_Chunk * agc)
2573 {
2574 
2575 	TOOLS_DATA_PREDATOR* tdp=(TOOLS_DATA_PREDATOR*) PoolAllocateMem(sizeof(TOOLS_DATA_PREDATOR));
2576 	tdp->position.vx = (int)(agc->location.x * local_scale);
2577 	tdp->position.vy = (int)(agc->location.y * local_scale);
2578 	tdp->position.vz = (int)(agc->location.z * local_scale);
2579 
2580 	#if 0
2581 	switch (agc->textureID)
2582 	{
2583 		case 1:
2584 			tdp->shapeIndex = GetLoadedShapeMSL("PHead1");
2585 			break;
2586 		case 2:
2587 			tdp->shapeIndex = GetLoadedShapeMSL("PHead2");
2588 			break;
2589 		case 3:
2590 			tdp->shapeIndex = GetLoadedShapeMSL("PHead3");
2591 			break;
2592 		case 4:
2593 			tdp->shapeIndex = GetLoadedShapeMSL("PHead4");
2594 			break;
2595 		default :
2596 			tdp->shapeIndex = GetLoadedShapeMSL("fred");	/* patrick 8/7/96 */
2597 			break;
2598 	}
2599 	#endif
2600 	tdp->predator_number=agc->textureID;
2601 	tdp->shapeIndex = 0;
2602 
2603 	switch((agc->sub_type)&7)
2604 	{
2605 		case 0:
2606 			tdp->primary=PNPCW_Pistol;
2607 			break;
2608 		case 1:
2609 			tdp->primary=PNPCW_Wristblade;
2610 			break;
2611 		case 2:
2612 			tdp->primary=PNPCW_PlasmaCaster;
2613 			break;
2614 		case 3:
2615 			tdp->primary=PNPCW_Staff;
2616 			break;
2617 		default :
2618 			tdp->primary=PNPCW_Pistol;
2619 			break;
2620 
2621 	}
2622 	switch((agc->sub_type>>3)&7)
2623 	{
2624 		case 0:
2625 			tdp->secondary=PNPCW_Pistol;
2626 			break;
2627 		case 1:
2628 			tdp->secondary=PNPCW_Wristblade;
2629 			break;
2630 		case 2:
2631 			tdp->secondary=PNPCW_PlasmaCaster;
2632 			break;
2633 		case 3:
2634 			tdp->secondary=PNPCW_Staff;
2635 			break;
2636 		default :
2637 			tdp->secondary=PNPCW_Pistol;
2638 			break;
2639 
2640 	}
2641 	//make sure primary and secondary weapons are different
2642 	if(tdp->primary==tdp->secondary)
2643 	{
2644 		if(tdp->primary==PNPCW_Wristblade)
2645 			tdp->secondary=PNPCW_Pistol;
2646 		else
2647 			tdp->secondary=PNPCW_Wristblade;
2648 	}
2649 
2650 	tdp->path=-1;
2651 	tdp->stepnumber=-1;
2652 
2653 	for(int i=0;i<SB_NAME_LENGTH;i++) tdp->death_target_ID[i]=0;
2654 	//look for extra strategy stuff
2655 	AVP_Generator_Extra_Data_Chunk* agedc=agc->get_extra_data_chunk();
2656 	AVP_Strategy_Chunk* asc=0;
2657 
2658 	if(agedc)
2659 	{
2660 		Chunk * pChunk = agedc->lookup_single_child("AVPSTRAT");
2661 		if(pChunk)
2662 		{
2663 			asc=(AVP_Strategy_Chunk*) pChunk;
2664 
2665 			if(asc->Strategy)
2666 			{
2667 				switch(asc->Strategy->StrategyType)
2668 				{
2669 					case StratEnemy :
2670 						{
2671 							EnemyStrategy* es=(EnemyStrategy*)asc->Strategy;
2672 
2673 							*(ObjectID*)&tdp->death_target_ID[0]=es->DeathTarget;
2674 							tdp->death_target_request=es->target_request;
2675 							switch (es->MissionType)
2676 							{
2677 								case 1:
2678 									tdp->path=es->ExtraMissionData &0xffff;
2679 									tdp->stepnumber=ConvertObjectIndexToPathIndex(tdp->path,es->ExtraMissionData>>16);
2680 									if(tdp->stepnumber==-1)
2681 									{
2682 										LOGDXFMT(("Error setting up path for predator %s\n",agc->name));
2683 										GLOBALASSERT(0);
2684 									}
2685 
2686 									break;
2687 							}
2688 
2689 
2690 						}
2691 						break;
2692 				}
2693 			}
2694 		}
2695 	}
2696 
2697 
2698 
2699 
2700 	ObjectID ID=agc->CalculateID();
2701 	*(ObjectID*)&tdp->nameID[0] = ID;
2702 
2703 	if(agc->flags & AVPGENFLAG_GENERATORINACTIVE)
2704 		AddToBehaviourList(agc->name,ID, I_BehaviourDormantPredator, (void *) tdp,0,agc->get_alternate_locations_chunk(),agc->flags);
2705 	else
2706 		AddToBehaviourList(agc->name,ID, I_BehaviourPredator, (void *) tdp,0,agc->get_alternate_locations_chunk(),agc->flags);
2707 }
2708 
add_queen(AVP_Generator_Chunk * agc)2709 static void add_queen(AVP_Generator_Chunk * agc)
2710 {
2711 
2712 	TOOLS_DATA_QUEEN* tdq=(TOOLS_DATA_QUEEN*) PoolAllocateMem(sizeof(TOOLS_DATA_QUEEN));
2713 	tdq->position.vx = (int)(agc->location.x * local_scale);
2714 	tdq->position.vy = (int)(agc->location.y * local_scale);
2715 	tdq->position.vz = (int)(agc->location.z * local_scale);
2716 
2717 	tdq->shapeIndex = 0;
2718 
2719 	ObjectID ID=agc->CalculateID();
2720 	*(ObjectID*)&tdq->nameID[0]=ID;
2721 
2722 
2723 	//look for extra strategy stuff
2724 	for(int i=0;i<SB_NAME_LENGTH;i++) tdq->death_target_ID[i]=0;
2725 	tdq->death_target_request=0;
2726 
2727 	AVP_Generator_Extra_Data_Chunk* agedc=agc->get_extra_data_chunk();
2728 	AVP_Strategy_Chunk* asc=0;
2729 	if(agedc)
2730 	{
2731 		Chunk * pChunk = agedc->lookup_single_child("AVPSTRAT");
2732 		if(pChunk)
2733 		{
2734 			asc=(AVP_Strategy_Chunk*) pChunk;
2735 
2736 			if(asc->Strategy)
2737 			{
2738 				switch(asc->Strategy->StrategyType)
2739 				{
2740 					case StratEnemy :
2741 						{
2742 							EnemyStrategy* es=(EnemyStrategy*)asc->Strategy;
2743 
2744 							*(ObjectID*)&tdq->death_target_ID[0]=es->DeathTarget;
2745 							tdq->death_target_request=es->target_request;
2746 						}
2747 						break;
2748 
2749 				}
2750 			}
2751 		}
2752 	}
2753 
2754 
2755 	AddToBehaviourList(agc->name,ID, I_BehaviourQueenAlien, (void *) tdq,0,agc->get_alternate_locations_chunk(),agc->flags);
2756 
2757 }
2758 
add_hugger(AVP_Generator_Chunk * agc)2759 static void add_hugger(AVP_Generator_Chunk * agc)
2760 {
2761 
2762 	TOOLS_DATA_FACEHUGGER* tdfh =(TOOLS_DATA_FACEHUGGER*) PoolAllocateMem(sizeof(TOOLS_DATA_FACEHUGGER));
2763 
2764 	tdfh->position.vx = (int)(agc->location.x * local_scale);
2765 	tdfh->position.vy = (int)(agc->location.y * local_scale);
2766 	tdfh->position.vz = (int)(agc->location.z * local_scale);
2767 
2768 	//tdfh->shapeIndex = GetLoadedShapeMSL("Facehug");
2769 	tdfh->shapeIndex = 0;
2770 
2771 	tdfh->startInactive=(agc->flags & AVPGENFLAG_GENERATORINACTIVE)!=0;
2772 
2773 	ObjectID ID=agc->CalculateID();
2774 	*(ObjectID*)&tdfh->nameID[0]=ID;
2775 
2776 
2777 	for(int i=0;i<SB_NAME_LENGTH;i++) tdfh->death_target_ID[i]=0;
2778 
2779 	//look for extra strategy stuff
2780 	AVP_Generator_Extra_Data_Chunk* agedc=agc->get_extra_data_chunk();
2781 	AVP_Strategy_Chunk* asc=0;
2782 
2783 	if(agedc)
2784 	{
2785 		Chunk * pChunk = agedc->lookup_single_child("AVPSTRAT");
2786 		if(pChunk)
2787 		{
2788 			asc=(AVP_Strategy_Chunk*) pChunk;
2789 
2790 			if(asc->Strategy)
2791 			{
2792 				switch(asc->Strategy->StrategyType)
2793 				{
2794 					case StratEnemy :
2795 						{
2796 							EnemyStrategy* es=(EnemyStrategy*)asc->Strategy;
2797 
2798 							*(ObjectID*)&tdfh->death_target_ID[0]=es->DeathTarget;
2799 							tdfh->death_target_request=es->target_request;
2800 
2801 						}
2802 						break;
2803 				}
2804 			}
2805 		}
2806 	}
2807 
2808 
2809 	AddToBehaviourList(agc->name,ID, I_BehaviourFaceHugger, (void *) tdfh,0,agc->get_alternate_locations_chunk(),agc->flags);
2810 }
2811 
add_autogun(AVP_Generator_Chunk * agc)2812 static void add_autogun(AVP_Generator_Chunk * agc)
2813 {
2814 	AUTOGUN_TOOLS_TEMPLATE* att=(AUTOGUN_TOOLS_TEMPLATE*) PoolAllocateMem(sizeof(AUTOGUN_TOOLS_TEMPLATE));
2815 	att->position.vx = (int)(agc->location.x * local_scale);
2816 	att->position.vy = (int)(agc->location.y * local_scale);
2817 	att->position.vz = (int)(agc->location.z * local_scale);
2818 
2819 	att->shapenum = 0;
2820 
2821 	att->startInactive=(agc->flags & AVPGENFLAG_GENERATORINACTIVE)!=0;
2822 
2823 	att->orientation.EulerX=0;
2824 	att->orientation.EulerY=agc->orientation & 4095;
2825 	att->orientation.EulerZ=0;
2826 
2827 	att->ammo=(agc->extra1<<8)+agc->extra2;
2828 	if(att->ammo>=30000) att->ammo=0x7fffffff;
2829 
2830 	//look for extra strategy stuff
2831 	for(int i=0;i<SB_NAME_LENGTH;i++) att->death_target_ID[i]=0;
2832 	att->death_target_request=0;
2833 
2834 	AVP_Generator_Extra_Data_Chunk* agedc=agc->get_extra_data_chunk();
2835 	AVP_Strategy_Chunk* asc=0;
2836 	if(agedc)
2837 	{
2838 		Chunk * pChunk = agedc->lookup_single_child("AVPSTRAT");
2839 		if(pChunk)
2840 		{
2841 			asc=(AVP_Strategy_Chunk*) pChunk;
2842 
2843 			if(asc->Strategy)
2844 			{
2845 				switch(asc->Strategy->StrategyType)
2846 				{
2847 					case StratEnemy :
2848 						{
2849 							EnemyStrategy* es=(EnemyStrategy*)asc->Strategy;
2850 
2851 							*(ObjectID*)&att->death_target_ID[0]=es->DeathTarget;
2852 							att->death_target_request=es->target_request;
2853 						}
2854 						break;
2855 
2856 				}
2857 			}
2858 		}
2859 	}
2860 
2861 
2862 	ObjectID ID=agc->CalculateID();
2863 	*(ObjectID*)&att->nameID[0]=ID;
2864 
2865 	AddToBehaviourList(agc->name,ID,I_BehaviourAutoGun, (void *) att,0,agc->get_alternate_locations_chunk(),agc->flags);
2866 }
2867 
2868 
add_xenoborg(AVP_Generator_Chunk * agc)2869 static void add_xenoborg(AVP_Generator_Chunk * agc)
2870 {
2871 
2872 	TOOLS_DATA_XENO* tdx=(TOOLS_DATA_XENO*) PoolAllocateMem(sizeof(TOOLS_DATA_XENO));
2873 
2874 	tdx->position.vx = (int)(agc->location.x * local_scale);
2875 	tdx->position.vy = (int)(agc->location.y * local_scale);
2876 	tdx->position.vz = (int)(agc->location.z * local_scale);
2877 
2878 	tdx->shapeIndex = 0;
2879 
2880 	tdx->starteuler.EulerX=0;
2881 	tdx->starteuler.EulerY=agc->orientation & 4095;
2882 	tdx->starteuler.EulerZ=0;
2883 
2884 	if(agc->extra1)
2885 		tdx->UpTime=(int)agc->extra1*5;
2886 	else
2887 		tdx->UpTime=20;//default value
2888 	if(agc->extra2)
2889 		tdx->ModuleRange=agc->extra2;
2890 	else
2891 		tdx->ModuleRange=7;//default value
2892 
2893 	//look for extra strategy stuff
2894 	for(int i=0;i<SB_NAME_LENGTH;i++) tdx->death_target_ID[i]=0;
2895 	tdx->death_target_request=0;
2896 	AVP_Generator_Extra_Data_Chunk* agedc=agc->get_extra_data_chunk();
2897 	AVP_Strategy_Chunk* asc=0;
2898 	if(agedc)
2899 	{
2900 		Chunk * pChunk = agedc->lookup_single_child("AVPSTRAT");
2901 		if(pChunk)
2902 		{
2903 			asc=(AVP_Strategy_Chunk*) pChunk;
2904 
2905 			if(asc->Strategy)
2906 			{
2907 				switch(asc->Strategy->StrategyType)
2908 				{
2909 					case StratEnemy :
2910 						{
2911 							EnemyStrategy* es=(EnemyStrategy*)asc->Strategy;
2912 
2913 							*(ObjectID*)&tdx->death_target_ID[0]=es->DeathTarget;
2914 							tdx->death_target_request=es->target_request;
2915 						}
2916 						break;
2917 
2918 				}
2919 			}
2920 		}
2921 	}
2922 
2923 
2924 	ObjectID ID=agc->CalculateID();
2925 	*(ObjectID*)&tdx->nameID[0]=ID;
2926 
2927 
2928 	AddToBehaviourList(agc->name,ID, I_BehaviourXenoborg, (void *) tdx,0,agc->get_alternate_locations_chunk(),agc->flags);
2929 
2930 }
2931 
2932 extern "C"{
2933 extern void SetHiveParamaters(int enemytype,int max,int genpermin,int deltagenpermin,int time);
2934 };
2935 
setup_generators(Environment_Data_Chunk * envd)2936 void setup_generators (Environment_Data_Chunk * envd)
2937 {
2938 	//first setup the global generator paramaters
2939 	Chunk * pChunk = envd->lookup_single_child("GLOGENDC");
2940 
2941 	int generator_enemy;
2942 
2943 	if(pChunk)
2944 	{
2945 		Global_Generator_Data_Chunk* ggdc=(Global_Generator_Data_Chunk*)pChunk;
2946 		switch(ggdc->EnemyGenerated)
2947 		{
2948 			case Generate_Aliens :
2949 				generator_enemy=I_BehaviourAlien;
2950 				break;
2951 			case Generate_Marines :
2952 				generator_enemy=I_BehaviourMarine;
2953 				break;
2954 			default :
2955 				GLOBALASSERT("Invalid enemy type"==0);
2956 
2957 		}
2958 		SetHiveParamaters(generator_enemy,ggdc->MaxNPCSOnLevel,ggdc->NPCSPerMinute,ggdc->NPCAcceleration,ggdc->HiveStateChangeTime*ONE_FIXED);
2959 
2960 	}
2961 	else
2962 	{
2963 		generator_enemy=I_BehaviourAlien;
2964 		SetHiveParamaters(generator_enemy,25,4,2,60*ONE_FIXED);
2965 	}
2966 
2967 
2968 
2969 	Special_Objects_Chunk * soc = 0;
2970 
2971  	pChunk = envd->lookup_single_child ("SPECLOBJ");
2972 	if (pChunk)
2973 	{
2974 		soc = (Special_Objects_Chunk *)pChunk;
2975 	}
2976 		// and alien generator objects
2977 
2978 	if (soc)
2979 	{
2980 		{
2981 			List<Chunk *> cl;
2982 			soc->lookup_child("AVPGENER",cl);
2983 			for (LIF<Chunk *> cli(&cl); !cli.done(); cli.next())
2984 			{
2985 				AVP_Generator_Chunk * agc = (AVP_Generator_Chunk *)cli();
2986 
2987 				if (agc->type)
2988 				{
2989 
2990 					#if 0
2991 					if(AvP.PlayerType==I_Alien && (agc->flags & AVPGENFLAG_AVPGAMEMODEALIEN)||
2992 					   AvP.PlayerType==I_Marine && (agc->flags & AVPGENFLAG_AVPGAMEMODEMARINE)||
2993 					   AvP.PlayerType==I_Predator && (agc->flags & AVPGENFLAG_AVPGAMEMODEPREDATOR))
2994 					#endif
2995 					{
2996 						//note : only aliens can appear in a network game
2997 						switch (agc->type)
2998 						{
2999 							case 1:
3000 								add_alien(agc);
3001 								break;
3002 							case 2:
3003 								if(AvP.Network == I_No_Network)
3004 									add_predator(agc);
3005 								break;
3006 
3007 							case 3:
3008 								if(AvP.Network == I_No_Network)
3009 									add_hugger(agc);
3010 								break;
3011 							case 4:
3012 								if(AvP.Network == I_No_Network)
3013 									add_xenoborg(agc);
3014 								break;
3015 							case 5:
3016 								add_alien(agc);//add_alien also does predaliens
3017 								break;
3018 							case 6:
3019 								if(AvP.Network == I_No_Network)
3020 									add_queen(agc);
3021 								break;
3022 							case 7:
3023 								if(AvP.Network == I_No_Network)
3024 									add_marine(agc);
3025 								break;
3026 							case 8:
3027 								add_alien(agc); //add_alien will also do pretorian guards
3028 								break;
3029 
3030 							case 9:
3031 								if(AvP.Network == I_No_Network)
3032 									add_autogun(agc);
3033 								break;
3034 
3035 							default:
3036 
3037 								break;
3038 						}
3039 
3040 
3041 					}
3042 				}
3043 				else
3044 				{
3045 					#if 0
3046 					//check to see if generator is flagged for this game mode
3047 
3048 					if(AvP.PlayerType==I_Alien && (agc->flags & AVPGENFLAG_AVPGAMEMODEALIEN)||
3049 					   AvP.PlayerType==I_Marine && (agc->flags & AVPGENFLAG_AVPGAMEMODEMARINE)||
3050 					   AvP.PlayerType==I_Predator && (agc->flags & AVPGENFLAG_AVPGAMEMODEPREDATOR))
3051 					#endif
3052 					//see if generator is a multiplayer start position
3053 					if(agc->flags & AVPGENFLAG_MULTIPLAYERSTART)
3054 					{
3055 						continue;
3056 					}
3057 
3058 
3059 					{
3060 						ObjectID ID=agc->CalculateID();
3061 
3062 
3063 						GENERATOR_BLOCK* tdg = (GENERATOR_BLOCK*) PoolAllocateMem(sizeof(GENERATOR_BLOCK));
3064 						memset(tdg,0,sizeof(GENERATOR_BLOCK));
3065 
3066 						tdg->Position.vx = (int)(agc->location.x * local_scale);
3067 						tdg->Position.vy = (int)(agc->location.y * local_scale);
3068 						tdg->Position.vz = (int)(agc->location.z * local_scale);
3069 						tdg->Active=!(agc->flags & AVPGENFLAG_GENERATORINACTIVE);
3070 
3071 						tdg->GenerationRate=1;
3072 						tdg->GenerationRateIncrease=0;
3073 						tdg->use_own_rate_values=0;
3074 
3075 						tdg->MaxGenNPCs=0;
3076 						tdg->use_own_max_npc=0;
3077 
3078 						tdg->path=-1;
3079 						tdg->stepnumber=-1;
3080 
3081 						AVP_Generator_Extended_Settings_Chunk* setting=agc->get_extended_settings();
3082 						if(setting)
3083 						{
3084 							/*The weightings are in the same order in generator_block and avp_generator_weighting,
3085 							and I can't be bothered to copy them individually*/
3086 							int* copyfrom = (int*) &setting->weights->PulseMarine_Wt;
3087 							int* copyto =  (int*) &tdg->PulseMarine_Wt;
3088 
3089 							for(int i=0;i<15;i++)
3090 							{
3091 								copyto[i]=copyfrom[i];
3092 								tdg->WeightingTotal+=copyto[i];
3093 							}
3094 
3095 							if(agc->flags & AVPGENFLAG_USEOWNRATE)
3096 							{
3097 								tdg->GenerationRate=setting->GenerationRate;
3098 								tdg->GenerationRateIncrease=setting->GenRateIncrease;
3099 								tdg->use_own_rate_values=1;
3100 							}
3101 							if(agc->flags & AVPGENFLAG_USEOWNLIMIT)
3102 							{
3103 								tdg->MaxGenNPCs=setting->GenLimit;
3104 								tdg->use_own_max_npc=1;
3105 							}
3106 
3107 						}
3108 
3109 						if(tdg->WeightingTotal==0)
3110 						{
3111 							//set genrator to generate level's default creature
3112 							if(generator_enemy==I_BehaviourAlien)
3113 							{
3114 								tdg->Alien_Wt=1;
3115 								tdg->WeightingTotal=1;
3116 							}
3117 							else
3118 							{
3119 								tdg->PulseMarine_Wt=1;
3120 								tdg->WeightingTotal=1;
3121 							}
3122 
3123 						}
3124 
3125 
3126 						/*See if generator has extra strategy data, currently just used for producing path following creatures*/
3127 
3128 						AVP_Generator_Extra_Data_Chunk* agedc=agc->get_extra_data_chunk();
3129 
3130 						if(agedc)
3131 						{
3132 							AVP_Strategy_Chunk* asc = (AVP_Strategy_Chunk*) agedc->lookup_single_child("AVPSTRAT");
3133 							if(asc)
3134 							{
3135 
3136 								if(asc->Strategy)
3137 								{
3138 									switch(asc->Strategy->StrategyType)
3139 									{
3140 										case StratGenerator :
3141 											{
3142 											    GeneratorStrategy* gs=(GeneratorStrategy*)asc->Strategy;
3143 
3144 												if(gs->MissionType==1)
3145 												{
3146 													tdg->path=gs->ExtraMissionData &0xffff;
3147 													tdg->stepnumber=ConvertObjectIndexToPathIndex(tdg->path,gs->ExtraMissionData>>16);
3148 													if(tdg->stepnumber==-1)
3149 													{
3150 														LOGDXFMT(("Error setting up path for generator %s\n",agc->name));
3151 														GLOBALASSERT(0);
3152 													}
3153 												}
3154 
3155 
3156 											}
3157 											break;
3158 									}
3159 								}
3160 							}
3161 						}
3162 
3163 
3164 						AddToBehaviourList(agc->name,ID, I_BehaviourGenerator, (void *) tdg,0,agc->get_alternate_locations_chunk(),agc->flags);
3165 					}
3166 				}
3167 
3168 			}
3169 		}
3170 
3171 		if(AvP.Network != I_No_Network)
3172 		{
3173 			//setup multiplayer start positions
3174 			numMarineStartPos=0;
3175 			numAlienStartPos=0;
3176 			numPredatorStartPos=0;
3177 
3178 			marineStartPositions=0;
3179 			alienStartPositions=0;
3180 			predatorStartPositions=0;
3181 
3182 			//go through the list to find the number of each type of start location
3183 			List<Chunk *> cl;
3184 			soc->lookup_child("AVPGENER",cl);
3185 
3186 			LIF<Chunk *> cli(&cl);
3187 			for (; !cli.done(); cli.next())
3188 			{
3189 				AVP_Generator_Chunk * agc = (AVP_Generator_Chunk *)cli();
3190 				if(agc->type) continue;
3191 				if(!(agc->flags & AVPGENFLAG_MULTIPLAYERSTART))
3192 				{
3193 					continue;
3194 				}
3195 
3196 
3197 				if(agc->flags & AVPGENFLAG_AVPGAMEMODEALIEN) numAlienStartPos++;
3198 				if(agc->flags & AVPGENFLAG_AVPGAMEMODEMARINE) numMarineStartPos++;
3199 				if(agc->flags & AVPGENFLAG_AVPGAMEMODEPREDATOR) numPredatorStartPos++;
3200 			}
3201 
3202 			if(numMarineStartPos)
3203 			{
3204 				marineStartPositions=(MULTIPLAYER_START*) PoolAllocateMem(sizeof(MULTIPLAYER_START)*numMarineStartPos);
3205 			}
3206 			if(numPredatorStartPos)
3207 			{
3208 				predatorStartPositions=(MULTIPLAYER_START*) PoolAllocateMem(sizeof(MULTIPLAYER_START)*numPredatorStartPos);
3209 			}
3210 			if(numAlienStartPos)
3211 			{
3212 				alienStartPositions=(MULTIPLAYER_START*) PoolAllocateMem(sizeof(MULTIPLAYER_START)*numAlienStartPos);
3213 			}
3214 
3215 			int mpos=0;
3216 			int apos=0;
3217 			int ppos=0;
3218 
3219 			//go through the list a second time setting up the positions
3220 			for(cli.restart();!cli.done();cli.next())
3221 			{
3222 				AVP_Generator_Chunk * agc = (AVP_Generator_Chunk *)cli();
3223 				if(agc->type) continue;
3224 				if(!(agc->flags & AVPGENFLAG_MULTIPLAYERSTART))
3225 				{
3226 					continue;
3227 				}
3228 
3229 				MULTIPLAYER_START start_pos;
3230 				start_pos.location.vx = (int)(agc->location.x * local_scale);
3231 				start_pos.location.vy = (int)(agc->location.y * local_scale);
3232 				start_pos.location.vz = (int)(agc->location.z * local_scale);
3233 
3234 				start_pos.orientation.EulerX=0;
3235 				start_pos.orientation.EulerY=agc->orientation & 4095;
3236 				start_pos.orientation.EulerZ=0;
3237 
3238 				if(agc->flags & AVPGENFLAG_AVPGAMEMODEALIEN) alienStartPositions[apos++]=start_pos;
3239 				if(agc->flags & AVPGENFLAG_AVPGAMEMODEMARINE) marineStartPositions[mpos++]=start_pos;
3240 				if(agc->flags & AVPGENFLAG_AVPGAMEMODEPREDATOR) predatorStartPositions[ppos++]=start_pos;
3241 			}
3242 		}
3243 	}
3244 
3245 }
3246 
3247 typedef struct mission_setup
3248 {
3249 	AVP_Strategy_Chunk* asc;
3250 	int order_number;
3251 	ObjectID ID;
3252 	MissionObjective* mission;
3253 }MISSION_SETUP;
3254 
3255 static List<MISSION_SETUP *> mos_list;
3256 
add_mission_to_list(AVP_Strategy_Chunk * asc,ObjectID id)3257 static void add_mission_to_list(AVP_Strategy_Chunk * asc,ObjectID id)
3258 {
3259 	MISSION_SETUP* ms=new MISSION_SETUP;
3260 
3261 	ms->asc=asc;
3262 	ms->ID=id;
3263 	ms->mission=0;
3264 
3265 	MissionObjectiveStrategy * mos = (MissionObjectiveStrategy *)asc->Strategy;
3266 	ms->order_number=mos->mission_number;
3267 
3268 	for(LIF<MISSION_SETUP*> mlif(&mos_list);!mlif.done();mlif.next())
3269 	{
3270 		if(mlif()->order_number>ms->order_number)
3271 		{
3272 			mos_list.add_entry_before(ms,mlif());
3273 			return;
3274 		}
3275 	}
3276 	mos_list.add_entry(ms);
3277 }
3278 
SetupMissionObjectives()3279 void SetupMissionObjectives()
3280 {
3281 	LIF<MISSION_SETUP*> mlif(&mos_list);
3282 
3283 	for(; !mlif.done(); mlif.next())
3284 	{
3285 		MissionObjectiveStrategy * mos=(MissionObjectiveStrategy*) mlif()->asc->Strategy;
3286 		assert (mos->mission_description_string>=0 && mos->mission_description_string<450);
3287 		assert (mos->mission_complete_string>=0 && mos->mission_complete_string<450);
3288 
3289 		TEXTSTRING_ID desc_string;
3290 		if(mos->mission_description_string==0)
3291 			desc_string=TEXTSTRING_BLANK;
3292 		else
3293 			desc_string=(TEXTSTRING_ID)((mos->mission_description_string-1)+TEXTSTRING_LEVELMSG_001);
3294 
3295 		TEXTSTRING_ID complete_string;
3296 		if(mos->mission_complete_string==0)
3297 			complete_string=TEXTSTRING_BLANK;
3298 		else
3299 			complete_string=(TEXTSTRING_ID)((mos->mission_complete_string-1)+TEXTSTRING_LEVELMSG_001);
3300 
3301 		MissionObjectiveState m_state;
3302 
3303 		if(mos->flags & MissionFlag_Visible)
3304 		{
3305 			if (mos->flags & MissionFlag_CurrentlyPossible)
3306 		 		m_state=MOS_VisibleUnachieved;
3307 			else
3308 		 		m_state=MOS_VisibleUnachievedNotPossible;
3309 		}
3310 		else if (mos->flags & MissionFlag_CurrentlyPossible)
3311 		{
3312 			m_state=MOS_HiddenUnachieved;
3313 		}
3314 		else
3315 		  	m_state=MOS_HiddenUnachievedNotPossible;
3316 
3317 		MissionObjective* mission;
3318 
3319 		/* KJL 22:50:21 02/08/98 - set any additional effect of completing the mission */
3320 		switch(mos->mission_completion_effect)
3321 		{
3322 			default: // fall through to 'no effect' if effect not yet catered for
3323 			case MCE_None:
3324 				mission = new MissionObjective(desc_string,m_state,complete_string,MissionFX_None);
3325 				break;
3326 			case MCE_CompleteLevel:
3327 				mission = new MissionObjective(desc_string,m_state,complete_string,MissionFX_CompletesLevel);
3328 				break;
3329 		}
3330 
3331 		mlif()->mission=mission;
3332 
3333 		MISSION_COMPLETE_TOOLS_TEMPLATE* mctt=(MISSION_COMPLETE_TOOLS_TEMPLATE*) PoolAllocateMem(sizeof(MISSION_COMPLETE_TOOLS_TEMPLATE));
3334 		mctt->mission_objective_ptr=mission;
3335 		*(ObjectID*)&mctt->nameID[0]=mlif()->ID;
3336 
3337 		AddToBehaviourList(0,mlif()->ID, I_BehaviourMissionComplete, (void*)mctt,-1);
3338 	}
3339 
3340 	//now set up the mission alterations
3341 	for(mlif.restart();!mlif.done();mlif.next())
3342 	{
3343 		MissionObjectiveStrategy * mos=(MissionObjectiveStrategy*) mlif()->asc->Strategy;
3344 
3345 		for(int i=0;i<mos->num_mission_targets;i++)
3346 		{
3347 			//find the mission referred to
3348 			for(LIF<MISSION_SETUP*> mlif2(&mos_list);!mlif2.done();mlif2.next())
3349 			{
3350 				if(mlif2()->ID==mos->mission_targets->target_mission)
3351 				{
3352 					mlif()->mission->AddMissionAlteration(mlif2()->mission,mos->mission_targets->effect_on_target);
3353 					break;
3354 				}
3355 			}
3356 
3357 		}
3358 
3359 	}
3360 
3361 	while(mos_list.size())
3362 	{
3363 		delete mos_list.first_entry();
3364 		mos_list.delete_first_entry();
3365 	}
3366 }
3367 
3368 
3369 
setup_light_data(LIGHTBLOCK * lPtr,Light_Chunk * lc)3370 void setup_light_data (LIGHTBLOCK * lPtr, Light_Chunk * lc)
3371 {
3372 	/* KJL 14:42:42 20/02/98 - this function has been updated;
3373 	many things have been removed from the lightblock structure */
3374 
3375 	lPtr->LightFlags = lc->light.engine_light_flags | LFlag_PreLitSource
3376 										 | LFlag_AbsPos | LFlag_WasNotAllocated
3377 										 | LFlag_AbsLightDir | LFlag_CosAtten; // Forcing attenuation
3378 
3379 	lPtr->LightType = LightType_PerVertex;
3380 
3381 	lPtr->LightWorld.vx = (int)(lc->light.location.x * local_scale);
3382 	lPtr->LightWorld.vy = (int)(lc->light.location.y * local_scale);
3383 	lPtr->LightWorld.vz = (int)(lc->light.location.z * local_scale);
3384 
3385 	lPtr->LightBright = (int)(lc->light.brightness * 1.0);
3386 	lPtr->LightBrightStore = (int)(lc->light.brightness * 1.0);
3387 
3388 	/* KJL 10:57:57 9/24/97 - colour scales - these take the values 0 to 65536 */
3389 	lPtr->RedScale = ((lc->light.colour>>16)&255)*257;
3390 	lPtr->GreenScale = ((lc->light.colour>>8)&255)*257;
3391 	lPtr->BlueScale = ((lc->light.colour)&255)*257;
3392 
3393 	lPtr->LightRange = (int)((lc->light.range * 1.0) * local_scale);
3394 
3395 	if (lc->light.local_light_flags & LOFlag_NoPreLight)
3396 	{
3397 		lPtr->LightFlags &= ~LFlag_PreLitSource;
3398 	}
3399 
3400 }
3401 
setup_placed_light_data(LIGHTBLOCK * lPtr,Placed_Object_Light_Chunk * lc)3402 void setup_placed_light_data (LIGHTBLOCK * lPtr, Placed_Object_Light_Chunk * lc)
3403 {
3404 	/* KJL 14:42:42 20/02/98 - this function has been updated;
3405 	many things have been removed from the lightblock structure */
3406 
3407 	lPtr->LightFlags = lc->light.engine_light_flags | LFlag_WasNotAllocated
3408 										 | LFlag_AbsLightDir | LFlag_CosAtten; // Forcing attenuation
3409 
3410 	if(lc->light.flags & PlacedLightFlag_NoSpecular)
3411 	{
3412 		lPtr->LightFlags|=LFlag_NoSpecular;
3413 	}
3414 
3415 	lPtr->LightType = LightType_PerVertex;
3416 
3417 	lPtr->LightWorld.vx = 0;
3418 	lPtr->LightWorld.vy = 0;
3419 	lPtr->LightWorld.vz = 0;
3420 
3421 	lPtr->LightBright = (int)(lc->light.brightness * 1.0);
3422 	lPtr->LightBrightStore = (int)(lc->light.brightness * 1.0);
3423 
3424 	/* KJL 10:57:57 9/24/97 - colour scales - these take the values 0 to 65536 */
3425 	lPtr->RedScale = ((lc->light.up_colour>>16)&255)*257;
3426 	lPtr->GreenScale = ((lc->light.up_colour>>8)&255)*257;
3427 	lPtr->BlueScale = ((lc->light.up_colour)&255)*257;
3428 
3429 	lPtr->LightRange = (int)((lc->light.range * 1.0) * local_scale);
3430 
3431 }
3432 
SetUpRunTimeLights()3433 void SetUpRunTimeLights ()
3434 {
3435 	// go through the list of modules adding lights
3436 
3437 	Environment_Data_Chunk * edc = 0;
3438 	Light_Set_Chunk * lsc = 0;
3439 
3440 	Chunk * pChunk = Env_Chunk->lookup_single_child("REBENVDT");
3441 
3442 	if (pChunk)
3443 	{
3444 		edc = (Environment_Data_Chunk *)pChunk;
3445 
3446 		List<Chunk *> cl;
3447 		edc->lookup_child("LIGHTSET",cl);
3448 
3449 		while (cl.size())
3450 		{
3451 			Light_Set_Chunk * ls = (Light_Set_Chunk *)cl.first_entry();
3452 
3453 			Chunk * pChunk2 = ls->lookup_single_child("LTSETHDR");
3454 			if (pChunk2)
3455 			{
3456 				if (!strncmp(light_set_name, ((Light_Set_Header_Chunk *)pChunk2)->light_set_name, 8))
3457 				{
3458 					lsc = ls;
3459 					break;
3460 				}
3461 			}
3462 
3463 			cl.delete_first_entry();
3464 		}
3465 
3466 	}
3467 
3468 	if (!lsc)
3469 	{
3470 		return;
3471 	}
3472 
3473 	pChunk = lsc->lookup_single_child("AMBIENCE");
3474 
3475 	if (pChunk)
3476 	{
3477 		GlobalAmbience = (chnk_playcam_vdb.SVDB_Ambience = ((Lighting_Ambience_Chunk *)pChunk)->ambience);
3478 
3479  		VIEWDESCRIPTORBLOCK *VDBPtr = ActiveVDBList[0];
3480 
3481 		if (VDBPtr)
3482 		{
3483 			VDBPtr->VDB_Ambience = GlobalAmbience;
3484 		}
3485 	}
3486 
3487 	List<Chunk *> cl;
3488 	lsc->lookup_child ("STDLIGHT",cl);
3489 	LIF<Chunk *> cli(&cl);
3490 
3491 
3492 	MODULE ** m_arrayPtr = MainScene.sm_marray;
3493 
3494 	while (*m_arrayPtr)
3495 	{
3496 		List<Light_Chunk *> lights_for_this_module;
3497 
3498 		MODULE * this_mod = *m_arrayPtr++;
3499 
3500 		if (this_mod->m_flags & m_flag_infinite)
3501 		{
3502 			continue;
3503 		}
3504 
3505 		for (cli.restart(); !cli.done(); cli.next())
3506 		{
3507 			Light_Chunk * lc = (Light_Chunk *)cli();
3508 
3509 			// try to throw away light
3510 			if (!(lc->light.local_light_flags & LOFlag_Runtime))
3511 			{
3512 				continue;
3513 			}
3514 
3515 			if (lc->light_added_to_module)
3516 			{
3517 				continue;
3518 			}
3519 
3520 			if ((lc->light.location.x * local_scale) > (this_mod->m_world.vx + this_mod->m_maxx))
3521 				continue;
3522 
3523 			if ((lc->light.location.x * local_scale) < (this_mod->m_world.vx + this_mod->m_minx))
3524 				continue;
3525 
3526 			if ((lc->light.location.y * local_scale) > (this_mod->m_world.vy + this_mod->m_maxy))
3527 				continue;
3528 
3529 			if ((lc->light.location.y * local_scale) < (this_mod->m_world.vy + this_mod->m_miny))
3530 				continue;
3531 
3532 			if ((lc->light.location.z * local_scale) > (this_mod->m_world.vz + this_mod->m_maxz))
3533 				continue;
3534 
3535 			if ((lc->light.location.z * local_scale) < (this_mod->m_world.vz + this_mod->m_minz))
3536 				continue;
3537 
3538 			// light in module
3539 
3540 			lc->light_added_to_module = TRUE;
3541 
3542 			lights_for_this_module.add_entry(lc);
3543 
3544 		}
3545 
3546 		this_mod->m_numlights = lights_for_this_module.size();
3547 
3548 		assert (lights_for_this_module.size() <= MaxObjectLights);
3549 
3550 		if (lights_for_this_module.size())
3551 		{
3552 			this_mod->m_lightarray = (LIGHTBLOCK *) PoolAllocateMem (sizeof(LIGHTBLOCK)*(lights_for_this_module.size()));
3553 			if (!this_mod->m_lightarray)
3554 			{
3555 				memoryInitialisationFailure = 1;
3556 				return;
3557 			}
3558 
3559 			LIGHTBLOCK * lPtr = this_mod->m_lightarray;
3560 
3561 			for (LIF<Light_Chunk *> lci(&lights_for_this_module); !lci.done(); lci.next(), lPtr++)
3562 			{
3563 				setup_light_data (lPtr, lci());
3564 			}
3565 		}
3566 		else
3567 		{
3568 			this_mod->m_lightarray = 0;
3569 		}
3570 	}
3571 }
3572 #if 0
3573 void SetupExternalLift(AVP_External_Strategy_Chunk* aesc)
3574 {
3575 	LiftStrategy* ls=(LiftStrategy*)aesc->Strategy;
3576 
3577 	ObjectID ControlID={0x7fffffff,0x7fffffff};
3578 	for(int i=0;i<ls->NumExternalLifts;i++)
3579 	{
3580 		if(ls->ExternalLifts[i].EnvNum==aesc->ThisEnvNum)
3581 		{
3582 	  		ControlID=Minimum(ControlID,ls->ExternalLifts[i].LiftID);
3583 		}
3584 	}
3585 
3586 
3587 	LIFT_TOOLS_TEMPLATE * ltt = new LIFT_TOOLS_TEMPLATE;
3588 
3589 	*((ObjectID *)ltt->my_module_name) = aesc->ObjID;
3590 	*((ObjectID *)ltt->call_switch_name) = ls->AssocCallSwitch;
3591 	*((ObjectID *)ltt->lift_door_name) = ls->AssocDoor;
3592 	*((ObjectID *)ltt->lift_floor_switch_name) = ls->AssocFloorSwitch;
3593 
3594 	ltt->environment = aesc->ExtEnvNum-1;
3595 
3596 	ltt->num_floor = ls->Floor;
3597 
3598 	*((ObjectID *)ltt->control_sb_name)=ControlID;
3599 
3600 	ltt->controller = 0;
3601 
3602 	ltt->num_stations = ls->NumAssocLifts + ls->NumExternalLifts+1;
3603 
3604 	ltt->lift_flags=ls->LiftFlags;
3605 
3606 	*((ObjectID *)ltt->nameID) = aesc->ObjID;
3607 
3608 	ltt->orient=ls->Facing;
3609 	if((ls->LiftFlags & LiftFlag_Airlock) || (ls->LiftFlags & LiftFlag_ExitOtherSide))
3610 		ltt->orient=(ltt->orient+2) % 4;
3611 
3612 	ltt_list.add_entry(ltt);
3613 }
3614 #endif
3615 
DealWithExternalObjectStategies(Environment_Data_Chunk * envd)3616 void DealWithExternalObjectStategies (Environment_Data_Chunk * envd)
3617 {
3618 	List<Chunk*> chlist;
3619 	#if 0
3620 	envd->lookup_child("AVPEXSTR",chlist);
3621 	for(LIF<Chunk*> slif(&chlist);!slif.done();slif.next())
3622 	{
3623 		AVP_External_Strategy_Chunk* aesc=(AVP_External_Strategy_Chunk*) slif();
3624 		if(aesc->Strategy)
3625 		{
3626 			switch(aesc->Strategy->StrategyType)
3627 			{
3628 				case StratLift :
3629 					SetupExternalLift(aesc);
3630 					break;
3631 			}
3632 		}
3633 	}
3634 	#endif
3635 
3636 	Chunk * pChunk = envd->lookup_single_child("SPECLOBJ");
3637 	if(pChunk)
3638 	{
3639 		List<Chunk *> chlist;
3640 		((Chunk_With_Children*)pChunk)->lookup_child("VIOBJECT",chlist);
3641 		for(LIF<Chunk*> chlif(&chlist);!chlif.done();chlif.next())
3642 		{
3643 			Virtual_Object_Chunk* voc=(Virtual_Object_Chunk*)chlif();
3644 			Chunk * pChunk2=voc->lookup_single_child("AVPSTRAT");
3645 			if(!pChunk2)continue;
3646 			AVP_Strategy_Chunk* asc=(AVP_Strategy_Chunk*)pChunk2;
3647 
3648 			pChunk2=voc->lookup_single_child("VOBJPROP");
3649 			if(!pChunk2)continue;
3650 			Virtual_Object_Properties_Chunk* vopc=(Virtual_Object_Properties_Chunk*)pChunk2;
3651 
3652 			if(asc->Strategy)
3653 			{
3654 				switch(asc->Strategy->StrategyType)
3655 				{
3656 					case StratAreaSwitch: //(Area Switch derived from Multi Switch)
3657 					case StratMultiSwitch:
3658 						add_multiswitch (vopc->name,asc,vopc->ID);
3659 						break;
3660 					case StratBinSwitch:
3661 						add_binswitch (vopc->name,asc,vopc->ID);
3662 						break;
3663 					case StratLinkSwitch:
3664 						add_linkswitch (vopc->name,asc,vopc->ID);
3665 						break;
3666 
3667 					case StratMessage:
3668 						add_message_strategy (vopc->name,asc,vopc->ID);
3669 						break;
3670 
3671 					case StratMissionObjective :
3672 						add_mission_to_list(asc,vopc->ID);
3673 						break;
3674 
3675 					case StratDeathVolume :
3676 						add_deathvolume(vopc->name,asc,vopc->ID);
3677 						break;
3678 
3679 					case StratSelfDestruct :
3680 						add_selfdestruct(vopc->name,asc,vopc->ID);
3681 						break;
3682 				}
3683 			}
3684 		}
3685 	}
3686 	SetupMissionObjectives();
3687 }
3688 
3689 
setup_sounds(Environment_Data_Chunk * envd)3690 void setup_sounds (Environment_Data_Chunk * envd)
3691 {
3692 	Special_Objects_Chunk * soc = 0;
3693 
3694  	Chunk * pChunk = envd->lookup_single_child ("SPECLOBJ");
3695 	if (pChunk)
3696 	{
3697 		soc = (Special_Objects_Chunk *)pChunk;
3698 	}
3699 
3700 	if (soc)
3701 	{
3702 		List<Chunk *> cl;
3703 		soc->lookup_child("SOUNDOB2",cl);
3704 		for (LIF<Chunk *> cli(&cl); !cli.done(); cli.next())
3705 		{
3706 			Sound_Object_Chunk * snd = (Sound_Object_Chunk *) cli();
3707 			SOUND_TOOLS_TEMPLATE* stt =(SOUND_TOOLS_TEMPLATE*) PoolAllocateMem(sizeof(SOUND_TOOLS_TEMPLATE));
3708 
3709 			stt->position.vx = (int)(snd->position.x * local_scale);
3710 			stt->position.vy = (int)(snd->position.y * local_scale);
3711 			stt->position.vz = (int)(snd->position.z * local_scale);
3712 
3713 			stt->inner_range = (unsigned)(snd->inner_range * local_scale);
3714 			stt->outer_range = (unsigned)(snd->outer_range * local_scale);
3715 			stt->max_volume = snd->max_volume;
3716 			stt->pitch = snd->pitch;
3717 
3718 			stt->playing = 0;
3719 			stt->loop = 0;
3720 
3721 			if(snd->flags & SoundObjectFlag_NotPlayingAtStart)
3722 				stt->playing=0;
3723 			else
3724 				stt->playing=1;
3725 
3726 			if(snd->flags & SoundObjectFlag_NoLoop)
3727 				stt->loop=0;
3728 			else
3729 				stt->loop=1;
3730 
3731 			stt->sound_name =(char*) PoolAllocateMem(strlen (snd->wav_name) + 1);
3732 			strcpy(stt->sound_name,snd->wav_name);
3733 			stt->sound_loaded=GetSoundForMainRif(snd->wav_name);
3734 
3735 			AddToBehaviourList(snd->snd_name,snd->CalculateID(), I_BehaviourPlacedSound, (void *) stt);
3736 		}
3737 	}
3738 }
3739 
3740 
setup_cables(Environment_Data_Chunk * envd)3741 void setup_cables(Environment_Data_Chunk * envd)
3742 {
3743 	if(!envd) return;
3744 	Special_Objects_Chunk* soc = (Special_Objects_Chunk*) envd->lookup_single_child("SPECLOBJ");
3745 	if(!soc) return;
3746 	List<Chunk*> chlist;
3747 	soc->lookup_child("AVPCABLE",chlist);
3748 
3749 	for(LIF<Chunk*> chlif(&chlist);!chlif.done();chlif.next())
3750 	{
3751 		AVP_Power_Cable_Chunk* appc=(AVP_Power_Cable_Chunk*)chlif();
3752 
3753 		POWER_CABLE_TOOLS_TEMPLATE* tdpc=(POWER_CABLE_TOOLS_TEMPLATE*) PoolAllocateMem(sizeof(POWER_CABLE_TOOLS_TEMPLATE));
3754 
3755 		tdpc->position.vx = (int)(appc->location.x * local_scale);
3756 		tdpc->position.vy = (int)(appc->location.y * local_scale);
3757 		tdpc->position.vz = (int)(appc->location.z * local_scale);
3758 
3759 		if(appc->flags & PowerCableFlag_UseDefaultSettings)
3760 		{
3761 			tdpc->max_charge=90*ONE_FIXED;
3762 			tdpc->current_charge=90*ONE_FIXED;
3763 			tdpc->recharge_rate=ONE_FIXED;
3764 		}
3765 		else
3766 		{
3767 			tdpc->max_charge=appc->max_charge;
3768 			tdpc->current_charge=appc->initial_charge;
3769 			tdpc->recharge_rate=appc->recharge_rate;
3770 		}
3771 		*(ObjectID*)&tdpc->nameID[0]=appc->id;
3772 
3773 		AddToBehaviourList(0,appc->id, I_BehaviourPowerCable, (void *) tdpc,0);
3774 
3775 	}
3776 }
3777 
setup_particle_generators(Environment_Data_Chunk * envd)3778 void setup_particle_generators(Environment_Data_Chunk * envd)
3779 {
3780 	if(!envd) return;
3781 	Special_Objects_Chunk* soc = (Special_Objects_Chunk*) envd->lookup_single_child("SPECLOBJ");
3782 	if(!soc) return;
3783 
3784 	List<Chunk*> chlist;
3785 	soc->lookup_child("PARGENER",chlist);
3786 
3787 	for(LIF<Chunk*> chlif(&chlist);!chlif.done();chlif.next())
3788 	{
3789 
3790 		AVP_Particle_Generator_Chunk* part_chunk=(AVP_Particle_Generator_Chunk*)chlif();
3791 		AVP_Particle_Generator_Data_Chunk* data_chunk=(AVP_Particle_Generator_Data_Chunk*)part_chunk->get_data_chunk();
3792 		GLOBALASSERT(data_chunk);
3793 
3794 		PARTICLE_GENERATOR_TOOLS_TEMPLATE* part_temp=(PARTICLE_GENERATOR_TOOLS_TEMPLATE*) PoolAllocateMem(sizeof(PARTICLE_GENERATOR_TOOLS_TEMPLATE));
3795 
3796 		part_temp->position.vx = (int)(data_chunk->location.x * local_scale);
3797 		part_temp->position.vy = (int)(data_chunk->location.y * local_scale);
3798 		part_temp->position.vz = (int)(data_chunk->location.z * local_scale);
3799 
3800 		*(ObjectID*)&part_temp->nameID[0]=data_chunk->id;
3801 		*(ObjectID*)&part_temp->parentID[0]=data_chunk->parent_id;
3802 
3803 		part_temp->type=(enum particle_generator_type)data_chunk->type;
3804 
3805 		part_temp->probability=(data_chunk->probability*ONE_FIXED)/100;
3806 		part_temp->speed=data_chunk->speed*10;
3807 
3808 		if(data_chunk->type==PARGEN_TYPE_SPARK)
3809 			part_temp->frequency=(data_chunk->time*ONE_FIXED)/10;
3810 		else
3811 			part_temp->frequency=ONE_FIXED/max(data_chunk->quantity,1);
3812 
3813 		part_temp->active=!(data_chunk->flags & ParticleGeneratorFlag_Inactive);
3814 
3815 		{
3816 			//get direction vector from orientation
3817 			QUAT q;
3818 			q.quatx = (int) -(data_chunk->orientation.x*ONE_FIXED);
3819 			q.quaty = (int) -(data_chunk->orientation.y*ONE_FIXED);
3820 			q.quatz = (int) -(data_chunk->orientation.z*ONE_FIXED);
3821 			q.quatw = (int)  (data_chunk->orientation.w*ONE_FIXED);
3822 
3823 			MATRIXCH m;
3824 			QuatToMat (&q, &m);
3825 
3826 			part_temp->orientation=m;
3827 
3828 		}
3829 
3830 		setup_track_sound(part_chunk->get_sound_chunk(),&part_temp->sound);
3831 
3832 		AddToBehaviourList(data_chunk->name,data_chunk->id, I_BehaviourParticleGenerator, (void *) part_temp,0,part_chunk->get_alternate_locations_chunk());
3833 
3834 	}
3835 }
3836 
get_marine_facing_point(VECTORCH & pos,EULER & euler,VECTORCH & facing_point)3837 static void get_marine_facing_point(VECTORCH& pos,EULER& euler,VECTORCH& facing_point)
3838 {
3839 	//select point 2 metres(ish) in front of marine
3840 	MATRIXCH mat;
3841 	CreateEulerMatrix(&euler,&mat);
3842 	facing_point=pos;
3843 	facing_point.vx+=mat.mat13/30;
3844 	facing_point.vy+=mat.mat23/30;
3845 	facing_point.vz+=mat.mat33/30;
3846 }
3847