FS2_Open
Open source remastering of the Freespace 2 engine
missionshipchoice.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 #include "ai/aigoals.h"
14 #include "anim/animplay.h"
15 #include "anim/packunpack.h"
16 #include "cfile/cfile.h"
17 #include "cmdline/cmdline.h"
18 #include "freespace2/freespace.h"
19 #include "gamehelp/contexthelp.h"
21 #include "gamesnd/gamesnd.h"
22 #include "globalincs/alphacolors.h"
23 #include "globalincs/linklist.h"
24 #include "hud/hudbrackets.h"
25 #include "hud/hudparse.h"
26 #include "hud/hudwingmanstatus.h"
27 #include "io/key.h"
28 #include "io/mouse.h"
29 #include "io/timer.h"
30 #include "lighting/lighting.h"
31 #include "localization/localize.h"
32 #include "menuui/snazzyui.h"
33 #include "mission/missionhotkey.h"
34 #include "mission/missionparse.h"
35 #include "missionui/missionbrief.h"
39 #include "network/multi.h"
40 #include "network/multimsgs.h"
42 #include "network/multiui.h"
43 #include "network/multiutil.h"
44 #include "parse/parselo.h"
45 #include "pilotfile/pilotfile.h"
46 #include "playerman/player.h"
47 #include "popup/popup.h"
48 #include "render/3d.h"
49 #include "ship/ship.h"
51 #include "weapon/weapon.h"
52 
53 
55 // Game-wide Globals
59 int Ship_select_open = 0; // This game-wide global flag is set to 1 to indicate that the ship
60  // select screen has been opened and memory allocated. This flag
61  // is needed so we can know if ship_select_close() needs to called if
62  // restoring a game from the Options screen invoked from ship select
63 
64 int Commit_pressed; // flag to indicate that the commit button was pressed
65  // use a flag, so the ship_create() can be done at the end of the loop
66 
68 // Module Globals
70 static int Ship_anim_class = -1; // ship class that is playing as an animation
71 static int Ss_delta_x, Ss_delta_y; // used to offset the carried icon to make it smoothly leave static position
72 
73 // UnknownPlayer //
76 
78 //static matrix ShipScreenOrient = IDENTITY_MATRIX;
79 
81 // UI Data structs
83 typedef struct ss_icon_info
84 {
89 } ss_icon_info;
90 
91 typedef struct ss_slot_info
92 {
93  int status; // slot status (WING_SLOT_DISABLED, etc)
94  int sa_index; // index into ship arrival list, -1 if ship is created
96 } ss_slot_info;
97 
98 typedef struct ss_wing_info
99 {
101  int wingnum;
102  int is_late;
104 } ss_wing_info;
105 
106 //ss_icon_info Ss_icons[MAX_SHIP_CLASSES]; // holds ui info on different ship icons
107 //ss_wing_info Ss_wings[MAX_WING_BLOCKS]; // holds ui info for wings and wing slots
108 
111 
114 
116 
117 int Selected_ss_class; // set to ship class of selected ship, -1 if none selected
118 int Hot_ss_icon; // index that icon is over in list (0..MAX_WING_SLOTS-1)
119 int Hot_ss_slot; // index for slot that mouse is over (0..MAX_WSS_SLOTS)
120 
122 // Ship Select UI
125 
127 
128 static int Ship_anim_coords[GR_NUM_RESOLUTIONS][2] = {
129  {
130  257, 84 // GR_640
131  },
132  {
133  412, 135 // GR_1024
134  }
135 };
136 
137 static int Ship_info_coords[GR_NUM_RESOLUTIONS][2] = {
138  {
139  28, 78 // GR_640
140  },
141  {
142  45, 125 // GR_1024
143  }
144 };
145 
146 // coordinate lookup indicies
147 #define SHIP_SELECT_X_COORD 0
148 #define SHIP_SELECT_Y_COORD 1
149 #define SHIP_SELECT_W_COORD 2
150 #define SHIP_SELECT_H_COORD 3
151 
152 
153 // NK: changed from 37 to 51 for new FS2 animations
154 #define SHIP_ANIM_LOOP_FRAME 51
155 
156 #define MAX_ICONS_ON_SCREEN 4
157 
158 // (x,y) pairs for ship icon and ship icon number
160  {
161  {23,331,4,341},
162  {23,361,4,371},
163  {23,391,4,401},
164  {23,421,4,431}
165  },
166  {
167  {29,530,10,540},
168  {29,578,10,588},
169  {29,626,10,636},
170  {29,674,10,684}
171  }
172 };
173 
174 // Store the x locations for the icons in the wing formations
176  {
177  {124,345},
178  {100,376},
179  {148,376},
180  {124,407},
181 
182  {222,345},
183  {198,376},
184  {246,376},
185  {222,407},
186 
187  {320,345},
188  {296,376},
189  {344,376},
190  {320,407}
191  },
192  {
193  {218,584},
194  {194,615},
195  {242,615},
196  {218,646},
197 
198  {373,584},
199  {349,615},
200  {397,615},
201  {373,646},
202 
203  {531,584},
204  {507,615},
205  {555,615},
206  {531,646}
207  }
208 };
209 
211 // Linked List of icons to show on ship selection list
213 #define SS_ACTIVE_ITEM_USED (1<<0)
214 typedef struct ss_active_item
215 {
218  int flags;
220 
221 static ss_active_item SS_active_head;
222 //static ss_active_item SS_active_items[MAX_WSS_SLOTS];//DTP commented out or else singleplayer will only have a max of MAX_WSS_SLOTS ships
223 static ss_active_item SS_active_items[MAX_SHIP_CLASSES];//DTP, now we have all ships in the TBL, as they can all be playerships
224 
225 static int SS_active_list_start;
226 static int SS_active_list_size;
227 
229 // Background bitmaps data for ship_select
231 static char* Ship_select_background_fname[GR_NUM_RESOLUTIONS] = {
232  "ShipSelect",
233  "2_ShipSelect"
234 };
235 
236 static char* Ship_select_background_mask_fname[GR_NUM_RESOLUTIONS] = {
237  "ShipSelect-m",
238  "2_ShipSelect-m"
239 };
240 
242 
244 // Ship select specific buttons
246 #define NUM_SS_BUTTONS 4
247 #define SS_BUTTON_SCROLL_UP 0
248 #define SS_BUTTON_SCROLL_DOWN 1
249 #define SS_BUTTON_RESET 2
250 #define SS_BUTTON_DUMMY 3 // needed to capture mouse for drag/drop icons
251 
252 // convenient struct for handling all button controls
253 struct ss_buttons {
254  char *filename;
255  int x, y, xt, yt;
256  int hotspot;
258  UI_BUTTON button; // because we have a class inside this struct, we need the constructor below..
259 
260  ss_buttons(char *name, int x1, int y1, int xt1, int yt1, int h, int s) : filename(name), x(x1), y(y1), xt(xt1), yt(yt1), hotspot(h), scrollable(s) {}
261 };
262 
263 static ss_buttons Ship_select_buttons[GR_NUM_RESOLUTIONS][NUM_SS_BUTTONS] = {
264  { // GR_640
265  ss_buttons("ssb_08", 5, 303, -1, -1, 8, 0), // SCROLL UP
266  ss_buttons("ssb_09", 5, 454, -1, -1, 9, 0), // SCROLL DOWN
267  ss_buttons("ssb_39", 571, 347, -1, -1, 39,0), // RESET
268  ss_buttons("ssb_39", 0, 0, -1, -1, 99,0) // dummy for drag n' drop
269  },
270  { // GR_1024
271  ss_buttons("2_ssb_08", 8, 485, -1, -1, 8, 0), // SCROLL UP
272  ss_buttons("2_ssb_09", 8, 727, -1, -1, 9, 0), // SCROLL DOWN
273  ss_buttons("2_ssb_39", 913, 556, -1, -1, 39,0), // RESET
274  ss_buttons("2_ssb_39", 0, 0, -1, -1, 99,0) // dummy for drag n' drop
275  }
276 };
277 
278 // ship select text
279 #define SHIP_SELECT_NUM_TEXT 1
281  { // GR_640
282  { "Reset", 1337, 580, 337, UI_XSTR_COLOR_GREEN, -1, &Ship_select_buttons[0][SS_BUTTON_RESET].button }
283  },
284  { // GR_1024
285  { "Reset", 1337, 938, 546, UI_XSTR_COLOR_GREEN, -1, &Ship_select_buttons[1][SS_BUTTON_RESET].button }
286  }
287 };
288 
289 // Mask bitmap pointer and Mask bitmap_id
290 static bitmap* ShipSelectMaskPtr; // bitmap pointer to the ship select mask bitmap
291 static ubyte* ShipSelectMaskData; // pointer to actual bitmap data
292 static int Shipselect_mask_w, Shipselect_mask_h;
293 static int ShipSelectMaskBitmap; // bitmap id of the ship select mask bitmap
294 
295 static MENU_REGION Region[NUM_SHIP_SELECT_REGIONS];
296 static int Num_mask_regions;
297 
298 //stuff for ht&l. vars and such
299 extern float View_zoom, Canv_h2, Canv_w2;
300 extern int Cmdline_nohtl;
301 
303 // Drag and Drop variables
305 typedef struct ss_carry_icon_info
306 {
307  int from_slot; // slot index (0..MAX_WSS_SLOTS-1), -1 if carried from list
308  int ship_class; // ship class of carried icon
311 
313 
315 // Internal function prototypes
317 
318 // render functions
319 void draw_ship_icons();
320 void draw_ship_icon_with_number(int screen_offset, int ship_class);
321 void start_ship_animation(int ship_class, int play_sound=0);
322 
323 // pick-up
324 int pick_from_ship_list(int screen_offset, int ship_class);
325 void pick_from_wing(int wb_num, int ws_num);
326 
327 // ui related
328 void ship_select_button_do(int i);
331 void ss_restore_loadout();
332 void maybe_change_selected_wing_ship(int wb_num, int ws_num);
333 
334 // init functions
335 void ss_init_pool(team_data *pteam);
336 int create_wings();
337 
338 // loading/unloading
339 void ss_unload_all_icons();
340 void ss_unload_all_anims();
341 void ss_init_units();
342 anim* ss_load_individual_animation(int ship_class);
343 
344 // Carry icon functions
346 void ss_reset_carried_icon();
347 void ss_set_carried_icon(int from_slot, int ship_class);
348 
349 #define SHIP_DESC_X 445
350 #define SHIP_DESC_Y 273
351 
352 const char *ss_tooltip_handler(const char *str)
353 {
354  if (Selected_ss_class < 0)
355  return NULL;
356 
357  if (!stricmp(str, NOX("@ship_name"))) {
358  return Ship_info[Selected_ss_class].name;
359 
360  } else if (!stricmp(str, NOX("@ship_type"))) {
361  return Ship_info[Selected_ss_class].type_str;
362 
363  } else if (!stricmp(str, NOX("@ship_maneuverability"))) {
364  return Ship_info[Selected_ss_class].maneuverability_str;
365 
366  } else if (!stricmp(str, NOX("@ship_armor"))) {
367  return Ship_info[Selected_ss_class].armor_str;
368 
369  } else if (!stricmp(str, NOX("@ship_manufacturer"))) {
370  return Ship_info[Selected_ss_class].manufacturer_str;
371 
372  } else if (!stricmp(str, NOX("@ship_desc"))) {
373  char *str2;
374  int x, y, w, h;
375 
376  str2 = Ship_info[Selected_ss_class].desc;
377  if (str2 == NULL)
378  return NULL;
379 
380  gr_get_string_size(&w, &h, str2);
381  x = SHIP_DESC_X - w / 2;
382  y = SHIP_DESC_Y - h / 2;
383 
385  gr_rect(x - 5, y - 5, w + 10, h + 10, GR_RESIZE_MENU);
386 
388  gr_string(x, y, str2, GR_RESIZE_MENU);
389  return str2;
390  }
391 
392  return NULL;
393 }
394 
395 // Is an icon being carried?
397 {
398  if ( Carried_ss_icon.ship_class >= 0 ) {
399  return 1;
400  }
401 
402  return 0;
403 }
404 
405 // Clear out carried icon info
407 {
408  Carried_ss_icon.from_slot = -1;
409  Carried_ss_icon.ship_class = -1;
410 }
411 
412 // return !0 if carried icon has moved from where it was picked up
414 {
415  int mx, my;
416 
417  mouse_get_pos_unscaled( &mx, &my );
418  if ( Carried_ss_icon.from_x != mx || Carried_ss_icon.from_y != my) {
419  return 1;
420  }
421 
422  return 0;
423 }
424 
425 // Set carried icon data
426 void ss_set_carried_icon(int from_slot, int ship_class)
427 {
428  Carried_ss_icon.from_slot = from_slot;
429  Carried_ss_icon.ship_class = ship_class;
430 
431  // Set the mouse to captured
432  Ship_select_buttons[gr_screen.res][SS_BUTTON_DUMMY].button.capture_mouse();
433 }
434 
435 // clear all active list items, and reset the flags inside the SS_active_items[] array
437 {
438  int i;
439  for ( i = 0; i < static_cast<int>(Ship_info.size()); i++ ) { //DTP singleplayer ship choice fix
440  //for ( i = 0; i < MAX_WSS_SLOTS; i++ ) {
441  SS_active_items[i].flags = 0;
442  SS_active_items[i].ship_class = -1;
443  }
444  list_init(&SS_active_head);
445 
446  SS_active_list_start = 0;
447  SS_active_list_size = 0;
448 }
449 
450 
451 // get a free element from SS_active_items[]
453 {
454  int i;
455  for ( i = 0; i < static_cast<int>(Ship_info.size()); i++ ) {
456  //for ( i = 0; i < MAX_WSS_SLOTS; i++ ) { //DTP, ONLY MAX_WSS_SLOTS SHIPS ???
457  if ( SS_active_items[i].flags == 0 ) {
458  SS_active_items[i].flags |= SS_ACTIVE_ITEM_USED;
459  return &SS_active_items[i];
460  }
461  }
462  return NULL;
463 }
464 
465 
466 // add a ship into the active list
467 void active_list_add(int ship_class)
468 {
469  ss_active_item *sai;
470 
472  Assert(sai != NULL);
473  sai->ship_class = ship_class;
474  list_append(&SS_active_head, sai);
475 }
476 
477 // remove a ship from the active list
478 void active_list_remove(int ship_class)
479 {
480  ss_active_item *sai, *temp;
481 
482  // next store players not assigned to wings
483  sai = GET_FIRST(&SS_active_head);
484 
485  while(sai != END_OF_LIST(&SS_active_head)){
486  temp = GET_NEXT(sai);
487  if ( sai->ship_class == ship_class ) {
488  list_remove(&SS_active_head, sai);
489  sai->flags = 0;
490  }
491  sai = temp;
492  }
493 }
494 
495 // Build up the ship selection active list, which is a list of all ships that the player
496 // can choose from.
498 {
499  int i;
500  ss_active_item *sai;
501 
502  Assert( Ss_pool != NULL );
503 
505 
506  // build the active list
507  for ( i = 0; i < static_cast<int>(Ship_info.size()); i++ ) {
508  if ( Ss_pool[i] > 0 ) {
510  if ( sai != NULL ) {
511  sai->ship_class = i;
512  list_append(&SS_active_head, sai);
513  SS_active_list_size++;
514  }
515  }
516  }
517 }
518 
520 {
521  int i;
522  ss_buttons *b;
523 
524  for ( i = 0; i < NUM_SS_BUTTONS; i++ ) {
525  b = &Ship_select_buttons[gr_screen.res][i];
526  if ( b->button.pressed() ) {
528  }
529  }
530 }
531 
532 // reset the ship selection to the mission defaults
534 {
535  if ( Game_mode & GM_MULTIPLAYER ) {
536  Int3();
537  return;
538  }
539 
541  ss_init_units();
545 
546  // reset weapons
548 
550 }
551 
552 // -------------------------------------------------------------------
553 // ship_select_redraw_pressed_buttons()
554 //
555 // Redraw any ship select buttons that are pressed down. This function is needed
556 // since we sometimes need to draw pressed buttons last to ensure the entire
557 // button gets drawn (and not overlapped by other buttons)
558 //
560 {
561  int i;
562  ss_buttons *b;
563 
565 
566  for ( i = 0; i < NUM_SS_BUTTONS; i++ ) {
567  b = &Ship_select_buttons[gr_screen.res][i];
568  if ( b->button.pressed() ) {
569  b->button.draw_forced(2);
570  }
571  }
572 }
573 
575 {
576  ss_buttons *b;
577  int i;
578 
579  for ( i = 0; i < NUM_SS_BUTTONS; i++ ) {
580  b = &Ship_select_buttons[gr_screen.res][i];
581  b->button.create( &Ship_select_ui_window, "", b->x, b->y, 60, 30, b->scrollable);
582  // set up callback for when a mouse first goes over a button
584  b->button.set_bmaps(b->filename);
585  b->button.link_hotspot(b->hotspot);
586  }
587 
588  // add all xstrs
589  for(i=0; i<SHIP_SELECT_NUM_TEXT; i++){
590  Ship_select_ui_window.add_XSTR(&Ship_select_text[gr_screen.res][i]);
591  }
592 
593  // We don't want to have the reset button appear in multiplayer
594  if ( Game_mode & GM_MULTIPLAYER ) {
595  Ship_select_buttons[gr_screen.res][SS_BUTTON_RESET].button.disable();
596  Ship_select_buttons[gr_screen.res][SS_BUTTON_RESET].button.hide();
597  }
598 
599  Ship_select_buttons[gr_screen.res][SS_BUTTON_DUMMY].button.disable();
600  Ship_select_buttons[gr_screen.res][SS_BUTTON_DUMMY].button.hide();
601 }
602 
603 // -------------------------------------------------------------------------------------
604 // ship_select_button_do() do the button action for the specified pressed button
605 //
607 {
608  if ( Background_playing )
609  return;
610 
611  switch ( i ) {
614  break;
615 
616  if ( common_scroll_down_pressed(&SS_active_list_start, SS_active_list_size, MAX_ICONS_ON_SCREEN) ) {
618  } else {
620  }
621  break;
622 
625  break;
626 
627  if ( common_scroll_up_pressed(&SS_active_list_start, SS_active_list_size, MAX_ICONS_ON_SCREEN) ) {
629  } else {
631  }
632 
633  break;
634 
635  case SHIP_SELECT_RESET:
637  break;
638  } // end switch
639 }
640 
641 // ---------------------------------------------------------------------
642 // ship_select_init() is called once when the ship select screen begins
643 //
644 //
646 {
647 // SS_active_items = new ss_active_item[Num_ship_classes];
648 
649  common_set_interface_palette("ShipPalette");
651 
652  // if in multiplayer -- set my state to be ship select
653  if ( Game_mode & GM_MULTIPLAYER ){
654  // also set the ship which is mine as the default
656  }
657 
658  set_active_ui(&Ship_select_ui_window);
660 
662 
665 
666  if ( Ship_select_open ) {
667  //reset the animation
668  Ship_anim_class = -1;
670  common_buttons_maybe_reload(&Ship_select_ui_window); // AL 11-21-97: this is necessary since we may returning from the hotkey
671  // screen, which can release common button bitmaps.
673  nprintf(("Alan","ship_select_init() returning without doing anything\n"));
674  return;
675  }
676 
677  nprintf(("Alan","entering ship_select_init()\n"));
679 
680  ShipSelectMaskBitmap = bm_load(Ship_select_background_mask_fname[gr_screen.res]);
681  if (ShipSelectMaskBitmap < 0) {
682  if (gr_screen.res == GR_640) {
683  Error(LOCATION,"Could not load in 'shipselect-m'!");
684  } else if (gr_screen.res == GR_1024) {
685  Error(LOCATION,"Could not load in '2_shipselect-m'!");
686  }
687  }
688 
689  Shipselect_mask_w = -1;
690  Shipselect_mask_h = -1;
691 
692  // get a pointer to bitmap by using bm_lock()
693  ShipSelectMaskPtr = bm_lock(ShipSelectMaskBitmap, 8, BMP_AABITMAP);
694  ShipSelectMaskData = (ubyte*)ShipSelectMaskPtr->data;
695  bm_get_info(ShipSelectMaskBitmap, &Shipselect_mask_w, &Shipselect_mask_h);
696 
697  // Set up the mask regions
698  // initialize the different regions of the menu that will react when the mouse moves over it
699  Num_mask_regions = 0;
700 
701  snazzy_menu_add_region(&Region[Num_mask_regions++], "", COMMON_BRIEFING_REGION, 0);
702  snazzy_menu_add_region(&Region[Num_mask_regions++], "", COMMON_SS_REGION, 0);
703  snazzy_menu_add_region(&Region[Num_mask_regions++], "", COMMON_WEAPON_REGION, 0);
704  snazzy_menu_add_region(&Region[Num_mask_regions++], "", COMMON_COMMIT_REGION, 0);
705  snazzy_menu_add_region(&Region[Num_mask_regions++], "", COMMON_HELP_REGION, 0);
706  snazzy_menu_add_region(&Region[Num_mask_regions++], "", COMMON_OPTIONS_REGION, 0);
707 
708  snazzy_menu_add_region(&Region[Num_mask_regions++], "", SHIP_SELECT_SHIP_SCROLL_UP, 0);
709  snazzy_menu_add_region(&Region[Num_mask_regions++], "", SHIP_SELECT_SHIP_SCROLL_DOWN, 0);
710 
711  snazzy_menu_add_region(&Region[Num_mask_regions++], "", SHIP_SELECT_ICON_0, 0);
712  snazzy_menu_add_region(&Region[Num_mask_regions++], "", SHIP_SELECT_ICON_1, 0);
713  snazzy_menu_add_region(&Region[Num_mask_regions++], "", SHIP_SELECT_ICON_2, 0);
714  snazzy_menu_add_region(&Region[Num_mask_regions++], "", SHIP_SELECT_ICON_3, 0);
715 
716  snazzy_menu_add_region(&Region[Num_mask_regions++], "", WING_0_SHIP_0, 0);
717  snazzy_menu_add_region(&Region[Num_mask_regions++], "", WING_0_SHIP_1, 0);
718  snazzy_menu_add_region(&Region[Num_mask_regions++], "", WING_0_SHIP_2, 0);
719  snazzy_menu_add_region(&Region[Num_mask_regions++], "", WING_0_SHIP_3, 0);
720  snazzy_menu_add_region(&Region[Num_mask_regions++], "", WING_1_SHIP_0, 0);
721  snazzy_menu_add_region(&Region[Num_mask_regions++], "", WING_1_SHIP_1, 0);
722  snazzy_menu_add_region(&Region[Num_mask_regions++], "", WING_1_SHIP_2, 0);
723  snazzy_menu_add_region(&Region[Num_mask_regions++], "", WING_1_SHIP_3, 0);
724  snazzy_menu_add_region(&Region[Num_mask_regions++], "", WING_2_SHIP_0, 0);
725  snazzy_menu_add_region(&Region[Num_mask_regions++], "", WING_2_SHIP_1, 0);
726  snazzy_menu_add_region(&Region[Num_mask_regions++], "", WING_2_SHIP_2, 0);
727  snazzy_menu_add_region(&Region[Num_mask_regions++], "", WING_2_SHIP_3, 0);
728 
729  Ship_select_open = 1; // This game-wide global flag is set to 1 to indicate that the ship
730  // select screen has been opened and memory allocated. This flag
731  // is needed so we can know if ship_select_close() needs to called if
732  // restoring a game from the Options screen invoked from ship select
733 
734  // init ship selection masks and buttons
735  Ship_select_ui_window.create( 0, 0, gr_screen.max_w_unscaled, gr_screen.max_h_unscaled, 0 );
736  Ship_select_ui_window.set_mask_bmap(Ship_select_background_mask_fname[gr_screen.res]);
737  Ship_select_ui_window.tooltip_handler = ss_tooltip_handler;
738  common_buttons_init(&Ship_select_ui_window);
740 
741  // init ship selection background bitmap
743 
744  // init ship selection ship model rendering window
746 }
747 
748 
749 // Return the ship class for the icon specified by index. Need to iterate through the active
750 // list of icons to find out what ship class for this icon
751 //
752 // input: index => list index (0..3)
753 // exit: ship class, -1 if none
754 //
756 {
757  ss_active_item *sai;
758  int list_entry, i, count;
759 
760  i = 0;
761  count = 0;
762  list_entry = -1;
763  for ( sai = GET_FIRST(&SS_active_head); sai != END_OF_LIST(&SS_active_head); sai = GET_NEXT(sai) ) {
764  count++;
765  if ( count <= SS_active_list_start )
766  continue;
767 
768  if ( i >= MAX_ICONS_ON_SCREEN )
769  break;
770 
771  if ( i == index ) {
772  list_entry = sai->ship_class;
773  break;
774  }
775 
776  i++;
777  }
778 
779  return list_entry;
780 }
781 
782 // ---------------------------------------------------------------------
783 // maybe_pick_up_list_icon()
784 //
786 {
787  int ship_class;
788 
789  ship_class = ss_get_ship_class_from_list(offset);
790  if ( ship_class != -1 ) {
791  pick_from_ship_list(offset, ship_class);
792  }
793 }
794 
795 // ---------------------------------------------------------------------
796 // maybe_change_selected_ship()
797 //
799 {
800  int ship_class;
801 
802  ship_class = ss_get_ship_class_from_list(offset);
803  if ( ship_class == -1 )
804  return;
805 
806  if ( Ss_mouse_down_on_region != (SHIP_SELECT_ICON_0+offset) ) {
807  return;
808  }
809 
810  if ( Selected_ss_class == -1 ) {
811  Selected_ss_class = ship_class;
813  }
814  else if ( Selected_ss_class != ship_class ) {
815  Selected_ss_class = ship_class;
817  }
818  else
819  Assert( Selected_ss_class == ship_class );
820 }
821 
822 void maybe_change_selected_wing_ship(int wb_num, int ws_num)
823 {
824  Assert(wb_num >= 0 && wb_num < MAX_WING_BLOCKS);
825  Assert(ws_num >= 0 && ws_num < MAX_WING_SLOTS);
826  Assert( (Ss_wings != NULL) && (Wss_slots != NULL) );
827 
828  if ( Ss_wings[wb_num].wingnum < 0 ) {
829  return;
830  }
831 
832  if ( Selected_ss_class != -1 && Selected_ss_class != Wss_slots[wb_num*MAX_WING_SLOTS+ws_num].ship_class ) {
835  }
836 }
837 
838 // ---------------------------------------------------------------------
839 // do_mouse_over_wing_slot()
840 //
841 // returns: 0 => icon wasn't dropped onto slot
842 // 1 => icon was dropped onto slot
843 int do_mouse_over_wing_slot(int block, int slot)
844 {
845  Hot_ss_slot = block*MAX_WING_SLOTS + slot;
846 
847  if ( !mouse_down(MOUSE_LEFT_BUTTON) ) {
848  if ( ss_icon_being_carried() ) {
849 
850  if ( ss_disabled_slot(block*MAX_WING_SLOTS+slot) ) {
852  return 0;
853  }
854 
855  if ( !ss_carried_icon_moved() ) {
857  return 0;
858  }
859 
860  ss_drop(Carried_ss_icon.from_slot, Carried_ss_icon.ship_class, Hot_ss_slot, -1);
862  }
863  }
864  else {
865  if ( Ss_mouse_down_on_region == (WING_0_SHIP_0+block*MAX_WING_SLOTS+slot) ) {
866  pick_from_wing(block, slot);
867  }
868  }
869 
870  return 1;
871 }
872 
874 {
875  Hot_ss_icon = index;
876 
878  return;
879  }
880 
883 }
884 
885 // Icon has been dropped, but not onto a wing slot
887 {
888  if ( Drop_icon_mflag ) {
889  if ( ss_icon_being_carried() ) {
890  // Add back into the ship entry list
891  if ( Carried_ss_icon.from_slot >= 0 ) {
892  // return to list
893  ss_drop(Carried_ss_icon.from_slot, -1, -1, Carried_ss_icon.ship_class);
894  } else {
895  if ( ss_carried_icon_moved() ) {
897  }
898  }
900  }
901  }
902 }
903 
904 // maybe flash a button if player hasn't done anything for a while
906 {
907  if ( common_flash_bright() ) {
908  // weapon loadout button
911  } else {
913  }
914  }
915 }
916 
917 // blit any active ship information text
919 {
920  int y_start, line_height;
921  ship_info *sip;
922  char str[100];
923  color *header_clr = &Color_white;
924  color *text = &Color_green;
925 
926 
927  // if we don't have a valid ship selected, do nothing
928  if(Selected_ss_class == -1){
929  return;
930  }
931 
932  // get the ship class
934 
935  // starting line
936  y_start = Ship_info_coords[gr_screen.res][SHIP_SELECT_Y_COORD];
937 
938  line_height = gr_get_font_height() + 1;
939 
940  memset(str,0,100);
941 
942  // blit the ship class (name)
943  gr_set_color_fast(header_clr);
944  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD], y_start, XSTR("Class",739), GR_RESIZE_MENU);
945  y_start += line_height;
946  if(strlen((sip->alt_name[0]) ? sip->alt_name : sip->name)){
947  gr_set_color_fast(text);
948 
949  // Goober5000
950  char temp[NAME_LENGTH];
951  strcpy_s(temp, (sip->alt_name[0]) ? sip->alt_name : sip->name);
953 
954  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD]+4, y_start, temp, GR_RESIZE_MENU);
955  }
956  y_start += line_height;
957 
958  // blit the ship type
959  gr_set_color_fast(header_clr);
960  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD], y_start, XSTR("Type",740), GR_RESIZE_MENU);
961  y_start += line_height;
962  gr_set_color_fast(text);
963  if((sip->type_str != NULL) && strlen(sip->type_str)){
964  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD]+4, y_start, sip->type_str, GR_RESIZE_MENU);
965  }
966  else
967  {
968  ship_get_type(str, sip);
969  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD]+4, y_start, str, GR_RESIZE_MENU);
970  }
971  y_start+=line_height;
972 
973  // blit the ship length
974  gr_set_color_fast(header_clr);
975  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD], y_start, XSTR("Length",741), GR_RESIZE_MENU);
976  y_start += line_height;
977  gr_set_color_fast(text);
978  if((sip->ship_length != NULL) && strlen(sip->ship_length)){
979  if (Lcl_gr || Lcl_pl) {
980  // in german and polish, drop the s from Meters and make sure M is caps
981  char *sp = strstr(sip->ship_length, "Meters");
982  if (sp) {
983  sp[5] = ' '; // make the old s a space now
984  }
985  }
986  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD]+4, y_start, sip->ship_length, GR_RESIZE_MENU);
987  }
988  else if(ShipSelectModelNum >= 0)
989  {
991  sprintf( str, "%d", fl2i(pm->maxs.xyz.z - pm->mins.xyz.z) );
992  strcat_s(str, " M");
993  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD]+4, y_start, str, GR_RESIZE_MENU);
994  }
995  else
996  {
997  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD]+4, y_start, "Unknown", GR_RESIZE_MENU);
998  }
999  y_start += line_height;
1000 
1001  // blit the max velocity
1002  gr_set_color_fast(header_clr);
1003  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD], y_start, XSTR("Max Velocity",742), GR_RESIZE_MENU);
1004  y_start += line_height;
1005  sprintf(str, XSTR("%d m/s",743),fl2i((float)sip->max_vel.xyz.z * Hud_speed_multiplier));
1006  gr_set_color_fast(text);
1007  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD]+4, y_start,str, GR_RESIZE_MENU);
1008  y_start += line_height;
1009 
1010  // blit the maneuverability
1011  gr_set_color_fast(header_clr);
1012  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD], y_start, XSTR("Maneuverability",744), GR_RESIZE_MENU);
1013  y_start += line_height;
1014  gr_set_color_fast(text);
1015  if((sip->maneuverability_str != NULL) && strlen(sip->maneuverability_str)){
1016  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD]+4, y_start, sip->maneuverability_str, GR_RESIZE_MENU);
1017  }
1018  else if(ShipSelectModelNum >= 0)
1019  {
1020  int sum = fl2i(sip->rotation_time.xyz.x + sip->rotation_time.xyz.y);
1021  if(sum <= 6)
1022  strcpy_s(str, "Excellent");
1023  else if(sum < 7)
1024  strcpy_s(str, "High");
1025  else if(sum < 8)
1026  strcpy_s(str, "Good");
1027  else if(sum < 9)
1028  strcpy_s(str, "Average");
1029  else if(sum < 10)
1030  strcpy_s(str, "Poor");
1031  else if(sum < 15)
1032  strcpy_s(str, "Very Poor");
1033  else
1034  strcpy_s(str, "Extremely Poor");
1035 
1036  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD]+4, y_start, str, GR_RESIZE_MENU);
1037  }
1038  else
1039  {
1040  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD]+4, y_start, "Unknown", GR_RESIZE_MENU);
1041  }
1042  y_start += line_height;
1043 
1044  // blit the armor
1045  gr_set_color_fast(header_clr);
1046  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD], y_start, XSTR("Armor",745), GR_RESIZE_MENU);
1047  y_start += line_height;
1048  gr_set_color_fast(text);
1049  if((sip->armor_str != NULL) && strlen(sip->armor_str)){
1050  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD]+4, y_start, sip->armor_str, GR_RESIZE_MENU);
1051  }
1052  else
1053  {
1054  int sum = fl2i(sip->max_hull_strength + sip->max_shield_strength);
1055  if(sum <= 600)
1056  strcpy_s(str, "Light");
1057  else if(sum <= 700)
1058  strcpy_s(str, "Average");
1059  else if(sum <= 900)
1060  strcpy_s(str, "Medium");
1061  else if(sum <= 1100)
1062  strcpy_s(str, "Heavy");
1063  else if(sum <= 1300)
1064  strcpy_s(str, "Very Heavy");
1065  else if(sum <= 2000)
1066  strcpy_s(str, "Ultra Heavy");
1067  else if(sum <= 30000)
1068  strcpy_s(str, "Light Capital");
1069  else if(sum <= 75000)
1070  strcpy_s(str, "Medium Capital");
1071  else if(sum <= 200000)
1072  strcpy_s(str, "Heavy Capital");
1073  else if(sum <= 800000)
1074  strcpy_s(str, "Very Heavy Capital");
1075  else
1076  strcpy_s(str, "Ultra Heavy Capital");
1077 
1078 
1079  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD]+4, y_start,str, GR_RESIZE_MENU);
1080  }
1081  y_start += line_height;
1082 
1083  // blit the gun mounts
1084  gr_set_color_fast(header_clr);
1085  if((sip->gun_mounts != NULL) && strlen(sip->gun_mounts))
1086  {
1087  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD], y_start, XSTR("Gun Mounts",746), GR_RESIZE_MENU);
1088  y_start += line_height;
1089  gr_set_color_fast(text);
1090  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD]+4, y_start, sip->gun_mounts, GR_RESIZE_MENU);
1091  }
1092  else if(ShipSelectModelNum >= 0)
1093  {
1094  //Calculate the number of gun mounts
1095  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD], y_start, XSTR("Gun Mounts",746), GR_RESIZE_MENU);
1096  y_start += line_height;
1097  gr_set_color_fast(text);
1098  int i;
1099  int sum = 0;
1101  for(i = 0; i < pm->n_guns; i++)
1102  {
1103  sum += pm->gun_banks[i].num_slots;
1104  }
1105  if(sum != 0)
1106  sprintf(str, "%d", sum);
1107  else
1108  strcpy_s(str, "None");
1109  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD]+4, y_start, str, GR_RESIZE_MENU);
1110  }
1111  else
1112  {
1113  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD], y_start, XSTR("Gun Banks",1626), GR_RESIZE_MENU);
1114  y_start += line_height;
1115  gr_set_color_fast(text);
1116  if(sip->num_primary_banks)
1117  {
1118  sprintf(str, "%d", sip->num_primary_banks);
1119  }
1120  else
1121  {
1122  strcpy_s(str, "None");
1123  }
1124  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD]+4, y_start, str, GR_RESIZE_MENU);
1125  }
1126  y_start += line_height;
1127 
1128  // blit the missile banks
1129  gr_set_color_fast(header_clr);
1130  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD], y_start, XSTR("Missile Banks",747), GR_RESIZE_MENU);
1131  y_start += line_height;
1132  gr_set_color_fast(text);
1133  if((sip->missile_banks != NULL) && strlen(sip->missile_banks)){
1134  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD]+4, y_start, sip->missile_banks, GR_RESIZE_MENU);
1135  }
1136  else
1137  {
1138  if(sip->num_secondary_banks)
1139  {
1140  sprintf(str, "%d", sip->num_secondary_banks);
1141  }
1142  else
1143  {
1144  strcpy_s(str, "None");
1145  }
1146  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD]+4, y_start, str, GR_RESIZE_MENU);
1147  }
1148  y_start += line_height;
1149 
1150  if(ShipSelectModelNum >= 0)
1151  {
1152  int num_turrets = 0;
1153  int x;
1154  for(x = 0; x < sip->n_subsystems; x++)
1155  {
1156  if(sip->subsystems[x].type == SUBSYSTEM_TURRET)
1157  num_turrets++;
1158  /*
1159  for(y = 0; y < MAX_SHIP_PRIMARY_BANKS || y < MAX_SHIP_SECONDARY_BANKS; y++)
1160  {
1161  if(y < MAX_SHIP_PRIMARY_BANKS)
1162  {
1163  if(sip->subsystems[x].primary_banks[y] != -1)
1164  {
1165  num_turrets++;
1166  break;
1167  }
1168  }
1169 
1170  if(y < MAX_SHIP_SECONDARY_BANKS)
1171  {
1172  if(sip->subsystems[x].secondary_banks[y] != -1)
1173  {
1174  num_turrets++;
1175  break;
1176  }
1177  }
1178  }
1179  */
1180  }
1181  if(num_turrets)
1182  {
1183  gr_set_color_fast(header_clr);
1184  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD], y_start, XSTR("Turrets",1627), GR_RESIZE_MENU);
1185  y_start += line_height;
1186  gr_set_color_fast(text);
1187  sprintf(str, "%d", num_turrets);
1188  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD]+4, y_start, str, GR_RESIZE_MENU);
1189  y_start += line_height;
1190  }
1191  }
1192 
1193  // blit the manufacturer
1194  gr_set_color_fast(header_clr);
1195  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD], y_start, XSTR("Manufacturer",748), GR_RESIZE_MENU);
1196  y_start += line_height;
1197  gr_set_color_fast(text);
1198  if((sip->manufacturer_str != NULL) && strlen(sip->manufacturer_str)){
1199  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD]+4, y_start, sip->manufacturer_str, GR_RESIZE_MENU);
1200  }
1201  else
1202  {
1203  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD]+4, y_start, Species_info[sip->species].species_name, GR_RESIZE_MENU);
1204  }
1205  y_start += line_height;
1206 
1207  // blit the _short_ text description, if it exists
1208  // split the text info up
1209 
1210  if (sip->desc == NULL)
1211  return;
1212 
1213  gr_set_color_fast(header_clr);
1214  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD], y_start, XSTR("Description",1571), GR_RESIZE_MENU);
1215  y_start += line_height;
1216 
1217  Assert(strlen(sip->desc));
1218 
1219  int n_lines;
1220  int n_chars[MAX_BRIEF_LINES];
1221  const char *p_str[MAX_BRIEF_LINES];
1222  char Ship_select_ship_info_text[1500];
1223  char Ship_select_ship_info_lines[MAX_NUM_SHIP_DESC_LINES][SHIP_SELECT_SHIP_INFO_MAX_LINE_LEN];
1224  int Ship_select_ship_info_line_count;
1225 
1226  strcpy_s(Ship_select_ship_info_text, sip->desc);
1227 
1228  if(Ship_select_ship_info_text[0] != '\0'){
1229  // split the string into multiple lines
1230  // MageKing17: Changed to use the widths determined by Yarn here: http://scp.indiegames.us/mantis/view.php?id=3144#c16516
1231  n_lines = split_str(Ship_select_ship_info_text, gr_screen.res == GR_640 ? 204 : 328, n_chars, p_str, MAX_NUM_SHIP_DESC_LINES, 0);
1232 
1233  // copy the split up lines into the text lines array
1234  for (int idx = 0;idx<n_lines;idx++ ) {
1236  strncpy(Ship_select_ship_info_lines[idx], p_str[idx], n_chars[idx]);
1237  Ship_select_ship_info_lines[idx][n_chars[idx]] = 0;
1238  drop_leading_white_space(Ship_select_ship_info_lines[idx]);
1239  }
1240 
1241  // get the line count
1242  Ship_select_ship_info_line_count = n_lines;
1243  } else {
1244  // set the line count to
1245  Ship_select_ship_info_line_count = 0;
1246  }
1247 
1248  Assert(Ship_select_ship_info_line_count < MAX_NUM_SHIP_DESC_LINES);
1249  gr_set_color_fast(text);
1250  for(int idx=0;idx<Ship_select_ship_info_line_count;idx++){
1251  gr_string(Ship_info_coords[gr_screen.res][SHIP_SELECT_X_COORD]+4, y_start, Ship_select_ship_info_lines[idx], GR_RESIZE_MENU);
1252  y_start += line_height;
1253  }
1254 
1255 }
1256 
1257 
1258 // ---------------------------------------------------------------------
1259 // ship_select_do() is called once per game frame, and is responsible for
1260 // updating the ship select screen
1261 //
1262 // frametime is in seconds
1263 
1265 
1266 void ship_select_do(float frametime)
1267 {
1268  int k, ship_select_choice, snazzy_action;
1269 
1270  ship_select_choice = snazzy_menu_do(ShipSelectMaskData, Shipselect_mask_w, Shipselect_mask_h, Num_mask_regions, Region, &snazzy_action, 0);
1271 
1272  Hot_ss_icon = -1;
1273  Hot_ss_slot = -1;
1274 
1275  k = common_select_do(frametime);
1276 
1277  // Check common keypresses
1278  common_check_keys(k);
1279 
1280  if ( Mouse_down_last_frame ) {
1281  Ss_mouse_down_on_region = ship_select_choice;
1282  }
1283 
1284  // Check for the mouse over a region (not clicked, just over)
1285  if ( ship_select_choice > -1 ) {
1286 
1287  switch(ship_select_choice) {
1288  case SHIP_SELECT_ICON_0:
1290  break;
1291  case SHIP_SELECT_ICON_1:
1293  break;
1294  case SHIP_SELECT_ICON_2:
1296  break;
1297  case SHIP_SELECT_ICON_3:
1299  break;
1300  case WING_0_SHIP_0:
1301  if ( do_mouse_over_wing_slot(0,0) )
1302  ship_select_choice = -1;
1303  break;
1304  case WING_0_SHIP_1:
1305  if ( do_mouse_over_wing_slot(0,1) )
1306  ship_select_choice = -1;
1307  break;
1308  case WING_0_SHIP_2:
1309  if ( do_mouse_over_wing_slot(0,2) )
1310  ship_select_choice = -1;
1311  break;
1312  case WING_0_SHIP_3:
1313  if ( do_mouse_over_wing_slot(0,3) )
1314  ship_select_choice = -1;
1315  break;
1316  case WING_1_SHIP_0:
1317  if ( do_mouse_over_wing_slot(1,0) )
1318  ship_select_choice = -1;
1319  break;
1320  case WING_1_SHIP_1:
1321  if ( do_mouse_over_wing_slot(1,1) )
1322  ship_select_choice = -1;
1323  break;
1324  case WING_1_SHIP_2:
1325  if ( do_mouse_over_wing_slot(1,2) )
1326  ship_select_choice = -1;
1327  break;
1328  case WING_1_SHIP_3:
1329  if ( do_mouse_over_wing_slot(1,3) )
1330  ship_select_choice = -1;
1331  break;
1332  case WING_2_SHIP_0:
1333  if ( do_mouse_over_wing_slot(2,0) )
1334  ship_select_choice = -1;
1335  break;
1336  case WING_2_SHIP_1:
1337  if ( do_mouse_over_wing_slot(2,1) )
1338  ship_select_choice = -1;
1339  break;
1340  case WING_2_SHIP_2:
1341  if ( do_mouse_over_wing_slot(2,2) )
1342  ship_select_choice = -1;
1343  break;
1344  case WING_2_SHIP_3:
1345  if ( do_mouse_over_wing_slot(2,3) )
1346  ship_select_choice = -1;
1347  break;
1348 
1349  default:
1350  break;
1351  } // end switch
1352  }
1353 
1354  // check buttons
1357 
1358  // Check for the mouse clicks over a region
1359  if ( ship_select_choice > -1 && snazzy_action == SNAZZY_CLICKED ) {
1360  switch (ship_select_choice) {
1361 
1362  case SHIP_SELECT_ICON_0:
1364  break;
1365 
1366  case SHIP_SELECT_ICON_1:
1368  break;
1369 
1370  case SHIP_SELECT_ICON_2:
1372  break;
1373 
1374  case SHIP_SELECT_ICON_3:
1376  break;
1377 
1378  case WING_0_SHIP_0:
1380  break;
1381 
1382  case WING_0_SHIP_1:
1384  break;
1385 
1386  case WING_0_SHIP_2:
1388  break;
1389 
1390  case WING_0_SHIP_3:
1392  break;
1393 
1394  case WING_1_SHIP_0:
1396  break;
1397 
1398  case WING_1_SHIP_1:
1400  break;
1401 
1402  case WING_1_SHIP_2:
1404  break;
1405 
1406  case WING_1_SHIP_3:
1408  break;
1409 
1410  case WING_2_SHIP_0:
1412  break;
1413 
1414  case WING_2_SHIP_1:
1416  break;
1417 
1418  case WING_2_SHIP_2:
1420  break;
1421 
1422  case WING_2_SHIP_3:
1424  break;
1425 
1426  default:
1427  break;
1428 
1429  } // end switch
1430  }
1431 
1433 
1434  Assert( Ss_icons != NULL );
1435 
1436  if ( !Background_playing ) {
1439  gr_bitmap(0, 0, GR_RESIZE_MENU);
1440  Ship_select_ui_window.draw();
1443  }
1444  if(!Cmdline_ship_choice_3d && ((Selected_ss_class >= 0) && (Ss_icons[Selected_ss_class].ss_anim.num_frames > 0)))
1445  {
1446  generic_anim_render(&Ss_icons[Selected_ss_class].ss_anim, (help_overlay_active(Ship_select_overlay_id)) ? 0 : frametime, Ship_anim_coords[gr_screen.res][0], Ship_anim_coords[gr_screen.res][1], true);
1447  } else {
1448  // The new rendering code for 3D ships courtesy your friendly UnknownPlayer :)
1449 
1450  // check we have a valid ship class selected
1451  if ( (Selected_ss_class >= 0) && (ShipSelectModelNum >= 0) )
1452  {
1454  float rev_rate = REVOLUTION_RATE;
1455  if (sip->flags & SIF_BIG_SHIP) {
1456  rev_rate *= 1.7f;
1457  }
1458  if (sip->flags & SIF_HUGE_SHIP) {
1459  rev_rate *= 3.0f;
1460  }
1461 
1462  model_render_params render_info;
1463 
1464  if (sip->uses_team_colors) {
1465  render_info.set_team_color(sip->default_team_name, "none", 0, 0);
1466  }
1467 
1469  &render_info,
1471  Ship_anim_coords[gr_screen.res][0],
1472  Ship_anim_coords[gr_screen.res][1],
1476  &sip->closeup_pos,
1477  sip->closeup_zoom * 1.3f,
1478  rev_rate,
1481  sip->selection_effect);
1482  }
1483  }
1484 
1485  // The background transition plays once. Display ship icons after Background done playing
1486  if ( !Background_playing ) {
1487  draw_ship_icons();
1488  for ( int i = 0; i < MAX_WING_BLOCKS; i++ ) {
1490  }
1491  }
1492 
1493  if ( ss_icon_being_carried() ) {
1494  int mouse_x, mouse_y, sx, sy;
1495  mouse_get_pos_unscaled( &mouse_x, &mouse_y );
1496  sx = mouse_x + Ss_delta_x;
1497  sy = mouse_y + Ss_delta_y;
1498  if(Ss_icons[Carried_ss_icon.ship_class].icon_bmaps[ICON_FRAME_SELECTED] != -1)
1499  {
1500  gr_set_bitmap(Ss_icons[Carried_ss_icon.ship_class].icon_bmaps[ICON_FRAME_SELECTED]);
1501  gr_bitmap(sx, sy, GR_RESIZE_MENU);
1502  }
1503  else
1504  {
1505  ship_info *sip = &Ship_info[Carried_ss_icon.ship_class];
1506  if(Ss_icons[Carried_ss_icon.ship_class].model_index == -1) {
1507  Ss_icons[Carried_ss_icon.ship_class].model_index = model_load(sip->pof_file, sip->n_subsystems, &sip->subsystems[0]);
1508  mprintf(("SL WARNING: Had to attempt to page in model for %s paged in manually! Result: %d\n", sip->name, Ss_icons[Carried_ss_icon.ship_class].model_index));
1509  }
1511 
1512  int w = 32;
1513  int h = 28;
1514 
1515  draw_brackets_square(sx, sy, sx + w, sy + h, GR_RESIZE_MENU);
1516 
1517  if(Ss_icons[Carried_ss_icon.ship_class].model_index != -1)
1518  {
1519  draw_model_icon(Ss_icons[Carried_ss_icon.ship_class].model_index, MR_AUTOCENTER | MR_NO_FOGGING | MR_NO_LIGHTING, sip->closeup_zoom / 1.25f, sx, sy, w, h, sip, GR_RESIZE_MENU);
1520  }
1521  }
1522  }
1523 
1524  // draw out ship information
1526 
1527 
1529 
1530  // blit help overlay if active
1532 
1533  gr_reset_clip();
1534  gr_flip();
1535 
1537  // Done Rendering and Drawing 3D //
1539 
1540  if ( Game_mode & GM_MULTIPLAYER ) {
1541  if ( Selected_ss_class >= 0 )
1543  }
1544 
1545  // If the commit button was pressed, do the commit button actions. Done at the end of the
1546  // loop so there isn't a skip in the animation (since ship_create() can take a long time if
1547  // the ship model is not in memory
1548  if ( Commit_pressed ) {
1549  commit_pressed();
1550  Commit_pressed = 0;
1551  }
1552 }
1553 
1554 
1555 // ------------------------------------------------------------------------
1556 // ship_select_close() is called once when the ship select screen is exited
1557 //
1558 //
1560 {
1561  key_flush();
1562 
1564 
1565  if ( !Ship_select_open ) {
1566  nprintf(("Alan","ship_select_close() returning without doing anything\n"));
1567  return;
1568  }
1569 
1570  nprintf(("Alan", "Entering ship_select_close()\n"));
1571 
1572  // done with the bitmaps, so unlock it
1573  bm_unlock(ShipSelectMaskBitmap);
1574 
1575  // unload the bitmaps
1576  bm_release(ShipSelectMaskBitmap);
1577 
1578  Ship_select_ui_window.destroy();
1579 
1580  Ship_anim_class = -1;
1581  Ship_select_open = 0; // This game-wide global flag is set to 0 to indicate that the ship
1582  // select screen has been closed and memory freed. This flag
1583  // is needed so we can know if ship_select_close() needs to called if
1584  // restoring a game from the Options screen invoked from ship select
1585 
1586 // delete[] SS_active_items;
1587 }
1588 
1589 // ss_unload_icons() frees the bitmaps used for ship icons
1591 {
1592  int i,j;
1593  ss_icon_info *icon;
1594 
1595  Assert( Ss_icons != NULL );
1596 
1597  for ( i = 0; i < MAX_SHIP_CLASSES; i++ ) {
1598  icon = &Ss_icons[i];
1599 
1600  for ( j = 0; j < NUM_ICON_FRAMES; j++ ) {
1601  if ( icon->icon_bmaps[j] >= 0 ) {
1602  bm_release(icon->icon_bmaps[j]);
1603  icon->icon_bmaps[j] = -1;
1604  }
1605  }
1606  }
1607 }
1608 
1609 // ------------------------------------------------------------------------
1610 // draw_ship_icons() will request which icons to draw on screen.
1612 {
1613  int i;
1614  int count=0;
1615 
1616  ss_active_item *sai;
1617  i = 0;
1618  for ( sai = GET_FIRST(&SS_active_head); sai != END_OF_LIST(&SS_active_head); sai = GET_NEXT(sai) ) {
1619  count++;
1620  if ( count <= SS_active_list_start )
1621  continue;
1622 
1623  if ( i >= MAX_ICONS_ON_SCREEN )
1624  break;
1625 
1627  i++;
1628  }
1629 }
1630 
1631 // ------------------------------------------------------------------------
1632 // draw_ship_icon_with_number() will draw a ship icon on screen with the
1633 // number of available ships to the left.
1634 //
1635 //
1636 void draw_ship_icon_with_number(int screen_offset, int ship_class)
1637 {
1638  char buf[32];
1639  int num_x,num_y;
1640  ss_icon_info *ss_icon;
1641  color *color_to_draw = NULL;
1642  //shader *shader_to_use;
1643 
1644 
1645  Assert( screen_offset >= 0 && screen_offset <= 3 );
1646  Assert( ship_class >= 0 );
1647  Assert( (Ss_pool != NULL) && (Ss_icons != NULL) );
1648  ss_icon = &Ss_icons[ship_class];
1649 
1650  num_x = Ship_list_coords[gr_screen.res][screen_offset][2];
1651  num_y = Ship_list_coords[gr_screen.res][screen_offset][3];
1652 
1653  // assume default bitmap is to be used
1654  if(ss_icon->current_icon_bitmap != -1)
1655  ss_icon->current_icon_bitmap = ss_icon->icon_bmaps[ICON_FRAME_NORMAL];
1656  else
1657  color_to_draw = &Icon_colors[ICON_FRAME_NORMAL];
1658 
1659  // next check if ship has mouse over it
1660  if ( Hot_ss_icon > -1 ) {
1661  Assert(Hot_ss_icon <= 3);
1662  if ( Hot_ss_icon == screen_offset )
1663  {
1664  if(ss_icon->model_index == -1)
1665  ss_icon->current_icon_bitmap = ss_icon->icon_bmaps[ICON_FRAME_HOT];
1666  else
1667  color_to_draw = &Icon_colors[ICON_FRAME_HOT];
1668  }
1669  }
1670 
1671  // highest precedence is if the ship is selected
1672  if ( Selected_ss_class > -1 ) {
1673  if ( Selected_ss_class == ship_class )
1674  {
1675  if(ss_icon->model_index == -1)
1676  ss_icon->current_icon_bitmap = ss_icon->icon_bmaps[ICON_FRAME_SELECTED];
1677  else
1678  color_to_draw = &Icon_colors[ICON_FRAME_SELECTED];
1679  }
1680  }
1681 
1682  if ( Ss_pool[ship_class] <= 0 ) {
1683  return;
1684  }
1685 
1686  // blit the icon
1687  if(ss_icon->current_icon_bitmap != -1)
1688  {
1690  gr_bitmap(Ship_list_coords[gr_screen.res][screen_offset][0], Ship_list_coords[gr_screen.res][screen_offset][1], GR_RESIZE_MENU);
1691  }
1692  else
1693  {
1694  ship_info *sip = &Ship_info[ship_class];
1695  if(ss_icon->model_index == -1) {
1696  ss_icon->model_index = model_load(sip->pof_file, sip->n_subsystems, &sip->subsystems[0]);
1697  mprintf(("SL WARNING: Had to attempt to page in model for %s paged in manually! Result: %d\n", sip->name, ss_icon->model_index));
1698  }
1699  gr_set_color_fast(color_to_draw);
1700  draw_brackets_square(Ship_list_coords[gr_screen.res][screen_offset][0], Ship_list_coords[gr_screen.res][screen_offset][1], Ship_list_coords[gr_screen.res][screen_offset][0] + 32, Ship_list_coords[gr_screen.res][screen_offset][1] + 28, GR_RESIZE_MENU);
1701  if(ss_icon->model_index != -1)
1702  {
1703  draw_model_icon(ss_icon->model_index, MR_AUTOCENTER | MR_NO_FOGGING | MR_NO_LIGHTING, sip->closeup_zoom / 1.25f, Ship_list_coords[gr_screen.res][screen_offset][0],Ship_list_coords[gr_screen.res][screen_offset][1], 32, 28, sip, GR_RESIZE_MENU);
1704  }
1705  }
1706 
1707  // blit the number
1708  sprintf(buf, "%d", Ss_pool[ship_class] );
1710  gr_string(num_x, num_y, buf, GR_RESIZE_MENU);
1711 }
1712 
1713 // ------------------------------------------------------------------------
1714 // this loads an individual animation file
1715 // it attempts to load a hires version (ie, it attaches a "2_" in front of the
1716 // filename. if no hires version is available, it defaults to the lowres
1717 
1718 // ------------------------------------------------------------------------
1719 // start_ship_animation() will start a ship animation playing, and will
1720 // load the compressed anim from disk if required.
1721 //
1722 // UPDATE: this code now initializes a 3d model of a ship to spin like it does
1723 // in the tech room - UnknownPlayer
1724 void start_ship_animation(int ship_class, int play_sound)
1725 {
1726  char *p;
1727  char animation_filename[CF_MAX_FILENAME_LENGTH+4];
1728 
1729  if (ship_class < 0) {
1730  mprintf(("No ship class passed in to start_ship_animation\n"));
1731  ShipSelectModelNum = -1;
1732  return;
1733  }
1734 
1735  ship_info *sip = &Ship_info[ship_class];
1736 
1738 
1739  if ( Cmdline_ship_choice_3d || !strlen(sip->anim_filename) ) {
1740 
1741  //Unload Anim if one was playing
1742  if(Ship_anim_class > 0 && Ss_icons[Ship_anim_class].ss_anim.num_frames > 0) {
1743  generic_anim_unload(&Ss_icons[Ship_anim_class].ss_anim);
1744  Ship_anim_class = -1;
1745  }
1746 
1747  // Load the necessary model file
1749 
1750  // page in ship textures properly (takes care of nondimming pixels)
1752 
1753  if (sip->model_num < 0) {
1754  mprintf(("Couldn't load model file %s in missionshipchoice.cpp\n", sip->pof_file));
1755  }
1756  } else {
1757  Assert( ship_class >= 0 );
1758  Assert( Ss_icons != NULL );
1759 
1760  if (Ship_anim_class == ship_class) {
1761  return;
1762  }
1763 
1764  //If there was a model loaded for the previous ship, unload it
1765  if (ShipSelectModelNum >= 0 ) {
1767  ShipSelectModelNum = -1;
1768  }
1769 
1770  //unload the previous anim
1771  if(Ship_anim_class > 0 && Ss_icons[Ship_anim_class].ss_anim.num_frames > 0)
1772  generic_anim_unload(&Ss_icons[Ship_anim_class].ss_anim);
1773  //load animation here, we now only have one loaded
1774  p = strchr(Ship_info[ship_class].anim_filename, '.' );
1775  if(p)
1776  *p = '\0';
1777  if (gr_screen.res == GR_1024) {
1778  strcpy_s(animation_filename, "2_");
1779  strcat_s(animation_filename, Ship_info[ship_class].anim_filename);
1780  }
1781  else {
1782  strcpy_s(animation_filename, Ship_info[ship_class].anim_filename);
1783  }
1784 
1785  generic_anim_init(&Ss_icons[ship_class].ss_anim, animation_filename);
1786  Ss_icons[ship_class].ss_anim.ani.bg_type = bm_get_type(Ship_select_background_bitmap);
1787  if(generic_anim_stream(&Ss_icons[ship_class].ss_anim) == -1) {
1788  //we've failed to load an animation, load an image and treat it like a 1 frame animation
1789  Ss_icons[ship_class].ss_anim.first_frame = bm_load(Ship_info[ship_class].anim_filename); //if we fail here, the value is still -1
1790  if(Ss_icons[ship_class].ss_anim.first_frame != -1) {
1791  Ss_icons[ship_class].ss_anim.num_frames = 1;
1792  }
1793  }
1794 
1795  Ship_anim_class = ship_class;
1796  }
1797 
1798 // if ( play_sound ) {
1800 // }
1801 }
1802 
1804 {
1805  Assert( Ss_icons != NULL );
1806 
1807  for ( int i = 0; i < MAX_SHIP_CLASSES; i++ ) {
1808  if ( Ss_icons[i].ss_anim.num_frames ) {
1809  generic_anim_unload(&Ss_icons[i].ss_anim);
1810  }
1811  }
1812 }
1813 
1814 bool is_weapon_carried(int weapon_index)
1815 {
1816  for (int slot = 0; slot < MAX_WING_BLOCKS*MAX_WING_SLOTS; slot++)
1817  {
1818  // a ship must exist in this slot
1819  if (Wss_slots[slot].ship_class >= 0)
1820  {
1821  for (int bank = 0; bank < MAX_SHIP_WEAPONS; bank++)
1822  {
1823  // there must be a weapon here
1824  if (Wss_slots[slot].wep_count[bank] > 0)
1825  {
1826  if (Wss_slots[slot].wep[bank] == weapon_index)
1827  return true;
1828  }
1829  }
1830  }
1831  }
1832 
1833  return false;
1834 }
1835 
1836 // ------------------------------------------------------------------------
1837 // commit_pressed() is called when the commit button from any of the briefing/ship select/ weapon
1838 // select screens is pressed. The ship selected is created, and the interface music is stopped.
1840 {
1841  int j, player_ship_info_index;
1842 
1843  if ( Wss_num_wings > 0 ) {
1844  if(!(Game_mode & GM_MULTIPLAYER)){
1845  int rc;
1846  rc = create_wings();
1847  if (rc != 0) {
1849  return;
1850  }
1851  }
1852  }
1853  else if(Player_obj != NULL)
1854  {
1855  if ( Selected_ss_class == -1 ) {
1856  player_ship_info_index = Team_data[Common_team].default_ship;
1857 
1858  } else {
1859  Assert(Selected_ss_class >= 0 );
1860  player_ship_info_index = Selected_ss_class;
1861  }
1862 
1863  update_player_ship( player_ship_info_index );
1865  popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, XSTR( "Player ship has no weapons", 461));
1866  return;
1867  }
1868  }
1869 
1870  // Goober5000 - mjn.mixael's required weapon feature
1871  int num_required_weapons = 0;
1872  int num_satisfied_weapons = 0;
1873  SCP_string weapon_list;
1874  for (j=0; j<MAX_WEAPON_TYPES; j++)
1875  {
1876  if (Team_data[Common_team].weapon_required[j])
1877  {
1878  // add it to the message list
1879  num_required_weapons++;
1880  if (num_required_weapons > 1)
1881  weapon_list.append(1, EOLN);
1882  weapon_list.append(Weapon_info[j].name);
1883 
1884  // see if it's carried by any ship
1885  if (is_weapon_carried(j))
1886  num_satisfied_weapons++;
1887  }
1888  }
1889  if (num_satisfied_weapons < num_required_weapons)
1890  {
1891  if (num_required_weapons == 1)
1892  {
1893  popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, XSTR("The %s is required for this mission, but it has not been added to any ship loadout.", 1624), weapon_list.c_str());
1894  return;
1895  }
1896  else if (num_required_weapons > 1)
1897  {
1898  popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, XSTR("The following weapons are required for this mission, but at least one of them has not been added to any ship loadout:\n\n%s", 1625), weapon_list.c_str());
1899  return;
1900  }
1901  }
1902 
1903  // Check to ensure that the hotkeys are still pointing to valid objects. It is possible
1904  // for the player to assign a ship to a hotkey, then go and delete that ship in the
1905  // ship selection, and then try to start the mission. This function will detect those objects,
1906  // and remove them from the hotkey linked lists.
1908 
1909  // Goober5000 - no sound when skipping briefing
1912 
1913  // save the player loadout
1914  if ( !(Game_mode & GM_MULTIPLAYER) ) {
1917  wss_save_loadout();
1918  }
1919 
1920  // warp the mouse cursor the the middle of the screen for those who control with a mouse
1922 
1923  // move to the next stage
1924  // in multiplayer this is the final mission sync
1925  if(Game_mode & GM_MULTIPLAYER){
1926  if (MULTIPLAYER_MASTER) {
1927  // process the initial orders now (moved from post_process_mission()in missionparse)
1930  }
1931 
1934 
1935  // otherwise tell the standalone to move everyone into this state and continue
1938  }
1939  }
1940  // in single player we jump directly into the mission
1941  else {
1942  Pilot.save_savefile();
1944  }
1945 }
1946 
1947 // ------------------------------------------------------------------------
1948 // pick_from_ship_list() will determine if an icon from the ship selection
1949 // list can be picked up (for drag and drop). It calculates the difference
1950 // in x & y between the icon and the mouse, so we can move the icon with the
1951 // mouse in a realistic way
1952 int pick_from_ship_list(int screen_offset, int ship_class)
1953 {
1954  int rval = -1;
1955  Assert(ship_class >= 0);
1956  Assert( Ss_pool != NULL );
1957 
1958  if ( Wss_num_wings == 0 )
1959  return rval;
1960 
1961  // If carrying an icon, then do nothing
1962  if ( ss_icon_being_carried() )
1963  return rval;
1964 
1965  if ( Ss_pool[ship_class] > 0 ) {
1966  int mouse_x, mouse_y;
1967 
1968  ss_set_carried_icon(-1, ship_class);
1969  mouse_get_pos_unscaled( &mouse_x, &mouse_y );
1970  Ss_delta_x = Ship_list_coords[gr_screen.res][screen_offset][0] - mouse_x;
1971  Ss_delta_y = Ship_list_coords[gr_screen.res][screen_offset][1] - mouse_y;
1972  Assert( Ss_pool[ship_class] >= 0 );
1973  rval = 0;
1974  }
1975 
1977  return rval;
1978 }
1979 
1980 // ------------------------------------------------------------------------
1981 // pick_from_wing() will determine if an icon from the wing formation (wb_num)
1982 // and slot number (ws_num) can be picked up (for drag and drop). It calculates
1983 // the difference in x & y between the icon and the mouse, so we can move the icon with the
1984 // mouse in a realistic way
1985 void pick_from_wing(int wb_num, int ws_num)
1986 {
1987  int slot_index;
1988  Assert(wb_num >= 0 && wb_num < MAX_WING_BLOCKS);
1989  Assert(ws_num >= 0 && ws_num < MAX_WING_SLOTS);
1990  Assert( (Ss_wings != NULL) && (Wss_slots != NULL) );
1991 
1992  ss_wing_info *wb;
1993  ss_slot_info *ws;
1994  wb = &Ss_wings[wb_num];
1995  ws = &wb->ss_slots[ws_num];
1996  slot_index = wb_num*MAX_WING_SLOTS+ws_num;
1997 
1998  if ( wb->wingnum < 0 )
1999  return;
2000 
2001  // Take care of case where the mouse button goes from up to down in one frame while
2002  // carrying an icon
2004  if ( !ss_disabled_slot(slot_index) ) {
2005  ss_drop(Carried_ss_icon.from_slot, Carried_ss_icon.ship_class, slot_index, -1);
2008  }
2009  }
2010 
2011  if ( ss_icon_being_carried() )
2012  return;
2013 
2014  if ( ss_disabled_slot(slot_index) ) {
2015  return;
2016  }
2017 
2018  if ( ws->status & WING_SLOT_IGNORE_SHIPS) {
2019  return;
2020  }
2021 
2022  switch ( ws->status ) {
2023  case WING_SLOT_EMPTY:
2025  // TODO: add fail sound
2026  return;
2027  break;
2028 
2030  case WING_SLOT_FILLED:
2031  {
2032  int mouse_x, mouse_y;
2033  Assert(Wss_slots[slot_index].ship_class >= 0);
2034  ss_set_carried_icon(slot_index, Wss_slots[slot_index].ship_class);
2035 
2036  mouse_get_pos_unscaled( &mouse_x, &mouse_y );
2037  Ss_delta_x = Wing_icon_coords[gr_screen.res][slot_index][0] - mouse_x;
2038  Ss_delta_y = Wing_icon_coords[gr_screen.res][slot_index][1] - mouse_y;
2039  Carried_ss_icon.from_x = mouse_x;
2040  Carried_ss_icon.from_y = mouse_y;
2041  }
2042  break;
2043 
2044  default:
2045  Int3();
2046  break;
2047 
2048  } // end switch
2049 
2051 }
2052 
2053 // ------------------------------------------------------------------------
2054 // draw_wing_block() will draw the wing icons for the wing formation number
2055 // passed in as a parameter.
2056 //
2057 // input: wb_num => wing block number (numbering starts at 0)
2058 // hot_slot => index of slot that mouse is over
2059 // selected_slot => index of slot that is selected
2060 // class_select => all ships of this class are drawn selected (send -1 to not use)
2061 void draw_wing_block(int wb_num, int hot_slot, int selected_slot, int class_select, bool ship_selection )
2062 {
2063  ss_wing_info *wb;
2064  ss_slot_info *ws;
2065  ss_icon_info *icon;
2066  wing *wp;
2067  int i, w, h, sx, sy, slot_index, mask;
2068  int bitmap_to_draw = -1;
2069  color *color_to_draw = NULL;
2070  //shader *shader_to_use = NULL;
2071 
2072  Assert(wb_num >= 0 && wb_num < MAX_WING_BLOCKS);
2073  Assert( (Ss_wings != NULL) && (Wss_slots != NULL) && (Ss_icons != NULL) );
2074 
2075  wb = &Ss_wings[wb_num];
2076 
2077  if ( wb->wingnum == -1 )
2078  return;
2079 
2080  // print the wing name under the wing
2081  wp = &Wings[wb->wingnum];
2082  gr_get_string_size(&w, &h, wp->name);
2083  sx = Wing_icon_coords[gr_screen.res][wb_num*MAX_WING_SLOTS][0] + 16 - w/2;
2084  sy = Wing_icon_coords[gr_screen.res][wb_num*MAX_WING_SLOTS + 3][1] + 32 + h;
2086  gr_string(sx, sy, wp->name, GR_RESIZE_MENU);
2087 
2088  for ( i = 0; i < MAX_WING_SLOTS; i++ ) {
2089  bitmap_to_draw = -1;
2090  ws = &wb->ss_slots[i];
2091  slot_index = wb_num*MAX_WING_SLOTS + i;
2092 
2093  if ( Wss_slots[slot_index].ship_class >= 0 ) {
2094  icon = &Ss_icons[Wss_slots[slot_index].ship_class];
2095  } else {
2096  icon = NULL;
2097  }
2098 
2099  mask = ~WING_SLOT_LOCKED;
2100  mask &= ~WING_SLOT_IS_PLAYER;
2101  if (ship_selection) {
2102  mask &= ~WING_SLOT_WEAPONS_DISABLED;
2103  }
2104  else {
2105  mask &= ~WING_SLOT_SHIPS_DISABLED;
2106  }
2107 
2108  switch(ws->status & mask ) {
2109  case WING_SLOT_FILLED:
2111 
2112  Assert(icon);
2113 
2114  if ( class_select >= 0 ) { // only ship select
2115  if ( Carried_ss_icon.from_slot == slot_index ) {
2116  if ( ss_carried_icon_moved() ) {
2117  bitmap_to_draw = Wing_slot_empty_bitmap;
2118  } else {
2119  bitmap_to_draw = -1;
2120  }
2121  break;
2122  }
2123  }
2124 
2125  if ( ws->status & WING_SLOT_LOCKED ) {
2126  if(icon->model_index == -1)
2127  bitmap_to_draw = icon->icon_bmaps[ICON_FRAME_DISABLED];
2128  else
2129  color_to_draw = &Icon_colors[ICON_FRAME_DISABLED];
2130 
2131  // in multiplayer, determine if this it the special case where the slot is disabled, and
2132  // it is also _my_ slot (ie, team capatains/host have not locked players yet)
2133  if((Game_mode & GM_MULTIPLAYER) && multi_ts_disabled_high_slot(slot_index)){
2134  if(icon->model_index == -1)
2135  bitmap_to_draw = icon->icon_bmaps[ICON_FRAME_DISABLED_HIGH];
2136  else
2137  color_to_draw = &Icon_colors[ICON_FRAME_DISABLED_HIGH];
2138  }
2139  break;
2140  }
2141 
2142  if(icon->model_index == -1)
2143  bitmap_to_draw = icon->icon_bmaps[ICON_FRAME_NORMAL];
2144  else
2145  color_to_draw = &Icon_colors[ICON_FRAME_NORMAL];
2146  if ( selected_slot == slot_index || class_select == Wss_slots[slot_index].ship_class)
2147  {
2148  if(icon->model_index == -1)
2149  bitmap_to_draw = icon->icon_bmaps[ICON_FRAME_SELECTED];
2150  else
2151  color_to_draw = &Icon_colors[ICON_FRAME_SELECTED];
2152  }
2153  else if ( hot_slot == slot_index )
2154  {
2156  {
2157  if(icon->model_index == -1)
2158  bitmap_to_draw = icon->icon_bmaps[ICON_FRAME_SELECTED];
2159  else
2160  color_to_draw = &Icon_colors[ICON_FRAME_SELECTED];
2161  }
2162  else
2163  {
2164  if(icon->model_index == -1)
2165  bitmap_to_draw = icon->icon_bmaps[ICON_FRAME_HOT];
2166  else
2167  color_to_draw = &Icon_colors[ICON_FRAME_HOT];
2168  }
2169  }
2170 
2171  if ( ws->status & WING_SLOT_IS_PLAYER && (selected_slot != slot_index) )
2172  {
2173  if(icon->model_index == -1)
2174  bitmap_to_draw = icon->icon_bmaps[ICON_FRAME_PLAYER];
2175  else
2176  color_to_draw = &Icon_colors[ICON_FRAME_PLAYER];
2177  }
2178  break;
2179 
2180  case WING_SLOT_EMPTY:
2182  bitmap_to_draw = Wing_slot_empty_bitmap;
2183  break;
2184 
2185  default:
2186  if ( icon ) {
2187  if(icon->model_index == -1)
2188  bitmap_to_draw = icon->icon_bmaps[ICON_FRAME_DISABLED];
2189  else
2190  color_to_draw = &Icon_colors[ICON_FRAME_DISABLED];
2191  } else {
2192  bitmap_to_draw = Wing_slot_disabled_bitmap;
2193  }
2194  break;
2195  } // end switch
2196 
2197 
2198  if ( bitmap_to_draw != -1 ) {
2199  gr_set_bitmap(bitmap_to_draw);
2201  }
2202  else if(color_to_draw != NULL)
2203  {
2204  ship_info *sip = &Ship_info[Wss_slots[slot_index].ship_class];
2205  gr_set_color_fast(color_to_draw);
2206  draw_brackets_square(Wing_icon_coords[gr_screen.res][slot_index][0], Wing_icon_coords[gr_screen.res][slot_index][1], Wing_icon_coords[gr_screen.res][slot_index][0] + 32, Wing_icon_coords[gr_screen.res][slot_index][1] + 28, GR_RESIZE_MENU);
2208  }
2209  }
2210 }
2211 
2212 // called by multiplayer team select to set the slot based flags
2213 void ss_make_slot_empty(int slot_index)
2214 {
2215  int wing_num,slot_num;
2216  ss_wing_info *wb;
2217  ss_slot_info *ws;
2218 
2219  Assert( Ss_wings != NULL );
2220 
2221  // calculate the wing #
2222  wing_num = slot_index / MAX_WING_SLOTS;
2223  slot_num = slot_index % MAX_WING_SLOTS;
2224 
2225  // get the wing and slot entries
2226  wb = &Ss_wings[wing_num];
2227  ws = &wb->ss_slots[slot_num];
2228 
2229  // set the flags
2231  ws->status |= WING_SLOT_EMPTY;
2232 }
2233 
2234 // called by multiplayer team select to set the slot based flags
2235 void ss_make_slot_full(int slot_index)
2236 {
2237  int wing_num,slot_num;
2238  ss_wing_info *wb;
2239  ss_slot_info *ws;
2240 
2241  Assert( Ss_wings != NULL );
2242 
2243  // calculate the wing #
2244  wing_num = slot_index / MAX_WING_SLOTS;
2245  slot_num = slot_index % MAX_WING_SLOTS;
2246 
2247  // get the wing and slot entries
2248  wb = &Ss_wings[wing_num];
2249  ws = &wb->ss_slots[slot_num];
2250 
2251  // set the flags
2253  ws->status |= WING_SLOT_FILLED;
2254 }
2255 
2256 void ss_blit_ship_icon(int x,int y,int ship_class,int bmap_num)
2257 {
2258  // blit the bitmap in the correct location
2259  if(ship_class == -1)
2260  {
2263  }
2264  else
2265  {
2266  Assert( Ss_icons != NULL );
2267 
2268  ss_icon_info *icon = &Ss_icons[ship_class];
2269  if(icon->icon_bmaps[bmap_num] != -1)
2270  {
2271  Assert(icon->icon_bmaps[bmap_num] != -1);
2272  gr_set_bitmap(icon->icon_bmaps[bmap_num]);
2273  gr_bitmap(x,y,GR_RESIZE_MENU);
2274  }
2275  else
2276  {
2277  ship_info *sip = &Ship_info[ship_class];
2278  if(icon->model_index == -1) {
2279  icon->model_index = model_load(sip->pof_file, sip->n_subsystems, &sip->subsystems[0]);
2280  mprintf(("SL WARNING: Had to attempt to page in model for %s paged in manually! Result: %d\n", sip->name, icon->model_index));
2281  }
2282  if(icon->model_index != -1)
2283  {
2284  gr_set_color_fast(&Icon_colors[bmap_num]);
2285  draw_brackets_square(x, y, x + 32, y + 28, GR_RESIZE_MENU);
2287  }
2288  }
2289  }
2290 
2291 }
2292 
2293 // ------------------------------------------------------------------------
2294 // unload_ship_icons() frees the memory that was used to hold the bitmaps
2295 // for ship icons
2296 //
2298 {
2299  if ( Wing_slot_empty_bitmap != -1 ) {
2302  }
2303 
2304  if ( Wing_slot_disabled_bitmap != -1 ) {
2307  }
2308 }
2309 
2310 // ------------------------------------------------------------------------
2311 // create_wings() will ensure the correct ships are in the player wings
2312 // for the game. It works by calling change_ship_type() on the wing ships
2313 // so they match what the player selected. ship_create() is called for the
2314 // player ship (and current_count, ship_index[] is updated), since it is not yet
2315 // part of the wing structure.
2316 //
2317 // returns: 0 ==> success
2318 // !0 ==> failure
2320 {
2321  ss_wing_info *wb;
2322  ss_slot_info *ws;
2323  wing *wp;
2324  p_object *p_objp;
2325 
2326  int shipnum, objnum, slot_index;
2327  int cleanup_ship_index[MAX_WING_SLOTS];
2328  int i,j,k;
2329  int found_pobj;
2330 
2331  Assert( (Ss_wings != NULL) && (Wss_slots != NULL) );
2332 
2333  for ( i = 0; i < MAX_WING_BLOCKS; i++ ) {
2334 
2335  wb = &Ss_wings[i];
2336 
2337  if ( wb->wingnum == -1 )
2338  continue;
2339 
2340  wp = &Wings[wb->wingnum];
2341 
2342  for ( j = 0; j < MAX_WING_SLOTS; j++ ) {
2343  slot_index = i*MAX_WING_SLOTS+j;
2344  ws = &wb->ss_slots[j];
2346  if ( wp->ship_index[j] >= 0 ) {
2347  Assert(Ships[wp->ship_index[j]].objnum >= 0);
2348  }
2349 
2350  if ( ws->status & WING_SLOT_IS_PLAYER ) {
2351  update_player_ship(Wss_slots[slot_index].ship_class);
2352 
2353  if ( wl_update_ship_weapons(Ships[Player_obj->instance].objnum, &Wss_slots[i*MAX_WING_SLOTS+j]) == -1 ) {
2354  popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, XSTR( "Player ship has no weapons", 461));
2355  return -1;
2356  }
2357 
2358  objnum = OBJ_INDEX(Player_obj);
2359  shipnum = Objects[objnum].instance;
2360  } else {
2361  if ( wb->is_late) {
2362  found_pobj = 0;
2363  for ( p_objp = GET_FIRST(&Ship_arrival_list); p_objp != END_OF_LIST(&Ship_arrival_list); p_objp = GET_NEXT(p_objp) ) {
2364  if ( p_objp->wingnum == WING_INDEX(wp) ) {
2365  if ( ws->sa_index == POBJ_INDEX(p_objp) ) {
2366  p_objp->ship_class = Wss_slots[slot_index].ship_class;
2367  wl_update_parse_object_weapons(p_objp, &Wss_slots[i*MAX_WING_SLOTS+j]);
2368  found_pobj = 1;
2369  break;
2370  }
2371  }
2372  }
2373  Assert(found_pobj);
2374  }
2375  else {
2376  // AL 10/04/97
2377  // Change the ship type of the ship if different than current.
2378  // NOTE: This will reset the weapons for this ship. I think this is
2379  // the right thing to do, since the ships may have different numbers
2380  // of weapons and may not have the same allowed weapon types
2381  if ( Ships[wp->ship_index[j]].ship_info_index != Wss_slots[slot_index].ship_class )
2382  change_ship_type(wp->ship_index[j], Wss_slots[slot_index].ship_class);
2383  wl_update_ship_weapons(Ships[wp->ship_index[j]].objnum, &Wss_slots[i*MAX_WING_SLOTS+j]);
2384  }
2385  }
2386  }
2387  else if (ws->status & WING_SLOT_EMPTY) {
2388  if ( ws->status & WING_SLOT_IS_PLAYER ) {
2389  popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, XSTR( "Player %s must select a place in player wing", 462), Player->callsign);
2390  return -1;
2391  }
2392  }
2393  } // end for (wing slot)
2394  } // end for (wing block)
2395 
2396  for ( i = 0; i < MAX_WING_BLOCKS; i++ ) {
2397  wb = &Ss_wings[i];
2398 
2399  if ( wb->wingnum == -1 )
2400  continue;
2401 
2402  wp = &Wings[wb->wingnum];
2403 
2404  for ( k = 0; k < MAX_WING_SLOTS; k++ ) {
2405  cleanup_ship_index[k] = -1;
2406  }
2407 
2408  for ( j = 0; j < MAX_WING_SLOTS; j++ ) {
2409  ws = &wb->ss_slots[j];
2410  switch( ws->status ) {
2411  case WING_SLOT_EMPTY:
2412  // delete ship that is not going to be used by the wing
2413  if ( wb->is_late ) {
2415  wp->wave_count--;
2416  Assert(wp->wave_count >= 0);
2417  }
2418  else {
2419  shipnum = wp->ship_index[j];
2420  Assert( shipnum >= 0 && shipnum < MAX_SHIPS );
2421  cleanup_ship_index[j] = shipnum;
2423  obj_delete(Ships[shipnum].objnum);
2424  hud_set_wingman_status_none( Ships[shipnum].wing_status_wing_index, Ships[shipnum].wing_status_wing_pos);
2425  }
2426  break;
2427 
2428  default:
2429  break;
2430 
2431  } // end switch
2432 
2433  } // end for (wing slot)
2434 
2435  for ( k = 0; k < MAX_WING_SLOTS; k++ ) {
2436  if ( cleanup_ship_index[k] != -1 ) {
2437  ship_wing_cleanup( cleanup_ship_index[k], wp );
2438  }
2439  }
2440 
2441  } // end for (wing block)
2442 
2443  return 0;
2444 }
2445 
2446 // ----------------------------------------------------------------------------
2447 // update_player_ship()
2448 //
2449 // Updates the ship class of the player ship
2450 //
2451 // parameters: si_index => ship info index of ship class to change to
2452 //
2453 //
2454 void update_player_ship(int si_index)
2455 {
2456  Assert( si_index >= 0 );
2457  Assert( Player_obj != NULL);
2458 
2459  // AL 10/04/97
2460  // Change the ship type of the player ship if different than current.
2461  // NOTE: This will reset the weapons for this ship. I think this is
2462  // the right thing to do, since the ships may have different numbers
2463  // of weapons and may not have the same allowed weapon types
2464  if ( Player_ship->ship_info_index != si_index )
2465  change_ship_type(Player_obj->instance, si_index);
2466 
2467  Player->last_ship_flown_si_index = si_index;
2468 }
2469 
2470 /*
2471  * create a default player ship
2472  *
2473  * @note: only used for quick start missions
2474  *
2475  * @param use_last_flown select ship that was last flown on a mission (default parameter set to 1)
2476  *
2477  * @return 0 => success, !0 => failure
2478  */
2479 int create_default_player_ship(int use_last_flown)
2480 {
2481  int player_ship_class=-1;
2482 
2483  // find the ship that matches the string stored in default_player_ship
2484 
2485  if ( use_last_flown ) {
2486  player_ship_class = Players[Player_num].last_ship_flown_si_index;
2487  }
2488  else {
2489  for (auto it = Ship_info.cbegin(); it != Ship_info.cend(); ++it) {
2490  if ( !stricmp(it->name, default_player_ship) ) {
2491  player_ship_class = std::distance(Ship_info.cbegin(), it);
2492  Players[Player_num].last_ship_flown_si_index = player_ship_class;
2493  break;
2494  }
2495  }
2496 
2497  if (player_ship_class == -1)
2498  return 1;
2499  }
2500 
2501  // if we still haven't found the last flown ship, handle the error semi-gracefully
2502  if (player_ship_class == -1) {
2504  "a valid last flown ship\n\nHave you played any missions since activating this mod/campaign?", 1619));
2505  return 1;
2506  } else {
2507  update_player_ship(player_ship_class);
2508  }
2509 
2510  // debug code to keep using descent style physics if the player starts a new game
2511 #ifndef NDEBUG
2512  if ( use_descent ) {
2513  use_descent = 0;
2515  }
2516 #endif
2517 
2518  return 0;
2519 }
2520 
2521 // return the original ship class for the specified slot
2523 {
2524  int wnum, snum;
2525 
2526  Assert( Ss_wings != NULL );
2527 
2528  wnum = slot_num/MAX_WING_SLOTS;
2529  snum = slot_num%MAX_WING_SLOTS;
2530 
2531  return Ss_wings[wnum].ss_slots[snum].original_ship_class;
2532 }
2533 
2534 // return the ship arrival index for the slot (-1 means no ship arrival index)
2535 int ss_return_saindex(int slot_num)
2536 {
2537  int wnum, snum;
2538 
2539  Assert( Ss_wings != NULL );
2540 
2541  wnum = slot_num/MAX_WING_SLOTS;
2542  snum = slot_num%MAX_WING_SLOTS;
2543 
2544  return Ss_wings[wnum].ss_slots[snum].sa_index;
2545 }
2546 
2547 // ----------------------------------------------------------------------------
2548 // ss_return_ship()
2549 //
2550 // For a given wing slot, return the ship index if the ship has been created.
2551 // Otherwise, find the index into Parse_objects[] for the ship
2552 //
2553 // input: wing_block => wing block of ship to find
2554 // wing_slot => wing slot of ship to find
2555 // ship_index => OUTPUT parameter: the Ships[] index of the ship in the wing slot
2556 // This value will be -1 if there is no ship created yet
2557 // ppobjp => OUTPUT parameter: returns a pointer to a parse object for
2558 // the ship that hasn't been created yet. Set to NULL if the
2559 // ship has already been created
2560 //
2561 // returns: the original ship class of the ship, or -1 if the ship doesn't exist
2562 //
2563 // NOTE: For the player wing, the player is not yet in the wp->ship_index[].. so
2564 // that is why there is an offset of 1 when getting ship indicies from the player
2565 // wing. The player is special cased by looking at the status of the wing slot
2566 //
2567 int ss_return_ship(int wing_block, int wing_slot, int *ship_index, p_object **ppobjp)
2568 {
2569  *ship_index = -1;
2570  *ppobjp = NULL;
2571 
2572  ss_slot_info *ws;
2573 
2574  Assert( Ss_wings != NULL );
2575 
2576  if (!Wss_num_wings) {
2577  *ppobjp = NULL;
2578  *ship_index = Player_obj->instance;
2579  return Player_ship->ship_info_index;
2580  }
2581 
2582  if ( Ss_wings[wing_block].wingnum < 0 ) {
2583  return -1;
2584  }
2585 
2586  ws = &Ss_wings[wing_block].ss_slots[wing_slot];
2587 
2588  // Check to see if ship is on the ship arrivals list
2589  if ( ws->sa_index != -1 ) {
2590  *ship_index = -1;
2591  *ppobjp = &Parse_objects[ws->sa_index];
2592  } else {
2593  *ship_index = Wings[Ss_wings[wing_block].wingnum].ship_index[wing_slot];
2594  Assert(*ship_index != -1);
2595  }
2596 
2597  return ws->original_ship_class;
2598 }
2599 
2600 // return the name of the ship in the specified wing position... if the ship is the
2601 // player ship, return the player callsign
2602 //
2603 // input: ensure at least NAME_LENGTH bytes allocated for name buffer
2604 void ss_return_name(int wing_block, int wing_slot, char *name)
2605 {
2606  ss_slot_info *ws;
2607  wing *wp;
2608 
2609  Assert( Ss_wings != NULL );
2610 
2611  ws = &Ss_wings[wing_block].ss_slots[wing_slot];
2612  wp = &Wings[Ss_wings[wing_block].wingnum];
2613 
2614  if (!Wss_num_wings) {
2615  strcpy(name, Player->callsign);
2616  return;
2617  }
2618 
2619  // Check to see if ship is on the ship arrivals list
2620  if ( ws->sa_index != -1 ) {
2621  strcpy(name, Parse_objects[ws->sa_index].name);
2622  } else {
2623  ship *sp;
2624  sp = &Ships[wp->ship_index[wing_slot]];
2625 
2626  // in multiplayer, return the callsigns of the players who are in the ships
2627  if(Game_mode & GM_MULTIPLAYER){
2628  int player_index = multi_find_player_by_object(&Objects[sp->objnum]);
2629  if(player_index != -1){
2630  strcpy(name,Net_players[player_index].m_player->callsign);
2631  } else {
2632  strcpy(name,sp->ship_name);
2633  }
2634  } else {
2635  strcpy(name, sp->ship_name);
2636  }
2637  }
2638 }
2639 
2641 {
2642  return Selected_ss_class;
2643 }
2644 
2645 // Set selected ship to the first occupied wing slot, or first ship in pool if no slots are occupied
2647 {
2648  int i;
2649 
2650  Assert( (Ss_pool != NULL) && (Wss_slots != NULL) );
2651 
2652  Selected_ss_class = -1;
2653 
2654  if ( Wss_num_wings <= 0 ) {
2656  return;
2657  }
2658 
2659  // get first ship class found on slots
2660  for ( i = 0; i < MAX_WSS_SLOTS; i++ ) {
2661  if ( Wss_slots[i].ship_class >= 0 ) {
2663  break;
2664  }
2665  }
2666 
2667  if ( Selected_ss_class == -1 ) {
2668  Int3();
2669  for ( i = 0; i < static_cast<int>(Ship_info.size()); i++ ) {
2670  if ( Ss_pool[i] > 0 ) {
2671  Selected_ss_class = i;
2672  }
2673  }
2674  }
2675 
2676  if ( Selected_ss_class == -1 ) {
2677  Int3();
2678  return;
2679  }
2680 }
2681 
2682 // There may be ships that are in wings but not in Team_data[0]. Since we still want to show those
2683 // icons in the ship selection list, the code below checks for these cases. If a ship is found in
2684 // a wing, and is not in Team_data[0], it is appended to the end of the ship_count[] and ship_list[] arrays
2685 // that are in Team_data[0]
2686 //
2687 // exit: number of distinct ship classes available to choose from
2689 {
2690  int i, j, k, ship_in_parse_player, list_size;
2691  p_object *p_objp;
2692  team_data *p_team_data;
2693 
2694  p_team_data = tdata;
2695  ship_in_parse_player = 0;
2696  list_size = p_team_data->num_ship_choices;
2697 
2698  for ( i = 0; i < MAX_STARTING_WINGS; i++ ) {
2699  wing *wp;
2700  if ( Starting_wings[i] == -1 )
2701  continue;
2702  wp = &Wings[Starting_wings[i]];
2703  for ( j = 0; j < wp->current_count; j++ ) {
2704  ship_in_parse_player = 0;
2705 
2706  for ( k = 0; k < p_team_data->num_ship_choices; k++ ) {
2707  Assert( p_team_data->ship_count[k] >= 0 );
2708  if ( p_team_data->ship_list[k] == Ships[wp->ship_index[j]].ship_info_index ) {
2709  ship_in_parse_player = 1;
2710  break;
2711  }
2712  } // end for, go to next item in parse player
2713 
2714  if ( !ship_in_parse_player ) {
2715  p_team_data->ship_count[list_size] = 0;
2716  p_team_data->ship_list[list_size] = Ships[wp->ship_index[j]].ship_info_index;
2717  p_team_data->num_ship_choices++;
2718  list_size++;
2719  }
2720  } // end for, go get next ship in wing
2721 
2722  if ( wp->current_count == 0 ) {
2723 
2724  for ( p_objp = GET_FIRST(&Ship_arrival_list); p_objp != END_OF_LIST(&Ship_arrival_list); p_objp = GET_NEXT(p_objp) ) {
2725  if ( p_objp->wingnum == WING_INDEX(wp) ) {
2726  ship_in_parse_player = 0;
2727 
2728  for ( k = 0; k < p_team_data->num_ship_choices; k++ ) {
2729  Assert( p_team_data->ship_count[k] >= 0 );
2730  if ( p_team_data->ship_list[k] == p_objp->ship_class ) {
2731  ship_in_parse_player = 1;
2732  break;
2733  }
2734  } // end for, go to next item in parse player
2735 
2736  if ( !ship_in_parse_player ) {
2737  p_team_data->ship_count[list_size] = 0;
2738  p_team_data->ship_list[list_size] = p_objp->ship_class;
2739  p_team_data->num_ship_choices++;
2740  list_size++;
2741  }
2742  }
2743  }
2744  }
2745  } // end for, go to next wing
2746 
2747  if ( list_size == 0 ) {
2748  // ensure that the default player ship is in the ship_list too
2749  ship_in_parse_player = 0;
2750  for ( k = 0; k < p_team_data->num_ship_choices; k++ ) {
2751  Assert( p_team_data->ship_count[k] >= 0 );
2752  if ( p_team_data->ship_list[k] == p_team_data->default_ship ) {
2753  ship_in_parse_player = 1;
2754  break;
2755  }
2756  }
2757  if ( !ship_in_parse_player ) {
2758  p_team_data->ship_count[list_size] = 0;
2759  p_team_data->ship_list[list_size] = p_team_data->default_ship;
2760  p_team_data->num_ship_choices++;
2761  list_size++;
2762  }
2763  }
2764 
2765  return list_size;
2766 }
2767 
2768 // set numbers of ships in pool to default values
2770 {
2771  int i;
2772 
2773  Assert( Ss_pool != NULL );
2774 
2775  for ( i = 0; i < MAX_SHIP_CLASSES; i++ ) {
2776  Ss_pool[i] = -1;
2777  }
2778 
2779  // set number of available ships based on counts in team_data
2780  for ( i = 0; i < pteam->num_ship_choices; i++ ) {
2781  if (Ss_pool[pteam->ship_list[i]] == -1) {
2782  Ss_pool[pteam->ship_list[i]] = 0;
2783  }
2784  Ss_pool[pteam->ship_list[i]] += pteam->ship_count[i];
2785  }
2786 }
2787 
2788 // load the icons for a specific ship class
2789 void ss_load_icons(int ship_class)
2790 {
2791  ss_icon_info *icon;
2792 
2793  Assert( Ss_icons != NULL );
2794 
2795  icon = &Ss_icons[ship_class];
2796  ship_info *sip = &Ship_info[ship_class];
2797 
2798  if(!Cmdline_ship_choice_3d && strlen(sip->icon_filename))
2799  {
2800  int first_frame, num_frames, i;
2801  first_frame = bm_load_animation(sip->icon_filename, &num_frames);
2802 
2803  Assertion(first_frame != -1, "Failed to load icon %s\n", sip->icon_filename); // Could not load in icon frames.. get Alan
2804  if (first_frame == -1)
2805  return;
2806 
2807  for ( i = 0; i < num_frames; i++ ) {
2808  icon->icon_bmaps[i] = first_frame+i;
2809  }
2810 
2811  // set the current bitmap for the ship icon
2813  }
2814  else
2815  {
2816  icon->model_index = model_load(sip->pof_file, sip->n_subsystems, &sip->subsystems[0]);
2817  model_page_in_textures(icon->model_index, ship_class);
2818  }
2819 }
2820 
2821 // load all the icons for ships in the pool
2823 {
2824  int i, j;
2825 
2826  Assert( (Ss_pool != NULL) && (Ss_icons != NULL) );
2827 
2828  for ( i = 0; i < MAX_SHIP_CLASSES; i++ ) {
2829  // clear out data
2830  Ss_icons[i].current_icon_bitmap = -1;
2831  for ( j = 0; j < NUM_ICON_FRAMES; j++ ) {
2832  Ss_icons[i].icon_bmaps[j] = -1;
2833  }
2834  Ss_icons[i].model_index = -1;
2835 
2836  if ( Ss_pool[i] >= 0 ) {
2837  ss_load_icons(i);
2838  }
2839  }
2840 }
2841 
2842 // determine if the slot is disabled
2843 int ss_disabled_slot(int slot_num, bool ship_selection)
2844 {
2845  int status;
2846 
2847  if ( Wss_num_wings <= 0 ){
2848  return 0;
2849  }
2850 
2851  Assert( Ss_wings != NULL );
2852 
2853  // HACK HACK HACK - call the team select function in multiplayer
2854  if(Game_mode & GM_MULTIPLAYER) {
2855  return multi_ts_disabled_slot(slot_num);
2856  }
2857 
2858  status = Ss_wings[slot_num/MAX_WING_SLOTS].ss_slots[slot_num%MAX_WING_SLOTS].status;
2859 
2860  if (ship_selection) {
2861  return ( status & WING_SLOT_IGNORE_SHIPS );
2862  }
2863  else {
2864  return ( status & WING_SLOT_IGNORE_WEAPONS );
2865  }
2866 }
2867 
2868 // Goober5000 - determine if the slot is valid
2869 int ss_valid_slot(int slot_num)
2870 {
2871  int status;
2872 
2873  if (ss_disabled_slot(slot_num))
2874  return 0;
2875 
2876  Assert( Ss_wings != NULL );
2877 
2878  status = Ss_wings[slot_num/MAX_WING_SLOTS].ss_slots[slot_num%MAX_WING_SLOTS].status;
2879 
2880  return (status & WING_SLOT_FILLED) && !(status & WING_SLOT_EMPTY);
2881 }
2882 
2883 // reset the slot data
2885 {
2886  int i,j;
2887  ss_slot_info *slot;
2888 
2889  Assert( (Wss_slots != NULL) && (Ss_wings != NULL) );
2890 
2891  for ( i = 0; i < MAX_WSS_SLOTS; i++ ) {
2892  Wss_slots[i].ship_class = -1;
2893  for ( j = 0; j < MAX_SHIP_WEAPONS; j++ ) {
2894  Wss_slots[i].wep[j] = 0;
2895  Wss_slots[i].wep_count[j] = 0;
2896  }
2897  }
2898 
2899  for ( i = 0; i < MAX_WING_BLOCKS; i++ ) {
2900  for ( j = 0; j < MAX_WING_SLOTS; j++ ) {
2901  slot = &Ss_wings[i].ss_slots[j];
2902  slot->status = WING_SLOT_LOCKED;
2903  slot->sa_index = -1;
2904  slot->original_ship_class = -1;
2905  }
2906  }
2907 }
2908 
2909 // initialize all wing struct stuff
2911 {
2912  int idx;
2913 
2914  Assert( Ss_wings != NULL );
2915 
2916  for(idx=0;idx<MAX_STARTING_WINGS;idx++){
2917  Ss_wings[idx].wingnum = -1;
2918  Ss_wings[idx].num_slots = 0;
2919  Ss_wings[idx].is_late = 0;
2920  }
2921 }
2922 
2923 // set up Wss_num_wings and Wss_wings[] based on Starting_wings[] info
2924 void ss_init_wing_info(int wing_num,int starting_wing_num)
2925 {
2926  wing *wp;
2927  ss_wing_info *ss_wing;
2928  ss_slot_info *slot;
2929 
2930  Assert( Ss_wings != NULL );
2931 
2932  ss_wing = &Ss_wings[wing_num];
2933 
2934  if ( Starting_wings[starting_wing_num] < 0 ) {
2935  return;
2936  }
2937 
2938  ss_wing->wingnum = Starting_wings[starting_wing_num];
2939  Wss_num_wings++;
2940 
2941  wp = &Wings[ss_wing->wingnum];
2942  // niffiwan: don't overrun the array
2943  if (wp->current_count > MAX_WING_SLOTS) {
2944  Warning(LOCATION, "Starting Wing '%s' has '%d' ships. Truncating ship selection to 'MAX_WING_SLOTS'\n", Starting_wing_names[ss_wing->wingnum],wp->current_count);
2945  ss_wing->num_slots = MAX_WING_SLOTS;
2946  } else {
2947  ss_wing->num_slots = wp->current_count;
2948  }
2949 
2950  // deal with wing arriving after mission start
2951  if ( wp->current_count == 0 || wp->ship_index[0] == -1 ) {
2952  p_object *p_objp;
2953  // Temporarily fill in the current count and initialize the ship list in the wing
2954  // This gets cleaned up before the mission is started
2955  for ( p_objp = GET_FIRST(&Ship_arrival_list); p_objp != END_OF_LIST(&Ship_arrival_list); p_objp = GET_NEXT(p_objp) ) {
2956  if ( p_objp->wingnum == WING_INDEX(wp) ) {
2957  // niffiwan: don't overrun the array
2958  if (ss_wing->num_slots >= MAX_WING_SLOTS) {
2959  Warning(LOCATION, "Starting Wing '%s' has more than 'MAX_WING_SLOTS' ships\n", Starting_wing_names[ss_wing->wingnum]);
2960  break;
2961  }
2962  slot = &ss_wing->ss_slots[ss_wing->num_slots++];
2963  slot->sa_index = POBJ_INDEX(p_objp);
2964  slot->original_ship_class = p_objp->ship_class;
2965  }
2966  ss_wing->is_late = 1;
2967  }
2968  }
2969 }
2970 
2971 // Determine if a ship is actually a console player ship
2973 {
2974  int wingnum, slotnum;
2975 
2976  wingnum=index/MAX_WING_SLOTS;
2977  slotnum=index%MAX_WING_SLOTS;
2978 
2979  if ( wingnum >= Wss_num_wings ) {
2980  return 0;
2981  }
2982 
2983  Assert( Ss_wings != NULL );
2984 
2985  if ( Ss_wings[wingnum].ss_slots[slotnum].status & WING_SLOT_IS_PLAYER ) {
2986  return 1;
2987  }
2988 
2989  return 0;
2990 }
2991 
2992 // init the ship selection portion of the units, and set up the ui data
2994 {
2995  int i,j;
2996  wing *wp;
2997  ss_slot_info *ss_slot;
2998  ss_wing_info *ss_wing;
2999 
3000  Assert( (Ss_wings != NULL) && (Wss_slots != NULL) );
3001 
3002  for ( i = 0; i < Wss_num_wings; i++ ) {
3003 
3004  ss_wing = &Ss_wings[i];
3005 
3006  if ( ss_wing->wingnum < 0 ) {
3007  Int3();
3008  continue;
3009  }
3010 
3011  wp = &Wings[ss_wing->wingnum];
3012 
3013  for ( j = 0; j < ss_wing->num_slots; j++ ) {
3014 
3015  ss_slot = &ss_wing->ss_slots[j];
3016 
3017  if ( ss_slot->sa_index == -1 ) {
3019  }
3020 
3021  //set the lock to the default
3022  if (Game_mode & GM_MULTIPLAYER) {
3023  ss_slot->status = WING_SLOT_LOCKED;
3024  }
3025  else {
3026  ss_slot->status = 0;
3027  }
3028 
3029  // Set the type of slot. Check if the slot is marked as locked, if so then the player is not
3030  // going to be able to modify that ship.
3031  if ( ss_slot->sa_index == -1 ) {
3032  int objnum;
3033  if ( Ships[wp->ship_index[j]].flags2 & SF2_SHIP_LOCKED ) {
3034  ss_slot->status |= WING_SLOT_SHIPS_DISABLED;
3035  }
3036  if ( Ships[wp->ship_index[j]].flags2 & SF2_WEAPONS_LOCKED ) {
3037  ss_slot->status |= WING_SLOT_WEAPONS_DISABLED;
3038  }
3039 
3040  // if neither the ship or weapon has been locked, mark the slot as filled
3041  if (!(ss_slot->status & WING_SLOT_DISABLED)) {
3042  ss_slot->status = WING_SLOT_FILLED;
3043  }
3044 
3045  objnum = Ships[wp->ship_index[j]].objnum;
3046  if ( Objects[objnum].flags & OF_PLAYER_SHIP ) {
3047  if ( ss_slot->status & WING_SLOT_LOCKED ) {
3048  // Int3(); // Get Alan
3049 
3050  // just unflag it
3051  ss_slot->status &= ~(WING_SLOT_LOCKED);
3052  }
3053  ss_slot->status |= WING_SLOT_FILLED;
3054  if ( objnum == OBJ_INDEX(Player_obj) ) {
3055  ss_slot->status |= WING_SLOT_IS_PLAYER;
3056  }
3057  }
3058  } else {
3059  if ( Parse_objects[ss_slot->sa_index].flags2 & P2_SF2_SHIP_LOCKED ) {
3060  ss_slot->status |= WING_SLOT_SHIPS_DISABLED;
3061  }
3062  if ( Parse_objects[ss_slot->sa_index].flags2 & P2_SF2_WEAPONS_LOCKED ) {
3063  ss_slot->status |= WING_SLOT_WEAPONS_DISABLED;
3064  }
3065 
3066  // if the slot is not marked as locked, it's filled
3067  if (!(ss_slot->status & WING_SLOT_DISABLED)) {
3068  ss_slot->status = WING_SLOT_FILLED;
3069  }
3070  if ( Parse_objects[ss_slot->sa_index].flags & P_OF_PLAYER_START ) {
3071  if ( ss_slot->status & WING_SLOT_LOCKED ) {
3072  // Int3(); // Get Alan
3073 
3074  // just unflag it
3075  ss_slot->status &= ~(WING_SLOT_LOCKED);
3076  }
3077  ss_slot->status |= WING_SLOT_FILLED;
3078  ss_slot->status |= WING_SLOT_IS_PLAYER;
3079  }
3080  }
3081 
3082  // Assign the ship class to the unit
3084 
3085  } // end for
3086  } // end for
3087 
3088  // lock/unlock any necessary slots for multiplayer
3089  if(Game_mode & GM_MULTIPLAYER){
3091  }
3092 }
3093 
3094 // set the necessary pointers
3096 {
3097  Assert( (team >= 0) && (team < MAX_TVT_TEAMS) );
3098 
3099  Ss_wings = Ss_wings_teams[team];
3100  Ss_icons = Ss_icons_teams[team];
3101 }
3102 
3103 // reset the necessary pointers to defaults
3105 {
3107 
3108  if ( Ship_select_open )
3109  return;
3110 
3111  Ss_wings = NULL;
3112  Ss_icons = NULL;
3113 }
3114 
3115 // initialize team specific stuff
3116 void ship_select_init_team_data(int team_num)
3117 {
3118  int idx;
3119 
3120  // set up the pointers to initialize the data structures.
3121  common_set_team_pointers(team_num);
3122 
3123  ss_fixup_team_data(&Team_data[team_num]);
3124  ss_init_pool(&Team_data[team_num]);
3125 
3126  ss_clear_slots(); // reset data for slots
3127  ss_clear_wings();
3128 
3129  // determine how many wings we should be checking for
3130  Wss_num_wings = 0;
3131 
3132  if(MULTI_TEAM){
3133  // now setup wings for easy reference
3134  ss_init_wing_info(0,team_num);
3135  } else {
3136  // now setup wings for easy reference
3137  for (idx = 0; idx < MAX_STARTING_WINGS; idx++) {
3139  }
3140  }
3141 
3142 
3143  // if there are no wings, don't call the init_units() function
3144  if ( Wss_num_wings <= 0 ) {
3145  Wss_slots[0].ship_class = Team_data[team_num].default_ship;
3146  return;
3147  }
3148 
3149  ss_init_units();
3150 }
3151 
3152 // called when the briefing is entered
3154 {
3155  // initialize team critical data for all teams
3156  int idx;
3157 
3158  if(MULTI_TEAM){
3159  // initialize for all teams in the game
3160  for(idx=0;idx<MULTI_TS_MAX_TVT_TEAMS;idx++){
3162  }
3163 
3164  // finally, intialize team data for myself
3166  } else {
3168  }
3169 
3170  init_active_list();
3171 
3172  // load the necessary icons/animations
3174 
3177 }
3178 
3180 {
3183 }
3184 
3185 // change any interface data based on updated Wss_slots[] and Ss_pool[]
3187 {
3188  int i;
3189  ss_slot_info *slot;
3190 
3191  Assert( Ss_wings != NULL );
3192 
3193  int old_list_start = SS_active_list_start;
3194 
3195  init_active_list(); // build the list of pool ships
3196 
3197  if ( old_list_start < SS_active_list_size ) {
3198  SS_active_list_start = old_list_start;
3199  }
3200 
3201  for ( i = 0; i < MAX_WSS_SLOTS; i++ ) {
3202  slot = &Ss_wings[i/MAX_WING_SLOTS].ss_slots[i%MAX_WING_SLOTS];
3203 
3204  if ( Wss_slots[i].ship_class == -1 ) {
3205  if ( slot->status & WING_SLOT_FILLED ) {
3206  slot->status &= ~WING_SLOT_FILLED;
3207  slot->status |= WING_SLOT_EMPTY;
3208  }
3209  } else {
3210  if ( slot->status & WING_SLOT_EMPTY ) {
3211  slot->status &= ~WING_SLOT_EMPTY;
3212  slot->status |= WING_SLOT_FILLED;
3213  }
3214  }
3215  }
3216 }
3217 
3218 // exit: data changed flag
3219 int ss_swap_slot_slot(int from_slot, int to_slot, int *sound)
3220 {
3221  int i, tmp;
3222 
3223  if ( from_slot == to_slot ) {
3224  *sound=SND_ICON_DROP_ON_WING;
3225  return 0;
3226  }
3227 
3228  // ensure from_slot has a ship to pick up
3229  if ( Wss_slots[from_slot].ship_class < 0 ) {
3230  *sound=SND_ICON_DROP;
3231  return 0;
3232  }
3233 
3234  // swap ship class
3235  tmp = Wss_slots[from_slot].ship_class;
3236  Wss_slots[from_slot].ship_class = Wss_slots[to_slot].ship_class;
3237  Wss_slots[to_slot].ship_class = tmp;
3238 
3239  // swap weapons
3240  for ( i = 0; i < MAX_SHIP_WEAPONS; i++ ) {
3241  tmp = Wss_slots[from_slot].wep[i];
3242  Wss_slots[from_slot].wep[i] = Wss_slots[to_slot].wep[i];
3243  Wss_slots[to_slot].wep[i] = tmp;
3244 
3245  tmp = Wss_slots[from_slot].wep_count[i];
3246  Wss_slots[from_slot].wep_count[i] = Wss_slots[to_slot].wep_count[i];
3247  Wss_slots[to_slot].wep_count[i] = tmp;
3248  }
3249 
3250  *sound=SND_ICON_DROP_ON_WING;
3251  return 1;
3252 }
3253 
3254 // exit: data changed flag
3255 int ss_dump_to_list(int from_slot, int to_list, int *sound)
3256 {
3257  int i;
3258  wss_unit *slot;
3259 
3260  Assert( (Ss_pool != NULL) && (Wl_pool != NULL) && (Wss_slots != NULL) );
3261 
3262  slot = &Wss_slots[from_slot];
3263 
3264  // ensure from_slot has a ship to pick up
3265  if ( slot->ship_class < 0 ) {
3266  *sound=SND_ICON_DROP;
3267  return 0;
3268  }
3269 
3270  // put ship back in list
3271  Ss_pool[to_list]++; // return to list
3272  slot->ship_class = -1; // remove from slot
3273 
3274  // put weapons back in list
3275  for ( i = 0; i < MAX_SHIP_WEAPONS; i++ ) {
3276  if ( (slot->wep[i] >= 0) && (slot->wep_count[i] > 0) ) {
3277  Wl_pool[slot->wep[i]] += slot->wep_count[i];
3278  slot->wep[i] = -1;
3279  slot->wep_count[i] = 0;
3280  }
3281  }
3282 
3283  *sound=SND_ICON_DROP;
3284  return 1;
3285 }
3286 
3287 // exit: data changed flag
3288 int ss_grab_from_list(int from_list, int to_slot, int *sound)
3289 {
3290  wss_unit *slot;
3291  int i, wep[MAX_SHIP_WEAPONS], wep_count[MAX_SHIP_WEAPONS];
3292 
3293  Assert( (Ss_pool != NULL) && (Wss_slots != NULL) );
3294 
3295  slot = &Wss_slots[to_slot];
3296 
3297  // ensure that pool has ship
3298  if ( Ss_pool[from_list] <= 0 )
3299  {
3300  *sound=SND_ICON_DROP;
3301  return 0;
3302  }
3303 
3304  Assert(slot->ship_class < 0 ); // slot should be empty
3305 
3306  // take ship from list->slot
3307  Ss_pool[from_list]--;
3308  slot->ship_class = from_list;
3309 
3310  // take weapons from list->slot
3311  wl_get_default_weapons(from_list, to_slot, wep, wep_count);
3312  wl_remove_weps_from_pool(wep, wep_count, slot->ship_class);
3313  for ( i = 0; i < MAX_SHIP_WEAPONS; i++ )
3314  {
3315  slot->wep[i] = wep[i];
3316  slot->wep_count[i] = wep_count[i];
3317  }
3318 
3319  *sound=SND_ICON_DROP_ON_WING;
3320  return 1;
3321 }
3322 
3323 // exit: data changed flag
3324 int ss_swap_list_slot(int from_list, int to_slot, int *sound)
3325 {
3326  int i, wep[MAX_SHIP_WEAPONS], wep_count[MAX_SHIP_WEAPONS];
3327  wss_unit *slot;
3328 
3329  Assert( (Ss_pool != NULL) && (Wl_pool != NULL) && (Wss_slots != NULL) );
3330 
3331  // ensure that pool has ship
3332  if ( Ss_pool[from_list] <= 0 )
3333  {
3334  *sound=SND_ICON_DROP;
3335  return 0;
3336  }
3337 
3338  slot = &Wss_slots[to_slot];
3339  Assert(slot->ship_class >= 0 ); // slot should be filled
3340 
3341  // put ship from slot->list
3342  Ss_pool[Wss_slots[to_slot].ship_class]++;
3343 
3344  // put weapons from slot->list
3345  for ( i = 0; i < MAX_SHIP_WEAPONS; i++ )
3346  {
3347  if ( (slot->wep[i] >= 0) && (slot->wep_count[i] > 0) )
3348  {
3349  Wl_pool[slot->wep[i]] += slot->wep_count[i];
3350  slot->wep[i] = -1;
3351  slot->wep_count[i] = 0;
3352  }
3353  }
3354 
3355  // take ship from list->slot
3356  Ss_pool[from_list]--;
3357  slot->ship_class = from_list;
3358 
3359  // take weapons from list->slot
3360  wl_get_default_weapons(from_list, to_slot, wep, wep_count);
3361  wl_remove_weps_from_pool(wep, wep_count, slot->ship_class);
3362  for ( i = 0; i < MAX_SHIP_WEAPONS; i++ )
3363  {
3364  slot->wep[i] = wep[i];
3365  slot->wep_count[i] = wep_count[i];
3366  }
3367 
3368  *sound=SND_ICON_DROP_ON_WING;
3369  return 1;
3370 }
3371 
3372 void ss_apply(int mode, int from_slot, int from_list, int to_slot, int to_list,int player_index)
3373 {
3374  int update=0;
3375  int sound=-1;
3376 
3377  switch(mode){
3378  case WSS_SWAP_SLOT_SLOT:
3379  update = ss_swap_slot_slot(from_slot, to_slot, &sound);
3380  break;
3381  case WSS_DUMP_TO_LIST:
3382  update = ss_dump_to_list(from_slot, to_list, &sound);
3383  break;
3384  case WSS_GRAB_FROM_LIST:
3385  update = ss_grab_from_list(from_list, to_slot, &sound);
3386  break;
3387  case WSS_SWAP_LIST_SLOT:
3388  update = ss_swap_list_slot(from_list, to_slot, &sound);
3389  break;
3390  }
3391 
3392  // only play this sound if the move was done locally (by the host in other words)
3393  if ( (sound >= 0) && (player_index == -1) ) {
3394  gamesnd_play_iface(sound);
3395  }
3396 
3397  if ( update ) {
3398  // NO LONGER USED - THERE IS A MULTIPLAYER VERSION OF THIS SCREEN NOW
3399  /*
3400  if ( MULTIPLAYER_HOST ) {
3401  int size;
3402  ubyte wss_data[MAX_PACKET_SIZE-20];
3403  size = store_wss_data(wss_data, MAX_PACKET_SIZE-20, sound);
3404  send_wss_update_packet(wss_data, size, player_index);
3405  }
3406  */
3407 
3409  }
3410 }
3411 
3412 void ss_drop(int from_slot,int from_list,int to_slot,int to_list,int player_index)
3413 {
3414  int mode;
3416 
3417  mode = wss_get_mode(from_slot, from_list, to_slot, to_list, -1);
3418  if ( mode >= 0 ) {
3419  ss_apply(mode, from_slot, from_list, to_slot, to_list,player_index);
3420  }
3421 }
3422 
3423 // lock/unlock any necessary slots for multiplayer
3425 {
3426  int i,j;
3427  ss_slot_info *ss_slot;
3428  ss_wing_info *ss_wing;
3429 
3430  // no wings
3431  if ( Wss_num_wings <= 0 ) {
3432  Assert( Wss_slots != NULL );
3434  return;
3435  }
3436 
3437  Assert( Ss_wings != NULL );
3438 
3439  for ( i = 0; i < Wss_num_wings; i++ ) {
3440  ss_wing = &Ss_wings[i];
3441  if ( ss_wing->wingnum < 0 ) {
3442  Int3();
3443  continue;
3444  }
3445 
3446  // NOTE : the method below will eventually have to change to account for all possible netgame options
3447  for ( j = 0; j < ss_wing->num_slots; j++ ) {
3448  // get the slot pointer
3449  ss_slot = &ss_wing->ss_slots[j];
3450 
3451  if (ss_slot->sa_index == -1) {
3452  // lock all slots by default
3453  ss_slot->status |= WING_SLOT_LOCKED;
3454 
3455  // if this is my slot, then unlock it
3457  ss_slot->status &= ~WING_SLOT_LOCKED;
3458  }
3459  }
3460  }
3461  }
3462 }
#define SF2_WEAPONS_LOCKED
Definition: ship.h:507
void gr_rect(int x, int y, int w, int h, int resize_mode)
Definition: 2d.cpp:2068
void ship_wing_cleanup(int shipnum, wing *wingp)
Definition: ship.cpp:7640
bool uses_team_colors
Definition: ship.h:1365
void ship_select_blit_ship_info()
Definition: sound.cpp:39
int ss_return_saindex(int slot_num)
void bm_unlock(int handle)
Unlocks a bitmap.
Definition: bmpman.cpp:3005
void set_highlight_action(void(*_user_function)(void))
Definition: button.cpp:375
pilotfile Pilot
Definition: pilotfile.cpp:7
void hud_set_wingman_status_none(int wing_index, int wing_pos)
#define WING_0_SHIP_2
char Starting_wing_names[MAX_STARTING_WINGS][NAME_LENGTH]
Definition: ship.cpp:139
#define WING_0_SHIP_3
wing Wings[MAX_WINGS]
Definition: ship.cpp:128
int Wing_icon_coords[GR_NUM_RESOLUTIONS][MAX_WSS_SLOTS][2]
int i
Definition: multi_pxo.cpp:466
void mouse_set_pos(int xpos, int ypos)
Definition: mouse.cpp:604
void ship_select_init()
#define WING_SLOT_IS_PLAYER
void add_XSTR(char *string, int _xstr_id, int _x, int _y, UI_GADGET *_assoc, int _color_type, int _font_id=-1)
Definition: window.cpp:476
int use_descent
int button_hilighted()
Definition: button.cpp:387
void draw_ship_icons()
int ship_class
Definition: multi.h:451
ss_active_item * get_free_active_list_node()
void wss_save_loadout()
int objnum
Definition: ship.h:537
int Game_mode
Definition: systemvars.cpp:24
GLfloat GLfloat GLfloat GLfloat h
Definition: Glext.h:7280
#define SS_BUTTON_DUMMY
vec3d mins
Definition: model.h:746
void gr_flip()
Definition: 2d.cpp:2113
commit pressed
Definition: gamesnd.h:294
#define ON_SHIP_SELECT
Definition: missionbrief.h:19
brief_common_buttons Common_buttons[3][GR_NUM_RESOLUTIONS][NUM_COMMON_BUTTONS]
char Game_current_mission_filename[MAX_FILENAME_LEN]
Definition: fredstubs.cpp:26
polymodel * model_get(int model_num)
Definition: modelread.cpp:3134
weapon_info Weapon_info[MAX_WEAPON_TYPES]
Definition: weapons.cpp:79
net_player * Net_player
Definition: multi.cpp:94
#define GR_RESIZE_MENU
Definition: 2d.h:684
#define MOUSE_LEFT_BUTTON
Definition: mouse.h:43
char default_player_ship[255]
void draw_model_icon(int model_id, int flags, float closeup_zoom, int x, int y, int w, int h, const ship_info *sip, int resize_mode, const vec3d *closeup_pos)
int Hot_ss_slot
void ss_set_carried_icon(int from_slot, int ship_class)
char icon_filename[MAX_FILENAME_LEN]
Definition: ship.h:1338
GLuint index
Definition: Glext.h:5608
bool save_savefile()
Definition: csg.cpp:1524
int ss_return_original_ship_class(int slot_num)
int Tech_ship_display_coords[GR_NUM_RESOLUTIONS][4]
Definition: techmenu.cpp:102
int ss_grab_from_list(int from_list, int to_slot, int *sound)
#define MAX_BRIEF_LINES
#define MAX_SHIPS
Definition: globals.h:37
SCP_vector< p_object > Parse_objects
int anim_timer_start
drop a ship icon on a wing slot
Definition: gamesnd.h:289
float Canv_h2
Definition: 3dsetup.cpp:40
void ss_reset_carried_icon()
int snazzy_menu_do(ubyte *data, int mask_w, int mask_h, int num_regions, MENU_REGION *regions, int *action, int poll_key, int *key)
Definition: snazzyui.cpp:59
void ss_blit_ship_icon(int x, int y, int ship_class, int bmap_num)
#define WING_SLOT_IGNORE_WEAPONS
int model_num
Definition: ship.h:1189
void ss_load_all_icons()
void ship_add_exited_ship(ship *sp, int reason)
Definition: ship.cpp:5298
void _cdecl void void _cdecl void _cdecl Warning(char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
#define WING_0_SHIP_0
Assert(pm!=NULL)
struct ss_icon_info ss_icon_info
char filename[MAX_FILENAME_LEN]
int pick_from_ship_list(int screen_offset, int ship_class)
#define GR_NUM_RESOLUTIONS
Definition: 2d.h:651
#define mprintf(args)
Definition: pstypes.h:238
ss_wing_info * Ss_wings
w_bank * gun_banks
Definition: model.h:772
__inline void gr_string(int x, int y, const char *string, int resize_mode=GR_RESIZE_FULL)
Definition: 2d.h:769
#define WING_2_SHIP_0
#define EOLN
Definition: parselo.h:32
void clear_active_list()
general failure sound for any event
Definition: gamesnd.h:297
Definition: 2d.h:95
int ss_disabled_slot(int slot_num, bool ship_selection)
int res
Definition: 2d.h:370
int max_h_unscaled
Definition: 2d.h:361
int bm_get_info(int handle, int *w, int *h, ubyte *flags, int *nframes, int *fps)
Gets info on the bitmap indexed by handle.
Definition: bmpman.cpp:769
#define SHIP_SELECT_ICON_0
#define MR_NO_LIGHTING
Definition: model.h:867
int Lcl_pl
Definition: localize.cpp:49
struct vec3d::@225::@227 xyz
void unload_wing_icons()
CButton * team
int Hot_ss_icon
UI_WINDOW Ship_select_ui_window
void pick_from_wing(int wb_num, int ws_num)
#define SHIP_SELECT_SHIP_INFO_MAX_LINE_LEN
#define SEF_PLAYER_DELETED
Definition: ship.h:849
struct ss_active_item ss_active_item
#define Assertion(expr, msg,...)
Definition: clang.h:41
void common_check_buttons()
#define GR_MAYBE_CLEAR_RES(bmap)
Definition: 2d.h:639
vec3d maxs
Definition: model.h:746
model_subsystem * subsystems
Definition: ship.h:1271
#define MAX_WSS_SLOTS
int ship_class
Definition: missionparse.h:351
Definition: ship.h:1516
int common_scroll_up_pressed(int *start, int size, int max_show)
GLenum mode
Definition: Glext.h:5794
int Background_playing
int do_mouse_over_wing_slot(int block, int slot)
int Ship_select_overlay_id
void help_overlay_set_state(int overlay_id, int resolution_index, int state)
void key_flush()
Definition: key.cpp:356
#define P2_SF2_WEAPONS_LOCKED
Definition: missionparse.h:509
virtual void hide(int n)
Definition: gadget.cpp:207
void gr_set_color_fast(color *dst)
Definition: 2d.cpp:1197
int ss_get_selected_ship()
void ss_synch_interface()
void common_buttons_maybe_reload(UI_WINDOW *ui_window)
Definition: ui.h:195
std::basic_string< char, std::char_traits< char >, std::allocator< char > > SCP_string
Definition: vmallocator.h:21
int flags
Definition: multi.h:463
#define OF_PLAYER_SHIP
Definition: object.h:109
#define WING_1_SHIP_3
void set_active_ui(UI_WINDOW *ui_window)
void mission_hotkey_validate()
int Selected_ss_class
void gr_set_bitmap(int bitmap_num, int alphablend_mode, int bitblt_mode, float alpha)
Definition: 2d.cpp:2105
int max_w_unscaled
Definition: 2d.h:361
#define Int3()
Definition: pstypes.h:292
#define SS_ACTIVE_ITEM_USED
ss_active_item * prev
#define WSS_GRAB_FROM_LIST
#define COMMON_WEAPON_REGION
int Mouse_down_last_frame
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: Glext.h:7308
const char *(* tooltip_handler)(const char *text)
Definition: ui.h:649
int bm_release(int handle, int clear_render_targets)
Frees both a bitmap's data and it's associated slot.
Definition: bmpman.cpp:2603
void draw_ship_icon_with_number(int screen_offset, int ship_class)
int ShipSelectModelNum
void ss_return_name(int wing_block, int wing_slot, char *name)
void snazzy_menu_add_region(MENU_REGION *region, const char *text, int mask, int key, int click_sound)
Definition: snazzyui.cpp:163
char callsign[CALLSIGN_LEN+1]
Definition: player.h:91
int ss_valid_slot(int slot_num)
void do_mouse_over_list_slot(int index)
#define BMP_AABITMAP
antialiased bitmap
Definition: bmpman.h:52
void generic_anim_unload(generic_anim *ga)
Definition: generic.cpp:291
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 wl_update_parse_object_weapons(p_object *pobjp, wss_unit *slot)
anim * ss_load_individual_animation(int ship_class)
int mouse_get_pos_unscaled(int *xpos, int *ypos)
Definition: mouse.cpp:580
int Multi_sync_mode
Definition: multiui.cpp:7348
#define SHIP_SELECT_ICON_1
int wep_count[MAX_SHIP_WEAPONS]
int ship_count[MAX_SHIP_CLASSES]
Definition: missionparse.h:535
#define MAX_WING_SLOTS
ss_wing_info Ss_wings_teams[MAX_TVT_TEAMS][MAX_WING_BLOCKS]
#define SHIP_SELECT_Y_COORD
void common_reset_buttons()
void common_set_interface_palette(char *filename)
int species
Definition: ship.h:1166
void common_flash_button_init()
void draw_forced(int frame_num)
Definition: button.cpp:104
int create_default_player_ship(int use_last_flown)
void wl_reset_to_defaults()
const char * ss_tooltip_handler(const char *str)
int mouse_down(int btn)
Definition: mouse.cpp:315
int ss_icon_being_carried()
player Players[MAX_PLAYERS]
int * Wl_pool
void destroy()
Definition: window.cpp:189
int ss_carried_icon_moved()
int num_frames
Definition: generic.h:20
#define gr_reset_clip
Definition: 2d.h:745
int instance
Definition: object.h:150
void set_mask_bmap(char *fname)
Definition: window.cpp:75
#define MISSION_FLAG_NO_BRIEFING
Definition: missionparse.h:78
int set_bmaps(char *ani_filename, int nframes=3, int start_frame=1)
Definition: gadget.cpp:71
GLintptr offset
Definition: Glext.h:5497
char ship_select_background[GR_NUM_RESOLUTIONS][MAX_FILENAME_LEN]
char pof_file[MAX_FILENAME_LEN]
Definition: ship.h:1183
net_player_info p_info
Definition: multi.h:473
void ss_clear_wings()
void mission_parse_fixup_players()
#define NUM_ICON_FRAMES
#define SIF_BIG_SHIP
Definition: ship.h:944
void common_redraw_pressed_buttons()
int common_select_do(float frametime)
#define MAX_SHIP_WEAPONS
Definition: globals.h:64
ss_icon_info Ss_icons_teams[MAX_TVT_TEAMS][MAX_SHIP_CLASSES]
#define NETINFO_FLAG_AM_MASTER
Definition: multi.h:599
int ss_wing_slot_is_console_player(int index)
char * desc
Definition: ship.h:1173
void ship_select_buttons_init()
#define SHIP_SELECT_NUM_TEXT
char * manufacturer_str
Definition: ship.h:1172
#define WING_1_SHIP_1
#define nprintf(args)
Definition: pstypes.h:239
#define GM_MULTIPLAYER
Definition: systemvars.h:18
#define SHIP_SELECT_SHIP_SCROLL_UP
int first_frame
Definition: generic.h:19
#define SS_BUTTON_RESET
char name[NAME_LENGTH]
Definition: ship.h:1517
#define MAX_SHIP_CLASSES
Definition: globals.h:48
int Ship_list_coords[GR_NUM_RESOLUTIONS][MAX_ICONS_ON_SCREEN][4]
int multi_ts_disabled_slot(int slot_num, int player_index)
int flags
Definition: ship.h:1227
#define POBJ_INDEX(pobjp)
Definition: missionparse.h:523
void active_list_add(int ship_class)
void ss_restore_loadout()
int Cmdline_ship_choice_3d
Definition: cmdline.cpp:378
#define MAX_STARTING_WINGS
Definition: globals.h:54
int pressed()
Definition: button.cpp:325
void ss_clear_slots()
int last_ship_flown_si_index
Definition: player.h:122
int Commit_pressed
#define MAX_WEAPON_TYPES
Definition: globals.h:73
#define COMMON_SS_REGION
void active_list_remove(int ship_class)
#define ICON_FRAME_DISABLED_HIGH
void draw_wing_block(int wb_num, int hot_slot, int selected_slot, int class_select, bool ship_selection)
ss_active_item * next
void generic_anim_render(generic_anim *ga, float frametime, int x, int y, bool menu)
Definition: generic.cpp:437
#define w(p)
Definition: modelsinc.h:68
sprintf(buf,"(%f,%f,%f)", v3->xyz.x, v3->xyz.y, v3->xyz.z)
#define WING_SLOT_FILLED
void set_team_color(team_color &clr)
void toggle_player_object()
SCP_string default_team_name
Definition: ship.h:1366
int wl_update_ship_weapons(int objnum, wss_unit *slot)
void ship_select_redraw_pressed_buttons()
int n_subsystems
Definition: ship.h:1270
#define SUBSYSTEM_TURRET
Definition: model.h:54
char * ship_length
Definition: ship.h:1177
#define GR_640
Definition: 2d.h:652
#define MAX_NUM_SHIP_DESC_LINES
#define SHIP_SELECT_RESET
char * type_str
Definition: ship.h:1169
Definition: bmpman.h:101
float max_shield_strength
Definition: ship.h:1310
#define WING_SLOT_SHIPS_DISABLED
#define P2_SF2_SHIP_LOCKED
Definition: missionparse.h:508
int ss_fixup_team_data(team_data *tdata)
GLdouble s
Definition: Glext.h:5321
void ai_post_process_mission()
Definition: aigoals.cpp:159
void common_select_init()
int split_str(const char *src, int max_pixel_w, int *n_chars, const char **p_str, int max_lines, char ignore_char)
Definition: parselo.cpp:3412
bitmap * bm_lock(int handle, ubyte bpp, ubyte flags, bool nodebug)
Locks down the bitmap indexed by bitmapnum.
Definition: bmpman.cpp:1754
void ss_make_slot_full(int slot_index)
int current_count
Definition: ship.h:1530
ss_buttons(char *name, int x1, int y1, int xt1, int yt1, int h, int s)
#define SHIP_DESC_X
void ss_maybe_drop_icon()
#define SHIP_SELECT_ICON_2
void common_set_team_pointers(int team)
#define NETINFO_FLAG_GAME_HOST
Definition: multi.h:603
vec3d closeup_pos
Definition: ship.h:1327
#define WING_2_SHIP_1
void maybe_change_selected_wing_ship(int wb_num, int ws_num)
void send_mission_sync_packet(int mode, int start_campaign)
Definition: multimsgs.cpp:5154
#define ICON_FRAME_DISABLED
int wss_get_mode(int from_slot, int from_list, int to_slot, int to_list, int wl_ship_slot)
Definition: ship.h:534
void ss_reset_team_pointers()
int model_load(char *filename, int n_subsystems, model_subsystem *subsystems, int ferror=1, int duplicate=0)
Definition: modelread.cpp:2573
int num_slots
Definition: model.h:433
void start_ship_animation(int ship_class, int play_sound=0)
#define MAX_WING_BLOCKS
void model_page_in_textures(int modelnum, int ship_info_index=-1)
int default_ship
Definition: missionparse.h:530
void ship_select_check_buttons()
int idx
Definition: multiui.cpp:761
#define SHIP_SELECT_ICON_3
void maybe_change_selected_ship(int offset)
void common_check_keys(int k)
void common_render_selected_screen_button()
#define WING_SLOT_LOCKED
int wave_count
Definition: ship.h:1527
vec3d rotation_time
Definition: ship.h:1198
char name[NAME_LENGTH]
Definition: ship.h:1163
object Objects[MAX_OBJECTS]
Definition: object.cpp:62
GLint GLint GLint GLint GLint x
Definition: Glext.h:5182
void ship_select_do(float frametime)
int Drop_on_wing_mflag
unsigned char ubyte
Definition: pstypes.h:62
int Wing_slot_disabled_bitmap
#define NUM_SHIP_SELECT_REGIONS
const char * XSTR(const char *str, int index)
Definition: localize.cpp:851
int Ship_select_background_bitmap
void update_player_ship(int si_index)
#define OBJ_INDEX(objp)
Definition: object.h:235
#define MULTI_TEAM
Definition: multi.h:655
ship * Player_ship
Definition: ship.cpp:124
#define MAX_ICONS_ON_SCREEN
char modified[DATE_TIME_LENGTH]
Definition: missionparse.h:135
void ss_init_pool(team_data *pteam)
void ss_apply(int mode, int from_slot, int from_list, int to_slot, int to_list, int player_index)
int max_w
Definition: 2d.h:360
#define NOX(s)
Definition: pstypes.h:473
int ss_swap_slot_slot(int from_slot, int to_slot, int *sound)
char * armor_str
Definition: ship.h:1171
void ss_unload_all_anims()
bool end_string_at_first_hash_symbol(char *src)
Definition: parselo.cpp:3833
void init_active_list()
void _cdecl void void _cdecl Error(const char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
#define P_OF_PLAYER_START
Definition: missionparse.h:453
void ship_select_close()
GLbitfield flags
Definition: Glext.h:6722
#define SIF_HUGE_SHIP
Definition: ship.h:945
int Starting_wings[MAX_STARTING_WINGS]
Definition: ship.cpp:132
int Common_team
int ss_swap_list_slot(int from_list, int to_slot, int *sound)
void capture_mouse()
Definition: gadget.cpp:225
int num_secondary_banks
Definition: ship.h:1298
GLuint const GLchar * name
Definition: Glext.h:5608
#define MULTI_TS_MAX_TVT_TEAMS
wss_unit * Wss_slots
color Color_black
Definition: alphacolors.cpp:32
#define REVOLUTION_RATE
Definition: techmenu.cpp:37
void common_buttons_init(UI_WINDOW *ui_window)
void ship_select_common_close()
#define COMMON_HELP_REGION
#define ICON_FRAME_SELECTED
void maybe_pick_up_list_icon(int offset)
int create_wings()
int bm_load(const char *real_filename)
Loads a bitmap so we can draw with it later.
Definition: bmpman.cpp:1119
#define WING_1_SHIP_2
GLboolean GLboolean GLboolean b
Definition: Glext.h:5781
ship Ships[MAX_SHIPS]
Definition: ship.cpp:122
struct ss_wing_info ss_wing_info
struct generic_anim::@239::@241 ani
struct ss_slot_info ss_slot_info
void ss_set_team_pointers(int team)
color Color_green
Definition: alphacolors.cpp:31
briefing * Briefing
void ship_select_button_do(int i)
color Color_bright_white
Definition: alphacolors.cpp:32
#define WING_INDEX(wingp)
Definition: ship.h:1601
char alt_name[NAME_LENGTH]
Definition: ship.h:1164
int Wss_num_wings
int common_scroll_down_pressed(int *start, int size, int max_show)
void obj_delete(int objnum)
Definition: object.cpp:522
scroll pressed (and scroll)
Definition: gamesnd.h:296
color Color_white
Definition: alphacolors.cpp:32
color Icon_colors[NUM_ICON_FRAMES]
#define SHIP_SELECT_SHIP_SCROLL_DOWN
generic_anim ss_anim
void link_hotspot(int num)
Definition: gadget.cpp:50
char anim_filename[MAX_FILENAME_LEN]
Definition: ship.h:1340
#define strcat_s(...)
Definition: safe_strings.h:68
void create(UI_WINDOW *wnd, char *_text, int _x, int _y, int _w, int _h, int do_repeat=0, int ignore_focus=0)
Definition: button.cpp:26
#define NAME_LENGTH
Definition: globals.h:15
#define COMMON_COMMIT_REGION
int wep[MAX_SHIP_WEAPONS]
GLubyte GLubyte GLubyte GLubyte w
Definition: Glext.h:5679
void draw_model_rotating(model_render_params *render_info, int model_id, int x1, int y1, int x2, int y2, float *rotation_buffer, vec3d *closeup_pos, float closeup_zoom, float rev_rate, int flags, int resize_mode, int effect)
#define SHIP_SELECT_X_COORD
#define fl2i(fl)
Definition: floating.h:33
void ss_reset_selected_ship()
void create(int _x, int _y, int _w, int _h, int _flags, int _f_id=-1)
Definition: window.cpp:140
loadout_data Player_loadout
#define ICON_FRAME_HOT
player * Player
float Hud_speed_multiplier
Definition: hudparse.cpp:41
int Wing_slot_empty_bitmap
Definition: ui.h:584
void ss_init_wing_info(int wing_num, int starting_wing_num)
screen gr_screen
Definition: 2d.cpp:46
#define MULTI_SYNC_POST_BRIEFING
Definition: multiui.h:139
#define SF2_SHIP_LOCKED
Definition: ship.h:506
int Ss_mouse_down_on_region
void gr_get_string_size(int *w, int *h, const char *text, int len=9999)
Definition: font.cpp:196
void generic_anim_init(generic_anim *ga)
Definition: generic.cpp:80
void wl_get_default_weapons(int ship_class, int slot_num, int *wep, int *wep_count)
void ship_select_init_team_data(int team_num)
Definition: ui.h:162
ship animation starts (ie text and ship first appear)
Definition: gamesnd.h:298
void ss_unload_all_icons()
void ss_init_units()
int gr_get_font_height()
Definition: font.cpp:187
void ss_reset_to_default()
#define WING_SLOT_EMPTY
int ship_info_index
Definition: ship.h:539
GLfloat GLfloat p
Definition: Glext.h:8373
#define MULTIPLAYER_MASTER
Definition: multi.h:130
#define ICON_FRAME_PLAYER
char * missile_banks
Definition: ship.h:1179
#define COMMON_OPTIONS_REGION
#define WSS_SWAP_SLOT_SLOT
SCP_vector< ship_info > Ship_info
Definition: ship.cpp:164
#define LOCATION
Definition: pstypes.h:245
void common_play_highlight_sound()
Definition: gamesnd.cpp:1151
int max_h
Definition: 2d.h:360
float View_zoom
Definition: 3dsetup.cpp:30
#define SNAZZY_CLICKED
Definition: snazzyui.h:29
SCP_vector< species_info > Species_info
ptr_u data
Pointer to data, or maybe offset into VRAM.
Definition: bmpman.h:109
int * Ss_pool
ss_carry_icon_info Carried_ss_icon
BM_TYPE bm_get_type(int handle)
Returns the image type of the given bitmap handle.
Definition: bmpman.cpp:894
#define NUM_SS_BUTTONS
int ss_dump_to_list(int from_slot, int to_list, int *sound)
char * maneuverability_str
Definition: ship.h:1170
#define CF_MAX_FILENAME_LENGTH
Definition: cfile.h:39
#define WSS_SWAP_LIST_SLOT
void wl_remove_weps_from_pool(int *wep, int *wep_count, int ship_class)
#define WING_SLOT_IGNORE_SHIPS
color Color_normal
Definition: alphacolors.cpp:28
void drop_leading_white_space(char *str)
Definition: parselo.cpp:115
void change_ship_type(int n, int ship_type, int by_sexp)
Definition: ship.cpp:9983
#define MAX_TVT_TEAMS
Definition: globals.h:57
int n_guns
Definition: model.h:768
GLint GLsizei count
Definition: Gl.h:1491
void gr_bitmap(int _x, int _y, int resize_mode)
Definition: 2d.cpp:1303
void ss_make_slot_empty(int slot_index)
p_object Ship_arrival_list
void ss_load_icons(int ship_class)
#define UI_XSTR_COLOR_GREEN
Definition: ui.h:160
team_data Team_data[MAX_TVT_TEAMS]
object * Player_obj
Definition: object.cpp:56
int ship_index
Definition: multi.h:450
void ship_select_common_init()
void ss_drop(int from_slot, int from_list, int to_slot, int to_list, int player_index)
uint flags2
Definition: ship.h:645
int temp
Definition: lua.cpp:4996
int mission_ui_background_load(const char *custom_background, const char *single_background, const char *multi_background)
float Canv_w2
Definition: 3dsetup.cpp:39
int ship_index[MAX_SHIPS_PER_WING]
Definition: ship.h:1531
polymodel * pm
Definition: lua.cpp:1598
float closeup_zoom
Definition: ship.h:1328
#define WING_2_SHIP_2
float max_hull_strength
Definition: ship.h:1309
int icon_bmaps[NUM_ICON_FRAMES]
#define WING_1_SHIP_0
int ss_get_ship_class_from_list(int index)
void gamesnd_play_iface(int n)
Definition: gamesnd.cpp:260
mission The_mission
void ss_maybe_flash_button()
int multi_ts_disabled_high_slot(int slot_index, int player_index)
int Ship_select_open
void disable()
Definition: gadget.cpp:432
void draw()
Definition: window.cpp:220
#define COMMON_BRIEFING_REGION
#define WING_2_SHIP_3
#define WING_SLOT_DISABLED
#define SS_OVERLAY
Definition: contexthelp.h:21
void commit_pressed()
int Current_screen
vec3d max_vel
Definition: ship.h:1196
int common_flash_bright()
int multi_find_player_by_object(object *objp)
Definition: multiutil.cpp:500
#define wp(p)
Definition: modelsinc.h:69
void ss_recalc_multiplayer_slots()
int help_overlay_get_index(const char *overlay_name)
int generic_anim_stream(generic_anim *ga)
Definition: generic.cpp:159
float ShipSelectScreenShipRot
void draw_brackets_square(int x1, int y1, int x2, int y2, int resize_mode)
Definition: hudbrackets.cpp:49
net_player Net_players[MAX_PLAYERS]
Definition: multi.cpp:93
int Cmdline_nohtl
Definition: cmdline.cpp:438
int timer_get_milliseconds()
Definition: timer.cpp:150
void gameseq_post_event(int event)
GLenum GLint GLuint mask
Definition: Glext.h:5605
#define WING_0_SHIP_1
#define MR_NO_FOGGING
Definition: model.h:884
int num_ship_choices
Definition: missionparse.h:531
#define stricmp(s1, s2)
Definition: config.h:271
int Select_default_ship
drop a ship icon back to the list
Definition: gamesnd.h:290
void help_overlay_maybe_blit(int overlay_id, int resolution_index)
struct ss_carry_icon_info ss_carry_icon_info
int help_overlay_active(int overlay_id)
#define GR_1024
Definition: 2d.h:653
char ship_name[NAME_LENGTH]
Definition: ship.h:604
int selection_effect
Definition: ship.h:1342
#define SHIP_DESC_Y
ss_icon_info * Ss_icons
int Lcl_gr
Definition: localize.cpp:48
#define ICON_FRAME_NORMAL
char * gun_mounts
Definition: ship.h:1178
#define WSS_DUMP_TO_LIST
ss_slot_info ss_slots[MAX_WING_SLOTS]
void model_unload(int modelnum, int force=0)
Definition: modelread.cpp:162
GLint y
Definition: Gl.h:1505
int num_primary_banks
Definition: ship.h:1293
char last_modified[DATE_TIME_LENGTH]
bool is_weapon_carried(int weapon_index)
int Drop_icon_mflag
int ship_list[MAX_SHIP_CLASSES]
Definition: missionparse.h:533
int Player_num
#define strcpy_s(...)
Definition: safe_strings.h:67
#define WING_SLOT_WEAPONS_DISABLED
int ss_return_ship(int wing_block, int wing_slot, int *ship_index, p_object **ppobjp)
int ship_get_type(char *output, ship_info *sip)
Definition: ship.cpp:5464
UI_XSTR Ship_select_text[GR_NUM_RESOLUTIONS][SHIP_SELECT_NUM_TEXT]
#define MR_AUTOCENTER
Definition: model.h:875