2 * $Logfile: /Freespace2/code/Hud/HUDescort.cpp $
7 * C module for managing and displaying ships that are in an escort
10 * Revision 1.1 2002/05/03 03:28:09 root
14 * 22 8/04/99 2:24a Dave
15 * Fixed escort gauge ordering for dogfight.
17 * 21 7/30/99 7:01p Dave
18 * Dogfight escort gauge. Fixed up laser rendering in Glide.
20 * 20 7/29/99 1:57p Jefff
21 * Fixed location of "D" for disabled ships in hi-res
23 * 19 7/22/99 7:49p Dave
24 * Show enemy ships on the escort list in red.
26 * 18 6/23/99 10:13p Andsager
27 * Fix Baranec hud escort default color bug!
29 * 17 6/10/99 3:43p Dave
30 * Do a better job of syncing text colors to HUD gauges.
32 * 16 5/24/99 11:28a Dave
33 * Sexpression for adding/removing ships from the hud escort list.
35 * 15 3/30/99 5:40p Dave
36 * Fixed reinforcements for TvT in multiplayer.
38 * 14 3/19/99 9:51a Dave
39 * Checkin to repair massive source safe crash. Also added support for
40 * pof-style nebulae, and some new weapons code.
42 * 14 3/12/99 4:24p Andsager
43 * Fix bug where two or more ships are culled from escort list same frame
45 * 13 3/04/99 9:22a Andsager
46 * Make escort list work with ship-is-visible. When not visible, dump,
47 * when becoming visible, maybe add.
49 * 12 3/02/99 12:27p Andsager
50 * Fixed bug in hud_add_ship_to_escort -- multiple entries and
51 * uninitialized entries.
53 * 11 3/02/99 11:45a Anoop
54 * put in assert for escort list
56 * 10 3/01/99 12:00p Andsager
57 * Fix escort priority to look at newly added ships.
59 * 9 2/03/99 6:13p Andsager
60 * Added priorities to escort list. Folded escort hit info into
63 * 8 2/01/99 9:47a Jasen
64 * Tweaked coords for the monitoring window in hi res.
66 * 7 1/30/99 7:48p Jasen
68 * 6 1/07/99 9:07a Jasen
71 * 5 12/28/98 3:17p Dave
72 * Support for multiple hud bitmap filenames for hi-res mode.
84 #include "hudtarget.h"
85 #include "hudtargetbox.h"
87 #include "freespace.h"
90 #include "hudshield.h"
92 #include "hudescort.h"
94 #include "alphacolors.h"
96 #include "multiutil.h"
100 typedef struct escort_info
103 int obj_signature; // so we are sure we have a valid objnum
104 int priority; // higher priority is higher in the list
105 short np_id; // netplayer id (for multiplayer dogfight mode)
106 shield_hit_info hit_info;
109 escort_info Escort_ships[MAX_ESCORT_SHIPS];
110 int Num_escort_ships;
113 // size of complete escort list, including all those wanting to get onto list but without space
114 #define MAX_COMPLETE_ESCORT_LIST 20
117 #define NUM_ESCORT_FRAMES 3
118 hud_frames Escort_gauges[NUM_ESCORT_FRAMES];
119 int Escort_gauges_loaded = 0;
121 int Escort_gauge_y[MAX_ESCORT_SHIPS] = { 219, 230, 241 };
124 int Escort_gauge_text_coords[GR_NUM_RESOLUTIONS][MAX_ESCORT_SHIPS][4][2] =
168 // escort gauge coords
169 int Escort_coords[GR_NUM_RESOLUTIONS][4][2] = {
184 // monitoring text coords
185 int Monitoring_coords[GR_NUM_RESOLUTIONS][2] = {
194 char *Escort_gauge_filenames[GR_NUM_RESOLUTIONS][MAX_ESCORT_SHIPS] =
210 static int Last_target_index; // index into Escort_gauges for last targeted via 'Next Escort Target' key
212 // data needed from HUDshield.cpp
213 extern hud_frames Shield_mini_gauge;
215 // called from HUD init, loads the bitmap data in once, and resets any data for each level
216 void hud_escort_init()
220 if ( !Escort_gauges_loaded ) {
221 for ( i = 0; i < MAX_ESCORT_SHIPS; i++ ) {
222 Escort_gauges[i].first_frame = bm_load_animation(Escort_gauge_filenames[gr_screen.res][i], &Escort_gauges[i].num_frames);
223 if ( Escort_gauges[i].first_frame == -1 ) {
224 Warning(LOCATION, "Could not load in ani: %s\n", Escort_gauge_filenames[gr_screen.res][i]);
228 Escort_gauges_loaded = 1;
231 Last_target_index = -1;
234 // ----------------------------------------------------------------------
235 // hud_escort_clear_all()
237 void hud_escort_clear_all()
241 Num_escort_ships = 0;
242 for ( i = 0; i < MAX_ESCORT_SHIPS; i++ ) {
243 Escort_ships[i].obj_signature = -99;
244 Escort_ships[i].np_id = -1;
245 shield_info_reset(&Escort_ships[i].hit_info);
249 // internal helper function for sort.
250 // sorts first by priority number and then alphabetically
251 int escort_compare_func(const void *e1, const void *e2)
253 escort_info *escort1, *escort2;
257 escort1 = (escort_info*) e1;
258 escort2 = (escort_info*) e2;
260 // multiplayer dogfight
261 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)){
264 n1 = find_player_id(escort1->np_id);
265 n2 = find_player_id(escort2->np_id);
266 if((n1 < 0) || (n2 < 0) || (Net_players[n1].player == NULL) || (Net_players[n2].player == NULL)){
269 // player 1 is higher than player 2
270 if(Net_players[n1].player->stats.m_kill_count_ok >= Net_players[n2].player->stats.m_kill_count_ok){
277 diff = escort2->priority - escort1->priority;
283 name1 = Ships[Objects[escort1->objnum].instance].ship_name;
284 name2 = Ships[Objects[escort2->objnum].instance].ship_name;
286 ret = stricmp(name1, name2);
293 // create complete priority sorted escort list for all active ships
294 // escorts - array of escort info
295 // num_escorts - number of escorts requests in field of active ships
296 // This will be culled to MAX_ESCORTS, selecting the top set from escorts
297 void hud_create_complete_escort_list(escort_info *escorts, int *num_escorts)
303 // start with none on list
306 // multiplayer dogfight
307 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)){
308 for(idx=0; idx<MAX_PLAYERS; idx++){
309 // break out of the loop when we have reached our max
310 if ( *num_escorts == MAX_COMPLETE_ESCORT_LIST ) {
311 mprintf(("exceeded max ships in big escort list"));
315 // is this a valid player
316 if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_OBSERVER(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx])){
318 escorts[*num_escorts].objnum = -1;
319 escorts[*num_escorts].obj_signature = -1;
320 escorts[*num_escorts].priority = -1;
321 escorts[*num_escorts].np_id = Net_players[idx].player_id;
328 for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
329 Assert( so->objnum >= 0 && so->objnum < MAX_OBJECTS);
330 if((so->objnum < 0) || (so->objnum >= MAX_OBJECTS)){
333 objp = &Objects[so->objnum];
334 Assert( objp->type == OBJ_SHIP );
335 if(objp->type != OBJ_SHIP){
339 // break out of the loop when we have reached our max
340 if ( *num_escorts == MAX_COMPLETE_ESCORT_LIST ) {
341 mprintf(("exceeded max ships in big escort list"));
345 // only process ships that might be on the list
346 if ( !(Ships[objp->instance].flags & SF_ESCORT) ){
350 // only process ships that can be seen by sensors
351 if ( (Ships[objp->instance].flags & SF_HIDDEN_FROM_SENSORS) ){
355 // don't process ships that are dying, or objects that should be dead
356 if ( (Ships[objp->instance].flags & (SF_DYING|SF_DEPARTING)) || (objp->flags & OF_SHOULD_BE_DEAD) ){
361 escorts[*num_escorts].objnum = so->objnum;
362 escorts[*num_escorts].obj_signature = objp->signature;
363 escorts[*num_escorts].priority = Ships[objp->instance].escort_priority;
364 escorts[*num_escorts].np_id = -1;
371 // ----------------------------------------------------------------------
372 // hud_init_escort_info()
374 // Set up the escort list
376 void hud_setup_escort_list(int level)
378 int num_escorts, num_complete_escorts;
379 escort_info complete_escorts[MAX_COMPLETE_ESCORT_LIST];
381 hud_escort_clear_all();
383 // get complete escort list
384 hud_create_complete_escort_list(complete_escorts, &num_complete_escorts);
386 // sort escort list by priority
387 qsort(complete_escorts, num_complete_escorts, sizeof(escort_info), escort_compare_func);
389 // set number in escort list
390 num_escorts = num_complete_escorts;
391 if (num_escorts > MAX_ESCORT_SHIPS) {
392 num_escorts = MAX_ESCORT_SHIPS;
395 // add ships to escort list
396 for (Num_escort_ships=0; Num_escort_ships<num_escorts; Num_escort_ships++) {
397 Escort_ships[Num_escort_ships].obj_signature = complete_escorts[Num_escort_ships].obj_signature;
398 Escort_ships[Num_escort_ships].priority = complete_escorts[Num_escort_ships].priority;
399 Escort_ships[Num_escort_ships].objnum = complete_escorts[Num_escort_ships].objnum;
400 Escort_ships[Num_escort_ships].np_id = complete_escorts[Num_escort_ships].np_id;
404 Show_escort_view = 1;
409 // combine complete escort list with Escort_ships, keeping valid hit info
410 void merge_escort_lists(escort_info *complete_escorts, int num_complete_escorts)
412 int i, j, top_complete_escorts;
413 int valid_hit_info[MAX_ESCORT_SHIPS];
415 // may be > 1 ship change to list (ie, 2 or 3 culled during same frame)
416 // set Num_escort_ships and cap
417 Num_escort_ships = num_complete_escorts;
418 if (Num_escort_ships > MAX_ESCORT_SHIPS) {
419 Num_escort_ships = MAX_ESCORT_SHIPS;
423 if (Num_escort_ships == 0) {
427 // check used as a flag whether top slots in complete_escorts were copied
428 // this is important re. hit info
429 for (i=0; i<MAX_ESCORT_SHIPS; i++) {
430 valid_hit_info[i] = 0;
433 // get the top slots in complete escort list that will be copied onto Escort_ships
434 top_complete_escorts = num_complete_escorts;
435 if (top_complete_escorts > MAX_ESCORT_SHIPS) {
436 top_complete_escorts = MAX_ESCORT_SHIPS;
439 // copy for Escort_ships to complete_escorts to retain hit_info
440 if(!((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT))){
441 for (i=0; i<top_complete_escorts; i++) {
442 for (j=0; j<Num_escort_ships; j++) {
443 if (Escort_ships[j].obj_signature == complete_escorts[i].obj_signature) {
444 complete_escorts[i] = Escort_ships[j];
445 valid_hit_info[i] = 1;
451 // copy top slots to Escort_ships
452 for (i=0; i<top_complete_escorts; i++) {
453 Escort_ships[i] = complete_escorts[i];
454 // check all ships are valid
455 int objnum = Escort_ships[i].objnum;
456 Assert( objnum >=0 && objnum < MAX_OBJECTS );
457 if((objnum < 0) || (objnum >= MAX_OBJECTS)){
460 if ( !valid_hit_info[i] ) {
461 shield_info_reset(&Escort_ships[i].hit_info);
466 // reset Num_escort_ships
467 Num_escort_ships = top_complete_escorts;
471 // ----------------------------------------------------------------------
472 // hud_remove_ship_from_escort_index()
474 // Take a ship out of the escort list
475 void hud_remove_ship_from_escort_index(int dead_index, int objnum)
477 int i, count, num_complete_escorts;
478 escort_info bakup_arr[MAX_ESCORT_SHIPS], complete_escorts[MAX_COMPLETE_ESCORT_LIST];
480 // remove him from escort list
481 if((objnum >= 0) && (Objects[objnum].type == OBJ_SHIP) && (Objects[objnum].instance >= 0)){
482 Ships[Objects[objnum].instance].flags &= ~SF_ESCORT;
486 for ( i = 0; i < Num_escort_ships; i++ ) {
487 if ( i != dead_index ) {
488 bakup_arr[count++] = Escort_ships[i];
492 for ( i = 0; i < count; i++ ) {
493 Escort_ships[i] = bakup_arr[i];
497 Assert(Num_escort_ships >= 0);
499 // get complete escort list
500 hud_create_complete_escort_list(complete_escorts, &num_complete_escorts);
502 // sort escort list by priority
503 qsort(complete_escorts, num_complete_escorts, sizeof(escort_info), escort_compare_func);
506 merge_escort_lists(complete_escorts, num_complete_escorts);
508 hud_gauge_popup_start(HUD_ESCORT_VIEW);
512 // called once per frame to remove dead or departed ships from the escort list
513 void hud_escort_cull_list()
515 int i, objnum, np_index;
517 // multiplayer dogfight
518 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)){
519 for ( i = 0; i < Num_escort_ships; i++ ) {
520 np_index = find_player_id(Escort_ships[i].np_id);
522 // maybe remove him if he left
523 if ( np_index < 0 ) {
524 hud_remove_ship_from_escort_index(i, -1);
531 for ( i = 0; i < Num_escort_ships; i++ ) {
532 objnum = Escort_ships[i].objnum;
533 Assert( objnum >=0 && objnum < MAX_OBJECTS );
534 if ( Objects[objnum].flags & OF_SHOULD_BE_DEAD || Ships[Objects[objnum].instance].flags & SF_HIDDEN_FROM_SENSORS ) {
535 hud_remove_ship_from_escort_index(i, objnum);
542 // Set the color for the text to be displayed
543 int hud_escort_set_gauge_color(int index, int friendly)
546 shield_hit_info *shi;
548 shi = &Escort_ships[index].hit_info;
550 // multiplayer dogfight
551 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)){
552 hud_set_gauge_color(HUD_ESCORT_VIEW);
557 hud_set_gauge_color(HUD_ESCORT_VIEW, HUD_C_DIM);
559 gr_set_color_fast(&Color_red);
562 // set flashing color
563 if ( !timestamp_elapsed(shi->shield_hit_timers[HULL_HIT_OFFSET]) ) {
564 if ( timestamp_elapsed(shi->shield_hit_next_flash[HULL_HIT_OFFSET]) ) {
565 shi->shield_hit_next_flash[HULL_HIT_OFFSET] = timestamp(SHIELD_FLASH_INTERVAL);
566 shi->shield_show_bright ^= (1<<HULL_HIT_OFFSET); // toggle between default and bright frames
570 if ( shi->shield_show_bright & (1<<HULL_HIT_OFFSET) ) {
572 hud_set_gauge_color(HUD_ESCORT_VIEW, HUD_C_BRIGHT);
574 gr_set_color_fast(&Color_bright_red);
578 hud_set_gauge_color(HUD_ESCORT_VIEW, HUD_C_DIM);
580 gr_set_color_fast(&Color_dim_red);
588 // draw the shield icon and integrity for the escort ship
589 void hud_escort_show_icon(int index, object *objp)
591 float shields, integrity;
592 int screen_integrity, offset;
596 shield_hit_info *shi;
598 // multiplayer dogfight code should never get into here
599 Assert(!((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)));
600 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)){
604 sp = &Ships[objp->instance];
605 sip = &Ship_info[sp->ship_info_index];
606 shi = &Escort_ships[index].hit_info;
608 // determine if its "friendly" or not
609 if(Player_ship != NULL){
610 hud_escort_set_gauge_color(index, (sp->team == Player_ship->team) ? 1 : 0);
612 hud_escort_set_gauge_color(index, 1);
615 // draw a 'D' if a ship is disabled
616 if ( (sp->flags & SF_DISABLED) || (ship_subsys_disrupted(sp, SUBSYSTEM_ENGINE)) ) {
617 emp_hud_string( Escort_gauge_text_coords[gr_screen.res][index][3][0], Escort_gauge_text_coords[gr_screen.res][index][3][1], EG_NULL, XSTR( "D", 284));
620 // print out ship name
621 strcpy(buf, sp->ship_name);
622 gr_force_fit_string(buf, 255, 100);
624 emp_hud_string( Escort_gauge_text_coords[gr_screen.res][index][0][0], Escort_gauge_text_coords[gr_screen.res][index][0][1], EG_ESCORT1 + index, buf);
626 // show ship integrity
627 hud_get_target_strength(objp, &shields, &integrity);
628 screen_integrity = fl2i(integrity*100 + 0.5f);
630 if ( screen_integrity < 100 ) {
632 if ( screen_integrity == 0 ) {
633 if ( integrity > 0 ) {
634 screen_integrity = 1;
638 emp_hud_printf( Escort_gauge_text_coords[gr_screen.res][index][2][0]+offset, Escort_gauge_text_coords[gr_screen.res][index][2][1], EG_NULL, "%d", screen_integrity);
641 // multiplayer dogfight
642 void hud_escort_show_icon_dogfight(int index)
644 int hull_integrity = 100;
652 // always use the standard color to avoid confusion
653 hud_set_gauge_color(HUD_ESCORT_VIEW);
656 np_index = find_player_id(Escort_ships[index].np_id);
657 if((np_index < 0) || (np_index >= MAX_PLAYERS) || (Net_players[np_index].player == NULL)){
661 // print out player name
662 strcpy(buf, Net_players[np_index].player->callsign);
663 gr_force_fit_string(buf, 255, 100 - stat_shift);
664 emp_hud_string( Escort_gauge_text_coords[gr_screen.res][index][0][0], Escort_gauge_text_coords[gr_screen.res][index][0][1], EG_ESCORT1 + index, buf);
666 // can we get the player object?
668 if((Net_players[np_index].player->objnum >= 0) && (Net_players[np_index].player->objnum < MAX_OBJECTS) && (Objects[Net_players[np_index].player->objnum].type == OBJ_SHIP)){
669 objp = &Objects[Net_players[np_index].player->objnum];
670 if((objp->instance >= 0) && (objp->instance < MAX_SHIPS) && (Ships[objp->instance].ship_info_index >= 0) && (Ships[objp->instance].ship_info_index < MAX_SHIPS)){
671 sip = &Ship_info[Ships[objp->instance].ship_info_index];
676 hull_integrity = (int)(((float)objp->hull_strength / (float)sip->initial_hull_strength) * 100.0f);
677 if(hull_integrity < 0){
682 // show ship integrity
684 emp_hud_printf( Escort_gauge_text_coords[gr_screen.res][index][2][0] - stat_shift, Escort_gauge_text_coords[gr_screen.res][index][2][1], EG_NULL, "%d", Net_players[np_index].player->stats.m_kill_count_ok);
686 emp_hud_printf( Escort_gauge_text_coords[gr_screen.res][index][2][0] - stat_shift, Escort_gauge_text_coords[gr_screen.res][index][2][1], EG_NULL, "(%d%%) %d", hull_integrity, Net_players[np_index].player->stats.m_kill_count_ok);
691 // ----------------------------------------------------------------------
692 // hud_display_escort()
694 // Display the data on ships in the escort list
695 void hud_display_escort()
700 if ( !Show_escort_view ) {
704 if ( !Num_escort_ships ) {
708 // hud_set_default_color();
709 hud_set_gauge_color(HUD_ESCORT_VIEW);
711 // draw the top of the escort view
712 GR_AABITMAP(Escort_gauges[0].first_frame, Escort_coords[gr_screen.res][0][0], Escort_coords[gr_screen.res][0][1]);
713 gr_string(Monitoring_coords[gr_screen.res][0], Monitoring_coords[gr_screen.res][1], XSTR( "monitoring", 285));
715 if ( Num_escort_ships >= 2 ) {
716 GR_AABITMAP(Escort_gauges[1].first_frame, Escort_coords[gr_screen.res][1][0], Escort_coords[gr_screen.res][1][1]);
719 if ( Num_escort_ships >= 3 ) {
720 GR_AABITMAP(Escort_gauges[1].first_frame, Escort_coords[gr_screen.res][2][0], Escort_coords[gr_screen.res][2][1]);
723 // draw bottom of box
724 GR_AABITMAP(Escort_gauges[2].first_frame, Escort_coords[gr_screen.res][3][0], Escort_coords[gr_screen.res][Num_escort_ships][1]);
726 // multiplayer dogfight
727 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)){
728 // draw the escort ship data
729 for ( i = 0; i < Num_escort_ships; i++ ) {
730 // oops. only show top 3
736 hud_escort_show_icon_dogfight(i);
741 // draw the escort ship data
742 for ( i = 0; i < Num_escort_ships; i++ ) {
743 objp = &Objects[Escort_ships[i].objnum];
744 hud_escort_show_icon(i, objp);
749 // ----------------------------------------------------------------------
750 // hud_escort_view_toggle()
752 void hud_escort_view_toggle()
754 Show_escort_view ^= 1;
755 if ( Show_escort_view ) {
756 HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Escort view enabled", 286));
758 HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Escort view disabled", 287));
762 // try to add a ship to the escort list, if slot available
763 void hud_add_ship_to_escort(int objnum, int supress_feedback)
765 escort_info complete_escorts[MAX_COMPLETE_ESCORT_LIST];
766 int num_complete_escorts, idx, found;
768 // get complete escort list
769 hud_create_complete_escort_list(complete_escorts, &num_complete_escorts);
771 // check if ship is already on complete escort list
773 for (idx=0; idx<num_complete_escorts; idx++) {
774 if (complete_escorts[idx].obj_signature == Objects[objnum].signature) {
780 // add new ship into complete list
782 complete_escorts[num_complete_escorts].objnum = objnum;
783 complete_escorts[num_complete_escorts].obj_signature = Objects[objnum].signature;
784 complete_escorts[num_complete_escorts].priority = Ships[Objects[objnum].instance].escort_priority;
786 // remove him from escort list
787 Ships[Objects[objnum].instance].flags |= SF_ESCORT;
789 num_complete_escorts++;
792 // sort escort list by priority
793 qsort(complete_escorts, num_complete_escorts, sizeof(escort_info), escort_compare_func);
796 merge_escort_lists(complete_escorts, num_complete_escorts);
799 if ( (Num_escort_ships == MAX_ESCORT_SHIPS) && !supress_feedback) {
801 // search thru list for objnum
802 for (idx=0; idx<Num_escort_ships; idx++) {
803 if (Escort_ships[idx].objnum == objnum) {
810 HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Escort list is full with %d ships", 288), Num_escort_ships);
811 snd_play( &Snds[SND_TARGET_FAIL]);
815 hud_gauge_popup_start(HUD_ESCORT_VIEW);
819 // ----------------------------------------------------------------------
820 // hud_add_remove_ship_escort()
822 void hud_add_remove_ship_escort(int objnum, int supress_feedback)
826 // no ships on the escort list in multiplayer dogfight
827 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)){
836 if ( Objects[objnum].type != OBJ_SHIP ) {
837 if ( !supress_feedback ) {
838 snd_play( &Snds[SND_TARGET_FAIL]);
844 for ( i = 0; i < Num_escort_ships; i++ ) {
845 if ( Escort_ships[i].obj_signature == Objects[objnum].signature ) {
852 hud_remove_ship_from_escort_index(i, objnum);
856 hud_add_ship_to_escort(objnum, supress_feedback);
859 void hud_remove_ship_from_escort(int objnum)
863 // no ships on the escort list in multiplayer dogfight
864 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)){
874 for ( i = 0; i < Num_escort_ships; i++ ) {
875 if ( Escort_ships[i].obj_signature == Objects[objnum].signature ) {
882 hud_remove_ship_from_escort_index(i, objnum);
887 // Called whenever a ship is hit to determine if that ship is in the escort list. If it
888 // is, then start timers to flash the name hull/shield icon for that ship.
889 void hud_escort_ship_hit(object *objp, int quadrant)
892 shield_hit_info *shi;
894 // no ships on the escort list in multiplayer dogfight
895 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)){
899 for ( i = 0; i < Num_escort_ships; i++ ) {
900 if ( Escort_ships[i].objnum == OBJ_INDEX(objp) ) {
901 shi = &Escort_ships[i].hit_info;
902 num = Quadrant_xlate[quadrant];
903 hud_gauge_popup_start(HUD_ESCORT_VIEW);
904 if ( quadrant >= 0 ) {
905 shi->shield_hit_timers[num] = timestamp(SHIELD_HIT_DURATION);
907 shi->shield_hit_timers[HULL_HIT_OFFSET] = timestamp(SHIELD_HIT_DURATION);
913 // target the next ship in the escort list
914 void hud_escort_target_next()
918 if ( Num_escort_ships == 0 ) {
919 snd_play( &Snds[SND_TARGET_FAIL], 0.0f );
924 if ( Last_target_index >= Num_escort_ships ) {
925 Last_target_index = 0;
928 objnum = Escort_ships[Last_target_index].objnum;
929 set_target_objnum( Player_ai, objnum);
930 hud_restore_subsystem_target(&Ships[Objects[objnum].instance]);
933 // return the number of ships currently on the escort list
934 int hud_escort_num_ships_on_list()
936 return Num_escort_ships;
939 // Return the object number for the ship at index position in the escort list
940 int hud_escort_return_objnum(int index)
942 int escort_objnum, escort_sig;
943 if ( index >= Num_escort_ships ) {
947 escort_objnum = Escort_ships[index].objnum;
948 escort_sig = Escort_ships[index].obj_signature;
950 if ( escort_objnum < 0 ) {
954 // ensure this is still a valid index
955 if ( Objects[escort_objnum].signature != escort_sig ) {
959 return Escort_ships[index].objnum;
963 void hudescort_page_in()
967 for ( i = 0; i < MAX_ESCORT_SHIPS; i++ ) {
968 bm_page_in_aabitmap( Escort_gauges[i].first_frame, Escort_gauges[i].num_frames);
972 void hud_escort_add_player(short id)
974 Assert(Game_mode & GM_MULTIPLAYER);
975 if(!(Game_mode & GM_MULTIPLAYER)){
981 // just go through and add as long as its not a duplicate
982 for(idx=0; idx<Num_escort_ships; idx++){
983 if(Escort_ships[idx].np_id == id){
988 // re-setup the escort list
989 hud_setup_escort_list(0);
992 void hud_escort_remove_player(short id)
994 Assert(Game_mode & GM_MULTIPLAYER);
995 if(!(Game_mode & GM_MULTIPLAYER)){
1001 // find the instance and remove it if possible
1002 for(idx=0; idx<Num_escort_ships; idx++){
1003 if(Escort_ships[idx].np_id == id){
1004 hud_remove_ship_from_escort_index(idx, -1);