]> icculus.org git repositories - taylor/freespace2.git/blob - src/hud/hudreticle.cpp
initial loading/progress screen for emscripten
[taylor/freespace2.git] / src / hud / hudreticle.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell 
5  * or otherwise commercially exploit the source or things you created based on
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/Hud/HUDreticle.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * C module to draw and manage the recticle
16  *
17  * $Log$
18  * Revision 1.6  2003/05/25 02:30:42  taylor
19  * Freespace 1 support
20  *
21  * Revision 1.5  2003/05/22 15:58:44  taylor
22  * fix missed German build option for auto-lang
23  *
24  * Revision 1.4  2002/06/17 06:33:09  relnev
25  * ryan's struct patch for gcc 2.95
26  *
27  * Revision 1.3  2002/06/09 04:41:21  relnev
28  * added copyright header
29  *
30  * Revision 1.2  2002/05/07 03:16:45  theoddone33
31  * The Great Newline Fix
32  *
33  * Revision 1.1.1.1  2002/05/03 03:28:09  root
34  * Initial import.
35  *
36  * 
37  * 14    10/27/99 10:04p Jefff
38  * changed german match speed indicator
39  * 
40  * 13    10/14/99 2:50p Jefff
41  * localization fixes
42  * 
43  * 12    8/28/99 4:54p Dave
44  * Fixed directives display for multiplayer clients for wings with
45  * multiple waves. Fixed hud threat indicator rendering color.
46  * 
47  * 11    8/09/99 3:14p Dave
48  * Make "launch" warning gauge draw in code.
49  * 
50  * 10    6/10/99 3:43p Dave
51  * Do a better job of syncing text colors to HUD gauges.
52  * 
53  * 9     6/08/99 10:48a Jasenw
54  * new coords for new HUD stuff
55  * 
56  * 8     6/03/99 2:31p Jasenw
57  * changed coords and removed weapon indicators.
58  * 
59  * 7     1/07/99 2:21p Jasen
60  * fixed toparc
61  * 
62  * 6     1/07/99 9:07a Jasen
63  * HUD coords
64  * 
65  * 5     12/28/98 3:17p Dave
66  * Support for multiple hud bitmap filenames for hi-res mode.
67  * 
68  * 4     12/21/98 5:02p Dave
69  * Modified all hud elements to be multi-resolution friendly.
70  * 
71  * 3     11/05/98 4:18p Dave
72  * First run nebula support. Beefed up localization a bit. Removed all
73  * conditional compiles for foreign versions. Modified mission file
74  * format.
75  * 
76  * 2     10/07/98 10:53a Dave
77  * Initial checkin.
78  * 
79  * 1     10/07/98 10:49a Dave
80  * 
81  * 69    8/28/98 3:28p Dave
82  * EMP effect done. AI effects may need some tweaking as required.
83  * 
84  * 68    8/25/98 1:48p Dave
85  * First rev of EMP effect. Player side stuff basically done. Next comes
86  * AI code.
87  * 
88  * 67    6/12/98 4:52p Hoffoss
89  * Added support for special characters in in forgeign languages.
90  * 
91  * 66    6/09/98 5:17p Lawrance
92  * French/German localization
93  * 
94  * 65    6/09/98 10:31a Hoffoss
95  * Created index numbers for all xstr() references.  Any new xstr() stuff
96  * added from here on out should be added to the end if the list.  The
97  * current list count can be found in FreeSpace.cpp (search for
98  * XSTR_SIZE).
99  * 
100  * 64    5/21/98 7:18p Lawrance
101  * Don't flash 'launch' for attempted lock
102  * 
103  * 63    5/13/98 1:53p Lawrance
104  * If no secondary banks on a ship, show correct reticle gauge
105  * 
106  * 62    5/06/98 8:05p Dave
107  * Made standalone reset properly under weird conditions. Tweak
108  * optionsmulti screen. Upped MAX_WEAPONS to 350. Put in new launch
109  * countdown anim. Minro ui fixes/tweaks.
110  * 
111  * 61    5/05/98 5:51p Lawrance
112  * Draw HUD center crosshair with bright alpha index
113  * 
114  * 60    5/04/98 6:12p Lawrance
115  * fix progblems with weapon gauges in situation when weapons are on ship
116  * 
117  * 59    5/01/98 4:22p Lawrance
118  * Use ship->weapons instead of sip when displaying weapon linking gauge
119  * 
120  * 58    4/13/98 11:19a Lawrance
121  * fix launch threat indicator
122  * 
123  * 57    4/08/98 10:34p Allender
124  * make threat indicators work in multiplayer.  Fix socket problem (once
125  * and for all???)
126  * 
127  * 56    3/26/98 5:26p John
128  * added new paging code. nonfunctional.
129  * 
130  * 55    2/23/98 6:49p Lawrance
131  * Use gr_aabitmap_ex() instead of clipping regions
132  * 
133  * 54    2/22/98 4:17p John
134  * More string externalization classification... 190 left to go!
135  * 
136  * 53    2/22/98 12:19p John
137  * Externalized some strings
138  * 
139  * 52    2/12/98 4:58p Lawrance
140  * Change to new flashing method.
141  * 
142  * 51    2/09/98 9:07p Lawrance
143  * Ensure 'evaded' popup has precedence over 'launch' popup
144  * 
145  * 50    1/25/98 10:31p Lawrance
146  * Don't draw most hud gauges when viewing from another ship.
147  * 
148  * 49    1/19/98 11:37p Lawrance
149  * Fixing Optimization build warnings
150  * 
151  * 48    1/14/98 10:21a Lawrance
152  * Draw reticle correctly when gauges are disabled.
153  * 
154  * 47    1/08/98 3:20p Johnson
155  * ALAN: Ensure entire throttle gauge flashes
156  * 
157  * 46    1/05/98 9:38p Lawrance
158  * Implement flashing HUD gauges.
159  * 
160  * 45    1/02/98 9:10p Lawrance
161  * Big changes to how colors get set on the HUD.
162  * 
163  * 44    12/16/97 9:13p Lawrance
164  * Integrate new gauges into HUD config.
165  * 
166  * 43    12/10/97 10:02p Lawrance
167  * Change weapon linking to use flags.
168  * 
169  * 42    12/08/97 1:49p Lawrance
170  * only play threat lock sound when a lock is being attempted
171  * 
172  * 41    11/17/97 6:37p Lawrance
173  * new gauges: extended target view, new lock triangles, support ship view
174  * 
175  * 40    11/11/97 10:25p Lawrance
176  * add sound hook for when missile threat flashes
177  * 
178  * 39    11/11/97 5:05p Lawrance
179  * get threat indicator working more reliably
180  * 
181  * 38    11/05/97 11:20p Lawrance
182  * add speed numbers to the reticle
183  * 
184  * 37    11/04/97 7:49p Lawrance
185  * integrating new HUD reticle and shield icons
186  * 
187  * 36    11/03/97 5:38p Dave
188  * Cleaned up more multiplayer sequencing. Added OBJ_OBSERVER module/type.
189  * Restructured HUD_config structs/flags.
190  * 
191  * $NoKeywords: $
192  *
193 */
194
195 #include "2d.h"
196
197 #include "hudreticle.h"
198 #include "hud.h"
199 #include "math.h"
200 #include "player.h"
201 #include "ship.h"
202 #include "freespace.h"
203 #include "ai.h"
204 #include "bmpman.h"
205 #include "key.h"
206 #include "timer.h"
207 #include "math.h"
208 #include "gamesnd.h"
209 #include "hudtargetbox.h"
210 #include "multi.h"
211 #include "emp.h"
212 #include "localize.h"
213
214 static int Reticle_inited = 0;
215
216 #ifdef MAKE_FS1
217         #define NUM_RETICLE_ANIS                11
218 #else
219         #define NUM_RETICLE_ANIS                        6               // keep up to date when modifying the number of reticle ani files
220 #endif
221
222 #define RETICLE_TOP_ARC                         0
223 #define RETICLE_LASER_WARN                      1
224 #define RETICLE_LOCK_WARN                       2
225 #define RETICLE_LEFT_ARC                        3
226 #define RETICLE_RIGHT_ARC                       4
227 #ifdef MAKE_FS1
228 #define RETICLE_ONE_PRIMARY             5
229 #define RETICLE_TWO_PRIMARY             6
230 #define RETICLE_ONE_SECONDARY   7
231 #define RETICLE_TWO_SECONDARY   8
232 #define RETICLE_THREE_SECONDARY 9
233 #define RETICLE_CENTER                  10
234 // #define RETICLE_LAUNCH_LABEL 11
235 #else
236 #define RETICLE_CENTER                  5
237 #endif
238
239 int Hud_throttle_frame_h[GR_NUM_RESOLUTIONS] = {
240         85,
241         136
242 };
243 int Hud_throttle_frame_w[GR_NUM_RESOLUTIONS] = {
244         49, 
245         78
246 };
247 int Hud_throttle_frame_bottom_y[GR_NUM_RESOLUTIONS] = {
248 #ifdef MAKE_FS1
249         330,
250 #else
251         325,
252 #endif
253         520
254 };
255 int Hud_throttle_h[GR_NUM_RESOLUTIONS] = {
256 #ifdef MAKE_FS1
257         49,
258 #else
259         50,
260 #endif
261         80
262 };
263 int Hud_throttle_bottom_y[GR_NUM_RESOLUTIONS] = {
264 #ifdef MAKE_FS1
265         312,
266 #else
267         307,
268 #endif
269         491
270 };
271 int Hud_throttle_aburn_h[GR_NUM_RESOLUTIONS] = {
272         17,
273         27
274 };
275 int Hud_throttle_aburn_button[GR_NUM_RESOLUTIONS] = {
276         259,
277         414
278 };
279
280 int Outer_circle_radius[GR_NUM_RESOLUTIONS] = {
281         104,
282         166
283 };
284
285 int Hud_reticle_center[GR_NUM_RESOLUTIONS][2] = {
286         { // GR_640
287                 320, 242
288         },
289         { // GR_1024
290                 512, 385
291         }
292 };
293
294 char Reticle_frame_names[GR_NUM_RESOLUTIONS][NUM_RETICLE_ANIS][MAX_FILENAME_LEN] = 
295 {
296 //XSTR:OFF
297         { // GR_640
298 #ifdef MAKE_FS1
299                 "toparc1",
300                 "toparc2",
301                 "toparc3",
302                 "leftarc",
303                 "rightarc1",
304                 "rightarc2",
305                 "rightarc3",
306                 "rightarc4",
307                 "rightarc5",
308                 "rightarc6",
309 //              "toparc4",
310                 "reticle1",
311 #else
312                 "toparc1",
313                 "toparc2",
314                 "toparc3",
315                 "leftarc",
316                 "rightarc1",
317                 "reticle1",
318 #endif
319         }, 
320         { // GR_1024
321                 "2_toparc1",
322                 "2_toparc2",
323                 "2_toparc3",
324                 "2_leftarc",
325                 "2_rightarc1",
326 #ifdef MAKE_FS1
327                 "2_rightarc2",
328                 "2_rightarc3",
329                 "2_rightarc4",
330                 "2_rightarc5",
331                 "2_rightarc6",  
332                 // "2_toparc4",
333 #endif
334                 "2_reticle1",   
335         }
336 //XSTR:ON
337 };
338
339 // reticle frame coords
340 int Reticle_frame_coords[GR_NUM_RESOLUTIONS][NUM_RETICLE_ANIS][2] = {
341         { // GR_640
342 #ifdef MAKE_FS1
343                 {241, 139},             // toparc1
344                 {300, 139},             // toparc2
345                 {320, 139},             // toparc3
346                 {220, 246},             // leftarc
347                 {374, 244},             // rightarc1
348                 {406, 255},             // rightarc2
349                 {406, 255},             // rightarc3
350                 {391, 278},             // rightarc4
351                 {391, 278},             // rightarc5
352                 {391, 278},             // rightarc6
353                 // {297, 162},  // toparc4
354                 {308, 233}              // reticle1
355 #else
356                 {241, 137},             // toparc1
357                 {400, 245},             // toparc2
358                 {394, 261},             // toparc3
359                 {216, 168},             // leftarc
360                 {359, 168},             // rightarc1
361                 {308, 235}              // reticle1
362 #endif
363         }, 
364         { // GR_1024
365                 {386, 219},
366                 {640, 393},
367                 {631, 419},
368                 {346, 269},
369                 {574, 269},
370 #ifdef MAKE_FS1
371                 {649, 401},
372                 {649, 401},
373                 {625, 438},
374                 {625, 438},
375                 {625, 438},
376 //              {475, 258},
377 #endif
378                 {493, 370}
379         }
380 };
381
382 // "launch" gauge coords
383 int Reticle_launch_coords[GR_NUM_RESOLUTIONS][2] = {
384         { // GR_640
385                 297,    161
386         },
387         { // GR_1024
388                 475,    258
389         }
390 };
391
392 hud_frames Reticle_gauges[NUM_RETICLE_ANIS];
393
394 #define THREAT_DUMBFIRE                         (1<<0)
395 #define THREAT_ATTEMPT_LOCK             (1<<1)
396 #define THREAT_LOCK                                     (1<<2)
397
398 #define THREAT_UPDATE_DUMBFIRE_TIME             1000            // time between checking for dumbfire threats
399 #define THREAT_UPDATE_LOCK_TIME                 500             // time between checking for lock threats
400
401 #define THREAT_DUMBFIRE_FLASH                           180
402 #define THREAT_LOCK_FLASH                                       180
403 static int Threat_dumbfire_timer;               // timestamp for when to show next flashing frame for dumbfire threat
404 static int Threat_lock_timer;                           // timestamp for when to show next flashing frame for lock threat
405
406 static int Threat_dumbfire_frame;                       // frame offset of current dumbfire flashing warning
407 static int Threat_lock_frame;                           // frame offset of current lock flashing warning
408
409 // coordinates
410 static int Max_speed_coords[GR_NUM_RESOLUTIONS][2] = 
411 {
412         { // GR_640
413                 236, 254
414         }, 
415         { // GR_1024
416                 377, 406
417         }
418 };
419 static int Zero_speed_coords[GR_NUM_RESOLUTIONS][2] = {
420         { // GR_640
421                 252, 303
422         },
423         { // GR_1024
424                 403, 485
425         }
426 };
427
428 // Called at the start of each level.. use Reticle_inited so we only load frames once
429 void hud_init_reticle()
430 {
431         int                     i;
432         hud_frames      *hfp;
433
434         Threat_dumbfire_timer = timestamp(0);
435         Threat_lock_timer = timestamp(0);
436         Threat_dumbfire_frame = 1;
437         Threat_lock_frame = 1;
438         Player->threat_flags = 0;
439         Player->update_dumbfire_time = timestamp(0);            
440         Player->update_lock_time = timestamp(0);
441
442         if ( Reticle_inited ) {
443                 return;
444         }
445
446         for ( i = 0; i < NUM_RETICLE_ANIS; i++ ) {
447                 hfp = &Reticle_gauges[i];
448                 hfp->first_frame = bm_load_animation(Reticle_frame_names[gr_screen.res][i], &hfp->num_frames);
449                 if ( hfp->first_frame < 0 ) {
450                         Warning(LOCATION,"Cannot load hud ani: %s\n", Reticle_frame_names[gr_screen.res][i]);
451                 }
452         }
453
454         Reticle_inited = 1;
455 }
456
457 // called once per frame to update the reticle gauges.  Makes calls to
458 // ship_dumbfire_threat() and ship_lock_threat() and updates Threat_flags.
459 void hud_update_reticle( player *pp )
460 {
461         int rval;
462         ship *shipp;
463
464         // multiplayer clients won't call this routine
465         if ( MULTIPLAYER_CLIENT || MULTI_OBSERVER(Net_players[MY_NET_PLAYER_NUM]))
466                 return;
467
468         shipp = &Ships[Objects[pp->objnum].instance];
469
470         if ( ship_dumbfire_threat(shipp) ) {
471                 pp->threat_flags |= THREAT_DUMBFIRE;
472                 pp->update_dumbfire_time = timestamp(THREAT_UPDATE_DUMBFIRE_TIME);
473         }
474
475         if ( timestamp_elapsed(pp->update_dumbfire_time) ) {
476                 pp->update_dumbfire_time = timestamp(THREAT_UPDATE_DUMBFIRE_TIME);
477                 pp->threat_flags &= ~THREAT_DUMBFIRE;
478         }
479
480         if ( timestamp_elapsed(pp->update_lock_time) ) {
481                 pp->threat_flags &= ~(THREAT_LOCK | THREAT_ATTEMPT_LOCK);
482                 pp->update_lock_time = timestamp(THREAT_UPDATE_LOCK_TIME);
483                 rval = ship_lock_threat(shipp);
484                 if ( rval == 1 ) {
485                         pp->threat_flags |= THREAT_ATTEMPT_LOCK;
486                 } else if ( rval == 2 ) {
487                         pp->threat_flags |= THREAT_LOCK;
488                 }
489         }
490 }
491
492 // draw left arc (the dark portion of the throttle gauge)
493 void hud_render_throttle_background(int y_end)
494 {
495         int x,y,w,h;
496
497         hud_set_gauge_color(HUD_THROTTLE_GAUGE);
498
499         x = Reticle_frame_coords[gr_screen.res][RETICLE_LEFT_ARC][0];
500         y = Reticle_frame_coords[gr_screen.res][RETICLE_LEFT_ARC][1];
501
502         bm_get_info( Reticle_gauges[RETICLE_LEFT_ARC].first_frame+1,&w,&h);     
503
504         if ( y_end > y ) {
505                 GR_AABITMAP_EX(Reticle_gauges[RETICLE_LEFT_ARC].first_frame+1, x, y, w, y_end-y+1, 0, 0);               
506         }
507 }
508
509 // draw left arc (the bright portion of the throttle gauge)
510 void hud_render_throttle_foreground(int y_end)
511 {
512         int x,y,w,h;
513
514         hud_set_gauge_color(HUD_THROTTLE_GAUGE);
515
516         x = Reticle_frame_coords[gr_screen.res][RETICLE_LEFT_ARC][0];
517         y = Reticle_frame_coords[gr_screen.res][RETICLE_LEFT_ARC][1];
518
519         bm_get_info( Reticle_gauges[RETICLE_LEFT_ARC].first_frame+1,&w,&h);
520
521         if ( y_end < Hud_throttle_frame_bottom_y[gr_screen.res] ) {             
522                 GR_AABITMAP_EX(Reticle_gauges[RETICLE_LEFT_ARC].first_frame+2, x, y_end, w, h-(y_end-y), 0, y_end-y);           
523         }
524 }
525
526 // Draw the throttle speed number
527 void hud_render_throttle_speed(float current_speed, int y_end)
528 {
529         char buf[32];
530         int sx, sy, x_pos, y_pos, w, h;
531
532         hud_set_gauge_color(HUD_THROTTLE_GAUGE);
533
534         // y_end is the y-coordinate of the current throttle setting, calc x-coordinate for edge of 
535         // circle (x^2 + y^2 = r^2)
536         y_pos = Hud_reticle_center[gr_screen.res][1] - y_end;
537         x_pos = (int)sqrt(double(Outer_circle_radius[gr_screen.res] * Outer_circle_radius[gr_screen.res] - y_pos * y_pos) );
538         x_pos = Hud_reticle_center[gr_screen.res][0] - x_pos;
539
540         // draw current speed at (x_pos, y_end);
541         SDL_snprintf(buf, SDL_arraysize(buf), "%d", fl2i(current_speed+0.5f));
542         hud_num_make_mono(buf);
543         gr_get_string_size(&w, &h, buf);
544         sx = x_pos - w - 2;
545         sy = fl2i(y_end - h/2.0f + 1.5);
546         gr_printf(sx, sy, buf);
547
548         if ( Players[Player_num].flags & PLAYER_FLAGS_MATCH_TARGET ) {
549                 int offset;
550                 if ( current_speed <= 9.5 ) {
551                         offset = 0;
552                 } else {
553                         offset = 3;
554                 }
555                 if (Lcl_gr) {
556                         // print an m, cuz the voice says its an m.  
557                         // its a normal m cuz the german font has no special m (its an a)
558                         gr_string(sx+offset, sy + h, "m");
559                 } else {
560                         gr_printf(sx+offset, sy + h, "%c", Lcl_special_chars + 3);
561                 }
562         }
563 }
564
565 // draw the "desired speed" bar on the throttle
566 void hud_render_throttle_line(int y)
567 {
568         // hud_set_bright_color();
569         hud_set_gauge_color(HUD_THROTTLE_GAUGE, HUD_C_BRIGHT);
570
571         GR_AABITMAP_EX(Reticle_gauges[RETICLE_LEFT_ARC].first_frame+3, Reticle_frame_coords[gr_screen.res][RETICLE_LEFT_ARC][0], y, Hud_throttle_frame_w[gr_screen.res], 1, 0, y-Reticle_frame_coords[gr_screen.res][RETICLE_LEFT_ARC][1]);     
572 }
573
574 // Draw the throttle gauge along the left arc of the reticle
575 void hud_show_throttle()
576 {
577         float   desired_speed, max_speed, current_speed, percent_max, percent_aburn_max;
578         int     desired_y_pos, y_end;
579
580         ship_info       *sip;
581         sip = &Ship_info[Player_ship->ship_info_index];
582
583         current_speed = Player_obj->phys_info.fspeed;
584         if ( current_speed < 0.0f){
585                 current_speed = 0.0f;
586         }
587
588         max_speed = Ships[Player_obj->instance].current_max_speed;
589         if ( max_speed <= 0 ) {
590                 max_speed = sip->max_vel.xyz.z;
591         }
592
593         desired_speed = Player->ci.forward * max_speed;
594         if ( desired_speed < 0.0f ){            // so ships that go backwards don't force the indicators below where they can go
595                 desired_speed = 0.0f;
596         }
597
598         desired_y_pos = Hud_throttle_bottom_y[gr_screen.res] - fl2i(Hud_throttle_h[gr_screen.res]*desired_speed/max_speed+0.5f) - 1;
599
600         SDL_assert(max_speed != 0);
601         percent_max = current_speed / max_speed;
602
603         percent_aburn_max = 0.0f;
604         if ( percent_max > 1 ) {
605                 percent_max = 1.0f;
606                 percent_aburn_max = (current_speed - max_speed) / (sip->afterburner_max_vel.xyz.z - max_speed);
607                 if ( percent_aburn_max > 1.0f ) {
608                         percent_aburn_max = 1.0f;
609                 }
610                 if ( percent_aburn_max < 0 ) {
611                         percent_aburn_max = 0.0f;
612                 }
613         }
614
615         y_end = Hud_throttle_bottom_y[gr_screen.res] - fl2i(Hud_throttle_h[gr_screen.res]*percent_max+0.5f);
616         if ( percent_aburn_max > 0 ) {
617                 y_end -= fl2i(percent_aburn_max * Hud_throttle_aburn_h[gr_screen.res] + 0.5f);
618         }
619
620         if ( Player_obj->phys_info.flags & PF_AFTERBURNER_ON ) {
621                 desired_y_pos = 240;
622         }
623
624         // draw left arc (the dark portion of the throttle gauge)
625 #ifdef MAKE_FS1
626         hud_render_throttle_background(y_end);
627 #endif
628
629         // draw throttle speed number
630         hud_render_throttle_speed(current_speed, y_end);
631
632         // draw the "desired speed" bar on the throttle
633         hud_render_throttle_line(desired_y_pos);
634
635         // draw left arc (the bright portion of the throttle gauge)
636         hud_render_throttle_foreground(y_end);
637
638         gr_printf(Max_speed_coords[gr_screen.res][0], Max_speed_coords[gr_screen.res][1], "%d",fl2i(max_speed));
639         gr_printf(Zero_speed_coords[gr_screen.res][0], Zero_speed_coords[gr_screen.res][1], XSTR( "0", 292));
640 }
641
642 #ifdef MAKE_FS1
643 // Draw the primary and secondary weapon indicators along the right arc of the reticle
644 void hud_show_reticle_weapons()
645 {
646         int                     gauge_index=0, frame_offset=0;
647         ship_weapon     *swp;
648
649         swp = &Player_ship->weapons;
650
651         switch( swp->num_primary_banks ) {
652                 case 0:
653                         gauge_index = -1;
654                         break;
655
656                 case 1:
657                         gauge_index = RETICLE_ONE_PRIMARY;
658                         if ( Player_ship->weapons.current_primary_bank == -1 ) {
659                                 frame_offset = 0;       
660                         } else {
661                                 frame_offset = 1;       
662                         }
663                         break;
664
665                 case 2:
666                         gauge_index = RETICLE_TWO_PRIMARY;
667                         if ( swp->current_primary_bank == -1 ) {
668                                 frame_offset = 0;       
669                         } else {
670                                 if ( Player_ship->flags & SF_PRIMARY_LINKED ) {
671                                         frame_offset = 3;
672                                 } else {
673                                         if ( swp->current_primary_bank == 0 ) {
674                                                 frame_offset = 1;
675                                         } else {
676                                                 frame_offset = 2;
677                                         }
678                                 }
679                         }
680                         break;
681
682                 default:
683                         Int3(); // shouldn't happen (get Alan if it does)
684                         return;
685                         break;
686         }
687         
688         if ( gauge_index != -1 ) {
689                 GR_AABITMAP(Reticle_gauges[gauge_index].first_frame+frame_offset, Reticle_frame_coords[gr_screen.res][gauge_index][0], Reticle_frame_coords[gr_screen.res][gauge_index][1]);            
690         }
691
692         int num_banks = swp->num_secondary_banks;
693         if ( num_banks <= 0 ) {
694                 num_banks = Ship_info[Player_ship->ship_info_index].num_secondary_banks;
695         }
696
697         switch( num_banks ) {
698                 case 0:
699                         Int3();
700                         gauge_index = -1;
701                         break;
702
703                 case 1:
704                         gauge_index = RETICLE_ONE_SECONDARY;
705                         break;
706
707                 case 2:
708                         gauge_index = RETICLE_TWO_SECONDARY;
709                         break;
710
711                 case 3:
712                         gauge_index = RETICLE_THREE_SECONDARY;
713                         break;
714
715                 default:
716                         Int3(); // shouldn't happen (get Alan if it does)
717                         return;
718                         break;
719         }
720         
721         if ( gauge_index != -1 ) {
722                 if ( swp->num_secondary_banks <= 0 ) {
723                         frame_offset = 0;
724                 } else {
725                         frame_offset = swp->current_secondary_bank+1;
726                 }
727
728                 GR_AABITMAP(Reticle_gauges[gauge_index].first_frame+frame_offset, Reticle_frame_coords[gr_screen.res][gauge_index][0], Reticle_frame_coords[gr_screen.res][gauge_index][1]);            
729         }
730 }
731 #endif
732
733 // Draw the lock threat gauge on the HUD.  Use Threat_flags to determine if a 
734 // threat exists, and draw flashing frames.
735 void hud_show_lock_threat()
736 {
737         int frame_offset;
738
739         if ( Player->threat_flags & (THREAT_LOCK | THREAT_ATTEMPT_LOCK) ) {
740                 if ( timestamp_elapsed(Threat_lock_timer) ) {
741                         if ( Player->threat_flags & THREAT_LOCK )  {
742                                 Threat_lock_timer = timestamp(fl2i(THREAT_LOCK_FLASH/2.0f));
743                         } else {
744                                 Threat_lock_timer = timestamp(THREAT_LOCK_FLASH);
745                         }
746                         Threat_lock_frame++;
747                         if ( Threat_lock_frame > 2 ) {
748                                 Threat_lock_frame = 1;
749                         }
750                         if ( (Threat_lock_frame == 2) && (Player->threat_flags & THREAT_ATTEMPT_LOCK ) ) {
751                                 snd_play( &Snds[SND_THREAT_FLASH]);
752                         }
753                 }
754                 frame_offset = Threat_lock_frame;
755         } else {
756                 frame_offset = 0;
757         }
758
759 #ifdef FS2_DEMO
760         // demo .hcf has gauge color wrong, so just match center reticle instead
761         hud_set_gauge_color(HUD_CENTER_RETICLE);
762 #else
763         hud_set_gauge_color(HUD_THREAT_GAUGE);
764 #endif
765
766         GR_AABITMAP(Reticle_gauges[RETICLE_LOCK_WARN].first_frame+frame_offset, Reticle_frame_coords[gr_screen.res][RETICLE_LOCK_WARN][0], Reticle_frame_coords[gr_screen.res][RETICLE_LOCK_WARN][1]);
767
768         // "launch" flash
769         if ( (frame_offset > 0) && (Player->threat_flags & THREAT_LOCK) ) {
770                 if ( hud_targetbox_flash_expired(TBOX_FLASH_CMEASURE) ) {
771                         // hack
772                         int bright;
773                         if(frame_offset % 2){
774                                 bright = 1;
775                         } else {
776                                 bright = 0;
777                         }
778                         // GR_AABITMAP(Reticle_gauges[RETICLE_LAUNCH_LABEL].first_frame+frame_offset%2, Reticle_frame_coords[gr_screen.res][RETICLE_LAUNCH_LABEL][0], Reticle_frame_coords[gr_screen.res][RETICLE_LAUNCH_LABEL][1]);
779
780                         // use hud text flash gauge code
781                         hud_show_text_flash_icon(XSTR("Launch", 1507), Reticle_launch_coords[gr_screen.res][1], bright);
782                 }
783         }
784 }
785
786 // Draw the dumbfire threat gauge on the HUD.  Use Threat_flags to determine if a
787 // threat exists, and draw flashing frames.
788 void hud_show_dumbfire_threat()
789 {
790         int frame_offset;
791
792         if ( Player->threat_flags & THREAT_DUMBFIRE ) {
793                 if ( timestamp_elapsed(Threat_dumbfire_timer) ) {
794                         Threat_dumbfire_timer = timestamp(THREAT_DUMBFIRE_FLASH);
795                         Threat_dumbfire_frame++;
796                         if ( Threat_dumbfire_frame > 2 ) {
797                                 Threat_dumbfire_frame = 1;
798                         }
799                 }
800                 frame_offset = Threat_dumbfire_frame;
801         } else {
802                 frame_offset = 0;
803         }
804
805 #ifdef FS2_DEMO
806         // demo .hcf has gauge color wrong, so just match center reticle instead
807         hud_set_gauge_color(HUD_CENTER_RETICLE);
808 #else
809         hud_set_gauge_color(HUD_THREAT_GAUGE);
810 #endif
811
812         GR_AABITMAP(Reticle_gauges[RETICLE_LASER_WARN].first_frame + frame_offset, Reticle_frame_coords[gr_screen.res][RETICLE_LASER_WARN][0], Reticle_frame_coords[gr_screen.res][RETICLE_LASER_WARN][1]);     
813 }
814
815 // Draw the center of the reticle
816 void hud_show_center_reticle()
817 {
818         SDL_assert(Reticle_gauges[RETICLE_CENTER].first_frame != -1 );
819
820 //      hud_set_default_color();
821         // hud_set_bright_color();
822         hud_set_gauge_color(HUD_CENTER_RETICLE, HUD_C_BRIGHT);
823
824         GR_AABITMAP(Reticle_gauges[RETICLE_CENTER].first_frame, Reticle_frame_coords[gr_screen.res][RETICLE_CENTER][0], Reticle_frame_coords[gr_screen.res][RETICLE_CENTER][1]);
825 }
826
827 // Draw top portion of reticle
828 void hud_show_top_arc()
829 {
830         hud_set_gauge_color(HUD_CENTER_RETICLE);
831
832         // hud_set_default_color();
833         if ( hud_gauge_active(HUD_THREAT_GAUGE) ) {     
834                 // draw top arc
835                 GR_AABITMAP(Reticle_gauges[RETICLE_TOP_ARC].first_frame+1, Reticle_frame_coords[gr_screen.res][RETICLE_TOP_ARC][0], Reticle_frame_coords[gr_screen.res][RETICLE_TOP_ARC][1]);           
836
837                 // draw dumbfire threat
838                 hud_show_dumbfire_threat();
839
840                 // draw lock threat
841                 hud_show_lock_threat();
842         } else {                
843                 // draw top arc without any holes
844                 GR_AABITMAP(Reticle_gauges[RETICLE_TOP_ARC].first_frame, Reticle_frame_coords[gr_screen.res][RETICLE_TOP_ARC][0], Reticle_frame_coords[gr_screen.res][RETICLE_TOP_ARC][1]);
845         }
846 }
847
848 // Draw right portion of reticle
849 void hud_show_right_arc()
850 {       
851         hud_set_gauge_color(HUD_CENTER_RETICLE);
852
853 #ifndef MAKE_FS1
854         GR_AABITMAP(Reticle_gauges[RETICLE_RIGHT_ARC].first_frame+1, Reticle_frame_coords[gr_screen.res][RETICLE_RIGHT_ARC][0], Reticle_frame_coords[gr_screen.res][RETICLE_RIGHT_ARC][1]);             
855 #else
856                 
857         // draw the weapons indicators in the holes along the right arc
858         if ( hud_gauge_active(HUD_WEAPON_LINKING_GAUGE) ) {             
859                 // draw right arc with holes in it
860                 GR_AABITMAP(Reticle_gauges[RETICLE_RIGHT_ARC].first_frame+1, Reticle_frame_coords[gr_screen.res][RETICLE_RIGHT_ARC][0], Reticle_frame_coords[gr_screen.res][RETICLE_RIGHT_ARC][1]);             
861 //              the following line was removed by Jasen to get rid of "undeclared identifier"
862 //              hehe - DB
863                 hud_show_reticle_weapons();
864         } else {                
865                 // draw right arc without any holes
866                 GR_AABITMAP(Reticle_gauges[RETICLE_RIGHT_ARC].first_frame, Reticle_frame_coords[gr_screen.res][RETICLE_RIGHT_ARC][0], Reticle_frame_coords[gr_screen.res][RETICLE_RIGHT_ARC][1]);
867         }
868 #endif
869 }
870
871 // Draw the left portion of the reticle
872 void hud_show_left_arc()
873 {                       
874 #ifndef MAKE_FS1  // FS1: is drawn another way
875         // draw left arc (the dark portion of the throttle gauge)
876         hud_set_gauge_color(HUD_CENTER_RETICLE);        
877         GR_AABITMAP(Reticle_gauges[RETICLE_LEFT_ARC].first_frame, Reticle_frame_coords[gr_screen.res][RETICLE_LEFT_ARC][0], Reticle_frame_coords[gr_screen.res][RETICLE_LEFT_ARC][1]);                  
878 #endif
879         
880         // draw the throttle
881         if ( hud_gauge_active(HUD_THROTTLE_GAUGE) ) {
882                 hud_set_gauge_color(HUD_THROTTLE_GAUGE);
883                 hud_show_throttle();            
884         } 
885 }
886
887 // called once per frame from HUD_render_2d() to draw the reticle gauges
888 void hud_show_reticle()
889 {
890         if ( !(Viewer_mode & VM_OTHER_SHIP) ) {
891                 hud_show_top_arc();
892                 hud_show_right_arc();
893                 hud_show_left_arc();
894         }
895
896         // draw the center of the reticle
897         if ( hud_gauge_active(HUD_CENTER_RETICLE) ) {
898                 hud_show_center_reticle();
899         }
900 }
901
902 void hudreticle_page_in()
903 {
904         hud_frames      *hfp;
905
906         int i;
907         for ( i = 0; i < NUM_RETICLE_ANIS; i++ ) {
908                 hfp = &Reticle_gauges[i];
909                 bm_page_in_aabitmap( hfp->first_frame, hfp->num_frames);
910         }
911
912 }