1 /* Patrick 14/7/97----------------------------
2   Source for Multi-Player ghost object support header
3   ----------------------------------------------------------------------*/
4 #include "3dc.h"
5 #include "inline.h"
6 #include "module.h"
7 #include "stratdef.h"
8 #include "gamedef.h"
9 #include "bh_types.h"
10 #include "dynblock.h"
11 #include "bh_debri.h"
12 #include "bh_alien.h"
13 #include "bh_pred.h"
14 #include "bh_marin.h"
15 #include "pvisible.h"
16 #include "pldnet.h"
17 #include "pldghost.h"
18 #include "lighting.h"
19 #include "psnd.h"
20 #include "load_shp.h"
21 #include "projload.hpp"
22 #include "particle.h"
23 #include "sfx.h"
24 #include "psndplat.h"
25 #include "bh_corpse.h"
26 #include "bh_weap.h"
27 #include "showcmds.h"
28 #include "weapons.h"
29 
30 #define UseLocalAssert Yes
31 #include "ourasert.h"
32 
33 /*----------------------------------------------------------------------
34   Global Variables
35   ----------------------------------------------------------------------*/
36 
37 
38 /*----------------------------------------------------------------------
39   External globals
40   ----------------------------------------------------------------------*/
41 extern int NormalFrameTime;
42 extern int GlobalFrameCounter;
43 extern ACTIVESOUNDSAMPLE ActiveSounds[];
44 extern DEATH_DATA Alien_Deaths[];
45 extern HITLOCATIONTABLE *GetThisHitLocationTable(char *id);
46 
47 extern MATRIXCH Identity_RotMat; /* From HModel.c */
48 
49 /*-----------------------------------------------------------------------
50   Prototypes
51   ----------------------------------------------------------------------*/
52 
53 static void SetPlayerGhostAnimationSequence(STRATEGYBLOCK *sbPtr, int sequence, int special);
54 #if 0
55 static void InitPlayerGhostAnimSequence(STRATEGYBLOCK *sbPtr);
56 #endif
57 static void UpdatePlayerGhostAnimSequence(STRATEGYBLOCK *sbPtr, int sequence, int special);
58 
59 SOUND3DDATA Ghost_Explosion_SoundData={
60 	{0,0,0,},
61 	{0,0,0,},
62 	15000,
63 	150000,
64 };
65 
66 void UpdateObjectTrails(STRATEGYBLOCK *sbPtr);
67 static void CalculatePosnForGhostAutoGunMuzzleFlash(STRATEGYBLOCK *sbPtr,VECTORCH *position, EULER *orientation);
68 void UpdateAlienAIGhostAnimSequence(STRATEGYBLOCK *sbPtr,HMODEL_SEQUENCE_TYPES type, int subtype, int length, int tweeningtime);
69 
70 /*-----------------------------------------------------------------------
71   Functions...
72   ----------------------------------------------------------------------*/
73 
74 /* updates an existing ghost's position and orientation: Before calling this
75 need to use FindGhost to locate the ghost (which confirms it's existance) */
UpdateGhost(STRATEGYBLOCK * sbPtr,VECTORCH * position,EULER * orientation,int sequence,int special)76 void UpdateGhost(STRATEGYBLOCK *sbPtr,VECTORCH *position,EULER *orientation,int sequence, int special)
77 {
78 	NETGHOSTDATABLOCK *ghostData;
79 
80 	LOCALASSERT(sbPtr);
81 	ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
82 
83 	/* for visibility support: as ghosts can be moved when invisible, we need to work out
84 	which module they're in	whenever we update them. We must be carefull, however, not
85 	to set the containingModule to NULL if the object has moved outside the env, as
86 	the	visibility system expects that we at least know what module any object WAS in,
87 	even if we do not now... thus, if we cannot find a containing module, we abort the update */
88 
89 	/* KJL 21:01:09 23/05/98 - I've put this test here because the player's image in a mirror goes
90 	throught this code, and it's obviously going to be outside the environment */
91 	if (sbPtr->I_SBtype==I_BehaviourNetGhost)
92 	{
93 		MODULE *myContainingModule = ModuleFromPosition(position, (sbPtr->containingModule));
94 		if(myContainingModule==NULL)
95 		{
96 			//Not in any module , so don't try updating ghost,
97 			//except for various projectiles which can be shot
98 			//out of the environment semi-legitamately
99 			if(ghostData->type!=I_BehaviourGrenade &&
100 			   ghostData->type!=I_BehaviourRocket &&
101 			   ghostData->type!=I_BehaviourPPPlasmaBolt &&
102 			   ghostData->type!=I_BehaviourSpeargunBolt &&
103 			   ghostData->type!=I_BehaviourPredatorDisc_SeekTrack &&
104 			   ghostData->type!=I_BehaviourPredatorEnergyBolt &&
105 			   ghostData->type!=I_BehaviourPulseGrenade &&
106 			   ghostData->type!=I_BehaviourFlareGrenade &&
107 			   ghostData->type!=I_BehaviourFragmentationGrenade &&
108 			   ghostData->type!=I_BehaviourClusterGrenade &&
109 			   ghostData->type!=I_BehaviourFrisbeeEnergyBolt &&
110 			   ghostData->type!=I_BehaviourProximityGrenade)
111 					return;
112 		}
113 		else
114 		{
115 			sbPtr->containingModule = myContainingModule;
116 		}
117 	}
118 
119 	/* CDF 29/7/98 I'll assume that stationary discs are stuck. */
120 	if (ghostData->type==I_BehaviourPredatorDisc_SeekTrack) {
121 		DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
122 		if ((dynPtr->Position.vx==dynPtr->PrevPosition.vx)&&
123 			(dynPtr->Position.vy==dynPtr->PrevPosition.vy)&&
124 			(dynPtr->Position.vz==dynPtr->PrevPosition.vz)) {
125 			ghostData->HModelController.Playing=0;
126 
127 
128 		} else {
129 			extern void NewTrailPoint(DYNAMICSBLOCK *dynPtr);
130 			ghostData->HModelController.Playing=1;
131 			//draw the disc's trail
132 			NewTrailPoint(dynPtr);
133 
134 			//update sound for disc
135 			if(ghostData->SoundHandle!=SOUND_NOACTIVEINDEX) {
136 				Sound_Update3d(ghostData->SoundHandle,&(sbPtr->DynPtr->Position));
137 			} else {
138 			 	Sound_Play(SID_PREDATOR_DISK_FLYING,"del",&(sbPtr->DynPtr->Position),&ghostData->SoundHandle);
139 
140 			}
141 		}
142 	}
143 
144 	if (ghostData->type==I_BehaviourFrisbee) {
145 		//update sound for disc
146 		if(ghostData->SoundHandle!=SOUND_NOACTIVEINDEX) {
147 			Sound_Update3d(ghostData->SoundHandle,&(sbPtr->DynPtr->Position));
148 		} else {
149 		 	Sound_Play(SID_ED_SKEETERDISC_SPIN,"del",&(sbPtr->DynPtr->Position),&ghostData->SoundHandle);
150 		}
151 	}
152 
153 	/* update the dynamics block */
154 	{
155 		DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
156 //		dynPtr->Position = dynPtr->PrevPosition = *position;
157 		dynPtr->PrevPosition = dynPtr->Position;
158 		dynPtr->PrevOrientMat = dynPtr->OrientMat;
159 		dynPtr->Position = *position;
160 		dynPtr->OrientEuler = *orientation;
161 		CreateEulerMatrix(&dynPtr->OrientEuler,&dynPtr->OrientMat);
162 		TransposeMatrixCH(&dynPtr->OrientMat);
163 	}
164 	UpdateObjectTrails(sbPtr);
165 	#if 0
166 	if (ghostData->type == I_BehaviourPredatorEnergyBolt)
167 	{
168 	 	MakePlasmaTrailParticles(sbPtr->DynPtr,32);
169 	}
170 	#endif
171 
172 
173 	/* if we're a player type, update the animation sequence */
174 	if((ghostData->type==I_BehaviourMarinePlayer)||
175 	   (ghostData->type==I_BehaviourAlienPlayer)||
176 	   (ghostData->type==I_BehaviourPredatorPlayer))
177 	{
178 		if(sequence!=-1)
179 		{
180 			UpdatePlayerGhostAnimSequence(sbPtr,sequence, special);
181 		}
182    	}
183 
184 	/* KJL 15:59:59 26/11/98 - no pheromone trails */
185 	#if 0
186 	if (AvP.PlayerType == I_Alien)
187 	{
188 		if ((ghostData->type==I_BehaviourMarinePlayer)
189 		  ||(ghostData->type==I_BehaviourPredatorPlayer))
190 		NewTrailPoint(sbPtr->DynPtr);
191 	}
192 	#endif
193 
194 	/* KJL 16:58:04 17/06/98 - we want to update anims differently for NPCS */
195 	if((ghostData->type==I_BehaviourMarine)||
196 	   (ghostData->type==I_BehaviourAlien)||
197 	   (ghostData->type==I_BehaviourPredator))
198 	{
199 		UpdatePlayerGhostAnimSequence(sbPtr,sequence, special);
200 	}
201 
202 	/* refresh integrity */
203 	ghostData->integrity = GHOST_INTEGRITY;
204 
205 }
UpdateObjectTrails(STRATEGYBLOCK * sbPtr)206 void UpdateObjectTrails(STRATEGYBLOCK *sbPtr)
207 {
208 	NETGHOSTDATABLOCK *ghostDataPtr;
209 
210     LOCALASSERT(sbPtr);
211 
212 	ghostDataPtr = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
213 	LOCALASSERT(ghostDataPtr);
214 
215 	LOCALASSERT(sbPtr->DynPtr);
216 
217 	switch(ghostDataPtr->type)
218 	{
219 		case I_BehaviourPulseGrenade:
220 		{
221 			MakeRocketTrailParticles(&(sbPtr->DynPtr->PrevPosition), &(sbPtr->DynPtr->Position));
222 			break;
223 		}
224 		case I_BehaviourRocket:
225 		{
226 			MakeRocketTrailParticles(&(sbPtr->DynPtr->PrevPosition), &(sbPtr->DynPtr->Position));
227 			break;
228 		}
229 		case I_BehaviourPredatorEnergyBolt:
230 		{
231 		  	MakePlasmaTrailParticles(sbPtr->DynPtr,32);
232 			break;
233 		}
234 		case I_BehaviourFrisbeeEnergyBolt:
235 		{
236 		  	MakeDewlineTrailParticles(sbPtr->DynPtr,32);
237 			break;
238 		}
239 		case I_BehaviourFrisbee:
240 		{
241 			{
242 				int l;
243 				for (l=0;l<4;l++)
244 					MakeFlareParticle(sbPtr->DynPtr);
245 			}
246 			break;
247 		}
248 		case I_BehaviourGrenade:
249 		case I_BehaviourProximityGrenade:
250 		{
251 			MakeGrenadeTrailParticles(&(sbPtr->DynPtr->PrevPosition), &(sbPtr->DynPtr->Position));
252 			break;
253 		}
254 		default:
255 			break;
256 	}
257 }
258 
259 
260 /* removes a ghost */
RemoveGhost(STRATEGYBLOCK * sbPtr)261 void RemoveGhost(STRATEGYBLOCK *sbPtr)
262 {
263 	NETGHOSTDATABLOCK *ghostData;
264 
265 	LOCALASSERT(sbPtr);
266 	ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
267 	LOCALASSERT(ghostData);
268 
269 	/* this is where we add fragmentation and explosion	effects to destroyed ghosts */
270 	switch(ghostData->type)
271 	{
272 		case(I_BehaviourAlienPlayer):
273 		case(I_BehaviourMarinePlayer):
274 		case(I_BehaviourPredatorPlayer):
275 		{
276 			Extreme_Gibbing(sbPtr,ghostData->HModelController.section_data,ONE_FIXED);
277 			break;
278 		}
279 		case(I_BehaviourGrenade):
280 		{
281 			if (sbPtr->containingModule) {
282 				Ghost_Explosion_SoundData.position=sbPtr->DynPtr->Position;
283 				Sound_Play(SID_ED_GRENADE_EXPLOSION,"n",&Ghost_Explosion_SoundData);
284 			}
285 			break;
286     	}
287 		case(I_BehaviourRocket):
288 		{
289 			if (sbPtr->containingModule) {
290 				Ghost_Explosion_SoundData.position=sbPtr->DynPtr->Position;
291 				Sound_Play(SID_NICE_EXPLOSION,"n",&Ghost_Explosion_SoundData);
292 			}
293 			break;
294     	}
295 		case(I_BehaviourProximityGrenade):
296 		{
297 			if (sbPtr->containingModule) {
298 				Ghost_Explosion_SoundData.position=sbPtr->DynPtr->Position;
299 				Sound_Play(SID_ED_GRENADE_PROXEXPLOSION,"n",&Ghost_Explosion_SoundData);
300 			}
301 			break;
302     	}
303 		case(I_BehaviourFragmentationGrenade):
304 		case(I_BehaviourClusterGrenade):
305 		{
306 			if (sbPtr->containingModule) {
307 				Ghost_Explosion_SoundData.position=sbPtr->DynPtr->Position;
308 				Sound_Play(SID_NADEEXPLODE,"n",&Ghost_Explosion_SoundData);
309 			}
310 			break;
311     	}
312 		case(I_BehaviourPulseGrenade):
313 		{
314 			if (sbPtr->containingModule) {
315 				Ghost_Explosion_SoundData.position=sbPtr->DynPtr->Position;
316 				Sound_Play(SID_NADEEXPLODE,"n",&Ghost_Explosion_SoundData);
317 			}
318 			break;
319     	}
320 		case(I_BehaviourNPCPredatorDisc):
321 		case(I_BehaviourPredatorDisc_SeekTrack):
322 		{
323 			/* MakeAnExplosion... ?	*/
324 		    Sound_Play(SID_NADEEXPLODE,"d",&(sbPtr->DynPtr->Position));
325 			break;
326 		}
327 		case(I_BehaviourFrisbee):
328 		{
329 			//Ghost_Explosion_SoundData.position=sbPtr->DynPtr->Position;
330 			//Sound_Play(SID_NICE_EXPLOSION,"n",&Ghost_Explosion_SoundData);
331 			break;
332     	}
333 		case (I_BehaviourPPPlasmaBolt) :
334 		{
335 			break;
336 		}
337 
338 
339 		case(I_BehaviourAlienSpit):
340 		{
341 			break;
342 		}
343 		case(I_BehaviourNetCorpse):
344 		{
345 			break;
346 		}
347 		default:
348 		{
349 			/* do absolutely bugger all, probably:
350 			remaining cases are: predator energy bolt;flame;predator disc;flare;
351 			and AUTOGUN */
352 			break;
353 		}
354 	}
355 
356 	/* see if we've got a sound... */
357 	if(ghostData->SoundHandle  != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle);
358 	if(ghostData->SoundHandle2 != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle2);
359 	if(ghostData->SoundHandle3 != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle3);
360 	if(ghostData->SoundHandle4 != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle4);
361 
362 	/* see if we've got a muzzle flash... */
363 	if(ghostData->myGunFlash)
364 	{
365 		RemoveNPCGunFlashEffect(ghostData->myGunFlash);
366 		ghostData->myGunFlash = NULL;
367 	}
368 
369 	DestroyAnyStrategyBlock(sbPtr);
370 }
371 
372 /* removes a given player's ghost, and all associated ghosts, eg when a player
373 leaves the game... */
RemovePlayersGhosts(DPID id)374 void RemovePlayersGhosts(DPID id)
375 {
376 	extern int NumActiveStBlocks;
377 	extern STRATEGYBLOCK *ActiveStBlockList[];
378 
379 	int sbIndex = 0;
380 	STRATEGYBLOCK *sbPtr;
381 
382 	while(sbIndex < NumActiveStBlocks)
383 	{
384 		sbPtr = ActiveStBlockList[sbIndex++];
385 		if(sbPtr->I_SBtype==I_BehaviourNetGhost)
386 		{
387 			NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
388 			LOCALASSERT(ghostData);
389 			if(ghostData->playerId==id) {
390 				RemoveGhost(sbPtr);
391 			}
392 		}
393 	}
394 }
395 
396 
397 /* locates a ghost from Id and ObId */
FindGhost(DPID Id,int obId)398 STRATEGYBLOCK *FindGhost(DPID Id, int obId)
399 {
400 	extern int NumActiveStBlocks;
401 	extern STRATEGYBLOCK *ActiveStBlockList[];
402 
403 	int sbIndex = 0;
404 	STRATEGYBLOCK *sbPtr;
405 
406 	while(sbIndex < NumActiveStBlocks)
407 	{
408 		sbPtr = ActiveStBlockList[sbIndex++];
409 		if(sbPtr->I_SBtype==I_BehaviourNetGhost)
410 		{
411 			NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
412 			LOCALASSERT(ghostData);
413 
414 			if((ghostData->playerId==Id)&&(ghostData->playerObjectId==obId)) return sbPtr;
415 		}
416 	}
417 	return NULL;
418 }
419 
420 /* create a new ghost: doesn't do shape animation stuff: this is performed using a
421 seperate set of functions */
CreateNetGhost(DPID playerId,int objectId,VECTORCH * position,EULER * orientation,AVP_BEHAVIOUR_TYPE type,unsigned char IOType,unsigned char subtype)422 STRATEGYBLOCK *CreateNetGhost(DPID playerId, int objectId, VECTORCH *position, EULER* orientation, AVP_BEHAVIOUR_TYPE type, unsigned char IOType, unsigned char subtype)
423 {
424 	int i;
425 	STRATEGYBLOCK *sbPtr;
426 	MODULE *myContainingModule;
427 
428 	/* first check that the position we've been passed is in a module */
429 	myContainingModule = ModuleFromPosition(position, (MODULE *)0);
430 	if(myContainingModule==NULL) return NULL;
431 
432 	/* create a strategy block */
433 	sbPtr = CreateActiveStrategyBlock();
434 	if(!sbPtr)
435 	{
436 		/* allocation failed */
437 		return NULL;
438 	}
439 	InitialiseSBValues(sbPtr);
440 	sbPtr->I_SBtype = I_BehaviourNetGhost;
441 
442 	for(i = 0; i < SB_NAME_LENGTH; i++) sbPtr->SBname[i] = '\0';
443 	AssignNewSBName(sbPtr);
444 
445 	/* dynamics block */
446 	{
447 		DYNAMICSBLOCK *dynPtr;
448 
449 		/* need different templates for objects and sprites */
450 		#if EXTRAPOLATION_TEST
451 		if(type==I_BehaviourMarinePlayer||type==I_BehaviourAlienPlayer||type==I_BehaviourPredatorPlayer || type==I_BehaviourAlien)
452 		{
453 			dynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_MARINE_PLAYER);
454 			if(type==I_BehaviourAlienPlayer || type==I_BehaviourAlien)
455 			{
456 				dynPtr->ToppleForce=TOPPLE_FORCE_ALIEN;
457 			}
458 		}
459 		else
460 		#endif
461 		{
462 			dynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_NET_GHOST);
463 		}
464 		if(!dynPtr)
465 		{
466 			/* allocation failed */
467 			RemoveBehaviourStrategy(sbPtr);
468 			return NULL;
469 		}
470 
471 		sbPtr->DynPtr = dynPtr;
472 		/* zero linear velocity in dynamics block */
473 		dynPtr->LinVelocity.vx = dynPtr->LinVelocity.vy = dynPtr->LinVelocity.vz = 0;
474 		dynPtr->LinImpulse.vx = dynPtr->LinImpulse.vy = dynPtr->LinImpulse.vz = 0;
475 		dynPtr->GravityOn = 0;
476 
477 		dynPtr->Position = dynPtr->PrevPosition = *position;
478 		dynPtr->OrientEuler = *orientation;
479 		CreateEulerMatrix(&dynPtr->OrientEuler, &dynPtr->OrientMat);
480 		TransposeMatrixCH(&dynPtr->OrientMat);
481 
482 	}
483 
484 	/* data block */
485 	{
486 		NETGHOSTDATABLOCK *ghostData = AllocateMem(sizeof(NETGHOSTDATABLOCK));
487 		if(!ghostData)
488 		{
489 			/* allocation failed */
490 			RemoveBehaviourStrategy(sbPtr);
491 			return NULL;
492 		}
493 		sbPtr->SBdataptr = (void *)ghostData;
494 		ghostData->playerId = playerId;
495 		ghostData->playerObjectId = objectId;
496 		ghostData->type = type;
497 		ghostData->IOType=(INANIMATEOBJECT_TYPE)IOType;
498 		ghostData->subtype=(int)subtype;
499 		ghostData->myGunFlash = NULL;
500 		ghostData->GunFlashFrameStamp=GlobalFrameCounter;
501 		ghostData->SoundHandle  = SOUND_NOACTIVEINDEX;
502 		ghostData->SoundHandle2 = SOUND_NOACTIVEINDEX;
503 		ghostData->SoundHandle3 = SOUND_NOACTIVEINDEX;
504 		ghostData->SoundHandle4 = SOUND_NOACTIVEINDEX;
505 		ghostData->currentAnimSequence = 0;
506 		ghostData->timer = 0;
507 		ghostData->CloakingEffectiveness = 0;
508 		ghostData->IgnitionHandshaking = 0;
509 		ghostData->soundStartFlag = 0;
510 		ghostData->FlameHitCount = 0;
511 		ghostData->FlechetteHitCount = 0;
512 		ghostData->invulnerable=0;
513 		ghostData->onlyValidFar=0;
514 
515 		#if EXTRAPOLATION_TEST
516 		ghostData->velocity.vx=0;
517 		ghostData->velocity.vy=0;
518 		ghostData->velocity.vz=0;
519 		ghostData->extrapTimerLast=0;
520 		ghostData->extrapTimer=0;
521 		#endif
522 
523 		/* Clear HModelController. */
524 		ghostData->HModelController.Seconds_For_Sequence=0;
525 		ghostData->HModelController.timer_increment=0;
526 		ghostData->HModelController.Sequence_Type=0;
527 		ghostData->HModelController.Sub_Sequence=0;
528 		ghostData->HModelController.sequence_timer=0;
529 		ghostData->HModelController.FrameStamp=0;
530 		ghostData->HModelController.keyframe_flags=0;
531 		ghostData->HModelController.Deltas=NULL;
532 		ghostData->HModelController.Root_Section=NULL;
533 		ghostData->HModelController.section_data=NULL;
534 		ghostData->HModelController.After_Tweening_Sequence_Type=0;
535 		ghostData->HModelController.After_Tweening_Sub_Sequence=0;
536 		ghostData->HModelController.AT_seconds_for_sequence=0;
537 		ghostData->HModelController.Playing=0;
538 		ghostData->HModelController.Reversed=0;
539 		ghostData->HModelController.Looped=0;
540 		ghostData->HModelController.Tweening=0;
541 		ghostData->HModelController.LoopAfterTweening=0;
542 		ghostData->HModelController.ElevationTweening=0;
543 		/* Whew. */
544 		ghostData->hltable=0;
545 		/* init the integrity */
546 		ghostData->integrity = GHOST_INTEGRITY;
547 
548  		/* set the shape */
549 		switch(type)
550 		{
551 			case(I_BehaviourMarinePlayer):
552 			{
553 				CreateMarineHModel(ghostData,WEAPON_PULSERIFLE);
554 				ProveHModel_Far(&ghostData->HModelController,sbPtr);
555 				break;
556 			}
557 			case(I_BehaviourAlienPlayer):
558 			{
559 				CreateAlienHModel(ghostData,0);
560 				ProveHModel_Far(&ghostData->HModelController,sbPtr);
561 				break;
562 			}
563  			case(I_BehaviourPredatorPlayer):
564 			{
565 				CreatePredatorHModel(ghostData,WEAPON_PRED_WRISTBLADE);
566 				ProveHModel_Far(&ghostData->HModelController,sbPtr);
567 				break;
568 			}
569 
570 			/* KJL 16:57:14 17/06/98 - NPC characters */
571 			case(I_BehaviourAlien):
572 			{
573 				CreateAlienHModel(ghostData,subtype);
574 
575 				ProveHModel_Far(&ghostData->HModelController,sbPtr);
576 				break;
577 			}
578 
579 
580 			case(I_BehaviourGrenade):
581 			case(I_BehaviourPulseGrenade):
582 				sbPtr->shapeIndex = GetLoadedShapeMSL("Shell");
583 				break;
584 			case(I_BehaviourFragmentationGrenade):
585 				sbPtr->shapeIndex = GetLoadedShapeMSL("Frag");
586 				break;
587 			case(I_BehaviourClusterGrenade):
588 				sbPtr->shapeIndex = GetLoadedShapeMSL("Cluster");
589 				break;
590 			case(I_BehaviourRocket):
591 				sbPtr->shapeIndex = GetLoadedShapeMSL("missile");
592 				break;
593 			case(I_BehaviourPredatorEnergyBolt):
594 				sbPtr->shapeIndex = 0; // uses a special effect
595 				//need to play the energy bolt being fired sound
596 				Sound_Play(SID_PRED_LAUNCHER,"hpd",(FastRandom()&255)-128,&sbPtr->DynPtr->Position);
597 				break;
598 			case(I_BehaviourFrisbeeEnergyBolt):
599 				sbPtr->shapeIndex = 0; // uses a special effect
600 				//need to play the energy bolt being fired sound
601 				Sound_Play(SID_PRED_LAUNCHER,"hpd",(FastRandom()&255)-128,&sbPtr->DynPtr->Position);
602 				break;
603 			case(I_BehaviourPPPlasmaBolt):
604 				sbPtr->shapeIndex = 0; // uses a special effect
605 				break;
606 			case(I_BehaviourNPCPredatorDisc):
607 			case(I_BehaviourPredatorDisc_SeekTrack):
608 				{
609 
610 				SECTION *root_section = GetNamedHierarchyFromLibrary("disk","Disk");
611 
612 				GLOBALASSERT(root_section);
613 
614 				Create_HModel(&ghostData->HModelController,root_section);
615 				InitHModelSequence(&ghostData->HModelController,HMSQT_MarineStand,MSSS_Minigun_Delta,ONE_FIXED);
616 				ProveHModel_Far(&ghostData->HModelController,sbPtr);
617 
618 				/* Just to make sure. */
619 				sbPtr->shapeIndex = GetLoadedShapeMSL("Shell");
620 				break;
621 				}
622 			case(I_BehaviourFrisbee):
623 				{
624 
625 				SECTION *root_section = GetNamedHierarchyFromLibrary("mdisk","Mdisk");
626 
627 				GLOBALASSERT(root_section);
628 
629 				Create_HModel(&ghostData->HModelController,root_section);
630 				InitHModelSequence(&ghostData->HModelController,HMSQT_MarineStand,MSSS_Minigun_Delta,(ONE_FIXED>>1));
631 				ProveHModel_Far(&ghostData->HModelController,sbPtr);
632 
633 				/* Just to make sure. */
634 				sbPtr->shapeIndex = GetLoadedShapeMSL("Shell");
635 
636 				Sound_Play(SID_ED_SKEETERLAUNCH,"hd",&(sbPtr->DynPtr->Position));
637 
638 				break;
639 				}
640 			case(I_BehaviourInanimateObject):
641 			/* That *should* only happen for pred discs at this stage */
642 			//Now there are also weapons that appear when players die
643 				if(IOType==IOT_Weapon)
644 				{
645 					switch(subtype)
646 					{
647 	 					case WEAPON_MARINE_PISTOL:
648 	 					case WEAPON_PULSERIFLE:
649 							sbPtr->shapeIndex=GetLoadedShapeMSL("pulse");
650 							break;
651 						case WEAPON_SMARTGUN:
652 							sbPtr->shapeIndex=GetLoadedShapeMSL("smart");
653 							break;
654 						case WEAPON_FLAMETHROWER:
655 							sbPtr->shapeIndex=GetLoadedShapeMSL("flame");
656 							break;
657 						case WEAPON_SADAR:
658 							sbPtr->shapeIndex=GetLoadedShapeMSL("sadar");
659 							break;
660 						case WEAPON_GRENADELAUNCHER:
661 							sbPtr->shapeIndex=GetLoadedShapeMSL("grenade");
662 							break;
663 						case WEAPON_MINIGUN:
664 							sbPtr->shapeIndex=GetLoadedShapeMSL("minigun");
665 							break;
666 						case WEAPON_FRISBEE_LAUNCHER:
667 							sbPtr->shapeIndex=GetLoadedShapeMSL("sadar");
668 							break;
669 						default :
670 							GLOBALASSERT(0=="Unexpected weapon type");
671 
672 
673 					}
674 					sbPtr->DynPtr->IsPickupObject=1;
675 					GLOBALASSERT(sbPtr->shapeIndex!=-1);
676 
677 				}
678 				else
679 				{
680 					SECTION *disc_section;
681 					SECTION *root_section = GetNamedHierarchyFromLibrary("disk","Disk");
682 
683 					GLOBALASSERT(IOType==IOT_Ammo);
684 					GLOBALASSERT(subtype==AMMO_PRED_DISC);
685 					GLOBALASSERT(root_section);
686 
687 					#if 0
688 					Create_HModel(&ghostData->HModelController,root_section);
689 					InitHModelSequence(&ghostData->HModelController,HMSQT_MarineStand,MSSS_Minigun_Delta,ONE_FIXED);
690 					ProveHModel_Far(&ghostData->HModelController,sbPtr);
691 
692 					/* Just to make sure. */
693 					sbPtr->shapeIndex = GetLoadedShapeMSL("Shell");
694 					#else
695 					/* Now it's not hierarchical! */
696 					disc_section=GetThisSection(root_section,"disk");
697 					GLOBALASSERT(disc_section);
698 
699 					sbPtr->shapeIndex = disc_section->ShapeNum;
700 					#endif
701 				}
702 				break;
703 
704 			case(I_BehaviourFlareGrenade):
705 				sbPtr->shapeIndex = GetLoadedShapeMSL("Flare");
706 				ghostData->timer = FLARE_LIFETIME*ONE_FIXED;
707 				break;
708 			case(I_BehaviourProximityGrenade):
709 				sbPtr->shapeIndex = GetLoadedShapeMSL("Proxmine");
710 				ghostData->timer = PROX_GRENADE_LIFETIME*ONE_FIXED*2;
711 				break;
712 			case(I_BehaviourAlienSpit):
713 				sbPtr->shapeIndex = GetLoadedShapeMSL("Spit");
714 				break;
715 			case(I_BehaviourAutoGun):
716 				sbPtr->shapeIndex = GetLoadedShapeMSL("Sentry01");
717 				break;
718 			case(I_BehaviourSpeargunBolt):
719 				sbPtr->shapeIndex = GetLoadedShapeMSL("spear");
720 				//speargun bolt won't get any location updates , so set integrity
721 				//to be the standard speargun timeout time.
722 				ghostData->integrity = 20*ONE_FIXED;
723 
724 			    //play the sound for the bolt as well
725 			    Sound_Play(SID_SPEARGUN_HITTING_WALL,"d",&sbPtr->DynPtr->Position);
726 				//and make the sparks
727 				{
728 					VECTORCH pos = sbPtr->DynPtr->Position;
729 					pos.vx += sbPtr->DynPtr->OrientMat.mat31;
730 					pos.vy += sbPtr->DynPtr->OrientMat.mat32;
731 					pos.vz += sbPtr->DynPtr->OrientMat.mat33;
732 					MakeFocusedExplosion(&(sbPtr->DynPtr->Position), &pos, 20, PARTICLE_SPARK);
733 				}
734 
735 				break;
736 			default:
737 				break;
738 		}
739 		LOCALASSERT(sbPtr->shapeIndex!=-1);
740 
741 	}
742 
743 	/* strategy block initialisation, after dynamics block creation */
744 	sbPtr->maintainVisibility = 1;
745  	sbPtr->containingModule = myContainingModule;
746 
747  	return sbPtr;
748 }
749 
750 int UseExtrapolation=1;
751 #if EXTRAPOLATION_TEST
PlayerGhostExtrapolation()752 void PlayerGhostExtrapolation()
753 {
754 	extern int NumActiveStBlocks;
755 	extern STRATEGYBLOCK *ActiveStBlockList[];
756 
757 	int sbIndex = 0;
758 	STRATEGYBLOCK *sbPtr;
759 
760 
761 	//search for all ghosts of players
762 	while(sbIndex < NumActiveStBlocks)
763 	{
764 		sbPtr = ActiveStBlockList[sbIndex++];
765 		if(sbPtr->I_SBtype==I_BehaviourNetGhost)
766 		{
767 			NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
768 			if(ghostData->type==I_BehaviourMarinePlayer ||
769 			   ghostData->type==I_BehaviourAlienPlayer ||
770 			   ghostData->type==I_BehaviourAlien ||
771 			   ghostData->type==I_BehaviourPredatorPlayer)
772 			{
773 				int time;
774 				DYNAMICSBLOCK* dynPtr= sbPtr->DynPtr;
775 				if(ghostData->onlyValidFar) continue;
776 
777 				if(UseExtrapolation)
778 				{
779 
780 					dynPtr->LinVelocity.vx=0;
781 					dynPtr->LinVelocity.vy=0;
782 					dynPtr->LinVelocity.vz=0;
783 
784 					dynPtr->IsNetGhost=0;
785 
786 					ghostData->extrapTimer+=NormalFrameTime;
787 					if(ghostData->extrapTimer<0) ghostData->extrapTimer=0;
788 					if(ghostData->extrapTimer>ONE_FIXED/2) ghostData->extrapTimer=ONE_FIXED/2;
789 
790 					time=ghostData->extrapTimer-ghostData->extrapTimerLast;
791 					ghostData->extrapTimerLast=ghostData->extrapTimer;
792 
793 					if(ghostData->velocity.vx==0 && ghostData->velocity.vy==0 && ghostData->velocity.vz==0)
794 					{
795 						/*
796 						Not moving , so alter the dynamics block settings to match those of a non-extrapolated
797 						net ghost.
798 						*/
799 						dynPtr->LinImpulse.vx=0;
800 						dynPtr->LinImpulse.vy=0;
801 						dynPtr->LinImpulse.vz=0;
802 
803 						ghostData->extrapTimerLast=ghostData->extrapTimer=0;
804 						dynPtr->IsNetGhost=1;
805 						dynPtr->UseStandardGravity=1;
806 						sbPtr->DynPtr->ToppleForce=TOPPLE_FORCE_NONE;
807 					}
808 					else if(time>0)
809 					{
810 						dynPtr->LinVelocity=ghostData->velocity;
811 						if(time!=NormalFrameTime)
812 						{
813 							//only doing interpolation for a fraction of a frame
814 							//so we need to scale the velocity accordingly
815 							dynPtr->LinVelocity.vx=WideMulNarrowDiv(dynPtr->LinVelocity.vx,time,NormalFrameTime);
816 							dynPtr->LinVelocity.vy=WideMulNarrowDiv(dynPtr->LinVelocity.vy,time,NormalFrameTime);
817 							dynPtr->LinVelocity.vz=WideMulNarrowDiv(dynPtr->LinVelocity.vz,time,NormalFrameTime);
818 						}
819 					}
820 
821 
822 					/*
823 					if(sbPtr->SBdptr)
824 					{
825 						sbPtr->SBdptr->ObRadius=1200;
826 					}
827 					*/
828 
829 				}
830 				else
831 				{
832 					//not using extrapolation , so make sure dynamics block
833 					//contains normal ghost settings
834 					dynPtr->LinImpulse.vx=0;
835 					dynPtr->LinImpulse.vy=0;
836 					dynPtr->LinImpulse.vz=0;
837 
838 					dynPtr->LinVelocity.vx=0;
839 					dynPtr->LinVelocity.vy=0;
840 					dynPtr->LinVelocity.vz=0;
841 
842 					dynPtr->UseStandardGravity=1;
843 
844 					dynPtr->IsNetGhost=1;
845 
846 				   	sbPtr->DynPtr->ToppleForce=TOPPLE_FORCE_NONE;
847 				}
848 			}
849 		}
850 	}
851 }
852 
PostDynamicsExtrapolationUpdate()853 void PostDynamicsExtrapolationUpdate()
854 {
855 	extern DPID MultiplayerObservedPlayer;
856 	extern int NumActiveStBlocks;
857 	extern STRATEGYBLOCK *ActiveStBlockList[];
858 
859 	int sbIndex = 0;
860 	STRATEGYBLOCK *sbPtr;
861 
862 	if(!UseExtrapolation) return;
863 
864 	//search for all ghosts of players
865 	while(sbIndex < NumActiveStBlocks)
866 	{
867 		sbPtr = ActiveStBlockList[sbIndex++];
868 		if(sbPtr->I_SBtype==I_BehaviourNetGhost)
869 		{
870 			NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
871 			if(ghostData->type==I_BehaviourMarinePlayer ||
872 			   ghostData->type==I_BehaviourAlienPlayer ||
873 			   ghostData->type==I_BehaviourPredatorPlayer)
874 			{
875 				if(ghostData->myGunFlash)
876 				{
877 					HandleGhostGunFlashEffect(sbPtr, 3);
878 				}
879 				//are we currently following this player's movements
880 				if(MultiplayerObservedPlayer)
881 				{
882 					if(MultiplayerObservedPlayer==ghostData->playerId)
883 					{
884 						Player->ObStrategyBlock->DynPtr->Position=sbPtr->DynPtr->Position;
885 						Player->ObStrategyBlock->DynPtr->PrevPosition=sbPtr->DynPtr->Position;
886 
887 						Player->ObStrategyBlock->DynPtr->OrientEuler = sbPtr->DynPtr->OrientEuler;
888 						CreateEulerMatrix(&Player->ObStrategyBlock->DynPtr->OrientEuler,&Player->ObStrategyBlock->DynPtr->OrientMat);
889 						TransposeMatrixCH(&Player->ObStrategyBlock->DynPtr->OrientMat);
890 
891 					}
892 				}
893 			}
894 		}
895 	}
896 }
897 #endif //EXTRAPOLATION_TEST
898 
899 extern HIERARCHY_VARIANT_DATA* GetHierarchyAlternateShapeSetCollectionFromLibrary(const char* rif_name,int index);
ChangeGhostMarineAccoutrementSet(HMODELCONTROLLER * HModelController,DPID playerId)900 void ChangeGhostMarineAccoutrementSet(HMODELCONTROLLER *HModelController,DPID playerId)
901 {
902 
903 	HIERARCHY_VARIANT_DATA* variant_data;
904 	HIERARCHY_SHAPE_REPLACEMENT* replacement_array;
905 	int index=0;
906 	int a;
907 
908 	LOCALASSERT(HModelController);
909 
910 	//find the index for this player
911 	if(playerId)
912 	{
913 		for(index=0;index<(NET_MAXPLAYERS);index++)
914 		{
915 			if(netGameData.playerData[index].playerId==playerId)
916 			{
917 				break;
918 			}
919 		}
920 	}
921 
922 	variant_data=GetHierarchyAlternateShapeSetCollectionFromLibrary("hnpcmarine",index+1);
923 
924 	if (variant_data==NULL) {
925 		return;
926 	}
927 
928 
929 	replacement_array=(HIERARCHY_SHAPE_REPLACEMENT*)variant_data->replacements;
930 
931 	if (replacement_array==NULL) {
932 		return;
933 	}
934 
935 
936 	a=0;
937 
938 	while (replacement_array[a].replaced_section_name!=NULL)
939 	{
940 		SECTION_DATA *target_section;
941 
942 		target_section=GetThisSectionData(HModelController->section_data,
943 			replacement_array[a].replaced_section_name);
944 		if (target_section) {
945 			target_section->Shape=replacement_array[a].replacement_shape;
946 			#if 1
947 			target_section->ShapeNum=replacement_array[a].replacement_shape_index;
948 			#endif
949 
950 			Setup_Texture_Animation_For_Section(target_section);
951 
952 		}
953 		a++;
954 	}
955 
956 }
957 
CreateMarineHModel(NETGHOSTDATABLOCK * ghostDataPtr,int weapon)958 void CreateMarineHModel(NETGHOSTDATABLOCK *ghostDataPtr, int weapon)
959 {
960 	SECTION *root_section;
961 
962 	/* KJL 11:09:14 27/01/98 - pick which model to create based on the character's weapon */
963 	switch (weapon)
964 	{
965 		default:
966 		case WEAPON_PULSERIFLE:
967 		{
968 			root_section = GetNamedHierarchyFromLibrary("hnpcmarine","marine with pulse rifle");
969 			break;
970 		}
971 		case WEAPON_TWO_PISTOLS:
972 		{
973 			root_section = GetNamedHierarchyFromLibrary("hnpcmarine","Two Pistol");
974 			break;
975 		}
976 		case WEAPON_MARINE_PISTOL:
977 		{
978 			root_section = GetNamedHierarchyFromLibrary("hnpcmarine","PISTOL");
979 			break;
980 		}
981 		case WEAPON_FLAMETHROWER:
982 		{
983 			root_section = GetNamedHierarchyFromLibrary("hnpcmarine","marine with flame thrower");
984 			break;
985 		}
986 		case WEAPON_SMARTGUN:
987 		{
988 			root_section = GetNamedHierarchyFromLibrary("hnpcmarine","marine with smart gun");
989 			break;
990 		}
991 		case WEAPON_MINIGUN:
992 		{
993 			root_section = GetNamedHierarchyFromLibrary("hnpcmarine","Marine with Mini Gun");
994 			break;
995 		}
996 		case WEAPON_SADAR:
997 		{
998 			root_section = GetNamedHierarchyFromLibrary("hnpcmarine","marine with SADAR");
999 			break;
1000 		}
1001 		case WEAPON_GRENADELAUNCHER:
1002 		{
1003 			root_section = GetNamedHierarchyFromLibrary("hnpcmarine","marine + grenade launcher");
1004 			break;
1005 		}
1006 		case WEAPON_CUDGEL:
1007 		{
1008 			root_section = GetNamedHierarchyFromLibrary("hnpcmarine","Cudgel");
1009 			break;
1010 		}
1011 		case WEAPON_FRISBEE_LAUNCHER:
1012 		{
1013 			root_section = GetNamedHierarchyFromLibrary("hnpcmarine","skeeter");
1014 			break;
1015 		}
1016 	}
1017 	Create_HModel(&ghostDataPtr->HModelController,root_section);
1018 	ghostDataPtr->CurrentWeapon = weapon;
1019 
1020 	ChangeGhostMarineAccoutrementSet(&ghostDataPtr->HModelController,ghostDataPtr->playerId);
1021 
1022 	/* KJL 11:09:38 27/01/98 - set a default anim sequence to use */
1023 	ghostDataPtr->currentAnimSequence = MSQ_Stand;
1024 	InitHModelSequence(&ghostDataPtr->HModelController,(int)HMSQT_MarineStand,(int)MSSS_Standard,ONE_FIXED);
1025 
1026 	/* KJL 11:09:52 27/01/98 - find the section which hold the muzzle flash data */
1027 	ghostDataPtr->GunflashSectionPtr=GetThisSectionData(ghostDataPtr->HModelController.section_data,"dum flash");
1028 	GLOBALASSERT(ghostDataPtr->GunflashSectionPtr);
1029 
1030 	/* CDF 8/4/98 Elevation Delta Sequence. */
1031 	{
1032 		DELTA_CONTROLLER *delta;
1033 		delta=Add_Delta_Sequence(&ghostDataPtr->HModelController,"Elevation",(int)HMSQT_MarineStand,(int)MSSS_Elevation,0);
1034 		GLOBALASSERT(delta);
1035 		delta->timer=32767;
1036 	}
1037 	//add hit delta
1038 	if (HModelSequence_Exists(&ghostDataPtr->HModelController,(int)HMSQT_MarineStand,(int)MSSS_HitChestFront))
1039 	{
1040 		DELTA_CONTROLLER *delta;
1041 		delta=Add_Delta_Sequence(&ghostDataPtr->HModelController,"HitDelta",(int)HMSQT_MarineStand,(int)MSSS_HitChestFront,(ONE_FIXED>>2));
1042 		GLOBALASSERT(delta);
1043 		delta->Playing=0;
1044 	}
1045 
1046 	ghostDataPtr->hltable=(HITLOCATIONTABLE*)GetThisHitLocationTable("marine with pulse rifle");
1047 
1048 }
CreateAlienHModel(NETGHOSTDATABLOCK * ghostDataPtr,int alienType)1049 void CreateAlienHModel(NETGHOSTDATABLOCK *ghostDataPtr,int alienType)
1050 {
1051 	SECTION *root_section;
1052 
1053 	switch(alienType)
1054 	{
1055 		case AT_Predalien :
1056 			root_section=GetNamedHierarchyFromLibrary("hnpcpred_alien","TEMPLATE");
1057 			ghostDataPtr->hltable=GetThisHitLocationTable("predalien");
1058 			break;
1059 		case AT_Praetorian :
1060 			root_section=GetNamedHierarchyFromLibrary("hnpcpretorian","Template");
1061 			ghostDataPtr->hltable=GetThisHitLocationTable("praetorian");
1062 			break;
1063 		default :
1064 			root_section = GetNamedHierarchyFromLibrary("hnpcalien","alien");
1065 			ghostDataPtr->hltable=GetThisHitLocationTable("alien");
1066 			break;
1067 	}
1068 
1069 
1070 	Create_HModel(&ghostDataPtr->HModelController,root_section);
1071 	ghostDataPtr->currentAnimSequence = ASQ_Stand;
1072 	InitHModelSequence(&ghostDataPtr->HModelController,(int)HMSQT_AlienStand,(int)ASSS_Standard,ONE_FIXED);
1073 
1074 	ghostDataPtr->CurrentWeapon = 0;
1075 
1076 	/* CDF 12/4/98 Elevation Delta Sequence. */
1077 	{
1078 		DELTA_CONTROLLER *delta;
1079 		delta=Add_Delta_Sequence(&ghostDataPtr->HModelController,"Elevation",(int)HMSQT_AlienStand,(int)ASSS_Standard_Elevation,0);
1080 		GLOBALASSERT(delta);
1081 		delta->timer=32767;
1082 
1083 		delta->Active=0; /* Default for predator. */
1084 	}
1085 }
CreatePredatorHModel(NETGHOSTDATABLOCK * ghostDataPtr,int weapon)1086 void CreatePredatorHModel(NETGHOSTDATABLOCK *ghostDataPtr, int weapon)
1087 {
1088 	SECTION *root_section;
1089 	/* KJL 11:09:14 27/01/98 - pick which model to create based on the character's weapon */
1090 	switch (weapon)
1091 	{
1092 		default:
1093 		case WEAPON_PRED_WRISTBLADE:
1094 		{
1095 			root_section = GetNamedHierarchyFromLibrary("hnpcpredator","pred with wristblade");
1096 			break;
1097 		}
1098 		case WEAPON_PRED_STAFF:
1099 		{
1100 			root_section = GetNamedHierarchyFromLibrary("hnpcpredator","pred with staff");
1101 			break;
1102 		}
1103 		case WEAPON_PRED_RIFLE:
1104 		{
1105 			root_section = GetNamedHierarchyFromLibrary("hnpcpredator","Speargun");
1106 			break;
1107 		}
1108 		case WEAPON_PRED_PISTOL:
1109 		{
1110 			root_section = GetNamedHierarchyFromLibrary("hnpcpredator","pred + pistol");
1111 			break;
1112 		}
1113 		case WEAPON_PRED_SHOULDERCANNON:
1114 		{
1115 			root_section = GetNamedHierarchyFromLibrary("hnpcpredator","pred with Plasma Caster");
1116 			break;
1117 		}
1118 		case WEAPON_PRED_DISC:
1119 		{
1120 			root_section = GetNamedHierarchyFromLibrary("hnpcpredator","pred with disk");
1121 			break;
1122 		}
1123 		case WEAPON_PRED_MEDICOMP:
1124 		{
1125 			root_section = GetNamedHierarchyFromLibrary("hnpcpredator","medicomp");
1126 			break;
1127 		}
1128 
1129 		/*
1130 	WEAPON_PRED_RIFLE,
1131 	,
1132 		  */
1133 	}
1134 
1135 	Create_HModel(&ghostDataPtr->HModelController,root_section);
1136 	ghostDataPtr->CurrentWeapon = weapon;
1137 
1138 	GLOBALASSERT(ghostDataPtr->HModelController.Root_Section==root_section);
1139 
1140 	InitHModelSequence(&ghostDataPtr->HModelController,(int)HMSQT_PredatorStand,(int)PSSS_Standard,ONE_FIXED);
1141 	ghostDataPtr->currentAnimSequence = PredSQ_Stand;
1142 
1143 //	ghostDataPtr->GunflashSectionPtr=GetThisSectionData(ghostDataPtr->HModelController.section_data,"dum flash");
1144 //	GLOBALASSERT(ghostDataPtr->GunflashSectionPtr);
1145 
1146 	/* CDF 11/4/98 Elevation Delta Sequence. */
1147 	{
1148 		DELTA_CONTROLLER *delta;
1149 		delta=Add_Delta_Sequence(&ghostDataPtr->HModelController,"Elevation",(int)HMSQT_PredatorStand,(int)PSSS_Elevation,0);
1150 		GLOBALASSERT(delta);
1151 		delta->timer=32767;
1152 
1153 		delta->Active=0; /* Default for predator. */
1154 	}
1155 
1156     if (HModelSequence_Exists(&ghostDataPtr->HModelController,(int)HMSQT_PredatorStand,(int)PSSS_HitChestFront))
1157     {
1158     	DELTA_CONTROLLER *delta;
1159     	delta=Add_Delta_Sequence(&ghostDataPtr->HModelController,"HitDelta",(int)HMSQT_PredatorStand,(int)PSSS_HitChestFront,-1);
1160     	GLOBALASSERT(delta);
1161     	delta->Playing=0;
1162     }
1163 	ghostDataPtr->hltable=GetThisHitLocationTable("predator");
1164 }
1165 
1166 
1167 /* these functions are called directly by the visibility management system */
MakeGhostNear(STRATEGYBLOCK * sbPtr)1168 void MakeGhostNear(STRATEGYBLOCK *sbPtr)
1169 {
1170 	extern MODULEMAPBLOCK AlienDefaultMap;
1171 	NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
1172 	MODULE tempModule;
1173 	DISPLAYBLOCK *dPtr;
1174 	DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
1175 	SFXBLOCK *sfxPtr=0;
1176 
1177 	LOCALASSERT(ghostData);
1178 
1179 	/* KJL 11:56:09 08/05/98 - if shape doesn't exist, use a sfx */
1180 	if ( (ghostData->type==I_BehaviourPredatorEnergyBolt)
1181 	   ||(ghostData->type==I_BehaviourFrisbeeEnergyBolt)
1182 	   ||(ghostData->type==I_BehaviourPPPlasmaBolt) )
1183 	{
1184 		sfxPtr = AllocateSfxBlock();
1185 		// if we haven't got a free sfx block, return */
1186 		if (!sfxPtr) return;
1187 	}
1188 
1189 	if(ghostData->onlyValidFar)
1190 	{
1191 		//Far alien ai , don't have enough information to make it near
1192 		return;
1193 	}
1194 
1195     LOCALASSERT(dynPtr);
1196 	LOCALASSERT(sbPtr->SBdptr == NULL);
1197 
1198 	AlienDefaultMap.MapShape = sbPtr->shapeIndex;
1199 	tempModule.m_mapptr = &AlienDefaultMap;
1200 	tempModule.m_sbptr = (STRATEGYBLOCK*)NULL;
1201 	tempModule.m_numlights = 0;
1202 	tempModule.m_lightarray = (struct lightblock *)0;
1203 	tempModule.m_extraitemdata = (struct extraitemdata *)0;
1204 	tempModule.m_dptr = NULL; /* this is important */
1205 	AllocateModuleObject(&tempModule);
1206 	dPtr = tempModule.m_dptr;
1207 	if(dPtr==NULL) return; /* cannot create displayblock, so leave object "far" */
1208 
1209 
1210 	sbPtr->SBdptr = dPtr;
1211 	dPtr->ObStrategyBlock = sbPtr;
1212 	dPtr->ObMyModule = NULL;
1213 	dPtr->HModelControlBlock=NULL;
1214 
1215 	 /* set the animation sequence, if we're a player ghost */
1216 	if(ghostData->playerObjectId==GHOST_PLAYEROBJECTID)
1217 	{
1218 		LOCALASSERT((ghostData->type == I_BehaviourMarinePlayer)||
1219 					(ghostData->type == I_BehaviourPredatorPlayer)||
1220 					(ghostData->type == I_BehaviourAlienPlayer));
1221 
1222 		dPtr->HModelControlBlock=&ghostData->HModelController;
1223 		ProveHModel(dPtr->HModelControlBlock,dPtr);
1224     }
1225 	else if (
1226 		(ghostData->type == I_BehaviourAlien)||
1227 		(ghostData->type == I_BehaviourPredatorDisc_SeekTrack)||
1228 		(ghostData->type == I_BehaviourFrisbee)||
1229 		(ghostData->type == I_BehaviourNetCorpse)
1230 		) {
1231 		dPtr->HModelControlBlock=&ghostData->HModelController;
1232 		ProveHModel(dPtr->HModelControlBlock,dPtr);
1233 	}
1234 
1235 	else dPtr->ShapeAnimControlBlock = NULL;
1236 
1237 	/* need to initialise positional information in the new display block */
1238 	dPtr->ObWorld = dynPtr->Position;
1239 	dPtr->ObEuler = dynPtr->OrientEuler;
1240 	dPtr->ObMat = dynPtr->OrientMat;
1241 	dPtr->SfxPtr = sfxPtr;
1242 
1243 	/* finally, need to add lighting effects to the displayblock */
1244 	switch(ghostData->type)
1245 	{
1246 		case(I_BehaviourPulseGrenade):
1247 		case(I_BehaviourRocket):
1248 		{
1249 			AddLightingEffectToObject(dPtr,LFX_ROCKETJET);
1250 			break;
1251 		}
1252 		case(I_BehaviourPredatorEnergyBolt):
1253 		{
1254 			sfxPtr->SfxID = SFX_PREDATOR_PLASMA_BOLT;
1255 			AddLightingEffectToObject(dPtr,LFX_PLASMA_BOLT);
1256 			break;
1257 		}
1258 		case(I_BehaviourFrisbeeEnergyBolt):
1259 		{
1260 			sfxPtr->SfxID = SFX_FRISBEE_PLASMA_BOLT;
1261 			AddLightingEffectToObject(dPtr,LFX_PLASMA_BOLT);
1262 			break;
1263 		}
1264 		case(I_BehaviourPPPlasmaBolt):
1265 		{
1266 			sfxPtr->SfxID = SFX_SMALL_PREDATOR_PLASMA_BOLT;
1267 			AddLightingEffectToObject(dPtr,LFX_PLASMA_BOLT);
1268 			break;
1269 		}
1270 
1271 		case(I_BehaviourFlareGrenade):
1272 		{
1273 			AddLightingEffectToObject(dPtr,LFX_FLARE);
1274 
1275 			break;
1276 		}
1277 		default:
1278 			break;
1279 	}
1280 }
1281 
MakeGhostFar(STRATEGYBLOCK * sbPtr)1282 void MakeGhostFar(STRATEGYBLOCK *sbPtr)
1283 {
1284 	int i;
1285 	LOCALASSERT(sbPtr->SBdptr != NULL);
1286 
1287 	/* get rid of the displayblock */
1288 	i = DestroyActiveObject(sbPtr->SBdptr);
1289 	LOCALASSERT(i==0);
1290 	sbPtr->SBdptr = NULL;
1291 }
1292 
1293 /* this function handles damage to a netghost object:
1294 basically, it just sends a network message, which should be picked up by the owning object */
DamageNetworkGhost(STRATEGYBLOCK * sbPtr,DAMAGE_PROFILE * damage,int multiple,SECTION_DATA * section,VECTORCH * incoming)1295 void DamageNetworkGhost(STRATEGYBLOCK *sbPtr, DAMAGE_PROFILE *damage, int multiple, SECTION_DATA *section,VECTORCH* incoming)
1296 {
1297 	int sectionID;
1298 	int delta_seq=-1;
1299 	int delta_sub_seq=-1;
1300 
1301 	LOCALASSERT(AvP.Network!=I_No_Network);
1302 
1303 	if(section)
1304 	{
1305 		//get the appropriate delta sequence
1306 		NETGHOSTDATABLOCK *ghostData;
1307 		int frontback;
1308 		ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
1309 
1310 		if(ghostData->type==I_BehaviourMarinePlayer)
1311 		{
1312 			int CrouchSubSequence;
1313 			int StandSubSequence;
1314 
1315 			if (incoming) {
1316 				if (incoming->vz>=0) {
1317 					frontback=0;
1318 				} else {
1319 					frontback=1;
1320 				}
1321 			} else {
1322 				/* Default to front. */
1323 				frontback=1;
1324 			}
1325 
1326 
1327 			if (section==NULL)
1328 			{
1329 				if (frontback==0)
1330 				{
1331 					CrouchSubSequence=MCrSS_HitChestBack;
1332 					StandSubSequence=MSSS_HitChestBack;
1333 				}
1334 				else
1335 				{
1336 					CrouchSubSequence=MCrSS_HitChestFront;
1337 					StandSubSequence=MSSS_HitChestFront;
1338 				}
1339 			} else if (section->sempai->flags&section_flag_head)
1340 			{
1341 				if (frontback==0)
1342 				{
1343 					CrouchSubSequence=MCrSS_HitHeadBack;
1344 					StandSubSequence=MSSS_HitHeadBack;
1345 				}
1346 				else
1347 				{
1348 					CrouchSubSequence=MCrSS_HitHeadFront;
1349 					StandSubSequence=MSSS_HitHeadFront;
1350 				}
1351 			} else if ((section->sempai->flags&section_flag_left_arm)
1352 				||(section->sempai->flags&section_flag_left_hand))
1353 			{
1354 				if (frontback==0)
1355 				{
1356 					CrouchSubSequence=MCrSS_HitRightArm;
1357 					StandSubSequence=MSSS_HitRightArm;
1358 				}
1359 				else
1360 				{
1361 					CrouchSubSequence=MCrSS_HitLeftArm;
1362 					StandSubSequence=MSSS_HitLeftArm;
1363 				}
1364 			} else if ((section->sempai->flags&section_flag_right_arm)
1365 				||(section->sempai->flags&section_flag_right_hand))
1366 			{
1367 				if (frontback==0)
1368 				{
1369 					CrouchSubSequence=MCrSS_HitLeftArm;
1370 					StandSubSequence=MSSS_HitLeftArm;
1371 				}
1372 				else
1373 				{
1374 				 	CrouchSubSequence=MCrSS_HitRightArm;
1375 				 	StandSubSequence=MSSS_HitRightArm;
1376 				}
1377 
1378 			} else if ((section->sempai->flags&section_flag_left_leg)
1379 				||(section->sempai->flags&section_flag_left_foot))
1380 			{
1381 				CrouchSubSequence=MCrSS_HitLeftLeg;
1382 				StandSubSequence=MSSS_HitLeftLeg;
1383 
1384 			} else if ((section->sempai->flags&section_flag_right_leg)
1385 				||(section->sempai->flags&section_flag_right_foot))
1386 			{
1387 				CrouchSubSequence=MCrSS_HitRightLeg;
1388 				StandSubSequence=MSSS_HitRightLeg;
1389 
1390 			} else {
1391 				/* Chest or misc. hit. */
1392 				if (frontback==0) {
1393 					CrouchSubSequence=MCrSS_HitChestBack;
1394 					StandSubSequence=MSSS_HitChestBack;
1395 				} else {
1396 					CrouchSubSequence=MCrSS_HitChestFront;
1397 					StandSubSequence=MSSS_HitChestFront;
1398 				}
1399 			}
1400 
1401 			if(ghostData->currentAnimSequence==MSQ_Crawl ||
1402 			   ghostData->currentAnimSequence==MSQ_Crawl_Backwards ||
1403 			   ghostData->currentAnimSequence==MSQ_Crouch)
1404 			{
1405 				delta_seq=(int)HMSQT_MarineCrouch;
1406 				delta_sub_seq=(int)CrouchSubSequence;
1407 			}
1408 			else
1409 			{
1410 				delta_seq=(int)HMSQT_MarineStand;
1411 				delta_sub_seq=(int)StandSubSequence;
1412 			}
1413 
1414 			PlayHitDeltaOnGhost(sbPtr,delta_seq,delta_sub_seq);
1415 		}
1416 		else if(ghostData->type==I_BehaviourPredatorPlayer)
1417 		{
1418 			int CrouchSubSequence;
1419 			int StandSubSequence;
1420 
1421 			if (incoming) {
1422 				if (incoming->vz>=0) {
1423 					frontback=0;
1424 				} else {
1425 					frontback=1;
1426 				}
1427 			} else {
1428 				/* Default to front. */
1429 				frontback=1;
1430 			}
1431 
1432             if (section==NULL)
1433             {
1434             	if (frontback==0)
1435             	{
1436                 	CrouchSubSequence=PCrSS_HitChestBack;
1437                 	StandSubSequence=PSSS_HitChestBack;
1438                 }
1439                 else
1440                 {
1441                 	CrouchSubSequence=PCrSS_HitChestFront;
1442                 	StandSubSequence=PSSS_HitChestFront;
1443                 }
1444             } else if (section->sempai->flags&section_flag_head)
1445             {
1446             	if (frontback==0)
1447             	{
1448                 	CrouchSubSequence=PCrSS_HitHeadBack;
1449                 	StandSubSequence=PSSS_HitHeadBack;
1450                 }
1451                 else
1452                 {
1453                 	CrouchSubSequence=PCrSS_HitHeadFront;
1454                 	StandSubSequence=PSSS_HitHeadFront;
1455                 }
1456             } else if ((section->sempai->flags&section_flag_left_arm)
1457             	||(section->sempai->flags&section_flag_left_hand))
1458             {
1459             	if (frontback==0)
1460             	{
1461             		CrouchSubSequence=PCrSS_HitRightArm;
1462             		StandSubSequence=PSSS_HitRightArm;
1463 				}
1464 				else
1465 				{
1466             		CrouchSubSequence=PCrSS_HitLeftArm;
1467             		StandSubSequence=PSSS_HitLeftArm;
1468 				}
1469 
1470             } else if ((section->sempai->flags&section_flag_right_arm)
1471             	||(section->sempai->flags&section_flag_right_hand))
1472             {
1473             	if (frontback==0)
1474 				{
1475             	   	CrouchSubSequence=PCrSS_HitLeftArm;
1476             		StandSubSequence=PSSS_HitLeftArm;
1477 				}
1478 				else
1479 				{
1480             	   	CrouchSubSequence=PCrSS_HitRightArm;
1481             		StandSubSequence=PSSS_HitRightArm;
1482 				}
1483 
1484             } else if ((section->sempai->flags&section_flag_left_leg)
1485             	||(section->sempai->flags&section_flag_left_foot)) {
1486            		CrouchSubSequence=PCrSS_HitLeftLeg;
1487            		StandSubSequence=PSSS_HitLeftLeg;
1488 
1489             } else if ((section->sempai->flags&section_flag_right_leg)
1490             	||(section->sempai->flags&section_flag_right_foot)) {
1491            		CrouchSubSequence=PCrSS_HitRightLeg;
1492            		StandSubSequence=PSSS_HitRightLeg;
1493             } else {
1494                     /* Chest or misc. hit. */
1495            		if (frontback==0) {
1496            			CrouchSubSequence=PCrSS_HitChestBack;
1497            			StandSubSequence=PSSS_HitChestBack;
1498            		} else {
1499            			CrouchSubSequence=PCrSS_HitChestFront;
1500            			StandSubSequence=PSSS_HitChestFront;
1501            		}
1502             }
1503 
1504 
1505 			if(ghostData->currentAnimSequence==PredSQ_Crawl ||
1506 			   ghostData->currentAnimSequence==PredSQ_Crawl_Backwards ||
1507 			   ghostData->currentAnimSequence==PredSQ_Crouch ||
1508 			   ghostData->currentAnimSequence==PredSQ_CrouchedSwipe ||
1509 			   ghostData->currentAnimSequence==PredSQ_CrawlingSwipe ||
1510 			   ghostData->currentAnimSequence==PredSQ_CrawlingSwipe_Backwards)
1511 
1512 			{
1513 				delta_seq=(int)HMSQT_PredatorCrouch;
1514 				delta_sub_seq=(int)CrouchSubSequence;
1515 			}
1516 			else
1517 			{
1518 				delta_seq=(int)HMSQT_PredatorStand;
1519 				delta_sub_seq=(int)StandSubSequence;
1520 			}
1521 
1522 			PlayHitDeltaOnGhost(sbPtr,delta_seq,delta_sub_seq);
1523 
1524 		}
1525 
1526 	}
1527 
1528 	if (section) {
1529 		sectionID=section->sempai->IDnumber;
1530 	} else {
1531 		sectionID=-1;
1532 	}
1533 	AddNetMsg_LocalObjectDamaged(sbPtr, damage, multiple,sectionID,delta_seq,delta_sub_seq,incoming);
1534 }
1535 
1536 /* This function maintains a player ghost's gunflash effect, and is called from
1537 processmsg_playerstate(). It maintains the ghost given by index, and takes as a
1538 parameter the state of the net-player's muzzle flash, as indicated in the last
1539 network message.  It */
HandleGhostGunFlashEffect(STRATEGYBLOCK * sbPtr,int gunFlashOn)1540 void HandleGhostGunFlashEffect(STRATEGYBLOCK *sbPtr, int gunFlashOn)
1541 {
1542 	NETGHOSTDATABLOCK *ghostData;
1543 
1544 	LOCALASSERT(sbPtr);
1545 	ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
1546 	LOCALASSERT(ghostData);
1547 
1548 	/* aliens shouldn't have gun flashes */
1549 	if((ghostData->type == I_BehaviourAlienPlayer)
1550 	 ||(ghostData->type == I_BehaviourPredatorPlayer))
1551 	{
1552 		ghostData->myGunFlash = NULL;
1553 		return;
1554 	}
1555 
1556 	LOCALASSERT((ghostData->type == I_BehaviourMarinePlayer)||
1557 				(ghostData->type == I_BehaviourPredatorPlayer));
1558 
1559 	//ReleasePrintDebuggingText("Muzzle Flash %d\n",gunFlashOn);
1560 
1561 	/* Handle two pistols? */
1562 	if (ghostData->type == I_BehaviourMarinePlayer) {
1563 		if (gunFlashOn==2) {
1564 			ghostData->GunflashSectionPtr=GetThisSectionData(ghostData->HModelController.section_data,"dum L flash");
1565 			if (ghostData->GunflashSectionPtr==NULL) {
1566 				ghostData->GunflashSectionPtr=GetThisSectionData(ghostData->HModelController.section_data,"dum flash");
1567 			}
1568 		} else if (gunFlashOn==1) {
1569 			ghostData->GunflashSectionPtr=GetThisSectionData(ghostData->HModelController.section_data,"dum flash");
1570 		} else if (gunFlashOn==3) {
1571 			/* Extrapolation. */
1572 		}
1573 	}
1574 
1575 	if(ghostData->myGunFlash)
1576 	{
1577 		/* I've already got a gun flash... */
1578 		if(gunFlashOn)
1579 		{
1580 			/* Maintain existing gun flash */
1581 			LOCALASSERT(ghostData->GunflashSectionPtr);
1582 
1583 			if (sbPtr->SBdptr)
1584 			{
1585 				ProveHModel(&ghostData->HModelController,sbPtr->SBdptr);
1586 				MaintainNPCGunFlashEffect
1587 				(
1588 					ghostData->myGunFlash,
1589 					&ghostData->GunflashSectionPtr->World_Offset,
1590 					&ghostData->GunflashSectionPtr->SecMat
1591 				);
1592 			}
1593 		}
1594 		else
1595 		{
1596 			if (ghostData->GunFlashFrameStamp!=GlobalFrameCounter) {
1597 				/* Maintain for at least one frame. */
1598 				RemoveNPCGunFlashEffect(ghostData->myGunFlash);
1599 				ghostData->myGunFlash = NULL;
1600 			}
1601 		}
1602 	}
1603 	else
1604 	{
1605 		if(gunFlashOn)
1606 		{
1607 			/* new flash */
1608 			LOCALASSERT(ghostData->GunflashSectionPtr);
1609 			ghostData->GunFlashFrameStamp=GlobalFrameCounter;
1610 	 		if (sbPtr->SBdptr)
1611 	 		{
1612 			 	ProveHModel(&ghostData->HModelController,sbPtr->SBdptr);
1613 
1614 				if (ghostData->CurrentWeapon==WEAPON_SMARTGUN)
1615 				{
1616 					ghostData->myGunFlash = AddNPCGunFlashEffect
1617 					(
1618 						&ghostData->GunflashSectionPtr->World_Offset,
1619 						&ghostData->GunflashSectionPtr->SecMat,
1620 						SFX_MUZZLE_FLASH_SMARTGUN
1621 					);
1622 				}
1623 				else if (ghostData->CurrentWeapon==WEAPON_FRISBEE_LAUNCHER)
1624 				{
1625 					ghostData->myGunFlash = AddNPCGunFlashEffect
1626 					(
1627 						&ghostData->GunflashSectionPtr->World_Offset,
1628 						&ghostData->GunflashSectionPtr->SecMat,
1629 						SFX_MUZZLE_FLASH_SKEETER
1630 					);
1631 				}
1632 				else
1633 				{
1634 					ghostData->myGunFlash = AddNPCGunFlashEffect
1635 					(
1636 						&ghostData->GunflashSectionPtr->World_Offset,
1637 						&ghostData->GunflashSectionPtr->SecMat,
1638 						SFX_MUZZLE_FLASH_AMORPHOUS
1639 					);
1640 				}
1641 			}
1642 		}
1643 	}
1644 	#if 0
1645 	/* KJL 15:32:57 13/05/98 - Tracer code - isn't working too well */
1646 	if(ghostData->GunflashSectionPtr && !(FastRandom()&15))
1647 	{
1648 		VECTORCH endPosition = ghostData->GunflashSectionPtr->World_Offset;
1649 		endPosition.vx += ghostData->GunflashSectionPtr->SecMat.mat31>>3;
1650 		endPosition.vy += ghostData->GunflashSectionPtr->SecMat.mat32>>3;
1651 		endPosition.vz += ghostData->GunflashSectionPtr->SecMat.mat33>>3;
1652 		MakeParticle(&(ghostData->GunflashSectionPtr->World_Offset),&endPosition,PARTICLE_TRACER);
1653 	}
1654 	#endif
1655 
1656 }
1657 
1658 
1659 /* Patrick 14/7/97 -----------------------------------------------------------
1660 Shape animation control functions for player ghosts:
1661 
1662 Init initilaises the character sequence, and should only be called when a new
1663 player ghost is created, after the sb and datablock have been set up.
1664 
1665 Update changes the sequence if appropriate (and calls set if the sbPtr has a dptr)
1666 
1667 Set selects the correct sequence/type, infers the speed and follow-on sequences,
1668 etc, and sets it.
1669 ------------------------------------------------------------------------------*/
1670 #if 0
1671 static void InitPlayerGhostAnimSequence(STRATEGYBLOCK *sbPtr)
1672 {
1673 	NETGHOSTDATABLOCK *ghostData;
1674 	AVP_BEHAVIOUR_TYPE type;
1675 
1676 	LOCALASSERT(sbPtr);
1677 	LOCALASSERT(!(sbPtr->SBdptr));
1678 	ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
1679 	LOCALASSERT(ghostData);
1680 	type = ghostData->type;
1681 
1682 	InitShapeAnimationController(&ghostData->ShpAnimCtrl, GetShapeData(sbPtr->shapeIndex));
1683 	switch(type)
1684 	{
1685 		case(I_BehaviourMarinePlayer):
1686 		{
1687 			ghostData->currentAnimSequence = MSQ_Stand;
1688 			break;
1689 		}
1690 		case(I_BehaviourAlienPlayer):
1691 		{
1692 			ghostData->currentAnimSequence = ASQ_Stand;
1693 			break;
1694 		}
1695 		case(I_BehaviourPredatorPlayer):
1696 		{
1697 			ghostData->currentAnimSequence = PredSQ_Stand;
1698 			break;
1699 		}
1700 		default:
1701 		{
1702 			LOCALASSERT(1==0);
1703 			break;
1704 		}
1705 	}
1706 }
1707 #endif
1708 
UpdatePlayerGhostAnimSequence(STRATEGYBLOCK * sbPtr,int sequence,int special)1709 static void UpdatePlayerGhostAnimSequence(STRATEGYBLOCK *sbPtr, int sequence, int special)
1710 {
1711 	NETGHOSTDATABLOCK *ghostData;
1712 
1713 	LOCALASSERT(sbPtr);
1714 	ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
1715 	LOCALASSERT(ghostData);
1716 
1717 	switch(ghostData->type)
1718 	{
1719 		case(I_BehaviourMarinePlayer):
1720 		{
1721 			//ReleasePrintDebuggingText("Update Marine with Special %d\n",special);
1722 			/* if the current sequence is the same as the new sequence, do nothing */
1723 			if (((MARINE_SEQUENCE)ghostData->currentAnimSequence == (MARINE_SEQUENCE)sequence)
1724 				&&(ghostData->CurrentWeapon!=WEAPON_TWO_PISTOLS)
1725 				&&(!((ghostData->CurrentWeapon==WEAPON_MARINE_PISTOL)&&(special)))
1726 				) {
1727 				return;
1728 			}
1729 			/* if we're dead, and passed dying, do nothing */
1730 			if(((MARINE_SEQUENCE)ghostData->currentAnimSequence == MSQ_StandDeadFront)&&
1731 			   ((MARINE_SEQUENCE)sequence == MSQ_StandDieFront)) return;
1732 			if(((MARINE_SEQUENCE)ghostData->currentAnimSequence == MSQ_CrouchDead)&&
1733 			   ((MARINE_SEQUENCE)sequence == MSQ_CrouchDie)) return;
1734 			/* need to update the anim sequence, then*/
1735 			SetPlayerGhostAnimationSequence(sbPtr, sequence, special);
1736 			break;
1737 		}
1738 		case(I_BehaviourAlienPlayer):
1739 		{
1740 			/* if the current sequence is the same as the new sequence, do nothing */
1741 			if(!HModelAnimation_IsFinished(&ghostData->HModelController))
1742 			{
1743 				if((ALIEN_SEQUENCE)ghostData->currentAnimSequence == (ALIEN_SEQUENCE)sequence)
1744 				{
1745 					if(ghostData->currentAnimSequence==ASQ_RunningAttack_Claw ||
1746 					   ghostData->currentAnimSequence==ASQ_RunningTailStrike ||
1747 					   ghostData->currentAnimSequence==ASQ_RunningAttack_Claw_Backwards ||
1748 					   ghostData->currentAnimSequence==ASQ_RunningTailStrike_Backwards ||
1749 					   ghostData->currentAnimSequence==ASQ_CrawlingAttack_Claw ||
1750 					   ghostData->currentAnimSequence==ASQ_CrawlingAttack_Claw_Backwards ||
1751 					   ghostData->currentAnimSequence==ASQ_CrawlingTailStrike ||
1752 					   ghostData->currentAnimSequence==ASQ_CrawlingTailStrike_Backwards)
1753 					{
1754 						ghostData->HModelController.Looped=1;
1755 						ghostData->HModelController.LoopAfterTweening=1;
1756 					}
1757 
1758 					#if 0
1759 					if(ghostData->currentAnimSequence==ASQ_RunningAttack_Claw ||
1760 					   ghostData->currentAnimSequence==ASQ_RunningTailStrike ||
1761 					   ghostData->currentAnimSequence==ASQ_RunningAttack_Claw_Backwards ||
1762 					   ghostData->currentAnimSequence==ASQ_RunningTailStrike_Backwards ||
1763 					   ghostData->currentAnimSequence==ASQ_CrawlingAttack_Claw ||
1764 					   ghostData->currentAnimSequence==ASQ_CrawlingAttack_Claw_Backwards ||
1765 					   ghostData->currentAnimSequence==ASQ_CrawlingTailStrike ||
1766 					   ghostData->currentAnimSequence==ASQ_CrawlingTailStrike_Backwards ||
1767 					   ghostData->currentAnimSequence==ASQ_Run ||
1768 					   ghostData->currentAnimSequence==ASQ_RunningTailPoise ||
1769 					   ghostData->currentAnimSequence==ASQ_Run_Backwards ||
1770 					   ghostData->currentAnimSequence==ASQ_RunningTailPoise_Backwards ||
1771 					   ghostData->currentAnimSequence==ASQ_Crawl ||
1772 					   ghostData->currentAnimSequence==ASQ_Scamper ||
1773 					   ghostData->currentAnimSequence==ASQ_CrawlingTailPoise ||
1774 					   ghostData->currentAnimSequence==ASQ_Crawl_Backwards ||
1775 					   ghostData->currentAnimSequence==ASQ_Scamper_Backwards ||
1776 					   ghostData->currentAnimSequence==ASQ_CrawlingTailPoise_Backwards)
1777 
1778 					{
1779 						if(ghostData->HModelController.Tweening==Controller_NoTweening)
1780 						{
1781 							HModel_SetToolsRelativeSpeed(&ghostData->HModelController,(512*ONE_FIXED)/18000/*ALIEN_MOVESCALE*/);
1782 						}
1783 					}
1784 					#endif
1785 
1786 
1787 					return;
1788 				}
1789 			}
1790 			/* need to update the anim sequence, then*/
1791 			SetPlayerGhostAnimationSequence(sbPtr, sequence, special);
1792 			break;
1793 		}
1794 		case(I_BehaviourPredatorPlayer):
1795 		{
1796 			/* if the current sequence is the same as the new sequence, do nothing */
1797 			if(!HModelAnimation_IsFinished(&ghostData->HModelController))
1798 			{
1799 				if(ghostData->currentAnimSequence == sequence)
1800 				{
1801 					if(ghostData->currentAnimSequence==PredSQ_RunningSwipe ||
1802 					   ghostData->currentAnimSequence==PredSQ_RunningSwipe_Backwards ||
1803 					   ghostData->currentAnimSequence==PredSQ_CrawlingSwipe ||
1804 					   ghostData->currentAnimSequence==PredSQ_CrawlingSwipe_Backwards)
1805 					{
1806 						ghostData->HModelController.Looped=1;
1807 						ghostData->HModelController.LoopAfterTweening=1;
1808 					}
1809 					return;
1810 				}
1811 			}
1812 			/* if we're dead, and passed dying, do nothing */
1813 			if(((PREDATOR_SEQUENCE)ghostData->currentAnimSequence == PredSQ_StandDead)&&
1814 			   ((PREDATOR_SEQUENCE)sequence == PredSQ_StandDie)) return;
1815 			if(((PREDATOR_SEQUENCE)ghostData->currentAnimSequence == PredSQ_CrouchDead)&&
1816 			   ((PREDATOR_SEQUENCE)sequence == PredSQ_CrouchDie)) return;
1817 			/* need to update the anim sequence, then*/
1818 			SetPlayerGhostAnimationSequence(sbPtr, sequence, special);
1819 			break;
1820 		}
1821 
1822 		case(I_BehaviourAlien):
1823 		{
1824 			/* if the current sequence is the same as the new sequence, do nothing */
1825 
1826 			if(ghostData->currentAnimSequence == sequence) return;
1827 
1828 			/* need to update the anim sequence, then*/
1829 			SetPlayerGhostAnimationSequence(sbPtr, sequence, special);
1830 			break;
1831 		}
1832 
1833 
1834 		default:
1835 		{
1836 			LOCALASSERT(1==0);
1837 			break;
1838 		}
1839 	}
1840 }
1841 
SetPlayerGhostAnimationSequence(STRATEGYBLOCK * sbPtr,int sequence,int special)1842 static void SetPlayerGhostAnimationSequence(STRATEGYBLOCK *sbPtr, int sequence, int special)
1843 {
1844 	NETGHOSTDATABLOCK *ghostData;
1845 	AVP_BEHAVIOUR_TYPE type;
1846 
1847 	DELTA_CONTROLLER *FireLeft,*FireRight;
1848 
1849 	LOCALASSERT(sbPtr);
1850 	ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
1851 	LOCALASSERT(ghostData);
1852 	type = ghostData->type;
1853 
1854 	if(!(sbPtr->SBdptr))
1855 	{
1856 		/* update the ghost's current sequence: do this even if we don't have a displayblock */
1857 		ghostData->currentAnimSequence = sequence;
1858 		return; /* no displayblock: can't actually set it */
1859 	}
1860 
1861 	switch(type)
1862 	{
1863 		case(I_BehaviourMarinePlayer):
1864 		{
1865 			switch((MARINE_SEQUENCE)sequence)
1866 			{
1867 				case(MSQ_Walk):
1868 				{
1869 					if (ghostData->CurrentWeapon==WEAPON_SMARTGUN) {
1870 						InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Attack_Primary,(ONE_FIXED>>1),1);
1871 					} else if (ghostData->CurrentWeapon==WEAPON_MARINE_PISTOL) {
1872 						InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Attack_Primary,(ONE_FIXED>>1),1);
1873 					} else if (ghostData->CurrentWeapon==WEAPON_TWO_PISTOLS) {
1874 						/* Oh, no. */
1875 						if (special) {
1876 							if ((ghostData->HModelController.Sequence_Type!=(int)HMSQT_MarineRun)||(ghostData->HModelController.Sub_Sequence!=MRSS_Fire_From_Hips)) {
1877 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Fire_From_Hips,(ONE_FIXED>>1),1);
1878 							}
1879 						} else {
1880 							if ((ghostData->HModelController.Sequence_Type!=(int)HMSQT_MarineRun)||(ghostData->HModelController.Sub_Sequence!=MRSS_Standard)) {
1881 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Standard,(ONE_FIXED>>1),1);
1882 							}
1883 						}
1884 					} else {
1885 						InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Standard,(ONE_FIXED>>1),1);
1886 					}
1887 					break;
1888 				}
1889 				case(MSQ_Walk_Backwards):
1890 				{
1891 					if (ghostData->CurrentWeapon==WEAPON_SMARTGUN) {
1892 						InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineRun,(int)MRSS_Attack_Primary,(ONE_FIXED>>1));
1893 					} else if (ghostData->CurrentWeapon==WEAPON_MARINE_PISTOL) {
1894 						InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineRun,(int)MRSS_Attack_Primary,(ONE_FIXED>>1));
1895 					} else if (ghostData->CurrentWeapon==WEAPON_TWO_PISTOLS) {
1896 						/* Oh, no. */
1897 						if (special) {
1898 							if ((ghostData->HModelController.Sequence_Type!=(int)HMSQT_MarineRun)||(ghostData->HModelController.Sub_Sequence!=MRSS_Fire_From_Hips)) {
1899 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Fire_From_Hips,(ONE_FIXED>>1),1);
1900 							}
1901 						} else {
1902 							if ((ghostData->HModelController.Sequence_Type!=(int)HMSQT_MarineRun)||(ghostData->HModelController.Sub_Sequence!=MRSS_Standard)) {
1903 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Standard,(ONE_FIXED>>1),1);
1904 							}
1905 						}
1906 					} else {
1907 						InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineRun,(int)MRSS_Standard,(ONE_FIXED>>1));
1908 					}
1909 					ghostData->HModelController.Reversed=1;
1910 					break;
1911 				}
1912 				case(MSQ_RunningFire):
1913 				{
1914 					if (ghostData->CurrentWeapon==WEAPON_MARINE_PISTOL) {
1915 						InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineRun,(int)MRSS_Attack_Primary,(ONE_FIXED>>1));
1916 					} else if (ghostData->CurrentWeapon==WEAPON_TWO_PISTOLS) {
1917 
1918 						FireRight=Get_Delta_Sequence(&ghostData->HModelController,"FireRight");
1919 						if (FireRight==NULL) {
1920 							FireRight=Add_Delta_Sequence(&ghostData->HModelController,"FireRight",HMSQT_MarineStand,MSSS_Attack_Primary,ONE_FIXED);
1921 							FireRight->Playing=0;
1922 							FireRight->Active=0;
1923 						}
1924 
1925 						FireLeft=Get_Delta_Sequence(&ghostData->HModelController,"FireLeft");
1926 						if (FireLeft==NULL) {
1927 							FireLeft=Add_Delta_Sequence(&ghostData->HModelController,"FireLeft",HMSQT_MarineStand,MSSS_Attack_Secondary,ONE_FIXED);
1928 							FireLeft->Playing=0;
1929 							FireLeft->Active=0;
1930 						}
1931 
1932 						if (special) {
1933 							if ((ghostData->HModelController.Sequence_Type!=(int)HMSQT_MarineRun)||(ghostData->HModelController.Sub_Sequence!=MRSS_Fire_From_Hips)) {
1934 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Fire_From_Hips,(ONE_FIXED>>1),1);
1935 							}
1936 						} else {
1937 							if ((ghostData->HModelController.Sequence_Type!=(int)HMSQT_MarineRun)||(ghostData->HModelController.Sub_Sequence!=MRSS_Standard)) {
1938 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Standard,(ONE_FIXED>>1),1);
1939 							}
1940 						}
1941 
1942 						Start_Delta_Sequence(FireRight,HMSQT_MarineStand,MSSS_Attack_Primary,-1);
1943 						FireRight->Playing=1;
1944 						FireRight->Active=1;
1945 
1946 					} else {
1947 						InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineRun,(int)MRSS_Attack_Primary,(ONE_FIXED>>1));
1948 					}
1949 					break;
1950 				}
1951 				case(MSQ_RunningFireSecondary):
1952 				{
1953 					if (ghostData->CurrentWeapon==WEAPON_MARINE_PISTOL) {
1954 						InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineRun,(int)MRSS_Attack_Primary,(ONE_FIXED>>1));
1955 					} else if (ghostData->CurrentWeapon==WEAPON_TWO_PISTOLS) {
1956 
1957 						FireRight=Get_Delta_Sequence(&ghostData->HModelController,"FireRight");
1958 						if (FireRight==NULL) {
1959 							FireRight=Add_Delta_Sequence(&ghostData->HModelController,"FireRight",HMSQT_MarineStand,MSSS_Attack_Primary,ONE_FIXED);
1960 							FireRight->Playing=0;
1961 							FireRight->Active=0;
1962 						}
1963 
1964 						FireLeft=Get_Delta_Sequence(&ghostData->HModelController,"FireLeft");
1965 						if (FireLeft==NULL) {
1966 							FireLeft=Add_Delta_Sequence(&ghostData->HModelController,"FireLeft",HMSQT_MarineStand,MSSS_Attack_Secondary,ONE_FIXED);
1967 							FireLeft->Playing=0;
1968 							FireLeft->Active=0;
1969 						}
1970 
1971 						if (special) {
1972 							if ((ghostData->HModelController.Sequence_Type!=(int)HMSQT_MarineRun)||(ghostData->HModelController.Sub_Sequence!=MRSS_Fire_From_Hips)) {
1973 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Fire_From_Hips,(ONE_FIXED>>1),1);
1974 							}
1975 						} else {
1976 							if ((ghostData->HModelController.Sequence_Type!=(int)HMSQT_MarineRun)||(ghostData->HModelController.Sub_Sequence!=MRSS_Standard)) {
1977 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Standard,(ONE_FIXED>>1),1);
1978 							}
1979 						}
1980 
1981 						Start_Delta_Sequence(FireLeft,HMSQT_MarineStand,MSSS_Attack_Secondary,-1);
1982 						FireLeft->Playing=1;
1983 						FireLeft->Active=1;
1984 
1985 					} else {
1986 						InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineRun,(int)MRSS_Attack_Primary,(ONE_FIXED>>1));
1987 					}
1988 					break;
1989 				}
1990 				case(MSQ_RunningFire_Backwards):
1991 				{
1992 					if (ghostData->CurrentWeapon==WEAPON_MARINE_PISTOL) {
1993 						InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineRun,(int)MRSS_Attack_Primary,(ONE_FIXED>>1));
1994 						ghostData->HModelController.Reversed=1;
1995 					} else if (ghostData->CurrentWeapon==WEAPON_TWO_PISTOLS) {
1996 
1997 						FireRight=Get_Delta_Sequence(&ghostData->HModelController,"FireRight");
1998 						if (FireRight==NULL) {
1999 							FireRight=Add_Delta_Sequence(&ghostData->HModelController,"FireRight",HMSQT_MarineStand,MSSS_Attack_Primary,ONE_FIXED);
2000 							FireRight->Playing=0;
2001 							FireRight->Active=0;
2002 						}
2003 
2004 						FireLeft=Get_Delta_Sequence(&ghostData->HModelController,"FireLeft");
2005 						if (FireLeft==NULL) {
2006 							FireLeft=Add_Delta_Sequence(&ghostData->HModelController,"FireLeft",HMSQT_MarineStand,MSSS_Attack_Secondary,ONE_FIXED);
2007 							FireLeft->Playing=0;
2008 							FireLeft->Active=0;
2009 						}
2010 
2011 						if (special) {
2012 							if ((ghostData->HModelController.Sequence_Type!=(int)HMSQT_MarineRun)||(ghostData->HModelController.Sub_Sequence!=MRSS_Fire_From_Hips)) {
2013 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Fire_From_Hips,(ONE_FIXED>>1),1);
2014 								ghostData->HModelController.Reversed=1;
2015 							}
2016 						} else {
2017 							if ((ghostData->HModelController.Sequence_Type!=(int)HMSQT_MarineRun)||(ghostData->HModelController.Sub_Sequence!=MRSS_Standard)) {
2018 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Standard,(ONE_FIXED>>1),1);
2019 								ghostData->HModelController.Reversed=1;
2020 							}
2021 						}
2022 
2023 						Start_Delta_Sequence(FireRight,HMSQT_MarineStand,MSSS_Attack_Primary,-1);
2024 						FireRight->Playing=1;
2025 						FireRight->Active=1;
2026 
2027 					} else {
2028 						InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineRun,(int)MRSS_Attack_Primary,(ONE_FIXED>>1));
2029 						ghostData->HModelController.Reversed=1;
2030 					}
2031 					break;
2032 				}
2033 				case(MSQ_RunningFireSecondary_Backwards):
2034 				{
2035 					if (ghostData->CurrentWeapon==WEAPON_MARINE_PISTOL) {
2036 						InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineRun,(int)MRSS_Attack_Primary,(ONE_FIXED>>1));
2037 						ghostData->HModelController.Reversed=1;
2038 					} else if (ghostData->CurrentWeapon==WEAPON_TWO_PISTOLS) {
2039 
2040 						FireRight=Get_Delta_Sequence(&ghostData->HModelController,"FireRight");
2041 						if (FireRight==NULL) {
2042 							FireRight=Add_Delta_Sequence(&ghostData->HModelController,"FireRight",HMSQT_MarineStand,MSSS_Attack_Primary,ONE_FIXED);
2043 							FireRight->Playing=0;
2044 							FireRight->Active=0;
2045 						}
2046 
2047 						FireLeft=Get_Delta_Sequence(&ghostData->HModelController,"FireLeft");
2048 						if (FireLeft==NULL) {
2049 							FireLeft=Add_Delta_Sequence(&ghostData->HModelController,"FireLeft",HMSQT_MarineStand,MSSS_Attack_Secondary,ONE_FIXED);
2050 							FireLeft->Playing=0;
2051 							FireLeft->Active=0;
2052 						}
2053 
2054 						if (special) {
2055 							if ((ghostData->HModelController.Sequence_Type!=(int)HMSQT_MarineRun)||(ghostData->HModelController.Sub_Sequence!=MRSS_Fire_From_Hips)) {
2056 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Fire_From_Hips,(ONE_FIXED>>1),1);
2057 								ghostData->HModelController.Reversed=1;
2058 							}
2059 						} else {
2060 							if ((ghostData->HModelController.Sequence_Type!=(int)HMSQT_MarineRun)||(ghostData->HModelController.Sub_Sequence!=MRSS_Standard)) {
2061 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineRun,(int)MRSS_Standard,(ONE_FIXED>>1),1);
2062 								ghostData->HModelController.Reversed=1;
2063 							}
2064 						}
2065 
2066 						Start_Delta_Sequence(FireLeft,HMSQT_MarineStand,MSSS_Attack_Secondary,-1);
2067 						FireLeft->Playing=1;
2068 						FireLeft->Active=1;
2069 
2070 					} else {
2071 						InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineRun,(int)MRSS_Attack_Primary,(ONE_FIXED>>1));
2072 						ghostData->HModelController.Reversed=1;
2073 					}
2074 					break;
2075 				}
2076 				case(MSQ_StandingFire):
2077 				{
2078 					if (ghostData->CurrentWeapon==WEAPON_TWO_PISTOLS) {
2079 
2080 						FireRight=Get_Delta_Sequence(&ghostData->HModelController,"FireRight");
2081 						if (FireRight==NULL) {
2082 							FireRight=Add_Delta_Sequence(&ghostData->HModelController,"FireRight",HMSQT_MarineStand,MSSS_Attack_Primary,ONE_FIXED);
2083 							FireRight->Playing=0;
2084 							FireRight->Active=0;
2085 						}
2086 
2087 						FireLeft=Get_Delta_Sequence(&ghostData->HModelController,"FireLeft");
2088 						if (FireLeft==NULL) {
2089 							FireLeft=Add_Delta_Sequence(&ghostData->HModelController,"FireLeft",HMSQT_MarineStand,MSSS_Attack_Secondary,ONE_FIXED);
2090 							FireLeft->Playing=0;
2091 							FireLeft->Active=0;
2092 						}
2093 
2094 						if (special) {
2095 							if ((ghostData->HModelController.Sequence_Type!=(int)HMSQT_MarineStand)||(ghostData->HModelController.Sub_Sequence!=MSSS_FireFromHips)) {
2096 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineStand,(int)MSSS_FireFromHips,(ONE_FIXED>>1),1);
2097 							}
2098 						} else {
2099 							if ((ghostData->HModelController.Sequence_Type!=(int)HMSQT_MarineStand)||(ghostData->HModelController.Sub_Sequence!=MSSS_Standard)) {
2100 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineStand,(int)MSSS_Standard,(ONE_FIXED>>1),1);
2101 							}
2102 						}
2103 
2104 						Start_Delta_Sequence(FireRight,HMSQT_MarineStand,MSSS_Attack_Primary,-1);
2105 						FireRight->Playing=1;
2106 						FireRight->Active=1;
2107 
2108 					} else {
2109 						InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineStand,(int)MSSS_Attack_Primary,ONE_FIXED);
2110 					}
2111 					break;
2112 				}
2113 				case(MSQ_StandingFireSecondary):
2114 				{
2115 					if (ghostData->CurrentWeapon==WEAPON_TWO_PISTOLS) {
2116 
2117 						FireRight=Get_Delta_Sequence(&ghostData->HModelController,"FireRight");
2118 						if (FireRight==NULL) {
2119 							FireRight=Add_Delta_Sequence(&ghostData->HModelController,"FireRight",HMSQT_MarineStand,MSSS_Attack_Primary,ONE_FIXED);
2120 							FireRight->Playing=0;
2121 							FireRight->Active=0;
2122 						}
2123 
2124 						FireLeft=Get_Delta_Sequence(&ghostData->HModelController,"FireLeft");
2125 						if (FireLeft==NULL) {
2126 							FireLeft=Add_Delta_Sequence(&ghostData->HModelController,"FireLeft",HMSQT_MarineStand,MSSS_Attack_Secondary,ONE_FIXED);
2127 							FireLeft->Playing=0;
2128 							FireLeft->Active=0;
2129 						}
2130 
2131 						if (special) {
2132 							if ((ghostData->HModelController.Sequence_Type!=(int)HMSQT_MarineStand)||(ghostData->HModelController.Sub_Sequence!=MSSS_FireFromHips)) {
2133 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineStand,(int)MSSS_FireFromHips,(ONE_FIXED>>1),1);
2134 							}
2135 						} else {
2136 							if ((ghostData->HModelController.Sequence_Type!=(int)HMSQT_MarineStand)||(ghostData->HModelController.Sub_Sequence!=MSSS_Standard)) {
2137 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineStand,(int)MSSS_Standard,(ONE_FIXED>>1),1);
2138 							}
2139 						}
2140 
2141 						Start_Delta_Sequence(FireLeft,HMSQT_MarineStand,MSSS_Attack_Secondary,-1);
2142 						FireLeft->Playing=1;
2143 						FireLeft->Active=1;
2144 
2145 					} else {
2146 						InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineStand,(int)MSSS_Attack_Primary,ONE_FIXED);
2147 					}
2148 					break;
2149 				}
2150 				case(MSQ_Stand):
2151 				{
2152 					BOOL standing_attack=FALSE;
2153 					/* Removed the test for 'standing swipe'... */
2154 					if(ghostData->currentAnimSequence>=MSQ_BaseOfCudgelAttacks)
2155 					{
2156 						if((ghostData->currentAnimSequence-MSQ_BaseOfCudgelAttacks)%2==1)
2157 						{
2158 							standing_attack=TRUE;
2159 						}
2160 					}
2161 
2162 					if(standing_attack)
2163 					{
2164 						//if currently playing a standing attack allow it to finish first
2165 						if(!HModelAnimation_IsFinished(&ghostData->HModelController)) return;
2166 					}
2167 
2168 					if (ghostData->CurrentWeapon==WEAPON_TWO_PISTOLS) {
2169 						if (special) {
2170 							if ((ghostData->HModelController.Sequence_Type!=(int)HMSQT_MarineStand)||(ghostData->HModelController.Sub_Sequence!=MSSS_FireFromHips)) {
2171 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineStand,(int)MSSS_FireFromHips,(ONE_FIXED>>1),1);
2172 							}
2173 						} else {
2174 							if ((ghostData->HModelController.Sequence_Type!=(int)HMSQT_MarineStand)||(ghostData->HModelController.Sub_Sequence!=MSSS_Standard)) {
2175 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineStand,(int)MSSS_Standard,(ONE_FIXED>>1),1);
2176 							}
2177 						}
2178 					} else {
2179 						InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineStand,(int)MSSS_Standard,ONE_FIXED,1);
2180 	//					InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineStand,(int)MSSS_Standard,ONE_FIXED);
2181 					}
2182 					break;
2183 				}
2184 				case(MSQ_Crawl):
2185 				{
2186 					if (ghostData->CurrentWeapon==WEAPON_TWO_PISTOLS) {
2187 						if (special) {
2188 							if ((ghostData->HModelController.Sequence_Type!=(int)HMSQT_MarineCrawl)||(ghostData->HModelController.Sub_Sequence!=MCSS_FireFromHips)) {
2189 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineCrawl,(int)MCSS_FireFromHips,(ONE_FIXED>>1),1);
2190 							}
2191 						} else {
2192 							if ((ghostData->HModelController.Sequence_Type!=(int)HMSQT_MarineCrawl)||(ghostData->HModelController.Sub_Sequence!=MCSS_Standard)) {
2193 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineCrawl,(int)MCSS_Standard,(ONE_FIXED>>1),1);
2194 							}
2195 						}
2196 					} else {
2197 						InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_MarineCrawl,(int)MCSS_Standard,(ONE_FIXED>>1),1);
2198 					}
2199 					break;
2200 				}
2201 				case(MSQ_Crawl_Backwards):
2202 				{
2203 					if (ghostData->CurrentWeapon==WEAPON_TWO_PISTOLS) {
2204 						if (special) {
2205 							if ((ghostData->HModelController.Sequence_Type!=(int)HMSQT_MarineCrawl)||(ghostData->HModelController.Sub_Sequence!=MCSS_FireFromHips)) {
2206 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineCrawl,(int)MCSS_FireFromHips,(ONE_FIXED>>1),1);
2207 							}
2208 						} else {
2209 							if ((ghostData->HModelController.Sequence_Type!=(int)HMSQT_MarineCrawl)||(ghostData->HModelController.Sub_Sequence!=MCSS_Standard)) {
2210 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineCrawl,(int)MCSS_Standard,(ONE_FIXED>>1),1);
2211 							}
2212 						}
2213 					} else {
2214 						InitHModelSequence(&ghostData->HModelController,(int)HMSQT_MarineCrawl,(int)MCSS_Standard,(ONE_FIXED>>1));
2215 					}
2216 					ghostData->HModelController.Reversed=1;
2217 					break;
2218 				}
2219 				case(MSQ_Crouch):
2220 				{
2221 					BOOL crouched_attack=FALSE;
2222 					if(ghostData->currentAnimSequence>=MSQ_BaseOfCudgelAttacks)
2223 					{
2224 						if((ghostData->currentAnimSequence-MSQ_BaseOfCudgelAttacks)%2==0)
2225 						{
2226 							crouched_attack=TRUE;
2227 						}
2228 					}
2229 
2230 					if(crouched_attack)
2231 					{
2232 						//if currently playing a standing attack allow it to finish first
2233 						if(!HModelAnimation_IsFinished(&ghostData->HModelController)) return;
2234 					}
2235 
2236 					if (ghostData->CurrentWeapon==WEAPON_TWO_PISTOLS) {
2237 						if (special) {
2238 							if ((ghostData->HModelController.Sequence_Type!=(int)HMSQT_MarineCrouch)||(ghostData->HModelController.Sub_Sequence!=MCrSS_FireFromHips)) {
2239 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineCrouch,(int)MCrSS_FireFromHips,(ONE_FIXED>>1),1);
2240 							}
2241 						} else {
2242 							if ((ghostData->HModelController.Sequence_Type!=(int)HMSQT_MarineCrouch)||(ghostData->HModelController.Sub_Sequence!=MCrSS_Standard)) {
2243 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineCrouch,(int)MCrSS_Standard,(ONE_FIXED>>1),1);
2244 							}
2245 						}
2246 					} else {
2247 						InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_MarineCrouch,(int)MCrSS_Standard,ONE_FIXED,1);
2248 					}
2249 					break;
2250 				}
2251 				case(MSQ_Jump):
2252 				{
2253 					if (HModelSequence_Exists(&ghostData->HModelController,(int)HMSQT_MarineStand,(int)MSSS_Jump)) {
2254 						InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_MarineStand,(int)MSSS_Jump,(ONE_FIXED),0);
2255 						break;
2256 					} else {
2257 						InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineStand,(int)MSSS_Standard,ONE_FIXED,1);
2258 						break;
2259 					}
2260 
2261 				}
2262 				case(MSQ_Taunt):
2263 				{
2264 					if (HModelSequence_Exists(&ghostData->HModelController,(int)HMSQT_MarineStand,(int)MSSS_Taunt_One)) {
2265 						if ((ghostData->HModelController.Sequence_Type!=(int)HMSQT_MarineStand)||(ghostData->HModelController.Sub_Sequence!=MSSS_Taunt_One)) {
2266 							InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_MarineStand,(int)MSSS_Taunt_One,(TAUNT_LENGTH-(ONE_FIXED>>3)),0);
2267 						}
2268 						break;
2269 					} else {
2270 						/* Default. */
2271 						InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_MarineStand,(int)MSSS_Standard,ONE_FIXED,1);
2272 						break;
2273 					}
2274 
2275 				}
2276 				case(MSQ_StandDieFront):
2277 				case(MSQ_CrouchDie):
2278 				{
2279 					break;
2280 				}
2281 				default:
2282 				{
2283 					int attack;
2284 					/* Now includes cudgel attacks... */
2285 					if ((int)sequence>=(int)MSQ_BaseOfCudgelAttacks) {
2286 						attack=(int)sequence-(int)MSQ_BaseOfCudgelAttacks;
2287 
2288 						if(ghostData->currentAnimSequence>=MSQ_BaseOfCudgelAttacks)
2289 						{
2290 							//already playing some form of attack
2291 							if(!HModelAnimation_IsFinished(&ghostData->HModelController)) return;
2292 						}
2293 						switch (attack) {
2294 							case 0:
2295 								/* Crouching Primary Fire. */
2296 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>4),(int)HMSQT_MarineCrouch,(int)MCrSS_Attack_Primary,-1,0);
2297 								break;
2298 							case 1:
2299 								/* Standing Primary Fire. */
2300 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>4),(int)HMSQT_MarineStand,(int)MSSS_Attack_Primary,-1,0);
2301 								break;
2302 							case 2:
2303 								/* Crouching Secondary Fire. */
2304 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>4),(int)HMSQT_MarineCrouch,(int)MCrSS_Attack_Secondary,-1,0);
2305 								break;
2306 							case 3:
2307 								/* Standing Secondary Fire. */
2308 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>4),(int)HMSQT_MarineStand,(int)MSSS_Attack_Secondary,-1,0);
2309 								break;
2310 							default:
2311 							/* KJL 16:56:15 26/11/98 - hmm. Any 'unknown' attacks will be replaced with a fast jab */
2312 							{
2313 								if (attack&1)
2314 								{
2315 									/* Standing Fast Jab. */
2316 									InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>4),(int)HMSQT_MarineStand,(int)MSSS_Attack_Primary,-1,0);
2317 								}
2318 								else
2319 								{
2320 									/* Crouching Fast Jab. */
2321 									InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>4),(int)HMSQT_MarineCrouch,(int)MCrSS_Attack_Primary,-1,0);
2322 								}
2323 								break;
2324 							}
2325 						}
2326 					} else {
2327 						attack=(int)sequence-(int)MSQ_BaseOfCudgelAttacks;
2328 
2329 						if (attack) {
2330 							InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_PredatorCrouch,(int)PCrSS_Attack_Primary,-1,0);
2331 						} else {
2332 							InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_PredatorStand,(int)PSSS_Attack_Primary,-1,0);
2333 						}
2334 					}
2335 					break;
2336 				}
2337 			}
2338 			break;
2339 		}
2340 		case(I_BehaviourAlienPlayer):
2341 		case(I_BehaviourAlien):
2342 		{
2343 			switch((ALIEN_SEQUENCE)sequence)
2344 			{
2345 				case(ASQ_Stand):
2346 				case(ASQ_StandingTailPoise):
2347 				{
2348 					if(ghostData->currentAnimSequence==ASQ_StandingAttack_Claw ||
2349 					   ghostData->currentAnimSequence==ASQ_StandingTailStrike ||
2350 					   ghostData->currentAnimSequence==ASQ_Eat)
2351 					{
2352 						//if currently playing a standing attack allow it to finish first
2353 						if(!HModelAnimation_IsFinished(&ghostData->HModelController)) return;
2354 					}
2355 
2356 					InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienStand,(int)ASSS_Standard,ONE_FIXED,1);
2357 					break;
2358 				}
2359 				case(ASQ_StandingAttack_Claw):
2360 				{
2361 					int chosenSequence;
2362 
2363 					if(ghostData->currentAnimSequence==ASQ_StandingAttack_Claw ||
2364 					   ghostData->currentAnimSequence==ASQ_StandingTailStrike ||
2365 					   ghostData->currentAnimSequence==ASQ_Eat)
2366 					{
2367 						//if already playing a standing attack allow it to finish first
2368 						if(!HModelAnimation_IsFinished(&ghostData->HModelController)) return;
2369 					}
2370 
2371 					/*Pick a random claw attack*/
2372 					switch(FastRandom()%6)
2373 					{
2374 						case 0:
2375 							chosenSequence=ASSS_Attack_Right_Swipe_In;
2376 							break;
2377 						case 1:
2378 							chosenSequence=ASSS_Attack_Left_Swipe_In;
2379 							break;
2380 						case 2:
2381 							chosenSequence=ASSS_Attack_Both_In;
2382 							break;
2383 						case 3:
2384 							chosenSequence=ASSS_Attack_Both_Down;
2385 							break;
2386 						case 4:
2387 							chosenSequence=ASSS_Attack_Low_Left_Swipe;
2388 							break;
2389 						case 5:
2390 							chosenSequence=ASSS_Attack_Low_Right_Swipe;
2391 							break;
2392 
2393 					}
2394 					InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienStand,chosenSequence,-1/*(ONE_FIXED/6)*/,0);
2395 
2396 					break;
2397 				}
2398 
2399 				case(ASQ_StandingTailStrike):
2400 				{
2401 					if(ghostData->currentAnimSequence==ASQ_StandingAttack_Claw ||
2402 					   ghostData->currentAnimSequence==ASQ_StandingTailStrike ||
2403 					   ghostData->currentAnimSequence==ASQ_Eat)
2404 					{
2405 						//if already playing a standing attack allow it to finish first
2406 						if(!HModelAnimation_IsFinished(&ghostData->HModelController)) return;
2407 					}
2408 
2409 					InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienStand,(int)ASSS_Attack_Tail,-1/*(ONE_FIXED/6)*/,0);
2410 					break;
2411 				}
2412 				case(ASQ_Eat) :
2413 				{
2414 					if(ghostData->currentAnimSequence==ASQ_StandingAttack_Claw ||
2415 					   ghostData->currentAnimSequence==ASQ_StandingTailStrike ||
2416 					   ghostData->currentAnimSequence==ASQ_Eat)
2417 					{
2418 						//if already playing a standing attack allow it to finish first
2419 						if(!HModelAnimation_IsFinished(&ghostData->HModelController)) return;
2420 					}
2421 
2422 					InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienStand,(int)ASSS_Attack_Bite,-1,0);
2423 					break;
2424 				}
2425 
2426 				case(ASQ_Run):
2427 				case(ASQ_RunningTailPoise):
2428 				{
2429 					if(ghostData->currentAnimSequence==ASQ_RunningAttack_Claw ||
2430 					   ghostData->currentAnimSequence==ASQ_RunningTailStrike)
2431 					{
2432 						if(!HModelAnimation_IsFinished(&ghostData->HModelController))
2433 						{
2434 							ghostData->HModelController.Looped=0;
2435 							ghostData->HModelController.LoopAfterTweening=0;
2436 							return;
2437 						}
2438 					}
2439 					InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienRun,(int)ARSS_Standard,ONE_FIXED,1);
2440 					break;
2441 				}
2442 				case(ASQ_Run_Backwards):
2443 				case(ASQ_RunningTailPoise_Backwards):
2444 				{
2445 					if(ghostData->currentAnimSequence==ASQ_RunningAttack_Claw_Backwards ||
2446 					   ghostData->currentAnimSequence==ASQ_RunningTailStrike_Backwards)
2447 					{
2448 						if(!HModelAnimation_IsFinished(&ghostData->HModelController))
2449 						{
2450 							ghostData->HModelController.Looped=0;
2451 							ghostData->HModelController.LoopAfterTweening=0;
2452 							return;
2453 						}
2454 					}
2455 					InitHModelSequence(&ghostData->HModelController,(int)HMSQT_AlienRun,(int)ARSS_Standard,ONE_FIXED);
2456 					ghostData->HModelController.Reversed=1;
2457 					break;
2458 				}
2459 				case(ASQ_RunningAttack_Claw):
2460 				case(ASQ_RunningTailStrike):
2461 				{
2462 					InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienRun,(int)ARSS_Attack_Swipe,ONE_FIXED/*(ONE_FIXED/6)*/,1);
2463 					break;
2464 				}
2465 				case(ASQ_RunningAttack_Claw_Backwards):
2466 				case(ASQ_RunningTailStrike_Backwards):
2467 				{
2468 					InitHModelSequence(&ghostData->HModelController,(int)HMSQT_AlienRun,(int)ARSS_Attack_Swipe,ONE_FIXED/*(ONE_FIXED/6)*/);
2469 					ghostData->HModelController.Reversed=1;
2470 					ghostData->HModelController.Looped=1;
2471 					break;
2472 				}
2473 				case(ASQ_Crawl):
2474 				case(ASQ_CrawlingTailPoise):
2475 				{
2476 					if(ghostData->currentAnimSequence==ASQ_CrawlingAttack_Claw ||
2477 					   ghostData->currentAnimSequence==ASQ_CrawlingTailStrike)
2478 					{
2479 						if(!HModelAnimation_IsFinished(&ghostData->HModelController))
2480 						{
2481 							ghostData->HModelController.Looped=0;
2482 							ghostData->HModelController.LoopAfterTweening=0;
2483 							return;
2484 						}
2485 					}
2486 					InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienCrawl,(int)ACSS_Standard,ONE_FIXED,1);
2487 					break;
2488 				}
2489 				case (ASQ_Scamper):
2490 				{
2491 					if(ghostData->currentAnimSequence==ASQ_CrawlingAttack_Claw ||
2492 					   ghostData->currentAnimSequence==ASQ_CrawlingTailStrike)
2493 					{
2494 						if(!HModelAnimation_IsFinished(&ghostData->HModelController))
2495 						{
2496 							ghostData->HModelController.Looped=0;
2497 							ghostData->HModelController.LoopAfterTweening=0;
2498 							return;
2499 						}
2500 					}
2501 					InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienCrawl,(int)ACSS_Scamper,ONE_FIXED,1);
2502 					break;
2503 				}
2504 
2505 				case(ASQ_Crawl_Backwards):
2506 				case(ASQ_CrawlingTailPoise_Backwards):
2507 				{
2508 					if(ghostData->currentAnimSequence==ASQ_CrawlingAttack_Claw_Backwards ||
2509 					   ghostData->currentAnimSequence==ASQ_CrawlingTailStrike_Backwards)
2510 					{
2511 						if(!HModelAnimation_IsFinished(&ghostData->HModelController))
2512 						{
2513 							ghostData->HModelController.Looped=0;
2514 							ghostData->HModelController.LoopAfterTweening=0;
2515 							return;
2516 						}
2517 					}
2518 					InitHModelSequence(&ghostData->HModelController,(int)HMSQT_AlienCrawl,(int)ACSS_Standard,ONE_FIXED);
2519 					ghostData->HModelController.Reversed=1;
2520 					break;
2521 				}
2522 				case(ASQ_Scamper_Backwards):
2523 				{
2524 					if(ghostData->currentAnimSequence==ASQ_CrawlingAttack_Claw_Backwards ||
2525 					   ghostData->currentAnimSequence==ASQ_CrawlingTailStrike_Backwards)
2526 					{
2527 						if(!HModelAnimation_IsFinished(&ghostData->HModelController))
2528 						{
2529 							ghostData->HModelController.Looped=0;
2530 							ghostData->HModelController.LoopAfterTweening=0;
2531 							return;
2532 						}
2533 					}
2534 					InitHModelSequence(&ghostData->HModelController,(int)HMSQT_AlienCrawl,(int)ACSS_Scamper,ONE_FIXED);
2535 					ghostData->HModelController.Reversed=1;
2536 					break;
2537 				}
2538 
2539 				case(ASQ_CrawlingAttack_Claw):
2540 				case(ASQ_CrawlingTailStrike):
2541 				{
2542 					InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienCrouch,(int)ACrSS_Attack_Swipe,ONE_FIXED/*(ONE_FIXED/6)*/,1);
2543 					break;
2544 				}
2545 				case(ASQ_CrawlingAttack_Claw_Backwards):
2546 				case(ASQ_CrawlingTailStrike_Backwards):
2547 				{
2548 					InitHModelSequence(&ghostData->HModelController,(int)HMSQT_AlienCrouch,(int)ACrSS_Attack_Swipe,ONE_FIXED/*(ONE_FIXED/6)*/);
2549 					ghostData->HModelController.Reversed=1;
2550 					ghostData->HModelController.Looped=1;
2551 					break;
2552 				}
2553 				#if 0
2554 				case(ASQ_CrawlingTailStrike):
2555 				{
2556 					InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienCrawl,(int)ACSS_Attack_Tail,ONE_FIXED/*(ONE_FIXED/6)*/,1);
2557 					break;
2558 				}
2559 				case(ASQ_CrawlingTailStrike_Backwards):
2560 				{
2561 					InitHModelSequence(&ghostData->HModelController,(int)HMSQT_AlienCrawl,(int)ACSS_Attack_Tail,ONE_FIXED/*(ONE_FIXED/6)*/);
2562 					ghostData->HModelController.Reversed=1;
2563 					ghostData->HModelController.Looped=1;
2564 					break;
2565 				}
2566 				#endif
2567 				case(ASQ_Crouch):
2568 				case(ASQ_CrouchedTailPoise):
2569 				{
2570 					if(ghostData->currentAnimSequence==ASQ_CrouchedAttack_Claw ||
2571 					   ghostData->currentAnimSequence==ASQ_CrouchEat||
2572 					   ghostData->currentAnimSequence==ASQ_CrouchedTailStrike)
2573 					{
2574 						if(!HModelAnimation_IsFinished(&ghostData->HModelController)) return;
2575 					}
2576 					InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienCrouch,(int)ACSS_Standard,ONE_FIXED,1);
2577 					break;
2578 				}
2579 				case(ASQ_CrouchedAttack_Claw):
2580 				{
2581 					if(ghostData->currentAnimSequence==ASQ_CrouchedAttack_Claw ||
2582 					   ghostData->currentAnimSequence==ASQ_CrouchedTailStrike ||
2583 					   ghostData->currentAnimSequence==ASQ_CrouchEat)
2584 					{
2585 						//if already playing a crouched attack allow it to finish first
2586 						if(!HModelAnimation_IsFinished(&ghostData->HModelController)) return;
2587 					}
2588 					InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienCrouch,(int)ACrSS_Attack_Swipe,-1/*(ONE_FIXED/6)*/,0);
2589 					break;
2590 				}
2591 				case(ASQ_CrouchedTailStrike):
2592 				{
2593 					if(ghostData->currentAnimSequence==ASQ_CrouchedAttack_Claw ||
2594 					   ghostData->currentAnimSequence==ASQ_CrouchedTailStrike ||
2595 					   ghostData->currentAnimSequence==ASQ_CrouchEat)
2596 					{
2597 						//if already playing a crouched attack allow it to finish first
2598 						if(!HModelAnimation_IsFinished(&ghostData->HModelController)) return;
2599 					}
2600 					InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienCrouch,(int)ACrSS_Attack_Tail,-1/*(ONE_FIXED/6)*/,0);
2601 					break;
2602 				}
2603 				case(ASQ_CrouchEat) :
2604 				{
2605 					if(ghostData->currentAnimSequence==ASQ_CrouchedAttack_Claw ||
2606 					   ghostData->currentAnimSequence==ASQ_CrouchedTailStrike ||
2607 					   ghostData->currentAnimSequence==ASQ_CrouchEat)
2608 					{
2609 						//if already playing a crouched attack allow it to finish first
2610 						if(!HModelAnimation_IsFinished(&ghostData->HModelController)) return;
2611 					}
2612 					InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienCrouch,(int)ACrSS_Attack_Bite,-1,0);
2613 					break;
2614 				}
2615 				case(ASQ_Jump):
2616 				case(ASQ_Pounce):
2617 				case(ASQ_JumpingTailPoise):
2618 				case(ASQ_JumpingTailStrike):
2619 				{
2620 					InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienRun,(int)ARSS_Jump,ONE_FIXED,1);
2621 					break;
2622 				}
2623 				case(ASQ_Taunt):
2624 				{
2625 					if (HModelSequence_Exists(&ghostData->HModelController,(int)HMSQT_AlienStand,(int)ASSS_Taunt)) {
2626 						InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_AlienStand,(int)ASSS_Taunt,(TAUNT_LENGTH-(ONE_FIXED>>3)),0);
2627 						break;
2628 					} else {
2629 						/* Default. */
2630 						InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_AlienStand,(int)ASSS_Standard,ONE_FIXED,1);
2631 						break;
2632 					}
2633 
2634 				}
2635 				default:
2636 				{
2637 					/* no other sequences should be set */
2638 					LOCALASSERT("Unknown Alien anim sequence"==0);
2639 					break;
2640 				}
2641 			}
2642 		  	break;
2643 		}
2644 		case(I_BehaviourPredatorPlayer):
2645 		{
2646 			switch((PREDATOR_SEQUENCE)sequence)
2647 			{
2648 				case(PredSQ_Stand):
2649 				{
2650 					BOOL standing_attack=FALSE;
2651 					if(ghostData->currentAnimSequence==PredSQ_StandingSwipe)
2652 					{
2653 						standing_attack=TRUE;
2654 					}
2655 					else if(ghostData->currentAnimSequence>=PredSQ_BaseOfWristbladeAttacks)
2656 					{
2657 						if((ghostData->currentAnimSequence-PredSQ_BaseOfWristbladeAttacks)%2==1)
2658 						{
2659 							standing_attack=TRUE;
2660 						}
2661 					}
2662 
2663 					if(standing_attack)
2664 					{
2665 						//if currently playing a standing attack allow it to finish first
2666 						if(!HModelAnimation_IsFinished(&ghostData->HModelController)) return;
2667 					}
2668 
2669 					InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_PredatorStand,(int)PSSS_Standard,ONE_FIXED,1);
2670 					break;
2671 				}
2672 				case(PredSQ_StandingSwipe):
2673 				{
2674 					InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_PredatorStand,(int)PSSS_Attack_Primary,-1,0);
2675 					break;
2676 				}
2677 
2678 				case(PredSQ_RunningSwipe):
2679 				{
2680 					InitHModelSequence(&ghostData->HModelController,(int)HMSQT_PredatorRun,(int)PRSS_Attack_Primary,(ONE_FIXED>>1));
2681 					ghostData->HModelController.Looped=0;
2682 					break;
2683 				}
2684 
2685 				case(PredSQ_RunningSwipe_Backwards):
2686 				{
2687 					InitHModelSequence(&ghostData->HModelController,(int)HMSQT_PredatorRun,(int)PRSS_Attack_Primary,(ONE_FIXED>>1));
2688 					ghostData->HModelController.Looped=0;
2689 					ghostData->HModelController.Reversed=1;
2690 					break;
2691 				}
2692 
2693 				case(PredSQ_Run):
2694 				{
2695 					if(ghostData->currentAnimSequence==PredSQ_RunningSwipe)
2696 					{
2697 						if(!HModelAnimation_IsFinished(&ghostData->HModelController))
2698 						{
2699 							ghostData->HModelController.Looped=0;
2700 							ghostData->HModelController.LoopAfterTweening=0;
2701 							return;
2702 						}
2703 					}
2704 
2705 					InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_PredatorRun,(int)PSSS_Standard,(ONE_FIXED>>1),1);
2706 
2707 					break;
2708 				}
2709 
2710 				case(PredSQ_Run_Backwards):
2711 				{
2712 					if(ghostData->currentAnimSequence==PredSQ_RunningSwipe_Backwards)
2713 					{
2714 						if(!HModelAnimation_IsFinished(&ghostData->HModelController))
2715 						{
2716 							ghostData->HModelController.Looped=0;
2717 							ghostData->HModelController.LoopAfterTweening=0;
2718 							return;
2719 						}
2720 					}
2721 
2722 					InitHModelSequence(&ghostData->HModelController,(int)HMSQT_PredatorRun,(int)PSSS_Standard,(ONE_FIXED>>1));
2723 					ghostData->HModelController.Reversed=1;
2724 					break;
2725 				}
2726 				case(PredSQ_Crawl):
2727 				{
2728 					if(ghostData->currentAnimSequence==PredSQ_CrawlingSwipe)
2729 					{
2730 						if(!HModelAnimation_IsFinished(&ghostData->HModelController))
2731 						{
2732 							ghostData->HModelController.Looped=0;
2733 							ghostData->HModelController.LoopAfterTweening=0;
2734 							return;
2735 						}
2736 					}
2737 
2738 					InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_PredatorCrawl,(int)PCSS_Standard,(ONE_FIXED>>1),1);
2739 					break;
2740 				}
2741 				case(PredSQ_Crawl_Backwards):
2742 				{
2743 					if(ghostData->currentAnimSequence==PredSQ_CrawlingSwipe_Backwards)
2744 					{
2745 						if(!HModelAnimation_IsFinished(&ghostData->HModelController))
2746 						{
2747 							ghostData->HModelController.Looped=0;
2748 							ghostData->HModelController.LoopAfterTweening=0;
2749 							return;
2750 						}
2751 					}
2752 
2753 					InitHModelSequence(&ghostData->HModelController,(int)HMSQT_PredatorCrawl,(int)PCSS_Standard,(ONE_FIXED>>1));
2754 					ghostData->HModelController.Reversed=1;
2755 					break;
2756 				}
2757 				case(PredSQ_Crouch):
2758 				{
2759 					BOOL crouched_attack=FALSE;
2760 					if(ghostData->currentAnimSequence==PredSQ_CrouchedSwipe)
2761 					{
2762 						crouched_attack=TRUE;
2763 					}
2764 					else if(ghostData->currentAnimSequence>=PredSQ_BaseOfWristbladeAttacks)
2765 					{
2766 						if((ghostData->currentAnimSequence-PredSQ_BaseOfWristbladeAttacks)%2==0)
2767 						{
2768 							crouched_attack=TRUE;
2769 						}
2770 					}
2771 
2772 					if(crouched_attack)
2773 					{
2774 						//if currently playing a standing attack allow it to finish first
2775 						if(!HModelAnimation_IsFinished(&ghostData->HModelController)) return;
2776 					}
2777 
2778 					if(ghostData->currentAnimSequence==PredSQ_CrouchedSwipe)
2779 					{
2780 						if(!HModelAnimation_IsFinished(&ghostData->HModelController))
2781 						{
2782 							return;
2783 						}
2784 					}
2785 
2786 					InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_PredatorCrouch,(int)PCrSS_Standard,ONE_FIXED,1);
2787 					break;
2788 				}
2789 				case(PredSQ_CrouchedSwipe):
2790 				{
2791 					InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_PredatorCrouch,(int)PCrSS_Attack_Primary,-1,0);
2792 					break;
2793 				}
2794 				case(PredSQ_CrawlingSwipe):
2795 				{
2796 					InitHModelSequence(&ghostData->HModelController,(int)HMSQT_PredatorCrawl,(int)PCSS_Attack_Primary,(ONE_FIXED>>1));
2797 					ghostData->HModelController.Looped=0;
2798 					break;
2799 				}
2800 				case(PredSQ_CrawlingSwipe_Backwards):
2801 				{
2802 					InitHModelSequence(&ghostData->HModelController,(int)HMSQT_PredatorCrawl,(int)PCSS_Attack_Primary,(ONE_FIXED>>1));
2803 					ghostData->HModelController.Looped=0;
2804 					ghostData->HModelController.Reversed=1;
2805 					break;
2806 				}
2807 				case(PredSQ_Jump):
2808 				{
2809 					if (HModelSequence_Exists(&ghostData->HModelController,(int)HMSQT_PredatorStand,(int)PSSS_Jump)) {
2810 						InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_PredatorStand,(int)PSSS_Jump,(ONE_FIXED),0);
2811 						break;
2812 					} else {
2813 						InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_PredatorStand,(int)PSSS_Standard,ONE_FIXED,1);
2814 						break;
2815 					}
2816 
2817 				}
2818 				case(PredSQ_Taunt):
2819 				{
2820 					if (HModelSequence_Exists(&ghostData->HModelController,(int)HMSQT_PredatorStand,(int)PSSS_Taunt_One)) {
2821 						InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_PredatorStand,(int)PSSS_Taunt_One,(TAUNT_LENGTH-(ONE_FIXED>>3)),0);
2822 						break;
2823 					} else {
2824 						/* Default. */
2825 						InitHModelTweening(&ghostData->HModelController,(ONE_FIXED)>>3,(int)HMSQT_PredatorStand,(int)PSSS_Standard,ONE_FIXED,1);
2826 						break;
2827 					}
2828 
2829 				}
2830 				case(PredSQ_StandDie):
2831 				{
2832 					break;
2833 				}
2834 				case(PredSQ_CrouchDie):
2835 				{
2836 					break;
2837 				}
2838 				default:
2839 				{
2840 					int attack;
2841 					/* Must cover STAFF ATTACKS, and WRISTBLADE ATTACKS! */
2842 					if ((int)sequence>=(int)PredSQ_BaseOfWristbladeAttacks) {
2843 						attack=(int)sequence-(int)PredSQ_BaseOfWristbladeAttacks;
2844 
2845 						if(ghostData->currentAnimSequence>=PredSQ_BaseOfWristbladeAttacks)
2846 						{
2847 							//already playing some form of attack
2848 							if(!HModelAnimation_IsFinished(&ghostData->HModelController)) return;
2849 						}
2850 						switch (attack) {
2851 							case 0:
2852 								/* Crouching Fast Jab. */
2853 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>4),(int)HMSQT_PredatorCrouch,(int)PCrSS_Attack_Primary,-1,0);
2854 								break;
2855 							case 1:
2856 								/* Standing Fast Jab. */
2857 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>4),(int)HMSQT_PredatorStand,(int)PSSS_Attack_Quick_Jab,-1,0);
2858 								break;
2859 							case 2:
2860 								/* Crouching Slow Jab. */
2861 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>4),(int)HMSQT_PredatorCrouch,(int)PCrSS_Attack_Primary,-1,0);
2862 								break;
2863 							case 3:
2864 								/* Standing Slow Jab. */
2865 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>4),(int)HMSQT_PredatorStand,(int)PSSS_Attack_Primary,-1,0);
2866 								break;
2867 							case 4:
2868 								/* Crouching Uppercut. */
2869 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>4),(int)HMSQT_PredatorCrouch,(int)PCrSS_Attack_Primary,-1,0);
2870 								break;
2871 							case 5:
2872 								/* Standing Uppercut. */
2873 								InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>4),(int)HMSQT_PredatorStand,(int)PSSS_Attack_Uppercut,-1,0);
2874 								break;
2875 							default:
2876 							/* KJL 16:56:15 26/11/98 - hmm. Any 'unknown' attacks will be replaced with a fast jab */
2877 							{
2878 								if (attack&1)
2879 								{
2880 									/* Standing Fast Jab. */
2881 									InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>4),(int)HMSQT_PredatorStand,(int)PSSS_Attack_Quick_Jab,-1,0);
2882 								}
2883 								else
2884 								{
2885 									/* Crouching Fast Jab. */
2886 									InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>4),(int)HMSQT_PredatorCrouch,(int)PCrSS_Attack_Primary,-1,0);
2887 								}
2888 								break;
2889 							}
2890 						}
2891 					} else {
2892 						attack=(int)sequence-(int)PredSQ_BaseOfStaffAttacks;
2893 
2894 						if (attack) {
2895 							InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_PredatorCrouch,(int)PCrSS_Attack_Primary,-1,0);
2896 						} else {
2897 							InitHModelTweening(&ghostData->HModelController,(ONE_FIXED>>3),(int)HMSQT_PredatorStand,(int)PSSS_Attack_Primary,-1,0);
2898 						}
2899 					}
2900 					break;
2901 				}
2902 			}
2903 			break;
2904 		}
2905 		default:
2906 		{
2907 			LOCALASSERT(1==0);
2908 			break;
2909 		}
2910 	}
2911 	/* update the ghost's current sequence*/
2912 	ghostData->currentAnimSequence = sequence;
2913 }
2914 
2915 
2916 
2917 /* Patrick 5/8/97 --------------------------------------------------
2918 Handles the player's weapon sound effects... this should be called
2919 after update ghost/create ghost has been called for player ghost
2920 in processnetmsg_playerstate().
2921 ---------------------------------------------------------------------*/
HandlePlayerGhostWeaponSound(STRATEGYBLOCK * sbPtr,int weapon,int firingPrimary,int firingSecondary)2922 void HandlePlayerGhostWeaponSound(STRATEGYBLOCK *sbPtr, int weapon, int firingPrimary, int firingSecondary)
2923 {
2924 	NETGHOSTDATABLOCK *ghostData;
2925 	AVP_BEHAVIOUR_TYPE type;
2926 
2927 	LOCALASSERT(sbPtr);
2928 	LOCALASSERT(sbPtr->DynPtr);
2929 	LOCALASSERT(weapon>=0);
2930 
2931 	ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
2932 	LOCALASSERT(ghostData);
2933 	type = ghostData->type;
2934 
2935 	switch((enum WEAPON_ID)weapon)
2936 	{
2937 		case(NULL_WEAPON):
2938 		{
2939 			/* stop sound if we've got it */
2940 			if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle);
2941 			break;
2942 		}
2943 		case(WEAPON_CUDGEL):
2944 		{
2945 			//no sound for the moment.
2946 			if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle);
2947 			break;
2948 		}
2949 		case(WEAPON_PULSERIFLE):
2950 		{
2951 			LOCALASSERT(type==I_BehaviourMarinePlayer);
2952 			if(firingPrimary)
2953 			{
2954 				if(ghostData->SoundHandle == SOUND_NOACTIVEINDEX)
2955 				   	Sound_Play(SID_PULSE_LOOP,"elhd",&(ghostData->SoundHandle),&(sbPtr->DynPtr->Position));
2956 				else
2957 					Sound_Update3d(ghostData->SoundHandle, &(sbPtr->DynPtr->Position));
2958 			}
2959 			else
2960 			{
2961 				if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX)
2962 				{
2963 					Sound_Stop(ghostData->SoundHandle);
2964 					Sound_Play(SID_PULSE_END,"hd",&(sbPtr->DynPtr->Position));
2965 				}
2966 				if(firingSecondary)	Sound_Play(SID_NADEFIRE,"hd",&(sbPtr->DynPtr->Position));
2967 			}
2968 			break;
2969 		}
2970 		case(WEAPON_TWO_PISTOLS):
2971 		case(WEAPON_MARINE_PISTOL):
2972 		{
2973 			LOCALASSERT(type==I_BehaviourMarinePlayer);
2974 			/* stop sound if we've got it */
2975 			if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) {
2976 				Sound_Stop(ghostData->SoundHandle);
2977 			}
2978 			if ((firingPrimary)||(firingSecondary)) {
2979 				//ReleasePrintDebuggingText("Ghost Gunfire Sound!\n");
2980 				Sound_Play(SID_SHOTGUN,"hd",&(sbPtr->DynPtr->Position));
2981 			}
2982 			break;
2983 		}
2984 		case(WEAPON_AUTOSHOTGUN):
2985 		{
2986 			LOCALASSERT(type==I_BehaviourMarinePlayer);
2987 			/* stop sound if we've got it */
2988 			if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle);
2989 			if(firingPrimary) Sound_Play(SID_SHOTGUN,"hd",&(sbPtr->DynPtr->Position));
2990 			break;
2991 		}
2992 		case(WEAPON_SMARTGUN):
2993 		{
2994 			LOCALASSERT(type==I_BehaviourMarinePlayer);
2995 			if(firingPrimary)
2996 			{
2997 				if(ghostData->SoundHandle == SOUND_NOACTIVEINDEX)
2998 				{
2999     				unsigned int rand=FastRandom() % 3;
3000     				switch (rand)
3001     				{
3002       					case(0):
3003       					{
3004         					Sound_Play(SID_SMART1,"ehpd",&(ghostData->SoundHandle),((FastRandom()&255)-128),&(sbPtr->DynPtr->Position));
3005         					break;
3006       					}
3007       					case(1):
3008       					{
3009         					Sound_Play(SID_SMART2,"ehpd",&(ghostData->SoundHandle),((FastRandom()&255)-128),&(sbPtr->DynPtr->Position));
3010         					break;
3011       					}
3012       					case(2):
3013       					{
3014         					Sound_Play(SID_SMART3,"ehpd",&(ghostData->SoundHandle),((FastRandom()&255)-128),&(sbPtr->DynPtr->Position));
3015         					break;
3016       					}
3017 						default:
3018 						{
3019 							break;
3020 						}
3021 					}
3022 			   	}
3023 				else Sound_Update3d(ghostData->SoundHandle, &(sbPtr->DynPtr->Position));
3024 			}
3025 			else
3026 			{
3027 				if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle);
3028 			}
3029 			break;
3030 		}
3031 		case(WEAPON_FLAMETHROWER):
3032 		{
3033 			LOCALASSERT(type==I_BehaviourMarinePlayer);
3034 			if(firingPrimary)
3035 			{
3036 				if(ghostData->SoundHandle == SOUND_NOACTIVEINDEX)
3037 				   	Sound_Play(SID_INCIN_LOOP,"elhd",&(ghostData->SoundHandle),&(sbPtr->DynPtr->Position));
3038 				else
3039 					Sound_Update3d(ghostData->SoundHandle, &(sbPtr->DynPtr->Position));
3040 			}
3041 			else
3042 			{
3043 				if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle);
3044 			}
3045 			if (firingPrimary)
3046 			{
3047 				if (sbPtr->SBdptr)
3048 				{
3049 					ProveHModel(&ghostData->HModelController,sbPtr->SBdptr);
3050 					FireNetGhostFlameThrower
3051 					(
3052 						&ghostData->GunflashSectionPtr->World_Offset,
3053 						&ghostData->GunflashSectionPtr->SecMat
3054 					);
3055 					/* Lighting? */
3056 					if (sbPtr->SBdptr) {
3057 						AddLightingEffectToObject(sbPtr->SBdptr,LFX_MUZZLEFLASH);
3058 					}
3059 				}
3060 			}
3061 			break;
3062 		}
3063 		case(WEAPON_PLASMAGUN):
3064 		{
3065 			LOCALASSERT(type==I_BehaviourMarinePlayer);
3066 			/* stop sound if we've got it */
3067 			if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle);
3068 			break;
3069 		}
3070 		case(WEAPON_SADAR):
3071 		{
3072 			LOCALASSERT(type==I_BehaviourMarinePlayer);
3073 			/* stop sound if we've got it */
3074 			if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle);
3075 			if(firingPrimary) Sound_Play(SID_SADAR_FIRE,"hd",&(sbPtr->DynPtr->Position));
3076 			break;
3077 		}
3078 		case(WEAPON_GRENADELAUNCHER):
3079 		{
3080 			LOCALASSERT(type==I_BehaviourMarinePlayer);
3081 			/* stop sound if we've got it */
3082 			if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle);
3083 			if(firingPrimary) Sound_Play(SID_ROCKFIRE,"hd",&(sbPtr->DynPtr->Position));
3084 			break;
3085 		}
3086 		case(WEAPON_MINIGUN):
3087 		{
3088 			LOCALASSERT(type==I_BehaviourMarinePlayer);
3089 			if(firingPrimary)
3090 			{
3091 				if(ghostData->SoundHandle == SOUND_NOACTIVEINDEX)
3092 				   	Sound_Play(SID_MINIGUN_LOOP,"elhd",&(ghostData->SoundHandle),&(sbPtr->DynPtr->Position));
3093 				else
3094 					Sound_Update3d(ghostData->SoundHandle, &(sbPtr->DynPtr->Position));
3095 			}
3096 			else
3097 			{
3098 				if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX)
3099 				{
3100 					Sound_Stop(ghostData->SoundHandle);
3101 					Sound_Play(SID_MINIGUN_END,"hd",&(sbPtr->DynPtr->Position));
3102 				}
3103 			}
3104 			break;
3105 		}
3106 		case(WEAPON_FRISBEE_LAUNCHER):
3107 		{
3108 			LOCALASSERT(type==I_BehaviourMarinePlayer);
3109 			/* stop sound if we've got it */
3110 			if (firingPrimary) {
3111 				if (ghostData->SoundHandle!=SOUND_NOACTIVEINDEX) {
3112 					if (ActiveSounds[ghostData->SoundHandle].soundIndex!=SID_ED_SKEETERCHARGE) {
3113 						Sound_Stop(ghostData->SoundHandle);
3114 					}
3115 				}
3116 				if (ghostData->SoundHandle==SOUND_NOACTIVEINDEX) {
3117 					if (ghostData->soundStartFlag==0) {
3118 						Sound_Play(SID_ED_SKEETERCHARGE,"ehd",&ghostData->SoundHandle,&(sbPtr->DynPtr->Position));
3119 						ghostData->soundStartFlag = 1;
3120 					}
3121 				}
3122 			} else {
3123 				ghostData->soundStartFlag = 0;
3124 				if (ghostData->SoundHandle != SOUND_NOACTIVEINDEX) {
3125 					Sound_Stop(ghostData->SoundHandle);
3126 				}
3127 			}
3128 			break;
3129 		}
3130 		case(WEAPON_PRED_WRISTBLADE):
3131 		case(WEAPON_PRED_STAFF):
3132 		{
3133 			LOCALASSERT(type==I_BehaviourPredatorPlayer);
3134 			/* stop sound if we've got it */
3135 			//use the sounds connected to the hierarchy
3136 			#if 0
3137 			if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle);
3138 			if((firingPrimary)&&(ghostData->SoundHandle == SOUND_NOACTIVEINDEX))
3139 				Sound_Play(SID_SWIPE,"ehd",&(ghostData->SoundHandle),&(sbPtr->DynPtr->Position));
3140 			#endif
3141 			break;
3142 		}
3143 		case(WEAPON_PRED_PISTOL):
3144 		{
3145 			LOCALASSERT(type==I_BehaviourPredatorPlayer);
3146 			if(firingPrimary)
3147 			{
3148 				if(ghostData->SoundHandle == SOUND_NOACTIVEINDEX) {
3149 				   	Sound_Play(SID_PRED_PISTOL,"hd",&(sbPtr->DynPtr->Position));
3150 				}
3151 				//   	Sound_Play(SID_PULSE_LOOP,"elhd",&(ghostData->SoundHandle),&(sbPtr->DynPtr->Position));
3152 				//else
3153 				//	Sound_Update3d(ghostData->SoundHandle, &(sbPtr->DynPtr->Position));
3154 				#if 0
3155 				if (sbPtr->SBdptr)
3156 				{
3157 					ProveHModel(&ghostData->HModelController,sbPtr->SBdptr);
3158 					//create the particles for the pistol firing
3159 					{
3160 						SECTION_DATA *muzzle;
3161 						VECTORCH null_vec;
3162 
3163 						muzzle=GetThisSectionData(ghostData->HModelController.section_data,"dum flash");
3164 
3165 						null_vec.vx=0;
3166 						null_vec.vy=0;
3167 						null_vec.vz=0;
3168 
3169 						GLOBALASSERT(muzzle);
3170 
3171 //						FirePredPistolFlechettes(&muzzle->World_Offset,&null_vec,&muzzle->SecMat,0,&ghostData->timer,FALSE);
3172 //						CreatePPPlasmaBoltKernel(&muzzle->World_Offset,&muzzle->SecMat, 0);
3173 					}
3174 				}
3175 				#endif
3176 			}
3177 			else
3178 			{
3179 				//if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX)
3180 				//{
3181 				//	Sound_Stop(ghostData->SoundHandle);
3182 				//	Sound_Play(SID_PULSE_END,"hd",&(sbPtr->DynPtr->Position));
3183 				//}
3184 			}
3185 			break;
3186 		}
3187 		case(WEAPON_PRED_RIFLE):
3188 		{
3189 			LOCALASSERT(type==I_BehaviourPredatorPlayer);
3190 			#if 0
3191 			/* stop sound if we've got it */
3192 			if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle);
3193 			//sound is played by spear creation
3194 			#else
3195 			/* stop sound if we've got it */
3196 			if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle);
3197 			if(firingPrimary) Sound_Play(SID_PRED_LASER,"hd",&(sbPtr->DynPtr->Position));
3198 			#endif
3199 			break;
3200 		}
3201 		case(WEAPON_PRED_SHOULDERCANNON):
3202 		{
3203 			LOCALASSERT(type==I_BehaviourPredatorPlayer);
3204 			/* stop sound if we've got it */
3205 			if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle);
3206 			//sound is caused by energy bolt creation
3207 			break;
3208 		}
3209 		case(WEAPON_PRED_DISC):
3210 		{
3211 			LOCALASSERT(type==I_BehaviourPredatorPlayer);
3212 			/* stop sound if we've got it */
3213 			if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle);
3214 			/* currently no sound for this */
3215 			break;
3216 		}
3217 		case(WEAPON_ALIEN_CLAW):
3218 		{
3219 			//appropriate sounds should be triggered by the animation
3220 			#if 0
3221 			LOCALASSERT(type==I_BehaviourAlienPlayer);
3222 			/* stop sound if we've got it */
3223 			//if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle);
3224 
3225 			if((firingPrimary)&&(ghostData->SoundHandle == SOUND_NOACTIVEINDEX))
3226 				Sound_Play(SID_SWIPE,"ehd",&(ghostData->SoundHandle),&(sbPtr->DynPtr->Position));
3227 			#endif
3228 
3229 			break;
3230 		}
3231 		case(WEAPON_ALIEN_GRAB):
3232 		{
3233 			//appropriate sounds should be triggered by the animation
3234 			#if 0
3235 			LOCALASSERT(type==I_BehaviourAlienPlayer);
3236 			/* stop sound if we've got it */
3237 			if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle);
3238 			if((firingPrimary)&&(ghostData->SoundHandle == SOUND_NOACTIVEINDEX))
3239 				Sound_Play(SID_SWISH,"ehd",&(ghostData->SoundHandle),&(sbPtr->DynPtr->Position));
3240 			#endif
3241 			break;
3242 		}
3243 		case(WEAPON_ALIEN_SPIT):
3244 		{
3245 			LOCALASSERT(type==I_BehaviourAlienPlayer);
3246 			/* stop sound if we've got it */
3247 			if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle);
3248 			if(firingPrimary) Sound_Play(SID_PRED_NEWROAR,"hd",&(sbPtr->DynPtr->Position));
3249 			break;
3250 		}
3251 		case(WEAPON_PRED_MEDICOMP):
3252 		{
3253 			if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle);
3254 			break;
3255 		}
3256 		default:
3257 		{
3258 			LOCALASSERT(1==0);
3259 			/* stop sound if we've got it */
3260 			if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle);
3261 			break;
3262 		}
3263 	}
3264 }
3265 
ExtractTimerFromElevation(int elevation)3266 int ExtractTimerFromElevation(int elevation) {
3267 
3268 	int fake_timer,angle1;
3269 
3270 	if (elevation > 1024) elevation-=4096;
3271 	angle1=-elevation;
3272 
3273 	GLOBALASSERT(angle1>=-1024);
3274 	GLOBALASSERT(angle1<=1024);
3275 
3276 	fake_timer=1024-angle1;
3277 	fake_timer<<=5;
3278 	if (fake_timer==65536) fake_timer=65535;
3279 
3280 	GLOBALASSERT(fake_timer>=0);
3281 	GLOBALASSERT(fake_timer<65536);
3282 
3283 	return(fake_timer);
3284 }
3285 
3286 /* KJL 17:11:43 26/01/98 - weapon elevation */
HandleWeaponElevation(STRATEGYBLOCK * sbPtr,int elevation,int weapon)3287 void HandleWeaponElevation(STRATEGYBLOCK *sbPtr, int elevation, int weapon)
3288 {
3289 	NETGHOSTDATABLOCK *ghostDataPtr;
3290 	DELTA_CONTROLLER *elevation_controller;
3291 
3292 	LOCALASSERT(sbPtr);
3293 	ghostDataPtr = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
3294 	LOCALASSERT(ghostDataPtr);
3295 
3296 
3297 	LOCALASSERT(elevation>=0);
3298 	LOCALASSERT(elevation<4096);
3299 
3300 	if (ghostDataPtr->type == I_BehaviourMarinePlayer)
3301 	{
3302 		if (weapon != ghostDataPtr->CurrentWeapon)
3303 		{
3304 			Dispel_HModel(&ghostDataPtr->HModelController);
3305 			CreateMarineHModel(ghostDataPtr, weapon);
3306 			ProveHModel_Far(&ghostDataPtr->HModelController,sbPtr);
3307 		}
3308 
3309 		elevation_controller=Get_Delta_Sequence(&ghostDataPtr->HModelController,"Elevation");
3310 		/* Deal with elevation sequence. */
3311 		GLOBALASSERT(elevation_controller);
3312 		elevation_controller->Active=1;
3313 		switch(ghostDataPtr->currentAnimSequence) {
3314 			case MSQ_StandDieFront:
3315 			case MSQ_StandDieBack:
3316 			case MSQ_StandDeadFront:
3317 			case MSQ_StandDeadBack:
3318 			case MSQ_CrouchDie:
3319 			case MSQ_CrouchDead:
3320 			case MSQ_Taunt:
3321 				{
3322 					/* Force no elevation. */
3323 					elevation_controller->Active=0;
3324 					break;
3325 				}
3326 			case MSQ_RunningFire:
3327 			case MSQ_RunningFire_Backwards:
3328 				if (ghostDataPtr->CurrentWeapon==WEAPON_GRENADELAUNCHER) {
3329 					elevation_controller->Active=0;
3330 					ghostDataPtr->HModelController.Looped=0;
3331 					break;
3332 				} else if (ghostDataPtr->CurrentWeapon==WEAPON_TWO_PISTOLS) {
3333 					if (ghostDataPtr->HModelController.Sub_Sequence==MRSS_Fire_From_Hips) {
3334 						elevation_controller->sequence_type=HMSQT_MarineStand;
3335 						elevation_controller->sub_sequence=(int)MSSS_Hip_Fire_Elevation;
3336 					} else {
3337 						if (HModelSequence_Exists(&ghostDataPtr->HModelController,
3338 							HMSQT_MarineRun,(int)MRSS_Elevation)) {
3339 							elevation_controller->sequence_type=HMSQT_MarineRun;
3340 							elevation_controller->sub_sequence=(int)MRSS_Elevation;
3341 						} else {
3342 							elevation_controller->sequence_type=HMSQT_MarineStand;
3343 							elevation_controller->sub_sequence=(int)MSSS_Elevation;
3344 						}
3345 					}
3346 					elevation_controller->timer=ExtractTimerFromElevation(elevation);
3347 				} else {
3348 					if (HModelSequence_Exists(&ghostDataPtr->HModelController,
3349 						HMSQT_MarineRun,(int)MRSS_Elevation)) {
3350 						elevation_controller->sequence_type=HMSQT_MarineRun;
3351 						elevation_controller->sub_sequence=(int)MRSS_Elevation;
3352 					} else {
3353 						elevation_controller->sequence_type=HMSQT_MarineStand;
3354 						elevation_controller->sub_sequence=(int)MSSS_Elevation;
3355 					}
3356 					elevation_controller->timer=ExtractTimerFromElevation(elevation);
3357 					break;
3358 				}
3359 			case MSQ_StandingFire:
3360 				if (ghostDataPtr->CurrentWeapon==WEAPON_GRENADELAUNCHER) {
3361 					elevation_controller->Active=0;
3362 					ghostDataPtr->HModelController.Looped=0;
3363 					break;
3364 				} else if (ghostDataPtr->CurrentWeapon==WEAPON_TWO_PISTOLS) {
3365 					if (ghostDataPtr->HModelController.Sub_Sequence==MSSS_FireFromHips) {
3366 						elevation_controller->sequence_type=HMSQT_MarineStand;
3367 						elevation_controller->sub_sequence=(int)MSSS_Hip_Fire_Elevation;
3368 					} else {
3369 						elevation_controller->sequence_type=HMSQT_MarineStand;
3370 						elevation_controller->sub_sequence=(int)MSSS_Elevation;
3371 					}
3372 					elevation_controller->timer=ExtractTimerFromElevation(elevation);
3373 				} else {
3374 					elevation_controller->sequence_type=HMSQT_MarineStand;
3375 					elevation_controller->sub_sequence=(int)MSSS_Elevation;
3376 					elevation_controller->timer=ExtractTimerFromElevation(elevation);
3377 					break;
3378 				}
3379 			case MSQ_Walk:
3380 			case MSQ_Walk_Backwards:
3381 				{
3382 					if (ghostDataPtr->CurrentWeapon==WEAPON_TWO_PISTOLS) {
3383 						if (ghostDataPtr->HModelController.Sub_Sequence==MRSS_Fire_From_Hips) {
3384 							elevation_controller->sequence_type=HMSQT_MarineStand;
3385 							elevation_controller->sub_sequence=(int)MSSS_Hip_Fire_Elevation;
3386 						} else {
3387 							if (HModelSequence_Exists(&ghostDataPtr->HModelController,
3388 								HMSQT_MarineRun,(int)MRSS_Elevation)) {
3389 								elevation_controller->sequence_type=HMSQT_MarineRun;
3390 								elevation_controller->sub_sequence=(int)MRSS_Elevation;
3391 							} else {
3392 								elevation_controller->sequence_type=HMSQT_MarineStand;
3393 								elevation_controller->sub_sequence=(int)MSSS_Elevation;
3394 							}
3395 						}
3396 						elevation_controller->timer=ExtractTimerFromElevation(elevation);
3397 					} else {
3398 						if (HModelSequence_Exists(&ghostDataPtr->HModelController,
3399 							HMSQT_MarineRun,(int)MRSS_Elevation)) {
3400 							elevation_controller->sequence_type=HMSQT_MarineRun;
3401 							elevation_controller->sub_sequence=(int)MRSS_Elevation;
3402 						} else {
3403 							elevation_controller->sequence_type=HMSQT_MarineStand;
3404 							elevation_controller->sub_sequence=(int)MSSS_Elevation;
3405 						}
3406 						elevation_controller->timer=ExtractTimerFromElevation(elevation);
3407 					}
3408 					break;
3409 				}
3410 			case MSQ_Crawl:
3411 			case MSQ_Crawl_Backwards:
3412 				{
3413 					if (ghostDataPtr->CurrentWeapon==WEAPON_TWO_PISTOLS) {
3414 						if (ghostDataPtr->HModelController.Sub_Sequence==MCSS_FireFromHips) {
3415 							elevation_controller->sequence_type=HMSQT_MarineCrouch;
3416 							elevation_controller->sub_sequence=(int)MCrSS_Hip_Fire_Elevation;
3417 						} else {
3418 							if (HModelSequence_Exists(&ghostDataPtr->HModelController,
3419 								HMSQT_MarineCrawl,(int)MCSS_Elevation)) {
3420 								elevation_controller->sequence_type=HMSQT_MarineCrawl;
3421 								elevation_controller->sub_sequence=(int)MCSS_Elevation;
3422 							} else {
3423 								elevation_controller->sequence_type=HMSQT_MarineCrouch;
3424 								elevation_controller->sub_sequence=(int)MCrSS_Elevation;
3425 							}
3426 						}
3427 					} else {
3428 						if (HModelSequence_Exists(&ghostDataPtr->HModelController,
3429 							HMSQT_MarineCrawl,(int)MCSS_Elevation)) {
3430 							elevation_controller->sequence_type=HMSQT_MarineCrawl;
3431 							elevation_controller->sub_sequence=(int)MCSS_Elevation;
3432 						} else {
3433 							elevation_controller->sequence_type=HMSQT_MarineCrouch;
3434 							elevation_controller->sub_sequence=(int)MCrSS_Elevation;
3435 						}
3436 					}
3437 					elevation_controller->timer=ExtractTimerFromElevation(elevation);
3438 					break;
3439 				}
3440 			case MSQ_Crouch:
3441 				{
3442 					if (ghostDataPtr->CurrentWeapon==WEAPON_TWO_PISTOLS) {
3443 						if (ghostDataPtr->HModelController.Sub_Sequence==MCrSS_FireFromHips) {
3444 							elevation_controller->sequence_type=HMSQT_MarineCrouch;
3445 							elevation_controller->sub_sequence=(int)MCrSS_Hip_Fire_Elevation;
3446 						} else {
3447 							elevation_controller->sequence_type=HMSQT_MarineCrouch;
3448 							elevation_controller->sub_sequence=(int)MCrSS_Elevation;
3449 						}
3450 					} else {
3451 						elevation_controller->sequence_type=HMSQT_MarineCrouch;
3452 						elevation_controller->sub_sequence=(int)MCrSS_Elevation;
3453 					}
3454 					elevation_controller->timer=ExtractTimerFromElevation(elevation);
3455 					break;
3456 				}
3457 			case MSQ_Stand:
3458 			case MSQ_Jump:
3459 			default:
3460 				{
3461 					if (ghostDataPtr->CurrentWeapon==WEAPON_TWO_PISTOLS) {
3462 						if (ghostDataPtr->HModelController.Sub_Sequence==MSSS_FireFromHips) {
3463 							elevation_controller->sequence_type=HMSQT_MarineStand;
3464 							elevation_controller->sub_sequence=(int)MSSS_Hip_Fire_Elevation;
3465 						} else {
3466 							elevation_controller->sequence_type=HMSQT_MarineStand;
3467 							elevation_controller->sub_sequence=(int)MSSS_Elevation;
3468 						}
3469 					} else {
3470 						elevation_controller->sequence_type=HMSQT_MarineStand;
3471 						elevation_controller->sub_sequence=(int)MSSS_Elevation;
3472 					}
3473 					elevation_controller->timer=ExtractTimerFromElevation(elevation);
3474 				}
3475 				break;
3476 		}
3477 		if ((HModelSequence_Exists(&ghostDataPtr->HModelController,elevation_controller->sequence_type,elevation_controller->sub_sequence))
3478 			&& (elevation_controller->Active)) {
3479 			elevation_controller->Active=1;
3480 			textprint("Using elevation delta.\n");
3481 		} else {
3482 			elevation_controller->Active=0;
3483 		}
3484 	}
3485 	else if (ghostDataPtr->type == I_BehaviourPredatorPlayer)
3486 	{
3487 		if (weapon != ghostDataPtr->CurrentWeapon)
3488 		{
3489 			Dispel_HModel(&ghostDataPtr->HModelController);
3490 			CreatePredatorHModel(ghostDataPtr, weapon);
3491 			ProveHModel_Far(&ghostDataPtr->HModelController,sbPtr);
3492 		}
3493 		elevation_controller=Get_Delta_Sequence(&ghostDataPtr->HModelController,"Elevation");
3494 		/* Deal with elevation sequence. */
3495 		GLOBALASSERT(elevation_controller);
3496 		elevation_controller->Active=1; /* enabled? */
3497 		switch(ghostDataPtr->currentAnimSequence) {
3498 			case PredSQ_Taunt:
3499 			case PredSQ_StandDie:
3500 			case PredSQ_StandDead:
3501 			case PredSQ_CrouchDie:
3502 			case PredSQ_CrouchDead:
3503 				{
3504 					elevation_controller->Active=0;
3505 					/* Force no elevation. */
3506 					break;
3507 				}
3508 			case PredSQ_Run:
3509 			case PredSQ_Run_Backwards:
3510 			case PredSQ_RunningSwipe:
3511 			case PredSQ_RunningSwipe_Backwards:
3512 				{
3513 					elevation_controller->sequence_type=HMSQT_PredatorStand;
3514 					elevation_controller->sub_sequence=(int)PSSS_Elevation;
3515 					elevation_controller->timer=ExtractTimerFromElevation(elevation);
3516 				}
3517 				break;
3518 			case PredSQ_Crouch:
3519 			case PredSQ_CrouchedSwipe:
3520 				{
3521 					elevation_controller->sequence_type=HMSQT_PredatorCrouch;
3522 					elevation_controller->sub_sequence=(int)PCrSS_Elevation;
3523 					elevation_controller->timer=ExtractTimerFromElevation(elevation);
3524 				}
3525 				break;
3526 			case PredSQ_Crawl:
3527 			case PredSQ_CrawlingSwipe:
3528 			case PredSQ_Crawl_Backwards:
3529 			case PredSQ_CrawlingSwipe_Backwards:
3530 				{
3531 					elevation_controller->sequence_type=HMSQT_PredatorCrouch;
3532 					elevation_controller->sub_sequence=(int)PCrSS_Elevation;
3533 					elevation_controller->timer=ExtractTimerFromElevation(elevation);
3534 				}
3535 				break;
3536 			case PredSQ_Jump:
3537 			case PredSQ_Stand:
3538 			case PredSQ_StandingSwipe:
3539 			default:
3540 				{
3541 					elevation_controller->sequence_type=HMSQT_PredatorStand;
3542 					elevation_controller->sub_sequence=(int)PSSS_Elevation;
3543 					elevation_controller->timer=ExtractTimerFromElevation(elevation);
3544 				}
3545 				break;
3546 		}
3547 		if ((HModelSequence_Exists(&ghostDataPtr->HModelController,elevation_controller->sequence_type,elevation_controller->sub_sequence))
3548 			&& (elevation_controller->Active)) {
3549 			elevation_controller->Active=1;
3550 		} else {
3551 			elevation_controller->Active=0;
3552 		}
3553 	}
3554 	else if (ghostDataPtr->type == I_BehaviourAlienPlayer)
3555 	{
3556 
3557 		if (ghostDataPtr->CurrentWeapon==-1)
3558 		{
3559 			//this only happens for aliens , if a player changes character
3560 			Dispel_HModel(&ghostDataPtr->HModelController);
3561 			CreateAlienHModel(ghostDataPtr,0);
3562 			ProveHModel_Far(&ghostDataPtr->HModelController,sbPtr);
3563 		}
3564 
3565 		elevation_controller=Get_Delta_Sequence(&ghostDataPtr->HModelController,"Elevation");
3566 		/* Deal with elevation sequence. */
3567 		GLOBALASSERT(elevation_controller);
3568 		elevation_controller->Active=1; /* enabled? */
3569 		switch(ghostDataPtr->currentAnimSequence) {
3570 			case ASQ_Pain:
3571 			case ASQ_Jump:
3572 			case ASQ_Eat:
3573 			case ASQ_Pounce:
3574 			case ASQ_JumpingTailPoise:
3575 			case ASQ_JumpingTailStrike:
3576 			case ASQ_Taunt:
3577 				{
3578 					elevation_controller->Active=0;
3579 					/* Force no elevation. */
3580 					break;
3581 				}
3582 			case ASQ_Crouch:
3583 			case ASQ_CrouchedAttack_Claw:
3584 			case ASQ_CrouchedTailPoise:
3585 			case ASQ_CrouchedTailStrike:
3586 			case ASQ_Crawl:
3587 			case ASQ_CrawlingAttack_Claw:
3588 			case ASQ_CrawlingTailPoise:
3589 			case ASQ_CrawlingTailStrike:
3590 			case ASQ_Crawl_Backwards:
3591 			case ASQ_CrawlingTailPoise_Backwards:
3592 			case ASQ_CrawlingTailStrike_Backwards:
3593 			case ASQ_CrawlingAttack_Claw_Backwards:
3594 			case ASQ_Scamper:
3595 			case ASQ_Scamper_Backwards:
3596 			case ASQ_CrouchEat :
3597 				{
3598 					elevation_controller->sequence_type=HMSQT_AlienCrouch;
3599 					elevation_controller->sub_sequence=(int)ACrSS_Standard_Elevation;
3600 					elevation_controller->timer=ExtractTimerFromElevation(elevation);
3601 					break;
3602 				}
3603 			case ASQ_Run:
3604 			case ASQ_RunningAttack_Claw:
3605 			case ASQ_RunningTailPoise:
3606 			case ASQ_RunningTailStrike:
3607 			case ASQ_Run_Backwards:
3608 			case ASQ_RunningAttack_Claw_Backwards:
3609 			case ASQ_RunningTailPoise_Backwards:
3610 			case ASQ_RunningTailStrike_Backwards:
3611 			case ASQ_Stand:
3612 			case ASQ_StandingAttack_Claw:
3613 			case ASQ_StandingTailPoise:
3614 			case ASQ_StandingTailStrike:
3615 				{
3616 					elevation_controller->sequence_type=HMSQT_AlienStand;
3617 					elevation_controller->sub_sequence=(int)ASSS_Standard_Elevation;
3618 					elevation_controller->timer=ExtractTimerFromElevation(elevation);
3619 					break;
3620 				}
3621 			default:
3622 				{
3623 					elevation_controller->sequence_type=HMSQT_AlienStand;
3624 					elevation_controller->sub_sequence=(int)ASSS_Standard_Elevation;
3625 					elevation_controller->timer=ExtractTimerFromElevation(elevation);
3626 				}
3627 				break;
3628 		}
3629 		if ((HModelSequence_Exists(&ghostDataPtr->HModelController,elevation_controller->sequence_type,elevation_controller->sub_sequence))
3630 			&& (elevation_controller->Active)) {
3631 			elevation_controller->Active=1;
3632 		} else {
3633 			elevation_controller->Active=0;
3634 		}
3635 	}
3636 
3637 
3638 }
3639 
3640 
3641 /* Patrick 15/7/97 --------------------------------------------------
3642 Manages the ghost's integrities
3643 ---------------------------------------------------------------------*/
MaintainGhosts(void)3644 void MaintainGhosts(void)
3645 {
3646 	extern int NumActiveStBlocks;
3647 	extern STRATEGYBLOCK *ActiveStBlockList[];
3648 
3649 	int sbIndex = 0;
3650 	STRATEGYBLOCK *sbPtr;
3651 
3652 	/* only do this when we're playing */
3653 	if(netGameData.myGameState!=NGS_Playing) return;
3654 
3655 	while(sbIndex < NumActiveStBlocks)
3656 	{
3657 		sbPtr = ActiveStBlockList[sbIndex++];
3658 		if(sbPtr->I_SBtype==I_BehaviourNetGhost)
3659 		{
3660 			NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
3661 			LOCALASSERT(ghostData);
3662 			ghostData->integrity-=NormalFrameTime;
3663 			if(ghostData->integrity<0) {
3664 				RemoveGhost(sbPtr);
3665 			}
3666 			else switch (ghostData->type)
3667 			{
3668 				case I_BehaviourFlareGrenade:
3669 				{
3670 					if (ghostData->timer>ONE_FIXED*4)
3671 					{
3672 						/* EventCounter - was in anon. union with currentAnimSequence */
3673 						ghostData->currentAnimSequence += NormalFrameTime;
3674 					}
3675 					else
3676 					{
3677 						/* EventCounter */
3678 						ghostData->currentAnimSequence += MUL_FIXED(NormalFrameTime,ghostData->timer)/4;
3679 					}
3680 
3681 			   		/* EventCounter */
3682 					while (ghostData->currentAnimSequence >= FLARE_PARTICLE_GENERATION_TIME)
3683 					{
3684 						/* EventCounter */
3685 						ghostData->currentAnimSequence -= FLARE_PARTICLE_GENERATION_TIME;
3686 						MakeFlareParticle(sbPtr->DynPtr);
3687 					}
3688 
3689 					/* add lighting effect if near */
3690 					if (sbPtr->SBdptr)
3691 					{
3692 						LIGHTBLOCK *lightPtr = sbPtr->SBdptr->ObLights[0];
3693 						LOCALASSERT(sbPtr->SBdptr->ObNumLights==1);
3694 						LOCALASSERT(lightPtr);
3695 						lightPtr->LightBright = 1+MUL_FIXED
3696 												(
3697 													(ONE_FIXED*4-(FastRandom()&32767)),
3698 													ghostData->timer/FLARE_LIFETIME
3699 												);
3700 					}
3701 			   		ghostData->timer -= NormalFrameTime;
3702 
3703 					//Stop flare from disappearing from lack of update messages.
3704 					//This is so the number of meessages sent can be reduced when the flare has stopped moving.
3705 					ghostData->integrity=ghostData->timer;
3706 
3707 					break;
3708 				}
3709 				case I_BehaviourProximityGrenade:
3710 				{
3711 					DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
3712 					LOCALASSERT(dynPtr);
3713 					if (ghostData->timer<=PROX_GRENADE_LIFETIME*ONE_FIXED)
3714 					{
3715 						{
3716 							int scale = ONE_FIXED-ghostData->timer/PROX_GRENADE_LIFETIME;
3717 							scale = MUL_FIXED(scale,scale);
3718 							scale = MUL_FIXED(scale,scale)*8;
3719 
3720 							/* EventCounter */
3721 							ghostData->currentAnimSequence += NormalFrameTime + MUL_FIXED(NormalFrameTime,scale);
3722 				   		}
3723 				   		/* EventCounter */
3724 						while (ghostData->currentAnimSequence >= PROX_GRENADE_SOUND_GENERATION_TIME)
3725 						{
3726 							/* EventCounter */
3727 							ghostData->currentAnimSequence -= PROX_GRENADE_SOUND_GENERATION_TIME;
3728 							Sound_Play(SID_PROX_GRENADE_ACTIVE,"d",&(dynPtr->Position));
3729 						}
3730 
3731 				   		ghostData->timer -= NormalFrameTime;
3732 					   	if (ghostData->timer<=PROX_GRENADE_TRIGGER_TIME && ghostData->SoundHandle==SOUND_NOACTIVEINDEX)
3733 						{
3734 							Sound_Play(SID_PROX_GRENADE_READYTOBLOW,"de",&(dynPtr->Position),&ghostData->SoundHandle);
3735 						}
3736 
3737 						//Stop flare from disappearing from lack of update messages.
3738 						//This is so the number of meessages sent can be reduced when the flare has stopped moving.
3739 					}
3740 					else
3741 					{
3742 						if(!(dynPtr->Position.vx!=dynPtr->PrevPosition.vx ||
3743 						     dynPtr->Position.vy!=dynPtr->PrevPosition.vy ||
3744 						     dynPtr->Position.vz!=dynPtr->PrevPosition.vz))
3745 						{
3746 							ghostData->timer = PROX_GRENADE_LIFETIME*ONE_FIXED;
3747 						}
3748 					}
3749 					{
3750 						// scan for objects in proximity
3751 						extern int NumActiveStBlocks;
3752 						extern STRATEGYBLOCK *ActiveStBlockList[];
3753 						int i = NumActiveStBlocks;
3754 						while(i--)
3755 						{
3756 							STRATEGYBLOCK *obstaclePtr = ActiveStBlockList[i];
3757 							DYNAMICSBLOCK *obstacleDynPtr = obstaclePtr->DynPtr;
3758 
3759 							if (obstacleDynPtr)
3760 							{
3761 								if(ValidTargetForProxMine(obstaclePtr))
3762 								{
3763 									VECTORCH disp = obstacleDynPtr->Position;
3764 									disp.vx -= dynPtr->Position.vx;
3765 									disp.vy -= dynPtr->Position.vy;
3766 									disp.vz -= dynPtr->Position.vz;
3767 
3768 									if (Approximate3dMagnitude(&disp)<=PROX_GRENADE_RANGE)
3769 									{
3770 										if(ghostData->SoundHandle  != SOUND_NOACTIVEINDEX)
3771 										{
3772 											if (ActiveSounds[ghostData->SoundHandle].soundIndex!=SID_PROX_GRENADE_READYTOBLOW)
3773 											{
3774 												Sound_Stop(ghostData->SoundHandle);
3775 											}
3776 											else
3777 											{
3778 												break;
3779 											}
3780 										}
3781 										Sound_Play(SID_PROX_GRENADE_READYTOBLOW,"de",&(dynPtr->Position),&ghostData->SoundHandle);
3782 										break;
3783 									}
3784 								}
3785 							}
3786 						}
3787 					}
3788 
3789 					ghostData->integrity=ghostData->timer;
3790 					break;
3791 				}
3792 				default:
3793 					break;
3794 			}
3795 		}
3796 	}
3797 }
3798 
3799 /* Patrick 13/10/97 --------------------------------------------------
3800 Added for autogun ghost support
3801 ---------------------------------------------------------------------*/
3802 #define AGUNGHOST_FIRINGPOINT_INFRONT	500
3803 #define AGUNGHOST_FIRINGPOINT_ACROSS	0
3804 #define AGUNGHOST_FIRINGPOINT_UP		200
3805 
HandleGhostAutoGunMuzzleFlash(STRATEGYBLOCK * sbPtr,int firing)3806 void HandleGhostAutoGunMuzzleFlash(STRATEGYBLOCK *sbPtr, int firing)
3807 {
3808 	NETGHOSTDATABLOCK *ghostData;
3809 
3810 	LOCALASSERT(sbPtr);
3811 	ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
3812 	LOCALASSERT(ghostData);
3813 	LOCALASSERT(ghostData->type == I_BehaviourAutoGun);
3814 
3815 	if(ghostData->myGunFlash)
3816 	{
3817 		/* I've already got a gun flash... */
3818 		if(firing)
3819 		{
3820 			/* Maintain existing gun flash */
3821 			VECTORCH position;
3822 			EULER orientation;
3823 			MATRIXCH mat;
3824 			CalculatePosnForGhostAutoGunMuzzleFlash(sbPtr, &position, &orientation);
3825 
3826 			CreateEulerMatrix(&orientation, &mat);
3827 			TransposeMatrixCH(&mat);
3828 
3829 			MaintainNPCGunFlashEffect(ghostData->myGunFlash, &position, &mat);
3830 		}
3831 		else
3832 		{
3833 			RemoveNPCGunFlashEffect(ghostData->myGunFlash);
3834 			ghostData->myGunFlash = NULL;
3835 		}
3836 	}
3837 	else
3838 	{
3839 		if(firing)
3840 		{
3841   			/* Need a new gun flash */
3842 			VECTORCH position;
3843 			EULER orientation;
3844 			MATRIXCH mat;
3845 			CalculatePosnForGhostAutoGunMuzzleFlash(sbPtr, &position, &orientation);
3846 			CreateEulerMatrix(&orientation, &mat);
3847 			TransposeMatrixCH(&mat);
3848 			ghostData->myGunFlash = AddNPCGunFlashEffect(&position, &mat, SFX_MUZZLE_FLASH_AMORPHOUS);
3849 		}
3850 	}
3851 }
3852 
HandleGhostAutoGunSound(STRATEGYBLOCK * sbPtr,int firing)3853 void HandleGhostAutoGunSound(STRATEGYBLOCK *sbPtr, int firing)
3854 {
3855 	NETGHOSTDATABLOCK *ghostData;
3856 	AVP_BEHAVIOUR_TYPE type;
3857 
3858 	LOCALASSERT(sbPtr);
3859 	LOCALASSERT(sbPtr->DynPtr);
3860 
3861 	ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
3862 	LOCALASSERT(ghostData);
3863 	type = ghostData->type;
3864 	LOCALASSERT(type==I_BehaviourAutoGun);
3865 
3866 	if(firing)
3867 	{
3868 		if(ghostData->SoundHandle == SOUND_NOACTIVEINDEX)
3869 			Sound_Play(SID_SENTRY_GUN,"eld",&(ghostData->SoundHandle),&(sbPtr->DynPtr->Position));
3870 		/* don't need sound update, as autoguns don't move */
3871 	}
3872 	else if(ghostData->SoundHandle != SOUND_NOACTIVEINDEX)
3873 	{
3874 		Sound_Stop(ghostData->SoundHandle);
3875 		Sound_Play(SID_SENTRY_END,"hd",&(sbPtr->DynPtr->Position));
3876 	}
3877 }
3878 
CalculatePosnForGhostAutoGunMuzzleFlash(STRATEGYBLOCK * sbPtr,VECTORCH * position,EULER * orientation)3879 static void CalculatePosnForGhostAutoGunMuzzleFlash(STRATEGYBLOCK *sbPtr,VECTORCH *position, EULER *orientation)
3880 {
3881 	VECTORCH upNormal = {0,-65536,0};
3882 	VECTORCH inFrontVec = {0,0,0};
3883 	VECTORCH toSideVec = {0,0,0};
3884 	EULER firingOrient = {0,0,0};
3885 
3886 	/* orientation is easy */
3887 	firingOrient.EulerY = sbPtr->DynPtr->OrientEuler.EulerY;
3888 	*orientation = firingOrient;
3889 
3890 	/* vector in front */
3891 	inFrontVec.vx = GetSin(firingOrient.EulerY);
3892 	inFrontVec.vz = GetCos(firingOrient.EulerY);
3893 	Normalise(&inFrontVec);
3894 
3895 	/* vectors in front, to side, and up */
3896 	CrossProduct(&inFrontVec,&upNormal,&toSideVec);
3897 	LOCALASSERT(toSideVec.vy==0);
3898 	inFrontVec.vx = MUL_FIXED(inFrontVec.vx,AGUNGHOST_FIRINGPOINT_INFRONT);
3899 	inFrontVec.vz = MUL_FIXED(inFrontVec.vz,AGUNGHOST_FIRINGPOINT_INFRONT);
3900 	toSideVec.vx = MUL_FIXED(toSideVec.vx,AGUNGHOST_FIRINGPOINT_ACROSS);
3901 	toSideVec.vz = MUL_FIXED(toSideVec.vz,AGUNGHOST_FIRINGPOINT_ACROSS);
3902 
3903 	position->vx = sbPtr->DynPtr->Position.vx + inFrontVec.vx +	toSideVec.vx;
3904 	position->vy = sbPtr->DynPtr->Position.vy - AGUNGHOST_FIRINGPOINT_UP;
3905 	position->vz = sbPtr->DynPtr->Position.vz + inFrontVec.vz +	toSideVec.vz;
3906 }
3907 
3908 /* patrick 14/10/97 : added to support cloaked predators in net game */
MaintainGhostCloakingStatus(STRATEGYBLOCK * sbPtr,int IsCloaked)3909 void MaintainGhostCloakingStatus(STRATEGYBLOCK *sbPtr, int IsCloaked)
3910 {
3911 	NETGHOSTDATABLOCK *ghostData;
3912 	AVP_BEHAVIOUR_TYPE type;
3913 
3914 	LOCALASSERT(sbPtr);
3915 	ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
3916 	LOCALASSERT(ghostData);
3917 	type = ghostData->type;
3918 
3919 	if(type!=I_BehaviourPredatorPlayer)
3920 	{
3921 		ghostData->CloakingEffectiveness = 0;
3922 		return;
3923 	}
3924 
3925 	/* Handle sound playing. */
3926 	if (ghostData->CloakingEffectiveness) {
3927 		if (IsCloaked==0) {
3928 			/* Cloak turns off. */
3929 			Sound_Play(SID_PRED_CLOAKOFF,"hd",&(sbPtr->DynPtr->Position));
3930 		}
3931 	} else {
3932 		if (IsCloaked) {
3933 			/* Cloak turns on. */
3934 			Sound_Play(SID_PRED_CLOAKON,"hd",&(sbPtr->DynPtr->Position));
3935 		}
3936 	}
3937 
3938 	ghostData->CloakingEffectiveness = IsCloaked;
3939 }
3940 
3941 
3942 /* KJL 14:18:32 27/01/98 - object behaviour for network ghosts */
NetGhostBehaviour(STRATEGYBLOCK * sbPtr)3943 extern void NetGhostBehaviour(STRATEGYBLOCK *sbPtr)
3944 {
3945 	NETGHOSTDATABLOCK *ghostDataPtr;
3946 
3947     LOCALASSERT(sbPtr);
3948 
3949 	ghostDataPtr = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
3950 	LOCALASSERT(ghostDataPtr);
3951 
3952 	switch(ghostDataPtr->type)
3953 	{
3954 		case I_BehaviourNetCorpse:
3955 		{
3956 			/* A copy of the fn. for real ones, minus existance. */
3957 			DISPLAYBLOCK *dispPtr = sbPtr->SBdptr;
3958 
3959 			/* do we have a displayblock? */
3960 			if (dispPtr)
3961 			{
3962 				dispPtr->SpecialFXFlags |= SFXFLAG_MELTINGINTOGROUND;
3963 				dispPtr->ObFlags2 = ghostDataPtr->timer/2;
3964 
3965 			}
3966 
3967 			/* Does the corpse that falls when not visible make no sound? */
3968 			ProveHModel_Far(&ghostDataPtr->HModelController,sbPtr);
3969 			ghostDataPtr->timer-=NormalFrameTime;
3970 			break;
3971 		}
3972 		default:
3973 			break;
3974 	}
3975 
3976 	if (sbPtr->SBdptr) {
3977 		if (sbPtr->SBdptr->HModelControlBlock) {
3978 
3979 			/* Fire sound code. */
3980 			if(ghostDataPtr->SoundHandle3!=SOUND_NOACTIVEINDEX) Sound_Update3d(ghostDataPtr->SoundHandle3,&(sbPtr->DynPtr->Position));
3981 			if(ghostDataPtr->SoundHandle4!=SOUND_NOACTIVEINDEX) Sound_Update3d(ghostDataPtr->SoundHandle4,&(sbPtr->DynPtr->Position));
3982 
3983 			if (sbPtr->SBDamageBlock.IsOnFire) {
3984 				if (ghostDataPtr->IgnitionHandshaking==0) {
3985 					AddNetMsg_LocalObjectOnFire(sbPtr);
3986 				}
3987 				if (ghostDataPtr->SoundHandle3!=SOUND_NOACTIVEINDEX) {
3988 					if (ActiveSounds[ghostDataPtr->SoundHandle3].soundIndex!=SID_FIRE) {
3989 						Sound_Stop(ghostDataPtr->SoundHandle3);
3990 					 	Sound_Play(SID_FIRE,"dlev",&(sbPtr->DynPtr->Position),&ghostDataPtr->SoundHandle3,127);
3991 					}
3992 				} else {
3993 				 	Sound_Play(SID_FIRE,"dlev",&(sbPtr->DynPtr->Position),&ghostDataPtr->SoundHandle3,127);
3994 				}
3995 			} else {
3996 				if (ghostDataPtr->SoundHandle3!=SOUND_NOACTIVEINDEX) {
3997 					Sound_Stop(ghostDataPtr->SoundHandle3);
3998 				}
3999 			}
4000 		}
4001 	}
4002 
4003 	if(ghostDataPtr->FlameHitCount)
4004 	{
4005 		//send a damage message for all the flame particles that have hit
4006 		CauseDamageToObject(sbPtr,&TemplateAmmo[AMMO_FLAMETHROWER].MaxDamage[AvP.Difficulty], (ONE_FIXED/400)*ghostDataPtr->FlameHitCount,NULL);
4007 		ghostDataPtr->FlameHitCount=0;
4008 
4009 	}
4010 	if(ghostDataPtr->FlechetteHitCount)
4011 	{
4012 		//send a damage message for all the flechette particles that have hit
4013 		extern DAMAGE_PROFILE FlechetteDamage;
4014 		CauseDamageToObject(sbPtr,&FlechetteDamage,ONE_FIXED*ghostDataPtr->FlechetteHitCount,NULL);
4015 		ghostDataPtr->FlechetteHitCount=0;
4016 
4017 	}
4018 }
4019 
MaintainGhostFireStatus(STRATEGYBLOCK * sbPtr,int IsOnFire)4020 void MaintainGhostFireStatus(STRATEGYBLOCK *sbPtr, int IsOnFire)
4021 {
4022 	NETGHOSTDATABLOCK *ghostData;
4023 
4024 	LOCALASSERT(sbPtr);
4025 	ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
4026 	LOCALASSERT(ghostData);
4027 
4028 	if (IsOnFire) {
4029 		if (ghostData->IgnitionHandshaking==0) {
4030 			/* Recieved confirmation. */
4031 			ghostData->IgnitionHandshaking=1;
4032 			if (sbPtr->SBDamageBlock.IsOnFire==0) {
4033 				/* Set alight by something else? */
4034 				sbPtr->SBDamageBlock.IsOnFire=1;
4035 			}
4036 		} else {
4037 			/* Corroberated - do nothing. */
4038 		}
4039 	} else {
4040 		if (ghostData->IgnitionHandshaking==0) {
4041 			/* Corroberated - do nothing. */
4042 		} else {
4043 			/* Fire gone out? */
4044 			ghostData->IgnitionHandshaking=0;
4045 			sbPtr->SBDamageBlock.IsOnFire=0;
4046 		}
4047 	}
4048 }
4049 
Engage_Template_Death(STRATEGYBLOCK * sbPtr,SECTION * root,HMODELCONTROLLER * controller,int type,int subtype,int length,int tweening)4050 void Engage_Template_Death(STRATEGYBLOCK *sbPtr,SECTION *root,HMODELCONTROLLER *controller,int type, int subtype,
4051 	int length, int tweening) {
4052 
4053 	RemoveAllDeltas(controller);
4054 	Transmogrify_HModels(sbPtr,controller, root, 1, 0,0);
4055 	InitHModelTweening(controller,tweening,type,subtype,length,0);
4056 
4057 }
4058 
Create_Marine_Standing_Template_Death(STRATEGYBLOCK * sbPtr,HMODELCONTROLLER * controller,int type,int subtype,int length,int tweening)4059 void Create_Marine_Standing_Template_Death(STRATEGYBLOCK *sbPtr,HMODELCONTROLLER *controller,int type, int subtype,
4060 	int length, int tweening) {
4061 
4062 	/* Standing template. */
4063 	SECTION *root;
4064 
4065 	/* This has gotta be considered weird. */
4066 	InitHModelSequence(controller,(int)HMSQT_MarineStand,
4067 		(int)MSSS_Dies_Standard,(ONE_FIXED<<1));
4068 	ProveHModel_Far(controller,sbPtr);
4069 	/* And now we change it.  See? */
4070 
4071 	root=GetNamedHierarchyFromLibrary("hnpcmarine","Template");
4072 
4073 	Engage_Template_Death(sbPtr,root,controller,type,subtype,length,tweening);
4074 
4075 }
4076 
Create_Predator_Standing_Template_Death(STRATEGYBLOCK * sbPtr,HMODELCONTROLLER * controller,int type,int subtype,int length,int tweening)4077 void Create_Predator_Standing_Template_Death(STRATEGYBLOCK *sbPtr,HMODELCONTROLLER *controller,int type, int subtype,
4078 	int length, int tweening) {
4079 
4080 	/* Standing template. */
4081 	SECTION *root;
4082 
4083 	/* This has gotta be considered weird. */
4084 	InitHModelSequence(controller,(int)HMSQT_PredatorStand,
4085 		(int)PSSS_Dies_Standard,(ONE_FIXED<<1));
4086 	ProveHModel_Far(controller,sbPtr);
4087 	/* And now we change it.  See? */
4088 
4089 	root=GetNamedHierarchyFromLibrary("hnpcpredator","Template");
4090 
4091 	Engage_Template_Death(sbPtr,root,controller,type,subtype,length,tweening);
4092 }
4093 
4094 /* Kills a ghost, to leave a corpse */
KillGhost(STRATEGYBLOCK * sbPtr,int objectId)4095 void KillGhost(STRATEGYBLOCK *sbPtr,int objectId)
4096 {
4097 	NETGHOSTDATABLOCK *ghostData;
4098 
4099 	LOCALASSERT(sbPtr);
4100 	ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
4101 	LOCALASSERT(ghostData);
4102 
4103 	/* this is where we add fragmentation and explosion	effects to destroyed ghosts */
4104 	switch(ghostData->type)
4105 	{
4106 		case(I_BehaviourAlienPlayer):
4107 		case(I_BehaviourMarinePlayer):
4108 		case(I_BehaviourPredatorPlayer):
4109 		{
4110 			/* Drop through, for the moment. */
4111 			#if EXTRAPOLATION_TEST
4112 			sbPtr->DynPtr->LinImpulse.vx=0;
4113 			sbPtr->DynPtr->LinImpulse.vy=0;
4114 			sbPtr->DynPtr->LinImpulse.vz=0;
4115 
4116 		   	sbPtr->DynPtr->LinVelocity.vx=0;
4117 			sbPtr->DynPtr->LinVelocity.vy=0;
4118 			sbPtr->DynPtr->LinVelocity.vz=0;
4119 
4120 			sbPtr->DynPtr->UseStandardGravity=1;
4121 
4122 			sbPtr->DynPtr->IsNetGhost=1;
4123 
4124 			sbPtr->DynPtr->ToppleForce=TOPPLE_FORCE_NONE;
4125 
4126 			#endif
4127 			break;
4128 		}
4129 		case(I_BehaviourGrenade):
4130 		case(I_BehaviourRocket):
4131 		case(I_BehaviourProximityGrenade):
4132 		case(I_BehaviourFragmentationGrenade):
4133 		case(I_BehaviourClusterGrenade):
4134 		case(I_BehaviourPulseGrenade):
4135 		case(I_BehaviourNPCPredatorDisc):
4136 		case(I_BehaviourPredatorDisc_SeekTrack):
4137 		case(I_BehaviourAlienSpit):
4138 		case(I_BehaviourInanimateObject):
4139 		default:
4140 		{
4141 			/* Default to something else. */
4142 			RemoveGhost(sbPtr);
4143 			return;
4144 			break;
4145 		}
4146 	}
4147 
4148 	/* see if we've got a sound... */
4149 	if(ghostData->SoundHandle  != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle);
4150 	if(ghostData->SoundHandle2 != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle2);
4151 	if(ghostData->SoundHandle3 != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle3);
4152 	if(ghostData->SoundHandle4 != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle4);
4153 
4154 	/* see if we've got a muzzle flash... */
4155 	if(ghostData->myGunFlash)
4156 	{
4157 		RemoveNPCGunFlashEffect(ghostData->myGunFlash);
4158 		ghostData->myGunFlash = NULL;
4159 	}
4160 
4161 	/* Now.. you're a ghost.  Of a corpse. */
4162 
4163 /*--------------------------------------------------------------------**
4164 ** 	The animation sequence we should use will come in a later message **
4165 **--------------------------------------------------------------------*/
4166 
4167 	ghostData->subtype=ghostData->type;
4168 	ghostData->type=I_BehaviourNetCorpse;
4169 	ghostData->IOType=IOT_Non;
4170 	ghostData->playerObjectId=objectId;
4171 	ghostData->timer=CORPSE_EXPIRY_TIME; /* Arbitrarily */
4172 
4173 	if (ghostData->HModelController.Deltas) {
4174 		RemoveAllDeltas(&ghostData->HModelController);
4175 	}
4176 
4177 	sbPtr->DynPtr->OnlyCollideWithEnvironment = 1;
4178 
4179 	//allow the corpse to fall to the floor
4180 	sbPtr->DynPtr->GravityOn=1;
4181 
4182 	/* And the final touch. */
4183 //	KillRandomSections(ghostData->HModelController.section_data,(ONE_FIXED>>2));
4184 }
4185 
ApplyGhostCorpseDeathAnim(STRATEGYBLOCK * sbPtr,int deathId)4186 extern void ApplyGhostCorpseDeathAnim(STRATEGYBLOCK *sbPtr,int deathId)
4187 {
4188 	extern DEATH_DATA Marine_Deaths[];
4189 	extern DEATH_DATA Alien_Deaths[];
4190 	extern DEATH_DATA Predator_Deaths[];
4191 	DEATH_DATA* this_death;
4192 
4193 	NETGHOSTDATABLOCK *ghostData;
4194 	LOCALASSERT(sbPtr);
4195 	ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
4196 	LOCALASSERT(ghostData);
4197 
4198 	if(ghostData->type!=I_BehaviourNetCorpse) return;
4199 
4200 	switch(ghostData->subtype)
4201 	{
4202 		case I_BehaviourMarinePlayer :
4203 		{
4204 			this_death=GetThisDeath_FromCode(&ghostData->HModelController,&Marine_Deaths[0],deathId);
4205 			if (this_death->Template)
4206 			{
4207 				SECTION* template_root=GetNamedHierarchyFromLibrary("hnpcmarine","Template");
4208 				LOCALASSERT(template_root);
4209 				/* Convert to template. */
4210 				Transmogrify_HModels(sbPtr,&ghostData->HModelController,
4211 					template_root, 0, 0,0);
4212 			}
4213 			else
4214 			{
4215 				SECTION* template_root=GetNamedHierarchyFromLibrary("hnpcmarine","Template");
4216 				LOCALASSERT(template_root);
4217 				/* Convert to template. */
4218 				TrimToTemplate(sbPtr,&ghostData->HModelController,
4219 					template_root, 0);
4220 			}
4221 		}
4222 		break;
4223 
4224 		case I_BehaviourPredatorPlayer :
4225 		{
4226 			this_death=GetThisDeath_FromCode(&ghostData->HModelController,&Predator_Deaths[0],deathId);
4227 			if (this_death->Template)
4228 			{
4229 				SECTION* template_root=GetNamedHierarchyFromLibrary("hnpcpredator","Template");
4230 				LOCALASSERT(template_root);
4231 				/* Convert to template. */
4232 				Transmogrify_HModels(sbPtr,&ghostData->HModelController,
4233 					template_root, 1, 0,0);
4234 			}
4235 		}
4236 		break;
4237 
4238 		case I_BehaviourAlienPlayer :
4239 		{
4240 			this_death=GetThisDeath_FromCode(&ghostData->HModelController,&Alien_Deaths[0],deathId);
4241 		}
4242 		break;
4243 
4244 		default :
4245 			return;
4246 
4247 	}
4248 
4249 
4250 	if(this_death->TweeningTime<=0)
4251 	{
4252 		InitHModelSequence(&ghostData->HModelController,this_death->Sequence_Type,this_death->Sub_Sequence,this_death->Sequence_Length);
4253 	}
4254 	else
4255 	{
4256 		InitHModelTweening(&ghostData->HModelController, this_death->TweeningTime,this_death->Sequence_Type,this_death->Sub_Sequence,this_death->Sequence_Length,0);
4257 	}
4258 
4259 	/* Electric death sound? */
4260 	if (this_death->Electrical) {
4261 		Sound_Play(SID_ED_ELEC_DEATH,"de",&sbPtr->DynPtr->Position,&ghostData->SoundHandle4);
4262 	}
4263 
4264 }
4265 
ApplyCorpseDeathAnim(STRATEGYBLOCK * sbPtr,int deathId)4266 extern void ApplyCorpseDeathAnim(STRATEGYBLOCK *sbPtr,int deathId)
4267 {
4268 	extern DEATH_DATA Marine_Deaths[];
4269 	extern DEATH_DATA Alien_Deaths[];
4270 	extern DEATH_DATA Predator_Deaths[];
4271 	DEATH_DATA* this_death;
4272 
4273 	NETCORPSEDATABLOCK *corpseDataPtr=(NETCORPSEDATABLOCK *)sbPtr->SBdataptr;
4274 
4275 	switch(corpseDataPtr->Type)
4276 	{
4277 		case I_BehaviourMarinePlayer :
4278 		{
4279 			this_death=GetThisDeath_FromCode(&corpseDataPtr->HModelController,&Marine_Deaths[0],deathId);
4280 			if (this_death->Template)
4281 			{
4282 				SECTION* template_root=GetNamedHierarchyFromLibrary("hnpcmarine","Template");
4283 				LOCALASSERT(template_root);
4284 				/* Convert to template. */
4285 				Transmogrify_HModels(sbPtr,&corpseDataPtr->HModelController,
4286 					template_root, 0, 0,0);
4287 			}
4288 			else
4289 			{
4290 				SECTION* template_root=GetNamedHierarchyFromLibrary("hnpcmarine","Template");
4291 				LOCALASSERT(template_root);
4292 				/* Convert to template. */
4293 				TrimToTemplate(sbPtr,&corpseDataPtr->HModelController,
4294 					template_root, 0);
4295 			}
4296 		}
4297 		break;
4298 
4299 		case I_BehaviourPredatorPlayer :
4300 		{
4301 			this_death=GetThisDeath_FromCode(&corpseDataPtr->HModelController,&Predator_Deaths[0],deathId);
4302 			if (this_death->Template)
4303 			{
4304 				SECTION* template_root=GetNamedHierarchyFromLibrary("hnpcpredator","Template");
4305 				LOCALASSERT(template_root);
4306 				/* Convert to template. */
4307 				Transmogrify_HModels(sbPtr,&corpseDataPtr->HModelController,
4308 					template_root, 1, 0,0);
4309 			}
4310 		}
4311 		break;
4312 
4313 		case I_BehaviourAlienPlayer :
4314 		{
4315 			this_death=GetThisDeath_FromCode(&corpseDataPtr->HModelController,&Alien_Deaths[0],deathId);
4316 		}
4317 		break;
4318 
4319 		default :
4320 			return;
4321 
4322 	}
4323 
4324 
4325 	if(this_death->TweeningTime<=0)
4326 	{
4327 		InitHModelSequence(&corpseDataPtr->HModelController,this_death->Sequence_Type,this_death->Sub_Sequence,this_death->Sequence_Length);
4328 	}
4329 	else
4330 	{
4331 		InitHModelTweening(&corpseDataPtr->HModelController, this_death->TweeningTime,this_death->Sequence_Type,this_death->Sub_Sequence,this_death->Sequence_Length,0);
4332 	}
4333 	corpseDataPtr->This_Death=this_death;
4334 
4335 	/* Electric death sound? */
4336 	if (this_death->Electrical) {
4337 		Sound_Play(SID_ED_ELEC_DEATH,"de",&sbPtr->DynPtr->Position,&corpseDataPtr->SoundHandle4);
4338 	}
4339 
4340 }
4341 
KillAlienAIGhost(STRATEGYBLOCK * sbPtr,int death_code,int death_time,int GibbFactor)4342 extern void KillAlienAIGhost(STRATEGYBLOCK *sbPtr,int death_code,int death_time,int GibbFactor) {
4343 
4344 	NETGHOSTDATABLOCK *ghostData;
4345 	DEATH_DATA *this_death;
4346 
4347 	LOCALASSERT(sbPtr);
4348 	ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
4349 	LOCALASSERT(ghostData);
4350 
4351 
4352 	/* To ensure we know what we're doing... */
4353 	if (ghostData->type!=I_BehaviourAlien) {
4354 		GLOBALASSERT(0);
4355 	}
4356 
4357 	if(ghostData->onlyValidFar)
4358 	{
4359 		RemoveGhost(sbPtr);
4360 		return;
4361 	}
4362 
4363 	this_death=GetThisDeath_FromCode(&ghostData->HModelController,Alien_Deaths,death_code);
4364 	GLOBALASSERT(this_death);
4365 
4366 	/* see if we've got a sound... */
4367 	if(ghostData->SoundHandle  != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle);
4368 	if(ghostData->SoundHandle2 != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle2);
4369 	if(ghostData->SoundHandle3 != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle3);
4370 	if(ghostData->SoundHandle4 != SOUND_NOACTIVEINDEX) Sound_Stop(ghostData->SoundHandle4);
4371 
4372 	/* see if we've got a muzzle flash... */
4373 	if(ghostData->myGunFlash)
4374 	{
4375 		RemoveNPCGunFlashEffect(ghostData->myGunFlash);
4376 		ghostData->myGunFlash = NULL;
4377 	}
4378 
4379 	/* Convert that sucker. */
4380 	ghostData->type=I_BehaviourNetCorpse;
4381 	/*
4382 	Alien subtype (alien/predalien/praetorian) gets shuffled down into IOType.
4383 	Not entirely appropriate , but it will do...
4384 	*/
4385 	ghostData->IOType=ghostData->subtype;
4386 	ghostData->subtype=I_BehaviourAlien;
4387 	ghostData->timer=death_time;
4388 
4389 	if (ghostData->HModelController.Deltas) {
4390 		RemoveAllDeltas(&ghostData->HModelController);
4391 	}
4392 	/* Now let's do the sequence. */
4393  	UpdateAlienAIGhostAnimSequence(sbPtr,this_death->Sequence_Type,this_death->Sub_Sequence,
4394  		this_death->Sequence_Length,this_death->TweeningTime);
4395 	ghostData->HModelController.LoopAfterTweening=0;
4396 
4397 	//Allow players to walk through the corpse
4398 	sbPtr->DynPtr->OnlyCollideWithEnvironment = 1;
4399 
4400 	#if EXTRAPOLATION_TEST
4401 	sbPtr->DynPtr->LinImpulse.vx=0;
4402 	sbPtr->DynPtr->LinImpulse.vy=0;
4403 	sbPtr->DynPtr->LinImpulse.vz=0;
4404 
4405 	sbPtr->DynPtr->LinVelocity.vx=0;
4406 	sbPtr->DynPtr->LinVelocity.vy=0;
4407 	sbPtr->DynPtr->LinVelocity.vz=0;
4408 
4409 	sbPtr->DynPtr->UseStandardGravity=1;
4410 
4411 	sbPtr->DynPtr->IsNetGhost=1;
4412 
4413 	sbPtr->DynPtr->ToppleForce=TOPPLE_FORCE_NONE;
4414 	#endif
4415 	//allow the corpse to fall to the floor
4416 	sbPtr->DynPtr->GravityOn=1;
4417 
4418 	/* Gibb the corpse? */
4419 	if (GibbFactor) {
4420 		DoAlienLimbLossSound(&sbPtr->DynPtr->Position);
4421 		Extreme_Gibbing(sbPtr,ghostData->HModelController.section_data,GibbFactor);
4422 	}
4423 
4424 	/* Electric death sound? */
4425 	if (this_death->Electrical) {
4426 		Sound_Play(SID_ED_ELEC_DEATH,"de",&sbPtr->DynPtr->Position,&ghostData->SoundHandle4);
4427 	}
4428 
4429 }
4430 
Deduce_PlayerDeathSequence(void)4431 int Deduce_PlayerDeathSequence(void) {
4432 
4433 	int a;
4434 	PLAYER_STATUS *playerStatusPtr = (PLAYER_STATUS *)(Player->ObStrategyBlock->SBdataptr);
4435 
4436 	a=((FastRandom()&65535)>>12)&14; /* 0,2,4,6,8,10,12,14 */
4437 	if (playerStatusPtr->ShapeState == PMph_Crouching) {
4438 		return(a);
4439 	} else {
4440 		return(a+1);
4441 	}
4442 
4443 }
4444 
Deduce_PlayerMarineDeathSequence(STRATEGYBLOCK * sbPtr,DAMAGE_PROFILE * damage,int multiple,VECTORCH * incoming)4445 int Deduce_PlayerMarineDeathSequence(STRATEGYBLOCK* sbPtr,DAMAGE_PROFILE* damage,int multiple,VECTORCH* incoming)
4446 {
4447 	PLAYER_STATUS *playerStatusPtr = (PLAYER_STATUS *)(Player->ObStrategyBlock->SBdataptr);
4448 	NETCORPSEDATABLOCK *corpseDataPtr=(NETCORPSEDATABLOCK *)sbPtr->SBdataptr;
4449 
4450 	int deathtype,gibbFactor;
4451 
4452 	/* Set GibbFactor  and death type*/
4453 	gibbFactor=0;
4454 	{
4455 		int tkd;
4456 
4457 		tkd=TotalKineticDamage(damage);
4458 		deathtype=0;
4459 
4460 		if (damage->ExplosivePower==1) {
4461 			if (MUL_FIXED(tkd,(multiple&((ONE_FIXED<<1)-1)))>20) {
4462 				/* Okay, you can gibb now. */
4463 				gibbFactor=ONE_FIXED>>1;
4464 				deathtype=2;
4465 			}
4466 		} else if ((tkd>60)&&((multiple>>16)>1)) {
4467 			int newmult;
4468 
4469 			newmult=DIV_FIXED(multiple,NormalFrameTime);
4470 			if (MUL_FIXED(tkd,newmult)>(500)) {
4471 				/* Loadsabullets! */
4472 				gibbFactor=-(ONE_FIXED>>2);
4473 				deathtype=2;
4474 			}
4475 		}
4476 
4477 		if ((damage->ExplosivePower==2)||(damage->ExplosivePower==6)) {
4478 			/* Basically SADARS only. */
4479 			gibbFactor=ONE_FIXED;
4480 			deathtype=3;
4481 		}
4482 	}
4483 
4484 	if (damage->ForceBoom) {
4485 		deathtype+=damage->ForceBoom;
4486 	}
4487 
4488 	{
4489 		SECTION_DATA *chest;
4490 
4491 		chest=GetThisSectionData(corpseDataPtr->HModelController.section_data,"chest");
4492 
4493 		if (chest==NULL) {
4494 			/* I'm impressed. */
4495 			deathtype+=2;
4496 		} else if ((chest->flags&section_data_notreal)
4497 			&&(chest->flags&section_data_terminate_here)) {
4498 			/* That's gotta hurt. */
4499 			deathtype++;
4500 		}
4501 	}
4502 
4503 
4504 	/* Now final stage. */
4505 	{
4506 		DEATH_DATA *this_death;
4507 		HIT_FACING facing;
4508 		SECTION *root;
4509 		int burning,electrical;
4510 		int crouched;
4511 
4512 		root=GetNamedHierarchyFromLibrary("hnpcmarine","Template");
4513 
4514 		facing.Front=0;
4515 		facing.Back=0;
4516 		facing.Left=0;
4517 		facing.Right=0;
4518 
4519 		if (incoming) {
4520 			if (incoming->vz>0) {
4521 				facing.Back=1;
4522 			} else {
4523 				facing.Front=1;
4524 			}
4525 			if (incoming->vx>0) {
4526 				facing.Right=1;
4527 			} else {
4528 				facing.Left=1;
4529 			}
4530 		}
4531 
4532 		if ((playerStatusPtr->fireTimer>0)
4533 			&&(damage->Impact==0)
4534 			&&(damage->Cutting==0)
4535 			&&(damage->Penetrative==0)
4536 			&&(damage->Fire>0)
4537 			&&(damage->Electrical==0)
4538 			&&(damage->Acid==0)
4539 			) {
4540 			burning=1;
4541 		} else {
4542 			burning=0;
4543 		}
4544 
4545 		if ((damage->Impact==0)
4546 			&&(damage->Cutting==0)
4547 			&&(damage->Penetrative==0)
4548 			&&(damage->Fire==0)
4549 			&&(damage->Electrical>0)
4550 			&&(damage->Acid==0)
4551 			) {
4552 			electrical=1;
4553 		} else {
4554 			electrical=0;
4555 		}
4556 
4557 		if (playerStatusPtr->ShapeState == PMph_Crouching)
4558 		{
4559 			crouched=1;
4560 		}
4561 		else
4562 		{
4563 			crouched=0;
4564 		}
4565 
4566 		this_death=GetMarineDeathSequence(&corpseDataPtr->HModelController,root,corpseDataPtr->Wounds,corpseDataPtr->Wounds,
4567 			deathtype,&facing,burning,crouched,electrical);
4568 
4569 		GLOBALASSERT(this_death);
4570 
4571 		return this_death->Multiplayer_Code;
4572 	}
4573 }
4574 
Deduce_PlayerAlienDeathSequence(STRATEGYBLOCK * sbPtr,DAMAGE_PROFILE * damage,int multiple,VECTORCH * incoming)4575 int Deduce_PlayerAlienDeathSequence(STRATEGYBLOCK* sbPtr,DAMAGE_PROFILE* damage,int multiple,VECTORCH* incoming)
4576 {
4577 	PLAYER_STATUS *playerStatusPtr = (PLAYER_STATUS *)(Player->ObStrategyBlock->SBdataptr);
4578 	NETCORPSEDATABLOCK *corpseDataPtr=(NETCORPSEDATABLOCK *)sbPtr->SBdataptr;
4579 
4580 	int tkd,deathtype;
4581 
4582 	/* Get death type. */
4583 	tkd=TotalKineticDamage(damage);
4584 	deathtype=0;
4585 
4586 	if (damage->ExplosivePower==1) {
4587 	 	/* Explosion case. */
4588 	 	if (MUL_FIXED(tkd,(multiple&((ONE_FIXED<<1)-1)))>20) {
4589 	 		/* Okay, you can gibb now. */
4590 			deathtype=2;
4591 	 	}
4592 	} else if ((tkd<40)&&((multiple>>16)>1)) {
4593 	 	int newmult;
4594 
4595 	 	newmult=DIV_FIXED(multiple,NormalFrameTime);
4596 	 	if (MUL_FIXED(tkd,newmult)>700) {
4597 	 		/* Excessive bullets case 1. */
4598 			deathtype=2;
4599 	 	} else if (MUL_FIXED(tkd,newmult)>250) {
4600 	 		/* Excessive bullets case 2. */
4601 			deathtype=1;
4602 	 	}
4603 	}
4604 
4605 	if ((damage->ExplosivePower==2)||(damage->ExplosivePower==6)) {
4606 		/* Basically SADARS only. */
4607 		deathtype=3;
4608 	}
4609 
4610 	if (damage->ForceBoom) {
4611 		deathtype+=damage->ForceBoom;
4612 	}
4613 
4614 	{
4615 		SECTION_DATA *chest=GetThisSectionData(corpseDataPtr->HModelController.section_data,"chest");
4616 
4617 		if (chest==NULL) {
4618 			/* I'm impressed. */
4619 			deathtype+=2;
4620 		} else if ((chest->flags&section_data_notreal)
4621 			&&(chest->flags&section_data_terminate_here)) {
4622 			/* That's gotta hurt. */
4623 			deathtype++;
4624 		}
4625 	}
4626 
4627 	{
4628 
4629 
4630 		DEATH_DATA *this_death;
4631 		HIT_FACING facing;
4632 		int crouched;
4633 
4634 		facing.Front=0;
4635 		facing.Back=0;
4636 		facing.Left=0;
4637 		facing.Right=0;
4638 
4639 		if (incoming) {
4640 			if (incoming->vz>0) {
4641 				facing.Back=1;
4642 			} else {
4643 				facing.Front=1;
4644 			}
4645 			if (incoming->vx>0) {
4646 				facing.Right=1;
4647 			} else {
4648 				facing.Left=1;
4649 			}
4650 		}
4651 		if (playerStatusPtr->ShapeState == PMph_Crouching)
4652 		{
4653 			crouched=1;
4654 		}
4655 		else
4656 		{
4657 			crouched=0;
4658 		}
4659 
4660 		this_death=GetAlienDeathSequence(&corpseDataPtr->HModelController,NULL,corpseDataPtr->Wounds,corpseDataPtr->Wounds,
4661 			deathtype,&facing,0,crouched,0);
4662 
4663 		return this_death->Multiplayer_Code;
4664 	}
4665 
4666 }
4667 
Deduce_PlayerPredatorDeathSequence(STRATEGYBLOCK * sbPtr,DAMAGE_PROFILE * damage,int multiple,VECTORCH * incoming)4668 int Deduce_PlayerPredatorDeathSequence(STRATEGYBLOCK* sbPtr,DAMAGE_PROFILE* damage,int multiple,VECTORCH* incoming)
4669 {
4670 	PLAYER_STATUS *playerStatusPtr = (PLAYER_STATUS *)(Player->ObStrategyBlock->SBdataptr);
4671 	NETCORPSEDATABLOCK *corpseDataPtr=(NETCORPSEDATABLOCK *)sbPtr->SBdataptr;
4672 
4673     int deathtype=0;
4674     int tkd = TotalKineticDamage(damage);
4675 
4676     if (damage->ExplosivePower==1) {
4677     	if (MUL_FIXED(tkd,(multiple&((ONE_FIXED<<1)-1)))>20) {
4678         	/* Okay, you can... splat now. */
4679         	deathtype=2;
4680         }
4681     } else if ((tkd<40)&&((multiple>>16)>1)) {
4682     	int newmult;
4683 
4684     	newmult=DIV_FIXED(multiple,NormalFrameTime);
4685     	if (MUL_FIXED(tkd,newmult)>(500)) {
4686     	    deathtype=2;
4687         }
4688     }
4689 
4690     if ((damage->ExplosivePower==2)||(damage->ExplosivePower==6)) {
4691     	/* Basically SADARS only. */
4692     	deathtype=3;
4693     }
4694 
4695     if (damage->ForceBoom) {
4696     	deathtype+=damage->ForceBoom;
4697     }
4698 
4699     {
4700     	SECTION_DATA *chest;
4701 
4702     	chest=GetThisSectionData(corpseDataPtr->HModelController.section_data,"chest");
4703 
4704     	if (chest==NULL) {
4705     		/* I'm impressed. */
4706     		deathtype+=2;
4707     	} else if ((chest->flags&section_data_notreal)
4708     		&&(chest->flags&section_data_terminate_here)) {
4709     		/* That's gotta hurt. */
4710     		deathtype++;
4711     	}
4712     }
4713 
4714 	{
4715 		DEATH_DATA *this_death;
4716 		HIT_FACING facing;
4717 		SECTION *root;
4718 		int burning;
4719 		int crouched;
4720 
4721 		root=GetNamedHierarchyFromLibrary("hnpcpredator","Template");
4722 
4723 		facing.Front=0;
4724 		facing.Back=0;
4725 		facing.Left=0;
4726 		facing.Right=0;
4727 
4728 		if (incoming) {
4729 			if (incoming->vz>0) {
4730 				facing.Back=1;
4731 			} else {
4732 				facing.Front=1;
4733 			}
4734 			if (incoming->vx>0) {
4735 				facing.Right=1;
4736 			} else {
4737 				facing.Left=1;
4738 			}
4739 		}
4740 
4741 		if ((damage->Impact==0)
4742 			&&(damage->Cutting==0)
4743 			&&(damage->Penetrative==0)
4744 			&&(damage->Fire>0)
4745 			&&(damage->Electrical==0)
4746 			&&(damage->Acid==0)
4747 			) {
4748 			burning=1;
4749 		} else {
4750 			burning=0;
4751 		}
4752 
4753 		if (playerStatusPtr->ShapeState == PMph_Crouching)
4754 		{
4755 			crouched=1;
4756 		}
4757 		else
4758 		{
4759 			crouched=0;
4760 		}
4761 
4762 		this_death=GetPredatorDeathSequence(&corpseDataPtr->HModelController,root,corpseDataPtr->Wounds,
4763 		      corpseDataPtr->Wounds,deathtype,&facing,burning,crouched,0);
4764 
4765 		GLOBALASSERT(this_death);
4766 
4767 
4768 		return this_death->Multiplayer_Code;
4769 	}
4770 
4771 }
4772 
MakeNewCorpse()4773 STRATEGYBLOCK *MakeNewCorpse()
4774 {
4775 	int i;
4776 	STRATEGYBLOCK *sbPtr;
4777 	SECTION *root_section;
4778 	signed char weapon;
4779 	NETCORPSEDATABLOCK *corpseData;
4780 	PLAYER_WEAPON_DATA *weaponPtr;
4781 	PLAYER_STATUS *playerStatusPtr = (PLAYER_STATUS *)(Player->ObStrategyBlock->SBdataptr);
4782 
4783 	LOCALASSERT(playerStatusPtr);
4784    	weaponPtr = &(playerStatusPtr->WeaponSlot[playerStatusPtr->SelectedWeaponSlot]);
4785 	weapon = (signed char)(weaponPtr->WeaponIDNumber);
4786 
4787 	/* create a strategy block - same as for a ghost */
4788 	sbPtr = CreateActiveStrategyBlock();
4789 	if(!sbPtr)
4790 	{
4791 		/* allocation failed */
4792 		return NULL;
4793 	}
4794 	InitialiseSBValues(sbPtr);
4795 	sbPtr->I_SBtype = I_BehaviourNetCorpse;
4796 
4797 	for(i = 0; i < SB_NAME_LENGTH; i++) sbPtr->SBname[i] = '\0';
4798 	AssignNewSBName(sbPtr);
4799 
4800 	/* dynamics block */
4801 	{
4802 		DYNAMICSBLOCK *dynPtr;
4803 
4804 		/* need different templates for objects and sprites */
4805 		dynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_MARINE_PLAYER);
4806 		if(!dynPtr)
4807 		{
4808 			/* allocation failed */
4809 			RemoveBehaviourStrategy(sbPtr);
4810 			return NULL;
4811 		}
4812 		dynPtr->CanClimbStairs = 0;
4813 		dynPtr->IgnoreThePlayer = 1;
4814 
4815 		sbPtr->DynPtr = dynPtr;
4816 		/* zero linear velocity in dynamics block */
4817 		dynPtr->LinVelocity.vx = dynPtr->LinVelocity.vy = dynPtr->LinVelocity.vz = 0;
4818 		dynPtr->LinImpulse.vx = dynPtr->LinImpulse.vy = dynPtr->LinImpulse.vz = 0;
4819 		dynPtr->GravityOn = 1;
4820 		dynPtr->UseStandardGravity = 1;
4821 
4822 		dynPtr->Position = dynPtr->PrevPosition = Player->ObStrategyBlock->DynPtr->Position;
4823 		dynPtr->OrientEuler = Player->ObStrategyBlock->DynPtr->OrientEuler;
4824 		CreateEulerMatrix(&dynPtr->OrientEuler, &dynPtr->OrientMat);
4825 		TransposeMatrixCH(&dynPtr->OrientMat);
4826 
4827 	}
4828 
4829 	sbPtr->maintainVisibility = 1;
4830 	sbPtr->containingModule = ModuleFromPosition(&(sbPtr->DynPtr->Position), 0);
4831 
4832 	/* data block */
4833 	{
4834 		corpseData = AllocateMem(sizeof(NETCORPSEDATABLOCK));
4835 		if(!corpseData)
4836 		{
4837 			/* allocation failed */
4838 			RemoveBehaviourStrategy(sbPtr);
4839 			return NULL;
4840 		}
4841 		sbPtr->SBdataptr = (void *)corpseData;
4842 		corpseData->SoundHandle  = SOUND_NOACTIVEINDEX;
4843 		corpseData->SoundHandle2 = SOUND_NOACTIVEINDEX;
4844 		corpseData->SoundHandle3 = SOUND_NOACTIVEINDEX;
4845 		corpseData->SoundHandle4 = SOUND_NOACTIVEINDEX;
4846 
4847 		switch(AvP.PlayerType)
4848 		{
4849 			case I_Marine :
4850 				corpseData->Type=I_BehaviourMarinePlayer;
4851 				break;
4852 			case I_Alien :
4853 				corpseData->Type=I_BehaviourAlienPlayer;
4854 				break;
4855 			case I_Predator :
4856 				corpseData->Type=I_BehaviourPredatorPlayer;
4857 				break;
4858 		}
4859 		corpseData->GibbFactor=0;
4860 		corpseData->This_Death=NULL;
4861 
4862 		/* Clear cloak data... */
4863 		corpseData->CloakStatus = PCLOAK_Off;
4864 		corpseData->CloakTimer = 0;
4865 		corpseData->destructTimer = -1;
4866 		/* Clear deathfiring stuff... */
4867 		corpseData->WeaponMisfireFunction=NULL;
4868 		corpseData->My_Gunflash_Section=NULL;
4869 		corpseData->weapon_variable=0;
4870 		corpseData->Android=0;
4871 		corpseData->TemplateRoot=NULL;
4872 		corpseData->DeathFiring=0;
4873 		corpseData->hltable=NULL;
4874 
4875 		corpseData->Wounds=0;
4876 
4877  		/* set the shape */
4878 		switch(AvP.PlayerType)
4879 		{
4880 			case(I_Marine):
4881 			{
4882 
4883 				corpseData->hltable=GetThisHitLocationTable("marine with pulse rifle");
4884 				/* Select hierarchy from character's selected weapon. */
4885 				//while we're at it , also deal with creating the pickupable weapon
4886 			   	{
4887 
4888 			   		VECTORCH location=Player->ObStrategyBlock->DynPtr->Position;
4889 			   		STRATEGYBLOCK* weaponSbPtr = CreateMultiplayerWeaponPickup(&location,weapon,0);
4890 					if(weaponSbPtr)
4891 					{
4892 						//hide the newly created weapon from this player , until the player respawns
4893 						weaponSbPtr->maintainVisibility=0;
4894 					}
4895 				}
4896 				switch (weapon)
4897 				{
4898 					default:
4899 					case WEAPON_PULSERIFLE:
4900 					{
4901 						root_section = GetNamedHierarchyFromLibrary("hnpcmarine","marine with pulse rifle");
4902 						break;
4903 					}
4904 					case WEAPON_TWO_PISTOLS:
4905 					{
4906 						root_section = GetNamedHierarchyFromLibrary("hnpcmarine","Two Pistol");
4907 						break;
4908 					}
4909 					case WEAPON_MARINE_PISTOL:
4910 					{
4911 						root_section = GetNamedHierarchyFromLibrary("hnpcmarine","PISTOL");
4912 						break;
4913 					}
4914 					case WEAPON_FLAMETHROWER:
4915 					{
4916 						root_section = GetNamedHierarchyFromLibrary("hnpcmarine","marine with flame thrower");
4917 						break;
4918 					}
4919 					case WEAPON_SMARTGUN:
4920 					{
4921 						root_section = GetNamedHierarchyFromLibrary("hnpcmarine","marine with smart gun");
4922 						break;
4923 					}
4924 					case WEAPON_MINIGUN:
4925 					{
4926 						root_section = GetNamedHierarchyFromLibrary("hnpcmarine","Marine with Mini Gun");
4927 						break;
4928 					}
4929 					case WEAPON_SADAR:
4930 					{
4931 						root_section = GetNamedHierarchyFromLibrary("hnpcmarine","marine with SADAR");
4932 						break;
4933 					}
4934 					case WEAPON_GRENADELAUNCHER:
4935 					{
4936 						root_section = GetNamedHierarchyFromLibrary("hnpcmarine","marine + grenade launcher");
4937 						break;
4938 					}
4939 					case WEAPON_CUDGEL:
4940 					{
4941 						root_section = GetNamedHierarchyFromLibrary("hnpcmarine","Cudgel");
4942 						break;
4943 					}
4944 					case WEAPON_FRISBEE_LAUNCHER:
4945 					{
4946 						root_section = GetNamedHierarchyFromLibrary("hnpcmarine","skeeter");
4947 						break;
4948 					}
4949 				}
4950 				Create_HModel(&corpseData->HModelController,root_section);
4951 				{
4952 					extern DPID AVPDPNetID;
4953 					ChangeGhostMarineAccoutrementSet(&corpseData->HModelController,AVPDPNetID);
4954 				}
4955 				//choose a default sequence , the proper death anim will be set later
4956 				InitHModelSequence(&corpseData->HModelController,(int)HMSQT_MarineStand,(int)MSSS_Standard,ONE_FIXED);
4957 
4958 				break;
4959 			}
4960 			case(I_Alien):
4961 			{
4962 				corpseData->hltable=GetThisHitLocationTable("alien");
4963 
4964 				root_section = GetNamedHierarchyFromLibrary("hnpcalien","alien");
4965 				Create_HModel(&corpseData->HModelController,root_section);
4966 
4967 				//choose a default sequence , the proper death anim will be set later
4968 				InitHModelSequence(&corpseData->HModelController,(int)HMSQT_AlienStand,(int)ASSS_Standard,ONE_FIXED);
4969 				break;
4970 			}
4971 			case(I_Predator):
4972 			{
4973 				corpseData->hltable=GetThisHitLocationTable("predator");
4974 				switch (weapon)
4975 				{
4976 					default:
4977 					case WEAPON_PRED_WRISTBLADE:
4978 					{
4979 						root_section = GetNamedHierarchyFromLibrary("hnpcpredator","pred with wristblade");
4980 						break;
4981 					}
4982 					case WEAPON_PRED_RIFLE:
4983 					{
4984 						root_section = GetNamedHierarchyFromLibrary("hnpcpredator","Speargun");
4985 						break;
4986 					}
4987 					case WEAPON_PRED_PISTOL:
4988 					{
4989 						root_section = GetNamedHierarchyFromLibrary("hnpcpredator","pred + pistol");
4990 						break;
4991 					}
4992 					case WEAPON_PRED_SHOULDERCANNON:
4993 					{
4994 						root_section = GetNamedHierarchyFromLibrary("hnpcpredator","pred with Plasma Caster");
4995 						break;
4996 					}
4997 					case WEAPON_PRED_DISC:
4998 					{
4999 						root_section = GetNamedHierarchyFromLibrary("hnpcpredator","pred with disk");
5000 						break;
5001 					}
5002 					case WEAPON_PRED_MEDICOMP:
5003 					{
5004 						root_section = GetNamedHierarchyFromLibrary("hnpcpredator","medicomp");
5005 						break;
5006 					}
5007 				}
5008 				Create_HModel(&corpseData->HModelController,root_section);
5009 
5010 				//choose a default sequence , the proper death anim will be set later
5011 				InitHModelSequence(&corpseData->HModelController,(int)HMSQT_PredatorStand,(int)PSSS_Elevation,ONE_FIXED);
5012 				break;
5013 			}
5014 		}
5015 	}
5016 	/* Now fix timer. */
5017 	corpseData->timer=CORPSE_EXPIRY_TIME; /* Arbitrarily */
5018 	corpseData->validityTimer=CORPSE_VALIDITY_TIME;
5019 	corpseData->HModelController.Looped=0;
5020 	ProveHModel_Far(&corpseData->HModelController,sbPtr);
5021 	MakeCorpseNear(sbPtr);
5022 	GLOBALASSERT(sbPtr->SBdptr);
5023 	sbPtr->SBdptr->ObFlags|=ObFlag_NotVis;
5024 	/* And the fire. */
5025 
5026 	if (Player->ObStrategyBlock->SBDamageBlock.IsOnFire) {
5027 		sbPtr->SBDamageBlock.IsOnFire=1;
5028 	}
5029 	/* Defaults to zero. */
5030 
5031 	if (playerStatusPtr->soundHandle3!=SOUND_NOACTIVEINDEX) {
5032 		if (ActiveSounds[playerStatusPtr->soundHandle3].soundIndex==SID_FIRE) {
5033 			/* Pass fire sound across. */
5034 			corpseData->SoundHandle3=playerStatusPtr->soundHandle3;
5035 			playerStatusPtr->soundHandle3=SOUND_NOACTIVEINDEX;
5036 		}
5037 	}
5038 
5039 	/* And the final touch. */
5040 //	KillRandomSections(corpseData->HModelController.section_data,(ONE_FIXED>>2));
5041 
5042 	return(sbPtr);
5043 }
5044 
UpdateAlienAIGhostAnimSequence(STRATEGYBLOCK * sbPtr,HMODEL_SEQUENCE_TYPES type,int subtype,int length,int tweeningtime)5045 void UpdateAlienAIGhostAnimSequence(STRATEGYBLOCK *sbPtr,HMODEL_SEQUENCE_TYPES type, int subtype, int length, int tweeningtime)
5046 {
5047 
5048 	NETGHOSTDATABLOCK *ghostData;
5049 
5050 	LOCALASSERT(sbPtr);
5051 	ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
5052 
5053 	GLOBALASSERT(length!=0);
5054 
5055 
5056 
5057 	/* Are we already playing this one? */
5058 	if ((ghostData->HModelController.Sequence_Type==type)&&(ghostData->HModelController.Sub_Sequence==subtype)) {
5059 		/* Yes, but... */
5060 		/*I think we only want to change speed if we're not tweening*/
5061 		if (tweeningtime<=0)
5062 		{
5063 			if (length!=ghostData->HModelController.Seconds_For_Sequence) {
5064 				HModel_ChangeSpeed(&ghostData->HModelController,length);
5065 			}
5066 		}
5067 
5068 	} else if (tweeningtime<=0) {
5069 		InitHModelSequence(&ghostData->HModelController,(int)type,subtype,length);
5070 	} else {
5071 		InitHModelTweening(&ghostData->HModelController, tweeningtime, (int)type,subtype,length, 1);
5072 	}
5073 
5074 	ghostData->HModelController.Playing=1;
5075 	/* Might be unset... */
5076 }
5077 
5078 /* This a copy of UpdateGhost, with extra parameters. */
UpdateAlienAIGhost(STRATEGYBLOCK * sbPtr,VECTORCH * position,EULER * orientation,int sequence_type,int sub_sequence,int sequence_length)5079 void UpdateAlienAIGhost(STRATEGYBLOCK *sbPtr,VECTORCH *position,EULER *orientation,int sequence_type,int sub_sequence, int sequence_length)
5080 {
5081 	NETGHOSTDATABLOCK *ghostData;
5082 
5083 	LOCALASSERT(sbPtr);
5084 	ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
5085 
5086 	/* for visibility support: as ghosts can be moved when invisible, we need to work out
5087 	which module they're in	whenever we update them. We must be carefull, however, not
5088 	to set the containingModule to NULL if the object has moved outside the env, as
5089 	the	visibility system expects that we at least know what module any object WAS in,
5090 	even if we do not now... thus, if we cannot find a containing module, we abort the update */
5091 
5092 	/* KJL 21:01:09 23/05/98 - I've put this test here because the player's image in a mirror goes
5093 	throught this code, and it's obviously going to be outside the environment */
5094 	if (sbPtr->I_SBtype==I_BehaviourNetGhost)
5095 	{
5096 		MODULE *myContainingModule = ModuleFromPosition(position, (sbPtr->containingModule));
5097 		if(myContainingModule==NULL) return;
5098 		sbPtr->containingModule = myContainingModule;
5099 	}
5100 
5101 
5102 	if (ghostData->type!=I_BehaviourAlien) {
5103 		GLOBALASSERT(0);
5104 	}
5105 
5106 	//We have enough information to be able to make this alien near (should we want to)
5107 	ghostData->onlyValidFar=0;
5108 
5109 	/* update the dynamics block */
5110 	{
5111 		DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
5112 
5113 		dynPtr->PrevPosition = dynPtr->Position;
5114 		dynPtr->PrevOrientMat = dynPtr->OrientMat;
5115 		dynPtr->Position = *position;
5116 		dynPtr->OrientEuler = *orientation;
5117 		CreateEulerMatrix(&dynPtr->OrientEuler,&dynPtr->OrientMat);
5118 		TransposeMatrixCH(&dynPtr->OrientMat);
5119 	}
5120 
5121 	/* KJL 16:58:04 17/06/98 - we want to update anims differently for NPCS */
5122 	if ((sequence_type!=-1)&&(sub_sequence!=-1)) {
5123 		/* Not tweening! */
5124 		UpdateAlienAIGhostAnimSequence(sbPtr,sequence_type,sub_sequence,sequence_length,(ONE_FIXED>>2));
5125 	}
5126 
5127 	/* refresh integrity */
5128 	ghostData->integrity = GHOST_INTEGRITY;
5129 }
5130 
Convert_DiscGhost_To_PickupGhost(STRATEGYBLOCK * sbPtr)5131 void Convert_DiscGhost_To_PickupGhost(STRATEGYBLOCK *sbPtr) {
5132 
5133 	DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
5134 	NETGHOSTDATABLOCK *ghostData= (NETGHOSTDATABLOCK * ) sbPtr->SBdataptr;
5135 	/* Transmogrify a disc ghost behaviour to a disc ammo pickup! */
5136 
5137 	/* Sort out dynamics block */
5138 	dynPtr->LinVelocity.vx=0;
5139 	dynPtr->LinVelocity.vy=0;
5140 	dynPtr->LinVelocity.vz=0;
5141 
5142 	dynPtr->LinImpulse.vx=0;
5143 	dynPtr->LinImpulse.vy=0;
5144 	dynPtr->LinImpulse.vz=0;
5145 
5146 	ghostData->type=I_BehaviourInanimateObject;
5147 	ghostData->IOType=IOT_Ammo;
5148 	ghostData->subtype=AMMO_PRED_DISC;
5149 
5150 	ghostData->HModelController.Playing=0;
5151 	/* Deal with flip up case? */
5152 
5153 	/* The final shape is NOT hierarchical. */
5154 	{
5155 		SECTION_DATA *disc_section;
5156 		disc_section=GetThisSectionData(ghostData->HModelController.section_data,"disk");
5157 		GLOBALASSERT(disc_section);
5158 
5159 		sbPtr->shapeIndex=disc_section->sempai->ShapeNum;
5160 		Dispel_HModel(&ghostData->HModelController);
5161 		if (sbPtr->SBdptr) {
5162 			sbPtr->SBdptr->ObShape=disc_section->sempai->ShapeNum;
5163 			sbPtr->SBdptr->ObShapeData=disc_section->sempai->Shape;
5164 			sbPtr->SBdptr->HModelControlBlock=NULL;
5165 		}
5166 	}
5167 
5168 	if(ghostData->SoundHandle!=SOUND_NOACTIVEINDEX)
5169 	{
5170 		Sound_Stop(ghostData->SoundHandle);
5171 	}
5172 	Sound_Play(SID_DISC_STICKSINWALL,"dp",&(sbPtr->DynPtr->Position),((FastRandom()&511)-255));
5173 
5174 
5175 }
5176 
5177 
5178 
PlayHitDeltaOnGhost(STRATEGYBLOCK * sbPtr,char delta_seq,char delta_sub_seq)5179 void PlayHitDeltaOnGhost(STRATEGYBLOCK *sbPtr,char delta_seq,char delta_sub_seq)
5180 {
5181 	DELTA_CONTROLLER *hitdelta;
5182 	NETGHOSTDATABLOCK *ghostData;
5183 
5184 	LOCALASSERT(sbPtr);
5185 	ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
5186 
5187 	//only play hit deltas on marine and predator players
5188 	if(ghostData->type!=I_BehaviourMarinePlayer && ghostData->type!=I_BehaviourPredatorPlayer) return;
5189 
5190 	hitdelta=Get_Delta_Sequence(&ghostData->HModelController,"HitDelta");
5191 
5192 	if(hitdelta)
5193 	{
5194    		if (HModelSequence_Exists(&ghostData->HModelController,(int)delta_seq,(int)delta_sub_seq))
5195 		{
5196 			Start_Delta_Sequence(hitdelta,(int)delta_seq,(int) delta_sub_seq,ONE_FIXED/2);
5197 			hitdelta->Playing=1;
5198 		}
5199 	}
5200 
5201 }
5202 
PlayOtherSound(enum soundindex SoundIndex,VECTORCH * position,int explosion)5203 void PlayOtherSound(enum soundindex SoundIndex, VECTORCH *position, int explosion) {
5204 
5205 	if (explosion) {
5206 		Ghost_Explosion_SoundData.position=*position;
5207 		Sound_Play(SoundIndex,"n",&Ghost_Explosion_SoundData);
5208 	} else {
5209 	    Sound_Play(SoundIndex,"d",position);
5210 	}
5211 
5212 }
5213 
5214 
5215 
5216 
5217 
5218 
5219 
5220 
5221 
5222 
5223 
5224 
5225