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§ion_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§ion_flag_left_arm)
1352 ||(section->sempai->flags§ion_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§ion_flag_right_arm)
1365 ||(section->sempai->flags§ion_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§ion_flag_left_leg)
1379 ||(section->sempai->flags§ion_flag_left_foot))
1380 {
1381 CrouchSubSequence=MCrSS_HitLeftLeg;
1382 StandSubSequence=MSSS_HitLeftLeg;
1383
1384 } else if ((section->sempai->flags§ion_flag_right_leg)
1385 ||(section->sempai->flags§ion_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§ion_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§ion_flag_left_arm)
1457 ||(section->sempai->flags§ion_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§ion_flag_right_arm)
1471 ||(section->sempai->flags§ion_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§ion_flag_left_leg)
1485 ||(section->sempai->flags§ion_flag_left_foot)) {
1486 CrouchSubSequence=PCrSS_HitLeftLeg;
1487 StandSubSequence=PSSS_HitLeftLeg;
1488
1489 } else if ((section->sempai->flags§ion_flag_right_leg)
1490 ||(section->sempai->flags§ion_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§ion_data_notreal)
4497 &&(chest->flags§ion_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§ion_data_notreal)
4621 &&(chest->flags§ion_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§ion_data_notreal)
4708 &&(chest->flags§ion_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