4b825dc642cb6eb9a060e54bf8d69288fbee4904ebd360ec63ec976c05699f3180e866b3f69e5472
 
 
1
#include "system.h"
 
 
2
#include "species_sound.h"
 
 
3
#include "stratdef.h"
 
 
4
#include "bh_types.h"
 
 
5
#include "debris.h"
 
 
6
#include "npc_alien.h"
 
 
7
#include "npc_marine.h"
 
 
8
#include "corpse.h"
 
 
9
#include <assert.h>
 
 
10
#include "weaponbehaviour.h"
 
 
11
#include "pldghost.h"
 
 
12
#include "weapons.h"
 
 
13
#include "dynamics.h"
 
 
14
#include <stdio.h>
 
 
15
#include <string.h>
 
 
16
#include <stdlib.h>
 
 
17
 
 
 
18
#define HDEBRIS_BLEEDING_TIME    (ONE_FIXED*2)
 
 
19
 
 
 
20
extern int NumActiveBlocks;
 
 
21
extern SECTION * GetNamedHierarchyFromLibrary(const char * rif_name, const char * hier_name);
 
 
22
extern int GetLoadedShapeMSL(char const * shapename);
 
 
23
extern struct shapefragmentdesc * GetFragDesc(int shapeIndex);
 
 
24
extern MATRIXCH IdentityMatrix;
 
 
25
 
 
 
26
extern void SetSeededFastRandom(int seed);
 
 
27
 
 
 
28
static int generate_random_between (int first, int second)
 
 
29
{
 
 
30
    int diff = second - first;
 
 
31
 
 
 
32
    if (!diff)
 
 
33
        return first;
 
 
34
 
 
 
35
    int absdiff = abs (diff);
 
 
36
    int rand_no = FastRandom () % absdiff;
 
 
37
 
 
 
38
return ( (diff < 0) ? (second + rand_no) : (first + rand_no));
 
 
39
}
 
 
40
 
 
 
41
void MakeFragments(STRATEGYBLOCK * sbptr)
 
 
42
{
 
 
43
    VECTORCH diff;
 
 
44
 
 
 
45
    if( (NumActiveBlocks > maxobjects-5) || (NumActiveStBlocks > maxstblocks-5))
 
 
46
        return;
 
 
47
 
 
 
48
    if (!sbptr->DynPtr || !sbptr->DisplayBlock)
 
 
49
        return;
 
 
50
 
 
 
51
    VECTORCH * posPtr = &sbptr->DynPtr->Position;
 
 
52
    struct shapefragmentdesc * fragdesc = GetFragDesc(sbptr->shapeIndex);
 
 
53
 
 
 
54
    if(NULL == fragdesc)
 
 
55
    {
 
 
56
          Sound_Play(SID_EXPLOSION, "d", posPtr);  
 
 
57
        return;
 
 
58
    }
 
 
59
    else if(NULL == fragdesc->sh_fragsound)
 
 
60
    {
 
 
61
          Sound_Play(SID_EXPLOSION, "d", posPtr);  
 
 
62
    }
 
 
63
    else
 
 
64
    {
 
 
65
        SHAPEFRAGMENTSOUND * fragsound = fragdesc->sh_fragsound;
 
 
66
 
 
 
67
        if(SID_NOSOUND != fragsound->sound_number)
 
 
68
        {
 
 
69
              Sound_Play((SOUNDINDEX)fragsound->sound_number, "d", posPtr);  
 
 
70
 
 
 
71
            /*
 
 
72
                SOUND3DDATA s3d;
 
 
73
                s3d.position = *posPtr;
 
 
74
                s3d.inner_range = fragsound->inner_range;
 
 
75
                s3d.outer_range = fragsound->outer_range;
 
 
76
                s3d.velocity.vx = s3d.velocity.vy = s3d.velocity.vz = 0;
 
 
77
                Sound_Play ((SOUNDINDEX)fragsound->sound_number, "nvp", &s3d, fragsound->max_volume, fragsound->pitch);
 
 
78
            */
 
 
79
        }
 
 
80
    }
 
 
81
 
 
 
82
    SHAPEFRAGMENT * frags = fragdesc->sh_frags;
 
 
83
 
 
 
84
    while (frags->ShapeIndex > 0)
 
 
85
    {
 
 
86
        int i = 0;
 
 
87
 
 
 
88
        for (; i < frags->NumFrags; i++)
 
 
89
        {
 
 
90
            STRATEGYBLOCK* sbPtr = CreateActiveStrategyBlock(I_BehaviourFragment);
 
 
91
 
 
 
92
            if (NULL == sbPtr)
 
 
93
                return;
 
 
94
 
 
 
95
            VECTORCH offset = { frags->x_offset, frags->y_offset, frags->z_offset };
 
 
96
 
 
 
97
            DISPLAYBLOCK *dispPtr = sbPtr->DisplayBlock = AllocateNewObject(frags->ShapeIndex); 
 
 
98
            DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_STATIC);
 
 
99
            sbPtr->dataptr = malloc(sizeof(ONE_SHOT_BEHAV_BLOCK));
 
 
100
 
 
 
101
            if ((NULL == dispPtr) || (NULL == sbPtr->dataptr) || (NULL == dynPtr))
 
 
102
            {    
 
 
103
                RemoveBehaviourStrategy(sbPtr);
 
 
104
                return;
 
 
105
            }
 
 
106
 
 
 
107
            dynPtr->Mass = 10;
 
 
108
            dynPtr->IsStatic = 0;
 
 
109
            dynPtr->IgnoreSameObjectsAsYou = 1;
 
 
110
 
 
 
111
            if (!offset.vx && !offset.vy && !offset.vz)
 
 
112
            {
 
 
113
                // place the fragment randomly within the bounding box of the parent
 
 
114
                offset.vx = generate_random_between(mainshapelist[sbptr->shapeIndex]->shapemaxx, mainshapelist[sbptr->shapeIndex]->shapeminx);
 
 
115
                offset.vy = generate_random_between(mainshapelist[sbptr->shapeIndex]->shapemaxy, mainshapelist[sbptr->shapeIndex]->shapeminy);
 
 
116
                offset.vz = generate_random_between(mainshapelist[sbptr->shapeIndex]->shapemaxz, mainshapelist[sbptr->shapeIndex]->shapeminz);
 
 
117
            }
 
 
118
 
 
 
119
            dispPtr->ObStrategyBlock = sbPtr;
 
 
120
 
 
 
121
            ((ONE_SHOT_BEHAV_BLOCK * ) sbPtr->dataptr)->counter = ((FastRandom() & 32768) << 2) + 65535 * 4;
 
 
122
 
 
 
123
            RotateVector(&offset, &sbptr->DynPtr->OrientMat);
 
 
124
 
 
 
125
            if (sbptr->containingModule)
 
 
126
            {
 
 
127
                if (frags->x_offset || frags->y_offset || frags->z_offset)
 
 
128
                {
 
 
129
                    diff.vx = offset.vx;
 
 
130
                    diff.vy = offset.vy;
 
 
131
                    diff.vz = offset.vz;
 
 
132
                }
 
 
133
                else
 
 
134
                {
 
 
135
                    diff.vx = sbptr->containingModule->m_mapptr->MapWorld.vx - posPtr->vx;
 
 
136
                    diff.vy = sbptr->containingModule->m_mapptr->MapWorld.vy - posPtr->vy;
 
 
137
                    diff.vz = sbptr->containingModule->m_mapptr->MapWorld.vz - posPtr->vz;
 
 
138
                }
 
 
139
 
 
 
140
                Normalise(&diff);
 
 
141
            }
 
 
142
            else
 
 
143
            {
 
 
144
                diff.vx = diff.vz = 0;
 
 
145
                diff.vy = ONE_FIXED;
 
 
146
            }
 
 
147
 
 
 
148
            {
 
 
149
                /*give fragment an impulse roughly in the direction of its offset*/
 
 
150
                VECTORCH impulse = offset;
 
 
151
 
 
 
152
                if(impulse.vx || impulse.vy || impulse.vz)
 
 
153
                {
 
 
154
                    Normalise(&impulse);
 
 
155
 
 
 
156
                     impulse.vx /= generate_random_between(5,10);
 
 
157
                  //    impulse.vy /= generate_random_between(5,10);
 
 
158
                     impulse.vz /= generate_random_between(5,10);
 
 
159
                }
 
 
160
 
 
 
161
                   dynPtr->LinImpulse = impulse;
 
 
162
            }
 
 
163
 
 
 
164
            diff.vx = (diff.vx >> 4);
 
 
165
            diff.vy = (diff.vy >> 4);
 
 
166
            diff.vz = (diff.vz >> 4);
 
 
167
 
 
 
168
            offset.vx += posPtr->vx;
 
 
169
            offset.vy += posPtr->vy;
 
 
170
            offset.vz += posPtr->vz;
 
 
171
 
 
 
172
            dispPtr->ObWorld = offset;
 
 
173
            dispPtr->ObMat = sbptr->DynPtr->OrientMat;
 
 
174
            dispPtr->ObEuler = sbptr->DynPtr->OrientEuler;
 
 
175
 
 
 
176
            dynPtr->Position = offset;
 
 
177
            dynPtr->OrientMat = sbptr->DynPtr->OrientMat;
 
 
178
            dynPtr->OrientEuler = sbptr->DynPtr->OrientEuler;
 
 
179
            dynPtr->PrevOrientMat = sbptr->DynPtr->PrevOrientMat;
 
 
180
            dynPtr->PrevOrientEuler = sbptr->DynPtr->PrevOrientEuler;
 
 
181
 
 
 
182
            dynPtr->AngVelocity.EulerX = (((FastRandom()&2047)-1023))<<2;
 
 
183
            dynPtr->AngVelocity.EulerY = (((FastRandom()&2047)-1023))<<2;
 
 
184
            dynPtr->AngVelocity.EulerZ = (((FastRandom()&2047)-1023))<<2;
 
 
185
 
 
 
186
            dynPtr->LinImpulse.vy = - (FastRandom() & 1023) << 2;
 
 
187
 
 
 
188
            /* Look to see if object has only one polygon in it;
 
 
189
               if so it's probably a glass fragment, so don't bother
 
 
190
               giving it collisions */
 
 
191
 
 
 
192
            if (1 == dispPtr->ShapeData->numitems)
 
 
193
                dynPtr->DynamicsType = DYN_TYPE_NO_COLLISIONS;
 
 
194
        }
 
 
195
 
 
 
196
        frags++;
 
 
197
    }
 
 
198
}
 
 
199
 
 
 
200
static void DoAlienLimbLossSound(VECTORCH *position)
 
 
201
{
 
 
202
    SpeciesSound(0, ASC_LimbLoss, 0, NULL, position, ALIEN_SOUND);
 
 
203
}
 
 
204
 
 
 
205
static void MakeFleshRippingNoises(VECTORCH *positionPtr)
 
 
206
{
 
 
207
    Sound_Play(SID_BODY_BEING_HACKED_UP_0 + (FastRandom() % 5) , "d", positionPtr);
 
 
208
}
 
 
209
 
 
 
210
DISPLAYBLOCK *MakeHierarchicalDebris(STRATEGYBLOCK *parent_sbPtr, SECTION_DATA *root, VECTORCH *positionPtr, MATRIXCH *orientation, int *wounds, int speed,
VECTORCH *incoming)
 
 
211
{
 
 
212
    /* KJL 16:53:22 28/02/98 - this seems to happen a lot in multiplayer */
 
 
213
    if(
 
 
214
    (positionPtr->vx > 1000000 || positionPtr->vx < -1000000)
 
 
215
    || 
 
 
216
    (positionPtr->vy > 1000000 || positionPtr->vy < -1000000)
 
 
217
    ||    
 
 
218
    (positionPtr->vz > 1000000 || positionPtr->vz < -1000000)
 
 
219
    )
 
 
220
        return NULL;
 
 
221
 
 
 
222
    if( (NumActiveBlocks > maxobjects-5) || (NumActiveStBlocks > maxstblocks-5))
 
 
223
        return NULL;
 
 
224
 
 
 
225
    assert(root);
 
 
226
 
 
 
227
    /* Right away, try to intercept all molotov cocktails! */
 
 
228
    if (!(root->flags & section_data_notreal) && !strcmp(root->sempai->Section_Name, "bottle"))
 
 
229
    {
 
 
230
        return SpawnMolotovCocktail(root, orientation);
 
 
231
    }
 
 
232
 
 
 
233
    STRATEGYBLOCK* sbPtr = CreateActiveStrategyBlock(I_BehaviourHierarchicalFragment);
 
 
234
 
 
 
235
    if(NULL == sbPtr)
 
 
236
        return NULL;
 
 
237
 
 
 
238
    DISPLAYBLOCK *dispPtr = sbPtr->DisplayBlock = AllocateNewObject(GetLoadedShapeMSL("Shell"));    
 
 
239
    DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_STATIC);
 
 
240
    sbPtr->dataptr = malloc(sizeof(HDEBRIS_BEHAV_BLOCK));
 
 
241
 
 
 
242
    if ((NULL == dispPtr) || (NULL == dynPtr) || (NULL == sbPtr->dataptr))
 
 
243
    {
 
 
244
        RemoveBehaviourStrategy(sbPtr);
 
 
245
        return NULL;
 
 
246
    }
 
 
247
 
 
 
248
    dynPtr->Mass = 10;
 
 
249
    dynPtr->IsStatic = 0;
 
 
250
    dynPtr->IgnoreSameObjectsAsYou = 1;
 
 
251
    dynPtr->Position = *positionPtr;
 
 
252
    dynPtr->OrientMat = *orientation;
 
 
253
 
 
 
254
    dispPtr->ObWorld = *positionPtr;
 
 
255
    dispPtr->ObStrategyBlock = sbPtr;
 
 
256
    dispPtr->ObMat = *orientation;
 
 
257
    //dispPtr->ObMat = IdentityMatrix;
 
 
258
 
 
 
259
 
 
 
260
    // 2. NOW set up the strategyblock-specific fields for
 
 
261
    // the new displayblock. We won't go through the "AttachNew
 
 
262
    // StrategyBlock" and "AssignRunTimeBehaviours" pair, since
 
 
263
    // the first switches on ObShape and the second on bhvr;
 
 
264
    // but, in this case, there isn't a particular connection
 
 
265
    // between them.
 
 
266
 
 
 
267
    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->counter = HDEBRIS_LIFETIME;
 
 
268
    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Bounce_Sound = SID_NOSOUND;
 
 
269
 
 
 
270
    int wounds_temp = Splice_HModels(&(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), root);
 
 
271
 
 
 
272
    if (wounds)
 
 
273
         *wounds = wounds_temp;
 
 
274
 
 
 
275
    if (parent_sbPtr)
 
 
276
    {
 
 
277
        /* Inherit fire! */
 
 
278
 
 
 
279
        sbPtr->DamageBlock.IsOnFire = parent_sbPtr->DamageBlock.IsOnFire;
 
 
280
 
 
 
281
        /* KJL 11:28:27 14/10/98 - this is set so we can later know what the debris was part of */
 
 
282
        /* CDF 3/3/99 put it in the switch statement, to deal with complex cases */
 
 
283
        /* Creature specific code! */
 
 
284
 
 
 
285
        switch (parent_sbPtr->type)
 
 
286
        {
 
 
287
            case I_BehaviourAlien:
 
 
288
            {
 
 
289
                ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(parent_sbPtr->dataptr);    
 
 
290
 
 
 
291
                /* Just go to spasm. */
 
 
292
                InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_AlienStand,
ASSS_Spasm, -1, 1);
 
 
293
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
294
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
295
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = I_BehaviourAlien;
 
 
296
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = alienStatusPointer->Type;
 
 
297
                root->SecMat = *orientation;
 
 
298
 
 
 
299
                DoAlienLimbLossSound(positionPtr);
 
 
300
 
 
 
301
                /* Last as long as a dead alien. */
 
 
302
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->counter = ALIEN_DYINGTIME;
 
 
303
            }
 
 
304
            break;
 
 
305
            case I_BehaviourMarine:
 
 
306
            {
 
 
307
                /* See if we can strip to template. */
 
 
308
                MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(parent_sbPtr->dataptr);    
 
 
309
 
 
 
310
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = I_BehaviourMarine;
 
 
311
 
 
 
312
                if(marineStatusPointer->My_Weapon->ARealMarine)
 
 
313
                {
 
 
314
                    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = 1;
 
 
315
                }
 
 
316
                else if(marineStatusPointer->Android)
 
 
317
                {
 
 
318
                    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = -1;
 
 
319
                }
 
 
320
                else
 
 
321
                {
 
 
322
                    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = 0;
 
 
323
                }
 
 
324
 
 
 
325
                SECTION *template_root = GetNamedHierarchyFromLibrary(marineStatusPointer->My_Weapon->Riffname,
marineStatusPointer->My_Weapon->TemplateName);
 
 
326
                /* Now, find the section that matches. */
 
 
327
                SECTION *template_sempai = Get_Corresponding_Section_Recursive(template_root, (((HDEBRIS_BEHAV_BLOCK * )
sbPtr->dataptr)->HModelController).Root_Section->Section_Name);
 
 
328
 
 
 
329
                if (template_sempai)
 
 
330
                {
 
 
331
                    /* We have a match! */
 
 
332
                    Transmogrify_HModels(sbPtr, &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), template_sempai, 1, 0, 0);
 
 
333
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_MarineStand, MSSS_Spasm, -1, 1);
 
 
334
                    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
335
                    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
336
                    //((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootRotation = 1;
 
 
337
                    //MakeFleshRippingNoises(positionPtr);
 
 
338
                }
 
 
339
                else
 
 
340
                {
 
 
341
                    /* Forget it.  Must be a disembodied weapon, or something. */
 
 
342
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED<<1), 0, 1, ONE_FIXED, 0);
 
 
343
                    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
344
                    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
345
                    //((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootRotation = 1;
 
 
346
                    dynPtr->OnlyCollideWithEnvironment = 1;
 
 
347
                    //dispPtr->ObMat = *orientation;
 
 
348
                    /* Below is an alternative... */
 
 
349
                }
 
 
350
 
 
 
351
                root->SecMat = *orientation;
 
 
352
 
 
 
353
                /* Since we're dealing with a marine, consider expressions. */
 
 
354
                {
 
 
355
                    SECTION_DATA *head = GetThisSectionData(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.section_data, "head");
 
 
356
 
 
 
357
                    if (head && !(head->flags & section_data_notreal))
 
 
358
                    {
 
 
359
                        TXACTRLBLK *tacb = head->tac_ptr;
 
 
360
 
 
 
361
                        while (tacb)
 
 
362
                        {
 
 
363
                            tacb->tac_sequence = 4;
 
 
364
                            tacb->tac_txah_s = GetTxAnimHeaderFromShape(tacb, head->ShapeNum);
 
 
365
                            tacb = tacb->tac_next;
 
 
366
                        }
 
 
367
                    }
 
 
368
                }
 
 
369
 
 
 
370
                /* Last as long as a dead marine. */
 
 
371
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->counter = MARINE_DYINGTIME;
 
 
372
            }
 
 
373
            break;
 
 
374
            case I_BehaviourPredator:
 
 
375
            {
 
 
376
                /* See if we can strip to template. */
 
 
377
 
 
 
378
                SECTION *template_root = GetNamedHierarchyFromLibrary("hnpcpredator", "Template");
 
 
379
                /* Now, find the section that matches. */
 
 
380
                SECTION *template_sempai = Get_Corresponding_Section_Recursive(template_root, (((HDEBRIS_BEHAV_BLOCK * )
sbPtr->dataptr)->HModelController).Root_Section->Section_Name);
 
 
381
 
 
 
382
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = I_BehaviourPredator;
 
 
383
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = 0;
 
 
384
 
 
 
385
                if (template_sempai)
 
 
386
                {
 
 
387
                    /* We have a match! */
 
 
388
                    Transmogrify_HModels(sbPtr, &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), template_sempai, 1, 0, 0);
 
 
389
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_PredatorStand, PSSS_Spasm, -1, 1);
 
 
390
                    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
391
                    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
392
                    root->SecMat = *orientation;
 
 
393
                }
 
 
394
                else
 
 
395
                {
 
 
396
                    /* Forget it.  Must be a disembodied weapon, or something. */
 
 
397
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED<<1), 0, 1, ONE_FIXED, 0);
 
 
398
                    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
399
                    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
400
                    root->SecMat = *orientation;
 
 
401
                }
 
 
402
                /* Just freeze for now! */
 
 
403
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.Playing = 0;
 
 
404
                /* Last as long as a dead predator. */
 
 
405
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->counter = PRED_DIETIME;
 
 
406
            }
 
 
407
            break;
 
 
408
            case I_BehaviourCorpse:
 
 
409
            {
 
 
410
                CORPSEDATABLOCK *corpseDataPtr = (CORPSEDATABLOCK *)parent_sbPtr->dataptr;
 
 
411
 
 
 
412
                switch (corpseDataPtr->Type)
 
 
413
                {
 
 
414
                    case I_BehaviourAlien:
 
 
415
                    {
 
 
416
                        DoAlienLimbLossSound(positionPtr);
 
 
417
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_AlienStand, ASSS_Spasm, -1, 1);
 
 
418
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = corpseDataPtr->subtype;
 
 
419
                    }
 
 
420
                    break;
 
 
421
                    case I_BehaviourMarine:
 
 
422
                    {
 
 
423
                        /* Now, find the section that matches. */
 
 
424
                    /*
 
 
425
                        SECTION *template_root = corpseDataPtr->TemplateRoot;
 
 
426
                        SECTION *template_sempai =
 
 
427
                        Get_Corresponding_Section_Recursive(template_root, (((HDEBRIS_BEHAV_BLOCK * )
sbPtr->dataptr)->HModelController).Root_Section->Section_Name);
 
 
428
                        //if (template_sempai) MakeFleshRippingNoises(positionPtr);
 
 
429
                    */
 
 
430
 
 
 
431
                        if (!strcmp(root->sempai->Section_Name, "spring one"))
 
 
432
                        {
 
 
433
                            // stops smart gun going crazy
 
 
434
                        }
 
 
435
                        else
 
 
436
                        {
 
 
437
                            InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController),(ONE_FIXED>>2),
HMSQT_MarineStand, MSSS_Spasm, -1, 1);
 
 
438
                        }
 
 
439
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = corpseDataPtr->subtype;
 
 
440
                    }
 
 
441
                    break;
 
 
442
                    case I_BehaviourPredator:
 
 
443
                    {
 
 
444
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_PredatorStand, PSSS_Spasm, -1, 1);
 
 
445
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = corpseDataPtr->subtype;
 
 
446
                    }
 
 
447
                    break;
 
 
448
                    default:
 
 
449
                    {
 
 
450
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED<<1), 0, 1, ONE_FIXED, 0);
 
 
451
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = corpseDataPtr->subtype;
 
 
452
                    }
 
 
453
                }
 
 
454
 
 
 
455
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
456
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
457
                root->SecMat = *orientation;
 
 
458
 
 
 
459
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = corpseDataPtr->Type;
 
 
460
                /* Inherit counter from parent corpse. */
 
 
461
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->counter = corpseDataPtr->timer;
 
 
462
            }
 
 
463
            break;
 
 
464
            case I_BehaviourHierarchicalFragment:
 
 
465
            {
 
 
466
                HDEBRIS_BEHAV_BLOCK *debrisDataPtr  = (HDEBRIS_BEHAV_BLOCK *)parent_sbPtr->dataptr;
 
 
467
 
 
 
468
                switch (debrisDataPtr->Type)
 
 
469
                {
 
 
470
                    case I_BehaviourAlien:
 
 
471
                    {
 
 
472
                        //DoAlienLimbLossSound(positionPtr);
 
 
473
                        /* Sound should be the same for all types of alien! */
 
 
474
                        InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_AlienStand,
ASSS_Spasm, -1, 1);
 
 
475
                    }
 
 
476
                    break;
 
 
477
                    case I_BehaviourMarine:
 
 
478
                    {
 
 
479
                        if (!strcmp(root->sempai->Section_Name, "SADAR"))
 
 
480
                        {
 
 
481
                            ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Bounce_Sound = SID_LARGEWEAPONDROP;
 
 
482
                            dynPtr->Elasticity = (ONE_FIXED >> 3);
 
 
483
                        }
 
 
484
                        else if (!strcmp(root->sempai->Section_Name, "gren stock")
 
 
485
                        || !strcmp(root->sempai->Section_Name, "flamer")
 
 
486
                        || !strcmp(root->sempai->Section_Name, "flame thrower")
 
 
487
                        || !strcmp(root->sempai->Section_Name, "mini gun"))
 
 
488
                        {
 
 
489
                            ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Bounce_Sound = SID_LARGEWEAPONDROP;
 
 
490
                        }
 
 
491
                        else if (!strcmp(root->sempai->Section_Name, "spring one"))
 
 
492
                        {
 
 
493
                            /* This is a smartgun! */
 
 
494
                            ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Bounce_Sound = SID_LARGEWEAPONDROP;
 
 
495
                            /* Whilst we're here... */
 
 
496
                            dispPtr->ObMat = *orientation;
 
 
497
                            root->SecMat = IdentityMatrix;
 
 
498
                            ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootRotation = 1;
 
 
499
                            ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.Playing = 0;
 
 
500
                        }
 
 
501
                        else if (!strcmp(root->sempai->Section_Name, "pulse mag"))
 
 
502
                        {
 
 
503
                            /* Don't have a 'tink' yet... */
 
 
504
                            dynPtr->Elasticity = (ONE_FIXED >> 1);
 
 
505
                        }
 
 
506
                        else
 
 
507
                        {
 
 
508
                            //MakeFleshRippingNoises(positionPtr);
 
 
509
                            InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2),
HMSQT_MarineStand, MSSS_Spasm, -1, 1);
 
 
510
                        }
 
 
511
                    }
 
 
512
                    break;
 
 
513
                    case I_BehaviourPredator:
 
 
514
                        InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_PredatorStand,
PSSS_Spasm, -1, 1);
 
 
515
                    break;
 
 
516
                    default:
 
 
517
                        InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED<<1), 0, 1, ONE_FIXED, 0);
 
 
518
                }
 
 
519
 
 
 
520
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
521
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
522
                root->SecMat = *orientation;
 
 
523
 
 
 
524
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = debrisDataPtr->Type;
 
 
525
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = debrisDataPtr->SubType;
 
 
526
                /* Inherit counter from parent debris. */
 
 
527
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->counter = debrisDataPtr->counter;
 
 
528
            }
 
 
529
            break;
 
 
530
            case I_BehaviourNetGhost:
 
 
531
            {
 
 
532
                NETGHOSTDATABLOCK *dataptr = parent_sbPtr->dataptr;
 
 
533
 
 
 
534
                switch (dataptr->type)
 
 
535
                {
 
 
536
                    case I_BehaviourAlien:
 
 
537
                    {
 
 
538
                        //DoAlienLimbLossSound(positionPtr);
 
 
539
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_AlienStand, ASSS_Spasm, -1, 1);
 
 
540
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
541
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
542
                        root->SecMat = *orientation;
 
 
543
 
 
 
544
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = I_BehaviourAlien;
 
 
545
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = dataptr->subtype;
 
 
546
                    }
 
 
547
                    break;
 
 
548
                    case I_BehaviourCorpse:
 
 
549
                    {
 
 
550
                        switch (dataptr->subtype)
 
 
551
                        {
 
 
552
                            case I_BehaviourAlien:
 
 
553
                            {
 
 
554
                                DoAlienLimbLossSound(positionPtr);
 
 
555
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_AlienStand, ASSS_Spasm, -1, 1);
 
 
556
                                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
557
                                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
558
                                root->SecMat = *orientation;
 
 
559
 
 
 
560
                                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = I_BehaviourAlien;
 
 
561
                                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = dataptr->IOType;
 
 
562
                            }
 
 
563
                            break;
 
 
564
                            default:
 
 
565
                            {
 
 
566
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED<<1), 0, 1, ONE_FIXED, 0);
 
 
567
                                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
568
                                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
569
                                root->SecMat = *orientation;
 
 
570
 
 
 
571
                                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = parent_sbPtr->type;
 
 
572
                                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = 0;
 
 
573
                            }
 
 
574
                        }
 
 
575
                    }
 
 
576
                    break;
 
 
577
                    default:
 
 
578
                        InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED<<1), 0, 1, ONE_FIXED, 0);
 
 
579
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
580
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
581
                        root->SecMat = *orientation;
 
 
582
 
 
 
583
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = parent_sbPtr->type;
 
 
584
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = 0;
 
 
585
                }
 
 
586
            }
 
 
587
            break;
 
 
588
            case I_BehaviourAutoGun:
 
 
589
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Bounce_Sound = SID_LARGEWEAPONDROP;
 
 
590
                // no break for you
 
 
591
            default:
 
 
592
                InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED<<1), 0, 1, ONE_FIXED, 0);
 
 
593
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
594
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
595
                root->SecMat = *orientation;
 
 
596
 
 
 
597
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = parent_sbPtr->type;
 
 
598
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = 0;
 
 
599
        }
 
 
600
    }
 
 
601
    else
 
 
602
    {
 
 
603
        /* KJL 11:27:54 14/10/98 - set behaviour type to null to avoid confusion */
 
 
604
        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = I_BehaviourNull;
 
 
605
        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = 0;
 
 
606
        InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED<<1), 0, 1, ONE_FIXED, 0);
 
 
607
        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
608
        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
609
        //((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootRotation = 1;
 
 
610
        root->SecMat = *orientation;
 
 
611
    }
 
 
612
 
 
 
613
    dispPtr->HModelControlBlock = &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController);
 
 
614
 
 
 
615
    if(incoming)
 
 
616
    {
 
 
617
        dynPtr->LinImpulse = *incoming;
 
 
618
    }
 
 
619
    else
 
 
620
    {
 
 
621
        // Give explosion fragments an angular velocity
 
 
622
        dynPtr->AngVelocity.EulerX = (FastRandom() & 2047) - 1024;
 
 
623
        dynPtr->AngVelocity.EulerY = (FastRandom() & 2047) - 1024;
 
 
624
        dynPtr->AngVelocity.EulerZ = (FastRandom() & 2047) - 1024;
 
 
625
 
 
 
626
        {
 
 
627
            int random = (FastRandom() & 1023) - 512;
 
 
628
 
 
 
629
            if (random > 0)
 
 
630
                dynPtr->LinImpulse.vx = (random + 100) << speed;
 
 
631
            else
 
 
632
                dynPtr->LinImpulse.vx = (random - 100) << speed;
 
 
633
        }
 
 
634
 
 
 
635
        {
 
 
636
            int random = (FastRandom() & 1023) - 768;
 
 
637
 
 
 
638
            if (random > 0)
 
 
639
                dynPtr->LinImpulse.vy = (random + 100) << speed;
 
 
640
            else
 
 
641
                dynPtr->LinImpulse.vy = (random - 100) << speed;
 
 
642
        }
 
 
643
 
 
 
644
        {
 
 
645
            int random = (FastRandom() & 1023) - 512;
 
 
646
 
 
 
647
            if (random > 0)
 
 
648
                dynPtr->LinImpulse.vz = (random + 100) << speed;
 
 
649
            else
 
 
650
                dynPtr->LinImpulse.vz = (random - 100) << speed;
 
 
651
        }
 
 
652
    }
 
 
653
 
 
 
654
    ProveHModel(dispPtr->HModelControlBlock, dispPtr);
 
 
655
 
 
 
656
return dispPtr;
 
 
657
}
 
 
658
 
 
 
659
void make_clip(SECTION_DATA *root, VECTORCH *positionPtr, MATRIXCH *orientation)
 
 
660
{
 
 
661
    assert(root);
 
 
662
 
 
 
663
    if( (NumActiveBlocks > maxobjects-5) || (NumActiveStBlocks > maxstblocks-5))
 
 
664
        return;
 
 
665
 
 
 
666
    STRATEGYBLOCK* sbPtr = CreateActiveStrategyBlock(I_BehaviourHierarchicalFragment);
 
 
667
 
 
 
668
    if(NULL != sbPtr)
 
 
669
    {
 
 
670
        DISPLAYBLOCK *dispPtr = sbPtr->DisplayBlock = CreateActiveObject();
 
 
671
        DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_STATIC);
 
 
672
        sbPtr->dataptr = malloc(sizeof(HDEBRIS_BEHAV_BLOCK));
 
 
673
 
 
 
674
        if(!dispPtr || !sbPtr->dataptr || !dynPtr)
 
 
675
        {
 
 
676
            RemoveBehaviourStrategy(sbPtr);
 
 
677
            return;
 
 
678
        }
 
 
679
 
 
 
680
        dynPtr->Mass = 1;
 
 
681
        dynPtr->IsStatic = 0;
 
 
682
        dynPtr->IgnoreSameObjectsAsYou = 1;
 
 
683
        dynPtr->OnlyCollideWithEnvironment = 1;
 
 
684
 
 
 
685
        dispPtr->extent.min_x = -10;
 
 
686
        dispPtr->extent.min_y = -10;
 
 
687
        dispPtr->extent.min_z = -10;
 
 
688
        dispPtr->extent.max_x = 10;
 
 
689
        dispPtr->extent.max_y = 10;
 
 
690
        dispPtr->extent.max_z = 10;
 
 
691
        dispPtr->ObMat = IdentityMatrix;
 
 
692
        dispPtr->ObWorld = *positionPtr;
 
 
693
 
 
 
694
        // 2. NOW set up the strategyblock-specific fields for
 
 
695
        // the new displayblock. We won't go through the "AttachNew
 
 
696
        // StrategyBlock" and "AssignRunTimeBehaviours" pair, since
 
 
697
        // the first switches on ObShape and the second on bhvr;
 
 
698
        // but, in this case, there isn't a particular connection
 
 
699
        // between them.
 
 
700
 
 
 
701
        dispPtr->ObStrategyBlock = sbPtr;
 
 
702
 
 
 
703
        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->counter = HDEBRIS_LIFETIME;
 
 
704
        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Bounce_Sound = SID_NOSOUND;
 
 
705
 
 
 
706
        Splice_HModels(&(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), root);
 
 
707
 
 
 
708
        /* KJL 11:27:54 14/10/98 - set behaviour type to null to avoid confusion */
 
 
709
        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = I_BehaviourNull;
 
 
710
        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = 0;
 
 
711
        InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED<<1), 0, 1, ONE_FIXED, 0);
 
 
712
        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
713
        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
714
        //((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootRotation = 1;
 
 
715
        root->SecMat = *orientation;
 
 
716
 
 
 
717
        dispPtr->HModelControlBlock = &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController);
 
 
718
 
 
 
719
        dynPtr->Position = *positionPtr;
 
 
720
        dynPtr->OrientMat = *orientation;
 
 
721
 
 
 
722
        ProveHModel(dispPtr->HModelControlBlock, dispPtr);
 
 
723
 
 
 
724
        assert(dispPtr->ObWorld.vx < 1000000 && dispPtr->ObWorld.vx > -1000000);
 
 
725
        assert(dispPtr->ObWorld.vy < 1000000 && dispPtr->ObWorld.vy > -1000000);
 
 
726
        assert(dispPtr->ObWorld.vz < 1000000 && dispPtr->ObWorld.vz > -1000000);
 
 
727
    }
 
 
728
}
 
 
729
 
 
 
730
void HierarchicalFragmentBehaviour(STRATEGYBLOCK *sptr)
 
 
731
{
 
 
732
    int bounce = 0;
 
 
733
    HDEBRIS_BEHAV_BLOCK *hdbhv = (HDEBRIS_BEHAV_BLOCK * )sptr->dataptr;
 
 
734
     DYNAMICSBLOCK *dynPtr = sptr->DynPtr;
 
 
735
    COLLISIONREPORT *reportptr = dynPtr->CollisionReportPtr;
 
 
736
 
 
 
737
    if (hdbhv->counter < 0)
 
 
738
    {            
 
 
739
        sptr->please_destroy_me = 1;
 
 
740
        return;            
 
 
741
    }
 
 
742
 
 
 
743
    if (sptr->DisplayBlock)
 
 
744
    {
 
 
745
        sptr->DisplayBlock->SpecialFXFlags |= SFXFLAG_MELTINGINTOGROUND;
 
 
746
        sptr->DisplayBlock->ObFlags2 = hdbhv->counter / 2;
 
 
747
    }
 
 
748
 
 
 
749
    if (sptr->DamageBlock.IsOnFire)
 
 
750
    {
 
 
751
        hdbhv->HModelController.DisableBleeding = 1;
 
 
752
        sptr->DamageBlock.IsOnFire -= NormalFrameTime;
 
 
753
 
 
 
754
        if (sptr->DamageBlock.IsOnFire < 0)
 
 
755
            sptr->DamageBlock.IsOnFire = 0;
 
 
756
    }
 
 
757
 
 
 
758
    /* CDF 8/3/99 Added this on request... */
 
 
759
    if (hdbhv->counter < (HDEBRIS_LIFETIME - HDEBRIS_BLEEDING_TIME))
 
 
760
        hdbhv->HModelController.DisableBleeding = 1;
 
 
761
 
 
 
762
    hdbhv->counter -= NormalFrameTime;
 
 
763
 
 
 
764
    if (reportptr == NULL)
 
 
765
    {
 
 
766
        hdbhv->bouncelastframe = 0;
 
 
767
    }
 
 
768
    else if(DynamicObjectIsMoving(dynPtr))
 
 
769
    {
 
 
770
        do
 
 
771
        {
 
 
772
            if (NULL == reportptr->ObstacleSBPtr)
 
 
773
            {
 
 
774
                bounce = 1;
 
 
775
 
 
 
776
                if(-1 != reportptr->ModuleIndex)
 
 
777
                {
 
 
778
                    if (hdbhv->HModelController.Root_Section->flags & section_sprays_acid)
 
 
779
                    {
 
 
780
                        MakeDecal(DECAL_SCORCHED, &reportptr->ObstacleNormal, &reportptr->ObstaclePoint, reportptr->ModuleIndex);
 
 
781
                    }
 
 
782
                    else if (hdbhv->HModelController.Root_Section->flags & section_sprays_blood)
 
 
783
                    {
 
 
784
                    MakeDecal(((-1 == hdbhv->SubType) ? DECAL_ANDROID_BLOOD_SPLASH : DECAL_HUMAN_BLOOD_SPLASH), &reportptr->ObstacleNormal,
&reportptr->ObstaclePoint, reportptr->ModuleIndex);
 
 
785
                    }
 
 
786
                    else if (hdbhv->HModelController.Root_Section->flags & section_sprays_predoblood)
 
 
787
                    {
 
 
788
                        MakeDecal(DECAL_PREDATOR_BLOOD_SPLASH, &reportptr->ObstacleNormal, &reportptr->ObstaclePoint, reportptr->ModuleIndex);
 
 
789
                    }
 
 
790
                }
 
 
791
            }
 
 
792
            else
 
 
793
            {
 
 
794
                if (hdbhv->HModelController.Root_Section->flags & section_sprays_acid)
 
 
795
                {
 
 
796
                    switch(reportptr->ObstacleSBPtr->type)
 
 
797
                    {
 
 
798
                        case I_BehaviourMarine:
 
 
799
                        case I_BehaviourPredator:
 
 
800
                        case I_BehaviourMarinePlayer:
 
 
801
                        case I_BehaviourPredatorPlayer:
 
 
802
                        case I_BehaviourAutoGun:
 
 
803
                        case I_BehaviourInanimateObject:
 
 
804
                        case I_BehaviourPlacedLight:
 
 
805
                        case I_BehaviourVideoScreen:
 
 
806
                        case I_BehaviourSpeargunBolt:
 
 
807
                            CauseDamageToObject(reportptr->ObstacleSBPtr, &TemplateAmmo[AMMO_ALIEN_FRAG].MaxDamage, ONE_FIXED, NULL);
 
 
808
                        break;
 
 
809
                        /*
 
 
810
                        case I_BehaviourRocket:
 
 
811
                        case I_BehaviourFlare:
 
 
812
                        case I_BehaviourPulseGrenade:
 
 
813
                        case I_BehaviourGrenade:
 
 
814
                        case I_BehaviourFragmentationGrenade:
 
 
815
                        case I_BehaviourProximityGrenade:
 
 
816
                            reportptr->ObstacleSBPtr->please_destroy_me = 1;
 
 
817
                        */
 
 
818
                        default:
 
 
819
                        break;
 
 
820
                    }
 
 
821
                }
 
 
822
            }
 
 
823
 
 
 
824
            reportptr = reportptr->NextCollisionReportPtr;
 
 
825
 
 
 
826
        } while (reportptr);
 
 
827
    }
 
 
828
 
 
 
829
    if (bounce && !hdbhv->bouncelastframe)
 
 
830
    {
 
 
831
        if (hdbhv->Bounce_Sound != SID_NOSOUND)
 
 
832
            Sound_Play(hdbhv->Bounce_Sound, "dp", &dynPtr->Position, ((FastRandom()&511)-255));
 
 
833
 
 
 
834
        hdbhv->bouncelastframe = 1;
 
 
835
    }
 
 
836
 
 
 
837
    if (dynPtr->IsInContactWithFloor)
 
 
838
        dynPtr->AngVelocity.EulerX = dynPtr->AngVelocity.EulerY = dynPtr->AngVelocity.EulerZ = 0;
 
 
839
    else
 
 
840
        DynamicallyRotateObject(dynPtr);
 
 
841
}