4b825dc642cb6eb9a060e54bf8d69288fbee4904ebd360ec63ec976c05699f3180e866b3f69e5472
 
 
1
#include "npc_common.h"
 
 
2
#include "npc_sentrygun.h"
 
 
3
#include "sequnces.h"
 
 
4
#include "lighting.h"
 
 
5
#include "particle.h"
 
 
6
#include <stdlib.h>
 
 
7
 
 
 
8
#define SENTRYGUN_DRAMA 0
 
 
9
 
 
 
10
int SentrygunSpread = 5;
 
 
11
int sentrygun_infinity_ammo = 0;
 
 
12
int sentrygun_reload_ammo = 0;
 
 
13
 
 
 
14
SOUND3DDATA SentryFire_SoundData =
 
 
15
{
 
 
16
    {0,0,0,},
 
 
17
    {0,0,0,},
 
 
18
    20000,
 
 
19
    40000,
 
 
20
};
 
 
21
 
 
 
22
SOUND3DDATA SentryWhirr_SoundData =
 
 
23
{
 
 
24
    {0,0,0,},
 
 
25
    {0,0,0,},
 
 
26
    0,
 
 
27
    32000,
 
 
28
};
 
 
29
 
 
 
30
static int make_new_sentrygun(STRATEGYBLOCK *sbPtr, int start_ammo, AG_STATE start_state)
 
 
31
{
 
 
32
    sbPtr->dataptr = malloc(sizeof(AUTOGUN_STATUS_BLOCK));
 
 
33
    sbPtr->maintainVisibility = 1;
 
 
34
    sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_DEFAULT);
 
 
35
 
 
 
36
    if((NULL == sbPtr->dataptr) || (NULL == sbPtr->DynPtr))
 
 
37
    {
 
 
38
        RemoveBehaviourStrategy(sbPtr);
 
 
39
        return 0;
 
 
40
    }
 
 
41
 
 
 
42
    sbPtr->DynPtr->Mass = 400;
 
 
43
    sbPtr->DynPtr->CanClimbStairs = 0;
 
 
44
    AUTOGUN_STATUS_BLOCK *new_sentrygun = sbPtr->dataptr;
 
 
45
    new_sentrygun->behaviourState = start_state;
 
 
46
 
 
 
47
    new_sentrygun->HModelController.Deltas = NULL;
 
 
48
    new_sentrygun->HModelController.Root_Section = NULL;
 
 
49
    new_sentrygun->HModelController.section_data = NULL;
 
 
50
    new_sentrygun->gun_pan = NULL;
 
 
51
    new_sentrygun->gun_tilt = NULL;
 
 
52
    new_sentrygun->Target = NULL;
 
 
53
    COPY_NAME(new_sentrygun->Target_SBname, Null_Name);
 
 
54
 
 
 
55
    new_sentrygun->targetTrackPos.vx = 0;
 
 
56
    new_sentrygun->targetTrackPos.vy = 0;
 
 
57
    new_sentrygun->targetTrackPos.vz = 0;
 
 
58
 
 
 
59
    new_sentrygun->Gun_Pan = 0;
 
 
60
    new_sentrygun->Gun_Tilt = 0;
 
 
61
    new_sentrygun->GunFlash = NULL;
 
 
62
 
 
 
63
    new_sentrygun->incidentFlag = 0;
 
 
64
    new_sentrygun->incidentTimer = 0;
 
 
65
 
 
 
66
    new_sentrygun->ammo = start_ammo;
 
 
67
    new_sentrygun->roundsFired = 0;
 
 
68
    new_sentrygun->volleyFired = 0;
 
 
69
 
 
 
70
      new_sentrygun->soundHandle = SOUND_NOACTIVEINDEX;
 
 
71
      new_sentrygun->soundHandle2 = SOUND_NOACTIVEINDEX;
 
 
72
    new_sentrygun->Firing = 0;
 
 
73
    new_sentrygun->WhirrSoundOn = 0;
 
 
74
    new_sentrygun->Drama = 0;
 
 
75
      new_sentrygun->createdByPlayer = 0;
 
 
76
    new_sentrygun->gunpandir = 0;
 
 
77
    new_sentrygun->guntiltdir = 0;
 
 
78
    new_sentrygun->OnTarget = 0;
 
 
79
    new_sentrygun->OnTarget_LastFrame = 0;
 
 
80
    new_sentrygun->death_target_sbptr = NULL;
 
 
81
    new_sentrygun->death_target_request = 0;
 
 
82
 
 
 
83
    {
 
 
84
        int i = 0;
 
 
85
        for(i=0; i < SB_NAME_LENGTH; i++)
 
 
86
            new_sentrygun->death_target_ID[i] = 0;
 
 
87
    }
 
 
88
 
 
 
89
    {
 
 
90
        const NPC_DATA *NpcData = &NpcDataList[I_NPC_SentryGun];
 
 
91
        sbPtr->DamageBlock = NpcData->StartingStats;
 
 
92
        sbPtr->DamageBlock.Health = NpcData->StartingStats.Health << ONE_FIXED_SHIFT;
 
 
93
        sbPtr->DamageBlock.Armour = NpcData->StartingStats.Armour << ONE_FIXED_SHIFT;
 
 
94
    }
 
 
95
 
 
 
96
    SECTION *root_section = GetNamedHierarchyFromLibrary("sentry", "gun");
 
 
97
 
 
 
98
    if (!root_section)
 
 
99
    {
 
 
100
        RemoveBehaviourStrategy(sbPtr);
 
 
101
        return 0;
 
 
102
    }
 
 
103
 
 
 
104
    Create_HModel(&new_sentrygun->HModelController,root_section);
 
 
105
    InitHModelSequence(&new_sentrygun->HModelController, HMSQT_Xenoborg, XBSS_Powered_Up_Standard, ONE_FIXED);
 
 
106
 
 
 
107
    {
 
 
108
        DELTA_CONTROLLER *delta = Add_Delta_Sequence(&new_sentrygun->HModelController, "GunTilt", (int)HMSQT_Xenoborg,
(int)XBSS_Head_Vertical_Delta, 0);
 
 
109
        assert(delta);
 
 
110
        delta->timer = 32767;
 
 
111
        delta->Active = 0;
 
 
112
 
 
 
113
        delta = Add_Delta_Sequence(&new_sentrygun->HModelController, "GunPan", (int)HMSQT_Xenoborg, (int)XBSS_Head_Horizontal_Delta, 0);
 
 
114
        assert(delta);
 
 
115
        delta->timer = 32767;
 
 
116
        delta->Active = 0;
 
 
117
    }
 
 
118
 
 
 
119
return 1;
 
 
120
}
 
 
121
 
 
 
122
void MakeSentrygunNear(STRATEGYBLOCK *sbPtr)
 
 
123
{
 
 
124
    DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
125
    AUTOGUN_STATUS_BLOCK *agunStatusPointer = (AUTOGUN_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
126
 
 
 
127
    DISPLAYBLOCK *dPtr = CreateActiveObject();
 
 
128
 
 
 
129
    if(dPtr == NULL)
 
 
130
        return; /* if cannot create displayblock, leave far */
 
 
131
 
 
 
132
    sbPtr->DisplayBlock = dPtr;
 
 
133
    dPtr->ObStrategyBlock = sbPtr;
 
 
134
 
 
 
135
    /* need to initialise positional information in the new display block */ 
 
 
136
    dPtr->ObWorld = dynPtr->Position;
 
 
137
    dPtr->ObEuler = dynPtr->OrientEuler;
 
 
138
    dPtr->ObMat = dynPtr->OrientMat;
 
 
139
 
 
 
140
       /* state and sequence init */
 
 
141
    dPtr->HModelControlBlock = &agunStatusPointer->HModelController;
 
 
142
 
 
 
143
    ProveHModel(dPtr->HModelControlBlock, dPtr);
 
 
144
}
 
 
145
 
 
 
146
void CreateSentrygun(VECTORCH *Position)
 
 
147
{
 
 
148
    STRATEGYBLOCK* sbPtr = CreateActiveStrategyBlock(I_BehaviourAutoGun);
 
 
149
 
 
 
150
    if((NULL != sbPtr) && make_new_sentrygun(sbPtr, 500, I_tracking))
 
 
151
    {
 
 
152
        AUTOGUN_STATUS_BLOCK *agunStatus = (AUTOGUN_STATUS_BLOCK *)sbPtr->dataptr;
 
 
153
        agunStatus->createdByPlayer = 1;
 
 
154
 
 
 
155
        DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
156
        dynPtr->PrevPosition = dynPtr->Position = *Position;
 
 
157
        dynPtr->OrientEuler.EulerY = PlayerStatus.DisplayBlock->ObEuler.EulerY;
 
 
158
        CreateEulerMatrix(&dynPtr->OrientEuler, &dynPtr->OrientMat);
 
 
159
        TransposeMatrixCH(&dynPtr->OrientMat);
 
 
160
        AssignNewSBName(sbPtr);
 
 
161
        //if(AvP.Network != I_No_Network) AddNetGameObjectID(sbPtr);
 
 
162
        sbPtr->containingModule = ModuleFromPosition(&sbPtr->DynPtr->Position, NULL);
 
 
163
 
 
 
164
        if(!sbPtr->containingModule)
 
 
165
            RemoveBehaviourStrategy(sbPtr);
 
 
166
    }
 
 
167
}
 
 
168
 
 
 
169
void CastSentrygunBot() 
 
 
170
{
 
 
171
    #define BOTRANGE 2000
 
 
172
 
 
 
173
    VECTORCH position;
 
 
174
 
 
 
175
    position = PlayerStatus.sbptr->DynPtr->Position;
 
 
176
    position.vx += MUL_FIXED(PlayerStatus.sbptr->DynPtr->OrientMat.mat31, BOTRANGE);
 
 
177
    position.vy += MUL_FIXED(PlayerStatus.sbptr->DynPtr->OrientMat.mat32, BOTRANGE);
 
 
178
    position.vz += MUL_FIXED(PlayerStatus.sbptr->DynPtr->OrientMat.mat33, BOTRANGE);
 
 
179
 
 
 
180
    CreateSentrygun(&position);
 
 
181
}
 
 
182
 
 
 
183
void AutoGunBehaveInit(void *bhdata, STRATEGYBLOCK *sbPtr)
 
 
184
{
 
 
185
    int i;
 
 
186
 
 
 
187
    AUTOGUN_TOOLS_TEMPLATE *toolsData = (AUTOGUN_TOOLS_TEMPLATE *)bhdata; 
 
 
188
 
 
 
189
    for(i=0; i < SB_NAME_LENGTH; i++)
 
 
190
        sbPtr->SBname[i] = toolsData->nameID[i];
 
 
191
 
 
 
192
    if(make_new_sentrygun(sbPtr, toolsData->ammo, (toolsData->startInactive ? I_inactive : I_tracking)))
 
 
193
    {
 
 
194
        AUTOGUN_STATUS_BLOCK *agunStatus = (AUTOGUN_STATUS_BLOCK *)sbPtr->dataptr;
 
 
195
        agunStatus->death_target_request = toolsData->death_target_request;
 
 
196
        DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
197
        dynPtr->PrevPosition = dynPtr->Position = toolsData->position;
 
 
198
        dynPtr->OrientEuler = toolsData->orientation;
 
 
199
        CreateEulerMatrix(&dynPtr->OrientEuler, &dynPtr->OrientMat);
 
 
200
        TransposeMatrixCH(&dynPtr->OrientMat);
 
 
201
        sbPtr->containingModule = ModuleFromPosition(&sbPtr->DynPtr->Position, NULL);
 
 
202
 
 
 
203
        if(!sbPtr->containingModule)
 
 
204
            RemoveBehaviourStrategy(sbPtr);
 
 
205
    }
 
 
206
}
 
 
207
 
 
 
208
void MakeSentrygunFar(STRATEGYBLOCK *sbPtr)
 
 
209
{
 
 
210
    AUTOGUN_STATUS_BLOCK *agunStatusPointer = (AUTOGUN_STATUS_BLOCK *)(sbPtr->dataptr);        
 
 
211
    assert(agunStatusPointer);
 
 
212
 
 
 
213
    DestroyActiveObject(&sbPtr->DisplayBlock);
 
 
214
    DestroyActiveObject(&agunStatusPointer->GunFlash);
 
 
215
 
 
 
216
    /* agun data block init */
 
 
217
    if(agunStatusPointer->behaviourState != I_disabled)
 
 
218
           agunStatusPointer->stateTimer = 0;
 
 
219
 
 
 
220
    /* zero linear velocity in dynamics block */
 
 
221
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;    
 
 
222
}
 
 
223
 
 
 
224
static void Autogun_VerifyDeltaControllers(STRATEGYBLOCK *sbPtr)
 
 
225
{
 
 
226
    assert(sbPtr);
 
 
227
    AUTOGUN_STATUS_BLOCK *agunStatusPointer = (AUTOGUN_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
228
    assert(agunStatusPointer);                      
 
 
229
 
 
 
230
    /* Nothing has deltas like a xenoborg does. */
 
 
231
    /* But sentryguns try their best. */
 
 
232
 
 
 
233
    agunStatusPointer->gun_pan = Get_Delta_Sequence(&agunStatusPointer->HModelController,"GunPan");
 
 
234
    assert(agunStatusPointer->gun_pan);
 
 
235
 
 
 
236
    agunStatusPointer->gun_tilt = Get_Delta_Sequence(&agunStatusPointer->HModelController,"GunTilt");
 
 
237
    assert(agunStatusPointer->gun_tilt);
 
 
238
}
 
 
239
 
 
 
240
static void AGun_ComputeDeltaValues(STRATEGYBLOCK *sbPtr)
 
 
241
{
 
 
242
    assert(sbPtr);
 
 
243
    AUTOGUN_STATUS_BLOCK *agunStatusPointer = (AUTOGUN_STATUS_BLOCK *)(sbPtr->dataptr);        
 
 
244
    assert(agunStatusPointer);
 
 
245
 
 
 
246
    /* Interpret all status block values, and apply to deltas. */
 
 
247
    /* Gun Pan first. */
 
 
248
 
 
 
249
    int angle = agunStatusPointer->Gun_Pan >> 4;
 
 
250
 
 
 
251
    if (angle >= 3072)
 
 
252
        angle -= 4096;
 
 
253
 
 
 
254
    if (angle >= 2048)
 
 
255
        angle -= 4096;
 
 
256
 
 
 
257
    assert(agunStatusPointer->gun_pan);
 
 
258
 
 
 
259
    /* Now, we have an angle. */
 
 
260
 
 
 
261
    if (angle > SGUN_PAN_GIMBALL)
 
 
262
    {
 
 
263
        angle = SGUN_PAN_GIMBALL;
 
 
264
    }
 
 
265
    else if (angle < -SGUN_PAN_GIMBALL)
 
 
266
    {
 
 
267
        angle = -SGUN_PAN_GIMBALL;
 
 
268
    }
 
 
269
 
 
 
270
    {
 
 
271
        int fake_timer;
 
 
272
 
 
 
273
        if (angle > 0)
 
 
274
        {
 
 
275
            fake_timer = DIV_FIXED(angle,(SGUN_PAN_GIMBALL<<1));
 
 
276
            fake_timer += 32767;
 
 
277
 
 
 
278
            if (fake_timer > 65536)
 
 
279
                fake_timer = 65535;
 
 
280
            else if (fake_timer < 0)
 
 
281
                fake_timer = 0;
 
 
282
        }
 
 
283
        else
 
 
284
        {
 
 
285
            fake_timer = DIV_FIXED(angle,(SGUN_PAN_GIMBALL<<1));
 
 
286
            fake_timer += 32767;
 
 
287
 
 
 
288
            if (fake_timer > 65536)
 
 
289
                fake_timer = 65535;
 
 
290
            else if (fake_timer < 0)
 
 
291
                fake_timer = 0;
 
 
292
        }
 
 
293
 
 
 
294
        if (agunStatusPointer->gun_pan->timer != fake_timer)
 
 
295
            agunStatusPointer->WhirrSoundOn = 1;
 
 
296
 
 
 
297
        agunStatusPointer->gun_pan->timer = fake_timer;
 
 
298
    }
 
 
299
 
 
 
300
    /* Gun Tilt... */
 
 
301
 
 
 
302
    angle = agunStatusPointer->Gun_Tilt>>4;
 
 
303
 
 
 
304
    if (angle >= 3072)
 
 
305
        angle -= 4096;
 
 
306
 
 
 
307
    if (angle >= 2048)
 
 
308
        angle = angle - 3072;
 
 
309
 
 
 
310
    if (angle > 1024)
 
 
311
        angle = 2048-angle;
 
 
312
 
 
 
313
    assert(agunStatusPointer->gun_tilt);
 
 
314
 
 
 
315
    /* Now, we have an angle. */
 
 
316
 
 
 
317
    if (angle > SGUN_PITCH_GIMBALL)
 
 
318
    {
 
 
319
        angle = SGUN_PITCH_GIMBALL;
 
 
320
    }
 
 
321
    else if (angle < -SGUN_PITCH_GIMBALL)
 
 
322
    {
 
 
323
        angle = -SGUN_PITCH_GIMBALL;
 
 
324
    }
 
 
325
 
 
 
326
    assert(angle >= -1024);
 
 
327
    assert(angle <= 1024);
 
 
328
 
 
 
329
    {
 
 
330
        int fake_timer = 1024 - angle;
 
 
331
 
 
 
332
        fake_timer <<= 5;
 
 
333
 
 
 
334
        if (fake_timer == 65536)
 
 
335
            fake_timer = 65535;
 
 
336
 
 
 
337
        fake_timer = 65536 - fake_timer;
 
 
338
 
 
 
339
        assert(fake_timer >= 0);
 
 
340
        assert(fake_timer < 65536);
 
 
341
 
 
 
342
        if (agunStatusPointer->gun_tilt->timer != fake_timer)
 
 
343
            agunStatusPointer->WhirrSoundOn = 1;
 
 
344
 
 
 
345
        agunStatusPointer->gun_tilt->timer = fake_timer;
 
 
346
    }
 
 
347
}
 
 
348
 
 
 
349
static int Autogun_TargetFilter(STRATEGYBLOCK *candidate)
 
 
350
{
 
 
351
    // Reject NULLs and far targets.
 
 
352
    if (candidate->DisplayBlock == NULL)
 
 
353
        return 0;
 
 
354
 
 
 
355
    // Shoot pretty much anything.
 
 
356
    switch (candidate->type)
 
 
357
    {
 
 
358
        case I_BehaviourAlien:
 
 
359
        case I_BehaviourPredator:
 
 
360
        case I_BehaviourFaceHugger:
 
 
361
        case I_BehaviourAlienPlayer:
 
 
362
        case I_BehaviourPredatorPlayer:
 
 
363
        case I_BehaviourXenoborg:
 
 
364
        case I_BehaviourQueenAlien:
 
 
365
            return 1;
 
 
366
        case I_BehaviourDummy:
 
 
367
        {
 
 
368
            DUMMY_STATUS_BLOCK *dummyStatusPointer = (DUMMY_STATUS_BLOCK *)(candidate->dataptr);    
 
 
369
            assert(dummyStatusPointer);
 
 
370
            switch (dummyStatusPointer->PlayerType)
 
 
371
            {
 
 
372
                case I_Alien:
 
 
373
                case I_Predator:
 
 
374
                    return 1;
 
 
375
                default:
 
 
376
                    return 0;
 
 
377
            }
 
 
378
        }
 
 
379
        default:
 
 
380
        return 0;
 
 
381
    }
 
 
382
}
 
 
383
 
 
 
384
static STRATEGYBLOCK *Autogun_GetNewTarget(STRATEGYBLOCK *sbPtr)
 
 
385
{
 
 
386
    int neardist = ONE_FIXED;
 
 
387
    int a;
 
 
388
    STRATEGYBLOCK *nearest = NULL;
 
 
389
 
 
 
390
    for (a=0; a < NumActiveStBlocks; a++)
 
 
391
    {
 
 
392
        STRATEGYBLOCK *candidate = ActiveStBlockList[a];
 
 
393
 
 
 
394
        if ((candidate != sbPtr) && candidate->DynPtr && Autogun_TargetFilter(candidate))
 
 
395
        {
 
 
396
            VECTORCH offset;
 
 
397
 
 
 
398
            offset.vx = (&sbPtr->DynPtr->Position)->vx - candidate->DynPtr->Position.vx;
 
 
399
            offset.vy = (&sbPtr->DynPtr->Position)->vy - candidate->DynPtr->Position.vy;
 
 
400
            offset.vz = (&sbPtr->DynPtr->Position)->vz - candidate->DynPtr->Position.vz;
 
 
401
 
 
 
402
            int dist = Approximate3dMagnitude(&offset);
 
 
403
 
 
 
404
            if ((dist < neardist) && NPCCanSeeTarget(sbPtr, candidate) && !NPC_IsDead(candidate))
 
 
405
            {
 
 
406
                MODULE *dmod = ModuleFromPosition(&sbPtr->DynPtr->Position, PlayerStatus.sbptr->containingModule);
 
 
407
                assert(dmod);
 
 
408
 
 
 
409
                if (IsModuleVisibleFromModule(dmod, candidate->containingModule))
 
 
410
                    nearest = candidate;
 
 
411
            }
 
 
412
        }
 
 
413
    }
 
 
414
 
 
 
415
return(nearest);
 
 
416
}
 
 
417
 
 
 
418
int AGunSight_FrustrumReject(VECTORCH *localOffset)
 
 
419
{
 
 
420
    VECTORCH fixed_offset = *localOffset;
 
 
421
 
 
 
422
//    printf("Local Offset: %d %d %d\n",localOffset->vx,localOffset->vy,localOffset->vz);
 
 
423
 
 
 
424
    fixed_offset.vy -= 300; /* ish */
 
 
425
 
 
 
426
    return (((fixed_offset.vz < 0) && ( ((fixed_offset.vy) < (-fixed_offset.vz)) && (fixed_offset.vy >= 0)))
 
 
427
         ||((fixed_offset.vy < 0) && ((-fixed_offset.vy) < (-fixed_offset.vz))));
 
 
428
    /*
 
 
429
        return 1; // 180 horizontal, 90 vertical.
 
 
430
    else
 
 
431
        return 0;
 
 
432
    */
 
 
433
}
 
 
434
 
 
 
435
void AGunMovement_ScanLeftRight(STRATEGYBLOCK *sbPtr,int rate)
 
 
436
{
 
 
437
    assert(sbPtr);
 
 
438
    AUTOGUN_STATUS_BLOCK *agunStatusPointer    = (AUTOGUN_STATUS_BLOCK *)(sbPtr->dataptr);        
 
 
439
    assert(agunStatusPointer);
 
 
440
 
 
 
441
    /* Let's wave the gun around, half full tracking. */
 
 
442
    if (agunStatusPointer->gunpandir)
 
 
443
    {
 
 
444
        agunStatusPointer->Gun_Pan += (NormalFrameTime >> rate);
 
 
445
 
 
 
446
        if (agunStatusPointer->Gun_Pan > (SGUN_PAN_GIMBALL << 3))
 
 
447
        {
 
 
448
            agunStatusPointer->Gun_Pan = (SGUN_PAN_GIMBALL << 3);
 
 
449
            agunStatusPointer->gunpandir = 0;
 
 
450
        }
 
 
451
    }
 
 
452
    else
 
 
453
    {
 
 
454
        agunStatusPointer->Gun_Pan -= (NormalFrameTime >> rate);
 
 
455
 
 
 
456
        if (agunStatusPointer->Gun_Pan < -(SGUN_PAN_GIMBALL << 3))
 
 
457
        {
 
 
458
            agunStatusPointer->Gun_Pan = -(SGUN_PAN_GIMBALL << 3);
 
 
459
            agunStatusPointer->gunpandir = 1;
 
 
460
        }
 
 
461
    }
 
 
462
 
 
 
463
    if (agunStatusPointer->gun_pan)
 
 
464
        agunStatusPointer->gun_pan->Active = 1;
 
 
465
 
 
 
466
    /* And centre tilt. */
 
 
467
    if (agunStatusPointer->Gun_Tilt < 0)
 
 
468
    {
 
 
469
        agunStatusPointer->Gun_Tilt+=(NormalFrameTime>>rate);
 
 
470
 
 
 
471
        if (agunStatusPointer->Gun_Tilt > (SGUN_PAN_GIMBALL << 3))
 
 
472
        {
 
 
473
            agunStatusPointer->Gun_Tilt = (SGUN_PAN_GIMBALL << 3);
 
 
474
        }
 
 
475
        else if (agunStatusPointer->Gun_Tilt > 0)
 
 
476
        {
 
 
477
            agunStatusPointer->Gun_Tilt = 0;
 
 
478
        }
 
 
479
 
 
 
480
    }
 
 
481
    else if (agunStatusPointer->Gun_Tilt > 0)
 
 
482
    {
 
 
483
        agunStatusPointer->Gun_Tilt -= (NormalFrameTime >> rate);
 
 
484
 
 
 
485
        if (agunStatusPointer->Gun_Tilt < -(SGUN_PAN_GIMBALL << 3))
 
 
486
        {
 
 
487
            agunStatusPointer->Gun_Tilt = -(SGUN_PAN_GIMBALL << 3);
 
 
488
 
 
 
489
        }
 
 
490
        else if (agunStatusPointer->Gun_Tilt < 0)
 
 
491
        {
 
 
492
            agunStatusPointer->Gun_Tilt = 0;
 
 
493
        }
 
 
494
    }
 
 
495
 
 
 
496
    if (agunStatusPointer->gun_tilt)
 
 
497
        agunStatusPointer->gun_tilt->Active = 1;
 
 
498
}
 
 
499
 
 
 
500
void AGunMovement_Centre(STRATEGYBLOCK *sbPtr,int rate)
 
 
501
{
 
 
502
    assert(sbPtr);
 
 
503
    AUTOGUN_STATUS_BLOCK *agunStatusPointer    = (AUTOGUN_STATUS_BLOCK *)(sbPtr->dataptr);        
 
 
504
    assert(agunStatusPointer);
 
 
505
 
 
 
506
    /* Let's centre pan... */
 
 
507
    if (agunStatusPointer->Gun_Pan < 0)
 
 
508
    {
 
 
509
        agunStatusPointer->Gun_Pan += (NormalFrameTime >> rate);
 
 
510
 
 
 
511
        if (agunStatusPointer->Gun_Pan > (SGUN_PAN_GIMBALL << 3))
 
 
512
        {
 
 
513
            agunStatusPointer->Gun_Pan = (SGUN_PAN_GIMBALL << 3);
 
 
514
 
 
 
515
        }
 
 
516
        else if (agunStatusPointer->Gun_Pan > 0)
 
 
517
        {
 
 
518
            agunStatusPointer->Gun_Pan = 0;
 
 
519
        }
 
 
520
    }
 
 
521
    else if (agunStatusPointer->Gun_Pan > 0)
 
 
522
    {
 
 
523
        agunStatusPointer->Gun_Pan -= (NormalFrameTime >> rate);
 
 
524
 
 
 
525
        if (agunStatusPointer->Gun_Pan < -(SGUN_PAN_GIMBALL << 3))
 
 
526
        {
 
 
527
            agunStatusPointer->Gun_Pan = -(SGUN_PAN_GIMBALL << 3);
 
 
528
        }
 
 
529
        else if (agunStatusPointer->Gun_Pan < 0)
 
 
530
        {
 
 
531
            agunStatusPointer->Gun_Pan = 0;
 
 
532
        }
 
 
533
    }
 
 
534
 
 
 
535
    if (agunStatusPointer->gun_pan)
 
 
536
        agunStatusPointer->gun_pan->Active = 1;
 
 
537
 
 
 
538
    /* And centre tilt. */
 
 
539
    if (agunStatusPointer->Gun_Tilt < 0)
 
 
540
    {
 
 
541
        agunStatusPointer->Gun_Tilt += (NormalFrameTime >> rate);
 
 
542
 
 
 
543
        if (agunStatusPointer->Gun_Tilt > (SGUN_PAN_GIMBALL << 3))
 
 
544
        {
 
 
545
            agunStatusPointer->Gun_Tilt = (SGUN_PAN_GIMBALL << 3);
 
 
546
 
 
 
547
        }
 
 
548
        else if (agunStatusPointer->Gun_Tilt > 0)
 
 
549
        {
 
 
550
            agunStatusPointer->Gun_Tilt = 0;
 
 
551
        }
 
 
552
    }
 
 
553
    else if (agunStatusPointer->Gun_Tilt > 0)
 
 
554
    {
 
 
555
        agunStatusPointer->Gun_Tilt -= (NormalFrameTime >> rate);
 
 
556
 
 
 
557
        if (agunStatusPointer->Gun_Tilt < -(SGUN_PAN_GIMBALL << 3))
 
 
558
        {
 
 
559
            agunStatusPointer->Gun_Tilt = -(SGUN_PAN_GIMBALL << 3);
 
 
560
 
 
 
561
        }
 
 
562
        else if (agunStatusPointer->Gun_Tilt < 0)
 
 
563
        {
 
 
564
            agunStatusPointer->Gun_Tilt = 0;
 
 
565
        }
 
 
566
    }
 
 
567
 
 
 
568
    if (agunStatusPointer->gun_tilt)
 
 
569
        agunStatusPointer->gun_tilt->Active = 1;
 
 
570
}
 
 
571
 
 
 
572
void AGun_GetRelativeAngles(STRATEGYBLOCK *sbPtr, int *anglex, int *angley, VECTORCH *pivotPoint) 
 
 
573
{
 
 
574
    VECTORCH targetPos;
 
 
575
 
 
 
576
    assert(sbPtr);
 
 
577
    AUTOGUN_STATUS_BLOCK *agunStatusPointer    = (AUTOGUN_STATUS_BLOCK *)(sbPtr->dataptr);        
 
 
578
    assert(agunStatusPointer);
 
 
579
 
 
 
580
    /* First, extract relative angle. */
 
 
581
 
 
 
582
    MATRIXCH WtoL = sbPtr->DynPtr->OrientMat;
 
 
583
    TransposeMatrixCH(&WtoL);
 
 
584
    targetPos = agunStatusPointer->targetTrackPos;
 
 
585
    targetPos.vx -= pivotPoint->vx;
 
 
586
    targetPos.vy -= pivotPoint->vy;
 
 
587
    targetPos.vz -= pivotPoint->vz;
 
 
588
    RotateVector(&targetPos,&WtoL);
 
 
589
 
 
 
590
    /* Now... */
 
 
591
    {
 
 
592
        int offsetx = targetPos.vx;
 
 
593
        int offsety = targetPos.vz;
 
 
594
        int offseta = -(targetPos.vy);
 
 
595
 
 
 
596
        while( (offsetx > (ONE_FIXED>>2))
 
 
597
            ||(offsety > (ONE_FIXED>>2))
 
 
598
            ||(offseta > (ONE_FIXED>>2))
 
 
599
            ||(offsetx < -(ONE_FIXED>>2))
 
 
600
            ||(offsety < -(ONE_FIXED>>2))
 
 
601
            ||(offseta < -(ONE_FIXED>>2)))
 
 
602
        {
 
 
603
            offsetx >>= 1;
 
 
604
            offsety >>= 1;
 
 
605
            offseta >>= 1;
 
 
606
        }
 
 
607
 
 
 
608
        int offsetz = SqRoot32((offsetx*offsetx)+(offsety*offsety));
 
 
609
 
 
 
610
        if (angley)
 
 
611
        {
 
 
612
            *angley = ArcTan(offseta, offsetz);
 
 
613
 
 
 
614
            if (*angley >= 3072)
 
 
615
                *angley -= 4096;
 
 
616
 
 
 
617
            if (*angley >= 2048)
 
 
618
                *angley = (*angley) - 3072;
 
 
619
 
 
 
620
            if (*angley > 1024)
 
 
621
                *angley = 2048 - *angley;
 
 
622
        }
 
 
623
 
 
 
624
        if (anglex)
 
 
625
        {
 
 
626
            *anglex = ArcTan(offsetx, offsety);
 
 
627
 
 
 
628
            if (*anglex >= 3072)
 
 
629
                *anglex -= 4096;
 
 
630
 
 
 
631
            if (*anglex >= 2048)
 
 
632
                *anglex = *anglex - 4096;
 
 
633
        }
 
 
634
    }
 
 
635
}
 
 
636
 
 
 
637
int AGunMovement_TrackToAngles(STRATEGYBLOCK *sbPtr,int rate,int in_anglex,int in_angley)
 
 
638
{
 
 
639
    int real_anglex = in_anglex;
 
 
640
    int angley = in_angley;
 
 
641
    int online = 0;
 
 
642
 
 
 
643
    assert(sbPtr);
 
 
644
    AUTOGUN_STATUS_BLOCK *agunStatusPointer    = (AUTOGUN_STATUS_BLOCK *)(sbPtr->dataptr);        
 
 
645
    assert(agunStatusPointer);
 
 
646
 
 
 
647
    /* Now fix multiples. */
 
 
648
    while ((real_anglex > 4095) || (real_anglex < 0))
 
 
649
    {
 
 
650
        if (real_anglex <0)
 
 
651
        {
 
 
652
            real_anglex += 4096;
 
 
653
        }
 
 
654
        else if (real_anglex > 4095)
 
 
655
        {
 
 
656
            real_anglex -= 4096;
 
 
657
        }
 
 
658
    }
 
 
659
 
 
 
660
    if (real_anglex >= 3072)
 
 
661
        real_anglex -= 4096;
 
 
662
 
 
 
663
    if (real_anglex >= 2048)
 
 
664
        real_anglex = real_anglex - 3072;
 
 
665
 
 
 
666
    if (real_anglex > 1024)
 
 
667
        real_anglex = 2048 - real_anglex;
 
 
668
 
 
 
669
    if (angley >= 3072)
 
 
670
        angley -= 4096;
 
 
671
 
 
 
672
    if (angley >= 2048)
 
 
673
        angley = angley-3072;
 
 
674
 
 
 
675
    if (angley > 1024)
 
 
676
        angley = 2048-angley;
 
 
677
 
 
 
678
    real_anglex <<= 4;
 
 
679
    angley <<= 4;
 
 
680
 
 
 
681
    if (agunStatusPointer->Gun_Pan<real_anglex)
 
 
682
    {
 
 
683
        agunStatusPointer->Gun_Pan += (NormalFrameTime >> rate);
 
 
684
 
 
 
685
        if (agunStatusPointer->Gun_Pan > (SGUN_PAN_GIMBALL << 4))
 
 
686
        {
 
 
687
            agunStatusPointer->Gun_Pan = (SGUN_PAN_GIMBALL << 4);
 
 
688
        }
 
 
689
        else if (agunStatusPointer->Gun_Pan > real_anglex)
 
 
690
        {
 
 
691
            agunStatusPointer->Gun_Pan = real_anglex;
 
 
692
            online++;
 
 
693
        }
 
 
694
    }
 
 
695
    else if (agunStatusPointer->Gun_Pan > real_anglex)
 
 
696
    {
 
 
697
        agunStatusPointer->Gun_Pan -= (NormalFrameTime >> rate);
 
 
698
 
 
 
699
        if (agunStatusPointer->Gun_Pan < -(SGUN_PAN_GIMBALL << 4))
 
 
700
        {
 
 
701
            agunStatusPointer->Gun_Pan = -(SGUN_PAN_GIMBALL << 4);
 
 
702
        }
 
 
703
        else if (agunStatusPointer->Gun_Pan < real_anglex)
 
 
704
        {
 
 
705
            agunStatusPointer->Gun_Pan = real_anglex;
 
 
706
            online++;
 
 
707
        }
 
 
708
    }
 
 
709
    else
 
 
710
    {
 
 
711
        online++;
 
 
712
    }
 
 
713
 
 
 
714
    if (agunStatusPointer->gun_pan)
 
 
715
        agunStatusPointer->gun_pan->Active = 1;
 
 
716
 
 
 
717
    /* Now y. */
 
 
718
    angley = -angley;
 
 
719
    /* Oops. */
 
 
720
 
 
 
721
    /* Note that Sentryguns now only track vertically HALF their full traverse. */
 
 
722
    /* Those shifts used to be <<4. */
 
 
723
 
 
 
724
    if (agunStatusPointer->Gun_Tilt < angley)
 
 
725
    {
 
 
726
        agunStatusPointer->Gun_Tilt += (NormalFrameTime >> rate);
 
 
727
 
 
 
728
        if (agunStatusPointer->Gun_Tilt > (SGUN_PITCH_GIMBALL << 3))
 
 
729
        {
 
 
730
            agunStatusPointer->Gun_Tilt = (SGUN_PITCH_GIMBALL << 3);
 
 
731
        }
 
 
732
        else if (agunStatusPointer->Gun_Tilt > angley)
 
 
733
        {
 
 
734
            agunStatusPointer->Gun_Tilt = angley;
 
 
735
            online++;
 
 
736
        }
 
 
737
    }
 
 
738
    else if (agunStatusPointer->Gun_Tilt > angley)
 
 
739
    {
 
 
740
        agunStatusPointer->Gun_Tilt -= (NormalFrameTime >> rate);
 
 
741
 
 
 
742
        if (agunStatusPointer->Gun_Tilt < -(SGUN_PITCH_GIMBALL << 3))
 
 
743
        {
 
 
744
            agunStatusPointer->Gun_Tilt = -(SGUN_PITCH_GIMBALL << 3);
 
 
745
        }
 
 
746
        else if (agunStatusPointer->Gun_Tilt < angley)
 
 
747
        {
 
 
748
            agunStatusPointer->Gun_Tilt = angley;
 
 
749
            online++;
 
 
750
        }
 
 
751
    }
 
 
752
    else
 
 
753
    {
 
 
754
        online++;
 
 
755
    }
 
 
756
 
 
 
757
    if (agunStatusPointer->gun_tilt)
 
 
758
        agunStatusPointer->gun_tilt->Active = 1;
 
 
759
 
 
 
760
return (online > 1);
 
 
761
}
 
 
762
 
 
 
763
void Execute_AGun_Target(STRATEGYBLOCK *sbPtr) 
 
 
764
{
 
 
765
    int anglex,angley;
 
 
766
 
 
 
767
    assert(sbPtr);
 
 
768
    AUTOGUN_STATUS_BLOCK *agunStatusPointer    = (AUTOGUN_STATUS_BLOCK *)(sbPtr->dataptr);        
 
 
769
    assert(agunStatusPointer);
 
 
770
 
 
 
771
    {
 
 
772
        SECTION_DATA *gun_section = GetThisSectionData(agunStatusPointer->HModelController.section_data,"gun");
 
 
773
        assert(gun_section);
 
 
774
 
 
 
775
        AGun_GetRelativeAngles(sbPtr,&anglex,&angley,&gun_section->World_Offset);
 
 
776
    }
 
 
777
 
 
 
778
    agunStatusPointer->OnTarget_LastFrame = agunStatusPointer->OnTarget;
 
 
779
 
 
 
780
    if (AGunMovement_TrackToAngles(sbPtr,2,anglex,angley))
 
 
781
    {
 
 
782
        /* Pointing at target! */
 
 
783
        agunStatusPointer->OnTarget = 1;
 
 
784
 
 
 
785
        if (!agunStatusPointer->OnTarget_LastFrame)
 
 
786
        {
 
 
787
            /* Newly aquired! */
 
 
788
            //Sound_Play(SID_SENTRYGUN_LOCK,"d",&sbPtr->DynPtr->Position);
 
 
789
            agunStatusPointer->Drama = SENTRYGUN_DRAMA;
 
 
790
        }
 
 
791
 
 
 
792
        if (agunStatusPointer->Drama <= 0)
 
 
793
        {
 
 
794
            if (!agunStatusPointer->Firing)
 
 
795
            {
 
 
796
                /* Renew firing. */
 
 
797
                agunStatusPointer->Firing = ONE_FIXED >> 1;
 
 
798
            }
 
 
799
        }
 
 
800
        else
 
 
801
        {
 
 
802
            agunStatusPointer->Firing = 0;
 
 
803
            agunStatusPointer->Drama -= NormalFrameTime;
 
 
804
 
 
 
805
            if (agunStatusPointer->Drama < 0)
 
 
806
                agunStatusPointer->Drama = 0;
 
 
807
        }
 
 
808
    }
 
 
809
    else
 
 
810
    {
 
 
811
        agunStatusPointer->OnTarget = 0;
 
 
812
    }
 
 
813
}
 
 
814
 
 
 
815
static void AGun_MaintainGun(STRATEGYBLOCK *sbPtr)
 
 
816
{
 
 
817
    VECTORCH alpha;
 
 
818
    VECTORCH beta;
 
 
819
 
 
 
820
    AUTOGUN_STATUS_BLOCK *agunStatusPointer = (AUTOGUN_STATUS_BLOCK *)(sbPtr->dataptr);        
 
 
821
 
 
 
822
    SECTION_DATA *dum = GetThisSectionData(agunStatusPointer->HModelController.section_data, "flash dummy");
 
 
823
 
 
 
824
    if (!agunStatusPointer->Firing || (dum == NULL) || !sbPtr->DisplayBlock)
 
 
825
    {
 
 
826
        DestroyActiveObject(&agunStatusPointer->GunFlash);
 
 
827
        return;
 
 
828
    }
 
 
829
 
 
 
830
    if (sentrygun_reload_ammo)
 
 
831
    {
 
 
832
        agunStatusPointer->ammo = 500;
 
 
833
        sentrygun_reload_ammo = 0;
 
 
834
    }
 
 
835
 
 
 
836
    /* Okay, must be firing.  Did we get anyone? */
 
 
837
 
 
 
838
    int volley_section = AGUN_ROF * NormalFrameTime;
 
 
839
 
 
 
840
    agunStatusPointer->volleyFired += volley_section;
 
 
841
 
 
 
842
    if (agunStatusPointer->volleyFired > (AGUN_VOLLEYSIZE << ONE_FIXED_SHIFT))
 
 
843
        agunStatusPointer->volleyFired = (AGUN_VOLLEYSIZE << ONE_FIXED_SHIFT);
 
 
844
 
 
 
845
    int totalrounds = agunStatusPointer->volleyFired >> ONE_FIXED_SHIFT;
 
 
846
    assert(totalrounds >= agunStatusPointer->roundsFired);
 
 
847
    int multiple = totalrounds-agunStatusPointer->roundsFired;
 
 
848
 
 
 
849
    if (multiple && !agunStatusPointer->ammo) 
 
 
850
    {
 
 
851
        /* Click ineffectually. */
 
 
852
        if (agunStatusPointer->soundHandle != SOUND_NOACTIVEINDEX) 
 
 
853
        {
 
 
854
            if (ActiveSounds[agunStatusPointer->soundHandle].soundIndex != SID_NOAMMO)
 
 
855
                Sound_Stop(agunStatusPointer->soundHandle);
 
 
856
        }
 
 
857
        else
 
 
858
        //if (agunStatusPointer->soundHandle == SOUND_NOACTIVEINDEX) 
 
 
859
        {
 
 
860
            Sound_Play(SID_NOAMMO, "del", &sbPtr->DynPtr->Position, &agunStatusPointer->soundHandle);
 
 
861
        }
 
 
862
 
 
 
863
        DestroyActiveObject(&agunStatusPointer->GunFlash);
 
 
864
    return;
 
 
865
    }
 
 
866
 
 
 
867
    if (!sentrygun_infinity_ammo)
 
 
868
    {
 
 
869
        if (multiple > agunStatusPointer->ammo)
 
 
870
        {
 
 
871
            multiple = agunStatusPointer->ammo;
 
 
872
            agunStatusPointer->ammo = 0;
 
 
873
        }
 
 
874
        else
 
 
875
            agunStatusPointer->ammo -= multiple;
 
 
876
    }
 
 
877
 
 
 
878
    agunStatusPointer->roundsFired += multiple;
 
 
879
 
 
 
880
    /* End of volley? */
 
 
881
    if (agunStatusPointer->volleyFired == (AGUN_VOLLEYSIZE << ONE_FIXED_SHIFT))
 
 
882
    {
 
 
883
        agunStatusPointer->volleyFired= 0;
 
 
884
        agunStatusPointer->roundsFired = 0;
 
 
885
        agunStatusPointer->Target= NULL;
 
 
886
    }
 
 
887
 
 
 
888
    while (multiple)
 
 
889
    {
 
 
890
        /* Set up LOS. */
 
 
891
        //get a random rotation , for error in firing direction
 
 
892
        MATRIXCH rotate;
 
 
893
 
 
 
894
        multiple--;
 
 
895
 
 
 
896
        {
 
 
897
            EULER e;
 
 
898
            //convert angle from degrees to the engine units
 
 
899
            int spread = (SentrygunSpread* 4096) / 360;
 
 
900
            e.EulerX = (MUL_FIXED(FastRandom()&0xffff,spread*2)-spread)&wrap360;
 
 
901
            e.EulerY =(MUL_FIXED(FastRandom()&0xffff,spread*2)-spread)&wrap360;
 
 
902
            e.EulerZ = 0;
 
 
903
            CreateEulerMatrix(&e,&rotate);
 
 
904
        }
 
 
905
 
 
 
906
        alpha = dum->World_Offset;
 
 
907
        beta.vx = dum->SecMat.mat31;
 
 
908
        beta.vy = dum->SecMat.mat32;
 
 
909
        beta.vz = dum->SecMat.mat33;
 
 
910
 
 
 
911
        RotateVector(&beta, &rotate);
 
 
912
 
 
 
913
        if(FindPolygonInLineOfSight(&beta, &alpha, sbPtr->DisplayBlock))
 
 
914
        {
 
 
915
            #if DEBUG
 
 
916
            if (LOS_HModel_Section && LOS_ObjectHitPtr->ObStrategyBlock && LOS_ObjectHitPtr->ObStrategyBlock->DisplayBlock)
 
 
917
            {
 
 
918
                assert(LOS_ObjectHitPtr->ObStrategyBlock->DisplayBlock->HModelControlBlock == LOS_HModel_Section->my_controller);
 
 
919
            }
 
 
920
            #endif
 
 
921
 
 
 
922
            /*Don't allow the sentrygun to destroy 'special' inanimate objects.  Doing so ruins some puzzles*/
 
 
923
 
 
 
924
            if (LOS_ObjectHitPtr->Module)
 
 
925
            {
 
 
926
                /* bad idea to put bullethole on a morphing object */
 
 
927
                if(!LOS_ObjectHitPtr->ObMorphCtrl)
 
 
928
                    MakeDecal(DECAL_BULLETHOLE, &LOS_ObjectNormal, &LOS_Point, LOS_ObjectHitPtr->Module->m_index);
 
 
929
 
 
 
930
                /* cause a ricochet 1 in 8 times */
 
 
931
                if ((FastRandom() & 65535) < 8192)
 
 
932
                    MakeImpactSparks(&beta, &LOS_ObjectNormal, &LOS_Point);
 
 
933
            }
 
 
934
            else if(LOS_ObjectHitPtr->ObStrategyBlock)
 
 
935
            {
 
 
936
                STRATEGYBLOCK* hit_sbptr = LOS_ObjectHitPtr->ObStrategyBlock;
 
 
937
                VECTORCH incoming, *invec = NULL;
 
 
938
 
 
 
939
                switch(hit_sbptr->type)
 
 
940
                {
 
 
941
                    case I_BehaviourInanimateObject:
 
 
942
                    {
 
 
943
                        INANIMATEOBJECT_STATUSBLOCK* objectstatusptr = (INANIMATEOBJECT_STATUSBLOCK*)hit_sbptr->dataptr;
 
 
944
 
 
 
945
                        if(objectstatusptr->event_target)
 
 
946
                            continue; /*This object has best be left*/
 
 
947
                    }
 
 
948
                    break;
 
 
949
                    case I_BehaviourQueenAlien:
 
 
950
                    {
 
 
951
                        if ((FastRandom() & 65535) < 8192)
 
 
952
                            MakeImpactSparks(&beta, &LOS_ObjectNormal, &LOS_Point);
 
 
953
                    }
 
 
954
                    default:
 
 
955
                    break;
 
 
956
                }
 
 
957
 
 
 
958
                if (hit_sbptr->DynPtr)
 
 
959
                {
 
 
960
                    MATRIXCH WtoLMat = hit_sbptr->DynPtr->OrientMat;
 
 
961
                    /* Consider incoming hit direction. */
 
 
962
                    TransposeMatrixCH(&WtoLMat);
 
 
963
                    RotateAndCopyVector(&beta, &incoming, &WtoLMat);
 
 
964
                    invec = &incoming;
 
 
965
                }
 
 
966
 
 
 
967
                if (LOS_HModel_Section && hit_sbptr->DisplayBlock && hit_sbptr->DisplayBlock->HModelControlBlock)
 
 
968
                {
 
 
969
                    AddDecalToHModel(&LOS_ObjectNormal, &LOS_Point, LOS_HModel_Section);
 
 
970
                    CauseDamageToHModel(hit_sbptr->DisplayBlock->HModelControlBlock, hit_sbptr, &TemplateAmmo[AMMO_AUTOGUN].MaxDamage, ONE_FIXED,
LOS_HModel_Section, invec, &LOS_Point, 0);
 
 
971
                }
 
 
972
                else
 
 
973
                {
 
 
974
                    CauseDamageToObject(hit_sbptr, &TemplateAmmo[AMMO_AUTOGUN].MaxDamage, ONE_FIXED, invec);
 
 
975
                }
 
 
976
 
 
 
977
                if (hit_sbptr->DynPtr)
 
 
978
                {
 
 
979
                    DYNAMICSBLOCK *dynPtr = hit_sbptr->DynPtr;
 
 
980
                    EULER rotation;
 
 
981
                    int magnitudeOfForce = (5000 * TotalKineticDamage(&TemplateAmmo[AMMO_AUTOGUN].MaxDamage)) / dynPtr->Mass;
 
 
982
                    /* okay, not too sure yet what this should do */
 
 
983
                    dynPtr->LinImpulse.vx += MUL_FIXED(beta.vx, magnitudeOfForce);
 
 
984
                    dynPtr->LinImpulse.vy += MUL_FIXED(beta.vy, magnitudeOfForce);
 
 
985
                    dynPtr->LinImpulse.vz += MUL_FIXED(beta.vz, magnitudeOfForce);
 
 
986
                }
 
 
987
            }
 
 
988
        }
 
 
989
    }
 
 
990
 
 
 
991
    if (agunStatusPointer->GunFlash == NULL)
 
 
992
    {
 
 
993
        DISPLAYBLOCK *dPtr = CreateSFXObject(SFX_MUZZLE_FLASH_SMARTGUN);
 
 
994
 
 
 
995
        if(dPtr)
 
 
996
        {
 
 
997
            dPtr->ObWorld = dum->World_Offset;
 
 
998
            dPtr->ObMat = dum->SecMat;
 
 
999
            AddLightingEffectToObject(dPtr, LFX_MUZZLEFLASH);
 
 
1000
            dPtr->SfxPtr->EffectDrawnLastFrame = 0;
 
 
1001
            agunStatusPointer->GunFlash = dPtr;
 
 
1002
        }
 
 
1003
    }
 
 
1004
    else
 
 
1005
    {
 
 
1006
 
 
 
1007
        agunStatusPointer->GunFlash->ObWorld = dum->World_Offset;
 
 
1008
        agunStatusPointer->GunFlash->ObMat = dum->SecMat;
 
 
1009
        AddLightingEffectToObject(agunStatusPointer->GunFlash, LFX_MUZZLEFLASH);
 
 
1010
    }
 
 
1011
 
 
 
1012
    if (agunStatusPointer->soundHandle == SOUND_NOACTIVEINDEX)
 
 
1013
    {
 
 
1014
        SentryFire_SoundData.position = sbPtr->DynPtr->Position;
 
 
1015
        //Sound_Play(SID_SENTRY_GUN, "nel", &SentryFire_SoundData, &agunStatusPointer->soundHandle);
 
 
1016
        Sound_Play(SID_SENTRY_GUN, "ed", &agunStatusPointer->soundHandle, &sbPtr->DynPtr->Position);
 
 
1017
    }
 
 
1018
    else
 
 
1019
    {
 
 
1020
        if (ActiveSounds[agunStatusPointer->soundHandle].soundIndex != SID_SENTRY_GUN)
 
 
1021
            Sound_Stop(agunStatusPointer->soundHandle);
 
 
1022
    }
 
 
1023
}
 
 
1024
 
 
 
1025
void Execute_AGun_Dying(STRATEGYBLOCK *sbPtr)
 
 
1026
{
 
 
1027
    assert(sbPtr);
 
 
1028
    AUTOGUN_STATUS_BLOCK *agunStatusPointer    = (AUTOGUN_STATUS_BLOCK *)(sbPtr->dataptr);        
 
 
1029
    assert(agunStatusPointer);
 
 
1030
 
 
 
1031
    /* Droop the gun. */
 
 
1032
    if (agunStatusPointer->Gun_Tilt < 8192)
 
 
1033
    {
 
 
1034
        agunStatusPointer->Gun_Tilt += NormalFrameTime >> 3;
 
 
1035
 
 
 
1036
        if (agunStatusPointer->Gun_Tilt > (SGUN_PITCH_GIMBALL << 3))
 
 
1037
        {
 
 
1038
            agunStatusPointer->Gun_Tilt = SGUN_PITCH_GIMBALL << 3;
 
 
1039
        }
 
 
1040
        else if (agunStatusPointer->Gun_Tilt > 8192)
 
 
1041
        {
 
 
1042
            agunStatusPointer->Gun_Tilt = 8192;
 
 
1043
        }
 
 
1044
    }
 
 
1045
 
 
 
1046
    {
 
 
1047
        /* do we have a displayblock? */
 
 
1048
        DISPLAYBLOCK *dispPtr = sbPtr->DisplayBlock;
 
 
1049
 
 
 
1050
        if (dispPtr)
 
 
1051
        {
 
 
1052
            dispPtr->SpecialFXFlags |= SFXFLAG_MELTINGINTOGROUND;
 
 
1053
            dispPtr->ObFlags2 = agunStatusPointer->stateTimer/2;
 
 
1054
 
 
 
1055
            if (dispPtr->ObFlags2 < ONE_FIXED)
 
 
1056
                agunStatusPointer->HModelController.DisableBleeding = 1;
 
 
1057
        }
 
 
1058
    }
 
 
1059
 
 
 
1060
    agunStatusPointer->stateTimer -= NormalFrameTime;
 
 
1061
}
 
 
1062
 
 
 
1063
void AutoGunBehaveFun(STRATEGYBLOCK* sbPtr)
 
 
1064
{
 
 
1065
    assert(sbPtr);
 
 
1066
    AUTOGUN_STATUS_BLOCK *agunStatusPointer = (AUTOGUN_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
1067
    assert(agunStatusPointer);
 
 
1068
 
 
 
1069
    /* test if we've got a containing module: if we haven't, do nothing.
 
 
1070
    This is important as the object could have been marked for deletion by the visibility 
 
 
1071
    management system...*/
 
 
1072
 
 
 
1073
    if(!sbPtr->containingModule)
 
 
1074
    {
 
 
1075
        sbPtr->please_destroy_me = 1; /* just to make sure */
 
 
1076
    return;
 
 
1077
    }
 
 
1078
 
 
 
1079
    #if DEBUG
 
 
1080
    if(sbPtr->DisplayBlock)
 
 
1081
    {
 
 
1082
        assert(ModuleCurrVisArray[sbPtr->containingModule->m_index]);                        
 
 
1083
    }
 
 
1084
    #endif
 
 
1085
 
 
 
1086
    Autogun_VerifyDeltaControllers(sbPtr);
 
 
1087
 
 
 
1088
    if (NULL != agunStatusPointer->Target)
 
 
1089
    {
 
 
1090
        if (NULL == agunStatusPointer->Target->DisplayBlock)
 
 
1091
        {
 
 
1092
            agunStatusPointer->Target = Autogun_GetNewTarget(sbPtr);
 
 
1093
 
 
 
1094
            if (agunStatusPointer->Target)
 
 
1095
            {
 
 
1096
                COPY_NAME(agunStatusPointer->Target_SBname, agunStatusPointer->Target->SBname);
 
 
1097
                GetTargetingPointOfObject_Far(agunStatusPointer->Target, &agunStatusPointer->targetTrackPos);
 
 
1098
            }
 
 
1099
            else
 
 
1100
            {
 
 
1101
                agunStatusPointer->targetTrackPos.vx = agunStatusPointer->targetTrackPos.vy = agunStatusPointer->targetTrackPos.vz = 0;
 
 
1102
            }
 
 
1103
        }
 
 
1104
        else
 
 
1105
        {
 
 
1106
            /* We have a valid target that we can't see? */
 
 
1107
            if (NAME_ISEQUAL(agunStatusPointer->Target->SBname, agunStatusPointer->Target_SBname)
 
 
1108
            && !NPC_IsDead(agunStatusPointer->Target) && NPCCanSeeTarget(sbPtr, agunStatusPointer->Target))
 
 
1109
            {
 
 
1110
                GetTargetingPointOfObject_Far(agunStatusPointer->Target, &agunStatusPointer->targetTrackPos);
 
 
1111
            }
 
 
1112
            else
 
 
1113
            {
 
 
1114
                agunStatusPointer->Target = NULL;
 
 
1115
                agunStatusPointer->targetTrackPos.vx = agunStatusPointer->targetTrackPos.vy = agunStatusPointer->targetTrackPos.vz = 0;
 
 
1116
            }
 
 
1117
        }
 
 
1118
    }
 
 
1119
    else
 
 
1120
    {
 
 
1121
        if (NULL != sbPtr->DisplayBlock)
 
 
1122
        {
 
 
1123
            agunStatusPointer->Target = Autogun_GetNewTarget(sbPtr);
 
 
1124
 
 
 
1125
            if (agunStatusPointer->Target)
 
 
1126
            {
 
 
1127
                COPY_NAME(agunStatusPointer->Target_SBname, agunStatusPointer->Target->SBname);
 
 
1128
                GetTargetingPointOfObject_Far(agunStatusPointer->Target, &agunStatusPointer->targetTrackPos);
 
 
1129
            }
 
 
1130
            else
 
 
1131
            {
 
 
1132
                agunStatusPointer->targetTrackPos.vx = agunStatusPointer->targetTrackPos.vy = agunStatusPointer->targetTrackPos.vz = 0;
 
 
1133
            }
 
 
1134
        }
 
 
1135
    }
 
 
1136
 
 
 
1137
    if (agunStatusPointer->Firing)
 
 
1138
    {
 
 
1139
        agunStatusPointer->Firing -= NormalFrameTime;
 
 
1140
 
 
 
1141
        if (agunStatusPointer->Firing < 0)
 
 
1142
            agunStatusPointer->Firing = 0;
 
 
1143
    }
 
 
1144
 
 
 
1145
    /* Unset incident flag. */
 
 
1146
    agunStatusPointer->incidentFlag = 0;
 
 
1147
    agunStatusPointer->incidentTimer -= NormalFrameTime;
 
 
1148
 
 
 
1149
    if (agunStatusPointer->incidentTimer < 0)
 
 
1150
    {
 
 
1151
        agunStatusPointer->incidentFlag = 1;
 
 
1152
        agunStatusPointer->incidentTimer = 32767+(FastRandom()&65535);
 
 
1153
    }
 
 
1154
 
 
 
1155
    /* Now, switch by state. */
 
 
1156
    switch (agunStatusPointer->behaviourState)
 
 
1157
    {
 
 
1158
        case I_inactive:
 
 
1159
            AGunMovement_Centre(sbPtr,2);
 
 
1160
            agunStatusPointer->Target = NULL;
 
 
1161
        break;
 
 
1162
        case I_tracking:
 
 
1163
            if (agunStatusPointer->Target == NULL)
 
 
1164
                AGunMovement_ScanLeftRight(sbPtr,2);
 
 
1165
            else
 
 
1166
                Execute_AGun_Target(sbPtr);
 
 
1167
        break;
 
 
1168
        case I_disabled:
 
 
1169
            /* Dying function. */
 
 
1170
            Execute_AGun_Dying(sbPtr);
 
 
1171
        break;
 
 
1172
        default:
 
 
1173
            /* No action? */
 
 
1174
            break;
 
 
1175
    }
 
 
1176
 
 
 
1177
    /* if we have actually died, we need to remove the strategyblock... so do this here */
 
 
1178
 
 
 
1179
    if((agunStatusPointer->behaviourState == I_disabled) && (agunStatusPointer->stateTimer <= 0))
 
 
1180
        sbPtr->please_destroy_me = 1;
 
 
1181
 
 
 
1182
    agunStatusPointer->WhirrSoundOn = 0;
 
 
1183
    AGun_ComputeDeltaValues(sbPtr);
 
 
1184
 
 
 
1185
    if (agunStatusPointer->WhirrSoundOn && (agunStatusPointer->behaviourState != I_disabled))
 
 
1186
    {
 
 
1187
        int dist = VectorDistance(&PlayerStatus.DisplayBlock->ObWorld, &sbPtr->DynPtr->Position);
 
 
1188
 
 
 
1189
        if (dist < SentryWhirr_SoundData.outer_range)
 
 
1190
        {
 
 
1191
            /* Play whirr sound.  Start and End sounds removed for artistic reasons. */
 
 
1192
 
 
 
1193
            if (agunStatusPointer->soundHandle2 == SOUND_NOACTIVEINDEX)
 
 
1194
            {
 
 
1195
                SentryWhirr_SoundData.position = sbPtr->DynPtr->Position;
 
 
1196
                //Sound_Play(SID_SENTRYTURN, "nel", &SentryWhirr_SoundData, &agunStatusPointer->soundHandle2);
 
 
1197
                Sound_Play(SID_SENTRYTURN, "edl", &agunStatusPointer->soundHandle2, &sbPtr->DynPtr->Position);
 
 
1198
            }
 
 
1199
            #if DEBUG
 
 
1200
            else
 
 
1201
            {
 
 
1202
                assert(ActiveSounds[agunStatusPointer->soundHandle2].soundIndex == SID_SENTRYTURN);
 
 
1203
            }
 
 
1204
            #endif
 
 
1205
        }
 
 
1206
        else
 
 
1207
        {
 
 
1208
            /* Stop whirr sound. */
 
 
1209
            if (agunStatusPointer->soundHandle2 != SOUND_NOACTIVEINDEX)
 
 
1210
                Sound_Stop(agunStatusPointer->soundHandle2);
 
 
1211
        }
 
 
1212
    }
 
 
1213
    else
 
 
1214
    {
 
 
1215
        /* Stop whirr sound. */
 
 
1216
        if (agunStatusPointer->soundHandle2 != SOUND_NOACTIVEINDEX)
 
 
1217
            Sound_Stop(agunStatusPointer->soundHandle2);
 
 
1218
    }
 
 
1219
 
 
 
1220
    /* Verify firing. */
 
 
1221
    if (agunStatusPointer->behaviourState == I_disabled)
 
 
1222
        agunStatusPointer->Firing = 0;
 
 
1223
 
 
 
1224
    ProveHModel_Far(&agunStatusPointer->HModelController, sbPtr);
 
 
1225
 
 
 
1226
    /* Now, are we firing? */
 
 
1227
 
 
 
1228
    if(!sbPtr->DisplayBlock)
 
 
1229
        agunStatusPointer->Firing = 0; // Just to be sure, for now.
 
 
1230
 
 
 
1231
    AGun_MaintainGun(sbPtr);
 
 
1232
 
 
 
1233
    /* Think sounds. */
 
 
1234
    if (!agunStatusPointer->Firing)
 
 
1235
    {
 
 
1236
        if (agunStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
1237
        {
 
 
1238
            if (ActiveSounds[agunStatusPointer->soundHandle].soundIndex == SID_SENTRY_GUN)
 
 
1239
                Sound_Play(SID_SENTRY_END, "d", &sbPtr->DynPtr->Position);
 
 
1240
 
 
 
1241
            Sound_Stop(agunStatusPointer->soundHandle);
 
 
1242
        }
 
 
1243
 
 
 
1244
        /* Sequences! */
 
 
1245
        if (agunStatusPointer->HModelController.Sub_Sequence != XBSS_Powered_Up_Standard)
 
 
1246
            InitHModelTweening(&agunStatusPointer->HModelController, (ONE_FIXED>>3), (int)HMSQT_Xenoborg, XBSS_Powered_Up_Standard, (ONE_FIXED),
1);
 
 
1247
    }
 
 
1248
    else
 
 
1249
    {
 
 
1250
        if (agunStatusPointer->HModelController.Sub_Sequence != XBSS_Fire_Bolter)
 
 
1251
            InitHModelTweening(&agunStatusPointer->HModelController, (ONE_FIXED>>3), (int)HMSQT_Xenoborg, XBSS_Fire_Bolter, (ONE_FIXED>>2),
1);
 
 
1252
    }
 
 
1253
 
 
 
1254
    if (agunStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
1255
        Sound_Update3d(agunStatusPointer->soundHandle, &sbPtr->DynPtr->Position);
 
 
1256
}
 
 
1257
 
 
 
1258
void SentryGunIsDamaged(STRATEGYBLOCK *sbPtr, const DAMAGE_PROFILE *damage, int multiple, int wounds,VECTORCH *incoming)
 
 
1259
{
 
 
1260
    if (sbPtr->DamageBlock.Health <= 0)
 
 
1261
    {
 
 
1262
        AUTOGUN_STATUS_BLOCK *agunStatusPointer = (AUTOGUN_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
1263
 
 
 
1264
        /* Oh yes, kill them, too. */
 
 
1265
 
 
 
1266
        if (agunStatusPointer->behaviourState != I_disabled)
 
 
1267
        {      
 
 
1268
            /* make an explosion sound */    
 
 
1269
            Sound_Play(SID_SENTRYGUNDEST, "d", &sbPtr->DynPtr->Position);  
 
 
1270
 
 
 
1271
            agunStatusPointer->stateTimer = AGUN_DYINGTIME;
 
 
1272
            agunStatusPointer->HModelController.Looped = 0;
 
 
1273
            agunStatusPointer->HModelController.LoopAfterTweening = 0;
 
 
1274
            /* switch state */
 
 
1275
            agunStatusPointer->behaviourState = I_disabled;
 
 
1276
 
 
 
1277
            if(agunStatusPointer->death_target_sbptr)
 
 
1278
                RequestState(agunStatusPointer->death_target_sbptr,agunStatusPointer->death_target_request, 0);
 
 
1279
 
 
 
1280
            if (agunStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
1281
                Sound_Stop(agunStatusPointer->soundHandle); // Well, it shouldn't be!
 
 
1282
        }
 
 
1283
    }
 
 
1284
}
 
 
1285
 
 
 
1286
/*--------------------**
 
 
1287
** Loading and Saving **
 
 
1288
**--------------------*/
 
 
1289
#include "savegame.h"
 
 
1290
 
 
 
1291
typedef struct agun_save_block
 
 
1292
{
 
 
1293
    SAVE_BLOCK_STRATEGY_HEADER header;
 
 
1294
 
 
 
1295
//behaviour block stuff
 
 
1296
    AG_STATE behaviourState;
 
 
1297
    int stateTimer;
 
 
1298
 
 
 
1299
    VECTORCH targetTrackPos;
 
 
1300
 
 
 
1301
    int Gun_Pan;
 
 
1302
    int Gun_Tilt;
 
 
1303
    int incidentFlag;
 
 
1304
    int incidentTimer;
 
 
1305
    int ammo;
 
 
1306
    int roundsFired;
 
 
1307
    int volleyFired;
 
 
1308
    int Firing;
 
 
1309
    int WhirrSoundOn;
 
 
1310
    int Drama;
 
 
1311
 
 
 
1312
      unsigned int createdByPlayer:1;
 
 
1313
    unsigned int gunpandir    :1;
 
 
1314
    unsigned int guntiltdir    :1;
 
 
1315
    unsigned int OnTarget    :1;
 
 
1316
    unsigned int OnTarget_LastFrame    :1;
 
 
1317
//annoying pointer related things
 
 
1318
 
 
 
1319
    char Target_SBname[SB_NAME_LENGTH];
 
 
1320
 
 
 
1321
//strategy block stuff
 
 
1322
    DAMAGEBLOCK DamageBlock;
 
 
1323
    DYNAMICSBLOCK dynamics;
 
 
1324
 
 
 
1325
} AGUN_SAVE_BLOCK;
 
 
1326
 
 
 
1327
//defines for load/save macros
 
 
1328
#define SAVELOAD_BLOCK block
 
 
1329
#define SAVELOAD_BEHAV agunStatusPointer
 
 
1330
 
 
 
1331
void LoadStrategy_Autogun(SAVE_BLOCK_STRATEGY_HEADER* header)
 
 
1332
{
 
 
1333
    AGUN_SAVE_BLOCK* block = (AGUN_SAVE_BLOCK*) header; 
 
 
1334
 
 
 
1335
    //check the size of the save block
 
 
1336
    if(header->size != sizeof(*block))
 
 
1337
        return;
 
 
1338
 
 
 
1339
    //find the existing strategy block
 
 
1340
    STRATEGYBLOCK* sbPtr = FindSBWithName(header->SBname);
 
 
1341
 
 
 
1342
    if(!sbPtr)
 
 
1343
        return;
 
 
1344
 
 
 
1345
    //make sure the strategy found is of the right type
 
 
1346
    if(sbPtr->type != I_BehaviourAutoGun)
 
 
1347
        return;
 
 
1348
 
 
 
1349
    AUTOGUN_STATUS_BLOCK* agunStatusPointer = (AUTOGUN_STATUS_BLOCK*) sbPtr->dataptr;
 
 
1350
 
 
 
1351
    //start copying stuff
 
 
1352
    COPYELEMENT_LOAD(behaviourState)
 
 
1353
    COPYELEMENT_LOAD(stateTimer)
 
 
1354
    COPYELEMENT_LOAD(targetTrackPos)
 
 
1355
    COPYELEMENT_LOAD(Gun_Pan)
 
 
1356
    COPYELEMENT_LOAD(Gun_Tilt)
 
 
1357
    COPYELEMENT_LOAD(incidentFlag)
 
 
1358
    COPYELEMENT_LOAD(incidentTimer)
 
 
1359
    COPYELEMENT_LOAD(ammo)
 
 
1360
    COPYELEMENT_LOAD(roundsFired)
 
 
1361
    COPYELEMENT_LOAD(volleyFired)
 
 
1362
    COPYELEMENT_LOAD(Firing)
 
 
1363
    COPYELEMENT_LOAD(WhirrSoundOn)
 
 
1364
    COPYELEMENT_LOAD(Drama)
 
 
1365
    COPYELEMENT_LOAD(createdByPlayer)
 
 
1366
    COPYELEMENT_LOAD(gunpandir)
 
 
1367
    COPYELEMENT_LOAD(guntiltdir)
 
 
1368
    COPYELEMENT_LOAD(OnTarget)
 
 
1369
    COPYELEMENT_LOAD(OnTarget_LastFrame)
 
 
1370
 
 
 
1371
    //load target
 
 
1372
    COPY_NAME(agunStatusPointer->Target_SBname,block->Target_SBname);
 
 
1373
    agunStatusPointer->Target = FindSBWithName(agunStatusPointer->Target_SBname);
 
 
1374
 
 
 
1375
    //copy strategy block stuff
 
 
1376
    *sbPtr->DynPtr = block->dynamics;
 
 
1377
    sbPtr->DamageBlock = block->DamageBlock;
 
 
1378
 
 
 
1379
    //load hierarchy
 
 
1380
    {
 
 
1381
        SAVE_BLOCK_HEADER* hier_header = GetNextBlockIfOfType(SaveBlock_Hierarchy);
 
 
1382
 
 
 
1383
        if(hier_header)
 
 
1384
            LoadHierarchy(hier_header,&agunStatusPointer->HModelController);
 
 
1385
    }
 
 
1386
 
 
 
1387
    //get delta controller pointers
 
 
1388
    Autogun_VerifyDeltaControllers(sbPtr);
 
 
1389
 
 
 
1390
    Load_SoundState(&agunStatusPointer->soundHandle);
 
 
1391
    Load_SoundState(&agunStatusPointer->soundHandle2);
 
 
1392
}
 
 
1393
 
 
 
1394
void SaveStrategy_Autogun(STRATEGYBLOCK* sbPtr)
 
 
1395
{
 
 
1396
    AUTOGUN_STATUS_BLOCK* agunStatusPointer;
 
 
1397
    AGUN_SAVE_BLOCK* block;
 
 
1398
 
 
 
1399
    GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
 
 
1400
    agunStatusPointer =(AUTOGUN_STATUS_BLOCK*) sbPtr->dataptr;
 
 
1401
 
 
 
1402
    //start copying stuff
 
 
1403
    COPYELEMENT_SAVE(behaviourState)
 
 
1404
    COPYELEMENT_SAVE(stateTimer)
 
 
1405
    COPYELEMENT_SAVE(targetTrackPos)
 
 
1406
    COPYELEMENT_SAVE(Gun_Pan)
 
 
1407
    COPYELEMENT_SAVE(Gun_Tilt)
 
 
1408
    COPYELEMENT_SAVE(incidentFlag)
 
 
1409
    COPYELEMENT_SAVE(incidentTimer)
 
 
1410
    COPYELEMENT_SAVE(ammo)
 
 
1411
    COPYELEMENT_SAVE(roundsFired)
 
 
1412
    COPYELEMENT_SAVE(volleyFired)
 
 
1413
    COPYELEMENT_SAVE(Firing)
 
 
1414
    COPYELEMENT_SAVE(WhirrSoundOn)
 
 
1415
    COPYELEMENT_SAVE(Drama)
 
 
1416
    COPYELEMENT_SAVE(createdByPlayer)
 
 
1417
    COPYELEMENT_SAVE(gunpandir)
 
 
1418
    COPYELEMENT_SAVE(guntiltdir)
 
 
1419
    COPYELEMENT_SAVE(OnTarget)
 
 
1420
    COPYELEMENT_SAVE(OnTarget_LastFrame)
 
 
1421
 
 
 
1422
    //save target
 
 
1423
    COPY_NAME(block->Target_SBname,agunStatusPointer->Target_SBname);
 
 
1424
 
 
 
1425
    //save strategy block stuff
 
 
1426
    block->dynamics = *sbPtr->DynPtr;
 
 
1427
    block->dynamics.CollisionReportPtr = NULL;
 
 
1428
    block->DamageBlock = sbPtr->DamageBlock;
 
 
1429
 
 
 
1430
    //save the hierarchy
 
 
1431
    SaveHierarchy(&agunStatusPointer->HModelController);
 
 
1432
 
 
 
1433
    Save_SoundState(&agunStatusPointer->soundHandle);
 
 
1434
    Save_SoundState(&agunStatusPointer->soundHandle2);
 
 
1435
}