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