FS2_Open
Open source remastering of the Freespace 2 engine
hudescort.cpp
Go to the documentation of this file.
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 the
6  * source.
7  *
8 */
9 
10 
11 
12 
13 
14 #include "gamesnd/gamesnd.h"
15 #include "globalincs/alphacolors.h"
16 #include "globalincs/linklist.h"
17 #include "globalincs/systemvars.h"
18 #include "hud/hudescort.h"
19 #include "hud/hudmessage.h"
20 #include "hud/hudparse.h"
21 #include "hud/hudshield.h"
22 #include "hud/hudtargetbox.h"
23 #include "iff_defs/iff_defs.h"
24 #include "io/timer.h"
25 #include "network/multi.h"
26 #include "network/multiutil.h"
27 #include "object/object.h"
28 #include "parse/parselo.h"
29 #include "playerman/player.h"
30 #include "ship/ship.h"
31 #include "weapon/emp.h"
32 
33 
35 
36 typedef struct escort_info
37 {
38  int objnum;
39  int obj_signature; // so we are sure we have a valid objnum
40  int priority; // higher priority is higher in the list
41  short np_id; // netplayer id (for multiplayer dogfight mode)
42 
43  // These parallel the way the shield_hit_info struct works; intentionally
44  // not using it here because this is a lot simpler and less error-prone
48 } escort_info;
49 
53 
54 //int Escort_gauge_y[MAX_ESCORT_SHIPS] = { 219, 230, 241 };
55 
56 /*
57 int Escort_gauge_text_coords[GR_NUM_RESOLUTIONS][MAX_ESCORT_SHIPS][4][2] =
58 {
59  { // GR_640
60  {
61  {489,219},
62  {599,212},
63  {604,219},
64  {474,219}
65  },
66  {
67  {489,230},
68  {599,223},
69  {604,230},
70  {474,230}
71  },
72  {
73  {489,241},
74  {599,234},
75  {604,241},
76  {474,241}
77  },
78  },
79  { // GR_1024
80  {
81  {869,343},
82  {973,338},
83  {981,343},
84  {854,343}
85  },
86  {
87  {869,354},
88  {973,349},
89  {981,354},
90  {854,354}
91  },
92  {
93  {869,365},
94  {973,360},
95  {981,365},
96  {854,365}
97  },
98  }
99 };
100 
101 // escort gauge coords
102 int Escort_coords[GR_NUM_RESOLUTIONS][4][2] = {
103  { // GR_640
104  {486, 206},
105  {486, 219},
106  {486, 230},
107  {486, 241}
108  },
109  { // GR_1024
110  {865, 330},
111  {865, 343},
112  {865, 354},
113  {865, 365}
114  }
115 };
116 
117 // monitoring text coords
118 int Monitoring_coords[GR_NUM_RESOLUTIONS][2] = {
119  { // GR_640
120  489, 208
121  },
122  { // GR_1024
123  869, 331
124  }
125 };
126 
127 char *Escort_gauge_filenames[GR_NUM_RESOLUTIONS][MAX_ESCORT_SHIPS] =
128 {
129 //XSTR:OFF
130  { // GR_640
131  "escort1",
132  "escort2",
133  "escort3"
134  },
135  { // GR_1024
136  "escort1",
137  "escort2",
138  "escort3"
139  }
140 //XSTR:ON
141 };*/
142 
143 static int Last_target_index; // index into Escort_gauges for last targeted via 'Next Escort Target' key
144 
147 {
148 }
149 
151 {
152  strcpy_s(header_text, text);
153 }
154 
156 {
157  header_text_offsets[0] = x;
158  header_text_offsets[1] = y;
159 }
160 
162 {
163  list_start_offsets[0] = x;
164  list_start_offsets[1] = y;
165 }
166 
168 {
169  entry_h = h;
170 }
171 
173 {
174  entry_stagger_w = w;
175 }
176 
178 {
180 }
181 
183 {
184  ship_name_offsets[0] = x;
185  ship_name_offsets[1] = y;
186 }
187 
189 {
192 }
193 
195 {
196  ship_status_offsets[0] = x;
197  ship_status_offsets[1] = y;
198 }
199 
201 {
203 }
204 
206 {
207  right_align_names = align;
208 }
209 
210 void HudGaugeEscort::initBitmaps(char *fname_top, char *fname_middle, char *fname_bottom)
211 {
212  Escort_gauges[0].first_frame = bm_load_animation(fname_top, &Escort_gauges[0].num_frames);
213  if (Escort_gauges[0].first_frame == -1) {
214  Warning(LOCATION, "Could not load in ani: %s\n", fname_top);
215  return;
216  }
217 
218  Escort_gauges[1].first_frame = bm_load_animation(fname_middle, &Escort_gauges[1].num_frames);
219  if (Escort_gauges[1].first_frame == -1) {
220  Warning(LOCATION, "Could not load in ani: %s\n", fname_middle);
221  return;
222  }
223 
224  Escort_gauges[2].first_frame = bm_load_animation(fname_bottom, &Escort_gauges[2].num_frames);
225  if (Escort_gauges[2].first_frame == -1) {
226  Warning(LOCATION, "Could not load in ani: %s\n", fname_bottom);
227  return;
228  }
229 }
230 
232 {
233  int i;
234 
235  for ( i = 0; i < NUM_ESCORT_FRAMES; i++ ) {
236  bm_page_in_aabitmap( Escort_gauges[i].first_frame, Escort_gauges[i].num_frames);
237  }
238 }
239 
241 {
242  int is_flashing = 0;
243  int is_bright = 0;
244  int seen_from_team = (Player_ship != NULL) ? Player_ship->team : -1;
245 
246  // multiplayer dogfight
247  if(MULTI_DOGFIGHT)
248  {
249  setGaugeColor();
250  return 0;
251  }
252 
253  // set flashing color
254  if (!timestamp_elapsed(Escort_ships[index].escort_hit_timer))
255  {
256  is_flashing = 1;
257  if (Escort_ships[index].escort_show_bright)
258  {
259  is_bright = 1;
260  }
261  }
262 
263  // Goober5000 - now base this on team color
264  gr_set_color_fast(iff_get_color_by_team_and_object(team, seen_from_team, is_bright, &Objects[Escort_ships[index].objnum]));
265 
266 
267  // Goober5000 - an alternative; same as original but incorporating teams for non-friendlies
268  /*
269  if ((seen_from_team == team) || (seen_from_team < 0)) // :V: sez assume friendly if Player_ship is NULL
270  hud_set_gauge_color(HUD_ESCORT_VIEW, is_bright ? HUD_C_BRIGHT : HUD_C_DIM);
271  else
272  gr_set_color_fast(iff_get_color_by_team(team, seen_from_team, is_bright));
273  */
274 
275 
276  // Goober5000 - original color logic
277  /*
278  if ((seen_from_team == team) || (seen_from_team < 0)) // :V: sez assume friendly if Player_ship is NULL
279  hud_set_gauge_color(HUD_ESCORT_VIEW, is_bright ? HUD_C_BRIGHT : HUD_C_DIM);
280  else
281  gr_set_color_fast(is_bright ? &Color_bright_red : &Color_red);
282  */
283 
284 
285  return is_flashing;
286 }
287 
288 void HudGaugeEscort::render(float frametime)
289 {
290  int i = 0;
291 
292  if ( !Show_escort_view ) {
293  return;
294  }
295 
296  if ( !Num_escort_ships ) {
297  return;
298  }
299 
300  // hud_set_default_color();
301  setGaugeColor();
302 
303  // draw the top of the escort view
304  renderBitmap(Escort_gauges[0].first_frame, position[0], position[1]);
306 
307  int x = position[0] + list_start_offsets[0];
308  int y = position[1] + list_start_offsets[1];
309 
310  //This is temporary
312  i=0;
313 
314  if(Num_escort_ships)
315  {
316  for(; i < Num_escort_ships; i++)
317  {
318  if(i != 0)
319  {
320  x += entry_stagger_w;
321  y += entry_h;
322  }
323  renderBitmap(Escort_gauges[1].first_frame, x, y);
324 
325  //Now we just show the ships info
326  renderIcon(x, y, i);
327  }
328 
329  //Increment for last entry
330  x += entry_stagger_w;
331  y += entry_h;
332  }
333 
334  //Back to right #
336 
337  //Show the last escort entry
338  renderBitmap(Escort_gauges[2].first_frame, x, y + bottom_bg_offset);
339  renderIcon(x, y, i);
340 }
341 
342 // draw the shield icon and integrity for the escort ship
343 void HudGaugeEscort::renderIcon(int x, int y, int index)
344 {
345  if(MULTI_DOGFIGHT && index <= 2)
346  {
347  renderIconDogfight(x, y, index);
348  return;
349  }
350 
351  float shields, integrity;
352  int screen_integrity, offset;
353  char buf[255];
354 
355  object *objp = &Objects[Escort_ships[index].objnum];
356  ship *sp = &Ships[objp->instance];
357 
358  // determine if its "friendly" or not
359  // Goober5000 - changed in favor of just passing the team
360  setGaugeColorEscort(index, sp->team);
361  /*
362  if(Player_ship != NULL){
363  hud_escort_set_gauge_color(index, (sp->team == Player_ship->team) ? 1 : 0);
364  } else {
365  hud_escort_set_gauge_color(index, 1);
366  }
367  */
368 
369  // draw a 'D' if a ship is disabled
370  if ( (sp->flags & SF_DISABLED) || (ship_subsys_disrupted(sp, SUBSYSTEM_ENGINE)) ) {
371  renderString( x + ship_status_offsets[0], y + ship_status_offsets[1], EG_NULL, XSTR( "D", 284));
372  }
373 
374  // print out ship name
375  strcpy_s(buf, sp->ship_name);
377  const int w = gr_force_fit_string(buf, 255, ship_name_max_width);
378 
379  if (right_align_names) {
381  } else {
382  renderString( x + ship_name_offsets[0], y + ship_name_offsets[1], EG_ESCORT1 + index, buf);
383  }
384 
385  // show ship integrity
386  hud_get_target_strength(objp, &shields, &integrity);
387  screen_integrity = fl2i(integrity*100 + 0.5f);
388  offset = 0;
389  if ( screen_integrity < 100 ) {
390  offset = 2;
391  if ( screen_integrity == 0 ) {
392  if ( integrity > 0 ) {
393  screen_integrity = 1;
394  }
395  }
396  }
397  renderPrintf( x+ship_integrity_offsets[0] + offset, y+ship_integrity_offsets[1], EG_NULL, "%d", screen_integrity);
398 
399  //Let's be nice.
400  setGaugeColor();
401 }
402 
403 // multiplayer dogfight
405 {
406  int hull_integrity = 100;
407  char buf[255];
408  int np_index;
409  object *objp;
410 
411  int stat_shift = 40;
412 
413  // always use the standard color to avoid confusion
414  setGaugeColor();
415 
416  // netplayer index
417  np_index = find_player_id(Escort_ships[index].np_id);
418  if((np_index < 0) || (np_index >= MAX_PLAYERS) || (Net_players[np_index].m_player == NULL)){
419  return;
420  }
421 
422  // print out player name
423  strcpy_s(buf, Net_players[np_index].m_player->callsign);
424  gr_force_fit_string(buf, 255, 100 - stat_shift);
425  renderString( x + ship_name_offsets[0], y + ship_name_offsets[1], EG_ESCORT1 + index, buf);
426 
427  // can we get the player object?
428  objp = NULL;
429  if((Net_players[np_index].m_player->objnum >= 0) && (Net_players[np_index].m_player->objnum < MAX_OBJECTS) && (Objects[Net_players[np_index].m_player->objnum].type == OBJ_SHIP)){
430  objp = &Objects[Net_players[np_index].m_player->objnum];
431  if((objp->instance >= 0) && (objp->instance < MAX_SHIPS) && (Ships[objp->instance].ship_info_index >= 0) && (Ships[objp->instance].ship_info_index < MAX_SHIPS)){
432  //
433  } else {
434  return;
435  }
436 
437  hull_integrity = (int)(((float)objp->hull_strength / (float)Ships[objp->instance].ship_max_hull_strength) * 100.0f);
438  if(hull_integrity < 0){
439  hull_integrity = 0;
440  }
441  }
442 
443  // show ship integrity
444  if(objp == NULL){
445  renderPrintf( x+ship_integrity_offsets[0] - stat_shift, y+ship_integrity_offsets[1], EG_NULL, "%d", Net_players[np_index].m_player->stats.m_kill_count_ok);
446  } else {
447  renderPrintf( x+ship_integrity_offsets[0] - stat_shift, y+ship_integrity_offsets[1], EG_NULL, "(%d%%) %d", hull_integrity, Net_players[np_index].m_player->stats.m_kill_count_ok);
448  }
449 }
450 
452 {
453  if(Num_escort_ships)
454  {
455  for(int i = 0; i < Num_escort_ships; i++)
456  {
457  if (!timestamp_elapsed(Escort_ships[i].escort_hit_timer))
458  {
459  if (timestamp_elapsed(Escort_ships[i].escort_hit_next_flash))
460  {
462  Escort_ships[i].escort_show_bright = !Escort_ships[i].escort_show_bright; // toggle between default and bright frames
463  }
464  }
465  }
466  }
467 }
468 
469 // called from HUD init, loads the bitmap data in once, and resets any data for each level
471 {
472  Last_target_index = -1;
473 
476  }
477 }
478 
479 // ----------------------------------------------------------------------
480 // hud_escort_clear_all()
481 //
482 void hud_escort_clear_all(bool clear_flags)
483 {
484  int i;
485 
486  Num_escort_ships = 0;
487  for ( i = 0; i < Max_escort_ships; i++ ) {
488  if(clear_flags && (Escort_ships[i].objnum >= 0) && (Objects[Escort_ships[i].objnum].type == OBJ_SHIP) && (Objects[Escort_ships[i].objnum].instance >= 0)){
489  Ships[Objects[Escort_ships[i].objnum].instance].flags &= ~SF_ESCORT;
490  }
491  Escort_ships[i].obj_signature = -99;
492  Escort_ships[i].np_id = -1;
493  Escort_ships[i].escort_hit_timer = 0;
494  Escort_ships[i].escort_hit_next_flash = 0;
495  Escort_ships[i].escort_show_bright = false;
496  }
497 }
498 
499 // internal helper function for sort.
500 // sorts first by priority number and then alphabetically
501 int escort_compare_func(const void *e1, const void *e2)
502 {
503  escort_info *escort1, *escort2;
504  int diff;
505  int ret;
506 
507  escort1 = (escort_info*) e1;
508  escort2 = (escort_info*) e2;
509 
510  // multiplayer dogfight
511  if(MULTI_DOGFIGHT){
512  int n1, n2;
513 
514  n1 = find_player_id(escort1->np_id);
515  n2 = find_player_id(escort2->np_id);
516  if((n1 < 0) || (n2 < 0) || (Net_players[n1].m_player == NULL) || (Net_players[n2].m_player == NULL)){
517  ret = 0;
518  } else {
519  // player 1 is higher than player 2
520  if(Net_players[n1].m_player->stats.m_kill_count_ok >= Net_players[n2].m_player->stats.m_kill_count_ok){
521  ret = -1;
522  } else {
523  ret = 1;
524  }
525  }
526  } else {
527  diff = escort2->priority - escort1->priority;
528 
529  if (diff != 0) {
530  ret = diff;
531  } else {
532  char *name1, *name2;
533  name1 = Ships[Objects[escort1->objnum].instance].ship_name;
534  name2 = Ships[Objects[escort2->objnum].instance].ship_name;
535 
536  ret = stricmp(name1, name2);
537  }
538  }
539 
540  return ret;
541 }
542 
543 // create complete priority sorted escort list for all active ships
544 // escorts - array of escort info
545 // num_escorts - number of escorts requests in field of active ships
546 // This will be culled to MAX_ESCORTS, selecting the top set from escorts
547 void hud_create_complete_escort_list(escort_info *escorts, int *num_escorts)
548 {
549  ship_obj *so;
550  object *objp;
551 
552  // start with none on list
553  *num_escorts = 0;
554 
555  int idx;
556 
557  // multiplayer dogfight
558  if(MULTI_DOGFIGHT){
559  for(idx=0; idx<MAX_PLAYERS; idx++){
560  // break out of the loop when we have reached our max
561  if ( *num_escorts == MAX_COMPLETE_ESCORT_LIST ) {
562  mprintf(("exceeded max ships in big escort list\n"));
563  break;
564  }
565 
566  // is this a valid player
568  // add the ship
569  escorts[*num_escorts].objnum = -1;
570  escorts[*num_escorts].obj_signature = -1;
571  escorts[*num_escorts].priority = -1;
572  escorts[*num_escorts].np_id = Net_players[idx].player_id;
573  escorts[*num_escorts].escort_hit_timer = 0;
574  escorts[*num_escorts].escort_hit_next_flash = 0;
575  escorts[*num_escorts].escort_show_bright = false;
576  (*num_escorts)++;
577  }
578  }
579  }
580  // all others
581  else {
582  for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
583  Assert( so->objnum >= 0 && so->objnum < MAX_OBJECTS);
584  if((so->objnum < 0) || (so->objnum >= MAX_OBJECTS)){
585  continue;
586  }
587  objp = &Objects[so->objnum];
588  Assert( objp->type == OBJ_SHIP );
589  if(objp->type != OBJ_SHIP){
590  continue;
591  }
592 
593  // break out of the loop when we have reached our max
594  if ( *num_escorts == MAX_COMPLETE_ESCORT_LIST ) {
595  mprintf(("exceeded max ships in big escort list\n"));
596  break;
597  }
598 
599  // only process ships that might be on the list
600  if ( !(Ships[objp->instance].flags & SF_ESCORT) ){
601  continue;
602  }
603 
604  // only process ships that can be seen by sensors
605  if ( (Ships[objp->instance].flags & SF_HIDDEN_FROM_SENSORS) ){
606  continue;
607  }
608 
609  // don't process most stealth ships
610  if ( (Ships[objp->instance].flags2 & SF2_STEALTH) )
611  {
612  if ( Ships[objp->instance].team == Player_ship->team )
613  {
614  // friendly stealths are only not seen when explicitly specified
616  {
617  continue;
618  }
619  }
620  // non-friendly stealths are never seen
621  else
622  {
623  continue;
624  }
625  }
626 
627  // don't process objects that should be dead
628  if ( objp->flags & OF_SHOULD_BE_DEAD ) {
629  continue;
630  }
631 
632  // add the ship
633  escorts[*num_escorts].objnum = so->objnum;
634  escorts[*num_escorts].obj_signature = objp->signature;
635  escorts[*num_escorts].priority = Ships[objp->instance].escort_priority;
636  escorts[*num_escorts].np_id = -1;
637  escorts[*num_escorts].escort_hit_timer = 0;
638  escorts[*num_escorts].escort_hit_next_flash = 0;
639  escorts[*num_escorts].escort_show_bright = false;
640  (*num_escorts)++;
641  }
642  }
643 }
644 
645 
646 // ----------------------------------------------------------------------
647 // hud_init_escort_info()
648 //
649 // Set up the escort list
650 //
652 {
653  int num_escorts, num_complete_escorts;
654  escort_info complete_escorts[MAX_COMPLETE_ESCORT_LIST];
655 
657 
658  // get complete escort list
659  hud_create_complete_escort_list(complete_escorts, &num_complete_escorts);
660 
661  // sort escort list by priority
662  insertion_sort(complete_escorts, num_complete_escorts, sizeof(escort_info), escort_compare_func);
663 
664  // set number in escort list
665  num_escorts = num_complete_escorts;
666  if (num_escorts > Max_escort_ships) {
667  num_escorts = Max_escort_ships;
668  }
669 
670  // add ships to escort list
671  for (Num_escort_ships=0; Num_escort_ships<num_escorts; Num_escort_ships++) {
672  Escort_ships[Num_escort_ships].obj_signature = complete_escorts[Num_escort_ships].obj_signature;
673  Escort_ships[Num_escort_ships].priority = complete_escorts[Num_escort_ships].priority;
674  Escort_ships[Num_escort_ships].objnum = complete_escorts[Num_escort_ships].objnum;
675  Escort_ships[Num_escort_ships].np_id = complete_escorts[Num_escort_ships].np_id;
676  Escort_ships[Num_escort_ships].escort_hit_timer = 0;
677  Escort_ships[Num_escort_ships].escort_hit_next_flash = 0;
678  Escort_ships[Num_escort_ships].escort_show_bright = false;
679  }
680 
681  if(level){
682  Show_escort_view = 1;
683  }
684 }
685 
686 
687 // combine complete escort list with Escort_ships, keeping valid hit info
688 void merge_escort_lists(escort_info *complete_escorts, int num_complete_escorts)
689 {
690  int i, j, top_complete_escorts;
691  int valid_hit_info[MAX_COMPLETE_ESCORT_LIST];
692 
693  // may be > 1 ship change to list (ie, 2 or 3 culled during same frame)
694  // set Num_escort_ships and cap
695  Num_escort_ships = num_complete_escorts;
698  }
699 
700  // nothing to do
701  if (Num_escort_ships == 0) {
702  return;
703  }
704 
705  // check used as a flag whether top slots in complete_escorts were copied
706  // this is important re. hit info
707  for (i=0; i<Max_escort_ships; i++) {
708  valid_hit_info[i] = 0;
709  }
710 
711  // get the top slots in complete escort list that will be copied onto Escort_ships
712  top_complete_escorts = num_complete_escorts;
713  if (top_complete_escorts > Max_escort_ships) {
714  top_complete_escorts = Max_escort_ships;
715  }
716 
717  // copy for Escort_ships to complete_escorts to retain hit_info
718  if(!MULTI_DOGFIGHT) {
719  for (i=0; i<top_complete_escorts; i++) {
720  for (j=0; j<Num_escort_ships; j++) {
721  if (Escort_ships[j].obj_signature == complete_escorts[i].obj_signature) {
722  complete_escorts[i] = Escort_ships[j];
723  valid_hit_info[i] = 1;
724  break;
725  }
726  }
727  }
728 
729  // copy top slots to Escort_ships
730  for (i=0; i<top_complete_escorts; i++) {
731  Escort_ships[i] = complete_escorts[i];
732  // check all ships are valid
733  int objnum = Escort_ships[i].objnum;
734  Assert( objnum >=0 && objnum < MAX_OBJECTS );
735  if((objnum < 0) || (objnum >= MAX_OBJECTS)){
736  continue;
737  }
738  if ( !valid_hit_info[i] ) {
739  Escort_ships[i].escort_hit_timer = 0;
740  Escort_ships[i].escort_hit_next_flash = 0;
741  Escort_ships[i].escort_show_bright = false;
742  }
743  }
744  }
745 
746  // reset Num_escort_ships
747  Num_escort_ships = top_complete_escorts;
748 }
749 
750 
751 // ----------------------------------------------------------------------
752 // hud_remove_ship_from_escort_index()
753 //
754 // Take a ship out of the escort list
755 void hud_remove_ship_from_escort_index(int dead_index, int objnum)
756 {
757  int i, count, num_complete_escorts;
758  escort_info bakup_arr[MAX_COMPLETE_ESCORT_LIST], complete_escorts[MAX_COMPLETE_ESCORT_LIST];
759 
760  // remove him from escort list
761  if((objnum >= 0) && (Objects[objnum].type == OBJ_SHIP) && (Objects[objnum].instance >= 0)){
762  Ships[Objects[objnum].instance].flags &= ~SF_ESCORT;
763  }
764 
765  count = 0;
766  for ( i = 0; i < Num_escort_ships; i++ ) {
767  if ( i != dead_index ) {
768  bakup_arr[count++] = Escort_ships[i];
769  }
770  }
771 
772  for ( i = 0; i < count; i++ ) {
773  Escort_ships[i] = bakup_arr[i];
774  }
775 
776  Num_escort_ships--;
777  Assert(Num_escort_ships >= 0);
778 
779  // get complete escort list
780  hud_create_complete_escort_list(complete_escorts, &num_complete_escorts);
781 
782  // sort escort list by priority
783  insertion_sort(complete_escorts, num_complete_escorts, sizeof(escort_info), escort_compare_func);
784 
785  // merge list
786  merge_escort_lists(complete_escorts, num_complete_escorts);
787 
789 
790 }
791 
792 // called once per frame to refresh the escort list if important flags changed
794 {
795  int i;
796 
797  int np_index;
798 
799  // multiplayer dogfight
800  if(MULTI_DOGFIGHT){
801  for ( i = 0; i < Num_escort_ships; i++ ) {
802  np_index = find_player_id(Escort_ships[i].np_id);
803 
804  // maybe remove him if he left
805  if ( np_index < 0 ) {
807  break;
808  }
809  }
810  }
811  // everything else
812  else {
813  for ( i = 0; i < Num_escort_ships; i++ ) {
814  int objnum = Escort_ships[i].objnum;
815  Assert( objnum >=0 && objnum < MAX_OBJECTS );
816 
817  if ( Objects[objnum].flags & OF_SHOULD_BE_DEAD ) {
819  break;
820  } else if ( Objects[objnum].type == OBJ_SHIP ) {
821  int shipnum = Objects[objnum].instance;
822  Assert( shipnum >= 0 && shipnum < MAX_SHIPS );
823 
824  if ( (Ships[shipnum].flags & SF_HIDDEN_FROM_SENSORS)
825  || ((Ships[shipnum].flags2 & SF2_STEALTH) && ((Ships[shipnum].team != Player_ship->team) || (Ships[shipnum].flags2 & SF2_FRIENDLY_STEALTH_INVIS)))
826  ) {
828  break;
829  }
830  }
831  }
832  }
833 }
834 
835 // ----------------------------------------------------------------------
836 // hud_escort_view_toggle()
837 //
839 {
840  Show_escort_view ^= 1;
841  if ( Show_escort_view ) {
842  HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Escort view enabled", 286));
843  } else {
844  HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Escort view disabled", 287));
845  }
846 }
847 
848 // try to add a ship to the escort list, if slot available
849 void hud_add_ship_to_escort(int objnum, int supress_feedback)
850 {
851  escort_info complete_escorts[MAX_COMPLETE_ESCORT_LIST];
852  int num_complete_escorts, idx, found;
853 
854  // get complete escort list
855  hud_create_complete_escort_list(complete_escorts, &num_complete_escorts);
856 
857  // ensure the complete escort list is not full already
858  if (num_complete_escorts == MAX_COMPLETE_ESCORT_LIST)
859  {
860  return;
861  }
862 
863  // check if ship is already on complete escort list
864  found = 0;
865  for (idx=0; idx<num_complete_escorts; idx++) {
866  if (complete_escorts[idx].obj_signature == Objects[objnum].signature) {
867  found = 1;
868  break;
869  }
870  }
871 
872  // add new ship into complete list
873  if ( !found ) {
874  complete_escorts[num_complete_escorts].objnum = objnum;
875  complete_escorts[num_complete_escorts].obj_signature = Objects[objnum].signature;
876  complete_escorts[num_complete_escorts].priority = Ships[Objects[objnum].instance].escort_priority;
877  complete_escorts[num_complete_escorts].escort_hit_timer = 0;
878  complete_escorts[num_complete_escorts].escort_hit_next_flash = 0;
879  complete_escorts[num_complete_escorts].escort_show_bright = false;
880 
881  // add him to escort list
882  Ships[Objects[objnum].instance].flags |= SF_ESCORT;
883 
884  num_complete_escorts++;
885  }
886 
887  // sort escort list by priority
888  insertion_sort(complete_escorts, num_complete_escorts, sizeof(escort_info), escort_compare_func);
889 
890  // merge list
891  merge_escort_lists(complete_escorts, num_complete_escorts);
892 
893  // maybe do feedback
894  if ( (Num_escort_ships == Max_escort_ships) && !supress_feedback) {
895  found = 0;
896  // search thru list for objnum
897  for (idx=0; idx<Num_escort_ships; idx++) {
898  if (Escort_ships[idx].objnum == objnum) {
899  found = 1;
900  break;
901  }
902  }
903 
904  if (!found) {
905  HUD_sourced_printf(HUD_SOURCE_HIDDEN, XSTR( "Escort list is full with %d ships", 288), Num_escort_ships);
907  }
908  }
909 
911 }
912 
913 
914 // ----------------------------------------------------------------------
915 // hud_add_remove_ship_escort()
916 //
917 void hud_add_remove_ship_escort(int objnum, int supress_feedback)
918 {
919  int in_escort, i;
920 
921  // no ships on the escort list in multiplayer dogfight
922  if(MULTI_DOGFIGHT){
923  return;
924  }
925 
926  if ( objnum < 0 ) {
927  Int3();
928  return;
929  }
930 
931  if ( Objects[objnum].type != OBJ_SHIP ) {
932  if ( !supress_feedback ) {
934  }
935  return;
936  }
937 
938  in_escort = 0;
939  for ( i = 0; i < Num_escort_ships; i++ ) {
940  if ( Escort_ships[i].obj_signature == Objects[objnum].signature ) {
941  in_escort = 1;
942  break;
943  }
944  }
945 
946  if ( in_escort ) {
948  return;
949  }
950 
951  hud_add_ship_to_escort(objnum, supress_feedback);
952 }
953 
955 {
956  int in_escort, i;
957 
958  // no ships on the escort list in multiplayer dogfight
959  if(MULTI_DOGFIGHT){
960  return;
961  }
962 
963  if ( objnum < 0 ) {
964  Int3();
965  return;
966  }
967 
968  in_escort = 0;
969  for ( i = 0; i < Num_escort_ships; i++ ) {
970  if ( Escort_ships[i].obj_signature == Objects[objnum].signature ) {
971  in_escort = 1;
972  break;
973  }
974  }
975 
976  if ( in_escort ) {
978  return;
979  }
980 }
981 
989 void hud_escort_ship_hit(object *objp, int quadrant)
990 {
991  // no ships on the escort list in multiplayer dogfight
992  if(MULTI_DOGFIGHT){
993  return;
994  }
995 
996  for ( int i = 0; i < Num_escort_ships; i++ ) {
997  if ( Escort_ships[i].objnum == OBJ_INDEX(objp) ) {
1001  }
1002  }
1003 }
1004 
1005 // target the next ship in the escort list
1007 {
1008  int objnum;
1009 
1010  if ( Num_escort_ships == 0 ) {
1011  snd_play( &Snds[SND_TARGET_FAIL], 0.0f );
1012  return;
1013  }
1014 
1015  Last_target_index++;
1016  if ( Last_target_index >= Num_escort_ships ) {
1017  Last_target_index = 0;
1018  }
1019 
1020  objnum = Escort_ships[Last_target_index].objnum;
1021  set_target_objnum( Player_ai, objnum);
1022  hud_restore_subsystem_target(&Ships[Objects[objnum].instance]);
1023 }
1024 
1025 // return the number of ships currently on the escort list
1027 {
1028  return Num_escort_ships;
1029 }
1030 
1031 // Return the object number for the ship at index position in the escort list
1033 {
1034  int escort_objnum, escort_sig;
1035  if ( index >= Num_escort_ships || index >= MAX_COMPLETE_ESCORT_LIST) {
1036  return -1;
1037  }
1038 
1039  escort_objnum = Escort_ships[index].objnum;
1040  escort_sig = Escort_ships[index].obj_signature;
1041 
1042  if ( escort_objnum < 0 ) {
1043  return -1;
1044  }
1045 
1046  // ensure this is still a valid index
1047  if ( Objects[escort_objnum].signature != escort_sig ) {
1048  return -1;
1049  }
1050 
1051  return Escort_ships[index].objnum;
1052 }
1053 
1055 {
1057  if(!(Game_mode & GM_MULTIPLAYER)){
1058  return;
1059  }
1060 
1061  int idx;
1062 
1063  // just go through and add as long as its not a duplicate
1064  for(idx=0; idx<Num_escort_ships; idx++){
1065  if(Escort_ships[idx].np_id == id){
1066  return;
1067  }
1068  }
1069 
1070  // re-setup the escort list
1072 }
1073 
1075 {
1077  if(!(Game_mode & GM_MULTIPLAYER)){
1078  return;
1079  }
1080 
1081  int idx;
1082 
1083  // find the instance and remove it if possible
1084  for(idx=0; idx<Num_escort_ships; idx++){
1085  if(Escort_ships[idx].np_id == id){
1087  return;
1088  }
1089  }
1090 }
void hud_get_target_strength(object *objp, float *shields, float *integrity)
void hud_escort_update_list()
Definition: hudescort.cpp:451
hud_frames Escort_gauges[NUM_ESCORT_FRAMES]
Definition: hudescort.h:43
void initShipStatusOffsets(int x, int y)
Definition: hudescort.cpp:194
int timestamp(int delta_ms)
Definition: timer.cpp:226
int i
Definition: multi_pxo.cpp:466
void hud_gauge_popup_start(int gauge_index, int time)
Start a gauge to pop-up.
Definition: hud.cpp:3036
void initBitmaps(char *fname_top, char *fname_middle, char *fname_bottom)
Definition: hudescort.cpp:210
#define HUD_OBJECT_ESCORT
Definition: hudparse.h:121
ai_info * Player_ai
Definition: ai.cpp:24
int team
Definition: ship.h:606
int entry_stagger_w
Definition: hudescort.h:49
void hud_remove_ship_from_escort_index(int dead_index, int objnum)
Definition: hudescort.cpp:755
int Game_mode
Definition: systemvars.cpp:24
GLfloat GLfloat GLfloat GLfloat h
Definition: Glext.h:7280
void hud_escort_add_player(short id)
Definition: hudescort.cpp:1054
SCP_vector< game_snd > Snds
Definition: gamesnd.cpp:19
int bottom_bg_offset
Definition: hudescort.h:50
int escort_priority
Definition: ship.h:541
GLuint index
Definition: Glext.h:5608
#define VM_WARP_CHASE
Definition: systemvars.h:37
player * m_player
Definition: multi.h:459
void renderIcon(int x, int y, int index)
Definition: hudescort.cpp:343
#define MAX_SHIPS
Definition: globals.h:37
int hud_escort_num_ships_on_list()
Definition: hudescort.cpp:1026
void setGaugeColor(int bright_index=-4)
Definition: hud.cpp:445
color * iff_get_color_by_team_and_object(int team, int seen_from_team, int is_bright, object *objp)
Definition: iff_defs.cpp:678
void hud_create_complete_escort_list(escort_info *escorts, int *num_escorts)
Definition: hudescort.cpp:547
#define MULTI_STANDALONE(np)
Definition: multi.h:139
int Show_escort_view
Definition: hudescort.cpp:34
void _cdecl void void _cdecl void _cdecl Warning(char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
Assert(pm!=NULL)
#define mprintf(args)
Definition: pstypes.h:238
#define VM_EXTERNAL
Definition: systemvars.h:31
void hud_escort_ship_hit(object *objp, int quadrant)
Definition: hudescort.cpp:989
CButton * team
void initShipNameMaxWidth(int w)
Definition: hudescort.cpp:200
int find_player_id(short player_id)
Definition: multiutil.cpp:465
GLclampf f
Definition: Glext.h:7097
#define MAX_OBJECTS
Definition: globals.h:83
void initEntryHeight(int h)
Definition: hudescort.cpp:167
#define SF2_FRIENDLY_STEALTH_INVIS
Definition: ship.h:484
#define EG_ESCORT1
Definition: emp.h:36
void initShipNameOffsets(int x, int y)
Definition: hudescort.cpp:182
#define SHIELD_FLASH_INTERVAL
Definition: hudshield.h:19
void gr_set_color_fast(color *dst)
Definition: 2d.cpp:1197
uint flags
Definition: ship.h:644
object * objp
Definition: lua.cpp:3105
#define Int3()
Definition: pstypes.h:292
void HUD_sourced_printf(int source, const char *format,...)
Definition: hudmessage.cpp:571
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: Glext.h:7308
int signature
Definition: object.h:145
GLenum type
Definition: Gl.h:1492
int hud_escort_return_objnum(int index)
Definition: hudescort.cpp:1032
int bm_load_animation(const char *real_filename, int *nframes, int *fps, int *keyframe, int can_drop_frames, int dir_type)
Loads a bitmap sequance so we can draw with it.
Definition: bmpman.cpp:1420
void initHeaderTextOffsets(int x, int y)
Definition: hudescort.cpp:155
Definition: hud.h:201
int Max_escort_ships
Definition: hudescort.cpp:52
int objnum
Definition: ship.h:1483
int ship_integrity_offsets[2]
Definition: hudescort.h:52
int m_kill_count_ok
Definition: scoring.h:115
typedef int(SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version *)
int instance
Definition: object.h:150
GLintptr offset
Definition: Glext.h:5497
#define VM_DEAD_VIEW
Definition: systemvars.h:33
void initShipIntegrityOffsets(int x, int y)
Definition: hudescort.cpp:188
float ship_max_hull_strength
Definition: ship.h:597
#define GM_MULTIPLAYER
Definition: systemvars.h:18
int ship_subsys_disrupted(ship_subsys *ss)
Definition: ship.cpp:9033
void initHeaderText(char *text)
Definition: hudescort.cpp:150
void renderIconDogfight(int x, int y, int index)
Definition: hudescort.cpp:404
float hull_strength
Definition: object.h:160
#define w(p)
Definition: modelsinc.h:68
void initRightAlignNames(bool align)
Definition: hudescort.cpp:205
#define SF_HIDDEN_FROM_SENSORS
Definition: ship.h:464
void hud_add_ship_to_escort(int objnum, int supress_feedback)
Definition: hudescort.cpp:849
short np_id
Definition: hudescort.cpp:41
#define MULTI_OBSERVER(np)
Definition: multi.h:140
#define HUD_SOURCE_HIDDEN
Definition: hudmessage.h:23
void hud_escort_view_toggle()
Definition: hudescort.cpp:838
void hud_escort_cull_list()
Definition: hudescort.cpp:793
int snd_play(game_snd *gs, float pan, float vol_scale, int priority, bool is_voice_msg)
Definition: sound.cpp:517
#define SHIELD_HIT_DURATION
Definition: hudshield.h:18
#define MAX_PLAYERS
Definition: pstypes.h:32
short player_id
Definition: multi.h:460
#define MULTI_DOGFIGHT
Definition: multi.h:656
void insertion_sort(void *array_base, size_t array_size, size_t element_size, int(*fncompare)(const void *, const void *))
Definition: systemvars.cpp:599
Definition: ship.h:534
int idx
Definition: multiui.cpp:761
void renderString(int x, int y, const char *str)
Definition: hud.cpp:665
bool escort_show_bright
Definition: hudescort.cpp:47
#define SF_DISABLED
Definition: ship.h:448
object Objects[MAX_OBJECTS]
Definition: object.cpp:62
GLint GLint GLint GLint GLint x
Definition: Glext.h:5182
const char * XSTR(const char *str, int index)
Definition: localize.cpp:851
int objnum
Definition: player.h:124
#define OBJ_INDEX(objp)
Definition: object.h:235
target fail sound (i.e. press targeting key, but nothing happens)
Definition: gamesnd.h:96
ship * Player_ship
Definition: ship.cpp:124
#define EG_NULL
Definition: emp.h:29
bool end_string_at_first_hash_symbol(char *src)
Definition: parselo.cpp:3833
#define OBJ_SHIP
Definition: object.h:32
int escort_hit_timer
Definition: hudescort.cpp:45
GLbitfield flags
Definition: Glext.h:6722
int first_frame
Definition: hud.h:33
#define SUBSYSTEM_ENGINE
Definition: model.h:53
ship Ships[MAX_SHIPS]
Definition: ship.cpp:122
void hud_escort_remove_player(short id)
Definition: hudescort.cpp:1074
int setGaugeColorEscort(int index, int team)
Definition: hudescort.cpp:240
struct escort_info escort_info
GLubyte GLubyte GLubyte GLubyte w
Definition: Glext.h:5679
int position[2]
Definition: hud.h:204
int set_target_objnum(ai_info *aip, int objnum)
Definition: aicode.cpp:1250
void bm_page_in_aabitmap(int bitmapnum, int nframes)
Marks a texture as being used for this level, and is anti-aliased.
Definition: bmpman.cpp:2354
#define fl2i(fl)
Definition: floating.h:33
#define MULTI_CONNECTED(np)
Definition: multi.h:136
void hud_remove_ship_from_escort(int objnum)
Definition: hudescort.cpp:954
#define MAX_COMPLETE_ESCORT_LIST
Definition: globals.h:68
int gr_force_fit_string(char *str, int max_str, int max_width)
Definition: font.cpp:48
char header_text[NAME_LENGTH]
Definition: hudescort.h:46
bool right_align_names
Definition: hudescort.h:55
void hud_setup_escort_list(int level)
Definition: hudescort.cpp:651
ship_obj Ship_obj_list
Definition: ship.cpp:162
void hud_escort_target_next()
Definition: hudescort.cpp:1006
int ship_info_index
Definition: ship.h:539
#define LOCATION
Definition: pstypes.h:245
#define VM_PADLOCK_ANY
Definition: systemvars.h:46
int escort_hit_next_flash
Definition: hudescort.cpp:46
#define timestamp_elapsed(stamp)
Definition: timer.h:102
#define OF_SHOULD_BE_DEAD
Definition: object.h:106
int ship_name_offsets[2]
Definition: hudescort.h:51
escort_info Escort_ships[MAX_COMPLETE_ESCORT_LIST]
Definition: hudescort.cpp:50
void renderPrintf(int x, int y, const char *format,...)
Definition: hud.cpp:724
int ship_status_offsets[2]
Definition: hudescort.h:53
GLint GLsizei count
Definition: Gl.h:1491
#define SF_ESCORT
Definition: ship.h:438
#define NUM_ESCORT_FRAMES
Definition: hudescort.h:18
void merge_escort_lists(escort_info *complete_escorts, int num_complete_escorts)
Definition: hudescort.cpp:688
void hud_restore_subsystem_target(ship *shipp)
Definition: hudtarget.cpp:4379
uint flags2
Definition: ship.h:645
void initListStartOffsets(int x, int y)
Definition: hudescort.cpp:161
void hud_escort_clear_all(bool clear_flags)
Definition: hudescort.cpp:482
#define VM_OTHER_SHIP
Definition: systemvars.h:35
false
Definition: lua.cpp:6789
#define SF2_STEALTH
Definition: ship.h:485
uint flags
Definition: object.h:151
int list_start_offsets[2]
Definition: hudescort.h:47
GLint level
Definition: Glext.h:5180
char type
Definition: object.h:146
int obj_signature
Definition: hudescort.cpp:39
int escort_compare_func(const void *e1, const void *e2)
Definition: hudescort.cpp:501
int header_text_offsets[2]
Definition: hudescort.h:45
net_player Net_players[MAX_PLAYERS]
Definition: multi.cpp:93
#define HUD_ESCORT_VIEW
Definition: hudgauges.h:35
#define stricmp(s1, s2)
Definition: config.h:271
virtual void render(float frametime)
Definition: hudescort.cpp:288
void hud_add_remove_ship_escort(int objnum, int supress_feedback)
Definition: hudescort.cpp:917
void initBottomBgOffset(int offset)
Definition: hudescort.cpp:177
char ship_name[NAME_LENGTH]
Definition: ship.h:604
GLint y
Definition: Gl.h:1505
int ship_name_max_width
Definition: hudescort.h:54
void hud_escort_init()
Definition: hudescort.cpp:470
scoring_struct stats
Definition: player.h:127
void initEntryStaggerWidth(int w)
Definition: hudescort.cpp:172
#define strcpy_s(...)
Definition: safe_strings.h:67
int Num_escort_ships
Definition: hudescort.cpp:51
void renderBitmap(int x, int y)
Definition: hud.cpp:782