1 /* bh_corpse.c 19/8/98 */
2 #include "3dc.h"
3 
4 #include "inline.h"
5 #include "module.h"
6 
7 #include "stratdef.h"
8 #include "gamedef.h"
9 #include "bh_types.h"
10 #include "comp_shp.h"
11 #include "dynblock.h"
12 #include "dynamics.h"
13 #include "lighting.h"
14 
15 #include "pfarlocs.h"
16 #include "pvisible.h"
17 #include "pheromon.h"
18 #include "bh_gener.h"
19 #include "bh_far.h"
20 #include "bh_pred.h"
21 #include "bh_marin.h"
22 #include "bh_weap.h"
23 #include "bh_debri.h"
24 #include "bh_alien.h"
25 #include "bh_xeno.h"
26 #include "psnd.h"
27 #include "weapons.h"
28 #include "load_shp.h"
29 #include "particle.h"
30 #include "sfx.h"
31 #include "huddefs.h"
32 #include "pldghost.h"
33 #include "pldnet.h"
34 #include "psndplat.h"
35 #include "ai_sight.h"
36 #include "los.h"
37 #include "bh_corpse.h"
38 
39 #include "dxlog.h"
40 
41 #define UseLocalAssert Yes
42 #include "ourasert.h"
43 
44 #include "sequnces.h"
45 #include "showcmds.h"
46 #include "extents.h"
47 
48 extern int NormalFrameTime;
49 extern SECTION * GetNamedHierarchyFromLibrary(const char * rif_name, const char * hier_name);
50 extern HITLOCATIONTABLE *GetThisHitLocationTable(char *id);
51 extern MARINE_WEAPON_DATA *GetThisNPCMarineWeapon(MARINE_NPC_WEAPONS this_id);
52 
53 void SetCorpseAnimSequence_Core(STRATEGYBLOCK *sbPtr,HMODEL_SEQUENCE_TYPES type, int subtype, int length, int tweeningtime);
54 
55 /* these functions are called directly by the visibility management system */
MakeCorpseNear(STRATEGYBLOCK * sbPtr)56 void MakeCorpseNear(STRATEGYBLOCK *sbPtr)
57 {
58 	extern MODULEMAPBLOCK AlienDefaultMap;
59 	NETCORPSEDATABLOCK *corpseData = (NETCORPSEDATABLOCK *)sbPtr->SBdataptr;
60 	MODULE tempModule;
61 	DISPLAYBLOCK *dPtr;
62 	DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
63 
64 	LOCALASSERT(corpseData);
65     LOCALASSERT(dynPtr);
66 	LOCALASSERT(sbPtr->SBdptr == NULL);
67 
68 	AlienDefaultMap.MapShape = sbPtr->shapeIndex;
69 	tempModule.m_mapptr = &AlienDefaultMap;
70 	tempModule.m_sbptr = (STRATEGYBLOCK*)NULL;
71 	tempModule.m_numlights = 0;
72 	tempModule.m_lightarray = (struct lightblock *)0;
73 	tempModule.m_extraitemdata = (struct extraitemdata *)0;
74 	tempModule.m_dptr = NULL; /* this is important */
75 	AllocateModuleObject(&tempModule);
76 	dPtr = tempModule.m_dptr;
77 	if(dPtr==NULL) return; /* cannot create displayblock, so leave object "far" */
78 
79 	sbPtr->SBdptr = dPtr;
80 	dPtr->ObStrategyBlock = sbPtr;
81 	dPtr->ObMyModule = NULL;
82 	dPtr->HModelControlBlock=NULL;
83 
84 	/* need to initialise positional information in the new display block */
85 	/*Must be done before ProveHModel*/
86 	dPtr->ObWorld = dynPtr->Position;
87 	dPtr->ObEuler = dynPtr->OrientEuler;
88 	dPtr->ObMat = dynPtr->OrientMat;
89 
90 	 /* set the animation sequence, if we're a player corpse */
91 	{
92 		/* Okay, no messing, you MUST be a player corpse. */
93 		dPtr->HModelControlBlock=&corpseData->HModelController;
94 		ProveHModel(dPtr->HModelControlBlock,dPtr);
95     }
96 
97 
98 }
99 
MakeCorpseFar(STRATEGYBLOCK * sbPtr)100 void MakeCorpseFar(STRATEGYBLOCK *sbPtr)
101 {
102 	int i;
103 	LOCALASSERT(sbPtr->SBdptr != NULL);
104 
105 	/* get rid of the displayblock */
106 	i = DestroyActiveObject(sbPtr->SBdptr);
107 	LOCALASSERT(i==0);
108 	sbPtr->SBdptr = NULL;
109 }
110 
Convert_Alien_To_Corpse(STRATEGYBLOCK * sbPtr,DEATH_DATA * this_death,DAMAGE_PROFILE * damage)111 void Convert_Alien_To_Corpse(STRATEGYBLOCK *sbPtr,DEATH_DATA *this_death,DAMAGE_PROFILE* damage) {
112 
113 	NETCORPSEDATABLOCK *corpseDataPtr;
114 	ALIEN_STATUS_BLOCK *alienStatusPointer;
115 
116 	alienStatusPointer=(ALIEN_STATUS_BLOCK *)(sbPtr->SBdataptr);
117 	/* Convert an alien... to a corpse. */
118 
119     GLOBALASSERT(sbPtr);
120 	GLOBALASSERT(this_death);
121 	GLOBALASSERT(alienStatusPointer);
122 
123 	/* Inform the network. */
124 	if (AvP.Network != I_No_Network)
125 	{
126 		AddNetMsg_AlienAIKilled(sbPtr,this_death->Multiplayer_Code,ALIEN_DYINGTIME,alienStatusPointer->GibbFactor,damage);
127 	}
128 
129 	corpseDataPtr = (void *)AllocateMem(sizeof(NETCORPSEDATABLOCK));
130 	GLOBALASSERT(corpseDataPtr);
131 
132 	/* Fill in corpseDataPtr... */
133 	corpseDataPtr->SoundHandle  = SOUND_NOACTIVEINDEX;
134 	corpseDataPtr->SoundHandle2 = SOUND_NOACTIVEINDEX;
135 	corpseDataPtr->SoundHandle3 = SOUND_NOACTIVEINDEX;
136 	corpseDataPtr->SoundHandle4 = SOUND_NOACTIVEINDEX;
137 
138 	corpseDataPtr->Type=I_BehaviourAlien;
139 	corpseDataPtr->GibbFactor=alienStatusPointer->GibbFactor;
140 	corpseDataPtr->This_Death=this_death;
141 
142 	corpseDataPtr->CloakStatus = PCLOAK_Off;
143 	corpseDataPtr->CloakTimer = 0;
144 	corpseDataPtr->destructTimer = -1;
145 	corpseDataPtr->WeaponMisfireFunction=NULL;
146 	corpseDataPtr->My_Gunflash_Section=NULL;
147 	corpseDataPtr->My_Weapon=NULL;
148 	corpseDataPtr->weapon_variable=0;
149 	corpseDataPtr->Android=0;
150 	corpseDataPtr->ARealMarine=0;
151 	corpseDataPtr->TemplateRoot=NULL;
152 	corpseDataPtr->DeathFiring=0;
153 	corpseDataPtr->Wounds=0;
154 
155 	switch (alienStatusPointer->Type) {
156 		case AT_Standard:
157 		default:
158 			corpseDataPtr->subtype = 0;
159 			corpseDataPtr->hltable=GetThisHitLocationTable("alien");
160 			break;
161 		case AT_Predalien:
162 			corpseDataPtr->subtype = 1;
163 			corpseDataPtr->hltable=GetThisHitLocationTable("predalien");
164 			break;
165 		case AT_Praetorian:
166 			corpseDataPtr->subtype = 2;
167 			corpseDataPtr->hltable=GetThisHitLocationTable("praetorian");
168 			break;
169 	}
170 
171 	/* Remember wounds, or not? */
172 	Splice_HModels(&corpseDataPtr->HModelController,alienStatusPointer->HModelController.section_data);
173 
174 	/* Heh... now bin the old data block! */
175 	if(alienStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
176 		Sound_Stop(alienStatusPointer->soundHandle);
177 	}
178 	if(alienStatusPointer->soundHandle2!=SOUND_NOACTIVEINDEX) {
179 		Sound_Stop(alienStatusPointer->soundHandle2);
180 	}
181 	Dispel_HModel(&alienStatusPointer->HModelController);
182 	DeallocateMem(sbPtr->SBdataptr);
183 	/* Turn into the corpse. */
184 	sbPtr->SBdataptr=corpseDataPtr;
185 	sbPtr->I_SBtype=I_BehaviourNetCorpse;
186 
187  	SetCorpseAnimSequence_Core(sbPtr,this_death->Sequence_Type,this_death->Sub_Sequence,
188  		this_death->Sequence_Length,this_death->TweeningTime);
189 
190 	if (sbPtr->SBdptr) {
191 		/* Swap controllers round. */
192 		sbPtr->SBdptr->HModelControlBlock=&corpseDataPtr->HModelController;
193 		ProveHModel(&corpseDataPtr->HModelController,sbPtr->SBdptr);
194 	} else {
195 		ProveHModel_Far(&corpseDataPtr->HModelController,sbPtr);
196 	}
197 
198 	corpseDataPtr->timer=ALIEN_DYINGTIME;
199 	corpseDataPtr->validityTimer=CORPSE_VALIDITY_TIME;
200 	corpseDataPtr->HModelController.Looped=0;
201 	corpseDataPtr->HModelController.LoopAfterTweening=0;
202 
203 	/* stop motion */
204 	LOCALASSERT(sbPtr->DynPtr);
205 	sbPtr->DynPtr->Friction	= 400000;
206 	sbPtr->DynPtr->LinImpulse.vx+=sbPtr->DynPtr->LinVelocity.vx;
207 	sbPtr->DynPtr->LinImpulse.vy+=sbPtr->DynPtr->LinVelocity.vy;
208 	sbPtr->DynPtr->LinImpulse.vz+=sbPtr->DynPtr->LinVelocity.vz;
209 	sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
210 	sbPtr->DynPtr->CanClimbStairs = 0;
211 	/* Experiment... */
212 	sbPtr->DynPtr->UseStandardGravity=1;
213 	sbPtr->DynPtr->Mass	= 160;
214 	/* Okay... */
215 
216 	/* KJL 17:19:35 27/08/98 - ignore the player, other body parts, etc */
217 	sbPtr->DynPtr->OnlyCollideWithEnvironment = 1;
218 
219 	/* Electric death sound? */
220 	if (corpseDataPtr->This_Death->Electrical) {
221 		Sound_Play(SID_ED_ELEC_DEATH,"de",&sbPtr->DynPtr->Position,&corpseDataPtr->SoundHandle4);
222 	}
223 }
224 
Convert_Predator_To_Corpse(STRATEGYBLOCK * sbPtr,DEATH_DATA * this_death)225 void Convert_Predator_To_Corpse(STRATEGYBLOCK *sbPtr,DEATH_DATA *this_death) {
226 
227 	NETCORPSEDATABLOCK *corpseDataPtr;
228 	PREDATOR_STATUS_BLOCK *predatorStatusPointer;
229 
230 	predatorStatusPointer=(PREDATOR_STATUS_BLOCK *)(sbPtr->SBdataptr);
231 	/* Convert a predator... to a corpse. */
232 
233     GLOBALASSERT(sbPtr);
234 	GLOBALASSERT(this_death);
235 	GLOBALASSERT(predatorStatusPointer);
236 
237 	corpseDataPtr = (void *)AllocateMem(sizeof(NETCORPSEDATABLOCK));
238 	GLOBALASSERT(corpseDataPtr);
239 
240 	/* Fill in corpseDataPtr... */
241 	corpseDataPtr->SoundHandle  = SOUND_NOACTIVEINDEX;
242 	corpseDataPtr->SoundHandle2 = SOUND_NOACTIVEINDEX;
243 	corpseDataPtr->SoundHandle3 = SOUND_NOACTIVEINDEX;
244 	corpseDataPtr->SoundHandle4 = SOUND_NOACTIVEINDEX;
245 
246 	corpseDataPtr->Type=I_BehaviourPredator;
247 	corpseDataPtr->GibbFactor=predatorStatusPointer->GibbFactor;
248 	corpseDataPtr->This_Death=this_death;
249 
250 	corpseDataPtr->CloakStatus = predatorStatusPointer->CloakStatus;
251 	corpseDataPtr->CloakTimer  = predatorStatusPointer->CloakTimer;
252 
253 	if ((predatorStatusPointer->behaviourState==PBS_SelfDestruct)
254 		&&(predatorStatusPointer->internalState==1)) {
255 		corpseDataPtr->destructTimer = predatorStatusPointer->stateTimer;
256 	} else {
257 		corpseDataPtr->destructTimer = -1;
258 	}
259 
260 	corpseDataPtr->WeaponMisfireFunction=NULL;
261 	corpseDataPtr->My_Gunflash_Section=NULL;
262 	corpseDataPtr->weapon_variable=0;
263 	corpseDataPtr->Android=0;
264 	corpseDataPtr->ARealMarine=0;
265 	corpseDataPtr->TemplateRoot=NULL;
266 	corpseDataPtr->My_Weapon=NULL;
267 	corpseDataPtr->DeathFiring=0;
268 	corpseDataPtr->subtype = 0;
269 	corpseDataPtr->Wounds=0;
270 
271 	corpseDataPtr->hltable=GetThisHitLocationTable(predatorStatusPointer->Selected_Weapon->HitLocationTableName);
272 
273 	/* Remember wounds, or not? */
274 	Splice_HModels(&corpseDataPtr->HModelController,predatorStatusPointer->HModelController.section_data);
275 
276 	if (this_death->Template) {
277 		SECTION *root;
278 		/* Convert to template. */
279 		root=GetNamedHierarchyFromLibrary("hnpcpredator","Template");
280 		Transmogrify_HModels(sbPtr,&corpseDataPtr->HModelController,
281 			root, 1, 0,0);
282 	}
283 
284 	/* Heh... now bin the old data block! */
285 	if(predatorStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
286 		Sound_Stop(predatorStatusPointer->soundHandle);
287 	}
288 	Dispel_HModel(&predatorStatusPointer->HModelController);
289 	DeallocateMem(sbPtr->SBdataptr);
290 	/* Turn into the corpse. */
291 	sbPtr->SBdataptr=corpseDataPtr;
292 	sbPtr->I_SBtype=I_BehaviourNetCorpse;
293 
294  	SetCorpseAnimSequence_Core(sbPtr,this_death->Sequence_Type,this_death->Sub_Sequence,
295  		this_death->Sequence_Length,this_death->TweeningTime);
296 
297 	if (sbPtr->SBdptr) {
298 		/* Swap controllers round. */
299 		sbPtr->SBdptr->HModelControlBlock=&corpseDataPtr->HModelController;
300 		ProveHModel(&corpseDataPtr->HModelController,sbPtr->SBdptr);
301 	} else {
302 		ProveHModel_Far(&corpseDataPtr->HModelController,sbPtr);
303 	}
304 
305 	corpseDataPtr->timer=PRED_DIETIME;
306 	corpseDataPtr->validityTimer=CORPSE_VALIDITY_TIME;
307 	corpseDataPtr->HModelController.Looped=0;
308 	corpseDataPtr->HModelController.LoopAfterTweening=0;
309 
310 	/* stop motion */
311 	LOCALASSERT(sbPtr->DynPtr);
312 	sbPtr->DynPtr->Friction	= 400000;
313 	sbPtr->DynPtr->LinImpulse.vx+=sbPtr->DynPtr->LinVelocity.vx;
314 	sbPtr->DynPtr->LinImpulse.vy+=sbPtr->DynPtr->LinVelocity.vy;
315 	sbPtr->DynPtr->LinImpulse.vz+=sbPtr->DynPtr->LinVelocity.vz;
316 	sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
317 	sbPtr->DynPtr->CanClimbStairs = 0;
318 
319 	/* KJL 17:19:35 27/08/98 - ignore the player, other body parts, etc */
320 	sbPtr->DynPtr->OnlyCollideWithEnvironment = 1;
321 
322 	/* Electric death sound? */
323 	if (corpseDataPtr->This_Death->Electrical) {
324 		Sound_Play(SID_ED_ELEC_DEATH,"de",&sbPtr->DynPtr->Position,&corpseDataPtr->SoundHandle4);
325 	}
326 
327 }
328 
Convert_Marine_To_Corpse(STRATEGYBLOCK * sbPtr,DEATH_DATA * this_death)329 void Convert_Marine_To_Corpse(STRATEGYBLOCK *sbPtr,DEATH_DATA *this_death) {
330 
331 	NETCORPSEDATABLOCK *corpseDataPtr;
332 	MARINE_STATUS_BLOCK *marineStatusPointer;
333 
334 	marineStatusPointer=(MARINE_STATUS_BLOCK *)(sbPtr->SBdataptr);
335 	/* Convert a predator... to a corpse. */
336 
337     GLOBALASSERT(sbPtr);
338 	GLOBALASSERT(this_death);
339 	GLOBALASSERT(marineStatusPointer);
340 
341 	corpseDataPtr = (void *)AllocateMem(sizeof(NETCORPSEDATABLOCK));
342 	GLOBALASSERT(corpseDataPtr);
343 
344 	/* Fill in corpseDataPtr... */
345 	corpseDataPtr->SoundHandle  = SOUND_NOACTIVEINDEX;
346 	corpseDataPtr->SoundHandle2 = SOUND_NOACTIVEINDEX;
347 	corpseDataPtr->SoundHandle3 = SOUND_NOACTIVEINDEX;
348 	corpseDataPtr->SoundHandle4 = SOUND_NOACTIVEINDEX;
349 
350 	corpseDataPtr->Type=I_BehaviourMarine;
351 	corpseDataPtr->GibbFactor=marineStatusPointer->GibbFactor;
352 	corpseDataPtr->This_Death=this_death;
353 
354 	corpseDataPtr->CloakStatus = PCLOAK_Off;
355 	corpseDataPtr->CloakTimer = 0;
356 	corpseDataPtr->destructTimer = -1;
357 
358 	corpseDataPtr->My_Weapon=marineStatusPointer->My_Weapon;
359 	corpseDataPtr->WeaponMisfireFunction=marineStatusPointer->My_Weapon->WeaponMisfireFunction;
360 	corpseDataPtr->My_Gunflash_Section=marineStatusPointer->My_Gunflash_Section;
361 	corpseDataPtr->TemplateRoot=GetNamedHierarchyFromLibrary(marineStatusPointer->My_Weapon->Riffname,marineStatusPointer->My_Weapon->TemplateName);
362 	corpseDataPtr->Android=marineStatusPointer->Android;
363 	corpseDataPtr->ARealMarine=marineStatusPointer->My_Weapon->ARealMarine;
364 	corpseDataPtr->weapon_variable=0;
365 	corpseDataPtr->Wounds=0;
366 
367 	corpseDataPtr->subtype = 0;
368 	corpseDataPtr->hltable=GetThisHitLocationTable(marineStatusPointer->My_Weapon->HitLocationTableName);
369 
370 	if (corpseDataPtr->WeaponMisfireFunction) {
371 		if (marineStatusPointer->behaviourState==MBS_Firing) {
372 			corpseDataPtr->DeathFiring=1;
373 		} else {
374 			corpseDataPtr->DeathFiring=0;
375 		}
376 	} else {
377 		corpseDataPtr->DeathFiring=0;
378 	}
379 
380 	/* Remember wounds, or not? */
381 	Splice_HModels(&corpseDataPtr->HModelController,marineStatusPointer->HModelController.section_data);
382 
383 	if (this_death->Template) {
384 		/* Convert to template. */
385 		Transmogrify_HModels(sbPtr,&corpseDataPtr->HModelController,
386 			corpseDataPtr->TemplateRoot, 1, 0,0);
387 	}
388 	/* Pass over some sounds? */
389 
390 	/* Heh... now bin the old data block! */
391 	if(marineStatusPointer->soundHandle!=SOUND_NOACTIVEINDEX) {
392 		Sound_Stop(marineStatusPointer->soundHandle);
393 	}
394 	if(marineStatusPointer->soundHandle2!=SOUND_NOACTIVEINDEX) {
395 		/* soundHandle2 is the voice! */
396 		corpseDataPtr->SoundHandle2=marineStatusPointer->soundHandle2;
397 		ActiveSounds[marineStatusPointer->soundHandle2].externalRef=&corpseDataPtr->SoundHandle2;
398 	}
399 	Dispel_HModel(&marineStatusPointer->HModelController);
400 	DeallocateMem(sbPtr->SBdataptr);
401 	/* Turn into the corpse. */
402 	sbPtr->SBdataptr=corpseDataPtr;
403 	sbPtr->I_SBtype=I_BehaviourNetCorpse;
404 
405  	SetCorpseAnimSequence_Core(sbPtr,this_death->Sequence_Type,this_death->Sub_Sequence,
406  		this_death->Sequence_Length,this_death->TweeningTime);
407 
408 	if (sbPtr->SBdptr) {
409 		/* Swap controllers round. */
410 		sbPtr->SBdptr->HModelControlBlock=&corpseDataPtr->HModelController;
411 		ProveHModel(&corpseDataPtr->HModelController,sbPtr->SBdptr);
412 	} else {
413 		ProveHModel_Far(&corpseDataPtr->HModelController,sbPtr);
414 	}
415 
416 	corpseDataPtr->timer=MARINE_DYINGTIME;
417 	corpseDataPtr->validityTimer=CORPSE_VALIDITY_TIME;
418 	corpseDataPtr->HModelController.Looped=0;
419 	corpseDataPtr->HModelController.LoopAfterTweening=0;
420 
421 	/* stop motion */
422 	LOCALASSERT(sbPtr->DynPtr);
423 	sbPtr->DynPtr->Friction	= 400000;
424 	sbPtr->DynPtr->LinImpulse.vx+=sbPtr->DynPtr->LinVelocity.vx;
425 	sbPtr->DynPtr->LinImpulse.vy+=sbPtr->DynPtr->LinVelocity.vy;
426 	sbPtr->DynPtr->LinImpulse.vz+=sbPtr->DynPtr->LinVelocity.vz;
427 	sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
428 	sbPtr->DynPtr->CanClimbStairs = 0;
429 
430 	/* KJL 17:19:35 27/08/98 - ignore the player, other body parts, etc */
431 	sbPtr->DynPtr->OnlyCollideWithEnvironment = 1;
432 
433 	/* Electric death sound? */
434 	if (corpseDataPtr->This_Death->Electrical) {
435 		Sound_Play(SID_ED_ELEC_DEATH,"de",&sbPtr->DynPtr->Position,&corpseDataPtr->SoundHandle4);
436 	}
437 
438 }
439 
Convert_Xenoborg_To_Corpse(STRATEGYBLOCK * sbPtr,DEATH_DATA * this_death)440 void Convert_Xenoborg_To_Corpse(STRATEGYBLOCK *sbPtr,DEATH_DATA *this_death) {
441 
442 	NETCORPSEDATABLOCK *corpseDataPtr;
443 	XENO_STATUS_BLOCK *xenoStatusPointer;
444 
445 	xenoStatusPointer=(XENO_STATUS_BLOCK *)(sbPtr->SBdataptr);
446 	/* Convert an xenoborg... to a corpse. */
447 
448     GLOBALASSERT(sbPtr);
449 	GLOBALASSERT(this_death);
450 	GLOBALASSERT(xenoStatusPointer);
451 
452 	corpseDataPtr = (void *)AllocateMem(sizeof(NETCORPSEDATABLOCK));
453 	GLOBALASSERT(corpseDataPtr);
454 
455 	/* Fill in corpseDataPtr... */
456 	corpseDataPtr->SoundHandle  = SOUND_NOACTIVEINDEX;
457 	corpseDataPtr->SoundHandle2 = SOUND_NOACTIVEINDEX;
458 	corpseDataPtr->SoundHandle3 = SOUND_NOACTIVEINDEX;
459 	corpseDataPtr->SoundHandle4 = SOUND_NOACTIVEINDEX;
460 
461 	corpseDataPtr->Type=I_BehaviourXenoborg;
462 	corpseDataPtr->GibbFactor=xenoStatusPointer->GibbFactor;
463 	corpseDataPtr->This_Death=this_death;
464 
465 	corpseDataPtr->CloakStatus = PCLOAK_Off;
466 	corpseDataPtr->CloakTimer = 0;
467 	corpseDataPtr->destructTimer = -1;
468 	corpseDataPtr->WeaponMisfireFunction=NULL;
469 	corpseDataPtr->My_Gunflash_Section=NULL;
470 	corpseDataPtr->weapon_variable=0;
471 	corpseDataPtr->Android=0;
472 	corpseDataPtr->ARealMarine=0;
473 	corpseDataPtr->TemplateRoot=NULL;
474 	corpseDataPtr->My_Weapon=NULL;
475 	corpseDataPtr->DeathFiring=0;
476 	corpseDataPtr->subtype = 0;
477 	corpseDataPtr->Wounds=0;
478 
479 	corpseDataPtr->hltable=GetThisHitLocationTable("xenoborg");
480 
481 	/* Remember wounds, or not? */
482 	Splice_HModels(&corpseDataPtr->HModelController,xenoStatusPointer->HModelController.section_data);
483 
484 	/* Heh... now bin the old data block! */
485 	Dispel_HModel(&xenoStatusPointer->HModelController);
486 	DeallocateMem(sbPtr->SBdataptr);
487 	/* Turn into the corpse. */
488 	sbPtr->SBdataptr=corpseDataPtr;
489 	sbPtr->I_SBtype=I_BehaviourNetCorpse;
490 
491  	SetCorpseAnimSequence_Core(sbPtr,this_death->Sequence_Type,this_death->Sub_Sequence,
492  		this_death->Sequence_Length,this_death->TweeningTime);
493 
494 	if (sbPtr->SBdptr) {
495 		/* Swap controllers round. */
496 		sbPtr->SBdptr->HModelControlBlock=&corpseDataPtr->HModelController;
497 		ProveHModel(&corpseDataPtr->HModelController,sbPtr->SBdptr);
498 	} else {
499 		ProveHModel_Far(&corpseDataPtr->HModelController,sbPtr);
500 	}
501 
502 	corpseDataPtr->timer=XENO_DYINGTIME;
503 	corpseDataPtr->validityTimer=CORPSE_VALIDITY_TIME;
504 	corpseDataPtr->HModelController.Looped=0;
505 	corpseDataPtr->HModelController.LoopAfterTweening=0;
506 
507 	/* stop motion */
508 	LOCALASSERT(sbPtr->DynPtr);
509 	sbPtr->DynPtr->Friction	= 400000;
510 	sbPtr->DynPtr->LinImpulse.vx+=sbPtr->DynPtr->LinVelocity.vx;
511 	sbPtr->DynPtr->LinImpulse.vy+=sbPtr->DynPtr->LinVelocity.vy;
512 	sbPtr->DynPtr->LinImpulse.vz+=sbPtr->DynPtr->LinVelocity.vz;
513 	sbPtr->DynPtr->LinVelocity.vx = sbPtr->DynPtr->LinVelocity.vy = sbPtr->DynPtr->LinVelocity.vz = 0;
514 	sbPtr->DynPtr->CanClimbStairs = 0;
515 	/* Experiment... */
516 	sbPtr->DynPtr->UseStandardGravity=1;
517 	sbPtr->DynPtr->Mass	= 160;
518 	/* Okay... */
519 
520 	/* KJL 17:19:35 27/08/98 - ignore the player, other body parts, etc */
521 	sbPtr->DynPtr->OnlyCollideWithEnvironment = 1;
522 
523 	#if 0
524 	/* Electric death sound? */
525 	if (corpseDataPtr->This_Death->Electrical) {
526 		Sound_Play(SID_ED_ELEC_DEATH,"de",&sbPtr->DynPtr->Position,&corpseDataPtr->SoundHandle4);
527 	}
528 	#endif
529 
530 }
531 
CorpseBehaveFun(STRATEGYBLOCK * sbPtr)532 void CorpseBehaveFun(STRATEGYBLOCK *sbPtr)
533 {
534 
535 	/* Just count down. */
536 	NETCORPSEDATABLOCK *corpseDataPtr;
537 
538     LOCALASSERT(sbPtr);
539 
540 	corpseDataPtr = (NETCORPSEDATABLOCK *)sbPtr->SBdataptr;
541 	LOCALASSERT(corpseDataPtr);
542 
543 
544 	if (corpseDataPtr->timer<=0)
545 	{
546 		PLAYER_STATUS *playerStatusPtr = (PLAYER_STATUS *)(Player->ObStrategyBlock->SBdataptr);
547 
548 		if (playerStatusPtr->MyCorpse==sbPtr) {
549 			/* Set players corpse to null. */
550 			playerStatusPtr->MyCorpse=NULL;
551 		}
552 
553 		if(corpseDataPtr->SoundHandle  != SOUND_NOACTIVEINDEX) Sound_Stop(corpseDataPtr->SoundHandle);
554 		if(corpseDataPtr->SoundHandle2 != SOUND_NOACTIVEINDEX) Sound_Stop(corpseDataPtr->SoundHandle2);
555 		if(corpseDataPtr->SoundHandle3 != SOUND_NOACTIVEINDEX) Sound_Stop(corpseDataPtr->SoundHandle3);
556 		if(corpseDataPtr->SoundHandle4 != SOUND_NOACTIVEINDEX) Sound_Stop(corpseDataPtr->SoundHandle4);
557 
558 		/* Remove corpse. */
559 		DestroyAnyStrategyBlock(sbPtr);
560 		AddNetMsg_LocalObjectDestroyed(sbPtr);
561 		return;
562 	}
563 	else
564 	{
565 		DISPLAYBLOCK *dispPtr = sbPtr->SBdptr;
566 
567 		/* do we have a displayblock? */
568 		if (dispPtr)
569 		{
570 			dispPtr->SpecialFXFlags |= SFXFLAG_MELTINGINTOGROUND;
571 			dispPtr->ObFlags2 = corpseDataPtr->timer/2;
572 
573 			if (corpseDataPtr->Type==I_BehaviourXenoborg) {
574 				/* Particularly important for xenoborgs... optional for others? */
575 				if (dispPtr->ObFlags2<ONE_FIXED) {
576 					corpseDataPtr->HModelController.DisableBleeding=1;
577 				}
578 			}
579 		}
580 
581 		/* Does the corpse that falls when not visible make no sound? */
582 		ProveHModel_Far(&corpseDataPtr->HModelController,sbPtr);
583 	}
584 
585 	corpseDataPtr->timer-=NormalFrameTime;
586 	corpseDataPtr->validityTimer-=NormalFrameTime;
587 
588 	/* May get decapitated whilst screaming... */
589 	if ((corpseDataPtr->Type==I_BehaviourMarine)
590 		||((corpseDataPtr->Type==I_BehaviourMarinePlayer)&&(AvP.PlayerType==I_Marine))) {
591 
592 		SECTION_DATA *head;
593 
594 		head=GetThisSectionData(corpseDataPtr->HModelController.section_data,"head");
595 
596 		/* Is it still attached? */
597 		if (head) {
598 			if (head->flags&section_data_notreal) {
599 				head=NULL;
600 			}
601 		}
602 
603 		if (head==NULL) {
604 			if(corpseDataPtr->SoundHandle2 != SOUND_NOACTIVEINDEX) {
605 				Sound_Stop(corpseDataPtr->SoundHandle2);
606 			}
607 		}
608 	}
609 
610 	if ((corpseDataPtr->Type==I_BehaviourPredator)||
611 		((corpseDataPtr->Type==I_BehaviourMarinePlayer)&&(AvP.PlayerType==I_Predator))) {
612 
613 		/* If we're a partially cloaked predator, continue to decloak. */
614 		if (corpseDataPtr->CloakStatus==PCLOAK_Off) {
615 			/* Do nothing. */
616 		} else if (corpseDataPtr->CloakStatus==PCLOAK_Activating) {
617 			/* Don't reset timer. */
618 			corpseDataPtr->CloakStatus = PCLOAK_Deactivating;
619 		} else if (corpseDataPtr->CloakStatus==PCLOAK_Deactivating) {
620 			/* Okay, okay! */
621 		} else {
622 			/* Cloak must be On. */
623 			corpseDataPtr->CloakStatus = PCLOAK_Deactivating;
624 			corpseDataPtr->CloakTimer = 0; /* Was predStatus->PredShimmer. */
625 		}
626 		GLOBALASSERT((corpseDataPtr->CloakStatus==PCLOAK_Deactivating)||(corpseDataPtr->CloakStatus==PCLOAK_Off));
627 		/* Run the timer. */
628 		if (corpseDataPtr->CloakStatus==PCLOAK_Deactivating) {
629 			corpseDataPtr->CloakTimer += NormalFrameTime;
630 			if(corpseDataPtr->CloakTimer>=(ONE_FIXED))
631 			{
632 				corpseDataPtr->CloakTimer=0;
633 				corpseDataPtr->CloakStatus=PCLOAK_Off;
634 			}
635 		}
636 	} else {
637 		GLOBALASSERT(corpseDataPtr->CloakStatus==PCLOAK_Off);
638 	}
639 
640 	/* Marine specifics. */
641 	if (corpseDataPtr->Type==I_BehaviourMarine) {
642 		/* Did marine die with the trigger held down? */
643 		if (corpseDataPtr->DeathFiring) {
644 			/* Is there a gunflash? */
645 			if(corpseDataPtr->My_Gunflash_Section) {
646 				/* But is it still attached? */
647 				if (corpseDataPtr->My_Gunflash_Section->my_controller==&(corpseDataPtr->HModelController)) {
648 					/* Keep firing! */
649 					LOCALASSERT(corpseDataPtr->WeaponMisfireFunction);
650 					/* Shouldn't be doing this without knowing why. */
651 					(*corpseDataPtr->WeaponMisfireFunction)(corpseDataPtr->My_Gunflash_Section,&corpseDataPtr->weapon_variable);
652 				}
653 			}
654 		}
655 
656 		/* Do we want to trim off the weapons? */
657 
658 		if (corpseDataPtr->HModelController.keyframe_flags) {
659 
660 			GLOBALASSERT(corpseDataPtr->TemplateRoot);
661 
662 			TrimToTemplate(sbPtr,&corpseDataPtr->HModelController,corpseDataPtr->TemplateRoot, 1);
663 		}
664 	}
665 
666 	/* Fire sound code. */
667 	if(corpseDataPtr->SoundHandle3!=SOUND_NOACTIVEINDEX) Sound_Update3d(corpseDataPtr->SoundHandle3,&(sbPtr->DynPtr->Position));
668 	if(corpseDataPtr->SoundHandle4!=SOUND_NOACTIVEINDEX) Sound_Update3d(corpseDataPtr->SoundHandle4,&(sbPtr->DynPtr->Position));
669 
670 	if (sbPtr->SBDamageBlock.IsOnFire) {
671 		if (corpseDataPtr->SoundHandle3!=SOUND_NOACTIVEINDEX) {
672 			if (ActiveSounds[corpseDataPtr->SoundHandle3].soundIndex!=SID_FIRE) {
673 				Sound_Stop(corpseDataPtr->SoundHandle3);
674 			 	Sound_Play(SID_FIRE,"dlev",&(sbPtr->DynPtr->Position),&corpseDataPtr->SoundHandle3,127);
675 			}
676 		} else {
677 		 	Sound_Play(SID_FIRE,"dlev",&(sbPtr->DynPtr->Position),&corpseDataPtr->SoundHandle3,127);
678 		}
679 	} else {
680 		if (corpseDataPtr->SoundHandle3!=SOUND_NOACTIVEINDEX) {
681 			Sound_Stop(corpseDataPtr->SoundHandle3);
682 		}
683 	}
684 
685 	#if CORPSE_SIGHTINGS
686 	Marine_CorpseSightingTest(sbPtr);
687 	#endif
688 
689 	/* Finally consider destructing preds. */
690 	if (corpseDataPtr->destructTimer>=0) {
691 		corpseDataPtr->destructTimer-=NormalFrameTime;
692 		if (corpseDataPtr->destructTimer<=0) {
693 			StartPredatorSelfDestructExplosion(sbPtr);
694 			corpseDataPtr->GibbFactor=ONE_FIXED;
695 			corpseDataPtr->destructTimer=-1;
696 		}
697 	}
698 }
699 
SetCorpseAnimSequence_Core(STRATEGYBLOCK * sbPtr,HMODEL_SEQUENCE_TYPES type,int subtype,int length,int tweeningtime)700 void SetCorpseAnimSequence_Core(STRATEGYBLOCK *sbPtr,HMODEL_SEQUENCE_TYPES type, int subtype, int length, int tweeningtime)
701 {
702 
703 	NETCORPSEDATABLOCK *corpseStatus=(NETCORPSEDATABLOCK *)(sbPtr->SBdataptr);
704 
705 	GLOBALASSERT(length!=0);
706 
707 	if (tweeningtime<=0) {
708 		InitHModelSequence(&corpseStatus->HModelController,(int)type,subtype,length);
709 	} else {
710 		InitHModelTweening(&corpseStatus->HModelController, tweeningtime, (int)type,subtype,length,0);
711 	}
712 
713 	corpseStatus->HModelController.Playing=1;
714 	/* Might be unset... */
715 }
716 
CorpseIsDamaged(STRATEGYBLOCK * sbPtr,DAMAGE_PROFILE * damage,int multiple,int wounds,SECTION_DATA * Section,VECTORCH * incoming)717 void CorpseIsDamaged(STRATEGYBLOCK *sbPtr, DAMAGE_PROFILE *damage, int multiple, int wounds,SECTION_DATA *Section,VECTORCH *incoming) {
718 
719 	NETCORPSEDATABLOCK *corpseDataPtr;
720 	int tkd,deathtype;
721 
722     LOCALASSERT(sbPtr);
723 	corpseDataPtr = (NETCORPSEDATABLOCK *)sbPtr->SBdataptr;
724 	LOCALASSERT(corpseDataPtr);
725 
726 	/* Set up gibb factor. */
727 
728 	tkd=TotalKineticDamage(damage);
729 	deathtype=0;
730 
731 	corpseDataPtr->Wounds|=wounds;
732 
733 	switch(corpseDataPtr->Type) {
734 		case I_BehaviourMarinePlayer:
735 			{
736 				if (damage->ExplosivePower==1) {
737 					if (MUL_FIXED(tkd,(multiple&((ONE_FIXED<<1)-1)))>20) {
738 						/* Okay, you can gibb now. */
739 						corpseDataPtr->GibbFactor=ONE_FIXED>>1;
740 						deathtype=2;
741 					}
742 				} else if ((tkd>60)&&((multiple>>16)>1)) {
743 					int newmult;
744 
745 					newmult=DIV_FIXED(multiple,NormalFrameTime);
746 					if (MUL_FIXED(tkd,newmult)>(500)) {
747 						/* Loadsabullets! */
748 						corpseDataPtr->GibbFactor=-(ONE_FIXED>>2);
749 						deathtype=2;
750 					}
751 				}
752 
753 				if ((damage->ExplosivePower==2)||(damage->ExplosivePower==6)) {
754 					/* Basically SADARS only. */
755 					corpseDataPtr->GibbFactor=ONE_FIXED;
756 					deathtype=3;
757 				}
758 
759 				if (damage->ForceBoom) {
760 					deathtype+=damage->ForceBoom;
761 				}
762 			}
763 			break;
764 		case I_BehaviourAlien:
765 		case I_BehaviourAlienPlayer:
766 			{
767 				if (damage->ExplosivePower==1) {
768 				 	/* Explosion case. */
769 				 	if (MUL_FIXED(tkd,(multiple&((ONE_FIXED<<1)-1)))>20) {
770 				 		/* Okay, you can gibb now. */
771 				 		corpseDataPtr->GibbFactor=ONE_FIXED>>1;
772 						deathtype=2;
773 				 	}
774 				} else if ((tkd<40)&&((multiple>>16)>1)) {
775 				 	int newmult;
776 
777 				 	newmult=DIV_FIXED(multiple,NormalFrameTime);
778 				 	if (MUL_FIXED(tkd,newmult)>700) {
779 				 		/* Excessive bullets case 1. */
780 				 		corpseDataPtr->GibbFactor=ONE_FIXED>>2;
781 						deathtype=2;
782 				 	} else if (MUL_FIXED(tkd,newmult)>250) {
783 				 		/* Excessive bullets case 2. */
784 				 		corpseDataPtr->GibbFactor=ONE_FIXED>>3;
785 						deathtype=1;
786 				 	}
787 				}
788 
789 				/* Predaliens and preatorians only gibb for sadars. */
790 				if (corpseDataPtr->subtype!=0) {
791 					corpseDataPtr->GibbFactor=0;
792 					/* But retain deathtype. */
793 				}
794 
795 				if ((damage->ExplosivePower==2)||(damage->ExplosivePower==6)) {
796 					/* Basically SADARS only. */
797 					if (corpseDataPtr->Type==AT_Standard) {
798 						corpseDataPtr->GibbFactor=ONE_FIXED;
799 					} else {
800 						corpseDataPtr->GibbFactor=ONE_FIXED>>2;
801 					}
802 					deathtype=3;
803 				}
804 
805 				if (damage->ForceBoom) {
806 					deathtype+=damage->ForceBoom;
807 				}
808 				/* No additional gibbing for flamethrowers. */
809 
810 				if (damage->Id==AMMO_PREDPISTOL_STRIKE) {
811 					/* Blow up if hit by the bolt? */
812 					corpseDataPtr->GibbFactor=ONE_FIXED>>3;
813 				} else if (damage->Id==AMMO_PRED_PISTOL) {
814 					/* Unfortunately, that can't happen.  Try this test instead. */
815 					if (multiple>(43253)) {
816 						/* Must be pretty close. */
817 						corpseDataPtr->GibbFactor=ONE_FIXED>>3;
818 					}
819 				} else if (damage->Id==AMMO_FLECHETTE_POSTMAX) {
820 					corpseDataPtr->GibbFactor=ONE_FIXED>>2;
821 				}
822 			}
823 			break;
824 		case I_BehaviourPredator:
825 		case I_BehaviourXenoborg:
826 			/* Predator and Xenoborg 'splatting' currently ommitted... */
827 			break;
828 		default:
829 			break;
830 	}
831 
832 }
833 
834 
835 
836 
837 
838 
839 
840 /*--------------------**
841 ** Loading and Saving **
842 **--------------------*/
843 #include "savegame.h"
844 typedef struct corpse_save_block
845 {
846 	SAVE_BLOCK_STRATEGY_HEADER header;
847 
848 	int timer;
849 	int validityTimer;
850 
851 	AVP_BEHAVIOUR_TYPE Type;
852 	int hltable_index;
853 	int GibbFactor;
854 
855 	/* If you're a predator... */
856 	PRED_CLOAKSTATE CloakStatus;
857 	int CloakTimer;
858 	int destructTimer;
859 	/* If you're a marine... */
860 	int weapon_id;
861 	int weapon_variable;
862 	int Android;
863 	int ARealMarine;
864 	/* If you're an alien... */
865 	int subtype;
866 
867 	int Wounds;
868 
869 	int DeathFiring	:1;
870 
871 
872 	int deathCode;
873 
874 	//strategyblock stuff
875 	int integrity;
876 	DAMAGEBLOCK SBDamageBlock;
877 	DYNAMICSBLOCK dynamics;
878 }CORPSE_SAVE_BLOCK;
879 
880 
881 
882 //defines for load/save macros
883 #define SAVELOAD_BLOCK block
884 #define SAVELOAD_BEHAV corpseDataPtr
885 
886 
LoadStrategy_Corpse(SAVE_BLOCK_STRATEGY_HEADER * header)887 void LoadStrategy_Corpse(SAVE_BLOCK_STRATEGY_HEADER* header)
888 {
889 	extern HITLOCATIONTABLE Global_Hitlocation_Tables[];
890 
891 	STRATEGYBLOCK* sbPtr;
892 	NETCORPSEDATABLOCK* corpseDataPtr;
893 	CORPSE_SAVE_BLOCK* block = (CORPSE_SAVE_BLOCK*) header;
894 
895 	//check the size of the save block
896 	if(header->size!=sizeof(*block)) return;
897 
898 	//see if there is a living version of this corpse
899 	sbPtr = FindSBWithName(header->SBname);
900 
901 	if(sbPtr)
902 	{
903 		//make sure the strategy found is some type of creature
904 		if(sbPtr->I_SBtype != I_BehaviourAlien &&
905 		   sbPtr->I_SBtype != I_BehaviourMarine &&
906 		   sbPtr->I_SBtype != I_BehaviourPredator &&
907 		   sbPtr->I_SBtype != I_BehaviourDormantPredator &&
908 		   sbPtr->I_SBtype != I_BehaviourXenoborg &&
909 		   sbPtr->I_SBtype != I_BehaviourFaceHugger)
910 		{
911 			return;
912 		}
913 		//get rid of it then
914 		DestroyAnyStrategyBlock(sbPtr);
915 
916 		sbPtr = NULL;
917 	}
918 
919 	//now we need to create a corpse from scratch
920 	sbPtr = CreateActiveStrategyBlock();
921 	if(!sbPtr)
922 	{
923 		GLOBALASSERT(0=="Run out of strategy blocks");
924 		return;
925 	}
926 	InitialiseSBValues(sbPtr);
927 	corpseDataPtr = (void *)AllocateMem(sizeof(NETCORPSEDATABLOCK));
928 
929 	//fill in some default values
930 	memset(corpseDataPtr,0,sizeof(*corpseDataPtr));
931 
932 	corpseDataPtr->SoundHandle  = SOUND_NOACTIVEINDEX;
933 	corpseDataPtr->SoundHandle2 = SOUND_NOACTIVEINDEX;
934 	corpseDataPtr->SoundHandle3 = SOUND_NOACTIVEINDEX;
935 	corpseDataPtr->SoundHandle4 = SOUND_NOACTIVEINDEX;
936 
937 	sbPtr->SBdataptr=corpseDataPtr;
938 	sbPtr->I_SBtype=I_BehaviourNetCorpse;
939 	COPY_NAME(sbPtr->SBname,block->header.SBname);
940 	sbPtr->shapeIndex = 0;
941 	sbPtr->maintainVisibility = 1;
942 
943 	//get a dynamics block
944 	sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_SPRITE_NPC);
945 
946 
947 	//start copying stuff
948 
949 	COPYELEMENT_LOAD(timer)
950 	COPYELEMENT_LOAD(validityTimer)
951 	COPYELEMENT_LOAD(Type)
952 	COPYELEMENT_LOAD(GibbFactor)
953 	COPYELEMENT_LOAD(CloakStatus)
954 	COPYELEMENT_LOAD(CloakTimer)
955 	COPYELEMENT_LOAD(destructTimer)
956 	COPYELEMENT_LOAD(weapon_variable)
957 	COPYELEMENT_LOAD(Android)
958 	COPYELEMENT_LOAD(ARealMarine)
959 	COPYELEMENT_LOAD(subtype)
960 	COPYELEMENT_LOAD(Wounds)
961 	COPYELEMENT_LOAD(DeathFiring)
962 
963 
964 	//copy strategy block stuff
965 	*sbPtr->DynPtr = block->dynamics;
966 	sbPtr->integrity = block->integrity;
967 	sbPtr->SBDamageBlock = block->SBDamageBlock;
968 
969 	//hit location table
970 	if(block->hltable_index>=0)
971 	{
972 		corpseDataPtr->hltable = &Global_Hitlocation_Tables[block->hltable_index];
973 	}
974 	else
975 	{
976 		corpseDataPtr->hltable = NULL;
977 	}
978 
979 	// get death_data
980 	corpseDataPtr->This_Death = GetThisDeath_FromUniqueCode(block->deathCode);
981 
982 	//get marine's weapon (if a marine)
983 	corpseDataPtr->My_Weapon = GetThisNPCMarineWeapon(block->weapon_id);
984 	if(corpseDataPtr->My_Weapon)
985 	{
986 		corpseDataPtr->WeaponMisfireFunction=corpseDataPtr->My_Weapon->WeaponMisfireFunction;
987 		corpseDataPtr->My_Gunflash_Section=corpseDataPtr->My_Gunflash_Section;
988 		corpseDataPtr->TemplateRoot=GetNamedHierarchyFromLibrary(corpseDataPtr->My_Weapon->Riffname,corpseDataPtr->My_Weapon->TemplateName);
989 	}
990 
991 
992 	//load the corpse's hierarchy
993 	{
994 		SAVE_BLOCK_HEADER* hier_header = GetNextBlockIfOfType(SaveBlock_Hierarchy);
995 		if(hier_header)
996 		{
997 			LoadHierarchy(hier_header,&corpseDataPtr->HModelController);
998 		}
999 	}
1000 
1001 	Load_SoundState(&corpseDataPtr->SoundHandle);
1002 	Load_SoundState(&corpseDataPtr->SoundHandle2);
1003 	Load_SoundState(&corpseDataPtr->SoundHandle3);
1004 	Load_SoundState(&corpseDataPtr->SoundHandle4);
1005 
1006 }
1007 
1008 
SaveStrategy_Corpse(STRATEGYBLOCK * sbPtr)1009 void SaveStrategy_Corpse(STRATEGYBLOCK* sbPtr)
1010 {
1011 	CORPSE_SAVE_BLOCK *block;
1012 	NETCORPSEDATABLOCK* corpseDataPtr;
1013 
1014 	corpseDataPtr = (NETCORPSEDATABLOCK*)sbPtr->SBdataptr;
1015 
1016 	GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
1017 
1018 	//start copying stuff
1019 
1020 	COPYELEMENT_SAVE(timer)
1021 	COPYELEMENT_SAVE(validityTimer)
1022 	COPYELEMENT_SAVE(Type)
1023 	COPYELEMENT_SAVE(GibbFactor)
1024 	COPYELEMENT_SAVE(CloakStatus)
1025 	COPYELEMENT_SAVE(CloakTimer)
1026 	COPYELEMENT_SAVE(destructTimer)
1027 	COPYELEMENT_SAVE(weapon_variable)
1028 	COPYELEMENT_SAVE(Android)
1029 	COPYELEMENT_SAVE(ARealMarine)
1030 	COPYELEMENT_SAVE(subtype)
1031 	COPYELEMENT_SAVE(Wounds)
1032 	COPYELEMENT_SAVE(DeathFiring)
1033 
1034 
1035 	//hit location table
1036 	if(corpseDataPtr->hltable)
1037 	{
1038 		block->hltable_index = corpseDataPtr->hltable->index;
1039 	}
1040 	else
1041 	{
1042 		block->hltable_index = -1;
1043 	}
1044 
1045 	//save death code
1046 	if(corpseDataPtr->This_Death)
1047 	{
1048 		block->deathCode = corpseDataPtr->This_Death->Unique_Code;
1049 	}
1050 	else
1051 	{
1052 		block->deathCode = -1;
1053 	}
1054 
1055 	//save marine's weapon
1056 	if(corpseDataPtr->My_Weapon)
1057 		block->weapon_id = corpseDataPtr->My_Weapon->id;
1058 	else
1059 		block->weapon_id = -1;
1060 
1061 
1062 	//save strategy block stuff
1063 
1064 	block->dynamics = *sbPtr->DynPtr;
1065 	block->dynamics.CollisionReportPtr=0;
1066 
1067 	block->integrity = sbPtr->integrity;
1068 	block->SBDamageBlock = sbPtr->SBDamageBlock;
1069 
1070 	//save the  hierarchy
1071 	SaveHierarchy(&corpseDataPtr->HModelController);
1072 
1073 	Save_SoundState(&corpseDataPtr->SoundHandle);
1074 	Save_SoundState(&corpseDataPtr->SoundHandle2);
1075 	Save_SoundState(&corpseDataPtr->SoundHandle3);
1076 	Save_SoundState(&corpseDataPtr->SoundHandle4);
1077 }
1078