1 /*-------------- Patrick 15/10/96 ------------------
2 Source file for Player Movement ...
3 ----------------------------------------------------*/
4 #include "3dc.h"
5 #include "inline.h"
6 #include "module.h"
7
8 #include "gamedef.h"
9 #include "stratdef.h"
10 #include "dynblock.h"
11 #include "dynamics.h"
12 #include "gameplat.h"
13
14 #include "bh_types.h"
15
16 #define UseLocalAssert 1
17 #include "ourasert.h"
18 #include "comp_shp.h"
19
20 #include "pmove.h"
21 #include "usr_io.h"
22 #include "bh_far.h"
23 #include "triggers.h"
24 #include "pvisible.h"
25 #include "inventry.h"
26 #include "pfarlocs.h"
27 #include "weapons.h"
28 #include "pheromon.h"
29 #include "bh_pred.h"
30 #include "psnd.h"
31 #include "bh_weap.h"
32 #include "equipmnt.h"
33 #include "bh_agun.h"
34 #include "los.h"
35 #include "pldnet.h"
36 #include "bonusabilities.h"
37 #include "avp_menus.h"
38 #include "lighting.h"
39 #include "scream.h"
40 #include "player.h"
41 #include "avp_userprofile.h"
42
43
44 #define ALIEN_CONTACT_WEAPON 0
45 #if ALIEN_CONTACT_WEAPON
46 static void AlienContactWeapon(void);
47 #endif
48
49 #ifdef AVP_DEBUG_VERSION
50 #define FLY_MODE_CHEAT_ON 1
51 #else
52 #ifdef AVP_DEBUG_FOR_FOX
53 #define FLY_MODE_CHEAT_ON 1
54 #else
55 #define FLY_MODE_CHEAT_ON 0
56 #endif
57 #endif
58 //!(PREDATOR_DEMO||MARINE_DEMO||ALIEN_DEMO||DEATHMATCH_DEMO)
59 #if FLY_MODE_CHEAT_ON
60 extern unsigned char KeyboardInput[];
61 #endif
62 extern int DebouncedGotAnyKey;
63
64 /*KJL*****************************************************
65 * If the define below is set to non-zero then the player *
66 * movement values will be loaded in from movement.txt *
67 *****************************************************KJL*/
68 #define LOAD_IN_MOVEMENT_VALUES 0
69
70 #if LOAD_IN_MOVEMENT_VALUES
71
72 static int AlienForwardSpeed;
73 static int AlienStrafeSpeed;
74 static int AlienTurnSpeed;
75 static int AlienJumpSpeed;
76 static int PredatorForwardSpeed;
77 static int PredatorStrafeSpeed;
78 static int PredatorTurnSpeed;
79 static int PredatorJumpSpeed;
80 static int MarineForwardSpeed;
81 static int MarineStrafeSpeed;
82 static int MarineTurnSpeed;
83 static int MarineJumpSpeed;
84
85 static void LoadInMovementValues(void);
86 #endif
87
88 /* Globals */
89 int CrouchIsToggleKey;
90 char CrouchKeyDebounced;
91 int executeDemo;
92
93 /* Global Externs */
94 extern DISPLAYBLOCK* Player;
95 extern int NormalFrameTime;
96 extern int predHUDSoundHandle;
97 extern int predOVision_SoundHandle;
98 extern int TauntSoundPlayed;
99
100 extern unsigned char GotAnyKey;
101
102 static char FlyModeOn = 0;
103 #if FLY_MODE_CHEAT_ON
104 static char FlyModeDebounced = 0;
105 #endif
106
107 #if 0
108 static char BonusAbilityDebounced = 0;
109 static void MakePlayerLieDown(STRATEGYBLOCK* sbPtr);
110 #endif
111
112 extern int deathFadeLevel;
113 extern VIEWDESCRIPTORBLOCK *Global_VDB_Ptr;
114
115 // DISPLAYBLOCK *playerdb;
116
117 extern void DeInitialisePlayer(void);
118
119 /* some prototypes for this source file */
120 static void MakePlayerCrouch(STRATEGYBLOCK* sbPtr);
121 static void MaintainPlayerShape(STRATEGYBLOCK* sbPtr);
122 static void NetPlayerDeadProcessing(STRATEGYBLOCK* sbPtr);
123 static void CorpseMovement(STRATEGYBLOCK *sbPtr);
124
125 extern SECTION * GetNamedHierarchyFromLibrary(const char * rif_name, const char * hier_name);
126 extern void NewOnScreenMessage(unsigned char *messagePtr);
127 extern void RemoveAllThisPlayersDiscs(void);
128
129 int timeInContactWithFloor;
130
131 extern int weaponHandle;
132
133 extern int PlayerDamagedOverlayIntensity;
134
135
136 #define JETPACK_MAX_SPEED 10000
137 #define JETPACK_THRUST 40000
138
139 /*-----------------------------------------------------------
140 Initialise player movement data
141 -------------------------------------------------------------*/
InitPlayerMovementData(STRATEGYBLOCK * sbPtr)142 void InitPlayerMovementData(STRATEGYBLOCK* sbPtr)
143 {
144 InitPlayerGameInput(sbPtr);
145
146 /* set the player's morph control block and state*/
147 {
148 PLAYER_STATUS *playerStatusPtr = (PLAYER_STATUS *)(sbPtr->SBdataptr);
149 LOCALASSERT(playerStatusPtr);
150
151 playerStatusPtr->ShapeState = PMph_Standing;
152 playerStatusPtr->ViewPanX = 0;
153
154 playerStatusPtr->DemoMode = 0;
155 }
156
157 /* KJL 13:35:13 16/03/98 - make sure fly mode is off */
158 FlyModeOn = 0;
159
160 timeInContactWithFloor=(ONE_FIXED/10);
161
162 #if LOAD_IN_MOVEMENT_VALUES
163 LoadInMovementValues();
164 #endif
165
166 }
167
StartPlayerTaunt(void)168 void StartPlayerTaunt(void) {
169
170 PLAYER_STATUS *playerStatusPtr;
171
172 /* get the player status block ... */
173 playerStatusPtr = (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
174 GLOBALASSERT(playerStatusPtr);
175
176 if (playerStatusPtr->tauntTimer) {
177 return;
178 }
179
180 playerStatusPtr->tauntTimer=-1; /* Cue to start. */
181 TauntSoundPlayed=0;
182 }
183
184 /*-------------- Patrick 15/10/96 ----------------
185 --------------------------------------------------*/
PlayerBehaviour(STRATEGYBLOCK * sbPtr)186 void PlayerBehaviour(STRATEGYBLOCK* sbPtr)
187 {
188 PLAYER_STATUS *playerStatusPtr;
189
190 /* get the player status block ... */
191 playerStatusPtr = (PLAYER_STATUS *) (sbPtr->SBdataptr);
192 GLOBALASSERT(playerStatusPtr);
193
194 /* KJL 18:05:55 03/10/97 - is anybody there? */
195 if (playerStatusPtr->IsAlive)
196 {
197 if (playerStatusPtr->tauntTimer>0) {
198 playerStatusPtr->tauntTimer-=NormalFrameTime;
199 if (playerStatusPtr->tauntTimer<0) {
200 playerStatusPtr->tauntTimer=0;
201 }
202 } else if (AvP.Network==I_No_Network) {
203 /* *Might* need to monitor this... */
204 if (playerStatusPtr->tauntTimer==-1) {
205 /* Begin taunt. */
206 playerStatusPtr->tauntTimer=TAUNT_LENGTH;
207 } else if (playerStatusPtr->tauntTimer>0) {
208 playerStatusPtr->tauntTimer-=NormalFrameTime;
209 if (playerStatusPtr->tauntTimer<0) {
210 playerStatusPtr->tauntTimer=0;
211 }
212 }
213 }
214 ExecuteFreeMovement(sbPtr);
215 }
216 else CorpseMovement(sbPtr);
217
218 if(playerStatusPtr->IsAlive)
219 {
220 if ((sbPtr->containingModule)&&(!Observer)) {
221 /* Update pheromone system. If there's no containing module, *
222 * well... I sigh with despair at the system. But I cannot change it. */
223
224 switch(AvP.PlayerType)
225 {
226 case I_Marine:
227 AddMarinePheromones(sbPtr->containingModule->m_aimodule);
228 break;
229 case I_Predator:
230 /* Ah well, for the moment... */
231 AddMarinePheromones(sbPtr->containingModule->m_aimodule);
232 break;
233 case I_Alien:
234 break;
235 default:
236 GLOBALASSERT(0);
237 break;
238 }
239 }
240 }
241
242 }
243
244
245
246
247 /*------------------------Patrick 21/10/96------------------------
248 Newer cleaned up version, supporting new input functions
249 ----------------------------------------------------------------*/
250 #define ALIEN_MOVESCALE 18000
251 #define PREDATOR_MOVESCALE 16000
252 #define MARINE_MOVESCALE 15000
253
254 #define TURNSCALE 2000
255 #define JUMPVELOCITY 9000
256
257 #define FASTMOVESCALE 12000
258 #define SLOWMOVESCALE 8000
259 #define FASTTURNSCALE 2000
260 #define SLOWTURNSCALE 1000
261 #define FASTSTRAFESCALE 10000
262 #define SLOWSTRAFESCALE 6000
263
264 /* KJL 14:39:45 01/14/97 - Camera stuff */
265 #define PANRATESHIFT 6
266 #define TIMEBEFOREAUTOCENTREVIEW 16384
267
268 /* patrick 9/7/97: these are for testing AI pre-calculated values... */
269 #define PATTEST_EPS 0
270 #define PATTEST_AUXLOCS 0
271 #if (PATTEST_EPS&&PATTEST_AUXLOCS)
272 #error Cannot have both
273 #endif
274 #if PATTEST_EPS
275 void EpLocationTest(void);
276 #endif
277 #if PATTEST_AUXLOCS
278 void AuxLocationTest(void);
279 #endif
280
ExecuteFreeMovement(STRATEGYBLOCK * sbPtr)281 void ExecuteFreeMovement(STRATEGYBLOCK* sbPtr)
282 {
283 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
284
285 /* access the extra data hanging off the strategy block */
286 PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (sbPtr->SBdataptr);
287
288 if (dynPtr->IsInContactWithFloor) {
289 timeInContactWithFloor+=NormalFrameTime;
290 } else {
291 timeInContactWithFloor=0;
292 }
293
294 /*------------------------------------------------------
295 GAME INPUTS
296 Call the (platform dependant) game input reading fn.
297 ------------------------------------------------------*/
298 ReadPlayerGameInput(sbPtr);
299
300 /* KJL 11:07:42 10/09/98 - Bonus Abilities */
301 switch (AvP.PlayerType)
302 {
303 case I_Alien:
304 break;
305 #if 0
306 case I_Predator: /* KJL 11:08:19 10/09/98 - Grappling Hook */
307 {
308 if (playerStatusPtr->Mvt_InputRequests.Flags.Rqst_BonusAbility)
309 {
310 if(BonusAbilityDebounced)
311 {
312 ActivateGrapplingHook();
313 BonusAbilityDebounced = 0;
314 }
315 }
316 else BonusAbilityDebounced = 1;
317
318 break;
319 }
320 #endif
321 case I_Predator: /* KJL 11:08:19 10/09/98 - Cycle Vision Mode */
322 {
323 if (playerStatusPtr->Mvt_InputRequests.Flags.Rqst_CycleVisionMode)
324 {
325 ChangePredatorVisionMode();
326 }
327 if (playerStatusPtr->Mvt_InputRequests.Flags.Rqst_GrapplingHook &&
328 playerStatusPtr->GrapplingHookEnabled)
329 {
330 ActivateGrapplingHook();
331 }
332
333 break;
334 }
335 case I_Marine:
336 break;
337 }
338
339 if (playerStatusPtr->Mvt_InputRequests.Flags.Rqst_Operate)
340 OperateObjectInLineOfSight();
341
342 /* patrick 9/7/97: these are for testing AI pre-calculated values... */
343 #if PATTEST_EPS
344 EpLocationTest();
345 #endif
346 #if PATTEST_AUXLOCS
347 AuxLocationTest();
348 #endif
349
350
351 /* Alien damages things by being in contact with them */
352 #if ALIEN_CONTACT_WEAPON
353 if (AvP.PlayerType == I_Alien) AlienContactWeapon();
354 #endif
355
356 /*------------------------------------------------------
357 MOVEMENT
358
359 NB player must be standing for faster movement
360 ------------------------------------------------------*/
361
362 /* KJL 16:59:53 01/07/97 - New 3d strategy code */
363 {
364 int MaxSpeed;
365 int forwardSpeed;
366 int strafeSpeed;
367 int turnSpeed;
368 int jumpSpeed;
369
370 #if LOAD_IN_MOVEMENT_VALUES
371 switch (AvP.PlayerType)
372 {
373 case I_Alien:
374 forwardSpeed = AlienForwardSpeed;
375 strafeSpeed = AlienStrafeSpeed;
376 turnSpeed = AlienTurnSpeed;
377 jumpSpeed = AlienJumpSpeed;
378 break;
379
380 case I_Predator:
381 forwardSpeed = PredatorForwardSpeed;
382 strafeSpeed = PredatorStrafeSpeed;
383 turnSpeed = PredatorTurnSpeed;
384 jumpSpeed = PredatorJumpSpeed;
385 break;
386
387 case I_Marine:
388 forwardSpeed = MarineForwardSpeed;
389 strafeSpeed = MarineStrafeSpeed;
390 turnSpeed = MarineTurnSpeed;
391 jumpSpeed = MarineJumpSpeed;
392 break;
393 }
394 #else
395 switch (AvP.PlayerType)
396 {
397 case I_Alien:
398 forwardSpeed = ALIEN_MOVESCALE;
399 strafeSpeed = ALIEN_MOVESCALE;
400 turnSpeed = TURNSCALE;
401 jumpSpeed = JUMPVELOCITY;
402 break;
403 case I_Predator:
404 forwardSpeed = PREDATOR_MOVESCALE;
405 strafeSpeed = PREDATOR_MOVESCALE;
406 turnSpeed = TURNSCALE;
407 jumpSpeed = JUMPVELOCITY;
408 break;
409 case I_Marine:
410 forwardSpeed = MARINE_MOVESCALE;
411 strafeSpeed = MARINE_MOVESCALE;
412 turnSpeed = TURNSCALE;
413 jumpSpeed = JUMPVELOCITY;
414 break;
415 }
416 #endif
417
418 MaxSpeed=forwardSpeed;
419
420 if((playerStatusPtr->Mvt_InputRequests.Flags.Rqst_Strafe)&&(playerStatusPtr->Mvt_SideStepIncrement==0))
421 {
422 strafeSpeed = MUL_FIXED(strafeSpeed,playerStatusPtr->Mvt_TurnIncrement);
423 }
424 else
425 {
426 strafeSpeed = MUL_FIXED(strafeSpeed,playerStatusPtr->Mvt_SideStepIncrement);
427 }
428 forwardSpeed = MUL_FIXED(forwardSpeed,playerStatusPtr->Mvt_MotionIncrement);
429 turnSpeed = MUL_FIXED(turnSpeed,playerStatusPtr->Mvt_TurnIncrement);
430
431 if (MIRROR_CHEATMODE)
432 {
433 turnSpeed = -turnSpeed;
434 strafeSpeed = -strafeSpeed;
435 }
436
437 {
438 extern int CameraZoomLevel;
439 if(CameraZoomLevel)
440 {
441 turnSpeed >>= CameraZoomLevel;
442 playerStatusPtr->Mvt_PitchIncrement >>= CameraZoomLevel;
443 }
444 }
445
446 if( ((AvP.PlayerType == I_Alien) || (playerStatusPtr->ShapeState == PMph_Standing))
447 && (playerStatusPtr->Mvt_InputRequests.Flags.Rqst_Faster) && (playerStatusPtr->Encumberance.CanRun) )
448 {
449 /* Test - half backward speed for predators */
450 if (AvP.PlayerType==I_Predator) {
451 if (playerStatusPtr->Mvt_MotionIncrement<0) {
452 forwardSpeed = (forwardSpeed)/2;
453 }
454 }
455 }
456 else
457 {
458 /* walk = half speed */
459 strafeSpeed = (strafeSpeed)/2;
460 forwardSpeed = (forwardSpeed)/2;
461 turnSpeed = (turnSpeed)/2;
462 }
463
464 /* Marker */
465
466 strafeSpeed=MUL_FIXED(strafeSpeed,playerStatusPtr->Encumberance.MovementMultiple);
467 forwardSpeed=MUL_FIXED(forwardSpeed,playerStatusPtr->Encumberance.MovementMultiple);
468 turnSpeed=MUL_FIXED(turnSpeed,playerStatusPtr->Encumberance.TurningMultiple);
469 jumpSpeed=MUL_FIXED(jumpSpeed,playerStatusPtr->Encumberance.JumpingMultiple);
470
471 /* KJL 17:45:03 9/9/97 - inertia means it's difficult to stop */
472 if (forwardSpeed*playerStatusPtr->ForwardInertia<0) playerStatusPtr->ForwardInertia = 0;
473 if (strafeSpeed*playerStatusPtr->StrafeInertia<0) playerStatusPtr->StrafeInertia = 0;
474
475 if (!forwardSpeed)
476 {
477 int deltaForward = (FASTMOVESCALE*NormalFrameTime)>>14;
478 if (playerStatusPtr->ForwardInertia>0)
479 {
480 forwardSpeed = playerStatusPtr->ForwardInertia - deltaForward;
481 if (forwardSpeed<0) forwardSpeed=0;
482 }
483 else if (playerStatusPtr->ForwardInertia<0)
484 {
485 forwardSpeed = playerStatusPtr->ForwardInertia + deltaForward;
486 if (forwardSpeed>0) forwardSpeed=0;
487 }
488 }
489 else
490 {
491 int deltaForward = MUL_FIXED(forwardSpeed*4,NormalFrameTime);
492 {
493 int a = playerStatusPtr->ForwardInertia + deltaForward;
494 if (forwardSpeed>0)
495 {
496 if (a<forwardSpeed) forwardSpeed = a;
497 }
498 else
499 {
500 if (a>forwardSpeed) forwardSpeed = a;
501 }
502 }
503 }
504
505 if (!strafeSpeed)
506 {
507 int deltaStrafe = (FASTSTRAFESCALE*NormalFrameTime)>>14;
508 if (playerStatusPtr->StrafeInertia>0)
509 {
510 strafeSpeed = playerStatusPtr->StrafeInertia - deltaStrafe;
511 if (strafeSpeed<0) strafeSpeed=0;
512 }
513 else if (playerStatusPtr->StrafeInertia<0)
514 {
515 strafeSpeed = playerStatusPtr->StrafeInertia + deltaStrafe;
516 if (strafeSpeed>0) strafeSpeed=0;
517 }
518 }
519 else
520 {
521 int deltaForward = MUL_FIXED(strafeSpeed*4,NormalFrameTime);
522 {
523 int a = playerStatusPtr->StrafeInertia + deltaForward;
524 if (strafeSpeed>0)
525 {
526 if (a<strafeSpeed) strafeSpeed = a;
527 }
528 else
529 {
530 if (a>strafeSpeed) strafeSpeed = a;
531 }
532 }
533 }
534
535 /* inertia on turning - currently off */
536 #if 0
537 if(!turnSpeed)
538 {
539 int deltaTurn = (FASTTURNSCALE*NormalFrameTime)>>15;
540 if (playerStatusPtr->TurnInertia>0)
541 {
542 turnSpeed = playerStatusPtr->TurnInertia - deltaTurn;
543 if (turnSpeed<0) turnSpeed=0;
544 }
545 else if (playerStatusPtr->TurnInertia<0)
546 {
547 turnSpeed = playerStatusPtr->TurnInertia + deltaTurn;
548 if (turnSpeed>0) turnSpeed=0;
549 }
550 }
551 #endif
552
553 /* Hold it! Correct forwardSpeed vs. strafeSpeed? */
554
555 #if 0
556 {
557 int mag,angle;
558
559 mag=(forwardSpeed*forwardSpeed)+(strafeSpeed*strafeSpeed);
560 if (mag>(MaxSpeed*MaxSpeed)) {
561
562 angle=ArcTan(forwardSpeed,strafeSpeed);
563
564 forwardSpeed=MUL_FIXED(GetSin(angle),MaxSpeed);
565 strafeSpeed=MUL_FIXED(GetCos(angle),MaxSpeed);
566
567 }
568 }
569 #endif
570
571 if (playerStatusPtr->Mvt_InputRequests.Flags.Rqst_Jetpack &&
572 playerStatusPtr->JetpackEnabled)
573 {
574 if (dynPtr->LinImpulse.vy>-JETPACK_MAX_SPEED)
575 {
576 dynPtr->LinImpulse.vy-=MUL_FIXED(JETPACK_THRUST,NormalFrameTime);
577 }
578 AddLightingEffectToObject(Player,LFX_OBJECTONFIRE);
579 /* Sound handling. */
580 if (playerStatusPtr->soundHandle5==SOUND_NOACTIVEINDEX) {
581 Sound_Play(SID_ED_JETPACK_START,"h");
582 Sound_Play(SID_ED_JETPACK_MID,"el",&playerStatusPtr->soundHandle5);
583 }
584
585 } else {
586 /* Sound handling. */
587 if (playerStatusPtr->soundHandle5!=SOUND_NOACTIVEINDEX) {
588 Sound_Play(SID_ED_JETPACK_END,"h");
589 Sound_Stop(playerStatusPtr->soundHandle5);
590 }
591 }
592
593 #if FLY_MODE_CHEAT_ON
594 dynPtr->GravityOn=1;
595 if (KeyboardInput[KEY_F6]&&(!(playerStatusPtr->DemoMode)))
596 {
597 if(FlyModeDebounced)
598 {
599 FlyModeOn = !FlyModeOn;
600 FlyModeDebounced = 0;
601 }
602 }
603 else FlyModeDebounced = 1;
604
605 if(FlyModeOn)
606 {
607 dynPtr->LinVelocity.vx = 0;
608 dynPtr->LinVelocity.vy = 0;
609 dynPtr->LinVelocity.vz = forwardSpeed;
610 // dynPtr->IsNetGhost=1;
611 if(playerStatusPtr->Mvt_InputRequests.Flags.Rqst_Strafe)
612 {
613 dynPtr->LinVelocity.vx = strafeSpeed;
614 }
615 else if((playerStatusPtr->Mvt_InputRequests.Flags.Rqst_SideStepLeft)
616 || (playerStatusPtr->Mvt_InputRequests.Flags.Rqst_SideStepRight))
617 {
618 dynPtr->LinVelocity.vx = strafeSpeed;
619 }
620
621 /* rotate LinVelocity along camera view */
622 {
623 MATRIXCH mat = Global_VDB_Ptr->VDB_Mat;
624 TransposeMatrixCH(&mat);
625 RotateVector(&dynPtr->LinVelocity,&mat);
626 }
627 dynPtr->GravityOn=0;
628 dynPtr->LinImpulse.vx=0;
629 dynPtr->LinImpulse.vy=0;
630 dynPtr->LinImpulse.vz=0;
631 }
632 else
633 #endif
634 /* KJL 12:28:48 14/04/98 - if we're not in contact with the floor, but we've hit
635 something, set our velocity to zero (otherwise leave it alone) */
636 if(!dynPtr->IsInContactWithFloor)
637 {
638 if (playerStatusPtr->Mvt_InputRequests.Flags.Rqst_Jetpack &&
639 playerStatusPtr->JetpackEnabled)
640 {
641 dynPtr->LinVelocity.vx = 0;
642 dynPtr->LinVelocity.vy = 0;
643 if (forwardSpeed>0)
644 {
645 dynPtr->LinVelocity.vz = forwardSpeed/2;
646 }
647 else
648 {
649 dynPtr->LinVelocity.vz = forwardSpeed/4;
650 }
651 // dynPtr->IsNetGhost=1;
652 if(playerStatusPtr->Mvt_InputRequests.Flags.Rqst_Strafe)
653 {
654 dynPtr->LinVelocity.vx = strafeSpeed/4;
655 }
656 else if((playerStatusPtr->Mvt_InputRequests.Flags.Rqst_SideStepLeft)
657 || (playerStatusPtr->Mvt_InputRequests.Flags.Rqst_SideStepRight))
658 {
659 dynPtr->LinVelocity.vx = strafeSpeed/4;
660 }
661
662 /* rotate LinVelocity into world space */
663 RotateVector(&dynPtr->LinVelocity,&dynPtr->OrientMat);
664 }
665 else if (dynPtr->CollisionReportPtr)
666 {
667 dynPtr->LinVelocity.vx = 0;
668 dynPtr->LinVelocity.vy = 0;
669 dynPtr->LinVelocity.vz = forwardSpeed/8;
670 /* rotate LinVelocity into world space */
671 RotateVector(&dynPtr->LinVelocity,&dynPtr->OrientMat);
672
673 }
674 }
675 /* this bit sets the velocity: don't do it in demo mode, though
676 as we set our own velocity... */
677 else if((dynPtr->IsInContactWithFloor)&&(!(playerStatusPtr->DemoMode)))
678 {
679 dynPtr->LinVelocity.vx = 0;
680 dynPtr->LinVelocity.vy = 0;
681 dynPtr->LinVelocity.vz = forwardSpeed;
682
683 if(playerStatusPtr->Mvt_InputRequests.Flags.Rqst_Strafe)
684 {
685 dynPtr->LinVelocity.vx = strafeSpeed;
686 }
687 else if((playerStatusPtr->Mvt_InputRequests.Flags.Rqst_SideStepLeft)
688 || (playerStatusPtr->Mvt_InputRequests.Flags.Rqst_SideStepRight))
689 {
690 dynPtr->LinVelocity.vx = strafeSpeed;
691 }
692
693 if(playerStatusPtr->Mvt_InputRequests.Flags.Rqst_Jump)
694 {
695 COLLISIONREPORT *reportPtr = Player->ObStrategyBlock->DynPtr->CollisionReportPtr;
696 int notTooSteep = 0;
697
698 while (reportPtr) /* while there is a valid report */
699 {
700 int dot = DotProduct(&(reportPtr->ObstacleNormal),&(dynPtr->GravityDirection));
701
702 if (dot<-60000)
703 {
704 notTooSteep = 1;
705 break;
706 }
707 /* skip to next report */
708 reportPtr = reportPtr->NextCollisionReportPtr;
709 }
710
711 if (notTooSteep)
712 {
713 /* alien can jump in the direction it's looking */
714 if (AvP.PlayerType == I_Alien)
715 {
716 VECTORCH viewDir;
717
718 viewDir.vx = Global_VDB_Ptr->VDB_Mat.mat13;
719 viewDir.vy = Global_VDB_Ptr->VDB_Mat.mat23;
720 viewDir.vz = Global_VDB_Ptr->VDB_Mat.mat33;
721 if ((playerStatusPtr->ShapeState == PMph_Crouching) && (DotProduct(&viewDir,&dynPtr->GravityDirection)<-32768))
722 {
723 dynPtr->LinImpulse.vx += MUL_FIXED(viewDir.vx,jumpSpeed*3);
724 dynPtr->LinImpulse.vy += MUL_FIXED(viewDir.vy,jumpSpeed*3);
725 dynPtr->LinImpulse.vz += MUL_FIXED(viewDir.vz,jumpSpeed*3);
726 }
727 else
728 {
729 dynPtr->LinImpulse.vx -= MUL_FIXED(dynPtr->GravityDirection.vx,jumpSpeed);
730 dynPtr->LinImpulse.vy -= MUL_FIXED(dynPtr->GravityDirection.vy,jumpSpeed);
731 dynPtr->LinImpulse.vz -= MUL_FIXED(dynPtr->GravityDirection.vz,jumpSpeed);
732 dynPtr->LinVelocity.vz += jumpSpeed;
733 }
734 dynPtr->TimeNotInContactWithFloor = -1;
735 }
736 else
737 {
738 dynPtr->LinImpulse.vx -= MUL_FIXED(dynPtr->GravityDirection.vx,jumpSpeed);
739 dynPtr->LinImpulse.vy -= MUL_FIXED(dynPtr->GravityDirection.vy,jumpSpeed);
740 dynPtr->LinImpulse.vz -= MUL_FIXED(dynPtr->GravityDirection.vz,jumpSpeed);
741 dynPtr->TimeNotInContactWithFloor = 0;
742 }
743
744 switch(AvP.PlayerType)
745 {
746 case I_Marine:
747 {
748 #if 0
749 if (playerStatusPtr->soundHandle==SOUND_NOACTIVEINDEX) {
750 int rand=(FastRandom()%4);
751
752 switch (rand) {
753 case 0:
754 Sound_Play(SID_MARINE_JUMP_START,"he",&playerStatusPtr->soundHandle);
755 break;
756 case 1:
757 Sound_Play(SID_MARINE_JUMP_START_2,"he",&playerStatusPtr->soundHandle);
758 break;
759 case 2:
760 Sound_Play(SID_MARINE_JUMP_START_3,"he",&playerStatusPtr->soundHandle);
761 break;
762 default:
763 Sound_Play(SID_MARINE_JUMP_START_4,"he",&playerStatusPtr->soundHandle);
764 break;
765 }
766 }
767 #else
768 if (playerStatusPtr->soundHandle==SOUND_NOACTIVEINDEX) {
769 PlayMarineScream(0,SC_Jump,0,&playerStatusPtr->soundHandle,NULL);
770 if(AvP.Network!=I_No_Network) netGameData.myLastScream=SC_Jump;
771 }
772 #endif
773 break;
774 }
775 case I_Alien:
776 break;
777 case I_Predator:
778 {
779 #if 0
780 if (playerStatusPtr->soundHandle==SOUND_NOACTIVEINDEX) {
781 int rand=(FastRandom()%3);
782
783 switch (rand) {
784 case 0:
785 Sound_Play(SID_PRED_JUMP_START_1,"he",&playerStatusPtr->soundHandle);
786 break;
787 case 1:
788 Sound_Play(SID_PRED_JUMP_START_2,"he",&playerStatusPtr->soundHandle);
789 break;
790 default:
791 Sound_Play(SID_PRED_JUMP_START_3,"he",&playerStatusPtr->soundHandle);
792 break;
793 }
794 }
795 #else
796 if (playerStatusPtr->soundHandle==SOUND_NOACTIVEINDEX) {
797 PlayPredatorSound(0,PSC_Jump,0,&playerStatusPtr->soundHandle,NULL);
798 if(AvP.Network!=I_No_Network) netGameData.myLastScream=PSC_Jump;
799 }
800 #endif
801 break;
802 }
803 default:
804 break;
805
806 }
807 }
808 }
809 /* rotate LinVelocity into world space */
810 RotateVector(&dynPtr->LinVelocity,&dynPtr->OrientMat);
811 }
812
813 /* zero angular velocity */
814 dynPtr->AngVelocity.EulerX = 0;
815 dynPtr->AngVelocity.EulerZ = 0;
816
817 if(playerStatusPtr->Mvt_InputRequests.Flags.Rqst_Strafe)
818 {
819 dynPtr->AngVelocity.EulerY = 0;
820 }
821 else
822 {
823 dynPtr->AngVelocity.EulerY = turnSpeed;
824 }
825
826 playerStatusPtr->ForwardInertia = forwardSpeed;
827 playerStatusPtr->StrafeInertia = strafeSpeed;
828 playerStatusPtr->TurnInertia = turnSpeed;
829 }
830 /*KJL****************************************************************************************
831 * The player's AngVelocity as set by the above code is only valid in the player's object *
832 * space, and so has to be rotated into world space. So aliens can walk on the ceiling, etc. *
833 ****************************************************************************************KJL*/
834 if (dynPtr->AngVelocity.EulerY)
835 {
836 MATRIXCH mat;
837
838 int angle = MUL_FIXED(NormalFrameTime,dynPtr->AngVelocity.EulerY)&4095;
839 int cos = GetCos(angle);
840 int sin = GetSin(angle);
841 mat.mat11 = cos;
842 mat.mat12 = 0;
843 mat.mat13 = -sin;
844 mat.mat21 = 0;
845 mat.mat22 = 65536;
846 mat.mat23 = 0;
847 mat.mat31 = sin;
848 mat.mat32 = 0;
849 mat.mat33 = cos;
850
851 MatrixMultiply(&dynPtr->OrientMat,&mat,&dynPtr->OrientMat);
852 MatrixToEuler(&dynPtr->OrientMat, &dynPtr->OrientEuler);
853
854 }
855 /*------------------------------------------------------
856 CROUCHING, LYING DOWN, ETC.
857 ------------------------------------------------------*/
858 MaintainPlayerShape(sbPtr);
859
860 /* Alien's wall-crawling abilities */
861 if (AvP.PlayerType == I_Alien)
862 {
863 /* let alien walk on walls & ceiling */
864 if ( (playerStatusPtr->ShapeState == PMph_Crouching)
865 &&(!dynPtr->RequestsToStandUp) )
866 {
867 dynPtr->UseStandardGravity=0;
868 }
869 else
870 {
871 dynPtr->UseStandardGravity=1;
872 }
873 }
874
875
876
877
878 /*------------------------------------------------------
879 WEAPON FIRING
880 Kevin: The player input functions now interface directly
881 with the weapons state machine. I hope.
882 ------------------------------------------------------*/
883
884 /*------------------------------------------------------
885 CAMERA Controls
886 ------------------------------------------------------*/
887
888 /* If AbsolutePitch is set, view angle comes direct from Mvt_PitchIncrement,
889 which takes values -65536 to +65536. */
890
891
892 if (playerStatusPtr->Absolute_Pitching)
893 {
894 playerStatusPtr->ViewPanX = MUL_FIXED(playerStatusPtr->Mvt_PitchIncrement,1024-128);
895 playerStatusPtr->ViewPanX &= wrap360;
896 }
897 else
898 {
899 static int timeBeenContinuouslyMoving=0;
900 int AllowedLookDownAngle;
901 int AllowedLookUpAngle;
902
903 if (AvP.PlayerType==I_Alien)
904 {
905 AllowedLookUpAngle = 0;
906 AllowedLookDownAngle = 2048;
907 }
908 else
909 {
910 AllowedLookUpAngle = 128;
911 AllowedLookDownAngle = 2048-128;
912 }
913
914 if (!ControlMethods.AutoCentreOnMovement)
915 {
916 timeBeenContinuouslyMoving = 0;
917 }
918
919 if (playerStatusPtr->Mvt_MotionIncrement == 0)
920 {
921 timeBeenContinuouslyMoving=0;
922 }
923 else
924 {
925 if (timeBeenContinuouslyMoving>TIMEBEFOREAUTOCENTREVIEW
926 && !playerStatusPtr->Mvt_InputRequests.Flags.Rqst_LookUp
927 && !playerStatusPtr->Mvt_InputRequests.Flags.Rqst_LookDown)
928 {
929 playerStatusPtr->Mvt_InputRequests.Flags.Rqst_CentreView =1;
930 }
931 else
932 {
933 timeBeenContinuouslyMoving+=NormalFrameTime;
934 }
935 }
936
937 if(playerStatusPtr->Mvt_InputRequests.Flags.Rqst_LookUp)
938 {
939 playerStatusPtr->ViewPanX += 1024;
940 playerStatusPtr->ViewPanX &= wrap360;
941
942 playerStatusPtr->ViewPanX += MUL_FIXED
943 (
944 playerStatusPtr->Mvt_PitchIncrement,
945 NormalFrameTime>>PANRATESHIFT
946 );
947
948 if (playerStatusPtr->ViewPanX < AllowedLookUpAngle) playerStatusPtr->ViewPanX=AllowedLookUpAngle;
949
950 playerStatusPtr->ViewPanX -= 1024;
951 playerStatusPtr->ViewPanX &= wrap360;
952 }
953 else if(playerStatusPtr->Mvt_InputRequests.Flags.Rqst_LookDown)
954 {
955 playerStatusPtr->ViewPanX += 1024;
956 playerStatusPtr->ViewPanX &= wrap360;
957
958 playerStatusPtr->ViewPanX += MUL_FIXED
959 (
960 playerStatusPtr->Mvt_PitchIncrement,
961 NormalFrameTime>>PANRATESHIFT
962 );
963
964 if (playerStatusPtr->ViewPanX > AllowedLookDownAngle) playerStatusPtr->ViewPanX=AllowedLookDownAngle;
965
966 playerStatusPtr->ViewPanX -= 1024;
967 playerStatusPtr->ViewPanX &= wrap360;
968 }
969 if(playerStatusPtr->Mvt_InputRequests.Flags.Rqst_CentreView)
970 {
971 playerStatusPtr->ViewPanX += 1024;
972 playerStatusPtr->ViewPanX &= wrap360;
973
974 if (playerStatusPtr->ViewPanX > 1024)
975 {
976 playerStatusPtr->ViewPanX -= (NormalFrameTime>>PANRATESHIFT)*2;
977 if (playerStatusPtr->ViewPanX < 1024) playerStatusPtr->ViewPanX=1024;
978 }
979 else if (playerStatusPtr->ViewPanX < 1024)
980 {
981 playerStatusPtr->ViewPanX += (NormalFrameTime>>PANRATESHIFT)*2;
982 if (playerStatusPtr->ViewPanX > 1024) playerStatusPtr->ViewPanX=1024;
983 }
984
985 playerStatusPtr->ViewPanX -= 1024;
986 playerStatusPtr->ViewPanX &= wrap360;
987 }
988 }
989
990 HandleGrapplingHookForces();
991 }
992
993
994 /*------------------------------------------------------
995 Crouch and Lie down support fns.
996 ------------------------------------------------------*/
997
MaintainPlayerShape(STRATEGYBLOCK * sbPtr)998 static void MaintainPlayerShape(STRATEGYBLOCK* sbPtr)
999 {
1000 PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (sbPtr->SBdataptr);
1001
1002 /* maintain play morphing state */
1003 switch (playerStatusPtr->ShapeState)
1004 {
1005 case(PMph_Standing):
1006 {
1007 /* if we're standing, check inputs for a request to
1008 crouch or lie down */
1009 if (playerStatusPtr->Encumberance.CanCrouch)
1010 {
1011 if(playerStatusPtr->Mvt_InputRequests.Flags.Rqst_Crouch)
1012 {
1013 if (CrouchKeyDebounced)
1014 {
1015 MakePlayerCrouch(sbPtr);
1016 CrouchKeyDebounced = 0;
1017 }
1018 }
1019 else
1020 {
1021 CrouchKeyDebounced = 1;
1022 }
1023
1024 }
1025
1026
1027 sbPtr->DynPtr->RequestsToStandUp=0;
1028
1029 break;
1030 }
1031 case(PMph_Crouching):
1032 {
1033 /* if we're crouching, then check inputs for crouch request.
1034 if there isn't one, stand up again */
1035 if(sbPtr->DynPtr->RequestsToStandUp)
1036 {
1037 //currently crouching , but have had a request to stand up.
1038 //cancel request if the crouch key is pressed again
1039 if (playerStatusPtr->Encumberance.CanCrouch)
1040 {
1041 if(playerStatusPtr->Mvt_InputRequests.Flags.Rqst_Crouch)
1042 {
1043 if (CrouchKeyDebounced)
1044 {
1045 sbPtr->DynPtr->RequestsToStandUp = 0;
1046 CrouchKeyDebounced = 0;
1047 }
1048 }
1049 else
1050 {
1051 CrouchKeyDebounced = 1;
1052 }
1053
1054 }
1055 }
1056 else
1057 {
1058 if (!(playerStatusPtr->Encumberance.CanCrouch))
1059 {
1060 sbPtr->DynPtr->RequestsToStandUp=1;
1061 }
1062
1063 if (CrouchIsToggleKey)
1064 {
1065 if(playerStatusPtr->Mvt_InputRequests.Flags.Rqst_Crouch)
1066 {
1067 if (CrouchKeyDebounced)
1068 {
1069 sbPtr->DynPtr->RequestsToStandUp=1;
1070 CrouchKeyDebounced = 0;
1071 }
1072 }
1073 else
1074 {
1075 CrouchKeyDebounced = 1;
1076 }
1077 }
1078 else if(!(playerStatusPtr->Mvt_InputRequests.Flags.Rqst_Crouch))
1079 {
1080 sbPtr->DynPtr->RequestsToStandUp=1;
1081 }
1082 }
1083 break;
1084 }
1085 case(PMph_Lying):
1086 {
1087 /* if we're lying, then check inputs for lie request.
1088 if there isn't one, stand up again */
1089 break;
1090 }
1091 default:
1092 {
1093 /* should never get here */
1094 GLOBALASSERT(1==0);
1095 }
1096
1097 }
1098
1099 }
1100
MakePlayerCrouch(STRATEGYBLOCK * sbPtr)1101 static void MakePlayerCrouch(STRATEGYBLOCK* sbPtr)
1102 {
1103 PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (sbPtr->SBdataptr);
1104
1105 /* set player state */
1106 playerStatusPtr->ShapeState = PMph_Crouching;
1107
1108 return;
1109 }
1110
1111 #if 0
1112 static void MakePlayerLieDown(STRATEGYBLOCK* sbPtr)
1113 {
1114 PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (sbPtr->SBdataptr);
1115
1116
1117 /* set player state */
1118 playerStatusPtr->ShapeState = PMph_Lying;
1119
1120 return;
1121 }
1122 #endif
1123
1124
1125 int deathFadeLevel;
1126
CorpseMovement(STRATEGYBLOCK * sbPtr)1127 static void CorpseMovement(STRATEGYBLOCK *sbPtr)
1128 {
1129 extern int RealFrameTime;
1130
1131 /* only fade non-net game */
1132 if(AvP.Network == I_No_Network)
1133 {
1134 if(deathFadeLevel>0)
1135 {
1136 /* fade screen to black */
1137 //SetPaletteFadeLevel(deathFadeLevel);
1138 deathFadeLevel-= RealFrameTime/4;
1139 if (deathFadeLevel<0) deathFadeLevel = 0;
1140
1141 }
1142 else
1143 {
1144 deathFadeLevel = 0;
1145 /* KJL 15:44:10 03/11/97 - game over, quit main loop */
1146 /* restart level instead -Richard*/
1147 if (DebouncedGotAnyKey)
1148 {
1149 AvP.RestartLevel = 1;
1150 }
1151 }
1152 }
1153 else
1154 {
1155 if(deathFadeLevel>0)
1156 {
1157 deathFadeLevel-= RealFrameTime/2;
1158 }
1159 else
1160 {
1161 deathFadeLevel = 0;
1162 NetPlayerDeadProcessing(sbPtr);
1163 }
1164 }
1165 }
1166
1167 /*-------------------Patrick 14/4/97--------------------
1168 This function does necessary processing for a dead
1169 network player...
1170 ------------------------------------------------------*/
NetPlayerDeadProcessing(STRATEGYBLOCK * sbPtr)1171 static void NetPlayerDeadProcessing(STRATEGYBLOCK *sbPtr)
1172 {
1173 PLAYER_STATUS *psPtr= (PLAYER_STATUS *) (sbPtr->SBdataptr);
1174
1175 /* call the read input function so that we can still respawn/quit, etc */
1176 ReadPlayerGameInput(sbPtr);
1177
1178 /* check for re-spawn */
1179 if(psPtr->Mvt_InputRequests.Flags.Rqst_Operate)
1180 {
1181 if(AreThereAnyLivesLeft())
1182 {
1183 //check for change of character
1184 if(netGameData.myCharacterType!=netGameData.myNextCharacterType)
1185 {
1186 switch(netGameData.myNextCharacterType)
1187 {
1188 case (NGCT_Marine) :
1189 ChangeToMarine();
1190 break;
1191
1192 case (NGCT_Alien) :
1193 ChangeToAlien();
1194 break;
1195
1196 case (NGCT_Predator) :
1197 ChangeToPredator();
1198 break;
1199
1200 default :
1201 GLOBALASSERT("dodgy character type"==0);
1202 break;
1203
1204 }
1205
1206 netGameData.myCharacterType=netGameData.myNextCharacterType;
1207 }
1208 else
1209 {
1210 /* CDF 15/3/99, delete all discs... */
1211 RemoveAllThisPlayersDiscs();
1212
1213 NetPlayerRespawn(sbPtr);
1214 }
1215
1216 /* dynamics block stuff... */
1217 {
1218 EULER zeroEuler = {0,0,0};
1219 VECTORCH zeroVec = {0,0,0};
1220 DYNAMICSBLOCK *dynPtr = sbPtr->DynPtr;
1221
1222 dynPtr->Position = zeroVec;
1223 dynPtr->OrientEuler = zeroEuler;
1224 dynPtr->LinVelocity = zeroVec;
1225 dynPtr->LinImpulse = zeroVec;
1226
1227 CreateEulerMatrix(&dynPtr->OrientEuler, &dynPtr->OrientMat);
1228 TransposeMatrixCH(&dynPtr->OrientMat);
1229
1230 //Need to get rid of collisions for this frame , so player doesn't pick up
1231 //his dropped weapon when he respawns.
1232 dynPtr->CollisionReportPtr=0;
1233 }
1234 TeleportNetPlayerToAStartingPosition(sbPtr,0);
1235 }
1236 else
1237 {
1238 //no lives left , so have to act as an observer
1239 GetNextMultiplayerObservedPlayer();
1240
1241 //The player's dropped weapon (if there was one) can now be drawn
1242 MakePlayersWeaponPickupVisible();
1243
1244 }
1245 }
1246 }
1247
1248 extern void InitPlayerCloakingSystem(void);
1249 //make the player into new healthy character
NetPlayerRespawn(STRATEGYBLOCK * sbPtr)1250 void NetPlayerRespawn(STRATEGYBLOCK *sbPtr)
1251 {
1252 extern int LeanScale;
1253 #if 0
1254 SECTION *root_section;
1255 #endif
1256
1257 PLAYER_STATUS *psPtr= (PLAYER_STATUS *) (sbPtr->SBdataptr);
1258
1259
1260 /* Turn on corpse. */
1261 if (psPtr->MyCorpse) {
1262 if (psPtr->MyCorpse->SBdptr) {
1263 psPtr->MyCorpse->SBdptr->ObFlags&=~ObFlag_NotVis;
1264 }
1265 }
1266 psPtr->MyCorpse=NULL;
1267 DeInitialisePlayer();
1268 /* When you're going to respawn... you might change */
1269 /* character class, after all. */
1270 InitialisePlayersInventory(psPtr);
1271 /* psPtr->Health=STARTOFGAME_MARINE_HEALTH; */
1272 /* psPtr->Armour=STARTOFGAME_MARINE_ARMOUR; */
1273 psPtr->IsAlive = 1;
1274 psPtr->MyFaceHugger=NULL;
1275 psPtr->Energy=STARTOFGAME_MARINE_ENERGY;
1276 {
1277 NPC_DATA *NpcData;
1278 NPC_TYPES PlayerType;
1279
1280 switch(AvP.PlayerType)
1281 {
1282 case(I_Marine):
1283 {
1284 switch (AvP.Difficulty) {
1285 case I_Easy:
1286 PlayerType=I_PC_Marine_Easy;
1287 break;
1288 default:
1289 case I_Medium:
1290 PlayerType=I_PC_Marine_Medium;
1291 break;
1292 case I_Hard:
1293 PlayerType=I_PC_Marine_Hard;
1294 break;
1295 case I_Impossible:
1296 PlayerType=I_PC_Marine_Impossible;
1297 break;
1298 }
1299 LeanScale=ONE_FIXED;
1300
1301 #if 0 //this hmodel isn't being set up for the moment - Richard
1302 root_section=GetNamedHierarchyFromLibrary("hnpcmarine","Template");
1303 if (!root_section) {
1304 GLOBALASSERT(0);
1305 /* Sorry, there's just no bouncing back from this one. Fix it. */
1306 return;
1307 }
1308 Create_HModel(&psPtr->HModelController,root_section);
1309 InitHModelSequence(&psPtr->HModelController,0,0,ONE_FIXED);
1310 /* Doesn't matter what the sequence is... */
1311 #endif
1312 break;
1313 }
1314 case(I_Predator):
1315 {
1316 switch (AvP.Difficulty) {
1317 case I_Easy:
1318 PlayerType=I_PC_Predator_Easy;
1319 break;
1320 default:
1321 case I_Medium:
1322 PlayerType=I_PC_Predator_Medium;
1323 break;
1324 case I_Hard:
1325 PlayerType=I_PC_Predator_Hard;
1326 break;
1327 case I_Impossible:
1328 PlayerType=I_PC_Predator_Impossible;
1329 break;
1330 }
1331 LeanScale=ONE_FIXED;
1332
1333 #if 0 //this hmodel isn't being set up for the moment - Richard
1334 root_section=GetNamedHierarchyFromLibrary("hnpcpredator","Template");
1335 if (!root_section) {
1336 GLOBALASSERT(0);
1337 /* Sorry, there's just no bouncing back from this one. Fix it. */
1338 return;
1339 }
1340 Create_HModel(&psPtr->HModelController,root_section);
1341 InitHModelSequence(&psPtr->HModelController,0,0,ONE_FIXED);
1342 /* Doesn't matter what the sequence is... */
1343 #endif
1344 break;
1345 }
1346 case(I_Alien):
1347 {
1348 switch (AvP.Difficulty) {
1349 case I_Easy:
1350 PlayerType=I_PC_Alien_Easy;
1351 break;
1352 default:
1353 case I_Medium:
1354 PlayerType=I_PC_Alien_Medium;
1355 break;
1356 case I_Hard:
1357 PlayerType=I_PC_Alien_Hard;
1358 break;
1359 case I_Impossible:
1360 PlayerType=I_PC_Alien_Impossible;
1361 break;
1362 }
1363 LeanScale=ONE_FIXED*3;
1364
1365 #if 0 //this hmodel isn't being set up for the moment - Richard
1366 root_section=GetNamedHierarchyFromLibrary("hnpcalien","alien");
1367 if (!root_section) {
1368 GLOBALASSERT(0);
1369 /* Sorry, there's just no bouncing back from this one. Fix it. */
1370 return;
1371 }
1372 Create_HModel(&psPtr->HModelController,root_section);
1373 InitHModelSequence(&psPtr->HModelController,0,0,ONE_FIXED);
1374 /* Doesn't matter what the sequence is... */
1375 #endif
1376 break;
1377 }
1378 default:
1379 {
1380 LOCALASSERT(1==0);
1381 break;
1382 }
1383 }
1384
1385 NpcData = GetThisNpcData(PlayerType);
1386 LOCALASSERT(NpcData);
1387 sbPtr->SBDamageBlock.Health=NpcData->StartingStats.Health<<ONE_FIXED_SHIFT;
1388 sbPtr->SBDamageBlock.Armour=NpcData->StartingStats.Armour<<ONE_FIXED_SHIFT;
1389 sbPtr->SBDamageBlock.SB_H_flags=NpcData->StartingStats.SB_H_flags;
1390 sbPtr->SBDamageBlock.IsOnFire=0;
1391 }
1392
1393 psPtr->Encumberance.MovementMultiple=ONE_FIXED;
1394 psPtr->Encumberance.TurningMultiple=ONE_FIXED;
1395 psPtr->Encumberance.JumpingMultiple=ONE_FIXED;
1396 psPtr->Encumberance.CanCrouch=1;
1397 psPtr->Encumberance.CanRun=1;
1398 psPtr->Health=sbPtr->SBDamageBlock.Health;
1399 psPtr->Armour=sbPtr->SBDamageBlock.Armour;
1400
1401 psPtr->ForwardInertia=0;
1402 psPtr->StrafeInertia=0;
1403 psPtr->TurnInertia=0;
1404 psPtr->IsMovingInWater = 0;
1405
1406 psPtr->incidentFlag=0;
1407 psPtr->incidentTimer=0;
1408
1409 if (psPtr->soundHandle!=SOUND_NOACTIVEINDEX) {
1410 Sound_Stop(psPtr->soundHandle);
1411 }
1412 if (psPtr->soundHandle3!=SOUND_NOACTIVEINDEX) {
1413 Sound_Stop(psPtr->soundHandle3);
1414 }
1415
1416 if (weaponHandle!=SOUND_NOACTIVEINDEX) {
1417 Sound_Stop(weaponHandle);
1418 }
1419
1420 if (predHUDSoundHandle!=SOUND_NOACTIVEINDEX) {
1421 Sound_Stop(predHUDSoundHandle);
1422 }
1423
1424 if (predOVision_SoundHandle!=SOUND_NOACTIVEINDEX) {
1425 Sound_Stop(predOVision_SoundHandle);
1426 }
1427
1428 //reset the player's elasticity (which gets altered upon death)
1429 sbPtr->DynPtr->Elasticity = 0;
1430
1431
1432 InitPlayerCloakingSystem();
1433
1434 SetupVision();
1435
1436 PlayerDamagedOverlayIntensity = 0;
1437
1438 //no longer acting as an observer
1439 TurnOffMultiplayerObserveMode();
1440
1441 //The player's dropped weapon (if there was one) can now be drawn
1442 MakePlayersWeaponPickupVisible();
1443 }
1444
1445
1446 /* Patrick 9/7/97 ---------------------------------------------------
1447 These two functions are used for testing the pre-processed AI
1448 locations... (either entry points or auxilary locs)
1449 They teleport the player to the next location in the sequence,
1450 in response to the player pressing 'unused3' (currently the U key).
1451 --------------------------------------------------------------------*/
1452 #if PATTEST_EPS
1453 static int pF_ModuleIndex = 0;
1454 static int pF_EpIndex = 0;
1455 static int pF_HaveStarted = 0;
1456 static int pF_CanMove = 0;
1457
EpLocationTest(void)1458 void EpLocationTest(void)
1459 {
1460 extern SCENE Global_Scene;
1461 extern SCENEMODULE **Global_ModulePtr;
1462 extern int ModuleArraySize;
1463
1464 SCENEMODULE *ScenePtr;
1465 MODULE **moduleListPointer;
1466 DYNAMICSBLOCK *dynPtr = Player->ObStrategyBlock->DynPtr;
1467 MODULE *thisModulePtr;
1468
1469 LOCALASSERT(Global_ModulePtr);
1470 ScenePtr = Global_ModulePtr[Global_Scene];
1471 moduleListPointer = ScenePtr->sm_marray;
1472
1473 if(PlayerStatusPtr->Mvt_InputRequests.Flags.Rqst_Unused3)
1474 {
1475 if(pF_CanMove == 1)
1476 {
1477 /* move to the next one */
1478 pF_EpIndex++;
1479 if(pF_EpIndex >= FALLP_EntryPoints[pF_ModuleIndex].numEntryPoints)
1480 {
1481 pF_EpIndex=0;
1482 do
1483 {
1484 pF_ModuleIndex++;
1485 if(pF_ModuleIndex>=ModuleArraySize) pF_ModuleIndex = 0;
1486 }
1487 while(FALLP_EntryPoints[pF_ModuleIndex].numEntryPoints==0);
1488 }
1489
1490 /* now move to the new location */
1491 thisModulePtr = moduleListPointer[pF_ModuleIndex];
1492 dynPtr->Position = FALLP_EntryPoints[pF_ModuleIndex].entryPointsList[(pF_EpIndex)].position;
1493 dynPtr->Position.vx += thisModulePtr->m_world.vx;
1494 dynPtr->Position.vy += thisModulePtr->m_world.vy;
1495 dynPtr->Position.vz += thisModulePtr->m_world.vz;
1496
1497 dynPtr->PrevPosition = dynPtr->Position;
1498
1499 pF_HaveStarted = 1;
1500 pF_CanMove = 0;
1501 }
1502 }
1503 else pF_CanMove = 1;
1504
1505 if (pF_HaveStarted)
1506 {
1507 textprint("CURRENT FAR MODULE %d \n", pF_ModuleIndex);
1508 textprint("EP number %d from module %d \n", pF_EpIndex, FALLP_EntryPoints[pF_ModuleIndex].entryPointsList[(pF_EpIndex)].donorIndex);
1509 }
1510 }
1511
1512 #endif
1513 #if PATTEST_AUXLOCS
1514 static int pF_ModuleIndex = 0;
1515 static int pF_AuxIndex = 0;
1516 static int pF_HaveStarted = 0;
1517 static int pF_CanMove = 0;
1518
AuxLocationTest(void)1519 void AuxLocationTest(void)
1520 {
1521 extern SCENE Global_Scene;
1522 extern SCENEMODULE **Global_ModulePtr;
1523 extern int ModuleArraySize;
1524
1525 SCENEMODULE *ScenePtr;
1526 MODULE **moduleListPointer;
1527 DYNAMICSBLOCK *dynPtr=Player->ObStrategyBlock->DynPtr;
1528 MODULE *thisModulePtr;
1529
1530 LOCALASSERT(Global_ModulePtr);
1531 ScenePtr = Global_ModulePtr[Global_Scene];
1532 moduleListPointer = ScenePtr->sm_marray;
1533
1534 /* dynPtr->GravityOn = 0; */
1535
1536 if(PlayerStatusPtr->Mvt_InputRequests.Flags.Rqst_Unused3)
1537 {
1538 if(pF_CanMove == 1)
1539 {
1540 /* move to the next one */
1541 pF_AuxIndex++;
1542 if(pF_AuxIndex >= FALLP_AuxLocs[pF_ModuleIndex].numLocations)
1543 {
1544 pF_AuxIndex=0;
1545 do
1546 {
1547 pF_ModuleIndex++;
1548 if(pF_ModuleIndex>=ModuleArraySize) pF_ModuleIndex = 0;
1549 }
1550 while(FALLP_AuxLocs[pF_ModuleIndex].numLocations==0);
1551 }
1552
1553 /* now move to the new location */
1554 thisModulePtr = moduleListPointer[pF_ModuleIndex];
1555 dynPtr->Position = FALLP_AuxLocs[pF_ModuleIndex].locationsList[pF_AuxIndex];
1556 dynPtr->Position.vx += thisModulePtr->m_world.vx;
1557 dynPtr->Position.vy += thisModulePtr->m_world.vy;
1558 dynPtr->Position.vz += thisModulePtr->m_world.vz;
1559 dynPtr->Position.vy -= 1000;
1560
1561 dynPtr->PrevPosition = dynPtr->Position;
1562 pF_HaveStarted = 1;
1563 pF_CanMove = 0;
1564 }
1565 }
1566 else pF_CanMove = 1;
1567
1568 if (pF_HaveStarted)
1569 {
1570 textprint("CURRENT FAR MODULE %d \n", pF_ModuleIndex);
1571 textprint("AUX number %d \n", pF_AuxIndex);
1572 }
1573 }
1574
1575 #endif
1576
1577
1578
1579
1580
1581 /* KJL 10:34:54 8/5/97 - The alien can damage things by merely touching them
1582
1583 This will need work to get the values right - the damage done could be
1584 scaled by the alien's experience points, the relative velocities of the
1585 objects, and so on.
1586 */
1587 #define ALIEN_CONTACT_WEAPON_DAMAGE 50
1588 #define ALIEN_CONTACT_WEAPON_DELAY 65536
1589
1590 #if ALIEN_CONTACT_WEAPON
AlienContactWeapon(void)1591 static void AlienContactWeapon(void)
1592 {
1593 COLLISIONREPORT *reportPtr = Player->ObStrategyBlock->DynPtr->CollisionReportPtr;
1594 static int contactWeaponTimer = 0;
1595
1596 if (contactWeaponTimer<=0)
1597 {
1598 contactWeaponTimer = ALIEN_CONTACT_WEAPON_DELAY;
1599
1600 while (reportPtr) /* while there is a valid report */
1601 {
1602 if (reportPtr->ObstacleSBPtr)
1603 {
1604 switch(reportPtr->ObstacleSBPtr->I_SBtype)
1605 {
1606 case I_BehaviourMarinePlayer:
1607 case I_BehaviourAlienPlayer:
1608 case I_BehaviourPredatorPlayer:
1609 case I_BehaviourPredator:
1610 case I_BehaviourMarine:
1611 case I_BehaviourSeal:
1612 case I_BehaviourNetGhost:
1613 {
1614 /* make alienesque noise */
1615 Sound_Play(SID_HIT_FLESH,"h");
1616
1617 /* damage unfortunate object */
1618 CauseDamageToObject(reportPtr->ObstacleSBPtr,ALIEN_CONTACT_WEAPON_DAMAGE,NULL);
1619 break;
1620 }
1621 default:
1622 break;
1623 }
1624 }
1625 /* skip to next report */
1626 reportPtr = reportPtr->NextCollisionReportPtr;
1627 }
1628 }
1629 else
1630 {
1631 contactWeaponTimer -= NormalFrameTime;
1632 }
1633
1634 }
1635 #endif
1636
1637 /* Demo code removed, CDF 28/9/98, by order of Kevin */
1638
1639 #if LOAD_IN_MOVEMENT_VALUES
LoadInMovementValues(void)1640 static void LoadInMovementValues(void)
1641 {
1642
1643 FILE *fpInput;
1644
1645 fpInput = fopen("movement.txt","rb");
1646
1647 while(fgetc(fpInput) != '#');
1648 while(fgetc(fpInput) != '#');
1649 fscanf(fpInput, "%d",&AlienForwardSpeed);
1650 while(fgetc(fpInput) != '#');
1651 fscanf(fpInput, "%d",&AlienStrafeSpeed);
1652 while(fgetc(fpInput) != '#');
1653 fscanf(fpInput, "%d",&AlienTurnSpeed);
1654 while(fgetc(fpInput) != '#');
1655 fscanf(fpInput, "%d",&AlienJumpSpeed);
1656
1657 while(fgetc(fpInput) != '#');
1658 fscanf(fpInput, "%d",&PredatorForwardSpeed);
1659 while(fgetc(fpInput) != '#');
1660 fscanf(fpInput, "%d",&PredatorStrafeSpeed);
1661 while(fgetc(fpInput) != '#');
1662 fscanf(fpInput, "%d",&PredatorTurnSpeed);
1663 while(fgetc(fpInput) != '#');
1664 fscanf(fpInput, "%d",&PredatorJumpSpeed);
1665
1666 while(fgetc(fpInput) != '#');
1667 fscanf(fpInput, "%d",&MarineForwardSpeed);
1668 while(fgetc(fpInput) != '#');
1669 fscanf(fpInput, "%d",&MarineStrafeSpeed);
1670 while(fgetc(fpInput) != '#');
1671 fscanf(fpInput, "%d",&MarineTurnSpeed);
1672 while(fgetc(fpInput) != '#');
1673 fscanf(fpInput, "%d",&MarineJumpSpeed);
1674
1675 fclose(fpInput);
1676 }
1677 #endif
1678
1679
ThrowAFlare(void)1680 void ThrowAFlare(void)
1681 {
1682 extern int NumberOfFlaresActive;
1683
1684 if (NumberOfFlaresActive<4)
1685 {
1686 extern VIEWDESCRIPTORBLOCK *ActiveVDBList[];
1687 VIEWDESCRIPTORBLOCK *VDBPtr = ActiveVDBList[0];
1688 MATRIXCH mat = VDBPtr->VDB_Mat;
1689 VECTORCH position = VDBPtr->VDB_World;
1690
1691 TransposeMatrixCH(&mat);
1692
1693 CreateGrenadeKernel(I_BehaviourFlareGrenade,&position,&mat,1);
1694 Sound_Play(SID_THROW_FLARE,"h");
1695 }
1696
1697 }
1698