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