4b825dc642cb6eb9a060e54bf8d69288fbee4904ebd360ec63ec976c05699f3180e866b3f69e5472
 
 
1
#include "hud.h"
 
 
2
#include "system.h"
 
 
3
#include "stratdef.h"
 
 
4
#include "bh_types.h"
 
 
5
#include "weapons.h"
 
 
6
#include "psndplat.h"
 
 
7
#include "frustum.h"
 
 
8
#include "targeting.h"
 
 
9
#include "pldghost.h"
 
 
10
#include "npc_alien.h"
 
 
11
#include "kshape.h"
 
 
12
#include "userprofile.h"
 
 
13
#include <assert.h>
 
 
14
#include "lighting.h"
 
 
15
 
 
 
16
#define BrightWhite    0xffffffff
 
 
17
#define MarineGreen    ((255<<24)+(95<<16)+(179<<8)+(39))
 
 
18
#define MarineRed      ((255<<24)+(255<<16))
 
 
19
#define flare_hud_colour 0x5fffff00
 
 
20
 
 
 
21
#define PREDATOR_LOCK_ON_SPEED (3)
 
 
22
#define MOTIONTRACKERVOLUME (MUL_FIXED(VOLUME_MAX, MotionTrackerVolume))
 
 
23
#define MOTIONTRACKER_MAXBLIPS    10
 
 
24
 
 
 
25
void draw_no_hud() {}
 
 
26
extern void DoPlayersWeaponHModel(DISPLAYBLOCK *dptr);
 
 
27
extern void HUDQuad_Output(int imageNumber, struct VertexTag *quadVerticesPtr, unsigned int colour);
 
 
28
extern void FadeDownScreen(int brightness, int colour);
 
 
29
extern int GetLoadedShapeMSL(char const * shapename);
 
 
30
extern void RenderHUDString_Centred(char *stringPtr, int centreX, int y, int colour);
 
 
31
extern void RenderHUDNumber_Centred(unsigned int number,int x,int y,int colour);
 
 
32
extern void DrawNoiseOverlay(int t);
 
 
33
extern void RenderHUDString(const char *stringPtr,int x,int y,int colour);
 
 
34
extern void ScreenInversionOverlay();
 
 
35
 
 
 
36
extern SCREENDESCRIPTORBLOCK ScreenDescriptorBlock;
 
 
37
extern int SmartTargetSightX, SmartTargetSightY;
 
 
38
extern float CameraZoomScale;
 
 
39
extern int HUDImageNumber;
 
 
40
extern int SpecialFXImageNumber;
 
 
41
extern int HUDFontsImageNumber;
 
 
42
extern int AlienTeethOffset;
 
 
43
extern int AlienTongueOffset;
 
 
44
extern int PredatorNumbersImageNumber;
 
 
45
 
 
 
46
static int MTScanLineSize = MOTIONTRACKER_SMALLESTSCANLINESIZE;
 
 
47
static int PreviousMTScanLineSize = MOTIONTRACKER_SMALLESTSCANLINESIZE;
 
 
48
static int MTDelayBetweenScans = 0;
 
 
49
static int NoOfMTBlips = 0;
 
 
50
static int MTSoundHandle = SOUND_NOACTIVEINDEX;
 
 
51
static int MotionTrackerHalfWidth;
 
 
52
static int MotionTrackerTextureSize;
 
 
53
static int MotionTrackerCentreY;
 
 
54
static int MotionTrackerCentreX;
 
 
55
static int MT_BlipHeight;
 
 
56
static int MT_BlipWidth;
 
 
57
static int MotionTrackerScale;
 
 
58
static int MotionTrackerSpeed = ONE_FIXED*2;
 
 
59
static int MotionTrackerVolume = ONE_FIXED;
 
 
60
 
 
 
61
int cloakDebounce = 1;
 
 
62
int AlienBiteAttackInProgress = 0;
 
 
63
int predOVision_SoundHandle;
 
 
64
int PredatorVisionChangeCounter;
 
 
65
int HUDScaleFactor;
 
 
66
int CameraZoomLevel;
 
 
67
int predHUDSoundHandle = SOUND_NOACTIVEINDEX;
 
 
68
int GunMuzzleSightX, GunMuzzleSightY;
 
 
69
 
 
 
70
static const int HUDTranslucencyLevel = 64;
 
 
71
static const int CloakThreshold = (5 * ONE_FIXED);
 
 
72
static const int PredatorVisionThreshold = (3 * ONE_FIXED);
 
 
73
static const int CloakPowerOnDrain = (2 * ONE_FIXED);
 
 
74
static const int TrickleCharge = 20000;
 
 
75
 
 
 
76
static struct
 
 
77
{
 
 
78
    int X;
 
 
79
    int Y;
 
 
80
    int Brightness;
 
 
81
 
 
 
82
} MotionTrackerBlips[MOTIONTRACKER_MAXBLIPS];
 
 
83
 
 
 
84
static struct HUDImageDesc
 
 
85
{
 
 
86
    int ImageNumber;
 
 
87
 
 
 
88
    int TopLeftX;
 
 
89
    int TopLeftY;
 
 
90
 
 
 
91
    int TopLeftU;
 
 
92
    int TopLeftV;
 
 
93
 
 
 
94
    int Width;
 
 
95
    int Height;
 
 
96
 
 
 
97
    int Scale;
 
 
98
 
 
 
99
    uint8_t Red;
 
 
100
    uint8_t Green;
 
 
101
    uint8_t Blue;
 
 
102
    uint8_t Translucency; /* 0 == invisible, 255 == opaque */ 
 
 
103
 
 
 
104
} BlueBar;
 
 
105
 
 
 
106
struct HUDCharDesc
 
 
107
{
 
 
108
    char Character;
 
 
109
    int X;
 
 
110
    int Y;
 
 
111
 
 
 
112
    uint8_t Red;
 
 
113
    uint8_t Green;
 
 
114
    uint8_t Blue;
 
 
115
    uint8_t Alpha;
 
 
116
};
 
 
117
 
 
 
118
static void Draw_HUDImage(struct HUDImageDesc *imageDescPtr)
 
 
119
{
 
 
120
    struct VertexTag quadVertices[4];
 
 
121
    int scaledWidth;
 
 
122
    int scaledHeight;
 
 
123
 
 
 
124
    if (imageDescPtr->Scale == ONE_FIXED)
 
 
125
    {
 
 
126
        scaledWidth = imageDescPtr->Width;
 
 
127
        scaledHeight = imageDescPtr->Height;
 
 
128
    }
 
 
129
    else
 
 
130
    {
 
 
131
        scaledWidth = MUL_FIXED(imageDescPtr->Scale, imageDescPtr->Width);
 
 
132
        scaledHeight = MUL_FIXED(imageDescPtr->Scale, imageDescPtr->Height);
 
 
133
    }
 
 
134
 
 
 
135
    quadVertices[0].U = imageDescPtr->TopLeftU;
 
 
136
    quadVertices[0].V = imageDescPtr->TopLeftV;
 
 
137
 
 
 
138
    quadVertices[1].U = imageDescPtr->TopLeftU + imageDescPtr->Width;
 
 
139
    quadVertices[1].V = imageDescPtr->TopLeftV;
 
 
140
 
 
 
141
    quadVertices[2].U = imageDescPtr->TopLeftU + imageDescPtr->Width;
 
 
142
    quadVertices[2].V = imageDescPtr->TopLeftV + imageDescPtr->Height;
 
 
143
 
 
 
144
    quadVertices[3].U = imageDescPtr->TopLeftU;
 
 
145
    quadVertices[3].V = imageDescPtr->TopLeftV + imageDescPtr->Height;
 
 
146
 
 
 
147
    quadVertices[0].X = imageDescPtr->TopLeftX;
 
 
148
    quadVertices[0].Y = imageDescPtr->TopLeftY;
 
 
149
 
 
 
150
    quadVertices[1].X = imageDescPtr->TopLeftX + scaledWidth;
 
 
151
    quadVertices[1].Y = imageDescPtr->TopLeftY;
 
 
152
 
 
 
153
    quadVertices[2].X = imageDescPtr->TopLeftX + scaledWidth;
 
 
154
    quadVertices[2].Y = imageDescPtr->TopLeftY + scaledHeight;
 
 
155
 
 
 
156
    quadVertices[3].X = imageDescPtr->TopLeftX;
 
 
157
    quadVertices[3].Y = imageDescPtr->TopLeftY + scaledHeight;
 
 
158
 
 
 
159
    HUDQuad_Output(imageDescPtr->ImageNumber, quadVertices, RGBA_MAKE(imageDescPtr->Red, imageDescPtr->Green, imageDescPtr->Blue,
imageDescPtr->Translucency));
 
 
160
}
 
 
161
 
 
 
162
enum HUD_FONT
 
 
163
{
 
 
164
        MARINE_HUD_FONT_MT_SMALL,
 
 
165
        MARINE_HUD_FONT_MT_BIG,
 
 
166
};
 
 
167
 
 
 
168
static void BLTDigitToHUD(char digit, int x, int font)
 
 
169
{
 
 
170
 
 
 
171
static struct HUDFontDescTag
 
 
172
{
 
 
173
        int XOffset;
 
 
174
        int Height;
 
 
175
        int Width;
 
 
176
 
 
 
177
} const HUDFontDesc[] =
 
 
178
    {
 
 
179
        //MARINE_HUD_FONT_MT_SMALL,
 
 
180
        {
 
 
181
            232,//XOffset
 
 
182
            12,//Height
 
 
183
            8,//Width
 
 
184
        },
 
 
185
        //MARINE_HUD_FONT_MT_BIG,
 
 
186
        {
 
 
187
            241,//XOffset
 
 
188
            24,//Height
 
 
189
            14,//Width
 
 
190
        },
 
 
191
    };
 
 
192
 
 
 
193
    struct HUDImageDesc imageDesc;
 
 
194
    int y = -4;
 
 
195
 
 
 
196
    imageDesc.Scale = MotionTrackerScale;
 
 
197
    x = MUL_FIXED(x, MotionTrackerScale) + MotionTrackerCentreX;
 
 
198
    y = MUL_FIXED(y, MotionTrackerScale) + MotionTrackerCentreY;
 
 
199
    imageDesc.ImageNumber = HUDImageNumber;
 
 
200
    imageDesc.TopLeftX = x;
 
 
201
    imageDesc.TopLeftY = y;
 
 
202
    imageDesc.TopLeftU = HUDFontDesc[font].XOffset;
 
 
203
    imageDesc.TopLeftV = digit * (HUDFontDesc[font].Height + 1) + 1;
 
 
204
    imageDesc.Height = HUDFontDesc[font].Height;
 
 
205
    imageDesc.Width = HUDFontDesc[font].Width;
 
 
206
    imageDesc.Translucency = HUDTranslucencyLevel;
 
 
207
    imageDesc.Red = imageDesc.Green = imageDesc.Blue = 255;
 
 
208
 
 
 
209
    Draw_HUDImage(&imageDesc);
 
 
210
}
 
 
211
 
 
 
212
static void YClipMotionTrackerVertices(struct VertexTag *v1, struct VertexTag *v2)
 
 
213
{
 
 
214
    char vertex1Inside = 0,vertex2Inside = 0;
 
 
215
 
 
 
216
    if (v1->Y < 0)
 
 
217
        vertex1Inside = 1;
 
 
218
 
 
 
219
    if (v2->Y < 0)
 
 
220
        vertex2Inside = 1;
 
 
221
 
 
 
222
    /* if both vertices inside clip region no clipping required */
 
 
223
    if (vertex1Inside && vertex2Inside)
 
 
224
            return;
 
 
225
 
 
 
226
    /* if both vertices outside clip region no action required 
 
 
227
    (the other lines will be clipped) */
 
 
228
 
 
 
229
    if (!vertex1Inside && !vertex2Inside)
 
 
230
            return;
 
 
231
 
 
 
232
    /* okay, let's clip */
 
 
233
    if (vertex1Inside)
 
 
234
    {
 
 
235
        int lambda = DIV_FIXED(v1->Y,v2->Y - v1->Y);
 
 
236
 
 
 
237
        v2->X = v1->X - MUL_FIXED(v2->X - v1->X,lambda);
 
 
238
        v2->Y = 0;
 
 
239
 
 
 
240
        v2->U = v1->U - MUL_FIXED(v2->U - v1->U,lambda);
 
 
241
        v2->V = v1->V - MUL_FIXED(v2->V - v1->V,lambda);
 
 
242
    }
 
 
243
    else
 
 
244
    {
 
 
245
        int lambda = DIV_FIXED(v2->Y,v1->Y - v2->Y);
 
 
246
 
 
 
247
        v1->X = v2->X - MUL_FIXED(v1->X - v2->X,lambda);
 
 
248
        v1->Y = 0;
 
 
249
 
 
 
250
        v1->U = v2->U - MUL_FIXED(v1->U - v2->U,lambda);
 
 
251
        v1->V = v2->V - MUL_FIXED(v1->V - v2->V,lambda);
 
 
252
    }
 
 
253
}
 
 
254
 
 
 
255
static void BLTMotionTrackerToHUD(int scanLineSize)
 
 
256
{
 
 
257
    struct VertexTag quadVertices[4];
 
 
258
 
 
 
259
    BlueBar.TopLeftY = ScreenDescriptorBlock.SDB_Height - MUL_FIXED(MotionTrackerScale, 35);
 
 
260
    MotionTrackerCentreY = BlueBar.TopLeftY;
 
 
261
    MotionTrackerCentreX = MUL_FIXED(MotionTrackerScale, (BlueBar.Width / 2));
 
 
262
    BlueBar.Scale = MotionTrackerScale;
 
 
263
 
 
 
264
    int motionTrackerScaledHalfWidth = MUL_FIXED(MotionTrackerScale * 3, MotionTrackerHalfWidth / 2);
 
 
265
 
 
 
266
    int angle = 4095 - PlayerStatus.DisplayBlock->ObEuler.EulerY;
 
 
267
 
 
 
268
    int widthCos = MUL_FIXED ( motionTrackerScaledHalfWidth, GetCos(angle) );
 
 
269
    int widthSin = MUL_FIXED ( motionTrackerScaledHalfWidth, GetSin(angle) );
 
 
270
 
 
 
271
    /* I've put these -1s in here to help clipping 45 degree cases,
 
 
272
    where two vertices can end up around the clipping line of Y=0 */
 
 
273
    quadVertices[0].X = (-widthCos - (-widthSin));
 
 
274
    quadVertices[0].Y = (-widthSin + (-widthCos)) -1;
 
 
275
    quadVertices[0].U = 1;
 
 
276
    quadVertices[0].V = 1;
 
 
277
    quadVertices[1].X = (widthCos - (-widthSin));
 
 
278
    quadVertices[1].Y = (widthSin + (-widthCos)) -1;
 
 
279
    quadVertices[1].U = 1 + MotionTrackerTextureSize;
 
 
280
    quadVertices[1].V = 1;
 
 
281
    quadVertices[2].X = (widthCos - widthSin);
 
 
282
    quadVertices[2].Y = (widthSin + widthCos) -1;
 
 
283
    quadVertices[2].U = 1 + MotionTrackerTextureSize;
 
 
284
    quadVertices[2].V = 1 + MotionTrackerTextureSize;
 
 
285
    quadVertices[3].X = ((-widthCos) - widthSin);
 
 
286
    quadVertices[3].Y = ((-widthSin) + widthCos) -1;
 
 
287
    quadVertices[3].U = 1;                               
 
 
288
    quadVertices[3].V = 1 + MotionTrackerTextureSize;
 
 
289
 
 
 
290
    /* clip to Y<=0 */
 
 
291
    YClipMotionTrackerVertices(&quadVertices[0], &quadVertices[1]);
 
 
292
    YClipMotionTrackerVertices(&quadVertices[1], &quadVertices[2]);
 
 
293
    YClipMotionTrackerVertices(&quadVertices[2], &quadVertices[3]);
 
 
294
    YClipMotionTrackerVertices(&quadVertices[3], &quadVertices[0]);
 
 
295
 
 
 
296
    /* translate into screen coords */
 
 
297
    quadVertices[0].X += MotionTrackerCentreX;
 
 
298
    quadVertices[1].X += MotionTrackerCentreX;
 
 
299
    quadVertices[2].X += MotionTrackerCentreX;
 
 
300
    quadVertices[3].X += MotionTrackerCentreX;
 
 
301
    quadVertices[0].Y += MotionTrackerCentreY;
 
 
302
    quadVertices[1].Y += MotionTrackerCentreY;
 
 
303
    quadVertices[2].Y += MotionTrackerCentreY;
 
 
304
    quadVertices[3].Y += MotionTrackerCentreY;
 
 
305
 
 
 
306
    /* dodgy offset 'cos I'm not x clipping */
 
 
307
    if (quadVertices[0].X == -1)
 
 
308
        quadVertices[0].X = 0;
 
 
309
 
 
 
310
    if (quadVertices[1].X == -1)
 
 
311
        quadVertices[1].X = 0;
 
 
312
 
 
 
313
    if (quadVertices[2].X == -1)
 
 
314
        quadVertices[2].X = 0;
 
 
315
 
 
 
316
    if (quadVertices[3].X == -1)
 
 
317
        quadVertices[3].X = 0;
 
 
318
 
 
 
319
    /* check u & v are >0 */
 
 
320
    if (quadVertices[0].V < 0)
 
 
321
        quadVertices[0].V = 0;
 
 
322
 
 
 
323
    if (quadVertices[1].V < 0)
 
 
324
        quadVertices[1].V = 0;
 
 
325
 
 
 
326
    if (quadVertices[2].V < 0)
 
 
327
        quadVertices[2].V = 0;
 
 
328
 
 
 
329
    if (quadVertices[3].V < 0)
 
 
330
        quadVertices[3].V = 0;
 
 
331
 
 
 
332
    if (quadVertices[0].U < 0)
 
 
333
        quadVertices[0].U = 0;
 
 
334
 
 
 
335
    if (quadVertices[1].U < 0)
 
 
336
        quadVertices[1].U = 0;
 
 
337
 
 
 
338
    if (quadVertices[2].U < 0)
 
 
339
        quadVertices[2].U = 0;
 
 
340
 
 
 
341
    if (quadVertices[3].U < 0)
 
 
342
        quadVertices[3].U = 0;
 
 
343
 
 
 
344
    HUDQuad_Output(HUDImageNumber, quadVertices, RGBA_MAKE(255, 255, 255, HUDTranslucencyLevel));
 
 
345
 
 
 
346
    struct HUDImageDesc imageDesc;
 
 
347
 
 
 
348
    imageDesc.ImageNumber = HUDImageNumber;
 
 
349
    imageDesc.Scale = MUL_FIXED(MotionTrackerScale*3, scanLineSize/2);
 
 
350
    imageDesc.TopLeftX = MotionTrackerCentreX - MUL_FIXED(motionTrackerScaledHalfWidth, scanLineSize);
 
 
351
    imageDesc.TopLeftY = MotionTrackerCentreY - MUL_FIXED(motionTrackerScaledHalfWidth, scanLineSize);
 
 
352
    imageDesc.TopLeftU = 1;
 
 
353
    imageDesc.TopLeftV = 132;
 
 
354
    imageDesc.Height = 64;
 
 
355
    imageDesc.Width = 128;
 
 
356
    imageDesc.Red = imageDesc.Green = imageDesc.Blue = 255;
 
 
357
    imageDesc.Translucency = HUDTranslucencyLevel;
 
 
358
 
 
 
359
     Draw_HUDImage(&imageDesc);
 
 
360
 
 
 
361
    BlueBar.Translucency = HUDTranslucencyLevel;
 
 
362
    Draw_HUDImage(&BlueBar);
 
 
363
}
 
 
364
 
 
 
365
static void BLTMotionTrackerBlipToHUD(int x, int y, int brightness)
 
 
366
{
 
 
367
    struct HUDImageDesc imageDesc;
 
 
368
    int frame = (brightness * 5) / 65537;
 
 
369
    int motionTrackerScaledHalfWidth = MUL_FIXED(MotionTrackerScale * 3, MotionTrackerHalfWidth / 2);
 
 
370
 
 
 
371
    assert(brightness <= 65536);
 
 
372
    assert(frame >= 0 && frame < 5);
 
 
373
 
 
 
374
    frame = 4 - frame; // frames bloody wrong way round
 
 
375
    imageDesc.ImageNumber = HUDImageNumber;
 
 
376
    imageDesc.Scale = MUL_FIXED(MotionTrackerScale * 3, (brightness + ONE_FIXED)/4);
 
 
377
    imageDesc.TopLeftX = MotionTrackerCentreX - MUL_FIXED(MT_BlipWidth/2, imageDesc.Scale) + MUL_FIXED(x, motionTrackerScaledHalfWidth);
 
 
378
    imageDesc.TopLeftY = MotionTrackerCentreY - MUL_FIXED(MT_BlipHeight/2, imageDesc.Scale) - MUL_FIXED(y, motionTrackerScaledHalfWidth);
 
 
379
    imageDesc.TopLeftU = 227;
 
 
380
    imageDesc.TopLeftV = 187;
 
 
381
    imageDesc.Height = MT_BlipHeight;
 
 
382
    imageDesc.Width = MT_BlipWidth;
 
 
383
 
 
 
384
    int trans = MUL_FIXED(brightness * 2,HUDTranslucencyLevel);
 
 
385
 
 
 
386
    if (trans > 255) 
 
 
387
        trans = 255;
 
 
388
 
 
 
389
    imageDesc.Translucency = trans;
 
 
390
    imageDesc.Red = 255;
 
 
391
    imageDesc.Green = 255;
 
 
392
    imageDesc.Blue = 255;
 
 
393
 
 
 
394
    if (imageDesc.TopLeftX < 0) /* then we need to clip */
 
 
395
    {
 
 
396
        imageDesc.Width += imageDesc.TopLeftX;
 
 
397
        imageDesc.TopLeftU -= imageDesc.TopLeftX;
 
 
398
        imageDesc.TopLeftX = 0;
 
 
399
    }
 
 
400
 
 
 
401
    Draw_HUDImage(&imageDesc);
 
 
402
}
 
 
403
 
 
 
404
static void DrawHUDPredatorDigit(struct HUDCharDesc *charDescPtr, int scale)
 
 
405
{
 
 
406
    struct HUDImageDesc imageDesc;
 
 
407
 
 
 
408
    imageDesc.ImageNumber = PredatorNumbersImageNumber;
 
 
409
    imageDesc.TopLeftX = charDescPtr->X;
 
 
410
    imageDesc.TopLeftY = charDescPtr->Y;
 
 
411
 
 
 
412
    if (charDescPtr->Character < 5)
 
 
413
    {
 
 
414
        imageDesc.TopLeftU = charDescPtr->Character * 51;
 
 
415
        imageDesc.TopLeftV = 1;
 
 
416
    }
 
 
417
    else
 
 
418
    {
 
 
419
        imageDesc.TopLeftU = (charDescPtr->Character - 5) * 51;
 
 
420
        imageDesc.TopLeftV = 52;
 
 
421
    }
 
 
422
 
 
 
423
    imageDesc.Height = imageDesc.Width = 50;
 
 
424
    imageDesc.Scale = scale;
 
 
425
    imageDesc.Translucency = charDescPtr->Alpha;
 
 
426
    imageDesc.Red = charDescPtr->Red;
 
 
427
    imageDesc.Green = charDescPtr->Green;
 
 
428
    imageDesc.Blue = charDescPtr->Blue;
 
 
429
 
 
 
430
    Draw_HUDImage(&imageDesc);
 
 
431
}
 
 
432
 
 
 
433
static void BLTGunSightToHUD(int screenX, int screenY, int gunsightShape)
 
 
434
{
 
 
435
      struct HUDImageDesc imageDesc;
 
 
436
    static const int gunsightSize = 13;
 
 
437
 
 
 
438
    screenX = (screenX - (gunsightSize / 2));
 
 
439
      screenY = (screenY - (gunsightSize / 2));
 
 
440
 
 
 
441
    imageDesc.ImageNumber = HUDImageNumber;
 
 
442
    imageDesc.TopLeftX = screenX;
 
 
443
    imageDesc.TopLeftY = screenY;
 
 
444
    imageDesc.TopLeftU = 227;
 
 
445
    imageDesc.TopLeftV = 131 + (gunsightShape * (gunsightSize + 1) );
 
 
446
    imageDesc.Height = imageDesc.Width = gunsightSize;
 
 
447
    imageDesc.Scale = ONE_FIXED;
 
 
448
    imageDesc.Translucency = 128;
 
 
449
    imageDesc.Red = imageDesc.Green = imageDesc.Blue = 255;
 
 
450
 
 
 
451
    Draw_HUDImage(&imageDesc);
 
 
452
}
 
 
453
 
 
 
454
static void AlienHealth()
 
 
455
{
 
 
456
    struct VertexTag quadVertices[4];
 
 
457
    int scaledWidth;
 
 
458
    int health = (PlayerStatus.Health * 100) / PlayerStatus.StartingHealth;
 
 
459
 
 
 
460
    health = (health + 65535) >> 16;
 
 
461
 
 
 
462
    if (health < 100)
 
 
463
        scaledWidth = WideMulNarrowDiv(ScreenDescriptorBlock.SDB_Width, health, 100);
 
 
464
    else
 
 
465
        scaledWidth = ScreenDescriptorBlock.SDB_Width;
 
 
466
 
 
 
467
    int scaledHeight = scaledWidth / 32;
 
 
468
    int x = (ScreenDescriptorBlock.SDB_Width - scaledWidth) / 2;
 
 
469
    int y = ScreenDescriptorBlock.SDB_Height - ScreenDescriptorBlock.SDB_Width / 32 + x / 32;
 
 
470
 
 
 
471
    quadVertices[0].U = 8;
 
 
472
    quadVertices[0].V = 5;
 
 
473
    quadVertices[1].U = 57;//255;
 
 
474
    quadVertices[1].V = 5;
 
 
475
    quadVertices[2].U = 57;//255;
 
 
476
    quadVertices[2].V = 55;//255;
 
 
477
    quadVertices[3].U = 8;
 
 
478
    quadVertices[3].V = 55;//255;
 
 
479
 
 
 
480
    quadVertices[0].X = x;
 
 
481
    quadVertices[0].Y = y;
 
 
482
    quadVertices[1].X = x + scaledWidth;
 
 
483
    quadVertices[1].Y = y;
 
 
484
    quadVertices[2].X = x + scaledWidth;
 
 
485
    quadVertices[2].Y = y + scaledHeight;
 
 
486
    quadVertices[3].X = x;
 
 
487
    quadVertices[3].Y = y + scaledHeight;
 
 
488
 
 
 
489
    if (!PlayerStatus.CurrentLightAtPlayer)
 
 
490
    ;//    HUDQuad_Output (SpecialFXImageNumber, quadVertices, MarineRed);
 
 
491
    else
 
 
492
        HUDQuad_Output (SpecialFXImageNumber, quadVertices, 0xff003fff);
 
 
493
 
 
 
494
    health /= 2;
 
 
495
 
 
 
496
    if (health < 100)
 
 
497
    {
 
 
498
        if (health < 0)
 
 
499
            health = scaledWidth = 0;
 
 
500
        else
 
 
501
            scaledWidth = WideMulNarrowDiv(ScreenDescriptorBlock.SDB_Width, health, 100);
 
 
502
    }
 
 
503
    else
 
 
504
    {
 
 
505
        scaledWidth = ScreenDescriptorBlock.SDB_Width;
 
 
506
    }
 
 
507
 
 
 
508
    scaledHeight = scaledWidth / 32;
 
 
509
    x = (ScreenDescriptorBlock.SDB_Width - scaledWidth) / 2;
 
 
510
    y = ScreenDescriptorBlock.SDB_Height - ScreenDescriptorBlock.SDB_Width / 32 + x / 32;
 
 
511
 
 
 
512
    quadVertices[0].X = x;
 
 
513
    quadVertices[0].Y = y;
 
 
514
    quadVertices[1].X = x + scaledWidth;
 
 
515
    quadVertices[1].Y = y;
 
 
516
    quadVertices[2].X = x + scaledWidth;
 
 
517
    quadVertices[2].Y = y + scaledHeight;
 
 
518
    quadVertices[3].X = x;
 
 
519
    quadVertices[3].Y = y + scaledHeight;
 
 
520
 
 
 
521
    HUDQuad_Output (SpecialFXImageNumber, quadVertices, 0xffffffff);
 
 
522
}
 
 
523
 
 
 
524
static void PredatorHealthAndEnergy()
 
 
525
{
 
 
526
    int i = 0;
 
 
527
    int scale = DIV_FIXED(ScreenDescriptorBlock.SDB_Width, 640);
 
 
528
    int size = MUL_FIXED(51, scale);
 
 
529
        int value = MUL_FIXED(PlayerStatus.Health / PlayerStatus.StartingHealth, 59);
 
 
530
 
 
 
531
    for (; i < 6; i++)
 
 
532
    {
 
 
533
        struct HUDCharDesc charDesc;
 
 
534
        charDesc.X = 0;
 
 
535
        charDesc.Y = i * size;
 
 
536
 
 
 
537
        charDesc.Red = 255;
 
 
538
        charDesc.Green = 0;
 
 
539
        charDesc.Blue = 0;
 
 
540
        charDesc.Alpha= 255;
 
 
541
 
 
 
542
        int v = value - i * 9;
 
 
543
 
 
 
544
        if (v > 9)
 
 
545
            v = 9;
 
 
546
        else if (v < 0)
 
 
547
            v = 0;
 
 
548
 
 
 
549
        charDesc.Character = v;
 
 
550
 
 
 
551
        DrawHUDPredatorDigit(&charDesc, scale);
 
 
552
    }
 
 
553
 
 
 
554
    value = MUL_FIXED(DIV_FIXED(PlayerStatus.FieldCharge, PLAYERCLOAK_MAXENERGY), 59);
 
 
555
 
 
 
556
    for (i = 0; i < 6; i++)
 
 
557
    {
 
 
558
        struct HUDCharDesc charDesc;
 
 
559
        charDesc.X = ScreenDescriptorBlock.SDB_Width - size;            
 
 
560
        charDesc.Y = i * size;
 
 
561
 
 
 
562
        charDesc.Red = 0;
 
 
563
        charDesc.Green = charDesc.Blue = charDesc.Alpha = 255;
 
 
564
 
 
 
565
        int v = value - i * 9;
 
 
566
 
 
 
567
        if (v > 9)
 
 
568
            v = 9;
 
 
569
        else if (v < 0)
 
 
570
            v = 0;
 
 
571
 
 
 
572
        charDesc.Character = v;
 
 
573
 
 
 
574
        DrawHUDPredatorDigit(&charDesc,scale);
 
 
575
    }
 
 
576
}
 
 
577
 
 
 
578
void InitMarineHUD()
 
 
579
{
 
 
580
    MotionTrackerHalfWidth = 127 / 2;
 
 
581
    MotionTrackerTextureSize = 128;
 
 
582
 
 
 
583
    BlueBar.ImageNumber = HUDImageNumber;
 
 
584
    BlueBar.TopLeftX = 0;
 
 
585
    BlueBar.TopLeftY = ScreenDescriptorBlock.SDB_Height - 40;
 
 
586
    BlueBar.TopLeftU = 1;
 
 
587
    BlueBar.TopLeftV = 223;
 
 
588
    BlueBar.Red = BlueBar.Green = BlueBar.Blue = 255;
 
 
589
 
 
 
590
    BlueBar.Height = 32;
 
 
591
    BlueBar.Width = 204;
 
 
592
 
 
 
593
    MT_BlipHeight = MT_BlipWidth = 12;
 
 
594
 
 
 
595
    /* centre of motion tracker */
 
 
596
    MotionTrackerCentreY = BlueBar.TopLeftY;
 
 
597
    MotionTrackerCentreX = BlueBar.Width / 2;
 
 
598
    MotionTrackerScale = 65536;
 
 
599
 
 
 
600
    HUDScaleFactor = DIV_FIXED(ScreenDescriptorBlock.SDB_Width, 640);    
 
 
601
}
 
 
602
 
 
 
603
/* returns approx. magnitude */
 
 
604
static int Fast2dMagnitude(int dx, int dy)
 
 
605
{
 
 
606
    dx = abs(dx);
 
 
607
    dy = abs(dy);
 
 
608
 
 
 
609
    return (dx > dy) ? (dx + dy / 3) : (dy + dx / 3);
 
 
610
}
 
 
611
 
 
 
612
void centre_gunsight()
 
 
613
{
 
 
614
    SmartTargetSightX = GunMuzzleSightX = ScreenDescriptorBlock.SDB_Width << 15;
 
 
615
    SmartTargetSightY = GunMuzzleSightY = ScreenDescriptorBlock.SDB_Height << 15;
 
 
616
}
 
 
617
 
 
 
618
static void AimGunSight(int aimingSpeed)
 
 
619
{
 
 
620
    int boundary = 55000 * ScreenDescriptorBlock.SDB_CentreY;
 
 
621
    int targetX = SmartTargetSightX;
 
 
622
    int targetY = SmartTargetSightY;
 
 
623
 
 
 
624
    /* restrict target to a bounding box */
 
 
625
        int leftBoundary = (ScreenDescriptorBlock.SDB_Width << 15) - boundary;
 
 
626
        int rightBoundary = (ScreenDescriptorBlock.SDB_Width << 15) + boundary;
 
 
627
 
 
 
628
    if (targetX < leftBoundary)
 
 
629
        targetX = leftBoundary;
 
 
630
    else if (targetX > rightBoundary)
 
 
631
        targetX = rightBoundary;
 
 
632
 
 
 
633
        int topBoundary = (ScreenDescriptorBlock.SDB_Height << 15) - boundary;
 
 
634
        int bottomBoundary = (ScreenDescriptorBlock.SDB_Height << 15) + boundary;
 
 
635
 
 
 
636
    if (targetY < topBoundary)
 
 
637
        targetY = topBoundary;
 
 
638
    else if (targetY > bottomBoundary)
 
 
639
        targetY = bottomBoundary;
 
 
640
 
 
 
641
    int dx = targetX - GunMuzzleSightX;
 
 
642
    int dy = targetY - GunMuzzleSightY;
 
 
643
    int mag = Fast2dMagnitude(dx, dy);
 
 
644
 
 
 
645
    /* return if no need to move sight */
 
 
646
    if (!mag)
 
 
647
        return;
 
 
648
 
 
 
649
    dx = WideMulNarrowDiv(aimingSpeed, dx, mag);
 
 
650
    dy = WideMulNarrowDiv(aimingSpeed, dy, mag);
 
 
651
    GunMuzzleSightX += dx;
 
 
652
    GunMuzzleSightY += dy;
 
 
653
 
 
 
654
    /* if overshoot target, move sight back */
 
 
655
    if ( (dx > 0 && GunMuzzleSightX > targetX) || (dx < 0 && GunMuzzleSightX < targetX))
 
 
656
            GunMuzzleSightX = targetX;
 
 
657
 
 
 
658
    if ( (dy > 0 && GunMuzzleSightY > targetY) || (dy < 0 && GunMuzzleSightY < targetY))
 
 
659
            GunMuzzleSightY = targetY;
 
 
660
}
 
 
661
 
 
 
662
int weaponHandle = SOUND_NOACTIVEINDEX;
 
 
663
 
 
 
664
static void MarinesAmmo()
 
 
665
{
 
 
666
    const int xCentre = MUL_FIXED(HUDLayout_RightmostTextCentre, HUDScaleFactor) + ScreenDescriptorBlock.SDB_Width;
 
 
667
    const int uppertextplacement_y = ScreenDescriptorBlock.SDB_Height - MUL_FIXED(HUDScaleFactor, HUDLayout_Magazines_TopY);
 
 
668
    const int uppernumberplacement = ScreenDescriptorBlock.SDB_Height - MUL_FIXED(HUDScaleFactor, HUDLayout_Magazines_TopY - HUDLayout_Linespacing);
 
 
669
    const int lowertextplacement_y = ScreenDescriptorBlock.SDB_Height - MUL_FIXED(HUDScaleFactor, HUDLayout_Rounds_TopY - HUDLayout_Linespacing);
 
 
670
    const int lowernumberplacement_y = ScreenDescriptorBlock.SDB_Height - MUL_FIXED(HUDScaleFactor, HUDLayout_Rounds_TopY);
 
 
671
 
 
 
672
    switch(PlayerStatus.SelectedWeapon->WeaponIDNumber)
 
 
673
    {
 
 
674
        case WEAPON_PULSERIFLE:
 
 
675
        {
 
 
676
            int local_x = xCentre + MUL_FIXED(HUDScaleFactor, HUDLayout_RightmostTextCentre*2);
 
 
677
            RenderHUDNumber_Centred(PlayerStatus.SelectedWeapon->SecondaryRoundsRemaining, local_x, lowertextplacement_y, MarineRed);
 
 
678
            RenderHUDString_Centred("Grenades" , local_x, lowernumberplacement_y, BrightWhite);
 
 
679
 
 
 
680
            if(PlayerStatus.muzzle_flash)
 
 
681
            {
 
 
682
                DrawPlayersMuzzleFlash(MUZZLE_FLASH_AMORPHOUS);
 
 
683
                PlayerStatus.muzzle_flash = 0;
 
 
684
            }
 
 
685
        }
 
 
686
        break;
 
 
687
        case WEAPON_SMARTGUN:
 
 
688
        {
 
 
689
            //AimGunSight(160 * NormalFrameTime);
 
 
690
 
 
 
691
            if(PlayerStatus.muzzle_flash)
 
 
692
            {
 
 
693
                DrawPlayersMuzzleFlash(MUZZLE_FLASH_SMARTGUN);
 
 
694
                PlayerStatus.muzzle_flash = 0;
 
 
695
            }
 
 
696
 
 
 
697
            if(PlayerStatus.SmartGunMode)
 
 
698
            {
 
 
699
                if (SmartTarget(4, 0))
 
 
700
                {
 
 
701
                    if (CHEATMODE_MIRROR != UserProfile.active_bonus) // tracking target so use the red box
 
 
702
                    {
 
 
703
                        BLTGunSightToHUD(SmartTargetSightX >> 16, SmartTargetSightY >> 16, 2);
 
 
704
                        BLTGunSightToHUD(GunMuzzleSightX >> 16, GunMuzzleSightY >> 16, 0);
 
 
705
                    }
 
 
706
                    else
 
 
707
                    {
 
 
708
                        BLTGunSightToHUD(ScreenDescriptorBlock.SDB_Width - (SmartTargetSightX >> 16), SmartTargetSightY >> 16, 2);
 
 
709
                        BLTGunSightToHUD(ScreenDescriptorBlock.SDB_Width - (GunMuzzleSightX >> 16), GunMuzzleSightY >> 16, 0);
 
 
710
                    }
 
 
711
                }
 
 
712
                else
 
 
713
                {
 
 
714
                    if (CHEATMODE_MIRROR != UserProfile.active_bonus) // not tracking anything, use green box
 
 
715
                    {
 
 
716
                        BLTGunSightToHUD(SmartTargetSightX >> 16,SmartTargetSightY >> 16, 1);
 
 
717
                        BLTGunSightToHUD(GunMuzzleSightX >> 16, GunMuzzleSightY >> 16, 0);
 
 
718
                    }
 
 
719
                    else
 
 
720
                    {
 
 
721
                        BLTGunSightToHUD(ScreenDescriptorBlock.SDB_Width - (SmartTargetSightX >> 16), SmartTargetSightY >> 16, 1);
 
 
722
                        BLTGunSightToHUD(ScreenDescriptorBlock.SDB_Width - (GunMuzzleSightX >> 16), GunMuzzleSightY >> 16, 0);
 
 
723
                    }
 
 
724
                }
 
 
725
 
 
 
726
                RenderHUDString_Centred("track", xCentre, ScreenDescriptorBlock.SDB_Height - MUL_FIXED(HUDScaleFactor, HUDLayout_AmmoDesc_TopY),
BrightWhite);
 
 
727
            }
 
 
728
            else
 
 
729
            {
 
 
730
                SmartTargetSightX = GunMuzzleSightX = ScreenDescriptorBlock.SDB_Width << 15;
 
 
731
                SmartTargetSightY = GunMuzzleSightY = ScreenDescriptorBlock.SDB_Height << 15;
 
 
732
 
 
 
733
                if (CHEATMODE_MIRROR != UserProfile.active_bonus)
 
 
734
                {
 
 
735
                    BLTGunSightToHUD(SmartTargetSightX >> 16, SmartTargetSightY >> 16, 1);
 
 
736
                    BLTGunSightToHUD(GunMuzzleSightX >> 16, GunMuzzleSightY >> 16, 0);
 
 
737
                }
 
 
738
                else
 
 
739
                {
 
 
740
                    BLTGunSightToHUD(ScreenDescriptorBlock.SDB_Width - (SmartTargetSightX >> 16), SmartTargetSightY >> 16, 1);
 
 
741
                    BLTGunSightToHUD(ScreenDescriptorBlock.SDB_Width - (GunMuzzleSightX >> 16), GunMuzzleSightY >> 16, 0);
 
 
742
                }
 
 
743
 
 
 
744
                RenderHUDString_Centred("free", xCentre, ScreenDescriptorBlock.SDB_Height - MUL_FIXED(HUDScaleFactor, HUDLayout_AmmoDesc_TopY),
BrightWhite);
 
 
745
            }
 
 
746
        }
 
 
747
        break;
 
 
748
        case WEAPON_GRENADELAUNCHER:
 
 
749
        {
 
 
750
            char * ammo_string;
 
 
751
 
 
 
752
            switch(GrenadeLauncherData.SelectedAmmo)
 
 
753
            {
 
 
754
                case AMMO_GRENADE:
 
 
755
                    ammo_string = "Grenade";
 
 
756
                break;
 
 
757
                case AMMO_FRAGMENTATION_GRENADE:
 
 
758
                    ammo_string = "Frag";
 
 
759
                break;
 
 
760
                case AMMO_PROXIMITY_GRENADE:
 
 
761
                    ammo_string = "Proxy Mine";
 
 
762
                break;
 
 
763
                default:
 
 
764
                    ammo_string = "";
 
 
765
            }
 
 
766
 
 
 
767
            RenderHUDString_Centred(ammo_string, xCentre, ScreenDescriptorBlock.SDB_Height - MUL_FIXED(HUDScaleFactor, HUDLayout_AmmoDesc_TopY), BrightWhite);
 
 
768
        }
 
 
769
        break;
 
 
770
        case WEAPON_SADAR:
 
 
771
        {
 
 
772
            if (CHEATMODE_MIRROR != UserProfile.active_bonus)
 
 
773
                BLTGunSightToHUD(GunMuzzleSightX >> 16, GunMuzzleSightY >> 16, 0);
 
 
774
            else
 
 
775
                BLTGunSightToHUD(ScreenDescriptorBlock.SDB_Width - (GunMuzzleSightX >> 16), GunMuzzleSightY >> 16, 0);
 
 
776
 
 
 
777
            RenderHUDString_Centred ("Rounds", xCentre, lowernumberplacement_y, BrightWhite);
 
 
778
            RenderHUDNumber_Centred (PlayerStatus.SelectedWeapon->PrimaryRoundsRemaining, xCentre, lowertextplacement_y, MarineRed);
 
 
779
 
 
 
780
            //if(WEAPONSTATE_FIRING_PRIMARY == PlayerStatus.WeaponState) DrawPlayersMuzzleFlash(MUZZLE_FLASH_SKEETER);
 
 
781
        }
 
 
782
        return;
 
 
783
        case WEAPON_FLAMETHROWER:
 
 
784
        {
 
 
785
            RenderHUDString_Centred ("Cannisters", xCentre, uppertextplacement_y, BrightWhite);
 
 
786
            RenderHUDNumber_Centred (PlayerStatus.SelectedWeapon->MagazinesRemaining, xCentre, uppernumberplacement, MarineRed);
 
 
787
            RenderHUDString_Centred ("Fuel", xCentre, lowernumberplacement_y, BrightWhite);
 
 
788
            RenderHUDNumber_Centred (PlayerStatus.SelectedWeapon->PrimaryRoundsRemaining, xCentre, lowertextplacement_y, MarineRed);
 
 
789
        }
 
 
790
        return;
 
 
791
        case WEAPON_FRISBEE_LAUNCHER:
 
 
792
        {
 
 
793
            RenderHUDString_Centred ("Rounds", xCentre, lowernumberplacement_y, BrightWhite);
 
 
794
            RenderHUDNumber_Centred (PlayerStatus.SelectedWeapon->PrimaryRoundsRemaining, xCentre, lowertextplacement_y, MarineRed);
 
 
795
 
 
 
796
            //if(WEAPONSTATE_FIRING_PRIMARY == PlayerStatus.WeaponState) DrawPlayersMuzzleFlash(MUZZLE_FLASH_SKEETER);
 
 
797
        }
 
 
798
        return;
 
 
799
        case WEAPON_MINIGUN:
 
 
800
        {
 
 
801
            if(PlayerStatus.muzzle_flash)
 
 
802
            {
 
 
803
                DrawPlayersMuzzleFlash(MUZZLE_FLASH_AMORPHOUS);
 
 
804
                PlayerStatus.muzzle_flash = 0;
 
 
805
            }
 
 
806
        /*
 
 
807
            if (!PlayerStatus.IsAlive)
 
 
808
            {
 
 
809
                if(weaponHandle != SOUND_NOACTIVEINDEX)
 
 
810
                {
 
 
811
                    Sound_Play(SID_MINIGUN_END, "h");
 
 
812
                    Sound_Stop(weaponHandle);
 
 
813
                }
 
 
814
            }
 
 
815
        */
 
 
816
        }
 
 
817
        break;
 
 
818
        case WEAPON_TWO_PISTOLS:
 
 
819
        {
 
 
820
            if(PlayerStatus.muzzle_flash)
 
 
821
            {
 
 
822
                DrawPlayersMuzzleFlash(MUZZLE_FLASH_AMORPHOUS);
 
 
823
                PlayerStatus.muzzle_flash = 0;
 
 
824
            }
 
 
825
 
 
 
826
            int local_xCentre = xCentre + MUL_FIXED(HUDScaleFactor, HUDLayout_RightmostTextCentre * 2);
 
 
827
 
 
 
828
            RenderHUDNumber_Centred(PlayerStatus.SelectedWeapon->SecondaryRoundsRemaining, local_xCentre, lowertextplacement_y, MarineRed);
 
 
829
            RenderHUDString_Centred("Rounds" , local_xCentre, lowernumberplacement_y, BrightWhite);
 
 
830
        }
 
 
831
        break;
 
 
832
        case WEAPON_MARINE_PISTOL:
 
 
833
            if(PlayerStatus.muzzle_flash)
 
 
834
            {
 
 
835
                DrawPlayersMuzzleFlash(MUZZLE_FLASH_AMORPHOUS);
 
 
836
                PlayerStatus.muzzle_flash = 0;
 
 
837
            }
 
 
838
        break;
 
 
839
        //case WEAPON_CUDGEL:
 
 
840
        default:
 
 
841
            break;
 
 
842
    }
 
 
843
 
 
 
844
    RenderHUDString_Centred("Magazines", xCentre, uppertextplacement_y, BrightWhite);
 
 
845
    RenderHUDNumber_Centred(PlayerStatus.SelectedWeapon->MagazinesRemaining, xCentre, uppernumberplacement, MarineRed);
 
 
846
    RenderHUDString_Centred("Rounds", xCentre, lowernumberplacement_y, BrightWhite);
 
 
847
    RenderHUDNumber_Centred(PlayerStatus.SelectedWeapon->PrimaryRoundsRemaining, xCentre, lowertextplacement_y, MarineRed);
 
 
848
}
 
 
849
 
 
 
850
int ObjectShouldAppearOnMotionTracker(STRATEGYBLOCK *sbPtr)
 
 
851
{
 
 
852
    switch(sbPtr->type)
 
 
853
    {
 
 
854
    /*
 
 
855
        case I_BehaviourHierarchicalFragment:
 
 
856
        {
 
 
857
            HDEBRIS_BEHAV_BLOCK *debrisDataPtr  = (HDEBRIS_BEHAV_BLOCK *)sbPtr->dataptr;
 
 
858
 
 
 
859
            switch(debrisDataPtr->Type)
 
 
860
            {
 
 
861
            case I_BehaviourAlien:
 
 
862
            case I_BehaviourMarine:
 
 
863
            case I_BehaviourPredator:
 
 
864
            return DynamicObjectIsMoving(sbPtr->DynPtr);
 
 
865
            default:
 
 
866
            break;
 
 
867
            }
 
 
868
 
 
 
869
        }
 
 
870
        break;
 
 
871
    */
 
 
872
        case I_BehaviourAlien:
 
 
873
        case I_BehaviourMarine:
 
 
874
        case I_BehaviourPredator:
 
 
875
        case I_BehaviourFaceHugger:
 
 
876
        case I_BehaviourMarinePlayer:
 
 
877
        case I_BehaviourPredatorPlayer:
 
 
878
        case I_BehaviourAlienPlayer:
 
 
879
        case I_BehaviourXenoborg:
 
 
880
        case I_BehaviourQueenAlien:
 
 
881
        {
 
 
882
             if(DynamicObjectIsMoving(sbPtr->DynPtr))
 
 
883
             {
 
 
884
                 return 1;
 
 
885
             }
 
 
886
             else if (sbPtr->DisplayBlock && sbPtr->DisplayBlock->HModelControlBlock)
 
 
887
             {
 
 
888
                return sbPtr->DisplayBlock->HModelControlBlock->Playing;
 
 
889
             }
 
 
890
             else
 
 
891
                 return 0;
 
 
892
        }
 
 
893
        case I_BehaviourNetGhost:
 
 
894
        {
 
 
895
            NETGHOSTDATABLOCK *ghostData = (NETGHOSTDATABLOCK *)sbPtr->dataptr;
 
 
896
 
 
 
897
            switch(ghostData->type)
 
 
898
            {
 
 
899
                case I_BehaviourAlienPlayer:
 
 
900
                case I_BehaviourPredatorPlayer:
 
 
901
                case I_BehaviourMarinePlayer:
 
 
902
                     return DynamicObjectIsMoving(sbPtr->DynPtr);
 
 
903
                default:
 
 
904
                return 0;
 
 
905
            }
 
 
906
        }
 
 
907
        default:
 
 
908
        return 0;
 
 
909
    }
 
 
910
}
 
 
911
 
 
 
912
static int DoMotionTrackerBlips()
 
 
913
{
 
 
914
    DYNAMICSBLOCK *playerDynPtr = PlayerStatus.sbptr->DynPtr;
 
 
915
    int numberOfObjects = NumActiveStBlocks;
 
 
916
    int nearestDistance = MOTIONTRACKER_RANGE;
 
 
917
 
 
 
918
    int phi = playerDynPtr->OrientEuler.EulerY;
 
 
919
    int cosPhi = MUL_FIXED(GetCos(phi), MOTIONTRACKER_SCALE);
 
 
920
    int sinPhi = MUL_FIXED(GetSin(phi), MOTIONTRACKER_SCALE);
 
 
921
 
 
 
922
    while (numberOfObjects--)
 
 
923
    {
 
 
924
        STRATEGYBLOCK *objectPtr = ActiveStBlockList[numberOfObjects];
 
 
925
        DYNAMICSBLOCK *objectDynPtr = objectPtr->DynPtr;
 
 
926
 
 
 
927
        if (NoOfMTBlips == MOTIONTRACKER_MAXBLIPS)
 
 
928
                break;
 
 
929
 
 
 
930
          if (objectDynPtr && (!objectDynPtr->IsStatic || objectDynPtr->IsNetGhost) && ObjectShouldAppearOnMotionTracker(objectPtr))
 
 
931
        {
 
 
932
            /* 2d vector from player to object */
 
 
933
            int dx = objectDynPtr->Position.vx - playerDynPtr->Position.vx;
 
 
934
            int dz = objectDynPtr->Position.vz - playerDynPtr->Position.vz;
 
 
935
 
 
 
936
            {
 
 
937
                int absdx = abs(dx);
 
 
938
                int absdz = abs(dz);
 
 
939
 
 
 
940
                /* ignore objects past MT's detection distance */
 
 
941
                /* do quick box check */
 
 
942
                if (absdx > MOTIONTRACKER_RANGE || absdz > MOTIONTRACKER_RANGE)
 
 
943
                        continue;
 
 
944
            }
 
 
945
 
 
 
946
                int y = MUL_FIXED(dx,sinPhi) + MUL_FIXED(dz,cosPhi);
 
 
947
 
 
 
948
                /* ignore objects 'behind' MT */
 
 
949
                if (y >= 0)
 
 
950
                {
 
 
951
                    //int x = MUL_FIXED(dx,cosPhi) - MUL_FIXED(dz,sinPhi);
 
 
952
                    int dist = Fast2dMagnitude(dx, dz);
 
 
953
                    int radius = MUL_FIXED(dist, MOTIONTRACKER_SCALE);
 
 
954
 
 
 
955
                    if (radius <= MTScanLineSize)
 
 
956
                    {
 
 
957
                        int dx = objectDynPtr->PrevPosition.vx - playerDynPtr->PrevPosition.vx;
 
 
958
                        int dz = objectDynPtr->PrevPosition.vz - playerDynPtr->PrevPosition.vz;
 
 
959
                        int prevRadius = MUL_FIXED(Fast2dMagnitude(dx, dz), MOTIONTRACKER_SCALE);
 
 
960
 
 
 
961
                        if ((radius > PreviousMTScanLineSize) || (radius < PreviousMTScanLineSize && prevRadius > PreviousMTScanLineSize))
 
 
962
                        {
 
 
963
                            /* remember distance for possible display on HUD */
 
 
964
                            if (nearestDistance > dist)
 
 
965
                                nearestDistance = dist;
 
 
966
 
 
 
967
                            /* create new blip */
 
 
968
                    //        MotionTrackerBlips[NoOfMTBlips].X = x;
 
 
969
                    //        MotionTrackerBlips[NoOfMTBlips].Y = y;
 
 
970
                            MotionTrackerBlips[NoOfMTBlips].X = objectDynPtr->Position.vx;
 
 
971
                            MotionTrackerBlips[NoOfMTBlips].Y = objectDynPtr->Position.vz;
 
 
972
                            MotionTrackerBlips[NoOfMTBlips].Brightness = 65536;
 
 
973
                            NoOfMTBlips++;
 
 
974
                        }
 
 
975
                    }
 
 
976
                }
 
 
977
        }
 
 
978
    }
 
 
979
 
 
 
980
return nearestDistance;
 
 
981
}
 
 
982
 
 
 
983
/*
 
 
984
This function scans through the active block list looking for dynamic objects
 
 
985
which are detectable by the Motion Tracker.
 
 
986
*/
 
 
987
 
 
 
988
static void MotionTracker()
 
 
989
{
 
 
990
     static char distanceNotLocked = 1;
 
 
991
    static int distance = 0;
 
 
992
 
 
 
993
    /* draw static motion tracker background, and the moving scanline */
 
 
994
    BLTMotionTrackerToHUD(MTScanLineSize);
 
 
995
 
 
 
996
    if(distanceNotLocked) /* if MT hasn't found any contacts this scan */
 
 
997
    {
 
 
998
        int nearestDistance = DoMotionTrackerBlips();
 
 
999
 
 
 
1000
           if (nearestDistance < MOTIONTRACKER_RANGE)
 
 
1001
        {
 
 
1002
            distance = nearestDistance;
 
 
1003
            distanceNotLocked = 0;
 
 
1004
 
 
 
1005
            if (MTSoundHandle == SOUND_NOACTIVEINDEX)
 
 
1006
            {
 
 
1007
                int panicFactor = MUL_FIXED(nearestDistance, MOTIONTRACKER_SCALE);
 
 
1008
 
 
 
1009
                if (panicFactor < 21845)
 
 
1010
                {
 
 
1011
                    Sound_Play(SID_TRACKER_WHEEP_HIGH, "dev", &PlayerStatus.sbptr->DynPtr->Position, &MTSoundHandle,
MOTIONTRACKERVOLUME);
 
 
1012
                }
 
 
1013
                else if (panicFactor < 21845 * 2)
 
 
1014
                {
 
 
1015
                    Sound_Play(SID_TRACKER_WHEEP,"ev", &MTSoundHandle, MOTIONTRACKERVOLUME);
 
 
1016
                }
 
 
1017
                else
 
 
1018
                {
 
 
1019
                    Sound_Play(SID_TRACKER_WHEEP_LOW, "dev", &PlayerStatus.sbptr->DynPtr->Position, &MTSoundHandle,
MOTIONTRACKERVOLUME);
 
 
1020
                }
 
 
1021
            }
 
 
1022
        }
 
 
1023
        else if (!NoOfMTBlips) /* if the MT is blank, cycle the distance digits */
 
 
1024
        {
 
 
1025
            distance = MUL_FIXED(MTScanLineSize, MOTIONTRACKER_RANGE);
 
 
1026
         }
 
 
1027
    }
 
 
1028
    else
 
 
1029
        DoMotionTrackerBlips();
 
 
1030
 
 
 
1031
    /* evaluate the distance digits */
 
 
1032
    {
 
 
1033
        int value = distance / 15;
 
 
1034
        BLTDigitToHUD(value % 10, 17, MARINE_HUD_FONT_MT_SMALL);      
 
 
1035
 
 
 
1036
        value /= 10;
 
 
1037
        BLTDigitToHUD(value % 10, 9, MARINE_HUD_FONT_MT_SMALL);      
 
 
1038
 
 
 
1039
        value /= 10;
 
 
1040
        BLTDigitToHUD(value % 10, -9, MARINE_HUD_FONT_MT_BIG);      
 
 
1041
 
 
 
1042
        value /= 10;
 
 
1043
        BLTDigitToHUD(value % 10, -25, MARINE_HUD_FONT_MT_BIG);      
 
 
1044
    }
 
 
1045
 
 
 
1046
    if (MTDelayBetweenScans)
 
 
1047
    {
 
 
1048
        MTDelayBetweenScans -= NormalFrameTime;
 
 
1049
 
 
 
1050
        if (MTDelayBetweenScans < 0) 
 
 
1051
        {
 
 
1052
            MTDelayBetweenScans = 0;
 
 
1053
 
 
 
1054
            Sound_Play(SID_TRACKER_CLICK, "v", MOTIONTRACKERVOLUME);
 
 
1055
 
 
 
1056
            PreviousMTScanLineSize = MTScanLineSize = MOTIONTRACKER_SMALLESTSCANLINESIZE;
 
 
1057
            distanceNotLocked = 1; /* allow MT to look for a new nearest contact distance */
 
 
1058
        }
 
 
1059
    }
 
 
1060
    else
 
 
1061
    {
 
 
1062
        /* expand scanline or wrap it around */
 
 
1063
        PreviousMTScanLineSize = MTScanLineSize;
 
 
1064
 
 
 
1065
        if (MTScanLineSize >= 65536)
 
 
1066
        {             
 
 
1067
            MTDelayBetweenScans = 65536;
 
 
1068
            MTScanLineSize = 0;
 
 
1069
        }
 
 
1070
        else if (MTScanLineSize > 32768) 
 
 
1071
        {
 
 
1072
            MTScanLineSize += MUL_FIXED(MOTIONTRACKER_SPEED * 2, NormalFrameTime);
 
 
1073
        }
 
 
1074
        else
 
 
1075
        {
 
 
1076
            MTScanLineSize += MUL_FIXED(MOTIONTRACKER_SPEED, NormalFrameTime);
 
 
1077
        }
 
 
1078
 
 
 
1079
        if (MTScanLineSize > 65536)
 
 
1080
            MTScanLineSize = 65536;
 
 
1081
    }
 
 
1082
 
 
 
1083
    /* draw blips to HUD */
 
 
1084
    {
 
 
1085
        DYNAMICSBLOCK *playerDynPtr = PlayerStatus.sbptr->DynPtr;
 
 
1086
        int phi = playerDynPtr->OrientEuler.EulerY;
 
 
1087
        int cosPhi = MUL_FIXED(GetCos(phi), MOTIONTRACKER_SCALE);
 
 
1088
        int sinPhi = MUL_FIXED(GetSin(phi), MOTIONTRACKER_SCALE);
 
 
1089
 
 
 
1090
        /* made more awkward because we want to draw the brightest last */
 
 
1091
        int i = 0;
 
 
1092
 
 
 
1093
        while( i < NoOfMTBlips )
 
 
1094
        {
 
 
1095
            int y = MotionTrackerBlips[i].Y - playerDynPtr->Position.vz;
 
 
1096
              int x = MotionTrackerBlips[i].X - playerDynPtr->Position.vx;
 
 
1097
            int y2 = MUL_FIXED(x, sinPhi) + MUL_FIXED(y, cosPhi);
 
 
1098
 
 
 
1099
            if (y2 >= 0)
 
 
1100
            {
 
 
1101
                x = MUL_FIXED(x, cosPhi) - MUL_FIXED(y, sinPhi);
 
 
1102
 
 
 
1103
                if(Fast2dMagnitude(x, y2) < ONE_FIXED)
 
 
1104
                    BLTMotionTrackerBlipToHUD ( x, y2, MotionTrackerBlips[i].Brightness );
 
 
1105
            }
 
 
1106
 
 
 
1107
            MotionTrackerBlips[i].Brightness -= MUL_FIXED(MOTIONTRACKER_SPEED / 3, NormalFrameTime);
 
 
1108
        /*
 
 
1109
            if (MotionTrackerBlips[i].Brightness < 0)
 
 
1110
            {
 
 
1111
                // Kill ith blip by copying the last blip in the list over the ith and decreasing the number of blips
 
 
1112
                MotionTrackerBlips[i] = MotionTrackerBlips[--NoOfMTBlips];
 
 
1113
                continue;
 
 
1114
            }
 
 
1115
        */
 
 
1116
            i++;
 
 
1117
        }
 
 
1118
 
 
 
1119
        i = NoOfMTBlips;
 
 
1120
 
 
 
1121
        while(i--)
 
 
1122
        {
 
 
1123
            if (MotionTrackerBlips[i].Brightness < 0)
 
 
1124
            {
 
 
1125
                // Kill ith blip by copying the last blip in the list over the ith and decreasing the number of blips
 
 
1126
                MotionTrackerBlips[i] = MotionTrackerBlips[--NoOfMTBlips];
 
 
1127
            } 
 
 
1128
        }
 
 
1129
    }
 
 
1130
}
 
 
1131
 
 
 
1132
static void DrawAlienTeeth()
 
 
1133
{
 
 
1134
    if(GetBitingTarget()) 
 
 
1135
    {
 
 
1136
        if (AlienTeethOffset < ONE_FIXED)
 
 
1137
            AlienTeethOffset += NormalFrameTime * 2;
 
 
1138
        else if (AlienTeethOffset > ONE_FIXED)
 
 
1139
            AlienTeethOffset = ONE_FIXED;
 
 
1140
    }
 
 
1141
    else if(AlienTeethOffset)
 
 
1142
    {
 
 
1143
        if (AlienTeethOffset > 0)
 
 
1144
            AlienTeethOffset -= NormalFrameTime;
 
 
1145
        else
 
 
1146
            AlienTeethOffset = 0;
 
 
1147
    }
 
 
1148
 
 
 
1149
    if(AlienTeethOffset)
 
 
1150
    {
 
 
1151
        extern const DISPLAYBLOCK Zero_Displayblock;
 
 
1152
        DISPLAYBLOCK displayblock = Zero_Displayblock; 
 
 
1153
        MakeLightElement(&PlayerStatus.DisplayBlock->ObWorld, LIGHTELEMENT_ALIEN_TEETH);
 
 
1154
        MakeLightElement(&PlayerStatus.DisplayBlock->ObWorld, LIGHTELEMENT_ALIEN_TEETH2);
 
 
1155
        displayblock.ObMat = Global_VDB.VDB_Mat;
 
 
1156
 
 
 
1157
        TransposeMatrixCH(&displayblock.ObMat);
 
 
1158
 
 
 
1159
        int offsetY = MUL_FIXED(GetSin(AlienTeethOffset / 64), 80);
 
 
1160
 
 
 
1161
        displayblock.ObShape = GetLoadedShapeMSL("uppertuth@tongue");
 
 
1162
        displayblock.ObWorld.vy = -200 + offsetY;
 
 
1163
        displayblock.ObWorld.vz = 80;
 
 
1164
        displayblock.ObView = displayblock.ObWorld;
 
 
1165
 
 
 
1166
        MATRIXCH myMat = Global_VDB.VDB_Mat;
 
 
1167
        TransposeMatrixCH(&myMat);
 
 
1168
        RotateVector(&displayblock.ObWorld, &myMat);    
 
 
1169
        displayblock.ObWorld.vx += Global_VDB.VDB_World.vx;
 
 
1170
        displayblock.ObWorld.vy += Global_VDB.VDB_World.vy;
 
 
1171
        displayblock.ObWorld.vz += Global_VDB.VDB_World.vz;
 
 
1172
 
 
 
1173
        DisplayAlienTeeth(&displayblock);
 
 
1174
 
 
 
1175
        displayblock.ObShape = GetLoadedShapeMSL("lowertuth@tongue");
 
 
1176
        displayblock.ObWorld.vx = 0;
 
 
1177
        displayblock.ObWorld.vy = 200 - offsetY;
 
 
1178
        displayblock.ObWorld.vz = 80;
 
 
1179
        displayblock.ObView = displayblock.ObWorld;
 
 
1180
 
 
 
1181
        RotateVector(&displayblock.ObWorld, &myMat);    
 
 
1182
        displayblock.ObWorld.vx += Global_VDB.VDB_World.vx;
 
 
1183
        displayblock.ObWorld.vy += Global_VDB.VDB_World.vy;
 
 
1184
        displayblock.ObWorld.vz += Global_VDB.VDB_World.vz;
 
 
1185
 
 
 
1186
        DisplayAlienTeeth(&displayblock);
 
 
1187
    }
 
 
1188
 
 
 
1189
}
 
 
1190
 
 
 
1191
#define PREDATOR_LOCK_ON_TIME (ONE_FIXED *5 / 3)
 
 
1192
 
 
 
1193
static int triangle_lock(int has_target)
 
 
1194
{
 
 
1195
    static int PredSight_LockOnTime = 0;
 
 
1196
    static int PredSight_Angle = 0;
 
 
1197
    static int play_once_per_target = 0;
 
 
1198
 
 
 
1199
    if (has_target)
 
 
1200
    {
 
 
1201
        if (play_once_per_target)
 
 
1202
        {
 
 
1203
            play_once_per_target = 0;
 
 
1204
            Sound_Play(SID_PREDATOR_PLASMACASTER_REDTRIANGLES, "h");
 
 
1205
        }
 
 
1206
 
 
 
1207
        int segmentScale = PredSight_LockOnTime;
 
 
1208
 
 
 
1209
        if (segmentScale <= ONE_FIXED)
 
 
1210
            RenderPredatorTargetingSegment((PredSight_Angle+1365*2)&4095, segmentScale, PredSight_LockOnTime);
 
 
1211
 
 
 
1212
        segmentScale -= PREDATOR_LOCK_ON_TIME/5;
 
 
1213
 
 
 
1214
        if (segmentScale < 0)
 
 
1215
            segmentScale = 0;
 
 
1216
 
 
 
1217
        if (segmentScale <= ONE_FIXED)
 
 
1218
            RenderPredatorTargetingSegment((PredSight_Angle+1365)&4095, segmentScale, PredSight_LockOnTime);
 
 
1219
 
 
 
1220
        segmentScale -= PREDATOR_LOCK_ON_TIME / 5;
 
 
1221
 
 
 
1222
        if (segmentScale < 0)
 
 
1223
            segmentScale = 0;
 
 
1224
        else if (segmentScale > ONE_FIXED)
 
 
1225
            segmentScale = ONE_FIXED;
 
 
1226
 
 
 
1227
        RenderPredatorTargetingSegment(PredSight_Angle, segmentScale, PredSight_LockOnTime);
 
 
1228
 
 
 
1229
        if (PredSight_LockOnTime > 0)
 
 
1230
        {
 
 
1231
            PredSight_LockOnTime -= NormalFrameTime * PREDATOR_LOCK_ON_SPEED;
 
 
1232
 
 
 
1233
            if (PredSight_LockOnTime < 0)
 
 
1234
            {
 
 
1235
                PredSight_LockOnTime = 0;
 
 
1236
                /* Locked on - play a sound. */
 
 
1237
/*
 
 
1238
                if (WEAPON_PRED_DISC == PlayerStatus.SelectedWeapon->WeaponIDNumber)
 
 
1239
                    Sound_Play(SID_PREDATOR_DISK_TARGET_LOCKED,"h");
 
 
1240
                else
 
 
1241
                    Sound_Play(SID_PREDATOR_PLASMACASTER_TARGET_FOUND,"h");
 
 
1242
*/
 
 
1243
            }
 
 
1244
        }
 
 
1245
        else
 
 
1246
        {
 
 
1247
            PredSight_Angle += NormalFrameTime >> 6;
 
 
1248
            PredSight_Angle &= 4095;
 
 
1249
        }
 
 
1250
    }
 
 
1251
    else
 
 
1252
    {
 
 
1253
        PredSight_LockOnTime = PREDATOR_LOCK_ON_TIME;
 
 
1254
        PredSight_Angle = 0;
 
 
1255
        play_once_per_target = 1;
 
 
1256
    }
 
 
1257
 
 
 
1258
    if (PredSight_LockOnTime)
 
 
1259
    {    
 
 
1260
        GunMuzzleSightX = ScreenDescriptorBlock.SDB_Width << 15;
 
 
1261
        GunMuzzleSightY = ScreenDescriptorBlock.SDB_Height << 15;
 
 
1262
    }
 
 
1263
    else
 
 
1264
    {
 
 
1265
        GunMuzzleSightX = SmartTargetSightX;
 
 
1266
        GunMuzzleSightY = SmartTargetSightY;
 
 
1267
    }
 
 
1268
 
 
 
1269
return PredSight_LockOnTime;
 
 
1270
}
 
 
1271
 
 
 
1272
static void DrawPredatorSights()
 
 
1273
{
 
 
1274
    struct HUDImageDesc imageDesc;
 
 
1275
 
 
 
1276
    imageDesc.ImageNumber = HUDFontsImageNumber;
 
 
1277
    imageDesc.TopLeftX = (ScreenDescriptorBlock.SDB_Width - 16) / 2;
 
 
1278
    imageDesc.TopLeftY = (ScreenDescriptorBlock.SDB_Height - 14) / 2;
 
 
1279
    imageDesc.TopLeftU = 1;
 
 
1280
    imageDesc.TopLeftV = 51;
 
 
1281
    imageDesc.Height = 15;
 
 
1282
    imageDesc.Width = 17;
 
 
1283
    imageDesc.Scale = ONE_FIXED;
 
 
1284
    imageDesc.Translucency = 128;
 
 
1285
    imageDesc.Red = imageDesc.Green = imageDesc.Blue = 255;
 
 
1286
 
 
 
1287
    Draw_HUDImage(&imageDesc);
 
 
1288
}
 
 
1289
 
 
 
1290
static void HandlePredatorWeapon()
 
 
1291
{
 
 
1292
    switch(PlayerStatus.SelectedWeapon->WeaponIDNumber)
 
 
1293
    {
 
 
1294
        case WEAPON_PRED_SHOULDERCANNON:
 
 
1295
        {
 
 
1296
            three_dots();
 
 
1297
        {
 
 
1298
            extern HMODELCONTROLLER PlayersWeaponHModelController;
 
 
1299
            static const char *sectionName[]= {"Dum bar display", "Dum 1 display", "Dum 2 display", "Dum 3 display",
"Dum 4 display"};
 
 
1300
            SECTION_DATA *sectionPtr = GetThisSectionData(PlayersWeaponHModelController.section_data, sectionName[0]);
 
 
1301
 
 
 
1302
            if (sectionPtr)
 
 
1303
                RenderPredatorPlasmaCasterCharge(PlayerStatus.PlasmaCasterCharge, &sectionPtr->World_Offset, &sectionPtr->SecMat);
 
 
1304
        }
 
 
1305
 
 
 
1306
 
 
 
1307
            if ( (PlayerStatus.WeaponState != WEAPONSTATE_SWAPPING_IN) && (PlayerStatus.WeaponState != WEAPONSTATE_READYING) &&
!triangle_lock(SmartTarget(0, ONE_FIXED)) )
 
 
1308
            {
 
 
1309
                // We must be locked on and steady.
 
 
1310
                if(predHUDSoundHandle != SOUND_NOACTIVEINDEX) 
 
 
1311
                {
 
 
1312
                    if (ActiveSounds[predHUDSoundHandle].soundIndex != SID_PREDATOR_PLASMACASTER_TARGET_LOCKED)
 
 
1313
                            Sound_Stop(predHUDSoundHandle);
 
 
1314
                }
 
 
1315
                else
 
 
1316
                {
 
 
1317
                    Sound_Play(SID_PREDATOR_PLASMACASTER_TARGET_LOCKED, "elh", &predHUDSoundHandle);
 
 
1318
                }
 
 
1319
            }
 
 
1320
            else
 
 
1321
            {
 
 
1322
                // Not locked on - don't be looping!
 
 
1323
                if(predHUDSoundHandle != SOUND_NOACTIVEINDEX) 
 
 
1324
                {
 
 
1325
                    Sound_Stop(predHUDSoundHandle);
 
 
1326
                    // We were locked on...
 
 
1327
                    Sound_Play(SID_PREDATOR_PLASMACASTER_TARGET_LOST, "h");
 
 
1328
                }
 
 
1329
            }
 
 
1330
        }
 
 
1331
        break;
 
 
1332
        case WEAPON_PRED_DISC:
 
 
1333
        {
 
 
1334
            if(PlayerStatus.WeaponState == WEAPONSTATE_FIRING_PRIMARY)            
 
 
1335
            {
 
 
1336
                //Sound_Play(SID_PRED_FRISBEE, "hp", (FastRandom()&255)-128);
 
 
1337
            }
 
 
1338
            else
 
 
1339
            {
 
 
1340
                if (PlayerStatus.SelectedWeapon->PrimaryRoundsRemaining)
 
 
1341
                if(!triangle_lock(SmartTarget(4, ONE_FIXED)))
 
 
1342
                { }
 
 
1343
                ;//    Sound_Play(SID_PREDATOR_DISK_TARGET_LOCKED,"h");
 
 
1344
            }
 
 
1345
        }
 
 
1346
        break;
 
 
1347
        case WEAPON_PRED_RIFLE:
 
 
1348
        {
 
 
1349
            DrawPredatorSights();
 
 
1350
            //three_dots();
 
 
1351
            int value = PlayerStatus.SelectedWeapon->PrimaryRoundsRemaining;
 
 
1352
            int scale = DIV_FIXED(ScreenDescriptorBlock.SDB_Width, 640);
 
 
1353
            int size = MUL_FIXED(51, scale);
 
 
1354
            int i = 0;
 
 
1355
 
 
 
1356
            for (; i < 4; i++)
 
 
1357
            {
 
 
1358
                struct HUDCharDesc charDesc;
 
 
1359
                charDesc.X = i * size / 2;            
 
 
1360
                charDesc.Y = ScreenDescriptorBlock.SDB_Height - size / 2;
 
 
1361
 
 
 
1362
                charDesc.Red = 0;
 
 
1363
                charDesc.Green = 0;
 
 
1364
                charDesc.Blue = 255;
 
 
1365
                charDesc.Alpha= 255;
 
 
1366
 
 
 
1367
                int v = value - i * 9;
 
 
1368
 
 
 
1369
                if (v > 9)
 
 
1370
                    v = 9;
 
 
1371
                else if (v < 0)
 
 
1372
                    v = 0;
 
 
1373
 
 
 
1374
                charDesc.Character = v;
 
 
1375
 
 
 
1376
                DrawHUDPredatorDigit(&charDesc, scale / 2);
 
 
1377
            }
 
 
1378
        }
 
 
1379
        default:
 
 
1380
        break;
 
 
1381
    }
 
 
1382
}
 
 
1383
 
 
 
1384
void toggle_cloak()
 
 
1385
{
 
 
1386
    if (cloakDebounce)
 
 
1387
    {
 
 
1388
        cloakDebounce = 0;
 
 
1389
 
 
 
1390
        if (PlayerStatus.cloakOn)
 
 
1391
        {
 
 
1392
            Sound_Play(SID_PRED_CLOAKOFF,"h");
 
 
1393
            PlayerStatus.cloakOn = 0;
 
 
1394
        }
 
 
1395
        else if (PlayerStatus.FieldCharge > CloakThreshold)
 
 
1396
        {
 
 
1397
            /* Check validity. */
 
 
1398
            PlayerStatus.FieldCharge -= CloakPowerOnDrain;
 
 
1399
            CurrentGameStats_ChargeUsed(CloakPowerOnDrain);
 
 
1400
            PlayerStatus.cloakOn = 1;
 
 
1401
            PlayerStatus.CloakingEffectiveness = 0;
 
 
1402
            Sound_Play(SID_PRED_CLOAKON, "h");
 
 
1403
        }
 
 
1404
    }
 
 
1405
}
 
 
1406
 
 
 
1407
static void MaintainZoomingLevel()
 
 
1408
{
 
 
1409
    extern void DrawScanlinesOverlay(float level);
 
 
1410
    static float ZoomLevels[] = { 1.0f, 0.4f, 0.1f, 0.02f };
 
 
1411
 
 
 
1412
    float requestedZoomScale = ZoomLevels[CameraZoomLevel];
 
 
1413
 
 
 
1414
    if (requestedZoomScale < CameraZoomScale)
 
 
1415
    {
 
 
1416
        int i = 0;
 
 
1417
        while (CameraZoomScale <= ZoomLevels[++i])
 
 
1418
            continue;
 
 
1419
 
 
 
1420
        if (CameraZoomScale == ZoomLevels[i-1])
 
 
1421
            Sound_Play(SID_PRED_ZOOM_IN, "h");
 
 
1422
 
 
 
1423
        float deltaZoom = (ZoomLevels[i-1] - ZoomLevels[i]) * (float)NormalFrameTime / 32768.0f;
 
 
1424
    //    printf("deltaZoom %f, zone %d\n",deltaZoom,i);
 
 
1425
 
 
 
1426
        CameraZoomScale -= deltaZoom;
 
 
1427
 
 
 
1428
        if (CameraZoomScale < ZoomLevels[i])
 
 
1429
            CameraZoomScale = ZoomLevels[i];
 
 
1430
 
 
 
1431
        DrawScanlinesOverlay( (CameraZoomScale - ZoomLevels[i-1]) / (ZoomLevels[i]-ZoomLevels[i-1]) );
 
 
1432
    }
 
 
1433
    else if (requestedZoomScale > CameraZoomScale)
 
 
1434
    {
 
 
1435
        CameraZoomScale = requestedZoomScale;
 
 
1436
        DrawScanlinesOverlay(1);
 
 
1437
        Sound_Play(SID_PRED_ZOOM_OUT, "h");
 
 
1438
    }
 
 
1439
}
 
 
1440
 
 
 
1441
void predator_hud()
 
 
1442
{
 
 
1443
    DoPlayersWeaponHModel(&PlayerStatus.weapon);
 
 
1444
 
 
 
1445
    if (PlayerStatus.cloakOn)
 
 
1446
    {
 
 
1447
        if (PlayerStatus.FieldCharge < CloakThreshold)
 
 
1448
        {
 
 
1449
            cloakDebounce = 1; // just in case someone is pressing (primaryInput/secondaryInput)->Cloak
 
 
1450
            toggle_cloak();
 
 
1451
        }
 
 
1452
        else
 
 
1453
        {
 
 
1454
            //static const int CloakDrain = 12000;
 
 
1455
            //PlayerStatus.FieldCharge -= MUL_FIXED(NormalFrameTime, CloakDrain); CurrentGameStats_ChargeUsed(PlayerStatus.FieldCharge);
 
 
1456
 
 
 
1457
            DrawNoiseOverlay(16);
 
 
1458
            CurrentGameStats_CloakOn();
 
 
1459
 
 
 
1460
            switch(PlayerStatus.weapon.HModelControlBlock->Sub_Sequence)
 
 
1461
            {
 
 
1462
                case PHSS_Stand:
 
 
1463
                case PHSS_Fidget:
 
 
1464
                case PHSS_Hold:
 
 
1465
                {
 
 
1466
                    DYNAMICSBLOCK *dynPtr = PlayerStatus.sbptr->DynPtr;
 
 
1467
                    VECTORCH velocity;
 
 
1468
 
 
 
1469
                    velocity.vx = dynPtr->Position.vx - dynPtr->PrevPosition.vx;
 
 
1470
                    velocity.vy = dynPtr->Position.vy - dynPtr->PrevPosition.vy;
 
 
1471
                    velocity.vz = dynPtr->Position.vz - dynPtr->PrevPosition.vz;
 
 
1472
 
 
 
1473
                    int maxPossibleEffectiveness = ONE_FIXED - DIV_FIXED(Magnitude(&velocity) * 2, NormalFrameTime);
 
 
1474
 
 
 
1475
                    if (maxPossibleEffectiveness < 0)
 
 
1476
                        maxPossibleEffectiveness = 0;
 
 
1477
 
 
 
1478
                    PlayerStatus.CloakingEffectiveness += NormalFrameTime;
 
 
1479
 
 
 
1480
                    if (PlayerStatus.CloakingEffectiveness > maxPossibleEffectiveness)
 
 
1481
                        PlayerStatus.CloakingEffectiveness = maxPossibleEffectiveness;
 
 
1482
                }
 
 
1483
                break;
 
 
1484
                default:
 
 
1485
                    PlayerStatus.CloakingEffectiveness -= NormalFrameTime / 4;
 
 
1486
 
 
 
1487
                    if(PlayerStatus.CloakingEffectiveness < 0)
 
 
1488
                        PlayerStatus.CloakingEffectiveness = 0;
 
 
1489
            }
 
 
1490
        }
 
 
1491
    }
 
 
1492
    else if (PlayerStatus.CloakingEffectiveness)
 
 
1493
    {
 
 
1494
        PlayerStatus.CloakingEffectiveness -= NormalFrameTime;
 
 
1495
 
 
 
1496
        if (PlayerStatus.CloakingEffectiveness < 0)
 
 
1497
            PlayerStatus.CloakingEffectiveness = 0;
 
 
1498
    }
 
 
1499
 
 
 
1500
    if (PlayerStatus.VisionMode != VISION_MODE_NORMAL)
 
 
1501
    {
 
 
1502
        if (PlayerStatus.FieldCharge < ONE_FIXED)
 
 
1503
        {
 
 
1504
            PlayerStatus.VisionMode = VISION_MODE_NORMAL;
 
 
1505
            Sound_Stop(predOVision_SoundHandle);
 
 
1506
            PredatorVisionChangeCounter = ONE_FIXED;
 
 
1507
        }
 
 
1508
        else
 
 
1509
        {
 
 
1510
            if (PlayerStatus.VisionMode == VISION_MODE_PRED_SEEPREDTECH)
 
 
1511
            {
 
 
1512
                extern void PredatorScreenInversionOverlay();
 
 
1513
                PredatorScreenInversionOverlay();
 
 
1514
            }
 
 
1515
 
 
 
1516
            //if (predOVision_SoundHandle == SOUND_NOACTIVEINDEX) Sound_Play(SID_PREDATOR_CLOAKING_ACTIVE, "elh", &predOVision_SoundHandle);
 
 
1517
        }
 
 
1518
    }
 
 
1519
    //else
 
 
1520
    {
 
 
1521
        PlayerStatus.FieldCharge += MUL_FIXED(NormalFrameTime, ((I_Hard == AvP.Difficulty) ? (TrickleCharge >> 1) : TrickleCharge));
 
 
1522
 
 
 
1523
        if(PlayerStatus.FieldCharge > PLAYERCLOAK_MAXENERGY)
 
 
1524
            PlayerStatus.FieldCharge = PLAYERCLOAK_MAXENERGY;
 
 
1525
 
 
 
1526
        //    Infinite field charge?
 
 
1527
        //    PlayerStatus.FieldCharge = PLAYERCLOAK_MAXENERGY;
 
 
1528
    }
 
 
1529
 
 
 
1530
    if (PredatorVisionChangeCounter)
 
 
1531
    {
 
 
1532
        FadeDownScreen(ONE_FIXED - PredatorVisionChangeCounter, 0xffffffff);
 
 
1533
        PredatorVisionChangeCounter -= NormalFrameTime*4;
 
 
1534
 
 
 
1535
        if (PredatorVisionChangeCounter < 0)
 
 
1536
            PredatorVisionChangeCounter = 0;
 
 
1537
    }
 
 
1538
 
 
 
1539
    MaintainZoomingLevel();
 
 
1540
 
 
 
1541
    //flash health if invulnerable
 
 
1542
    if(!PlayerStatus.invulnerabilityTimer || !(PlayerStatus.invulnerabilityTimer / 12000 % 2))
 
 
1543
        PredatorHealthAndEnergy();
 
 
1544
 
 
 
1545
    HandlePredatorWeapon();
 
 
1546
}
 
 
1547
 
 
 
1548
void marine_hud()
 
 
1549
{
 
 
1550
    int x_rightmost = MUL_FIXED(HUDLayout_RightmostTextCentre, HUDScaleFactor) + ScreenDescriptorBlock.SDB_Width;
 
 
1551
 
 
 
1552
    DoPlayersWeaponHModel(&PlayerStatus.weapon);
 
 
1553
 
 
 
1554
    //flash health if invulnerable
 
 
1555
    if(!PlayerStatus.invulnerabilityTimer || !(PlayerStatus.invulnerabilityTimer / 12000 % 2))
 
 
1556
    {
 
 
1557
        int health = (PlayerStatus.Health * 100) / PlayerStatus.StartingHealth;
 
 
1558
        int armour = (PlayerStatus.Armour * 100) / PlayerStatus.StartingArmour;
 
 
1559
 
 
 
1560
        health = (health + 65535) >> 16;
 
 
1561
        armour = (armour + 65535) >> 16;
 
 
1562
 
 
 
1563
        RenderHUDString_Centred("Health", x_rightmost, MUL_FIXED(HUDLayout_Health_TopY, HUDScaleFactor), BrightWhite);
 
 
1564
        RenderHUDString_Centred("Armour", x_rightmost, MUL_FIXED(HUDLayout_Armour_TopY, HUDScaleFactor), BrightWhite);
 
 
1565
        RenderHUDNumber_Centred(health, x_rightmost, MUL_FIXED(HUDLayout_Health_TopY + HUDLayout_Linespacing, HUDScaleFactor), MarineGreen);    
 
 
1566
        RenderHUDNumber_Centred(armour, x_rightmost, MUL_FIXED(HUDLayout_Armour_TopY + HUDLayout_Linespacing, HUDScaleFactor), MarineGreen);
 
 
1567
    }
 
 
1568
 
 
 
1569
    MarinesAmmo();
 
 
1570
    MotionTracker();
 
 
1571
 
 
 
1572
    if(PlayerStatus.FlaresLeft)
 
 
1573
    {
 
 
1574
        static const char flares_remaining[21] = "IIIIIIIIIIIIIIIIIIII";
 
 
1575
        const char * ptr = &flares_remaining[20] - PlayerStatus.FlaresLeft;
 
 
1576
        RenderHUDString(ptr, 0, ScreenDescriptorBlock.SDB_Height - MUL_FIXED(MotionTrackerScale, 15), flare_hud_colour);
 
 
1577
    }
 
 
1578
 
 
 
1579
    if (VISION_MODE_IMAGEINTENSIFIER == PlayerStatus.VisionMode)
 
 
1580
    {
 
 
1581
        PlayerStatus.imageintensifier_battery -= NormalFrameTime;
 
 
1582
 
 
 
1583
        if(PlayerStatus.imageintensifier_battery < 0)
 
 
1584
        {
 
 
1585
            PlayerStatus.imageintensifier_battery = 0;
 
 
1586
            PlayerStatus.VisionMode = VISION_MODE_NORMAL;
 
 
1587
            Sound_Play(SID_IMAGE_OFF, "h");
 
 
1588
            ChooseLightingModel();
 
 
1589
        }
 
 
1590
        else
 
 
1591
        {
 
 
1592
            RenderHUDString_Centred("Battery", x_rightmost, MUL_FIXED(HUDLayout_Battery_TopY, HUDScaleFactor), 0x58ffffff);
 
 
1593
            RenderHUDNumber_Centred(PlayerStatus.imageintensifier_battery >> ONE_FIXED_SHIFT, x_rightmost, MUL_FIXED(HUDLayout_Battery_TopY +
HUDLayout_Linespacing, HUDScaleFactor), MarineRed);
 
 
1594
            DrawNoiseOverlay(64);
 
 
1595
        }
 
 
1596
    }
 
 
1597
}
 
 
1598
 
 
 
1599
void alien_hud()
 
 
1600
{
 
 
1601
    SetFrustrumType(FRUSTRUM_TYPE_NORMAL);
 
 
1602
    Global_VDB.VDB_ProjX = ScreenDescriptorBlock.SDB_CentreX;
 
 
1603
    Global_VDB.VDB_ProjY = ScreenDescriptorBlock.SDB_CentreY;
 
 
1604
 
 
 
1605
    DoPlayersWeaponHModel(&PlayerStatus.weapon);
 
 
1606
 
 
 
1607
    if (VISION_MODE_ALIEN_SENSE == PlayerStatus.VisionMode)
 
 
1608
        ScreenInversionOverlay();
 
 
1609
 
 
 
1610
    SetFrustrumType(FRUSTRUM_TYPE_WIDE);
 
 
1611
    Global_VDB.VDB_ProjX /= 2; 
 
 
1612
    Global_VDB.VDB_ProjY /= 2;
 
 
1613
 
 
 
1614
    if (AlienBiteAttackInProgress)
 
 
1615
    {
 
 
1616
        CameraZoomScale += (float)NormalFrameTime / 65536.0f;
 
 
1617
 
 
 
1618
        if (AlienTongueOffset)
 
 
1619
        {
 
 
1620
            RenderInsideAlienTongue(AlienTongueOffset);
 
 
1621
            AlienTongueOffset -= NormalFrameTime;
 
 
1622
 
 
 
1623
            if (AlienTongueOffset < 0)
 
 
1624
                AlienTongueOffset = 0;
 
 
1625
        }
 
 
1626
 
 
 
1627
        if (CameraZoomScale > 1.0f)
 
 
1628
        {
 
 
1629
            AlienBiteAttackInProgress = 0;
 
 
1630
            CameraZoomScale = 1.0f;
 
 
1631
        }
 
 
1632
        else
 
 
1633
        {
 
 
1634
            if (CameraZoomScale != 0.25f)
 
 
1635
            {
 
 
1636
                int b = (CameraZoomScale * 65536.0f);
 
 
1637
 
 
 
1638
                if (b < 32768)
 
 
1639
                    b = 32768;
 
 
1640
 
 
 
1641
                FadeDownScreen(b, 0xff0000);
 
 
1642
            }
 
 
1643
        }
 
 
1644
    }
 
 
1645
    else
 
 
1646
    {
 
 
1647
        DrawAlienTeeth();
 
 
1648
    }
 
 
1649
 
 
 
1650
    AlienHealth();
 
 
1651
}