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