4b825dc642cb6eb9a060e54bf8d69288fbee490494a6641b73026d662261604d7d192beae70b11dc
 
 
1
#include "system.h"
 
 
2
#include "prototyp.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 "scream.h"
 
 
9
#include "corpse.h"
 
 
10
#include <assert.h>
 
 
11
#include "weaponbehaviour.h"
 
 
12
#include "pldghost.h"
 
 
13
#include "savegame.h"
 
 
14
#include "weapons.h"
 
 
15
#include "dynamics.h"
 
 
16
#include <stdio.h>
 
 
17
#include <string.h>
 
 
18
#include <stdlib.h>
 
 
19
 
 
 
20
#include "projload.hpp"
 
 
21
 
 
 
22
#define HDEBRIS_BLEEDING_TIME    (ONE_FIXED*2)
 
 
23
 
 
 
24
extern int NumActiveBlocks;
 
 
25
extern SECTION * GetNamedHierarchyFromLibrary(const char * rif_name, const char * hier_name);
 
 
26
extern int GetLoadedShapeMSL(char const * shapename);
 
 
27
extern MATRIXCH IdentityMatrix;
 
 
28
 
 
 
29
extern void SetSeededFastRandom(int seed);
 
 
30
 
 
 
31
static int generate_random_between (int first, int second)
 
 
32
{
 
 
33
    int diff = second - first;
 
 
34
 
 
 
35
    if (!diff)
 
 
36
        return first;
 
 
37
 
 
 
38
    int absdiff = abs (diff);
 
 
39
    int rand_no = FastRandom () % absdiff;
 
 
40
 
 
 
41
return ( (diff < 0) ? (second + rand_no) : (first + rand_no));
 
 
42
}
 
 
43
 
 
 
44
void MakeFragments(STRATEGYBLOCK * sbptr)
 
 
45
{
 
 
46
    VECTORCH diff;
 
 
47
 
 
 
48
    if( (NumActiveBlocks > maxobjects-5) || (NumActiveStBlocks > maxstblocks-5))
 
 
49
        return;
 
 
50
 
 
 
51
    if (!sbptr->DynPtr || !sbptr->DisplayBlock)
 
 
52
        return;
 
 
53
 
 
 
54
    VECTORCH * posPtr = &sbptr->DynPtr->Position;
 
 
55
    struct shapefragmentdesc * fragdesc = GetFragDesc(sbptr->shapeIndex);
 
 
56
 
 
 
57
    if(!fragdesc)
 
 
58
    {
 
 
59
          Sound_Play(SID_EXPLOSION, "d", posPtr);  
 
 
60
        return;
 
 
61
    }
 
 
62
    else if(!fragdesc->sh_fragsound)
 
 
63
    {
 
 
64
          Sound_Play(SID_EXPLOSION, "d", posPtr);  
 
 
65
    }
 
 
66
    else
 
 
67
    {
 
 
68
        SHAPEFRAGMENTSOUND * fragsound = fragdesc->sh_fragsound;
 
 
69
 
 
 
70
        if(SID_NOSOUND != fragsound->sound_number)
 
 
71
        {
 
 
72
              Sound_Play((SOUNDINDEX)fragsound->sound_number, "d", posPtr);  
 
 
73
 
 
 
74
            /*
 
 
75
                SOUND3DDATA s3d;
 
 
76
                s3d.position = *posPtr;
 
 
77
                s3d.inner_range = fragsound->inner_range;
 
 
78
                s3d.outer_range = fragsound->outer_range;
 
 
79
                s3d.velocity.vx = s3d.velocity.vy = s3d.velocity.vz = 0;
 
 
80
                Sound_Play ((SOUNDINDEX)fragsound->sound_number, "nvp", &s3d, fragsound->max_volume, fragsound->pitch);
 
 
81
            */
 
 
82
        }
 
 
83
    }
 
 
84
 
 
 
85
    SHAPEFRAGMENT * frags = fragdesc->sh_frags;
 
 
86
 
 
 
87
    while (frags->ShapeIndex > 0)
 
 
88
    {
 
 
89
        int i = 0;
 
 
90
 
 
 
91
        for (; i < frags->NumFrags; i++)
 
 
92
        {
 
 
93
            STRATEGYBLOCK* sbPtr = CreateActiveStrategyBlock(I_BehaviourFragment);
 
 
94
 
 
 
95
            if (NULL == sbPtr)
 
 
96
                return;
 
 
97
 
 
 
98
            VECTORCH offset = { frags->x_offset, frags->y_offset, frags->z_offset };
 
 
99
 
 
 
100
            DISPLAYBLOCK *dispPtr = sbPtr->DisplayBlock = AllocateNewObject(frags->ShapeIndex); 
 
 
101
            DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_STATIC);
 
 
102
            sbPtr->dataptr = malloc(sizeof(ONE_SHOT_BEHAV_BLOCK));
 
 
103
 
 
 
104
            if ((NULL == dispPtr) || (NULL == sbPtr->dataptr) || (NULL == dynPtr))
 
 
105
            {    
 
 
106
                RemoveBehaviourStrategy(sbPtr);
 
 
107
                return;
 
 
108
            }
 
 
109
 
 
 
110
            dynPtr->Mass = 10;
 
 
111
            dynPtr->IsStatic = 0;
 
 
112
            dynPtr->IgnoreSameObjectsAsYou = 1;
 
 
113
 
 
 
114
            if (!offset.vx && !offset.vy && !offset.vz)
 
 
115
            {
 
 
116
                // place the fragment randomly within the bounding box of the parent
 
 
117
                offset.vx = generate_random_between(mainshapelist[sbptr->shapeIndex]->shapemaxx, mainshapelist[sbptr->shapeIndex]->shapeminx);
 
 
118
                offset.vy = generate_random_between(mainshapelist[sbptr->shapeIndex]->shapemaxy, mainshapelist[sbptr->shapeIndex]->shapeminy);
 
 
119
                offset.vz = generate_random_between(mainshapelist[sbptr->shapeIndex]->shapemaxz, mainshapelist[sbptr->shapeIndex]->shapeminz);
 
 
120
            }
 
 
121
 
 
 
122
            dispPtr->ObStrategyBlock = sbPtr;
 
 
123
 
 
 
124
            ((ONE_SHOT_BEHAV_BLOCK * ) sbPtr->dataptr)->counter = ((FastRandom() & 32768) << 2) + 65535 * 4;
 
 
125
 
 
 
126
            RotateVector(&offset, &sbptr->DynPtr->OrientMat);
 
 
127
 
 
 
128
            if (sbptr->containingModule)
 
 
129
            {
 
 
130
                if (frags->x_offset || frags->y_offset || frags->z_offset)
 
 
131
                {
 
 
132
                    diff.vx = offset.vx;
 
 
133
                    diff.vy = offset.vy;
 
 
134
                    diff.vz = offset.vz;
 
 
135
                }
 
 
136
                else
 
 
137
                {
 
 
138
                    diff.vx = sbptr->containingModule->m_mapptr->MapWorld.vx - posPtr->vx;
 
 
139
                    diff.vy = sbptr->containingModule->m_mapptr->MapWorld.vy - posPtr->vy;
 
 
140
                    diff.vz = sbptr->containingModule->m_mapptr->MapWorld.vz - posPtr->vz;
 
 
141
                }
 
 
142
 
 
 
143
                Normalise(&diff);
 
 
144
            }
 
 
145
            else
 
 
146
            {
 
 
147
                diff.vx = diff.vz = 0;
 
 
148
                diff.vy = ONE_FIXED;
 
 
149
            }
 
 
150
 
 
 
151
            {
 
 
152
                /*give fragment an impulse roughly in the direction of its offset*/
 
 
153
                VECTORCH impulse = offset;
 
 
154
 
 
 
155
                if(impulse.vx || impulse.vy || impulse.vz)
 
 
156
                {
 
 
157
                    Normalise(&impulse);
 
 
158
 
 
 
159
                     impulse.vx /= generate_random_between(5,10);
 
 
160
                  //    impulse.vy /= generate_random_between(5,10);
 
 
161
                     impulse.vz /= generate_random_between(5,10);
 
 
162
                }
 
 
163
 
 
 
164
                   dynPtr->LinImpulse = impulse;
 
 
165
            }
 
 
166
 
 
 
167
            diff.vx = (diff.vx >> 4);
 
 
168
            diff.vy = (diff.vy >> 4);
 
 
169
            diff.vz = (diff.vz >> 4);
 
 
170
 
 
 
171
            offset.vx += posPtr->vx;
 
 
172
            offset.vy += posPtr->vy;
 
 
173
            offset.vz += posPtr->vz;
 
 
174
 
 
 
175
            dispPtr->ObWorld = offset;
 
 
176
            dispPtr->ObMat = sbptr->DynPtr->OrientMat;
 
 
177
            dispPtr->ObEuler = sbptr->DynPtr->OrientEuler;
 
 
178
 
 
 
179
            dynPtr->Position = offset;
 
 
180
            dynPtr->OrientMat = sbptr->DynPtr->OrientMat;
 
 
181
            dynPtr->OrientEuler = sbptr->DynPtr->OrientEuler;
 
 
182
            dynPtr->PrevOrientMat = sbptr->DynPtr->PrevOrientMat;
 
 
183
            dynPtr->PrevOrientEuler = sbptr->DynPtr->PrevOrientEuler;
 
 
184
 
 
 
185
            dynPtr->AngVelocity.EulerX = (((FastRandom()&2047)-1023))<<2;
 
 
186
            dynPtr->AngVelocity.EulerY = (((FastRandom()&2047)-1023))<<2;
 
 
187
            dynPtr->AngVelocity.EulerZ = (((FastRandom()&2047)-1023))<<2;
 
 
188
 
 
 
189
            dynPtr->LinImpulse.vy = - (FastRandom() & 1023) << 2;
 
 
190
 
 
 
191
            /* Look to see if object has only one polygon in it;
 
 
192
               if so it's probably a glass fragment, so don't bother
 
 
193
               giving it collisions */
 
 
194
 
 
 
195
            if (1 == dispPtr->ShapeData->numitems)
 
 
196
                dynPtr->DynamicsType = DYN_TYPE_NO_COLLISIONS;
 
 
197
        }
 
 
198
 
 
 
199
        frags++;
 
 
200
    }
 
 
201
}
 
 
202
 
 
 
203
static void DoAlienLimbLossSound(VECTORCH *position)
 
 
204
{
 
 
205
    PlayAlienSound(0, ASC_LimbLoss, 0, NULL, position);
 
 
206
}
 
 
207
 
 
 
208
static void MakeFleshRippingNoises(VECTORCH *positionPtr)
 
 
209
{
 
 
210
    Sound_Play(SID_BODY_BEING_HACKED_UP_0 + (FastRandom() % 5) , "d", positionPtr);
 
 
211
}
 
 
212
 
 
 
213
DISPLAYBLOCK *disengage_part(STRATEGYBLOCK *parent_sbPtr, SECTION_DATA *root, VECTORCH *positionPtr, MATRIXCH *orientation, int *wounds, int speed)
 
 
214
{
 
 
215
    if( (NumActiveBlocks > maxobjects-5) || (NumActiveStBlocks > maxstblocks-5))
 
 
216
        return NULL;
 
 
217
 
 
 
218
    assert(root);
 
 
219
 
 
 
220
    STRATEGYBLOCK* sbPtr= CreateActiveStrategyBlock(I_BehaviourHierarchicalFragment);
 
 
221
 
 
 
222
    if(NULL == sbPtr)
 
 
223
        return NULL;
 
 
224
 
 
 
225
    //DISPLAYBLOCK *dispPtr = AllocateNewObject(root->sempai->ShapeNum);
 
 
226
    DISPLAYBLOCK *dispPtr = sbPtr->DisplayBlock = AllocateNewObject(GetLoadedShapeMSL("Shell"));    
 
 
227
    DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_STATIC);
 
 
228
    sbPtr->dataptr = malloc(sizeof(HDEBRIS_BEHAV_BLOCK));
 
 
229
 
 
 
230
    if (!dispPtr || !dynPtr || (NULL == sbPtr->dataptr))
 
 
231
    {
 
 
232
        RemoveBehaviourStrategy(sbPtr);
 
 
233
        return NULL;
 
 
234
    }
 
 
235
 
 
 
236
    dynPtr->Mass = 10;
 
 
237
    dynPtr->IsStatic = 0;
 
 
238
    dynPtr->IgnoreSameObjectsAsYou = 1;
 
 
239
    dispPtr->ObWorld = *positionPtr;
 
 
240
 
 
 
241
    // 2. NOW set up the strategyblock-specific fields for
 
 
242
    // the new displayblock. We won't go through the "AttachNew
 
 
243
    // StrategyBlock" and "AssignRunTimeBehaviours" pair, since
 
 
244
    // the first switches on ObShape and the second on bhvr;
 
 
245
    // but, in this case, there isn't a particular connection
 
 
246
    // between them.
 
 
247
 
 
 
248
    dispPtr->ObStrategyBlock = sbPtr;
 
 
249
 
 
 
250
    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->counter = HDEBRIS_LIFETIME;
 
 
251
    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->smokes = 0;
 
 
252
    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Bounce_Sound = SID_NOSOUND;
 
 
253
    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->GibbFactor = 0;
 
 
254
 
 
 
255
    if (root->sempai->flags & section_flag_gibbwhenfragged)
 
 
256
        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->GibbFactor = (ONE_FIXED >> 1);
 
 
257
 
 
 
258
    /* Inheritance of android flag. */
 
 
259
    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Android = 0;
 
 
260
 
 
 
261
    int wounds_temp = Splice_HModels(&(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), root);
 
 
262
 
 
 
263
    if (wounds)
 
 
264
         *wounds = wounds_temp;
 
 
265
 
 
 
266
    if (parent_sbPtr)
 
 
267
    {
 
 
268
        /* Inherit fire! */
 
 
269
 
 
 
270
        sbPtr->DamageBlock.IsOnFire = parent_sbPtr->DamageBlock.IsOnFire;
 
 
271
 
 
 
272
        /* KJL 11:28:27 14/10/98 - this is set so we can later know what the debris was part of */
 
 
273
        /* CDF 3/3/99 put it in the switch statement, to deal with complex cases */
 
 
274
        /* Creature specific code! */
 
 
275
 
 
 
276
        switch (parent_sbPtr->type)
 
 
277
        {
 
 
278
            case I_BehaviourAlien:
 
 
279
            {
 
 
280
                ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(parent_sbPtr->dataptr);    
 
 
281
                /* Just go to spasm. */
 
 
282
                InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_AlienStand,
ASSS_Spasm, -1, 1);
 
 
283
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
284
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
285
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = I_BehaviourAlien;
 
 
286
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = alienStatusPointer->Type;
 
 
287
                root->SecMat = *orientation;
 
 
288
 
 
 
289
                DoAlienLimbLossSound(positionPtr);
 
 
290
 
 
 
291
                /* Last as long as a dead alien. */
 
 
292
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->counter = ALIEN_DYINGTIME;
 
 
293
            }
 
 
294
            break;
 
 
295
            case I_BehaviourMarine:
 
 
296
            {
 
 
297
                /* See if we can strip to template. */
 
 
298
                MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(parent_sbPtr->dataptr);    
 
 
299
 
 
 
300
                SECTION *template_root = GetNamedHierarchyFromLibrary(marineStatusPointer->My_Weapon->Riffname,
marineStatusPointer->My_Weapon->TemplateName);
 
 
301
                /* Now, find the section that matches. */
 
 
302
                SECTION *template_sempai = Get_Corresponding_Section_Recursive(template_root, (((HDEBRIS_BEHAV_BLOCK * )
sbPtr->dataptr)->HModelController).Root_Section->Section_Name);
 
 
303
 
 
 
304
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Android = marineStatusPointer->Android;
 
 
305
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = I_BehaviourMarine;
 
 
306
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = marineStatusPointer->My_Weapon->ARealMarine;
 
 
307
 
 
 
308
                if (template_sempai)
 
 
309
                {
 
 
310
                    /* We have a match! */
 
 
311
                    Transmogrify_HModels(sbPtr, &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), template_sempai, 1, 0, 0);
 
 
312
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_MarineStand, MSSS_Spasm, -1, 1);
 
 
313
                    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
314
                    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
315
                    //((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootRotation = 1;
 
 
316
                    //MakeFleshRippingNoises(positionPtr);
 
 
317
                }
 
 
318
                else
 
 
319
                {
 
 
320
                    /* Forget it.  Must be a disembodied weapon, or something. */
 
 
321
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED<<1), 0, 1, ONE_FIXED, 0);
 
 
322
                    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
323
                    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
324
                    //((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootRotation = 1;
 
 
325
 
 
 
326
                    //dispPtr->ObMat = *orientation;
 
 
327
                    /* Below is an alternative... */
 
 
328
                }
 
 
329
 
 
 
330
                root->SecMat = *orientation;
 
 
331
 
 
 
332
                /* Since we're dealing with a marine, consider expressions. */
 
 
333
                {
 
 
334
                    SECTION_DATA *head = GetThisSectionData(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.section_data, "head");
 
 
335
 
 
 
336
                    if (head && !(head->flags & section_data_notreal))
 
 
337
                    {
 
 
338
                        TXACTRLBLK *tacb = head->tac_ptr;
 
 
339
 
 
 
340
                        while (tacb)
 
 
341
                        {
 
 
342
                            tacb->tac_sequence = 4;
 
 
343
                            tacb->tac_txah_s = GetTxAnimHeaderFromShape(tacb, head->ShapeNum);
 
 
344
                            tacb = tacb->tac_next;
 
 
345
                        }
 
 
346
                    }
 
 
347
                }
 
 
348
 
 
 
349
                /* Last as long as a dead marine. */
 
 
350
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->counter = MARINE_DYINGTIME;
 
 
351
            }
 
 
352
            break;
 
 
353
            case I_BehaviourPredator:
 
 
354
            {
 
 
355
                /* See if we can strip to template. */
 
 
356
 
 
 
357
                SECTION *template_root = GetNamedHierarchyFromLibrary("hnpcpredator", "Template");
 
 
358
                /* Now, find the section that matches. */
 
 
359
                SECTION *template_sempai = Get_Corresponding_Section_Recursive(template_root, (((HDEBRIS_BEHAV_BLOCK * )
sbPtr->dataptr)->HModelController).Root_Section->Section_Name);
 
 
360
 
 
 
361
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = I_BehaviourPredator;
 
 
362
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = 0;
 
 
363
 
 
 
364
                if (template_sempai)
 
 
365
                {
 
 
366
                    /* We have a match! */
 
 
367
                    Transmogrify_HModels(sbPtr, &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), template_sempai, 1, 0, 0);
 
 
368
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_PredatorStand, PSSS_Spasm, -1, 1);
 
 
369
                    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
370
                    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
371
                    root->SecMat = *orientation;
 
 
372
                }
 
 
373
                else
 
 
374
                {
 
 
375
                    /* Forget it.  Must be a disembodied weapon, or something. */
 
 
376
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED<<1), 0, 1, ONE_FIXED, 0);
 
 
377
                    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
378
                    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
379
                    root->SecMat = *orientation;
 
 
380
                }
 
 
381
                /* Just freeze for now! */
 
 
382
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.Playing = 0;
 
 
383
                /* Last as long as a dead predator. */
 
 
384
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->counter = PRED_DIETIME;
 
 
385
            }
 
 
386
            break;
 
 
387
            case I_BehaviourCorpse:
 
 
388
            {
 
 
389
                CORPSEDATABLOCK *corpseDataPtr = (CORPSEDATABLOCK *)parent_sbPtr->dataptr;
 
 
390
 
 
 
391
                switch (corpseDataPtr->Type)
 
 
392
                {
 
 
393
                    case I_BehaviourAlien:
 
 
394
                    {
 
 
395
                        DoAlienLimbLossSound(positionPtr);
 
 
396
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_AlienStand, ASSS_Spasm, -1, 1);
 
 
397
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = corpseDataPtr->subtype;
 
 
398
                    }
 
 
399
                    break;
 
 
400
                    case I_BehaviourMarine:
 
 
401
                    {
 
 
402
                        SECTION *template_sempai;
 
 
403
                        SECTION *template_root = corpseDataPtr->TemplateRoot;
 
 
404
                        /* Now, find the section that matches. */
 
 
405
template_sempai=Get_Corresponding_Section_Recursive(template_root, (((HDEBRIS_BEHAV_BLOCK * )
sbPtr->dataptr)->HModelController).Root_Section->Section_Name);
 
 
406
 
 
 
407
                        //if (template_sempai) MakeFleshRippingNoises(positionPtr);
 
 
408
 
 
 
409
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController),(ONE_FIXED>>2), HMSQT_MarineStand, MSSS_Spasm, -1, 1);
 
 
410
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = corpseDataPtr->ARealMarine;
 
 
411
                    }
 
 
412
                    break;
 
 
413
                    case I_BehaviourPredator:
 
 
414
                    {
 
 
415
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_PredatorStand, PSSS_Spasm, -1, 1);
 
 
416
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = corpseDataPtr->subtype;
 
 
417
                    }
 
 
418
                    break;
 
 
419
                    default:
 
 
420
                    {
 
 
421
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED<<1), 0, 1, ONE_FIXED, 0);
 
 
422
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = corpseDataPtr->subtype;
 
 
423
                    }
 
 
424
                }
 
 
425
 
 
 
426
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
427
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
428
                root->SecMat = *orientation;
 
 
429
 
 
 
430
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = corpseDataPtr->Type;
 
 
431
                /* Inherit counter from parent corpse. */
 
 
432
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->counter = corpseDataPtr->timer;
 
 
433
            }
 
 
434
            break;
 
 
435
            case I_BehaviourHierarchicalFragment:
 
 
436
            {
 
 
437
                HDEBRIS_BEHAV_BLOCK *debrisDataPtr  = (HDEBRIS_BEHAV_BLOCK *)parent_sbPtr->dataptr;
 
 
438
 
 
 
439
                switch (debrisDataPtr->Type)
 
 
440
                {
 
 
441
                    case I_BehaviourAlien:
 
 
442
                    {
 
 
443
                        //DoAlienLimbLossSound(positionPtr);
 
 
444
                        /* Sound should be the same for all types of alien! */
 
 
445
                        InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_AlienStand,
ASSS_Spasm, -1, 1);
 
 
446
                    }
 
 
447
                    break;
 
 
448
                    case I_BehaviourMarine:
 
 
449
                        //MakeFleshRippingNoises(positionPtr);
 
 
450
                        InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_MarineStand,
MSSS_Spasm, -1, 1);
 
 
451
 
 
 
452
                        if (!strcmp(root->sempai->Section_Name, "SADAR"))
 
 
453
                        {
 
 
454
                            ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Bounce_Sound = SID_LARGEWEAPONDROP;
 
 
455
                            dynPtr->Elasticity = (ONE_FIXED >> 3);
 
 
456
                        }
 
 
457
                        else if (!strcmp(root->sempai->Section_Name, "gren stock")
 
 
458
                        || !strcmp(root->sempai->Section_Name, "flamer")
 
 
459
                        || !strcmp(root->sempai->Section_Name, "flame thrower")
 
 
460
                        || !strcmp(root->sempai->Section_Name, "mini gun"))
 
 
461
                        {
 
 
462
                            ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Bounce_Sound = SID_LARGEWEAPONDROP;
 
 
463
                        }
 
 
464
                        else if (!strcmp(root->sempai->Section_Name, "spring one"))
 
 
465
                        {
 
 
466
                            /* This is a smartgun! */
 
 
467
                            ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Bounce_Sound = SID_LARGEWEAPONDROP;
 
 
468
                            /* Whilst we're here... */
 
 
469
                            dispPtr->ObMat = *orientation;
 
 
470
                            root->SecMat = IdentityMatrix;
 
 
471
                            ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootRotation = 1;
 
 
472
                            ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.Playing = 0;
 
 
473
                        }
 
 
474
                        else if (!strcmp(root->sempai->Section_Name, "pulse mag"))
 
 
475
                        {
 
 
476
                            /* Don't have a 'tink' yet... */
 
 
477
                            dynPtr->Elasticity = (ONE_FIXED >> 1);
 
 
478
                        }
 
 
479
                    break;
 
 
480
                    case I_BehaviourPredator:
 
 
481
                        InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_PredatorStand,
PSSS_Spasm, -1, 1);
 
 
482
                    break;
 
 
483
                    default:
 
 
484
                        InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED<<1), 0, 1, ONE_FIXED, 0);
 
 
485
                }
 
 
486
 
 
 
487
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
488
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
489
                root->SecMat = *orientation;
 
 
490
 
 
 
491
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = debrisDataPtr->Type;
 
 
492
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = debrisDataPtr->SubType;
 
 
493
                /* Inherit counter from parent debris. */
 
 
494
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->counter = debrisDataPtr->counter;
 
 
495
            }
 
 
496
            break;
 
 
497
            case I_BehaviourNetGhost:
 
 
498
            {
 
 
499
                NETGHOSTDATABLOCK *dataptr = parent_sbPtr->dataptr;
 
 
500
 
 
 
501
                switch (dataptr->type)
 
 
502
                {
 
 
503
                    case I_BehaviourAlien:
 
 
504
                    {
 
 
505
                        //DoAlienLimbLossSound(positionPtr);
 
 
506
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_AlienStand, ASSS_Spasm, -1, 1);
 
 
507
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
508
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
509
                        root->SecMat = *orientation;
 
 
510
 
 
 
511
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = I_BehaviourAlien;
 
 
512
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = dataptr->subtype;
 
 
513
                    }
 
 
514
                    break;
 
 
515
                    case I_BehaviourCorpse:
 
 
516
                    {
 
 
517
                        switch (dataptr->subtype)
 
 
518
                        {
 
 
519
                            case I_BehaviourAlien:
 
 
520
                            {
 
 
521
                                DoAlienLimbLossSound(positionPtr);
 
 
522
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_AlienStand, ASSS_Spasm, -1, 1);
 
 
523
                                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
524
                                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
525
                                root->SecMat = *orientation;
 
 
526
 
 
 
527
                                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = I_BehaviourAlien;
 
 
528
                                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = dataptr->IOType;
 
 
529
                            }
 
 
530
                            break;
 
 
531
                            default:
 
 
532
                            {
 
 
533
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED<<1), 0, 1, ONE_FIXED, 0);
 
 
534
                                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
535
                                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
536
                                root->SecMat = *orientation;
 
 
537
 
 
 
538
                                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = parent_sbPtr->type;
 
 
539
                                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = 0;
 
 
540
                            }
 
 
541
                        }
 
 
542
                    }
 
 
543
                    break;
 
 
544
                    default:
 
 
545
                        InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED<<1), 0, 1, ONE_FIXED, 0);
 
 
546
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
547
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
548
                        root->SecMat = *orientation;
 
 
549
 
 
 
550
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = parent_sbPtr->type;
 
 
551
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = 0;
 
 
552
                }
 
 
553
            }
 
 
554
            break;
 
 
555
            case I_BehaviourAutoGun:
 
 
556
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Bounce_Sound = SID_LARGEWEAPONDROP;
 
 
557
                // no break for you
 
 
558
            default:
 
 
559
                InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED<<1), 0, 1, ONE_FIXED, 0);
 
 
560
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
561
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
562
                root->SecMat = *orientation;
 
 
563
 
 
 
564
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = parent_sbPtr->type;
 
 
565
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = 0;
 
 
566
        }
 
 
567
    }
 
 
568
    else
 
 
569
    {
 
 
570
        /* KJL 11:27:54 14/10/98 - set behaviour type to null to avoid confusion */
 
 
571
        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = I_BehaviourNull;
 
 
572
        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = 0;
 
 
573
        InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED<<1), 0, 1, ONE_FIXED, 0);
 
 
574
        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
575
        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
576
        //((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootRotation = 1;
 
 
577
        root->SecMat = *orientation;
 
 
578
    }
 
 
579
 
 
 
580
    dispPtr->HModelControlBlock = &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController);
 
 
581
 
 
 
582
    dispPtr->ObWorld = *positionPtr;
 
 
583
    //dispPtr->ObMat = *orientation;
 
 
584
    dispPtr->ObMat = IdentityMatrix;
 
 
585
 
 
 
586
    dynPtr->Position = *positionPtr;
 
 
587
    dynPtr->OrientMat = *orientation;
 
 
588
    //dynPtr->Mass = 5;
 
 
589
    dynPtr->Mass = 1;
 
 
590
 
 
 
591
    ProveHModel(dispPtr->HModelControlBlock, dispPtr);
 
 
592
 
 
 
593
return dispPtr;
 
 
594
}
 
 
595
 
 
 
596
DISPLAYBLOCK *MakeHierarchicalDebris(STRATEGYBLOCK *parent_sbPtr, SECTION_DATA *root, VECTORCH *positionPtr, MATRIXCH *orientation, int *wounds, int speed,
VECTORCH *incoming)
 
 
597
{
 
 
598
    /* KJL 16:53:22 28/02/98 - this seems to happen a lot in multiplayer */
 
 
599
    if(
 
 
600
    (positionPtr->vx > 1000000 || positionPtr->vx < -1000000)
 
 
601
    || 
 
 
602
    (positionPtr->vy > 1000000 || positionPtr->vy < -1000000)
 
 
603
    ||    
 
 
604
    (positionPtr->vz > 1000000 || positionPtr->vz < -1000000)
 
 
605
    )
 
 
606
        return NULL;
 
 
607
 
 
 
608
    if( (NumActiveBlocks > maxobjects-5) || (NumActiveStBlocks > maxstblocks-5))
 
 
609
        return NULL;
 
 
610
 
 
 
611
    assert(root);
 
 
612
 
 
 
613
    /* Right away, try to intercept all molotov cocktails! */
 
 
614
    if (!(root->flags & section_data_notreal) && !strcmp(root->sempai->Section_Name, "bottle"))
 
 
615
    {
 
 
616
        DISPLAYBLOCK *dispPtr = SpawnMolotovCocktail(root, orientation);
 
 
617
        /* Correct speed. */
 
 
618
 
 
 
619
        if (dispPtr)
 
 
620
        {
 
 
621
            DYNAMICSBLOCK *dynPtr = dispPtr->ObStrategyBlock->DynPtr;
 
 
622
 
 
 
623
            /* This code CnP'd from further down! */
 
 
624
            dynPtr->AngVelocity.EulerX = (FastRandom() & 2047) - 1024;
 
 
625
            dynPtr->AngVelocity.EulerY = (FastRandom() & 2047) - 1024;
 
 
626
            dynPtr->AngVelocity.EulerZ = (FastRandom() & 2047) - 1024;
 
 
627
 
 
 
628
            {
 
 
629
                int random = (FastRandom() & 1023) - 512;
 
 
630
 
 
 
631
                if (random > 0)
 
 
632
                    dynPtr->LinImpulse.vx = (random + 100) << speed;
 
 
633
                else
 
 
634
                    dynPtr->LinImpulse.vx = (random - 100) << speed;
 
 
635
            }
 
 
636
 
 
 
637
            {
 
 
638
                int random = (FastRandom() & 1023) - 768;
 
 
639
 
 
 
640
                if (random > 0)
 
 
641
                    dynPtr->LinImpulse.vy = (random + 100) << speed;
 
 
642
                else
 
 
643
                    dynPtr->LinImpulse.vy = (random - 100) << speed;
 
 
644
            }
 
 
645
 
 
 
646
            {
 
 
647
                int random = (FastRandom() & 1023) - 512;
 
 
648
 
 
 
649
                if (random > 0)
 
 
650
                    dynPtr->LinImpulse.vz = (random + 100) << speed;
 
 
651
                else
 
 
652
                    dynPtr->LinImpulse.vz = (random - 100) << speed;
 
 
653
            }
 
 
654
        }
 
 
655
 
 
 
656
        return dispPtr;
 
 
657
    }
 
 
658
 
 
 
659
    STRATEGYBLOCK* sbPtr = CreateActiveStrategyBlock(I_BehaviourHierarchicalFragment);
 
 
660
 
 
 
661
    if(NULL == sbPtr)
 
 
662
        return NULL;
 
 
663
 
 
 
664
    DISPLAYBLOCK *dispPtr = sbPtr->DisplayBlock = AllocateNewObject(GetLoadedShapeMSL("Shell"));    
 
 
665
    DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_STATIC);
 
 
666
    sbPtr->dataptr = malloc(sizeof(HDEBRIS_BEHAV_BLOCK));
 
 
667
 
 
 
668
    if (!dispPtr || !dynPtr || !sbPtr->dataptr)
 
 
669
    {
 
 
670
        RemoveBehaviourStrategy(sbPtr);
 
 
671
        return NULL;
 
 
672
    }
 
 
673
 
 
 
674
    dynPtr->Mass = 10;
 
 
675
    dynPtr->IsStatic = 0;
 
 
676
    dynPtr->IgnoreSameObjectsAsYou = 1;
 
 
677
 
 
 
678
    dispPtr->ObWorld = *positionPtr;
 
 
679
    dispPtr->ObStrategyBlock = sbPtr;
 
 
680
    dynPtr->Mass = 80;
 
 
681
 
 
 
682
    // 2. NOW set up the strategyblock-specific fields for
 
 
683
    // the new displayblock. We won't go through the "AttachNew
 
 
684
    // StrategyBlock" and "AssignRunTimeBehaviours" pair, since
 
 
685
    // the first switches on ObShape and the second on bhvr;
 
 
686
    // but, in this case, there isn't a particular connection
 
 
687
    // between them.
 
 
688
 
 
 
689
    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->counter = HDEBRIS_LIFETIME;
 
 
690
    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->smokes = 0;
 
 
691
    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Bounce_Sound = SID_NOSOUND;
 
 
692
    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->GibbFactor = 0;
 
 
693
 
 
 
694
    if (root->sempai->flags & section_flag_gibbwhenfragged)
 
 
695
        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->GibbFactor = (ONE_FIXED >> 1);
 
 
696
 
 
 
697
    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Android = 0;
 
 
698
 
 
 
699
    int wounds_temp = Splice_HModels(&(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), root);
 
 
700
 
 
 
701
    if (wounds)
 
 
702
         *wounds = wounds_temp;
 
 
703
 
 
 
704
    if (parent_sbPtr)
 
 
705
    {
 
 
706
        /* Inherit fire! */
 
 
707
 
 
 
708
        sbPtr->DamageBlock.IsOnFire = parent_sbPtr->DamageBlock.IsOnFire;
 
 
709
 
 
 
710
        /* KJL 11:28:27 14/10/98 - this is set so we can later know what the debris was part of */
 
 
711
        /* CDF 3/3/99 put it in the switch statement, to deal with complex cases */
 
 
712
        /* Creature specific code! */
 
 
713
 
 
 
714
        switch (parent_sbPtr->type)
 
 
715
        {
 
 
716
            case I_BehaviourAlien:
 
 
717
            {
 
 
718
                ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(parent_sbPtr->dataptr);    
 
 
719
                assert(alienStatusPointer);
 
 
720
                /* Just go to spasm. */
 
 
721
                InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_AlienStand,
ASSS_Spasm, -1, 1);
 
 
722
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
723
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
724
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = I_BehaviourAlien;
 
 
725
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = alienStatusPointer->Type;
 
 
726
                root->SecMat = *orientation;
 
 
727
 
 
 
728
                DoAlienLimbLossSound(positionPtr);
 
 
729
 
 
 
730
                /* Last as long as a dead alien. */
 
 
731
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->counter = ALIEN_DYINGTIME;
 
 
732
            }
 
 
733
            break;
 
 
734
            case I_BehaviourMarine:
 
 
735
            {
 
 
736
                /* See if we can strip to template. */
 
 
737
                MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(parent_sbPtr->dataptr);    
 
 
738
                assert(marineStatusPointer);
 
 
739
 
 
 
740
                SECTION *template_root = GetNamedHierarchyFromLibrary(marineStatusPointer->My_Weapon->Riffname,
marineStatusPointer->My_Weapon->TemplateName);
 
 
741
                /* Now, find the section that matches. */
 
 
742
                SECTION *template_sempai = Get_Corresponding_Section_Recursive(template_root, (((HDEBRIS_BEHAV_BLOCK * )
sbPtr->dataptr)->HModelController).Root_Section->Section_Name);
 
 
743
 
 
 
744
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Android = marineStatusPointer->Android;
 
 
745
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = I_BehaviourMarine;
 
 
746
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = marineStatusPointer->My_Weapon->ARealMarine;
 
 
747
 
 
 
748
                if (template_sempai)
 
 
749
                {
 
 
750
                    /* We have a match! */
 
 
751
                    Transmogrify_HModels(sbPtr, &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), template_sempai, 1, 0, 0);
 
 
752
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_MarineStand, MSSS_Spasm, -1, 1);
 
 
753
                    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
754
                    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
755
                    //((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootRotation = 1;
 
 
756
                    //MakeFleshRippingNoises(positionPtr);
 
 
757
                }
 
 
758
                else
 
 
759
                {
 
 
760
                    /* Forget it.  Must be a disembodied weapon, or something. */
 
 
761
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED<<1), 0, 1, ONE_FIXED, 0);
 
 
762
                    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
763
                    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
764
                    //((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootRotation = 1;
 
 
765
 
 
 
766
                    //dispPtr->ObMat = *orientation;
 
 
767
                    /* Below is an alternative... */
 
 
768
                }
 
 
769
 
 
 
770
                root->SecMat = *orientation;
 
 
771
 
 
 
772
                /* Since we're dealing with a marine, consider expressions. */
 
 
773
                {
 
 
774
                    SECTION_DATA *head = GetThisSectionData(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.section_data, "head");
 
 
775
 
 
 
776
                    if (head && !(head->flags & section_data_notreal))
 
 
777
                    {
 
 
778
                        TXACTRLBLK *tacb = head->tac_ptr;
 
 
779
 
 
 
780
                        while (tacb)
 
 
781
                        {
 
 
782
                            tacb->tac_sequence = 4;
 
 
783
                            tacb->tac_txah_s = GetTxAnimHeaderFromShape(tacb, head->ShapeNum);
 
 
784
                            tacb = tacb->tac_next;
 
 
785
                        }
 
 
786
                    }
 
 
787
                }
 
 
788
 
 
 
789
                /* Last as long as a dead marine. */
 
 
790
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->counter = MARINE_DYINGTIME;
 
 
791
            }
 
 
792
            break;
 
 
793
            case I_BehaviourPredator:
 
 
794
            {
 
 
795
                /* See if we can strip to template. */
 
 
796
 
 
 
797
                SECTION *template_root = GetNamedHierarchyFromLibrary("hnpcpredator", "Template");
 
 
798
                /* Now, find the section that matches. */
 
 
799
                SECTION *template_sempai = Get_Corresponding_Section_Recursive(template_root, (((HDEBRIS_BEHAV_BLOCK * )
sbPtr->dataptr)->HModelController).Root_Section->Section_Name);
 
 
800
 
 
 
801
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = I_BehaviourPredator;
 
 
802
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = 0;
 
 
803
 
 
 
804
                if (template_sempai)
 
 
805
                {
 
 
806
                    /* We have a match! */
 
 
807
                    Transmogrify_HModels(sbPtr, &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), template_sempai, 1, 0, 0);
 
 
808
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_PredatorStand, PSSS_Spasm, -1, 1);
 
 
809
                    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
810
                    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
811
                    root->SecMat = *orientation;
 
 
812
                }
 
 
813
                else
 
 
814
                {
 
 
815
                    /* Forget it.  Must be a disembodied weapon, or something. */
 
 
816
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED<<1), 0, 1, ONE_FIXED, 0);
 
 
817
                    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
818
                    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
819
                    root->SecMat = *orientation;
 
 
820
                }
 
 
821
                /* Just freeze for now! */
 
 
822
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.Playing = 0;
 
 
823
                /* Last as long as a dead predator. */
 
 
824
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->counter = PRED_DIETIME;
 
 
825
            }
 
 
826
            break;
 
 
827
            case I_BehaviourCorpse:
 
 
828
            {
 
 
829
                CORPSEDATABLOCK *corpseDataPtr = (CORPSEDATABLOCK *)parent_sbPtr->dataptr;
 
 
830
 
 
 
831
                switch (corpseDataPtr->Type)
 
 
832
                {
 
 
833
                    case I_BehaviourAlien:
 
 
834
                    {
 
 
835
                        DoAlienLimbLossSound(positionPtr);
 
 
836
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_AlienStand, ASSS_Spasm, -1, 1);
 
 
837
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = corpseDataPtr->subtype;
 
 
838
                    }
 
 
839
                    break;
 
 
840
                    case I_BehaviourMarine:
 
 
841
                    {
 
 
842
                        SECTION *template_sempai;
 
 
843
                        SECTION *template_root = corpseDataPtr->TemplateRoot;
 
 
844
                        /* Now, find the section that matches. */
 
 
845
template_sempai=Get_Corresponding_Section_Recursive(template_root, (((HDEBRIS_BEHAV_BLOCK * )
sbPtr->dataptr)->HModelController).Root_Section->Section_Name);
 
 
846
 
 
 
847
                        //if (template_sempai) MakeFleshRippingNoises(positionPtr);
 
 
848
 
 
 
849
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController),(ONE_FIXED>>2), HMSQT_MarineStand, MSSS_Spasm, -1, 1);
 
 
850
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = corpseDataPtr->ARealMarine;
 
 
851
                    }
 
 
852
                    break;
 
 
853
                    case I_BehaviourPredator:
 
 
854
                    {
 
 
855
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_PredatorStand, PSSS_Spasm, -1, 1);
 
 
856
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = corpseDataPtr->subtype;
 
 
857
                    }
 
 
858
                    break;
 
 
859
                    default:
 
 
860
                    {
 
 
861
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED<<1), 0, 1, ONE_FIXED, 0);
 
 
862
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = corpseDataPtr->subtype;
 
 
863
                    }
 
 
864
                }
 
 
865
 
 
 
866
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
867
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
868
                root->SecMat = *orientation;
 
 
869
 
 
 
870
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = corpseDataPtr->Type;
 
 
871
                /* Inherit counter from parent corpse. */
 
 
872
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->counter = corpseDataPtr->timer;
 
 
873
            }
 
 
874
            break;
 
 
875
            case I_BehaviourHierarchicalFragment:
 
 
876
            {
 
 
877
                HDEBRIS_BEHAV_BLOCK *debrisDataPtr  = (HDEBRIS_BEHAV_BLOCK *)parent_sbPtr->dataptr;
 
 
878
 
 
 
879
                switch (debrisDataPtr->Type)
 
 
880
                {
 
 
881
                    case I_BehaviourAlien:
 
 
882
                    {
 
 
883
                        //DoAlienLimbLossSound(positionPtr);
 
 
884
                        /* Sound should be the same for all types of alien! */
 
 
885
                        InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_AlienStand,
ASSS_Spasm, -1, 1);
 
 
886
                    }
 
 
887
                    break;
 
 
888
                    case I_BehaviourMarine:
 
 
889
                        //MakeFleshRippingNoises(positionPtr);
 
 
890
                        InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_MarineStand,
MSSS_Spasm, -1, 1);
 
 
891
 
 
 
892
                        if (!strcmp(root->sempai->Section_Name, "SADAR"))
 
 
893
                        {
 
 
894
                            ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Bounce_Sound = SID_LARGEWEAPONDROP;
 
 
895
                            dynPtr->Elasticity = (ONE_FIXED >> 3);
 
 
896
                        }
 
 
897
                        else if (!strcmp(root->sempai->Section_Name, "gren stock")
 
 
898
                        || !strcmp(root->sempai->Section_Name, "flamer")
 
 
899
                        || !strcmp(root->sempai->Section_Name, "flame thrower")
 
 
900
                        || !strcmp(root->sempai->Section_Name, "mini gun"))
 
 
901
                        {
 
 
902
                            ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Bounce_Sound = SID_LARGEWEAPONDROP;
 
 
903
                        }
 
 
904
                        else if (!strcmp(root->sempai->Section_Name, "spring one"))
 
 
905
                        {
 
 
906
                            /* This is a smartgun! */
 
 
907
                            ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Bounce_Sound = SID_LARGEWEAPONDROP;
 
 
908
                            /* Whilst we're here... */
 
 
909
                            dispPtr->ObMat = *orientation;
 
 
910
                            root->SecMat = IdentityMatrix;
 
 
911
                            ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootRotation = 1;
 
 
912
                            ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.Playing = 0;
 
 
913
                        }
 
 
914
                        else if (!strcmp(root->sempai->Section_Name, "pulse mag"))
 
 
915
                        {
 
 
916
                            /* Don't have a 'tink' yet... */
 
 
917
                            dynPtr->Elasticity = (ONE_FIXED >> 1);
 
 
918
                        }
 
 
919
                    break;
 
 
920
                    case I_BehaviourPredator:
 
 
921
                        InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_PredatorStand,
PSSS_Spasm, -1, 1);
 
 
922
                    break;
 
 
923
                    default:
 
 
924
                        InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED<<1), 0, 1, ONE_FIXED, 0);
 
 
925
                }
 
 
926
 
 
 
927
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
928
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
929
                root->SecMat = *orientation;
 
 
930
 
 
 
931
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = debrisDataPtr->Type;
 
 
932
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = debrisDataPtr->SubType;
 
 
933
                /* Inherit counter from parent debris. */
 
 
934
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->counter = debrisDataPtr->counter;
 
 
935
            }
 
 
936
            break;
 
 
937
            case I_BehaviourNetGhost:
 
 
938
            {
 
 
939
                NETGHOSTDATABLOCK *dataptr = parent_sbPtr->dataptr;
 
 
940
 
 
 
941
                switch (dataptr->type)
 
 
942
                {
 
 
943
                    case I_BehaviourAlien:
 
 
944
                    {
 
 
945
                        //DoAlienLimbLossSound(positionPtr);
 
 
946
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_AlienStand, ASSS_Spasm, -1, 1);
 
 
947
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
948
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
949
                        root->SecMat = *orientation;
 
 
950
 
 
 
951
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = I_BehaviourAlien;
 
 
952
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = dataptr->subtype;
 
 
953
                    }
 
 
954
                    break;
 
 
955
                    case I_BehaviourCorpse:
 
 
956
                    {
 
 
957
                        switch (dataptr->subtype)
 
 
958
                        {
 
 
959
                            case I_BehaviourAlien:
 
 
960
                            {
 
 
961
                                DoAlienLimbLossSound(positionPtr);
 
 
962
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED>>2), HMSQT_AlienStand, ASSS_Spasm, -1, 1);
 
 
963
                                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
964
                                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
965
                                root->SecMat = *orientation;
 
 
966
 
 
 
967
                                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = I_BehaviourAlien;
 
 
968
                                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = dataptr->IOType;
 
 
969
                            }
 
 
970
                            break;
 
 
971
                            default:
 
 
972
                            {
 
 
973
InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED<<1), 0, 1, ONE_FIXED, 0);
 
 
974
                                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
975
                                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
976
                                root->SecMat = *orientation;
 
 
977
 
 
 
978
                                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = parent_sbPtr->type;
 
 
979
                                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = 0;
 
 
980
                            }
 
 
981
                        }
 
 
982
                    }
 
 
983
                    break;
 
 
984
                    default:
 
 
985
                        InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED<<1), 0, 1, ONE_FIXED, 0);
 
 
986
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
987
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
988
                        root->SecMat = *orientation;
 
 
989
 
 
 
990
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = parent_sbPtr->type;
 
 
991
                        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = 0;
 
 
992
                }
 
 
993
            }
 
 
994
            break;
 
 
995
            case I_BehaviourAutoGun:
 
 
996
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Bounce_Sound = SID_LARGEWEAPONDROP;
 
 
997
                // no break for you
 
 
998
            default:
 
 
999
                InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED<<1), 0, 1, ONE_FIXED, 0);
 
 
1000
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
1001
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
1002
                root->SecMat = *orientation;
 
 
1003
 
 
 
1004
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = parent_sbPtr->type;
 
 
1005
                ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = 0;
 
 
1006
        }
 
 
1007
    }
 
 
1008
    else
 
 
1009
    {
 
 
1010
        /* KJL 11:27:54 14/10/98 - set behaviour type to null to avoid confusion */
 
 
1011
        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = I_BehaviourNull;
 
 
1012
        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = 0;
 
 
1013
        InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED<<1), 0, 1, ONE_FIXED, 0);
 
 
1014
        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
1015
        ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
1016
        //((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootRotation = 1;
 
 
1017
        root->SecMat = *orientation;
 
 
1018
    }
 
 
1019
 
 
 
1020
    dispPtr->HModelControlBlock = &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController);
 
 
1021
 
 
 
1022
    dispPtr->ObWorld = *positionPtr;
 
 
1023
    //dispPtr->ObMat = *orientation;
 
 
1024
    dispPtr->ObMat = IdentityMatrix;
 
 
1025
 
 
 
1026
    dynPtr->Position = *positionPtr;
 
 
1027
    dynPtr->OrientMat = *orientation;
 
 
1028
    //dynPtr->Mass = 5;
 
 
1029
if(incoming)
 
 
1030
    dynPtr->LinImpulse = *incoming;
 
 
1031
/*
 
 
1032
    // Give explosion fragments an angular velocity
 
 
1033
    dynPtr->AngVelocity.EulerX = (FastRandom() & 2047) - 1024;
 
 
1034
    dynPtr->AngVelocity.EulerY = (FastRandom() & 2047) - 1024;
 
 
1035
    dynPtr->AngVelocity.EulerZ = (FastRandom() & 2047) - 1024;
 
 
1036
 
 
 
1037
    {
 
 
1038
        int random = (FastRandom() & 1023) - 512;
 
 
1039
 
 
 
1040
        if (random > 0)
 
 
1041
            dynPtr->LinImpulse.vx = (random + 100) << speed;
 
 
1042
        else
 
 
1043
            dynPtr->LinImpulse.vx = (random - 100) << speed;
 
 
1044
    }
 
 
1045
 
 
 
1046
    {
 
 
1047
        int random = (FastRandom() & 1023) - 768;
 
 
1048
 
 
 
1049
        if (random > 0)
 
 
1050
            dynPtr->LinImpulse.vy = (random + 100) << speed;
 
 
1051
        else
 
 
1052
            dynPtr->LinImpulse.vy = (random - 100) << speed;
 
 
1053
    }
 
 
1054
 
 
 
1055
    {
 
 
1056
        int random = (FastRandom() & 1023) - 512;
 
 
1057
 
 
 
1058
        if (random > 0)
 
 
1059
            dynPtr->LinImpulse.vz = (random + 100) << speed;
 
 
1060
        else
 
 
1061
            dynPtr->LinImpulse.vz = (random - 100) << speed;
 
 
1062
    }
 
 
1063
*/
 
 
1064
 
 
 
1065
    ProveHModel(dispPtr->HModelControlBlock, dispPtr);
 
 
1066
 
 
 
1067
return dispPtr;
 
 
1068
}
 
 
1069
 
 
 
1070
void make_clip(SECTION_DATA *root, VECTORCH *positionPtr, MATRIXCH *orientation)
 
 
1071
{
 
 
1072
    assert(root);
 
 
1073
 
 
 
1074
    if( (NumActiveBlocks > maxobjects-5) || (NumActiveStBlocks > maxstblocks-5))
 
 
1075
        return;
 
 
1076
 
 
 
1077
    STRATEGYBLOCK* sbPtr = CreateActiveStrategyBlock(I_BehaviourHierarchicalFragment);
 
 
1078
 
 
 
1079
    if(NULL == sbPtr)
 
 
1080
        return;
 
 
1081
 
 
 
1082
    DISPLAYBLOCK *dispPtr = sbPtr->DisplayBlock = CreateActiveObject();
 
 
1083
    DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_STATIC);
 
 
1084
    sbPtr->dataptr = malloc(sizeof(HDEBRIS_BEHAV_BLOCK));
 
 
1085
 
 
 
1086
    if(!dispPtr || !sbPtr->dataptr || !dynPtr)
 
 
1087
    {
 
 
1088
        RemoveBehaviourStrategy(sbPtr);
 
 
1089
        return;
 
 
1090
    }
 
 
1091
 
 
 
1092
    dynPtr->Mass = 1;
 
 
1093
    dynPtr->IsStatic = 0;
 
 
1094
    dynPtr->IgnoreSameObjectsAsYou = 1;
 
 
1095
 
 
 
1096
    dispPtr->extent.min_x = -10;
 
 
1097
    dispPtr->extent.min_y = -10;
 
 
1098
    dispPtr->extent.min_z = -10;
 
 
1099
    dispPtr->extent.max_x = 10;
 
 
1100
    dispPtr->extent.max_y = 10;
 
 
1101
    dispPtr->extent.max_z = 10;
 
 
1102
    dispPtr->ObMat = IdentityMatrix;
 
 
1103
    dispPtr->ObWorld = *positionPtr;
 
 
1104
 
 
 
1105
    // 2. NOW set up the strategyblock-specific fields for
 
 
1106
    // the new displayblock. We won't go through the "AttachNew
 
 
1107
    // StrategyBlock" and "AssignRunTimeBehaviours" pair, since
 
 
1108
    // the first switches on ObShape and the second on bhvr;
 
 
1109
    // but, in this case, there isn't a particular connection
 
 
1110
    // between them.
 
 
1111
 
 
 
1112
    dispPtr->ObStrategyBlock = sbPtr;
 
 
1113
 
 
 
1114
    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->counter = HDEBRIS_LIFETIME;
 
 
1115
    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->smokes = 0;
 
 
1116
    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Bounce_Sound = SID_NOSOUND;
 
 
1117
    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->GibbFactor = 0;
 
 
1118
    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Android = 0;
 
 
1119
 
 
 
1120
    Splice_HModels(&(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), root);
 
 
1121
 
 
 
1122
    /* KJL 11:27:54 14/10/98 - set behaviour type to null to avoid confusion */
 
 
1123
    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->Type = I_BehaviourNull;
 
 
1124
    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->SubType = 0;
 
 
1125
    InitHModelTweening( &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController), (ONE_FIXED<<1), 0, 1, ONE_FIXED, 0);
 
 
1126
    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.LockTopSection = 1;
 
 
1127
    ((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootDisplacement = 1;
 
 
1128
    //((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController.ZeroRootRotation = 1;
 
 
1129
    root->SecMat = *orientation;
 
 
1130
 
 
 
1131
    dispPtr->HModelControlBlock = &(((HDEBRIS_BEHAV_BLOCK * ) sbPtr->dataptr)->HModelController);
 
 
1132
 
 
 
1133
    dynPtr->Position = *positionPtr;
 
 
1134
    dynPtr->OrientMat = *orientation;
 
 
1135
    dynPtr->Mass = 1;
 
 
1136
 
 
 
1137
    ProveHModel(dispPtr->HModelControlBlock, dispPtr);
 
 
1138
 
 
 
1139
    assert(dispPtr->ObWorld.vx < 1000000 && dispPtr->ObWorld.vx > -1000000);
 
 
1140
    assert(dispPtr->ObWorld.vy < 1000000 && dispPtr->ObWorld.vy > -1000000);
 
 
1141
    assert(dispPtr->ObWorld.vz < 1000000 && dispPtr->ObWorld.vz > -1000000);
 
 
1142
}
 
 
1143
 
 
 
1144
void HierarchicalFragmentBehaviour(STRATEGYBLOCK *sptr)
 
 
1145
{
 
 
1146
    int bounce = 0;
 
 
1147
    assert(sptr);
 
 
1148
    HDEBRIS_BEHAV_BLOCK *hdbhv = (HDEBRIS_BEHAV_BLOCK * )sptr->dataptr;
 
 
1149
     DYNAMICSBLOCK *dynPtr = sptr->DynPtr;
 
 
1150
    assert(dynPtr);
 
 
1151
    COLLISIONREPORT *reportptr = dynPtr->CollisionReportPtr;
 
 
1152
 
 
 
1153
    if (hdbhv->counter < 0)
 
 
1154
    {            
 
 
1155
        sptr->please_destroy_me = 1;
 
 
1156
        return;            
 
 
1157
    }
 
 
1158
 
 
 
1159
    if (sptr->DisplayBlock)
 
 
1160
    {
 
 
1161
        sptr->DisplayBlock->SpecialFXFlags |= SFXFLAG_MELTINGINTOGROUND;
 
 
1162
        sptr->DisplayBlock->ObFlags2 = hdbhv->counter / 2;
 
 
1163
    }
 
 
1164
 
 
 
1165
    /* CDF 8/3/99 Added this on request... */
 
 
1166
    if (sptr->DamageBlock.IsOnFire || (hdbhv->counter < (HDEBRIS_LIFETIME - HDEBRIS_BLEEDING_TIME)))
 
 
1167
        hdbhv->HModelController.DisableBleeding = 1;
 
 
1168
 
 
 
1169
    hdbhv->counter -= NormalFrameTime;
 
 
1170
 
 
 
1171
    if (reportptr == NULL)
 
 
1172
    {
 
 
1173
        hdbhv->bouncelastframe = 0;
 
 
1174
    }
 
 
1175
    else if(DynamicObjectIsMoving(dynPtr))
 
 
1176
    {
 
 
1177
        do
 
 
1178
        {
 
 
1179
            if (NULL == reportptr->ObstacleSBPtr)
 
 
1180
            {
 
 
1181
                bounce = 1;
 
 
1182
 
 
 
1183
                if(-1 != reportptr->ModuleIndex)
 
 
1184
                {
 
 
1185
                    if (hdbhv->HModelController.Root_Section->flags & section_sprays_acid)
 
 
1186
                    {
 
 
1187
                        MakeDecal(DECAL_SCORCHED, &reportptr->ObstacleNormal, &reportptr->ObstaclePoint, reportptr->ModuleIndex);
 
 
1188
                    }
 
 
1189
                    else if (hdbhv->HModelController.Root_Section->flags & section_sprays_blood)
 
 
1190
                    {
 
 
1191
                    MakeDecal((hdbhv->Android ? DECAL_ANDROID_BLOOD_SPLASH : DECAL_HUMAN_BLOOD_SPLASH), &reportptr->ObstacleNormal,
&reportptr->ObstaclePoint, reportptr->ModuleIndex);
 
 
1192
                    }
 
 
1193
                    else if (hdbhv->HModelController.Root_Section->flags & section_sprays_predoblood)
 
 
1194
                    {
 
 
1195
                        MakeDecal(DECAL_PREDATOR_BLOOD_SPLASH, &reportptr->ObstacleNormal, &reportptr->ObstaclePoint, reportptr->ModuleIndex);
 
 
1196
                    }
 
 
1197
                }
 
 
1198
            }
 
 
1199
            else
 
 
1200
            {
 
 
1201
                if (hdbhv->HModelController.Root_Section->flags & section_sprays_acid)
 
 
1202
                {
 
 
1203
                    switch(reportptr->ObstacleSBPtr->type)
 
 
1204
                    {
 
 
1205
                        case I_BehaviourMarine:
 
 
1206
                        case I_BehaviourPredator:
 
 
1207
                        case I_BehaviourMarinePlayer:
 
 
1208
                        case I_BehaviourPredatorPlayer:
 
 
1209
                        case I_BehaviourAutoGun:
 
 
1210
                        case I_BehaviourInanimateObject:
 
 
1211
                        case I_BehaviourPlacedLight:
 
 
1212
                        case I_BehaviourVideoScreen:
 
 
1213
                        case I_BehaviourSpeargunBolt:
 
 
1214
                            CauseDamageToObject(reportptr->ObstacleSBPtr, &TemplateAmmo[AMMO_ALIEN_FRAG].MaxDamage, ONE_FIXED, NULL);
 
 
1215
                        break;
 
 
1216
                        /*
 
 
1217
                        case I_BehaviourRocket:
 
 
1218
                        case I_BehaviourFlare:
 
 
1219
                        case I_BehaviourPulseGrenade:
 
 
1220
                        case I_BehaviourGrenade:
 
 
1221
                        case I_BehaviourFragmentationGrenade:
 
 
1222
                        case I_BehaviourProximityGrenade:
 
 
1223
                            reportptr->ObstacleSBPtr->please_destroy_me = 1;
 
 
1224
                        */
 
 
1225
                        default:
 
 
1226
                        break;
 
 
1227
                    }
 
 
1228
                }
 
 
1229
            }
 
 
1230
 
 
 
1231
            reportptr = reportptr->NextCollisionReportPtr;
 
 
1232
 
 
 
1233
        } while (reportptr);
 
 
1234
    }
 
 
1235
 
 
 
1236
    if (bounce && !hdbhv->bouncelastframe)
 
 
1237
    {
 
 
1238
        if (hdbhv->Bounce_Sound != SID_NOSOUND)
 
 
1239
            Sound_Play(hdbhv->Bounce_Sound, "dp", &dynPtr->Position, ((FastRandom()&511)-255));
 
 
1240
 
 
 
1241
        hdbhv->bouncelastframe = 1;
 
 
1242
    }
 
 
1243
 
 
 
1244
    if (dynPtr->IsInContactWithFloor)
 
 
1245
        dynPtr->AngVelocity.EulerX = dynPtr->AngVelocity.EulerY = dynPtr->AngVelocity.EulerZ = 0;
 
 
1246
    else
 
 
1247
        DynamicallyRotateObject(dynPtr);
 
 
1248
}
 
 
1249
 
 
 
1250
/*-------------------------------**
 
 
1251
** Load/Save hierarchical debris **
 
 
1252
**-------------------------------*/
 
 
1253
 
 
 
1254
typedef struct hier_debris_save_block
 
 
1255
{
 
 
1256
    SAVE_BLOCK_STRATEGY_HEADER header;
 
 
1257
 
 
 
1258
//behaviour block stuff
 
 
1259
    int counter;
 
 
1260
    int smokes;
 
 
1261
    int GibbFactor;
 
 
1262
    int Android;
 
 
1263
 
 
 
1264
    AVP_BEHAVIOUR_TYPE Type;
 
 
1265
    int SubType;
 
 
1266
 
 
 
1267
    int bouncelastframe;
 
 
1268
    enum soundindex Bounce_Sound;
 
 
1269
 
 
 
1270
//strategy block stuff
 
 
1271
    DAMAGEBLOCK DamageBlock;
 
 
1272
    DYNAMICSBLOCK dynamics;
 
 
1273
 
 
 
1274
} HIER_DEBRIS_SAVE_BLOCK;
 
 
1275
 
 
 
1276
//defines for load/save macros
 
 
1277
#define SAVELOAD_BLOCK block
 
 
1278
#define SAVELOAD_BEHAV hdebrisStatusPointer
 
 
1279
 
 
 
1280
void LoadStrategy_HierarchicalDebris(SAVE_BLOCK_STRATEGY_HEADER* header)
 
 
1281
{
 
 
1282
    HIER_DEBRIS_SAVE_BLOCK* block = (HIER_DEBRIS_SAVE_BLOCK*) header;
 
 
1283
 
 
 
1284
    //check the size of the save block
 
 
1285
    if(header->size != sizeof(*block))
 
 
1286
        return;
 
 
1287
 
 
 
1288
    //We need to create the debris then.
 
 
1289
 
 
 
1290
    STRATEGYBLOCK* sbPtr = CreateActiveStrategyBlock(I_BehaviourHierarchicalFragment);
 
 
1291
 
 
 
1292
    if(NULL == sbPtr)
 
 
1293
        return;
 
 
1294
 
 
 
1295
    DISPLAYBLOCK* dispPtr = sbPtr->DisplayBlock = AllocateNewObject(GetLoadedShapeMSL("Shell"));
 
 
1296
    sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_STATIC);
 
 
1297
    sbPtr->dataptr = malloc(sizeof(HDEBRIS_BEHAV_BLOCK));
 
 
1298
 
 
 
1299
    if((NULL == dispPtr) || (NULL == sbPtr->DynPtr) || (NULL == sbPtr->dataptr))
 
 
1300
    {
 
 
1301
        RemoveBehaviourStrategy(sbPtr);
 
 
1302
        return;
 
 
1303
    }
 
 
1304
 
 
 
1305
    sbPtr->DynPtr->Mass = 10;
 
 
1306
    sbPtr->DynPtr->IsStatic = 0;
 
 
1307
    sbPtr->DynPtr->IgnoreSameObjectsAsYou = 1;
 
 
1308
 
 
 
1309
    dispPtr->ObStrategyBlock = sbPtr;
 
 
1310
 
 
 
1311
    HDEBRIS_BEHAV_BLOCK* hdebrisStatusPointer = (HDEBRIS_BEHAV_BLOCK *)sbPtr->dataptr;
 
 
1312
 
 
 
1313
    hdebrisStatusPointer->HModelController.Deltas = NULL;
 
 
1314
    hdebrisStatusPointer->HModelController.Root_Section = NULL;
 
 
1315
    hdebrisStatusPointer->HModelController.section_data = NULL;
 
 
1316
 
 
 
1317
    dispPtr->HModelControlBlock = &hdebrisStatusPointer->HModelController;
 
 
1318
 
 
 
1319
    COPYELEMENT_LOAD(counter)
 
 
1320
    COPYELEMENT_LOAD(smokes)
 
 
1321
    COPYELEMENT_LOAD(GibbFactor)
 
 
1322
    COPYELEMENT_LOAD(Android)
 
 
1323
    COPYELEMENT_LOAD(Type)
 
 
1324
    COPYELEMENT_LOAD(SubType)
 
 
1325
    COPYELEMENT_LOAD(bouncelastframe)
 
 
1326
    COPYELEMENT_LOAD(Bounce_Sound)
 
 
1327
 
 
 
1328
    *sbPtr->DynPtr = block->dynamics;
 
 
1329
    sbPtr->DamageBlock = block->DamageBlock;
 
 
1330
 
 
 
1331
    {
 
 
1332
        SAVE_BLOCK_HEADER* hier_header = GetNextBlockIfOfType(SaveBlock_Hierarchy);
 
 
1333
 
 
 
1334
        if(hier_header)
 
 
1335
            LoadHierarchy(hier_header, &hdebrisStatusPointer->HModelController);
 
 
1336
    }
 
 
1337
}
 
 
1338
 
 
 
1339
void SaveStrategy_HierarchicalDebris(STRATEGYBLOCK* sbPtr)
 
 
1340
{
 
 
1341
    HDEBRIS_BEHAV_BLOCK* hdebrisStatusPointer;
 
 
1342
    HIER_DEBRIS_SAVE_BLOCK* block;
 
 
1343
 
 
 
1344
    GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
 
 
1345
    hdebrisStatusPointer = (HDEBRIS_BEHAV_BLOCK*) sbPtr->dataptr;
 
 
1346
 
 
 
1347
    //start copying stuff
 
 
1348
 
 
 
1349
    COPYELEMENT_SAVE(counter)
 
 
1350
    COPYELEMENT_SAVE(smokes)
 
 
1351
    COPYELEMENT_SAVE(GibbFactor)
 
 
1352
    COPYELEMENT_SAVE(Android)
 
 
1353
    COPYELEMENT_SAVE(Type)
 
 
1354
    COPYELEMENT_SAVE(SubType)
 
 
1355
    COPYELEMENT_SAVE(bouncelastframe)
 
 
1356
    COPYELEMENT_SAVE(Bounce_Sound)
 
 
1357
 
 
 
1358
    //save strategy block stuff
 
 
1359
    block->dynamics = *sbPtr->DynPtr;
 
 
1360
    block->dynamics.CollisionReportPtr = 0;
 
 
1361
    block->DamageBlock = sbPtr->DamageBlock;
 
 
1362
 
 
 
1363
    SaveHierarchy(&hdebrisStatusPointer->HModelController);
 
 
1364
}
 
 
1365
 
 
 
1366
/*------------------**
 
 
1367
** Load/Save Debris **
 
 
1368
**------------------*/
 
 
1369
 
 
 
1370
typedef struct debris_save_block
 
 
1371
{
 
 
1372
    SAVE_BLOCK_STRATEGY_HEADER header;
 
 
1373
 
 
 
1374
    int counter;
 
 
1375
    int dynamicModuleObject;
 
 
1376
    int shapeIndex;
 
 
1377
    int shapeNumPoints;
 
 
1378
    int shapeNumItems;
 
 
1379
    int shapeRadius;
 
 
1380
 
 
 
1381
//strategy block stuff
 
 
1382
    DAMAGEBLOCK DamageBlock;
 
 
1383
    DYNAMICSBLOCK dynamics;
 
 
1384
 
 
 
1385
} DEBRIS_SAVE_BLOCK;
 
 
1386
 
 
 
1387
STRATEGYBLOCK*  MakeDebrisForLoad(int shapeIndex,int counter, int dynamicModuleObject)
 
 
1388
{
 
 
1389
    if( (NumActiveBlocks > maxobjects - 5) || (NumActiveStBlocks > maxstblocks - 5))
 
 
1390
        return NULL;
 
 
1391
 
 
 
1392
    STRATEGYBLOCK* sbPtr = CreateActiveStrategyBlock(I_BehaviourFragment);
 
 
1393
 
 
 
1394
    if (sbPtr)
 
 
1395
    {
 
 
1396
        DISPLAYBLOCK *dispPtr = sbPtr->DisplayBlock = AllocateNewObject(shapeIndex); 
 
 
1397
        DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_STATIC);
 
 
1398
        sbPtr->dataptr = malloc(sizeof(ONE_SHOT_BEHAV_BLOCK ));
 
 
1399
        sbPtr->shapeIndex = shapeIndex;
 
 
1400
 
 
 
1401
        if ((sbPtr->dataptr == NULL) || (NULL ==  dynPtr) || (NULL == dispPtr))
 
 
1402
        {
 
 
1403
            RemoveBehaviourStrategy(sbPtr);
 
 
1404
            return NULL;
 
 
1405
        }
 
 
1406
 
 
 
1407
        dispPtr->ObStrategyBlock = sbPtr;
 
 
1408
        dynPtr->Mass = 10;
 
 
1409
        dynPtr->IsStatic = 0;
 
 
1410
        dynPtr->IgnoreSameObjectsAsYou = 1;
 
 
1411
 
 
 
1412
        ((ONE_SHOT_BEHAV_BLOCK * ) sbPtr->dataptr)->counter = counter;
 
 
1413
 
 
 
1414
        if(dynamicModuleObject)
 
 
1415
            dispPtr->ObFlags3 |= ObFlag3_DynamicModuleObject;
 
 
1416
 
 
 
1417
        return sbPtr;
 
 
1418
    }
 
 
1419
 
 
 
1420
return NULL;
 
 
1421
}
 
 
1422
 
 
 
1423
void LoadStrategy_Debris(SAVE_BLOCK_HEADER* header)
 
 
1424
{
 
 
1425
    STRATEGYBLOCK* sbPtr;
 
 
1426
    DEBRIS_SAVE_BLOCK* block = (DEBRIS_SAVE_BLOCK*)header;
 
 
1427
 
 
 
1428
    if(block->header.size == sizeof(*block))
 
 
1429
    {
 
 
1430
        struct shapeheader* shp = GetShapeData(block->shapeIndex);
 
 
1431
 
 
 
1432
        //check that the shape at shapeIndex is correct
 
 
1433
        if(!shp
 
 
1434
        || (shp->numitems != block->shapeNumItems)
 
 
1435
        || (shp->numpoints != block->shapeNumPoints)
 
 
1436
        || (shp->shaperadius != block->shapeRadius) )
 
 
1437
            return;
 
 
1438
 
 
 
1439
        sbPtr = MakeDebrisForLoad(block->shapeIndex, block->counter, block->dynamicModuleObject);
 
 
1440
 
 
 
1441
        if(!sbPtr)
 
 
1442
        {
 
 
1443
            *sbPtr->DynPtr = block->dynamics;
 
 
1444
            sbPtr->DamageBlock = block->DamageBlock;
 
 
1445
        }
 
 
1446
    }
 
 
1447
}
 
 
1448
 
 
 
1449
void SaveStrategy_Debris(STRATEGYBLOCK* sbPtr)
 
 
1450
{
 
 
1451
    DEBRIS_SAVE_BLOCK* block;
 
 
1452
    ONE_SHOT_BEHAV_BLOCK* behav = (ONE_SHOT_BEHAV_BLOCK*)sbPtr->dataptr;
 
 
1453
 
 
 
1454
    if(!sbPtr->DisplayBlock || !sbPtr->DisplayBlock->ShapeData)
 
 
1455
        return;
 
 
1456
 
 
 
1457
    struct shapeheader* shp = sbPtr->DisplayBlock->ShapeData;
 
 
1458
 
 
 
1459
    GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
 
 
1460
 
 
 
1461
    block->counter = behav->counter;
 
 
1462
    block->shapeIndex = sbPtr->DisplayBlock->ObShape;
 
 
1463
    block->dynamicModuleObject = (sbPtr->DisplayBlock->ObFlags3 & ObFlag3_DynamicModuleObject);
 
 
1464
 
 
 
1465
    block->shapeNumPoints = shp->numpoints;
 
 
1466
    block->shapeNumItems  = shp->numitems;
 
 
1467
    block->shapeRadius = shp->shaperadius;
 
 
1468
 
 
 
1469
//strategy block stuff
 
 
1470
    block->dynamics = *sbPtr->DynPtr;
 
 
1471
    block->dynamics.CollisionReportPtr = NULL;
 
 
1472
    block->DamageBlock = sbPtr->DamageBlock;
 
 
1473
}