]> icculus.org git repositories - btb/d2x.git/blob - main/gauges.c
always show bomb count if player has them
[btb/d2x.git] / main / gauges.c
1 /* $Id: gauges.c,v 1.25 2006-07-29 04:15:55 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 = NULL;
74 grs_canvas *Canv_AfterburnerGauge = NULL;
75 grs_canvas *Canv_SBEnergyGauge = NULL;
76 grs_canvas *Canv_SBAfterburnerGauge = NULL;
77 grs_canvas *Canv_RightEnergyGauge = NULL;
78 grs_canvas *Canv_NumericalGauge = NULL;
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         grs_font *save_font = grd_curcanv->cv_font;
1691
1692         gr_set_curfont(GAME_FONT);
1693
1694         PAGE_IN_GAUGE( SB_GAUGE_ENERGY );
1695         PAGE_IN_GAUGE( GAUGE_AFTERBURNER );
1696
1697         Canv_LeftEnergyGauge    = gr_create_sub_canvas( grd_curcanv, LEFT_ENERGY_GAUGE_X, LEFT_ENERGY_GAUGE_Y, LEFT_ENERGY_GAUGE_W, LEFT_ENERGY_GAUGE_H );
1698         Canv_SBEnergyGauge              = gr_create_sub_canvas( grd_curcanv, SB_ENERGY_GAUGE_X, SB_ENERGY_GAUGE_Y, SB_ENERGY_GAUGE_W, SB_ENERGY_GAUGE_H );
1699         Canv_SBAfterburnerGauge = gr_create_sub_canvas( grd_curcanv, SB_AFTERBURNER_GAUGE_X, SB_AFTERBURNER_GAUGE_Y, SB_AFTERBURNER_GAUGE_W, SB_AFTERBURNER_GAUGE_H );
1700         Canv_RightEnergyGauge   = gr_create_sub_canvas( grd_curcanv, RIGHT_ENERGY_GAUGE_X, RIGHT_ENERGY_GAUGE_Y, RIGHT_ENERGY_GAUGE_W, RIGHT_ENERGY_GAUGE_H );
1701         Canv_NumericalGauge             = gr_create_sub_canvas( grd_curcanv, NUMERICAL_GAUGE_X, NUMERICAL_GAUGE_Y, NUMERICAL_GAUGE_W, NUMERICAL_GAUGE_H );
1702         Canv_AfterburnerGauge   = gr_create_sub_canvas( grd_curcanv, AFTERBURNER_GAUGE_X, AFTERBURNER_GAUGE_Y, AFTERBURNER_GAUGE_W, AFTERBURNER_GAUGE_H );
1703
1704         gr_set_curfont(save_font);
1705 }
1706
1707 void close_gauge_canvases()
1708 {
1709         if (Canv_LeftEnergyGauge)
1710         {
1711                 gr_free_sub_canvas( Canv_LeftEnergyGauge );
1712                 gr_free_sub_canvas( Canv_SBEnergyGauge );
1713                 gr_free_sub_canvas( Canv_SBAfterburnerGauge );
1714                 gr_free_sub_canvas( Canv_RightEnergyGauge );
1715                 gr_free_sub_canvas( Canv_NumericalGauge );
1716                 gr_free_sub_canvas( Canv_AfterburnerGauge );
1717         }
1718 }
1719
1720 void init_gauges()
1721 {
1722         int i;
1723
1724         //draw_gauges_on        = 1;
1725
1726         for (i=0; i<2; i++ )    {
1727                 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)) ) 
1728                         old_score[i] = -99;
1729                 else
1730                         old_score[i]                    = -1;
1731                 old_energy[i]                   = -1;
1732                 old_shields[i]                  = -1;
1733                 old_flags[i]                    = -1;
1734                 old_cloak[i]                    = -1;
1735                 old_lives[i]                    = -1;
1736                 old_afterburner[i]      = -1;
1737                 old_bombcount[i]                = 0;
1738                 old_laser_level[i]      = 0;
1739         
1740                 old_weapon[0][i] = old_weapon[1][i] = -1;
1741                 old_ammo_count[0][i] = old_ammo_count[1][i] = -1;
1742                 Old_Omega_charge[i] = -1;
1743         }
1744
1745         cloak_fade_state = 0;
1746
1747         weapon_box_user[0] = weapon_box_user[1] = WBU_WEAPON;
1748 }
1749
1750 void draw_energy_bar(int energy)
1751 {
1752         int not_energy;
1753         int x1, x2, y;
1754
1755         // Draw left energy bar
1756         gr_set_current_canvas( Canv_LeftEnergyGauge );
1757         PAGE_IN_GAUGE( GAUGE_ENERGY_LEFT );
1758         gr_ubitmapm( 0, 0, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_ENERGY_LEFT)] );
1759         gr_setcolor( BM_XRGB(0,0,0) );
1760
1761         if ( !Current_display_mode )
1762                 not_energy = 61 - (energy*61)/100;
1763         else
1764                 not_energy = 125 - (energy*125)/100;
1765
1766         if (energy < 100)
1767                 for (y=0; y < LEFT_ENERGY_GAUGE_H; y++) {
1768                         x1 = LEFT_ENERGY_GAUGE_H - 1 - y;
1769                         x2 = LEFT_ENERGY_GAUGE_H - 1 - y + not_energy;
1770
1771                         if (x2 > LEFT_ENERGY_GAUGE_W - y/3)
1772                                 x2 = LEFT_ENERGY_GAUGE_W - y/3;
1773                         
1774                         if (x2 > x1) gr_uline( i2f(x1), i2f(y), i2f(x2), i2f(y) ); 
1775                 }
1776         
1777         gr_set_current_canvas( get_current_game_screen() );
1778
1779         // Draw right energy bar
1780         gr_set_current_canvas( Canv_RightEnergyGauge );
1781         PAGE_IN_GAUGE( GAUGE_ENERGY_RIGHT );
1782         gr_ubitmapm( 0, 0, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_ENERGY_RIGHT) ] );
1783         gr_setcolor( BM_XRGB(0,0,0) );
1784
1785         if (energy < 100)
1786                 for (y=0; y < RIGHT_ENERGY_GAUGE_H; y++) {
1787                         x1 = RIGHT_ENERGY_GAUGE_W - RIGHT_ENERGY_GAUGE_H + 1 + y - not_energy;
1788                         x2 = RIGHT_ENERGY_GAUGE_W - RIGHT_ENERGY_GAUGE_H + 1 + y;
1789
1790                         if (x1 < y/3)
1791                                 x1 = y/3;
1792
1793                         if (x2 > x1) gr_uline( i2f(x1), i2f(y), i2f(x2), i2f(y) );  
1794                 }
1795
1796         gr_set_current_canvas( get_current_game_screen() );
1797 }
1798
1799 ubyte afterburner_bar_table[AFTERBURNER_GAUGE_H_L*2] = {
1800                         3,11,
1801                         3,11,
1802                         3,11,
1803                         3,11,
1804                         3,11,
1805                         3,11,
1806                         2,11,
1807                         2,10,
1808                         2,10,
1809                         2,10,
1810                         2,10,
1811                         2,10,
1812                         2,10,
1813                         1,10,
1814                         1,10,
1815                         1,10,
1816                         1,9,
1817                         1,9,
1818                         1,9,
1819                         1,9,
1820                         0,9,
1821                         0,9,
1822                         0,8,
1823                         0,8,
1824                         0,8,
1825                         0,8,
1826                         1,8,
1827                         2,8,
1828                         3,8,
1829                         4,8,
1830                         5,8,
1831                         6,7,
1832 };
1833
1834 ubyte afterburner_bar_table_hires[AFTERBURNER_GAUGE_H_H*2] = {
1835         5,20,
1836         5,20,
1837         5,19,
1838         5,19,
1839         5,19,
1840         5,19,
1841         4,19,
1842         4,19,
1843         4,19,
1844         4,19,
1845
1846         4,19,
1847         4,18,
1848         4,18,
1849         4,18,
1850         4,18,
1851         3,18,
1852         3,18,
1853         3,18,
1854         3,18,
1855         3,18,
1856
1857         3,18,
1858         3,17,
1859         3,17,
1860         2,17,
1861         2,17,
1862         2,17,
1863         2,17,
1864         2,17,
1865         2,17,
1866         2,17,
1867
1868         2,17,
1869         2,16,
1870         2,16,
1871         1,16,
1872         1,16,
1873         1,16,
1874         1,16,
1875         1,16,
1876         1,16,
1877         1,16,
1878
1879         1,16,
1880         1,15,
1881         1,15,
1882         1,15,
1883         0,15,
1884         0,15,
1885         0,15,
1886         0,15,
1887         0,15,
1888         0,15,
1889
1890         0,14,
1891         0,14,
1892         0,14,
1893         1,14,
1894         2,14,
1895         3,14,
1896         4,14,
1897         5,14,
1898         6,13,
1899         7,13,
1900
1901         8,13,
1902         9,13,
1903         10,13,
1904         11,13,
1905         12,13
1906 };
1907
1908
1909 void draw_afterburner_bar(int afterburner)
1910 {
1911         int not_afterburner;
1912         int y;
1913
1914         // Draw afterburner bar
1915         gr_set_current_canvas( Canv_AfterburnerGauge );
1916         PAGE_IN_GAUGE( GAUGE_AFTERBURNER );
1917         gr_ubitmapm( 0, 0, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_AFTERBURNER) ] );
1918         gr_setcolor( BM_XRGB(0,0,0) );
1919
1920         not_afterburner = fixmul(f1_0 - afterburner,AFTERBURNER_GAUGE_H);
1921
1922         for (y=0;y<not_afterburner;y++) {
1923
1924                 gr_uline( i2f(Current_display_mode ? afterburner_bar_table_hires[y*2] : afterburner_bar_table[y*2]), i2f(y),
1925                                                 i2f((Current_display_mode ? afterburner_bar_table_hires[y*2 + 1] : afterburner_bar_table[y*2 + 1]) + 1), i2f(y) ); 
1926         }
1927
1928         gr_set_current_canvas( get_current_game_screen() );
1929 }
1930
1931 void draw_shield_bar(int shield)
1932 {
1933         int bm_num = shield>=100?9:(shield / 10);
1934
1935         PAGE_IN_GAUGE( GAUGE_SHIELDS+9-bm_num   );
1936         gr_ubitmapm( SHIELD_GAUGE_X, SHIELD_GAUGE_Y, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_SHIELDS+9-bm_num) ] );
1937 }
1938
1939 #define CLOAK_FADE_WAIT_TIME  0x400
1940
1941 void draw_player_ship(int cloak_state,int old_cloak_state,int x, int y)
1942 {
1943         static fix cloak_fade_timer=0;
1944         static int cloak_fade_value=GR_FADE_LEVELS-1;
1945         static int refade = 0;
1946         grs_bitmap *bm = NULL;
1947
1948         if (Game_mode & GM_TEAM)        {
1949                 #ifdef NETWORK
1950                 PAGE_IN_GAUGE( GAUGE_SHIPS+get_team(Player_num) );
1951                 bm = &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_SHIPS+get_team(Player_num)) ];
1952                 #endif
1953         } else {
1954                 PAGE_IN_GAUGE( GAUGE_SHIPS+Player_num );
1955                 bm = &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_SHIPS+Player_num) ];
1956         }
1957         
1958
1959         if (old_cloak_state==-1 && cloak_state)
1960                         cloak_fade_value=0;
1961
1962 //      mprintf((0, "cloak/oldcloak %d/%d", cloak_state, old_cloak_state));
1963
1964         if (!cloak_state) {
1965                 cloak_fade_value=GR_FADE_LEVELS-1;
1966                 cloak_fade_state = 0;
1967         }
1968
1969         if (cloak_state==1 && old_cloak_state==0)
1970                 cloak_fade_state = -1;
1971         //else if (cloak_state==0 && old_cloak_state==1)
1972         //      cloak_fade_state = 1;
1973
1974         if (cloak_state && GameTime > Players[Player_num].cloak_time + CLOAK_TIME_MAX - i2f(3))         //doing "about-to-uncloak" effect
1975                 if (cloak_fade_state==0)
1976                         cloak_fade_state = 2;
1977         
1978
1979         if (cloak_fade_state)
1980                 cloak_fade_timer -= FrameTime;
1981
1982         while (cloak_fade_state && cloak_fade_timer < 0) {
1983
1984                 cloak_fade_timer += CLOAK_FADE_WAIT_TIME;
1985
1986                 cloak_fade_value += cloak_fade_state;
1987
1988                 if (cloak_fade_value >= GR_FADE_LEVELS-1) {
1989                         cloak_fade_value = GR_FADE_LEVELS-1;
1990                         if (cloak_fade_state == 2 && cloak_state)
1991                                 cloak_fade_state = -2;
1992                         else
1993                                 cloak_fade_state = 0;
1994                 }
1995                 else if (cloak_fade_value <= 0) {
1996                         cloak_fade_value = 0;
1997                         if (cloak_fade_state == -2)
1998                                 cloak_fade_state = 2;
1999                         else
2000                                 cloak_fade_state = 0;
2001                 }
2002         }
2003
2004 //      To fade out both pages in a paged mode.
2005         if (refade) refade = 0;
2006         else if (cloak_state && old_cloak_state && !cloak_fade_state && !refade) {
2007                 cloak_fade_state = -1;
2008                 refade = 1;
2009         }
2010
2011         gr_set_current_canvas(&VR_render_buffer[0]);
2012
2013         gr_ubitmap( x, y, bm);
2014
2015         Gr_scanline_darkening_level = cloak_fade_value;
2016         gr_rect(x, y, x+bm->bm_w-1, y+bm->bm_h-1);
2017         Gr_scanline_darkening_level = GR_FADE_LEVELS;
2018
2019         gr_set_current_canvas( get_current_game_screen() );
2020
2021         gr_bm_ubitbltm( bm->bm_w, bm->bm_h, x, y, x, y, &VR_render_buffer[0].cv_bitmap, &grd_curcanv->cv_bitmap);
2022 }
2023
2024 #define INV_FRAME_TIME  (f1_0/10)               //how long for each frame
2025
2026 void draw_numerical_display(int shield, int energy)
2027 {
2028         gr_set_current_canvas( Canv_NumericalGauge );
2029         gr_set_curfont( GAME_FONT );
2030         PAGE_IN_GAUGE( GAUGE_NUMERICAL );
2031         gr_ubitmap( 0, 0, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_NUMERICAL) ] );
2032
2033         gr_set_fontcolor(gr_getcolor(14,14,23),-1 );
2034
2035         if (!Current_display_mode) {
2036                 gr_printf((shield>99)?3:((shield>9)?5:7),15,"%d",shield);
2037                 gr_set_fontcolor(gr_getcolor(25,18,6),-1 );
2038                 gr_printf((energy>99)?3:((energy>9)?5:7),2,"%d",energy);
2039         } else {
2040                 gr_printf((shield>99)?7:((shield>9)?11:15),33,"%d",shield);
2041                 gr_set_fontcolor(gr_getcolor(25,18,6),-1 );
2042                 gr_printf((energy>99)?7:((energy>9)?11:15),4,"%d",energy);
2043         }
2044         
2045         gr_set_current_canvas( get_current_game_screen() );
2046 }
2047
2048
2049 void draw_keys()
2050 {
2051         gr_set_current_canvas( get_current_game_screen() );
2052
2053         if (Players[Player_num].flags & PLAYER_FLAGS_BLUE_KEY ) {
2054                 PAGE_IN_GAUGE( GAUGE_BLUE_KEY );
2055                 gr_ubitmapm( GAUGE_BLUE_KEY_X, GAUGE_BLUE_KEY_Y, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_BLUE_KEY) ] );
2056         } else {
2057                 PAGE_IN_GAUGE( GAUGE_BLUE_KEY_OFF );
2058                 gr_ubitmapm( GAUGE_BLUE_KEY_X, GAUGE_BLUE_KEY_Y, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_BLUE_KEY_OFF) ] );
2059         }
2060
2061         if (Players[Player_num].flags & PLAYER_FLAGS_GOLD_KEY)  {
2062                 PAGE_IN_GAUGE( GAUGE_GOLD_KEY );
2063                 gr_ubitmapm( GAUGE_GOLD_KEY_X, GAUGE_GOLD_KEY_Y, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_GOLD_KEY) ] );
2064         } else {
2065                 PAGE_IN_GAUGE( GAUGE_GOLD_KEY_OFF );
2066                 gr_ubitmapm( GAUGE_GOLD_KEY_X, GAUGE_GOLD_KEY_Y, &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_GOLD_KEY_OFF) ] );
2067         }
2068
2069         if (Players[Player_num].flags & PLAYER_FLAGS_RED_KEY)   {
2070                 PAGE_IN_GAUGE( GAUGE_RED_KEY );
2071                 gr_ubitmapm( GAUGE_RED_KEY_X,  GAUGE_RED_KEY_Y,  &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_RED_KEY) ] );
2072         } else {
2073                 PAGE_IN_GAUGE( GAUGE_RED_KEY_OFF );
2074                 gr_ubitmapm( GAUGE_RED_KEY_X,  GAUGE_RED_KEY_Y,  &GameBitmaps[ GET_GAUGE_INDEX(GAUGE_RED_KEY_OFF) ] );
2075         }
2076 }
2077
2078
2079 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)
2080 {
2081         grs_bitmap *bm;
2082         char *p;
2083
2084         //clear the window
2085         gr_setcolor(BM_XRGB(0,0,0));
2086         
2087    gr_rect(box->left,box->top,box->right,box->bot);
2088
2089         if (Piggy_hamfile_version >= 3 // !SHAREWARE
2090                 && Current_display_mode)
2091         {
2092                 bm=&GameBitmaps[Weapon_info[info_index].hires_picture.index];
2093                 PIGGY_PAGE_IN( Weapon_info[info_index].hires_picture );
2094         } else {
2095                 bm=&GameBitmaps[Weapon_info[info_index].picture.index];
2096                 PIGGY_PAGE_IN( Weapon_info[info_index].picture );
2097         }
2098
2099         Assert(bm != NULL);
2100
2101         gr_ubitmapm(pic_x,pic_y,bm);
2102         
2103         gr_set_fontcolor(gr_getcolor(0,20,0),-1 );
2104
2105         if ((p=strchr(name,'\n'))!=NULL) {
2106                 *p=0;
2107                 gr_printf(text_x,text_y,name);
2108                 gr_printf(text_x,text_y+grd_curcanv->cv_font->ft_h+1,p+1);
2109                 *p='\n';
2110         } else
2111                 gr_printf(text_x,text_y,name);
2112
2113         //      For laser, show level and quadness
2114         if (info_index == LASER_ID || info_index == SUPER_LASER_ID) {
2115                 char    temp_str[7];
2116
2117                 sprintf(temp_str, "%s: 0", TXT_LVL);
2118
2119                 temp_str[5] = Players[Player_num].laser_level+1 + '0';
2120
2121                 gr_printf(text_x,text_y+Line_spacing, temp_str);
2122
2123                 if (Players[Player_num].flags & PLAYER_FLAGS_QUAD_LASERS) {
2124                         strcpy(temp_str, TXT_QUAD);
2125                         gr_printf(text_x,text_y+2*Line_spacing, temp_str);
2126
2127                 }
2128
2129         }
2130 }
2131
2132
2133 void draw_weapon_info(int weapon_type,int weapon_num,int laser_level)
2134 {
2135         int info_index;
2136
2137         if (weapon_type == 0) {
2138                 info_index = Primary_weapon_to_weapon_info[weapon_num];
2139
2140                 if (info_index == LASER_ID && laser_level > MAX_LASER_LEVEL)
2141                         info_index = SUPER_LASER_ID;
2142
2143                 if (Cockpit_mode == CM_STATUS_BAR)
2144                         draw_weapon_info_sub(info_index,
2145                                 &gauge_boxes[SB_PRIMARY_BOX],
2146                                 SB_PRIMARY_W_PIC_X,SB_PRIMARY_W_PIC_Y,
2147                                 PRIMARY_WEAPON_NAMES_SHORT(weapon_num),
2148                                 SB_PRIMARY_W_TEXT_X,SB_PRIMARY_W_TEXT_Y);
2149                 else
2150                         draw_weapon_info_sub(info_index,
2151                                 &gauge_boxes[COCKPIT_PRIMARY_BOX],
2152                                 PRIMARY_W_PIC_X,PRIMARY_W_PIC_Y,
2153                                 PRIMARY_WEAPON_NAMES_SHORT(weapon_num),
2154                                 PRIMARY_W_TEXT_X,PRIMARY_W_TEXT_Y);
2155
2156         }
2157         else {
2158                 info_index = Secondary_weapon_to_weapon_info[weapon_num];
2159
2160                 if (Cockpit_mode == CM_STATUS_BAR)
2161                         draw_weapon_info_sub(info_index,
2162                                 &gauge_boxes[SB_SECONDARY_BOX],
2163                                 SB_SECONDARY_W_PIC_X,SB_SECONDARY_W_PIC_Y,
2164                                 SECONDARY_WEAPON_NAMES_SHORT(weapon_num),
2165                                 SB_SECONDARY_W_TEXT_X,SB_SECONDARY_W_TEXT_Y);
2166                 else
2167                         draw_weapon_info_sub(info_index,
2168                                 &gauge_boxes[COCKPIT_SECONDARY_BOX],
2169                                 SECONDARY_W_PIC_X,SECONDARY_W_PIC_Y,
2170                                 SECONDARY_WEAPON_NAMES_SHORT(weapon_num),
2171                                 SECONDARY_W_TEXT_X,SECONDARY_W_TEXT_Y);
2172         }
2173 }
2174
2175 void draw_ammo_info(int x,int y,int ammo_count,int primary)
2176 {
2177         int w;
2178         char str[16];
2179
2180         if (primary)
2181                 w = (grd_curcanv->cv_font->ft_w*7)/2;
2182         else
2183                 w = (grd_curcanv->cv_font->ft_w*5)/2;
2184
2185         gr_setcolor(BM_XRGB(0,0,0));
2186         gr_rect(x,y,x+w,y+grd_curcanv->cv_font->ft_h);
2187         gr_set_fontcolor(gr_getcolor(20,0,0),-1 );
2188         sprintf(str,"%03d",ammo_count);
2189         convert_1s(str);
2190         gr_printf(x,y,str);
2191 }
2192
2193 void draw_secondary_ammo_info(int ammo_count)
2194 {
2195         if (Cockpit_mode == CM_STATUS_BAR)
2196                 draw_ammo_info(SB_SECONDARY_AMMO_X,SB_SECONDARY_AMMO_Y,ammo_count,0);
2197         else
2198                 draw_ammo_info(SECONDARY_AMMO_X,SECONDARY_AMMO_Y,ammo_count,0);
2199 }
2200
2201 //returns true if drew picture
2202 int draw_weapon_box(int weapon_type,int weapon_num)
2203 {
2204         int drew_flag=0;
2205         int laser_level_changed;
2206
2207         gr_set_current_canvas(&VR_render_buffer[0]);
2208
2209         gr_set_curfont( GAME_FONT );
2210
2211         laser_level_changed = (weapon_type==0 && weapon_num==LASER_INDEX && (Players[Player_num].laser_level != old_laser_level[VR_current_page]));
2212
2213         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))
2214         {
2215                 weapon_box_states[weapon_type] = WS_FADING_OUT;
2216                 weapon_box_fade_values[weapon_type]=i2f(GR_FADE_LEVELS-1);
2217         }
2218                 
2219         if (weapon_box_states[weapon_type] == WS_FADING_OUT) {
2220                 draw_weapon_info(weapon_type,old_weapon[weapon_type][VR_current_page],old_laser_level[VR_current_page]);
2221                 old_ammo_count[weapon_type][VR_current_page]=-1;
2222                 Old_Omega_charge[VR_current_page]=-1;
2223                 drew_flag=1;
2224                 weapon_box_fade_values[weapon_type] -= FrameTime * FADE_SCALE;
2225                 if (weapon_box_fade_values[weapon_type] <= 0) {
2226                         weapon_box_states[weapon_type] = WS_FADING_IN;
2227                         old_weapon[weapon_type][VR_current_page] = weapon_num;
2228                         old_weapon[weapon_type][!VR_current_page] = weapon_num;
2229                         old_laser_level[VR_current_page] = Players[Player_num].laser_level;
2230                         old_laser_level[!VR_current_page] = Players[Player_num].laser_level;
2231                         weapon_box_fade_values[weapon_type] = 0;
2232                 }
2233         }
2234         else if (weapon_box_states[weapon_type] == WS_FADING_IN) {
2235                 if (weapon_num != old_weapon[weapon_type][VR_current_page]) {
2236                         weapon_box_states[weapon_type] = WS_FADING_OUT;
2237                 }
2238                 else {
2239                         draw_weapon_info(weapon_type,weapon_num,Players[Player_num].laser_level);
2240                         old_ammo_count[weapon_type][VR_current_page]=-1;
2241                         Old_Omega_charge[VR_current_page]=-1;
2242                         drew_flag=1;
2243                         weapon_box_fade_values[weapon_type] += FrameTime * FADE_SCALE;
2244                         if (weapon_box_fade_values[weapon_type] >= i2f(GR_FADE_LEVELS-1)) {
2245                                 weapon_box_states[weapon_type] = WS_SET;
2246                                 old_weapon[weapon_type][!VR_current_page] = -1;         //force redraw (at full fade-in) of other page
2247                         }
2248                 }
2249         } else
2250         //      if (old_weapon[weapon_type][VR_current_page] == -1)
2251                         {
2252                         //@@if (laser_level_changed)
2253                         //@@    old_weapon[weapon_type][VR_current_page] = LASER_INDEX;
2254                         //@@else 
2255                         {
2256                                 draw_weapon_info(weapon_type, weapon_num, Players[Player_num].laser_level);
2257                                 old_weapon[weapon_type][VR_current_page] = weapon_num;
2258                                 old_ammo_count[weapon_type][VR_current_page] = -1;
2259                                 Old_Omega_charge[VR_current_page] = -1;
2260                                 old_laser_level[VR_current_page] = Players[Player_num].laser_level;
2261                                 drew_flag = 1;
2262                         }
2263                 }
2264
2265         if (weapon_box_states[weapon_type] != WS_SET) {         //fade gauge
2266                 int fade_value = f2i(weapon_box_fade_values[weapon_type]);
2267                 int boxofs = (Cockpit_mode==CM_STATUS_BAR)?SB_PRIMARY_BOX:COCKPIT_PRIMARY_BOX;
2268                 
2269                 Gr_scanline_darkening_level = fade_value;
2270                 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);
2271
2272                 Gr_scanline_darkening_level = GR_FADE_LEVELS;
2273         }
2274
2275         gr_set_current_canvas(get_current_game_screen());
2276         return drew_flag;
2277 }
2278
2279 fix static_time[2];
2280
2281 void draw_static(int win)
2282 {
2283         vclip *vc = &Vclip[VCLIP_MONITOR_STATIC];
2284         grs_bitmap *bmp;
2285         int framenum;
2286         int boxofs = (Cockpit_mode==CM_STATUS_BAR)?SB_PRIMARY_BOX:COCKPIT_PRIMARY_BOX;
2287         int x,y;
2288
2289         static_time[win] += FrameTime;
2290         if (static_time[win] >= vc->play_time) {
2291                 weapon_box_user[win] = WBU_WEAPON;
2292                 return;
2293         }
2294
2295         framenum = static_time[win] * vc->num_frames / vc->play_time;
2296
2297         PIGGY_PAGE_IN(vc->frames[framenum]);
2298
2299         bmp = &GameBitmaps[vc->frames[framenum].index];
2300
2301         gr_set_current_canvas(&VR_render_buffer[0]);
2302    
2303         for (x=gauge_boxes[boxofs+win].left;x<gauge_boxes[boxofs+win].right;x+=bmp->bm_w)
2304                 for (y=gauge_boxes[boxofs+win].top;y<gauge_boxes[boxofs+win].bot;y+=bmp->bm_h)
2305                         gr_bitmap(x,y,bmp);
2306
2307         gr_set_current_canvas(get_current_game_screen());
2308
2309         copy_gauge_box(&gauge_boxes[boxofs+win],&VR_render_buffer[0].cv_bitmap);
2310 }
2311
2312 void draw_weapon_boxes()
2313 {
2314         int boxofs = (Cockpit_mode==CM_STATUS_BAR)?SB_PRIMARY_BOX:COCKPIT_PRIMARY_BOX;
2315         int drew;
2316
2317         if (weapon_box_user[0] == WBU_WEAPON) {
2318                 drew = draw_weapon_box(0,Primary_weapon);
2319                 if (drew) 
2320                         copy_gauge_box(&gauge_boxes[boxofs+0],&VR_render_buffer[0].cv_bitmap);
2321
2322                 if (weapon_box_states[0] == WS_SET) {
2323                         if ((Primary_weapon == VULCAN_INDEX) || (Primary_weapon == GAUSS_INDEX))
2324                         {
2325                                 if (Newdemo_state == ND_STATE_RECORDING &&
2326                 Players[Player_num].primary_ammo[VULCAN_INDEX] != old_ammo_count[0][VR_current_page])
2327                                         newdemo_record_primary_ammo(old_ammo_count[0][VR_current_page], Players[Player_num].primary_ammo[VULCAN_INDEX]);
2328                                 draw_primary_ammo_info(f2i((unsigned) VULCAN_AMMO_SCALE * (unsigned) Players[Player_num].primary_ammo[VULCAN_INDEX]));
2329                                 old_ammo_count[0][VR_current_page] = Players[Player_num].primary_ammo[VULCAN_INDEX];
2330                         }
2331
2332                         if (Primary_weapon == OMEGA_INDEX)
2333                         {
2334                                 if (Newdemo_state == ND_STATE_RECORDING &&
2335                 Omega_charge != Old_Omega_charge[VR_current_page])
2336                                         newdemo_record_primary_ammo(Old_Omega_charge[VR_current_page], Omega_charge);
2337                                 draw_primary_ammo_info(Omega_charge * 100/MAX_OMEGA_CHARGE);
2338                                 Old_Omega_charge[VR_current_page] = Omega_charge;
2339                         }
2340                 }
2341         }
2342         else if (weapon_box_user[0] == WBU_STATIC)
2343                 draw_static(0);
2344
2345         if (weapon_box_user[1] == WBU_WEAPON) {
2346                 drew = draw_weapon_box(1,Secondary_weapon);
2347                 if (drew)
2348                         copy_gauge_box(&gauge_boxes[boxofs+1],&VR_render_buffer[0].cv_bitmap);
2349
2350                 if (weapon_box_states[1] == WS_SET)
2351                 {
2352                         old_bombcount[VR_current_page] = 0x7fff;        //force redraw
2353                         if (Newdemo_state == ND_STATE_RECORDING &&
2354         Players[Player_num].secondary_ammo[Secondary_weapon] != old_ammo_count[1][VR_current_page])
2355                                 newdemo_record_secondary_ammo(old_ammo_count[1][VR_current_page], Players[Player_num].secondary_ammo[Secondary_weapon]);
2356                         draw_secondary_ammo_info(Players[Player_num].secondary_ammo[Secondary_weapon]);
2357                         old_ammo_count[1][VR_current_page] = Players[Player_num].secondary_ammo[Secondary_weapon];
2358
2359                         if (Cockpit_mode == CM_STATUS_BAR)
2360                                 show_bomb_count(SB_BOMB_COUNT_X, SB_BOMB_COUNT_Y, gr_find_closest_color(0, 0, 0), 0);
2361                         else
2362                                 show_bomb_count(BOMB_COUNT_X, BOMB_COUNT_Y, gr_find_closest_color(0, 0, 0), 0);
2363                 }
2364         }
2365         else if (weapon_box_user[1] == WBU_STATIC)
2366                 draw_static(1);
2367 }
2368
2369
2370 void sb_draw_energy_bar(energy)
2371 {
2372         int erase_height, w, h, aw;
2373         char energy_str[20];
2374
2375         gr_set_current_canvas( Canv_SBEnergyGauge );
2376
2377         PAGE_IN_GAUGE( SB_GAUGE_ENERGY );
2378         gr_ubitmapm(0, 0, &GameBitmaps[GET_GAUGE_INDEX(SB_GAUGE_ENERGY)]);
2379
2380         erase_height = (100 - energy) * SB_ENERGY_GAUGE_H / 100;
2381
2382         if (erase_height > 0) {
2383                 gr_setcolor( BM_XRGB(0,0,0) );
2384                 gr_rect(0, 0, SB_ENERGY_GAUGE_W - 1, erase_height - 1);
2385         }
2386         
2387         //draw numbers
2388         sprintf(energy_str, "%d", energy);
2389         gr_get_string_size(energy_str, &w, &h, &aw );
2390         gr_set_fontcolor(gr_getcolor(25,18,6),-1 );
2391         gr_printf(((SB_ENERGY_GAUGE_W - w)/2), SB_ENERGY_GAUGE_H - GAME_FONT->ft_h - (GAME_FONT->ft_h / 4), "%d", energy);
2392
2393         gr_set_current_canvas(get_current_game_screen());
2394 }
2395
2396 void sb_draw_afterburner()
2397 {
2398         int erase_height, w, h, aw;
2399         char ab_str[3] = "AB";
2400
2401         gr_set_current_canvas( Canv_SBAfterburnerGauge );
2402         PAGE_IN_GAUGE( SB_GAUGE_AFTERBURNER );
2403         gr_ubitmapm(0, 0, &GameBitmaps[GET_GAUGE_INDEX(SB_GAUGE_AFTERBURNER)]);
2404
2405         erase_height = fixmul((f1_0 - Afterburner_charge),SB_AFTERBURNER_GAUGE_H);
2406
2407         if (erase_height > 0) {
2408                 gr_setcolor( BM_XRGB(0,0,0) );
2409                 gr_rect(0, 0, SB_AFTERBURNER_GAUGE_W - 1, erase_height - 1);
2410         }
2411
2412         //draw legend
2413         if (Players[Player_num].flags & PLAYER_FLAGS_AFTERBURNER)
2414                 gr_set_fontcolor(gr_getcolor(45,0,0),-1 );
2415         else 
2416                 gr_set_fontcolor(gr_getcolor(12,12,12),-1 );
2417
2418         gr_get_string_size(ab_str, &w, &h, &aw );
2419         gr_printf(((SB_AFTERBURNER_GAUGE_W - w)/2), SB_AFTERBURNER_GAUGE_H - GAME_FONT->ft_h - (GAME_FONT->ft_h / 4), "AB");
2420         gr_set_current_canvas(get_current_game_screen());
2421 }
2422
2423 void sb_draw_shield_num(int shield)
2424 {
2425         //draw numbers
2426
2427         gr_set_curfont( GAME_FONT );
2428         gr_set_fontcolor(gr_getcolor(14,14,23),-1 );
2429
2430         //erase old one
2431 //      PIGGY_PAGE_IN(cockpit_bitmap[Cockpit_mode + (Current_display_mode ? (Num_cockpits/2) : 0)]);
2432
2433 //      gr_setcolor(gr_gpixel(&grd_curcanv->cv_bitmap, SB_SHIELD_NUM_X - 1, SB_SHIELD_NUM_Y - 1));
2434
2435 //      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);
2436         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);
2437 }
2438
2439 void sb_draw_shield_bar(int shield)
2440 {
2441         int bm_num = shield>=100?9:(shield / 10);
2442
2443         gr_set_current_canvas(get_current_game_screen());
2444         PAGE_IN_GAUGE( GAUGE_SHIELDS+9-bm_num );
2445         gr_ubitmapm( SB_SHIELD_GAUGE_X, SB_SHIELD_GAUGE_Y, &GameBitmaps[GET_GAUGE_INDEX(GAUGE_SHIELDS+9-bm_num) ] );
2446 }
2447
2448 void sb_draw_keys()
2449 {
2450         grs_bitmap * bm;
2451         int flags = Players[Player_num].flags;
2452
2453         gr_set_current_canvas(get_current_game_screen());
2454         bm = &GameBitmaps[ GET_GAUGE_INDEX((flags&PLAYER_FLAGS_BLUE_KEY)?SB_GAUGE_BLUE_KEY:SB_GAUGE_BLUE_KEY_OFF) ];
2455         PAGE_IN_GAUGE( (flags&PLAYER_FLAGS_BLUE_KEY)?SB_GAUGE_BLUE_KEY:SB_GAUGE_BLUE_KEY_OFF );
2456         gr_ubitmapm( SB_GAUGE_KEYS_X, SB_GAUGE_BLUE_KEY_Y, bm );
2457         bm = &GameBitmaps[ GET_GAUGE_INDEX((flags&PLAYER_FLAGS_GOLD_KEY)?SB_GAUGE_GOLD_KEY:SB_GAUGE_GOLD_KEY_OFF) ];
2458         PAGE_IN_GAUGE( (flags&PLAYER_FLAGS_GOLD_KEY)?SB_GAUGE_GOLD_KEY:SB_GAUGE_GOLD_KEY_OFF );
2459         gr_ubitmapm( SB_GAUGE_KEYS_X, SB_GAUGE_GOLD_KEY_Y, bm );
2460         bm = &GameBitmaps[ GET_GAUGE_INDEX((flags&PLAYER_FLAGS_RED_KEY)?SB_GAUGE_RED_KEY:SB_GAUGE_RED_KEY_OFF) ];
2461         PAGE_IN_GAUGE( (flags&PLAYER_FLAGS_RED_KEY)?SB_GAUGE_RED_KEY:SB_GAUGE_RED_KEY_OFF );
2462         gr_ubitmapm( SB_GAUGE_KEYS_X, SB_GAUGE_RED_KEY_Y, bm  );
2463 }
2464
2465 //      Draws invulnerable ship, or maybe the flashing ship, depending on invulnerability time left.
2466 void draw_invulnerable_ship()
2467 {
2468         static fix time=0;
2469
2470         gr_set_current_canvas(get_current_game_screen());
2471
2472         if (((Players[Player_num].invulnerable_time + INVULNERABLE_TIME_MAX - GameTime) > F1_0*4) || (GameTime & 0x8000)) {
2473
2474                 if (Cockpit_mode == CM_STATUS_BAR)      {
2475                         PAGE_IN_GAUGE( GAUGE_INVULNERABLE+invulnerable_frame );
2476                         gr_ubitmapm( SB_SHIELD_GAUGE_X, SB_SHIELD_GAUGE_Y, &GameBitmaps[GET_GAUGE_INDEX(GAUGE_INVULNERABLE+invulnerable_frame) ] );
2477                 } else {
2478                         PAGE_IN_GAUGE( GAUGE_INVULNERABLE+invulnerable_frame );
2479                         gr_ubitmapm( SHIELD_GAUGE_X, SHIELD_GAUGE_Y, &GameBitmaps[GET_GAUGE_INDEX(GAUGE_INVULNERABLE+invulnerable_frame)] );
2480                 }
2481
2482                 time += FrameTime;
2483
2484                 while (time > INV_FRAME_TIME) {
2485                         time -= INV_FRAME_TIME;
2486                         if (++invulnerable_frame == N_INVULNERABLE_FRAMES)
2487                                 invulnerable_frame=0;
2488                 }
2489         } else if (Cockpit_mode == CM_STATUS_BAR)
2490                 sb_draw_shield_bar(f2ir(Players[Player_num].shields));
2491         else
2492                 draw_shield_bar(f2ir(Players[Player_num].shields));
2493 }
2494
2495 extern int Missile_gun;
2496 extern int allowed_to_fire_laser(void);
2497 extern int allowed_to_fire_missile(void);
2498
2499 rgb player_rgb[] = {
2500                                                         {15,15,23},
2501                                                         {27,0,0},
2502                                                         {0,23,0},
2503                                                         {30,11,31},
2504                                                         {31,16,0},
2505                                                         {24,17,6},
2506                                                         {14,21,12},
2507                                                         {29,29,0},
2508                                                 };
2509
2510 extern ubyte Newdemo_flying_guided;
2511 extern int max_window_w;
2512
2513 typedef struct {
2514         sbyte x, y;
2515 } xy;
2516
2517 //offsets for reticle parts: high-big  high-sml  low-big  low-sml
2518 xy cross_offsets[4] =           { {-8,-5},      {-4,-2},        {-4,-2}, {-2,-1} };
2519 xy primary_offsets[4] =         { {-30,14}, {-16,6},    {-15,6}, {-8, 2} };
2520 xy secondary_offsets[4] =       { {-24,2},      {-12,0}, {-12,1}, {-6,-2} };
2521
2522 //draw the reticle
2523 void show_reticle(int force_big_one)
2524 {
2525         int x,y;
2526         int laser_ready,missile_ready,laser_ammo,missile_ammo;
2527         int cross_bm_num,primary_bm_num,secondary_bm_num;
2528         int use_hires_reticle,small_reticle,ofs,gauge_index;
2529
2530         if (Newdemo_state==ND_STATE_PLAYBACK && Newdemo_flying_guided)
2531         {
2532                  draw_guided_crosshair();
2533                  return;
2534         }
2535
2536         x = grd_curcanv->cv_w/2;
2537         y = grd_curcanv->cv_h/2;
2538
2539         laser_ready = allowed_to_fire_laser();
2540         missile_ready = allowed_to_fire_missile();
2541
2542         laser_ammo = player_has_weapon(Primary_weapon,0);
2543         missile_ammo = player_has_weapon(Secondary_weapon,1);
2544
2545         primary_bm_num = (laser_ready && laser_ammo==HAS_ALL);
2546         secondary_bm_num = (missile_ready && missile_ammo==HAS_ALL);
2547
2548         if (primary_bm_num && Primary_weapon==LASER_INDEX && (Players[Player_num].flags & PLAYER_FLAGS_QUAD_LASERS))
2549                 primary_bm_num++;
2550
2551         if (Secondary_weapon_to_gun_num[Secondary_weapon]==7)
2552                 secondary_bm_num += 3;          //now value is 0,1 or 3,4
2553         else if (secondary_bm_num && !(Missile_gun&1))
2554                         secondary_bm_num++;
2555
2556         cross_bm_num = ((primary_bm_num > 0) || (secondary_bm_num > 0));
2557
2558         Assert(primary_bm_num <= 2);
2559         Assert(secondary_bm_num <= 4);
2560         Assert(cross_bm_num <= 1);
2561 #ifdef OGL
2562         if (gl_reticle==2 || (gl_reticle && grd_curcanv->cv_bitmap.bm_w > 320))
2563         {
2564                 ogl_draw_reticle(cross_bm_num,primary_bm_num,secondary_bm_num);
2565         }
2566         else
2567         {
2568 #endif
2569
2570
2571                 use_hires_reticle = (FontHires != 0);
2572
2573         small_reticle = !(grd_curcanv->cv_bitmap.bm_w*3 > max_window_w*2 || force_big_one);
2574         ofs = (use_hires_reticle?0:2) + small_reticle;
2575
2576         gauge_index = (small_reticle?SML_RETICLE_CROSS:RETICLE_CROSS) + cross_bm_num;
2577         PAGE_IN_GAUGE( gauge_index );
2578         gr_ubitmapm(x+cross_offsets[ofs].x,y+cross_offsets[ofs].y,&GameBitmaps[GET_GAUGE_INDEX(gauge_index)] );
2579
2580         gauge_index = (small_reticle?SML_RETICLE_PRIMARY:RETICLE_PRIMARY) + primary_bm_num;
2581         PAGE_IN_GAUGE( gauge_index );
2582         gr_ubitmapm(x+primary_offsets[ofs].x,y+primary_offsets[ofs].y,&GameBitmaps[GET_GAUGE_INDEX(gauge_index)] );
2583
2584         gauge_index = (small_reticle?SML_RETICLE_SECONDARY:RETICLE_SECONDARY) + secondary_bm_num;
2585         PAGE_IN_GAUGE( gauge_index );
2586         gr_ubitmapm(x+secondary_offsets[ofs].x,y+secondary_offsets[ofs].y,&GameBitmaps[GET_GAUGE_INDEX(gauge_index)] );
2587
2588 #ifdef OGL
2589         }
2590 #endif
2591 }
2592
2593 #ifdef NETWORK
2594 void hud_show_kill_list()
2595 {
2596         int n_players,player_list[MAX_NUM_NET_PLAYERS];
2597         int n_left,i,x0,x1,y,save_y,fth;
2598
2599 // ugly hack since placement of netgame players and kills is based off of
2600 // menuhires (which is always 1 for mac).  This throws off placement of
2601 // players in pixel double mode.
2602
2603         if (Show_kill_list_timer > 0)
2604         {
2605                 Show_kill_list_timer -= FrameTime;
2606                 if (Show_kill_list_timer < 0)
2607                         Show_kill_list = 0;
2608         }
2609         
2610         gr_set_curfont( GAME_FONT );
2611
2612         n_players = multi_get_kill_list(player_list);
2613
2614         if (Show_kill_list == 3)
2615                 n_players = 2;
2616
2617         if (n_players <= 4)
2618                 n_left = n_players;
2619         else
2620                 n_left = (n_players+1)/2;
2621
2622         //If font size changes, this code might not work right anymore 
2623         //Assert(GAME_FONT->ft_h==5 && GAME_FONT->ft_w==7);
2624
2625         fth = GAME_FONT->ft_h;
2626
2627         x0 = LHX(1); x1 = LHX(43);
2628
2629         if (Game_mode & GM_MULTI_COOP)
2630                 x1 = LHX(31);
2631
2632         save_y = y = grd_curcanv->cv_h - n_left*(fth+1);
2633
2634         if (Cockpit_mode == CM_FULL_COCKPIT) {
2635                 save_y = y -= LHX(6);
2636                 if (Game_mode & GM_MULTI_COOP)
2637                         x1 = LHX(33);
2638                 else
2639                         x1 = LHX(43);
2640         }
2641
2642         for (i=0;i<n_players;i++) {
2643                 int player_num;
2644                 char name[9];
2645                 int sw,sh,aw;
2646
2647                 if (i>=n_left) {
2648                         if (Cockpit_mode == CM_FULL_COCKPIT)
2649                                 x0 = grd_curcanv->cv_w - LHX(53);
2650                         else
2651                                 x0 = grd_curcanv->cv_w - LHX(60);
2652                         if (Game_mode & GM_MULTI_COOP)
2653                                 x1 = grd_curcanv->cv_w - LHX(27);
2654                         else
2655                                 x1 = grd_curcanv->cv_w - LHX(15);  // Right edge of name, change this for width problems
2656                         if (i==n_left)
2657                                 y = save_y;
2658
2659         if (Netgame.KillGoal || Netgame.PlayTimeAllowed)
2660            {
2661              x1-=LHX(18);
2662             // x0-=LHX(18);
2663            }
2664                 }
2665      else  if (Netgame.KillGoal || Netgame.PlayTimeAllowed)
2666            {
2667                                  x1 = LHX(43);
2668              x1-=LHX(18);
2669             // x0-=LHX(18);
2670            }
2671
2672         
2673                 if (Show_kill_list == 3)
2674                         player_num = i;
2675                 else
2676                         player_num = player_list[i];
2677
2678                 if (Show_kill_list == 1 || Show_kill_list==2)
2679                 {
2680                         int color;
2681
2682                         if (Players[player_num].connected != 1)
2683                                 gr_set_fontcolor(gr_getcolor(12, 12, 12), -1);
2684                         else if (Game_mode & GM_TEAM) {
2685                                 color = get_team(player_num);
2686                                 gr_set_fontcolor(gr_getcolor(player_rgb[color].r,player_rgb[color].g,player_rgb[color].b),-1 );
2687                         }
2688                         else {
2689                                 color = player_num;
2690                                 gr_set_fontcolor(gr_getcolor(player_rgb[color].r,player_rgb[color].g,player_rgb[color].b),-1 );
2691                         }
2692                 }       
2693
2694                 else 
2695                 {
2696                         gr_set_fontcolor(gr_getcolor(player_rgb[player_num].r,player_rgb[player_num].g,player_rgb[player_num].b),-1 );
2697                 }
2698
2699                 if (Show_kill_list == 3)
2700                         strcpy(name, Netgame.team_name[i]);
2701                 else
2702                         strcpy(name,Players[player_num].callsign);      // Note link to above if!!
2703                 gr_get_string_size(name,&sw,&sh,&aw);
2704                 while (sw > (x1-x0-LHX(2))) {
2705                         name[strlen(name)-1]=0;
2706                         gr_get_string_size(name,&sw,&sh,&aw);
2707                 }
2708                 gr_printf(x0,y,"%s",name);
2709
2710                 if (Show_kill_list==2)
2711                  {
2712                   if (Players[player_num].net_killed_total+Players[player_num].net_kills_total==0)
2713                         gr_printf (x1,y,"NA");
2714                   else
2715                    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));           
2716                  }
2717                 else if (Show_kill_list == 3)   
2718                         gr_printf(x1,y,"%3d",team_kills[i]);
2719                 else if (Game_mode & GM_MULTI_COOP)
2720                         gr_printf(x1,y,"%-6d",Players[player_num].score);
2721       else if (Netgame.PlayTimeAllowed || Netgame.KillGoal)
2722          gr_printf(x1,y,"%3d(%d)",Players[player_num].net_kills_total,Players[player_num].KillGoalCount);
2723       else
2724                         gr_printf(x1,y,"%3d",Players[player_num].net_kills_total);
2725                         
2726                 y += fth+1;
2727
2728         }
2729
2730 #ifdef MACINTOSH
2731         MenuHires = 1;
2732 #endif
2733 }
2734 #endif
2735
2736 #ifndef RELEASE
2737 extern int Saving_movie_frames;
2738 #else
2739 #define Saving_movie_frames 0
2740 #endif
2741
2742 //returns true if viewer can see object
2743 int see_object(int objnum)
2744 {
2745         fvi_query fq;
2746         int hit_type;
2747         fvi_info hit_data;
2748
2749         //see if we can see this player
2750
2751         fq.p0                                   = &Viewer->pos;
2752         fq.p1                                   = &Objects[objnum].pos;
2753         fq.rad                                  = 0;
2754         fq.thisobjnum                   = Viewer - Objects;
2755         fq.flags                                = FQ_TRANSWALL | FQ_CHECK_OBJS;
2756         fq.startseg                             = Viewer->segnum;
2757         fq.ignore_obj_list      = NULL;
2758
2759         hit_type = find_vector_intersection(&fq, &hit_data);
2760
2761         return (hit_type == HIT_OBJECT && hit_data.hit_object == objnum);
2762 }
2763
2764 #ifdef NETWORK
2765 //show names of teammates & players carrying flags
2766 void show_HUD_names()
2767 {
2768         int show_team_names,show_all_names,show_flags,player_team;
2769         int p;
2770
2771         show_all_names = ((Newdemo_state == ND_STATE_PLAYBACK) || (Netgame.ShowAllNames && Show_reticle_name));
2772         show_team_names = (((Game_mode & GM_MULTI_COOP) || (Game_mode & GM_TEAM)) && Show_reticle_name);
2773         show_flags = (Game_mode & GM_CAPTURE) | (Game_mode & GM_HOARD);
2774
2775         if (! (show_all_names || show_team_names || show_flags))
2776                 return;
2777
2778         player_team = get_team(Player_num);
2779
2780         for (p=0;p<N_players;p++) {     //check all players
2781                 int objnum;
2782                 int show_name,has_flag;
2783
2784                 show_name = ((show_all_names && !(Players[p].flags & PLAYER_FLAGS_CLOAKED)) || (show_team_names && get_team(p)==player_team));
2785                 has_flag = (Players[p].connected && Players[p].flags & PLAYER_FLAGS_FLAG);
2786
2787                 if (Newdemo_state == ND_STATE_PLAYBACK) {
2788                         //if this is a demo, the objnum in the player struct is wrong,
2789                         //so we search the object list for the objnum
2790
2791                         for (objnum=0;objnum<=Highest_object_index;objnum++)
2792                                 if (Objects[objnum].type==OBJ_PLAYER && Objects[objnum].id == p)
2793                                         break;
2794                         if (objnum > Highest_object_index)              //not in list, thus not visible
2795                                 show_name = has_flag = 0;                               //..so don't show name
2796                 }
2797                 else
2798                         objnum = Players[p].objnum;
2799
2800                 if ((show_name || has_flag) && see_object(objnum)) {
2801                         g3s_point player_point;
2802
2803                         g3_rotate_point(&player_point,&Objects[objnum].pos);
2804
2805                         if (player_point.p3_codes == 0) {       //on screen
2806
2807                                 g3_project_point(&player_point);
2808
2809                                 if (! (player_point.p3_flags & PF_OVERFLOW)) {
2810                                         fix x,y;
2811                         
2812                                         x = player_point.p3_sx;
2813                                         y = player_point.p3_sy;
2814                         
2815                                         if (show_name) {                                // Draw callsign on HUD
2816                                                 char s[CALLSIGN_LEN+1];
2817                                                 int w, h, aw;
2818                                                 int x1, y1;
2819                                                 int color_num;
2820                         
2821                                                 color_num = (Game_mode & GM_TEAM)?get_team(p):p;
2822
2823                                                 sprintf(s, "%s", Players[p].callsign);
2824                                                 gr_get_string_size(s, &w, &h, &aw);
2825                                                 gr_set_fontcolor(gr_getcolor(player_rgb[color_num].r,player_rgb[color_num].g,player_rgb[color_num].b),-1 );
2826                                                 x1 = f2i(x)-w/2;
2827                                                 y1 = f2i(y)-h/2;
2828                                                 gr_string (x1, y1, s);
2829                                         }
2830                 
2831                                         if (has_flag) {                         // Draw box on HUD
2832                                                 fix dx,dy,w,h;
2833                         
2834                                                 dy = -fixmuldiv(fixmul(Objects[objnum].size,Matrix_scale.y),i2f(grd_curcanv->cv_h)/2,player_point.p3_z);
2835                                                 dx = fixmul(dy,grd_curscreen->sc_aspect);
2836         
2837                                                 w = dx/4;
2838                                                 h = dy/4;
2839         
2840                                                 if (Game_mode & GM_CAPTURE)
2841                                                         gr_setcolor((get_team(p) == TEAM_BLUE)?BM_XRGB(31,0,0):BM_XRGB(0,0,31));
2842                                                 else if (Game_mode & GM_HOARD)
2843                                                 {
2844                                                         if (Game_mode & GM_TEAM)
2845                                                                 gr_setcolor((get_team(p) == TEAM_RED)?BM_XRGB(31,0,0):BM_XRGB(0,0,31));
2846                                                         else
2847                                                                 gr_setcolor(BM_XRGB(0,31,0));
2848                                                 }
2849
2850                                                 gr_line(x+dx-w,y-dy,x+dx,y-dy);
2851                                                 gr_line(x+dx,y-dy,x+dx,y-dy+h);
2852         
2853                                                 gr_line(x-dx,y-dy,x-dx+w,y-dy);
2854                                                 gr_line(x-dx,y-dy,x-dx,y-dy+h);
2855         
2856                                                 gr_line(x+dx-w,y+dy,x+dx,y+dy);
2857                                                 gr_line(x+dx,y+dy,x+dx,y+dy-h);
2858         
2859                                                 gr_line(x-dx,y+dy,x-dx+w,y+dy);
2860                                                 gr_line(x-dx,y+dy,x-dx,y+dy-h);
2861                                         }
2862                                 }
2863                         }
2864                 }
2865         }
2866 }
2867 #endif
2868
2869
2870 extern int last_drawn_cockpit[2];
2871
2872 //draw all the things on the HUD
2873 void draw_hud()
2874 {
2875
2876 #if 0 //def OGL
2877         if (Cockpit_mode==CM_STATUS_BAR){
2878                 //ogl needs to redraw every frame, at least currently.
2879                 //              init_cockpit();
2880                         last_drawn_cockpit[0]=-1;
2881                         last_drawn_cockpit[1]=-1;
2882                                   init_gauges();
2883                 
2884                                //              vr_reset_display();
2885         }
2886 #endif
2887                                           
2888
2889         Line_spacing = GAME_FONT->ft_h + GAME_FONT->ft_h/4;
2890
2891         //      Show score so long as not in rearview
2892         if ( !Rear_view && Cockpit_mode!=CM_REAR_VIEW && Cockpit_mode!=CM_STATUS_BAR && !Saving_movie_frames) {
2893                 hud_show_score();
2894                 if (score_time)
2895                         hud_show_score_added();
2896         }
2897
2898         if ( !Rear_view && Cockpit_mode!=CM_REAR_VIEW && !Saving_movie_frames) 
2899          hud_show_timer_count();
2900
2901         //      Show other stuff if not in rearview or letterbox.
2902         if (!Rear_view && Cockpit_mode!=CM_REAR_VIEW) { // && Cockpit_mode!=CM_LETTERBOX) {
2903                 if (Cockpit_mode==CM_STATUS_BAR || Cockpit_mode==CM_FULL_SCREEN)
2904                         hud_show_homing_warning();
2905
2906                 if (Cockpit_mode==CM_FULL_SCREEN) {
2907                         hud_show_energy();
2908                         hud_show_shield();
2909                         hud_show_afterburner();
2910                         hud_show_weapons();
2911                         if (!Saving_movie_frames)
2912                                 hud_show_keys();
2913                         hud_show_cloak_invuln();
2914
2915                         if ( ( Newdemo_state==ND_STATE_RECORDING ) && ( Players[Player_num].flags != old_flags[VR_current_page] )) {
2916                                 newdemo_record_player_flags(old_flags[VR_current_page], Players[Player_num].flags);
2917                                 old_flags[VR_current_page] = Players[Player_num].flags;
2918                         }
2919                 }
2920
2921                 #ifdef NETWORK
2922                 #ifndef RELEASE
2923                 if (!(Game_mode&GM_MULTI && Show_kill_list) && !Saving_movie_frames)
2924                         show_time();
2925                 #endif
2926                 #endif
2927                 if (Reticle_on && Cockpit_mode != CM_LETTERBOX && (!Use_player_head_angles))
2928                         show_reticle(0);
2929
2930 #ifdef NETWORK
2931                 show_HUD_names();
2932
2933                 if (Cockpit_mode != CM_LETTERBOX && Cockpit_mode != CM_REAR_VIEW)
2934                         hud_show_flag();
2935
2936                 if (Cockpit_mode != CM_LETTERBOX && Cockpit_mode != CM_REAR_VIEW)
2937                         hud_show_orbs();
2938
2939 #endif
2940                 if (!Saving_movie_frames)
2941                         HUD_render_message_frame();
2942
2943                 if (Cockpit_mode!=CM_STATUS_BAR && !Saving_movie_frames)
2944                         hud_show_lives();
2945
2946                 #ifdef NETWORK
2947                 if (Game_mode&GM_MULTI && Show_kill_list)
2948                         hud_show_kill_list();
2949                 #endif
2950         }
2951
2952         if (Rear_view && Cockpit_mode!=CM_REAR_VIEW) {
2953                 HUD_render_message_frame();
2954                 gr_set_curfont( GAME_FONT );
2955                 gr_set_fontcolor(gr_getcolor(0,31,0),-1 );
2956                 if (Newdemo_state == ND_STATE_PLAYBACK)
2957                         gr_printf(0x8000,grd_curcanv->cv_h-14,TXT_REAR_VIEW);
2958                 else
2959                         gr_printf(0x8000,grd_curcanv->cv_h-10,TXT_REAR_VIEW);
2960         }
2961 }
2962
2963 extern short *BackBuffer;
2964
2965 //print out some player statistics
2966 void render_gauges()
2967 {
2968         static int old_display_mode = -2;
2969         int energy = f2ir(Players[Player_num].energy);
2970         int shields = f2ir(Players[Player_num].shields);
2971         int cloak = ((Players[Player_num].flags&PLAYER_FLAGS_CLOAKED) != 0);
2972  
2973         Assert(Cockpit_mode==CM_FULL_COCKPIT || Cockpit_mode==CM_STATUS_BAR);
2974
2975 // check to see if our display mode has changed since last render time --
2976 // if so, then we need to make new gauge canvases.
2977 // Also make the first gauge canvases here, in the game,
2978 // because they are [now] sub-canvases.
2979
2980   
2981         if (old_display_mode != Current_display_mode)
2982         {
2983                 close_gauge_canvases();
2984                 init_gauge_canvases();
2985                 old_display_mode = Current_display_mode;
2986         }
2987
2988         if (shields < 0 ) shields = 0;
2989
2990         gr_set_current_canvas(get_current_game_screen());
2991         gr_set_curfont( GAME_FONT );
2992
2993         if (Newdemo_state == ND_STATE_RECORDING)
2994                 if (Players[Player_num].homing_object_dist >= 0)
2995                         newdemo_record_homing_distance(Players[Player_num].homing_object_dist);
2996
2997         if (Cockpit_mode == CM_FULL_COCKPIT)
2998                 draw_player_ship(cloak, old_cloak[VR_current_page], SHIP_GAUGE_X, SHIP_GAUGE_Y);
2999         else
3000                 draw_player_ship(cloak, old_cloak[VR_current_page], SB_SHIP_GAUGE_X, SB_SHIP_GAUGE_Y);
3001
3002         old_cloak[VR_current_page] = cloak;
3003
3004         if (Cockpit_mode == CM_FULL_COCKPIT) {
3005                 if (Newdemo_state == ND_STATE_RECORDING && (energy != old_energy[VR_current_page]))
3006                 {
3007                         newdemo_record_player_energy(old_energy[VR_current_page], energy);
3008                         old_energy[VR_current_page] = energy;
3009                 }
3010                 draw_energy_bar(energy);
3011                 draw_numerical_display(shields, energy);
3012
3013                 if (Newdemo_state == ND_STATE_RECORDING && (Afterburner_charge != old_afterburner[VR_current_page]))
3014                 {
3015                         newdemo_record_player_afterburner(old_afterburner[VR_current_page], Afterburner_charge);
3016                         old_afterburner[VR_current_page] = Afterburner_charge;
3017                 }
3018                 draw_afterburner_bar(Afterburner_charge);
3019
3020                 if (Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE) {
3021                         draw_invulnerable_ship();
3022                         old_shields[VR_current_page] = shields ^ 1;
3023                 } else {                // Draw the shield gauge
3024                         if (Newdemo_state == ND_STATE_RECORDING && (shields != old_shields[VR_current_page]))
3025                         {
3026                                 newdemo_record_player_shields(old_shields[VR_current_page], shields);
3027                                 old_shields[VR_current_page] = shields;
3028                         }
3029                         draw_shield_bar(shields);
3030                 }
3031                 draw_numerical_display(shields, energy);
3032         
3033                 if (Newdemo_state == ND_STATE_RECORDING && (Players[Player_num].flags != old_flags[VR_current_page]))
3034                 {
3035                         newdemo_record_player_flags(old_flags[VR_current_page], Players[Player_num].flags);
3036                         old_flags[VR_current_page] = Players[Player_num].flags;
3037                 }
3038                 draw_keys();
3039
3040                 show_homing_warning();
3041
3042         } else if (Cockpit_mode == CM_STATUS_BAR) {
3043
3044                 if (Newdemo_state == ND_STATE_RECORDING && (energy != old_energy[VR_current_page]))
3045                 {
3046                         newdemo_record_player_energy(old_energy[VR_current_page], energy);
3047                         old_energy[VR_current_page] = energy;
3048                 }
3049                 sb_draw_energy_bar(energy);
3050
3051                 if (Newdemo_state == ND_STATE_RECORDING && (Afterburner_charge != old_afterburner[VR_current_page]))
3052                 {
3053                         newdemo_record_player_afterburner(old_afterburner[VR_current_page], Afterburner_charge);
3054                         old_afterburner[VR_current_page] = Afterburner_charge;
3055                 }
3056                 sb_draw_afterburner();
3057
3058                 if (Players[Player_num].flags & PLAYER_FLAGS_INVULNERABLE)
3059                 {
3060                         draw_invulnerable_ship();
3061                         old_shields[VR_current_page] = shields ^ 1;
3062                 } 
3063                 else
3064                 {               // Draw the shield gauge
3065                         if (Newdemo_state == ND_STATE_RECORDING && (shields != old_shields[VR_current_page]))
3066                         {
3067                                 newdemo_record_player_shields(old_shields[VR_current_page], shields);
3068                                 old_shields[VR_current_page] = shields;
3069                         }
3070                         sb_draw_shield_bar(shields);
3071                 }
3072                 sb_draw_shield_num(shields);
3073
3074                 if (Newdemo_state == ND_STATE_RECORDING && (Players[Player_num].flags != old_flags[VR_current_page]))
3075                 {
3076                         newdemo_record_player_flags(old_flags[VR_current_page], Players[Player_num].flags);
3077                         old_flags[VR_current_page] = Players[Player_num].flags;
3078                 }
3079                 sb_draw_keys();
3080         
3081
3082                 // May want to record this in a demo...
3083                 if ((Game_mode & GM_MULTI) && !(Game_mode & GM_MULTI_COOP))
3084                 {
3085                         sb_show_lives();
3086                         old_lives[VR_current_page] = Players[Player_num].net_killed_total;
3087                 }
3088                 else
3089                 {
3090                         sb_show_lives();
3091                         old_lives[VR_current_page] = Players[Player_num].lives;
3092                 }
3093
3094                 if ((Game_mode&GM_MULTI) && !(Game_mode & GM_MULTI_COOP))
3095                 {
3096                         sb_show_score();
3097                         old_score[VR_current_page] = Players[Player_num].net_kills_total;
3098                 }
3099                 else
3100                 {
3101                         sb_show_score();
3102                         old_score[VR_current_page] = Players[Player_num].score;
3103
3104                         //if (score_time)
3105                                 sb_show_score_added();
3106                 }
3107         }
3108
3109
3110         draw_weapon_boxes();
3111
3112 }
3113
3114 //      ---------------------------------------------------------------------------------------------------------
3115 //      Call when picked up a laser powerup.
3116 //      If laser is active, set old_weapon[0] to -1 to force redraw.
3117 void update_laser_weapon_info(void)
3118 {
3119         if (old_weapon[0][VR_current_page] == 0)
3120                 if (! (Players[Player_num].laser_level > MAX_LASER_LEVEL && old_laser_level[VR_current_page] <= MAX_LASER_LEVEL))
3121                         old_weapon[0][VR_current_page] = -1;
3122 }
3123
3124 extern int Game_window_y;
3125 void fill_background(void);
3126
3127 int SW_drawn[2], SW_x[2], SW_y[2], SW_w[2], SW_h[2];
3128
3129 //draws a 3d view into one of the cockpit windows.  win is 0 for left,
3130 //1 for right.  viewer is object.  NULL object means give up window
3131 //user is one of the WBU_ constants.  If rear_view_flag is set, show a
3132 //rear view.  If label is non-NULL, print the label at the top of the
3133 //window.
3134 void do_cockpit_window_view(int win,object *viewer,int rear_view_flag,int user,char *label)
3135 {
3136         grs_canvas window_canv;
3137         static grs_canvas overlap_canv;
3138         object *viewer_save = Viewer;
3139         static int overlap_dirty[2]={0,0};
3140         int boxnum;
3141         static int window_x,window_y;
3142         gauge_box *box;
3143         int rear_view_save = Rear_view;
3144         int w,h,dx;
3145
3146         box = NULL;
3147
3148         if (viewer == NULL) {                                                           //this user is done
3149
3150                 Assert(user == WBU_WEAPON || user == WBU_STATIC);
3151
3152                 if (user == WBU_STATIC && weapon_box_user[win] != WBU_STATIC)
3153                         static_time[win] = 0;
3154
3155                 if (weapon_box_user[win] == WBU_WEAPON || weapon_box_user[win] == WBU_STATIC)
3156                         return;         //already set
3157
3158                 weapon_box_user[win] = user;
3159
3160                 if (overlap_dirty[win]) {
3161                         gr_set_current_canvas(&VR_screen_pages[VR_current_page]);
3162                         fill_background();
3163                         overlap_dirty[win] = 0;
3164                 }
3165
3166                 return;
3167         }
3168
3169         update_rendered_data(win+1, viewer, rear_view_flag, user);
3170
3171         weapon_box_user[win] = user;                                            //say who's using window
3172                 
3173         Viewer = viewer;
3174         Rear_view = rear_view_flag;
3175
3176         if (Cockpit_mode == CM_FULL_SCREEN)
3177         {
3178
3179                 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
3180
3181                 h = i2f(w) / grd_curscreen->sc_aspect;
3182
3183                 dx = (win==0)?-(w+(w/10)):(w/10);
3184
3185                 window_x = VR_render_buffer[0].cv_bitmap.bm_w/2+dx;
3186                 window_y = VR_render_buffer[0].cv_bitmap.bm_h-h-(h/10);
3187
3188                 //copy these vars so stereo code can get at them
3189                 SW_drawn[win]=1; SW_x[win] = window_x; SW_y[win] = window_y; SW_w[win] = w; SW_h[win] = h; 
3190
3191                 gr_init_sub_canvas(&window_canv,&VR_render_buffer[0],window_x,window_y,w,h);
3192         }
3193         else {
3194                 if (Cockpit_mode == CM_FULL_COCKPIT)
3195                         boxnum = (COCKPIT_PRIMARY_BOX)+win;
3196                 else if (Cockpit_mode == CM_STATUS_BAR)
3197                         boxnum = (SB_PRIMARY_BOX)+win;
3198                 else
3199                         goto abort;
3200
3201                 box = &gauge_boxes[boxnum];
3202
3203                 gr_init_sub_canvas(&window_canv,&VR_render_buffer[0],box->left,box->top,box->right-box->left+1,box->bot-box->top+1);
3204         }
3205
3206         gr_set_current_canvas(&window_canv);
3207         
3208         render_frame(0, win+1);
3209                 
3210         //      HACK! If guided missile, wake up robots as necessary.
3211         if (viewer->type == OBJ_WEAPON) {
3212                 // -- Used to require to be GUIDED -- if (viewer->id == GUIDEDMISS_ID)
3213                 wake_up_rendered_objects(viewer, win+1);
3214         }
3215
3216         if (label) {
3217                 gr_set_curfont( GAME_FONT );
3218                 if (Color_0_31_0 == -1)
3219                         Color_0_31_0 = gr_getcolor(0,31,0);
3220                 gr_set_fontcolor(Color_0_31_0, -1);
3221                 gr_printf(0x8000,2,label);
3222         }
3223
3224         if (user == WBU_GUIDED)
3225                 draw_guided_crosshair();
3226
3227         if (Cockpit_mode == CM_FULL_SCREEN) {
3228                 int small_window_bottom,big_window_bottom,extra_part_h;
3229                 
3230                 {
3231                         gr_setcolor(BM_XRGB(0,0,32));
3232                         gr_ubox(0,0,grd_curcanv->cv_bitmap.bm_w-1,grd_curcanv->cv_bitmap.bm_h-1);
3233                 }
3234
3235                 //if the window only partially overlaps the big 3d window, copy
3236                 //the extra part to the visible screen
3237
3238                 big_window_bottom = Game_window_y + Game_window_h - 1;
3239
3240                 if (window_y > big_window_bottom) {
3241
3242                         //the small window is completely outside the big 3d window, so
3243                         //copy it to the visible screen
3244
3245                         if (VR_screen_flags & VRF_USE_PAGING)
3246                                 gr_set_current_canvas(&VR_screen_pages[!VR_current_page]);
3247                         else
3248                                 gr_set_current_canvas(get_current_game_screen());
3249
3250                         gr_bitmap(window_x,window_y,&window_canv.cv_bitmap);
3251
3252                         overlap_dirty[win] = 1;
3253                 }
3254                 else {
3255
3256                         small_window_bottom = window_y + window_canv.cv_bitmap.bm_h - 1;
3257                         
3258                         extra_part_h = small_window_bottom - big_window_bottom;
3259
3260                         if (extra_part_h > 0) {
3261                         
3262                                 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);
3263
3264                                 if (VR_screen_flags & VRF_USE_PAGING)
3265                                         gr_set_current_canvas(&VR_screen_pages[!VR_current_page]);
3266                                 else
3267                                         gr_set_current_canvas(get_current_game_screen());
3268
3269                                 gr_bitmap(window_x,big_window_bottom+1,&overlap_canv.cv_bitmap);
3270                                 
3271                                 overlap_dirty[win] = 1;
3272                         }
3273                 }
3274         }
3275         else {
3276         
3277                 gr_set_current_canvas(get_current_game_screen());
3278                 copy_gauge_box(box,&VR_render_buffer[0].cv_bitmap);
3279         }
3280
3281         //force redraw when done
3282         old_weapon[win][VR_current_page] = old_ammo_count[win][VR_current_page] = -1;
3283
3284 abort:;
3285
3286         Viewer = viewer_save;
3287
3288         Rear_view = rear_view_save;
3289 }
3290
3291 #ifdef MACINTOSH
3292         void calculate_sub_view_window_bounds(int inSubWindowNum, TQARect* outBoundsRect)
3293         {
3294                 int             boxNumber               = 0;
3295                 gauge_box*      currentGaugeBox = NULL;
3296                 int w   = 0;
3297                 int h   = 0;
3298                 int dx  = 0;
3299                 int window_x = 0;
3300                 int window_y = 0;
3301
3302                 Assert(outBoundsRect);
3303                 Assert((inSubWindowNum == 0) || (inSubWindowNum == 1));
3304                 
3305                 switch (Cockpit_mode)
3306                 {
3307                         case CM_FULL_SCREEN:
3308                                 // note: this calculation is taken from do_cockpit_window_view for the full
3309                                 // screen mode case
3310                 
3311                                 w = (VR_render_buffer[0].cv_bitmap.bm_w) / 6;
3312                                 h = (i2f(w)) / (grd_curscreen->sc_aspect);
3313                 
3314                                 dx = (inSubWindowNum==0)?-(w+(w/10)):(w/10);
3315                 
3316                                 window_x = ((VR_render_buffer[0].cv_bitmap.bm_w) / 2) + dx;
3317                                 window_y = (VR_render_buffer[0].cv_bitmap.bm_h) - h - (h/10);
3318                                 
3319                                 outBoundsRect->top              = window_x;
3320                                 outBoundsRect->left             = window_y;
3321                                 outBoundsRect->bottom   = window_x + w;
3322                                 outBoundsRect->right    = window_y + h;
3323                                 break;
3324         
3325                         case CM_FULL_COCKPIT:
3326                         case CM_STATUS_BAR:
3327                                 if (inSubWindowNum == 0)
3328                                 {
3329                                         boxNumber = SB_PRIMARY_BOX;
3330                                 }
3331                                 else
3332                                 {
3333                                         boxNumber = SB_SECONDARY_BOX;
3334                                 }
3335                                 
3336                                 //boxNumber = (Current_display_mode * 4) + (Cockpit_mode * 2) + inSubWindowNum;
3337                                 currentGaugeBox = &gauge_boxes[boxNumber];
3338                                 Assert(currentGaugeBox);
3339                                 
3340                                 outBoundsRect->top              = currentGaugeBox->top;
3341                                 outBoundsRect->left             = currentGaugeBox->left;
3342                                 outBoundsRect->bottom   = currentGaugeBox->bot + 1;
3343                                 outBoundsRect->right    = currentGaugeBox->right + 1;
3344                                 
3345                                 break;
3346         
3347                         default:
3348                                 Int3();
3349                                 return;
3350                 }
3351         }
3352
3353 #endif
3354
3355