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