]> icculus.org git repositories - btb/d2x.git/blob - main/gauges.c
more header cleanup
[btb/d2x.git] / main / gauges.c
1 /*
2 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
3 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
4 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
5 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
6 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
7 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
8 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
9 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
10 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
11 COPYRIGHT 1993-1999 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
12 */
13
14 /*
15  *
16  * Inferno gauge drivers
17  *
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #include <conf.h>
22 #endif
23
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <stdarg.h>
28
29 #include "inferno.h"
30 #include "error.h"
31 #include "mono.h"
32 #ifdef OGL
33 #include "ogl_init.h"
34 #endif
35
36
37 void draw_ammo_info(int x,int y,int ammo_count,int primary);
38 extern void draw_guided_crosshair(void);
39
40 bitmap_index Gauges[MAX_GAUGE_BMS];   // Array of all gauge bitmaps.
41 bitmap_index Gauges_hires[MAX_GAUGE_BMS];   // hires gauges
42
43 grs_canvas *Canv_LeftEnergyGauge = NULL;
44 grs_canvas *Canv_AfterburnerGauge = NULL;
45 grs_canvas *Canv_SBEnergyGauge = NULL;
46 grs_canvas *Canv_SBAfterburnerGauge = NULL;
47 grs_canvas *Canv_RightEnergyGauge = NULL;
48 grs_canvas *Canv_NumericalGauge = NULL;
49
50 //Flags for gauges/hud stuff
51 cvar_t Reticle_on = { "crosshair", "1", 1 };
52
53 //bitmap numbers for gauges
54
55 #define GAUGE_SHIELDS                   0               //0..9, in decreasing order (100%,90%...0%)
56
57 #define GAUGE_INVULNERABLE              10              //10..19
58 #define N_INVULNERABLE_FRAMES   10
59
60 #define GAUGE_AFTERBURNER       20
61 #define GAUGE_ENERGY_LEFT               21
62 #define GAUGE_ENERGY_RIGHT              22
63 #define GAUGE_NUMERICAL                 23
64
65 #define GAUGE_BLUE_KEY                  24
66 #define GAUGE_GOLD_KEY                  25
67 #define GAUGE_RED_KEY                   26
68 #define GAUGE_BLUE_KEY_OFF              27
69 #define GAUGE_GOLD_KEY_OFF              28
70 #define GAUGE_RED_KEY_OFF               29
71
72 #define SB_GAUGE_BLUE_KEY               30
73 #define SB_GAUGE_GOLD_KEY               31
74 #define SB_GAUGE_RED_KEY                32
75 #define SB_GAUGE_BLUE_KEY_OFF   33
76 #define SB_GAUGE_GOLD_KEY_OFF   34
77 #define SB_GAUGE_RED_KEY_OFF    35
78
79 #define SB_GAUGE_ENERGY                 36
80
81 #define GAUGE_LIVES                             37      
82
83 #define GAUGE_SHIPS                             38
84 #define GAUGE_SHIPS_LAST                45
85
86 #define RETICLE_CROSS                   46
87 #define RETICLE_PRIMARY                 48
88 #define RETICLE_SECONDARY               51
89 #define RETICLE_LAST                            55
90
91 #define GAUGE_HOMING_WARNING_ON 56
92 #define GAUGE_HOMING_WARNING_OFF        57
93
94 #define SML_RETICLE_CROSS               58
95 #define SML_RETICLE_PRIMARY     60
96 #define SML_RETICLE_SECONDARY   63
97 #define SML_RETICLE_LAST                67
98
99 #define KEY_ICON_BLUE                   68
100 #define KEY_ICON_YELLOW                 69
101 #define KEY_ICON_RED                            70
102
103 #define SB_GAUGE_AFTERBURNER    71
104
105 #define FLAG_ICON_RED                   72
106 #define FLAG_ICON_BLUE                  73
107
108
109 /* Use static inline function under GCC to avoid CR/LF issues */
110 #ifdef __GNUC__
111 #define PAGE_IN_GAUGE(x) _page_in_gauge(x)
112 static inline void _page_in_gauge(int x)
113 {
114     if (FontHires) {
115         PIGGY_PAGE_IN(Gauges_hires[x]);
116     } else {
117         PIGGY_PAGE_IN(Gauges[x]);
118     }
119 }
120
121 #else
122 #define PAGE_IN_GAUGE(x) \
123         do {                                                                                                    \
124                 if (FontHires) {                                \
125                         PIGGY_PAGE_IN(Gauges_hires[x]);         \
126                 } else {                                                                                        \
127                         PIGGY_PAGE_IN(Gauges[x]);                               \
128                 }                                                                                                       \
129         } while (0)
130
131 #endif
132
133 #define GET_GAUGE_INDEX(x)      (FontHires?Gauges_hires[x].index:Gauges[x].index)
134
135 //change MAX_GAUGE_BMS when adding gauges
136
137 //Coordinats for gauges
138
139 // cockpit keys
140
141 #define GAUGE_BLUE_KEY_X_L              272
142 #define GAUGE_BLUE_KEY_Y_L              152
143 #define GAUGE_BLUE_KEY_X_H              535
144 #define GAUGE_BLUE_KEY_Y_H              374
145 #define GAUGE_BLUE_KEY_X        (SM_HIRES?GAUGE_BLUE_KEY_X_H:GAUGE_BLUE_KEY_X_L)
146 #define GAUGE_BLUE_KEY_Y        (SM_HIRES?GAUGE_BLUE_KEY_Y_H:GAUGE_BLUE_KEY_Y_L)
147
148 #define GAUGE_GOLD_KEY_X_L              273
149 #define GAUGE_GOLD_KEY_Y_L              162
150 #define GAUGE_GOLD_KEY_X_H              537
151 #define GAUGE_GOLD_KEY_Y_H              395
152 #define GAUGE_GOLD_KEY_X        (SM_HIRES?GAUGE_GOLD_KEY_X_H:GAUGE_GOLD_KEY_X_L)
153 #define GAUGE_GOLD_KEY_Y        (SM_HIRES?GAUGE_GOLD_KEY_Y_H:GAUGE_GOLD_KEY_Y_L)
154
155 #define GAUGE_RED_KEY_X_L               274
156 #define GAUGE_RED_KEY_Y_L               172
157 #define GAUGE_RED_KEY_X_H               539
158 #define GAUGE_RED_KEY_Y_H               416
159 #define GAUGE_RED_KEY_X         (SM_HIRES?GAUGE_RED_KEY_X_H:GAUGE_RED_KEY_X_L)
160 #define GAUGE_RED_KEY_Y         (SM_HIRES?GAUGE_RED_KEY_Y_H:GAUGE_RED_KEY_Y_L)
161
162 // status bar keys
163
164 #define SB_GAUGE_KEYS_X_L          11
165 #define SB_GAUGE_KEYS_X_H               26
166 #define SB_GAUGE_KEYS_X         (SM_HIRES?SB_GAUGE_KEYS_X_H:SB_GAUGE_KEYS_X_L)
167
168 #define SB_GAUGE_BLUE_KEY_Y_L           153
169 #define SB_GAUGE_GOLD_KEY_Y_L           169
170 #define SB_GAUGE_RED_KEY_Y_L            185
171
172 #define SB_GAUGE_BLUE_KEY_Y_H           390
173 #define SB_GAUGE_GOLD_KEY_Y_H           422
174 #define SB_GAUGE_RED_KEY_Y_H            454
175
176 #define SB_GAUGE_BLUE_KEY_Y     (SM_HIRES?SB_GAUGE_BLUE_KEY_Y_H:SB_GAUGE_BLUE_KEY_Y_L)
177 #define SB_GAUGE_GOLD_KEY_Y     (SM_HIRES?SB_GAUGE_GOLD_KEY_Y_H:SB_GAUGE_GOLD_KEY_Y_L)
178 #define SB_GAUGE_RED_KEY_Y      (SM_HIRES?SB_GAUGE_RED_KEY_Y_H:SB_GAUGE_RED_KEY_Y_L)
179
180 // cockpit enery gauges
181
182 #define LEFT_ENERGY_GAUGE_X_L   70
183 #define LEFT_ENERGY_GAUGE_Y_L   131
184 #define LEFT_ENERGY_GAUGE_W_L   64
185 #define LEFT_ENERGY_GAUGE_H_L   8
186
187 #define LEFT_ENERGY_GAUGE_X_H   137
188 #define LEFT_ENERGY_GAUGE_Y_H   314
189 #define LEFT_ENERGY_GAUGE_W_H   133
190 #define LEFT_ENERGY_GAUGE_H_H   21
191
192 #define LEFT_ENERGY_GAUGE_X     (SM_HIRES?LEFT_ENERGY_GAUGE_X_H:LEFT_ENERGY_GAUGE_X_L)
193 #define LEFT_ENERGY_GAUGE_Y     (SM_HIRES?LEFT_ENERGY_GAUGE_Y_H:LEFT_ENERGY_GAUGE_Y_L)
194 #define LEFT_ENERGY_GAUGE_W     (SM_HIRES?LEFT_ENERGY_GAUGE_W_H:LEFT_ENERGY_GAUGE_W_L)
195 #define LEFT_ENERGY_GAUGE_H     (SM_HIRES?LEFT_ENERGY_GAUGE_H_H:LEFT_ENERGY_GAUGE_H_L)
196
197 #define RIGHT_ENERGY_GAUGE_X    (SM_HIRES?380:190)
198 #define RIGHT_ENERGY_GAUGE_Y    (SM_HIRES?314:131)
199 #define RIGHT_ENERGY_GAUGE_W    (SM_HIRES?133:64)
200 #define RIGHT_ENERGY_GAUGE_H    (SM_HIRES?21:8)
201
202 // cockpit afterburner gauge
203
204 #define AFTERBURNER_GAUGE_X_L   45-1
205 #define AFTERBURNER_GAUGE_Y_L   158
206 #define AFTERBURNER_GAUGE_W_L   12
207 #define AFTERBURNER_GAUGE_H_L   32
208
209 #define AFTERBURNER_GAUGE_X_H   88
210 #define AFTERBURNER_GAUGE_Y_H   377
211 #define AFTERBURNER_GAUGE_W_H   21
212 #define AFTERBURNER_GAUGE_H_H   65
213
214 #define AFTERBURNER_GAUGE_X     (SM_HIRES?AFTERBURNER_GAUGE_X_H:AFTERBURNER_GAUGE_X_L)
215 #define AFTERBURNER_GAUGE_Y     (SM_HIRES?AFTERBURNER_GAUGE_Y_H:AFTERBURNER_GAUGE_Y_L)
216 #define AFTERBURNER_GAUGE_W     (SM_HIRES?AFTERBURNER_GAUGE_W_H:AFTERBURNER_GAUGE_W_L)
217 #define AFTERBURNER_GAUGE_H     (SM_HIRES?AFTERBURNER_GAUGE_H_H:AFTERBURNER_GAUGE_H_L)
218
219 // sb energy gauge
220
221 #define SB_ENERGY_GAUGE_X       (SM_HIRES?196:98)
222 #define SB_ENERGY_GAUGE_Y       (SM_HIRES?382:(155-2))
223 #define SB_ENERGY_GAUGE_W       (SM_HIRES?32:16)
224 #define SB_ENERGY_GAUGE_H       (SM_HIRES?60:29)
225
226 // sb afterburner gauge
227
228 #define SB_AFTERBURNER_GAUGE_X  (SM_HIRES?196:98)
229 #define SB_AFTERBURNER_GAUGE_Y  (SM_HIRES?446:184)
230 #define SB_AFTERBURNER_GAUGE_W  (SM_HIRES?33:16)
231 #define SB_AFTERBURNER_GAUGE_H  (SM_HIRES?29:13)
232
233 #define SB_ENERGY_NUM_X         (SB_ENERGY_GAUGE_X+(SM_HIRES?4:2))
234 #define SB_ENERGY_NUM_Y         (SM_HIRES?457:175)
235
236 #define SHIELD_GAUGE_X          (SM_HIRES?292:146)
237 #define SHIELD_GAUGE_Y          (SM_HIRES?374:155)
238 #define SHIELD_GAUGE_W          (SM_HIRES?70:35)
239 #define SHIELD_GAUGE_H          (SM_HIRES?77:32)
240
241 #define SHIP_GAUGE_X            (SHIELD_GAUGE_X+(SM_HIRES?11:5))
242 #define SHIP_GAUGE_Y            (SHIELD_GAUGE_Y+(SM_HIRES?10:5))
243
244 #define SB_SHIELD_GAUGE_X       (SM_HIRES?247:123) //139
245 #define SB_SHIELD_GAUGE_Y       (SM_HIRES?395:163)
246
247 #define SB_SHIP_GAUGE_X         (SB_SHIELD_GAUGE_X+(SM_HIRES?11:5))
248 #define SB_SHIP_GAUGE_Y         (SB_SHIELD_GAUGE_Y+(SM_HIRES?10:5))
249
250 #define SB_SHIELD_NUM_X         (SB_SHIELD_GAUGE_X+(SM_HIRES?21:12)) //151
251 #define SB_SHIELD_NUM_Y         (SB_SHIELD_GAUGE_Y-(SM_HIRES?16:8))  //156 -- MWA used to be hard coded to 156
252
253 #define NUMERICAL_GAUGE_X       (SM_HIRES?308:154)
254 #define NUMERICAL_GAUGE_Y       (SM_HIRES?316:130)
255 #define NUMERICAL_GAUGE_W       (SM_HIRES?38:19)
256 #define NUMERICAL_GAUGE_H       (SM_HIRES?55:22)
257
258 #define PRIMARY_W_PIC_X         (SM_HIRES?(135-10):64)
259 #define PRIMARY_W_PIC_Y         (SM_HIRES?370:154)
260 #define PRIMARY_W_TEXT_X        (SM_HIRES?182:87)
261 #define PRIMARY_W_TEXT_Y        (SM_HIRES?400:157)
262 #define PRIMARY_AMMO_X          (SM_HIRES?186:(96-3))
263 #define PRIMARY_AMMO_Y          (SM_HIRES?420:171)
264
265 #define SECONDARY_W_PIC_X       (SM_HIRES?466:234)
266 #define SECONDARY_W_PIC_Y       (SM_HIRES?374:154)
267 #define SECONDARY_W_TEXT_X      (SM_HIRES?413:207)
268 #define SECONDARY_W_TEXT_Y      (SM_HIRES?378:157)
269 #define SECONDARY_AMMO_X        (SM_HIRES?428:213)
270 #define SECONDARY_AMMO_Y        (SM_HIRES?407:171)
271
272 #define SB_LIVES_X              (SM_HIRES?(550-10-3):266)
273 #define SB_LIVES_Y              (SM_HIRES?450-3:185)
274 #define SB_LIVES_LABEL_X        (SM_HIRES?475:237)
275 #define SB_LIVES_LABEL_Y                (SB_LIVES_Y+1)
276
277 #define SB_SCORE_RIGHT_L                301
278 #define SB_SCORE_RIGHT_H                (605+8)
279 #define SB_SCORE_RIGHT          (SM_HIRES?SB_SCORE_RIGHT_H:SB_SCORE_RIGHT_L)
280
281 #define SB_SCORE_Y              (SM_HIRES?398:158)
282 #define SB_SCORE_LABEL_X        (SM_HIRES?475:237)
283
284 #define SB_SCORE_ADDED_RIGHT    (SM_HIRES?SB_SCORE_RIGHT_H:SB_SCORE_RIGHT_L)
285 #define SB_SCORE_ADDED_Y        (SM_HIRES?413:165)
286
287 #define HOMING_WARNING_X        (SM_HIRES?14:7)
288 #define HOMING_WARNING_Y        (SM_HIRES?415:171)
289
290 #define BOMB_COUNT_X            (SM_HIRES?546:275)
291 #define BOMB_COUNT_Y            (SM_HIRES?445:186)
292
293 #define SB_BOMB_COUNT_X         (SM_HIRES?342:171)
294 #define SB_BOMB_COUNT_Y         (SM_HIRES?458:191)
295
296 #define LHX(x)          ((x)*(MenuHires?2:1))
297 #define LHY(y)          ((y)*(MenuHires?2.4:1))
298
299 static int score_display[2];
300 static fix score_time;
301
302 static int old_score[2]                         = { -1, -1 };
303 static int old_energy[2]                        = { -1, -1 };
304 static int old_shields[2]                       = { -1, -1 };
305 static int old_flags[2]                         = { -1, -1 };
306 static int old_weapon[2][2]             = {{ -1, -1 },{-1,-1}};
307 static int old_ammo_count[2][2] = {{ -1, -1 },{-1,-1}};
308 static int Old_Omega_charge[2]  = { -1, -1 };
309 static int old_laser_level[2]           = { -1, -1 };
310 static int old_cloak[2]                         = { 0, 0 };
311 static int old_lives[2]                         = { -1, -1 };
312 static fix old_afterburner[2]           = { -1, -1 };
313 static int old_bombcount[2]             = { 0, 0 };
314
315 static int invulnerable_frame = 0;
316
317 static int cloak_fade_state;            //0=steady, -1 fading out, 1 fading in 
318
319 #define WS_SET                          0               //in correct state
320 #define WS_FADING_OUT   1
321 #define WS_FADING_IN            2
322
323 int weapon_box_user[2]={WBU_WEAPON,WBU_WEAPON};         //see WBU_ constants in gauges.h
324 int weapon_box_states[2] = {WS_SET, WS_SET};
325 fix weapon_box_fade_values[2];
326
327 #define FADE_SCALE      (2*i2f(GR_FADE_LEVELS)/REARM_TIME)              // fade out and back in REARM_TIME, in fade levels per seconds (int)
328
329 typedef struct span {
330         sbyte l,r;
331 } span;
332
333 //store delta x values from left of box
334 span weapon_window_left[] = {           //first span 67,151
335                 {8,51},
336                 {6,53},
337                 {5,54},
338                 {4-1,53+2},
339                 {4-1,53+3},
340                 {4-1,53+3},
341                 {4-2,53+3},
342                 {4-2,53+3},
343                 {3-1,53+3},
344                 {3-1,53+3},
345                 {3-1,53+3},
346                 {3-1,53+3},
347                 {3-1,53+3},
348                 {3-1,53+3},
349                 {3-1,53+3},
350                 {3-2,53+3},
351                 {2-1,53+3},
352                 {2-1,53+3},
353                 {2-1,53+3},
354                 {2-1,53+3},
355                 {2-1,53+3},
356                 {2-1,53+3},
357                 {2-1,53+3},
358                 {2-1,53+3},
359                 {1-1,53+3},
360                 {1-1,53+2},
361                 {1-1,53+2},
362                 {1-1,53+2},
363                 {1-1,53+2},
364                 {1-1,53+2},
365                 {1-1,53+2},
366                 {1-1,53+2},
367                 {0,53+2},
368                 {0,53+2},
369                 {0,53+2},
370                 {0,53+2},
371                 {0,52+3},
372                 {1-1,52+2},
373                 {2-2,51+3},
374                 {3-2,51+2},
375                 {4-2,50+2},
376                 {5-2,50},
377                 {5-2+2,50-2},
378         };
379
380
381 //store delta x values from left of box
382 span weapon_window_right[] = {          //first span 207,154
383                 {208-202,255-202},
384                 {206-202,257-202},
385                 {205-202,258-202},
386                 {204-202,259-202},
387                 {203-202,260-202},
388                 {203-202,260-202},
389                 {203-202,260-202},
390                 {203-202,260-202},
391                 {203-202,260-202},
392                 {203-202,261-202},
393                 {203-202,261-202},
394                 {203-202,261-202},
395                 {203-202,261-202},
396                 {203-202,261-202},
397                 {203-202,261-202},
398                 {203-202,261-202},
399                 {203-202,261-202},
400                 {203-202,261-202},
401                 {203-202,262-202},
402                 {203-202,262-202},
403                 {203-202,262-202},
404                 {203-202,262-202},
405                 {203-202,262-202},
406                 {203-202,262-202},
407                 {203-202,262-202},
408                 {203-202,262-202},
409                 {204-202,263-202},
410                 {204-202,263-202},
411                 {204-202,263-202},
412                 {204-202,263-202},
413                 {204-202,263-202},
414                 {204-202,263-202},
415                 {204-202,263-202},
416                 {204-202,263-202},
417                 {204-202,263-202},
418                 {204-202,263-202},
419                 {204-202,263-202},
420                 {204-202,263-202},
421                 {205-202,263-202},
422                 {206-202,262-202},
423                 {207-202,261-202},
424                 {208-202,260-202},
425                 {211-202,255-202},
426         };
427
428 //store delta x values from left of box
429 span weapon_window_left_hires[] = {             //first span 67,154
430         {20,110},
431         {18,113},
432         {16,114},
433         {15,116},
434         {14,117},
435         {13,118},
436         {12,119},
437         {11,119},
438         {10,120},
439         {10,120},
440         {9,121},
441         {8,121},
442         {8,121},
443         {8,122},
444         {7,122},
445         {7,122},
446         {7,122},
447         {7,122},
448         {7,122},
449         {6,122},
450         {6,122},
451         {6,122},
452         {6,122},
453         {6,122},
454         {6,122},
455         {6,122},
456         {6,122},
457         {6,122},
458         {6,122},
459         {5,122},
460         {5,122},
461         {5,122},
462         {5,122},
463         {5,121},
464         {5,121},
465         {5,121},
466         {5,121},
467         {5,121},
468         {5,121},
469         {4,121},
470         {4,121},
471         {4,121},
472         {4,121},
473         {4,121},
474         {4,121},
475         {4,121},
476         {4,121},
477         {4,121},
478         {4,121},
479         {3,121},
480         {3,121},
481         {3,120},
482         {3,120},
483         {3,120},
484         {3,120},
485         {3,120},
486         {3,120},
487         {3,120},
488         {3,120},
489         {3,120},
490         {2,120},
491         {2,120},
492         {2,120},
493         {2,120},
494         {2,120},
495         {2,120},
496         {2,120},
497         {2,120},
498         {2,120},
499         {2,120},
500         {2,120},
501         {2,120},
502         {1,120},
503         {1,120},
504         {1,119},
505         {1,119},
506         {1,119},
507         {1,119},
508         {1,119},
509         {1,119},
510         {1,119},
511         {1,119},
512         {0,119},
513         {0,119},
514         {0,119},
515         {0,119},
516         {0,119},
517         {0,119},
518         {0,119},
519         {0,118},
520         {0,118},
521         {0,118},
522         {0,117},
523         {0,117},
524         {0,117},
525         {1,116},
526         {1,116},
527         {2,115},
528         {2,114},
529         {3,113},
530         {4,112},
531         {5,111},
532         {5,110},
533         {7,109},
534         {9,107},
535         {10,105},
536         {12,102},
537 };
538
539
540 //store delta x values from left of box
541 span weapon_window_right_hires[] = {            //first span 207,154
542         {12,105},
543         {9,107},
544         {8,109},
545         {6,110},
546         {5,111},
547         {4,112},
548         {3,113},
549         {3,114},
550         {2,115},
551         {2,115},
552         {1,116},
553         {1,117},
554         {1,117},
555         {0,117},
556         {0,118},
557         {0,118},
558         {0,118},
559         {0,118},
560         {0,118},
561         {0,119},
562         {0,119},
563         {0,119},
564         {0,119},
565         {0,119},
566         {0,119},
567         {0,119},
568         {0,119},
569         {0,119},
570         {0,119},
571         {0,120},
572         {0,120},
573         {0,120},
574         {0,120},
575         {1,120},
576         {1,120},
577         {1,120},
578         {1,120},
579         {1,120},
580         {1,120},
581         {1,121},
582         {1,121},
583         {1,121},
584         {1,121},
585         {1,121},
586         {1,121},
587         {1,121},
588         {1,121},
589         {1,121},
590         {1,121},
591         {1,122},
592         {1,122},
593         {2,122},
594         {2,122},
595         {2,122},
596         {2,122},
597         {2,122},
598         {2,122},
599         {2,122},
600         {2,122},
601         {2,123},
602         {2,123},
603         {2,123},
604         {2,123},
605         {2,123},
606         {2,123},
607         {2,123},
608         {2,123},
609         {2,123},
610         {2,123},
611         {2,123},
612         {2,123},
613         {2,123},
614         {2,124},
615         {2,124},
616         {3,124},
617         {3,124},
618         {3,124},
619         {3,124},
620         {3,124},
621         {3,124},
622         {3,124},
623         {3,125},
624         {3,125},
625         {3,125},
626         {3,125},
627         {3,125},
628         {3,125},
629         {3,125},
630         {3,125},
631         {4,125},
632         {4,125},
633         {4,125},
634         {5,125},
635         {5,125},
636         {5,125},
637         {6,125},
638         {6,124},
639         {7,123},
640         {8,123},
641         {9,122},
642         {10,121},
643         {11,120},
644         {12,120},
645         {13,118},
646         {15,117},
647         {18,115},
648         {20,114},
649 };
650
651                                                                                         
652 #define N_LEFT_WINDOW_SPANS  (sizeof(weapon_window_left)/sizeof(*weapon_window_left))
653 #define N_RIGHT_WINDOW_SPANS (sizeof(weapon_window_right)/sizeof(*weapon_window_right))
654
655 #define N_LEFT_WINDOW_SPANS_H  (sizeof(weapon_window_left_hires)/sizeof(*weapon_window_left_hires))
656 #define N_RIGHT_WINDOW_SPANS_H (sizeof(weapon_window_right_hires)/sizeof(*weapon_window_right_hires))
657
658 // defining box boundries for weapon pictures
659
660 #define PRIMARY_W_BOX_LEFT_L            63
661 #define PRIMARY_W_BOX_TOP_L             151             //154
662 #define PRIMARY_W_BOX_RIGHT_L           (PRIMARY_W_BOX_LEFT_L+58)
663 #define PRIMARY_W_BOX_BOT_L             (PRIMARY_W_BOX_TOP_L+N_LEFT_WINDOW_SPANS-1)
664                                                                                         
665 #define PRIMARY_W_BOX_LEFT_H            121
666 #define PRIMARY_W_BOX_TOP_H             364
667 #define PRIMARY_W_BOX_RIGHT_H           242
668 #define PRIMARY_W_BOX_BOT_H             (PRIMARY_W_BOX_TOP_H+N_LEFT_WINDOW_SPANS_H-1)           //470
669                                                                                         
670 #define PRIMARY_W_BOX_LEFT      (SM_HIRES?PRIMARY_W_BOX_LEFT_H:PRIMARY_W_BOX_LEFT_L)
671 #define PRIMARY_W_BOX_TOP       (SM_HIRES?PRIMARY_W_BOX_TOP_H:PRIMARY_W_BOX_TOP_L)
672 #define PRIMARY_W_BOX_RIGHT     (SM_HIRES?PRIMARY_W_BOX_RIGHT_H:PRIMARY_W_BOX_RIGHT_L)
673 #define PRIMARY_W_BOX_BOT       (SM_HIRES?PRIMARY_W_BOX_BOT_H:PRIMARY_W_BOX_BOT_L)
674
675 #define SECONDARY_W_BOX_LEFT_L  202     //207
676 #define SECONDARY_W_BOX_TOP_L           151
677 #define SECONDARY_W_BOX_RIGHT_L 263     //(SECONDARY_W_BOX_LEFT+54)
678 #define SECONDARY_W_BOX_BOT_L           (SECONDARY_W_BOX_TOP_L+N_RIGHT_WINDOW_SPANS-1)
679
680 #define SECONDARY_W_BOX_LEFT_H  404
681 #define SECONDARY_W_BOX_TOP_H           363
682 #define SECONDARY_W_BOX_RIGHT_H 529
683 #define SECONDARY_W_BOX_BOT_H           (SECONDARY_W_BOX_TOP_H+N_RIGHT_WINDOW_SPANS_H-1)                //470
684
685 #define SECONDARY_W_BOX_LEFT    (SM_HIRES?SECONDARY_W_BOX_LEFT_H:SECONDARY_W_BOX_LEFT_L)
686 #define SECONDARY_W_BOX_TOP     (SM_HIRES?SECONDARY_W_BOX_TOP_H:SECONDARY_W_BOX_TOP_L)
687 #define SECONDARY_W_BOX_RIGHT   (SM_HIRES?SECONDARY_W_BOX_RIGHT_H:SECONDARY_W_BOX_RIGHT_L)
688 #define SECONDARY_W_BOX_BOT     (SM_HIRES?SECONDARY_W_BOX_BOT_H:SECONDARY_W_BOX_BOT_L)
689
690 #define SB_PRIMARY_W_BOX_LEFT_L         34              //50
691 #define SB_PRIMARY_W_BOX_TOP_L          153
692 #define SB_PRIMARY_W_BOX_RIGHT_L                (SB_PRIMARY_W_BOX_LEFT_L+53+2)
693 #define SB_PRIMARY_W_BOX_BOT_L          (195+1)
694                                                                                         
695 #define SB_PRIMARY_W_BOX_LEFT_H         68
696 #define SB_PRIMARY_W_BOX_TOP_H          381
697 #define SB_PRIMARY_W_BOX_RIGHT_H                179
698 #define SB_PRIMARY_W_BOX_BOT_H          473
699                                                                                         
700 #define SB_PRIMARY_W_BOX_LEFT   (SM_HIRES?SB_PRIMARY_W_BOX_LEFT_H:SB_PRIMARY_W_BOX_LEFT_L)
701 #define SB_PRIMARY_W_BOX_TOP    (SM_HIRES?SB_PRIMARY_W_BOX_TOP_H:SB_PRIMARY_W_BOX_TOP_L)
702 #define SB_PRIMARY_W_BOX_RIGHT  (SM_HIRES?SB_PRIMARY_W_BOX_RIGHT_H:SB_PRIMARY_W_BOX_RIGHT_L)
703 #define SB_PRIMARY_W_BOX_BOT    (SM_HIRES?SB_PRIMARY_W_BOX_BOT_H:SB_PRIMARY_W_BOX_BOT_L)
704                                                                                         
705 #define SB_SECONDARY_W_BOX_LEFT_L       169
706 #define SB_SECONDARY_W_BOX_TOP_L                153
707 #define SB_SECONDARY_W_BOX_RIGHT_L      (SB_SECONDARY_W_BOX_LEFT_L+54+1)
708 #define SB_SECONDARY_W_BOX_BOT_L                (153+43)
709
710 #define SB_SECONDARY_W_BOX_LEFT_H       338
711 #define SB_SECONDARY_W_BOX_TOP_H                381
712 #define SB_SECONDARY_W_BOX_RIGHT_H      449
713 #define SB_SECONDARY_W_BOX_BOT_H                473
714
715 #define SB_SECONDARY_W_BOX_LEFT (SM_HIRES?SB_SECONDARY_W_BOX_LEFT_H:SB_SECONDARY_W_BOX_LEFT_L) //210
716 #define SB_SECONDARY_W_BOX_TOP  (SM_HIRES?SB_SECONDARY_W_BOX_TOP_H:SB_SECONDARY_W_BOX_TOP_L)
717 #define SB_SECONDARY_W_BOX_RIGHT (SM_HIRES?SB_SECONDARY_W_BOX_RIGHT_H:SB_SECONDARY_W_BOX_RIGHT_L)
718 #define SB_SECONDARY_W_BOX_BOT  (SM_HIRES?SB_SECONDARY_W_BOX_BOT_H:SB_SECONDARY_W_BOX_BOT_L)
719
720 #define SB_PRIMARY_W_PIC_X                      (SB_PRIMARY_W_BOX_LEFT+1)       //51
721 #define SB_PRIMARY_W_PIC_Y      (SM_HIRES?382:154)
722 #define SB_PRIMARY_W_TEXT_X     (SB_PRIMARY_W_BOX_LEFT+(SM_HIRES?50:24)) //(51+23)
723 #define SB_PRIMARY_W_TEXT_Y     (SM_HIRES?390:157)
724 #define SB_PRIMARY_AMMO_X       (SB_PRIMARY_W_BOX_LEFT+(SM_HIRES?(38+20):30))   //((SB_PRIMARY_W_BOX_LEFT+33)-3) //(51+32)
725 #define SB_PRIMARY_AMMO_Y       (SM_HIRES?410:171)
726
727 #define SB_SECONDARY_W_PIC_X    (SM_HIRES?385:(SB_SECONDARY_W_BOX_LEFT+29))     //(212+27)
728 #define SB_SECONDARY_W_PIC_Y    (SM_HIRES?382:154)
729 #define SB_SECONDARY_W_TEXT_X           (SB_SECONDARY_W_BOX_LEFT+2)     //212
730 #define SB_SECONDARY_W_TEXT_Y   (SM_HIRES?389:157)
731 #define SB_SECONDARY_AMMO_X     (SB_SECONDARY_W_BOX_LEFT+(SM_HIRES?(14-4):11))  //(212+9)
732 #define SB_SECONDARY_AMMO_Y     (SM_HIRES?414:171)
733
734 typedef struct gauge_box {
735         int left,top;
736         int right,bot;          //maximal box
737         span *spanlist; //list of left,right spans for copy
738 } gauge_box;
739
740 gauge_box gauge_boxes[] = {
741
742 // primary left/right low res
743                 {PRIMARY_W_BOX_LEFT_L,PRIMARY_W_BOX_TOP_L,PRIMARY_W_BOX_RIGHT_L,PRIMARY_W_BOX_BOT_L,weapon_window_left},
744                 {SECONDARY_W_BOX_LEFT_L,SECONDARY_W_BOX_TOP_L,SECONDARY_W_BOX_RIGHT_L,SECONDARY_W_BOX_BOT_L,weapon_window_right},
745
746 //sb left/right low res
747                 {SB_PRIMARY_W_BOX_LEFT_L,SB_PRIMARY_W_BOX_TOP_L,SB_PRIMARY_W_BOX_RIGHT_L,SB_PRIMARY_W_BOX_BOT_L,NULL},
748                 {SB_SECONDARY_W_BOX_LEFT_L,SB_SECONDARY_W_BOX_TOP_L,SB_SECONDARY_W_BOX_RIGHT_L,SB_SECONDARY_W_BOX_BOT_L,NULL},
749
750 // primary left/right hires
751                 {PRIMARY_W_BOX_LEFT_H,PRIMARY_W_BOX_TOP_H,PRIMARY_W_BOX_RIGHT_H,PRIMARY_W_BOX_BOT_H,weapon_window_left_hires},
752                 {SECONDARY_W_BOX_LEFT_H,SECONDARY_W_BOX_TOP_H,SECONDARY_W_BOX_RIGHT_H,SECONDARY_W_BOX_BOT_H,weapon_window_right_hires},
753
754 // sb left/right hires
755                 {SB_PRIMARY_W_BOX_LEFT_H,SB_PRIMARY_W_BOX_TOP_H,SB_PRIMARY_W_BOX_RIGHT_H,SB_PRIMARY_W_BOX_BOT_H,NULL},
756                 {SB_SECONDARY_W_BOX_LEFT_H,SB_SECONDARY_W_BOX_TOP_H,SB_SECONDARY_W_BOX_RIGHT_H,SB_SECONDARY_W_BOX_BOT_H,NULL},
757         };
758
759 // these macros refer to arrays above
760
761 #define COCKPIT_PRIMARY_BOX     (SM_HIRES?4:0)
762 #define COCKPIT_SECONDARY_BOX   (SM_HIRES?5:1)
763 #define SB_PRIMARY_BOX          (SM_HIRES?6:2)
764 #define SB_SECONDARY_BOX        (SM_HIRES?7:3)
765
766 int     Color_0_31_0 = -1;
767
768 //copy a box from the off-screen buffer to the visible page
769 void copy_gauge_box(gauge_box *box,grs_bitmap *bm)
770 {
771         if (box->spanlist) {
772                 int n_spans = box->bot-box->top+1;
773                 int cnt,y;
774
775 //gr_setcolor(BM_XRGB(31,0,0));
776
777                 for (cnt=0,y=box->top;cnt<n_spans;cnt++,y++) {
778                         gr_bm_ubitblt(box->spanlist[cnt].r-box->spanlist[cnt].l+1,1,
779                                                 box->left+box->spanlist[cnt].l,y,box->left+box->spanlist[cnt].l,y,bm,&grd_curcanv->cv_bitmap);
780
781                         //gr_scanline(box->left+box->spanlist[cnt].l,box->left+box->spanlist[cnt].r,y);
782                 }
783         }
784         else
785          {
786                 gr_bm_ubitblt(box->right-box->left+1,box->bot-box->top+1,
787                                                 box->left,box->top,box->left,box->top,
788                                                 bm,&grd_curcanv->cv_bitmap);
789          }
790 }
791
792 //fills in the coords of the hostage video window
793 void get_hostage_window_coords(int *x,int *y,int *w,int *h)
794 {
795         if (Cockpit_mode.intval == CM_STATUS_BAR) {
796                 *x = SB_SECONDARY_W_BOX_LEFT;
797                 *y = SB_SECONDARY_W_BOX_TOP;
798                 *w = SB_SECONDARY_W_BOX_RIGHT - SB_SECONDARY_W_BOX_LEFT + 1;
799                 *h = SB_SECONDARY_W_BOX_BOT - SB_SECONDARY_W_BOX_TOP + 1;
800         }
801         else {
802                 *x = SECONDARY_W_BOX_LEFT;
803                 *y = SECONDARY_W_BOX_TOP;
804                 *w = SECONDARY_W_BOX_RIGHT - SECONDARY_W_BOX_LEFT + 1;
805                 *h = SECONDARY_W_BOX_BOT - SECONDARY_W_BOX_TOP + 1;
806         }
807
808 }
809
810 //these should be in gr.h 
811 #define cv_w  cv_bitmap.bm_w
812 #define cv_h  cv_bitmap.bm_h
813
814 extern int HUD_nmessages, hud_first; // From hud.c
815 extern char HUD_messages[HUD_MAX_NUM][HUD_MESSAGE_LENGTH+5]; 
816 extern fix ThisLevelTime;
817 extern fix Omega_charge;
818
819 void hud_show_score()
820 {
821         char    score_str[20];
822         int     w, h, aw;
823
824         if ((HUD_nmessages > 0) && (strlen(HUD_messages[hud_first]) > 38))
825                 return;
826
827         gr_set_curfont( GAME_FONT );
828
829         if ( ((Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP)) ) {
830                 sprintf(score_str, "%s: %5d", TXT_KILLS, Players[Player_num].net_kills_total);
831         } else {
832                 sprintf(score_str, "%s: %5d", TXT_SCORE, Players[Player_num].score);
833         }
834
835         gr_get_string_size(score_str, &w, &h, &aw );
836
837         if (Color_0_31_0 == -1)
838                 Color_0_31_0 = gr_getcolor(0,31,0);
839         gr_set_fontcolor(Color_0_31_0, -1);
840
841         gr_printf(grd_curcanv->cv_w-w-LHX(2), 3, score_str);
842  }
843
844 void hud_show_timer_count()
845  {
846 #ifdef NETWORK
847         char    score_str[20];
848         int     w, h, aw,i;
849         fix timevar=0;
850 #endif
851
852         if ((HUD_nmessages > 0) && (strlen(HUD_messages[hud_first]) > 38))
853                 return;
854
855 #ifdef NETWORK
856    if ((Game_mode & GM_NETWORK) && Netgame.PlayTimeAllowed)
857     {
858      timevar=i2f (Netgame.PlayTimeAllowed*5*60);
859      i=f2i(timevar-ThisLevelTime);
860      i++;
861     
862      sprintf(score_str, "T - %5d", i);
863                                                                                                                                                                                                  
864      gr_get_string_size(score_str, &w, &h, &aw );
865
866      if (Color_0_31_0 == -1)
867                 Color_0_31_0 = gr_getcolor(0,31,0);
868      gr_set_fontcolor(Color_0_31_0, -1);
869
870      if (i>-1 && !Control_center_destroyed)
871              gr_printf(grd_curcanv->cv_w-w-LHX(10), LHX(11), score_str);
872     }
873 #endif
874  }
875
876
877 //y offset between lines on HUD
878 int Line_spacing;
879
880 void hud_show_score_added()
881 {
882         int     color;
883         int     w, h, aw;
884         char    score_str[20];
885
886         if ( (Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP) ) 
887                 return;
888
889         if (score_display[0] == 0)
890                 return;
891
892         gr_set_curfont( GAME_FONT );
893
894         score_time -= FrameTime;
895         if (score_time > 0) {
896                 color = f2i(score_time * 20) + 12;
897
898                 if (color < 10) color = 12;
899                 if (color > 31) color = 30;
900
901                 color = color - (color % 4);    //      Only allowing colors 12,16,20,24,28 speeds up gr_getcolor, improves caching
902
903                 if (Cheats_enabled)
904                         sprintf(score_str, "%s", TXT_CHEATER);
905                 else
906                         sprintf(score_str, "%5d", score_display[0]);
907
908                 gr_get_string_size(score_str, &w, &h, &aw );
909                 gr_set_fontcolor(gr_getcolor(0, color, 0),-1 );
910                 gr_printf(grd_curcanv->cv_w-w-LHX(2+10), Line_spacing+4, score_str);
911         } else {
912                 score_time = 0;
913                 score_display[0] = 0;
914         }
915         
916 }
917
918 void sb_show_score()
919 {                                                                                                                                                                                                                                                                    
920         char    score_str[20];
921         int x,y;
922         int     w, h, aw;
923         static int last_x[4]={SB_SCORE_RIGHT_L,SB_SCORE_RIGHT_L,SB_SCORE_RIGHT_H,SB_SCORE_RIGHT_H};
924         int redraw_score;
925
926         if ( (Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP) ) 
927                 redraw_score = -99;
928         else
929                 redraw_score = -1;
930
931         //if (old_score[VR_current_page] == redraw_score)
932         {
933                 gr_set_curfont( GAME_FONT );
934                 gr_set_fontcolor(gr_getcolor(0,20,0),-1 );
935
936                 if ( (Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP) ) 
937                         {
938                          gr_printf(SB_SCORE_LABEL_X,SB_SCORE_Y,"%s:", TXT_KILLS);
939                         }
940                 else
941                   {
942                         gr_printf(SB_SCORE_LABEL_X,SB_SCORE_Y,"%s:", TXT_SCORE);
943                   }
944         }
945
946         gr_set_curfont( GAME_FONT );
947         if ( (Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP) ) 
948                 sprintf(score_str, "%5d", Players[Player_num].net_kills_total);
949         else
950                 sprintf(score_str, "%5d", Players[Player_num].score);
951         gr_get_string_size(score_str, &w, &h, &aw );
952
953         x = SB_SCORE_RIGHT-w-LHX(2);
954         y = SB_SCORE_Y;
955         
956         //erase old score
957         gr_setcolor(BM_XRGB(0,0,0));
958         gr_rect(last_x[(SM_HIRES?2:0) + VR_current_page], y, SB_SCORE_RIGHT, y + GAME_FONT->ft_h);
959
960         if ( (Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP) ) 
961                 gr_set_fontcolor(gr_getcolor(0,20,0),-1 );
962         else
963                 gr_set_fontcolor(gr_getcolor(0,31,0),-1 );      
964  
965         gr_printf(x,y,score_str);
966
967         last_x[(SM_HIRES?2:0) + VR_current_page] = x;
968 }
969
970 void sb_show_score_added()
971 {
972         int     color;
973         int w, h, aw;
974         char    score_str[32];
975         int x;
976         static int last_x[4]={SB_SCORE_RIGHT_L,SB_SCORE_RIGHT_L,SB_SCORE_RIGHT_H,SB_SCORE_RIGHT_H};
977         static  int last_score_display[2] = { -1, -1};
978         
979         if ( (Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP) ) 
980                 return;
981
982         if (score_display[VR_current_page] == 0)
983                 return;
984
985         gr_set_curfont( GAME_FONT );
986
987         score_time -= FrameTime;
988         if (score_time > 0) {
989                 if (score_display[VR_current_page] != last_score_display[VR_current_page])
990                 {
991                         gr_setcolor(BM_XRGB(0,0,0));
992                         gr_rect(last_x[(SM_HIRES?2:0) + VR_current_page], SB_SCORE_ADDED_Y, SB_SCORE_ADDED_RIGHT, SB_SCORE_ADDED_Y + GAME_FONT->ft_h);
993
994                         last_score_display[VR_current_page] = score_display[VR_current_page];
995                 }
996
997                 color = f2i(score_time * 20) + 10;
998
999                 if (color < 10) color = 10;
1000                 if (color > 31) color = 31;
1001
1002                 if (Cheats_enabled)
1003                         sprintf(score_str, "%s", TXT_CHEATER);
1004                 else
1005                         sprintf(score_str, "%5d", score_display[VR_current_page]);
1006
1007                 gr_get_string_size(score_str, &w, &h, &aw );
1008
1009                 x = SB_SCORE_ADDED_RIGHT-w-LHX(2);
1010
1011                 gr_set_fontcolor(gr_getcolor(0, color, 0),-1 );
1012
1013                 gr_printf(x, SB_SCORE_ADDED_Y, score_str);
1014
1015
1016                 last_x[(SM_HIRES?2:0) + VR_current_page] = x;
1017
1018         } else {
1019                 //erase old score
1020                 gr_setcolor(BM_XRGB(0,0,0));
1021                 gr_rect(last_x[(SM_HIRES?2:0) + VR_current_page], SB_SCORE_ADDED_Y, SB_SCORE_ADDED_RIGHT, SB_SCORE_ADDED_Y + GAME_FONT->ft_h);
1022
1023                 score_time = 0;
1024                 score_display[VR_current_page] = 0;
1025
1026         }
1027 }
1028
1029 fix     Last_warning_beep_time[2] = {0,0};              //      Time we last played homing missile warning beep.
1030
1031 //      -----------------------------------------------------------------------------
1032 void play_homing_warning(void)
1033 {
1034         fix     beep_delay;
1035
1036         if (Endlevel_sequence || Player_is_dead)
1037                 return;
1038
1039         if (Players[Player_num].homing_object_dist >= 0) {
1040                 beep_delay = Players[Player_num].homing_object_dist/128;
1041                 if (beep_delay > F1_0)
1042                         beep_delay = F1_0;
1043                 else if (beep_delay < F1_0/8)
1044                         beep_delay = F1_0/8;
1045
1046                 if (Last_warning_beep_time[VR_current_page] > GameTime)
1047                         Last_warning_beep_time[VR_current_page] = 0;
1048
1049                 if (GameTime - Last_warning_beep_time[VR_current_page] > beep_delay/2) {
1050                         digi_play_sample( SOUND_HOMING_WARNING, F1_0 );
1051                         Last_warning_beep_time[VR_current_page] = GameTime;
1052                 }
1053         }
1054 }
1055
1056 int     Last_homing_warning_shown[2]={-1,-1};
1057
1058 //      -----------------------------------------------------------------------------
1059 void show_homing_warning(void)
1060 {
1061         if ((Cockpit_mode.intval == CM_STATUS_BAR) || (Endlevel_sequence)) {
1062                 if (Last_homing_warning_shown[VR_current_page] == 1) {
1063                         PAGE_IN_GAUGE( GAUGE_HOMING_WARNING_OFF );
1064
1065                         gr_ubitmapm( HOMING_WARNING_X, HOMING_WARNING_Y, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_HOMING_WARNING_OFF) ] );
1066
1067                         Last_homing_warning_shown[VR_current_page] = 0;
1068                 }
1069                 return;
1070         }
1071
1072         gr_set_current_canvas( get_current_game_screen() );
1073
1074
1075         if (Players[Player_num].homing_object_dist >= 0) {
1076
1077                 if (GameTime & 0x4000) {
1078                         if (Last_homing_warning_shown[VR_current_page] != 1) {
1079                                 PAGE_IN_GAUGE( GAUGE_HOMING_WARNING_ON );
1080                                 gr_ubitmapm( HOMING_WARNING_X, HOMING_WARNING_Y, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_HOMING_WARNING_ON) ] );
1081                                 Last_homing_warning_shown[VR_current_page] = 1;
1082                         }
1083                 } else {
1084                         if (Last_homing_warning_shown[VR_current_page] != 0) {
1085                                 PAGE_IN_GAUGE( GAUGE_HOMING_WARNING_OFF );
1086                                 gr_ubitmapm( HOMING_WARNING_X, HOMING_WARNING_Y, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_HOMING_WARNING_OFF) ] );
1087                                 Last_homing_warning_shown[VR_current_page] = 0;
1088                         }
1089                 }
1090         } else if (Last_homing_warning_shown[VR_current_page] != 0) {
1091                 PAGE_IN_GAUGE( GAUGE_HOMING_WARNING_OFF );
1092                 gr_ubitmapm( HOMING_WARNING_X, HOMING_WARNING_Y, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_HOMING_WARNING_OFF) ] );
1093                 Last_homing_warning_shown[VR_current_page] = 0;
1094         }
1095 }
1096
1097 #define MAX_SHOWN_LIVES 4
1098
1099 extern int Game_window_y;
1100 extern int SW_y[2];
1101
1102 void hud_show_homing_warning(void)
1103 {
1104         if (Players[Player_num].homing_object_dist >= 0) {
1105                 if (GameTime & 0x4000) {
1106                         int x=0x8000, y=grd_curcanv->cv_h-Line_spacing;
1107
1108                         if (weapon_box_user[0] != WBU_WEAPON || weapon_box_user[1] != WBU_WEAPON) {
1109                                 int wy = (weapon_box_user[0] != WBU_WEAPON)?SW_y[0]:SW_y[1];
1110                                 y = min(y,(wy - Line_spacing - Game_window_y));
1111                         }
1112
1113                         gr_set_curfont( GAME_FONT );
1114                         gr_set_fontcolor(gr_getcolor(0,31,0),-1 );
1115                         gr_printf(x,y,TXT_LOCK);
1116                 }
1117         }
1118 }
1119
1120 void hud_show_keys(void)
1121 {
1122         int y = 3*Line_spacing;
1123         int dx = GAME_FONT->ft_w+GAME_FONT->ft_w/2;
1124
1125         if (Players[Player_num].flags & PLAYER_FLAGS_BLUE_KEY) {
1126                 PAGE_IN_GAUGE( KEY_ICON_BLUE );
1127                 gr_ubitmapm(2,y,&GameBitmaps[ GET_GAUGE_INDEX(KEY_ICON_BLUE) ] );
1128
1129         }
1130
1131         if (Players[Player_num].flags & PLAYER_FLAGS_GOLD_KEY) {
1132                 PAGE_IN_GAUGE( KEY_ICON_YELLOW );
1133                 gr_ubitmapm(2+dx,y,&GameBitmaps[ GET_GAUGE_INDEX(KEY_ICON_YELLOW) ] );
1134         }
1135
1136         if (Players[Player_num].flags & PLAYER_FLAGS_RED_KEY) {
1137                 PAGE_IN_GAUGE( KEY_ICON_RED );
1138                 gr_ubitmapm(2+2*dx,y,&GameBitmaps[ GET_GAUGE_INDEX(KEY_ICON_RED) ] );
1139         }
1140
1141 }
1142
1143 #ifdef NETWORK
1144 extern grs_bitmap Orb_icons[2];
1145
1146 void hud_show_orbs (void)
1147 {
1148         if (Game_mode & GM_HOARD) {
1149                 int x,y;
1150                 grs_bitmap *bm;
1151
1152                 x=y=0;
1153
1154                 if (Cockpit_mode.intval == CM_FULL_COCKPIT) {
1155                         y = 2*Line_spacing;
1156                         x = 4*GAME_FONT->ft_w;
1157                 }
1158                 else if (Cockpit_mode.intval == CM_STATUS_BAR) {
1159                         y = Line_spacing;
1160                         x = GAME_FONT->ft_w;
1161                 }
1162                 else if (Cockpit_mode.intval == CM_FULL_SCREEN) {
1163                         y = 5*Line_spacing;
1164                         x = GAME_FONT->ft_w;
1165                         if (FontHires)
1166                                 y += Line_spacing;
1167                 }
1168                 else
1169                         Int3();         //what sort of cockpit?
1170
1171                 bm = &Orb_icons[FontHires];
1172                 gr_ubitmapm(x,y,bm);
1173
1174                 gr_set_fontcolor(gr_getcolor(0,31,0),-1 );
1175                 gr_printf(x+bm->bm_w+bm->bm_w/2, y+(FontHires?2:1), "x %d", Players[Player_num].secondary_ammo[PROXIMITY_INDEX]);
1176
1177         }
1178 }
1179
1180 void hud_show_flag(void)
1181 {
1182         if ((Game_mode & GM_CAPTURE) && (Players[Player_num].flags & PLAYER_FLAGS_FLAG)) {
1183                 int x,y,icon;
1184
1185                 x=y=0;
1186
1187                 if (Cockpit_mode.intval == CM_FULL_COCKPIT) {
1188                         y = 2*Line_spacing;
1189                         x = 4*GAME_FONT->ft_w;
1190                 }
1191                 else if (Cockpit_mode.intval == CM_STATUS_BAR) {
1192                         y = Line_spacing;
1193                         x = GAME_FONT->ft_w;
1194                 }
1195                 else if (Cockpit_mode.intval == CM_FULL_SCREEN) {
1196                         y = 5*Line_spacing;
1197                         x = GAME_FONT->ft_w;
1198                         if (FontHires)
1199                                 y += Line_spacing;
1200                 }
1201                 else
1202                         Int3();         //what sort of cockpit?
1203
1204
1205                 icon = (get_team(Player_num) == TEAM_BLUE)?FLAG_ICON_RED:FLAG_ICON_BLUE;
1206
1207                 PAGE_IN_GAUGE( icon );
1208                 gr_ubitmapm(x,y,&GameBitmaps[ GET_GAUGE_INDEX(icon) ] );
1209
1210         }
1211 }
1212 #endif
1213
1214 void hud_show_energy(void)
1215 {
1216         //gr_set_current_canvas(&VR_render_sub_buffer[0]);      //render off-screen
1217         gr_set_curfont( GAME_FONT );
1218         gr_set_fontcolor(gr_getcolor(0,31,0),-1 );
1219         if (Game_mode & GM_MULTI)
1220                 gr_printf(2, grd_curcanv->cv_h-5*Line_spacing,"%s: %i", TXT_ENERGY, f2ir(Players[Player_num].energy));
1221         else
1222                 gr_printf(2, grd_curcanv->cv_h-Line_spacing,"%s: %i", TXT_ENERGY, f2ir(Players[Player_num].energy));
1223
1224         if (Newdemo_state==ND_STATE_RECORDING ) {
1225                 int energy = f2ir(Players[Player_num].energy);
1226
1227                 if (energy != old_energy[VR_current_page]) {
1228                         newdemo_record_player_energy(old_energy[VR_current_page], energy);
1229                         old_energy[VR_current_page] = energy;
1230                 }
1231         }
1232 }
1233
1234 void hud_show_afterburner(void)
1235 {
1236         int y;
1237
1238         if (! (Players[Player_num].flags & PLAYER_FLAGS_AFTERBURNER))
1239                 return;         //don't draw if don't have
1240
1241         gr_set_curfont( GAME_FONT );
1242         gr_set_fontcolor(gr_getcolor(0,31,0),-1 );
1243
1244         y = (Game_mode & GM_MULTI)?(-8*Line_spacing):(-3*Line_spacing);
1245
1246         gr_printf(2, grd_curcanv->cv_h+y, "burn: %d%%" , fixmul(Afterburner_charge,100));
1247
1248         if (Newdemo_state==ND_STATE_RECORDING ) {
1249
1250                 if (Afterburner_charge != old_afterburner[VR_current_page]) {
1251                         newdemo_record_player_afterburner(old_afterburner[VR_current_page], Afterburner_charge);
1252                         old_afterburner[VR_current_page] = Afterburner_charge;
1253                 }
1254         }
1255 }
1256
1257 char *d2_very_short_secondary_weapon_names[] =
1258                 {"Flash","Guided","SmrtMine","Mercury","Shaker"};
1259
1260 #define SECONDARY_WEAPON_NAMES_VERY_SHORT(weapon_num)                                   \
1261         ((weapon_num <= MEGA_INDEX)?(*(&TXT_CONCUSSION + (weapon_num))):        \
1262         d2_very_short_secondary_weapon_names[weapon_num-SMISSILE1_INDEX])
1263
1264 //return which bomb will be dropped next time the bomb key is pressed
1265 extern int which_bomb();
1266
1267 void show_bomb_count(int x,int y,int bg_color,int always_show)
1268 {
1269         int bomb,count,countx;
1270         char txt[5],*t;
1271
1272         bomb = which_bomb();
1273         count = Players[Player_num].secondary_ammo[bomb];
1274
1275         #ifndef RELEASE
1276         count = min(count,99);  //only have room for 2 digits - cheating give 200
1277         #endif
1278
1279         countx = (bomb==PROXIMITY_INDEX)?count:-count;
1280
1281         if (always_show && count == 0)          //no bombs, draw nothing on HUD
1282                 return;
1283
1284         //if (!always_show && countx == old_bombcount[VR_current_page])
1285         //      return;
1286
1287 // I hate doing this off of hard coded coords!!!!
1288
1289         if (Cockpit_mode.intval == CM_STATUS_BAR) { //draw background
1290                 gr_setcolor(bg_color);
1291                 if (!SM_HIRES) {
1292                         gr_rect(169,189,189,196);
1293                         gr_setcolor(gr_find_closest_color(10,10,10));
1294                         gr_scanline(168,189,189);
1295                 } else {
1296                         gr_rect(338,453,378,470);
1297
1298                         gr_setcolor(gr_find_closest_color(10,10,10));
1299                         gr_scanline(336,378,453);
1300                 }
1301         }
1302
1303         if (count)
1304                 gr_set_fontcolor((bomb==PROXIMITY_INDEX)?gr_find_closest_color(55,0,0):gr_getcolor(59,50,21),bg_color);
1305         else
1306                 gr_set_fontcolor(bg_color,bg_color);    //erase by drawing in background color
1307
1308         sprintf(txt,"B:%02d",count);
1309
1310         while ((t=strchr(txt,'1')) != NULL)
1311                 *t = '\x84';    //convert to wide '1'
1312
1313         gr_string(x,y,txt);
1314
1315         old_bombcount[VR_current_page] = countx;
1316 }
1317
1318 void draw_primary_ammo_info(int ammo_count)
1319 {
1320         if (Cockpit_mode.intval == CM_STATUS_BAR)
1321                 draw_ammo_info(SB_PRIMARY_AMMO_X,SB_PRIMARY_AMMO_Y,ammo_count,1);
1322         else
1323                 draw_ammo_info(PRIMARY_AMMO_X,PRIMARY_AMMO_Y,ammo_count,1);
1324 }
1325
1326 //convert '1' characters to special wide ones
1327 #define convert_1s(s) do {char *p=s; while ((p=strchr(p,'1')) != NULL) *p=132;} while(0)
1328
1329 void hud_show_weapons(void)
1330 {
1331         int     w, h, aw;
1332         int     y;
1333         char    *weapon_name;
1334         char    weapon_str[32];
1335
1336 //      gr_set_current_canvas(&VR_render_sub_buffer[0]);        //render off-screen
1337         gr_set_curfont( GAME_FONT );
1338         gr_set_fontcolor(gr_getcolor(0,31,0),-1 );
1339
1340         y = grd_curcanv->cv_h;
1341
1342         if (Game_mode & GM_MULTI)
1343                 y -= 4*Line_spacing;
1344
1345         weapon_name = PRIMARY_WEAPON_NAMES_SHORT(Primary_weapon);
1346
1347         switch (Primary_weapon) {
1348                 case LASER_INDEX:
1349                         if (Players[Player_num].flags & PLAYER_FLAGS_QUAD_LASERS)
1350                                 sprintf(weapon_str, "%s %s %i", TXT_QUAD, weapon_name, Players[Player_num].laser_level+1);
1351                         else
1352                                 sprintf(weapon_str, "%s %i", weapon_name, Players[Player_num].laser_level+1);
1353                         break;
1354
1355                 case SUPER_LASER_INDEX: Int3(); break;  //no such thing as super laser
1356
1357                 case VULCAN_INDEX:              
1358                 case GAUSS_INDEX:                       
1359                         sprintf(weapon_str, "%s: %i", weapon_name, f2i((unsigned) Players[Player_num].primary_ammo[VULCAN_INDEX] * (unsigned) VULCAN_AMMO_SCALE)); 
1360                         convert_1s(weapon_str);
1361                         break;
1362
1363                 case SPREADFIRE_INDEX:
1364                 case PLASMA_INDEX:
1365                 case FUSION_INDEX:
1366                 case HELIX_INDEX:
1367                 case PHOENIX_INDEX:
1368                         strcpy(weapon_str, weapon_name);
1369                         break;
1370                 case OMEGA_INDEX:
1371                         sprintf(weapon_str, "%s: %03i", weapon_name, Omega_charge * 100/MAX_OMEGA_CHARGE);
1372                         convert_1s(weapon_str);
1373                         break;
1374
1375                 default:                                                Int3(); weapon_str[0] = 0;      break;
1376         }
1377
1378         gr_get_string_size(weapon_str, &w, &h, &aw );
1379         gr_printf(grd_curcanv->cv_bitmap.bm_w-5-w, y-2*Line_spacing, weapon_str);
1380
1381         if (Primary_weapon == VULCAN_INDEX) {
1382                 if (Players[Player_num].primary_ammo[Primary_weapon] != old_ammo_count[0][VR_current_page]) {
1383                         if (Newdemo_state == ND_STATE_RECORDING)
1384                                 newdemo_record_primary_ammo(old_ammo_count[0][VR_current_page], Players[Player_num].primary_ammo[Primary_weapon]);
1385                         old_ammo_count[0][VR_current_page] = Players[Player_num].primary_ammo[Primary_weapon];
1386                 }
1387         }
1388
1389         if (Primary_weapon == OMEGA_INDEX) {
1390                 if (Omega_charge != Old_Omega_charge[VR_current_page]) {
1391                         if (Newdemo_state == ND_STATE_RECORDING)
1392                                 newdemo_record_primary_ammo(Old_Omega_charge[VR_current_page], Omega_charge);
1393                         Old_Omega_charge[VR_current_page] = Omega_charge;
1394                 }
1395         }
1396
1397         weapon_name = SECONDARY_WEAPON_NAMES_VERY_SHORT(Secondary_weapon);
1398
1399         sprintf(weapon_str, "%s %d",weapon_name,Players[Player_num].secondary_ammo[Secondary_weapon]);
1400         gr_get_string_size(weapon_str, &w, &h, &aw );
1401         gr_printf(grd_curcanv->cv_bitmap.bm_w-5-w, y-Line_spacing, weapon_str);
1402
1403         if (Players[Player_num].secondary_ammo[Secondary_weapon] != old_ammo_count[1][VR_current_page]) {
1404                 if (Newdemo_state == ND_STATE_RECORDING)
1405                         newdemo_record_secondary_ammo(old_ammo_count[1][VR_current_page], Players[Player_num].secondary_ammo[Secondary_weapon]);
1406                 old_ammo_count[1][VR_current_page] = Players[Player_num].secondary_ammo[Secondary_weapon];
1407         }
1408
1409         show_bomb_count(grd_curcanv->cv_bitmap.bm_w-(3*GAME_FONT->ft_w+(FontHires?0:2)), y-3*Line_spacing,-1,1);
1410 }
1411
1412 void hud_show_cloak_invuln(void)
1413 {
1414         gr_set_fontcolor(gr_getcolor(0,31,0),-1 );
1415
1416         if (Players[Player_num].flags & PLAYER_FLAGS_CLOAKED) {
1417                 int     y = grd_curcanv->cv_h;
1418
1419                 if (Game_mode & GM_MULTI)
1420                         y -= 7*Line_spacing;
1421                 else
1422                         y -= 4*Line_spacing;
1423
1424                 if ((Players[Player_num].cloak_time+CLOAK_TIME_MAX - GameTime > F1_0*3 ) || (GameTime & 0x8000))
1425                         gr_printf(2, y, "%s", TXT_CLOAKED);
1426         }
1427
1428         if (Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE) {
1429                 int     y = grd_curcanv->cv_h;
1430
1431                 if (Game_mode & GM_MULTI)
1432                         y -= 10*Line_spacing;
1433                 else
1434                         y -= 5*Line_spacing;
1435
1436                 if (((Players[Player_num].invulnerable_time + INVULNERABLE_TIME_MAX - GameTime) > F1_0*4) || (GameTime & 0x8000))
1437                         gr_printf(2, y, "%s", TXT_INVULNERABLE);
1438         }
1439
1440 }
1441
1442 void hud_show_shield(void)
1443 {
1444 //      gr_set_current_canvas(&VR_render_sub_buffer[0]);        //render off-screen
1445         gr_set_curfont( GAME_FONT );
1446         gr_set_fontcolor(gr_getcolor(0,31,0),-1 );
1447
1448         if ( Players[Player_num].shields >= 0 ) {
1449                 if (Game_mode & GM_MULTI)
1450                         gr_printf(2, grd_curcanv->cv_h-6*Line_spacing,"%s: %i", TXT_SHIELD, f2ir(Players[Player_num].shields));
1451                 else
1452                         gr_printf(2, grd_curcanv->cv_h-2*Line_spacing,"%s: %i", TXT_SHIELD, f2ir(Players[Player_num].shields));
1453         } else {
1454                 if (Game_mode & GM_MULTI)
1455                         gr_printf(2, grd_curcanv->cv_h-6*Line_spacing,"%s: 0", TXT_SHIELD );
1456                 else
1457                         gr_printf(2, grd_curcanv->cv_h-2*Line_spacing,"%s: 0", TXT_SHIELD );
1458         }
1459
1460         if (Newdemo_state==ND_STATE_RECORDING ) {
1461                 int shields = f2ir(Players[Player_num].shields);
1462
1463                 if (shields != old_shields[VR_current_page]) {          // Draw the shield gauge
1464                         newdemo_record_player_shields(old_shields[VR_current_page], shields);
1465                         old_shields[VR_current_page] = shields;
1466                 }
1467         }
1468 }
1469
1470 //draw the icons for number of lives
1471 void hud_show_lives()
1472 {
1473         if ((HUD_nmessages > 0) && (strlen(HUD_messages[hud_first]) > 38))
1474                 return;
1475
1476         if (Game_mode & GM_MULTI) {
1477                 gr_set_curfont( GAME_FONT );
1478                 gr_set_fontcolor(gr_getcolor(0,31,0),-1 );
1479                 gr_printf(10, 3, "%s: %d", TXT_DEATHS, Players[Player_num].net_killed_total);
1480         } 
1481         else if (Players[Player_num].lives > 1)  {
1482                 grs_bitmap *bm;
1483                 gr_set_curfont( GAME_FONT );
1484                 gr_set_fontcolor(gr_getcolor(0,20,0),-1 );
1485                 PAGE_IN_GAUGE( GAUGE_LIVES );
1486                 bm = &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_LIVES) ];
1487                 gr_ubitmapm(10,3,bm);
1488                 gr_printf(10+bm->bm_w+bm->bm_w/2, 4, "x %d", Players[Player_num].lives-1);
1489         }
1490
1491 }
1492
1493 void sb_show_lives()
1494 {
1495         int x,y;
1496         grs_bitmap * bm = &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_LIVES) ];
1497         x = SB_LIVES_X;
1498         y = SB_LIVES_Y;
1499   
1500         //if (old_lives[VR_current_page] == -1)
1501         {
1502                 gr_set_curfont( GAME_FONT );
1503                 gr_set_fontcolor(gr_getcolor(0,20,0),-1 );
1504                 if (Game_mode & GM_MULTI)
1505                         gr_printf(SB_LIVES_LABEL_X,SB_LIVES_LABEL_Y,"%s:", TXT_DEATHS);
1506                 else
1507                         gr_printf(SB_LIVES_LABEL_X,SB_LIVES_LABEL_Y,"%s:", TXT_LIVES);
1508
1509         }
1510
1511         if (Game_mode & GM_MULTI)
1512         {
1513                 char killed_str[20];
1514                 int w, h, aw;
1515                 static int last_x[4] = {SB_SCORE_RIGHT_L,SB_SCORE_RIGHT_L,SB_SCORE_RIGHT_H,SB_SCORE_RIGHT_H};
1516                 int x;
1517
1518                 sprintf(killed_str, "%5d", Players[Player_num].net_killed_total);
1519                 gr_get_string_size(killed_str, &w, &h, &aw);
1520                 gr_setcolor(BM_XRGB(0,0,0));
1521                 gr_rect(last_x[(SM_HIRES?2:0) + VR_current_page], y + 1, SB_SCORE_RIGHT, y + GAME_FONT->ft_h);
1522                 gr_set_fontcolor(gr_getcolor(0,20,0),-1);
1523                 x = SB_SCORE_RIGHT-w-2;         
1524                 gr_printf(x, y+1, killed_str);
1525                 last_x[(SM_HIRES?2:0) + VR_current_page] = x;
1526                 return;
1527         }
1528
1529         //if (old_lives[VR_current_page]==-1 || Players[Player_num].lives != old_lives[VR_current_page])
1530         {
1531
1532                 //erase old icons
1533
1534                 gr_setcolor(BM_XRGB(0,0,0));
1535       
1536            gr_rect(x, y, SB_SCORE_RIGHT, y+bm->bm_h);
1537
1538                 if (Players[Player_num].lives-1 > 0) {
1539                         gr_set_curfont( GAME_FONT );
1540                         gr_set_fontcolor(gr_getcolor(0,20,0),-1 );
1541                         PAGE_IN_GAUGE( GAUGE_LIVES );
1542
1543                         gr_ubitmapm(x, y,bm);
1544                         gr_printf(x+bm->bm_w+GAME_FONT->ft_w, y, "x %d", Players[Player_num].lives-1);
1545
1546 //                      gr_printf(x+12, y, "x %d", Players[Player_num].lives-1);
1547                 }
1548         }
1549
1550 //      for (i=0;i<draw_count;i++,x+=bm->bm_w+2)
1551 //              gr_ubitmapm(x,y,bm);
1552
1553 }
1554
1555 #ifndef RELEASE
1556
1557 #ifdef PIGGY_USE_PAGING
1558 extern int Piggy_bitmap_cache_next;
1559 #endif
1560
1561 void show_time()
1562 {
1563         int secs = f2i(Players[Player_num].time_level) % 60;
1564         int mins = f2i(Players[Player_num].time_level) / 60;
1565
1566         gr_set_curfont( GAME_FONT );
1567
1568         if (Color_0_31_0 == -1)
1569                 Color_0_31_0 = gr_getcolor(0,31,0);
1570         gr_set_fontcolor(Color_0_31_0, -1 );
1571
1572         gr_printf(grd_curcanv->cv_w-4*GAME_FONT->ft_w,grd_curcanv->cv_h-4*Line_spacing,"%d:%02d", mins, secs);
1573
1574 //@@#ifdef PIGGY_USE_PAGING
1575 //@@    {
1576 //@@            char text[25];
1577 //@@            int w,h,aw;
1578 //@@            sprintf( text, "%d KB", Piggy_bitmap_cache_next/1024 );
1579 //@@            gr_get_string_size( text, &w, &h, &aw );        
1580 //@@            gr_printf(grd_curcanv->cv_w-10-w,grd_curcanv->cv_h/2, text );
1581 //@@    }
1582 //@@#endif
1583
1584 }
1585 #endif
1586
1587 #define EXTRA_SHIP_SCORE        50000           //get new ship every this many points
1588
1589 void add_points_to_score(int points) 
1590 {
1591         int prev_score;
1592
1593         score_time += f1_0*2;
1594         score_display[0] += points;
1595         score_display[1] += points;
1596         if (score_time > f1_0*4) score_time = f1_0*4;
1597
1598         if (points == 0 || Cheats_enabled)
1599                 return;
1600
1601         if ((Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP))
1602                 return;
1603
1604         prev_score=Players[Player_num].score;
1605
1606         Players[Player_num].score += points;
1607
1608         if (Newdemo_state == ND_STATE_RECORDING)
1609                 newdemo_record_player_score(points);
1610
1611 #ifdef NETWORK
1612         if (Game_mode & GM_MULTI_COOP)
1613                 multi_send_score();
1614
1615         if (Game_mode & GM_MULTI)
1616                 return;
1617 #endif
1618
1619         if (Players[Player_num].score/EXTRA_SHIP_SCORE != prev_score/EXTRA_SHIP_SCORE) {
1620                 int snd;
1621                 Players[Player_num].lives += Players[Player_num].score/EXTRA_SHIP_SCORE - prev_score/EXTRA_SHIP_SCORE;
1622                 powerup_basic(20, 20, 20, 0, TXT_EXTRA_LIFE);
1623                 if ((snd=Powerup_info[POW_EXTRA_LIFE].hit_sound) > -1 )
1624                         digi_play_sample( snd, F1_0 );
1625         }
1626 }
1627
1628 void add_bonus_points_to_score(int points) 
1629 {
1630         int prev_score;
1631
1632         if (points == 0 || Cheats_enabled)
1633                 return;
1634
1635         prev_score=Players[Player_num].score;
1636
1637         Players[Player_num].score += points;
1638
1639
1640         if (Newdemo_state == ND_STATE_RECORDING)
1641                 newdemo_record_player_score(points);
1642
1643         if (Game_mode & GM_MULTI)
1644                 return;
1645
1646         if (Players[Player_num].score/EXTRA_SHIP_SCORE != prev_score/EXTRA_SHIP_SCORE) {
1647                 int snd;
1648                 Players[Player_num].lives += Players[Player_num].score/EXTRA_SHIP_SCORE - prev_score/EXTRA_SHIP_SCORE;
1649                 if ((snd=Powerup_info[POW_EXTRA_LIFE].hit_sound) > -1 )
1650                         digi_play_sample( snd, F1_0 );
1651         }
1652 }
1653
1654 #include "key.h"
1655
1656 void init_gauge_canvases()
1657 {
1658         grs_font *save_font = grd_curcanv->cv_font;
1659
1660         gr_set_curfont(GAME_FONT);
1661
1662         PAGE_IN_GAUGE( SB_GAUGE_ENERGY );
1663         PAGE_IN_GAUGE( GAUGE_AFTERBURNER );
1664
1665         Canv_LeftEnergyGauge    = gr_create_sub_canvas( grd_curcanv, LEFT_ENERGY_GAUGE_X, LEFT_ENERGY_GAUGE_Y, LEFT_ENERGY_GAUGE_W, LEFT_ENERGY_GAUGE_H );
1666         Canv_SBEnergyGauge              = gr_create_sub_canvas( grd_curcanv, SB_ENERGY_GAUGE_X, SB_ENERGY_GAUGE_Y, SB_ENERGY_GAUGE_W, SB_ENERGY_GAUGE_H );
1667         Canv_SBAfterburnerGauge = gr_create_sub_canvas( grd_curcanv, SB_AFTERBURNER_GAUGE_X, SB_AFTERBURNER_GAUGE_Y, SB_AFTERBURNER_GAUGE_W, SB_AFTERBURNER_GAUGE_H );
1668         Canv_RightEnergyGauge   = gr_create_sub_canvas( grd_curcanv, RIGHT_ENERGY_GAUGE_X, RIGHT_ENERGY_GAUGE_Y, RIGHT_ENERGY_GAUGE_W, RIGHT_ENERGY_GAUGE_H );
1669         Canv_NumericalGauge             = gr_create_sub_canvas( grd_curcanv, NUMERICAL_GAUGE_X, NUMERICAL_GAUGE_Y, NUMERICAL_GAUGE_W, NUMERICAL_GAUGE_H );
1670         Canv_AfterburnerGauge   = gr_create_sub_canvas( grd_curcanv, AFTERBURNER_GAUGE_X, AFTERBURNER_GAUGE_Y, AFTERBURNER_GAUGE_W, AFTERBURNER_GAUGE_H );
1671
1672         gr_set_curfont(save_font);
1673 }
1674
1675 void close_gauge_canvases()
1676 {
1677         if (Canv_LeftEnergyGauge)
1678         {
1679                 gr_free_sub_canvas( Canv_LeftEnergyGauge );
1680                 gr_free_sub_canvas( Canv_SBEnergyGauge );
1681                 gr_free_sub_canvas( Canv_SBAfterburnerGauge );
1682                 gr_free_sub_canvas( Canv_RightEnergyGauge );
1683                 gr_free_sub_canvas( Canv_NumericalGauge );
1684                 gr_free_sub_canvas( Canv_AfterburnerGauge );
1685         }
1686 }
1687
1688 void init_gauges()
1689 {
1690         int i;
1691
1692         //draw_gauges_on        = 1;
1693
1694         for (i=0; i<2; i++ )    {
1695                 if ( ((Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP)) || ((Newdemo_state == ND_STATE_PLAYBACK) && (Newdemo_game_mode & GM_MULTI) && !(Newdemo_game_mode & GM_MULTI_COOP)) ) 
1696                         old_score[i] = -99;
1697                 else
1698                         old_score[i]                    = -1;
1699                 old_energy[i]                   = -1;
1700                 old_shields[i]                  = -1;
1701                 old_flags[i]                    = -1;
1702                 old_cloak[i]                    = -1;
1703                 old_lives[i]                    = -1;
1704                 old_afterburner[i]      = -1;
1705                 old_bombcount[i]                = 0;
1706                 old_laser_level[i]      = 0;
1707         
1708                 old_weapon[0][i] = old_weapon[1][i] = -1;
1709                 old_ammo_count[0][i] = old_ammo_count[1][i] = -1;
1710                 Old_Omega_charge[i] = -1;
1711         }
1712
1713         cloak_fade_state = 0;
1714
1715         weapon_box_user[0] = weapon_box_user[1] = WBU_WEAPON;
1716 }
1717
1718 void draw_energy_bar(int energy)
1719 {
1720         int not_energy;
1721         int x1, x2, y;
1722
1723         // Draw left energy bar
1724         gr_set_current_canvas( Canv_LeftEnergyGauge );
1725         PAGE_IN_GAUGE( GAUGE_ENERGY_LEFT );
1726         gr_ubitmapm( 0, 0, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_ENERGY_LEFT)] );
1727         gr_setcolor( BM_XRGB(0,0,0) );
1728
1729         if (!SM_HIRES)
1730                 not_energy = 61 - (energy*61)/100;
1731         else
1732                 not_energy = 125 - (energy*125)/100;
1733
1734         if (energy < 100)
1735                 for (y=0; y < LEFT_ENERGY_GAUGE_H; y++) {
1736                         x1 = LEFT_ENERGY_GAUGE_H - 1 - y;
1737                         x2 = LEFT_ENERGY_GAUGE_H - 1 - y + not_energy;
1738
1739                         if (x2 > LEFT_ENERGY_GAUGE_W - y/3)
1740                                 x2 = LEFT_ENERGY_GAUGE_W - y/3;
1741                         
1742                         if (x2 > x1) gr_uline( i2f(x1), i2f(y), i2f(x2), i2f(y) ); 
1743                 }
1744         
1745         gr_set_current_canvas( get_current_game_screen() );
1746
1747         // Draw right energy bar
1748         gr_set_current_canvas( Canv_RightEnergyGauge );
1749         PAGE_IN_GAUGE( GAUGE_ENERGY_RIGHT );
1750         gr_ubitmapm( 0, 0, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_ENERGY_RIGHT) ] );
1751         gr_setcolor( BM_XRGB(0,0,0) );
1752
1753         if (energy < 100)
1754                 for (y=0; y < RIGHT_ENERGY_GAUGE_H; y++) {
1755                         x1 = RIGHT_ENERGY_GAUGE_W - RIGHT_ENERGY_GAUGE_H + 1 + y - not_energy;
1756                         x2 = RIGHT_ENERGY_GAUGE_W - RIGHT_ENERGY_GAUGE_H + 1 + y;
1757
1758                         if (x1 < y/3)
1759                                 x1 = y/3;
1760
1761                         if (x2 > x1) gr_uline( i2f(x1), i2f(y), i2f(x2), i2f(y) );  
1762                 }
1763
1764         gr_set_current_canvas( get_current_game_screen() );
1765 }
1766
1767 ubyte afterburner_bar_table[AFTERBURNER_GAUGE_H_L*2] = {
1768                         3,11,
1769                         3,11,
1770                         3,11,
1771                         3,11,
1772                         3,11,
1773                         3,11,
1774                         2,11,
1775                         2,10,
1776                         2,10,
1777                         2,10,
1778                         2,10,
1779                         2,10,
1780                         2,10,
1781                         1,10,
1782                         1,10,
1783                         1,10,
1784                         1,9,
1785                         1,9,
1786                         1,9,
1787                         1,9,
1788                         0,9,
1789                         0,9,
1790                         0,8,
1791                         0,8,
1792                         0,8,
1793                         0,8,
1794                         1,8,
1795                         2,8,
1796                         3,8,
1797                         4,8,
1798                         5,8,
1799                         6,7,
1800 };
1801
1802 ubyte afterburner_bar_table_hires[AFTERBURNER_GAUGE_H_H*2] = {
1803         5,20,
1804         5,20,
1805         5,19,
1806         5,19,
1807         5,19,
1808         5,19,
1809         4,19,
1810         4,19,
1811         4,19,
1812         4,19,
1813
1814         4,19,
1815         4,18,
1816         4,18,
1817         4,18,
1818         4,18,
1819         3,18,
1820         3,18,
1821         3,18,
1822         3,18,
1823         3,18,
1824
1825         3,18,
1826         3,17,
1827         3,17,
1828         2,17,
1829         2,17,
1830         2,17,
1831         2,17,
1832         2,17,
1833         2,17,
1834         2,17,
1835
1836         2,17,
1837         2,16,
1838         2,16,
1839         1,16,
1840         1,16,
1841         1,16,
1842         1,16,
1843         1,16,
1844         1,16,
1845         1,16,
1846
1847         1,16,
1848         1,15,
1849         1,15,
1850         1,15,
1851         0,15,
1852         0,15,
1853         0,15,
1854         0,15,
1855         0,15,
1856         0,15,
1857
1858         0,14,
1859         0,14,
1860         0,14,
1861         1,14,
1862         2,14,
1863         3,14,
1864         4,14,
1865         5,14,
1866         6,13,
1867         7,13,
1868
1869         8,13,
1870         9,13,
1871         10,13,
1872         11,13,
1873         12,13
1874 };
1875
1876
1877 void draw_afterburner_bar(int afterburner)
1878 {
1879         int not_afterburner;
1880         int y;
1881
1882         // Draw afterburner bar
1883         gr_set_current_canvas( Canv_AfterburnerGauge );
1884         PAGE_IN_GAUGE( GAUGE_AFTERBURNER );
1885         gr_ubitmapm( 0, 0, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_AFTERBURNER) ] );
1886         gr_setcolor( BM_XRGB(0,0,0) );
1887
1888         not_afterburner = fixmul(f1_0 - afterburner,AFTERBURNER_GAUGE_H);
1889
1890         for (y=0;y<not_afterburner;y++) {
1891
1892                 gr_uline( i2f(SM_HIRES ? afterburner_bar_table_hires[y*2] : afterburner_bar_table[y*2]), i2f(y),
1893                                                 i2f((SM_HIRES ? afterburner_bar_table_hires[y*2 + 1] : afterburner_bar_table[y*2 + 1]) + 1), i2f(y) );
1894         }
1895
1896         gr_set_current_canvas( get_current_game_screen() );
1897 }
1898
1899 void draw_shield_bar(int shield)
1900 {
1901         int bm_num = shield>=100?9:(shield / 10);
1902
1903         PAGE_IN_GAUGE( GAUGE_SHIELDS+9-bm_num   );
1904         gr_ubitmapm( SHIELD_GAUGE_X, SHIELD_GAUGE_Y, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_SHIELDS+9-bm_num) ] );
1905 }
1906
1907 #define CLOAK_FADE_WAIT_TIME  0x400
1908
1909 void draw_player_ship(int cloak_state,int old_cloak_state,int x, int y)
1910 {
1911         static fix cloak_fade_timer=0;
1912         static int cloak_fade_value=GR_FADE_LEVELS-1;
1913         static int refade = 0;
1914         grs_bitmap *bm = NULL;
1915
1916         if (Game_mode & GM_TEAM)        {
1917                 #ifdef NETWORK
1918                 PAGE_IN_GAUGE( GAUGE_SHIPS+get_team(Player_num) );
1919                 bm = &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_SHIPS+get_team(Player_num)) ];
1920                 #endif
1921         } else {
1922                 PAGE_IN_GAUGE( GAUGE_SHIPS+Player_num );
1923                 bm = &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_SHIPS+Player_num) ];
1924         }
1925         
1926
1927         if (old_cloak_state==-1 && cloak_state)
1928                         cloak_fade_value=0;
1929
1930 //      mprintf((0, "cloak/oldcloak %d/%d", cloak_state, old_cloak_state));
1931
1932         if (!cloak_state) {
1933                 cloak_fade_value=GR_FADE_LEVELS-1;
1934                 cloak_fade_state = 0;
1935         }
1936
1937         if (cloak_state==1 && old_cloak_state==0)
1938                 cloak_fade_state = -1;
1939         //else if (cloak_state==0 && old_cloak_state==1)
1940         //      cloak_fade_state = 1;
1941
1942         if (cloak_state && GameTime > Players[Player_num].cloak_time + CLOAK_TIME_MAX - i2f(3))         //doing "about-to-uncloak" effect
1943                 if (cloak_fade_state==0)
1944                         cloak_fade_state = 2;
1945         
1946
1947         if (cloak_fade_state)
1948                 cloak_fade_timer -= FrameTime;
1949
1950         while (cloak_fade_state && cloak_fade_timer < 0) {
1951
1952                 cloak_fade_timer += CLOAK_FADE_WAIT_TIME;
1953
1954                 cloak_fade_value += cloak_fade_state;
1955
1956                 if (cloak_fade_value >= GR_FADE_LEVELS-1) {
1957                         cloak_fade_value = GR_FADE_LEVELS-1;
1958                         if (cloak_fade_state == 2 && cloak_state)
1959                                 cloak_fade_state = -2;
1960                         else
1961                                 cloak_fade_state = 0;
1962                 }
1963                 else if (cloak_fade_value <= 0) {
1964                         cloak_fade_value = 0;
1965                         if (cloak_fade_state == -2)
1966                                 cloak_fade_state = 2;
1967                         else
1968                                 cloak_fade_state = 0;
1969                 }
1970         }
1971
1972 //      To fade out both pages in a paged mode.
1973         if (refade) refade = 0;
1974         else if (cloak_state && old_cloak_state && !cloak_fade_state && !refade) {
1975                 cloak_fade_state = -1;
1976                 refade = 1;
1977         }
1978
1979         gr_set_current_canvas(&VR_render_buffer[0]);
1980
1981         gr_ubitmap( x, y, bm);
1982
1983         Gr_scanline_darkening_level = cloak_fade_value;
1984         gr_rect(x, y, x+bm->bm_w-1, y+bm->bm_h-1);
1985         Gr_scanline_darkening_level = GR_FADE_LEVELS;
1986
1987         gr_set_current_canvas( get_current_game_screen() );
1988
1989         gr_bm_ubitbltm( bm->bm_w, bm->bm_h, x, y, x, y, &VR_render_buffer[0].cv_bitmap, &grd_curcanv->cv_bitmap);
1990 }
1991
1992 #define INV_FRAME_TIME  (f1_0/10)               //how long for each frame
1993
1994 void draw_numerical_display(int shield, int energy)
1995 {
1996         gr_set_current_canvas( Canv_NumericalGauge );
1997         gr_set_curfont( GAME_FONT );
1998         PAGE_IN_GAUGE( GAUGE_NUMERICAL );
1999         gr_ubitmap( 0, 0, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_NUMERICAL) ] );
2000
2001         gr_set_fontcolor(gr_getcolor(14,14,23),-1 );
2002
2003         if (!SM_HIRES) {
2004                 gr_printf((shield>99)?3:((shield>9)?5:7),15,"%d",shield);
2005                 gr_set_fontcolor(gr_getcolor(25,18,6),-1 );
2006                 gr_printf((energy>99)?3:((energy>9)?5:7),2,"%d",energy);
2007         } else {
2008                 gr_printf((shield>99)?7:((shield>9)?11:15),33,"%d",shield);
2009                 gr_set_fontcolor(gr_getcolor(25,18,6),-1 );
2010                 gr_printf((energy>99)?7:((energy>9)?11:15),4,"%d",energy);
2011         }
2012         
2013         gr_set_current_canvas( get_current_game_screen() );
2014 }
2015
2016
2017 void draw_keys()
2018 {
2019         gr_set_current_canvas( get_current_game_screen() );
2020
2021         if (Players[Player_num].flags & PLAYER_FLAGS_BLUE_KEY ) {
2022                 PAGE_IN_GAUGE( GAUGE_BLUE_KEY );
2023                 gr_ubitmapm( GAUGE_BLUE_KEY_X, GAUGE_BLUE_KEY_Y, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_BLUE_KEY) ] );
2024         } else {
2025                 PAGE_IN_GAUGE( GAUGE_BLUE_KEY_OFF );
2026                 gr_ubitmapm( GAUGE_BLUE_KEY_X, GAUGE_BLUE_KEY_Y, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_BLUE_KEY_OFF) ] );
2027         }
2028
2029         if (Players[Player_num].flags & PLAYER_FLAGS_GOLD_KEY)  {
2030                 PAGE_IN_GAUGE( GAUGE_GOLD_KEY );
2031                 gr_ubitmapm( GAUGE_GOLD_KEY_X, GAUGE_GOLD_KEY_Y, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_GOLD_KEY) ] );
2032         } else {
2033                 PAGE_IN_GAUGE( GAUGE_GOLD_KEY_OFF );
2034                 gr_ubitmapm( GAUGE_GOLD_KEY_X, GAUGE_GOLD_KEY_Y, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_GOLD_KEY_OFF) ] );
2035         }
2036
2037         if (Players[Player_num].flags & PLAYER_FLAGS_RED_KEY)   {
2038                 PAGE_IN_GAUGE( GAUGE_RED_KEY );
2039                 gr_ubitmapm( GAUGE_RED_KEY_X,  GAUGE_RED_KEY_Y,  &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_RED_KEY) ] );
2040         } else {
2041                 PAGE_IN_GAUGE( GAUGE_RED_KEY_OFF );
2042                 gr_ubitmapm( GAUGE_RED_KEY_X,  GAUGE_RED_KEY_Y,  &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_RED_KEY_OFF) ] );
2043         }
2044 }
2045
2046
2047 void draw_weapon_info_sub(int info_index,gauge_box *box,int pic_x,int pic_y,char *name,int text_x,int text_y)
2048 {
2049         grs_bitmap *bm;
2050         char *p;
2051
2052         //clear the window
2053         gr_setcolor(BM_XRGB(0,0,0));
2054         
2055    gr_rect(box->left,box->top,box->right,box->bot);
2056
2057         if (Piggy_hamfile_version >= 3 // !SHAREWARE
2058                 && SM_HIRES)
2059         {
2060                 bm=&GameBitmaps[Weapon_info[info_index].hires_picture.index];
2061                 PIGGY_PAGE_IN( Weapon_info[info_index].hires_picture );
2062         } else {
2063                 bm=&GameBitmaps[Weapon_info[info_index].picture.index];
2064                 PIGGY_PAGE_IN( Weapon_info[info_index].picture );
2065         }
2066
2067         Assert(bm != NULL);
2068
2069         gr_ubitmapm(pic_x,pic_y,bm);
2070         
2071         gr_set_fontcolor(gr_getcolor(0,20,0),-1 );
2072
2073         if ((p=strchr(name,'\n'))!=NULL) {
2074                 *p=0;
2075                 gr_printf(text_x,text_y,name);
2076                 gr_printf(text_x,text_y+grd_curcanv->cv_font->ft_h+1,p+1);
2077                 *p='\n';
2078         } else
2079                 gr_printf(text_x,text_y,name);
2080
2081         //      For laser, show level and quadness
2082         if (info_index == LASER_ID || info_index == SUPER_LASER_ID) {
2083                 char    temp_str[7];
2084
2085                 sprintf(temp_str, "%s: 0", TXT_LVL);
2086
2087                 temp_str[5] = Players[Player_num].laser_level+1 + '0';
2088
2089                 gr_printf(text_x,text_y+Line_spacing, temp_str);
2090
2091                 if (Players[Player_num].flags & PLAYER_FLAGS_QUAD_LASERS) {
2092                         strcpy(temp_str, TXT_QUAD);
2093                         gr_printf(text_x,text_y+2*Line_spacing, temp_str);
2094
2095                 }
2096
2097         }
2098 }
2099
2100
2101 void draw_weapon_info(int weapon_type,int weapon_num,int laser_level)
2102 {
2103         int info_index;
2104
2105         if (weapon_type == 0) {
2106                 info_index = Primary_weapon_to_weapon_info[weapon_num];
2107
2108                 if (info_index == LASER_ID && laser_level > MAX_LASER_LEVEL)
2109                         info_index = SUPER_LASER_ID;
2110
2111                 if (Cockpit_mode.intval == CM_STATUS_BAR)
2112                         draw_weapon_info_sub(info_index,
2113                                 &gauge_boxes[SB_PRIMARY_BOX],
2114                                 SB_PRIMARY_W_PIC_X,SB_PRIMARY_W_PIC_Y,
2115                                 PRIMARY_WEAPON_NAMES_SHORT(weapon_num),
2116                                 SB_PRIMARY_W_TEXT_X,SB_PRIMARY_W_TEXT_Y);
2117                 else
2118                         draw_weapon_info_sub(info_index,
2119                                 &gauge_boxes[COCKPIT_PRIMARY_BOX],
2120                                 PRIMARY_W_PIC_X,PRIMARY_W_PIC_Y,
2121                                 PRIMARY_WEAPON_NAMES_SHORT(weapon_num),
2122                                 PRIMARY_W_TEXT_X,PRIMARY_W_TEXT_Y);
2123
2124         }
2125         else {
2126                 info_index = Secondary_weapon_to_weapon_info[weapon_num];
2127
2128                 if (Cockpit_mode.intval == CM_STATUS_BAR)
2129                         draw_weapon_info_sub(info_index,
2130                                 &gauge_boxes[SB_SECONDARY_BOX],
2131                                 SB_SECONDARY_W_PIC_X,SB_SECONDARY_W_PIC_Y,
2132                                 SECONDARY_WEAPON_NAMES_SHORT(weapon_num),
2133                                 SB_SECONDARY_W_TEXT_X,SB_SECONDARY_W_TEXT_Y);
2134                 else
2135                         draw_weapon_info_sub(info_index,
2136                                 &gauge_boxes[COCKPIT_SECONDARY_BOX],
2137                                 SECONDARY_W_PIC_X,SECONDARY_W_PIC_Y,
2138                                 SECONDARY_WEAPON_NAMES_SHORT(weapon_num),
2139                                 SECONDARY_W_TEXT_X,SECONDARY_W_TEXT_Y);
2140         }
2141 }
2142
2143 void draw_ammo_info(int x,int y,int ammo_count,int primary)
2144 {
2145         int w;
2146         char str[16];
2147
2148         if (primary)
2149                 w = (grd_curcanv->cv_font->ft_w*7)/2;
2150         else
2151                 w = (grd_curcanv->cv_font->ft_w*5)/2;
2152
2153         gr_setcolor(BM_XRGB(0,0,0));
2154         gr_rect(x,y,x+w,y+grd_curcanv->cv_font->ft_h);
2155         gr_set_fontcolor(gr_getcolor(20,0,0),-1 );
2156         sprintf(str,"%03d",ammo_count);
2157         convert_1s(str);
2158         gr_printf(x,y,str);
2159 }
2160
2161 void draw_secondary_ammo_info(int ammo_count)
2162 {
2163         if (Cockpit_mode.intval == CM_STATUS_BAR)
2164                 draw_ammo_info(SB_SECONDARY_AMMO_X,SB_SECONDARY_AMMO_Y,ammo_count,0);
2165         else
2166                 draw_ammo_info(SECONDARY_AMMO_X,SECONDARY_AMMO_Y,ammo_count,0);
2167 }
2168
2169 //returns true if drew picture
2170 int draw_weapon_box(int weapon_type,int weapon_num)
2171 {
2172         int drew_flag=0;
2173         int laser_level_changed;
2174
2175         gr_set_current_canvas(&VR_render_buffer[0]);
2176
2177         gr_set_curfont( GAME_FONT );
2178
2179         laser_level_changed = (weapon_type==0 && weapon_num==LASER_INDEX && (Players[Player_num].laser_level != old_laser_level[VR_current_page]));
2180
2181         if ((weapon_num != old_weapon[weapon_type][VR_current_page] || laser_level_changed) && weapon_box_states[weapon_type] == WS_SET && (old_weapon[weapon_type][VR_current_page] != -1))
2182         {
2183                 weapon_box_states[weapon_type] = WS_FADING_OUT;
2184                 weapon_box_fade_values[weapon_type]=i2f(GR_FADE_LEVELS-1);
2185         }
2186                 
2187         if (weapon_box_states[weapon_type] == WS_FADING_OUT) {
2188                 draw_weapon_info(weapon_type,old_weapon[weapon_type][VR_current_page],old_laser_level[VR_current_page]);
2189                 old_ammo_count[weapon_type][VR_current_page]=-1;
2190                 Old_Omega_charge[VR_current_page]=-1;
2191                 drew_flag=1;
2192                 weapon_box_fade_values[weapon_type] -= FrameTime * FADE_SCALE;
2193                 if (weapon_box_fade_values[weapon_type] <= 0) {
2194                         weapon_box_states[weapon_type] = WS_FADING_IN;
2195                         old_weapon[weapon_type][VR_current_page] = weapon_num;
2196                         old_weapon[weapon_type][!VR_current_page] = weapon_num;
2197                         old_laser_level[VR_current_page] = Players[Player_num].laser_level;
2198                         old_laser_level[!VR_current_page] = Players[Player_num].laser_level;
2199                         weapon_box_fade_values[weapon_type] = 0;
2200                 }
2201         }
2202         else if (weapon_box_states[weapon_type] == WS_FADING_IN) {
2203                 if (weapon_num != old_weapon[weapon_type][VR_current_page]) {
2204                         weapon_box_states[weapon_type] = WS_FADING_OUT;
2205                 }
2206                 else {
2207                         draw_weapon_info(weapon_type,weapon_num,Players[Player_num].laser_level);
2208                         old_ammo_count[weapon_type][VR_current_page]=-1;
2209                         Old_Omega_charge[VR_current_page]=-1;
2210                         drew_flag=1;
2211                         weapon_box_fade_values[weapon_type] += FrameTime * FADE_SCALE;
2212                         if (weapon_box_fade_values[weapon_type] >= i2f(GR_FADE_LEVELS-1)) {
2213                                 weapon_box_states[weapon_type] = WS_SET;
2214                                 old_weapon[weapon_type][!VR_current_page] = -1;         //force redraw (at full fade-in) of other page
2215                         }
2216                 }
2217         } else
2218         //      if (old_weapon[weapon_type][VR_current_page] == -1)
2219                         {
2220                         //@@if (laser_level_changed)
2221                         //@@    old_weapon[weapon_type][VR_current_page] = LASER_INDEX;
2222                         //@@else 
2223                         {
2224                                 draw_weapon_info(weapon_type, weapon_num, Players[Player_num].laser_level);
2225                                 old_weapon[weapon_type][VR_current_page] = weapon_num;
2226                                 old_ammo_count[weapon_type][VR_current_page] = -1;
2227                                 Old_Omega_charge[VR_current_page] = -1;
2228                                 old_laser_level[VR_current_page] = Players[Player_num].laser_level;
2229                                 drew_flag = 1;
2230                         }
2231                 }
2232
2233         if (weapon_box_states[weapon_type] != WS_SET) {         //fade gauge
2234                 int fade_value = f2i(weapon_box_fade_values[weapon_type]);
2235                 int boxofs = (Cockpit_mode.intval == CM_STATUS_BAR)?SB_PRIMARY_BOX:COCKPIT_PRIMARY_BOX;
2236                 
2237                 Gr_scanline_darkening_level = fade_value;
2238                 gr_rect(gauge_boxes[boxofs+weapon_type].left,gauge_boxes[boxofs+weapon_type].top,gauge_boxes[boxofs+weapon_type].right,gauge_boxes[boxofs+weapon_type].bot);
2239
2240                 Gr_scanline_darkening_level = GR_FADE_LEVELS;
2241         }
2242
2243         gr_set_current_canvas(get_current_game_screen());
2244         return drew_flag;
2245 }
2246
2247 fix static_time[2];
2248
2249 void draw_static(int win)
2250 {
2251         vclip *vc = &Vclip[VCLIP_MONITOR_STATIC];
2252         grs_bitmap *bmp;
2253         int framenum;
2254         int boxofs = (Cockpit_mode.intval == CM_STATUS_BAR)?SB_PRIMARY_BOX:COCKPIT_PRIMARY_BOX;
2255         int x,y;
2256
2257         static_time[win] += FrameTime;
2258         if (static_time[win] >= vc->play_time) {
2259                 weapon_box_user[win] = WBU_WEAPON;
2260                 return;
2261         }
2262
2263         framenum = static_time[win] * vc->num_frames / vc->play_time;
2264
2265         PIGGY_PAGE_IN(vc->frames[framenum]);
2266
2267         bmp = &GameBitmaps[vc->frames[framenum].index];
2268
2269         gr_set_current_canvas(&VR_render_buffer[0]);
2270    
2271         for (x=gauge_boxes[boxofs+win].left;x<gauge_boxes[boxofs+win].right;x+=bmp->bm_w)
2272                 for (y=gauge_boxes[boxofs+win].top;y<gauge_boxes[boxofs+win].bot;y+=bmp->bm_h)
2273                         gr_bitmap(x,y,bmp);
2274
2275         gr_set_current_canvas(get_current_game_screen());
2276
2277         copy_gauge_box(&gauge_boxes[boxofs+win],&VR_render_buffer[0].cv_bitmap);
2278 }
2279
2280 void draw_weapon_boxes()
2281 {
2282         int boxofs = (Cockpit_mode.intval == CM_STATUS_BAR)?SB_PRIMARY_BOX:COCKPIT_PRIMARY_BOX;
2283         int drew;
2284
2285         if (weapon_box_user[0] == WBU_WEAPON) {
2286                 drew = draw_weapon_box(0,Primary_weapon);
2287                 if (drew) 
2288                         copy_gauge_box(&gauge_boxes[boxofs+0],&VR_render_buffer[0].cv_bitmap);
2289
2290                 if (weapon_box_states[0] == WS_SET) {
2291                         if ((Primary_weapon == VULCAN_INDEX) || (Primary_weapon == GAUSS_INDEX))
2292                         {
2293                                 if (Newdemo_state == ND_STATE_RECORDING &&
2294                 Players[Player_num].primary_ammo[VULCAN_INDEX] != old_ammo_count[0][VR_current_page])
2295                                         newdemo_record_primary_ammo(old_ammo_count[0][VR_current_page], Players[Player_num].primary_ammo[VULCAN_INDEX]);
2296                                 draw_primary_ammo_info(f2i((unsigned) VULCAN_AMMO_SCALE * (unsigned) Players[Player_num].primary_ammo[VULCAN_INDEX]));
2297                                 old_ammo_count[0][VR_current_page] = Players[Player_num].primary_ammo[VULCAN_INDEX];
2298                         }
2299
2300                         if (Primary_weapon == OMEGA_INDEX)
2301                         {
2302                                 if (Newdemo_state == ND_STATE_RECORDING &&
2303                 Omega_charge != Old_Omega_charge[VR_current_page])
2304                                         newdemo_record_primary_ammo(Old_Omega_charge[VR_current_page], Omega_charge);
2305                                 draw_primary_ammo_info(Omega_charge * 100/MAX_OMEGA_CHARGE);
2306                                 Old_Omega_charge[VR_current_page] = Omega_charge;
2307                         }
2308                 }
2309         }
2310         else if (weapon_box_user[0] == WBU_STATIC)
2311                 draw_static(0);
2312
2313         if (weapon_box_user[1] == WBU_WEAPON) {
2314                 drew = draw_weapon_box(1,Secondary_weapon);
2315                 if (drew)
2316                         copy_gauge_box(&gauge_boxes[boxofs+1],&VR_render_buffer[0].cv_bitmap);
2317
2318                 if (weapon_box_states[1] == WS_SET)
2319                 {
2320                         old_bombcount[VR_current_page] = 0x7fff;        //force redraw
2321                         if (Newdemo_state == ND_STATE_RECORDING &&
2322         Players[Player_num].secondary_ammo[Secondary_weapon] != old_ammo_count[1][VR_current_page])
2323                                 newdemo_record_secondary_ammo(old_ammo_count[1][VR_current_page], Players[Player_num].secondary_ammo[Secondary_weapon]);
2324                         draw_secondary_ammo_info(Players[Player_num].secondary_ammo[Secondary_weapon]);
2325                         old_ammo_count[1][VR_current_page] = Players[Player_num].secondary_ammo[Secondary_weapon];
2326
2327                         if (Cockpit_mode.intval == CM_STATUS_BAR)
2328                                 show_bomb_count(SB_BOMB_COUNT_X, SB_BOMB_COUNT_Y, gr_find_closest_color(0, 0, 0), 0);
2329                         else
2330                                 show_bomb_count(BOMB_COUNT_X, BOMB_COUNT_Y, gr_find_closest_color(0, 0, 0), 0);
2331                 }
2332         }
2333         else if (weapon_box_user[1] == WBU_STATIC)
2334                 draw_static(1);
2335 }
2336
2337
2338 void sb_draw_energy_bar(int energy)
2339 {
2340         int erase_height, w, h, aw;
2341         char energy_str[20];
2342
2343         gr_set_current_canvas( Canv_SBEnergyGauge );
2344
2345         PAGE_IN_GAUGE( SB_GAUGE_ENERGY );
2346         gr_ubitmapm(0, 0, &GameBitmaps[GET_GAUGE_INDEX(SB_GAUGE_ENERGY)]);
2347
2348         erase_height = (100 - energy) * SB_ENERGY_GAUGE_H / 100;
2349
2350         if (erase_height > 0) {
2351                 gr_setcolor( BM_XRGB(0,0,0) );
2352                 gr_rect(0, 0, SB_ENERGY_GAUGE_W - 1, erase_height - 1);
2353         }
2354         
2355         //draw numbers
2356         sprintf(energy_str, "%d", energy);
2357         gr_get_string_size(energy_str, &w, &h, &aw );
2358         gr_set_fontcolor(gr_getcolor(25,18,6),-1 );
2359         gr_printf(((SB_ENERGY_GAUGE_W - w)/2), SB_ENERGY_GAUGE_H - GAME_FONT->ft_h - (GAME_FONT->ft_h / 4), "%d", energy);
2360
2361         gr_set_current_canvas(get_current_game_screen());
2362 }
2363
2364 void sb_draw_afterburner()
2365 {
2366         int erase_height, w, h, aw;
2367         char ab_str[3] = "AB";
2368
2369         gr_set_current_canvas( Canv_SBAfterburnerGauge );
2370         PAGE_IN_GAUGE( SB_GAUGE_AFTERBURNER );
2371         gr_ubitmapm(0, 0, &GameBitmaps[GET_GAUGE_INDEX(SB_GAUGE_AFTERBURNER)]);
2372
2373         erase_height = fixmul((f1_0 - Afterburner_charge),SB_AFTERBURNER_GAUGE_H);
2374
2375         if (erase_height > 0) {
2376                 gr_setcolor( BM_XRGB(0,0,0) );
2377                 gr_rect(0, 0, SB_AFTERBURNER_GAUGE_W - 1, erase_height - 1);
2378         }
2379
2380         //draw legend
2381         if (Players[Player_num].flags & PLAYER_FLAGS_AFTERBURNER)
2382                 gr_set_fontcolor(gr_getcolor(45,0,0),-1 );
2383         else 
2384                 gr_set_fontcolor(gr_getcolor(12,12,12),-1 );
2385
2386         gr_get_string_size(ab_str, &w, &h, &aw );
2387         gr_printf(((SB_AFTERBURNER_GAUGE_W - w)/2), SB_AFTERBURNER_GAUGE_H - GAME_FONT->ft_h - (GAME_FONT->ft_h / 4), "AB");
2388         gr_set_current_canvas(get_current_game_screen());
2389 }
2390
2391 void sb_draw_shield_num(int shield)
2392 {
2393         //draw numbers
2394
2395         gr_set_curfont( GAME_FONT );
2396         gr_set_fontcolor(gr_getcolor(14,14,23),-1 );
2397
2398         //erase old one
2399 //      PIGGY_PAGE_IN(cockpit_bitmap[Cockpit_mode.intval + (SM_HIRES ? (Num_cockpits/2) : 0)]);
2400
2401 //      gr_setcolor(gr_gpixel(&grd_curcanv->cv_bitmap, SB_SHIELD_NUM_X - 1, SB_SHIELD_NUM_Y - 1));
2402
2403 //      gr_rect(SB_SHIELD_NUM_X, SB_SHIELD_NUM_Y, SB_SHIELD_NUM_X + (SM_HIRES ? 27 : 13), SB_SHIELD_NUM_Y + GAME_FONT->ft_h);
2404         gr_printf((shield>99)?SB_SHIELD_NUM_X:((shield>9)?SB_SHIELD_NUM_X+2:SB_SHIELD_NUM_X+4),SB_SHIELD_NUM_Y,"%d",shield);
2405 }
2406
2407 void sb_draw_shield_bar(int shield)
2408 {
2409         int bm_num = shield>=100?9:(shield / 10);
2410
2411         gr_set_current_canvas(get_current_game_screen());
2412         PAGE_IN_GAUGE( GAUGE_SHIELDS+9-bm_num );
2413         gr_ubitmapm( SB_SHIELD_GAUGE_X, SB_SHIELD_GAUGE_Y, &GameBitmaps[GET_GAUGE_INDEX(GAUGE_SHIELDS+9-bm_num) ] );
2414 }
2415
2416 void sb_draw_keys()
2417 {
2418         grs_bitmap * bm;
2419         int flags = Players[Player_num].flags;
2420
2421         gr_set_current_canvas(get_current_game_screen());
2422         bm = &GameBitmaps[ GET_GAUGE_INDEX((flags&PLAYER_FLAGS_BLUE_KEY)?SB_GAUGE_BLUE_KEY:SB_GAUGE_BLUE_KEY_OFF) ];
2423         PAGE_IN_GAUGE( (flags&PLAYER_FLAGS_BLUE_KEY)?SB_GAUGE_BLUE_KEY:SB_GAUGE_BLUE_KEY_OFF );
2424         gr_ubitmapm( SB_GAUGE_KEYS_X, SB_GAUGE_BLUE_KEY_Y, bm );
2425         bm = &GameBitmaps[ GET_GAUGE_INDEX((flags&PLAYER_FLAGS_GOLD_KEY)?SB_GAUGE_GOLD_KEY:SB_GAUGE_GOLD_KEY_OFF) ];
2426         PAGE_IN_GAUGE( (flags&PLAYER_FLAGS_GOLD_KEY)?SB_GAUGE_GOLD_KEY:SB_GAUGE_GOLD_KEY_OFF );
2427         gr_ubitmapm( SB_GAUGE_KEYS_X, SB_GAUGE_GOLD_KEY_Y, bm );
2428         bm = &GameBitmaps[ GET_GAUGE_INDEX((flags&PLAYER_FLAGS_RED_KEY)?SB_GAUGE_RED_KEY:SB_GAUGE_RED_KEY_OFF) ];
2429         PAGE_IN_GAUGE( (flags&PLAYER_FLAGS_RED_KEY)?SB_GAUGE_RED_KEY:SB_GAUGE_RED_KEY_OFF );
2430         gr_ubitmapm( SB_GAUGE_KEYS_X, SB_GAUGE_RED_KEY_Y, bm  );
2431 }
2432
2433 //      Draws invulnerable ship, or maybe the flashing ship, depending on invulnerability time left.
2434 void draw_invulnerable_ship()
2435 {
2436         static fix time=0;
2437
2438         gr_set_current_canvas(get_current_game_screen());
2439
2440         if (((Players[Player_num].invulnerable_time + INVULNERABLE_TIME_MAX - GameTime) > F1_0*4) || (GameTime & 0x8000)) {
2441
2442                 if (Cockpit_mode.intval == CM_STATUS_BAR) {
2443                         PAGE_IN_GAUGE( GAUGE_INVULNERABLE+invulnerable_frame );
2444                         gr_ubitmapm( SB_SHIELD_GAUGE_X, SB_SHIELD_GAUGE_Y, &GameBitmaps[GET_GAUGE_INDEX(GAUGE_INVULNERABLE+invulnerable_frame) ] );
2445                 } else {
2446                         PAGE_IN_GAUGE( GAUGE_INVULNERABLE+invulnerable_frame );
2447                         gr_ubitmapm( SHIELD_GAUGE_X, SHIELD_GAUGE_Y, &GameBitmaps[GET_GAUGE_INDEX(GAUGE_INVULNERABLE+invulnerable_frame)] );
2448                 }
2449
2450                 time += FrameTime;
2451
2452                 while (time > INV_FRAME_TIME) {
2453                         time -= INV_FRAME_TIME;
2454                         if (++invulnerable_frame == N_INVULNERABLE_FRAMES)
2455                                 invulnerable_frame=0;
2456                 }
2457         } else if (Cockpit_mode.intval == CM_STATUS_BAR)
2458                 sb_draw_shield_bar(f2ir(Players[Player_num].shields));
2459         else
2460                 draw_shield_bar(f2ir(Players[Player_num].shields));
2461 }
2462
2463 extern int Missile_gun;
2464 extern int allowed_to_fire_laser(void);
2465 extern int allowed_to_fire_missile(void);
2466
2467 rgb player_rgb[] = {
2468                                                         {15,15,23},
2469                                                         {27,0,0},
2470                                                         {0,23,0},
2471                                                         {30,11,31},
2472                                                         {31,16,0},
2473                                                         {24,17,6},
2474                                                         {14,21,12},
2475                                                         {29,29,0},
2476                                                 };
2477
2478 extern ubyte Newdemo_flying_guided;
2479 extern int max_window_w;
2480
2481 typedef struct {
2482         sbyte x, y;
2483 } xy;
2484
2485 //offsets for reticle parts: high-big  high-sml  low-big  low-sml
2486 xy cross_offsets[4] =           { {-8,-5},      {-4,-2},        {-4,-2}, {-2,-1} };
2487 xy primary_offsets[4] =         { {-30,14}, {-16,6},    {-15,6}, {-8, 2} };
2488 xy secondary_offsets[4] =       { {-24,2},      {-12,0}, {-12,1}, {-6,-2} };
2489
2490 //draw the reticle
2491 void show_reticle(int force_big_one)
2492 {
2493         int x,y;
2494         int laser_ready,missile_ready,laser_ammo,missile_ammo;
2495         int cross_bm_num,primary_bm_num,secondary_bm_num;
2496         int use_hires_reticle,small_reticle,ofs,gauge_index;
2497
2498         if (Newdemo_state==ND_STATE_PLAYBACK && Newdemo_flying_guided)
2499         {
2500                  draw_guided_crosshair();
2501                  return;
2502         }
2503
2504         x = grd_curcanv->cv_w/2;
2505         y = grd_curcanv->cv_h/2;
2506
2507         laser_ready = allowed_to_fire_laser();
2508         missile_ready = allowed_to_fire_missile();
2509
2510         laser_ammo = player_has_weapon(Primary_weapon,0);
2511         missile_ammo = player_has_weapon(Secondary_weapon,1);
2512
2513         primary_bm_num = (laser_ready && laser_ammo==HAS_ALL);
2514         secondary_bm_num = (missile_ready && missile_ammo==HAS_ALL);
2515
2516         if (primary_bm_num && Primary_weapon==LASER_INDEX && (Players[Player_num].flags & PLAYER_FLAGS_QUAD_LASERS))
2517                 primary_bm_num++;
2518
2519         if (Secondary_weapon_to_gun_num[Secondary_weapon]==7)
2520                 secondary_bm_num += 3;          //now value is 0,1 or 3,4
2521         else if (secondary_bm_num && !(Missile_gun&1))
2522                         secondary_bm_num++;
2523
2524         cross_bm_num = ((primary_bm_num > 0) || (secondary_bm_num > 0));
2525
2526         Assert(primary_bm_num <= 2);
2527         Assert(secondary_bm_num <= 4);
2528         Assert(cross_bm_num <= 1);
2529 #ifdef OGL
2530         if (gl_reticle==2 || (gl_reticle && grd_curcanv->cv_bitmap.bm_w > 320))
2531         {
2532                 ogl_draw_reticle(cross_bm_num,primary_bm_num,secondary_bm_num);
2533         }
2534         else
2535         {
2536 #endif
2537
2538
2539                 use_hires_reticle = (FontHires != 0);
2540
2541         small_reticle = !(grd_curcanv->cv_bitmap.bm_w*3 > max_window_w*2 || force_big_one);
2542         ofs = (use_hires_reticle?0:2) + small_reticle;
2543
2544         gauge_index = (small_reticle?SML_RETICLE_CROSS:RETICLE_CROSS) + cross_bm_num;
2545         PAGE_IN_GAUGE( gauge_index );
2546         gr_ubitmapm(x+cross_offsets[ofs].x,y+cross_offsets[ofs].y,&GameBitmaps[GET_GAUGE_INDEX(gauge_index)] );
2547
2548         gauge_index = (small_reticle?SML_RETICLE_PRIMARY:RETICLE_PRIMARY) + primary_bm_num;
2549         PAGE_IN_GAUGE( gauge_index );
2550         gr_ubitmapm(x+primary_offsets[ofs].x,y+primary_offsets[ofs].y,&GameBitmaps[GET_GAUGE_INDEX(gauge_index)] );
2551
2552         gauge_index = (small_reticle?SML_RETICLE_SECONDARY:RETICLE_SECONDARY) + secondary_bm_num;
2553         PAGE_IN_GAUGE( gauge_index );
2554         gr_ubitmapm(x+secondary_offsets[ofs].x,y+secondary_offsets[ofs].y,&GameBitmaps[GET_GAUGE_INDEX(gauge_index)] );
2555
2556 #ifdef OGL
2557         }
2558 #endif
2559 }
2560
2561 #ifdef NETWORK
2562 void hud_show_kill_list()
2563 {
2564         int n_players,player_list[MAX_NUM_NET_PLAYERS];
2565         int n_left,i,x0,x1,y,save_y,fth;
2566
2567 // ugly hack since placement of netgame players and kills is based off of
2568 // menuhires (which is always 1 for mac).  This throws off placement of
2569 // players in pixel double mode.
2570
2571         if (Show_kill_list_timer > 0)
2572         {
2573                 Show_kill_list_timer -= FrameTime;
2574                 if (Show_kill_list_timer < 0)
2575                         Show_kill_list = 0;
2576         }
2577         
2578         gr_set_curfont( GAME_FONT );
2579
2580         n_players = multi_get_kill_list(player_list);
2581
2582         if (Show_kill_list == 3)
2583                 n_players = 2;
2584
2585         if (n_players <= 4)
2586                 n_left = n_players;
2587         else
2588                 n_left = (n_players+1)/2;
2589
2590         //If font size changes, this code might not work right anymore 
2591         //Assert(GAME_FONT->ft_h==5 && GAME_FONT->ft_w==7);
2592
2593         fth = GAME_FONT->ft_h;
2594
2595         x0 = LHX(1); x1 = LHX(43);
2596
2597         if (Game_mode & GM_MULTI_COOP)
2598                 x1 = LHX(31);
2599
2600         save_y = y = grd_curcanv->cv_h - n_left*(fth+1);
2601
2602         if (Cockpit_mode.intval == CM_FULL_COCKPIT) {
2603                 save_y = y -= LHX(6);
2604                 if (Game_mode & GM_MULTI_COOP)
2605                         x1 = LHX(33);
2606                 else
2607                         x1 = LHX(43);
2608         }
2609
2610         for (i=0;i<n_players;i++) {
2611                 int player_num;
2612                 char name[9];
2613                 int sw,sh,aw;
2614
2615                 if (i>=n_left) {
2616                         if (Cockpit_mode.intval == CM_FULL_COCKPIT)
2617                                 x0 = grd_curcanv->cv_w - LHX(53);
2618                         else
2619                                 x0 = grd_curcanv->cv_w - LHX(60);
2620                         if (Game_mode & GM_MULTI_COOP)
2621                                 x1 = grd_curcanv->cv_w - LHX(27);
2622                         else
2623                                 x1 = grd_curcanv->cv_w - LHX(15);  // Right edge of name, change this for width problems
2624                         if (i==n_left)
2625                                 y = save_y;
2626
2627         if (Netgame.KillGoal || Netgame.PlayTimeAllowed)
2628            {
2629              x1-=LHX(18);
2630             // x0-=LHX(18);
2631            }
2632                 }
2633      else  if (Netgame.KillGoal || Netgame.PlayTimeAllowed)
2634            {
2635                                  x1 = LHX(43);
2636              x1-=LHX(18);
2637             // x0-=LHX(18);
2638            }
2639
2640         
2641                 if (Show_kill_list == 3)
2642                         player_num = i;
2643                 else
2644                         player_num = player_list[i];
2645
2646                 if (Show_kill_list == 1 || Show_kill_list==2)
2647                 {
2648                         int color;
2649
2650                         if (Players[player_num].connected != 1)
2651                                 gr_set_fontcolor(gr_getcolor(12, 12, 12), -1);
2652                         else if (Game_mode & GM_TEAM) {
2653                                 color = get_team(player_num);
2654                                 gr_set_fontcolor(gr_getcolor(player_rgb[color].r,player_rgb[color].g,player_rgb[color].b),-1 );
2655                         }
2656                         else {
2657                                 color = player_num;
2658                                 gr_set_fontcolor(gr_getcolor(player_rgb[color].r,player_rgb[color].g,player_rgb[color].b),-1 );
2659                         }
2660                 }       
2661
2662                 else 
2663                 {
2664                         gr_set_fontcolor(gr_getcolor(player_rgb[player_num].r,player_rgb[player_num].g,player_rgb[player_num].b),-1 );
2665                 }
2666
2667                 if (Show_kill_list == 3)
2668                         strcpy(name, Netgame.team_name[i]);
2669                 else
2670                         strcpy(name,Players[player_num].callsign);      // Note link to above if!!
2671                 gr_get_string_size(name,&sw,&sh,&aw);
2672                 while (sw > (x1-x0-LHX(2))) {
2673                         name[strlen(name)-1]=0;
2674                         gr_get_string_size(name,&sw,&sh,&aw);
2675                 }
2676                 gr_printf(x0,y,"%s",name);
2677
2678                 if (Show_kill_list==2)
2679                  {
2680                   if (Players[player_num].net_killed_total+Players[player_num].net_kills_total==0)
2681                         gr_printf (x1,y,"NA");
2682                   else
2683                    gr_printf (x1,y,"%d%%",(int)((float)((float)Players[player_num].net_kills_total/((float)Players[player_num].net_killed_total+(float)Players[player_num].net_kills_total))*100.0));           
2684                  }
2685                 else if (Show_kill_list == 3)   
2686                         gr_printf(x1,y,"%3d",team_kills[i]);
2687                 else if (Game_mode & GM_MULTI_COOP)
2688                         gr_printf(x1,y,"%-6d",Players[player_num].score);
2689       else if (Netgame.PlayTimeAllowed || Netgame.KillGoal)
2690          gr_printf(x1,y,"%3d(%d)",Players[player_num].net_kills_total,Players[player_num].KillGoalCount);
2691       else
2692                         gr_printf(x1,y,"%3d",Players[player_num].net_kills_total);
2693                         
2694                 y += fth+1;
2695
2696         }
2697
2698 #ifdef MACINTOSH
2699         MenuHires = 1;
2700 #endif
2701 }
2702 #endif
2703
2704 #ifndef RELEASE
2705 extern int Saving_movie_frames;
2706 #else
2707 #define Saving_movie_frames 0
2708 #endif
2709
2710 //returns true if viewer can see object
2711 int see_object(int objnum)
2712 {
2713         fvi_query fq;
2714         int hit_type;
2715         fvi_info hit_data;
2716
2717         //see if we can see this player
2718
2719         fq.p0                                   = &Viewer->pos;
2720         fq.p1                                   = &Objects[objnum].pos;
2721         fq.rad                                  = 0;
2722         fq.thisobjnum       = OBJECT_NUMBER(Viewer);
2723         fq.flags                                = FQ_TRANSWALL | FQ_CHECK_OBJS;
2724         fq.startseg                             = Viewer->segnum;
2725         fq.ignore_obj_list      = NULL;
2726
2727         hit_type = find_vector_intersection(&fq, &hit_data);
2728
2729         return (hit_type == HIT_OBJECT && hit_data.hit_object == objnum);
2730 }
2731
2732 #ifdef NETWORK
2733 //show names of teammates & players carrying flags
2734 void show_HUD_names()
2735 {
2736         int show_team_names,show_all_names,show_flags,player_team;
2737         int p;
2738
2739         show_all_names = ((Newdemo_state == ND_STATE_PLAYBACK) || (Netgame.ShowAllNames && Show_reticle_name));
2740         show_team_names = (((Game_mode & GM_MULTI_COOP) || (Game_mode & GM_TEAM)) && Show_reticle_name);
2741         show_flags = (Game_mode & GM_CAPTURE) | (Game_mode & GM_HOARD);
2742
2743         if (! (show_all_names || show_team_names || show_flags))
2744                 return;
2745
2746         player_team = get_team(Player_num);
2747
2748         for (p=0;p<N_players;p++) {     //check all players
2749                 int objnum;
2750                 int show_name,has_flag;
2751
2752                 show_name = ((show_all_names && !(Players[p].flags & PLAYER_FLAGS_CLOAKED)) || (show_team_names && get_team(p)==player_team));
2753                 has_flag = (Players[p].connected && Players[p].flags & PLAYER_FLAGS_FLAG);
2754
2755                 if (Newdemo_state == ND_STATE_PLAYBACK) {
2756                         //if this is a demo, the objnum in the player struct is wrong,
2757                         //so we search the object list for the objnum
2758
2759                         for (objnum=0;objnum<=Highest_object_index;objnum++)
2760                                 if (Objects[objnum].type==OBJ_PLAYER && Objects[objnum].id == p)
2761                                         break;
2762                         if (objnum > Highest_object_index)              //not in list, thus not visible
2763                                 show_name = has_flag = 0;                               //..so don't show name
2764                 }
2765                 else
2766                         objnum = Players[p].objnum;
2767
2768                 if ((show_name || has_flag) && see_object(objnum)) {
2769                         g3s_point player_point;
2770
2771                         g3_rotate_point(&player_point,&Objects[objnum].pos);
2772
2773                         if (player_point.p3_codes == 0) {       //on screen
2774
2775                                 g3_project_point(&player_point);
2776
2777                                 if (! (player_point.p3_flags & PF_OVERFLOW)) {
2778                                         fix x,y;
2779                         
2780                                         x = player_point.p3_sx;
2781                                         y = player_point.p3_sy;
2782                         
2783                                         if (show_name) {                                // Draw callsign on HUD
2784                                                 char s[CALLSIGN_LEN+1];
2785                                                 int w, h, aw;
2786                                                 int x1, y1;
2787                                                 int color_num;
2788                         
2789                                                 color_num = (Game_mode & GM_TEAM)?get_team(p):p;
2790
2791                                                 sprintf(s, "%s", Players[p].callsign);
2792                                                 gr_get_string_size(s, &w, &h, &aw);
2793                                                 gr_set_fontcolor(gr_getcolor(player_rgb[color_num].r,player_rgb[color_num].g,player_rgb[color_num].b),-1 );
2794                                                 x1 = f2i(x)-w/2;
2795                                                 y1 = f2i(y)-h/2;
2796                                                 gr_string (x1, y1, s);
2797                                         }
2798                 
2799                                         if (has_flag) {                         // Draw box on HUD
2800                                                 fix dx,dy,w,h;
2801                         
2802                                                 dy = -fixmuldiv(fixmul(Objects[objnum].size,Matrix_scale.y),i2f(grd_curcanv->cv_h)/2,player_point.p3_z);
2803                                                 dx = fixmul(dy,grd_curscreen->sc_aspect);
2804         
2805                                                 w = dx/4;
2806                                                 h = dy/4;
2807         
2808                                                 if (Game_mode & GM_CAPTURE)
2809                                                         gr_setcolor((get_team(p) == TEAM_BLUE)?BM_XRGB(31,0,0):BM_XRGB(0,0,31));
2810                                                 else if (Game_mode & GM_HOARD)
2811                                                 {
2812                                                         if (Game_mode & GM_TEAM)
2813                                                                 gr_setcolor((get_team(p) == TEAM_RED)?BM_XRGB(31,0,0):BM_XRGB(0,0,31));
2814                                                         else
2815                                                                 gr_setcolor(BM_XRGB(0,31,0));
2816                                                 }
2817
2818                                                 gr_line(x+dx-w,y-dy,x+dx,y-dy);
2819                                                 gr_line(x+dx,y-dy,x+dx,y-dy+h);
2820         
2821                                                 gr_line(x-dx,y-dy,x-dx+w,y-dy);
2822                                                 gr_line(x-dx,y-dy,x-dx,y-dy+h);
2823         
2824                                                 gr_line(x+dx-w,y+dy,x+dx,y+dy);
2825                                                 gr_line(x+dx,y+dy,x+dx,y+dy-h);
2826         
2827                                                 gr_line(x-dx,y+dy,x-dx+w,y+dy);
2828                                                 gr_line(x-dx,y+dy,x-dx,y+dy-h);
2829                                         }
2830                                 }
2831                         }
2832                 }
2833         }
2834 }
2835 #endif
2836
2837
2838 extern int last_drawn_cockpit[2];
2839
2840 //draw all the things on the HUD
2841 void draw_hud()
2842 {
2843
2844 #if 0 //def OGL
2845         if (Cockpit_mode.intval == CM_STATUS_BAR) {
2846                 //ogl needs to redraw every frame, at least currently.
2847                 //              init_cockpit();
2848                         last_drawn_cockpit[0]=-1;
2849                         last_drawn_cockpit[1]=-1;
2850                                   init_gauges();
2851                 
2852                                //              vr_reset_display();
2853         }
2854 #endif
2855                                           
2856
2857         Line_spacing = GAME_FONT->ft_h + GAME_FONT->ft_h/4;
2858
2859         //      Show score so long as not in rearview
2860         if ( !Rear_view && Cockpit_mode.intval != CM_REAR_VIEW && Cockpit_mode.intval != CM_STATUS_BAR && !Saving_movie_frames) {
2861                 hud_show_score();
2862                 if (score_time)
2863                         hud_show_score_added();
2864         }
2865
2866         if ( !Rear_view && Cockpit_mode.intval != CM_REAR_VIEW && !Saving_movie_frames)
2867          hud_show_timer_count();
2868
2869         //      Show other stuff if not in rearview or letterbox.
2870         if (!Rear_view && Cockpit_mode.intval != CM_REAR_VIEW) { // && Cockpit_mode.intval!=CM_LETTERBOX) {
2871                 if (Cockpit_mode.intval == CM_STATUS_BAR || Cockpit_mode.intval == CM_FULL_SCREEN)
2872                         hud_show_homing_warning();
2873
2874                 if (Cockpit_mode.intval == CM_FULL_SCREEN) {
2875                         hud_show_energy();
2876                         hud_show_shield();
2877                         hud_show_afterburner();
2878                         hud_show_weapons();
2879                         if (!Saving_movie_frames)
2880                                 hud_show_keys();
2881                         hud_show_cloak_invuln();
2882
2883                         if ( ( Newdemo_state == ND_STATE_RECORDING ) && ( Players[Player_num].flags != old_flags[VR_current_page] )) {
2884                                 newdemo_record_player_flags(old_flags[VR_current_page], Players[Player_num].flags);
2885                                 old_flags[VR_current_page] = Players[Player_num].flags;
2886                         }
2887                 }
2888
2889                 #ifdef NETWORK
2890                 #ifndef RELEASE
2891                 if (!(Game_mode&GM_MULTI && Show_kill_list) && !Saving_movie_frames)
2892                         show_time();
2893                 #endif
2894                 #endif
2895                 if (Reticle_on.intval && Cockpit_mode.intval != CM_LETTERBOX && (!Use_player_head_angles))
2896                         show_reticle(0);
2897
2898 #ifdef NETWORK
2899                 show_HUD_names();
2900
2901                 if (Cockpit_mode.intval != CM_LETTERBOX && Cockpit_mode.intval != CM_REAR_VIEW)
2902                         hud_show_flag();
2903
2904                 if (Cockpit_mode.intval != CM_LETTERBOX && Cockpit_mode.intval != CM_REAR_VIEW)
2905                         hud_show_orbs();
2906
2907 #endif
2908                 if (!Saving_movie_frames)
2909                         HUD_render_message_frame();
2910
2911                 if (Cockpit_mode.intval != CM_STATUS_BAR && !Saving_movie_frames)
2912                         hud_show_lives();
2913
2914                 #ifdef NETWORK
2915                 if (Game_mode&GM_MULTI && Show_kill_list)
2916                         hud_show_kill_list();
2917                 #endif
2918         }
2919
2920         if (Rear_view && Cockpit_mode.intval != CM_REAR_VIEW) {
2921                 HUD_render_message_frame();
2922                 gr_set_curfont( GAME_FONT );
2923                 gr_set_fontcolor(gr_getcolor(0,31,0),-1 );
2924                 if (Newdemo_state == ND_STATE_PLAYBACK)
2925                         gr_printf(0x8000,grd_curcanv->cv_h-14,TXT_REAR_VIEW);
2926                 else
2927                         gr_printf(0x8000,grd_curcanv->cv_h-10,TXT_REAR_VIEW);
2928         }
2929 }
2930
2931 extern short *BackBuffer;
2932
2933 //print out some player statistics
2934 void render_gauges()
2935 {
2936         static uint32_t old_display_mode = 0xfffffffe;
2937         int energy = f2ir(Players[Player_num].energy);
2938         int shields = f2ir(Players[Player_num].shields);
2939         int cloak = ((Players[Player_num].flags&PLAYER_FLAGS_CLOAKED) != 0);
2940  
2941         Assert(Cockpit_mode.intval == CM_FULL_COCKPIT || Cockpit_mode.intval == CM_STATUS_BAR);
2942
2943 // check to see if our display mode has changed since last render time --
2944 // if so, then we need to make new gauge canvases.
2945 // Also make the first gauge canvases here, in the game,
2946 // because they are [now] sub-canvases.
2947
2948   
2949         if (old_display_mode != Current_display_mode)
2950         {
2951                 close_gauge_canvases();
2952                 init_gauge_canvases();
2953                 old_display_mode = Current_display_mode;
2954         }
2955
2956         if (shields < 0 ) shields = 0;
2957
2958         gr_set_current_canvas(get_current_game_screen());
2959         gr_set_curfont( GAME_FONT );
2960
2961         if (Newdemo_state == ND_STATE_RECORDING)
2962                 if (Players[Player_num].homing_object_dist >= 0)
2963                         newdemo_record_homing_distance(Players[Player_num].homing_object_dist);
2964
2965         if (Cockpit_mode.intval == CM_FULL_COCKPIT)
2966                 draw_player_ship(cloak, old_cloak[VR_current_page], SHIP_GAUGE_X, SHIP_GAUGE_Y);
2967         else
2968                 draw_player_ship(cloak, old_cloak[VR_current_page], SB_SHIP_GAUGE_X, SB_SHIP_GAUGE_Y);
2969
2970         old_cloak[VR_current_page] = cloak;
2971
2972         if (Cockpit_mode.intval == CM_FULL_COCKPIT) {
2973                 if (Newdemo_state == ND_STATE_RECORDING && (energy != old_energy[VR_current_page]))
2974                 {
2975                         newdemo_record_player_energy(old_energy[VR_current_page], energy);
2976                         old_energy[VR_current_page] = energy;
2977                 }
2978                 draw_energy_bar(energy);
2979                 draw_numerical_display(shields, energy);
2980
2981                 if (Newdemo_state == ND_STATE_RECORDING && (Afterburner_charge != old_afterburner[VR_current_page]))
2982                 {
2983                         newdemo_record_player_afterburner(old_afterburner[VR_current_page], Afterburner_charge);
2984                         old_afterburner[VR_current_page] = Afterburner_charge;
2985                 }
2986                 draw_afterburner_bar(Afterburner_charge);
2987
2988                 if (Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE) {
2989                         draw_invulnerable_ship();
2990                         old_shields[VR_current_page] = shields ^ 1;
2991                 } else {                // Draw the shield gauge
2992                         if (Newdemo_state == ND_STATE_RECORDING && (shields != old_shields[VR_current_page]))
2993                         {
2994                                 newdemo_record_player_shields(old_shields[VR_current_page], shields);
2995                                 old_shields[VR_current_page] = shields;
2996                         }
2997                         draw_shield_bar(shields);
2998                 }
2999                 draw_numerical_display(shields, energy);
3000         
3001                 if (Newdemo_state == ND_STATE_RECORDING && (Players[Player_num].flags != old_flags[VR_current_page]))
3002                 {
3003                         newdemo_record_player_flags(old_flags[VR_current_page], Players[Player_num].flags);
3004                         old_flags[VR_current_page] = Players[Player_num].flags;
3005                 }
3006                 draw_keys();
3007
3008                 show_homing_warning();
3009
3010         } else if (Cockpit_mode.intval == CM_STATUS_BAR) {
3011
3012                 if (Newdemo_state == ND_STATE_RECORDING && (energy != old_energy[VR_current_page]))
3013                 {
3014                         newdemo_record_player_energy(old_energy[VR_current_page], energy);
3015                         old_energy[VR_current_page] = energy;
3016                 }
3017                 sb_draw_energy_bar(energy);
3018
3019                 if (Newdemo_state == ND_STATE_RECORDING && (Afterburner_charge != old_afterburner[VR_current_page]))
3020                 {
3021                         newdemo_record_player_afterburner(old_afterburner[VR_current_page], Afterburner_charge);
3022                         old_afterburner[VR_current_page] = Afterburner_charge;
3023                 }
3024                 sb_draw_afterburner();
3025
3026                 if (Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE)
3027                 {
3028                         draw_invulnerable_ship();
3029                         old_shields[VR_current_page] = shields ^ 1;
3030                 } 
3031                 else
3032                 {               // Draw the shield gauge
3033                         if (Newdemo_state == ND_STATE_RECORDING && (shields != old_shields[VR_current_page]))
3034                         {
3035                                 newdemo_record_player_shields(old_shields[VR_current_page], shields);
3036                                 old_shields[VR_current_page] = shields;
3037                         }
3038                         sb_draw_shield_bar(shields);
3039                 }
3040                 sb_draw_shield_num(shields);
3041
3042                 if (Newdemo_state == ND_STATE_RECORDING && (Players[Player_num].flags != old_flags[VR_current_page]))
3043                 {
3044                         newdemo_record_player_flags(old_flags[VR_current_page], Players[Player_num].flags);
3045                         old_flags[VR_current_page] = Players[Player_num].flags;
3046                 }
3047                 sb_draw_keys();
3048         
3049
3050                 // May want to record this in a demo...
3051                 if ((Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP))
3052                 {
3053                         sb_show_lives();
3054                         old_lives[VR_current_page] = Players[Player_num].net_killed_total;
3055                 }
3056                 else
3057                 {
3058                         sb_show_lives();
3059                         old_lives[VR_current_page] = Players[Player_num].lives;
3060                 }
3061
3062                 if ((Game_mode&GM_MULTI) && !(Game_mode & GM_MULTI_COOP))
3063                 {
3064                         sb_show_score();
3065                         old_score[VR_current_page] = Players[Player_num].net_kills_total;
3066                 }
3067                 else
3068                 {
3069                         sb_show_score();
3070                         old_score[VR_current_page] = Players[Player_num].score;
3071
3072                         //if (score_time)
3073                                 sb_show_score_added();
3074                 }
3075         }
3076
3077
3078         draw_weapon_boxes();
3079
3080 }
3081
3082 //      ---------------------------------------------------------------------------------------------------------
3083 //      Call when picked up a laser powerup.
3084 //      If laser is active, set old_weapon[0] to -1 to force redraw.
3085 void update_laser_weapon_info(void)
3086 {
3087         if (old_weapon[0][VR_current_page] == 0)
3088                 if (! (Players[Player_num].laser_level > MAX_LASER_LEVEL && old_laser_level[VR_current_page] <= MAX_LASER_LEVEL))
3089                         old_weapon[0][VR_current_page] = -1;
3090 }
3091
3092 extern int Game_window_y;
3093 void fill_background(void);
3094
3095 int SW_drawn[2], SW_x[2], SW_y[2], SW_w[2], SW_h[2];
3096
3097 //draws a 3d view into one of the cockpit windows.  win is 0 for left,
3098 //1 for right.  viewer is object.  NULL object means give up window
3099 //user is one of the WBU_ constants.  If rear_view_flag is set, show a
3100 //rear view.  If label is non-NULL, print the label at the top of the
3101 //window.
3102 void do_cockpit_window_view(int win,object *viewer,int rear_view_flag,int user,char *label)
3103 {
3104         grs_canvas window_canv;
3105         static grs_canvas overlap_canv;
3106         object *viewer_save = Viewer;
3107         static int overlap_dirty[2]={0,0};
3108         int boxnum;
3109         static int window_x,window_y;
3110         gauge_box *box;
3111         int rear_view_save = Rear_view;
3112         int w,h,dx;
3113
3114         box = NULL;
3115
3116         if (viewer == NULL) {                                                           //this user is done
3117
3118                 Assert(user == WBU_WEAPON || user == WBU_STATIC);
3119
3120                 if (user == WBU_STATIC && weapon_box_user[win] != WBU_STATIC)
3121                         static_time[win] = 0;
3122
3123                 if (weapon_box_user[win] == WBU_WEAPON || weapon_box_user[win] == WBU_STATIC)
3124                         return;         //already set
3125
3126                 weapon_box_user[win] = user;
3127
3128                 if (overlap_dirty[win]) {
3129                         gr_set_current_canvas(&VR_screen_pages[VR_current_page]);
3130                         fill_background();
3131                         overlap_dirty[win] = 0;
3132                 }
3133
3134                 return;
3135         }
3136
3137         update_rendered_data(win+1, viewer, rear_view_flag, user);
3138
3139         weapon_box_user[win] = user;                                            //say who's using window
3140                 
3141         Viewer = viewer;
3142         Rear_view = rear_view_flag;
3143
3144         if (Cockpit_mode.intval == CM_FULL_SCREEN)
3145         {
3146
3147                 w = VR_render_buffer[0].cv_bitmap.bm_w/6;                       // hmm.  I could probably do the sub_buffer assigment for all macines, but I aint gonna chance it
3148
3149                 h = i2f(w) / grd_curscreen->sc_aspect;
3150
3151                 dx = (win==0)?-(w+(w/10)):(w/10);
3152
3153                 window_x = VR_render_buffer[0].cv_bitmap.bm_w/2+dx;
3154                 window_y = VR_render_buffer[0].cv_bitmap.bm_h-h-(h/10);
3155
3156                 //copy these vars so stereo code can get at them
3157                 SW_drawn[win]=1; SW_x[win] = window_x; SW_y[win] = window_y; SW_w[win] = w; SW_h[win] = h; 
3158
3159                 gr_init_sub_canvas(&window_canv,&VR_render_buffer[0],window_x,window_y,w,h);
3160         }
3161         else {
3162                 if (Cockpit_mode.intval == CM_FULL_COCKPIT)
3163                         boxnum = (COCKPIT_PRIMARY_BOX)+win;
3164                 else if (Cockpit_mode.intval == CM_STATUS_BAR)
3165                         boxnum = (SB_PRIMARY_BOX)+win;
3166                 else
3167                         goto abort;
3168
3169                 box = &gauge_boxes[boxnum];
3170
3171                 gr_init_sub_canvas(&window_canv,&VR_render_buffer[0],box->left,box->top,box->right-box->left+1,box->bot-box->top+1);
3172         }
3173
3174         gr_set_current_canvas(&window_canv);
3175         
3176         render_frame(0, win+1);
3177                 
3178         //      HACK! If guided missile, wake up robots as necessary.
3179         if (viewer->type == OBJ_WEAPON) {
3180                 // -- Used to require to be GUIDED -- if (viewer->id == GUIDEDMISS_ID)
3181                 wake_up_rendered_objects(viewer, win+1);
3182         }
3183
3184         if (label) {
3185                 gr_set_curfont( GAME_FONT );
3186                 if (Color_0_31_0 == -1)
3187                         Color_0_31_0 = gr_getcolor(0,31,0);
3188                 gr_set_fontcolor(Color_0_31_0, -1);
3189                 gr_printf(0x8000,2,label);
3190         }
3191
3192         if (user == WBU_GUIDED)
3193                 draw_guided_crosshair();
3194
3195         if (Cockpit_mode.intval == CM_FULL_SCREEN) {
3196                 int small_window_bottom,big_window_bottom,extra_part_h;
3197                 
3198                 {
3199                         gr_setcolor(BM_XRGB(0,0,32));
3200                         gr_ubox(0,0,grd_curcanv->cv_bitmap.bm_w-1,grd_curcanv->cv_bitmap.bm_h-1);
3201                 }
3202
3203                 //if the window only partially overlaps the big 3d window, copy
3204                 //the extra part to the visible screen
3205
3206                 big_window_bottom = Game_window_y + Game_window_h.intval - 1;
3207
3208                 if (window_y > big_window_bottom) {
3209
3210                         //the small window is completely outside the big 3d window, so
3211                         //copy it to the visible screen
3212
3213                         if (VR_screen_flags & VRF_USE_PAGING)
3214                                 gr_set_current_canvas(&VR_screen_pages[!VR_current_page]);
3215                         else
3216                                 gr_set_current_canvas(get_current_game_screen());
3217
3218                         gr_bitmap(window_x,window_y,&window_canv.cv_bitmap);
3219
3220                         overlap_dirty[win] = 1;
3221                 }
3222                 else {
3223
3224                         small_window_bottom = window_y + window_canv.cv_bitmap.bm_h - 1;
3225                         
3226                         extra_part_h = small_window_bottom - big_window_bottom;
3227
3228                         if (extra_part_h > 0) {
3229                         
3230                                 gr_init_sub_canvas(&overlap_canv,&window_canv,0,window_canv.cv_bitmap.bm_h-extra_part_h,window_canv.cv_bitmap.bm_w,extra_part_h);
3231
3232                                 if (VR_screen_flags & VRF_USE_PAGING)
3233                                         gr_set_current_canvas(&VR_screen_pages[!VR_current_page]);
3234                                 else
3235                                         gr_set_current_canvas(get_current_game_screen());
3236
3237                                 gr_bitmap(window_x,big_window_bottom+1,&overlap_canv.cv_bitmap);
3238                                 
3239                                 overlap_dirty[win] = 1;
3240                         }
3241                 }
3242         }
3243         else {
3244         
3245                 gr_set_current_canvas(get_current_game_screen());
3246                 copy_gauge_box(box,&VR_render_buffer[0].cv_bitmap);
3247         }
3248
3249         //force redraw when done
3250         old_weapon[win][VR_current_page] = old_ammo_count[win][VR_current_page] = -1;
3251
3252 abort:;
3253
3254         Viewer = viewer_save;
3255
3256         Rear_view = rear_view_save;
3257 }
3258
3259 #ifdef MACINTOSH
3260         void calculate_sub_view_window_bounds(int inSubWindowNum, TQARect* outBoundsRect)
3261         {
3262                 int             boxNumber               = 0;
3263                 gauge_box*      currentGaugeBox = NULL;
3264                 int w   = 0;
3265                 int h   = 0;
3266                 int dx  = 0;
3267                 int window_x = 0;
3268                 int window_y = 0;
3269
3270                 Assert(outBoundsRect);
3271                 Assert((inSubWindowNum == 0) || (inSubWindowNum == 1));
3272                 
3273                 switch (Cockpit_mode.intval)
3274                 {
3275                         case CM_FULL_SCREEN:
3276                                 // note: this calculation is taken from do_cockpit_window_view for the full
3277                                 // screen mode case
3278                 
3279                                 w = (VR_render_buffer[0].cv_bitmap.bm_w) / 6;
3280                                 h = (i2f(w)) / (grd_curscreen->sc_aspect);
3281                 
3282                                 dx = (inSubWindowNum==0)?-(w+(w/10)):(w/10);
3283                 
3284                                 window_x = ((VR_render_buffer[0].cv_bitmap.bm_w) / 2) + dx;
3285                                 window_y = (VR_render_buffer[0].cv_bitmap.bm_h) - h - (h/10);
3286                                 
3287                                 outBoundsRect->top              = window_x;
3288                                 outBoundsRect->left             = window_y;
3289                                 outBoundsRect->bottom   = window_x + w;
3290                                 outBoundsRect->right    = window_y + h;
3291                                 break;
3292         
3293                         case CM_FULL_COCKPIT:
3294                         case CM_STATUS_BAR:
3295                                 if (inSubWindowNum == 0)
3296                                 {
3297                                         boxNumber = SB_PRIMARY_BOX;
3298                                 }
3299                                 else
3300                                 {
3301                                         boxNumber = SB_SECONDARY_BOX;
3302                                 }
3303                                 
3304                                 //boxNumber = (Current_display_mode * 4) + (Cockpit_mode.intval * 2) + inSubWindowNum;
3305                                 currentGaugeBox = &gauge_boxes[boxNumber];
3306                                 Assert(currentGaugeBox);
3307                                 
3308                                 outBoundsRect->top              = currentGaugeBox->top;
3309                                 outBoundsRect->left             = currentGaugeBox->left;
3310                                 outBoundsRect->bottom   = currentGaugeBox->bot + 1;
3311                                 outBoundsRect->right    = currentGaugeBox->right + 1;
3312                                 
3313                                 break;
3314         
3315                         default:
3316                                 Int3();
3317                                 return;
3318                 }
3319         }
3320
3321 #endif
3322
3323