]> icculus.org git repositories - taylor/freespace2.git/blob - src/menuui/barracks.cpp
disable multi in FS2 demo with emscripten for now
[taylor/freespace2.git] / src / menuui / barracks.cpp
1 /*
2  * Copyright (C) Volition, Inc. 1999.  All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell 
5  * or otherwise commercially exploit the source or things you created based on
6  * the source.
7  */
8
9 /*
10  * $Logfile: /Freespace2/code/MenuUI/Barracks.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * C file for implementing barracks section
16  *
17  * $Log$
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
24  *
25  * Revision 1.5  2004/09/20 01:31:44  theoddone33
26  * GCC 3.4 fixes.
27  *
28  * Revision 1.4  2003/05/25 02:30:42  taylor
29  * Freespace 1 support
30  *
31  * Revision 1.3  2002/06/09 04:41:22  relnev
32  * added copyright header
33  *
34  * Revision 1.2  2002/05/07 03:16:46  theoddone33
35  * The Great Newline Fix
36  *
37  * Revision 1.1.1.1  2002/05/03 03:28:09  root
38  * Initial import.
39  *
40  * 
41  * 42    10/25/99 5:47p Jefff
42  * reassigned some xstr ids
43  * 
44  * 41    9/14/99 11:01p Jefff
45  * stats area coord fix
46  * 
47  * 40    9/09/99 11:24a Jefff
48  * 
49  * 39    9/02/99 11:26a Jefff
50  * fixed incorrect pilot list dimensions
51  * 
52  * 38    8/17/99 2:24p Dave
53  * Fixed wacky squad color stuff.
54  * 
55  * 37    8/16/99 4:27p Jefff
56  * fix button position on squad change error popup
57  * 
58  * 36    8/11/99 3:58p Jefff
59  * fixed player list box coord bug
60  * 
61  * 35    8/05/99 2:46p Jefff
62  * added popup to the disabled squad selection buttons in single player
63  * 
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.
67  * 
68  * 33    7/27/99 7:17p Jefff
69  * Replaced some art text with XSTR() text.
70  * 
71  * 32    7/15/99 9:20a Andsager
72  * FS2_DEMO initial checkin
73  * 
74  * 31    6/29/99 7:39p Dave
75  * Lots of small bug fixes.
76  * 
77  * 30    6/16/99 4:06p Dave
78  * New pilot info popup. Added new draw-bitmap-as-poly function.
79  * 
80  * 29    6/11/99 11:13a Dave
81  * last minute changes before press tour build.
82  * 
83  * 28    4/25/99 7:43p Dave
84  * Misc small bug fixes. Made sun draw properly.
85  * 
86  * 27    4/25/99 3:02p Dave
87  * Build defines for the E3 build.
88  * 
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.
93  * 
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
97  * response packets.
98  * 
99  * 24    2/02/99 12:09p Neilk
100  * Fixed text coords, centered pilot and squad pics in 1024x768, added vss
101  * comment template
102  *
103  * $NoKeywords: $
104  */
105
106 #include "barracks.h"
107 #include "managepilot.h"
108 #include "ui.h"
109 #include "font.h"
110 #include "key.h"
111 #include "gamesnd.h"
112 #include "osapi.h"
113 #include "popup.h"
114 #include "playermenu.h"
115 #include "gamesequence.h"
116 #include "contexthelp.h"
117 #include "2d.h"
118 #include "ctype.h"
119 #include "freespace.h"
120 #include "systemvars.h"
121 #include "bmpman.h"
122 #include "mouse.h"
123 #include "osregistry.h"
124 #include "alphacolors.h"
125
126 void delete_pilot_file( const char *pilot_name, int single );           // manage_pilot.cpp
127
128 // stats defines
129 #define NUM_STAT_LINES 85
130 #define STAT_COLUMN1_W 40
131 #define STAT_COLUMN2_W 10
132
133 static int Stat_column1_w[GR_NUM_RESOLUTIONS] =
134 {
135         40,             // GR_640
136         40                      // GR_1024
137 };
138
139 static int Stat_column2_w[GR_NUM_RESOLUTIONS] =
140 {
141         10,             // GR_640
142         10                      // GR_1024
143 };
144
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
150
151 // area ints
152
153 // pilot selection field
154 static int Barracks_list_coords[GR_NUM_RESOLUTIONS][4] = {
155         { // GR_640
156 #ifdef MAKE_FS1
157                 58, 42, 400, 105
158 #else
159                 42, 34, 400, 90
160 #endif
161         },
162         { // GR_1024
163                 45, 51, 646, 144
164         }
165 };
166
167 // pilot stats field
168 static int Barracks_stats_coords[GR_NUM_RESOLUTIONS][4] = {
169         { // GR_640
170 #ifdef MAKE_FS1
171                 35, 215, 240, 250
172 #else
173                 32, 212, 240, 250
174 #endif
175         },
176         { // GR_1024
177                 42, 351, 240, 400
178         }
179 };
180
181 static int Barracks_stats2_coords[GR_NUM_RESOLUTIONS][3] = {
182         { // GR_640
183                 276, 212, 81            // X2, , W2
184         },
185         { // GR_1024
186                 286, 351, 81            // X2, , W2
187         }
188 };
189
190 // pilot picture field
191 static int Barracks_image_coords[GR_NUM_RESOLUTIONS][4] = {
192         { // GR_640
193 #ifdef MAKE_FS1
194                 460, 33, 160, 120
195 #else
196                 461, 23, 160, 120
197 #endif
198         },
199         { // GR_1024
200                 782, 58, 160, 120
201         }
202 };
203
204 // pilot picture # of # location
205 static int Barracks_image_number_coords[GR_NUM_RESOLUTIONS][2] = {
206         { // GR_640
207 #ifdef MAKE_FS1
208 #ifndef FS1_DEMO
209                 489, 171
210 #else
211                 489, 183
212 #endif  // FS1_DEMO
213 #else
214                 461, 145
215 #endif
216         },
217         { // GR_1024
218                 732, 239
219         }
220 };
221
222 // pilot squad logo field
223 int Barracks_squad_coords[GR_NUM_RESOLUTIONS][4] = {
224         { // GR_640
225                 495, 177, 128, 128
226         },
227         { // GR_1024
228                 829, 323, 128, 128
229         }
230 };
231
232 // pilot squad # of # location
233 int Barracks_squad_number_coords[GR_NUM_RESOLUTIONS][2] = {
234         { // GR_640
235                 492, 307
236         },
237         { // GR_1024
238                 794, 500
239         }
240 };
241
242 // button defines
243 #ifdef MAKE_FS1
244         #define BARRACKS_NUM_BUTTONS            17
245 #else
246         #define BARRACKS_NUM_BUTTONS            19
247 #endif
248
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
259
260 #ifndef MAKE_FS1
261 // squad logo picture buttons
262 #define B_SQUAD_PREV_BUTTON                     17
263 #define B_SQUAD_NEXT_BUTTON                     18
264 #endif
265
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
269
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
274
275 // general buttons
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
279
280 //XSTR:OFF
281 // bitmaps defs
282 static const char *Barracks_bitmap_fname[GR_NUM_RESOLUTIONS] = {
283         "Barracks",             // GR_640
284         "2_Barracks"            // GR_1024
285 };
286
287 static const char *Barracks_bitmap_mask_fname[GR_NUM_RESOLUTIONS] = {
288         "Barracks-M",           // GR_640
289         "2_Barracks-M"          // GR_1024
290 };
291
292 //XSTR:ON
293
294 #define BARRACKS_IMAGE_NOT_LOADED       -2
295
296 struct barracks_bitmaps {
297         const char *filename;
298         int x, y;
299         int b;
300 };
301
302 struct barracks_buttons {
303         const char *filename;
304         int x, y;
305         int text_x, text_y;     // this is where the text label is
306         int hotspot;
307         int repeat;
308         UI_BUTTON button;  // because we have a class inside this struct, we need the constructor below..
309
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) {}
311 };
312
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;
319 #else
320 static int Background_bitmap = -1;
321 #endif
322 static UI_WINDOW Ui_window;
323 static UI_BUTTON List_region;
324 static UI_INPUTBOX Inputbox;
325
326 static barracks_buttons Buttons[GR_NUM_RESOLUTIONS][BARRACKS_NUM_BUTTONS] = {
327 //XSTR:OFF
328         {               // GR_640
329 #ifdef MAKE_FS1
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
333 #ifndef FS1_DEMO
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
336 #else
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
339 #endif
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
352 #else
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)
372 #endif
373         },
374         {               // GR_1024
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),
392 #ifndef MAKE_FS1
393                         barracks_buttons("2_BAB_17", 896,       491,    0,              0,              17),
394                         barracks_buttons("2_BAB_18", 958,       491,    0,              0,              18)
395 #endif
396         }
397 //XSTR:ON
398 };
399
400
401 // FIXME add to strings.tbl, set correct coords
402 #ifndef MAKE_FS1
403 #define BARRACKS_NUM_TEXT                       2
404
405 UI_XSTR Barracks_text[GR_NUM_RESOLUTIONS][BARRACKS_NUM_TEXT] = {
406         { 
407                 // GR_640
408                 { "Barracks",                   1434,           17, 7,          UI_XSTR_COLOR_GREEN, -1, NULL },
409                 { "Pilot Stats",                1435,           17, 180,                UI_XSTR_COLOR_GREEN, -1, NULL }
410         }, 
411         { 
412                 // GR_1024
413                 { "Barracks",                   1434,           27, 11,         UI_XSTR_COLOR_GREEN, -1, NULL },
414                 { "Pilot Stats",                1435,           27, 288,                UI_XSTR_COLOR_GREEN, -1, NULL }
415         }
416 };
417 #endif
418
419
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];
423
424 extern int Player_sel_mode;
425
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;
442
443 void barracks_squad_change_popup();
444
445
446 // -------------------------------------------------------------------------------------------------
447 //
448 // BARRACKS screen
449 //
450
451 void barracks_init_stats(scoring_struct *stats)
452 {
453         int i;
454         float f;
455
456         Num_stat_lines = 0;
457
458         SDL_strlcpy(Stat_labels[Num_stat_lines], XSTR( "*All Time Stats", 50), STAT_COLUMN1_W);
459         Stats[Num_stat_lines][0] = 0;
460         Num_stat_lines++;
461
462         SDL_assert(Num_stat_lines < NUM_STAT_LINES);
463         Stat_labels[Num_stat_lines][0] = 0;
464         Stats[Num_stat_lines][0] = 0;
465         Num_stat_lines++;       
466
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);
470         Num_stat_lines++;
471
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);
475         Num_stat_lines++;
476
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);
480         Num_stat_lines++;
481
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;
486         } else {
487                 f = 0.0f;
488         }
489         SDL_snprintf(Stats[Num_stat_lines], STAT_COLUMN2_W, XSTR( "%.1f%%", 55), f);
490         Num_stat_lines++;
491
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;
496         } else {
497                 f = 0.0f;
498         }
499         SDL_snprintf(Stats[Num_stat_lines], STAT_COLUMN2_W, XSTR( "%.1f%%", 55), f);
500         Num_stat_lines++;
501
502         SDL_assert(Num_stat_lines < NUM_STAT_LINES);
503         Stat_labels[Num_stat_lines][0] = 0;
504         Stats[Num_stat_lines][0] = 0;
505         Num_stat_lines++;
506
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);
510         Num_stat_lines++;
511
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);
515         Num_stat_lines++;
516
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);
520         Num_stat_lines++;
521
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;
526         } else {
527                 f = 0.0f;
528         }
529         SDL_snprintf(Stats[Num_stat_lines], STAT_COLUMN2_W, XSTR( "%.1f%%", 55), f);
530         Num_stat_lines++;
531
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;
536         } else {
537                 f = 0.0f;
538         }
539         SDL_snprintf(Stats[Num_stat_lines], STAT_COLUMN2_W, XSTR( "%.1f%%", 55), f);
540         Num_stat_lines++;
541
542         SDL_assert(Num_stat_lines < NUM_STAT_LINES);
543         Stat_labels[Num_stat_lines][0] = 0;
544         Stats[Num_stat_lines][0] = 0;
545         Num_stat_lines++;
546
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);
550         Num_stat_lines++;
551
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);
555         Num_stat_lines++;
556
557         SDL_assert(Num_stat_lines < NUM_STAT_LINES);
558         Stat_labels[Num_stat_lines][0] = 0;
559         Stats[Num_stat_lines][0] = 0;
560         Num_stat_lines++;
561
562         SDL_assert(Num_stat_lines < NUM_STAT_LINES);
563         Stat_labels[Num_stat_lines][0] = 0;
564         Stats[Num_stat_lines][0] = 0;
565         Num_stat_lines++;
566
567         SDL_strlcpy(Stat_labels[Num_stat_lines], XSTR( "*Kills by Ship Type", 64), STAT_COLUMN1_W);
568         Stats[Num_stat_lines][0] = 0;
569         Num_stat_lines++;
570
571         SDL_assert(Num_stat_lines < NUM_STAT_LINES);
572         Stat_labels[Num_stat_lines][0] = 0;
573         Stats[Num_stat_lines][0] = 0;
574         Num_stat_lines++;
575
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]);
582                         Num_stat_lines++;
583                 }
584         }
585
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]);
589         }
590 }
591
592 // sets or clears hotkeys for pilot selection.
593 void barracks_set_hotkeys(bool pilot_text_enter_mode)
594 {
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);
597
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);
601
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);
604
605         Buttons[gr_screen.res][B_ACCEPT_BUTTON].button.set_hotkey(pilot_text_enter_mode ? KEY_CTRLED | SDLK_RETURN : -1);
606 }
607
608 // strip the possible .pcx extension off a filename
609 void barracks_strip_pcx(char *str)
610 {
611         int flen = strlen(str);
612         int elen = 4;           
613         if ((flen > 4) && !SDL_strcasecmp(str + flen - elen, ".pcx")) {
614                 str[flen - elen] = '\0';
615         }
616 }
617
618 // new pilot name has focus, so update stats/pic to that pilot
619 int barracks_new_pilot_selected()
620 {
621         char stripped[MAX_FILENAME_LEN+1] = "";
622
623         // save the previous pilot first, so changes to it are kept
624         if (strlen(Cur_pilot->callsign)) {
625                 write_pilot_file();
626         }
627
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
631                 return -1;
632         }
633
634         if (read_pilot_file(Pilots[Selected_line], !Player_sel_mode, Cur_pilot)) {
635                 Cur_pilot->callsign[0] = 0;  // this indicates no pilot active
636                 return -1;
637         }
638
639         // init stuff to reflect new pilot
640         int i;
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])) {
646                         break;
647                 }
648         }
649         Pic_number = 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])) {
654                         break;
655                 }
656         }
657         Pic_squad_number = i;   
658         
659         return 0;
660 }
661
662 void barracks_set_callsign_enter_mode(bool set_callsign_enter_mode)
663 {
664         // set global mode variable
665         Barracks_callsign_enter_mode = set_callsign_enter_mode;
666
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
670 #ifdef MAKE_FS1
671                 Buttons[gr_screen.res][idx].button.enable(!set_callsign_enter_mode);
672 #else
673                 if((idx != B_SQUAD_PREV_BUTTON) && (idx != B_SQUAD_NEXT_BUTTON)){
674                         Buttons[gr_screen.res][idx].button.enable(!set_callsign_enter_mode);
675                 }
676 #endif
677         }
678
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);
685 }
686
687 // creates a new pilot file
688 void barracks_create_new_pilot()
689 {
690         // check if too many pilots
691         if (Num_pilots >= MAX_PILOTS) {
692                 gamesnd_play_iface(SND_GENERAL_FAIL);
693                 return;
694         }
695
696         // play sound for pilot creation
697         gamesnd_play_iface(SND_SCROLL);
698         
699         // only write pilot file if there is an active pilot
700         if (strlen(Player->callsign)) {
701                 write_pilot_file();
702         }
703
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);
707         while (idx--) {
708                 SDL_strlcpy(Pilots[idx + 1], Pilots[idx], MAX_FILENAME_LEN);
709                 Pilot_ranks[idx + 1] = Pilot_ranks[idx];
710         }
711
712         Selected_line = 0;
713         Num_pilots++;
714         Pilots[Selected_line][0] = 0;
715         Pilot_ranks[Selected_line] = 0;
716         List_scroll_offset = 0;
717
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());
726 }
727
728 // exiting screen without canceling, so load in the new pilot selected here
729 int barracks_pilot_accepted()
730 {
731         char str[CALLSIGN_LEN + 1];
732
733         // check if pilot active.  If not, don't allow accept.
734         if (!Cur_pilot->callsign[0]){
735                 return -1;
736         }
737
738         // set his image 
739         player_set_squad_bitmap(Cur_pilot, Cur_pilot->squad_filename);
740
741 //      Skill_level = get_default_skill_level();
742
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 );
746         
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 );
753         return 0;
754 }
755
756 // scroll up barracks pilot list one line
757 void barracks_scroll_callsign_up()
758 {
759         if (Selected_line > 0) {
760                 Selected_line--;
761                 gamesnd_play_iface(SND_SCROLL);
762         } else {
763                 gamesnd_play_iface(SND_GENERAL_FAIL);
764         }
765         
766         if ((Selected_line >= 0) && (Selected_line < List_scroll_offset)) {
767                 List_scroll_offset = Selected_line;
768         }
769 }
770
771 // scroll down barracks pilot list one line
772 void barracks_scroll_callsign_down()
773 {
774         if (Selected_line < Num_pilots - 1) {
775                 Selected_line++;
776                 gamesnd_play_iface(SND_SCROLL);
777         } else {
778                 gamesnd_play_iface(SND_GENERAL_FAIL);
779         }
780         
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++;
785         }
786 }
787
788 // scroll up barracks stats list one line
789 void barracks_scroll_stats_up()
790 {
791         if (Stats_scroll_offset > 0) {
792                 Stats_scroll_offset--;
793                 gamesnd_play_iface(SND_SCROLL);
794         } else {
795                 gamesnd_play_iface(SND_GENERAL_FAIL);
796         }
797 }
798
799 // scroll down barracks stats list one line
800 void barracks_scroll_stats_down()
801 {
802         int font_height = gr_get_font_height();
803
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);
807         } else {
808                 gamesnd_play_iface(SND_GENERAL_FAIL);
809         }
810 }
811
812 // show previous pilot pic
813 void barracks_prev_pic()
814 {
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);
818                 return;
819         }
820
821         // reset pilot pic number
822         Pic_number--;
823         if (Pic_number < 0) {
824                 Pic_number = Num_pilot_images - 1;
825         }
826
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));
830         }
831
832         // play scroll sound
833         gamesnd_play_iface(SND_SCROLL);
834 }
835
836 // show next pilot pic
837 void barracks_next_pic()
838 {
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);
842                 return;
843         }
844
845         // reset pilot pic number
846         Pic_number++;
847         if (Pic_number >= Num_pilot_images){
848                 Pic_number = 0;
849         }
850
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));
854         }
855
856         // play scroll sound
857         gamesnd_play_iface(SND_SCROLL);
858 }
859
860 // show previous squad pic
861 void barracks_prev_squad_pic()
862 {
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);
866                 return;
867         }
868
869         // reset pilot pic number
870         Pic_squad_number--;
871         if (Pic_squad_number < 0) {
872                 Pic_squad_number = Num_pilot_squad_images - 1;
873         }
874
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));
878         }
879
880         // play scroll sound
881         gamesnd_play_iface(SND_SCROLL);
882 }
883
884 // show next pilot pic
885 void barracks_next_squad_pic()
886 {
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);
890                 return;
891         }
892
893         // reset pilot pic number
894         Pic_squad_number++;
895         if (Pic_squad_number >= Num_pilot_squad_images){
896                 Pic_squad_number = 0;
897         }
898
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));
902         }
903
904         // play scroll sound
905         gamesnd_play_iface(SND_SCROLL);
906 }
907
908 static void barracks_delete_pilot_callback(int choice)
909 {
910         char buf[MAX_FILENAME_LEN];
911         int active = 0;
912
913         popup_done();
914
915         if (choice != 1) {
916                 return;
917         }
918
919         if (!SDL_strcasecmp(Pilots[Selected_line], Cur_pilot->callsign)) {
920                 active = 1;
921         }
922
923         SDL_strlcpy(buf, Pilots[Selected_line], SDL_arraysize(buf));
924         for (int i=Selected_line; i<Num_pilots-1; i++) {
925                 SDL_strlcpy(Pilots[i], Pilots[i + 1], MAX_FILENAME_LEN);
926                 Pilot_ranks[i] = Pilot_ranks[i + 1];
927         }
928
929         Num_pilots--;
930         if (Selected_line >= Num_pilots) {
931                 Selected_line = Num_pilots - 1;
932         }
933
934         if (active) {
935                 if (Selected_line >= 0) {
936                         barracks_new_pilot_selected();
937                 } else {
938                         Cur_pilot->callsign[0] = 0;
939                 }
940         }
941
942         delete_pilot_file(buf, Player_sel_mode == PLAYER_SELECT_MODE_SINGLE ? 1 : 0);
943         gamesnd_play_iface(SND_USER_SELECT);
944 }
945
946 void barracks_delete_pilot()
947 {
948         if (!Num_pilots) {
949                 gamesnd_play_iface(SND_GENERAL_FAIL);
950                 return;
951         }
952
953         popup_callback(barracks_delete_pilot_callback, PF_TITLE_BIG | PF_TITLE_RED, 2, POPUP_NO, POPUP_YES, XSTR( "Warning!\n\nAre you sure you wish to delete this pilot?", 65));
954 }
955
956 // Filter out pilots of wrong type (which shouldn't be in the directory we are checking, but just to be safe..)
957 int barracks_pilot_filter(const char *filename)
958 {
959         int r, rank;
960
961         r = verify_pilot_file(filename, Player_sel_mode == PLAYER_SELECT_MODE_SINGLE, &rank);
962         if (rank >= Rank_pips_count)
963                 rank = Rank_pips_count - 1;
964
965         if (!r) {
966                 Pilot_ranks[Num_pilots++] = rank;
967         }
968
969         return !r;
970 }
971
972 // callback handler for the squadon selection buttons when they are disabled (in single player)
973 void barracks_squad_change_popup()
974 {
975         // show a popup
976         popup(PF_USE_AFFIRMATIVE_ICON | PF_NO_NETWORKING, 1, POPUP_OK, XSTR("You cannot change your squadron in Single Player mode.", 1445));
977 }
978
979
980 void barracks_init_player_stuff(int mode)
981 {
982         // determine if we should be looking for single or multiplayers at the outset
983         Player_sel_mode = mode;
984         
985         // get the list of pilots based upon whether we're in single or multiplayer mode
986         Num_pilots = 0;
987         Get_file_list_filter = barracks_pilot_filter;
988
989         // single player specific stuff
990         if (mode == PLAYER_SELECT_MODE_SINGLE) {
991                 Num_pilots = cf_get_file_list_preallocated(MAX_PILOTS, Pilots_arr, Pilots, CF_TYPE_SINGLE_PLAYERS, NOX("*.plr"), CF_SORT_TIME);
992
993 #ifndef MAKE_FS1
994                 // disable squad logo switching         
995                 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.hide();
996                 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.disable();
997                 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.set_disabled_action(barracks_squad_change_popup);
998                 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.hide();
999                 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.disable();                   
1000                 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.set_disabled_action(barracks_squad_change_popup);
1001 #endif
1002         }
1003         // multiplayer specific stuff
1004         else {
1005                 Num_pilots = cf_get_file_list_preallocated(MAX_PILOTS, Pilots_arr, Pilots, CF_TYPE_MULTI_PLAYERS, NOX("*.plr"), CF_SORT_TIME);
1006
1007 #ifndef MAKE_FS1
1008                 // enable squad logo switching
1009                 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.enable();
1010                 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.unhide();
1011                 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.enable();
1012                 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.unhide();                    
1013 #endif
1014         }
1015
1016         int ranks[MAX_PILOTS];
1017
1018         SDL_zero(ranks);
1019
1020         for (int i=0; i<Num_pilots; i++) {
1021                 int j;
1022                 for (j=0; j<Num_pilots; j++) {
1023                         if (!strcmp(Pilots[i], Pilots_arr[j])) {
1024                                 ranks[i] = Pilot_ranks[j];
1025                                 break;
1026                         }
1027                 }
1028                 SDL_assert(j < Num_pilots);  // Pilot not found?  How is that possible?
1029         }
1030
1031         for (int i=0; i<Num_pilots; i++) {
1032                 Pilot_ranks[i] = ranks[i];
1033         }
1034
1035         Selected_line = List_scroll_offset = 0;
1036         barracks_new_pilot_selected();
1037
1038 }
1039
1040 #if !(defined(DEMO) || defined(OEM_BUILD) || defined(__EMSCRIPTEN__))
1041 static void barracks_convert_pilot_callback(int choice)
1042 {
1043         char old_pic[256] = "";
1044         char old_squad_pic[256] = "";
1045         char old_squad[256] = "";
1046
1047         popup_done();
1048
1049         if (choice != 1) {
1050                 return;
1051         }
1052
1053         SDL_strlcpy(old_pic, Cur_pilot->image_filename, SDL_arraysize(old_pic));
1054         SDL_strlcpy(old_squad_pic, Cur_pilot->squad_filename, SDL_arraysize(old_squad_pic));
1055         SDL_strlcpy(old_squad, Cur_pilot->squad_name, SDL_arraysize(old_squad));
1056         init_new_pilot(Cur_pilot, 0);
1057         SDL_strlcpy(Cur_pilot->image_filename, old_pic, SDL_arraysize(Cur_pilot->image_filename));
1058         SDL_strlcpy(Cur_pilot->squad_filename, old_squad_pic, SDL_arraysize(Cur_pilot->squad_filename));
1059         SDL_strlcpy(Cur_pilot->squad_name, old_squad, SDL_arraysize(Cur_pilot->squad_name));
1060         if (Player_sel_mode == PLAYER_SELECT_MODE_SINGLE) {
1061                 Cur_pilot->flags |= PLAYER_FLAGS_IS_MULTI;
1062                 write_pilot_file();
1063                 barracks_init_player_stuff(PLAYER_SELECT_MODE_MULTI);
1064
1065         } else {
1066                 write_pilot_file();
1067                 barracks_init_player_stuff(PLAYER_SELECT_MODE_SINGLE);
1068         }
1069
1070         gamesnd_play_iface(SND_USER_SELECT);
1071 }
1072 #endif
1073
1074 void barracks_button_pressed(int n)
1075 {
1076         switch (n) {
1077                 case B_PILOT_SCROLL_UP_BUTTON:
1078                         barracks_scroll_callsign_up();
1079                         break;
1080
1081                 case B_PILOT_SCROLL_DOWN_BUTTON:
1082                         barracks_scroll_callsign_down();
1083                         break;
1084
1085                 case B_STATS_SCROLL_UP_BUTTON:
1086                         barracks_scroll_stats_up();
1087                         break;
1088
1089                 case B_STATS_SCROLL_DOWN_BUTTON:
1090                         barracks_scroll_stats_down();
1091                         break;
1092
1093                 case B_PIC_PREV_PILOT_BUTTON:
1094                         barracks_prev_pic();
1095                         break;
1096
1097                 case B_PIC_NEXT_PILOT_BUTTON:
1098                         barracks_next_pic();
1099                         break;
1100
1101 #ifndef MAKE_FS1
1102                 case B_SQUAD_PREV_BUTTON:
1103                         barracks_prev_squad_pic();
1104                         break;
1105
1106                 case B_SQUAD_NEXT_BUTTON:
1107                         barracks_next_squad_pic();
1108                         break;
1109 #endif
1110
1111                 case B_PILOT_SET_ACTIVE_BUTTON:
1112                         if (barracks_new_pilot_selected()){
1113                                 gamesnd_play_iface(SND_GENERAL_FAIL);
1114                                 
1115                                 // throw up a popup telling the player that he should create a pilot first
1116                                 if(Player_sel_mode == PLAYER_SELECT_MODE_SINGLE){
1117                                         popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR( "You must create a single player pilot.", 66));
1118                                 } else {
1119                                         popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR( "You must create a multi player pilot.", 67));
1120                                 }
1121                         } else {
1122                                 gamesnd_play_iface(SND_SCROLL);
1123                         }
1124                         break;
1125
1126                 case B_ACCEPT_BUTTON:                   
1127                         if (Num_pilots && !barracks_pilot_accepted()) {
1128                                 gamesnd_play_iface(SND_COMMIT_PRESSED);
1129                                 gameseq_post_event(GS_EVENT_MAIN_MENU);
1130                         } else {
1131                                 gamesnd_play_iface(SND_GENERAL_FAIL);
1132
1133                                 // throw up a popup telling the player that he should create a pilot first
1134                                 if(Player_sel_mode == PLAYER_SELECT_MODE_SINGLE){
1135                                         popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR( "You must create a single player pilot.", 66));
1136                                 } else {
1137                                         popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR( "You must create a multi player pilot.", 67));
1138                                 }
1139                         }
1140                         break;
1141
1142                 case B_PILOT_CLONE_BUTTON:
1143                         if (Num_pilots < 1) {
1144                                 gamesnd_play_error_beep();
1145                                 break;
1146                         }
1147
1148                         Clone_flag = 1;
1149                         barracks_create_new_pilot();
1150                         break;
1151
1152                 case B_PILOT_CONVERT_BUTTON: {
1153 #if defined(DEMO) || defined(OEM_BUILD) || defined(__EMSCRIPTEN__)
1154                         game_feature_not_in_demo_popup();
1155 #else
1156                         const char *str;
1157                         char temp[256];
1158
1159                         if (!barracks_new_pilot_selected()) {
1160                                 if (Player_sel_mode == PLAYER_SELECT_MODE_SINGLE)
1161                                         str = XSTR( "multiplayer", 68);
1162                                 else
1163                                         str = XSTR( "single player", 69);
1164
1165                                 SDL_snprintf(temp, SDL_arraysize(temp), XSTR( "This will overwrite your %s pilot.  Proceed?", 70), str);
1166                                 if (!verify_pilot_file(Cur_pilot->callsign, Player_sel_mode == PLAYER_SELECT_MODE_MULTI)) {
1167                                         popup_callback(barracks_convert_pilot_callback, 0, 2, POPUP_CANCEL, POPUP_OK, temp);
1168                                 }
1169                         } else {
1170                                 gamesnd_play_iface(SND_GENERAL_FAIL);
1171                         }
1172 #endif
1173                         break;
1174                 }
1175
1176                 case B_PILOT_CREATE_BOTTON:
1177                         Clone_flag = 0;
1178                         barracks_create_new_pilot();
1179                         break;
1180
1181                 case B_HELP_BUTTON:
1182                         launch_context_help();
1183                         gamesnd_play_iface(SND_HELP_PRESSED);
1184                         break;
1185
1186                 case B_OPTION_BUTTON:
1187                         gamesnd_play_iface(SND_SWITCH_SCREENS);
1188                         gameseq_post_event(GS_EVENT_OPTIONS_MENU);
1189                         break;
1190
1191                 case B_STATS_MEDAL_BUTTON:
1192 #if defined(FS2_DEMO) || defined(FS1_DEMO)
1193                         game_feature_not_in_demo_popup();
1194 #else
1195                         gamesnd_play_iface(SND_SWITCH_SCREENS);
1196                         gameseq_post_event(GS_EVENT_VIEW_MEDALS);
1197 #endif
1198                         break;
1199
1200                 case B_PILOT_DELETE_BUTTON:
1201                         barracks_delete_pilot();
1202                         break;
1203
1204                 case B_PILOT_SINGLE_MODE_BUTTON:
1205                         if (Player_sel_mode != PLAYER_SELECT_MODE_SINGLE) {
1206                                 gamesnd_play_iface(SND_USER_SELECT);
1207                                 barracks_init_player_stuff(PLAYER_SELECT_MODE_SINGLE);
1208                         }                                               
1209                         break;
1210
1211                 case B_PILOT_MULTI_MODE_BUTTON:
1212 #if defined(DEMO) || defined(OEM_BUILD) || defined(__EMSCRIPTEN__) // not for FS2_DEMO
1213                         game_feature_not_in_demo_popup();
1214 #else
1215                         if (Player_sel_mode != PLAYER_SELECT_MODE_MULTI) {
1216                                 gamesnd_play_iface(SND_USER_SELECT);
1217                                 barracks_init_player_stuff(PLAYER_SELECT_MODE_MULTI);
1218                         }
1219 #endif
1220                         break;
1221         }
1222 }
1223
1224
1225 void barracks_display_pilot_callsigns(int prospective_pilot)
1226 {
1227         int y = 0;
1228         int cur_pilot_idx = List_scroll_offset;
1229
1230         int multi = 0;
1231         if (Player_sel_mode == PLAYER_SELECT_MODE_MULTI) {
1232                 multi = 1;
1233         }
1234
1235         int font_height = gr_get_font_height();
1236         while (y + font_height <= Barracks_list_coords[gr_screen.res][BARRACKS_H_COORD]) {
1237                 if (cur_pilot_idx >= Num_pilots)
1238                         break;
1239
1240                 if (!SDL_strcasecmp(Cur_pilot->callsign, Pilots[cur_pilot_idx]) && (is_pilot_multi(Cur_pilot) == multi)) {
1241                         if ((cur_pilot_idx == Selected_line) || (cur_pilot_idx == prospective_pilot)) {
1242                                 gr_set_color_fast(&Color_text_active_hi);
1243                         } else {
1244                                 gr_set_color_fast(&Color_text_active);
1245                         }
1246                 } else {
1247                         if (cur_pilot_idx == Selected_line) {
1248                                 gr_set_color_fast(&Color_text_selected);
1249                         } else if (cur_pilot_idx == prospective_pilot) {
1250                                 gr_set_color_fast(&Color_text_subselected);
1251                         } else {
1252                                 gr_set_color_fast(&Color_text_normal);
1253                         }
1254                 }
1255
1256                 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]);
1257 #ifndef FS1_DEMO
1258                 gr_set_bitmap(Rank_pips_bitmaps + Pilot_ranks[cur_pilot_idx], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1259                 gr_bitmap(Barracks_list_coords[gr_screen.res][BARRACKS_X_COORD] - 34, Barracks_list_coords[gr_screen.res][BARRACKS_Y_COORD] + y);
1260 #endif
1261  
1262                 y += font_height;
1263                 cur_pilot_idx++;
1264         }
1265 }
1266
1267
1268
1269 void barracks_display_pilot_stats()
1270 {
1271         int y = 0;
1272         int z = Stats_scroll_offset;
1273         int font_height = gr_get_font_height();
1274         char *str;
1275         int i, w, h;
1276         while (y + font_height <= Barracks_stats_coords[gr_screen.res][BARRACKS_H_COORD]) {
1277                 if (z >= Num_stat_lines) {
1278                         break;
1279                 }
1280
1281                 str = Stat_labels[z];
1282                 if (*str == '*') {
1283                         gr_set_color_fast(&Color_text_heading);
1284                         str++;
1285
1286                         gr_get_string_size(&w, &h, str);
1287                         i = Barracks_stats_coords[gr_screen.res][BARRACKS_Y_COORD] + y + h / 2 - 1;                     
1288                         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);
1289                         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);
1290
1291                 } else {
1292                         gr_set_color_fast(&Color_text_normal);
1293                 }
1294
1295                 gr_get_string_size(&w, NULL, str);
1296                 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);
1297                 str = Stats[z];
1298                 if (*str) {
1299                         gr_printf(Barracks_stats2_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_stats_coords[gr_screen.res][BARRACKS_Y_COORD] + y, "%s", str);
1300                 }
1301
1302                 y += font_height;
1303                 z++;
1304         }
1305 }
1306
1307
1308 // process pilot callsign
1309 void barracks_accept_new_pilot_callsign()
1310 {
1311         char buf[CALLSIGN_LEN + 1];
1312         char name[MAX_FILENAME_LEN];
1313         int i;
1314
1315         int z = 0;
1316         Inputbox.get_text(buf);
1317         drop_white_space(buf);
1318
1319         if (!isalpha(*buf)) {
1320                 z = 1;
1321         } else {
1322                 for (i=1; buf[i]; i++) {
1323                         if (!isalpha(buf[i]) && !isdigit(buf[i]) && !SDL_strchr(VALID_PILOT_CHARS, buf[i])) {
1324                                 return;
1325                         }
1326                 }
1327         }
1328
1329         for (i=1; i<Num_pilots; i++) {
1330                 if (!SDL_strcasecmp(buf, Pilots[i])) {
1331                         if (pilot_verify_overwrite() == 1) {
1332                                 SDL_strlcpy(name, Pilots[Selected_line], SDL_arraysize(name));
1333                                 for (z=i; z<Num_pilots-1; z++) {
1334                                         SDL_strlcpy(Pilots[z], Pilots[z + 1], MAX_FILENAME_LEN);
1335                                         Pilot_ranks[z] = Pilot_ranks[z + 1];
1336                                 }
1337
1338                                 Num_pilots--;
1339                                 delete_pilot_file(name, Player_sel_mode == PLAYER_SELECT_MODE_SINGLE ? 1 : 0);
1340                         }
1341                         return;
1342                 }
1343         }
1344
1345         if (!*buf || (i < Num_pilots)) { // duplicate name, alert user
1346                 z = 1;
1347         }
1348
1349         if (z) {
1350                 gamesnd_play_iface(SND_GENERAL_FAIL);
1351                 return;
1352         }
1353
1354         SDL_strlcpy(Pilots[0], buf, MAX_FILENAME_LEN);
1355         SDL_strlcpy(Cur_pilot->callsign, buf, SDL_arraysize(Cur_pilot->callsign));
1356         init_new_pilot(Cur_pilot, !Clone_flag);
1357         
1358         // again, make sure we set his flags correctly to ensure that he gets saved to the proper directory and gets
1359         // displayed correctly
1360         if (Player_sel_mode == PLAYER_SELECT_MODE_SINGLE) {
1361                 Cur_pilot->flags &= ~(PLAYER_FLAGS_IS_MULTI);
1362         } else {
1363                 Cur_pilot->flags |= PLAYER_FLAGS_IS_MULTI;
1364                 Cur_pilot->stats.flags |= STATS_FLAG_MULTIPLAYER;
1365         }
1366
1367         if ( !(Game_mode & GM_STANDALONE_SERVER) ) {
1368                 write_pilot_file(Cur_pilot);
1369         }
1370
1371         Selected_line = 0;
1372         barracks_new_pilot_selected();
1373         barracks_set_callsign_enter_mode(false);
1374 }
1375
1376
1377 // draw pilot image and clean up afterwards
1378 void barracks_draw_pilot_pic()
1379 {
1380         // draw pilot pic
1381         if (Cur_pilot->callsign[0] && (Pic_number >= 0) && (Pic_number < Num_pilot_images)) {
1382                 if (Pilot_images[Pic_number] >= 0) {
1383                         // JAS: This code is hacked to allow the animation to use all 256 colors
1384                         extern int Palman_allow_any_color;
1385                         Palman_allow_any_color = 1;
1386                         gr_set_bitmap(Pilot_images[Pic_number], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1387                         gr_bitmap(Barracks_image_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_image_coords[gr_screen.res][BARRACKS_Y_COORD]);
1388                         Palman_allow_any_color = 0;
1389
1390                         // print number of the current pic
1391                         char buf[40];                   
1392                         SDL_snprintf(buf, SDL_arraysize(buf), XSTR( "%d of %d", 71), Pic_number + 1, Num_pilot_images);
1393                         gr_printf(Barracks_image_number_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_image_number_coords[gr_screen.res][BARRACKS_Y_COORD], buf);                           
1394                 }
1395         } else {
1396                 Pic_number = -1;
1397         }
1398 }
1399
1400 // draw squad image and clean up afterwards
1401 void barracks_draw_squad_pic()
1402 {
1403         char buf[40];
1404
1405         // draw pilot pic
1406         if (Cur_pilot->callsign[0] && (Pic_squad_number >= 0) && (Pic_squad_number < Num_pilot_squad_images)) {
1407                 if (Pilot_squad_images[Pic_squad_number] >= 0) {
1408                         // JAS: This code is hacked to allow the animation to use all 256 colors
1409                         extern int Palman_allow_any_color;
1410                         Palman_allow_any_color = 1;
1411                         gr_set_bitmap(Pilot_squad_images[Pic_squad_number], GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1412                         gr_bitmap(Barracks_squad_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_squad_coords[gr_screen.res][BARRACKS_Y_COORD]);
1413                         Palman_allow_any_color = 0;
1414
1415                         // print number of current squad pic
1416                         if(Player_sel_mode != PLAYER_SELECT_MODE_SINGLE){
1417                                 SDL_snprintf(buf, SDL_arraysize(buf), XSTR( "%d of %d", 71), Pic_squad_number+1, Num_pilot_squad_images);
1418                                 gr_printf(Barracks_squad_number_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_squad_number_coords[gr_screen.res][BARRACKS_Y_COORD], buf);
1419                         }
1420                 }
1421         } else {
1422                 Pic_squad_number = -1;
1423         }       
1424 }
1425
1426 // -----------------------------------------------------------------------------
1427 void barracks_init()
1428 {
1429 #ifndef MAKE_FS1
1430         UI_WINDOW *w = &Ui_window;
1431 #endif
1432
1433         // save current pilot file, so we don't possibly loose it.
1434         write_pilot_file();
1435
1436         // create interface
1437         Ui_window.create(0, 0, gr_screen.max_w, gr_screen.max_h, 0);
1438         Ui_window.set_mask_bmap(Barracks_bitmap_mask_fname[gr_screen.res]);
1439
1440         // load background bitmap
1441         Background_bitmap = bm_load(Barracks_bitmap_fname[gr_screen.res]);
1442         if(Background_bitmap < 0){
1443                 // we failed to load the bitmap - this is very bad
1444                 Int3();
1445         }
1446
1447         // create buttons
1448         for (int i=0; i<BARRACKS_NUM_BUTTONS; i++) {
1449                 // create the object
1450                 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);
1451
1452                 // set the sound to play when highlighted
1453                 Buttons[gr_screen.res][i].button.set_highlight_action(common_play_highlight_sound);
1454
1455                 // set the ani for the button
1456                 Buttons[gr_screen.res][i].button.set_bmaps(Buttons[gr_screen.res][i].filename);
1457
1458                 // set the hotspot
1459                 Buttons[gr_screen.res][i].button.link_hotspot(Buttons[gr_screen.res][i].hotspot);
1460         }
1461
1462         // add all strings      
1463 #ifndef MAKE_FS1
1464         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);
1465         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);
1466         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);
1467         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);
1468         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);
1469         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);
1470         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);
1471         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);
1472         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);
1473         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);
1474         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);    
1475         for(int i=0; i<BARRACKS_NUM_TEXT; i++) {
1476                 w->add_XSTR(&Barracks_text[gr_screen.res][i]);
1477         }
1478 #endif
1479
1480         // button for selecting pilot
1481         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);
1482         List_region.hide();
1483
1484         // create input box (for new pilot)
1485         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);
1486         Inputbox.set_valid_chars(VALID_PILOT_CHARS);
1487         Inputbox.disable();
1488         Inputbox.hide();
1489
1490         // load in help overlay bitmap  
1491         help_overlay_load(BARRACKS_OVERLAY);
1492         help_overlay_set_state(BARRACKS_OVERLAY,0);     
1493
1494         // other init stuff
1495         Barracks_callsign_enter_mode = 0;       
1496         List_scroll_offset = Stats_scroll_offset = Pic_number = Pic_squad_number = Selected_line = 0;
1497         Cur_pilot = &Players[Player_num];
1498
1499         // disable squad logo selection buttons in single player
1500 #ifndef MAKE_FS1
1501         if(!(Cur_pilot->flags & PLAYER_FLAGS_IS_MULTI)){
1502                 // squad logo picture buttons           
1503                 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.hide();
1504                 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.disable();
1505                 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.hide();
1506                 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.disable();
1507         } else {
1508                 // squad logo picture buttons           
1509                 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.enable();
1510                 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.unhide();
1511                 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.enable();
1512                 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.unhide();            
1513         }
1514 #endif
1515
1516         // set up hotkeys for buttons so we draw the correct animation frame when a key is pressed
1517         barracks_set_hotkeys(1);
1518
1519         // load ramp pips
1520 #ifndef FS1_DEMO
1521         Rank_pips_bitmaps = bm_load_animation("IconRankMini.ani", &Rank_pips_count);    
1522 #endif
1523
1524         // load up the pilot pic list
1525         pilot_load_pic_list();  
1526         pilot_load_squad_pic_list();
1527         
1528         // don't load pilot images yet
1529         for (int i=0; i<MAX_PILOT_IMAGES; i++) {
1530                 Pilot_images[i] = BARRACKS_IMAGE_NOT_LOADED;  // while -1 is can't load
1531                 Pilot_squad_images[i] = BARRACKS_IMAGE_NOT_LOADED;
1532         }
1533         
1534         // init stats
1535         barracks_init_stats(&Cur_pilot->stats);
1536
1537         // disable some buttons for the multiplayer beta and e3 build
1538 #if defined(MULTIPLAYER_BETA_BUILD) || defined(E3_BUILD) || defined(PRESS_TOUR_BUILD)
1539         Buttons[gr_screen.res][B_PILOT_CLONE_BUTTON].button.hide();
1540         Buttons[gr_screen.res][B_PILOT_CONVERT_BUTTON].button.hide();   
1541         Buttons[gr_screen.res][B_PILOT_CLONE_BUTTON].button.disable();  
1542         Buttons[gr_screen.res][B_PILOT_CONVERT_BUTTON].button.disable();        
1543 #endif
1544
1545         // multiplayer beta build
1546 #ifdef MULTIPLAYER_BETA_BUILD
1547         Buttons[gr_screen.res][B_PILOT_SINGLE_MODE_BUTTON].button.hide();
1548         Buttons[gr_screen.res][B_PILOT_SINGLE_MODE_BUTTON].button.disable();
1549 #endif
1550
1551         // e3 build
1552 #if defined(E3_BUILD) || defined(PRESS_TOUR_BUILD)
1553         Buttons[gr_screen.res][B_PILOT_MULTI_MODE_BUTTON].button.hide();
1554         Buttons[gr_screen.res][B_PILOT_MULTI_MODE_BUTTON].button.disable();
1555 #endif
1556
1557         // base the mode we're in (single or multi) on the status of the currently selected pilot
1558 #ifdef MULTIPLAYER_BETA_BUILD
1559         barracks_init_player_stuff(1);
1560 #elif defined(E3_BUILD) || defined(PRESS_TOUR_BUILD)
1561         barracks_init_player_stuff(0);
1562 #else
1563         barracks_init_player_stuff(is_pilot_multi(Player));     
1564 #endif
1565
1566 #if defined(MAKE_FS1) && !defined(FS1_DEMO)
1567         PilotWin01 = bm_load(NOX("PilotWin01"));
1568         PilotWin02 = bm_load(NOX("PilotWin02"));
1569         PilotWin03 = bm_load(NOX("PilotWin03"));
1570         PilotWin04 = bm_load(NOX("PilotWin04"));
1571 #endif
1572 }
1573
1574 // -----------------------------------------------------------------------------
1575 void barracks_do_frame(float frametime)
1576 {
1577         int k = Ui_window.process();
1578
1579         if ( k > 0 ) {
1580                 if ( help_overlay_active(BARRACKS_OVERLAY) ) {
1581                         help_overlay_set_state(BARRACKS_OVERLAY,0);
1582                         k = 0;
1583                 }
1584         }
1585
1586         // pilot that mouse is over
1587         int prospective_pilot = -1;
1588         int i;
1589
1590         // Entering pilot callsign
1591         if (Barracks_callsign_enter_mode) {
1592                 // set focus to inputbox
1593                 Inputbox.set_focus();
1594
1595                 switch (k) {
1596                         case SDLK_ESCAPE:
1597                                 // cancel create pilot
1598                                 Num_pilots--;
1599                                 for (i=0; i<Num_pilots; i++) {
1600                                         SDL_strlcpy(Pilots[i], Pilots[i + 1], MAX_FILENAME_LEN);
1601                                         Pilot_ranks[i] = Pilot_ranks[i + 1];
1602                                 }
1603
1604                                 barracks_set_callsign_enter_mode(false);
1605                                 break;
1606
1607                         case SDLK_RETURN:
1608                                 barracks_accept_new_pilot_callsign();
1609                                 break;
1610                 } 
1611         } else {
1612                 // not entering pilot callsign
1613                 switch (k) {
1614                         case SDLK_RETURN:
1615                                 if (barracks_new_pilot_selected()) {
1616                                         gamesnd_play_iface(SND_GENERAL_FAIL);
1617                                 } else {
1618                                         gamesnd_play_iface(SND_USER_SELECT);
1619                                 }
1620                                 break;
1621
1622                         case SDLK_ESCAPE:  // cancel
1623                                 if (!help_overlay_active(BARRACKS_OVERLAY)) {
1624                                         if (Num_pilots && !barracks_pilot_accepted()) {
1625                                                 gameseq_post_event(GS_EVENT_MAIN_MENU);
1626                                         } else {
1627                                                 gamesnd_play_iface(SND_GENERAL_FAIL);
1628                                         }
1629                                 } else {
1630                                         // kill the overlay
1631                                         help_overlay_set_state(BARRACKS_OVERLAY,0);
1632                                 }
1633                                 break;
1634
1635                         case SDLK_TAB:  // switch mode (simgle/multi)
1636 #if defined(DEMO) || defined(OEM_BUILD) || defined(__EMSCRIPTEN__) // not for FS2_DEMO
1637         game_feature_not_in_demo_popup();
1638 #else
1639                                 if (Player_sel_mode == PLAYER_SELECT_MODE_SINGLE) {
1640                                         barracks_init_player_stuff(PLAYER_SELECT_MODE_MULTI);
1641                                 } else {
1642                                         barracks_init_player_stuff(PLAYER_SELECT_MODE_SINGLE);
1643                                 }
1644
1645                                 gamesnd_play_iface(SND_USER_SELECT);
1646 #endif
1647                                 break;
1648
1649                         case SDLK_F1:  // show help overlay
1650                                 gamesnd_play_iface(SND_HELP_PRESSED);
1651                                 break;
1652
1653                         case SDLK_F2:  // goto options screen
1654                                 gamesnd_play_iface(SND_SWITCH_SCREENS);
1655                                 gameseq_post_event(GS_EVENT_OPTIONS_MENU);
1656                                 break;
1657                 }       // end switch
1658
1659                 // process buttons
1660                 for (i=0; i<BARRACKS_NUM_BUTTONS; i++) {
1661                         if (Buttons[gr_screen.res][i].button.pressed()) {
1662                                 barracks_button_pressed(i);
1663                         }
1664                 }
1665
1666                 // if mouse is over a pilot, find index into Pilots array
1667                 if (List_region.is_mouse_on()) {
1668                         int y;
1669                         List_region.get_mouse_pos(NULL, &y);
1670                         int pilot_index = List_scroll_offset + (y / gr_get_font_height());
1671                         if ((pilot_index >= 0) && (pilot_index < Num_pilots)) {
1672                                 prospective_pilot = pilot_index;
1673                         }
1674                 }
1675                 
1676                 // if mouse clicked in list region, find index into Pilots array 
1677                 if (List_region.pressed()) {
1678                         if (prospective_pilot != -1) {
1679                                 Selected_line = prospective_pilot;
1680                                 gamesnd_play_iface(SND_USER_SELECT);
1681                         }
1682                 }
1683         }
1684
1685         // check mouse over help
1686         if (mouse_down(MOUSE_LEFT_BUTTON)) {
1687                 help_overlay_set_state(BARRACKS_OVERLAY, 0);
1688         }
1689
1690         // do pilot pic stuff
1691         if ((Pic_number >= 0) && (Pic_number < Num_pilot_images)) {
1692                 if (Pilot_images[Pic_number] == BARRACKS_IMAGE_NOT_LOADED) {  // haven't tried loading it yet
1693                         Pilot_images[Pic_number] = bm_load(Pilot_image_names[Pic_number]);
1694                         if (Pilot_images[Pic_number] >= 0) {
1695                                 int w, h;
1696
1697                                 bm_get_info(Pilot_images[Pic_number], &w, &h, NULL);
1698                                 // check for invalid pilot pic file
1699                                 if ((w != PLAYER_PILOT_PIC_W) || (h != PLAYER_PILOT_PIC_H)) {
1700                                         bm_unload(Pilot_images[Pic_number]);
1701                                         Pilot_images[Pic_number] = -1;
1702                                 }
1703                         }
1704                 }               
1705         } else {
1706                 Pic_number = -1;
1707         }
1708
1709         // do squad pic stuff
1710         if ((Pic_squad_number >= 0) && (Pic_squad_number < Num_pilot_squad_images)) {
1711                 if (Pilot_squad_images[Pic_squad_number] == BARRACKS_IMAGE_NOT_LOADED) {  // haven't tried loading it yet
1712                         Pilot_squad_images[Pic_squad_number] = bm_load_duplicate(Pilot_squad_image_names[Pic_squad_number]);
1713                         if (Pilot_squad_images[Pic_squad_number] >= 0) {
1714                                 int w, h;
1715
1716                                 bm_get_info(Pilot_squad_images[Pic_squad_number], &w, &h, NULL);
1717                                 // check for invalid pilot pic file
1718                                 if ((w != PLAYER_SQUAD_PIC_W) || (h != PLAYER_SQUAD_PIC_H)) {
1719                                         bm_unload(Pilot_squad_images[Pic_squad_number]);
1720                                         Pilot_squad_images[Pic_squad_number] = -1;
1721                                 }
1722                         }
1723                 }
1724         } else {
1725                 Pic_squad_number = -1;
1726         }
1727
1728         // draw the background, etc
1729         gr_reset_clip();        
1730         GR_MAYBE_CLEAR_RES(Background_bitmap);
1731         if (Background_bitmap >= 0) {
1732                 gr_set_bitmap(Background_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1733                 gr_bitmap(0, 0);        
1734         }               
1735
1736         // draw pilot image and clean up afterwards
1737         barracks_draw_pilot_pic();
1738         barracks_draw_squad_pic();
1739
1740 #if defined(MAKE_FS1) && !defined(FS1_DEMO)
1741         if (PilotWin01 != -1) {
1742                 gr_set_bitmap(PilotWin01, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1743                 gr_bitmap(447, 18);
1744         }
1745
1746         if (PilotWin02 != -1) {
1747                 gr_set_bitmap(PilotWin02, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1748                 gr_bitmap(620, 38);
1749         }
1750
1751         if (PilotWin03 != -1) {
1752                 gr_set_bitmap(PilotWin03, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1753                 gr_bitmap(447, 137);
1754         }
1755
1756         if (PilotWin04 != -1) {
1757                 gr_set_bitmap(PilotWin04, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1758                 gr_bitmap(447, 36);
1759         }
1760 #endif
1761
1762
1763         // draw the window      
1764         Ui_window.draw();       
1765
1766         // light up the correct mode button (single or multi)   
1767         if (Player_sel_mode == PLAYER_SELECT_MODE_SINGLE) {
1768                 Buttons[gr_screen.res][B_PILOT_SINGLE_MODE_BUTTON].button.draw_forced(2);
1769         } else {
1770                 Buttons[gr_screen.res][B_PILOT_MULTI_MODE_BUTTON].button.draw_forced(2);
1771         }       
1772
1773         // write out pilot call signs
1774         barracks_display_pilot_callsigns(prospective_pilot);
1775
1776         // write out current pilot stats
1777         barracks_display_pilot_stats();
1778
1779         // blit help overlay if active
1780         help_overlay_maybe_blit(BARRACKS_OVERLAY);      
1781         
1782         // flip the page
1783         gr_flip();
1784 }
1785
1786 // -----------------------------------------------------------------------------
1787 void barracks_close()
1788 {
1789 #if defined(MAKE_FS1) && !defined(FS1_DEMO)
1790     if (PilotWin01 != -1){
1791         bm_unload(PilotWin01);
1792         PilotWin01 = -1;
1793     }
1794     if (PilotWin02 != -1){
1795         bm_unload(PilotWin02);
1796         PilotWin02 = -1;
1797     }
1798     if (PilotWin03 != -1){
1799         bm_unload(PilotWin03);
1800         PilotWin03 = -1;
1801     }
1802     if (PilotWin04 != -1){
1803         bm_unload(PilotWin04);
1804         PilotWin04 = -1;
1805     }
1806 #endif
1807
1808         // destroy window
1809         Ui_window.destroy();
1810
1811         // release background bitmap
1812         if (Background_bitmap >= 0) {
1813                 bm_unload(Background_bitmap);
1814         }       
1815
1816         // release rank pip bitmaps
1817         for (int i=0; i<Rank_pips_count; i++) {
1818                 bm_release(Rank_pips_bitmaps + i);
1819         }       
1820
1821         // release pilot pic bitmaps
1822         for (int i=0; i<Num_pilot_images; i++) {
1823                 if (Pilot_images[i] >= 0) {
1824                         bm_unload(Pilot_images[i]);
1825                 }
1826         }
1827
1828         // unload the overlay bitmap
1829         help_overlay_unload(BARRACKS_OVERLAY);
1830
1831         game_flush();
1832 }
1833