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