1 /* KJL 16:23:20 10/25/96 - I'm moved all the weapon stuff to the newly created weapon.c,
2 so player.c is looking a bit bare at the moment. */
3 #include "3dc.h"
4 #include "module.h"
5 #include "inline.h"
6
7 #include "stratdef.h"
8 #include "gamedef.h"
9 #include "bh_types.h"
10 #include "inventry.h"
11 #include "gameplat.h"
12 #include "dynblock.h"
13 #include "dynamics.h"
14 #include "comp_shp.h"
15 #include "weapons.h"
16 #include "vision.h"
17 #include "pheromon.h"
18 #include "avpview.h"
19 #include "particle.h"
20 #include "scream.h"
21 #include "savegame.h"
22 #include "game_statistics.h"
23 #include "pfarlocs.h"
24 #include "bh_ais.h"
25
26 #define UseLocalAssert Yes
27 #include "ourasert.h"
28
29 #include "psnd.h"
30 #include "psndplat.h"
31 #include "player.h"
32
33 /* for win 95 net support */
34 #include "pldnet.h"
35 #include "pldghost.h"
36 //#include "dp_func.h"
37
38 #include "showcmds.h"
39 #include "bonusabilities.h"
40
41 extern DPID AVPDPNetID;
42
43 #define PLAYER_HMODEL 0
44
45 /*KJL****************************************************************************************
46 * G L O B A L S *
47 ****************************************************************************************KJL*/
48 VECTORCH PlayerStartLocation;
49 MATRIXCH PlayerStartMat;
50 extern int NormalFrameTime;
51 extern ACTIVESOUNDSAMPLE ActiveSounds[];
52 extern int PlayerDamagedOverlayIntensity;
53 extern int playerNoise;
54 extern int predHUDSoundHandle;
55 extern int predOVision_SoundHandle;
56
57 extern int AIModuleArraySize;
58
59 int GimmeChargeCalls;
60 int HtoHStrikes;
61 int CurrentLightAtPlayer;
62 int TauntSoundPlayed;
63
64 int TrickleCharge=9000;
65 int CloakDrain=12000;
66 int CloakThreshold=(5*ONE_FIXED);
67 int CloakPowerOnDrain=(2*ONE_FIXED);
68
69 extern DPID myNetworkKillerId;
70 extern DPID myIgniterId;
71 extern int MyHitBodyPartId;
72 extern HMODELCONTROLLER PlayersWeaponHModelController;
73 extern SECTION_DATA *PWMFSDP; /* PlayersWeaponMuzzleFlashSectionDataPointer */
74
75 /*KJL****************************************************************************************
76 * P R O T O T Y P E S *
77 ****************************************************************************************KJL*/
78 void InitPlayer(STRATEGYBLOCK* sbPtr, int sb_type);
79 void MaintainPlayer(void);
80 void PlayerIsDamaged(STRATEGYBLOCK *sbPtr, DAMAGE_PROFILE *damage, int multiplier,VECTORCH* incoming);
81 static void PlayerIsDead(DAMAGE_PROFILE *damage,int multiplier,VECTORCH* incoming);
82
83 extern int LightIntensityAtPoint(VECTORCH *pointPtr);
84 extern SECTION * GetNamedHierarchyFromLibrary(const char * rif_name, const char * hier_name);
85 extern int SlotForThisWeapon(enum WEAPON_ID weaponID);
86 extern void PointAlert(int level, VECTORCH *point);
87 extern void RemoveAllThisPlayersDiscs(void);
88 void ShowAdjacencies(void);
89
90 extern int ShowAdj;
91
92 /*KJL****************************************************************************************
93 * F U N C T I O N S *
94 ****************************************************************************************KJL*/
95
96 PLAYER_STATUS* PlayerStatusPtr = NULL;
97 static PLAYER_STATUS PlayerStatusBlock;
98 int ShowPredoStats=0;
99 int Observer=0;
100
101 /* Patrick 22/8/97------------------------------------------------
102 Cloaking stuff
103 ------------------------------------------------------------------*/
104 void InitPlayerCloakingSystem(void);
105 static void DoPlayerCloakingSystem(void);
106
InitPlayer(STRATEGYBLOCK * sbPtr,int sb_type)107 void InitPlayer(STRATEGYBLOCK* sbPtr, int sb_type)
108 {
109 /*KJL**************************************************************************************
110 * InitPlayer() was written by me. It attaches the extra player data to the strategy block *
111 * and fills in some initial values. *
112 **************************************************************************************KJL*/
113
114 #if 0
115 SECTION *root_section;
116 #endif
117 PLAYER_STATUS *psPtr = &PlayerStatusBlock;
118 GLOBALASSERT(psPtr);
119 GLOBALASSERT(sbPtr);
120
121 // set up our global
122
123 PlayerStatusPtr = psPtr;
124
125
126 sbPtr->I_SBtype = sb_type;
127 sbPtr->SBdataptr = (void*)psPtr;
128
129 InitialisePlayersInventory(psPtr);
130
131 /* Initialise Player's stats */
132 {
133 NPC_DATA *NpcData;
134 NPC_TYPES PlayerType;
135
136 switch(AvP.PlayerType)
137 {
138 case(I_Marine):
139 {
140 switch (AvP.Difficulty) {
141 case I_Easy:
142 PlayerType=I_PC_Marine_Easy;
143 break;
144 default:
145 case I_Medium:
146 PlayerType=I_PC_Marine_Medium;
147 break;
148 case I_Hard:
149 PlayerType=I_PC_Marine_Hard;
150 break;
151 case I_Impossible:
152 PlayerType=I_PC_Marine_Impossible;
153 break;
154 }
155
156 #if 0 //this hmodel isn't being set up for the moment - Richard
157 root_section=GetNamedHierarchyFromLibrary("hnpcmarine","Template");
158 if (!root_section) {
159 GLOBALASSERT(0);
160 /* Sorry, there's just no bouncing back from this one. Fix it. */
161 return;
162 }
163 #if PLAYER_HMODEL
164 Create_HModel(&psPtr->HModelController,root_section);
165 InitHModelSequence(&psPtr->HModelController,0,0,ONE_FIXED);
166 #endif
167 /* Doesn't matter what the sequence is... */
168 #endif
169 break;
170 }
171 case(I_Predator):
172 {
173 switch (AvP.Difficulty) {
174 case I_Easy:
175 PlayerType=I_PC_Predator_Easy;
176 break;
177 default:
178 case I_Medium:
179 PlayerType=I_PC_Predator_Medium;
180 break;
181 case I_Hard:
182 PlayerType=I_PC_Predator_Hard;
183 break;
184 case I_Impossible:
185 PlayerType=I_PC_Predator_Impossible;
186 break;
187 }
188
189 #if 0 //this hmodel isn't being set up for the moment - Richard
190 root_section=GetNamedHierarchyFromLibrary("hnpcpredator","Template");
191 if (!root_section) {
192 GLOBALASSERT(0);
193 /* Sorry, there's just no bouncing back from this one. Fix it. */
194 return;
195 }
196 #if PLAYER_HMODEL
197 Create_HModel(&psPtr->HModelController,root_section);
198 InitHModelSequence(&psPtr->HModelController,0,0,ONE_FIXED);
199 #endif
200 /* Doesn't matter what the sequence is... */
201 #endif
202 break;
203 }
204 case(I_Alien):
205 {
206 switch (AvP.Difficulty) {
207 case I_Easy:
208 PlayerType=I_PC_Alien_Easy;
209 break;
210 default:
211 case I_Medium:
212 PlayerType=I_PC_Alien_Medium;
213 break;
214 case I_Hard:
215 PlayerType=I_PC_Alien_Hard;
216 break;
217 case I_Impossible:
218 PlayerType=I_PC_Alien_Impossible;
219 break;
220 }
221
222 #if 0 //this hmodel isn't being set up for the moment - Richard
223 root_section=GetNamedHierarchyFromLibrary("hnpcalien","alien");
224 if (!root_section) {
225 GLOBALASSERT(0);
226 /* Sorry, there's just no bouncing back from this one. Fix it. */
227 return;
228 }
229 #if PLAYER_HMODEL
230 Create_HModel(&psPtr->HModelController,root_section);
231 InitHModelSequence(&psPtr->HModelController,0,0,ONE_FIXED);
232 #endif
233 /* Doesn't matter what the sequence is... */
234 #endif
235 break;
236
237 }
238 default:
239 {
240 LOCALASSERT(1==0);
241 break;
242 }
243 }
244
245 NpcData=GetThisNpcData(PlayerType);
246 LOCALASSERT(NpcData);
247 sbPtr->SBDamageBlock.Health=NpcData->StartingStats.Health<<ONE_FIXED_SHIFT;
248 sbPtr->SBDamageBlock.Armour=NpcData->StartingStats.Armour<<ONE_FIXED_SHIFT;
249 sbPtr->SBDamageBlock.SB_H_flags=NpcData->StartingStats.SB_H_flags;
250 sbPtr->SBDamageBlock.IsOnFire=0;
251
252 //{
253 // int *nptr,i;
254 // nptr=(int *)sbPtr->SBname;
255 // for (i=0; i<(SB_NAME_LENGTH>>2); i++) {
256 // *nptr=FastRandom();
257 // nptr++;
258 // }
259 // sbPtr->SBname[SB_NAME_LENGTH-1]=3; /* Just to make sure... */
260 //}
261 AssignNewSBName(sbPtr);
262 }
263
264 //psPtr->Health=STARTOFGAME_MARINE_HEALTH;
265 psPtr->Energy=STARTOFGAME_MARINE_ENERGY;
266 //psPtr->Armour=STARTOFGAME_MARINE_ARMOUR;
267
268 psPtr->Encumberance.MovementMultiple=ONE_FIXED;
269 psPtr->Encumberance.TurningMultiple=ONE_FIXED;
270 psPtr->Encumberance.JumpingMultiple=ONE_FIXED;
271 psPtr->Encumberance.CanCrouch=1;
272 psPtr->Encumberance.CanRun=1;
273
274 psPtr->incidentFlag=0;
275 psPtr->incidentTimer=0;
276
277 /* CDF 16/9/97 Now, those health and armour stats are those of the last cycle. */
278
279 psPtr->Health=sbPtr->SBDamageBlock.Health;
280 psPtr->Armour=sbPtr->SBDamageBlock.Armour;
281
282 psPtr->IsAlive = 1;
283 psPtr->IHaveAPlacedAutogun = 0;
284 psPtr->MyFaceHugger=NULL;
285 psPtr->MyCorpse=NULL;
286 psPtr->tauntTimer=0;
287 TauntSoundPlayed=0;
288 psPtr->fireTimer=0;
289 psPtr->invulnerabilityTimer=0;
290 /* Better safe than sorry. */
291 psPtr->soundHandle=SOUND_NOACTIVEINDEX;
292 psPtr->soundHandle3=SOUND_NOACTIVEINDEX;
293 psPtr->soundHandle4=SOUND_NOACTIVEINDEX;
294 psPtr->soundHandle5=SOUND_NOACTIVEINDEX;
295 psPtr->soundHandleForPredatorCloakDamaged=SOUND_NOACTIVEINDEX;
296 InitPlayerCloakingSystem();/* Patrick 22/8/97 : Cloaking stuff */
297
298 /* KJL 12:06:01 11/14/96 - allocate dynamics block & fill from template */
299 sbPtr->DynPtr = AllocateDynamicsBlock(DYNAMICS_TEMPLATE_MARINE_PLAYER);
300 /* for the time being get world position and orientation from the displayblock */
301 {
302 DISPLAYBLOCK *dPtr = sbPtr->SBdptr;
303 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
304 GLOBALASSERT(dPtr);
305 GLOBALASSERT(dynPtr);
306
307 dynPtr->Position = PlayerStartLocation;
308 dynPtr->OrientMat = PlayerStartMat;
309 MatrixToEuler(&dynPtr->OrientMat,&dynPtr->OrientEuler);
310 //dynPtr->OrientEuler = dPtr->ObEuler;
311
312
313 dynPtr->PrevPosition = dynPtr->Position;
314 dynPtr->PrevOrientMat = dynPtr->OrientMat;
315 dynPtr->PrevOrientEuler = dynPtr->OrientEuler;
316
317 /* let alien walk on walls & ceiling */
318 if (AvP.PlayerType == I_Alien)
319 {
320 dynPtr->ToppleForce = TOPPLE_FORCE_ALIEN;
321 }
322
323 /* KJL 10:56:57 11/24/97 - set ObRadius to a sensible value */
324 dPtr->ObRadius = 1200;
325
326 /*
327 if (AvP.PlayerType == I_Alien) sbPtr->I_SBtype = I_BehaviourAlienPlayer;
328 if (AvP.PlayerType == I_Predator) sbPtr->I_SBtype = I_BehaviourPredatorPlayer;*/
329 /* KJL 18:30:09 11/11/98 - datum used for falling damage */
330 {
331 extern int PlayersMaxHeightWhilstNotInContactWithGround;
332 PlayersMaxHeightWhilstNotInContactWithGround=dynPtr->Position.vy;
333 }
334 }
335
336 /* zero inertia values */
337 psPtr->ForwardInertia=0;
338 psPtr->StrafeInertia=0;
339 psPtr->TurnInertia=0;
340 psPtr->IsMovingInWater = 0;
341 PlayerDamagedOverlayIntensity = 0;
342
343 /* a little addition by patrick */
344 InitPlayerMovementData(sbPtr);
345
346 /* security clearance */
347 psPtr->securityClearances = 0;
348
349 /* thou art mortal */
350 psPtr->IsImmortal = 0;
351
352 if (AvP.Network==I_No_Network)
353 {
354 SoundSys_FadeIn();
355 }
356 else
357 {
358 SoundSys_ResetFadeLevel();
359 }
360
361 //restore the number of saves allowed
362 ResetNumberOfSaves();
363
364 //choosing a start position now occurs later on
365 // if(AvP.Network!=I_No_Network) TeleportNetPlayerToAStartingPosition(sbPtr, 1);
366 }
367
ChangeToMarine()368 void ChangeToMarine()
369 {
370 if(AvP.Network!=I_No_Network)
371 {
372 AvP.PlayerType=I_Marine;
373 NetPlayerRespawn(Player->ObStrategyBlock);
374 InitPlayerMovementData(Player->ObStrategyBlock);
375 Player->ObStrategyBlock->DynPtr->ToppleForce=TOPPLE_FORCE_NONE;
376 netGameData.myCharacterType=netGameData.myNextCharacterType=NGCT_Marine;
377
378 //reorient the player
379 {
380 EULER e;
381 MatrixToEuler(&Player->ObStrategyBlock->DynPtr->OrientMat,&e);
382 e.EulerX=0;
383 e.EulerZ=0;
384
385 CreateEulerMatrix(&e,&Player->ObStrategyBlock->DynPtr->OrientMat);
386 TransposeMatrixCH(&Player->ObStrategyBlock->DynPtr->OrientMat);
387
388 Player->ObStrategyBlock->DynPtr->UseStandardGravity=1;
389 }
390
391 /* CDF 15/3/99, delete all discs... */
392 RemoveAllThisPlayersDiscs();
393
394 }
395 }
ChangeToAlien()396 void ChangeToAlien()
397 {
398 if(AvP.Network!=I_No_Network)
399 {
400 AvP.PlayerType=I_Alien;
401 NetPlayerRespawn(Player->ObStrategyBlock);
402 InitPlayerMovementData(Player->ObStrategyBlock);
403 Player->ObStrategyBlock->DynPtr->ToppleForce=TOPPLE_FORCE_ALIEN;
404
405 netGameData.myCharacterType=netGameData.myNextCharacterType=NGCT_Alien;
406
407 /* CDF 15/3/99, delete all discs... */
408 RemoveAllThisPlayersDiscs();
409 }
410 }
ChangeToPredator()411 void ChangeToPredator()
412 {
413 if(AvP.Network!=I_No_Network)
414 {
415 AvP.PlayerType=I_Predator;
416 NetPlayerRespawn(Player->ObStrategyBlock);
417 InitPlayerMovementData(Player->ObStrategyBlock);
418 Player->ObStrategyBlock->DynPtr->ToppleForce=TOPPLE_FORCE_NONE;
419 netGameData.myCharacterType=netGameData.myNextCharacterType=NGCT_Predator;
420
421 //reorient the player
422 {
423 EULER e;
424 MatrixToEuler(&Player->ObStrategyBlock->DynPtr->OrientMat,&e);
425 e.EulerX=0;
426 e.EulerZ=0;
427
428 CreateEulerMatrix(&e,&Player->ObStrategyBlock->DynPtr->OrientMat);
429 TransposeMatrixCH(&Player->ObStrategyBlock->DynPtr->OrientMat);
430
431 Player->ObStrategyBlock->DynPtr->UseStandardGravity=1;
432 }
433
434 /* CDF 15/3/99, delete all discs... */
435 RemoveAllThisPlayersDiscs();
436 }
437 }
438
MaintainPlayer(void)439 void MaintainPlayer(void)
440 {
441 int rand = FastRandom();
442 PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
443
444 if (playerStatusPtr->IsAlive)
445 {
446 MaintainPlayersInventory();
447 }
448
449 if (ShowAdj) {
450 ShowAdjacencies();
451 }
452
453 /* Set here, as first point. */
454 playerNoise=0;
455
456 /* Incident handling. */
457 playerStatusPtr->incidentFlag=0;
458
459 playerStatusPtr->incidentTimer-=NormalFrameTime;
460
461 if (playerStatusPtr->incidentTimer<0) {
462 playerStatusPtr->incidentFlag=1;
463 playerStatusPtr->incidentTimer=32767+(FastRandom()&65535);
464 }
465
466 /* CDF 9/6/98 - I can't believe this isn't done!!! */
467 Player->ObStrategyBlock->containingModule = playerPherModule;
468
469 if (Observer) {
470 textprint("Observer Mode...\n");
471 }
472 textprint("HtoH Strikes %d\n",HtoHStrikes);
473
474 DoPlayerCloakingSystem();/* Patrick 22/8/97 : Cloaking stuff */
475 // HandlePredatorVisionModes();
476
477 CurrentLightAtPlayer=LightIntensityAtPoint(&Player->ObStrategyBlock->DynPtr->Position);
478
479 #if 1
480 textprint("PlayerLight %d\n",CurrentLightAtPlayer);
481 #endif
482
483 if(AvP.Network==I_No_Network)
484 {
485 #if 1
486 if(playerStatusPtr->Mvt_InputRequests.Flags.Rqst_PauseGame)
487 {
488 // go to start menu
489 AvP.MainLoopRunning = 0;
490 }
491 #endif
492 }
493 else
494 if(playerStatusPtr->Mvt_InputRequests.Flags.Rqst_PauseGame)
495 {
496 if (AvP.Network == I_Host)
497 {
498 TransmitEndOfGameNetMsg();
499 netGameData.myGameState = NGS_EndGame;
500 }
501 else if (AvP.Network == I_Peer)
502 {
503 TransmitPlayerLeavingNetMsg();
504 netGameData.myGameState = NGS_Leaving;
505 }
506 // go to start menu
507 AvP.MainLoopRunning = 0;
508 }
509
510 //Update the player's invulnerabilty timer
511 if(playerStatusPtr->invulnerabilityTimer>0)
512 {
513 playerStatusPtr->invulnerabilityTimer-=NormalFrameTime;
514
515 if(playerStatusPtr->invulnerabilityTimer<=0)
516 {
517 playerStatusPtr->invulnerabilityTimer=0;
518 }
519 //lose invulnerability if player is firing
520
521 if(playerStatusPtr->Mvt_InputRequests.Flags.Rqst_FirePrimaryWeapon)
522 {
523 PLAYER_WEAPON_DATA *weaponPtr = &(playerStatusPtr->WeaponSlot[playerStatusPtr->SelectedWeaponSlot]);
524 if(weaponPtr->WeaponIDNumber!=WEAPON_PRED_MEDICOMP)
525 {
526 playerStatusPtr->invulnerabilityTimer=0;
527 }
528 }
529 if(playerStatusPtr->Mvt_InputRequests.Flags.Rqst_FireSecondaryWeapon)
530 {
531 //not many weapons have an offensive secondary fire
532 PLAYER_WEAPON_DATA *weaponPtr = &(playerStatusPtr->WeaponSlot[playerStatusPtr->SelectedWeaponSlot]);
533 if(weaponPtr->WeaponIDNumber == WEAPON_PULSERIFLE ||
534 weaponPtr->WeaponIDNumber == WEAPON_CUDGEL ||
535 weaponPtr->WeaponIDNumber == WEAPON_MARINE_PISTOL ||
536 weaponPtr->WeaponIDNumber == WEAPON_TWO_PISTOLS ||
537 weaponPtr->WeaponIDNumber == WEAPON_PRED_WRISTBLADE ||
538 weaponPtr->WeaponIDNumber == WEAPON_ALIEN_CLAW)
539 {
540 playerStatusPtr->invulnerabilityTimer=0;
541 }
542 }
543 }
544
545
546 if (AvP.DestructTimer>0) {
547 extern int NormalFrameTime;
548
549 AvP.DestructTimer-=NormalFrameTime;
550 if (AvP.DestructTimer<0) AvP.DestructTimer=0;
551
552 } else if (AvP.DestructTimer==0) {
553 // ...Destruct?
554 CauseDamageToObject(Player->ObStrategyBlock,&TemplateAmmo[AMMO_SADAR_TOW].MaxDamage[AvP.Difficulty], 25*ONE_FIXED,NULL);
555 // That'll learn 'em.
556 }
557
558 /* Take speed sample. */
559 {
560 int speed;
561
562 speed=Approximate3dMagnitude(&Player->ObStrategyBlock->DynPtr->LinVelocity);
563 CurrentGameStats_SpeedSample(speed,NormalFrameTime);
564 }
565
566 /* Is the player on fire? */
567 if (Player->ObStrategyBlock->SBDamageBlock.IsOnFire) {
568
569 myNetworkKillerId=myIgniterId;
570 CauseDamageToObject(Player->ObStrategyBlock,&firedamage,NormalFrameTime,NULL);
571 myNetworkKillerId=AVPDPNetID;
572
573 if (playerStatusPtr->soundHandle3!=SOUND_NOACTIVEINDEX) {
574 if (ActiveSounds[playerStatusPtr->soundHandle3].soundIndex!=SID_FIRE) {
575 Sound_Stop(playerStatusPtr->soundHandle3);
576 Sound_Play(SID_FIRE,"dlev",&(Player->ObStrategyBlock->DynPtr->Position),&playerStatusPtr->soundHandle3,127);
577 } else {
578 Sound_Update3d(playerStatusPtr->soundHandle3,&(Player->ObStrategyBlock->DynPtr->Position));
579 }
580 } else if (playerStatusPtr->IsAlive) {
581 Sound_Play(SID_FIRE,"dlev",&(Player->ObStrategyBlock->DynPtr->Position),&playerStatusPtr->soundHandle3,127);
582 }
583
584 /* Put the fire out... */
585
586 #if 1
587 {
588 int speed;
589 /* Go out? */
590 speed=Approximate3dMagnitude(&Player->ObStrategyBlock->DynPtr->LinVelocity);
591
592 if (speed>22000) {
593 /* Jumping alien. */
594 playerStatusPtr->fireTimer-=(NormalFrameTime*6);
595 } else if (speed>15000) {
596 /* Running alien. */
597 playerStatusPtr->fireTimer-=(NormalFrameTime<<2);
598 } else {
599 /* Normal bloke. */
600 playerStatusPtr->fireTimer-=NormalFrameTime;
601 }
602
603 if(playerStatusPtr->invulnerabilityTimer>0)
604 {
605 //player is invulnerable, so put him out.
606 playerStatusPtr->fireTimer=0;
607 }
608
609 if (playerStatusPtr->fireTimer<=0) {
610 /* Go out. */
611 Player->ObStrategyBlock->SBDamageBlock.IsOnFire=0;
612 playerStatusPtr->fireTimer=0;
613 }
614 }
615 #else
616 if (playerStatusPtr->incidentFlag) {
617 int speed;
618 /* Go out? */
619 speed=Approximate3dMagnitude(&Player->ObStrategyBlock->DynPtr->LinVelocity);
620
621 if (speed>15000) {
622 /* Running alien. */
623 if ((FastRandom()&65535)<13107) {
624 Player->ObStrategyBlock->SBDamageBlock.IsOnFire=0;
625 }
626 } else {
627 /* Normal bloke. */
628 if ((FastRandom()&65535)<3000) {
629 Player->ObStrategyBlock->SBDamageBlock.IsOnFire=0;
630 }
631 }
632 }
633 #endif
634 } else {
635 if (playerStatusPtr->soundHandle3!=SOUND_NOACTIVEINDEX) {
636 Sound_Stop(playerStatusPtr->soundHandle3);
637 }
638 }
639
640 if (playerStatusPtr->IsMovingInWater)
641 {
642 #if 0
643 if (playerStatusPtr->soundHandle4==SOUND_NOACTIVEINDEX) {
644 switch (rand % 4) {
645 case 0:
646 Sound_Play(SID_SPLASH1,"dev",&(Player->ObStrategyBlock->DynPtr->Position),&playerStatusPtr->soundHandle4,127);
647 break;
648 case 1:
649 Sound_Play(SID_SPLASH2,"dev",&(Player->ObStrategyBlock->DynPtr->Position),&playerStatusPtr->soundHandle4,127);
650 break;
651 case 2:
652 Sound_Play(SID_SPLASH3,"dev",&(Player->ObStrategyBlock->DynPtr->Position),&playerStatusPtr->soundHandle4,127);
653 break;
654 default:
655 Sound_Play(SID_SPLASH4,"dev",&(Player->ObStrategyBlock->DynPtr->Position),&playerStatusPtr->soundHandle4,127);
656 break;
657 }
658 }
659 #else
660 /* KJL 19:07:57 25/05/98 - make a noise at most every 1/4 of a sec */
661 if (playerStatusPtr->soundHandle4<=0)
662 {
663 switch (rand&3)
664 {
665 case 0:
666 Sound_Play(SID_SPLASH1,"d",&(Player->ObStrategyBlock->DynPtr->Position));
667 break;
668 case 1:
669 Sound_Play(SID_SPLASH2,"d",&(Player->ObStrategyBlock->DynPtr->Position));
670 break;
671 case 2:
672 Sound_Play(SID_SPLASH3,"d",&(Player->ObStrategyBlock->DynPtr->Position));
673 break;
674 default:
675 Sound_Play(SID_SPLASH4,"d",&(Player->ObStrategyBlock->DynPtr->Position));
676 break;
677
678 }
679 playerStatusPtr->soundHandle4=16384;
680 }
681 else
682 {
683 playerStatusPtr->soundHandle4-=NormalFrameTime;
684 }
685 #endif
686 }
687
688
689 /* KJL 14:54:48 25/05/98 - reset water flag to zero for next frame */
690 playerStatusPtr->IsMovingInWater = 0;
691
692 /* Taunt effects. */
693 if (playerStatusPtr->tauntTimer) {
694 int ex,ey,ez;
695
696 playerNoise=1;
697 /* An actual noise, too, would probably be good. */
698
699 if (AvP.PlayerType==I_Alien) {
700
701 //if (playerStatusPtr->tauntTimer>(TAUNT_LENGTH>>1)) {
702 if (TauntSoundPlayed==0) {
703 /* That should make sure we don't get more than one. */
704 if (playerStatusPtr->soundHandle==SOUND_NOACTIVEINDEX) {
705 #if 0
706 Sound_Play(SID_ALIEN_SCREAM,"de",&(Player->ObStrategyBlock->DynPtr->Position),&playerStatusPtr->soundHandle);
707 #else
708 PlayAlienSound(0,ASC_Taunt,0,&playerStatusPtr->soundHandle,&(Player->ObStrategyBlock->DynPtr->Position));
709 if(AvP.Network!=I_No_Network) netGameData.myLastScream=ASC_Taunt;
710 #endif
711 TauntSoundPlayed=1;
712 }
713 }
714
715 /* Wave the head around? */
716 ex=0;
717 ey=0;
718 ez=0;
719
720 ex=MUL_FIXED(64,GetSin(((playerStatusPtr->tauntTimer>>6)&wrap360)));
721 ey=MUL_FIXED(128,GetSin(((playerStatusPtr->tauntTimer>>5)&wrap360)));
722 ez=MUL_FIXED(-64,GetSin(((playerStatusPtr->tauntTimer>>5)&wrap360)));
723
724 ex&=wrap360;
725 ey&=wrap360;
726 ez&=wrap360;
727
728 HeadOrientation.EulerX=ex;
729 HeadOrientation.EulerY=ey;
730 HeadOrientation.EulerZ=ez;
731 } else if (AvP.PlayerType==I_Marine) {
732 if (TauntSoundPlayed==0) {
733 /* That should make sure we don't get more than one. */
734 if (playerStatusPtr->soundHandle==SOUND_NOACTIVEINDEX) {
735 PlayMarineScream(0,SC_Taunt,0,&playerStatusPtr->soundHandle,NULL);
736 if(AvP.Network!=I_No_Network) netGameData.myLastScream=SC_Taunt;
737 TauntSoundPlayed=1;
738 }
739 }
740 } else if (AvP.PlayerType==I_Predator) {
741 if (TauntSoundPlayed==0) {
742 /* That should make sure we don't get more than one. */
743 if (playerStatusPtr->soundHandle==SOUND_NOACTIVEINDEX) {
744 PlayPredatorSound(0,PSC_Taunt,0,&playerStatusPtr->soundHandle,NULL);
745 if(AvP.Network!=I_No_Network) netGameData.myLastScream=PSC_Taunt;
746 TauntSoundPlayed=1;
747 }
748 }
749 } else {
750 GLOBALASSERT(0);
751 }
752
753 }
754
755 /* Decay alien superhealth. */
756 if (AvP.PlayerType==I_Alien) {
757 NPC_DATA *NpcData;
758
759 switch (AvP.Difficulty) {
760 case I_Easy:
761 NpcData=GetThisNpcData(I_PC_Alien_Easy);
762 break;
763 default:
764 case I_Medium:
765 NpcData=GetThisNpcData(I_PC_Alien_Medium);
766 break;
767 case I_Hard:
768 NpcData=GetThisNpcData(I_PC_Alien_Hard);
769 break;
770 case I_Impossible:
771 NpcData=GetThisNpcData(I_PC_Alien_Impossible);
772 break;
773 }
774 LOCALASSERT(NpcData);
775
776 if (Player->ObStrategyBlock->SBDamageBlock.Health>(NpcData->StartingStats.Health<<ONE_FIXED_SHIFT)) {
777 /* Decay health a bit. */
778 Player->ObStrategyBlock->SBDamageBlock.Health-=(NormalFrameTime);
779 if (Player->ObStrategyBlock->SBDamageBlock.Health<(NpcData->StartingStats.Health<<ONE_FIXED_SHIFT)) {
780 Player->ObStrategyBlock->SBDamageBlock.Health=NpcData->StartingStats.Health<<ONE_FIXED_SHIFT;
781 }
782 PlayerStatusPtr->Health=Player->ObStrategyBlock->SBDamageBlock.Health;
783 }
784 }
785 }
786
PlayerIsDamaged(STRATEGYBLOCK * sbPtr,DAMAGE_PROFILE * damage,int multiplier,VECTORCH * incoming)787 void PlayerIsDamaged(STRATEGYBLOCK *sbPtr, DAMAGE_PROFILE *damage, int multiplier,VECTORCH* incoming)
788 {
789 int rand = FastRandom();
790 int pitch = (rand & 255) - 128;
791 int deltaHealth;
792 int deltaArmour;
793
794 /* access the extra data hanging off the strategy block */
795 PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (sbPtr->SBdataptr);
796 GLOBALASSERT(playerStatusPtr);
797
798 deltaHealth=playerStatusPtr->Health-sbPtr->SBDamageBlock.Health;
799 deltaArmour=playerStatusPtr->Armour-sbPtr->SBDamageBlock.Armour;
800
801 CurrentGameStats_DamageTaken(deltaHealth,deltaArmour);
802
803 /* Patrick 4/8/97--------------------------------------------------
804 A little hack-et to make the predator tougher in multiplayer games
805 ------------------------------------------------------------------*/
806 //if((AvP.Network!=I_No_Network)&&(AvP.PlayerType==I_Predator)) damage>>=1;
807 /* ChrisF 16/9/97 No, predators are now... wait for it... tough. */
808
809 if (playerStatusPtr->IsAlive)
810 {
811 #if 0
812 damage <<= 16;
813 if (playerStatusPtr->Armour > 0)
814 {
815 if (playerStatusPtr->Armour >= damage/2)
816 {
817 playerStatusPtr->Armour -= damage/2;
818 playerStatusPtr->Health -= damage/4;
819 }
820 else
821 {
822 damage -= playerStatusPtr->Armour*2;
823 playerStatusPtr->Health -= playerStatusPtr->Armour/2 + damage;
824 playerStatusPtr->Armour = 0;
825 }
826 }
827 else
828 {
829 playerStatusPtr->Health -= damage;
830 }
831 #endif
832 {
833 int maxTilt = deltaHealth>>12;
834 int halfTilt = maxTilt/2;
835 if (maxTilt)
836 {
837 HeadOrientation.EulerX = (FastRandom()%maxTilt)-halfTilt;
838 HeadOrientation.EulerY = (FastRandom()%maxTilt)-halfTilt;
839 HeadOrientation.EulerZ = (FastRandom()%maxTilt)-halfTilt;
840
841 if (HeadOrientation.EulerX < 0) HeadOrientation.EulerX += 4096;
842 if (HeadOrientation.EulerY < 0) HeadOrientation.EulerY += 4096;
843 if (HeadOrientation.EulerZ < 0) HeadOrientation.EulerZ += 4096;
844 }
845 }
846
847 if ((playerStatusPtr->soundHandle==SOUND_NOACTIVEINDEX)&&(deltaHealth||deltaArmour)) {
848 switch (AvP.PlayerType)
849 {
850 case I_Alien:
851 {
852 if ((damage->Impact==0)
853 &&(damage->Cutting==0)
854 &&(damage->Penetrative==0)
855 &&(damage->Fire>0)
856 &&(damage->Electrical==0)
857 &&(damage->Acid==0)
858 ) {
859 PlayAlienSound(0,ASC_PC_OnFire,pitch,&playerStatusPtr->soundHandle,NULL);
860 if(AvP.Network!=I_No_Network) netGameData.myLastScream=ASC_PC_OnFire;
861 } else {
862 PlayAlienSound(0,ASC_Scream_Hurt,pitch,&playerStatusPtr->soundHandle,NULL);
863 if(AvP.Network!=I_No_Network) netGameData.myLastScream=ASC_Scream_Hurt;
864 }
865 break;
866 }
867
868 case I_Marine:
869 {
870 if (damage->Id==AMMO_FACEHUGGER) {
871 PlayMarineScream(0,SC_Facehugged,pitch,&playerStatusPtr->soundHandle,NULL);
872 } else if (damage->Id==AMMO_FALLING_POSTMAX) {
873 PlayMarineScream(0,SC_Falling,pitch,&playerStatusPtr->soundHandle,NULL);
874 } else if ((damage->Impact==0)
875 &&(damage->Cutting==0)
876 &&(damage->Penetrative==0)
877 &&(damage->Fire==0)
878 &&(damage->Electrical==0)
879 &&(damage->Acid>0)
880 ) {
881 PlayMarineScream(0,SC_Acid,pitch,&playerStatusPtr->soundHandle,NULL);
882 if(AvP.Network!=I_No_Network) netGameData.myLastScream=SC_Acid;
883 } else if ((damage->Impact==0)
884 &&(damage->Cutting==0)
885 &&(damage->Penetrative==0)
886 &&(damage->Fire>0)
887 &&(damage->Electrical==0)
888 &&(damage->Acid==0)
889 ) {
890 PlayMarineScream(0,SC_PC_OnFire,pitch,&playerStatusPtr->soundHandle,NULL);
891 if(AvP.Network!=I_No_Network) netGameData.myLastScream=SC_PC_OnFire;
892 } else {
893 PlayMarineScream(0,SC_Pain,pitch,&playerStatusPtr->soundHandle,NULL);
894 if(AvP.Network!=I_No_Network) netGameData.myLastScream=SC_Pain;
895 }
896 break;
897 }
898
899 case I_Predator:
900 {
901 if (damage->Id==AMMO_FACEHUGGER) {
902 PlayPredatorSound(0,PSC_Facehugged,pitch,&playerStatusPtr->soundHandle,NULL);
903 } else if ((damage->Impact==0)
904 &&(damage->Cutting==0)
905 &&(damage->Penetrative==0)
906 &&(damage->Fire==0)
907 &&(damage->Electrical==0)
908 &&(damage->Acid>0)
909 ) {
910 PlayPredatorSound(0,PSC_Acid,pitch,&playerStatusPtr->soundHandle,NULL);
911 if(AvP.Network!=I_No_Network) netGameData.myLastScream=PSC_Acid;
912 } else if ((damage->Impact==0)
913 &&(damage->Cutting==0)
914 &&(damage->Penetrative==0)
915 &&(damage->Fire>0)
916 &&(damage->Electrical==0)
917 &&(damage->Acid==0)
918 ) {
919 PlayPredatorSound(0,PSC_PC_OnFire,pitch,&playerStatusPtr->soundHandle,NULL);
920 if(AvP.Network!=I_No_Network) netGameData.myLastScream=PSC_PC_OnFire;
921 } else {
922 PlayPredatorSound(0,PSC_Scream_Hurt,pitch,&playerStatusPtr->soundHandle,NULL);
923 if(AvP.Network!=I_No_Network) netGameData.myLastScream=PSC_Scream_Hurt;
924 }
925 break;
926 }
927
928 default:
929 {
930 break;
931 }
932 }
933 playerNoise=1;
934 /* Alert marines, pretty much whoever you are. */
935 if (AvP.PlayerType==I_Marine) {
936 PointAlert(3, &Player->ObStrategyBlock->DynPtr->Position);
937 } else {
938 #if 0
939 PointAlert(2, &Player->ObStrategyBlock->DynPtr->Position);
940 #endif
941 }
942 }
943
944 {
945 NPC_DATA *NpcData;
946 int scaled_DeltaHealth;
947
948 switch (AvP.PlayerType)
949 {
950 case I_Marine:
951 switch (AvP.Difficulty) {
952 case I_Easy:
953 NpcData=GetThisNpcData(I_PC_Marine_Easy);
954 break;
955 default:
956 case I_Medium:
957 NpcData=GetThisNpcData(I_PC_Marine_Medium);
958 break;
959 case I_Hard:
960 NpcData=GetThisNpcData(I_PC_Marine_Hard);
961 break;
962 case I_Impossible:
963 NpcData=GetThisNpcData(I_PC_Marine_Impossible);
964 break;
965 }
966 break;
967 case I_Alien:
968 switch (AvP.Difficulty) {
969 case I_Easy:
970 NpcData=GetThisNpcData(I_PC_Alien_Easy);
971 break;
972 default:
973 case I_Medium:
974 NpcData=GetThisNpcData(I_PC_Alien_Medium);
975 break;
976 case I_Hard:
977 NpcData=GetThisNpcData(I_PC_Alien_Hard);
978 break;
979 case I_Impossible:
980 NpcData=GetThisNpcData(I_PC_Alien_Impossible);
981 break;
982 }
983 break;
984 case I_Predator:
985 switch (AvP.Difficulty) {
986 case I_Easy:
987 NpcData=GetThisNpcData(I_PC_Predator_Easy);
988 break;
989 default:
990 case I_Medium:
991 NpcData=GetThisNpcData(I_PC_Predator_Medium);
992 break;
993 case I_Hard:
994 NpcData=GetThisNpcData(I_PC_Predator_Hard);
995 break;
996 case I_Impossible:
997 NpcData=GetThisNpcData(I_PC_Predator_Impossible);
998 break;
999 }
1000 break;
1001 default:
1002 LOCALASSERT(0);
1003 break;
1004 }
1005 /* Compute scaled deltaHealth... */
1006 scaled_DeltaHealth=MUL_FIXED(deltaHealth,100);
1007 scaled_DeltaHealth=DIV_FIXED(scaled_DeltaHealth,NpcData->StartingStats.Health);
1008
1009 if (scaled_DeltaHealth>PlayerDamagedOverlayIntensity)
1010 {
1011 PlayerDamagedOverlayIntensity=scaled_DeltaHealth;
1012 }
1013 }
1014
1015 if (deltaHealth>ONE_FIXED)
1016 {
1017 VECTORCH abovePosition = Global_VDB_Ptr->VDB_World;
1018 abovePosition.vy-=1000;
1019 switch (AvP.PlayerType)
1020 {
1021 case I_Alien:
1022 MakeBloodExplosion(&Global_VDB_Ptr->VDB_World, 127, &abovePosition, deltaHealth/ONE_FIXED, PARTICLE_ALIEN_BLOOD);
1023 break;
1024 case I_Marine:
1025 MakeBloodExplosion(&Global_VDB_Ptr->VDB_World, 127, &abovePosition, deltaHealth/ONE_FIXED, PARTICLE_HUMAN_BLOOD);
1026 break;
1027 case I_Predator:
1028 MakeBloodExplosion(&Global_VDB_Ptr->VDB_World, 127, &abovePosition, deltaHealth/ONE_FIXED, PARTICLE_PREDATOR_BLOOD);
1029 break;
1030 }
1031 }
1032
1033 if (sbPtr->SBDamageBlock.Health <= 0)
1034 {
1035 if (playerStatusPtr->IsImmortal) sbPtr->SBDamageBlock.Health=0;
1036 else
1037 {
1038 PlayerIsDead(damage,multiplier,incoming);
1039 }
1040 }
1041
1042 playerStatusPtr->Health=sbPtr->SBDamageBlock.Health;
1043 playerStatusPtr->Armour=sbPtr->SBDamageBlock.Armour;
1044
1045 }
1046 }
1047
1048 extern EULER deathTargetOrientation;
1049 extern int deathFadeLevel;
1050 extern int weaponHandle;
1051
PlayerIsDead(DAMAGE_PROFILE * damage,int multiplier,VECTORCH * incoming)1052 static void PlayerIsDead(DAMAGE_PROFILE* damage,int multiplier,VECTORCH* incoming)
1053 {
1054 STRATEGYBLOCK *sbPtr = Player->ObStrategyBlock;
1055 PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (sbPtr->SBdataptr);
1056 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
1057
1058 /* Stop pred hud sound. */
1059 if(predHUDSoundHandle != SOUND_NOACTIVEINDEX) {
1060 Sound_Stop(predHUDSoundHandle);
1061 }
1062 if(predOVision_SoundHandle != SOUND_NOACTIVEINDEX) {
1063 Sound_Stop(predOVision_SoundHandle);
1064 }
1065 if(weaponHandle != SOUND_NOACTIVEINDEX) {
1066 Sound_Stop(weaponHandle);
1067 }
1068
1069 // Do some death sounds
1070
1071 switch (AvP.PlayerType)
1072 {
1073 case I_Alien:
1074 {
1075 PlayAlienSound(0,ASC_Scream_Dying,0,NULL,NULL);
1076 break;
1077 }
1078 case I_Marine:
1079 {
1080 if (damage->Id==AMMO_FACEHUGGER) {
1081 PlayMarineScream(0,SC_Facehugged,0,NULL,NULL);
1082 } else {
1083 PlayMarineScream(0,SC_Death,0,NULL,NULL);
1084 }
1085 break;
1086 }
1087 case I_Predator:
1088 {
1089 if (damage->Id==AMMO_FACEHUGGER) {
1090 PlayPredatorSound(0,PSC_Facehugged,0,NULL,NULL);
1091 } else {
1092 PlayPredatorSound(0,PSC_Scream_Dying,0,NULL,NULL);
1093 }
1094
1095 {
1096 VECTORCH abovePosition = Global_VDB_Ptr->VDB_World;
1097 abovePosition.vy-=1000;
1098 MakeBloodExplosion(&Global_VDB_Ptr->VDB_World, 127, &abovePosition, 200, PARTICLE_PREDATOR_BLOOD);
1099 }
1100 break;
1101 }
1102 default:
1103 {
1104 break;
1105 }
1106 }
1107
1108 /* Well, it was nice knowing you. */
1109 //playerStatusPtr->Health = 0;
1110 sbPtr->SBDamageBlock.Health=0;
1111 playerStatusPtr->IsAlive = 0;
1112
1113 /* make player fall to the ground */
1114 // Player->ObShape=I_ShapeMarinePlayerLieDown;
1115 // MapBlockInit(Player);
1116
1117 /* give player a little bounce */
1118 dynPtr->Elasticity = 16384;
1119 /* but a lot of friction */
1120 // dynPtr->Friction = 1<<20;
1121 // dynPtr->Mass = 1<<20;
1122
1123 /* cancel any velocity */
1124 dynPtr->LinVelocity.vx = 0;
1125 dynPtr->LinVelocity.vy = 0;
1126 dynPtr->LinVelocity.vz = 0;
1127
1128 deathTargetOrientation.EulerX = 0;//1024-(FastRandom()&255);
1129 deathFadeLevel=65536;
1130
1131 /* if in single player, fade out sound... */
1132 if (AvP.Network==I_No_Network)
1133 {
1134 SoundSys_FadeOut();
1135 }
1136
1137 if (AvP.PlayerType == I_Alien)
1138 {
1139 sbPtr->DynPtr->UseStandardGravity=1;
1140 }
1141
1142 /* network support... */
1143 if(AvP.Network!=I_No_Network)
1144 {
1145 playerStatusPtr->MyCorpse=MakeNewCorpse();
1146 AddNetMsg_PlayerKilled((*((int *)(&(playerStatusPtr->MyCorpse->SBname[4])))),damage);
1147
1148 /*---------------------------------------------------------**
1149 ** handle various special body being torn apart cases **
1150 **---------------------------------------------------------*/
1151
1152 /*Note that we need to apply the damage to the corpse before we can determine a
1153 suitable death anim sequence*/
1154 if(damage)
1155 {
1156 HMODELCONTROLLER* hmodel=playerStatusPtr->MyCorpse->SBdptr->HModelControlBlock;
1157 //was the player killed by a jaw attack?
1158 if(damage->Id==AMMO_ALIEN_BITE_KILLSECTION && AvP.PlayerType!=I_Alien)
1159 {
1160 //knock the head of the corpse
1161 SECTION_DATA *head;
1162 head=GetThisSectionData(playerStatusPtr->MyCorpse->SBdptr->HModelControlBlock->section_data,"head");
1163 //do lots of damage to it
1164 if(head)
1165 {
1166 CauseDamageToHModel(playerStatusPtr->MyCorpse->SBdptr->HModelControlBlock,playerStatusPtr->MyCorpse, &TemplateAmmo[AMMO_ALIEN_BITE_KILLSECTION].MaxDamage[AvP.Difficulty],
1167 ONE_FIXED,head,NULL,NULL,0);
1168 }
1169 //play the head being bitten off sound
1170 Sound_Play(SID_ALIEN_JAW_ATTACK,"d",&(Player->ObStrategyBlock->DynPtr->Position));
1171
1172 }
1173 //chopped by predator disc?
1174 else if(damage->Id==AMMO_PRED_DISC && AvP.PlayerType!=I_Predator)
1175 {
1176 SECTION_DATA *firstSectionPtr;
1177 SECTION_DATA *chest_section=0;
1178
1179 firstSectionPtr=hmodel->section_data;
1180 LOCALASSERT(firstSectionPtr);
1181 LOCALASSERT(firstSectionPtr->flags§ion_data_initialised);
1182
1183 /* look for the object's torso in preference */
1184 chest_section =GetThisSectionData(hmodel->section_data,"chest");
1185
1186 if (chest_section)
1187 {
1188 CauseDamageToHModel(hmodel,playerStatusPtr->MyCorpse,damage, ONE_FIXED, chest_section,incoming,&chest_section->World_Offset,0);
1189 }
1190 else
1191 {
1192 CauseDamageToObject(playerStatusPtr->MyCorpse,damage, ONE_FIXED,incoming);
1193 }
1194 }
1195 //blown up by shoulder cannon?
1196 else if(damage->Id==AMMO_PLASMACASTER_PCKILL && AvP.PlayerType!=I_Predator)
1197 {
1198 SECTION_DATA *firstSectionPtr;
1199 SECTION_DATA *chest_section=0;
1200
1201 firstSectionPtr=hmodel->section_data;
1202 LOCALASSERT(firstSectionPtr);
1203 LOCALASSERT(firstSectionPtr->flags§ion_data_initialised);
1204
1205 /* look for the object's torso in preference */
1206 chest_section =GetThisSectionData(hmodel->section_data,"chest");
1207
1208 if (chest_section)
1209 {
1210 //spherical blood explosion for aliens
1211 if(AvP.PlayerType==I_Alien)
1212 CauseDamageToHModel(hmodel,playerStatusPtr->MyCorpse,damage, ONE_FIXED, chest_section,NULL,&chest_section->World_Offset,0);
1213 else
1214 CauseDamageToHModel(hmodel,playerStatusPtr->MyCorpse,damage, ONE_FIXED, chest_section,incoming,&chest_section->World_Offset,0);
1215 }
1216 else
1217 {
1218 CauseDamageToObject(playerStatusPtr->MyCorpse,damage, ONE_FIXED,NULL);
1219 }
1220 }
1221 else
1222 {
1223 SECTION_DATA *section_data=0;
1224 if(MyHitBodyPartId!=-1)
1225 {
1226 //we have the id of the section that was hit when we died
1227 //so try to find the section
1228 section_data=GetThisSectionData_FromID(hmodel->section_data,MyHitBodyPartId);
1229 }
1230 //damage the corpse with the fatal blow
1231 if(section_data)
1232 {
1233 DISPLAYBLOCK *fragged_section=0;
1234 fragged_section=CauseDamageToHModel(hmodel,playerStatusPtr->MyCorpse,damage,
1235 multiplier,section_data,incoming,NULL,0);
1236
1237 if(fragged_section && incoming && damage->Id==AMMO_PRED_RIFLE)
1238 {
1239 //a speargun has fragged off a body part , so we need to create a spear
1240 VECTORCH direction=*incoming;
1241 RotateVector(&direction,&Player->ObMat);
1242 CreateSpearPossiblyWithFragment(fragged_section,&fragged_section->ObWorld,&direction);
1243
1244 }
1245 }
1246 else
1247 {
1248 CauseDamageToObject(playerStatusPtr->MyCorpse,damage,multiplier,incoming);
1249 }
1250 }
1251 }
1252 /*---------------------------------**
1253 ** Choose death anim sequence **
1254 **---------------------------------*/
1255 {
1256 int deathId;
1257 switch(AvP.PlayerType)
1258 {
1259 case I_Marine :
1260 deathId = Deduce_PlayerMarineDeathSequence(playerStatusPtr->MyCorpse,damage,multiplier,incoming);
1261 break;
1262
1263 case I_Alien :
1264 deathId = Deduce_PlayerAlienDeathSequence(playerStatusPtr->MyCorpse,damage,multiplier,incoming);
1265 break;
1266
1267 case I_Predator :
1268 deathId = Deduce_PlayerPredatorDeathSequence(playerStatusPtr->MyCorpse,damage,multiplier,incoming);
1269 break;
1270 }
1271 //apply the animation
1272 ApplyCorpseDeathAnim(playerStatusPtr->MyCorpse,deathId);
1273 //tell everyone else about the chosen death
1274 AddNetMsg_PlayerDeathAnim(deathId,*(int*)&playerStatusPtr->MyCorpse->SBname[4]);
1275
1276 }
1277
1278 // if(AvP.Network==I_Host) DoNetScoresForHostDeath();
1279
1280 //does this death require a change in character type?
1281 if(netGameData.gameType==NGT_LastManStanding)
1282 {
1283 //Am I a marine or predator?
1284 if(AvP.PlayerType!=I_Alien)
1285 {
1286 //was I killed by an alien?
1287 if(myNetworkKillerId && myNetworkKillerId!=AVPDPNetID)
1288 {
1289 int killer_index=PlayerIdInPlayerList(myNetworkKillerId);
1290 GLOBALASSERT(killer_index!=NET_IDNOTINPLAYERLIST);
1291 if(netGameData.playerData[killer_index].characterType==NGCT_Alien)
1292 {
1293 //set the next character to be an alien then
1294 netGameData.myNextCharacterType=NGCT_Alien;
1295 }
1296
1297 }
1298 else
1299 {
1300 //suicide , so become an alien anyway
1301 netGameData.myNextCharacterType=NGCT_Alien;
1302 }
1303 }
1304 }
1305 else if(netGameData.gameType==NGT_PredatorTag || netGameData.gameType==NGT_AlienTag)
1306 {
1307 //we may need to change character
1308 extern void SpeciesTag_DetermineMyNextCharacterType();
1309 SpeciesTag_DetermineMyNextCharacterType();
1310 }
1311 }
1312
1313 if (playerStatusPtr->soundHandle!=SOUND_NOACTIVEINDEX) {
1314 Sound_Stop(playerStatusPtr->soundHandle);
1315 }
1316 if (playerStatusPtr->soundHandle3!=SOUND_NOACTIVEINDEX) {
1317 Sound_Stop(playerStatusPtr->soundHandle3);
1318 }
1319
1320 /* KJL 15:36:41 10/09/98 - don't hang around on my behalf */
1321 DisengageGrapplingHook();
1322
1323 }
1324
ActivateSelfDestructSequence(int seconds)1325 void ActivateSelfDestructSequence (int seconds)
1326 {
1327 // Currently does nothing, called when sequence is activated
1328
1329 if (AvP.DestructTimer==-1) {
1330 AvP.DestructTimer=ONE_FIXED*seconds; //2 1/2 mins.
1331 }
1332 }
1333
DeInitialisePlayer(void)1334 void DeInitialisePlayer(void) {
1335 /* I thought it would be logical to put it here... */
1336
1337 int slot = MAX_NO_OF_WEAPON_SLOTS;
1338 #if 0
1339 PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
1340 #endif
1341
1342 do {
1343 TXACTRLBLK *txactrl,*txactrl_next;
1344 PLAYER_WEAPON_DATA *wdPtr = &PlayerStatusBlock.WeaponSlot[--slot];
1345
1346 txactrl_next = wdPtr->TxAnimCtrl;
1347
1348 while(txactrl_next)
1349 {
1350 txactrl = txactrl_next;
1351 txactrl_next = txactrl->tac_next;
1352 DeallocateMem((void*)txactrl);
1353 }
1354
1355 wdPtr->TxAnimCtrl=NULL;
1356 } while(slot);
1357
1358 #if 0 //this hmodel isn't being set up for the moment - Richard
1359 Dispel_HModel(&playerStatusPtr->HModelController);
1360 #endif
1361
1362 }
1363
1364 static int cloakDebounce = 1;
1365
InitPlayerCloakingSystem(void)1366 void InitPlayerCloakingSystem(void)
1367 {
1368 PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
1369 LOCALASSERT(playerStatusPtr);
1370
1371 playerStatusPtr->cloakOn = 0;
1372 playerStatusPtr->cloakPositionGivenAway = 0;
1373 playerStatusPtr->CloakingEffectiveness = 0;
1374
1375 playerStatusPtr->FieldCharge = PLAYERCLOAK_MAXENERGY;
1376 playerStatusPtr->cloakPositionGivenAwayTimer = 0;
1377 playerStatusPtr->PlasmaCasterCharge=0;
1378
1379 GimmeChargeCalls=0;
1380 HtoHStrikes=0;
1381 CurrentLightAtPlayer=0;
1382 }
1383
DoPlayerCloakingSystem(void)1384 static void DoPlayerCloakingSystem(void)
1385 {
1386 extern int NormalFrameTime;
1387 PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
1388 LOCALASSERT(playerStatusPtr);
1389
1390 if(AvP.PlayerType!=I_Predator) return;
1391 if(!(playerStatusPtr->IsAlive)) return;
1392
1393 /* Handle controls. */
1394 if (playerStatusPtr->Mvt_InputRequests.Flags.Rqst_ChangeVision)
1395 {
1396 if (cloakDebounce)
1397 {
1398 cloakDebounce = 0;
1399 if (playerStatusPtr->cloakOn)
1400 {
1401 Sound_Play(SID_PRED_CLOAKOFF,"h");
1402 playerStatusPtr->cloakOn = 0;
1403 //playerNoise=1;
1404 } else {
1405 /* Check validity. */
1406 if ((playerStatusPtr->FieldCharge>CloakThreshold)
1407 &&(playerStatusPtr->FieldCharge>CloakPowerOnDrain)) {
1408
1409 PLAYER_WEAPON_DATA *weaponPtr;
1410 TEMPLATE_WEAPON_DATA *twPtr;
1411
1412 weaponPtr = &(playerStatusPtr->WeaponSlot[playerStatusPtr->SelectedWeaponSlot]);
1413 twPtr = &TemplateWeapon[weaponPtr->WeaponIDNumber];
1414 if (!(((weaponPtr->CurrentState==WEAPONSTATE_FIRING_PRIMARY)||(weaponPtr->CurrentState==WEAPONSTATE_FIRING_SECONDARY))
1415 &&(twPtr->FireWhenCloaked==0)))
1416 {
1417 playerStatusPtr->FieldCharge-=CloakPowerOnDrain;
1418 CurrentGameStats_ChargeUsed(CloakPowerOnDrain);
1419 playerStatusPtr->cloakOn = 1;
1420 playerStatusPtr->CloakingEffectiveness = 0;
1421 Sound_Play(SID_PRED_CLOAKON,"h");
1422 //playerNoise=1;
1423 }
1424 }
1425 }
1426 }
1427 }
1428 else
1429 {
1430 cloakDebounce = 1;
1431
1432 if (playerStatusPtr->cloakOn)
1433 {
1434 int maxPossibleEffectiveness;
1435 VECTORCH velocity;
1436 DYNAMICSBLOCK *dynPtr=Player->ObStrategyBlock->DynPtr;
1437
1438 velocity.vx = dynPtr->Position.vx - dynPtr->PrevPosition.vx;
1439 velocity.vy = dynPtr->Position.vy - dynPtr->PrevPosition.vy;
1440 velocity.vz = dynPtr->Position.vz - dynPtr->PrevPosition.vz;
1441
1442 if (playerStatusPtr->IsMovingInWater)
1443 {
1444 maxPossibleEffectiveness = 0;
1445 if(playerStatusPtr->soundHandleForPredatorCloakDamaged==SOUND_NOACTIVEINDEX)
1446 Sound_Play(SID_PREDATOR_CLOAKING_DAMAGED,"el",playerStatusPtr->soundHandleForPredatorCloakDamaged);
1447 }
1448 else
1449 {
1450 if(playerStatusPtr->soundHandleForPredatorCloakDamaged!=SOUND_NOACTIVEINDEX)
1451 Sound_Stop(playerStatusPtr->soundHandleForPredatorCloakDamaged);
1452
1453 maxPossibleEffectiveness = ONE_FIXED - DIV_FIXED(Magnitude(&velocity)*2,NormalFrameTime);
1454 if (maxPossibleEffectiveness<0) maxPossibleEffectiveness = 0;
1455 }
1456
1457 playerStatusPtr->CloakingEffectiveness += NormalFrameTime;
1458 if (playerStatusPtr->CloakingEffectiveness>maxPossibleEffectiveness)
1459 {
1460 playerStatusPtr->CloakingEffectiveness = maxPossibleEffectiveness;
1461 }
1462 }
1463 else
1464 {
1465 playerStatusPtr->CloakingEffectiveness -= NormalFrameTime;
1466 if (playerStatusPtr->CloakingEffectiveness<0)
1467 {
1468 playerStatusPtr->CloakingEffectiveness=0;
1469 }
1470 if(playerStatusPtr->soundHandleForPredatorCloakDamaged!=SOUND_NOACTIVEINDEX)
1471 Sound_Stop(playerStatusPtr->soundHandleForPredatorCloakDamaged);
1472 }
1473
1474 }
1475 #if 1
1476
1477 /* position-given-away-timer runs whatever state the cloak is in */
1478 if(playerStatusPtr->cloakPositionGivenAway)
1479 {
1480 playerStatusPtr->cloakPositionGivenAwayTimer-=NormalFrameTime;
1481 if(playerStatusPtr->cloakPositionGivenAwayTimer<=0)
1482 {
1483 playerStatusPtr->cloakPositionGivenAwayTimer = 0;
1484 playerStatusPtr->cloakPositionGivenAway = 0;
1485 playerStatusPtr->CloakingEffectiveness = 0;
1486 }
1487 }
1488
1489 /* now sort out energy discharge/recharge */
1490 if(playerStatusPtr->cloakOn)
1491 {
1492 int chargeUsed;
1493
1494 chargeUsed=MUL_FIXED(NormalFrameTime,CloakDrain);
1495
1496 if (playerStatusPtr->IsMovingInWater) {
1497 chargeUsed<<=2;
1498 }
1499
1500 if (chargeUsed>playerStatusPtr->FieldCharge) {
1501 chargeUsed=playerStatusPtr->FieldCharge;
1502 }
1503 playerStatusPtr->FieldCharge -= chargeUsed;
1504 CurrentGameStats_ChargeUsed(chargeUsed);
1505 if(playerStatusPtr->FieldCharge <= 0)
1506 {
1507 playerStatusPtr->FieldCharge = 0;
1508 playerStatusPtr->cloakOn = 0;
1509 playerStatusPtr->Mvt_InputRequests.Flags.Rqst_ChangeVision = 1;
1510 Sound_Play(SID_PRED_CLOAKOFF,"h");
1511 //playerNoise=1;
1512 }
1513
1514 /* TrickleCharge Difficulty Variation! */
1515 if ((AvP.Difficulty==I_Hard)||(AvP.Difficulty==I_Impossible)) {
1516 playerStatusPtr->FieldCharge += MUL_FIXED(NormalFrameTime,(TrickleCharge>>1));
1517 } else {
1518 playerStatusPtr->FieldCharge += MUL_FIXED(NormalFrameTime,TrickleCharge);
1519 }
1520
1521 if(playerStatusPtr->FieldCharge > PLAYERCLOAK_MAXENERGY) {
1522 playerStatusPtr->FieldCharge = PLAYERCLOAK_MAXENERGY;
1523 }
1524
1525 }
1526 else
1527 {
1528 if(playerStatusPtr->FieldCharge < PLAYERCLOAK_MAXENERGY)
1529 {
1530
1531 /* TrickleCharge Difficulty Variation! */
1532 if ((AvP.Difficulty==I_Hard)||(AvP.Difficulty==I_Impossible)) {
1533 playerStatusPtr->FieldCharge += MUL_FIXED(NormalFrameTime,(TrickleCharge>>1));
1534 } else {
1535 playerStatusPtr->FieldCharge += MUL_FIXED(NormalFrameTime,TrickleCharge);
1536 }
1537
1538 if(playerStatusPtr->FieldCharge > PLAYERCLOAK_MAXENERGY) {
1539 playerStatusPtr->FieldCharge = PLAYERCLOAK_MAXENERGY;
1540 }
1541
1542 #if 0
1543 /* Infinite field charge? */
1544 playerStatusPtr->FieldCharge = PLAYERCLOAK_MAXENERGY;
1545 #endif
1546 }
1547 }
1548 #endif
1549
1550 if (ShowPredoStats) {
1551 /* for testing */
1552 PrintDebuggingText("Cloak on: %d \n",playerStatusPtr->cloakOn);
1553 PrintDebuggingText("Field Charge: %d \n",playerStatusPtr->FieldCharge);
1554 {
1555 int a;
1556 /* Speargun ammo count */
1557 a=SlotForThisWeapon(WEAPON_PRED_RIFLE);
1558 if (a!=-1) {
1559 PrintDebuggingText("Speargun Rounds: %d Clips: %d\n",(playerStatusPtr->WeaponSlot[a].PrimaryRoundsRemaining>>ONE_FIXED_SHIFT),playerStatusPtr->WeaponSlot[a].PrimaryMagazinesRemaining);
1560 } else {
1561 PrintDebuggingText("Speargun not possessed.\n");
1562 }
1563
1564 }
1565 PrintDebuggingText("Cloak given away: %d \n", playerStatusPtr->cloakPositionGivenAway);
1566 PrintDebuggingText("Cloak given away timer: %d \n", playerStatusPtr->cloakPositionGivenAwayTimer);
1567 PrintDebuggingText("Cloaking Effectiveness: %d \n", playerStatusPtr->CloakingEffectiveness);
1568 PrintDebuggingText("Gimme_Charge Calls: %d \n",GimmeChargeCalls);
1569 }
1570 #if 1
1571 /* now, if we are cloaked, lets see if we have given away our position...
1572 if we have already given away our position, we may do so again */
1573 if(playerStatusPtr->cloakOn)
1574 {
1575 PLAYER_WEAPON_DATA *weaponPtr;
1576 TEMPLATE_WEAPON_DATA *twPtr;
1577
1578 weaponPtr = &(playerStatusPtr->WeaponSlot[playerStatusPtr->SelectedWeaponSlot]);
1579 twPtr = &TemplateWeapon[weaponPtr->WeaponIDNumber];
1580
1581 /* weapon fire ?*/
1582 if(((PlayerStatusPtr->WeaponSlot[PlayerStatusPtr->SelectedWeaponSlot].CurrentState==WEAPONSTATE_FIRING_PRIMARY)&&(!twPtr->PrimaryIsMeleeWeapon))||
1583 ((PlayerStatusPtr->WeaponSlot[PlayerStatusPtr->SelectedWeaponSlot].CurrentState==WEAPONSTATE_FIRING_SECONDARY)&&(!twPtr->SecondaryIsMeleeWeapon)))
1584 {
1585 playerStatusPtr->cloakPositionGivenAway = 1;
1586 playerStatusPtr->cloakPositionGivenAwayTimer = PLAYERCLOAK_POSTIONGIVENAWAYTIME;
1587 }
1588 /* collision with npc ?*/
1589 {
1590 struct collisionreport *nextReport;
1591 LOCALASSERT(Player->ObStrategyBlock->DynPtr);
1592 nextReport = Player->ObStrategyBlock->DynPtr->CollisionReportPtr;
1593
1594 while(nextReport)
1595 {
1596 if(nextReport->ObstacleSBPtr)
1597 {
1598 if((nextReport->ObstacleSBPtr->I_SBtype==I_BehaviourAlien)||
1599 (nextReport->ObstacleSBPtr->I_SBtype==I_BehaviourMarine)||
1600 (nextReport->ObstacleSBPtr->I_SBtype==I_BehaviourXenoborg)||
1601 (nextReport->ObstacleSBPtr->I_SBtype==I_BehaviourPredatorAlien)||
1602 (nextReport->ObstacleSBPtr->I_SBtype==I_BehaviourQueenAlien)||
1603 (nextReport->ObstacleSBPtr->I_SBtype==I_BehaviourFaceHugger)||
1604 (nextReport->ObstacleSBPtr->I_SBtype==I_BehaviourSeal))
1605 {
1606 playerStatusPtr->cloakPositionGivenAway = 1;
1607 playerStatusPtr->cloakPositionGivenAwayTimer = PLAYERCLOAK_POSTIONGIVENAWAYTIME;
1608 break;
1609 }
1610 }
1611 nextReport = nextReport->NextCollisionReportPtr;
1612 }
1613 }
1614 }
1615 #endif
1616
1617 if (playerStatusPtr->cloakOn) {
1618 CurrentGameStats_CloakOn();
1619 }
1620 }
1621
GimmeCharge(void)1622 void GimmeCharge(void) {
1623
1624 PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
1625 LOCALASSERT(playerStatusPtr);
1626
1627 if(AvP.PlayerType!=I_Predator) return;
1628
1629 playerStatusPtr->FieldCharge = PLAYERCLOAK_MAXENERGY;
1630
1631 GimmeChargeCalls++;
1632
1633 }
1634
1635 #define AUTOSPOT_RANGE (1000)
1636
AlienPCIsCurrentlyVisible(int checktime,STRATEGYBLOCK * sbPtr)1637 int AlienPCIsCurrentlyVisible(int checktime,STRATEGYBLOCK *sbPtr) {
1638
1639 PLAYER_WEAPON_DATA *weaponPtr;
1640 int range;
1641 DYNAMICSBLOCK *dynPtr=(Player->ObStrategyBlock->DynPtr);
1642 PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
1643 LOCALASSERT(playerStatusPtr);
1644 /* sbPtr is the viewer. */
1645
1646 if (AvP.PlayerType!=I_Alien) {
1647 /* Just to be sure. */
1648 return(1);
1649 }
1650
1651 weaponPtr = &(playerStatusPtr->WeaponSlot[playerStatusPtr->SelectedWeaponSlot]);
1652
1653 /* Set a default range? */
1654 range=-1;
1655 /* Maybe we also need an autospot range. */
1656 if (sbPtr) {
1657 VECTORCH offset;
1658
1659 offset.vx=dynPtr->Position.vx-sbPtr->DynPtr->Position.vx;
1660 offset.vy=dynPtr->Position.vy-sbPtr->DynPtr->Position.vy;
1661 offset.vz=dynPtr->Position.vz-sbPtr->DynPtr->Position.vz;
1662
1663 range=Approximate3dMagnitude(&offset);
1664
1665 /* In fact, let's turn this around... */
1666
1667 if (playerStatusPtr->ShapeState==PMph_Standing) {
1668 if (range>=(CurrentLightAtPlayer)+AUTOSPOT_RANGE) {
1669 return(0);
1670 }
1671 } else {
1672 if (range>=(CurrentLightAtPlayer>>1)+AUTOSPOT_RANGE) {
1673 /* Half that range if crouching? */
1674 return(0);
1675 }
1676 }
1677
1678 /* I guess, if we're in _pitch_ darkness... see nothing outside that range? */
1679 if (CurrentLightAtPlayer<=2560) {
1680 if (playerStatusPtr->ShapeState==PMph_Standing) {
1681 if (range<=(CurrentLightAtPlayer)+AUTOSPOT_RANGE) {
1682 return(1);
1683 }
1684 } else {
1685 if (range<=(CurrentLightAtPlayer>>1)+AUTOSPOT_RANGE) {
1686 /* Half that range if crouching? */
1687 return(1);
1688 }
1689 }
1690 return(0);
1691 }
1692
1693 }
1694
1695
1696 if (playerStatusPtr->ShapeState==PMph_Standing) {
1697 /* Default to visible, unless stationary and in near darkness. */
1698 if (weaponPtr->CurrentState!=WEAPONSTATE_IDLE) {
1699 /* Don't even breathe. */
1700 return(1);
1701 }
1702 if ((dynPtr->Position.vx!=dynPtr->PrevPosition.vx)||
1703 (dynPtr->Position.vy!=dynPtr->PrevPosition.vy)||
1704 (dynPtr->Position.vz!=dynPtr->PrevPosition.vz)) {
1705 /* Stand perfectly still. */
1706 return(1);
1707 }
1708 if (checktime) {
1709 int chance;
1710 /* There is a chance of being seen regardless. */
1711 chance=32767; /* Lets say. */
1712 if ((FastRandom()&65535)<chance) {
1713 return(1);
1714 }
1715 }
1716 if (CurrentLightAtPlayer<5000) {
1717 return(0);
1718 }
1719 return(1);
1720 } else {
1721 int speed;
1722
1723 /* Crouching. Default to cloaked, unless they get 'lucky'. */
1724 if (weaponPtr->CurrentState==WEAPONSTATE_FIRING_PRIMARY) {
1725 /* Just don't claw. */
1726 return(1);
1727 }
1728
1729 if (CurrentLightAtPlayer>17000) {
1730 /* It's too bright, mere crouching won't save you. */
1731 return(1);
1732 }
1733 #if 0
1734 if ((dynPtr->Position.vx!=dynPtr->PrevPosition.vx)||
1735 (dynPtr->Position.vy!=dynPtr->PrevPosition.vy)||
1736 (dynPtr->Position.vz!=dynPtr->PrevPosition.vz)) {
1737 /* Stand perfectly still? */
1738 return(1);
1739 }
1740 #else
1741 speed=Approximate3dMagnitude(&Player->ObStrategyBlock->DynPtr->LinVelocity);
1742 /* Speed: < 5000 = standing. > 22000 = jumping.
1743 In practice, walk/fall = 18000 ish, jump = 27000 ish. */
1744 if (speed>22000) {
1745 /* Not getting away with that, mate. */
1746 return(1);
1747 }
1748 speed-=5000;
1749 if (speed<0) {
1750 speed=0;
1751 }
1752 /* Now should be 0->17000 ish. */
1753 speed<<=1;
1754 #endif
1755 if (checktime) {
1756 int chance;
1757 /* There is a chance of being seen. */
1758 chance=CurrentLightAtPlayer-5000;
1759 #if 1
1760 chance+=speed;
1761 #endif
1762 if ((FastRandom()&65535)<chance) {
1763 return(1);
1764 }
1765 }
1766 return(0);
1767 }
1768 }
1769
1770 #if 0
1771 static void HandlePredatorVisionModes(void)
1772 {
1773 extern unsigned char DebouncedKeyboardInput[];
1774
1775 if (DebouncedKeyboardInput[KEY_K])
1776 {
1777 ChangePredatorVisionMode();
1778 }
1779 }
1780 #endif
1781
ShowAdjacencies(void)1782 void ShowAdjacencies(void) {
1783
1784 int moduleCounter;
1785 AIMODULE **AdjModuleRefPtr;
1786 AIMODULE *thisModule;
1787 AIMODULE *ModuleListPointer;
1788
1789 /* Utility function... */
1790 PrintDebuggingText("Adjacencies FROM Player's Module (%s):\n",
1791 (*(playerPherModule->m_aimodule->m_module_ptrs))->name);
1792
1793 thisModule=playerPherModule->m_aimodule;
1794
1795 AdjModuleRefPtr = thisModule->m_link_ptrs;
1796
1797 if(AdjModuleRefPtr) /* check that there is a list of adjacent modules */
1798 {
1799 while(*AdjModuleRefPtr != 0)
1800 {
1801 /* Probably want some validity test for the link. */
1802 if (AIModuleIsPhysical(*AdjModuleRefPtr)) {
1803 /* Probably a valid link... */
1804 if (CheckAdjacencyValidity((*AdjModuleRefPtr),thisModule,0)) {
1805 PrintDebuggingText("--AI Module of %s, general.\n",(*((*AdjModuleRefPtr)->m_module_ptrs))->name);
1806 } else if (CheckAdjacencyValidity((*AdjModuleRefPtr),thisModule,1)) {
1807 PrintDebuggingText("--AI Module of %s, alien only.\n",(*((*AdjModuleRefPtr)->m_module_ptrs))->name);
1808 } else {
1809 PrintDebuggingText("--AI Module of %s, fails validity test!\n",(*((*AdjModuleRefPtr)->m_module_ptrs))->name);
1810 }
1811 }
1812 /* next adjacent module reference pointer */
1813 AdjModuleRefPtr++;
1814 }
1815 }
1816
1817 PrintDebuggingText("Adjacencies TO Player's Module:\n");
1818
1819 {
1820 extern AIMODULE *AIModuleArray;
1821
1822 ModuleListPointer = AIModuleArray;
1823 }
1824
1825 /* go through each aimodule in the environment */
1826 for(moduleCounter = 0; moduleCounter < AIModuleArraySize; moduleCounter++)
1827 {
1828
1829 /* get a pointer to the next current module */
1830 thisModule = &(ModuleListPointer[moduleCounter]);
1831 LOCALASSERT(thisModule);
1832
1833 AdjModuleRefPtr = thisModule->m_link_ptrs;
1834
1835 if(AdjModuleRefPtr) /* check that there is a list of adjacent modules */
1836 {
1837 while(*AdjModuleRefPtr != 0)
1838 {
1839 /* Probably want some validity test for the link. */
1840 if (AIModuleIsPhysical(*AdjModuleRefPtr)) {
1841 /* Is this the target? */
1842 if ((*AdjModuleRefPtr)==(playerPherModule->m_aimodule)) {
1843
1844 /* Probably a valid link... */
1845 if (CheckAdjacencyValidity((*AdjModuleRefPtr),thisModule,0)) {
1846 PrintDebuggingText("--AI Module of %s, general.\n",(*(thisModule->m_module_ptrs))->name);
1847 } else if (CheckAdjacencyValidity((*AdjModuleRefPtr),thisModule,1)) {
1848 PrintDebuggingText("--AI Module of %s, alien only.\n",(*(thisModule->m_module_ptrs))->name);
1849 } else {
1850 PrintDebuggingText("--AI Module of %s, fails validity test!\n",(*(thisModule->m_module_ptrs))->name);
1851 }
1852
1853 }
1854 }
1855 /* next adjacent module reference pointer */
1856 AdjModuleRefPtr++;
1857 }
1858 }
1859
1860 }
1861
1862 }
1863
1864
1865
1866 /*---------------------------**
1867 ** Loading and saving player **
1868 **---------------------------*/
1869
1870
1871 typedef struct player_save_block
1872 {
1873 SAVE_BLOCK_STRATEGY_HEADER header;
1874
1875 //behaviour block things
1876 PLAYER_WEAPON_DATA WeaponSlot[MAX_NO_OF_WEAPON_SLOTS];
1877
1878 enum WEAPON_SLOT SelectedWeaponSlot;
1879 enum WEAPON_SLOT SwapToWeaponSlot;
1880 enum WEAPON_SLOT PreviouslySelectedWeaponSlot;
1881
1882 int Health; /* in 16.16 */
1883 int Energy; /* in 16.16 */
1884 int Armour; /* in 16.16 */
1885
1886
1887 enum player_morph_state ShapeState; /* for controlling morphing */
1888
1889 signed int ForwardInertia;
1890 signed int StrafeInertia;
1891 signed int TurnInertia;
1892
1893 int ViewPanX; /* the looking up/down value that used to be in displayblock */
1894
1895 unsigned int securityClearances;
1896
1897 unsigned int IsAlive :1;
1898 unsigned int IsImmortal :1;
1899 unsigned int Mvt_AnalogueTurning :1;
1900 unsigned int Mvt_AnaloguePitching :1;
1901 unsigned int Absolute_Pitching :1;
1902 unsigned int SwappingIsDebounced :1;
1903 unsigned int DemoMode :1;
1904 unsigned int IHaveAPlacedAutogun :1;
1905 unsigned int IsMovingInWater :1;
1906 unsigned int JetpackEnabled :1;
1907 unsigned int GrapplingHookEnabled :1;
1908
1909 unsigned int MTrackerType;
1910
1911 unsigned int cloakOn :1;
1912 unsigned int cloakPositionGivenAway :1;
1913 int FieldCharge;
1914 int cloakPositionGivenAwayTimer;
1915 int PlasmaCasterCharge;
1916
1917 int CloakingEffectiveness;
1918
1919 ENCUMBERANCE_STATE Encumberance;
1920 int tauntTimer;
1921
1922 int incidentFlag;
1923 int incidentTimer;
1924 int fireTimer;
1925
1926 //some stuff for the weapon displayblock
1927 VECTORCH Weapon_World;
1928 EULER Weapon_Euler;
1929 MATRIXCH Weapon_Matrix;
1930
1931
1932 //and globals
1933 enum VISION_MODE_ID CurrentVisionMode;
1934 SMARTGUN_MODES SmartgunMode;
1935 GRENADE_LAUNCHER_DATA GrenadeLauncherData;
1936
1937
1938 //strategy block stuff
1939 DYNAMICSBLOCK dynamics;
1940 int integrity;
1941 DAMAGEBLOCK SBDamageBlock;
1942
1943 }PLAYER_SAVE_BLOCK;
1944
1945 //defines for load/save macros
1946 #define SAVELOAD_BLOCK block
1947 #define SAVELOAD_BEHAV playerStatusPtr
1948
1949
SaveStrategy_Player(STRATEGYBLOCK * sbPtr)1950 void SaveStrategy_Player(STRATEGYBLOCK* sbPtr)
1951 {
1952 PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (sbPtr->SBdataptr);
1953 PLAYER_SAVE_BLOCK* block;
1954 int i;
1955
1956 GET_STRATEGY_SAVE_BLOCK(block,sbPtr);
1957
1958
1959 COPYELEMENT_SAVE(SelectedWeaponSlot)
1960 COPYELEMENT_SAVE(SwapToWeaponSlot)
1961 COPYELEMENT_SAVE(PreviouslySelectedWeaponSlot)
1962
1963 COPYELEMENT_SAVE(Health) /* in 16.16 */
1964 COPYELEMENT_SAVE(Energy) /* in 16.16 */
1965 COPYELEMENT_SAVE(Armour) /* in 16.16 */
1966
1967
1968 COPYELEMENT_SAVE(ShapeState) /* for controlling morphing */
1969
1970 COPYELEMENT_SAVE(ForwardInertia)
1971 COPYELEMENT_SAVE(StrafeInertia)
1972 COPYELEMENT_SAVE(TurnInertia)
1973
1974 COPYELEMENT_SAVE(ViewPanX) /* the looking up/down value that used to be in displayblock */
1975
1976 COPYELEMENT_SAVE(securityClearances)
1977
1978 COPYELEMENT_SAVE(IsAlive)
1979 COPYELEMENT_SAVE(IsImmortal)
1980 COPYELEMENT_SAVE(Mvt_AnalogueTurning)
1981 COPYELEMENT_SAVE(Mvt_AnaloguePitching)
1982 COPYELEMENT_SAVE(Absolute_Pitching)
1983 COPYELEMENT_SAVE(SwappingIsDebounced)
1984 COPYELEMENT_SAVE(DemoMode)
1985 COPYELEMENT_SAVE(IHaveAPlacedAutogun)
1986 COPYELEMENT_SAVE(IsMovingInWater)
1987 COPYELEMENT_SAVE(JetpackEnabled)
1988 COPYELEMENT_SAVE(GrapplingHookEnabled )
1989
1990 COPYELEMENT_SAVE(MTrackerType)
1991
1992 COPYELEMENT_SAVE(cloakOn)
1993 COPYELEMENT_SAVE(cloakPositionGivenAway)
1994 COPYELEMENT_SAVE(FieldCharge)
1995 COPYELEMENT_SAVE(cloakPositionGivenAwayTimer)
1996 COPYELEMENT_SAVE(PlasmaCasterCharge)
1997 COPYELEMENT_SAVE(CloakingEffectiveness)
1998 COPYELEMENT_SAVE(Encumberance)
1999 COPYELEMENT_SAVE(tauntTimer)
2000
2001 COPYELEMENT_SAVE(incidentFlag)
2002 COPYELEMENT_SAVE(incidentTimer)
2003 COPYELEMENT_SAVE(fireTimer)
2004
2005 for(i=0;i<MAX_NO_OF_WEAPON_SLOTS;i++)
2006 {
2007 block->WeaponSlot[i].WeaponIDNumber = playerStatusPtr->WeaponSlot[i].WeaponIDNumber;
2008 block->WeaponSlot[i].CurrentState = playerStatusPtr->WeaponSlot[i].CurrentState;
2009 block->WeaponSlot[i].StateTimeOutCounter = playerStatusPtr->WeaponSlot[i].StateTimeOutCounter;
2010 block->WeaponSlot[i].PrimaryRoundsRemaining = playerStatusPtr->WeaponSlot[i].PrimaryRoundsRemaining;
2011 block->WeaponSlot[i].SecondaryRoundsRemaining = playerStatusPtr->WeaponSlot[i].SecondaryRoundsRemaining;
2012 block->WeaponSlot[i].PrimaryMagazinesRemaining = playerStatusPtr->WeaponSlot[i].PrimaryMagazinesRemaining;
2013 block->WeaponSlot[i].SecondaryMagazinesRemaining = playerStatusPtr->WeaponSlot[i].SecondaryMagazinesRemaining;
2014 block->WeaponSlot[i].PositionOffset = playerStatusPtr->WeaponSlot[i].PositionOffset;
2015 block->WeaponSlot[i].DirectionOffset = playerStatusPtr->WeaponSlot[i].DirectionOffset;
2016 block->WeaponSlot[i].Possessed = playerStatusPtr->WeaponSlot[i].Possessed;
2017 }
2018
2019 //some stuff for the weapon displayblock
2020 block->Weapon_World = PlayersWeapon.ObWorld;
2021 block->Weapon_Euler = PlayersWeapon.ObEuler;
2022 block->Weapon_Matrix = PlayersWeapon.ObMat;
2023
2024 //global
2025 block->CurrentVisionMode = CurrentVisionMode;
2026 block->SmartgunMode = SmartgunMode;
2027 block->GrenadeLauncherData = GrenadeLauncherData;
2028
2029 //strategy block stuff
2030
2031 block->integrity = sbPtr->integrity;
2032 block->SBDamageBlock = sbPtr->SBDamageBlock;
2033
2034 block->dynamics = *sbPtr->DynPtr;
2035 block->dynamics.CollisionReportPtr=0;
2036
2037 //save the weapon hierarchy
2038 SaveHierarchy(&PlayersWeaponHModelController);
2039
2040
2041 Save_SoundState(&playerStatusPtr->soundHandle);
2042 Save_SoundState(&playerStatusPtr->soundHandle3);
2043 Save_SoundState(&playerStatusPtr->soundHandle5);
2044 Save_SoundState(&playerStatusPtr->soundHandleForPredatorCloakDamaged);
2045 }
2046
LoadStrategy_Player(SAVE_BLOCK_STRATEGY_HEADER * header)2047 void LoadStrategy_Player(SAVE_BLOCK_STRATEGY_HEADER* header)
2048 {
2049 PLAYER_SAVE_BLOCK* block = (PLAYER_SAVE_BLOCK*) header;
2050 STRATEGYBLOCK* sbPtr = Player->ObStrategyBlock;
2051 PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (sbPtr->SBdataptr);
2052 int i;
2053
2054 if(block->header.size != sizeof(*block)) return;
2055
2056 COPY_NAME(sbPtr->SBname,header->SBname);
2057
2058
2059
2060 COPYELEMENT_LOAD(SelectedWeaponSlot)
2061 COPYELEMENT_LOAD(SwapToWeaponSlot)
2062 COPYELEMENT_LOAD(PreviouslySelectedWeaponSlot)
2063
2064 COPYELEMENT_LOAD(Health) /* in 16.16 */
2065 COPYELEMENT_LOAD(Energy) /* in 16.16 */
2066 COPYELEMENT_LOAD(Armour) /* in 16.16 */
2067
2068
2069 COPYELEMENT_LOAD(ShapeState) /* for controlling morphing */
2070
2071 COPYELEMENT_LOAD(ForwardInertia)
2072 COPYELEMENT_LOAD(StrafeInertia)
2073 COPYELEMENT_LOAD(TurnInertia)
2074
2075 COPYELEMENT_LOAD(ViewPanX) /* the looking up/down value that used to be in displayblock */
2076
2077 COPYELEMENT_LOAD(securityClearances)
2078
2079 COPYELEMENT_LOAD(IsAlive)
2080 COPYELEMENT_LOAD(IsImmortal)
2081 COPYELEMENT_LOAD(Mvt_AnalogueTurning)
2082 COPYELEMENT_LOAD(Mvt_AnaloguePitching)
2083 COPYELEMENT_LOAD(Absolute_Pitching)
2084 COPYELEMENT_LOAD(SwappingIsDebounced)
2085 COPYELEMENT_LOAD(DemoMode)
2086 COPYELEMENT_LOAD(IHaveAPlacedAutogun)
2087 COPYELEMENT_LOAD(IsMovingInWater)
2088 COPYELEMENT_LOAD(JetpackEnabled)
2089 COPYELEMENT_LOAD(GrapplingHookEnabled )
2090
2091 COPYELEMENT_LOAD(MTrackerType)
2092
2093 COPYELEMENT_LOAD(cloakOn)
2094 COPYELEMENT_LOAD(cloakPositionGivenAway)
2095 COPYELEMENT_LOAD(FieldCharge)
2096 COPYELEMENT_LOAD(cloakPositionGivenAwayTimer)
2097 COPYELEMENT_LOAD(PlasmaCasterCharge)
2098 COPYELEMENT_LOAD(CloakingEffectiveness)
2099 COPYELEMENT_LOAD(Encumberance)
2100 COPYELEMENT_LOAD(tauntTimer)
2101
2102 COPYELEMENT_LOAD(incidentFlag)
2103 COPYELEMENT_LOAD(incidentTimer)
2104 COPYELEMENT_LOAD(fireTimer)
2105
2106 // playerStatusPtr->SwapToWeaponSlot = block->SelectedWeaponSlot;
2107
2108
2109
2110 for(i=0;i<MAX_NO_OF_WEAPON_SLOTS;i++)
2111 {
2112 playerStatusPtr->WeaponSlot[i].WeaponIDNumber = block->WeaponSlot[i].WeaponIDNumber;
2113 playerStatusPtr->WeaponSlot[i].CurrentState = block->WeaponSlot[i].CurrentState;
2114 playerStatusPtr->WeaponSlot[i].StateTimeOutCounter = block->WeaponSlot[i].StateTimeOutCounter;
2115 playerStatusPtr->WeaponSlot[i].PrimaryRoundsRemaining = block->WeaponSlot[i].PrimaryRoundsRemaining;
2116 playerStatusPtr->WeaponSlot[i].SecondaryRoundsRemaining = block->WeaponSlot[i].SecondaryRoundsRemaining;
2117 playerStatusPtr->WeaponSlot[i].PrimaryMagazinesRemaining = block->WeaponSlot[i].PrimaryMagazinesRemaining;
2118 playerStatusPtr->WeaponSlot[i].SecondaryMagazinesRemaining = block->WeaponSlot[i].SecondaryMagazinesRemaining;
2119 playerStatusPtr->WeaponSlot[i].PositionOffset = block->WeaponSlot[i].PositionOffset;
2120 playerStatusPtr->WeaponSlot[i].DirectionOffset = block->WeaponSlot[i].DirectionOffset;
2121 playerStatusPtr->WeaponSlot[i].Possessed = block->WeaponSlot[i].Possessed;
2122 }
2123
2124 //some stuff for the weapon displayblock
2125 PlayersWeapon.ObWorld = block->Weapon_World;
2126 PlayersWeapon.ObEuler = block->Weapon_Euler;
2127 PlayersWeapon.ObMat = block->Weapon_Matrix;
2128
2129 //global
2130 CurrentVisionMode = block->CurrentVisionMode;
2131 SmartgunMode = block->SmartgunMode;
2132 GrenadeLauncherData = block->GrenadeLauncherData;
2133
2134 //strategy block stuff
2135 *sbPtr->DynPtr = block->dynamics;
2136 sbPtr->integrity = block->integrity;
2137 sbPtr->SBDamageBlock = block->SBDamageBlock;
2138
2139
2140
2141
2142 {
2143 extern VIEWDESCRIPTORBLOCK* Global_VDB_Ptr;
2144 sbPtr->containingModule = ModuleFromPosition(&(sbPtr->DynPtr->Position), (MODULE*)0);
2145 Global_VDB_Ptr->VDB_World = sbPtr->DynPtr->Position;
2146 }
2147
2148
2149 //load the weapon hierarchy
2150 {
2151 SAVE_BLOCK_HEADER* hier_header = GetNextBlockIfOfType(SaveBlock_Hierarchy);
2152 if(hier_header)
2153 {
2154 LoadHierarchy(hier_header,&PlayersWeaponHModelController);
2155 }
2156 else
2157 {
2158 Dispel_HModel(&PlayersWeaponHModelController);
2159 }
2160 }
2161
2162
2163 PlayersWeapon.HModelControlBlock = &PlayersWeaponHModelController;
2164
2165 //get the section data pointers
2166 PWMFSDP=GetThisSectionData(PlayersWeaponHModelController.section_data,"dum flash");
2167 if (PWMFSDP==NULL) {
2168 PWMFSDP=GetThisSectionData(PlayersWeaponHModelController.section_data,"Dum flash");
2169 }
2170
2171 Load_SoundState(&playerStatusPtr->soundHandle);
2172 Load_SoundState(&playerStatusPtr->soundHandle3);
2173 Load_SoundState(&playerStatusPtr->soundHandle5);
2174 Load_SoundState(&playerStatusPtr->soundHandleForPredatorCloakDamaged);
2175
2176 }
2177
2178