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