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