]> icculus.org git repositories - taylor/freespace2.git/blob - src/menuui/barracks.cpp
added copyright header
[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.3  2002/06/09 04:41:22  relnev
19  * added copyright header
20  *
21  * Revision 1.2  2002/05/07 03:16:46  theoddone33
22  * The Great Newline Fix
23  *
24  * Revision 1.1.1.1  2002/05/03 03:28:09  root
25  * Initial import.
26  *
27  * 
28  * 42    10/25/99 5:47p Jefff
29  * reassigned some xstr ids
30  * 
31  * 41    9/14/99 11:01p Jefff
32  * stats area coord fix
33  * 
34  * 40    9/09/99 11:24a Jefff
35  * 
36  * 39    9/02/99 11:26a Jefff
37  * fixed incorrect pilot list dimensions
38  * 
39  * 38    8/17/99 2:24p Dave
40  * Fixed wacky squad color stuff.
41  * 
42  * 37    8/16/99 4:27p Jefff
43  * fix button position on squad change error popup
44  * 
45  * 36    8/11/99 3:58p Jefff
46  * fixed player list box coord bug
47  * 
48  * 35    8/05/99 2:46p Jefff
49  * added popup to the disabled squad selection buttons in single player
50  * 
51  * 34    8/02/99 11:02p Dave
52  * Fixed up squad filename and squad name copying when converting a pilot
53  * between single and multiplayer.
54  * 
55  * 33    7/27/99 7:17p Jefff
56  * Replaced some art text with XSTR() text.
57  * 
58  * 32    7/15/99 9:20a Andsager
59  * FS2_DEMO initial checkin
60  * 
61  * 31    6/29/99 7:39p Dave
62  * Lots of small bug fixes.
63  * 
64  * 30    6/16/99 4:06p Dave
65  * New pilot info popup. Added new draw-bitmap-as-poly function.
66  * 
67  * 29    6/11/99 11:13a Dave
68  * last minute changes before press tour build.
69  * 
70  * 28    4/25/99 7:43p Dave
71  * Misc small bug fixes. Made sun draw properly.
72  * 
73  * 27    4/25/99 3:02p Dave
74  * Build defines for the E3 build.
75  * 
76  * 26    3/24/99 4:05p Dave
77  * Put in support for assigning the player to a specific squadron with a
78  * specific logo. Preliminary work for doing pos/orient checksumming in
79  * multiplayer to reduce bandwidth.
80  * 
81  * 25    2/25/99 4:19p Dave
82  * Added multiplayer_beta defines. Added cd_check define. Fixed a few
83  * release build warnings. Added more data to the squad war request and
84  * response packets.
85  * 
86  * 24    2/02/99 12:09p Neilk
87  * Fixed text coords, centered pilot and squad pics in 1024x768, added vss
88  * comment template
89  *
90  * $NoKeywords: $
91  */
92
93 #include "barracks.h"
94 #include "managepilot.h"
95 #include "ui.h"
96 #include "font.h"
97 #include "key.h"
98 #include "gamesnd.h"
99 #include "osapi.h"
100 #include "popup.h"
101 #include "playermenu.h"
102 #include "gamesequence.h"
103 #include "contexthelp.h"
104 #include "2d.h"
105 #include "ctype.h"
106 #include "freespace.h"
107 #include "systemvars.h"
108 #include "bmpman.h"
109 #include "mouse.h"
110 #include "osregistry.h"
111 #include "alphacolors.h"
112
113 void delete_pilot_file( char *pilot_name, int single );         // manage_pilot.cpp
114
115 // stats defines
116 #define NUM_STAT_LINES 85
117 #define STAT_COLUMN1_W 40
118 #define STAT_COLUMN2_W 10
119
120 static int Stat_column1_w[GR_NUM_RESOLUTIONS] =
121 {
122         40,             // GR_640
123         40                      // GR_1024
124 };
125
126 static int Stat_column2_w[GR_NUM_RESOLUTIONS] =
127 {
128         10,             // GR_640
129         10                      // GR_1024
130 };
131
132 // constants for coordinate lookup
133 #define BARRACKS_X_COORD 0
134 #define BARRACKS_Y_COORD 1
135 #define BARRACKS_W_COORD 2
136 #define BARRACKS_H_COORD 3
137
138 // area ints
139
140 // pilot selection field
141 static int Barracks_list_coords[GR_NUM_RESOLUTIONS][4] = {
142         { // GR_640
143                 42, 34, 400, 90
144         },
145         { // GR_1024
146                 45, 51, 646, 144
147         }
148 };
149
150 // pilot stats field
151 static int Barracks_stats_coords[GR_NUM_RESOLUTIONS][4] = {
152         { // GR_640
153                 32, 212, 240, 250
154         },
155         { // GR_1024
156                 42, 351, 240, 400
157         }
158 };
159
160 static int Barracks_stats2_coords[GR_NUM_RESOLUTIONS][3] = {
161         { // GR_640
162                 276, 212, 81            // X2, , W2
163         },
164         { // GR_1024
165                 286, 351, 81            // X2, , W2
166         }
167 };
168
169 // pilot picture field
170 static int Barracks_image_coords[GR_NUM_RESOLUTIONS][4] = {
171         { // GR_640
172                 461, 23, 160, 120
173         },
174         { // GR_1024
175                 782, 58, 160, 120
176         }
177 };
178
179 // pilot picture # of # location
180 static int Barracks_image_number_coords[GR_NUM_RESOLUTIONS][2] = {
181         { // GR_640
182                 461, 145
183         },
184         { // GR_1024
185                 732, 239
186         }
187 };
188
189 // pilot squad logo field
190 int Barracks_squad_coords[GR_NUM_RESOLUTIONS][4] = {
191         { // GR_640
192                 495, 177, 128, 128
193         },
194         { // GR_1024
195                 829, 323, 128, 128
196         }
197 };
198
199 // pilot squad # of # location
200 int Barracks_squad_number_coords[GR_NUM_RESOLUTIONS][2] = {
201         { // GR_640
202                 492, 307
203         },
204         { // GR_1024
205                 794, 500
206         }
207 };
208
209 // button defines
210 #define BARRACKS_NUM_BUTTONS            19
211
212 // pilot selection buttons
213 #define B_PILOT_CREATE_BOTTON                   0       // B_PILOT_CREATE_BOTTON
214 #define B_PILOT_SCROLL_UP_BUTTON                1       // B_PILOT_SCROLL_UP_BUTTON
215 #define B_PILOT_SCROLL_DOWN_BUTTON      2       // B_PILOT_SCROLL_DOWN_BUTTON
216 #define B_PILOT_DELETE_BUTTON                   11      // B_PILOT_B_PILOT_DELETE_BUTTON
217 #define B_PILOT_SET_ACTIVE_BUTTON       12      // B_PILOT_B_PILOT_SET_ACTIVE_BUTTON
218 #define B_PILOT_CLONE_BUTTON                    13      // B_PILOT_B_PILOT_CLONE_BUTTON
219 #define B_PILOT_SINGLE_MODE_BUTTON      14      // B_PILOT_SINGLE_MODE_BUTTON
220 #define B_PILOT_MULTI_MODE_BUTTON       15      // B_PILOT_MULTI_MODE_BUTTON
221 #define B_PILOT_CONVERT_BUTTON          16      // B_PILOT_B_PILOT_CONVERT_BUTTON
222
223 // squad logo picture buttons
224 #define B_SQUAD_PREV_BUTTON                     17
225 #define B_SQUAD_NEXT_BUTTON                     18
226
227 // pilot picture buttons
228 #define B_PIC_PREV_PILOT_BUTTON         3       // B_PILOT_B_PIC_PREV_PILOT_BUTTON
229 #define B_PIC_NEXT_PILOT_BUTTON         4       // B_PILOT_B_PIC_NEXT_PILOT_BUTTON
230
231 // pilot stat buttons
232 #define B_STATS_MEDAL_BUTTON                    8       // B_STATS_MEDAL_BUTTON
233 #define B_STATS_SCROLL_DOWN_BUTTON      9       // B_STATS_SCROLL_DOWN_BUTTON
234 #define B_STATS_SCROLL_UP_BUTTON                10      // B_STATS_SCROLL_UP_BUTTON
235
236 // general buttons
237 #define B_ACCEPT_BUTTON                                 5       // B_B_ACCEPT_BUTTON
238 #define B_HELP_BUTTON                                   6       // B_B_HELP_BUTTON
239 #define B_OPTION_BUTTON                                 7       // B_OPTION_BUTTON
240
241 //XSTR:OFF
242 // bitmaps defs
243 static char *Barracks_bitmap_fname[GR_NUM_RESOLUTIONS] = {
244         "Barracks",             // GR_640
245         "2_Barracks"            // GR_1024
246 };
247
248 static char *Barracks_bitmap_mask_fname[GR_NUM_RESOLUTIONS] = {
249         "Barracks-M",           // GR_640
250         "2_Barracks-M"          // GR_1024
251 };
252
253 //XSTR:ON
254
255 #define BARRACKS_IMAGE_NOT_LOADED       -2
256
257 struct barracks_bitmaps {
258         char *filename;
259         int x, y;
260         int b;
261 };
262
263 struct barracks_buttons {
264         char *filename;
265         int x, y;
266         int text_x, text_y;     // this is where the text label is
267         int hotspot;
268         int repeat;
269         UI_BUTTON button;  // because we have a class inside this struct, we need the constructor below..
270
271         barracks_buttons(char *name, int x1, int y1, int x2, int y2, int h, int r = 0) : filename(name), x(x1), y(y1), text_x(x2), text_y(y2), hotspot(h), repeat(r) {}
272 };
273
274 static int Background_bitmap = -1;
275 static UI_WINDOW Ui_window;
276 static UI_BUTTON List_region;
277 static UI_INPUTBOX Inputbox;
278
279 static barracks_buttons Buttons[GR_NUM_RESOLUTIONS][BARRACKS_NUM_BUTTONS] = {
280 //XSTR:OFF
281         {               // GR_640
282                         barracks_buttons("BAB_00", 8,           122,    11,     157,    0),             
283                         barracks_buttons("BAB_01", 323, 130,    0,              0,              1, 1),
284                         barracks_buttons("BAB_02", 350, 130,    0,              0,              2,      1),
285                         barracks_buttons("BAB_03", 559, 143,    0,              0,              3,      1),                     
286                         barracks_buttons("BAB_04", 598, 143,    0,              0,              4,      1),
287                         barracks_buttons("BAB_05", 571, 425,    578,    413,    5),
288                         barracks_buttons("BAB_06", 533, 425,    500,    438,    6),
289                         barracks_buttons("BAB_07", 533, 453,    481,    465,    7),
290                         barracks_buttons("BAB_08", 361, 425,    401,    465,    8),
291                         barracks_buttons("BAB_09", 0,           267,    0,              0,              9,      1),
292                         barracks_buttons("BAB_10", 0,           224,    0,              0,              10,1),
293                         barracks_buttons("BAB_11", 120, 122,    123,    157,    11),    
294                         barracks_buttons("BAB_12", 376, 124,    378,    163,    12),
295                         barracks_buttons("BAB_13", 66,  122,    69,     157,    13),
296                         barracks_buttons("BAB_14", 323, 0,              324,    25,     14),
297                         barracks_buttons("BAB_15", 372, 0,              374,    25,     15),
298                         barracks_buttons("BAB_16", 180, 122,    182,    157,    16),
299                         barracks_buttons("BAB_17", 559, 306,    0,              0,              17),
300                         barracks_buttons("BAB_18", 598, 306,    0,              0,              18)
301         },
302         {               // GR_1024
303                         barracks_buttons("2_BAB_00", 14,                196,    35,     252,    0),
304                         barracks_buttons("2_BAB_01", 518,       209,    0,              0,              1,      1),
305                         barracks_buttons("2_BAB_02", 561,       209,    0,              0,              2,      1),
306                         barracks_buttons("2_BAB_03", 896,       229,    0,              0,              3,      1),
307                         barracks_buttons("2_BAB_04", 958,       229,    0,              0,              4,      1),
308                         barracks_buttons("2_BAB_05", 914,       681,    932,    665,    5),
309                         barracks_buttons("2_BAB_06", 854,       681,    800,    704,    6),
310                         barracks_buttons("2_BAB_07", 854,       724,    778,    743,    7),
311                         barracks_buttons("2_BAB_08", 579,       681,    641,    743,    8),
312                         barracks_buttons("2_BAB_09", 0,         428,    0,              0,              9,      1),
313                         barracks_buttons("2_BAB_10", 0,         360,    0,              0,              10,1),
314                         barracks_buttons("2_BAB_11", 193,       196,    214,    252,    11),
315                         barracks_buttons("2_BAB_12", 602,       200,    617,    262,    12),
316                         barracks_buttons("2_BAB_13", 107,       196,    128,    252,    13),
317                         barracks_buttons("2_BAB_14", 517,       0,              532,    40,     14),
318                         barracks_buttons("2_BAB_15", 596,       0,              614,    40,     15),
319                         barracks_buttons("2_BAB_16", 289,       196,    309,    252,    16),
320                         barracks_buttons("2_BAB_17", 896,       491,    0,              0,              17),
321                         barracks_buttons("2_BAB_18", 958,       491,    0,              0,              18)
322         }
323 //XSTR:ON
324 };
325
326
327 // FIXME add to strings.tbl, set correct coords
328 #define BARRACKS_NUM_TEXT                       2
329 UI_XSTR Barracks_text[GR_NUM_RESOLUTIONS][BARRACKS_NUM_TEXT] = {
330         { 
331                 // GR_640
332                 { "Barracks",                   1434,           17, 7,          UI_XSTR_COLOR_GREEN, -1, NULL },
333                 { "Pilot Stats",                1435,           17, 180,                UI_XSTR_COLOR_GREEN, -1, NULL }
334         }, 
335         { 
336                 // GR_1024
337                 { "Barracks",                   1434,           27, 11,         UI_XSTR_COLOR_GREEN, -1, NULL },
338                 { "Pilot Stats",                1435,           27, 288,                UI_XSTR_COLOR_GREEN, -1, NULL }
339         }
340 };
341
342
343 static int Num_stat_lines;
344 static char Stat_labels[NUM_STAT_LINES][STAT_COLUMN1_W];
345 static char Stats[NUM_STAT_LINES][STAT_COLUMN2_W];
346
347 extern int Player_sel_mode;
348
349 static player *Cur_pilot;
350 static int Num_pilots;
351 static int Selected_line;
352 static char Pilots_arr[MAX_PILOTS][MAX_FILENAME_LEN];
353 static char *Pilots[MAX_PILOTS];
354 static int Pic_number;
355 static int Pic_squad_number;
356 static bool Barracks_callsign_enter_mode;
357 static int Pilot_ranks[MAX_PILOTS];
358 static int List_scroll_offset;
359 static int Stats_scroll_offset;
360 static int Clone_flag;
361 static int Pilot_images[MAX_PILOT_IMAGES];
362 static int Pilot_squad_images[MAX_PILOT_IMAGES];
363 static int Rank_pips_bitmaps;
364 static int Rank_pips_count;
365
366 void barracks_squad_change_popup();
367
368
369 // -------------------------------------------------------------------------------------------------
370 //
371 // BARRACKS screen
372 //
373
374 #define STRCPY1(a, b) do {      \
375         Assert(strlen(b) < STAT_COLUMN1_W); \
376         strcpy(a, b); \
377 } while (0)
378
379 void barracks_init_stats(scoring_struct *stats)
380 {
381         int i;
382         float f;
383
384         Num_stat_lines = 0;
385
386         STRCPY1(Stat_labels[Num_stat_lines], XSTR( "*All Time Stats", 50));
387         Stats[Num_stat_lines][0] = 0;
388         Num_stat_lines++;
389
390         Assert(Num_stat_lines < NUM_STAT_LINES);
391         Stat_labels[Num_stat_lines][0] = 0;
392         Stats[Num_stat_lines][0] = 0;
393         Num_stat_lines++;       
394
395         Assert(Num_stat_lines < NUM_STAT_LINES);
396         STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Primary weapon shots:", 51));
397         sprintf(Stats[Num_stat_lines], "%d", stats->p_shots_fired);
398         Num_stat_lines++;
399
400         Assert(Num_stat_lines < NUM_STAT_LINES);
401         STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Primary weapon hits:", 52));
402         sprintf(Stats[Num_stat_lines], "%d", stats->p_shots_hit);
403         Num_stat_lines++;
404
405         Assert(Num_stat_lines < NUM_STAT_LINES);
406         STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Primary friendly hits:", 53));
407         sprintf(Stats[Num_stat_lines], "%d", stats->p_bonehead_hits);
408         Num_stat_lines++;
409
410         Assert(Num_stat_lines < NUM_STAT_LINES);
411         STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Primary hit %:", 54));
412         if (stats->p_shots_fired > 0) {
413                 f = (float) stats->p_shots_hit * 100.0f / (float) stats->p_shots_fired;
414         } else {
415                 f = 0.0f;
416         }
417         sprintf(Stats[Num_stat_lines], XSTR( "%.1f%%", 55), f);
418         Num_stat_lines++;
419
420         Assert(Num_stat_lines < NUM_STAT_LINES);
421         STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Primary friendly hit %:", 56));
422         if (stats->p_bonehead_hits > 0) {
423                 f = (float) stats->p_bonehead_hits * 100.0f / (float) stats->p_shots_fired;
424         } else {
425                 f = 0.0f;
426         }
427         sprintf(Stats[Num_stat_lines], XSTR( "%.1f%%", 55), f);
428         Num_stat_lines++;
429
430         Assert(Num_stat_lines < NUM_STAT_LINES);
431         Stat_labels[Num_stat_lines][0] = 0;
432         Stats[Num_stat_lines][0] = 0;
433         Num_stat_lines++;
434
435         Assert(Num_stat_lines < NUM_STAT_LINES);
436         STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Secondary weapon shots:", 57));
437         sprintf(Stats[Num_stat_lines], "%d", stats->s_shots_fired);
438         Num_stat_lines++;
439
440         Assert(Num_stat_lines < NUM_STAT_LINES);
441         STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Secondary weapon hits:", 58));
442         sprintf(Stats[Num_stat_lines], "%d", stats->s_shots_hit);
443         Num_stat_lines++;
444
445         Assert(Num_stat_lines < NUM_STAT_LINES);
446         STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Secondary friendly hits:", 59));
447         sprintf(Stats[Num_stat_lines], "%d", stats->s_bonehead_hits);
448         Num_stat_lines++;
449
450         Assert(Num_stat_lines < NUM_STAT_LINES);
451         STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Secondary hit %:", 60));
452         if (stats->s_shots_fired > 0) {
453                 f = (float) stats->s_shots_hit * 100.0f / (float) stats->s_shots_fired;
454         } else {
455                 f = 0.0f;
456         }
457         sprintf(Stats[Num_stat_lines], XSTR( "%.1f%%", 55), f);
458         Num_stat_lines++;
459
460         Assert(Num_stat_lines < NUM_STAT_LINES);
461         STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Secondary friendly hit %:", 61));
462         if (stats->s_bonehead_hits > 0) {
463                 f = (float) stats->s_bonehead_hits * 100.0f / (float) stats->s_shots_fired;
464         } else {
465                 f = 0.0f;
466         }
467         sprintf(Stats[Num_stat_lines], XSTR( "%.1f%%", 55), f);
468         Num_stat_lines++;
469
470         Assert(Num_stat_lines < NUM_STAT_LINES);
471         Stat_labels[Num_stat_lines][0] = 0;
472         Stats[Num_stat_lines][0] = 0;
473         Num_stat_lines++;
474
475         Assert(Num_stat_lines < NUM_STAT_LINES);
476         STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Total kills:", 62));
477         sprintf(Stats[Num_stat_lines], "%d", stats->kill_count_ok);
478         Num_stat_lines++;
479
480         Assert(Num_stat_lines < NUM_STAT_LINES);
481         STRCPY1(Stat_labels[Num_stat_lines], XSTR( "Assists:", 63));
482         sprintf(Stats[Num_stat_lines], "%d", stats->assists);
483         Num_stat_lines++;
484
485         Assert(Num_stat_lines < NUM_STAT_LINES);
486         Stat_labels[Num_stat_lines][0] = 0;
487         Stats[Num_stat_lines][0] = 0;
488         Num_stat_lines++;
489
490         Assert(Num_stat_lines < NUM_STAT_LINES);
491         Stat_labels[Num_stat_lines][0] = 0;
492         Stats[Num_stat_lines][0] = 0;
493         Num_stat_lines++;
494
495         STRCPY1(Stat_labels[Num_stat_lines], XSTR( "*Kills by Ship Type", 64));
496         Stats[Num_stat_lines][0] = 0;
497         Num_stat_lines++;
498
499         Assert(Num_stat_lines < NUM_STAT_LINES);
500         Stat_labels[Num_stat_lines][0] = 0;
501         Stats[Num_stat_lines][0] = 0;
502         Num_stat_lines++;
503
504         for (i=0; i<Num_ship_types; i++) {
505                 if (stats->kills[i]) {
506                         Assert(Num_stat_lines < NUM_STAT_LINES);
507                         Assert(strlen(Ship_info[i].name) + 1 < STAT_COLUMN1_W);
508                         sprintf(Stat_labels[Num_stat_lines], NOX("%s:"), Ship_info[i].name);
509                         sprintf(Stats[Num_stat_lines], "%d", stats->kills[i]);
510                         Num_stat_lines++;
511                 }
512         }
513
514         for (i=0; i<Num_stat_lines; i++) {
515                 gr_force_fit_string(Stat_labels[i], Stat_column1_w[gr_screen.res], Barracks_stats_coords[gr_screen.res][BARRACKS_W_COORD]);
516                 gr_force_fit_string(Stats[i], Stat_column2_w[gr_screen.res], Barracks_stats2_coords[gr_screen.res][BARRACKS_W_COORD]);
517         }
518 }
519
520 // sets or clears hotkeys for pilot selection.
521 void barracks_set_hotkeys(bool pilot_text_enter_mode)
522 {
523         Buttons[gr_screen.res][B_PILOT_SCROLL_UP_BUTTON].button.set_hotkey(pilot_text_enter_mode ? KEY_UP : -1);
524         Buttons[gr_screen.res][B_PILOT_SCROLL_DOWN_BUTTON].button.set_hotkey(pilot_text_enter_mode ? KEY_DOWN : -1);
525
526         Buttons[gr_screen.res][B_PILOT_CREATE_BOTTON].button.set_hotkey(pilot_text_enter_mode ? KEY_C : -1);
527         Buttons[gr_screen.res][B_PILOT_SET_ACTIVE_BUTTON].button.set_hotkey(pilot_text_enter_mode ? KEY_ENTER : -1);
528         Buttons[gr_screen.res][B_PILOT_DELETE_BUTTON].button.set_hotkey(pilot_text_enter_mode ? KEY_DELETE : -1);
529
530         Buttons[gr_screen.res][B_PIC_PREV_PILOT_BUTTON].button.set_hotkey(pilot_text_enter_mode ? KEY_LEFT : -1);
531         Buttons[gr_screen.res][B_PIC_NEXT_PILOT_BUTTON].button.set_hotkey(pilot_text_enter_mode ? KEY_RIGHT : -1);
532
533         Buttons[gr_screen.res][B_ACCEPT_BUTTON].button.set_hotkey(pilot_text_enter_mode ? KEY_CTRLED | KEY_ENTER : -1);
534 }
535
536 // strip the possible .pcx extension off a filename
537 void barracks_strip_pcx(char *str)
538 {
539         int flen = strlen(str);
540         int elen = 4;           
541         if ((flen > 4) && !stricmp(str + flen - elen, ".pcx")) {
542                 str[flen - elen] = '\0';
543         }
544 }
545
546 // new pilot name has focus, so update stats/pic to that pilot
547 int barracks_new_pilot_selected()
548 {
549         char stripped[MAX_FILENAME_LEN+1] = "";
550
551         // save the previous pilot first, so changes to it are kept
552         if (strlen(Cur_pilot->callsign)) {
553                 write_pilot_file();
554         }
555
556         // check if we have a valid pilot hilighted.  If so, attempt to active it
557         if ((Num_pilots < 1) || (Selected_line < 0) || (Selected_line >= Num_pilots)) {
558                 Cur_pilot->callsign[0] = 0;  // this indicates no pilot active
559                 return -1;
560         }
561
562         if (read_pilot_file(Pilots[Selected_line], !Player_sel_mode, Cur_pilot)) {
563                 Cur_pilot->callsign[0] = 0;  // this indicates no pilot active
564                 return -1;
565         }
566
567         // init stuff to reflect new pilot
568         int i;
569         barracks_init_stats(&Cur_pilot->stats);
570         for (i=0; i<Num_pilot_images; i++) {
571                 strcpy(stripped, Cur_pilot->image_filename);
572                 barracks_strip_pcx(stripped);
573                 if (!stricmp(stripped, Pilot_image_names[i])) {
574                         break;
575                 }
576         }
577         Pic_number = i;
578         for ( i=0; i<Num_pilot_squad_images; i++) {
579                 strcpy(stripped, Cur_pilot->squad_filename);
580                 barracks_strip_pcx(stripped);
581                 if (!stricmp(stripped, Pilot_squad_image_names[i])) {
582                         break;
583                 }
584         }
585         Pic_squad_number = i;   
586         
587         return 0;
588 }
589
590 void barracks_set_callsign_enter_mode(bool set_callsign_enter_mode)
591 {
592         // set global mode variable
593         Barracks_callsign_enter_mode = set_callsign_enter_mode;
594
595         // disable/enable all buttons
596         for (int idx=0; idx<BARRACKS_NUM_BUTTONS; idx++) {
597                 // don't ever mess with the prev and next squad logo buttons
598                 if((idx != B_SQUAD_PREV_BUTTON) && (idx != B_SQUAD_NEXT_BUTTON)){
599                         Buttons[gr_screen.res][idx].button.enable(!set_callsign_enter_mode);
600                 }
601         }
602
603         // enable/disable hotkeys
604         barracks_set_hotkeys(!set_callsign_enter_mode);
605         // disable/enable inputbox
606         Inputbox.enable(set_callsign_enter_mode);
607         // hide/unhide inputbox
608         Inputbox.hide(!set_callsign_enter_mode);
609 }
610
611 // creates a new pilot file
612 void barracks_create_new_pilot()
613 {
614         // check if too many pilots
615         if (Num_pilots >= MAX_PILOTS) {
616                 gamesnd_play_iface(SND_GENERAL_FAIL);
617                 return;
618         }
619
620         // play sound for pilot creation
621         gamesnd_play_iface(SND_SCROLL);
622         
623         // only write pilot file if there is an active pilot
624         if (strlen(Player->callsign)) {
625                 write_pilot_file();
626         }
627
628         // move other pilot names and ranks down to make room for the new one
629         int idx = Num_pilots;
630         Assert(Num_pilots >= 0);
631         while (idx--) {
632                 strcpy(Pilots[idx + 1], Pilots[idx]);
633                 Pilot_ranks[idx + 1] = Pilot_ranks[idx];
634         }
635
636         Selected_line = 0;
637         Num_pilots++;
638         Pilots[Selected_line][0] = 0;
639         Pilot_ranks[Selected_line] = 0;
640         List_scroll_offset = 0;
641
642         // set mode to accept pilot name text
643         barracks_set_callsign_enter_mode(true);
644         // set focus to input box
645         Inputbox.set_focus();
646         // set initial pilot name to ""
647         Inputbox.set_text("");
648         // reset size of input box to only 1 line
649         Inputbox.update_dimensions(Barracks_list_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_list_coords[gr_screen.res][BARRACKS_Y_COORD], Barracks_list_coords[gr_screen.res][BARRACKS_W_COORD], gr_get_font_height());
650 }
651
652 // exiting screen without canceling, so load in the new pilot selected here
653 int barracks_pilot_accepted()
654 {
655         char str[CALLSIGN_LEN + 1];
656
657         // check if pilot active.  If not, don't allow accept.
658         if (!Cur_pilot->callsign[0]){
659                 return -1;
660         }
661
662         // set his image 
663         player_set_squad_bitmap(Cur_pilot, Cur_pilot->squad_filename);
664
665 //      Skill_level = get_default_skill_level();
666
667         // MWA -- I think that we should be writing Cur_pilot here.
668         //write_pilot_file(!is_pilot_multi(Cur_pilot));
669         write_pilot_file( Cur_pilot );
670         
671         // when we store the LastPlayer key, we have to mark it as being single or multiplayer, so we know where to look for him
672         // (since we could have a single and a multiplayer pilot with the same callsign)
673         // we'll distinguish them by putting an M and the end of the multiplayer callsign and a P at the end of a single player
674         strcpy(str, Cur_pilot->callsign);
675         strcat(str, is_pilot_multi(Cur_pilot) ? NOX("M") : NOX("S"));
676         os_config_write_string( NULL, "LastPlayer", str );
677         return 0;
678 }
679
680 // scroll up barracks pilot list one line
681 void barracks_scroll_callsign_up()
682 {
683         if (Selected_line > 0) {
684                 Selected_line--;
685                 gamesnd_play_iface(SND_SCROLL);
686         } else {
687                 gamesnd_play_iface(SND_GENERAL_FAIL);
688         }
689         
690         if ((Selected_line >= 0) && (Selected_line < List_scroll_offset)) {
691                 List_scroll_offset = Selected_line;
692         }
693 }
694
695 // scroll down barracks pilot list one line
696 void barracks_scroll_callsign_down()
697 {
698         if (Selected_line < Num_pilots - 1) {
699                 Selected_line++;
700                 gamesnd_play_iface(SND_SCROLL);
701         } else {
702                 gamesnd_play_iface(SND_GENERAL_FAIL);
703         }
704         
705         // num_pilots_to_fill_height is the number of pilots that can fit in given height
706         int num_pilots_to_fill_height = Barracks_list_coords[gr_screen.res][BARRACKS_H_COORD] / gr_get_font_height();
707         if (Selected_line >= List_scroll_offset + num_pilots_to_fill_height) {
708                 List_scroll_offset++;
709         }
710 }
711
712 // scroll up barracks stats list one line
713 void barracks_scroll_stats_up()
714 {
715         if (Stats_scroll_offset > 0) {
716                 Stats_scroll_offset--;
717                 gamesnd_play_iface(SND_SCROLL);
718         } else {
719                 gamesnd_play_iface(SND_GENERAL_FAIL);
720         }
721 }
722
723 // scroll down barracks stats list one line
724 void barracks_scroll_stats_down()
725 {
726         int font_height = gr_get_font_height();
727
728         if (Stats_scroll_offset + Barracks_stats_coords[gr_screen.res][BARRACKS_H_COORD] / font_height < Num_stat_lines) {
729                 Stats_scroll_offset++;
730                 gamesnd_play_iface(SND_SCROLL);
731         } else {
732                 gamesnd_play_iface(SND_GENERAL_FAIL);
733         }
734 }
735
736 // show previous pilot pic
737 void barracks_prev_pic()
738 {
739         // check if no pilot images or no pilot selected
740         if ((Num_pilot_images == 0) || (Cur_pilot->callsign[0] == '\0')) {
741                 gamesnd_play_iface(SND_GENERAL_FAIL);
742                 return;
743         }
744
745         // reset pilot pic number
746         Pic_number--;
747         if (Pic_number < 0) {
748                 Pic_number = Num_pilot_images - 1;
749         }
750
751         // copy pilot pic filename into pilot struct
752         if ((Pic_number >= 0) && (Pic_number < Num_pilot_images)) {
753                 strcpy(Cur_pilot->image_filename, Pilot_image_names[Pic_number]);
754         }
755
756         // play scroll sound
757         gamesnd_play_iface(SND_SCROLL);
758 }
759
760 // show next pilot pic
761 void barracks_next_pic()
762 {
763         // check if no pilot images or no pilot selected
764         if ((Num_pilot_images == 0) || (Cur_pilot->callsign[0] == '\0')) {
765                 gamesnd_play_iface(SND_GENERAL_FAIL);
766                 return;
767         }
768
769         // reset pilot pic number
770         Pic_number++;
771         if (Pic_number >= Num_pilot_images){
772                 Pic_number = 0;
773         }
774
775         // copy pilot pic filename into pilot struct
776         if ((Pic_number >= 0) && (Pic_number < Num_pilot_images)){
777                 strcpy(Cur_pilot->image_filename, Pilot_image_names[Pic_number]);
778         }
779
780         // play scroll sound
781         gamesnd_play_iface(SND_SCROLL);
782 }
783
784 // show previous squad pic
785 void barracks_prev_squad_pic()
786 {
787         // check if no pilot images or no pilot selected
788         if ((Num_pilot_squad_images == 0) || (Cur_pilot->callsign[0] == '\0')) {
789                 gamesnd_play_iface(SND_GENERAL_FAIL);
790                 return;
791         }
792
793         // reset pilot pic number
794         Pic_squad_number--;
795         if (Pic_squad_number < 0) {
796                 Pic_squad_number = Num_pilot_squad_images - 1;
797         }
798
799         // copy pilot pic filename into pilot struct
800         if ((Pic_squad_number >= 0) && (Pic_squad_number < Num_pilot_squad_images)) {
801                 strcpy(Cur_pilot->squad_filename, Pilot_squad_image_names[Pic_squad_number]);
802         }
803
804         // play scroll sound
805         gamesnd_play_iface(SND_SCROLL);
806 }
807
808 // show next pilot pic
809 void barracks_next_squad_pic()
810 {
811         // check if no pilot images or no pilot selected
812         if ((Num_pilot_squad_images == 0) || (Cur_pilot->callsign[0] == '\0')) {
813                 gamesnd_play_iface(SND_GENERAL_FAIL);
814                 return;
815         }
816
817         // reset pilot pic number
818         Pic_squad_number++;
819         if (Pic_squad_number >= Num_pilot_squad_images){
820                 Pic_squad_number = 0;
821         }
822
823         // copy pilot pic filename into pilot struct
824         if ((Pic_squad_number >= 0) && (Pic_squad_number < Num_pilot_squad_images)){
825                 strcpy(Cur_pilot->squad_filename, Pilot_squad_image_names[Pic_squad_number]);
826         }
827
828         // play scroll sound
829         gamesnd_play_iface(SND_SCROLL);
830 }
831
832 void barracks_delete_pilot()
833 {
834         char buf[MAX_FILENAME_LEN];
835         int active = 0;
836
837         if (!Num_pilots) {
838                 gamesnd_play_iface(SND_GENERAL_FAIL);
839                 return;
840         }
841
842         int popup_rval = popup(PF_TITLE_BIG | PF_TITLE_RED, 2, POPUP_NO, POPUP_YES, XSTR( "Warning!\n\nAre you sure you wish to delete this pilot?", 65));
843         if (popup_rval != 1) {
844                 return;
845         }
846
847         if (!stricmp(Pilots[Selected_line], Cur_pilot->callsign)) {
848                 active = 1;
849         }
850
851         strcpy(buf, Pilots[Selected_line]);
852         for (int i=Selected_line; i<Num_pilots-1; i++) {
853                 strcpy(Pilots[i], Pilots[i + 1]);
854                 Pilot_ranks[i] = Pilot_ranks[i + 1];
855         }
856
857         Num_pilots--;
858         if (Selected_line >= Num_pilots) {
859                 Selected_line = Num_pilots - 1;
860         }
861
862         if (active) {
863                 if (Selected_line >= 0) {
864                         barracks_new_pilot_selected();
865                 } else {
866                         Cur_pilot->callsign[0] = 0;
867                 }
868         }
869
870         delete_pilot_file(buf, Player_sel_mode == PLAYER_SELECT_MODE_SINGLE ? 1 : 0);
871         gamesnd_play_iface(SND_USER_SELECT);
872 }
873
874 // Filter out pilots of wrong type (which shouldn't be in the directory we are checking, but just to be safe..)
875 int barracks_pilot_filter(char *filename)
876 {
877         int r, rank;
878
879         r = verify_pilot_file(filename, Player_sel_mode == PLAYER_SELECT_MODE_SINGLE, &rank);
880         if (rank >= Rank_pips_count)
881                 rank = Rank_pips_count - 1;
882
883         if (!r) {
884                 Pilot_ranks[Num_pilots++] = rank;
885         }
886
887         return !r;
888 }
889
890 // callback handler for the squadon selection buttons when they are disabled (in single player)
891 void barracks_squad_change_popup()
892 {
893         // show a popup
894         popup( PF_USE_AFFIRMATIVE_ICON | PF_NO_NETWORKING, 1, POPUP_OK, XSTR("You cannot change your squadron in Single Player mode.", 1445));
895 }
896
897
898 void barracks_init_player_stuff(int mode)
899 {
900         // determine if we should be looking for single or multiplayers at the outset
901         Player_sel_mode = mode;
902         
903         // get the list of pilots based upon whether we're in single or multiplayer mode
904         Num_pilots = 0;
905         Get_file_list_filter = barracks_pilot_filter;
906
907         // single player specific stuff
908         if (mode == PLAYER_SELECT_MODE_SINGLE) {
909                 Num_pilots = cf_get_file_list_preallocated(MAX_PILOTS, Pilots_arr, Pilots, CF_TYPE_SINGLE_PLAYERS, NOX("*.plr"), CF_SORT_TIME);
910
911                 // disable squad logo switching         
912                 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.hide();
913                 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.disable();
914                 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.set_disabled_action(barracks_squad_change_popup);
915                 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.hide();
916                 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.disable();                   
917                 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.set_disabled_action(barracks_squad_change_popup);
918         }
919         // multiplayer specific stuff
920         else {
921                 Num_pilots = cf_get_file_list_preallocated(MAX_PILOTS, Pilots_arr, Pilots, CF_TYPE_MULTI_PLAYERS, NOX("*.plr"), CF_SORT_TIME);
922
923                 // enable squad logo switching
924                 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.enable();
925                 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.unhide();
926                 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.enable();
927                 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.unhide();                    
928         }
929
930         int ranks[MAX_PILOTS];
931
932         for (int i=0; i<Num_pilots; i++) {
933                 int j;
934                 for (j=0; j<Num_pilots; j++) {
935                         if (!strcmp(Pilots[i], Pilots_arr[j])) {
936                                 ranks[i] = Pilot_ranks[j];
937                                 break;
938                         }
939                 }
940                 Assert(j < Num_pilots);  // Pilot not found?  How is that possible?
941         }
942
943         for (int i=0; i<Num_pilots; i++) {
944                 Pilot_ranks[i] = ranks[i];
945         }
946
947         Selected_line = List_scroll_offset = 0;
948         barracks_new_pilot_selected();
949
950 }
951
952 void barracks_button_pressed(int n)
953 {
954         switch (n) {
955                 case B_PILOT_SCROLL_UP_BUTTON:
956                         barracks_scroll_callsign_up();
957                         break;
958
959                 case B_PILOT_SCROLL_DOWN_BUTTON:
960                         barracks_scroll_callsign_down();
961                         break;
962
963                 case B_STATS_SCROLL_UP_BUTTON:
964                         barracks_scroll_stats_up();
965                         break;
966
967                 case B_STATS_SCROLL_DOWN_BUTTON:
968                         barracks_scroll_stats_down();
969                         break;
970
971                 case B_PIC_PREV_PILOT_BUTTON:
972                         barracks_prev_pic();
973                         break;
974
975                 case B_PIC_NEXT_PILOT_BUTTON:
976                         barracks_next_pic();
977                         break;
978
979                 case B_SQUAD_PREV_BUTTON:
980                         barracks_prev_squad_pic();
981                         break;
982
983                 case B_SQUAD_NEXT_BUTTON:
984                         barracks_next_squad_pic();
985                         break;
986
987                 case B_PILOT_SET_ACTIVE_BUTTON:
988                         if (barracks_new_pilot_selected()){
989                                 gamesnd_play_iface(SND_GENERAL_FAIL);
990                                 
991                                 // throw up a popup telling the player that he should create a pilot first
992                                 if(Player_sel_mode == PLAYER_SELECT_MODE_SINGLE){
993                                         popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR( "You must create a single player pilot.", 66));
994                                 } else {
995                                         popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR( "You must create a multi player pilot.", 67));
996                                 }
997                         } else {
998                                 gamesnd_play_iface(SND_SCROLL);
999                         }
1000                         break;
1001
1002                 case B_ACCEPT_BUTTON:                   
1003                         if (Num_pilots && !barracks_pilot_accepted()) {
1004                                 gamesnd_play_iface(SND_COMMIT_PRESSED);
1005                                 gameseq_post_event(GS_EVENT_MAIN_MENU);
1006                         } else {
1007                                 gamesnd_play_iface(SND_GENERAL_FAIL);
1008
1009                                 // throw up a popup telling the player that he should create a pilot first
1010                                 if(Player_sel_mode == PLAYER_SELECT_MODE_SINGLE){
1011                                         popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR( "You must create a single player pilot.", 66));
1012                                 } else {
1013                                         popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR( "You must create a multi player pilot.", 67));
1014                                 }
1015                         }
1016                         break;
1017
1018                 case B_PILOT_CLONE_BUTTON:
1019                         if (Num_pilots < 1) {
1020                                 gamesnd_play_error_beep();
1021                                 break;
1022                         }
1023
1024                         Clone_flag = 1;
1025                         barracks_create_new_pilot();
1026                         break;
1027
1028                 case B_PILOT_CONVERT_BUTTON: {
1029 #if defined(DEMO) || defined(OEM_BUILD)
1030                         game_feature_not_in_demo_popup();
1031 #else
1032                         char temp[256], *str;
1033                         char old_pic[256] = "";
1034                         char old_squad_pic[256] = "";
1035                         char old_squad[256] = "";
1036                         int z;
1037
1038                         if (!barracks_new_pilot_selected()) {
1039                                 if (Player_sel_mode == PLAYER_SELECT_MODE_SINGLE)
1040                                         str = XSTR( "multiplayer", 68);
1041                                 else
1042                                         str = XSTR( "single player", 69);
1043
1044                                 sprintf(temp, XSTR( "This will overwrite your %s pilot.  Proceed?", 70), str);
1045                                 if (!verify_pilot_file(Cur_pilot->callsign, Player_sel_mode == PLAYER_SELECT_MODE_MULTI)) {
1046                                         z = popup(0, 2, POPUP_CANCEL, POPUP_OK, temp);
1047                                         if (z != 1)
1048                                                 break;
1049                                 }
1050
1051                                 strcpy(old_pic, Cur_pilot->image_filename);
1052                                 strcpy(old_squad_pic, Cur_pilot->squad_filename);
1053                                 strcpy(old_squad, Cur_pilot->squad_name);
1054                                 init_new_pilot(Cur_pilot, 0);
1055                                 strcpy(Cur_pilot->image_filename, old_pic);
1056                                 strcpy(Cur_pilot->squad_filename, old_squad_pic);
1057                                 strcpy(Cur_pilot->squad_name, old_squad);
1058                                 if (Player_sel_mode == PLAYER_SELECT_MODE_SINGLE) {
1059                                         Cur_pilot->flags |= PLAYER_FLAGS_IS_MULTI;
1060                                         write_pilot_file();
1061                                         barracks_init_player_stuff(PLAYER_SELECT_MODE_MULTI);
1062
1063                                 } else {
1064                                         write_pilot_file();
1065                                         barracks_init_player_stuff(PLAYER_SELECT_MODE_SINGLE);
1066                                 }
1067
1068                                 gamesnd_play_iface(SND_USER_SELECT);
1069
1070                         } else {
1071                                 gamesnd_play_iface(SND_GENERAL_FAIL);
1072                         }
1073 #endif
1074                         break;
1075                 }
1076
1077                 case B_PILOT_CREATE_BOTTON:
1078                         Clone_flag = 0;
1079                         barracks_create_new_pilot();
1080                         break;
1081
1082                 case B_HELP_BUTTON:
1083                         launch_context_help();
1084                         gamesnd_play_iface(SND_HELP_PRESSED);
1085                         break;
1086
1087                 case B_OPTION_BUTTON:
1088                         gamesnd_play_iface(SND_SWITCH_SCREENS);
1089                         gameseq_post_event(GS_EVENT_OPTIONS_MENU);
1090                         break;
1091
1092                 case B_STATS_MEDAL_BUTTON:
1093 #ifdef FS2_DEMO
1094                         game_feature_not_in_demo_popup();
1095 #else
1096                         gamesnd_play_iface(SND_SWITCH_SCREENS);
1097                         gameseq_post_event(GS_EVENT_VIEW_MEDALS);
1098 #endif
1099                         break;
1100
1101                 case B_PILOT_DELETE_BUTTON:
1102                         barracks_delete_pilot();
1103                         break;
1104
1105                 case B_PILOT_SINGLE_MODE_BUTTON:
1106                         if (Player_sel_mode != PLAYER_SELECT_MODE_SINGLE) {
1107                                 gamesnd_play_iface(SND_USER_SELECT);
1108                                 barracks_init_player_stuff(PLAYER_SELECT_MODE_SINGLE);
1109                         }                                               
1110                         break;
1111
1112                 case B_PILOT_MULTI_MODE_BUTTON:
1113 #if defined(DEMO) || defined(OEM_BUILD) // not for FS2_DEMO
1114                         game_feature_not_in_demo_popup();
1115 #else
1116                         if (Player_sel_mode != PLAYER_SELECT_MODE_MULTI) {
1117                                 gamesnd_play_iface(SND_USER_SELECT);
1118                                 barracks_init_player_stuff(PLAYER_SELECT_MODE_MULTI);
1119                         }
1120 #endif
1121                         break;
1122         }
1123 }
1124
1125
1126 void barracks_display_pilot_callsigns(int prospective_pilot)
1127 {
1128         int y = 0;
1129         int cur_pilot_idx = List_scroll_offset;
1130
1131         int multi = 0;
1132         if (Player_sel_mode == PLAYER_SELECT_MODE_MULTI) {
1133                 multi = 1;
1134         }
1135
1136         int font_height = gr_get_font_height();
1137         while (y + font_height <= Barracks_list_coords[gr_screen.res][BARRACKS_H_COORD]) {
1138                 if (cur_pilot_idx >= Num_pilots)
1139                         break;
1140
1141                 if (!stricmp(Cur_pilot->callsign, Pilots[cur_pilot_idx]) && (is_pilot_multi(Cur_pilot) == multi)) {
1142                         if ((cur_pilot_idx == Selected_line) || (cur_pilot_idx == prospective_pilot)) {
1143                                 gr_set_color_fast(&Color_text_active_hi);
1144                         } else {
1145                                 gr_set_color_fast(&Color_text_active);
1146                         }
1147                 } else {
1148                         if (cur_pilot_idx == Selected_line) {
1149                                 gr_set_color_fast(&Color_text_selected);
1150                         } else if (cur_pilot_idx == prospective_pilot) {
1151                                 gr_set_color_fast(&Color_text_subselected);
1152                         } else {
1153                                 gr_set_color_fast(&Color_text_normal);
1154                         }
1155                 }
1156
1157                 gr_printf(Barracks_list_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_list_coords[gr_screen.res][BARRACKS_Y_COORD] + y, Pilots[cur_pilot_idx]);
1158                 gr_set_bitmap(Rank_pips_bitmaps + Pilot_ranks[cur_pilot_idx]);
1159                 gr_bitmap(Barracks_list_coords[gr_screen.res][BARRACKS_X_COORD] - 34, Barracks_list_coords[gr_screen.res][BARRACKS_Y_COORD] + y);
1160  
1161                 y += font_height;
1162                 cur_pilot_idx++;
1163         }
1164 }
1165
1166
1167
1168 void barracks_display_pilot_stats()
1169 {
1170         int y = 0;
1171         int z = Stats_scroll_offset;
1172         int font_height = gr_get_font_height();
1173         char *str;
1174         int i, w, h;
1175         while (y + font_height <= Barracks_stats_coords[gr_screen.res][BARRACKS_H_COORD]) {
1176                 if (z >= Num_stat_lines) {
1177                         break;
1178                 }
1179
1180                 str = Stat_labels[z];
1181                 if (*str == '*') {
1182                         gr_set_color_fast(&Color_text_heading);
1183                         str++;
1184
1185                         gr_get_string_size(&w, &h, str);
1186                         i = Barracks_stats_coords[gr_screen.res][BARRACKS_Y_COORD] + y + h / 2 - 1;                     
1187                         gr_line(Barracks_stats_coords[gr_screen.res][BARRACKS_X_COORD], i, Barracks_stats_coords[gr_screen.res][BARRACKS_X_COORD] + Barracks_stats_coords[gr_screen.res][BARRACKS_W_COORD] - w - 2, i);
1188                         gr_line(Barracks_stats_coords[gr_screen.res][BARRACKS_X_COORD] + Barracks_stats_coords[gr_screen.res][BARRACKS_W_COORD] + 1, i, Barracks_stats2_coords[gr_screen.res][BARRACKS_X_COORD] + Barracks_stats2_coords[gr_screen.res][BARRACKS_W_COORD], i);
1189
1190                 } else {
1191                         gr_set_color_fast(&Color_text_normal);
1192                 }
1193
1194                 gr_get_string_size(&w, NULL, str);
1195                 gr_printf(Barracks_stats_coords[gr_screen.res][BARRACKS_X_COORD] + Barracks_stats_coords[gr_screen.res][BARRACKS_W_COORD] - w, Barracks_stats_coords[gr_screen.res][BARRACKS_Y_COORD] + y, "%s", str);
1196                 str = Stats[z];
1197                 if (*str) {
1198                         gr_printf(Barracks_stats2_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_stats_coords[gr_screen.res][BARRACKS_Y_COORD] + y, "%s", str);
1199                 }
1200
1201                 y += font_height;
1202                 z++;
1203         }
1204 }
1205
1206
1207 // process pilot callsign
1208 void barracks_accept_new_pilot_callsign()
1209 {
1210         char buf[CALLSIGN_LEN + 1];
1211         char name[MAX_FILENAME_LEN];
1212         int i;
1213
1214         int z = 0;
1215         Inputbox.get_text(buf);
1216         drop_white_space(buf);
1217
1218         if (!isalpha(*buf)) {
1219                 z = 1;
1220         } else {
1221                 for (i=1; buf[i]; i++) {
1222                         if (!isalpha(buf[i]) && !isdigit(buf[i]) && !strchr(VALID_PILOT_CHARS, buf[i])) {
1223                                 z = 1;
1224                                 return;
1225                         }
1226                 }
1227         }
1228
1229         for (i=1; i<Num_pilots; i++) {
1230                 if (!stricmp(buf, Pilots[i])) {
1231                         z = 1;
1232                         if (pilot_verify_overwrite() == 1) {
1233                                 strcpy(name, Pilots[Selected_line]);
1234                                 for (z=i; z<Num_pilots-1; z++) {
1235                                         strcpy(Pilots[z], Pilots[z + 1]);
1236                                         Pilot_ranks[z] = Pilot_ranks[z + 1];
1237                                 }
1238
1239                                 Num_pilots--;
1240                                 delete_pilot_file(name, Player_sel_mode == PLAYER_SELECT_MODE_SINGLE ? 1 : 0);
1241                                 z = 0;
1242                         }
1243                         return;
1244                 }
1245         }
1246
1247         if (!*buf || (i < Num_pilots)) { // duplicate name, alert user
1248                 z = 1;
1249         }
1250
1251         if (z) {
1252                 gamesnd_play_iface(SND_GENERAL_FAIL);
1253                 return;
1254         }
1255
1256         strcpy(Pilots[0], buf);
1257         strcpy(Cur_pilot->callsign, buf);
1258         init_new_pilot(Cur_pilot, !Clone_flag);
1259         
1260         // again, make sure we set his flags correctly to ensure that he gets saved to the proper directory and gets
1261         // displayed correctly
1262         if (Player_sel_mode == PLAYER_SELECT_MODE_SINGLE) {
1263                 Cur_pilot->flags &= ~(PLAYER_FLAGS_IS_MULTI);
1264         } else {
1265                 Cur_pilot->flags |= PLAYER_FLAGS_IS_MULTI;
1266                 Cur_pilot->stats.flags |= STATS_FLAG_MULTIPLAYER;
1267         }
1268
1269         if ( !(Game_mode & GM_STANDALONE_SERVER) ) {
1270                 write_pilot_file(Cur_pilot);
1271         }
1272
1273         Selected_line = 0;
1274         barracks_new_pilot_selected();
1275         barracks_set_callsign_enter_mode(false);
1276 }
1277
1278
1279 // draw pilot image and clean up afterwards
1280 void barracks_draw_pilot_pic()
1281 {
1282         // draw pilot pic
1283         if (Cur_pilot->callsign[0] && (Pic_number >= 0) && (Pic_number < Num_pilot_images)) {
1284                 if (Pilot_images[Pic_number] >= 0) {
1285                         // JAS: This code is hacked to allow the animation to use all 256 colors
1286                         extern int Palman_allow_any_color;
1287                         Palman_allow_any_color = 1;
1288                         gr_set_bitmap(Pilot_images[Pic_number]);
1289                         gr_bitmap(Barracks_image_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_image_coords[gr_screen.res][BARRACKS_Y_COORD]);
1290                         Palman_allow_any_color = 0;
1291
1292                         // print number of the current pic
1293                         char buf[40];                   
1294                         sprintf(buf, XSTR( "%d of %d", 71), Pic_number + 1, Num_pilot_images);
1295                         gr_printf(Barracks_image_number_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_image_number_coords[gr_screen.res][BARRACKS_Y_COORD], buf);                           
1296                 }
1297         } else {
1298                 Pic_number = -1;
1299         }
1300 }
1301
1302 // draw squad image and clean up afterwards
1303 void barracks_draw_squad_pic()
1304 {
1305         char buf[40];
1306
1307         // draw pilot pic
1308         if (Cur_pilot->callsign[0] && (Pic_squad_number >= 0) && (Pic_squad_number < Num_pilot_squad_images)) {
1309                 if (Pilot_squad_images[Pic_squad_number] >= 0) {
1310                         // JAS: This code is hacked to allow the animation to use all 256 colors
1311                         extern int Palman_allow_any_color;
1312                         Palman_allow_any_color = 1;
1313                         gr_set_bitmap(Pilot_squad_images[Pic_squad_number]);
1314                         gr_bitmap(Barracks_squad_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_squad_coords[gr_screen.res][BARRACKS_Y_COORD]);
1315                         Palman_allow_any_color = 0;
1316
1317                         // print number of current squad pic
1318                         if(Player_sel_mode != PLAYER_SELECT_MODE_SINGLE){
1319                                 sprintf(buf,XSTR( "%d of %d", 71), Pic_squad_number+1, Num_pilot_squad_images);
1320                                 gr_printf(Barracks_squad_number_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_squad_number_coords[gr_screen.res][BARRACKS_Y_COORD], buf);
1321                         }
1322                 }
1323         } else {
1324                 Pic_squad_number = -1;
1325         }       
1326 }
1327
1328 // -----------------------------------------------------------------------------
1329 void barracks_init()
1330 {
1331         UI_WINDOW *w = &Ui_window;
1332
1333         // save current pilot file, so we don't possibly loose it.
1334         write_pilot_file();
1335
1336         // create interface
1337         Ui_window.create(0, 0, gr_screen.max_w, gr_screen.max_h, 0);
1338         Ui_window.set_mask_bmap(Barracks_bitmap_mask_fname[gr_screen.res]);
1339
1340         // load background bitmap
1341         Background_bitmap = bm_load(Barracks_bitmap_fname[gr_screen.res]);
1342         if(Background_bitmap < 0){
1343                 // we failed to load the bitmap - this is very bad
1344                 Int3();
1345         }
1346
1347         // create buttons
1348         for (int i=0; i<BARRACKS_NUM_BUTTONS; i++) {
1349                 // create the object
1350                 Buttons[gr_screen.res][i].button.create(&Ui_window, "", Buttons[gr_screen.res][i].x, Buttons[gr_screen.res][i].y, 60, 30, Buttons[gr_screen.res][i].repeat, 1);
1351
1352                 // set the sound to play when highlighted
1353                 Buttons[gr_screen.res][i].button.set_highlight_action(common_play_highlight_sound);
1354
1355                 // set the ani for the button
1356                 Buttons[gr_screen.res][i].button.set_bmaps(Buttons[gr_screen.res][i].filename);
1357
1358                 // set the hotspot
1359                 Buttons[gr_screen.res][i].button.link_hotspot(Buttons[gr_screen.res][i].hotspot);
1360         }
1361
1362         // add all strings      
1363         w->add_XSTR("Create", 1034, Buttons[gr_screen.res][0].text_x,  Buttons[gr_screen.res][0].text_y, &Buttons[gr_screen.res][0].button, UI_XSTR_COLOR_GREEN);
1364         w->add_XSTR("Accept", 1035, Buttons[gr_screen.res][5].text_x,  Buttons[gr_screen.res][5].text_y, &Buttons[gr_screen.res][5].button, UI_XSTR_COLOR_PINK);
1365         w->add_XSTR("Help",   928, Buttons[gr_screen.res][6].text_x,  Buttons[gr_screen.res][6].text_y, &Buttons[gr_screen.res][6].button, UI_XSTR_COLOR_GREEN);
1366         w->add_XSTR("Options",1036, Buttons[gr_screen.res][7].text_x,  Buttons[gr_screen.res][7].text_y, &Buttons[gr_screen.res][7].button, UI_XSTR_COLOR_GREEN);
1367         w->add_XSTR("Medals", 1037, Buttons[gr_screen.res][8].text_x,  Buttons[gr_screen.res][8].text_y, &Buttons[gr_screen.res][8].button, UI_XSTR_COLOR_GREEN);
1368         w->add_XSTR("Remove", 1038, Buttons[gr_screen.res][11].text_x,  Buttons[gr_screen.res][11].text_y, &Buttons[gr_screen.res][11].button, UI_XSTR_COLOR_GREEN);
1369         w->add_XSTR("Select", 1552, Buttons[gr_screen.res][12].text_x,  Buttons[gr_screen.res][12].text_y, &Buttons[gr_screen.res][12].button, UI_XSTR_COLOR_GREEN);
1370         w->add_XSTR("Clone",  1040, Buttons[gr_screen.res][13].text_x,  Buttons[gr_screen.res][13].text_y, &Buttons[gr_screen.res][13].button, UI_XSTR_COLOR_GREEN);
1371         w->add_XSTR("Single", 1041, Buttons[gr_screen.res][14].text_x,  Buttons[gr_screen.res][14].text_y,  &Buttons[gr_screen.res][14].button, UI_XSTR_COLOR_GREEN);
1372         w->add_XSTR("Multi",  1042, Buttons[gr_screen.res][15].text_x,  Buttons[gr_screen.res][15].text_y,  &Buttons[gr_screen.res][15].button, UI_XSTR_COLOR_GREEN);
1373         w->add_XSTR("Convert",1043, Buttons[gr_screen.res][16].text_x,  Buttons[gr_screen.res][16].text_y, &Buttons[gr_screen.res][16].button, UI_XSTR_COLOR_GREEN);    
1374         for(int i=0; i<BARRACKS_NUM_TEXT; i++) {
1375                 w->add_XSTR(&Barracks_text[gr_screen.res][i]);
1376         }
1377
1378         // button for selecting pilot
1379         List_region.create(&Ui_window, "", Barracks_list_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_list_coords[gr_screen.res][BARRACKS_Y_COORD], Barracks_list_coords[gr_screen.res][BARRACKS_W_COORD], Barracks_list_coords[gr_screen.res][BARRACKS_H_COORD], 0, 1);
1380         List_region.hide();
1381
1382         // create input box (for new pilot)
1383         Inputbox.create(&Ui_window, Barracks_list_coords[gr_screen.res][BARRACKS_X_COORD], Barracks_list_coords[gr_screen.res][BARRACKS_Y_COORD], Barracks_list_coords[gr_screen.res][BARRACKS_W_COORD], CALLSIGN_LEN - 1, "", UI_INPUTBOX_FLAG_INVIS | UI_INPUTBOX_FLAG_KEYTHRU | UI_INPUTBOX_FLAG_LETTER_FIRST);
1384         Inputbox.set_valid_chars(VALID_PILOT_CHARS);
1385         Inputbox.disable();
1386         Inputbox.hide();
1387
1388         // load in help overlay bitmap  
1389         help_overlay_load(BARRACKS_OVERLAY);
1390         help_overlay_set_state(BARRACKS_OVERLAY,0);     
1391
1392         // other init stuff
1393         Barracks_callsign_enter_mode = 0;       
1394         List_scroll_offset = Stats_scroll_offset = Pic_number = Pic_squad_number = Selected_line = 0;
1395         Cur_pilot = &Players[Player_num];
1396
1397         // disable squad logo selection buttons in single player
1398         if(!(Cur_pilot->flags & PLAYER_FLAGS_IS_MULTI)){
1399                 // squad logo picture buttons           
1400                 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.hide();
1401                 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.disable();
1402                 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.hide();
1403                 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.disable();
1404         } else {
1405                 // squad logo picture buttons           
1406                 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.enable();
1407                 Buttons[gr_screen.res][B_SQUAD_PREV_BUTTON].button.unhide();
1408                 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.enable();
1409                 Buttons[gr_screen.res][B_SQUAD_NEXT_BUTTON].button.unhide();            
1410         }
1411
1412         // set up hotkeys for buttons so we draw the correct animation frame when a key is pressed
1413         barracks_set_hotkeys(1);
1414
1415         // load ramp pips
1416         Rank_pips_bitmaps = bm_load_animation("IconRankMini.ani", &Rank_pips_count);    
1417
1418         // load up the pilot pic list
1419         pilot_load_pic_list();  
1420         pilot_load_squad_pic_list();
1421         
1422         // don't load pilot images yet
1423         for (int i=0; i<MAX_PILOT_IMAGES; i++) {
1424                 Pilot_images[i] = BARRACKS_IMAGE_NOT_LOADED;  // while -1 is can't load
1425                 Pilot_squad_images[i] = BARRACKS_IMAGE_NOT_LOADED;
1426         }
1427         
1428         // init stats
1429         barracks_init_stats(&Cur_pilot->stats);
1430
1431         // disable some buttons for the multiplayer beta and e3 build
1432 #if defined(MULTIPLAYER_BETA_BUILD) || defined(E3_BUILD) || defined(PRESS_TOUR_BUILD)
1433         Buttons[gr_screen.res][B_PILOT_CLONE_BUTTON].button.hide();
1434         Buttons[gr_screen.res][B_PILOT_CONVERT_BUTTON].button.hide();   
1435         Buttons[gr_screen.res][B_PILOT_CLONE_BUTTON].button.disable();  
1436         Buttons[gr_screen.res][B_PILOT_CONVERT_BUTTON].button.disable();        
1437 #endif
1438
1439         // multiplayer beta build
1440 #ifdef MULTIPLAYER_BETA_BUILD
1441         Buttons[gr_screen.res][B_PILOT_SINGLE_MODE_BUTTON].button.hide();
1442         Buttons[gr_screen.res][B_PILOT_SINGLE_MODE_BUTTON].button.disable();
1443 #endif
1444
1445         // e3 build
1446 #if defined(E3_BUILD) || defined(PRESS_TOUR_BUILD)
1447         Buttons[gr_screen.res][B_PILOT_MULTI_MODE_BUTTON].button.hide();
1448         Buttons[gr_screen.res][B_PILOT_MULTI_MODE_BUTTON].button.disable();
1449 #endif
1450         
1451         // base the mode we're in (single or multi) on the status of the currently selected pilot
1452 #ifdef MULTIPLAYER_BETA_BUILD
1453         barracks_init_player_stuff(1);
1454 #elif defined(E3_BUILD) || defined(PRESS_TOUR_BUILD)
1455         barracks_init_player_stuff(0);
1456 #else
1457         barracks_init_player_stuff(is_pilot_multi(Player));     
1458 #endif
1459 }
1460
1461 // -----------------------------------------------------------------------------
1462 void barracks_do_frame(float frametime)
1463 {
1464         int k = Ui_window.process();
1465
1466         if ( k > 0 ) {
1467                 if ( help_overlay_active(BARRACKS_OVERLAY) ) {
1468                         help_overlay_set_state(BARRACKS_OVERLAY,0);
1469                         k = 0;
1470                 }
1471         }
1472
1473         // pilot that mouse is over
1474         int prospective_pilot = -1;
1475         int i;
1476
1477         // Entering pilot callsign
1478         if (Barracks_callsign_enter_mode) {
1479                 // set focus to inputbox
1480                 Inputbox.set_focus();
1481
1482                 switch (k) {
1483                         case KEY_ESC:
1484                                 // cancel create pilot
1485                                 Num_pilots--;
1486                                 for (i=0; i<Num_pilots; i++) {
1487                                         strcpy(Pilots[i], Pilots[i + 1]);
1488                                         Pilot_ranks[i] = Pilot_ranks[i + 1];
1489                                 }
1490
1491                                 barracks_set_callsign_enter_mode(false);
1492                                 break;
1493
1494                         case KEY_ENTER: 
1495                                 barracks_accept_new_pilot_callsign();
1496                                 break;
1497                 } 
1498         } else {
1499                 // not entering pilot callsign
1500                 switch (k) {
1501                         case KEY_ENTER:
1502                                 if (barracks_new_pilot_selected()) {
1503                                         gamesnd_play_iface(SND_GENERAL_FAIL);
1504                                 } else {
1505                                         gamesnd_play_iface(SND_USER_SELECT);
1506                                 }
1507                                 break;
1508
1509                         case KEY_ESC:  // cancel
1510                                 if (!help_overlay_active(BARRACKS_OVERLAY)) {
1511                                         if (Num_pilots && !barracks_pilot_accepted()) {
1512                                                 gameseq_post_event(GS_EVENT_MAIN_MENU);
1513                                         } else {
1514                                                 gamesnd_play_iface(SND_GENERAL_FAIL);
1515                                         }
1516                                 } else {
1517                                         // kill the overlay
1518                                         help_overlay_set_state(BARRACKS_OVERLAY,0);
1519                                 }
1520                                 break;
1521
1522                         case KEY_TAB:  // switch mode (simgle/multi)
1523 #if defined(DEMO) || defined(OEM_BUILD) // not for FS2_DEMO
1524         game_feature_not_in_demo_popup();
1525 #else
1526                                 if (Player_sel_mode == PLAYER_SELECT_MODE_SINGLE) {
1527                                         barracks_init_player_stuff(PLAYER_SELECT_MODE_MULTI);
1528                                 } else {
1529                                         barracks_init_player_stuff(PLAYER_SELECT_MODE_SINGLE);
1530                                 }
1531
1532                                 gamesnd_play_iface(SND_USER_SELECT);
1533 #endif
1534                                 break;
1535
1536                         case KEY_F1:  // show help overlay
1537                                 gamesnd_play_iface(SND_HELP_PRESSED);
1538                                 break;
1539
1540                         case KEY_F2:  // goto options screen
1541                                 gamesnd_play_iface(SND_SWITCH_SCREENS);
1542                                 gameseq_post_event(GS_EVENT_OPTIONS_MENU);
1543                                 break;
1544                 }       // end switch
1545
1546                 // process buttons
1547                 for (i=0; i<BARRACKS_NUM_BUTTONS; i++) {
1548                         if (Buttons[gr_screen.res][i].button.pressed()) {
1549                                 barracks_button_pressed(i);
1550                         }
1551                 }
1552
1553                 // if mouse is over a pilot, find index into Pilots array
1554                 if (List_region.is_mouse_on()) {
1555                         int y;
1556                         List_region.get_mouse_pos(NULL, &y);
1557                         int pilot_index = List_scroll_offset + (y / gr_get_font_height());
1558                         if ((pilot_index >= 0) && (pilot_index < Num_pilots)) {
1559                                 prospective_pilot = pilot_index;
1560                         }
1561                 }
1562                 
1563                 // if mouse clicked in list region, find index into Pilots array 
1564                 if (List_region.pressed()) {
1565                         if (prospective_pilot != -1) {
1566                                 Selected_line = prospective_pilot;
1567                                 gamesnd_play_iface(SND_USER_SELECT);
1568                         }
1569                 }
1570         }
1571
1572         // check mouse over help
1573         if (mouse_down(MOUSE_LEFT_BUTTON)) {
1574                 help_overlay_set_state(BARRACKS_OVERLAY, 0);
1575         }
1576
1577         // do pilot pic stuff
1578         if ((Pic_number >= 0) && (Pic_number < Num_pilot_images)) {
1579                 if (Pilot_images[Pic_number] == BARRACKS_IMAGE_NOT_LOADED) {  // haven't tried loading it yet
1580                         Pilot_images[Pic_number] = bm_load(Pilot_image_names[Pic_number]);
1581                         if (Pilot_images[Pic_number] >= 0) {
1582                                 int w, h;
1583
1584                                 bm_get_info(Pilot_images[Pic_number], &w, &h, NULL);
1585                                 // check for invalid pilot pic file
1586                                 if ((w != PLAYER_PILOT_PIC_W) || (h != PLAYER_PILOT_PIC_H)) {
1587                                         bm_unload(Pilot_images[Pic_number]);
1588                                         Pilot_images[Pic_number] = -1;
1589                                 }
1590                         }
1591                 }               
1592         } else {
1593                 Pic_number = -1;
1594         }
1595
1596         // do squad pic stuff
1597         if ((Pic_squad_number >= 0) && (Pic_squad_number < Num_pilot_squad_images)) {
1598                 if (Pilot_squad_images[Pic_squad_number] == BARRACKS_IMAGE_NOT_LOADED) {  // haven't tried loading it yet
1599                         Pilot_squad_images[Pic_squad_number] = bm_load_duplicate(Pilot_squad_image_names[Pic_squad_number]);
1600                         if (Pilot_squad_images[Pic_squad_number] >= 0) {
1601                                 int w, h;
1602
1603                                 bm_get_info(Pilot_squad_images[Pic_squad_number], &w, &h, NULL);
1604                                 // check for invalid pilot pic file
1605                                 if ((w != PLAYER_SQUAD_PIC_W) || (h != PLAYER_SQUAD_PIC_H)) {
1606                                         bm_unload(Pilot_squad_images[Pic_squad_number]);
1607                                         Pilot_squad_images[Pic_squad_number] = -1;
1608                                 }
1609                         }
1610                 }
1611         } else {
1612                 Pic_squad_number = -1;
1613         }
1614
1615         // draw the background, etc
1616         gr_reset_clip();        
1617         GR_MAYBE_CLEAR_RES(Background_bitmap);
1618         if (Background_bitmap >= 0) {
1619                 gr_set_bitmap(Background_bitmap);
1620                 gr_bitmap(0, 0);        
1621         }               
1622
1623         // draw pilot image and clean up afterwards
1624         barracks_draw_pilot_pic();
1625         barracks_draw_squad_pic();
1626
1627         // draw the window      
1628         Ui_window.draw();       
1629
1630         // light up the correct mode button (single or multi)   
1631         if (Player_sel_mode == PLAYER_SELECT_MODE_SINGLE) {
1632                 Buttons[gr_screen.res][B_PILOT_SINGLE_MODE_BUTTON].button.draw_forced(2);
1633         } else {
1634                 Buttons[gr_screen.res][B_PILOT_MULTI_MODE_BUTTON].button.draw_forced(2);
1635         }       
1636
1637         // write out pilot call signs
1638         barracks_display_pilot_callsigns(prospective_pilot);
1639
1640         // write out current pilot stats
1641         barracks_display_pilot_stats();
1642
1643         // blit help overlay if active
1644         help_overlay_maybe_blit(BARRACKS_OVERLAY);      
1645         
1646         // flip the page
1647         gr_flip();
1648 }
1649
1650 // -----------------------------------------------------------------------------
1651 void barracks_close()
1652 {
1653         // destroy window
1654         Ui_window.destroy();
1655
1656         // release background bitmap
1657         if (Background_bitmap >= 0) {
1658                 bm_unload(Background_bitmap);
1659         }       
1660
1661         // release rank pip bitmaps
1662         for (int i=0; i<Rank_pips_count; i++) {
1663                 bm_release(Rank_pips_bitmaps + i);
1664         }       
1665
1666         // release pilot pic bitmaps
1667         for (int i=0; i<Num_pilot_images; i++) {
1668                 if (Pilot_images[i] >= 0) {
1669                         bm_unload(Pilot_images[i]);
1670                 }
1671         }
1672
1673         // unload the overlay bitmap
1674         help_overlay_unload(BARRACKS_OVERLAY);
1675
1676         game_flush();
1677 }
1678