4b825dc642cb6eb9a060e54bf8d69288fbee490494a6641b73026d662261604d7d192beae70b11dc
 
 
1
#include "system.h"
 
 
2
#include "prototyp.h"
 
 
3
#include "stratdef.h"
 
 
4
#include "bh_types.h"
 
 
5
#include "lighting.h"
 
 
6
#include "pfarlocs.h"
 
 
7
#include "pheromon.h"
 
 
8
#include "generator.h"
 
 
9
#include "bh_ais.h"
 
 
10
#include "bh_far.h"
 
 
11
#include "npc_marine.h"
 
 
12
#include "debris.h"
 
 
13
#include "npc_alien.h"
 
 
14
#include "weapons.h"
 
 
15
#include "weaponbehaviour.h"
 
 
16
#include "hud.h"
 
 
17
#include "pldghost.h"
 
 
18
#include "psndplat.h"
 
 
19
#include "los.h"
 
 
20
#include "corpse.h"
 
 
21
#include "npc_dummy.h"
 
 
22
#include "scream.h"
 
 
23
#include "targeting.h"
 
 
24
#include "extents.h"
 
 
25
#include "userprofile.h"
 
 
26
#include <assert.h>
 
 
27
#include <stdio.h>
 
 
28
 
 
 
29
extern void EnableBehaviourType(STRATEGYBLOCK* sbptr, void *bhdata);
 
 
30
 
 
 
31
#define FLARE_COUNTER (ONE_FIXED * 20)
 
 
32
#define ALL_PULSERIFLES 0
 
 
33
#define ANARCHY 0
 
 
34
#define PISTOL_CLIP_SIZE 12
 
 
35
#define SENTRY_SENSITIVITY 1500
 
 
36
#define MARINE_AUTODETECT_ALIEN 2500
 
 
37
#define MARINE_AUTODETECT_CLOAKED_PREDATOR 7000
 
 
38
 
 
 
39
#define SUSPECT_SENSITIVITY 2100
 
 
40
/* Ten centimetres.  It can make a lot of difference. */
 
 
41
 
 
 
42
#define ALL_NEW_AVOIDANCE    (1)
 
 
43
 
 
 
44
/* external global variables used in this file */
 
 
45
extern int ModuleArraySize;
 
 
46
extern uint8_t Null_Name[8];
 
 
47
extern const VECTORCH null_vec;
 
 
48
 
 
 
49
extern HIERARCHY_VARIANT_DATA* GetHierarchyAlternateShapeSetCollectionFromLibrary(const char* rif_name,int collection_index);
 
 
50
extern SECTION * GetNamedHierarchyFromLibrary(const char * rif_name, const char * hier_name);
 
 
51
extern int LightIntensityAtPoint(VECTORCH *pointPtr);
 
 
52
 
 
 
53
int Marine_Terminal_Velocity = 20000;
 
 
54
static const MARINE_WEAPON_DATA NPC_Marine_Weapons[MNPCW_End];
 
 
55
 
 
 
56
static const VECTORCH ShotgunBlast[] =
 
 
57
{
 
 
58
    {0,0,400,},
 
 
59
    {100,0,400,},
 
 
60
    {-100,0,400,},
 
 
61
    {50,0,400,},
 
 
62
    {-50,0,400,},
 
 
63
    {-1,-1,-1,},
 
 
64
};
 
 
65
 
 
 
66
SQUAD_COMMAND_STATE NpcSquad;
 
 
67
 
 
 
68
#define MARINE_PRINT_STATE 0
 
 
69
 
 
 
70
static void Marine_SwitchExpression(STRATEGYBLOCK *sbPtr,int state) 
 
 
71
{
 
 
72
    assert(sbPtr);
 
 
73
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
74
    assert(marineStatusPointer);
 
 
75
 
 
 
76
    SECTION_DATA *head = GetThisSectionData(marineStatusPointer->HModelController.section_data, "head");
 
 
77
 
 
 
78
    marineStatusPointer->Expression = state;
 
 
79
    marineStatusPointer->Blink = -1;
 
 
80
 
 
 
81
    if (head && !(head->flags & section_data_notreal))
 
 
82
    {
 
 
83
        TXACTRLBLK *tacb = head->tac_ptr;
 
 
84
 
 
 
85
        while (tacb)
 
 
86
        {
 
 
87
            tacb->tac_sequence = state ;
 
 
88
            tacb->tac_txah_s = GetTxAnimHeaderFromShape(tacb, head->ShapeNum);
 
 
89
            tacb = tacb->tac_next;
 
 
90
        }
 
 
91
    }
 
 
92
}
 
 
93
 
 
 
94
static int make_new_marine(STRATEGYBLOCK* sbPtr, MARINE_NPC_WEAPONS its_weapon)
 
 
95
{
 
 
96
    sbPtr->dataptr = malloc(sizeof(MARINE_STATUS_BLOCK));
 
 
97
    sbPtr->maintainVisibility = 1;
 
 
98
    sbPtr->containingModule = ModuleFromPosition(&sbPtr->DynPtr->Position, NULL);
 
 
99
 
 
 
100
    if (NULL == sbPtr->dataptr)
 
 
101
    {
 
 
102
        RemoveBehaviourStrategy(sbPtr);
 
 
103
        return 0;
 
 
104
    }
 
 
105
 
 
 
106
    MARINE_STATUS_BLOCK *new_marine = (MARINE_STATUS_BLOCK *)sbPtr->dataptr;
 
 
107
 
 
 
108
    NPC_InitMovementData(&new_marine->moveData);
 
 
109
    NPC_InitWanderData(&new_marine->wanderData);
 
 
110
 
 
 
111
    Initialise_AvoidanceManager(&new_marine->avoidanceManager);
 
 
112
    InitWaypointManager(&new_marine->waypointManager);
 
 
113
 
 
 
114
    new_marine->volleySize = 0;
 
 
115
 
 
 
116
    new_marine->behaviourState = MBS_Waiting;
 
 
117
    new_marine->lastState = MBS_Waiting;
 
 
118
 
 
 
119
    new_marine->Target = NULL;
 
 
120
    COPY_NAME(new_marine->Target_SBname, Null_Name);
 
 
121
 
 
 
122
    {
 
 
123
        int i = 0;
 
 
124
        for(; i < SB_NAME_LENGTH; i++)
 
 
125
            new_marine->death_target_ID[i] = 0; 
 
 
126
    }
 
 
127
 
 
 
128
    new_marine->HModelController.Deltas = NULL;
 
 
129
    new_marine->HModelController.Root_Section = NULL;
 
 
130
    new_marine->HModelController.section_data = NULL;
 
 
131
    new_marine->death_target_sbptr = NULL;
 
 
132
    new_marine->death_target_request = 0;
 
 
133
    new_marine->generator_sbptr = NULL;
 
 
134
    new_marine->lastmodule = NULL;
 
 
135
    new_marine->destinationmodule = NULL;
 
 
136
    new_marine->missionmodule = NULL;
 
 
137
    new_marine->fearmodule = NULL;
 
 
138
    new_marine->my_spot.vx = 0;
 
 
139
    new_marine->my_spot.vy = 0;
 
 
140
    new_marine->my_spot.vz = 0;
 
 
141
    new_marine->my_facing_point.vx = 0;
 
 
142
    new_marine->my_facing_point.vy = 0;
 
 
143
    new_marine->my_facing_point.vz = 0;
 
 
144
    new_marine->nearSpeed = MARINE_NEAR_SPEED;
 
 
145
    new_marine->acceleration = 0;
 
 
146
    new_marine->speedConstant = 0;
 
 
147
    new_marine->accelerationConstant = 0;
 
 
148
    new_marine->suspect_point.vx = 0;
 
 
149
    new_marine->suspect_point.vy = 0;
 
 
150
    new_marine->suspect_point.vz = 0;
 
 
151
    new_marine->suspicious = 0;
 
 
152
    new_marine->previous_suspicion = 0;
 
 
153
    new_marine->using_squad_suspicion = 0;
 
 
154
    new_marine->gotapoint = 0;
 
 
155
    new_marine->lastframe_fallingspeed = 0;
 
 
156
    new_marine->path = -1;
 
 
157
    new_marine->stepnumber = -1;
 
 
158
    new_marine->stateTimer = MARINE_FAR_MOVE_TIME;
 
 
159
    new_marine->internalState = 0;
 
 
160
    new_marine->weaponTarget.vx = 0;
 
 
161
    new_marine->weaponTarget.vy = 0;
 
 
162
    new_marine->weaponTarget.vz = 0;
 
 
163
    new_marine->myGunFlash = NULL;
 
 
164
    new_marine->soundHandle = SOUND_NOACTIVEINDEX;
 
 
165
    new_marine->soundHandle2 = SOUND_NOACTIVEINDEX;
 
 
166
    new_marine->obstruction.environment = 0;
 
 
167
    new_marine->obstruction.destructableObject = 0;
 
 
168
    new_marine->obstruction.otherCharacter = 0;
 
 
169
    new_marine->obstruction.anySingleObstruction = 0;
 
 
170
    new_marine->IAmCrouched = 0;
 
 
171
 
 
 
172
    #if ALL_PULSERIFLES
 
 
173
        new_marine->My_Weapon = &NPC_Marine_Weapons[MNPCW_PulseRifle];
 
 
174
    #else
 
 
175
        new_marine->My_Weapon = &NPC_Marine_Weapons[its_weapon];
 
 
176
    #endif
 
 
177
 
 
 
178
    new_marine->My_Gunflash_Section = NULL;
 
 
179
    new_marine->My_Elevation_Section = NULL;
 
 
180
    new_marine->lastroundhit = 0;
 
 
181
    new_marine->lasthitsection = NULL;
 
 
182
    new_marine->GibbFactor = 0;
 
 
183
    new_marine->Wounds = 0;
 
 
184
 
 
 
185
    new_marine->incidentFlag = 0;
 
 
186
    new_marine->incidentTimer = 0;
 
 
187
 
 
 
188
    new_marine->weapon_variable = 0;
 
 
189
    new_marine->weapon_variable2 = 0;
 
 
190
    new_marine->clipammo = 0;
 
 
191
    new_marine->roundsForThisTarget = 0;
 
 
192
 
 
 
193
    new_marine->Female = 0;
 
 
194
    new_marine->Android = 0;
 
 
195
    new_marine->Skill = ONE_FIXED;
 
 
196
    new_marine->Courage = ONE_FIXED;
 
 
197
    new_marine->Voice = 0;
 
 
198
    new_marine->VoicePitch = (FastRandom() & 255) - 128;
 
 
199
 
 
 
200
    new_marine->FiringAnim = 0;
 
 
201
    new_marine->Expression = 0;
 
 
202
    new_marine->Target_Expression = 0;
 
 
203
    new_marine->Blink = -1;
 
 
204
    new_marine->SpotFlag = 0;
 
 
205
    new_marine->FlareActive = 0;
 
 
206
 
 
 
207
    {
 
 
208
        const MOVEMENT_DATA *movementData;
 
 
209
 
 
 
210
        new_marine->speedConstant = (ONE_FIXED - 8192) + (FastRandom() & 16383);
 
 
211
        new_marine->accelerationConstant = (ONE_FIXED - 8192) + (FastRandom() & 16383);
 
 
212
 
 
 
213
        if (new_marine->My_Weapon->ARealMarine)
 
 
214
            movementData = GetThisMovementData(MDI_Marine_Combat);
 
 
215
        else
 
 
216
            movementData = GetThisMovementData(MDI_Civilian_Combat);
 
 
217
 
 
 
218
        assert(movementData);
 
 
219
        new_marine->nearSpeed = MUL_FIXED(movementData->maxSpeed, new_marine->speedConstant);
 
 
220
        new_marine->acceleration = MUL_FIXED(movementData->acceleration, new_marine->accelerationConstant);
 
 
221
    }
 
 
222
 
 
 
223
    SECTION *root_section = GetNamedHierarchyFromLibrary(new_marine->My_Weapon->Riffname, new_marine->My_Weapon->HierarchyName);
 
 
224
 
 
 
225
    if (!root_section || !sbPtr->containingModule)
 
 
226
    {
 
 
227
        RemoveBehaviourStrategy(sbPtr);
 
 
228
        return 0;
 
 
229
    }
 
 
230
 
 
 
231
    Create_HModel(&new_marine->HModelController, root_section);
 
 
232
    InitHModelSequence(&new_marine->HModelController, (int)HMSQT_MarineRun, (int)MRSS_Standard, ONE_FIXED);
 
 
233
 
 
 
234
    if (new_marine->My_Weapon->UseElevation)
 
 
235
    {
 
 
236
        DELTA_CONTROLLER *delta = Add_Delta_Sequence(&new_marine->HModelController, "Elevation", (int)HMSQT_MarineStand, (int)MSSS_Elevation,
0);
 
 
237
        assert(delta);
 
 
238
        delta->timer = 32767;
 
 
239
    }
 
 
240
 
 
 
241
    if (new_marine->My_Weapon->id == MNPCW_Minigun)
 
 
242
    {
 
 
243
        DELTA_CONTROLLER *delta = Add_Delta_Sequence(&new_marine->HModelController, "Minigun", (int)HMSQT_MarineStand, (int)MSSS_Minigun_Delta,
(ONE_FIXED>>3));
 
 
244
        assert(delta);
 
 
245
        delta->Playing = 0;
 
 
246
        delta->Looped = 1;
 
 
247
    }
 
 
248
    else if (new_marine->My_Weapon->id == MNPCW_MPistol)
 
 
249
    {
 
 
250
        /* Special case for pistols? */
 
 
251
        new_marine->lastroundhit = PISTOL_CLIP_SIZE;
 
 
252
    }
 
 
253
 
 
 
254
    /* Create blank hit delta sequence. */
 
 
255
    if (!strcmp("hnpcmarine", new_marine->My_Weapon->Riffname) && HModelSequence_Exists(&new_marine->HModelController,
(int)HMSQT_MarineStand, (int)MSSS_HitChestFront))
 
 
256
    {
 
 
257
        DELTA_CONTROLLER *delta = Add_Delta_Sequence(&new_marine->HModelController, "HitDelta", (int)HMSQT_MarineStand,
(int)MSSS_HitChestFront, (ONE_FIXED>>2));
 
 
258
        assert(delta);
 
 
259
        delta->Playing = 0;
 
 
260
    }
 
 
261
 
 
 
262
    if(new_marine->My_Weapon->GunflashName)
 
 
263
    new_marine->My_Gunflash_Section = GetThisSectionData(new_marine->HModelController.section_data, new_marine->My_Weapon->GunflashName);
 
 
264
 
 
 
265
    if(new_marine->My_Weapon->ElevationSection)
 
 
266
    new_marine->My_Elevation_Section = GetThisSectionData(new_marine->HModelController.section_data, new_marine->My_Weapon->ElevationSection);
 
 
267
 
 
 
268
    new_marine->Android = new_marine->My_Weapon->Android;
 
 
269
 
 
 
270
    ProveHModel_Far(&new_marine->HModelController, sbPtr);
 
 
271
 
 
 
272
    new_marine->clipammo = new_marine->My_Weapon->clip_size;
 
 
273
 
 
 
274
    {
 
 
275
        const NPC_DATA *NpcData;
 
 
276
 
 
 
277
        if (new_marine->My_Weapon->Android)
 
 
278
        {
 
 
279
            NpcData = &NpcDataList[I_NPC_Android];
 
 
280
        }
 
 
281
        else if (new_marine->My_Weapon->ARealMarine)
 
 
282
        {
 
 
283
            NpcData = &NpcDataList[I_NPC_Marine];
 
 
284
        }
 
 
285
        else
 
 
286
        {
 
 
287
            NpcData = &NpcDataList[I_NPC_Civilian];
 
 
288
        }
 
 
289
 
 
 
290
        sbPtr->DamageBlock = NpcData->StartingStats;
 
 
291
        sbPtr->DamageBlock.Health = NpcData->StartingStats.Health << ONE_FIXED_SHIFT;
 
 
292
        sbPtr->DamageBlock.Armour = NpcData->StartingStats.Armour << ONE_FIXED_SHIFT;
 
 
293
    }
 
 
294
 
 
 
295
    Marine_SwitchExpression(sbPtr, 0);
 
 
296
 
 
 
297
return 1;
 
 
298
}
 
 
299
 
 
 
300
void InitSquad() 
 
 
301
{
 
 
302
    NpcSquad.alertStatus = 0;
 
 
303
    NpcSquad.responseLevel = 0;
 
 
304
    NpcSquad.alertZone = NULL;
 
 
305
    NpcSquad.alertPriority = 0;
 
 
306
    NpcSquad.Squad_Suspicion = 0;
 
 
307
    NpcSquad.squad_suspect_point.vx = 0;
 
 
308
    NpcSquad.squad_suspect_point.vy = 0;
 
 
309
    NpcSquad.squad_suspect_point.vz = 0;
 
 
310
    NpcSquad.RespondingMarines = 0;
 
 
311
    NpcSquad.Alt_RespondingMarines = 0;
 
 
312
    NpcSquad.NearUnpanickedMarines = 0;
 
 
313
    NpcSquad.Alt_NearUnpanickedMarines = 0;
 
 
314
    NpcSquad.NearPanickedMarines = 0;
 
 
315
    NpcSquad.Alt_NearPanickedMarines = 0;
 
 
316
    NpcSquad.NearBurningMarines = 0;
 
 
317
    NpcSquad.Alt_NearBurningMarines = 0;
 
 
318
    NpcSquad.Squad_Delta_Morale = 0;
 
 
319
    NpcSquad.Nextframe_Squad_Delta_Morale = 0;
 
 
320
}
 
 
321
 
 
 
322
void DoSquad()
 
 
323
{
 
 
324
    /* Maintain squad level stuff. */
 
 
325
 
 
 
326
    if (NpcSquad.alertZone != NULL)
 
 
327
        MaintainMarineTargetZone(NpcSquad.alertZone);
 
 
328
 
 
 
329
    /* Maintain squad suspicion. */
 
 
330
    if (NpcSquad.Squad_Suspicion > 0)
 
 
331
    {
 
 
332
        NpcSquad.Squad_Suspicion -= NormalFrameTime;
 
 
333
 
 
 
334
        if (NpcSquad.Squad_Suspicion < 0)
 
 
335
            NpcSquad.Squad_Suspicion = 0;
 
 
336
    }
 
 
337
 
 
 
338
    /* Maintain stats. */
 
 
339
    NpcSquad.RespondingMarines = NpcSquad.Alt_RespondingMarines;
 
 
340
    NpcSquad.Alt_RespondingMarines = 0;
 
 
341
 
 
 
342
    NpcSquad.NearUnpanickedMarines = NpcSquad.Alt_NearUnpanickedMarines;
 
 
343
    NpcSquad.Alt_NearUnpanickedMarines = 0;
 
 
344
 
 
 
345
    NpcSquad.NearPanickedMarines = NpcSquad.Alt_NearPanickedMarines;
 
 
346
    NpcSquad.Alt_NearPanickedMarines = 0;
 
 
347
 
 
 
348
    NpcSquad.NearBurningMarines = NpcSquad.Alt_NearBurningMarines;
 
 
349
    NpcSquad.Alt_NearBurningMarines = 0;
 
 
350
 
 
 
351
    NpcSquad.Squad_Delta_Morale = NpcSquad.Nextframe_Squad_Delta_Morale;
 
 
352
    NpcSquad.Nextframe_Squad_Delta_Morale = 0;
 
 
353
 
 
 
354
    /* Update morale. */
 
 
355
    NpcSquad.Nextframe_Squad_Delta_Morale += MUL_FIXED(NormalFrameTime, (NpcSquad.NearUnpanickedMarines*50));
 
 
356
    NpcSquad.Nextframe_Squad_Delta_Morale -= MUL_FIXED(NormalFrameTime, (NpcSquad.NearPanickedMarines*1000));
 
 
357
    NpcSquad.Nextframe_Squad_Delta_Morale -= MUL_FIXED(NormalFrameTime, (NpcSquad.NearBurningMarines*3000));
 
 
358
 
 
 
359
    if (CHEATMODE_TERROR == UserProfile.active_bonus)
 
 
360
        NpcSquad.Nextframe_Squad_Delta_Morale = -100000000;
 
 
361
 
 
 
362
    #if MARINE_PRINT_STATE
 
 
363
    {
 
 
364
        printf("Marine Alert Status = %d\n", NpcSquad.alertStatus);
 
 
365
        printf("Marine Alert Priority = %d\n", NpcSquad.alertPriority);
 
 
366
        printf("Responding Marines = %d\n", NpcSquad.RespondingMarines);
 
 
367
        printf("NearPanicked Marines = %d\n", NpcSquad.NearPanickedMarines);
 
 
368
        printf("NearUnpanicked Marines = %d\n", NpcSquad.NearUnpanickedMarines);
 
 
369
        printf("NearBurning Marines = %d\n", NpcSquad.NearBurningMarines);
 
 
370
        printf("Marine Outstanding Response Level = %d\n", NpcSquad.responseLevel);
 
 
371
 
 
 
372
        if (NpcSquad.alertZone == NULL)
 
 
373
        {
 
 
374
            printf("Marine Alert Zone = NULL\n");
 
 
375
        }
 
 
376
        else
 
 
377
        {
 
 
378
            MODULE *sampleModule = *(NpcSquad.alertZone->m_module_ptrs);
 
 
379
 
 
 
380
            if (sampleModule == NULL)
 
 
381
                printf("Marine Alert Zone = Totally Farped! %d\n",NpcSquad.alertZone->m_index);
 
 
382
            else
 
 
383
                printf("Marine Alert Zone = %d, '%s'\n",sampleModule->m_index,sampleModule->name);
 
 
384
        }
 
 
385
        printf("Squad Suspicion = %d\n",NpcSquad.Squad_Suspicion);
 
 
386
        printf("Squad Suspect Point = %d %d %d\n",NpcSquad.squad_suspect_point.vx,
 
 
387
        NpcSquad.squad_suspect_point.vy,NpcSquad.squad_suspect_point.vz);
 
 
388
    }
 
 
389
    #endif
 
 
390
}
 
 
391
 
 
 
392
void ZoneAlert(int level,AIMODULE *targetModule)
 
 
393
{
 
 
394
    int idealResponse;    
 
 
395
    /* Bad stuff is going down. */
 
 
396
 
 
 
397
    /* Switch to this one if it has a higher level than the current priority. */
 
 
398
 
 
 
399
    if (level < NpcSquad.alertPriority)
 
 
400
        return; /* Don't bother me with trifles! */
 
 
401
 
 
 
402
    if (level >= NpcSquad.alertStatus)
 
 
403
        NpcSquad.alertStatus = level;
 
 
404
 
 
 
405
    NpcSquad.alertPriority = level;
 
 
406
    NpcSquad.alertZone = targetModule;
 
 
407
 
 
 
408
    switch (NpcSquad.alertStatus)
 
 
409
    {
 
 
410
        case 0:
 
 
411
            /* Can this ever happen? */
 
 
412
            idealResponse = 1;
 
 
413
            break;
 
 
414
        case 1:
 
 
415
            idealResponse = 1;
 
 
416
            break;
 
 
417
        case 2:
 
 
418
            idealResponse = 3;
 
 
419
            break;
 
 
420
        case 3:
 
 
421
            idealResponse = 5;
 
 
422
            break;
 
 
423
        default:
 
 
424
            idealResponse = 1;
 
 
425
            break;
 
 
426
    }
 
 
427
 
 
 
428
    if (NpcSquad.RespondingMarines < idealResponse)
 
 
429
        NpcSquad.responseLevel = idealResponse - NpcSquad.RespondingMarines;
 
 
430
}
 
 
431
 
 
 
432
void PointAlert(int level, VECTORCH *point)
 
 
433
{
 
 
434
    MODULE *alertModule = ModuleFromPosition(point, PlayerStatus.sbptr->containingModule);
 
 
435
 
 
 
436
    if (NpcSquad.Squad_Suspicion != SQUAD_PARANOIA_TIME)
 
 
437
    {
 
 
438
        NpcSquad.Squad_Suspicion = SQUAD_PARANOIA_TIME;
 
 
439
        NpcSquad.squad_suspect_point = *point;
 
 
440
    }
 
 
441
 
 
 
442
    if (alertModule != NULL)
 
 
443
        ZoneAlert(level, alertModule->m_aimodule);
 
 
444
}
 
 
445
 
 
 
446
void DeprioritiseAlert(AIMODULE *aimodule)
 
 
447
{
 
 
448
    /* Parameterised, to make sure we're doing it right. */
 
 
449
 
 
 
450
    if (aimodule == NpcSquad.alertZone)
 
 
451
        NpcSquad.alertPriority = 0;
 
 
452
}
 
 
453
 
 
 
454
void Console_ZoneAlert()
 
 
455
{
 
 
456
/*
 
 
457
    extern SCENEMODULE MainScene;
 
 
458
    //MODULE *target = PlayerStatus.sbptr->containingModule;
 
 
459
 
 
 
460
    if (!input || (input >= ModuleArraySize))
 
 
461
        target = PlayerStatus.sbptr->containingModule;
 
 
462
    else
 
 
463
        target = MainScene.sm_marray[input];    
 
 
464
*/
 
 
465
    //static char tempstring[256];
 
 
466
    //sprintf(tempstring, "NEW ZONE ALERT IN %d, '%s'\n", target->m_index,target->name);
 
 
467
    //GADGET_NewOnScreenMessage(tempstring);
 
 
468
 
 
 
469
    if(PlayerStatus.sbptr->containingModule)
 
 
470
        ZoneAlert(3, PlayerStatus.sbptr->containingModule->m_aimodule);
 
 
471
}
 
 
472
 
 
 
473
static void ChangeToAlternateAccoutrementSet(STRATEGYBLOCK *sbPtr, int index)
 
 
474
{
 
 
475
    assert(sbPtr);
 
 
476
 
 
 
477
    int a = 0;
 
 
478
 
 
 
479
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
480
    assert(marineStatusPointer);
 
 
481
 
 
 
482
    HIERARCHY_VARIANT_DATA* variant_data = GetHierarchyAlternateShapeSetCollectionFromLibrary(marineStatusPointer->My_Weapon->Riffname, index);
 
 
483
 
 
 
484
    if (variant_data == NULL)
 
 
485
        return;
 
 
486
 
 
 
487
    marineStatusPointer->Female = variant_data->female;
 
 
488
    marineStatusPointer->Voice = variant_data->voice;
 
 
489
 
 
 
490
    HIERARCHY_SHAPE_REPLACEMENT* replacement_array = (HIERARCHY_SHAPE_REPLACEMENT*)variant_data->replacements;
 
 
491
 
 
 
492
    if (replacement_array == NULL)
 
 
493
        return;
 
 
494
 
 
 
495
    while (replacement_array[a].replaced_section_name != NULL)
 
 
496
    {
 
 
497
        SECTION_DATA *target_section = GetThisSectionData(marineStatusPointer->HModelController.section_data, replacement_array[a].replaced_section_name);
 
 
498
 
 
 
499
        if (target_section)
 
 
500
        {
 
 
501
            target_section->Shape = replacement_array[a].replacement_shape;
 
 
502
            target_section->ShapeNum= replacement_array[a].replacement_shape_index;
 
 
503
            target_section->replacement_id = replacement_array[a].replacement_id;
 
 
504
            Setup_Texture_Animation_For_Section(target_section);
 
 
505
        }
 
 
506
        a++;
 
 
507
    }
 
 
508
}
 
 
509
 
 
 
510
static void SetMarineAnimationSequence(STRATEGYBLOCK *sbPtr,HMODEL_SEQUENCE_TYPES type, int subtype, int length, int tweening)
 
 
511
{
 
 
512
    assert(sbPtr);
 
 
513
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
514
    assert(marineStatusPointer);
 
 
515
 
 
 
516
    assert(length != 0);
 
 
517
 
 
 
518
    if (tweening <= 0)
 
 
519
        InitHModelSequence(&marineStatusPointer->HModelController,(int)type,subtype,length);
 
 
520
    else
 
 
521
        InitHModelTweening(&marineStatusPointer->HModelController, tweening, (int)type,subtype,length, 1);
 
 
522
 
 
 
523
    ProveHModel_Far(&marineStatusPointer->HModelController,sbPtr);
 
 
524
}
 
 
525
 
 
 
526
static int MarineShouldBeCrawling(STRATEGYBLOCK *sbPtr)
 
 
527
{
 
 
528
    return (sbPtr->containingModule->m_flags & MODULEFLAG_AIRDUCT);
 
 
529
}
 
 
530
 
 
 
531
static void HandleFidgetAnimations(STRATEGYBLOCK *sbPtr) 
 
 
532
{
 
 
533
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
534
 
 
 
535
    /* A sub function for simplicity. */
 
 
536
 
 
 
537
    int no_fidget = 0;
 
 
538
    switch(marineStatusPointer->HModelController.Sub_Sequence)
 
 
539
    {
 
 
540
        case MSSS_Stand_To_Fidget:
 
 
541
        case MSSS_Fidget_A:
 
 
542
        case MSSS_Fidget_B:
 
 
543
        case MSSS_Fidget_C:
 
 
544
        break;
 
 
545
        default:
 
 
546
        no_fidget = 1;
 
 
547
    }
 
 
548
 
 
 
549
    /* Are we in some sort of fidget anim? */
 
 
550
    if ((marineStatusPointer->HModelController.Sequence_Type != HMSQT_MarineStand) || no_fidget)
 
 
551
    {
 
 
552
        if ((marineStatusPointer->HModelController.Sequence_Type == HMSQT_MarineRun) && (marineStatusPointer->HModelController.Sub_Sequence ==
MRSS_Mooch_Bored))
 
 
553
        {
 
 
554
            /* Mooch bored does not require Stand_To_Fidget - go directly to Fidget_A. */
 
 
555
            if (HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,(int)MSSS_Fidget_A))
 
 
556
            {
 
 
557
                SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_Fidget_A, ONE_FIXED<<3, (ONE_FIXED>>3));
 
 
558
                marineStatusPointer->internalState = 0;
 
 
559
            }
 
 
560
            else
 
 
561
            {
 
 
562
                /* No fidgets at all! */
 
 
563
                SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_Standard, ONE_FIXED, (ONE_FIXED>>3));
 
 
564
            }
 
 
565
        }
 
 
566
        else if (HModelSequence_Exists(&marineStatusPointer->HModelController, (int)HMSQT_MarineStand, (int)MSSS_Stand_To_Fidget))
 
 
567
        {
 
 
568
            /* Not in any kind of fidget anim: run Stand_To_Fidget if poss. */
 
 
569
            SetMarineAnimationSequence(sbPtr,HMSQT_MarineStand,MSSS_Stand_To_Fidget,((ONE_FIXED*3)/2),(ONE_FIXED>>3));
 
 
570
            marineStatusPointer->HModelController.LoopAfterTweening = 0;
 
 
571
        }
 
 
572
        else if (HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,(int)MSSS_Fidget_A))
 
 
573
        {
 
 
574
            SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_Fidget_A, ONE_FIXED<<3, (ONE_FIXED>>3));
 
 
575
        }
 
 
576
        else
 
 
577
        {
 
 
578
            /* No fidgets at all! */
 
 
579
            SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_Standard, ONE_FIXED, (ONE_FIXED>>3));
 
 
580
        }
 
 
581
    }
 
 
582
    else
 
 
583
    {
 
 
584
        if (HModelSequence_Exists(&marineStatusPointer->HModelController, (int)HMSQT_MarineStand, (int)MSSS_Stand_To_Fidget))
 
 
585
        {
 
 
586
            /* We must have gone through StandToFidget, or at least be in it. */
 
 
587
            if (((marineStatusPointer->HModelController.Tweening == Controller_NoTweening)
 
 
588
                && (marineStatusPointer->HModelController.sequence_timer == (ONE_FIXED-1))
 
 
589
                && !marineStatusPointer->HModelController.Looped)
 
 
590
                || (marineStatusPointer->HModelController.keyframe_flags && marineStatusPointer->internalState))
 
 
591
            {
 
 
592
                /* End of old sequence. */
 
 
593
                /* Go back to normal. */
 
 
594
                if (HModelSequence_Exists(&marineStatusPointer->HModelController, (int)HMSQT_MarineStand, (int)MSSS_Fidget_A))
 
 
595
                {
 
 
596
                    SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_Fidget_A, ONE_FIXED<<3, (ONE_FIXED>>3));
 
 
597
                    marineStatusPointer->internalState = 0;
 
 
598
                }
 
 
599
            }
 
 
600
            else if (marineStatusPointer->HModelController.keyframe_flags)
 
 
601
            {
 
 
602
                if ((FastRandom() & 65535) < 21846)
 
 
603
                {
 
 
604
                    if ((FastRandom() & 65535) < 32767)
 
 
605
                    {
 
 
606
                        if (HModelSequence_Exists(&marineStatusPointer->HModelController, (int)HMSQT_MarineStand, (int)MSSS_Fidget_B))
 
 
607
                        {
 
 
608
                            SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_Fidget_B, -1, (ONE_FIXED>>3));
 
 
609
                            marineStatusPointer->HModelController.LoopAfterTweening = 0;
 
 
610
                            marineStatusPointer->internalState = 1;
 
 
611
                        }
 
 
612
                        else if (HModelSequence_Exists(&marineStatusPointer->HModelController, (int)HMSQT_MarineStand, (int)MSSS_Fidget_C))
 
 
613
                        {
 
 
614
                            SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_Fidget_C, -1, (ONE_FIXED>>3));
 
 
615
                            marineStatusPointer->HModelController.LoopAfterTweening = 0;
 
 
616
                            marineStatusPointer->internalState = 2;
 
 
617
                        }
 
 
618
                    }
 
 
619
                    else
 
 
620
                    {
 
 
621
                        if (HModelSequence_Exists(&marineStatusPointer->HModelController, (int)HMSQT_MarineStand, (int)MSSS_Fidget_C))
 
 
622
                        {
 
 
623
                            SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_Fidget_C, -1, (ONE_FIXED>>3));
 
 
624
                            marineStatusPointer->HModelController.LoopAfterTweening = 0;
 
 
625
                            marineStatusPointer->internalState = 2;
 
 
626
                        }
 
 
627
                        else if (HModelSequence_Exists(&marineStatusPointer->HModelController, (int)HMSQT_MarineStand, (int)MSSS_Fidget_B))
 
 
628
                        {
 
 
629
                            SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_Fidget_B, -1, (ONE_FIXED>>3));
 
 
630
                            marineStatusPointer->HModelController.LoopAfterTweening = 0;
 
 
631
                            marineStatusPointer->internalState = 1;
 
 
632
                        }
 
 
633
                    }
 
 
634
                }
 
 
635
                /* Else do nothing, I guess. */
 
 
636
            }
 
 
637
        }
 
 
638
        //else { No stand to fidget. }
 
 
639
    }
 
 
640
}
 
 
641
 
 
 
642
static void HandleWaitingAnimations(STRATEGYBLOCK *sbPtr) 
 
 
643
{
 
 
644
    int tweeningtime = ((FastRandom() & 65535) + 32767) >> 3;
 
 
645
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
646
 
 
 
647
    {
 
 
648
        DELTA_CONTROLLER *delta = Get_Delta_Sequence(&marineStatusPointer->HModelController, "sprintheaddelta");
 
 
649
 
 
 
650
        /* There should be NO head turn delta. */
 
 
651
        if (delta)
 
 
652
            Remove_Delta_Sequence(&marineStatusPointer->HModelController, "sprintheaddelta");
 
 
653
    }
 
 
654
 
 
 
655
    if(marineStatusPointer->IAmCrouched)
 
 
656
    {
 
 
657
        if (marineStatusPointer->HModelController.Sequence_Type != HMSQT_MarineCrouch || marineStatusPointer->HModelController.Sub_Sequence !=
MCrSS_Standard)
 
 
658
            SetMarineAnimationSequence(sbPtr, HMSQT_MarineCrouch, MCrSS_Standard, ONE_FIXED, tweeningtime);
 
 
659
    }
 
 
660
    else
 
 
661
    {
 
 
662
        if (marineStatusPointer->suspicious)
 
 
663
        {
 
 
664
            /* Go directly to wait alert, if you can. */
 
 
665
            if (HModelSequence_Exists(&marineStatusPointer->HModelController, HMSQT_MarineStand, MSSS_Wait_Alert))
 
 
666
            {
 
 
667
                if ((marineStatusPointer->HModelController.Sequence_Type != HMSQT_MarineStand) || (marineStatusPointer->HModelController.Sub_Sequence !=
MSSS_Wait_Alert))
 
 
668
                    SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_Wait_Alert, (MUL_FIXED((ONE_FIXED<<2), ((FastRandom()&32767)+65536))),
tweeningtime);
 
 
669
            return;
 
 
670
            }
 
 
671
        }
 
 
672
 
 
 
673
        HandleFidgetAnimations(sbPtr);
 
 
674
    }
 
 
675
}
 
 
676
 
 
 
677
static void SetMarineElevation(STRATEGYBLOCK *sbPtr)
 
 
678
{
 
 
679
    VECTORCH *gunpos;
 
 
680
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
681
 
 
 
682
    if (!marineStatusPointer->My_Weapon->UseElevation)
 
 
683
        return; /* Non elevating weapon. */
 
 
684
 
 
 
685
    if (marineStatusPointer->My_Elevation_Section)
 
 
686
        gunpos = &marineStatusPointer->My_Elevation_Section->World_Offset;
 
 
687
    else
 
 
688
        gunpos = &sbPtr->DynPtr->Position;
 
 
689
 
 
 
690
    /* Aim at weaponTarget. */
 
 
691
 
 
 
692
    int offsetx = marineStatusPointer->weaponTarget.vx - gunpos->vx;
 
 
693
    int offsety = marineStatusPointer->weaponTarget.vz - gunpos->vz;
 
 
694
    int offseta = -(marineStatusPointer->weaponTarget.vy - gunpos->vy);
 
 
695
 
 
 
696
    while( (offsetx > (ONE_FIXED >> 2))
 
 
697
        ||(offsety > (ONE_FIXED >> 2))
 
 
698
        ||(offseta > (ONE_FIXED >> 2))
 
 
699
        ||(offsetx < -(ONE_FIXED >> 2))
 
 
700
        ||(offsety < -(ONE_FIXED >> 2))
 
 
701
        ||(offseta < -(ONE_FIXED >> 2)))
 
 
702
    {
 
 
703
        offsetx >>= 1;
 
 
704
        offsety >>= 1;
 
 
705
        offseta >>= 1;
 
 
706
    }
 
 
707
 
 
 
708
    int offsetz = SqRoot32((offsetx*offsetx)+(offsety*offsety));
 
 
709
    int angle1 = ArcTan(offseta,offsetz);
 
 
710
 
 
 
711
    if (angle1 >= 3072)
 
 
712
        angle1 -= 4096;
 
 
713
 
 
 
714
    if (angle1 >= 2048)
 
 
715
        angle1 = angle1-3072;
 
 
716
 
 
 
717
    if (angle1 > 1024)
 
 
718
        angle1 = 2048-angle1;
 
 
719
 
 
 
720
    assert(angle1 >= -1024);
 
 
721
    assert(angle1 <= 1024);
 
 
722
 
 
 
723
    DELTA_CONTROLLER *elevation_controller = Get_Delta_Sequence(&marineStatusPointer->HModelController, "Elevation");
 
 
724
    assert(elevation_controller);
 
 
725
 
 
 
726
    if(NULL == elevation_controller) // jadda
 
 
727
        return;
 
 
728
 
 
 
729
    if (marineStatusPointer->IAmCrouched)
 
 
730
    {
 
 
731
        elevation_controller->sequence_type = HMSQT_MarineCrouch;
 
 
732
        elevation_controller->sub_sequence = MCrSS_Elevation;
 
 
733
    }
 
 
734
    else
 
 
735
    {
 
 
736
        if (marineStatusPointer->FiringAnim == 1)
 
 
737
        {
 
 
738
            elevation_controller->sequence_type = HMSQT_MarineStand;
 
 
739
            elevation_controller->sub_sequence = MSSS_Hip_Fire_Elevation;
 
 
740
        }
 
 
741
        else
 
 
742
        {
 
 
743
            elevation_controller->sequence_type = HMSQT_MarineStand;
 
 
744
            elevation_controller->sub_sequence = MSSS_Elevation;
 
 
745
        }
 
 
746
    }
 
 
747
 
 
 
748
    {
 
 
749
        int fake_timer = 1024 - angle1;
 
 
750
 
 
 
751
        fake_timer <<= 5;
 
 
752
 
 
 
753
        if (fake_timer == 65536)
 
 
754
            fake_timer = 65535;
 
 
755
 
 
 
756
        assert(fake_timer >= 0);
 
 
757
        assert(fake_timer < 65536);
 
 
758
 
 
 
759
        elevation_controller->timer = fake_timer;
 
 
760
    }
 
 
761
 
 
 
762
    switch(marineStatusPointer->My_Weapon->id)
 
 
763
    {
 
 
764
        case MNPCW_MPistol:
 
 
765
            /* Unless you're a reloading pistol. */
 
 
766
            if (marineStatusPointer->lastroundhit == -1)
 
 
767
                elevation_controller->timer = 32767;
 
 
768
        break;
 
 
769
        /* Or a firing grenade launcher or shotgun in state 1. */
 
 
770
        case MNPCW_GrenadeLauncher:
 
 
771
        case MNPCW_MShotgun:
 
 
772
        case MNPCW_Android:
 
 
773
        case MNPCW_AndroidSpecial:
 
 
774
        {
 
 
775
            if ((marineStatusPointer->behaviourState == MBS_Firing) && marineStatusPointer->internalState)
 
 
776
                    elevation_controller->timer = 32767;
 
 
777
        }
 
 
778
        default:
 
 
779
        break;
 
 
780
    }
 
 
781
}
 
 
782
 
 
 
783
static void Marine_Enter_Firing_State(STRATEGYBLOCK *sbPtr) 
 
 
784
{
 
 
785
    assert(sbPtr);
 
 
786
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
787
    assert(marineStatusPointer);
 
 
788
 
 
 
789
    if(NULL == marineStatusPointer->Target)
 
 
790
{
 
 
791
puts("FO"); //jadda
 
 
792
return;
 
 
793
}
 
 
794
    marineStatusPointer->gotapoint = 0;
 
 
795
    int range = VectorDistance(&marineStatusPointer->Target->DynPtr->Position, &sbPtr->DynPtr->Position);
 
 
796
 
 
 
797
    marineStatusPointer->lastState = marineStatusPointer->behaviourState;
 
 
798
    marineStatusPointer->behaviourState = MBS_Firing;
 
 
799
    marineStatusPointer->volleySize = 0;
 
 
800
 
 
 
801
    if (marineStatusPointer->My_Weapon->id != MNPCW_MPistol)
 
 
802
        marineStatusPointer->lastroundhit = 0;
 
 
803
 
 
 
804
    marineStatusPointer->lasthitsection = NULL;
 
 
805
    marineStatusPointer->stateTimer = marineStatusPointer->My_Weapon->FiringTime;
 
 
806
    assert(marineStatusPointer->Target);
 
 
807
 
 
 
808
    NPCGetTargetPosition(&marineStatusPointer->weaponTarget, marineStatusPointer->Target);
 
 
809
 
 
 
810
    {
 
 
811
        /* There should be NO head turn delta. */
 
 
812
        DELTA_CONTROLLER *delta = Get_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
 
 
813
 
 
 
814
        if (delta)
 
 
815
            Remove_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
 
 
816
    }
 
 
817
 
 
 
818
    /* Arbitrarily decide to crouch? */
 
 
819
    if (marineStatusPointer->Android)
 
 
820
    {
 
 
821
        marineStatusPointer->IAmCrouched = 0;
 
 
822
    }
 
 
823
    else
 
 
824
    {
 
 
825
        int prob = 20000;
 
 
826
 
 
 
827
        if (range < 6000)
 
 
828
            prob += 10000;
 
 
829
 
 
 
830
        if ((marineStatusPointer->Target->DynPtr->Position.vy - sbPtr->DynPtr->Position.vy) > 3000)
 
 
831
            prob += 20000;
 
 
832
 
 
 
833
        if ((FastRandom() & 65535) < prob)
 
 
834
            marineStatusPointer->IAmCrouched = 1;
 
 
835
    }
 
 
836
 
 
 
837
    if (HModelSequence_Exists(&marineStatusPointer->HModelController, HMSQT_MarineStand,MSSS_FireFromHips))
 
 
838
    {
 
 
839
        int target = marineStatusPointer->Courage >> 1;
 
 
840
 
 
 
841
        if (marineStatusPointer->Mission == MM_Guard)
 
 
842
            target += 32767;
 
 
843
 
 
 
844
        if ((FastRandom() & ((ONE_FIXED << 1) - 1)) > target)
 
 
845
            marineStatusPointer->FiringAnim = 1;
 
 
846
        else
 
 
847
            marineStatusPointer->FiringAnim = 0;
 
 
848
    }
 
 
849
    else
 
 
850
    {
 
 
851
        marineStatusPointer->FiringAnim = 0;
 
 
852
    }
 
 
853
 
 
 
854
    if(marineStatusPointer->IAmCrouched)
 
 
855
    {
 
 
856
        SetMarineAnimationSequence(sbPtr,HMSQT_MarineCrouch,MCrSS_Attack_Primary,-1,(ONE_FIXED>>3));
 
 
857
    }
 
 
858
    else
 
 
859
    {
 
 
860
        if (marineStatusPointer->FiringAnim == 1)
 
 
861
        {
 
 
862
            SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_FireFromHips, -1, (ONE_FIXED>>3));
 
 
863
        }
 
 
864
        else
 
 
865
        {
 
 
866
            if (marineStatusPointer->My_Weapon->id != MNPCW_TwoPistols)
 
 
867
            {
 
 
868
                SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_Attack_Primary, -1, (ONE_FIXED>>3));
 
 
869
            }
 
 
870
            else
 
 
871
            {
 
 
872
                /* Two Pistols uses Stand Standard. */
 
 
873
                SetMarineAnimationSequence(sbPtr,HMSQT_MarineStand,MSSS_Standard,-1,(ONE_FIXED>>3));
 
 
874
            }
 
 
875
        }
 
 
876
    }
 
 
877
 
 
 
878
    marineStatusPointer->Target_Expression = 1;
 
 
879
 
 
 
880
    /* This next for firing only! */
 
 
881
    marineStatusPointer->HModelController.StopAfterTweening = 1;
 
 
882
 
 
 
883
    switch(marineStatusPointer->My_Weapon->id)
 
 
884
    {
 
 
885
        case MNPCW_PulseRifle:
 
 
886
            if (!marineStatusPointer->FiringAnim && !marineStatusPointer->IAmCrouched)
 
 
887
                marineStatusPointer->Target_Expression = 7;
 
 
888
        break;
 
 
889
        case MNPCW_GrenadeLauncher:
 
 
890
        {
 
 
891
            /* Why do we need internalState 1 here again? */
 
 
892
            marineStatusPointer->internalState = 1;
 
 
893
            marineStatusPointer->HModelController.Looped = 0;
 
 
894
            marineStatusPointer->HModelController.LoopAfterTweening = 0;
 
 
895
 
 
 
896
            /* Put loft in now? */
 
 
897
            {
 
 
898
                int range = VectorDistance(&marineStatusPointer->weaponTarget, &sbPtr->DynPtr->Position);
 
 
899
 
 
 
900
                marineStatusPointer->weaponTarget.vy -= (range /8);
 
 
901
            }
 
 
902
        }
 
 
903
        break;
 
 
904
        case MNPCW_Flamethrower:
 
 
905
        case MNPCW_MFlamer:
 
 
906
            marineStatusPointer->weapon_variable = 0;
 
 
907
        break;
 
 
908
        case MNPCW_MShotgun:
 
 
909
        case MNPCW_Android:
 
 
910
        case MNPCW_AndroidSpecial:
 
 
911
        {
 
 
912
            marineStatusPointer->internalState = 1;
 
 
913
            marineStatusPointer->HModelController.Looped = 0;
 
 
914
            marineStatusPointer->HModelController.LoopAfterTweening = 0;
 
 
915
        }
 
 
916
        default:
 
 
917
        break;
 
 
918
    }
 
 
919
}
 
 
920
/*
 
 
921
//Marine_Enter_PanicReload_State(sbPtr);
 
 
922
//Marine_Enter_Reload_State(sbPtr);
 
 
923
 
 
 
924
switch(marineStatusPointer->behaviourState)
 
 
925
{
 
 
926
case MBS_Reloading:
 
 
927
case MBS_PanicReloading:
 
 
928
case MBS_PumpAction:
 
 
929
    if (HModelAnimation_IsFinished(&marineStatusPointer->HModelController))
 
 
930
        marineStatusPointer->behaviourState = marineStatusPointer->lastState;
 
 
931
        //marineStatusPointer->behaviourState = MBS_Waiting;
 
 
932
break;
 
 
933
}
 
 
934
*/
 
 
935
 
 
 
936
static void HandleMovingAnimations(STRATEGYBLOCK *sbPtr) 
 
 
937
{
 
 
938
    int style = -1;
 
 
939
    const MOVEMENT_DATA *movementData;
 
 
940
    VECTORCH offset;
 
 
941
    int speed,animfactor;
 
 
942
 
 
 
943
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
944
 
 
 
945
    /* First test to see if we're in midair. */
 
 
946
    if (HModelSequence_Exists(&marineStatusPointer->HModelController, HMSQT_MarineStand, MSSS_Jump))
 
 
947
    {
 
 
948
        if (!sbPtr->DynPtr->IsInContactWithFloor)
 
 
949
        {
 
 
950
            VECTORCH offset;
 
 
951
 
 
 
952
            offset.vx = sbPtr->DynPtr->Position.vx - sbPtr->DynPtr->PrevPosition.vx;
 
 
953
            offset.vy = sbPtr->DynPtr->Position.vy - sbPtr->DynPtr->PrevPosition.vy;
 
 
954
            offset.vz = sbPtr->DynPtr->Position.vz - sbPtr->DynPtr->PrevPosition.vz;
 
 
955
 
 
 
956
            if (offset.vx || offset.vy || offset.vz)
 
 
957
            {
 
 
958
                if ((marineStatusPointer->HModelController.Sequence_Type != HMSQT_MarineStand) || (marineStatusPointer->HModelController.Sub_Sequence !=
MSSS_Jump))
 
 
959
                {
 
 
960
                    SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_Jump, -1, (ONE_FIXED >> 4));
 
 
961
                    return;
 
 
962
                }
 
 
963
            }
 
 
964
        }
 
 
965
    }
 
 
966
 
 
 
967
    if(marineStatusPointer->suspicious || ((ONE_FIXED << 1) > marineStatusPointer->Courage))
 
 
968
    {
 
 
969
 
 
 
970
    }
 
 
971
 
 
 
972
    if(!marineStatusPointer->IAmCrouched)
 
 
973
        marineStatusPointer->IAmCrouched = MarineShouldBeCrawling(sbPtr);
 
 
974
 
 
 
975
    //MARINE_BHSTATE baseState = (marineStatusPointer->behaviourState == MBS_Avoidance) ? marineStatusPointer->lastState :
marineStatusPointer->behaviourState;
 
 
976
    MARINE_BHSTATE baseState = marineStatusPointer->behaviourState;
 
 
977
 
 
 
978
    switch (baseState)
 
 
979
    {
 
 
980
        case MBS_Firing:
 
 
981
        Marine_Enter_Firing_State(sbPtr);
 
 
982
        return;
 
 
983
        case MBS_Waiting:
 
 
984
            sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
985
            HandleWaitingAnimations(sbPtr);
 
 
986
            return;
 
 
987
        break;
 
 
988
        case MBS_Wandering:
 
 
989
            style = 1;
 
 
990
        break;
 
 
991
        case MBS_Retreating:
 
 
992
            style = 4;
 
 
993
        break;
 
 
994
        case MBS_Sentry:
 
 
995
        case MBS_Returning:
 
 
996
        case MBS_Pathfinding:
 
 
997
            if (marineStatusPointer->Target == NULL)
 
 
998
            {
 
 
999
                if (marineStatusPointer->suspicious)
 
 
1000
                    style = 2;
 
 
1001
                else
 
 
1002
                    style = 1;
 
 
1003
            }
 
 
1004
            else
 
 
1005
            {
 
 
1006
                style = 3;
 
 
1007
            }
 
 
1008
        case MBS_Approaching:
 
 
1009
        case MBS_Responding:
 
 
1010
            if (marineStatusPointer->Target == NULL)
 
 
1011
                style = 2;
 
 
1012
            else
 
 
1013
                style = 3;
 
 
1014
        break;
 
 
1015
        case MBS_Avoidance:
 
 
1016
            /* Definitely shouldn't be here! */
 
 
1017
            assert(0);
 
 
1018
        break;
 
 
1019
        default:
 
 
1020
            /* Shouldn't really be here. */
 
 
1021
            style = 3;
 
 
1022
    }
 
 
1023
 
 
 
1024
    SetMarineElevation(sbPtr);
 
 
1025
 
 
 
1026
    int can_mooch_bored = HModelSequence_Exists(&marineStatusPointer->HModelController, HMSQT_MarineRun, MRSS_Mooch_Bored); // no target and calm
 
 
1027
    int can_mooch_alert = HModelSequence_Exists(&marineStatusPointer->HModelController, HMSQT_MarineRun, MRSS_Mooch_Alert); // not target alert can see
target
 
 
1028
    int can_sprint = HModelSequence_Exists(&marineStatusPointer->HModelController, HMSQT_MarineRun, MRSS_Sprint); // determed run
 
 
1029
 
 
 
1030
    /* Finally... */
 
 
1031
    offset.vx = sbPtr->DynPtr->Position.vx - sbPtr->DynPtr->PrevPosition.vx;
 
 
1032
    offset.vy = sbPtr->DynPtr->Position.vy - sbPtr->DynPtr->PrevPosition.vy;
 
 
1033
    offset.vz = sbPtr->DynPtr->Position.vz - sbPtr->DynPtr->PrevPosition.vz;
 
 
1034
 
 
 
1035
    {
 
 
1036
        /* ...compute speed factor... */
 
 
1037
        speed = Magnitude(&offset);
 
 
1038
 
 
 
1039
        if (speed < MUL_FIXED(NormalFrameTime, 50))
 
 
1040
        {
 
 
1041
            /* Not moving much, are we? */
 
 
1042
            style = 0;
 
 
1043
        }
 
 
1044
 
 
 
1045
        speed = DIV_FIXED(speed, NormalFrameTime);
 
 
1046
    }
 
 
1047
 
 
 
1048
    /* Now, pre-emptive reject of unavailable cases. */
 
 
1049
    if (style == 1)
 
 
1050
    {
 
 
1051
        if (!can_mooch_bored)
 
 
1052
            style = 3;
 
 
1053
    }
 
 
1054
 
 
 
1055
    if (style == 2)
 
 
1056
    {
 
 
1057
        if (!can_mooch_alert)
 
 
1058
            style = 3;
 
 
1059
    }
 
 
1060
 
 
 
1061
    if (style == 4)
 
 
1062
    {
 
 
1063
        if (!can_sprint)
 
 
1064
            style = 3;
 
 
1065
    }
 
 
1066
 
 
 
1067
    if (!speed)
 
 
1068
    {
 
 
1069
        style = 0;
 
 
1070
        animfactor = ONE_FIXED;
 
 
1071
    }
 
 
1072
    else
 
 
1073
    {
 
 
1074
        animfactor = DIV_FIXED(625, speed); // Was 512!  Difference to correct for rounding down...
 
 
1075
    }
 
 
1076
 
 
 
1077
    assert(animfactor > 0);
 
 
1078
 
 
 
1079
    /* ...and do it. */
 
 
1080
 
 
 
1081
    if(marineStatusPointer->IAmCrouched && ((MBS_Approaching == marineStatusPointer->behaviourState) || (MBS_Firing ==
marineStatusPointer->behaviourState)))
 
 
1082
    {
 
 
1083
        if ((marineStatusPointer->HModelController.Sequence_Type != HMSQT_MarineCrawl) || (marineStatusPointer->HModelController.Sub_Sequence !=
MCSS_Standard))
 
 
1084
        {
 
 
1085
            SetMarineAnimationSequence(sbPtr, HMSQT_MarineCrawl, MCSS_Standard, ONE_FIXED, ONE_FIXED >> 4);
 
 
1086
        }
 
 
1087
 
 
 
1088
        if (marineStatusPointer->My_Weapon->ARealMarine)
 
 
1089
            movementData = GetThisMovementData(MDI_Marine_Combat);
 
 
1090
        else
 
 
1091
            movementData = GetThisMovementData(MDI_Civilian_Combat);
 
 
1092
    }
 
 
1093
    else
 
 
1094
    {
 
 
1095
        switch (style)
 
 
1096
        {
 
 
1097
            case -1:
 
 
1098
                /* Whoops! */
 
 
1099
                assert(0);
 
 
1100
                puts("Whoops");
 
 
1101
                return;
 
 
1102
            break;
 
 
1103
            case 1:
 
 
1104
            {
 
 
1105
                /* If we're here, we must be able to mooch bored. */
 
 
1106
                if ((marineStatusPointer->HModelController.Sequence_Type != HMSQT_MarineRun) || (marineStatusPointer->HModelController.Sub_Sequence !=
MRSS_Mooch_Bored))
 
 
1107
                {
 
 
1108
                    SetMarineAnimationSequence(sbPtr, HMSQT_MarineRun, MRSS_Mooch_Bored, ((ONE_FIXED * 7) / 5), (ONE_FIXED >> 4));
 
 
1109
                }
 
 
1110
 
 
 
1111
                if (marineStatusPointer->My_Weapon->ARealMarine)
 
 
1112
                    movementData = GetThisMovementData(MDI_Marine_Mooch_Bored);
 
 
1113
                else
 
 
1114
                    movementData = GetThisMovementData(MDI_Civilian_Mooch_Bored);
 
 
1115
            }
 
 
1116
            break;
 
 
1117
            case 2:
 
 
1118
            {
 
 
1119
                /* If we're here, we must be able to mooch alert. */
 
 
1120
                if ((marineStatusPointer->HModelController.Sequence_Type != HMSQT_MarineRun) || (marineStatusPointer->HModelController.Sub_Sequence !=
MRSS_Mooch_Alert))
 
 
1121
                {
 
 
1122
                    SetMarineAnimationSequence(sbPtr, HMSQT_MarineRun, MRSS_Mooch_Alert, ((ONE_FIXED*23)/10), (ONE_FIXED>>4));
 
 
1123
                }
 
 
1124
 
 
 
1125
                if (marineStatusPointer->My_Weapon->ARealMarine)
 
 
1126
                    movementData = GetThisMovementData(MDI_Marine_Mooch_Alert);
 
 
1127
                else
 
 
1128
                    movementData = GetThisMovementData(MDI_Civilian_Mooch_Alert);
 
 
1129
            }
 
 
1130
            break;
 
 
1131
            case 4:
 
 
1132
            {
 
 
1133
                /* If we're here, we must be able to sprint. */
 
 
1134
                if ((marineStatusPointer->HModelController.Sequence_Type != HMSQT_MarineRun) || (marineStatusPointer->HModelController.Sub_Sequence !=
MRSS_Sprint))
 
 
1135
                {
 
 
1136
                    SetMarineAnimationSequence(sbPtr, HMSQT_MarineRun, MRSS_Sprint, ((ONE_FIXED*7)/10), (ONE_FIXED>>4));
 
 
1137
                }
 
 
1138
 
 
 
1139
                if (marineStatusPointer->My_Weapon->ARealMarine)
 
 
1140
                    movementData = GetThisMovementData(MDI_Marine_Sprint);
 
 
1141
                else
 
 
1142
                    movementData = GetThisMovementData(MDI_Civilian_Sprint);
 
 
1143
            }
 
 
1144
            break;
 
 
1145
            default:
 
 
1146
            {
 
 
1147
                if ((marineStatusPointer->HModelController.Sequence_Type != HMSQT_MarineRun) || (marineStatusPointer->HModelController.Sub_Sequence !=
MRSS_Standard))
 
 
1148
                {
 
 
1149
                    SetMarineAnimationSequence(sbPtr, HMSQT_MarineRun, MRSS_Standard, ONE_FIXED, (ONE_FIXED>>4));
 
 
1150
                }
 
 
1151
 
 
 
1152
                if (marineStatusPointer->My_Weapon->ARealMarine)
 
 
1153
                    movementData = GetThisMovementData(MDI_Marine_Combat);
 
 
1154
                else
 
 
1155
                    movementData = GetThisMovementData(MDI_Civilian_Combat);
 
 
1156
            }
 
 
1157
        }
 
 
1158
    }
 
 
1159
 
 
 
1160
    marineStatusPointer->nearSpeed = MUL_FIXED(movementData->maxSpeed, marineStatusPointer->speedConstant);
 
 
1161
    marineStatusPointer->acceleration = MUL_FIXED(movementData->acceleration, marineStatusPointer->accelerationConstant);
 
 
1162
 
 
 
1163
printf("MOVEM STYPE %d\n", style);
 
 
1164
    if (!marineStatusPointer->HModelController.Tweening)
 
 
1165
        HModel_SetToolsRelativeSpeed(&marineStatusPointer->HModelController, animfactor);
 
 
1166
//jadda
 
 
1167
    /* Finally, civilians sprinting away look over their shoulders... */
 
 
1168
    {
 
 
1169
        DELTA_CONTROLLER *delta;
 
 
1170
 
 
 
1171
        if (!marineStatusPointer->My_Weapon->ARealMarine)
 
 
1172
        {
 
 
1173
            if (style == 4)
 
 
1174
            {
 
 
1175
                if (!marineStatusPointer->IAmCrouched)
 
 
1176
                {
 
 
1177
                    if (marineStatusPointer->behaviourState == MBS_Retreating)
 
 
1178
                    {
 
 
1179
                        if (HModelSequence_Exists(&marineStatusPointer->HModelController, HMSQT_MarineRun, MRSS_SprintHeadDelta))
 
 
1180
                        {
 
 
1181
                            delta = Get_Delta_Sequence(&marineStatusPointer->HModelController, "sprintheaddelta");
 
 
1182
puts("ilians sprinting away look over their shou");
 
 
1183
                            if (!delta)
 
 
1184
                            {
 
 
1185
                                /* Add it. */
 
 
1186
                                delta = Add_Delta_Sequence(&marineStatusPointer->HModelController, "sprintheaddelta", (int)HMSQT_MarineRun,
(int)MRSS_SprintHeadDelta, -1);
 
 
1187
                                assert(delta);
 
 
1188
                                delta->Playing = delta->Looped = 0;
 
 
1189
                            }
 
 
1190
 
 
 
1191
                            /* Now we must have it... */
 
 
1192
                            if (!delta->Playing)
 
 
1193
                            {
 
 
1194
                                if (marineStatusPointer->incidentFlag)
 
 
1195
                                {
 
 
1196
                                    /* Start it. */
 
 
1197
                                    Start_Delta_Sequence(delta, (int)HMSQT_MarineRun, (int)MRSS_SprintHeadDelta, -1);
 
 
1198
                                    delta->Playing = 1;
 
 
1199
                                }
 
 
1200
                            }
 
 
1201
                            else
 
 
1202
                            {
 
 
1203
                                if (DeltaAnimation_IsFinished(delta))
 
 
1204
                                    delta->Playing = 0;
 
 
1205
                            }
 
 
1206
                        return;
 
 
1207
                        }
 
 
1208
                    }
 
 
1209
                }
 
 
1210
            }
 
 
1211
        }
 
 
1212
 
 
 
1213
        /* There should be NO such delta. */
 
 
1214
        delta = Get_Delta_Sequence(&marineStatusPointer->HModelController, "sprintheaddelta");
 
 
1215
 
 
 
1216
        if (delta)
 
 
1217
            Remove_Delta_Sequence(&marineStatusPointer->HModelController, "sprintheaddelta");
 
 
1218
    }
 
 
1219
}
 
 
1220
 
 
 
1221
static void Marine_Enter_Pathfinder_State(STRATEGYBLOCK *sbPtr) 
 
 
1222
{
 
 
1223
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
1224
 
 
 
1225
    marineStatusPointer->gotapoint = 0;
 
 
1226
    marineStatusPointer->volleySize = 0;
 
 
1227
    NPC_InitMovementData(&(marineStatusPointer->moveData));
 
 
1228
    InitWaypointManager(&marineStatusPointer->waypointManager);
 
 
1229
    marineStatusPointer->lastState = marineStatusPointer->behaviourState;
 
 
1230
    marineStatusPointer->behaviourState = MBS_Pathfinding;
 
 
1231
    marineStatusPointer->destinationmodule = NULL;
 
 
1232
    marineStatusPointer->stateTimer = MARINE_NEAR_TIMEBETWEENFIRING;                     
 
 
1233
    marineStatusPointer->Target_Expression = 0;
 
 
1234
}
 
 
1235
 
 
 
1236
static void Marine_Enter_Approach_State(STRATEGYBLOCK *sbPtr) 
 
 
1237
{
 
 
1238
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
1239
 
 
 
1240
    marineStatusPointer->gotapoint = 0;
 
 
1241
    marineStatusPointer->volleySize = 0;
 
 
1242
    NPC_InitMovementData(&marineStatusPointer->moveData);
 
 
1243
    InitWaypointManager(&marineStatusPointer->waypointManager);
 
 
1244
    marineStatusPointer->lastState = marineStatusPointer->behaviourState;
 
 
1245
    marineStatusPointer->behaviourState = MBS_Approaching;
 
 
1246
    marineStatusPointer->stateTimer = MARINE_NEAR_TIMEBETWEENFIRING;                     
 
 
1247
 
 
 
1248
    /* Neutral??? */
 
 
1249
    marineStatusPointer->Target_Expression = 0;
 
 
1250
    marineStatusPointer->destinationmodule = NULL;
 
 
1251
}
 
 
1252
 
 
 
1253
static AIMODULE *FarNPC_GetTargetAIModuleForMarineRespond(STRATEGYBLOCK *sbPtr)
 
 
1254
{
 
 
1255
    unsigned int highestSmell = 0;
 
 
1256
    AIMODULE* targetModule = NULL;
 
 
1257
 
 
 
1258
    assert(sbPtr);    
 
 
1259
    if(sbPtr->containingModule == NULL)
 
 
1260
        return NULL;
 
 
1261
 
 
 
1262
    AIMODULE **AdjModuleRefPtr = sbPtr->containingModule->m_aimodule->m_link_ptrs;
 
 
1263
 
 
 
1264
    /* check that there is a list of adjacent modules, and that it is not
 
 
1265
    empty (ie points to zero) */
 
 
1266
 
 
 
1267
    if(AdjModuleRefPtr)    
 
 
1268
    {
 
 
1269
        while(*AdjModuleRefPtr != 0)
 
 
1270
        {
 
 
1271
            /* get the index */
 
 
1272
            int AdjModuleIndex = (*AdjModuleRefPtr)->m_index;
 
 
1273
 
 
 
1274
            if (CheckAdjacencyValidity((*AdjModuleRefPtr), sbPtr->containingModule->m_aimodule,0))
 
 
1275
            {
 
 
1276
                /* if this adjacent module's smell value is higher than
 
 
1277
                the current 'highest smell' record the new module as the
 
 
1278
                target. */
 
 
1279
                if(PherMars_ReadBuf[AdjModuleIndex] > highestSmell)
 
 
1280
                {                        
 
 
1281
                    highestSmell = PherMars_ReadBuf[AdjModuleIndex];
 
 
1282
                    targetModule = *AdjModuleRefPtr;                            
 
 
1283
                }
 
 
1284
            }
 
 
1285
            /* next adjacent module reference pointer */
 
 
1286
            AdjModuleRefPtr++;
 
 
1287
        }
 
 
1288
    }
 
 
1289
 
 
 
1290
return targetModule;
 
 
1291
}
 
 
1292
 
 
 
1293
static void GetPointToFaceMarineTowards(STRATEGYBLOCK *sbPtr,VECTORCH *output) 
 
 
1294
{
 
 
1295
    AIMODULE **AdjModuleRefPtr;
 
 
1296
    AIMODULE* chosenModule = NULL;
 
 
1297
    VECTORCH chosenEpWorld;
 
 
1298
    AIMODULE *targetModule;
 
 
1299
    int numFound = 0;
 
 
1300
 
 
 
1301
    assert(sbPtr);
 
 
1302
 
 
 
1303
    if (sbPtr->containingModule == NULL)
 
 
1304
        return;
 
 
1305
 
 
 
1306
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
1307
    assert(marineStatusPointer);
 
 
1308
 
 
 
1309
    /* First trap... are you suspicious? */
 
 
1310
    if (marineStatusPointer->suspicious)
 
 
1311
    {
 
 
1312
        MODULE *suspect_module = ModuleFromPosition(&marineStatusPointer->suspect_point,sbPtr->containingModule);
 
 
1313
 
 
 
1314
        if (suspect_module == NULL)
 
 
1315
        {
 
 
1316
            /* Gordon Bennet. */
 
 
1317
             *output = marineStatusPointer->suspect_point;
 
 
1318
            marineStatusPointer->gotapoint = 1;
 
 
1319
            /* Congratulations. */
 
 
1320
        return;
 
 
1321
        }
 
 
1322
 
 
 
1323
        /* In the same module? */
 
 
1324
        if (sbPtr->containingModule->m_aimodule == suspect_module->m_aimodule)
 
 
1325
        {
 
 
1326
             *output = marineStatusPointer->suspect_point;
 
 
1327
            marineStatusPointer->gotapoint = 1;
 
 
1328
            /* Congratulations. */
 
 
1329
        return;
 
 
1330
        }
 
 
1331
 
 
 
1332
        /* Can you see the suspect point? */
 
 
1333
        if (sbPtr->DisplayBlock != NULL)
 
 
1334
        {
 
 
1335
            if (IsThisObjectVisibleFromThisPosition(sbPtr->DisplayBlock,&marineStatusPointer->suspect_point))
 
 
1336
            {
 
 
1337
                 *output = marineStatusPointer->suspect_point;
 
 
1338
                marineStatusPointer->gotapoint = 1;
 
 
1339
                /* Congratulations. */
 
 
1340
            return;
 
 
1341
            }
 
 
1342
        }
 
 
1343
 
 
 
1344
        {
 
 
1345
            /* Try to face towards the most appropriate EP. */
 
 
1346
            targetModule = GetNextModuleForLink(sbPtr->containingModule->m_aimodule,suspect_module->m_aimodule,7,0);
 
 
1347
 
 
 
1348
            if ((targetModule == NULL) || (targetModule == sbPtr->containingModule->m_aimodule))
 
 
1349
            {
 
 
1350
                 *output = marineStatusPointer->suspect_point;
 
 
1351
                marineStatusPointer->gotapoint = 1;
 
 
1352
                /* Congratulations. */
 
 
1353
            return;
 
 
1354
            }
 
 
1355
            else
 
 
1356
            {
 
 
1357
                /* Get the EP. */
 
 
1358
                FARENTRYPOINT *thisEp = GetAIModuleEP(targetModule, sbPtr->containingModule->m_aimodule);
 
 
1359
 
 
 
1360
                if(thisEp)
 
 
1361
                {
 
 
1362
                    VECTORCH thisEpWorld = thisEp->position;
 
 
1363
 
 
 
1364
                    thisEpWorld.vx += targetModule->m_world.vx;
 
 
1365
                    thisEpWorld.vy += targetModule->m_world.vy;
 
 
1366
                    thisEpWorld.vz += targetModule->m_world.vz;            
 
 
1367
 
 
 
1368
                     *output = thisEpWorld;
 
 
1369
                    marineStatusPointer->gotapoint=1;
 
 
1370
                    /* Congratulations. */
 
 
1371
                return;
 
 
1372
                }
 
 
1373
 
 
 
1374
                /* Still here?  Can't you get anything right? */
 
 
1375
                 *output = marineStatusPointer->suspect_point;
 
 
1376
                marineStatusPointer->gotapoint = 1;
 
 
1377
                /* Congratulations. */
 
 
1378
            return;
 
 
1379
            }
 
 
1380
        }
 
 
1381
    }
 
 
1382
 
 
 
1383
    /* We know your module, don't we? */
 
 
1384
 
 
 
1385
    marineStatusPointer->gotapoint = 0;
 
 
1386
    targetModule = NULL;
 
 
1387
 
 
 
1388
    /* Okay.  If you're a guard, do your job. */
 
 
1389
    if (marineStatusPointer->Mission == MM_Guard)
 
 
1390
    {
 
 
1391
         *output = marineStatusPointer->my_facing_point;
 
 
1392
        marineStatusPointer->gotapoint = 1;
 
 
1393
        /* Congratulations. */
 
 
1394
    return;
 
 
1395
    }
 
 
1396
 
 
 
1397
    // SBF - 20080518 - commented out - this block of code is a NO-OP
 
 
1398
    // due to the aliased targetModule variable.  This code might have
 
 
1399
    // been disabled intentionally? In any case, disabling this code
 
 
1400
    // works around a crash in FarNPC_GetTargetAIModuleForMarineRespond
 
 
1401
    // during level reloads.
 
 
1402
 
 
 
1403
#if 0 // SBF - 20080518 - commented out if (NpcSquad.alertZone) {
 
 
1404
        /* Might want to face towards trouble. */
 
 
1405
        if (sbPtr->containingModule->m_aimodule!=NpcSquad.alertZone) {
 
 
1406
            AIMODULE *targetModule=0;
 
 
1407
            targetModule = FarNPC_GetTargetAIModuleForMarineRespond(sbPtr);
 
 
1408
        }
 
 
1409
    }
 
 
1410
 
 
 
1411
    /* Did that work? */
 
 
1412
 
 
 
1413
    if (targetModule) {
 
 
1414
        FARENTRYPOINT *thisEp = GetAIModuleEP(targetModule, sbPtr->containingModule->m_aimodule);
 
 
1415
        if(thisEp) {
 
 
1416
            VECTORCH thisEpWorld = thisEp->position;
 
 
1417
 
 
 
1418
            thisEpWorld.vx += targetModule->m_world.vx;
 
 
1419
            thisEpWorld.vy += targetModule->m_world.vy;
 
 
1420
            thisEpWorld.vz += targetModule->m_world.vz;            
 
 
1421
 
 
 
1422
             *output = thisEpWorld;
 
 
1423
            marineStatusPointer->gotapoint = 1;
 
 
1424
            /* Congratulations. */
 
 
1425
            return;
 
 
1426
 
 
 
1427
        }
 
 
1428
    }
 
 
1429
#endif // SBF - 20080518 - commented out
 
 
1430
 
 
 
1431
    AdjModuleRefPtr = sbPtr->containingModule->m_aimodule->m_link_ptrs;    
 
 
1432
    /* check if there is a module adjacency list */ 
 
 
1433
 
 
 
1434
    if(!AdjModuleRefPtr || !(*AdjModuleRefPtr))
 
 
1435
        return; /* Just be random, then. */
 
 
1436
 
 
 
1437
    while(*AdjModuleRefPtr)
 
 
1438
    {
 
 
1439
        AIMODULE *nextAdjModule = *AdjModuleRefPtr;                
 
 
1440
 
 
 
1441
        if ( !((*(nextAdjModule->m_module_ptrs))->m_flags & MODULEFLAG_AIRDUCT))
 
 
1442
        {
 
 
1443
            /* Overlook airducts :-) */
 
 
1444
            FARENTRYPOINT *thisEp = GetAIModuleEP(nextAdjModule, sbPtr->containingModule->m_aimodule);
 
 
1445
 
 
 
1446
            if(thisEp)
 
 
1447
            {
 
 
1448
                if (!thisEp->alien_only)
 
 
1449
                {
 
 
1450
                    /* aha. an ep!... */ 
 
 
1451
                    VECTORCH thisEpWorld = thisEp->position;
 
 
1452
 
 
 
1453
                    thisEpWorld.vx += nextAdjModule->m_world.vx;
 
 
1454
                    thisEpWorld.vy += nextAdjModule->m_world.vy;
 
 
1455
                    thisEpWorld.vz += nextAdjModule->m_world.vz;            
 
 
1456
 
 
 
1457
                    numFound++;
 
 
1458
 
 
 
1459
                    if(!(FastRandom() % numFound))
 
 
1460
                    {
 
 
1461
                        /* take this one */
 
 
1462
                        chosenModule = nextAdjModule;
 
 
1463
                        chosenEpWorld = thisEpWorld;
 
 
1464
                    }
 
 
1465
                }
 
 
1466
            }
 
 
1467
        }
 
 
1468
 
 
 
1469
        AdjModuleRefPtr++;
 
 
1470
    }
 
 
1471
 
 
 
1472
    if(chosenModule)
 
 
1473
    {
 
 
1474
        assert(numFound >= 1);
 
 
1475
         *output = chosenEpWorld;
 
 
1476
        marineStatusPointer->gotapoint = 1;
 
 
1477
        /* Congratulations. */
 
 
1478
    }
 
 
1479
}
 
 
1480
 
 
 
1481
static void Marine_Enter_Wait_State(STRATEGYBLOCK *sbPtr) 
 
 
1482
{
 
 
1483
    assert(sbPtr);
 
 
1484
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
1485
    assert(marineStatusPointer);
 
 
1486
 
 
 
1487
    marineStatusPointer->gotapoint = marineStatusPointer->internalState = marineStatusPointer->volleySize = 0;
 
 
1488
    marineStatusPointer->lastState = marineStatusPointer->behaviourState;
 
 
1489
    marineStatusPointer->behaviourState = MBS_Waiting;
 
 
1490
    marineStatusPointer->stateTimer = MARINE_NEARWAITTIME;
 
 
1491
    marineStatusPointer->Target_Expression = 0;
 
 
1492
    GetPointToFaceMarineTowards(sbPtr,&marineStatusPointer->wanderData.worldPosition);
 
 
1493
}
 
 
1494
 
 
 
1495
static void Marine_Enter_SentryMode_State(STRATEGYBLOCK *sbPtr) 
 
 
1496
{
 
 
1497
    assert(sbPtr);
 
 
1498
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
1499
    assert(marineStatusPointer);
 
 
1500
 
 
 
1501
    marineStatusPointer->gotapoint = marineStatusPointer->volleySize = 0;
 
 
1502
    marineStatusPointer->lastState = marineStatusPointer->behaviourState;
 
 
1503
    marineStatusPointer->behaviourState = MBS_Sentry;
 
 
1504
    marineStatusPointer->stateTimer = ONE_FIXED; /* Ignored anyway... */
 
 
1505
    marineStatusPointer->Target_Expression = 0;
 
 
1506
    GetPointToFaceMarineTowards(sbPtr,&marineStatusPointer->wanderData.worldPosition);
 
 
1507
}
 
 
1508
 
 
 
1509
static void InitMission(STRATEGYBLOCK *sbPtr, MARINE_MISSION mission)
 
 
1510
{
 
 
1511
    MARINE_STATUS_BLOCK *marineStatus = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
1512
    assert(marineStatus);
 
 
1513
 
 
 
1514
    marineStatus->lastState = MBS_Waiting;
 
 
1515
 
 
 
1516
    switch (mission)
 
 
1517
    {
 
 
1518
        case MM_Guard:
 
 
1519
            marineStatus->Mission = MM_Guard;
 
 
1520
               marineStatus->behaviourState = MBS_Sentry;
 
 
1521
            Marine_Enter_SentryMode_State(sbPtr);
 
 
1522
        break;
 
 
1523
        case MM_LocalGuard:
 
 
1524
            marineStatus->Mission = MM_LocalGuard;
 
 
1525
               marineStatus->behaviourState = MBS_Waiting;
 
 
1526
            Marine_Enter_Wait_State(sbPtr);
 
 
1527
        break;
 
 
1528
        case MM_NonCom:
 
 
1529
            marineStatus->Mission = MM_NonCom;
 
 
1530
               marineStatus->behaviourState = MBS_Waiting;
 
 
1531
            Marine_Enter_Wait_State(sbPtr);
 
 
1532
        break;
 
 
1533
        case MM_Wait_Then_Wander:
 
 
1534
            marineStatus->Mission = MM_Wait_Then_Wander;
 
 
1535
               marineStatus->behaviourState = MBS_Waiting;
 
 
1536
            Marine_Enter_Wait_State(sbPtr);
 
 
1537
        break;
 
 
1538
        case MM_Pathfinder:
 
 
1539
            marineStatus->Mission = MM_Pathfinder;
 
 
1540
               marineStatus->behaviourState = MBS_Pathfinding;
 
 
1541
            Marine_Enter_Pathfinder_State(sbPtr);
 
 
1542
        break;
 
 
1543
        case MM_Wander:
 
 
1544
        default:
 
 
1545
            marineStatus->Mission = MM_Wander;
 
 
1546
               marineStatus->behaviourState = MBS_Approaching;
 
 
1547
            Marine_Enter_Approach_State(sbPtr);
 
 
1548
    }
 
 
1549
}
 
 
1550
 
 
 
1551
static void CentreMarineElevation(STRATEGYBLOCK *sbPtr)
 
 
1552
{
 
 
1553
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
1554
 
 
 
1555
    if (!marineStatusPointer->My_Weapon->UseElevation)
 
 
1556
        return; /* Non elevating weapon. */
 
 
1557
 
 
 
1558
    DELTA_CONTROLLER *elevation_controller = Get_Delta_Sequence(&marineStatusPointer->HModelController,"Elevation");
 
 
1559
 
 
 
1560
    assert(elevation_controller);
 
 
1561
 
 
 
1562
    if (marineStatusPointer->IAmCrouched)
 
 
1563
    {
 
 
1564
        elevation_controller->sequence_type = HMSQT_MarineCrouch;
 
 
1565
        elevation_controller->sub_sequence = MCrSS_Elevation;
 
 
1566
    }
 
 
1567
    else
 
 
1568
    {
 
 
1569
        if (marineStatusPointer->FiringAnim == 1)
 
 
1570
        {
 
 
1571
            elevation_controller->sequence_type = HMSQT_MarineStand;
 
 
1572
            elevation_controller->sub_sequence = MSSS_Hip_Fire_Elevation;
 
 
1573
        }
 
 
1574
        else
 
 
1575
        {
 
 
1576
            elevation_controller->sequence_type = HMSQT_MarineStand;
 
 
1577
            elevation_controller->sub_sequence = MSSS_Elevation;
 
 
1578
        }
 
 
1579
    }
 
 
1580
 
 
 
1581
    elevation_controller->timer = 32767;
 
 
1582
}
 
 
1583
 
 
 
1584
void MakeMarineNear(STRATEGYBLOCK *sbPtr)
 
 
1585
{
 
 
1586
    DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
1587
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
1588
 
 
 
1589
    /* first of all, see how many marines are currently near: if there are too many,
 
 
1590
    destroy this one, and try to force a generator to make a replacement */
 
 
1591
 
 
 
1592
if(0)
 
 
1593
    if(NumGeneratorNPCsVisible() >= MAX_VISIBLEGENERATORNPCS)
 
 
1594
    {
 
 
1595
        sbPtr->please_destroy_me = 1;
 
 
1596
        ForceAGenerator();
 
 
1597
    }
 
 
1598
 
 
 
1599
    DISPLAYBLOCK *dPtr = CreateActiveObject();
 
 
1600
 
 
 
1601
    if(dPtr == NULL)
 
 
1602
        return; /* cannot allocate displayblock, so leave far */
 
 
1603
 
 
 
1604
    sbPtr->DisplayBlock = dPtr;
 
 
1605
    dPtr->ObStrategyBlock = sbPtr;
 
 
1606
 
 
 
1607
    /* need to initialise positional information in the new display block */ 
 
 
1608
    dPtr->ObWorld = dynPtr->Position;
 
 
1609
    dPtr->ObEuler = dynPtr->OrientEuler;
 
 
1610
    dPtr->ObMat = dynPtr->OrientMat;
 
 
1611
 
 
 
1612
    /* marine data block init */
 
 
1613
    marineStatusPointer->weaponTarget.vx = marineStatusPointer->weaponTarget.vy = marineStatusPointer->weaponTarget.vz = 0;            
 
 
1614
 
 
 
1615
    /* state and sequence initialisation */
 
 
1616
    dPtr->HModelControlBlock = &marineStatusPointer->HModelController;
 
 
1617
 
 
 
1618
    /* Just in case. */
 
 
1619
    CentreMarineElevation(sbPtr);
 
 
1620
    InitWaypointManager(&marineStatusPointer->waypointManager);
 
 
1621
 
 
 
1622
    ProveHModel(dPtr->HModelControlBlock, dPtr);
 
 
1623
 
 
 
1624
    marineStatusPointer->IAmCrouched = MarineShouldBeCrawling(sbPtr);
 
 
1625
 
 
 
1626
    if (marineStatusPointer->behaviourState == MBS_Firing)
 
 
1627
        Marine_Enter_Firing_State(sbPtr); /* To avoid negative volleys */
 
 
1628
 
 
 
1629
    marineStatusPointer->gotapoint = 0;
 
 
1630
 
 
 
1631
    /* Once they become near, Wait_Then_Hunt marines become Wander marines. */
 
 
1632
 
 
 
1633
    switch(marineStatusPointer->Mission)
 
 
1634
    {
 
 
1635
        case MM_Wait_Then_Wander:
 
 
1636
            marineStatusPointer->Mission = MM_Wander;
 
 
1637
        break;
 
 
1638
        case MM_Pathfinder:
 
 
1639
        {
 
 
1640
            /* And force pathfinders to get a new module? */
 
 
1641
            if (marineStatusPointer->behaviourState == MBS_Pathfinding)
 
 
1642
                marineStatusPointer->wanderData.currentModule = NPC_NOWANDERMODULE;
 
 
1643
        }
 
 
1644
        default:
 
 
1645
        break;
 
 
1646
    }
 
 
1647
 
 
 
1648
    marineStatusPointer->lastframe_fallingspeed = -1;
 
 
1649
}
 
 
1650
 
 
 
1651
static void CreateMarineBot(VECTORCH *Position, int weapon)
 
 
1652
{
 
 
1653
    STRATEGYBLOCK* sbPtr = CreateActiveStrategyBlock(I_BehaviourMarine);
 
 
1654
 
 
 
1655
    if(!sbPtr)
 
 
1656
    {
 
 
1657
        printf("FAILED TO CREATE BOT: SB CREATION FAILURE");
 
 
1658
        return;
 
 
1659
    }
 
 
1660
 
 
 
1661
    sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_DEFAULT);
 
 
1662
 
 
 
1663
    if(sbPtr->DynPtr)
 
 
1664
    {
 
 
1665
        DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
1666
        AssignNewSBName(sbPtr);
 
 
1667
        dynPtr->PrevPosition = dynPtr->Position = *Position;
 
 
1668
        CreateEulerMatrix(&dynPtr->OrientEuler, &dynPtr->OrientMat);
 
 
1669
        TransposeMatrixCH(&dynPtr->OrientMat);      
 
 
1670
 
 
 
1671
        //make_new_marine(sbPtr, MNPCW_MMolotov);
 
 
1672
        //make_new_marine(sbPtr, MNPCW_GrenadeLauncher);
 
 
1673
        //make_new_marine(sbPtr, MNPCW_SADAR);
 
 
1674
        int marine_ok;
 
 
1675
 
 
 
1676
        if ( (weapon <= 0) || (weapon >= (int)MNPCW_End))
 
 
1677
            marine_ok = make_new_marine(sbPtr, MNPCW_PulseRifle);
 
 
1678
        else
 
 
1679
            marine_ok = make_new_marine(sbPtr, weapon - 1);
 
 
1680
 
 
 
1681
        if(marine_ok)
 
 
1682
        {
 
 
1683
            MARINE_STATUS_BLOCK *marineStatus = (MARINE_STATUS_BLOCK *)sbPtr->dataptr;
 
 
1684
 
 
 
1685
            //use accoutement set for both marine and civilian
 
 
1686
            //pick a random texture id rather than using 0 , so that we can get 
 
 
1687
            //texture ids not normally allowed by the level
 
 
1688
            ChangeToAlternateAccoutrementSet(sbPtr, FastRandom());
 
 
1689
 
 
 
1690
            if (marineStatus->My_Weapon->WeaponFireFunction == NULL)
 
 
1691
                InitMission(sbPtr, MM_NonCom);
 
 
1692
            else
 
 
1693
                InitMission(sbPtr, MM_Wander);
 
 
1694
        }
 
 
1695
    }
 
 
1696
    else
 
 
1697
    {
 
 
1698
        RemoveBehaviourStrategy(sbPtr);
 
 
1699
        GADGET_NewOnScreenMessage("FAILED TO CREATE BOT: DYNBLOCK CREATION FAILURE");
 
 
1700
    }
 
 
1701
}
 
 
1702
 
 
 
1703
void CastMarineBot(int weapon)
 
 
1704
{
 
 
1705
    #define BOTRANGE 2000
 
 
1706
 
 
 
1707
    VECTORCH position;
 
 
1708
    position = PlayerStatus.sbptr->DynPtr->Position;
 
 
1709
    position.vx += MUL_FIXED(PlayerStatus.sbptr->DynPtr->OrientMat.mat31, BOTRANGE);        
 
 
1710
    position.vy += MUL_FIXED(PlayerStatus.sbptr->DynPtr->OrientMat.mat32, BOTRANGE);        
 
 
1711
    position.vz += MUL_FIXED(PlayerStatus.sbptr->DynPtr->OrientMat.mat33, BOTRANGE);        
 
 
1712
 
 
 
1713
    CreateMarineBot(&position, weapon);
 
 
1714
}
 
 
1715
 
 
 
1716
/*------------------------Patrick 24/2/97-----------------------------
 
 
1717
  Marine/Seal behaviour shell functions
 
 
1718
  --------------------------------------------------------------------*/
 
 
1719
 
 
 
1720
void InitMarineBehaviour(void* bhdata, STRATEGYBLOCK *sbPtr)
 
 
1721
{
 
 
1722
    TOOLS_DATA_MARINE *toolsData = (TOOLS_DATA_MARINE *)bhdata; 
 
 
1723
 
 
 
1724
    {
 
 
1725
    int i;
 
 
1726
    for(i=0;i < SB_NAME_LENGTH; i++)
 
 
1727
        sbPtr->SBname[i] = toolsData->nameID[i];
 
 
1728
    }
 
 
1729
 
 
 
1730
    /* create, initialise and attach a dynamics block */
 
 
1731
    sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_DEFAULT);
 
 
1732
 
 
 
1733
    if(sbPtr->DynPtr)
 
 
1734
    {
 
 
1735
        DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
1736
        dynPtr->PrevPosition = dynPtr->Position = toolsData->position;
 
 
1737
        CreateEulerMatrix(&dynPtr->OrientEuler, &dynPtr->OrientMat);
 
 
1738
        TransposeMatrixCH(&dynPtr->OrientMat);
 
 
1739
 
 
 
1740
        if(make_new_marine(sbPtr, toolsData->marine_type))
 
 
1741
        {
 
 
1742
            MARINE_STATUS_BLOCK *marineStatus = (MARINE_STATUS_BLOCK *)sbPtr->dataptr;
 
 
1743
            int i = 0;
 
 
1744
 
 
 
1745
            marineStatus->my_spot = sbPtr->DynPtr->Position;
 
 
1746
 
 
 
1747
            if (toolsData->Mission == MM_NonCom)
 
 
1748
                marineStatus->My_Weapon = &NPC_Marine_Weapons[MNPCW_MUnarmed];
 
 
1749
 
 
 
1750
            marineStatus->my_facing_point = toolsData->facing_point;
 
 
1751
            marineStatus->path = toolsData->path;
 
 
1752
            marineStatus->stepnumber = toolsData->stepnumber;
 
 
1753
 
 
 
1754
            assert(marineStatus->My_Weapon->HierarchyName);
 
 
1755
 
 
 
1756
            for(; i < SB_NAME_LENGTH;i++)
 
 
1757
                marineStatus->death_target_ID[i] = toolsData->death_target_ID[i];
 
 
1758
 
 
 
1759
            ChangeToAlternateAccoutrementSet(sbPtr, toolsData->textureID);
 
 
1760
 
 
 
1761
            marineStatus->death_target_request = toolsData->death_target_request;
 
 
1762
 
 
 
1763
            if (marineStatus->My_Weapon->WeaponFireFunction == NULL)
 
 
1764
                InitMission(sbPtr, MM_NonCom);
 
 
1765
            else
 
 
1766
                InitMission(sbPtr, toolsData->Mission);
 
 
1767
        }
 
 
1768
    }
 
 
1769
    else 
 
 
1770
    {
 
 
1771
        RemoveBehaviourStrategy(sbPtr);
 
 
1772
    }
 
 
1773
}
 
 
1774
 
 
 
1775
void CreateMarineDynamic(STRATEGYBLOCK *Generator, MARINE_NPC_WEAPONS weapon_for_marine)
 
 
1776
{
 
 
1777
    GENERATOR_BLOCK *generatorBlock = Generator->dataptr;
 
 
1778
    STRATEGYBLOCK* sbPtr = CreateActiveStrategyBlock(I_BehaviourMarine);
 
 
1779
 
 
 
1780
    if(NULL == sbPtr)
 
 
1781
        return;
 
 
1782
 
 
 
1783
    sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_DEFAULT);
 
 
1784
 
 
 
1785
    if(sbPtr->DynPtr)
 
 
1786
    {
 
 
1787
        DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
1788
        AssignNewSBName(sbPtr);
 
 
1789
        dynPtr->PrevPosition = dynPtr->Position = ((GENERATOR_BLOCK* )Generator->dataptr)->Position;
 
 
1790
        CreateEulerMatrix(&dynPtr->OrientEuler, &dynPtr->OrientMat);
 
 
1791
        TransposeMatrixCH(&dynPtr->OrientMat);      
 
 
1792
 
 
 
1793
        if(make_new_marine(sbPtr, weapon_for_marine))
 
 
1794
        {
 
 
1795
            MARINE_STATUS_BLOCK *marineStatus = (MARINE_STATUS_BLOCK *)sbPtr->dataptr;
 
 
1796
            marineStatus->generator_sbptr = Generator;
 
 
1797
            marineStatus->my_facing_point = sbPtr->DynPtr->Position;
 
 
1798
            marineStatus->path = generatorBlock->path;
 
 
1799
            marineStatus->stepnumber = generatorBlock->stepnumber;
 
 
1800
 
 
 
1801
            //use accoutement set for both marine and civilian
 
 
1802
            //texture id 0 picks random one out of those allowed by the level
 
 
1803
            ChangeToAlternateAccoutrementSet(sbPtr, 0);
 
 
1804
 
 
 
1805
            if (marineStatus->My_Weapon->WeaponFireFunction == NULL)
 
 
1806
            {
 
 
1807
                InitMission(sbPtr, MM_NonCom);
 
 
1808
            }
 
 
1809
            else if ( (marineStatus->path != -1) && (marineStatus->stepnumber != -1))
 
 
1810
            {
 
 
1811
                InitMission(sbPtr, MM_Pathfinder);
 
 
1812
            }
 
 
1813
            else
 
 
1814
            {
 
 
1815
                InitMission(sbPtr, MM_Wander);
 
 
1816
            }
 
 
1817
        }
 
 
1818
 
 
 
1819
        /* assert marine is starting as invisible */
 
 
1820
        assert(!ModuleCurrVisArray[sbPtr->containingModule->m_index]);
 
 
1821
    }
 
 
1822
    else 
 
 
1823
    {
 
 
1824
        RemoveBehaviourStrategy(sbPtr);
 
 
1825
    }
 
 
1826
}
 
 
1827
 
 
 
1828
static void NPC_Maintain_Minigun(STRATEGYBLOCK *sbPtr, DELTA_CONTROLLER *mgd)
 
 
1829
{
 
 
1830
    assert(sbPtr);
 
 
1831
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
1832
    assert(marineStatusPointer);
 
 
1833
 
 
 
1834
    if (mgd == NULL)
 
 
1835
        return;
 
 
1836
 
 
 
1837
       if ((marineStatusPointer->behaviourState != MBS_Firing)
 
 
1838
           || (marineStatusPointer->HModelController.Tweening != Controller_NoTweening)
 
 
1839
           || !marineStatusPointer->HModelController.Playing)
 
 
1840
       {
 
 
1841
        /* Not firing. */
 
 
1842
        marineStatusPointer->weapon_variable -= (NormalFrameTime<<3);
 
 
1843
 
 
 
1844
        if (marineStatusPointer->weapon_variable < MINIGUN_IDLE_SPEED)
 
 
1845
            marineStatusPointer->weapon_variable = MINIGUN_IDLE_SPEED;
 
 
1846
    }
 
 
1847
 
 
 
1848
    if (marineStatusPointer->weapon_variable != marineStatusPointer->weapon_variable2)
 
 
1849
    {
 
 
1850
        if (marineStatusPointer->weapon_variable)
 
 
1851
        {
 
 
1852
            int hmspinrate = DIV_FIXED(ONE_FIXED,marineStatusPointer->weapon_variable);
 
 
1853
 
 
 
1854
            Delta_Sequence_ChangeSpeed(mgd, hmspinrate);
 
 
1855
            mgd->Playing = 1;
 
 
1856
        }
 
 
1857
        else
 
 
1858
        {
 
 
1859
            mgd->Playing = 0;
 
 
1860
        }
 
 
1861
    }
 
 
1862
 
 
 
1863
    marineStatusPointer->weapon_variable2 = marineStatusPointer->weapon_variable;
 
 
1864
}
 
 
1865
 
 
 
1866
static void Marine_ConsiderFallingDamage(STRATEGYBLOCK *sbPtr)
 
 
1867
{
 
 
1868
    assert(sbPtr);
 
 
1869
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
1870
    assert(marineStatusPointer);
 
 
1871
 
 
 
1872
    if (sbPtr->DynPtr->IsInContactWithFloor)
 
 
1873
    {
 
 
1874
        if (marineStatusPointer->lastframe_fallingspeed > 0)
 
 
1875
        {
 
 
1876
            if (marineStatusPointer->lastframe_fallingspeed > Marine_Terminal_Velocity)
 
 
1877
            {
 
 
1878
                VECTORCH point,point2;
 
 
1879
 
 
 
1880
                /* Kill marine... */
 
 
1881
                CauseDamageToObject(sbPtr, &damage_profiles[FALLINGDAMAGE], (50*ONE_FIXED), NULL);
 
 
1882
                /* Experiment with blood. */
 
 
1883
                GetTargetingPointOfObject_Far(sbPtr,&point);
 
 
1884
 
 
 
1885
                point2 = sbPtr->DynPtr->Position;
 
 
1886
                point2.vy -= 200;
 
 
1887
                MakeBloodExplosion(&point2, 127, &point, 50, ((marineStatusPointer->Android) ? PARTICLE_ANDROID_BLOOD : PARTICLE_HUMAN_BLOOD));
 
 
1888
                /* Crunching sound optional. */
 
 
1889
            }
 
 
1890
        }
 
 
1891
 
 
 
1892
        marineStatusPointer->lastframe_fallingspeed = 0;
 
 
1893
    }
 
 
1894
    else
 
 
1895
    {
 
 
1896
        /* Compute falling speed. */
 
 
1897
        if (marineStatusPointer->lastframe_fallingspeed >= 0)
 
 
1898
        {
 
 
1899
            int offset = sbPtr->DynPtr->Position.vy - sbPtr->DynPtr->PrevPosition.vy;
 
 
1900
 
 
 
1901
            marineStatusPointer->lastframe_fallingspeed = DIV_FIXED(offset,NormalFrameTime);
 
 
1902
 
 
 
1903
            if (marineStatusPointer->lastframe_fallingspeed < 0)
 
 
1904
                marineStatusPointer->lastframe_fallingspeed = 0;
 
 
1905
        }
 
 
1906
        else
 
 
1907
        {
 
 
1908
            marineStatusPointer->lastframe_fallingspeed = 0;
 
 
1909
        }
 
 
1910
    }
 
 
1911
}
 
 
1912
 
 
 
1913
static void throw_flare(MARINE_STATUS_BLOCK *marineStatusPointer)
 
 
1914
{
 
 
1915
    DISPLAYBLOCK *dispPtr = MakeObject(I_BehaviourFlare, &marineStatusPointer->My_Gunflash_Section->World_Offset);
 
 
1916
 
 
 
1917
    if (NULL != dispPtr)
 
 
1918
    {
 
 
1919
        /* make displayblock a dynamic module object */
 
 
1920
        dispPtr->ObFlags3 |= ObFlag3_DynamicModuleObject;
 
 
1921
 
 
 
1922
        DYNAMICSBLOCK *dynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_GRENADE);
 
 
1923
        dispPtr->ObStrategyBlock->dataptr = malloc(sizeof(FLARE_BEHAV_BLOCK));
 
 
1924
        dispPtr->ObStrategyBlock->DynPtr = dynPtr;
 
 
1925
 
 
 
1926
        if ((NULL != dynPtr) && (NULL != dispPtr->ObStrategyBlock->dataptr))
 
 
1927
        {
 
 
1928
            dynPtr->Position = marineStatusPointer->My_Gunflash_Section->World_Offset;
 
 
1929
            dynPtr->Position = marineStatusPointer->My_Gunflash_Section->World_Offset;
 
 
1930
            dynPtr->OrientMat = marineStatusPointer->My_Gunflash_Section->SecMat;
 
 
1931
 
 
 
1932
            #define GRENADE_SPEED 700
 
 
1933
            dynPtr->LinImpulse.vx = MUL_FIXED(dynPtr->OrientMat.mat31, GRENADE_SPEED);
 
 
1934
            dynPtr->LinImpulse.vy = MUL_FIXED(dynPtr->OrientMat.mat32, GRENADE_SPEED);
 
 
1935
            dynPtr->LinImpulse.vz = MUL_FIXED(dynPtr->OrientMat.mat33, GRENADE_SPEED);
 
 
1936
            dynPtr->IgnoresNotVisPolys = 1;
 
 
1937
            dynPtr->StopOnCollision = 1;
 
 
1938
 
 
 
1939
            ((FLARE_BEHAV_BLOCK *)dispPtr->ObStrategyBlock->dataptr)->LifeTimeRemaining = FLARE_LIFETIME * ONE_FIXED;
 
 
1940
            ((FLARE_BEHAV_BLOCK *)dispPtr->ObStrategyBlock->dataptr)->ParticleGenerationTimer = 0;
 
 
1941
            AddLightingEffectToObject(dispPtr, LFX_FLARE);
 
 
1942
            ((FLARE_BEHAV_BLOCK *)dispPtr->ObStrategyBlock->dataptr)->SoundHandle = SOUND_NOACTIVEINDEX;
 
 
1943
            ((FLARE_BEHAV_BLOCK *)dispPtr->ObStrategyBlock->dataptr)->becomeStuck = 0;
 
 
1944
            marineStatusPointer->FlareActive = FLARE_COUNTER;
 
 
1945
        }
 
 
1946
        else
 
 
1947
        {
 
 
1948
            RemoveBehaviourStrategy(dispPtr->ObStrategyBlock);
 
 
1949
        }
 
 
1950
    }
 
 
1951
}
 
 
1952
 
 
 
1953
static int MarineCanSeeTarget(STRATEGYBLOCK *sbPtr)
 
 
1954
{
 
 
1955
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
1956
 
 
 
1957
    if (marineStatusPointer->Target == NULL)
 
 
1958
        return 0; /* You can't see nothin. */
 
 
1959
 
 
 
1960
    int targetIsNotVisable = 0;
 
 
1961
    int targetTaunted = 0;
 
 
1962
 
 
 
1963
    VECTORCH offset;
 
 
1964
    offset.vx = sbPtr->DynPtr->Position.vx - marineStatusPointer->Target->DynPtr->Position.vx;
 
 
1965
    offset.vy = sbPtr->DynPtr->Position.vy - marineStatusPointer->Target->DynPtr->Position.vy;
 
 
1966
    offset.vz = sbPtr->DynPtr->Position.vz - marineStatusPointer->Target->DynPtr->Position.vz;
 
 
1967
    int dist = Approximate3dMagnitude(&offset);
 
 
1968
 
 
 
1969
    switch(marineStatusPointer->Target->type)
 
 
1970
    {
 
 
1971
        case I_BehaviourAlien:
 
 
1972
        {
 
 
1973
            ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(marineStatusPointer->Target->dataptr);
 
 
1974
 
 
 
1975
            if ((dist > MARINE_AUTODETECT_ALIEN) && !alienStatusPointer->CurrentLightAtAlien)
 
 
1976
                targetIsNotVisable = 1; //!DynamicObjectIsMoving(marineStatusPointer->Target->DynPtr);
 
 
1977
        }
 
 
1978
        break;
 
 
1979
        case I_BehaviourAlienPlayer:
 
 
1980
 
 
 
1981
            if ((dist > MARINE_AUTODETECT_ALIEN) && !PlayerStatus.CurrentLightAtPlayer)
 
 
1982
            {
 
 
1983
                targetIsNotVisable = !DynamicObjectIsMoving(PlayerStatus.sbptr->DynPtr);
 
 
1984
            }
 
 
1985
 
 
 
1986
            if (PlayerStatus.tauntTimer)
 
 
1987
            {
 
 
1988
                /* Idiot. */
 
 
1989
                targetIsNotVisable = 1;
 
 
1990
                /* On the other hand, */
 
 
1991
                targetTaunted = 1;
 
 
1992
            }
 
 
1993
        break;
 
 
1994
        case I_BehaviourPredatorPlayer:
 
 
1995
            if(PlayerStatus.cloakOn && (dist > MARINE_AUTODETECT_CLOAKED_PREDATOR) && (PlayerStatus.CloakingEffectiveness == ONE_FIXED))
 
 
1996
                targetIsNotVisable = 1;
 
 
1997
 
 
 
1998
            if (PlayerStatus.tauntTimer)
 
 
1999
            {
 
 
2000
                /* Idiot. */
 
 
2001
                targetIsNotVisable = 1;
 
 
2002
                /* On the other hand, */
 
 
2003
                targetTaunted = 1;
 
 
2004
            }
 
 
2005
        break;
 
 
2006
        case I_BehaviourPredator:
 
 
2007
        {
 
 
2008
            PREDATOR_STATUS_BLOCK *predStatus = (PREDATOR_STATUS_BLOCK *)marineStatusPointer->Target->dataptr;
 
 
2009
 
 
 
2010
            assert(predStatus);
 
 
2011
 
 
 
2012
            if ((predStatus->CloakStatus == PCLOAK_On) && (dist > MARINE_AUTODETECT_CLOAKED_PREDATOR) &&
(predStatus->CloakingEffectiveness == ONE_FIXED))
 
 
2013
                targetIsNotVisable = 1;
 
 
2014
        }
 
 
2015
        default:
 
 
2016
        break;
 
 
2017
    }
 
 
2018
 
 
 
2019
    if (marineStatusPointer->Target->DamageBlock.IsOnFire)
 
 
2020
        targetIsNotVisable = 0; /* Oh come ON. */
 
 
2021
 
 
 
2022
    if(!NPCCanSeeTarget(sbPtr, marineStatusPointer->Target))
 
 
2023
    {
 
 
2024
        /* I'm suspicious now. */
 
 
2025
        marineStatusPointer->suspicious = MARINE_PARANOIA_TIME;
 
 
2026
        marineStatusPointer->suspect_point = marineStatusPointer->Target->DynPtr->Position;
 
 
2027
        /* And unset previous_suspicion. */
 
 
2028
        marineStatusPointer->previous_suspicion = 0;
 
 
2029
        marineStatusPointer->using_squad_suspicion = 0;
 
 
2030
    return 0;
 
 
2031
    }
 
 
2032
 
 
 
2033
    if(targetIsNotVisable)
 
 
2034
        return 0;
 
 
2035
 
 
 
2036
    if (targetTaunted && marineStatusPointer->Target && !marineStatusPointer->Android)
 
 
2037
    {
 
 
2038
        if (dist < 16834)
 
 
2039
        {
 
 
2040
            dist = 16384 - dist;
 
 
2041
            dist <<= 2;
 
 
2042
            marineStatusPointer->Courage -= MUL_FIXED((NormalFrameTime << 1), dist);
 
 
2043
        }
 
 
2044
    }
 
 
2045
 
 
 
2046
return 1;
 
 
2047
}
 
 
2048
 
 
 
2049
static int Marine_TargetFilter(STRATEGYBLOCK *candidate)
 
 
2050
{
 
 
2051
    switch (candidate->type)
 
 
2052
    {
 
 
2053
        case I_BehaviourAlien:
 
 
2054
        case I_BehaviourPredator:
 
 
2055
        case I_BehaviourAlienPlayer:
 
 
2056
        case I_BehaviourPredatorPlayer:
 
 
2057
        case I_BehaviourFaceHugger:
 
 
2058
        case I_BehaviourXenoborg:
 
 
2059
        case I_BehaviourQueenAlien:
 
 
2060
            return 1;
 
 
2061
        case I_BehaviourDummy:
 
 
2062
        {
 
 
2063
            DUMMY_STATUS_BLOCK *dummyStatusPointer = (DUMMY_STATUS_BLOCK *)(candidate->dataptr);    
 
 
2064
            assert(dummyStatusPointer);
 
 
2065
 
 
 
2066
            switch (dummyStatusPointer->PlayerType)
 
 
2067
            {
 
 
2068
                case I_Alien:
 
 
2069
                case I_Predator:
 
 
2070
                    return 1;
 
 
2071
                default:
 
 
2072
                    return 0;
 
 
2073
            }
 
 
2074
        }
 
 
2075
        default:
 
 
2076
        return 0;
 
 
2077
    }
 
 
2078
}
 
 
2079
 
 
 
2080
static void Marine_AssumePanicExpression(STRATEGYBLOCK *sbPtr)
 
 
2081
{
 
 
2082
    assert(sbPtr);
 
 
2083
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
2084
    assert(marineStatusPointer);
 
 
2085
 
 
 
2086
    if ((marineStatusPointer->Expression > 2) && (marineStatusPointer->Expression < 6))
 
 
2087
    {
 
 
2088
        /* In a blink. */
 
 
2089
        Marine_SwitchExpression(sbPtr, 5);
 
 
2090
 
 
 
2091
        if (marineStatusPointer->Blink < 0)
 
 
2092
        {
 
 
2093
            /* Dunno why, but you never know. */
 
 
2094
            marineStatusPointer->Blink = 0;
 
 
2095
        }
 
 
2096
    }
 
 
2097
    else
 
 
2098
    {
 
 
2099
        /* Not in a blink. */
 
 
2100
        Marine_SwitchExpression(sbPtr, 2);
 
 
2101
    }
 
 
2102
}
 
 
2103
 
 
 
2104
static void Marine_SurpriseSound(STRATEGYBLOCK *sbPtr) 
 
 
2105
{
 
 
2106
    assert(sbPtr);
 
 
2107
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
2108
    assert(marineStatusPointer);
 
 
2109
 
 
 
2110
    if (marineStatusPointer->Android)
 
 
2111
        return;
 
 
2112
 
 
 
2113
    if (marineStatusPointer->soundHandle2 == SOUND_NOACTIVEINDEX)
 
 
2114
    {
 
 
2115
        PlayMarineScream(marineStatusPointer->Voice, MSC_Surprise, marineStatusPointer->VoicePitch, &marineStatusPointer->soundHandle2,
&sbPtr->DynPtr->Position);
 
 
2116
 
 
 
2117
        if (!marineStatusPointer->Android)
 
 
2118
            marineStatusPointer->Courage -= 5000;
 
 
2119
    }
 
 
2120
 
 
 
2121
    /* Open the mouth? */
 
 
2122
    Marine_AssumePanicExpression(sbPtr);
 
 
2123
}
 
 
2124
 
 
 
2125
static int MarineCanSeeObject(STRATEGYBLOCK *sbPtr, STRATEGYBLOCK *target)
 
 
2126
{
 
 
2127
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
2128
 
 
 
2129
    int targetIsNotVisable = 0;
 
 
2130
    int targetTaunted = 0;
 
 
2131
    int targetWasCloaked = 0;
 
 
2132
 
 
 
2133
    VECTORCH offset;
 
 
2134
    offset.vx = sbPtr->DynPtr->Position.vx - target->DynPtr->Position.vx;
 
 
2135
    offset.vy = sbPtr->DynPtr->Position.vy - target->DynPtr->Position.vy;
 
 
2136
    offset.vz = sbPtr->DynPtr->Position.vz - target->DynPtr->Position.vz;
 
 
2137
    int dist = Approximate3dMagnitude(&offset);
 
 
2138
 
 
 
2139
    switch(target->type)
 
 
2140
    {
 
 
2141
        case I_BehaviourAlien:
 
 
2142
        {
 
 
2143
            ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(target->dataptr);
 
 
2144
 
 
 
2145
            if(Predalien != alienStatusPointer->Type)
 
 
2146
            {
 
 
2147
                if ((dist > MARINE_AUTODETECT_ALIEN) && !alienStatusPointer->CurrentLightAtAlien)
 
 
2148
                targetIsNotVisable = !DynamicObjectIsMoving(target->DynPtr);
 
 
2149
            }
 
 
2150
        }
 
 
2151
        break;
 
 
2152
        case I_BehaviourAlienPlayer:
 
 
2153
 
 
 
2154
            if ((dist > MARINE_AUTODETECT_ALIEN) && !PlayerStatus.CurrentLightAtPlayer)
 
 
2155
            {
 
 
2156
                if(!DynamicObjectIsMoving(PlayerStatus.sbptr->DynPtr))
 
 
2157
                {
 
 
2158
                    targetIsNotVisable = 1;
 
 
2159
                    targetWasCloaked = 1;
 
 
2160
                }
 
 
2161
            }
 
 
2162
 
 
 
2163
            if (PlayerStatus.tauntTimer)
 
 
2164
            {
 
 
2165
                /* Idiot. */
 
 
2166
                targetIsNotVisable = 0;
 
 
2167
                /* On the other hand, */
 
 
2168
                targetTaunted = 1;
 
 
2169
            }
 
 
2170
        break;
 
 
2171
        case I_BehaviourPredatorPlayer:
 
 
2172
            if(PlayerStatus.cloakOn && (dist > MARINE_AUTODETECT_CLOAKED_PREDATOR) && (PlayerStatus.CloakingEffectiveness == ONE_FIXED))
 
 
2173
            {
 
 
2174
                targetIsNotVisable = 1;
 
 
2175
                targetWasCloaked = 1;
 
 
2176
            }
 
 
2177
 
 
 
2178
            if (PlayerStatus.tauntTimer)
 
 
2179
            {
 
 
2180
                /* Idiot. */
 
 
2181
                targetIsNotVisable = 0;
 
 
2182
                /* On the other hand, */
 
 
2183
                targetTaunted = 1;
 
 
2184
            }
 
 
2185
        break;
 
 
2186
        case I_BehaviourPredator:
 
 
2187
        {
 
 
2188
            PREDATOR_STATUS_BLOCK *predStatus = (PREDATOR_STATUS_BLOCK *)target->dataptr;
 
 
2189
 
 
 
2190
            if ((predStatus->CloakStatus == PCLOAK_On) && (dist > MARINE_AUTODETECT_CLOAKED_PREDATOR) &&
(predStatus->CloakingEffectiveness == ONE_FIXED))
 
 
2191
            {
 
 
2192
                targetIsNotVisable = 1;
 
 
2193
                targetWasCloaked = 1;
 
 
2194
            }
 
 
2195
        }
 
 
2196
        default:
 
 
2197
        break;
 
 
2198
    }
 
 
2199
 
 
 
2200
    if (target->DamageBlock.IsOnFire)
 
 
2201
        targetIsNotVisable = 0; /* Oh come ON. */
 
 
2202
 
 
 
2203
    /* NO saw last frame usage! */
 
 
2204
 
 
 
2205
    if (targetIsNotVisable)
 
 
2206
        return 0;
 
 
2207
 
 
 
2208
    if(!NPCCanSeeTarget(sbPtr, target))
 
 
2209
        return 0;
 
 
2210
 
 
 
2211
    if (targetWasCloaked && (marineStatusPointer->Target == NULL))
 
 
2212
    {
 
 
2213
        /* Exhibit suprise? */
 
 
2214
        if ((FastRandom() & 65535) < 16384)
 
 
2215
            Marine_SurpriseSound(sbPtr);
 
 
2216
    }
 
 
2217
 
 
 
2218
    if (targetTaunted && marineStatusPointer->Target && !marineStatusPointer->Android)
 
 
2219
    {
 
 
2220
        /* It must be the player. */
 
 
2221
        if (dist < 16834)
 
 
2222
        {
 
 
2223
            dist = 16384 - dist;
 
 
2224
            dist <<= 2;
 
 
2225
            marineStatusPointer->Courage -= MUL_FIXED((NormalFrameTime << 1), dist);
 
 
2226
        }
 
 
2227
    }
 
 
2228
 
 
 
2229
return 1;
 
 
2230
}
 
 
2231
 
 
 
2232
static STRATEGYBLOCK *Marine_GetNewTarget(VECTORCH *marinepos, STRATEGYBLOCK *me)
 
 
2233
{
 
 
2234
    int neardist = ONE_FIXED;
 
 
2235
    STRATEGYBLOCK *nearest = NULL;
 
 
2236
    int a = 0;
 
 
2237
 
 
 
2238
    assert(me);
 
 
2239
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(me->dataptr);
 
 
2240
    assert(marineStatusPointer);
 
 
2241
    MODULE *dmod = ModuleFromPosition(marinepos, PlayerStatus.sbptr->containingModule);
 
 
2242
    assert(dmod);
 
 
2243
 
 
 
2244
    for (; a < NumActiveStBlocks; a++)
 
 
2245
    {
 
 
2246
        STRATEGYBLOCK *candidate = ActiveStBlockList[a];
 
 
2247
 
 
 
2248
        if ((candidate != me) && candidate->DynPtr)
 
 
2249
        {
 
 
2250
            /* Arc reject. */
 
 
2251
            MATRIXCH WtoL = me->DynPtr->OrientMat;
 
 
2252
            VECTORCH offset;
 
 
2253
 
 
 
2254
            offset.vx = marinepos->vx - candidate->DynPtr->Position.vx;
 
 
2255
            offset.vy = marinepos->vy - candidate->DynPtr->Position.vy;
 
 
2256
            offset.vz = marinepos->vz - candidate->DynPtr->Position.vz;
 
 
2257
 
 
 
2258
            TransposeMatrixCH(&WtoL);
 
 
2259
            RotateVector(&offset,&WtoL);
 
 
2260
 
 
 
2261
            if ((offset.vz <= 0) && Marine_TargetFilter(candidate))
 
 
2262
            {
 
 
2263
                int dist = Approximate3dMagnitude(&offset);
 
 
2264
 
 
 
2265
                if ((dist < neardist) && !NPC_IsDead(candidate))
 
 
2266
                {
 
 
2267
                    if (candidate->DisplayBlock && me->DisplayBlock)
 
 
2268
                    {
 
 
2269
                        /* Near case. */
 
 
2270
                        if (MarineCanSeeObject(me, candidate))
 
 
2271
                        {
 
 
2272
                            nearest = candidate;
 
 
2273
                            neardist = dist;
 
 
2274
                        }
 
 
2275
                    }
 
 
2276
                    else
 
 
2277
                    {
 
 
2278
                        if (IsModuleVisibleFromModule(dmod, candidate->containingModule))
 
 
2279
                        {
 
 
2280
                            nearest = candidate;
 
 
2281
                            neardist = dist;
 
 
2282
                        }    
 
 
2283
                    }
 
 
2284
                }
 
 
2285
            }
 
 
2286
        }
 
 
2287
    }
 
 
2288
 
 
 
2289
    if (NULL != nearest)
 
 
2290
    {
 
 
2291
        PointAlert(2, &nearest->DynPtr->Position);
 
 
2292
 
 
 
2293
        /* Must have seen them. */
 
 
2294
        marineStatusPointer->roundsForThisTarget = 0;
 
 
2295
 
 
 
2296
        if ((!marineStatusPointer->suspicious && ((FastRandom() & 65535) < 16384)) || (neardist < ((FastRandom() & 4095) + 1000))) 
 
 
2297
            Marine_SurpriseSound(me); /* Exhibit suprise? */
 
 
2298
    }
 
 
2299
 
 
 
2300
return nearest;
 
 
2301
}
 
 
2302
 
 
 
2303
static int Marine_SoundInterest(SOUNDINDEX soundIndex)
 
 
2304
{
 
 
2305
    /* returns 0->ONE_FIXED scale.  0 is ignored.  Otherwise, larger value means lower priority. */
 
 
2306
 
 
 
2307
    switch (soundIndex)
 
 
2308
    {
 
 
2309
        case SID_PRED_LAUNCHER:
 
 
2310
        case SID_PRED_ROAR:
 
 
2311
        case SID_PLASMABOLT_DISSIPATE:
 
 
2312
        case SID_PLASMABOLT_HIT:
 
 
2313
        case SID_BODY_BEING_HACKED_UP_0:
 
 
2314
        case SID_BODY_BEING_HACKED_UP_1:
 
 
2315
        case SID_BODY_BEING_HACKED_UP_2:
 
 
2316
        case SID_BODY_BEING_HACKED_UP_3:
 
 
2317
        case SID_BODY_BEING_HACKED_UP_4:
 
 
2318
        case SID_PREDATOR_DISK_HITTING_TARGET:
 
 
2319
        case SID_PREDATOR_DISK_HITTING_WALL:
 
 
2320
        case SID_PRED_SMALLLANDING:
 
 
2321
        case SID_GRAPPLE_HIT_WALL:
 
 
2322
        case SID_ELEC_DEATH:
 
 
2323
            /* Enemy sounds! */
 
 
2324
            //return MUL_FIXED(NormalFrameTime, -3000);
 
 
2325
        case SID_MINIGUN_LOOP:
 
 
2326
        case SID_INCIN_LOOP:
 
 
2327
        case SID_GRENADE_LAUNCH:
 
 
2328
        case SID_PULSE_LOOP:
 
 
2329
        case SID_SHOTGUN:
 
 
2330
        case SID_SMART1:
 
 
2331
        case SID_SMART2:
 
 
2332
        case SID_SMART3:
 
 
2333
        case SID_TRACKER_WHEEP_HIGH:
 
 
2334
        case SID_TRACKER_WHEEP_LOW:
 
 
2335
        case SID_SADAR_FIRE:
 
 
2336
        case SID_GRENADE_EXPLOSION:
 
 
2337
        case SID_GRENADE_PROXEXPLOSION:
 
 
2338
        case SID_MOLOTOV_EXPLOSION:
 
 
2339
            /* Marine type sounds. */
 
 
2340
            //return MUL_FIXED(NormalFrameTime, 300);
 
 
2341
            return MUL_FIXED(NormalFrameTime, -3000);
 
 
2342
        case SID_FIRE:
 
 
2343
        case SID_SPLASH1:
 
 
2344
        case SID_SPLASH2:
 
 
2345
        case SID_SPLASH3:
 
 
2346
        case SID_SPLASH4:
 
 
2347
        case SID_POWERUP:
 
 
2348
        case SID_POWERDN:
 
 
2349
        case SID_DOORMID:
 
 
2350
        case SID_BORGON:
 
 
2351
        case SID_SPARKS:
 
 
2352
        case SID_STOMP:
 
 
2353
        case SID_LOADMOVE:
 
 
2354
        case SID_NOAMMO:
 
 
2355
        case SID_PULSEGRENADELAUNCH:
 
 
2356
        case SID_NADEEXPLODE:
 
 
2357
        case SID_SENTRY_GUN:
 
 
2358
        case SID_NICE_EXPLOSION:
 
 
2359
        case SID_EXPLOSION:
 
 
2360
        case SID_SPEARGUN_HITTING_WALL:
 
 
2361
        case SID_DISC_STICKSINWALL:
 
 
2362
        case SID_PRED_PISTOL_EXPLOSION:
 
 
2363
        case SID_SENTRYGUNDEST:
 
 
2364
            /* Weird sounds. */
 
 
2365
            return ONE_FIXED;
 
 
2366
        case SID_STARTOF_SCREAMSLOTS:
 
 
2367
        case SID_ENDOF_SCREAMSLOTS:
 
 
2368
        case SID_STARTOF_ENVSLOTS:
 
 
2369
        case SID_ENDOF_ENVSLOTS:
 
 
2370
            /* Environment sounds. */
 
 
2371
            //return MUL_FIXED(NormalFrameTime, -300);
 
 
2372
            return MUL_FIXED(NormalFrameTime, -3000);
 
 
2373
        default:
 
 
2374
            return MUL_FIXED(NormalFrameTime, -3000);
 
 
2375
            //return MUL_FIXED(NormalFrameTime, -1500);
 
 
2376
    }
 
 
2377
}
 
 
2378
 
 
 
2379
static int Marine_SoundCourageBonus(SOUNDINDEX soundIndex) 
 
 
2380
{
 
 
2381
    /* Returns a FRI value. + is GOOD! */
 
 
2382
 
 
 
2383
    switch (soundIndex)
 
 
2384
    {
 
 
2385
        case SID_PRED_LAUNCHER:
 
 
2386
        case SID_PRED_FRISBEE:
 
 
2387
        case SID_PRED_PISTOL:
 
 
2388
        case SID_PRED_LASER:
 
 
2389
        case SID_ALIEN_KILL:
 
 
2390
        case SID_PRED_ROAR:
 
 
2391
        case SID_PLASMABOLT_DISSIPATE:
 
 
2392
        case SID_PLASMABOLT_HIT:
 
 
2393
        case SID_ALIEN_JAW_ATTACK:
 
 
2394
        case SID_BODY_BEING_HACKED_UP_0:
 
 
2395
        case SID_BODY_BEING_HACKED_UP_1:
 
 
2396
        case SID_BODY_BEING_HACKED_UP_2:
 
 
2397
        case SID_BODY_BEING_HACKED_UP_3:
 
 
2398
        case SID_BODY_BEING_HACKED_UP_4:
 
 
2399
        //case SID_PREDATOR_PICKUP_FIELDCHARGE:
 
 
2400
        //case SID_PREDATOR_CLOAKING_ACTIVE:
 
 
2401
        //case SID_PREDATOR_PLASMACASTER_TARGET_FOUND:
 
 
2402
        //case SID_PREDATOR_PLASMACASTER_TARGET_LOCKED:
 
 
2403
        //case SID_PREDATOR_PLASMACASTER_TARGET_LOST:
 
 
2404
        //case SID_PREDATOR_PLASMACASTER_CHARGING:
 
 
2405
        //case SID_PREDATOR_PLASMACASTER_EMPTY:
 
 
2406
        //case SID_PREDATOR_DISK_TARGET_LOCKED:
 
 
2407
        case SID_PREDATOR_DISK_FLYING:
 
 
2408
        case SID_PREDATOR_DISK_HITTING_TARGET:
 
 
2409
        case SID_PREDATOR_DISK_HITTING_WALL:
 
 
2410
        case SID_PREDATOR_DISK_BEING_CAUGHT:
 
 
2411
        case SID_PREDATOR_DISK_RECOVERED:
 
 
2412
        //case SID_PRED_CLOAKON:
 
 
2413
        //case SID_PRED_CLOAKOFF:
 
 
2414
        case SID_PRED_SMALLLANDING:
 
 
2415
        case SID_GRAPPLE_HIT_WALL:
 
 
2416
        case SID_GRAPPLE_THROW:
 
 
2417
        case SID_ELEC_DEATH:
 
 
2418
            /* Enemy sounds! */
 
 
2419
            return MUL_FIXED(NormalFrameTime, -3000);
 
 
2420
        case SID_MINIGUN_END:
 
 
2421
        case SID_MINIGUN_LOOP:
 
 
2422
        case SID_INCIN_START:
 
 
2423
        case SID_INCIN_LOOP:
 
 
2424
        case SID_INCIN_END:
 
 
2425
        case SID_GRENADE_LAUNCH:
 
 
2426
        case SID_PULSE_START:
 
 
2427
        case SID_PULSE_LOOP:
 
 
2428
        case SID_PULSE_END:
 
 
2429
        case SID_SHOTGUN:
 
 
2430
        case SID_SMART1:
 
 
2431
        case SID_SMART2:
 
 
2432
        case SID_SMART3:
 
 
2433
        case SID_TRACKER_WHEEP_HIGH:
 
 
2434
        case SID_TRACKER_WHEEP_LOW:
 
 
2435
        case SID_PULSE_RIFLE_FIRING_EMPTY:
 
 
2436
        case SID_THROW_FLARE:
 
 
2437
        case SID_MINIGUN_EMPTY:
 
 
2438
        //case SID_SMART_MODESWITCH:
 
 
2439
        case SID_GRENADE_BOUNCE:
 
 
2440
        case SID_BURNING_FLARE:
 
 
2441
        case SID_MARINE_PICKUP_WEAPON:
 
 
2442
        case SID_MARINE_PICKUP_ARMOUR:
 
 
2443
        case SID_SENTRYGUN_SHUTDOWN:
 
 
2444
        case SID_MINIGUN_READY:
 
 
2445
        case SID_SADAR_FIRE:
 
 
2446
        case SID_GRENADE_EXPLOSION:
 
 
2447
        case SID_GRENADE_PROXEXPLOSION:
 
 
2448
        case SID_MOLOTOV_EXPLOSION:
 
 
2449
        case SID_LARGEWEAPONDROP:
 
 
2450
            /* Marine type sounds. */
 
 
2451
            return MUL_FIXED(NormalFrameTime, 300);
 
 
2452
        case SID_FIRE:
 
 
2453
        case SID_SPLASH1:
 
 
2454
        case SID_SPLASH2:
 
 
2455
        case SID_SPLASH3:
 
 
2456
        case SID_SPLASH4:
 
 
2457
        case SID_POWERUP:
 
 
2458
        case SID_POWERDN:
 
 
2459
        case SID_ACID_SPRAY:
 
 
2460
        case SID_DOORSTART:
 
 
2461
        case SID_DOORMID:
 
 
2462
        case SID_DOOREND:
 
 
2463
        case SID_BORGON:
 
 
2464
        case SID_SPARKS:
 
 
2465
        case SID_STOMP:
 
 
2466
        case SID_LOADMOVE:
 
 
2467
        case SID_NOAMMO:
 
 
2468
        case SID_PULSEGRENADELAUNCH:
 
 
2469
        case SID_NADEEXPLODE:
 
 
2470
        case SID_SENTRY_GUN:
 
 
2471
        case SID_SENTRY_END:
 
 
2472
        case SID_NICE_EXPLOSION:
 
 
2473
        case SID_EXPLOSION:
 
 
2474
        case SID_FRAG_RICOCHETS:
 
 
2475
        case SID_SPEARGUN_HITTING_WALL:
 
 
2476
        case SID_DISC_STICKSINWALL:
 
 
2477
        case SID_PREDATOR_PLASMACASTER_REDTRIANGLES:
 
 
2478
        case SID_PRED_PISTOL_EXPLOSION:
 
 
2479
        case SID_PROX_GRENADE_READYTOBLOW:
 
 
2480
        case SID_PROX_GRENADE_ACTIVE:
 
 
2481
        case SID_SENTRYGUNDEST:
 
 
2482
            /* Weird sounds. */
 
 
2483
            return ONE_FIXED;
 
 
2484
        case SID_ARMSTART:
 
 
2485
        case SID_ARMMID:
 
 
2486
        case SID_ARMEND:
 
 
2487
        case SID_TRACKER_CLICK:
 
 
2488
        case SID_TRACKER_WHEEP:
 
 
2489
        //case SID_TELETEXT:
 
 
2490
        case SID_RICOCH1:
 
 
2491
        case SID_RICOCH2:
 
 
2492
        case SID_RICOCH3:
 
 
2493
        case SID_RICOCH4:
 
 
2494
        case SID_NOSOUND:
 
 
2495
        //case SID_PRED_ZOOM_IN:
 
 
2496
        //case SID_PRED_ZOOM_OUT:
 
 
2497
        case SID_MARINE_SMALLLANDING:
 
 
2498
        //case SID_LIGHT_FLICKER_ON:
 
 
2499
        case SID_SENTRYTURN:
 
 
2500
        case SID_PULSE_SWIPE01:
 
 
2501
        case SID_PULSE_SWIPE02:
 
 
2502
        case SID_PULSE_SWIPE03:
 
 
2503
        case SID_PULSE_SWIPE04:
 
 
2504
        case SID_JETPACK_START:
 
 
2505
        case SID_JETPACK_MID:
 
 
2506
        case SID_JETPACK_END:
 
 
2507
            /* Basic marine sounds, and the sentrygun. */
 
 
2508
            return 0;
 
 
2509
        case SID_STARTOF_SCREAMSLOTS:
 
 
2510
        case SID_ENDOF_SCREAMSLOTS:
 
 
2511
        case SID_STARTOF_ENVSLOTS:
 
 
2512
        case SID_ENDOF_ENVSLOTS:
 
 
2513
            /* Environment sounds. */
 
 
2514
            return MUL_FIXED(NormalFrameTime,-300);
 
 
2515
        default:
 
 
2516
            /* Eh?  Could be a scream... */
 
 
2517
            return MUL_FIXED(NormalFrameTime,-1500);
 
 
2518
    }
 
 
2519
}
 
 
2520
 
 
 
2521
static void DoMarineHearing(STRATEGYBLOCK *sbPtr)
 
 
2522
{
 
 
2523
    VECTORCH offset;
 
 
2524
 
 
 
2525
    assert(sbPtr);
 
 
2526
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
2527
    assert(marineStatusPointer);
 
 
2528
 
 
 
2529
    int nearest = -1;
 
 
2530
    int neardist = 10000000;
 
 
2531
    /* Hence, if you're still interested in something else, return. */
 
 
2532
 
 
 
2533
    int a=0;
 
 
2534
    for(; a < SOUND_MAXACTIVE; a++) 
 
 
2535
    {
 
 
2536
        /* Ignore sounds with no position. */
 
 
2537
        if (ActiveSounds[a].threedee && !ActiveSounds[a].loop && !ActiveSounds[a].marine_ignore && (ActiveSounds[a].soundIndex !=
SID_NOSOUND))
 
 
2538
        {
 
 
2539
            int priority;
 
 
2540
            if ((SID_STARTOF_SCREAMSLOTS >= ActiveSounds[a].soundIndex) && (ActiveSounds[a].soundIndex < SID_ENDOF_SCREAMSLOTS))
 
 
2541
            {
 
 
2542
                priority = MUL_FIXED(NormalFrameTime, -1500);
 
 
2543
            }
 
 
2544
            else
 
 
2545
            {
 
 
2546
                priority = Marine_SoundInterest(ActiveSounds[a].soundIndex);
 
 
2547
            }
 
 
2548
 
 
 
2549
            if (!marineStatusPointer->Android)
 
 
2550
                marineStatusPointer->Courage += Marine_SoundCourageBonus(ActiveSounds[a].soundIndex);
 
 
2551
 
 
 
2552
            if (priority)
 
 
2553
            {
 
 
2554
                int test_dist;
 
 
2555
                /* Interesting sound... */
 
 
2556
                offset.vx = sbPtr->DynPtr->Position.vx - ActiveSounds[a].threedeedata.position.vx;
 
 
2557
                offset.vy = sbPtr->DynPtr->Position.vy - ActiveSounds[a].threedeedata.position.vy;
 
 
2558
                offset.vz = sbPtr->DynPtr->Position.vz - ActiveSounds[a].threedeedata.position.vz;
 
 
2559
 
 
 
2560
                int dist = Approximate3dMagnitude(&offset);
 
 
2561
 
 
 
2562
                if (ActiveSounds[a].threedeedata.outer_range == -1)
 
 
2563
                    test_dist = 100000; /* 100 m. */
 
 
2564
                else
 
 
2565
                    test_dist = ActiveSounds[a].threedeedata.outer_range;
 
 
2566
 
 
 
2567
                if (dist <= test_dist)
 
 
2568
                {
 
 
2569
                    /* In range.  Modify by priority. */
 
 
2570
                    dist = MUL_FIXED(dist, priority);
 
 
2571
 
 
 
2572
                    if (dist < neardist)
 
 
2573
                    {
 
 
2574
                        /* Got one! */
 
 
2575
                        nearest = a;
 
 
2576
                        neardist = dist;
 
 
2577
                    }
 
 
2578
                }
 
 
2579
            }
 
 
2580
        }
 
 
2581
    }
 
 
2582
 
 
 
2583
    /* Finally, test the player. */
 
 
2584
    if (PlayerStatus.Noise)
 
 
2585
    {
 
 
2586
        offset.vx = sbPtr->DynPtr->Position.vx - PlayerStatus.sbptr->DynPtr->Position.vx;
 
 
2587
        offset.vy = sbPtr->DynPtr->Position.vy - PlayerStatus.sbptr->DynPtr->Position.vy;
 
 
2588
        offset.vz = sbPtr->DynPtr->Position.vz - PlayerStatus.sbptr->DynPtr->Position.vz;
 
 
2589
 
 
 
2590
        int dist = Approximate3dMagnitude(&offset);
 
 
2591
 
 
 
2592
        if (dist <= 100000)
 
 
2593
        {
 
 
2594
            /* In range.  Assume priority is ONE_FIXED. */
 
 
2595
            if (dist < neardist)
 
 
2596
            {
 
 
2597
                /* Got one! */
 
 
2598
                nearest = -2;
 
 
2599
                neardist = dist;
 
 
2600
            }
 
 
2601
        }
 
 
2602
    }
 
 
2603
 
 
 
2604
    if (nearest != -1)
 
 
2605
    {
 
 
2606
        int level,priority;
 
 
2607
 
 
 
2608
        if (nearest == -2)
 
 
2609
        {
 
 
2610
            /* Heard the player! */
 
 
2611
 
 
 
2612
            marineStatusPointer->suspicious = MARINE_PARANOIA_TIME;
 
 
2613
            marineStatusPointer->suspect_point = PlayerStatus.sbptr->DynPtr->Position;
 
 
2614
            /* Set this to zero when you get a *new* suspicion. */
 
 
2615
            marineStatusPointer->previous_suspicion = 0;
 
 
2616
            marineStatusPointer->using_squad_suspicion = 0;
 
 
2617
 
 
 
2618
            level = 2;
 
 
2619
        }
 
 
2620
        else
 
 
2621
        {
 
 
2622
            marineStatusPointer->suspicious = MARINE_PARANOIA_TIME;
 
 
2623
            marineStatusPointer->suspect_point = ActiveSounds[nearest].threedeedata.position;
 
 
2624
            /* Set this to zero when you get a *new* suspicion. */
 
 
2625
            marineStatusPointer->previous_suspicion = 0;
 
 
2626
            marineStatusPointer->using_squad_suspicion = 0;
 
 
2627
 
 
 
2628
            priority = Marine_SoundInterest(ActiveSounds[nearest].soundIndex);
 
 
2629
 
 
 
2630
            if (priority > ONE_FIXED)
 
 
2631
            {
 
 
2632
                level = 1;
 
 
2633
            }
 
 
2634
            else if (priority < ONE_FIXED)
 
 
2635
            {
 
 
2636
                level = 3;
 
 
2637
            }
 
 
2638
            else
 
 
2639
            {
 
 
2640
                level = 2;
 
 
2641
            }
 
 
2642
        }
 
 
2643
 
 
 
2644
        PointAlert(level, &marineStatusPointer->suspect_point);
 
 
2645
    }
 
 
2646
}
 
 
2647
 
 
 
2648
static void Marine_AssumeNeutralExpression(STRATEGYBLOCK *sbPtr) 
 
 
2649
{
 
 
2650
    assert(sbPtr);
 
 
2651
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
2652
    assert(marineStatusPointer);
 
 
2653
 
 
 
2654
    if ((marineStatusPointer->Expression > 2) && (marineStatusPointer->Expression < 6))
 
 
2655
    {
 
 
2656
        /* In a blink. */
 
 
2657
        Marine_SwitchExpression(sbPtr, 3);
 
 
2658
 
 
 
2659
        if (marineStatusPointer->Blink < 0)
 
 
2660
        {
 
 
2661
            /* Dunno why, but you never know. */
 
 
2662
            marineStatusPointer->Blink = 0;
 
 
2663
        }
 
 
2664
    }
 
 
2665
    else
 
 
2666
    {
 
 
2667
        /* Not in a blink. */
 
 
2668
        Marine_SwitchExpression(sbPtr, 0);
 
 
2669
    }
 
 
2670
}
 
 
2671
 
 
 
2672
static void Marine_AssumeGrimaceExpression(STRATEGYBLOCK *sbPtr) 
 
 
2673
{
 
 
2674
    assert(sbPtr);
 
 
2675
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
2676
    assert(marineStatusPointer);
 
 
2677
 
 
 
2678
    if ((marineStatusPointer->Expression > 2) && (marineStatusPointer->Expression < 6))
 
 
2679
    {
 
 
2680
        /* In a blink. */
 
 
2681
        Marine_SwitchExpression(sbPtr, 4);
 
 
2682
 
 
 
2683
        if (marineStatusPointer->Blink < 0)
 
 
2684
        {
 
 
2685
            /* Dunno why, but you never know. */
 
 
2686
            marineStatusPointer->Blink = 0;
 
 
2687
        }
 
 
2688
    }
 
 
2689
    else
 
 
2690
    {
 
 
2691
        /* Not in a blink. */
 
 
2692
        Marine_SwitchExpression(sbPtr,1);
 
 
2693
    }
 
 
2694
}
 
 
2695
 
 
 
2696
static void Marine_AssumeWink1Expression(STRATEGYBLOCK *sbPtr) 
 
 
2697
{
 
 
2698
    assert(sbPtr);
 
 
2699
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
2700
    assert(marineStatusPointer);
 
 
2701
 
 
 
2702
    /* Who cares about blinking? */
 
 
2703
    Marine_SwitchExpression(sbPtr, 6);
 
 
2704
    marineStatusPointer->Blink = -1;
 
 
2705
}
 
 
2706
 
 
 
2707
static void Marine_AssumeWink2Expression(STRATEGYBLOCK *sbPtr) 
 
 
2708
{
 
 
2709
    assert(sbPtr);
 
 
2710
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
2711
    assert(marineStatusPointer);
 
 
2712
 
 
 
2713
    /* Who cares about blinking? */
 
 
2714
    Marine_SwitchExpression(sbPtr, 7);
 
 
2715
    marineStatusPointer->Blink = -1;
 
 
2716
}
 
 
2717
 
 
 
2718
static int Marine_HasHisMouthOpen(STRATEGYBLOCK *sbPtr) 
 
 
2719
{
 
 
2720
    assert(sbPtr);
 
 
2721
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
2722
    assert(marineStatusPointer);
 
 
2723
 
 
 
2724
    /* yeah, okay, it's hard coded. */
 
 
2725
    return ((marineStatusPointer->Expression == 2) || (marineStatusPointer->Expression == 5));
 
 
2726
}
 
 
2727
 
 
 
2728
static void Marine_UpdateFace(STRATEGYBLOCK *sbPtr) 
 
 
2729
{
 
 
2730
    assert(sbPtr);
 
 
2731
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
2732
    assert(marineStatusPointer);
 
 
2733
 
 
 
2734
    if (marineStatusPointer->Expression != marineStatusPointer->Target_Expression)
 
 
2735
    {
 
 
2736
        /* Right, consider this. */
 
 
2737
        if (Marine_HasHisMouthOpen(sbPtr))
 
 
2738
        {
 
 
2739
            /* Does the target expression also have it's mouth open? */
 
 
2740
            if (!((marineStatusPointer->Target_Expression == 2) || (marineStatusPointer->Target_Expression == 5)))
 
 
2741
            {
 
 
2742
                /* Are we screaming? */
 
 
2743
                if (marineStatusPointer->soundHandle2 != SOUND_NOACTIVEINDEX)
 
 
2744
                    return; // Can't close our mouth yet.
 
 
2745
            }
 
 
2746
        }
 
 
2747
    }
 
 
2748
 
 
 
2749
    /* Also ignore if you're in the wink counterpart of the target. */
 
 
2750
    switch (marineStatusPointer->Target_Expression)
 
 
2751
    {
 
 
2752
        case 0:
 
 
2753
            if (marineStatusPointer->Expression == 3)
 
 
2754
                return;
 
 
2755
            break;
 
 
2756
        case 1:
 
 
2757
            if (marineStatusPointer->Expression == 4)
 
 
2758
                return;
 
 
2759
            break;
 
 
2760
        case 2:
 
 
2761
            if (marineStatusPointer->Expression == 5)
 
 
2762
                return;
 
 
2763
            break;
 
 
2764
        default:
 
 
2765
            break;
 
 
2766
    }
 
 
2767
 
 
 
2768
    /* Exit if current==target? */    
 
 
2769
 
 
 
2770
    if (marineStatusPointer->Expression == marineStatusPointer->Target_Expression)
 
 
2771
        return;
 
 
2772
 
 
 
2773
    /* If we got here, it must be okay... but do it properly! */
 
 
2774
    switch (marineStatusPointer->Target_Expression)
 
 
2775
    {
 
 
2776
        case 0:
 
 
2777
        case 3:
 
 
2778
            Marine_AssumeNeutralExpression(sbPtr);
 
 
2779
            break;
 
 
2780
        case 1:
 
 
2781
        case 4:
 
 
2782
            Marine_AssumeGrimaceExpression(sbPtr);
 
 
2783
            break;
 
 
2784
        case 2:
 
 
2785
        case 5:
 
 
2786
            Marine_AssumePanicExpression(sbPtr);
 
 
2787
            break;
 
 
2788
        case 6:
 
 
2789
            Marine_AssumeWink1Expression(sbPtr);
 
 
2790
            break;
 
 
2791
        case 7:
 
 
2792
            Marine_AssumeWink2Expression(sbPtr);
 
 
2793
            break;
 
 
2794
        default:
 
 
2795
            assert(0);
 
 
2796
            break;
 
 
2797
    }
 
 
2798
}
 
 
2799
 
 
 
2800
static void Marine_PanicScream(STRATEGYBLOCK *sbPtr) 
 
 
2801
{
 
 
2802
    assert(sbPtr);
 
 
2803
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
2804
    assert(marineStatusPointer);
 
 
2805
 
 
 
2806
    if (marineStatusPointer->Android)
 
 
2807
        return;
 
 
2808
 
 
 
2809
    if (marineStatusPointer->soundHandle2 == SOUND_NOACTIVEINDEX)
 
 
2810
    {
 
 
2811
        PlayMarineScream(marineStatusPointer->Voice, MSC_Panic,marineStatusPointer->VoicePitch,
 
 
2812
            &marineStatusPointer->soundHandle2, &sbPtr->DynPtr->Position);
 
 
2813
    }
 
 
2814
}
 
 
2815
 
 
 
2816
static void Marine_Enter_Retreat_State(STRATEGYBLOCK *sbPtr) 
 
 
2817
{
 
 
2818
    assert(sbPtr);
 
 
2819
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
2820
    assert(marineStatusPointer);
 
 
2821
 
 
 
2822
    marineStatusPointer->gotapoint = 0;
 
 
2823
    marineStatusPointer->volleySize = 0;
 
 
2824
    NPC_InitMovementData(&marineStatusPointer->moveData);
 
 
2825
    InitWaypointManager(&marineStatusPointer->waypointManager);
 
 
2826
    marineStatusPointer->lastState = marineStatusPointer->behaviourState;
 
 
2827
    marineStatusPointer->behaviourState = MBS_Retreating;
 
 
2828
    marineStatusPointer->stateTimer = MARINE_NEAR_TIMEBETWEENFIRING;                     
 
 
2829
    marineStatusPointer->fearmodule = NULL;
 
 
2830
    /* It'll get set on state execution. */
 
 
2831
 
 
 
2832
    if ((FastRandom() & 65535) < 32767)
 
 
2833
    {
 
 
2834
        marineStatusPointer->Target_Expression = 2;
 
 
2835
        Marine_PanicScream(sbPtr);
 
 
2836
    }
 
 
2837
    else
 
 
2838
    {
 
 
2839
        marineStatusPointer->Target_Expression = 1;
 
 
2840
    }
 
 
2841
}
 
 
2842
 
 
 
2843
static void GetFirstRandomDirection(MARINE_STATUS_BLOCK *marineStatusPointer,VECTORCH *output) 
 
 
2844
{
 
 
2845
    MATRIXCH tempmat;
 
 
2846
    EULER tempeul;
 
 
2847
    VECTORCH tempvec = { 0, 0, 65535 };
 
 
2848
    int rnum = FastRandom() & 65535;
 
 
2849
 
 
 
2850
    rnum >>= 4;
 
 
2851
 
 
 
2852
    tempeul.EulerY = rnum;
 
 
2853
    tempeul.EulerX = 0;
 
 
2854
    tempeul.EulerZ = 0;
 
 
2855
 
 
 
2856
    CreateEulerMatrix(&tempeul, &tempmat);
 
 
2857
 
 
 
2858
    RotateAndCopyVector(&tempvec,output,&tempmat);
 
 
2859
 
 
 
2860
    marineStatusPointer->lastroundhit = (rnum<<20)+(rnum<<4);
 
 
2861
}
 
 
2862
 
 
 
2863
static void GetNewRandomDirection(MARINE_STATUS_BLOCK *marineStatusPointer) 
 
 
2864
{
 
 
2865
    int rnum = FastRandom() & 65535;
 
 
2866
    marineStatusPointer->lastroundhit &= 65535;
 
 
2867
    marineStatusPointer->lastroundhit |= rnum << 16;
 
 
2868
}
 
 
2869
 
 
 
2870
static void TurnToFaceRandomDirection(MARINE_STATUS_BLOCK *marineStatusPointer,VECTORCH *output) 
 
 
2871
{
 
 
2872
    MATRIXCH tempmat;
 
 
2873
    EULER tempeul;
 
 
2874
    VECTORCH tempvec = { 0, 0, 65535 };
 
 
2875
 
 
 
2876
    int currentangle = marineStatusPointer->lastroundhit  & 65535;
 
 
2877
    int targetangle = (marineStatusPointer->lastroundhit >> 16) & 65535;
 
 
2878
 
 
 
2879
    int deltaangle = targetangle - currentangle;
 
 
2880
    int deltaangle2 = deltaangle;
 
 
2881
 
 
 
2882
    if (deltaangle < 0)
 
 
2883
        deltaangle += 65536;
 
 
2884
 
 
 
2885
    if (deltaangle > 32767)
 
 
2886
    {
 
 
2887
        currentangle -= NormalFrameTime >> 1;
 
 
2888
 
 
 
2889
        if (currentangle < 0)
 
 
2890
            currentangle += 65536;
 
 
2891
    }
 
 
2892
    else
 
 
2893
    {
 
 
2894
        currentangle += NormalFrameTime >> 1;
 
 
2895
 
 
 
2896
        if (currentangle > 65535)
 
 
2897
            currentangle -= 65536;
 
 
2898
    }
 
 
2899
 
 
 
2900
    /* Overshoot test. */
 
 
2901
    deltaangle = targetangle - currentangle;
 
 
2902
 
 
 
2903
    if ((deltaangle * deltaangle2) <= 0)
 
 
2904
    {
 
 
2905
        currentangle = targetangle;
 
 
2906
    }
 
 
2907
 
 
 
2908
    assert(currentangle < 65536);
 
 
2909
    marineStatusPointer->lastroundhit &= ~65535;
 
 
2910
    marineStatusPointer->lastroundhit |= currentangle;
 
 
2911
 
 
 
2912
    currentangle >>= 4;
 
 
2913
    tempeul.EulerX = 0;
 
 
2914
    tempeul.EulerY = currentangle;
 
 
2915
    tempeul.EulerZ = 0;
 
 
2916
 
 
 
2917
    CreateEulerMatrix(&tempeul,&tempmat);
 
 
2918
    RotateAndCopyVector(&tempvec,output,&tempmat);
 
 
2919
}
 
 
2920
 
 
 
2921
static STATE_RETURN_CONDITION Execute_MFS_Wait(STRATEGYBLOCK *sbPtr)
 
 
2922
{
 
 
2923
    AIMODULE *targetModule = NULL;
 
 
2924
    assert(sbPtr);
 
 
2925
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
2926
    assert(marineStatusPointer);
 
 
2927
 
 
 
2928
    if (marineStatusPointer->suspicious)
 
 
2929
    {
 
 
2930
        VECTORCH orientationDirn;
 
 
2931
 
 
 
2932
        orientationDirn.vx =  marineStatusPointer->suspect_point.vx - sbPtr->DynPtr->Position.vx;
 
 
2933
        orientationDirn.vy = 0;
 
 
2934
        orientationDirn.vz = marineStatusPointer->suspect_point.vz - sbPtr->DynPtr->Position.vz;
 
 
2935
        int correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE);
 
 
2936
        marineStatusPointer->gotapoint = 0;
 
 
2937
    }
 
 
2938
 
 
 
2939
    /* Might want to spin on the spot. */
 
 
2940
    if (marineStatusPointer->gotapoint == 1)
 
 
2941
    {
 
 
2942
        VECTORCH orientationDirn;
 
 
2943
 
 
 
2944
        orientationDirn.vx = marineStatusPointer->wanderData.worldPosition.vx - sbPtr->DynPtr->Position.vx;
 
 
2945
        orientationDirn.vy = 0;
 
 
2946
        orientationDirn.vz = marineStatusPointer->wanderData.worldPosition.vz - sbPtr->DynPtr->Position.vz;
 
 
2947
 
 
 
2948
        if (NPCOrientateToVector(sbPtr, &orientationDirn, ONE_FIXED))
 
 
2949
        {
 
 
2950
            marineStatusPointer->gotapoint = 2;
 
 
2951
            /* Done. */
 
 
2952
        }
 
 
2953
    }
 
 
2954
    else if (!marineStatusPointer->gotapoint)
 
 
2955
    {
 
 
2956
        GetPointToFaceMarineTowards(sbPtr,&marineStatusPointer->wanderData.worldPosition);
 
 
2957
    }
 
 
2958
 
 
 
2959
    /* See if you're allowed to respond. */
 
 
2960
 
 
 
2961
    switch(marineStatusPointer->Mission)
 
 
2962
    {
 
 
2963
        case MM_Wait_Then_Wander:
 
 
2964
        case MM_Guard:
 
 
2965
            return SRC_No_Change;
 
 
2966
        default:
 
 
2967
        break;
 
 
2968
    }
 
 
2969
 
 
 
2970
    /* Possible response?  LocalGuarders are allowed to wander. */
 
 
2971
 
 
 
2972
    if (NpcSquad.alertZone && (marineStatusPointer->Mission != MM_LocalGuard) && (marineStatusPointer->Mission != MM_NonCom))
 
 
2973
    {
 
 
2974
        if (sbPtr->containingModule->m_aimodule != NpcSquad.alertZone)
 
 
2975
        {
 
 
2976
            if (NpcSquad.responseLevel > 0)
 
 
2977
            {
 
 
2978
                /* Picked up a target.  Can we move to respond? */
 
 
2979
                targetModule = FarNPC_GetTargetAIModuleForMarineRespond(sbPtr);
 
 
2980
 
 
 
2981
                if (targetModule)
 
 
2982
                {
 
 
2983
                    NpcSquad.responseLevel--;
 
 
2984
                    return SRC_Request_Respond;
 
 
2985
                }
 
 
2986
            }
 
 
2987
        }
 
 
2988
    }
 
 
2989
 
 
 
2990
    /* Decrement the Far state timer */
 
 
2991
    marineStatusPointer->stateTimer -= NormalFrameTime;    
 
 
2992
    /* check if far state timer has timed-out. If so, it is time 
 
 
2993
    to do something. Otherwise just return. */
 
 
2994
 
 
 
2995
    if(marineStatusPointer->stateTimer > 0)
 
 
2996
        return SRC_No_Change;
 
 
2997
 
 
 
2998
    /* Might want to wander. */
 
 
2999
 
 
 
3000
    if ((FastRandom() & 65535) < 2048)
 
 
3001
    {
 
 
3002
        /* we should be wandering... we're bored of waiting. */
 
 
3003
        return SRC_Request_Wander;
 
 
3004
    }
 
 
3005
 
 
 
3006
    /* reset timer */
 
 
3007
    marineStatusPointer->stateTimer = MARINE_FAR_MOVE_TIME;                    
 
 
3008
 
 
 
3009
return SRC_No_Change;
 
 
3010
}
 
 
3011
 
 
 
3012
static void Marine_AngryScream(STRATEGYBLOCK *sbPtr) 
 
 
3013
{
 
 
3014
    assert(sbPtr);
 
 
3015
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
3016
    assert(marineStatusPointer);
 
 
3017
 
 
 
3018
    if (marineStatusPointer->Android)
 
 
3019
        return;
 
 
3020
 
 
 
3021
    if (marineStatusPointer->soundHandle2 == SOUND_NOACTIVEINDEX)
 
 
3022
    {
 
 
3023
        PlayMarineScream(marineStatusPointer->Voice, MSC_Angry, marineStatusPointer->VoicePitch,
 
 
3024
            &marineStatusPointer->soundHandle2, &sbPtr->DynPtr->Position);
 
 
3025
    }
 
 
3026
}
 
 
3027
 
 
 
3028
static STATE_RETURN_CONDITION Execute_MNS_PanicReloading(STRATEGYBLOCK *sbPtr)
 
 
3029
{
 
 
3030
    assert(sbPtr);
 
 
3031
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
3032
    assert(marineStatusPointer);
 
 
3033
 
 
 
3034
    assert(sbPtr->DynPtr);
 
 
3035
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
3036
 
 
 
3037
    if (!sbPtr->DisplayBlock)
 
 
3038
    {
 
 
3039
        /* We're far... do the timer! */
 
 
3040
        ProveHModel_Far(&marineStatusPointer->HModelController,sbPtr);
 
 
3041
    }
 
 
3042
 
 
 
3043
    /* Scream handling. */
 
 
3044
    if (marineStatusPointer->soundHandle2 == SOUND_NOACTIVEINDEX)
 
 
3045
    {
 
 
3046
        if (marineStatusPointer->incidentFlag)
 
 
3047
        {
 
 
3048
            if (Marine_HasHisMouthOpen(sbPtr))
 
 
3049
            {
 
 
3050
                if (marineStatusPointer->My_Weapon->id == MNPCW_MUnarmed)
 
 
3051
                    Marine_PanicScream(sbPtr);
 
 
3052
                else
 
 
3053
                    Marine_AngryScream(sbPtr);
 
 
3054
            }
 
 
3055
            else
 
 
3056
            {
 
 
3057
                /* Scream anyway? */
 
 
3058
                Marine_PanicScream(sbPtr);
 
 
3059
                /* Open the mouth? */
 
 
3060
                Marine_AssumePanicExpression(sbPtr);
 
 
3061
            }
 
 
3062
        }
 
 
3063
    }
 
 
3064
 
 
 
3065
    /* Clip management. */
 
 
3066
    if (marineStatusPointer->My_Weapon->ClipName)
 
 
3067
    {
 
 
3068
        SECTION_DATA *clip = GetThisSectionData(marineStatusPointer->HModelController.section_data, marineStatusPointer->My_Weapon->ClipName);
 
 
3069
 
 
 
3070
        if (clip)
 
 
3071
        {
 
 
3072
            /* Now, check keyframe flags. */
 
 
3073
            if (marineStatusPointer->HModelController.keyframe_flags & 4)
 
 
3074
            {
 
 
3075
                /* Vanish it. */
 
 
3076
                clip->flags |= (section_data_terminate_here | section_data_notreal);
 
 
3077
            }
 
 
3078
 
 
 
3079
            if (marineStatusPointer->HModelController.keyframe_flags & 1)
 
 
3080
            {
 
 
3081
                /* Trim it off. */
 
 
3082
                make_clip(clip, &clip->World_Offset, &clip->SecMat);
 
 
3083
            }
 
 
3084
 
 
 
3085
            if (marineStatusPointer->HModelController.keyframe_flags & 2)
 
 
3086
            {
 
 
3087
                /* Put it back. */
 
 
3088
                clip->flags &= (~(section_data_terminate_here | section_data_notreal));
 
 
3089
 
 
 
3090
                if (marineStatusPointer->My_Weapon->id == MNPCW_SADAR)
 
 
3091
                {
 
 
3092
                    /* Heaven help us. */
 
 
3093
 
 
 
3094
                    SECTION *root_section =
GetNamedHierarchyFromLibrary(marineStatusPointer->My_Weapon->Riffname,marineStatusPointer->My_Weapon->HierarchyName);
 
 
3095
                    assert(root_section);
 
 
3096
 
 
 
3097
                    Transmogrify_HModels(sbPtr,&marineStatusPointer->HModelController,root_section,0,1,1);
 
 
3098
                    ProveHModel_Far(&marineStatusPointer->HModelController,sbPtr);
 
 
3099
    marineStatusPointer->My_Gunflash_Section =
GetThisSectionData(marineStatusPointer->HModelController.section_data,marineStatusPointer->My_Weapon->GunflashName);
 
 
3100
marineStatusPointer->My_Elevation_Section =
GetThisSectionData(marineStatusPointer->HModelController.section_data,marineStatusPointer->My_Weapon->ElevationSection);
 
 
3101
                }
 
 
3102
            }
 
 
3103
        }
 
 
3104
    }
 
 
3105
 
 
 
3106
    if (HModelAnimation_IsFinished(&marineStatusPointer->HModelController))
 
 
3107
    {
 
 
3108
        marineStatusPointer->clipammo = marineStatusPointer->My_Weapon->clip_size;
 
 
3109
        return SRC_Request_Approach;
 
 
3110
    }
 
 
3111
 
 
 
3112
return SRC_No_Change;
 
 
3113
}
 
 
3114
 
 
 
3115
int MarineSight_FrustrumReject(STRATEGYBLOCK *sbPtr,VECTORCH *localOffset,STRATEGYBLOCK *target)
 
 
3116
{
 
 
3117
    assert(sbPtr->containingModule); 
 
 
3118
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
3119
 
 
 
3120
    if (marineStatusPointer->Target == NULL)
 
 
3121
    {
 
 
3122
        /* Chop off the top 45 degrees. */
 
 
3123
        if ( (localOffset->vz < 0) && (((localOffset->vy - 100) >= 0)
 
 
3124
            ||(((localOffset->vy - 100) < 0) && ((-(localOffset->vy - 100)) < (-localOffset->vz))) ))
 
 
3125
        {
 
 
3126
            /* 180 horizontal, 180 vertical. */
 
 
3127
            return 1;
 
 
3128
        }
 
 
3129
        else
 
 
3130
        {
 
 
3131
            return 0;
 
 
3132
        }
 
 
3133
    }
 
 
3134
    else if (marineStatusPointer->Target != target)
 
 
3135
    {
 
 
3136
        if ( (localOffset->vz < 0) 
 
 
3137
    //        && (localOffset->vz <  (localOffset->vy+500)) 
 
 
3138
    //         && (localOffset->vz > -(localOffset->vy+500)) 
 
 
3139
            ) {
 
 
3140
            /* 180 horizontal, 180 vertical. */
 
 
3141
            return 1;
 
 
3142
        }
 
 
3143
        else
 
 
3144
        {
 
 
3145
            return 0;
 
 
3146
        }
 
 
3147
    }
 
 
3148
    else
 
 
3149
    {
 
 
3150
        /* Slightly different now, for error correction. */
 
 
3151
        if (localOffset->vz < 0)
 
 
3152
        {
 
 
3153
            return 1;
 
 
3154
        }
 
 
3155
        else
 
 
3156
        {
 
 
3157
            /* 270 horizontal, 180 vertical. */
 
 
3158
            if ( ((localOffset->vx > 0) && (localOffset->vx < localOffset->vz)) || ((localOffset->vx < 0) &&
((-localOffset->vx) < localOffset->vz)) )
 
 
3159
                return 0;
 
 
3160
            else
 
 
3161
                return 1;
 
 
3162
        }
 
 
3163
    }
 
 
3164
}
 
 
3165
 
 
 
3166
static int MarineIsAwareOfTarget(STRATEGYBLOCK *sbPtr)
 
 
3167
{
 
 
3168
    int targetIsNotVisable = 0;
 
 
3169
 
 
 
3170
    /* Like MarineCanSeeTarget, but the 'Far' version:  should it hunt? */
 
 
3171
 
 
 
3172
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
3173
 
 
 
3174
    if (marineStatusPointer->Target != NULL)
 
 
3175
    {
 
 
3176
        VECTORCH offset;
 
 
3177
        offset.vx = sbPtr->DynPtr->Position.vx - marineStatusPointer->Target->DynPtr->Position.vx;
 
 
3178
        offset.vy = sbPtr->DynPtr->Position.vy - marineStatusPointer->Target->DynPtr->Position.vy;
 
 
3179
        offset.vz = sbPtr->DynPtr->Position.vz - marineStatusPointer->Target->DynPtr->Position.vz;
 
 
3180
        int dist = Approximate3dMagnitude(&offset);
 
 
3181
 
 
 
3182
        switch(marineStatusPointer->Target->type)
 
 
3183
        {
 
 
3184
            case I_BehaviourAlien:
 
 
3185
            {
 
 
3186
                ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)marineStatusPointer->Target->dataptr;
 
 
3187
 
 
 
3188
                if ((dist > MARINE_AUTODETECT_ALIEN) && !alienStatusPointer->CurrentLightAtAlien)
 
 
3189
                    targetIsNotVisable = !DynamicObjectIsMoving(marineStatusPointer->Target->DynPtr);
 
 
3190
            }
 
 
3191
            break;
 
 
3192
            case I_BehaviourAlienPlayer:
 
 
3193
 
 
 
3194
                if ((dist > MARINE_AUTODETECT_ALIEN) && !PlayerStatus.CurrentLightAtPlayer)
 
 
3195
                    targetIsNotVisable = !DynamicObjectIsMoving(PlayerStatus.sbptr->DynPtr);
 
 
3196
            break;
 
 
3197
            case I_BehaviourPredatorPlayer:
 
 
3198
                if(PlayerStatus.cloakOn && (dist > MARINE_AUTODETECT_CLOAKED_PREDATOR) && (PlayerStatus.CloakingEffectiveness == ONE_FIXED))
 
 
3199
                    targetIsNotVisable = 1;
 
 
3200
            break;
 
 
3201
            case I_BehaviourPredator:
 
 
3202
            {
 
 
3203
                PREDATOR_STATUS_BLOCK *predStatus = (PREDATOR_STATUS_BLOCK *)marineStatusPointer->Target->dataptr;
 
 
3204
 
 
 
3205
                assert(predStatus);
 
 
3206
 
 
 
3207
                if ((predStatus->CloakStatus == PCLOAK_On) && (dist > MARINE_AUTODETECT_CLOAKED_PREDATOR) &&
(predStatus->CloakingEffectiveness == ONE_FIXED))
 
 
3208
                    targetIsNotVisable = 1;
 
 
3209
            }
 
 
3210
            default:
 
 
3211
            break;
 
 
3212
        }
 
 
3213
 
 
 
3214
        if (marineStatusPointer->Target->DamageBlock.IsOnFire)
 
 
3215
            targetIsNotVisable = 0; /* Oh come ON. */
 
 
3216
 
 
 
3217
        if (!targetIsNotVisable)
 
 
3218
        {
 
 
3219
            if (!sbPtr->DisplayBlock)
 
 
3220
            {
 
 
3221
                if (marineStatusPointer->Target->containingModule)
 
 
3222
                {
 
 
3223
                    if (IsModuleVisibleFromModule(marineStatusPointer->Target->containingModule,sbPtr->containingModule))
 
 
3224
                    {
 
 
3225
                        /* Remember your suspicion! */
 
 
3226
                        marineStatusPointer->previous_suspicion = marineStatusPointer->suspicious;
 
 
3227
                        /* Seen, unset suspicion. */
 
 
3228
                        marineStatusPointer->suspicious = 1;
 
 
3229
                    return 1;
 
 
3230
                    }
 
 
3231
                }
 
 
3232
            }
 
 
3233
            else
 
 
3234
            {
 
 
3235
                if (MarineCanSeeTarget(sbPtr))
 
 
3236
                {
 
 
3237
                    /* Remember your suspicion! */
 
 
3238
                    marineStatusPointer->previous_suspicion = marineStatusPointer->suspicious;
 
 
3239
                    /* Near visibility - seen target, unset suspicion. */
 
 
3240
                    marineStatusPointer->suspicious = 1;
 
 
3241
                return 1;
 
 
3242
                }
 
 
3243
            }
 
 
3244
        }
 
 
3245
    }
 
 
3246
 
 
 
3247
    /* Lastly, is there something we want to investigate? */
 
 
3248
 
 
 
3249
    if (marineStatusPointer->suspicious)
 
 
3250
    {
 
 
3251
        if (!sbPtr->DisplayBlock)
 
 
3252
        {
 
 
3253
            /* Far case. */
 
 
3254
            MODULE *targetModule = ModuleFromPosition(&marineStatusPointer->suspect_point,sbPtr->containingModule);
 
 
3255
 
 
 
3256
            /* Target isn't guaranteed, is it? */
 
 
3257
 
 
 
3258
            if (targetModule && IsModuleVisibleFromModule(targetModule, sbPtr->containingModule))
 
 
3259
            {
 
 
3260
                /* Shouldn't have a target now. */
 
 
3261
                marineStatusPointer->Target = NULL;
 
 
3262
                return 0;
 
 
3263
                /* If there was something there, we should have picked it up by now. */
 
 
3264
            }
 
 
3265
            /* Still suspicious. */
 
 
3266
        }
 
 
3267
        else
 
 
3268
        {
 
 
3269
            /* Near case. */
 
 
3270
            VECTORCH offset;
 
 
3271
            MATRIXCH WtoL = sbPtr->DynPtr->OrientMat;
 
 
3272
            /* Arc reject. */
 
 
3273
 
 
 
3274
            offset.vx = sbPtr->DynPtr->Position.vx - marineStatusPointer->suspect_point.vx;
 
 
3275
            offset.vy = sbPtr->DynPtr->Position.vy - marineStatusPointer->suspect_point.vy;
 
 
3276
            offset.vz = sbPtr->DynPtr->Position.vz - marineStatusPointer->suspect_point.vz;
 
 
3277
 
 
 
3278
            TransposeMatrixCH(&WtoL);
 
 
3279
            RotateVector(&offset,&WtoL);
 
 
3280
            /* Do reject. */
 
 
3281
 
 
 
3282
            if (MarineSight_FrustrumReject(sbPtr, &offset, NULL))
 
 
3283
            {
 
 
3284
                if (IsThisObjectVisibleFromThisPosition(sbPtr->DisplayBlock,&marineStatusPointer->suspect_point))
 
 
3285
                {
 
 
3286
                    /* I know what you're going to say.  That's backwards. */
 
 
3287
                    /* By this point I would have thought there's no valid target. */
 
 
3288
                    marineStatusPointer->Target = NULL;
 
 
3289
                    return 0;
 
 
3290
                    /* Well, show me 'IsThisPositionVisibleFromThisObject' and I'll be happy to change it. */
 
 
3291
                }
 
 
3292
            }
 
 
3293
        }
 
 
3294
    }
 
 
3295
 
 
 
3296
return 0;
 
 
3297
}
 
 
3298
 
 
 
3299
static void ProcessFarMarineTargetModule(STRATEGYBLOCK *sbPtr, AIMODULE* targetModule)
 
 
3300
{
 
 
3301
    assert(sbPtr);
 
 
3302
    assert(targetModule);
 
 
3303
    assert(sbPtr->type == I_BehaviourMarine);
 
 
3304
 
 
 
3305
    NPC_TARGETMODULESTATUS targetStatus = GetTargetAIModuleStatus(sbPtr, targetModule,0);
 
 
3306
 
 
 
3307
    switch(targetStatus)
 
 
3308
    {
 
 
3309
        case NPCTM_NormalRoom:
 
 
3310
        case NPCTM_AirDuct:
 
 
3311
        case NPCTM_ProxDoorOpen:
 
 
3312
        case NPCTM_SecurityDoorOpen:
 
 
3313
            /* locate to target, and move thro' quick as we can't retrigger    */
 
 
3314
        case NPCTM_LiftDoorOpen:
 
 
3315
            // do nothing - can't use lifts
 
 
3316
        {
 
 
3317
            /* loacate to target */
 
 
3318
            LocateFarNPCInAIModule(sbPtr, targetModule);
 
 
3319
        }
 
 
3320
        break;
 
 
3321
        case NPCTM_NoEntryPoint:
 
 
3322
        case NPCTM_LiftDoorNotOpen:
 
 
3323
               /*  do nothing - can't open lift doors */
 
 
3324
        case NPCTM_LiftTeleport:
 
 
3325
        {
 
 
3326
            /* do nothing */
 
 
3327
            FarNpc_FlipAround(sbPtr);
 
 
3328
        break;
 
 
3329
        }
 
 
3330
        case NPCTM_ProxDoorNotOpen:
 
 
3331
        {
 
 
3332
            MODULE *renderModule = *targetModule->m_module_ptrs;
 
 
3333
            /* trigger the door, and set timer to quick so we can catch the door when it's open */
 
 
3334
            ((PROXDOOR_BEHAV_BLOCK *)renderModule->m_sbptr->dataptr)->marineTrigger = 1;
 
 
3335
        break;
 
 
3336
        }
 
 
3337
        case NPCTM_SecurityDoorNotOpen:
 
 
3338
        {
 
 
3339
            MODULE *renderModule = *targetModule->m_module_ptrs;
 
 
3340
            /* do some door opening stuff here. Door should stay open for long enough
 
 
3341
            for us to catch it open next time */
 
 
3342
            RequestState(renderModule->m_sbptr, 1, 0);
 
 
3343
           break;
 
 
3344
        }
 
 
3345
        default:
 
 
3346
        {
 
 
3347
            assert(1==0);
 
 
3348
        }
 
 
3349
    }
 
 
3350
}
 
 
3351
 
 
 
3352
static STATE_RETURN_CONDITION Execute_MFS_Respond(STRATEGYBLOCK *sbPtr)
 
 
3353
{
 
 
3354
    assert(sbPtr);
 
 
3355
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
3356
    assert(marineStatusPointer);
 
 
3357
 
 
 
3358
    /* Decrement the Far state timer */
 
 
3359
    marineStatusPointer->stateTimer -= NormalFrameTime;    
 
 
3360
 
 
 
3361
    #if MARINE_PRINT_STATE
 
 
3362
        if (marineStatusPointer->destinationmodule == NULL)
 
 
3363
            printf("Target module is NULL\n");
 
 
3364
        else
 
 
3365
            printf("Target module is %s\n",(*(marineStatusPointer->destinationmodule->m_module_ptrs))->name);
 
 
3366
    #endif
 
 
3367
 
 
 
3368
    /* check if far state timer has timed-out. If so, it is time to do something. Otherwise just return. */
 
 
3369
    if(marineStatusPointer->stateTimer > 0)
 
 
3370
        return SRC_No_Change;
 
 
3371
 
 
 
3372
    /* check for state changes */
 
 
3373
 
 
 
3374
    if (MarineIsAwareOfTarget(sbPtr))
 
 
3375
    {
 
 
3376
        /* Picked up a target. */
 
 
3377
        return SRC_Request_Approach;
 
 
3378
    }
 
 
3379
 
 
 
3380
    /* get the target module... */
 
 
3381
    AIMODULE *targetModule = FarNPC_GetTargetAIModuleForMarineRespond(sbPtr);
 
 
3382
 
 
 
3383
    if (targetModule == sbPtr->containingModule->m_aimodule)
 
 
3384
    {
 
 
3385
        /* We've arrived. */
 
 
3386
        DeprioritiseAlert(sbPtr->containingModule->m_aimodule);
 
 
3387
        /* Hey, if it's real, there'll be a new one soon enough. */
 
 
3388
        return SRC_Request_Wait;
 
 
3389
    }
 
 
3390
 
 
 
3391
    /* if there is no target module, it means that the pred is trapped in an
 
 
3392
    unlinked module. In this case, reset the timer and return. */            
 
 
3393
 
 
 
3394
    if(!targetModule)
 
 
3395
    {
 
 
3396
        /* We can't do it. */
 
 
3397
        return SRC_Request_Wait;
 
 
3398
    }
 
 
3399
 
 
 
3400
    /* Examine target, and decide what to do */
 
 
3401
    assert(AIModuleIsPhysical(targetModule));        
 
 
3402
    ProcessFarMarineTargetModule(sbPtr, targetModule);    
 
 
3403
    /* reset timer */
 
 
3404
    marineStatusPointer->stateTimer = MARINE_FAR_MOVE_TIME;                    
 
 
3405
    marineStatusPointer->destinationmodule = targetModule;
 
 
3406
 
 
 
3407
return SRC_No_Change;
 
 
3408
}
 
 
3409
 
 
 
3410
static void Marine_Enter_PanicReload_State(STRATEGYBLOCK *sbPtr) 
 
 
3411
{
 
 
3412
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
3413
 
 
 
3414
    if(marineStatusPointer->clipammo != marineStatusPointer->My_Weapon->clip_size)
 
 
3415
    {
 
 
3416
       
assert(HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,marineStatusPointer->My_Weapon->Reload_Sequence));
 
 
3417
 
 
 
3418
        marineStatusPointer->gotapoint = 0;
 
 
3419
        marineStatusPointer->internalState = 0;
 
 
3420
        marineStatusPointer->volleySize = 0;
 
 
3421
        marineStatusPointer->lastState = marineStatusPointer->behaviourState;
 
 
3422
        marineStatusPointer->behaviourState = MBS_PanicReloading;
 
 
3423
        marineStatusPointer->stateTimer = MARINE_NEARWAITTIME;
 
 
3424
 
 
 
3425
        {
 
 
3426
            /* There should be NO head turn delta. */
 
 
3427
            DELTA_CONTROLLER *delta = Get_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
 
 
3428
 
 
 
3429
            if (delta)
 
 
3430
                Remove_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
 
 
3431
        }
 
 
3432
 
 
 
3433
        if ((FastRandom() & 65535) < 32767)
 
 
3434
        {
 
 
3435
            marineStatusPointer->Target_Expression = 2;
 
 
3436
 
 
 
3437
            if (marineStatusPointer->My_Weapon->id == MNPCW_MUnarmed)
 
 
3438
                Marine_PanicScream(sbPtr);
 
 
3439
            else
 
 
3440
                Marine_AngryScream(sbPtr);
 
 
3441
        }
 
 
3442
        else
 
 
3443
        {
 
 
3444
            marineStatusPointer->Target_Expression = 1;
 
 
3445
        }
 
 
3446
 
 
 
3447
        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
3448
 
 
 
3449
        /* .... and stop the sound */
 
 
3450
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
3451
        {
 
 
3452
            Sound_Stop(marineStatusPointer->soundHandle);        
 
 
3453
            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
3454
        }
 
 
3455
 
 
 
3456
        if (HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,MSSS_Panic_Reload))
 
 
3457
            SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_Panic_Reload, -1, (ONE_FIXED>>3));
 
 
3458
        else
 
 
3459
            SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, marineStatusPointer->My_Weapon->Reload_Sequence, -1, (ONE_FIXED>>3));
 
 
3460
 
 
 
3461
        marineStatusPointer->HModelController.LoopAfterTweening = 0;
 
 
3462
    }
 
 
3463
}
 
 
3464
 
 
 
3465
static void Marine_Enter_PumpAction_State(STRATEGYBLOCK *sbPtr) 
 
 
3466
{
 
 
3467
    assert(sbPtr);
 
 
3468
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
3469
    assert(marineStatusPointer);
 
 
3470
    assert(HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,MSSS_PumpAction));
 
 
3471
 
 
 
3472
    /* Maintain many things from fire. */    
 
 
3473
    marineStatusPointer->gotapoint = 0;
 
 
3474
    marineStatusPointer->lastState = marineStatusPointer->behaviourState;
 
 
3475
    marineStatusPointer->behaviourState = MBS_PumpAction;
 
 
3476
 
 
 
3477
    {
 
 
3478
        /* There should be NO head turn delta. */
 
 
3479
        DELTA_CONTROLLER *delta = Get_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
 
 
3480
 
 
 
3481
        if (delta)
 
 
3482
            Remove_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
 
 
3483
    }
 
 
3484
 
 
 
3485
    /* Dunno if this is right. */
 
 
3486
    marineStatusPointer->Target_Expression = 1;
 
 
3487
 
 
 
3488
    DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
3489
 
 
 
3490
    /* .... and stop the sound */
 
 
3491
    if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
3492
    {
 
 
3493
        Sound_Stop(marineStatusPointer->soundHandle);        
 
 
3494
        Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
3495
    }
 
 
3496
 
 
 
3497
    if (marineStatusPointer->IAmCrouched)
 
 
3498
        SetMarineAnimationSequence(sbPtr, HMSQT_MarineCrouch, MCrSS_PumpAction, -1, (ONE_FIXED>>5));
 
 
3499
    else
 
 
3500
        SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_PumpAction, -1, (ONE_FIXED>>5));
 
 
3501
 
 
 
3502
    marineStatusPointer->HModelController.LoopAfterTweening = 0;
 
 
3503
}
 
 
3504
 
 
 
3505
static void Marine_Enter_Avoidance_State(STRATEGYBLOCK *sbPtr) 
 
 
3506
{
 
 
3507
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
3508
 
 
 
3509
    /* Make sure obstruction is set! */
 
 
3510
 
 
 
3511
    marineStatusPointer->gotapoint = 0;
 
 
3512
 
 
 
3513
    NPC_InitMovementData(&(marineStatusPointer->moveData));
 
 
3514
    InitWaypointManager(&marineStatusPointer->waypointManager);
 
 
3515
    NPCGetAvoidanceDirection(sbPtr, &(marineStatusPointer->moveData.avoidanceDirn),&marineStatusPointer->obstruction);                        
 
 
3516
    marineStatusPointer->volleySize = 0;
 
 
3517
    marineStatusPointer->lastState = marineStatusPointer->behaviourState;
 
 
3518
    marineStatusPointer->behaviourState = MBS_Avoidance;          
 
 
3519
    marineStatusPointer->stateTimer = NPC_AVOIDTIME;
 
 
3520
 
 
 
3521
    /* Don't interfere with expression... */
 
 
3522
}
 
 
3523
 
 
 
3524
static void Marine_Enter_Reload_State(STRATEGYBLOCK *sbPtr) 
 
 
3525
{
 
 
3526
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
3527
 
 
 
3528
    if(marineStatusPointer->clipammo != marineStatusPointer->My_Weapon->clip_size)
 
 
3529
    {
 
 
3530
       
assert(HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,marineStatusPointer->My_Weapon->Reload_Sequence));
 
 
3531
 
 
 
3532
        marineStatusPointer->gotapoint = marineStatusPointer->internalState = marineStatusPointer->volleySize = 0;
 
 
3533
        marineStatusPointer->lastState = marineStatusPointer->behaviourState;
 
 
3534
        marineStatusPointer->behaviourState = MBS_Reloading;
 
 
3535
        marineStatusPointer->stateTimer = MARINE_NEARWAITTIME;
 
 
3536
 
 
 
3537
        {
 
 
3538
            /* There should be NO head turn delta. */
 
 
3539
            DELTA_CONTROLLER *delta = Get_Delta_Sequence(&marineStatusPointer->HModelController, "sprintheaddelta");
 
 
3540
 
 
 
3541
            if (delta)
 
 
3542
                Remove_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
 
 
3543
        }
 
 
3544
 
 
 
3545
        /* Dunno if this is right. */
 
 
3546
        marineStatusPointer->Target_Expression = 1;
 
 
3547
 
 
 
3548
        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
3549
 
 
 
3550
        /* .... and stop the sound */
 
 
3551
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
3552
        {
 
 
3553
            Sound_Stop(marineStatusPointer->soundHandle);        
 
 
3554
            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
3555
        }
 
 
3556
 
 
 
3557
        SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, marineStatusPointer->My_Weapon->Reload_Sequence, -1, (ONE_FIXED>>3));
 
 
3558
        marineStatusPointer->HModelController.LoopAfterTweening = 0;
 
 
3559
    }
 
 
3560
}
 
 
3561
 
 
 
3562
static void Marine_Enter_Taunt_State(STRATEGYBLOCK *sbPtr) 
 
 
3563
{
 
 
3564
    assert(sbPtr);
 
 
3565
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
3566
    assert(marineStatusPointer);
 
 
3567
 
 
 
3568
    if (marineStatusPointer->Android)
 
 
3569
        return;
 
 
3570
 
 
 
3571
    {
 
 
3572
        /* There should be NO head turn delta. */
 
 
3573
        DELTA_CONTROLLER *delta = Get_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
 
 
3574
 
 
 
3575
        if (delta)
 
 
3576
            Remove_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
 
 
3577
    }
 
 
3578
 
 
 
3579
    if (HModelSequence_Exists(&marineStatusPointer->HModelController, (int)HMSQT_MarineStand, (int)MSSS_Taunt_One))
 
 
3580
    {
 
 
3581
        marineStatusPointer->gotapoint = marineStatusPointer->internalState = marineStatusPointer->volleySize = 0;
 
 
3582
        marineStatusPointer->lastState = marineStatusPointer->behaviourState;
 
 
3583
        marineStatusPointer->behaviourState = MBS_Taunting;
 
 
3584
        marineStatusPointer->stateTimer = MARINE_NEARWAITTIME;
 
 
3585
 
 
 
3586
        SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_Taunt_One, -1, (ONE_FIXED>>3));
 
 
3587
        marineStatusPointer->HModelController.LoopAfterTweening = 0;
 
 
3588
    }
 
 
3589
    else
 
 
3590
    {
 
 
3591
        Marine_Enter_Wait_State(sbPtr); /* Aw, forget it. */
 
 
3592
        return;
 
 
3593
    }
 
 
3594
 
 
 
3595
    if ((FastRandom() & 65535) < 32767)
 
 
3596
        marineStatusPointer->Target_Expression = 6;
 
 
3597
 
 
 
3598
    if (marineStatusPointer->soundHandle2 == SOUND_NOACTIVEINDEX)
 
 
3599
    {
 
 
3600
        PlayMarineScream(marineStatusPointer->Voice, MSC_Taunt, marineStatusPointer->VoicePitch,
 
 
3601
            &marineStatusPointer->soundHandle2, &sbPtr->DynPtr->Position);
 
 
3602
    }
 
 
3603
}
 
 
3604
 
 
 
3605
static void Marine_Enter_Respond_State(STRATEGYBLOCK *sbPtr)
 
 
3606
{
 
 
3607
    assert(sbPtr);
 
 
3608
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
3609
    assert(marineStatusPointer);
 
 
3610
 
 
 
3611
    marineStatusPointer->gotapoint = 0;
 
 
3612
    marineStatusPointer->volleySize = 0;
 
 
3613
    NPC_InitMovementData(&marineStatusPointer->moveData);
 
 
3614
    marineStatusPointer->lastState = marineStatusPointer->behaviourState;
 
 
3615
    marineStatusPointer->behaviourState = MBS_Responding;
 
 
3616
 
 
 
3617
    if (NpcSquad.responseLevel)
 
 
3618
        NpcSquad.responseLevel--;
 
 
3619
 
 
 
3620
    marineStatusPointer->stateTimer = MARINE_NEAR_TIMEBETWEENFIRING;                     
 
 
3621
 
 
 
3622
    /* Determined! */
 
 
3623
    marineStatusPointer->Target_Expression = 0;
 
 
3624
 
 
 
3625
    /* We must now be suspicious. */
 
 
3626
    marineStatusPointer->suspicious = MARINE_PARANOIA_TIME;
 
 
3627
    marineStatusPointer->suspect_point = NpcSquad.squad_suspect_point;
 
 
3628
 
 
 
3629
    /* That'll do as a default. */
 
 
3630
    if (NpcSquad.alertZone)
 
 
3631
    {
 
 
3632
        /* Gotta have a point. */
 
 
3633
        marineStatusPointer->suspect_point = NpcSquad.alertZone->m_world;
 
 
3634
    }
 
 
3635
 
 
 
3636
    /* Set this to zero when you get a *new* suspicion. */
 
 
3637
    marineStatusPointer->previous_suspicion = 0;
 
 
3638
    marineStatusPointer->using_squad_suspicion = 1;
 
 
3639
}
 
 
3640
 
 
 
3641
static void Marine_Enter_PullPistol_State(STRATEGYBLOCK *sbPtr) 
 
 
3642
{
 
 
3643
    assert(sbPtr);
 
 
3644
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
3645
    assert(marineStatusPointer);
 
 
3646
    assert(marineStatusPointer->My_Weapon->ARealMarine);
 
 
3647
 
 
 
3648
    marineStatusPointer->gotapoint = marineStatusPointer->internalState = marineStatusPointer->volleySize = 0;
 
 
3649
    marineStatusPointer->lastState = marineStatusPointer->behaviourState;
 
 
3650
    marineStatusPointer->behaviourState = MBS_GetWeapon;
 
 
3651
    marineStatusPointer->stateTimer = MARINE_NEARWAITTIME;
 
 
3652
 
 
 
3653
    {
 
 
3654
        /* There should be NO head turn delta... */
 
 
3655
        DELTA_CONTROLLER *delta = Get_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
 
 
3656
 
 
 
3657
        if (delta)
 
 
3658
            Remove_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
 
 
3659
 
 
 
3660
        /* ...and NO Minigun delta... */
 
 
3661
        delta = Get_Delta_Sequence(&marineStatusPointer->HModelController,"Minigun");
 
 
3662
 
 
 
3663
        if (delta)
 
 
3664
            Remove_Delta_Sequence(&marineStatusPointer->HModelController,"Minigun");
 
 
3665
 
 
 
3666
        /* ...and strip out HitDelta for now, too. */
 
 
3667
        delta = Get_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta");
 
 
3668
 
 
 
3669
        if (delta)
 
 
3670
            Remove_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta");
 
 
3671
    }
 
 
3672
 
 
 
3673
    /* Now, try to be clever... */
 
 
3674
    /* Turn into a pistol guy! */
 
 
3675
    const MARINE_WEAPON_DATA *pistol_data = &NPC_Marine_Weapons[MNPCW_PistolMarine];
 
 
3676
 
 
 
3677
    SECTION *root = GetNamedHierarchyFromLibrary(pistol_data->Riffname, pistol_data->HierarchyName);
 
 
3678
    assert(root);
 
 
3679
 
 
 
3680
    marineStatusPointer->HModelController.Sequence_Type = HMSQT_MarineStand;
 
 
3681
    marineStatusPointer->HModelController.Sub_Sequence = MSSS_Get_Weapon;
 
 
3682
    /* That's to put the pistol in the right place... */
 
 
3683
Transmogrify_HModels(sbPtr, &marineStatusPointer->HModelController, root, 1, 1, 0);
 
 
3684
marineStatusPointer->My_Weapon = pistol_data;
 
 
3685
marineStatusPointer->My_Gunflash_Section =
GetThisSectionData(marineStatusPointer->HModelController.section_data,marineStatusPointer->My_Weapon->GunflashName);
 
 
3686
marineStatusPointer->My_Elevation_Section =
GetThisSectionData(marineStatusPointer->HModelController.section_data,marineStatusPointer->My_Weapon->ElevationSection);
 
 
3687
 
 
 
3688
    /* Start loaded! */
 
 
3689
    marineStatusPointer->clipammo = marineStatusPointer->My_Weapon->clip_size;
 
 
3690
 
 
 
3691
    /* Dunno if this is right. */
 
 
3692
    marineStatusPointer->Target_Expression = 1;
 
 
3693
 
 
 
3694
    DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
3695
 
 
 
3696
    /* .... and stop the sound */
 
 
3697
    if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
3698
    {
 
 
3699
        Sound_Stop(marineStatusPointer->soundHandle);        
 
 
3700
        Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
3701
    }
 
 
3702
 
 
 
3703
    SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_Get_Weapon, -1, (ONE_FIXED>>3));
 
 
3704
    marineStatusPointer->HModelController.LoopAfterTweening = 0;
 
 
3705
 
 
 
3706
    /* Attempt to put the hitdelta back? */
 
 
3707
    if (HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,(int)MSSS_HitChestFront))
 
 
3708
    {
 
 
3709
    DELTA_CONTROLLER *delta =
Add_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta",(int)HMSQT_MarineStand,(int)MSSS_HitChestFront,(ONE_FIXED>>2));
 
 
3710
    assert(delta);
 
 
3711
    delta->Playing = 0;
 
 
3712
    }
 
 
3713
 
 
 
3714
    DeInitialise_HModel(&marineStatusPointer->HModelController);
 
 
3715
    ProveHModel_Far(&marineStatusPointer->HModelController,sbPtr);
 
 
3716
}
 
 
3717
 
 
 
3718
static void Marine_Enter_PanicFire_State(STRATEGYBLOCK *sbPtr) 
 
 
3719
{
 
 
3720
    assert(sbPtr);
 
 
3721
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
3722
    assert(marineStatusPointer);
 
 
3723
 
 
 
3724
    marineStatusPointer->gotapoint = 0;
 
 
3725
 
 
 
3726
    {
 
 
3727
        /* There should be NO head turn delta. */
 
 
3728
        DELTA_CONTROLLER *delta = Get_Delta_Sequence(&marineStatusPointer->HModelController, "sprintheaddelta");
 
 
3729
 
 
 
3730
        if (delta)
 
 
3731
            Remove_Delta_Sequence(&marineStatusPointer->HModelController, "sprintheaddelta");
 
 
3732
    }
 
 
3733
 
 
 
3734
    switch(marineStatusPointer->My_Weapon->id)
 
 
3735
    {
 
 
3736
        case MNPCW_SADAR:
 
 
3737
        case MNPCW_Skeeter:
 
 
3738
            Marine_Enter_PullPistol_State(sbPtr);
 
 
3739
        return;
 
 
3740
        case MNPCW_MMolotov:
 
 
3741
        {
 
 
3742
            if (marineStatusPointer->Target)
 
 
3743
                Marine_Enter_Firing_State(sbPtr);
 
 
3744
            else
 
 
3745
                Marine_Enter_Wait_State(sbPtr);
 
 
3746
        return;
 
 
3747
        }
 
 
3748
        case MNPCW_Flamethrower:
 
 
3749
        case MNPCW_MFlamer:
 
 
3750
            marineStatusPointer->weapon_variable = 0;
 
 
3751
        default:
 
 
3752
        break;
 
 
3753
    }
 
 
3754
 
 
 
3755
    marineStatusPointer->internalState = 0;
 
 
3756
    marineStatusPointer->lastState = marineStatusPointer->behaviourState;
 
 
3757
    marineStatusPointer->behaviourState = MBS_PanicFire;
 
 
3758
    marineStatusPointer->volleySize = 0;
 
 
3759
 
 
 
3760
    if (marineStatusPointer->My_Weapon->id != MNPCW_MPistol)
 
 
3761
        marineStatusPointer->lastroundhit = 0;
 
 
3762
 
 
 
3763
    marineStatusPointer->lasthitsection = NULL;
 
 
3764
    marineStatusPointer->stateTimer = marineStatusPointer->My_Weapon->FiringTime;                     
 
 
3765
 
 
 
3766
    if (marineStatusPointer->Target)
 
 
3767
        NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
 
 
3768
 
 
 
3769
    if ((FastRandom() & 65535) < 32767)
 
 
3770
    {
 
 
3771
        marineStatusPointer->Target_Expression = 2;
 
 
3772
 
 
 
3773
        if (marineStatusPointer->My_Weapon->id == MNPCW_MUnarmed)
 
 
3774
            Marine_PanicScream(sbPtr);
 
 
3775
        else
 
 
3776
            Marine_AngryScream(sbPtr);
 
 
3777
    }
 
 
3778
    else
 
 
3779
    {
 
 
3780
        marineStatusPointer->Target_Expression = 1;
 
 
3781
    }
 
 
3782
 
 
 
3783
    if (HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,(int)MSSS_WildFire_0))
 
 
3784
    {
 
 
3785
        /* *can* enter wild fire... */
 
 
3786
        /* Sequence will be set in the function. */
 
 
3787
    }
 
 
3788
    else
 
 
3789
    {
 
 
3790
        /* Aw, forget it. */
 
 
3791
        Marine_Enter_Retreat_State(sbPtr);
 
 
3792
        marineStatusPointer->suspicious = MARINE_PANIC_TIME;
 
 
3793
    }
 
 
3794
}
 
 
3795
 
 
 
3796
static int MarineRetreatsInTheFaceOfDanger(STRATEGYBLOCK *sbPtr)
 
 
3797
{
 
 
3798
    assert(sbPtr);
 
 
3799
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
3800
    assert(marineStatusPointer);
 
 
3801
 
 
 
3802
    /* This depends on mission, armament, and whether he's cornered. */
 
 
3803
 
 
 
3804
    if (marineStatusPointer->Android)
 
 
3805
        return 0;
 
 
3806
return 0; // NO FEAR 
 
 
3807
    switch (marineStatusPointer->Mission)
 
 
3808
    {
 
 
3809
        case MM_NonCom:
 
 
3810
        case MM_Guard:
 
 
3811
        case MM_Wander:
 
 
3812
        case MM_Wait_Then_Wander:
 
 
3813
        case MM_LocalGuard:
 
 
3814
        case MM_Pathfinder:
 
 
3815
            return ((FastRandom() & 65535) > marineStatusPointer->Courage);
 
 
3816
        default:
 
 
3817
            return 0;
 
 
3818
    }
 
 
3819
}
 
 
3820
 
 
 
3821
static void Marine_Enter_Wander_State(STRATEGYBLOCK *sbPtr) 
 
 
3822
{
 
 
3823
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
3824
 
 
 
3825
    marineStatusPointer->gotapoint = 0;
 
 
3826
 
 
 
3827
    NPC_InitMovementData(&(marineStatusPointer->moveData));
 
 
3828
    NPC_InitWanderData(&(marineStatusPointer->wanderData));
 
 
3829
    InitWaypointManager(&marineStatusPointer->waypointManager);
 
 
3830
    marineStatusPointer->volleySize = 0;
 
 
3831
    marineStatusPointer->lastState = marineStatusPointer->behaviourState;
 
 
3832
    marineStatusPointer->behaviourState = MBS_Wandering;
 
 
3833
    marineStatusPointer->stateTimer = MARINE_NEAR_TIMEBETWEENFIRING;                                 
 
 
3834
    marineStatusPointer->Target_Expression = 0;
 
 
3835
}
 
 
3836
 
 
 
3837
static void EndMarineMuzzleFlash(STRATEGYBLOCK *sbPtr, MARINE_STATUS_BLOCK *marineStatusPointer) 
 
 
3838
{
 
 
3839
    DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
3840
 
 
 
3841
    if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
3842
    {
 
 
3843
        Sound_Stop(marineStatusPointer->soundHandle);
 
 
3844
        Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
3845
    }
 
 
3846
}
 
 
3847
 
 
 
3848
static void WanderMission_SwitchState(STRATEGYBLOCK *sbPtr, STATE_RETURN_CONDITION state_result) 
 
 
3849
{
 
 
3850
    STATE_RETURN_CONDITION real_state_result;
 
 
3851
    /* Experiment: override result? */
 
 
3852
    switch (state_result)
 
 
3853
    {
 
 
3854
        case SRC_Request_Fire:
 
 
3855
        case SRC_Request_Approach:
 
 
3856
            if (MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
3857
            {
 
 
3858
                real_state_result = SRC_Request_Retreat;
 
 
3859
                break;
 
 
3860
            }
 
 
3861
        default:
 
 
3862
            real_state_result = state_result;
 
 
3863
            break;
 
 
3864
    }
 
 
3865
 
 
 
3866
    switch (real_state_result)
 
 
3867
    {
 
 
3868
        case SRC_No_Change:
 
 
3869
        {
 
 
3870
            /* No action. */
 
 
3871
        break;
 
 
3872
        }
 
 
3873
        case SRC_Request_Wait:
 
 
3874
        {
 
 
3875
            Marine_Enter_Wait_State(sbPtr);
 
 
3876
        break;
 
 
3877
        }
 
 
3878
        case SRC_Request_Fire:
 
 
3879
        {
 
 
3880
            Marine_Enter_Firing_State(sbPtr);
 
 
3881
        break;
 
 
3882
        }
 
 
3883
        case SRC_Request_PanicFire:
 
 
3884
        {
 
 
3885
            Marine_Enter_PanicFire_State(sbPtr);
 
 
3886
        break;
 
 
3887
        }
 
 
3888
        case SRC_Request_Avoidance:
 
 
3889
        {
 
 
3890
            Marine_Enter_Avoidance_State(sbPtr);
 
 
3891
        break;
 
 
3892
        }
 
 
3893
        case SRC_Request_Approach:
 
 
3894
        {
 
 
3895
            Marine_Enter_Approach_State(sbPtr);
 
 
3896
        break;
 
 
3897
        }
 
 
3898
        case SRC_Request_Wander:
 
 
3899
        {
 
 
3900
            Marine_Enter_Wander_State(sbPtr);
 
 
3901
        break;
 
 
3902
        }
 
 
3903
        case SRC_Request_Retreat:
 
 
3904
        {
 
 
3905
            Marine_Enter_Retreat_State(sbPtr);
 
 
3906
        break;
 
 
3907
        }
 
 
3908
        case SRC_Request_Respond:
 
 
3909
        {
 
 
3910
            Marine_Enter_Respond_State(sbPtr);
 
 
3911
        break;
 
 
3912
        }
 
 
3913
        case SRC_Request_PullPistol:
 
 
3914
        {
 
 
3915
            Marine_Enter_PullPistol_State(sbPtr);
 
 
3916
        break;
 
 
3917
        }
 
 
3918
        default:
 
 
3919
        {
 
 
3920
            /* How did we end up here? */
 
 
3921
            assert(0);
 
 
3922
            break;
 
 
3923
        }
 
 
3924
    }
 
 
3925
}
 
 
3926
 
 
 
3927
static STATE_RETURN_CONDITION Execute_MFS_Retreat(STRATEGYBLOCK *sbPtr)
 
 
3928
{
 
 
3929
    assert(sbPtr);
 
 
3930
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
3931
    assert(marineStatusPointer);
 
 
3932
 
 
 
3933
    /* Decrement the Far state timer */
 
 
3934
    marineStatusPointer->stateTimer -= NormalFrameTime << 1;
 
 
3935
    /* Double speed, remember? */
 
 
3936
 
 
 
3937
    /* check if far state timer has timed-out. If so, it is time
 
 
3938
    to do something. Otherwise just return. */
 
 
3939
    if(marineStatusPointer->stateTimer > 0)
 
 
3940
        return SRC_No_Change;
 
 
3941
 
 
 
3942
    AIMODULE *old_fearmod = marineStatusPointer->fearmodule;
 
 
3943
 
 
 
3944
    /* From where am I running? */
 
 
3945
    if(MarineIsAwareOfTarget(sbPtr))
 
 
3946
    {
 
 
3947
        marineStatusPointer->fearmodule = marineStatusPointer->Target->containingModule->m_aimodule;
 
 
3948
    }
 
 
3949
    else if (marineStatusPointer->fearmodule == NULL)
 
 
3950
    {
 
 
3951
        marineStatusPointer->fearmodule = sbPtr->containingModule->m_aimodule;
 
 
3952
    }
 
 
3953
 
 
 
3954
    if (marineStatusPointer->fearmodule != old_fearmod)
 
 
3955
        marineStatusPointer->destinationmodule = General_GetAIModuleForRetreat(sbPtr,marineStatusPointer->fearmodule,5);
 
 
3956
 
 
 
3957
    AIMODULE *targetModule = GetNextModuleForLink(sbPtr->containingModule->m_aimodule,marineStatusPointer->destinationmodule,6,0);
 
 
3958
 
 
 
3959
    if(!targetModule)
 
 
3960
    {
 
 
3961
        /* We can't do it. */
 
 
3962
        return SRC_Request_Wait;
 
 
3963
    }
 
 
3964
 
 
 
3965
    /* Examine target, and decide what to do */
 
 
3966
    assert(AIModuleIsPhysical(targetModule));        
 
 
3967
    ProcessFarMarineTargetModule(sbPtr, targetModule);    
 
 
3968
    /* reset timer */
 
 
3969
    marineStatusPointer->stateTimer = MARINE_FAR_MOVE_TIME;                    
 
 
3970
    marineStatusPointer->destinationmodule=targetModule;
 
 
3971
 
 
 
3972
return SRC_No_Change;
 
 
3973
}
 
 
3974
 
 
 
3975
static STATE_RETURN_CONDITION Execute_MNS_PumpAction(STRATEGYBLOCK *sbPtr)
 
 
3976
{
 
 
3977
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
3978
 
 
 
3979
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
3980
 
 
 
3981
    if (!sbPtr->DisplayBlock)
 
 
3982
    {
 
 
3983
        /* We're far... do the timer! */
 
 
3984
        ProveHModel_Far(&marineStatusPointer->HModelController,sbPtr);
 
 
3985
    }
 
 
3986
 
 
 
3987
    if (!HModelAnimation_IsFinished(&marineStatusPointer->HModelController))
 
 
3988
        return SRC_No_Change;
 
 
3989
 
 
 
3990
    /* Exit procedure... same as firing was. */
 
 
3991
 
 
 
3992
    if (marineStatusPointer->Target == NULL)
 
 
3993
        return SRC_Request_Wait;
 
 
3994
 
 
 
3995
    int range = VectorDistance(&marineStatusPointer->Target->DynPtr->Position, &sbPtr->DynPtr->Position);
 
 
3996
 
 
 
3997
    /* State timer should be continuous from fire state. */
 
 
3998
    if(marineStatusPointer->stateTimer > 0)
 
 
3999
        return SRC_Request_Fire;
 
 
4000
 
 
 
4001
    if(range < MARINE_CLOSE_APPROACH_DISTANCE)
 
 
4002
    {
 
 
4003
        /* renew firing, as we are still too close to approach */ 
 
 
4004
        marineStatusPointer->stateTimer = marineStatusPointer->My_Weapon->FiringTime;                     
 
 
4005
        marineStatusPointer->volleySize = 0;
 
 
4006
        assert(marineStatusPointer->Target);
 
 
4007
        NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
 
 
4008
 
 
 
4009
    return SRC_Request_Fire;
 
 
4010
    }
 
 
4011
    else
 
 
4012
    {
 
 
4013
        /* we are far enough away, so return to approach */
 
 
4014
        return (marineStatusPointer->Android) ? SRC_Request_Fire : SRC_Request_Approach;
 
 
4015
    }
 
 
4016
 
 
 
4017
return SRC_Request_Fire;
 
 
4018
}
 
 
4019
 
 
 
4020
static STATE_RETURN_CONDITION Execute_MNS_AcidAvoidance(STRATEGYBLOCK *sbPtr)
 
 
4021
{
 
 
4022
    VECTORCH velocityDirection = {0,0,0};
 
 
4023
 
 
 
4024
    /* Your mission: to advance out of the acid. */
 
 
4025
 
 
 
4026
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
4027
 
 
 
4028
    /* Where are we going? */
 
 
4029
 
 
 
4030
    marineStatusPointer->stateTimer -= NormalFrameTime;
 
 
4031
 
 
 
4032
    if (marineStatusPointer->stateTimer < 0)
 
 
4033
        return SRC_Request_Approach;
 
 
4034
 
 
 
4035
    /* Ok: should have a current target at this stage... */
 
 
4036
    NPCGetMovementDirection(sbPtr, &velocityDirection,
&(marineStatusPointer->wanderData.worldPosition),&marineStatusPointer->waypointManager);
 
 
4037
    NPCSetVelocity(sbPtr, &velocityDirection, marineStatusPointer->nearSpeed);    
 
 
4038
 
 
 
4039
    if (New_NPC_IsObstructed(sbPtr,&marineStatusPointer->avoidanceManager))
 
 
4040
        return SRC_Request_Avoidance; /* Go to all new avoidance. */
 
 
4041
 
 
 
4042
return SRC_No_Change;
 
 
4043
}
 
 
4044
 
 
 
4045
static STATE_RETURN_CONDITION Execute_MNS_GetWeapon(STRATEGYBLOCK *sbPtr)
 
 
4046
{
 
 
4047
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
4048
 
 
 
4049
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
4050
 
 
 
4051
    if (!sbPtr->DisplayBlock)
 
 
4052
    {
 
 
4053
        /* We're far... do the timer! */
 
 
4054
        ProveHModel_Far(&marineStatusPointer->HModelController,sbPtr);
 
 
4055
    }
 
 
4056
 
 
 
4057
    return (HModelAnimation_IsFinished(&marineStatusPointer->HModelController)) ? SRC_Request_Wait : SRC_No_Change;
 
 
4058
}
 
 
4059
 
 
 
4060
 
 
 
4061
static STATE_RETURN_CONDITION Execute_MNS_Reloading(STRATEGYBLOCK *sbPtr) // jadda
 
 
4062
{
 
 
4063
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
4064
 
 
 
4065
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
4066
 
 
 
4067
    if (!sbPtr->DisplayBlock)
 
 
4068
    {
 
 
4069
        /* We're far... do the timer! */
 
 
4070
        ProveHModel_Far(&marineStatusPointer->HModelController,sbPtr);
 
 
4071
    }
 
 
4072
 
 
 
4073
    if (marineStatusPointer->My_Weapon->ClipName)
 
 
4074
    {
 
 
4075
        SECTION_DATA *clip = GetThisSectionData(marineStatusPointer->HModelController.section_data, marineStatusPointer->My_Weapon->ClipName);
 
 
4076
 
 
 
4077
        if (clip)
 
 
4078
        {
 
 
4079
            /* Now, check keyframe flags. */
 
 
4080
            if (marineStatusPointer->HModelController.keyframe_flags & 4)
 
 
4081
            {
 
 
4082
                /* Vanish it. */
 
 
4083
                clip->flags |= (section_data_terminate_here | section_data_notreal);
 
 
4084
            }
 
 
4085
 
 
 
4086
            if (marineStatusPointer->HModelController.keyframe_flags & 1)
 
 
4087
            {
 
 
4088
                /* Trim it off. */
 
 
4089
                make_clip(clip, &clip->World_Offset, &clip->SecMat);
 
 
4090
            }
 
 
4091
 
 
 
4092
            if (marineStatusPointer->HModelController.keyframe_flags & 2)
 
 
4093
            {
 
 
4094
                /* Put it back. */
 
 
4095
                clip->flags &= (~(section_data_terminate_here | section_data_notreal));
 
 
4096
 
 
 
4097
                switch(marineStatusPointer->My_Weapon->id)
 
 
4098
                {
 
 
4099
                    case MNPCW_SADAR:
 
 
4100
                    case MNPCW_Skeeter:
 
 
4101
                    {
 
 
4102
                        /* Heaven help us. */
 
 
4103
 
 
 
4104
                        SECTION *root_section = GetNamedHierarchyFromLibrary(marineStatusPointer->My_Weapon->Riffname,
marineStatusPointer->My_Weapon->HierarchyName);
 
 
4105
                        assert(root_section);
 
 
4106
 
 
 
4107
                        Transmogrify_HModels(sbPtr,&marineStatusPointer->HModelController,root_section,0,1,1);
 
 
4108
                        ProveHModel_Far(&marineStatusPointer->HModelController,sbPtr);
 
 
4109
    marineStatusPointer->My_Gunflash_Section = GetThisSectionData(marineStatusPointer->HModelController.section_data,
marineStatusPointer->My_Weapon->GunflashName);
 
 
4110
    marineStatusPointer->My_Elevation_Section = GetThisSectionData(marineStatusPointer->HModelController.section_data,
marineStatusPointer->My_Weapon->ElevationSection);
 
 
4111
                    }
 
 
4112
                    default:
 
 
4113
                    break;
 
 
4114
                }
 
 
4115
            }
 
 
4116
        }
 
 
4117
    }
 
 
4118
 
 
 
4119
    if (HModelAnimation_IsFinished(&marineStatusPointer->HModelController))
 
 
4120
    {
 
 
4121
        marineStatusPointer->clipammo = marineStatusPointer->My_Weapon->clip_size;
 
 
4122
        marineStatusPointer->volleySize = 0;
 
 
4123
        marineStatusPointer->lastroundhit = 0;
 
 
4124
        marineStatusPointer->lasthitsection = NULL;
 
 
4125
        return SRC_Request_Approach;
 
 
4126
    }
 
 
4127
 
 
 
4128
return SRC_No_Change;
 
 
4129
}
 
 
4130
 
 
 
4131
static STATE_RETURN_CONDITION Execute_MNS_Taunting(STRATEGYBLOCK *sbPtr)
 
 
4132
{
 
 
4133
    assert(sbPtr);
 
 
4134
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
4135
    assert(marineStatusPointer);
 
 
4136
 
 
 
4137
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
4138
 
 
 
4139
    if (!sbPtr->DisplayBlock)
 
 
4140
    {
 
 
4141
        /* We're far... do the timer! */
 
 
4142
        ProveHModel_Far(&marineStatusPointer->HModelController,sbPtr);
 
 
4143
    }
 
 
4144
 
 
 
4145
return HModelAnimation_IsFinished(&marineStatusPointer->HModelController) ? SRC_Request_Wait : SRC_No_Change;
 
 
4146
}
 
 
4147
 
 
 
4148
static STATE_RETURN_CONDITION Execute_MNS_Retreat(STRATEGYBLOCK *sbPtr)
 
 
4149
{
 
 
4150
    VECTORCH velocityDirection = {0,0,0};
 
 
4151
 
 
 
4152
    /* Your mission: to advance out of trouble, even if near. */
 
 
4153
 
 
 
4154
    assert(sbPtr);
 
 
4155
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
4156
    assert(marineStatusPointer);
 
 
4157
 
 
 
4158
    AIMODULE *old_fearmod = marineStatusPointer->fearmodule;
 
 
4159
 
 
 
4160
    /* From where am I running? */
 
 
4161
    if(MarineIsAwareOfTarget(sbPtr))
 
 
4162
    {
 
 
4163
        marineStatusPointer->fearmodule = marineStatusPointer->Target->containingModule->m_aimodule;
 
 
4164
    }
 
 
4165
    else if (marineStatusPointer->fearmodule == NULL)
 
 
4166
    {
 
 
4167
        marineStatusPointer->fearmodule = sbPtr->containingModule->m_aimodule;
 
 
4168
 
 
 
4169
        if (CHEATMODE_TERROR == UserProfile.active_bonus)
 
 
4170
        {
 
 
4171
            /* Better correct... */
 
 
4172
            marineStatusPointer->fearmodule = PlayerStatus.sbptr->containingModule->m_aimodule;
 
 
4173
        }
 
 
4174
    }
 
 
4175
 
 
 
4176
    if (marineStatusPointer->fearmodule != old_fearmod)
 
 
4177
        marineStatusPointer->destinationmodule = General_GetAIModuleForRetreat(sbPtr,marineStatusPointer->fearmodule,5);
 
 
4178
 
 
 
4179
    {
 
 
4180
        AIMODULE *targetModule = GetNextModuleForLink(sbPtr->containingModule->m_aimodule,marineStatusPointer->destinationmodule,6,0);
 
 
4181
 
 
 
4182
        if ((targetModule == sbPtr->containingModule->m_aimodule) || (targetModule == NULL))
 
 
4183
            return (marineStatusPointer->Target) ? SRC_Request_PanicFire : SRC_Request_Wait; /* There's no-where to run! */
 
 
4184
 
 
 
4185
        assert(targetModule);
 
 
4186
 
 
 
4187
        FARENTRYPOINT *thisEp = GetAIModuleEP(targetModule,sbPtr->containingModule->m_aimodule);
 
 
4188
 
 
 
4189
        if (!thisEp)
 
 
4190
        {
 
 
4191
            //printf("This assert is a busted adjacency!\nNo EP between %s and %s.",targetModule->name,sbPtr->containingModule->name);
 
 
4192
            printf("This assert is a busted adjacency!");
 
 
4193
            assert(thisEp);
 
 
4194
        }
 
 
4195
 
 
 
4196
        /* If that fired, there's a farped adjacency. */
 
 
4197
        assert(thisEp->alien_only == 0);
 
 
4198
        /* If that fired, GetNextModuleForLink went wrong. */
 
 
4199
 
 
 
4200
        marineStatusPointer->wanderData.worldPosition = thisEp->position;
 
 
4201
        marineStatusPointer->wanderData.worldPosition.vx += targetModule->m_world.vx;
 
 
4202
        marineStatusPointer->wanderData.worldPosition.vy += targetModule->m_world.vy;
 
 
4203
        marineStatusPointer->wanderData.worldPosition.vz += targetModule->m_world.vz;
 
 
4204
    }
 
 
4205
 
 
 
4206
    /* Ok: should have a current target at this stage... */
 
 
4207
    NPCGetMovementDirection(sbPtr, &velocityDirection,
&(marineStatusPointer->wanderData.worldPosition),&marineStatusPointer->waypointManager);
 
 
4208
 
 
 
4209
    if (marineStatusPointer->Target)
 
 
4210
    {
 
 
4211
        VECTORCH vectotarget;
 
 
4212
        /* Are we running in a stupid direction? */
 
 
4213
        vectotarget.vx = marineStatusPointer->Target->DynPtr->Position.vx - sbPtr->DynPtr->Position.vx;
 
 
4214
        vectotarget.vy = marineStatusPointer->Target->DynPtr->Position.vy - sbPtr->DynPtr->Position.vy;
 
 
4215
        vectotarget.vz = marineStatusPointer->Target->DynPtr->Position.vz - sbPtr->DynPtr->Position.vz;
 
 
4216
        Normalise(&vectotarget);
 
 
4217
 
 
 
4218
        if (DotProduct(&vectotarget,&velocityDirection) > 55000)
 
 
4219
            return SRC_Request_PanicFire; /* Argh!  He's in the way! */
 
 
4220
    }
 
 
4221
 
 
 
4222
    NPCSetVelocity(sbPtr, &velocityDirection, marineStatusPointer->nearSpeed);    
 
 
4223
 
 
 
4224
    /* ...so we must be here for the duration. */
 
 
4225
 
 
 
4226
    /* Scream handling. */
 
 
4227
    if (marineStatusPointer->soundHandle2 == SOUND_NOACTIVEINDEX)
 
 
4228
    {
 
 
4229
        if (marineStatusPointer->incidentFlag && Marine_HasHisMouthOpen(sbPtr))
 
 
4230
        {
 
 
4231
            if (marineStatusPointer->My_Weapon->id == MNPCW_MUnarmed)
 
 
4232
                Marine_PanicScream(sbPtr);
 
 
4233
        }
 
 
4234
    }
 
 
4235
 
 
 
4236
    /* test here for impeding collisions, and not being able to reach target... */
 
 
4237
    #if ALL_NEW_AVOIDANCE
 
 
4238
    {
 
 
4239
        if (New_NPC_IsObstructed(sbPtr,&marineStatusPointer->avoidanceManager))
 
 
4240
            return SRC_Request_Avoidance; /* Go to all new avoidance. */
 
 
4241
    }
 
 
4242
    #else
 
 
4243
    {
 
 
4244
        STRATEGYBLOCK *destructableObject = NULL;
 
 
4245
 
 
 
4246
        NPC_IsObstructed(sbPtr,&(marineStatusPointer->moveData),&marineStatusPointer->obstruction,&destructableObject);
 
 
4247
 
 
 
4248
        if(marineStatusPointer->obstruction.environment || marineStatusPointer->obstruction.otherCharacter)
 
 
4249
            return SRC_Request_Avoidance;
 
 
4250
 
 
 
4251
        if(marineStatusPointer->obstruction.destructableObject)
 
 
4252
        {
 
 
4253
            assert(destructableObject);
 
 
4254
            CauseDamageToObject(destructableObject,&TemplateAmmo[AMMO_NPC_OBSTACLE_CLEAR].MaxDamage, ONE_FIXED,NULL);
 
 
4255
        }
 
 
4256
    }
 
 
4257
 
 
 
4258
    if(NPC_CannotReachTarget(&marineStatusPointer->moveData, &marineStatusPointer->wanderData.worldPosition, &velocityDirection))
 
 
4259
    {
 
 
4260
        /* go to avoidance */
 
 
4261
        /* no sequence change required */
 
 
4262
 
 
 
4263
        marineStatusPointer->obstruction.environment = 1;
 
 
4264
        marineStatusPointer->obstruction.destructableObject = 0;
 
 
4265
        marineStatusPointer->obstruction.otherCharacter = 0;
 
 
4266
        marineStatusPointer->obstruction.anySingleObstruction = 0;
 
 
4267
 
 
 
4268
        return SRC_Request_Avoidance;
 
 
4269
    }
 
 
4270
    #endif
 
 
4271
 
 
 
4272
return SRC_No_Change;
 
 
4273
}
 
 
4274
 
 
 
4275
static STATE_RETURN_CONDITION Execute_MNS_Respond(STRATEGYBLOCK *sbPtr)
 
 
4276
{
 
 
4277
    VECTORCH velocityDirection = {0,0,0};
 
 
4278
 
 
 
4279
    /* Your mission: to advance into the alert zone, even if near. */
 
 
4280
 
 
 
4281
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
4282
 
 
 
4283
    /* should we change to approach state? */
 
 
4284
    if(MarineIsAwareOfTarget(sbPtr))
 
 
4285
        return SRC_Request_Approach;
 
 
4286
 
 
 
4287
    /* If we've picked up a new target, go for it. */
 
 
4288
    if (sbPtr->containingModule->m_aimodule == NpcSquad.alertZone)
 
 
4289
    {
 
 
4290
        /* We're here! */
 
 
4291
        DeprioritiseAlert(sbPtr->containingModule->m_aimodule);
 
 
4292
        /* Hey, if it's real, there'll be a new one soon enough. */
 
 
4293
        return SRC_Request_Approach;
 
 
4294
    }
 
 
4295
 
 
 
4296
    {
 
 
4297
        AIMODULE *targetModule = FarNPC_GetTargetAIModuleForMarineRespond(sbPtr);
 
 
4298
 
 
 
4299
        if (targetModule == sbPtr->containingModule->m_aimodule)
 
 
4300
        {
 
 
4301
            /* Looks like we've arrived. */
 
 
4302
            /* Hey, it'll drop through. */
 
 
4303
            return SRC_Request_Approach;
 
 
4304
        }
 
 
4305
 
 
 
4306
        if (!targetModule)
 
 
4307
        {
 
 
4308
            /* Must be sealed off. */
 
 
4309
            return SRC_Request_Wait;
 
 
4310
        }                
 
 
4311
 
 
 
4312
        FARENTRYPOINT *thisEp = GetAIModuleEP(targetModule,sbPtr->containingModule->m_aimodule);
 
 
4313
 
 
 
4314
        if (!thisEp)
 
 
4315
        {
 
 
4316
            //printf("This assert is a busted adjacency!\nNo EP between %s and %s.",targetModule->name,sbPtr->containingModule->name);
 
 
4317
            printf("This assert is a busted adjacency!");
 
 
4318
            assert(thisEp);
 
 
4319
        }
 
 
4320
 
 
 
4321
        /* If that fired, there's a farped adjacency. */
 
 
4322
        assert(thisEp->alien_only == 0);
 
 
4323
        /* If that fired, GetNextModuleForLink went wrong. */
 
 
4324
 
 
 
4325
        marineStatusPointer->wanderData.worldPosition = thisEp->position;
 
 
4326
        marineStatusPointer->wanderData.worldPosition.vx += targetModule->m_world.vx;
 
 
4327
        marineStatusPointer->wanderData.worldPosition.vy += targetModule->m_world.vy;
 
 
4328
        marineStatusPointer->wanderData.worldPosition.vz += targetModule->m_world.vz;
 
 
4329
    }
 
 
4330
 
 
 
4331
    /* ok: should have a current target at this stage... */
 
 
4332
    NPCGetMovementDirection(sbPtr, &velocityDirection,
&(marineStatusPointer->wanderData.worldPosition),&marineStatusPointer->waypointManager);
 
 
4333
    NPCSetVelocity(sbPtr, &velocityDirection, marineStatusPointer->nearSpeed);    
 
 
4334
 
 
 
4335
    /* test here for impeding collisions, and not being able to reach target... */
 
 
4336
    #if ALL_NEW_AVOIDANCE
 
 
4337
    {
 
 
4338
        if (New_NPC_IsObstructed(sbPtr,&marineStatusPointer->avoidanceManager))
 
 
4339
            return SRC_Request_Avoidance;
 
 
4340
    }
 
 
4341
    #else
 
 
4342
    {
 
 
4343
        STRATEGYBLOCK *destructableObject = NULL;
 
 
4344
 
 
 
4345
        NPC_IsObstructed(sbPtr,&(marineStatusPointer->moveData),&marineStatusPointer->obstruction,&destructableObject);
 
 
4346
 
 
 
4347
        if(marineStatusPointer->obstruction.environment || marineStatusPointer->obstruction.otherCharacter)
 
 
4348
            return SRC_Request_Avoidance;
 
 
4349
 
 
 
4350
        if(marineStatusPointer->obstruction.destructableObject)
 
 
4351
        {
 
 
4352
            assert(destructableObject);
 
 
4353
            CauseDamageToObject(destructableObject,&TemplateAmmo[AMMO_NPC_OBSTACLE_CLEAR].MaxDamage, ONE_FIXED,NULL);
 
 
4354
        }
 
 
4355
    }
 
 
4356
 
 
 
4357
    if(NPC_CannotReachTarget(&marineStatusPointer->moveData, &marineStatusPointer->wanderData.worldPosition, &velocityDirection))
 
 
4358
    {
 
 
4359
        /* go to avoidance */
 
 
4360
        /* no sequence change required */
 
 
4361
 
 
 
4362
        marineStatusPointer->obstruction.environment = 1;
 
 
4363
        marineStatusPointer->obstruction.destructableObject = 0;
 
 
4364
        marineStatusPointer->obstruction.otherCharacter = 0;
 
 
4365
        marineStatusPointer->obstruction.anySingleObstruction = 0;
 
 
4366
 
 
 
4367
        return SRC_Request_Avoidance;
 
 
4368
    }
 
 
4369
    #endif
 
 
4370
 
 
 
4371
return SRC_No_Change;
 
 
4372
}
 
 
4373
 
 
 
4374
static void Marine_MirrorSuspectPoint(STRATEGYBLOCK *sbPtr)
 
 
4375
{
 
 
4376
    VECTORCH offset;
 
 
4377
 
 
 
4378
    assert(sbPtr);
 
 
4379
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
4380
    assert(marineStatusPointer);
 
 
4381
 
 
 
4382
    offset.vx = marineStatusPointer->suspect_point.vx - sbPtr->DynPtr->Position.vx;
 
 
4383
    offset.vy = marineStatusPointer->suspect_point.vy - sbPtr->DynPtr->Position.vy;
 
 
4384
    offset.vz = marineStatusPointer->suspect_point.vz - sbPtr->DynPtr->Position.vz;
 
 
4385
 
 
 
4386
    marineStatusPointer->suspect_point.vx = sbPtr->DynPtr->Position.vx - offset.vx;
 
 
4387
    marineStatusPointer->suspect_point.vy = sbPtr->DynPtr->Position.vy - offset.vy;
 
 
4388
    marineStatusPointer->suspect_point.vz = sbPtr->DynPtr->Position.vz - offset.vz;
 
 
4389
}
 
 
4390
 
 
 
4391
static STATE_RETURN_CONDITION Execute_MNS_SentryMode(STRATEGYBLOCK *sbPtr) 
 
 
4392
{
 
 
4393
    VECTORCH orientationDirn,offset,velocityDirection;
 
 
4394
 
 
 
4395
    assert(sbPtr);
 
 
4396
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
4397
    assert(marineStatusPointer);
 
 
4398
 
 
 
4399
    offset.vx = sbPtr->DynPtr->Position.vx - marineStatusPointer->my_spot.vx;
 
 
4400
    offset.vy = sbPtr->DynPtr->Position.vy - marineStatusPointer->my_spot.vy;
 
 
4401
    offset.vz = sbPtr->DynPtr->Position.vz - marineStatusPointer->my_spot.vz;
 
 
4402
    /* Fix for midair start points, grrrr. */
 
 
4403
    offset.vy >>= 2;
 
 
4404
 
 
 
4405
    /* Find distance off spot. */
 
 
4406
    int dist = Approximate3dMagnitude(&offset);
 
 
4407
 
 
 
4408
    if ((dist < SENTRY_SENSITIVITY) && (sbPtr->containingModule->m_aimodule == marineStatusPointer->missionmodule))
 
 
4409
    {
 
 
4410
        /* On the spot. */
 
 
4411
        /* zero velocity */
 
 
4412
        assert(sbPtr->DynPtr);
 
 
4413
        sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
4414
 
 
 
4415
        int correctlyOrientated = 0;
 
 
4416
 
 
 
4417
        if(MarineIsAwareOfTarget(sbPtr))
 
 
4418
        {
 
 
4419
            assert(marineStatusPointer->Target);
 
 
4420
            NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
 
 
4421
 
 
 
4422
            /* orientate to firing point first */
 
 
4423
            orientationDirn.vx = marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
 
 
4424
            orientationDirn.vy = 0;
 
 
4425
            orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
 
 
4426
            correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE);
 
 
4427
        }
 
 
4428
        else if (marineStatusPointer->suspicious)
 
 
4429
        {
 
 
4430
            /* Orientate to suspect point? */
 
 
4431
            orientationDirn.vx = marineStatusPointer->suspect_point.vx - sbPtr->DynPtr->Position.vx;
 
 
4432
            orientationDirn.vy = 0;
 
 
4433
            orientationDirn.vz = marineStatusPointer->suspect_point.vz - sbPtr->DynPtr->Position.vz;
 
 
4434
            correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE);
 
 
4435
 
 
 
4436
            if (correctlyOrientated)
 
 
4437
            {
 
 
4438
                /* Please don't be staring at a wall... */
 
 
4439
                VECTORCH sight_vec;
 
 
4440
                SECTION_DATA *head_sec = GetThisSectionData(marineStatusPointer->HModelController.section_data, "head");
 
 
4441
                assert(head_sec);
 
 
4442
 
 
 
4443
                sight_vec.vx = sbPtr->DynPtr->OrientMat.mat31;
 
 
4444
                sight_vec.vy = sbPtr->DynPtr->OrientMat.mat32;
 
 
4445
                sight_vec.vz = sbPtr->DynPtr->OrientMat.mat33;
 
 
4446
 
 
 
4447
                FindPolygonInLineOfSight(&sight_vec,&head_sec->World_Offset,0,sbPtr->DisplayBlock);
 
 
4448
 
 
 
4449
                if(LOS_ObjectHitPtr)
 
 
4450
                {
 
 
4451
                    if((NULL == LOS_ObjectHitPtr->ObStrategyBlock) || (LOS_ObjectHitPtr->ObStrategyBlock->DisplayBlock &&
LOS_ObjectHitPtr->ObStrategyBlock->DisplayBlock->Module))
 
 
4452
                    {
 
 
4453
                        if (LOS_Lambda < 2000)
 
 
4454
                            Marine_MirrorSuspectPoint(sbPtr);
 
 
4455
                    }
 
 
4456
                }
 
 
4457
            }
 
 
4458
 
 
 
4459
            marineStatusPointer->gotapoint = 0;
 
 
4460
        }
 
 
4461
        else
 
 
4462
        {
 
 
4463
            if (marineStatusPointer->gotapoint)
 
 
4464
            {
 
 
4465
                VECTORCH orientationDirn;
 
 
4466
 
 
 
4467
                orientationDirn.vx = marineStatusPointer->wanderData.worldPosition.vx - sbPtr->DynPtr->Position.vx;
 
 
4468
                orientationDirn.vy = 0;
 
 
4469
                orientationDirn.vz = marineStatusPointer->wanderData.worldPosition.vz - sbPtr->DynPtr->Position.vz;
 
 
4470
                int correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE);
 
 
4471
            }
 
 
4472
            else
 
 
4473
            {
 
 
4474
                GetPointToFaceMarineTowards(sbPtr,&marineStatusPointer->wanderData.worldPosition);
 
 
4475
            }
 
 
4476
        }
 
 
4477
 
 
 
4478
        if(!correctlyOrientated)
 
 
4479
            return SRC_No_Change;
 
 
4480
 
 
 
4481
        if (marineStatusPointer->Target == NULL)
 
 
4482
        {
 
 
4483
            /* Must be suspicious? */
 
 
4484
            if (marineStatusPointer->suspicious)
 
 
4485
                return SRC_No_Change;
 
 
4486
 
 
 
4487
            /* Else drop through? */
 
 
4488
        }
 
 
4489
        else
 
 
4490
        {
 
 
4491
            /* We have a target, and should be correctly orientated. */
 
 
4492
 
 
 
4493
            if (MarineCanSeeTarget(sbPtr))
 
 
4494
            {
 
 
4495
                /* I can see! */
 
 
4496
                int range = VectorDistance(&marineStatusPointer->Target->DynPtr->Position, &sbPtr->DynPtr->Position);
 
 
4497
 
 
 
4498
                if ((marineStatusPointer->My_Weapon->MaxRange == -1) || (range < marineStatusPointer->My_Weapon->MaxRange))
 
 
4499
                    return SRC_Request_Fire;    
 
 
4500
            }
 
 
4501
            else
 
 
4502
            {
 
 
4503
                /* Eh? */
 
 
4504
                if (marineStatusPointer->suspicious)
 
 
4505
                    return SRC_No_Change;
 
 
4506
            }
 
 
4507
        }
 
 
4508
 
 
 
4509
        /* Well, we're stuck with sentrymode. */
 
 
4510
        if (marineStatusPointer->gotapoint)
 
 
4511
        {
 
 
4512
            VECTORCH orientationDirn;
 
 
4513
 
 
 
4514
            orientationDirn.vx = marineStatusPointer->wanderData.worldPosition.vx - sbPtr->DynPtr->Position.vx;
 
 
4515
            orientationDirn.vy = 0;
 
 
4516
            orientationDirn.vz = marineStatusPointer->wanderData.worldPosition.vz - sbPtr->DynPtr->Position.vz;
 
 
4517
            int correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE);
 
 
4518
        }
 
 
4519
        else
 
 
4520
        {
 
 
4521
            GetPointToFaceMarineTowards(sbPtr,&marineStatusPointer->wanderData.worldPosition);
 
 
4522
        }
 
 
4523
 
 
 
4524
    return SRC_No_Change;
 
 
4525
    }
 
 
4526
 
 
 
4527
    /* If you got here, you're lost. */
 
 
4528
 
 
 
4529
    if (marineStatusPointer->missionmodule == NULL)
 
 
4530
        return SRC_No_Change; /* Fused! */
 
 
4531
 
 
 
4532
    if (sbPtr->containingModule->m_aimodule != marineStatusPointer->missionmodule)
 
 
4533
    {
 
 
4534
        AIMODULE *targetModule;
 
 
4535
        /* Not even in the same module! */
 
 
4536
 
 
 
4537
        if(marineStatusPointer->wanderData.currentModule == NPC_NOWANDERMODULE)
 
 
4538
            NPC_InitMovementData(&(marineStatusPointer->moveData));
 
 
4539
 
 
 
4540
        if ((marineStatusPointer->wanderData.currentModule == NPC_NOWANDERMODULE)
 
 
4541
            ||(marineStatusPointer->wanderData.currentModule != sbPtr->containingModule->m_aimodule->m_index))
 
 
4542
        {
 
 
4543
            targetModule = GetNextModuleForLink(sbPtr->containingModule->m_aimodule,marineStatusPointer->missionmodule,7,0);
 
 
4544
 
 
 
4545
            if (targetModule)
 
 
4546
            {
 
 
4547
                FARENTRYPOINT *thisEp = GetAIModuleEP(targetModule, sbPtr->containingModule->m_aimodule);
 
 
4548
 
 
 
4549
                if(thisEp)
 
 
4550
                {
 
 
4551
                    /* aha. an ep!... */ 
 
 
4552
                    VECTORCH thisEpWorld = thisEp->position;
 
 
4553
 
 
 
4554
                    thisEpWorld.vx += targetModule->m_world.vx;
 
 
4555
                    thisEpWorld.vy += targetModule->m_world.vy;
 
 
4556
                    thisEpWorld.vz += targetModule->m_world.vz;            
 
 
4557
 
 
 
4558
                    marineStatusPointer->wanderData.currentModule = sbPtr->containingModule->m_aimodule->m_index;
 
 
4559
                     marineStatusPointer->wanderData.worldPosition = thisEpWorld;
 
 
4560
 
 
 
4561
                    assert(thisEp->alien_only == 0);
 
 
4562
                    /* If that fired, GetNextModuleForLink went wrong. */
 
 
4563
                }
 
 
4564
                else
 
 
4565
                {
 
 
4566
                    /* Failure case. */
 
 
4567
                    marineStatusPointer->wanderData.currentModule = NPC_NOWANDERMODULE;
 
 
4568
                }
 
 
4569
            }
 
 
4570
            else
 
 
4571
            {
 
 
4572
                /* Another failure case. */
 
 
4573
                marineStatusPointer->wanderData.currentModule = NPC_NOWANDERMODULE;
 
 
4574
            }
 
 
4575
        }
 
 
4576
 
 
 
4577
        /* if we still haven't got one, bimble about in this one for a bit. */
 
 
4578
        if(marineStatusPointer->wanderData.currentModule == NPC_NOWANDERMODULE)
 
 
4579
        {
 
 
4580
            NPC_InitMovementData(&(marineStatusPointer->moveData));
 
 
4581
            marineStatusPointer->moveData.lastModule=marineStatusPointer->lastmodule;
 
 
4582
            NPC_FindAIWanderTarget(sbPtr,&(marineStatusPointer->wanderData),&(marineStatusPointer->moveData),0);
 
 
4583
        }
 
 
4584
 
 
 
4585
        if(marineStatusPointer->wanderData.currentModule == NPC_NOWANDERMODULE)
 
 
4586
        {
 
 
4587
            /* STILL broken!  We're in a lot of trouble. */
 
 
4588
            return SRC_No_Change;
 
 
4589
        }
 
 
4590
 
 
 
4591
        /* Should have a legal target. */
 
 
4592
        NPCGetMovementDirection(sbPtr, &velocityDirection,
&(marineStatusPointer->wanderData.worldPosition),&marineStatusPointer->waypointManager);
 
 
4593
    }
 
 
4594
    else
 
 
4595
    {
 
 
4596
        /* Same module, wrong place.  Just go for it.  */
 
 
4597
        NPCGetMovementDirection(sbPtr, &velocityDirection, &marineStatusPointer->my_spot, &marineStatusPointer->waypointManager);
 
 
4598
    }
 
 
4599
 
 
 
4600
    NPCSetVelocity(sbPtr, &velocityDirection, marineStatusPointer->nearSpeed);    
 
 
4601
 
 
 
4602
    /* test here for impeding collisions, and not being able to reach target... */
 
 
4603
    #if ALL_NEW_AVOIDANCE
 
 
4604
    {
 
 
4605
        if (New_NPC_IsObstructed(sbPtr,&marineStatusPointer->avoidanceManager))
 
 
4606
            return SRC_Request_Avoidance;
 
 
4607
    }
 
 
4608
    #else
 
 
4609
    {
 
 
4610
        STRATEGYBLOCK *destructableObject = NULL;
 
 
4611
        NPC_IsObstructed(sbPtr,&(marineStatusPointer->moveData),&marineStatusPointer->obstruction,&destructableObject);
 
 
4612
 
 
 
4613
        if(marineStatusPointer->obstruction.environment || marineStatusPointer->obstruction.otherCharacter)
 
 
4614
            return SRC_Request_Avoidance;
 
 
4615
 
 
 
4616
        if(marineStatusPointer->obstruction.destructableObject)
 
 
4617
        {
 
 
4618
            assert(destructableObject);
 
 
4619
            CauseDamageToObject(destructableObject,&TemplateAmmo[AMMO_NPC_OBSTACLE_CLEAR].MaxDamage, ONE_FIXED,NULL);
 
 
4620
        }
 
 
4621
    }
 
 
4622
 
 
 
4623
    if(NPC_CannotReachTarget(&marineStatusPointer->moveData, &marineStatusPointer->wanderData.worldPosition, &velocityDirection))
 
 
4624
    {
 
 
4625
        /* go to avoidance */
 
 
4626
        /* no sequence change required */
 
 
4627
 
 
 
4628
        marineStatusPointer->obstruction.environment = 1;
 
 
4629
        marineStatusPointer->obstruction.destructableObject = 0;
 
 
4630
        marineStatusPointer->obstruction.otherCharacter = 0;
 
 
4631
        marineStatusPointer->obstruction.anySingleObstruction = 0;
 
 
4632
 
 
 
4633
        return SRC_Request_Avoidance;
 
 
4634
    }
 
 
4635
    #endif
 
 
4636
 
 
 
4637
return SRC_No_Change;
 
 
4638
}
 
 
4639
 
 
 
4640
static STATE_RETURN_CONDITION Execute_MNS_Wait(STRATEGYBLOCK *sbPtr)
 
 
4641
{
 
 
4642
    /* wait until near state timer runs out, then wander:
 
 
4643
    alternatively, if we can attack the target, go straight to approach */
 
 
4644
 
 
 
4645
    assert(sbPtr);
 
 
4646
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
4647
    assert(marineStatusPointer);
 
 
4648
 
 
 
4649
    /* zero velocity */
 
 
4650
    assert(sbPtr->DynPtr);
 
 
4651
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
4652
 
 
 
4653
    /* test for attack */
 
 
4654
    if (MarineIsAwareOfTarget(sbPtr))
 
 
4655
        return ((FastRandom() & 65535) < 32767) ? SRC_Request_Approach : SRC_Request_Fire;
 
 
4656
 
 
 
4657
    if (marineStatusPointer->suspicious)
 
 
4658
    {
 
 
4659
        VECTORCH targetPosition = marineStatusPointer->suspect_point;
 
 
4660
 
 
 
4661
        targetPosition.vx -= sbPtr->DynPtr->Position.vx;
 
 
4662
        targetPosition.vy -= sbPtr->DynPtr->Position.vy;
 
 
4663
        targetPosition.vz -= sbPtr->DynPtr->Position.vz;
 
 
4664
 
 
 
4665
        /* Let's try doing this. */
 
 
4666
        targetPosition.vy >>= 2;
 
 
4667
 
 
 
4668
        int range = Approximate3dMagnitude(&targetPosition);
 
 
4669
 
 
 
4670
        if (range > SUSPECT_SENSITIVITY)
 
 
4671
        {
 
 
4672
            /* Too far away! */
 
 
4673
            marineStatusPointer->suspicious = MARINE_PARANOIA_TIME;
 
 
4674
            /* Used to unset suspicion at that point. */
 
 
4675
            return SRC_Request_Approach;
 
 
4676
        }
 
 
4677
        else
 
 
4678
        {
 
 
4679
            /* We could at least turn to face it. */
 
 
4680
            VECTORCH orientationDirn;
 
 
4681
            int correctlyOrientated;
 
 
4682
 
 
 
4683
            orientationDirn.vx = marineStatusPointer->suspect_point.vx - sbPtr->DynPtr->Position.vx;
 
 
4684
            orientationDirn.vy = 0;
 
 
4685
            orientationDirn.vz = marineStatusPointer->suspect_point.vz - sbPtr->DynPtr->Position.vz;
 
 
4686
 
 
 
4687
            if (sbPtr->DamageBlock.IsOnFire)
 
 
4688
            {
 
 
4689
                /* Can't handle 'suspect points' stuck to them! */
 
 
4690
                correctlyOrientated = 1;
 
 
4691
            }
 
 
4692
            else
 
 
4693
            {
 
 
4694
                correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE);
 
 
4695
            }
 
 
4696
 
 
 
4697
            /* For when suspicion times out. */
 
 
4698
            marineStatusPointer->gotapoint = 0;
 
 
4699
 
 
 
4700
            if (correctlyOrientated)
 
 
4701
            {
 
 
4702
                /* Please don't be staring at a wall... */
 
 
4703
                VECTORCH sight_vec;
 
 
4704
                SECTION_DATA *head_sec = GetThisSectionData(marineStatusPointer->HModelController.section_data, "head");
 
 
4705
                assert(head_sec);
 
 
4706
 
 
 
4707
                sight_vec.vx = sbPtr->DynPtr->OrientMat.mat31;
 
 
4708
                sight_vec.vy = sbPtr->DynPtr->OrientMat.mat32;
 
 
4709
                sight_vec.vz = sbPtr->DynPtr->OrientMat.mat33;
 
 
4710
 
 
 
4711
                FindPolygonInLineOfSight(&sight_vec, &head_sec->World_Offset, 0, sbPtr->DisplayBlock);
 
 
4712
 
 
 
4713
                if((NULL == LOS_ObjectHitPtr->ObStrategyBlock) || (LOS_ObjectHitPtr->ObStrategyBlock->DisplayBlock &&
LOS_ObjectHitPtr->ObStrategyBlock->DisplayBlock->Module))
 
 
4714
                {
 
 
4715
                    if (LOS_Lambda < 2000)
 
 
4716
                        Marine_MirrorSuspectPoint(sbPtr);
 
 
4717
                }
 
 
4718
            }
 
 
4719
        }
 
 
4720
    }
 
 
4721
 
 
 
4722
    /* Think Sequences. */
 
 
4723
 
 
 
4724
    if (NpcSquad.alertZone && (marineStatusPointer->Mission != MM_LocalGuard) && (marineStatusPointer->Mission != MM_NonCom))
 
 
4725
    {
 
 
4726
        /* Are we already there? */
 
 
4727
        if (sbPtr->containingModule->m_aimodule != NpcSquad.alertZone)
 
 
4728
        {
 
 
4729
            if (NpcSquad.responseLevel > 0)
 
 
4730
            {
 
 
4731
                /* Picked up a target.  Can we move to respond? */
 
 
4732
                AIMODULE *targetModule = FarNPC_GetTargetAIModuleForMarineRespond(sbPtr);
 
 
4733
 
 
 
4734
                if (targetModule)
 
 
4735
                    return SRC_Request_Respond;
 
 
4736
            }
 
 
4737
        }
 
 
4738
    }
 
 
4739
 
 
 
4740
    /* still waiting: decrement timer */
 
 
4741
    marineStatusPointer->stateTimer -= NormalFrameTime;
 
 
4742
 
 
 
4743
    if(marineStatusPointer->stateTimer <= 0)
 
 
4744
    {
 
 
4745
        /* Might want to wander. */
 
 
4746
 
 
 
4747
        if ((FastRandom() & 65535) < 2048)
 
 
4748
            return SRC_Request_Wander; /* we should be wandering... we're bored of waiting. */
 
 
4749
 
 
 
4750
        /* No, I'm happy waiting. */
 
 
4751
        marineStatusPointer->stateTimer = MARINE_NEARWAITTIME;
 
 
4752
    return SRC_No_Change;
 
 
4753
    }
 
 
4754
 
 
 
4755
    /* Well, we're stuck with waiting. */
 
 
4756
 
 
 
4757
    if (marineStatusPointer->suspicious)
 
 
4758
        return SRC_No_Change; /* Stay facing the suspect point. */
 
 
4759
 
 
 
4760
    if (marineStatusPointer->gotapoint)
 
 
4761
    {
 
 
4762
        VECTORCH orientationDirn;
 
 
4763
 
 
 
4764
        orientationDirn.vx = marineStatusPointer->wanderData.worldPosition.vx - sbPtr->DynPtr->Position.vx;
 
 
4765
        orientationDirn.vy = 0;
 
 
4766
        orientationDirn.vz = marineStatusPointer->wanderData.worldPosition.vz - sbPtr->DynPtr->Position.vz;
 
 
4767
        int correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE);
 
 
4768
    }
 
 
4769
    else
 
 
4770
    {
 
 
4771
        GetPointToFaceMarineTowards(sbPtr,&marineStatusPointer->wanderData.worldPosition);
 
 
4772
    }
 
 
4773
 
 
 
4774
return SRC_No_Change;
 
 
4775
}
 
 
4776
 
 
 
4777
void NPC_GetBimbleTarget(STRATEGYBLOCK *sbPtr,VECTORCH *output) 
 
 
4778
{
 
 
4779
    int success = 0;
 
 
4780
 
 
 
4781
    /* Get a random position in the same module. */
 
 
4782
 
 
 
4783
    MODULE *my_module = sbPtr->containingModule;
 
 
4784
 
 
 
4785
    while (!success)
 
 
4786
    {
 
 
4787
        do
 
 
4788
        {
 
 
4789
            output->vx = FastRandom() & 65535;
 
 
4790
            output->vx += my_module->m_minx;
 
 
4791
 
 
 
4792
        } while (!( (output->vx > my_module->m_minx) && (output->vx < my_module->m_maxx) ));
 
 
4793
 
 
 
4794
        do
 
 
4795
        {
 
 
4796
            output->vz = FastRandom() & 65535;
 
 
4797
            output->vz += my_module->m_minz;
 
 
4798
 
 
 
4799
        } while (!( (output->vz > my_module->m_minz) && (output->vz < my_module->m_maxz) ));
 
 
4800
 
 
 
4801
        output->vy = sbPtr->DynPtr->Position.vy;
 
 
4802
        output->vy -= my_module->m_world.vy;
 
 
4803
 
 
 
4804
        if (!( (output->vy > my_module->m_miny) && (output->vy < my_module->m_maxy) ))
 
 
4805
        {
 
 
4806
            do
 
 
4807
            {
 
 
4808
                output->vy = FastRandom() & 65535;
 
 
4809
                output->vy += my_module->m_miny;
 
 
4810
 
 
 
4811
            } while (!( (output->vy > my_module->m_miny) && (output->vy < my_module->m_maxy) ));
 
 
4812
        }
 
 
4813
 
 
 
4814
        assert(PointIsInModule(my_module,output));
 
 
4815
 
 
 
4816
        output->vx += my_module->m_world.vx;
 
 
4817
        output->vy += my_module->m_world.vy;
 
 
4818
        output->vz += my_module->m_world.vz;
 
 
4819
 
 
 
4820
        /* Check for waypoints? */
 
 
4821
 
 
 
4822
        if (my_module->m_waypoints)
 
 
4823
        {
 
 
4824
            VECTORCH alternate;
 
 
4825
 
 
 
4826
            if (GetPositionValidity(my_module,output,&alternate) == NULL)
 
 
4827
            {
 
 
4828
                /* Failure! */
 
 
4829
                success = 0;
 
 
4830
            }
 
 
4831
            else
 
 
4832
            {
 
 
4833
                if ( (alternate.vx != output->vx) || (alternate.vy != output->vy) || (alternate.vz != output->vz) )
 
 
4834
                {
 
 
4835
                    *output = alternate;
 
 
4836
                    /* Success! */
 
 
4837
                    success = 1;
 
 
4838
                }
 
 
4839
                else
 
 
4840
                {
 
 
4841
                    /* Success! */
 
 
4842
                    success = 1;
 
 
4843
                }
 
 
4844
            }
 
 
4845
        }
 
 
4846
        else
 
 
4847
        {
 
 
4848
            /* Success! */
 
 
4849
            success = 1;
 
 
4850
        }
 
 
4851
    }
 
 
4852
}
 
 
4853
 
 
 
4854
static STATE_RETURN_CONDITION Execute_MNS_Wander(STRATEGYBLOCK *sbPtr)
 
 
4855
{
 
 
4856
    VECTORCH velocityDirection = {0,0,0};
 
 
4857
 
 
 
4858
    assert(sbPtr);
 
 
4859
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
4860
    assert(marineStatusPointer);
 
 
4861
 
 
 
4862
    /* should we change to approach state? */
 
 
4863
    if (MarineIsAwareOfTarget(sbPtr) || marineStatusPointer->suspicious)
 
 
4864
        return SRC_Request_Approach; /* doesn't require a sequence change */
 
 
4865
 
 
 
4866
    /* Is there a new alert? */
 
 
4867
    if (NpcSquad.alertZone && (marineStatusPointer->Mission != MM_LocalGuard) && (marineStatusPointer->Mission != MM_NonCom))
 
 
4868
    {
 
 
4869
        /* Are we already there? */
 
 
4870
        if (sbPtr->containingModule->m_aimodule != NpcSquad.alertZone)
 
 
4871
        {
 
 
4872
            if (NpcSquad.responseLevel > 0)
 
 
4873
            {
 
 
4874
                /* Picked up a target.  Can we move to respond? */
 
 
4875
                AIMODULE *targetModule = FarNPC_GetTargetAIModuleForMarineRespond(sbPtr);
 
 
4876
 
 
 
4877
                if (targetModule)
 
 
4878
                    return SRC_Request_Respond;
 
 
4879
            }
 
 
4880
        }
 
 
4881
    }
 
 
4882
 
 
 
4883
    /* Are we bored of wandering yet? */
 
 
4884
 
 
 
4885
    marineStatusPointer->stateTimer -= NormalFrameTime;
 
 
4886
 
 
 
4887
    if (marineStatusPointer->stateTimer <= 0)
 
 
4888
    {
 
 
4889
        /* Time to make a decision. */
 
 
4890
        marineStatusPointer->stateTimer = MARINE_NEARWAITTIME;
 
 
4891
 
 
 
4892
        if ((FastRandom() & 65535) < 8192)
 
 
4893
            return SRC_Request_Wait; /* This is too tiring... let's just wait around a while. */
 
 
4894
    }
 
 
4895
 
 
 
4896
    /* Are we using bimble rules? */
 
 
4897
 
 
 
4898
    if (marineStatusPointer->wanderData.currentModule == NPC_BIMBLINGINMODULE)
 
 
4899
    {
 
 
4900
        /* Range to target... */
 
 
4901
        int range = VectorDistance((&marineStatusPointer->wanderData.worldPosition),(&sbPtr->DynPtr->Position));
 
 
4902
 
 
 
4903
        if (range < 2000)
 
 
4904
        {
 
 
4905
            /* Reset system, try again. */
 
 
4906
            marineStatusPointer->wanderData.currentModule = NPC_NOWANDERMODULE;
 
 
4907
            marineStatusPointer->moveData.lastModule = NULL;
 
 
4908
        }
 
 
4909
    }
 
 
4910
    else
 
 
4911
    {
 
 
4912
        /* wander target aquisition: if no target, or moved module */
 
 
4913
        assert(sbPtr->containingModule);
 
 
4914
 
 
 
4915
        if(marineStatusPointer->wanderData.currentModule == NPC_NOWANDERMODULE)
 
 
4916
        {
 
 
4917
            NPC_InitMovementData(&(marineStatusPointer->moveData));
 
 
4918
            marineStatusPointer->moveData.lastModule = marineStatusPointer->lastmodule;
 
 
4919
            NPC_FindAIWanderTarget(sbPtr,&(marineStatusPointer->wanderData),&(marineStatusPointer->moveData),0);
 
 
4920
        }
 
 
4921
        else if(marineStatusPointer->wanderData.currentModule != sbPtr->containingModule->m_aimodule->m_index)
 
 
4922
        {
 
 
4923
            NPC_FindAIWanderTarget(sbPtr,&(marineStatusPointer->wanderData),&(marineStatusPointer->moveData),0);
 
 
4924
        }
 
 
4925
 
 
 
4926
        /* if we still haven't got one, bimble about in this one for a bit. */
 
 
4927
        if(marineStatusPointer->wanderData.currentModule == NPC_NOWANDERMODULE)
 
 
4928
        {
 
 
4929
            NPC_GetBimbleTarget(sbPtr,&marineStatusPointer->wanderData.worldPosition);
 
 
4930
            marineStatusPointer->wanderData.currentModule = NPC_BIMBLINGINMODULE;
 
 
4931
        }
 
 
4932
    }
 
 
4933
 
 
 
4934
    /* ok: should have a current target at this stage... */
 
 
4935
    NPCGetMovementDirection(sbPtr, &velocityDirection,
&(marineStatusPointer->wanderData.worldPosition),&marineStatusPointer->waypointManager);
 
 
4936
    NPCSetVelocity(sbPtr, &velocityDirection, marineStatusPointer->nearSpeed);    
 
 
4937
 
 
 
4938
    /* test here for impeding collisions, and not being able to reach target... */
 
 
4939
    #if ALL_NEW_AVOIDANCE
 
 
4940
    {
 
 
4941
        if (New_NPC_IsObstructed(sbPtr,&marineStatusPointer->avoidanceManager))
 
 
4942
            return SRC_Request_Avoidance;
 
 
4943
    }
 
 
4944
    #else
 
 
4945
    {
 
 
4946
        STRATEGYBLOCK *destructableObject = NULL;
 
 
4947
        NPC_IsObstructed(sbPtr,&(marineStatusPointer->moveData),&marineStatusPointer->obstruction,&destructableObject);
 
 
4948
 
 
 
4949
        if(marineStatusPointer->obstruction.environment || marineStatusPointer->obstruction.otherCharacter)
 
 
4950
            return SRC_Request_Avoidance;
 
 
4951
 
 
 
4952
        if(marineStatusPointer->obstruction.destructableObject)
 
 
4953
        {
 
 
4954
            assert(destructableObject);
 
 
4955
            CauseDamageToObject(destructableObject,&TemplateAmmo[AMMO_NPC_OBSTACLE_CLEAR].MaxDamage, ONE_FIXED,NULL);
 
 
4956
        }
 
 
4957
    }
 
 
4958
 
 
 
4959
    if(NPC_CannotReachTarget(&marineStatusPointer->moveData, &marineStatusPointer->wanderData.worldPosition, &velocityDirection))
 
 
4960
    {
 
 
4961
        /* go to avoidance */
 
 
4962
        /* no sequence change required */
 
 
4963
 
 
 
4964
        marineStatusPointer->obstruction.environment = 1;
 
 
4965
        marineStatusPointer->obstruction.destructableObject = 0;
 
 
4966
        marineStatusPointer->obstruction.otherCharacter = 0;
 
 
4967
        marineStatusPointer->obstruction.anySingleObstruction = 0;
 
 
4968
 
 
 
4969
        return SRC_Request_Avoidance;
 
 
4970
    }
 
 
4971
    #endif
 
 
4972
 
 
 
4973
return SRC_No_Change;
 
 
4974
}
 
 
4975
 
 
 
4976
/*
 
 
4977
NB avoidance state behaviour function probabaly doesn't need to check
 
 
4978
for crouching, or for target becoming cloaked.  Only when we exit the state
 
 
4979
do we need to check these behaviour parameters to pick a new state and sequence
 
 
4980
*/
 
 
4981
 
 
 
4982
static STATE_RETURN_CONDITION Execute_MNS_Avoidance(STRATEGYBLOCK *sbPtr)
 
 
4983
{
 
 
4984
    int terminateState = 0;
 
 
4985
 
 
 
4986
    assert(sbPtr);
 
 
4987
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
4988
    assert(marineStatusPointer);
 
 
4989
 
 
 
4990
    #if ALL_NEW_AVOIDANCE
 
 
4991
    /* New avoidance kernel. */
 
 
4992
 
 
 
4993
    NPCSetVelocity(sbPtr, &(marineStatusPointer->avoidanceManager.avoidanceDirection), (marineStatusPointer->nearSpeed));
 
 
4994
    /* Velocity CANNOT be zero, unless deliberately so! */    
 
 
4995
    {
 
 
4996
        AVOIDANCE_RETURN_CONDITION rc = AllNewAvoidanceKernel(sbPtr,&marineStatusPointer->avoidanceManager);
 
 
4997
 
 
 
4998
        if (rc != AvRC_Avoidance)
 
 
4999
            terminateState = 1;
 
 
5000
 
 
 
5001
        /* Should put in a test for AvRC_Failure here. */
 
 
5002
    }
 
 
5003
 
 
 
5004
    #else
 
 
5005
    /* set velocity */
 
 
5006
    assert((marineStatusPointer->moveData.avoidanceDirn.vx !=0 ) ||
 
 
5007
                (marineStatusPointer->moveData.avoidanceDirn.vy != 0) ||
 
 
5008
                (marineStatusPointer->moveData.avoidanceDirn.vz != 0));
 
 
5009
 
 
 
5010
    NPCSetVelocity(sbPtr, &(marineStatusPointer->moveData.avoidanceDirn), (marineStatusPointer->nearSpeed));
 
 
5011
 
 
 
5012
    /* decrement state timer */
 
 
5013
    marineStatusPointer->stateTimer -= NormalFrameTime;
 
 
5014
 
 
 
5015
    if(marineStatusPointer->stateTimer <= 0)
 
 
5016
        terminateState = 1;
 
 
5017
 
 
 
5018
    {
 
 
5019
        STRATEGYBLOCK *destructableObject = NULL;
 
 
5020
        NPC_OBSTRUCTIONREPORT obstruction;
 
 
5021
 
 
 
5022
        NPC_IsObstructed(sbPtr,&(marineStatusPointer->moveData),&obstruction,&destructableObject);
 
 
5023
 
 
 
5024
        if(obstruction.anySingleObstruction)
 
 
5025
            terminateState = 1;
 
 
5026
    }
 
 
5027
    #endif
 
 
5028
 
 
 
5029
    if(terminateState)
 
 
5030
    {
 
 
5031
        /* switch to approach */
 
 
5032
        if(MarineIsAwareOfTarget(sbPtr))
 
 
5033
        {
 
 
5034
            /* go to approach */
 
 
5035
 
 
 
5036
            return SRC_Request_Approach;
 
 
5037
            /* Was fire! */
 
 
5038
        }
 
 
5039
        else
 
 
5040
        {
 
 
5041
            /* go to an appropriate state */
 
 
5042
            switch (marineStatusPointer->lastState)
 
 
5043
            {
 
 
5044
                case MBS_Retreating:
 
 
5045
                    return SRC_Request_Retreat;
 
 
5046
                case MBS_Returning:
 
 
5047
                    return SRC_Request_Return;
 
 
5048
                case MBS_Responding:
 
 
5049
                    return SRC_Request_Respond;
 
 
5050
                case MBS_Approaching:
 
 
5051
                    /* Go directly to approach.  Do not pass GO.  Do not collect 200 zorkmids. */
 
 
5052
                    return SRC_Request_Approach;
 
 
5053
                case MBS_Sentry:
 
 
5054
                    /* Go back to sentry. */
 
 
5055
                    return SRC_Request_Wait;
 
 
5056
                default:
 
 
5057
                    return SRC_Request_Wander;
 
 
5058
            }
 
 
5059
        }
 
 
5060
    }
 
 
5061
 
 
 
5062
return SRC_No_Change;
 
 
5063
}
 
 
5064
 
 
 
5065
static STATE_RETURN_CONDITION Execute_MNS_Approach(STRATEGYBLOCK *sbPtr)
 
 
5066
{
 
 
5067
    VECTORCH velocityDirection = {0,0,0};
 
 
5068
    VECTORCH targetPosition;
 
 
5069
    int targetIsAirduct = 0;
 
 
5070
 
 
 
5071
    assert(sbPtr);
 
 
5072
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
5073
    assert(marineStatusPointer);
 
 
5074
 
 
 
5075
    /* now check for state changes... firstly, if we can no longer attack the target, go to wander */
 
 
5076
 
 
 
5077
    if(!MarineIsAwareOfTarget(sbPtr))
 
 
5078
    {
 
 
5079
        if (!marineStatusPointer->suspicious)
 
 
5080
            return SRC_Request_Wait; /* Return to wait.  Nothing to worry about. */
 
 
5081
    }
 
 
5082
    else
 
 
5083
    {
 
 
5084
        /* We have a target that we are aware of. */
 
 
5085
 
 
 
5086
        int range = VectorDistance(&marineStatusPointer->Target->DynPtr->Position, &sbPtr->DynPtr->Position);
 
 
5087
 
 
 
5088
        /* if we are close... go directly to firing */
 
 
5089
        if(range < marineStatusPointer->My_Weapon->ForceFireRange)
 
 
5090
            return SRC_Request_Fire; /* switch directly to firing, at this distance */
 
 
5091
 
 
 
5092
        /* if our state timer has run out in approach state, see if we can fire*/
 
 
5093
        if(marineStatusPointer->stateTimer > 0)
 
 
5094
            marineStatusPointer->stateTimer -= NormalFrameTime;
 
 
5095
 
 
 
5096
        if(marineStatusPointer->stateTimer <= 0)
 
 
5097
        {
 
 
5098
            /* it is time to fire, if we can see the target  */
 
 
5099
               if(MarineCanSeeTarget(sbPtr) && ((marineStatusPointer->My_Weapon->MaxRange == -1) 
 
 
5100
               || (range < marineStatusPointer->My_Weapon->MaxRange)))
 
 
5101
            {
 
 
5102
                /* we are going to fire then */        
 
 
5103
                return SRC_Request_Fire;          
 
 
5104
            }
 
 
5105
            else
 
 
5106
            {
 
 
5107
                   /* renew approach state */
 
 
5108
                   marineStatusPointer->stateTimer = MARINE_NEAR_TIMEBETWEENFIRING;
 
 
5109
            }
 
 
5110
        }
 
 
5111
    }
 
 
5112
 
 
 
5113
    /* Kick them out of the stupid state? */
 
 
5114
 
 
 
5115
    /* See which way we want to go. */
 
 
5116
    if ((marineStatusPointer->destinationmodule == sbPtr->containingModule->m_aimodule)
 
 
5117
        ||(marineStatusPointer->destinationmodule == NULL))
 
 
5118
    {
 
 
5119
        AIMODULE *targetModule = NULL;
 
 
5120
        MODULE *tcm;
 
 
5121
 
 
 
5122
        if (marineStatusPointer->Target == NULL)
 
 
5123
        {
 
 
5124
            /* Must be approaching a suspect point. */
 
 
5125
            assert(marineStatusPointer->suspicious);
 
 
5126
            tcm = ModuleFromPosition(&marineStatusPointer->suspect_point, sbPtr->containingModule);
 
 
5127
        }
 
 
5128
        else
 
 
5129
        {
 
 
5130
            if (marineStatusPointer->Target->containingModule)
 
 
5131
                tcm = marineStatusPointer->Target->containingModule;
 
 
5132
            else
 
 
5133
                tcm = ModuleFromPosition(&marineStatusPointer->Target->DynPtr->Position, sbPtr->containingModule);
 
 
5134
        }
 
 
5135
 
 
 
5136
        if (tcm)
 
 
5137
            targetModule = GetNextModuleForLink(sbPtr->containingModule->m_aimodule, tcm->m_aimodule, 7, 0);
 
 
5138
 
 
 
5139
        if (targetModule == sbPtr->containingModule->m_aimodule)
 
 
5140
        {
 
 
5141
            /* Try going for it, we still can't see them. */
 
 
5142
            if (marineStatusPointer->Target)
 
 
5143
            {
 
 
5144
                NPCGetMovementTarget(sbPtr, marineStatusPointer->Target, &targetPosition, &targetIsAirduct,0);
 
 
5145
            }
 
 
5146
            else
 
 
5147
            {
 
 
5148
                /* Just use the target point? */
 
 
5149
                targetPosition = marineStatusPointer->suspect_point;
 
 
5150
 
 
 
5151
                VECTORCH relTargetPosition = targetPosition;
 
 
5152
 
 
 
5153
                relTargetPosition.vx -= sbPtr->DynPtr->Position.vx;
 
 
5154
                relTargetPosition.vy -= sbPtr->DynPtr->Position.vy;
 
 
5155
                relTargetPosition.vz -= sbPtr->DynPtr->Position.vz;
 
 
5156
 
 
 
5157
                /* Let's try doing this. */
 
 
5158
                relTargetPosition.vy >>= 2;
 
 
5159
 
 
 
5160
                int range2 = Approximate3dMagnitude(&relTargetPosition);
 
 
5161
 
 
 
5162
                if (range2 < SUSPECT_SENSITIVITY)
 
 
5163
                {
 
 
5164
                    /* That's probably close enough. */
 
 
5165
                    marineStatusPointer->suspicious = MARINE_PARANOIA_TIME;
 
 
5166
                    /* Used to unset suspicion at that point. */
 
 
5167
                    /* Get back to business? */
 
 
5168
                    return (marineStatusPointer->Mission == MM_Pathfinder) ? SRC_Request_Return : SRC_Request_Wait;
 
 
5169
                }
 
 
5170
            }
 
 
5171
 
 
 
5172
            NPCGetMovementDirection(sbPtr, &velocityDirection, &targetPosition,&marineStatusPointer->waypointManager);
 
 
5173
        }
 
 
5174
        else if (!targetModule)
 
 
5175
        {
 
 
5176
            /* Must be inaccessible.  Time out suspicion. */
 
 
5177
            marineStatusPointer->suspicious -= NormalFrameTime;
 
 
5178
            /* To fix the next trap... */
 
 
5179
 
 
 
5180
            if (!marineStatusPointer->suspicious)
 
 
5181
                marineStatusPointer->suspicious = -1;
 
 
5182
 
 
 
5183
            if (marineStatusPointer->suspicious < 0)
 
 
5184
            {
 
 
5185
                marineStatusPointer->suspicious = 0;
 
 
5186
                /* Set to zero on natural timeout, too. */
 
 
5187
                marineStatusPointer->previous_suspicion = 0;
 
 
5188
                marineStatusPointer->using_squad_suspicion = 0;
 
 
5189
 
 
 
5190
                switch(marineStatusPointer->behaviourState)
 
 
5191
                {
 
 
5192
                    case MBS_Waiting:
 
 
5193
                    case MBS_Sentry:
 
 
5194
                        /* We might concievably want to do this for all states. */
 
 
5195
                        marineStatusPointer->gotapoint = 0;
 
 
5196
                    default:
 
 
5197
                    break;
 
 
5198
                }
 
 
5199
            }
 
 
5200
 
 
 
5201
        #if MARINE_PRINT_STATE
 
 
5202
            if (marineStatusPointer->Target)
 
 
5203
            {
 
 
5204
                if (marineStatusPointer->Target->containingModule)
 
 
5205
                    printf("I can see you, but I can't get there!\n");
 
 
5206
                else
 
 
5207
                    printf("Hey, you've got no Containing Module!\n");
 
 
5208
            }
 
 
5209
            else
 
 
5210
            {
 
 
5211
                printf("Can't get to the suspect point!\n");
 
 
5212
                /* Yuck.  Stop it. */
 
 
5213
                marineStatusPointer->suspicious = 1;
 
 
5214
                /* Just this once, let's unset it... We can't do anything about it. */
 
 
5215
                return SRC_Request_Wait;
 
 
5216
            }
 
 
5217
        #endif
 
 
5218
 
 
 
5219
        return SRC_No_Change;
 
 
5220
        }
 
 
5221
        else
 
 
5222
        {
 
 
5223
            FARENTRYPOINT *thisEp = GetAIModuleEP(targetModule,sbPtr->containingModule->m_aimodule);
 
 
5224
 
 
 
5225
            if (!thisEp)
 
 
5226
            {
 
 
5227
                printf("This assert is a busted adjacency!\nNo EP between %s and %s.",
 
 
5228
                (*(targetModule->m_module_ptrs))->name, sbPtr->containingModule->name);
 
 
5229
                //printf("This assert is a busted adjacency!");
 
 
5230
                assert(thisEp);
 
 
5231
            }
 
 
5232
 
 
 
5233
            /* If that fired, there's a farped adjacency. */
 
 
5234
            assert(thisEp->alien_only == 0);
 
 
5235
            /* If that fired, GetNextModuleForLink went wrong. */
 
 
5236
 
 
 
5237
            marineStatusPointer->wanderData.worldPosition = thisEp->position;
 
 
5238
            marineStatusPointer->wanderData.worldPosition.vx += targetModule->m_world.vx;
 
 
5239
            marineStatusPointer->wanderData.worldPosition.vy += targetModule->m_world.vy;
 
 
5240
            marineStatusPointer->wanderData.worldPosition.vz += targetModule->m_world.vz;
 
 
5241
 
 
 
5242
            NPCGetMovementDirection(sbPtr, &velocityDirection,
&(marineStatusPointer->wanderData.worldPosition),&marineStatusPointer->waypointManager);
 
 
5243
        }
 
 
5244
    }
 
 
5245
    else if (marineStatusPointer->destinationmodule != NULL)
 
 
5246
    {
 
 
5247
        /* Go towards next module. */
 
 
5248
        NPCGetMovementDirection(sbPtr, &velocityDirection,
&(marineStatusPointer->wanderData.worldPosition),&marineStatusPointer->waypointManager);
 
 
5249
    }
 
 
5250
    else
 
 
5251
    {
 
 
5252
        /*  we are still in approach state: target the target, and move */
 
 
5253
        if (marineStatusPointer->Target)
 
 
5254
        {
 
 
5255
            NPCGetMovementTarget(sbPtr, marineStatusPointer->Target, &targetPosition, &targetIsAirduct,0);
 
 
5256
        }
 
 
5257
        else
 
 
5258
        {
 
 
5259
            /* How did we get here, anyway? */
 
 
5260
            targetPosition = marineStatusPointer->suspect_point;
 
 
5261
        }
 
 
5262
 
 
 
5263
        NPCGetMovementDirection(sbPtr, &velocityDirection, &targetPosition,&marineStatusPointer->waypointManager);
 
 
5264
    }
 
 
5265
 
 
 
5266
    /* Should have a velocity set now. */
 
 
5267
 
 
 
5268
    NPCSetVelocity(sbPtr, &velocityDirection, marineStatusPointer->nearSpeed);    
 
 
5269
 
 
 
5270
    /* test here for impeding collisions, and not being able to reach target... */
 
 
5271
    #if ALL_NEW_AVOIDANCE
 
 
5272
    {
 
 
5273
        if (New_NPC_IsObstructed(sbPtr,&marineStatusPointer->avoidanceManager))
 
 
5274
            return SRC_Request_Avoidance;
 
 
5275
    }
 
 
5276
    #else
 
 
5277
    {
 
 
5278
        STRATEGYBLOCK *destructableObject = NULL;
 
 
5279
 
 
 
5280
        NPC_IsObstructed(sbPtr,&(marineStatusPointer->moveData),&marineStatusPointer->obstruction,&destructableObject);
 
 
5281
 
 
 
5282
        if(marineStatusPointer->obstruction.environment)
 
 
5283
            return SRC_Request_Avoidance;
 
 
5284
 
 
 
5285
        if(marineStatusPointer->obstruction.destructableObject)
 
 
5286
        {
 
 
5287
            assert(destructableObject);
 
 
5288
            CauseDamageToObject(destructableObject,&TemplateAmmo[AMMO_NPC_OBSTACLE_CLEAR].MaxDamage, ONE_FIXED,NULL);
 
 
5289
        }
 
 
5290
    }
 
 
5291
 
 
 
5292
    if(NPC_CannotReachTarget(&marineStatusPointer->moveData, &targetPosition, &velocityDirection))
 
 
5293
    {
 
 
5294
        marineStatusPointer->obstruction.environment = 1;
 
 
5295
        marineStatusPointer->obstruction.destructableObject = 0;
 
 
5296
        marineStatusPointer->obstruction.otherCharacter = 0;
 
 
5297
        marineStatusPointer->obstruction.anySingleObstruction = 0;
 
 
5298
 
 
 
5299
        return SRC_Request_Avoidance;
 
 
5300
    }
 
 
5301
    #endif
 
 
5302
 
 
 
5303
return SRC_No_Change;
 
 
5304
}
 
 
5305
 
 
 
5306
static STATE_RETURN_CONDITION Execute_MFS_Avoidance(STRATEGYBLOCK *sbPtr) 
 
 
5307
{
 
 
5308
    assert(sbPtr);
 
 
5309
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
5310
    assert(marineStatusPointer);
 
 
5311
 
 
 
5312
    /* High on the list of Things Not To Be Doing. */
 
 
5313
 
 
 
5314
    #if ALL_NEW_AVOIDANCE
 
 
5315
    Initialise_AvoidanceManager(&marineStatusPointer->avoidanceManager);
 
 
5316
    #endif
 
 
5317
 
 
 
5318
    switch (marineStatusPointer->lastState)
 
 
5319
    {
 
 
5320
        case MBS_Retreating:
 
 
5321
            return SRC_Request_Retreat;
 
 
5322
        case MBS_Returning:
 
 
5323
            return SRC_Request_Return;
 
 
5324
        case MBS_Responding:
 
 
5325
            return SRC_Request_Respond;
 
 
5326
        case MBS_Approaching:
 
 
5327
            /* Go directly to approach.  Do not pass GO.  Do not collect 200 zorkmids. */
 
 
5328
            return SRC_Request_Approach;
 
 
5329
        default:
 
 
5330
            return SRC_Request_Wander;
 
 
5331
    }
 
 
5332
}
 
 
5333
 
 
 
5334
static STATE_RETURN_CONDITION Execute_MFS_Firing(STRATEGYBLOCK *sbPtr)
 
 
5335
{
 
 
5336
    assert(sbPtr);
 
 
5337
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
5338
    assert(marineStatusPointer);
 
 
5339
 
 
 
5340
    /* I can't deal with this right now.  Better wait instead. */
 
 
5341
 
 
 
5342
    DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
5343
 
 
 
5344
    /* .... and stop the sound */
 
 
5345
    if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
5346
    {
 
 
5347
        Sound_Stop(marineStatusPointer->soundHandle);
 
 
5348
        Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
5349
    }
 
 
5350
 
 
 
5351
return SRC_Request_Wait;
 
 
5352
}
 
 
5353
 
 
 
5354
static STATE_RETURN_CONDITION Execute_MFS_Approach(STRATEGYBLOCK *sbPtr) 
 
 
5355
{
 
 
5356
    MODULE *tcm;
 
 
5357
 
 
 
5358
    assert(sbPtr);
 
 
5359
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
5360
    assert(marineStatusPointer);
 
 
5361
 
 
 
5362
    if (!MarineIsAwareOfTarget(sbPtr))
 
 
5363
        return SRC_Request_Wander; /* we should be wandering... can't hunt other NPCs */
 
 
5364
 
 
 
5365
    /* See if we can fire? */
 
 
5366
 
 
 
5367
    if (marineStatusPointer->Target)
 
 
5368
    {
 
 
5369
        if (marineStatusPointer->Target->containingModule)
 
 
5370
        {
 
 
5371
            if (IsModuleVisibleFromModule(marineStatusPointer->Target->containingModule,sbPtr->containingModule))
 
 
5372
                return SRC_Request_Fire; /* Take the shot? */
 
 
5373
        }
 
 
5374
    }
 
 
5375
 
 
 
5376
    /* Can't fire.  We want to get closer, then. */
 
 
5377
 
 
 
5378
    if (marineStatusPointer->Target->containingModule)
 
 
5379
        tcm = marineStatusPointer->Target->containingModule;
 
 
5380
    else
 
 
5381
        tcm = ModuleFromPosition(&marineStatusPointer->Target->DynPtr->Position, sbPtr->containingModule);
 
 
5382
 
 
 
5383
    if (tcm)
 
 
5384
    {
 
 
5385
        AIMODULE *targetModule = GetNextModuleForLink(sbPtr->containingModule->m_aimodule,tcm->m_aimodule,7,0);
 
 
5386
 
 
 
5387
        if (targetModule)
 
 
5388
        {
 
 
5389
            /* We have somewhere to go. */
 
 
5390
            assert(AIModuleIsPhysical(targetModule));        
 
 
5391
            ProcessFarMarineTargetModule(sbPtr, targetModule);    
 
 
5392
            /* reset timer */
 
 
5393
            marineStatusPointer->stateTimer = MARINE_FAR_MOVE_TIME;
 
 
5394
            marineStatusPointer->destinationmodule = targetModule;
 
 
5395
            return SRC_No_Change;
 
 
5396
        }
 
 
5397
    }
 
 
5398
 
 
 
5399
    /* Can't do nothin.  Better wait, then.  Everything else will see to itself. */
 
 
5400
    if (marineStatusPointer->Mission == MM_Pathfinder)
 
 
5401
        return SRC_Request_Return;
 
 
5402
    else
 
 
5403
        return SRC_Request_Wait;
 
 
5404
}
 
 
5405
 
 
 
5406
static STATE_RETURN_CONDITION Execute_MFS_Wander(STRATEGYBLOCK *sbPtr)
 
 
5407
{
 
 
5408
    AIMODULE *targetModule = NULL;
 
 
5409
    assert(sbPtr);
 
 
5410
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
5411
    assert(marineStatusPointer);
 
 
5412
 
 
 
5413
    /* Decrement the Far state timer */
 
 
5414
    marineStatusPointer->stateTimer -= NormalFrameTime;    
 
 
5415
    /* check if far state timer has timed-out. If so, it is time 
 
 
5416
    to do something. Otherwise just return. */
 
 
5417
 
 
 
5418
    if(marineStatusPointer->stateTimer > 0)
 
 
5419
        return SRC_No_Change;
 
 
5420
 
 
 
5421
    /* check for state changes */
 
 
5422
    /* Hack! */
 
 
5423
    if(MarineIsAwareOfTarget(sbPtr))
 
 
5424
        return SRC_Request_Approach; /* we should be hunting */
 
 
5425
 
 
 
5426
    /* New alert? */
 
 
5427
    if (NpcSquad.alertZone && (marineStatusPointer->Mission != MM_LocalGuard) && (marineStatusPointer->Mission != MM_NonCom))
 
 
5428
    {
 
 
5429
        if (sbPtr->containingModule->m_aimodule != NpcSquad.alertZone)
 
 
5430
        {
 
 
5431
            if (NpcSquad.responseLevel > 0)
 
 
5432
            {
 
 
5433
                /* Picked up a target.  Can we move to respond? */
 
 
5434
                targetModule = FarNPC_GetTargetAIModuleForMarineRespond(sbPtr);
 
 
5435
                if (targetModule)
 
 
5436
                {
 
 
5437
                    NpcSquad.responseLevel--;
 
 
5438
                    return SRC_Request_Respond;
 
 
5439
                }
 
 
5440
            }
 
 
5441
        }
 
 
5442
    }
 
 
5443
 
 
 
5444
    /* Bored of wandering?  How about we wait a while? */
 
 
5445
    if ((FastRandom() & 65535) < 2048)
 
 
5446
        return SRC_Request_Wait; /* we should be wandering... we're bored of waiting. */
 
 
5447
 
 
 
5448
    /* get the target module... */
 
 
5449
    targetModule = FarNPC_GetTargetAIModuleForWander(sbPtr,marineStatusPointer->lastmodule,0);
 
 
5450
 
 
 
5451
    /*
 
 
5452
    if there is no target module, it means that the pred is trapped in an
 
 
5453
    unlinked module. In this case, reset the timer and return.
 
 
5454
    */            
 
 
5455
 
 
 
5456
    if(!targetModule)
 
 
5457
    {
 
 
5458
        marineStatusPointer->stateTimer = MARINE_FAR_MOVE_TIME;
 
 
5459
        return SRC_No_Change;        
 
 
5460
    }
 
 
5461
 
 
 
5462
    /* Examine target, and decide what to do */
 
 
5463
    assert(AIModuleIsPhysical(targetModule));        
 
 
5464
    ProcessFarMarineTargetModule(sbPtr, targetModule);    
 
 
5465
    /* reset timer */
 
 
5466
    marineStatusPointer->stateTimer = MARINE_FAR_MOVE_TIME;                    
 
 
5467
 
 
 
5468
return SRC_No_Change;
 
 
5469
}
 
 
5470
 
 
 
5471
static STATE_RETURN_CONDITION Execute_MNS_Pathfinder(STRATEGYBLOCK *sbPtr)
 
 
5472
{
 
 
5473
    VECTORCH velocityDirection = {0,0,0};
 
 
5474
 
 
 
5475
    assert(sbPtr);
 
 
5476
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
5477
    assert(marineStatusPointer);
 
 
5478
 
 
 
5479
    /* should we change to approach state? */
 
 
5480
    if(MarineIsAwareOfTarget(sbPtr))
 
 
5481
        return SRC_Request_Approach; /* doesn't require a sequence change */
 
 
5482
 
 
 
5483
    if (marineStatusPointer->suspicious)
 
 
5484
    {
 
 
5485
        /* Are we allowed to check it out? */
 
 
5486
        MODULE *targetModule = ModuleFromPosition(&marineStatusPointer->suspect_point, sbPtr->containingModule);
 
 
5487
 
 
 
5488
        if (targetModule && IsModuleVisibleFromModule(targetModule, sbPtr->containingModule))
 
 
5489
        {
 
 
5490
            /* I suppose we'd better go, then. */
 
 
5491
            return MarineRetreatsInTheFaceOfDanger(sbPtr) ? SRC_Request_Wait : SRC_Request_Approach;
 
 
5492
        }
 
 
5493
    }
 
 
5494
 
 
 
5495
    /* Ignore alerts. */
 
 
5496
 
 
 
5497
    marineStatusPointer->stateTimer -= NormalFrameTime;
 
 
5498
 
 
 
5499
    if(marineStatusPointer->wanderData.currentModule == NPC_NOWANDERMODULE)
 
 
5500
        NPC_InitMovementData(&(marineStatusPointer->moveData));
 
 
5501
 
 
 
5502
    if ((marineStatusPointer->wanderData.currentModule == NPC_NOWANDERMODULE)
 
 
5503
        ||(marineStatusPointer->wanderData.currentModule != sbPtr->containingModule->m_aimodule->m_index))
 
 
5504
    {
 
 
5505
        /* Okay, so where are we exactly? */
 
 
5506
 
 
 
5507
        if ((marineStatusPointer->stepnumber < 0) || (marineStatusPointer->path < 0))
 
 
5508
            return SRC_Request_Wander; /* Get OUT! */
 
 
5509
 
 
 
5510
        AIMODULE *targetModule = TranslatePathIndex(marineStatusPointer->stepnumber,marineStatusPointer->path);
 
 
5511
 
 
 
5512
        if (targetModule == NULL)
 
 
5513
            return SRC_Request_Wander; /* Oh, to heck with this.  Try to wander. */
 
 
5514
 
 
 
5515
        /* Right, so there is a somewhere to get to. */
 
 
5516
 
 
 
5517
        if (targetModule != sbPtr->containingModule->m_aimodule)
 
 
5518
        {
 
 
5519
            /* But we're nowhere near it.  Geeze... */
 
 
5520
            marineStatusPointer->missionmodule = targetModule;
 
 
5521
            return SRC_Request_Return;
 
 
5522
        }
 
 
5523
 
 
 
5524
        /* Okay, so now we need to know where to go now. */
 
 
5525
 
 
 
5526
        int nextModuleIndex = GetNextModuleInPath(marineStatusPointer->stepnumber,marineStatusPointer->path);
 
 
5527
 
 
 
5528
        assert(nextModuleIndex >= 0);
 
 
5529
 
 
 
5530
        /* If that fires, it's Richard's fault. */
 
 
5531
        targetModule = TranslatePathIndex(nextModuleIndex,marineStatusPointer->path);
 
 
5532
        assert(targetModule);
 
 
5533
        /* Ditto. */
 
 
5534
 
 
 
5535
        marineStatusPointer->stepnumber = nextModuleIndex;
 
 
5536
 
 
 
5537
        FARENTRYPOINT *thisEp = GetAIModuleEP(targetModule, sbPtr->containingModule->m_aimodule);
 
 
5538
 
 
 
5539
        if(thisEp)
 
 
5540
        {
 
 
5541
            /* aha. an ep!... */ 
 
 
5542
            VECTORCH thisEpWorld = thisEp->position;
 
 
5543
 
 
 
5544
            thisEpWorld.vx += targetModule->m_world.vx;
 
 
5545
            thisEpWorld.vy += targetModule->m_world.vy;
 
 
5546
            thisEpWorld.vz += targetModule->m_world.vz;            
 
 
5547
 
 
 
5548
            marineStatusPointer->wanderData.currentModule = sbPtr->containingModule->m_aimodule->m_index;
 
 
5549
            marineStatusPointer->wanderData.worldPosition = thisEpWorld;
 
 
5550
            assert(thisEp->alien_only == 0);
 
 
5551
            /* If that fired, the path goes through an alien-only link. */
 
 
5552
        }
 
 
5553
        else
 
 
5554
        {
 
 
5555
            /* Failure case. */
 
 
5556
            marineStatusPointer->wanderData.currentModule = NPC_NOWANDERMODULE;
 
 
5557
        }
 
 
5558
    }
 
 
5559
 
 
 
5560
    /* if we still haven't got one, wander for a bit. */
 
 
5561
    if(marineStatusPointer->wanderData.currentModule == NPC_NOWANDERMODULE)
 
 
5562
    {
 
 
5563
        NPC_InitMovementData(&(marineStatusPointer->moveData));
 
 
5564
        marineStatusPointer->moveData.lastModule = marineStatusPointer->lastmodule;
 
 
5565
        NPC_FindAIWanderTarget(sbPtr,&(marineStatusPointer->wanderData),&(marineStatusPointer->moveData),0);
 
 
5566
    }
 
 
5567
 
 
 
5568
    if(marineStatusPointer->wanderData.currentModule == NPC_NOWANDERMODULE)
 
 
5569
    {
 
 
5570
        /* STILL broken!  Okay, just... wander forever, then. */
 
 
5571
        return SRC_Request_Wander;
 
 
5572
    }
 
 
5573
 
 
 
5574
    /* ok: should have a current target at this stage... */
 
 
5575
    NPCGetMovementDirection(sbPtr, &velocityDirection,
&(marineStatusPointer->wanderData.worldPosition),&marineStatusPointer->waypointManager);
 
 
5576
    NPCSetVelocity(sbPtr, &velocityDirection, marineStatusPointer->nearSpeed);    
 
 
5577
 
 
 
5578
    /* test here for impeding collisions, and not being able to reach target... */
 
 
5579
    #if ALL_NEW_AVOIDANCE
 
 
5580
    {
 
 
5581
        if (New_NPC_IsObstructed(sbPtr,&marineStatusPointer->avoidanceManager))
 
 
5582
            return SRC_Request_Avoidance;
 
 
5583
    }
 
 
5584
    #else
 
 
5585
    {
 
 
5586
        STRATEGYBLOCK *destructableObject = NULL;
 
 
5587
        NPC_IsObstructed(sbPtr,&(marineStatusPointer->moveData),&marineStatusPointer->obstruction,&destructableObject);
 
 
5588
 
 
 
5589
        if(marineStatusPointer->obstruction.environment || marineStatusPointer->obstruction.otherCharacter)
 
 
5590
            return SRC_Request_Avoidance;
 
 
5591
 
 
 
5592
        if(marineStatusPointer->obstruction.destructableObject)
 
 
5593
        {
 
 
5594
            assert(destructableObject);
 
 
5595
            CauseDamageToObject(destructableObject,&TemplateAmmo[AMMO_NPC_OBSTACLE_CLEAR].MaxDamage, ONE_FIXED,NULL);
 
 
5596
        }
 
 
5597
    }
 
 
5598
 
 
 
5599
    if(NPC_CannotReachTarget(&marineStatusPointer->moveData, &marineStatusPointer->wanderData.worldPosition, &velocityDirection))
 
 
5600
    {
 
 
5601
        /* go to avoidance */
 
 
5602
        /* no sequence change required */
 
 
5603
 
 
 
5604
        marineStatusPointer->obstruction.environment = 1;
 
 
5605
        marineStatusPointer->obstruction.destructableObject = 0;
 
 
5606
        marineStatusPointer->obstruction.otherCharacter = 0;
 
 
5607
        marineStatusPointer->obstruction.anySingleObstruction = 0;
 
 
5608
 
 
 
5609
        return SRC_Request_Avoidance;
 
 
5610
    }
 
 
5611
    #endif
 
 
5612
 
 
 
5613
return SRC_No_Change;
 
 
5614
}
 
 
5615
 
 
 
5616
static void Marine_Enter_Return_State(STRATEGYBLOCK *sbPtr) 
 
 
5617
{
 
 
5618
    assert(sbPtr);
 
 
5619
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
5620
    assert(marineStatusPointer);
 
 
5621
 
 
 
5622
    marineStatusPointer->gotapoint = 0;
 
 
5623
    marineStatusPointer->volleySize = 0;
 
 
5624
 
 
 
5625
    NPC_InitMovementData(&(marineStatusPointer->moveData));
 
 
5626
    InitWaypointManager(&marineStatusPointer->waypointManager);
 
 
5627
 
 
 
5628
    marineStatusPointer->lastState = marineStatusPointer->behaviourState;
 
 
5629
    marineStatusPointer->behaviourState = MBS_Returning;
 
 
5630
    marineStatusPointer->destinationmodule = NULL;
 
 
5631
    marineStatusPointer->stateTimer = MARINE_NEAR_TIMEBETWEENFIRING;                     
 
 
5632
    marineStatusPointer->Target_Expression = 0;
 
 
5633
}
 
 
5634
 
 
 
5635
static void PathfinderMission_SwitchState(STRATEGYBLOCK *sbPtr,STATE_RETURN_CONDITION state_result) 
 
 
5636
{
 
 
5637
    STATE_RETURN_CONDITION real_state_result;
 
 
5638
    /* Experiment: override result? */
 
 
5639
    switch (state_result)
 
 
5640
    {
 
 
5641
        case SRC_Request_Fire:
 
 
5642
        case SRC_Request_Approach:
 
 
5643
            if (MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
5644
            {
 
 
5645
                real_state_result = SRC_Request_Retreat;
 
 
5646
                break;
 
 
5647
            }
 
 
5648
        default:
 
 
5649
            real_state_result = state_result;
 
 
5650
            break;
 
 
5651
    }
 
 
5652
 
 
 
5653
    switch (real_state_result)
 
 
5654
    {
 
 
5655
        case SRC_No_Change:
 
 
5656
        {
 
 
5657
            /* No action. */
 
 
5658
        break;
 
 
5659
        }
 
 
5660
        case SRC_Request_Wait:
 
 
5661
        {
 
 
5662
            Marine_Enter_Pathfinder_State(sbPtr);
 
 
5663
        break;
 
 
5664
        }
 
 
5665
        case SRC_Request_Fire:
 
 
5666
        {
 
 
5667
            Marine_Enter_Firing_State(sbPtr);
 
 
5668
        break;
 
 
5669
        }
 
 
5670
        case SRC_Request_PanicFire:
 
 
5671
        {
 
 
5672
            Marine_Enter_PanicFire_State(sbPtr);
 
 
5673
        break;
 
 
5674
        }
 
 
5675
        case SRC_Request_Avoidance:
 
 
5676
        {
 
 
5677
            Marine_Enter_Avoidance_State(sbPtr);
 
 
5678
        break;
 
 
5679
        }
 
 
5680
        case SRC_Request_Approach:
 
 
5681
        {
 
 
5682
            Marine_Enter_Approach_State(sbPtr);
 
 
5683
        break;
 
 
5684
        }
 
 
5685
        case SRC_Request_Wander:
 
 
5686
        {
 
 
5687
            Marine_Enter_Wander_State(sbPtr);
 
 
5688
        break;
 
 
5689
        }
 
 
5690
        case SRC_Request_Retreat:
 
 
5691
        {
 
 
5692
            Marine_Enter_Retreat_State(sbPtr);
 
 
5693
        break;
 
 
5694
        }
 
 
5695
        case SRC_Request_Respond:
 
 
5696
        {
 
 
5697
            Marine_Enter_Respond_State(sbPtr);
 
 
5698
        break;
 
 
5699
        }
 
 
5700
        case SRC_Request_Return:
 
 
5701
        {
 
 
5702
            Marine_Enter_Return_State(sbPtr);
 
 
5703
        break;
 
 
5704
        }
 
 
5705
        case SRC_Request_PullPistol:
 
 
5706
        {
 
 
5707
            Marine_Enter_PullPistol_State(sbPtr);
 
 
5708
        break;
 
 
5709
        }
 
 
5710
        default:
 
 
5711
        {
 
 
5712
            /* How did we end up here? */
 
 
5713
            assert(0);
 
 
5714
        break;
 
 
5715
        }
 
 
5716
    }
 
 
5717
}
 
 
5718
 
 
 
5719
static STATE_RETURN_CONDITION Execute_MNS_Return(STRATEGYBLOCK *sbPtr)
 
 
5720
{
 
 
5721
    VECTORCH velocityDirection = {0,0,0};
 
 
5722
 
 
 
5723
    assert(sbPtr);
 
 
5724
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
5725
    assert(marineStatusPointer);
 
 
5726
 
 
 
5727
    /* should we change to approach state? */
 
 
5728
    if(MarineIsAwareOfTarget(sbPtr))
 
 
5729
        return SRC_Request_Approach; /* doesn't require a sequence change */
 
 
5730
 
 
 
5731
    marineStatusPointer->stateTimer -= NormalFrameTime;
 
 
5732
 
 
 
5733
    /* Are we there yet? */
 
 
5734
    if (sbPtr->containingModule->m_aimodule == marineStatusPointer->missionmodule)
 
 
5735
        return SRC_Request_Wait;
 
 
5736
 
 
 
5737
    /* Target module aquisition. */
 
 
5738
 
 
 
5739
    assert(sbPtr->containingModule);
 
 
5740
 
 
 
5741
    if(marineStatusPointer->wanderData.currentModule == NPC_NOWANDERMODULE)
 
 
5742
        NPC_InitMovementData(&(marineStatusPointer->moveData));
 
 
5743
 
 
 
5744
    if ((marineStatusPointer->wanderData.currentModule == NPC_NOWANDERMODULE)
 
 
5745
        || (marineStatusPointer->wanderData.currentModule != sbPtr->containingModule->m_aimodule->m_index))
 
 
5746
    {
 
 
5747
        AIMODULE *targetModule = GetNextModuleForLink(sbPtr->containingModule->m_aimodule,marineStatusPointer->missionmodule,7,0);
 
 
5748
 
 
 
5749
        if (targetModule)
 
 
5750
        {
 
 
5751
            FARENTRYPOINT *thisEp = GetAIModuleEP(targetModule, sbPtr->containingModule->m_aimodule);
 
 
5752
 
 
 
5753
            if(thisEp)
 
 
5754
            {
 
 
5755
                /* aha. an ep!... */ 
 
 
5756
                VECTORCH thisEpWorld = thisEp->position;
 
 
5757
 
 
 
5758
                thisEpWorld.vx += targetModule->m_world.vx;
 
 
5759
                thisEpWorld.vy += targetModule->m_world.vy;
 
 
5760
                thisEpWorld.vz += targetModule->m_world.vz;            
 
 
5761
 
 
 
5762
                marineStatusPointer->wanderData.currentModule = sbPtr->containingModule->m_aimodule->m_index;
 
 
5763
                 marineStatusPointer->wanderData.worldPosition = thisEpWorld;
 
 
5764
 
 
 
5765
                assert(thisEp->alien_only == 0);
 
 
5766
                /* If that fired, GetNextModuleForLink went wrong. */
 
 
5767
            }
 
 
5768
            else
 
 
5769
            {
 
 
5770
                /* Failure case. */
 
 
5771
                marineStatusPointer->wanderData.currentModule = NPC_NOWANDERMODULE;
 
 
5772
            }
 
 
5773
        }
 
 
5774
        else
 
 
5775
        {
 
 
5776
            /* Another failure case. */
 
 
5777
            marineStatusPointer->wanderData.currentModule = NPC_NOWANDERMODULE;
 
 
5778
        }
 
 
5779
    }
 
 
5780
 
 
 
5781
    /* if we still haven't got one, bimble about in this one for a bit. */
 
 
5782
    if(marineStatusPointer->wanderData.currentModule == NPC_NOWANDERMODULE)
 
 
5783
    {
 
 
5784
        NPC_InitMovementData(&(marineStatusPointer->moveData));
 
 
5785
        marineStatusPointer->moveData.lastModule = marineStatusPointer->lastmodule;
 
 
5786
        NPC_FindAIWanderTarget(sbPtr,&(marineStatusPointer->wanderData),&(marineStatusPointer->moveData),0);
 
 
5787
    }
 
 
5788
 
 
 
5789
    if(marineStatusPointer->wanderData.currentModule == NPC_NOWANDERMODULE)
 
 
5790
        return SRC_Request_Wander; /* STILL broken!  Okay, just... wander, then. */
 
 
5791
 
 
 
5792
    /* ok: should have a current target at this stage... */
 
 
5793
    NPCGetMovementDirection(sbPtr, &velocityDirection,
&(marineStatusPointer->wanderData.worldPosition),&marineStatusPointer->waypointManager);
 
 
5794
    NPCSetVelocity(sbPtr, &velocityDirection, marineStatusPointer->nearSpeed);    
 
 
5795
 
 
 
5796
    /* test here for impeding collisions, and not being able to reach target... */
 
 
5797
    #if ALL_NEW_AVOIDANCE
 
 
5798
    {
 
 
5799
        if (New_NPC_IsObstructed(sbPtr,&marineStatusPointer->avoidanceManager))
 
 
5800
            return SRC_Request_Avoidance; /* Go to all new avoidance. */
 
 
5801
    }
 
 
5802
    #else
 
 
5803
    {
 
 
5804
        STRATEGYBLOCK *destructableObject = NULL;
 
 
5805
        NPC_IsObstructed(sbPtr,&(marineStatusPointer->moveData),&marineStatusPointer->obstruction,&destructableObject);
 
 
5806
 
 
 
5807
        if(marineStatusPointer->obstruction.environment || marineStatusPointer->obstruction.otherCharacter)
 
 
5808
            return SRC_Request_Avoidance;
 
 
5809
 
 
 
5810
        if(marineStatusPointer->obstruction.destructableObject)
 
 
5811
        {
 
 
5812
            assert(destructableObject);
 
 
5813
            CauseDamageToObject(destructableObject,&TemplateAmmo[AMMO_NPC_OBSTACLE_CLEAR].MaxDamage, ONE_FIXED,NULL);
 
 
5814
        }
 
 
5815
    }
 
 
5816
 
 
 
5817
    if(NPC_CannotReachTarget(&marineStatusPointer->moveData, &marineStatusPointer->wanderData.worldPosition, &velocityDirection))
 
 
5818
    {
 
 
5819
        /* go to avoidance */
 
 
5820
        /* no sequence change required */
 
 
5821
 
 
 
5822
        marineStatusPointer->obstruction.environment = 1;
 
 
5823
        marineStatusPointer->obstruction.destructableObject = 0;
 
 
5824
        marineStatusPointer->obstruction.otherCharacter = 0;
 
 
5825
        marineStatusPointer->obstruction.anySingleObstruction = 0;
 
 
5826
 
 
 
5827
        return SRC_Request_Avoidance;
 
 
5828
    }
 
 
5829
    #endif
 
 
5830
 
 
 
5831
return SRC_No_Change;
 
 
5832
}
 
 
5833
 
 
 
5834
static STATE_RETURN_CONDITION Execute_MFS_Pathfinder(STRATEGYBLOCK *sbPtr)
 
 
5835
{
 
 
5836
    assert(sbPtr);
 
 
5837
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
5838
    assert(marineStatusPointer);
 
 
5839
 
 
 
5840
    /* Okay, so you're a LocalGuard or Pathfinder who's gotten lost. */
 
 
5841
 
 
 
5842
    /* Decrement the Far state timer */
 
 
5843
    marineStatusPointer->stateTimer -= NormalFrameTime;    
 
 
5844
    /* check if far state timer has timed-out. If so, it is time 
 
 
5845
    to do something. Otherwise just return. */
 
 
5846
 
 
 
5847
    if(marineStatusPointer->stateTimer > 0)
 
 
5848
        return SRC_No_Change;
 
 
5849
 
 
 
5850
    /* check for state changes */
 
 
5851
    /* Hack! */
 
 
5852
    if(MarineIsAwareOfTarget(sbPtr))
 
 
5853
        return SRC_Request_Approach; /* we should be engaging */
 
 
5854
 
 
 
5855
    /* Ignore alerts. */
 
 
5856
 
 
 
5857
    /* Never break out of pathfinder unless your life is in danger! */
 
 
5858
 
 
 
5859
    /* Okay, so where are we exactly? */
 
 
5860
 
 
 
5861
    if ((marineStatusPointer->stepnumber < 0) || (marineStatusPointer->path < 0))
 
 
5862
        return SRC_Request_Wander; /* Get OUT! */
 
 
5863
 
 
 
5864
    AIMODULE *targetModule = TranslatePathIndex(marineStatusPointer->stepnumber,marineStatusPointer->path);
 
 
5865
 
 
 
5866
    if (targetModule == NULL)
 
 
5867
    {
 
 
5868
        /* Oh, to heck with this.  Try to wander. */
 
 
5869
        return SRC_Request_Wander;
 
 
5870
    }
 
 
5871
 
 
 
5872
    /* Right, so there is a somewhere to get to. */
 
 
5873
 
 
 
5874
    if (targetModule != sbPtr->containingModule->m_aimodule)
 
 
5875
    {
 
 
5876
        /* But we're nowhere near it.  Geeze... */
 
 
5877
        marineStatusPointer->missionmodule = targetModule;
 
 
5878
        return SRC_Request_Return;
 
 
5879
    }
 
 
5880
 
 
 
5881
    /* Okay, so now we need to know where to go now. */
 
 
5882
 
 
 
5883
    int nextModuleIndex = GetNextModuleInPath(marineStatusPointer->stepnumber,marineStatusPointer->path);
 
 
5884
 
 
 
5885
    assert(nextModuleIndex>=0);
 
 
5886
 
 
 
5887
    /* If that fires, it's Richard's fault. */
 
 
5888
    targetModule = TranslatePathIndex(nextModuleIndex,marineStatusPointer->path);
 
 
5889
 
 
 
5890
    assert(targetModule);
 
 
5891
    /* Ditto. */
 
 
5892
    marineStatusPointer->stepnumber = nextModuleIndex;
 
 
5893
 
 
 
5894
    /* Examine target, and decide what to do */
 
 
5895
    assert(AIModuleIsPhysical(targetModule));        
 
 
5896
    ProcessFarMarineTargetModule(sbPtr, targetModule);    
 
 
5897
    /* reset timer */
 
 
5898
    marineStatusPointer->stateTimer = MARINE_FAR_MOVE_TIME;                    
 
 
5899
 
 
 
5900
return SRC_No_Change;
 
 
5901
}
 
 
5902
 
 
 
5903
static STATE_RETURN_CONDITION Execute_MFS_Return(STRATEGYBLOCK *sbPtr)
 
 
5904
{
 
 
5905
    assert(sbPtr);
 
 
5906
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
5907
    assert(marineStatusPointer);
 
 
5908
 
 
 
5909
    /* Okay, so you're a LocalGuard or Pathfinder who's gotten lost. */
 
 
5910
 
 
 
5911
    /* Decrement the Far state timer */
 
 
5912
    marineStatusPointer->stateTimer -= NormalFrameTime;    
 
 
5913
    /* check if far state timer has timed-out. If so, it is time 
 
 
5914
    to do something. Otherwise just return. */
 
 
5915
 
 
 
5916
    if(marineStatusPointer->stateTimer > 0)
 
 
5917
        return SRC_No_Change;
 
 
5918
 
 
 
5919
    /* check for state changes */
 
 
5920
    /* Hack! */
 
 
5921
    if(MarineIsAwareOfTarget(sbPtr))
 
 
5922
        return SRC_Request_Approach; /* we should be engaging */
 
 
5923
 
 
 
5924
    /* Never break out of return unless your life is in danger! */
 
 
5925
 
 
 
5926
    /* Or unless we're back. */
 
 
5927
 
 
 
5928
    if (sbPtr->containingModule->m_aimodule == marineStatusPointer->missionmodule)
 
 
5929
        return SRC_Request_Wait;
 
 
5930
 
 
 
5931
    /* get the target module... */
 
 
5932
 
 
 
5933
    AIMODULE *targetModule = GetNextModuleForLink(sbPtr->containingModule->m_aimodule,marineStatusPointer->missionmodule,7,0);
 
 
5934
 
 
 
5935
    /* If there is no target module, we're way out there.  Better wander a bit more. */
 
 
5936
    if(!targetModule)
 
 
5937
        targetModule = FarNPC_GetTargetAIModuleForWander(sbPtr,marineStatusPointer->lastmodule,0);
 
 
5938
 
 
 
5939
    /* Examine target, and decide what to do */
 
 
5940
    if (AIModuleIsPhysical(targetModule) == 0)
 
 
5941
    {
 
 
5942
        /* We're probably fubared.  Change to Wander. */
 
 
5943
        if (marineStatusPointer->Mission != MM_NonCom)
 
 
5944
        {
 
 
5945
            /* Dunno what a NonCom is doing here, but Code Defensively! */
 
 
5946
            marineStatusPointer->Mission = MM_Wander;
 
 
5947
        }
 
 
5948
 
 
 
5949
    return SRC_Request_Wait;
 
 
5950
    }
 
 
5951
 
 
 
5952
    ProcessFarMarineTargetModule(sbPtr, targetModule);    
 
 
5953
    /* reset timer */
 
 
5954
    marineStatusPointer->stateTimer = MARINE_FAR_MOVE_TIME;                    
 
 
5955
 
 
 
5956
return SRC_No_Change;
 
 
5957
}
 
 
5958
 
 
 
5959
static void GuardMission_SwitchState(STRATEGYBLOCK *sbPtr,STATE_RETURN_CONDITION state_result) 
 
 
5960
{
 
 
5961
    STATE_RETURN_CONDITION real_state_result;
 
 
5962
 
 
 
5963
    assert(sbPtr);
 
 
5964
    assert(sbPtr->containingModule); 
 
 
5965
 
 
 
5966
    /* Experiment: override result? */
 
 
5967
    switch (state_result)
 
 
5968
    {
 
 
5969
        case (SRC_Request_Fire):
 
 
5970
        case (SRC_Request_Approach):
 
 
5971
            if (MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
5972
            {
 
 
5973
                real_state_result = SRC_Request_PanicFire;
 
 
5974
                break;
 
 
5975
            }
 
 
5976
        default:
 
 
5977
            real_state_result = state_result;
 
 
5978
            break;
 
 
5979
    }
 
 
5980
 
 
 
5981
    switch (real_state_result)
 
 
5982
    {
 
 
5983
        case SRC_No_Change:
 
 
5984
        {
 
 
5985
            /* No action. */
 
 
5986
        break;
 
 
5987
        }
 
 
5988
        case SRC_Request_Wait:
 
 
5989
        case SRC_Request_Avoidance:
 
 
5990
        case SRC_Request_Approach:
 
 
5991
        case SRC_Request_Wander:
 
 
5992
            Marine_Enter_SentryMode_State(sbPtr);
 
 
5993
        break;
 
 
5994
        case SRC_Request_Fire:
 
 
5995
            Marine_Enter_Firing_State(sbPtr);
 
 
5996
        break;
 
 
5997
        case SRC_Request_PanicFire:
 
 
5998
            Marine_Enter_PanicFire_State(sbPtr);
 
 
5999
        break;
 
 
6000
        case SRC_Request_Retreat:
 
 
6001
            Marine_Enter_Retreat_State(sbPtr);
 
 
6002
        break;
 
 
6003
        case SRC_Request_PullPistol:
 
 
6004
            Marine_Enter_PullPistol_State(sbPtr);
 
 
6005
        break;
 
 
6006
        default:
 
 
6007
        {
 
 
6008
            /* How did we end up here? */
 
 
6009
            assert(0);
 
 
6010
            break;
 
 
6011
        }
 
 
6012
    }
 
 
6013
}
 
 
6014
 
 
 
6015
static void LocalGuardMission_SwitchState(STRATEGYBLOCK *sbPtr,STATE_RETURN_CONDITION state_result) 
 
 
6016
{
 
 
6017
    STATE_RETURN_CONDITION real_state_result;
 
 
6018
 
 
 
6019
    assert(sbPtr);
 
 
6020
    assert(sbPtr->containingModule); 
 
 
6021
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
6022
    assert(marineStatusPointer);
 
 
6023
 
 
 
6024
    /* Experiment: override result? */
 
 
6025
    switch (state_result)
 
 
6026
    {
 
 
6027
        case (SRC_Request_Fire):
 
 
6028
        case (SRC_Request_Approach):
 
 
6029
            if (MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
6030
            {
 
 
6031
                real_state_result = SRC_Request_Retreat;
 
 
6032
                break;
 
 
6033
            }
 
 
6034
        default:
 
 
6035
            real_state_result = state_result;
 
 
6036
            break;
 
 
6037
    }
 
 
6038
 
 
 
6039
    switch (real_state_result)
 
 
6040
    {
 
 
6041
        case SRC_No_Change:
 
 
6042
        {
 
 
6043
            /* No action. */
 
 
6044
        break;
 
 
6045
        }
 
 
6046
        case SRC_Request_Wait:
 
 
6047
        {
 
 
6048
            if (marineStatusPointer->missionmodule == sbPtr->containingModule->m_aimodule)
 
 
6049
                Marine_Enter_Wait_State(sbPtr);
 
 
6050
            else
 
 
6051
                Marine_Enter_Return_State(sbPtr);
 
 
6052
        break;
 
 
6053
        }
 
 
6054
        case SRC_Request_Fire:
 
 
6055
        {
 
 
6056
            Marine_Enter_Firing_State(sbPtr);
 
 
6057
        break;
 
 
6058
        }
 
 
6059
        case SRC_Request_PanicFire:
 
 
6060
        {
 
 
6061
            Marine_Enter_PanicFire_State(sbPtr);
 
 
6062
        break;
 
 
6063
        }
 
 
6064
        case SRC_Request_Avoidance:
 
 
6065
        {
 
 
6066
            Marine_Enter_Avoidance_State(sbPtr);
 
 
6067
        break;
 
 
6068
        }
 
 
6069
        case SRC_Request_Approach:
 
 
6070
        {
 
 
6071
            Marine_Enter_Approach_State(sbPtr);
 
 
6072
        break;
 
 
6073
        }
 
 
6074
        case SRC_Request_Wander:
 
 
6075
        {
 
 
6076
            Marine_Enter_Wander_State(sbPtr);
 
 
6077
        break;
 
 
6078
        }
 
 
6079
        case SRC_Request_Retreat:
 
 
6080
        {
 
 
6081
            Marine_Enter_Retreat_State(sbPtr);
 
 
6082
        break;
 
 
6083
        }
 
 
6084
        case SRC_Request_Return:
 
 
6085
        {
 
 
6086
            Marine_Enter_Return_State(sbPtr);
 
 
6087
        break;
 
 
6088
        }
 
 
6089
        case SRC_Request_PullPistol:
 
 
6090
        {
 
 
6091
            Marine_Enter_PullPistol_State(sbPtr);
 
 
6092
        break;
 
 
6093
        }
 
 
6094
        default:
 
 
6095
        {
 
 
6096
            /* How did we end up here? */
 
 
6097
            assert(0);
 
 
6098
        break;
 
 
6099
        }
 
 
6100
    }
 
 
6101
}
 
 
6102
 
 
 
6103
static STATE_RETURN_CONDITION Execute_MFS_SentryMode(STRATEGYBLOCK *sbPtr)
 
 
6104
{
 
 
6105
    assert(sbPtr);
 
 
6106
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
6107
    assert(marineStatusPointer);
 
 
6108
 
 
 
6109
    /* Okay, so you're a Sentry who's been pushed off his spot. */
 
 
6110
 
 
 
6111
    if ((sbPtr->containingModule->m_aimodule == marineStatusPointer->missionmodule) || (marineStatusPointer->missionmodule == NULL))
 
 
6112
    {
 
 
6113
        if (marineStatusPointer->missionmodule != NULL)
 
 
6114
        {
 
 
6115
            VECTORCH offset;
 
 
6116
            /* Relocate? */
 
 
6117
 
 
 
6118
            offset.vx = sbPtr->DynPtr->Position.vx - marineStatusPointer->my_spot.vx;
 
 
6119
            offset.vy = sbPtr->DynPtr->Position.vy - marineStatusPointer->my_spot.vy;
 
 
6120
            offset.vz = sbPtr->DynPtr->Position.vz - marineStatusPointer->my_spot.vz;
 
 
6121
            /* Fix for midair start points, grrrr. */
 
 
6122
            offset.vy >>= 2;
 
 
6123
 
 
 
6124
            if (Approximate3dMagnitude(&offset) > SENTRY_SENSITIVITY)
 
 
6125
            {
 
 
6126
                sbPtr->DynPtr->Position = marineStatusPointer->my_spot;
 
 
6127
                sbPtr->containingModule = ModuleFromPosition(&sbPtr->DynPtr->Position, sbPtr->containingModule);
 
 
6128
            }
 
 
6129
        }
 
 
6130
 
 
 
6131
        if (marineStatusPointer->suspicious)
 
 
6132
        {
 
 
6133
            VECTORCH orientationDirn;
 
 
6134
 
 
 
6135
            orientationDirn.vx = marineStatusPointer->suspect_point.vx - sbPtr->DynPtr->Position.vx;
 
 
6136
            orientationDirn.vy = 0;
 
 
6137
            orientationDirn.vz = marineStatusPointer->suspect_point.vz - sbPtr->DynPtr->Position.vz;
 
 
6138
            int correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE);
 
 
6139
            marineStatusPointer->gotapoint = 0;
 
 
6140
        }
 
 
6141
 
 
 
6142
        /* Might want to spin on the spot. */
 
 
6143
        if (marineStatusPointer->gotapoint == 1)
 
 
6144
        {
 
 
6145
            VECTORCH orientationDirn;
 
 
6146
 
 
 
6147
            orientationDirn.vx = marineStatusPointer->wanderData.worldPosition.vx - sbPtr->DynPtr->Position.vx;
 
 
6148
            orientationDirn.vy = 0;
 
 
6149
            orientationDirn.vz = marineStatusPointer->wanderData.worldPosition.vz - sbPtr->DynPtr->Position.vz;
 
 
6150
 
 
 
6151
            int correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn, ONE_FIXED);
 
 
6152
 
 
 
6153
            if (correctlyOrientated)
 
 
6154
            {
 
 
6155
                marineStatusPointer->gotapoint = 2;
 
 
6156
                /* Done. */
 
 
6157
            }
 
 
6158
        }
 
 
6159
        else if (!marineStatusPointer->gotapoint)
 
 
6160
        {
 
 
6161
            GetPointToFaceMarineTowards(sbPtr,&marineStatusPointer->wanderData.worldPosition);
 
 
6162
        }
 
 
6163
    }
 
 
6164
    else
 
 
6165
    {
 
 
6166
        /* Decrement the Far state timer */
 
 
6167
        marineStatusPointer->stateTimer -= NormalFrameTime;    
 
 
6168
 
 
 
6169
        /* check if far state timer has timed-out. If so, it is time 
 
 
6170
        to do something. Otherwise just return. */
 
 
6171
        if(marineStatusPointer->stateTimer > 0)
 
 
6172
            return SRC_No_Change;
 
 
6173
 
 
 
6174
        /* Never engage, and ignore alerts. */                
 
 
6175
 
 
 
6176
        if (sbPtr->containingModule->m_aimodule == marineStatusPointer->missionmodule)
 
 
6177
            return SRC_No_Change; /* Same state next frame. */
 
 
6178
 
 
 
6179
        /* get the target module... */
 
 
6180
 
 
 
6181
        AIMODULE *targetModule = GetNextModuleForLink(sbPtr->containingModule->m_aimodule,marineStatusPointer->missionmodule,7,0);
 
 
6182
 
 
 
6183
        /* If there is no target module, we're way out there.  Better wander a bit more. */
 
 
6184
        if(!targetModule)
 
 
6185
            targetModule = FarNPC_GetTargetAIModuleForWander(sbPtr,marineStatusPointer->lastmodule,0);
 
 
6186
 
 
 
6187
        /* Examine target, and decide what to do */
 
 
6188
        assert(AIModuleIsPhysical(targetModule));        
 
 
6189
        ProcessFarMarineTargetModule(sbPtr, targetModule);    
 
 
6190
        /* reset timer */
 
 
6191
        marineStatusPointer->stateTimer = MARINE_FAR_MOVE_TIME;                    
 
 
6192
    }
 
 
6193
 
 
 
6194
return SRC_No_Change;
 
 
6195
}
 
 
6196
 
 
 
6197
static void LoiterMission_SwitchState(STRATEGYBLOCK *sbPtr,STATE_RETURN_CONDITION state_result)
 
 
6198
{
 
 
6199
    STATE_RETURN_CONDITION real_state_result;
 
 
6200
 
 
 
6201
    assert(sbPtr);
 
 
6202
    assert(sbPtr->containingModule); 
 
 
6203
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
6204
    assert(marineStatusPointer);
 
 
6205
 
 
 
6206
    /* Experiment: override result? */
 
 
6207
    switch (state_result)
 
 
6208
    {
 
 
6209
        case (SRC_Request_Fire):
 
 
6210
        case (SRC_Request_Approach):
 
 
6211
            if ((MarineRetreatsInTheFaceOfDanger(sbPtr)) && (marineStatusPointer->Target))
 
 
6212
            {
 
 
6213
                real_state_result = SRC_Request_Retreat;
 
 
6214
                break;
 
 
6215
            }
 
 
6216
        default:
 
 
6217
            real_state_result = state_result;
 
 
6218
            break;
 
 
6219
    }
 
 
6220
 
 
 
6221
    switch(real_state_result)
 
 
6222
    {
 
 
6223
        case SRC_No_Change:
 
 
6224
            /* No action. */
 
 
6225
        break;
 
 
6226
        case SRC_Request_Wait:
 
 
6227
            Marine_Enter_Wait_State(sbPtr);
 
 
6228
        break;
 
 
6229
        case SRC_Request_Fire:
 
 
6230
        case SRC_Request_PanicReload:
 
 
6231
            Marine_Enter_Retreat_State(sbPtr);
 
 
6232
        break;
 
 
6233
        case SRC_Request_Avoidance:
 
 
6234
            Marine_Enter_Avoidance_State(sbPtr);
 
 
6235
        break;
 
 
6236
        case SRC_Request_Approach:
 
 
6237
        {
 
 
6238
            if (marineStatusPointer->Target)
 
 
6239
            {
 
 
6240
                /* Approach?  You must be mad! */
 
 
6241
                Marine_Enter_Retreat_State(sbPtr);
 
 
6242
            }
 
 
6243
            else
 
 
6244
            {
 
 
6245
                /* We must be just suspicious. */
 
 
6246
                Marine_Enter_Approach_State(sbPtr);
 
 
6247
            }
 
 
6248
        break;
 
 
6249
        }
 
 
6250
        case SRC_Request_Retreat:
 
 
6251
            Marine_Enter_Retreat_State(sbPtr);
 
 
6252
        break;
 
 
6253
        case SRC_Request_Wander:
 
 
6254
            Marine_Enter_Wander_State(sbPtr);
 
 
6255
        break;
 
 
6256
        case SRC_Request_PanicFire:
 
 
6257
            Marine_Enter_PanicFire_State(sbPtr);
 
 
6258
        break;
 
 
6259
        default:
 
 
6260
        {
 
 
6261
            /* How did we end up here? */
 
 
6262
            assert(0);
 
 
6263
            break;
 
 
6264
        }
 
 
6265
    }
 
 
6266
}
 
 
6267
 
 
 
6268
static int human_in_los(STRATEGYBLOCK *sbPtr)
 
 
6269
{
 
 
6270
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
6271
return 0;
 
 
6272
    VECTORCH shotvector = {0, 0, 65535};
 
 
6273
    RotateVector(&shotvector, &marineStatusPointer->My_Gunflash_Section->SecMat);
 
 
6274
    Normalise(&shotvector);
 
 
6275
    FindPolygonInLineOfSight(&shotvector ,&marineStatusPointer->My_Gunflash_Section->World_Offset, 0, sbPtr->DisplayBlock);
 
 
6276
 
 
 
6277
    if (LOS_ObjectHitPtr && LOS_ObjectHitPtr->ObStrategyBlock)
 
 
6278
    {
 
 
6279
        switch(LOS_ObjectHitPtr->ObStrategyBlock->type)
 
 
6280
        {
 
 
6281
            case I_BehaviourMarine:
 
 
6282
            case I_BehaviourMarinePlayer:
 
 
6283
                return 1;
 
 
6284
            default:
 
 
6285
                return 0;
 
 
6286
        }
 
 
6287
    }
 
 
6288
 
 
 
6289
return 0;
 
 
6290
}
 
 
6291
 
 
 
6292
void MarineBehaviour(STRATEGYBLOCK *sbPtr)
 
 
6293
{
 
 
6294
    int marineIsNear = 0;
 
 
6295
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
6296
 
 
 
6297
    /* test if we've got a containing module: if we haven't, do nothing.
 
 
6298
    This is important as the object could have been marked for deletion by the visibility 
 
 
6299
    management system...*/
 
 
6300
 
 
 
6301
    if(!sbPtr->containingModule)
 
 
6302
    {
 
 
6303
        sbPtr->please_destroy_me = 1;
 
 
6304
        return;
 
 
6305
    }
 
 
6306
 
 
 
6307
    if(sbPtr->DisplayBlock)
 
 
6308
    {
 
 
6309
        marineIsNear = 1;
 
 
6310
        assert(ModuleCurrVisArray[sbPtr->containingModule->m_index]);                        
 
 
6311
    }
 
 
6312
/*
 
 
6313
    if (ShowSlack)
 
 
6314
    {
 
 
6315
        VECTORCH offset;
 
 
6316
        int slack = 0;
 
 
6317
 
 
 
6318
        offset.vx = (sbPtr->DynPtr->Position.vx - sbPtr->DynPtr->PrevPosition.vx);
 
 
6319
        offset.vy = (sbPtr->DynPtr->Position.vy - sbPtr->DynPtr->PrevPosition.vy);
 
 
6320
        offset.vz = (sbPtr->DynPtr->Position.vz - sbPtr->DynPtr->PrevPosition.vz);
 
 
6321
 
 
 
6322
        synthSpeed = DIV_FIXED(Magnitude(&offset), NormalFrameTime);
 
 
6323
        int setSpeed = Magnitude(&sbPtr->DynPtr->LinVelocity);
 
 
6324
 
 
 
6325
        if (setSpeed)
 
 
6326
            slack = (ONE_FIXED-(DIV_FIXED(synthSpeed, setSpeed)));
 
 
6327
 
 
 
6328
        printf("MaxSpeed = %d, SynthSpeed = %d, SetSpeed = %d, Slack %d\n",alienStatusPointer->MaxSpeed, synthSpeed, setSpeed, slack);
 
 
6329
    }
 
 
6330
*/
 
 
6331
    InitWaypointSystem(0);
 
 
6332
 
 
 
6333
    if (marineStatusPointer->Target)
 
 
6334
    {
 
 
6335
        if (NPC_IsDead(marineStatusPointer->Target) || !NAME_ISEQUAL(marineStatusPointer->Target->SBname, marineStatusPointer->Target_SBname))
 
 
6336
        {
 
 
6337
            marineStatusPointer->Target = NULL;
 
 
6338
            marineStatusPointer->lastroundhit = 0;
 
 
6339
            marineStatusPointer->lasthitsection = NULL;
 
 
6340
            marineStatusPointer->behaviourState = MBS_Waiting;
 
 
6341
        }
 
 
6342
        else
 
 
6343
        {
 
 
6344
            printf("HAS TARGET");
 
 
6345
 
 
 
6346
            if(!MarineCanSeeTarget(sbPtr))
 
 
6347
            {
 
 
6348
                marineStatusPointer->suspect_point = marineStatusPointer->Target->DynPtr->Position;
 
 
6349
                marineStatusPointer->previous_suspicion = marineStatusPointer->suspicious;
 
 
6350
                marineStatusPointer->suspicious = MARINE_PARANOIA_TIME * 6;
 
 
6351
                marineStatusPointer->using_squad_suspicion = 1;
 
 
6352
                PointAlert(2, &marineStatusPointer->suspect_point);
 
 
6353
                NpcSquad.squad_suspect_point = marineStatusPointer->suspect_point;
 
 
6354
printf(" CANNOT SEE IT ");
 
 
6355
                switch(marineStatusPointer->behaviourState)
 
 
6356
                {
 
 
6357
                    case MBS_Responding:
 
 
6358
                        printf("RESPONDINT");
 
 
6359
                        if(marineStatusPointer->incidentFlag)
 
 
6360
                        {
 
 
6361
                            printf("changing to APPROCH");
 
 
6362
                            marineStatusPointer->behaviourState = MBS_Approaching;
 
 
6363
                        }
 
 
6364
                        puts("");
 
 
6365
                    break;
 
 
6366
                    case MBS_Approaching: // jadda
 
 
6367
                        printf("APPROCK");
 
 
6368
                        if(0)
 
 
6369
                        if(marineStatusPointer->incidentFlag)
 
 
6370
                        {
 
 
6371
                            printf("Changint to RESPON");
 
 
6372
                            marineStatusPointer->behaviourState = MBS_Responding;
 
 
6373
                        }
 
 
6374
 
 
 
6375
                            if(DynamicObjectIsMoving(sbPtr->DynPtr))
 
 
6376
                                marineStatusPointer->suspicious = MARINE_PARANOIA_TIME;
 
 
6377
                        puts("");
 
 
6378
                    break;
 
 
6379
                    default:
 
 
6380
                            if(!DynamicObjectIsMoving(sbPtr->DynPtr))
 
 
6381
                            {
 
 
6382
                                if (marineStatusPointer->clipammo <= 0)
 
 
6383
                                    ;//Marine_Enter_Reload_State(sbPtr);
 
 
6384
                                else
 
 
6385
                                {
 
 
6386
                                    //marineStatusPointer->behaviourState = MBS_Waiting;
 
 
6387
                                }
 
 
6388
 
 
 
6389
                                    printf(" STANDINT STILL ");
 
 
6390
                                    //    marineStatusPointer->behaviourState = MBS_Sentry;
 
 
6391
                                if(0) if(marineStatusPointer->incidentFlag)
 
 
6392
                                if(MBS_Avoidance == marineStatusPointer->behaviourState)
 
 
6393
                                {
 
 
6394
                                    marineStatusPointer->Target = NULL;
 
 
6395
 
 
 
6396
                                    switch(FastRandom() & 3)
 
 
6397
                                    {
 
 
6398
                                        case 0:
 
 
6399
                                        marineStatusPointer->behaviourState = MBS_Waiting;
 
 
6400
                                        printf(" new state waiting");
 
 
6401
                                        break;
 
 
6402
                                        case 1:
 
 
6403
                                        marineStatusPointer->behaviourState = MBS_Retreating;
 
 
6404
                                        printf(" new state retreat");
 
 
6405
                                        break;
 
 
6406
                                        case 2:
 
 
6407
                                        marineStatusPointer->behaviourState = MBS_Returning;
 
 
6408
                                        printf(" new state retunring");
 
 
6409
                                        break;
 
 
6410
                                        case 3:
 
 
6411
                                        marineStatusPointer->behaviourState = MBS_Sentry;
 
 
6412
                                        printf(" new state sentry");
 
 
6413
                                    }
 
 
6414
                                }
 
 
6415
                                else
 
 
6416
                                {
 
 
6417
                                        printf(" new state avoid ");
 
 
6418
                                    marineStatusPointer->behaviourState = MBS_Avoidance;
 
 
6419
                                }
 
 
6420
                            }
 
 
6421
                            else
 
 
6422
                            {
 
 
6423
                                        printf(" new state approach");
 
 
6424
                                marineStatusPointer->behaviourState = MBS_Approaching;
 
 
6425
                            }
 
 
6426
                                //marineStatusPointer->behaviourState = MBS_Approaching;
 
 
6427
                }
 
 
6428
                puts("");
 
 
6429
 
 
 
6430
                //if(marineStatusPointer->incidentFlag)
 
 
6431
                if ((FastRandom() & 65535) > ONE_FIXED - 11128)
 
 
6432
                {
 
 
6433
                    Marine_Enter_Taunt_State(sbPtr);
 
 
6434
                    puts("TATNN");
 
 
6435
                }
 
 
6436
            }
 
 
6437
            else
 
 
6438
            {
 
 
6439
                if(marineIsNear)
 
 
6440
                {
 
 
6441
                    if (human_in_los(sbPtr))
 
 
6442
                    {
 
 
6443
                        marineStatusPointer->Courage += MUL_FIXED(NormalFrameTime, 300);
 
 
6444
                        marineStatusPointer->behaviourState = ((FastRandom() & 127) > 10) ?  MBS_Approaching : MBS_Avoidance; 
 
 
6445
                    }
 
 
6446
                    else
 
 
6447
                    {
 
 
6448
                        int range = VectorDistance(&marineStatusPointer->Target->DynPtr->Position, &sbPtr->DynPtr->Position);
 
 
6449
 
 
 
6450
                        if(range < MARINE_CLOSE_APPROACH_DISTANCE)
 
 
6451
                        {
 
 
6452
                            marineStatusPointer->behaviourState = MBS_Waiting;
 
 
6453
                            marineStatusPointer->IAmCrouched = 1;
 
 
6454
                            puts("close");
 
 
6455
                        }
 
 
6456
                        else
 
 
6457
                        {
 
 
6458
                            puts("long");
 
 
6459
 
 
 
6460
                            marineStatusPointer->IAmCrouched = 0;
 
 
6461
                            //(*marineStatusPointer->My_Weapon->WeaponFireFunction)(sbPtr);
 
 
6462
                            //SetMarineElevation(sbPtr);
 
 
6463
                        }
 
 
6464
                    }
 
 
6465
                }
 
 
6466
                else
 
 
6467
                {
 
 
6468
                    //Execute_MFS_Firing(sbPtr);// jadda fix this
 
 
6469
                }
 
 
6470
 
 
 
6471
                //if (MBS_Waiting == marineStatusPointer->behaviourState) puts("WAITIN");
 
 
6472
                    //printf("your are so fucking dead! This is going to be game over\n");
 
 
6473
            }
 
 
6474
        }
 
 
6475
/*
 
 
6476
    switch(marineStatusPointer->behaviourState)
 
 
6477
    {
 
 
6478
        case MBS_Waiting:
 
 
6479
        case MBS_Wandering:
 
 
6480
        case MBS_Sentry:
 
 
6481
        case MBS_Approaching:
 
 
6482
        case MBS_Firing:
 
 
6483
        case MBS_Avoidance:
 
 
6484
        case MBS_Responding:
 
 
6485
        case MBS_Returning:
 
 
6486
        case MBS_Pathfinding:
 
 
6487
        case MBS_Taunting:
 
 
6488
        case MBS_PanicFire:
 
 
6489
        case MBS_Reloading:
 
 
6490
        case MBS_PumpAction:
 
 
6491
        case MBS_GetWeapon:
 
 
6492
        case MBS_PanicReloading:
 
 
6493
        case MBS_AcidAvoidance:
 
 
6494
 
 
 
6495
    } MARINE_BHSTATE;
 
 
6496
*/
 
 
6497
    }
 
 
6498
 
 
 
6499
    if ((marineStatusPointer->Target == NULL) 
 
 
6500
        #if ANARCHY
 
 
6501
        || (marineStatusPointer->lastmodule != sbPtr->containingModule->m_aimodule)
 
 
6502
        #endif
 
 
6503
        )
 
 
6504
    {
 
 
6505
        if (marineIsNear || marineStatusPointer->incidentFlag)
 
 
6506
        {
 
 
6507
            /* Get new target. */
 
 
6508
            marineStatusPointer->roundsForThisTarget = 0;
 
 
6509
            marineStatusPointer->Target = Marine_GetNewTarget(&sbPtr->DynPtr->Position, sbPtr);
 
 
6510
 
 
 
6511
            if (marineStatusPointer->Target)
 
 
6512
            {
 
 
6513
                COPY_NAME(marineStatusPointer->Target_SBname, marineStatusPointer->Target->SBname);
 
 
6514
 
 
 
6515
                /* Remember your suspicion... */
 
 
6516
                marineStatusPointer->previous_suspicion = marineStatusPointer->suspicious;
 
 
6517
                marineStatusPointer->suspicious = 0;
 
 
6518
 
 
 
6519
                if (marineStatusPointer->Target == PlayerStatus.sbptr)
 
 
6520
                {
 
 
6521
                    if (!marineStatusPointer->SpotFlag)
 
 
6522
                    {
 
 
6523
                        CurrentGameStats_Spotted();
 
 
6524
                        marineStatusPointer->SpotFlag = 1;
 
 
6525
                    }
 
 
6526
                }
 
 
6527
 
 
 
6528
                /* New Enemy! */
 
 
6529
 
 
 
6530
                if (!NpcSquad.alertStatus)
 
 
6531
                    NpcSquad.alertStatus = 1;
 
 
6532
 
 
 
6533
                if (marineStatusPointer->Target->containingModule)
 
 
6534
                    ZoneAlert(2, marineStatusPointer->Target->containingModule->m_aimodule);
 
 
6535
                else
 
 
6536
                    ZoneAlert(2, sbPtr->containingModule->m_aimodule);
 
 
6537
            }
 
 
6538
        }
 
 
6539
    }
 
 
6540
 
 
 
6541
    if (marineStatusPointer->suspicious)
 
 
6542
    {
 
 
6543
        switch(marineStatusPointer->behaviourState)
 
 
6544
        {
 
 
6545
            case MBS_Approaching:
 
 
6546
            case MBS_Responding:
 
 
6547
            {
 
 
6548
                int range = VectorDistance(&marineStatusPointer->suspect_point, &sbPtr->DynPtr->Position);
 
 
6549
 
 
 
6550
                if (((range < SUSPECT_SENSITIVITY) && !MarineCanSeeTarget(sbPtr)) || !DynamicObjectIsMoving(sbPtr->DynPtr))
 
 
6551
                {
 
 
6552
                    // goto default;
 
 
6553
                }
 
 
6554
                else
 
 
6555
                break;
 
 
6556
            }
 
 
6557
            default:
 
 
6558
            {
 
 
6559
                VECTORCH orientationDirn;
 
 
6560
 
 
 
6561
                orientationDirn.vx = marineStatusPointer->suspect_point.vx - sbPtr->DynPtr->Position.vx;
 
 
6562
                orientationDirn.vy = 0;
 
 
6563
                orientationDirn.vz = marineStatusPointer->suspect_point.vz - sbPtr->DynPtr->Position.vz;
 
 
6564
 
 
 
6565
                if (!NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE))
 
 
6566
                    return;
 
 
6567
 
 
 
6568
                marineStatusPointer->suspicious -= NormalFrameTime;
 
 
6569
 
 
 
6570
                if(marineStatusPointer->incidentFlag)
 
 
6571
                if (marineStatusPointer->suspicious < 0)
 
 
6572
                {
 
 
6573
                    marineStatusPointer->Target = NULL;
 
 
6574
                    /* Set to zero on natural timeout, too. */
 
 
6575
                    marineStatusPointer->suspicious = 0;
 
 
6576
                    marineStatusPointer->previous_suspicion = 0;
 
 
6577
                    marineStatusPointer->using_squad_suspicion = 0;
 
 
6578
                    marineStatusPointer->gotapoint = 0;
 
 
6579
                }
 
 
6580
            }
 
 
6581
        }
 
 
6582
 
 
 
6583
        if (marineStatusPointer->My_Weapon->ARealMarine)
 
 
6584
        {
 
 
6585
            if (!marineStatusPointer->FlareActive && !LightIntensityAtPoint(&marineStatusPointer->suspect_point))
 
 
6586
            {
 
 
6587
                throw_flare(marineStatusPointer);
 
 
6588
            }
 
 
6589
            else if (marineStatusPointer->FlareActive)
 
 
6590
            {
 
 
6591
                marineStatusPointer->FlareActive -= NormalFrameTime;
 
 
6592
 
 
 
6593
                if (marineStatusPointer->FlareActive < 0)
 
 
6594
                    marineStatusPointer->FlareActive  = 0;
 
 
6595
            }
 
 
6596
        }
 
 
6597
    }
 
 
6598
 
 
 
6599
    /* Squad level suspicion? */
 
 
6600
    switch(marineStatusPointer->behaviourState)
 
 
6601
    {
 
 
6602
        case MBS_Firing:
 
 
6603
        break;
 
 
6604
        case MBS_Approaching:
 
 
6605
            EndMarineMuzzleFlash(sbPtr, marineStatusPointer);
 
 
6606
        break;
 
 
6607
        default:
 
 
6608
            EndMarineMuzzleFlash(sbPtr, marineStatusPointer);
 
 
6609
            if ((!marineStatusPointer->suspicious || marineStatusPointer->using_squad_suspicion) && NpcSquad.Squad_Suspicion &&
sbPtr->DisplayBlock)
 
 
6610
            {
 
 
6611
                /* Use squad suspicion. */
 
 
6612
                marineStatusPointer->suspicious = MARINE_PARANOIA_TIME;
 
 
6613
                marineStatusPointer->suspect_point = NpcSquad.squad_suspect_point;
 
 
6614
                /* Set this to zero when you get a *new* suspicion. */
 
 
6615
                marineStatusPointer->previous_suspicion = 0;
 
 
6616
                marineStatusPointer->using_squad_suspicion = 1;
 
 
6617
            }
 
 
6618
    }
 
 
6619
 
 
 
6620
    /* Unset incident flag. */
 
 
6621
    marineStatusPointer->incidentFlag = 0;
 
 
6622
    marineStatusPointer->incidentTimer -= NormalFrameTime;
 
 
6623
 
 
 
6624
    if (marineStatusPointer->incidentTimer < 0)
 
 
6625
    {
 
 
6626
        marineStatusPointer->incidentFlag = 1;
 
 
6627
        marineStatusPointer->incidentTimer = 32767 + (FastRandom() & 65535);
 
 
6628
    }
 
 
6629
 
 
 
6630
    /* Blinking! */
 
 
6631
    {
 
 
6632
        if (marineStatusPointer->Expression < 3)
 
 
6633
        {
 
 
6634
            if (marineStatusPointer->incidentFlag)
 
 
6635
            {
 
 
6636
                if ((FastRandom() & 65535) < 24000)
 
 
6637
                {
 
 
6638
                    switch (marineStatusPointer->Expression)
 
 
6639
                    {
 
 
6640
                        default:
 
 
6641
                            assert(0);
 
 
6642
                        break;
 
 
6643
                        case 0:
 
 
6644
                            Marine_SwitchExpression(sbPtr,3);
 
 
6645
                        break;
 
 
6646
                        case 1:
 
 
6647
                            Marine_SwitchExpression(sbPtr,4);
 
 
6648
                        break;
 
 
6649
                        case 2:
 
 
6650
                            Marine_SwitchExpression(sbPtr,5);
 
 
6651
                        break;
 
 
6652
                    }
 
 
6653
 
 
 
6654
                    marineStatusPointer->Blink = 0;
 
 
6655
                }
 
 
6656
            }
 
 
6657
        }
 
 
6658
        else if (marineStatusPointer->Expression >= 3)
 
 
6659
        {
 
 
6660
            if (marineStatusPointer->Blink >= 0)
 
 
6661
            {
 
 
6662
                marineStatusPointer->Blink += NormalFrameTime;
 
 
6663
 
 
 
6664
                if (marineStatusPointer->Blink > (ONE_FIXED/7))
 
 
6665
                {
 
 
6666
                    switch (marineStatusPointer->Expression)
 
 
6667
                    {
 
 
6668
                        default:
 
 
6669
                            assert(0);
 
 
6670
                        break;
 
 
6671
                        case 3:
 
 
6672
                            Marine_SwitchExpression(sbPtr,0);
 
 
6673
                        break;
 
 
6674
                        case 4:
 
 
6675
                            Marine_SwitchExpression(sbPtr,1);
 
 
6676
                        break;
 
 
6677
                        case 5:
 
 
6678
                            Marine_SwitchExpression(sbPtr,2);
 
 
6679
                        break;
 
 
6680
                    }
 
 
6681
                }
 
 
6682
            }
 
 
6683
        }
 
 
6684
 
 
 
6685
        AddPheromones(sbPtr->containingModule->m_aimodule);
 
 
6686
        DoMarineHearing(sbPtr);
 
 
6687
 
 
 
6688
        {
 
 
6689
            /* Brushing Test. */
 
 
6690
 
 
 
6691
            struct collisionreport *nextReport = sbPtr->DynPtr->CollisionReportPtr;
 
 
6692
            int while_true = 1;
 
 
6693
 
 
 
6694
            while(nextReport && while_true)
 
 
6695
            {
 
 
6696
                if(nextReport->ObstacleSBPtr)
 
 
6697
                {    
 
 
6698
                    switch(nextReport->ObstacleSBPtr->type)
 
 
6699
                    {
 
 
6700
                        case I_BehaviourAlienPlayer:
 
 
6701
                        case I_BehaviourPredatorPlayer:
 
 
6702
                        case I_BehaviourMarinePlayer:
 
 
6703
                        case I_BehaviourPredator:
 
 
6704
                        case I_BehaviourAlien:
 
 
6705
                        case I_BehaviourNetGhost:
 
 
6706
                        case I_BehaviourFaceHugger:
 
 
6707
                        case I_BehaviourXenoborg:
 
 
6708
                        case I_BehaviourQueenAlien:
 
 
6709
                        {
 
 
6710
                            while_true = 0;
 
 
6711
                            marineStatusPointer->suspicious = MARINE_PARANOIA_TIME;
 
 
6712
                            marineStatusPointer->suspect_point = nextReport->ObstacleSBPtr->DynPtr->Position;
 
 
6713
                            /* Set this to zero when you get a *new* suspicion. */
 
 
6714
                            marineStatusPointer->previous_suspicion = 0;
 
 
6715
                            marineStatusPointer->using_squad_suspicion = 0;
 
 
6716
                            marineStatusPointer->behaviourState = MBS_Responding;
 
 
6717
 
 
 
6718
                            if (!marineStatusPointer->Android)
 
 
6719
                                marineStatusPointer->Courage -= NormalFrameTime >> 1;
 
 
6720
                        }
 
 
6721
                        default:
 
 
6722
                        break;
 
 
6723
                    }
 
 
6724
                }
 
 
6725
 
 
 
6726
                nextReport = nextReport->NextCollisionReportPtr;
 
 
6727
            }
 
 
6728
        }
 
 
6729
 
 
 
6730
        /* Make marines heal, really slowly? */
 
 
6731
        HModel_Regen(&marineStatusPointer->HModelController, (120 * ONE_FIXED));
 
 
6732
        /* Two minutes.  Only heals sections, too. */
 
 
6733
 
 
 
6734
        /* Change the face if we can... */
 
 
6735
        Marine_UpdateFace(sbPtr);
 
 
6736
 
 
 
6737
        /* And finally, update lastframe flag. */
 
 
6738
        Marine_ConsiderFallingDamage(sbPtr);
 
 
6739
    }
 
 
6740
 
 
 
6741
    /* That was senses. Now courage. */
 
 
6742
    if (!marineStatusPointer->Android)
 
 
6743
    {
 
 
6744
        if ((marineStatusPointer->Target == NULL) && !marineStatusPointer->suspicious)
 
 
6745
            marineStatusPointer->Courage += MUL_FIXED(NormalFrameTime, 300);
 
 
6746
 
 
 
6747
        marineStatusPointer->Courage += NpcSquad.Squad_Delta_Morale;
 
 
6748
 
 
 
6749
        if (marineStatusPointer->Courage >= (ONE_FIXED << 1))
 
 
6750
        {
 
 
6751
            marineStatusPointer->Courage = ONE_FIXED << 1;
 
 
6752
        }
 
 
6753
        else if (marineStatusPointer->Courage < 0)
 
 
6754
        {
 
 
6755
            marineStatusPointer->Courage = 0;
 
 
6756
        }
 
 
6757
    }
 
 
6758
    else
 
 
6759
    {
 
 
6760
        marineStatusPointer->Courage = ONE_FIXED;
 
 
6761
    }
 
 
6762
 
 
 
6763
    if (sbPtr->DamageBlock.IsOnFire)
 
 
6764
    {
 
 
6765
        if (marineStatusPointer->Mission != MM_RunAroundOnFire)
 
 
6766
        {
 
 
6767
            if (!marineStatusPointer->Android)
 
 
6768
            {
 
 
6769
                /* Grimace. */
 
 
6770
                Marine_SwitchExpression(sbPtr,5);
 
 
6771
 
 
 
6772
                DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
6773
 
 
 
6774
                /* Switch to template. */
 
 
6775
                SECTION *root = GetNamedHierarchyFromLibrary(marineStatusPointer->My_Weapon->Riffname,
marineStatusPointer->My_Weapon->TemplateName);
 
 
6776
 
 
 
6777
                /* Remove all deltas. */
 
 
6778
                Remove_Delta_Sequence(&marineStatusPointer->HModelController,"Elevation");
 
 
6779
                Remove_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta");
 
 
6780
                Remove_Delta_Sequence(&marineStatusPointer->HModelController,"Minigun");
 
 
6781
                Remove_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
 
 
6782
 
 
 
6783
                Transmogrify_HModels(sbPtr,&marineStatusPointer->HModelController, root, 1, 0,0);
 
 
6784
 
 
 
6785
                SetMarineAnimationSequence(sbPtr, HMSQT_MarineRun, MRSS_Tem_Run_On_Fire, (ONE_FIXED*3), (ONE_FIXED>>2));
 
 
6786
 
 
 
6787
                GetFirstRandomDirection(marineStatusPointer, &marineStatusPointer->wanderData.worldPosition);
 
 
6788
 
 
 
6789
                /* Hey, it's a spare vector. */
 
 
6790
                marineStatusPointer->nearSpeed = MARINE_NEAR_SPEED >> 1;
 
 
6791
                NPCSetVelocity(sbPtr, &marineStatusPointer->wanderData.worldPosition, marineStatusPointer->nearSpeed);    
 
 
6792
 
 
 
6793
                marineStatusPointer->Mission = MM_RunAroundOnFire;
 
 
6794
                marineStatusPointer->behaviourState = MBS_Wandering;
 
 
6795
                marineStatusPointer->lastState = MBS_Waiting;
 
 
6796
                marineStatusPointer->stateTimer = ONE_FIXED;
 
 
6797
 
 
 
6798
                if (marineIsNear)
 
 
6799
                {
 
 
6800
                    /* check if we should be crouched or standing up */
 
 
6801
                    if(marineStatusPointer->IAmCrouched)
 
 
6802
                    {
 
 
6803
                        /* curently crouched */
 
 
6804
                        if(!MarineShouldBeCrawling(sbPtr))
 
 
6805
                        {
 
 
6806
                            /* should be running*/
 
 
6807
                            marineStatusPointer->IAmCrouched = 0;
 
 
6808
                            SetMarineAnimationSequence(sbPtr, HMSQT_MarineRun, MRSS_Tem_Run_On_Fire, ONE_FIXED, (ONE_FIXED>>3));
 
 
6809
                        }
 
 
6810
                    }
 
 
6811
                    else
 
 
6812
                    {
 
 
6813
                        /* currently standing */
 
 
6814
                        if(MarineShouldBeCrawling(sbPtr))
 
 
6815
                        {
 
 
6816
                            /* should be crawling, I guess... */
 
 
6817
                            marineStatusPointer->IAmCrouched = 1;
 
 
6818
                            SetMarineAnimationSequence(sbPtr, HMSQT_MarineCrawl, MCrSS_Standard, ONE_FIXED, (ONE_FIXED>>3));
 
 
6819
                        }
 
 
6820
                    }
 
 
6821
 
 
 
6822
                    /* Set velocity for this frame. */
 
 
6823
                    marineStatusPointer->stateTimer -= NormalFrameTime;
 
 
6824
 
 
 
6825
                    if (marineStatusPointer->stateTimer < 0)
 
 
6826
                    {
 
 
6827
                        marineStatusPointer->stateTimer = 0;
 
 
6828
                        GetNewRandomDirection(marineStatusPointer);
 
 
6829
                        marineStatusPointer->stateTimer = ONE_FIXED;
 
 
6830
                    }
 
 
6831
 
 
 
6832
                    TurnToFaceRandomDirection(marineStatusPointer, &marineStatusPointer->wanderData.worldPosition);
 
 
6833
                    NPCSetVelocity(sbPtr, &marineStatusPointer->wanderData.worldPosition, marineStatusPointer->nearSpeed);    
 
 
6834
 
 
 
6835
                }
 
 
6836
                else
 
 
6837
                {
 
 
6838
                    Execute_MFS_Wait(sbPtr);
 
 
6839
                }
 
 
6840
            }
 
 
6841
        }
 
 
6842
        else
 
 
6843
        {
 
 
6844
            if (marineIsNear)
 
 
6845
            {
 
 
6846
                int sound_handle =  marineStatusPointer->Android ? marineStatusPointer->soundHandle2 : marineStatusPointer->soundHandle;
 
 
6847
                // androids dont do burning scream voice soundHandle2
 
 
6848
                // humans don't use weapons when on fire soundHandle
 
 
6849
 
 
 
6850
                if (ActiveSounds[sound_handle].soundIndex != SID_FIRE)
 
 
6851
                {
 
 
6852
                    Sound_Stop(sound_handle);
 
 
6853
                    Sound_Play(SID_FIRE, "dle", &sbPtr->DynPtr->Position, &sound_handle);
 
 
6854
                }
 
 
6855
                else if(SOUND_NOACTIVEINDEX != sound_handle)
 
 
6856
                {
 
 
6857
                    Sound_Update3d(sound_handle, &sbPtr->DynPtr->Position);
 
 
6858
                }
 
 
6859
            }
 
 
6860
            printf("RAOF marine running in %s\n", sbPtr->containingModule->name);
 
 
6861
            CauseDamageToObject(sbPtr, &damage_profiles[FIREDAMAGE], NormalFrameTime * 24, NULL);
 
 
6862
 
 
 
6863
            if (sbPtr->type == I_BehaviourCorpse)
 
 
6864
                return; /* Gettin' out of here... */
 
 
6865
        }
 
 
6866
    }
 
 
6867
 
 
 
6868
    switch (marineStatusPointer->Mission)
 
 
6869
    {
 
 
6870
        case MM_Wait_Then_Wander:
 
 
6871
        case MM_Wander:
 
 
6872
        {
 
 
6873
            STATE_RETURN_CONDITION state_result;
 
 
6874
 
 
 
6875
            switch(marineStatusPointer->behaviourState)
 
 
6876
            {
 
 
6877
                case MBS_Approaching:
 
 
6878
                {
 
 
6879
                    //printf("Wander marine approach in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
6880
 
 
 
6881
                    if(marineIsNear)
 
 
6882
                    {
 
 
6883
                        state_result = Execute_MNS_Approach(sbPtr);
 
 
6884
                        CentreMarineElevation(sbPtr);
 
 
6885
                    }
 
 
6886
                    else
 
 
6887
                    {
 
 
6888
                        state_result = Execute_MFS_Approach(sbPtr);
 
 
6889
                    }
 
 
6890
 
 
 
6891
                    WanderMission_SwitchState(sbPtr, state_result);
 
 
6892
                }
 
 
6893
                break;
 
 
6894
                case MBS_Firing:
 
 
6895
                {
 
 
6896
                    //printf("Wander marine firing in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
6897
 
 
 
6898
                    if (marineIsNear)
 
 
6899
                    {
 
 
6900
                        //state_result = (*marineStatusPointer->My_Weapon->WeaponFireFunction)(sbPtr);
 
 
6901
                        //SetMarineElevation(sbPtr);
 
 
6902
                    }
 
 
6903
                    else
 
 
6904
                    {
 
 
6905
                        //state_result = Execute_MFS_Firing(sbPtr);
 
 
6906
                    }
 
 
6907
 
 
 
6908
                    WanderMission_SwitchState(sbPtr, state_result);
 
 
6909
                }
 
 
6910
                break;
 
 
6911
                case MBS_PanicFire:
 
 
6912
                {
 
 
6913
                    //printf("Wander marine panic firing in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
6914
 
 
 
6915
                    if (marineIsNear)
 
 
6916
                    {
 
 
6917
                        state_result = (*marineStatusPointer->My_Weapon->WeaponPanicFireFunction)(sbPtr);
 
 
6918
                        CentreMarineElevation(sbPtr);
 
 
6919
                    }
 
 
6920
                    else
 
 
6921
                    {
 
 
6922
                        //state_result = Execute_MFS_Firing(sbPtr);
 
 
6923
                    }
 
 
6924
 
 
 
6925
                    WanderMission_SwitchState(sbPtr, state_result);
 
 
6926
                }
 
 
6927
                break;
 
 
6928
                case MBS_Avoidance:
 
 
6929
                {
 
 
6930
                    #if MARINE_PRINT_STATE
 
 
6931
                    {
 
 
6932
                        printf("Wander marine ");
 
 
6933
 
 
 
6934
                        switch (marineStatusPointer->avoidanceManager.substate)
 
 
6935
                        {
 
 
6936
                            default:
 
 
6937
                            case AvSS_FreeMovement:
 
 
6938
                                printf("Avoidance Level 0");
 
 
6939
                            break;
 
 
6940
                            case AvSS_FirstAvoidance:
 
 
6941
                                printf("Avoidance Level 1");
 
 
6942
                            break;
 
 
6943
                            case AvSS_SecondAvoidance:
 
 
6944
                                printf("Avoidance Level 2");
 
 
6945
                            break;
 
 
6946
                            case AvSS_ThirdAvoidance:
 
 
6947
                                printf("Avoidance Level 3");
 
 
6948
                            break;
 
 
6949
                        }    
 
 
6950
 
 
 
6951
                        printf(" in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
6952
                    }
 
 
6953
                    #endif
 
 
6954
 
 
 
6955
                    if(marineIsNear)
 
 
6956
                    {
 
 
6957
                        state_result = Execute_MNS_Avoidance(sbPtr);
 
 
6958
                        CentreMarineElevation(sbPtr);
 
 
6959
                    }
 
 
6960
                    else
 
 
6961
                    {
 
 
6962
                        state_result = Execute_MFS_Avoidance(sbPtr);
 
 
6963
                    }
 
 
6964
 
 
 
6965
                    WanderMission_SwitchState(sbPtr, state_result);
 
 
6966
                }
 
 
6967
                break;
 
 
6968
                case MBS_Wandering:
 
 
6969
                {
 
 
6970
                    //printf("Wander marine wander in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
6971
 
 
 
6972
                    if (marineIsNear)
 
 
6973
                    {
 
 
6974
                        state_result = Execute_MNS_Wander(sbPtr);
 
 
6975
                        CentreMarineElevation(sbPtr);
 
 
6976
                    }
 
 
6977
                    else
 
 
6978
                    {
 
 
6979
                        state_result = Execute_MFS_Wander(sbPtr);
 
 
6980
                    }
 
 
6981
 
 
 
6982
                    WanderMission_SwitchState(sbPtr, state_result);
 
 
6983
                }
 
 
6984
                break;
 
 
6985
                case MBS_Responding:
 
 
6986
                {
 
 
6987
                    //printf("Wander marine responding in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
6988
 
 
 
6989
                    if (marineIsNear)
 
 
6990
                    {
 
 
6991
                        state_result = Execute_MNS_Respond(sbPtr);
 
 
6992
                        CentreMarineElevation(sbPtr);
 
 
6993
                    }
 
 
6994
                    else
 
 
6995
                    {
 
 
6996
                        state_result = Execute_MFS_Respond(sbPtr);
 
 
6997
                    }
 
 
6998
 
 
 
6999
                    WanderMission_SwitchState(sbPtr, state_result);
 
 
7000
                }
 
 
7001
                break;
 
 
7002
                case MBS_Retreating:
 
 
7003
                {
 
 
7004
                    /* Real men never retreat! */
 
 
7005
                    //printf("Wander marine Retreating in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7006
 
 
 
7007
                    if (marineIsNear)
 
 
7008
                    {
 
 
7009
                        state_result = Execute_MNS_Retreat(sbPtr);
 
 
7010
                        CentreMarineElevation(sbPtr);
 
 
7011
                    }
 
 
7012
                    else
 
 
7013
                    {
 
 
7014
                        state_result = Execute_MFS_Retreat(sbPtr);
 
 
7015
                    }
 
 
7016
 
 
 
7017
                    WanderMission_SwitchState(sbPtr, state_result);
 
 
7018
                }
 
 
7019
                break;
 
 
7020
                case MBS_Waiting:
 
 
7021
                {
 
 
7022
                    //printf("Wander marine wait in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7023
 
 
 
7024
                    if (marineIsNear)
 
 
7025
                    {
 
 
7026
                        state_result = Execute_MNS_Wait(sbPtr);
 
 
7027
                        CentreMarineElevation(sbPtr);
 
 
7028
                    }
 
 
7029
                    else
 
 
7030
                    {
 
 
7031
                        state_result = Execute_MFS_Wait(sbPtr);
 
 
7032
                    }
 
 
7033
 
 
 
7034
                    WanderMission_SwitchState(sbPtr, state_result);
 
 
7035
                }
 
 
7036
                break;
 
 
7037
                case MBS_Sentry:
 
 
7038
                {
 
 
7039
                    //printf("Wander marine sentry in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7040
 
 
 
7041
                    assert(0);
 
 
7042
 
 
 
7043
                    if(marineIsNear)
 
 
7044
                    {
 
 
7045
                        state_result = Execute_MNS_SentryMode(sbPtr);
 
 
7046
                        CentreMarineElevation(sbPtr);
 
 
7047
                    }
 
 
7048
                    else
 
 
7049
                    {
 
 
7050
                        state_result = Execute_MFS_Wait(sbPtr);
 
 
7051
                    }
 
 
7052
 
 
 
7053
                    WanderMission_SwitchState(sbPtr, state_result);
 
 
7054
                }
 
 
7055
                break;
 
 
7056
                case MBS_Taunting:
 
 
7057
                {
 
 
7058
                    //printf("Wander marine taunt in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7059
 
 
 
7060
                    state_result = Execute_MNS_Taunting(sbPtr);
 
 
7061
 
 
 
7062
                    if(marineIsNear)
 
 
7063
                        CentreMarineElevation(sbPtr);
 
 
7064
 
 
 
7065
                    WanderMission_SwitchState(sbPtr, state_result);
 
 
7066
                }
 
 
7067
                break;
 
 
7068
                case MBS_Reloading:
 
 
7069
                {
 
 
7070
                    //printf("Wander marine reloading in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7071
 
 
 
7072
                    state_result = Execute_MNS_Reloading(sbPtr);
 
 
7073
 
 
 
7074
                    if(marineIsNear)
 
 
7075
                        CentreMarineElevation(sbPtr);
 
 
7076
 
 
 
7077
                    WanderMission_SwitchState(sbPtr, state_result);
 
 
7078
                }
 
 
7079
                break;
 
 
7080
                case MBS_PanicReloading:
 
 
7081
                {
 
 
7082
                    //printf("Wander marine panic reloading in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7083
 
 
 
7084
                    state_result = Execute_MNS_PanicReloading(sbPtr);
 
 
7085
 
 
 
7086
                    if(marineIsNear)
 
 
7087
                        CentreMarineElevation(sbPtr);
 
 
7088
 
 
 
7089
                    WanderMission_SwitchState(sbPtr, state_result);
 
 
7090
                }
 
 
7091
                break;
 
 
7092
                case MBS_GetWeapon:
 
 
7093
                {
 
 
7094
                    //printf("Wander marine get weapon in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7095
 
 
 
7096
                    state_result = Execute_MNS_GetWeapon(sbPtr);
 
 
7097
 
 
 
7098
                    if(marineIsNear)
 
 
7099
                        CentreMarineElevation(sbPtr);
 
 
7100
 
 
 
7101
                    WanderMission_SwitchState(sbPtr, state_result);
 
 
7102
                }
 
 
7103
                break;
 
 
7104
                case MBS_Returning:
 
 
7105
                case MBS_Pathfinding:
 
 
7106
                {
 
 
7107
                    /* How the hell did you get here?!? */
 
 
7108
                    Marine_Enter_Wander_State(sbPtr);
 
 
7109
                }
 
 
7110
                break;
 
 
7111
                case MBS_AcidAvoidance:
 
 
7112
                {
 
 
7113
                    //printf("Wander marine acid avoidance in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7114
 
 
 
7115
                    if (marineIsNear)
 
 
7116
                    {
 
 
7117
                        state_result = Execute_MNS_AcidAvoidance(sbPtr);
 
 
7118
                        CentreMarineElevation(sbPtr);
 
 
7119
                        WanderMission_SwitchState(sbPtr, state_result);
 
 
7120
                    }
 
 
7121
                    else
 
 
7122
                    {
 
 
7123
                        Marine_Enter_Wait_State(sbPtr);
 
 
7124
                    }
 
 
7125
                }
 
 
7126
                break;
 
 
7127
                default:
 
 
7128
                {
 
 
7129
                    printf("Marine in unsupported state %d!\n",marineStatusPointer->behaviourState);
 
 
7130
                    assert(1==0);
 
 
7131
                }
 
 
7132
            }
 
 
7133
 
 
 
7134
            if (!marineIsNear)
 
 
7135
            {
 
 
7136
                /* check here to see if marine is in a proximity door - if so, trigger it to open. */
 
 
7137
                {
 
 
7138
                    MODULEDOORTYPE doorType = ModuleIsADoor(sbPtr->containingModule);
 
 
7139
 
 
 
7140
                    if(doorType == MDT_ProxDoor)    
 
 
7141
                        ((PROXDOOR_BEHAV_BLOCK *)sbPtr->containingModule->m_sbptr->dataptr)->marineTrigger = 1;
 
 
7142
                }
 
 
7143
 
 
 
7144
                /* lastly, do a containment test: to make sure that we are inside a module. */
 
 
7145
                #if DEBUG
 
 
7146
                {
 
 
7147
                    VECTORCH localCoords;
 
 
7148
                    MODULE *thisModule = sbPtr->containingModule;
 
 
7149
 
 
 
7150
                    assert(thisModule);
 
 
7151
 
 
 
7152
                    localCoords = sbPtr->DynPtr->Position;
 
 
7153
                    localCoords.vx -= thisModule->m_world.vx;
 
 
7154
                    localCoords.vy -= thisModule->m_world.vy;
 
 
7155
                    localCoords.vz -= thisModule->m_world.vz;
 
 
7156
 
 
 
7157
                    if(!PointIsInModule(thisModule, &localCoords))
 
 
7158
                    {
 
 
7159
                        printf("FAR MARINE MODULE CONTAINMENT FAILURE \n");
 
 
7160
                        assert(1==0);
 
 
7161
                    }  
 
 
7162
                }
 
 
7163
                #endif
 
 
7164
            }
 
 
7165
        }
 
 
7166
        break;
 
 
7167
        case MM_Guard:
 
 
7168
        {
 
 
7169
            STATE_RETURN_CONDITION state_result;
 
 
7170
 
 
 
7171
            /* Firstly, fix missionmodule. */
 
 
7172
 
 
 
7173
            if (marineStatusPointer->missionmodule == NULL)
 
 
7174
            {
 
 
7175
                marineStatusPointer->missionmodule = sbPtr->containingModule->m_aimodule;
 
 
7176
                marineStatusPointer->my_spot = sbPtr->DynPtr->Position;
 
 
7177
            }
 
 
7178
 
 
 
7179
            switch(marineStatusPointer->behaviourState)
 
 
7180
            {
 
 
7181
                case MBS_Approaching:
 
 
7182
                {
 
 
7183
                    //printf("Guard marine approaching in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7184
 
 
 
7185
                    assert(0);
 
 
7186
 
 
 
7187
                    if (marineIsNear)
 
 
7188
                    {
 
 
7189
                        state_result = Execute_MNS_Approach(sbPtr);
 
 
7190
                        CentreMarineElevation(sbPtr);
 
 
7191
                    }
 
 
7192
                    else
 
 
7193
                    {
 
 
7194
                        state_result = Execute_MFS_Wander(sbPtr);
 
 
7195
                    }
 
 
7196
 
 
 
7197
                    GuardMission_SwitchState(sbPtr,state_result);
 
 
7198
                }
 
 
7199
                break;
 
 
7200
                case MBS_Firing:
 
 
7201
                {
 
 
7202
                    //printf("Guard marine firing in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7203
 
 
 
7204
                    if (marineIsNear)
 
 
7205
                    {
 
 
7206
                        //state_result = (*marineStatusPointer->My_Weapon->WeaponFireFunction)(sbPtr);
 
 
7207
                        //SetMarineElevation(sbPtr);
 
 
7208
                    }
 
 
7209
                    else
 
 
7210
                    {
 
 
7211
                        //state_result = Execute_MFS_Firing(sbPtr);
 
 
7212
                    }
 
 
7213
 
 
 
7214
                    GuardMission_SwitchState(sbPtr,state_result);
 
 
7215
                }
 
 
7216
                break;
 
 
7217
                case MBS_PanicFire:
 
 
7218
                {
 
 
7219
                    //printf("Guard marine panic firing in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7220
 
 
 
7221
                    if (marineIsNear)
 
 
7222
                    {
 
 
7223
                        state_result = (*marineStatusPointer->My_Weapon->WeaponPanicFireFunction)(sbPtr);
 
 
7224
                        CentreMarineElevation(sbPtr);
 
 
7225
                    }
 
 
7226
                    else
 
 
7227
                    {
 
 
7228
                        state_result = Execute_MFS_Firing(sbPtr);
 
 
7229
                    }
 
 
7230
 
 
 
7231
                    GuardMission_SwitchState(sbPtr,state_result);
 
 
7232
                }
 
 
7233
                break;
 
 
7234
                case MBS_Avoidance:
 
 
7235
                {
 
 
7236
                    #if MARINE_PRINT_STATE
 
 
7237
                    {
 
 
7238
                        printf("Guard marine ");
 
 
7239
 
 
 
7240
                        switch (marineStatusPointer->avoidanceManager.substate)
 
 
7241
                        {
 
 
7242
                            default:
 
 
7243
                            case AvSS_FreeMovement:
 
 
7244
                                printf("Avoidance Level 0");
 
 
7245
                            break;
 
 
7246
                            case AvSS_FirstAvoidance:
 
 
7247
                                printf("Avoidance Level 1");
 
 
7248
                            break;
 
 
7249
                            case AvSS_SecondAvoidance:
 
 
7250
                                printf("Avoidance Level 2");
 
 
7251
                            break;
 
 
7252
                            case AvSS_ThirdAvoidance:
 
 
7253
                                printf("Avoidance Level 3");
 
 
7254
                        }    
 
 
7255
                        printf(" in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7256
                    }
 
 
7257
                    #endif
 
 
7258
 
 
 
7259
                    if (marineIsNear)
 
 
7260
                    {
 
 
7261
                        state_result = Execute_MNS_Avoidance(sbPtr);
 
 
7262
                        CentreMarineElevation(sbPtr);
 
 
7263
                    }
 
 
7264
                    else
 
 
7265
                    {
 
 
7266
                        state_result = Execute_MFS_Avoidance(sbPtr);
 
 
7267
                    }
 
 
7268
 
 
 
7269
                    GuardMission_SwitchState(sbPtr,state_result);
 
 
7270
                }
 
 
7271
                break;
 
 
7272
                case MBS_Wandering:
 
 
7273
                {
 
 
7274
                    //printf("Guard marine wandering in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7275
 
 
 
7276
                    if (marineIsNear)
 
 
7277
                    {
 
 
7278
                        state_result = Execute_MNS_Wander(sbPtr);
 
 
7279
                        CentreMarineElevation(sbPtr);
 
 
7280
                    }
 
 
7281
                    else
 
 
7282
                    {
 
 
7283
                        state_result = Execute_MFS_Wait(sbPtr);
 
 
7284
                    }
 
 
7285
 
 
 
7286
                    GuardMission_SwitchState(sbPtr,state_result);
 
 
7287
                }
 
 
7288
                break;
 
 
7289
                case MBS_Retreating:
 
 
7290
                {
 
 
7291
                    //printf("Guard marine retreating in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7292
 
 
 
7293
                    /* Real men never retreat! */
 
 
7294
                    if (marineIsNear)
 
 
7295
                    {
 
 
7296
                        state_result = Execute_MNS_Retreat(sbPtr);
 
 
7297
                        CentreMarineElevation(sbPtr);
 
 
7298
                    }
 
 
7299
                    else
 
 
7300
                    {
 
 
7301
                        state_result = Execute_MFS_Retreat(sbPtr);
 
 
7302
                    }
 
 
7303
 
 
 
7304
                    GuardMission_SwitchState(sbPtr,state_result);
 
 
7305
                }
 
 
7306
                break;
 
 
7307
                case MBS_Waiting:
 
 
7308
                {
 
 
7309
                    //printf("Guard marine waiting in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7310
 
 
 
7311
                    if (marineIsNear)
 
 
7312
                    {
 
 
7313
                        state_result = Execute_MNS_SentryMode(sbPtr);
 
 
7314
                        CentreMarineElevation(sbPtr);
 
 
7315
                    }
 
 
7316
                    else
 
 
7317
                    {
 
 
7318
                        state_result = Execute_MFS_SentryMode(sbPtr);
 
 
7319
                    }
 
 
7320
 
 
 
7321
                    state_result = SRC_Request_Wait; /* Go back to sentry. */
 
 
7322
 
 
 
7323
                    GuardMission_SwitchState(sbPtr,state_result);
 
 
7324
                }
 
 
7325
                break;
 
 
7326
                case MBS_Responding:
 
 
7327
                case MBS_Sentry:
 
 
7328
                {
 
 
7329
                    //printf("Guard marine sentry in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7330
 
 
 
7331
                    if (marineIsNear)
 
 
7332
                    {
 
 
7333
                        state_result = Execute_MNS_SentryMode(sbPtr);
 
 
7334
                        CentreMarineElevation(sbPtr);
 
 
7335
                    }
 
 
7336
                    else
 
 
7337
                    {
 
 
7338
                        state_result = Execute_MFS_SentryMode(sbPtr);
 
 
7339
                    }
 
 
7340
 
 
 
7341
                    GuardMission_SwitchState(sbPtr,state_result);
 
 
7342
                }
 
 
7343
                break;
 
 
7344
                case MBS_Taunting:
 
 
7345
                {
 
 
7346
                    //printf("Guard marine taunt in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7347
 
 
 
7348
                    state_result = Execute_MNS_Taunting(sbPtr);
 
 
7349
 
 
 
7350
                    if(marineIsNear)
 
 
7351
                        CentreMarineElevation(sbPtr);
 
 
7352
 
 
 
7353
                    GuardMission_SwitchState(sbPtr,state_result);
 
 
7354
                }
 
 
7355
                break;
 
 
7356
                case MBS_Reloading:
 
 
7357
                {
 
 
7358
                    //printf("Guard marine reloading in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7359
 
 
 
7360
                    state_result = Execute_MNS_Reloading(sbPtr);
 
 
7361
 
 
 
7362
                    if(marineIsNear)
 
 
7363
                        CentreMarineElevation(sbPtr);
 
 
7364
 
 
 
7365
                    GuardMission_SwitchState(sbPtr,state_result);
 
 
7366
                }
 
 
7367
                break;
 
 
7368
                case MBS_PanicReloading:
 
 
7369
                {
 
 
7370
                    //printf("Guard marine panic reloading in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7371
 
 
 
7372
                    state_result = Execute_MNS_PanicReloading(sbPtr);
 
 
7373
 
 
 
7374
                    if(marineIsNear)
 
 
7375
                        CentreMarineElevation(sbPtr);
 
 
7376
 
 
 
7377
                    GuardMission_SwitchState(sbPtr,state_result);
 
 
7378
                }
 
 
7379
                break;
 
 
7380
                case MBS_GetWeapon:
 
 
7381
                {
 
 
7382
                    //printf("Guard marine get weapon in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7383
 
 
 
7384
                    state_result = Execute_MNS_GetWeapon(sbPtr);
 
 
7385
 
 
 
7386
                    if(marineIsNear)
 
 
7387
                        CentreMarineElevation(sbPtr);
 
 
7388
 
 
 
7389
                    GuardMission_SwitchState(sbPtr,state_result);
 
 
7390
                }
 
 
7391
                break;
 
 
7392
                case MBS_Returning:
 
 
7393
                case MBS_Pathfinding:
 
 
7394
                {
 
 
7395
                    /* How the hell did you get here?!? */
 
 
7396
                    Marine_Enter_Wander_State(sbPtr);
 
 
7397
                }
 
 
7398
                break;
 
 
7399
                case MBS_AcidAvoidance:
 
 
7400
                {
 
 
7401
                    //printf("Guard marine acid avoidance in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7402
 
 
 
7403
                    if (marineIsNear)
 
 
7404
                    {
 
 
7405
                        state_result = Execute_MNS_AcidAvoidance(sbPtr);
 
 
7406
                        CentreMarineElevation(sbPtr);
 
 
7407
                    }
 
 
7408
                    else
 
 
7409
                    {
 
 
7410
                        Marine_Enter_Wait_State(sbPtr);
 
 
7411
                    break;
 
 
7412
                    }
 
 
7413
 
 
 
7414
                    GuardMission_SwitchState(sbPtr,state_result);
 
 
7415
                }
 
 
7416
                break;
 
 
7417
                default:
 
 
7418
                {
 
 
7419
                    printf("Guard marine in unsupported state %d!\n",marineStatusPointer->behaviourState);
 
 
7420
                    assert(1==0);
 
 
7421
                }
 
 
7422
            }
 
 
7423
 
 
 
7424
            if (!marineIsNear)
 
 
7425
            {    
 
 
7426
                /* check here to see if marine is in a proximity door - if so, trigger it to open. */
 
 
7427
                {
 
 
7428
                    MODULEDOORTYPE doorType = ModuleIsADoor(sbPtr->containingModule);
 
 
7429
 
 
 
7430
                    if(doorType == MDT_ProxDoor)    
 
 
7431
                        ((PROXDOOR_BEHAV_BLOCK *)sbPtr->containingModule->m_sbptr->dataptr)->marineTrigger = 1;
 
 
7432
                }
 
 
7433
 
 
 
7434
                /* lastly, do a containment test: to make sure that we are inside a module. */
 
 
7435
                #if DEBUG
 
 
7436
                {
 
 
7437
                    VECTORCH localCoords;
 
 
7438
                    MODULE *thisModule = sbPtr->containingModule;
 
 
7439
 
 
 
7440
                    assert(thisModule);
 
 
7441
 
 
 
7442
                    localCoords = sbPtr->DynPtr->Position;
 
 
7443
                    localCoords.vx -= thisModule->m_world.vx;
 
 
7444
                    localCoords.vy -= thisModule->m_world.vy;
 
 
7445
                    localCoords.vz -= thisModule->m_world.vz;
 
 
7446
 
 
 
7447
                    if(!PointIsInModule(thisModule, &localCoords))
 
 
7448
                    {
 
 
7449
                        printf("FAR MARINE MODULE CONTAINMENT FAILURE \n");
 
 
7450
                        assert(1==0);
 
 
7451
                    }
 
 
7452
                }
 
 
7453
                #endif
 
 
7454
            }
 
 
7455
        }
 
 
7456
        break;
 
 
7457
        case MM_LocalGuard:
 
 
7458
        {
 
 
7459
            STATE_RETURN_CONDITION state_result;
 
 
7460
 
 
 
7461
            /* Firstly, fix missionmodule. */
 
 
7462
 
 
 
7463
            if (marineStatusPointer->missionmodule == NULL)
 
 
7464
                marineStatusPointer->missionmodule = sbPtr->containingModule->m_aimodule;
 
 
7465
 
 
 
7466
            switch(marineStatusPointer->behaviourState)
 
 
7467
            {
 
 
7468
                case MBS_Approaching:
 
 
7469
                {
 
 
7470
                    //printf("Local Guard marine approaching in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7471
 
 
 
7472
                    if (marineIsNear)
 
 
7473
                    {
 
 
7474
                        state_result = Execute_MNS_Approach(sbPtr);
 
 
7475
                        CentreMarineElevation(sbPtr);
 
 
7476
                    }
 
 
7477
                    else
 
 
7478
                    {
 
 
7479
                        state_result = Execute_MFS_Wander(sbPtr);
 
 
7480
                    }
 
 
7481
 
 
 
7482
                    LocalGuardMission_SwitchState(sbPtr,state_result);
 
 
7483
                }
 
 
7484
                break;
 
 
7485
                case MBS_Firing:
 
 
7486
                {
 
 
7487
                    //printf("Local Guard marine firing in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7488
 
 
 
7489
                    if (marineIsNear)
 
 
7490
                    {
 
 
7491
                        //state_result = (*marineStatusPointer->My_Weapon->WeaponFireFunction)(sbPtr);
 
 
7492
                        //SetMarineElevation(sbPtr);
 
 
7493
                    }
 
 
7494
                    else
 
 
7495
                    {
 
 
7496
                        state_result = Execute_MFS_Firing(sbPtr);
 
 
7497
                    }
 
 
7498
 
 
 
7499
                    LocalGuardMission_SwitchState(sbPtr,state_result);
 
 
7500
                }
 
 
7501
                break;
 
 
7502
                case MBS_PanicFire:
 
 
7503
                {
 
 
7504
                    //printf("Local Guard marine panic firing in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7505
 
 
 
7506
                    if (marineIsNear)
 
 
7507
                    {
 
 
7508
                        state_result = (*marineStatusPointer->My_Weapon->WeaponPanicFireFunction)(sbPtr);
 
 
7509
                        CentreMarineElevation(sbPtr);
 
 
7510
                    }
 
 
7511
                    else
 
 
7512
                    {
 
 
7513
                        state_result = Execute_MFS_Firing(sbPtr);
 
 
7514
                    }
 
 
7515
 
 
 
7516
                    LocalGuardMission_SwitchState(sbPtr,state_result);
 
 
7517
                }
 
 
7518
                break;
 
 
7519
                case MBS_Avoidance:
 
 
7520
                {
 
 
7521
                    #if MARINE_PRINT_STATE
 
 
7522
                    {
 
 
7523
                        printf("Local Guard marine ");
 
 
7524
 
 
 
7525
                        switch (marineStatusPointer->avoidanceManager.substate)
 
 
7526
                        {
 
 
7527
                            default:
 
 
7528
                            case AvSS_FreeMovement:
 
 
7529
                                printf("Avoidance Level 0");
 
 
7530
                            break;
 
 
7531
                            case AvSS_FirstAvoidance:
 
 
7532
                                printf("Avoidance Level 1");
 
 
7533
                            break;
 
 
7534
                            case AvSS_SecondAvoidance:
 
 
7535
                                printf("Avoidance Level 2");
 
 
7536
                            break;
 
 
7537
                            case AvSS_ThirdAvoidance:
 
 
7538
                                printf("Avoidance Level 3");
 
 
7539
                        }    
 
 
7540
                        printf(" in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7541
                    }
 
 
7542
                    #endif
 
 
7543
 
 
 
7544
                    if (marineIsNear)
 
 
7545
                    {
 
 
7546
                        state_result = Execute_MNS_Avoidance(sbPtr);
 
 
7547
                        CentreMarineElevation(sbPtr);
 
 
7548
                    }
 
 
7549
                    else
 
 
7550
                    {
 
 
7551
                        state_result = Execute_MFS_Avoidance(sbPtr);
 
 
7552
                    }
 
 
7553
 
 
 
7554
                    LocalGuardMission_SwitchState(sbPtr,state_result);
 
 
7555
                }
 
 
7556
                break;
 
 
7557
                case MBS_Wandering:
 
 
7558
                {
 
 
7559
                    //printf("Local Guard marine wandering in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7560
 
 
 
7561
                    if (marineIsNear)
 
 
7562
                    {
 
 
7563
                        state_result = Execute_MNS_Wander(sbPtr);
 
 
7564
                        CentreMarineElevation(sbPtr);
 
 
7565
                    }
 
 
7566
                    else
 
 
7567
                    {
 
 
7568
                        state_result = Execute_MFS_Wait(sbPtr);
 
 
7569
                    }
 
 
7570
 
 
 
7571
                    LocalGuardMission_SwitchState(sbPtr,state_result);
 
 
7572
                }
 
 
7573
                break;
 
 
7574
                case MBS_Retreating:
 
 
7575
                {
 
 
7576
                    //printf("Local Guard marine retreating in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7577
 
 
 
7578
                    /* Real men never retreat! */
 
 
7579
                    if (marineIsNear)
 
 
7580
                    {
 
 
7581
                        state_result = Execute_MNS_Retreat(sbPtr);
 
 
7582
                        CentreMarineElevation(sbPtr);
 
 
7583
                    }
 
 
7584
                    else
 
 
7585
                    {
 
 
7586
                        state_result = Execute_MFS_Retreat(sbPtr);
 
 
7587
                    }
 
 
7588
 
 
 
7589
                    LocalGuardMission_SwitchState(sbPtr,state_result);
 
 
7590
                }
 
 
7591
                break;
 
 
7592
                case MBS_Waiting:
 
 
7593
                {
 
 
7594
                    //printf("Local Guard marine waiting in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7595
 
 
 
7596
                    if (marineIsNear)
 
 
7597
                    {
 
 
7598
                        state_result = Execute_MNS_Wait(sbPtr);
 
 
7599
                        CentreMarineElevation(sbPtr);
 
 
7600
                    }
 
 
7601
                    else
 
 
7602
                    {
 
 
7603
                        state_result = Execute_MFS_Wait(sbPtr);
 
 
7604
                    }
 
 
7605
 
 
 
7606
                    LocalGuardMission_SwitchState(sbPtr,state_result);
 
 
7607
                }
 
 
7608
                break;
 
 
7609
                case MBS_Responding:
 
 
7610
                {
 
 
7611
                    /* Well, it *might* happen... */
 
 
7612
                    //printf("Local Guard marine responding in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7613
 
 
 
7614
                    if (marineIsNear)
 
 
7615
                    {
 
 
7616
                        state_result = Execute_MNS_Respond(sbPtr);
 
 
7617
                        CentreMarineElevation(sbPtr);
 
 
7618
                    }
 
 
7619
                    else
 
 
7620
                    {
 
 
7621
                        state_result = Execute_MFS_Respond(sbPtr);
 
 
7622
                    }
 
 
7623
 
 
 
7624
                    LocalGuardMission_SwitchState(sbPtr,state_result);
 
 
7625
                }
 
 
7626
                break;
 
 
7627
                case MBS_Returning:
 
 
7628
                {
 
 
7629
                    //printf("Local Guard marine returning in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7630
 
 
 
7631
                    if (marineIsNear)
 
 
7632
                    {
 
 
7633
                        state_result = Execute_MNS_Return(sbPtr);
 
 
7634
                        CentreMarineElevation(sbPtr);
 
 
7635
                    }
 
 
7636
                    else
 
 
7637
                    {
 
 
7638
                        state_result = Execute_MFS_Return(sbPtr);
 
 
7639
                    }
 
 
7640
 
 
 
7641
                    LocalGuardMission_SwitchState(sbPtr,state_result);
 
 
7642
                }
 
 
7643
                break;
 
 
7644
                case MBS_Sentry:
 
 
7645
                {
 
 
7646
                    // printf("Local Guard marine sentry in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7647
 
 
 
7648
                    if (marineIsNear)
 
 
7649
                    {
 
 
7650
                        state_result = Execute_MNS_SentryMode(sbPtr);
 
 
7651
                        CentreMarineElevation(sbPtr);
 
 
7652
                    }
 
 
7653
                    else
 
 
7654
                    {
 
 
7655
                        state_result = Execute_MFS_Wait(sbPtr);
 
 
7656
                    }
 
 
7657
 
 
 
7658
                    LocalGuardMission_SwitchState(sbPtr,state_result);
 
 
7659
                }
 
 
7660
                break;
 
 
7661
                case MBS_Taunting:
 
 
7662
                {
 
 
7663
                    //printf("Local Guard marine taunt in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7664
 
 
 
7665
                    state_result = Execute_MNS_Taunting(sbPtr);
 
 
7666
 
 
 
7667
                    if(marineIsNear)
 
 
7668
                        CentreMarineElevation(sbPtr);
 
 
7669
 
 
 
7670
                    LocalGuardMission_SwitchState(sbPtr,state_result);
 
 
7671
                }
 
 
7672
                break;
 
 
7673
                case MBS_Reloading:
 
 
7674
                {
 
 
7675
                    // printf("Local Guard marine reloading in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7676
 
 
 
7677
                    state_result = Execute_MNS_Reloading(sbPtr);
 
 
7678
 
 
 
7679
                    if(marineIsNear)
 
 
7680
                        CentreMarineElevation(sbPtr);
 
 
7681
 
 
 
7682
                    LocalGuardMission_SwitchState(sbPtr,state_result);
 
 
7683
                }
 
 
7684
                break;
 
 
7685
                case MBS_PanicReloading:
 
 
7686
                {
 
 
7687
                    // printf("Local Guard marine panic reloading in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7688
 
 
 
7689
                    state_result = Execute_MNS_PanicReloading(sbPtr);
 
 
7690
 
 
 
7691
                    if(marineIsNear)
 
 
7692
                        CentreMarineElevation(sbPtr);
 
 
7693
 
 
 
7694
                    LocalGuardMission_SwitchState(sbPtr,state_result);
 
 
7695
                }
 
 
7696
                break;
 
 
7697
                case MBS_GetWeapon:
 
 
7698
                {
 
 
7699
                    //printf("Local Guard marine get weapon in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7700
 
 
 
7701
                    state_result = Execute_MNS_GetWeapon(sbPtr);
 
 
7702
 
 
 
7703
                    if(marineIsNear)
 
 
7704
                        CentreMarineElevation(sbPtr);
 
 
7705
 
 
 
7706
                    LocalGuardMission_SwitchState(sbPtr,state_result);
 
 
7707
                }
 
 
7708
                break;
 
 
7709
                case MBS_Pathfinding:
 
 
7710
                {
 
 
7711
                    /* How the hell did you get here?!? */
 
 
7712
                    Marine_Enter_Return_State(sbPtr);
 
 
7713
                }
 
 
7714
                break;
 
 
7715
                case MBS_AcidAvoidance:
 
 
7716
                {
 
 
7717
                    // printf("Local Guard marine acid avoidance in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7718
 
 
 
7719
                    if (marineIsNear)
 
 
7720
                    {
 
 
7721
                        state_result = Execute_MNS_AcidAvoidance(sbPtr);
 
 
7722
                        CentreMarineElevation(sbPtr);
 
 
7723
                    }
 
 
7724
                    else
 
 
7725
                    {
 
 
7726
                        Marine_Enter_Wait_State(sbPtr);
 
 
7727
                        break;
 
 
7728
                    }
 
 
7729
 
 
 
7730
                    LocalGuardMission_SwitchState(sbPtr,state_result);
 
 
7731
                }
 
 
7732
                break;
 
 
7733
                default:
 
 
7734
                {
 
 
7735
                    printf("Local Guard marine in unsupported state %d!\n",marineStatusPointer->behaviourState);
 
 
7736
                    assert(1 == 0);
 
 
7737
                }
 
 
7738
            }
 
 
7739
 
 
 
7740
            if (!marineIsNear)
 
 
7741
            {    
 
 
7742
                /* check here to see if marine is in a proximity door - if so, trigger it to open. */
 
 
7743
                {
 
 
7744
                    MODULEDOORTYPE doorType = ModuleIsADoor(sbPtr->containingModule);
 
 
7745
 
 
 
7746
                    if(doorType == MDT_ProxDoor)    
 
 
7747
                        ((PROXDOOR_BEHAV_BLOCK *)sbPtr->containingModule->m_sbptr->dataptr)->marineTrigger = 1;
 
 
7748
                }
 
 
7749
 
 
 
7750
                /* lastly, do a containment test: to make sure that we are inside a module. */
 
 
7751
                #if DEBUG
 
 
7752
                {
 
 
7753
                    VECTORCH localCoords;
 
 
7754
                    MODULE *thisModule = sbPtr->containingModule;
 
 
7755
 
 
 
7756
                    assert(thisModule);
 
 
7757
 
 
 
7758
                    localCoords = sbPtr->DynPtr->Position;
 
 
7759
                    localCoords.vx -= thisModule->m_world.vx;
 
 
7760
                    localCoords.vy -= thisModule->m_world.vy;
 
 
7761
                    localCoords.vz -= thisModule->m_world.vz;
 
 
7762
 
 
 
7763
                    if(!PointIsInModule(thisModule, &localCoords))
 
 
7764
                    {
 
 
7765
                        printf("FAR MARINE MODULE CONTAINMENT FAILURE \n");
 
 
7766
                        assert(1==0);
 
 
7767
                    } 
 
 
7768
                }
 
 
7769
                #endif
 
 
7770
            }
 
 
7771
        }
 
 
7772
        break;
 
 
7773
        case MM_NonCom:
 
 
7774
        {
 
 
7775
            STATE_RETURN_CONDITION state_result;
 
 
7776
 
 
 
7777
            /* Fleeing Behaviour. */
 
 
7778
 
 
 
7779
            switch(marineStatusPointer->behaviourState)
 
 
7780
            {
 
 
7781
                case MBS_Approaching:
 
 
7782
                {
 
 
7783
                    // printf("Noncombatant approaching in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7784
 
 
 
7785
                    if (marineIsNear)
 
 
7786
                    {
 
 
7787
                        state_result = Execute_MNS_Approach(sbPtr);
 
 
7788
                        CentreMarineElevation(sbPtr);
 
 
7789
                    }
 
 
7790
                    else
 
 
7791
                    {
 
 
7792
                        state_result = Execute_MFS_Wait(sbPtr);
 
 
7793
                    }
 
 
7794
 
 
 
7795
                    LoiterMission_SwitchState(sbPtr,state_result);
 
 
7796
                }
 
 
7797
                break;
 
 
7798
                case MBS_Firing:
 
 
7799
                {
 
 
7800
                    //printf("Noncombatant firing in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7801
 
 
 
7802
                    if (marineIsNear)
 
 
7803
                    {
 
 
7804
                        assert(0);
 
 
7805
                        //state_result = (*marineStatusPointer->My_Weapon->WeaponFireFunction)(sbPtr);
 
 
7806
                        //SetMarineElevation(sbPtr);
 
 
7807
                    }
 
 
7808
                    else
 
 
7809
                    {
 
 
7810
                        state_result = Execute_MFS_Firing(sbPtr);
 
 
7811
                    }
 
 
7812
 
 
 
7813
                    LoiterMission_SwitchState(sbPtr,state_result);
 
 
7814
                }
 
 
7815
                break;
 
 
7816
                case MBS_PanicFire:
 
 
7817
                {
 
 
7818
                    //printf("Noncombatant panic firing in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7819
 
 
 
7820
                    if (marineIsNear)
 
 
7821
                    {
 
 
7822
                        state_result = (*marineStatusPointer->My_Weapon->WeaponPanicFireFunction)(sbPtr);
 
 
7823
                        CentreMarineElevation(sbPtr);
 
 
7824
                    }
 
 
7825
                    else
 
 
7826
                    {
 
 
7827
                        state_result = Execute_MFS_Firing(sbPtr);
 
 
7828
                    }
 
 
7829
 
 
 
7830
                    LoiterMission_SwitchState(sbPtr,state_result);
 
 
7831
                }
 
 
7832
                break;
 
 
7833
                case MBS_Avoidance:
 
 
7834
                {
 
 
7835
                    #if MARINE_PRINT_STATE
 
 
7836
                    {
 
 
7837
                        printf("Noncombatant ");
 
 
7838
 
 
 
7839
                        switch (marineStatusPointer->avoidanceManager.substate)
 
 
7840
                        {
 
 
7841
                            default:
 
 
7842
                            case AvSS_FreeMovement:
 
 
7843
                                printf("Avoidance Level 0");
 
 
7844
                            break;
 
 
7845
                            case AvSS_FirstAvoidance:
 
 
7846
                                printf("Avoidance Level 1");
 
 
7847
                            break;
 
 
7848
                            case AvSS_SecondAvoidance:
 
 
7849
                                printf("Avoidance Level 2");
 
 
7850
                            break;
 
 
7851
                            case AvSS_ThirdAvoidance:
 
 
7852
                                printf("Avoidance Level 3");
 
 
7853
                        }    
 
 
7854
                        printf(" in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7855
                    }
 
 
7856
                    #endif
 
 
7857
 
 
 
7858
                    if (marineIsNear)
 
 
7859
                    {
 
 
7860
                        state_result = Execute_MNS_Avoidance(sbPtr);
 
 
7861
                        CentreMarineElevation(sbPtr);
 
 
7862
                    }
 
 
7863
                    else
 
 
7864
                    {
 
 
7865
                        state_result = Execute_MFS_Avoidance(sbPtr);
 
 
7866
                    }
 
 
7867
 
 
 
7868
                    LoiterMission_SwitchState(sbPtr,state_result);
 
 
7869
                }
 
 
7870
                break;
 
 
7871
                case MBS_Responding:
 
 
7872
                case MBS_Wandering:
 
 
7873
                {
 
 
7874
                    // printf("Noncombatant wandering in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7875
 
 
 
7876
                    if (marineIsNear)
 
 
7877
                    {
 
 
7878
                        state_result = Execute_MNS_Wander(sbPtr);
 
 
7879
                        CentreMarineElevation(sbPtr);
 
 
7880
                    }
 
 
7881
                    else
 
 
7882
                    {
 
 
7883
                        state_result = Execute_MFS_Wander(sbPtr);
 
 
7884
                    }
 
 
7885
 
 
 
7886
                    LoiterMission_SwitchState(sbPtr,state_result);
 
 
7887
                }
 
 
7888
                break;
 
 
7889
                case MBS_Retreating:
 
 
7890
                {
 
 
7891
                    //printf("Noncombatant retreating in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7892
 
 
 
7893
                    /* Wusses, now: they retreat. */
 
 
7894
                    if (marineIsNear)
 
 
7895
                    {
 
 
7896
                        state_result = Execute_MNS_Retreat(sbPtr);
 
 
7897
                        CentreMarineElevation(sbPtr);
 
 
7898
                    }
 
 
7899
                    else
 
 
7900
                    {
 
 
7901
                        state_result = Execute_MFS_Retreat(sbPtr);
 
 
7902
                    }
 
 
7903
 
 
 
7904
                    LoiterMission_SwitchState(sbPtr,state_result);
 
 
7905
                }
 
 
7906
                break;
 
 
7907
                case MBS_Waiting:
 
 
7908
                {
 
 
7909
                    //printf("Noncombatant waiting in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7910
 
 
 
7911
                    if (marineIsNear)
 
 
7912
                    {
 
 
7913
                        state_result = Execute_MNS_Wait(sbPtr);
 
 
7914
                        CentreMarineElevation(sbPtr);
 
 
7915
                    }
 
 
7916
                    else
 
 
7917
                    {
 
 
7918
                        state_result = Execute_MFS_Wait(sbPtr);
 
 
7919
                    }
 
 
7920
 
 
 
7921
                    LoiterMission_SwitchState(sbPtr,state_result);
 
 
7922
                }
 
 
7923
                break;
 
 
7924
                case MBS_Sentry:
 
 
7925
                {
 
 
7926
                    assert(0);
 
 
7927
 
 
 
7928
                    //printf("Noncombatant sentry in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7929
 
 
 
7930
                    if (marineIsNear)
 
 
7931
                    {
 
 
7932
                        state_result = Execute_MNS_SentryMode(sbPtr);
 
 
7933
                        CentreMarineElevation(sbPtr);
 
 
7934
                    }
 
 
7935
                    else
 
 
7936
                    {
 
 
7937
                        state_result = Execute_MFS_Wait(sbPtr);
 
 
7938
                    }
 
 
7939
 
 
 
7940
                    LoiterMission_SwitchState(sbPtr,state_result);
 
 
7941
                }
 
 
7942
                break;
 
 
7943
                case MBS_Reloading:
 
 
7944
                {
 
 
7945
                    //printf("Noncombatant reloading in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7946
 
 
 
7947
                    state_result = Execute_MNS_Reloading(sbPtr);
 
 
7948
 
 
 
7949
                    if(marineIsNear)
 
 
7950
                        CentreMarineElevation(sbPtr);
 
 
7951
 
 
 
7952
                    LoiterMission_SwitchState(sbPtr,state_result);
 
 
7953
                }
 
 
7954
                break;
 
 
7955
                case MBS_PanicReloading:
 
 
7956
                {
 
 
7957
                    //printf("Noncombatant panic reloading in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7958
 
 
 
7959
                    if(marineIsNear)
 
 
7960
                    {
 
 
7961
                        state_result = Execute_MNS_PanicReloading(sbPtr);
 
 
7962
                        CentreMarineElevation(sbPtr);
 
 
7963
                    }
 
 
7964
                    else
 
 
7965
                    {
 
 
7966
                        state_result = Execute_MNS_PanicReloading(sbPtr);
 
 
7967
                    }
 
 
7968
 
 
 
7969
                    LoiterMission_SwitchState(sbPtr,state_result);
 
 
7970
                }
 
 
7971
                break;
 
 
7972
                case MBS_Returning:
 
 
7973
                case MBS_Pathfinding:
 
 
7974
                {
 
 
7975
                    /* How the hell did you get here?!? */
 
 
7976
                    Marine_Enter_Wander_State(sbPtr);
 
 
7977
                }
 
 
7978
                break;
 
 
7979
                case MBS_AcidAvoidance:
 
 
7980
                {
 
 
7981
                    //printf("Noncombatant acid avoidance in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
7982
 
 
 
7983
                    if (marineIsNear)
 
 
7984
                    {
 
 
7985
                        state_result = Execute_MNS_AcidAvoidance(sbPtr);
 
 
7986
                        CentreMarineElevation(sbPtr);
 
 
7987
                    }
 
 
7988
                    else
 
 
7989
                    {
 
 
7990
                        Marine_Enter_Wait_State(sbPtr);
 
 
7991
                        break;
 
 
7992
                    }
 
 
7993
 
 
 
7994
                    LoiterMission_SwitchState(sbPtr,state_result);
 
 
7995
                }
 
 
7996
                break;
 
 
7997
                default:
 
 
7998
                {
 
 
7999
                    /* NonComs can't taunt. */
 
 
8000
                    printf("Marine in unsupported state %d!\n",marineStatusPointer->behaviourState);
 
 
8001
                    assert(1==0);
 
 
8002
                }
 
 
8003
            }
 
 
8004
 
 
 
8005
            if (!marineIsNear)
 
 
8006
            {    
 
 
8007
                /* check here to see if marine is in a proximity door - if so, trigger it to open. */
 
 
8008
                {
 
 
8009
                    MODULEDOORTYPE doorType = ModuleIsADoor(sbPtr->containingModule);
 
 
8010
 
 
 
8011
                    if(doorType == MDT_ProxDoor)    
 
 
8012
                        ((PROXDOOR_BEHAV_BLOCK *)sbPtr->containingModule->m_sbptr->dataptr)->marineTrigger = 1;
 
 
8013
                }
 
 
8014
 
 
 
8015
                /* lastly, do a containment test: to make sure that we are inside a module. */
 
 
8016
                #if DEBUG
 
 
8017
                {
 
 
8018
                    VECTORCH localCoords;
 
 
8019
                    MODULE *thisModule = sbPtr->containingModule;
 
 
8020
 
 
 
8021
                    assert(thisModule);
 
 
8022
 
 
 
8023
                    localCoords = sbPtr->DynPtr->Position;
 
 
8024
                    localCoords.vx -= thisModule->m_world.vx;
 
 
8025
                    localCoords.vy -= thisModule->m_world.vy;
 
 
8026
                    localCoords.vz -= thisModule->m_world.vz;
 
 
8027
 
 
 
8028
                    if(!PointIsInModule(thisModule, &localCoords))
 
 
8029
                    {
 
 
8030
                        printf("FAR MARINE MODULE CONTAINMENT FAILURE \n");
 
 
8031
                        assert(1==0);
 
 
8032
                    }
 
 
8033
                }
 
 
8034
                #endif
 
 
8035
            }
 
 
8036
        }
 
 
8037
        break;
 
 
8038
        case MM_Pathfinder:
 
 
8039
        {
 
 
8040
            STATE_RETURN_CONDITION state_result;
 
 
8041
 
 
 
8042
            switch(marineStatusPointer->behaviourState)
 
 
8043
            {
 
 
8044
                case MBS_Approaching:
 
 
8045
                {
 
 
8046
                    // printf("Pathfinder marine approach in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
8047
 
 
 
8048
                    if(marineIsNear)
 
 
8049
                    {
 
 
8050
                        state_result = Execute_MNS_Approach(sbPtr);
 
 
8051
                        CentreMarineElevation(sbPtr);
 
 
8052
                    }
 
 
8053
                    else
 
 
8054
                    {
 
 
8055
                        state_result = Execute_MFS_Approach(sbPtr);
 
 
8056
                    }
 
 
8057
 
 
 
8058
                    PathfinderMission_SwitchState(sbPtr,state_result);
 
 
8059
                }
 
 
8060
                break;
 
 
8061
                case MBS_Firing:
 
 
8062
                {
 
 
8063
                    //printf("Pathfinder marine firing in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
8064
 
 
 
8065
                    if (marineIsNear)
 
 
8066
                    {
 
 
8067
                        //state_result = (*marineStatusPointer->My_Weapon->WeaponFireFunction)(sbPtr);
 
 
8068
                        //SetMarineElevation(sbPtr);
 
 
8069
                    }
 
 
8070
                    else
 
 
8071
                    {
 
 
8072
                        state_result = Execute_MFS_Firing(sbPtr);
 
 
8073
                    }
 
 
8074
 
 
 
8075
                    PathfinderMission_SwitchState(sbPtr,state_result);
 
 
8076
                }
 
 
8077
                break;
 
 
8078
                case MBS_PanicFire:
 
 
8079
                {
 
 
8080
                    //printf("Pathfinder marine panic firing in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
8081
 
 
 
8082
                    if (marineIsNear)
 
 
8083
                    {
 
 
8084
                        state_result = (*marineStatusPointer->My_Weapon->WeaponPanicFireFunction)(sbPtr);
 
 
8085
                        CentreMarineElevation(sbPtr);
 
 
8086
                    }
 
 
8087
                    else
 
 
8088
                    {
 
 
8089
                        state_result = Execute_MFS_Firing(sbPtr);
 
 
8090
                    }
 
 
8091
 
 
 
8092
                    PathfinderMission_SwitchState(sbPtr,state_result);
 
 
8093
                }
 
 
8094
                break;
 
 
8095
                case MBS_Avoidance:
 
 
8096
                {
 
 
8097
                    #if MARINE_PRINT_STATE
 
 
8098
                    {
 
 
8099
                        printf("Pathfinder marine ");
 
 
8100
 
 
 
8101
                        switch (marineStatusPointer->avoidanceManager.substate)
 
 
8102
                        {
 
 
8103
                            default:
 
 
8104
                            case AvSS_FreeMovement:
 
 
8105
                                printf("Avoidance Level 0");
 
 
8106
                            break;
 
 
8107
                            case AvSS_FirstAvoidance:
 
 
8108
                                printf("Avoidance Level 1");
 
 
8109
                            break;
 
 
8110
                            case AvSS_SecondAvoidance:
 
 
8111
                                printf("Avoidance Level 2");
 
 
8112
                            break;
 
 
8113
                            case AvSS_ThirdAvoidance:
 
 
8114
                                printf("Avoidance Level 3");
 
 
8115
                        }    
 
 
8116
 
 
 
8117
                        printf(" in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
8118
                    }
 
 
8119
                    #endif
 
 
8120
 
 
 
8121
                    if(marineIsNear)
 
 
8122
                    {
 
 
8123
                        state_result = Execute_MNS_Avoidance(sbPtr);
 
 
8124
                        CentreMarineElevation(sbPtr);
 
 
8125
                    }
 
 
8126
                    else
 
 
8127
                    {
 
 
8128
                        state_result = Execute_MFS_Avoidance(sbPtr);
 
 
8129
                    }
 
 
8130
 
 
 
8131
                    PathfinderMission_SwitchState(sbPtr,state_result);
 
 
8132
                }
 
 
8133
                break;
 
 
8134
                case MBS_Wandering:
 
 
8135
                {
 
 
8136
                    //printf("Pathfinder marine wander in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
8137
 
 
 
8138
                    if (marineIsNear)
 
 
8139
                    {
 
 
8140
                        state_result = Execute_MNS_Wander(sbPtr);
 
 
8141
                        CentreMarineElevation(sbPtr);
 
 
8142
                    }
 
 
8143
                    else
 
 
8144
                    {
 
 
8145
                        state_result = Execute_MFS_Wander(sbPtr);
 
 
8146
                    }
 
 
8147
 
 
 
8148
                    PathfinderMission_SwitchState(sbPtr,state_result);
 
 
8149
                }
 
 
8150
                break;
 
 
8151
                case MBS_Responding:
 
 
8152
                {
 
 
8153
                    //printf("Pathfinder marine responding in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
8154
 
 
 
8155
                    if (marineIsNear)
 
 
8156
                    {
 
 
8157
                        state_result = Execute_MNS_Respond(sbPtr);
 
 
8158
                        CentreMarineElevation(sbPtr);
 
 
8159
                    }
 
 
8160
                    else
 
 
8161
                    {
 
 
8162
                        state_result = Execute_MFS_Respond(sbPtr);
 
 
8163
                    }
 
 
8164
 
 
 
8165
                    PathfinderMission_SwitchState(sbPtr,state_result);
 
 
8166
                }
 
 
8167
                break;
 
 
8168
                case MBS_Retreating:
 
 
8169
                {
 
 
8170
                    //printf("Pathfinder marine retreating in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
8171
 
 
 
8172
                    if (marineIsNear)
 
 
8173
                    {
 
 
8174
                        state_result = Execute_MNS_Retreat(sbPtr);
 
 
8175
                        CentreMarineElevation(sbPtr);
 
 
8176
                    }
 
 
8177
                    else
 
 
8178
                    {
 
 
8179
                        state_result = Execute_MFS_Retreat(sbPtr);
 
 
8180
                    }
 
 
8181
 
 
 
8182
                    PathfinderMission_SwitchState(sbPtr,state_result);
 
 
8183
                }
 
 
8184
                break;
 
 
8185
                case MBS_Waiting:
 
 
8186
                {
 
 
8187
                    //printf("Pathfinder marine wait in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
8188
 
 
 
8189
                    if (marineIsNear)
 
 
8190
                    {
 
 
8191
                        state_result = Execute_MNS_Wait(sbPtr);
 
 
8192
                        CentreMarineElevation(sbPtr);
 
 
8193
                    }
 
 
8194
                    else
 
 
8195
                    {
 
 
8196
                        state_result = Execute_MFS_Wait(sbPtr);
 
 
8197
                    }
 
 
8198
 
 
 
8199
                    PathfinderMission_SwitchState(sbPtr,state_result);
 
 
8200
                }
 
 
8201
                break;
 
 
8202
                case MBS_Sentry:
 
 
8203
                {
 
 
8204
                    //printf("Pathfinder marine sentry in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
8205
 
 
 
8206
                    assert(0);
 
 
8207
 
 
 
8208
                    if(marineIsNear)
 
 
8209
                    {
 
 
8210
                        state_result = Execute_MNS_SentryMode(sbPtr);
 
 
8211
                        CentreMarineElevation(sbPtr);
 
 
8212
                    }
 
 
8213
                    else
 
 
8214
                    {
 
 
8215
                        state_result = Execute_MFS_Wait(sbPtr);
 
 
8216
                    }
 
 
8217
 
 
 
8218
                    PathfinderMission_SwitchState(sbPtr,state_result);
 
 
8219
                }
 
 
8220
                break;
 
 
8221
                case MBS_Pathfinding:
 
 
8222
                {
 
 
8223
                    //printf("Pathfinder marine pathfinding in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
8224
 
 
 
8225
                    if (marineIsNear)
 
 
8226
                    {
 
 
8227
                        state_result = Execute_MNS_Pathfinder(sbPtr);
 
 
8228
                        CentreMarineElevation(sbPtr);
 
 
8229
                    }
 
 
8230
                    else
 
 
8231
                    {
 
 
8232
                        state_result = Execute_MFS_Pathfinder(sbPtr);
 
 
8233
                    }
 
 
8234
 
 
 
8235
                    PathfinderMission_SwitchState(sbPtr,state_result);
 
 
8236
                }
 
 
8237
                break;
 
 
8238
                case MBS_Taunting:
 
 
8239
                {
 
 
8240
                    //printf("Pathfinder marine taunt in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
8241
 
 
 
8242
                    state_result = Execute_MNS_Taunting(sbPtr);
 
 
8243
 
 
 
8244
                    if(marineIsNear)
 
 
8245
                        CentreMarineElevation(sbPtr);
 
 
8246
 
 
 
8247
                    PathfinderMission_SwitchState(sbPtr,state_result);
 
 
8248
                }
 
 
8249
                break;
 
 
8250
                case MBS_Returning:
 
 
8251
                {
 
 
8252
                    //printf("Pathfinder marine returning in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
8253
 
 
 
8254
                    if (marineIsNear)
 
 
8255
                    {
 
 
8256
                        state_result = Execute_MNS_Return(sbPtr);
 
 
8257
                        CentreMarineElevation(sbPtr);
 
 
8258
                    }
 
 
8259
                    else
 
 
8260
                    {
 
 
8261
                        state_result = Execute_MFS_Return(sbPtr);
 
 
8262
                    }
 
 
8263
 
 
 
8264
                    PathfinderMission_SwitchState(sbPtr,state_result);
 
 
8265
                }
 
 
8266
                break;
 
 
8267
                case MBS_Reloading:
 
 
8268
                {
 
 
8269
                    //printf("Pathfinder marine reloading in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
8270
 
 
 
8271
                    state_result = Execute_MNS_Reloading(sbPtr);
 
 
8272
 
 
 
8273
                    if(marineIsNear)
 
 
8274
                        CentreMarineElevation(sbPtr);
 
 
8275
 
 
 
8276
                    PathfinderMission_SwitchState(sbPtr,state_result);
 
 
8277
                }
 
 
8278
                break;
 
 
8279
                case MBS_PanicReloading:
 
 
8280
                {
 
 
8281
                    //printf("Pathfinder marine panic reloading in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
8282
 
 
 
8283
                    state_result = Execute_MNS_PanicReloading(sbPtr);
 
 
8284
 
 
 
8285
                    if(marineIsNear)
 
 
8286
                        CentreMarineElevation(sbPtr);
 
 
8287
 
 
 
8288
                    PathfinderMission_SwitchState(sbPtr,state_result);
 
 
8289
                }
 
 
8290
                break;
 
 
8291
                case MBS_GetWeapon:
 
 
8292
                {
 
 
8293
                    //printf("Pathfinder marine get weapon in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
8294
 
 
 
8295
                    if(marineIsNear)
 
 
8296
                    {
 
 
8297
                        state_result = Execute_MNS_GetWeapon(sbPtr);
 
 
8298
                        CentreMarineElevation(sbPtr);
 
 
8299
                    }
 
 
8300
                    else
 
 
8301
                    {
 
 
8302
                        state_result = Execute_MNS_GetWeapon(sbPtr);
 
 
8303
                    }
 
 
8304
 
 
 
8305
                    PathfinderMission_SwitchState(sbPtr,state_result);
 
 
8306
                }
 
 
8307
                break;
 
 
8308
                case MBS_AcidAvoidance:
 
 
8309
                {
 
 
8310
                    //printf("Prahfinder marine acid avoidance in %s: %d\n",sbPtr->containingModule->name,marineStatusPointer->Courage);
 
 
8311
 
 
 
8312
                    if (marineIsNear)
 
 
8313
                    {
 
 
8314
                        state_result = Execute_MNS_AcidAvoidance(sbPtr);
 
 
8315
                        CentreMarineElevation(sbPtr);
 
 
8316
                    }
 
 
8317
                    else
 
 
8318
                    {
 
 
8319
                        Marine_Enter_Wait_State(sbPtr);
 
 
8320
                        break;
 
 
8321
                    }
 
 
8322
 
 
 
8323
                    PathfinderMission_SwitchState(sbPtr,state_result);
 
 
8324
                }
 
 
8325
                break;
 
 
8326
                default:
 
 
8327
                {
 
 
8328
                    printf("Marine in unsupported state %d!\n",marineStatusPointer->behaviourState);
 
 
8329
                    assert(1==0);
 
 
8330
                }
 
 
8331
            }
 
 
8332
 
 
 
8333
            if (!marineIsNear)
 
 
8334
            {
 
 
8335
                /* check here to see if marine is in a proximity door - if so, trigger it to open. */
 
 
8336
                {
 
 
8337
                    MODULEDOORTYPE doorType = ModuleIsADoor(sbPtr->containingModule);
 
 
8338
 
 
 
8339
                    if(doorType == MDT_ProxDoor)    
 
 
8340
                        ((PROXDOOR_BEHAV_BLOCK *)sbPtr->containingModule->m_sbptr->dataptr)->marineTrigger = 1;
 
 
8341
                }
 
 
8342
 
 
 
8343
                /* lastly, do a containment test: to make sure that we are inside a module. */
 
 
8344
                #if DEBUG
 
 
8345
                {
 
 
8346
                    VECTORCH localCoords;
 
 
8347
                    MODULE *thisModule = sbPtr->containingModule;
 
 
8348
 
 
 
8349
                    assert(thisModule);
 
 
8350
 
 
 
8351
                    localCoords = sbPtr->DynPtr->Position;
 
 
8352
                    localCoords.vx -= thisModule->m_world.vx;
 
 
8353
                    localCoords.vy -= thisModule->m_world.vy;
 
 
8354
                    localCoords.vz -= thisModule->m_world.vz;
 
 
8355
 
 
 
8356
                    if(!PointIsInModule(thisModule, &localCoords))
 
 
8357
                    {
 
 
8358
                        printf("FAR MARINE MODULE CONTAINMENT FAILURE \n");
 
 
8359
                        assert(1==0);
 
 
8360
                    } 
 
 
8361
                }
 
 
8362
                #endif
 
 
8363
            }
 
 
8364
        }
 
 
8365
        break;
 
 
8366
        default:
 
 
8367
        {
 
 
8368
            assert(0);
 
 
8369
            break;
 
 
8370
        }
 
 
8371
    }
 
 
8372
 
 
 
8373
    if (CHEATMODE_TERROR == UserProfile.active_bonus)
 
 
8374
    {
 
 
8375
        switch(marineStatusPointer->behaviourState)
 
 
8376
        {
 
 
8377
            case MBS_PanicFire:
 
 
8378
            case MBS_PanicReloading:
 
 
8379
            case MBS_Retreating:
 
 
8380
            case MBS_Approaching:
 
 
8381
            case MBS_GetWeapon:
 
 
8382
            case MBS_Taunting:
 
 
8383
            case MBS_Avoidance:
 
 
8384
            break;
 
 
8385
            default:
 
 
8386
                Marine_Enter_Retreat_State(sbPtr);
 
 
8387
        }
 
 
8388
    }
 
 
8389
 
 
 
8390
    if (marineStatusPointer->My_Weapon->id == MNPCW_Minigun)
 
 
8391
    {
 
 
8392
        DELTA_CONTROLLER *mgd = Get_Delta_Sequence(&marineStatusPointer->HModelController, "Minigun");
 
 
8393
 
 
 
8394
        if (mgd)
 
 
8395
            NPC_Maintain_Minigun(sbPtr,mgd);
 
 
8396
    }
 
 
8397
 
 
 
8398
    marineStatusPointer->lastmodule = sbPtr->containingModule->m_aimodule;
 
 
8399
 
 
 
8400
    /* Update squad stats. */
 
 
8401
    switch(marineStatusPointer->behaviourState)
 
 
8402
    {
 
 
8403
        case MBS_Avoidance:
 
 
8404
            if(MBS_Responding != marineStatusPointer->lastState)
 
 
8405
                    break;
 
 
8406
        case MBS_Responding:
 
 
8407
            NpcSquad.Alt_RespondingMarines++;
 
 
8408
        default:
 
 
8409
        break;
 
 
8410
    }
 
 
8411
 
 
 
8412
    if (sbPtr->DisplayBlock)
 
 
8413
    {
 
 
8414
        if(sbPtr->DamageBlock.IsOnFire)
 
 
8415
            NpcSquad.Alt_NearBurningMarines++;
 
 
8416
 
 
 
8417
        switch(marineStatusPointer->behaviourState)
 
 
8418
        {
 
 
8419
            case MBS_Retreating:
 
 
8420
            case MM_RunAroundOnFire:
 
 
8421
                /* Burning marines are considered panicked, too. */
 
 
8422
                NpcSquad.Alt_NearPanickedMarines++;
 
 
8423
            default:
 
 
8424
            break;
 
 
8425
        }
 
 
8426
 
 
 
8427
        if (marineStatusPointer->My_Weapon->ARealMarine)
 
 
8428
        {
 
 
8429
            switch(marineStatusPointer->behaviourState)
 
 
8430
            {
 
 
8431
                case MBS_Retreating:
 
 
8432
                break;
 
 
8433
                default:
 
 
8434
                NpcSquad.Alt_NearUnpanickedMarines++;
 
 
8435
            }
 
 
8436
        }
 
 
8437
    }
 
 
8438
 
 
 
8439
    if(sbPtr->DisplayBlock)
 
 
8440
        HandleMovingAnimations(sbPtr);
 
 
8441
}
 
 
8442
 
 
 
8443
void MakeMarineFar(STRATEGYBLOCK *sbPtr)
 
 
8444
{
 
 
8445
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
8446
 
 
 
8447
    DestroyActiveObject(&sbPtr->DisplayBlock);
 
 
8448
 
 
 
8449
    marineStatusPointer->stateTimer = MARINE_FAR_MOVE_TIME;
 
 
8450
 
 
 
8451
    /* zero linear velocity in dynamics block */
 
 
8452
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
8453
 
 
 
8454
    DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
8455
 
 
 
8456
    /* stop sound, if we have one */
 
 
8457
    if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
8458
        Sound_Stop(marineStatusPointer->soundHandle);    
 
 
8459
 
 
 
8460
    if(marineStatusPointer->soundHandle2 != SOUND_NOACTIVEINDEX)
 
 
8461
        Sound_Stop(marineStatusPointer->soundHandle2);    
 
 
8462
}
 
 
8463
 
 
 
8464
static void Marine_OoophSound(STRATEGYBLOCK *sbPtr) 
 
 
8465
{
 
 
8466
    assert(sbPtr);
 
 
8467
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
8468
    assert(marineStatusPointer);
 
 
8469
 
 
 
8470
    if (marineStatusPointer->Android)
 
 
8471
        return;
 
 
8472
 
 
 
8473
    if (marineStatusPointer->soundHandle2 == SOUND_NOACTIVEINDEX)
 
 
8474
    {
 
 
8475
        PlayMarineScream(marineStatusPointer->Voice, MSC_Oooph, marineStatusPointer->VoicePitch,
 
 
8476
            &marineStatusPointer->soundHandle2, &sbPtr->DynPtr->Position);
 
 
8477
    }
 
 
8478
}
 
 
8479
 
 
 
8480
static void Marine_BurningDeathScream(STRATEGYBLOCK *sbPtr) 
 
 
8481
{
 
 
8482
    assert(sbPtr);
 
 
8483
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
8484
    assert(marineStatusPointer);
 
 
8485
 
 
 
8486
    if (marineStatusPointer->Android)
 
 
8487
        return;
 
 
8488
 
 
 
8489
    if (marineStatusPointer->soundHandle2 == SOUND_NOACTIVEINDEX)
 
 
8490
    {
 
 
8491
        /* I figure if you're screaming already, forget it. */
 
 
8492
        PlayMarineScream(marineStatusPointer->Voice, MSC_OnFire,marineStatusPointer->VoicePitch,
 
 
8493
            &marineStatusPointer->soundHandle2, &sbPtr->DynPtr->Position);
 
 
8494
    }
 
 
8495
    /* That too was really quite unpleasant. */
 
 
8496
}
 
 
8497
 
 
 
8498
static void Marine_ElectrocutionScream(STRATEGYBLOCK *sbPtr) 
 
 
8499
{
 
 
8500
    assert(sbPtr);
 
 
8501
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
8502
    assert(marineStatusPointer);
 
 
8503
 
 
 
8504
    if (marineStatusPointer->Android)
 
 
8505
        return;
 
 
8506
 
 
 
8507
    if (marineStatusPointer->soundHandle2 == SOUND_NOACTIVEINDEX)
 
 
8508
    {
 
 
8509
        /* I figure if you're screaming already, forget it. */
 
 
8510
        PlayMarineScream(marineStatusPointer->Voice, MSC_Electrocution, marineStatusPointer->VoicePitch,
 
 
8511
            &marineStatusPointer->soundHandle2, &sbPtr->DynPtr->Position);
 
 
8512
    }
 
 
8513
}
 
 
8514
 
 
 
8515
static void Marine_DeathScream(STRATEGYBLOCK *sbPtr) 
 
 
8516
{
 
 
8517
    assert(sbPtr);
 
 
8518
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
8519
    assert(marineStatusPointer);
 
 
8520
 
 
 
8521
    if (marineStatusPointer->Android)
 
 
8522
        return;
 
 
8523
 
 
 
8524
    if (marineStatusPointer->soundHandle2 == SOUND_NOACTIVEINDEX)
 
 
8525
    {
 
 
8526
        /* I figure if you're screaming already, forget it. */
 
 
8527
        PlayMarineScream(marineStatusPointer->Voice, MSC_Death, marineStatusPointer->VoicePitch,
 
 
8528
            &marineStatusPointer->soundHandle2, &sbPtr->DynPtr->Position);
 
 
8529
    }
 
 
8530
}
 
 
8531
 
 
 
8532
static void Marine_MuteVoice(STRATEGYBLOCK *sbPtr) 
 
 
8533
{
 
 
8534
    assert(sbPtr);
 
 
8535
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
8536
    assert(marineStatusPointer);
 
 
8537
 
 
 
8538
    if(marineStatusPointer->soundHandle2 != SOUND_NOACTIVEINDEX)
 
 
8539
        Sound_Stop(marineStatusPointer->soundHandle2); /* Cut them off! */
 
 
8540
}
 
 
8541
 
 
 
8542
static void KillMarine(STRATEGYBLOCK *sbPtr, const DAMAGE_PROFILE *damage, int multiple, int wounds,SECTION_DATA *Section,VECTORCH *incoming)
 
 
8543
{
 
 
8544
    int deathtype = 0;
 
 
8545
    assert(sbPtr->containingModule); 
 
 
8546
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
8547
 
 
 
8548
    marineStatusPointer->Target = NULL;
 
 
8549
 
 
 
8550
    /* Morale. */
 
 
8551
    if (marineStatusPointer->My_Weapon->ARealMarine)
 
 
8552
    {
 
 
8553
        /* Only marine deaths get 'spotted' everywhere, by the APC guy! */
 
 
8554
        NpcSquad.Nextframe_Squad_Delta_Morale -= 10000;
 
 
8555
        /* So, warn the squad? */
 
 
8556
        ZoneAlert(3, sbPtr->containingModule->m_aimodule);
 
 
8557
    }
 
 
8558
 
 
 
8559
    Marine_MuteVoice(sbPtr);
 
 
8560
 
 
 
8561
    /*notify death target ,if marine has one*/
 
 
8562
    if(marineStatusPointer->death_target_sbptr)
 
 
8563
        RequestState(marineStatusPointer->death_target_sbptr, marineStatusPointer->death_target_request, 0);
 
 
8564
 
 
 
8565
    DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
8566
 
 
 
8567
    /* stop sound, if we have one, and it's not the fire */
 
 
8568
    if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
8569
    {
 
 
8570
        if (ActiveSounds[marineStatusPointer->soundHandle].soundIndex != SID_FIRE)
 
 
8571
            Sound_Stop(marineStatusPointer->soundHandle);
 
 
8572
    }
 
 
8573
 
 
 
8574
    {
 
 
8575
        int tkd = TotalKineticDamage(damage);
 
 
8576
/*
 
 
8577
        if (damage->ExplosivePower == 1)
 
 
8578
        {
 
 
8579
            if (MUL_FIXED(tkd, (multiple&((ONE_FIXED << 1) -1))) > 20)
 
 
8580
            {
 
 
8581
                // Okay, you can gibb now.
 
 
8582
                marineStatusPointer->GibbFactor = ONE_FIXED>>1;
 
 
8583
                deathtype = 2;
 
 
8584
            }
 
 
8585
        }
 
 
8586
        else
 
 
8587
*/
 
 
8588
        if (damage->ExplosivePower)
 
 
8589
        {
 
 
8590
            marineStatusPointer->GibbFactor = ONE_FIXED;
 
 
8591
            deathtype = 3;
 
 
8592
        }
 
 
8593
        else if ((tkd > 60) && ((multiple >> 16) > 1))
 
 
8594
        {
 
 
8595
            int newmult = DIV_FIXED(multiple, NormalFrameTime);
 
 
8596
 
 
 
8597
            if (MUL_FIXED(tkd,newmult) > (500))
 
 
8598
            {
 
 
8599
                /* Loadsabullets! */
 
 
8600
                marineStatusPointer->GibbFactor = -(ONE_FIXED>>2);
 
 
8601
                deathtype = 2;
 
 
8602
            }
 
 
8603
        }
 
 
8604
    }
 
 
8605
 
 
 
8606
    if (damage->ForceBoom)
 
 
8607
        deathtype += damage->ForceBoom;
 
 
8608
 
 
 
8609
    {
 
 
8610
        SECTION_DATA *chest = GetThisSectionData(marineStatusPointer->HModelController.section_data, "chest");
 
 
8611
 
 
 
8612
        if (chest == NULL)
 
 
8613
        {
 
 
8614
            /* I'm impressed. */
 
 
8615
            deathtype += 2;
 
 
8616
        }
 
 
8617
        else if ((chest->flags & section_data_notreal) && (chest->flags & section_data_terminate_here))
 
 
8618
        {
 
 
8619
            /* That's gotta hurt. */
 
 
8620
            deathtype++;
 
 
8621
        }
 
 
8622
    }
 
 
8623
 
 
 
8624
    int head = 1;
 
 
8625
 
 
 
8626
    if (!marineStatusPointer->GibbFactor)
 
 
8627
    {
 
 
8628
        /* make a sound... if you have a head. */
 
 
8629
        SECTION_DATA *head = GetThisSectionData(marineStatusPointer->HModelController.section_data, "head");
 
 
8630
 
 
 
8631
        /* Is it still attached? */
 
 
8632
        if (head && !(head->flags & section_data_notreal))
 
 
8633
        {
 
 
8634
            if (marineStatusPointer->Expression != 3)
 
 
8635
            {
 
 
8636
                /* Expression 3 just looks too peaceful. */
 
 
8637
                if(sbPtr->DamageBlock.IsOnFire)
 
 
8638
                {
 
 
8639
                    Marine_BurningDeathScream(sbPtr);
 
 
8640
                }
 
 
8641
                else if (  (!damage->Impact)
 
 
8642
                    && (!damage->Cutting)
 
 
8643
                    && (!damage->Penetrative)
 
 
8644
                    && (!damage->Fire)
 
 
8645
                    && (damage->Electrical > 0)
 
 
8646
                    && (!damage->Acid))
 
 
8647
                {
 
 
8648
                    Marine_ElectrocutionScream(sbPtr);
 
 
8649
                }
 
 
8650
                else if (Section && (damage->Id == AMMO_PRED_RIFLE))
 
 
8651
                {
 
 
8652
                    /* Hit in the chest or pelvis by a speargun? */
 
 
8653
                    if(!strcmp(Section->sempai->Section_Name, "pelvis")
 
 
8654
                    || !strcmp(Section->sempai->Section_Name, "pelvis presley")
 
 
8655
                    || !strcmp(Section->sempai->Section_Name, "chest") )
 
 
8656
                    {
 
 
8657
                        Marine_OoophSound(sbPtr);
 
 
8658
                    }
 
 
8659
                    else
 
 
8660
                    {
 
 
8661
                        Marine_DeathScream(sbPtr);
 
 
8662
                    }
 
 
8663
                }
 
 
8664
                else
 
 
8665
                {
 
 
8666
                    Marine_DeathScream(sbPtr);
 
 
8667
                }
 
 
8668
            }
 
 
8669
        }
 
 
8670
        else
 
 
8671
        {
 
 
8672
            head = 0;
 
 
8673
        }
 
 
8674
    }
 
 
8675
    else
 
 
8676
    {
 
 
8677
        if (marineStatusPointer->GibbFactor > 0)
 
 
8678
            Extreme_Gibbing(sbPtr, marineStatusPointer->HModelController.section_data, marineStatusPointer->GibbFactor, incoming);
 
 
8679
 
 
 
8680
        marineStatusPointer->GibbFactor = 0;
 
 
8681
    }
 
 
8682
 
 
 
8683
    /* See if anyone saw that? */
 
 
8684
    int a = 0;
 
 
8685
    for (; a < NumActiveStBlocks; a++)
 
 
8686
    {
 
 
8687
        STRATEGYBLOCK *candidate = ActiveStBlockList[a];
 
 
8688
        assert(candidate);
 
 
8689
 
 
 
8690
        if (candidate->type == I_BehaviourMarine)
 
 
8691
        {
 
 
8692
            /* Are you already suspicious? */
 
 
8693
            MARINE_STATUS_BLOCK *fellow_marine = (MARINE_STATUS_BLOCK *)(candidate->dataptr);
 
 
8694
 
 
 
8695
            /* Did you see that? */
 
 
8696
            if (NPCCanSeeTarget(candidate, sbPtr))
 
 
8697
            {
 
 
8698
                if (!fellow_marine->Android)
 
 
8699
                {
 
 
8700
                    if (marineStatusPointer->GibbFactor)
 
 
8701
                    {
 
 
8702
                        fellow_marine->Courage -= 20000;
 
 
8703
                    }
 
 
8704
                    else if (!head)
 
 
8705
                    {
 
 
8706
                        fellow_marine->Courage -= 15000;
 
 
8707
                    }
 
 
8708
                    else
 
 
8709
                    {
 
 
8710
                        fellow_marine->Courage -= 10000;
 
 
8711
                    }
 
 
8712
                }
 
 
8713
 
 
 
8714
                if (!fellow_marine->suspicious || fellow_marine->using_squad_suspicion)
 
 
8715
                {
 
 
8716
                    /* Okay, react. */
 
 
8717
                    fellow_marine->suspicious = MARINE_PARANOIA_TIME;
 
 
8718
                    fellow_marine->suspect_point = sbPtr->DynPtr->Position;
 
 
8719
                    /* Set this to zero when you get a *new* suspicion. */
 
 
8720
                    fellow_marine->previous_suspicion = 0;
 
 
8721
                    fellow_marine->using_squad_suspicion = 0;
 
 
8722
                }
 
 
8723
            }
 
 
8724
        }
 
 
8725
    }
 
 
8726
 
 
 
8727
    /* Now final stage. */
 
 
8728
    {
 
 
8729
        HIT_FACING facing = { 0,0,0,0 };
 
 
8730
        int burning = 0;
 
 
8731
        int electrical = 0;
 
 
8732
 
 
 
8733
        SECTION *root = GetNamedHierarchyFromLibrary(marineStatusPointer->My_Weapon->Riffname, marineStatusPointer->My_Weapon->TemplateName);
 
 
8734
 
 
 
8735
        if (incoming)
 
 
8736
        {
 
 
8737
            if (incoming->vz > 0)
 
 
8738
                facing.Back = 1;
 
 
8739
            else
 
 
8740
                facing.Front = 1;
 
 
8741
 
 
 
8742
            if (incoming->vx > 0)
 
 
8743
                facing.Right = 1;
 
 
8744
            else
 
 
8745
                facing.Left = 1;
 
 
8746
        }
 
 
8747
 
 
 
8748
        if (!damage->Impact && !damage->Cutting && !damage->Penetrative && !damage->Acid)
 
 
8749
        {
 
 
8750
            if (!damage->Fire)
 
 
8751
            {
 
 
8752
                if (damage->Electrical)
 
 
8753
                    electrical = 1;
 
 
8754
            }
 
 
8755
            else if (!damage->Electrical && sbPtr->DamageBlock.IsOnFire)
 
 
8756
            {
 
 
8757
                burning = 1;
 
 
8758
            }
 
 
8759
        }
 
 
8760
 
 
 
8761
        DEATH_DATA *this_death = GetMarineDeathSequence(&marineStatusPointer->HModelController, root, marineStatusPointer->Wounds,
marineStatusPointer->Wounds,
 
 
8762
            deathtype, &facing,burning,marineStatusPointer->IAmCrouched,electrical);
 
 
8763
 
 
 
8764
        assert(this_death);
 
 
8765
 
 
 
8766
        Remove_Delta_Sequence(&marineStatusPointer->HModelController, "Elevation");
 
 
8767
        Remove_Delta_Sequence(&marineStatusPointer->HModelController, "HitDelta");
 
 
8768
        Remove_Delta_Sequence(&marineStatusPointer->HModelController, "Minigun");
 
 
8769
        Remove_Delta_Sequence(&marineStatusPointer->HModelController, "sprintheaddelta");
 
 
8770
 
 
 
8771
        Convert_Marine_To_Corpse(sbPtr, this_death);
 
 
8772
    }
 
 
8773
}
 
 
8774
 
 
 
8775
static void Marine_WoundedScream(STRATEGYBLOCK *sbPtr) 
 
 
8776
{
 
 
8777
    assert(sbPtr);
 
 
8778
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
8779
    assert(marineStatusPointer);
 
 
8780
 
 
 
8781
    if (marineStatusPointer->Android)
 
 
8782
        return;
 
 
8783
 
 
 
8784
    if (marineStatusPointer->soundHandle2 == SOUND_NOACTIVEINDEX)
 
 
8785
    {
 
 
8786
        PlayMarineScream(marineStatusPointer->Voice, MSC_Pain, marineStatusPointer->VoicePitch,
 
 
8787
            &marineStatusPointer->soundHandle2, &sbPtr->DynPtr->Position);
 
 
8788
    }
 
 
8789
}
 
 
8790
 
 
 
8791
static void Marine_Activate_AcidAvoidance_State(STRATEGYBLOCK *sbPtr, VECTORCH *incidence) 
 
 
8792
{
 
 
8793
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
8794
 
 
 
8795
    marineStatusPointer->gotapoint = 0;
 
 
8796
 
 
 
8797
    NPC_InitMovementData(&marineStatusPointer->moveData);
 
 
8798
    NPC_InitWanderData(&marineStatusPointer->wanderData);
 
 
8799
    InitWaypointManager(&marineStatusPointer->waypointManager);
 
 
8800
    marineStatusPointer->volleySize = 0;
 
 
8801
    marineStatusPointer->lastState = marineStatusPointer->behaviourState;
 
 
8802
    marineStatusPointer->behaviourState = MBS_AcidAvoidance;
 
 
8803
    marineStatusPointer->stateTimer = ONE_FIXED;
 
 
8804
 
 
 
8805
    /* Get a destination. */
 
 
8806
    {
 
 
8807
        VECTORCH dest;
 
 
8808
 
 
 
8809
        if (incidence)
 
 
8810
        {
 
 
8811
            dest = *incidence;
 
 
8812
        }
 
 
8813
        else
 
 
8814
        {
 
 
8815
            /* Boo. */
 
 
8816
            dest.vx = sbPtr->DynPtr->OrientMat.mat11;
 
 
8817
            dest.vy = sbPtr->DynPtr->OrientMat.mat12;
 
 
8818
            dest.vy = sbPtr->DynPtr->OrientMat.mat13;
 
 
8819
        }
 
 
8820
 
 
 
8821
        AlignVelocityToGravity(sbPtr, &dest);
 
 
8822
 
 
 
8823
        if (!Approximate3dMagnitude(&dest))
 
 
8824
        {
 
 
8825
            /* Boo. */
 
 
8826
            dest.vx = sbPtr->DynPtr->OrientMat.mat11;
 
 
8827
            dest.vy = sbPtr->DynPtr->OrientMat.mat12;
 
 
8828
            dest.vy = sbPtr->DynPtr->OrientMat.mat13;
 
 
8829
        }
 
 
8830
 
 
 
8831
        marineStatusPointer->wanderData.worldPosition = sbPtr->DynPtr->Position;
 
 
8832
        marineStatusPointer->wanderData.worldPosition.vx += (dest.vx>>6);
 
 
8833
        marineStatusPointer->wanderData.worldPosition.vy += (dest.vy>>6);
 
 
8834
        marineStatusPointer->wanderData.worldPosition.vz += (dest.vz>>6);
 
 
8835
    }
 
 
8836
 
 
 
8837
    /* Not sure we need an expression for this one. */
 
 
8838
}
 
 
8839
 
 
 
8840
static void Marine_Enter_OneArmPistol_State(STRATEGYBLOCK *sbPtr) 
 
 
8841
{
 
 
8842
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
8843
 
 
 
8844
    marineStatusPointer->gotapoint = 0;
 
 
8845
    marineStatusPointer->internalState = 0;
 
 
8846
    marineStatusPointer->volleySize = 0;
 
 
8847
    marineStatusPointer->lastState = marineStatusPointer->behaviourState;
 
 
8848
    marineStatusPointer->behaviourState = MBS_GetWeapon;
 
 
8849
    marineStatusPointer->stateTimer = MARINE_NEARWAITTIME;
 
 
8850
 
 
 
8851
    {
 
 
8852
        /* There should be NO head turn delta... */
 
 
8853
        DELTA_CONTROLLER *delta = Get_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
 
 
8854
 
 
 
8855
        if (delta)
 
 
8856
            Remove_Delta_Sequence(&marineStatusPointer->HModelController,"sprintheaddelta");
 
 
8857
 
 
 
8858
        /* ...and NO Minigun delta... */
 
 
8859
        delta = Get_Delta_Sequence(&marineStatusPointer->HModelController,"Minigun");
 
 
8860
 
 
 
8861
        if (delta)
 
 
8862
            Remove_Delta_Sequence(&marineStatusPointer->HModelController,"Minigun");
 
 
8863
 
 
 
8864
        /* ...and strip out HitDelta for now, too. */
 
 
8865
        delta = Get_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta");
 
 
8866
 
 
 
8867
        if (delta)
 
 
8868
            Remove_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta");
 
 
8869
    }
 
 
8870
 
 
 
8871
    /* Now, try to be clever... */
 
 
8872
    /* Turn into an Android Special!  */
 
 
8873
    const MARINE_WEAPON_DATA *pistol_data = &NPC_Marine_Weapons[MNPCW_Android_Pistol_Special];
 
 
8874
 
 
 
8875
    SECTION *root = GetNamedHierarchyFromLibrary(pistol_data->Riffname,pistol_data->HierarchyName);
 
 
8876
    assert(root);
 
 
8877
 
 
 
8878
    marineStatusPointer->HModelController.Sequence_Type = HMSQT_MarineStand;
 
 
8879
    marineStatusPointer->HModelController.Sub_Sequence = MSSS_Get_Weapon;
 
 
8880
    /* That's to put the pistol in the right place... */
 
 
8881
    Transmogrify_HModels(sbPtr,&marineStatusPointer->HModelController,root, 1, 1,0);
 
 
8882
    marineStatusPointer->My_Weapon = pistol_data;
 
 
8883
    marineStatusPointer->My_Gunflash_Section = GetThisSectionData(marineStatusPointer->HModelController.section_data,
marineStatusPointer->My_Weapon->GunflashName);
 
 
8884
    marineStatusPointer->My_Elevation_Section = GetThisSectionData(marineStatusPointer->HModelController.section_data,
marineStatusPointer->My_Weapon->ElevationSection);
 
 
8885
    /* Start loaded! */
 
 
8886
    marineStatusPointer->clipammo = marineStatusPointer->My_Weapon->clip_size;
 
 
8887
 
 
 
8888
    DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
8889
 
 
 
8890
    /* .... and stop the sound */
 
 
8891
    if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
8892
    {
 
 
8893
        Sound_Stop(marineStatusPointer->soundHandle);        
 
 
8894
        Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
8895
    }
 
 
8896
 
 
 
8897
    SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_Get_Weapon, -1, (ONE_FIXED>>3));
 
 
8898
    marineStatusPointer->HModelController.LoopAfterTweening = 0;
 
 
8899
 
 
 
8900
    /* Attempt to put the hitdelta back? */
 
 
8901
    if (HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,(int)MSSS_HitChestFront))
 
 
8902
    {
 
 
8903
        DELTA_CONTROLLER *delta =
Add_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta",(int)HMSQT_MarineStand,(int)MSSS_HitChestFront,(ONE_FIXED>>2));
 
 
8904
        assert(delta);
 
 
8905
        delta->Playing = 0;
 
 
8906
    }
 
 
8907
 
 
 
8908
    DeInitialise_HModel(&marineStatusPointer->HModelController);
 
 
8909
    ProveHModel_Far(&marineStatusPointer->HModelController,sbPtr);
 
 
8910
}
 
 
8911
 
 
 
8912
static void Marine_Enter_OneArmShotgun_State(STRATEGYBLOCK *sbPtr) 
 
 
8913
{
 
 
8914
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
8915
 
 
 
8916
    marineStatusPointer->gotapoint = 0;
 
 
8917
    marineStatusPointer->internalState = 0;
 
 
8918
    marineStatusPointer->volleySize = 0;
 
 
8919
    marineStatusPointer->lastState = marineStatusPointer->behaviourState;
 
 
8920
    marineStatusPointer->behaviourState = MBS_Waiting;
 
 
8921
    marineStatusPointer->stateTimer = MARINE_NEARWAITTIME;
 
 
8922
 
 
 
8923
    {
 
 
8924
        /* There should be NO head turn delta... */
 
 
8925
        DELTA_CONTROLLER *delta = Get_Delta_Sequence(&marineStatusPointer->HModelController, "sprintheaddelta");
 
 
8926
 
 
 
8927
        if (delta)
 
 
8928
            Remove_Delta_Sequence(&marineStatusPointer->HModelController, "sprintheaddelta");
 
 
8929
 
 
 
8930
        /* ...and NO Minigun delta... */
 
 
8931
        delta = Get_Delta_Sequence(&marineStatusPointer->HModelController, "Minigun");
 
 
8932
 
 
 
8933
        if (delta)
 
 
8934
            Remove_Delta_Sequence(&marineStatusPointer->HModelController, "Minigun");
 
 
8935
 
 
 
8936
        /* ...and strip out HitDelta for now, too. */
 
 
8937
 
 
 
8938
        delta = Get_Delta_Sequence(&marineStatusPointer->HModelController, "HitDelta");
 
 
8939
 
 
 
8940
        if (delta)
 
 
8941
            Remove_Delta_Sequence(&marineStatusPointer->HModelController, "HitDelta");
 
 
8942
    }
 
 
8943
 
 
 
8944
    /* Now, try to be clever... */
 
 
8945
    /* Turn into an Android Special!  */
 
 
8946
    const MARINE_WEAPON_DATA *pistol_data = &NPC_Marine_Weapons[MNPCW_AndroidSpecial];
 
 
8947
 
 
 
8948
    SECTION *root = GetNamedHierarchyFromLibrary(pistol_data->Riffname, pistol_data->HierarchyName);
 
 
8949
    assert(root);
 
 
8950
 
 
 
8951
    marineStatusPointer->HModelController.Sequence_Type = HMSQT_MarineStand;
 
 
8952
    marineStatusPointer->HModelController.Sub_Sequence = MSSS_Standard;
 
 
8953
    /* That's to put the pistol in the right place... */
 
 
8954
    Transmogrify_HModels(sbPtr,&marineStatusPointer->HModelController,root, 1, 1,0);
 
 
8955
    marineStatusPointer->My_Weapon = pistol_data;
 
 
8956
    marineStatusPointer->My_Gunflash_Section = GetThisSectionData(marineStatusPointer->HModelController.section_data,
marineStatusPointer->My_Weapon->GunflashName);
 
 
8957
    marineStatusPointer->My_Elevation_Section = GetThisSectionData(marineStatusPointer->HModelController.section_data,
marineStatusPointer->My_Weapon->ElevationSection);
 
 
8958
 
 
 
8959
    /* Retain clipammo from the old shotgun. */
 
 
8960
 
 
 
8961
    DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
8962
 
 
 
8963
    /* .... and stop the sound */
 
 
8964
    if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
8965
    {
 
 
8966
        Sound_Stop(marineStatusPointer->soundHandle);        
 
 
8967
        Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
8968
    }
 
 
8969
 
 
 
8970
    SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_Standard, -1, (ONE_FIXED>>3));
 
 
8971
    marineStatusPointer->HModelController.LoopAfterTweening = 0;
 
 
8972
 
 
 
8973
    /* Attempt to put the hitdelta back? */
 
 
8974
    if (HModelSequence_Exists(&marineStatusPointer->HModelController, (int)HMSQT_MarineStand, (int)MSSS_HitChestFront))
 
 
8975
    {
 
 
8976
        DELTA_CONTROLLER *delta =
Add_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta",(int)HMSQT_MarineStand,(int)MSSS_HitChestFront,(ONE_FIXED>>2));
 
 
8977
        assert(delta);
 
 
8978
        delta->Playing = 0;
 
 
8979
    }
 
 
8980
 
 
 
8981
    DeInitialise_HModel(&marineStatusPointer->HModelController);
 
 
8982
    ProveHModel_Far(&marineStatusPointer->HModelController,sbPtr);
 
 
8983
}
 
 
8984
 
 
 
8985
void MarineIsDamaged(STRATEGYBLOCK *sbPtr, const DAMAGE_PROFILE *damage, int multiple, int wounds, SECTION_DATA *Section, VECTORCH *incoming)
 
 
8986
{
 
 
8987
    assert(sbPtr->containingModule); 
 
 
8988
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
8989
 
 
 
8990
    if(!sbPtr->DisplayBlock)
 
 
8991
    {
 
 
8992
        sbPtr->please_destroy_me = 1;
 
 
8993
        return;
 
 
8994
    }
 
 
8995
 
 
 
8996
    marineStatusPointer->Wounds |= wounds;
 
 
8997
 
 
 
8998
    /* Might want to get a new target? */
 
 
8999
 
 
 
9000
    if(sbPtr->DamageBlock.Health <= 0)
 
 
9001
    {
 
 
9002
        int dice = FastRandom() & 65535;
 
 
9003
 
 
 
9004
        if (marineStatusPointer->Android)
 
 
9005
        {
 
 
9006
            Marine_SwitchExpression(sbPtr,3);
 
 
9007
        }
 
 
9008
        else if (dice < 32768)
 
 
9009
        {
 
 
9010
            Marine_SwitchExpression(sbPtr,5);
 
 
9011
        }
 
 
9012
        else
 
 
9013
        {
 
 
9014
            Marine_SwitchExpression(sbPtr,4);
 
 
9015
        }
 
 
9016
 
 
 
9017
        if (AvP.PlayerType != I_Marine)
 
 
9018
            CurrentGameStats_CreatureKilled(sbPtr, Section);
 
 
9019
 
 
 
9020
        KillMarine(sbPtr, damage, multiple, wounds, Section,incoming);
 
 
9021
    }
 
 
9022
    else
 
 
9023
    {
 
 
9024
        if (sbPtr->DamageBlock.IsOnFire)
 
 
9025
        {
 
 
9026
            if (!marineStatusPointer->Android)
 
 
9027
            if (marineStatusPointer->soundHandle2 == SOUND_NOACTIVEINDEX)
 
 
9028
            {
 
 
9029
                PlayMarineScream(marineStatusPointer->Voice, MSC_OnFire, marineStatusPointer->VoicePitch,
 
 
9030
                    &marineStatusPointer->soundHandle2, &sbPtr->DynPtr->Position);
 
 
9031
            }
 
 
9032
            /* Urgh, that was really grim. */
 
 
9033
        }
 
 
9034
        else if ( !damage->Impact && !damage->Cutting
 
 
9035
            && !damage->Penetrative && !damage->Fire
 
 
9036
            && !damage->Electrical && damage->Acid)
 
 
9037
        {
 
 
9038
            if (!marineStatusPointer->Android)
 
 
9039
            if (marineStatusPointer->soundHandle2 == SOUND_NOACTIVEINDEX)
 
 
9040
            {
 
 
9041
                PlayMarineScream(marineStatusPointer->Voice, MSC_Acid,marineStatusPointer->VoicePitch,
 
 
9042
                    &marineStatusPointer->soundHandle2, &sbPtr->DynPtr->Position);
 
 
9043
            }
 
 
9044
 
 
 
9045
            switch(marineStatusPointer->behaviourState)
 
 
9046
            {
 
 
9047
                case MBS_AcidAvoidance:
 
 
9048
                case MBS_Firing:
 
 
9049
                case MBS_Avoidance:
 
 
9050
                case MBS_PanicFire:
 
 
9051
                case MBS_Reloading:
 
 
9052
                case MBS_PumpAction:
 
 
9053
                case MBS_GetWeapon:
 
 
9054
                case MBS_PanicReloading:
 
 
9055
                break;
 
 
9056
                default:
 
 
9057
                    Marine_Activate_AcidAvoidance_State(sbPtr, incoming);
 
 
9058
            }
 
 
9059
        }
 
 
9060
        else
 
 
9061
        {
 
 
9062
            Marine_WoundedScream(sbPtr);
 
 
9063
        }
 
 
9064
 
 
 
9065
        /* Open the mouth? */
 
 
9066
        Marine_AssumePanicExpression(sbPtr);
 
 
9067
 
 
 
9068
        /* If not dead, play a hit delta. */
 
 
9069
        /* Default to front. */
 
 
9070
        int frontback = 1;
 
 
9071
 
 
 
9072
        DELTA_CONTROLLER *hitdelta = Get_Delta_Sequence(&marineStatusPointer->HModelController, "HitDelta");
 
 
9073
 
 
 
9074
        if (incoming && (incoming->vz >= 0))
 
 
9075
            frontback = 0;
 
 
9076
 
 
 
9077
        if (hitdelta)
 
 
9078
        {
 
 
9079
            /* A hierarchy with hit deltas! */
 
 
9080
            int CrouchSubSequence;
 
 
9081
            int StandSubSequence;
 
 
9082
 
 
 
9083
            if (Section == NULL)
 
 
9084
            {
 
 
9085
                if (!frontback)
 
 
9086
                {
 
 
9087
                    CrouchSubSequence = MCrSS_HitChestBack;
 
 
9088
                    StandSubSequence = MSSS_HitChestBack;
 
 
9089
                }
 
 
9090
                else
 
 
9091
                {
 
 
9092
                    CrouchSubSequence = MCrSS_HitChestFront;
 
 
9093
                    StandSubSequence = MSSS_HitChestFront;
 
 
9094
                }
 
 
9095
            }
 
 
9096
            else if (Section->sempai->flags & section_flag_head)
 
 
9097
            {
 
 
9098
                if (!frontback)
 
 
9099
                {
 
 
9100
                    CrouchSubSequence = MCrSS_HitHeadBack;
 
 
9101
                    StandSubSequence = MSSS_HitHeadBack;
 
 
9102
                }
 
 
9103
                else
 
 
9104
                {
 
 
9105
                    CrouchSubSequence = MCrSS_HitHeadFront;
 
 
9106
                    StandSubSequence = MSSS_HitHeadFront;
 
 
9107
                }
 
 
9108
            }
 
 
9109
            else if ((Section->sempai->flags & section_flag_left_arm) || (Section->sempai->flags & section_flag_left_hand))
 
 
9110
            {
 
 
9111
                if (!frontback)
 
 
9112
                {
 
 
9113
                    CrouchSubSequence = MCrSS_HitRightArm;
 
 
9114
                    StandSubSequence = MSSS_HitRightArm;
 
 
9115
                }
 
 
9116
                else
 
 
9117
                {
 
 
9118
                    CrouchSubSequence = MCrSS_HitLeftArm;
 
 
9119
                    StandSubSequence = MSSS_HitLeftArm;
 
 
9120
                }
 
 
9121
            }
 
 
9122
            else if ((Section->sempai->flags & section_flag_right_arm) ||(Section->sempai->flags & section_flag_right_hand))
 
 
9123
            {
 
 
9124
                if (!frontback)
 
 
9125
                {
 
 
9126
                    CrouchSubSequence = MCrSS_HitLeftArm;
 
 
9127
                    StandSubSequence = MSSS_HitLeftArm;
 
 
9128
                }
 
 
9129
                else
 
 
9130
                {
 
 
9131
                    CrouchSubSequence = MCrSS_HitRightArm;
 
 
9132
                    StandSubSequence = MSSS_HitRightArm;
 
 
9133
                }
 
 
9134
            }
 
 
9135
            else if ((Section->sempai->flags & section_flag_left_leg) ||(Section->sempai->flags & section_flag_left_foot))
 
 
9136
                {
 
 
9137
                if (!frontback)
 
 
9138
                {
 
 
9139
                    CrouchSubSequence = MCrSS_HitRightLeg;
 
 
9140
                    StandSubSequence = MSSS_HitRightLeg;
 
 
9141
                }
 
 
9142
                else
 
 
9143
                {
 
 
9144
                    CrouchSubSequence=MCrSS_HitLeftLeg;
 
 
9145
                    StandSubSequence=MSSS_HitLeftLeg;
 
 
9146
                }
 
 
9147
            }
 
 
9148
            else if ((Section->sempai->flags & section_flag_right_leg) || (Section->sempai->flags & section_flag_right_foot))
 
 
9149
            {
 
 
9150
                if (!frontback)
 
 
9151
                {
 
 
9152
                    CrouchSubSequence = MCrSS_HitLeftLeg;
 
 
9153
                    StandSubSequence = MSSS_HitLeftLeg;
 
 
9154
                }
 
 
9155
                else
 
 
9156
                {
 
 
9157
                    CrouchSubSequence = MCrSS_HitRightLeg;
 
 
9158
                    StandSubSequence = MSSS_HitRightLeg;
 
 
9159
                }
 
 
9160
            }
 
 
9161
            else
 
 
9162
            {
 
 
9163
                /* Chest or misc. hit. */
 
 
9164
                if (!frontback)
 
 
9165
                {
 
 
9166
                    CrouchSubSequence = MCrSS_HitChestBack;
 
 
9167
                    StandSubSequence = MSSS_HitChestBack;
 
 
9168
                }
 
 
9169
                else
 
 
9170
                {
 
 
9171
                    CrouchSubSequence = MCrSS_HitChestFront;
 
 
9172
                    StandSubSequence = MSSS_HitChestFront;
 
 
9173
                }
 
 
9174
            }
 
 
9175
 
 
 
9176
            if(marineStatusPointer->IAmCrouched)
 
 
9177
            {
 
 
9178
                if (HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineCrouch,CrouchSubSequence))
 
 
9179
                    Start_Delta_Sequence(hitdelta, (int)HMSQT_MarineCrouch, CrouchSubSequence, -1); /* Was (ONE_FIXED>>2) */
 
 
9180
            }
 
 
9181
            else
 
 
9182
            {
 
 
9183
                if (HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,StandSubSequence))
 
 
9184
                    Start_Delta_Sequence(hitdelta, (int)HMSQT_MarineStand, StandSubSequence, -1); /* Was (ONE_FIXED>>2) */
 
 
9185
            }
 
 
9186
 
 
 
9187
            hitdelta->Playing = 1;
 
 
9188
            /* Not looped. */
 
 
9189
        }
 
 
9190
 
 
 
9191
        /* Finally, warn the squad. */
 
 
9192
        ZoneAlert(3, sbPtr->containingModule->m_aimodule);
 
 
9193
 
 
 
9194
        /* And become suspicious. */
 
 
9195
        marineStatusPointer->suspicious = MARINE_PARANOIA_TIME;
 
 
9196
        /* Set this to zero when you get a *new* suspicion. */
 
 
9197
 
 
 
9198
        marineStatusPointer->previous_suspicion = 0;
 
 
9199
        marineStatusPointer->using_squad_suspicion = 0;
 
 
9200
 
 
 
9201
        if (incoming)
 
 
9202
        {
 
 
9203
            marineStatusPointer->suspect_point = *incoming;
 
 
9204
            /* Flip it round! */
 
 
9205
            marineStatusPointer->suspect_point.vx = -marineStatusPointer->suspect_point.vx;
 
 
9206
            marineStatusPointer->suspect_point.vy = -marineStatusPointer->suspect_point.vy;
 
 
9207
            marineStatusPointer->suspect_point.vz = -marineStatusPointer->suspect_point.vz;
 
 
9208
 
 
 
9209
            Normalise(&marineStatusPointer->suspect_point);
 
 
9210
 
 
 
9211
            marineStatusPointer->suspect_point.vx >>= 5;
 
 
9212
            marineStatusPointer->suspect_point.vy >>= 5;
 
 
9213
            marineStatusPointer->suspect_point.vz >>= 5;
 
 
9214
        }
 
 
9215
        else
 
 
9216
        {
 
 
9217
            marineStatusPointer->suspect_point.vx = 0;
 
 
9218
            marineStatusPointer->suspect_point.vy = 0;
 
 
9219
            marineStatusPointer->suspect_point.vz = -2000;
 
 
9220
        }
 
 
9221
 
 
 
9222
        RotateVector(&marineStatusPointer->suspect_point, &sbPtr->DynPtr->OrientMat);
 
 
9223
 
 
 
9224
        marineStatusPointer->suspect_point.vx += sbPtr->DynPtr->Position.vx;
 
 
9225
        marineStatusPointer->suspect_point.vy += sbPtr->DynPtr->Position.vy;
 
 
9226
        marineStatusPointer->suspect_point.vz += sbPtr->DynPtr->Position.vz;
 
 
9227
 
 
 
9228
        /* Switch wounded androids into an appropriate state. */
 
 
9229
        if (marineStatusPointer->Android)
 
 
9230
        {
 
 
9231
            if (marineStatusPointer->Wounds & section_flag_left_hand)
 
 
9232
            {
 
 
9233
                if (marineStatusPointer->My_Weapon->id != MNPCW_AndroidSpecial)
 
 
9234
                    Marine_Enter_OneArmShotgun_State(sbPtr);
 
 
9235
            }
 
 
9236
            else if (marineStatusPointer->Wounds & section_flag_right_hand)
 
 
9237
            {
 
 
9238
                if (marineStatusPointer->My_Weapon->id != MNPCW_Android_Pistol_Special)
 
 
9239
                    Marine_Enter_OneArmPistol_State(sbPtr);
 
 
9240
            }
 
 
9241
        }
 
 
9242
    }
 
 
9243
}
 
 
9244
 
 
 
9245
static void MaintainMarineGunFlash(STRATEGYBLOCK *sbPtr)
 
 
9246
{
 
 
9247
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
9248
 
 
 
9249
    if(marineStatusPointer->myGunFlash != NULL)
 
 
9250
    {
 
 
9251
        assert(marineStatusPointer->My_Gunflash_Section);
 
 
9252
        marineStatusPointer->myGunFlash->ObWorld = marineStatusPointer->My_Gunflash_Section->World_Offset;
 
 
9253
        marineStatusPointer->myGunFlash->ObMat = marineStatusPointer->My_Gunflash_Section->SecMat;
 
 
9254
        AddLightingEffectToObject(marineStatusPointer->myGunFlash, LFX_MUZZLEFLASH);
 
 
9255
    }
 
 
9256
    else
 
 
9257
    {
 
 
9258
        DISPLAYBLOCK *dPtr = CreateSFXObject(marineStatusPointer->My_Weapon->SfxID);
 
 
9259
 
 
 
9260
        if(dPtr)
 
 
9261
        {
 
 
9262
            dPtr->ObWorld = marineStatusPointer->My_Gunflash_Section->World_Offset;
 
 
9263
            dPtr->ObMat = marineStatusPointer->My_Gunflash_Section->SecMat;
 
 
9264
            AddLightingEffectToObject(dPtr, LFX_MUZZLEFLASH);
 
 
9265
            dPtr->SfxPtr->EffectDrawnLastFrame = 0;
 
 
9266
            marineStatusPointer->myGunFlash = dPtr;
 
 
9267
        }
 
 
9268
    }
 
 
9269
}
 
 
9270
 
 
 
9271
static void MarineFireFlameThrower(STRATEGYBLOCK *sbPtr)
 
 
9272
{
 
 
9273
    assert(sbPtr);
 
 
9274
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
9275
    assert(marineStatusPointer);
 
 
9276
    assert(marineStatusPointer->My_Gunflash_Section);
 
 
9277
 
 
 
9278
    FireFlameThrower(&marineStatusPointer->My_Gunflash_Section->World_Offset,&null_vec,
 
 
9279
        &marineStatusPointer->My_Gunflash_Section->SecMat,0,&marineStatusPointer->weapon_variable);
 
 
9280
}
 
 
9281
 
 
 
9282
static void MarineMisfireFlameThrower(SECTION_DATA *muzzle, int *timer)
 
 
9283
{
 
 
9284
    FireFlameThrower(&muzzle->World_Offset, &null_vec, &muzzle->SecMat, 0, timer);
 
 
9285
}
 
 
9286
 
 
 
9287
static STATE_RETURN_CONDITION Execute_MNS_DischargeFlamethrower(STRATEGYBLOCK *sbPtr)
 
 
9288
{
 
 
9289
    VECTORCH orientationDirn;
 
 
9290
    int correctlyOrientated;
 
 
9291
 
 
 
9292
    assert(sbPtr);
 
 
9293
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
9294
    assert(marineStatusPointer);
 
 
9295
 
 
 
9296
    marineStatusPointer->HModelController.Playing = 1;
 
 
9297
 
 
 
9298
    /* zero velocity */
 
 
9299
    assert(sbPtr->DynPtr);
 
 
9300
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
9301
 
 
 
9302
    DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
9303
 
 
 
9304
    /* first of all, validate this state: if the target suddenly becomes cloaked, then
 
 
9305
    we should switch immediately to wait state*/
 
 
9306
    if(!MarineCanSeeTarget(sbPtr))
 
 
9307
    {
 
 
9308
        /* .... and stop the sound */
 
 
9309
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
9310
        {
 
 
9311
            Sound_Stop(marineStatusPointer->soundHandle);        
 
 
9312
            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
9313
        }
 
 
9314
 
 
 
9315
    return SRC_Request_Wait;
 
 
9316
    }
 
 
9317
 
 
 
9318
    assert(marineStatusPointer->Target);
 
 
9319
    NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
 
 
9320
 
 
 
9321
    /* Fix weapon target! */
 
 
9322
    if (marineStatusPointer->My_Weapon->TargetCallibrationShift)
 
 
9323
    {
 
 
9324
        marineStatusPointer->weaponTarget.vx -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat11,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
9325
        marineStatusPointer->weaponTarget.vy -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat12,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
9326
        marineStatusPointer->weaponTarget.vz -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat13,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
9327
    }
 
 
9328
 
 
 
9329
    /* Here we must have a target.  Renew suspicion for new arrivals. */
 
 
9330
    if (!NpcSquad.Squad_Suspicion)
 
 
9331
        PointAlert(2, &marineStatusPointer->weaponTarget);
 
 
9332
 
 
 
9333
    /* Are we out of range? */
 
 
9334
    {
 
 
9335
        int range = VectorDistance(&marineStatusPointer->Target->DynPtr->Position, &sbPtr->DynPtr->Position);
 
 
9336
 
 
 
9337
        if ((marineStatusPointer->My_Weapon->MaxRange != -1) && (range >= marineStatusPointer->My_Weapon->MaxRange))
 
 
9338
        {
 
 
9339
            /* .... and stop the sound */
 
 
9340
            if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
9341
            {
 
 
9342
                Sound_Stop(marineStatusPointer->soundHandle);        
 
 
9343
                Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
9344
            }
 
 
9345
 
 
 
9346
        return SRC_Request_Approach;
 
 
9347
        }
 
 
9348
    }
 
 
9349
 
 
 
9350
    /* orientate to firing point first */
 
 
9351
    orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
 
 
9352
    orientationDirn.vy = 0;
 
 
9353
    orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
 
 
9354
    correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE);
 
 
9355
 
 
 
9356
    /* I have a cunning plan... */
 
 
9357
    {
 
 
9358
        DELTA_CONTROLLER *delta = Get_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta");
 
 
9359
 
 
 
9360
        if (delta && !DeltaAnimation_IsFinished(delta))
 
 
9361
            correctlyOrientated = 0;
 
 
9362
    }
 
 
9363
 
 
 
9364
    /* we are not correctly orientated to the target: this could happen because we have
 
 
9365
    just entered this state, or the target has moved during firing*/
 
 
9366
 
 
 
9367
    if(!correctlyOrientated || (marineStatusPointer->HModelController.Tweening != Controller_NoTweening))
 
 
9368
    {
 
 
9369
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
9370
            Sound_Stop(marineStatusPointer->soundHandle);
 
 
9371
 
 
 
9372
    return SRC_No_Change;
 
 
9373
    }
 
 
9374
 
 
 
9375
    if (human_in_los(sbPtr))
 
 
9376
    {
 
 
9377
        marineStatusPointer->Courage -= ONE_FIXED >> 3;
 
 
9378
        //marineStatusPointer->HModelController.Playing = 0;
 
 
9379
        return ((FastRandom() & 127) > 10) ?  SRC_Request_Approach : SRC_Request_Avoidance; 
 
 
9380
    }
 
 
9381
 
 
 
9382
    /* at this point we are correctly orientated: if we have no gunflash yet,
 
 
9383
    and our state timer is set to marine_near_firetime then we have either
 
 
9384
    just started firing, or have become dis-orienated between bursts. This is a good
 
 
9385
    time to consider firing a grenade... */
 
 
9386
 
 
 
9387
    /* No grenades with FT. */
 
 
9388
 
 
 
9389
    /* look after the sound */
 
 
9390
    if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
9391
    {
 
 
9392
        Sound_Update3d(marineStatusPointer->soundHandle,&(sbPtr->DynPtr->Position));
 
 
9393
    }
 
 
9394
    else 
 
 
9395
    { 
 
 
9396
        /* SID_INCIN_LOOP? */
 
 
9397
        Sound_Play(marineStatusPointer->My_Weapon->StartSound, "d", &sbPtr->DynPtr->Position);
 
 
9398
        Sound_Play(marineStatusPointer->My_Weapon->LoopSound, "del", &sbPtr->DynPtr->Position,
&marineStatusPointer->soundHandle);
 
 
9399
    }
 
 
9400
 
 
 
9401
    marineStatusPointer->stateTimer -= NormalFrameTime;
 
 
9402
 
 
 
9403
    MarineFireFlameThrower(sbPtr);
 
 
9404
 
 
 
9405
    /* Lighting? */
 
 
9406
    if (sbPtr->DisplayBlock)
 
 
9407
        AddLightingEffectToObject(sbPtr->DisplayBlock, LFX_MUZZLEFLASH);
 
 
9408
 
 
 
9409
    if (marineStatusPointer->clipammo > 0)
 
 
9410
    {
 
 
9411
        marineStatusPointer->clipammo -= NormalFrameTime;
 
 
9412
 
 
 
9413
        if (marineStatusPointer->clipammo <= 0)
 
 
9414
            Marine_Enter_Reload_State(sbPtr);
 
 
9415
    }
 
 
9416
 
 
 
9417
    if(marineStatusPointer->stateTimer > 0)
 
 
9418
        return SRC_No_Change;
 
 
9419
 
 
 
9420
    /* we are far enough away, so return to approach */
 
 
9421
 
 
 
9422
    DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
9423
 
 
 
9424
    /* .... and stop the sound */
 
 
9425
    if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
9426
    {
 
 
9427
        Sound_Stop(marineStatusPointer->soundHandle);        
 
 
9428
        Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
9429
    }
 
 
9430
 
 
 
9431
return SRC_Request_Approach;
 
 
9432
}
 
 
9433
 
 
 
9434
/* Should return between 0 and ONE_FIXED... */
 
 
9435
static int SpeedRangeMods(VECTORCH *range, VECTORCH *speed)
 
 
9436
{
 
 
9437
    int magrange = Approximate3dMagnitude(range);
 
 
9438
    int rmod = magrange >> 2;
 
 
9439
    int magspeed = Approximate3dMagnitude(speed);
 
 
9440
    int dot = abs(DotProduct(range, speed));
 
 
9441
 
 
 
9442
    int ab = MUL_FIXED(magrange, magspeed);
 
 
9443
 
 
 
9444
    ab <<= 1;
 
 
9445
 
 
 
9446
    if (!ab)
 
 
9447
        dot = 0;
 
 
9448
    else
 
 
9449
        dot = DIV_FIXED(dot, ab);
 
 
9450
 
 
 
9451
    if (dot > ONE_FIXED)
 
 
9452
    {
 
 
9453
        dot = ONE_FIXED;
 
 
9454
        /* Well, I suppose it could happen. */
 
 
9455
        /* Accuracy errors... */
 
 
9456
        assert(dot <= ONE_FIXED);    
 
 
9457
    }
 
 
9458
 
 
 
9459
    int theta = ArcCos(dot);
 
 
9460
    int sinthet = GetSin(theta);
 
 
9461
 
 
 
9462
    dot = WideMulNarrowDiv(sinthet, magspeed, magrange);
 
 
9463
 
 
 
9464
    dot <<= 3;
 
 
9465
 
 
 
9466
return (dot + rmod);    
 
 
9467
}
 
 
9468
 
 
 
9469
static int VerifyHitShot(STRATEGYBLOCK *shooter, STRATEGYBLOCK *target, VECTORCH *muzzlepos, VECTORCH *in_shotvector, enum AMMO_ID AmmoID, int multiple) 
 
 
9470
{
 
 
9471
        DISPLAYBLOCK *target_dptr = target ? target->DisplayBlock : NULL;
 
 
9472
        VECTORCH shotVector = *in_shotvector;
 
 
9473
 
 
 
9474
        Normalise(&shotVector);
 
 
9475
 
 
 
9476
        FindPolygonInLineOfSight(&shotVector, muzzlepos, 0, shooter->DisplayBlock);
 
 
9477
 
 
 
9478
        if (LOS_ObjectHitPtr)
 
 
9479
    {
 
 
9480
        #if DEBUG
 
 
9481
                if (LOS_HModel_Section && LOS_ObjectHitPtr->ObStrategyBlock && LOS_ObjectHitPtr->ObStrategyBlock->DisplayBlock)
 
 
9482
        {
 
 
9483
            assert(LOS_ObjectHitPtr->ObStrategyBlock->DisplayBlock->HModelControlBlock == LOS_HModel_Section->my_controller);
 
 
9484
                }
 
 
9485
        #endif
 
 
9486
 
 
 
9487
        if (LOS_ObjectHitPtr == target_dptr)
 
 
9488
            return 1;
 
 
9489
 
 
 
9490
        HandleWeaponImpact(&LOS_Point, LOS_ObjectHitPtr->ObStrategyBlock, AmmoID, &shotVector, multiple * ONE_FIXED, LOS_HModel_Section);
 
 
9491
        }
 
 
9492
 
 
 
9493
return 0;
 
 
9494
}
 
 
9495
 
 
 
9496
static void CastLOSProjectile(STRATEGYBLOCK *sbPtr, VECTORCH *muzzlepos, VECTORCH *in_shotvector, enum AMMO_ID AmmoID, int multiple, int inaccurate)
 
 
9497
{
 
 
9498
        VECTORCH shotVector = *in_shotvector;
 
 
9499
        Normalise(&shotVector);
 
 
9500
 
 
 
9501
        if (inaccurate)
 
 
9502
    {
 
 
9503
                shotVector.vx += ((FastRandom()%(ONE_FIXED>>2))-(ONE_FIXED>>3));
 
 
9504
                shotVector.vy += ((FastRandom()%(ONE_FIXED>>2))-(ONE_FIXED>>3));
 
 
9505
                shotVector.vz += ((FastRandom()%(ONE_FIXED>>2))-(ONE_FIXED>>3));
 
 
9506
                Normalise(&shotVector);
 
 
9507
        }
 
 
9508
 
 
 
9509
        FindPolygonInLineOfSight(&shotVector, muzzlepos, 0, sbPtr->DisplayBlock);
 
 
9510
 
 
 
9511
        if (LOS_ObjectHitPtr)
 
 
9512
    {
 
 
9513
        #if DEBUG
 
 
9514
        if (LOS_HModel_Section && LOS_ObjectHitPtr->ObStrategyBlock && LOS_ObjectHitPtr->ObStrategyBlock->DisplayBlock)
 
 
9515
        {
 
 
9516
            assert(LOS_ObjectHitPtr->ObStrategyBlock->DisplayBlock->HModelControlBlock == LOS_HModel_Section->my_controller);
 
 
9517
        }
 
 
9518
        #endif
 
 
9519
 
 
 
9520
        /* this fn needs updating to take amount of damage into account etc. */
 
 
9521
        HandleWeaponImpact(&LOS_Point, LOS_ObjectHitPtr->ObStrategyBlock, AmmoID, &shotVector, multiple * ONE_FIXED, LOS_HModel_Section);
 
 
9522
        }
 
 
9523
}
 
 
9524
 
 
 
9525
/* Project actual shot? */
 
 
9526
static void ProjectNPCShot(STRATEGYBLOCK *sbPtr, STRATEGYBLOCK *target, VECTORCH *muzzlepos, MATRIXCH *muzzleorient, enum AMMO_ID AmmoID, int multiple)
 
 
9527
{
 
 
9528
    VECTORCH shotVector;  /* direction of view-line */
 
 
9529
    VECTORCH targetPos;
 
 
9530
 
 
 
9531
    GetTargetingPointOfObject_Far(target, &targetPos);
 
 
9532
 
 
 
9533
    shotVector.vx = targetPos.vx - muzzlepos->vx;
 
 
9534
    shotVector.vy = targetPos.vy - muzzlepos->vy;
 
 
9535
    shotVector.vz = targetPos.vz - muzzlepos->vz;
 
 
9536
 
 
 
9537
    int mag = Approximate3dMagnitude(&shotVector);
 
 
9538
 
 
 
9539
    shotVector.vx = MUL_FIXED(muzzleorient->mat31,mag);
 
 
9540
    shotVector.vy = MUL_FIXED(muzzleorient->mat32,mag);
 
 
9541
    shotVector.vz = MUL_FIXED(muzzleorient->mat33,mag);
 
 
9542
 
 
 
9543
    mag >>= 2; /* For now. */
 
 
9544
 
 
 
9545
    shotVector.vx += ((FastRandom()%mag) - (mag>>1));
 
 
9546
    shotVector.vy += ((FastRandom()%mag) - (mag>>1));
 
 
9547
    shotVector.vz += ((FastRandom()%mag) - (mag>>1));
 
 
9548
 
 
 
9549
    Normalise(&shotVector);
 
 
9550
 
 
 
9551
    FindPolygonInLineOfSight_TwoIgnores(&shotVector, muzzlepos, 0, sbPtr->DisplayBlock, target->DisplayBlock);
 
 
9552
 
 
 
9553
    if (LOS_ObjectHitPtr)
 
 
9554
    {
 
 
9555
        #if DEBUG
 
 
9556
        if (LOS_HModel_Section && LOS_ObjectHitPtr->ObStrategyBlock && LOS_ObjectHitPtr->ObStrategyBlock->DisplayBlock)
 
 
9557
        {
 
 
9558
            assert(LOS_ObjectHitPtr->ObStrategyBlock->DisplayBlock->HModelControlBlock == LOS_HModel_Section->my_controller);
 
 
9559
        }
 
 
9560
        #endif
 
 
9561
 
 
 
9562
        /* this fn needs updating to take amount of damage into account etc. */
 
 
9563
        HandleWeaponImpact(&LOS_Point, LOS_ObjectHitPtr->ObStrategyBlock, AmmoID, &shotVector, multiple * ONE_FIXED, LOS_HModel_Section);
 
 
9564
    }
 
 
9565
}
 
 
9566
 
 
 
9567
static void DischargeLOSWeapon_Core(STRATEGYBLOCK *sbPtr)
 
 
9568
{
 
 
9569
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
9570
    int hitroll = marineStatusPointer->Skill;
 
 
9571
 
 
 
9572
    if (marineStatusPointer->Target)
 
 
9573
    {
 
 
9574
        VECTORCH relPos,relPos2;
 
 
9575
        relPos.vx = marineStatusPointer->Target->DynPtr->Position.vx - sbPtr->DynPtr->Position.vx;
 
 
9576
        relPos.vy = marineStatusPointer->Target->DynPtr->Position.vy - sbPtr->DynPtr->Position.vy;
 
 
9577
        relPos.vz = marineStatusPointer->Target->DynPtr->Position.vz - sbPtr->DynPtr->Position.vz;
 
 
9578
 
 
 
9579
        relPos2.vx = marineStatusPointer->Target->DynPtr->Position.vx - marineStatusPointer->Target->DynPtr->PrevPosition.vx;
 
 
9580
        relPos2.vy = marineStatusPointer->Target->DynPtr->Position.vy - marineStatusPointer->Target->DynPtr->PrevPosition.vy;
 
 
9581
        relPos2.vz = marineStatusPointer->Target->DynPtr->Position.vz - marineStatusPointer->Target->DynPtr->PrevPosition.vz;
 
 
9582
 
 
 
9583
        //range = VectorDistance(&marineStatusPointer->Target->DynPtr->Position, &sbPtr->DynPtr->Position);
 
 
9584
        switch(marineStatusPointer->Target->type)
 
 
9585
        {
 
 
9586
            case I_BehaviourPredatorPlayer:
 
 
9587
            case I_BehaviourAlienPlayer:
 
 
9588
                /* Vs the player, lighting effects on aliens and cloaked preds. */
 
 
9589
                hitroll = MUL_FIXED(hitroll, ((PlayerStatus.CurrentLightAtPlayer >> 1) + 32767));
 
 
9590
            default:
 
 
9591
            break;
 
 
9592
        }
 
 
9593
 
 
 
9594
        hitroll -= SpeedRangeMods(&relPos, &relPos2);
 
 
9595
    }
 
 
9596
 
 
 
9597
    MaintainMarineGunFlash(sbPtr);
 
 
9598
 
 
 
9599
    /* look after the sound */
 
 
9600
    if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
9601
    {
 
 
9602
        Sound_Update3d(marineStatusPointer->soundHandle, &sbPtr->DynPtr->Position);
 
 
9603
    }
 
 
9604
    else 
 
 
9605
    { 
 
 
9606
        Sound_Play(marineStatusPointer->My_Weapon->StartSound, "d", &sbPtr->DynPtr->Position);
 
 
9607
        Sound_Play(marineStatusPointer->My_Weapon->LoopSound, "del", &sbPtr->DynPtr->Position,
&marineStatusPointer->soundHandle);
 
 
9608
    }
 
 
9609
 
 
 
9610
    marineStatusPointer->stateTimer -= NormalFrameTime;
 
 
9611
 
 
 
9612
    /* Volleysize is now rounds fired this state. */
 
 
9613
 
 
 
9614
    int volleytime = marineStatusPointer->My_Weapon->FiringTime - marineStatusPointer->stateTimer;
 
 
9615
    /* It was that or reverse the state timer for this state. */
 
 
9616
    int volleyrounds = MUL_FIXED(volleytime, marineStatusPointer->My_Weapon->FiringRate);
 
 
9617
    volleyrounds >>= ONE_FIXED_SHIFT;
 
 
9618
    volleyrounds -= marineStatusPointer->volleySize;
 
 
9619
    marineStatusPointer->volleySize += volleyrounds;
 
 
9620
 
 
 
9621
    assert(volleyrounds >= 0);
 
 
9622
 
 
 
9623
    /* We're counting ammo. */
 
 
9624
    if (volleyrounds > marineStatusPointer->clipammo)
 
 
9625
        volleyrounds = marineStatusPointer->clipammo;
 
 
9626
 
 
 
9627
    marineStatusPointer->clipammo -= volleyrounds;
 
 
9628
 
 
 
9629
    marineStatusPointer->roundsForThisTarget += volleyrounds;
 
 
9630
 
 
 
9631
    /* Now hit the target with volleyrounds bullets. */
 
 
9632
 
 
 
9633
    hitroll += marineStatusPointer->My_Weapon->Accuracy;
 
 
9634
 
 
 
9635
    /* Here we go... */
 
 
9636
    {
 
 
9637
        #define SUSTAINMOD (ONE_FIXED >> 3)
 
 
9638
        int hits = 0;
 
 
9639
        int a = 0;
 
 
9640
 
 
 
9641
        for (; a < volleyrounds; a++)
 
 
9642
        {
 
 
9643
            int realhitroll = hitroll;
 
 
9644
 
 
 
9645
            if (marineStatusPointer->lastroundhit)
 
 
9646
                realhitroll += SUSTAINMOD;
 
 
9647
 
 
 
9648
            if (marineStatusPointer->Target)
 
 
9649
            {
 
 
9650
                if (marineStatusPointer->lasthitsection)
 
 
9651
                {
 
 
9652
                    if ((marineStatusPointer->lasthitsection->flags & section_data_notreal) || (marineStatusPointer->lasthitsection->flags &
section_data_terminate_here))
 
 
9653
                    {
 
 
9654
                        /* Invalid. */
 
 
9655
                        marineStatusPointer->lasthitsection = NULL;
 
 
9656
                    }
 
 
9657
                    else if(marineStatusPointer->Target->DisplayBlock)
 
 
9658
                    {
 
 
9659
                        HMODELCONTROLLER *tctrl = marineStatusPointer->Target->DisplayBlock->HModelControlBlock;
 
 
9660
                        /* Verify this section is valid? */
 
 
9661
 
 
 
9662
                        if ( (tctrl != NULL) && (tctrl != marineStatusPointer->lasthitsection->my_controller))
 
 
9663
                            marineStatusPointer->lasthitsection = NULL; // Invalid.
 
 
9664
                    }
 
 
9665
                }
 
 
9666
 
 
 
9667
                if ( !marineStatusPointer->lastroundhit || (marineStatusPointer->lasthitsection == NULL))
 
 
9668
                    marineStatusPointer->lasthitsection = HitLocationRoll(marineStatusPointer->Target, sbPtr);
 
 
9669
            }
 
 
9670
 
 
 
9671
            marineStatusPointer->lastroundhit = 0;
 
 
9672
 
 
 
9673
            if ((FastRandom() & 65535) < realhitroll)
 
 
9674
            {
 
 
9675
                if (marineStatusPointer->Target)
 
 
9676
                    hits++;
 
 
9677
 
 
 
9678
                marineStatusPointer->lastroundhit = 1;
 
 
9679
            }
 
 
9680
        }
 
 
9681
 
 
 
9682
        /* Handle Damage. */
 
 
9683
        {
 
 
9684
 
 
 
9685
            VECTORCH shotvector = {0, 0, 65535};
 
 
9686
            RotateVector(&shotvector, &marineStatusPointer->My_Gunflash_Section->SecMat);
 
 
9687
 
 
 
9688
            if (hits)
 
 
9689
            {
 
 
9690
                if (VerifyHitShot(sbPtr, marineStatusPointer->Target, &marineStatusPointer->My_Gunflash_Section->World_Offset, &shotvector,
marineStatusPointer->My_Weapon->Ammo_Type, hits))
 
 
9691
                {
 
 
9692
                    VECTORCH rel_pos;
 
 
9693
                    VECTORCH attack_dir;
 
 
9694
                    rel_pos.vx = marineStatusPointer->Target->DynPtr->Position.vx - sbPtr->DynPtr->Position.vx;
 
 
9695
                    rel_pos.vy = marineStatusPointer->Target->DynPtr->Position.vy - sbPtr->DynPtr->Position.vy;
 
 
9696
                    rel_pos.vz = marineStatusPointer->Target->DynPtr->Position.vz - sbPtr->DynPtr->Position.vz;
 
 
9697
 
 
 
9698
                    /* If 0, hits have been dealt with. */
 
 
9699
                    GetDirectionOfAttack(marineStatusPointer->Target, &rel_pos, &attack_dir);
 
 
9700
 
 
 
9701
                    if (marineStatusPointer->lasthitsection)
 
 
9702
                    {
 
 
9703
CauseDamageToHModel(marineStatusPointer->lasthitsection->my_controller, marineStatusPointer->Target,
&TemplateAmmo[marineStatusPointer->My_Weapon->Ammo_Type].MaxDamage, ONE_FIXED * hits, marineStatusPointer->lasthitsection, &attack_dir, NULL,
0);
 
 
9704
                    }
 
 
9705
                    else
 
 
9706
                    {
 
 
9707
                        CauseDamageToObject(marineStatusPointer->Target, &TemplateAmmo[marineStatusPointer->My_Weapon->Ammo_Type].MaxDamage,
ONE_FIXED * hits, &attack_dir);
 
 
9708
                    }
 
 
9709
                }
 
 
9710
            }
 
 
9711
 
 
 
9712
            if ((volleyrounds - hits) > 0)
 
 
9713
            {
 
 
9714
                assert(marineStatusPointer->My_Gunflash_Section);
 
 
9715
 
 
 
9716
                if (marineStatusPointer->Target)
 
 
9717
                {
 
 
9718
                    ProjectNPCShot(sbPtr, marineStatusPointer->Target, &marineStatusPointer->My_Gunflash_Section->World_Offset,
 
 
9719
                    &marineStatusPointer->My_Gunflash_Section->SecMat, marineStatusPointer->My_Weapon->Ammo_Type, (volleyrounds - hits));
 
 
9720
                }
 
 
9721
                else
 
 
9722
                {
 
 
9723
                    /* Like a miss, so it's inaccurate. */
 
 
9724
                    CastLOSProjectile(sbPtr, &marineStatusPointer->My_Gunflash_Section->World_Offset, &shotvector,
marineStatusPointer->My_Weapon->Ammo_Type, volleyrounds, 1);
 
 
9725
                }
 
 
9726
            }
 
 
9727
        }
 
 
9728
    }
 
 
9729
}
 
 
9730
 
 
 
9731
static STATE_RETURN_CONDITION unarmed_weapon_func(STRATEGYBLOCK *sbPtr)
 
 
9732
{
 
 
9733
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
9734
    marineStatusPointer->behaviourState = MBS_Waiting;
 
 
9735
    marineStatusPointer->behaviourState = MBS_Retreating;
 
 
9736
    marineStatusPointer->Target = NULL;
 
 
9737
    return SRC_No_Change;
 
 
9738
}
 
 
9739
 
 
 
9740
static STATE_RETURN_CONDITION Execute_MNS_DischargePulserifle(STRATEGYBLOCK *sbPtr)
 
 
9741
{
 
 
9742
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
9743
 
 
 
9744
    marineStatusPointer->HModelController.Playing = 1;
 
 
9745
 
 
 
9746
    //sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
9747
 
 
 
9748
    /* first of all, validate this state: if the target suddenly becomes cloaked, then we should switch immediately to wait state*/
 
 
9749
/*
 
 
9750
    if (marineStatusPointer->volleySize < marineStatusPointer->My_Weapon->MinimumBurstSize)
 
 
9751
    {
 
 
9752
        // Keep firing!
 
 
9753
    }
 
 
9754
    else
 
 
9755
        EndMarineMuzzleFlash(sbPtr, marineStatusPointer);
 
 
9756
 
 
 
9757
    else if(!MarineCanSeeTarget(sbPtr) && 0)
 
 
9758
    {
 
 
9759
        marineStatusPointer->lastroundhit = 0;
 
 
9760
        marineStatusPointer->lasthitsection = NULL;
 
 
9761
        return SRC_Request_Wait;
 
 
9762
    }
 
 
9763
*/
 
 
9764
 
 
 
9765
    if (marineStatusPointer->Target)
 
 
9766
    {
 
 
9767
        NPCGetTargetPosition(&marineStatusPointer->weaponTarget, marineStatusPointer->Target);
 
 
9768
        /* Fix weapon target! */
 
 
9769
 
 
 
9770
        if (marineStatusPointer->My_Weapon->TargetCallibrationShift)
 
 
9771
        {
 
 
9772
            marineStatusPointer->weaponTarget.vx -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat11,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
9773
            marineStatusPointer->weaponTarget.vy -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat12,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
9774
            marineStatusPointer->weaponTarget.vz -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat13,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
9775
        }
 
 
9776
 
 
 
9777
        /* Here we must have a target.  Renew suspicion for new arrivals. */
 
 
9778
        if (!NpcSquad.Squad_Suspicion)
 
 
9779
            PointAlert(2, &marineStatusPointer->weaponTarget);
 
 
9780
    }
 
 
9781
    /* Otherwise, stay facing the same way. */
 
 
9782
 
 
 
9783
    /* orientate to firing point first */
 
 
9784
    VECTORCH orientationDirn;
 
 
9785
    orientationDirn.vx = marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
 
 
9786
    orientationDirn.vy = 0;
 
 
9787
    orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
 
 
9788
    int correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE);
 
 
9789
 
 
 
9790
    /* I have a cunning plan... */
 
 
9791
    {
 
 
9792
        DELTA_CONTROLLER *delta = Get_Delta_Sequence(&marineStatusPointer->HModelController, "HitDelta");
 
 
9793
 
 
 
9794
        if (delta && !DeltaAnimation_IsFinished(delta))
 
 
9795
            correctlyOrientated = 0;
 
 
9796
    }
 
 
9797
 
 
 
9798
    /* I have another cunning plan... */
 
 
9799
    if ((marineStatusPointer->volleySize > 0) && (marineStatusPointer->volleySize < marineStatusPointer->My_Weapon->MinimumBurstSize))
 
 
9800
            correctlyOrientated = 1;
 
 
9801
 
 
 
9802
    /* we are not correctly orientated to the target: this could happen because we have
 
 
9803
    just entered this state, or the target has moved during firing*/
 
 
9804
 
 
 
9805
    if(!correctlyOrientated || (marineStatusPointer->HModelController.Tweening != Controller_NoTweening))
 
 
9806
    {
 
 
9807
        /* stop visual and audio cues: technically, we're not firing at this moment */
 
 
9808
        marineStatusPointer->lastroundhit = 0;
 
 
9809
        marineStatusPointer->lasthitsection = NULL;
 
 
9810
        return SRC_No_Change;
 
 
9811
    }
 
 
9812
 
 
 
9813
    if (human_in_los(sbPtr))
 
 
9814
    {
 
 
9815
        marineStatusPointer->Courage += MUL_FIXED(NormalFrameTime, 300);
 
 
9816
        return ((FastRandom() & 127) > 10) ?  SRC_Request_Approach : SRC_Request_Avoidance; 
 
 
9817
    }
 
 
9818
 
 
 
9819
    int range;
 
 
9820
 
 
 
9821
    if (marineStatusPointer->Target)
 
 
9822
    {
 
 
9823
        range = VectorDistance(&marineStatusPointer->Target->DynPtr->Position, &sbPtr->DynPtr->Position);
 
 
9824
 
 
 
9825
        if ((marineStatusPointer->myGunFlash == NULL) && (marineStatusPointer->stateTimer == MARINE_NEAR_FIRE_TIME))
 
 
9826
        {
 
 
9827
            if (range > MARINE_TOO_CLOSE_TO_GRENADE_FOOL)
 
 
9828
            {
 
 
9829
                if (!marineStatusPointer->IAmCrouched && !(FastRandom() & MARINE_CHANCEOFGRENADE))
 
 
9830
                {
 
 
9831
                    NPCGetTargetPosition(&marineStatusPointer->weaponTarget, marineStatusPointer->Target);
 
 
9832
 
 
 
9833
                    if((sbPtr->DynPtr->Position.vy - marineStatusPointer->weaponTarget.vy) > 2500)
 
 
9834
                    {
 
 
9835
                        /* too high */
 
 
9836
                    }
 
 
9837
                    else
 
 
9838
                    {
 
 
9839
                        InitialisePulseGrenadeBehaviour(&marineStatusPointer->My_Gunflash_Section->World_Offset,
&marineStatusPointer->My_Gunflash_Section->SecMat);
 
 
9840
                        marineStatusPointer->stateTimer = MARINE_NEAR_TIMEBETWEENFIRING;
 
 
9841
                        marineStatusPointer->volleySize = 0;
 
 
9842
 
 
 
9843
                        if((FastRandom() & 127) < 10)
 
 
9844
                        Marine_Enter_Taunt_State(sbPtr);
 
 
9845
                    }
 
 
9846
                }
 
 
9847
            }
 
 
9848
        }
 
 
9849
 
 
 
9850
        DischargeLOSWeapon_Core(sbPtr);
 
 
9851
 
 
 
9852
        if (marineStatusPointer->clipammo <= 0)
 
 
9853
            Marine_Enter_Reload_State(sbPtr);
 
 
9854
 
 
 
9855
        if (NPC_IsDead(marineStatusPointer->Target))
 
 
9856
        {
 
 
9857
            marineStatusPointer->Target = Marine_GetNewTarget(&sbPtr->DynPtr->Position, sbPtr);
 
 
9858
 
 
 
9859
            if(NULL == marineStatusPointer->Target)
 
 
9860
            {
 
 
9861
                if ((marineStatusPointer->volleySize >= marineStatusPointer->My_Weapon->MinimumBurstSize))
 
 
9862
                {
 
 
9863
                    /* Huzzah! */
 
 
9864
                    marineStatusPointer->lastroundhit = 0;
 
 
9865
                    marineStatusPointer->lasthitsection = NULL;
 
 
9866
 
 
 
9867
                    if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
9868
                    {
 
 
9869
                        Sound_Stop(marineStatusPointer->soundHandle);
 
 
9870
                        Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
9871
                    }
 
 
9872
 
 
 
9873
                    Marine_Enter_Taunt_State(sbPtr);
 
 
9874
                }
 
 
9875
 
 
 
9876
                return SRC_No_Change;
 
 
9877
            }
 
 
9878
 
 
 
9879
            return SRC_Request_Wait;
 
 
9880
        }
 
 
9881
    }
 
 
9882
 
 
 
9883
    if(marineStatusPointer->stateTimer > 0)
 
 
9884
        return SRC_No_Change;
 
 
9885
 
 
 
9886
    if(range < MARINE_CLOSE_APPROACH_DISTANCE)
 
 
9887
    {
 
 
9888
        /* renew firing, as we are still too close to approach */ 
 
 
9889
        marineStatusPointer->stateTimer = marineStatusPointer->My_Weapon->FiringTime;                     
 
 
9890
        marineStatusPointer->volleySize = 0;
 
 
9891
        NPCGetTargetPosition(&marineStatusPointer->weaponTarget, marineStatusPointer->Target);
 
 
9892
        /* stop visual and audio cues: technically, we're not firing at this moment */
 
 
9893
 
 
 
9894
        marineStatusPointer->Courage -= ONE_FIXED >> 3;
 
 
9895
 
 
 
9896
        return SRC_Request_Fire;
 
 
9897
    }
 
 
9898
    else
 
 
9899
    {
 
 
9900
        return ((FastRandom() & 127) > 10) ?  SRC_No_Change : SRC_Request_Approach;
 
 
9901
    }
 
 
9902
}
 
 
9903
 
 
 
9904
static STATE_RETURN_CONDITION Execute_MNS_DischargeSmartgun(STRATEGYBLOCK *sbPtr)
 
 
9905
{
 
 
9906
    int range = 0;
 
 
9907
 
 
 
9908
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
9909
    marineStatusPointer->HModelController.Playing = 1;
 
 
9910
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
9911
 
 
 
9912
    /* first of all, validate this state: if the target suddenly becomes cloaked, then
 
 
9913
    we should switch immediately to wait state*/
 
 
9914
    if (marineStatusPointer->volleySize < marineStatusPointer->My_Weapon->MinimumBurstSize)
 
 
9915
    {
 
 
9916
        /* Keep firing! */
 
 
9917
        //jadda
 
 
9918
    }
 
 
9919
    else if(!MarineCanSeeTarget(sbPtr) && 0)
 
 
9920
    {
 
 
9921
        /* ... and remove the gunflash */
 
 
9922
        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
9923
 
 
 
9924
        /* .... and stop the sound */
 
 
9925
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
9926
        {
 
 
9927
            Sound_Stop(marineStatusPointer->soundHandle);        
 
 
9928
            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
9929
        }
 
 
9930
 
 
 
9931
        marineStatusPointer->lastroundhit = 0;
 
 
9932
        marineStatusPointer->lasthitsection = NULL;
 
 
9933
        //return SRC_Request_Wait;
 
 
9934
    }
 
 
9935
 
 
 
9936
    if (marineStatusPointer->clipammo <= 0)
 
 
9937
        Marine_Enter_Reload_State(sbPtr);
 
 
9938
 
 
 
9939
    if (marineStatusPointer->Target)
 
 
9940
    {
 
 
9941
        NPCGetTargetPosition(&marineStatusPointer->weaponTarget, marineStatusPointer->Target);
 
 
9942
 
 
 
9943
        /* Fix weapon target! */
 
 
9944
        if (marineStatusPointer->My_Weapon->TargetCallibrationShift)
 
 
9945
        {
 
 
9946
            marineStatusPointer->weaponTarget.vx -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat11,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
9947
            marineStatusPointer->weaponTarget.vy -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat12,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
9948
            marineStatusPointer->weaponTarget.vz -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat13,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
9949
        }
 
 
9950
 
 
 
9951
        /* Here we must have a target.  Renew suspicion for new arrivals. */
 
 
9952
        if (!NpcSquad.Squad_Suspicion)
 
 
9953
            PointAlert(2,&marineStatusPointer->weaponTarget);
 
 
9954
    }
 
 
9955
    /* Otherwise, stay facing the same way. */
 
 
9956
 
 
 
9957
    /* orientate to firing point first */
 
 
9958
    VECTORCH orientationDirn;
 
 
9959
    orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
 
 
9960
    orientationDirn.vy = 0;
 
 
9961
    orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
 
 
9962
    int correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE);
 
 
9963
 
 
 
9964
    /* I have a cunning plan... */
 
 
9965
    {
 
 
9966
        DELTA_CONTROLLER *delta = Get_Delta_Sequence(&marineStatusPointer->HModelController, "HitDelta");
 
 
9967
 
 
 
9968
        if (delta && !DeltaAnimation_IsFinished(delta))
 
 
9969
            correctlyOrientated = 0;
 
 
9970
    }
 
 
9971
 
 
 
9972
    /* I have another cunning plan... */
 
 
9973
    if ((marineStatusPointer->volleySize > 0) && (marineStatusPointer->volleySize < marineStatusPointer->My_Weapon->MinimumBurstSize))
 
 
9974
            correctlyOrientated = 1;
 
 
9975
 
 
 
9976
    /* we are not correctly orientated to the target: this could happen because we have
 
 
9977
    just entered this state, or the target has moved during firing*/
 
 
9978
    if(!correctlyOrientated || (marineStatusPointer->HModelController.Tweening != Controller_NoTweening))
 
 
9979
    {
 
 
9980
        /* stop visual and audio cues: technically, we're not firing at this moment */
 
 
9981
        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
9982
 
 
 
9983
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
9984
        {
 
 
9985
            Sound_Stop(marineStatusPointer->soundHandle);
 
 
9986
            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
9987
        }
 
 
9988
 
 
 
9989
        marineStatusPointer->lastroundhit = 0;
 
 
9990
        marineStatusPointer->lasthitsection = NULL;
 
 
9991
 
 
 
9992
        return SRC_No_Change;
 
 
9993
    }
 
 
9994
 
 
 
9995
    if (human_in_los(sbPtr))
 
 
9996
    {
 
 
9997
        //marineStatusPointer->Courage -= ONE_FIXED >> 3;
 
 
9998
        marineStatusPointer->Courage += MUL_FIXED(NormalFrameTime, 300);
 
 
9999
        //marineStatusPointer->HModelController.Playing = 0;
 
 
10000
        return ((FastRandom() & 127) > 10) ?  SRC_Request_Approach : SRC_Request_Avoidance; 
 
 
10001
    }
 
 
10002
 
 
 
10003
    if (marineStatusPointer->Target)
 
 
10004
        range = VectorDistance(&marineStatusPointer->Target->DynPtr->Position, &sbPtr->DynPtr->Position);
 
 
10005
 
 
 
10006
    {
 
 
10007
        MaintainMarineGunFlash(sbPtr);
 
 
10008
 
 
 
10009
        /* look after the sound */
 
 
10010
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
10011
        {
 
 
10012
            Sound_Update3d(marineStatusPointer->soundHandle, &sbPtr->DynPtr->Position);
 
 
10013
        }
 
 
10014
        else 
 
 
10015
        { 
 
 
10016
            Sound_Play(marineStatusPointer->My_Weapon->StartSound, "d", &sbPtr->DynPtr->Position);
 
 
10017
            Sound_Play(marineStatusPointer->My_Weapon->LoopSound, "del", &sbPtr->DynPtr->Position,
&marineStatusPointer->soundHandle);
 
 
10018
        }
 
 
10019
 
 
 
10020
        marineStatusPointer->stateTimer -= NormalFrameTime;
 
 
10021
 
 
 
10022
        /* Volleysize is now rounds fired this state. */
 
 
10023
 
 
 
10024
        int volleytime = marineStatusPointer->My_Weapon->FiringTime - marineStatusPointer->stateTimer;
 
 
10025
        /* It was that or reverse the state timer for this state. */
 
 
10026
        int volleyrounds = MUL_FIXED(volleytime, marineStatusPointer->My_Weapon->FiringRate);
 
 
10027
        volleyrounds >>= ONE_FIXED_SHIFT;
 
 
10028
 
 
 
10029
        volleyrounds -= marineStatusPointer->volleySize;
 
 
10030
        marineStatusPointer->volleySize += volleyrounds;
 
 
10031
 
 
 
10032
        assert(volleyrounds >= 0);
 
 
10033
 
 
 
10034
        if (marineStatusPointer->clipammo != -1)
 
 
10035
        {
 
 
10036
            /* We're counting ammo. */
 
 
10037
            if (volleyrounds>marineStatusPointer->clipammo)
 
 
10038
                volleyrounds = marineStatusPointer->clipammo;
 
 
10039
 
 
 
10040
            marineStatusPointer->clipammo-=volleyrounds;
 
 
10041
            assert(marineStatusPointer->clipammo >= 0);
 
 
10042
        }
 
 
10043
 
 
 
10044
        marineStatusPointer->roundsForThisTarget += volleyrounds;
 
 
10045
 
 
 
10046
        /* Now hit the target with volleyrounds bullets. */
 
 
10047
 
 
 
10048
        {
 
 
10049
            VECTORCH shotvector = { 0, 0, 65535 };
 
 
10050
            RotateVector(&shotvector, &marineStatusPointer->My_Gunflash_Section->SecMat);
 
 
10051
            CastLOSProjectile(sbPtr, &marineStatusPointer->My_Gunflash_Section->World_Offset, &shotvector,
marineStatusPointer->My_Weapon->Ammo_Type, volleyrounds, 0);
 
 
10052
        }
 
 
10053
    }
 
 
10054
 
 
 
10055
    if (marineStatusPointer->Target == NULL)
 
 
10056
        return SRC_No_Change; /* Getting out of here! */
 
 
10057
 
 
 
10058
    /* Did we get him? */
 
 
10059
    if (NPC_IsDead(marineStatusPointer->Target) && (marineStatusPointer->volleySize >= marineStatusPointer->My_Weapon->MinimumBurstSize))
 
 
10060
    {
 
 
10061
        marineStatusPointer->Target = Marine_GetNewTarget(&sbPtr->DynPtr->Position,sbPtr);
 
 
10062
 
 
 
10063
        if (MarineRetreatsInTheFaceOfDanger(sbPtr) && (NULL == marineStatusPointer->Target))
 
 
10064
        {
 
 
10065
            /* Huzzah! */
 
 
10066
            DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
10067
 
 
 
10068
            if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
10069
            {
 
 
10070
                Sound_Stop(marineStatusPointer->soundHandle);
 
 
10071
                Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
10072
            }
 
 
10073
 
 
 
10074
            marineStatusPointer->lastroundhit = 0;
 
 
10075
            marineStatusPointer->lasthitsection = NULL;
 
 
10076
            Marine_Enter_Taunt_State(sbPtr);
 
 
10077
        }
 
 
10078
    }
 
 
10079
 
 
 
10080
    if(marineStatusPointer->stateTimer > 0)
 
 
10081
        return SRC_No_Change;
 
 
10082
 
 
 
10083
    if(range < MARINE_CLOSE_APPROACH_DISTANCE * 2)
 
 
10084
    {
 
 
10085
        /* renew firing, as we are still too close to approach */ 
 
 
10086
        marineStatusPointer->stateTimer = marineStatusPointer->My_Weapon->FiringTime;                     
 
 
10087
        marineStatusPointer->volleySize = 0;
 
 
10088
        NPCGetTargetPosition(&marineStatusPointer->weaponTarget, marineStatusPointer->Target);
 
 
10089
        /* stop visual and audio cues: technically, we're not firing at this moment */
 
 
10090
        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
10091
 
 
 
10092
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
10093
        {
 
 
10094
            Sound_Stop(marineStatusPointer->soundHandle);
 
 
10095
            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
10096
        }
 
 
10097
 
 
 
10098
        if (!marineStatusPointer->Android)
 
 
10099
            marineStatusPointer->Courage -= (ONE_FIXED>>3);
 
 
10100
 
 
 
10101
        return SRC_Request_Fire;
 
 
10102
    }
 
 
10103
    else
 
 
10104
    {
 
 
10105
        /* we are far enough away, so return to approach */
 
 
10106
 
 
 
10107
        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
10108
 
 
 
10109
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
10110
        {
 
 
10111
            Sound_Stop(marineStatusPointer->soundHandle);        
 
 
10112
            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
10113
        }
 
 
10114
 
 
 
10115
        return SRC_Request_Approach;
 
 
10116
    }
 
 
10117
 
 
 
10118
return SRC_No_Change;
 
 
10119
}
 
 
10120
 
 
 
10121
static STATE_RETURN_CONDITION Execute_MNS_DischargeShotgun(STRATEGYBLOCK *sbPtr)
 
 
10122
{
 
 
10123
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
10124
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
10125
 
 
 
10126
    /* first of all, validate this state: if the target suddenly becomes cloaked, then
 
 
10127
    we should switch immediately to wait state.*/
 
 
10128
 
 
 
10129
if(0)
 
 
10130
    if(!MarineCanSeeTarget(sbPtr))
 
 
10131
    {
 
 
10132
        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
10133
 
 
 
10134
        /* .... and stop the sound */
 
 
10135
        if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX)
 
 
10136
        {
 
 
10137
            Sound_Stop(marineStatusPointer->soundHandle);        
 
 
10138
            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
10139
        }
 
 
10140
 
 
 
10141
        return SRC_Request_Wait;
 
 
10142
    }
 
 
10143
 
 
 
10144
    if (!marineStatusPointer->clipammo)
 
 
10145
        Marine_Enter_Reload_State(sbPtr);
 
 
10146
 
 
 
10147
    /* Here we must have a target.  Renew suspicion for new arrivals. */
 
 
10148
    if (!NpcSquad.Squad_Suspicion)
 
 
10149
        PointAlert(2,&marineStatusPointer->weaponTarget);
 
 
10150
 
 
 
10151
    /* Deal with tweening part. */
 
 
10152
    if (marineStatusPointer->internalState)
 
 
10153
    {
 
 
10154
        if (marineStatusPointer->HModelController.Tweening == Controller_NoTweening)
 
 
10155
        {
 
 
10156
            marineStatusPointer->HModelController.Playing = 0;
 
 
10157
            marineStatusPointer->HModelController.sequence_timer = 0;
 
 
10158
            marineStatusPointer->internalState = 0;
 
 
10159
        }
 
 
10160
 
 
 
10161
        return SRC_No_Change;
 
 
10162
    }
 
 
10163
 
 
 
10164
    if (!marineStatusPointer->HModelController.Playing)
 
 
10165
    {
 
 
10166
        /* Only terminate if you haven't fired yet... */
 
 
10167
        if(!MarineCanSeeTarget(sbPtr))
 
 
10168
        {
 
 
10169
            DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
10170
 
 
 
10171
            /* .... and stop the sound */
 
 
10172
            if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
10173
            {
 
 
10174
                Sound_Stop(marineStatusPointer->soundHandle);        
 
 
10175
                Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
10176
            }
 
 
10177
 
 
 
10178
            return SRC_Request_Wait;
 
 
10179
        }
 
 
10180
 
 
 
10181
        assert(marineStatusPointer->Target);
 
 
10182
        NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
 
 
10183
        /* Fix weapon target! */
 
 
10184
        if (marineStatusPointer->My_Weapon->TargetCallibrationShift)
 
 
10185
        {
 
 
10186
            marineStatusPointer->weaponTarget.vx -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat11,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
10187
            marineStatusPointer->weaponTarget.vy -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat12,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
10188
            marineStatusPointer->weaponTarget.vz -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat13,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
10189
        }
 
 
10190
{
 
 
10191
        /* orientate to firing point first */
 
 
10192
        VECTORCH orientationDirn;
 
 
10193
 
 
 
10194
        orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
 
 
10195
        orientationDirn.vy = 0;
 
 
10196
        orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
 
 
10197
        int correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE);
 
 
10198
 
 
 
10199
        /* we are not correctly orientated to the target: this could happen because we have
 
 
10200
        just entered this state, or the target has moved during firing*/
 
 
10201
        if(!correctlyOrientated || (marineStatusPointer->HModelController.Tweening != Controller_NoTweening))
 
 
10202
        {
 
 
10203
            /* stop visual and audio cues: technically, we're not firing at this moment */
 
 
10204
            DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
10205
 
 
 
10206
            if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
10207
            {
 
 
10208
                Sound_Stop(marineStatusPointer->soundHandle);
 
 
10209
                Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
10210
            }
 
 
10211
 
 
 
10212
        return SRC_No_Change;
 
 
10213
        }
 
 
10214
 
 
 
10215
}
 
 
10216
        /* If you are correctly oriented, you can now fire! */
 
 
10217
 
 
 
10218
        marineStatusPointer->HModelController.Playing = 1;
 
 
10219
        marineStatusPointer->HModelController.sequence_timer = 0;
 
 
10220
    {
 
 
10221
        int hitroll = 0;
 
 
10222
 
 
 
10223
        while (ShotgunBlast[hitroll].vz > 0)
 
 
10224
        {
 
 
10225
            VECTORCH world_vec;
 
 
10226
 
 
 
10227
            RotateAndCopyVector(&ShotgunBlast[hitroll], &world_vec, &marineStatusPointer->My_Gunflash_Section->SecMat);
 
 
10228
            Normalise(&world_vec);
 
 
10229
            FindPolygonInLineOfSight(&world_vec, &marineStatusPointer->My_Gunflash_Section->World_Offset, 0, sbPtr->DisplayBlock);
 
 
10230
 
 
 
10231
            if (LOS_ObjectHitPtr)
 
 
10232
            {
 
 
10233
                if (LOS_ObjectHitPtr->ObStrategyBlock)
 
 
10234
                {
 
 
10235
                    switch(LOS_ObjectHitPtr->ObStrategyBlock->type)
 
 
10236
                    {
 
 
10237
                        case I_BehaviourMarine:
 
 
10238
                        case I_BehaviourMarinePlayer:
 
 
10239
                        {
 
 
10240
                            marineStatusPointer->Courage -= ONE_FIXED >> 3;
 
 
10241
                            //marineStatusPointer->HModelController.Playing = 0;
 
 
10242
                            return SRC_Request_Approach;
 
 
10243
                        }
 
 
10244
                        default:
 
 
10245
                        break;;
 
 
10246
                    }
 
 
10247
                }
 
 
10248
            }
 
 
10249
            hitroll++;
 
 
10250
        }
 
 
10251
    }
 
 
10252
 
 
 
10253
        /* at this point we are correctly orientated: if we have no gunflash yet,
 
 
10254
        and our state timer is set to marine_near_firetime then we have either
 
 
10255
        just started firing, or have become dis-orienated between bursts. This is a good
 
 
10256
        time to consider firing a grenade... */
 
 
10257
 
 
 
10258
        MaintainMarineGunFlash(sbPtr);
 
 
10259
 
 
 
10260
        /* look after the sound */
 
 
10261
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
10262
        {
 
 
10263
            Sound_Update3d(marineStatusPointer->soundHandle,&(sbPtr->DynPtr->Position));
 
 
10264
        }
 
 
10265
        else 
 
 
10266
        { 
 
 
10267
            Sound_Play(marineStatusPointer->My_Weapon->StartSound, "d", &sbPtr->DynPtr->Position);
 
 
10268
            Sound_Play(marineStatusPointer->My_Weapon->LoopSound, "del", &sbPtr->DynPtr->Position,
&marineStatusPointer->soundHandle);
 
 
10269
        }
 
 
10270
 
 
 
10271
        /* Now hit the target with a shotgun blast. */
 
 
10272
 
 
 
10273
        int hitroll = 0;
 
 
10274
        while (ShotgunBlast[hitroll].vz > 0)
 
 
10275
        {
 
 
10276
            VECTORCH world_vec;
 
 
10277
 
 
 
10278
            RotateAndCopyVector(&ShotgunBlast[hitroll],&world_vec,&marineStatusPointer->My_Gunflash_Section->SecMat);
 
 
10279
            CastLOSProjectile(sbPtr, &marineStatusPointer->My_Gunflash_Section->World_Offset, &world_vec,
marineStatusPointer->My_Weapon->Ammo_Type, 1, 0);
 
 
10280
 
 
 
10281
            hitroll++;
 
 
10282
        }
 
 
10283
 
 
 
10284
        if (marineStatusPointer->clipammo > 0)
 
 
10285
            marineStatusPointer->clipammo--;
 
 
10286
    }
 
 
10287
    else
 
 
10288
    {
 
 
10289
        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
10290
 
 
 
10291
        /* .... and stop the sound */
 
 
10292
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
10293
        {
 
 
10294
            Sound_Stop(marineStatusPointer->soundHandle);        
 
 
10295
            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
10296
        }
 
 
10297
    }
 
 
10298
 
 
 
10299
    marineStatusPointer->stateTimer -= NormalFrameTime;
 
 
10300
 
 
 
10301
    /* You must have fired already. */
 
 
10302
    assert(marineStatusPointer->HModelController.Looped==0);
 
 
10303
 
 
 
10304
    if (HModelAnimation_IsFinished(&marineStatusPointer->HModelController))
 
 
10305
        Marine_Enter_PumpAction_State(sbPtr);
 
 
10306
 
 
 
10307
return SRC_No_Change;
 
 
10308
}
 
 
10309
 
 
 
10310
static STATE_RETURN_CONDITION Execute_MNS_DischargePistol(STRATEGYBLOCK *sbPtr)
 
 
10311
{
 
 
10312
    assert(sbPtr);
 
 
10313
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
10314
    assert(marineStatusPointer);
 
 
10315
 
 
 
10316
    assert((marineStatusPointer->My_Weapon->id == MNPCW_MPistol)
 
 
10317
        ||(marineStatusPointer->My_Weapon->id == MNPCW_PistolMarine)
 
 
10318
        ||(marineStatusPointer->My_Weapon->id == MNPCW_Android_Pistol_Special));
 
 
10319
 
 
 
10320
    /* zero velocity */
 
 
10321
    assert(sbPtr->DynPtr);
 
 
10322
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
10323
 
 
 
10324
    if(!MarineCanSeeTarget(sbPtr))
 
 
10325
    {
 
 
10326
        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
10327
 
 
 
10328
        /* .... and stop the sound */
 
 
10329
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
10330
        {
 
 
10331
            Sound_Stop(marineStatusPointer->soundHandle);        
 
 
10332
            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
10333
        }
 
 
10334
 
 
 
10335
    return SRC_Request_Wait;
 
 
10336
    }
 
 
10337
 
 
 
10338
    if (!marineStatusPointer->clipammo)
 
 
10339
        Marine_Enter_Reload_State(sbPtr);
 
 
10340
 
 
 
10341
    /* Here we must have a target.  Renew suspicion for new arrivals. */
 
 
10342
    if (!NpcSquad.Squad_Suspicion)
 
 
10343
        PointAlert(2,&marineStatusPointer->weaponTarget);
 
 
10344
 
 
 
10345
    int hitroll = marineStatusPointer->Skill; /* Marine skill... */
 
 
10346
    int range;
 
 
10347
{
 
 
10348
    VECTORCH relPos,relPos2;
 
 
10349
    relPos.vx = (marineStatusPointer->Target->DynPtr->Position.vx) - (sbPtr->DynPtr->Position.vx);
 
 
10350
    relPos.vy = (marineStatusPointer->Target->DynPtr->Position.vy) - (sbPtr->DynPtr->Position.vy);
 
 
10351
    relPos.vz = (marineStatusPointer->Target->DynPtr->Position.vz) - (sbPtr->DynPtr->Position.vz);
 
 
10352
 
 
 
10353
    relPos2.vx = (marineStatusPointer->Target->DynPtr->Position.vx) - (marineStatusPointer->Target->DynPtr->PrevPosition.vx);
 
 
10354
    relPos2.vy = (marineStatusPointer->Target->DynPtr->Position.vy) - (marineStatusPointer->Target->DynPtr->PrevPosition.vy);
 
 
10355
    relPos2.vz = (marineStatusPointer->Target->DynPtr->Position.vz) - (marineStatusPointer->Target->DynPtr->PrevPosition.vz);
 
 
10356
    hitroll -= SpeedRangeMods(&relPos, &relPos2);
 
 
10357
    range = VectorDistance(&marineStatusPointer->Target->DynPtr->Position, &sbPtr->DynPtr->Position);
 
 
10358
}
 
 
10359
 
 
 
10360
    /* first of all, validate this state: if the target suddenly becomes cloaked, then
 
 
10361
    we should switch immediately to wait state.*/
 
 
10362
 
 
 
10363
    if (marineStatusPointer->HModelController.keyframe_flags || !marineStatusPointer->HModelController.Playing)
 
 
10364
    {
 
 
10365
        marineStatusPointer->HModelController.Playing = 0;
 
 
10366
        marineStatusPointer->HModelController.sequence_timer = 0;
 
 
10367
 
 
 
10368
        /* Only terminate if you haven't fired yet... */
 
 
10369
        if(!MarineCanSeeTarget(sbPtr))
 
 
10370
        {
 
 
10371
            DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
10372
 
 
 
10373
            /* .... and stop the sound */
 
 
10374
            if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
10375
            {
 
 
10376
                Sound_Stop(marineStatusPointer->soundHandle);        
 
 
10377
                Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
10378
            }
 
 
10379
 
 
 
10380
        return SRC_Request_Wait;
 
 
10381
        }
 
 
10382
 
 
 
10383
        assert(marineStatusPointer->Target);
 
 
10384
        NPCGetTargetPosition(&marineStatusPointer->weaponTarget, marineStatusPointer->Target);
 
 
10385
 
 
 
10386
        /* Fix weapon target! */
 
 
10387
        if (marineStatusPointer->My_Weapon->TargetCallibrationShift)
 
 
10388
        {
 
 
10389
            marineStatusPointer->weaponTarget.vx -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat11,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
10390
            marineStatusPointer->weaponTarget.vy -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat12,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
10391
            marineStatusPointer->weaponTarget.vz -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat13,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
10392
        }
 
 
10393
 
 
 
10394
        /* orientate to firing point first */
 
 
10395
        int correctlyOrientated;
 
 
10396
 
 
 
10397
        {
 
 
10398
        VECTORCH orientationDirn;
 
 
10399
        orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
 
 
10400
        orientationDirn.vy = 0;
 
 
10401
        orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
 
 
10402
        int correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE);
 
 
10403
        }
 
 
10404
 
 
 
10405
        /* we are not correctly orientated to the target: this could happen because we have
 
 
10406
        just entered this state, or the target has moved during firing*/
 
 
10407
 
 
 
10408
        if(!correctlyOrientated || (marineStatusPointer->HModelController.Tweening == Controller_Tweening))
 
 
10409
        {
 
 
10410
            /* stop visual and audio cues: technically, we're not firing at this moment */
 
 
10411
            DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
10412
 
 
 
10413
            if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
10414
            {
 
 
10415
                Sound_Stop(marineStatusPointer->soundHandle);
 
 
10416
                Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
10417
            }
 
 
10418
 
 
 
10419
        return SRC_No_Change;
 
 
10420
        }
 
 
10421
 
 
 
10422
        if (human_in_los(sbPtr))
 
 
10423
        {
 
 
10424
            //marineStatusPointer->Courage -= ONE_FIXED >> 3;
 
 
10425
            marineStatusPointer->Courage += MUL_FIXED(NormalFrameTime, 300);
 
 
10426
            //marineStatusPointer->HModelController.Playing = 0;
 
 
10427
            return ((FastRandom() & 127) > 10) ?  SRC_Request_Approach : SRC_Request_Avoidance; 
 
 
10428
        }
 
 
10429
 
 
 
10430
        /* If you are correctly oriented, you can now fire! */
 
 
10431
 
 
 
10432
        marineStatusPointer->HModelController.Playing = 1;
 
 
10433
 
 
 
10434
        if (marineStatusPointer->clipammo > 0)
 
 
10435
            marineStatusPointer->clipammo--;
 
 
10436
 
 
 
10437
        marineStatusPointer->roundsForThisTarget++;
 
 
10438
 
 
 
10439
        /* at this point we are correctly orientated: if we have no gunflash yet,
 
 
10440
        and our state timer is set to marine_near_firetime then we have either
 
 
10441
        just started firing, or have become dis-orienated between bursts. This is a good
 
 
10442
        time to consider firing a grenade... */
 
 
10443
 
 
 
10444
        MaintainMarineGunFlash(sbPtr);
 
 
10445
 
 
 
10446
        /* look after the sound */
 
 
10447
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
10448
        {
 
 
10449
            Sound_Update3d(marineStatusPointer->soundHandle,&(sbPtr->DynPtr->Position));
 
 
10450
        }
 
 
10451
        else 
 
 
10452
        { 
 
 
10453
            Sound_Play(marineStatusPointer->My_Weapon->StartSound, "d", &sbPtr->DynPtr->Position);
 
 
10454
            Sound_Play(marineStatusPointer->My_Weapon->LoopSound, "del", &sbPtr->DynPtr->Position,
&marineStatusPointer->soundHandle);
 
 
10455
        }
 
 
10456
 
 
 
10457
        /* Now hit the target with one bullet. */
 
 
10458
 
 
 
10459
        switch(marineStatusPointer->Target->type)
 
 
10460
        {
 
 
10461
            case I_BehaviourPredatorPlayer:
 
 
10462
                if(!PlayerStatus.cloakOn)
 
 
10463
                    break;
 
 
10464
            case I_BehaviourAlienPlayer:
 
 
10465
                /* Vs the player, lighting effects on aliens and cloaked preds. */
 
 
10466
                hitroll = MUL_FIXED(hitroll, ((PlayerStatus.CurrentLightAtPlayer >> 1) + 32767));
 
 
10467
            default:
 
 
10468
            break;
 
 
10469
        }
 
 
10470
 
 
 
10471
        hitroll += marineStatusPointer->My_Weapon->Accuracy;
 
 
10472
 
 
 
10473
        {
 
 
10474
            /* Handle Damage. */
 
 
10475
            if ((FastRandom() & 65535) < hitroll)
 
 
10476
            {
 
 
10477
                /* DO DAMAGE TO TARGET HERE */
 
 
10478
 
 
 
10479
                VECTORCH rel_pos,attack_dir;
 
 
10480
                VECTORCH shotvector = {0,0,65535};
 
 
10481
 
 
 
10482
                RotateVector(&shotvector, &marineStatusPointer->My_Gunflash_Section->SecMat);
 
 
10483
 
 
 
10484
                rel_pos.vx = marineStatusPointer->Target->DynPtr->Position.vx - sbPtr->DynPtr->Position.vx;
 
 
10485
                rel_pos.vy = marineStatusPointer->Target->DynPtr->Position.vy - sbPtr->DynPtr->Position.vy;
 
 
10486
                rel_pos.vz = marineStatusPointer->Target->DynPtr->Position.vz - sbPtr->DynPtr->Position.vz;
 
 
10487
 
 
 
10488
                if (VerifyHitShot(sbPtr, marineStatusPointer->Target, &marineStatusPointer->My_Gunflash_Section->World_Offset, &shotvector,
marineStatusPointer->My_Weapon->Ammo_Type, 1))
 
 
10489
                {
 
 
10490
                    GetDirectionOfAttack(marineStatusPointer->Target, &rel_pos, &attack_dir);
 
 
10491
                    /* Get hit location? */
 
 
10492
 
 
 
10493
                    marineStatusPointer->lasthitsection = HitLocationRoll(marineStatusPointer->Target,sbPtr);
 
 
10494
 
 
 
10495
                    if (marineStatusPointer->lasthitsection)
 
 
10496
                    {
 
 
10497
CauseDamageToHModel(marineStatusPointer->lasthitsection->my_controller,
marineStatusPointer->Target,&TemplateAmmo[marineStatusPointer->My_Weapon->Ammo_Type].MaxDamage, ONE_FIXED,
marineStatusPointer->lasthitsection,&attack_dir,NULL,0);
 
 
10498
                    }
 
 
10499
                    else
 
 
10500
                    {
 
 
10501
CauseDamageToObject(marineStatusPointer->Target, &TemplateAmmo[marineStatusPointer->My_Weapon->Ammo_Type].MaxDamage, ONE_FIXED, &attack_dir);
 
 
10502
                    }
 
 
10503
                }
 
 
10504
            }
 
 
10505
            else
 
 
10506
            {
 
 
10507
                assert(marineStatusPointer->My_Gunflash_Section);
 
 
10508
ProjectNPCShot(sbPtr, marineStatusPointer->Target,
&marineStatusPointer->My_Gunflash_Section->World_Offset,&marineStatusPointer->My_Gunflash_Section->SecMat,
marineStatusPointer->My_Weapon->Ammo_Type, 1);
 
 
10509
            }
 
 
10510
 
 
 
10511
            /* Did we get him? */
 
 
10512
            if (NPC_IsDead(marineStatusPointer->Target) && marineStatusPointer->My_Weapon->ARealMarine)
 
 
10513
            {
 
 
10514
                /* Only real marines taunt. */
 
 
10515
                if ((marineStatusPointer->roundsForThisTarget == 1) || MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
10516
                {
 
 
10517
                    if (Marine_GetNewTarget(&sbPtr->DynPtr->Position,sbPtr) == NULL)
 
 
10518
                    {
 
 
10519
                        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
10520
 
 
 
10521
                        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
10522
                        {
 
 
10523
                            Sound_Stop(marineStatusPointer->soundHandle);
 
 
10524
                            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
10525
                        }
 
 
10526
 
 
 
10527
                        marineStatusPointer->lastroundhit = 0;
 
 
10528
                        marineStatusPointer->lasthitsection = NULL;
 
 
10529
                        Marine_Enter_Taunt_State(sbPtr);
 
 
10530
                    }
 
 
10531
                }
 
 
10532
            }
 
 
10533
        }
 
 
10534
    }
 
 
10535
    else
 
 
10536
    {
 
 
10537
        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
10538
 
 
 
10539
        /* .... and stop the sound */
 
 
10540
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
10541
        {
 
 
10542
            Sound_Stop(marineStatusPointer->soundHandle);        
 
 
10543
            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
10544
        }
 
 
10545
    }
 
 
10546
 
 
 
10547
    marineStatusPointer->stateTimer -= NormalFrameTime;
 
 
10548
 
 
 
10549
    /* You must have fired already. */
 
 
10550
 
 
 
10551
    if(marineStatusPointer->stateTimer > 0)
 
 
10552
        return SRC_No_Change;
 
 
10553
 
 
 
10554
    if ((range < MARINE_CLOSE_APPROACH_DISTANCE) || marineStatusPointer->Android)
 
 
10555
    {
 
 
10556
        /* renew firing, as we are still too close to approach */ 
 
 
10557
        marineStatusPointer->stateTimer = marineStatusPointer->My_Weapon->FiringTime;                     
 
 
10558
        marineStatusPointer->volleySize = 0;
 
 
10559
        assert(marineStatusPointer->Target);
 
 
10560
 
 
 
10561
        NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
 
 
10562
 
 
 
10563
        if (!marineStatusPointer->Android)
 
 
10564
            marineStatusPointer->Courage -= (ONE_FIXED>>3);
 
 
10565
 
 
 
10566
    return SRC_No_Change;
 
 
10567
    }
 
 
10568
    else
 
 
10569
    {
 
 
10570
        /* we are far enough away, so return to approach */
 
 
10571
 
 
 
10572
        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
10573
 
 
 
10574
    return SRC_Request_Approach;
 
 
10575
    }
 
 
10576
 
 
 
10577
return SRC_No_Change;
 
 
10578
}
 
 
10579
 
 
 
10580
static STATE_RETURN_CONDITION Execute_MNS_ThrowMolotov(STRATEGYBLOCK *sbPtr)
 
 
10581
{
 
 
10582
    assert(sbPtr);
 
 
10583
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
10584
    assert(marineStatusPointer);
 
 
10585
 
 
 
10586
    assert(sbPtr->DynPtr);
 
 
10587
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
10588
 
 
 
10589
    /* first of all, validate this state: if the target suddenly becomes cloaked, then
 
 
10590
    we should switch immediately to wait state.*/
 
 
10591
 
 
 
10592
    if (marineStatusPointer->stateTimer == marineStatusPointer->My_Weapon->FiringTime)
 
 
10593
    {
 
 
10594
        marineStatusPointer->HModelController.Playing = 0;
 
 
10595
        marineStatusPointer->HModelController.sequence_timer = 0;
 
 
10596
        marineStatusPointer->stateTimer--;
 
 
10597
    }
 
 
10598
 
 
 
10599
    if (marineStatusPointer->Target)
 
 
10600
    {
 
 
10601
        /* Only terminate if you haven't fired yet... */
 
 
10602
        if(!MarineCanSeeTarget(sbPtr))
 
 
10603
        {
 
 
10604
            /* .... and stop the sound */
 
 
10605
            if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
10606
            {
 
 
10607
                Sound_Stop(marineStatusPointer->soundHandle);        
 
 
10608
                Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
10609
            }
 
 
10610
 
 
 
10611
            return SRC_Request_Wait;
 
 
10612
        }
 
 
10613
 
 
 
10614
        NPCGetTargetPosition(&marineStatusPointer->weaponTarget, marineStatusPointer->Target);
 
 
10615
        /* Fix weapon target! */
 
 
10616
 
 
 
10617
        if (marineStatusPointer->My_Weapon->TargetCallibrationShift)
 
 
10618
        {
 
 
10619
        marineStatusPointer->weaponTarget.vx -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat11,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
10620
        marineStatusPointer->weaponTarget.vy -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat12,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
10621
        marineStatusPointer->weaponTarget.vz -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat13,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
10622
        }
 
 
10623
 
 
 
10624
        /* Here we must have a target.  Renew suspicion for new arrivals. */
 
 
10625
        if (!NpcSquad.Squad_Suspicion)
 
 
10626
            PointAlert(2, &marineStatusPointer->weaponTarget);
 
 
10627
    }
 
 
10628
 
 
 
10629
    /* orientate to firing point first */
 
 
10630
    {
 
 
10631
        VECTORCH orientationDirn;
 
 
10632
        orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
 
 
10633
        orientationDirn.vy = 0;
 
 
10634
        orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
 
 
10635
 
 
 
10636
        /* we are not correctly orientated to the target: this could happen because we have
 
 
10637
        just entered this state, or the target has moved during firing*/
 
 
10638
 
 
 
10639
        if(!NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE))
 
 
10640
        {
 
 
10641
            if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
10642
            {
 
 
10643
                Sound_Stop(marineStatusPointer->soundHandle);
 
 
10644
                Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
10645
            }
 
 
10646
 
 
 
10647
        return SRC_No_Change;
 
 
10648
        }
 
 
10649
    }
 
 
10650
 
 
 
10651
    /* If you are correctly oriented, you can now fire! */
 
 
10652
 
 
 
10653
    marineStatusPointer->HModelController.Playing = 1;
 
 
10654
 
 
 
10655
    /* at this point we are correctly orientated: if we have no gunflash yet,
 
 
10656
    and our state timer is set to marine_near_firetime then we have either
 
 
10657
    just started firing, or have become dis-orienated between bursts. This is a good
 
 
10658
    time to consider firing a grenade... */
 
 
10659
 
 
 
10660
    /* No muzzle flash. */
 
 
10661
 
 
 
10662
    /* look after the sound */
 
 
10663
    if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
10664
    {
 
 
10665
        Sound_Update3d(marineStatusPointer->soundHandle, &sbPtr->DynPtr->Position);
 
 
10666
    }
 
 
10667
    else 
 
 
10668
    { 
 
 
10669
        Sound_Play(marineStatusPointer->My_Weapon->StartSound, "d", &sbPtr->DynPtr->Position);
 
 
10670
        Sound_Play(marineStatusPointer->My_Weapon->LoopSound,"del",&sbPtr->DynPtr->Position,
&marineStatusPointer->soundHandle);
 
 
10671
    }
 
 
10672
 
 
 
10673
    if(marineStatusPointer->My_Gunflash_Section)
 
 
10674
    {
 
 
10675
        if (marineStatusPointer->HModelController.keyframe_flags)
 
 
10676
        {
 
 
10677
            /* Throw! */            
 
 
10678
            SpawnMolotovCocktail(marineStatusPointer->My_Gunflash_Section, &sbPtr->DynPtr->OrientMat);
 
 
10679
            marineStatusPointer->My_Gunflash_Section = NULL;
 
 
10680
            marineStatusPointer->Mission = MM_NonCom;
 
 
10681
            /* Turn into a noncom! */
 
 
10682
 
 
 
10683
            {
 
 
10684
                /* Remove hitdelta, if there is one. */
 
 
10685
                DELTA_CONTROLLER *delta = Get_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta");
 
 
10686
 
 
 
10687
                if (delta)
 
 
10688
                    Remove_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta");
 
 
10689
            }
 
 
10690
 
 
 
10691
            const MARINE_WEAPON_DATA *noncom = &NPC_Marine_Weapons[MNPCW_MUnarmed];
 
 
10692
 
 
 
10693
            SECTION *root = GetNamedHierarchyFromLibrary(noncom->Riffname,noncom->HierarchyName);
 
 
10694
            Transmogrify_HModels(sbPtr,&marineStatusPointer->HModelController,root, 1, 0,0);
 
 
10695
            marineStatusPointer->My_Weapon = noncom;
 
 
10696
 
 
 
10697
            /* Attempt to put the hitdelta back? */
 
 
10698
            if (HModelSequence_Exists(&marineStatusPointer->HModelController,(int)HMSQT_MarineStand,(int)MSSS_HitChestFront))
 
 
10699
            {
 
 
10700
DELTA_CONTROLLER *delta =
Add_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta",(int)HMSQT_MarineStand,(int)MSSS_HitChestFront,(ONE_FIXED>>2));
 
 
10701
            assert(delta);
 
 
10702
            delta->Playing = 0;
 
 
10703
            }
 
 
10704
 
 
 
10705
            marineStatusPointer->Target = NULL;
 
 
10706
            return SRC_Request_Retreat;
 
 
10707
        }
 
 
10708
    }
 
 
10709
 
 
 
10710
return SRC_No_Change;
 
 
10711
}
 
 
10712
 
 
 
10713
static STATE_RETURN_CONDITION Execute_MNS_DischargeGL(STRATEGYBLOCK *sbPtr)
 
 
10714
{
 
 
10715
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
10716
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
10717
 
 
 
10718
    /* first of all, validate this state: if the target suddenly becomes cloaked, then
 
 
10719
    we should switch immediately to wait state.*/
 
 
10720
 
 
 
10721
    if(!MarineCanSeeTarget(sbPtr))
 
 
10722
    {
 
 
10723
        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
10724
 
 
 
10725
        /* .... and stop the sound */
 
 
10726
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
10727
        {
 
 
10728
            Sound_Stop(marineStatusPointer->soundHandle);        
 
 
10729
            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
10730
        }
 
 
10731
 
 
 
10732
        return SRC_Request_Wait;
 
 
10733
    }
 
 
10734
 
 
 
10735
    if (!marineStatusPointer->clipammo)
 
 
10736
        Marine_Enter_Reload_State(sbPtr);
 
 
10737
 
 
 
10738
    /* Here we must have a target.  Renew suspicion for new arrivals. */
 
 
10739
    if (!NpcSquad.Squad_Suspicion)
 
 
10740
        PointAlert(2, &marineStatusPointer->weaponTarget);
 
 
10741
 
 
 
10742
    /* Deal with tweening part. */
 
 
10743
    if (marineStatusPointer->internalState)
 
 
10744
    {
 
 
10745
        if (marineStatusPointer->HModelController.Tweening == Controller_NoTweening)
 
 
10746
        {
 
 
10747
            marineStatusPointer->HModelController.Playing = 0;
 
 
10748
            marineStatusPointer->HModelController.sequence_timer = 0;
 
 
10749
            marineStatusPointer->internalState = 0;
 
 
10750
        }
 
 
10751
 
 
 
10752
        return SRC_No_Change;
 
 
10753
    }
 
 
10754
 
 
 
10755
    if (!marineStatusPointer->HModelController.Playing)
 
 
10756
    {
 
 
10757
        /* Only terminate if you haven't fired yet... */
 
 
10758
        if(!MarineCanSeeTarget(sbPtr))
 
 
10759
        {
 
 
10760
            DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
10761
 
 
 
10762
            /* .... and stop the sound */
 
 
10763
            if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
10764
            {
 
 
10765
                Sound_Stop(marineStatusPointer->soundHandle);        
 
 
10766
                Sound_Play(marineStatusPointer->My_Weapon->EndSound,"d", &sbPtr->DynPtr->Position);
 
 
10767
            }
 
 
10768
 
 
 
10769
        return SRC_Request_Wait;
 
 
10770
        }
 
 
10771
 
 
 
10772
        assert(marineStatusPointer->Target);
 
 
10773
        NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
 
 
10774
        /* Fix weapon target! */
 
 
10775
 
 
 
10776
        if (marineStatusPointer->My_Weapon->TargetCallibrationShift)
 
 
10777
        {
 
 
10778
            marineStatusPointer->weaponTarget.vx -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat11,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
10779
            marineStatusPointer->weaponTarget.vy -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat12,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
10780
            marineStatusPointer->weaponTarget.vz -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat13,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
10781
        }
 
 
10782
 
 
 
10783
        /* Aim up a little? */
 
 
10784
        int range = VectorDistance((&marineStatusPointer->weaponTarget),(&sbPtr->DynPtr->Position));
 
 
10785
 
 
 
10786
        marineStatusPointer->weaponTarget.vy -= (range / 8);
 
 
10787
 
 
 
10788
    {
 
 
10789
        VECTORCH orientationDirn;
 
 
10790
        /* orientate to firing point first */
 
 
10791
        orientationDirn.vx = marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
 
 
10792
        orientationDirn.vy = 0;
 
 
10793
        orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
 
 
10794
 
 
 
10795
        /* we are not correctly orientated to the target: this could happen because we have
 
 
10796
        just entered this state, or the target has moved during firing*/
 
 
10797
 
 
 
10798
        if(!NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE) || (marineStatusPointer->HModelController.Tweening != Controller_NoTweening))
 
 
10799
        {
 
 
10800
            /* stop visual and audio cues: technically, we're not firing at this moment */
 
 
10801
            DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
10802
 
 
 
10803
            if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
10804
            {
 
 
10805
                Sound_Stop(marineStatusPointer->soundHandle);
 
 
10806
                Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
10807
            }
 
 
10808
 
 
 
10809
        return SRC_No_Change;
 
 
10810
        }
 
 
10811
    }
 
 
10812
 
 
 
10813
        if (human_in_los(sbPtr))
 
 
10814
        {
 
 
10815
            //marineStatusPointer->Courage -= ONE_FIXED >> 3;
 
 
10816
            marineStatusPointer->Courage += MUL_FIXED(NormalFrameTime, 300);
 
 
10817
            //marineStatusPointer->HModelController.Playing = 0;
 
 
10818
            return ((FastRandom() & 127) > 10) ?  SRC_Request_Approach : SRC_Request_Avoidance; 
 
 
10819
        }
 
 
10820
 
 
 
10821
        /* If you are correctly oriented, you can now fire! */
 
 
10822
        marineStatusPointer->HModelController.Playing = 1;
 
 
10823
        marineStatusPointer->HModelController.sequence_timer = 0;
 
 
10824
    {
 
 
10825
        int range = VectorDistance((&marineStatusPointer->Target->DynPtr->Position),(&sbPtr->DynPtr->Position));
 
 
10826
 
 
 
10827
        /* Are they, by some chance, really close? */
 
 
10828
        if (range < marineStatusPointer->My_Weapon->MinRange)
 
 
10829
        {
 
 
10830
            if (!MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
10831
            {
 
 
10832
                /* Stay frosty. */
 
 
10833
                return SRC_Request_PullPistol;
 
 
10834
            }
 
 
10835
            else
 
 
10836
            {
 
 
10837
                if (MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
10838
                {
 
 
10839
                    /* Fail twice, then flee... else continue. */
 
 
10840
                    return SRC_Request_Retreat;
 
 
10841
                }
 
 
10842
            }
 
 
10843
        }
 
 
10844
    }
 
 
10845
 
 
 
10846
        /* at this point we are correctly orientated: if we have no gunflash yet,
 
 
10847
        and our state timer is set to marine_near_firetime then we have either
 
 
10848
        just started firing, or have become dis-orienated between bursts. This is a good
 
 
10849
        time to consider firing a grenade... */
 
 
10850
 
 
 
10851
        MaintainMarineGunFlash(sbPtr);
 
 
10852
 
 
 
10853
        /* look after the sound */
 
 
10854
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
10855
        {
 
 
10856
            Sound_Update3d(marineStatusPointer->soundHandle, &sbPtr->DynPtr->Position);
 
 
10857
        }
 
 
10858
        else 
 
 
10859
        { 
 
 
10860
            Sound_Play(marineStatusPointer->My_Weapon->StartSound, "d", &sbPtr->DynPtr->Position);
 
 
10861
            Sound_Play(marineStatusPointer->My_Weapon->LoopSound, "del", &sbPtr->DynPtr->Position,
&marineStatusPointer->soundHandle);
 
 
10862
        }
 
 
10863
 
 
 
10864
        assert(marineStatusPointer->My_Gunflash_Section);
 
 
10865
 
 
 
10866
        CreateGrenadeKernel(I_BehaviourGrenade, &marineStatusPointer->My_Gunflash_Section->World_Offset,
&marineStatusPointer->My_Gunflash_Section->SecMat,0);
 
 
10867
 
 
 
10868
        if (marineStatusPointer->clipammo > 0)
 
 
10869
            marineStatusPointer->clipammo--;
 
 
10870
    }
 
 
10871
    else
 
 
10872
    {
 
 
10873
        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
10874
 
 
 
10875
        /* .... and stop the sound */
 
 
10876
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
10877
        {
 
 
10878
            Sound_Stop(marineStatusPointer->soundHandle);        
 
 
10879
            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
10880
        }
 
 
10881
    }
 
 
10882
 
 
 
10883
    marineStatusPointer->stateTimer -= NormalFrameTime;
 
 
10884
 
 
 
10885
    /* You must have fired already. */
 
 
10886
 
 
 
10887
    assert(marineStatusPointer->HModelController.Looped == 0);
 
 
10888
 
 
 
10889
     if (HModelAnimation_IsFinished(&marineStatusPointer->HModelController))
 
 
10890
        Marine_Enter_PumpAction_State(sbPtr);
 
 
10891
 
 
 
10892
return SRC_No_Change;
 
 
10893
}
 
 
10894
 
 
 
10895
static STATE_RETURN_CONDITION Execute_MNS_DischargeSADAR(STRATEGYBLOCK *sbPtr)
 
 
10896
{
 
 
10897
    int range;
 
 
10898
 
 
 
10899
    assert(sbPtr);
 
 
10900
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
10901
    assert(marineStatusPointer);
 
 
10902
 
 
 
10903
    /* zero velocity */
 
 
10904
    assert(sbPtr->DynPtr);
 
 
10905
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
10906
 
 
 
10907
    /* first of all, validate this state: if the target suddenly becomes cloaked, then
 
 
10908
    we should switch immediately to wait state.*/
 
 
10909
 
 
 
10910
    if(!MarineCanSeeTarget(sbPtr))
 
 
10911
    {
 
 
10912
        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
10913
 
 
 
10914
        /* .... and stop the sound */
 
 
10915
        if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX)
 
 
10916
        {
 
 
10917
            Sound_Stop(marineStatusPointer->soundHandle);        
 
 
10918
            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
10919
        }
 
 
10920
 
 
 
10921
    return SRC_Request_Wait;
 
 
10922
    }
 
 
10923
 
 
 
10924
    if (!marineStatusPointer->clipammo)
 
 
10925
        Marine_Enter_Reload_State(sbPtr);
 
 
10926
 
 
 
10927
    /* Here we must have a target.  Renew suspicion for new arrivals. */
 
 
10928
    if (!NpcSquad.Squad_Suspicion)
 
 
10929
        PointAlert(2,&marineStatusPointer->weaponTarget);
 
 
10930
 
 
 
10931
    if (marineStatusPointer->stateTimer == marineStatusPointer->My_Weapon->FiringTime)
 
 
10932
    {
 
 
10933
        if (marineStatusPointer->HModelController.Tweening == Controller_NoTweening)
 
 
10934
            marineStatusPointer->HModelController.Playing = 0;
 
 
10935
 
 
 
10936
        /* Only terminate if you haven't fired yet... */
 
 
10937
        if(!MarineCanSeeTarget(sbPtr))
 
 
10938
        {
 
 
10939
            DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
10940
 
 
 
10941
            /* .... and stop the sound */
 
 
10942
            if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
10943
            {
 
 
10944
                Sound_Stop(marineStatusPointer->soundHandle);        
 
 
10945
                Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
10946
            }
 
 
10947
 
 
 
10948
        return SRC_Request_Wait;
 
 
10949
        }
 
 
10950
 
 
 
10951
        assert(marineStatusPointer->Target);
 
 
10952
        NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
 
 
10953
 
 
 
10954
        /* Fix weapon target! */
 
 
10955
        if (marineStatusPointer->My_Weapon->TargetCallibrationShift)
 
 
10956
        {
 
 
10957
            marineStatusPointer->weaponTarget.vx -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat11,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
10958
            marineStatusPointer->weaponTarget.vy -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat12,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
10959
            marineStatusPointer->weaponTarget.vz -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat13,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
10960
        }
 
 
10961
    {
 
 
10962
        /* orientate to firing point first */
 
 
10963
        VECTORCH orientationDirn;
 
 
10964
        orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
 
 
10965
        orientationDirn.vy = 0;
 
 
10966
        orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
 
 
10967
        int correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE);
 
 
10968
 
 
 
10969
        /* we are not correctly orientated to the target: this could happen because we have
 
 
10970
        just entered this state, or the target has moved during firing*/
 
 
10971
 
 
 
10972
        if(!correctlyOrientated || (marineStatusPointer->HModelController.Tweening != Controller_NoTweening))
 
 
10973
        {
 
 
10974
            /* stop visual and audio cues: technically, we're not firing at this moment */
 
 
10975
            DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
10976
 
 
 
10977
            if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX)
 
 
10978
            {
 
 
10979
                Sound_Stop(marineStatusPointer->soundHandle);
 
 
10980
                Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
10981
            }
 
 
10982
 
 
 
10983
        return SRC_No_Change;
 
 
10984
        }
 
 
10985
    }
 
 
10986
        /* If you are correctly oriented, you can now fire! */
 
 
10987
 
 
 
10988
        marineStatusPointer->HModelController.Playing = 1;
 
 
10989
        marineStatusPointer->HModelController.sequence_timer = 0;
 
 
10990
 
 
 
10991
        range = VectorDistance((&marineStatusPointer->Target->DynPtr->Position),(&sbPtr->DynPtr->Position));
 
 
10992
 
 
 
10993
        /* Are they, by some chance, really close? */
 
 
10994
        if (range < marineStatusPointer->My_Weapon->MinRange)
 
 
10995
        {
 
 
10996
            if (!MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
10997
            {
 
 
10998
                /* Stay frosty. */
 
 
10999
                return SRC_Request_PullPistol;
 
 
11000
            }
 
 
11001
            else
 
 
11002
            {
 
 
11003
                if (MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
11004
                {
 
 
11005
                    /* Fail twice, then flee... else continue. */
 
 
11006
                    return SRC_Request_Retreat;
 
 
11007
                }
 
 
11008
            }
 
 
11009
        }
 
 
11010
 
 
 
11011
        /* at this point we are correctly orientated: if we have no gunflash yet,
 
 
11012
        and our state timer is set to marine_near_firetime then we have either
 
 
11013
        just started firing, or have become dis-orienated between bursts. This is a good
 
 
11014
        time to consider firing a grenade... */
 
 
11015
 
 
 
11016
        if (human_in_los(sbPtr))
 
 
11017
        {
 
 
11018
            //marineStatusPointer->Courage -= ONE_FIXED >> 3;
 
 
11019
            marineStatusPointer->Courage += MUL_FIXED(NormalFrameTime, 300);
 
 
11020
            //marineStatusPointer->HModelController.Playing = 0;
 
 
11021
            return ((FastRandom() & 127) > 10) ?  SRC_Request_Approach : SRC_Request_Avoidance; 
 
 
11022
        }
 
 
11023
 
 
 
11024
        MaintainMarineGunFlash(sbPtr);
 
 
11025
 
 
 
11026
        /* look after the sound */
 
 
11027
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
11028
        {
 
 
11029
            Sound_Update3d(marineStatusPointer->soundHandle,&(sbPtr->DynPtr->Position));
 
 
11030
        }
 
 
11031
        else 
 
 
11032
        { 
 
 
11033
            Sound_Play(marineStatusPointer->My_Weapon->StartSound, "d", &sbPtr->DynPtr->Position);
 
 
11034
            Sound_Play(marineStatusPointer->My_Weapon->LoopSound, "del", &sbPtr->DynPtr->Position,
&marineStatusPointer->soundHandle);
 
 
11035
        }
 
 
11036
 
 
 
11037
        /* Now fire a rocket. */
 
 
11038
 
 
 
11039
        {
 
 
11040
            SECTION_DATA *rocket_section = GetThisSectionData(marineStatusPointer->HModelController.section_data,"dum flash");
 
 
11041
 
 
 
11042
            assert(rocket_section);
 
 
11043
 
 
 
11044
            CreateRocketKernel(&rocket_section->World_Offset, &rocket_section->SecMat, 0);
 
 
11045
 
 
 
11046
            if (marineStatusPointer->clipammo > 0)
 
 
11047
                marineStatusPointer->clipammo--;
 
 
11048
        }
 
 
11049
    }
 
 
11050
 
 
 
11051
    if (marineStatusPointer->stateTimer < marineStatusPointer->My_Weapon->FiringTime)
 
 
11052
    {
 
 
11053
        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
11054
 
 
 
11055
        /* .... and stop the sound */
 
 
11056
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
11057
        {
 
 
11058
            Sound_Stop(marineStatusPointer->soundHandle);        
 
 
11059
            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
11060
        }
 
 
11061
    }
 
 
11062
 
 
 
11063
    marineStatusPointer->stateTimer -= NormalFrameTime;
 
 
11064
 
 
 
11065
    /* You must have fired already. */
 
 
11066
 
 
 
11067
    if(marineStatusPointer->stateTimer > 0)
 
 
11068
        return SRC_No_Change;
 
 
11069
 
 
 
11070
    if(range < MARINE_CLOSE_APPROACH_DISTANCE)
 
 
11071
    {
 
 
11072
        /* renew firing, as we are still too close to approach */ 
 
 
11073
        marineStatusPointer->stateTimer = marineStatusPointer->My_Weapon->FiringTime;                     
 
 
11074
        marineStatusPointer->volleySize = 0;
 
 
11075
        assert(marineStatusPointer->Target);
 
 
11076
        NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
 
 
11077
    return SRC_No_Change;
 
 
11078
    }
 
 
11079
    else
 
 
11080
    {
 
 
11081
        /* we are far enough away, so return to approach */
 
 
11082
        return SRC_Request_Approach;
 
 
11083
    }
 
 
11084
 
 
 
11085
return SRC_No_Change;
 
 
11086
}
 
 
11087
 
 
 
11088
static STATE_RETURN_CONDITION Execute_MNS_DischargeMinigun(STRATEGYBLOCK *sbPtr)
 
 
11089
{
 
 
11090
    int range;
 
 
11091
 
 
 
11092
    assert(sbPtr);
 
 
11093
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
11094
    assert(marineStatusPointer);
 
 
11095
 
 
 
11096
    /* zero velocity */
 
 
11097
    assert(sbPtr->DynPtr);
 
 
11098
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
11099
 
 
 
11100
    marineStatusPointer->HModelController.Playing = 1;
 
 
11101
 
 
 
11102
    /* first of all, validate this state: if the target suddenly becomes cloaked, then
 
 
11103
    we should switch immediately to wait state*/
 
 
11104
 
 
 
11105
    if (marineStatusPointer->volleySize < marineStatusPointer->My_Weapon->MinimumBurstSize)
 
 
11106
    {
 
 
11107
        /* Keep firing! */
 
 
11108
    }
 
 
11109
    else
 
 
11110
    {
 
 
11111
        if(!MarineCanSeeTarget(sbPtr))
 
 
11112
        {
 
 
11113
            DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
11114
 
 
 
11115
            /* .... and stop the sound */
 
 
11116
            if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
11117
            {
 
 
11118
                Sound_Stop(marineStatusPointer->soundHandle);        
 
 
11119
                Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
11120
            }
 
 
11121
 
 
 
11122
            marineStatusPointer->lastroundhit = 0;
 
 
11123
            marineStatusPointer->lasthitsection = NULL;
 
 
11124
            return SRC_Request_Wait;
 
 
11125
        }
 
 
11126
    }
 
 
11127
 
 
 
11128
    if (marineStatusPointer->Target)
 
 
11129
    {
 
 
11130
        assert(marineStatusPointer->Target);
 
 
11131
        NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
 
 
11132
        /* Fix weapon target! */
 
 
11133
 
 
 
11134
        if (marineStatusPointer->My_Weapon->TargetCallibrationShift)
 
 
11135
        {
 
 
11136
            marineStatusPointer->weaponTarget.vx -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat11,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
11137
            marineStatusPointer->weaponTarget.vy -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat12,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
11138
            marineStatusPointer->weaponTarget.vz -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat13,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
11139
        }
 
 
11140
 
 
 
11141
        /* Here we must have a target.  Renew suspicion for new arrivals. */
 
 
11142
        if (!NpcSquad.Squad_Suspicion)
 
 
11143
            PointAlert(2,&marineStatusPointer->weaponTarget);
 
 
11144
    }
 
 
11145
    /* Otherwise, stay facing the same way. */
 
 
11146
 
 
 
11147
    /* orientate to firing point first */
 
 
11148
{
 
 
11149
    VECTORCH orientationDirn;
 
 
11150
    orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
 
 
11151
    orientationDirn.vy = 0;
 
 
11152
    orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
 
 
11153
    int correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE);
 
 
11154
 
 
 
11155
    /* I have a cunning plan... */
 
 
11156
    {
 
 
11157
        DELTA_CONTROLLER *delta = Get_Delta_Sequence(&marineStatusPointer->HModelController,"HitDelta");
 
 
11158
 
 
 
11159
        if (delta && !DeltaAnimation_IsFinished(delta))
 
 
11160
            correctlyOrientated = 0;
 
 
11161
    }
 
 
11162
 
 
 
11163
    /* I have another cunning plan... */
 
 
11164
    if ((marineStatusPointer->volleySize > 0) && (marineStatusPointer->volleySize < marineStatusPointer->My_Weapon->MinimumBurstSize))
 
 
11165
            correctlyOrientated = 1;
 
 
11166
 
 
 
11167
    /* we are not correctly orientated to the target: this could happen because we have
 
 
11168
    just entered this state, or the target has moved during firing */
 
 
11169
 
 
 
11170
    if(!correctlyOrientated || (marineStatusPointer->HModelController.Tweening != Controller_NoTweening))
 
 
11171
    {
 
 
11172
        /* stop visual and audio cues: technically, we're not firing at this moment */
 
 
11173
        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
11174
 
 
 
11175
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
11176
        {
 
 
11177
            Sound_Stop(marineStatusPointer->soundHandle);
 
 
11178
            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
11179
        }
 
 
11180
 
 
 
11181
        marineStatusPointer->lastroundhit = 0;
 
 
11182
        marineStatusPointer->lasthitsection = NULL;
 
 
11183
        return SRC_No_Change;
 
 
11184
    }
 
 
11185
}
 
 
11186
 
 
 
11187
    if (human_in_los(sbPtr))
 
 
11188
    {
 
 
11189
        marineStatusPointer->Courage += MUL_FIXED(NormalFrameTime, 300);
 
 
11190
        //marineStatusPointer->HModelController.Playing = 0;
 
 
11191
        return ((FastRandom() & 127) > 10) ?  SRC_Request_Approach : SRC_Request_Avoidance; 
 
 
11192
    }
 
 
11193
 
 
 
11194
    marineStatusPointer->weapon_variable += (NormalFrameTime << 7);
 
 
11195
 
 
 
11196
    if (marineStatusPointer->weapon_variable >= MINIGUN_MAX_SPEED)
 
 
11197
    {
 
 
11198
        marineStatusPointer->weapon_variable = MINIGUN_MAX_SPEED;
 
 
11199
        DischargeLOSWeapon_Core(sbPtr);
 
 
11200
    }
 
 
11201
 
 
 
11202
    if (marineStatusPointer->Target == NULL)
 
 
11203
        return SRC_No_Change; /* Getting out of here! */
 
 
11204
 
 
 
11205
    range = VectorDistance(&marineStatusPointer->Target->DynPtr->Position, &sbPtr->DynPtr->Position);
 
 
11206
 
 
 
11207
    /* Did we get him? */
 
 
11208
    if ((NPC_IsDead(marineStatusPointer->Target)) && (marineStatusPointer->volleySize >=
marineStatusPointer->My_Weapon->MinimumBurstSize))
 
 
11209
    {
 
 
11210
        if (MarineRetreatsInTheFaceOfDanger(sbPtr) && Marine_GetNewTarget(&sbPtr->DynPtr->Position,sbPtr) == NULL)
 
 
11211
        {
 
 
11212
            DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
11213
 
 
 
11214
            if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
11215
            {
 
 
11216
                Sound_Stop(marineStatusPointer->soundHandle);
 
 
11217
                Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
11218
            }
 
 
11219
 
 
 
11220
            marineStatusPointer->lastroundhit = 0;
 
 
11221
            marineStatusPointer->lasthitsection = NULL;
 
 
11222
            Marine_Enter_Taunt_State(sbPtr);
 
 
11223
        }
 
 
11224
    }
 
 
11225
 
 
 
11226
    if(marineStatusPointer->stateTimer > 0)
 
 
11227
        return SRC_No_Change;
 
 
11228
 
 
 
11229
    if(range < MARINE_CLOSE_APPROACH_DISTANCE)
 
 
11230
    {
 
 
11231
        /* renew firing, as we are still too close to approach */ 
 
 
11232
        marineStatusPointer->stateTimer = marineStatusPointer->My_Weapon->FiringTime;                     
 
 
11233
        marineStatusPointer->volleySize = 0;
 
 
11234
        assert(marineStatusPointer->Target);
 
 
11235
        NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
 
 
11236
 
 
 
11237
        /* stop visual and audio cues: technically, we're not firing at this moment */
 
 
11238
        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
11239
 
 
 
11240
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
11241
        {
 
 
11242
            Sound_Stop(marineStatusPointer->soundHandle);
 
 
11243
            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
11244
        }
 
 
11245
 
 
 
11246
        if (!marineStatusPointer->Android)
 
 
11247
            marineStatusPointer->Courage -= (ONE_FIXED>>3);
 
 
11248
 
 
 
11249
    return SRC_Request_Fire;
 
 
11250
    }
 
 
11251
    else
 
 
11252
    {
 
 
11253
        /* we are far enough away, so return to approach */
 
 
11254
 
 
 
11255
        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
11256
 
 
 
11257
        /* .... and stop the sound */
 
 
11258
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
11259
        {
 
 
11260
            Sound_Stop(marineStatusPointer->soundHandle);        
 
 
11261
            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
11262
        }
 
 
11263
 
 
 
11264
    return SRC_Request_Approach;
 
 
11265
    }
 
 
11266
 
 
 
11267
return SRC_No_Change;
 
 
11268
}
 
 
11269
 
 
 
11270
static STATE_RETURN_CONDITION Execute_MNS_NullPanicFire(STRATEGYBLOCK *sbPtr)
 
 
11271
{
 
 
11272
    /* This MUST exist to redirect weapons with no panic fire. */
 
 
11273
 
 
 
11274
    /* zero velocity */
 
 
11275
    assert(sbPtr->DynPtr);
 
 
11276
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
11277
 
 
 
11278
return SRC_Request_Wait;
 
 
11279
}
 
 
11280
 
 
 
11281
static STATE_RETURN_CONDITION Execute_MNS_PanicFireLOSWeapon(STRATEGYBLOCK *sbPtr)
 
 
11282
{
 
 
11283
    assert(sbPtr);
 
 
11284
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
11285
    assert(marineStatusPointer);
 
 
11286
 
 
 
11287
    marineStatusPointer->HModelController.Playing = 1;
 
 
11288
 
 
 
11289
    /* zero velocity */
 
 
11290
    assert(sbPtr->DynPtr);
 
 
11291
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
11292
 
 
 
11293
    /* Stabilise sequence. */
 
 
11294
    if (marineStatusPointer->Target == NULL)
 
 
11295
    {
 
 
11296
        switch(marineStatusPointer->HModelController.Sequence_Type)
 
 
11297
        {
 
 
11298
            case HMSQT_MarineStand:
 
 
11299
            case MSSS_WildFire_0:
 
 
11300
            break;
 
 
11301
            default:
 
 
11302
                SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_0, -1, (ONE_FIXED>>3));
 
 
11303
        }
 
 
11304
    }
 
 
11305
    else
 
 
11306
    {
 
 
11307
        VECTORCH *gunpos;
 
 
11308
        /* Pick a sequence based on angle. */
 
 
11309
 
 
 
11310
        if (marineStatusPointer->My_Elevation_Section)
 
 
11311
            gunpos = &marineStatusPointer->My_Elevation_Section->World_Offset;
 
 
11312
        else
 
 
11313
            gunpos = &sbPtr->DynPtr->Position;
 
 
11314
 
 
 
11315
        /* Aim at Target. */
 
 
11316
 
 
 
11317
        int offsetx = (marineStatusPointer->Target->DynPtr->Position.vx) - gunpos->vx;
 
 
11318
        int offsety = (marineStatusPointer->Target->DynPtr->Position.vz) - gunpos->vz;
 
 
11319
        int offseta = -((marineStatusPointer->Target->DynPtr->Position.vy) - gunpos->vy);
 
 
11320
 
 
 
11321
        while( (offsetx > (ONE_FIXED>>2))
 
 
11322
            ||(offsety > (ONE_FIXED>>2))
 
 
11323
            ||(offseta > (ONE_FIXED>>2))
 
 
11324
            ||(offsetx < -(ONE_FIXED>>2))
 
 
11325
            ||(offsety < -(ONE_FIXED>>2))
 
 
11326
            ||(offseta < -(ONE_FIXED>>2)))
 
 
11327
        {
 
 
11328
            offsetx >>= 1;
 
 
11329
            offsety >>= 1;
 
 
11330
            offseta >>= 1;
 
 
11331
        }
 
 
11332
 
 
 
11333
        int offsetz = SqRoot32((offsetx*offsetx)+(offsety*offsety));
 
 
11334
        int angle1 = ArcTan(offseta,offsetz);
 
 
11335
 
 
 
11336
        if (angle1 >= 3072)
 
 
11337
            angle1 -= 4096;
 
 
11338
 
 
 
11339
        if (angle1 >= 2048)
 
 
11340
            angle1 = angle1 - 3072;
 
 
11341
 
 
 
11342
        if (angle1 > 1024)
 
 
11343
            angle1 = 2048 - angle1;
 
 
11344
 
 
 
11345
        assert(angle1 >= -1024);
 
 
11346
        assert(angle1 <= 1024);
 
 
11347
 
 
 
11348
        int sequence = -1;
 
 
11349
        /* Now correct for hysteresis... */
 
 
11350
        {
 
 
11351
            int threshold22,threshold45,threshold67,threshold90,ideal_sequence;
 
 
11352
 
 
 
11353
            switch(marineStatusPointer->HModelController.Sub_Sequence)
 
 
11354
            {
 
 
11355
                case MSSS_WildFire_90:
 
 
11356
                    threshold22 = 70;
 
 
11357
                    threshold45 = 220;
 
 
11358
                    threshold67 = 490;
 
 
11359
                    threshold90 = 730;
 
 
11360
                break;
 
 
11361
                case MSSS_WildFire_67:
 
 
11362
                    threshold22 = 70;
 
 
11363
                    threshold45 = 220;
 
 
11364
                    threshold67 = 490;
 
 
11365
                    threshold90 = 768;
 
 
11366
                break;
 
 
11367
                case MSSS_WildFire_45:
 
 
11368
                    threshold22 = 70;
 
 
11369
                    threshold45 = 220;
 
 
11370
                    threshold67 = 512;
 
 
11371
                    threshold90 = 768;
 
 
11372
                break;
 
 
11373
                case MSSS_WildFire_22:
 
 
11374
                    threshold22 = 70;
 
 
11375
                    threshold45 = 256;
 
 
11376
                    threshold67 = 512;
 
 
11377
                    threshold90 = 768;
 
 
11378
                break;
 
 
11379
                default:
 
 
11380
                    threshold22 = 90;
 
 
11381
                    threshold45 = 256;
 
 
11382
                    threshold67 = 512;
 
 
11383
                    threshold90 = 768;
 
 
11384
            }
 
 
11385
 
 
 
11386
            if (angle1 > threshold90)
 
 
11387
            {
 
 
11388
                ideal_sequence = 4;
 
 
11389
            }
 
 
11390
            else if (angle1 > threshold67)
 
 
11391
            {
 
 
11392
                ideal_sequence = 3;
 
 
11393
            }
 
 
11394
            else if (angle1 > threshold45)
 
 
11395
            {
 
 
11396
                ideal_sequence = 2;
 
 
11397
            }
 
 
11398
            else if (angle1 > threshold22)
 
 
11399
            {
 
 
11400
                ideal_sequence = 1;
 
 
11401
            }
 
 
11402
            else
 
 
11403
            {
 
 
11404
                ideal_sequence = 0;
 
 
11405
            }
 
 
11406
 
 
 
11407
            while (sequence == -1)
 
 
11408
            {
 
 
11409
                switch (ideal_sequence)
 
 
11410
                {
 
 
11411
                    case 0:
 
 
11412
                    default:
 
 
11413
                        sequence = 0;
 
 
11414
                        break;
 
 
11415
                    case 1:
 
 
11416
                        if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_WildFire_22))
 
 
11417
                            sequence = 1;
 
 
11418
                        else
 
 
11419
                            ideal_sequence = 0;
 
 
11420
                        break;
 
 
11421
                    case 2:
 
 
11422
                        if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_WildFire_45))
 
 
11423
                            sequence = 2;
 
 
11424
                        else
 
 
11425
                            ideal_sequence = 1;
 
 
11426
                        break;
 
 
11427
                    case 3:
 
 
11428
                        if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_WildFire_67))
 
 
11429
                            sequence = 3;
 
 
11430
                        else
 
 
11431
                            ideal_sequence = 2;
 
 
11432
                        break;
 
 
11433
                    case 4:
 
 
11434
                        if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_WildFire_90))
 
 
11435
                            sequence = 4;
 
 
11436
                        else
 
 
11437
                            ideal_sequence = 3;
 
 
11438
                        break;
 
 
11439
                }
 
 
11440
            }
 
 
11441
        }
 
 
11442
 
 
 
11443
        switch (sequence)
 
 
11444
        {
 
 
11445
            case 4:
 
 
11446
                if ((marineStatusPointer->HModelController.Sequence_Type != HMSQT_MarineStand)
 
 
11447
                    || (marineStatusPointer->HModelController.Sub_Sequence != MSSS_WildFire_90))
 
 
11448
                {
 
 
11449
                    SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_90, -1, (ONE_FIXED>>3));
 
 
11450
                }
 
 
11451
                break;
 
 
11452
            case 3:
 
 
11453
                if ((marineStatusPointer->HModelController.Sequence_Type != HMSQT_MarineStand)
 
 
11454
                    || (marineStatusPointer->HModelController.Sub_Sequence != MSSS_WildFire_67))
 
 
11455
                {
 
 
11456
                    SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_67, -1, (ONE_FIXED>>3));
 
 
11457
                }
 
 
11458
                break;
 
 
11459
            case 2:
 
 
11460
                if ((marineStatusPointer->HModelController.Sequence_Type != HMSQT_MarineStand)
 
 
11461
                    ||(marineStatusPointer->HModelController.Sub_Sequence != MSSS_WildFire_45))
 
 
11462
                {
 
 
11463
                    SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_45, -1, (ONE_FIXED>>3));
 
 
11464
                }
 
 
11465
                break;
 
 
11466
            case 1:
 
 
11467
                if ((marineStatusPointer->HModelController.Sequence_Type != HMSQT_MarineStand)
 
 
11468
                    ||(marineStatusPointer->HModelController.Sub_Sequence != MSSS_WildFire_22))
 
 
11469
                {
 
 
11470
                    SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_22, -1, (ONE_FIXED>>3));
 
 
11471
                }
 
 
11472
                break;
 
 
11473
            case 0:
 
 
11474
            default:
 
 
11475
                if ((marineStatusPointer->HModelController.Sequence_Type != HMSQT_MarineStand)
 
 
11476
                    ||(marineStatusPointer->HModelController.Sub_Sequence != MSSS_WildFire_0))
 
 
11477
                {
 
 
11478
                    SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_0, -1, (ONE_FIXED>>3));
 
 
11479
                }
 
 
11480
                break;
 
 
11481
        }
 
 
11482
    }
 
 
11483
 
 
 
11484
    if (marineStatusPointer->clipammo <= 0)
 
 
11485
        return SRC_Request_PanicReload;
 
 
11486
 
 
 
11487
    /* Scream handling. */
 
 
11488
    if (marineStatusPointer->soundHandle2 == SOUND_NOACTIVEINDEX)
 
 
11489
    {
 
 
11490
        if (marineStatusPointer->incidentFlag && Marine_HasHisMouthOpen(sbPtr))
 
 
11491
        {
 
 
11492
            if (marineStatusPointer->My_Weapon->id == MNPCW_MUnarmed)
 
 
11493
                Marine_AngryScream(sbPtr);
 
 
11494
        }
 
 
11495
    }
 
 
11496
 
 
 
11497
    if (marineStatusPointer->Target == NULL)
 
 
11498
    {
 
 
11499
        if (marineStatusPointer->incidentFlag)
 
 
11500
        {
 
 
11501
            /* Courage roll to stop. */
 
 
11502
            if (MarineRetreatsInTheFaceOfDanger(sbPtr) == 0)
 
 
11503
            {
 
 
11504
                DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
11505
 
 
 
11506
                if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
11507
                {
 
 
11508
                    Sound_Stop(marineStatusPointer->soundHandle);
 
 
11509
                    Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
11510
                }
 
 
11511
 
 
 
11512
                /* Try to be suspicious? */
 
 
11513
                marineStatusPointer->suspicious = MARINE_PANIC_TIME;
 
 
11514
                marineStatusPointer->suspect_point = marineStatusPointer->weaponTarget;
 
 
11515
                /* Set this to zero when you get a *new* suspicion. */
 
 
11516
                marineStatusPointer->previous_suspicion = 0;
 
 
11517
                marineStatusPointer->using_squad_suspicion = 0;
 
 
11518
 
 
 
11519
            return SRC_Request_Wait;
 
 
11520
            }
 
 
11521
        }
 
 
11522
    }
 
 
11523
    else
 
 
11524
    {
 
 
11525
        assert(marineStatusPointer->Target);
 
 
11526
 
 
 
11527
        NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
 
 
11528
 
 
 
11529
        /* orientate to firing point first */
 
 
11530
        VECTORCH orientationDirn;
 
 
11531
        orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
 
 
11532
        orientationDirn.vy = 0;
 
 
11533
        orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
 
 
11534
        int correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE);
 
 
11535
 
 
 
11536
        if (correctlyOrientated && !MarineCanSeeTarget(sbPtr))
 
 
11537
            marineStatusPointer->Target = NULL; /* Lost target... */
 
 
11538
    }
 
 
11539
 
 
 
11540
    if (!NpcSquad.Squad_Suspicion)
 
 
11541
    {
 
 
11542
        if (marineStatusPointer->Target)
 
 
11543
        {
 
 
11544
            /* Here we must have a target.  Renew suspicion for new arrivals. */
 
 
11545
            PointAlert(2,&marineStatusPointer->weaponTarget);
 
 
11546
        }
 
 
11547
        else
 
 
11548
        {
 
 
11549
            PointAlert(1,&sbPtr->DynPtr->Position);
 
 
11550
        }
 
 
11551
    }
 
 
11552
 
 
 
11553
    /* Wait for end of tweening before we proceed. */
 
 
11554
    if (marineStatusPointer->HModelController.Tweening != Controller_NoTweening)
 
 
11555
    {
 
 
11556
        /* stop visual and audio cues: technically, we're not firing at this moment */
 
 
11557
        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
11558
 
 
 
11559
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
11560
        {
 
 
11561
            Sound_Stop(marineStatusPointer->soundHandle);
 
 
11562
            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
11563
        }
 
 
11564
 
 
 
11565
    return SRC_No_Change;
 
 
11566
    }
 
 
11567
 
 
 
11568
    /* Right.  Correctly orientated or not, we blaze away. */
 
 
11569
 
 
 
11570
    MaintainMarineGunFlash(sbPtr);
 
 
11571
 
 
 
11572
    /* look after the sound */
 
 
11573
    if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
11574
    {
 
 
11575
        Sound_Update3d(marineStatusPointer->soundHandle,&(sbPtr->DynPtr->Position));
 
 
11576
    }
 
 
11577
    else 
 
 
11578
    { 
 
 
11579
        Sound_Play(marineStatusPointer->My_Weapon->StartSound, "d", &sbPtr->DynPtr->Position);
 
 
11580
        Sound_Play(marineStatusPointer->My_Weapon->LoopSound, "del", &sbPtr->DynPtr->Position,
&marineStatusPointer->soundHandle);
 
 
11581
    }
 
 
11582
 
 
 
11583
    marineStatusPointer->stateTimer -= NormalFrameTime;
 
 
11584
 
 
 
11585
    /* Volleysize is now rounds fired this state. */
 
 
11586
 
 
 
11587
    int volleytime = marineStatusPointer->My_Weapon->FiringTime-marineStatusPointer->stateTimer;
 
 
11588
    /* It was that or reverse the state timer for this state. */
 
 
11589
    int volleyrounds = MUL_FIXED(volleytime, marineStatusPointer->My_Weapon->FiringRate);
 
 
11590
    volleyrounds >>= ONE_FIXED_SHIFT;
 
 
11591
    volleyrounds -= marineStatusPointer->volleySize;
 
 
11592
    marineStatusPointer->volleySize += volleyrounds;
 
 
11593
 
 
 
11594
    assert(volleyrounds >= 0);
 
 
11595
 
 
 
11596
    if (marineStatusPointer->clipammo != -1)
 
 
11597
    {
 
 
11598
        /* We're counting ammo. */
 
 
11599
        if (volleyrounds>marineStatusPointer->clipammo)
 
 
11600
            volleyrounds = marineStatusPointer->clipammo;
 
 
11601
 
 
 
11602
        marineStatusPointer->clipammo -= volleyrounds;
 
 
11603
        assert(marineStatusPointer->clipammo>=0);
 
 
11604
    }
 
 
11605
 
 
 
11606
    /* Now fire volleyrounds bullets. */
 
 
11607
    if (volleyrounds > 0)
 
 
11608
    {
 
 
11609
        VECTORCH shotvector = {0, 0, 65535};
 
 
11610
        RotateVector(&shotvector,&marineStatusPointer->My_Gunflash_Section->SecMat);
 
 
11611
        CastLOSProjectile(sbPtr, &marineStatusPointer->My_Gunflash_Section->World_Offset, &shotvector,
marineStatusPointer->My_Weapon->Ammo_Type, volleyrounds, 1);
 
 
11612
    }
 
 
11613
 
 
 
11614
    /* Now, consider termination. */
 
 
11615
 
 
 
11616
    if (marineStatusPointer->incidentFlag)
 
 
11617
    {
 
 
11618
        if (MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
11619
        {
 
 
11620
            /* Two consecutive tests... */
 
 
11621
            if (MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
11622
            {
 
 
11623
                /* stop visual and audio cues: technically, we're not firing at this moment */
 
 
11624
                DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
11625
 
 
 
11626
                if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
11627
                {
 
 
11628
                    Sound_Stop(marineStatusPointer->soundHandle);
 
 
11629
                    Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
11630
                }
 
 
11631
 
 
 
11632
                return SRC_Request_Retreat;
 
 
11633
            }
 
 
11634
        }
 
 
11635
    }
 
 
11636
 
 
 
11637
return SRC_No_Change;
 
 
11638
}
 
 
11639
 
 
 
11640
static STATE_RETURN_CONDITION Execute_MNS_PanicFireFlamethrower(STRATEGYBLOCK *sbPtr)
 
 
11641
{
 
 
11642
    assert(sbPtr);
 
 
11643
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
11644
    assert(marineStatusPointer);
 
 
11645
 
 
 
11646
    marineStatusPointer->HModelController.Playing = 1;
 
 
11647
 
 
 
11648
    /* zero velocity */
 
 
11649
    assert(sbPtr->DynPtr);
 
 
11650
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
11651
 
 
 
11652
    /* Stabilise sequence. */
 
 
11653
    if (marineStatusPointer->Target == NULL)
 
 
11654
    {
 
 
11655
        switch(marineStatusPointer->HModelController.Sequence_Type)
 
 
11656
        {
 
 
11657
            case HMSQT_MarineStand:
 
 
11658
            case MSSS_WildFire_0:
 
 
11659
            break;
 
 
11660
            default:
 
 
11661
                SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_0, -1, (ONE_FIXED>>3));
 
 
11662
        }
 
 
11663
    }
 
 
11664
    else
 
 
11665
    {
 
 
11666
        VECTORCH *gunpos;
 
 
11667
        /* Pick a sequence based on angle. */
 
 
11668
 
 
 
11669
        if (marineStatusPointer->My_Elevation_Section)
 
 
11670
            gunpos = &marineStatusPointer->My_Elevation_Section->World_Offset;
 
 
11671
        else
 
 
11672
            gunpos = &sbPtr->DynPtr->Position;
 
 
11673
 
 
 
11674
        /* Aim at Target. */
 
 
11675
 
 
 
11676
        int offsetx = (marineStatusPointer->Target->DynPtr->Position.vx)-(gunpos->vx);
 
 
11677
        int offsety = (marineStatusPointer->Target->DynPtr->Position.vz)-(gunpos->vz);
 
 
11678
        int offseta = -((marineStatusPointer->Target->DynPtr->Position.vy)-(gunpos->vy));
 
 
11679
 
 
 
11680
        while( (offsetx > (ONE_FIXED>>2))
 
 
11681
            ||(offsety > (ONE_FIXED>>2))
 
 
11682
            ||(offseta > (ONE_FIXED>>2))
 
 
11683
            ||(offsetx < -(ONE_FIXED>>2))
 
 
11684
            ||(offsety < -(ONE_FIXED>>2))
 
 
11685
            ||(offseta < -(ONE_FIXED>>2)))
 
 
11686
        {
 
 
11687
            offsetx >>= 1;
 
 
11688
            offsety >>= 1;
 
 
11689
            offseta >>= 1;
 
 
11690
        }
 
 
11691
 
 
 
11692
        int offsetz = SqRoot32((offsetx*offsetx)+(offsety*offsety));
 
 
11693
        int angle1 = ArcTan(offseta,offsetz);
 
 
11694
 
 
 
11695
        if (angle1 >= 3072)
 
 
11696
            angle1 -= 4096;
 
 
11697
 
 
 
11698
        if (angle1 >= 2048)
 
 
11699
            angle1 = angle1 - 3072;
 
 
11700
 
 
 
11701
        if (angle1 > 1024)
 
 
11702
            angle1 = 2048 - angle1;
 
 
11703
 
 
 
11704
        assert(angle1 >= -1024);
 
 
11705
        assert(angle1 <= 1024);
 
 
11706
 
 
 
11707
        /* Now correct for hysteresis... */
 
 
11708
        {
 
 
11709
            int highthreshold,topthreshold;
 
 
11710
 
 
 
11711
            switch(marineStatusPointer->HModelController.Sub_Sequence)
 
 
11712
            {
 
 
11713
                case MSSS_WildFire_90:
 
 
11714
                    highthreshold = 90;
 
 
11715
                    topthreshold = 1024 - 300;
 
 
11716
                break;
 
 
11717
                case MSSS_WildFire_45:
 
 
11718
                    highthreshold = 90;
 
 
11719
                    topthreshold = 1024 - 256;
 
 
11720
                break;
 
 
11721
                default:
 
 
11722
                    highthreshold = 128;
 
 
11723
                    topthreshold = 1024 - 256;
 
 
11724
            }
 
 
11725
 
 
 
11726
            if (angle1 > topthreshold)
 
 
11727
            {
 
 
11728
                if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_WildFire_90))
 
 
11729
                {
 
 
11730
                    /* Escape for civvie flamethrower here? */
 
 
11731
                    switch(marineStatusPointer->HModelController.Sequence_Type)
 
 
11732
                    {
 
 
11733
                        case HMSQT_MarineStand:
 
 
11734
                        case MSSS_WildFire_90:
 
 
11735
                        break;
 
 
11736
                        default:
 
 
11737
                            SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_90, -1, (ONE_FIXED>>3));
 
 
11738
                    }
 
 
11739
                }
 
 
11740
            }
 
 
11741
            else if (angle1 > highthreshold) //Was 256!
 
 
11742
            {
 
 
11743
                if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_WildFire_45))
 
 
11744
                {
 
 
11745
                    switch(marineStatusPointer->HModelController.Sequence_Type)
 
 
11746
                    {
 
 
11747
                        case HMSQT_MarineStand:
 
 
11748
                        case MSSS_WildFire_45:
 
 
11749
                        break;
 
 
11750
                        default:
 
 
11751
                            SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_45, -1, (ONE_FIXED>>3));
 
 
11752
                    }
 
 
11753
                }
 
 
11754
            }
 
 
11755
            else
 
 
11756
            {
 
 
11757
                switch(marineStatusPointer->HModelController.Sequence_Type)
 
 
11758
                {
 
 
11759
                    case HMSQT_MarineStand:
 
 
11760
                    case MSSS_WildFire_0:
 
 
11761
                    break;
 
 
11762
                    default:
 
 
11763
                        SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_0, -1, (ONE_FIXED>>3));
 
 
11764
                }
 
 
11765
            }
 
 
11766
 
 
 
11767
        }
 
 
11768
    }
 
 
11769
 
 
 
11770
    if (marineStatusPointer->Target == NULL)
 
 
11771
    {
 
 
11772
        if (marineStatusPointer->incidentFlag)
 
 
11773
        {
 
 
11774
            /* Courage roll to stop. */
 
 
11775
            if (!MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
11776
            {
 
 
11777
                /* Okay, calm down a bit. */
 
 
11778
                DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
11779
 
 
 
11780
                if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
11781
                {
 
 
11782
                    Sound_Stop(marineStatusPointer->soundHandle);
 
 
11783
                    Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
11784
                }
 
 
11785
 
 
 
11786
                /* Try to be suspicious? */
 
 
11787
                marineStatusPointer->suspicious = MARINE_PANIC_TIME;
 
 
11788
                marineStatusPointer->suspect_point = marineStatusPointer->weaponTarget;
 
 
11789
                /* Set this to zero when you get a *new* suspicion. */
 
 
11790
                marineStatusPointer->previous_suspicion = 0;
 
 
11791
                marineStatusPointer->using_squad_suspicion = 0;
 
 
11792
 
 
 
11793
                return SRC_Request_Wait;
 
 
11794
            }
 
 
11795
        }
 
 
11796
    }
 
 
11797
    else
 
 
11798
    {
 
 
11799
        assert(marineStatusPointer->Target);
 
 
11800
 
 
 
11801
        NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
 
 
11802
 
 
 
11803
        /* orientate to firing point first */
 
 
11804
        VECTORCH orientationDirn;
 
 
11805
        orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
 
 
11806
        orientationDirn.vy = 0;
 
 
11807
        orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
 
 
11808
        int correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE);
 
 
11809
 
 
 
11810
        if (correctlyOrientated && !MarineCanSeeTarget(sbPtr))
 
 
11811
            marineStatusPointer->Target = NULL;
 
 
11812
    }
 
 
11813
 
 
 
11814
    if (marineStatusPointer->clipammo <= 0)
 
 
11815
    {
 
 
11816
        if (MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
11817
            return (marineStatusPointer->My_Weapon->ARealMarine) ? SRC_Request_PullPistol : SRC_Request_PanicReload;
 
 
11818
        else
 
 
11819
            return SRC_Request_PanicReload;
 
 
11820
    }
 
 
11821
 
 
 
11822
    /* Scream handling. */
 
 
11823
    if (marineStatusPointer->soundHandle2 == SOUND_NOACTIVEINDEX)
 
 
11824
    {
 
 
11825
        if (marineStatusPointer->incidentFlag)
 
 
11826
        {
 
 
11827
            if (Marine_HasHisMouthOpen(sbPtr))
 
 
11828
            {
 
 
11829
                if (marineStatusPointer->My_Weapon->id == MNPCW_MUnarmed)
 
 
11830
                    Marine_AngryScream(sbPtr);
 
 
11831
            }
 
 
11832
        }
 
 
11833
    }
 
 
11834
 
 
 
11835
    if (!NpcSquad.Squad_Suspicion)
 
 
11836
    {
 
 
11837
        if (marineStatusPointer->Target)
 
 
11838
        {
 
 
11839
            /* Here we must have a target.  Renew suspicion for new arrivals. */
 
 
11840
            PointAlert(2,&marineStatusPointer->weaponTarget);
 
 
11841
        }
 
 
11842
        else
 
 
11843
        {
 
 
11844
            PointAlert(1,&sbPtr->DynPtr->Position);
 
 
11845
        }
 
 
11846
    }
 
 
11847
 
 
 
11848
    DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
11849
 
 
 
11850
    /* Wait for end of tweening before we proceed. */
 
 
11851
    if (marineStatusPointer->HModelController.Tweening != Controller_NoTweening)
 
 
11852
    {
 
 
11853
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
11854
        {
 
 
11855
            Sound_Stop(marineStatusPointer->soundHandle);
 
 
11856
            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
11857
        }
 
 
11858
 
 
 
11859
    return SRC_No_Change;
 
 
11860
    }
 
 
11861
 
 
 
11862
    /* look after the sound */
 
 
11863
    if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
11864
    {
 
 
11865
        Sound_Update3d(marineStatusPointer->soundHandle,&(sbPtr->DynPtr->Position));
 
 
11866
    }
 
 
11867
    else 
 
 
11868
    { 
 
 
11869
        Sound_Play(marineStatusPointer->My_Weapon->StartSound, "d", &sbPtr->DynPtr->Position);
 
 
11870
        Sound_Play(marineStatusPointer->My_Weapon->LoopSound, "del", &sbPtr->DynPtr->Position,
&marineStatusPointer->soundHandle);
 
 
11871
    }
 
 
11872
 
 
 
11873
    marineStatusPointer->stateTimer -= NormalFrameTime;
 
 
11874
 
 
 
11875
    MarineFireFlameThrower(sbPtr);
 
 
11876
 
 
 
11877
    /* Lighting? */
 
 
11878
    if (sbPtr->DisplayBlock)
 
 
11879
        AddLightingEffectToObject(sbPtr->DisplayBlock,LFX_MUZZLEFLASH);
 
 
11880
 
 
 
11881
    if (marineStatusPointer->clipammo > 0)
 
 
11882
    {
 
 
11883
        marineStatusPointer->clipammo -= NormalFrameTime;
 
 
11884
 
 
 
11885
        if (marineStatusPointer->clipammo < 0)
 
 
11886
            marineStatusPointer->clipammo =0;
 
 
11887
    }
 
 
11888
 
 
 
11889
    /* Now, consider termination. */
 
 
11890
 
 
 
11891
    if (marineStatusPointer->incidentFlag)
 
 
11892
    {
 
 
11893
        if (MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
11894
        {
 
 
11895
            /* Two consecutive tests... */
 
 
11896
            if (MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
11897
            {
 
 
11898
                /* stop visual and audio cues: technically, we're not firing at this moment */
 
 
11899
                DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
11900
 
 
 
11901
                if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
11902
                {
 
 
11903
                    Sound_Stop(marineStatusPointer->soundHandle);
 
 
11904
                    Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
11905
                }
 
 
11906
 
 
 
11907
            return SRC_Request_Retreat;
 
 
11908
            }
 
 
11909
        }
 
 
11910
    }
 
 
11911
 
 
 
11912
return SRC_No_Change;
 
 
11913
}
 
 
11914
 
 
 
11915
static STATE_RETURN_CONDITION Execute_MNS_PanicFireGL(STRATEGYBLOCK *sbPtr)
 
 
11916
{
 
 
11917
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
11918
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
11919
 
 
 
11920
    marineStatusPointer->HModelController.Playing = 1;
 
 
11921
 
 
 
11922
    /* Stabilise sequence. */
 
 
11923
    if (marineStatusPointer->Target == NULL)
 
 
11924
    {
 
 
11925
        switch(marineStatusPointer->HModelController.Sequence_Type)
 
 
11926
        {
 
 
11927
            case HMSQT_MarineStand:
 
 
11928
            case MSSS_WildFire_0:
 
 
11929
            break;
 
 
11930
            default:
 
 
11931
                SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_0, -1, (ONE_FIXED>>3));
 
 
11932
        }
 
 
11933
    }
 
 
11934
    else
 
 
11935
    {
 
 
11936
        VECTORCH *gunpos;
 
 
11937
        /* Pick a sequence based on angle. */
 
 
11938
 
 
 
11939
        if (marineStatusPointer->My_Elevation_Section)
 
 
11940
            gunpos = &marineStatusPointer->My_Elevation_Section->World_Offset;
 
 
11941
        else
 
 
11942
            gunpos = &sbPtr->DynPtr->Position;
 
 
11943
 
 
 
11944
        /* Aim at Target. */
 
 
11945
 
 
 
11946
        int offsetx = marineStatusPointer->Target->DynPtr->Position.vx - gunpos->vx;
 
 
11947
        int offsety = marineStatusPointer->Target->DynPtr->Position.vz - gunpos->vz;
 
 
11948
        int offseta = -(marineStatusPointer->Target->DynPtr->Position.vy - gunpos->vy);
 
 
11949
 
 
 
11950
        while( (offsetx > (ONE_FIXED>>2))
 
 
11951
            ||(offsety > (ONE_FIXED>>2))
 
 
11952
            ||(offseta > (ONE_FIXED>>2))
 
 
11953
            ||(offsetx < -(ONE_FIXED>>2))
 
 
11954
            ||(offsety < -(ONE_FIXED>>2))
 
 
11955
            ||(offseta < -(ONE_FIXED>>2)))
 
 
11956
        {
 
 
11957
            offsetx >>= 1;
 
 
11958
            offsety >>= 1;
 
 
11959
            offseta >>= 1;
 
 
11960
        }
 
 
11961
 
 
 
11962
        int offsetz = SqRoot32((offsetx*offsetx)+(offsety*offsety));
 
 
11963
        int angle1 = ArcTan(offseta,offsetz);
 
 
11964
 
 
 
11965
        if (angle1 >= 3072)
 
 
11966
            angle1 -= 4096;
 
 
11967
 
 
 
11968
        if (angle1 >= 2048)
 
 
11969
            angle1 = angle1-3072;
 
 
11970
 
 
 
11971
        if (angle1 > 1024)
 
 
11972
            angle1 = 2048-angle1;
 
 
11973
 
 
 
11974
        assert(angle1 >= -1024);
 
 
11975
        assert(angle1 <= 1024);
 
 
11976
 
 
 
11977
        /* Now correct for hysteresis... */
 
 
11978
        {
 
 
11979
            int highthreshold,topthreshold;
 
 
11980
 
 
 
11981
            switch(marineStatusPointer->HModelController.Sub_Sequence)
 
 
11982
            {
 
 
11983
                case MSSS_WildFire_90:
 
 
11984
                    highthreshold = 90;
 
 
11985
                    topthreshold = 1024 - 300;
 
 
11986
                break;
 
 
11987
                case MSSS_WildFire_45:
 
 
11988
                    highthreshold = 90;
 
 
11989
                    topthreshold = 1024 - 256;
 
 
11990
                break;
 
 
11991
                default:
 
 
11992
                    highthreshold = 128;
 
 
11993
                    topthreshold = 1024 - 256;
 
 
11994
            }
 
 
11995
 
 
 
11996
            if (angle1 > topthreshold)
 
 
11997
            {
 
 
11998
                if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_WildFire_90))
 
 
11999
                {
 
 
12000
                    /* Escape for civvie flamethrower here? */
 
 
12001
                    switch(marineStatusPointer->HModelController.Sequence_Type)
 
 
12002
                    {
 
 
12003
                        case HMSQT_MarineStand:
 
 
12004
                        case MSSS_WildFire_90:
 
 
12005
                        break;
 
 
12006
                        default:
 
 
12007
                            SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_90, -1, (ONE_FIXED>>3));
 
 
12008
                    }
 
 
12009
                }
 
 
12010
            }
 
 
12011
            else if (angle1 > highthreshold) //Was 256!
 
 
12012
            {
 
 
12013
                if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_WildFire_45))
 
 
12014
                {
 
 
12015
                    switch(marineStatusPointer->HModelController.Sequence_Type)
 
 
12016
                    {
 
 
12017
                        case HMSQT_MarineStand:
 
 
12018
                        case MSSS_WildFire_45:
 
 
12019
                        break;
 
 
12020
                        default:
 
 
12021
                            SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_45, -1 ,(ONE_FIXED>>3));
 
 
12022
                    }
 
 
12023
                }
 
 
12024
            }
 
 
12025
            else
 
 
12026
            {
 
 
12027
                switch(marineStatusPointer->HModelController.Sequence_Type)
 
 
12028
                {
 
 
12029
                    case HMSQT_MarineStand:
 
 
12030
                    case MSSS_WildFire_0:
 
 
12031
                    break;
 
 
12032
                    default:
 
 
12033
                        SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_0, -1, (ONE_FIXED>>3));
 
 
12034
                }
 
 
12035
            }
 
 
12036
        }
 
 
12037
    }
 
 
12038
 
 
 
12039
    if (marineStatusPointer->Target == NULL)
 
 
12040
    {
 
 
12041
        if (marineStatusPointer->incidentFlag)
 
 
12042
        {
 
 
12043
            /* Courage roll to stop. */
 
 
12044
            if (!MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
12045
            {
 
 
12046
                /* Okay, calm down a bit. */
 
 
12047
                DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
12048
 
 
 
12049
                if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
12050
                {
 
 
12051
                    Sound_Stop(marineStatusPointer->soundHandle);
 
 
12052
                    Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
12053
                }
 
 
12054
 
 
 
12055
                /* Try to be suspicious? */
 
 
12056
                marineStatusPointer->suspicious = MARINE_PANIC_TIME;
 
 
12057
                marineStatusPointer->suspect_point = marineStatusPointer->weaponTarget;
 
 
12058
                /* Set this to zero when you get a *new* suspicion. */
 
 
12059
                marineStatusPointer->previous_suspicion = 0;
 
 
12060
                marineStatusPointer->using_squad_suspicion = 0;
 
 
12061
 
 
 
12062
                return SRC_Request_Wait;
 
 
12063
            }
 
 
12064
        }
 
 
12065
    }
 
 
12066
    else
 
 
12067
    {
 
 
12068
        NPCGetTargetPosition(&marineStatusPointer->weaponTarget, marineStatusPointer->Target);
 
 
12069
 
 
 
12070
        /* orientate to firing point first */
 
 
12071
        VECTORCH orientationDirn;
 
 
12072
        orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
 
 
12073
        orientationDirn.vy = 0;
 
 
12074
        orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
 
 
12075
        int correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE);
 
 
12076
 
 
 
12077
        if (correctlyOrientated && !MarineCanSeeTarget(sbPtr))
 
 
12078
            marineStatusPointer->Target = NULL;
 
 
12079
    }
 
 
12080
 
 
 
12081
    if (marineStatusPointer->clipammo <= 0)
 
 
12082
        return SRC_Request_PanicReload;
 
 
12083
 
 
 
12084
    /* Scream handling. */
 
 
12085
    if (marineStatusPointer->soundHandle2 == SOUND_NOACTIVEINDEX)
 
 
12086
    {
 
 
12087
        if (marineStatusPointer->incidentFlag)
 
 
12088
        {
 
 
12089
            if (Marine_HasHisMouthOpen(sbPtr))
 
 
12090
            {
 
 
12091
                if (marineStatusPointer->My_Weapon->id == MNPCW_MUnarmed)
 
 
12092
                    Marine_AngryScream(sbPtr);
 
 
12093
            }
 
 
12094
        }
 
 
12095
    }
 
 
12096
 
 
 
12097
    if (!NpcSquad.Squad_Suspicion)
 
 
12098
    {
 
 
12099
        if (marineStatusPointer->Target)
 
 
12100
        {
 
 
12101
            /* Here we must have a target.  Renew suspicion for new arrivals. */
 
 
12102
            PointAlert(2,&marineStatusPointer->weaponTarget);
 
 
12103
        }
 
 
12104
        else
 
 
12105
        {
 
 
12106
            PointAlert(1,&sbPtr->DynPtr->Position);
 
 
12107
        }
 
 
12108
    }
 
 
12109
 
 
 
12110
    /* Wait for end of tweening before we proceed. */
 
 
12111
    if (marineStatusPointer->HModelController.Tweening != Controller_NoTweening)
 
 
12112
    {
 
 
12113
        /* stop visual and audio cues: technically, we're not firing at this moment */
 
 
12114
        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
12115
 
 
 
12116
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
12117
        {
 
 
12118
            Sound_Stop(marineStatusPointer->soundHandle);
 
 
12119
            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
12120
        }
 
 
12121
 
 
 
12122
        return SRC_No_Change;
 
 
12123
    }
 
 
12124
 
 
 
12125
    /* Stop cues anyway? */
 
 
12126
    DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
12127
 
 
 
12128
    if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
12129
    {
 
 
12130
        Sound_Stop(marineStatusPointer->soundHandle);
 
 
12131
        Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
12132
    }
 
 
12133
 
 
 
12134
    if (marineStatusPointer->Target)
 
 
12135
    {
 
 
12136
        int range = VectorDistance((&marineStatusPointer->Target->DynPtr->Position),(&sbPtr->DynPtr->Position));
 
 
12137
 
 
 
12138
        /* Are they, by some chance, really close? */
 
 
12139
        if (range < marineStatusPointer->My_Weapon->MinRange)
 
 
12140
        {
 
 
12141
            if (!MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
12142
            {
 
 
12143
                /* Stay cool. */
 
 
12144
                return SRC_Request_PullPistol;
 
 
12145
            }
 
 
12146
            /* Probably can't flee... :-) */
 
 
12147
        }
 
 
12148
    }
 
 
12149
 
 
 
12150
    /* Right.  Correctly orientated or not, we blaze away. */
 
 
12151
 
 
 
12152
    int keyframeflags = marineStatusPointer->HModelController.keyframe_flags >> 1;
 
 
12153
 
 
 
12154
    /* I know there are only four firing points... */
 
 
12155
    int a = 0;
 
 
12156
    for (a=0; a < 4; a++)
 
 
12157
    {
 
 
12158
        if (keyframeflags & 1)
 
 
12159
        {
 
 
12160
            /* Fire a grenade! */
 
 
12161
 
 
 
12162
            MaintainMarineGunFlash(sbPtr);
 
 
12163
 
 
 
12164
            /* look after the sound */
 
 
12165
            if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
12166
            {
 
 
12167
                Sound_Update3d(marineStatusPointer->soundHandle, &sbPtr->DynPtr->Position);
 
 
12168
            }
 
 
12169
            else
 
 
12170
            { 
 
 
12171
                Sound_Play(marineStatusPointer->My_Weapon->StartSound, "d", &sbPtr->DynPtr->Position);
 
 
12172
                Sound_Play(marineStatusPointer->My_Weapon->LoopSound, "del", &sbPtr->DynPtr->Position,
&marineStatusPointer->soundHandle);
 
 
12173
            }
 
 
12174
 
 
 
12175
            assert(marineStatusPointer->My_Gunflash_Section);
 
 
12176
            CreateGrenadeKernel(I_BehaviourGrenade, &marineStatusPointer->My_Gunflash_Section->World_Offset,
&marineStatusPointer->My_Gunflash_Section->SecMat,0);
 
 
12177
 
 
 
12178
            if (marineStatusPointer->clipammo > 0)
 
 
12179
                marineStatusPointer->clipammo--;
 
 
12180
        }
 
 
12181
 
 
 
12182
        keyframeflags >>= 1;
 
 
12183
    }
 
 
12184
 
 
 
12185
    /* ...and they are all identical. */
 
 
12186
 
 
 
12187
    /* Now, consider termination. */
 
 
12188
 
 
 
12189
    if (marineStatusPointer->incidentFlag)
 
 
12190
    {
 
 
12191
        if (MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
12192
        {
 
 
12193
            /* Two consecutive tests... */
 
 
12194
            if (MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
12195
            {
 
 
12196
                /* stop visual and audio cues: technically, we're not firing at this moment */
 
 
12197
                DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
12198
 
 
 
12199
                if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX)
 
 
12200
                {
 
 
12201
                    Sound_Stop(marineStatusPointer->soundHandle);
 
 
12202
                    Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
12203
                }
 
 
12204
 
 
 
12205
            return SRC_Request_Retreat;
 
 
12206
            }
 
 
12207
        }
 
 
12208
    }
 
 
12209
 
 
 
12210
return SRC_No_Change;
 
 
12211
}
 
 
12212
 
 
 
12213
static STATE_RETURN_CONDITION Execute_MNS_PanicFireMinigun(STRATEGYBLOCK *sbPtr)
 
 
12214
{
 
 
12215
    assert(sbPtr);
 
 
12216
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
12217
    assert(marineStatusPointer);
 
 
12218
 
 
 
12219
    marineStatusPointer->HModelController.Playing = 1;
 
 
12220
 
 
 
12221
    /* zero velocity */
 
 
12222
    assert(sbPtr->DynPtr);
 
 
12223
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
12224
 
 
 
12225
    /* Stabilise sequence. */
 
 
12226
    if (marineStatusPointer->Target == NULL)
 
 
12227
    {
 
 
12228
        switch(marineStatusPointer->HModelController.Sequence_Type)
 
 
12229
        {
 
 
12230
            case HMSQT_MarineStand:
 
 
12231
            case MSSS_WildFire_0:
 
 
12232
            break;
 
 
12233
            default:
 
 
12234
                SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_0, -1, (ONE_FIXED>>3));
 
 
12235
        }
 
 
12236
    }
 
 
12237
    else
 
 
12238
    {
 
 
12239
        VECTORCH *gunpos;
 
 
12240
        /* Pick a sequence based on angle. */
 
 
12241
 
 
 
12242
        if (marineStatusPointer->My_Elevation_Section)
 
 
12243
            gunpos = &marineStatusPointer->My_Elevation_Section->World_Offset;
 
 
12244
        else
 
 
12245
            gunpos = &sbPtr->DynPtr->Position;
 
 
12246
 
 
 
12247
        /* Aim at Target. */
 
 
12248
 
 
 
12249
        int offsetx = marineStatusPointer->Target->DynPtr->Position.vx - gunpos->vx;
 
 
12250
        int offsety = marineStatusPointer->Target->DynPtr->Position.vz - gunpos->vz;
 
 
12251
        int offseta = -(marineStatusPointer->Target->DynPtr->Position.vy - gunpos->vy);
 
 
12252
 
 
 
12253
        while( (offsetx > (ONE_FIXED>>2))
 
 
12254
            ||(offsety > (ONE_FIXED>>2))
 
 
12255
            ||(offseta > (ONE_FIXED>>2))
 
 
12256
            ||(offsetx < -(ONE_FIXED>>2))
 
 
12257
            ||(offsety < -(ONE_FIXED>>2))
 
 
12258
            ||(offseta < -(ONE_FIXED>>2)))
 
 
12259
        {
 
 
12260
            offsetx >>= 1;
 
 
12261
            offsety >>= 1;
 
 
12262
            offseta >>= 1;
 
 
12263
        }
 
 
12264
 
 
 
12265
        int offsetz = SqRoot32((offsetx*offsetx)+(offsety*offsety));
 
 
12266
        int angle1 = ArcTan(offseta,offsetz);
 
 
12267
 
 
 
12268
        if (angle1 >= 3072)
 
 
12269
            angle1 -= 4096;
 
 
12270
 
 
 
12271
        if (angle1 >= 2048)
 
 
12272
            angle1 = angle1-3072;
 
 
12273
 
 
 
12274
        if (angle1 > 1024)
 
 
12275
            angle1 = 2048-angle1;
 
 
12276
 
 
 
12277
        assert(angle1 >= -1024);
 
 
12278
        assert(angle1 <= 1024);
 
 
12279
 
 
 
12280
        /* Now correct for hysteresis... */
 
 
12281
        {
 
 
12282
            int highthreshold,topthreshold;
 
 
12283
 
 
 
12284
            switch(marineStatusPointer->HModelController.Sub_Sequence)
 
 
12285
            {
 
 
12286
                case MSSS_WildFire_90:
 
 
12287
                    highthreshold = 90;
 
 
12288
                    topthreshold = 1024 - 300;
 
 
12289
                break;
 
 
12290
                case MSSS_WildFire_45:
 
 
12291
                    highthreshold = 90;
 
 
12292
                    topthreshold = 1024 - 256;
 
 
12293
                break;
 
 
12294
                default:
 
 
12295
                    highthreshold = 128;
 
 
12296
                    topthreshold = 1024 - 256;
 
 
12297
            }
 
 
12298
 
 
 
12299
            if (angle1 > topthreshold)
 
 
12300
            {
 
 
12301
                if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_WildFire_90))
 
 
12302
                {
 
 
12303
                    switch(marineStatusPointer->HModelController.Sequence_Type)
 
 
12304
                    {
 
 
12305
                        case HMSQT_MarineStand:
 
 
12306
                        case MSSS_WildFire_90:
 
 
12307
                        break;
 
 
12308
                        default:
 
 
12309
                            SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_90, -1, (ONE_FIXED>>3));
 
 
12310
                    }
 
 
12311
                }
 
 
12312
            }
 
 
12313
            else if (angle1 > highthreshold)
 
 
12314
            {
 
 
12315
                if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_WildFire_45))
 
 
12316
                {
 
 
12317
                    switch(marineStatusPointer->HModelController.Sequence_Type)
 
 
12318
                    {
 
 
12319
                        case HMSQT_MarineStand:
 
 
12320
                        case MSSS_WildFire_45:
 
 
12321
                        break;
 
 
12322
                        default:
 
 
12323
                            SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_45, -1, (ONE_FIXED>>3));
 
 
12324
                    }
 
 
12325
                }
 
 
12326
            }
 
 
12327
            else
 
 
12328
            {
 
 
12329
                switch(marineStatusPointer->HModelController.Sequence_Type)
 
 
12330
                {
 
 
12331
                    case HMSQT_MarineStand:
 
 
12332
                    case MSSS_WildFire_0:
 
 
12333
                    break;
 
 
12334
                    default:
 
 
12335
                        SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_0, -1, (ONE_FIXED>>3));
 
 
12336
                }
 
 
12337
            }
 
 
12338
        }
 
 
12339
    }
 
 
12340
 
 
 
12341
    if (marineStatusPointer->clipammo <= 0)
 
 
12342
        return MarineRetreatsInTheFaceOfDanger(sbPtr) ? SRC_Request_PullPistol : SRC_Request_PanicReload;
 
 
12343
 
 
 
12344
    /* Scream handling. */
 
 
12345
    if (marineStatusPointer->soundHandle2 == SOUND_NOACTIVEINDEX)
 
 
12346
    {
 
 
12347
        if (marineStatusPointer->incidentFlag && Marine_HasHisMouthOpen(sbPtr))
 
 
12348
        {
 
 
12349
            if (marineStatusPointer->My_Weapon->id == MNPCW_MUnarmed)
 
 
12350
                Marine_AngryScream(sbPtr);
 
 
12351
        }
 
 
12352
    }
 
 
12353
 
 
 
12354
    if ((marineStatusPointer->Target == NULL) && (marineStatusPointer->volleySize >= marineStatusPointer->My_Weapon->MinimumBurstSize))
 
 
12355
    {
 
 
12356
        if (marineStatusPointer->incidentFlag)
 
 
12357
        {
 
 
12358
            /* Courage roll to stop. */
 
 
12359
            if (!MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
12360
            {
 
 
12361
                /* Okay, calm down a bit. */
 
 
12362
                DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
12363
 
 
 
12364
                if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
12365
                {
 
 
12366
                    Sound_Stop(marineStatusPointer->soundHandle);
 
 
12367
                    Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
12368
                }
 
 
12369
 
 
 
12370
                /* Try to be suspicious? */
 
 
12371
                marineStatusPointer->suspicious = MARINE_PANIC_TIME;
 
 
12372
                marineStatusPointer->suspect_point = marineStatusPointer->weaponTarget;
 
 
12373
                /* Set this to zero when you get a *new* suspicion. */
 
 
12374
                marineStatusPointer->previous_suspicion = 0;
 
 
12375
                marineStatusPointer->using_squad_suspicion = 0;
 
 
12376
 
 
 
12377
            return SRC_Request_Wait;
 
 
12378
            }
 
 
12379
        }
 
 
12380
    }
 
 
12381
    else
 
 
12382
    {
 
 
12383
        if (marineStatusPointer->Target)
 
 
12384
        {
 
 
12385
            NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
 
 
12386
 
 
 
12387
            /* orientate to firing point first */
 
 
12388
            VECTORCH orientationDirn;
 
 
12389
            orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
 
 
12390
            orientationDirn.vy = 0;
 
 
12391
            orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
 
 
12392
            int correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE);
 
 
12393
 
 
 
12394
            if (correctlyOrientated && !MarineCanSeeTarget(sbPtr))
 
 
12395
                marineStatusPointer->Target = NULL;
 
 
12396
        }
 
 
12397
    }
 
 
12398
 
 
 
12399
    if (!NpcSquad.Squad_Suspicion)
 
 
12400
    {
 
 
12401
        if (marineStatusPointer->Target)
 
 
12402
        {
 
 
12403
            /* Here we must have a target.  Renew suspicion for new arrivals. */
 
 
12404
            PointAlert(2,&marineStatusPointer->weaponTarget);
 
 
12405
        }
 
 
12406
        else
 
 
12407
        {
 
 
12408
            PointAlert(1,&sbPtr->DynPtr->Position);
 
 
12409
        }
 
 
12410
    }
 
 
12411
 
 
 
12412
    /* Wait for end of tweening before we proceed. */
 
 
12413
     if (marineStatusPointer->HModelController.Tweening != Controller_NoTweening)
 
 
12414
    {
 
 
12415
        /* stop visual and audio cues: technically, we're not firing at this moment */
 
 
12416
        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
12417
 
 
 
12418
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
12419
        {
 
 
12420
            Sound_Stop(marineStatusPointer->soundHandle);
 
 
12421
            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
12422
        }
 
 
12423
 
 
 
12424
    return SRC_No_Change;
 
 
12425
    }
 
 
12426
 
 
 
12427
    /* Right.  Correctly orientated or not, we blaze away. */
 
 
12428
 
 
 
12429
    marineStatusPointer->weapon_variable += (NormalFrameTime << 7);
 
 
12430
 
 
 
12431
    if (marineStatusPointer->weapon_variable >= MINIGUN_MAX_SPEED)
 
 
12432
    {
 
 
12433
        marineStatusPointer->weapon_variable = MINIGUN_MAX_SPEED;
 
 
12434
        DischargeLOSWeapon_Core(sbPtr);
 
 
12435
    }
 
 
12436
 
 
 
12437
    /* Now, consider termination. */
 
 
12438
 
 
 
12439
    if (marineStatusPointer->volleySize < MINIGUN_MINIMUM_BURST)
 
 
12440
        return SRC_No_Change; /* Can't terminate yet. */
 
 
12441
 
 
 
12442
    if (marineStatusPointer->incidentFlag)
 
 
12443
    {
 
 
12444
        if (MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
12445
        {
 
 
12446
            /* Two consecutive tests... */
 
 
12447
            if (MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
12448
            {
 
 
12449
                /* stop visual and audio cues: technically, we're not firing at this moment */
 
 
12450
                DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
12451
 
 
 
12452
                if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
12453
                {
 
 
12454
                    Sound_Stop(marineStatusPointer->soundHandle);
 
 
12455
                    Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
12456
                }
 
 
12457
 
 
 
12458
                return SRC_Request_Retreat;
 
 
12459
            }
 
 
12460
        }
 
 
12461
    }
 
 
12462
 
 
 
12463
return SRC_No_Change;
 
 
12464
}
 
 
12465
 
 
 
12466
static STATE_RETURN_CONDITION Execute_MNS_PanicFirePistol(STRATEGYBLOCK *sbPtr)
 
 
12467
{
 
 
12468
    assert(sbPtr);
 
 
12469
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
12470
    assert(marineStatusPointer);
 
 
12471
 
 
 
12472
    marineStatusPointer->HModelController.Playing = 1;
 
 
12473
 
 
 
12474
    /* zero velocity */
 
 
12475
    assert(sbPtr->DynPtr);
 
 
12476
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
12477
 
 
 
12478
    /* Stabilise sequence. */
 
 
12479
    if (marineStatusPointer->Target == NULL)
 
 
12480
    {
 
 
12481
        switch(marineStatusPointer->HModelController.Sequence_Type)
 
 
12482
        {
 
 
12483
            case HMSQT_MarineStand:
 
 
12484
            case MSSS_WildFire_0:
 
 
12485
            break;
 
 
12486
            default:
 
 
12487
                SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_0, -1, (ONE_FIXED>>3));
 
 
12488
        }
 
 
12489
    }
 
 
12490
    else
 
 
12491
    {
 
 
12492
        VECTORCH *gunpos;
 
 
12493
        /* Pick a sequence based on angle. */
 
 
12494
 
 
 
12495
        if (marineStatusPointer->My_Elevation_Section)
 
 
12496
            gunpos = &marineStatusPointer->My_Elevation_Section->World_Offset;
 
 
12497
        else
 
 
12498
            gunpos = &sbPtr->DynPtr->Position;
 
 
12499
 
 
 
12500
        /* Aim at Target. */
 
 
12501
 
 
 
12502
        int offsetx = marineStatusPointer->Target->DynPtr->Position.vx - gunpos->vx;
 
 
12503
        int offsety = marineStatusPointer->Target->DynPtr->Position.vz - gunpos->vz;
 
 
12504
        int offseta = -(marineStatusPointer->Target->DynPtr->Position.vy - gunpos->vy);
 
 
12505
 
 
 
12506
        while( (offsetx > (ONE_FIXED>>2))
 
 
12507
            ||(offsety > (ONE_FIXED>>2))
 
 
12508
            ||(offseta > (ONE_FIXED>>2))
 
 
12509
            ||(offsetx < -(ONE_FIXED>>2))
 
 
12510
            ||(offsety < -(ONE_FIXED>>2))
 
 
12511
            ||(offseta < -(ONE_FIXED>>2)))
 
 
12512
        {
 
 
12513
            offsetx >>= 1;
 
 
12514
            offsety >>= 1;
 
 
12515
            offseta >>= 1;
 
 
12516
        }
 
 
12517
 
 
 
12518
        int offsetz = SqRoot32((offsetx*offsetx)+(offsety*offsety));
 
 
12519
        int angle1 = ArcTan(offseta,offsetz);
 
 
12520
 
 
 
12521
        if (angle1 >= 3072)
 
 
12522
            angle1 -= 4096;
 
 
12523
 
 
 
12524
        if (angle1 >= 2048)
 
 
12525
            angle1 = angle1-3072;
 
 
12526
 
 
 
12527
        if (angle1 > 1024)
 
 
12528
            angle1 = 2048 - angle1;
 
 
12529
 
 
 
12530
        assert(angle1 >= -1024);
 
 
12531
        assert(angle1 <= 1024);
 
 
12532
 
 
 
12533
        /* Now correct for hysteresis... */
 
 
12534
        {
 
 
12535
            int highthreshold,topthreshold;
 
 
12536
 
 
 
12537
            switch(marineStatusPointer->HModelController.Sub_Sequence)
 
 
12538
            {
 
 
12539
                case MSSS_WildFire_90:
 
 
12540
                    highthreshold = 90;
 
 
12541
                    topthreshold = 1024 - 300;
 
 
12542
                break;
 
 
12543
                case MSSS_WildFire_45:
 
 
12544
                    highthreshold = 90;
 
 
12545
                    topthreshold = 1024 - 256;
 
 
12546
                break;
 
 
12547
                default:
 
 
12548
                    highthreshold = 128;
 
 
12549
                    topthreshold = 1024 - 256;
 
 
12550
            }
 
 
12551
 
 
 
12552
            if (angle1 > topthreshold)
 
 
12553
            {
 
 
12554
                if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_WildFire_90))
 
 
12555
                {
 
 
12556
                    /* Escape for civvie flamethrower here? */
 
 
12557
                    switch(marineStatusPointer->HModelController.Sequence_Type)
 
 
12558
                    {
 
 
12559
                        case HMSQT_MarineStand:
 
 
12560
                        case MSSS_WildFire_90:
 
 
12561
                        break;
 
 
12562
                        default:
 
 
12563
                            SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_90, -1, (ONE_FIXED>>3));
 
 
12564
                    }
 
 
12565
                }
 
 
12566
            }
 
 
12567
            else if (angle1 > highthreshold) //Was 256!
 
 
12568
            {
 
 
12569
                if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_WildFire_45))
 
 
12570
                {
 
 
12571
                    switch(marineStatusPointer->HModelController.Sequence_Type)
 
 
12572
                    {
 
 
12573
                        case HMSQT_MarineStand:
 
 
12574
                        case MSSS_WildFire_45:
 
 
12575
                        break;
 
 
12576
                        default:
 
 
12577
                        SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_45, -1, (ONE_FIXED>>3));
 
 
12578
                    }
 
 
12579
                }
 
 
12580
            }
 
 
12581
            else
 
 
12582
            {
 
 
12583
                switch(marineStatusPointer->HModelController.Sequence_Type)
 
 
12584
                {
 
 
12585
                    case HMSQT_MarineStand:
 
 
12586
                    case MSSS_WildFire_0:
 
 
12587
                    break;
 
 
12588
                    default:
 
 
12589
                        SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_0, -1, (ONE_FIXED>>3));
 
 
12590
                }
 
 
12591
            }
 
 
12592
        }
 
 
12593
    }
 
 
12594
 
 
 
12595
    if (marineStatusPointer->clipammo <= 0)
 
 
12596
        return SRC_Request_PanicReload;
 
 
12597
 
 
 
12598
    /* Scream handling. */
 
 
12599
    if (marineStatusPointer->soundHandle2 == SOUND_NOACTIVEINDEX)
 
 
12600
    {
 
 
12601
        if (marineStatusPointer->incidentFlag && Marine_HasHisMouthOpen(sbPtr))
 
 
12602
        {
 
 
12603
            if (marineStatusPointer->My_Weapon->id == MNPCW_MUnarmed)
 
 
12604
                Marine_AngryScream(sbPtr);
 
 
12605
        }
 
 
12606
    }
 
 
12607
 
 
 
12608
    if (marineStatusPointer->Target == NULL)
 
 
12609
    {
 
 
12610
        if (marineStatusPointer->incidentFlag)
 
 
12611
        {
 
 
12612
            /* Courage roll to stop. */
 
 
12613
            if (!MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
12614
            {
 
 
12615
                /* Okay, calm down a bit. */
 
 
12616
                DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
12617
 
 
 
12618
                if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
12619
                {
 
 
12620
                    Sound_Stop(marineStatusPointer->soundHandle);
 
 
12621
                    Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
12622
                }
 
 
12623
 
 
 
12624
                /* Try to be suspicious? */
 
 
12625
                marineStatusPointer->suspicious = MARINE_PANIC_TIME;
 
 
12626
                marineStatusPointer->suspect_point = marineStatusPointer->weaponTarget;
 
 
12627
                /* Set this to zero when you get a *new* suspicion. */
 
 
12628
                marineStatusPointer->previous_suspicion = 0;
 
 
12629
                marineStatusPointer->using_squad_suspicion = 0;
 
 
12630
 
 
 
12631
            return SRC_Request_Wait;
 
 
12632
            }
 
 
12633
        }
 
 
12634
    }
 
 
12635
    else
 
 
12636
    {
 
 
12637
        assert(marineStatusPointer->Target);
 
 
12638
 
 
 
12639
        NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
 
 
12640
        /* Fix weapon target! */
 
 
12641
 
 
 
12642
        if (marineStatusPointer->My_Weapon->TargetCallibrationShift)
 
 
12643
        {
 
 
12644
            marineStatusPointer->weaponTarget.vx -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat11,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
12645
            marineStatusPointer->weaponTarget.vy -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat12,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
12646
            marineStatusPointer->weaponTarget.vz -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat13,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
12647
        }
 
 
12648
 
 
 
12649
        /* orientate to firing point first */
 
 
12650
        VECTORCH orientationDirn;
 
 
12651
        orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
 
 
12652
        orientationDirn.vy = 0;
 
 
12653
        orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
 
 
12654
        int correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE);
 
 
12655
 
 
 
12656
        if (correctlyOrientated && !MarineCanSeeTarget(sbPtr))
 
 
12657
            marineStatusPointer->Target = NULL;
 
 
12658
    }
 
 
12659
 
 
 
12660
    if (!NpcSquad.Squad_Suspicion)
 
 
12661
    {
 
 
12662
        if (marineStatusPointer->Target)
 
 
12663
        {
 
 
12664
            /* Here we must have a target.  Renew suspicion for new arrivals. */
 
 
12665
            PointAlert(2,&marineStatusPointer->weaponTarget);
 
 
12666
        }
 
 
12667
        else
 
 
12668
        {
 
 
12669
            PointAlert(1,&sbPtr->DynPtr->Position);
 
 
12670
        }
 
 
12671
    }
 
 
12672
 
 
 
12673
    DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
12674
 
 
 
12675
    /* Wait for end of tweening before we proceed. */
 
 
12676
    if (marineStatusPointer->HModelController.Tweening != Controller_NoTweening)
 
 
12677
    {
 
 
12678
        /* stop visual and audio cues: technically, we're not firing at this moment */
 
 
12679
 
 
 
12680
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
12681
        {
 
 
12682
            Sound_Stop(marineStatusPointer->soundHandle);
 
 
12683
            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
12684
        }
 
 
12685
 
 
 
12686
    return SRC_No_Change;
 
 
12687
    }
 
 
12688
 
 
 
12689
    if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
12690
    {
 
 
12691
        Sound_Stop(marineStatusPointer->soundHandle);
 
 
12692
        Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
12693
    }
 
 
12694
 
 
 
12695
    /* Right.  Correctly orientated or not, we blaze away. */
 
 
12696
 
 
 
12697
    int keyframeflags = marineStatusPointer->HModelController.keyframe_flags>>1;
 
 
12698
 
 
 
12699
    /* I know there are only six possible firing points... */
 
 
12700
 
 
 
12701
    int a =0;
 
 
12702
    for (; a < 6; a++)
 
 
12703
    {
 
 
12704
        if ((keyframeflags & 1) || (( a == 0) && (marineStatusPointer->HModelController.Tweening == Controller_EndTweening)))
 
 
12705
        {
 
 
12706
            /* Fire a shot. */
 
 
12707
 
 
 
12708
            MaintainMarineGunFlash(sbPtr);
 
 
12709
 
 
 
12710
            /* look after the sound */
 
 
12711
            if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
12712
            {
 
 
12713
                Sound_Update3d(marineStatusPointer->soundHandle,&(sbPtr->DynPtr->Position));
 
 
12714
            }
 
 
12715
            else
 
 
12716
            { 
 
 
12717
                Sound_Play(marineStatusPointer->My_Weapon->StartSound, "d", &sbPtr->DynPtr->Position);
 
 
12718
                Sound_Play(marineStatusPointer->My_Weapon->LoopSound, "del", &sbPtr->DynPtr->Position,
&marineStatusPointer->soundHandle);
 
 
12719
            }
 
 
12720
 
 
 
12721
            {
 
 
12722
                VECTORCH shotvector = { 0, 0, 65535 };
 
 
12723
                RotateVector(&shotvector,&marineStatusPointer->My_Gunflash_Section->SecMat);
 
 
12724
 
 
 
12725
                CastLOSProjectile(sbPtr, &marineStatusPointer->My_Gunflash_Section->World_Offset, &shotvector,
marineStatusPointer->My_Weapon->Ammo_Type, 1, 1);
 
 
12726
 
 
 
12727
                if (marineStatusPointer->clipammo > 0)
 
 
12728
                    marineStatusPointer->clipammo--;
 
 
12729
            }
 
 
12730
        }
 
 
12731
 
 
 
12732
    keyframeflags >>= 1;
 
 
12733
    }
 
 
12734
    /* ...and they are all identical. */
 
 
12735
 
 
 
12736
    /* Now, consider termination. */
 
 
12737
 
 
 
12738
    if (marineStatusPointer->incidentFlag)
 
 
12739
    {
 
 
12740
        if (MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
12741
        {
 
 
12742
            /* Two consecutive tests... */
 
 
12743
            if (MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
12744
            {
 
 
12745
                /* stop visual and audio cues: technically, we're not firing at this moment */
 
 
12746
                DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
12747
 
 
 
12748
                if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
12749
                {
 
 
12750
                    Sound_Stop(marineStatusPointer->soundHandle);
 
 
12751
                    Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
12752
                }
 
 
12753
 
 
 
12754
            return SRC_Request_Retreat;
 
 
12755
            }
 
 
12756
        }
 
 
12757
    }
 
 
12758
 
 
 
12759
return SRC_No_Change;
 
 
12760
}
 
 
12761
 
 
 
12762
static STATE_RETURN_CONDITION Execute_MNS_PanicFireShotgun(STRATEGYBLOCK *sbPtr)
 
 
12763
{
 
 
12764
    assert(sbPtr);
 
 
12765
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
12766
    assert(marineStatusPointer);
 
 
12767
 
 
 
12768
    marineStatusPointer->HModelController.Playing = 1;
 
 
12769
 
 
 
12770
    /* zero velocity */
 
 
12771
    assert(sbPtr->DynPtr);
 
 
12772
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
12773
 
 
 
12774
    /* Stabilise sequence. */
 
 
12775
    if (marineStatusPointer->Target == NULL)
 
 
12776
    {
 
 
12777
        switch(marineStatusPointer->HModelController.Sequence_Type)
 
 
12778
        {
 
 
12779
            case HMSQT_MarineStand:
 
 
12780
            case MSSS_WildFire_0:
 
 
12781
            break;
 
 
12782
            default:
 
 
12783
                SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_0, -1, (ONE_FIXED>>3));
 
 
12784
        }
 
 
12785
    }
 
 
12786
    else
 
 
12787
    {
 
 
12788
        VECTORCH *gunpos;
 
 
12789
        /* Pick a sequence based on angle. */
 
 
12790
 
 
 
12791
        if (marineStatusPointer->My_Elevation_Section)
 
 
12792
            gunpos = &marineStatusPointer->My_Elevation_Section->World_Offset;
 
 
12793
        else
 
 
12794
            gunpos = &sbPtr->DynPtr->Position;
 
 
12795
 
 
 
12796
        /* Aim at Target. */
 
 
12797
 
 
 
12798
        int offsetx = marineStatusPointer->Target->DynPtr->Position.vx - gunpos->vx;
 
 
12799
        int offsety = marineStatusPointer->Target->DynPtr->Position.vz - gunpos->vz;
 
 
12800
        int offseta = -(marineStatusPointer->Target->DynPtr->Position.vy - gunpos->vy);
 
 
12801
 
 
 
12802
        while( (offsetx > (ONE_FIXED>>2))
 
 
12803
            ||(offsety > (ONE_FIXED>>2))
 
 
12804
            ||(offseta > (ONE_FIXED>>2))
 
 
12805
            ||(offsetx < -(ONE_FIXED>>2))
 
 
12806
            ||(offsety < -(ONE_FIXED>>2))
 
 
12807
            ||(offseta < -(ONE_FIXED>>2)))
 
 
12808
        {
 
 
12809
            offsetx >>= 1;
 
 
12810
            offsety >>= 1;
 
 
12811
            offseta >>= 1;
 
 
12812
        }
 
 
12813
 
 
 
12814
        int offsetz = SqRoot32((offsetx*offsetx)+(offsety*offsety));
 
 
12815
        int angle1 = ArcTan(offseta,offsetz);
 
 
12816
 
 
 
12817
        if (angle1 >= 3072)
 
 
12818
            angle1 -= 4096;
 
 
12819
 
 
 
12820
        if (angle1 >= 2048)
 
 
12821
            angle1 = angle1-3072;
 
 
12822
 
 
 
12823
        if (angle1 > 1024)
 
 
12824
            angle1 = 2048 - angle1;
 
 
12825
 
 
 
12826
        assert(angle1 >= -1024);
 
 
12827
        assert(angle1 <= 1024);
 
 
12828
 
 
 
12829
        /* Now correct for hysteresis... */
 
 
12830
        {
 
 
12831
            int highthreshold,topthreshold;
 
 
12832
 
 
 
12833
            switch(marineStatusPointer->HModelController.Sub_Sequence)
 
 
12834
            {
 
 
12835
                case MSSS_WildFire_90:
 
 
12836
                    highthreshold = 90;
 
 
12837
                    topthreshold = 1024 - 300;
 
 
12838
                break;
 
 
12839
                case MSSS_WildFire_45:
 
 
12840
                    highthreshold = 90;
 
 
12841
                    topthreshold = 1024 - 256;
 
 
12842
                break;
 
 
12843
                default:
 
 
12844
                    highthreshold = 128;
 
 
12845
                    topthreshold = 1024 - 256;
 
 
12846
            }
 
 
12847
 
 
 
12848
            if (angle1 > topthreshold)
 
 
12849
            {
 
 
12850
                if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_WildFire_90))
 
 
12851
                {
 
 
12852
                    /* Escape for civvie flamethrower here? */
 
 
12853
                    switch(marineStatusPointer->HModelController.Sequence_Type)
 
 
12854
                    {
 
 
12855
                        case HMSQT_MarineStand:
 
 
12856
                        case MSSS_WildFire_90:
 
 
12857
                        break;
 
 
12858
                        default:
 
 
12859
                            SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_90, -1, (ONE_FIXED>>3));
 
 
12860
                    }
 
 
12861
                }
 
 
12862
            }
 
 
12863
            else if (angle1 > highthreshold)
 
 
12864
            {
 
 
12865
                if (HModelSequence_Exists(&marineStatusPointer->HModelController,HMSQT_MarineStand,MSSS_WildFire_45))
 
 
12866
                {
 
 
12867
                    switch(marineStatusPointer->HModelController.Sequence_Type)
 
 
12868
                    {
 
 
12869
                        case HMSQT_MarineStand:
 
 
12870
                        case MSSS_WildFire_45:
 
 
12871
                        break;
 
 
12872
                        default:
 
 
12873
                            SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_45, -1, (ONE_FIXED>>3));
 
 
12874
                    }
 
 
12875
                }
 
 
12876
            }
 
 
12877
            else
 
 
12878
            {
 
 
12879
                switch(marineStatusPointer->HModelController.Sequence_Type)
 
 
12880
                {
 
 
12881
                    case HMSQT_MarineStand:
 
 
12882
                    case MSSS_WildFire_0:
 
 
12883
                    break;
 
 
12884
                    default:
 
 
12885
                        SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_0, -1, (ONE_FIXED>>3));
 
 
12886
                }
 
 
12887
            }
 
 
12888
        }
 
 
12889
    }
 
 
12890
 
 
 
12891
    if (marineStatusPointer->clipammo <= 0)
 
 
12892
        return SRC_Request_PanicReload;
 
 
12893
 
 
 
12894
    /* Scream handling. */
 
 
12895
    if (marineStatusPointer->soundHandle2 == SOUND_NOACTIVEINDEX)
 
 
12896
    {
 
 
12897
        if (marineStatusPointer->incidentFlag && Marine_HasHisMouthOpen(sbPtr))
 
 
12898
        {
 
 
12899
            if (marineStatusPointer->My_Weapon->id == MNPCW_MUnarmed)
 
 
12900
                Marine_AngryScream(sbPtr);
 
 
12901
        }
 
 
12902
    }
 
 
12903
 
 
 
12904
    if (marineStatusPointer->Target == NULL)
 
 
12905
    {
 
 
12906
        if (marineStatusPointer->incidentFlag)
 
 
12907
        {
 
 
12908
            /* Courage roll to stop. */
 
 
12909
            if (!MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
12910
            {
 
 
12911
                /* Okay, calm down a bit. */
 
 
12912
                DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
12913
 
 
 
12914
                if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
12915
                {
 
 
12916
                    Sound_Stop(marineStatusPointer->soundHandle);
 
 
12917
                    Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
12918
                }
 
 
12919
                /* Try to be suspicious? */
 
 
12920
                marineStatusPointer->suspicious = MARINE_PANIC_TIME;
 
 
12921
                marineStatusPointer->suspect_point = marineStatusPointer->weaponTarget;
 
 
12922
                /* Set this to zero when you get a *new* suspicion. */
 
 
12923
                marineStatusPointer->previous_suspicion = 0;
 
 
12924
                marineStatusPointer->using_squad_suspicion = 0;
 
 
12925
 
 
 
12926
            return SRC_Request_Wait;
 
 
12927
            }
 
 
12928
        }
 
 
12929
    }
 
 
12930
    else
 
 
12931
    {
 
 
12932
        assert(marineStatusPointer->Target);
 
 
12933
 
 
 
12934
        NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
 
 
12935
 
 
 
12936
        /* orientate to firing point first */
 
 
12937
        VECTORCH orientationDirn;
 
 
12938
        orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
 
 
12939
        orientationDirn.vy = 0;
 
 
12940
        orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
 
 
12941
        int correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE);
 
 
12942
 
 
 
12943
        if (correctlyOrientated && !MarineCanSeeTarget(sbPtr))
 
 
12944
            marineStatusPointer->Target = NULL;
 
 
12945
    }
 
 
12946
 
 
 
12947
    if (!NpcSquad.Squad_Suspicion)
 
 
12948
    {
 
 
12949
        if (marineStatusPointer->Target)
 
 
12950
        {
 
 
12951
            /* Here we must have a target.  Renew suspicion for new arrivals. */
 
 
12952
            PointAlert(2,&marineStatusPointer->weaponTarget);
 
 
12953
        }
 
 
12954
        else
 
 
12955
        {
 
 
12956
            PointAlert(1,&sbPtr->DynPtr->Position);
 
 
12957
        }
 
 
12958
    }
 
 
12959
 
 
 
12960
    /* Wait for end of tweening before we proceed. */
 
 
12961
    if (marineStatusPointer->HModelController.Tweening != Controller_NoTweening)
 
 
12962
    {
 
 
12963
        /* stop visual and audio cues: technically, we're not firing at this moment */
 
 
12964
        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
12965
 
 
 
12966
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
12967
        {
 
 
12968
            Sound_Stop(marineStatusPointer->soundHandle);
 
 
12969
            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
12970
        }
 
 
12971
 
 
 
12972
    return SRC_No_Change;
 
 
12973
    }
 
 
12974
 
 
 
12975
    /* Stop cues anyway? */
 
 
12976
    DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
12977
 
 
 
12978
    if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
12979
    {
 
 
12980
        Sound_Stop(marineStatusPointer->soundHandle);
 
 
12981
        Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
12982
    }
 
 
12983
 
 
 
12984
    /* Right.  Correctly orientated or not, we blaze away. */
 
 
12985
 
 
 
12986
    int keyframeflags = marineStatusPointer->HModelController.keyframe_flags>>1;
 
 
12987
 
 
 
12988
    /* I know there are only three firing points... */
 
 
12989
    int a = 0;
 
 
12990
    for (; a < 3; a++)
 
 
12991
    {
 
 
12992
        if (keyframeflags & 1)
 
 
12993
        {
 
 
12994
            MaintainMarineGunFlash(sbPtr);
 
 
12995
 
 
 
12996
            /* look after the sound */
 
 
12997
            if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
12998
            {
 
 
12999
                Sound_Update3d(marineStatusPointer->soundHandle, &sbPtr->DynPtr->Position);
 
 
13000
            }
 
 
13001
            else
 
 
13002
            { 
 
 
13003
                Sound_Play(marineStatusPointer->My_Weapon->StartSound, "d", &sbPtr->DynPtr->Position);
 
 
13004
                Sound_Play(marineStatusPointer->My_Weapon->LoopSound, "del", &sbPtr->DynPtr->Position,
&marineStatusPointer->soundHandle);
 
 
13005
            }
 
 
13006
 
 
 
13007
            /* Now hit the target with a shotgun blast. */
 
 
13008
 
 
 
13009
            int b = 0;
 
 
13010
 
 
 
13011
            while (ShotgunBlast[b].vz > 0)
 
 
13012
            {
 
 
13013
                VECTORCH world_vec;
 
 
13014
 
 
 
13015
            RotateAndCopyVector(&ShotgunBlast[b],&world_vec,&marineStatusPointer->My_Gunflash_Section->SecMat);
 
 
13016
            CastLOSProjectile(sbPtr, &marineStatusPointer->My_Gunflash_Section->World_Offset, &world_vec,
marineStatusPointer->My_Weapon->Ammo_Type, 1, 0);
 
 
13017
 
 
 
13018
                b++;
 
 
13019
            }
 
 
13020
 
 
 
13021
            if (marineStatusPointer->clipammo > 0)
 
 
13022
                marineStatusPointer->clipammo--;
 
 
13023
        }
 
 
13024
 
 
 
13025
        keyframeflags >>= 1;
 
 
13026
    }
 
 
13027
    /* ...and they are all identical. */
 
 
13028
 
 
 
13029
    /* Now, consider termination. */
 
 
13030
 
 
 
13031
    if (marineStatusPointer->incidentFlag)
 
 
13032
    {
 
 
13033
        if (MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
13034
        {
 
 
13035
            /* Two consecutive tests... */
 
 
13036
            if (MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
13037
            {
 
 
13038
                /* stop visual and audio cues: technically, we're not firing at this moment */
 
 
13039
                DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
13040
 
 
 
13041
                if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
13042
                {
 
 
13043
                    Sound_Stop(marineStatusPointer->soundHandle);
 
 
13044
                    Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
13045
                }
 
 
13046
 
 
 
13047
            return SRC_Request_Retreat;
 
 
13048
            }
 
 
13049
        }
 
 
13050
    }
 
 
13051
 
 
 
13052
return SRC_No_Change;
 
 
13053
}
 
 
13054
 
 
 
13055
static void Marine_EnterExtremePanicAnimation(STRATEGYBLOCK *sbPtr)
 
 
13056
{
 
 
13057
    if ((FastRandom() & 65535) < 21845)
 
 
13058
    {
 
 
13059
        SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_90, -1, (ONE_FIXED>>1));
 
 
13060
    }
 
 
13061
    else if ((FastRandom() & 65535) < 21845)
 
 
13062
    {
 
 
13063
        SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_45, -1, (ONE_FIXED>>1));
 
 
13064
    }
 
 
13065
    else
 
 
13066
    {
 
 
13067
        SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_WildFire_0, -1, (ONE_FIXED>>1));
 
 
13068
    }
 
 
13069
}
 
 
13070
 
 
 
13071
static void Marine_EnterLesserPanicAnimation(STRATEGYBLOCK *sbPtr)
 
 
13072
{
 
 
13073
    if ((FastRandom() & 65535) < 32767)
 
 
13074
        SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_Panic_One, -1, (ONE_FIXED>>1));
 
 
13075
    else
 
 
13076
        SetMarineAnimationSequence(sbPtr, HMSQT_MarineStand, MSSS_Panic_Two, -1, (ONE_FIXED>>1));
 
 
13077
}
 
 
13078
 
 
 
13079
static void Marine_Sobbing(STRATEGYBLOCK *sbPtr) 
 
 
13080
{
 
 
13081
    assert(sbPtr);
 
 
13082
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
13083
    assert(marineStatusPointer);
 
 
13084
 
 
 
13085
    if (marineStatusPointer->Android)
 
 
13086
        return;
 
 
13087
 
 
 
13088
    /* This is getting quite upsetting... */
 
 
13089
 
 
 
13090
    if (marineStatusPointer->soundHandle2 == SOUND_NOACTIVEINDEX)
 
 
13091
    {
 
 
13092
        PlayMarineScream(marineStatusPointer->Voice, MSC_Sobbing,marineStatusPointer->VoicePitch,
 
 
13093
            &marineStatusPointer->soundHandle2, &sbPtr->DynPtr->Position);
 
 
13094
    }
 
 
13095
}
 
 
13096
 
 
 
13097
static STATE_RETURN_CONDITION Execute_MNS_PanicFireUnarmed(STRATEGYBLOCK *sbPtr)
 
 
13098
{
 
 
13099
    /* Also known as... gibber in terror. */
 
 
13100
 
 
 
13101
    assert(sbPtr);
 
 
13102
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
13103
    assert(marineStatusPointer);
 
 
13104
 
 
 
13105
    marineStatusPointer->HModelController.Playing = 1;
 
 
13106
 
 
 
13107
    /* zero velocity */
 
 
13108
    assert(sbPtr->DynPtr);
 
 
13109
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
13110
 
 
 
13111
    /* Firstly, are we trying to retreat? */
 
 
13112
    if (marineStatusPointer->internalState == 1)
 
 
13113
    {
 
 
13114
        /* Wait for tweening to finish... */
 
 
13115
        if (marineStatusPointer->HModelController.Tweening == Controller_NoTweening)
 
 
13116
        {
 
 
13117
            /* Then the first incidentFlag we get, we're outta here. */
 
 
13118
            if (marineStatusPointer->incidentFlag)
 
 
13119
                return SRC_Request_Retreat;
 
 
13120
        }
 
 
13121
 
 
 
13122
    return SRC_No_Change;
 
 
13123
    }
 
 
13124
 
 
 
13125
    /* Stabilise sequence. */
 
 
13126
 
 
 
13127
    if ((marineStatusPointer->HModelController.Sequence_Type != HMSQT_MarineStand) ||
 
 
13128
    ((marineStatusPointer->HModelController.Sub_Sequence != MSSS_WildFire_0)
 
 
13129
    &&(marineStatusPointer->HModelController.Sub_Sequence != MSSS_WildFire_45)
 
 
13130
    && (marineStatusPointer->HModelController.Sub_Sequence != MSSS_WildFire_90)))
 
 
13131
    {
 
 
13132
        /* If we're not in one of the 'extreme panic' animations, are we in one of the others? */
 
 
13133
        if ((marineStatusPointer->HModelController.Sequence_Type != HMSQT_MarineStand)
 
 
13134
        ||((marineStatusPointer->HModelController.Sub_Sequence != MSSS_Panic_One) && (marineStatusPointer->HModelController.Sub_Sequence !=
MSSS_Panic_Two)))
 
 
13135
        {
 
 
13136
            /* No, we're not.  See which level of panic to go into... */
 
 
13137
            if (MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
13138
            {
 
 
13139
                /* It's PaNiC tImE! */
 
 
13140
                Marine_EnterExtremePanicAnimation(sbPtr);
 
 
13141
            }
 
 
13142
            else
 
 
13143
            {
 
 
13144
                /* Just look worried. */
 
 
13145
                Marine_EnterLesserPanicAnimation(sbPtr);
 
 
13146
            }
 
 
13147
        }
 
 
13148
        else
 
 
13149
        {
 
 
13150
            /* Yes, we are.  Is it getting worse? */
 
 
13151
            if (marineStatusPointer->incidentFlag)
 
 
13152
            {
 
 
13153
                int range;
 
 
13154
                STRATEGYBLOCK *threat = Marine_GetNewTarget(&sbPtr->DynPtr->Position,sbPtr);
 
 
13155
 
 
 
13156
                if (threat)
 
 
13157
                    range = VectorDistance(&sbPtr->DynPtr->Position,&threat->DynPtr->Position);
 
 
13158
                else
 
 
13159
                    range = 100000;
 
 
13160
 
 
 
13161
                if (MarineRetreatsInTheFaceOfDanger(sbPtr) || (range < 3000))
 
 
13162
                {
 
 
13163
                    if (range < 3000)
 
 
13164
                    {
 
 
13165
                        if (marineStatusPointer->Android == 0)
 
 
13166
                            marineStatusPointer->Courage -= 5000;
 
 
13167
                    }
 
 
13168
 
 
 
13169
                    Marine_EnterExtremePanicAnimation(sbPtr);
 
 
13170
                }
 
 
13171
                else
 
 
13172
                {
 
 
13173
                    /* Feeling really brave? */
 
 
13174
                    if (MarineRetreatsInTheFaceOfDanger(sbPtr) == 0)
 
 
13175
                        marineStatusPointer->Target_Expression = 1;
 
 
13176
                }
 
 
13177
            }
 
 
13178
            /* Else remain as you were. */
 
 
13179
        }
 
 
13180
    }
 
 
13181
    else
 
 
13182
    {
 
 
13183
        /* We are in extreme panic.  Is it getting better? */
 
 
13184
        if (marineStatusPointer->incidentFlag)
 
 
13185
        {
 
 
13186
            if ((FastRandom() & 65535) < 13107)
 
 
13187
            {
 
 
13188
                if (!MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
13189
                {
 
 
13190
                    if (!MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
13191
                    {
 
 
13192
                        /* Two consecutive tests. */
 
 
13193
                        Marine_EnterLesserPanicAnimation(sbPtr);
 
 
13194
                    }
 
 
13195
                }
 
 
13196
            }
 
 
13197
        }
 
 
13198
        /* Enforce panic expression, too. */
 
 
13199
        marineStatusPointer->Target_Expression = 2;
 
 
13200
    }
 
 
13201
 
 
 
13202
    if (marineStatusPointer->Target == NULL)
 
 
13203
    {
 
 
13204
        /* Civvies with courage 0 get a bonus to shut up... */
 
 
13205
        if (!marineStatusPointer->Courage)
 
 
13206
        {
 
 
13207
            /* No reason to block this for Androids. */
 
 
13208
            marineStatusPointer->Courage = 5000;
 
 
13209
        }
 
 
13210
 
 
 
13211
        if (marineStatusPointer->incidentFlag)
 
 
13212
        {
 
 
13213
            /* Courage roll to stop. */
 
 
13214
            if (!MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
13215
            {
 
 
13216
                /* Okay, calm down a bit. */
 
 
13217
                DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
13218
 
 
 
13219
                if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
13220
                {
 
 
13221
                    Sound_Stop(marineStatusPointer->soundHandle);
 
 
13222
                    Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
13223
                }
 
 
13224
 
 
 
13225
                /* Try to be suspicious? */
 
 
13226
                marineStatusPointer->suspicious = MARINE_PANIC_TIME;
 
 
13227
                marineStatusPointer->suspect_point = marineStatusPointer->weaponTarget;
 
 
13228
                /* Set this to zero when you get a *new* suspicion. */
 
 
13229
                marineStatusPointer->previous_suspicion = 0;
 
 
13230
                marineStatusPointer->using_squad_suspicion = 0;
 
 
13231
 
 
 
13232
                if ((marineStatusPointer->HModelController.Sequence_Type != HMSQT_MarineStand)
 
 
13233
                    ||((marineStatusPointer->HModelController.Sub_Sequence != MSSS_Panic_One)
 
 
13234
                        &&(marineStatusPointer->HModelController.Sub_Sequence != MSSS_Panic_Two)))
 
 
13235
                {
 
 
13236
                    Marine_EnterLesserPanicAnimation(sbPtr);
 
 
13237
                    return SRC_No_Change;
 
 
13238
                }
 
 
13239
                else
 
 
13240
                {
 
 
13241
                    return SRC_Request_Wait;
 
 
13242
                }
 
 
13243
            }
 
 
13244
        }
 
 
13245
    }
 
 
13246
    else
 
 
13247
    {
 
 
13248
        assert(marineStatusPointer->Target);
 
 
13249
        NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
 
 
13250
 
 
 
13251
        /* May as well keep an eye out. */
 
 
13252
        VECTORCH orientationDirn;
 
 
13253
        orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
 
 
13254
        orientationDirn.vy = 0;
 
 
13255
        orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
 
 
13256
    }
 
 
13257
 
 
 
13258
    /* Scream handling. */
 
 
13259
    if (marineStatusPointer->soundHandle2 == SOUND_NOACTIVEINDEX)
 
 
13260
    {
 
 
13261
        if (marineStatusPointer->incidentFlag)
 
 
13262
        {
 
 
13263
            if (Marine_HasHisMouthOpen(sbPtr))
 
 
13264
            {
 
 
13265
                Marine_Sobbing(sbPtr);
 
 
13266
            }
 
 
13267
            else
 
 
13268
            {
 
 
13269
                /* Start yelling again? */
 
 
13270
                if (MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
13271
                    marineStatusPointer->Target_Expression = 2;
 
 
13272
            }
 
 
13273
        }
 
 
13274
    }
 
 
13275
 
 
 
13276
    if (!NpcSquad.Squad_Suspicion)
 
 
13277
    {
 
 
13278
        if (marineStatusPointer->Target)
 
 
13279
        {
 
 
13280
            /* Here we must have a target.  Renew suspicion for new arrivals. */
 
 
13281
            PointAlert(2,&marineStatusPointer->weaponTarget);
 
 
13282
        }
 
 
13283
        else
 
 
13284
        {
 
 
13285
            PointAlert(1,&sbPtr->DynPtr->Position);
 
 
13286
        }
 
 
13287
    }
 
 
13288
 
 
 
13289
    /* Wait for end of tweening before we proceed. */
 
 
13290
    if (marineStatusPointer->HModelController.Tweening != Controller_NoTweening)
 
 
13291
    {
 
 
13292
        /* stop visual and audio cues: technically, we're not firing at this moment */
 
 
13293
        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
13294
 
 
 
13295
        if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX)
 
 
13296
        {
 
 
13297
            Sound_Stop(marineStatusPointer->soundHandle);
 
 
13298
            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
13299
        }
 
 
13300
 
 
 
13301
    return SRC_No_Change;
 
 
13302
    }
 
 
13303
 
 
 
13304
    /* No functionality in here... */
 
 
13305
 
 
 
13306
    marineStatusPointer->stateTimer -= NormalFrameTime;
 
 
13307
 
 
 
13308
    /* Now, consider termination. */
 
 
13309
 
 
 
13310
    if (marineStatusPointer->incidentFlag)
 
 
13311
    {
 
 
13312
        if ((FastRandom() & 65535) < 13107)
 
 
13313
        {
 
 
13314
            if (!MarineRetreatsInTheFaceOfDanger(sbPtr) || !MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
13315
            {
 
 
13316
                /* Two chances... */
 
 
13317
 
 
 
13318
                /* stop visual and audio cues: technically, we're not firing at this moment */
 
 
13319
                DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
13320
 
 
 
13321
                if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
13322
                {
 
 
13323
                    Sound_Stop(marineStatusPointer->soundHandle);
 
 
13324
                    Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
13325
                }
 
 
13326
 
 
 
13327
                if ((marineStatusPointer->HModelController.Sequence_Type != HMSQT_MarineStand)
 
 
13328
                    ||((marineStatusPointer->HModelController.Sub_Sequence != MSSS_Panic_One)
 
 
13329
                        &&(marineStatusPointer->HModelController.Sub_Sequence != MSSS_Panic_Two)))
 
 
13330
                {
 
 
13331
                    Marine_EnterLesserPanicAnimation(sbPtr);
 
 
13332
                    marineStatusPointer->internalState = 1;
 
 
13333
                    /* This is a bit pre-emptive, but never mind. */
 
 
13334
 
 
 
13335
                    if (!marineStatusPointer->Android)
 
 
13336
                        marineStatusPointer->Courage -= 5000;
 
 
13337
 
 
 
13338
                return SRC_No_Change;
 
 
13339
                }
 
 
13340
                else
 
 
13341
                {
 
 
13342
                    return SRC_Request_Retreat;
 
 
13343
                }
 
 
13344
            }
 
 
13345
        }
 
 
13346
    }
 
 
13347
 
 
 
13348
return SRC_No_Change;
 
 
13349
}
 
 
13350
 
 
 
13351
static int GetClosestStepInPath(int path, MODULE* current_module)
 
 
13352
{
 
 
13353
        int i;
 
 
13354
        assert(path >= 0 && path < PathArraySize);
 
 
13355
        assert(PathArray);
 
 
13356
 
 
 
13357
        if(!current_module) 
 
 
13358
        return 0;
 
 
13359
 
 
 
13360
        PATHHEADER* path_head = &PathArray[path];
 
 
13361
        assert(path_head->path_length);
 
 
13362
 
 
 
13363
        //see if enemy is currently in any of the modules in the path
 
 
13364
        {
 
 
13365
                AIMODULE* current_aimodule = current_module->m_aimodule;
 
 
13366
 
 
 
13367
                for(i=0; i < path_head->path_length; i++)
 
 
13368
                {
 
 
13369
                        if(current_aimodule == path_head->modules_in_path[i])     
 
 
13370
                                return i;
 
 
13371
                }
 
 
13372
        }
 
 
13373
 
 
 
13374
        //enemy not on path , so try to find the closest module on the path
 
 
13375
        {
 
 
13376
                int closest_distance = 0x7fffffff;
 
 
13377
                int closest_point = 0;
 
 
13378
                VECTORCH* current_pos = &current_module->m_world;
 
 
13379
 
 
 
13380
                for(i=0; i < path_head->path_length; i++)
 
 
13381
                {
 
 
13382
            VECTORCH diff = path_head->modules_in_path[i]->m_world;
 
 
13383
 
 
 
13384
            diff.vx -= current_pos->vx;
 
 
13385
            diff.vy -= current_pos->vy;
 
 
13386
            diff.vz -= current_pos->vz;
 
 
13387
 
 
 
13388
                        int distance = Approximate3dMagnitude(&diff);
 
 
13389
 
 
 
13390
                        if(distance < closest_distance)
 
 
13391
                        {
 
 
13392
                                closest_distance = distance;
 
 
13393
                                closest_point = i;
 
 
13394
                        }
 
 
13395
                }
 
 
13396
 
 
 
13397
    return closest_point;
 
 
13398
        }
 
 
13399
}
 
 
13400
 
 
 
13401
void SendRequestToMarine(STRATEGYBLOCK* sbPtr, int state, int extended_data)
 
 
13402
{
 
 
13403
    //handle RequestState (from switches etc.)
 
 
13404
    assert(sbPtr);
 
 
13405
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
13406
    assert(marineStatusPointer);
 
 
13407
 
 
 
13408
    if(extended_data & 1)
 
 
13409
    {
 
 
13410
        //change mission type 
 
 
13411
        MARINE_MISSION new_mission = MM_Wait_Then_Wander;
 
 
13412
        int new_path = -1;
 
 
13413
        int new_stepnumber = -1;
 
 
13414
 
 
 
13415
        //state must be 1
 
 
13416
        if(!state)
 
 
13417
            return;
 
 
13418
 
 
 
13419
        //can't change mission type if non-combatant or if on fire
 
 
13420
        switch(marineStatusPointer->Mission)
 
 
13421
        {
 
 
13422
            case MM_NonCom:
 
 
13423
            case MM_RunAroundOnFire:
 
 
13424
            return;
 
 
13425
            default:
 
 
13426
            break;
 
 
13427
        }
 
 
13428
 
 
 
13429
        switch((extended_data >> 7) & 0xff)
 
 
13430
        {
 
 
13431
            case 0:
 
 
13432
                new_mission = MM_Wait_Then_Wander;
 
 
13433
                break;
 
 
13434
            case 1:
 
 
13435
                new_mission = MM_Wander;
 
 
13436
                break;
 
 
13437
            case 2:
 
 
13438
                new_mission = MM_Guard;
 
 
13439
                //need to cacluculate mission module from 'myspot' guard location
 
 
13440
                {
 
 
13441
                    MODULE* module = ModuleFromPosition(&marineStatusPointer->my_spot, NULL);
 
 
13442
                    assert(module);
 
 
13443
                    marineStatusPointer->missionmodule = module->m_aimodule;
 
 
13444
                }
 
 
13445
                break;
 
 
13446
            case 3:
 
 
13447
                new_mission = MM_LocalGuard;
 
 
13448
                break;
 
 
13449
            case 4:
 
 
13450
                new_mission = MM_Pathfinder;
 
 
13451
                break;
 
 
13452
        }
 
 
13453
 
 
 
13454
        if(new_mission == MM_Pathfinder)
 
 
13455
        {
 
 
13456
            //find the path and stepnumber
 
 
13457
            new_path = (extended_data >> 15) & 0xff;
 
 
13458
            new_stepnumber = GetClosestStepInPath(new_path,sbPtr->containingModule);
 
 
13459
        }
 
 
13460
 
 
 
13461
        marineStatusPointer->path = new_path;
 
 
13462
        marineStatusPointer->stepnumber = new_stepnumber;
 
 
13463
        InitMission(sbPtr, new_mission);
 
 
13464
    }
 
 
13465
}
 
 
13466
 
 
 
13467
static STATE_RETURN_CONDITION Execute_MNS_DischargeTwoPistols(STRATEGYBLOCK *sbPtr)
 
 
13468
{
 
 
13469
    int range;
 
 
13470
    int mod;
 
 
13471
 
 
 
13472
    assert(sbPtr);
 
 
13473
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
13474
    assert(marineStatusPointer);
 
 
13475
    int hitroll = marineStatusPointer->Skill; /* Marine skill... */
 
 
13476
 
 
 
13477
    assert(marineStatusPointer->My_Weapon->id==MNPCW_TwoPistols);
 
 
13478
 
 
 
13479
    /* zero velocity */
 
 
13480
    assert(sbPtr->DynPtr);
 
 
13481
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
13482
 
 
 
13483
    if(!MarineCanSeeTarget(sbPtr))
 
 
13484
    {
 
 
13485
        /* Remove the gunflash */
 
 
13486
        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
13487
 
 
 
13488
        /* .... and stop the sound */
 
 
13489
        if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX)
 
 
13490
        {
 
 
13491
            Sound_Stop(marineStatusPointer->soundHandle);        
 
 
13492
            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
13493
        }
 
 
13494
 
 
 
13495
    return SRC_Request_Wait;
 
 
13496
    }
 
 
13497
 
 
 
13498
    if (!marineStatusPointer->clipammo)
 
 
13499
        Marine_Enter_Reload_State(sbPtr);
 
 
13500
 
 
 
13501
    /* Here we must have a target.  Renew suspicion for new arrivals. */
 
 
13502
    if (!NpcSquad.Squad_Suspicion)
 
 
13503
        PointAlert(2,&marineStatusPointer->weaponTarget);
 
 
13504
 
 
 
13505
    /* first of all, validate this state: if the target suddenly becomes cloaked, then
 
 
13506
    we should switch immediately to wait state.*/
 
 
13507
 
 
 
13508
    //if ((marineStatusPointer->HModelController.keyframe_flags)
 
 
13509
    //    ||(marineStatusPointer->HModelController.Playing==0)) {
 
 
13510
 
 
 
13511
{
 
 
13512
    VECTORCH relPos,relPos2;
 
 
13513
    relPos.vx = marineStatusPointer->Target->DynPtr->Position.vx - sbPtr->DynPtr->Position.vx;
 
 
13514
    relPos.vy = marineStatusPointer->Target->DynPtr->Position.vy - sbPtr->DynPtr->Position.vy;
 
 
13515
    relPos.vz = marineStatusPointer->Target->DynPtr->Position.vz - sbPtr->DynPtr->Position.vz;
 
 
13516
 
 
 
13517
    relPos2.vx = marineStatusPointer->Target->DynPtr->Position.vx - marineStatusPointer->Target->DynPtr->PrevPosition.vx;
 
 
13518
    relPos2.vy = marineStatusPointer->Target->DynPtr->Position.vy - marineStatusPointer->Target->DynPtr->PrevPosition.vy;
 
 
13519
    relPos2.vz = marineStatusPointer->Target->DynPtr->Position.vz - marineStatusPointer->Target->DynPtr->PrevPosition.vz;
 
 
13520
    mod = SpeedRangeMods(&relPos, &relPos2);
 
 
13521
}
 
 
13522
    range = VectorDistance(&marineStatusPointer->Target->DynPtr->Position, &sbPtr->DynPtr->Position);
 
 
13523
 
 
 
13524
    if (!marineStatusPointer->volleySize)
 
 
13525
    {
 
 
13526
        //marineStatusPointer->HModelController.Playing = 0;
 
 
13527
        //marineStatusPointer->HModelController.sequence_timer = 0;
 
 
13528
 
 
 
13529
        /* Only terminate if you haven't fired yet... */
 
 
13530
        if(!MarineCanSeeTarget(sbPtr))
 
 
13531
        {
 
 
13532
            /* ... and remove the gunflash */
 
 
13533
            DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
13534
 
 
 
13535
            /* .... and stop the sound */
 
 
13536
            if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
13537
            {
 
 
13538
                Sound_Stop(marineStatusPointer->soundHandle);        
 
 
13539
                Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
13540
            }
 
 
13541
 
 
 
13542
        return SRC_Request_Wait;
 
 
13543
        }
 
 
13544
 
 
 
13545
        assert(marineStatusPointer->Target);
 
 
13546
        NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
 
 
13547
 
 
 
13548
        /* Fix weapon target! */
 
 
13549
        if (marineStatusPointer->My_Weapon->TargetCallibrationShift)
 
 
13550
        {
 
 
13551
            marineStatusPointer->weaponTarget.vx -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat11,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
13552
            marineStatusPointer->weaponTarget.vy -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat12,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
13553
            marineStatusPointer->weaponTarget.vz -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat13,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
13554
        }
 
 
13555
 
 
 
13556
        /* orientate to firing point first */
 
 
13557
        {
 
 
13558
        VECTORCH orientationDirn;
 
 
13559
        orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
 
 
13560
        orientationDirn.vy = 0;
 
 
13561
        orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
 
 
13562
        int correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE);
 
 
13563
 
 
 
13564
        /* we are not correctly orientated to the target: this could happen because we have
 
 
13565
        just entered this state, or the target has moved during firing*/
 
 
13566
        //if((!correctlyOrientated)||(marineStatusPointer->HModelController.Tweening==Controller_Tweening)) {
 
 
13567
 
 
 
13568
        if (!correctlyOrientated)
 
 
13569
        {
 
 
13570
            /* stop visual and audio cues: technically, we're not firing at this moment */
 
 
13571
            DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
13572
 
 
 
13573
            if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
13574
            {
 
 
13575
                Sound_Stop(marineStatusPointer->soundHandle);
 
 
13576
                Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
13577
            }
 
 
13578
 
 
 
13579
        return SRC_No_Change;
 
 
13580
        }
 
 
13581
        }
 
 
13582
 
 
 
13583
        /* If you are correctly oriented, you can now fire! */
 
 
13584
 
 
 
13585
        marineStatusPointer->volleySize++;
 
 
13586
        marineStatusPointer->HModelController.Playing = 1;
 
 
13587
 
 
 
13588
        if (marineStatusPointer->clipammo > 0)
 
 
13589
            marineStatusPointer->clipammo--;
 
 
13590
 
 
 
13591
        marineStatusPointer->roundsForThisTarget++;
 
 
13592
 
 
 
13593
        /* Alternate gun flash. */
 
 
13594
        if (!strcmp(marineStatusPointer->My_Gunflash_Section->sempai->Section_Name,"dum flash"))
 
 
13595
            marineStatusPointer->My_Gunflash_Section = GetThisSectionData(marineStatusPointer->HModelController.section_data, "dum L flash");
 
 
13596
        else
 
 
13597
            marineStatusPointer->My_Gunflash_Section = GetThisSectionData(marineStatusPointer->HModelController.section_data, "dum flash");
 
 
13598
 
 
 
13599
        MaintainMarineGunFlash(sbPtr);
 
 
13600
 
 
 
13601
        /* look after the sound */
 
 
13602
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
13603
        {
 
 
13604
            Sound_Update3d(marineStatusPointer->soundHandle,&(sbPtr->DynPtr->Position));
 
 
13605
        }
 
 
13606
        else 
 
 
13607
        { 
 
 
13608
            Sound_Play(marineStatusPointer->My_Weapon->StartSound, "d", &sbPtr->DynPtr->Position);
 
 
13609
            Sound_Play(marineStatusPointer->My_Weapon->LoopSound, "del", &sbPtr->DynPtr->Position,
&marineStatusPointer->soundHandle);
 
 
13610
        }
 
 
13611
 
 
 
13612
        /* Now hit the target with one bullet. */
 
 
13613
 
 
 
13614
        switch(marineStatusPointer->Target->type)
 
 
13615
        {
 
 
13616
            case I_BehaviourPredatorPlayer:
 
 
13617
            {
 
 
13618
                if (!PlayerStatus.cloakOn)
 
 
13619
                    break;
 
 
13620
            }
 
 
13621
            case I_BehaviourAlienPlayer:
 
 
13622
                /* Vs the player, lighting effects on aliens and cloaked preds. */
 
 
13623
                hitroll = MUL_FIXED(hitroll, ((PlayerStatus.CurrentLightAtPlayer >> 1) + 32767));
 
 
13624
            default:
 
 
13625
            break;
 
 
13626
        }
 
 
13627
 
 
 
13628
        hitroll -= mod;
 
 
13629
        hitroll += marineStatusPointer->My_Weapon->Accuracy;
 
 
13630
 
 
 
13631
        {
 
 
13632
            /* Handle Damage. */
 
 
13633
            if ((FastRandom() & 65535) < hitroll)
 
 
13634
            {
 
 
13635
                /* DO DAMAGE TO TARGET HERE */
 
 
13636
 
 
 
13637
                VECTORCH rel_pos,attack_dir;
 
 
13638
                int dist;
 
 
13639
                VECTORCH shotvector = { 0, 0, 65535 };
 
 
13640
                RotateVector(&shotvector, &marineStatusPointer->My_Gunflash_Section->SecMat);
 
 
13641
 
 
 
13642
                rel_pos.vx = marineStatusPointer->Target->DynPtr->Position.vx - sbPtr->DynPtr->Position.vx;
 
 
13643
                rel_pos.vy = marineStatusPointer->Target->DynPtr->Position.vy - sbPtr->DynPtr->Position.vy;
 
 
13644
                rel_pos.vz = marineStatusPointer->Target->DynPtr->Position.vz - sbPtr->DynPtr->Position.vz;
 
 
13645
 
 
 
13646
                dist = Approximate3dMagnitude(&rel_pos);
 
 
13647
 
 
 
13648
                if (VerifyHitShot(sbPtr, marineStatusPointer->Target, &marineStatusPointer->My_Gunflash_Section->World_Offset, &shotvector,
marineStatusPointer->My_Weapon->Ammo_Type, 1))
 
 
13649
                {
 
 
13650
                    GetDirectionOfAttack(marineStatusPointer->Target,&rel_pos,&attack_dir);
 
 
13651
                    /* Get hit location? */
 
 
13652
 
 
 
13653
                    marineStatusPointer->lasthitsection = HitLocationRoll(marineStatusPointer->Target,sbPtr);
 
 
13654
 
 
 
13655
                    if (marineStatusPointer->lasthitsection)
 
 
13656
CauseDamageToHModel(marineStatusPointer->lasthitsection->my_controller,
marineStatusPointer->Target,&TemplateAmmo[marineStatusPointer->My_Weapon->Ammo_Type].MaxDamage, ONE_FIXED,
marineStatusPointer->lasthitsection,&attack_dir,NULL,0);
 
 
13657
                    else
 
 
13658
CauseDamageToObject(marineStatusPointer->Target, &TemplateAmmo[marineStatusPointer->My_Weapon->Ammo_Type].MaxDamage, ONE_FIXED, &attack_dir);
 
 
13659
                }
 
 
13660
            }
 
 
13661
            else
 
 
13662
            {
 
 
13663
                assert(marineStatusPointer->My_Gunflash_Section);
 
 
13664
ProjectNPCShot(sbPtr, marineStatusPointer->Target,
&marineStatusPointer->My_Gunflash_Section->World_Offset,&marineStatusPointer->My_Gunflash_Section->SecMat,
marineStatusPointer->My_Weapon->Ammo_Type, 1);
 
 
13665
            }
 
 
13666
 
 
 
13667
            /* Did we get him? */
 
 
13668
            if (NPC_IsDead(marineStatusPointer->Target) && marineStatusPointer->My_Weapon->ARealMarine)
 
 
13669
            {
 
 
13670
                /* Only real marines taunt. */
 
 
13671
                if ((marineStatusPointer->roundsForThisTarget == 1) || MarineRetreatsInTheFaceOfDanger(sbPtr))
 
 
13672
                {
 
 
13673
                    if (Marine_GetNewTarget(&sbPtr->DynPtr->Position,sbPtr) == NULL)
 
 
13674
                    {
 
 
13675
                        /* Huzzah! */
 
 
13676
                        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
13677
 
 
 
13678
                        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
13679
                        {
 
 
13680
                            Sound_Stop(marineStatusPointer->soundHandle);
 
 
13681
                            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
13682
                        }
 
 
13683
                        marineStatusPointer->lastroundhit = 0;
 
 
13684
                        marineStatusPointer->lasthitsection = NULL;
 
 
13685
                        Marine_Enter_Taunt_State(sbPtr);
 
 
13686
                    }
 
 
13687
                }
 
 
13688
            }
 
 
13689
        }
 
 
13690
    }
 
 
13691
    else
 
 
13692
    {
 
 
13693
        /* Remove the gunflash */
 
 
13694
        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
13695
 
 
 
13696
        /* .... and stop the sound */
 
 
13697
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
13698
        {
 
 
13699
            Sound_Stop(marineStatusPointer->soundHandle);        
 
 
13700
            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
13701
        }
 
 
13702
    }
 
 
13703
 
 
 
13704
    marineStatusPointer->stateTimer -= (NormalFrameTime);
 
 
13705
 
 
 
13706
    /* You must have fired already. */
 
 
13707
 
 
 
13708
    if(marineStatusPointer->stateTimer > 0)
 
 
13709
        return SRC_No_Change;
 
 
13710
 
 
 
13711
    if ((range < MARINE_CLOSE_APPROACH_DISTANCE) || marineStatusPointer->Android
 
 
13712
        //||(marineStatusPointer->volleySize<marineStatusPointer->My_Weapon->MinimumBurstSize))
 
 
13713
        )
 
 
13714
    {
 
 
13715
        /* renew firing, as we are still too close to approach */ 
 
 
13716
        marineStatusPointer->stateTimer = marineStatusPointer->My_Weapon->FiringTime;
 
 
13717
        marineStatusPointer->volleySize = 0;
 
 
13718
        assert(marineStatusPointer->Target);
 
 
13719
 
 
 
13720
        NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
 
 
13721
 
 
 
13722
        //if (marineStatusPointer->Android==0)
 
 
13723
        //    marineStatusPointer->Courage-=(ONE_FIXED>>3);
 
 
13724
 
 
 
13725
    return SRC_No_Change;
 
 
13726
    }
 
 
13727
    else
 
 
13728
    {
 
 
13729
        /* we are far enough away, so return to approach */
 
 
13730
 
 
 
13731
        /* Remove the gunflash */
 
 
13732
        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
13733
 
 
 
13734
        marineStatusPointer->volleySize = 0;
 
 
13735
 
 
 
13736
    return SRC_Request_Approach;
 
 
13737
    }
 
 
13738
 
 
 
13739
return SRC_No_Change;
 
 
13740
}
 
 
13741
 
 
 
13742
static STATE_RETURN_CONDITION Execute_MNS_DischargeSkeeter(STRATEGYBLOCK *sbPtr)
 
 
13743
{
 
 
13744
    VECTORCH orientationDirn;
 
 
13745
    int correctlyOrientated;
 
 
13746
    int range;
 
 
13747
 
 
 
13748
    assert(sbPtr);
 
 
13749
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
13750
    assert(marineStatusPointer);
 
 
13751
 
 
 
13752
    /* zero velocity */
 
 
13753
    assert(sbPtr->DynPtr);
 
 
13754
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
13755
 
 
 
13756
    /* If a skeeter launcher has started firing, he can't stop! */
 
 
13757
 
 
 
13758
    if (!marineStatusPointer->clipammo)
 
 
13759
        Marine_Enter_Reload_State(sbPtr);
 
 
13760
 
 
 
13761
    if (marineStatusPointer->Target)
 
 
13762
    {
 
 
13763
        /* Here we must have a target.  Renew suspicion for new arrivals. */
 
 
13764
        if (!NpcSquad.Squad_Suspicion)
 
 
13765
            PointAlert(2,&marineStatusPointer->weaponTarget);
 
 
13766
    }
 
 
13767
 
 
 
13768
    if (marineStatusPointer->stateTimer == marineStatusPointer->My_Weapon->FiringTime)
 
 
13769
    {
 
 
13770
        /* First cycle. */    
 
 
13771
        if (marineStatusPointer->HModelController.Tweening == Controller_NoTweening)
 
 
13772
            marineStatusPointer->HModelController.Playing = 0;
 
 
13773
 
 
 
13774
        /* Only terminate if you haven't begun firing yet... */
 
 
13775
 
 
 
13776
        if (marineStatusPointer->Target == NULL)
 
 
13777
            return SRC_Request_Wait;
 
 
13778
 
 
 
13779
        if(!MarineCanSeeTarget(sbPtr))
 
 
13780
        {
 
 
13781
            /* ... and remove the gunflash */
 
 
13782
            DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
13783
 
 
 
13784
            /* .... and stop the sound */
 
 
13785
            if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
13786
            {
 
 
13787
                Sound_Stop(marineStatusPointer->soundHandle);        
 
 
13788
                Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
13789
            }
 
 
13790
 
 
 
13791
        return SRC_Request_Wait;
 
 
13792
        }
 
 
13793
 
 
 
13794
        assert(marineStatusPointer->Target);
 
 
13795
        NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
 
 
13796
 
 
 
13797
        /* Fix weapon target! */
 
 
13798
        if (marineStatusPointer->My_Weapon->TargetCallibrationShift)
 
 
13799
        {
 
 
13800
            marineStatusPointer->weaponTarget.vx-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat11,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
13801
            marineStatusPointer->weaponTarget.vy-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat12,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
13802
            marineStatusPointer->weaponTarget.vz-=MUL_FIXED(sbPtr->DynPtr->OrientMat.mat13,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
13803
        }
 
 
13804
 
 
 
13805
        /* orientate to firing point first */
 
 
13806
        orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
 
 
13807
        orientationDirn.vy = 0;
 
 
13808
        orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
 
 
13809
        correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE);
 
 
13810
 
 
 
13811
        /* Consider range. */
 
 
13812
 
 
 
13813
        range = VectorDistance(&marineStatusPointer->Target->DynPtr->Position, &sbPtr->DynPtr->Position);
 
 
13814
 
 
 
13815
        /* Are they, by some chance, really close? */
 
 
13816
        if (range < marineStatusPointer->My_Weapon->MinRange)
 
 
13817
        {
 
 
13818
            /* Even a complete idiot wouldn't fire this thing by reflex. */
 
 
13819
            return SRC_Request_PullPistol;
 
 
13820
        }
 
 
13821
 
 
 
13822
        if (correctlyOrientated)
 
 
13823
        {
 
 
13824
            /* If you are correctly oriented, you can now fire! */
 
 
13825
            marineStatusPointer->HModelController.Playing = 1;
 
 
13826
            marineStatusPointer->HModelController.sequence_timer = 0;
 
 
13827
            marineStatusPointer->stateTimer -= NormalFrameTime;
 
 
13828
 
 
 
13829
            if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
13830
                Sound_Stop(marineStatusPointer->soundHandle);
 
 
13831
 
 
 
13832
            if(marineStatusPointer->soundHandle == SOUND_NOACTIVEINDEX)
 
 
13833
                Sound_Play(marineStatusPointer->My_Weapon->StartSound, "de", &sbPtr->DynPtr->Position,
&marineStatusPointer->soundHandle);
 
 
13834
        }
 
 
13835
 
 
 
13836
    return SRC_No_Change;
 
 
13837
    }
 
 
13838
    else if (marineStatusPointer->stateTimer > 0)
 
 
13839
    {
 
 
13840
        /* We must be in the build up. */
 
 
13841
        if (marineStatusPointer->Target)
 
 
13842
        {
 
 
13843
            NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
 
 
13844
            /* Fix weapon target! */
 
 
13845
            if (marineStatusPointer->My_Weapon->TargetCallibrationShift)
 
 
13846
            {
 
 
13847
            marineStatusPointer->weaponTarget.vx -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat11,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
13848
            marineStatusPointer->weaponTarget.vy -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat12,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
13849
            marineStatusPointer->weaponTarget.vz -= MUL_FIXED(sbPtr->DynPtr->OrientMat.mat13,
marineStatusPointer->My_Weapon->TargetCallibrationShift);
 
 
13850
            }
 
 
13851
 
 
 
13852
            /* orientate to firing point first */
 
 
13853
            orientationDirn.vx =  marineStatusPointer->weaponTarget.vx - sbPtr->DynPtr->Position.vx;
 
 
13854
            orientationDirn.vy = 0;
 
 
13855
            orientationDirn.vz = marineStatusPointer->weaponTarget.vz - sbPtr->DynPtr->Position.vz;
 
 
13856
            correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE);
 
 
13857
        }
 
 
13858
        else
 
 
13859
        {
 
 
13860
            /* Tough! */
 
 
13861
            correctlyOrientated = 1;
 
 
13862
        }
 
 
13863
 
 
 
13864
        MaintainMarineGunFlash(sbPtr);
 
 
13865
 
 
 
13866
        /* look after the sound */
 
 
13867
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
13868
            Sound_Update3d(marineStatusPointer->soundHandle,&(sbPtr->DynPtr->Position));
 
 
13869
 
 
 
13870
        marineStatusPointer->stateTimer -= NormalFrameTime;
 
 
13871
 
 
 
13872
    return SRC_No_Change;
 
 
13873
    }
 
 
13874
    else
 
 
13875
    {
 
 
13876
        /* Now fire a skeeter. */
 
 
13877
 
 
 
13878
        /* Remove the gunflash */
 
 
13879
        DestroyActiveObject(&marineStatusPointer->myGunFlash);
 
 
13880
 
 
 
13881
        /* .... and stop the sound */
 
 
13882
        if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
13883
        {
 
 
13884
            Sound_Stop(marineStatusPointer->soundHandle);        
 
 
13885
            Sound_Play(marineStatusPointer->My_Weapon->EndSound, "d", &sbPtr->DynPtr->Position);
 
 
13886
        }
 
 
13887
 
 
 
13888
        {
 
 
13889
            SECTION_DATA *rocket_section = GetThisSectionData(marineStatusPointer->HModelController.section_data, "dum flash");
 
 
13890
 
 
 
13891
            CreateFrisbeeKernel(&rocket_section->World_Offset, &rocket_section->SecMat,0);
 
 
13892
 
 
 
13893
            if (marineStatusPointer->clipammo > 0)
 
 
13894
                marineStatusPointer->clipammo--;
 
 
13895
        }
 
 
13896
 
 
 
13897
        /* You must have fired already. */
 
 
13898
 
 
 
13899
        if(range < MARINE_CLOSE_APPROACH_DISTANCE)
 
 
13900
        {
 
 
13901
            /* renew firing, as we are still too close to approach */ 
 
 
13902
            marineStatusPointer->stateTimer = marineStatusPointer->My_Weapon->FiringTime;                     
 
 
13903
            marineStatusPointer->volleySize = 0;
 
 
13904
            assert(marineStatusPointer->Target);
 
 
13905
            NPCGetTargetPosition(&(marineStatusPointer->weaponTarget),marineStatusPointer->Target);
 
 
13906
 
 
 
13907
        return SRC_No_Change;
 
 
13908
        }
 
 
13909
        else
 
 
13910
        {
 
 
13911
            /* we are far enough away, so return to approach */
 
 
13912
            return SRC_Request_Approach;
 
 
13913
        }
 
 
13914
    }
 
 
13915
 
 
 
13916
return SRC_No_Change;
 
 
13917
}
 
 
13918
 
 
 
13919
static const MARINE_WEAPON_DATA NPC_Marine_Weapons[MNPCW_End] =
 
 
13920
{
 
 
13921
    {
 
 
13922
        MNPCW_PulseRifle,            /* ID */
 
 
13923
        SFX_MUZZLE_FLASH_AMORPHOUS,        /* enum SFX_ID SfxID; */
 
 
13924
        Execute_MNS_DischargePulserifle,    /* Func. */
 
 
13925
        NULL,                    /* Misfire func. */
 
 
13926
        Execute_MNS_PanicFireLOSWeapon,        /* WeaponPanicFireFunction */
 
 
13927
        "hnpcmarine",                /* Riffname */
 
 
13928
        "marine with pulse rifle",         /* HierarchyName */
 
 
13929
        "dum flash",                /* GunflashName */
 
 
13930
        "pulse rifle",                /* ElevationSection */
 
 
13931
        "marine with pulse rifle",         /* HitLocationTableName */
 
 
13932
        "Template",                /* TemplateName */
 
 
13933
        "pulse mag",                /* ClipName */
 
 
13934
        0,                    /* MinRange (Don't fire when closer) */
 
 
13935
        MARINE_CLOSE_APPROACH_DISTANCE,        /* ForceFireRange (Fire if closer) */
 
 
13936
        -1,                    /* MaxRange (Don't fire if further) */
 
 
13937
        0,                    /* Accuracy */
 
 
13938
        100/6 * ONE_FIXED,            /* Firing Rate */
 
 
13939
        MARINE_NEAR_FIRE_TIME,            /* Firing Time */
 
 
13940
        PULSERIFLE_MINIMUM_BURST,        /* MinimumBurstSize */
 
 
13941
        AMMO_10MM_CULW,                /* Ammo profile */
 
 
13942
        99,                    /* clip_size */
 
 
13943
        MSSS_Reload,                /* Reload_Sequence */
 
 
13944
        300,                    /* TargetCallibrationShift */
 
 
13945
        SID_NOSOUND,                /* StartSound */
 
 
13946
        SID_PULSE_LOOP,                /* LoopSound */
 
 
13947
        SID_NOSOUND,                /* EndSound */
 
 
13948
        1,                    /* UseElevation */
 
 
13949
        1,                    /* ARealMarine */
 
 
13950
        0                    /* Android */
 
 
13951
    },
 
 
13952
    {
 
 
13953
        MNPCW_Smartgun,                /* ID */
 
 
13954
        SFX_MUZZLE_FLASH_SMARTGUN,        /* enum SFX_ID SfxID; */
 
 
13955
        Execute_MNS_DischargeSmartgun,        /* Func. */
 
 
13956
        NULL,                    /* Misfire func. */
 
 
13957
        Execute_MNS_PanicFireLOSWeapon,        /* WeaponPanicFireFunction */
 
 
13958
        "hnpcmarine",                /* Riffname */
 
 
13959
        "marine with smart gun",        /* HierarchyName */
 
 
13960
        "dum flash",                /* GunflashName */
 
 
13961
        "smart gun",                /* ElevationSection */
 
 
13962
        "marine with smart gun",         /* HitLocationTableName */
 
 
13963
        "Template",                /* TemplateName */
 
 
13964
        "smart mag",                /* ClipName */
 
 
13965
        0,                    /* MinRange (Don't fire when closer) */
 
 
13966
        MARINE_CLOSE_APPROACH_DISTANCE,        /* ForceFireRange (Fire if closer) */
 
 
13967
        36000,                    /* MaxRange (Don't fire if further) */
 
 
13968
        ONE_FIXED,                /* Accuracy */
 
 
13969
        50*ONE_FIXED,                /* Firing Rate */
 
 
13970
        MARINE_NEAR_FIRE_TIME,            /* Firing Time */
 
 
13971
        SMARTGUN_MINIMUM_BURST,            /* MinimumBurstSize */
 
 
13972
        AMMO_SMARTGUN,                /* Ammo profile */
 
 
13973
        300,                    /* clip_size */
 
 
13974
        MSSS_Reload,                /* Reload_Sequence */
 
 
13975
        0,                    /* TargetCallibrationShift */
 
 
13976
        SID_NOSOUND,                /* StartSound */
 
 
13977
        SID_SMART1,                 /* LoopSound */
 
 
13978
        SID_NOSOUND,                /* EndSound */
 
 
13979
        1,                    /* UseElevation */
 
 
13980
        1,                    /* ARealMarine */
 
 
13981
        0                    /* Android */
 
 
13982
    },
 
 
13983
    {
 
 
13984
        MNPCW_Flamethrower,            /* ID */
 
 
13985
        SFX_NONE,                /* enum SFX_ID SfxID; */
 
 
13986
        Execute_MNS_DischargeFlamethrower,    /* Func. */
 
 
13987
        MarineMisfireFlameThrower,        /* Misfire func. */
 
 
13988
        Execute_MNS_PanicFireFlamethrower,    /* WeaponPanicFireFunction */
 
 
13989
        "hnpcmarine",                /* Riffname */
 
 
13990
        "marine with flame thrower",        /* HierarchyName */
 
 
13991
        "dum flash",                /* GunflashName */
 
 
13992
        "flamer",                /* ElevationSection */
 
 
13993
        "marine with flame thrower",        /* HitLocationTableName */
 
 
13994
        "Template",                /* TemplateName */
 
 
13995
        "flamer mag",                /* ClipName */
 
 
13996
        0,                    /* MinRange (Don't fire when closer) */
 
 
13997
        5000,                    /* ForceFireRange (Fire if closer) */
 
 
13998
        10000,                    /* MaxRange (Don't fire if further) */
 
 
13999
        ONE_FIXED,                /* Accuracy */
 
 
14000
        200,                    /* Firing Rate */
 
 
14001
        MARINE_NEAR_FIRE_TIME<<2,        /* Firing Time */
 
 
14002
        0,                    /* MinimumBurstSize */
 
 
14003
        AMMO_FLAMETHROWER,            /* Ammo profile */
 
 
14004
        (ONE_FIXED*3),                /* clip_size */
 
 
14005
        MSSS_Reload,                /* Reload_Sequence */
 
 
14006
        0,                    /* TargetCallibrationShift */
 
 
14007
        SID_INCIN_START,            /* StartSound */
 
 
14008
        SID_INCIN_LOOP,                /* LoopSound */
 
 
14009
        SID_INCIN_END,                /* EndSound */
 
 
14010
        1,                    /* UseElevation */
 
 
14011
        1,                    /* ARealMarine */
 
 
14012
        0                    /* Android */
 
 
14013
    },
 
 
14014
    {
 
 
14015
        MNPCW_SADAR,                /* ID */
 
 
14016
        SFX_MUZZLE_FLASH_AMORPHOUS,        /* enum SFX_ID SfxID; */
 
 
14017
        Execute_MNS_DischargeSADAR,        /* Func. */
 
 
14018
        NULL,                    /* Misfire func. */
 
 
14019
        Execute_MNS_NullPanicFire,        /* WeaponPanicFireFunction */
 
 
14020
        "hnpcmarine",                /* Riffname */
 
 
14021
        "marine with SADAR",            /* HierarchyName */
 
 
14022
        "dum flame",                /* GunflashName */
 
 
14023
        "SADAR Tube",                /* ElevationSection */
 
 
14024
        "marine with pulse rifle",         /* HitLocationTableName */
 
 
14025
        "Template",                /* TemplateName */
 
 
14026
        "SADAR",                /* ClipName */
 
 
14027
        5000,                    /* MinRange (Don't fire when closer) */
 
 
14028
        MARINE_CLOSE_APPROACH_DISTANCE,        /* ForceFireRange (Fire if closer) */
 
 
14029
        -1,                    /* MaxRange (Don't fire if further) */
 
 
14030
        0,                    /* Accuracy */
 
 
14031
        100/6 * ONE_FIXED,            /* Firing Rate */
 
 
14032
        MARINE_NEAR_FIRE_TIME,            /* Firing Time */
 
 
14033
        0,                    /* MinimumBurstSize */
 
 
14034
        AMMO_10MM_CULW,                /* Ammo profile */
 
 
14035
        1,                    /* clip_size */
 
 
14036
        MSSS_Reload,                /* Reload_Sequence */
 
 
14037
        300,                    /* TargetCallibrationShift */
 
 
14038
        SID_SADAR_FIRE,                /* StartSound */
 
 
14039
        SID_NOSOUND,                /* LoopSound */
 
 
14040
        SID_NOSOUND,                /* EndSound */
 
 
14041
        1,                    /* UseElevation */
 
 
14042
        1,                    /* ARealMarine */
 
 
14043
        0                    /* Android */
 
 
14044
    },
 
 
14045
    {
 
 
14046
        MNPCW_GrenadeLauncher,            /* ID */
 
 
14047
        SFX_MUZZLE_FLASH_AMORPHOUS,        /* enum SFX_ID SfxID; */
 
 
14048
        Execute_MNS_DischargeGL,        /* Func. */
 
 
14049
        NULL,                    /* Misfire func. */
 
 
14050
        Execute_MNS_PanicFireGL,        /* WeaponPanicFireFunction */
 
 
14051
        "hnpcmarine",                /* Riffname */
 
 
14052
        "marine + grenade launcher",        /* HierarchyName */
 
 
14053
        "dum flash",                /* GunflashName */
 
 
14054
        "gren stock",                /* ElevationSection */
 
 
14055
        "marine with pulse rifle",         /* HitLocationTableName */
 
 
14056
        "Template",                /* TemplateName */
 
 
14057
        "gren mag",                /* ClipName */
 
 
14058
        9000,                    /* MinRange (Don't fire when closer) */
 
 
14059
        MARINE_CLOSE_APPROACH_DISTANCE,        /* ForceFireRange (Fire if closer) */
 
 
14060
        -1,                    /* MaxRange (Don't fire if further) */
 
 
14061
        0,                    /* Accuracy */
 
 
14062
        100/6 * ONE_FIXED,            /* Firing Rate */
 
 
14063
        MARINE_NEAR_FIRE_TIME,            /* Firing Time */
 
 
14064
        0,                    /* MinimumBurstSize */
 
 
14065
        AMMO_10MM_CULW,                /* Ammo profile */
 
 
14066
        6,                    /* clip_size */
 
 
14067
        MSSS_Reload,                  /* Reload_Sequence */
 
 
14068
        0,                    /* TargetCallibrationShift */
 
 
14069
        SID_GRENADE_LAUNCH,                /* StartSound */
 
 
14070
        SID_NOSOUND,                /* LoopSound */
 
 
14071
        SID_NOSOUND,                /* EndSound */
 
 
14072
        1,                    /* UseElevation */
 
 
14073
        1,                    /* ARealMarine */
 
 
14074
        0                    /* Android */
 
 
14075
    },
 
 
14076
    {
 
 
14077
        MNPCW_Minigun,                /* ID */
 
 
14078
        SFX_MUZZLE_FLASH_AMORPHOUS,        /* enum SFX_ID SfxID; */
 
 
14079
        Execute_MNS_DischargeMinigun,        /* Func. */
 
 
14080
        NULL,                    /* Misfire func. */
 
 
14081
        Execute_MNS_PanicFireMinigun,        /* WeaponPanicFireFunction */
 
 
14082
        "hnpcmarine",                /* Riffname */
 
 
14083
        "Marine with Mini Gun",         /* HierarchyName */
 
 
14084
        "dum flash",                /* GunflashName */
 
 
14085
        "mini gun",                /* ElevationSection */
 
 
14086
        "marine with pulse rifle",         /* HitLocationTableName */
 
 
14087
        "Template",                /* TemplateName */
 
 
14088
        "mini mag",                /* ClipName */
 
 
14089
        0,                    /* MinRange (Don't fire when closer) */
 
 
14090
        MARINE_CLOSE_APPROACH_DISTANCE,        /* ForceFireRange (Fire if closer) */
 
 
14091
        -1,                    /* MaxRange (Don't fire if further) */
 
 
14092
        0,                    /* Accuracy */
 
 
14093
        100 * ONE_FIXED,            /* Firing Rate */
 
 
14094
        MARINE_NEAR_FIRE_TIME,            /* Firing Time */
 
 
14095
        MINIGUN_MINIMUM_BURST,            /* MinimumBurstSize */
 
 
14096
        AMMO_MINIGUN,                /* Ammo profile */
 
 
14097
        800,                    /* clip_size */
 
 
14098
        MSSS_Reload,                /* Reload_Sequence */
 
 
14099
        0,                    /* TargetCallibrationShift */
 
 
14100
        SID_NOSOUND,                /* StartSound */
 
 
14101
        SID_MINIGUN_LOOP,            /* LoopSound */
 
 
14102
        SID_MINIGUN_END,             /* EndSound */
 
 
14103
        1,                    /* UseElevation */
 
 
14104
        1,                    /* ARealMarine */
 
 
14105
        0                    /* Android */
 
 
14106
    },
 
 
14107
    {
 
 
14108
        MNPCW_PistolMarine,            /* ID */
 
 
14109
        SFX_MUZZLE_FLASH_AMORPHOUS,        /* enum SFX_ID SfxID; */
 
 
14110
        Execute_MNS_DischargePistol,        /* Func. */
 
 
14111
        NULL,                    /* Misfire func. */
 
 
14112
        Execute_MNS_PanicFirePistol,        /* WeaponPanicFireFunction */
 
 
14113
        "hnpcmarine",                /* Riffname */
 
 
14114
        "PISTOL",                /* HierarchyName */
 
 
14115
        "dum flash",                /* GunflashName */
 
 
14116
        "Rbicep",                /* ElevationSection */
 
 
14117
        "marine with pulse rifle",         /* HitLocationTableName */
 
 
14118
        "Template",                /* TemplateName */
 
 
14119
        NULL,                    /* ClipName */
 
 
14120
        0,                    /* MinRange (Don't fire when closer) */
 
 
14121
        MARINE_CLOSE_APPROACH_DISTANCE,        /* ForceFireRange (Fire if closer) */
 
 
14122
        -1,                    /* MaxRange (Don't fire if further) */
 
 
14123
        30000,                      /* Accuracy */
 
 
14124
        1,                    /* Firing Rate */
 
 
14125
        MARINE_NEAR_FIRE_TIME,            /* Firing Time */
 
 
14126
        0,                    /* MinimumBurstSize */
 
 
14127
        AMMO_MARINE_PISTOL,            /* Ammo profile */
 
 
14128
        12,                    /* clip_size */
 
 
14129
        MSSS_Reload,                /* Reload_Sequence */
 
 
14130
        250,                    /* TargetCallibrationShift */
 
 
14131
        SID_SHOTGUN,                /* StartSound */
 
 
14132
        SID_NOSOUND,                /* LoopSound */
 
 
14133
        SID_NOSOUND,                /* EndSound */
 
 
14134
        1,                    /* UseElevation */
 
 
14135
        1,                    /* ARealMarine */
 
 
14136
        0                    /* Android */
 
 
14137
    },
 
 
14138
    {
 
 
14139
        MNPCW_MShotgun,                /* ID */
 
 
14140
        SFX_MUZZLE_FLASH_AMORPHOUS,        /* enum SFX_ID SfxID; */
 
 
14141
        Execute_MNS_DischargeShotgun,        /* Func. */
 
 
14142
        NULL,                    /* Misfire func. */
 
 
14143
        Execute_MNS_PanicFireShotgun,        /* WeaponPanicFireFunction */
 
 
14144
        "hnpc_civvie",                /* Riffname */
 
 
14145
        "male_shotgun",                 /* HierarchyName */
 
 
14146
        "flash dummy",                /* GunflashName */
 
 
14147
        "shot gun",                /* ElevationSection */
 
 
14148
        "male civvie",                 /* HitLocationTableName */
 
 
14149
        "TEMPLATE",                /* TemplateName */
 
 
14150
        NULL,                    /* ClipName */
 
 
14151
        0,                    /* MinRange (Don't fire when closer) */
 
 
14152
        MARINE_CLOSE_APPROACH_DISTANCE,        /* ForceFireRange (Fire if closer) */
 
 
14153
        -1,                    /* MaxRange (Don't fire if further) */
 
 
14154
        0,                    /* Accuracy */
 
 
14155
        1,                    /* Firing Rate */
 
 
14156
        -1,                    /* Firing Time */
 
 
14157
        0,                    /* MinimumBurstSize */
 
 
14158
        AMMO_SHOTGUN,                /* Ammo profile */
 
 
14159
        8,                    /* clip_size */
 
 
14160
        MSSS_Reload,                /* Reload_Sequence */
 
 
14161
        0,                    /* TargetCallibrationShift */
 
 
14162
        SID_SHOTGUN,                /* StartSound */
 
 
14163
        SID_NOSOUND,                /* LoopSound */
 
 
14164
        SID_NOSOUND,                /* EndSound */
 
 
14165
        1,                    /* UseElevation */
 
 
14166
        0,                    /* ARealMarine */
 
 
14167
        0                    /* Android */
 
 
14168
    },
 
 
14169
    {
 
 
14170
        MNPCW_MPistol,                /* ID */
 
 
14171
        SFX_MUZZLE_FLASH_AMORPHOUS,        /* enum SFX_ID SfxID; */
 
 
14172
        Execute_MNS_DischargePistol,        /* Func. */
 
 
14173
        NULL,                    /* Misfire func. */
 
 
14174
        Execute_MNS_PanicFirePistol,        /* WeaponPanicFireFunction */
 
 
14175
        "hnpc_civvie",                /* Riffname */
 
 
14176
        "male_pistol",                 /* HierarchyName */
 
 
14177
        "flash dummy",                /* GunflashName */
 
 
14178
        "male right bicep",            /* ElevationSection */
 
 
14179
        "male civvie",                 /* HitLocationTableName */
 
 
14180
        "TEMPLATE",                /* TemplateName */
 
 
14181
        NULL,                    /* ClipName */
 
 
14182
        0,                    /* MinRange (Don't fire when closer) */
 
 
14183
        MARINE_CLOSE_APPROACH_DISTANCE,        /* ForceFireRange (Fire if closer) */
 
 
14184
        -1,                    /* MaxRange (Don't fire if further) */
 
 
14185
        10000,                      /* Accuracy */
 
 
14186
        1,                    /* Firing Rate */
 
 
14187
        MARINE_NEAR_FIRE_TIME,            /* Firing Time */
 
 
14188
        0,                    /* MinimumBurstSize */
 
 
14189
        AMMO_10MM_CULW,                /* Ammo profile */
 
 
14190
        PISTOL_CLIP_SIZE,            /* clip_size */
 
 
14191
        MSSS_Reload,                /* Reload_Sequence */
 
 
14192
        0,                    /* TargetCallibrationShift */
 
 
14193
        SID_SHOTGUN,                /* StartSound */
 
 
14194
        SID_NOSOUND,                /* LoopSound */
 
 
14195
        SID_NOSOUND,                /* EndSound */
 
 
14196
        1,                    /* UseElevation */
 
 
14197
        0,                    /* ARealMarine */
 
 
14198
        0                    /* Android */
 
 
14199
    },
 
 
14200
    {
 
 
14201
        MNPCW_MFlamer,                /* ID */
 
 
14202
        SFX_NONE,                /* enum SFX_ID SfxID; */
 
 
14203
        Execute_MNS_DischargeFlamethrower,    /* Func. */
 
 
14204
        MarineMisfireFlameThrower,        /* Misfire func. */
 
 
14205
        Execute_MNS_PanicFireFlamethrower,    /* WeaponPanicFireFunction */
 
 
14206
        "hnpc_civvie",                /* Riffname */
 
 
14207
        "male_flamer",                 /* HierarchyName */
 
 
14208
        "flash dummy",                /* GunflashName */
 
 
14209
        "male right bicep",            /* ElevationSection */
 
 
14210
        "male civvie",                 /* HitLocationTableName */
 
 
14211
        "TEMPLATE",                /* TemplateName */
 
 
14212
        "flame canaster",            /* ClipName */
 
 
14213
        0,                    /* MinRange (Don't fire when closer) */
 
 
14214
        5000,                    /* ForceFireRange (Fire if closer) */
 
 
14215
        10000,                    /* MaxRange (Don't fire if further) */
 
 
14216
        ONE_FIXED,                /* Accuracy */
 
 
14217
        200,                    /* Firing Rate */
 
 
14218
        MARINE_NEAR_FIRE_TIME<<2,        /* Firing Time */
 
 
14219
        0,                    /* MinimumBurstSize */
 
 
14220
        AMMO_FLAMETHROWER,            /* Ammo profile */
 
 
14221
        (ONE_FIXED*2),                /* clip_size */
 
 
14222
        MSSS_Reload,                 /* Reload_Sequence */
 
 
14223
        0,                    /* TargetCallibrationShift */
 
 
14224
        SID_INCIN_START,            /* StartSound */
 
 
14225
        SID_INCIN_LOOP,                /* LoopSound */
 
 
14226
        SID_INCIN_END,                /* EndSound */
 
 
14227
        1,                    /* UseElevation */
 
 
14228
        0,                    /* ARealMarine */
 
 
14229
        0                    /* Android */
 
 
14230
    },
 
 
14231
    {
 
 
14232
        MNPCW_MUnarmed,                /* ID */
 
 
14233
        SFX_NONE,                /* enum SFX_ID SfxID; */
 
 
14234
        unarmed_weapon_func,            /* Func. */
 
 
14235
        NULL,                    /* Misfire func. */
 
 
14236
        Execute_MNS_PanicFireUnarmed,        /* WeaponPanicFireFunction */
 
 
14237
        "hnpc_civvie",                 /* Riffname */
 
 
14238
        "male_unarmed",                 /* HierarchyName */
 
 
14239
        NULL,                    /* GunflashName */
 
 
14240
        NULL,                    /* ElevationSection */
 
 
14241
        "male civvie",                /* HitLocationTableName */
 
 
14242
        "TEMPLATE",                /* TemplateName */
 
 
14243
        NULL,                    /* ClipName */
 
 
14244
        0,                    /* MinRange (Don't fire when closer) */
 
 
14245
        MARINE_CLOSE_APPROACH_DISTANCE,        /* ForceFireRange (Fire if closer) */
 
 
14246
        -1,                    /* MaxRange (Don't fire if further) */
 
 
14247
        0,                    /* Accuracy */
 
 
14248
        1,                    /* Firing Rate */
 
 
14249
        MARINE_NEAR_FIRE_TIME,            /* Firing Time */
 
 
14250
        0,                    /* MinimumBurstSize */
 
 
14251
        AMMO_NONE,                /* Ammo profile */
 
 
14252
        -1,                    /* clip_size */
 
 
14253
        MSSS_Standard,                /* Reload_Sequence */
 
 
14254
        0,                    /* TargetCallibrationShift */
 
 
14255
        SID_NOSOUND,                /* StartSound */
 
 
14256
        SID_NOSOUND,                /* LoopSound */
 
 
14257
        SID_NOSOUND,                /* EndSound */
 
 
14258
        0,                    /* UseElevation */
 
 
14259
        0,                    /* ARealMarine */
 
 
14260
        0                    /* Android */
 
 
14261
    },
 
 
14262
    {
 
 
14263
        MNPCW_MMolotov,                /* ID */
 
 
14264
        SFX_NONE,                /* enum SFX_ID SfxID; */
 
 
14265
        Execute_MNS_ThrowMolotov,        /* Func. */
 
 
14266
        NULL,                    /* Misfire func. */
 
 
14267
        Execute_MNS_NullPanicFire,        /* WeaponPanicFireFunction */
 
 
14268
        "hnpc_civvie",                /* Riffname */
 
 
14269
        "male_bottle",                  /* HierarchyName */
 
 
14270
        "bottle",                /* GunflashName */
 
 
14271
        NULL,                    /* ElevationSection */
 
 
14272
        "male civvie",                 /* HitLocationTableName */
 
 
14273
        "TEMPLATE",                /* TemplateName */
 
 
14274
        NULL,                    /* ClipName */
 
 
14275
        0,                    /* MinRange (Don't fire when closer) */
 
 
14276
        MARINE_CLOSE_APPROACH_DISTANCE,        /* ForceFireRange (Fire if closer) */
 
 
14277
        10000,                    /* MaxRange (Don't fire if further) */
 
 
14278
        -10000,                    /* Accuracy */
 
 
14279
        1,                    /* Firing Rate */
 
 
14280
        MARINE_NEAR_FIRE_TIME,            /* Firing Time */
 
 
14281
        0,                    /* MinimumBurstSize */
 
 
14282
        AMMO_10MM_CULW,                /* Ammo profile */
 
 
14283
        -1,                    /* clip_size */
 
 
14284
        MSSS_Standard,                /* Reload_Sequence */
 
 
14285
        0,                    /* TargetCallibrationShift */
 
 
14286
        SID_NOSOUND,                /* StartSound */
 
 
14287
        SID_NOSOUND,                /* LoopSound */
 
 
14288
        SID_NOSOUND,                /* EndSound */
 
 
14289
        0,                    /* UseElevation */
 
 
14290
        0,                    /* ARealMarine */
 
 
14291
        0                    /* Android */
 
 
14292
    },
 
 
14293
    {
 
 
14294
        MNPCW_Android,                /* ID */
 
 
14295
        SFX_MUZZLE_FLASH_AMORPHOUS,        /* enum SFX_ID SfxID; */
 
 
14296
        Execute_MNS_DischargeShotgun,        /* Func. */
 
 
14297
        NULL,                    /* Misfire func. */
 
 
14298
        Execute_MNS_PanicFireShotgun,        /* WeaponPanicFireFunction */
 
 
14299
        "hnpc_civvie",                /* Riffname */
 
 
14300
        "Android shotgun",             /* HierarchyName */
 
 
14301
        "flash dummy",                /* GunflashName */
 
 
14302
        "shot gun",                /* ElevationSection */
 
 
14303
        "male civvie",                 /* HitLocationTableName */
 
 
14304
        "Android template",            /* TemplateName */
 
 
14305
        NULL,                    /* ClipName */
 
 
14306
        0,                    /* MinRange (Don't fire when closer) */
 
 
14307
        MARINE_CLOSE_APPROACH_DISTANCE,        /* ForceFireRange (Fire if closer) */
 
 
14308
        -1,                    /* MaxRange (Don't fire if further) */
 
 
14309
        0,                    /* Accuracy */
 
 
14310
        1,                    /* Firing Rate */
 
 
14311
        -1,                    /* Firing Time */
 
 
14312
        0,                    /* MinimumBurstSize */
 
 
14313
        AMMO_SHOTGUN,                /* Ammo profile */
 
 
14314
        8,                    /* clip_size */
 
 
14315
        MSSS_Reload,                /* Reload_Sequence */
 
 
14316
        0,                    /* TargetCallibrationShift */
 
 
14317
        SID_SHOTGUN,                /* StartSound */
 
 
14318
        SID_NOSOUND,                /* LoopSound */
 
 
14319
        SID_NOSOUND,                /* EndSound */
 
 
14320
        1,                    /* UseElevation */
 
 
14321
        0,                    /* ARealMarine */
 
 
14322
        1                    /* Android */
 
 
14323
    },
 
 
14324
    {
 
 
14325
        MNPCW_AndroidSpecial,            /* ID */
 
 
14326
        SFX_MUZZLE_FLASH_AMORPHOUS,        /* enum SFX_ID SfxID; */
 
 
14327
        Execute_MNS_DischargeShotgun,        /* Func. */
 
 
14328
        NULL,                    /* Misfire func. */
 
 
14329
        Execute_MNS_PanicFireShotgun,        /* WeaponPanicFireFunction */
 
 
14330
        "hnpc_civvie",                /* Riffname */
 
 
14331
        "Android Shotgun Special",        /* HierarchyName */
 
 
14332
        "flash dummy",                /* GunflashName */
 
 
14333
        "male right bicep",            /* ElevationSection */
 
 
14334
        "male civvie",                 /* HitLocationTableName */
 
 
14335
        "Android template",            /* TemplateName */
 
 
14336
        NULL,                    /* ClipName */
 
 
14337
        0,                    /* MinRange (Don't fire when closer) */
 
 
14338
        MARINE_CLOSE_APPROACH_DISTANCE,        /* ForceFireRange (Fire if closer) */
 
 
14339
        -1,                    /* MaxRange (Don't fire if further) */
 
 
14340
        0,                    /* Accuracy */
 
 
14341
        1,                    /* Firing Rate */
 
 
14342
        -1,                    /* Firing Time */
 
 
14343
        0,                    /* MinimumBurstSize */
 
 
14344
        AMMO_SHOTGUN,                /* Ammo profile */
 
 
14345
        8,                    /* clip_size */
 
 
14346
        MSSS_Reload,                /* Reload_Sequence */
 
 
14347
        0,                    /* TargetCallibrationShift */
 
 
14348
        SID_SHOTGUN,                /* StartSound */
 
 
14349
        SID_NOSOUND,                /* LoopSound */
 
 
14350
        SID_NOSOUND,                /* EndSound */
 
 
14351
        1,                    /* UseElevation */
 
 
14352
        0,                    /* ARealMarine */
 
 
14353
        1                    /* Android */
 
 
14354
    },
 
 
14355
    {
 
 
14356
        MNPCW_Android_Pistol_Special,        /* ID */
 
 
14357
        SFX_MUZZLE_FLASH_AMORPHOUS,        /* enum SFX_ID SfxID; */
 
 
14358
        Execute_MNS_DischargePistol,        /* Func. */
 
 
14359
        NULL,                    /* Misfire func. */
 
 
14360
        Execute_MNS_PanicFirePistol,        /* WeaponPanicFireFunction */
 
 
14361
        "hnpc_civvie",                /* Riffname */
 
 
14362
        "Android Pistol Special",        /* HierarchyName */
 
 
14363
        "flash dummy",                /* GunflashName */
 
 
14364
        "male right bicep",            /* ElevationSection */
 
 
14365
        "male civvie",                 /* HitLocationTableName */
 
 
14366
        "Android template",            /* TemplateName */
 
 
14367
        NULL,                    /* ClipName */
 
 
14368
        0,                    /* MinRange (Don't fire when closer) */
 
 
14369
        MARINE_CLOSE_APPROACH_DISTANCE,        /* ForceFireRange (Fire if closer) */
 
 
14370
        -1,                    /* MaxRange (Don't fire if further) */
 
 
14371
        10000,                      /* Accuracy */
 
 
14372
        1,                    /* Firing Rate */
 
 
14373
        MARINE_NEAR_FIRE_TIME,            /* Firing Time */
 
 
14374
        0,                    /* MinimumBurstSize */
 
 
14375
        AMMO_10MM_CULW,                /* Ammo profile */
 
 
14376
        PISTOL_CLIP_SIZE,            /* clip_size */
 
 
14377
        MSSS_Reload,                /* Reload_Sequence */
 
 
14378
        0,                    /* TargetCallibrationShift */
 
 
14379
        SID_SHOTGUN,                /* StartSound */
 
 
14380
        SID_NOSOUND,                /* LoopSound */
 
 
14381
        SID_NOSOUND,                /* EndSound */
 
 
14382
        1,                    /* UseElevation */
 
 
14383
        0,                    /* ARealMarine */
 
 
14384
        1                    /* Android */
 
 
14385
    },
 
 
14386
    {
 
 
14387
        MNPCW_TwoPistols,            /* ID */
 
 
14388
        SFX_MUZZLE_FLASH_AMORPHOUS,        /* enum SFX_ID SfxID; */
 
 
14389
        Execute_MNS_DischargeTwoPistols,    /* Func. */
 
 
14390
        NULL,                    /* Misfire func. */
 
 
14391
        Execute_MNS_PanicFirePistol,        /* WeaponPanicFireFunction */
 
 
14392
        "hnpcmarine",                /* Riffname */
 
 
14393
        "Two Pistol",                 /* HierarchyName */
 
 
14394
        "dum flash",                /* GunflashName */
 
 
14395
        "Rbicep",                /* ElevationSection */
 
 
14396
        "marine with pulse rifle",         /* HitLocationTableName */
 
 
14397
        "Template",                /* TemplateName */
 
 
14398
        NULL,                    /* ClipName */
 
 
14399
        0,                    /* MinRange (Don't fire when closer) */
 
 
14400
        MARINE_CLOSE_APPROACH_DISTANCE,        /* ForceFireRange (Fire if closer) */
 
 
14401
        -1,                    /* MaxRange (Don't fire if further) */
 
 
14402
        30000,                      /* Accuracy */
 
 
14403
        12,                    /* Firing Rate */
 
 
14404
        (MARINE_NEAR_FIRE_TIME>>2),        /* Firing Time */
 
 
14405
        0,                    /* MinimumBurstSize */
 
 
14406
        AMMO_MARINE_PISTOL,            /* Ammo profile */
 
 
14407
        24,                    /* clip_size */
 
 
14408
        MSSS_Reload,                /* Reload_Sequence */
 
 
14409
        250,                    /* TargetCallibrationShift */
 
 
14410
        SID_SHOTGUN,                /* StartSound */
 
 
14411
        SID_NOSOUND,                /* LoopSound */
 
 
14412
        SID_NOSOUND,                /* EndSound */
 
 
14413
        1,                    /* UseElevation */
 
 
14414
        1,                    /* ARealMarine */
 
 
14415
        0                    /* Android */
 
 
14416
    },
 
 
14417
    {
 
 
14418
        MNPCW_Skeeter,                /* ID */
 
 
14419
        SFX_MUZZLE_FLASH_SKEETER,        /* enum SFX_ID SfxID; */
 
 
14420
        Execute_MNS_DischargeSkeeter,        /* Func. */
 
 
14421
        NULL,                    /* Misfire func. */
 
 
14422
        Execute_MNS_NullPanicFire,        /* WeaponPanicFireFunction */
 
 
14423
        "hnpcmarine",                /* Riffname */
 
 
14424
        "skeeter",                /* HierarchyName */
 
 
14425
        "dum flash",                /* GunflashName */
 
 
14426
        "Skeeter Tube",                /* ElevationSection */
 
 
14427
        "marine with pulse rifle",         /* HitLocationTableName */
 
 
14428
        "Template",                /* TemplateName */
 
 
14429
        "Skeeter",                /* ClipName */
 
 
14430
        5000,                    /* MinRange (Don't fire when closer) */
 
 
14431
        MARINE_CLOSE_APPROACH_DISTANCE,        /* ForceFireRange (Fire if closer) */
 
 
14432
        -1,                    /* MaxRange (Don't fire if further) */
 
 
14433
        0,                    /* Accuracy */
 
 
14434
        ONE_FIXED,                /* Firing Rate */
 
 
14435
        1625*ONE_FIXED/2000,            /* Firing Time */
 
 
14436
        0,                    /* MinimumBurstSize */
 
 
14437
        AMMO_10MM_CULW,                /* Ammo profile */
 
 
14438
        1,                    /* clip_size */
 
 
14439
        MSSS_Reload,                /* Reload_Sequence */
 
 
14440
        300,                    /* TargetCallibrationShift */
 
 
14441
        //SID_ED_SKEETERCHARGE,            /* StartSound */
 
 
14442
        0,                    /* StartSound */
 
 
14443
        SID_NOSOUND,                /* LoopSound */
 
 
14444
        //SID_ED_SKEETERLAUNCH,            /* EndSound */
 
 
14445
        0,
 
 
14446
        1,                    /* UseElevation */
 
 
14447
        1,                    /* ARealMarine */
 
 
14448
        0                    /* Android */
 
 
14449
    },
 
 
14450
    {
 
 
14451
        MNPCW_Scientist_A,            /* ID */
 
 
14452
        SFX_NONE,                /* enum SFX_ID SfxID; */
 
 
14453
        unarmed_weapon_func,            /* Func. */
 
 
14454
        NULL,                    /* Misfire func. */
 
 
14455
        Execute_MNS_NullPanicFire,        /* WeaponPanicFireFunction */
 
 
14456
        "scientist",                /* Riffname */
 
 
14457
        "clip",                     /* HierarchyName */
 
 
14458
        "clip board",                /* GunflashName */
 
 
14459
        NULL,                    /* ElevationSection */
 
 
14460
        "bub with molotov",             /* HitLocationTableName */
 
 
14461
        "Template",                /* TemplateName */
 
 
14462
        NULL,                    /* ClipName */
 
 
14463
        0,                    /* MinRange (Don't fire when closer) */
 
 
14464
        MARINE_CLOSE_APPROACH_DISTANCE,        /* ForceFireRange (Fire if closer) */
 
 
14465
        10000,                    /* MaxRange (Don't fire if further) */
 
 
14466
        -10000,                    /* Accuracy */
 
 
14467
        1,                    /* Firing Rate */
 
 
14468
        MARINE_NEAR_FIRE_TIME,            /* Firing Time */
 
 
14469
        0,                    /* MinimumBurstSize */
 
 
14470
        AMMO_10MM_CULW,                /* Ammo profile */
 
 
14471
        -1,                    /* clip_size */
 
 
14472
        MSSS_Standard,                /* Reload_Sequence */
 
 
14473
        0,                    /* TargetCallibrationShift */
 
 
14474
        SID_NOSOUND,                /* StartSound */
 
 
14475
        SID_NOSOUND,                /* LoopSound */
 
 
14476
        SID_NOSOUND,                /* EndSound */
 
 
14477
        0,                    /* UseElevation */
 
 
14478
        0,                    /* ARealMarine */
 
 
14479
        0                    /* Android */
 
 
14480
    },
 
 
14481
    {
 
 
14482
        MNPCW_Scientist_B,            /* ID */
 
 
14483
        SFX_NONE,                /* enum SFX_ID SfxID; */
 
 
14484
        unarmed_weapon_func,            /* Func. */
 
 
14485
        NULL,                    /* Misfire func. */
 
 
14486
        Execute_MNS_NullPanicFire,        /* WeaponPanicFireFunction */
 
 
14487
        "scientist",                /* Riffname */
 
 
14488
        "testtube",                  /* HierarchyName */
 
 
14489
        "test tube",                /* GunflashName */
 
 
14490
        NULL,                    /* ElevationSection */
 
 
14491
        "bub with molotov",             /* HitLocationTableName */
 
 
14492
        "Template",                /* TemplateName */
 
 
14493
        NULL,                    /* ClipName */
 
 
14494
        0,                    /* MinRange (Don't fire when closer) */
 
 
14495
        MARINE_CLOSE_APPROACH_DISTANCE,        /* ForceFireRange (Fire if closer) */
 
 
14496
        10000,                    /* MaxRange (Don't fire if further) */
 
 
14497
        -10000,                    /* Accuracy */
 
 
14498
        1,                    /* Firing Rate */
 
 
14499
        MARINE_NEAR_FIRE_TIME,            /* Firing Time */
 
 
14500
        0,                    /* MinimumBurstSize */
 
 
14501
        AMMO_10MM_CULW,                /* Ammo profile */
 
 
14502
        -1,                    /* clip_size */
 
 
14503
        MSSS_Standard,                /* Reload_Sequence */
 
 
14504
        0,                    /* TargetCallibrationShift */
 
 
14505
        SID_NOSOUND,                /* StartSound */
 
 
14506
        SID_NOSOUND,                /* LoopSound */
 
 
14507
        SID_NOSOUND,                /* EndSound */
 
 
14508
        0,                    /* UseElevation */
 
 
14509
        0,                    /* ARealMarine */
 
 
14510
        0                    /* Android */
 
 
14511
    }
 
 
14512
};
 
 
14513
 
 
 
14514
const MARINE_WEAPON_DATA *GetThisNPCMarineWeapon(MARINE_NPC_WEAPONS this_id)
 
 
14515
{
 
 
14516
    return &NPC_Marine_Weapons[this_id];
 
 
14517
}
 
 
14518
 
 
 
14519
/*--------------------**
 
 
14520
** Loading and Saving **
 
 
14521
**--------------------*/
 
 
14522
#include "savegame.h"
 
 
14523
typedef struct marine_save_block
 
 
14524
{
 
 
14525
    SAVE_BLOCK_STRATEGY_HEADER header;
 
 
14526
 
 
 
14527
 //from marine status block
 
 
14528
     signed int volleySize;
 
 
14529
 
 
 
14530
     MARINE_BHSTATE behaviourState;
 
 
14531
     MARINE_BHSTATE lastState;
 
 
14532
 
 
 
14533
    MARINE_MISSION Mission;
 
 
14534
 
 
 
14535
    VECTORCH my_spot;
 
 
14536
    VECTORCH my_facing_point;
 
 
14537
 
 
 
14538
    /* Movement data. */
 
 
14539
    signed int nearSpeed;
 
 
14540
    int acceleration;
 
 
14541
    int speedConstant;
 
 
14542
    int accelerationConstant;
 
 
14543
    VECTORCH suspect_point;
 
 
14544
    int suspicious;
 
 
14545
    int previous_suspicion;
 
 
14546
    int using_squad_suspicion;
 
 
14547
    int gotapoint;
 
 
14548
    int lastframe_fallingspeed;
 
 
14549
    /* Pathfinder parameters */
 
 
14550
    int path;
 
 
14551
    int stepnumber;
 
 
14552
    /* Pathfinder parameters */
 
 
14553
    int stateTimer;
 
 
14554
    int internalState;
 
 
14555
 
 
 
14556
    VECTORCH weaponTarget;        /* position for firing weapon at */
 
 
14557
 
 
 
14558
    NPC_OBSTRUCTIONREPORT obstruction;
 
 
14559
    NPC_WANDERDATA wanderData;
 
 
14560
 
 
 
14561
    int IAmCrouched;
 
 
14562
    int lastroundhit;
 
 
14563
    int GibbFactor;
 
 
14564
    int Wounds;
 
 
14565
    int incidentFlag;
 
 
14566
    int incidentTimer;
 
 
14567
    int weapon_variable;
 
 
14568
    int weapon_variable2;
 
 
14569
    int clipammo;
 
 
14570
    int roundsForThisTarget;
 
 
14571
    int Female;
 
 
14572
    int Android;
 
 
14573
    int Skill;
 
 
14574
    int Courage;
 
 
14575
    int Voice;
 
 
14576
    int VoicePitch;
 
 
14577
    int FiringAnim;
 
 
14578
    int Expression;
 
 
14579
    int Target_Expression;
 
 
14580
    int Blink;
 
 
14581
    int SpotFlag;
 
 
14582
    int FlareActive;
 
 
14583
//annoying pointer related things
 
 
14584
    int lastmodule_index;
 
 
14585
    int destinationmodule_index;
 
 
14586
    int missionmodule_index;
 
 
14587
    int fearmodule_index;
 
 
14588
 
 
 
14589
    char Target_SBname[SB_NAME_LENGTH];
 
 
14590
    char Generator_SBname[SB_NAME_LENGTH];
 
 
14591
 
 
 
14592
    int weapon_id;
 
 
14593
 
 
 
14594
    //strategyblock stuff
 
 
14595
    DAMAGEBLOCK DamageBlock;
 
 
14596
    DYNAMICSBLOCK dynamics;
 
 
14597
 
 
 
14598
} MARINE_SAVE_BLOCK;
 
 
14599
 
 
 
14600
//defines for load/save macros
 
 
14601
#define SAVELOAD_BLOCK block
 
 
14602
#define SAVELOAD_BEHAV marineStatusPointer
 
 
14603
 
 
 
14604
void LoadStrategy_Marine(SAVE_BLOCK_STRATEGY_HEADER* header)
 
 
14605
{
 
 
14606
    MARINE_SAVE_BLOCK* block = (MARINE_SAVE_BLOCK*) header; 
 
 
14607
 
 
 
14608
    //check the size of the save block
 
 
14609
    if(header->size != sizeof(*block))
 
 
14610
        return;
 
 
14611
 
 
 
14612
    //find the existing strategy block
 
 
14613
    STRATEGYBLOCK* sbPtr = FindSBWithName(header->SBname);
 
 
14614
 
 
 
14615
    if(sbPtr)
 
 
14616
    {
 
 
14617
        //make sure the strategy found is of the right type
 
 
14618
        if(sbPtr->type != I_BehaviourMarine)
 
 
14619
            return;
 
 
14620
    }
 
 
14621
    else
 
 
14622
    {
 
 
14623
        //we will have to generate an alien then
 
 
14624
        TOOLS_DATA_MARINE tdm;
 
 
14625
 
 
 
14626
        //make sure the marine is in a module 
 
 
14627
        if(!ModuleFromPosition(&block->dynamics.Position, NULL))
 
 
14628
                return;
 
 
14629
 
 
 
14630
        sbPtr = CreateActiveStrategyBlock(I_BehaviourMarine);
 
 
14631
 
 
 
14632
        if(!sbPtr)
 
 
14633
            return;
 
 
14634
 
 
 
14635
        sbPtr->maintainVisibility = 1;
 
 
14636
        COPY_NAME(sbPtr->SBname,block->header.SBname);
 
 
14637
 
 
 
14638
        //create using a fake tools data
 
 
14639
        memset(&tdm,0,sizeof(TOOLS_DATA_MARINE));
 
 
14640
 
 
 
14641
        tdm.position = block->dynamics.Position;
 
 
14642
        COPY_NAME(tdm.nameID,block->header.SBname);
 
 
14643
        tdm. marine_type = block->weapon_id;
 
 
14644
 
 
 
14645
         EnableBehaviourType(sbPtr, &tdm );
 
 
14646
     }
 
 
14647
 
 
 
14648
    MARINE_STATUS_BLOCK* marineStatusPointer = (MARINE_STATUS_BLOCK*) sbPtr->dataptr;
 
 
14649
 
 
 
14650
    //start copying stuff
 
 
14651
 
 
 
14652
     COPYELEMENT_LOAD(volleySize)
 
 
14653
     COPYELEMENT_LOAD(behaviourState)
 
 
14654
     COPYELEMENT_LOAD(lastState)
 
 
14655
    COPYELEMENT_LOAD(Mission)
 
 
14656
    COPYELEMENT_LOAD(my_spot)
 
 
14657
    COPYELEMENT_LOAD(my_facing_point)
 
 
14658
    COPYELEMENT_LOAD(nearSpeed)
 
 
14659
    COPYELEMENT_LOAD(acceleration)
 
 
14660
    COPYELEMENT_LOAD(speedConstant)
 
 
14661
    COPYELEMENT_LOAD(accelerationConstant)
 
 
14662
    COPYELEMENT_LOAD(suspect_point)
 
 
14663
    COPYELEMENT_LOAD(suspicious)
 
 
14664
    COPYELEMENT_LOAD(previous_suspicion)
 
 
14665
    COPYELEMENT_LOAD(using_squad_suspicion)
 
 
14666
    COPYELEMENT_LOAD(gotapoint)
 
 
14667
    COPYELEMENT_LOAD(lastframe_fallingspeed)
 
 
14668
    COPYELEMENT_LOAD(path)
 
 
14669
    COPYELEMENT_LOAD(stepnumber)
 
 
14670
    COPYELEMENT_LOAD(stateTimer)
 
 
14671
    COPYELEMENT_LOAD(internalState)
 
 
14672
    COPYELEMENT_LOAD(weaponTarget)        /* position for firing weapon at */
 
 
14673
    COPYELEMENT_LOAD(obstruction)
 
 
14674
    COPYELEMENT_LOAD(wanderData)
 
 
14675
    COPYELEMENT_LOAD(IAmCrouched)
 
 
14676
    COPYELEMENT_LOAD(lastroundhit)
 
 
14677
    COPYELEMENT_LOAD(GibbFactor)
 
 
14678
    COPYELEMENT_LOAD(Wounds)
 
 
14679
 
 
 
14680
    COPYELEMENT_LOAD(incidentFlag)
 
 
14681
    COPYELEMENT_LOAD(incidentTimer)
 
 
14682
 
 
 
14683
    COPYELEMENT_LOAD(weapon_variable)
 
 
14684
    COPYELEMENT_LOAD(weapon_variable2)
 
 
14685
    COPYELEMENT_LOAD(clipammo)
 
 
14686
    COPYELEMENT_LOAD(roundsForThisTarget)
 
 
14687
 
 
 
14688
    COPYELEMENT_LOAD(Female)
 
 
14689
    COPYELEMENT_LOAD(Android)
 
 
14690
    COPYELEMENT_LOAD(Skill)
 
 
14691
    COPYELEMENT_LOAD(Courage)
 
 
14692
    COPYELEMENT_LOAD(Voice)
 
 
14693
    COPYELEMENT_LOAD(VoicePitch)
 
 
14694
 
 
 
14695
    COPYELEMENT_LOAD(FiringAnim)
 
 
14696
    COPYELEMENT_LOAD(Expression)
 
 
14697
    COPYELEMENT_LOAD(Target_Expression)
 
 
14698
    COPYELEMENT_LOAD(Blink)
 
 
14699
    COPYELEMENT_LOAD(SpotFlag)
 
 
14700
    COPYELEMENT_LOAD(FlareActive)
 
 
14701
 
 
 
14702
    //load ai module pointers
 
 
14703
    marineStatusPointer->lastmodule = GetPointerFromAIModuleIndex(block->lastmodule_index);
 
 
14704
    marineStatusPointer->destinationmodule = GetPointerFromAIModuleIndex(block->destinationmodule_index);
 
 
14705
    marineStatusPointer->missionmodule = GetPointerFromAIModuleIndex(block->missionmodule_index);
 
 
14706
    marineStatusPointer->fearmodule = GetPointerFromAIModuleIndex(block->fearmodule_index);
 
 
14707
 
 
 
14708
    //load target
 
 
14709
    COPY_NAME(marineStatusPointer->Target_SBname,block->Target_SBname);
 
 
14710
    marineStatusPointer->Target = FindSBWithName(marineStatusPointer->Target_SBname);
 
 
14711
 
 
 
14712
    //find the marine's generator
 
 
14713
    marineStatusPointer->generator_sbptr = FindSBWithName(block->Generator_SBname);
 
 
14714
    marineStatusPointer->My_Weapon = &NPC_Marine_Weapons[block->weapon_id];
 
 
14715
 
 
 
14716
    //copy strategy block stuff
 
 
14717
    *sbPtr->DynPtr = block->dynamics;
 
 
14718
    sbPtr->DamageBlock = block->DamageBlock;
 
 
14719
 
 
 
14720
    //load hierarchy
 
 
14721
    {
 
 
14722
        SAVE_BLOCK_HEADER* hier_header = GetNextBlockIfOfType(SaveBlock_Hierarchy);
 
 
14723
 
 
 
14724
        if(hier_header)
 
 
14725
            LoadHierarchy(hier_header,&marineStatusPointer->HModelController);
 
 
14726
    }
 
 
14727
 
 
 
14728
    if(marineStatusPointer->My_Weapon->GunflashName)
 
 
14729
    marineStatusPointer->My_Gunflash_Section = GetThisSectionData(marineStatusPointer->HModelController.section_data,
marineStatusPointer->My_Weapon->GunflashName);
 
 
14730
 
 
 
14731
    if(marineStatusPointer->My_Weapon->ElevationSection)
 
 
14732
    marineStatusPointer->My_Elevation_Section = GetThisSectionData(marineStatusPointer->HModelController.section_data,
marineStatusPointer->My_Weapon->ElevationSection);
 
 
14733
 
 
 
14734
    Load_SoundState(&marineStatusPointer->soundHandle);
 
 
14735
    Load_SoundState(&marineStatusPointer->soundHandle2);
 
 
14736
}
 
 
14737
 
 
 
14738
void SaveStrategy_Marine(STRATEGYBLOCK* sbPtr)
 
 
14739
{
 
 
14740
    MARINE_SAVE_BLOCK *block;
 
 
14741
    MARINE_STATUS_BLOCK* marineStatusPointer;
 
 
14742
 
 
 
14743
    GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
 
 
14744
    marineStatusPointer = (MARINE_STATUS_BLOCK*) sbPtr->dataptr;
 
 
14745
 
 
 
14746
    //start copying stuff
 
 
14747
 
 
 
14748
     COPYELEMENT_SAVE(volleySize)
 
 
14749
     COPYELEMENT_SAVE(behaviourState)
 
 
14750
     COPYELEMENT_SAVE(lastState)
 
 
14751
    COPYELEMENT_SAVE(Mission)
 
 
14752
    COPYELEMENT_SAVE(my_spot)
 
 
14753
    COPYELEMENT_SAVE(my_facing_point)
 
 
14754
    COPYELEMENT_SAVE(nearSpeed)
 
 
14755
    COPYELEMENT_SAVE(acceleration)
 
 
14756
    COPYELEMENT_SAVE(speedConstant)
 
 
14757
    COPYELEMENT_SAVE(accelerationConstant)
 
 
14758
    COPYELEMENT_SAVE(suspect_point)
 
 
14759
    COPYELEMENT_SAVE(suspicious)
 
 
14760
    COPYELEMENT_SAVE(previous_suspicion)
 
 
14761
    COPYELEMENT_SAVE(using_squad_suspicion)
 
 
14762
    COPYELEMENT_SAVE(gotapoint)
 
 
14763
    COPYELEMENT_SAVE(lastframe_fallingspeed)
 
 
14764
    COPYELEMENT_SAVE(path)
 
 
14765
    COPYELEMENT_SAVE(stepnumber)
 
 
14766
    COPYELEMENT_SAVE(stateTimer)
 
 
14767
    COPYELEMENT_SAVE(internalState)
 
 
14768
    COPYELEMENT_SAVE(weaponTarget)        /* position for firing weapon at */
 
 
14769
    COPYELEMENT_SAVE(obstruction)
 
 
14770
    COPYELEMENT_SAVE(wanderData)
 
 
14771
    COPYELEMENT_SAVE(IAmCrouched)
 
 
14772
    COPYELEMENT_SAVE(lastroundhit)
 
 
14773
    COPYELEMENT_SAVE(GibbFactor)
 
 
14774
    COPYELEMENT_SAVE(Wounds)
 
 
14775
 
 
 
14776
    COPYELEMENT_SAVE(incidentFlag)
 
 
14777
    COPYELEMENT_SAVE(incidentTimer)
 
 
14778
 
 
 
14779
    COPYELEMENT_SAVE(weapon_variable)
 
 
14780
    COPYELEMENT_SAVE(weapon_variable2)
 
 
14781
    COPYELEMENT_SAVE(clipammo)
 
 
14782
    COPYELEMENT_SAVE(roundsForThisTarget)
 
 
14783
 
 
 
14784
    COPYELEMENT_SAVE(Female)
 
 
14785
    COPYELEMENT_SAVE(Android)
 
 
14786
    COPYELEMENT_SAVE(Skill)
 
 
14787
    COPYELEMENT_SAVE(Courage)
 
 
14788
    COPYELEMENT_SAVE(Voice)
 
 
14789
    COPYELEMENT_SAVE(VoicePitch)
 
 
14790
 
 
 
14791
    COPYELEMENT_SAVE(FiringAnim)
 
 
14792
    COPYELEMENT_SAVE(Expression)
 
 
14793
    COPYELEMENT_SAVE(Target_Expression)
 
 
14794
    COPYELEMENT_SAVE(Blink)
 
 
14795
    COPYELEMENT_SAVE(SpotFlag)
 
 
14796
    COPYELEMENT_SAVE(FlareActive)
 
 
14797
 
 
 
14798
    //save ai module pointers
 
 
14799
    block->lastmodule_index = GetIndexFromAIModulePointer(marineStatusPointer->lastmodule);
 
 
14800
    block->destinationmodule_index = GetIndexFromAIModulePointer(marineStatusPointer->destinationmodule);
 
 
14801
    block->missionmodule_index = GetIndexFromAIModulePointer(marineStatusPointer->missionmodule);
 
 
14802
    block->fearmodule_index = GetIndexFromAIModulePointer(marineStatusPointer->fearmodule);
 
 
14803
 
 
 
14804
    //save target
 
 
14805
    COPY_NAME(block->Target_SBname,marineStatusPointer->Target_SBname);
 
 
14806
 
 
 
14807
    //save the marine's generator name
 
 
14808
    if(marineStatusPointer->generator_sbptr)
 
 
14809
        COPY_NAME(block->Generator_SBname,marineStatusPointer->generator_sbptr->SBname)
 
 
14810
    else
 
 
14811
        COPY_NAME(block->Generator_SBname,Null_Name)
 
 
14812
 
 
 
14813
    block->weapon_id = marineStatusPointer->My_Weapon->id;
 
 
14814
 
 
 
14815
    //copy strategy block stuff
 
 
14816
    block->dynamics = *sbPtr->DynPtr;
 
 
14817
    block->dynamics.CollisionReportPtr = 0;
 
 
14818
    block->DamageBlock = sbPtr->DamageBlock;
 
 
14819
 
 
 
14820
    //save the hierarchy
 
 
14821
    SaveHierarchy(&marineStatusPointer->HModelController);
 
 
14822
 
 
 
14823
    Save_SoundState(&marineStatusPointer->soundHandle);
 
 
14824
    Save_SoundState(&marineStatusPointer->soundHandle2);
 
 
14825
}
 
 
14826
 
 
 
14827
/*----------------------------**
 
 
14828
** And now the squad state... **
 
 
14829
**----------------------------*/
 
 
14830
 
 
 
14831
typedef struct marine_squad_save_block
 
 
14832
{
 
 
14833
    SAVE_BLOCK_HEADER header;
 
 
14834
 
 
 
14835
    int alertStatus;
 
 
14836
    int responseLevel;
 
 
14837
    int alertPriority;
 
 
14838
    int Squad_Suspicion;
 
 
14839
    VECTORCH squad_suspect_point;
 
 
14840
 
 
 
14841
    /* Now some stats. */
 
 
14842
    int RespondingMarines;
 
 
14843
    int Alt_RespondingMarines;
 
 
14844
    int NearUnpanickedMarines;
 
 
14845
    int Alt_NearUnpanickedMarines;
 
 
14846
    int NearPanickedMarines;
 
 
14847
    int Alt_NearPanickedMarines;
 
 
14848
    int NearBurningMarines;
 
 
14849
    int Alt_NearBurningMarines;
 
 
14850
    int Squad_Delta_Morale;
 
 
14851
    int Nextframe_Squad_Delta_Morale;
 
 
14852
    int alertZone_index;
 
 
14853
 
 
 
14854
} MARINE_SQUAD_SAVE_BLOCK;
 
 
14855
 
 
 
14856
#undef SAVELOAD_BEHAV
 
 
14857
//defines for load/save macros
 
 
14858
#define SAVELOAD_BEHAV (&NpcSquad)
 
 
14859
 
 
 
14860
void LoadMarineSquadState(SAVE_BLOCK_HEADER* header)
 
 
14861
{
 
 
14862
    MARINE_SQUAD_SAVE_BLOCK *block = (MARINE_SQUAD_SAVE_BLOCK*) header;
 
 
14863
 
 
 
14864
    //check the size of the save block
 
 
14865
    if(header->size != sizeof(*block))
 
 
14866
        return;
 
 
14867
 
 
 
14868
    COPYELEMENT_LOAD(alertStatus)
 
 
14869
    COPYELEMENT_LOAD(responseLevel)
 
 
14870
    COPYELEMENT_LOAD(alertPriority)
 
 
14871
    COPYELEMENT_LOAD(Squad_Suspicion)
 
 
14872
    COPYELEMENT_LOAD(squad_suspect_point)
 
 
14873
    COPYELEMENT_LOAD(RespondingMarines)
 
 
14874
    COPYELEMENT_LOAD(Alt_RespondingMarines)
 
 
14875
    COPYELEMENT_LOAD(NearUnpanickedMarines)
 
 
14876
    COPYELEMENT_LOAD(Alt_NearUnpanickedMarines)
 
 
14877
    COPYELEMENT_LOAD(NearPanickedMarines)
 
 
14878
    COPYELEMENT_LOAD(Alt_NearPanickedMarines)
 
 
14879
    COPYELEMENT_LOAD(NearBurningMarines)
 
 
14880
    COPYELEMENT_LOAD(Alt_NearBurningMarines)
 
 
14881
    COPYELEMENT_LOAD(Squad_Delta_Morale)
 
 
14882
    COPYELEMENT_LOAD(Nextframe_Squad_Delta_Morale)
 
 
14883
 
 
 
14884
    //and an aimodule
 
 
14885
    NpcSquad.alertZone = GetPointerFromAIModuleIndex(block->alertZone_index);
 
 
14886
}
 
 
14887
 
 
 
14888
void SaveMarineSquadState()
 
 
14889
{
 
 
14890
    MARINE_SQUAD_SAVE_BLOCK * block;
 
 
14891
 
 
 
14892
    GET_SAVE_BLOCK_POINTER(block);
 
 
14893
 
 
 
14894
    //fill in the header
 
 
14895
    block->header.type = SaveBlock_MarineSquad;
 
 
14896
    block->header.size = sizeof(*block);
 
 
14897
 
 
 
14898
    COPYELEMENT_SAVE(alertStatus)
 
 
14899
    COPYELEMENT_SAVE(responseLevel)
 
 
14900
    COPYELEMENT_SAVE(alertPriority)
 
 
14901
    COPYELEMENT_SAVE(Squad_Suspicion)
 
 
14902
    COPYELEMENT_SAVE(squad_suspect_point)
 
 
14903
    COPYELEMENT_SAVE(RespondingMarines)
 
 
14904
    COPYELEMENT_SAVE(Alt_RespondingMarines)
 
 
14905
    COPYELEMENT_SAVE(NearUnpanickedMarines)
 
 
14906
    COPYELEMENT_SAVE(Alt_NearUnpanickedMarines)
 
 
14907
    COPYELEMENT_SAVE(NearPanickedMarines)
 
 
14908
    COPYELEMENT_SAVE(Alt_NearPanickedMarines)
 
 
14909
    COPYELEMENT_SAVE(NearBurningMarines)
 
 
14910
    COPYELEMENT_SAVE(Alt_NearBurningMarines)
 
 
14911
    COPYELEMENT_SAVE(Squad_Delta_Morale)
 
 
14912
    COPYELEMENT_SAVE(Nextframe_Squad_Delta_Morale)
 
 
14913
 
 
 
14914
    //and an aimodule
 
 
14915
    block->alertZone_index = GetIndexFromAIModulePointer(NpcSquad.alertZone);
 
 
14916
}