]> icculus.org git repositories - taylor/freespace2.git/blob - src/hud/hudwingmanstatus.cpp
Initial revision
[taylor/freespace2.git] / src / hud / hudwingmanstatus.cpp
1 /*
2  * $Logfile: /Freespace2/code/Hud/HUDWingmanStatus.cpp $
3  * $Revision$
4  * $Date$
5  * $Author$
6  *
7  * Module for the wingman status gauge
8  *
9  * $Log$
10  * Revision 1.1  2002/05/03 03:28:09  root
11  * Initial revision
12  *
13  * 
14  * 7     6/10/99 3:43p Dave
15  * Do a better job of syncing text colors to HUD gauges.
16  * 
17  * 6     1/07/99 9:06a Jasen
18  * coords blah blah blah
19  * 
20  * 5     1/06/99 4:03p Dave
21  * Added better comments to wingman status gauge coords.
22  * 
23  * 4     12/28/98 3:17p Dave
24  * Support for multiple hud bitmap filenames for hi-res mode.
25  * 
26  * 3     12/21/98 5:03p Dave
27  * Modified all hud elements to be multi-resolution friendly.
28  * 
29  * 2     10/07/98 10:53a Dave
30  * Initial checkin.
31  * 
32  * 1     10/07/98 10:49a Dave
33  * 
34  * 17    8/25/98 1:48p Dave
35  * First rev of EMP effect. Player side stuff basically done. Next comes
36  * AI code.
37  * 
38  * 16    6/09/98 5:18p Lawrance
39  * French/German localization
40  * 
41  * 15    6/09/98 10:31a Hoffoss
42  * Created index numbers for all xstr() references.  Any new xstr() stuff
43  * added from here on out should be added to the end if the list.  The
44  * current list count can be found in FreeSpace.cpp (search for
45  * XSTR_SIZE).
46  * 
47  * 14    6/01/98 11:43a John
48  * JAS & MK:  Classified all strings for localization.
49  * 
50  * 13    5/06/98 2:46p Mike
51  * Modify num-ships-attacking system.
52  * 
53  * 12    4/17/98 1:42p Allender
54  * fixed optimized build warning
55  * 
56  * 11    4/16/98 2:56p Allender
57  * multiple wings were not working after I added Zeta wing
58  * 
59  * 10    4/15/98 11:09p Allender
60  * status gaugs works for team v. team
61  * 
62  * 9     4/14/98 1:35a Allender
63  * (blindly) work on wingman status gauge for team v team multiplayer
64  * 
65  * 8     4/01/98 9:21p John
66  * Made NDEBUG, optimized build with no warnings or errors.
67  * 
68  * 7     3/31/98 11:46p Lawrance
69  * Fix several bugs related to departing ships.
70  * 
71  * 6     3/26/98 5:26p John
72  * added new paging code. nonfunctional.
73  * 
74  * 5     3/22/98 11:13p Allender
75  * work with respawning -- save parse object so ship can be correctly
76  * restored.  Restore wingman status information so gauge updates
77  * correctly
78  * 
79  * 4     3/20/98 10:26a Lawrance
80  * Don't display gauge if Alpha1 is only ship
81  * 
82  * 3     3/18/98 12:03p John
83  * Marked all the new strings as externalized or not.
84  * 
85  * 2     3/14/98 4:59p Lawrance
86  * Totally rework HUD wingman status gauge to work with 5 arbitrary wings
87  * 
88  * 1     3/14/98 8:23a Lawrance
89  *
90  * $NoKeywords: $
91  */
92
93 #include "hud.h"
94 #include "hudwingmanstatus.h"
95 #include "ship.h"
96 #include "2d.h"
97 #include "bmpman.h"
98 #include "timer.h"
99 #include "hudtargetbox.h"
100 #include "linklist.h"
101 #include "systemvars.h"
102 #include "multi.h"
103 #include "emp.h"
104
105 #define HUD_WINGMAN_STATUS_NUM_FRAMES   5
106 #define BACKGROUND_LEFT                                         0
107 #define BACKGROUND_MIDDLE                                       1
108 #define BACKGROUND_RIGHT                                        2
109 #define WINGMAN_STATUS_DOTS                             3
110 #define WINGMAN_STATUS_NAMES                            4
111
112 static char *Wingman_status_filenames[GR_NUM_RESOLUTIONS][HUD_WINGMAN_STATUS_NUM_FRAMES] =
113 {
114 //XSTR:OFF
115         { // GR_640
116                 "wingman1",
117                 "wingman2",
118                 "wingman3",
119                 "wingman4",
120                 "wingman5",
121         }, 
122         { // GR_1024
123                 "wingman1",
124                 "wingman2",
125                 "wingman3",
126                 "wingman4",
127                 "wingman5",
128         }
129 //XSTR:ON
130 };
131
132 static hud_frames Wingman_status_frames[HUD_WINGMAN_STATUS_NUM_FRAMES];
133 static int Wingman_status_gauge_loaded=0;
134
135 #define HUD_WINGMAN_STATUS_NONE                 0               // wingman doesn't exist
136 #define HUD_WINGMAN_STATUS_DEAD                 1               // wingman has died
137 #define HUD_WINGMAN_STATUS_ALIVE                        2               // wingman is in the mission
138 #define HUD_WINGMAN_STATUS_NOT_HERE             3               // wingman hasn't arrived, or has departed
139
140 #define HUD_WINGMAN_MAX_WINGS                                           6               // upped to 6 to hold room for Zeta in team v team.
141 #define HUD_WINGMAN_MAX_SHIPS_PER_WINGS         6
142
143 typedef struct Wingman_status
144 {
145         int     ignore;                                                                                                 // set to 1 when we should ignore this item -- used in team v. team
146         int     used;
147         float hull[HUD_WINGMAN_MAX_SHIPS_PER_WINGS];                    // 0.0 -> 1.0
148         int     status[HUD_WINGMAN_MAX_SHIPS_PER_WINGS];                // HUD_WINGMAN_STATUS_* 
149 } wingman_status;
150
151 wingman_status HUD_wingman_status[HUD_WINGMAN_MAX_WINGS];
152
153 #define HUD_WINGMAN_UPDATE_STATUS_INTERVAL      200
154 static int HUD_wingman_update_timer;
155
156 static int HUD_wingman_flash_duration[HUD_WINGMAN_MAX_WINGS][HUD_WINGMAN_MAX_SHIPS_PER_WINGS];
157 static int HUD_wingman_flash_next[HUD_WINGMAN_MAX_WINGS][HUD_WINGMAN_MAX_SHIPS_PER_WINGS];
158 static int HUD_wingman_flash_is_bright;
159
160 // coords to draw wingman status icons, for 1-5 wings (0-4)
161 int HUD_wingman_left_coords[GR_NUM_RESOLUTIONS][5][2] = {
162         { // GR_640
163                 {550, 144},                             // where to draw the left part of gauge if we have 1 wing
164                 {550, 144},                             // "" 2 wings
165                 {515, 144},                             // "" 3 wings
166                 {480, 144},                             // "" 4 wings
167                 {445, 144}                              // "" 5 wings
168         },
169         { // GR_1024
170                 {932, 144},
171                 {932, 144},
172                 {897, 144},
173                 {862, 144},
174                 {827, 144}
175         },
176 };
177 int HUD_wingman_middle_coords[GR_NUM_RESOLUTIONS][5][2] = {
178         { // GR_640
179                 {0, 0},                                 // we never draw this for 1 wing
180                 {0, 0},                                 // we never draw this for 2 wings
181                 {586, 144},                             // where to draw the _first_ middle gauge for 3 wings
182                 {551, 144},                             // "" 4 wings
183                 {516, 144}                              // "" 5 wings
184         }, 
185         { // GR_1024
186                 {0, 0},
187                 {0, 0},
188                 {968, 144},
189                 {933, 144},
190                 {898, 144}
191         }
192 };
193 int HUD_wingman_right_coords[GR_NUM_RESOLUTIONS][5][2] = {
194         { // GR_640
195                 {621, 144},                     // always drawn in the same spot
196                 {621, 144},
197                 {621, 144},
198                 {621, 144},
199                 {621, 144},
200         }, 
201         { // GR_1024
202                 {1003, 144},
203                 {1003, 144},
204                 {1003, 144},
205                 {1003, 144},
206                 {1003, 144},
207         }
208 };
209
210 // special coordinates if only one wing is present
211 int HUD_wingman_status_single_coords[GR_NUM_RESOLUTIONS][4][2] = 
212 {
213         { // GR_640
214                 {589,159},                              // where to draw dots 1 - 4 if we have only one wing present (special case)
215                 {582,167},
216                 {596,167},
217                 {589,175},
218         }, 
219         { // GR_1024
220                 {971,159},
221                 {964,167},
222                 {978,167},
223                 {971,175},
224         }
225 };
226
227 int HUD_wingman_status_name_coords[GR_NUM_RESOLUTIONS][HUD_WINGMAN_MAX_WINGS][2] =
228 {
229         { // GR_640
230                 {459,185},                              // duplicated the first item because we only ever display 5 items
231                 {459,185},
232                 {494,185},
233                 {529,185},
234                 {564,185},
235                 {599,185},
236         },
237         { // GR_1024
238                 {841,185},                              // duplicated the first item because we only ever display 5 items
239                 {841,185},
240                 {876,185},
241                 {911,185},
242                 {946,185},
243                 {981,185},
244         }
245 };
246
247 int HUD_wingman_status_coords[GR_NUM_RESOLUTIONS][HUD_WINGMAN_MAX_WINGS][HUD_WINGMAN_MAX_SHIPS_PER_WINGS][2] = 
248 {
249         // duplicated first set of data because we will only ever display up to 5 wings
250         {       // GR_640
251                 // 1 wing present
252                 {{467,159},                                             // ship 1
253                 {460,167},                                              // ship 2
254                 {474,167},                                              // ship 3
255                 {467,175},                                              // ship 4
256                 {456,175},                                              // ship 5
257                 {478,175}},                                             // ship 6
258
259                 // 1 wing present
260                 {{467,159},
261                 {460,167},
262                 {474,167},
263                 {467,175},
264                 {456,175},
265                 {478,175}},
266
267                 // 2 wings present
268                 {{502,159},
269                 {495,167},
270                 {509,167},
271                 {502,175},
272                 {491,175},
273                 {513,175}},
274
275                 // 3 wings present
276                 {{537,159},
277                 {530,167},
278                 {544,167},
279                 {537,175},
280                 {526,175},
281                 {548,175}},
282
283                 // 4 wings present
284                 {{572,159},
285                 {565,167},
286                 {579,167},
287                 {572,175},
288                 {561,175},
289                 {583,175}},
290         
291                 // 5 wings present
292                 {{607,159},
293                 {600,167},
294                 {614,167},
295                 {607,175},
296                 {596,175},
297                 {618,175}},
298         }, 
299         {       // GR_1024
300                 {{849,159},
301                 {842,167},
302                 {856,167},
303                 {849,175},
304                 {838,175},
305                 {860,175}},
306
307                 {{849,159},
308                 {842,167},
309                 {856,167},
310                 {849,175},
311                 {838,175},
312                 {860,175}},
313
314                 {{884,159},
315                 {877,167},
316                 {891,167},
317                 {884,175},
318                 {873,175},
319                 {895,175}},
320
321                 {{919,159},
322                 {912,167},
323                 {926,167},
324                 {919,175},
325                 {908,175},
326                 {930,175}},
327
328                 {{954,159},
329                 {947,167},
330                 {961,167},
331                 {954,175},
332                 {943,175},
333                 {965,175}},
334         
335                 {{989,159},
336                 {982,167},
337                 {996,167},
338                 {989,175},
339                 {978,175},
340                 {1000,175}},
341         } 
342 };
343
344 int hud_wingman_status_wing_index(char *wing_name)
345 {
346 //XSTR:OFF
347         if ( !stricmp("alpha", wing_name) ) {
348                 return 0;
349         } else if ( !stricmp("beta", wing_name) ) {
350                 return 1;
351         } else if ( !stricmp("gamma", wing_name) ) {
352                 return 2;
353         } else if ( !stricmp("delta", wing_name) ) {
354                 return 3;
355         } else if ( !stricmp("epsilon", wing_name) ) {
356                 return 4;
357         } else if ( (Game_mode & GM_MULTIPLAYER) && IS_MISSION_MULTI_TEAMS && !stricmp("zeta", wing_name) ) {
358                 return 5;
359         } else {
360                 return -1;
361         }
362 //XSTR:ON
363 }
364
365 // flag a player wing ship as destroyed
366 void hud_set_wingman_status_dead(int wing_index, int wing_pos)
367 {
368         Assert(wing_index >= 0 && wing_index < HUD_WINGMAN_MAX_WINGS);
369         Assert(wing_pos >= 0 && wing_index < HUD_WINGMAN_MAX_SHIPS_PER_WINGS);
370
371         HUD_wingman_status[wing_index].status[wing_pos] = HUD_WINGMAN_STATUS_DEAD;
372 }
373
374 // flags a given player wing ship as departed
375 void hud_set_wingman_status_departed(int wing_index, int wing_pos)
376 {
377         Assert(wing_index >= 0 && wing_index < HUD_WINGMAN_MAX_WINGS);
378         Assert(wing_pos >= 0 && wing_index < HUD_WINGMAN_MAX_SHIPS_PER_WINGS);
379
380         HUD_wingman_status[wing_index].status[wing_pos] = HUD_WINGMAN_STATUS_NOT_HERE;
381 }
382
383 // flags a given player wing ship as not existing
384 void hud_set_wingman_status_none( int wing_index, int wing_pos)
385 {
386         int i;
387
388         Assert(wing_index >= 0 && wing_index < HUD_WINGMAN_MAX_WINGS);
389         Assert(wing_pos >= 0 && wing_index < HUD_WINGMAN_MAX_SHIPS_PER_WINGS);
390
391         HUD_wingman_status[wing_index].status[wing_pos] = HUD_WINGMAN_STATUS_NONE;
392
393         int used = 0;
394         for ( i = 0; i < HUD_WINGMAN_MAX_SHIPS_PER_WINGS; i++ ) {
395                 if ( HUD_wingman_status[wing_index].status[i] != HUD_WINGMAN_STATUS_NONE ) {
396                         used = 1;
397                         break;
398                 }
399         }
400
401         HUD_wingman_status[wing_index].used = used;
402 }
403
404 // flags a given player wing ship as "alive" (for multiplayer respawns )
405 void hud_set_wingman_status_alive( int wing_index, int wing_pos)
406 {
407         Assert(wing_index >= 0 && wing_index < HUD_WINGMAN_MAX_WINGS);
408         Assert(wing_pos >= 0 && wing_index < HUD_WINGMAN_MAX_SHIPS_PER_WINGS);
409
410         HUD_wingman_status[wing_index].status[wing_pos] = HUD_WINGMAN_STATUS_ALIVE;
411 }
412
413 // get the hull percent for a specific ship, return value 0.0 -> 1.0
414 float hud_get_ship_hull_percent(int ship_index)
415 {
416         ship_info       *sip;
417         object          *ship_objp;
418
419         ship_objp = &Objects[Ships[ship_index].objnum];
420         sip              = &Ship_info[Ships[ship_index].ship_info_index];
421
422         return (ship_objp->hull_strength / sip->initial_hull_strength);
423 }
424
425 void hud_wingman_status_init_late_wings()
426 {
427 /*
428         int i, j, wing_index;
429
430         for ( i = 0; i < num_wings; i++ ) {
431                 wing_index = hud_wingman_status_wing_index(Wings[i].name);
432
433                 if ( (wing_index >= 0) && (Wings[i].total_arrived_count == 0) ) {
434                         HUD_wingman_status[wing_index].used = 1;
435                         for (j = 0; j < Wings[i].wave_count; j++) {
436                                 HUD_wingman_status[wing_index].status[j] = HUD_WINGMAN_STATUS_NOT_HERE;
437                         }
438                 }
439         }
440 */
441 }
442
443 // function which marks the other team wing as not used for the wingman status gauge
444 void hud_wingman_kill_multi_teams()
445 {
446         int wing_index;
447
448         // do nothing in single player or non team v. team games
449         if ( Game_mode & GM_NORMAL )
450                 return;
451
452         if ( !IS_MISSION_MULTI_TEAMS )
453                 return;
454
455         wing_index = -1;
456         if ( Net_player->p_info.team == 0 )
457                 wing_index = hud_wingman_status_wing_index(NOX("zeta"));
458         else if ( Net_player->p_info.team == 1 )
459                 wing_index = hud_wingman_status_wing_index(NOX("alpha"));
460
461         if ( wing_index == -1 )
462                 return;
463
464         HUD_wingman_status[wing_index].ignore = 1;
465 }
466
467
468 // called once per level to init the wingman status gauge.  Loads in the frames the first time
469 void hud_init_wingman_status_gauge()
470 {
471         int     i, j;
472
473         if ( !Wingman_status_gauge_loaded ) {
474
475                 for ( i = 0; i < HUD_WINGMAN_STATUS_NUM_FRAMES; i++ ) {
476                         Wingman_status_frames[i].first_frame = bm_load_animation(Wingman_status_filenames[gr_screen.res][i], &Wingman_status_frames[i].num_frames);
477                         if ( Wingman_status_frames[i].first_frame == -1 ) {
478                                 Warning(LOCATION, NOX("Error loading Wingman_status_filenames[gr_screen.res][i]'\n"));
479                                 return;
480                         }
481                 }
482                 Wingman_status_gauge_loaded = 1;
483         }
484
485         hud_wingman_status_init_flash();
486
487         HUD_wingman_update_timer=timestamp(0);  // update status right away
488
489         for (i = 0; i < HUD_WINGMAN_MAX_WINGS; i++) {
490                 HUD_wingman_status[i].ignore = 0;
491                 HUD_wingman_status[i].used = 0;
492                 for ( j = 0; j < HUD_WINGMAN_MAX_SHIPS_PER_WINGS; j++ ) {
493                         HUD_wingman_status[i].status[j] = HUD_WINGMAN_STATUS_NONE;
494                 }
495         }
496
497         hud_wingman_status_init_late_wings();
498         hud_wingman_kill_multi_teams();
499         hud_wingman_status_update();
500 }
501
502 // Update the status of the wingman status
503 void hud_wingman_status_update()
504 {
505         if ( timestamp_elapsed(HUD_wingman_update_timer) ) {
506                 int             wing_index,wing_pos;
507                 ship_obj        *so;
508                 object  *ship_objp;
509                 ship            *shipp;
510
511                 HUD_wingman_update_timer=timestamp(HUD_WINGMAN_UPDATE_STATUS_INTERVAL);
512
513                 for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
514                         ship_objp = &Objects[so->objnum];
515                         shipp = &Ships[ship_objp->instance];
516
517                         wing_index = shipp->wing_status_wing_index;
518                         wing_pos = shipp->wing_status_wing_pos;
519
520                         if ( (wing_index >= 0) && (wing_pos >= 0) ) {
521
522                                 HUD_wingman_status[wing_index].used = 1;
523                                 if (!(shipp->flags & SF_DEPARTING) ) {
524                                         HUD_wingman_status[wing_index].status[wing_pos] = HUD_WINGMAN_STATUS_ALIVE;     
525                                 }
526                                 HUD_wingman_status[wing_index].hull[wing_pos] = hud_get_ship_hull_percent(ship_objp->instance);
527                                 if ( HUD_wingman_status[wing_index].hull[wing_pos] <= 0 ) {
528                                         HUD_wingman_status[wing_index].status[wing_pos] = HUD_WINGMAN_STATUS_DEAD;
529                                 }
530                         }
531                 }
532         }
533 }
534
535 void hud_wingman_status_blit_left_frame(int num_wings_to_draw)
536 {
537         int sx, sy, bitmap;
538
539         // draw left side of frame
540         if((num_wings_to_draw < 1) || (num_wings_to_draw > 5)){
541                 Int3();
542                 return;
543         }
544         sx = HUD_wingman_left_coords[gr_screen.res][num_wings_to_draw - 1][0];  
545         sy = HUD_wingman_left_coords[gr_screen.res][num_wings_to_draw - 1][1];          
546         bitmap = Wingman_status_frames[BACKGROUND_LEFT].first_frame;
547
548         if ( bitmap > -1 ) {
549                 GR_AABITMAP(bitmap, sx, sy);
550                 // gr_set_bitmap(bitmap);
551                 // gr_aabitmap(sx, sy);
552         }
553
554         // write "wingmen" on gauge
555         gr_string(sx+2, sy+2, XSTR( "wingmen", 352));
556 }
557
558 void hud_wingman_status_blit_middle_frame(int num_wings_to_draw)
559 {
560         int sx, sy, bitmap;
561         int idx;
562
563         bitmap = Wingman_status_frames[BACKGROUND_MIDDLE].first_frame;
564         if ( bitmap < 0 ) {
565                 return;
566         }
567
568         // don't draw for 1 or 2 wings
569         if((num_wings == 1) || (num_wings == 2)){
570                 return;
571         }
572
573         // draw left side of frame
574         if((num_wings_to_draw < 1) || (num_wings_to_draw > 5)){
575                 Int3();
576                 return;
577         }       
578         sx = -1;
579         sy = -1;
580         for(idx=num_wings_to_draw; idx>=3; idx--){
581                 sx = HUD_wingman_middle_coords[gr_screen.res][idx - 1][0];      
582                 sy = HUD_wingman_middle_coords[gr_screen.res][idx - 1][1];              
583                 GR_AABITMAP(bitmap, sx, sy);    
584         }       
585 }
586
587 void hud_wingman_status_blit_right_frame(int num_wings_to_draw)
588 {
589         int sx, sy, bitmap;
590
591         // draw left side of frame
592         if((num_wings_to_draw < 1) || (num_wings_to_draw > 5)){
593                 Int3();
594                 return;
595         }
596
597         sx = HUD_wingman_right_coords[gr_screen.res][num_wings_to_draw - 1][0]; 
598         sy = HUD_wingman_right_coords[gr_screen.res][num_wings_to_draw - 1][1];                 
599         bitmap = Wingman_status_frames[BACKGROUND_RIGHT].first_frame;
600
601         if ( bitmap > -1 ) {
602                 GR_AABITMAP(bitmap, sx, sy);            
603         }
604 }
605
606 void hud_wingman_status_blit_dots(int wing_index, int screen_index, int num_wings_to_draw)
607 {
608         int i, sx, sy, is_bright, bitmap = -1, screen_pos;
609
610         Wingman_status_frames[WINGMAN_STATUS_DOTS].first_frame;
611
612         if ( Wingman_status_frames[WINGMAN_STATUS_DOTS].first_frame < 0 ) {
613                 return;
614         }
615         
616         if ( Wingman_status_frames[WINGMAN_STATUS_NAMES].first_frame < 0 ) {
617                 return;
618         }
619
620         screen_pos = screen_index + (HUD_WINGMAN_MAX_WINGS - num_wings_to_draw);
621         
622         // draw wingman dots
623         for ( i = 0; i < HUD_WINGMAN_MAX_SHIPS_PER_WINGS; i++ ) {
624
625                 if ( hud_wingman_status_maybe_flash(wing_index, i) ) {
626                         is_bright=1;
627                 } else {
628                         is_bright=0;
629                 }
630
631                 switch( HUD_wingman_status[wing_index].status[i] ) {
632
633                 case HUD_WINGMAN_STATUS_ALIVE:
634                         bitmap = Wingman_status_frames[WINGMAN_STATUS_DOTS].first_frame;
635                         if ( HUD_wingman_status[wing_index].hull[i] > 0.5f ) {
636                                 // gr_set_color_fast(&IFF_colors[IFF_COLOR_FRIENDLY][is_bright]);
637                                 // use gauge color
638                                 hud_set_gauge_color(HUD_WINGMEN_STATUS, is_bright ? HUD_C_BRIGHT : HUD_C_NORMAL);
639                         } else {
640                                 gr_set_color_fast(&IFF_colors[IFF_COLOR_HOSTILE][is_bright]);
641                         }
642                         break;
643
644                 case HUD_WINGMAN_STATUS_DEAD:
645                         gr_set_color_fast(&IFF_colors[IFF_COLOR_HOSTILE][0]);
646                         bitmap = Wingman_status_frames[WINGMAN_STATUS_DOTS].first_frame+1;
647                         break;
648
649                 case HUD_WINGMAN_STATUS_NOT_HERE:
650                         // gr_set_color_fast(&IFF_colors[IFF_COLOR_FRIENDLY][0]);
651                         hud_set_gauge_color(HUD_WINGMEN_STATUS, is_bright ? HUD_C_BRIGHT : HUD_C_NORMAL);
652                         bitmap = Wingman_status_frames[WINGMAN_STATUS_DOTS].first_frame+1;
653                         break;
654
655                 default:
656                         bitmap=-1;
657                         break;
658
659                 }       // end swtich
660
661                 if ( num_wings_to_draw == 1 ) {
662                         sx = HUD_wingman_status_single_coords[gr_screen.res][i][0];
663                         sy = HUD_wingman_status_single_coords[gr_screen.res][i][1]; 
664                 } else {
665                         sx = HUD_wingman_status_coords[gr_screen.res][screen_pos][i][0];
666                         sy = HUD_wingman_status_coords[gr_screen.res][screen_pos][i][1]; 
667                 }
668
669                 if ( bitmap > -1 ) {
670                         GR_AABITMAP(bitmap, sx, sy);                    
671                 }
672         }
673
674         // draw wing name
675         bitmap = Wingman_status_frames[WINGMAN_STATUS_NAMES].first_frame + wing_index;
676
677         if ( num_wings_to_draw == 1 ) {
678                 sx = HUD_wingman_status_single_coords[gr_screen.res][0][0] - 8;
679                 sy = HUD_wingman_status_single_coords[gr_screen.res][0][1] + 26; 
680         } else {
681                 sx = HUD_wingman_status_name_coords[gr_screen.res][screen_pos][0];
682                 sy = HUD_wingman_status_name_coords[gr_screen.res][screen_pos][1]; 
683         }
684
685         // hud_set_default_color();
686         hud_set_gauge_color(HUD_WINGMEN_STATUS);
687         if ( bitmap > -1 ) {
688                 GR_AABITMAP(bitmap, sx, sy);
689                 // gr_set_bitmap(bitmap);
690                 // gr_aabitmap(sx, sy);
691         }
692
693 }
694
695 int hud_wingman_status_wingmen_exist(int num_wings_to_draw)
696 {
697         int i, j, count = 0;
698
699         switch ( num_wings_to_draw ) {
700         case 0:
701                 count = 0;
702                 break;
703         case 1:
704                 for (i = 0; i < HUD_WINGMAN_MAX_WINGS; i++) {
705                         if ( HUD_wingman_status[i].used > 0 ) {
706                                 for ( j = 0; j < HUD_WINGMAN_MAX_SHIPS_PER_WINGS; j++ ) {
707                                         if ( HUD_wingman_status[i].status[j] != HUD_WINGMAN_STATUS_NONE ) {
708                                                 count++;
709                                         }
710                                 }
711                         }
712                 }
713                 break;
714         default:
715                 count = 2;
716                 break;
717
718         }
719
720         if ( count > 1 ) {
721                 return 1;
722         }
723
724         return 0;
725 }
726
727 // Draw the wingman status gauge
728 void hud_wingman_status_render()
729 {
730         int i, count, num_wings_to_draw = 0;
731
732         for (i = 0; i < HUD_WINGMAN_MAX_WINGS; i++) {
733                 if ( (HUD_wingman_status[i].used > 0) && (HUD_wingman_status[i].ignore == 0) ) {
734                         num_wings_to_draw++;
735                 }
736         }
737
738         if ( !hud_wingman_status_wingmen_exist(num_wings_to_draw) ) {
739                 return;
740         }
741
742         // hud_set_default_color();
743         hud_set_gauge_color(HUD_WINGMEN_STATUS);
744
745         // blit the background frames
746         hud_wingman_status_blit_left_frame(num_wings_to_draw);
747         hud_wingman_status_blit_middle_frame(num_wings_to_draw);
748         hud_wingman_status_blit_right_frame(num_wings_to_draw);
749
750         count = 0;
751         for (i = 0; i < HUD_WINGMAN_MAX_WINGS; i++) {
752                 if ( (HUD_wingman_status[i].used <= 0) || (HUD_wingman_status[i].ignore == 1) ) {
753                         continue;
754                 }
755
756                 hud_wingman_status_blit_dots(i, count, num_wings_to_draw);
757                 count++;
758         }
759 }
760
761 // init the flashing timers for the wingman status gauge
762 void hud_wingman_status_init_flash()
763 {
764         int i, j;
765
766         for ( i = 0; i < HUD_WINGMAN_MAX_WINGS; i++ ) {
767                 for ( j = 0; j < HUD_WINGMAN_MAX_SHIPS_PER_WINGS; j++ ) {
768                         HUD_wingman_flash_duration[i][j] = timestamp(0);
769                         HUD_wingman_flash_next[i][j] = timestamp(0);
770                 }
771         }
772
773         HUD_wingman_flash_is_bright = 0;
774 }
775
776 // start the targetbox item flashing for TBOX_FLASH_DURATION
777 void hud_wingman_status_start_flash(int wing_index, int wing_pos)
778 {
779         HUD_wingman_flash_duration[wing_index][wing_pos] = timestamp(TBOX_FLASH_DURATION);
780 }
781
782 // set the color for flashing dot
783 // exit:        1 =>    set bright color
784 //                      0 =>    set default color
785 int hud_wingman_status_maybe_flash(int wing_index, int wing_pos)
786 {
787         int index, draw_bright=0;
788
789         index = wing_index*HUD_WINGMAN_MAX_SHIPS_PER_WINGS + wing_pos;
790
791         if ( !timestamp_elapsed(HUD_wingman_flash_duration[wing_index][wing_pos]) ) {
792                 if ( timestamp_elapsed(HUD_wingman_flash_next[wing_index][wing_pos]) ) {
793                         HUD_wingman_flash_next[wing_index][wing_pos] = timestamp(TBOX_FLASH_INTERVAL);
794                         HUD_wingman_flash_is_bright ^= (1<<index);      // toggle between default and bright frames
795                 }
796
797                 if ( HUD_wingman_flash_is_bright & (1<<index) ) {
798                         draw_bright=1;
799                 }
800         }
801
802         return draw_bright;
803 }
804
805 int hud_wingman_status_wing_pos(int shipnum, int wing_status_index, wing *wingp)
806 {
807         int i, wing_pos = -1;
808
809         for (i = 0; i < wingp->wave_count; i++) {
810                 if ( wingp->ship_index[i] == shipnum ) {
811                         wing_pos = i;
812                         break;
813                 }
814         }
815
816         return wing_pos;
817 }
818
819 void hud_wingman_status_set_index(int shipnum)
820 {
821         int     wing_index, wing_pos;
822         ship    *shipp;
823         wing    *wingp;
824
825         if ( shipnum < 0 ) {
826                 return;
827         }
828
829         shipp = &Ships[shipnum];
830
831         if ( shipp->wingnum < 0 ) {
832                 return;
833         }
834
835         wingp = &Wings[shipp->wingnum];
836
837         // Check for Alpha, Beta, Gamma, Delta or Epsilon wings
838         wing_index = hud_wingman_status_wing_index(wingp->name);
839         if ( wing_index < 0 ) {
840                 return;
841         }
842
843         shipp->wing_status_wing_index = (char)wing_index;
844
845         wing_pos = hud_wingman_status_wing_pos(shipnum, wing_index, wingp);
846
847         shipp->wing_status_wing_pos = (char)wing_pos;
848 }
849
850 void hudwingmanstatus_page_in()
851 {
852         int i;
853         for ( i = 0; i < HUD_WINGMAN_STATUS_NUM_FRAMES; i++ ) {
854                 bm_page_in_aabitmap( Wingman_status_frames[i].first_frame, Wingman_status_frames[i].num_frames );
855         }
856 }
857
858 int get_blip_bitmap()
859 {
860         return Wingman_status_frames[WINGMAN_STATUS_DOTS].first_frame+1;
861 }
862