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