2 * $Logfile: /Freespace2/code/MenuUI/Barracks.cpp $
7 * C file for implementing barracks section
10 * Revision 1.1 2002/05/03 03:28:09 root
14 * 42 10/25/99 5:47p Jefff
15 * reassigned some xstr ids
17 * 41 9/14/99 11:01p Jefff
18 * stats area coord fix
20 * 40 9/09/99 11:24a Jefff
22 * 39 9/02/99 11:26a Jefff
23 * fixed incorrect pilot list dimensions
25 * 38 8/17/99 2:24p Dave
26 * Fixed wacky squad color stuff.
28 * 37 8/16/99 4:27p Jefff
29 * fix button position on squad change error popup
31 * 36 8/11/99 3:58p Jefff
32 * fixed player list box coord bug
34 * 35 8/05/99 2:46p Jefff
35 * added popup to the disabled squad selection buttons in single player
37 * 34 8/02/99 11:02p Dave
38 * Fixed up squad filename and squad name copying when converting a pilot
39 * between single and multiplayer.
41 * 33 7/27/99 7:17p Jefff
42 * Replaced some art text with XSTR() text.
44 * 32 7/15/99 9:20a Andsager
45 * FS2_DEMO initial checkin
47 * 31 6/29/99 7:39p Dave
48 * Lots of small bug fixes.
50 * 30 6/16/99 4:06p Dave
51 * New pilot info popup. Added new draw-bitmap-as-poly function.
53 * 29 6/11/99 11:13a Dave
54 * last minute changes before press tour build.
56 * 28 4/25/99 7:43p Dave
57 * Misc small bug fixes. Made sun draw properly.
59 * 27 4/25/99 3:02p Dave
60 * Build defines for the E3 build.
62 * 26 3/24/99 4:05p Dave
63 * Put in support for assigning the player to a specific squadron with a
64 * specific logo. Preliminary work for doing pos/orient checksumming in
65 * multiplayer to reduce bandwidth.
67 * 25 2/25/99 4:19p Dave
68 * Added multiplayer_beta defines. Added cd_check define. Fixed a few
69 * release build warnings. Added more data to the squad war request and
72 * 24 2/02/99 12:09p Neilk
73 * Fixed text coords, centered pilot and squad pics in 1024x768, added vss
80 #include "managepilot.h"
87 #include "playermenu.h"
88 #include "gamesequence.h"
89 #include "contexthelp.h"
92 #include "freespace.h"
93 #include "systemvars.h"
96 #include "osregistry.h"
97 #include "alphacolors.h"
99 void delete_pilot_file( char *pilot_name, int single ); // manage_pilot.cpp
102 #define NUM_STAT_LINES 85
103 #define STAT_COLUMN1_W 40
104 #define STAT_COLUMN2_W 10
106 static int Stat_column1_w[GR_NUM_RESOLUTIONS] =
112 static int Stat_column2_w[GR_NUM_RESOLUTIONS] =
118 // constants for coordinate lookup
119 #define BARRACKS_X_COORD 0
120 #define BARRACKS_Y_COORD 1
121 #define BARRACKS_W_COORD 2
122 #define BARRACKS_H_COORD 3
126 // pilot selection field
127 static int Barracks_list_coords[GR_NUM_RESOLUTIONS][4] = {
137 static int Barracks_stats_coords[GR_NUM_RESOLUTIONS][4] = {
146 static int Barracks_stats2_coords[GR_NUM_RESOLUTIONS][3] = {
148 276, 212, 81 // X2, , W2
151 286, 351, 81 // X2, , W2
155 // pilot picture field
156 static int Barracks_image_coords[GR_NUM_RESOLUTIONS][4] = {
165 // pilot picture # of # location
166 static int Barracks_image_number_coords[GR_NUM_RESOLUTIONS][2] = {
175 // pilot squad logo field
176 int Barracks_squad_coords[GR_NUM_RESOLUTIONS][4] = {
185 // pilot squad # of # location
186 int Barracks_squad_number_coords[GR_NUM_RESOLUTIONS][2] = {
196 #define BARRACKS_NUM_BUTTONS 19
198 // pilot selection buttons
199 #define B_PILOT_CREATE_BOTTON 0 // B_PILOT_CREATE_BOTTON
200 #define B_PILOT_SCROLL_UP_BUTTON 1 // B_PILOT_SCROLL_UP_BUTTON
201 #define B_PILOT_SCROLL_DOWN_BUTTON 2 // B_PILOT_SCROLL_DOWN_BUTTON
202 #define B_PILOT_DELETE_BUTTON 11 // B_PILOT_B_PILOT_DELETE_BUTTON
203 #define B_PILOT_SET_ACTIVE_BUTTON 12 // B_PILOT_B_PILOT_SET_ACTIVE_BUTTON
204 #define B_PILOT_CLONE_BUTTON 13 // B_PILOT_B_PILOT_CLONE_BUTTON
205 #define B_PILOT_SINGLE_MODE_BUTTON 14 // B_PILOT_SINGLE_MODE_BUTTON
206 #define B_PILOT_MULTI_MODE_BUTTON 15 // B_PILOT_MULTI_MODE_BUTTON
207 #define B_PILOT_CONVERT_BUTTON 16 // B_PILOT_B_PILOT_CONVERT_BUTTON
209 // squad logo picture buttons
210 #define B_SQUAD_PREV_BUTTON 17
211 #define B_SQUAD_NEXT_BUTTON 18
213 // pilot picture buttons
214 #define B_PIC_PREV_PILOT_BUTTON 3 // B_PILOT_B_PIC_PREV_PILOT_BUTTON
215 #define B_PIC_NEXT_PILOT_BUTTON 4 // B_PILOT_B_PIC_NEXT_PILOT_BUTTON
217 // pilot stat buttons
218 #define B_STATS_MEDAL_BUTTON 8 // B_STATS_MEDAL_BUTTON
219 #define B_STATS_SCROLL_DOWN_BUTTON 9 // B_STATS_SCROLL_DOWN_BUTTON
220 #define B_STATS_SCROLL_UP_BUTTON 10 // B_STATS_SCROLL_UP_BUTTON
223 #define B_ACCEPT_BUTTON 5 // B_B_ACCEPT_BUTTON
224 #define B_HELP_BUTTON 6 // B_B_HELP_BUTTON
225 #define B_OPTION_BUTTON 7 // B_OPTION_BUTTON
229 static char *Barracks_bitmap_fname[GR_NUM_RESOLUTIONS] = {
230 "Barracks", // GR_640
231 "2_Barracks" // GR_1024
234 static char *Barracks_bitmap_mask_fname[GR_NUM_RESOLUTIONS] = {
235 "Barracks-M", // GR_640
236 "2_Barracks-M" // GR_1024
241 #define BARRACKS_IMAGE_NOT_LOADED -2
243 struct barracks_bitmaps {
249 struct barracks_buttons {
252 int text_x, text_y; // this is where the text label is
255 UI_BUTTON button; // because we have a class inside this struct, we need the constructor below..
257 barracks_buttons(char *name, int x1, int y1, int x2, int y2, int h, int r = 0) : filename(name), x(x1), y(y1), text_x(x2), text_y(y2), hotspot(h), repeat(r) {}
260 static int Background_bitmap = -1;
261 static UI_WINDOW Ui_window;
262 static UI_BUTTON List_region;
263 static UI_INPUTBOX Inputbox;
265 static barracks_buttons Buttons[GR_NUM_RESOLUTIONS][BARRACKS_NUM_BUTTONS] = {
268 barracks_buttons("BAB_00", 8, 122, 11, 157, 0),
269 barracks_buttons("BAB_01", 323, 130, 0, 0, 1, 1),
270 barracks_buttons("BAB_02", 350, 130, 0, 0, 2, 1),
271 barracks_buttons("BAB_03", 559, 143, 0, 0, 3, 1),
272 barracks_buttons("BAB_04", 598, 143, 0, 0, 4, 1),
273 barracks_buttons("BAB_05", 571, 425, 578, 413, 5),
274 barracks_buttons("BAB_06", 533, 425, 500, 438, 6),
275 barracks_buttons("BAB_07", 533, 453, 481, 465, 7),
276 barracks_buttons("BAB_08", 361, 425, 401, 465, 8),
277 barracks_buttons("BAB_09", 0, 267, 0, 0, 9, 1),
278 barracks_buttons("BAB_10", 0, 224, 0, 0, 10,1),
279 barracks_buttons("BAB_11", 120, 122, 123, 157, 11),
280 barracks_buttons("BAB_12", 376, 124, 378, 163, 12),
281 barracks_buttons("BAB_13", 66, 122, 69, 157, 13),
282 barracks_buttons("BAB_14", 323, 0, 324, 25, 14),
283 barracks_buttons("BAB_15", 372, 0, 374, 25, 15),
284 barracks_buttons("BAB_16", 180, 122, 182, 157, 16),
285 barracks_buttons("BAB_17", 559, 306, 0, 0, 17),
286 barracks_buttons("BAB_18", 598, 306, 0, 0, 18)
289 barracks_buttons("2_BAB_00", 14, 196, 35, 252, 0),
290 barracks_buttons("2_BAB_01", 518, 209, 0, 0, 1, 1),
291 barracks_buttons("2_BAB_02", 561, 209, 0, 0, 2, 1),
292 barracks_buttons("2_BAB_03", 896, 229, 0, 0, 3, 1),
293 barracks_buttons("2_BAB_04", 958, 229, 0, 0, 4, 1),
294 barracks_buttons("2_BAB_05", 914, 681, 932, 665, 5),
295 barracks_buttons("2_BAB_06", 854, 681, 800, 704, 6),
296 barracks_buttons("2_BAB_07", 854, 724, 778, 743, 7),
297 barracks_buttons("2_BAB_08", 579, 681, 641, 743, 8),
298 barracks_buttons("2_BAB_09", 0, 428, 0, 0, 9, 1),
299 barracks_buttons("2_BAB_10", 0, 360, 0, 0, 10,1),
300 barracks_buttons("2_BAB_11", 193, 196, 214, 252, 11),
301 barracks_buttons("2_BAB_12", 602, 200, 617, 262, 12),
302 barracks_buttons("2_BAB_13", 107, 196, 128, 252, 13),
303 barracks_buttons("2_BAB_14", 517, 0, 532, 40, 14),
304 barracks_buttons("2_BAB_15", 596, 0, 614, 40, 15),
305 barracks_buttons("2_BAB_16", 289, 196, 309, 252, 16),
306 barracks_buttons("2_BAB_17", 896, 491, 0, 0, 17),
307 barracks_buttons("2_BAB_18", 958, 491, 0, 0, 18)
313 // FIXME add to strings.tbl, set correct coords
314 #define BARRACKS_NUM_TEXT 2
315 UI_XSTR Barracks_text[GR_NUM_RESOLUTIONS][BARRACKS_NUM_TEXT] = {
318 { "Barracks", 1434, 17, 7, UI_XSTR_COLOR_GREEN, -1, NULL },
319 { "Pilot Stats", 1435, 17, 180, UI_XSTR_COLOR_GREEN, -1, NULL }
323 { "Barracks", 1434, 27, 11, UI_XSTR_COLOR_GREEN, -1, NULL },
324 { "Pilot Stats", 1435, 27, 288, UI_XSTR_COLOR_GREEN, -1, NULL }
329 static int Num_stat_lines;
330 static char Stat_labels[NUM_STAT_LINES][STAT_COLUMN1_W];
331 static char Stats[NUM_STAT_LINES][STAT_COLUMN2_W];
333 extern int Player_sel_mode;
335 static player *Cur_pilot;
336 static int Num_pilots;
337 static int Selected_line;
338 static char Pilots_arr[MAX_PILOTS][MAX_FILENAME_LEN];
339 static char *Pilots[MAX_PILOTS];
340 static int Pic_number;
341 static int Pic_squad_number;
342 static bool Barracks_callsign_enter_mode;
343 static int Pilot_ranks[MAX_PILOTS];
344 static int List_scroll_offset;
345 static int Stats_scroll_offset;
346 static int Clone_flag;
347 static int Pilot_images[MAX_PILOT_IMAGES];
348 static int Pilot_squad_images[MAX_PILOT_IMAGES];
349 static int Rank_pips_bitmaps;
350 static int Rank_pips_count;
352 void barracks_squad_change_popup();
355 // -------------------------------------------------------------------------------------------------
360 #define STRCPY1(a, b) do { \
361 Assert(strlen(b) < STAT_COLUMN1_W); \
365 void barracks_init_stats(scoring_struct *stats)
372 STRCPY1(Stat_labels[Num_stat_lines], XSTR( "*All Time Stats", 50));
373 Stats[Num_stat_lines][0] = 0;
376 Assert(Num_stat_lines < NUM_STAT_LINES);
377 Stat_labels[Num_stat_lines][0] = 0;
378 Stats[Num_stat_lines][0] = 0;
381 Assert(Num_stat_lines < NUM_STAT_LINES);
382 STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Primary weapon shots:", 51));
383 sprintf(Stats[Num_stat_lines], "%d", stats->p_shots_fired);
386 Assert(Num_stat_lines < NUM_STAT_LINES);
387 STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Primary weapon hits:", 52));
388 sprintf(Stats[Num_stat_lines], "%d", stats->p_shots_hit);
391 Assert(Num_stat_lines < NUM_STAT_LINES);
392 STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Primary friendly hits:", 53));
393 sprintf(Stats[Num_stat_lines], "%d", stats->p_bonehead_hits);
396 Assert(Num_stat_lines < NUM_STAT_LINES);
397 STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Primary hit %:", 54));
398 if (stats->p_shots_fired > 0) {
399 f = (float) stats->p_shots_hit * 100.0f / (float) stats->p_shots_fired;
403 sprintf(Stats[Num_stat_lines], XSTR( "%.1f%%", 55), f);
406 Assert(Num_stat_lines < NUM_STAT_LINES);
407 STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Primary friendly hit %:", 56));
408 if (stats->p_bonehead_hits > 0) {
409 f = (float) stats->p_bonehead_hits * 100.0f / (float) stats->p_shots_fired;
413 sprintf(Stats[Num_stat_lines], XSTR( "%.1f%%", 55), f);
416 Assert(Num_stat_lines < NUM_STAT_LINES);
417 Stat_labels[Num_stat_lines][0] = 0;
418 Stats[Num_stat_lines][0] = 0;
421 Assert(Num_stat_lines < NUM_STAT_LINES);
422 STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Secondary weapon shots:", 57));
423 sprintf(Stats[Num_stat_lines], "%d", stats->s_shots_fired);
426 Assert(Num_stat_lines < NUM_STAT_LINES);
427 STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Secondary weapon hits:", 58));
428 sprintf(Stats[Num_stat_lines], "%d", stats->s_shots_hit);
431 Assert(Num_stat_lines < NUM_STAT_LINES);
432 STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Secondary friendly hits:", 59));
433 sprintf(Stats[Num_stat_lines], "%d", stats->s_bonehead_hits);
436 Assert(Num_stat_lines < NUM_STAT_LINES);
437 STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Secondary hit %:", 60));
438 if (stats->s_shots_fired > 0) {
439 f = (float) stats->s_shots_hit * 100.0f / (float) stats->s_shots_fired;
443 sprintf(Stats[Num_stat_lines], XSTR( "%.1f%%", 55), f);
446 Assert(Num_stat_lines < NUM_STAT_LINES);
447 STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Secondary friendly hit %:", 61));
448 if (stats->s_bonehead_hits > 0) {
449 f = (float) stats->s_bonehead_hits * 100.0f / (float) stats->s_shots_fired;
453 sprintf(Stats[Num_stat_lines], XSTR( "%.1f%%", 55), f);
456 Assert(Num_stat_lines < NUM_STAT_LINES);
457 Stat_labels[Num_stat_lines][0] = 0;
458 Stats[Num_stat_lines][0] = 0;
461 Assert(Num_stat_lines < NUM_STAT_LINES);
462 STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Total kills:", 62));
463 sprintf(Stats[Num_stat_lines], "%d", stats->kill_count_ok);
466 Assert(Num_stat_lines < NUM_STAT_LINES);
467 STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Assists:", 63));
468 sprintf(Stats[Num_stat_lines], "%d", stats->assists);
471 Assert(Num_stat_lines < NUM_STAT_LINES);
472 Stat_labels[Num_stat_lines][0] = 0;
473 Stats[Num_stat_lines][0] = 0;
476 Assert(Num_stat_lines < NUM_STAT_LINES);
477 Stat_labels[Num_stat_lines][0] = 0;
478 Stats[Num_stat_lines][0] = 0;
481 STRCPY1(Stat_labels[Num_stat_lines], XSTR( "*Kills by Ship Type", 64));
482 Stats[Num_stat_lines][0] = 0;
485 Assert(Num_stat_lines < NUM_STAT_LINES);
486 Stat_labels[Num_stat_lines][0] = 0;
487 Stats[Num_stat_lines][0] = 0;
490 for (i=0; i<Num_ship_types; i++) {
491 if (stats->kills[i]) {
492 Assert(Num_stat_lines < NUM_STAT_LINES);
493 Assert(strlen(Ship_info[i].name) + 1 < STAT_COLUMN1_W);
494 sprintf(Stat_labels[Num_stat_lines], NOX("%s:"), Ship_info[i].name);
495 sprintf(Stats[Num_stat_lines], "%d", stats->kills[i]);
500 for (i=0; i<Num_stat_lines; i++) {
501 gr_force_fit_string(Stat_labels[i], Stat_column1_w[gr_screen.res], Barracks_stats_coords[gr_screen.res][BARRACKS_W_COORD]);
502 gr_force_fit_string(Stats[i], Stat_column2_w[gr_screen.res], Barracks_stats2_coords[gr_screen.res][BARRACKS_W_COORD]);
506 // sets or clears hotkeys for pilot selection.
507 void barracks_set_hotkeys(bool pilot_text_enter_mode)
509 Buttons[gr_screen.res][B_PILOT_SCROLL_UP_BUTTON].button.set_hotkey(pilot_text_enter_mode ? KEY_UP : -1);
510 Buttons[gr_screen.res][B_PILOT_SCROLL_DOWN_BUTTON].button.set_hotkey(pilot_text_enter_mode ? KEY_DOWN : -1);
512 Buttons[gr_screen.res][B_PILOT_CREATE_BOTTON].button.set_hotkey(pilot_text_enter_mode ? KEY_C : -1);
513 Buttons[gr_screen.res][B_PILOT_SET_ACTIVE_BUTTON].button.set_hotkey(pilot_text_enter_mode ? KEY_ENTER : -1);
514 Buttons[gr_screen.res][B_PILOT_DELETE_BUTTON].button.set_hotkey(pilot_text_enter_mode ? KEY_DELETE : -1);
516 Buttons[gr_screen.res][B_PIC_PREV_PILOT_BUTTON].button.set_hotkey(pilot_text_enter_mode ? KEY_LEFT : -1);
517 Buttons[gr_screen.res][B_PIC_NEXT_PILOT_BUTTON].button.set_hotkey(pilot_text_enter_mode ? KEY_RIGHT : -1);
519 Buttons[gr_screen.res][B_ACCEPT_BUTTON].button.set_hotkey(pilot_text_enter_mode ? KEY_CTRLED | KEY_ENTER : -1);
522 // strip the possible .pcx extension off a filename
523 void barracks_strip_pcx(char *str)
525 int flen = strlen(str);
527 if ((flen > 4) && !stricmp(str + flen - elen, ".pcx")) {
528 str[flen - elen] = '\0';
532 // new pilot name has focus, so update stats/pic to that pilot
533 int barracks_new_pilot_selected()
535 char stripped[MAX_FILENAME_LEN+1] = "";
537 // save the previous pilot first, so changes to it are kept
538 if (strlen(Cur_pilot->callsign)) {
542 // check if we have a valid pilot hilighted. If so, attempt to active it
543 if ((Num_pilots < 1) || (Selected_line < 0) || (Selected_line >= Num_pilots)) {
544 Cur_pilot->callsign[0] = 0; // this indicates no pilot active
548 if (read_pilot_file(Pilots[Selected_line], !Player_sel_mode, Cur_pilot)) {
549 Cur_pilot->callsign[0] = 0; // this indicates no pilot active
553 // init stuff to reflect new pilot
555 barracks_init_stats(&Cur_pilot->stats);
556 for (i=0; i<Num_pilot_images; i++) {
557 strcpy(stripped, Cur_pilot->image_filename);
558 barracks_strip_pcx(stripped);
559 if (!stricmp(stripped, Pilot_image_names[i])) {
564 for ( i=0; i<Num_pilot_squad_images; i++) {
565 strcpy(stripped, Cur_pilot->squad_filename);
566 barracks_strip_pcx(stripped);
567 if (!stricmp(stripped, Pilot_squad_image_names[i])) {
571 Pic_squad_number = i;
576 void barracks_set_callsign_enter_mode(bool set_callsign_enter_mode)
578 // set global mode variable
579 Barracks_callsign_enter_mode = set_callsign_enter_mode;
581 // disable/enable all buttons
582 for (int idx=0; idx<BARRACKS_NUM_BUTTONS; idx++) {
583 // don't ever mess with the prev and next squad logo buttons
584 if((idx != B_SQUAD_PREV_BUTTON) && (idx != B_SQUAD_NEXT_BUTTON)){
585 Buttons[gr_screen.res][idx].button.enable(!set_callsign_enter_mode);
589 // enable/disable hotkeys
590 barracks_set_hotkeys(!set_callsign_enter_mode);
591 // disable/enable inputbox
592 Inputbox.enable(set_callsign_enter_mode);
593 // hide/unhide inputbox
594 Inputbox.hide(!set_callsign_enter_mode);
597 // creates a new pilot file
598 void barracks_create_new_pilot()
600 // check if too many pilots
601 if (Num_pilots >= MAX_PILOTS) {
602 gamesnd_play_iface(SND_GENERAL_FAIL);
606 // play sound for pilot creation
607 gamesnd_play_iface(SND_SCROLL);
609 // only write pilot file if there is an active pilot
610 if (strlen(Player->callsign)) {
614 // move other pilot names and ranks down to make room for the new one
615 int idx = Num_pilots;
616 Assert(Num_pilots >= 0);
618 strcpy(Pilots[idx + 1], Pilots[idx]);
619 Pilot_ranks[idx + 1] = Pilot_ranks[idx];
624 Pilots[Selected_line][0] = 0;
625 Pilot_ranks[Selected_line] = 0;
626 List_scroll_offset = 0;
628 // set mode to accept pilot name text
629 barracks_set_callsign_enter_mode(true);
630 // set focus to input box
631 Inputbox.set_focus();
632 // set initial pilot name to ""
633 Inputbox.set_text("");
634 // reset size of input box to only 1 line
635 Inputbox.update_dimensions(Barracks_list_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_list_coords[gr_screen.res][BARRACKS_Y_COORD], Barracks_list_coords[gr_screen.res][BARRACKS_W_COORD], gr_get_font_height());
638 // exiting screen without canceling, so load in the new pilot selected here
639 int barracks_pilot_accepted()
641 char str[CALLSIGN_LEN + 1];
643 // check if pilot active. If not, don't allow accept.
644 if (!Cur_pilot->callsign[0]){
649 player_set_squad_bitmap(Cur_pilot, Cur_pilot->squad_filename);
651 // Skill_level = get_default_skill_level();
653 // MWA -- I think that we should be writing Cur_pilot here.
654 //write_pilot_file(!is_pilot_multi(Cur_pilot));
655 write_pilot_file( Cur_pilot );
657 // when we store the LastPlayer key, we have to mark it as being single or multiplayer, so we know where to look for him
658 // (since we could have a single and a multiplayer pilot with the same callsign)
659 // we'll distinguish them by putting an M and the end of the multiplayer callsign and a P at the end of a single player
660 strcpy(str, Cur_pilot->callsign);
661 strcat(str, is_pilot_multi(Cur_pilot) ? NOX("M") : NOX("S"));
662 os_config_write_string( NULL, "LastPlayer", str );
666 // scroll up barracks pilot list one line
667 void barracks_scroll_callsign_up()
669 if (Selected_line > 0) {
671 gamesnd_play_iface(SND_SCROLL);
673 gamesnd_play_iface(SND_GENERAL_FAIL);
676 if ((Selected_line >= 0) && (Selected_line < List_scroll_offset)) {
677 List_scroll_offset = Selected_line;
681 // scroll down barracks pilot list one line
682 void barracks_scroll_callsign_down()
684 if (Selected_line < Num_pilots - 1) {
686 gamesnd_play_iface(SND_SCROLL);
688 gamesnd_play_iface(SND_GENERAL_FAIL);
691 // num_pilots_to_fill_height is the number of pilots that can fit in given height
692 int num_pilots_to_fill_height = Barracks_list_coords[gr_screen.res][BARRACKS_H_COORD] / gr_get_font_height();
693 if (Selected_line >= List_scroll_offset + num_pilots_to_fill_height) {
694 List_scroll_offset++;
698 // scroll up barracks stats list one line
699 void barracks_scroll_stats_up()
701 if (Stats_scroll_offset > 0) {
702 Stats_scroll_offset--;
703 gamesnd_play_iface(SND_SCROLL);
705 gamesnd_play_iface(SND_GENERAL_FAIL);
709 // scroll down barracks stats list one line
710 void barracks_scroll_stats_down()
712 int font_height = gr_get_font_height();
714 if (Stats_scroll_offset + Barracks_stats_coords[gr_screen.res][BARRACKS_H_COORD] / font_height < Num_stat_lines) {
715 Stats_scroll_offset++;
716 gamesnd_play_iface(SND_SCROLL);
718 gamesnd_play_iface(SND_GENERAL_FAIL);
722 // show previous pilot pic
723 void barracks_prev_pic()
725 // check if no pilot images or no pilot selected
726 if ((Num_pilot_images == 0) || (Cur_pilot->callsign[0] == '\0')) {
727 gamesnd_play_iface(SND_GENERAL_FAIL);
731 // reset pilot pic number
733 if (Pic_number < 0) {
734 Pic_number = Num_pilot_images - 1;
737 // copy pilot pic filename into pilot struct
738 if ((Pic_number >= 0) && (Pic_number < Num_pilot_images)) {
739 strcpy(Cur_pilot->image_filename, Pilot_image_names[Pic_number]);
743 gamesnd_play_iface(SND_SCROLL);
746 // show next pilot pic
747 void barracks_next_pic()
749 // check if no pilot images or no pilot selected
750 if ((Num_pilot_images == 0) || (Cur_pilot->callsign[0] == '\0')) {
751 gamesnd_play_iface(SND_GENERAL_FAIL);
755 // reset pilot pic number
757 if (Pic_number >= Num_pilot_images){
761 // copy pilot pic filename into pilot struct
762 if ((Pic_number >= 0) && (Pic_number < Num_pilot_images)){
763 strcpy(Cur_pilot->image_filename, Pilot_image_names[Pic_number]);
767 gamesnd_play_iface(SND_SCROLL);
770 // show previous squad pic
771 void barracks_prev_squad_pic()
773 // check if no pilot images or no pilot selected
774 if ((Num_pilot_squad_images == 0) || (Cur_pilot->callsign[0] == '\0')) {
775 gamesnd_play_iface(SND_GENERAL_FAIL);
779 // reset pilot pic number
781 if (Pic_squad_number < 0) {
782 Pic_squad_number = Num_pilot_squad_images - 1;
785 // copy pilot pic filename into pilot struct
786 if ((Pic_squad_number >= 0) && (Pic_squad_number < Num_pilot_squad_images)) {
787 strcpy(Cur_pilot->squad_filename, Pilot_squad_image_names[Pic_squad_number]);
791 gamesnd_play_iface(SND_SCROLL);
794 // show next pilot pic
795 void barracks_next_squad_pic()
797 // check if no pilot images or no pilot selected
798 if ((Num_pilot_squad_images == 0) || (Cur_pilot->callsign[0] == '\0')) {
799 gamesnd_play_iface(SND_GENERAL_FAIL);
803 // reset pilot pic number
805 if (Pic_squad_number >= Num_pilot_squad_images){
806 Pic_squad_number = 0;
809 // copy pilot pic filename into pilot struct
810 if ((Pic_squad_number >= 0) && (Pic_squad_number < Num_pilot_squad_images)){
811 strcpy(Cur_pilot->squad_filename, Pilot_squad_image_names[Pic_squad_number]);
815 gamesnd_play_iface(SND_SCROLL);
818 void barracks_delete_pilot()
820 char buf[MAX_FILENAME_LEN];
824 gamesnd_play_iface(SND_GENERAL_FAIL);
828 int popup_rval = popup(PF_TITLE_BIG | PF_TITLE_RED, 2, POPUP_NO, POPUP_YES, XSTR( "Warning!\n\nAre you sure you wish to delete this pilot?", 65));
829 if (popup_rval != 1) {
833 if (!stricmp(Pilots[Selected_line], Cur_pilot->callsign)) {
837 strcpy(buf, Pilots[Selected_line]);
838 for (int i=Selected_line; i<Num_pilots-1; i++) {
839 strcpy(Pilots[i], Pilots[i + 1]);
840 Pilot_ranks[i] = Pilot_ranks[i + 1];
844 if (Selected_line >= Num_pilots) {
845 Selected_line = Num_pilots - 1;
849 if (Selected_line >= 0) {
850 barracks_new_pilot_selected();
852 Cur_pilot->callsign[0] = 0;
856 delete_pilot_file(buf, Player_sel_mode == PLAYER_SELECT_MODE_SINGLE ? 1 : 0);
857 gamesnd_play_iface(SND_USER_SELECT);
860 // Filter out pilots of wrong type (which shouldn't be in the directory we are checking, but just to be safe..)
861 int barracks_pilot_filter(char *filename)
865 r = verify_pilot_file(filename, Player_sel_mode == PLAYER_SELECT_MODE_SINGLE, &rank);
866 if (rank >= Rank_pips_count)
867 rank = Rank_pips_count - 1;
870 Pilot_ranks[Num_pilots++] = rank;
876 // callback handler for the squadon selection buttons when they are disabled (in single player)
877 void barracks_squad_change_popup()
880 popup( PF_USE_AFFIRMATIVE_ICON | PF_NO_NETWORKING, 1, POPUP_OK, XSTR("You cannot change your squadron in Single Player mode.", 1445));
884 void barracks_init_player_stuff(int mode)
886 // determine if we should be looking for single or multiplayers at the outset
887 Player_sel_mode = mode;
889 // get the list of pilots based upon whether we're in single or multiplayer mode
891 Get_file_list_filter = barracks_pilot_filter;
893 // single player specific stuff
894 if (mode == PLAYER_SELECT_MODE_SINGLE) {
895 Num_pilots = cf_get_file_list_preallocated(MAX_PILOTS, Pilots_arr, Pilots, CF_TYPE_SINGLE_PLAYERS, NOX("*.plr"), CF_SORT_TIME);
897 // disable squad logo switching
898 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.hide();
899 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.disable();
900 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.set_disabled_action(barracks_squad_change_popup);
901 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.hide();
902 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.disable();
903 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.set_disabled_action(barracks_squad_change_popup);
905 // multiplayer specific stuff
907 Num_pilots = cf_get_file_list_preallocated(MAX_PILOTS, Pilots_arr, Pilots, CF_TYPE_MULTI_PLAYERS, NOX("*.plr"), CF_SORT_TIME);
909 // enable squad logo switching
910 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.enable();
911 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.unhide();
912 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.enable();
913 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.unhide();
916 int ranks[MAX_PILOTS];
918 for (int i=0; i<Num_pilots; i++) {
920 for (j=0; j<Num_pilots; j++) {
921 if (!strcmp(Pilots[i], Pilots_arr[j])) {
922 ranks[i] = Pilot_ranks[j];
926 Assert(j < Num_pilots); // Pilot not found? How is that possible?
929 for (int i=0; i<Num_pilots; i++) {
930 Pilot_ranks[i] = ranks[i];
933 Selected_line = List_scroll_offset = 0;
934 barracks_new_pilot_selected();
938 void barracks_button_pressed(int n)
941 case B_PILOT_SCROLL_UP_BUTTON:
942 barracks_scroll_callsign_up();
945 case B_PILOT_SCROLL_DOWN_BUTTON:
946 barracks_scroll_callsign_down();
949 case B_STATS_SCROLL_UP_BUTTON:
950 barracks_scroll_stats_up();
953 case B_STATS_SCROLL_DOWN_BUTTON:
954 barracks_scroll_stats_down();
957 case B_PIC_PREV_PILOT_BUTTON:
961 case B_PIC_NEXT_PILOT_BUTTON:
965 case B_SQUAD_PREV_BUTTON:
966 barracks_prev_squad_pic();
969 case B_SQUAD_NEXT_BUTTON:
970 barracks_next_squad_pic();
973 case B_PILOT_SET_ACTIVE_BUTTON:
974 if (barracks_new_pilot_selected()){
975 gamesnd_play_iface(SND_GENERAL_FAIL);
977 // throw up a popup telling the player that he should create a pilot first
978 if(Player_sel_mode == PLAYER_SELECT_MODE_SINGLE){
979 popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR( "You must create a single player pilot.", 66));
981 popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR( "You must create a multi player pilot.", 67));
984 gamesnd_play_iface(SND_SCROLL);
988 case B_ACCEPT_BUTTON:
989 if (Num_pilots && !barracks_pilot_accepted()) {
990 gamesnd_play_iface(SND_COMMIT_PRESSED);
991 gameseq_post_event(GS_EVENT_MAIN_MENU);
993 gamesnd_play_iface(SND_GENERAL_FAIL);
995 // throw up a popup telling the player that he should create a pilot first
996 if(Player_sel_mode == PLAYER_SELECT_MODE_SINGLE){
997 popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR( "You must create a single player pilot.", 66));
999 popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR( "You must create a multi player pilot.", 67));
1004 case B_PILOT_CLONE_BUTTON:
1005 if (Num_pilots < 1) {
1006 gamesnd_play_error_beep();
1011 barracks_create_new_pilot();
1014 case B_PILOT_CONVERT_BUTTON: {
1015 #if defined(DEMO) || defined(OEM_BUILD)
1016 game_feature_not_in_demo_popup();
1018 char temp[256], *str;
1019 char old_pic[256] = "";
1020 char old_squad_pic[256] = "";
1021 char old_squad[256] = "";
1024 if (!barracks_new_pilot_selected()) {
1025 if (Player_sel_mode == PLAYER_SELECT_MODE_SINGLE)
1026 str = XSTR( "multiplayer", 68);
1028 str = XSTR( "single player", 69);
1030 sprintf(temp, XSTR( "This will overwrite your %s pilot. Proceed?", 70), str);
1031 if (!verify_pilot_file(Cur_pilot->callsign, Player_sel_mode == PLAYER_SELECT_MODE_MULTI)) {
1032 z = popup(0, 2, POPUP_CANCEL, POPUP_OK, temp);
1037 strcpy(old_pic, Cur_pilot->image_filename);
1038 strcpy(old_squad_pic, Cur_pilot->squad_filename);
1039 strcpy(old_squad, Cur_pilot->squad_name);
1040 init_new_pilot(Cur_pilot, 0);
1041 strcpy(Cur_pilot->image_filename, old_pic);
1042 strcpy(Cur_pilot->squad_filename, old_squad_pic);
1043 strcpy(Cur_pilot->squad_name, old_squad);
1044 if (Player_sel_mode == PLAYER_SELECT_MODE_SINGLE) {
1045 Cur_pilot->flags |= PLAYER_FLAGS_IS_MULTI;
1047 barracks_init_player_stuff(PLAYER_SELECT_MODE_MULTI);
1051 barracks_init_player_stuff(PLAYER_SELECT_MODE_SINGLE);
1054 gamesnd_play_iface(SND_USER_SELECT);
1057 gamesnd_play_iface(SND_GENERAL_FAIL);
1063 case B_PILOT_CREATE_BOTTON:
1065 barracks_create_new_pilot();
1069 launch_context_help();
1070 gamesnd_play_iface(SND_HELP_PRESSED);
1073 case B_OPTION_BUTTON:
1074 gamesnd_play_iface(SND_SWITCH_SCREENS);
1075 gameseq_post_event(GS_EVENT_OPTIONS_MENU);
1078 case B_STATS_MEDAL_BUTTON:
1080 game_feature_not_in_demo_popup();
1082 gamesnd_play_iface(SND_SWITCH_SCREENS);
1083 gameseq_post_event(GS_EVENT_VIEW_MEDALS);
1087 case B_PILOT_DELETE_BUTTON:
1088 barracks_delete_pilot();
1091 case B_PILOT_SINGLE_MODE_BUTTON:
1092 if (Player_sel_mode != PLAYER_SELECT_MODE_SINGLE) {
1093 gamesnd_play_iface(SND_USER_SELECT);
1094 barracks_init_player_stuff(PLAYER_SELECT_MODE_SINGLE);
1098 case B_PILOT_MULTI_MODE_BUTTON:
1099 #if defined(DEMO) || defined(OEM_BUILD) // not for FS2_DEMO
1100 game_feature_not_in_demo_popup();
1102 if (Player_sel_mode != PLAYER_SELECT_MODE_MULTI) {
1103 gamesnd_play_iface(SND_USER_SELECT);
1104 barracks_init_player_stuff(PLAYER_SELECT_MODE_MULTI);
1112 void barracks_display_pilot_callsigns(int prospective_pilot)
1115 int cur_pilot_idx = List_scroll_offset;
1118 if (Player_sel_mode == PLAYER_SELECT_MODE_MULTI) {
1122 int font_height = gr_get_font_height();
1123 while (y + font_height <= Barracks_list_coords[gr_screen.res][BARRACKS_H_COORD]) {
1124 if (cur_pilot_idx >= Num_pilots)
1127 if (!stricmp(Cur_pilot->callsign, Pilots[cur_pilot_idx]) && (is_pilot_multi(Cur_pilot) == multi)) {
1128 if ((cur_pilot_idx == Selected_line) || (cur_pilot_idx == prospective_pilot)) {
1129 gr_set_color_fast(&Color_text_active_hi);
1131 gr_set_color_fast(&Color_text_active);
1134 if (cur_pilot_idx == Selected_line) {
1135 gr_set_color_fast(&Color_text_selected);
1136 } else if (cur_pilot_idx == prospective_pilot) {
1137 gr_set_color_fast(&Color_text_subselected);
1139 gr_set_color_fast(&Color_text_normal);
1143 gr_printf(Barracks_list_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_list_coords[gr_screen.res][BARRACKS_Y_COORD] + y, Pilots[cur_pilot_idx]);
1144 gr_set_bitmap(Rank_pips_bitmaps + Pilot_ranks[cur_pilot_idx]);
1145 gr_bitmap(Barracks_list_coords[gr_screen.res][BARRACKS_X_COORD] - 34, Barracks_list_coords[gr_screen.res][BARRACKS_Y_COORD] + y);
1154 void barracks_display_pilot_stats()
1157 int z = Stats_scroll_offset;
1158 int font_height = gr_get_font_height();
1161 while (y + font_height <= Barracks_stats_coords[gr_screen.res][BARRACKS_H_COORD]) {
1162 if (z >= Num_stat_lines) {
1166 str = Stat_labels[z];
1168 gr_set_color_fast(&Color_text_heading);
1171 gr_get_string_size(&w, &h, str);
1172 i = Barracks_stats_coords[gr_screen.res][BARRACKS_Y_COORD] + y + h / 2 - 1;
1173 gr_line(Barracks_stats_coords[gr_screen.res][BARRACKS_X_COORD], i, Barracks_stats_coords[gr_screen.res][BARRACKS_X_COORD] + Barracks_stats_coords[gr_screen.res][BARRACKS_W_COORD] - w - 2, i);
1174 gr_line(Barracks_stats_coords[gr_screen.res][BARRACKS_X_COORD] + Barracks_stats_coords[gr_screen.res][BARRACKS_W_COORD] + 1, i, Barracks_stats2_coords[gr_screen.res][BARRACKS_X_COORD] + Barracks_stats2_coords[gr_screen.res][BARRACKS_W_COORD], i);
1177 gr_set_color_fast(&Color_text_normal);
1180 gr_get_string_size(&w, NULL, str);
1181 gr_printf(Barracks_stats_coords[gr_screen.res][BARRACKS_X_COORD] + Barracks_stats_coords[gr_screen.res][BARRACKS_W_COORD] - w, Barracks_stats_coords[gr_screen.res][BARRACKS_Y_COORD] + y, "%s", str);
1184 gr_printf(Barracks_stats2_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_stats_coords[gr_screen.res][BARRACKS_Y_COORD] + y, "%s", str);
1193 // process pilot callsign
1194 void barracks_accept_new_pilot_callsign()
1196 char buf[CALLSIGN_LEN + 1];
1197 char name[MAX_FILENAME_LEN];
1201 Inputbox.get_text(buf);
1202 drop_white_space(buf);
1204 if (!isalpha(*buf)) {
1207 for (i=1; buf[i]; i++) {
1208 if (!isalpha(buf[i]) && !isdigit(buf[i]) && !strchr(VALID_PILOT_CHARS, buf[i])) {
1215 for (i=1; i<Num_pilots; i++) {
1216 if (!stricmp(buf, Pilots[i])) {
1218 if (pilot_verify_overwrite() == 1) {
1219 strcpy(name, Pilots[Selected_line]);
1220 for (z=i; z<Num_pilots-1; z++) {
1221 strcpy(Pilots[z], Pilots[z + 1]);
1222 Pilot_ranks[z] = Pilot_ranks[z + 1];
1226 delete_pilot_file(name, Player_sel_mode == PLAYER_SELECT_MODE_SINGLE ? 1 : 0);
1233 if (!*buf || (i < Num_pilots)) { // duplicate name, alert user
1238 gamesnd_play_iface(SND_GENERAL_FAIL);
1242 strcpy(Pilots[0], buf);
1243 strcpy(Cur_pilot->callsign, buf);
1244 init_new_pilot(Cur_pilot, !Clone_flag);
1246 // again, make sure we set his flags correctly to ensure that he gets saved to the proper directory and gets
1247 // displayed correctly
1248 if (Player_sel_mode == PLAYER_SELECT_MODE_SINGLE) {
1249 Cur_pilot->flags &= ~(PLAYER_FLAGS_IS_MULTI);
1251 Cur_pilot->flags |= PLAYER_FLAGS_IS_MULTI;
1252 Cur_pilot->stats.flags |= STATS_FLAG_MULTIPLAYER;
1255 if ( !(Game_mode & GM_STANDALONE_SERVER) ) {
1256 write_pilot_file(Cur_pilot);
1260 barracks_new_pilot_selected();
1261 barracks_set_callsign_enter_mode(false);
1265 // draw pilot image and clean up afterwards
1266 void barracks_draw_pilot_pic()
1269 if (Cur_pilot->callsign[0] && (Pic_number >= 0) && (Pic_number < Num_pilot_images)) {
1270 if (Pilot_images[Pic_number] >= 0) {
1271 // JAS: This code is hacked to allow the animation to use all 256 colors
1272 extern int Palman_allow_any_color;
1273 Palman_allow_any_color = 1;
1274 gr_set_bitmap(Pilot_images[Pic_number]);
1275 gr_bitmap(Barracks_image_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_image_coords[gr_screen.res][BARRACKS_Y_COORD]);
1276 Palman_allow_any_color = 0;
1278 // print number of the current pic
1280 sprintf(buf, XSTR( "%d of %d", 71), Pic_number + 1, Num_pilot_images);
1281 gr_printf(Barracks_image_number_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_image_number_coords[gr_screen.res][BARRACKS_Y_COORD], buf);
1288 // draw squad image and clean up afterwards
1289 void barracks_draw_squad_pic()
1294 if (Cur_pilot->callsign[0] && (Pic_squad_number >= 0) && (Pic_squad_number < Num_pilot_squad_images)) {
1295 if (Pilot_squad_images[Pic_squad_number] >= 0) {
1296 // JAS: This code is hacked to allow the animation to use all 256 colors
1297 extern int Palman_allow_any_color;
1298 Palman_allow_any_color = 1;
1299 gr_set_bitmap(Pilot_squad_images[Pic_squad_number]);
1300 gr_bitmap(Barracks_squad_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_squad_coords[gr_screen.res][BARRACKS_Y_COORD]);
1301 Palman_allow_any_color = 0;
1303 // print number of current squad pic
1304 if(Player_sel_mode != PLAYER_SELECT_MODE_SINGLE){
1305 sprintf(buf,XSTR( "%d of %d", 71), Pic_squad_number+1, Num_pilot_squad_images);
1306 gr_printf(Barracks_squad_number_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_squad_number_coords[gr_screen.res][BARRACKS_Y_COORD], buf);
1310 Pic_squad_number = -1;
1314 // -----------------------------------------------------------------------------
1315 void barracks_init()
1317 UI_WINDOW *w = &Ui_window;
1319 // save current pilot file, so we don't possibly loose it.
1323 Ui_window.create(0, 0, gr_screen.max_w, gr_screen.max_h, 0);
1324 Ui_window.set_mask_bmap(Barracks_bitmap_mask_fname[gr_screen.res]);
1326 // load background bitmap
1327 Background_bitmap = bm_load(Barracks_bitmap_fname[gr_screen.res]);
1328 if(Background_bitmap < 0){
1329 // we failed to load the bitmap - this is very bad
1334 for (int i=0; i<BARRACKS_NUM_BUTTONS; i++) {
1335 // create the object
1336 Buttons[gr_screen.res][i].button.create(&Ui_window, "", Buttons[gr_screen.res][i].x, Buttons[gr_screen.res][i].y, 60, 30, Buttons[gr_screen.res][i].repeat, 1);
1338 // set the sound to play when highlighted
1339 Buttons[gr_screen.res][i].button.set_highlight_action(common_play_highlight_sound);
1341 // set the ani for the button
1342 Buttons[gr_screen.res][i].button.set_bmaps(Buttons[gr_screen.res][i].filename);
1345 Buttons[gr_screen.res][i].button.link_hotspot(Buttons[gr_screen.res][i].hotspot);
1349 w->add_XSTR("Create", 1034, Buttons[gr_screen.res][0].text_x, Buttons[gr_screen.res][0].text_y, &Buttons[gr_screen.res][0].button, UI_XSTR_COLOR_GREEN);
1350 w->add_XSTR("Accept", 1035, Buttons[gr_screen.res][5].text_x, Buttons[gr_screen.res][5].text_y, &Buttons[gr_screen.res][5].button, UI_XSTR_COLOR_PINK);
1351 w->add_XSTR("Help", 928, Buttons[gr_screen.res][6].text_x, Buttons[gr_screen.res][6].text_y, &Buttons[gr_screen.res][6].button, UI_XSTR_COLOR_GREEN);
1352 w->add_XSTR("Options",1036, Buttons[gr_screen.res][7].text_x, Buttons[gr_screen.res][7].text_y, &Buttons[gr_screen.res][7].button, UI_XSTR_COLOR_GREEN);
1353 w->add_XSTR("Medals", 1037, Buttons[gr_screen.res][8].text_x, Buttons[gr_screen.res][8].text_y, &Buttons[gr_screen.res][8].button, UI_XSTR_COLOR_GREEN);
1354 w->add_XSTR("Remove", 1038, Buttons[gr_screen.res][11].text_x, Buttons[gr_screen.res][11].text_y, &Buttons[gr_screen.res][11].button, UI_XSTR_COLOR_GREEN);
1355 w->add_XSTR("Select", 1552, Buttons[gr_screen.res][12].text_x, Buttons[gr_screen.res][12].text_y, &Buttons[gr_screen.res][12].button, UI_XSTR_COLOR_GREEN);
1356 w->add_XSTR("Clone", 1040, Buttons[gr_screen.res][13].text_x, Buttons[gr_screen.res][13].text_y, &Buttons[gr_screen.res][13].button, UI_XSTR_COLOR_GREEN);
1357 w->add_XSTR("Single", 1041, Buttons[gr_screen.res][14].text_x, Buttons[gr_screen.res][14].text_y, &Buttons[gr_screen.res][14].button, UI_XSTR_COLOR_GREEN);
1358 w->add_XSTR("Multi", 1042, Buttons[gr_screen.res][15].text_x, Buttons[gr_screen.res][15].text_y, &Buttons[gr_screen.res][15].button, UI_XSTR_COLOR_GREEN);
1359 w->add_XSTR("Convert",1043, Buttons[gr_screen.res][16].text_x, Buttons[gr_screen.res][16].text_y, &Buttons[gr_screen.res][16].button, UI_XSTR_COLOR_GREEN);
1360 for(int i=0; i<BARRACKS_NUM_TEXT; i++) {
1361 w->add_XSTR(&Barracks_text[gr_screen.res][i]);
1364 // button for selecting pilot
1365 List_region.create(&Ui_window, "", Barracks_list_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_list_coords[gr_screen.res][BARRACKS_Y_COORD], Barracks_list_coords[gr_screen.res][BARRACKS_W_COORD], Barracks_list_coords[gr_screen.res][BARRACKS_H_COORD], 0, 1);
1368 // create input box (for new pilot)
1369 Inputbox.create(&Ui_window, Barracks_list_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_list_coords[gr_screen.res][BARRACKS_Y_COORD], Barracks_list_coords[gr_screen.res][BARRACKS_W_COORD], CALLSIGN_LEN - 1, "", UI_INPUTBOX_FLAG_INVIS | UI_INPUTBOX_FLAG_KEYTHRU | UI_INPUTBOX_FLAG_LETTER_FIRST);
1370 Inputbox.set_valid_chars(VALID_PILOT_CHARS);
1374 // load in help overlay bitmap
1375 help_overlay_load(BARRACKS_OVERLAY);
1376 help_overlay_set_state(BARRACKS_OVERLAY,0);
1379 Barracks_callsign_enter_mode = 0;
1380 List_scroll_offset = Stats_scroll_offset = Pic_number = Pic_squad_number = Selected_line = 0;
1381 Cur_pilot = &Players[Player_num];
1383 // disable squad logo selection buttons in single player
1384 if(!(Cur_pilot->flags & PLAYER_FLAGS_IS_MULTI)){
1385 // squad logo picture buttons
1386 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.hide();
1387 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.disable();
1388 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.hide();
1389 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.disable();
1391 // squad logo picture buttons
1392 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.enable();
1393 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.unhide();
1394 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.enable();
1395 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.unhide();
1398 // set up hotkeys for buttons so we draw the correct animation frame when a key is pressed
1399 barracks_set_hotkeys(1);
1402 Rank_pips_bitmaps = bm_load_animation("IconRankMini.ani", &Rank_pips_count);
1404 // load up the pilot pic list
1405 pilot_load_pic_list();
1406 pilot_load_squad_pic_list();
1408 // don't load pilot images yet
1409 for (int i=0; i<MAX_PILOT_IMAGES; i++) {
1410 Pilot_images[i] = BARRACKS_IMAGE_NOT_LOADED; // while -1 is can't load
1411 Pilot_squad_images[i] = BARRACKS_IMAGE_NOT_LOADED;
1415 barracks_init_stats(&Cur_pilot->stats);
1417 // disable some buttons for the multiplayer beta and e3 build
1418 #if defined(MULTIPLAYER_BETA_BUILD) || defined(E3_BUILD) || defined(PRESS_TOUR_BUILD)
1419 Buttons[gr_screen.res][B_PILOT_CLONE_BUTTON].button.hide();
1420 Buttons[gr_screen.res][B_PILOT_CONVERT_BUTTON].button.hide();
1421 Buttons[gr_screen.res][B_PILOT_CLONE_BUTTON].button.disable();
1422 Buttons[gr_screen.res][B_PILOT_CONVERT_BUTTON].button.disable();
1425 // multiplayer beta build
1426 #ifdef MULTIPLAYER_BETA_BUILD
1427 Buttons[gr_screen.res][B_PILOT_SINGLE_MODE_BUTTON].button.hide();
1428 Buttons[gr_screen.res][B_PILOT_SINGLE_MODE_BUTTON].button.disable();
1432 #if defined(E3_BUILD) || defined(PRESS_TOUR_BUILD)
1433 Buttons[gr_screen.res][B_PILOT_MULTI_MODE_BUTTON].button.hide();
1434 Buttons[gr_screen.res][B_PILOT_MULTI_MODE_BUTTON].button.disable();
1437 // base the mode we're in (single or multi) on the status of the currently selected pilot
1438 #ifdef MULTIPLAYER_BETA_BUILD
1439 barracks_init_player_stuff(1);
1440 #elif defined(E3_BUILD) || defined(PRESS_TOUR_BUILD)
1441 barracks_init_player_stuff(0);
1443 barracks_init_player_stuff(is_pilot_multi(Player));
1447 // -----------------------------------------------------------------------------
1448 void barracks_do_frame(float frametime)
1450 int k = Ui_window.process();
1453 if ( help_overlay_active(BARRACKS_OVERLAY) ) {
1454 help_overlay_set_state(BARRACKS_OVERLAY,0);
1459 // pilot that mouse is over
1460 int prospective_pilot = -1;
1463 // Entering pilot callsign
1464 if (Barracks_callsign_enter_mode) {
1465 // set focus to inputbox
1466 Inputbox.set_focus();
1470 // cancel create pilot
1472 for (i=0; i<Num_pilots; i++) {
1473 strcpy(Pilots[i], Pilots[i + 1]);
1474 Pilot_ranks[i] = Pilot_ranks[i + 1];
1477 barracks_set_callsign_enter_mode(false);
1481 barracks_accept_new_pilot_callsign();
1485 // not entering pilot callsign
1488 if (barracks_new_pilot_selected()) {
1489 gamesnd_play_iface(SND_GENERAL_FAIL);
1491 gamesnd_play_iface(SND_USER_SELECT);
1495 case KEY_ESC: // cancel
1496 if (!help_overlay_active(BARRACKS_OVERLAY)) {
1497 if (Num_pilots && !barracks_pilot_accepted()) {
1498 gameseq_post_event(GS_EVENT_MAIN_MENU);
1500 gamesnd_play_iface(SND_GENERAL_FAIL);
1504 help_overlay_set_state(BARRACKS_OVERLAY,0);
1508 case KEY_TAB: // switch mode (simgle/multi)
1509 #if defined(DEMO) || defined(OEM_BUILD) // not for FS2_DEMO
1510 game_feature_not_in_demo_popup();
1512 if (Player_sel_mode == PLAYER_SELECT_MODE_SINGLE) {
1513 barracks_init_player_stuff(PLAYER_SELECT_MODE_MULTI);
1515 barracks_init_player_stuff(PLAYER_SELECT_MODE_SINGLE);
1518 gamesnd_play_iface(SND_USER_SELECT);
1522 case KEY_F1: // show help overlay
1523 gamesnd_play_iface(SND_HELP_PRESSED);
1526 case KEY_F2: // goto options screen
1527 gamesnd_play_iface(SND_SWITCH_SCREENS);
1528 gameseq_post_event(GS_EVENT_OPTIONS_MENU);
1533 for (i=0; i<BARRACKS_NUM_BUTTONS; i++) {
1534 if (Buttons[gr_screen.res][i].button.pressed()) {
1535 barracks_button_pressed(i);
1539 // if mouse is over a pilot, find index into Pilots array
1540 if (List_region.is_mouse_on()) {
1542 List_region.get_mouse_pos(NULL, &y);
1543 int pilot_index = List_scroll_offset + (y / gr_get_font_height());
1544 if ((pilot_index >= 0) && (pilot_index < Num_pilots)) {
1545 prospective_pilot = pilot_index;
1549 // if mouse clicked in list region, find index into Pilots array
1550 if (List_region.pressed()) {
1551 if (prospective_pilot != -1) {
1552 Selected_line = prospective_pilot;
1553 gamesnd_play_iface(SND_USER_SELECT);
1558 // check mouse over help
1559 if (mouse_down(MOUSE_LEFT_BUTTON)) {
1560 help_overlay_set_state(BARRACKS_OVERLAY, 0);
1563 // do pilot pic stuff
1564 if ((Pic_number >= 0) && (Pic_number < Num_pilot_images)) {
1565 if (Pilot_images[Pic_number] == BARRACKS_IMAGE_NOT_LOADED) { // haven't tried loading it yet
1566 Pilot_images[Pic_number] = bm_load(Pilot_image_names[Pic_number]);
1567 if (Pilot_images[Pic_number] >= 0) {
1570 bm_get_info(Pilot_images[Pic_number], &w, &h, NULL);
1571 // check for invalid pilot pic file
1572 if ((w != PLAYER_PILOT_PIC_W) || (h != PLAYER_PILOT_PIC_H)) {
1573 bm_unload(Pilot_images[Pic_number]);
1574 Pilot_images[Pic_number] = -1;
1582 // do squad pic stuff
1583 if ((Pic_squad_number >= 0) && (Pic_squad_number < Num_pilot_squad_images)) {
1584 if (Pilot_squad_images[Pic_squad_number] == BARRACKS_IMAGE_NOT_LOADED) { // haven't tried loading it yet
1585 Pilot_squad_images[Pic_squad_number] = bm_load_duplicate(Pilot_squad_image_names[Pic_squad_number]);
1586 if (Pilot_squad_images[Pic_squad_number] >= 0) {
1589 bm_get_info(Pilot_squad_images[Pic_squad_number], &w, &h, NULL);
1590 // check for invalid pilot pic file
1591 if ((w != PLAYER_SQUAD_PIC_W) || (h != PLAYER_SQUAD_PIC_H)) {
1592 bm_unload(Pilot_squad_images[Pic_squad_number]);
1593 Pilot_squad_images[Pic_squad_number] = -1;
1598 Pic_squad_number = -1;
1601 // draw the background, etc
1603 GR_MAYBE_CLEAR_RES(Background_bitmap);
1604 if (Background_bitmap >= 0) {
1605 gr_set_bitmap(Background_bitmap);
1609 // draw pilot image and clean up afterwards
1610 barracks_draw_pilot_pic();
1611 barracks_draw_squad_pic();
1616 // light up the correct mode button (single or multi)
1617 if (Player_sel_mode == PLAYER_SELECT_MODE_SINGLE) {
1618 Buttons[gr_screen.res][B_PILOT_SINGLE_MODE_BUTTON].button.draw_forced(2);
1620 Buttons[gr_screen.res][B_PILOT_MULTI_MODE_BUTTON].button.draw_forced(2);
1623 // write out pilot call signs
1624 barracks_display_pilot_callsigns(prospective_pilot);
1626 // write out current pilot stats
1627 barracks_display_pilot_stats();
1629 // blit help overlay if active
1630 help_overlay_maybe_blit(BARRACKS_OVERLAY);
1636 // -----------------------------------------------------------------------------
1637 void barracks_close()
1640 Ui_window.destroy();
1642 // release background bitmap
1643 if (Background_bitmap >= 0) {
1644 bm_unload(Background_bitmap);
1647 // release rank pip bitmaps
1648 for (int i=0; i<Rank_pips_count; i++) {
1649 bm_release(Rank_pips_bitmaps + i);
1652 // release pilot pic bitmaps
1653 for (int i=0; i<Num_pilot_images; i++) {
1654 if (Pilot_images[i] >= 0) {
1655 bm_unload(Pilot_images[i]);
1659 // unload the overlay bitmap
1660 help_overlay_unload(BARRACKS_OVERLAY);