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