1 /* Patrick 4/7/97 ----------------------------------------------------
2 Source file for Xenoborg AI behaviour functions....
3 --------------------------------------------------------------------*/
4
5 /* ChrisF 6/7/98. Hopeless. I'll have to take off and nuke the
6 entire site from orbit. */
7 #include "3dc.h"
8
9 #include "inline.h"
10 #include "module.h"
11 #include "stratdef.h"
12 #include "gamedef.h"
13 #include "bh_types.h"
14 #include "comp_shp.h"
15 #include "dynblock.h"
16 #include "dynamics.h"
17 #include "pfarlocs.h"
18 #include "pvisible.h"
19 #include "bh_pred.h"
20 #include "bh_xeno.h"
21 #include "lighting.h"
22 #include "bh_weap.h"
23 #include "weapons.h"
24 #include "bh_debri.h"
25 #include "plat_shp.h"
26 #include "particle.h"
27 #include "ai_sight.h"
28 #include "sequnces.h"
29 #include "huddefs.h"
30 #include "showcmds.h"
31 #include "sfx.h"
32 #include "bh_marin.h"
33 #include "bh_far.h"
34 #include "pldghost.h"
35 #include "pheromon.h"
36 #include "targeting.h"
37 #include "dxlog.h"
38 #include "los.h"
39 #include "bh_alien.h"
40 #include "bh_corpse.h"
41 #include "bh_dummy.h"
42 #include "game_statistics.h"
43
44 #define UseLocalAssert Yes
45 #include "ourasert.h"
46
47 #include "psnd.h"
48
49 #define XENO_SENTRYTIME (20)
50 #define FAR_XENO_ACTIVITY 0
51 #define FAR_XENO_FIRING 0
52
53 #define XENO_WALKING_ANIM_SPEED (ONE_FIXED<<1)
54 #define XENO_TURNING_ANIM_SPEED (ONE_FIXED<<1)
55
56 /* external global variables used in this file */
57 extern int ModuleArraySize;
58 extern char *ModuleCurrVisArray;
59 extern int NormalFrameTime;
60 extern unsigned char Null_Name[8];
61
62 VECTORCH null_vec={0,0,0};
63
64 extern HIERARCHY_SHAPE_REPLACEMENT* GetHierarchyAlternateShapeSetFromLibrary(const char* rif_name,const char* shape_set_name);
65 extern SECTION * GetNamedHierarchyFromLibrary(const char * rif_name, const char * hier_name);
66 extern void HandleWeaponImpact(VECTORCH *positionPtr, STRATEGYBLOCK *sbPtr, enum AMMO_ID AmmoID, VECTORCH *directionPtr, int multiple, SECTION_DATA *section_pointer);
67
68 int ShowXenoStats=0;
69
70 int RATweak=40;
71
72 void EnforceXenoborgShapeAnimSequence_Core(STRATEGYBLOCK *sbPtr,HMODEL_SEQUENCE_TYPES type, int subtype, int length, int tweeningtime);
73 void SetXenoborgShapeAnimSequence_Core(STRATEGYBLOCK *sbPtr,HMODEL_SEQUENCE_TYPES type, int subtype, int length, int tweeningtime);
74 void SetXenoborgShapeAnimSequence(STRATEGYBLOCK *sbPtr,HMODEL_SEQUENCE_TYPES type, int subtype, int length);
75 void XenoborgHandleMovingAnimation(STRATEGYBLOCK *sbPtr);
76
77 static void ComputeDeltaValues(STRATEGYBLOCK *sbPtr);
78 static void KillXeno(STRATEGYBLOCK *sbPtr,int wounds,DAMAGE_PROFILE *damage, int multiple,VECTORCH *incoming);
79 void CreateXenoborg(VECTORCH *Position,int type);
80 void Xenoborg_ActivateAllDeltas(STRATEGYBLOCK *sbPtr);
81 void Xenoborg_DeactivateAllDeltas(STRATEGYBLOCK *sbPtr);
82 STRATEGYBLOCK *Xenoborg_GetNewTarget(VECTORCH *xenopos, STRATEGYBLOCK *me);
83 void Xenoborg_GetRelativeAngles(STRATEGYBLOCK *sbPtr, int *anglex, int *angley, VECTORCH *pivotPoint);
84 void Xeno_UpdateTargetTrackPos(STRATEGYBLOCK *sbPtr);
85 int Xeno_Activation_Test(STRATEGYBLOCK *sbPtr);
86
87 void Xeno_HeadMovement_ScanLeftRight(STRATEGYBLOCK *sbPtr,int rate);
88 void Xeno_HeadMovement_ScanUpDown(STRATEGYBLOCK *sbPtr,int rate);
89 void Xeno_LeftArmMovement_TrackLeftRight(STRATEGYBLOCK *sbPtr,int rate);
90 void Xeno_LeftArmMovement_TrackUpDown(STRATEGYBLOCK *sbPtr,int rate);
91 void Xeno_RightArmMovement_TrackLeftRight(STRATEGYBLOCK *sbPtr,int rate);
92 void Xeno_RightArmMovement_TrackUpDown(STRATEGYBLOCK *sbPtr,int rate);
93 void Xeno_TorsoMovement_TrackLeftRight(STRATEGYBLOCK *sbPtr,int rate);
94 void Xeno_LeftArmMovement_WaveUp(STRATEGYBLOCK *sbPtr,int rate);
95 void Xeno_RightArmMovement_WaveUp(STRATEGYBLOCK *sbPtr,int rate);
96 void Xeno_TorsoMovement_TrackToAngle(STRATEGYBLOCK *sbPtr,int rate,int in_anglex);
97
98 void Xenoborg_MaintainLeftGun(STRATEGYBLOCK *sbPtr);
99 void Xenoborg_MaintainRightGun(STRATEGYBLOCK *sbPtr);
100 void Xeno_MaintainLasers(STRATEGYBLOCK *sbPtr);
101 void Xeno_SwitchLED(STRATEGYBLOCK *sbPtr,int state);
102 void Xeno_Stomp(STRATEGYBLOCK *sbPtr);
103 void Xeno_MaintainSounds(STRATEGYBLOCK *sbPtr);
104
105 int Xeno_HeadMovement_TrackToAngles(STRATEGYBLOCK *sbPtr,int rate,int in_anglex,int in_angley);
106 void Xeno_TorsoMovement_TrackToAngles(STRATEGYBLOCK *sbPtr,int rate,int in_anglex);
107 int Xeno_LeftArmMovement_TrackToAngles(STRATEGYBLOCK *sbPtr,int rate,int in_anglex,int in_angley);
108 int Xeno_RightArmMovement_TrackToAngles(STRATEGYBLOCK *sbPtr,int rate,int in_anglex,int in_angley);
109 void Xeno_TorsoMovement_Centre(STRATEGYBLOCK *sbPtr,int rate);
110 void Xeno_LeftArmMovement_Centre(STRATEGYBLOCK *sbPtr,int rate);
111 void Xeno_RightArmMovement_Centre(STRATEGYBLOCK *sbPtr,int rate);
112 void Xeno_Limbs_ShootTheRoof(STRATEGYBLOCK *sbPtr);
113
114 void Xeno_Enter_PowerUp_State(STRATEGYBLOCK *sbPtr);
115 void Xeno_Enter_PowerDown_State(STRATEGYBLOCK *sbPtr);
116 void Xeno_Enter_ActiveWait_State(STRATEGYBLOCK *sbPtr);
117 void Xeno_Enter_Dormant_State(STRATEGYBLOCK *sbPtr);
118 void Xeno_Enter_TurnToFace_State(STRATEGYBLOCK *sbPtr);
119 void Xeno_Enter_Following_State(STRATEGYBLOCK *sbPtr);
120 void Xeno_Enter_Returning_State(STRATEGYBLOCK *sbPtr);
121 void Xeno_Enter_ShootingTheRoof_State(STRATEGYBLOCK *sbPtr);
122
123 void Execute_Xeno_Dying(STRATEGYBLOCK *sbPtr);
124 void Execute_Xeno_Inactive(STRATEGYBLOCK *sbPtr);
125 void Execute_Xeno_PowerUp(STRATEGYBLOCK *sbPtr);
126 void Execute_Xeno_PowerDown(STRATEGYBLOCK *sbPtr);
127 void Execute_Xeno_ActiveWait(STRATEGYBLOCK *sbPtr);
128 void Execute_Xeno_TurnToFace(STRATEGYBLOCK *sbPtr);
129 void Execute_Xeno_Follow(STRATEGYBLOCK *sbPtr);
130 void Execute_Xeno_Return(STRATEGYBLOCK *sbPtr);
131 void Execute_Xeno_Avoidance(STRATEGYBLOCK *sbPtr);
132 void Execute_Xeno_ShootTheRoof(STRATEGYBLOCK *sbPtr);
133
134 void Execute_Xeno_ActiveWait_Far(STRATEGYBLOCK *sbPtr);
135 void Execute_Xeno_TurnToFace_Far(STRATEGYBLOCK *sbPtr);
136 void Execute_Xeno_Follow_Far(STRATEGYBLOCK *sbPtr);
137 void Execute_Xeno_Return_Far(STRATEGYBLOCK *sbPtr);
138 void Execute_Xeno_Avoidance_Far(STRATEGYBLOCK *sbPtr);
139
140 int XenoActivation_FrustrumReject(VECTORCH *localOffset);
141
142 /* Begin Code! */
143
CastXenoborg(void)144 void CastXenoborg(void) {
145
146 #define BOTRANGE 2000
147
148 VECTORCH position;
149
150 if (AvP.Network!=I_No_Network) {
151 NewOnScreenMessage("NO XENOBORGS IN MULTIPLAYER MODE");
152 return;
153 }
154
155 position=Player->ObStrategyBlock->DynPtr->Position;
156 position.vx+=MUL_FIXED(Player->ObStrategyBlock->DynPtr->OrientMat.mat31,BOTRANGE);
157 position.vy+=MUL_FIXED(Player->ObStrategyBlock->DynPtr->OrientMat.mat32,BOTRANGE);
158 position.vz+=MUL_FIXED(Player->ObStrategyBlock->DynPtr->OrientMat.mat33,BOTRANGE);
159
160 CreateXenoborg(&position, 0);
161
162 }
163
CreateXenoborg(VECTORCH * Position,int type)164 void CreateXenoborg(VECTORCH *Position,int type)
165 {
166 STRATEGYBLOCK* sbPtr;
167 int i;
168
169 /* create and initialise a strategy block */
170 sbPtr = CreateActiveStrategyBlock();
171 if(!sbPtr) {
172 NewOnScreenMessage("FAILED TO CREATE BOT: SB CREATION FAILURE");
173 return; /* failure */
174 }
175 InitialiseSBValues(sbPtr);
176
177 sbPtr->I_SBtype = I_BehaviourXenoborg;
178
179 AssignNewSBName(sbPtr);
180
181 /* create, initialise and attach a dynamics block */
182 sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_SPRITE_NPC);
183 if(sbPtr->DynPtr)
184 {
185 EULER zeroEuler = {0,0,0};
186 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
187 GLOBALASSERT(dynPtr);
188 dynPtr->PrevPosition = dynPtr->Position = *Position;
189 dynPtr->OrientEuler = zeroEuler;
190 CreateEulerMatrix(&dynPtr->OrientEuler, &dynPtr->OrientMat);
191 TransposeMatrixCH(&dynPtr->OrientMat);
192
193 dynPtr->Mass=500; /* As opposed to 160. */
194 }
195 else
196 {
197 /* dynamics block allocation failed... */
198 RemoveBehaviourStrategy(sbPtr);
199 NewOnScreenMessage("FAILED TO CREATE BOT: DYNBLOCK CREATION FAILURE");
200 return;
201 }
202
203 sbPtr->shapeIndex = 0;
204
205 sbPtr->maintainVisibility = 1;
206 sbPtr->containingModule = ModuleFromPosition(&(sbPtr->DynPtr->Position), (MODULE*)0);
207
208 /* create, initialise and attach an alien data block */
209 sbPtr->SBdataptr = (void *)AllocateMem(sizeof(XENO_STATUS_BLOCK));
210 if(sbPtr->SBdataptr)
211 {
212 SECTION *root_section;
213 XENO_STATUS_BLOCK *xenoStatus = (XENO_STATUS_BLOCK *)sbPtr->SBdataptr;
214
215 NPC_InitMovementData(&(xenoStatus->moveData));
216 NPC_InitWanderData(&(xenoStatus->wanderData));
217 InitWaypointManager(&xenoStatus->waypointManager);
218
219 /* Initialise xenoborg's stats */
220 {
221 NPC_DATA *NpcData;
222
223 NpcData=GetThisNpcData(I_NPC_Xenoborg);
224 LOCALASSERT(NpcData);
225 sbPtr->SBDamageBlock.Health=NpcData->StartingStats.Health<<ONE_FIXED_SHIFT;
226 sbPtr->SBDamageBlock.Armour=NpcData->StartingStats.Armour<<ONE_FIXED_SHIFT;
227 sbPtr->SBDamageBlock.SB_H_flags=NpcData->StartingStats.SB_H_flags;
228 }
229
230 xenoStatus->behaviourState=XS_Inactive;
231 xenoStatus->lastState=XS_Inactive;
232 xenoStatus->Target=NULL;
233 COPY_NAME(xenoStatus->Target_SBname,Null_Name);
234 xenoStatus->targetTrackPos.vx=0;
235 xenoStatus->targetTrackPos.vy=0;
236 xenoStatus->targetTrackPos.vz=0;
237
238 xenoStatus->Wounds=0;
239 xenoStatus->GibbFactor=0;
240 xenoStatus->stateTimer=XENO_POWERDOWN_TIME;
241 xenoStatus->my_module=sbPtr->containingModule->m_aimodule;
242 xenoStatus->my_spot_therin=sbPtr->DynPtr->Position;
243 {
244 /* Pull out my_orientdir_therin. */
245 xenoStatus->my_orientdir_therin.vx=0;
246 xenoStatus->my_orientdir_therin.vx=0;
247 xenoStatus->my_orientdir_therin.vz=1000;
248
249 RotateVector(&xenoStatus->my_orientdir_therin,&sbPtr->DynPtr->OrientMat);
250 }
251 xenoStatus->module_range=7;
252 xenoStatus->UpTime=XENO_SENTRYTIME*ONE_FIXED;
253 xenoStatus->Head_Pan=0;
254 xenoStatus->Head_Tilt=0;
255 xenoStatus->Left_Arm_Pan=0;
256 xenoStatus->Left_Arm_Tilt=0;
257 xenoStatus->Right_Arm_Pan=0;
258 xenoStatus->Right_Arm_Tilt=0;
259 xenoStatus->Torso_Twist=0;
260
261 xenoStatus->headpandir=0;
262 xenoStatus->headtiltdir=0;
263 xenoStatus->leftarmpandir=0;
264 xenoStatus->leftarmtiltdir=0;
265 xenoStatus->rightarmpandir=0;
266 xenoStatus->rightarmtiltdir=0;
267 xenoStatus->torsotwistdir=0;
268
269 xenoStatus->Old_Head_Pan=0;
270 xenoStatus->Old_Head_Tilt=0;
271 xenoStatus->Old_Left_Arm_Pan=0;
272 xenoStatus->Old_Left_Arm_Tilt=0;
273 xenoStatus->Old_Right_Arm_Pan=0;
274 xenoStatus->Old_Right_Arm_Tilt=0;
275 xenoStatus->Old_Torso_Twist=0;
276
277 xenoStatus->headLock=0;
278 xenoStatus->leftArmLock=0;
279 xenoStatus->rightArmLock=0;
280 xenoStatus->targetSightTest=0;
281 xenoStatus->IAmFar=1;
282 xenoStatus->ShotThisFrame=0;
283
284 xenoStatus->obstruction.environment=0;
285 xenoStatus->obstruction.destructableObject=0;
286 xenoStatus->obstruction.otherCharacter=0;
287 xenoStatus->obstruction.anySingleObstruction=0;
288
289 /* Init beams. */
290 xenoStatus->LeftMainBeam.BeamIsOn = 0;
291 xenoStatus->RightMainBeam.BeamIsOn = 0;
292 xenoStatus->TargetingLaser[0].SourcePosition=null_vec;
293 xenoStatus->TargetingLaser[0].TargetPosition=null_vec;
294 xenoStatus->TargetingLaser[0].BeamHasHitPlayer=0;
295 xenoStatus->TargetingLaser[0].BeamIsOn=0;
296
297 xenoStatus->TargetingLaser[1].SourcePosition=null_vec;
298 xenoStatus->TargetingLaser[1].TargetPosition=null_vec;
299 xenoStatus->TargetingLaser[1].BeamHasHitPlayer=0;
300 xenoStatus->TargetingLaser[1].BeamIsOn=0;
301
302 xenoStatus->TargetingLaser[2].SourcePosition=null_vec;
303 xenoStatus->TargetingLaser[2].TargetPosition=null_vec;
304 xenoStatus->TargetingLaser[2].BeamHasHitPlayer=0;
305 xenoStatus->TargetingLaser[2].BeamIsOn=0;
306
307 xenoStatus->FiringLeft=0;
308 xenoStatus->FiringRight=0;
309
310 xenoStatus->UseHeadLaser=0;
311 xenoStatus->UseLALaser=0;
312 xenoStatus->UseRALaser=0;
313
314 xenoStatus->head_moving=0;
315 xenoStatus->la_moving=0;
316 xenoStatus->ra_moving=0;
317 xenoStatus->torso_moving=0;
318
319 xenoStatus->HeadLaserOnTarget=0;
320 xenoStatus->LALaserOnTarget=0;
321 xenoStatus->RALaserOnTarget=0;
322
323 xenoStatus->soundHandle1=SOUND_NOACTIVEINDEX;
324 xenoStatus->soundHandle2=SOUND_NOACTIVEINDEX;
325
326 xenoStatus->incidentFlag=0;
327 xenoStatus->incidentTimer=0;
328
329 xenoStatus->head_whirr=SOUND_NOACTIVEINDEX;
330 xenoStatus->left_arm_whirr=SOUND_NOACTIVEINDEX;
331 xenoStatus->right_arm_whirr=SOUND_NOACTIVEINDEX;
332 xenoStatus->torso_whirr=SOUND_NOACTIVEINDEX;
333
334 xenoStatus->HModelController.section_data=NULL;
335 xenoStatus->HModelController.Deltas=NULL;
336
337 for(i=0;i<SB_NAME_LENGTH;i++) xenoStatus->death_target_ID[i] =0;
338 xenoStatus->death_target_sbptr=0;
339 xenoStatus->death_target_request=0;
340
341 root_section=GetNamedHierarchyFromLibrary("hnpc_xenoborg","xenobasic");
342
343 if (!root_section) {
344 RemoveBehaviourStrategy(sbPtr);
345 NewOnScreenMessage("FAILED TO CREATE BOT: NO HMODEL");
346 return;
347 }
348 Create_HModel(&xenoStatus->HModelController,root_section);
349 InitHModelSequence(&xenoStatus->HModelController,HMSQT_Xenoborg,XBSS_Powered_Down_Standard,ONE_FIXED);
350
351 {
352 DELTA_CONTROLLER *delta;
353
354 delta=Add_Delta_Sequence(&xenoStatus->HModelController,"HeadTilt",(int)HMSQT_Xenoborg,(int)XBSS_Head_Vertical_Delta,0);
355 GLOBALASSERT(delta);
356 delta->timer=32767;
357 delta->Active=0;
358
359 delta=Add_Delta_Sequence(&xenoStatus->HModelController,"HeadPan",(int)HMSQT_Xenoborg,(int)XBSS_Head_Horizontal_Delta,0);
360 GLOBALASSERT(delta);
361 delta->timer=32767;
362 delta->Active=0;
363
364 delta=Add_Delta_Sequence(&xenoStatus->HModelController,"LeftArmTilt",(int)HMSQT_Xenoborg,(int)XBSS_LeftArm_Vertical_Delta,0);
365 GLOBALASSERT(delta);
366 delta->timer=32767;
367 delta->Active=0;
368
369 delta=Add_Delta_Sequence(&xenoStatus->HModelController,"LeftArmPan",(int)HMSQT_Xenoborg,(int)XBSS_LeftArm_Horizontal_Delta,0);
370 GLOBALASSERT(delta);
371 delta->timer=32767;
372 delta->Active=0;
373
374 delta=Add_Delta_Sequence(&xenoStatus->HModelController,"RightArmTilt",(int)HMSQT_Xenoborg,(int)XBSS_RightArm_Vertical_Delta,0);
375 GLOBALASSERT(delta);
376 delta->timer=32767;
377 delta->Active=0;
378
379 delta=Add_Delta_Sequence(&xenoStatus->HModelController,"RightArmPan",(int)HMSQT_Xenoborg,(int)XBSS_RightArm_Horizontal_Delta,0);
380 GLOBALASSERT(delta);
381 delta->timer=32767;
382 delta->Active=0;
383
384 delta=Add_Delta_Sequence(&xenoStatus->HModelController,"TorsoTwist",(int)HMSQT_Xenoborg,(int)XBSS_Torso_Delta,0);
385 GLOBALASSERT(delta);
386 delta->timer=32767;
387 delta->Active=0;
388
389 }
390
391 /* Containment test NOW! */
392 if(!(sbPtr->containingModule))
393 {
394 /* no containing module can be found... abort*/
395 RemoveBehaviourStrategy(sbPtr);
396 NewOnScreenMessage("FAILED TO CREATE BOT: MODULE CONTAINMENT FAILURE");
397 return;
398 }
399 LOCALASSERT(sbPtr->containingModule);
400 Xeno_SwitchLED(sbPtr,0);
401
402 MakeXenoborgNear(sbPtr);
403
404 NewOnScreenMessage("XENOBORG CREATED");
405 }
406 else
407 {
408 /* no data block can be allocated */
409 RemoveBehaviourStrategy(sbPtr);
410 NewOnScreenMessage("FAILED TO CREATE BOT: MALLOC FAILURE");
411 return;
412 }
413 }
414
VerifyDeltaControllers(STRATEGYBLOCK * sbPtr)415 static void VerifyDeltaControllers(STRATEGYBLOCK *sbPtr) {
416
417 XENO_STATUS_BLOCK *xenoStatusPointer;
418
419 LOCALASSERT(sbPtr);
420 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
421 LOCALASSERT(xenoStatusPointer);
422
423 /* Nothing has deltas like a xenoborg does. */
424
425 xenoStatusPointer->head_pan=Get_Delta_Sequence(&xenoStatusPointer->HModelController,"HeadPan");
426 GLOBALASSERT(xenoStatusPointer->head_pan);
427
428 xenoStatusPointer->head_tilt=Get_Delta_Sequence(&xenoStatusPointer->HModelController,"HeadTilt");
429 GLOBALASSERT(xenoStatusPointer->head_tilt);
430
431 xenoStatusPointer->left_arm_pan=Get_Delta_Sequence(&xenoStatusPointer->HModelController,"LeftArmPan");
432 GLOBALASSERT(xenoStatusPointer->left_arm_pan);
433
434 xenoStatusPointer->left_arm_tilt=Get_Delta_Sequence(&xenoStatusPointer->HModelController,"LeftArmTilt");
435 GLOBALASSERT(xenoStatusPointer->left_arm_tilt);
436
437 xenoStatusPointer->right_arm_pan=Get_Delta_Sequence(&xenoStatusPointer->HModelController,"RightArmPan");
438 GLOBALASSERT(xenoStatusPointer->right_arm_pan);
439
440 xenoStatusPointer->right_arm_tilt=Get_Delta_Sequence(&xenoStatusPointer->HModelController,"RightArmTilt");
441 GLOBALASSERT(xenoStatusPointer->right_arm_tilt);
442
443 xenoStatusPointer->torso_twist=Get_Delta_Sequence(&xenoStatusPointer->HModelController,"TorsoTwist");
444 GLOBALASSERT(xenoStatusPointer->torso_twist);
445
446 }
447
448 /* Patrick 4/7/97 ----------------------------------------------------
449 Xenoborg initialiser, visibility management, behaviour shell, and
450 damage functions
451
452 ChrisF 6/7/98. I don't think so...
453 --------------------------------------------------------------------*/
InitXenoborgBehaviour(void * bhdata,STRATEGYBLOCK * sbPtr)454 void InitXenoborgBehaviour(void* bhdata, STRATEGYBLOCK *sbPtr)
455 {
456 TOOLS_DATA_XENO *toolsData;
457 int i;
458
459 LOCALASSERT(bhdata);
460 toolsData = (TOOLS_DATA_XENO *)bhdata;
461 LOCALASSERT(sbPtr);
462
463 /* check we're not in a net game */
464 if(AvP.Network != I_No_Network)
465 {
466 RemoveBehaviourStrategy(sbPtr);
467 return;
468 }
469
470 /* make the assumption that the loader has initialised the strategy block sensibly...
471 so just set the shapeIndex from the tools data & copy the name id*/
472 sbPtr->shapeIndex = toolsData->shapeIndex;
473 for(i=0;i<SB_NAME_LENGTH;i++) sbPtr->SBname[i] = toolsData->nameID[i];
474
475 /* create, initialise and attach a dynamics block */
476 sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_SPRITE_NPC);
477 if(sbPtr->DynPtr)
478 {
479 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
480 GLOBALASSERT(dynPtr);
481 dynPtr->PrevPosition = dynPtr->Position = toolsData->position;
482 dynPtr->OrientEuler = toolsData->starteuler;
483 CreateEulerMatrix(&dynPtr->OrientEuler, &dynPtr->OrientMat);
484 TransposeMatrixCH(&dynPtr->OrientMat);
485
486 dynPtr->Mass=1000; /* As opposed to 160. */
487 }
488 else
489 {
490 /* dynamics block allocation failed... */
491 RemoveBehaviourStrategy(sbPtr);
492 return;
493 }
494
495 sbPtr->maintainVisibility = 1;
496 sbPtr->containingModule = ModuleFromPosition(&(sbPtr->DynPtr->Position), (MODULE*)0);
497
498 /* create, initialise and attach a xeno data block */
499 sbPtr->SBdataptr = (void *)AllocateMem(sizeof(XENO_STATUS_BLOCK));
500 if(sbPtr->SBdataptr)
501 {
502 SECTION *root_section;
503 XENO_STATUS_BLOCK *xenoStatus = (XENO_STATUS_BLOCK *)sbPtr->SBdataptr;
504
505 NPC_InitMovementData(&(xenoStatus->moveData));
506 NPC_InitWanderData(&(xenoStatus->wanderData));
507 InitWaypointManager(&xenoStatus->waypointManager);
508
509 /* Initialise xenoborg's stats */
510 {
511 NPC_DATA *NpcData;
512
513 NpcData=GetThisNpcData(I_NPC_Xenoborg);
514 LOCALASSERT(NpcData);
515 sbPtr->SBDamageBlock.Health=NpcData->StartingStats.Health<<ONE_FIXED_SHIFT;
516 sbPtr->SBDamageBlock.Armour=NpcData->StartingStats.Armour<<ONE_FIXED_SHIFT;
517 sbPtr->SBDamageBlock.SB_H_flags=NpcData->StartingStats.SB_H_flags;
518 }
519
520 xenoStatus->behaviourState=XS_Inactive;
521 xenoStatus->lastState=XS_Inactive;
522 xenoStatus->Target=NULL;
523 COPY_NAME(xenoStatus->Target_SBname,Null_Name);
524 xenoStatus->targetTrackPos.vx=0;
525 xenoStatus->targetTrackPos.vy=0;
526 xenoStatus->targetTrackPos.vz=0;
527
528 xenoStatus->Wounds=0;
529 xenoStatus->GibbFactor=0;
530 xenoStatus->stateTimer=XENO_POWERDOWN_TIME;
531 xenoStatus->my_module=sbPtr->containingModule->m_aimodule;
532 xenoStatus->my_spot_therin=sbPtr->DynPtr->Position;
533 {
534 /* Pull out my_orientdir_therin. */
535 xenoStatus->my_orientdir_therin.vx=0;
536 xenoStatus->my_orientdir_therin.vx=0;
537 xenoStatus->my_orientdir_therin.vz=1000;
538
539 RotateVector(&xenoStatus->my_orientdir_therin,&sbPtr->DynPtr->OrientMat);
540 }
541 xenoStatus->module_range=toolsData->ModuleRange;
542 xenoStatus->UpTime=toolsData->UpTime*ONE_FIXED;
543 xenoStatus->Head_Pan=0;
544 xenoStatus->Head_Tilt=0;
545 xenoStatus->Left_Arm_Pan=0;
546 xenoStatus->Left_Arm_Tilt=0;
547 xenoStatus->Right_Arm_Pan=0;
548 xenoStatus->Right_Arm_Tilt=0;
549 xenoStatus->Torso_Twist=0;
550
551 xenoStatus->headpandir=0;
552 xenoStatus->headtiltdir=0;
553 xenoStatus->leftarmpandir=0;
554 xenoStatus->leftarmtiltdir=0;
555 xenoStatus->rightarmpandir=0;
556 xenoStatus->rightarmtiltdir=0;
557 xenoStatus->torsotwistdir=0;
558
559 xenoStatus->Old_Head_Pan=0;
560 xenoStatus->Old_Head_Tilt=0;
561 xenoStatus->Old_Left_Arm_Pan=0;
562 xenoStatus->Old_Left_Arm_Tilt=0;
563 xenoStatus->Old_Right_Arm_Pan=0;
564 xenoStatus->Old_Right_Arm_Tilt=0;
565 xenoStatus->Old_Torso_Twist=0;
566
567 xenoStatus->headLock=0;
568 xenoStatus->leftArmLock=0;
569 xenoStatus->rightArmLock=0;
570 xenoStatus->targetSightTest=0;
571 xenoStatus->IAmFar=1;
572 xenoStatus->ShotThisFrame=0;
573
574 xenoStatus->obstruction.environment=0;
575 xenoStatus->obstruction.destructableObject=0;
576 xenoStatus->obstruction.otherCharacter=0;
577 xenoStatus->obstruction.anySingleObstruction=0;
578
579 /* Init beams. */
580 xenoStatus->LeftMainBeam.BeamIsOn = 0;
581 xenoStatus->RightMainBeam.BeamIsOn = 0;
582 xenoStatus->TargetingLaser[0].SourcePosition=null_vec;
583 xenoStatus->TargetingLaser[0].TargetPosition=null_vec;
584 xenoStatus->TargetingLaser[0].BeamHasHitPlayer=0;
585 xenoStatus->TargetingLaser[0].BeamIsOn=0;
586
587 xenoStatus->TargetingLaser[1].SourcePosition=null_vec;
588 xenoStatus->TargetingLaser[1].TargetPosition=null_vec;
589 xenoStatus->TargetingLaser[1].BeamHasHitPlayer=0;
590 xenoStatus->TargetingLaser[1].BeamIsOn=0;
591
592 xenoStatus->TargetingLaser[2].SourcePosition=null_vec;
593 xenoStatus->TargetingLaser[2].TargetPosition=null_vec;
594 xenoStatus->TargetingLaser[2].BeamHasHitPlayer=0;
595 xenoStatus->TargetingLaser[2].BeamIsOn=0;
596
597 xenoStatus->FiringLeft=0;
598 xenoStatus->FiringRight=0;
599
600 xenoStatus->UseHeadLaser=0;
601 xenoStatus->UseLALaser=0;
602 xenoStatus->UseRALaser=0;
603
604 xenoStatus->head_moving=0;
605 xenoStatus->la_moving=0;
606 xenoStatus->ra_moving=0;
607 xenoStatus->torso_moving=0;
608
609 xenoStatus->HeadLaserOnTarget=0;
610 xenoStatus->LALaserOnTarget=0;
611 xenoStatus->RALaserOnTarget=0;
612
613
614 xenoStatus->soundHandle1=SOUND_NOACTIVEINDEX;
615 xenoStatus->soundHandle2=SOUND_NOACTIVEINDEX;
616
617 xenoStatus->incidentFlag=0;
618 xenoStatus->incidentTimer=0;
619
620 xenoStatus->head_whirr=SOUND_NOACTIVEINDEX;
621 xenoStatus->left_arm_whirr=SOUND_NOACTIVEINDEX;
622 xenoStatus->right_arm_whirr=SOUND_NOACTIVEINDEX;
623 xenoStatus->torso_whirr=SOUND_NOACTIVEINDEX;
624
625 xenoStatus->HModelController.section_data=NULL;
626 xenoStatus->HModelController.Deltas=NULL;
627
628 for(i=0;i<SB_NAME_LENGTH;i++) xenoStatus->death_target_ID[i] = toolsData->death_target_ID[i];
629 xenoStatus->death_target_sbptr=0;
630 xenoStatus->death_target_request=toolsData->death_target_request;
631
632 root_section=GetNamedHierarchyFromLibrary("hnpc_xenoborg","xenobasic");
633
634 GLOBALASSERT(root_section);
635
636 Create_HModel(&xenoStatus->HModelController,root_section);
637 InitHModelSequence(&xenoStatus->HModelController,HMSQT_Xenoborg,XBSS_Powered_Down_Standard,ONE_FIXED);
638
639 {
640 DELTA_CONTROLLER *delta;
641
642 delta=Add_Delta_Sequence(&xenoStatus->HModelController,"HeadTilt",(int)HMSQT_Xenoborg,(int)XBSS_Head_Vertical_Delta,0);
643 GLOBALASSERT(delta);
644 delta->timer=32767;
645 delta->Active=0;
646
647 delta=Add_Delta_Sequence(&xenoStatus->HModelController,"HeadPan",(int)HMSQT_Xenoborg,(int)XBSS_Head_Horizontal_Delta,0);
648 GLOBALASSERT(delta);
649 delta->timer=32767;
650 delta->Active=0;
651
652 delta=Add_Delta_Sequence(&xenoStatus->HModelController,"LeftArmTilt",(int)HMSQT_Xenoborg,(int)XBSS_LeftArm_Vertical_Delta,0);
653 GLOBALASSERT(delta);
654 delta->timer=32767;
655 delta->Active=0;
656
657 delta=Add_Delta_Sequence(&xenoStatus->HModelController,"LeftArmPan",(int)HMSQT_Xenoborg,(int)XBSS_LeftArm_Horizontal_Delta,0);
658 GLOBALASSERT(delta);
659 delta->timer=32767;
660 delta->Active=0;
661
662 delta=Add_Delta_Sequence(&xenoStatus->HModelController,"RightArmTilt",(int)HMSQT_Xenoborg,(int)XBSS_RightArm_Vertical_Delta,0);
663 GLOBALASSERT(delta);
664 delta->timer=32767;
665 delta->Active=0;
666
667 delta=Add_Delta_Sequence(&xenoStatus->HModelController,"RightArmPan",(int)HMSQT_Xenoborg,(int)XBSS_RightArm_Horizontal_Delta,0);
668 GLOBALASSERT(delta);
669 delta->timer=32767;
670 delta->Active=0;
671
672 delta=Add_Delta_Sequence(&xenoStatus->HModelController,"TorsoTwist",(int)HMSQT_Xenoborg,(int)XBSS_Torso_Delta,0);
673 GLOBALASSERT(delta);
674 delta->timer=32767;
675 delta->Active=0;
676
677 }
678
679 /* Containment test NOW! */
680 GLOBALASSERT(sbPtr->containingModule);
681 Xeno_SwitchLED(sbPtr,0);
682
683 }
684 else
685 {
686 /* no data block can be allocated */
687 RemoveBehaviourStrategy(sbPtr);
688 return;
689 }
690
691 }
692
XenoborgBehaviour(STRATEGYBLOCK * sbPtr)693 void XenoborgBehaviour(STRATEGYBLOCK *sbPtr)
694 {
695 XENO_STATUS_BLOCK *xenoStatusPointer;
696 NPC_DATA *NpcData;
697 int xenoborgIsNear;
698
699 LOCALASSERT(sbPtr);
700 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
701 LOCALASSERT(xenoStatusPointer);
702
703 NpcData=GetThisNpcData(I_NPC_Xenoborg);
704
705 /* test if we've got a containing module: if we haven't, do nothing.
706 This is important as the object could have been marked for deletion by the visibility
707 management system...*/
708 if(!sbPtr->containingModule)
709 {
710 DestroyAnyStrategyBlock(sbPtr); /* just to make sure */
711 return;
712 }
713
714 if(sbPtr->SBdptr) {
715 xenoborgIsNear=1;
716 LOCALASSERT(ModuleCurrVisArray[(sbPtr->containingModule->m_index)]);
717 } else {
718 xenoborgIsNear=0;
719 }
720
721 VerifyDeltaControllers(sbPtr);
722
723 #if 0
724 /* zero velocity */
725 LOCALASSERT(sbPtr->DynPtr);
726 sbPtr->DynPtr->LinVelocity.vx = 0;
727 sbPtr->DynPtr->LinVelocity.vy = 0;
728 sbPtr->DynPtr->LinVelocity.vz = 0;
729 #endif
730
731 InitWaypointSystem(0);
732
733 if (sbPtr->SBdptr) {
734 xenoStatusPointer->IAmFar=0;
735 } else {
736 xenoStatusPointer->IAmFar=1;
737 }
738
739 /* Store angles. */
740 xenoStatusPointer->Old_Head_Pan =xenoStatusPointer->Head_Pan;
741 xenoStatusPointer->Old_Head_Tilt =xenoStatusPointer->Head_Tilt;
742 xenoStatusPointer->Old_Left_Arm_Pan =xenoStatusPointer->Left_Arm_Pan;
743 xenoStatusPointer->Old_Left_Arm_Tilt =xenoStatusPointer->Left_Arm_Tilt;
744 xenoStatusPointer->Old_Right_Arm_Pan =xenoStatusPointer->Right_Arm_Pan;
745 xenoStatusPointer->Old_Right_Arm_Tilt =xenoStatusPointer->Right_Arm_Tilt;
746 xenoStatusPointer->Old_Torso_Twist =xenoStatusPointer->Torso_Twist;
747
748 xenoStatusPointer->head_moving=0;
749 xenoStatusPointer->la_moving=0;
750 xenoStatusPointer->ra_moving=0;
751 xenoStatusPointer->torso_moving=0;
752
753 /* Target handling. */
754 if (Validate_Target(xenoStatusPointer->Target,xenoStatusPointer->Target_SBname)==0) {
755 xenoStatusPointer->Target=NULL;
756 }
757
758 xenoStatusPointer->FiringLeft=0;
759 xenoStatusPointer->FiringRight=0;
760
761 xenoStatusPointer->UseHeadLaser=0;
762 xenoStatusPointer->UseLALaser=0;
763 xenoStatusPointer->UseRALaser=0;
764
765 xenoStatusPointer->LeftMainBeam.BeamIsOn = 0;
766 xenoStatusPointer->RightMainBeam.BeamIsOn = 0;
767 xenoStatusPointer->TargetingLaser[0].BeamIsOn=0;
768 xenoStatusPointer->TargetingLaser[1].BeamIsOn=0;
769 xenoStatusPointer->TargetingLaser[2].BeamIsOn=0;
770
771 if (xenoStatusPointer->Target==NULL) {
772 if ((xenoborgIsNear)||(xenoStatusPointer->incidentFlag)) {
773 /* Get new target. */
774 xenoStatusPointer->Target=Xenoborg_GetNewTarget(&sbPtr->DynPtr->Position,sbPtr);
775 xenoStatusPointer->targetSightTest=0;
776 if (xenoStatusPointer->Target) {
777 COPY_NAME(xenoStatusPointer->Target_SBname,xenoStatusPointer->Target->SBname);
778 xenoStatusPointer->targetSightTest=1;
779 }
780 Xeno_UpdateTargetTrackPos(sbPtr);
781 xenoStatusPointer->headLock=0;
782 xenoStatusPointer->leftArmLock=0;
783 xenoStatusPointer->rightArmLock=0;
784 }
785 } else if (NPCCanSeeTarget(sbPtr,xenoStatusPointer->Target,XENO_NEAR_VIEW_WIDTH)) {
786 Xeno_UpdateTargetTrackPos(sbPtr);
787 xenoStatusPointer->targetSightTest=1;
788 } else {
789 /* We have a target that we can't see. */
790 xenoStatusPointer->headLock=0;
791 xenoStatusPointer->leftArmLock=0;
792 xenoStatusPointer->rightArmLock=0;
793 xenoStatusPointer->targetSightTest=0;
794 }
795
796 if (xenoStatusPointer->GibbFactor) {
797 /* If you're gibbed, you're dead. */
798 sbPtr->SBDamageBlock.Health = 0;
799 }
800
801 /* Unset incident flag. */
802 xenoStatusPointer->incidentFlag=0;
803
804 xenoStatusPointer->incidentTimer-=NormalFrameTime;
805
806 if (xenoStatusPointer->incidentTimer<0) {
807 xenoStatusPointer->incidentFlag=1;
808 xenoStatusPointer->incidentTimer=32767+(FastRandom()&65535);
809 }
810
811 if (sbPtr->SBDamageBlock.IsOnFire) {
812
813 /* Why not? */
814 CauseDamageToObject(sbPtr,&firedamage,NormalFrameTime,NULL);
815
816 if (sbPtr->I_SBtype==I_BehaviourNetCorpse) {
817 /* Gettin' out of here... */
818 return;
819 }
820
821 if (xenoStatusPointer->incidentFlag) {
822 if ((FastRandom()&65535)<32767) {
823 sbPtr->SBDamageBlock.IsOnFire=0;
824 }
825 }
826
827 }
828
829 /* Now, switch by state. */
830
831 switch (xenoStatusPointer->behaviourState) {
832 case XS_ActiveWait:
833 if (xenoStatusPointer->IAmFar) {
834 Execute_Xeno_ActiveWait_Far(sbPtr);
835 } else {
836 Execute_Xeno_ActiveWait(sbPtr);
837 }
838 break;
839 case XS_TurnToFace:
840 if (xenoStatusPointer->IAmFar) {
841 Execute_Xeno_TurnToFace_Far(sbPtr);
842 } else {
843 Execute_Xeno_TurnToFace(sbPtr);
844 }
845 break;
846 case XS_Following:
847 if (xenoStatusPointer->IAmFar) {
848 Execute_Xeno_Follow_Far(sbPtr);
849 } else {
850 Execute_Xeno_Follow(sbPtr);
851 }
852 break;
853 case XS_Returning:
854 if (xenoStatusPointer->IAmFar) {
855 Execute_Xeno_Return_Far(sbPtr);
856 } else {
857 Execute_Xeno_Return(sbPtr);
858 }
859 break;
860 case XS_Avoidance:
861 if (xenoStatusPointer->IAmFar) {
862 Execute_Xeno_Avoidance_Far(sbPtr);
863 } else {
864 Execute_Xeno_Avoidance(sbPtr);
865 }
866 break;
867 case XS_Inactive:
868 Execute_Xeno_Inactive(sbPtr);
869 break;
870 case XS_Activating:
871 Execute_Xeno_PowerUp(sbPtr);
872 break;
873 case XS_Deactivating:
874 Execute_Xeno_PowerDown(sbPtr);
875 break;
876 case XS_Regenerating:
877 break;
878 case XS_Dying:
879 Execute_Xeno_Dying(sbPtr);
880 break;
881 case XS_ShootingTheRoof:
882 if (xenoStatusPointer->IAmFar) {
883 Execute_Xeno_ShootTheRoof(sbPtr);
884 } else {
885 Execute_Xeno_ShootTheRoof(sbPtr);
886 }
887 break;
888 default:
889 /* No action? */
890 break;
891 }
892
893 /* if we have actually died, we need to remove the strategyblock... so
894 do this here */
895 if((xenoStatusPointer->behaviourState == XS_Dying)&&(xenoStatusPointer->stateTimer <= 0)) {
896
897 DestroyAnyStrategyBlock(sbPtr);
898 }
899
900 if ((xenoStatusPointer->behaviourState!=XS_Dying)
901 &&(xenoStatusPointer->behaviourState!=XS_Inactive)
902 &&(xenoStatusPointer->behaviourState!=XS_Activating)
903 &&(xenoStatusPointer->behaviourState!=XS_Deactivating)) {
904 /* Time to regenerate? */
905 if ((sbPtr->SBDamageBlock.Health<(NpcData->StartingStats.Health<<(ONE_FIXED_SHIFT-2)))
906 &&(sbPtr->SBDamageBlock.Health>0)) {
907 /* 25% health or less. */
908 Xeno_Enter_PowerDown_State(sbPtr);
909 }
910 }
911
912 ComputeDeltaValues(sbPtr);
913
914 ProveHModel_Far(&xenoStatusPointer->HModelController,sbPtr);
915
916 #if (FAR_XENO_FIRING==0)
917 if (xenoStatusPointer->IAmFar) {
918 xenoStatusPointer->FiringLeft=0;
919 xenoStatusPointer->FiringRight=0;
920 }
921 #endif
922
923 /* Now lets deal with the sounds. */
924 Xeno_MaintainSounds(sbPtr);
925
926 if (xenoStatusPointer->IAmFar) {
927 /* No lasers if far. */
928 xenoStatusPointer->UseHeadLaser=0;
929 xenoStatusPointer->UseLALaser=0;
930 xenoStatusPointer->UseRALaser=0;
931 }
932
933 /* Now consider the lasers. */
934 Xeno_MaintainLasers(sbPtr);
935 Xeno_Stomp(sbPtr);
936
937 /* Now, are we firing? */
938 Xenoborg_MaintainLeftGun(sbPtr);
939 Xenoborg_MaintainRightGun(sbPtr);
940
941 /* Unset shot flag. */
942 xenoStatusPointer->ShotThisFrame=0;
943 }
944
MakeXenoborgNear(STRATEGYBLOCK * sbPtr)945 void MakeXenoborgNear(STRATEGYBLOCK *sbPtr)
946 {
947 extern MODULEMAPBLOCK AlienDefaultMap;
948
949 MODULE tempModule;
950 DISPLAYBLOCK *dPtr;
951 DYNAMICSBLOCK *dynPtr;
952 XENO_STATUS_BLOCK *xenoStatusPointer;
953
954 LOCALASSERT(sbPtr);
955 dynPtr = sbPtr->DynPtr;
956 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
957 LOCALASSERT(xenoStatusPointer);
958 LOCALASSERT(dynPtr);
959 LOCALASSERT(sbPtr->SBdptr == NULL);
960
961 AlienDefaultMap.MapShape = sbPtr->shapeIndex;
962 tempModule.m_mapptr = &AlienDefaultMap;
963 tempModule.m_sbptr = (STRATEGYBLOCK*)NULL;
964 tempModule.m_numlights = 0;
965 tempModule.m_lightarray = (struct lightblock *)0;
966 tempModule.m_extraitemdata = (struct extraitemdata *)0;
967 tempModule.m_dptr = NULL;
968 AllocateModuleObject(&tempModule);
969 dPtr = tempModule.m_dptr;
970 if(dPtr==NULL) return; /* if cannot create displayblock, leave far */
971
972 sbPtr->SBdptr = dPtr;
973 dPtr->ObStrategyBlock = sbPtr;
974 dPtr->ObMyModule = NULL;
975
976 /* need to initialise positional information in the new display block */
977 dPtr->ObWorld = dynPtr->Position;
978 dPtr->ObEuler = dynPtr->OrientEuler;
979 dPtr->ObMat = dynPtr->OrientMat;
980 /* zero linear velocity in dynamics block */
981 sbPtr->DynPtr->LinVelocity.vx = 0;
982 sbPtr->DynPtr->LinVelocity.vy = 0;
983 sbPtr->DynPtr->LinVelocity.vz = 0;
984
985 /* state and sequence init */
986 NPC_InitMovementData(&(xenoStatusPointer->moveData));
987 InitWaypointManager(&xenoStatusPointer->waypointManager);
988
989 dPtr->ShapeAnimControlBlock = NULL;
990 dPtr->ObTxAnimCtrlBlks = NULL;
991
992 dPtr->HModelControlBlock=&xenoStatusPointer->HModelController;
993
994 ProveHModel(dPtr->HModelControlBlock,dPtr);
995
996 xenoStatusPointer->IAmFar=0;
997
998 /* make a sound */
999 //Sound_Play(SID_ALIEN_HISS,"d",&sbPtr->DynPtr->Position);
1000 }
1001
MakeXenoborgFar(STRATEGYBLOCK * sbPtr)1002 void MakeXenoborgFar(STRATEGYBLOCK *sbPtr)
1003 {
1004 XENO_STATUS_BLOCK *xenoStatusPointer;
1005 int i;
1006
1007 LOCALASSERT(sbPtr);
1008 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
1009 LOCALASSERT(xenoStatusPointer);
1010 LOCALASSERT(sbPtr->SBdptr != NULL);
1011
1012 /* get rid of the displayblock */
1013 i = DestroyActiveObject(sbPtr->SBdptr);
1014 LOCALASSERT(i==0);
1015 sbPtr->SBdptr = NULL;
1016
1017 /* xenoborg data block init */
1018 if(xenoStatusPointer->behaviourState != XS_Dying) {
1019 xenoStatusPointer->stateTimer=0;
1020 }
1021
1022 /* zero linear velocity in dynamics block */
1023 sbPtr->DynPtr->LinVelocity.vx = 0;
1024 sbPtr->DynPtr->LinVelocity.vy = 0;
1025 sbPtr->DynPtr->LinVelocity.vz = 0;
1026
1027 xenoStatusPointer->IAmFar=1;
1028
1029 }
1030
Xenoborg_ActivateAllDeltas(STRATEGYBLOCK * sbPtr)1031 void Xenoborg_ActivateAllDeltas(STRATEGYBLOCK *sbPtr)
1032 {
1033 XENO_STATUS_BLOCK *xenoStatusPointer;
1034
1035 LOCALASSERT(sbPtr);
1036 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
1037 LOCALASSERT(xenoStatusPointer);
1038
1039 if (xenoStatusPointer->head_pan) {
1040 xenoStatusPointer->head_pan->Active=1;
1041 }
1042
1043 if (xenoStatusPointer->head_tilt) {
1044 xenoStatusPointer->head_tilt->Active=1;
1045 }
1046
1047 if (xenoStatusPointer->left_arm_pan) {
1048 xenoStatusPointer->left_arm_pan->Active=1;
1049 }
1050
1051 if (xenoStatusPointer->left_arm_tilt) {
1052 xenoStatusPointer->left_arm_tilt->Active=1;
1053 }
1054
1055 if (xenoStatusPointer->right_arm_pan) {
1056 xenoStatusPointer->right_arm_pan->Active=1;
1057 }
1058
1059 if (xenoStatusPointer->right_arm_tilt) {
1060 xenoStatusPointer->right_arm_tilt->Active=1;
1061 }
1062
1063 if (xenoStatusPointer->torso_twist) {
1064 xenoStatusPointer->torso_twist->Active=1;
1065 }
1066
1067 }
1068
Xenoborg_DeactivateAllDeltas(STRATEGYBLOCK * sbPtr)1069 void Xenoborg_DeactivateAllDeltas(STRATEGYBLOCK *sbPtr)
1070 {
1071 XENO_STATUS_BLOCK *xenoStatusPointer;
1072
1073 LOCALASSERT(sbPtr);
1074 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
1075 LOCALASSERT(xenoStatusPointer);
1076
1077 if (xenoStatusPointer->head_pan) {
1078 xenoStatusPointer->head_pan->Active=0;
1079 }
1080 xenoStatusPointer->Head_Pan=0;
1081
1082 if (xenoStatusPointer->head_tilt) {
1083 xenoStatusPointer->head_tilt->Active=0;
1084 }
1085 xenoStatusPointer->Head_Tilt=0;
1086
1087 if (xenoStatusPointer->left_arm_pan) {
1088 xenoStatusPointer->left_arm_pan->Active=0;
1089 }
1090 xenoStatusPointer->Left_Arm_Pan=0;
1091
1092 if (xenoStatusPointer->left_arm_tilt) {
1093 xenoStatusPointer->left_arm_tilt->Active=0;
1094 }
1095 xenoStatusPointer->Left_Arm_Tilt=0;
1096
1097 if (xenoStatusPointer->right_arm_pan) {
1098 xenoStatusPointer->right_arm_pan->Active=0;
1099 }
1100 xenoStatusPointer->Right_Arm_Pan=0;
1101
1102 if (xenoStatusPointer->right_arm_tilt) {
1103 xenoStatusPointer->right_arm_tilt->Active=0;
1104 }
1105 xenoStatusPointer->Right_Arm_Tilt=0;
1106
1107 if (xenoStatusPointer->torso_twist) {
1108 xenoStatusPointer->torso_twist->Active=0;
1109 }
1110 xenoStatusPointer->Torso_Twist=0;
1111
1112 }
1113
XenoborgIsDamaged(STRATEGYBLOCK * sbPtr,DAMAGE_PROFILE * damage,int multiple,int wounds,VECTORCH * incoming)1114 void XenoborgIsDamaged(STRATEGYBLOCK *sbPtr, DAMAGE_PROFILE *damage, int multiple, int wounds,VECTORCH *incoming)
1115 {
1116
1117 XENO_STATUS_BLOCK *xenoStatusPointer;
1118 LOCALASSERT(sbPtr);
1119 LOCALASSERT(sbPtr->DynPtr);
1120 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
1121 LOCALASSERT(xenoStatusPointer);
1122
1123 xenoStatusPointer->Wounds|=wounds;
1124 xenoStatusPointer->ShotThisFrame=1;
1125
1126 if (sbPtr->SBDamageBlock.Health <= 0) {
1127
1128 /* Oh yes, kill them, too. */
1129 if (xenoStatusPointer->behaviourState!=XS_Dying) {
1130 CurrentGameStats_CreatureKilled(sbPtr,NULL);
1131 KillXeno(sbPtr,wounds,damage,multiple,incoming);
1132 }
1133 }
1134
1135 if (xenoStatusPointer->behaviourState==XS_Inactive) {
1136 if (xenoStatusPointer->stateTimer>=XENO_POWERDOWN_TIME) {
1137 /* Ow, that hurt. */
1138 Xeno_Enter_PowerUp_State(sbPtr);
1139 }
1140 }
1141
1142 xenoStatusPointer->Target=NULL;
1143 }
1144
1145 /* patrick 29/7/97 -----------------------------------
1146 Thess functions to be called only from behaviour
1147 ------------------------------------------------------*/
KillXeno(STRATEGYBLOCK * sbPtr,int wounds,DAMAGE_PROFILE * damage,int multiple,VECTORCH * incoming)1148 static void KillXeno(STRATEGYBLOCK *sbPtr,int wounds,DAMAGE_PROFILE *damage, int multiple,VECTORCH *incoming)
1149 {
1150 XENO_STATUS_BLOCK *xenoStatusPointer;
1151 int deathtype,tkd;
1152
1153 LOCALASSERT(sbPtr);
1154 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
1155 LOCALASSERT(xenoStatusPointer);
1156
1157 /* make an explosion sound */
1158 Sound_Play(SID_SENTRYGUNDEST,"d",&sbPtr->DynPtr->Position);
1159
1160 xenoStatusPointer->stateTimer=XENO_DYINGTIME;
1161 xenoStatusPointer->HModelController.Looped=0;
1162 xenoStatusPointer->HModelController.LoopAfterTweening=0;
1163 /* switch state */
1164 xenoStatusPointer->behaviourState=XS_Dying;
1165
1166 Xenoborg_DeactivateAllDeltas(sbPtr);
1167 Xeno_SwitchLED(sbPtr,0);
1168
1169 if(xenoStatusPointer->death_target_sbptr)
1170 {
1171 RequestState(xenoStatusPointer->death_target_sbptr,xenoStatusPointer->death_target_request, 0);
1172 }
1173
1174
1175 if (xenoStatusPointer->soundHandle1!=SOUND_NOACTIVEINDEX) {
1176 /* Well, it shouldn't be! */
1177 Sound_Stop(xenoStatusPointer->soundHandle1);
1178 }
1179 if (xenoStatusPointer->soundHandle2!=SOUND_NOACTIVEINDEX) {
1180 /* Well, it shouldn't be! */
1181 Sound_Stop(xenoStatusPointer->soundHandle2);
1182 }
1183 if (xenoStatusPointer->head_whirr!=SOUND_NOACTIVEINDEX) {
1184 /* Well, it shouldn't be! */
1185 Sound_Stop(xenoStatusPointer->head_whirr);
1186 }
1187 if (xenoStatusPointer->left_arm_whirr!=SOUND_NOACTIVEINDEX) {
1188 /* Well, it shouldn't be! */
1189 Sound_Stop(xenoStatusPointer->left_arm_whirr);
1190 }
1191 if (xenoStatusPointer->right_arm_whirr!=SOUND_NOACTIVEINDEX) {
1192 /* Well, it shouldn't be! */
1193 Sound_Stop(xenoStatusPointer->right_arm_whirr);
1194 }
1195 if (xenoStatusPointer->torso_whirr!=SOUND_NOACTIVEINDEX) {
1196 /* Well, it shouldn't be! */
1197 Sound_Stop(xenoStatusPointer->torso_whirr);
1198 }
1199
1200 /* Set up gibb factor. */
1201
1202 tkd=TotalKineticDamage(damage);
1203 deathtype=0;
1204
1205 if (tkd>40) {
1206 /* Explosion case. */
1207 if (MUL_FIXED(tkd,(multiple&((ONE_FIXED<<1)-1)))>20) {
1208 /* Okay, you can gibb now. */
1209 xenoStatusPointer->GibbFactor=-(ONE_FIXED>>3);
1210 deathtype=2;
1211 }
1212 } else if ( (multiple>>16)>1 ) {
1213 int newmult;
1214
1215 newmult=DIV_FIXED(multiple,NormalFrameTime);
1216 if (MUL_FIXED(tkd,newmult)>700) {
1217 /* Excessive bullets case 1. */
1218 xenoStatusPointer->GibbFactor=-(ONE_FIXED>>5);
1219 deathtype=2;
1220 } else if (MUL_FIXED(tkd,newmult)>250) {
1221 /* Excessive bullets case 2. */
1222 //xenoStatusPointer->GibbFactor=ONE_FIXED>>6;
1223 deathtype=1;
1224 }
1225 }
1226
1227 if (tkd>200) {
1228 /* Basically SADARS only. */
1229 xenoStatusPointer->GibbFactor=-(ONE_FIXED>>2);
1230
1231 deathtype=3;
1232 }
1233
1234 /* No gibbing for flamethrower. */
1235
1236 {
1237 SECTION_DATA *chest=GetThisSectionData(xenoStatusPointer->HModelController.section_data,"chest");
1238
1239 if (chest==NULL) {
1240 /* I'm impressed. */
1241 deathtype+=2;
1242 } else if ((chest->flags§ion_data_notreal)
1243 &&(chest->flags§ion_data_terminate_here)) {
1244 /* That's gotta hurt. */
1245 deathtype++;
1246 }
1247 }
1248
1249
1250 {
1251 DEATH_DATA *this_death;
1252 HIT_FACING facing;
1253
1254 facing.Front=0;
1255 facing.Back=0;
1256 facing.Left=0;
1257 facing.Right=0;
1258
1259 if (incoming) {
1260 if (incoming->vz>0) {
1261 facing.Back=1;
1262 } else {
1263 facing.Front=1;
1264 }
1265 if (incoming->vx>0) {
1266 facing.Right=1;
1267 } else {
1268 facing.Left=1;
1269 }
1270 }
1271
1272 this_death=GetXenoborgDeathSequence(&xenoStatusPointer->HModelController,NULL,
1273 xenoStatusPointer->Wounds,(xenoStatusPointer->Wounds&(
1274 section_flag_left_leg|section_flag_right_leg|section_flag_left_foot|section_flag_right_foot)),
1275 deathtype,&facing,0,0,0);
1276
1277 GLOBALASSERT(this_death);
1278
1279 Convert_Xenoborg_To_Corpse(sbPtr,this_death);
1280 }
1281
1282 }
1283
Execute_Xeno_Dying(STRATEGYBLOCK * sbPtr)1284 void Execute_Xeno_Dying(STRATEGYBLOCK *sbPtr)
1285 {
1286 XENO_STATUS_BLOCK *xenoStatusPointer;
1287
1288 LOCALASSERT(sbPtr);
1289 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
1290 LOCALASSERT(xenoStatusPointer);
1291
1292 {
1293 DISPLAYBLOCK *dispPtr = sbPtr->SBdptr;
1294 /* do we have a displayblock? */
1295 if (dispPtr)
1296 {
1297 dispPtr->SpecialFXFlags |= SFXFLAG_MELTINGINTOGROUND;
1298 dispPtr->ObFlags2 = xenoStatusPointer->stateTimer/2;
1299 if (dispPtr->ObFlags2<ONE_FIXED) {
1300 xenoStatusPointer->HModelController.DisableBleeding=1;
1301 }
1302 }
1303 }
1304 xenoStatusPointer->stateTimer -= NormalFrameTime;
1305 }
1306
EnforceXenoborgShapeAnimSequence_Core(STRATEGYBLOCK * sbPtr,HMODEL_SEQUENCE_TYPES type,int subtype,int length,int tweeningtime)1307 void EnforceXenoborgShapeAnimSequence_Core(STRATEGYBLOCK *sbPtr,HMODEL_SEQUENCE_TYPES type, int subtype, int length, int tweeningtime) {
1308
1309 XENO_STATUS_BLOCK *xenoStatus;
1310
1311 xenoStatus=(XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
1312
1313 if ((xenoStatus->HModelController.Sequence_Type==type)
1314 &&(xenoStatus->HModelController.Sub_Sequence==subtype)) {
1315 return;
1316 } else {
1317 SetXenoborgShapeAnimSequence_Core(sbPtr,type,subtype,length,tweeningtime);
1318 }
1319 }
1320
SetXenoborgShapeAnimSequence_Core(STRATEGYBLOCK * sbPtr,HMODEL_SEQUENCE_TYPES type,int subtype,int length,int tweeningtime)1321 void SetXenoborgShapeAnimSequence_Core(STRATEGYBLOCK *sbPtr,HMODEL_SEQUENCE_TYPES type, int subtype, int length, int tweeningtime)
1322 {
1323
1324 XENO_STATUS_BLOCK *xenoStatus=(XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
1325
1326 GLOBALASSERT(length!=0);
1327
1328 if (tweeningtime<=0) {
1329 InitHModelSequence(&xenoStatus->HModelController,(int)type,subtype,length);
1330 } else {
1331 InitHModelTweening(&xenoStatus->HModelController, tweeningtime, (int)type,subtype,length, 1);
1332 //xenoStatus->HModelController.ElevationTweening=1;
1333 }
1334
1335 xenoStatus->HModelController.Playing=1;
1336 /* Might be unset... */
1337 }
1338
SetXenoborgShapeAnimSequence(STRATEGYBLOCK * sbPtr,HMODEL_SEQUENCE_TYPES type,int subtype,int length)1339 void SetXenoborgShapeAnimSequence(STRATEGYBLOCK *sbPtr,HMODEL_SEQUENCE_TYPES type, int subtype, int length) {
1340
1341 SetXenoborgShapeAnimSequence_Core(sbPtr,type,subtype,length,(ONE_FIXED>>2));
1342
1343 }
1344
Xenoborg_GetRelativeAngles(STRATEGYBLOCK * sbPtr,int * anglex,int * angley,VECTORCH * pivotPoint)1345 void Xenoborg_GetRelativeAngles(STRATEGYBLOCK *sbPtr, int *anglex, int *angley, VECTORCH *pivotPoint) {
1346
1347 XENO_STATUS_BLOCK *xenoStatusPointer;
1348 MATRIXCH WtoL;
1349 VECTORCH targetPos;
1350
1351 LOCALASSERT(sbPtr);
1352 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
1353 LOCALASSERT(xenoStatusPointer);
1354
1355 /* First, extract relative angle. */
1356
1357 WtoL=sbPtr->DynPtr->OrientMat;
1358 TransposeMatrixCH(&WtoL);
1359 targetPos=xenoStatusPointer->targetTrackPos;
1360 targetPos.vx-=pivotPoint->vx;
1361 targetPos.vy-=pivotPoint->vy;
1362 targetPos.vz-=pivotPoint->vz;
1363 RotateVector(&targetPos,&WtoL);
1364
1365 /* Now... */
1366 {
1367 int offsetx,offsety,offsetz,offseta;
1368
1369 offsetx=(targetPos.vx);
1370 offsety=(targetPos.vz);
1371 offseta=-(targetPos.vy);
1372
1373 while( (offsetx>(ONE_FIXED>>2))
1374 ||(offsety>(ONE_FIXED>>2))
1375 ||(offseta>(ONE_FIXED>>2))
1376 ||(offsetx<-(ONE_FIXED>>2))
1377 ||(offsety<-(ONE_FIXED>>2))
1378 ||(offseta<-(ONE_FIXED>>2))) {
1379
1380 offsetx>>=1;
1381 offsety>>=1;
1382 offseta>>=1;
1383
1384 }
1385
1386 offsetz=SqRoot32((offsetx*offsetx)+(offsety*offsety));
1387
1388 if (angley) {
1389 (*angley)=ArcTan(offseta,offsetz);
1390
1391 if ((*angley)>=3072) (*angley)-=4096;
1392 if ((*angley)>=2048) (*angley)=(*angley)-3072;
1393 if ((*angley)> 1024) (*angley)=2048-(*angley);
1394
1395 }
1396 if (anglex) {
1397 (*anglex)=ArcTan(offsetx,offsety);
1398
1399 if ((*anglex)>=3072) (*anglex)-=4096;
1400 if ((*anglex)>=2048) (*anglex)=(*anglex)-4096;
1401
1402 }
1403 }
1404
1405 }
1406
Execute_Xeno_Inactive(STRATEGYBLOCK * sbPtr)1407 void Execute_Xeno_Inactive(STRATEGYBLOCK *sbPtr)
1408 {
1409 XENO_STATUS_BLOCK *xenoStatusPointer;
1410 NPC_DATA *NpcData;
1411
1412 LOCALASSERT(sbPtr);
1413 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
1414 LOCALASSERT(xenoStatusPointer);
1415
1416 NpcData=GetThisNpcData(I_NPC_Xenoborg);
1417
1418 if (ShowXenoStats) {
1419 PrintDebuggingText("In Inactive.\n");
1420 }
1421
1422 if (!sbPtr->SBdptr) {
1423 /* We're far... do the timer! */
1424 ProveHModel_Far(&xenoStatusPointer->HModelController,sbPtr);
1425 }
1426
1427 /* Regenerate a bit? */
1428
1429 if (sbPtr->SBDamageBlock.Health>0) {
1430 int health_increment;
1431
1432 health_increment=DIV_FIXED((NpcData->StartingStats.Health*NormalFrameTime),XENO_REGEN_TIME);
1433 sbPtr->SBDamageBlock.Health+=health_increment;
1434
1435 if (sbPtr->SBDamageBlock.Health>(NpcData->StartingStats.Health<<ONE_FIXED_SHIFT)) {
1436 sbPtr->SBDamageBlock.Health=(NpcData->StartingStats.Health<<ONE_FIXED_SHIFT);
1437 }
1438
1439 HModel_Regen(&xenoStatusPointer->HModelController,XENO_REGEN_TIME);
1440 }
1441
1442 if (xenoStatusPointer->stateTimer<XENO_POWERDOWN_TIME) {
1443 xenoStatusPointer->stateTimer+=NormalFrameTime;
1444 } else {
1445 /* Tum te tum te tum. */
1446
1447 if (Xeno_Activation_Test(sbPtr)) {
1448 /* Oh well, orange alert. */
1449 Xeno_Enter_PowerUp_State(sbPtr);
1450 }
1451 }
1452 }
1453
Xeno_Enter_PowerUp_State(STRATEGYBLOCK * sbPtr)1454 void Xeno_Enter_PowerUp_State(STRATEGYBLOCK *sbPtr)
1455 {
1456 XENO_STATUS_BLOCK *xenoStatusPointer;
1457
1458 LOCALASSERT(sbPtr);
1459 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
1460 LOCALASSERT(xenoStatusPointer);
1461
1462 if (xenoStatusPointer->behaviourState!=XS_Inactive) {
1463 /* Ha! */
1464 return;
1465 }
1466
1467 xenoStatusPointer->Target=NULL;
1468 xenoStatusPointer->stateTimer=0;
1469 xenoStatusPointer->behaviourState=XS_Activating;
1470
1471 GLOBALASSERT(xenoStatusPointer->HModelController.Sequence_Type==HMSQT_Xenoborg);
1472 GLOBALASSERT(xenoStatusPointer->HModelController.Sub_Sequence==XBSS_Powered_Down_Standard);
1473
1474 SetXenoborgShapeAnimSequence_Core(sbPtr,HMSQT_Xenoborg,XBSS_Power_Up,(ONE_FIXED*4),(ONE_FIXED>>2));
1475
1476 xenoStatusPointer->HModelController.LoopAfterTweening=0;
1477
1478 Xenoborg_ActivateAllDeltas(sbPtr);
1479 Xeno_SwitchLED(sbPtr,1);
1480
1481 /* Now play with a sound. */
1482
1483 if (xenoStatusPointer->soundHandle1!=SOUND_NOACTIVEINDEX) {
1484 /* Well, it shouldn't be! */
1485 Sound_Stop(xenoStatusPointer->soundHandle1);
1486 }
1487 if (xenoStatusPointer->soundHandle2!=SOUND_NOACTIVEINDEX) {
1488 /* Well, it shouldn't be! */
1489 Sound_Stop(xenoStatusPointer->soundHandle2);
1490 }
1491 Sound_Play(SID_POWERUP,"de",&sbPtr->DynPtr->Position,&xenoStatusPointer->soundHandle1);
1492 }
1493
Xeno_Enter_PowerDown_State(STRATEGYBLOCK * sbPtr)1494 void Xeno_Enter_PowerDown_State(STRATEGYBLOCK *sbPtr)
1495 {
1496 XENO_STATUS_BLOCK *xenoStatusPointer;
1497
1498 LOCALASSERT(sbPtr);
1499 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
1500 LOCALASSERT(xenoStatusPointer);
1501
1502 if (xenoStatusPointer->behaviourState==XS_Inactive) {
1503 /* Ha! */
1504 return;
1505 }
1506
1507 xenoStatusPointer->Target=NULL;
1508 xenoStatusPointer->stateTimer=0;
1509 xenoStatusPointer->behaviourState=XS_Deactivating;
1510
1511 SetXenoborgShapeAnimSequence_Core(sbPtr,HMSQT_Xenoborg,XBSS_Power_Down,ONE_FIXED,(ONE_FIXED>>2));
1512
1513 xenoStatusPointer->HModelController.LoopAfterTweening=0;
1514
1515 /* zero velocity */
1516 LOCALASSERT(sbPtr->DynPtr);
1517 sbPtr->DynPtr->LinVelocity.vx = 0;
1518 sbPtr->DynPtr->LinVelocity.vy = 0;
1519 sbPtr->DynPtr->LinVelocity.vz = 0;
1520
1521 Xenoborg_DeactivateAllDeltas(sbPtr);
1522 Xeno_SwitchLED(sbPtr,0);
1523
1524 if (xenoStatusPointer->soundHandle1!=SOUND_NOACTIVEINDEX) {
1525 /* Well, it shouldn't be! */
1526 Sound_Stop(xenoStatusPointer->soundHandle1);
1527 }
1528 if (xenoStatusPointer->soundHandle2!=SOUND_NOACTIVEINDEX) {
1529 /* Stop BorgOn. */
1530 Sound_Stop(xenoStatusPointer->soundHandle2);
1531 }
1532 Sound_Play(SID_POWERDN,"de",&sbPtr->DynPtr->Position,&xenoStatusPointer->soundHandle1);
1533
1534 }
1535
Xeno_Enter_ActiveWait_State(STRATEGYBLOCK * sbPtr)1536 void Xeno_Enter_ActiveWait_State(STRATEGYBLOCK *sbPtr)
1537 {
1538 XENO_STATUS_BLOCK *xenoStatusPointer;
1539
1540 LOCALASSERT(sbPtr);
1541 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
1542 LOCALASSERT(xenoStatusPointer);
1543
1544 xenoStatusPointer->stateTimer=0;
1545 xenoStatusPointer->behaviourState=XS_ActiveWait;
1546
1547 SetXenoborgShapeAnimSequence_Core(sbPtr,HMSQT_Xenoborg,XBSS_Powered_Up_Standard,ONE_FIXED,(ONE_FIXED>>2));
1548
1549 /* zero velocity */
1550 LOCALASSERT(sbPtr->DynPtr);
1551 sbPtr->DynPtr->LinVelocity.vx = 0;
1552 sbPtr->DynPtr->LinVelocity.vy = 0;
1553 sbPtr->DynPtr->LinVelocity.vz = 0;
1554
1555 if (xenoStatusPointer->soundHandle1!=SOUND_NOACTIVEINDEX) {
1556 /* Well, it shouldn't be! */
1557 Sound_Stop(xenoStatusPointer->soundHandle1);
1558 }
1559
1560 }
1561
Xeno_Enter_TurnToFace_State(STRATEGYBLOCK * sbPtr)1562 void Xeno_Enter_TurnToFace_State(STRATEGYBLOCK *sbPtr)
1563 {
1564 XENO_STATUS_BLOCK *xenoStatusPointer;
1565
1566 LOCALASSERT(sbPtr);
1567 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
1568 LOCALASSERT(xenoStatusPointer);
1569
1570 xenoStatusPointer->stateTimer=0;
1571 xenoStatusPointer->behaviourState=XS_TurnToFace;
1572
1573 /* Sequence handled in the behaviour. */
1574
1575 if (xenoStatusPointer->soundHandle1!=SOUND_NOACTIVEINDEX) {
1576 /* Well, it shouldn't be! */
1577 Sound_Stop(xenoStatusPointer->soundHandle1);
1578 }
1579 Sound_Play(SID_LOADMOVE,"del",&sbPtr->DynPtr->Position,&xenoStatusPointer->soundHandle1);
1580
1581 /* zero velocity */
1582 LOCALASSERT(sbPtr->DynPtr);
1583 sbPtr->DynPtr->LinVelocity.vx = 0;
1584 sbPtr->DynPtr->LinVelocity.vy = 0;
1585 sbPtr->DynPtr->LinVelocity.vz = 0;
1586
1587 }
1588
Xeno_Enter_Following_State(STRATEGYBLOCK * sbPtr)1589 void Xeno_Enter_Following_State(STRATEGYBLOCK *sbPtr)
1590 {
1591 XENO_STATUS_BLOCK *xenoStatusPointer;
1592
1593 LOCALASSERT(sbPtr);
1594 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
1595 LOCALASSERT(xenoStatusPointer);
1596
1597 xenoStatusPointer->stateTimer=0;
1598 xenoStatusPointer->behaviourState=XS_Following;
1599 InitWaypointManager(&xenoStatusPointer->waypointManager);
1600
1601 /* Sequence handled in the behaviour. */
1602
1603 if (xenoStatusPointer->soundHandle1!=SOUND_NOACTIVEINDEX) {
1604 /* Well, it shouldn't be! */
1605 Sound_Stop(xenoStatusPointer->soundHandle1);
1606 }
1607 Sound_Play(SID_LOADMOVE,"del",&sbPtr->DynPtr->Position,&xenoStatusPointer->soundHandle1);
1608
1609 }
1610
Xeno_Enter_Returning_State(STRATEGYBLOCK * sbPtr)1611 void Xeno_Enter_Returning_State(STRATEGYBLOCK *sbPtr)
1612 {
1613 XENO_STATUS_BLOCK *xenoStatusPointer;
1614
1615 LOCALASSERT(sbPtr);
1616 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
1617 LOCALASSERT(xenoStatusPointer);
1618
1619 xenoStatusPointer->stateTimer=0;
1620 xenoStatusPointer->behaviourState=XS_Returning;
1621 InitWaypointManager(&xenoStatusPointer->waypointManager);
1622
1623 /* Sequence handled in the behaviour. */
1624
1625 xenoStatusPointer->Target=NULL;
1626 /* Forget your target, too. */
1627
1628 if (xenoStatusPointer->soundHandle1!=SOUND_NOACTIVEINDEX) {
1629 /* Well, it shouldn't be! */
1630 Sound_Stop(xenoStatusPointer->soundHandle1);
1631 }
1632 Sound_Play(SID_LOADMOVE,"del",&sbPtr->DynPtr->Position,&xenoStatusPointer->soundHandle1);
1633
1634 }
1635
Xeno_Enter_Dormant_State(STRATEGYBLOCK * sbPtr)1636 void Xeno_Enter_Dormant_State(STRATEGYBLOCK *sbPtr)
1637 {
1638 XENO_STATUS_BLOCK *xenoStatusPointer;
1639
1640 LOCALASSERT(sbPtr);
1641 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
1642 LOCALASSERT(xenoStatusPointer);
1643
1644 xenoStatusPointer->stateTimer=0;
1645 xenoStatusPointer->behaviourState=XS_Inactive;
1646
1647 SetXenoborgShapeAnimSequence_Core(sbPtr,HMSQT_Xenoborg,XBSS_Powered_Down_Standard,ONE_FIXED,(ONE_FIXED>>2));
1648
1649 if (xenoStatusPointer->soundHandle2!=SOUND_NOACTIVEINDEX) {
1650 /* Well, it shouldn't be! */
1651 Sound_Stop(xenoStatusPointer->soundHandle2);
1652 }
1653 /* soundHandle1 might be still powering down. */
1654
1655 /* zero velocity */
1656 LOCALASSERT(sbPtr->DynPtr);
1657 sbPtr->DynPtr->LinVelocity.vx = 0;
1658 sbPtr->DynPtr->LinVelocity.vy = 0;
1659 sbPtr->DynPtr->LinVelocity.vz = 0;
1660
1661 }
1662
Xeno_Enter_Avoidance_State(STRATEGYBLOCK * sbPtr)1663 void Xeno_Enter_Avoidance_State(STRATEGYBLOCK *sbPtr) {
1664
1665 XENO_STATUS_BLOCK *xenoStatusPointer;
1666
1667 LOCALASSERT(sbPtr);
1668 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
1669 LOCALASSERT(xenoStatusPointer);
1670
1671 /* Make sure obstruction is set! */
1672
1673 NPC_InitMovementData(&(xenoStatusPointer->moveData));
1674 NPCGetAvoidanceDirection(sbPtr, &(xenoStatusPointer->moveData.avoidanceDirn),&xenoStatusPointer->obstruction);
1675 xenoStatusPointer->lastState=xenoStatusPointer->behaviourState;
1676 xenoStatusPointer->behaviourState = XS_Avoidance;
1677 xenoStatusPointer->stateTimer = NPC_AVOIDTIME;
1678 InitWaypointManager(&xenoStatusPointer->waypointManager);
1679
1680 if (xenoStatusPointer->soundHandle1!=SOUND_NOACTIVEINDEX) {
1681 /* Well, it shouldn't be! */
1682 Sound_Stop(xenoStatusPointer->soundHandle1);
1683 }
1684 Sound_Play(SID_LOADMOVE,"del",&sbPtr->DynPtr->Position,&xenoStatusPointer->soundHandle1);
1685
1686 }
1687
Xeno_Enter_ShootingTheRoof_State(STRATEGYBLOCK * sbPtr)1688 void Xeno_Enter_ShootingTheRoof_State(STRATEGYBLOCK *sbPtr)
1689 {
1690 XENO_STATUS_BLOCK *xenoStatusPointer;
1691
1692 LOCALASSERT(sbPtr);
1693 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
1694 LOCALASSERT(xenoStatusPointer);
1695
1696 xenoStatusPointer->stateTimer=0;
1697 xenoStatusPointer->behaviourState=XS_ShootingTheRoof;
1698
1699 /* Sequence handled in the behaviour. */
1700
1701 if (xenoStatusPointer->soundHandle1!=SOUND_NOACTIVEINDEX) {
1702 /* Well, it shouldn't be! */
1703 Sound_Stop(xenoStatusPointer->soundHandle1);
1704 }
1705 Sound_Play(SID_LOADMOVE,"del",&sbPtr->DynPtr->Position,&xenoStatusPointer->soundHandle1);
1706
1707 /* zero velocity */
1708 LOCALASSERT(sbPtr->DynPtr);
1709 sbPtr->DynPtr->LinVelocity.vx = 0;
1710 sbPtr->DynPtr->LinVelocity.vy = 0;
1711 sbPtr->DynPtr->LinVelocity.vz = 0;
1712
1713 }
1714
Xeno_CopeWithLossOfHome(STRATEGYBLOCK * sbPtr)1715 void Xeno_CopeWithLossOfHome(STRATEGYBLOCK *sbPtr) {
1716
1717 XENO_STATUS_BLOCK *xenoStatusPointer;
1718
1719 LOCALASSERT(sbPtr);
1720 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
1721 LOCALASSERT(xenoStatusPointer);
1722
1723 /* Ooh, yuck. */
1724
1725 xenoStatusPointer->my_module=sbPtr->containingModule->m_aimodule;
1726 xenoStatusPointer->my_spot_therin=sbPtr->DynPtr->Position;
1727
1728 }
1729
Execute_Xeno_PowerUp(STRATEGYBLOCK * sbPtr)1730 void Execute_Xeno_PowerUp(STRATEGYBLOCK *sbPtr)
1731 {
1732 XENO_STATUS_BLOCK *xenoStatusPointer;
1733
1734 LOCALASSERT(sbPtr);
1735 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
1736 LOCALASSERT(xenoStatusPointer);
1737
1738 /* Wait to finish, I guess... */
1739
1740 if (ShowXenoStats) {
1741 PrintDebuggingText("In PowerUp.\n");
1742 }
1743
1744 if (!sbPtr->SBdptr) {
1745 /* We're far... do the timer! */
1746 ProveHModel_Far(&xenoStatusPointer->HModelController,sbPtr);
1747 }
1748
1749 xenoStatusPointer->Target=NULL;
1750 xenoStatusPointer->stateTimer+=NormalFrameTime;
1751
1752 if (xenoStatusPointer->soundHandle2==SOUND_NOACTIVEINDEX) {
1753 if (xenoStatusPointer->stateTimer>((ONE_FIXED*5)/2)) {
1754 /* Time to start the BorgOn sound. */
1755 Sound_Play(SID_BORGON,"del",&sbPtr->DynPtr->Position,&xenoStatusPointer->soundHandle2);
1756 }
1757 }
1758 if ((xenoStatusPointer->HModelController.Tweening==Controller_NoTweening)
1759 &&(xenoStatusPointer->HModelController.sequence_timer==(ONE_FIXED-1))) {
1760
1761 Xeno_Enter_ActiveWait_State(sbPtr);
1762 }
1763
1764
1765 }
1766
Execute_Xeno_PowerDown(STRATEGYBLOCK * sbPtr)1767 void Execute_Xeno_PowerDown(STRATEGYBLOCK *sbPtr)
1768 {
1769 XENO_STATUS_BLOCK *xenoStatusPointer;
1770
1771 LOCALASSERT(sbPtr);
1772 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
1773 LOCALASSERT(xenoStatusPointer);
1774
1775 if (ShowXenoStats) {
1776 PrintDebuggingText("In PowerDown.\n");
1777 }
1778
1779 EnforceXenoborgShapeAnimSequence_Core(sbPtr,HMSQT_Xenoborg,XBSS_Power_Down,ONE_FIXED,(ONE_FIXED>>2));
1780 xenoStatusPointer->HModelController.LoopAfterTweening=0;
1781 xenoStatusPointer->HModelController.Looped=0;
1782
1783 if (!sbPtr->SBdptr) {
1784 /* We're far... do the timer! */
1785 ProveHModel_Far(&xenoStatusPointer->HModelController,sbPtr);
1786 }
1787
1788 /* Wait to finish, I guess... */
1789
1790 xenoStatusPointer->Target=NULL;
1791
1792 if ((xenoStatusPointer->HModelController.Tweening==Controller_NoTweening)
1793 &&(xenoStatusPointer->HModelController.sequence_timer==(ONE_FIXED-1))) {
1794
1795 Xeno_Enter_Dormant_State(sbPtr);
1796 }
1797
1798
1799 }
1800
Xeno_TurnAndTarget(STRATEGYBLOCK * sbPtr,int * ref_anglex,int * ref_angley)1801 void Xeno_TurnAndTarget(STRATEGYBLOCK *sbPtr, int *ref_anglex,int *ref_angley) {
1802
1803 XENO_STATUS_BLOCK *xenoStatusPointer;
1804 int anglex,angley;
1805
1806 LOCALASSERT(sbPtr);
1807 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
1808 LOCALASSERT(xenoStatusPointer);
1809
1810 {
1811 SECTION_DATA *head_section;
1812
1813 head_section=GetThisSectionData(xenoStatusPointer->HModelController.section_data,"neck");
1814 GLOBALASSERT(head_section);
1815
1816 Xenoborg_GetRelativeAngles(sbPtr,&anglex,&angley,&head_section->World_Offset);
1817
1818 }
1819
1820 *ref_anglex=anglex;
1821 *ref_angley=angley;
1822
1823 /* Start turning / targeting procedure. */
1824 #if 0
1825 if ((xenoStatusPointer->headLock)
1826 ||(anglex>((((xenoStatusPointer->Torso_Twist>>4)+XENO_HEADPAN_GIMBALL)*7)/8))
1827 ||(anglex<((((xenoStatusPointer->Torso_Twist>>4)-XENO_HEADPAN_GIMBALL)*7)/8))) {
1828
1829 Xeno_TorsoMovement_TrackToAngle(sbPtr,XENO_TORSO_TWIST_RATE,anglex);
1830
1831 }
1832 #else
1833 /* Always torso twist. */
1834 Xeno_TorsoMovement_TrackToAngle(sbPtr,XENO_TORSO_TWIST_RATE,anglex);
1835 #endif
1836 xenoStatusPointer->headLock=Xeno_HeadMovement_TrackToAngles(sbPtr,XENO_HEAD_LOCK_RATE,anglex,angley);
1837
1838 /* Now the arm. */
1839
1840 if ((xenoStatusPointer->headLock)
1841 &&((anglex<XENO_LEFTARM_ACW_GIMBALL)||(anglex>-XENO_LEFTARM_CW_GIMBALL))) {
1842
1843 SECTION_DATA *this_section;
1844 int arm_anglex,arm_angley;
1845
1846 this_section=GetThisSectionData(xenoStatusPointer->HModelController.section_data,"left bicep");
1847 if (this_section) {
1848 Xenoborg_GetRelativeAngles(sbPtr,&arm_anglex,NULL,&this_section->World_Offset);
1849 } else {
1850 arm_anglex=0;
1851 }
1852
1853 this_section=GetThisSectionData(xenoStatusPointer->HModelController.section_data,"left forearm");
1854 if (this_section) {
1855 Xenoborg_GetRelativeAngles(sbPtr,NULL,&arm_angley,&this_section->World_Offset);
1856 } else {
1857 arm_angley=0;
1858 }
1859
1860 xenoStatusPointer->leftArmLock=Xeno_LeftArmMovement_TrackToAngles(sbPtr,XENO_ARM_LOCK_RATE,arm_anglex,arm_angley);
1861 }
1862
1863 if ((xenoStatusPointer->headLock)
1864 &&((anglex<XENO_RIGHTARM_ACW_GIMBALL)||(anglex>-XENO_RIGHTARM_CW_GIMBALL))) {
1865
1866 SECTION_DATA *this_section;
1867 int arm_anglex,arm_angley;
1868
1869 this_section=GetThisSectionData(xenoStatusPointer->HModelController.section_data,"right bicep");
1870 if (this_section) {
1871 Xenoborg_GetRelativeAngles(sbPtr,&arm_anglex,NULL,&this_section->World_Offset);
1872 } else {
1873 arm_anglex=0;
1874 }
1875
1876 this_section=GetThisSectionData(xenoStatusPointer->HModelController.section_data,"right forearm");
1877 if (this_section) {
1878 Xenoborg_GetRelativeAngles(sbPtr,NULL,&arm_angley,&this_section->World_Offset);
1879 } else {
1880 arm_angley=0;
1881 }
1882 xenoStatusPointer->rightArmLock=Xeno_RightArmMovement_TrackToAngles(sbPtr,XENO_ARM_LOCK_RATE,arm_anglex,arm_angley);
1883 }
1884 xenoStatusPointer->UseHeadLaser=1;
1885 }
1886
Xeno_Limbs_ShootTheRoof(STRATEGYBLOCK * sbPtr)1887 void Xeno_Limbs_ShootTheRoof(STRATEGYBLOCK *sbPtr) {
1888
1889 XENO_STATUS_BLOCK *xenoStatusPointer;
1890
1891 LOCALASSERT(sbPtr);
1892 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
1893 LOCALASSERT(xenoStatusPointer);
1894
1895
1896 Xeno_TorsoMovement_Centre(sbPtr,XENO_TORSO_TWIST_RATE);
1897 Xeno_LeftArmMovement_WaveUp(sbPtr,XENO_ARM_LOCK_RATE);
1898 Xeno_LeftArmMovement_TrackLeftRight(sbPtr,XENO_ARM_LOCK_RATE);
1899 Xeno_RightArmMovement_WaveUp(sbPtr,XENO_ARM_LOCK_RATE);
1900 Xeno_RightArmMovement_TrackLeftRight(sbPtr,XENO_ARM_LOCK_RATE);
1901 #if 0
1902 Xeno_HeadMovement_ScanLeftRight(sbPtr,XENO_HEAD_SCAN_RATE);
1903 Xeno_HeadMovement_ScanUpDown(sbPtr,XENO_HEAD_SCAN_RATE+2);
1904 #else
1905 Xeno_HeadMovement_TrackToAngles(sbPtr,XENO_HEAD_SCAN_RATE,0,XENO_HEADTILT_GIMBALL);
1906 #endif
1907 xenoStatusPointer->UseHeadLaser=0;
1908 xenoStatusPointer->UseRALaser=1;
1909 xenoStatusPointer->UseLALaser=1;
1910 xenoStatusPointer->FiringLeft=1;
1911 xenoStatusPointer->FiringRight=1;
1912
1913 }
1914
Execute_Xeno_ActiveWait(STRATEGYBLOCK * sbPtr)1915 void Execute_Xeno_ActiveWait(STRATEGYBLOCK *sbPtr)
1916 {
1917 XENO_STATUS_BLOCK *xenoStatusPointer;
1918 int anglex,angley,correctlyOrientated;
1919
1920 LOCALASSERT(sbPtr);
1921 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
1922 LOCALASSERT(xenoStatusPointer);
1923
1924 /* What to do? Do we have a target? */
1925
1926 if (ShowXenoStats) {
1927 PrintDebuggingText("In ActiveWait.\n");
1928 }
1929
1930 if (xenoStatusPointer->Target==NULL) {
1931 /* Let's wave the head around. */
1932 Xeno_TorsoMovement_Centre(sbPtr,XENO_TORSO_TWIST_RATE);
1933 Xeno_LeftArmMovement_Centre(sbPtr,XENO_ARM_LOCK_RATE);
1934 Xeno_RightArmMovement_Centre(sbPtr,XENO_ARM_LOCK_RATE);
1935 Xeno_HeadMovement_ScanLeftRight(sbPtr,XENO_HEAD_SCAN_RATE);
1936 Xeno_HeadMovement_ScanUpDown(sbPtr,XENO_HEAD_SCAN_RATE+2);
1937 xenoStatusPointer->UseHeadLaser=1;
1938 /* Are we at home? */
1939 if (sbPtr->containingModule->m_aimodule!=xenoStatusPointer->my_module) {
1940 Xeno_Enter_Returning_State(sbPtr);
1941 return;
1942 }
1943 /* Are we facing the right way? */
1944
1945 correctlyOrientated = NPCOrientateToVector(sbPtr, &xenoStatusPointer->my_orientdir_therin,(NPC_TURNRATE>>XENO_FOOT_TURN_RATE),NULL);
1946
1947 if (!correctlyOrientated) {
1948
1949 SECTION_DATA *master_section;
1950
1951 master_section=GetThisSectionData(xenoStatusPointer->HModelController.section_data,"pelvis presley");
1952 GLOBALASSERT(master_section);
1953
1954 Xenoborg_GetRelativeAngles(sbPtr,&anglex,&angley,&master_section->World_Offset);
1955
1956 if (anglex>0) {
1957 EnforceXenoborgShapeAnimSequence_Core(sbPtr,HMSQT_Xenoborg,XBSS_Turn_Right,XENO_TURNING_ANIM_SPEED,(ONE_FIXED>>2));
1958 } else {
1959 EnforceXenoborgShapeAnimSequence_Core(sbPtr,HMSQT_Xenoborg,XBSS_Turn_Left,XENO_TURNING_ANIM_SPEED,(ONE_FIXED>>2));
1960 }
1961 if (xenoStatusPointer->soundHandle1==SOUND_NOACTIVEINDEX) {
1962 Sound_Play(SID_LOADMOVE,"del",&sbPtr->DynPtr->Position,&xenoStatusPointer->soundHandle1);
1963 }
1964
1965 } else {
1966
1967 /* Otherwise just wait? */
1968 if (xenoStatusPointer->soundHandle1!=SOUND_NOACTIVEINDEX) {
1969 /* Well, it shouldn't be! */
1970 Sound_Stop(xenoStatusPointer->soundHandle1);
1971 }
1972 EnforceXenoborgShapeAnimSequence_Core(sbPtr,HMSQT_Xenoborg,XBSS_Powered_Up_Standard,ONE_FIXED,(ONE_FIXED>>2));
1973 xenoStatusPointer->stateTimer+=NormalFrameTime;
1974 if (xenoStatusPointer->stateTimer>xenoStatusPointer->UpTime) {
1975 Xeno_Enter_PowerDown_State(sbPtr);
1976 /* Voluntary powerdown! */
1977 xenoStatusPointer->stateTimer=XENO_POWERDOWN_TIME;
1978 }
1979 }
1980 return;
1981 }
1982
1983 GLOBALASSERT(xenoStatusPointer->Target);
1984 xenoStatusPointer->stateTimer=0;
1985 /* Now we have a target. Can we see it? */
1986 if (xenoStatusPointer->targetSightTest==0) {
1987 /* Can't see them. Are we out of range? */
1988 if (GetNextModuleForLink(sbPtr->containingModule->m_aimodule,
1989 xenoStatusPointer->my_module,(xenoStatusPointer->module_range)-1,0)==NULL) {
1990 Xeno_Enter_Returning_State(sbPtr);
1991 } else {
1992 Xeno_Enter_Following_State(sbPtr);
1993 }
1994 return;
1995 }
1996
1997 Xeno_TurnAndTarget(sbPtr,&anglex,&angley);
1998
1999 #if 0
2000 if ((anglex>(((XENO_HEADPAN_GIMBALL)*7)/8))
2001 ||(anglex<-(((XENO_HEADPAN_GIMBALL)*7)/8))) {
2002
2003 Xeno_Enter_TurnToFace_State(sbPtr);
2004
2005 }
2006 #else
2007 /* Always turn to face too? */
2008 Xeno_Enter_TurnToFace_State(sbPtr);
2009 #endif
2010
2011 }
2012
Execute_Xeno_TurnToFace(STRATEGYBLOCK * sbPtr)2013 void Execute_Xeno_TurnToFace(STRATEGYBLOCK *sbPtr)
2014 {
2015 XENO_STATUS_BLOCK *xenoStatusPointer;
2016 int correctlyOrientated;
2017 int anglex,angley;
2018
2019 LOCALASSERT(sbPtr);
2020 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
2021 LOCALASSERT(xenoStatusPointer);
2022
2023 /* Do we have a target? */
2024
2025 if (ShowXenoStats) {
2026 PrintDebuggingText("In Turn To Face.\n");
2027 }
2028
2029 if (xenoStatusPointer->Target==NULL) {
2030 Xeno_Enter_ActiveWait_State(sbPtr);
2031 /* Otherwise just wait? */
2032 return;
2033 }
2034
2035 /* Now we have a target. */
2036 GLOBALASSERT(xenoStatusPointer->Target);
2037
2038 /* Set up animation... Which Way? */
2039 {
2040 SECTION_DATA *master_section;
2041 VECTORCH orientationDirn;
2042
2043 master_section=GetThisSectionData(xenoStatusPointer->HModelController.section_data,"pelvis presley");
2044 GLOBALASSERT(master_section);
2045
2046 Xenoborg_GetRelativeAngles(sbPtr,&anglex,&angley,&master_section->World_Offset);
2047
2048 if (anglex>0) {
2049 EnforceXenoborgShapeAnimSequence_Core(sbPtr,HMSQT_Xenoborg,XBSS_Turn_Right,XENO_TURNING_ANIM_SPEED,(ONE_FIXED>>2));
2050 } else {
2051 EnforceXenoborgShapeAnimSequence_Core(sbPtr,HMSQT_Xenoborg,XBSS_Turn_Left,XENO_TURNING_ANIM_SPEED,(ONE_FIXED>>2));
2052 }
2053
2054 /* Then turn to face it, of course. */
2055
2056 orientationDirn.vx = xenoStatusPointer->targetTrackPos.vx - sbPtr->DynPtr->Position.vx;
2057 orientationDirn.vy = 0;
2058 orientationDirn.vz = xenoStatusPointer->targetTrackPos.vz - sbPtr->DynPtr->Position.vz;
2059 correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,(NPC_TURNRATE>>XENO_FOOT_TURN_RATE),NULL);
2060
2061 }
2062
2063 Xeno_TurnAndTarget(sbPtr,&anglex,&angley);
2064
2065 if (angley>=XENO_HEADTILT_GIMBALL) {
2066 Xeno_Enter_ShootingTheRoof_State(sbPtr);
2067 return;
2068 }
2069
2070 if (correctlyOrientated) {
2071 Xeno_Enter_ActiveWait_State(sbPtr);
2072 }
2073
2074 }
2075
Execute_Xeno_ShootTheRoof(STRATEGYBLOCK * sbPtr)2076 void Execute_Xeno_ShootTheRoof(STRATEGYBLOCK *sbPtr)
2077 {
2078 XENO_STATUS_BLOCK *xenoStatusPointer;
2079 int correctlyOrientated;
2080 int anglex,angley;
2081
2082 LOCALASSERT(sbPtr);
2083 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
2084 LOCALASSERT(xenoStatusPointer);
2085
2086 /* Do we have a target? */
2087
2088 if (ShowXenoStats) {
2089 PrintDebuggingText("In Shoot The Roof.\n");
2090 }
2091
2092 if ((xenoStatusPointer->Target==NULL)||(xenoStatusPointer->IAmFar)) {
2093 Xeno_Enter_ActiveWait_State(sbPtr);
2094 /* Otherwise just wait? */
2095 return;
2096 }
2097
2098 /* Now we have a target. */
2099 GLOBALASSERT(xenoStatusPointer->Target);
2100
2101 /* Set up animation... Which Way? Keep TurnToFace functionality? */
2102 {
2103 SECTION_DATA *master_section;
2104 VECTORCH orientationDirn;
2105
2106 master_section=GetThisSectionData(xenoStatusPointer->HModelController.section_data,"pelvis presley");
2107 GLOBALASSERT(master_section);
2108
2109 Xenoborg_GetRelativeAngles(sbPtr,&anglex,&angley,&master_section->World_Offset);
2110
2111 anglex=512;
2112
2113 if (anglex>0) {
2114 EnforceXenoborgShapeAnimSequence_Core(sbPtr,HMSQT_Xenoborg,XBSS_Turn_Right,XENO_TURNING_ANIM_SPEED,(ONE_FIXED>>2));
2115 } else {
2116 EnforceXenoborgShapeAnimSequence_Core(sbPtr,HMSQT_Xenoborg,XBSS_Turn_Left,XENO_TURNING_ANIM_SPEED,(ONE_FIXED>>2));
2117 }
2118
2119 #if 0
2120 /* Then turn to face it, of course. */
2121
2122 orientationDirn.vx = xenoStatusPointer->targetTrackPos.vx - sbPtr->DynPtr->Position.vx;
2123 orientationDirn.vy = 0;
2124 orientationDirn.vz = xenoStatusPointer->targetTrackPos.vz - sbPtr->DynPtr->Position.vz;
2125 #else
2126 /* Synthesize a new orientationDirn. */
2127 orientationDirn.vx=sbPtr->DynPtr->OrientMat.mat11;
2128 orientationDirn.vy=sbPtr->DynPtr->OrientMat.mat12;
2129 orientationDirn.vz=sbPtr->DynPtr->OrientMat.mat13;
2130 #endif
2131 correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,(NPC_TURNRATE>>XENO_FOOT_TURN_RATE),NULL);
2132
2133 }
2134
2135 Xeno_Limbs_ShootTheRoof(sbPtr);
2136
2137 if (angley<XENO_HEADTILT_GIMBALL) {
2138 Xeno_Enter_TurnToFace_State(sbPtr);
2139 return;
2140 }
2141
2142 }
2143
Execute_Xeno_Follow(STRATEGYBLOCK * sbPtr)2144 void Execute_Xeno_Follow(STRATEGYBLOCK *sbPtr)
2145 {
2146 XENO_STATUS_BLOCK *xenoStatusPointer;
2147 VECTORCH velocityDirection = {0,0,0};
2148 VECTORCH targetPosition;
2149 int targetIsAirduct = 0;
2150 int anglex,angley;
2151
2152 LOCALASSERT(sbPtr);
2153 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
2154 LOCALASSERT(xenoStatusPointer);
2155
2156 /* In theory, we're following the target, and can't see it. */
2157
2158 if (ShowXenoStats) {
2159 PrintDebuggingText("In Follow.\n");
2160 }
2161
2162 if (xenoStatusPointer->Target==NULL) {
2163 /* Let's wave the head around. */
2164 Xeno_HeadMovement_ScanLeftRight(sbPtr,XENO_HEAD_SCAN_RATE);
2165 /* Do we want to do this? */
2166 Xeno_HeadMovement_ScanUpDown(sbPtr,XENO_HEAD_SCAN_RATE+2);
2167 xenoStatusPointer->UseHeadLaser=1;
2168 /* And return to my module. */
2169 Xeno_Enter_Returning_State(sbPtr);
2170 return;
2171 }
2172
2173 GLOBALASSERT(xenoStatusPointer->Target);
2174 /* Now we know have a target. Can we see it yet? */
2175
2176 if (xenoStatusPointer->targetSightTest==0) {
2177
2178 AIMODULE *targetModule;
2179 FARENTRYPOINT *thisEp = (FARENTRYPOINT *)0;
2180
2181 /* Can't see them. Never mind. Go to the next module? */
2182 if (xenoStatusPointer->Target->containingModule==NULL) {
2183 /* Fall through for now. */
2184 targetModule=NULL;
2185 } else if (GetNextModuleForLink(sbPtr->containingModule->m_aimodule,
2186 xenoStatusPointer->my_module,(xenoStatusPointer->module_range)-1,0)==NULL) {
2187 /* Too Far! */
2188 Xeno_Enter_ActiveWait_State(sbPtr);
2189 return;
2190 } else {
2191 /* Still in range: keep going. */
2192 targetModule=GetNextModuleForLink(sbPtr->containingModule->m_aimodule,
2193 xenoStatusPointer->Target->containingModule->m_aimodule,xenoStatusPointer->module_range,0);
2194
2195 }
2196
2197 if (targetModule==NULL) {
2198 /* They're way away. */
2199 Xeno_Enter_Returning_State(sbPtr);
2200 return;
2201 }
2202
2203 if (targetModule==sbPtr->containingModule->m_aimodule) {
2204 /* Good Grief, Penfold! He's right there, but I can't see him! */
2205 NPCGetMovementDirection(sbPtr, &velocityDirection, &xenoStatusPointer->targetTrackPos,&xenoStatusPointer->waypointManager);
2206 NPCSetVelocity(sbPtr, &velocityDirection, XENO_NEAR_SPEED);
2207 targetPosition=xenoStatusPointer->targetTrackPos;
2208 if (ShowXenoStats) {
2209 PrintDebuggingText("Direct movement - no LOS.\n");
2210 }
2211 /* Oh, well. Go to last known position? */
2212 } else {
2213 thisEp=GetAIModuleEP(targetModule,sbPtr->containingModule->m_aimodule);
2214 if (!thisEp) {
2215 LOGDXFMT(("This assert is a busted adjacency!\nNo EP between %s and %s.",
2216 (*(targetModule->m_module_ptrs))->name,
2217 sbPtr->containingModule->name));
2218 GLOBALASSERT(thisEp);
2219 }
2220 /* If that fired, there's a farped adjacency. */
2221
2222 xenoStatusPointer->wanderData.worldPosition=thisEp->position;
2223 xenoStatusPointer->wanderData.worldPosition.vx+=targetModule->m_world.vx;
2224 xenoStatusPointer->wanderData.worldPosition.vy+=targetModule->m_world.vy;
2225 xenoStatusPointer->wanderData.worldPosition.vz+=targetModule->m_world.vz;
2226
2227 NPCGetMovementDirection(sbPtr, &velocityDirection, &(xenoStatusPointer->wanderData.worldPosition),&xenoStatusPointer->waypointManager);
2228 NPCSetVelocity(sbPtr, &velocityDirection, XENO_NEAR_SPEED);
2229 targetPosition=xenoStatusPointer->wanderData.worldPosition;
2230 }
2231 } else {
2232 /* Re-aquired! Get a bit closer? */
2233 int range;
2234
2235 if (GetNextModuleForLink(sbPtr->containingModule->m_aimodule,
2236 xenoStatusPointer->my_module,(xenoStatusPointer->module_range)-1,0)==NULL) {
2237 /* Too Far! */
2238 Xeno_Enter_ActiveWait_State(sbPtr);
2239 return;
2240 }
2241
2242 range=VectorDistance((&xenoStatusPointer->Target->DynPtr->Position),(&sbPtr->DynPtr->Position));
2243
2244 if (range>XENO_CLOSE_APPROACH_DISTANCE) {
2245 NPCGetMovementTarget(sbPtr, xenoStatusPointer->Target, &targetPosition, &targetIsAirduct,0);
2246 NPCGetMovementDirection(sbPtr, &velocityDirection, &targetPosition,&xenoStatusPointer->waypointManager);
2247 NPCSetVelocity(sbPtr, &velocityDirection, XENO_NEAR_SPEED);
2248 if (ShowXenoStats) {
2249 PrintDebuggingText("Direct movement - LOS Okay.\n");
2250 }
2251 } else {
2252 /* Return to ActiveWait. */
2253 Xeno_Enter_ActiveWait_State(sbPtr);
2254 return;
2255 }
2256
2257 }
2258
2259 #if 0
2260 EnforceXenoborgShapeAnimSequence_Core(sbPtr,HMSQT_Xenoborg,XBSS_Walking,XENO_WALKING_ANIM_SPEED,(ONE_FIXED>>2));
2261 #else
2262 XenoborgHandleMovingAnimation(sbPtr);
2263 #endif
2264
2265 if (xenoStatusPointer->targetSightTest==0) {
2266 Xeno_TorsoMovement_Centre(sbPtr,XENO_TORSO_TWIST_RATE);
2267 Xeno_LeftArmMovement_Centre(sbPtr,XENO_ARM_LOCK_RATE);
2268 Xeno_RightArmMovement_Centre(sbPtr,XENO_ARM_LOCK_RATE);
2269 Xeno_HeadMovement_ScanLeftRight(sbPtr,XENO_HEAD_SCAN_RATE);
2270 xenoStatusPointer->UseHeadLaser=1;
2271 } else {
2272 Xeno_TurnAndTarget(sbPtr,&anglex,&angley);
2273 }
2274
2275 /* test here for impeding collisions, and not being able to reach target... */
2276 {
2277 STRATEGYBLOCK *destructableObject = NULL;
2278
2279 NPC_IsObstructed(sbPtr,&(xenoStatusPointer->moveData),&xenoStatusPointer->obstruction,&destructableObject);
2280 #if 1
2281 if(xenoStatusPointer->obstruction.environment)
2282 {
2283 /* go to avoidance */
2284 Xeno_Enter_Avoidance_State(sbPtr);
2285 return;
2286 }
2287 #endif
2288 if(xenoStatusPointer->obstruction.destructableObject)
2289 {
2290 LOCALASSERT(destructableObject);
2291 CauseDamageToObject(destructableObject,&TemplateAmmo[AMMO_NPC_OBSTACLE_CLEAR].MaxDamage[AvP.Difficulty], ONE_FIXED,NULL);
2292 }
2293 }
2294
2295 if(NPC_CannotReachTarget(&(xenoStatusPointer->moveData), &targetPosition, &velocityDirection))
2296 {
2297
2298 xenoStatusPointer->obstruction.environment=1;
2299 xenoStatusPointer->obstruction.destructableObject=0;
2300 xenoStatusPointer->obstruction.otherCharacter=0;
2301 xenoStatusPointer->obstruction.anySingleObstruction=0;
2302
2303 Xeno_Enter_Avoidance_State(sbPtr);
2304 return;
2305 }
2306
2307 }
2308
Execute_Xeno_Return(STRATEGYBLOCK * sbPtr)2309 void Execute_Xeno_Return(STRATEGYBLOCK *sbPtr)
2310 {
2311 XENO_STATUS_BLOCK *xenoStatusPointer;
2312 VECTORCH velocityDirection = {0,0,0};
2313 VECTORCH *targetPosition=NULL;
2314
2315 LOCALASSERT(sbPtr);
2316 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
2317 LOCALASSERT(xenoStatusPointer);
2318
2319 /* In theory, we're following the target, and can't see it. */
2320
2321 if (ShowXenoStats) {
2322 PrintDebuggingText("In Return.\n");
2323 }
2324
2325 if (xenoStatusPointer->Target!=NULL) {
2326 /* Saw something! */
2327 /* Go to active wait. */
2328 Xeno_Enter_ActiveWait_State(sbPtr);
2329 return;
2330 }
2331
2332 GLOBALASSERT(xenoStatusPointer->Target==NULL);
2333 /* Find our way home. */
2334
2335 {
2336
2337 AIMODULE *targetModule;
2338 FARENTRYPOINT *thisEp = (FARENTRYPOINT *)0;
2339
2340 /* Go to the next module. */
2341 targetModule=GetNextModuleForLink(sbPtr->containingModule->m_aimodule,
2342 xenoStatusPointer->my_module,xenoStatusPointer->module_range+2,0);
2343 /* Just to be on the safe side. */
2344
2345 if (targetModule==NULL) {
2346 /* Emergency! */
2347 targetModule=GetNextModuleForLink(sbPtr->containingModule->m_aimodule,
2348 xenoStatusPointer->my_module,xenoStatusPointer->module_range+5,0);
2349 if (targetModule==NULL) {
2350 /* Totally broken. Stay here. */
2351 Xeno_CopeWithLossOfHome(sbPtr);
2352 return;
2353 }
2354 }
2355
2356 if (targetModule!=sbPtr->containingModule->m_aimodule) {
2357
2358 thisEp=GetAIModuleEP(targetModule,sbPtr->containingModule->m_aimodule);
2359 if (!thisEp) {
2360 LOGDXFMT(("This assert is a busted adjacency!\nNo EP between %s and %s.",
2361 (*(targetModule->m_module_ptrs))->name,
2362 sbPtr->containingModule->name));
2363 GLOBALASSERT(thisEp);
2364 }
2365 /* If that fired, there's a farped adjacency. */
2366
2367 xenoStatusPointer->wanderData.worldPosition=thisEp->position;
2368 xenoStatusPointer->wanderData.worldPosition.vx+=targetModule->m_world.vx;
2369 xenoStatusPointer->wanderData.worldPosition.vy+=targetModule->m_world.vy;
2370 xenoStatusPointer->wanderData.worldPosition.vz+=targetModule->m_world.vz;
2371
2372 NPCGetMovementDirection(sbPtr, &velocityDirection, &(xenoStatusPointer->wanderData.worldPosition),&xenoStatusPointer->waypointManager);
2373 NPCSetVelocity(sbPtr, &velocityDirection, XENO_NEAR_SPEED);
2374 targetPosition=&(xenoStatusPointer->wanderData.worldPosition);
2375 } else {
2376 VECTORCH offset;
2377 int dist;
2378 /* In our own home module! */
2379
2380 offset.vx=sbPtr->DynPtr->Position.vx-xenoStatusPointer->my_spot_therin.vx;
2381 offset.vy=sbPtr->DynPtr->Position.vy-xenoStatusPointer->my_spot_therin.vy;
2382 offset.vz=sbPtr->DynPtr->Position.vz-xenoStatusPointer->my_spot_therin.vz;
2383 /* Fix for midair start points, grrrr. */
2384 offset.vy>>=2;
2385
2386 /* Find distance off spot. */
2387 dist=Approximate3dMagnitude(&offset);
2388
2389 if (dist<XENO_SENTRY_SENSITIVITY) {
2390 Xeno_Enter_ActiveWait_State(sbPtr);
2391 return;
2392 } else {
2393 NPCGetMovementDirection(sbPtr, &velocityDirection, &(xenoStatusPointer->my_spot_therin),&xenoStatusPointer->waypointManager);
2394 NPCSetVelocity(sbPtr, &velocityDirection, XENO_NEAR_SPEED);
2395 targetPosition=&(xenoStatusPointer->my_spot_therin);
2396 }
2397 }
2398 }
2399
2400 #if 0
2401 EnforceXenoborgShapeAnimSequence_Core(sbPtr,HMSQT_Xenoborg,XBSS_Walking,XENO_WALKING_ANIM_SPEED,(ONE_FIXED>>2));
2402 #else
2403 XenoborgHandleMovingAnimation(sbPtr);
2404 #endif
2405
2406 Xeno_TorsoMovement_Centre(sbPtr,XENO_TORSO_TWIST_RATE);
2407 Xeno_LeftArmMovement_Centre(sbPtr,XENO_ARM_LOCK_RATE);
2408 Xeno_RightArmMovement_Centre(sbPtr,XENO_ARM_LOCK_RATE);
2409 Xeno_HeadMovement_ScanLeftRight(sbPtr,XENO_HEAD_SCAN_RATE);
2410 xenoStatusPointer->UseHeadLaser=1;
2411
2412 /* test here for impeding collisions, and not being able to reach target... */
2413 {
2414 STRATEGYBLOCK *destructableObject = NULL;
2415
2416 NPC_IsObstructed(sbPtr,&(xenoStatusPointer->moveData),&xenoStatusPointer->obstruction,&destructableObject);
2417 #if 1
2418 if(xenoStatusPointer->obstruction.environment)
2419 {
2420 /* go to avoidance */
2421 Xeno_Enter_Avoidance_State(sbPtr);
2422 return;
2423 }
2424 #endif
2425 if(xenoStatusPointer->obstruction.destructableObject)
2426 {
2427 LOCALASSERT(destructableObject);
2428 CauseDamageToObject(destructableObject,&TemplateAmmo[AMMO_NPC_OBSTACLE_CLEAR].MaxDamage[AvP.Difficulty], ONE_FIXED,NULL);
2429 }
2430 }
2431
2432 if(NPC_CannotReachTarget(&(xenoStatusPointer->moveData), targetPosition, &velocityDirection))
2433 {
2434
2435 xenoStatusPointer->obstruction.environment=1;
2436 xenoStatusPointer->obstruction.destructableObject=0;
2437 xenoStatusPointer->obstruction.otherCharacter=0;
2438 xenoStatusPointer->obstruction.anySingleObstruction=0;
2439
2440 Xeno_Enter_Avoidance_State(sbPtr);
2441 return;
2442 }
2443
2444 }
2445
Execute_Xeno_Avoidance(STRATEGYBLOCK * sbPtr)2446 void Execute_Xeno_Avoidance(STRATEGYBLOCK *sbPtr)
2447 {
2448 XENO_STATUS_BLOCK *xenoStatusPointer;
2449 int terminateState = 0;
2450 int anglex,angley;
2451
2452 LOCALASSERT(sbPtr);
2453 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
2454 LOCALASSERT(xenoStatusPointer);
2455
2456 if (ShowXenoStats) {
2457 PrintDebuggingText("In Avoidance.\n");
2458 }
2459
2460 /* Sequences... */
2461 #if 0
2462 EnforceXenoborgShapeAnimSequence_Core(sbPtr,HMSQT_Xenoborg,XBSS_Walking,XENO_WALKING_ANIM_SPEED,(ONE_FIXED>>2));
2463 #else
2464 XenoborgHandleMovingAnimation(sbPtr);
2465 #endif
2466
2467 if (xenoStatusPointer->targetSightTest==0) {
2468 Xeno_TorsoMovement_Centre(sbPtr,XENO_TORSO_TWIST_RATE);
2469 Xeno_LeftArmMovement_Centre(sbPtr,XENO_ARM_LOCK_RATE);
2470 Xeno_RightArmMovement_Centre(sbPtr,XENO_ARM_LOCK_RATE);
2471 Xeno_HeadMovement_ScanLeftRight(sbPtr,XENO_HEAD_SCAN_RATE);
2472 xenoStatusPointer->UseHeadLaser=1;
2473 } else {
2474 Xeno_TurnAndTarget(sbPtr,&anglex,&angley);
2475 }
2476
2477 /* set velocity */
2478 LOCALASSERT((xenoStatusPointer->moveData.avoidanceDirn.vx!=0)||
2479 (xenoStatusPointer->moveData.avoidanceDirn.vy!=0)||
2480 (xenoStatusPointer->moveData.avoidanceDirn.vz!=0));
2481 NPCSetVelocity(sbPtr, &(xenoStatusPointer->moveData.avoidanceDirn), (XENO_NEAR_SPEED));
2482
2483 /* decrement state timer */
2484 xenoStatusPointer->stateTimer -= NormalFrameTime;
2485 if(xenoStatusPointer->stateTimer <= 0) terminateState = 1;
2486
2487 {
2488 STRATEGYBLOCK *destructableObject = NULL;
2489 NPC_OBSTRUCTIONREPORT obstruction;
2490 NPC_IsObstructed(sbPtr,&(xenoStatusPointer->moveData),&obstruction,&destructableObject);
2491 if(obstruction.anySingleObstruction)
2492 {
2493 terminateState = 1;
2494 }
2495 }
2496
2497 if(terminateState)
2498 {
2499
2500 /* go to an appropriate state */
2501 switch (xenoStatusPointer->lastState) {
2502 case XS_Returning:
2503 Xeno_Enter_Returning_State(sbPtr);
2504 return;
2505 break;
2506 case XS_Following:
2507 Xeno_Enter_Following_State(sbPtr);
2508 return;
2509 break;
2510 default:
2511 Xeno_Enter_ActiveWait_State(sbPtr);
2512 return;
2513 break;
2514 }
2515 /* Still here? */
2516 return;
2517
2518 }
2519 return;
2520 }
2521
Xenoborg_TargetFilter(STRATEGYBLOCK * candidate)2522 int Xenoborg_TargetFilter(STRATEGYBLOCK *candidate) {
2523
2524 /* Let's face it, Xenos shoot everything but other xenos. */
2525 switch (candidate->I_SBtype) {
2526 case I_BehaviourMarinePlayer:
2527 case I_BehaviourAlienPlayer:
2528 case I_BehaviourPredatorPlayer:
2529 {
2530 if (Observer) {
2531 return(0);
2532 }
2533
2534 switch(AvP.PlayerType)
2535 {
2536 case I_Alien:
2537 case I_Predator:
2538 case I_Marine:
2539 return(1);
2540 break;
2541 default:
2542 GLOBALASSERT(0);
2543 return(0);
2544 break;
2545 }
2546 break;
2547 }
2548 case I_BehaviourDummy:
2549 {
2550 DUMMY_STATUS_BLOCK *dummyStatusPointer;
2551 dummyStatusPointer = (DUMMY_STATUS_BLOCK *)(candidate->SBdataptr);
2552 LOCALASSERT(dummyStatusPointer);
2553 switch (dummyStatusPointer->PlayerType) {
2554 case I_Marine:
2555 case I_Predator:
2556 case I_Alien:
2557 return(1);
2558 break;
2559 default:
2560 GLOBALASSERT(0);
2561 return(0);
2562 break;
2563 }
2564 break;
2565 }
2566 case I_BehaviourAlien:
2567 {
2568 if (NPC_IsDead(candidate)) {
2569 return(0);
2570 } else {
2571 /* Are we inactive? */
2572 ALIEN_STATUS_BLOCK *asb=(ALIEN_STATUS_BLOCK *)candidate->SBdataptr;
2573 GLOBALASSERT(asb);
2574 if (asb->BehaviourState==ABS_Dormant) {
2575 return(0);
2576 } else {
2577 return(1);
2578 }
2579 }
2580 break;
2581 }
2582 case I_BehaviourQueenAlien:
2583 case I_BehaviourFaceHugger:
2584 case I_BehaviourPredator:
2585 case I_BehaviourSeal:
2586 case I_BehaviourPredatorAlien:
2587 case I_BehaviourMarine:
2588 {
2589 if (NPC_IsDead(candidate)) {
2590 return(0);
2591 } else {
2592 return(1);
2593 }
2594 break;
2595 }
2596 case I_BehaviourXenoborg:
2597 return(0);
2598 break;
2599 case I_BehaviourNetGhost:
2600 {
2601 NETGHOSTDATABLOCK *dataptr;
2602 dataptr=candidate->SBdataptr;
2603 switch (dataptr->type) {
2604 case I_BehaviourMarinePlayer:
2605 case I_BehaviourAlienPlayer:
2606 case I_BehaviourPredatorPlayer:
2607 return(1);
2608 break;
2609 default:
2610 return(1);
2611 break;
2612 }
2613 }
2614 break;
2615 default:
2616 return(0);
2617 break;
2618 }
2619
2620 }
2621
Xenoborg_GetNewTarget(VECTORCH * xenopos,STRATEGYBLOCK * me)2622 STRATEGYBLOCK *Xenoborg_GetNewTarget(VECTORCH *xenopos, STRATEGYBLOCK *me) {
2623
2624 int neardist;
2625 STRATEGYBLOCK *nearest;
2626 int a;
2627 STRATEGYBLOCK *candidate;
2628 MODULE *dmod;
2629
2630 dmod=ModuleFromPosition(xenopos,playerPherModule);
2631
2632 LOCALASSERT(dmod);
2633
2634 nearest=NULL;
2635 neardist=ONE_FIXED;
2636
2637 for (a=0; a<NumActiveStBlocks; a++) {
2638 candidate=ActiveStBlockList[a];
2639 if (candidate!=me) {
2640 if (candidate->DynPtr) {
2641 if (Xenoborg_TargetFilter(candidate)) {
2642 VECTORCH offset;
2643 int dist;
2644
2645 offset.vx=xenopos->vx-candidate->DynPtr->Position.vx;
2646 offset.vy=xenopos->vy-candidate->DynPtr->Position.vy;
2647 offset.vz=xenopos->vz-candidate->DynPtr->Position.vz;
2648
2649 dist=Approximate3dMagnitude(&offset);
2650
2651 if (dist<neardist) {
2652 /* Check visibility? */
2653 if (NPCCanSeeTarget(me,candidate,XENO_NEAR_VIEW_WIDTH)) {
2654 if (!NPC_IsDead(candidate)) {
2655 if ((IsModuleVisibleFromModule(dmod,candidate->containingModule))) {
2656 nearest=candidate;
2657 }
2658 }
2659 }
2660 }
2661 }
2662 }
2663 }
2664 }
2665
2666 #if 0
2667 if (nearest==NULL) {
2668 if (Xenoborg_TargetFilter(Player->ObStrategyBlock)) {
2669 nearest=Player->ObStrategyBlock;
2670 } else {
2671 nearest=NULL; /* Erk! */
2672 }
2673 }
2674 #endif
2675
2676 return(nearest);
2677
2678 }
2679
ComputeDeltaValues(STRATEGYBLOCK * sbPtr)2680 static void ComputeDeltaValues(STRATEGYBLOCK *sbPtr)
2681 {
2682 XENO_STATUS_BLOCK *xenoStatusPointer;
2683 int angle;
2684
2685 LOCALASSERT(sbPtr);
2686 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
2687 LOCALASSERT(xenoStatusPointer);
2688
2689 /* Interpret all status block values, and apply to deltas. */
2690 /* Head Pan first. */
2691
2692 angle=xenoStatusPointer->Head_Pan>>4;
2693
2694 if (angle>=3072) angle-=4096;
2695 if (angle>=2048) angle=angle-4096;
2696
2697 /* Now, we have an angle. */
2698
2699 if (angle>XENO_HEADPAN_GIMBALL) {
2700 angle=XENO_HEADPAN_GIMBALL;
2701 } else if (angle<-XENO_HEADPAN_GIMBALL) {
2702 angle=-XENO_HEADPAN_GIMBALL;
2703 }
2704
2705 #if 0
2706 angle=angle*2;
2707
2708 GLOBALASSERT(xenoStatusPointer->head_pan);
2709
2710 {
2711 int fake_timer;
2712
2713 fake_timer=1024-angle;
2714 fake_timer<<=5;
2715 if (fake_timer==65536) fake_timer=65535;
2716 #else
2717 GLOBALASSERT(xenoStatusPointer->head_pan);
2718
2719 {
2720 int fake_timer;
2721
2722 fake_timer=DIV_FIXED(angle,(XENO_HEADPAN_GIMBALL<<1));
2723 fake_timer+=32767;
2724 fake_timer=65536-fake_timer;
2725 if (fake_timer>=65536) fake_timer=65535;
2726 if (fake_timer<=0) fake_timer=0;
2727
2728 #endif
2729
2730 GLOBALASSERT(fake_timer>=0);
2731 GLOBALASSERT(fake_timer<65536);
2732
2733 xenoStatusPointer->head_pan->timer=fake_timer;
2734
2735 }
2736
2737 /* Head tilt next. */
2738 angle=xenoStatusPointer->Head_Tilt>>4;
2739
2740 if (angle>=3072) angle-=4096;
2741 if (angle>=2048) angle=angle-3072;
2742 if (angle> 1024) angle=2048-angle;
2743
2744 /* Now, we have an angle. */
2745
2746 if (angle>XENO_HEADTILT_GIMBALL) {
2747 angle=XENO_HEADTILT_GIMBALL;
2748 } else if (angle<-XENO_HEADTILT_GIMBALL) {
2749 angle=-XENO_HEADTILT_GIMBALL;
2750 }
2751
2752 angle=angle*2;
2753
2754 GLOBALASSERT(angle>=-1024);
2755 GLOBALASSERT(angle<=1024);
2756
2757 GLOBALASSERT(xenoStatusPointer->head_tilt);
2758
2759 {
2760 int fake_timer;
2761
2762 fake_timer=1024-angle;
2763 fake_timer<<=5;
2764 if (fake_timer==65536) fake_timer=65535;
2765
2766 GLOBALASSERT(fake_timer>=0);
2767 GLOBALASSERT(fake_timer<65536);
2768
2769 xenoStatusPointer->head_tilt->timer=fake_timer;
2770
2771 }
2772
2773 /* Left Arm Pan now. */
2774
2775 angle=xenoStatusPointer->Left_Arm_Pan>>4;
2776
2777 if (angle>=3072) angle-=4096;
2778 if (angle>=2048) angle=angle-4096;
2779
2780 GLOBALASSERT(xenoStatusPointer->left_arm_pan);
2781
2782 /* Now, we have an angle. */
2783
2784 if (angle>XENO_LEFTARM_ACW_GIMBALL) {
2785 angle=XENO_LEFTARM_ACW_GIMBALL;
2786 } else if (angle<-XENO_LEFTARM_CW_GIMBALL) {
2787 angle=-XENO_LEFTARM_CW_GIMBALL;
2788 }
2789
2790 {
2791 int fake_timer;
2792
2793 if (angle>0) {
2794
2795 fake_timer=DIV_FIXED(angle,(XENO_LEFTARM_ACW_GIMBALL<<1));
2796 fake_timer+=32767;
2797 fake_timer=65536-fake_timer;
2798 if (fake_timer>=65536) fake_timer=65535;
2799 if (fake_timer<=0) fake_timer=0;
2800
2801 } else {
2802
2803 fake_timer=DIV_FIXED(angle,(XENO_LEFTARM_CW_GIMBALL<<1));
2804 fake_timer+=32767;
2805 fake_timer=65536-fake_timer;
2806 if (fake_timer>=65536) fake_timer=65535;
2807 if (fake_timer<=0) fake_timer=0;
2808
2809 }
2810
2811 GLOBALASSERT(fake_timer>=0);
2812 GLOBALASSERT(fake_timer<65536);
2813
2814 xenoStatusPointer->left_arm_pan->timer=fake_timer;
2815
2816 }
2817
2818 /* Left Arm Tilt... */
2819
2820 angle=xenoStatusPointer->Left_Arm_Tilt>>4;
2821
2822 if (angle>=3072) angle-=4096;
2823 if (angle>=2048) angle=angle-3072;
2824 if (angle> 1024) angle=2048-angle;
2825
2826 GLOBALASSERT(xenoStatusPointer->left_arm_tilt);
2827
2828 /* Now, we have an angle. */
2829
2830 if (angle>XENO_ARM_PITCH_GIMBALL) {
2831 angle=XENO_ARM_PITCH_GIMBALL;
2832 } else if (angle<-XENO_ARM_PITCH_GIMBALL) {
2833 angle=-XENO_ARM_PITCH_GIMBALL;
2834 }
2835
2836 GLOBALASSERT(angle>=-1024);
2837 GLOBALASSERT(angle<=1024);
2838
2839 {
2840 int fake_timer;
2841
2842 fake_timer=1024-angle;
2843 fake_timer<<=5;
2844 if (fake_timer==65536) fake_timer=65535;
2845
2846 GLOBALASSERT(fake_timer>=0);
2847 GLOBALASSERT(fake_timer<65536);
2848
2849 xenoStatusPointer->left_arm_tilt->timer=fake_timer;
2850
2851 }
2852
2853 /* Right Arm Pan now. */
2854
2855 angle=xenoStatusPointer->Right_Arm_Pan>>4;
2856
2857 if (angle>=3072) angle-=4096;
2858 if (angle>=2048) angle=angle-4096;
2859
2860 GLOBALASSERT(xenoStatusPointer->right_arm_pan);
2861
2862 /* Now, we have an angle. */
2863
2864 if (angle>XENO_RIGHTARM_ACW_GIMBALL) {
2865 angle=XENO_RIGHTARM_ACW_GIMBALL;
2866 } else if (angle<-XENO_RIGHTARM_CW_GIMBALL) {
2867 angle=-XENO_RIGHTARM_CW_GIMBALL;
2868 }
2869
2870 {
2871 int fake_timer;
2872
2873 if (angle>0) {
2874
2875 fake_timer=DIV_FIXED(angle,(XENO_RIGHTARM_ACW_GIMBALL<<1));
2876 fake_timer+=32767;
2877 if (fake_timer>=65536) fake_timer=65535;
2878
2879 } else {
2880
2881 fake_timer=DIV_FIXED(angle,(XENO_RIGHTARM_CW_GIMBALL<<1));
2882 fake_timer+=32767;
2883 if (fake_timer<=0) fake_timer=0;
2884
2885 }
2886
2887 GLOBALASSERT(fake_timer>=0);
2888 GLOBALASSERT(fake_timer<65536);
2889
2890 xenoStatusPointer->right_arm_pan->timer=fake_timer;
2891
2892 }
2893
2894 /* Right Arm Tilt... */
2895
2896 angle=xenoStatusPointer->Right_Arm_Tilt>>4;
2897
2898 if (angle>=3072) angle-=4096;
2899 if (angle>=2048) angle=angle-3072;
2900 if (angle> 1024) angle=2048-angle;
2901
2902 GLOBALASSERT(xenoStatusPointer->right_arm_pan);
2903
2904 /* Now, we have an angle. */
2905
2906 if (angle>XENO_ARM_PITCH_GIMBALL) {
2907 angle=XENO_ARM_PITCH_GIMBALL;
2908 } else if (angle<-XENO_ARM_PITCH_GIMBALL) {
2909 angle=-XENO_ARM_PITCH_GIMBALL;
2910 }
2911
2912 GLOBALASSERT(angle>=-1024);
2913 GLOBALASSERT(angle<=1024);
2914
2915 {
2916 int fake_timer;
2917
2918 fake_timer=1024-angle;
2919 fake_timer<<=5;
2920 if (fake_timer==65536) fake_timer=65535;
2921
2922 GLOBALASSERT(fake_timer>=0);
2923 GLOBALASSERT(fake_timer<65536);
2924
2925 xenoStatusPointer->right_arm_tilt->timer=fake_timer;
2926
2927 }
2928
2929 /* ... and Torso Twist. */
2930
2931 angle=xenoStatusPointer->Torso_Twist>>4;
2932
2933 if (angle>=3072) angle-=4096;
2934 if (angle>=2048) angle=angle-4096;
2935
2936 GLOBALASSERT(xenoStatusPointer->torso_twist);
2937
2938 /* Now, we have an angle. */
2939
2940 if (angle>XENO_TORSO_GIMBALL) {
2941 angle=XENO_TORSO_GIMBALL;
2942 } else if (angle<-XENO_TORSO_GIMBALL) {
2943 angle=-XENO_TORSO_GIMBALL;
2944 }
2945
2946 {
2947 int fake_timer;
2948
2949 if (angle>0) {
2950
2951 fake_timer=DIV_FIXED(angle,(XENO_TORSO_GIMBALL<<1));
2952 fake_timer+=32767;
2953 if (fake_timer>=65536) fake_timer=65535;
2954
2955 } else {
2956
2957 fake_timer=DIV_FIXED(angle,(XENO_TORSO_GIMBALL<<1));
2958 fake_timer+=32767;
2959 if (fake_timer<=0) fake_timer=0;
2960
2961 }
2962
2963 GLOBALASSERT(fake_timer>=0);
2964 GLOBALASSERT(fake_timer<65536);
2965
2966 xenoStatusPointer->torso_twist->timer=fake_timer;
2967
2968 }
2969
2970 }
2971
2972 void Xeno_HeadMovement_ScanLeftRight(STRATEGYBLOCK *sbPtr,int rate)
2973 {
2974 XENO_STATUS_BLOCK *xenoStatusPointer;
2975
2976 LOCALASSERT(sbPtr);
2977 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
2978 LOCALASSERT(xenoStatusPointer);
2979
2980 /* Let's wave the head around. */
2981 if (xenoStatusPointer->headpandir) {
2982 xenoStatusPointer->Head_Pan+=(NormalFrameTime>>rate);
2983 if (xenoStatusPointer->Head_Pan>(XENO_HEADPAN_GIMBALL<<4)) {
2984 xenoStatusPointer->Head_Pan=(XENO_HEADPAN_GIMBALL<<4);
2985 xenoStatusPointer->headpandir=0;
2986 } else {
2987 xenoStatusPointer->head_moving=1;
2988 }
2989 } else {
2990 xenoStatusPointer->Head_Pan-=(NormalFrameTime>>rate);
2991 if (xenoStatusPointer->Head_Pan<-(XENO_HEADPAN_GIMBALL<<4)) {
2992 xenoStatusPointer->Head_Pan=-(XENO_HEADPAN_GIMBALL<<4);
2993 xenoStatusPointer->headpandir=1;
2994 } else {
2995 xenoStatusPointer->head_moving=1;
2996 }
2997 }
2998 if (xenoStatusPointer->head_pan) {
2999 xenoStatusPointer->head_pan->Active=1;
3000 }
3001
3002 }
3003
3004 void Xeno_HeadMovement_ScanUpDown(STRATEGYBLOCK *sbPtr,int rate)
3005 {
3006 XENO_STATUS_BLOCK *xenoStatusPointer;
3007
3008 LOCALASSERT(sbPtr);
3009 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
3010 LOCALASSERT(xenoStatusPointer);
3011
3012 /* Let's wave the head around. */
3013 if (xenoStatusPointer->headtiltdir) {
3014 xenoStatusPointer->Head_Tilt+=(NormalFrameTime>>rate);
3015 if (xenoStatusPointer->Head_Tilt>(XENO_HEADTILT_GIMBALL<<4)) {
3016 xenoStatusPointer->Head_Tilt=(XENO_HEADTILT_GIMBALL<<4);
3017 xenoStatusPointer->headtiltdir=0;
3018 } else {
3019 xenoStatusPointer->head_moving=1;
3020 }
3021 } else {
3022 xenoStatusPointer->Head_Tilt-=(NormalFrameTime>>rate);
3023 if (xenoStatusPointer->Head_Tilt<-(XENO_HEADTILT_GIMBALL<<4)) {
3024 xenoStatusPointer->Head_Tilt=-(XENO_HEADTILT_GIMBALL<<4);
3025 xenoStatusPointer->headtiltdir=1;
3026 } else {
3027 xenoStatusPointer->head_moving=1;
3028 }
3029 }
3030 if (xenoStatusPointer->head_tilt) {
3031 xenoStatusPointer->head_tilt->Active=1;
3032 }
3033
3034 }
3035
3036 void Xeno_LeftArmMovement_TrackLeftRight(STRATEGYBLOCK *sbPtr,int rate)
3037 {
3038 XENO_STATUS_BLOCK *xenoStatusPointer;
3039
3040 LOCALASSERT(sbPtr);
3041 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
3042 LOCALASSERT(xenoStatusPointer);
3043
3044 /* Let's wave the left arm around. */
3045 if (xenoStatusPointer->leftarmpandir) {
3046 xenoStatusPointer->Left_Arm_Pan+=(NormalFrameTime>>rate);
3047 if (xenoStatusPointer->Left_Arm_Pan>(XENO_LEFTARM_ACW_GIMBALL<<4)) {
3048 xenoStatusPointer->Left_Arm_Pan=(XENO_LEFTARM_ACW_GIMBALL<<4);
3049 xenoStatusPointer->leftarmpandir=0;
3050 } else {
3051 xenoStatusPointer->la_moving=1;
3052 }
3053 } else {
3054 xenoStatusPointer->Left_Arm_Pan-=(NormalFrameTime>>rate);
3055 if (xenoStatusPointer->Left_Arm_Pan<-(XENO_LEFTARM_CW_GIMBALL<<4)) {
3056 xenoStatusPointer->Left_Arm_Pan=-(XENO_LEFTARM_CW_GIMBALL<<4);
3057 xenoStatusPointer->leftarmpandir=1;
3058 } else {
3059 xenoStatusPointer->la_moving=1;
3060 }
3061 }
3062
3063 if (xenoStatusPointer->left_arm_pan) {
3064 xenoStatusPointer->left_arm_pan->Active=1;
3065 }
3066
3067 }
3068
3069 void Xeno_LeftArmMovement_TrackUpDown(STRATEGYBLOCK *sbPtr,int rate)
3070 {
3071 XENO_STATUS_BLOCK *xenoStatusPointer;
3072
3073 LOCALASSERT(sbPtr);
3074 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
3075 LOCALASSERT(xenoStatusPointer);
3076
3077 /* Let's wave the left arm around. */
3078 if (xenoStatusPointer->leftarmtiltdir) {
3079 xenoStatusPointer->Left_Arm_Tilt+=(NormalFrameTime>>rate);
3080 if (xenoStatusPointer->Left_Arm_Tilt>(XENO_ARM_PITCH_GIMBALL<<4)) {
3081 xenoStatusPointer->Left_Arm_Tilt=(XENO_ARM_PITCH_GIMBALL<<4);
3082 xenoStatusPointer->leftarmtiltdir=0;
3083 } else {
3084 xenoStatusPointer->la_moving=1;
3085 }
3086 } else {
3087 xenoStatusPointer->Left_Arm_Tilt-=(NormalFrameTime>>rate);
3088 if (xenoStatusPointer->Left_Arm_Tilt<-(XENO_ARM_PITCH_GIMBALL<<4)) {
3089 xenoStatusPointer->Left_Arm_Tilt=-(XENO_ARM_PITCH_GIMBALL<<4);
3090 xenoStatusPointer->leftarmtiltdir=1;
3091 } else {
3092 xenoStatusPointer->la_moving=1;
3093 }
3094 }
3095
3096 if (xenoStatusPointer->left_arm_tilt) {
3097 xenoStatusPointer->left_arm_tilt->Active=1;
3098 }
3099
3100 }
3101
3102 void Xeno_LeftArmMovement_WaveUp(STRATEGYBLOCK *sbPtr,int rate)
3103 {
3104 XENO_STATUS_BLOCK *xenoStatusPointer;
3105
3106 LOCALASSERT(sbPtr);
3107 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
3108 LOCALASSERT(xenoStatusPointer);
3109
3110 /* Let's wave the left arm around. */
3111 if (xenoStatusPointer->leftarmtiltdir) {
3112 xenoStatusPointer->Left_Arm_Tilt+=(NormalFrameTime>>rate);
3113 if (xenoStatusPointer->Left_Arm_Tilt>-(XENO_HEADTILT_GIMBALL<<4)) {
3114 xenoStatusPointer->Left_Arm_Tilt=-(XENO_HEADTILT_GIMBALL<<4);
3115 xenoStatusPointer->leftarmtiltdir=0;
3116 } else {
3117 xenoStatusPointer->la_moving=1;
3118 }
3119 } else {
3120 xenoStatusPointer->Left_Arm_Tilt-=(NormalFrameTime>>rate);
3121 if (xenoStatusPointer->Left_Arm_Tilt<-(XENO_ARM_PITCH_GIMBALL<<4)) {
3122 xenoStatusPointer->Left_Arm_Tilt=-(XENO_ARM_PITCH_GIMBALL<<4);
3123 xenoStatusPointer->leftarmtiltdir=1;
3124 } else {
3125 xenoStatusPointer->la_moving=1;
3126 }
3127 }
3128
3129 if (xenoStatusPointer->left_arm_tilt) {
3130 xenoStatusPointer->left_arm_tilt->Active=1;
3131 }
3132
3133 }
3134
3135 void Xeno_RightArmMovement_TrackLeftRight(STRATEGYBLOCK *sbPtr,int rate)
3136 {
3137 XENO_STATUS_BLOCK *xenoStatusPointer;
3138
3139 LOCALASSERT(sbPtr);
3140 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
3141 LOCALASSERT(xenoStatusPointer);
3142
3143 /* Let's wave the Right arm around. */
3144 if (xenoStatusPointer->rightarmpandir) {
3145 xenoStatusPointer->Right_Arm_Pan+=(NormalFrameTime>>rate);
3146 if (xenoStatusPointer->Right_Arm_Pan>(XENO_RIGHTARM_ACW_GIMBALL<<4)) {
3147 xenoStatusPointer->Right_Arm_Pan=(XENO_RIGHTARM_ACW_GIMBALL<<4);
3148 xenoStatusPointer->rightarmpandir=0;
3149 } else {
3150 xenoStatusPointer->ra_moving=1;
3151 }
3152 } else {
3153 xenoStatusPointer->Right_Arm_Pan-=(NormalFrameTime>>rate);
3154 if (xenoStatusPointer->Right_Arm_Pan<-(XENO_RIGHTARM_CW_GIMBALL<<4)) {
3155 xenoStatusPointer->Right_Arm_Pan=-(XENO_RIGHTARM_CW_GIMBALL<<4);
3156 xenoStatusPointer->rightarmpandir=1;
3157 } else {
3158 xenoStatusPointer->ra_moving=1;
3159 }
3160 }
3161
3162 if (xenoStatusPointer->right_arm_pan) {
3163 xenoStatusPointer->right_arm_pan->Active=1;
3164 }
3165
3166 }
3167
3168 void Xeno_RightArmMovement_TrackUpDown(STRATEGYBLOCK *sbPtr,int rate)
3169 {
3170 XENO_STATUS_BLOCK *xenoStatusPointer;
3171
3172 LOCALASSERT(sbPtr);
3173 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
3174 LOCALASSERT(xenoStatusPointer);
3175
3176 /* Let's wave the Right arm around. */
3177 if (xenoStatusPointer->rightarmtiltdir) {
3178 xenoStatusPointer->Right_Arm_Tilt+=(NormalFrameTime>>rate);
3179 if (xenoStatusPointer->Right_Arm_Tilt>(XENO_ARM_PITCH_GIMBALL<<4)) {
3180 xenoStatusPointer->Right_Arm_Tilt=(XENO_ARM_PITCH_GIMBALL<<4);
3181 xenoStatusPointer->rightarmtiltdir=0;
3182 } else {
3183 xenoStatusPointer->ra_moving=1;
3184 }
3185 } else {
3186 xenoStatusPointer->Right_Arm_Tilt-=(NormalFrameTime>>rate);
3187 if (xenoStatusPointer->Right_Arm_Tilt<-(XENO_ARM_PITCH_GIMBALL<<4)) {
3188 xenoStatusPointer->Right_Arm_Tilt=-(XENO_ARM_PITCH_GIMBALL<<4);
3189 xenoStatusPointer->rightarmtiltdir=1;
3190 } else {
3191 xenoStatusPointer->ra_moving=1;
3192 }
3193 }
3194
3195 if (xenoStatusPointer->right_arm_tilt) {
3196 xenoStatusPointer->right_arm_tilt->Active=1;
3197 }
3198
3199 }
3200
3201 void Xeno_RightArmMovement_WaveUp(STRATEGYBLOCK *sbPtr,int rate)
3202 {
3203 XENO_STATUS_BLOCK *xenoStatusPointer;
3204
3205 LOCALASSERT(sbPtr);
3206 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
3207 LOCALASSERT(xenoStatusPointer);
3208
3209 /* Let's wave the Right arm around. */
3210 if (xenoStatusPointer->rightarmtiltdir) {
3211 xenoStatusPointer->Right_Arm_Tilt+=(NormalFrameTime>>rate);
3212 if (xenoStatusPointer->Right_Arm_Tilt>-(XENO_HEADTILT_GIMBALL<<4)) {
3213 xenoStatusPointer->Right_Arm_Tilt=-(XENO_HEADTILT_GIMBALL<<4);
3214 xenoStatusPointer->rightarmtiltdir=0;
3215 } else {
3216 xenoStatusPointer->ra_moving=1;
3217 }
3218 } else {
3219 xenoStatusPointer->Right_Arm_Tilt-=(NormalFrameTime>>rate);
3220 if (xenoStatusPointer->Right_Arm_Tilt<-(XENO_ARM_PITCH_GIMBALL<<4)) {
3221 xenoStatusPointer->Right_Arm_Tilt=-(XENO_ARM_PITCH_GIMBALL<<4);
3222 xenoStatusPointer->rightarmtiltdir=1;
3223 } else {
3224 xenoStatusPointer->ra_moving=1;
3225 }
3226 }
3227
3228 if (xenoStatusPointer->right_arm_tilt) {
3229 xenoStatusPointer->right_arm_tilt->Active=1;
3230 }
3231
3232 }
3233
3234 void Xeno_TorsoMovement_TrackLeftRight(STRATEGYBLOCK *sbPtr,int rate)
3235 {
3236 XENO_STATUS_BLOCK *xenoStatusPointer;
3237
3238 LOCALASSERT(sbPtr);
3239 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
3240 LOCALASSERT(xenoStatusPointer);
3241
3242 /* Let's twist the torso. */
3243 if (xenoStatusPointer->torsotwistdir) {
3244 xenoStatusPointer->Torso_Twist+=(NormalFrameTime>>rate);
3245 if (xenoStatusPointer->Torso_Twist>(XENO_TORSO_GIMBALL<<4)) {
3246 xenoStatusPointer->Torso_Twist=(XENO_TORSO_GIMBALL<<4);
3247 xenoStatusPointer->torsotwistdir=0;
3248 } else {
3249 xenoStatusPointer->torso_moving=1;
3250 }
3251 } else {
3252 xenoStatusPointer->Torso_Twist-=(NormalFrameTime>>rate);
3253 if (xenoStatusPointer->Torso_Twist<-(XENO_TORSO_GIMBALL<<4)) {
3254 xenoStatusPointer->Torso_Twist=-(XENO_TORSO_GIMBALL<<4);
3255 xenoStatusPointer->torsotwistdir=1;
3256 } else {
3257 xenoStatusPointer->torso_moving=1;
3258 }
3259 }
3260
3261 if (xenoStatusPointer->right_arm_tilt) {
3262 xenoStatusPointer->right_arm_tilt->Active=1;
3263 }
3264
3265 }
3266
3267 int Xeno_HeadMovement_TrackToAngles(STRATEGYBLOCK *sbPtr,int rate,int in_anglex,int in_angley)
3268 {
3269 XENO_STATUS_BLOCK *xenoStatusPointer;
3270 int real_anglex,angley,online;
3271
3272 LOCALASSERT(sbPtr);
3273 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
3274 LOCALASSERT(xenoStatusPointer);
3275
3276 /* Turn the head to face a certain way. */
3277
3278 real_anglex=in_anglex-(xenoStatusPointer->Torso_Twist>>4);
3279 angley=in_angley;
3280 online=0;
3281
3282 /* Now fix multiples. */
3283 while ((real_anglex>4095)||(real_anglex<0)) {
3284 if (real_anglex<0) {
3285 real_anglex+=4096;
3286 } else if (real_anglex>4095) {
3287 real_anglex-=4096;
3288 }
3289 }
3290
3291 if (real_anglex>=3072) real_anglex-=4096;
3292 if (real_anglex>=2048) real_anglex=real_anglex-3072;
3293 if (real_anglex> 1024) real_anglex=2048-real_anglex;
3294
3295 if (angley>=3072) angley-=4096;
3296 if (angley>=2048) angley=angley-3072;
3297 if (angley> 1024) angley=2048-angley;
3298
3299 GLOBALASSERT((real_anglex<=1024)&&(real_anglex>=-1024));
3300 GLOBALASSERT((angley<=1024)&&(angley>=-1024));
3301
3302 if (ShowXenoStats) {
3303 PrintDebuggingText("Target head angles: %d %d\n",real_anglex,angley);
3304 }
3305
3306 real_anglex<<=4;
3307 angley<<=4;
3308
3309 if (xenoStatusPointer->Head_Pan<real_anglex) {
3310 xenoStatusPointer->Head_Pan+=(NormalFrameTime>>rate);
3311 if (xenoStatusPointer->Head_Pan>(XENO_HEADPAN_GIMBALL<<4)) {
3312 xenoStatusPointer->Head_Pan=(XENO_HEADPAN_GIMBALL<<4);
3313 } else if (xenoStatusPointer->Head_Pan>real_anglex) {
3314 xenoStatusPointer->Head_Pan=real_anglex;
3315 online++;
3316 }
3317 } else if (xenoStatusPointer->Head_Pan>real_anglex) {
3318 xenoStatusPointer->Head_Pan-=(NormalFrameTime>>rate);
3319 if (xenoStatusPointer->Head_Pan<-(XENO_HEADPAN_GIMBALL<<4)) {
3320 xenoStatusPointer->Head_Pan=-(XENO_HEADPAN_GIMBALL<<4);
3321 } else if (xenoStatusPointer->Head_Pan<real_anglex) {
3322 xenoStatusPointer->Head_Pan=real_anglex;
3323 online++;
3324 }
3325 } else {
3326 online++;
3327 }
3328
3329 if (xenoStatusPointer->head_pan) {
3330 xenoStatusPointer->head_pan->Active=1;
3331 }
3332
3333 /* Now y. */
3334 angley=-angley;
3335 /* Oops. */
3336
3337 if (xenoStatusPointer->Head_Tilt<angley) {
3338 xenoStatusPointer->Head_Tilt+=(NormalFrameTime>>rate);
3339 if (xenoStatusPointer->Head_Tilt>(XENO_HEADTILT_GIMBALL<<4)) {
3340 xenoStatusPointer->Head_Tilt=(XENO_HEADTILT_GIMBALL<<4);
3341 } else if (xenoStatusPointer->Head_Tilt>angley) {
3342 xenoStatusPointer->Head_Tilt=angley;
3343 online++;
3344 }
3345 } else if (xenoStatusPointer->Head_Tilt>angley) {
3346 xenoStatusPointer->Head_Tilt-=(NormalFrameTime>>rate);
3347 if (xenoStatusPointer->Head_Tilt<-(XENO_HEADTILT_GIMBALL<<4)) {
3348 xenoStatusPointer->Head_Tilt=-(XENO_HEADTILT_GIMBALL<<4);
3349 } else if (xenoStatusPointer->Head_Tilt<angley) {
3350 xenoStatusPointer->Head_Tilt=angley;
3351 online++;
3352 }
3353 } else {
3354 online++;
3355 }
3356
3357 if (xenoStatusPointer->head_tilt) {
3358 xenoStatusPointer->head_tilt->Active=1;
3359 }
3360
3361 if (online<=1) {
3362 /* Still moving! */
3363 xenoStatusPointer->head_moving=1;
3364 }
3365
3366 if (xenoStatusPointer->HeadLaserOnTarget) {
3367 online=2;
3368 }
3369
3370 if (online>1) {
3371 return(1);
3372 } else {
3373 return(0);
3374 }
3375 }
3376
3377 void Xeno_TorsoMovement_TrackToAngle(STRATEGYBLOCK *sbPtr,int rate,int in_anglex)
3378 {
3379 XENO_STATUS_BLOCK *xenoStatusPointer;
3380 int anglex;
3381
3382 LOCALASSERT(sbPtr);
3383 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
3384 LOCALASSERT(xenoStatusPointer);
3385
3386 /* Turn the torso to face a certain way. No angley here. */
3387
3388 anglex=in_anglex;
3389
3390 if (anglex>=3072) anglex-=4096;
3391 if (anglex>=2048) anglex=anglex-3072;
3392 if (anglex> 1024) anglex=2048-anglex;
3393
3394 anglex<<=4;
3395
3396 if (xenoStatusPointer->Torso_Twist<anglex) {
3397 xenoStatusPointer->Torso_Twist+=(NormalFrameTime>>rate);
3398 if (xenoStatusPointer->Torso_Twist>(XENO_TORSO_GIMBALL<<4)) {
3399 xenoStatusPointer->Torso_Twist=(XENO_TORSO_GIMBALL<<4);
3400 } else if (xenoStatusPointer->Torso_Twist>anglex) {
3401 xenoStatusPointer->Torso_Twist=anglex;
3402 } else {
3403 xenoStatusPointer->torso_moving=1;
3404 }
3405 } else if (xenoStatusPointer->Torso_Twist>anglex) {
3406 xenoStatusPointer->Torso_Twist-=(NormalFrameTime>>rate);
3407 if (xenoStatusPointer->Torso_Twist<-(XENO_TORSO_GIMBALL<<4)) {
3408 xenoStatusPointer->Torso_Twist=-(XENO_TORSO_GIMBALL<<4);
3409 } else if (xenoStatusPointer->Torso_Twist<anglex) {
3410 xenoStatusPointer->Torso_Twist=anglex;
3411 } else {
3412 xenoStatusPointer->torso_moving=1;
3413 }
3414 }
3415
3416 if (xenoStatusPointer->torso_twist) {
3417 xenoStatusPointer->torso_twist->Active=1;
3418 }
3419
3420 }
3421
3422 void Xeno_TorsoMovement_Centre(STRATEGYBLOCK *sbPtr,int rate)
3423 {
3424 XENO_STATUS_BLOCK *xenoStatusPointer;
3425
3426 LOCALASSERT(sbPtr);
3427 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
3428 LOCALASSERT(xenoStatusPointer);
3429
3430 /* Turn the torso to face a certain way. No angley here. */
3431
3432 if (xenoStatusPointer->Torso_Twist<0) {
3433 xenoStatusPointer->Torso_Twist+=(NormalFrameTime>>rate);
3434 if (xenoStatusPointer->Torso_Twist>(XENO_TORSO_GIMBALL<<4)) {
3435 xenoStatusPointer->Torso_Twist=(XENO_TORSO_GIMBALL<<4);
3436 } else if (xenoStatusPointer->Torso_Twist>0) {
3437 xenoStatusPointer->Torso_Twist=0;
3438 } else {
3439 xenoStatusPointer->torso_moving=1;
3440 }
3441 } else if (xenoStatusPointer->Torso_Twist>0) {
3442 xenoStatusPointer->Torso_Twist-=(NormalFrameTime>>rate);
3443 if (xenoStatusPointer->Torso_Twist<-(XENO_TORSO_GIMBALL<<4)) {
3444 xenoStatusPointer->Torso_Twist=-(XENO_TORSO_GIMBALL<<4);
3445 } else if (xenoStatusPointer->Torso_Twist<0) {
3446 xenoStatusPointer->Torso_Twist=0;
3447 } else {
3448 xenoStatusPointer->torso_moving=1;
3449 }
3450 }
3451
3452 if (xenoStatusPointer->torso_twist) {
3453 xenoStatusPointer->torso_twist->Active=1;
3454 }
3455
3456 }
3457
3458 int Xeno_LeftArmMovement_TrackToAngles(STRATEGYBLOCK *sbPtr,int rate,int in_anglex,int in_angley)
3459 {
3460 XENO_STATUS_BLOCK *xenoStatusPointer;
3461 int real_anglex,angley,online;
3462
3463 LOCALASSERT(sbPtr);
3464 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
3465 LOCALASSERT(xenoStatusPointer);
3466
3467 /* Aim the Left Arm at a point. */
3468
3469 real_anglex=in_anglex-(xenoStatusPointer->Torso_Twist>>4);
3470 angley=in_angley;
3471 online=0;
3472
3473 /* Now fix multiples. */
3474 while ((real_anglex>4095)||(real_anglex<0)) {
3475 if (real_anglex<0) {
3476 real_anglex+=4096;
3477 } else if (real_anglex>4095) {
3478 real_anglex-=4096;
3479 }
3480 }
3481
3482 if (real_anglex>=3072) real_anglex-=4096;
3483 if (real_anglex>=2048) real_anglex=real_anglex-3072;
3484 if (real_anglex> 1024) real_anglex=2048-real_anglex;
3485
3486 if (angley>=3072) angley-=4096;
3487 if (angley>=2048) angley=angley-3072;
3488 if (angley> 1024) angley=2048-angley;
3489
3490 real_anglex<<=4;
3491 angley<<=4;
3492
3493 if (xenoStatusPointer->Left_Arm_Pan<real_anglex) {
3494 xenoStatusPointer->Left_Arm_Pan+=(NormalFrameTime>>rate);
3495 if (xenoStatusPointer->Left_Arm_Pan>(XENO_LEFTARM_ACW_GIMBALL<<4)) {
3496 xenoStatusPointer->Left_Arm_Pan=(XENO_LEFTARM_ACW_GIMBALL<<4);
3497 } else if (xenoStatusPointer->Left_Arm_Pan>real_anglex) {
3498 xenoStatusPointer->Left_Arm_Pan=real_anglex;
3499 online++;
3500 }
3501 } else if (xenoStatusPointer->Left_Arm_Pan>real_anglex) {
3502 xenoStatusPointer->Left_Arm_Pan-=(NormalFrameTime>>rate);
3503 if (xenoStatusPointer->Left_Arm_Pan<-(XENO_LEFTARM_CW_GIMBALL<<4)) {
3504 xenoStatusPointer->Left_Arm_Pan=-(XENO_LEFTARM_CW_GIMBALL<<4);
3505 } else if (xenoStatusPointer->Left_Arm_Pan<real_anglex) {
3506 xenoStatusPointer->Left_Arm_Pan=real_anglex;
3507 online++;
3508 }
3509 } else {
3510 online++;
3511 }
3512
3513 if (xenoStatusPointer->left_arm_pan) {
3514 xenoStatusPointer->left_arm_pan->Active=1;
3515 }
3516
3517 /* Now y. */
3518 angley=-angley;
3519 /* Oops. */
3520
3521 if (xenoStatusPointer->Left_Arm_Tilt<angley) {
3522 xenoStatusPointer->Left_Arm_Tilt+=(NormalFrameTime>>rate);
3523 if (xenoStatusPointer->Left_Arm_Tilt>(XENO_ARM_PITCH_GIMBALL<<4)) {
3524 xenoStatusPointer->Left_Arm_Tilt=(XENO_ARM_PITCH_GIMBALL<<4);
3525 } else if (xenoStatusPointer->Left_Arm_Tilt>angley) {
3526 xenoStatusPointer->Left_Arm_Tilt=angley;
3527 online++;
3528 }
3529 } else if (xenoStatusPointer->Left_Arm_Tilt>angley) {
3530 xenoStatusPointer->Left_Arm_Tilt-=(NormalFrameTime>>rate);
3531 if (xenoStatusPointer->Left_Arm_Tilt<-(XENO_ARM_PITCH_GIMBALL<<4)) {
3532 xenoStatusPointer->Left_Arm_Tilt=-(XENO_ARM_PITCH_GIMBALL<<4);
3533 } else if (xenoStatusPointer->Left_Arm_Tilt<angley) {
3534 xenoStatusPointer->Left_Arm_Tilt=angley;
3535 online++;
3536 }
3537 } else {
3538 online++;
3539 }
3540
3541 if (xenoStatusPointer->left_arm_tilt) {
3542 xenoStatusPointer->left_arm_tilt->Active=1;
3543 }
3544
3545 if (online<=1) {
3546 /* Still going! */
3547 xenoStatusPointer->la_moving=1;
3548 }
3549
3550 if (xenoStatusPointer->HeadLaserOnTarget) {
3551 xenoStatusPointer->UseLALaser=1;
3552 }
3553
3554 if (xenoStatusPointer->LALaserOnTarget) {
3555 online=2;
3556 }
3557
3558 if (online>1) {
3559 if (xenoStatusPointer->Target) {
3560 /* What the heck! */
3561 xenoStatusPointer->FiringLeft=1;
3562 }
3563 return(1);
3564 } else {
3565 return(0);
3566 }
3567
3568 }
3569
3570 void Xeno_LeftArmMovement_Centre(STRATEGYBLOCK *sbPtr,int rate)
3571 {
3572 XENO_STATUS_BLOCK *xenoStatusPointer;
3573
3574 LOCALASSERT(sbPtr);
3575 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
3576 LOCALASSERT(xenoStatusPointer);
3577
3578 /* Centre the Left Arm. */
3579
3580 if (xenoStatusPointer->Left_Arm_Pan<0) {
3581 xenoStatusPointer->Left_Arm_Pan+=(NormalFrameTime>>rate);
3582 if (xenoStatusPointer->Left_Arm_Pan>(XENO_LEFTARM_ACW_GIMBALL<<4)) {
3583 xenoStatusPointer->Left_Arm_Pan=(XENO_LEFTARM_ACW_GIMBALL<<4);
3584 } else if (xenoStatusPointer->Left_Arm_Pan>0) {
3585 xenoStatusPointer->Left_Arm_Pan=0;
3586 } else {
3587 xenoStatusPointer->la_moving=1;
3588 }
3589 } else if (xenoStatusPointer->Left_Arm_Pan>0) {
3590 xenoStatusPointer->Left_Arm_Pan-=(NormalFrameTime>>rate);
3591 if (xenoStatusPointer->Left_Arm_Pan<-(XENO_LEFTARM_CW_GIMBALL<<4)) {
3592 xenoStatusPointer->Left_Arm_Pan=-(XENO_LEFTARM_CW_GIMBALL<<4);
3593 } else if (xenoStatusPointer->Left_Arm_Pan<0) {
3594 xenoStatusPointer->Left_Arm_Pan=0;
3595 } else {
3596 xenoStatusPointer->la_moving=1;
3597 }
3598 }
3599
3600 if (xenoStatusPointer->left_arm_pan) {
3601 xenoStatusPointer->left_arm_pan->Active=1;
3602 }
3603
3604 /* Now y. */
3605
3606 if (xenoStatusPointer->Left_Arm_Tilt<0) {
3607 xenoStatusPointer->Left_Arm_Tilt+=(NormalFrameTime>>rate);
3608 if (xenoStatusPointer->Left_Arm_Tilt>(XENO_ARM_PITCH_GIMBALL<<4)) {
3609 xenoStatusPointer->Left_Arm_Tilt=(XENO_ARM_PITCH_GIMBALL<<4);
3610 } else if (xenoStatusPointer->Left_Arm_Tilt>0) {
3611 xenoStatusPointer->Left_Arm_Tilt=0;
3612 } else {
3613 xenoStatusPointer->la_moving=1;
3614 }
3615 } else if (xenoStatusPointer->Left_Arm_Tilt>0) {
3616 xenoStatusPointer->Left_Arm_Tilt-=(NormalFrameTime>>rate);
3617 if (xenoStatusPointer->Left_Arm_Tilt<-(XENO_ARM_PITCH_GIMBALL<<4)) {
3618 xenoStatusPointer->Left_Arm_Tilt=-(XENO_ARM_PITCH_GIMBALL<<4);
3619 } else if (xenoStatusPointer->Left_Arm_Tilt<0) {
3620 xenoStatusPointer->Left_Arm_Tilt=0;
3621 } else {
3622 xenoStatusPointer->la_moving=1;
3623 }
3624 }
3625
3626 if (xenoStatusPointer->left_arm_tilt) {
3627 xenoStatusPointer->left_arm_tilt->Active=1;
3628 }
3629
3630 return;
3631
3632 }
3633
3634 int Xeno_RightArmMovement_TrackToAngles(STRATEGYBLOCK *sbPtr,int rate,int in_anglex,int in_angley)
3635 {
3636 XENO_STATUS_BLOCK *xenoStatusPointer;
3637 int real_anglex,angley,online;
3638
3639 LOCALASSERT(sbPtr);
3640 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
3641 LOCALASSERT(xenoStatusPointer);
3642
3643 /* Aim the Right Arm at a point. */
3644
3645 real_anglex=in_anglex-(xenoStatusPointer->Torso_Twist>>4)+RATweak;
3646 angley=in_angley;
3647 online=0;
3648
3649 /* Now fix multiples. */
3650 while ((real_anglex>4095)||(real_anglex<0)) {
3651 if (real_anglex<0) {
3652 real_anglex+=4096;
3653 } else if (real_anglex>4095) {
3654 real_anglex-=4096;
3655 }
3656 }
3657
3658 if (real_anglex>=3072) real_anglex-=4096;
3659 if (real_anglex>=2048) real_anglex=real_anglex-3072;
3660 if (real_anglex> 1024) real_anglex=2048-real_anglex;
3661
3662 if (angley>=3072) angley-=4096;
3663 if (angley>=2048) angley=angley-3072;
3664 if (angley> 1024) angley=2048-angley;
3665
3666 real_anglex<<=4;
3667 angley<<=4;
3668
3669 if (xenoStatusPointer->Right_Arm_Pan<real_anglex) {
3670 xenoStatusPointer->Right_Arm_Pan+=(NormalFrameTime>>rate);
3671 if (xenoStatusPointer->Right_Arm_Pan>(XENO_RIGHTARM_ACW_GIMBALL<<4)) {
3672 xenoStatusPointer->Right_Arm_Pan=(XENO_RIGHTARM_ACW_GIMBALL<<4);
3673 } else if (xenoStatusPointer->Right_Arm_Pan>real_anglex) {
3674 xenoStatusPointer->Right_Arm_Pan=real_anglex;
3675 online++;
3676 }
3677 } else if (xenoStatusPointer->Right_Arm_Pan>real_anglex) {
3678 xenoStatusPointer->Right_Arm_Pan-=(NormalFrameTime>>rate);
3679 if (xenoStatusPointer->Right_Arm_Pan<-(XENO_RIGHTARM_CW_GIMBALL<<4)) {
3680 xenoStatusPointer->Right_Arm_Pan=-(XENO_RIGHTARM_CW_GIMBALL<<4);
3681 } else if (xenoStatusPointer->Right_Arm_Pan<real_anglex) {
3682 xenoStatusPointer->Right_Arm_Pan=real_anglex;
3683 online++;
3684 }
3685 } else {
3686 online++;
3687 }
3688
3689 if (xenoStatusPointer->right_arm_pan) {
3690 xenoStatusPointer->right_arm_pan->Active=1;
3691 }
3692
3693 /* Now y. */
3694 angley=-angley;
3695 /* Oops. */
3696
3697 if (xenoStatusPointer->Right_Arm_Tilt<angley) {
3698 xenoStatusPointer->Right_Arm_Tilt+=(NormalFrameTime>>rate);
3699 if (xenoStatusPointer->Right_Arm_Tilt>(XENO_ARM_PITCH_GIMBALL<<4)) {
3700 xenoStatusPointer->Right_Arm_Tilt=(XENO_ARM_PITCH_GIMBALL<<4);
3701 } else if (xenoStatusPointer->Right_Arm_Tilt>angley) {
3702 xenoStatusPointer->Right_Arm_Tilt=angley;
3703 online++;
3704 }
3705 } else if (xenoStatusPointer->Right_Arm_Tilt>angley) {
3706 xenoStatusPointer->Right_Arm_Tilt-=(NormalFrameTime>>rate);
3707 if (xenoStatusPointer->Right_Arm_Tilt<-(XENO_ARM_PITCH_GIMBALL<<4)) {
3708 xenoStatusPointer->Right_Arm_Tilt=-(XENO_ARM_PITCH_GIMBALL<<4);
3709 } else if (xenoStatusPointer->Right_Arm_Tilt<angley) {
3710 xenoStatusPointer->Right_Arm_Tilt=angley;
3711 online++;
3712 }
3713 } else {
3714 online++;
3715 }
3716
3717 if (xenoStatusPointer->right_arm_tilt) {
3718 xenoStatusPointer->right_arm_tilt->Active=1;
3719 }
3720
3721 if (online<=1) {
3722 /* Still moving! */
3723 xenoStatusPointer->ra_moving=1;
3724 }
3725
3726 if (xenoStatusPointer->HeadLaserOnTarget) {
3727 xenoStatusPointer->UseRALaser=1;
3728 }
3729
3730 if (xenoStatusPointer->RALaserOnTarget) {
3731 online=2;
3732 }
3733
3734 if (online>1) {
3735 if (xenoStatusPointer->Target) {
3736 /* What the heck! */
3737 xenoStatusPointer->FiringRight=1;
3738 }
3739 return(1);
3740 } else {
3741 return(0);
3742 }
3743
3744 }
3745
3746 void Xeno_RightArmMovement_Centre(STRATEGYBLOCK *sbPtr,int rate)
3747 {
3748 XENO_STATUS_BLOCK *xenoStatusPointer;
3749
3750 LOCALASSERT(sbPtr);
3751 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
3752 LOCALASSERT(xenoStatusPointer);
3753
3754 /* Centre the Right Arm. */
3755
3756 if (xenoStatusPointer->Right_Arm_Pan<0) {
3757 xenoStatusPointer->Right_Arm_Pan+=(NormalFrameTime>>rate);
3758 if (xenoStatusPointer->Right_Arm_Pan>(XENO_RIGHTARM_ACW_GIMBALL<<4)) {
3759 xenoStatusPointer->Right_Arm_Pan=(XENO_RIGHTARM_ACW_GIMBALL<<4);
3760 } else if (xenoStatusPointer->Right_Arm_Pan>0) {
3761 xenoStatusPointer->Right_Arm_Pan=0;
3762 } else {
3763 xenoStatusPointer->ra_moving=1;
3764 }
3765 } else if (xenoStatusPointer->Right_Arm_Pan>0) {
3766 xenoStatusPointer->Right_Arm_Pan-=(NormalFrameTime>>rate);
3767 if (xenoStatusPointer->Right_Arm_Pan<-(XENO_RIGHTARM_CW_GIMBALL<<4)) {
3768 xenoStatusPointer->Right_Arm_Pan=-(XENO_RIGHTARM_CW_GIMBALL<<4);
3769 } else if (xenoStatusPointer->Right_Arm_Pan<0) {
3770 xenoStatusPointer->Right_Arm_Pan=0;
3771 } else {
3772 xenoStatusPointer->ra_moving=1;
3773 }
3774 }
3775
3776 if (xenoStatusPointer->right_arm_pan) {
3777 xenoStatusPointer->right_arm_pan->Active=1;
3778 }
3779
3780 /* Now y. */
3781
3782 if (xenoStatusPointer->Right_Arm_Tilt<0) {
3783 xenoStatusPointer->Right_Arm_Tilt+=(NormalFrameTime>>rate);
3784 if (xenoStatusPointer->Right_Arm_Tilt>(XENO_ARM_PITCH_GIMBALL<<4)) {
3785 xenoStatusPointer->Right_Arm_Tilt=(XENO_ARM_PITCH_GIMBALL<<4);
3786 } else if (xenoStatusPointer->Right_Arm_Tilt>0) {
3787 xenoStatusPointer->Right_Arm_Tilt=0;
3788 } else {
3789 xenoStatusPointer->ra_moving=1;
3790 }
3791 } else if (xenoStatusPointer->Right_Arm_Tilt>0) {
3792 xenoStatusPointer->Right_Arm_Tilt-=(NormalFrameTime>>rate);
3793 if (xenoStatusPointer->Right_Arm_Tilt<-(XENO_ARM_PITCH_GIMBALL<<4)) {
3794 xenoStatusPointer->Right_Arm_Tilt=-(XENO_ARM_PITCH_GIMBALL<<4);
3795 } else if (xenoStatusPointer->Right_Arm_Tilt<0) {
3796 xenoStatusPointer->Right_Arm_Tilt=0;
3797 } else {
3798 xenoStatusPointer->ra_moving=1;
3799 }
3800 }
3801
3802 if (xenoStatusPointer->right_arm_tilt) {
3803 xenoStatusPointer->right_arm_tilt->Active=1;
3804 }
3805
3806 return;
3807
3808 }
3809
3810 int XenoActivation_FrustrumReject(VECTORCH *localOffset) {
3811
3812 if ( (localOffset->vz <0)
3813 && (localOffset->vz < localOffset->vx)
3814 && (localOffset->vz < -localOffset->vx)
3815 && (localOffset->vz < localOffset->vy)
3816 && (localOffset->vz < -localOffset->vy) ) {
3817
3818 /* 90 horizontal, 90 vertical. */
3819 return(1);
3820 } else {
3821 return(0);
3822 }
3823
3824 }
3825
3826 int XenoSight_FrustrumReject(STRATEGYBLOCK *sbPtr,VECTORCH *localOffset) {
3827
3828 XENO_STATUS_BLOCK *xenoStatusPointer;
3829
3830 LOCALASSERT(sbPtr);
3831 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
3832 LOCALASSERT(xenoStatusPointer);
3833
3834 if ( (localOffset->vx>0) ) {
3835 /* 180 horizontal, 180 vertical. */
3836 return(1);
3837 } else {
3838 if ((xenoStatusPointer->Target)||(xenoStatusPointer->ShotThisFrame)) {
3839 return(1);
3840 } else {
3841 return(0);
3842 }
3843 }
3844
3845 }
3846
3847 void Xeno_UpdateTargetTrackPos(STRATEGYBLOCK *sbPtr) {
3848
3849 XENO_STATUS_BLOCK *xenoStatusPointer;
3850
3851 LOCALASSERT(sbPtr);
3852 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
3853 LOCALASSERT(xenoStatusPointer);
3854
3855 if (xenoStatusPointer->Target==NULL) {
3856 xenoStatusPointer->targetTrackPos.vx=0;
3857 xenoStatusPointer->targetTrackPos.vy=0;
3858 xenoStatusPointer->targetTrackPos.vz=0;
3859 return;
3860 }
3861
3862 GetTargetingPointOfObject_Far(xenoStatusPointer->Target,&xenoStatusPointer->targetTrackPos);
3863
3864 }
3865
3866 static void ProcessFarXenoborgTargetModule(STRATEGYBLOCK *sbPtr, AIMODULE* targetModule)
3867 {
3868 NPC_TARGETMODULESTATUS targetStatus;
3869 XENO_STATUS_BLOCK *xenoStatusPointer;
3870
3871 LOCALASSERT(sbPtr);
3872 LOCALASSERT(targetModule);
3873 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
3874 LOCALASSERT(xenoStatusPointer);
3875
3876 targetStatus = GetTargetAIModuleStatus(sbPtr, targetModule,0);
3877 switch(targetStatus)
3878 {
3879 case(NPCTM_NoEntryPoint):
3880 {
3881 /* do nothing */
3882 FarNpc_FlipAround(sbPtr);
3883 break;
3884 }
3885 case(NPCTM_NormalRoom):
3886 {
3887 /* locate to target */
3888 LocateFarNPCInAIModule(sbPtr, targetModule);
3889 break;
3890 }
3891 case(NPCTM_AirDuct):
3892 {
3893 /* loacate to target */
3894 LocateFarNPCInAIModule(sbPtr, targetModule);
3895 break;
3896 }
3897 case(NPCTM_LiftTeleport):
3898 {
3899 /* do nothing */
3900 FarNpc_FlipAround(sbPtr);
3901 break;
3902 }
3903 case(NPCTM_ProxDoorOpen):
3904 {
3905 LocateFarNPCInAIModule(sbPtr, targetModule);
3906 break;
3907 }
3908 case(NPCTM_ProxDoorNotOpen):
3909 {
3910 MODULE *renderModule;
3911 renderModule=*(targetModule->m_module_ptrs);
3912 /* trigger the door, and set timer to quick so we can catch the door when it's open */
3913 ((PROXDOOR_BEHAV_BLOCK *)renderModule->m_sbptr->SBdataptr)->alienTrigger = 1;
3914 break;
3915 }
3916 case(NPCTM_LiftDoorOpen):
3917 {
3918 /* do nothing - can't use lifts */
3919 //FarNpc_FlipAround(sbPtr);
3920 /* What the hell!!! */
3921 LocateFarNPCInAIModule(sbPtr, targetModule);
3922 break;
3923 }
3924 case(NPCTM_LiftDoorNotOpen):
3925 {
3926 /* do nothing - can't open lift doors */
3927 FarNpc_FlipAround(sbPtr);
3928 break;
3929 }
3930 case(NPCTM_SecurityDoorOpen):
3931 {
3932 /* locate to target, and move thro' quick as we can't retrigger */
3933 LocateFarNPCInAIModule(sbPtr, targetModule);
3934 break;
3935 }
3936 case(NPCTM_SecurityDoorNotOpen):
3937 {
3938 MODULE *renderModule;
3939 renderModule=*(targetModule->m_module_ptrs);
3940 /* do some door opening stuff here. Door should stay open for long enough
3941 for us to catch it open next time */
3942 RequestState((renderModule->m_sbptr),1,0);
3943 break;
3944 }
3945 default:
3946 {
3947 LOCALASSERT(1==0);
3948 }
3949 }
3950 }
3951
3952 void Execute_Xeno_ActiveWait_Far(STRATEGYBLOCK *sbPtr)
3953 {
3954 XENO_STATUS_BLOCK *xenoStatusPointer;
3955 int anglex,angley,correctlyOrientated;
3956
3957 LOCALASSERT(sbPtr);
3958 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
3959 LOCALASSERT(xenoStatusPointer);
3960
3961 /* What to do? Do we have a target? */
3962
3963 if (ShowXenoStats) {
3964 PrintDebuggingText("In ActiveWait Far.\n");
3965 }
3966
3967 EnforceXenoborgShapeAnimSequence_Core(sbPtr,HMSQT_Xenoborg,XBSS_Powered_Up_Standard,ONE_FIXED,(ONE_FIXED>>2));
3968
3969 if (xenoStatusPointer->Target==NULL) {
3970 #if FAR_XENO_ACTIVITY
3971 /* Let's wave the head around. */
3972 Xeno_TorsoMovement_Centre(sbPtr,XENO_TORSO_TWIST_RATE);
3973 Xeno_LeftArmMovement_Centre(sbPtr,XENO_ARM_LOCK_RATE);
3974 Xeno_RightArmMovement_Centre(sbPtr,XENO_ARM_LOCK_RATE);
3975 Xeno_HeadMovement_ScanLeftRight(sbPtr,XENO_HEAD_SCAN_RATE);
3976 Xeno_HeadMovement_ScanUpDown(sbPtr,XENO_HEAD_SCAN_RATE+2);
3977 #endif
3978
3979 if (sbPtr->containingModule->m_aimodule!=xenoStatusPointer->my_module) {
3980 Xeno_Enter_Returning_State(sbPtr);
3981 return;
3982 }
3983
3984 xenoStatusPointer->stateTimer+=NormalFrameTime;
3985 if (xenoStatusPointer->stateTimer>xenoStatusPointer->UpTime) {
3986 Xeno_Enter_PowerDown_State(sbPtr);
3987 }
3988
3989 /* Are we at home? */
3990 if (sbPtr->containingModule->m_aimodule!=xenoStatusPointer->my_module) {
3991 Xeno_Enter_Returning_State(sbPtr);
3992 return;
3993 }
3994 /* Are we facing the right way? */
3995
3996 correctlyOrientated = NPCOrientateToVector(sbPtr, &xenoStatusPointer->my_orientdir_therin,ONE_FIXED,NULL);
3997
3998 if (!correctlyOrientated) {
3999
4000 SECTION_DATA *master_section;
4001
4002 master_section=GetThisSectionData(xenoStatusPointer->HModelController.section_data,"pelvis presley");
4003 GLOBALASSERT(master_section);
4004
4005 Xenoborg_GetRelativeAngles(sbPtr,&anglex,&angley,&master_section->World_Offset);
4006
4007 if (anglex>0) {
4008 EnforceXenoborgShapeAnimSequence_Core(sbPtr,HMSQT_Xenoborg,XBSS_Turn_Right,XENO_TURNING_ANIM_SPEED,(ONE_FIXED>>2));
4009 } else {
4010 EnforceXenoborgShapeAnimSequence_Core(sbPtr,HMSQT_Xenoborg,XBSS_Turn_Left,XENO_TURNING_ANIM_SPEED,(ONE_FIXED>>2));
4011 }
4012 #if FAR_XENO_ACTIVITY
4013 if (xenoStatusPointer->soundHandle1==SOUND_NOACTIVEINDEX) {
4014 Sound_Play(SID_LOADMOVE,"del",&sbPtr->DynPtr->Position,&xenoStatusPointer->soundHandle1);
4015 }
4016 #endif
4017 } else {
4018
4019 /* Otherwise just wait? */
4020 if (xenoStatusPointer->soundHandle1!=SOUND_NOACTIVEINDEX) {
4021 /* Well, it shouldn't be! */
4022 Sound_Stop(xenoStatusPointer->soundHandle1);
4023 }
4024 EnforceXenoborgShapeAnimSequence_Core(sbPtr,HMSQT_Xenoborg,XBSS_Powered_Up_Standard,ONE_FIXED,(ONE_FIXED>>2));
4025 xenoStatusPointer->stateTimer+=NormalFrameTime;
4026 if (xenoStatusPointer->stateTimer>xenoStatusPointer->UpTime) {
4027 Xeno_Enter_PowerDown_State(sbPtr);
4028 }
4029 }
4030 return;
4031 }
4032
4033 GLOBALASSERT(xenoStatusPointer->Target);
4034 /* Now we have a target. Can we see it? */
4035 if (xenoStatusPointer->targetSightTest==0) {
4036 /* Can't see them. Are we out of range? */
4037 if (GetNextModuleForLink(sbPtr->containingModule->m_aimodule,
4038 xenoStatusPointer->my_module,(xenoStatusPointer->module_range)-1,0)==NULL) {
4039 Xeno_Enter_Returning_State(sbPtr);
4040 } else {
4041 Xeno_Enter_Following_State(sbPtr);
4042 }
4043 return;
4044 }
4045
4046 #if FAR_XENO_ACTIVITY
4047 Xeno_TurnAndTarget(sbPtr,&anglex,&angley);
4048
4049 if ((anglex>(((XENO_HEADPAN_GIMBALL)*7)/8))
4050 ||(anglex<-(((XENO_HEADPAN_GIMBALL)*7)/8))) {
4051
4052 Xeno_Enter_TurnToFace_State(sbPtr);
4053
4054 }
4055 #endif
4056
4057 if (ShowXenoStats) {
4058 PrintDebuggingText("Targets in module....\n");
4059 }
4060
4061 }
4062
4063 void Execute_Xeno_TurnToFace_Far(STRATEGYBLOCK *sbPtr)
4064 {
4065 XENO_STATUS_BLOCK *xenoStatusPointer;
4066 int correctlyOrientated;
4067 int anglex,angley;
4068
4069 LOCALASSERT(sbPtr);
4070 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
4071 LOCALASSERT(xenoStatusPointer);
4072
4073 /* Do we have a target? */
4074
4075 if (ShowXenoStats) {
4076 PrintDebuggingText("In Turn To Face Far.\n");
4077 }
4078
4079 if (xenoStatusPointer->Target==NULL) {
4080 Xeno_Enter_ActiveWait_State(sbPtr);
4081 /* Otherwise just wait? */
4082 return;
4083 }
4084
4085 /* Now we have a target. */
4086 GLOBALASSERT(xenoStatusPointer->Target);
4087
4088 /* Set up animation... Which Way? */
4089 {
4090 SECTION_DATA *master_section;
4091 VECTORCH orientationDirn;
4092
4093 master_section=GetThisSectionData(xenoStatusPointer->HModelController.section_data,"pelvis presley");
4094 GLOBALASSERT(master_section);
4095
4096 Xenoborg_GetRelativeAngles(sbPtr,&anglex,&angley,&master_section->World_Offset);
4097
4098 if (anglex<2048) {
4099 EnforceXenoborgShapeAnimSequence_Core(sbPtr,HMSQT_Xenoborg,XBSS_Turn_Right,XENO_TURNING_ANIM_SPEED,(ONE_FIXED>>2));
4100 } else {
4101 EnforceXenoborgShapeAnimSequence_Core(sbPtr,HMSQT_Xenoborg,XBSS_Turn_Left,XENO_TURNING_ANIM_SPEED,(ONE_FIXED>>2));
4102 }
4103
4104 /* Then turn to face it, of course. */
4105
4106 orientationDirn.vx = xenoStatusPointer->targetTrackPos.vx - sbPtr->DynPtr->Position.vx;
4107 orientationDirn.vy = 0;
4108 orientationDirn.vz = xenoStatusPointer->targetTrackPos.vz - sbPtr->DynPtr->Position.vz;
4109 correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn,ONE_FIXED,NULL);
4110 /* Spin FAST. */
4111 }
4112
4113 #if FAR_XENO_ACTIVITY
4114 Xeno_TurnAndTarget(sbPtr,&anglex,&angley);
4115 #endif
4116
4117 if (correctlyOrientated) {
4118 Xeno_Enter_ActiveWait_State(sbPtr);
4119 }
4120
4121 }
4122
4123 void Execute_Xeno_Follow_Far(STRATEGYBLOCK *sbPtr)
4124 {
4125 XENO_STATUS_BLOCK *xenoStatusPointer;
4126 #if FAR_XENO_ACTIVITY
4127 int anglex,angley;
4128 #endif
4129
4130 LOCALASSERT(sbPtr);
4131 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
4132 LOCALASSERT(xenoStatusPointer);
4133
4134 /* In theory, we're following the target, and can't see it. */
4135
4136 if (ShowXenoStats) {
4137 PrintDebuggingText("In Follow Far.\n");
4138 }
4139
4140 if (xenoStatusPointer->Target==NULL) {
4141 /* Let's wave the head around. */
4142 #if FAR_XENO_ACTIVITY
4143 Xeno_HeadMovement_ScanLeftRight(sbPtr,XENO_HEAD_SCAN_RATE);
4144 Xeno_HeadMovement_ScanUpDown(sbPtr,XENO_HEAD_SCAN_RATE+2);
4145 #endif
4146 /* And return to my module. */
4147 Xeno_Enter_Returning_State(sbPtr);
4148 return;
4149 }
4150
4151 /* Increment the Far state timer */
4152 xenoStatusPointer->stateTimer += NormalFrameTime;
4153 /* check if far state timer has timed-out. If so, it is time
4154 to do something. Otherwise just return. */
4155 if(xenoStatusPointer->stateTimer < XENO_FAR_MOVE_TIME) {
4156 #if FAR_XENO_ACTIVITY
4157 Xeno_TurnAndTarget(sbPtr,&anglex,&angley);
4158 #endif
4159 return;
4160 }
4161
4162 GLOBALASSERT(xenoStatusPointer->Target);
4163 /* Now we know have a target. Can we see it yet? */
4164
4165 if (xenoStatusPointer->targetSightTest==0) {
4166
4167 AIMODULE *targetModule;
4168
4169 /* Can't see them. Never mind. Go to the next module? */
4170 if (xenoStatusPointer->Target->containingModule==NULL) {
4171 /* Fall through for now. */
4172 targetModule=NULL;
4173 } else if (GetNextModuleForLink(sbPtr->containingModule->m_aimodule,
4174 xenoStatusPointer->my_module,(xenoStatusPointer->module_range)-1,0)==NULL) {
4175 /* Too Far! */
4176 Xeno_Enter_ActiveWait_State(sbPtr);
4177 return;
4178 } else {
4179 /* Still in range: keep going. */
4180 targetModule=GetNextModuleForLink(sbPtr->containingModule->m_aimodule,
4181 xenoStatusPointer->Target->containingModule->m_aimodule,xenoStatusPointer->module_range,0);
4182
4183 }
4184
4185 if (targetModule==NULL) {
4186 /* They're way away. */
4187 Xeno_Enter_Returning_State(sbPtr);
4188 return;
4189 }
4190
4191 if (targetModule!=xenoStatusPointer->Target->containingModule->m_aimodule) {
4192
4193 GLOBALASSERT(targetModule);
4194 ProcessFarXenoborgTargetModule(sbPtr,targetModule);
4195
4196 } else {
4197 /* In our target's module! */
4198
4199 Xeno_Enter_ActiveWait_State(sbPtr);
4200
4201 }
4202
4203 } else {
4204 /* Re-aquired! */
4205 Xeno_Enter_ActiveWait_State(sbPtr);
4206 return;
4207 }
4208
4209 xenoStatusPointer->stateTimer=0;
4210
4211 #if 0
4212 EnforceXenoborgShapeAnimSequence_Core(sbPtr,HMSQT_Xenoborg,XBSS_Walking,XENO_WALKING_ANIM_SPEED,(ONE_FIXED>>2));
4213 #else
4214 XenoborgHandleMovingAnimation(sbPtr);
4215 #endif
4216
4217 #if FAR_XENO_ACTIVITY
4218 if (xenoStatusPointer->targetSightTest==0) {
4219 Xeno_TorsoMovement_Centre(sbPtr,XENO_TORSO_TWIST_RATE);
4220 Xeno_LeftArmMovement_Centre(sbPtr,XENO_ARM_LOCK_RATE);
4221 Xeno_RightArmMovement_Centre(sbPtr,XENO_ARM_LOCK_RATE);
4222 Xeno_HeadMovement_ScanLeftRight(sbPtr,XENO_HEAD_SCAN_RATE);
4223 } else {
4224 Xeno_TurnAndTarget(sbPtr,&anglex,&angley);
4225 }
4226 #endif
4227
4228 }
4229
4230 void Execute_Xeno_Return_Far(STRATEGYBLOCK *sbPtr)
4231 {
4232 XENO_STATUS_BLOCK *xenoStatusPointer;
4233
4234 LOCALASSERT(sbPtr);
4235 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
4236 LOCALASSERT(xenoStatusPointer);
4237
4238 /* In theory, we're following the target, and can't see it. */
4239
4240 if (ShowXenoStats) {
4241 PrintDebuggingText("In Return Far.\n");
4242 }
4243
4244 if (xenoStatusPointer->Target!=NULL) {
4245 /* Saw something! */
4246 /* Go to active wait. */
4247 Xeno_Enter_ActiveWait_State(sbPtr);
4248 return;
4249 }
4250
4251 /* Increment the Far state timer */
4252 xenoStatusPointer->stateTimer += NormalFrameTime;
4253 /* check if far state timer has timed-out. If so, it is time
4254 to do something. Otherwise just return. */
4255 if(xenoStatusPointer->stateTimer < XENO_FAR_MOVE_TIME) {
4256 #if FAR_XENO_ACTIVITY
4257 Xeno_HeadMovement_ScanLeftRight(sbPtr,XENO_HEAD_SCAN_RATE);
4258 Xeno_TorsoMovement_Centre(sbPtr,XENO_TORSO_TWIST_RATE);
4259 Xeno_LeftArmMovement_Centre(sbPtr,XENO_ARM_LOCK_RATE);
4260 Xeno_RightArmMovement_Centre(sbPtr,XENO_ARM_LOCK_RATE);
4261 #endif
4262 return;
4263 }
4264
4265 GLOBALASSERT(xenoStatusPointer->Target==NULL);
4266 /* Find our way home. */
4267
4268 {
4269
4270 AIMODULE *targetModule;
4271
4272 /* Go to the next module. */
4273 targetModule=GetNextModuleForLink(sbPtr->containingModule->m_aimodule,
4274 xenoStatusPointer->my_module,xenoStatusPointer->module_range+2,0);
4275 /* Just to be on the safe side. */
4276
4277 if (targetModule==NULL) {
4278 /* Emergency! */
4279 targetModule=GetNextModuleForLink(sbPtr->containingModule->m_aimodule,
4280 xenoStatusPointer->my_module,xenoStatusPointer->module_range+5,0);
4281 if (targetModule==NULL) {
4282 /* Totally broken. Stay here. */
4283 Xeno_CopeWithLossOfHome(sbPtr);
4284 return;
4285 }
4286 }
4287
4288 if (targetModule!=sbPtr->containingModule->m_aimodule) {
4289
4290 GLOBALASSERT(targetModule);
4291 ProcessFarXenoborgTargetModule(sbPtr,targetModule);
4292
4293 } else {
4294 /* In our own home module! */
4295
4296 sbPtr->DynPtr->Position=xenoStatusPointer->my_spot_therin;
4297
4298 Xeno_Enter_ActiveWait_State(sbPtr);
4299
4300 }
4301 }
4302
4303 xenoStatusPointer->stateTimer=0;
4304
4305 #if 0
4306 EnforceXenoborgShapeAnimSequence_Core(sbPtr,HMSQT_Xenoborg,XBSS_Walking,XENO_WALKING_ANIM_SPEED,(ONE_FIXED>>2));
4307 #else
4308 XenoborgHandleMovingAnimation(sbPtr);
4309 #endif
4310
4311 #if FAR_XENO_ACTIVITY
4312 Xeno_TorsoMovement_Centre(sbPtr,XENO_TORSO_TWIST_RATE);
4313 Xeno_LeftArmMovement_Centre(sbPtr,XENO_ARM_LOCK_RATE);
4314 Xeno_RightArmMovement_Centre(sbPtr,XENO_ARM_LOCK_RATE);
4315 Xeno_HeadMovement_ScanLeftRight(sbPtr,XENO_HEAD_SCAN_RATE);
4316 #endif
4317
4318 }
4319
4320 void Execute_Xeno_Avoidance_Far(STRATEGYBLOCK *sbPtr)
4321 {
4322 XENO_STATUS_BLOCK *xenoStatusPointer;
4323 #if FAR_XENO_ACTIVITY
4324 int anglex,angley;
4325 #endif
4326
4327 LOCALASSERT(sbPtr);
4328 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
4329 LOCALASSERT(xenoStatusPointer);
4330
4331 if (ShowXenoStats) {
4332 PrintDebuggingText("In Avoidance Far.\n");
4333 }
4334
4335 /* Sequences... */
4336 #if 0
4337 EnforceXenoborgShapeAnimSequence_Core(sbPtr,HMSQT_Xenoborg,XBSS_Walking,XENO_WALKING_ANIM_SPEED,(ONE_FIXED>>2));
4338 #else
4339 XenoborgHandleMovingAnimation(sbPtr);
4340 #endif
4341
4342 #if FAR_XENO_ACTIVITY
4343 if (xenoStatusPointer->targetSightTest==0) {
4344 Xeno_TorsoMovement_Centre(sbPtr,XENO_TORSO_TWIST_RATE);
4345 Xeno_LeftArmMovement_Centre(sbPtr,XENO_ARM_LOCK_RATE);
4346 Xeno_RightArmMovement_Centre(sbPtr,XENO_ARM_LOCK_RATE);
4347 Xeno_HeadMovement_ScanLeftRight(sbPtr,XENO_HEAD_SCAN_RATE);
4348 } else {
4349 Xeno_TurnAndTarget(sbPtr,&anglex,&angley);
4350 }
4351 #endif
4352
4353 {
4354
4355 /* go to an appropriate state */
4356 switch (xenoStatusPointer->lastState) {
4357 case XS_Returning:
4358 Xeno_Enter_Returning_State(sbPtr);
4359 return;
4360 break;
4361 case XS_Following:
4362 Xeno_Enter_Following_State(sbPtr);
4363 return;
4364 break;
4365 default:
4366 Xeno_Enter_ActiveWait_State(sbPtr);
4367 return;
4368 break;
4369 }
4370 /* Still here? */
4371 return;
4372
4373 }
4374 return;
4375 }
4376
4377 #define FIRING_RATE_LEFT 25
4378
4379 void Xenoborg_MaintainLeftGun(STRATEGYBLOCK *sbPtr)
4380 {
4381 XENO_STATUS_BLOCK *xenoStatusPointer;
4382 SECTION_DATA *left_dum;
4383 VECTORCH alpha;
4384 VECTORCH beta;
4385 int multiple;
4386
4387 LOCALASSERT(sbPtr);
4388 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
4389 LOCALASSERT(xenoStatusPointer);
4390
4391 left_dum=GetThisSectionData(xenoStatusPointer->HModelController.section_data,"flash dummy A");
4392
4393 if (xenoStatusPointer->Wounds§ion_flag_left_hand) {
4394 xenoStatusPointer->FiringLeft=0;
4395 }
4396
4397 if ((xenoStatusPointer->FiringLeft==0)||(left_dum==NULL)||(xenoStatusPointer->IAmFar)) {
4398 /* Not firing, go away. */
4399 xenoStatusPointer->LeftMainBeam.BeamIsOn = 0;
4400 return;
4401 }
4402
4403 /* Okay, must be firing. Did we get anyone? */
4404
4405 multiple=FIRING_RATE_LEFT*NormalFrameTime;
4406
4407 #if 0
4408 LOS_Lambda = NPC_MAX_VIEWRANGE;
4409 LOS_ObjectHitPtr = 0;
4410 LOS_HModel_Section=NULL;
4411 {
4412 extern int NumActiveBlocks;
4413 extern DISPLAYBLOCK* ActiveBlockList[];
4414 int numberOfObjects = NumActiveBlocks;
4415
4416 while (numberOfObjects--)
4417 {
4418 DISPLAYBLOCK* objectPtr = ActiveBlockList[numberOfObjects];
4419
4420 alpha = left_dum->World_Offset;
4421
4422 beta.vx=left_dum->SecMat.mat31;
4423 beta.vy=left_dum->SecMat.mat32;
4424 beta.vz=left_dum->SecMat.mat33;
4425
4426 GLOBALASSERT(objectPtr);
4427
4428 if (objectPtr!=sbPtr->SBdptr) {
4429 /* Can't hit self. */
4430 CheckForVectorIntersectionWith3dObject(objectPtr, &alpha, &beta,1);
4431 }
4432 }
4433 }
4434 #else
4435 {
4436 alpha = left_dum->World_Offset;
4437
4438 beta.vx=left_dum->SecMat.mat31;
4439 beta.vy=left_dum->SecMat.mat32;
4440 beta.vz=left_dum->SecMat.mat33;
4441 FindPolygonInLineOfSight(&beta,&alpha,0,sbPtr->SBdptr);
4442 }
4443 #endif
4444
4445 /* Now deal with LOS_ObjectHitPtr. */
4446 if (LOS_ObjectHitPtr) {
4447 if (LOS_HModel_Section) {
4448 if (LOS_ObjectHitPtr->ObStrategyBlock) {
4449 if (LOS_ObjectHitPtr->ObStrategyBlock->SBdptr) {
4450 GLOBALASSERT(LOS_ObjectHitPtr->ObStrategyBlock->SBdptr->HModelControlBlock==LOS_HModel_Section->my_controller);
4451 }
4452 }
4453 }
4454 /* this fn needs updating to take amount of damage into account etc. */
4455 HandleWeaponImpact(&LOS_Point,LOS_ObjectHitPtr->ObStrategyBlock,AMMO_XENOBORG,&beta, multiple, LOS_HModel_Section);
4456 }
4457
4458 /* Cheat for killing far targets? */
4459 if (xenoStatusPointer->Target) {
4460 if (xenoStatusPointer->Target->SBdptr==NULL) {
4461 HandleWeaponImpact(&xenoStatusPointer->Target->DynPtr->Position,xenoStatusPointer->Target,AMMO_XENOBORG,&beta, multiple, NULL);
4462 }
4463 }
4464
4465 /* update beam SFX data */
4466 xenoStatusPointer->LeftMainBeam.BeamIsOn = 1;
4467 xenoStatusPointer->LeftMainBeam.SourcePosition = left_dum->World_Offset;
4468
4469 if (LOS_ObjectHitPtr) {
4470 xenoStatusPointer->LeftMainBeam.TargetPosition = LOS_Point;
4471 } else {
4472 /* Must be hitting nothing... */
4473 xenoStatusPointer->LeftMainBeam.TargetPosition=alpha;
4474 xenoStatusPointer->LeftMainBeam.TargetPosition.vx+=(beta.vx>>3);
4475 xenoStatusPointer->LeftMainBeam.TargetPosition.vy+=(beta.vy>>3);
4476 xenoStatusPointer->LeftMainBeam.TargetPosition.vz+=(beta.vz>>3);
4477 }
4478
4479 if (LOS_ObjectHitPtr==Player)
4480 {
4481 xenoStatusPointer->LeftMainBeam.BeamHasHitPlayer = 1;
4482 }
4483 else
4484 {
4485 xenoStatusPointer->LeftMainBeam.BeamHasHitPlayer = 0;
4486 }
4487 }
4488
4489 #define FIRING_RATE_RIGHT 25
4490
4491 void Xenoborg_MaintainRightGun(STRATEGYBLOCK *sbPtr)
4492 {
4493 XENO_STATUS_BLOCK *xenoStatusPointer;
4494 SECTION_DATA *right_dum;
4495 VECTORCH alpha;
4496 VECTORCH beta;
4497 int multiple;
4498
4499 LOCALASSERT(sbPtr);
4500 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
4501 LOCALASSERT(xenoStatusPointer);
4502
4503 right_dum=GetThisSectionData(xenoStatusPointer->HModelController.section_data,"flash dummy B");
4504
4505 if (xenoStatusPointer->Wounds§ion_flag_right_hand) {
4506 xenoStatusPointer->FiringRight=0;
4507 }
4508
4509 if ((xenoStatusPointer->FiringRight==0)||(right_dum==NULL)||(xenoStatusPointer->IAmFar)) {
4510 /* Not firing, go away. */
4511 xenoStatusPointer->RightMainBeam.BeamIsOn = 0;
4512 return;
4513 }
4514
4515 /* Okay, must be firing. Did we get anyone? */
4516
4517 multiple=FIRING_RATE_RIGHT*NormalFrameTime;
4518
4519 #if 0
4520 LOS_Lambda = NPC_MAX_VIEWRANGE;
4521 LOS_ObjectHitPtr = 0;
4522 LOS_HModel_Section=NULL;
4523 {
4524 extern int NumActiveBlocks;
4525 extern DISPLAYBLOCK* ActiveBlockList[];
4526 int numberOfObjects = NumActiveBlocks;
4527
4528 while (numberOfObjects--)
4529 {
4530 DISPLAYBLOCK* objectPtr = ActiveBlockList[numberOfObjects];
4531
4532 alpha = right_dum->World_Offset;
4533
4534 beta.vx=right_dum->SecMat.mat31;
4535 beta.vy=right_dum->SecMat.mat32;
4536 beta.vz=right_dum->SecMat.mat33;
4537
4538 GLOBALASSERT(objectPtr);
4539
4540 if (objectPtr!=sbPtr->SBdptr) {
4541 /* Can't hit self. */
4542 CheckForVectorIntersectionWith3dObject(objectPtr, &alpha, &beta,1);
4543 }
4544 }
4545 }
4546 #else
4547 {
4548 alpha = right_dum->World_Offset;
4549
4550 beta.vx=right_dum->SecMat.mat31;
4551 beta.vy=right_dum->SecMat.mat32;
4552 beta.vz=right_dum->SecMat.mat33;
4553 FindPolygonInLineOfSight(&beta,&alpha,0,sbPtr->SBdptr);
4554 }
4555 #endif
4556 /* Now deal with LOS_ObjectHitPtr. */
4557 if (LOS_ObjectHitPtr) {
4558 if (LOS_HModel_Section) {
4559 if (LOS_ObjectHitPtr->ObStrategyBlock) {
4560 if (LOS_ObjectHitPtr->ObStrategyBlock->SBdptr) {
4561 GLOBALASSERT(LOS_ObjectHitPtr->ObStrategyBlock->SBdptr->HModelControlBlock==LOS_HModel_Section->my_controller);
4562 }
4563 }
4564 }
4565 /* this fn needs updating to take amount of damage into account etc. */
4566 HandleWeaponImpact(&LOS_Point,LOS_ObjectHitPtr->ObStrategyBlock,AMMO_XENOBORG,&beta, multiple, LOS_HModel_Section);
4567 }
4568
4569 /* Cheat for killing far targets? */
4570 if (xenoStatusPointer->Target) {
4571 if (xenoStatusPointer->Target->SBdptr==NULL) {
4572 HandleWeaponImpact(&xenoStatusPointer->Target->DynPtr->Position,xenoStatusPointer->Target,AMMO_XENOBORG,&beta, multiple, NULL);
4573 }
4574 }
4575
4576 /* update beam SFX data */
4577 xenoStatusPointer->RightMainBeam.BeamIsOn = 1;
4578 xenoStatusPointer->RightMainBeam.SourcePosition = right_dum->World_Offset;
4579
4580 if (LOS_ObjectHitPtr) {
4581 xenoStatusPointer->RightMainBeam.TargetPosition = LOS_Point;
4582 } else {
4583 /* Must be hitting nothing... */
4584 xenoStatusPointer->RightMainBeam.TargetPosition=alpha;
4585 xenoStatusPointer->RightMainBeam.TargetPosition.vx+=(beta.vx>>3);
4586 xenoStatusPointer->RightMainBeam.TargetPosition.vy+=(beta.vy>>3);
4587 xenoStatusPointer->RightMainBeam.TargetPosition.vz+=(beta.vz>>3);
4588 }
4589
4590 if (LOS_ObjectHitPtr==Player)
4591 {
4592 xenoStatusPointer->RightMainBeam.BeamHasHitPlayer = 1;
4593 }
4594 else
4595 {
4596 xenoStatusPointer->RightMainBeam.BeamHasHitPlayer = 0;
4597 }
4598
4599 }
4600
4601 int Xeno_Activation_Test(STRATEGYBLOCK *sbPtr) {
4602
4603 XENO_STATUS_BLOCK *xenoStatusPointer;
4604 STRATEGYBLOCK *candidate;
4605 MATRIXCH WtoL;
4606 int a;
4607 MODULE *dmod;
4608
4609 dmod=ModuleFromPosition(&sbPtr->DynPtr->Position,playerPherModule);
4610
4611 LOCALASSERT(dmod);
4612
4613 LOCALASSERT(sbPtr);
4614 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
4615 LOCALASSERT(xenoStatusPointer);
4616
4617 WtoL=sbPtr->DynPtr->OrientMat;
4618 TransposeMatrixCH(&WtoL);
4619
4620 for (a=0; a<NumActiveStBlocks; a++) {
4621 candidate=ActiveStBlockList[a];
4622 if (candidate!=sbPtr) {
4623 if (candidate->DynPtr) {
4624 if (Xenoborg_TargetFilter(candidate)) {
4625 VECTORCH offset;
4626
4627 offset.vx=sbPtr->DynPtr->Position.vx-candidate->DynPtr->Position.vx;
4628 offset.vy=sbPtr->DynPtr->Position.vy-candidate->DynPtr->Position.vy;
4629 offset.vz=sbPtr->DynPtr->Position.vz-candidate->DynPtr->Position.vz;
4630
4631 RotateVector(&offset,&WtoL);
4632
4633 if (XenoActivation_FrustrumReject(&offset)) {
4634 /* Check visibility? */
4635 if (NPCCanSeeTarget(sbPtr,candidate,XENO_NEAR_VIEW_WIDTH)) {
4636 if (!NPC_IsDead(candidate)) {
4637 if ((IsModuleVisibleFromModule(dmod,candidate->containingModule))) {
4638 return(1);
4639 }
4640 }
4641 }
4642 }
4643 }
4644 }
4645 }
4646 }
4647 return(0);
4648 }
4649
4650 void Xeno_MaintainLasers(STRATEGYBLOCK *sbPtr) {
4651
4652 XENO_STATUS_BLOCK *xenoStatusPointer;
4653 SECTION_DATA *dum;
4654 VECTORCH alpha;
4655 VECTORCH beta;
4656 int a,uselaser;
4657
4658 LOCALASSERT(sbPtr);
4659 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
4660 LOCALASSERT(xenoStatusPointer);
4661
4662 xenoStatusPointer->HeadLaserOnTarget=0;
4663 xenoStatusPointer->LALaserOnTarget=0;
4664 xenoStatusPointer->RALaserOnTarget=0;
4665
4666 #if (FAR_XENO_ACTIVITY==0)
4667 if (xenoStatusPointer->IAmFar) {
4668 xenoStatusPointer->TargetingLaser[0].BeamIsOn=0;
4669 xenoStatusPointer->TargetingLaser[1].BeamIsOn=0;
4670 xenoStatusPointer->TargetingLaser[2].BeamIsOn=0;
4671 return;
4672 }
4673 #endif
4674
4675 for (a=0; a<3; a++) {
4676
4677 xenoStatusPointer->TargetingLaser[a].BeamIsOn=0;
4678 switch (a) {
4679 case 0:
4680 dum=GetThisSectionData(xenoStatusPointer->HModelController.section_data,"flash dummyZ");
4681 if (xenoStatusPointer->UseHeadLaser) {
4682 uselaser=1;
4683 } else {
4684 uselaser=0;
4685 }
4686 if (dum==NULL) {
4687 uselaser=0;
4688 }
4689 break;
4690 case 1:
4691 dum=GetThisSectionData(xenoStatusPointer->HModelController.section_data,"flash dummy C");
4692 if (xenoStatusPointer->UseLALaser) {
4693 uselaser=1;
4694 } else {
4695 uselaser=0;
4696 }
4697 if (dum==NULL) {
4698 uselaser=0;
4699 }
4700 break;
4701 case 2:
4702 dum=GetThisSectionData(xenoStatusPointer->HModelController.section_data,"flash dummy D");
4703 if (xenoStatusPointer->UseRALaser) {
4704 uselaser=1;
4705 } else {
4706 uselaser=0;
4707 }
4708 if (dum==NULL) {
4709 uselaser=0;
4710 }
4711 break;
4712 default:
4713 GLOBALASSERT(0);
4714 break;
4715 }
4716
4717 if (uselaser) {
4718
4719 alpha = dum->World_Offset;
4720
4721 beta.vx=dum->SecMat.mat31;
4722 beta.vy=dum->SecMat.mat32;
4723 beta.vz=dum->SecMat.mat33;
4724
4725 FindPolygonInLineOfSight(&beta,&alpha,0,sbPtr->SBdptr);
4726
4727 /* Now deal with LOS_ObjectHitPtr. */
4728 if (LOS_ObjectHitPtr==Player) {
4729 xenoStatusPointer->TargetingLaser[a].BeamHasHitPlayer=1;
4730 } else {
4731 xenoStatusPointer->TargetingLaser[a].BeamHasHitPlayer=0;
4732 }
4733
4734 xenoStatusPointer->TargetingLaser[a].SourcePosition=alpha;
4735 if (LOS_ObjectHitPtr) {
4736 xenoStatusPointer->TargetingLaser[a].TargetPosition=LOS_Point;
4737 } else {
4738 /* Must be hitting nothing... */
4739 xenoStatusPointer->TargetingLaser[a].TargetPosition=alpha;
4740 xenoStatusPointer->TargetingLaser[a].TargetPosition.vx+=(beta.vx>>3);
4741 xenoStatusPointer->TargetingLaser[a].TargetPosition.vy+=(beta.vy>>3);
4742 xenoStatusPointer->TargetingLaser[a].TargetPosition.vz+=(beta.vz>>3);
4743
4744 }
4745 xenoStatusPointer->TargetingLaser[a].BeamIsOn=1;
4746
4747 if (LOS_ObjectHitPtr) {
4748 if (LOS_ObjectHitPtr->ObStrategyBlock==xenoStatusPointer->Target) {
4749 switch (a) {
4750 case 0:
4751 xenoStatusPointer->HeadLaserOnTarget=1;
4752 break;
4753 case 1:
4754 xenoStatusPointer->LALaserOnTarget=1;
4755 break;
4756 case 2:
4757 xenoStatusPointer->RALaserOnTarget=1;
4758 break;
4759 default:
4760 GLOBALASSERT(0);
4761 break;
4762 }
4763 }
4764 }
4765 }
4766 }
4767
4768 }
4769
4770 void Xeno_SwitchLED(STRATEGYBLOCK *sbPtr,int state) {
4771
4772 XENO_STATUS_BLOCK *xenoStatusPointer;
4773 SECTION_DATA *led;
4774
4775 LOCALASSERT(sbPtr);
4776 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
4777 LOCALASSERT(xenoStatusPointer);
4778
4779 led=GetThisSectionData(xenoStatusPointer->HModelController.section_data,"led");
4780
4781 if (led) {
4782 if (led->tac_ptr) {
4783 led->tac_ptr->tac_sequence = state ;
4784 led->tac_ptr->tac_txah_s = GetTxAnimHeaderFromShape(led->tac_ptr, led->ShapeNum);
4785 }
4786 }
4787 }
4788
4789 void Xeno_Stomp(STRATEGYBLOCK *sbPtr) {
4790
4791 XENO_STATUS_BLOCK *xenoStatusPointer;
4792 SECTION_DATA *foot;
4793
4794 LOCALASSERT(sbPtr);
4795 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
4796 LOCALASSERT(xenoStatusPointer);
4797
4798 foot=NULL;
4799
4800 if (xenoStatusPointer->HModelController.keyframe_flags&4) {
4801 foot=GetThisSectionData(xenoStatusPointer->HModelController.section_data,"right foot");
4802 } else if (xenoStatusPointer->HModelController.keyframe_flags&8) {
4803 foot=GetThisSectionData(xenoStatusPointer->HModelController.section_data,"left foot");
4804 }
4805
4806 if (foot) {
4807 Sound_Play(SID_STOMP,"d",&foot->World_Offset);
4808 }
4809
4810 }
4811
4812 void Xeno_MaintainSounds(STRATEGYBLOCK *sbPtr) {
4813
4814 XENO_STATUS_BLOCK *xenoStatusPointer;
4815 SECTION_DATA *sec;
4816
4817 LOCALASSERT(sbPtr);
4818 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
4819 LOCALASSERT(xenoStatusPointer);
4820
4821 /* First, the two big system sounds. */
4822 if (xenoStatusPointer->soundHandle1!=SOUND_NOACTIVEINDEX) {
4823 Sound_Update3d(xenoStatusPointer->soundHandle1,&sbPtr->DynPtr->Position);
4824 }
4825 if (xenoStatusPointer->soundHandle2!=SOUND_NOACTIVEINDEX) {
4826 Sound_Update3d(xenoStatusPointer->soundHandle2,&sbPtr->DynPtr->Position);
4827 }
4828
4829 /* Now, all the lesser sounds: */
4830 /* Head. */
4831 sec=GetThisSectionData(xenoStatusPointer->HModelController.section_data,"head");
4832 if (sec==NULL) {
4833 /* No sound. */
4834 if (xenoStatusPointer->head_whirr!=SOUND_NOACTIVEINDEX) {
4835 Sound_Stop(xenoStatusPointer->head_whirr);
4836 }
4837 } else {
4838 if (xenoStatusPointer->head_moving==0) {
4839 /* Stationary. */
4840 if (xenoStatusPointer->head_whirr!=SOUND_NOACTIVEINDEX) {
4841 Sound_Stop(xenoStatusPointer->head_whirr);
4842 Sound_Play(SID_ARMEND,"d",&sec->World_Offset);
4843 }
4844 } else {
4845 /* Moving! */
4846 if (xenoStatusPointer->head_whirr==SOUND_NOACTIVEINDEX) {
4847 Sound_Play(SID_ARMSTART,"d",&sec->World_Offset);
4848 Sound_Play(SID_ARMMID,"del",&sec->World_Offset,&xenoStatusPointer->head_whirr);
4849 } else {
4850 Sound_Update3d(xenoStatusPointer->head_whirr,&sec->World_Offset);
4851 }
4852 }
4853 }
4854 /* Left Arm. */
4855 sec=GetThisSectionData(xenoStatusPointer->HModelController.section_data,"left bicep");
4856 if (sec==NULL) {
4857 /* No sound. */
4858 if (xenoStatusPointer->left_arm_whirr!=SOUND_NOACTIVEINDEX) {
4859 Sound_Stop(xenoStatusPointer->left_arm_whirr);
4860 }
4861 } else {
4862 if (xenoStatusPointer->la_moving==0) {
4863 /* Stationary. */
4864 if (xenoStatusPointer->left_arm_whirr!=SOUND_NOACTIVEINDEX) {
4865 Sound_Stop(xenoStatusPointer->left_arm_whirr);
4866 Sound_Play(SID_ARMEND,"d",&sec->World_Offset);
4867 }
4868 } else {
4869 /* Moving! */
4870 if (xenoStatusPointer->left_arm_whirr==SOUND_NOACTIVEINDEX) {
4871 Sound_Play(SID_ARMSTART,"d",&sec->World_Offset);
4872 Sound_Play(SID_ARMMID,"del",&sec->World_Offset,&xenoStatusPointer->left_arm_whirr);
4873 } else {
4874 Sound_Update3d(xenoStatusPointer->left_arm_whirr,&sec->World_Offset);
4875 }
4876 }
4877 }
4878 /* Right Arm. */
4879 sec=GetThisSectionData(xenoStatusPointer->HModelController.section_data,"right bicep");
4880 if (sec==NULL) {
4881 /* No sound. */
4882 if (xenoStatusPointer->right_arm_whirr!=SOUND_NOACTIVEINDEX) {
4883 Sound_Stop(xenoStatusPointer->right_arm_whirr);
4884 }
4885 } else {
4886 if (xenoStatusPointer->ra_moving==0) {
4887 /* Stationary. */
4888 if (xenoStatusPointer->right_arm_whirr!=SOUND_NOACTIVEINDEX) {
4889 Sound_Stop(xenoStatusPointer->right_arm_whirr);
4890 Sound_Play(SID_ARMEND,"d",&sec->World_Offset);
4891 }
4892 } else {
4893 /* Moving! */
4894 if (xenoStatusPointer->right_arm_whirr==SOUND_NOACTIVEINDEX) {
4895 Sound_Play(SID_ARMSTART,"d",&sec->World_Offset);
4896 Sound_Play(SID_ARMMID,"del",&sec->World_Offset,&xenoStatusPointer->right_arm_whirr);
4897 } else {
4898 Sound_Update3d(xenoStatusPointer->right_arm_whirr,&sec->World_Offset);
4899 }
4900 }
4901 }
4902 /* Torso Twist. */
4903 sec=GetThisSectionData(xenoStatusPointer->HModelController.section_data,"chest");
4904 if (sec==NULL) {
4905 /* No sound. */
4906 if (xenoStatusPointer->torso_whirr!=SOUND_NOACTIVEINDEX) {
4907 Sound_Stop(xenoStatusPointer->torso_whirr);
4908 }
4909 } else {
4910 if (xenoStatusPointer->torso_moving==0) {
4911 /* Stationary. */
4912 if (xenoStatusPointer->torso_whirr!=SOUND_NOACTIVEINDEX) {
4913 Sound_Stop(xenoStatusPointer->torso_whirr);
4914 Sound_Play(SID_ARMEND,"d",&sec->World_Offset);
4915 }
4916 } else {
4917 /* Moving! */
4918 if (xenoStatusPointer->torso_whirr==SOUND_NOACTIVEINDEX) {
4919 Sound_Play(SID_ARMSTART,"d",&sec->World_Offset);
4920 Sound_Play(SID_ARMMID,"del",&sec->World_Offset,&xenoStatusPointer->torso_whirr);
4921 } else {
4922 Sound_Update3d(xenoStatusPointer->torso_whirr,&sec->World_Offset);
4923 }
4924 }
4925 }
4926 }
4927
4928 void XenoborgHandleMovingAnimation(STRATEGYBLOCK *sbPtr) {
4929
4930 XENO_STATUS_BLOCK *xenoStatusPointer;
4931 VECTORCH offset;
4932 int speed,animfactor;
4933
4934 LOCALASSERT(sbPtr);
4935 xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
4936 LOCALASSERT(xenoStatusPointer);
4937
4938 offset.vx=sbPtr->DynPtr->Position.vx-sbPtr->DynPtr->PrevPosition.vx;
4939 offset.vy=sbPtr->DynPtr->Position.vy-sbPtr->DynPtr->PrevPosition.vy;
4940 offset.vz=sbPtr->DynPtr->Position.vz-sbPtr->DynPtr->PrevPosition.vz;
4941
4942 /* ...compute speed factor... */
4943 speed=Magnitude(&offset);
4944 if (speed<(MUL_FIXED(NormalFrameTime,50))) {
4945 /* Not moving much, are we? Be stationary! */
4946 if (ShowXenoStats) {
4947 PrintDebuggingText("Forced stationary animation!\n");
4948 }
4949 EnforceXenoborgShapeAnimSequence_Core(sbPtr,HMSQT_Xenoborg,XBSS_Powered_Up_Standard,ONE_FIXED,(ONE_FIXED>>2));
4950 return;
4951 }
4952 speed=DIV_FIXED(speed,NormalFrameTime);
4953
4954 if (speed==0) {
4955 animfactor=ONE_FIXED;
4956 } else {
4957 animfactor=DIV_FIXED(625,speed); // Was 512! Difference to correct for rounding down...
4958 }
4959 GLOBALASSERT(animfactor>0);
4960 if (ShowXenoStats) {
4961 PrintDebuggingText("Anim Factor %d, Tweening %d\n",animfactor,xenoStatusPointer->HModelController.Tweening);
4962 }
4963
4964 /* Start animation. */
4965 EnforceXenoborgShapeAnimSequence_Core(sbPtr,HMSQT_Xenoborg,XBSS_Walking,XENO_WALKING_ANIM_SPEED,(ONE_FIXED>>2));
4966
4967 if (xenoStatusPointer->HModelController.Tweening==0) {
4968 HModel_SetToolsRelativeSpeed(&xenoStatusPointer->HModelController,animfactor);
4969 }
4970
4971 }
4972
4973
4974 /*--------------------**
4975 ** Loading and Saving **
4976 **--------------------*/
4977 #include "savegame.h"
4978
4979 typedef struct xenoborg_save_block
4980 {
4981 SAVE_BLOCK_STRATEGY_HEADER header;
4982
4983 //behaviour block stuff
4984 signed int health;
4985 XENO_BHSTATE behaviourState;
4986 XENO_BHSTATE lastState;
4987 int stateTimer;
4988 NPC_WANDERDATA wanderData;
4989 NPC_OBSTRUCTIONREPORT obstruction;
4990 VECTORCH my_spot_therin;
4991 VECTORCH my_orientdir_therin;
4992 int module_range;
4993 int UpTime;
4994 int GibbFactor;
4995 int Wounds;
4996
4997
4998
4999 VECTORCH targetTrackPos;
5000
5001 int Head_Pan;
5002 int Head_Tilt;
5003 int Left_Arm_Pan;
5004 int Left_Arm_Tilt;
5005 int Right_Arm_Pan;
5006 int Right_Arm_Tilt;
5007 int Torso_Twist;
5008
5009 int Old_Head_Pan;
5010 int Old_Head_Tilt;
5011 int Old_Left_Arm_Pan;
5012 int Old_Left_Arm_Tilt;
5013 int Old_Right_Arm_Pan;
5014 int Old_Right_Arm_Tilt;
5015 int Old_Torso_Twist;
5016
5017 LASER_BEAM_DESC LeftMainBeam;
5018 LASER_BEAM_DESC RightMainBeam;
5019 LASER_BEAM_DESC TargetingLaser[3];
5020
5021 unsigned int headpandir :1;
5022 unsigned int headtiltdir :1;
5023 unsigned int leftarmpandir :1;
5024 unsigned int leftarmtiltdir :1;
5025 unsigned int rightarmpandir :1;
5026 unsigned int rightarmtiltdir :1;
5027 unsigned int torsotwistdir :1;
5028
5029 unsigned int headLock :1;
5030 unsigned int leftArmLock :1;
5031 unsigned int rightArmLock :1;
5032 unsigned int targetSightTest :1;
5033 unsigned int IAmFar :1;
5034 unsigned int ShotThisFrame :1;
5035
5036 unsigned int FiringLeft :1;
5037 unsigned int FiringRight :1;
5038
5039 unsigned int UseHeadLaser :1;
5040 unsigned int UseLALaser :1;
5041 unsigned int UseRALaser :1;
5042
5043 unsigned int HeadLaserOnTarget :1;
5044 unsigned int LALaserOnTarget :1;
5045 unsigned int RALaserOnTarget :1;
5046
5047 unsigned int head_moving :1;
5048 unsigned int la_moving :1;
5049 unsigned int ra_moving :1;
5050 unsigned int torso_moving :1;
5051
5052 int incidentFlag;
5053 int incidentTimer;
5054
5055 int head_whirr;
5056 int left_arm_whirr;
5057 int right_arm_whirr;
5058 int torso_whirr;
5059
5060
5061 //annoying pointer related things
5062 int my_module_index;
5063
5064 char Target_SBname[SB_NAME_LENGTH];
5065
5066 //strategyblock stuff
5067 int integrity;
5068 DAMAGEBLOCK SBDamageBlock;
5069 DYNAMICSBLOCK dynamics;
5070 }XENOBORG_SAVE_BLOCK;
5071
5072
5073
5074
5075 //defines for load/save macros
5076 #define SAVELOAD_BLOCK block
5077 #define SAVELOAD_BEHAV xenoStatusPointer
5078
5079
5080 void LoadStrategy_Xenoborg(SAVE_BLOCK_STRATEGY_HEADER* header)
5081 {
5082 int i;
5083 STRATEGYBLOCK* sbPtr;
5084 XENO_STATUS_BLOCK* xenoStatusPointer;
5085 XENOBORG_SAVE_BLOCK* block = (XENOBORG_SAVE_BLOCK*) header;
5086
5087 //check the size of the save block
5088 if(header->size!=sizeof(*block)) return;
5089
5090 //find the existing strategy block
5091 sbPtr = FindSBWithName(header->SBname);
5092 if(!sbPtr) return;
5093
5094 //make sure the strategy found is of the right type
5095 if(sbPtr->I_SBtype != I_BehaviourXenoborg) return;
5096
5097 xenoStatusPointer =(XENO_STATUS_BLOCK*) sbPtr->SBdataptr;
5098
5099
5100 //start copying stuff
5101 COPYELEMENT_LOAD(health)
5102 COPYELEMENT_LOAD(behaviourState)
5103 COPYELEMENT_LOAD(lastState)
5104 COPYELEMENT_LOAD(stateTimer)
5105 COPYELEMENT_LOAD(wanderData)
5106 COPYELEMENT_LOAD(obstruction)
5107 COPYELEMENT_LOAD(my_spot_therin)
5108 COPYELEMENT_LOAD(my_orientdir_therin)
5109 COPYELEMENT_LOAD(module_range)
5110 COPYELEMENT_LOAD(UpTime)
5111 COPYELEMENT_LOAD(GibbFactor)
5112 COPYELEMENT_LOAD(Wounds)
5113 COPYELEMENT_LOAD(targetTrackPos)
5114 COPYELEMENT_LOAD(Head_Pan)
5115 COPYELEMENT_LOAD(Head_Tilt)
5116 COPYELEMENT_LOAD(Left_Arm_Pan)
5117 COPYELEMENT_LOAD(Left_Arm_Tilt)
5118 COPYELEMENT_LOAD(Right_Arm_Pan)
5119 COPYELEMENT_LOAD(Right_Arm_Tilt)
5120 COPYELEMENT_LOAD(Torso_Twist)
5121 COPYELEMENT_LOAD(Old_Head_Pan)
5122 COPYELEMENT_LOAD(Old_Head_Tilt)
5123 COPYELEMENT_LOAD(Old_Left_Arm_Pan)
5124 COPYELEMENT_LOAD(Old_Left_Arm_Tilt)
5125 COPYELEMENT_LOAD(Old_Right_Arm_Pan)
5126 COPYELEMENT_LOAD(Old_Right_Arm_Tilt)
5127 COPYELEMENT_LOAD(Old_Torso_Twist)
5128 COPYELEMENT_LOAD(LeftMainBeam)
5129 COPYELEMENT_LOAD(RightMainBeam)
5130
5131
5132 COPYELEMENT_LOAD(headpandir)
5133 COPYELEMENT_LOAD(headtiltdir)
5134 COPYELEMENT_LOAD(leftarmpandir)
5135 COPYELEMENT_LOAD(leftarmtiltdir)
5136 COPYELEMENT_LOAD(rightarmpandir)
5137 COPYELEMENT_LOAD(rightarmtiltdir)
5138 COPYELEMENT_LOAD(torsotwistdir)
5139
5140 COPYELEMENT_LOAD(headLock)
5141 COPYELEMENT_LOAD(leftArmLock)
5142 COPYELEMENT_LOAD(rightArmLock)
5143 COPYELEMENT_LOAD(targetSightTest)
5144 COPYELEMENT_LOAD(IAmFar)
5145 COPYELEMENT_LOAD(ShotThisFrame)
5146
5147 COPYELEMENT_LOAD(FiringLeft)
5148 COPYELEMENT_LOAD(FiringRight)
5149
5150 COPYELEMENT_LOAD(UseHeadLaser)
5151 COPYELEMENT_LOAD(UseLALaser)
5152 COPYELEMENT_LOAD(UseRALaser)
5153
5154 COPYELEMENT_LOAD(HeadLaserOnTarget)
5155 COPYELEMENT_LOAD(LALaserOnTarget)
5156 COPYELEMENT_LOAD(RALaserOnTarget)
5157
5158 COPYELEMENT_LOAD(head_moving)
5159 COPYELEMENT_LOAD(la_moving)
5160 COPYELEMENT_LOAD(ra_moving)
5161 COPYELEMENT_LOAD(torso_moving)
5162
5163 COPYELEMENT_LOAD(incidentFlag)
5164 COPYELEMENT_LOAD(incidentTimer)
5165
5166 COPYELEMENT_LOAD(head_whirr)
5167 COPYELEMENT_LOAD(left_arm_whirr)
5168 COPYELEMENT_LOAD(right_arm_whirr)
5169 COPYELEMENT_LOAD(torso_whirr)
5170
5171 for(i=0;i<3;i++)
5172 {
5173 COPYELEMENT_LOAD(TargetingLaser[i])
5174 }
5175
5176 //load ai module pointers
5177 xenoStatusPointer->my_module = GetPointerFromAIModuleIndex(block->my_module_index);
5178
5179 //load target
5180 COPY_NAME(xenoStatusPointer->Target_SBname,block->Target_SBname);
5181 xenoStatusPointer->Target = FindSBWithName(xenoStatusPointer->Target_SBname);
5182
5183 //copy strategy block stuff
5184 *sbPtr->DynPtr = block->dynamics;
5185 sbPtr->integrity = block->integrity;
5186 sbPtr->SBDamageBlock = block->SBDamageBlock;
5187
5188 //load hierarchy
5189 {
5190 SAVE_BLOCK_HEADER* hier_header = GetNextBlockIfOfType(SaveBlock_Hierarchy);
5191 if(hier_header)
5192 {
5193 LoadHierarchy(hier_header,&xenoStatusPointer->HModelController);
5194 }
5195 }
5196
5197
5198 //finally get the delta controller pointers
5199 VerifyDeltaControllers(sbPtr);
5200
5201 Load_SoundState(&xenoStatusPointer->soundHandle1);
5202 Load_SoundState(&xenoStatusPointer->soundHandle2);
5203 }
5204
5205
5206 void SaveStrategy_Xenoborg(STRATEGYBLOCK* sbPtr)
5207 {
5208 int i;
5209 XENO_STATUS_BLOCK* xenoStatusPointer;
5210 XENOBORG_SAVE_BLOCK* block;
5211
5212 GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
5213 xenoStatusPointer = (XENO_STATUS_BLOCK*) sbPtr->SBdataptr;
5214
5215 //start copying stuff
5216
5217 COPYELEMENT_SAVE(health)
5218 COPYELEMENT_SAVE(behaviourState)
5219 COPYELEMENT_SAVE(lastState)
5220 COPYELEMENT_SAVE(stateTimer)
5221 COPYELEMENT_SAVE(wanderData)
5222 COPYELEMENT_SAVE(obstruction)
5223 COPYELEMENT_SAVE(my_spot_therin)
5224 COPYELEMENT_SAVE(my_orientdir_therin)
5225 COPYELEMENT_SAVE(module_range)
5226 COPYELEMENT_SAVE(UpTime)
5227 COPYELEMENT_SAVE(GibbFactor)
5228 COPYELEMENT_SAVE(Wounds)
5229 COPYELEMENT_SAVE(targetTrackPos)
5230 COPYELEMENT_SAVE(Head_Pan)
5231 COPYELEMENT_SAVE(Head_Tilt)
5232 COPYELEMENT_SAVE(Left_Arm_Pan)
5233 COPYELEMENT_SAVE(Left_Arm_Tilt)
5234 COPYELEMENT_SAVE(Right_Arm_Pan)
5235 COPYELEMENT_SAVE(Right_Arm_Tilt)
5236 COPYELEMENT_SAVE(Torso_Twist)
5237 COPYELEMENT_SAVE(Old_Head_Pan)
5238 COPYELEMENT_SAVE(Old_Head_Tilt)
5239 COPYELEMENT_SAVE(Old_Left_Arm_Pan)
5240 COPYELEMENT_SAVE(Old_Left_Arm_Tilt)
5241 COPYELEMENT_SAVE(Old_Right_Arm_Pan)
5242 COPYELEMENT_SAVE(Old_Right_Arm_Tilt)
5243 COPYELEMENT_SAVE(Old_Torso_Twist)
5244 COPYELEMENT_SAVE(LeftMainBeam)
5245 COPYELEMENT_SAVE(RightMainBeam)
5246
5247
5248 COPYELEMENT_SAVE(headpandir)
5249 COPYELEMENT_SAVE(headtiltdir)
5250 COPYELEMENT_SAVE(leftarmpandir)
5251 COPYELEMENT_SAVE(leftarmtiltdir)
5252 COPYELEMENT_SAVE(rightarmpandir)
5253 COPYELEMENT_SAVE(rightarmtiltdir)
5254 COPYELEMENT_SAVE(torsotwistdir)
5255
5256 COPYELEMENT_SAVE(headLock)
5257 COPYELEMENT_SAVE(leftArmLock)
5258 COPYELEMENT_SAVE(rightArmLock)
5259 COPYELEMENT_SAVE(targetSightTest)
5260 COPYELEMENT_SAVE(IAmFar)
5261 COPYELEMENT_SAVE(ShotThisFrame)
5262
5263 COPYELEMENT_SAVE(FiringLeft)
5264 COPYELEMENT_SAVE(FiringRight)
5265
5266 COPYELEMENT_SAVE(UseHeadLaser)
5267 COPYELEMENT_SAVE(UseLALaser)
5268 COPYELEMENT_SAVE(UseRALaser)
5269
5270 COPYELEMENT_SAVE(HeadLaserOnTarget)
5271 COPYELEMENT_SAVE(LALaserOnTarget)
5272 COPYELEMENT_SAVE(RALaserOnTarget)
5273
5274 COPYELEMENT_SAVE(head_moving)
5275 COPYELEMENT_SAVE(la_moving)
5276 COPYELEMENT_SAVE(ra_moving)
5277 COPYELEMENT_SAVE(torso_moving)
5278
5279 COPYELEMENT_SAVE(incidentFlag)
5280 COPYELEMENT_SAVE(incidentTimer)
5281
5282 COPYELEMENT_SAVE(head_whirr)
5283 COPYELEMENT_SAVE(left_arm_whirr)
5284 COPYELEMENT_SAVE(right_arm_whirr)
5285 COPYELEMENT_SAVE(torso_whirr)
5286
5287 for(i=0;i<3;i++)
5288 {
5289 COPYELEMENT_SAVE(TargetingLaser[i])
5290 }
5291
5292 //load ai module pointers
5293 block->my_module_index = GetIndexFromAIModulePointer(xenoStatusPointer->my_module);
5294
5295 //save target
5296 COPY_NAME(block->Target_SBname,xenoStatusPointer->Target_SBname);
5297
5298 //save strategy block stuff
5299 block->dynamics = *sbPtr->DynPtr;
5300 block->dynamics.CollisionReportPtr=0;
5301
5302 block->integrity = sbPtr->integrity;
5303 block->SBDamageBlock = sbPtr->SBDamageBlock;
5304
5305 //save the hierarchy
5306 SaveHierarchy(&xenoStatusPointer->HModelController);
5307
5308 Save_SoundState(&xenoStatusPointer->soundHandle1);
5309 Save_SoundState(&xenoStatusPointer->soundHandle2);
5310 }
5311