1 /*KJL****************************************************************************************
2 *                                         	hud.c                                           *
3 ****************************************************************************************KJL*/
4 
5 
6 /*
7 	functions for drawing the HUD, processing sounds and
8 	Marine Hud contains the information for drawing stuff to the
9 	HUD. MarineWeaponHud contains he various information needed
10 	to copy Weapon data into the HUD
11 */
12 #include "3dc.h"
13 #include "module.h"
14 #include "inline.h"
15 
16 
17 #include "stratdef.h"
18 #include "gamedef.h"
19 #include "bh_types.h"
20 #include "comp_shp.h"
21 #include "huddefs.h"
22 #include "dynblock.h"
23 #include "weapons.h"
24 
25 #include "psnd.h"
26 #include "psndplat.h"
27 #include "dynamics.h"
28 
29 #include "particle.h"
30 #include "gadget.h"
31 #include "lighting.h"
32 #include "d3d_hud.h"
33 #include "frustum.h"
34 #include "pldghost.h"
35 
36 #include "d3d_render.h"
37 #include "kshape.h"
38 #include "opengl.h"
39 #include "bh_ais.h"
40 #include "bh_alien.h"
41 
42 #define UseLocalAssert Yes
43 #include "ourasert.h"
44 
45 #include "vision.h"
46 #include "bonusabilities.h"
47 #include "avp_menus.h"
48 #include "showcmds.h"
49 #include "game_statistics.h"
50 #include "pldnet.h"
51 #include "avp_userprofile.h"
52 #include "hud.h"
53 #include "chnkload.h"
54 
55 extern int ScanDrawMode;
56 
57 #define DO_PREDATOR_OVERLAY No
58 #define DO_ALIEN_OVERLAY No
59 
60 #define DRAW_HUD Yes
61 /*KJL****************************************************************************************
62 *  										G L O B A L S 	            					    *
63 ****************************************************************************************KJL*/
64 
65 
66 extern DISPLAYBLOCK* Player;
67 
68 extern int NumActiveBlocks;
69 extern DISPLAYBLOCK *ActiveBlockList[];
70 extern int NumOnScreenBlocks;
71 extern DISPLAYBLOCK *OnScreenBlockList[];
72 extern int NumActiveStBlocks;
73 extern STRATEGYBLOCK *ActiveStBlockList[maxstblocks];
74 
75 extern SCREENDESCRIPTORBLOCK ScreenDescriptorBlock;
76 extern int NormalFrameTime;
77 
78 extern VIEWDESCRIPTORBLOCK *Global_VDB_Ptr;
79 extern signed int RequestFadeToBlackLevel;
80 extern ACTIVESOUNDSAMPLE ActiveSounds[];
81 
82 extern int SmartTargetSightX, SmartTargetSightY;
83 extern char CurrentlySmartTargetingObject;
84 extern DISPLAYBLOCK *SmartTarget_Object;
85 extern DISPLAYBLOCK *Old_SmartTarget_Object;
86 
87 /* In 16.16 for smoothness. On-screen coords for the smart targeting system's sight */
88 
89 int GunMuzzleSightX, GunMuzzleSightY;
90 /* In 16.16 for smoothness. On-screen coords indicating to where the gun's muzzle is pointing */
91 
92 /* motion tracker info */
93 static int MTScanLineSize=MOTIONTRACKER_SMALLESTSCANLINESIZE;
94 static int PreviousMTScanLineSize=MOTIONTRACKER_SMALLESTSCANLINESIZE;
95 static int MTDelayBetweenScans=0;
96 static BLIP_TYPE MotionTrackerBlips[MOTIONTRACKER_MAXBLIPS];
97 static int NoOfMTBlips=0;
98 static int MTSoundHandle=SOUND_NOACTIVEINDEX;
99 int predHUDSoundHandle=SOUND_NOACTIVEINDEX;
100 
101 static int HUD_PrimaryRounds;
102 static int HUD_SecondaryRounds;
103 /* numerics buffer - the marine has more digits on his HUD than the other species */
104 char ValueOfHUDDigit[MAX_NO_OF_MARINE_HUD_DIGITS];
105 
106 
107 #define PREDATOR_LOCK_ON_TIME (ONE_FIXED*5/3)
108 #define PREDATOR_LOCK_ON_SPEED (3)
109 static int PredSight_LockOnTime;
110 static int PredSight_Angle;
111 
112 int AlienTeethOffset;
113 int AlienTongueOffset;
114 
115 int DrawCompanyLogos;
116 int LogosAlphaLevel;
117 int PlayerDamagedOverlayIntensity;
118 
119 int FadingGameInAfterLoading;
120 
121 int MotionTrackerSpeed = ONE_FIXED;
122 int MotionTrackerVolume = ONE_FIXED;
123 #define MOTIONTRACKERVOLUME (MUL_FIXED(VOLUME_MAX,MotionTrackerVolume))
124 
125 int CameraZoomLevel;
126 extern float CameraZoomScale;
127 static int DrawScanlineOverlay;
128 static float ScanlineLevel;
129 
130 
131 /*KJL****************************************************************************************
132 *                                    P R O T O T Y P E S	                                *
133 ****************************************************************************************KJL*/
134 //extern void SmartTarget(int speed);
135 extern void SmartTarget(int speed,int projectile_speed);
136 
137 extern void PlatformSpecificKillMarineHUD(void);
138 extern void PlatformSpecificKillAlienHUD(void);
139 extern void PlatformSpecificKillPredatorHUD(void);
140 extern void DrawScanlinesOverlay(float level);
141 extern void RenderThisDisplayblock(DISPLAYBLOCK *dbPtr);
142 void DisplayPredatorHealthAndEnergy(void);
143 
144 void InitHUD();
145 static void InitMarineHUD();
146 static void InitAlienHUD();
147 //static void CalcCoordsAndBLTWeapon(WEAPON_DATA* wptr);
148 
149 
150 static void DisplayHealthAndArmour(void);
151 static void DisplayMarinesAmmo(void);
152 
153 
154 static void DoMotionTracker(void);
155 static int DoMotionTrackerBlips(void);
156 
157 static void HandleMarineWeapon(void);
158 static void AimGunSight(int aimingSpeed, TEMPLATE_WEAPON_DATA *twPtr);
159 static void DrawMarineSights(void);
160 static void DrawPredatorSights(void);
161 void DrawWristDisplay(void);
162 static void DrawAlienTeeth(void);
163 
164 void CentreGunSight(void);
165 
166 
167 static void InitPredatorHUD();
168 //static int FindPredatorThreats(void);
169 #if DO_PREDATOR_OVERLAY
170 static void UpdatePredatorStatusValues(void);
171 #endif
172 static void HandlePredatorWeapon(void);
173 
174 static void HandleAlienWeapon(void);
175 #if DO_ALIEN_OVERLAY
176 static void UpdateAlienStatusValues(void);
177 #endif
178 
179 int Fast2dMagnitude(int dx, int dy);
180 
181 
182 /*KJL****************************************************************************************
183 *                                     F U N C T I O N S	                                    *
184 ****************************************************************************************KJL*/
InitHUD(void)185 void InitHUD(void)
186 {
187 	switch(AvP.PlayerType)
188 	{
189 		case I_Marine:
190   	 		InitMarineHUD();
191 			break;
192        	case I_Predator:
193 			InitPredatorHUD();
194 			break;
195 		case I_Alien:
196 			InitAlienHUD();
197 			break;
198 
199 		default:
200 			LOCALASSERT(1==0);
201 			break;
202 	}
203 
204 	// This should be set elsewhere as well, but just to be sure!!
205 	RequestFadeToBlackLevel = 0;
206 }
207 
KillHUD(void)208 void KillHUD(void)
209 {
210 	switch(AvP.PlayerType)
211 	{
212 		case I_Marine:
213 			PlatformSpecificKillMarineHUD();
214 			break;
215        	case I_Predator:
216 			PlatformSpecificKillPredatorHUD();
217 			break;
218 		case I_Alien:
219 			PlatformSpecificKillAlienHUD();
220 			break;
221 
222 		default:
223 			LOCALASSERT(1==0);
224 			break;
225 	}
226 }
InitMarineHUD(void)227 void InitMarineHUD(void)
228 {
229 	/*KJL****************************************************************************************
230 	* Okay. From now on everyone will call the fn below which loads and initialises ALL the gfx *
231 	* required for a marine, eg. weapons, motion tracker stuff, gun sights, et al.              *
232 	****************************************************************************************KJL*/
233 	PlatformSpecificInitMarineHUD();
234 
235 	SmartTarget_Object=NULL;
236 	Old_SmartTarget_Object=NULL;
237 
238 	{
239 		int i;
240 		for (i=0; i<sizeof(ValueOfHUDDigit)/sizeof(ValueOfHUDDigit[0]); i++)
241 			ValueOfHUDDigit[i]=0;
242 	}
243 
244 	/* Start the gun sight at the centre of the screen */
245 	/* SmartTargetSight in 16.16 coords, hence the shift up by 15 */
246 	SmartTargetSightX = (ScreenDescriptorBlock.SDB_Width<<15);
247 	SmartTargetSightY = (ScreenDescriptorBlock.SDB_Height<<15);
248 
249 	GunMuzzleSightX = (ScreenDescriptorBlock.SDB_Width<<15);
250 	GunMuzzleSightY = (ScreenDescriptorBlock.SDB_Height<<15);
251 
252 	HUD_PrimaryRounds = 0;
253 	HUD_SecondaryRounds = 0;
254 
255 }
256 
257 
InitAlienHUD(void)258 static void InitAlienHUD(void)
259 {
260 	PlatformSpecificInitAlienHUD();
261 	AlienTeethOffset = 0;
262 	AlienTongueOffset = 0;
263 
264 	SmartTarget_Object=NULL;
265 	Old_SmartTarget_Object=NULL;
266 
267 }
268 
ReInitHUD(void)269 void ReInitHUD(void)
270 {
271 	/* KJL 14:21:33 17/11/98 - Alien */
272 	AlienTeethOffset = 0;
273 	AlienTongueOffset = 0;
274 
275 
276 	/* KJL 14:21:48 17/11/98 - Marine */
277 	/* Start the gun sight at the centre of the screen */
278 	/* SmartTargetSight in 16.16 coords, hence the shift up by 15 */
279 	SmartTargetSightX = (ScreenDescriptorBlock.SDB_Width<<15);
280 	SmartTargetSightY = (ScreenDescriptorBlock.SDB_Height<<15);
281 
282 	GunMuzzleSightX = (ScreenDescriptorBlock.SDB_Width<<15);
283 	GunMuzzleSightY = (ScreenDescriptorBlock.SDB_Height<<15);
284 
285 	HUD_PrimaryRounds = 0;
286 	HUD_SecondaryRounds = 0;
287 
288 	/* KJL 14:21:54 17/11/98 - Predator */
289 	InitialiseGrapplingHook();
290 }
291 
292 /* KJL 16:27:39 09/20/96 - routine which handles all HUD activity */
MaintainHUD(void)293 void MaintainHUD(void)
294 {
295 	PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
296 	GLOBALASSERT(playerStatusPtr);
297 
298 //	RenderSmokeTest();
299 	PlatformSpecificEnteringHUD();
300 
301 	if (ScanDrawMode != ScanDrawDirectDraw)
302 	{
303 		HandleParticleSystem();
304 	}
305 	RenderGrapplingHook();
306 
307 	SecondFlushD3DZBuffer();
308 
309 	//DrawFontTest();
310 	if (Observer)
311 	{
312 		switch(AvP.PlayerType)
313 		{
314 			case I_Marine:
315 			{
316 		  		HandleMarineOVision();
317 				break;
318 			}
319 	       	case I_Predator:
320 			{
321   				HandlePredOVision();
322 				break;
323 			}
324 			case I_Alien:
325 			{
326 				HandleAlienOVision();
327 				break;
328 			}
329 			default:
330 				break;
331 		}
332 		CheckWireFrameMode(0);
333 		#if 1||!PREDATOR_DEMO
334 		GADGET_Render();
335 		#endif
336 		return;
337 	}
338 
339 //	GlobalAmbience=16384;
340 
341 	/* KJL 18:46:04 03/10/97 - for now I've completely turned off the HUD if you die; this
342 	can easily be changed */
343 	#if DRAW_HUD
344 	if (playerStatusPtr->MyFaceHugger!=NULL)
345 	{
346 		/* YUCK! */
347 		extern void PlotFaceHugger(STRATEGYBLOCK *sbPtr);
348 		PlotFaceHugger(playerStatusPtr->MyFaceHugger);
349 
350 	}
351 	else if (playerStatusPtr->IsAlive)
352 	{
353 		/* switch on player type */
354 		switch(AvP.PlayerType)
355 		{
356 			case I_Marine:
357 			{
358 				HandleMarineWeapon();
359 
360 	  	 	 	if (CurrentVisionMode==VISION_MODE_NORMAL) DoMotionTracker();
361 
362 				CheckWireFrameMode(0);
363 				//flash health if invulnerable
364 				if((playerStatusPtr->invulnerabilityTimer/12000 %2)==0)
365 				{
366 					DisplayHealthAndArmour();
367 				}
368 				DisplayMarinesAmmo();
369 		  		DrawMarineSights();
370 
371 				/* Paranoia check. */
372 		  		if(predHUDSoundHandle != SOUND_NOACTIVEINDEX) {
373 		       		Sound_Stop(predHUDSoundHandle);
374 				}
375 				break;
376 			}
377 	       	case I_Predator:
378 			{
379 				HandlePredatorWeapon();
380 				CheckWireFrameMode(0);
381 				//DrawPredatorEnergyBar();
382 	  			//DisplayHealthAndArmour();
383 			   	DrawWristDisplay();
384 
385   				HandlePredOVision();
386 				if (DrawScanlineOverlay) DrawScanlinesOverlay(ScanlineLevel);
387 
388 			   	DrawPredatorSights();
389 				//flash health if invulnerable
390 				if((playerStatusPtr->invulnerabilityTimer/12000 %2)==0)
391 				{
392 	  				DisplayPredatorHealthAndEnergy();
393 				}
394 
395 				break;
396 			}
397 			case I_Alien:
398 			{
399 				DrawAlienTeeth();
400 				if (AlienTongueOffset)
401 				{
402 					RenderInsideAlienTongue(AlienTongueOffset);
403 					AlienTongueOffset-=NormalFrameTime;
404 					if (AlienTongueOffset<0)
405 						AlienTongueOffset = 0;
406 				}
407 				SetFrustrumType(FRUSTRUM_TYPE_NORMAL);
408 				Global_VDB_Ptr->VDB_ProjX = (Global_VDB_Ptr->VDB_ClipRight - Global_VDB_Ptr->VDB_ClipLeft)/2;
409 				Global_VDB_Ptr->VDB_ProjY = (Global_VDB_Ptr->VDB_ClipDown - Global_VDB_Ptr->VDB_ClipUp)/2;
410 
411 				HandleAlienWeapon();
412 				HandleAlienOVision();
413 
414 				SetFrustrumType(FRUSTRUM_TYPE_WIDE);
415 				Global_VDB_Ptr->VDB_ProjX = (Global_VDB_Ptr->VDB_ClipRight - Global_VDB_Ptr->VDB_ClipLeft)/4;
416 				Global_VDB_Ptr->VDB_ProjY = (Global_VDB_Ptr->VDB_ClipDown - Global_VDB_Ptr->VDB_ClipUp)/4;
417 
418 				CheckWireFrameMode(0);
419 
420 				//flash health if invulnerable
421 				if((playerStatusPtr->invulnerabilityTimer/12000 %2)==0)
422 				{
423 					DisplayHealthAndArmour();
424 				}
425 				/* Paranoia check. */
426 		  		if(predHUDSoundHandle != SOUND_NOACTIVEINDEX) {
427 		       		Sound_Stop(predHUDSoundHandle);
428 				}
429 				break;
430 			}
431 			default:
432 				LOCALASSERT(1==0);
433 				break;
434 		}
435 	}
436 	else // player is dead!
437 	{
438 		switch(AvP.PlayerType)
439 		{
440 			case I_Marine:
441 			{
442 				break;
443 			}
444 	       	case I_Predator:
445 			{
446   				HandlePredOVision();
447 				break;
448 			}
449 			case I_Alien:
450 			{
451 				HandleAlienOVision();
452 				break;
453 			}
454 			default:
455 				break;
456 		}
457 	}
458 
459 	#endif
460 
461 	CheckWireFrameMode(0);
462 
463 	{
464 		extern int HeadUpDisplayZOffset;
465 		HeadUpDisplayZOffset = 0;
466 
467 		#if 1||!PREDATOR_DEMO
468 		GADGET_Render();
469 		#endif
470 
471 		switch(AvP.PlayerType)
472 		{
473 			case I_Marine:
474 			{
475 		  		HandleMarineOVision();
476 				break;
477 			}
478 	       	case I_Predator:
479 			{
480   	//			HandlePredOVision();
481 				break;
482 			}
483 			default:
484 				break;
485 		}
486 
487 	}
488 	{
489 		extern int AlienBiteAttackInProgress;
490 		if (AlienBiteAttackInProgress)
491 		{
492 			extern void D3D_FadeDownScreen(int brightness, int colour);
493 			int b;
494 			if (CameraZoomScale!=0.25f)
495 			{
496 				f2i(b,CameraZoomScale*65536.0f);
497 				if (b<32768) b=32768;
498 				D3D_FadeDownScreen(b,0xff0000);
499 			}
500 		}
501 	}
502 	// burn baby burn?
503 	if (Player->ObStrategyBlock->SBDamageBlock.IsOnFire)
504 	{
505 		D3D_PlayerOnFireOverlay();
506 	}
507 	else
508 	{
509 
510 		extern int PlayerDamagedOverlayIntensity;
511 		int intensity = PlayerDamagedOverlayIntensity>>12;
512 //		if (intensity>255) intensity = 255;
513 		if (intensity>128) intensity = 128;
514 
515 		if (intensity)
516 		{
517 			D3D_PlayerDamagedOverlay(intensity);
518 		}
519 
520 		PlayerDamagedOverlayIntensity -= NormalFrameTime<<5;
521 		if (PlayerDamagedOverlayIntensity<0) PlayerDamagedOverlayIntensity=0;
522 	}
523 	{
524 		#if 0
525 		if(DrawCompanyLogos && LogosAlphaLevel)
526 		{
527 			extern void D3D_DrawRebellionLogo(unsigned int alpha);
528 
529 			if (LogosAlphaLevel<ONE_FIXED)
530 			{
531 				D3D_DrawRebellionLogo(LogosAlphaLevel);
532 			}
533 			else
534 			{
535 				D3D_DrawRebellionLogo(0xff00);
536 			}
537 
538 			LogosAlphaLevel-=NormalFrameTime;
539 			if (LogosAlphaLevel<0) LogosAlphaLevel=0;
540 		}
541 		#endif
542 		if(FadingGameInAfterLoading)
543 		{
544 			extern void D3D_FadeDownScreen(int brightness, int colour);
545 			extern int RealFrameTime;
546 			D3D_FadeDownScreen(ONE_FIXED-FadingGameInAfterLoading, 0);
547 
548 			RenderBriefingText(ScreenDescriptorBlock.SDB_Height/2,FadingGameInAfterLoading);
549 
550 			FadingGameInAfterLoading-=RealFrameTime/2;
551 			if (FadingGameInAfterLoading<0) FadingGameInAfterLoading = 0;
552 		}
553 	}
554 	if(!playerStatusPtr->IsAlive)
555 	{
556 		if (AvP.Network==I_No_Network)
557 		{
558 			DoFailedLevelStatisticsScreen();
559 		}
560 		else
561 		{
562 			// place multiplayer stuff here - e.g. full scores/frags et al
563 		}
564 	}
565     if(AvP.Network != I_No_Network)
566 	{
567 		DoMultiplayerSpecificHud();
568 	}
569 }
570 
DoCompletedLevelStatisticsScreen(void)571 void DoCompletedLevelStatisticsScreen(void)
572 {
573 	extern int DebouncedGotAnyKey;
574 	extern unsigned char DebouncedKeyboardInput[];
575 	if (DebouncedKeyboardInput[KEY_ESCAPE])
576 	{
577 		AvP.RestartLevel = 1;
578 	}
579 	else if (DebouncedGotAnyKey)
580 	{
581 		AvP.MainLoopRunning = 0;
582 	}
583 	D3D_FadeDownScreen(0,0);
584 	DoStatisticsScreen(1);
585 	RenderStringCentred(GetTextString(TEXTSTRING_COMPLETEDLEVEL_PRESSAKEY),ScreenDescriptorBlock.SDB_Width/2,ScreenDescriptorBlock.SDB_Height-20,0xffffffff);
586 }
587 
588 
589 /*   This function scans through the active block list looking for dynamic objects
590    which are detectable	by the Motion Tracker.
591 */
DoMotionTracker(void)592 static void DoMotionTracker(void)
593 {
594  	static char distanceNotLocked=1;
595 	static int distance=0;
596 
597 	/* draw static motion tracker background, and the moving scanline */
598 	BLTMotionTrackerToHUD(MTScanLineSize);
599 
600 	if(distanceNotLocked) /* if MT hasn't found any contacts this scan */
601 	{
602 		int nearestDistance=DoMotionTrackerBlips();
603 
604    		if (nearestDistance<MOTIONTRACKER_RANGE) /* if picked up some blips */
605 		{
606 			distance=nearestDistance;
607 			distanceNotLocked=0;
608 
609 			if (MTSoundHandle==SOUND_NOACTIVEINDEX)
610 			{
611 				int panicFactor = MUL_FIXED(nearestDistance,MOTIONTRACKER_SCALE);
612 				if (panicFactor < 21845)
613 				{
614 					Sound_Play(SID_TRACKER_WHEEP_HIGH,"ev",&MTSoundHandle,MOTIONTRACKERVOLUME);
615 				}
616 				else if (panicFactor < 21845*2)
617 				{
618 					Sound_Play(SID_TRACKER_WHEEP,"ev",&MTSoundHandle,MOTIONTRACKERVOLUME);
619 				}
620 				else
621 				{
622 					Sound_Play(SID_TRACKER_WHEEP_LOW,"ev",&MTSoundHandle,MOTIONTRACKERVOLUME);
623 				}
624 			}
625 
626 			// Do motion tracker pitch change?
627 
628 			#if 0 // no - it sounds fucking awful
629 			if (MTSoundHandle!=SOUND_NOACTIVEINDEX)
630 			{
631 				int panicFactor = 65536 - MUL_FIXED(nearestDistance,MOTIONTRACKER_SCALE);
632 				LOCALASSERT(panicFactor>=0);
633 				panicFactor>>=8;              // Scale to 0-256
634 
635 				PlatChangeSoundPitch(MTSoundHandle,panicFactor);
636 
637 			}
638 			#endif
639 
640 		}
641 		else if (NoOfMTBlips==0) /* if the MT is blank, cycle the distance digits */
642 		{
643 			distance= MUL_FIXED(MTScanLineSize,MOTIONTRACKER_RANGE);
644  		}
645 	}
646 	else DoMotionTrackerBlips();
647 
648 	/* evaluate the distance digits */
649 	{
650     	int value=distance/10;
651         ValueOfHUDDigit[MARINE_HUD_MOTIONTRACKER_UNITS]=value%10;
652 
653 		value/=10;
654         ValueOfHUDDigit[MARINE_HUD_MOTIONTRACKER_TENS]=value%10;
655 
656         value/=10;
657 		ValueOfHUDDigit[MARINE_HUD_MOTIONTRACKER_HUNDREDS]=value%10;
658 
659 		value/=10;
660       	ValueOfHUDDigit[MARINE_HUD_MOTIONTRACKER_THOUSANDS]=value%10;
661 	}
662 
663 	if (MTDelayBetweenScans)
664 	{
665 		MTDelayBetweenScans-=NormalFrameTime;
666 		if (MTDelayBetweenScans<0)
667 		{
668 			MTDelayBetweenScans=0;
669 
670 			Sound_Play(SID_TRACKER_CLICK,"v",MOTIONTRACKERVOLUME);
671 
672 			PreviousMTScanLineSize =MTScanLineSize=MOTIONTRACKER_SMALLESTSCANLINESIZE;
673 			distanceNotLocked=1; /* allow MT to look for a new nearest contact distance */
674 		}
675 	}
676 	else
677 	{
678 		/* expand scanline or wrap it around */
679 		PreviousMTScanLineSize=MTScanLineSize;
680 
681 		if (MTScanLineSize>=65536)
682 		{
683 			MTDelayBetweenScans=65536;
684 			MTScanLineSize=0;
685 		}
686 		else if (MTScanLineSize>32768)
687 		{
688 			MTScanLineSize+= MUL_FIXED(MOTIONTRACKER_SPEED*2,NormalFrameTime);
689 		}
690 		else
691 		{
692 			MTScanLineSize+= MUL_FIXED(MOTIONTRACKER_SPEED,NormalFrameTime);
693 		}
694 
695 		if (MTScanLineSize>65536)
696 		{
697 			MTScanLineSize=65536;
698 		}
699 	}
700 
701 	/* draw blips to HUD */
702 	{
703 		DYNAMICSBLOCK *playerDynPtr = Player->ObStrategyBlock->DynPtr;
704 		int phi = playerDynPtr->OrientEuler.EulerY;
705 		int cosPhi = MUL_FIXED(GetCos(phi),MOTIONTRACKER_SCALE);
706 		int sinPhi = MUL_FIXED(GetSin(phi),MOTIONTRACKER_SCALE);
707     	int i;
708     	/* made more awkward because we want to draw the brightest last */
709 		i=0;
710 
711 		while(i<NoOfMTBlips)
712 		{
713 			int y = MotionTrackerBlips[i].Y-playerDynPtr->Position.vz;
714 		  	int x = MotionTrackerBlips[i].X-playerDynPtr->Position.vx;
715 			int y2 = MUL_FIXED(x,sinPhi) + MUL_FIXED(y,cosPhi);
716 
717 			if (y2>=0)
718 			{
719 				x = MUL_FIXED(x,cosPhi) - MUL_FIXED(y,sinPhi);
720 
721 				if(Fast2dMagnitude(x,y2)<ONE_FIXED)
722 				{
723 					BLTMotionTrackerBlipToHUD
724 					(
725 						x,
726 				   		y2,
727 						MotionTrackerBlips[i].Brightness
728 					);
729 				}
730 			}
731             i++;
732 		}
733 
734 		/* now fade or kill blips */
735 		i = NoOfMTBlips;
736 		while(i--) /* scan through all blips, starting with the last in the list */
737 		{
738 			/* decrease blip's brightness */
739 			MotionTrackerBlips[i].Brightness-=MUL_FIXED(MOTIONTRACKER_SPEED/3,NormalFrameTime);
740 			if (MotionTrackerBlips[i].Brightness<0)	/* then kill blip */
741 			{
742 				/* Kill ith blip by copying the last blip in the list over the ith
743 				   and decreasing the number of blips */
744 				NoOfMTBlips--;
745 				MotionTrackerBlips[i] = MotionTrackerBlips[NoOfMTBlips];
746 			}
747 		}
748 	}
749 
750 	return;
751 }
752 
753 /*KJL*********************************************************
754 * DoMotionTrackerBlips() looks a bit messy but works well.   *
755 *********************************************************KJL*/
ObjectShouldAppearOnMotionTracker(STRATEGYBLOCK * sbPtr)756 int ObjectShouldAppearOnMotionTracker(STRATEGYBLOCK *sbPtr)
757 {
758 	DYNAMICSBLOCK *objectDynPtr = sbPtr->DynPtr;
759 
760 	/* KJL 12:45:54 21/08/98 - objects which will never appear on the MT */
761 	if((sbPtr->I_SBtype == I_BehaviourInanimateObject)
762 		||(sbPtr->I_SBtype == I_BehaviourRubberDuck)) {
763 		return 0;
764 	}
765 
766 	if (sbPtr->SBflags.not_on_motiontracker) {
767 		return(0);
768 	}
769 
770 	/* KJL 12:46:28 21/08/98 - objects which need more checks */
771 	if (sbPtr->I_SBtype == I_BehaviourNetGhost)
772 	{
773 		NETGHOSTDATABLOCK *ghostData;
774 
775 		ghostData = (NETGHOSTDATABLOCK *)sbPtr->SBdataptr;
776 		LOCALASSERT(ghostData);
777 
778 		if((ghostData->type == I_BehaviourAlienPlayer)
779 		 &&(objectDynPtr->Position.vx == objectDynPtr->PrevPosition.vx)
780 		 &&(objectDynPtr->Position.vy == objectDynPtr->PrevPosition.vy)
781 		 &&(objectDynPtr->Position.vz == objectDynPtr->PrevPosition.vz))
782 			return 0;
783 	}
784 	else if (sbPtr->I_SBtype == I_BehaviourAlien)
785 	{
786 		ALIEN_STATUS_BLOCK * statusPtr = (ALIEN_STATUS_BLOCK *)sbPtr->SBdataptr;
787 
788    		if(statusPtr->BehaviourState == ABS_Dormant)
789 			return 0;
790 	}
791 	else if (sbPtr->I_SBtype == I_BehaviourPlatform)
792 	{
793 		if((objectDynPtr->Position.vx == objectDynPtr->PrevPosition.vx)
794 		 &&(objectDynPtr->Position.vy == objectDynPtr->PrevPosition.vy)
795 		 &&(objectDynPtr->Position.vz == objectDynPtr->PrevPosition.vz))
796 			return 0;
797 	}
798 	else if (sbPtr->I_SBtype == I_BehaviourProximityDoor)
799 	{
800 		PROXDOOR_BEHAV_BLOCK *doorbhv;
801 		doorbhv = (PROXDOOR_BEHAV_BLOCK*)sbPtr->SBdataptr;
802 		if (doorbhv->door_state == I_door_open || doorbhv->door_state == I_door_closed)
803 		{
804 			return 0;
805 		}
806 	}
807 
808 	return 1;
809 }
DoMotionTrackerBlips(void)810 static int DoMotionTrackerBlips(void)
811 {
812 	DYNAMICSBLOCK *playerDynPtr = Player->ObStrategyBlock->DynPtr;
813 	int numberOfObjects = NumActiveStBlocks;
814 	int cosPhi, sinPhi;
815 	int nearestDistance=MOTIONTRACKER_RANGE;
816 	{
817 		int phi = playerDynPtr->OrientEuler.EulerY;
818 		cosPhi = MUL_FIXED(GetCos(phi),MOTIONTRACKER_SCALE);
819 		sinPhi = MUL_FIXED(GetSin(phi),MOTIONTRACKER_SCALE);
820 	}
821 
822 	while (numberOfObjects--)
823 	{
824 		STRATEGYBLOCK *objectPtr = ActiveStBlockList[numberOfObjects];
825 		DYNAMICSBLOCK *objectDynPtr = objectPtr->DynPtr;
826 
827 		if (NoOfMTBlips==MOTIONTRACKER_MAXBLIPS) break;
828 
829   		if ((objectDynPtr)&&(!objectDynPtr->IsStatic || objectDynPtr->IsNetGhost)
830 			&&(ObjectShouldAppearOnMotionTracker(objectPtr)))
831 		{
832 		    /* 2d vector from player to object */
833 			int dx = objectDynPtr->Position.vx-playerDynPtr->Position.vx;
834 			int dz = objectDynPtr->Position.vz-playerDynPtr->Position.vz;
835 
836 			{
837 				int absdx=dx;
838 				int absdz=dz;
839 				if (absdx<0) absdx=-absdx;
840 				if (absdz<0) absdz=-absdz;
841 
842 				/* ignore objects past MT's detection distance */
843 				/* do quick box check */
844 				if (absdx>MOTIONTRACKER_RANGE || absdz>MOTIONTRACKER_RANGE)	continue;
845 			}
846 
847 			{
848 				int y = MUL_FIXED(dx,sinPhi) + MUL_FIXED(dz,cosPhi);
849 
850 				/* ignore objects 'behind' MT */
851 				if (y>=0)
852 				{
853 //				  	int x = MUL_FIXED(dx,cosPhi) - MUL_FIXED(dz,sinPhi);
854 					int dist = Fast2dMagnitude(dx,dz);
855 					int radius = MUL_FIXED(dist,MOTIONTRACKER_SCALE);
856 
857 					if (radius<=MTScanLineSize)
858 					{
859 						int prevRadius;
860 					 	{
861 							int dx = objectDynPtr->PrevPosition.vx-playerDynPtr->PrevPosition.vx;
862 							int dz = objectDynPtr->PrevPosition.vz-playerDynPtr->PrevPosition.vz;
863 							prevRadius = MUL_FIXED(Fast2dMagnitude(dx,dz),MOTIONTRACKER_SCALE);
864 						}
865 
866 						if ((radius>PreviousMTScanLineSize)
867 					 	  ||(radius<PreviousMTScanLineSize && prevRadius>PreviousMTScanLineSize))
868 						{
869 							/* remember distance for possible display on HUD */
870 							if (nearestDistance>dist) nearestDistance=dist;
871 
872 							/* create new blip */
873 				//			MotionTrackerBlips[NoOfMTBlips].X = x;
874 				//			MotionTrackerBlips[NoOfMTBlips].Y = y;
875 							MotionTrackerBlips[NoOfMTBlips].X = objectDynPtr->Position.vx;
876 							MotionTrackerBlips[NoOfMTBlips].Y = objectDynPtr->Position.vz;
877 							MotionTrackerBlips[NoOfMTBlips].Brightness = 65536;
878 						 	NoOfMTBlips++;
879 						 }
880 					}
881 				}
882 			}
883 		}
884 	}
885 	return nearestDistance;
886 }
887 
DisplayHealthAndArmour(void)888 static void DisplayHealthAndArmour(void)
889 {
890 	int health,armour;
891     /* access the extra data hanging off the strategy block */
892 	PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
893 	NPC_DATA *NpcData = NULL;
894 
895 	switch (AvP.PlayerType)
896 	{
897 		case I_Marine:
898 			switch (AvP.Difficulty) {
899 				case I_Easy:
900 					NpcData=GetThisNpcData(I_PC_Marine_Easy);
901 					break;
902 				default:
903 				case I_Medium:
904 					NpcData=GetThisNpcData(I_PC_Marine_Medium);
905 					break;
906 				case I_Hard:
907 					NpcData=GetThisNpcData(I_PC_Marine_Hard);
908 					break;
909 				case I_Impossible:
910 					NpcData=GetThisNpcData(I_PC_Marine_Impossible);
911 					break;
912 			}
913 			break;
914 		case I_Alien:
915 			switch (AvP.Difficulty) {
916 				case I_Easy:
917 					NpcData=GetThisNpcData(I_PC_Alien_Easy);
918 					break;
919 				default:
920 				case I_Medium:
921 					NpcData=GetThisNpcData(I_PC_Alien_Medium);
922 					break;
923 				case I_Hard:
924 					NpcData=GetThisNpcData(I_PC_Alien_Hard);
925 					break;
926 				case I_Impossible:
927 					NpcData=GetThisNpcData(I_PC_Alien_Impossible);
928 					break;
929 			}
930 			break;
931 		default:
932 			LOCALASSERT(0);
933 	}
934     GLOBALASSERT(playerStatusPtr);
935 
936 	health=(PlayerStatusPtr->Health*100)/NpcData->StartingStats.Health;
937 	armour=(PlayerStatusPtr->Armour*100)/NpcData->StartingStats.Armour;
938 
939 	health = (health+65535)>>16;
940 	armour = (armour+65535)>>16;
941 
942 	if(PlayerStatusPtr->Health<(NpcData->StartingStats.Health<<16))
943 	{
944 		//make sure health isn't displayed as 100 , if it is even slightly below.
945 		//(ie round down 99.5 , even though health is rounded up normally)
946 		health = min(health,99);
947 	}
948 	if(PlayerStatusPtr->Armour<(NpcData->StartingStats.Armour<<16))
949 	{
950 		//similarly for armour
951 		armour = min(armour,99);
952 	}
953 
954 	Render_HealthAndArmour(health,armour);
955 
956 }
957 
DisplayMarinesAmmo(void)958 static void DisplayMarinesAmmo(void)
959 {
960 	PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
961 	PLAYER_WEAPON_DATA *weaponPtr;
962 	TEMPLATE_WEAPON_DATA *twPtr;
963 	int primaryRounds, secondaryRounds;
964 
965     /* init a pointer to the weapon's data */
966     weaponPtr = &(playerStatusPtr->WeaponSlot[playerStatusPtr->SelectedWeaponSlot]);
967     twPtr = &TemplateWeapon[weaponPtr->WeaponIDNumber];
968 
969 	primaryRounds=weaponPtr->PrimaryRoundsRemaining>>16;
970     if ( (weaponPtr->PrimaryRoundsRemaining&0xffff) ) primaryRounds+=1;
971 	secondaryRounds=weaponPtr->SecondaryRoundsRemaining>>16;
972     if ( (weaponPtr->SecondaryRoundsRemaining&0xffff) ) secondaryRounds+=1;
973 
974 	if (primaryRounds>HUD_PrimaryRounds)
975 	{
976 		HUD_PrimaryRounds += NormalFrameTime/512;
977 	}
978 	if (primaryRounds<HUD_PrimaryRounds)
979 	{
980 		HUD_PrimaryRounds = primaryRounds;
981 	}
982 	if (secondaryRounds>HUD_SecondaryRounds)
983 	{
984 		HUD_SecondaryRounds += NormalFrameTime/512;
985 	}
986 	if (secondaryRounds<HUD_SecondaryRounds)
987 	{
988 		HUD_SecondaryRounds = secondaryRounds;
989 	}
990 
991 
992 	{
993 		enum AMMO_ID ammo;
994 
995 		if (weaponPtr->WeaponIDNumber == WEAPON_GRENADELAUNCHER)
996 		{
997 			ammo = GrenadeLauncherData.SelectedAmmo;
998 		}
999 		else
1000 		{
1001 			ammo = twPtr->PrimaryAmmoID;
1002 		}
1003 	    Render_MarineAmmo
1004 	    (
1005 	    	TemplateAmmo[ammo].ShortName,
1006 	    	TEXTSTRING_MAGAZINES,
1007 	    	weaponPtr->PrimaryMagazinesRemaining,
1008 	    	TEXTSTRING_ROUNDS,
1009 	    	HUD_PrimaryRounds,
1010 			1
1011 	    );
1012 	}
1013 	if (weaponPtr->WeaponIDNumber == WEAPON_PULSERIFLE)
1014 	{
1015         Render_MarineAmmo
1016         (
1017         	TemplateAmmo[twPtr->SecondaryAmmoID].ShortName,
1018         	TEXTSTRING_MAGAZINES,
1019         	weaponPtr->SecondaryMagazinesRemaining,
1020         	TEXTSTRING_ROUNDS,
1021         	HUD_SecondaryRounds,
1022 			0
1023         );
1024 	}
1025 
1026 	if (weaponPtr->WeaponIDNumber == WEAPON_TWO_PISTOLS)
1027 	{
1028         Render_MarineAmmo
1029         (
1030         	TemplateAmmo[twPtr->SecondaryAmmoID].ShortName,
1031         	TEXTSTRING_MAGAZINES,
1032         	weaponPtr->SecondaryMagazinesRemaining,
1033         	TEXTSTRING_ROUNDS,
1034         	HUD_SecondaryRounds,
1035 			0
1036         );
1037 	}
1038 
1039 }
1040 
HandleMarineWeapon(void)1041 static void HandleMarineWeapon(void)
1042 {
1043 	PLAYER_WEAPON_DATA *weaponPtr;
1044 	TEMPLATE_WEAPON_DATA *twPtr;
1045 
1046 	    /* access the extra data hanging off the strategy block */
1047 	PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
1048     GLOBALASSERT(playerStatusPtr);
1049 
1050 	{
1051 		/* player's current weapon */
1052     	GLOBALASSERT(playerStatusPtr->SelectedWeaponSlot<MAX_NO_OF_WEAPON_SLOTS);
1053 
1054         /* init a pointer to the weapon's data */
1055         weaponPtr = &(playerStatusPtr->WeaponSlot[playerStatusPtr->SelectedWeaponSlot]);
1056         twPtr = &TemplateWeapon[weaponPtr->WeaponIDNumber];
1057     }
1058 
1059 	/* draw 3d weapon */
1060 	PositionPlayersWeapon();
1061 
1062 
1063 	/* if there is no shape name then return */
1064 	if (twPtr->WeaponShapeName == NULL) return;
1065 	RenderThisDisplayblock(&PlayersWeapon);
1066 
1067 	if ((twPtr->MuzzleFlashShapeName != NULL)
1068 	  &&(!twPtr->PrimaryIsMeleeWeapon)
1069 	  &&( (weaponPtr->CurrentState == WEAPONSTATE_FIRING_PRIMARY)
1070 	   	||( (weaponPtr->WeaponIDNumber==WEAPON_MARINE_PISTOL)&&(weaponPtr->CurrentState == WEAPONSTATE_FIRING_SECONDARY) )
1071 	   	||( (weaponPtr->WeaponIDNumber==WEAPON_TWO_PISTOLS)&&(weaponPtr->CurrentState == WEAPONSTATE_FIRING_SECONDARY) ) ) )
1072 		PositionPlayersWeaponMuzzleFlash();
1073 
1074 	{
1075 
1076 
1077 		if ((twPtr->MuzzleFlashShapeName != NULL)
1078 		  	   &&(!twPtr->PrimaryIsMeleeWeapon)
1079 		  	   &&((weaponPtr->CurrentState == WEAPONSTATE_FIRING_PRIMARY)
1080 		  	   	||((weaponPtr->WeaponIDNumber==WEAPON_MARINE_PISTOL)&&(weaponPtr->CurrentState == WEAPONSTATE_FIRING_SECONDARY))
1081 		  	   	||((weaponPtr->WeaponIDNumber==WEAPON_TWO_PISTOLS)&&(weaponPtr->CurrentState == WEAPONSTATE_FIRING_SECONDARY) )))
1082 		{
1083 			static int onThisFrame=1;
1084 			if(onThisFrame || !twPtr->PrimaryIsRapidFire)
1085 			{
1086 				VECTORCH direction;
1087 
1088 				direction.vx = PlayersWeaponMuzzleFlash.ObMat.mat31;
1089 				direction.vy = PlayersWeaponMuzzleFlash.ObMat.mat32;
1090 				direction.vz = PlayersWeaponMuzzleFlash.ObMat.mat33;
1091 
1092 				if (weaponPtr->WeaponIDNumber==WEAPON_SMARTGUN)
1093 				{
1094 					DrawMuzzleFlash(&PlayersWeaponMuzzleFlash.ObWorld,&direction,MUZZLE_FLASH_SMARTGUN);
1095 				}
1096 				else if (weaponPtr->WeaponIDNumber==WEAPON_FRISBEE_LAUNCHER)
1097 				{
1098 					DrawMuzzleFlash(&PlayersWeaponMuzzleFlash.ObWorld,&direction,MUZZLE_FLASH_SKEETER);
1099 				}
1100 				else
1101 				{
1102 					DrawMuzzleFlash(&PlayersWeaponMuzzleFlash.ObWorld,&direction,MUZZLE_FLASH_AMORPHOUS);
1103 					#if 0
1104 					{
1105 						int i = 5;
1106 						VECTORCH velocity = direction;
1107 						velocity.vx >>= 9;
1108 						velocity.vy >>= 9;
1109 						velocity.vz >>= 9;
1110 						do
1111 						{
1112 							VECTORCH position = PlayersWeaponMuzzleFlash.ObWorld;
1113 							position.vx += (FastRandom()&15)-8;
1114 							position.vy += (FastRandom()&15)-8;
1115 							position.vz += (FastRandom()&15)-8;
1116 							MakeParticle(&position,&velocity,PARTICLE_GUNMUZZLE_SMOKE);
1117 						}
1118 						while(--i);
1119 					}
1120 					#endif
1121 				}
1122 			}
1123 			onThisFrame=!onThisFrame;
1124 		//	RenderThisDisplayblock(&PlayersWeaponMuzzleFlash);
1125 		}
1126 
1127 	}
1128 
1129 	/* handle smart targeting */
1130     SmartTarget(twPtr->SmartTargetSpeed,0);
1131 
1132 	/* aim gun sight */
1133     {
1134     	int aimingSpeed=twPtr->GunCrosshairSpeed * NormalFrameTime;
1135         AimGunSight(aimingSpeed,twPtr);
1136 	}
1137 }
1138 
DrawMarineSights(void)1139 static void DrawMarineSights(void)
1140 {
1141 	/* draw standard crosshairs */
1142 	if (MIRROR_CHEATMODE)
1143 	{
1144  		BLTGunSightToScreen(ScreenDescriptorBlock.SDB_Width - (GunMuzzleSightX>>16), GunMuzzleSightY>>16, GUNSIGHT_CROSSHAIR);
1145 	}
1146 	else
1147 	{
1148 	 	BLTGunSightToScreen(GunMuzzleSightX>>16, GunMuzzleSightY>>16, GUNSIGHT_CROSSHAIR);
1149 	}
1150 
1151 	/* draw smart target sights if required */
1152 	{
1153 	    /* access the extra data hanging off the strategy block */
1154 		PLAYER_STATUS *playerStatusPtr = (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
1155 		PLAYER_WEAPON_DATA *weaponPtr = &(playerStatusPtr->WeaponSlot[playerStatusPtr->SelectedWeaponSlot]);
1156 
1157 	    if (TemplateWeapon[weaponPtr->WeaponIDNumber].IsSmartTarget)
1158 	    {
1159 			if (MIRROR_CHEATMODE)
1160 			{
1161 		     	if (CurrentlySmartTargetingObject)	/* tracking target so use the red box */
1162 		     	{
1163 		     		BLTGunSightToScreen(ScreenDescriptorBlock.SDB_Width - (SmartTargetSightX>>16),SmartTargetSightY>>16,GUNSIGHT_REDBOX);
1164 				}
1165 				else /* not tracking anything, use green box */
1166 				{
1167 				   	BLTGunSightToScreen(ScreenDescriptorBlock.SDB_Width - (SmartTargetSightX>>16),SmartTargetSightY>>16,GUNSIGHT_GREENBOX);
1168 				}
1169 			}
1170 			else
1171 			{
1172 		     	if (CurrentlySmartTargetingObject)	/* tracking target so use the red box */
1173 		     	{
1174 		     		BLTGunSightToScreen(SmartTargetSightX>>16,SmartTargetSightY>>16,GUNSIGHT_REDBOX);
1175 				}
1176 				else /* not tracking anything, use green box */
1177 				{
1178 				   	BLTGunSightToScreen(SmartTargetSightX>>16,SmartTargetSightY>>16,GUNSIGHT_GREENBOX);
1179 				}
1180 			}
1181 	    }
1182 	}
1183 }
1184 
1185 
1186 
1187 /*KJL****************************************
1188 * ************** PREDATOR HUD ************* *
1189 ****************************************KJL*/
1190 
InitPredatorHUD(void)1191 static void InitPredatorHUD(void)
1192 {
1193 	PlatformSpecificInitPredatorHUD();
1194 
1195 	SmartTarget_Object=NULL;
1196 	Old_SmartTarget_Object=NULL;
1197 	InitialiseGrapplingHook();
1198 }
1199 
1200 #if DO_PREDATOR_OVERLAY
1201 
UpdatePredatorStatusValues(void)1202 static void UpdatePredatorStatusValues(void)
1203 {
1204 	PLAYER_WEAPON_DATA *weaponPtr;
1205 
1206     /* access the extra data hanging off the strategy block */
1207 	PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
1208     GLOBALASSERT(playerStatusPtr);
1209 
1210 	{
1211 		/* player's current weapon */
1212     	GLOBALASSERT(playerStatusPtr->SelectedWeaponSlot<MAX_NO_OF_WEAPON_SLOTS);
1213 
1214         /* init a pointer to the weapon's data */
1215         weaponPtr = &(playerStatusPtr->WeaponSlot[playerStatusPtr->SelectedWeaponSlot]);
1216     }
1217 
1218 
1219 	{
1220     	int value=WideMulNarrowDiv(playerStatusPtr->Health,45,6553600);
1221 
1222         if (value>=37)
1223         {
1224         	ValueOfHUDDigit[PREDATOR_HUD_HEALTH_5]= value-36;
1225 			ValueOfHUDDigit[PREDATOR_HUD_HEALTH_4]= 9;
1226 			ValueOfHUDDigit[PREDATOR_HUD_HEALTH_3]= 9;
1227 			ValueOfHUDDigit[PREDATOR_HUD_HEALTH_2]= 9;
1228 			ValueOfHUDDigit[PREDATOR_HUD_HEALTH_1]= 9;
1229 		}
1230 		else if (value>=28)
1231         {
1232         	ValueOfHUDDigit[PREDATOR_HUD_HEALTH_5]=	0;
1233 			ValueOfHUDDigit[PREDATOR_HUD_HEALTH_4]= value-27;
1234 			ValueOfHUDDigit[PREDATOR_HUD_HEALTH_3]= 9;
1235 			ValueOfHUDDigit[PREDATOR_HUD_HEALTH_2]= 9;
1236 			ValueOfHUDDigit[PREDATOR_HUD_HEALTH_1]= 9;
1237 		}
1238 		else if (value>=19)
1239         {
1240         	ValueOfHUDDigit[PREDATOR_HUD_HEALTH_5]= 0;
1241 			ValueOfHUDDigit[PREDATOR_HUD_HEALTH_4]= 0;
1242 			ValueOfHUDDigit[PREDATOR_HUD_HEALTH_3]= value-18;
1243 			ValueOfHUDDigit[PREDATOR_HUD_HEALTH_2]= 9;
1244 			ValueOfHUDDigit[PREDATOR_HUD_HEALTH_1]= 9;
1245 		}
1246 		else if (value>=10)
1247         {
1248         	ValueOfHUDDigit[PREDATOR_HUD_HEALTH_5]= 0;
1249 			ValueOfHUDDigit[PREDATOR_HUD_HEALTH_4]= 0;
1250 			ValueOfHUDDigit[PREDATOR_HUD_HEALTH_3]= 0;
1251 			ValueOfHUDDigit[PREDATOR_HUD_HEALTH_2]= value-9;
1252 			ValueOfHUDDigit[PREDATOR_HUD_HEALTH_1]= 9;
1253 		}
1254 		else
1255 		{
1256         	ValueOfHUDDigit[PREDATOR_HUD_HEALTH_5]= 0;
1257 			ValueOfHUDDigit[PREDATOR_HUD_HEALTH_4]= 0;
1258 			ValueOfHUDDigit[PREDATOR_HUD_HEALTH_3]= 0;
1259 			ValueOfHUDDigit[PREDATOR_HUD_HEALTH_2]= 0;
1260 			ValueOfHUDDigit[PREDATOR_HUD_HEALTH_1]= value;
1261 		}
1262 	}
1263 	{
1264     	int value=WideMulNarrowDiv(playerStatusPtr->Armour,45,6553600);
1265 
1266         if (value>=37)
1267         {
1268         	ValueOfHUDDigit[PREDATOR_HUD_ARMOUR_5]= value-36;
1269 			ValueOfHUDDigit[PREDATOR_HUD_ARMOUR_4]= 9;
1270 			ValueOfHUDDigit[PREDATOR_HUD_ARMOUR_3]= 9;
1271 			ValueOfHUDDigit[PREDATOR_HUD_ARMOUR_2]= 9;
1272 			ValueOfHUDDigit[PREDATOR_HUD_ARMOUR_1]= 9;
1273 		}
1274 		else if (value>=28)
1275         {
1276         	ValueOfHUDDigit[PREDATOR_HUD_ARMOUR_5]=	0;
1277 			ValueOfHUDDigit[PREDATOR_HUD_ARMOUR_4]= value-27;
1278 			ValueOfHUDDigit[PREDATOR_HUD_ARMOUR_3]= 9;
1279 			ValueOfHUDDigit[PREDATOR_HUD_ARMOUR_2]= 9;
1280 			ValueOfHUDDigit[PREDATOR_HUD_ARMOUR_1]= 9;
1281 		}
1282 		else if (value>=19)
1283         {
1284         	ValueOfHUDDigit[PREDATOR_HUD_ARMOUR_5]= 0;
1285 			ValueOfHUDDigit[PREDATOR_HUD_ARMOUR_4]= 0;
1286 			ValueOfHUDDigit[PREDATOR_HUD_ARMOUR_3]= value-18;
1287 			ValueOfHUDDigit[PREDATOR_HUD_ARMOUR_2]= 9;
1288 			ValueOfHUDDigit[PREDATOR_HUD_ARMOUR_1]= 9;
1289 		}
1290 		else if (value>=10)
1291         {
1292         	ValueOfHUDDigit[PREDATOR_HUD_ARMOUR_5]= 0;
1293 			ValueOfHUDDigit[PREDATOR_HUD_ARMOUR_4]= 0;
1294 			ValueOfHUDDigit[PREDATOR_HUD_ARMOUR_3]= 0;
1295 			ValueOfHUDDigit[PREDATOR_HUD_ARMOUR_2]= value-9;
1296 			ValueOfHUDDigit[PREDATOR_HUD_ARMOUR_1]= 9;
1297 		}
1298 		else
1299 		{
1300         	ValueOfHUDDigit[PREDATOR_HUD_ARMOUR_5]= 0;
1301 			ValueOfHUDDigit[PREDATOR_HUD_ARMOUR_4]= 0;
1302 			ValueOfHUDDigit[PREDATOR_HUD_ARMOUR_3]= 0;
1303 			ValueOfHUDDigit[PREDATOR_HUD_ARMOUR_2]= 0;
1304 			ValueOfHUDDigit[PREDATOR_HUD_ARMOUR_1]= value;
1305 		}
1306 	}
1307 
1308 #if 0
1309 	{
1310     	int value=playerStatusPtr->Energy>>16;	/* stored in 16.16 so shift down */
1311         ValueOfHUDDigit[MARINE_HUD_ENERGY_UNITS]=value%10;
1312 		value/=10;
1313         ValueOfHUDDigit[MARINE_HUD_ENERGY_TENS]=value%10;
1314         value/=10;
1315 		ValueOfHUDDigit[MARINE_HUD_ENERGY_HUNDREDS]=value%10;
1316 	}
1317 	{
1318     	int value=weaponPtr->RoundsRemaining>>16;
1319         /* ammo is in 16.16. we want the integer part, rounded up */
1320         if ( (weaponPtr->RoundsRemaining&0xffff) ) value+=1;
1321 
1322         ValueOfHUDDigit[MARINE_HUD_AMMO_ROUNDS_UNITS]=value%10;
1323 		value/=10;
1324         ValueOfHUDDigit[MARINE_HUD_AMMO_ROUNDS_TENS]=value%10;
1325         value/=10;
1326 		ValueOfHUDDigit[MARINE_HUD_AMMO_ROUNDS_HUNDREDS]=value%10;
1327 	}
1328 	{
1329     	int value=weaponPtr->MagazinesRemaining;
1330         ValueOfHUDDigit[MARINE_HUD_AMMO_MAGAZINES_UNITS]=value%10;
1331 		value/=10;
1332         ValueOfHUDDigit[MARINE_HUD_AMMO_MAGAZINES_TENS]=value%10;
1333     }
1334 #endif
1335 
1336 }
1337 
1338 #endif
1339 
DisplayPredatorHealthAndEnergy(void)1340 void DisplayPredatorHealthAndEnergy(void)
1341 {
1342 	PLAYER_WEAPON_DATA *weaponPtr = &(PlayerStatusPtr->WeaponSlot[PlayerStatusPtr->SelectedWeaponSlot]);
1343 	int value;
1344 	int i;
1345 	int scale = DIV_FIXED(ScreenDescriptorBlock.SDB_Width,640);
1346 	int size = MUL_FIXED(51,scale);
1347 	{
1348 		NPC_DATA *NpcData;
1349 		switch (AvP.Difficulty) {
1350 			case I_Easy:
1351 				NpcData=GetThisNpcData(I_PC_Predator_Easy);
1352 				break;
1353 			default:
1354 			case I_Medium:
1355 				NpcData=GetThisNpcData(I_PC_Predator_Medium);
1356 				break;
1357 			case I_Hard:
1358 				NpcData=GetThisNpcData(I_PC_Predator_Hard);
1359 				break;
1360 			case I_Impossible:
1361 				NpcData=GetThisNpcData(I_PC_Predator_Impossible);
1362 				break;
1363 		}
1364 		LOCALASSERT(NpcData);
1365 		value=MUL_FIXED(PlayerStatusPtr->Health/NpcData->StartingStats.Health,59);
1366 	}
1367 	for (i=0; i<6; i++)
1368 	{
1369 		HUDCharDesc charDesc;
1370 		charDesc.X = 0;
1371 		charDesc.Y = i*size;
1372 
1373 		charDesc.Red = 255;
1374 		charDesc.Green = 0;
1375 		charDesc.Blue = 0;
1376 		charDesc.Alpha= 255;
1377 
1378 		{
1379 			int v=value-i*9;
1380 			if (v>9) v=9;
1381 			else if (v<0) v=0;
1382 			charDesc.Character=v;
1383 		}
1384 
1385 		D3D_DrawHUDPredatorDigit(&charDesc,scale);
1386 	}
1387 	value= MUL_FIXED(DIV_FIXED(PlayerStatusPtr->FieldCharge,PLAYERCLOAK_MAXENERGY),59);
1388 	for (i=0; i<6; i++)
1389 	{
1390 		HUDCharDesc charDesc;
1391 		charDesc.X = ScreenDescriptorBlock.SDB_Width-size;
1392 		charDesc.Y = i*size;
1393 
1394 		charDesc.Red = 0;
1395 		charDesc.Green = 255;
1396 		charDesc.Blue = 255;
1397 		charDesc.Alpha= 255;
1398 
1399 		{
1400 			int v=value-i*9;
1401 			if (v>9) v=9;
1402 			else if (v<0) v=0;
1403 			charDesc.Character=v;
1404 		}
1405 
1406 		D3D_DrawHUDPredatorDigit(&charDesc,scale);
1407 	}
1408 	if (weaponPtr->WeaponIDNumber == WEAPON_PRED_RIFLE)
1409 	{
1410 		value = weaponPtr->PrimaryRoundsRemaining>>16;
1411 		for (i=0; i<4; i++)
1412 		{
1413 			HUDCharDesc charDesc;
1414 			charDesc.X = i*size/2;
1415 			charDesc.Y = ScreenDescriptorBlock.SDB_Height-size/2;
1416 
1417 			charDesc.Red = 0;
1418 			charDesc.Green = 0;
1419 			charDesc.Blue = 255;
1420 			charDesc.Alpha= 255;
1421 
1422 			{
1423 				int v=value-i*9;
1424 				if (v>9) v=9;
1425 				else if (v<0) v=0;
1426 				charDesc.Character=v;
1427 			}
1428 
1429 			D3D_DrawHUDPredatorDigit(&charDesc,scale/2);
1430 		}
1431 	}
1432 
1433 }
1434 #if 0
1435 static void DoPredatorThreatDisplay(void)
1436 {
1437 	/* evaluate the distance digits */
1438 	{
1439     	int value=WideMulNarrowDiv(FindPredatorThreats(),72,MOTIONTRACKER_RANGE);
1440 
1441         if (value>=64)
1442         {
1443         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_8]= value-63;
1444         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_7]= 9;
1445         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_6]= 9;
1446         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_5]= 9;
1447 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_4]= 9;
1448 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_3]= 9;
1449 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_2]= 9;
1450 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_1]= 9;
1451 		}
1452         else if (value>=55)
1453         {
1454         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_8]= 0;
1455         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_7]= value-54;
1456         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_6]= 9;
1457         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_5]= 9;
1458 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_4]= 9;
1459 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_3]= 9;
1460 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_2]= 9;
1461 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_1]= 9;
1462 		}
1463         else if (value>=46)
1464         {
1465         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_8]= 0;
1466         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_7]= 0;
1467         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_6]= value-45;
1468         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_5]= 9;
1469 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_4]= 9;
1470 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_3]= 9;
1471 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_2]= 9;
1472 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_1]= 9;
1473 		}
1474         else if (value>=37)
1475         {
1476         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_8]= 0;
1477         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_7]= 0;
1478         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_6]= 0;
1479         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_5]= value-36;
1480 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_4]= 9;
1481 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_3]= 9;
1482 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_2]= 9;
1483 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_1]= 9;
1484 		}
1485 		else if (value>=28)
1486         {
1487         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_8]= 0;
1488         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_7]= 0;
1489         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_6]= 0;
1490         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_5]=	0;
1491 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_4]= value-27;
1492 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_3]= 9;
1493 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_2]= 9;
1494 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_1]= 9;
1495 		}
1496 		else if (value>=19)
1497         {
1498         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_8]= 0;
1499         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_7]= 0;
1500         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_6]= 0;
1501         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_5]= 0;
1502 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_4]= 0;
1503 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_3]= value-18;
1504 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_2]= 9;
1505 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_1]= 9;
1506 		}
1507 		else if (value>=10)
1508         {
1509         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_8]= 0;
1510         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_7]= 0;
1511         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_6]= 0;
1512         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_5]= 0;
1513 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_4]= 0;
1514 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_3]= 0;
1515 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_2]= value-9;
1516 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_1]= 9;
1517 		}
1518 		else
1519 		{
1520         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_8]= 0;
1521         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_7]= 0;
1522         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_6]= 0;
1523         	ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_5]= 0;
1524 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_4]= 0;
1525 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_3]= 0;
1526 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_2]= 0;
1527 			ValueOfHUDDigit[PREDATOR_HUD_THREATDISPLAY_1]= value;
1528 		}
1529 	}
1530 
1531 
1532 	return;
1533 }
1534 
1535 
1536 static int FindPredatorThreats(void)
1537 {
1538 	DYNAMICSBLOCK *playerDynPtr = Player->ObStrategyBlock->DynPtr;
1539 	int numberOfObjects = NumActiveStBlocks;
1540 	int nearestDistance=MOTIONTRACKER_RANGE;
1541 
1542 	while (numberOfObjects--)
1543 	{
1544 		STRATEGYBLOCK *objectPtr = ActiveStBlockList[numberOfObjects];
1545 		DYNAMICSBLOCK *objectDynPtr = objectPtr->DynPtr;
1546 
1547 		if (objectPtr == Player->ObStrategyBlock) continue;
1548 
1549   		if (objectDynPtr)
1550 		{
1551 		    /* 2d vector from player to object */
1552 			int dx = objectDynPtr->Position.vx-playerDynPtr->Position.vx;
1553 			int dz = objectDynPtr->Position.vz-playerDynPtr->Position.vz;
1554 			int dy = objectDynPtr->Position.vy-playerDynPtr->Position.vy;
1555 
1556 			if (dy > -2000 || dy <2000)
1557 			{
1558 				int dist = Fast2dMagnitude(dx,dz);
1559 				/* remember distance for possible display on HUD */
1560 				if (nearestDistance>dist) nearestDistance=dist;
1561 
1562 			}
1563 		}
1564 	}
1565 	return nearestDistance;
1566 }
1567 #endif
HandlePredatorWeapon(void)1568 static void HandlePredatorWeapon(void)
1569 {
1570 	PLAYER_WEAPON_DATA *weaponPtr;
1571 	TEMPLATE_WEAPON_DATA *twPtr;
1572 
1573     /* access the extra data hanging off the strategy block */
1574 	PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
1575     GLOBALASSERT(playerStatusPtr);
1576 
1577 	{
1578 		/* player's current weapon */
1579     	GLOBALASSERT(playerStatusPtr->SelectedWeaponSlot<MAX_NO_OF_WEAPON_SLOTS);
1580 
1581         /* init a pointer to the weapon's data */
1582         weaponPtr = &(playerStatusPtr->WeaponSlot[playerStatusPtr->SelectedWeaponSlot]);
1583         twPtr = &TemplateWeapon[weaponPtr->WeaponIDNumber];
1584     }
1585 
1586 	//PositionPlayersWeapon();
1587 
1588 	{
1589 		extern void RenderThisDisplayblock(DISPLAYBLOCK *dbPtr);
1590 
1591 		/* draw 3d muzzle flash */
1592 		if ((twPtr->MuzzleFlashShapeName != NULL)
1593 		  &&(!twPtr->PrimaryIsMeleeWeapon)
1594 		  &&(weaponPtr->CurrentState == WEAPONSTATE_FIRING_PRIMARY) )
1595 			RenderThisDisplayblock(&PlayersWeaponMuzzleFlash);
1596 
1597 		/* draw 3d weapon */
1598 		if (twPtr->WeaponShapeName != NULL)
1599 			RenderThisDisplayblock(&PlayersWeapon);
1600 
1601 	}
1602 	if (twPtr->PrimaryIsMeleeWeapon)
1603 	{
1604 		GunMuzzleSightX = (ScreenDescriptorBlock.SDB_Width<<15);
1605 		GunMuzzleSightY = (ScreenDescriptorBlock.SDB_Height<<15);
1606 	}
1607 	else
1608 	{
1609 	    SmartTarget(twPtr->SmartTargetSpeed,ONE_FIXED);
1610 
1611 		/* aim gun sight */
1612 		if (weaponPtr->WeaponIDNumber == WEAPON_PRED_SHOULDERCANNON)
1613 		{
1614 			if (PredSight_LockOnTime)
1615 			{
1616 				GunMuzzleSightX = (ScreenDescriptorBlock.SDB_Width<<15);
1617 				GunMuzzleSightY = (ScreenDescriptorBlock.SDB_Height<<15);
1618 			}
1619 			else
1620 			{
1621 				GunMuzzleSightX = SmartTargetSightX;
1622 				GunMuzzleSightY = SmartTargetSightY;
1623 			}
1624 		}
1625 		else
1626 	    {
1627 	    	int aimingSpeed=twPtr->GunCrosshairSpeed * NormalFrameTime;
1628 	        AimGunSight(aimingSpeed,twPtr);
1629 		}
1630 	}
1631 
1632 }
1633 
DrawPredatorSights(void)1634 static void DrawPredatorSights(void)
1635 {
1636 	/* access the extra data hanging off the strategy block */
1637 	PLAYER_STATUS *playerStatusPtr = (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
1638 	PLAYER_WEAPON_DATA *weaponPtr = &(playerStatusPtr->WeaponSlot[playerStatusPtr->SelectedWeaponSlot]);
1639 
1640 	/* Enforce quiet unless we've got the plasmacaster. */
1641 	if (weaponPtr->WeaponIDNumber!=WEAPON_PRED_SHOULDERCANNON) {
1642   		if(predHUDSoundHandle != SOUND_NOACTIVEINDEX) {
1643        		Sound_Stop(predHUDSoundHandle);
1644 		}
1645 	} else {
1646 		/* Think about plasmacaster HUD sounds! */
1647 		textprint("PredSight_LockOnTime %d\n",PredSight_LockOnTime);
1648 		if ((PredSight_LockOnTime==0)
1649 			&&(weaponPtr->CurrentState!=WEAPONSTATE_SWAPPING_IN)
1650 			&&(weaponPtr->CurrentState!=WEAPONSTATE_READYING)
1651 			&&(SmartTarget_Object)) {
1652 			/* We must be locked on and steady. */
1653   			if(predHUDSoundHandle != SOUND_NOACTIVEINDEX) {
1654 				if (ActiveSounds[predHUDSoundHandle].soundIndex!=SID_PREDATOR_PLASMACASTER_TARGET_LOCKED) {
1655 		       		Sound_Stop(predHUDSoundHandle);
1656 				}
1657 			}
1658   			if(predHUDSoundHandle == SOUND_NOACTIVEINDEX) {
1659 	  			Sound_Play(SID_PREDATOR_PLASMACASTER_TARGET_LOCKED,"elh",&predHUDSoundHandle);
1660 			}
1661 		} else {
1662 			/* Not locked on - don't be looping! */
1663 	  		if(predHUDSoundHandle != SOUND_NOACTIVEINDEX) {
1664 	       		Sound_Stop(predHUDSoundHandle);
1665 				/* We were locked on... */
1666 				Sound_Play(SID_PREDATOR_PLASMACASTER_TARGET_LOST,"h");
1667 			}
1668 		}
1669 	}
1670 
1671     if (TemplateWeapon[weaponPtr->WeaponIDNumber].IsSmartTarget)
1672     {
1673 		/* ChrisF 19/2/99 Changed this to prevent 'instant' re-targetting. */
1674 		if ((SmartTarget_Object==NULL)||(SmartTarget_Object!=Old_SmartTarget_Object))
1675 		{
1676 			PredSight_LockOnTime = PREDATOR_LOCK_ON_TIME;
1677 			PredSight_Angle = 0;
1678 			/* Think about sound... */
1679 			if (SmartTarget_Object) {
1680 				Sound_Play(SID_PREDATOR_PLASMACASTER_REDTRIANGLES,"h");
1681 			}
1682 		}
1683 		else
1684 		{
1685 			int segmentScale=PredSight_LockOnTime;
1686 
1687 
1688 			if (segmentScale<=ONE_FIXED)
1689 			{
1690 				RenderPredatorTargetingSegment((PredSight_Angle+1365*2)&4095, segmentScale, PredSight_LockOnTime);
1691 			}
1692 
1693 			segmentScale -= PREDATOR_LOCK_ON_TIME/5;
1694 			if (segmentScale<0) segmentScale = 0;
1695 			if (segmentScale<=ONE_FIXED)
1696 			{
1697 				RenderPredatorTargetingSegment((PredSight_Angle+1365)&4095, segmentScale, PredSight_LockOnTime);
1698 			}
1699 
1700 			segmentScale -= PREDATOR_LOCK_ON_TIME/5;
1701 			if (segmentScale<0) segmentScale = 0;
1702 			if (segmentScale>ONE_FIXED) segmentScale = ONE_FIXED;
1703 
1704 	  		RenderPredatorTargetingSegment(PredSight_Angle, segmentScale, PredSight_LockOnTime);
1705 
1706 			if (PredSight_LockOnTime>0)
1707 			{
1708 				PredSight_LockOnTime -= NormalFrameTime*PREDATOR_LOCK_ON_SPEED;
1709 
1710 				if (PredSight_LockOnTime<0)
1711 				{
1712 					PredSight_LockOnTime = 0;
1713 					/* Locked on - play a sound. */
1714 					if (weaponPtr->WeaponIDNumber==WEAPON_PRED_DISC) {
1715 						Sound_Play(SID_PREDATOR_DISK_TARGET_LOCKED,"h");
1716 					} else if (weaponPtr->WeaponIDNumber==WEAPON_PRED_SHOULDERCANNON) {
1717 						Sound_Play(SID_PREDATOR_PLASMACASTER_TARGET_FOUND,"h");
1718 					}
1719 				}
1720 			}
1721 			else
1722 			{
1723 				PredSight_Angle += (NormalFrameTime>>6);
1724 				PredSight_Angle &= 4095;
1725 			}
1726 		}
1727 	}
1728 	{
1729 		extern int HUDFontsImageNumber;
1730 	  	HUDImageDesc imageDesc;
1731 
1732 		imageDesc.ImageNumber = HUDFontsImageNumber;
1733 		imageDesc.TopLeftX = (ScreenDescriptorBlock.SDB_Width-16)/2;
1734 		imageDesc.TopLeftY = (ScreenDescriptorBlock.SDB_Height-14)/2;
1735 		imageDesc.TopLeftU = 1;
1736 		imageDesc.TopLeftV = 51;
1737 		imageDesc.Height = 15;
1738 		imageDesc.Width = 17;
1739 		imageDesc.Scale = ONE_FIXED;
1740 		imageDesc.Translucency = 255;
1741 		imageDesc.Red = 255;
1742 		imageDesc.Green = 255;
1743 		imageDesc.Blue = 255;
1744 
1745 		Draw_HUDImage(&imageDesc);
1746 	}
1747 }
DrawWristDisplay(void)1748 void DrawWristDisplay(void)
1749 {
1750 	extern HMODELCONTROLLER PlayersWeaponHModelController;
1751 	SECTION_DATA *sectionPtr;
1752 
1753  	char *sectionName[]= {"Dum bar display","Dum 1 display","Dum 2 display","Dum 3 display","Dum 4 display"};
1754 
1755  	sectionPtr=GetThisSectionData(PlayersWeaponHModelController.section_data,sectionName[0]);
1756 	if (!sectionPtr) return;
1757 
1758 	RenderPredatorPlasmaCasterCharge(PlayerStatusPtr->PlasmaCasterCharge, &sectionPtr->World_Offset, &sectionPtr->SecMat);
1759 	#if 0
1760    	for (int i=0; i<5; i++)
1761    	{
1762    		DECAL CurrentDecal;
1763 		extern MODULE *playerPherModule;
1764 		int z= 0,halfWidth=50,halfHeight=50;
1765 
1766 
1767  		sectionPtr=GetThisSectionData(PlayersWeaponHModelController.section_data,sectionName[i]);
1768 		if (!sectionPtr) return;
1769 
1770 		CurrentDecal.DecalID = DECAL_PREDATOR_BLOOD;
1771 
1772  		CurrentDecal.Vertices[0].vx = -halfWidth;
1773 		CurrentDecal.Vertices[0].vz = -halfHeight;
1774 		CurrentDecal.Vertices[0].vy = z;
1775 		RotateVector(&(CurrentDecal.Vertices[0]),&sectionPtr->SecMat);
1776 		CurrentDecal.Vertices[0].vx += sectionPtr->World_Offset.vx;
1777 		CurrentDecal.Vertices[0].vy += sectionPtr->World_Offset.vy;
1778 		CurrentDecal.Vertices[0].vz += sectionPtr->World_Offset.vz;
1779 
1780 
1781 		CurrentDecal.Vertices[1].vx = halfWidth;
1782 		CurrentDecal.Vertices[1].vz = -halfHeight;
1783 		CurrentDecal.Vertices[1].vy = z;
1784 		RotateVector(&(CurrentDecal.Vertices[1]),&sectionPtr->SecMat);
1785 		CurrentDecal.Vertices[1].vx += sectionPtr->World_Offset.vx;
1786 		CurrentDecal.Vertices[1].vy += sectionPtr->World_Offset.vy;
1787 		CurrentDecal.Vertices[1].vz += sectionPtr->World_Offset.vz;
1788 
1789 		CurrentDecal.Vertices[2].vx = halfWidth;
1790 		CurrentDecal.Vertices[2].vz = halfHeight;
1791 		CurrentDecal.Vertices[2].vy = z;
1792 		RotateVector(&(CurrentDecal.Vertices[2]),&sectionPtr->SecMat);
1793 		CurrentDecal.Vertices[2].vx += sectionPtr->World_Offset.vx;
1794 		CurrentDecal.Vertices[2].vy += sectionPtr->World_Offset.vy;
1795 		CurrentDecal.Vertices[2].vz += sectionPtr->World_Offset.vz;
1796 
1797 		CurrentDecal.Vertices[3].vx = -halfWidth;
1798 		CurrentDecal.Vertices[3].vz = halfHeight;
1799 		CurrentDecal.Vertices[3].vy = z;
1800 		RotateVector(&(CurrentDecal.Vertices[3]),&sectionPtr->SecMat);
1801 		CurrentDecal.Vertices[3].vx += sectionPtr->World_Offset.vx;
1802 		CurrentDecal.Vertices[3].vy += sectionPtr->World_Offset.vy;
1803 		CurrentDecal.Vertices[3].vz += sectionPtr->World_Offset.vz;
1804 
1805 		CurrentDecal.ModuleIndex = playerPherModule->m_index;
1806 
1807 		CurrentDecal.UOffset = 0;
1808 
1809 		RenderDecal(&CurrentDecal);
1810 	}
1811 	#endif
1812 }
RotateVertex(VECTOR2D * vertexPtr,int theta)1813 void RotateVertex(VECTOR2D *vertexPtr, int theta)
1814 {
1815 	int vx,vy;
1816 	int sin = GetSin(theta);
1817 	int cos = GetCos(theta);
1818 
1819 	vx = MUL_FIXED(vertexPtr->vx,cos) - MUL_FIXED(vertexPtr->vy,sin);
1820 	vy = MUL_FIXED(vertexPtr->vx,sin) + MUL_FIXED(vertexPtr->vy,cos);
1821 
1822 	vertexPtr->vx = vx;
1823 	vertexPtr->vy = vy;
1824 }
1825 
1826 
1827 
1828 /*KJL********
1829 * ALIEN HUD *
1830 ********KJL*/
1831 
HandleAlienWeapon(void)1832 static void HandleAlienWeapon(void)
1833 {
1834 	PLAYER_WEAPON_DATA *weaponPtr;
1835 	TEMPLATE_WEAPON_DATA *twPtr;
1836 	extern int Alien_Visible_Weapon;
1837 
1838     /* access the extra data hanging off the strategy block */
1839 	PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
1840     GLOBALASSERT(playerStatusPtr);
1841 
1842 	{
1843 		/* player's current weapon */
1844     	GLOBALASSERT(playerStatusPtr->SelectedWeaponSlot<MAX_NO_OF_WEAPON_SLOTS);
1845 
1846         /* init a pointer to the weapon's data */
1847         weaponPtr = &(playerStatusPtr->WeaponSlot[playerStatusPtr->SelectedWeaponSlot]);
1848         twPtr = &TemplateWeapon[weaponPtr->WeaponIDNumber];
1849     }
1850 
1851 	//PositionPlayersWeapon();
1852 
1853 	{
1854 		extern void RenderThisDisplayblock(DISPLAYBLOCK *dbPtr);
1855 
1856 		/* draw 3d muzzle flash */
1857 		if ((twPtr->MuzzleFlashShapeName != NULL)
1858 		  &&(!twPtr->PrimaryIsMeleeWeapon)
1859 		  &&(weaponPtr->CurrentState == WEAPONSTATE_FIRING_PRIMARY) )
1860 			RenderThisDisplayblock(&PlayersWeaponMuzzleFlash);
1861 
1862 		/* draw 3d weapon */
1863 		/* if there is no shape name then return */
1864 		if (twPtr->WeaponShapeName == NULL) return;
1865 			RenderThisDisplayblock(&PlayersWeapon);
1866 
1867 	}
1868 	//if ((twPtr->PrimaryIsMeleeWeapon)&&
1869 	if ((weaponPtr->WeaponIDNumber == WEAPON_ALIEN_CLAW)&&(Alien_Visible_Weapon==0))
1870 	{
1871 		GunMuzzleSightX = (ScreenDescriptorBlock.SDB_Width<<15);
1872 		GunMuzzleSightY = (ScreenDescriptorBlock.SDB_Height<<15);
1873 	}
1874 	else
1875 	{
1876 	    SmartTarget(twPtr->SmartTargetSpeed,0);
1877 		/* aim gun sight */
1878 	    {
1879 	    	int aimingSpeed=twPtr->GunCrosshairSpeed * NormalFrameTime;
1880 	        AimGunSight(aimingSpeed,twPtr);
1881 		}
1882 	}
1883 
1884 }
1885 
1886 #if DO_ALIEN_OVERLAY
1887 
UpdateAlienStatusValues(void)1888 static void UpdateAlienStatusValues(void)
1889 {
1890     /* access the extra data hanging off the strategy block */
1891 	PLAYER_STATUS *playerStatusPtr= (PLAYER_STATUS *) (Player->ObStrategyBlock->SBdataptr);
1892     GLOBALASSERT(playerStatusPtr);
1893 	{
1894     	int value=playerStatusPtr->Health>>16;	/* stored in 16.16 so shift down */
1895         ValueOfHUDDigit[ALIEN_HUD_HEALTH_UNITS]=value%10;
1896 		value/=10;
1897         ValueOfHUDDigit[ALIEN_HUD_HEALTH_TENS]=value%10;
1898         value/=10;
1899 		ValueOfHUDDigit[ALIEN_HUD_HEALTH_HUNDREDS]=value%10;
1900 	}
1901 }
1902 
1903 #endif
1904 
DrawAlienTeeth(void)1905 static void DrawAlienTeeth(void)
1906 {
1907 	/* KJL 14:51:00 08/10/98 - test if bite attack is possible */
1908 	{
1909 		extern STRATEGYBLOCK *GetBitingTarget(void);
1910 		if(GetBitingTarget())
1911 		{
1912 			if (AlienTeethOffset<ONE_FIXED)
1913 			{
1914 				AlienTeethOffset += NormalFrameTime*2;
1915 			}
1916 			if (AlienTeethOffset>ONE_FIXED)
1917 			{
1918 				AlienTeethOffset = ONE_FIXED;
1919 			}
1920 		}
1921 		else
1922 		{
1923 			if (AlienTeethOffset>0)
1924 			{
1925 				AlienTeethOffset -= NormalFrameTime;
1926 			}
1927 			if (AlienTeethOffset<0)
1928 			{
1929 				AlienTeethOffset = 0;
1930 			}
1931 		}
1932 	}
1933 
1934 	if (AlienTeethOffset)
1935 	{
1936 		int offsetY;
1937 
1938 	   	DISPLAYBLOCK displayblock;
1939 
1940 	   	displayblock.ObMat=Global_VDB_Ptr->VDB_Mat;
1941 		TransposeMatrixCH(&displayblock.ObMat);
1942 	   	displayblock.name=NULL;
1943 	   	displayblock.ObEuler.EulerX=0;
1944 	   	displayblock.ObEuler.EulerY=0;
1945 	   	displayblock.ObEuler.EulerZ=0;
1946 	   	displayblock.ObFlags=ObFlag_ArbRot;
1947 	   	displayblock.ObFlags2=0;
1948 	   	displayblock.ObFlags3=0;
1949 	   	displayblock.ObNumLights=0;
1950 	   	displayblock.ObRadius=0;
1951 	   	displayblock.ObMaxX=0;
1952 	   	displayblock.ObMinX=0;
1953 	   	displayblock.ObMaxY=0;
1954 	   	displayblock.ObMinY=0;
1955 	   	displayblock.ObMaxZ=0;
1956 	   	displayblock.ObMinZ=0;
1957 	   	displayblock.ObTxAnimCtrlBlks=NULL;
1958 	   	displayblock.ObEIDPtr=NULL;
1959 	   	displayblock.ObMorphCtrl=NULL;
1960 	   	displayblock.ObStrategyBlock=NULL;
1961 	   	displayblock.ShapeAnimControlBlock=NULL;
1962 	   	displayblock.HModelControlBlock=NULL;
1963 	   	displayblock.ObMyModule=NULL;
1964 	   	displayblock.SpecialFXFlags = 0;
1965 	   	displayblock.SfxPtr=0;
1966 
1967 	   	offsetY = MUL_FIXED(GetSin(AlienTeethOffset/64),80);
1968 
1969 
1970 
1971 	   	displayblock.ObShape=GetLoadedShapeMSL("uppertuth@tongue");
1972 	   	displayblock.ObWorld.vx = 0;
1973 	   	displayblock.ObWorld.vy = -200+offsetY;
1974 	   	displayblock.ObWorld.vz = 80;
1975 	   	displayblock.ObView = displayblock.ObWorld;
1976 	   	{
1977 	   		MATRIXCH myMat = Global_VDB_Ptr->VDB_Mat;
1978 	   		TransposeMatrixCH(&myMat);
1979 	   		RotateVector(&(displayblock.ObWorld), &(myMat));
1980 	   		displayblock.ObWorld.vx += Global_VDB_Ptr->VDB_World.vx;
1981 	   		displayblock.ObWorld.vy += Global_VDB_Ptr->VDB_World.vy;
1982 	   		displayblock.ObWorld.vz += Global_VDB_Ptr->VDB_World.vz;
1983 	   	}
1984 
1985 		RenderThisDisplayblock(&displayblock);
1986 
1987 	   	displayblock.ObShape=GetLoadedShapeMSL("lowertuth@tongue");
1988 	   	displayblock.ObWorld.vx = 0;
1989 	   	displayblock.ObWorld.vy = 200-offsetY;
1990 	   	displayblock.ObWorld.vz = 80;
1991 	   	displayblock.ObView = displayblock.ObWorld;
1992 	   	{
1993 	   		MATRIXCH myMat = Global_VDB_Ptr->VDB_Mat;
1994 	   		TransposeMatrixCH(&myMat);
1995 	   		RotateVector(&(displayblock.ObWorld), &(myMat));
1996 	   		displayblock.ObWorld.vx += Global_VDB_Ptr->VDB_World.vx;
1997 	   		displayblock.ObWorld.vy += Global_VDB_Ptr->VDB_World.vy;
1998 	   		displayblock.ObWorld.vz += Global_VDB_Ptr->VDB_World.vz;
1999 	   	}
2000 
2001 		RenderThisDisplayblock(&displayblock);
2002 	}
2003 
2004 
2005 }
2006 
2007 
2008 
2009 /*KJL**************
2010 * Some useful fns *
2011 **************KJL*/
2012 
2013 /* returns approx. magnitude */
Fast2dMagnitude(int dx,int dy)2014 int Fast2dMagnitude(int dx, int dy)
2015 {
2016 	if (dx<0) dx = -dx;
2017 	if (dy<0) dy = -dy;
2018 
2019 	if (dx>dy)
2020 		return dx+dy/3;
2021 	else
2022 		return dy+dx/3;
2023 }
2024 
2025 
2026 
2027 /*KJL*************************
2028 * On screen messaging system *
2029 *************************KJL*/
2030 
NewOnScreenMessage(unsigned char * messagePtr)2031 extern void NewOnScreenMessage(unsigned char *messagePtr)
2032 {
2033 	GADGET_NewOnScreenMessage( messagePtr );
2034 }
2035 
AimGunSight(int aimingSpeed,TEMPLATE_WEAPON_DATA * twPtr)2036 static void AimGunSight(int aimingSpeed, TEMPLATE_WEAPON_DATA *twPtr)
2037 {
2038 	int dx,dy,mag;
2039 	int targetX,targetY;
2040     int boundary = twPtr->SmartTargetRadius*(ScreenDescriptorBlock.SDB_Height/2);
2041 
2042 	/* setup target */
2043     targetX = SmartTargetSightX;
2044     targetY = SmartTargetSightY;
2045 
2046     /* restrict target to a bounding box */
2047     {
2048     	int leftBoundary = (ScreenDescriptorBlock.SDB_Width<<15) - boundary;
2049         int rightBoundary = (ScreenDescriptorBlock.SDB_Width<<15) + boundary;
2050 
2051 	    if (targetX<leftBoundary) targetX=leftBoundary;
2052     	else if (targetX>rightBoundary)	targetX=rightBoundary;
2053     }
2054     {
2055     	int topBoundary = (ScreenDescriptorBlock.SDB_Height<<15) - boundary;
2056         int bottomBoundary = (ScreenDescriptorBlock.SDB_Height<<15) + boundary;
2057 
2058 	    if (targetY<topBoundary) targetY=topBoundary;
2059     	else if (targetY>bottomBoundary) targetY=bottomBoundary;
2060     }
2061 
2062     dx = targetX-GunMuzzleSightX;
2063   	dy = targetY-GunMuzzleSightY;
2064     mag = Fast2dMagnitude(dx,dy);
2065 
2066     /* return if no need to move sight */
2067 	if (mag==0) return;
2068 
2069     /* move the sight */
2070 	if (aimingSpeed)
2071 	{
2072 		dx = WideMulNarrowDiv(aimingSpeed,dx,mag);
2073 		dy = WideMulNarrowDiv(aimingSpeed,dy,mag);
2074 	    GunMuzzleSightX += dx;
2075 		GunMuzzleSightY += dy;
2076 
2077 	    /* if overshoot target, move sight back */
2078 		if ( (dx>0 && GunMuzzleSightX>targetX) || (dx<0 && GunMuzzleSightX<targetX)	)
2079 		{
2080 	    	GunMuzzleSightX = targetX;
2081 	    }
2082 		if ( (dy>0 && GunMuzzleSightY>targetY) || (dy<0 && GunMuzzleSightY<targetY)	)
2083 		{
2084 	    	GunMuzzleSightY = targetY;
2085 	    }
2086 	}
2087 	else
2088 	{
2089 		GunMuzzleSightX = targetX;
2090 		GunMuzzleSightY = targetY;
2091 	}
2092 	return;
2093 }
2094 
2095 /* returns approx. 9 times the magnitude of the vector */
Fast3dMagnitude(VECTORCH * v)2096 int Fast3dMagnitude(VECTORCH *v)
2097 {
2098 	int dx,dy,dz;
2099 
2100 	dx = v->vx;
2101 	if (dx<0) dx = -dx;
2102 
2103 	dy = v->vy;
2104 	if (dy<0) dy = -dy;
2105 
2106 	dz = v->vz*3;
2107 	if (dz<0) dz = -dz;
2108 
2109 	{
2110 		int temp;
2111 
2112 		if (dx>dy)
2113 			temp = 3*dx+dy;
2114 		else
2115 			temp = 3*dy+dx;
2116 
2117 		if (temp>dz)
2118 			return 3*temp+dz;
2119 		else
2120 			return 3*dz+temp;
2121 	}
2122 }
2123 
2124 static const float ZoomLevels[] = {1.0f,0.4f,0.1f,0.02f};
2125 
MaintainZoomingLevel(void)2126 void MaintainZoomingLevel(void)
2127 {
2128 	int i;
2129 	float deltaZoom;
2130 	float requestedZoomScale;
2131 
2132 	i = 0;
2133 	while (CameraZoomScale<=ZoomLevels[++i]);
2134 
2135 
2136 	deltaZoom = (ZoomLevels[i-1] - ZoomLevels[i])*(float)NormalFrameTime/32768.0f;
2137 //	textprint("deltaZoom %f, zone %d\n",deltaZoom,i);
2138 
2139    	requestedZoomScale = ZoomLevels[CameraZoomLevel];
2140 
2141 	if (requestedZoomScale<CameraZoomScale)
2142 	{
2143 		if (CameraZoomScale==ZoomLevels[i-1]) Sound_Play(SID_PRED_ZOOM_IN,"h");
2144 
2145 		CameraZoomScale -= deltaZoom;
2146 		if (CameraZoomScale<ZoomLevels[i]) CameraZoomScale = ZoomLevels[i];
2147 		DrawScanlineOverlay = 1;
2148 		ScanlineLevel = (CameraZoomScale - ZoomLevels[i-1])/(ZoomLevels[i]-ZoomLevels[i-1]);
2149 
2150 	}
2151 	else if (requestedZoomScale>CameraZoomScale)
2152 	{
2153 		#if 0
2154 		CameraZoomScale += deltaZoom;
2155 		if (requestedZoomScale<CameraZoomScale)
2156 		#endif
2157 		CameraZoomScale = requestedZoomScale;
2158 		DrawScanlineOverlay = 1;
2159 		ScanlineLevel=1.0f;
2160 		Sound_Play(SID_PRED_ZOOM_OUT,"h");
2161 	}
2162 	else
2163 	{
2164 		DrawScanlineOverlay = 0;
2165 	}
2166 
2167 //	textprint("ScanlineLevel %f\n",ScanlineLevel);
2168 
2169 
2170 }
2171