4b825dc642cb6eb9a060e54bf8d69288fbee490494a6641b73026d662261604d7d192beae70b11dc
 
 
1
/*------------------------Patrick 6/11/96-----------------------------
 
 
2
  Source file for alien AI behaviour functions....
 
 
3
  --------------------------------------------------------------------*/
 
 
4
#include "system.h"
 
 
5
#include "prototyp.h"
 
 
6
#include "stratdef.h"
 
 
7
#include "bh_types.h"
 
 
8
#include "bh_far.h"
 
 
9
#include "generator.h"
 
 
10
#include "npc_alien.h"
 
 
11
#include "npc_marine.h"
 
 
12
#include "weapons.h"
 
 
13
#include "pheromon.h"
 
 
14
#include "psndplat.h"
 
 
15
#include "extents.h"
 
 
16
#include "pldghost.h"
 
 
17
#include "bh_types.h"
 
 
18
#include "corpse.h"
 
 
19
#include "npc_dummy.h"
 
 
20
#include "scream.h"
 
 
21
#include "userprofile.h"
 
 
22
#include "pfarlocs.h"
 
 
23
#include "targeting.h"
 
 
24
#include "los.h"
 
 
25
#include "bh_light.h"
 
 
26
#include <assert.h>
 
 
27
#include <stdio.h>
 
 
28
 
 
 
29
#define ALIEN_CURVETOPLAYERDIST 8000
 
 
30
 
 
 
31
extern uint8_t Null_Name[8];
 
 
32
 
 
 
33
extern int NearAliens;
 
 
34
extern int FarAliens;
 
 
35
extern int ShowHiveState;
 
 
36
 
 
 
37
const SECTION * GetNamedHierarchyFromLibrary(const char * rif_name, const char *);
 
 
38
extern int LightIntensityAtPoint(VECTORCH *pointPtr);
 
 
39
AIMODULE *FarNPC_GetTargetAIModuleForRetreat(STRATEGYBLOCK *sbPtr);
 
 
40
extern void EnableBehaviourType(STRATEGYBLOCK* sbptr, void *bhdata);
 
 
41
 
 
 
42
extern ATTACK_DATA Alien_Special_Gripping_Attack;
 
 
43
 
 
 
44
static int GetAlienSpeedFactor_ForSequence(STRATEGYBLOCK *sbPtr, HMODEL_SEQUENCE_TYPES sequence_type, int subsequence)
 
 
45
{
 
 
46
    ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);        
 
 
47
 
 
 
48
    int factortype = -1;
 
 
49
 
 
 
50
    switch (sequence_type)
 
 
51
    {
 
 
52
        case HMSQT_AlienRun:
 
 
53
            switch ((ALIENRUN_SUBSEQUENCES)subsequence)
 
 
54
            {
 
 
55
                case ARSS_Standard:
 
 
56
                case ARSS_Attack_Swipe:
 
 
57
                    factortype = 2;
 
 
58
                break;
 
 
59
                case ARSS_Jump:
 
 
60
                    factortype = 1;
 
 
61
                break;
 
 
62
                case ARSS_Dies:
 
 
63
                    factortype = 0;
 
 
64
                break;
 
 
65
                default:
 
 
66
                    assert(0);
 
 
67
            }
 
 
68
        break;
 
 
69
        case HMSQT_AlienCrawl:
 
 
70
            switch ((ALIENCRAWL_SUBSEQUENCES)subsequence)
 
 
71
            {
 
 
72
                case ACSS_Standard:
 
 
73
                case ACSS_Crawl_Hurt:
 
 
74
                case ACSS_Scamper:
 
 
75
                    factortype = 2;
 
 
76
                break;
 
 
77
                case ACSS_Attack_Bite:
 
 
78
                case ACSS_Attack_Tail:
 
 
79
                    factortype = 1;
 
 
80
                break;
 
 
81
                case ACSS_Dies:
 
 
82
                case ACSS_Pain_Fall_Fwd:
 
 
83
                case ACSS_Pain_Fall_Back:
 
 
84
                case ACSS_Pain_Fall_Left:
 
 
85
                case ACSS_Pain_Fall_Right:
 
 
86
                case ACSS_Boom_Fall_Fwd:
 
 
87
                case ACSS_Boom_Fall_Back:
 
 
88
                case ACSS_Boom_Fall_Left:
 
 
89
                case ACSS_Boom_Fall_Right:
 
 
90
                    factortype = 0;
 
 
91
                break;
 
 
92
                default:
 
 
93
                    assert(0);
 
 
94
            }
 
 
95
        break;
 
 
96
        case HMSQT_AlienStand:
 
 
97
            switch ((ALIENSTAND_SUBSEQUENCES)subsequence)
 
 
98
            {
 
 
99
                case ASSS_Taunt:
 
 
100
                case ASSS_Taunt2:
 
 
101
                case ASSS_Taunt3:
 
 
102
                case ASSS_Fear:
 
 
103
                case ASSS_Standard:
 
 
104
                case ASSS_FidgetA:
 
 
105
                case ASSS_FidgetB:
 
 
106
                case ASSS_Attack_Right_Swipe_In:
 
 
107
                case ASSS_Attack_Left_Swipe_In:
 
 
108
                case ASSS_Attack_Both_In:
 
 
109
                case ASSS_Attack_Both_Down:
 
 
110
                case ASSS_Attack_Bite:
 
 
111
                case ASSS_Attack_Tail:
 
 
112
                case ASSS_Attack_Low_Left_Swipe:
 
 
113
                case ASSS_Attack_Low_Right_Swipe:
 
 
114
                case ASSS_Feed:
 
 
115
                case ASSS_Unfurl:
 
 
116
                case ASSS_Dormant:
 
 
117
                    factortype = 1;
 
 
118
                break;
 
 
119
                case ASSS_Dies:
 
 
120
                case ASSS_Pain_Fall_Fwd:
 
 
121
                case ASSS_Pain_Fall_Back:
 
 
122
                case ASSS_Pain_Fall_Left:
 
 
123
                case ASSS_Pain_Fall_Right:
 
 
124
                case ASSS_Boom_Fall_Fwd:
 
 
125
                case ASSS_Boom_Fall_Back:
 
 
126
                case ASSS_Boom_Fall_Left:
 
 
127
                case ASSS_Boom_Fall_Right:
 
 
128
                case ASSS_Spin_Clockwise:
 
 
129
                case ASSS_Spin_Anticlockwise:
 
 
130
                case ASSS_BurningDeath:
 
 
131
                    factortype = 0;
 
 
132
                break;
 
 
133
                default:
 
 
134
                    assert(0);
 
 
135
            }
 
 
136
        break;
 
 
137
        case HMSQT_AlienCrouch:
 
 
138
            switch ((ALIENCROUCH_SUBSEQUENCES)subsequence)
 
 
139
            {
 
 
140
                case ACrSS_Standard:
 
 
141
                    factortype = 2;
 
 
142
                break;
 
 
143
                case ACrSS_Attack_Bite:
 
 
144
                case ACrSS_Attack_Tail:
 
 
145
                case ACrSS_Attack_Swipe:
 
 
146
                case ACrSS_Pounce:
 
 
147
                case ACrSS_Taunt:
 
 
148
                    factortype = 1;
 
 
149
                break;
 
 
150
                case ACrSS_Dies:
 
 
151
                case ACrSS_Dies_Thrash:
 
 
152
                    factortype = 0;
 
 
153
                break;
 
 
154
                default:
 
 
155
                    assert(0);
 
 
156
            }
 
 
157
        break;
 
 
158
        case HMSQT_Hugger:
 
 
159
        default:
 
 
160
            /* Nooooo! */
 
 
161
            assert(0);
 
 
162
            break;
 
 
163
    }
 
 
164
 
 
 
165
    assert(factortype != -1);
 
 
166
 
 
 
167
    switch(factortype)
 
 
168
    {
 
 
169
        case 0:
 
 
170
            return ONE_FIXED;
 
 
171
        break;
 
 
172
        case 1:
 
 
173
        {
 
 
174
            /* Affected by alien type. */
 
 
175
 
 
 
176
            switch (alienStatusPointer->Type)
 
 
177
            {
 
 
178
                case Standard:
 
 
179
                    return ONE_FIXED;
 
 
180
                case Predalien:
 
 
181
                    return PREDALIEN_SPEED_FACTOR;
 
 
182
                case Praetorian:
 
 
183
                    return PRAETORIAN_SPEED_FACTOR;
 
 
184
                default:
 
 
185
                    assert(0);
 
 
186
                    break;
 
 
187
            }
 
 
188
        }
 
 
189
        break;
 
 
190
        case 2:
 
 
191
        {
 
 
192
            /* More complex.  Affected by alien type and health. */
 
 
193
            const NPC_DATA *NpcData;
 
 
194
            int prefactor;
 
 
195
 
 
 
196
            switch (alienStatusPointer->Type)
 
 
197
            {
 
 
198
                case Standard:
 
 
199
                default:
 
 
200
                    NpcData = &NpcDataList[I_NPC_Alien];
 
 
201
                    prefactor = ONE_FIXED;
 
 
202
                break;
 
 
203
                case Predalien:
 
 
204
                    NpcData = &NpcDataList[I_NPC_PredatorAlien];
 
 
205
                    prefactor = PREDALIEN_SPEED_FACTOR;
 
 
206
                break;
 
 
207
                case Praetorian:    
 
 
208
                    NpcData = &NpcDataList[I_NPC_PraetorianGuard];
 
 
209
                    prefactor = PRAETORIAN_SPEED_FACTOR;
 
 
210
            }
 
 
211
 
 
 
212
            int factor = sbPtr->DamageBlock.Health / NpcData->StartingStats.Health;
 
 
213
            /* ONE_FIXED shift already included. */
 
 
214
            assert(factor <= ONE_FIXED);
 
 
215
 
 
 
216
            factor += ONE_FIXED;
 
 
217
            factor >>= 1;
 
 
218
 
 
 
219
            /* Wounding effects. */
 
 
220
            if (alienStatusPointer->Wounds & (section_flag_left_leg | section_flag_right_leg))
 
 
221
            {
 
 
222
                /* Missing a leg. */
 
 
223
                factor -= (ONE_FIXED/3);
 
 
224
            }
 
 
225
            else if ((alienStatusPointer->Wounds & section_flag_left_foot) && (alienStatusPointer->Wounds & section_flag_right_foot))
 
 
226
            {
 
 
227
                /* Missing both feet. */
 
 
228
                factor -= (ONE_FIXED>>2);
 
 
229
            }
 
 
230
            else if ((alienStatusPointer->Wounds & section_flag_left_foot) || (alienStatusPointer->Wounds & section_flag_right_foot))
 
 
231
            {
 
 
232
                /* Missing one foot. */
 
 
233
                factor -= (ONE_FIXED>>3);
 
 
234
            }
 
 
235
 
 
 
236
            if (factor < (ONE_FIXED >> 3))
 
 
237
                factor = (ONE_FIXED >> 3);
 
 
238
 
 
 
239
            if (prefactor != ONE_FIXED)
 
 
240
                factor = MUL_FIXED(prefactor,factor);
 
 
241
 
 
 
242
            return factor;
 
 
243
        }
 
 
244
        break;
 
 
245
        default:
 
 
246
            assert(0);
 
 
247
    }
 
 
248
 
 
 
249
return 0;
 
 
250
}
 
 
251
 
 
 
252
static void RecomputeAlienSpeed(STRATEGYBLOCK *sbPtr)
 
 
253
{
 
 
254
    int basespeed;
 
 
255
 
 
 
256
    ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);        
 
 
257
 
 
 
258
    /* Change max speed. */
 
 
259
    int factor = GetAlienSpeedFactor_ForSequence(sbPtr, HMSQT_AlienRun, (int)ARSS_Standard);
 
 
260
 
 
 
261
    switch (alienStatusPointer->Type)
 
 
262
    {
 
 
263
        case Standard:
 
 
264
        default:
 
 
265
            basespeed = ALIEN_FORWARDVELOCITY;
 
 
266
        break;
 
 
267
        case Predalien:
 
 
268
            basespeed = MUL_FIXED(ALIEN_FORWARDVELOCITY, PREDALIEN_SPEED_FACTOR);
 
 
269
        break;
 
 
270
        case Praetorian:
 
 
271
            if (alienStatusPointer->IAmCrouched)
 
 
272
                basespeed = MUL_FIXED(ALIEN_FORWARDVELOCITY, MUL_FIXED(PRAETORIAN_CRAWLSPEED_FACTOR, PRAETORIAN_SPEED_FACTOR));
 
 
273
            else
 
 
274
                basespeed = MUL_FIXED(ALIEN_FORWARDVELOCITY, MUL_FIXED(PRAETORIAN_WALKSPEED_FACTOR, PRAETORIAN_SPEED_FACTOR));
 
 
275
    }
 
 
276
 
 
 
277
    alienStatusPointer->MaxSpeed = MUL_FIXED(factor, basespeed);
 
 
278
}
 
 
279
 
 
 
280
/* Patrick 27/6/97 *********************************
 
 
281
Some support functions for the alien:
 
 
282
Hopefully, these are fairly obvious...
 
 
283
****************************************************/
 
 
284
static void SetAlienShapeAnimSequence_Core(STRATEGYBLOCK *sbPtr, int type, int subtype, int length, int tweeningtime)
 
 
285
{
 
 
286
    ALIEN_STATUS_BLOCK *alienStatus = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
287
    assert(length != 0);
 
 
288
 
 
 
289
    if ((alienStatus->HModelController.Sequence_Type == type) && (subtype == alienStatus->HModelController.Sub_Sequence))
 
 
290
            return;
 
 
291
 
 
 
292
    alienStatus->last_anim_length = length;
 
 
293
printf("sec %d sub %d\n", alienStatus->HModelController.Sequence_Type, alienStatus->HModelController.Sub_Sequence);
 
 
294
puts("CHANGING SEC"); //jadda
 
 
295
 
 
 
296
    if (alienStatus->last_anim_length == -1)
 
 
297
        alienStatus->last_anim_length = ONE_FIXED; /* Stops divisions by zero. */
 
 
298
 
 
 
299
    /* Consider wounding. */
 
 
300
    {
 
 
301
        int factor = GetAlienSpeedFactor_ForSequence(sbPtr, type, subtype);
 
 
302
 
 
 
303
        if (factor != ONE_FIXED)
 
 
304
            length = DIV_FIXED(length, factor);
 
 
305
    }
 
 
306
 
 
 
307
    if (tweeningtime <= 0)
 
 
308
        InitHModelSequence(&alienStatus->HModelController, (int)type, subtype, length);
 
 
309
    else
 
 
310
        InitHModelTweening(&alienStatus->HModelController, tweeningtime, (int)type, subtype, length, 1);
 
 
311
 
 
 
312
    if(NetworkPeer == AvP.PlayMode)
 
 
313
        AddNetMsg_AlienAISeqChange(sbPtr, type, subtype, length, tweeningtime);
 
 
314
 
 
 
315
    alienStatus->HModelController.Playing = 1;
 
 
316
    RecomputeAlienSpeed(sbPtr);
 
 
317
}
 
 
318
 
 
 
319
static int AlienShouldBeCrawling(STRATEGYBLOCK *sbPtr)
 
 
320
{
 
 
321
    ALIEN_STATUS_BLOCK *alienStatus = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
322
 
 
 
323
    if(sbPtr->containingModule->m_flags & MODULEFLAG_AIRDUCT)
 
 
324
        return 1;
 
 
325
 
 
 
326
    /* Stand if you've lost both arm sections. */
 
 
327
    if ((alienStatus->Wounds & section_flag_left_arm) && (alienStatus->Wounds & section_flag_right_arm))
 
 
328
        return 0; /* This just looks silly. */
 
 
329
 
 
 
330
    if(sbPtr->DynPtr->OrientMat.mat22 < 63000)
 
 
331
        return 1;
 
 
332
 
 
 
333
    if (AlienIsEncouragedToCrawl() && alienStatus->EnableWaypoints)
 
 
334
        return 1;
 
 
335
 
 
 
336
    if (alienStatus->incidentFlag)
 
 
337
    {
 
 
338
        switch(alienStatus->Type)
 
 
339
        {
 
 
340
            case Standard:
 
 
341
            default:
 
 
342
                alienStatus->PreferToCrouch = (FastRandom() % 65535) > 36384; 
 
 
343
            break;
 
 
344
            case Predalien:
 
 
345
                alienStatus->PreferToCrouch = 0;
 
 
346
            break;
 
 
347
            case Praetorian:
 
 
348
                if ((FastRandom() % 65535) < 16384)
 
 
349
                    alienStatus->PreferToCrouch = ~alienStatus->PreferToCrouch;
 
 
350
        }
 
 
351
    }
 
 
352
 
 
 
353
return alienStatus->PreferToCrouch;
 
 
354
}
 
 
355
 
 
 
356
static void AlienHandleMovingAnimation(STRATEGYBLOCK *sbPtr) 
 
 
357
{
 
 
358
    ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
359
 
 
 
360
    if(alienStatusPointer->CanStand)
 
 
361
    {
 
 
362
        /* Make sure we're playing a 'moving' sequence, if we're actually moving. */
 
 
363
 
 
 
364
        VECTORCH offset;
 
 
365
        offset.vx = sbPtr->DynPtr->Position.vx - sbPtr->DynPtr->PrevPosition.vx;
 
 
366
        offset.vy = sbPtr->DynPtr->Position.vy - sbPtr->DynPtr->PrevPosition.vy;
 
 
367
        offset.vz = sbPtr->DynPtr->Position.vz - sbPtr->DynPtr->PrevPosition.vz;
 
 
368
 
 
 
369
        alienStatusPointer->IAmCrouched = AlienShouldBeCrawling(sbPtr);
 
 
370
 
 
 
371
        /* ...compute speed factor... */
 
 
372
        int speed = Magnitude(&offset);
 
 
373
 
 
 
374
        if (speed < (MUL_FIXED(NormalFrameTime, 100)))
 
 
375
        {
 
 
376
            /* Not moving much, are we? */
 
 
377
            /* Make sure we're playing a 'standing still' sequence. */
 
 
378
 
 
 
379
            if (alienStatusPointer->IAmCrouched)
 
 
380
                SetAlienShapeAnimSequence_Core(sbPtr, HMSQT_AlienCrouch, ACrSS_Standard, -1, (ONE_FIXED >> 3));
 
 
381
            else 
 
 
382
                SetAlienShapeAnimSequence_Core(sbPtr, HMSQT_AlienStand, ASSS_Standard, -1, (ONE_FIXED >> 3));
 
 
383
        }
 
 
384
        else
 
 
385
        {
 
 
386
            speed = DIV_FIXED(speed, NormalFrameTime);
 
 
387
            /* Right, now play the correct sort of sequence. */    
 
 
388
 
 
 
389
            if(alienStatusPointer->IAmCrouched)
 
 
390
            {
 
 
391
                if( ((Standard == alienStatusPointer->Type) && (sbPtr->DynPtr->OrientMat.mat22 < 63000)) || (Predalien ==
alienStatusPointer->Type))
 
 
392
                {
 
 
393
                    SetAlienShapeAnimSequence_Core(sbPtr, HMSQT_AlienCrawl, ACSS_Standard, ONE_FIXED >> 2, (ONE_FIXED >> 2));
 
 
394
                }
 
 
395
                else
 
 
396
                {
 
 
397
                    SetAlienShapeAnimSequence_Core(sbPtr, HMSQT_AlienCrawl, ACSS_Scamper, ONE_FIXED >> 2, (ONE_FIXED >> 2));
 
 
398
                }
 
 
399
            }
 
 
400
            else
 
 
401
            {
 
 
402
                SetAlienShapeAnimSequence_Core(sbPtr, HMSQT_AlienRun, ARSS_Standard, ONE_FIXED >> 1, (ONE_FIXED >> 2));
 
 
403
            }
 
 
404
        }
 
 
405
    }
 
 
406
    else
 
 
407
    {
 
 
408
        alienStatusPointer->IAmCrouched = 1;
 
 
409
        SetAlienShapeAnimSequence_Core(sbPtr, HMSQT_AlienCrawl, ACSS_Crawl_Hurt, ONE_FIXED >> 1, (ONE_FIXED >> 2));
 
 
410
    }
 
 
411
}
 
 
412
 
 
 
413
static int Alien_Special_Pounce_Condition(STRATEGYBLOCK *sbPtr) 
 
 
414
{
 
 
415
    ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
416
 
 
 
417
    if (sbPtr->containingModule->m_aimodule->m_waypoints == NULL)
 
 
418
    {
 
 
419
        /* If in an unwaypointed module... */
 
 
420
        DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
421
 
 
 
422
        if ((alienStatusPointer->Target->DynPtr->Position.vy - dynPtr->Position.vy) < -2000)
 
 
423
            return 1; // And the target is directly above us...
 
 
424
    }
 
 
425
 
 
 
426
return 0;
 
 
427
}
 
 
428
 
 
 
429
static void StartAlienAttackSequence(STRATEGYBLOCK *sbPtr) 
 
 
430
{
 
 
431
    ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
432
 
 
 
433
/*
 
 
434
    DYNAMICSBLOCK *objectDynPtr = sbPtr->DynPtr;
 
 
435
    ATTACK_DATA *thisAttack;
 
 
436
    //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>3), (int)HMSQT_AlienCrouch, (int)ACrSS_Attack_Swipe, -1, 1);
 
 
437
    //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>3), (int)HMSQT_AlienCrouch, (int)ACrSS_Pounce, -1, 1);
 
 
438
    //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>3), (int)HMSQT_AlienStand, (int)ASSS_Attack_Bite, -1, 1);
 
 
439
    //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>3), (int)HMSQT_AlienStand, (int)ASSS_Attack_Left_Swipe_In, -1, 1);
 
 
440
    //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>3), (int)HMSQT_AlienStand, (int)ASSS_Attack_Right_Swipe_In, -1, 1);
 
 
441
 
 
 
442
 
 
 
443
    //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>3), (int)HMSQT_AlienStand, (int)ASSS_Attack_Tail, -1, 1); // not
predalien
 
 
444
    //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>3), (int)HMSQT_AlienStand, (int)ASSS_Attack_Both_Down, -1, 1); // not
pratorian
 
 
445
 
 
 
446
    //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>3), (int)HMSQT_AlienCrouch, (int)ACrSS_Attack_Bite, -1, 1); // only
standard alien and pratorian bad
 
 
447
    //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>3), (int)HMSQT_AlienCrouch, (int)ACrSS_Attack_Tail, -1, 1); // only
predalien and standard bad
 
 
448
 
 
 
449
    int left_arm_disabled = ((alienStatusPointer->Wounds & section_flag_left_arm) || (alienStatusPointer->Wounds & section_flag_left_hand));
 
 
450
    int right_arm_disabled = ((alienStatusPointer->Wounds & section_flag_right_arm) || (alienStatusPointer->Wounds & section_flag_right_hand));
 
 
451
    int have_both_arms = !left_arm_disabled && !right_arm_disabled;
 
 
452
 
 
 
453
    //if(alienStatusPointer->IAmCrouched) { }
 
 
454
 
 
 
455
    switch(alienStatusPointer->Type)
 
 
456
    {
 
 
457
        case Standard:
 
 
458
        {
 
 
459
        if(0)
 
 
460
            if(DynamicObjectIsMoving(alienStatusPointer->Target->DynPtr))
 
 
461
            {
 
 
462
                if(alienStatusPointer->IAmCrouched)
 
 
463
                {
 
 
464
                    alienStatusPointer->IAmCrouched = 0;
 
 
465
                }
 
 
466
                else
 
 
467
                {
 
 
468
                    InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>3), (int)HMSQT_AlienRun, (int)ARSS_Attack_Swipe, -1, 1);
 
 
469
                }
 
 
470
            }
 
 
471
            else
 
 
472
            {
 
 
473
        //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>3), (int)HMSQT_AlienCrawl, (int)ACSS_Attack_Swipe, -1, 1);
 
 
474
        //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>3), (int)HMSQT_AlienStand, (int)ASSS_Attack_Low_Left_Swipe, -1, 1);
 
 
475
        //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>3), (int)HMSQT_AlienStand, (int)ASSS_Attack_Low_Right_Swipe, -1,
1);
 
 
476
        //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>3), (int)HMSQT_AlienStand, (int)ASSS_Attack_Both_In, -1, 1);
 
 
477
        //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>3), (int)HMSQT_AlienStand, (int)ASSS_Feed, -1, 1); // only standard
eat dead corsp on ground
 
 
478
            }
 
 
479
        }
 
 
480
        break;
 
 
481
        case Predalien:
 
 
482
        {
 
 
483
        }
 
 
484
        break;
 
 
485
        case Praetorian:
 
 
486
        {
 
 
487
 
 
 
488
        }
 
 
489
    }
 
 
490
 
 
 
491
    //}
 
 
492
    //return;
 
 
493
    if (!alienStatusPointer->Type && 0)
 
 
494
    {
 
 
495
        int collidingWithTarget = 0;
 
 
496
 
 
 
497
        // Test for gripping attack!
 
 
498
        {
 
 
499
            struct collisionreport *nextReport = sbPtr->DynPtr->CollisionReportPtr;
 
 
500
 
 
 
501
            while(nextReport)
 
 
502
            {        
 
 
503
                if(nextReport->ObstacleSBPtr)
 
 
504
                {    
 
 
505
                    if (nextReport->ObstacleSBPtr == alienStatusPointer->Target)
 
 
506
                        collidingWithTarget = 1;
 
 
507
                }
 
 
508
 
 
 
509
                nextReport = nextReport->NextCollisionReportPtr;
 
 
510
            }
 
 
511
        }
 
 
512
 
 
 
513
        if(collidingWithTarget && HModelSequence_Exists(&alienStatusPointer->HModelController, Alien_Special_Gripping_Attack.Sequence_Type,
Alien_Special_Gripping_Attack.Sub_Sequence))
 
 
514
        {
 
 
515
            VECTORCH offset,mypos;
 
 
516
            GetTargetingPointOfObject_Far(alienStatusPointer->Target, &offset);
 
 
517
            GetTargetingPointOfObject_Far(sbPtr, &mypos);
 
 
518
            offset.vx -= mypos.vx;
 
 
519
            offset.vy -= mypos.vy;
 
 
520
            offset.vz -= mypos.vz;
 
 
521
            Normalise(&offset);
 
 
522
 
 
 
523
            if (sbPtr->DynPtr->UseStandardGravity)
 
 
524
            {
 
 
525
                sbPtr->DynPtr->GravityDirection.vx = 0;
 
 
526
                sbPtr->DynPtr->GravityDirection.vy = 65536;
 
 
527
                sbPtr->DynPtr->GravityDirection.vz = 0;
 
 
528
            }
 
 
529
 
 
 
530
            if ((DotProduct(&offset,&sbPtr->DynPtr->GravityDirection) > 16962) && collidingWithTarget)
 
 
531
                thisAttack = &Alien_Special_Gripping_Attack; // 75 degs...
 
 
532
            else
 
 
533
                thisAttack = GetAlienAttackSequence(&alienStatusPointer->HModelController, alienStatusPointer->Wounds,
alienStatusPointer->IAmCrouched);
 
 
534
        }
 
 
535
        else if(DynamicObjectIsMoving(objectDynPtr))
 
 
536
        {
 
 
537
            //InitHModelSequence(&alienStatusPointer->HModelController,(int)HMSQT_AlienRun, (int)ARSS_Attack_Swipe, ONE_FIXED/2);
 
 
538
            thisAttack = GetAlienAttackSequence(&alienStatusPointer->HModelController,alienStatusPointer->Wounds, alienStatusPointer->IAmCrouched);
 
 
539
        }
 
 
540
        else
 
 
541
            thisAttack = GetAlienAttackSequence(&alienStatusPointer->HModelController, alienStatusPointer->Wounds,
alienStatusPointer->IAmCrouched);
 
 
542
    }
 
 
543
    else
 
 
544
    {
 
 
545
        thisAttack = GetAlienAttackSequence(&alienStatusPointer->HModelController,alienStatusPointer->Wounds, alienStatusPointer->IAmCrouched);
 
 
546
    }
 
 
547
*/
 
 
548
    ATTACK_DATA *thisAttack = GetAlienAttackSequence(&alienStatusPointer->HModelController,alienStatusPointer->Wounds,
alienStatusPointer->IAmCrouched);
 
 
549
    SetAlienShapeAnimSequence_Core(sbPtr, thisAttack->Sequence_Type, thisAttack->Sub_Sequence, thisAttack->Sequence_Length,
thisAttack->TweeningTime);
 
 
550
 
 
 
551
    alienStatusPointer->current_attack = thisAttack;
 
 
552
}
 
 
553
 
 
 
554
static void AlienRandomHiss(STRATEGYBLOCK *sbPtr)
 
 
555
{
 
 
556
    ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
557
 
 
 
558
    if (alienStatusPointer->sound_mouth == SOUND_NOACTIVEINDEX)
 
 
559
    {
 
 
560
        PlayAlienSound((int)alienStatusPointer->Type, ASC_Scream_General, 0, &alienStatusPointer->sound_mouth, &sbPtr->DynPtr->Position);
 
 
561
 
 
 
562
        if(NetworkPeer == AvP.PlayMode)
 
 
563
            AddNetMsg_SpotAlienSound((int)ASC_Scream_General, (int)alienStatusPointer->Type, 0, &sbPtr->DynPtr->Position);
 
 
564
    }
 
 
565
}
 
 
566
 
 
 
567
static int GoToJump(STRATEGYBLOCK *sbPtr)
 
 
568
{
 
 
569
    int speed;
 
 
570
    ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
571
    DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
572
 
 
 
573
    /* Must be upright. */
 
 
574
    if((dynPtr->OrientMat.mat22 < 63000) || !alienStatusPointer->CanStand)
 
 
575
        return 0;
 
 
576
 
 
 
577
    /* Should be able to jump now! */
 
 
578
 
 
 
579
    dynPtr->LinImpulse.vx = 0;
 
 
580
    dynPtr->LinImpulse.vy = -10000;
 
 
581
    dynPtr->LinImpulse.vz = 20000;
 
 
582
 
 
 
583
    RotateVector(&dynPtr->LinImpulse, &dynPtr->OrientMat);
 
 
584
    Normalise(&dynPtr->LinImpulse);
 
 
585
 
 
 
586
    switch (alienStatusPointer->Type)
 
 
587
    {
 
 
588
        case Standard:
 
 
589
        default:
 
 
590
            speed = ALIEN_JUMP_SPEED;
 
 
591
        break;
 
 
592
        case Predalien:
 
 
593
            speed = PREDALIEN_JUMP_SPEED;
 
 
594
        break;
 
 
595
        case Praetorian:
 
 
596
            speed = PRAETORIAN_JUMP_SPEED;
 
 
597
    }
 
 
598
 
 
 
599
    int factor = GetAlienSpeedFactor_ForSequence(sbPtr, HMSQT_AlienRun, (int)ARSS_Standard);
 
 
600
    speed = MUL_FIXED(speed, factor);
 
 
601
 
 
 
602
    dynPtr->LinImpulse.vx = MUL_FIXED(speed, dynPtr->LinImpulse.vx);
 
 
603
    dynPtr->LinImpulse.vy = MUL_FIXED(speed, dynPtr->LinImpulse.vy);
 
 
604
    dynPtr->LinImpulse.vz = MUL_FIXED(speed, dynPtr->LinImpulse.vz);
 
 
605
 
 
 
606
    alienStatusPointer->BehaviourState = ABS_Jump;
 
 
607
    alienStatusPointer->StateTimer = 0;
 
 
608
    SetAlienShapeAnimSequence_Core(sbPtr, HMSQT_AlienRun, ARSS_Jump, ONE_FIXED >> 1, (ONE_FIXED >> 2));
 
 
609
 
 
 
610
return 1;
 
 
611
}
 
 
612
 
 
 
613
static int AlienIsAbleToClimb(STRATEGYBLOCK *sbPtr) 
 
 
614
{
 
 
615
    ALIEN_STATUS_BLOCK *alienStatus = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
616
    DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
617
 
 
 
618
    return (alienStatus->CanClimb && alienStatus->IAmCrouched);
 
 
619
 
 
 
620
    if (!alienStatus->CanClimb || !alienStatus->IAmCrouched)
 
 
621
        return 0;
 
 
622
 
 
 
623
{
 
 
624
    struct collisionreport *CollisionReportPtr = dynPtr->CollisionReportPtr;
 
 
625
 
 
 
626
    while(CollisionReportPtr)
 
 
627
    {
 
 
628
        if(CollisionReportPtr->ObstacleSBPtr)
 
 
629
        {
 
 
630
            STRATEGYBLOCK* hit_sbptr = CollisionReportPtr->ObstacleSBPtr;
 
 
631
 
 
 
632
            switch(hit_sbptr->type)
 
 
633
            {
 
 
634
                case I_BehaviourInanimateObject:
 
 
635
                case I_BehaviourPlatform:
 
 
636
                case I_BehaviourVideoScreen:
 
 
637
                case I_BehaviourGrapplingHook:
 
 
638
                //case I_BehaviourPlacedLight:
 
 
639
                return 1;
 
 
640
                case I_BehaviourMarine:
 
 
641
                case I_BehaviourMarinePlayer:
 
 
642
                case I_BehaviourPredatorPlayer:
 
 
643
                case I_BehaviourPredator:
 
 
644
                case I_BehaviourPlacedLight:
 
 
645
                    CauseDamageToObject(hit_sbptr, &damage_profiles[FALLINGDAMAGE], (100*NormalFrameTime), NULL);
 
 
646
                case I_BehaviourAlien:
 
 
647
                case I_BehaviourAlienPlayer:
 
 
648
                case I_BehaviourFaceHugger:
 
 
649
                case I_BehaviourXenoborg:
 
 
650
                case I_BehaviourQueenAlien:
 
 
651
                    return 0;
 
 
652
                default:
 
 
653
                break;
 
 
654
            }
 
 
655
            return 0;
 
 
656
        }
 
 
657
        else
 
 
658
        return 1;
 
 
659
 
 
 
660
        CollisionReportPtr = CollisionReportPtr->NextCollisionReportPtr;
 
 
661
    }
 
 
662
}
 
 
663
 
 
 
664
return 0;
 
 
665
}
 
 
666
 
 
 
667
static int StartAlienTaunt(STRATEGYBLOCK *sbPtr) 
 
 
668
{
 
 
669
    ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
670
 
 
 
671
    if(alienStatusPointer->IAmCrouched)
 
 
672
    {
 
 
673
        if(Standard != alienStatusPointer->Type)
 
 
674
            return 0; /* No sequence - can't do it. */
 
 
675
 
 
 
676
        SetAlienShapeAnimSequence_Core(sbPtr, (int)HMSQT_AlienCrouch, ACrSS_Taunt, -1, (ONE_FIXED >> 3));
 
 
677
    }
 
 
678
    else
 
 
679
    {
 
 
680
        int sub_sequence = ASSS_Taunt;
 
 
681
 
 
 
682
        if(Standard == alienStatusPointer->Type)
 
 
683
        {
 
 
684
            switch(FastRandom() % 3)
 
 
685
            {
 
 
686
                case 0:
 
 
687
                default:
 
 
688
                break;
 
 
689
                case 1:
 
 
690
                    sub_sequence = ASSS_Taunt2;
 
 
691
                break;
 
 
692
                case 2:
 
 
693
                    sub_sequence = ASSS_Taunt3;
 
 
694
            }
 
 
695
        }
 
 
696
 
 
 
697
        /* The things I do for transparent code... */
 
 
698
 
 
 
699
        SetAlienShapeAnimSequence_Core(sbPtr, (int)HMSQT_AlienStand, sub_sequence, -1, (ONE_FIXED >> 3));
 
 
700
    }
 
 
701
 
 
 
702
    alienStatusPointer->HModelController.Looped = 0;
 
 
703
    alienStatusPointer->HModelController.LoopAfterTweening = 0;
 
 
704
    alienStatusPointer->BehaviourState = ABS_Taunting;
 
 
705
    alienStatusPointer->StateTimer = 0;
 
 
706
 
 
 
707
    AlienRandomHiss(sbPtr);
 
 
708
/*
 
 
709
    if (alienStatusPointer->sound_mouth == SOUND_NOACTIVEINDEX)
 
 
710
    {
 
 
711
        PlayAlienSound((int)alienStatusPointer->Type, ASC_Taunt, 0, &alienStatusPointer->sound_mouth, &sbPtr->DynPtr->Position);
 
 
712
 
 
 
713
        if(NetworkPeer == AvP.PlayMode)
 
 
714
            AddNetMsg_SpotAlienSound((int)ASC_Taunt, (int)alienStatusPointer->Type, 0, &sbPtr->DynPtr->Position);
 
 
715
    }
 
 
716
*/
 
 
717
 
 
 
718
return 1;
 
 
719
}
 
 
720
 
 
 
721
static int TargetIsFiringFlamethrowerAtAlien(STRATEGYBLOCK *sbPtr, int distance_to_target)
 
 
722
{
 
 
723
    ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
724
 
 
 
725
    /* First, let's see what the target is. */
 
 
726
    switch(alienStatusPointer->Target->type)
 
 
727
    {
 
 
728
        case I_BehaviourMarinePlayer:
 
 
729
        {
 
 
730
            /* Is the player firing a flamethrower? */
 
 
731
 
 
 
732
            if ((PlayerStatus.SelectedWeapon->WeaponIDNumber == WEAPON_FLAMETHROWER) && (PlayerStatus.WeaponState == WEAPONSTATE_FIRING_PRIMARY))
 
 
733
            //if ((PlayerStatus.SelectedWeapon->WeaponIDNumber == WEAPON_FLAMETHROWER) && (PlayerStatus.weapon.HModelControlBlock->Sub_Sequence ==
MHSS_Standard_Fire))
 
 
734
                break;
 
 
735
        }
 
 
736
        return 0;
 
 
737
        case I_BehaviourMarine:
 
 
738
        {
 
 
739
            assert(sbPtr);
 
 
740
            MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(alienStatusPointer->Target->dataptr);
 
 
741
            assert(marineStatusPointer);                      
 
 
742
 
 
 
743
            switch(marineStatusPointer->My_Weapon->id)
 
 
744
            {
 
 
745
                case MNPCW_Flamethrower:
 
 
746
                case MNPCW_MFlamer:
 
 
747
                    if (marineStatusPointer->behaviourState != MBS_Firing)
 
 
748
                        return 0;
 
 
749
                break;
 
 
750
                default:
 
 
751
                return 0;
 
 
752
            }
 
 
753
        }
 
 
754
        default:
 
 
755
        {
 
 
756
            /* Gotta insert a case for netghosts. */
 
 
757
            return 0;
 
 
758
        }
 
 
759
    }
 
 
760
 
 
 
761
    /* Next, let's see if the alien and the target are both in the other's front arc. */
 
 
762
 
 
 
763
    {
 
 
764
        VECTORCH sourcepos,targetpos,offset;
 
 
765
        MATRIXCH WtoL = sbPtr->DynPtr->OrientMat;
 
 
766
        GetTargetingPointOfObject_Far(sbPtr, &sourcepos);
 
 
767
        GetTargetingPointOfObject_Far(alienStatusPointer->Target, &targetpos);
 
 
768
 
 
 
769
        offset.vx = sourcepos.vx - targetpos.vx;
 
 
770
        offset.vy = sourcepos.vy - targetpos.vy;
 
 
771
        offset.vz = sourcepos.vz - targetpos.vz;
 
 
772
 
 
 
773
        TransposeMatrixCH(&WtoL);
 
 
774
        RotateVector(&offset,&WtoL);
 
 
775
 
 
 
776
        if ( (offset.vz <0) 
 
 
777
            && (offset.vz <  offset.vx) 
 
 
778
            && (offset.vz < -offset.vx) 
 
 
779
            && (offset.vz <  offset.vy) 
 
 
780
            && (offset.vz < -offset.vy) )
 
 
781
        {
 
 
782
            /* 90 horizontal, 90 vertical... continue. */
 
 
783
        }
 
 
784
        else
 
 
785
        {
 
 
786
            return 0;
 
 
787
        }
 
 
788
 
 
 
789
        /* Now test it for the other way round. */
 
 
790
 
 
 
791
        WtoL = alienStatusPointer->Target->DynPtr->OrientMat;
 
 
792
        GetTargetingPointOfObject_Far(alienStatusPointer->Target,&sourcepos);
 
 
793
        GetTargetingPointOfObject_Far(sbPtr,&targetpos);
 
 
794
 
 
 
795
        offset.vx = sourcepos.vx - targetpos.vx;
 
 
796
        offset.vy = sourcepos.vy - targetpos.vy;
 
 
797
        offset.vz = sourcepos.vz - targetpos.vz;
 
 
798
 
 
 
799
        TransposeMatrixCH(&WtoL);
 
 
800
        RotateVector(&offset, &WtoL);
 
 
801
 
 
 
802
        if ( (offset.vz < 0) 
 
 
803
            && (offset.vz <  offset.vx) 
 
 
804
            && (offset.vz < -offset.vx) 
 
 
805
            && (offset.vz <  offset.vy) 
 
 
806
            && (offset.vz < -offset.vy) )
 
 
807
        {
 
 
808
 
 
 
809
            /* 90 horizontal, 90 vertical... continue. */
 
 
810
        }
 
 
811
        else
 
 
812
        {
 
 
813
            return 0;
 
 
814
        }
 
 
815
    }
 
 
816
 
 
 
817
    //int range = VectorDistance(&alienStatusPointer->Target->DynPtr->Position, &sbPtr->DynPtr->Position);
 
 
818
    //printf("range %d\n", range);
 
 
819
 
 
 
820
    if (distance_to_target > 18000)
 
 
821
    {
 
 
822
        return StartAlienTaunt(sbPtr);
 
 
823
    }
 
 
824
    else
 
 
825
    {
 
 
826
        NPC_OBSTRUCTIONREPORT obstruction = {1,0,0,0};
 
 
827
        NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
828
        NPCGetAvoidanceDirection(sbPtr, &alienStatusPointer->moveData.avoidanceDirn, &obstruction);
 
 
829
        alienStatusPointer->BehaviourState = ABS_Avoidance;
 
 
830
        alienStatusPointer->StateTimer = NPC_AVOIDTIME/2;
 
 
831
    }
 
 
832
 
 
 
833
/* If here, then it must be true! */
 
 
834
return 1;
 
 
835
}
 
 
836
 
 
 
837
static ATTACK_DATA *AlienIsAbleToPounce(STRATEGYBLOCK *sbPtr) 
 
 
838
{
 
 
839
    VECTORCH targetPoint;
 
 
840
    ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
841
 
 
 
842
    /* Also not if you're badly hurt. */
 
 
843
    {
 
 
844
        int factor = GetAlienSpeedFactor_ForSequence(sbPtr, HMSQT_AlienRun, (int)ARSS_Standard);
 
 
845
 
 
 
846
        if (factor < ((ONE_FIXED*3)/4))
 
 
847
            return NULL;
 
 
848
    }
 
 
849
 
 
 
850
    if (NULL != alienStatusPointer->Target->DisplayBlock)
 
 
851
    {
 
 
852
        GetTargetingPointOfObject(alienStatusPointer->Target->DisplayBlock, &targetPoint);
 
 
853
 
 
 
854
        /* Do we have a clear line of sight? */
 
 
855
 
 
 
856
        if (IsThisObjectVisibleFromThisPosition_WithIgnore(sbPtr->DisplayBlock, alienStatusPointer->Target->DisplayBlock, &targetPoint))
 
 
857
        {
 
 
858
            /* Finally, test the sequence. */
 
 
859
            ATTACK_DATA *thisAttack = GetAlienPounceAttack(&alienStatusPointer->HModelController,alienStatusPointer->Wounds,
alienStatusPointer->IAmCrouched);
 
 
860
 
 
 
861
            if ((thisAttack == NULL) && !alienStatusPointer->IAmCrouched)
 
 
862
            {
 
 
863
                /* Try again crouched. Pook. */
 
 
864
                thisAttack = GetAlienPounceAttack(&alienStatusPointer->HModelController,alienStatusPointer->Wounds, 1);
 
 
865
            }
 
 
866
            return thisAttack;
 
 
867
        }
 
 
868
    }
 
 
869
 
 
 
870
return NULL;
 
 
871
}
 
 
872
 
 
 
873
static int StartAlienPounce(STRATEGYBLOCK *sbPtr) 
 
 
874
{
 
 
875
    ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
876
 
 
 
877
    if((sbPtr->DynPtr->OrientMat.mat22 < 63000) || (sbPtr->containingModule->m_flags & MODULEFLAG_AIRDUCT))
 
 
878
    {
 
 
879
        // First rule.  Must be on a flat floor,  And not in an airduct.
 
 
880
    }
 
 
881
    else if(alienStatusPointer->CanStand && sbPtr->DynPtr->IsInContactWithFloor)
 
 
882
    {
 
 
883
        ATTACK_DATA *thisAttack = AlienIsAbleToPounce(sbPtr);
 
 
884
 
 
 
885
        if (NULL != thisAttack)
 
 
886
        {
 
 
887
            SetAlienShapeAnimSequence_Core(sbPtr, thisAttack->Sequence_Type, thisAttack->Sub_Sequence, thisAttack->Sequence_Length,
thisAttack->TweeningTime);
 
 
888
 
 
 
889
            alienStatusPointer->HModelController.Looped = 0;
 
 
890
            alienStatusPointer->HModelController.LoopAfterTweening = 0;
 
 
891
            alienStatusPointer->current_attack = thisAttack;
 
 
892
            alienStatusPointer->BehaviourState = ABS_Pounce;
 
 
893
            alienStatusPointer->StateTimer = 0;
 
 
894
            return 1;
 
 
895
        }
 
 
896
    }
 
 
897
 
 
 
898
return 0;
 
 
899
}
 
 
900
 
 
 
901
static enum AMMO_ID GetAttackDamageType(STRATEGYBLOCK *sbPtr, int flagnum) 
 
 
902
{
 
 
903
    ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
904
 
 
 
905
    if (alienStatusPointer->current_attack == NULL)
 
 
906
        return AMMO_NONE;
 
 
907
 
 
 
908
    /* Fix praetorian damage here! */
 
 
909
 
 
 
910
    switch (alienStatusPointer->Type)
 
 
911
    {
 
 
912
        case Standard:
 
 
913
        default:
 
 
914
            /* No change. */
 
 
915
            return (alienStatusPointer->current_attack->flag_damage[flagnum]);
 
 
916
        case Predalien:
 
 
917
        {
 
 
918
            switch (alienStatusPointer->current_attack->flag_damage[flagnum])
 
 
919
            {
 
 
920
                case AMMO_ALIEN_CLAW:
 
 
921
                default:
 
 
922
                    return AMMO_NPC_PREDALIEN_CLAW;
 
 
923
                case AMMO_ALIEN_TAIL:
 
 
924
                    return AMMO_NPC_PREDALIEN_TAIL;
 
 
925
                case AMMO_NPC_ALIEN_BITE:
 
 
926
                    return AMMO_NPC_PREDALIEN_BITE;
 
 
927
            }
 
 
928
        }
 
 
929
        case Praetorian:
 
 
930
        {
 
 
931
            switch (alienStatusPointer->current_attack->flag_damage[flagnum])
 
 
932
            {
 
 
933
                case AMMO_ALIEN_CLAW:
 
 
934
                default:
 
 
935
                    return AMMO_NPC_PRAETORIAN_CLAW;
 
 
936
                case AMMO_ALIEN_TAIL:
 
 
937
                    return AMMO_NPC_PRAETORIAN_TAIL;
 
 
938
                case AMMO_NPC_ALIEN_BITE:
 
 
939
                    return AMMO_NPC_PRAETORIAN_BITE;
 
 
940
            }
 
 
941
        }
 
 
942
    }
 
 
943
}
 
 
944
 
 
 
945
static void AlienNearDamageShell(STRATEGYBLOCK *sbPtr)
 
 
946
{
 
 
947
    ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
948
 
 
 
949
    /* Damage shell! */
 
 
950
    int workingflags = alienStatusPointer->HModelController.keyframe_flags >> 1;
 
 
951
 
 
 
952
    int a=0;
 
 
953
    for (; a < NUM_ATTACKFLAGS; a++)
 
 
954
    {
 
 
955
        if (workingflags & 1)
 
 
956
        {
 
 
957
            /* Oops, check range first. */
 
 
958
            VECTORCH rel_pos, attack_dir;
 
 
959
            rel_pos.vx = alienStatusPointer->Target->DynPtr->Position.vx - sbPtr->DynPtr->Position.vx;
 
 
960
            rel_pos.vy = alienStatusPointer->Target->DynPtr->Position.vy - sbPtr->DynPtr->Position.vy;
 
 
961
            rel_pos.vz = alienStatusPointer->Target->DynPtr->Position.vz - sbPtr->DynPtr->Position.vz;
 
 
962
            GetDirectionOfAttack(alienStatusPointer->Target, &rel_pos, &attack_dir);
 
 
963
 
 
 
964
            if (alienStatusPointer->Target->DisplayBlock && alienStatusPointer->Target->DisplayBlock->HModelControlBlock)
 
 
965
                HtoHDamageToHModel(alienStatusPointer->Target, &TemplateAmmo[GetAttackDamageType(sbPtr, a)].MaxDamage, ONE_FIXED, sbPtr,
&attack_dir);
 
 
966
            else
 
 
967
                CauseDamageToObject(alienStatusPointer->Target, &TemplateAmmo[GetAttackDamageType(sbPtr, a)].MaxDamage, ONE_FIXED, &attack_dir);
 
 
968
        }
 
 
969
 
 
 
970
        /* Prepare next flag. */
 
 
971
        workingflags >>= 1;
 
 
972
    }
 
 
973
}
 
 
974
 
 
 
975
static AIMODULE *FarNPC_GetTargetAIModuleForGlobalHunt(STRATEGYBLOCK *sbPtr)
 
 
976
{
 
 
977
    unsigned int highestSmell = 0;
 
 
978
    AIMODULE* targetModule = NULL;
 
 
979
 
 
 
980
    AIMODULE **AdjModuleRefPtr = sbPtr->containingModule->m_aimodule->m_link_ptrs;
 
 
981
 
 
 
982
    /* check that there is a list of adjacent modules, and that it is not
 
 
983
    empty (ie points to zero) */
 
 
984
 
 
 
985
    if(AdjModuleRefPtr)
 
 
986
    {
 
 
987
        while(*AdjModuleRefPtr != 0)
 
 
988
        {
 
 
989
            /* get the index */
 
 
990
            int AdjModuleIndex = (*AdjModuleRefPtr)->m_index;
 
 
991
 
 
 
992
            /* if this adjacent module's smell value is higher than
 
 
993
            the current 'highest smell' record the new module as the
 
 
994
            target. */
 
 
995
 
 
 
996
            if(PherAls_ReadBuf[AdjModuleIndex] > highestSmell)
 
 
997
            {                        
 
 
998
                highestSmell = PherAls_ReadBuf[AdjModuleIndex];
 
 
999
                targetModule = *AdjModuleRefPtr;                            
 
 
1000
            }
 
 
1001
            /* next adjacent module reference pointer */
 
 
1002
            AdjModuleRefPtr++;
 
 
1003
        }
 
 
1004
    }
 
 
1005
 
 
 
1006
    if (highestSmell < PherAls_ReadBuf[sbPtr->containingModule->m_aimodule->m_index])
 
 
1007
        return (sbPtr->containingModule->m_aimodule);
 
 
1008
    else
 
 
1009
        return (targetModule);
 
 
1010
}
 
 
1011
 
 
 
1012
static void CheckPounceIntegrity(STRATEGYBLOCK *sbPtr) 
 
 
1013
{
 
 
1014
    VECTORCH targetPoint;
 
 
1015
    ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
1016
    DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
1017
 
 
 
1018
    if (alienStatusPointer->Target == NULL)
 
 
1019
    {
 
 
1020
        /* Attack what? */
 
 
1021
        alienStatusPointer->BehaviourState = ABS_Hunt;
 
 
1022
        alienStatusPointer->StateTimer = ALIEN_NEARWAITTIME;
 
 
1023
        return;
 
 
1024
    }
 
 
1025
 
 
 
1026
    if ((alienStatusPointer->Target->DisplayBlock == NULL) || ((alienStatusPointer->Target->DynPtr->Position.vy -
sbPtr->DynPtr->Position.vy) > 1000))
 
 
1027
    {
 
 
1028
        /* Yuck.  Target is far, or too far below you. */
 
 
1029
        NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
1030
        alienStatusPointer->BehaviourState = ABS_Approach;
 
 
1031
 
 
 
1032
        alienStatusPointer->StateTimer = 0;
 
 
1033
        alienStatusPointer->CurveTimeOut = 0;
 
 
1034
        return;
 
 
1035
    }
 
 
1036
 
 
 
1037
    GetTargetingPointOfObject(alienStatusPointer->Target->DisplayBlock, &targetPoint);
 
 
1038
 
 
 
1039
    /* Do we have a clear line of sight? */
 
 
1040
 
 
 
1041
    if (!IsThisObjectVisibleFromThisPosition_WithIgnore(sbPtr->DisplayBlock, alienStatusPointer->Target->DisplayBlock, &targetPoint))
 
 
1042
    {
 
 
1043
        /* Can't see! */
 
 
1044
        NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
1045
        alienStatusPointer->BehaviourState = ABS_Approach;
 
 
1046
 
 
 
1047
        alienStatusPointer->StateTimer = 0;
 
 
1048
        alienStatusPointer->CurveTimeOut = 0;
 
 
1049
        return;
 
 
1050
    }
 
 
1051
 
 
 
1052
    /* Orientate towards player, just to make sure we're facing */
 
 
1053
    {
 
 
1054
        VECTORCH orientationDirn;
 
 
1055
        orientationDirn.vx = alienStatusPointer->Target->DynPtr->Position.vx - sbPtr->DynPtr->Position.vx;
 
 
1056
        orientationDirn.vy = 0;
 
 
1057
        orientationDirn.vz = alienStatusPointer->Target->DynPtr->Position.vz - sbPtr->DynPtr->Position.vz;
 
 
1058
 
 
 
1059
        if (!NPCOrientateToVector(sbPtr, &orientationDirn,NPC_TURNRATE))
 
 
1060
        {
 
 
1061
            /* Still not right.  Be careful. */
 
 
1062
            alienStatusPointer->HModelController.StopAfterTweening = 1;
 
 
1063
        }
 
 
1064
        else
 
 
1065
        {
 
 
1066
            /* Okay for the moment. */
 
 
1067
            alienStatusPointer->HModelController.StopAfterTweening = 0;
 
 
1068
        }
 
 
1069
    }
 
 
1070
 
 
 
1071
    /* change back to approach?: don't need to directly test if we should go to wander, as 
 
 
1072
    approach state will do this... */
 
 
1073
    {
 
 
1074
        int distance_to_target = VectorDistance(&dynPtr->Position, &alienStatusPointer->Target->DynPtr->Position);
 
 
1075
 
 
 
1076
        if(distance_to_target > ALIEN_POUNCE_MAXRANGE)
 
 
1077
        {
 
 
1078
            NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
1079
            alienStatusPointer->BehaviourState = ABS_Approach;
 
 
1080
 
 
 
1081
            alienStatusPointer->StateTimer = 0;
 
 
1082
            alienStatusPointer->CurveTimeOut = 0;
 
 
1083
            return;
 
 
1084
        }
 
 
1085
    }
 
 
1086
 
 
 
1087
    /* Are we still able to pounce? */
 
 
1088
 
 
 
1089
    /* Not if you've lost any leg sections. */    
 
 
1090
    if ( (alienStatusPointer->Wounds & (section_flag_left_leg | section_flag_right_leg)) 
 
 
1091
        /* Also not if you've lost both feet. */
 
 
1092
        || ((alienStatusPointer->Wounds & section_flag_left_foot) && (alienStatusPointer->Wounds & section_flag_right_foot)) )
 
 
1093
    {
 
 
1094
        /* Can't stand either.  Fall over. */
 
 
1095
        /* That implies going back to approach, btw. */
 
 
1096
        NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
1097
        alienStatusPointer->BehaviourState = ABS_Approach;
 
 
1098
 
 
 
1099
        alienStatusPointer->StateTimer = 0;
 
 
1100
        alienStatusPointer->CurveTimeOut = 0;
 
 
1101
    }
 
 
1102
}
 
 
1103
 
 
 
1104
static void ApplyPounceImpulse(STRATEGYBLOCK *sbPtr) 
 
 
1105
{
 
 
1106
    VECTORCH pounceVector,targetPoint;
 
 
1107
    int speed;
 
 
1108
    ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
1109
    DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
1110
 
 
 
1111
    GetTargetingPointOfObject(alienStatusPointer->Target->DisplayBlock,&targetPoint);
 
 
1112
 
 
 
1113
    int dist = VectorDistance(&dynPtr->Position, &targetPoint);
 
 
1114
 
 
 
1115
    /* Apply a correction based on range. */
 
 
1116
    targetPoint.vy -= dist >> 3;
 
 
1117
 
 
 
1118
    pounceVector.vx = targetPoint.vx - dynPtr->Position.vx;
 
 
1119
    pounceVector.vy = targetPoint.vy - dynPtr->Position.vy;
 
 
1120
    pounceVector.vz = targetPoint.vz - dynPtr->Position.vz;
 
 
1121
 
 
 
1122
    Normalise(&pounceVector);
 
 
1123
    /* Must jump at least a little bit upwards. */
 
 
1124
    if (pounceVector.vy > -10000)
 
 
1125
        pounceVector.vy = -10000;
 
 
1126
 
 
 
1127
    switch (alienStatusPointer->Type)
 
 
1128
    {
 
 
1129
        case Standard:
 
 
1130
        default:
 
 
1131
            speed = ALIEN_JUMP_SPEED;
 
 
1132
        break;
 
 
1133
        case Predalien:
 
 
1134
            speed = PREDALIEN_JUMP_SPEED;
 
 
1135
        break;
 
 
1136
        case Praetorian:
 
 
1137
            speed = PRAETORIAN_JUMP_SPEED;
 
 
1138
    }
 
 
1139
 
 
 
1140
    int factor = GetAlienSpeedFactor_ForSequence(sbPtr, HMSQT_AlienRun, (int)ARSS_Standard);
 
 
1141
    speed = MUL_FIXED(speed, factor);
 
 
1142
 
 
 
1143
    pounceVector.vx = MUL_FIXED(speed,pounceVector.vx);
 
 
1144
    pounceVector.vy = MUL_FIXED(speed,pounceVector.vy);
 
 
1145
    pounceVector.vz = MUL_FIXED(speed,pounceVector.vz);
 
 
1146
 
 
 
1147
    sbPtr->DynPtr->LinImpulse = pounceVector;
 
 
1148
}
 
 
1149
 
 
 
1150
static int make_new_alien(STRATEGYBLOCK *sbPtr, ALIEN_TYPE type_of_alien, ALIEN_BHSTATE starting_state, STRATEGYBLOCK *Generator)
 
 
1151
{
 
 
1152
    sbPtr->dataptr = malloc(sizeof(ALIEN_STATUS_BLOCK));
 
 
1153
    sbPtr->maintainVisibility = 1;
 
 
1154
    sbPtr->containingModule = ModuleFromPosition(&sbPtr->DynPtr->Position, NULL);
 
 
1155
 
 
 
1156
    if(NULL == sbPtr->dataptr)
 
 
1157
    {
 
 
1158
        RemoveBehaviourStrategy(sbPtr);
 
 
1159
        return 0;
 
 
1160
    }
 
 
1161
 
 
 
1162
    ALIEN_STATUS_BLOCK *new_alien = (ALIEN_STATUS_BLOCK *)sbPtr->dataptr;
 
 
1163
 
 
 
1164
    new_alien->HModelController.Deltas = NULL;
 
 
1165
    new_alien->HModelController.Root_Section = NULL;
 
 
1166
    new_alien->HModelController.section_data = NULL;
 
 
1167
    new_alien->Type = type_of_alien;
 
 
1168
    new_alien->BehaviourState = starting_state;
 
 
1169
    new_alien->GibbFactor = 0;
 
 
1170
    new_alien->MaxSpeed = 0;
 
 
1171
    new_alien->Wounds = 0;
 
 
1172
    new_alien->last_anim_length = ONE_FIXED;
 
 
1173
    new_alien->incidentFlag = 0;
 
 
1174
    new_alien->incidentTimer = 0;
 
 
1175
    new_alien->CurveRadius = 0;
 
 
1176
    new_alien->CurveLength = 0;
 
 
1177
    new_alien->CurveTimeOut = 0;
 
 
1178
    new_alien->StateTimer = ALIEN_FAR_MOVE_TIME;
 
 
1179
    new_alien->IAmCrouched = 0;
 
 
1180
    new_alien->CurrentLightAtAlien = 0;
 
 
1181
    new_alien->EnableWaypoints = 0;
 
 
1182
    new_alien->PreferToCrouch = 0;
 
 
1183
    new_alien->aliensIgniterId = 0; //Which player in a multiplayer game toasted this poor beast?
 
 
1184
    new_alien->soundOnFire = SOUND_NOACTIVEINDEX;
 
 
1185
    new_alien->sound_mouth = SOUND_NOACTIVEINDEX;
 
 
1186
    new_alien->unconscious = 0;
 
 
1187
    new_alien->CanStand = 1;
 
 
1188
    new_alien->CanClimb = 1;
 
 
1189
    new_alien->current_attack = NULL;
 
 
1190
    new_alien->huntingModule = NULL;
 
 
1191
    new_alien->Target = NULL;
 
 
1192
 
 
 
1193
    COPY_NAME(new_alien->Target_SBname, Null_Name);
 
 
1194
 
 
 
1195
{
 
 
1196
    int i = 0;
 
 
1197
    for(; i < SB_NAME_LENGTH; i++)
 
 
1198
        new_alien->death_target_ID[i] = 0;
 
 
1199
}
 
 
1200
    new_alien->death_target_sbptr = NULL;
 
 
1201
    new_alien->generator_sbptr = Generator;
 
 
1202
 
 
 
1203
    {
 
 
1204
        const NPC_DATA *NpcData;
 
 
1205
        const SECTION *root_section;
 
 
1206
 
 
 
1207
        switch (new_alien->Type)
 
 
1208
        {
 
 
1209
            case 0:
 
 
1210
            default:
 
 
1211
                NpcData = &NpcDataList[I_NPC_Alien];
 
 
1212
                new_alien->MaxSpeed = ALIEN_FORWARDVELOCITY;
 
 
1213
                new_alien->EnableWaypoints = (FastRandom() & 7);
 
 
1214
                sbPtr->DynPtr->Mass = ALIEN_MASS;
 
 
1215
                root_section = GetNamedHierarchyFromLibrary("hnpcalien", "alien");
 
 
1216
            break;
 
 
1217
            case 1:
 
 
1218
                NpcData = &NpcDataList[I_NPC_PredatorAlien];
 
 
1219
                new_alien->MaxSpeed = MUL_FIXED(ALIEN_FORWARDVELOCITY, PREDALIEN_SPEED_FACTOR);
 
 
1220
                new_alien->EnableWaypoints = 1;
 
 
1221
                sbPtr->DynPtr->Mass = PREDALIEN_MASS;
 
 
1222
                root_section = GetNamedHierarchyFromLibrary("hnpcpred_alien", "TEMPLATE");
 
 
1223
            break;
 
 
1224
            case 2:
 
 
1225
                NpcData = &NpcDataList[I_NPC_PraetorianGuard];
 
 
1226
                new_alien->MaxSpeed = MUL_FIXED(ALIEN_FORWARDVELOCITY, MUL_FIXED(PRAETORIAN_WALKSPEED_FACTOR, PRAETORIAN_SPEED_FACTOR));
 
 
1227
                sbPtr->DynPtr->Mass = PRAETORIAN_MASS;
 
 
1228
                new_alien->EnableWaypoints = 0;
 
 
1229
                root_section = GetNamedHierarchyFromLibrary("hnpcpretorian", "Template");
 
 
1230
                new_alien->CanClimb = 0; // Praetorian Guard can't climb.  Sorry.
 
 
1231
        }
 
 
1232
 
 
 
1233
new_alien->EnableWaypoints = 0; // jadda
 
 
1234
        sbPtr->DamageBlock = NpcData->StartingStats;
 
 
1235
        sbPtr->DamageBlock.Health = NpcData->StartingStats.Health << ONE_FIXED_SHIFT;
 
 
1236
        sbPtr->DamageBlock.Armour = NpcData->StartingStats.Armour << ONE_FIXED_SHIFT;
 
 
1237
 
 
 
1238
        if (!root_section || !sbPtr->containingModule)
 
 
1239
        {
 
 
1240
            RemoveBehaviourStrategy(sbPtr);
 
 
1241
            return 0;
 
 
1242
        }
 
 
1243
 
 
 
1244
        Create_HModel(&new_alien->HModelController, root_section);
 
 
1245
    }
 
 
1246
 
 
 
1247
    NPC_InitMovementData(&new_alien->moveData);
 
 
1248
    NPC_InitWanderData(&new_alien->wanderData);
 
 
1249
    Initialise_AvoidanceManager(&new_alien->avoidanceManager);
 
 
1250
    InitWaypointManager(&new_alien->waypointManager);
 
 
1251
 
 
 
1252
    if(ABS_Dormant == new_alien->BehaviourState)
 
 
1253
        InitHModelSequence(&new_alien->HModelController, HMSQT_AlienStand, ASSS_Dormant, -1);
 
 
1254
    else
 
 
1255
        InitHModelSequence(&new_alien->HModelController, 0, 0, ONE_FIXED);
 
 
1256
 
 
 
1257
    new_alien->HModelController.Playing = 0;
 
 
1258
 
 
 
1259
    if (CHEATMODE_SLUGTRAIL == UserProfile.active_bonus) 
 
 
1260
    {
 
 
1261
        /* Blow off a leg? */
 
 
1262
        SECTION_DATA *leg = GetThisSectionData(new_alien->HModelController.section_data, "left thigh");
 
 
1263
 
 
 
1264
        if (leg) 
 
 
1265
        {
 
 
1266
            Prune_HModel_Virtual(leg);
 
 
1267
            new_alien->Wounds = section_flag_left_leg | section_flag_left_foot;
 
 
1268
            new_alien->CanStand = 0;
 
 
1269
            sbPtr->DamageBlock.Health -= (20 << ONE_FIXED_SHIFT);
 
 
1270
        }
 
 
1271
    }
 
 
1272
 
 
 
1273
    if (HModelSequence_Exists(&new_alien->HModelController, (int)HMSQT_AlienStand, (int)ASSS_Hit_Right))
 
 
1274
    {
 
 
1275
        DELTA_CONTROLLER *delta = Add_Delta_Sequence(&new_alien->HModelController, "HitDelta", (int)HMSQT_AlienStand, (int)ASSS_Hit_Right, -1);
 
 
1276
        assert(delta);
 
 
1277
        delta->Playing = 0;
 
 
1278
    }
 
 
1279
 
 
 
1280
    ProveHModel_Far(&new_alien->HModelController, sbPtr);
 
 
1281
 
 
 
1282
return 1;
 
 
1283
}
 
 
1284
 
 
 
1285
void CreateAlienBot(VECTORCH *Position, int type)
 
 
1286
{
 
 
1287
    STRATEGYBLOCK* sbPtr = CreateActiveStrategyBlock(I_BehaviourAlien);
 
 
1288
 
 
 
1289
    if(!sbPtr)
 
 
1290
        return;
 
 
1291
 
 
 
1292
    sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_DEFAULT);
 
 
1293
 
 
 
1294
    if(sbPtr->DynPtr)
 
 
1295
    {
 
 
1296
        DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
1297
        AssignNewSBName(sbPtr);
 
 
1298
        dynPtr->PrevPosition = dynPtr->Position = *Position;
 
 
1299
        CreateEulerMatrix(&dynPtr->OrientEuler, &dynPtr->OrientMat);
 
 
1300
        TransposeMatrixCH(&dynPtr->OrientMat);      
 
 
1301
        sbPtr->DynPtr->ToppleForce = TOPPLE_FORCE_ALIEN;
 
 
1302
        make_new_alien(sbPtr, type, ABS_Hunt, NULL);
 
 
1303
    }
 
 
1304
    else
 
 
1305
    {
 
 
1306
        RemoveBehaviourStrategy(sbPtr);
 
 
1307
    }
 
 
1308
}
 
 
1309
 
 
 
1310
void CastAlienBot(int type)
 
 
1311
{
 
 
1312
    #define BOTRANGE 2000
 
 
1313
 
 
 
1314
    VECTORCH position;
 
 
1315
    position = PlayerStatus.sbptr->DynPtr->Position;
 
 
1316
    position.vx += MUL_FIXED(PlayerStatus.sbptr->DynPtr->OrientMat.mat31, BOTRANGE);
 
 
1317
    position.vy += MUL_FIXED(PlayerStatus.sbptr->DynPtr->OrientMat.mat32, BOTRANGE);
 
 
1318
    position.vz += MUL_FIXED(PlayerStatus.sbptr->DynPtr->OrientMat.mat33, BOTRANGE);
 
 
1319
 
 
 
1320
    CreateAlienBot(&position, type);
 
 
1321
}
 
 
1322
 
 
 
1323
/*----------------------Patrick 15/11/96-----------------------------
 
 
1324
This function is called by the alien generators, to dynamically
 
 
1325
create a new alien, during the game.  The alien is initialised
 
 
1326
as invisible.
 
 
1327
 
 
 
1328
1. create a new strategy block (no diplay block)
 
 
1329
2. attach a dynamics block
 
 
1330
3. attach an alien data block
 
 
1331
4. initialise for far behaviour
 
 
1332
 
 
 
1333
NB the strategyblock passed here is a reference to the generator sb
 
 
1334
--------------------------------------------------------------------*/
 
 
1335
void CreateAlienDynamic(STRATEGYBLOCK *Generator, ALIEN_TYPE type_of_alien)
 
 
1336
{
 
 
1337
    STRATEGYBLOCK* sbPtr = CreateActiveStrategyBlock(I_BehaviourAlien);
 
 
1338
 
 
 
1339
    if(NULL != sbPtr)
 
 
1340
    {
 
 
1341
        DYNAMICSBLOCK *dynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_DEFAULT);
 
 
1342
 
 
 
1343
        if(NULL != dynPtr)
 
 
1344
        {
 
 
1345
            sbPtr->DynPtr = dynPtr;
 
 
1346
            AssignNewSBName(sbPtr);
 
 
1347
            dynPtr->PrevPosition = dynPtr->Position = ((GENERATOR_BLOCK* )Generator->dataptr)->Position;
 
 
1348
            CreateEulerMatrix(&dynPtr->OrientEuler, &dynPtr->OrientMat);
 
 
1349
            TransposeMatrixCH(&dynPtr->OrientMat);      
 
 
1350
            sbPtr->DynPtr->ToppleForce = TOPPLE_FORCE_ALIEN;
 
 
1351
            make_new_alien(sbPtr, type_of_alien, ABS_Hunt, Generator);
 
 
1352
 
 
 
1353
            /* assert alien is starting as invisible */
 
 
1354
            assert(!ModuleCurrVisArray[sbPtr->containingModule->m_index]);
 
 
1355
        }
 
 
1356
        else
 
 
1357
        {
 
 
1358
            RemoveBehaviourStrategy(sbPtr);
 
 
1359
        }
 
 
1360
    }
 
 
1361
}
 
 
1362
 
 
 
1363
void MakeAlienFar(STRATEGYBLOCK *sbPtr)
 
 
1364
{
 
 
1365
    ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
1366
    DestroyActiveObject(&sbPtr->DisplayBlock);
 
 
1367
 
 
 
1368
    if(alienStatusPointer->soundOnFire != SOUND_NOACTIVEINDEX)
 
 
1369
        Sound_Stop(alienStatusPointer->soundOnFire);                
 
 
1370
 
 
 
1371
    if(alienStatusPointer->sound_mouth != SOUND_NOACTIVEINDEX)
 
 
1372
        Sound_Stop(alienStatusPointer->sound_mouth);
 
 
1373
 
 
 
1374
    switch(alienStatusPointer->BehaviourState)
 
 
1375
    {
 
 
1376
        case ABS_Dormant:
 
 
1377
        case ABS_Awakening:
 
 
1378
        break;
 
 
1379
        default:
 
 
1380
            alienStatusPointer->BehaviourState = alienStatusPointer->Target ? ABS_Hunt : ABS_Wander;
 
 
1381
    }
 
 
1382
 
 
 
1383
    NPC_InitWanderData(&alienStatusPointer->wanderData);
 
 
1384
    alienStatusPointer->StateTimer = ALIEN_FAR_MOVE_TIME;    
 
 
1385
    alienStatusPointer->current_attack = NULL;
 
 
1386
}
 
 
1387
 
 
 
1388
/*----------------------Patrick 7/11/96-----------------------------
 
 
1389
This function is used to initialise a riff-loaded in alien.
 
 
1390
-------------------------------------------------------------------*/
 
 
1391
void InitAlienBehaviour(void* bhdata, STRATEGYBLOCK *sbPtr)
 
 
1392
{
 
 
1393
    TOOLS_DATA_ALIEN *toolsData = (TOOLS_DATA_ALIEN *)bhdata;
 
 
1394
    int i;
 
 
1395
 
 
 
1396
    /*
 
 
1397
    NB it is necessary that placed aliens are initialised without a
 
 
1398
    displayblock, otherwise far aliens will be re-initialised by
 
 
1399
    MakeAlienFar() to a hunting state instead of a wait state....*/            
 
 
1400
 
 
 
1401
    assert(!sbPtr->DisplayBlock);
 
 
1402
 
 
 
1403
    if(SinglePlayer == AvP.PlayMode)
 
 
1404
    {
 
 
1405
        for(i=0; i < SB_NAME_LENGTH; i++)
 
 
1406
            sbPtr->SBname[i] = toolsData->nameID[i];
 
 
1407
    }
 
 
1408
    else
 
 
1409
    {
 
 
1410
        //in a network game , generate a new sb name (so that it gets a reasonably low value)
 
 
1411
        AssignNewSBName(sbPtr);
 
 
1412
    }
 
 
1413
 
 
 
1414
    sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_DEFAULT);
 
 
1415
 
 
 
1416
    if(sbPtr->DynPtr)
 
 
1417
    {
 
 
1418
        DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
1419
        dynPtr->PrevPosition = dynPtr->Position = toolsData->position;
 
 
1420
        dynPtr->OrientEuler = toolsData->starteuler;
 
 
1421
        CreateEulerMatrix(&dynPtr->OrientEuler, &dynPtr->OrientMat);
 
 
1422
        TransposeMatrixCH(&dynPtr->OrientMat);      
 
 
1423
        sbPtr->DynPtr->ToppleForce = TOPPLE_FORCE_ALIEN;
 
 
1424
 
 
 
1425
        if(make_new_alien(sbPtr, toolsData->type, ((toolsData->start_inactive) ? ABS_Dormant : ABS_Wait), NULL))
 
 
1426
        {
 
 
1427
            ALIEN_STATUS_BLOCK * alienStatus = (ALIEN_STATUS_BLOCK *)sbPtr->dataptr;
 
 
1428
 
 
 
1429
            for(i=0; i < SB_NAME_LENGTH; i++)
 
 
1430
                alienStatus->death_target_ID[i] = toolsData->death_target_ID[i];
 
 
1431
        }
 
 
1432
    }
 
 
1433
    else
 
 
1434
    {
 
 
1435
        RemoveBehaviourStrategy(sbPtr);
 
 
1436
    }
 
 
1437
}
 
 
1438
 
 
 
1439
static int PlayerIsDeadAndNoLivingNetghosts()
 
 
1440
{
 
 
1441
    if(SinglePlayer == AvP.PlayMode)
 
 
1442
    {
 
 
1443
        //just need to check for the only player we have
 
 
1444
        return !PlayerStatus.Alive || Observer;
 
 
1445
    }
 
 
1446
    else
 
 
1447
    {
 
 
1448
        int sbIndex = 0;
 
 
1449
        //first check the host player
 
 
1450
 
 
 
1451
        if(PlayerStatus.Alive || Observer)
 
 
1452
            return 0;
 
 
1453
 
 
 
1454
        /* go through the strategy blocks looking for players*/
 
 
1455
        for(; sbIndex < NumActiveStBlocks; sbIndex++)
 
 
1456
        {
 
 
1457
            STRATEGYBLOCK *playerSbPtr = ActiveStBlockList[sbIndex];
 
 
1458
 
 
 
1459
            if(playerSbPtr->type == I_BehaviourNetGhost)
 
 
1460
            {
 
 
1461
                NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)playerSbPtr->dataptr;
 
 
1462
 
 
 
1463
                switch(ghostData->type)
 
 
1464
                {
 
 
1465
                    case I_BehaviourMarinePlayer:
 
 
1466
                    case I_BehaviourPredatorPlayer:
 
 
1467
                        //found a netghost of a player
 
 
1468
                        return 0;
 
 
1469
                    default:
 
 
1470
                    break;
 
 
1471
                }
 
 
1472
            }
 
 
1473
        }
 
 
1474
    }
 
 
1475
 
 
 
1476
//Dead, all dead.
 
 
1477
return 1;
 
 
1478
}
 
 
1479
 
 
 
1480
static int Alien_TargetFilter(STRATEGYBLOCK *candidate, const ALIEN_STATUS_BLOCK *alienStatusPointer)
 
 
1481
{
 
 
1482
    switch (candidate->type)
 
 
1483
    {
 
 
1484
        case I_BehaviourFlare:
 
 
1485
            return (!alienStatusPointer->Wounds && !(FastRandom() & 3)); // this could be a trap from marine bot or marine player
 
 
1486
        case I_BehaviourMarine:
 
 
1487
        case I_BehaviourMarinePlayer:
 
 
1488
        case I_BehaviourPredatorPlayer:
 
 
1489
        case I_BehaviourPredator:
 
 
1490
        case I_BehaviourAutoGun:
 
 
1491
        //case I_BehaviourAlien:
 
 
1492
        case I_BehaviourCorpse:
 
 
1493
            return 1;
 
 
1494
        case I_BehaviourPlacedLight:
 
 
1495
        {
 
 
1496
break;
 
 
1497
            if(Standard == alienStatusPointer->Type)
 
 
1498
            {
 
 
1499
                if(!candidate->maintainVisibility)
 
 
1500
                {
 
 
1501
                    return 0;
 
 
1502
                }
 
 
1503
                else
 
 
1504
                {
 
 
1505
                    PLACED_LIGHT_BEHAV_BLOCK* pl_bhv = (PLACED_LIGHT_BEHAV_BLOCK*)candidate->dataptr;
 
 
1506
 
 
 
1507
                    if(!candidate->maintainVisibility || candidate->DamageBlock.Indestructable) // valid anyway?
 
 
1508
                        return 0;
 
 
1509
                    else if(FastRandom() & 5)
 
 
1510
                        return ((Light_State_Broken != pl_bhv->state) && (Light_OnOff_Off != pl_bhv->on_off_state));
 
 
1511
                }
 
 
1512
            }
 
 
1513
            else
 
 
1514
            {
 
 
1515
                return 0;
 
 
1516
            }
 
 
1517
        }
 
 
1518
        case I_BehaviourNetGhost:
 
 
1519
        {
 
 
1520
            NETGHOSTDATABLOCK *dataptr = candidate->dataptr;
 
 
1521
 
 
 
1522
            switch (dataptr->type) 
 
 
1523
            {
 
 
1524
                case I_BehaviourMarinePlayer:
 
 
1525
                case I_BehaviourPredatorPlayer:
 
 
1526
                    return 1;
 
 
1527
                default:
 
 
1528
                    return 0;
 
 
1529
            }
 
 
1530
        }
 
 
1531
        default:
 
 
1532
        return 0;
 
 
1533
    }
 
 
1534
return 0;
 
 
1535
}
 
 
1536
 
 
 
1537
struct alien_targets
 
 
1538
{
 
 
1539
    int distance;
 
 
1540
    STRATEGYBLOCK * target;
 
 
1541
};
 
 
1542
 
 
 
1543
static int AlienHasPathToTarget(STRATEGYBLOCK *sbPtr) 
 
 
1544
{
 
 
1545
    ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
1546
 
 
 
1547
    return (alienStatusPointer->Target != NULL) ? ( NULL != GetNextModuleForLink_Core(sbPtr->containingModule->m_aimodule,
alienStatusPointer->Target->containingModule->m_aimodule, 4, 1, 1)) : 0;
 
 
1548
    //return (alienStatusPointer->Target != NULL) ? ( NULL != GetNextModuleForLink_Core(sbPtr->containingModule->m_aimodule,
alienStatusPointer->Target->containingModule->m_aimodule, 7, 0, 1)) : 0;
 
 
1549
}
 
 
1550
 
 
 
1551
static int sort_targets(const void *void_a, const void *void_b)
 
 
1552
{
 
 
1553
    const struct alien_targets * a = void_a;
 
 
1554
    const struct alien_targets * b = void_b;
 
 
1555
 
 
 
1556
    return (a->distance < b->distance) ? -1 : (a->distance > b->distance);
 
 
1557
}
 
 
1558
 
 
 
1559
static STRATEGYBLOCK *Alien_GetNewTarget(const STRATEGYBLOCK *sbptr)
 
 
1560
{
 
 
1561
    struct alien_targets Targets[5] = { {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL}, {0, NULL} };
 
 
1562
    int neardist = ONE_FIXED;
 
 
1563
    STRATEGYBLOCK *nearest = NULL;
 
 
1564
    //MODULE *dmod = ModuleFromPosition(&sbptr->DynPtr->Position, PlayerStatus.sbptr->containingModule);
 
 
1565
    //MODULE *dmod = ModuleFromPosition(&sbptr->DynPtr->Position, NULL);
 
 
1566
    ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(sbptr->dataptr);    
 
 
1567
    int a;
 
 
1568
    int i = 0;
 
 
1569
    int wraps = 0;
 
 
1570
    const VECTORCH *alienpos = &sbptr->DynPtr->Position;
 
 
1571
 
 
 
1572
    for (a = 0; a < NumActiveStBlocks; a++)
 
 
1573
    {
 
 
1574
        STRATEGYBLOCK *candidate = ActiveStBlockList[a];
 
 
1575
 
 
 
1576
        if (Alien_TargetFilter(candidate, alienStatusPointer))
 
 
1577
        {
 
 
1578
            VECTORCH offset;
 
 
1579
 
 
 
1580
            offset.vx = alienpos->vx - candidate->DynPtr->Position.vx;
 
 
1581
            offset.vy = alienpos->vy - candidate->DynPtr->Position.vy;
 
 
1582
            offset.vz = alienpos->vz - candidate->DynPtr->Position.vz;
 
 
1583
 
 
 
1584
            int dist = Approximate3dMagnitude(&offset);
 
 
1585
 
 
 
1586
            if (dist < neardist)
 
 
1587
            {
 
 
1588
                //if (!NPC_IsDead(candidate) && AlienHasPathToTarget(sbptr) && IsModuleVisibleFromModule(dmod, candidate->containingModule))
 
 
1589
                if (!NPC_IsDead(candidate))// && IsModuleVisibleFromModule(dmod, candidate->containingModule))
 
 
1590
                {
 
 
1591
                    nearest = candidate;
 
 
1592
                    neardist = dist;
 
 
1593
 
 
 
1594
                    if(4 == i)
 
 
1595
                    {
 
 
1596
                        i = 0;
 
 
1597
                        wraps = 1;
 
 
1598
                    }
 
 
1599
 
 
 
1600
                    Targets[i].target = candidate;
 
 
1601
                    Targets[i].distance = dist;
 
 
1602
                    i++;
 
 
1603
                }
 
 
1604
            }
 
 
1605
        }
 
 
1606
    }
 
 
1607
 
 
 
1608
 
 
 
1609
return nearest;
 
 
1610
    if(nearest)
 
 
1611
    {
 
 
1612
        int numberofnear_marines = 0;
 
 
1613
        int numberofnear_aliens = 0;
 
 
1614
        int numberofnear_predators = 0;
 
 
1615
        int hiding_in_waiting = 0;
 
 
1616
 
 
 
1617
        if (!alienStatusPointer->CurrentLightAtAlien)
 
 
1618
            hiding_in_waiting = !DynamicObjectIsMoving(sbptr->DynPtr);
 
 
1619
 
 
 
1620
        switch (nearest->type)
 
 
1621
        {
 
 
1622
            case I_BehaviourMarine:
 
 
1623
            case I_BehaviourMarinePlayer:
 
 
1624
            case I_BehaviourPredator:
 
 
1625
            case I_BehaviourPredatorPlayer:
 
 
1626
            {
 
 
1627
                if(neardist < ALIEN_POUNCE_MAXRANGE)
 
 
1628
                {
 
 
1629
                    if (alienStatusPointer->Wounds && (alienStatusPointer->Type == Standard))
 
 
1630
                    {
 
 
1631
                        alienStatusPointer->BehaviourState = ABS_Retreat;
 
 
1632
                        return NULL;
 
 
1633
                    }
 
 
1634
 
 
 
1635
                    return nearest;
 
 
1636
                }
 
 
1637
            }
 
 
1638
            default:
 
 
1639
            break;
 
 
1640
        }
 
 
1641
 
 
 
1642
        if (wraps)
 
 
1643
            i = 5;
 
 
1644
 
 
 
1645
        qsort(Targets, 5, sizeof(struct alien_targets), sort_targets);
 
 
1646
 
 
 
1647
        for (a = 0; a < i; a++)
 
 
1648
        {
 
 
1649
            if(NULL == Targets[a].target || (Targets[a].target == nearest))
 
 
1650
                continue;
 
 
1651
 
 
 
1652
            //printf("TARGETS type %d distance %d\n", Targets[a].target->type, Targets[a].distance);
 
 
1653
 
 
 
1654
            //if (alienStatusPointer->Wounds)
 
 
1655
            STRATEGYBLOCK *target = Targets[a].target;
 
 
1656
 
 
 
1657
            switch(target->type)
 
 
1658
            {
 
 
1659
                case I_BehaviourMarine:
 
 
1660
                case I_BehaviourMarinePlayer:
 
 
1661
                    numberofnear_marines++;
 
 
1662
 
 
 
1663
                    if (Targets[a].distance < ALIEN_POUNCE_MAXRANGE)
 
 
1664
                    {
 
 
1665
                        //if(hiding_in_waiting)
 
 
1666
                            return Targets[a].target;
 
 
1667
                    }
 
 
1668
                break;
 
 
1669
                case I_BehaviourPredatorPlayer:
 
 
1670
                case I_BehaviourPredator:
 
 
1671
                    numberofnear_predators++;
 
 
1672
 
 
 
1673
                    if (Targets[a].distance < ALIEN_POUNCE_MAXRANGE)
 
 
1674
                    {
 
 
1675
                        //if(hiding_in_waiting)
 
 
1676
                            return Targets[a].target;
 
 
1677
                    }
 
 
1678
                break;
 
 
1679
                case I_BehaviourPlacedLight:
 
 
1680
                    if(alienStatusPointer->CurrentLightAtAlien || alienStatusPointer->Wounds)
 
 
1681
                        return Targets[a].target;
 
 
1682
                break;
 
 
1683
                case I_BehaviourFlare:
 
 
1684
                {
 
 
1685
                    if (!alienStatusPointer->Wounds && !(FastRandom() & 3)) // this could be a trap from marine bot or marine player
 
 
1686
                    {
 
 
1687
                        alienStatusPointer->IAmCrouched = 0;
 
 
1688
                        return Targets[a].target;
 
 
1689
                    }
 
 
1690
                }
 
 
1691
                break;
 
 
1692
                case I_BehaviourAlien:
 
 
1693
                {
 
 
1694
                    ALIEN_STATUS_BLOCK *alien_friend = (ALIEN_STATUS_BLOCK *)(target->dataptr);    
 
 
1695
                    numberofnear_aliens++;
 
 
1696
 
 
 
1697
                    if(numberofnear_aliens > 3) // we have a cluster of aliens let's give alien cluster a target
 
 
1698
                    {
 
 
1699
                        STRATEGYBLOCK *chossen_target = NULL;
 
 
1700
                        neardist = ONE_FIXED;
 
 
1701
                        int x = 0;
 
 
1702
                        for (; x < NumActiveStBlocks; x++)
 
 
1703
                        {
 
 
1704
                            STRATEGYBLOCK *candidate = ActiveStBlockList[x];
 
 
1705
 
 
 
1706
                            if ((candidate != sbptr) && candidate->DynPtr)
 
 
1707
                            {
 
 
1708
                                switch (candidate->type)
 
 
1709
                                {
 
 
1710
                                    case I_BehaviourMarinePlayer:
 
 
1711
                                    case I_BehaviourPredatorPlayer:
 
 
1712
                                    case I_BehaviourMarine:
 
 
1713
                                    case I_BehaviourPredator:
 
 
1714
                                    {
 
 
1715
                                        VECTORCH offset;
 
 
1716
 
 
 
1717
                                        offset.vx = alienpos->vx - candidate->DynPtr->Position.vx;
 
 
1718
                                        offset.vy = alienpos->vy - candidate->DynPtr->Position.vy;
 
 
1719
                                        offset.vz = alienpos->vz - candidate->DynPtr->Position.vz;
 
 
1720
 
 
 
1721
                                        int dist = Approximate3dMagnitude(&offset);
 
 
1722
 
 
 
1723
                                        if (dist < neardist) 
 
 
1724
                                        {
 
 
1725
                                            if (!NPC_IsDead(candidate))// && IsModuleVisibleFromModule(dmod, candidate->containingModule)) 
 
 
1726
                                            {
 
 
1727
                                                chossen_target = candidate;
 
 
1728
                                                neardist = dist;
 
 
1729
                                            }
 
 
1730
                                        }
 
 
1731
                                    }
 
 
1732
                                    default:
 
 
1733
                                    break;
 
 
1734
                                }
 
 
1735
                            }
 
 
1736
                        }
 
 
1737
 
 
 
1738
                        if(chossen_target)
 
 
1739
                        {
 
 
1740
                            x=0;
 
 
1741
                            for (; x < i; x++)
 
 
1742
                            {
 
 
1743
                                ALIEN_STATUS_BLOCK *alien_friend = (ALIEN_STATUS_BLOCK *)(Targets[x].target->dataptr);    
 
 
1744
                                alien_friend->Target = chossen_target;
 
 
1745
                                //Targets[i].target
 
 
1746
                            }
 
 
1747
                            puts("realsing cluster");
 
 
1748
                        }
 
 
1749
 
 
 
1750
                        return nearest;
 
 
1751
                    }
 
 
1752
 
 
 
1753
                    //if(Targets[a].target->DynPtr->OrientMat.mat22 < 63000)
 
 
1754
                    if (!alien_friend->CurrentLightAtAlien && (NULL == alien_friend->Target))
 
 
1755
                    //if (NULL == alien_friend->Target)
 
 
1756
                    {
 
 
1757
                        // let's join up
 
 
1758
                        puts("let's join up");
 
 
1759
                        return Targets[a].target;
 
 
1760
                    }
 
 
1761
 
 
 
1762
                    if (alien_friend->Target)
 
 
1763
                    {
 
 
1764
                        switch (alien_friend->Target->type)
 
 
1765
                        {
 
 
1766
                            case I_BehaviourMarinePlayer:
 
 
1767
                            case I_BehaviourPredatorPlayer:
 
 
1768
                            case I_BehaviourPredator:
 
 
1769
                            case I_BehaviourAutoGun:
 
 
1770
                                return Targets[a].target;
 
 
1771
                            default:
 
 
1772
                            break;
 
 
1773
                        }
 
 
1774
                    }
 
 
1775
                }
 
 
1776
                default:
 
 
1777
                break;
 
 
1778
            }
 
 
1779
        }
 
 
1780
 
 
 
1781
        if(1 == numberofnear_aliens)
 
 
1782
        {
 
 
1783
            if((numberofnear_marines > 2) || numberofnear_predators)
 
 
1784
            {
 
 
1785
                alienStatusPointer->BehaviourState = ABS_Retreat;
 
 
1786
                return NULL;
 
 
1787
            }
 
 
1788
        }
 
 
1789
        else if (numberofnear_aliens > 2)
 
 
1790
        {
 
 
1791
            //if(I_BehaviourPlacedLight == nearest->type)
 
 
1792
            a = 0;
 
 
1793
            for (; a < i; a++)
 
 
1794
            {
 
 
1795
                switch(Targets[a].target->type)
 
 
1796
                {
 
 
1797
                    case I_BehaviourPlacedLight:
 
 
1798
                        return Targets[a].target;
 
 
1799
                    default:
 
 
1800
                    break;
 
 
1801
                }
 
 
1802
            }
 
 
1803
        }
 
 
1804
        else if (numberofnear_predators && (numberofnear_aliens < 2))
 
 
1805
        {
 
 
1806
        }
 
 
1807
    }
 
 
1808
 
 
 
1809
return nearest;
 
 
1810
}
 
 
1811
 
 
 
1812
/*--------------------Patrick 27/1/97----------------------
 
 
1813
  This function is used by the various far alien behaviour 
 
 
1814
  functions to move an alien NPC: it decides whether and how 
 
 
1815
  to move an alien into a given target.
 
 
1816
 
 
 
1817
  2/7/97 extra bit:
 
 
1818
  If a location fails, we flip the y-orientation of the npc,
 
 
1819
  so that wandering behaviour can find a new path;
 
 
1820
  ----------------------------------------------------------*/
 
 
1821
 
 
 
1822
static int ProcessFarAlienTargetModule(STRATEGYBLOCK *sbPtr, AIMODULE* targetModule)
 
 
1823
{
 
 
1824
    VECTORCH oldPos = sbPtr->DynPtr->Position;
 
 
1825
 
 
 
1826
    /* get the target module's status, and decide what to do */
 
 
1827
    switch(GetTargetAIModuleStatus(sbPtr, targetModule, 1))
 
 
1828
    {
 
 
1829
        case NPCTM_NoEntryPoint:
 
 
1830
        {
 
 
1831
            /* do nothing: can't get in. */
 
 
1832
            FarNpc_FlipAround(sbPtr);
 
 
1833
            //entryPointFailures++;
 
 
1834
        }
 
 
1835
        break;
 
 
1836
        case NPCTM_NormalRoom:
 
 
1837
        case NPCTM_LiftDoorOpen:
 
 
1838
        case NPCTM_ProxDoorOpen:
 
 
1839
        case NPCTM_AirDuct:
 
 
1840
        case NPCTM_SecurityDoorOpen:
 
 
1841
            /* locate to target    */
 
 
1842
            LocateFarNPCInAIModule(sbPtr, targetModule);
 
 
1843
        break;
 
 
1844
        case NPCTM_ProxDoorNotOpen:
 
 
1845
        {
 
 
1846
            MODULE *renderModule = *(targetModule->m_module_ptrs);
 
 
1847
            /* trigger the door, and set timer to quick so we can catch the door when it's open */
 
 
1848
            ((PROXDOOR_BEHAV_BLOCK *)renderModule->m_sbptr->dataptr)->alienTrigger = 1;
 
 
1849
        break;
 
 
1850
        }
 
 
1851
        case NPCTM_LiftTeleport: /* do nothing: aliens can't use lifts */
 
 
1852
        case NPCTM_LiftDoorNotOpen:
 
 
1853
        case NPCTM_SecurityDoorNotOpen:
 
 
1854
            /*  do nothing - well, there's nothing we can do, really*/
 
 
1855
            FarNpc_FlipAround(sbPtr);
 
 
1856
           break;
 
 
1857
        default:
 
 
1858
        {
 
 
1859
            assert(1==0);
 
 
1860
        }
 
 
1861
    }
 
 
1862
 
 
 
1863
    /* Now, deduce how far it's moved... */
 
 
1864
    oldPos.vx -= sbPtr->DynPtr->Position.vx;
 
 
1865
    oldPos.vy -= sbPtr->DynPtr->Position.vy;
 
 
1866
    oldPos.vz -= sbPtr->DynPtr->Position.vz;
 
 
1867
 
 
 
1868
    {
 
 
1869
        int distance = Approximate3dMagnitude(&oldPos);
 
 
1870
        /* How long? */
 
 
1871
 
 
 
1872
        return !distance ? ALIEN_FAR_MOVE_TIME : DIV_FIXED(distance, (ALIEN_FORWARDVELOCITY >> 1));
 
 
1873
    }
 
 
1874
}
 
 
1875
 
 
 
1876
void Alien_Awaken(STRATEGYBLOCK *sbPtr) 
 
 
1877
{
 
 
1878
    ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);        
 
 
1879
 
 
 
1880
    alienStatusPointer->BehaviourState = ABS_Awakening;
 
 
1881
    SetAlienShapeAnimSequence_Core(sbPtr, HMSQT_AlienStand, ASSS_Unfurl, -1, (ONE_FIXED>>2));
 
 
1882
    alienStatusPointer->HModelController.LoopAfterTweening = 0;
 
 
1883
}
 
 
1884
 
 
 
1885
/*----------------------Patrick 7/11/96-----------------------------
 
 
1886
AI alien behaviour execution shell:
 
 
1887
 
 
 
1888
1. patch to trap aliens who's current module is not set (and set it).
 
 
1889
2. call the visibility checking function.
 
 
1890
3. select either near or far behaviour functions.
 
 
1891
 
 
 
1892
NB the visibility checking function initialises near/far behaviour and
 
 
1893
allocates/deallocates displayblock based on changes in visibility
 
 
1894
for the alien's module.  This will, in due course, be invoked by a
 
 
1895
call back function from the module handler.
 
 
1896
--------------------------------------------------------------------*/
 
 
1897
 
 
 
1898
int AlienIsAwareOfTarget(STRATEGYBLOCK *sbPtr)
 
 
1899
{
 
 
1900
    ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);
 
 
1901
 
 
 
1902
    if (alienStatusPointer->Target != NULL)
 
 
1903
    {
 
 
1904
        assert(alienStatusPointer->Target->containingModule);
 
 
1905
 
 
 
1906
        switch(alienStatusPointer->Target->type)
 
 
1907
        {
 
 
1908
            case I_BehaviourMarinePlayer:
 
 
1909
            case I_BehaviourPredatorPlayer:
 
 
1910
                //return PlayerStatus.Alive;
 
 
1911
            default:
 
 
1912
                return IsModuleVisibleFromModule(sbPtr->containingModule, alienStatusPointer->Target->containingModule);
 
 
1913
        }
 
 
1914
    }
 
 
1915
 
 
 
1916
return 0;
 
 
1917
}
 
 
1918
 
 
 
1919
/*
 
 
1920
        if(alienStatusPointer->Type == Standard)
 
 
1921
        {
 
 
1922
            alienStatusPointer->CurrentLightAtAlien = LightIntensityAtPoint(&sbPtr->DynPtr->Position);
 
 
1923
 
 
 
1924
            printf("alienStatusPointer->BehaviourState %d\n", alienStatusPointer->BehaviourState);
 
 
1925
 
 
 
1926
            switch(alienStatusPointer->BehaviourState)
 
 
1927
            {
 
 
1928
                case ABS_Approach:
 
 
1929
                {
 
 
1930
                    if (!alienStatusPointer->CurrentLightAtAlien && alienStatusPointer->IAmCrouched &&
(sbPtr->DynPtr->OrientMat.mat22 < 63000))
 
 
1931
                    {
 
 
1932
                        switch(alienStatusPointer->Target->type)
 
 
1933
                        {
 
 
1934
                            case I_BehaviourAlien:
 
 
1935
                            {
 
 
1936
                                int distance_to_target = VectorDistance(&sbPtr->DynPtr->Position,
&alienStatusPointer->Target->DynPtr->Position);
 
 
1937
 
 
 
1938
                                if(distance_to_target < ALIEN_POUNCE_MAXRANGE)
 
 
1939
                                {
 
 
1940
                                    alienStatusPointer->BehaviourState = ABS_Wait;
 
 
1941
                                }
 
 
1942
                            }
 
 
1943
                            break;
 
 
1944
                            case I_BehaviourPlacedLight:
 
 
1945
                            {
 
 
1946
                                alienStatusPointer->BehaviourState = ABS_Wait;
 
 
1947
                                //alienStatusPointer->Target = NULL;
 
 
1948
                            }
 
 
1949
                            break;
 
 
1950
                            default:
 
 
1951
                            {
 
 
1952
                                int distance_to_target = VectorDistance(&sbPtr->DynPtr->Position,
&alienStatusPointer->Target->DynPtr->Position);
 
 
1953
                                int target_previous_distance = VectorDistance(&alienStatusPointer->Target->DynPtr->PrevPosition,
&sbPtr->DynPtr->Position);
 
 
1954
                                printf("hunt Distance to Target %d\n", distance_to_target);
 
 
1955
 
 
 
1956
                                if(target_previous_distance > distance_to_target)
 
 
1957
                                {
 
 
1958
                                    alienStatusPointer->BehaviourState = ABS_Wait;
 
 
1959
                                }
 
 
1960
                                else
 
 
1961
                                {
 
 
1962
                                    if((distance_to_target - target_previous_distance) > ALIEN_POUNCE_MAXRANGE*2)
 
 
1963
                                        alienStatusPointer->BehaviourState = ABS_Approach;
 
 
1964
                                    else
 
 
1965
                                        alienStatusPointer->BehaviourState = ((FastRandom() & 65535) > 20000) ? ABS_Approach : ABS_Wait;
 
 
1966
                                }
 
 
1967
                            }
 
 
1968
                        }
 
 
1969
                    }
 
 
1970
                }
 
 
1971
                break;
 
 
1972
                case ABS_Wait:
 
 
1973
                {
 
 
1974
                    if(alienStatusPointer->CurrentLightAtAlien)
 
 
1975
                    {
 
 
1976
                        if(alienStatusPointer->Target)
 
 
1977
                        {
 
 
1978
                            int distance_to_target = VectorDistance(&sbPtr->DynPtr->Position,
&alienStatusPointer->Target->DynPtr->Position);
 
 
1979
                            printf("wait Distance to Target %d\n", distance_to_target);
 
 
1980
 
 
 
1981
                            if(distance_to_target < ALIEN_ATTACKDISTANCE_MAX)
 
 
1982
                            {
 
 
1983
                                alienStatusPointer->BehaviourState = ABS_Attack;
 
 
1984
                            }
 
 
1985
                            else
 
 
1986
                            {
 
 
1987
                                if ((FastRandom() & 65535) < 24000)
 
 
1988
                                {
 
 
1989
                                    alienStatusPointer->BehaviourState = ABS_Avoidance;
 
 
1990
                                    alienStatusPointer->StateTimer = NPC_AVOIDTIME;
 
 
1991
                                }
 
 
1992
                                else
 
 
1993
                                {
 
 
1994
                                    alienStatusPointer->BehaviourState = ABS_Retreat;
 
 
1995
                                }
 
 
1996
                            }
 
 
1997
                        }
 
 
1998
                        else
 
 
1999
                        {
 
 
2000
                            alienStatusPointer->BehaviourState = ABS_Avoidance;
 
 
2001
                            alienStatusPointer->StateTimer = NPC_AVOIDTIME;
 
 
2002
                        }
 
 
2003
                    }
 
 
2004
                    else
 
 
2005
                    {
 
 
2006
                        int distance_to_target = VectorDistance(&sbPtr->DynPtr->Position, &alienStatusPointer->Target->DynPtr->Position);
 
 
2007
                        printf("Distance to Target %d\n", distance_to_target);
 
 
2008
 
 
 
2009
                        if (distance_to_target < ALIEN_POUNCE_MAXRANGE)
 
 
2010
                        {
 
 
2011
                            if(distance_to_target < ALIEN_ATTACKDISTANCE_MAX)
 
 
2012
                            {
 
 
2013
                                alienStatusPointer->BehaviourState = ABS_Attack;
 
 
2014
                            }
 
 
2015
                            else
 
 
2016
                            {
 
 
2017
                                //if ((FastRandom() & 127) < 80) AlienRandomHiss(sbPtr);
 
 
2018
                            }
 
 
2019
                        }
 
 
2020
                        else
 
 
2021
                        {
 
 
2022
                            int target_previous_distance = VectorDistance(&alienStatusPointer->Target->DynPtr->PrevPosition,
&sbPtr->DynPtr->Position);
 
 
2023
 
 
 
2024
                            if(target_previous_distance < distance_to_target)
 
 
2025
                            {
 
 
2026
                                alienStatusPointer->BehaviourState = ABS_Wait;
 
 
2027
                            }
 
 
2028
                            else
 
 
2029
                            {
 
 
2030
                                alienStatusPointer->BehaviourState = ((FastRandom() & 65535) < 25000) ? ABS_Approach : ABS_Wait;
 
 
2031
                            }
 
 
2032
                        }
 
 
2033
                    }
 
 
2034
                }
 
 
2035
                break;
 
 
2036
                case ABS_Wander:
 
 
2037
                    if (!alienStatusPointer->CurrentLightAtAlien && alienStatusPointer->IAmCrouched &&
(sbPtr->DynPtr->OrientMat.mat22 < 63000))
 
 
2038
                            alienStatusPointer->BehaviourState = ABS_Wait;
 
 
2039
                default:
 
 
2040
                break;
 
 
2041
            }
 
 
2042
        }
 
 
2043
        */
 
 
2044
 
 
 
2045
static void NearAlienBehaviour(STRATEGYBLOCK *sbPtr)
 
 
2046
{
 
 
2047
    ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
2048
    DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
2049
 
 
 
2050
printf("alienStatusPointer->BehaviourState %d %s\n", alienStatusPointer->BehaviourState, (sbPtr->DisplayBlock ? "near" :
"far")); //jadda
 
 
2051
 
 
 
2052
    if(ABS_Wait != alienStatusPointer->BehaviourState)
 
 
2053
        InitWaypointSystem(alienStatusPointer->EnableWaypoints);
 
 
2054
 
 
 
2055
    if (NULL == alienStatusPointer->current_attack)
 
 
2056
        AlienHandleMovingAnimation(sbPtr);
 
 
2057
 
 
 
2058
    switch (alienStatusPointer->BehaviourState)
 
 
2059
    {
 
 
2060
        case ABS_Approach:
 
 
2061
        {
 
 
2062
            VECTORCH targetPos;
 
 
2063
            int can_see_target;
 
 
2064
 
 
 
2065
            if (NULL == alienStatusPointer->Target)
 
 
2066
            {
 
 
2067
                alienStatusPointer->BehaviourState = ABS_Hunt;
 
 
2068
                alienStatusPointer->StateTimer = ALIEN_NEARWAITTIME;
 
 
2069
                InitWaypointManager(&alienStatusPointer->waypointManager);
 
 
2070
                NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
2071
                break;
 
 
2072
            }
 
 
2073
 
 
 
2074
            if(NPCCanSeeTarget(sbPtr, alienStatusPointer->Target))
 
 
2075
            {
 
 
2076
                puts("can see target");
 
 
2077
                can_see_target = 1;
 
 
2078
            }
 
 
2079
            else
 
 
2080
            {
 
 
2081
                can_see_target = 0;
 
 
2082
                puts("cannot see target");
 
 
2083
 
 
 
2084
                if(dynPtr->OrientMat.mat22 < 63000)
 
 
2085
                {
 
 
2086
                    puts("i am on wall");
 
 
2087
                }
 
 
2088
 
 
 
2089
                if(!DynamicObjectIsMoving(dynPtr))
 
 
2090
                {
 
 
2091
                    puts("Target is still");
 
 
2092
 
 
 
2093
                }
 
 
2094
 
 
 
2095
                switch(alienStatusPointer->Target->type)
 
 
2096
                {
 
 
2097
                    case I_BehaviourMarine:
 
 
2098
                    case I_BehaviourMarinePlayer:
 
 
2099
                    default:
 
 
2100
                    break;
 
 
2101
                }
 
 
2102
 
 
 
2103
                STRATEGYBLOCK *new_target = Alien_GetNewTarget(sbPtr);
 
 
2104
 
 
 
2105
if(0)
 
 
2106
                if((NULL != new_target) && (new_target != alienStatusPointer->Target))
 
 
2107
                {
 
 
2108
                    switch (new_target->type)
 
 
2109
                    {
 
 
2110
                        case I_BehaviourMarine:
 
 
2111
                        case I_BehaviourMarinePlayer:
 
 
2112
                        case I_BehaviourFlare:
 
 
2113
                            alienStatusPointer->Target = new_target;
 
 
2114
                        break;
 
 
2115
                        case I_BehaviourPlacedLight:
 
 
2116
                        {
 
 
2117
                            if(Standard == alienStatusPointer->Type)
 
 
2118
                            {
 
 
2119
                                if(!new_target->maintainVisibility)
 
 
2120
                                {
 
 
2121
                                }
 
 
2122
                                else
 
 
2123
                                {
 
 
2124
                                    PLACED_LIGHT_BEHAV_BLOCK* pl_bhv = (PLACED_LIGHT_BEHAV_BLOCK*)new_target->dataptr;
 
 
2125
 
 
 
2126
                                    if(!new_target->maintainVisibility || new_target->DamageBlock.Indestructable) // valid anyway?
 
 
2127
                                    {
 
 
2128
                                    }
 
 
2129
                                    else if((Light_State_Broken != pl_bhv->state) && (Light_OnOff_Off != pl_bhv->on_off_state))
 
 
2130
                                    {
 
 
2131
                                        alienStatusPointer->Target = new_target;
 
 
2132
                                        puts("NEW ligth_lamp TAGET");
 
 
2133
                                    }
 
 
2134
                                }
 
 
2135
                            }
 
 
2136
                        }
 
 
2137
                        default:
 
 
2138
                        break;
 
 
2139
                    }
 
 
2140
                }
 
 
2141
                //else puts("BAD TARGEEEEEEEEEEEE");
 
 
2142
            }
 
 
2143
 
 
 
2144
            if ((alienStatusPointer->Target->DynPtr->Position.vy - dynPtr->Position.vy) < -2000)
 
 
2145
            {
 
 
2146
                puts("SMAE POS");
 
 
2147
                //sleep(1);
 
 
2148
    //alienStatusPointer->BehaviourState = ABS_Wait;
 
 
2149
                    //return;
 
 
2150
            }
 
 
2151
//if(0)
 
 
2152
        { // test
 
 
2153
            VECTORCH orientationDirn;
 
 
2154
            int correctlyOrientated = 0;
 
 
2155
            orientationDirn.vx = alienStatusPointer->Target->DynPtr->Position.vx - sbPtr->DynPtr->Position.vx;
 
 
2156
            orientationDirn.vy = 0;
 
 
2157
            orientationDirn.vz = alienStatusPointer->Target->DynPtr->Position.vz - sbPtr->DynPtr->Position.vz;
 
 
2158
            correctlyOrientated = NPCOrientateToVector2(sbPtr, &orientationDirn, NPC_TURNRATE);
 
 
2159
 
 
 
2160
            //if (correctlyOrientated)
 
 
2161
            {
 
 
2162
                VECTORCH sight_vec;
 
 
2163
                SECTION_DATA *head_sec = GetThisSectionData(alienStatusPointer->HModelController.section_data, "head");
 
 
2164
                assert(head_sec);
 
 
2165
 
 
 
2166
                sight_vec.vx = sbPtr->DynPtr->OrientMat.mat31;
 
 
2167
                sight_vec.vy = sbPtr->DynPtr->OrientMat.mat32;
 
 
2168
                sight_vec.vz = sbPtr->DynPtr->OrientMat.mat33;
 
 
2169
 
 
 
2170
                FindPolygonInLineOfSight(&sight_vec, &head_sec->World_Offset, 0, sbPtr->DisplayBlock);
 
 
2171
 
 
 
2172
                if(LOS_ObjectHitPtr)
 
 
2173
                {
 
 
2174
                    if((NULL == LOS_ObjectHitPtr->ObStrategyBlock) || (LOS_ObjectHitPtr->ObStrategyBlock->DisplayBlock &&
LOS_ObjectHitPtr->ObStrategyBlock->DisplayBlock->Module))
 
 
2175
                    {
 
 
2176
                        if (LOS_Lambda < 1500)
 
 
2177
                        {
 
 
2178
                            puts("near is modeule");
 
 
2179
 
 
 
2180
                            if(alienStatusPointer->CanClimb)
 
 
2181
                            {
 
 
2182
                                alienStatusPointer->IAmCrouched = 1;
 
 
2183
        //if(0)
 
 
2184
            {
 
 
2185
                int approachingAirDuct = 0;
 
 
2186
                NPCGetMovementTarget(sbPtr, alienStatusPointer->Target, &targetPos, &approachingAirDuct, 1);
 
 
2187
 
 
 
2188
                /* use standard NPC direction finding... */
 
 
2189
                VECTORCH velocityDirection = {0,0,0};
 
 
2190
 
 
 
2191
                NPCGetMovementDirection(sbPtr, &velocityDirection, &targetPos, (alienStatusPointer->EnableWaypoints ?
&alienStatusPointer->waypointManager : NULL));
 
 
2192
 
 
 
2193
                NPCSetVelocity(sbPtr, &velocityDirection, alienStatusPointer->MaxSpeed);
 
 
2194
                alienStatusPointer->CurveTimeOut = 0; /* forces curve init next time curving is used */
 
 
2195
                return;
 
 
2196
            }
 
 
2197
                            }
 
 
2198
                        }
 
 
2199
                        else
 
 
2200
                        {
 
 
2201
                            puts("far is modeule");
 
 
2202
                        }
 
 
2203
                    }
 
 
2204
                    if(NULL != LOS_ObjectHitPtr->ObStrategyBlock)
 
 
2205
                    {
 
 
2206
                    if(alienStatusPointer->Target == LOS_ObjectHitPtr->ObStrategyBlock)
 
 
2207
                    {
 
 
2208
                        if (LOS_Lambda < ALIEN_POUNCE_STARTMAXRANGE)
 
 
2209
                            ;
 
 
2210
                    puts("OH YES");
 
 
2211
                    //sleep(1);
 
 
2212
                    }
 
 
2213
 
 
 
2214
                    }
 
 
2215
                }
 
 
2216
            }
 
 
2217
        }
 
 
2218
 
 
 
2219
            int distance_to_target = VectorDistance(&dynPtr->Position, &alienStatusPointer->Target->DynPtr->Position);
 
 
2220
            int target_previous_distance = VectorDistance(&alienStatusPointer->Target->DynPtr->PrevPosition, &dynPtr->Position);
 
 
2221
 
 
 
2222
            //dynPtr->UseStandardGravity = !AlienIsAbleToClimb(sbPtr);
 
 
2223
 
 
 
2224
            /* target acquisition ? */
 
 
2225
            /* Never curve in a waypoint module, you might hurt yourself. */
 
 
2226
            if((distance_to_target < ALIEN_CURVETOPLAYERDIST) && (NULL == sbPtr->containingModule->m_aimodule->m_waypoints))
 
 
2227
            {
 
 
2228
                GetTargetingPointOfObject_Far(alienStatusPointer->Target, &targetPos);
 
 
2229
 
 
 
2230
                //printf("curving alien \n");
 
 
2231
                /* translate target into alien's local space */
 
 
2232
 
 
 
2233
                {
 
 
2234
                    MATRIXCH toLocalSpaceMatrix = dynPtr->OrientMat;
 
 
2235
                    TransposeMatrixCH(&toLocalSpaceMatrix);
 
 
2236
 
 
 
2237
                    targetPos.vx -= dynPtr->Position.vx;
 
 
2238
                    targetPos.vy -= dynPtr->Position.vy;
 
 
2239
                    targetPos.vz -= dynPtr->Position.vz;
 
 
2240
                    RotateVector(&targetPos, &toLocalSpaceMatrix);
 
 
2241
                }
 
 
2242
 
 
 
2243
                /* tracking movement */
 
 
2244
                int distanceToTarget = Magnitude(&targetPos);
 
 
2245
 
 
 
2246
                if (dynPtr->IsInContactWithFloor)
 
 
2247
                {
 
 
2248
                    int offset;
 
 
2249
 
 
 
2250
                    if (alienStatusPointer->CurveTimeOut <= 0)
 
 
2251
                    {
 
 
2252
                        alienStatusPointer->CurveLength = distanceToTarget;
 
 
2253
                        alienStatusPointer->CurveRadius = ((FastRandom() & 16383) - 8192) * 2;
 
 
2254
                        alienStatusPointer->CurveTimeOut= ONE_FIXED * 3;
 
 
2255
                    }
 
 
2256
                    else
 
 
2257
                        alienStatusPointer->CurveTimeOut -= NormalFrameTime;
 
 
2258
 
 
 
2259
                    offset = MUL_FIXED(alienStatusPointer->CurveRadius, GetCos((1024*(distanceToTarget)/alienStatusPointer->CurveLength)&4095));
 
 
2260
 
 
 
2261
                    dynPtr->LinVelocity.vx = 
 
 
2262
                        WideMulNarrowDiv(alienStatusPointer->MaxSpeed, targetPos.vx, distanceToTarget)
 
 
2263
                        -
 
 
2264
                        WideMulNarrowDiv(offset, targetPos.vz, distanceToTarget);
 
 
2265
 
 
 
2266
                    dynPtr->LinVelocity.vz =
 
 
2267
                        WideMulNarrowDiv ( alienStatusPointer->MaxSpeed, targetPos.vz, distanceToTarget)
 
 
2268
                        +
 
 
2269
                        WideMulNarrowDiv ( offset, targetPos.vx, distanceToTarget);
 
 
2270
 
 
 
2271
                    if (!dynPtr->UseStandardGravity && (sbPtr->containingModule == PlayerStatus.sbptr->containingModule))
 
 
2272
                    {
 
 
2273
                        //VECTORCH velocityDirection=dynPtr->LinVelocity;
 
 
2274
                        VECTORCH velocityDirection;
 
 
2275
                        GetTargetingPointOfObject_Far(alienStatusPointer->Target, &velocityDirection);
 
 
2276
                        velocityDirection.vx -= dynPtr->Position.vx;
 
 
2277
                        velocityDirection.vy -= dynPtr->Position.vy;
 
 
2278
                        velocityDirection.vz -= dynPtr->Position.vz;
 
 
2279
 
 
 
2280
                        Normalise(&velocityDirection);
 
 
2281
                        int dot = DotProduct(&dynPtr->GravityDirection, &velocityDirection);
 
 
2282
 
 
 
2283
                        if (dot < -60000)
 
 
2284
                        {
 
 
2285
                            /* patrick 29/7/97: I have added the extra condition of not being in the same module as
 
 
2286
                            the player, so that alien does not jump at entry-points */
 
 
2287
                            dynPtr->TimeNotInContactWithFloor = 0;
 
 
2288
                            dynPtr->UseStandardGravity = 1;
 
 
2289
                            dynPtr->LinImpulse.vx -= MUL_FIXED(dynPtr->GravityDirection.vx, ALIEN_JUMPVELOCITY);
 
 
2290
                            dynPtr->LinImpulse.vy -= MUL_FIXED(dynPtr->GravityDirection.vy, ALIEN_JUMPVELOCITY);
 
 
2291
                            dynPtr->LinImpulse.vz -= MUL_FIXED(dynPtr->GravityDirection.vz, ALIEN_JUMPVELOCITY);
 
 
2292
                        }
 
 
2293
                    }
 
 
2294
 
 
 
2295
                    RotateVector(&dynPtr->LinVelocity, &dynPtr->OrientMat);
 
 
2296
 
 
 
2297
                    /* align to velocity */
 
 
2298
                    NPCOrientateToVector(sbPtr, &dynPtr->LinVelocity, NPC_TURNRATE);
 
 
2299
                }
 
 
2300
            }
 
 
2301
            else
 
 
2302
            {
 
 
2303
                int approachingAirDuct = 0;
 
 
2304
                NPCGetMovementTarget(sbPtr, alienStatusPointer->Target, &targetPos, &approachingAirDuct, 1);
 
 
2305
 
 
 
2306
                /* use standard NPC direction finding... */
 
 
2307
                VECTORCH velocityDirection = {0,0,0};
 
 
2308
 
 
 
2309
                NPCGetMovementDirection(sbPtr, &velocityDirection, &targetPos, (alienStatusPointer->EnableWaypoints ?
&alienStatusPointer->waypointManager : NULL));
 
 
2310
 
 
 
2311
                NPCSetVelocity(sbPtr, &velocityDirection, alienStatusPointer->MaxSpeed);
 
 
2312
                alienStatusPointer->CurveTimeOut = 0; /* forces curve init next time curving is used */
 
 
2313
 
 
 
2314
                /* Consider ripping off the wall. */
 
 
2315
                if (!dynPtr->UseStandardGravity && (distance_to_target < ALIEN_POUNCE_MAXRANGE))
 
 
2316
                {
 
 
2317
                    if (DotProduct(&dynPtr->GravityDirection, &velocityDirection) < -60000)
 
 
2318
                    {
 
 
2319
                        dynPtr->TimeNotInContactWithFloor = 0;
 
 
2320
                        dynPtr->UseStandardGravity = 1;
 
 
2321
                        dynPtr->LinImpulse.vx -= MUL_FIXED(dynPtr->GravityDirection.vx, ALIEN_JUMPVELOCITY);
 
 
2322
                        dynPtr->LinImpulse.vy -= MUL_FIXED(dynPtr->GravityDirection.vy, ALIEN_JUMPVELOCITY);
 
 
2323
                        dynPtr->LinImpulse.vz -= MUL_FIXED(dynPtr->GravityDirection.vz, ALIEN_JUMPVELOCITY);
 
 
2324
                        return;
 
 
2325
                    }
 
 
2326
                }
 
 
2327
            }
 
 
2328
 
 
 
2329
            /* Hang on, should we be doing this? */
 
 
2330
            if (!sbPtr->DamageBlock.IsOnFire)
 
 
2331
            {
 
 
2332
                if ((distance_to_target < 30000) && (dynPtr->OrientMat.mat22 >= 63000) && dynPtr->IsInContactWithFloor)
 
 
2333
                {
 
 
2334
                    /* 150% flamethrower 'range'. */
 
 
2335
                    if(TargetIsFiringFlamethrowerAtAlien(sbPtr, distance_to_target))
 
 
2336
                        return;
 
 
2337
                }
 
 
2338
            }
 
 
2339
 
 
 
2340
            /* should we change back to attack, maybe? */
 
 
2341
            if(can_see_target &&(distance_to_target < ALIEN_POUNCE_STARTMAXRANGE))
 
 
2342
            {
 
 
2343
                if (distance_to_target > ALIEN_POUNCE_MINRANGE)
 
 
2344
                {
 
 
2345
                    int EnablePounce = 0;
 
 
2346
 
 
 
2347
                    if(alienStatusPointer->incidentFlag)
 
 
2348
                    switch(alienStatusPointer->Type)
 
 
2349
                    {
 
 
2350
                        case Standard:
 
 
2351
                        default:
 
 
2352
                            EnablePounce = ((FastRandom() % 65535) < 16384);
 
 
2353
                        break;
 
 
2354
                        case Predalien:
 
 
2355
                            EnablePounce = ((FastRandom() % 65535) > 16384);
 
 
2356
                        break;
 
 
2357
                        case Praetorian:
 
 
2358
                            EnablePounce = (alienStatusPointer->PreferToCrouch) ? 1 : ((FastRandom() % 65535) > 16384);
 
 
2359
                    }
 
 
2360
 
 
 
2361
                    /* Might want to pounce. */
 
 
2362
                    if ((EnablePounce || Alien_Special_Pounce_Condition(sbPtr)) && StartAlienPounce(sbPtr))
 
 
2363
                    {
 
 
2364
                        return; // Success.
 
 
2365
                    }
 
 
2366
                }
 
 
2367
                else if (distance_to_target < ALIEN_ATTACKDISTANCE_MIN)
 
 
2368
                {
 
 
2369
                    alienStatusPointer->BehaviourState = ABS_Attack;
 
 
2370
                    return;
 
 
2371
                }
 
 
2372
            }
 
 
2373
            else if (alienStatusPointer->incidentFlag)
 
 
2374
            {
 
 
2375
                switch (alienStatusPointer->Type)
 
 
2376
                {
 
 
2377
                    case Standard:
 
 
2378
                    default:
 
 
2379
                        if (((FastRandom() & 65535) < ALIEN_JUMPINESS) && GoToJump(sbPtr)) // jadda
 
 
2380
                            return; // Boop!
 
 
2381
                    break;
 
 
2382
                    case Predalien:
 
 
2383
                        if (((FastRandom() & 65535) < PREDALIEN_JUMPINESS) && GoToJump(sbPtr))
 
 
2384
                            return; // Boop!
 
 
2385
                    break;
 
 
2386
                    case Praetorian:
 
 
2387
                        if (((FastRandom() & 65535) < PRAETORIAN_JUMPINESS) && GoToJump(sbPtr))
 
 
2388
                            return; // Boop!
 
 
2389
                }
 
 
2390
            }
 
 
2391
 
 
 
2392
            /* test here for impeding collisions, and not being able to reach target... */
 
 
2393
            {
 
 
2394
                STRATEGYBLOCK *destructableObject = NULL;
 
 
2395
                NPC_OBSTRUCTIONREPORT obstruction;
 
 
2396
 
 
 
2397
                NPC_IsObstructed(sbPtr, &alienStatusPointer->moveData, &obstruction, &destructableObject);
 
 
2398
 
 
 
2399
if(0)
 
 
2400
                if(Standard == alienStatusPointer->Type)
 
 
2401
                    alienStatusPointer->EnableWaypoints = 1;
 
 
2402
//if(0)
 
 
2403
                if(obstruction.environment)
 
 
2404
                {
 
 
2405
                    NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
2406
                    NPCGetAvoidanceDirection(sbPtr, &alienStatusPointer->moveData.avoidanceDirn, &obstruction);
 
 
2407
                    alienStatusPointer->BehaviourState = ABS_Avoidance;
 
 
2408
                    alienStatusPointer->StateTimer = NPC_AVOIDTIME;
 
 
2409
printf("gravite %d\n", dynPtr->UseStandardGravity);
 
 
2410
sleep(1);
 
 
2411
                return;
 
 
2412
                }
 
 
2413
                else if(obstruction.destructableObject)
 
 
2414
                {
 
 
2415
                    assert(destructableObject);
 
 
2416
                    CauseDamageToObject(destructableObject,&TemplateAmmo[AMMO_NPC_OBSTACLE_CLEAR].MaxDamage, ONE_FIXED,NULL);
 
 
2417
                }
 
 
2418
                else if (obstruction.anySingleObstruction && !obstruction.otherCharacter)
 
 
2419
                {
 
 
2420
                    /* Try for a nearer target? */
 
 
2421
                    //alienStatusPointer->Target = NULL;
 
 
2422
puts("bstruction.anySingleObstruction && !obstruction.otherChar");
 
 
2423
sleep(1);
 
 
2424
                }
 
 
2425
            }
 
 
2426
 
 
 
2427
            {
 
 
2428
                VECTORCH velocityDirection = dynPtr->LinVelocity;
 
 
2429
                Normalise(&velocityDirection);
 
 
2430
 
 
 
2431
//if(0)
 
 
2432
                if(NPC_CannotReachTarget(&alienStatusPointer->moveData, &targetPos, &velocityDirection))
 
 
2433
                {
 
 
2434
                    NPC_OBSTRUCTIONREPORT obstruction = {1,0,0,0};
 
 
2435
                    NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
2436
                    NPCGetAvoidanceDirection(sbPtr, &alienStatusPointer->moveData.avoidanceDirn, &obstruction);                        
 
 
2437
                    alienStatusPointer->BehaviourState = ABS_Avoidance;          
 
 
2438
                    alienStatusPointer->StateTimer = NPC_AVOIDTIME * 2;
 
 
2439
puts("NPC_CannotReachTarg");
 
 
2440
sleep(1);
 
 
2441
                }
 
 
2442
            }
 
 
2443
        }
 
 
2444
        break;
 
 
2445
        case ABS_Attack:
 
 
2446
        {
 
 
2447
            //dynPtr->UseStandardGravity = !AlienIsAbleToClimb(sbPtr);
 
 
2448
 
 
 
2449
            /* patrick 13/6/97: a little addition: Orientate towards player, just to make sure we're facing */
 
 
2450
            if (dynPtr->UseStandardGravity)
 
 
2451
            {
 
 
2452
                if(alienStatusPointer->CanStand)
 
 
2453
                    alienStatusPointer->IAmCrouched = 0;
 
 
2454
 
 
 
2455
                VECTORCH orientationDirn;
 
 
2456
                orientationDirn.vx = alienStatusPointer->Target->DynPtr->Position.vx - sbPtr->DynPtr->Position.vx;
 
 
2457
                orientationDirn.vy = 0;
 
 
2458
                orientationDirn.vz = alienStatusPointer->Target->DynPtr->Position.vz - sbPtr->DynPtr->Position.vz;
 
 
2459
                int correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE);
 
 
2460
            }
 
 
2461
            else
 
 
2462
            {
 
 
2463
                /* Replace this! */
 
 
2464
                VECTORCH orientationDirn;
 
 
2465
                orientationDirn.vx = alienStatusPointer->Target->DynPtr->Position.vx - sbPtr->DynPtr->Position.vx;
 
 
2466
                orientationDirn.vy = alienStatusPointer->Target->DynPtr->Position.vy - sbPtr->DynPtr->Position.vy;
 
 
2467
                orientationDirn.vz = alienStatusPointer->Target->DynPtr->Position.vz - sbPtr->DynPtr->Position.vz;
 
 
2468
 
 
 
2469
                int dot = -DotProduct(&dynPtr->GravityDirection, &orientationDirn);
 
 
2470
                /* Hold that thought. */
 
 
2471
                orientationDirn.vx -= MUL_FIXED(dot, dynPtr->GravityDirection.vx);
 
 
2472
                orientationDirn.vy -= MUL_FIXED(dot, dynPtr->GravityDirection.vy);
 
 
2473
                orientationDirn.vz -= MUL_FIXED(dot, dynPtr->GravityDirection.vz);
 
 
2474
 
 
 
2475
                int correctlyOrientated = NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE);
 
 
2476
            }
 
 
2477
 
 
 
2478
            int distance_to_target = VectorDistance(&dynPtr->Position, &alienStatusPointer->Target->DynPtr->Position);
 
 
2479
 
 
 
2480
            if(distance_to_target > ALIEN_ATTACKDISTANCE_MAX)
 
 
2481
            {
 
 
2482
                alienStatusPointer->current_attack = NULL;
 
 
2483
 
 
 
2484
                if(alienStatusPointer->Wounds && ((FastRandom() & 127) < 10))
 
 
2485
                {
 
 
2486
                    StartAlienTaunt(sbPtr);
 
 
2487
                }
 
 
2488
                else if((Standard == alienStatusPointer->Type) && dynPtr->UseStandardGravity && alienStatusPointer->CanStand)
 
 
2489
                {
 
 
2490
                    //if(DynamicObjectIsMoving(alienStatusPointer->Target->DynPtr))
 
 
2491
                    {
 
 
2492
                        //if ((HMSQT_AlienRun != alienStatusPointer->HModelController.Sequence_Type) && (ARSS_Attack_Swipe !=
alienStatusPointer->HModelController.Sub_Sequence))
 
 
2493
                        extern ATTACK_DATA Alien_Attacks[];
 
 
2494
                        SetAlienShapeAnimSequence_Core(sbPtr, HMSQT_AlienRun, ARSS_Attack_Swipe, ONE_FIXED >> 1, (ONE_FIXED >> 3));
 
 
2495
                        NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
2496
                        InitWaypointManager(&alienStatusPointer->waypointManager);
 
 
2497
                        alienStatusPointer->BehaviourState = ABS_Approach;
 
 
2498
                        alienStatusPointer->StateTimer = 0;
 
 
2499
                        alienStatusPointer->CurveTimeOut = 0;
 
 
2500
                        alienStatusPointer->current_attack = &Alien_Attacks[12]; // does not matter unless it's NULL
 
 
2501
                    }
 
 
2502
                }
 
 
2503
                else
 
 
2504
                {
 
 
2505
                    NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
2506
                    InitWaypointManager(&alienStatusPointer->waypointManager);
 
 
2507
                    alienStatusPointer->BehaviourState = ABS_Approach;
 
 
2508
                    alienStatusPointer->StateTimer = 0;
 
 
2509
                    alienStatusPointer->CurveTimeOut = 0;
 
 
2510
                    alienStatusPointer->current_attack = NULL;
 
 
2511
                }
 
 
2512
            }
 
 
2513
            else if (NULL == alienStatusPointer->current_attack)
 
 
2514
            {
 
 
2515
                StartAlienAttackSequence(sbPtr);
 
 
2516
            }
 
 
2517
            else
 
 
2518
            {
 
 
2519
                /* alien can inflict nastiness on the target */
 
 
2520
                alienStatusPointer->StateTimer -= NormalFrameTime;
 
 
2521
                AlienNearDamageShell(sbPtr);
 
 
2522
 
 
 
2523
                if (alienStatusPointer->HModelController.keyframe_flags & 1)
 
 
2524
                    alienStatusPointer->current_attack = NULL;
 
 
2525
 
 
 
2526
                if ((FastRandom() & 127) < 20)
 
 
2527
                    AlienRandomHiss(sbPtr);
 
 
2528
            }
 
 
2529
        }
 
 
2530
        break;
 
 
2531
        case ABS_Pounce:
 
 
2532
        {
 
 
2533
            /* Firstly, are we actually pouncing yet? */
 
 
2534
            /* StateTimer is a status flag. */
 
 
2535
 
 
 
2536
            if (!alienStatusPointer->StateTimer)
 
 
2537
            {
 
 
2538
                /* Still tweening? */
 
 
2539
                if (alienStatusPointer->HModelController.Tweening == Controller_NoTweening)
 
 
2540
                {
 
 
2541
                    /* We've finished!  Are we facing right? */
 
 
2542
                    VECTORCH orientationDirn;
 
 
2543
 
 
 
2544
                    orientationDirn.vx = alienStatusPointer->Target->DynPtr->Position.vx - sbPtr->DynPtr->Position.vx;
 
 
2545
                    orientationDirn.vy = 0;
 
 
2546
                    orientationDirn.vz = alienStatusPointer->Target->DynPtr->Position.vz - sbPtr->DynPtr->Position.vz;
 
 
2547
 
 
 
2548
                    if (NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE))
 
 
2549
                    {
 
 
2550
                        /* Okay, pounce! */
 
 
2551
 
 
 
2552
                        ApplyPounceImpulse(sbPtr);
 
 
2553
 
 
 
2554
                        alienStatusPointer->HModelController.Playing = 1;
 
 
2555
                        alienStatusPointer->StateTimer = 1;
 
 
2556
                    }
 
 
2557
                    else
 
 
2558
                    {
 
 
2559
                        /* Still not right!  Wait for proper facing. */
 
 
2560
                        alienStatusPointer->HModelController.Playing = 0;
 
 
2561
                        CheckPounceIntegrity(sbPtr);
 
 
2562
                    }
 
 
2563
                }
 
 
2564
                else
 
 
2565
                {
 
 
2566
                    /* Yup, still tweening.  Check state validity. */
 
 
2567
                    CheckPounceIntegrity(sbPtr);
 
 
2568
                }
 
 
2569
            }
 
 
2570
            else
 
 
2571
            {
 
 
2572
                struct collisionreport *CollisionReportPtr = dynPtr->CollisionReportPtr;
 
 
2573
 
 
 
2574
                if(CollisionReportPtr)
 
 
2575
                {
 
 
2576
                    do
 
 
2577
                    {
 
 
2578
                        if(CollisionReportPtr->ObstacleSBPtr)
 
 
2579
                        {
 
 
2580
                            STRATEGYBLOCK* hit_sbptr = CollisionReportPtr->ObstacleSBPtr;
 
 
2581
 
 
 
2582
                            switch(hit_sbptr->type)
 
 
2583
                            {
 
 
2584
                                case I_BehaviourMarine:
 
 
2585
                                case I_BehaviourMarinePlayer:
 
 
2586
                                case I_BehaviourPredatorPlayer:
 
 
2587
                                case I_BehaviourPredator:
 
 
2588
                                case I_BehaviourPlacedLight:
 
 
2589
                                    CauseDamageToObject(hit_sbptr, &damage_profiles[FALLINGDAMAGE], (100*NormalFrameTime), NULL);
 
 
2590
                                default:
 
 
2591
                                break;
 
 
2592
                            }
 
 
2593
                        }
 
 
2594
 
 
 
2595
                        CollisionReportPtr = CollisionReportPtr->NextCollisionReportPtr;
 
 
2596
 
 
 
2597
                    } while(CollisionReportPtr);
 
 
2598
 
 
 
2599
                    NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
2600
                    alienStatusPointer->BehaviourState = ABS_Attack;
 
 
2601
                    InitWaypointManager(&alienStatusPointer->waypointManager);
 
 
2602
                    alienStatusPointer->StateTimer = 0;
 
 
2603
                    alienStatusPointer->CurveTimeOut = 0;
 
 
2604
                    alienStatusPointer->current_attack = NULL;
 
 
2605
                }
 
 
2606
            }
 
 
2607
        }
 
 
2608
        break;
 
 
2609
        case ABS_Jump:
 
 
2610
        {
 
 
2611
            int terminateState = 0;
 
 
2612
            struct collisionreport *CollisionReportPtr = dynPtr->CollisionReportPtr;
 
 
2613
 
 
 
2614
            /* Pretty simple one, this.  Just fly through the air, until you hit something. */
 
 
2615
 
 
 
2616
            if (dynPtr->IsInContactWithFloor || dynPtr->IsInContactWithNearlyFlatFloor)
 
 
2617
                terminateState = 1;
 
 
2618
 
 
 
2619
            if(CollisionReportPtr)
 
 
2620
            {
 
 
2621
                do
 
 
2622
                {
 
 
2623
                    if(CollisionReportPtr->ObstacleSBPtr)
 
 
2624
                    {
 
 
2625
                        STRATEGYBLOCK* hit_sbptr = CollisionReportPtr->ObstacleSBPtr;
 
 
2626
 
 
 
2627
                        switch(hit_sbptr->type)
 
 
2628
                        {
 
 
2629
                            case I_BehaviourMarine:
 
 
2630
                            case I_BehaviourMarinePlayer:
 
 
2631
                            case I_BehaviourPredatorPlayer:
 
 
2632
                            case I_BehaviourPredator:
 
 
2633
                            case I_BehaviourPlacedLight:
 
 
2634
                                CauseDamageToObject(hit_sbptr, &damage_profiles[FALLINGDAMAGE], (100*NormalFrameTime), NULL);
 
 
2635
                            default:
 
 
2636
                            break;
 
 
2637
                        }
 
 
2638
                    }
 
 
2639
 
 
 
2640
                    CollisionReportPtr = CollisionReportPtr->NextCollisionReportPtr;
 
 
2641
 
 
 
2642
                } while(CollisionReportPtr);
 
 
2643
 
 
 
2644
                terminateState = 1;
 
 
2645
            }
 
 
2646
 
 
 
2647
            if (terminateState)
 
 
2648
            {
 
 
2649
                /* should be crawling. */
 
 
2650
                alienStatusPointer->IAmCrouched = 1;
 
 
2651
        //AlienHandleMovingAnimation(sbPtr);
 
 
2652
 
 
 
2653
                //dynPtr->UseStandardGravity = !(alienStatusPointer->CanClimb && (dynPtr->OrientMat.mat22 < 63000));
 
 
2654
                //dynPtr->UseStandardGravity = !AlienIsAbleToClimb(sbPtr);
 
 
2655
                NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
2656
                InitWaypointManager(&alienStatusPointer->waypointManager);
 
 
2657
                alienStatusPointer->BehaviourState = ABS_Approach;
 
 
2658
                alienStatusPointer->StateTimer = 0;
 
 
2659
                alienStatusPointer->CurveTimeOut = 0;
 
 
2660
                alienStatusPointer->current_attack = NULL;
 
 
2661
            }
 
 
2662
        }
 
 
2663
        break;
 
 
2664
        case ABS_Avoidance:
 
 
2665
        {
 
 
2666
            int terminateState = 0;
 
 
2667
            //dynPtr->UseStandardGravity = !AlienIsAbleToClimb(sbPtr);
 
 
2668
 
 
 
2669
        #if ALL_NEW_AVOIDANCE_ALIEN
 
 
2670
 
 
 
2671
            NPCSetVelocity(sbPtr, &alienStatusPointer->avoidanceManager.avoidanceDirection, alienStatusPointer->MaxSpeed);
 
 
2672
            /* Velocity CANNOT be zero, unless deliberately so! */    
 
 
2673
            {
 
 
2674
                if (AllNewAvoidanceKernel(sbPtr,&alienStatusPointer->avoidanceManager) != AvRC_Avoidance)
 
 
2675
                    terminateState = 1;
 
 
2676
            }
 
 
2677
        #else
 
 
2678
            /* set velocity */
 
 
2679
            assert((alienStatusPointer->moveData.avoidanceDirn.vx!=0)||
 
 
2680
                        (alienStatusPointer->moveData.avoidanceDirn.vy!=0)||
 
 
2681
                        (alienStatusPointer->moveData.avoidanceDirn.vz!=0));
 
 
2682
 
 
 
2683
            NPCSetVelocity(sbPtr, &alienStatusPointer->moveData.avoidanceDirn, alienStatusPointer->MaxSpeed);
 
 
2684
 
 
 
2685
            /* next, decrement state timer */
 
 
2686
            alienStatusPointer->StateTimer -= NormalFrameTime;
 
 
2687
 
 
 
2688
            if(alienStatusPointer->StateTimer <= 0)
 
 
2689
                terminateState = 1;
 
 
2690
 
 
 
2691
            /* and check for an impeding collision */
 
 
2692
            {
 
 
2693
                STRATEGYBLOCK *destructableObject;
 
 
2694
                NPC_OBSTRUCTIONREPORT obstruction;
 
 
2695
                NPC_IsObstructed(sbPtr, &alienStatusPointer->moveData, &obstruction, &destructableObject);
 
 
2696
 
 
 
2697
                if(obstruction.anySingleObstruction)
 
 
2698
                    terminateState = 1; // return to approach
 
 
2699
            }
 
 
2700
        #endif
 
 
2701
 
 
 
2702
            if(terminateState)
 
 
2703
            {
 
 
2704
                if(AlienHasPathToTarget(sbPtr))
 
 
2705
                {
 
 
2706
                    /* switch to approach */
 
 
2707
                    NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
2708
                    alienStatusPointer->BehaviourState = ABS_Approach;          
 
 
2709
                    InitWaypointManager(&alienStatusPointer->waypointManager);
 
 
2710
                    alienStatusPointer->StateTimer = 0;
 
 
2711
 
 
 
2712
                    /* no sequence change required */
 
 
2713
                }
 
 
2714
                else if (AlienIsAwareOfTarget(sbPtr))
 
 
2715
                {
 
 
2716
                    alienStatusPointer->BehaviourState = ABS_Hunt;
 
 
2717
                    InitWaypointManager(&alienStatusPointer->waypointManager);
 
 
2718
                    alienStatusPointer->StateTimer = ALIEN_NEARWAITTIME;
 
 
2719
                }
 
 
2720
                else
 
 
2721
                {
 
 
2722
                    NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
2723
                    NPC_InitWanderData(&alienStatusPointer->wanderData);
 
 
2724
                    alienStatusPointer->BehaviourState = ABS_Wander;          
 
 
2725
                    alienStatusPointer->StateTimer = 0;
 
 
2726
                    InitWaypointManager(&alienStatusPointer->waypointManager);
 
 
2727
                    /* no sequence change required */
 
 
2728
                }
 
 
2729
            }
 
 
2730
        }
 
 
2731
        break;
 
 
2732
        case ABS_Hunt:
 
 
2733
        {
 
 
2734
            VECTORCH velocityDirection = {0,0,0};
 
 
2735
            alienStatusPointer->IAmCrouched = 1;
 
 
2736
            //dynPtr->UseStandardGravity = !alienStatusPointer->CanClimb;
 
 
2737
 
 
 
2738
            /* should we change to approach state? */
 
 
2739
 
 
 
2740
            if(AlienHasPathToTarget(sbPtr))
 
 
2741
            {
 
 
2742
                /* doesn't require a sequence change */
 
 
2743
                NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
2744
                alienStatusPointer->BehaviourState = ABS_Approach;
 
 
2745
                InitWaypointManager(&alienStatusPointer->waypointManager);
 
 
2746
                alienStatusPointer->CurveTimeOut = 0;
 
 
2747
 
 
 
2748
                /* Bloodthirsty, these aliens... */
 
 
2749
                break;
 
 
2750
            }
 
 
2751
 
 
 
2752
            /* Hunting target aquisition. */
 
 
2753
            //if (sbPtr->containingModule != alienStatusPointer->my_containing_module) alienStatusPointer->huntingModule = NULL;
 
 
2754
 
 
 
2755
            /* Check again. */
 
 
2756
            if (alienStatusPointer->huntingModule != NULL)
 
 
2757
            {
 
 
2758
                FARENTRYPOINT *thisEp = GetAIModuleEP(alienStatusPointer->huntingModule,sbPtr->containingModule->m_aimodule);
 
 
2759
 
 
 
2760
                if (!thisEp)
 
 
2761
                    alienStatusPointer->huntingModule = NULL;
 
 
2762
            }
 
 
2763
 
 
 
2764
            if (alienStatusPointer->huntingModule == NULL)
 
 
2765
            {
 
 
2766
                AIMODULE *targetModule = FarNPC_GetTargetAIModuleForGlobalHunt(sbPtr);
 
 
2767
 
 
 
2768
                if (targetModule == NULL)
 
 
2769
                {
 
 
2770
                    /* Better have a handler for this. */
 
 
2771
                    alienStatusPointer->BehaviourState = ABS_Wander;
 
 
2772
                    alienStatusPointer->CurveTimeOut = 0;
 
 
2773
                    //printf("Target module is NULL!\n");
 
 
2774
                    break;
 
 
2775
                }
 
 
2776
 
 
 
2777
                //printf("Target module is %s\n", targetModule->name);
 
 
2778
                //printf("Target AI module for hunt found, %x.\n", (int)targetModule);
 
 
2779
 
 
 
2780
                if (targetModule == sbPtr->containingModule->m_aimodule)
 
 
2781
                {
 
 
2782
                    /* We should have arrived - get a new target? */
 
 
2783
                    if (alienStatusPointer->Target == NULL)
 
 
2784
                    {
 
 
2785
                        /* Oops - nobody about. */
 
 
2786
                        NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
2787
                        NPC_InitWanderData(&alienStatusPointer->wanderData);
 
 
2788
                        alienStatusPointer->BehaviourState = ABS_Wander;
 
 
2789
                        alienStatusPointer->CurveTimeOut = 0;
 
 
2790
                        InitWaypointManager(&alienStatusPointer->waypointManager);
 
 
2791
                    }
 
 
2792
                    else
 
 
2793
                    {
 
 
2794
                        alienStatusPointer->Target = NULL;
 
 
2795
                        alienStatusPointer->BehaviourState = ABS_Hunt;
 
 
2796
                        InitWaypointManager(&alienStatusPointer->waypointManager);
 
 
2797
                        alienStatusPointer->CurveTimeOut = 0;
 
 
2798
                    }
 
 
2799
                return;
 
 
2800
                }
 
 
2801
 
 
 
2802
                alienStatusPointer->huntingModule = targetModule;
 
 
2803
            }
 
 
2804
 
 
 
2805
            {
 
 
2806
                FARENTRYPOINT *thisEp = GetAIModuleEP(alienStatusPointer->huntingModule,sbPtr->containingModule->m_aimodule);
 
 
2807
 
 
 
2808
                if (!thisEp)
 
 
2809
                {
 
 
2810
        printf("This assert is a busted adjacency!\nNo EP between %s and
%s.",(*(alienStatusPointer->huntingModule->m_module_ptrs))->name,sbPtr->containingModule->name);
 
 
2811
                    //printf("This assert is a busted adjacency!");
 
 
2812
                    assert(thisEp);
 
 
2813
                }
 
 
2814
                /* If that fired, there's a farped adjacency. */
 
 
2815
 
 
 
2816
                alienStatusPointer->wanderData.worldPosition = thisEp->position;
 
 
2817
                alienStatusPointer->wanderData.worldPosition.vx += alienStatusPointer->huntingModule->m_world.vx;
 
 
2818
                alienStatusPointer->wanderData.worldPosition.vy += alienStatusPointer->huntingModule->m_world.vy;
 
 
2819
                alienStatusPointer->wanderData.worldPosition.vz += alienStatusPointer->huntingModule->m_world.vz;
 
 
2820
            }
 
 
2821
 
 
 
2822
            /* ok: should have a current target at this stage... */
 
 
2823
            NPCGetMovementDirection(sbPtr, &velocityDirection,
&alienStatusPointer->wanderData.worldPosition,&alienStatusPointer->waypointManager);
 
 
2824
            NPCSetVelocity(sbPtr, &velocityDirection, alienStatusPointer->MaxSpeed);
 
 
2825
 
 
 
2826
            /* test here for impeding collisions, and not being able to reach target... */
 
 
2827
            #if ALL_NEW_AVOIDANCE_ALIEN
 
 
2828
            {
 
 
2829
                if (New_NPC_IsObstructed(sbPtr,&alienStatusPointer->avoidanceManager))
 
 
2830
                {
 
 
2831
                    /* Go to all new avoidance. */
 
 
2832
                    alienStatusPointer->BehaviourState = ABS_Avoidance;
 
 
2833
                    alienStatusPointer->StateTimer = NPC_AVOIDTIME;
 
 
2834
                    InitWaypointManager(&alienStatusPointer->waypointManager);
 
 
2835
                    break;
 
 
2836
                }
 
 
2837
            }
 
 
2838
            #else
 
 
2839
            {
 
 
2840
                STRATEGYBLOCK *destructableObject = NULL;
 
 
2841
                NPC_OBSTRUCTIONREPORT obstruction;
 
 
2842
                NPC_IsObstructed(sbPtr,&alienStatusPointer->moveData,&obstruction,&destructableObject);
 
 
2843
 
 
 
2844
                if(obstruction.environment || obstruction.otherCharacter)
 
 
2845
                {
 
 
2846
                    /* go to avoidance */
 
 
2847
                    NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
2848
                    NPCGetAvoidanceDirection(sbPtr, &alienStatusPointer->moveData.avoidanceDirn, &obstruction);                        
 
 
2849
                    alienStatusPointer->BehaviourState = ABS_Avoidance;
 
 
2850
                    alienStatusPointer->StateTimer = NPC_AVOIDTIME;
 
 
2851
                    /* no sequence change required */
 
 
2852
                    break;
 
 
2853
                }
 
 
2854
 
 
 
2855
                if(obstruction.destructableObject)
 
 
2856
                {
 
 
2857
                    assert(destructableObject);
 
 
2858
                    CauseDamageToObject(destructableObject,&TemplateAmmo[AMMO_NPC_OBSTACLE_CLEAR].MaxDamage, ONE_FIXED,NULL);
 
 
2859
                }
 
 
2860
            }
 
 
2861
 
 
 
2862
            if(NPC_CannotReachTarget(&alienStatusPointer->moveData, &alienStatusPointer->wanderData.worldPosition, &velocityDirection))
 
 
2863
            {
 
 
2864
                /* go to avoidance */
 
 
2865
                NPC_OBSTRUCTIONREPORT obstruction = {1,0,0,0};
 
 
2866
                NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
2867
                NPCGetAvoidanceDirection(sbPtr, &alienStatusPointer->moveData.avoidanceDirn, &obstruction);                        
 
 
2868
                alienStatusPointer->BehaviourState = ABS_Avoidance;
 
 
2869
                alienStatusPointer->StateTimer = NPC_AVOIDTIME;
 
 
2870
                /* no sequence change required */
 
 
2871
            }
 
 
2872
            #endif
 
 
2873
        }
 
 
2874
        break;
 
 
2875
        case ABS_Wait:
 
 
2876
        {
 
 
2877
            if (!alienStatusPointer->IAmCrouched)
 
 
2878
            {
 
 
2879
                alienStatusPointer->IAmCrouched = 1;
 
 
2880
                alienStatusPointer->StateTimer = ONE_FIXED * 2;
 
 
2881
            }
 
 
2882
            else if(!alienStatusPointer->Wounds)
 
 
2883
            {
 
 
2884
                if(alienStatusPointer->HModelController.Playing)
 
 
2885
                {
 
 
2886
                    if(alienStatusPointer->HModelController.Tweening == Controller_NoTweening)
 
 
2887
                        sbPtr->DisplayBlock->HModelControlBlock->Playing = 0;
 
 
2888
 
 
 
2889
                //if(alienStatusPointer->StateTimer < 0)
 
 
2890
                    sbPtr->DisplayBlock->HModelControlBlock->Playing = 0;
 
 
2891
                {
 
 
2892
                    alienStatusPointer->HModelController.Playing = 0;;
 
 
2893
                    puts("not player ANIM");
 
 
2894
                    //alienStatusPointer->StateTimer = ALIEN_NEARWAITTIME * 40;
 
 
2895
                }
 
 
2896
                }
 
 
2897
            }
 
 
2898
        /*
 
 
2899
            if(AlienHasPathToTarget(sbPtr))
 
 
2900
            {
 
 
2901
                NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
2902
                alienStatusPointer->BehaviourState = ABS_Approach;
 
 
2903
                InitWaypointManager(&alienStatusPointer->waypointManager);
 
 
2904
 
 
 
2905
                alienStatusPointer->CurveTimeOut = 0;
 
 
2906
                alienStatusPointer->StateTimer = 0;    
 
 
2907
 
 
 
2908
            return;
 
 
2909
            }
 
 
2910
            else if (AlienIsAwareOfTarget(sbPtr))
 
 
2911
            {
 
 
2912
                alienStatusPointer->BehaviourState = ABS_Hunt;
 
 
2913
                alienStatusPointer->StateTimer = ALIEN_NEARWAITTIME;
 
 
2914
                InitWaypointManager(&alienStatusPointer->waypointManager);
 
 
2915
            }
 
 
2916
        */
 
 
2917
            /* still waiting: decrement timer */
 
 
2918
            alienStatusPointer->StateTimer -= NormalFrameTime;
 
 
2919
 
 
 
2920
            if(alienStatusPointer->StateTimer <= 0)
 
 
2921
            {
 
 
2922
                NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
2923
                NPC_InitWanderData(&alienStatusPointer->wanderData);
 
 
2924
                alienStatusPointer->BehaviourState = ABS_Wander;
 
 
2925
                InitWaypointManager(&alienStatusPointer->waypointManager);
 
 
2926
                alienStatusPointer->StateTimer = 0;        
 
 
2927
            }
 
 
2928
        }
 
 
2929
        break;
 
 
2930
        case ABS_Wander:
 
 
2931
        {
 
 
2932
            VECTORCH velocityDirection = {0,0,0};
 
 
2933
 
 
 
2934
            /* Do something else? */
 
 
2935
 
 
 
2936
            /* should we change to approach state? */
 
 
2937
            if(AlienHasPathToTarget(sbPtr))
 
 
2938
            {
 
 
2939
                /* doesn't require a sequence change */
 
 
2940
                NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
2941
                alienStatusPointer->BehaviourState = ABS_Approach;
 
 
2942
                alienStatusPointer->CurveTimeOut = 0;
 
 
2943
                InitWaypointManager(&alienStatusPointer->waypointManager);
 
 
2944
            break;
 
 
2945
            }
 
 
2946
            else if (AlienIsAwareOfTarget(sbPtr))
 
 
2947
            {
 
 
2948
                alienStatusPointer->BehaviourState = ABS_Hunt;
 
 
2949
                alienStatusPointer->StateTimer = ALIEN_NEARWAITTIME;
 
 
2950
                InitWaypointManager(&alienStatusPointer->waypointManager);
 
 
2951
            }
 
 
2952
 
 
 
2953
            /* Try to reaquire target? */
 
 
2954
            alienStatusPointer->Target = NULL;
 
 
2955
 
 
 
2956
            if(alienStatusPointer->wanderData.currentModule == NPC_NOWANDERMODULE)
 
 
2957
            {
 
 
2958
                NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
2959
                NPC_FindAIWanderTarget(sbPtr,&alienStatusPointer->wanderData, &alienStatusPointer->moveData, 1);
 
 
2960
            }
 
 
2961
            else if(alienStatusPointer->wanderData.currentModule != sbPtr->containingModule->m_aimodule->m_index)
 
 
2962
            {
 
 
2963
                NPC_FindAIWanderTarget(sbPtr, &alienStatusPointer->wanderData, &alienStatusPointer->moveData, 1);
 
 
2964
            }
 
 
2965
 
 
 
2966
            /* if we still haven't got one, go to wait */
 
 
2967
            if(alienStatusPointer->wanderData.currentModule == NPC_NOWANDERMODULE)
 
 
2968
            {
 
 
2969
                alienStatusPointer->BehaviourState = ABS_Wait;
 
 
2970
                alienStatusPointer->StateTimer = ALIEN_NEARWAITTIME;
 
 
2971
            }
 
 
2972
 
 
 
2973
            /* ok: should have a current target at this stage... */
 
 
2974
            NPCGetMovementDirection(sbPtr, &velocityDirection, &alienStatusPointer->wanderData.worldPosition,
&alienStatusPointer->waypointManager);
 
 
2975
            NPCSetVelocity(sbPtr, &velocityDirection, alienStatusPointer->MaxSpeed);
 
 
2976
 
 
 
2977
            /* test here for impeding collisions, and not being able to reach target... */
 
 
2978
 
 
 
2979
        #if ALL_NEW_AVOIDANCE_ALIEN
 
 
2980
            {
 
 
2981
                if (New_NPC_IsObstructed(sbPtr,&alienStatusPointer->avoidanceManager))
 
 
2982
                {
 
 
2983
                    /* Go to all new avoidance. */
 
 
2984
                    alienStatusPointer->BehaviourState = ABS_Avoidance;          
 
 
2985
                    alienStatusPointer->StateTimer = NPC_AVOIDTIME;
 
 
2986
                    InitWaypointManager(&alienStatusPointer->waypointManager);
 
 
2987
                    break;
 
 
2988
                }
 
 
2989
            }
 
 
2990
        #else
 
 
2991
            {
 
 
2992
                STRATEGYBLOCK *destructableObject = NULL;
 
 
2993
                NPC_OBSTRUCTIONREPORT obstruction;
 
 
2994
                NPC_IsObstructed(sbPtr, &alienStatusPointer->moveData, &obstruction,&destructableObject);
 
 
2995
 
 
 
2996
                if(obstruction.environment || obstruction.otherCharacter)
 
 
2997
                {
 
 
2998
                    /* go to avoidance */
 
 
2999
                    NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
3000
                    NPCGetAvoidanceDirection(sbPtr, &alienStatusPointer->moveData.avoidanceDirn, &obstruction);                        
 
 
3001
                    alienStatusPointer->BehaviourState = ABS_Avoidance;
 
 
3002
                    alienStatusPointer->StateTimer = NPC_AVOIDTIME;
 
 
3003
                    /* no sequence change required */
 
 
3004
                    break;
 
 
3005
                }
 
 
3006
 
 
 
3007
                if(obstruction.destructableObject)
 
 
3008
                {
 
 
3009
                    assert(destructableObject);
 
 
3010
                    CauseDamageToObject(destructableObject, &TemplateAmmo[AMMO_NPC_OBSTACLE_CLEAR].MaxDamage, ONE_FIXED, NULL);
 
 
3011
                }
 
 
3012
            }
 
 
3013
 
 
 
3014
            if(NPC_CannotReachTarget(&alienStatusPointer->moveData, &alienStatusPointer->wanderData.worldPosition, &velocityDirection))
 
 
3015
            {
 
 
3016
                /* go to avoidance */
 
 
3017
                NPC_OBSTRUCTIONREPORT obstruction = {1,0,0,0};
 
 
3018
                NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
3019
                NPCGetAvoidanceDirection(sbPtr, &alienStatusPointer->moveData.avoidanceDirn, &obstruction);
 
 
3020
                alienStatusPointer->BehaviourState = ABS_Avoidance;
 
 
3021
                alienStatusPointer->StateTimer = NPC_AVOIDTIME;
 
 
3022
                /* no sequence change required */
 
 
3023
            }
 
 
3024
        #endif
 
 
3025
        }
 
 
3026
        break;
 
 
3027
        case ABS_Retreat:
 
 
3028
        {
 
 
3029
            VECTORCH velocityDirection = {0,0,0};
 
 
3030
 
 
 
3031
            /* should we change to approach state? */
 
 
3032
            if(AlienIsAwareOfTarget(sbPtr))
 
 
3033
            {
 
 
3034
                // doesn't require a sequence change
 
 
3035
                NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
3036
                alienStatusPointer->BehaviourState = ABS_Approach;
 
 
3037
                InitWaypointManager(&alienStatusPointer->waypointManager);
 
 
3038
                alienStatusPointer->CurveTimeOut = 0;
 
 
3039
 
 
 
3040
                // Bloodthirsty, these aliens...
 
 
3041
                return;
 
 
3042
            }
 
 
3043
 
 
 
3044
            /* Retreat target aquisition. */
 
 
3045
            {
 
 
3046
                AIMODULE *targetModule = NearNPC_GetTargetAIModuleForRetreat(sbPtr, &(alienStatusPointer->moveData));
 
 
3047
 
 
 
3048
        /*        if (targetModule)
 
 
3049
                {
 
 
3050
                    //printf("Target module is %s\n",targetModule->name);
 
 
3051
                    //printf("Target AI module found, %x.\n",(int)targetModule);
 
 
3052
                }
 
 
3053
                else
 
 
3054
                {
 
 
3055
                    printf("Target module is NULL!\n");
 
 
3056
                }
 
 
3057
        */
 
 
3058
                if ((targetModule == sbPtr->containingModule->m_aimodule) || (targetModule == NULL))
 
 
3059
                {
 
 
3060
                    /* Hey, it'll drop through. */
 
 
3061
                    alienStatusPointer->BehaviourState = ABS_Hunt;
 
 
3062
                    alienStatusPointer->CurveTimeOut = 0;
 
 
3063
                    InitWaypointManager(&alienStatusPointer->waypointManager);
 
 
3064
                return;
 
 
3065
                }
 
 
3066
 
 
 
3067
                assert(targetModule);
 
 
3068
 
 
 
3069
                FARENTRYPOINT *thisEp = GetAIModuleEP(targetModule,sbPtr->containingModule->m_aimodule);
 
 
3070
 
 
 
3071
                if (!thisEp)
 
 
3072
                {
 
 
3073
                    //printf("This assert is a busted adjacency!\nNo EP between %s and
%s.",targetModule->name,sbPtr->containingModule->name);
 
 
3074
                    printf("This assert is a busted adjacency!");
 
 
3075
                    assert(thisEp);
 
 
3076
                }
 
 
3077
                /* If that fired, there's a farped adjacency. */
 
 
3078
 
 
 
3079
                alienStatusPointer->wanderData.worldPosition = thisEp->position;
 
 
3080
                alienStatusPointer->wanderData.worldPosition.vx += targetModule->m_world.vx;
 
 
3081
                alienStatusPointer->wanderData.worldPosition.vy += targetModule->m_world.vy;
 
 
3082
                alienStatusPointer->wanderData.worldPosition.vz += targetModule->m_world.vz;
 
 
3083
            }
 
 
3084
 
 
 
3085
            /* ok: should have a current target at this stage... */
 
 
3086
            NPCGetMovementDirection(sbPtr, &velocityDirection,
&(alienStatusPointer->wanderData.worldPosition),&alienStatusPointer->waypointManager);
 
 
3087
            NPCSetVelocity(sbPtr, &velocityDirection, alienStatusPointer->MaxSpeed);    
 
 
3088
 
 
 
3089
            /* test here for impeding collisions, and not being able to reach target... */
 
 
3090
        #if ALL_NEW_AVOIDANCE_ALIEN
 
 
3091
            {
 
 
3092
                if (New_NPC_IsObstructed(sbPtr,&alienStatusPointer->avoidanceManager))
 
 
3093
                {
 
 
3094
                    /* Go to all new avoidance. */
 
 
3095
                    alienStatusPointer->BehaviourState = ABS_Avoidance;          
 
 
3096
                    alienStatusPointer->StateTimer = NPC_AVOIDTIME;
 
 
3097
                    InitWaypointManager(&alienStatusPointer->waypointManager);
 
 
3098
                    return;
 
 
3099
                }
 
 
3100
            }
 
 
3101
        #else
 
 
3102
            {
 
 
3103
                STRATEGYBLOCK *destructableObject = NULL;
 
 
3104
                NPC_OBSTRUCTIONREPORT obstruction;
 
 
3105
                NPC_IsObstructed(sbPtr, &alienStatusPointer->moveData, &obstruction,&destructableObject);
 
 
3106
 
 
 
3107
                if(obstruction.environment || obstruction.otherCharacter)
 
 
3108
                {
 
 
3109
                    /* go to avoidance */
 
 
3110
                    NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
3111
                    NPCGetAvoidanceDirection(sbPtr, &alienStatusPointer->moveData.avoidanceDirn, &obstruction);                        
 
 
3112
                    alienStatusPointer->BehaviourState = ABS_Avoidance;
 
 
3113
                    alienStatusPointer->StateTimer = NPC_AVOIDTIME;
 
 
3114
                    /* no sequence change required */
 
 
3115
                    return;
 
 
3116
                }
 
 
3117
 
 
 
3118
                if(obstruction.destructableObject)
 
 
3119
                {
 
 
3120
                    assert(destructableObject);
 
 
3121
                    CauseDamageToObject(destructableObject, &TemplateAmmo[AMMO_NPC_OBSTACLE_CLEAR].MaxDamage, ONE_FIXED, NULL);
 
 
3122
                }
 
 
3123
            }
 
 
3124
 
 
 
3125
            if(NPC_CannotReachTarget(&alienStatusPointer->moveData, &alienStatusPointer->wanderData.worldPosition, &velocityDirection))
 
 
3126
            {
 
 
3127
                /* go to avoidance */
 
 
3128
                NPC_OBSTRUCTIONREPORT obstruction = {1,0,0,0};
 
 
3129
                NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
3130
                NPCGetAvoidanceDirection(sbPtr, &alienStatusPointer->moveData.avoidanceDirn, &obstruction);
 
 
3131
                alienStatusPointer->BehaviourState = ABS_Avoidance;
 
 
3132
                alienStatusPointer->StateTimer = NPC_AVOIDTIME;
 
 
3133
                /* no sequence change required */
 
 
3134
            }
 
 
3135
        #endif
 
 
3136
        }
 
 
3137
        default:
 
 
3138
        break;
 
 
3139
      }
 
 
3140
}
 
 
3141
 
 
 
3142
static void FarAlienBehaviour(STRATEGYBLOCK *sbPtr)
 
 
3143
{
 
 
3144
    ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
3145
 
 
 
3146
    switch(alienStatusPointer->BehaviourState)
 
 
3147
    {
 
 
3148
        case ABS_Hunt:
 
 
3149
        {
 
 
3150
            alienStatusPointer->StateTimer -= NormalFrameTime;
 
 
3151
 
 
 
3152
            if (alienStatusPointer->Target && (alienStatusPointer->Target->containingModule->m_aimodule ==
sbPtr->containingModule->m_aimodule))
 
 
3153
            {
 
 
3154
                alienStatusPointer->BehaviourState = ABS_Wait;
 
 
3155
                alienStatusPointer->StateTimer = 0;
 
 
3156
            }
 
 
3157
            else
 
 
3158
            {
 
 
3159
                /* check if far state timer has timed-out. If so, it is time 
 
 
3160
                to do something. Otherwise just return. */
 
 
3161
                if(alienStatusPointer->StateTimer > 0)
 
 
3162
                    return;
 
 
3163
 
 
 
3164
                /* check the alien hive, to see itf we've switched to regroup:
 
 
3165
                if so, reset the alien far behaviour state to retreat, with the alien far 
 
 
3166
                state timer set to 0, forcing a retreating movement next frame... */
 
 
3167
 
 
 
3168
                if(NPCHive.currentState == HS_Regroup)
 
 
3169
                {
 
 
3170
                    alienStatusPointer->BehaviourState = ABS_Retreat;
 
 
3171
                    alienStatusPointer->StateTimer = 0; /* forces execution of new state next frame*/
 
 
3172
                    return;
 
 
3173
                }
 
 
3174
 
 
 
3175
                if (!AlienIsAwareOfTarget(sbPtr) && (alienStatusPointer->Target == PlayerStatus.sbptr) && NPC_IsDead(PlayerStatus.sbptr))
 
 
3176
                {
 
 
3177
                    alienStatusPointer->BehaviourState = ABS_Wander;
 
 
3178
                    alienStatusPointer->StateTimer = 0; /* forces execution of new state next frame*/
 
 
3179
                }
 
 
3180
                else
 
 
3181
                {
 
 
3182
                    AIMODULE *targetModule = FarNPC_GetTargetAIModuleForHunt(sbPtr, 1);
 
 
3183
 
 
 
3184
                    /* if there is no target module, it means that the alien is trapped in an
 
 
3185
                    unlinked module. In this case, reset the timer and return. */            
 
 
3186
 
 
 
3187
                    if(!targetModule)
 
 
3188
                    {
 
 
3189
                        alienStatusPointer->StateTimer = ALIEN_FAR_MOVE_TIME;
 
 
3190
                        alienStatusPointer->BehaviourState = ABS_Wander;
 
 
3191
                        alienStatusPointer->CurveTimeOut = 0;
 
 
3192
                    }
 
 
3193
                    else
 
 
3194
                    {
 
 
3195
                        alienStatusPointer->StateTimer = ProcessFarAlienTargetModule(sbPtr, targetModule);
 
 
3196
                        alienStatusPointer->StateTimer += ONE_FIXED * 3 + ( (FastRandom() & 7) * ONE_FIXED);
 
 
3197
                    }
 
 
3198
                }
 
 
3199
            }
 
 
3200
        }
 
 
3201
          break;
 
 
3202
           case ABS_Retreat:
 
 
3203
        {
 
 
3204
            alienStatusPointer->StateTimer -= NormalFrameTime;
 
 
3205
 
 
 
3206
            /* check if far state timer has timed-out. If so, it is time 
 
 
3207
            to do something. Otherwise just return. */
 
 
3208
 
 
 
3209
            if(alienStatusPointer->StateTimer > 0)
 
 
3210
                return;
 
 
3211
 
 
 
3212
            /* check the alien hive, to see if we've switched to attack:
 
 
3213
            if so, reset the alien far behaviour state to attack, with the alien far 
 
 
3214
            state timer set to 0, forcing a movement next frame... 
 
 
3215
            NB if we can't attack the player, hunting function will automatically
 
 
3216
            switch to wander */
 
 
3217
 
 
 
3218
            if(NPCHive.currentState == HS_Attack)
 
 
3219
            {
 
 
3220
                alienStatusPointer->BehaviourState = ABS_Hunt;
 
 
3221
                alienStatusPointer->StateTimer = 0; /* forces execution of new state next frame*/
 
 
3222
                return;
 
 
3223
            }
 
 
3224
 
 
 
3225
            /* get the target module... */
 
 
3226
            AIMODULE *targetModule = FarNPC_GetTargetAIModuleForRetreat(sbPtr);
 
 
3227
 
 
 
3228
            /* if there is no target module, reset the timer and return. */            
 
 
3229
            if(!targetModule)
 
 
3230
            {
 
 
3231
                alienStatusPointer->StateTimer = ALIEN_FAR_MOVE_TIME;
 
 
3232
                return;        
 
 
3233
            }
 
 
3234
 
 
 
3235
            /* Examine target, and decide what to do */
 
 
3236
            assert(AIModuleIsPhysical(targetModule));
 
 
3237
 
 
 
3238
            alienStatusPointer->StateTimer = ProcessFarAlienTargetModule(sbPtr, targetModule);
 
 
3239
        }
 
 
3240
          break;
 
 
3241
           case ABS_Wander:
 
 
3242
        {
 
 
3243
            /* Decrement the Far state timer */
 
 
3244
            alienStatusPointer->StateTimer -= NormalFrameTime;
 
 
3245
 
 
 
3246
            /* check if far state timer has timed-out. If so, it is time to do something. Otherwise just return. */
 
 
3247
            if(alienStatusPointer->StateTimer > 0)
 
 
3248
                return;
 
 
3249
 
 
 
3250
            /* check for state changes:
 
 
3251
            if hive says retreat, then retreat, regardless of whether or not we can see the player 
 
 
3252
            otherwise, if we can see the player, go to hunt */
 
 
3253
 
 
 
3254
            if(NPCHive.currentState == HS_Regroup)
 
 
3255
            {
 
 
3256
                alienStatusPointer->BehaviourState = ABS_Retreat;
 
 
3257
                alienStatusPointer->StateTimer = 0; /* forces execution of new state next frame*/
 
 
3258
                return;
 
 
3259
            }
 
 
3260
 
 
 
3261
            /* see if we want to switch to attack */
 
 
3262
            if(AlienIsAwareOfTarget(sbPtr))
 
 
3263
            {
 
 
3264
                alienStatusPointer->BehaviourState = ABS_Hunt;
 
 
3265
                alienStatusPointer->StateTimer = 0; /* forces execution of new state next frame*/
 
 
3266
                return;
 
 
3267
            }
 
 
3268
 
 
 
3269
            /* get the target module... */
 
 
3270
 
 
 
3271
            AIMODULE *targetModule = FarNPC_GetTargetAIModuleForWander(sbPtr, NULL, 1);
 
 
3272
 
 
 
3273
            /* if there is no target module, reset the timer and return. */
 
 
3274
            alienStatusPointer->StateTimer = (NULL != targetModule) ? ProcessFarAlienTargetModule(sbPtr, targetModule) : ALIEN_FAR_MOVE_TIME;
 
 
3275
        }
 
 
3276
        break;
 
 
3277
        case ABS_Wait:
 
 
3278
        {
 
 
3279
            if (alienStatusPointer->Target && alienStatusPointer->Target->containingModule->m_aimodule !=
sbPtr->containingModule->m_aimodule)
 
 
3280
            {
 
 
3281
                alienStatusPointer->BehaviourState = ABS_Hunt;
 
 
3282
                alienStatusPointer->StateTimer = 0; /* forces execution of new state next frame*/
 
 
3283
            }
 
 
3284
            else
 
 
3285
            {
 
 
3286
                /* Decrement the Far state timer */
 
 
3287
                alienStatusPointer->StateTimer -= NormalFrameTime;
 
 
3288
 
 
 
3289
                /* check if far state timer has timed-out. If so, it is time to do something. Otherwise just return. */
 
 
3290
                if(alienStatusPointer->StateTimer > 0)
 
 
3291
                    return;
 
 
3292
            }
 
 
3293
        }
 
 
3294
        case ABS_Dormant:
 
 
3295
        case ABS_Awakening:
 
 
3296
        break;
 
 
3297
        case ABS_Avoidance:
 
 
3298
        {
 
 
3299
            /* No obstacles in far behaviour. */
 
 
3300
            Initialise_AvoidanceManager(&alienStatusPointer->avoidanceManager);
 
 
3301
        }
 
 
3302
        // no break
 
 
3303
        default:
 
 
3304
        {
 
 
3305
            alienStatusPointer->BehaviourState = ABS_Hunt;
 
 
3306
            alienStatusPointer->StateTimer = 0; /* forces execution of new state next frame*/
 
 
3307
        }
 
 
3308
    }
 
 
3309
 
 
 
3310
    /* check here to see if the alien is in a doorway....
 
 
3311
    If so, and it is a proximity door, make sure it is open. */
 
 
3312
    {
 
 
3313
        MODULEDOORTYPE doorType = ModuleIsADoor(sbPtr->containingModule);
 
 
3314
 
 
 
3315
        if(doorType == MDT_ProxDoor)
 
 
3316
            ((PROXDOOR_BEHAV_BLOCK *)sbPtr->containingModule->m_sbptr->dataptr)->alienTrigger = 1;
 
 
3317
    }
 
 
3318
 
 
 
3319
    if (ShowHiveState)
 
 
3320
    {
 
 
3321
        MODULE *thisModule = sbPtr->containingModule;
 
 
3322
        printf("This FAR ALIEN is in module %d, %s\n", thisModule->m_index, thisModule->name);
 
 
3323
    }
 
 
3324
 
 
 
3325
    /* make sure that we are inside a module:
 
 
3326
    if this fires it means that a far alien is not inside
 
 
3327
    the module it is supposed to be in */
 
 
3328
 
 
 
3329
    #if UseLocalAssert   
 
 
3330
    {
 
 
3331
        VECTORCH localCoords;
 
 
3332
        MODULE *thisModule = sbPtr->containingModule;
 
 
3333
 
 
 
3334
        assert(thisModule);
 
 
3335
 
 
 
3336
        localCoords = sbPtr->DynPtr->Position;
 
 
3337
        localCoords.vx -= thisModule->m_world.vx;
 
 
3338
        localCoords.vy -= thisModule->m_world.vy;
 
 
3339
        localCoords.vz -= thisModule->m_world.vz;
 
 
3340
 
 
 
3341
        if(!PointIsInModule(thisModule, &localCoords))
 
 
3342
        {
 
 
3343
            //printf("FAR ALIEN MODULE CONTAINMENT FAILURE \n");
 
 
3344
 
 
 
3345
            printf("Alien containment failure: alien is in %s, position is %d,%d,%d:\nModule extents are: %d:%d, %d:%d, %d:%d",
 
 
3346
                thisModule->name,localCoords.vx,localCoords.vy,localCoords.vz,
 
 
3347
                thisModule->m_maxx,thisModule->m_minx,thisModule->m_maxy,thisModule->m_miny,
 
 
3348
                thisModule->m_maxz,thisModule->m_minz);
 
 
3349
 
 
 
3350
            assert(1==0);
 
 
3351
        }  
 
 
3352
    }
 
 
3353
    #endif
 
 
3354
 
 
 
3355
    // printf("NO ENTRY POINT COUNT %d \n", entryPointFailures);
 
 
3356
}
 
 
3357
 
 
 
3358
void AlienBehaviour(STRATEGYBLOCK *sbPtr)
 
 
3359
{
 
 
3360
    ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
3361
    DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
3362
 
 
 
3363
    dynPtr->LinVelocity.vx = dynPtr->LinVelocity.vy = dynPtr->LinVelocity.vz = 0;
 
 
3364
    //dynPtr->UseStandardGravity = 1; // don't climb on walls, etc
 
 
3365
    dynPtr->UseStandardGravity = !AlienIsAbleToClimb(sbPtr);
 
 
3366
 
 
 
3367
    if(alienStatusPointer->unconscious)
 
 
3368
    {
 
 
3369
        alienStatusPointer->Target = alienStatusPointer->current_attack = NULL;
 
 
3370
 
 
 
3371
        if(alienStatusPointer->unconscious < 0)
 
 
3372
        {
 
 
3373
            alienStatusPointer->IAmCrouched = 1;
 
 
3374
 
 
 
3375
            if (HMSQT_AlienCrouch == alienStatusPointer->HModelController.Sequence_Type)
 
 
3376
            {
 
 
3377
                alienStatusPointer->unconscious = 0;
 
 
3378
                alienStatusPointer->BehaviourState = ABS_Hunt;
 
 
3379
            }
 
 
3380
            else
 
 
3381
            {
 
 
3382
                SetAlienShapeAnimSequence_Core(sbPtr, HMSQT_AlienCrouch, ACrSS_Standard, -1, (ONE_FIXED>>3));
 
 
3383
                return;
 
 
3384
            }
 
 
3385
        }
 
 
3386
        else
 
 
3387
        {
 
 
3388
            alienStatusPointer->unconscious -= NormalFrameTime;
 
 
3389
            return;
 
 
3390
        }
 
 
3391
    }
 
 
3392
 
 
 
3393
    /* Unset incident flag. */
 
 
3394
    alienStatusPointer->incidentFlag = 0;
 
 
3395
    alienStatusPointer->incidentTimer -= NormalFrameTime;
 
 
3396
 
 
 
3397
    if (alienStatusPointer->incidentTimer < 0) 
 
 
3398
    {
 
 
3399
        alienStatusPointer->incidentFlag = 1;
 
 
3400
        alienStatusPointer->incidentTimer = 32767 + (FastRandom() & 65535);
 
 
3401
    }
 
 
3402
 
 
 
3403
    if (sbPtr->DamageBlock.IsOnFire)
 
 
3404
    {
 
 
3405
        if(alienStatusPointer->soundOnFire != SOUND_NOACTIVEINDEX)
 
 
3406
            Sound_Update3d(alienStatusPointer->soundOnFire, &sbPtr->DynPtr->Position);
 
 
3407
        else
 
 
3408
              Sound_Play(SID_FIRE, "dle", &sbPtr->DynPtr->Position, &alienStatusPointer->soundOnFire);
 
 
3409
 
 
 
3410
        //for multiplayer games it is necessary to say who is doing this damage
 
 
3411
        //(that would be the person who set the alien on fire in the first place)
 
 
3412
        {
 
 
3413
/*
 
 
3414
            extern int myNetworkKillerId;
 
 
3415
            extern int AVPDPNetID;
 
 
3416
            myNetworkKillerId = alienStatusPointer->aliensIgniterId;
 
 
3417
            myNetworkKillerId = AVPDPNetID;
 
 
3418
*/
 
 
3419
        }
 
 
3420
 
 
 
3421
        if (alienStatusPointer->incidentFlag && ((FastRandom() & 65535) < 32767))
 
 
3422
        {
 
 
3423
            sbPtr->DamageBlock.IsOnFire = 0;
 
 
3424
            Sound_Stop(alienStatusPointer->soundOnFire);
 
 
3425
        }
 
 
3426
        else
 
 
3427
        {
 
 
3428
            int speed = Approximate3dMagnitude(&sbPtr->DynPtr->LinVelocity);
 
 
3429
            /* Go out? */
 
 
3430
 
 
 
3431
            if (speed > 22000)
 
 
3432
            {
 
 
3433
                /* Jumping alien. */
 
 
3434
                sbPtr->DamageBlock.IsOnFire -= NormalFrameTime * 6;
 
 
3435
            }
 
 
3436
            else if (speed > 15000) 
 
 
3437
            {
 
 
3438
                /* Running alien. */
 
 
3439
                sbPtr->DamageBlock.IsOnFire -= NormalFrameTime << 2;
 
 
3440
            }
 
 
3441
            else 
 
 
3442
            {
 
 
3443
                /* Normal bloke. */
 
 
3444
                sbPtr->DamageBlock.IsOnFire -= NormalFrameTime;
 
 
3445
            }
 
 
3446
 
 
 
3447
            if (sbPtr->DamageBlock.IsOnFire <= 0) 
 
 
3448
            {
 
 
3449
                sbPtr->DamageBlock.IsOnFire = 0;
 
 
3450
                Sound_Stop(alienStatusPointer->soundOnFire);
 
 
3451
            }
 
 
3452
        }
 
 
3453
    }
 
 
3454
 
 
 
3455
//printf("alienStatusPointer->BehaviourState %d %s\n", alienStatusPointer->BehaviourState, (sbPtr->DisplayBlock ? "near" :
"far")); //jadda
 
 
3456
//if(alienStatusPointer->Target != NULL) printf("has TARGET %d\n", alienStatusPointer->Target->type);
 
 
3457
//if(alienStatusPointer->current_attack != NULL) puts("nooooo nULL");
 
 
3458
//if(dynPtr->UseStandardGravity) puts("STANDARG GVRAVITY nULL"); else puts("NOT   STANDARG GVRAVITY nULL");
 
 
3459
 
 
 
3460
    switch(alienStatusPointer->BehaviourState)
 
 
3461
    {
 
 
3462
        case ABS_Awakening:
 
 
3463
        {
 
 
3464
            /* wait until near state timer runs out, then wander:
 
 
3465
            alternatively, if we can attack the player, go straight to approach */
 
 
3466
 
 
 
3467
            if (!sbPtr->DisplayBlock)
 
 
3468
                ProveHModel_Far(&alienStatusPointer->HModelController,sbPtr);
 
 
3469
 
 
 
3470
            if ((alienStatusPointer->HModelController.Tweening == Controller_NoTweening) && (alienStatusPointer->HModelController.sequence_timer
== (ONE_FIXED-1)))
 
 
3471
            {
 
 
3472
                NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
3473
                alienStatusPointer->BehaviourState = ABS_Approach;
 
 
3474
                InitWaypointManager(&alienStatusPointer->waypointManager);
 
 
3475
                alienStatusPointer->CurveTimeOut = 0;
 
 
3476
                alienStatusPointer->StateTimer = 0;    
 
 
3477
            }
 
 
3478
        }
 
 
3479
        return;
 
 
3480
        case ABS_Dormant:
 
 
3481
        {
 
 
3482
            /* wait until near state timer runs out, then wander:
 
 
3483
            alternatively, if we can attack the player, go straight to approach */
 
 
3484
 
 
 
3485
            /* Also used for FAR! */
 
 
3486
 
 
 
3487
            if (!sbPtr->DisplayBlock)
 
 
3488
            {
 
 
3489
                if (alienStatusPointer->HModelController.Playing)
 
 
3490
                {
 
 
3491
                    /* Try to call this as little as possible. */
 
 
3492
                    ProveHModel_Far(&alienStatusPointer->HModelController,sbPtr);
 
 
3493
 
 
 
3494
                    if (!alienStatusPointer->HModelController.Tweening)
 
 
3495
                        alienStatusPointer->HModelController.Playing = 0;
 
 
3496
                }
 
 
3497
            }
 
 
3498
            else
 
 
3499
            {
 
 
3500
                alienStatusPointer->HModelController.Playing = 1;
 
 
3501
            }
 
 
3502
 
 
 
3503
            /* Brushing Test. */
 
 
3504
            {
 
 
3505
                struct collisionreport *nextReport = sbPtr->DynPtr->CollisionReportPtr;
 
 
3506
 
 
 
3507
                while(nextReport)
 
 
3508
                {
 
 
3509
                    if(nextReport->ObstacleSBPtr)
 
 
3510
                    {    
 
 
3511
                        switch(nextReport->ObstacleSBPtr->type)
 
 
3512
                        {
 
 
3513
                            case I_BehaviourAlienPlayer:
 
 
3514
                            case I_BehaviourMarinePlayer:
 
 
3515
                            case I_BehaviourMarine:
 
 
3516
                            case I_BehaviourPredatorPlayer:
 
 
3517
                            case I_BehaviourNetGhost:
 
 
3518
                            case I_BehaviourXenoborg:
 
 
3519
                            case I_BehaviourQueenAlien:
 
 
3520
                            case I_BehaviourFaceHugger:
 
 
3521
                                Alien_Awaken(sbPtr);
 
 
3522
                            default:
 
 
3523
                            break;
 
 
3524
                        }
 
 
3525
                    }
 
 
3526
 
 
 
3527
                    nextReport = nextReport->NextCollisionReportPtr;
 
 
3528
                }
 
 
3529
            }
 
 
3530
        }
 
 
3531
        return;
 
 
3532
        case ABS_Taunting:
 
 
3533
        {
 
 
3534
            if (!sbPtr->DisplayBlock)
 
 
3535
            {
 
 
3536
                ProveHModel_Far(&alienStatusPointer->HModelController,sbPtr);
 
 
3537
            }
 
 
3538
            else
 
 
3539
            {
 
 
3540
                /* Orientate towards target, to avoid looking stupid */
 
 
3541
                if (alienStatusPointer->Target)
 
 
3542
                {
 
 
3543
                    VECTORCH orientationDirn;
 
 
3544
                    orientationDirn.vx = alienStatusPointer->Target->DynPtr->Position.vx - sbPtr->DynPtr->Position.vx;
 
 
3545
                    orientationDirn.vy = 0;
 
 
3546
                    orientationDirn.vz = alienStatusPointer->Target->DynPtr->Position.vz - sbPtr->DynPtr->Position.vz;
 
 
3547
                    NPCOrientateToVector(sbPtr, &orientationDirn, NPC_TURNRATE);
 
 
3548
                }
 
 
3549
            }
 
 
3550
 
 
 
3551
            if (HModelAnimation_IsFinished(&alienStatusPointer->HModelController))
 
 
3552
            {
 
 
3553
                /* Exit state somehow. */
 
 
3554
                InitWaypointManager(&alienStatusPointer->waypointManager);
 
 
3555
 
 
 
3556
                if (NULL != alienStatusPointer->Target)
 
 
3557
                    alienStatusPointer->BehaviourState = ABS_Wander;
 
 
3558
                else
 
 
3559
                    alienStatusPointer->BehaviourState = sbPtr->DisplayBlock ? ABS_Approach : ABS_Hunt;
 
 
3560
            }
 
 
3561
        }
 
 
3562
        return;
 
 
3563
        default:
 
 
3564
        {
 
 
3565
            if (NULL != alienStatusPointer->Target)
 
 
3566
            {
 
 
3567
                //if(NPC_IsDead(alienStatusPointer->Target) || !NAME_ISEQUAL(alienStatusPointer->Target->SBname, alienStatusPointer->Target_SBname)
|| !AlienHasPathToTarget(sbPtr))
 
 
3568
                if(NPC_IsDead(alienStatusPointer->Target) || !NAME_ISEQUAL(alienStatusPointer->Target->SBname, alienStatusPointer->Target_SBname))
 
 
3569
                {
 
 
3570
                    alienStatusPointer->BehaviourState = ABS_Hunt;
 
 
3571
                    alienStatusPointer->Target = alienStatusPointer->current_attack = NULL;
 
 
3572
                    alienStatusPointer->StateTimer = ALIEN_NEARWAITTIME;
 
 
3573
                    InitWaypointManager(&alienStatusPointer->waypointManager);
 
 
3574
                    NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
3575
                }
 
 
3576
            }
 
 
3577
 
 
 
3578
            if (sbPtr->DisplayBlock || alienStatusPointer->incidentFlag) 
 
 
3579
            {
 
 
3580
                if (alienStatusPointer->Target == NULL) 
 
 
3581
                {
 
 
3582
                    alienStatusPointer->current_attack = NULL;
 
 
3583
                    alienStatusPointer->Target = Alien_GetNewTarget(sbPtr);
 
 
3584
 
 
 
3585
                    if (alienStatusPointer->Target != NULL) 
 
 
3586
                    {
 
 
3587
                        COPY_NAME(alienStatusPointer->Target_SBname, alienStatusPointer->Target->SBname);
 
 
3588
 
 
 
3589
                        alienStatusPointer->StateTimer = ALIEN_FAR_MOVE_TIME;
 
 
3590
                        alienStatusPointer->StateTimer = 0;
 
 
3591
                        alienStatusPointer->BehaviourState = ABS_Approach;
 
 
3592
                    }
 
 
3593
                    else
 
 
3594
                    {
 
 
3595
                        //printf("Alien found no target!\n");
 
 
3596
                        AIMODULE *targetModule = FarNPC_GetTargetAIModuleForHunt(sbPtr, 1);
 
 
3597
 
 
 
3598
                        if (!targetModule || PlayerIsDeadAndNoLivingNetghosts()) 
 
 
3599
                        {
 
 
3600
                            if (alienStatusPointer->BehaviourState != ABS_Wander) 
 
 
3601
                            {
 
 
3602
                                NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
3603
                                alienStatusPointer->StateTimer = ALIEN_FAR_MOVE_TIME;
 
 
3604
                                alienStatusPointer->StateTimer = 0;
 
 
3605
                                alienStatusPointer->BehaviourState = ABS_Wander;
 
 
3606
                            }
 
 
3607
                        }
 
 
3608
                        else if (alienStatusPointer->BehaviourState != ABS_Hunt) 
 
 
3609
                        {
 
 
3610
                            alienStatusPointer->BehaviourState = ABS_Hunt;
 
 
3611
 
 
 
3612
                            if (sbPtr->DisplayBlock)
 
 
3613
                            {
 
 
3614
                                InitWaypointManager(&alienStatusPointer->waypointManager);
 
 
3615
                                alienStatusPointer->StateTimer = ALIEN_NEARWAITTIME;
 
 
3616
                            }
 
 
3617
                            else
 
 
3618
                            {
 
 
3619
                                alienStatusPointer->StateTimer = ALIEN_FAR_MOVE_TIME;
 
 
3620
                            }
 
 
3621
                        }
 
 
3622
                    }
 
 
3623
                }
 
 
3624
            }
 
 
3625
        }
 
 
3626
    }
 
 
3627
 
 
 
3628
    if(sbPtr->DisplayBlock) 
 
 
3629
    {
 
 
3630
        NearAliens++;
 
 
3631
        //printf("Near %s alien is in module %d, %s\n", descriptor, sbPtr->containingModule->m_index, sbPtr->containingModule->name);
 
 
3632
        NearAlienBehaviour(sbPtr);
 
 
3633
    }
 
 
3634
    else
 
 
3635
    {
 
 
3636
        //printf("Far Alien in module %s \n", sbPtr->containingModule->name);
 
 
3637
        FarAliens++;
 
 
3638
        FarAlienBehaviour(sbPtr);
 
 
3639
    }
 
 
3640
 
 
 
3641
    /* Update delta playing flag. */
 
 
3642
    {
 
 
3643
        DELTA_CONTROLLER *hitdelta = Get_Delta_Sequence(&alienStatusPointer->HModelController, "HitDelta");
 
 
3644
 
 
 
3645
        if (hitdelta && DeltaAnimation_IsFinished(hitdelta))
 
 
3646
            hitdelta->Playing = 0;
 
 
3647
    }
 
 
3648
 
 
 
3649
    HModel_Regen(&alienStatusPointer->HModelController, 4 * ONE_FIXED );
 
 
3650
}
 
 
3651
 
 
 
3652
/*----------------------Patrick 7/11/96-----------------------------
 
 
3653
This pair of functions handle the alien visibility switching....
 
 
3654
Note that the ai-pheromone system is maintained by these functions.
 
 
3655
--------------------------------------------------------------------*/
 
 
3656
void MakeAlienNear(STRATEGYBLOCK *sbPtr)
 
 
3657
{
 
 
3658
    /* first of all, see how many aliens are currently near: if there are too many,
 
 
3659
    destroy this alien, and try to force a generator to make a replacement */
 
 
3660
 
 
 
3661
    if(NumGeneratorNPCsVisible() >= MAX_VISIBLEGENERATORNPCS)
 
 
3662
    {
 
 
3663
        sbPtr->please_destroy_me = 1;
 
 
3664
        ForceAGenerator();
 
 
3665
    }
 
 
3666
 
 
 
3667
    DISPLAYBLOCK *dPtr = CreateActiveObject();
 
 
3668
 
 
 
3669
    if(NULL != dPtr)
 
 
3670
    {
 
 
3671
        ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
3672
        DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
 
 
3673
        sbPtr->DisplayBlock = dPtr;
 
 
3674
        dPtr->ObStrategyBlock = sbPtr;
 
 
3675
 
 
 
3676
        /* also need to initialise positional information in the new display block, 
 
 
3677
        from the existing dynamics block.
 
 
3678
        NB this necessary because this function is (usually) called between the 
 
 
3679
        dynamics and rendering systems so it is not initialised by the dynamics 
 
 
3680
        system the first frame it is drawn. */
 
 
3681
        dPtr->ObWorld = dynPtr->Position;
 
 
3682
        dPtr->ObEuler = dynPtr->OrientEuler;
 
 
3683
        dPtr->ObMat = dynPtr->OrientMat;
 
 
3684
 
 
 
3685
        dPtr->HModelControlBlock = &alienStatusPointer->HModelController;
 
 
3686
        ProveHModel(dPtr->HModelControlBlock, dPtr);
 
 
3687
 
 
 
3688
        /* init state timers */
 
 
3689
        alienStatusPointer->StateTimer = 0;
 
 
3690
        alienStatusPointer->StateTimer = ALIEN_FAR_MOVE_TIME;    
 
 
3691
        alienStatusPointer->CurveRadius = alienStatusPointer->CurveLength = alienStatusPointer->CurveTimeOut = 0;
 
 
3692
        InitWaypointManager(&alienStatusPointer->waypointManager);
 
 
3693
        dPtr->HModelControlBlock->Playing = 1;
 
 
3694
    }
 
 
3695
}
 
 
3696
 
 
 
3697
extern DEATH_DATA Alien_Deaths[];
 
 
3698
 
 
 
3699
/* patrick 29/7/97 -----------------------------------
 
 
3700
This function to be called only from behaviour
 
 
3701
-- ChrisF 1/4/98 What a stupid idea. This function ---
 
 
3702
-- to be called only from AlienIsDamaged. ------------
 
 
3703
------------------------------------------------------*/
 
 
3704
static void KillAlien(STRATEGYBLOCK *sbPtr, int wounds, const DAMAGE_PROFILE *damage, VECTORCH *incoming)
 
 
3705
{
 
 
3706
    DEATH_DATA *this_death = NULL;
 
 
3707
    ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
3708
    HIT_FACING facing = { 0,0,0,0 };
 
 
3709
 
 
 
3710
    if (incoming) 
 
 
3711
    {
 
 
3712
        if (incoming->vz > 0) 
 
 
3713
            facing.Back = 1;
 
 
3714
        else
 
 
3715
            facing.Front = 1;
 
 
3716
 
 
 
3717
        if (incoming->vx > 0) 
 
 
3718
            facing.Right = 1;
 
 
3719
        else
 
 
3720
            facing.Left = 1;
 
 
3721
    }
 
 
3722
 
 
 
3723
    /*If alien has a death target ,send a request*/
 
 
3724
    if(alienStatusPointer->death_target_sbptr)
 
 
3725
        RequestState(alienStatusPointer->death_target_sbptr, 1, 0);
 
 
3726
 
 
 
3727
    int deathtype = 0;
 
 
3728
    int electrical = damage->Electrical;
 
 
3729
 
 
 
3730
    switch(damage->Id)
 
 
3731
    {
 
 
3732
        case EXPLOSIONFIRE_BLAST:
 
 
3733
        case AMMO_FRAGMENTATION_GRENADE:
 
 
3734
            alienStatusPointer->GibbFactor = (alienStatusPointer->Type == Standard) ? ONE_FIXED >> 1 : ONE_FIXED >> 3;
 
 
3735
            Extreme_Gibbing(sbPtr, alienStatusPointer->HModelController.section_data, alienStatusPointer->GibbFactor, incoming);
 
 
3736
        break;
 
 
3737
        case AMMO_FLECHETTE: 
 
 
3738
            alienStatusPointer->GibbFactor = ONE_FIXED >> 4;
 
 
3739
            Extreme_Gibbing(sbPtr, alienStatusPointer->HModelController.section_data, alienStatusPointer->GibbFactor, incoming);
 
 
3740
        default:
 
 
3741
        break;
 
 
3742
    }
 
 
3743
 
 
 
3744
    if(alienStatusPointer->sound_mouth == SOUND_NOACTIVEINDEX)
 
 
3745
    {
 
 
3746
        /* make a sound... if you have a head. */
 
 
3747
        SECTION_DATA *chest = GetThisSectionData(alienStatusPointer->HModelController.section_data, "chest");
 
 
3748
 
 
 
3749
        if(NULL != chest)
 
 
3750
        {
 
 
3751
            SECTION_DATA *head = GetThisSectionData(alienStatusPointer->HModelController.section_data, "head");
 
 
3752
 
 
 
3753
            /* Is it still attached? */
 
 
3754
            if (head && !(head->flags & section_data_notreal))
 
 
3755
            {
 
 
3756
                PlayAlienSound((int)alienStatusPointer->Type, ASC_Scream_Dying, 0, &alienStatusPointer->sound_mouth,
&sbPtr->DynPtr->Position);
 
 
3757
                //PlayAlienSound((int)alienStatusPointer->Type, ASC_Death, 0, NULL, &sbPtr->DynPtr->Position);
 
 
3758
 
 
 
3759
                if(NetworkPeer == AvP.PlayMode)
 
 
3760
                    AddNetMsg_SpotAlienSound((int)ASC_Scream_Dying, (int)alienStatusPointer->Type, 0, &sbPtr->DynPtr->Position);
 
 
3761
            }
 
 
3762
        }
 
 
3763
    }
 
 
3764
 
 
 
3765
    if(sbPtr->DynPtr->OrientMat.mat22 < 63000) // should be crouched
 
 
3766
    {
 
 
3767
    }
 
 
3768
    else if(alienStatusPointer->IAmCrouched) // crouched on flat
 
 
3769
    {
 
 
3770
        if (Standard == alienStatusPointer->Type)
 
 
3771
        {
 
 
3772
            if (damage->Electrical)
 
 
3773
            {
 
 
3774
                //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED >> 2), (int)HMSQT_AlienCrawl, (int)ACSS_Pain_Fall_Right, -1,
0);
 
 
3775
                this_death = &Alien_Deaths[1];
 
 
3776
            }
 
 
3777
            else if(facing.Front && damage->ExplosivePower)
 
 
3778
            {
 
 
3779
                //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED >> 4), (int)HMSQT_AlienCrawl, (int)ACSS_Boom_Fall_Back,
ONE_FIXED, 0);
 
 
3780
                this_death = &Alien_Deaths[2];
 
 
3781
            }
 
 
3782
            else
 
 
3783
            {
 
 
3784
                //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED >> 2), (int)HMSQT_AlienCrouch, (int)ACrSS_Dies, -1, 0);
 
 
3785
                this_death = &Alien_Deaths[0];
 
 
3786
            }
 
 
3787
        }
 
 
3788
        else if(Predalien == alienStatusPointer->Type && ((FastRandom() & 65535) < 25000))
 
 
3789
        {
 
 
3790
            //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED >> 2), (int)HMSQT_AlienCrouch, (int)ACrSS_Dies_Thrash, -1, 0);
 
 
3791
            this_death = &Alien_Deaths[9];
 
 
3792
        }
 
 
3793
        else
 
 
3794
        {
 
 
3795
            //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED >> 2), (int)HMSQT_AlienCrouch, (int)ACrSS_Dies, -1, 0);
 
 
3796
            this_death = &Alien_Deaths[0];
 
 
3797
        }
 
 
3798
    }
 
 
3799
    else // standing on flat
 
 
3800
    {
 
 
3801
        if (Standard == alienStatusPointer->Type)
 
 
3802
        {
 
 
3803
            //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>2), (int)HMSQT_AlienStand, (int)ASSS_Boom_Fall_Back, -1, 0); //
not now
 
 
3804
            //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>2), (int)HMSQT_AlienStand, (int)ASSS_Spin_Clockwise, -1, 0); //
now now
 
 
3805
 
 
 
3806
            if(damage->ExplosivePower)
 
 
3807
            {
 
 
3808
                if((FastRandom() & 65535) < 30000)
 
 
3809
                {
 
 
3810
                    //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>2), (int)HMSQT_AlienStand, (int)ASSS_Pain_Fall_Back,
-1, 0);
 
 
3811
                    this_death = &Alien_Deaths[3];
 
 
3812
                }
 
 
3813
                else if(facing.Front)
 
 
3814
                {
 
 
3815
                    //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED >> 2), (int)HMSQT_AlienStand, (int)ASSS_Dies, -1, 0);
 
 
3816
                    this_death = &Alien_Deaths[4];
 
 
3817
                }
 
 
3818
                else if(facing.Back)
 
 
3819
                {
 
 
3820
                    //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>2), (int)HMSQT_AlienStand, (int)ASSS_Boom_Fall_Fwd, -1,
0);
 
 
3821
                    this_death = &Alien_Deaths[6];
 
 
3822
                }
 
 
3823
            }
 
 
3824
            else if(damage->Electrical && ((FastRandom() & 65535) > 20000))
 
 
3825
            {
 
 
3826
                if((FastRandom() & 65535) < 30000)
 
 
3827
                {
 
 
3828
                    //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED >> 2), (int)HMSQT_AlienStand, (int)ASSS_Pain_Fall_Fwd,
-1, 0);
 
 
3829
                    this_death = &Alien_Deaths[5];
 
 
3830
                }
 
 
3831
                else
 
 
3832
                {
 
 
3833
                }
 
 
3834
            }
 
 
3835
            else
 
 
3836
            {
 
 
3837
                if(facing.Front && ((FastRandom() & 65535) < 30000))
 
 
3838
                {
 
 
3839
                    //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>2), (int)HMSQT_AlienStand, (int)ASSS_Dies, -1, 0);
 
 
3840
                    this_death = &Alien_Deaths[4];
 
 
3841
                }
 
 
3842
                else
 
 
3843
                {
 
 
3844
                    switch(FastRandom() % 3)
 
 
3845
                    {
 
 
3846
                    case 0:
 
 
3847
                        //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>2), (int)HMSQT_AlienStand, (int)ASSS_Boom_Fall_Fwd,
-1, 0);
 
 
3848
                        this_death = &Alien_Deaths[6];
 
 
3849
                    break;
 
 
3850
                    case 1:
 
 
3851
                        //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>2), (int)HMSQT_AlienStand,
(int)ASSS_Pain_Fall_Back, -1, 0);
 
 
3852
                        this_death = &Alien_Deaths[3];
 
 
3853
                    break;
 
 
3854
                    case 2:
 
 
3855
                        //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>2), (int)HMSQT_AlienStand, (int)ASSS_Pain_Fall_Fwd,
-1, 0);
 
 
3856
                        this_death = &Alien_Deaths[5];
 
 
3857
                    }
 
 
3858
                }
 
 
3859
            }
 
 
3860
        }
 
 
3861
        else if (Predalien == alienStatusPointer->Type)
 
 
3862
        {
 
 
3863
            switch(FastRandom() % 4)
 
 
3864
            {
 
 
3865
            case 0:
 
 
3866
                //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED >> 2), (int)HMSQT_AlienStand, (int)ASSS_Pain_Fall_Back, -1,
0);
 
 
3867
                this_death = &Alien_Deaths[3];
 
 
3868
            break;
 
 
3869
            case 1:
 
 
3870
                //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED >> 2), (int)HMSQT_AlienStand, (int)ASSS_Dies, -1, 0);
 
 
3871
                this_death = &Alien_Deaths[4];
 
 
3872
            break;
 
 
3873
            case 2:
 
 
3874
                //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED >> 2), (int)HMSQT_AlienStand, (int)ASSS_Pain_Fall_Fwd, -1,
0);
 
 
3875
                this_death = &Alien_Deaths[5];
 
 
3876
            break;
 
 
3877
            case 3:
 
 
3878
                //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED >> 4), (int)HMSQT_AlienStand, (int)ASSS_Boom_Fall_Fwd, -1,
0);
 
 
3879
                this_death = &Alien_Deaths[6];
 
 
3880
            }
 
 
3881
    /*
 
 
3882
            if(facing.Front)
 
 
3883
            {
 
 
3884
                if(fall_back)
 
 
3885
                {
 
 
3886
                    //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED >> 2), (int)HMSQT_AlienStand, (int)ASSS_Dies, -1, 0);
 
 
3887
                    this_death = &Alien_Deaths[4];
 
 
3888
                }
 
 
3889
                else
 
 
3890
                {
 
 
3891
                    if((FastRandom() & 65535) > 20000)
 
 
3892
                    {
 
 
3893
                        //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED >> 2), (int)HMSQT_AlienStand,
(int)ASSS_Pain_Fall_Fwd, -1, 0);
 
 
3894
                        this_death = &Alien_Deaths[5];
 
 
3895
                    }
 
 
3896
                    else
 
 
3897
                    {
 
 
3898
                        //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED >> 2), (int)HMSQT_AlienStand, (int)ASSS_Dies, -1,
0);
 
 
3899
                        this_death = &Alien_Deaths[4];
 
 
3900
                    }
 
 
3901
                }
 
 
3902
            }
 
 
3903
            else
 
 
3904
            {
 
 
3905
                if(fall_back)
 
 
3906
                {
 
 
3907
                    //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED >> 2), (int)HMSQT_AlienStand, (int)ASSS_Pain_Fall_Fwd,
-1, 0);
 
 
3908
                    this_death = &Alien_Deaths[5];
 
 
3909
                }
 
 
3910
                else
 
 
3911
                {
 
 
3912
                    if((FastRandom() & 65535) > 20000)
 
 
3913
                    {
 
 
3914
                        //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED >> 2), (int)HMSQT_AlienStand,
(int)ASSS_Pain_Fall_Back, -1, 0);
 
 
3915
                        this_death = &Alien_Deaths[3];
 
 
3916
                    }
 
 
3917
                    else
 
 
3918
                    {
 
 
3919
                        //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED >> 4), (int)HMSQT_AlienStand,
(int)ASSS_Boom_Fall_Fwd, -1, 0);
 
 
3920
                        this_death = &Alien_Deaths[6];
 
 
3921
                    }
 
 
3922
                }
 
 
3923
            }
 
 
3924
    */
 
 
3925
        }
 
 
3926
        else
 
 
3927
        {
 
 
3928
            //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED >> 2), (int)HMSQT_AlienStand, (int)ASSS_Boom_Fall_Back, -1, 0);
// not now
 
 
3929
 
 
 
3930
            if(damage->Electrical)
 
 
3931
            {
 
 
3932
                //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>2), (int)HMSQT_AlienStand, (int)ASSS_Pain_Fall_Back, -1,
0);
 
 
3933
                this_death = &Alien_Deaths[3];
 
 
3934
            }
 
 
3935
            else if(facing.Front)
 
 
3936
            {
 
 
3937
                if(damage->ExplosivePower)
 
 
3938
                {
 
 
3939
                    //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>2), (int)HMSQT_AlienStand, (int)ASSS_Spin_Clockwise,
-1, 0);
 
 
3940
                    this_death = &Alien_Deaths[8];
 
 
3941
                }
 
 
3942
                else
 
 
3943
                {
 
 
3944
                    switch(FastRandom() % 3)
 
 
3945
                    {
 
 
3946
                        case 0:
 
 
3947
                            //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED >> 2), (int)HMSQT_AlienStand, (int)ASSS_Dies,
-1, 0);
 
 
3948
                            this_death = &Alien_Deaths[4];
 
 
3949
                        break;
 
 
3950
                        case 1:
 
 
3951
                            //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>2), (int)HMSQT_AlienStand,
(int)ASSS_Pain_Fall_Back, -1, 0);
 
 
3952
                            this_death = &Alien_Deaths[3];
 
 
3953
                        break;
 
 
3954
                        case 2:
 
 
3955
                            //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>2), (int)HMSQT_AlienStand,
(int)ASSS_Boom_Fall_Fwd, -1, 0);
 
 
3956
                            this_death = &Alien_Deaths[6];
 
 
3957
                    }
 
 
3958
                }
 
 
3959
            }
 
 
3960
            else
 
 
3961
            {
 
 
3962
                if((FastRandom() & 65535) < 20000)
 
 
3963
                {
 
 
3964
                    //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>2), (int)HMSQT_AlienStand, (int)ASSS_Pain_Fall_Back,
-1, 0);
 
 
3965
                    this_death = &Alien_Deaths[3];
 
 
3966
                }
 
 
3967
                else
 
 
3968
                {
 
 
3969
                    //InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>2), (int)HMSQT_AlienStand, (int)ASSS_Boom_Fall_Fwd, -1,
0);
 
 
3970
                    this_death = &Alien_Deaths[6];
 
 
3971
                }
 
 
3972
            }
 
 
3973
        }
 
 
3974
    }
 
 
3975
 
 
 
3976
if(this_death == NULL)
 
 
3977
this_death = GetAlienDeathSequence(&alienStatusPointer->HModelController, NULL, alienStatusPointer->Wounds, alienStatusPointer->Wounds, deathtype,
&facing, 0, alienStatusPointer->IAmCrouched, electrical);
 
 
3978
 
 
 
3979
    Convert_Alien_To_Corpse(sbPtr, this_death, damage);
 
 
3980
}
 
 
3981
 
 
 
3982
/*----------------------Patrick 7/11/96-----------------------------
 
 
3983
Handle weapon impact on an alien
 
 
3984
--------------------------------------------------------------------*/
 
 
3985
/* KJL 11:46:43 12/17/96 - rewritten */
 
 
3986
 
 
 
3987
// JB 16/6/97 rewritten
 
 
3988
// Patrick 29/7/97 rewritten again. again.
 
 
3989
// ChrisF 16/9/97 rewritten again again, again.
 
 
3990
// ChrisF 26/11/97 rewritten again, again, again, again.
 
 
3991
// ChrisF 1/4/98 rewritten again again again again again.  Okay, 'modified' then. Added directional parameter.
 
 
3992
// ChrisF 20/11/98 rewritten again again again again again again, added hit delta support.
 
 
3993
// ChrisF 15/2/99 rewritten again again again again again again again, added fragging noise.
 
 
3994
 
 
 
3995
void AlienIsDamaged(STRATEGYBLOCK *sbPtr, const DAMAGE_PROFILE *damage, int multiple, int wounds, SECTION_DATA *Section, VECTORCH *incoming)
 
 
3996
{
 
 
3997
    ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
3998
 
 
 
3999
    alienStatusPointer->Wounds |= wounds;
 
 
4000
 
 
 
4001
    alienStatusPointer->CanStand = !((alienStatusPointer->Wounds & (section_flag_left_leg | section_flag_right_leg))
 
 
4002
    || ((alienStatusPointer->Wounds & section_flag_left_foot) && (alienStatusPointer->Wounds & section_flag_right_foot)));
 
 
4003
 
 
 
4004
    /* Can only climb if alien has both hands... */
 
 
4005
    alienStatusPointer->CanClimb = !((alienStatusPointer->Wounds & section_flag_left_hand) || (alienStatusPointer->Wounds &
section_flag_right_hand));
 
 
4006
 
 
 
4007
    //if(!(alienStatusPointer->CanStand && alienStatusPointer->CanClimb))
 
 
4008
 
 
 
4009
    if(!alienStatusPointer->CanStand)
 
 
4010
        alienStatusPointer->IAmCrouched = 1;
 
 
4011
 
 
 
4012
    //if (incoming) printf("Alien hit from %d %d %d\n", incoming->vx, incoming->vy, incoming->vz);
 
 
4013
 
 
 
4014
    if(incoming && damage->ExplosivePower)
 
 
4015
        sbPtr->DynPtr->UseStandardGravity = 1;
 
 
4016
 
 
 
4017
    if (sbPtr->DamageBlock.Health <= 0)
 
 
4018
    {
 
 
4019
        if (AvP.PlayerType != I_Alien)
 
 
4020
            CurrentGameStats_CreatureKilled(sbPtr, Section);
 
 
4021
 
 
 
4022
        sbPtr->DynPtr->UseStandardGravity = 1;
 
 
4023
        KillAlien(sbPtr, wounds, damage, incoming);
 
 
4024
    }
 
 
4025
    else //if(!alienStatusPointer->unconscious)
 
 
4026
    {
 
 
4027
    if(0)
 
 
4028
        switch(alienStatusPointer->BehaviourState)
 
 
4029
        {
 
 
4030
            case ABS_Dormant:
 
 
4031
                Alien_Awaken(sbPtr);
 
 
4032
            break;
 
 
4033
            default:
 
 
4034
                if(NULL == alienStatusPointer->Target)
 
 
4035
                {
 
 
4036
                    NPC_OBSTRUCTIONREPORT obstruction = {0, 0, 1, 0};
 
 
4037
                    NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
4038
                    NPCGetAvoidanceDirection(sbPtr, &alienStatusPointer->moveData.avoidanceDirn, &obstruction);
 
 
4039
                    alienStatusPointer->BehaviourState = ABS_Avoidance;
 
 
4040
                    alienStatusPointer->StateTimer = NPC_AVOIDTIME;
 
 
4041
                    //alienStatusPointer->BehaviourState = ABS_Retreat;
 
 
4042
                    puts("no target");
 
 
4043
                }
 
 
4044
                else if((FastRandom() & 32) < 11)
 
 
4045
                {
 
 
4046
                puts("Target");
 
 
4047
                    NPC_OBSTRUCTIONREPORT obstruction = {0, 0, 1, 0};
 
 
4048
                    NPC_InitMovementData(&alienStatusPointer->moveData);
 
 
4049
                    NPCGetAvoidanceDirection(sbPtr, &alienStatusPointer->moveData.avoidanceDirn, &obstruction);
 
 
4050
                    alienStatusPointer->BehaviourState = ABS_Avoidance;
 
 
4051
                    alienStatusPointer->StateTimer = NPC_AVOIDTIME/8;
 
 
4052
                }
 
 
4053
        }
 
 
4054
 
 
 
4055
    if(!alienStatusPointer->CanStand)
 
 
4056
        SetAlienShapeAnimSequence_Core(sbPtr, HMSQT_AlienCrawl, ACSS_Crawl_Hurt, ONE_FIXED >> 1, (ONE_FIXED >> 2));
 
 
4057
 
 
 
4058
        if(((alienStatusPointer->Wounds & section_flag_left_arm) && (alienStatusPointer->Wounds & section_flag_right_arm))
 
 
4059
        ||
 
 
4060
        ((alienStatusPointer->Wounds & section_flag_left_hand) && (alienStatusPointer->Wounds & section_flag_right_hand)))
 
 
4061
        {
 
 
4062
            alienStatusPointer->MaxSpeed = 800;
 
 
4063
        }
 
 
4064
        else
 
 
4065
        {
 
 
4066
            RecomputeAlienSpeed(sbPtr);
 
 
4067
        }
 
 
4068
 
 
 
4069
        /* Now, get anim speed. */
 
 
4070
 
 
 
4071
        HMODEL_SEQUENCE_TYPES sequence_type = (HMODEL_SEQUENCE_TYPES)alienStatusPointer->HModelController.Sequence_Type;
 
 
4072
 
 
 
4073
        int subsequence = alienStatusPointer->HModelController.Sub_Sequence;
 
 
4074
        /* That is what the controller thinks the shape is playing. */
 
 
4075
 
 
 
4076
        int factor = GetAlienSpeedFactor_ForSequence(sbPtr, sequence_type, subsequence);
 
 
4077
        int changespeed = 0;
 
 
4078
 
 
 
4079
        switch (alienStatusPointer->Type)
 
 
4080
        {
 
 
4081
            case Standard:
 
 
4082
                if (factor != ONE_FIXED)
 
 
4083
                    changespeed = 1;
 
 
4084
            break;
 
 
4085
            case Predalien:
 
 
4086
                if (factor != PREDALIEN_SPEED_FACTOR)
 
 
4087
                    changespeed = 1;
 
 
4088
            break;
 
 
4089
            case Praetorian:
 
 
4090
                if (factor != PRAETORIAN_SPEED_FACTOR)
 
 
4091
                    changespeed = 1;
 
 
4092
            default:
 
 
4093
            break;
 
 
4094
        }
 
 
4095
 
 
 
4096
        if (changespeed)
 
 
4097
        {
 
 
4098
            /* ONE_FIXED implies we're playing an invariant length anim. */
 
 
4099
            int newspeed = DIV_FIXED(alienStatusPointer->last_anim_length, factor);
 
 
4100
 
 
 
4101
            HModel_ChangeSpeed(&alienStatusPointer->HModelController, newspeed);
 
 
4102
        }
 
 
4103
 
 
 
4104
        if (alienStatusPointer->sound_mouth == SOUND_NOACTIVEINDEX)
 
 
4105
        {
 
 
4106
            int pitch = (FastRandom() & 255) - 128;
 
 
4107
 
 
 
4108
            PlayAlienSound((int)alienStatusPointer->Type, ASC_Scream_Hurt, pitch, &alienStatusPointer->sound_mouth,
&sbPtr->DynPtr->Position);
 
 
4109
 
 
 
4110
            if(NetworkPeer == AvP.PlayMode)
 
 
4111
                AddNetMsg_SpotAlienSound(ASC_Scream_Hurt, (int)alienStatusPointer->Type, pitch, &sbPtr->DynPtr->Position);
 
 
4112
        }
 
 
4113
 
 
 
4114
        if (TotalKineticDamage(damage) >= 10)
 
 
4115
        {
 
 
4116
            int frontback = 1;
 
 
4117
 
 
 
4118
            if (incoming && (incoming->vz >= 0))
 
 
4119
                frontback = 0;
 
 
4120
 
 
 
4121
            if (frontback)
 
 
4122
            {
 
 
4123
                DELTA_CONTROLLER *hitdelta = Get_Delta_Sequence(&alienStatusPointer->HModelController, "HitDelta");
 
 
4124
 
 
 
4125
                /* Only do it from the front. */
 
 
4126
                if (hitdelta && !hitdelta->Playing)
 
 
4127
                {
 
 
4128
                    if(damage->ExplosivePower && (sbPtr->DynPtr->OrientMat.mat22 > 63000))
 
 
4129
                    {
 
 
4130
                        if(!alienStatusPointer->IAmCrouched)
 
 
4131
                        {
 
 
4132
                            if ((Praetorian == alienStatusPointer->Type) && ((FastRandom() & 65535) < 30000))
 
 
4133
                                InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>3), (int)HMSQT_AlienStand,
(int)ASSS_Spin_Clockwise, -1, 0);
 
 
4134
                            else
 
 
4135
                                InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED >> 2), (int)HMSQT_AlienStand, (int)ASSS_Dies,
-1, 0);
 
 
4136
 
 
 
4137
                            alienStatusPointer->unconscious = ONE_FIXED * 5 + ( (FastRandom() & 7) * ONE_FIXED);
 
 
4138
                        }
 
 
4139
                        else if ((Standard == alienStatusPointer->Type) && ((FastRandom() & 65535) < 30000))
 
 
4140
                        {
 
 
4141
                            InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED >> 4), (int)HMSQT_AlienCrawl,
(int)ACSS_Boom_Fall_Back, ONE_FIXED, 0);
 
 
4142
                            alienStatusPointer->unconscious = ONE_FIXED * 6 + ( (FastRandom() & 7) * ONE_FIXED);
 
 
4143
                        }
 
 
4144
                    }
 
 
4145
                    else
 
 
4146
                    {
 
 
4147
                        /* A hierarchy with hit deltas! */
 
 
4148
                        int CrouchSubSequence;
 
 
4149
                        int StandSubSequence;
 
 
4150
 
 
 
4151
                        if (Section == NULL)
 
 
4152
                        {
 
 
4153
                            if ((FastRandom() & 65535) < 32767)
 
 
4154
                            {
 
 
4155
                                CrouchSubSequence = ACrSS_Hit_Left;
 
 
4156
                                StandSubSequence = ASSS_Hit_Left;
 
 
4157
                            }
 
 
4158
                            else
 
 
4159
                            {
 
 
4160
                                CrouchSubSequence = ACrSS_Hit_Right;
 
 
4161
                                StandSubSequence = ASSS_Hit_Right;
 
 
4162
                            }
 
 
4163
                        }
 
 
4164
                        else if ((Section->sempai->flags & section_flag_left_arm) || (Section->sempai->flags & section_flag_left_hand))
 
 
4165
                        {
 
 
4166
                            CrouchSubSequence = ACrSS_Hit_Left;
 
 
4167
                            StandSubSequence = ASSS_Hit_Left;
 
 
4168
                        }
 
 
4169
                        else if ((Section->sempai->flags & section_flag_right_arm) || (Section->sempai->flags & section_flag_right_hand))
 
 
4170
                        {
 
 
4171
                            CrouchSubSequence = ACrSS_Hit_Right;
 
 
4172
                            StandSubSequence = ASSS_Hit_Right;
 
 
4173
                        }
 
 
4174
                        else
 
 
4175
                        {
 
 
4176
                            /* Chest or misc. hit. */
 
 
4177
                            if ((FastRandom() & 65535) < 32767)
 
 
4178
                            {
 
 
4179
                                CrouchSubSequence = ACrSS_Hit_Left;
 
 
4180
                                StandSubSequence = ASSS_Hit_Left;
 
 
4181
                            }
 
 
4182
                            else
 
 
4183
                            {
 
 
4184
                                CrouchSubSequence = ACrSS_Hit_Right;
 
 
4185
                                StandSubSequence = ASSS_Hit_Right;
 
 
4186
                            }
 
 
4187
                        }
 
 
4188
 
 
 
4189
                        if(alienStatusPointer->IAmCrouched)
 
 
4190
                        {
 
 
4191
                            if (HModelSequence_Exists(&alienStatusPointer->HModelController, (int)HMSQT_AlienCrouch, CrouchSubSequence))
 
 
4192
                                Start_Delta_Sequence(hitdelta, (int)HMSQT_AlienCrouch, CrouchSubSequence, -1);
 
 
4193
                        }
 
 
4194
                        else
 
 
4195
                        {
 
 
4196
                            if (HModelSequence_Exists(&alienStatusPointer->HModelController, (int)HMSQT_AlienStand, StandSubSequence))
 
 
4197
                                Start_Delta_Sequence(hitdelta, (int)HMSQT_AlienStand, StandSubSequence, -1);
 
 
4198
                        }
 
 
4199
 
 
 
4200
                        hitdelta->Playing = 1;
 
 
4201
                    }
 
 
4202
                }
 
 
4203
                else if(damage->ExplosivePower && (sbPtr->DynPtr->OrientMat.mat22 > 63000))
 
 
4204
                {
 
 
4205
                    if(!alienStatusPointer->IAmCrouched)
 
 
4206
                    {
 
 
4207
                        if ((Praetorian == alienStatusPointer->Type) && ((FastRandom() & 65535) < 30000))
 
 
4208
                            InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED>>3), (int)HMSQT_AlienStand,
(int)ASSS_Spin_Clockwise, -1, 0);
 
 
4209
                        else
 
 
4210
                            InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED >> 2), (int)HMSQT_AlienStand, (int)ASSS_Dies, -1,
0);
 
 
4211
 
 
 
4212
                        alienStatusPointer->unconscious = ONE_FIXED * 5 + ( (FastRandom() & 7) * ONE_FIXED);
 
 
4213
                    }
 
 
4214
                    else if ((Standard == alienStatusPointer->Type) && ((FastRandom() & 65535) < 30000))
 
 
4215
                    {
 
 
4216
                        InitHModelTweening(&alienStatusPointer->HModelController, (ONE_FIXED >> 4), (int)HMSQT_AlienCrawl,
(int)ACSS_Boom_Fall_Back, ONE_FIXED, 0);
 
 
4217
                        alienStatusPointer->unconscious = ONE_FIXED * 6 + ( (FastRandom() & 7) * ONE_FIXED);
 
 
4218
                    }
 
 
4219
                }
 
 
4220
            }
 
 
4221
        }
 
 
4222
    }
 
 
4223
}
 
 
4224
 
 
 
4225
/*--------------------**
 
 
4226
** Loading and Saving **
 
 
4227
**--------------------*/
 
 
4228
#include "savegame.h"
 
 
4229
typedef struct alien_save_block
 
 
4230
{
 
 
4231
    SAVE_BLOCK_STRATEGY_HEADER header;
 
 
4232
 
 
 
4233
    ALIEN_TYPE Type;
 
 
4234
    int GibbFactor;
 
 
4235
    int Wounds;
 
 
4236
    int last_anim_length;
 
 
4237
    ALIEN_BHSTATE BehaviourState;    
 
 
4238
 
 
 
4239
    int incidentFlag;
 
 
4240
    int incidentTimer;
 
 
4241
 
 
 
4242
    int CurveRadius;
 
 
4243
    int CurveLength;
 
 
4244
    int CurveTimeOut;
 
 
4245
    int StateTimer;
 
 
4246
    int IAmCrouched;
 
 
4247
    int CurrentLightAtAlien;
 
 
4248
    int unconscious;
 
 
4249
    int CanStand;
 
 
4250
    int CanClimb;
 
 
4251
    int huntingModuleIndex;
 
 
4252
    int currentAttackCode;
 
 
4253
//    NPC_MOVEMENTDATA moveData;
 
 
4254
    NPC_WANDERDATA wanderData;
 
 
4255
 
 
 
4256
//    HMODELCONTROLLER HModelController;
 
 
4257
 
 
 
4258
//    STRATEGYBLOCK* generator_sbptr;//0 unless created by a generator
 
 
4259
 
 
 
4260
    char Target_SBname[SB_NAME_LENGTH];
 
 
4261
    char Generator_SBname[SB_NAME_LENGTH];
 
 
4262
 
 
 
4263
    //strategyblock stuff
 
 
4264
    DAMAGEBLOCK DamageBlock;
 
 
4265
    DYNAMICSBLOCK dynamics;
 
 
4266
 
 
 
4267
} ALIEN_SAVE_BLOCK;
 
 
4268
 
 
 
4269
//defines for load/save macros
 
 
4270
#define SAVELOAD_BLOCK block
 
 
4271
#define SAVELOAD_BEHAV alienStatusPointer
 
 
4272
 
 
 
4273
void LoadStrategy_Alien(SAVE_BLOCK_STRATEGY_HEADER* header)
 
 
4274
{
 
 
4275
    ALIEN_STATUS_BLOCK* alienStatusPointer;
 
 
4276
    ALIEN_SAVE_BLOCK* block = (ALIEN_SAVE_BLOCK*) header; 
 
 
4277
 
 
 
4278
    //check the size of the save block
 
 
4279
    if(header->size != sizeof(*block))
 
 
4280
        return;
 
 
4281
 
 
 
4282
    //find the existing strategy block
 
 
4283
    STRATEGYBLOCK* sbPtr = FindSBWithName(header->SBname);
 
 
4284
 
 
 
4285
    if(sbPtr)
 
 
4286
    {
 
 
4287
        //make sure the strategy found is of the right type
 
 
4288
        if(sbPtr->type != I_BehaviourAlien)
 
 
4289
            return;
 
 
4290
    }
 
 
4291
    else
 
 
4292
    {
 
 
4293
        //we will have to generate an alien then
 
 
4294
        TOOLS_DATA_ALIEN tda;
 
 
4295
 
 
 
4296
        //make sure the alien is in a module 
 
 
4297
        if(!ModuleFromPosition(&block->dynamics.Position, NULL))
 
 
4298
            return;
 
 
4299
 
 
 
4300
        sbPtr = CreateActiveStrategyBlock(I_BehaviourAlien);
 
 
4301
 
 
 
4302
        if(!sbPtr)
 
 
4303
            return;
 
 
4304
 
 
 
4305
        sbPtr->maintainVisibility = 1;
 
 
4306
        COPY_NAME(sbPtr->SBname,block->header.SBname);
 
 
4307
 
 
 
4308
        //create using a fake tools data
 
 
4309
        tda.position = block->dynamics.Position;
 
 
4310
        COPY_NAME(tda.nameID, block->header.SBname);
 
 
4311
        COPY_NAME(tda.death_target_ID, Null_Name);
 
 
4312
        tda.type = block->Type;
 
 
4313
        tda.start_inactive = 0;
 
 
4314
 
 
 
4315
        tda.starteuler.EulerX = tda.starteuler.EulerY = tda.starteuler.EulerZ = 0;
 
 
4316
 
 
 
4317
         EnableBehaviourType(sbPtr, &tda);
 
 
4318
     }
 
 
4319
 
 
 
4320
    alienStatusPointer = (ALIEN_STATUS_BLOCK*)sbPtr->dataptr;
 
 
4321
 
 
 
4322
    //start copying stuff
 
 
4323
 
 
 
4324
    COPYELEMENT_LOAD(Type)
 
 
4325
    COPYELEMENT_LOAD(GibbFactor)
 
 
4326
    COPYELEMENT_LOAD(Wounds)
 
 
4327
    COPYELEMENT_LOAD(last_anim_length)
 
 
4328
    COPYELEMENT_LOAD(BehaviourState)
 
 
4329
    COPYELEMENT_LOAD(incidentFlag)
 
 
4330
    COPYELEMENT_LOAD(incidentTimer)
 
 
4331
    COPYELEMENT_LOAD(CurveRadius)
 
 
4332
    COPYELEMENT_LOAD(CurveLength)
 
 
4333
    COPYELEMENT_LOAD(CurveTimeOut)
 
 
4334
    COPYELEMENT_LOAD(StateTimer)
 
 
4335
    COPYELEMENT_LOAD(IAmCrouched)
 
 
4336
    COPYELEMENT_LOAD(CurrentLightAtAlien)
 
 
4337
    COPYELEMENT_LOAD(unconscious)
 
 
4338
    COPYELEMENT_LOAD(CanStand)
 
 
4339
    COPYELEMENT_LOAD(CanClimb)
 
 
4340
    COPYELEMENT_LOAD(wanderData)
 
 
4341
 
 
 
4342
    //load target
 
 
4343
    COPY_NAME(alienStatusPointer->Target_SBname,block->Target_SBname);
 
 
4344
    alienStatusPointer->Target = FindSBWithName(alienStatusPointer->Target_SBname);
 
 
4345
 
 
 
4346
    //load hunting module
 
 
4347
    if(block->huntingModuleIndex >= 0 && block->huntingModuleIndex < AIModuleArraySize)
 
 
4348
        alienStatusPointer->huntingModule = &AIModuleArray[block->huntingModuleIndex];
 
 
4349
    else
 
 
4350
        alienStatusPointer->huntingModule = NULL;
 
 
4351
 
 
 
4352
    //get the alien's attack from the attack code
 
 
4353
    alienStatusPointer->current_attack = GetThisAttack_FromUniqueCode(block->currentAttackCode);
 
 
4354
 
 
 
4355
    *sbPtr->DynPtr = block->dynamics;
 
 
4356
    sbPtr->DamageBlock = block->DamageBlock;
 
 
4357
 
 
 
4358
    //find the alien's generator
 
 
4359
    alienStatusPointer->generator_sbptr = FindSBWithName(block->Generator_SBname);
 
 
4360
 
 
 
4361
    //load the aliens hierarchy
 
 
4362
    {
 
 
4363
        SAVE_BLOCK_HEADER* hier_header = GetNextBlockIfOfType(SaveBlock_Hierarchy);
 
 
4364
 
 
 
4365
        if(hier_header)
 
 
4366
            LoadHierarchy(hier_header,&alienStatusPointer->HModelController);
 
 
4367
    }
 
 
4368
 
 
 
4369
    Load_SoundState(&alienStatusPointer->soundOnFire);
 
 
4370
    Load_SoundState(&alienStatusPointer->sound_mouth);
 
 
4371
}
 
 
4372
 
 
 
4373
void SaveStrategy_Alien(STRATEGYBLOCK* sbPtr)
 
 
4374
{
 
 
4375
    ALIEN_SAVE_BLOCK *block;
 
 
4376
    ALIEN_STATUS_BLOCK* alienStatusPointer = (ALIEN_STATUS_BLOCK*)sbPtr->dataptr;
 
 
4377
 
 
 
4378
    GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
 
 
4379
 
 
 
4380
    //start copying stuff
 
 
4381
 
 
 
4382
    COPYELEMENT_SAVE(Type)
 
 
4383
    COPYELEMENT_SAVE(GibbFactor)
 
 
4384
    COPYELEMENT_SAVE(Wounds)
 
 
4385
    COPYELEMENT_SAVE(last_anim_length)
 
 
4386
    COPYELEMENT_SAVE(BehaviourState)
 
 
4387
    COPYELEMENT_SAVE(incidentFlag)
 
 
4388
    COPYELEMENT_SAVE(incidentTimer)
 
 
4389
    COPYELEMENT_SAVE(CurveRadius)
 
 
4390
    COPYELEMENT_SAVE(CurveLength)
 
 
4391
    COPYELEMENT_SAVE(CurveTimeOut)
 
 
4392
    COPYELEMENT_SAVE(StateTimer)
 
 
4393
    COPYELEMENT_SAVE(IAmCrouched)
 
 
4394
    COPYELEMENT_SAVE(CurrentLightAtAlien)
 
 
4395
    COPYELEMENT_LOAD(unconscious)
 
 
4396
    COPYELEMENT_LOAD(CanStand)
 
 
4397
    COPYELEMENT_LOAD(CanClimb)
 
 
4398
    COPYELEMENT_SAVE(wanderData)
 
 
4399
 
 
 
4400
    //save target
 
 
4401
    COPY_NAME(block->Target_SBname,alienStatusPointer->Target_SBname);
 
 
4402
 
 
 
4403
    //save hunting module
 
 
4404
    if(alienStatusPointer->huntingModule)
 
 
4405
        block->huntingModuleIndex = alienStatusPointer->huntingModule->m_index;
 
 
4406
    else
 
 
4407
        block->huntingModuleIndex = -1;
 
 
4408
 
 
 
4409
    //save attack code
 
 
4410
    if(alienStatusPointer->current_attack)
 
 
4411
        block->currentAttackCode = alienStatusPointer->current_attack->Unique_Code;
 
 
4412
    else
 
 
4413
        block->currentAttackCode = -1;
 
 
4414
 
 
 
4415
    //save the alien's generator name
 
 
4416
    if(alienStatusPointer->generator_sbptr)
 
 
4417
    {
 
 
4418
        COPY_NAME(block->Generator_SBname, alienStatusPointer->generator_sbptr->SBname);
 
 
4419
    }
 
 
4420
    else
 
 
4421
    {
 
 
4422
        COPY_NAME(block->Generator_SBname, Null_Name);
 
 
4423
    }
 
 
4424
 
 
 
4425
    block->dynamics = *sbPtr->DynPtr;
 
 
4426
    block->dynamics.CollisionReportPtr = 0;
 
 
4427
    block->DamageBlock = sbPtr->DamageBlock;
 
 
4428
 
 
 
4429
    //save the aliens hierarchy
 
 
4430
    SaveHierarchy(&alienStatusPointer->HModelController);
 
 
4431
 
 
 
4432
    Save_SoundState(&alienStatusPointer->soundOnFire);
 
 
4433
    Save_SoundState(&alienStatusPointer->sound_mouth);
 
 
4434
}