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