4b825dc642cb6eb9a060e54bf8d69288fbee4904ebd360ec63ec976c05699f3180e866b3f69e5472
 
 
1
#include "npc_common.h"
 
 
2
#include "npc_xenoborg.h"
 
 
3
#include "particle.h"
 
 
4
#include "net.h"
 
 
5
#include <string.h>
 
 
6
 
 
 
7
extern void SetSeededFastRandom(int seed);
 
 
8
 
 
 
9
CORPSEDATABLOCK* make_new_corpse(AVP_BEHAVIOUR_TYPE type)
 
 
10
{
 
 
11
    CORPSEDATABLOCK *new_corpse = malloc(sizeof(CORPSEDATABLOCK));
 
 
12
 
 
 
13
    if (NULL != new_corpse)
 
 
14
    {
 
 
15
        new_corpse->timer = 0;
 
 
16
        new_corpse->validityTimer = 0;
 
 
17
        new_corpse->SoundHandle = SOUND_NOACTIVEINDEX;
 
 
18
        new_corpse->SoundHandle2 = SOUND_NOACTIVEINDEX;
 
 
19
        new_corpse->SoundHandle3 = SOUND_NOACTIVEINDEX;
 
 
20
        new_corpse->SoundHandle4 = SOUND_NOACTIVEINDEX;
 
 
21
        new_corpse->HModelController.Deltas = NULL;
 
 
22
        new_corpse->HModelController.Root_Section = NULL;
 
 
23
        new_corpse->HModelController.section_data = NULL;
 
 
24
        new_corpse->Type = type;
 
 
25
        new_corpse->hltable = NULL;
 
 
26
        new_corpse->This_Death = NULL;
 
 
27
        new_corpse->CloakStatus = PCLOAK_Off;
 
 
28
        new_corpse->CloakTimer = 0;
 
 
29
        new_corpse->My_Gunflash_Section = NULL;
 
 
30
        new_corpse->TemplateRoot = NULL;
 
 
31
        new_corpse->My_Weapon = NULL;
 
 
32
        new_corpse->weapon_variable = 0;
 
 
33
        new_corpse->subtype = 0;
 
 
34
        new_corpse->Wounds = 0;
 
 
35
        new_corpse->DeathFiring = 0;
 
 
36
        new_corpse->SelfDestructTimer = 0;
 
 
37
        new_corpse->BurstTimer = 0;
 
 
38
        new_corpse->clipammo= 0;
 
 
39
        new_corpse->volleySize = 0;
 
 
40
        new_corpse->myGunFlash = NULL;
 
 
41
    }
 
 
42
 
 
 
43
    return new_corpse;
 
 
44
}
 
 
45
 
 
 
46
/* these functions are called directly by the visibility management system */
 
 
47
void MakeCorpseNear(STRATEGYBLOCK *sbPtr)
 
 
48
{
 
 
49
    CORPSEDATABLOCK *corpseData = (CORPSEDATABLOCK *)sbPtr->dataptr;
 
 
50
    assert(corpseData);
 
 
51
 
 
 
52
    DISPLAYBLOCK *dPtr = CreateActiveObject();
 
 
53
 
 
 
54
    if(dPtr)
 
 
55
    {
 
 
56
        dPtr->ObShape = sbPtr->shapeIndex;
 
 
57
        dPtr->ShapeData = mainshapelist[sbPtr->shapeIndex];
 
 
58
        sbPtr->DisplayBlock = dPtr;
 
 
59
        dPtr->ObStrategyBlock = sbPtr;
 
 
60
 
 
 
61
        /* need to initialise positional information in the new display block */ 
 
 
62
        /*Must be done before ProveHModel*/
 
 
63
        dPtr->ObWorld = sbPtr->DynPtr->Position;
 
 
64
        dPtr->ObEuler = sbPtr->DynPtr->OrientEuler;
 
 
65
        dPtr->ObMat = sbPtr->DynPtr->OrientMat;
 
 
66
 
 
 
67
         /* set the animation sequence, if we're a player corpse */
 
 
68
        /* Okay, no messing, you MUST be a player corpse. */
 
 
69
        dPtr->HModelControlBlock = &corpseData->HModelController;
 
 
70
        ProveHModel(dPtr->HModelControlBlock,dPtr);
 
 
71
    }
 
 
72
}
 
 
73
 
 
 
74
void SetCorpseAnimSequence_Core(STRATEGYBLOCK *sbPtr,HMODEL_SEQUENCE_TYPES type, int subtype, int length, int tweeningtime)
 
 
75
{
 
 
76
    CORPSEDATABLOCK *corpseStatus = (CORPSEDATABLOCK *)(sbPtr->dataptr);
 
 
77
 
 
 
78
    assert(length != 0);
 
 
79
 
 
 
80
    if (tweeningtime <= 0)
 
 
81
        InitHModelSequence(&corpseStatus->HModelController,(int)type,subtype,length);
 
 
82
    else
 
 
83
        InitHModelTweening(&corpseStatus->HModelController, tweeningtime, (int)type,subtype,length,0);
 
 
84
 
 
 
85
    corpseStatus->HModelController.Playing = 1;
 
 
86
    /* Might be unset... */
 
 
87
}
 
 
88
 
 
 
89
void Convert_Alien_To_Corpse(STRATEGYBLOCK *sbPtr, DEATH_DATA *this_death, const DAMAGE_PROFILE* damage)
 
 
90
{
 
 
91
    ALIEN_STATUS_BLOCK *alienStatusPointer = (ALIEN_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
92
    CORPSEDATABLOCK *corpseDataPtr = make_new_corpse(I_BehaviourAlien);
 
 
93
 
 
 
94
    assert(this_death);
 
 
95
 
 
 
96
    if(NULL == corpseDataPtr)
 
 
97
    {
 
 
98
        RemoveBehaviourStrategy(sbPtr);
 
 
99
        return;
 
 
100
    }
 
 
101
 
 
 
102
    corpseDataPtr->This_Death = this_death;
 
 
103
 
 
 
104
    switch (alienStatusPointer->Type)
 
 
105
    {
 
 
106
        case Standard:
 
 
107
        default:
 
 
108
            corpseDataPtr->hltable = GetThisHitLocationTable("alien");
 
 
109
        break;
 
 
110
        case Predalien:
 
 
111
            corpseDataPtr->subtype = 1;
 
 
112
            corpseDataPtr->hltable = GetThisHitLocationTable("predalien");
 
 
113
        break;
 
 
114
        case Praetorian:
 
 
115
            corpseDataPtr->subtype = 2;
 
 
116
            corpseDataPtr->hltable = GetThisHitLocationTable("praetorian");
 
 
117
    }
 
 
118
 
 
 
119
    /* Remember wounds, or not? */
 
 
120
    Splice_HModels(&corpseDataPtr->HModelController, alienStatusPointer->HModelController.section_data);
 
 
121
 
 
 
122
    /* Heh... now bin the old data block! */
 
 
123
    if(alienStatusPointer->soundOnFire != SOUND_NOACTIVEINDEX)
 
 
124
        Sound_Stop(alienStatusPointer->soundOnFire);
 
 
125
 
 
 
126
    if(alienStatusPointer->sound_mouth != SOUND_NOACTIVEINDEX)
 
 
127
        Sound_Stop(alienStatusPointer->sound_mouth);
 
 
128
 
 
 
129
    Dispel_HModel(&alienStatusPointer->HModelController);
 
 
130
    free(sbPtr->dataptr);
 
 
131
    /* Turn into the corpse. */
 
 
132
    sbPtr->dataptr = corpseDataPtr;
 
 
133
    sbPtr->type = I_BehaviourCorpse;
 
 
134
 
 
 
135
    SetCorpseAnimSequence_Core(sbPtr, this_death->Sequence_Type, this_death->Sub_Sequence, this_death->Sequence_Length, this_death->TweeningTime);
 
 
136
 
 
 
137
    if (sbPtr->DisplayBlock)
 
 
138
    {
 
 
139
        /* Swap controllers round. */
 
 
140
        sbPtr->DisplayBlock->HModelControlBlock = &corpseDataPtr->HModelController;
 
 
141
        ProveHModel(&corpseDataPtr->HModelController, sbPtr->DisplayBlock);
 
 
142
    }
 
 
143
    else
 
 
144
    {
 
 
145
        ProveHModel_Far(&corpseDataPtr->HModelController, sbPtr);
 
 
146
    }
 
 
147
 
 
 
148
    corpseDataPtr->timer = ALIEN_DYINGTIME;
 
 
149
    corpseDataPtr->validityTimer = CORPSE_VALIDITY_TIME;
 
 
150
    corpseDataPtr->HModelController.Looped = 0;
 
 
151
    corpseDataPtr->HModelController.LoopAfterTweening = 0;
 
 
152
 
 
 
153
    /* stop motion */
 
 
154
    sbPtr->DynPtr->LinImpulse.vx += sbPtr->DynPtr->LinVelocity.vx;
 
 
155
    sbPtr->DynPtr->LinImpulse.vy += sbPtr->DynPtr->LinVelocity.vy;
 
 
156
    sbPtr->DynPtr->LinImpulse.vz += sbPtr->DynPtr->LinVelocity.vz;
 
 
157
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
158
    sbPtr->DynPtr->CanClimbStairs = 0;
 
 
159
    sbPtr->DynPtr->UseStandardGravity = 1;
 
 
160
 
 
 
161
    /* KJL 17:19:35 27/08/98 - ignore the player, other body parts, etc */
 
 
162
    sbPtr->DynPtr->OnlyCollideWithEnvironment = 1;
 
 
163
 
 
 
164
    /* Electric death sound? */
 
 
165
    if (corpseDataPtr->This_Death->Electrical)
 
 
166
        Sound_Play(SID_ELEC_DEATH, "de", &sbPtr->DynPtr->Position, &corpseDataPtr->SoundHandle4);
 
 
167
}
 
 
168
 
 
 
169
void Convert_Predator_To_Corpse(STRATEGYBLOCK *sbPtr, DEATH_DATA *this_death)
 
 
170
{
 
 
171
    PREDATOR_STATUS_BLOCK *predatorStatusPointer = (PREDATOR_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
172
    CORPSEDATABLOCK *corpseDataPtr = make_new_corpse(I_BehaviourPredator);
 
 
173
 
 
 
174
    if(NULL == corpseDataPtr)
 
 
175
    {
 
 
176
        RemoveBehaviourStrategy(sbPtr);
 
 
177
        return;
 
 
178
    }
 
 
179
 
 
 
180
    if (PBS_SelfDestruct == predatorStatusPointer->behaviourState)
 
 
181
    {
 
 
182
        if (1 == predatorStatusPointer->internalState)
 
 
183
            corpseDataPtr->SelfDestructTimer = predatorStatusPointer->stateTimer;
 
 
184
    }
 
 
185
 
 
 
186
    corpseDataPtr->This_Death = this_death;
 
 
187
    corpseDataPtr->CloakStatus = predatorStatusPointer->CloakStatus;
 
 
188
    corpseDataPtr->CloakTimer  = predatorStatusPointer->CloakTimer;
 
 
189
 
 
 
190
    corpseDataPtr->hltable = GetThisHitLocationTable(predatorStatusPointer->Selected_Weapon->HitLocationTableName);
 
 
191
 
 
 
192
    /* Remember wounds, or not? */
 
 
193
    Splice_HModels(&corpseDataPtr->HModelController, predatorStatusPointer->HModelController.section_data);
 
 
194
 
 
 
195
    if (this_death->Template)
 
 
196
    {
 
 
197
        /* Convert to template. */
 
 
198
        SECTION *root = GetNamedHierarchyFromLibrary("hnpcpredator", "Template");
 
 
199
        Transmogrify_HModels(sbPtr, &corpseDataPtr->HModelController, root, 1, 0, 0);
 
 
200
    }
 
 
201
 
 
 
202
    /* Heh... now bin the old data block! */
 
 
203
    if(predatorStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
204
        Sound_Stop(predatorStatusPointer->soundHandle);
 
 
205
 
 
 
206
    Dispel_HModel(&predatorStatusPointer->HModelController);
 
 
207
    free(sbPtr->dataptr);
 
 
208
    /* Turn into the corpse. */
 
 
209
    sbPtr->dataptr = corpseDataPtr;
 
 
210
    sbPtr->type = I_BehaviourCorpse;
 
 
211
 
 
 
212
     SetCorpseAnimSequence_Core(sbPtr, this_death->Sequence_Type, this_death->Sub_Sequence, this_death->Sequence_Length, this_death->TweeningTime);
 
 
213
 
 
 
214
    if (sbPtr->DisplayBlock)
 
 
215
    {
 
 
216
        /* Swap controllers round. */
 
 
217
        sbPtr->DisplayBlock->HModelControlBlock = &corpseDataPtr->HModelController;
 
 
218
        ProveHModel(&corpseDataPtr->HModelController, sbPtr->DisplayBlock);
 
 
219
    }
 
 
220
    else
 
 
221
    {
 
 
222
        ProveHModel_Far(&corpseDataPtr->HModelController, sbPtr);
 
 
223
    }
 
 
224
 
 
 
225
    corpseDataPtr->timer = PRED_DIETIME;
 
 
226
    corpseDataPtr->validityTimer = CORPSE_VALIDITY_TIME;
 
 
227
    corpseDataPtr->HModelController.Looped = 0;
 
 
228
    corpseDataPtr->HModelController.LoopAfterTweening = 0;
 
 
229
 
 
 
230
    /* stop motion */
 
 
231
    sbPtr->DynPtr->LinImpulse.vx += sbPtr->DynPtr->LinVelocity.vx;
 
 
232
    sbPtr->DynPtr->LinImpulse.vy += sbPtr->DynPtr->LinVelocity.vy;
 
 
233
    sbPtr->DynPtr->LinImpulse.vz += sbPtr->DynPtr->LinVelocity.vz;
 
 
234
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
235
    sbPtr->DynPtr->CanClimbStairs = 0;
 
 
236
 
 
 
237
    /* KJL 17:19:35 27/08/98 - ignore the player, other body parts, etc */
 
 
238
    sbPtr->DynPtr->OnlyCollideWithEnvironment = 1;
 
 
239
    /* Electric death sound? */
 
 
240
 
 
 
241
    if (corpseDataPtr->This_Death->Electrical)
 
 
242
        Sound_Play(SID_ELEC_DEATH, "de", &sbPtr->DynPtr->Position, &corpseDataPtr->SoundHandle4);
 
 
243
}
 
 
244
 
 
 
245
void Convert_Marine_To_Corpse(STRATEGYBLOCK *sbPtr, DEATH_DATA *this_death)
 
 
246
{
 
 
247
    MARINE_STATUS_BLOCK *marineStatusPointer = (MARINE_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
248
    CORPSEDATABLOCK *corpseDataPtr = make_new_corpse(I_BehaviourMarine);
 
 
249
 
 
 
250
    if(NULL == corpseDataPtr)
 
 
251
    {
 
 
252
        RemoveBehaviourStrategy(sbPtr);
 
 
253
        return;
 
 
254
    }
 
 
255
 
 
 
256
    corpseDataPtr->This_Death = this_death;
 
 
257
    corpseDataPtr->My_Weapon = marineStatusPointer->My_Weapon;
 
 
258
    corpseDataPtr->My_Gunflash_Section = marineStatusPointer->My_Gunflash_Section;
 
 
259
    corpseDataPtr->TemplateRoot = GetNamedHierarchyFromLibrary(marineStatusPointer->My_Weapon->Riffname,
marineStatusPointer->My_Weapon->TemplateName);
 
 
260
    corpseDataPtr->BurstTimer = marineStatusPointer->BurstTimer;
 
 
261
    corpseDataPtr->clipammo = marineStatusPointer->clipammo;
 
 
262
    corpseDataPtr->volleySize = marineStatusPointer->volleySize;
 
 
263
 
 
 
264
    switch(corpseDataPtr->My_Weapon->id)
 
 
265
    {
 
 
266
        case MNPCW_Flamethrower:
 
 
267
        case MNPCW_CivilianFlamer:
 
 
268
            if(marineStatusPointer->IAmFiring)
 
 
269
                corpseDataPtr->DeathFiring = ((FastRandom() & 65535) > 21846);
 
 
270
        break;
 
 
271
        default:
 
 
272
            corpseDataPtr->DeathFiring = (marineStatusPointer->volleySize < marineStatusPointer->My_Weapon->MinimumBurstSize);
 
 
273
    }
 
 
274
 
 
 
275
    if(marineStatusPointer->Android)
 
 
276
        corpseDataPtr->subtype = -1;
 
 
277
    else if(marineStatusPointer->My_Weapon->ARealMarine)
 
 
278
        corpseDataPtr->subtype = 1;
 
 
279
 
 
 
280
    corpseDataPtr->hltable = GetThisHitLocationTable(marineStatusPointer->My_Weapon->HitLocationTableName);            
 
 
281
 
 
 
282
    /* Remember wounds, or not? */
 
 
283
    Splice_HModels(&corpseDataPtr->HModelController, marineStatusPointer->HModelController.section_data);
 
 
284
 
 
 
285
    /* Convert to template. */
 
 
286
    if (this_death->Template)
 
 
287
        Transmogrify_HModels(sbPtr, &corpseDataPtr->HModelController, corpseDataPtr->TemplateRoot, 1, 0, 0);
 
 
288
 
 
 
289
    /* Pass over some sounds? */
 
 
290
 
 
 
291
    /* Heh... now bin the old data block! */
 
 
292
    if(marineStatusPointer->soundHandle != SOUND_NOACTIVEINDEX)
 
 
293
        Sound_Stop(marineStatusPointer->soundHandle);
 
 
294
 
 
 
295
    if(marineStatusPointer->sound_mouth != SOUND_NOACTIVEINDEX)
 
 
296
    {
 
 
297
        /* soundHandle2 is the voice! */
 
 
298
        corpseDataPtr->SoundHandle2 = marineStatusPointer->sound_mouth;
 
 
299
        ActiveSounds[marineStatusPointer->sound_mouth].externalRef = &corpseDataPtr->SoundHandle2;
 
 
300
    }
 
 
301
 
 
 
302
    Dispel_HModel(&marineStatusPointer->HModelController);
 
 
303
    free(sbPtr->dataptr);
 
 
304
    /* Turn into the corpse. */
 
 
305
    sbPtr->dataptr = corpseDataPtr;
 
 
306
    sbPtr->type = I_BehaviourCorpse;
 
 
307
 
 
 
308
     SetCorpseAnimSequence_Core(sbPtr, this_death->Sequence_Type, this_death->Sub_Sequence, this_death->Sequence_Length, this_death->TweeningTime);
 
 
309
 
 
 
310
    if (sbPtr->DisplayBlock)
 
 
311
    {
 
 
312
        /* Swap controllers round. */
 
 
313
        sbPtr->DisplayBlock->HModelControlBlock = &corpseDataPtr->HModelController;
 
 
314
        ProveHModel(&corpseDataPtr->HModelController, sbPtr->DisplayBlock);
 
 
315
    }
 
 
316
    else
 
 
317
    {
 
 
318
        ProveHModel_Far(&corpseDataPtr->HModelController, sbPtr);
 
 
319
    }
 
 
320
 
 
 
321
    corpseDataPtr->timer = MARINE_DYINGTIME;
 
 
322
    corpseDataPtr->validityTimer = CORPSE_VALIDITY_TIME;
 
 
323
    corpseDataPtr->HModelController.Looped = 0;
 
 
324
    corpseDataPtr->HModelController.LoopAfterTweening = 0;
 
 
325
 
 
 
326
    /* stop motion */
 
 
327
    sbPtr->DynPtr->LinImpulse.vx += sbPtr->DynPtr->LinVelocity.vx;
 
 
328
    sbPtr->DynPtr->LinImpulse.vy += sbPtr->DynPtr->LinVelocity.vy;
 
 
329
    sbPtr->DynPtr->LinImpulse.vz += sbPtr->DynPtr->LinVelocity.vz;
 
 
330
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
331
    sbPtr->DynPtr->CanClimbStairs = 0;
 
 
332
 
 
 
333
    /* KJL 17:19:35 27/08/98 - ignore the player, other body parts, etc */
 
 
334
    //sbPtr->DynPtr->OnlyCollideWithEnvironment = 1;
 
 
335
 
 
 
336
    /* Electric death sound? */
 
 
337
    if (corpseDataPtr->This_Death->Electrical)
 
 
338
        Sound_Play(SID_ELEC_DEATH, "de", &sbPtr->DynPtr->Position, &corpseDataPtr->SoundHandle4);
 
 
339
}
 
 
340
 
 
 
341
void Convert_Xenoborg_To_Corpse(STRATEGYBLOCK *sbPtr,DEATH_DATA *this_death)
 
 
342
{
 
 
343
    XENO_STATUS_BLOCK *xenoStatusPointer = (XENO_STATUS_BLOCK *)(sbPtr->dataptr);    
 
 
344
    CORPSEDATABLOCK *corpseDataPtr = make_new_corpse(I_BehaviourXenoborg);
 
 
345
 
 
 
346
    if(NULL == corpseDataPtr)
 
 
347
    {
 
 
348
        RemoveBehaviourStrategy(sbPtr);
 
 
349
        return;
 
 
350
    }
 
 
351
 
 
 
352
    corpseDataPtr->This_Death = this_death;
 
 
353
    corpseDataPtr->hltable = GetThisHitLocationTable("xenoborg");
 
 
354
 
 
 
355
    /* Remember wounds, or not? */
 
 
356
    Splice_HModels(&corpseDataPtr->HModelController, xenoStatusPointer->HModelController.section_data);
 
 
357
 
 
 
358
    /* Heh... now bin the old data block! */
 
 
359
    Dispel_HModel(&xenoStatusPointer->HModelController);
 
 
360
    free(sbPtr->dataptr);
 
 
361
    /* Turn into the corpse. */
 
 
362
    sbPtr->dataptr = corpseDataPtr;
 
 
363
    sbPtr->type = I_BehaviourCorpse;
 
 
364
 
 
 
365
     SetCorpseAnimSequence_Core(sbPtr, this_death->Sequence_Type, this_death->Sub_Sequence, this_death->Sequence_Length, this_death->TweeningTime);
 
 
366
 
 
 
367
    if (sbPtr->DisplayBlock)
 
 
368
    {
 
 
369
        /* Swap controllers round. */
 
 
370
        sbPtr->DisplayBlock->HModelControlBlock = &corpseDataPtr->HModelController;
 
 
371
        ProveHModel(&corpseDataPtr->HModelController, sbPtr->DisplayBlock);
 
 
372
    }
 
 
373
    else
 
 
374
    {
 
 
375
        ProveHModel_Far(&corpseDataPtr->HModelController, sbPtr);
 
 
376
    }
 
 
377
 
 
 
378
    corpseDataPtr->timer = XENO_DYINGTIME;
 
 
379
    corpseDataPtr->validityTimer = CORPSE_VALIDITY_TIME;
 
 
380
    corpseDataPtr->HModelController.Looped = 0;
 
 
381
    corpseDataPtr->HModelController.LoopAfterTweening = 0;
 
 
382
 
 
 
383
    /* stop motion */
 
 
384
    sbPtr->DynPtr->LinImpulse.vx += sbPtr->DynPtr->LinVelocity.vx;
 
 
385
    sbPtr->DynPtr->LinImpulse.vy += sbPtr->DynPtr->LinVelocity.vy;
 
 
386
    sbPtr->DynPtr->LinImpulse.vz += sbPtr->DynPtr->LinVelocity.vz;
 
 
387
    sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
 
 
388
    sbPtr->DynPtr->CanClimbStairs = 0;
 
 
389
    sbPtr->DynPtr->UseStandardGravity = 1;
 
 
390
 
 
 
391
    /* KJL 17:19:35 27/08/98 - ignore the player, other body parts, etc */
 
 
392
    sbPtr->DynPtr->OnlyCollideWithEnvironment = 1;
 
 
393
}
 
 
394
 
 
 
395
void CorpseBehaveFun(STRATEGYBLOCK *sbPtr)
 
 
396
{
 
 
397
    /* Just count down. */
 
 
398
    assert(sbPtr);
 
 
399
 
 
 
400
    CORPSEDATABLOCK *corpseDataPtr = (CORPSEDATABLOCK *)sbPtr->dataptr;
 
 
401
 
 
 
402
    if(corpseDataPtr->SelfDestructTimer)
 
 
403
    {
 
 
404
        corpseDataPtr->SelfDestructTimer -= NormalFrameTime;
 
 
405
 
 
 
406
        if (corpseDataPtr->SelfDestructTimer < 0)
 
 
407
        {
 
 
408
            corpseDataPtr->SelfDestructTimer = 0;
 
 
409
            MakeVolumetricExplosionAt(&sbPtr->DynPtr->Position, EXPLOSION_SADAR_BLAST);
 
 
410
            Sound_Play(SID_NICE_EXPLOSION, "d", &sbPtr->DynPtr->Position);
 
 
411
        }
 
 
412
    }
 
 
413
    else if (corpseDataPtr->timer > 0)
 
 
414
    {
 
 
415
        if (sbPtr->DisplayBlock)
 
 
416
        {
 
 
417
            sbPtr->DisplayBlock->SpecialFXFlags |= SFXFLAG_MELTINGINTOGROUND;
 
 
418
            sbPtr->DisplayBlock->ObFlags2 = corpseDataPtr->timer / 2;
 
 
419
        }
 
 
420
 
 
 
421
        /* Does the corpse that falls when not visible make no sound? */
 
 
422
        ProveHModel_Far(&corpseDataPtr->HModelController, sbPtr);
 
 
423
 
 
 
424
        corpseDataPtr->timer -= NormalFrameTime;
 
 
425
        corpseDataPtr->validityTimer -= NormalFrameTime;
 
 
426
 
 
 
427
        switch(corpseDataPtr->Type)
 
 
428
        {
 
 
429
            case I_BehaviourPredator:
 
 
430
            case I_BehaviourPredatorPlayer:
 
 
431
            {
 
 
432
                /* If we're a partially cloaked predator, continue to decloak. */
 
 
433
                switch(corpseDataPtr->CloakStatus)
 
 
434
                {
 
 
435
                    case PCLOAK_Deactivating:
 
 
436
                    case PCLOAK_Off:
 
 
437
                        /* Do nothing. */
 
 
438
                    break;
 
 
439
                    case PCLOAK_Activating:
 
 
440
                        /* Don't reset timer. */
 
 
441
                        corpseDataPtr->CloakStatus = PCLOAK_Deactivating;
 
 
442
                    break;
 
 
443
                    default:    
 
 
444
                    {
 
 
445
                        /* Cloak must be On. */
 
 
446
                        corpseDataPtr->CloakStatus = PCLOAK_Deactivating;        
 
 
447
                        corpseDataPtr->CloakTimer = 0; /* Was predStatus->PredShimmer. */
 
 
448
                    }
 
 
449
                }
 
 
450
 
 
 
451
                if (corpseDataPtr->CloakStatus == PCLOAK_Deactivating)
 
 
452
                {
 
 
453
                    corpseDataPtr->CloakTimer += NormalFrameTime;
 
 
454
 
 
 
455
                    if(corpseDataPtr->CloakTimer >= (ONE_FIXED))
 
 
456
                    {
 
 
457
                        corpseDataPtr->CloakTimer = 0;
 
 
458
                        corpseDataPtr->CloakStatus = PCLOAK_Off;
 
 
459
                    }
 
 
460
                }
 
 
461
            }
 
 
462
            break;
 
 
463
            case I_BehaviourMarine:
 
 
464
            {
 
 
465
                /* Did marine die with the trigger held down? */
 
 
466
                if (corpseDataPtr->DeathFiring && corpseDataPtr->My_Gunflash_Section)
 
 
467
                {
 
 
468
                    /* But is it still attached? */
 
 
469
                    if (corpseDataPtr->My_Gunflash_Section->my_controller == &corpseDataPtr->HModelController)
 
 
470
                    {
 
 
471
                        /* Keep firing! */
 
 
472
                        /* Shouldn't be doing this without knowing why. */
 
 
473
                        MarineDeathFiring(sbPtr);
 
 
474
                    }
 
 
475
                }
 
 
476
 
 
 
477
                MaintainCorpseGunFlash(sbPtr);
 
 
478
 
 
 
479
                /* Do we want to trim off the weapons? */
 
 
480
 
 
 
481
                if (corpseDataPtr->HModelController.keyframe_flags)
 
 
482
                {
 
 
483
                    assert(corpseDataPtr->TemplateRoot);
 
 
484
                    TrimToTemplate(sbPtr, &corpseDataPtr->HModelController, corpseDataPtr->TemplateRoot, 1);
 
 
485
                }
 
 
486
            } // no break
 
 
487
            case I_BehaviourMarinePlayer:
 
 
488
            {
 
 
489
                /* May get decapitated whilst screaming... */
 
 
490
                SECTION_DATA *head = GetThisSectionData(corpseDataPtr->HModelController.section_data, "head");
 
 
491
 
 
 
492
                /* Is it still attached? */
 
 
493
                if (head && !(head->flags & section_data_notreal))
 
 
494
                {
 
 
495
                    if(corpseDataPtr->SoundHandle2 != SOUND_NOACTIVEINDEX)
 
 
496
                        Sound_Stop(corpseDataPtr->SoundHandle2);
 
 
497
                }
 
 
498
            }
 
 
499
            break;
 
 
500
            case I_BehaviourXenoborg:
 
 
501
            {
 
 
502
                if (sbPtr->DisplayBlock)
 
 
503
                {
 
 
504
                    /* Particularly important for xenoborgs... optional for others? */
 
 
505
                    if (sbPtr->DisplayBlock->ObFlags2 < ONE_FIXED)
 
 
506
                        corpseDataPtr->HModelController.DisableBleeding = 1;
 
 
507
                }
 
 
508
            }
 
 
509
            default:
 
 
510
            break;
 
 
511
        }
 
 
512
 
 
 
513
        if(corpseDataPtr->SoundHandle4 != SOUND_NOACTIVEINDEX)
 
 
514
            Sound_Update3d(corpseDataPtr->SoundHandle4, &sbPtr->DynPtr->Position);
 
 
515
 
 
 
516
 
 
 
517
        if (sbPtr->DamageBlock.IsOnFire)
 
 
518
        {
 
 
519
            if(corpseDataPtr->SoundHandle3 != SOUND_NOACTIVEINDEX)
 
 
520
                Sound_Update3d(corpseDataPtr->SoundHandle3, &sbPtr->DynPtr->Position);
 
 
521
            else
 
 
522
                Sound_Play(SID_FIRE, "dle", &sbPtr->DynPtr->Position, &corpseDataPtr->SoundHandle3);
 
 
523
        }
 
 
524
        else if (corpseDataPtr->SoundHandle3 != SOUND_NOACTIVEINDEX)
 
 
525
        {
 
 
526
            Sound_Stop(corpseDataPtr->SoundHandle3);
 
 
527
        }
 
 
528
    }
 
 
529
    else
 
 
530
    {
 
 
531
        if(corpseDataPtr->SoundHandle  != SOUND_NOACTIVEINDEX) Sound_Stop(corpseDataPtr->SoundHandle);
 
 
532
        if(corpseDataPtr->SoundHandle2 != SOUND_NOACTIVEINDEX) Sound_Stop(corpseDataPtr->SoundHandle2);
 
 
533
        if(corpseDataPtr->SoundHandle3 != SOUND_NOACTIVEINDEX) Sound_Stop(corpseDataPtr->SoundHandle3);
 
 
534
        if(corpseDataPtr->SoundHandle4 != SOUND_NOACTIVEINDEX) Sound_Stop(corpseDataPtr->SoundHandle4);
 
 
535
 
 
 
536
        sbPtr->please_destroy_me = 1;
 
 
537
        AddNetMsg_LocalObjectDestroyed(sbPtr);
 
 
538
    }
 
 
539
}
 
 
540
 
 
 
541
void CorpseIsDamaged(STRATEGYBLOCK *sbPtr, const DAMAGE_PROFILE *damage, int wounds, VECTORCH *incoming)
 
 
542
{
 
 
543
    CORPSEDATABLOCK *corpseDataPtr = (CORPSEDATABLOCK *)sbPtr->dataptr;
 
 
544
    corpseDataPtr->Wounds |= wounds;
 
 
545
 
 
 
546
    if(damage->ExplosivePower)
 
 
547
    {
 
 
548
        Extreme_Gibbing(sbPtr, corpseDataPtr->HModelController.section_data, ONE_FIXED, incoming);
 
 
549
        sbPtr->please_destroy_me = 1;
 
 
550
    }
 
 
551
}