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.6 2005/03/29 02:18:47 taylor
19 * Various 64-bit platform fixes
20 * Fix compiler errors with MAKE_FS1 and fix gr_set_bitmap() too
21 * Make sure that turrets can fire at asteroids for FS1 (needed for a couple missions)
22 * Streaming audio support (big thanks to Pierre Willenbrock!!)
23 * Removed dependance on strings.tbl for FS1 since we don't actually need it now
25 * Revision 1.5 2004/09/20 01:31:44 theoddone33
28 * Revision 1.4 2003/05/25 02:30:42 taylor
31 * Revision 1.3 2002/06/09 04:41:22 relnev
32 * added copyright header
34 * Revision 1.2 2002/05/07 03:16:46 theoddone33
35 * The Great Newline Fix
37 * Revision 1.1.1.1 2002/05/03 03:28:09 root
41 * 42 10/25/99 5:47p Jefff
42 * reassigned some xstr ids
44 * 41 9/14/99 11:01p Jefff
45 * stats area coord fix
47 * 40 9/09/99 11:24a Jefff
49 * 39 9/02/99 11:26a Jefff
50 * fixed incorrect pilot list dimensions
52 * 38 8/17/99 2:24p Dave
53 * Fixed wacky squad color stuff.
55 * 37 8/16/99 4:27p Jefff
56 * fix button position on squad change error popup
58 * 36 8/11/99 3:58p Jefff
59 * fixed player list box coord bug
61 * 35 8/05/99 2:46p Jefff
62 * added popup to the disabled squad selection buttons in single player
64 * 34 8/02/99 11:02p Dave
65 * Fixed up squad filename and squad name copying when converting a pilot
66 * between single and multiplayer.
68 * 33 7/27/99 7:17p Jefff
69 * Replaced some art text with XSTR() text.
71 * 32 7/15/99 9:20a Andsager
72 * FS2_DEMO initial checkin
74 * 31 6/29/99 7:39p Dave
75 * Lots of small bug fixes.
77 * 30 6/16/99 4:06p Dave
78 * New pilot info popup. Added new draw-bitmap-as-poly function.
80 * 29 6/11/99 11:13a Dave
81 * last minute changes before press tour build.
83 * 28 4/25/99 7:43p Dave
84 * Misc small bug fixes. Made sun draw properly.
86 * 27 4/25/99 3:02p Dave
87 * Build defines for the E3 build.
89 * 26 3/24/99 4:05p Dave
90 * Put in support for assigning the player to a specific squadron with a
91 * specific logo. Preliminary work for doing pos/orient checksumming in
92 * multiplayer to reduce bandwidth.
94 * 25 2/25/99 4:19p Dave
95 * Added multiplayer_beta defines. Added cd_check define. Fixed a few
96 * release build warnings. Added more data to the squad war request and
99 * 24 2/02/99 12:09p Neilk
100 * Fixed text coords, centered pilot and squad pics in 1024x768, added vss
106 #include "barracks.h"
107 #include "managepilot.h"
114 #include "playermenu.h"
115 #include "gamesequence.h"
116 #include "contexthelp.h"
119 #include "freespace.h"
120 #include "systemvars.h"
123 #include "osregistry.h"
124 #include "alphacolors.h"
126 void delete_pilot_file( const char *pilot_name, int single ); // manage_pilot.cpp
129 #define NUM_STAT_LINES 85
130 #define STAT_COLUMN1_W 40
131 #define STAT_COLUMN2_W 10
133 static int Stat_column1_w[GR_NUM_RESOLUTIONS] =
139 static int Stat_column2_w[GR_NUM_RESOLUTIONS] =
145 // constants for coordinate lookup
146 #define BARRACKS_X_COORD 0
147 #define BARRACKS_Y_COORD 1
148 #define BARRACKS_W_COORD 2
149 #define BARRACKS_H_COORD 3
153 // pilot selection field
154 static int Barracks_list_coords[GR_NUM_RESOLUTIONS][4] = {
168 static int Barracks_stats_coords[GR_NUM_RESOLUTIONS][4] = {
181 static int Barracks_stats2_coords[GR_NUM_RESOLUTIONS][3] = {
183 276, 212, 81 // X2, , W2
186 286, 351, 81 // X2, , W2
190 // pilot picture field
191 static int Barracks_image_coords[GR_NUM_RESOLUTIONS][4] = {
204 // pilot picture # of # location
205 static int Barracks_image_number_coords[GR_NUM_RESOLUTIONS][2] = {
222 // pilot squad logo field
223 int Barracks_squad_coords[GR_NUM_RESOLUTIONS][4] = {
232 // pilot squad # of # location
233 int Barracks_squad_number_coords[GR_NUM_RESOLUTIONS][2] = {
244 #define BARRACKS_NUM_BUTTONS 17
246 #define BARRACKS_NUM_BUTTONS 19
249 // pilot selection buttons
250 #define B_PILOT_CREATE_BOTTON 0 // B_PILOT_CREATE_BOTTON
251 #define B_PILOT_SCROLL_UP_BUTTON 1 // B_PILOT_SCROLL_UP_BUTTON
252 #define B_PILOT_SCROLL_DOWN_BUTTON 2 // B_PILOT_SCROLL_DOWN_BUTTON
253 #define B_PILOT_DELETE_BUTTON 11 // B_PILOT_B_PILOT_DELETE_BUTTON
254 #define B_PILOT_SET_ACTIVE_BUTTON 12 // B_PILOT_B_PILOT_SET_ACTIVE_BUTTON
255 #define B_PILOT_CLONE_BUTTON 13 // B_PILOT_B_PILOT_CLONE_BUTTON
256 #define B_PILOT_SINGLE_MODE_BUTTON 14 // B_PILOT_SINGLE_MODE_BUTTON
257 #define B_PILOT_MULTI_MODE_BUTTON 15 // B_PILOT_MULTI_MODE_BUTTON
258 #define B_PILOT_CONVERT_BUTTON 16 // B_PILOT_B_PILOT_CONVERT_BUTTON
261 // squad logo picture buttons
262 #define B_SQUAD_PREV_BUTTON 17
263 #define B_SQUAD_NEXT_BUTTON 18
266 // pilot picture buttons
267 #define B_PIC_PREV_PILOT_BUTTON 3 // B_PILOT_B_PIC_PREV_PILOT_BUTTON
268 #define B_PIC_NEXT_PILOT_BUTTON 4 // B_PILOT_B_PIC_NEXT_PILOT_BUTTON
270 // pilot stat buttons
271 #define B_STATS_MEDAL_BUTTON 8 // B_STATS_MEDAL_BUTTON
272 #define B_STATS_SCROLL_DOWN_BUTTON 9 // B_STATS_SCROLL_DOWN_BUTTON
273 #define B_STATS_SCROLL_UP_BUTTON 10 // B_STATS_SCROLL_UP_BUTTON
276 #define B_ACCEPT_BUTTON 5 // B_B_ACCEPT_BUTTON
277 #define B_HELP_BUTTON 6 // B_B_HELP_BUTTON
278 #define B_OPTION_BUTTON 7 // B_OPTION_BUTTON
282 static const char *Barracks_bitmap_fname[GR_NUM_RESOLUTIONS] = {
283 "Barracks", // GR_640
284 "2_Barracks" // GR_1024
287 static const char *Barracks_bitmap_mask_fname[GR_NUM_RESOLUTIONS] = {
288 "Barracks-M", // GR_640
289 "2_Barracks-M" // GR_1024
294 #define BARRACKS_IMAGE_NOT_LOADED -2
296 struct barracks_bitmaps {
297 const char *filename;
302 struct barracks_buttons {
303 const char *filename;
305 int text_x, text_y; // this is where the text label is
308 UI_BUTTON button; // because we have a class inside this struct, we need the constructor below..
310 barracks_buttons(const 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) {}
313 #if defined(MAKE_FS1) && !defined(FS1_DEMO)
314 static int Background_bitmap;
315 static int PilotWin01 = -1;
316 static int PilotWin02 = -1;
317 static int PilotWin03 = -1;
318 static int PilotWin04 = -1;
320 static int Background_bitmap = -1;
322 static UI_WINDOW Ui_window;
323 static UI_BUTTON List_region;
324 static UI_INPUTBOX Inputbox;
326 static barracks_buttons Buttons[GR_NUM_RESOLUTIONS][BARRACKS_NUM_BUTTONS] = {
330 barracks_buttons("BAB_00", 12, 121, -1, -1, 0), // create
331 barracks_buttons("BAB_01", 322, 137, -1, -1, 1, 1), // barracks - arrow up
332 barracks_buttons("BAB_02", 347, 137, -1, -1, 2, 1), // barracks - arrow down
334 barracks_buttons("BAB_03", 570, 140, -1, -1, 3, 1), // pilot window - arrow left
335 barracks_buttons("BAB_04", 591, 140, -1, -1, 4, 1), // pilot window - arrow right
337 barracks_buttons("BAB_03", 570, 157, -1, -1, 3, 1), // pilot window - arrow left
338 barracks_buttons("BAB_04", 591, 157, -1, -1, 4, 1), // pilot window - arrow right
340 barracks_buttons("BAB_05", 562, 410, -1, -1, 5), // accept
341 barracks_buttons("BAB_06", 469, 427, -1, -1, 6), // help
342 barracks_buttons("BAB_07", 447, 452, -1, -1, 7), // options
343 barracks_buttons("BAB_08", 365, 415, -1, -1, 8), // medals
344 barracks_buttons("BAB_09", 0, 225, -1, -1, 9, 1), // pilot stats - arrows down
345 barracks_buttons("BAB_10", 0, 185, -1, -1, 10, 1), // pilot stats - arrows up
346 barracks_buttons("BAB_11", 124, 121, -1, -1, 11), // remove
347 barracks_buttons("BAB_12", 374, 127, -1, -1, 12), // barracks - accept
348 barracks_buttons("BAB_13", 70, 121, -1, -1, 13), // clone
349 barracks_buttons("BAB_14", 329, 13, -1, -1, 14), // single
350 barracks_buttons("BAB_15", 380, 13, -1, -1, 15), // multi
351 barracks_buttons("BAB_16", 183, 121, -1, -1, 16) // convert
353 barracks_buttons("BAB_00", 8, 122, 11, 157, 0),
354 barracks_buttons("BAB_01", 323, 130, 0, 0, 1, 1),
355 barracks_buttons("BAB_02", 350, 130, 0, 0, 2, 1),
356 barracks_buttons("BAB_03", 559, 143, 0, 0, 3, 1),
357 barracks_buttons("BAB_04", 598, 143, 0, 0, 4, 1),
358 barracks_buttons("BAB_05", 571, 425, 578, 413, 5),
359 barracks_buttons("BAB_06", 533, 425, 500, 438, 6),
360 barracks_buttons("BAB_07", 533, 453, 481, 465, 7),
361 barracks_buttons("BAB_08", 361, 425, 401, 465, 8),
362 barracks_buttons("BAB_09", 0, 267, 0, 0, 9, 1),
363 barracks_buttons("BAB_10", 0, 224, 0, 0, 10,1),
364 barracks_buttons("BAB_11", 120, 122, 123, 157, 11),
365 barracks_buttons("BAB_12", 376, 124, 378, 163, 12),
366 barracks_buttons("BAB_13", 66, 122, 69, 157, 13),
367 barracks_buttons("BAB_14", 323, 0, 324, 25, 14),
368 barracks_buttons("BAB_15", 372, 0, 374, 25, 15),
369 barracks_buttons("BAB_16", 180, 122, 182, 157, 16),
370 barracks_buttons("BAB_17", 559, 306, 0, 0, 17),
371 barracks_buttons("BAB_18", 598, 306, 0, 0, 18)
375 barracks_buttons("2_BAB_00", 14, 196, 35, 252, 0),
376 barracks_buttons("2_BAB_01", 518, 209, 0, 0, 1, 1),
377 barracks_buttons("2_BAB_02", 561, 209, 0, 0, 2, 1),
378 barracks_buttons("2_BAB_03", 896, 229, 0, 0, 3, 1),
379 barracks_buttons("2_BAB_04", 958, 229, 0, 0, 4, 1),
380 barracks_buttons("2_BAB_05", 914, 681, 932, 665, 5),
381 barracks_buttons("2_BAB_06", 854, 681, 800, 704, 6),
382 barracks_buttons("2_BAB_07", 854, 724, 778, 743, 7),
383 barracks_buttons("2_BAB_08", 579, 681, 641, 743, 8),
384 barracks_buttons("2_BAB_09", 0, 428, 0, 0, 9, 1),
385 barracks_buttons("2_BAB_10", 0, 360, 0, 0, 10,1),
386 barracks_buttons("2_BAB_11", 193, 196, 214, 252, 11),
387 barracks_buttons("2_BAB_12", 602, 200, 617, 262, 12),
388 barracks_buttons("2_BAB_13", 107, 196, 128, 252, 13),
389 barracks_buttons("2_BAB_14", 517, 0, 532, 40, 14),
390 barracks_buttons("2_BAB_15", 596, 0, 614, 40, 15),
391 barracks_buttons("2_BAB_16", 289, 196, 309, 252, 16),
393 barracks_buttons("2_BAB_17", 896, 491, 0, 0, 17),
394 barracks_buttons("2_BAB_18", 958, 491, 0, 0, 18)
401 // FIXME add to strings.tbl, set correct coords
403 #define BARRACKS_NUM_TEXT 2
405 UI_XSTR Barracks_text[GR_NUM_RESOLUTIONS][BARRACKS_NUM_TEXT] = {
408 { "Barracks", 1434, 17, 7, UI_XSTR_COLOR_GREEN, -1, NULL },
409 { "Pilot Stats", 1435, 17, 180, UI_XSTR_COLOR_GREEN, -1, NULL }
413 { "Barracks", 1434, 27, 11, UI_XSTR_COLOR_GREEN, -1, NULL },
414 { "Pilot Stats", 1435, 27, 288, UI_XSTR_COLOR_GREEN, -1, NULL }
420 static int Num_stat_lines;
421 static char Stat_labels[NUM_STAT_LINES][STAT_COLUMN1_W];
422 static char Stats[NUM_STAT_LINES][STAT_COLUMN2_W];
424 extern int Player_sel_mode;
426 static player *Cur_pilot;
427 static int Num_pilots;
428 static int Selected_line;
429 static char Pilots_arr[MAX_PILOTS][MAX_FILENAME_LEN];
430 static char *Pilots[MAX_PILOTS];
431 static int Pic_number;
432 static int Pic_squad_number;
433 static bool Barracks_callsign_enter_mode;
434 static int Pilot_ranks[MAX_PILOTS];
435 static int List_scroll_offset;
436 static int Stats_scroll_offset;
437 static int Clone_flag;
438 static int Pilot_images[MAX_PILOT_IMAGES];
439 static int Pilot_squad_images[MAX_PILOT_IMAGES];
440 static int Rank_pips_bitmaps;
441 static int Rank_pips_count;
443 void barracks_squad_change_popup();
446 // -------------------------------------------------------------------------------------------------
451 void barracks_init_stats(scoring_struct *stats)
458 SDL_strlcpy(Stat_labels[Num_stat_lines], XSTR( "*All Time Stats", 50), STAT_COLUMN1_W);
459 Stats[Num_stat_lines][0] = 0;
462 SDL_assert(Num_stat_lines < NUM_STAT_LINES);
463 Stat_labels[Num_stat_lines][0] = 0;
464 Stats[Num_stat_lines][0] = 0;
467 SDL_assert(Num_stat_lines < NUM_STAT_LINES);
468 SDL_strlcpy(Stat_labels[Num_stat_lines], XSTR( "Primary weapon shots:", 51), STAT_COLUMN1_W);
469 SDL_snprintf(Stats[Num_stat_lines], STAT_COLUMN2_W, "%d", stats->p_shots_fired);
472 SDL_assert(Num_stat_lines < NUM_STAT_LINES);
473 SDL_strlcpy(Stat_labels[Num_stat_lines], XSTR( "Primary weapon hits:", 52), STAT_COLUMN1_W);
474 SDL_snprintf(Stats[Num_stat_lines], STAT_COLUMN2_W, "%d", stats->p_shots_hit);
477 SDL_assert(Num_stat_lines < NUM_STAT_LINES);
478 SDL_strlcpy(Stat_labels[Num_stat_lines], XSTR( "Primary friendly hits:", 53), STAT_COLUMN1_W);
479 SDL_snprintf(Stats[Num_stat_lines], STAT_COLUMN2_W, "%d", stats->p_bonehead_hits);
482 SDL_assert(Num_stat_lines < NUM_STAT_LINES);
483 SDL_strlcpy(Stat_labels[Num_stat_lines], XSTR( "Primary hit %:", 54), STAT_COLUMN1_W);
484 if (stats->p_shots_fired > 0) {
485 f = (float) stats->p_shots_hit * 100.0f / (float) stats->p_shots_fired;
489 SDL_snprintf(Stats[Num_stat_lines], STAT_COLUMN2_W, XSTR( "%.1f%%", 55), f);
492 SDL_assert(Num_stat_lines < NUM_STAT_LINES);
493 SDL_strlcpy(Stat_labels[Num_stat_lines], XSTR( "Primary friendly hit %:", 56), STAT_COLUMN1_W);
494 if (stats->p_bonehead_hits > 0) {
495 f = (float) stats->p_bonehead_hits * 100.0f / (float) stats->p_shots_fired;
499 SDL_snprintf(Stats[Num_stat_lines], STAT_COLUMN2_W, XSTR( "%.1f%%", 55), f);
502 SDL_assert(Num_stat_lines < NUM_STAT_LINES);
503 Stat_labels[Num_stat_lines][0] = 0;
504 Stats[Num_stat_lines][0] = 0;
507 SDL_assert(Num_stat_lines < NUM_STAT_LINES);
508 SDL_strlcpy(Stat_labels[Num_stat_lines], XSTR( "Secondary weapon shots:", 57), STAT_COLUMN1_W);
509 SDL_snprintf(Stats[Num_stat_lines], STAT_COLUMN2_W, "%d", stats->s_shots_fired);
512 SDL_assert(Num_stat_lines < NUM_STAT_LINES);
513 SDL_strlcpy(Stat_labels[Num_stat_lines], XSTR( "Secondary weapon hits:", 58), STAT_COLUMN1_W);
514 SDL_snprintf(Stats[Num_stat_lines], STAT_COLUMN2_W, "%d", stats->s_shots_hit);
517 SDL_assert(Num_stat_lines < NUM_STAT_LINES);
518 SDL_strlcpy(Stat_labels[Num_stat_lines], XSTR( "Secondary friendly hits:", 59), STAT_COLUMN1_W);
519 SDL_snprintf(Stats[Num_stat_lines], STAT_COLUMN2_W, "%d", stats->s_bonehead_hits);
522 SDL_assert(Num_stat_lines < NUM_STAT_LINES);
523 SDL_strlcpy(Stat_labels[Num_stat_lines], XSTR( "Secondary hit %:", 60), STAT_COLUMN1_W);
524 if (stats->s_shots_fired > 0) {
525 f = (float) stats->s_shots_hit * 100.0f / (float) stats->s_shots_fired;
529 SDL_snprintf(Stats[Num_stat_lines], STAT_COLUMN2_W, XSTR( "%.1f%%", 55), f);
532 SDL_assert(Num_stat_lines < NUM_STAT_LINES);
533 SDL_strlcpy(Stat_labels[Num_stat_lines], XSTR( "Secondary friendly hit %:", 61), STAT_COLUMN1_W);
534 if (stats->s_bonehead_hits > 0) {
535 f = (float) stats->s_bonehead_hits * 100.0f / (float) stats->s_shots_fired;
539 SDL_snprintf(Stats[Num_stat_lines], STAT_COLUMN2_W, XSTR( "%.1f%%", 55), f);
542 SDL_assert(Num_stat_lines < NUM_STAT_LINES);
543 Stat_labels[Num_stat_lines][0] = 0;
544 Stats[Num_stat_lines][0] = 0;
547 SDL_assert(Num_stat_lines < NUM_STAT_LINES);
548 SDL_strlcpy(Stat_labels[Num_stat_lines], XSTR( "Total kills:", 62), STAT_COLUMN1_W);
549 SDL_snprintf(Stats[Num_stat_lines], STAT_COLUMN2_W, "%d", stats->kill_count_ok);
552 SDL_assert(Num_stat_lines < NUM_STAT_LINES);
553 SDL_strlcpy(Stat_labels[Num_stat_lines], XSTR( "Assists:", 63), STAT_COLUMN1_W);
554 SDL_snprintf(Stats[Num_stat_lines], STAT_COLUMN2_W, "%d", stats->assists);
557 SDL_assert(Num_stat_lines < NUM_STAT_LINES);
558 Stat_labels[Num_stat_lines][0] = 0;
559 Stats[Num_stat_lines][0] = 0;
562 SDL_assert(Num_stat_lines < NUM_STAT_LINES);
563 Stat_labels[Num_stat_lines][0] = 0;
564 Stats[Num_stat_lines][0] = 0;
567 SDL_strlcpy(Stat_labels[Num_stat_lines], XSTR( "*Kills by Ship Type", 64), STAT_COLUMN1_W);
568 Stats[Num_stat_lines][0] = 0;
571 SDL_assert(Num_stat_lines < NUM_STAT_LINES);
572 Stat_labels[Num_stat_lines][0] = 0;
573 Stats[Num_stat_lines][0] = 0;
576 for (i=0; i<Num_ship_types; i++) {
577 if (stats->kills[i]) {
578 SDL_assert(Num_stat_lines < NUM_STAT_LINES);
579 SDL_assert(strlen(Ship_info[i].name) + 1 < STAT_COLUMN1_W);
580 SDL_snprintf(Stat_labels[Num_stat_lines], STAT_COLUMN1_W, NOX("%s:"), Ship_info[i].name);
581 SDL_snprintf(Stats[Num_stat_lines], STAT_COLUMN2_W, "%d", stats->kills[i]);
586 for (i=0; i<Num_stat_lines; i++) {
587 gr_force_fit_string(Stat_labels[i], Stat_column1_w[gr_screen.res], Barracks_stats_coords[gr_screen.res][BARRACKS_W_COORD]);
588 gr_force_fit_string(Stats[i], Stat_column2_w[gr_screen.res], Barracks_stats2_coords[gr_screen.res][BARRACKS_W_COORD]);
592 // sets or clears hotkeys for pilot selection.
593 void barracks_set_hotkeys(bool pilot_text_enter_mode)
595 Buttons[gr_screen.res][B_PILOT_SCROLL_UP_BUTTON].button.set_hotkey(pilot_text_enter_mode ? SDLK_UP : -1);
596 Buttons[gr_screen.res][B_PILOT_SCROLL_DOWN_BUTTON].button.set_hotkey(pilot_text_enter_mode ? SDLK_DOWN : -1);
598 Buttons[gr_screen.res][B_PILOT_CREATE_BOTTON].button.set_hotkey(pilot_text_enter_mode ? SDLK_c : -1);
599 Buttons[gr_screen.res][B_PILOT_SET_ACTIVE_BUTTON].button.set_hotkey(pilot_text_enter_mode ? SDLK_RETURN : -1);
600 Buttons[gr_screen.res][B_PILOT_DELETE_BUTTON].button.set_hotkey(pilot_text_enter_mode ? SDLK_DELETE : -1);
602 Buttons[gr_screen.res][B_PIC_PREV_PILOT_BUTTON].button.set_hotkey(pilot_text_enter_mode ? SDLK_LEFT : -1);
603 Buttons[gr_screen.res][B_PIC_NEXT_PILOT_BUTTON].button.set_hotkey(pilot_text_enter_mode ? SDLK_RIGHT : -1);
605 Buttons[gr_screen.res][B_ACCEPT_BUTTON].button.set_hotkey(pilot_text_enter_mode ? KEY_CTRLED | SDLK_RETURN : -1);
608 // strip the possible .pcx extension off a filename
609 void barracks_strip_pcx(char *str)
611 int flen = strlen(str);
613 if ((flen > 4) && !SDL_strcasecmp(str + flen - elen, ".pcx")) {
614 str[flen - elen] = '\0';
618 // new pilot name has focus, so update stats/pic to that pilot
619 int barracks_new_pilot_selected()
621 char stripped[MAX_FILENAME_LEN+1] = "";
623 // save the previous pilot first, so changes to it are kept
624 if (strlen(Cur_pilot->callsign)) {
628 // check if we have a valid pilot hilighted. If so, attempt to active it
629 if ((Num_pilots < 1) || (Selected_line < 0) || (Selected_line >= Num_pilots)) {
630 Cur_pilot->callsign[0] = 0; // this indicates no pilot active
634 if (read_pilot_file(Pilots[Selected_line], !Player_sel_mode, Cur_pilot)) {
635 Cur_pilot->callsign[0] = 0; // this indicates no pilot active
639 // init stuff to reflect new pilot
641 barracks_init_stats(&Cur_pilot->stats);
642 for (i=0; i<Num_pilot_images; i++) {
643 SDL_strlcpy(stripped, Cur_pilot->image_filename, SDL_arraysize(stripped));
644 barracks_strip_pcx(stripped);
645 if (!SDL_strcasecmp(stripped, Pilot_image_names[i])) {
650 for ( i=0; i<Num_pilot_squad_images; i++) {
651 SDL_strlcpy(stripped, Cur_pilot->squad_filename, SDL_arraysize(stripped));
652 barracks_strip_pcx(stripped);
653 if (!SDL_strcasecmp(stripped, Pilot_squad_image_names[i])) {
657 Pic_squad_number = i;
662 void barracks_set_callsign_enter_mode(bool set_callsign_enter_mode)
664 // set global mode variable
665 Barracks_callsign_enter_mode = set_callsign_enter_mode;
667 // disable/enable all buttons
668 for (int idx=0; idx<BARRACKS_NUM_BUTTONS; idx++) {
669 // don't ever mess with the prev and next squad logo buttons
671 Buttons[gr_screen.res][idx].button.enable(!set_callsign_enter_mode);
673 if((idx != B_SQUAD_PREV_BUTTON) && (idx != B_SQUAD_NEXT_BUTTON)){
674 Buttons[gr_screen.res][idx].button.enable(!set_callsign_enter_mode);
679 // enable/disable hotkeys
680 barracks_set_hotkeys(!set_callsign_enter_mode);
681 // disable/enable inputbox
682 Inputbox.enable(set_callsign_enter_mode);
683 // hide/unhide inputbox
684 Inputbox.hide(!set_callsign_enter_mode);
687 // creates a new pilot file
688 void barracks_create_new_pilot()
690 // check if too many pilots
691 if (Num_pilots >= MAX_PILOTS) {
692 gamesnd_play_iface(SND_GENERAL_FAIL);
696 // play sound for pilot creation
697 gamesnd_play_iface(SND_SCROLL);
699 // only write pilot file if there is an active pilot
700 if (strlen(Player->callsign)) {
704 // move other pilot names and ranks down to make room for the new one
705 int idx = Num_pilots;
706 SDL_assert(Num_pilots >= 0);
708 SDL_strlcpy(Pilots[idx + 1], Pilots[idx], MAX_FILENAME_LEN);
709 Pilot_ranks[idx + 1] = Pilot_ranks[idx];
714 Pilots[Selected_line][0] = 0;
715 Pilot_ranks[Selected_line] = 0;
716 List_scroll_offset = 0;
718 // set mode to accept pilot name text
719 barracks_set_callsign_enter_mode(true);
720 // set focus to input box
721 Inputbox.set_focus();
722 // set initial pilot name to ""
723 Inputbox.set_text("");
724 // reset size of input box to only 1 line
725 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());
728 // exiting screen without canceling, so load in the new pilot selected here
729 int barracks_pilot_accepted()
731 char str[CALLSIGN_LEN + 1];
733 // check if pilot active. If not, don't allow accept.
734 if (!Cur_pilot->callsign[0]){
739 player_set_squad_bitmap(Cur_pilot, Cur_pilot->squad_filename);
741 // Skill_level = get_default_skill_level();
743 // MWA -- I think that we should be writing Cur_pilot here.
744 //write_pilot_file(!is_pilot_multi(Cur_pilot));
745 write_pilot_file( Cur_pilot );
747 // when we store the LastPlayer key, we have to mark it as being single or multiplayer, so we know where to look for him
748 // (since we could have a single and a multiplayer pilot with the same callsign)
749 // 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
750 SDL_strlcpy(str, Cur_pilot->callsign, SDL_arraysize(str));
751 SDL_strlcat(str, is_pilot_multi(Cur_pilot) ? NOX("M") : NOX("S"), SDL_arraysize(str));
752 os_config_write_string( NULL, "LastPlayer", str );
756 // scroll up barracks pilot list one line
757 void barracks_scroll_callsign_up()
759 if (Selected_line > 0) {
761 gamesnd_play_iface(SND_SCROLL);
763 gamesnd_play_iface(SND_GENERAL_FAIL);
766 if ((Selected_line >= 0) && (Selected_line < List_scroll_offset)) {
767 List_scroll_offset = Selected_line;
771 // scroll down barracks pilot list one line
772 void barracks_scroll_callsign_down()
774 if (Selected_line < Num_pilots - 1) {
776 gamesnd_play_iface(SND_SCROLL);
778 gamesnd_play_iface(SND_GENERAL_FAIL);
781 // num_pilots_to_fill_height is the number of pilots that can fit in given height
782 int num_pilots_to_fill_height = Barracks_list_coords[gr_screen.res][BARRACKS_H_COORD] / gr_get_font_height();
783 if (Selected_line >= List_scroll_offset + num_pilots_to_fill_height) {
784 List_scroll_offset++;
788 // scroll up barracks stats list one line
789 void barracks_scroll_stats_up()
791 if (Stats_scroll_offset > 0) {
792 Stats_scroll_offset--;
793 gamesnd_play_iface(SND_SCROLL);
795 gamesnd_play_iface(SND_GENERAL_FAIL);
799 // scroll down barracks stats list one line
800 void barracks_scroll_stats_down()
802 int font_height = gr_get_font_height();
804 if (Stats_scroll_offset + Barracks_stats_coords[gr_screen.res][BARRACKS_H_COORD] / font_height < Num_stat_lines) {
805 Stats_scroll_offset++;
806 gamesnd_play_iface(SND_SCROLL);
808 gamesnd_play_iface(SND_GENERAL_FAIL);
812 // show previous pilot pic
813 void barracks_prev_pic()
815 // check if no pilot images or no pilot selected
816 if ((Num_pilot_images == 0) || (Cur_pilot->callsign[0] == '\0')) {
817 gamesnd_play_iface(SND_GENERAL_FAIL);
821 // reset pilot pic number
823 if (Pic_number < 0) {
824 Pic_number = Num_pilot_images - 1;
827 // copy pilot pic filename into pilot struct
828 if ((Pic_number >= 0) && (Pic_number < Num_pilot_images)) {
829 SDL_strlcpy(Cur_pilot->image_filename, Pilot_image_names[Pic_number], SDL_arraysize(Cur_pilot->image_filename));
833 gamesnd_play_iface(SND_SCROLL);
836 // show next pilot pic
837 void barracks_next_pic()
839 // check if no pilot images or no pilot selected
840 if ((Num_pilot_images == 0) || (Cur_pilot->callsign[0] == '\0')) {
841 gamesnd_play_iface(SND_GENERAL_FAIL);
845 // reset pilot pic number
847 if (Pic_number >= Num_pilot_images){
851 // copy pilot pic filename into pilot struct
852 if ((Pic_number >= 0) && (Pic_number < Num_pilot_images)){
853 SDL_strlcpy(Cur_pilot->image_filename, Pilot_image_names[Pic_number], SDL_arraysize(Cur_pilot->image_filename));
857 gamesnd_play_iface(SND_SCROLL);
860 // show previous squad pic
861 void barracks_prev_squad_pic()
863 // check if no pilot images or no pilot selected
864 if ((Num_pilot_squad_images == 0) || (Cur_pilot->callsign[0] == '\0')) {
865 gamesnd_play_iface(SND_GENERAL_FAIL);
869 // reset pilot pic number
871 if (Pic_squad_number < 0) {
872 Pic_squad_number = Num_pilot_squad_images - 1;
875 // copy pilot pic filename into pilot struct
876 if ((Pic_squad_number >= 0) && (Pic_squad_number < Num_pilot_squad_images)) {
877 SDL_strlcpy(Cur_pilot->squad_filename, Pilot_squad_image_names[Pic_squad_number], SDL_arraysize(Cur_pilot->squad_filename));
881 gamesnd_play_iface(SND_SCROLL);
884 // show next pilot pic
885 void barracks_next_squad_pic()
887 // check if no pilot images or no pilot selected
888 if ((Num_pilot_squad_images == 0) || (Cur_pilot->callsign[0] == '\0')) {
889 gamesnd_play_iface(SND_GENERAL_FAIL);
893 // reset pilot pic number
895 if (Pic_squad_number >= Num_pilot_squad_images){
896 Pic_squad_number = 0;
899 // copy pilot pic filename into pilot struct
900 if ((Pic_squad_number >= 0) && (Pic_squad_number < Num_pilot_squad_images)){
901 SDL_strlcpy(Cur_pilot->squad_filename, Pilot_squad_image_names[Pic_squad_number], SDL_arraysize(Cur_pilot->squad_filename));
905 gamesnd_play_iface(SND_SCROLL);
908 void barracks_delete_pilot()
910 char buf[MAX_FILENAME_LEN];
914 gamesnd_play_iface(SND_GENERAL_FAIL);
918 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));
919 if (popup_rval != 1) {
923 if (!SDL_strcasecmp(Pilots[Selected_line], Cur_pilot->callsign)) {
927 SDL_strlcpy(buf, Pilots[Selected_line], SDL_arraysize(buf));
928 for (int i=Selected_line; i<Num_pilots-1; i++) {
929 SDL_strlcpy(Pilots[i], Pilots[i + 1], MAX_FILENAME_LEN);
930 Pilot_ranks[i] = Pilot_ranks[i + 1];
934 if (Selected_line >= Num_pilots) {
935 Selected_line = Num_pilots - 1;
939 if (Selected_line >= 0) {
940 barracks_new_pilot_selected();
942 Cur_pilot->callsign[0] = 0;
946 delete_pilot_file(buf, Player_sel_mode == PLAYER_SELECT_MODE_SINGLE ? 1 : 0);
947 gamesnd_play_iface(SND_USER_SELECT);
950 // Filter out pilots of wrong type (which shouldn't be in the directory we are checking, but just to be safe..)
951 int barracks_pilot_filter(const char *filename)
955 r = verify_pilot_file(filename, Player_sel_mode == PLAYER_SELECT_MODE_SINGLE, &rank);
956 if (rank >= Rank_pips_count)
957 rank = Rank_pips_count - 1;
960 Pilot_ranks[Num_pilots++] = rank;
966 // callback handler for the squadon selection buttons when they are disabled (in single player)
967 void barracks_squad_change_popup()
970 popup( PF_USE_AFFIRMATIVE_ICON | PF_NO_NETWORKING, 1, POPUP_OK, XSTR("You cannot change your squadron in Single Player mode.", 1445));
974 void barracks_init_player_stuff(int mode)
976 // determine if we should be looking for single or multiplayers at the outset
977 Player_sel_mode = mode;
979 // get the list of pilots based upon whether we're in single or multiplayer mode
981 Get_file_list_filter = barracks_pilot_filter;
983 // single player specific stuff
984 if (mode == PLAYER_SELECT_MODE_SINGLE) {
985 Num_pilots = cf_get_file_list_preallocated(MAX_PILOTS, Pilots_arr, Pilots, CF_TYPE_SINGLE_PLAYERS, NOX("*.plr"), CF_SORT_TIME);
988 // disable squad logo switching
989 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.hide();
990 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.disable();
991 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.set_disabled_action(barracks_squad_change_popup);
992 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.hide();
993 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.disable();
994 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.set_disabled_action(barracks_squad_change_popup);
997 // multiplayer specific stuff
999 Num_pilots = cf_get_file_list_preallocated(MAX_PILOTS, Pilots_arr, Pilots, CF_TYPE_MULTI_PLAYERS, NOX("*.plr"), CF_SORT_TIME);
1002 // enable squad logo switching
1003 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.enable();
1004 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.unhide();
1005 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.enable();
1006 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.unhide();
1010 int ranks[MAX_PILOTS];
1014 for (int i=0; i<Num_pilots; i++) {
1016 for (j=0; j<Num_pilots; j++) {
1017 if (!strcmp(Pilots[i], Pilots_arr[j])) {
1018 ranks[i] = Pilot_ranks[j];
1022 SDL_assert(j < Num_pilots); // Pilot not found? How is that possible?
1025 for (int i=0; i<Num_pilots; i++) {
1026 Pilot_ranks[i] = ranks[i];
1029 Selected_line = List_scroll_offset = 0;
1030 barracks_new_pilot_selected();
1034 void barracks_button_pressed(int n)
1037 case B_PILOT_SCROLL_UP_BUTTON:
1038 barracks_scroll_callsign_up();
1041 case B_PILOT_SCROLL_DOWN_BUTTON:
1042 barracks_scroll_callsign_down();
1045 case B_STATS_SCROLL_UP_BUTTON:
1046 barracks_scroll_stats_up();
1049 case B_STATS_SCROLL_DOWN_BUTTON:
1050 barracks_scroll_stats_down();
1053 case B_PIC_PREV_PILOT_BUTTON:
1054 barracks_prev_pic();
1057 case B_PIC_NEXT_PILOT_BUTTON:
1058 barracks_next_pic();
1062 case B_SQUAD_PREV_BUTTON:
1063 barracks_prev_squad_pic();
1066 case B_SQUAD_NEXT_BUTTON:
1067 barracks_next_squad_pic();
1071 case B_PILOT_SET_ACTIVE_BUTTON:
1072 if (barracks_new_pilot_selected()){
1073 gamesnd_play_iface(SND_GENERAL_FAIL);
1075 // throw up a popup telling the player that he should create a pilot first
1076 if(Player_sel_mode == PLAYER_SELECT_MODE_SINGLE){
1077 popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR( "You must create a single player pilot.", 66));
1079 popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR( "You must create a multi player pilot.", 67));
1082 gamesnd_play_iface(SND_SCROLL);
1086 case B_ACCEPT_BUTTON:
1087 if (Num_pilots && !barracks_pilot_accepted()) {
1088 gamesnd_play_iface(SND_COMMIT_PRESSED);
1089 gameseq_post_event(GS_EVENT_MAIN_MENU);
1091 gamesnd_play_iface(SND_GENERAL_FAIL);
1093 // throw up a popup telling the player that he should create a pilot first
1094 if(Player_sel_mode == PLAYER_SELECT_MODE_SINGLE){
1095 popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR( "You must create a single player pilot.", 66));
1097 popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR( "You must create a multi player pilot.", 67));
1102 case B_PILOT_CLONE_BUTTON:
1103 if (Num_pilots < 1) {
1104 gamesnd_play_error_beep();
1109 barracks_create_new_pilot();
1112 case B_PILOT_CONVERT_BUTTON: {
1113 #if defined(DEMO) || defined(OEM_BUILD)
1114 game_feature_not_in_demo_popup();
1118 char old_pic[256] = "";
1119 char old_squad_pic[256] = "";
1120 char old_squad[256] = "";
1123 if (!barracks_new_pilot_selected()) {
1124 if (Player_sel_mode == PLAYER_SELECT_MODE_SINGLE)
1125 str = XSTR( "multiplayer", 68);
1127 str = XSTR( "single player", 69);
1129 SDL_snprintf(temp, SDL_arraysize(temp), XSTR( "This will overwrite your %s pilot. Proceed?", 70), str);
1130 if (!verify_pilot_file(Cur_pilot->callsign, Player_sel_mode == PLAYER_SELECT_MODE_MULTI)) {
1131 z = popup(0, 2, POPUP_CANCEL, POPUP_OK, temp);
1136 SDL_strlcpy(old_pic, Cur_pilot->image_filename, SDL_arraysize(old_pic));
1137 SDL_strlcpy(old_squad_pic, Cur_pilot->squad_filename, SDL_arraysize(old_squad_pic));
1138 SDL_strlcpy(old_squad, Cur_pilot->squad_name, SDL_arraysize(old_squad));
1139 init_new_pilot(Cur_pilot, 0);
1140 SDL_strlcpy(Cur_pilot->image_filename, old_pic, SDL_arraysize(Cur_pilot->image_filename));
1141 SDL_strlcpy(Cur_pilot->squad_filename, old_squad_pic, SDL_arraysize(Cur_pilot->squad_filename));
1142 SDL_strlcpy(Cur_pilot->squad_name, old_squad, SDL_arraysize(Cur_pilot->squad_name));
1143 if (Player_sel_mode == PLAYER_SELECT_MODE_SINGLE) {
1144 Cur_pilot->flags |= PLAYER_FLAGS_IS_MULTI;
1146 barracks_init_player_stuff(PLAYER_SELECT_MODE_MULTI);
1150 barracks_init_player_stuff(PLAYER_SELECT_MODE_SINGLE);
1153 gamesnd_play_iface(SND_USER_SELECT);
1156 gamesnd_play_iface(SND_GENERAL_FAIL);
1162 case B_PILOT_CREATE_BOTTON:
1164 barracks_create_new_pilot();
1168 launch_context_help();
1169 gamesnd_play_iface(SND_HELP_PRESSED);
1172 case B_OPTION_BUTTON:
1173 gamesnd_play_iface(SND_SWITCH_SCREENS);
1174 gameseq_post_event(GS_EVENT_OPTIONS_MENU);
1177 case B_STATS_MEDAL_BUTTON:
1178 #if defined(FS2_DEMO) || defined(FS1_DEMO)
1179 game_feature_not_in_demo_popup();
1181 gamesnd_play_iface(SND_SWITCH_SCREENS);
1182 gameseq_post_event(GS_EVENT_VIEW_MEDALS);
1186 case B_PILOT_DELETE_BUTTON:
1187 barracks_delete_pilot();
1190 case B_PILOT_SINGLE_MODE_BUTTON:
1191 if (Player_sel_mode != PLAYER_SELECT_MODE_SINGLE) {
1192 gamesnd_play_iface(SND_USER_SELECT);
1193 barracks_init_player_stuff(PLAYER_SELECT_MODE_SINGLE);
1197 case B_PILOT_MULTI_MODE_BUTTON:
1198 #if defined(DEMO) || defined(OEM_BUILD) // not for FS2_DEMO
1199 game_feature_not_in_demo_popup();
1201 if (Player_sel_mode != PLAYER_SELECT_MODE_MULTI) {
1202 gamesnd_play_iface(SND_USER_SELECT);
1203 barracks_init_player_stuff(PLAYER_SELECT_MODE_MULTI);
1211 void barracks_display_pilot_callsigns(int prospective_pilot)
1214 int cur_pilot_idx = List_scroll_offset;
1217 if (Player_sel_mode == PLAYER_SELECT_MODE_MULTI) {
1221 int font_height = gr_get_font_height();
1222 while (y + font_height <= Barracks_list_coords[gr_screen.res][BARRACKS_H_COORD]) {
1223 if (cur_pilot_idx >= Num_pilots)
1226 if (!SDL_strcasecmp(Cur_pilot->callsign, Pilots[cur_pilot_idx]) && (is_pilot_multi(Cur_pilot) == multi)) {
1227 if ((cur_pilot_idx == Selected_line) || (cur_pilot_idx == prospective_pilot)) {
1228 gr_set_color_fast(&Color_text_active_hi);
1230 gr_set_color_fast(&Color_text_active);
1233 if (cur_pilot_idx == Selected_line) {
1234 gr_set_color_fast(&Color_text_selected);
1235 } else if (cur_pilot_idx == prospective_pilot) {
1236 gr_set_color_fast(&Color_text_subselected);
1238 gr_set_color_fast(&Color_text_normal);
1242 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]);
1244 gr_set_bitmap(Rank_pips_bitmaps + Pilot_ranks[cur_pilot_idx], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1245 gr_bitmap(Barracks_list_coords[gr_screen.res][BARRACKS_X_COORD] - 34, Barracks_list_coords[gr_screen.res][BARRACKS_Y_COORD] + y);
1255 void barracks_display_pilot_stats()
1258 int z = Stats_scroll_offset;
1259 int font_height = gr_get_font_height();
1262 while (y + font_height <= Barracks_stats_coords[gr_screen.res][BARRACKS_H_COORD]) {
1263 if (z >= Num_stat_lines) {
1267 str = Stat_labels[z];
1269 gr_set_color_fast(&Color_text_heading);
1272 gr_get_string_size(&w, &h, str);
1273 i = Barracks_stats_coords[gr_screen.res][BARRACKS_Y_COORD] + y + h / 2 - 1;
1274 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);
1275 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);
1278 gr_set_color_fast(&Color_text_normal);
1281 gr_get_string_size(&w, NULL, str);
1282 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);
1285 gr_printf(Barracks_stats2_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_stats_coords[gr_screen.res][BARRACKS_Y_COORD] + y, "%s", str);
1294 // process pilot callsign
1295 void barracks_accept_new_pilot_callsign()
1297 char buf[CALLSIGN_LEN + 1];
1298 char name[MAX_FILENAME_LEN];
1302 Inputbox.get_text(buf);
1303 drop_white_space(buf);
1305 if (!isalpha(*buf)) {
1308 for (i=1; buf[i]; i++) {
1309 if (!isalpha(buf[i]) && !isdigit(buf[i]) && !SDL_strchr(VALID_PILOT_CHARS, buf[i])) {
1315 for (i=1; i<Num_pilots; i++) {
1316 if (!SDL_strcasecmp(buf, Pilots[i])) {
1317 if (pilot_verify_overwrite() == 1) {
1318 SDL_strlcpy(name, Pilots[Selected_line], SDL_arraysize(name));
1319 for (z=i; z<Num_pilots-1; z++) {
1320 SDL_strlcpy(Pilots[z], Pilots[z + 1], MAX_FILENAME_LEN);
1321 Pilot_ranks[z] = Pilot_ranks[z + 1];
1325 delete_pilot_file(name, Player_sel_mode == PLAYER_SELECT_MODE_SINGLE ? 1 : 0);
1331 if (!*buf || (i < Num_pilots)) { // duplicate name, alert user
1336 gamesnd_play_iface(SND_GENERAL_FAIL);
1340 SDL_strlcpy(Pilots[0], buf, MAX_FILENAME_LEN);
1341 SDL_strlcpy(Cur_pilot->callsign, buf, SDL_arraysize(Cur_pilot->callsign));
1342 init_new_pilot(Cur_pilot, !Clone_flag);
1344 // again, make sure we set his flags correctly to ensure that he gets saved to the proper directory and gets
1345 // displayed correctly
1346 if (Player_sel_mode == PLAYER_SELECT_MODE_SINGLE) {
1347 Cur_pilot->flags &= ~(PLAYER_FLAGS_IS_MULTI);
1349 Cur_pilot->flags |= PLAYER_FLAGS_IS_MULTI;
1350 Cur_pilot->stats.flags |= STATS_FLAG_MULTIPLAYER;
1353 if ( !(Game_mode & GM_STANDALONE_SERVER) ) {
1354 write_pilot_file(Cur_pilot);
1358 barracks_new_pilot_selected();
1359 barracks_set_callsign_enter_mode(false);
1363 // draw pilot image and clean up afterwards
1364 void barracks_draw_pilot_pic()
1367 if (Cur_pilot->callsign[0] && (Pic_number >= 0) && (Pic_number < Num_pilot_images)) {
1368 if (Pilot_images[Pic_number] >= 0) {
1369 // JAS: This code is hacked to allow the animation to use all 256 colors
1370 extern int Palman_allow_any_color;
1371 Palman_allow_any_color = 1;
1372 gr_set_bitmap(Pilot_images[Pic_number], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1373 gr_bitmap(Barracks_image_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_image_coords[gr_screen.res][BARRACKS_Y_COORD]);
1374 Palman_allow_any_color = 0;
1376 // print number of the current pic
1378 SDL_snprintf(buf, SDL_arraysize(buf), XSTR( "%d of %d", 71), Pic_number + 1, Num_pilot_images);
1379 gr_printf(Barracks_image_number_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_image_number_coords[gr_screen.res][BARRACKS_Y_COORD], buf);
1386 // draw squad image and clean up afterwards
1387 void barracks_draw_squad_pic()
1392 if (Cur_pilot->callsign[0] && (Pic_squad_number >= 0) && (Pic_squad_number < Num_pilot_squad_images)) {
1393 if (Pilot_squad_images[Pic_squad_number] >= 0) {
1394 // JAS: This code is hacked to allow the animation to use all 256 colors
1395 extern int Palman_allow_any_color;
1396 Palman_allow_any_color = 1;
1397 gr_set_bitmap(Pilot_squad_images[Pic_squad_number], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1398 gr_bitmap(Barracks_squad_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_squad_coords[gr_screen.res][BARRACKS_Y_COORD]);
1399 Palman_allow_any_color = 0;
1401 // print number of current squad pic
1402 if(Player_sel_mode != PLAYER_SELECT_MODE_SINGLE){
1403 SDL_snprintf(buf, SDL_arraysize(buf), XSTR( "%d of %d", 71), Pic_squad_number+1, Num_pilot_squad_images);
1404 gr_printf(Barracks_squad_number_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_squad_number_coords[gr_screen.res][BARRACKS_Y_COORD], buf);
1408 Pic_squad_number = -1;
1412 // -----------------------------------------------------------------------------
1413 void barracks_init()
1416 UI_WINDOW *w = &Ui_window;
1419 // save current pilot file, so we don't possibly loose it.
1423 Ui_window.create(0, 0, gr_screen.max_w, gr_screen.max_h, 0);
1424 Ui_window.set_mask_bmap(Barracks_bitmap_mask_fname[gr_screen.res]);
1426 // load background bitmap
1427 Background_bitmap = bm_load(Barracks_bitmap_fname[gr_screen.res]);
1428 if(Background_bitmap < 0){
1429 // we failed to load the bitmap - this is very bad
1434 for (int i=0; i<BARRACKS_NUM_BUTTONS; i++) {
1435 // create the object
1436 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);
1438 // set the sound to play when highlighted
1439 Buttons[gr_screen.res][i].button.set_highlight_action(common_play_highlight_sound);
1441 // set the ani for the button
1442 Buttons[gr_screen.res][i].button.set_bmaps(Buttons[gr_screen.res][i].filename);
1445 Buttons[gr_screen.res][i].button.link_hotspot(Buttons[gr_screen.res][i].hotspot);
1450 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);
1451 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);
1452 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);
1453 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);
1454 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);
1455 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);
1456 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);
1457 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);
1458 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);
1459 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);
1460 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);
1461 for(int i=0; i<BARRACKS_NUM_TEXT; i++) {
1462 w->add_XSTR(&Barracks_text[gr_screen.res][i]);
1466 // button for selecting pilot
1467 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);
1470 // create input box (for new pilot)
1471 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);
1472 Inputbox.set_valid_chars(VALID_PILOT_CHARS);
1476 // load in help overlay bitmap
1477 help_overlay_load(BARRACKS_OVERLAY);
1478 help_overlay_set_state(BARRACKS_OVERLAY,0);
1481 Barracks_callsign_enter_mode = 0;
1482 List_scroll_offset = Stats_scroll_offset = Pic_number = Pic_squad_number = Selected_line = 0;
1483 Cur_pilot = &Players[Player_num];
1485 // disable squad logo selection buttons in single player
1487 if(!(Cur_pilot->flags & PLAYER_FLAGS_IS_MULTI)){
1488 // squad logo picture buttons
1489 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.hide();
1490 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.disable();
1491 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.hide();
1492 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.disable();
1494 // squad logo picture buttons
1495 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.enable();
1496 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.unhide();
1497 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.enable();
1498 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.unhide();
1502 // set up hotkeys for buttons so we draw the correct animation frame when a key is pressed
1503 barracks_set_hotkeys(1);
1507 Rank_pips_bitmaps = bm_load_animation("IconRankMini.ani", &Rank_pips_count);
1510 // load up the pilot pic list
1511 pilot_load_pic_list();
1512 pilot_load_squad_pic_list();
1514 // don't load pilot images yet
1515 for (int i=0; i<MAX_PILOT_IMAGES; i++) {
1516 Pilot_images[i] = BARRACKS_IMAGE_NOT_LOADED; // while -1 is can't load
1517 Pilot_squad_images[i] = BARRACKS_IMAGE_NOT_LOADED;
1521 barracks_init_stats(&Cur_pilot->stats);
1523 // disable some buttons for the multiplayer beta and e3 build
1524 #if defined(MULTIPLAYER_BETA_BUILD) || defined(E3_BUILD) || defined(PRESS_TOUR_BUILD)
1525 Buttons[gr_screen.res][B_PILOT_CLONE_BUTTON].button.hide();
1526 Buttons[gr_screen.res][B_PILOT_CONVERT_BUTTON].button.hide();
1527 Buttons[gr_screen.res][B_PILOT_CLONE_BUTTON].button.disable();
1528 Buttons[gr_screen.res][B_PILOT_CONVERT_BUTTON].button.disable();
1531 // multiplayer beta build
1532 #ifdef MULTIPLAYER_BETA_BUILD
1533 Buttons[gr_screen.res][B_PILOT_SINGLE_MODE_BUTTON].button.hide();
1534 Buttons[gr_screen.res][B_PILOT_SINGLE_MODE_BUTTON].button.disable();
1538 #if defined(E3_BUILD) || defined(PRESS_TOUR_BUILD)
1539 Buttons[gr_screen.res][B_PILOT_MULTI_MODE_BUTTON].button.hide();
1540 Buttons[gr_screen.res][B_PILOT_MULTI_MODE_BUTTON].button.disable();
1543 // base the mode we're in (single or multi) on the status of the currently selected pilot
1544 #ifdef MULTIPLAYER_BETA_BUILD
1545 barracks_init_player_stuff(1);
1546 #elif defined(E3_BUILD) || defined(PRESS_TOUR_BUILD)
1547 barracks_init_player_stuff(0);
1549 barracks_init_player_stuff(is_pilot_multi(Player));
1552 #if defined(MAKE_FS1) && !defined(FS1_DEMO)
1553 PilotWin01 = bm_load(NOX("PilotWin01"));
1554 PilotWin02 = bm_load(NOX("PilotWin02"));
1555 PilotWin03 = bm_load(NOX("PilotWin03"));
1556 PilotWin04 = bm_load(NOX("PilotWin04"));
1560 // -----------------------------------------------------------------------------
1561 void barracks_do_frame(float frametime)
1563 int k = Ui_window.process();
1566 if ( help_overlay_active(BARRACKS_OVERLAY) ) {
1567 help_overlay_set_state(BARRACKS_OVERLAY,0);
1572 // pilot that mouse is over
1573 int prospective_pilot = -1;
1576 // Entering pilot callsign
1577 if (Barracks_callsign_enter_mode) {
1578 // set focus to inputbox
1579 Inputbox.set_focus();
1583 // cancel create pilot
1585 for (i=0; i<Num_pilots; i++) {
1586 SDL_strlcpy(Pilots[i], Pilots[i + 1], MAX_FILENAME_LEN);
1587 Pilot_ranks[i] = Pilot_ranks[i + 1];
1590 barracks_set_callsign_enter_mode(false);
1594 barracks_accept_new_pilot_callsign();
1598 // not entering pilot callsign
1601 if (barracks_new_pilot_selected()) {
1602 gamesnd_play_iface(SND_GENERAL_FAIL);
1604 gamesnd_play_iface(SND_USER_SELECT);
1608 case SDLK_ESCAPE: // cancel
1609 if (!help_overlay_active(BARRACKS_OVERLAY)) {
1610 if (Num_pilots && !barracks_pilot_accepted()) {
1611 gameseq_post_event(GS_EVENT_MAIN_MENU);
1613 gamesnd_play_iface(SND_GENERAL_FAIL);
1617 help_overlay_set_state(BARRACKS_OVERLAY,0);
1621 case SDLK_TAB: // switch mode (simgle/multi)
1622 #if defined(DEMO) || defined(OEM_BUILD) // not for FS2_DEMO
1623 game_feature_not_in_demo_popup();
1625 if (Player_sel_mode == PLAYER_SELECT_MODE_SINGLE) {
1626 barracks_init_player_stuff(PLAYER_SELECT_MODE_MULTI);
1628 barracks_init_player_stuff(PLAYER_SELECT_MODE_SINGLE);
1631 gamesnd_play_iface(SND_USER_SELECT);
1635 case SDLK_F1: // show help overlay
1636 gamesnd_play_iface(SND_HELP_PRESSED);
1639 case SDLK_F2: // goto options screen
1640 gamesnd_play_iface(SND_SWITCH_SCREENS);
1641 gameseq_post_event(GS_EVENT_OPTIONS_MENU);
1646 for (i=0; i<BARRACKS_NUM_BUTTONS; i++) {
1647 if (Buttons[gr_screen.res][i].button.pressed()) {
1648 barracks_button_pressed(i);
1652 // if mouse is over a pilot, find index into Pilots array
1653 if (List_region.is_mouse_on()) {
1655 List_region.get_mouse_pos(NULL, &y);
1656 int pilot_index = List_scroll_offset + (y / gr_get_font_height());
1657 if ((pilot_index >= 0) && (pilot_index < Num_pilots)) {
1658 prospective_pilot = pilot_index;
1662 // if mouse clicked in list region, find index into Pilots array
1663 if (List_region.pressed()) {
1664 if (prospective_pilot != -1) {
1665 Selected_line = prospective_pilot;
1666 gamesnd_play_iface(SND_USER_SELECT);
1671 // check mouse over help
1672 if (mouse_down(MOUSE_LEFT_BUTTON)) {
1673 help_overlay_set_state(BARRACKS_OVERLAY, 0);
1676 // do pilot pic stuff
1677 if ((Pic_number >= 0) && (Pic_number < Num_pilot_images)) {
1678 if (Pilot_images[Pic_number] == BARRACKS_IMAGE_NOT_LOADED) { // haven't tried loading it yet
1679 Pilot_images[Pic_number] = bm_load(Pilot_image_names[Pic_number]);
1680 if (Pilot_images[Pic_number] >= 0) {
1683 bm_get_info(Pilot_images[Pic_number], &w, &h, NULL);
1684 // check for invalid pilot pic file
1685 if ((w != PLAYER_PILOT_PIC_W) || (h != PLAYER_PILOT_PIC_H)) {
1686 bm_unload(Pilot_images[Pic_number]);
1687 Pilot_images[Pic_number] = -1;
1695 // do squad pic stuff
1696 if ((Pic_squad_number >= 0) && (Pic_squad_number < Num_pilot_squad_images)) {
1697 if (Pilot_squad_images[Pic_squad_number] == BARRACKS_IMAGE_NOT_LOADED) { // haven't tried loading it yet
1698 Pilot_squad_images[Pic_squad_number] = bm_load_duplicate(Pilot_squad_image_names[Pic_squad_number]);
1699 if (Pilot_squad_images[Pic_squad_number] >= 0) {
1702 bm_get_info(Pilot_squad_images[Pic_squad_number], &w, &h, NULL);
1703 // check for invalid pilot pic file
1704 if ((w != PLAYER_SQUAD_PIC_W) || (h != PLAYER_SQUAD_PIC_H)) {
1705 bm_unload(Pilot_squad_images[Pic_squad_number]);
1706 Pilot_squad_images[Pic_squad_number] = -1;
1711 Pic_squad_number = -1;
1714 // draw the background, etc
1716 GR_MAYBE_CLEAR_RES(Background_bitmap);
1717 if (Background_bitmap >= 0) {
1718 gr_set_bitmap(Background_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1722 // draw pilot image and clean up afterwards
1723 barracks_draw_pilot_pic();
1724 barracks_draw_squad_pic();
1726 #if defined(MAKE_FS1) && !defined(FS1_DEMO)
1727 if (PilotWin01 != -1) {
1728 gr_set_bitmap(PilotWin01, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1732 if (PilotWin02 != -1) {
1733 gr_set_bitmap(PilotWin02, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1737 if (PilotWin03 != -1) {
1738 gr_set_bitmap(PilotWin03, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1739 gr_bitmap(447, 137);
1742 if (PilotWin04 != -1) {
1743 gr_set_bitmap(PilotWin04, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1752 // light up the correct mode button (single or multi)
1753 if (Player_sel_mode == PLAYER_SELECT_MODE_SINGLE) {
1754 Buttons[gr_screen.res][B_PILOT_SINGLE_MODE_BUTTON].button.draw_forced(2);
1756 Buttons[gr_screen.res][B_PILOT_MULTI_MODE_BUTTON].button.draw_forced(2);
1759 // write out pilot call signs
1760 barracks_display_pilot_callsigns(prospective_pilot);
1762 // write out current pilot stats
1763 barracks_display_pilot_stats();
1765 // blit help overlay if active
1766 help_overlay_maybe_blit(BARRACKS_OVERLAY);
1772 // -----------------------------------------------------------------------------
1773 void barracks_close()
1775 #if defined(MAKE_FS1) && !defined(FS1_DEMO)
1776 if (PilotWin01 != -1){
1777 bm_unload(PilotWin01);
1780 if (PilotWin02 != -1){
1781 bm_unload(PilotWin02);
1784 if (PilotWin03 != -1){
1785 bm_unload(PilotWin03);
1788 if (PilotWin04 != -1){
1789 bm_unload(PilotWin04);
1795 Ui_window.destroy();
1797 // release background bitmap
1798 if (Background_bitmap >= 0) {
1799 bm_unload(Background_bitmap);
1802 // release rank pip bitmaps
1803 for (int i=0; i<Rank_pips_count; i++) {
1804 bm_release(Rank_pips_bitmaps + i);
1807 // release pilot pic bitmaps
1808 for (int i=0; i<Num_pilot_images; i++) {
1809 if (Pilot_images[i] >= 0) {
1810 bm_unload(Pilot_images[i]);
1814 // unload the overlay bitmap
1815 help_overlay_unload(BARRACKS_OVERLAY);