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