2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
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
10 * $Logfile: /Freespace2/code/Hud/HUDescort.cpp $
15 * C module for managing and displaying ships that are in an escort
18 * Revision 1.3 2002/06/09 04:41:21 relnev
19 * added copyright header
21 * Revision 1.2 2002/05/07 03:16:45 theoddone33
22 * The Great Newline Fix
24 * Revision 1.1.1.1 2002/05/03 03:28:09 root
28 * 22 8/04/99 2:24a Dave
29 * Fixed escort gauge ordering for dogfight.
31 * 21 7/30/99 7:01p Dave
32 * Dogfight escort gauge. Fixed up laser rendering in Glide.
34 * 20 7/29/99 1:57p Jefff
35 * Fixed location of "D" for disabled ships in hi-res
37 * 19 7/22/99 7:49p Dave
38 * Show enemy ships on the escort list in red.
40 * 18 6/23/99 10:13p Andsager
41 * Fix Baranec hud escort default color bug!
43 * 17 6/10/99 3:43p Dave
44 * Do a better job of syncing text colors to HUD gauges.
46 * 16 5/24/99 11:28a Dave
47 * Sexpression for adding/removing ships from the hud escort list.
49 * 15 3/30/99 5:40p Dave
50 * Fixed reinforcements for TvT in multiplayer.
52 * 14 3/19/99 9:51a Dave
53 * Checkin to repair massive source safe crash. Also added support for
54 * pof-style nebulae, and some new weapons code.
56 * 14 3/12/99 4:24p Andsager
57 * Fix bug where two or more ships are culled from escort list same frame
59 * 13 3/04/99 9:22a Andsager
60 * Make escort list work with ship-is-visible. When not visible, dump,
61 * when becoming visible, maybe add.
63 * 12 3/02/99 12:27p Andsager
64 * Fixed bug in hud_add_ship_to_escort -- multiple entries and
65 * uninitialized entries.
67 * 11 3/02/99 11:45a Anoop
68 * put in assert for escort list
70 * 10 3/01/99 12:00p Andsager
71 * Fix escort priority to look at newly added ships.
73 * 9 2/03/99 6:13p Andsager
74 * Added priorities to escort list. Folded escort hit info into
77 * 8 2/01/99 9:47a Jasen
78 * Tweaked coords for the monitoring window in hi res.
80 * 7 1/30/99 7:48p Jasen
82 * 6 1/07/99 9:07a Jasen
85 * 5 12/28/98 3:17p Dave
86 * Support for multiple hud bitmap filenames for hi-res mode.
98 #include "hudtarget.h"
99 #include "hudtargetbox.h"
101 #include "freespace.h"
104 #include "hudshield.h"
106 #include "hudescort.h"
108 #include "alphacolors.h"
110 #include "multiutil.h"
112 int Show_escort_view;
114 typedef struct escort_info
117 int obj_signature; // so we are sure we have a valid objnum
118 int priority; // higher priority is higher in the list
119 short np_id; // netplayer id (for multiplayer dogfight mode)
120 shield_hit_info hit_info;
123 escort_info Escort_ships[MAX_ESCORT_SHIPS];
124 int Num_escort_ships;
127 // size of complete escort list, including all those wanting to get onto list but without space
128 #define MAX_COMPLETE_ESCORT_LIST 20
131 #define NUM_ESCORT_FRAMES 3
132 hud_frames Escort_gauges[NUM_ESCORT_FRAMES];
133 int Escort_gauges_loaded = 0;
135 int Escort_gauge_y[MAX_ESCORT_SHIPS] = { 219, 230, 241 };
138 int Escort_gauge_text_coords[GR_NUM_RESOLUTIONS][MAX_ESCORT_SHIPS][4][2] =
182 // escort gauge coords
183 int Escort_coords[GR_NUM_RESOLUTIONS][4][2] = {
198 // monitoring text coords
199 int Monitoring_coords[GR_NUM_RESOLUTIONS][2] = {
208 const char *Escort_gauge_filenames[GR_NUM_RESOLUTIONS][MAX_ESCORT_SHIPS] =
224 static int Last_target_index; // index into Escort_gauges for last targeted via 'Next Escort Target' key
226 // data needed from HUDshield.cpp
227 extern hud_frames Shield_mini_gauge;
229 // called from HUD init, loads the bitmap data in once, and resets any data for each level
230 void hud_escort_init()
234 if ( !Escort_gauges_loaded ) {
235 for ( i = 0; i < MAX_ESCORT_SHIPS; i++ ) {
236 Escort_gauges[i].first_frame = bm_load_animation(Escort_gauge_filenames[gr_screen.res][i], &Escort_gauges[i].num_frames);
237 if ( Escort_gauges[i].first_frame == -1 ) {
238 Warning(LOCATION, "Could not load in ani: %s\n", Escort_gauge_filenames[gr_screen.res][i]);
242 Escort_gauges_loaded = 1;
245 Last_target_index = -1;
248 // ----------------------------------------------------------------------
249 // hud_escort_clear_all()
251 void hud_escort_clear_all()
255 Num_escort_ships = 0;
256 for ( i = 0; i < MAX_ESCORT_SHIPS; i++ ) {
257 Escort_ships[i].obj_signature = -99;
258 Escort_ships[i].np_id = -1;
259 shield_info_reset(&Escort_ships[i].hit_info);
263 // internal helper function for sort.
264 // sorts first by priority number and then alphabetically
265 int escort_compare_func(const void *e1, const void *e2)
267 escort_info *escort1, *escort2;
271 escort1 = (escort_info*) e1;
272 escort2 = (escort_info*) e2;
274 // multiplayer dogfight
275 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)){
278 n1 = find_player_id(escort1->np_id);
279 n2 = find_player_id(escort2->np_id);
280 if((n1 < 0) || (n2 < 0) || (Net_players[n1].player == NULL) || (Net_players[n2].player == NULL)){
283 // player 1 is higher than player 2
284 if(Net_players[n1].player->stats.m_kill_count_ok >= Net_players[n2].player->stats.m_kill_count_ok){
291 diff = escort2->priority - escort1->priority;
297 name1 = Ships[Objects[escort1->objnum].instance].ship_name;
298 name2 = Ships[Objects[escort2->objnum].instance].ship_name;
300 ret = SDL_strcasecmp(name1, name2);
307 // create complete priority sorted escort list for all active ships
308 // escorts - array of escort info
309 // num_escorts - number of escorts requests in field of active ships
310 // This will be culled to MAX_ESCORTS, selecting the top set from escorts
311 void hud_create_complete_escort_list(escort_info *escorts, int *num_escorts)
317 // start with none on list
320 // multiplayer dogfight
321 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)){
322 for(idx=0; idx<MAX_PLAYERS; idx++){
323 // break out of the loop when we have reached our max
324 if ( *num_escorts == MAX_COMPLETE_ESCORT_LIST ) {
325 mprintf(("exceeded max ships in big escort list"));
329 // is this a valid player
330 if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_OBSERVER(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx])){
332 escorts[*num_escorts].objnum = -1;
333 escorts[*num_escorts].obj_signature = -1;
334 escorts[*num_escorts].priority = -1;
335 escorts[*num_escorts].np_id = Net_players[idx].player_id;
342 for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
343 SDL_assert( so->objnum >= 0 && so->objnum < MAX_OBJECTS);
344 if((so->objnum < 0) || (so->objnum >= MAX_OBJECTS)){
347 objp = &Objects[so->objnum];
348 SDL_assert( objp->type == OBJ_SHIP );
349 if(objp->type != OBJ_SHIP){
353 // break out of the loop when we have reached our max
354 if ( *num_escorts == MAX_COMPLETE_ESCORT_LIST ) {
355 mprintf(("exceeded max ships in big escort list"));
359 // only process ships that might be on the list
360 if ( !(Ships[objp->instance].flags & SF_ESCORT) ){
364 // only process ships that can be seen by sensors
365 if ( (Ships[objp->instance].flags & SF_HIDDEN_FROM_SENSORS) ){
369 // don't process ships that are dying, or objects that should be dead
370 if ( (Ships[objp->instance].flags & (SF_DYING|SF_DEPARTING)) || (objp->flags & OF_SHOULD_BE_DEAD) ){
375 escorts[*num_escorts].objnum = so->objnum;
376 escorts[*num_escorts].obj_signature = objp->signature;
377 escorts[*num_escorts].priority = Ships[objp->instance].escort_priority;
378 escorts[*num_escorts].np_id = -1;
385 // ----------------------------------------------------------------------
386 // hud_init_escort_info()
388 // Set up the escort list
390 void hud_setup_escort_list(int level)
392 int num_escorts, num_complete_escorts;
393 escort_info complete_escorts[MAX_COMPLETE_ESCORT_LIST];
395 hud_escort_clear_all();
397 // get complete escort list
398 hud_create_complete_escort_list(complete_escorts, &num_complete_escorts);
400 // sort escort list by priority
401 qsort(complete_escorts, num_complete_escorts, sizeof(escort_info), escort_compare_func);
403 // set number in escort list
404 num_escorts = num_complete_escorts;
405 if (num_escorts > MAX_ESCORT_SHIPS) {
406 num_escorts = MAX_ESCORT_SHIPS;
409 // add ships to escort list
410 for (Num_escort_ships=0; Num_escort_ships<num_escorts; Num_escort_ships++) {
411 Escort_ships[Num_escort_ships].obj_signature = complete_escorts[Num_escort_ships].obj_signature;
412 Escort_ships[Num_escort_ships].priority = complete_escorts[Num_escort_ships].priority;
413 Escort_ships[Num_escort_ships].objnum = complete_escorts[Num_escort_ships].objnum;
414 Escort_ships[Num_escort_ships].np_id = complete_escorts[Num_escort_ships].np_id;
418 Show_escort_view = 1;
423 // combine complete escort list with Escort_ships, keeping valid hit info
424 void merge_escort_lists(escort_info *complete_escorts, int num_complete_escorts)
426 int i, j, top_complete_escorts;
427 int valid_hit_info[MAX_ESCORT_SHIPS];
429 // may be > 1 ship change to list (ie, 2 or 3 culled during same frame)
430 // set Num_escort_ships and cap
431 Num_escort_ships = num_complete_escorts;
432 if (Num_escort_ships > MAX_ESCORT_SHIPS) {
433 Num_escort_ships = MAX_ESCORT_SHIPS;
437 if (Num_escort_ships == 0) {
441 // check used as a flag whether top slots in complete_escorts were copied
442 // this is important re. hit info
443 for (i=0; i<MAX_ESCORT_SHIPS; i++) {
444 valid_hit_info[i] = 0;
447 // get the top slots in complete escort list that will be copied onto Escort_ships
448 top_complete_escorts = num_complete_escorts;
449 if (top_complete_escorts > MAX_ESCORT_SHIPS) {
450 top_complete_escorts = MAX_ESCORT_SHIPS;
453 // copy for Escort_ships to complete_escorts to retain hit_info
454 if(!((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT))){
455 for (i=0; i<top_complete_escorts; i++) {
456 for (j=0; j<Num_escort_ships; j++) {
457 if (Escort_ships[j].obj_signature == complete_escorts[i].obj_signature) {
458 complete_escorts[i] = Escort_ships[j];
459 valid_hit_info[i] = 1;
465 // copy top slots to Escort_ships
466 for (i=0; i<top_complete_escorts; i++) {
467 Escort_ships[i] = complete_escorts[i];
468 // check all ships are valid
469 int objnum = Escort_ships[i].objnum;
470 SDL_assert( objnum >=0 && objnum < MAX_OBJECTS );
471 if((objnum < 0) || (objnum >= MAX_OBJECTS)){
474 if ( !valid_hit_info[i] ) {
475 shield_info_reset(&Escort_ships[i].hit_info);
480 // reset Num_escort_ships
481 Num_escort_ships = top_complete_escorts;
485 // ----------------------------------------------------------------------
486 // hud_remove_ship_from_escort_index()
488 // Take a ship out of the escort list
489 void hud_remove_ship_from_escort_index(int dead_index, int objnum)
491 int i, count, num_complete_escorts;
492 escort_info bakup_arr[MAX_ESCORT_SHIPS], complete_escorts[MAX_COMPLETE_ESCORT_LIST];
494 // remove him from escort list
495 if((objnum >= 0) && (Objects[objnum].type == OBJ_SHIP) && (Objects[objnum].instance >= 0)){
496 Ships[Objects[objnum].instance].flags &= ~SF_ESCORT;
500 for ( i = 0; i < Num_escort_ships; i++ ) {
501 if ( i != dead_index ) {
502 bakup_arr[count++] = Escort_ships[i];
506 for ( i = 0; i < count; i++ ) {
507 Escort_ships[i] = bakup_arr[i];
511 SDL_assert(Num_escort_ships >= 0);
513 // get complete escort list
514 hud_create_complete_escort_list(complete_escorts, &num_complete_escorts);
516 // sort escort list by priority
517 qsort(complete_escorts, num_complete_escorts, sizeof(escort_info), escort_compare_func);
520 merge_escort_lists(complete_escorts, num_complete_escorts);
522 hud_gauge_popup_start(HUD_ESCORT_VIEW);
526 // called once per frame to remove dead or departed ships from the escort list
527 void hud_escort_cull_list()
529 int i, objnum, np_index;
531 // multiplayer dogfight
532 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)){
533 for ( i = 0; i < Num_escort_ships; i++ ) {
534 np_index = find_player_id(Escort_ships[i].np_id);
536 // maybe remove him if he left
537 if ( np_index < 0 ) {
538 hud_remove_ship_from_escort_index(i, -1);
545 for ( i = 0; i < Num_escort_ships; i++ ) {
546 objnum = Escort_ships[i].objnum;
547 SDL_assert( objnum >=0 && objnum < MAX_OBJECTS );
548 if ( Objects[objnum].flags & OF_SHOULD_BE_DEAD || Ships[Objects[objnum].instance].flags & SF_HIDDEN_FROM_SENSORS ) {
549 hud_remove_ship_from_escort_index(i, objnum);
556 // Set the color for the text to be displayed
557 int hud_escort_set_gauge_color(int index, int friendly)
560 shield_hit_info *shi;
562 shi = &Escort_ships[index].hit_info;
564 // multiplayer dogfight
565 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)){
566 hud_set_gauge_color(HUD_ESCORT_VIEW);
571 hud_set_gauge_color(HUD_ESCORT_VIEW, HUD_C_DIM);
573 gr_set_color_fast(&Color_red);
576 // set flashing color
577 if ( !timestamp_elapsed(shi->shield_hit_timers[HULL_HIT_OFFSET]) ) {
578 if ( timestamp_elapsed(shi->shield_hit_next_flash[HULL_HIT_OFFSET]) ) {
579 shi->shield_hit_next_flash[HULL_HIT_OFFSET] = timestamp(SHIELD_FLASH_INTERVAL);
580 shi->shield_show_bright ^= (1<<HULL_HIT_OFFSET); // toggle between default and bright frames
584 if ( shi->shield_show_bright & (1<<HULL_HIT_OFFSET) ) {
586 hud_set_gauge_color(HUD_ESCORT_VIEW, HUD_C_BRIGHT);
588 gr_set_color_fast(&Color_bright_red);
592 hud_set_gauge_color(HUD_ESCORT_VIEW, HUD_C_DIM);
594 gr_set_color_fast(&Color_dim_red);
602 // draw the shield icon and integrity for the escort ship
603 void hud_escort_show_icon(int index, object *objp)
605 float shields, integrity;
606 int screen_integrity, offset;
610 // multiplayer dogfight code should never get into here
611 SDL_assert(!((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)));
612 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)){
616 sp = &Ships[objp->instance];
618 // determine if its "friendly" or not
619 if(Player_ship != NULL){
620 hud_escort_set_gauge_color(index, (sp->team == Player_ship->team) ? 1 : 0);
622 hud_escort_set_gauge_color(index, 1);
625 // draw a 'D' if a ship is disabled
626 if ( (sp->flags & SF_DISABLED) || (ship_subsys_disrupted(sp, SUBSYSTEM_ENGINE)) ) {
627 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));
630 // print out ship name
631 SDL_strlcpy(buf, sp->ship_name, SDL_arraysize(buf));
632 gr_force_fit_string(buf, 255, 100);
634 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);
636 // show ship integrity
637 hud_get_target_strength(objp, &shields, &integrity);
638 screen_integrity = fl2i(integrity*100 + 0.5f);
640 if ( screen_integrity < 100 ) {
642 if ( screen_integrity == 0 ) {
643 if ( integrity > 0 ) {
644 screen_integrity = 1;
648 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);
651 // multiplayer dogfight
652 void hud_escort_show_icon_dogfight(int index)
654 int hull_integrity = 100;
662 // always use the standard color to avoid confusion
663 hud_set_gauge_color(HUD_ESCORT_VIEW);
666 np_index = find_player_id(Escort_ships[index].np_id);
667 if((np_index < 0) || (np_index >= MAX_PLAYERS) || (Net_players[np_index].player == NULL)){
671 // print out player name
672 SDL_strlcpy(buf, Net_players[np_index].player->callsign, SDL_arraysize(buf));
673 gr_force_fit_string(buf, 255, 100 - stat_shift);
674 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);
676 // can we get the player object?
678 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)){
679 objp = &Objects[Net_players[np_index].player->objnum];
680 if((objp->instance >= 0) && (objp->instance < MAX_SHIPS) && (Ships[objp->instance].ship_info_index >= 0) && (Ships[objp->instance].ship_info_index < MAX_SHIPS)){
681 sip = &Ship_info[Ships[objp->instance].ship_info_index];
686 hull_integrity = (int)(((float)objp->hull_strength / (float)sip->initial_hull_strength) * 100.0f);
687 if(hull_integrity < 0){
692 // show ship integrity
694 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);
696 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);
701 // ----------------------------------------------------------------------
702 // hud_display_escort()
704 // Display the data on ships in the escort list
705 void hud_display_escort()
710 if ( !Show_escort_view ) {
714 if ( !Num_escort_ships ) {
718 // hud_set_default_color();
719 hud_set_gauge_color(HUD_ESCORT_VIEW);
721 // draw the top of the escort view
722 GR_AABITMAP(Escort_gauges[0].first_frame, Escort_coords[gr_screen.res][0][0], Escort_coords[gr_screen.res][0][1]);
723 gr_string(Monitoring_coords[gr_screen.res][0], Monitoring_coords[gr_screen.res][1], XSTR( "monitoring", 285));
725 if ( Num_escort_ships >= 2 ) {
726 GR_AABITMAP(Escort_gauges[1].first_frame, Escort_coords[gr_screen.res][1][0], Escort_coords[gr_screen.res][1][1]);
729 if ( Num_escort_ships >= 3 ) {
730 GR_AABITMAP(Escort_gauges[1].first_frame, Escort_coords[gr_screen.res][2][0], Escort_coords[gr_screen.res][2][1]);
733 // draw bottom of box
734 GR_AABITMAP(Escort_gauges[2].first_frame, Escort_coords[gr_screen.res][3][0], Escort_coords[gr_screen.res][Num_escort_ships][1]);
736 // multiplayer dogfight
737 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)){
738 // draw the escort ship data
739 for ( i = 0; i < Num_escort_ships; i++ ) {
740 // oops. only show top 3
746 hud_escort_show_icon_dogfight(i);
751 // draw the escort ship data
752 for ( i = 0; i < Num_escort_ships; i++ ) {
753 objp = &Objects[Escort_ships[i].objnum];
754 hud_escort_show_icon(i, objp);
759 // ----------------------------------------------------------------------
760 // hud_escort_view_toggle()
762 void hud_escort_view_toggle()
764 Show_escort_view ^= 1;
765 if ( Show_escort_view ) {
766 HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Escort view enabled", 286));
768 HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Escort view disabled", 287));
772 // try to add a ship to the escort list, if slot available
773 void hud_add_ship_to_escort(int objnum, int supress_feedback)
775 escort_info complete_escorts[MAX_COMPLETE_ESCORT_LIST];
776 int num_complete_escorts, idx, found;
778 // get complete escort list
779 hud_create_complete_escort_list(complete_escorts, &num_complete_escorts);
781 // check if ship is already on complete escort list
783 for (idx=0; idx<num_complete_escorts; idx++) {
784 if (complete_escorts[idx].obj_signature == Objects[objnum].signature) {
790 // add new ship into complete list
792 complete_escorts[num_complete_escorts].objnum = objnum;
793 complete_escorts[num_complete_escorts].obj_signature = Objects[objnum].signature;
794 complete_escorts[num_complete_escorts].priority = Ships[Objects[objnum].instance].escort_priority;
796 // remove him from escort list
797 Ships[Objects[objnum].instance].flags |= SF_ESCORT;
799 num_complete_escorts++;
802 // sort escort list by priority
803 qsort(complete_escorts, num_complete_escorts, sizeof(escort_info), escort_compare_func);
806 merge_escort_lists(complete_escorts, num_complete_escorts);
809 if ( (Num_escort_ships == MAX_ESCORT_SHIPS) && !supress_feedback) {
811 // search thru list for objnum
812 for (idx=0; idx<Num_escort_ships; idx++) {
813 if (Escort_ships[idx].objnum == objnum) {
820 HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Escort list is full with %d ships", 288), Num_escort_ships);
821 snd_play( &Snds[SND_TARGET_FAIL]);
825 hud_gauge_popup_start(HUD_ESCORT_VIEW);
829 // ----------------------------------------------------------------------
830 // hud_add_remove_ship_escort()
832 void hud_add_remove_ship_escort(int objnum, int supress_feedback)
836 // no ships on the escort list in multiplayer dogfight
837 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)){
846 if ( Objects[objnum].type != OBJ_SHIP ) {
847 if ( !supress_feedback ) {
848 snd_play( &Snds[SND_TARGET_FAIL]);
854 for ( i = 0; i < Num_escort_ships; i++ ) {
855 if ( Escort_ships[i].obj_signature == Objects[objnum].signature ) {
862 hud_remove_ship_from_escort_index(i, objnum);
866 hud_add_ship_to_escort(objnum, supress_feedback);
869 void hud_remove_ship_from_escort(int objnum)
873 // no ships on the escort list in multiplayer dogfight
874 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)){
884 for ( i = 0; i < Num_escort_ships; i++ ) {
885 if ( Escort_ships[i].obj_signature == Objects[objnum].signature ) {
892 hud_remove_ship_from_escort_index(i, objnum);
897 // Called whenever a ship is hit to determine if that ship is in the escort list. If it
898 // is, then start timers to flash the name hull/shield icon for that ship.
899 void hud_escort_ship_hit(object *objp, int quadrant)
902 shield_hit_info *shi;
904 // no ships on the escort list in multiplayer dogfight
905 if((Game_mode & GM_MULTIPLAYER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT)){
909 for ( i = 0; i < Num_escort_ships; i++ ) {
910 if ( Escort_ships[i].objnum == OBJ_INDEX(objp) ) {
911 shi = &Escort_ships[i].hit_info;
912 num = Quadrant_xlate[quadrant];
913 hud_gauge_popup_start(HUD_ESCORT_VIEW);
914 if ( quadrant >= 0 ) {
915 shi->shield_hit_timers[num] = timestamp(SHIELD_HIT_DURATION);
917 shi->shield_hit_timers[HULL_HIT_OFFSET] = timestamp(SHIELD_HIT_DURATION);
923 // target the next ship in the escort list
924 void hud_escort_target_next()
928 if ( Num_escort_ships == 0 ) {
929 snd_play( &Snds[SND_TARGET_FAIL], 0.0f );
934 if ( Last_target_index >= Num_escort_ships ) {
935 Last_target_index = 0;
938 objnum = Escort_ships[Last_target_index].objnum;
939 set_target_objnum( Player_ai, objnum);
940 hud_restore_subsystem_target(&Ships[Objects[objnum].instance]);
943 // return the number of ships currently on the escort list
944 int hud_escort_num_ships_on_list()
946 return Num_escort_ships;
949 // Return the object number for the ship at index position in the escort list
950 int hud_escort_return_objnum(int index)
952 int escort_objnum, escort_sig;
953 if ( index >= Num_escort_ships ) {
957 escort_objnum = Escort_ships[index].objnum;
958 escort_sig = Escort_ships[index].obj_signature;
960 if ( escort_objnum < 0 ) {
964 // ensure this is still a valid index
965 if ( Objects[escort_objnum].signature != escort_sig ) {
969 return Escort_ships[index].objnum;
973 void hudescort_page_in()
977 for ( i = 0; i < MAX_ESCORT_SHIPS; i++ ) {
978 bm_page_in_aabitmap( Escort_gauges[i].first_frame, Escort_gauges[i].num_frames);
982 void hud_escort_add_player(short id)
984 SDL_assert(Game_mode & GM_MULTIPLAYER);
985 if(!(Game_mode & GM_MULTIPLAYER)){
991 // just go through and add as long as its not a duplicate
992 for(idx=0; idx<Num_escort_ships; idx++){
993 if(Escort_ships[idx].np_id == id){
998 // re-setup the escort list
999 hud_setup_escort_list(0);
1002 void hud_escort_remove_player(short id)
1004 SDL_assert(Game_mode & GM_MULTIPLAYER);
1005 if(!(Game_mode & GM_MULTIPLAYER)){
1011 // find the instance and remove it if possible
1012 for(idx=0; idx<Num_escort_ships; idx++){
1013 if(Escort_ships[idx].np_id == id){
1014 hud_remove_ship_from_escort_index(idx, -1);