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, §ionPtr->World_Offset, §ionPtr->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]),§ionPtr->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]),§ionPtr->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]),§ionPtr->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]),§ionPtr->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