2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
4 * All source code herein is the property of Volition, Inc. You may not sell
5 * or otherwise commercially exploit the source or things you created based on
10 * $Logfile: /Freespace2/code/MenuUI/Barracks.cpp $
15 * C file for implementing barracks section
18 * Revision 1.3 2002/06/09 04:41:22 relnev
19 * added copyright header
21 * Revision 1.2 2002/05/07 03:16:46 theoddone33
22 * The Great Newline Fix
24 * Revision 1.1.1.1 2002/05/03 03:28:09 root
28 * 42 10/25/99 5:47p Jefff
29 * reassigned some xstr ids
31 * 41 9/14/99 11:01p Jefff
32 * stats area coord fix
34 * 40 9/09/99 11:24a Jefff
36 * 39 9/02/99 11:26a Jefff
37 * fixed incorrect pilot list dimensions
39 * 38 8/17/99 2:24p Dave
40 * Fixed wacky squad color stuff.
42 * 37 8/16/99 4:27p Jefff
43 * fix button position on squad change error popup
45 * 36 8/11/99 3:58p Jefff
46 * fixed player list box coord bug
48 * 35 8/05/99 2:46p Jefff
49 * added popup to the disabled squad selection buttons in single player
51 * 34 8/02/99 11:02p Dave
52 * Fixed up squad filename and squad name copying when converting a pilot
53 * between single and multiplayer.
55 * 33 7/27/99 7:17p Jefff
56 * Replaced some art text with XSTR() text.
58 * 32 7/15/99 9:20a Andsager
59 * FS2_DEMO initial checkin
61 * 31 6/29/99 7:39p Dave
62 * Lots of small bug fixes.
64 * 30 6/16/99 4:06p Dave
65 * New pilot info popup. Added new draw-bitmap-as-poly function.
67 * 29 6/11/99 11:13a Dave
68 * last minute changes before press tour build.
70 * 28 4/25/99 7:43p Dave
71 * Misc small bug fixes. Made sun draw properly.
73 * 27 4/25/99 3:02p Dave
74 * Build defines for the E3 build.
76 * 26 3/24/99 4:05p Dave
77 * Put in support for assigning the player to a specific squadron with a
78 * specific logo. Preliminary work for doing pos/orient checksumming in
79 * multiplayer to reduce bandwidth.
81 * 25 2/25/99 4:19p Dave
82 * Added multiplayer_beta defines. Added cd_check define. Fixed a few
83 * release build warnings. Added more data to the squad war request and
86 * 24 2/02/99 12:09p Neilk
87 * Fixed text coords, centered pilot and squad pics in 1024x768, added vss
94 #include "managepilot.h"
101 #include "playermenu.h"
102 #include "gamesequence.h"
103 #include "contexthelp.h"
106 #include "freespace.h"
107 #include "systemvars.h"
110 #include "osregistry.h"
111 #include "alphacolors.h"
113 void delete_pilot_file( char *pilot_name, int single ); // manage_pilot.cpp
116 #define NUM_STAT_LINES 85
117 #define STAT_COLUMN1_W 40
118 #define STAT_COLUMN2_W 10
120 static int Stat_column1_w[GR_NUM_RESOLUTIONS] =
126 static int Stat_column2_w[GR_NUM_RESOLUTIONS] =
132 // constants for coordinate lookup
133 #define BARRACKS_X_COORD 0
134 #define BARRACKS_Y_COORD 1
135 #define BARRACKS_W_COORD 2
136 #define BARRACKS_H_COORD 3
140 // pilot selection field
141 static int Barracks_list_coords[GR_NUM_RESOLUTIONS][4] = {
151 static int Barracks_stats_coords[GR_NUM_RESOLUTIONS][4] = {
160 static int Barracks_stats2_coords[GR_NUM_RESOLUTIONS][3] = {
162 276, 212, 81 // X2, , W2
165 286, 351, 81 // X2, , W2
169 // pilot picture field
170 static int Barracks_image_coords[GR_NUM_RESOLUTIONS][4] = {
179 // pilot picture # of # location
180 static int Barracks_image_number_coords[GR_NUM_RESOLUTIONS][2] = {
189 // pilot squad logo field
190 int Barracks_squad_coords[GR_NUM_RESOLUTIONS][4] = {
199 // pilot squad # of # location
200 int Barracks_squad_number_coords[GR_NUM_RESOLUTIONS][2] = {
210 #define BARRACKS_NUM_BUTTONS 19
212 // pilot selection buttons
213 #define B_PILOT_CREATE_BOTTON 0 // B_PILOT_CREATE_BOTTON
214 #define B_PILOT_SCROLL_UP_BUTTON 1 // B_PILOT_SCROLL_UP_BUTTON
215 #define B_PILOT_SCROLL_DOWN_BUTTON 2 // B_PILOT_SCROLL_DOWN_BUTTON
216 #define B_PILOT_DELETE_BUTTON 11 // B_PILOT_B_PILOT_DELETE_BUTTON
217 #define B_PILOT_SET_ACTIVE_BUTTON 12 // B_PILOT_B_PILOT_SET_ACTIVE_BUTTON
218 #define B_PILOT_CLONE_BUTTON 13 // B_PILOT_B_PILOT_CLONE_BUTTON
219 #define B_PILOT_SINGLE_MODE_BUTTON 14 // B_PILOT_SINGLE_MODE_BUTTON
220 #define B_PILOT_MULTI_MODE_BUTTON 15 // B_PILOT_MULTI_MODE_BUTTON
221 #define B_PILOT_CONVERT_BUTTON 16 // B_PILOT_B_PILOT_CONVERT_BUTTON
223 // squad logo picture buttons
224 #define B_SQUAD_PREV_BUTTON 17
225 #define B_SQUAD_NEXT_BUTTON 18
227 // pilot picture buttons
228 #define B_PIC_PREV_PILOT_BUTTON 3 // B_PILOT_B_PIC_PREV_PILOT_BUTTON
229 #define B_PIC_NEXT_PILOT_BUTTON 4 // B_PILOT_B_PIC_NEXT_PILOT_BUTTON
231 // pilot stat buttons
232 #define B_STATS_MEDAL_BUTTON 8 // B_STATS_MEDAL_BUTTON
233 #define B_STATS_SCROLL_DOWN_BUTTON 9 // B_STATS_SCROLL_DOWN_BUTTON
234 #define B_STATS_SCROLL_UP_BUTTON 10 // B_STATS_SCROLL_UP_BUTTON
237 #define B_ACCEPT_BUTTON 5 // B_B_ACCEPT_BUTTON
238 #define B_HELP_BUTTON 6 // B_B_HELP_BUTTON
239 #define B_OPTION_BUTTON 7 // B_OPTION_BUTTON
243 static char *Barracks_bitmap_fname[GR_NUM_RESOLUTIONS] = {
244 "Barracks", // GR_640
245 "2_Barracks" // GR_1024
248 static char *Barracks_bitmap_mask_fname[GR_NUM_RESOLUTIONS] = {
249 "Barracks-M", // GR_640
250 "2_Barracks-M" // GR_1024
255 #define BARRACKS_IMAGE_NOT_LOADED -2
257 struct barracks_bitmaps {
263 struct barracks_buttons {
266 int text_x, text_y; // this is where the text label is
269 UI_BUTTON button; // because we have a class inside this struct, we need the constructor below..
271 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) {}
274 static int Background_bitmap = -1;
275 static UI_WINDOW Ui_window;
276 static UI_BUTTON List_region;
277 static UI_INPUTBOX Inputbox;
279 static barracks_buttons Buttons[GR_NUM_RESOLUTIONS][BARRACKS_NUM_BUTTONS] = {
282 barracks_buttons("BAB_00", 8, 122, 11, 157, 0),
283 barracks_buttons("BAB_01", 323, 130, 0, 0, 1, 1),
284 barracks_buttons("BAB_02", 350, 130, 0, 0, 2, 1),
285 barracks_buttons("BAB_03", 559, 143, 0, 0, 3, 1),
286 barracks_buttons("BAB_04", 598, 143, 0, 0, 4, 1),
287 barracks_buttons("BAB_05", 571, 425, 578, 413, 5),
288 barracks_buttons("BAB_06", 533, 425, 500, 438, 6),
289 barracks_buttons("BAB_07", 533, 453, 481, 465, 7),
290 barracks_buttons("BAB_08", 361, 425, 401, 465, 8),
291 barracks_buttons("BAB_09", 0, 267, 0, 0, 9, 1),
292 barracks_buttons("BAB_10", 0, 224, 0, 0, 10,1),
293 barracks_buttons("BAB_11", 120, 122, 123, 157, 11),
294 barracks_buttons("BAB_12", 376, 124, 378, 163, 12),
295 barracks_buttons("BAB_13", 66, 122, 69, 157, 13),
296 barracks_buttons("BAB_14", 323, 0, 324, 25, 14),
297 barracks_buttons("BAB_15", 372, 0, 374, 25, 15),
298 barracks_buttons("BAB_16", 180, 122, 182, 157, 16),
299 barracks_buttons("BAB_17", 559, 306, 0, 0, 17),
300 barracks_buttons("BAB_18", 598, 306, 0, 0, 18)
303 barracks_buttons("2_BAB_00", 14, 196, 35, 252, 0),
304 barracks_buttons("2_BAB_01", 518, 209, 0, 0, 1, 1),
305 barracks_buttons("2_BAB_02", 561, 209, 0, 0, 2, 1),
306 barracks_buttons("2_BAB_03", 896, 229, 0, 0, 3, 1),
307 barracks_buttons("2_BAB_04", 958, 229, 0, 0, 4, 1),
308 barracks_buttons("2_BAB_05", 914, 681, 932, 665, 5),
309 barracks_buttons("2_BAB_06", 854, 681, 800, 704, 6),
310 barracks_buttons("2_BAB_07", 854, 724, 778, 743, 7),
311 barracks_buttons("2_BAB_08", 579, 681, 641, 743, 8),
312 barracks_buttons("2_BAB_09", 0, 428, 0, 0, 9, 1),
313 barracks_buttons("2_BAB_10", 0, 360, 0, 0, 10,1),
314 barracks_buttons("2_BAB_11", 193, 196, 214, 252, 11),
315 barracks_buttons("2_BAB_12", 602, 200, 617, 262, 12),
316 barracks_buttons("2_BAB_13", 107, 196, 128, 252, 13),
317 barracks_buttons("2_BAB_14", 517, 0, 532, 40, 14),
318 barracks_buttons("2_BAB_15", 596, 0, 614, 40, 15),
319 barracks_buttons("2_BAB_16", 289, 196, 309, 252, 16),
320 barracks_buttons("2_BAB_17", 896, 491, 0, 0, 17),
321 barracks_buttons("2_BAB_18", 958, 491, 0, 0, 18)
327 // FIXME add to strings.tbl, set correct coords
328 #define BARRACKS_NUM_TEXT 2
329 UI_XSTR Barracks_text[GR_NUM_RESOLUTIONS][BARRACKS_NUM_TEXT] = {
332 { "Barracks", 1434, 17, 7, UI_XSTR_COLOR_GREEN, -1, NULL },
333 { "Pilot Stats", 1435, 17, 180, UI_XSTR_COLOR_GREEN, -1, NULL }
337 { "Barracks", 1434, 27, 11, UI_XSTR_COLOR_GREEN, -1, NULL },
338 { "Pilot Stats", 1435, 27, 288, UI_XSTR_COLOR_GREEN, -1, NULL }
343 static int Num_stat_lines;
344 static char Stat_labels[NUM_STAT_LINES][STAT_COLUMN1_W];
345 static char Stats[NUM_STAT_LINES][STAT_COLUMN2_W];
347 extern int Player_sel_mode;
349 static player *Cur_pilot;
350 static int Num_pilots;
351 static int Selected_line;
352 static char Pilots_arr[MAX_PILOTS][MAX_FILENAME_LEN];
353 static char *Pilots[MAX_PILOTS];
354 static int Pic_number;
355 static int Pic_squad_number;
356 static bool Barracks_callsign_enter_mode;
357 static int Pilot_ranks[MAX_PILOTS];
358 static int List_scroll_offset;
359 static int Stats_scroll_offset;
360 static int Clone_flag;
361 static int Pilot_images[MAX_PILOT_IMAGES];
362 static int Pilot_squad_images[MAX_PILOT_IMAGES];
363 static int Rank_pips_bitmaps;
364 static int Rank_pips_count;
366 void barracks_squad_change_popup();
369 // -------------------------------------------------------------------------------------------------
374 #define STRCPY1(a, b) do { \
375 Assert(strlen(b) < STAT_COLUMN1_W); \
379 void barracks_init_stats(scoring_struct *stats)
386 STRCPY1(Stat_labels[Num_stat_lines], XSTR( "*All Time Stats", 50));
387 Stats[Num_stat_lines][0] = 0;
390 Assert(Num_stat_lines < NUM_STAT_LINES);
391 Stat_labels[Num_stat_lines][0] = 0;
392 Stats[Num_stat_lines][0] = 0;
395 Assert(Num_stat_lines < NUM_STAT_LINES);
396 STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Primary weapon shots:", 51));
397 sprintf(Stats[Num_stat_lines], "%d", stats->p_shots_fired);
400 Assert(Num_stat_lines < NUM_STAT_LINES);
401 STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Primary weapon hits:", 52));
402 sprintf(Stats[Num_stat_lines], "%d", stats->p_shots_hit);
405 Assert(Num_stat_lines < NUM_STAT_LINES);
406 STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Primary friendly hits:", 53));
407 sprintf(Stats[Num_stat_lines], "%d", stats->p_bonehead_hits);
410 Assert(Num_stat_lines < NUM_STAT_LINES);
411 STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Primary hit %:", 54));
412 if (stats->p_shots_fired > 0) {
413 f = (float) stats->p_shots_hit * 100.0f / (float) stats->p_shots_fired;
417 sprintf(Stats[Num_stat_lines], XSTR( "%.1f%%", 55), f);
420 Assert(Num_stat_lines < NUM_STAT_LINES);
421 STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Primary friendly hit %:", 56));
422 if (stats->p_bonehead_hits > 0) {
423 f = (float) stats->p_bonehead_hits * 100.0f / (float) stats->p_shots_fired;
427 sprintf(Stats[Num_stat_lines], XSTR( "%.1f%%", 55), f);
430 Assert(Num_stat_lines < NUM_STAT_LINES);
431 Stat_labels[Num_stat_lines][0] = 0;
432 Stats[Num_stat_lines][0] = 0;
435 Assert(Num_stat_lines < NUM_STAT_LINES);
436 STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Secondary weapon shots:", 57));
437 sprintf(Stats[Num_stat_lines], "%d", stats->s_shots_fired);
440 Assert(Num_stat_lines < NUM_STAT_LINES);
441 STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Secondary weapon hits:", 58));
442 sprintf(Stats[Num_stat_lines], "%d", stats->s_shots_hit);
445 Assert(Num_stat_lines < NUM_STAT_LINES);
446 STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Secondary friendly hits:", 59));
447 sprintf(Stats[Num_stat_lines], "%d", stats->s_bonehead_hits);
450 Assert(Num_stat_lines < NUM_STAT_LINES);
451 STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Secondary hit %:", 60));
452 if (stats->s_shots_fired > 0) {
453 f = (float) stats->s_shots_hit * 100.0f / (float) stats->s_shots_fired;
457 sprintf(Stats[Num_stat_lines], XSTR( "%.1f%%", 55), f);
460 Assert(Num_stat_lines < NUM_STAT_LINES);
461 STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Secondary friendly hit %:", 61));
462 if (stats->s_bonehead_hits > 0) {
463 f = (float) stats->s_bonehead_hits * 100.0f / (float) stats->s_shots_fired;
467 sprintf(Stats[Num_stat_lines], XSTR( "%.1f%%", 55), f);
470 Assert(Num_stat_lines < NUM_STAT_LINES);
471 Stat_labels[Num_stat_lines][0] = 0;
472 Stats[Num_stat_lines][0] = 0;
475 Assert(Num_stat_lines < NUM_STAT_LINES);
476 STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Total kills:", 62));
477 sprintf(Stats[Num_stat_lines], "%d", stats->kill_count_ok);
480 Assert(Num_stat_lines < NUM_STAT_LINES);
481 STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Assists:", 63));
482 sprintf(Stats[Num_stat_lines], "%d", stats->assists);
485 Assert(Num_stat_lines < NUM_STAT_LINES);
486 Stat_labels[Num_stat_lines][0] = 0;
487 Stats[Num_stat_lines][0] = 0;
490 Assert(Num_stat_lines < NUM_STAT_LINES);
491 Stat_labels[Num_stat_lines][0] = 0;
492 Stats[Num_stat_lines][0] = 0;
495 STRCPY1(Stat_labels[Num_stat_lines], XSTR( "*Kills by Ship Type", 64));
496 Stats[Num_stat_lines][0] = 0;
499 Assert(Num_stat_lines < NUM_STAT_LINES);
500 Stat_labels[Num_stat_lines][0] = 0;
501 Stats[Num_stat_lines][0] = 0;
504 for (i=0; i<Num_ship_types; i++) {
505 if (stats->kills[i]) {
506 Assert(Num_stat_lines < NUM_STAT_LINES);
507 Assert(strlen(Ship_info[i].name) + 1 < STAT_COLUMN1_W);
508 sprintf(Stat_labels[Num_stat_lines], NOX("%s:"), Ship_info[i].name);
509 sprintf(Stats[Num_stat_lines], "%d", stats->kills[i]);
514 for (i=0; i<Num_stat_lines; i++) {
515 gr_force_fit_string(Stat_labels[i], Stat_column1_w[gr_screen.res], Barracks_stats_coords[gr_screen.res][BARRACKS_W_COORD]);
516 gr_force_fit_string(Stats[i], Stat_column2_w[gr_screen.res], Barracks_stats2_coords[gr_screen.res][BARRACKS_W_COORD]);
520 // sets or clears hotkeys for pilot selection.
521 void barracks_set_hotkeys(bool pilot_text_enter_mode)
523 Buttons[gr_screen.res][B_PILOT_SCROLL_UP_BUTTON].button.set_hotkey(pilot_text_enter_mode ? KEY_UP : -1);
524 Buttons[gr_screen.res][B_PILOT_SCROLL_DOWN_BUTTON].button.set_hotkey(pilot_text_enter_mode ? KEY_DOWN : -1);
526 Buttons[gr_screen.res][B_PILOT_CREATE_BOTTON].button.set_hotkey(pilot_text_enter_mode ? KEY_C : -1);
527 Buttons[gr_screen.res][B_PILOT_SET_ACTIVE_BUTTON].button.set_hotkey(pilot_text_enter_mode ? KEY_ENTER : -1);
528 Buttons[gr_screen.res][B_PILOT_DELETE_BUTTON].button.set_hotkey(pilot_text_enter_mode ? KEY_DELETE : -1);
530 Buttons[gr_screen.res][B_PIC_PREV_PILOT_BUTTON].button.set_hotkey(pilot_text_enter_mode ? KEY_LEFT : -1);
531 Buttons[gr_screen.res][B_PIC_NEXT_PILOT_BUTTON].button.set_hotkey(pilot_text_enter_mode ? KEY_RIGHT : -1);
533 Buttons[gr_screen.res][B_ACCEPT_BUTTON].button.set_hotkey(pilot_text_enter_mode ? KEY_CTRLED | KEY_ENTER : -1);
536 // strip the possible .pcx extension off a filename
537 void barracks_strip_pcx(char *str)
539 int flen = strlen(str);
541 if ((flen > 4) && !stricmp(str + flen - elen, ".pcx")) {
542 str[flen - elen] = '\0';
546 // new pilot name has focus, so update stats/pic to that pilot
547 int barracks_new_pilot_selected()
549 char stripped[MAX_FILENAME_LEN+1] = "";
551 // save the previous pilot first, so changes to it are kept
552 if (strlen(Cur_pilot->callsign)) {
556 // check if we have a valid pilot hilighted. If so, attempt to active it
557 if ((Num_pilots < 1) || (Selected_line < 0) || (Selected_line >= Num_pilots)) {
558 Cur_pilot->callsign[0] = 0; // this indicates no pilot active
562 if (read_pilot_file(Pilots[Selected_line], !Player_sel_mode, Cur_pilot)) {
563 Cur_pilot->callsign[0] = 0; // this indicates no pilot active
567 // init stuff to reflect new pilot
569 barracks_init_stats(&Cur_pilot->stats);
570 for (i=0; i<Num_pilot_images; i++) {
571 strcpy(stripped, Cur_pilot->image_filename);
572 barracks_strip_pcx(stripped);
573 if (!stricmp(stripped, Pilot_image_names[i])) {
578 for ( i=0; i<Num_pilot_squad_images; i++) {
579 strcpy(stripped, Cur_pilot->squad_filename);
580 barracks_strip_pcx(stripped);
581 if (!stricmp(stripped, Pilot_squad_image_names[i])) {
585 Pic_squad_number = i;
590 void barracks_set_callsign_enter_mode(bool set_callsign_enter_mode)
592 // set global mode variable
593 Barracks_callsign_enter_mode = set_callsign_enter_mode;
595 // disable/enable all buttons
596 for (int idx=0; idx<BARRACKS_NUM_BUTTONS; idx++) {
597 // don't ever mess with the prev and next squad logo buttons
598 if((idx != B_SQUAD_PREV_BUTTON) && (idx != B_SQUAD_NEXT_BUTTON)){
599 Buttons[gr_screen.res][idx].button.enable(!set_callsign_enter_mode);
603 // enable/disable hotkeys
604 barracks_set_hotkeys(!set_callsign_enter_mode);
605 // disable/enable inputbox
606 Inputbox.enable(set_callsign_enter_mode);
607 // hide/unhide inputbox
608 Inputbox.hide(!set_callsign_enter_mode);
611 // creates a new pilot file
612 void barracks_create_new_pilot()
614 // check if too many pilots
615 if (Num_pilots >= MAX_PILOTS) {
616 gamesnd_play_iface(SND_GENERAL_FAIL);
620 // play sound for pilot creation
621 gamesnd_play_iface(SND_SCROLL);
623 // only write pilot file if there is an active pilot
624 if (strlen(Player->callsign)) {
628 // move other pilot names and ranks down to make room for the new one
629 int idx = Num_pilots;
630 Assert(Num_pilots >= 0);
632 strcpy(Pilots[idx + 1], Pilots[idx]);
633 Pilot_ranks[idx + 1] = Pilot_ranks[idx];
638 Pilots[Selected_line][0] = 0;
639 Pilot_ranks[Selected_line] = 0;
640 List_scroll_offset = 0;
642 // set mode to accept pilot name text
643 barracks_set_callsign_enter_mode(true);
644 // set focus to input box
645 Inputbox.set_focus();
646 // set initial pilot name to ""
647 Inputbox.set_text("");
648 // reset size of input box to only 1 line
649 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());
652 // exiting screen without canceling, so load in the new pilot selected here
653 int barracks_pilot_accepted()
655 char str[CALLSIGN_LEN + 1];
657 // check if pilot active. If not, don't allow accept.
658 if (!Cur_pilot->callsign[0]){
663 player_set_squad_bitmap(Cur_pilot, Cur_pilot->squad_filename);
665 // Skill_level = get_default_skill_level();
667 // MWA -- I think that we should be writing Cur_pilot here.
668 //write_pilot_file(!is_pilot_multi(Cur_pilot));
669 write_pilot_file( Cur_pilot );
671 // when we store the LastPlayer key, we have to mark it as being single or multiplayer, so we know where to look for him
672 // (since we could have a single and a multiplayer pilot with the same callsign)
673 // 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
674 strcpy(str, Cur_pilot->callsign);
675 strcat(str, is_pilot_multi(Cur_pilot) ? NOX("M") : NOX("S"));
676 os_config_write_string( NULL, "LastPlayer", str );
680 // scroll up barracks pilot list one line
681 void barracks_scroll_callsign_up()
683 if (Selected_line > 0) {
685 gamesnd_play_iface(SND_SCROLL);
687 gamesnd_play_iface(SND_GENERAL_FAIL);
690 if ((Selected_line >= 0) && (Selected_line < List_scroll_offset)) {
691 List_scroll_offset = Selected_line;
695 // scroll down barracks pilot list one line
696 void barracks_scroll_callsign_down()
698 if (Selected_line < Num_pilots - 1) {
700 gamesnd_play_iface(SND_SCROLL);
702 gamesnd_play_iface(SND_GENERAL_FAIL);
705 // num_pilots_to_fill_height is the number of pilots that can fit in given height
706 int num_pilots_to_fill_height = Barracks_list_coords[gr_screen.res][BARRACKS_H_COORD] / gr_get_font_height();
707 if (Selected_line >= List_scroll_offset + num_pilots_to_fill_height) {
708 List_scroll_offset++;
712 // scroll up barracks stats list one line
713 void barracks_scroll_stats_up()
715 if (Stats_scroll_offset > 0) {
716 Stats_scroll_offset--;
717 gamesnd_play_iface(SND_SCROLL);
719 gamesnd_play_iface(SND_GENERAL_FAIL);
723 // scroll down barracks stats list one line
724 void barracks_scroll_stats_down()
726 int font_height = gr_get_font_height();
728 if (Stats_scroll_offset + Barracks_stats_coords[gr_screen.res][BARRACKS_H_COORD] / font_height < Num_stat_lines) {
729 Stats_scroll_offset++;
730 gamesnd_play_iface(SND_SCROLL);
732 gamesnd_play_iface(SND_GENERAL_FAIL);
736 // show previous pilot pic
737 void barracks_prev_pic()
739 // check if no pilot images or no pilot selected
740 if ((Num_pilot_images == 0) || (Cur_pilot->callsign[0] == '\0')) {
741 gamesnd_play_iface(SND_GENERAL_FAIL);
745 // reset pilot pic number
747 if (Pic_number < 0) {
748 Pic_number = Num_pilot_images - 1;
751 // copy pilot pic filename into pilot struct
752 if ((Pic_number >= 0) && (Pic_number < Num_pilot_images)) {
753 strcpy(Cur_pilot->image_filename, Pilot_image_names[Pic_number]);
757 gamesnd_play_iface(SND_SCROLL);
760 // show next pilot pic
761 void barracks_next_pic()
763 // check if no pilot images or no pilot selected
764 if ((Num_pilot_images == 0) || (Cur_pilot->callsign[0] == '\0')) {
765 gamesnd_play_iface(SND_GENERAL_FAIL);
769 // reset pilot pic number
771 if (Pic_number >= Num_pilot_images){
775 // copy pilot pic filename into pilot struct
776 if ((Pic_number >= 0) && (Pic_number < Num_pilot_images)){
777 strcpy(Cur_pilot->image_filename, Pilot_image_names[Pic_number]);
781 gamesnd_play_iface(SND_SCROLL);
784 // show previous squad pic
785 void barracks_prev_squad_pic()
787 // check if no pilot images or no pilot selected
788 if ((Num_pilot_squad_images == 0) || (Cur_pilot->callsign[0] == '\0')) {
789 gamesnd_play_iface(SND_GENERAL_FAIL);
793 // reset pilot pic number
795 if (Pic_squad_number < 0) {
796 Pic_squad_number = Num_pilot_squad_images - 1;
799 // copy pilot pic filename into pilot struct
800 if ((Pic_squad_number >= 0) && (Pic_squad_number < Num_pilot_squad_images)) {
801 strcpy(Cur_pilot->squad_filename, Pilot_squad_image_names[Pic_squad_number]);
805 gamesnd_play_iface(SND_SCROLL);
808 // show next pilot pic
809 void barracks_next_squad_pic()
811 // check if no pilot images or no pilot selected
812 if ((Num_pilot_squad_images == 0) || (Cur_pilot->callsign[0] == '\0')) {
813 gamesnd_play_iface(SND_GENERAL_FAIL);
817 // reset pilot pic number
819 if (Pic_squad_number >= Num_pilot_squad_images){
820 Pic_squad_number = 0;
823 // copy pilot pic filename into pilot struct
824 if ((Pic_squad_number >= 0) && (Pic_squad_number < Num_pilot_squad_images)){
825 strcpy(Cur_pilot->squad_filename, Pilot_squad_image_names[Pic_squad_number]);
829 gamesnd_play_iface(SND_SCROLL);
832 void barracks_delete_pilot()
834 char buf[MAX_FILENAME_LEN];
838 gamesnd_play_iface(SND_GENERAL_FAIL);
842 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));
843 if (popup_rval != 1) {
847 if (!stricmp(Pilots[Selected_line], Cur_pilot->callsign)) {
851 strcpy(buf, Pilots[Selected_line]);
852 for (int i=Selected_line; i<Num_pilots-1; i++) {
853 strcpy(Pilots[i], Pilots[i + 1]);
854 Pilot_ranks[i] = Pilot_ranks[i + 1];
858 if (Selected_line >= Num_pilots) {
859 Selected_line = Num_pilots - 1;
863 if (Selected_line >= 0) {
864 barracks_new_pilot_selected();
866 Cur_pilot->callsign[0] = 0;
870 delete_pilot_file(buf, Player_sel_mode == PLAYER_SELECT_MODE_SINGLE ? 1 : 0);
871 gamesnd_play_iface(SND_USER_SELECT);
874 // Filter out pilots of wrong type (which shouldn't be in the directory we are checking, but just to be safe..)
875 int barracks_pilot_filter(char *filename)
879 r = verify_pilot_file(filename, Player_sel_mode == PLAYER_SELECT_MODE_SINGLE, &rank);
880 if (rank >= Rank_pips_count)
881 rank = Rank_pips_count - 1;
884 Pilot_ranks[Num_pilots++] = rank;
890 // callback handler for the squadon selection buttons when they are disabled (in single player)
891 void barracks_squad_change_popup()
894 popup( PF_USE_AFFIRMATIVE_ICON | PF_NO_NETWORKING, 1, POPUP_OK, XSTR("You cannot change your squadron in Single Player mode.", 1445));
898 void barracks_init_player_stuff(int mode)
900 // determine if we should be looking for single or multiplayers at the outset
901 Player_sel_mode = mode;
903 // get the list of pilots based upon whether we're in single or multiplayer mode
905 Get_file_list_filter = barracks_pilot_filter;
907 // single player specific stuff
908 if (mode == PLAYER_SELECT_MODE_SINGLE) {
909 Num_pilots = cf_get_file_list_preallocated(MAX_PILOTS, Pilots_arr, Pilots, CF_TYPE_SINGLE_PLAYERS, NOX("*.plr"), CF_SORT_TIME);
911 // disable squad logo switching
912 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.hide();
913 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.disable();
914 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.set_disabled_action(barracks_squad_change_popup);
915 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.hide();
916 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.disable();
917 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.set_disabled_action(barracks_squad_change_popup);
919 // multiplayer specific stuff
921 Num_pilots = cf_get_file_list_preallocated(MAX_PILOTS, Pilots_arr, Pilots, CF_TYPE_MULTI_PLAYERS, NOX("*.plr"), CF_SORT_TIME);
923 // enable squad logo switching
924 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.enable();
925 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.unhide();
926 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.enable();
927 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.unhide();
930 int ranks[MAX_PILOTS];
932 for (int i=0; i<Num_pilots; i++) {
934 for (j=0; j<Num_pilots; j++) {
935 if (!strcmp(Pilots[i], Pilots_arr[j])) {
936 ranks[i] = Pilot_ranks[j];
940 Assert(j < Num_pilots); // Pilot not found? How is that possible?
943 for (int i=0; i<Num_pilots; i++) {
944 Pilot_ranks[i] = ranks[i];
947 Selected_line = List_scroll_offset = 0;
948 barracks_new_pilot_selected();
952 void barracks_button_pressed(int n)
955 case B_PILOT_SCROLL_UP_BUTTON:
956 barracks_scroll_callsign_up();
959 case B_PILOT_SCROLL_DOWN_BUTTON:
960 barracks_scroll_callsign_down();
963 case B_STATS_SCROLL_UP_BUTTON:
964 barracks_scroll_stats_up();
967 case B_STATS_SCROLL_DOWN_BUTTON:
968 barracks_scroll_stats_down();
971 case B_PIC_PREV_PILOT_BUTTON:
975 case B_PIC_NEXT_PILOT_BUTTON:
979 case B_SQUAD_PREV_BUTTON:
980 barracks_prev_squad_pic();
983 case B_SQUAD_NEXT_BUTTON:
984 barracks_next_squad_pic();
987 case B_PILOT_SET_ACTIVE_BUTTON:
988 if (barracks_new_pilot_selected()){
989 gamesnd_play_iface(SND_GENERAL_FAIL);
991 // throw up a popup telling the player that he should create a pilot first
992 if(Player_sel_mode == PLAYER_SELECT_MODE_SINGLE){
993 popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR( "You must create a single player pilot.", 66));
995 popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR( "You must create a multi player pilot.", 67));
998 gamesnd_play_iface(SND_SCROLL);
1002 case B_ACCEPT_BUTTON:
1003 if (Num_pilots && !barracks_pilot_accepted()) {
1004 gamesnd_play_iface(SND_COMMIT_PRESSED);
1005 gameseq_post_event(GS_EVENT_MAIN_MENU);
1007 gamesnd_play_iface(SND_GENERAL_FAIL);
1009 // throw up a popup telling the player that he should create a pilot first
1010 if(Player_sel_mode == PLAYER_SELECT_MODE_SINGLE){
1011 popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR( "You must create a single player pilot.", 66));
1013 popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR( "You must create a multi player pilot.", 67));
1018 case B_PILOT_CLONE_BUTTON:
1019 if (Num_pilots < 1) {
1020 gamesnd_play_error_beep();
1025 barracks_create_new_pilot();
1028 case B_PILOT_CONVERT_BUTTON: {
1029 #if defined(DEMO) || defined(OEM_BUILD)
1030 game_feature_not_in_demo_popup();
1032 char temp[256], *str;
1033 char old_pic[256] = "";
1034 char old_squad_pic[256] = "";
1035 char old_squad[256] = "";
1038 if (!barracks_new_pilot_selected()) {
1039 if (Player_sel_mode == PLAYER_SELECT_MODE_SINGLE)
1040 str = XSTR( "multiplayer", 68);
1042 str = XSTR( "single player", 69);
1044 sprintf(temp, XSTR( "This will overwrite your %s pilot. Proceed?", 70), str);
1045 if (!verify_pilot_file(Cur_pilot->callsign, Player_sel_mode == PLAYER_SELECT_MODE_MULTI)) {
1046 z = popup(0, 2, POPUP_CANCEL, POPUP_OK, temp);
1051 strcpy(old_pic, Cur_pilot->image_filename);
1052 strcpy(old_squad_pic, Cur_pilot->squad_filename);
1053 strcpy(old_squad, Cur_pilot->squad_name);
1054 init_new_pilot(Cur_pilot, 0);
1055 strcpy(Cur_pilot->image_filename, old_pic);
1056 strcpy(Cur_pilot->squad_filename, old_squad_pic);
1057 strcpy(Cur_pilot->squad_name, old_squad);
1058 if (Player_sel_mode == PLAYER_SELECT_MODE_SINGLE) {
1059 Cur_pilot->flags |= PLAYER_FLAGS_IS_MULTI;
1061 barracks_init_player_stuff(PLAYER_SELECT_MODE_MULTI);
1065 barracks_init_player_stuff(PLAYER_SELECT_MODE_SINGLE);
1068 gamesnd_play_iface(SND_USER_SELECT);
1071 gamesnd_play_iface(SND_GENERAL_FAIL);
1077 case B_PILOT_CREATE_BOTTON:
1079 barracks_create_new_pilot();
1083 launch_context_help();
1084 gamesnd_play_iface(SND_HELP_PRESSED);
1087 case B_OPTION_BUTTON:
1088 gamesnd_play_iface(SND_SWITCH_SCREENS);
1089 gameseq_post_event(GS_EVENT_OPTIONS_MENU);
1092 case B_STATS_MEDAL_BUTTON:
1094 game_feature_not_in_demo_popup();
1096 gamesnd_play_iface(SND_SWITCH_SCREENS);
1097 gameseq_post_event(GS_EVENT_VIEW_MEDALS);
1101 case B_PILOT_DELETE_BUTTON:
1102 barracks_delete_pilot();
1105 case B_PILOT_SINGLE_MODE_BUTTON:
1106 if (Player_sel_mode != PLAYER_SELECT_MODE_SINGLE) {
1107 gamesnd_play_iface(SND_USER_SELECT);
1108 barracks_init_player_stuff(PLAYER_SELECT_MODE_SINGLE);
1112 case B_PILOT_MULTI_MODE_BUTTON:
1113 #if defined(DEMO) || defined(OEM_BUILD) // not for FS2_DEMO
1114 game_feature_not_in_demo_popup();
1116 if (Player_sel_mode != PLAYER_SELECT_MODE_MULTI) {
1117 gamesnd_play_iface(SND_USER_SELECT);
1118 barracks_init_player_stuff(PLAYER_SELECT_MODE_MULTI);
1126 void barracks_display_pilot_callsigns(int prospective_pilot)
1129 int cur_pilot_idx = List_scroll_offset;
1132 if (Player_sel_mode == PLAYER_SELECT_MODE_MULTI) {
1136 int font_height = gr_get_font_height();
1137 while (y + font_height <= Barracks_list_coords[gr_screen.res][BARRACKS_H_COORD]) {
1138 if (cur_pilot_idx >= Num_pilots)
1141 if (!stricmp(Cur_pilot->callsign, Pilots[cur_pilot_idx]) && (is_pilot_multi(Cur_pilot) == multi)) {
1142 if ((cur_pilot_idx == Selected_line) || (cur_pilot_idx == prospective_pilot)) {
1143 gr_set_color_fast(&Color_text_active_hi);
1145 gr_set_color_fast(&Color_text_active);
1148 if (cur_pilot_idx == Selected_line) {
1149 gr_set_color_fast(&Color_text_selected);
1150 } else if (cur_pilot_idx == prospective_pilot) {
1151 gr_set_color_fast(&Color_text_subselected);
1153 gr_set_color_fast(&Color_text_normal);
1157 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]);
1158 gr_set_bitmap(Rank_pips_bitmaps + Pilot_ranks[cur_pilot_idx]);
1159 gr_bitmap(Barracks_list_coords[gr_screen.res][BARRACKS_X_COORD] - 34, Barracks_list_coords[gr_screen.res][BARRACKS_Y_COORD] + y);
1168 void barracks_display_pilot_stats()
1171 int z = Stats_scroll_offset;
1172 int font_height = gr_get_font_height();
1175 while (y + font_height <= Barracks_stats_coords[gr_screen.res][BARRACKS_H_COORD]) {
1176 if (z >= Num_stat_lines) {
1180 str = Stat_labels[z];
1182 gr_set_color_fast(&Color_text_heading);
1185 gr_get_string_size(&w, &h, str);
1186 i = Barracks_stats_coords[gr_screen.res][BARRACKS_Y_COORD] + y + h / 2 - 1;
1187 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);
1188 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);
1191 gr_set_color_fast(&Color_text_normal);
1194 gr_get_string_size(&w, NULL, str);
1195 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);
1198 gr_printf(Barracks_stats2_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_stats_coords[gr_screen.res][BARRACKS_Y_COORD] + y, "%s", str);
1207 // process pilot callsign
1208 void barracks_accept_new_pilot_callsign()
1210 char buf[CALLSIGN_LEN + 1];
1211 char name[MAX_FILENAME_LEN];
1215 Inputbox.get_text(buf);
1216 drop_white_space(buf);
1218 if (!isalpha(*buf)) {
1221 for (i=1; buf[i]; i++) {
1222 if (!isalpha(buf[i]) && !isdigit(buf[i]) && !strchr(VALID_PILOT_CHARS, buf[i])) {
1229 for (i=1; i<Num_pilots; i++) {
1230 if (!stricmp(buf, Pilots[i])) {
1232 if (pilot_verify_overwrite() == 1) {
1233 strcpy(name, Pilots[Selected_line]);
1234 for (z=i; z<Num_pilots-1; z++) {
1235 strcpy(Pilots[z], Pilots[z + 1]);
1236 Pilot_ranks[z] = Pilot_ranks[z + 1];
1240 delete_pilot_file(name, Player_sel_mode == PLAYER_SELECT_MODE_SINGLE ? 1 : 0);
1247 if (!*buf || (i < Num_pilots)) { // duplicate name, alert user
1252 gamesnd_play_iface(SND_GENERAL_FAIL);
1256 strcpy(Pilots[0], buf);
1257 strcpy(Cur_pilot->callsign, buf);
1258 init_new_pilot(Cur_pilot, !Clone_flag);
1260 // again, make sure we set his flags correctly to ensure that he gets saved to the proper directory and gets
1261 // displayed correctly
1262 if (Player_sel_mode == PLAYER_SELECT_MODE_SINGLE) {
1263 Cur_pilot->flags &= ~(PLAYER_FLAGS_IS_MULTI);
1265 Cur_pilot->flags |= PLAYER_FLAGS_IS_MULTI;
1266 Cur_pilot->stats.flags |= STATS_FLAG_MULTIPLAYER;
1269 if ( !(Game_mode & GM_STANDALONE_SERVER) ) {
1270 write_pilot_file(Cur_pilot);
1274 barracks_new_pilot_selected();
1275 barracks_set_callsign_enter_mode(false);
1279 // draw pilot image and clean up afterwards
1280 void barracks_draw_pilot_pic()
1283 if (Cur_pilot->callsign[0] && (Pic_number >= 0) && (Pic_number < Num_pilot_images)) {
1284 if (Pilot_images[Pic_number] >= 0) {
1285 // JAS: This code is hacked to allow the animation to use all 256 colors
1286 extern int Palman_allow_any_color;
1287 Palman_allow_any_color = 1;
1288 gr_set_bitmap(Pilot_images[Pic_number]);
1289 gr_bitmap(Barracks_image_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_image_coords[gr_screen.res][BARRACKS_Y_COORD]);
1290 Palman_allow_any_color = 0;
1292 // print number of the current pic
1294 sprintf(buf, XSTR( "%d of %d", 71), Pic_number + 1, Num_pilot_images);
1295 gr_printf(Barracks_image_number_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_image_number_coords[gr_screen.res][BARRACKS_Y_COORD], buf);
1302 // draw squad image and clean up afterwards
1303 void barracks_draw_squad_pic()
1308 if (Cur_pilot->callsign[0] && (Pic_squad_number >= 0) && (Pic_squad_number < Num_pilot_squad_images)) {
1309 if (Pilot_squad_images[Pic_squad_number] >= 0) {
1310 // JAS: This code is hacked to allow the animation to use all 256 colors
1311 extern int Palman_allow_any_color;
1312 Palman_allow_any_color = 1;
1313 gr_set_bitmap(Pilot_squad_images[Pic_squad_number]);
1314 gr_bitmap(Barracks_squad_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_squad_coords[gr_screen.res][BARRACKS_Y_COORD]);
1315 Palman_allow_any_color = 0;
1317 // print number of current squad pic
1318 if(Player_sel_mode != PLAYER_SELECT_MODE_SINGLE){
1319 sprintf(buf,XSTR( "%d of %d", 71), Pic_squad_number+1, Num_pilot_squad_images);
1320 gr_printf(Barracks_squad_number_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_squad_number_coords[gr_screen.res][BARRACKS_Y_COORD], buf);
1324 Pic_squad_number = -1;
1328 // -----------------------------------------------------------------------------
1329 void barracks_init()
1331 UI_WINDOW *w = &Ui_window;
1333 // save current pilot file, so we don't possibly loose it.
1337 Ui_window.create(0, 0, gr_screen.max_w, gr_screen.max_h, 0);
1338 Ui_window.set_mask_bmap(Barracks_bitmap_mask_fname[gr_screen.res]);
1340 // load background bitmap
1341 Background_bitmap = bm_load(Barracks_bitmap_fname[gr_screen.res]);
1342 if(Background_bitmap < 0){
1343 // we failed to load the bitmap - this is very bad
1348 for (int i=0; i<BARRACKS_NUM_BUTTONS; i++) {
1349 // create the object
1350 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);
1352 // set the sound to play when highlighted
1353 Buttons[gr_screen.res][i].button.set_highlight_action(common_play_highlight_sound);
1355 // set the ani for the button
1356 Buttons[gr_screen.res][i].button.set_bmaps(Buttons[gr_screen.res][i].filename);
1359 Buttons[gr_screen.res][i].button.link_hotspot(Buttons[gr_screen.res][i].hotspot);
1363 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);
1364 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);
1365 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);
1366 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);
1367 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);
1368 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);
1369 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);
1370 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);
1371 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);
1372 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);
1373 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);
1374 for(int i=0; i<BARRACKS_NUM_TEXT; i++) {
1375 w->add_XSTR(&Barracks_text[gr_screen.res][i]);
1378 // button for selecting pilot
1379 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);
1382 // create input box (for new pilot)
1383 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);
1384 Inputbox.set_valid_chars(VALID_PILOT_CHARS);
1388 // load in help overlay bitmap
1389 help_overlay_load(BARRACKS_OVERLAY);
1390 help_overlay_set_state(BARRACKS_OVERLAY,0);
1393 Barracks_callsign_enter_mode = 0;
1394 List_scroll_offset = Stats_scroll_offset = Pic_number = Pic_squad_number = Selected_line = 0;
1395 Cur_pilot = &Players[Player_num];
1397 // disable squad logo selection buttons in single player
1398 if(!(Cur_pilot->flags & PLAYER_FLAGS_IS_MULTI)){
1399 // squad logo picture buttons
1400 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.hide();
1401 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.disable();
1402 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.hide();
1403 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.disable();
1405 // squad logo picture buttons
1406 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.enable();
1407 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.unhide();
1408 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.enable();
1409 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.unhide();
1412 // set up hotkeys for buttons so we draw the correct animation frame when a key is pressed
1413 barracks_set_hotkeys(1);
1416 Rank_pips_bitmaps = bm_load_animation("IconRankMini.ani", &Rank_pips_count);
1418 // load up the pilot pic list
1419 pilot_load_pic_list();
1420 pilot_load_squad_pic_list();
1422 // don't load pilot images yet
1423 for (int i=0; i<MAX_PILOT_IMAGES; i++) {
1424 Pilot_images[i] = BARRACKS_IMAGE_NOT_LOADED; // while -1 is can't load
1425 Pilot_squad_images[i] = BARRACKS_IMAGE_NOT_LOADED;
1429 barracks_init_stats(&Cur_pilot->stats);
1431 // disable some buttons for the multiplayer beta and e3 build
1432 #if defined(MULTIPLAYER_BETA_BUILD) || defined(E3_BUILD) || defined(PRESS_TOUR_BUILD)
1433 Buttons[gr_screen.res][B_PILOT_CLONE_BUTTON].button.hide();
1434 Buttons[gr_screen.res][B_PILOT_CONVERT_BUTTON].button.hide();
1435 Buttons[gr_screen.res][B_PILOT_CLONE_BUTTON].button.disable();
1436 Buttons[gr_screen.res][B_PILOT_CONVERT_BUTTON].button.disable();
1439 // multiplayer beta build
1440 #ifdef MULTIPLAYER_BETA_BUILD
1441 Buttons[gr_screen.res][B_PILOT_SINGLE_MODE_BUTTON].button.hide();
1442 Buttons[gr_screen.res][B_PILOT_SINGLE_MODE_BUTTON].button.disable();
1446 #if defined(E3_BUILD) || defined(PRESS_TOUR_BUILD)
1447 Buttons[gr_screen.res][B_PILOT_MULTI_MODE_BUTTON].button.hide();
1448 Buttons[gr_screen.res][B_PILOT_MULTI_MODE_BUTTON].button.disable();
1451 // base the mode we're in (single or multi) on the status of the currently selected pilot
1452 #ifdef MULTIPLAYER_BETA_BUILD
1453 barracks_init_player_stuff(1);
1454 #elif defined(E3_BUILD) || defined(PRESS_TOUR_BUILD)
1455 barracks_init_player_stuff(0);
1457 barracks_init_player_stuff(is_pilot_multi(Player));
1461 // -----------------------------------------------------------------------------
1462 void barracks_do_frame(float frametime)
1464 int k = Ui_window.process();
1467 if ( help_overlay_active(BARRACKS_OVERLAY) ) {
1468 help_overlay_set_state(BARRACKS_OVERLAY,0);
1473 // pilot that mouse is over
1474 int prospective_pilot = -1;
1477 // Entering pilot callsign
1478 if (Barracks_callsign_enter_mode) {
1479 // set focus to inputbox
1480 Inputbox.set_focus();
1484 // cancel create pilot
1486 for (i=0; i<Num_pilots; i++) {
1487 strcpy(Pilots[i], Pilots[i + 1]);
1488 Pilot_ranks[i] = Pilot_ranks[i + 1];
1491 barracks_set_callsign_enter_mode(false);
1495 barracks_accept_new_pilot_callsign();
1499 // not entering pilot callsign
1502 if (barracks_new_pilot_selected()) {
1503 gamesnd_play_iface(SND_GENERAL_FAIL);
1505 gamesnd_play_iface(SND_USER_SELECT);
1509 case KEY_ESC: // cancel
1510 if (!help_overlay_active(BARRACKS_OVERLAY)) {
1511 if (Num_pilots && !barracks_pilot_accepted()) {
1512 gameseq_post_event(GS_EVENT_MAIN_MENU);
1514 gamesnd_play_iface(SND_GENERAL_FAIL);
1518 help_overlay_set_state(BARRACKS_OVERLAY,0);
1522 case KEY_TAB: // switch mode (simgle/multi)
1523 #if defined(DEMO) || defined(OEM_BUILD) // not for FS2_DEMO
1524 game_feature_not_in_demo_popup();
1526 if (Player_sel_mode == PLAYER_SELECT_MODE_SINGLE) {
1527 barracks_init_player_stuff(PLAYER_SELECT_MODE_MULTI);
1529 barracks_init_player_stuff(PLAYER_SELECT_MODE_SINGLE);
1532 gamesnd_play_iface(SND_USER_SELECT);
1536 case KEY_F1: // show help overlay
1537 gamesnd_play_iface(SND_HELP_PRESSED);
1540 case KEY_F2: // goto options screen
1541 gamesnd_play_iface(SND_SWITCH_SCREENS);
1542 gameseq_post_event(GS_EVENT_OPTIONS_MENU);
1547 for (i=0; i<BARRACKS_NUM_BUTTONS; i++) {
1548 if (Buttons[gr_screen.res][i].button.pressed()) {
1549 barracks_button_pressed(i);
1553 // if mouse is over a pilot, find index into Pilots array
1554 if (List_region.is_mouse_on()) {
1556 List_region.get_mouse_pos(NULL, &y);
1557 int pilot_index = List_scroll_offset + (y / gr_get_font_height());
1558 if ((pilot_index >= 0) && (pilot_index < Num_pilots)) {
1559 prospective_pilot = pilot_index;
1563 // if mouse clicked in list region, find index into Pilots array
1564 if (List_region.pressed()) {
1565 if (prospective_pilot != -1) {
1566 Selected_line = prospective_pilot;
1567 gamesnd_play_iface(SND_USER_SELECT);
1572 // check mouse over help
1573 if (mouse_down(MOUSE_LEFT_BUTTON)) {
1574 help_overlay_set_state(BARRACKS_OVERLAY, 0);
1577 // do pilot pic stuff
1578 if ((Pic_number >= 0) && (Pic_number < Num_pilot_images)) {
1579 if (Pilot_images[Pic_number] == BARRACKS_IMAGE_NOT_LOADED) { // haven't tried loading it yet
1580 Pilot_images[Pic_number] = bm_load(Pilot_image_names[Pic_number]);
1581 if (Pilot_images[Pic_number] >= 0) {
1584 bm_get_info(Pilot_images[Pic_number], &w, &h, NULL);
1585 // check for invalid pilot pic file
1586 if ((w != PLAYER_PILOT_PIC_W) || (h != PLAYER_PILOT_PIC_H)) {
1587 bm_unload(Pilot_images[Pic_number]);
1588 Pilot_images[Pic_number] = -1;
1596 // do squad pic stuff
1597 if ((Pic_squad_number >= 0) && (Pic_squad_number < Num_pilot_squad_images)) {
1598 if (Pilot_squad_images[Pic_squad_number] == BARRACKS_IMAGE_NOT_LOADED) { // haven't tried loading it yet
1599 Pilot_squad_images[Pic_squad_number] = bm_load_duplicate(Pilot_squad_image_names[Pic_squad_number]);
1600 if (Pilot_squad_images[Pic_squad_number] >= 0) {
1603 bm_get_info(Pilot_squad_images[Pic_squad_number], &w, &h, NULL);
1604 // check for invalid pilot pic file
1605 if ((w != PLAYER_SQUAD_PIC_W) || (h != PLAYER_SQUAD_PIC_H)) {
1606 bm_unload(Pilot_squad_images[Pic_squad_number]);
1607 Pilot_squad_images[Pic_squad_number] = -1;
1612 Pic_squad_number = -1;
1615 // draw the background, etc
1617 GR_MAYBE_CLEAR_RES(Background_bitmap);
1618 if (Background_bitmap >= 0) {
1619 gr_set_bitmap(Background_bitmap);
1623 // draw pilot image and clean up afterwards
1624 barracks_draw_pilot_pic();
1625 barracks_draw_squad_pic();
1630 // light up the correct mode button (single or multi)
1631 if (Player_sel_mode == PLAYER_SELECT_MODE_SINGLE) {
1632 Buttons[gr_screen.res][B_PILOT_SINGLE_MODE_BUTTON].button.draw_forced(2);
1634 Buttons[gr_screen.res][B_PILOT_MULTI_MODE_BUTTON].button.draw_forced(2);
1637 // write out pilot call signs
1638 barracks_display_pilot_callsigns(prospective_pilot);
1640 // write out current pilot stats
1641 barracks_display_pilot_stats();
1643 // blit help overlay if active
1644 help_overlay_maybe_blit(BARRACKS_OVERLAY);
1650 // -----------------------------------------------------------------------------
1651 void barracks_close()
1654 Ui_window.destroy();
1656 // release background bitmap
1657 if (Background_bitmap >= 0) {
1658 bm_unload(Background_bitmap);
1661 // release rank pip bitmaps
1662 for (int i=0; i<Rank_pips_count; i++) {
1663 bm_release(Rank_pips_bitmaps + i);
1666 // release pilot pic bitmaps
1667 for (int i=0; i<Num_pilot_images; i++) {
1668 if (Pilot_images[i] >= 0) {
1669 bm_unload(Pilot_images[i]);
1673 // unload the overlay bitmap
1674 help_overlay_unload(BARRACKS_OVERLAY);