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