]> icculus.org git repositories - taylor/freespace2.git/blob - src/missionui/missionscreencommon.cpp
cleanup; compile warning fixes
[taylor/freespace2.git] / src / missionui / missionscreencommon.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/MissionUI/MissionScreenCommon.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * $Log$
16  * Revision 1.7  2003/08/03 16:10:29  taylor
17  * cleanup; compile warning fixes
18  *
19  * Revision 1.6  2003/06/11 18:30:33  taylor
20  * plug memory leaks
21  *
22  * Revision 1.5  2003/05/25 02:30:43  taylor
23  * Freespace 1 support
24  *
25  * Revision 1.4  2002/06/09 04:41:23  relnev
26  * added copyright header
27  *
28  * Revision 1.3  2002/06/01 07:12:33  relnev
29  * a few NDEBUG updates.
30  *
31  * removed a few warnings.
32  *
33  * Revision 1.2  2002/05/07 03:16:46  theoddone33
34  * The Great Newline Fix
35  *
36  * Revision 1.1.1.1  2002/05/03 03:28:10  root
37  * Initial import.
38  *
39  * 
40  * 13    10/14/99 2:51p Jefff
41  * localiztion fixes
42  * 
43  * 12    8/05/99 3:40p Jefff
44  * hi-res text adjustments
45  * 
46  * 11    7/15/99 9:20a Andsager
47  * FS2_DEMO initial checkin
48  * 
49  * 10    2/01/99 5:55p Dave
50  * Removed the idea of explicit bitmaps for buttons. Fixed text
51  * highlighting for disabled gadgets.
52  * 
53  * 9     1/30/99 7:33p Neilk
54  * Fixed coords problems for mission briefing screens
55  * 
56  * 8     1/30/99 5:08p Dave
57  * More new hi-res stuff.Support for nice D3D textures.
58  * 
59  * 7     1/29/99 4:17p Dave
60  * New interface screens.
61  * 
62  * 6     1/24/99 11:37p Dave
63  * First full rev of beam weapons. Very customizable. Removed some bogus
64  * Int3()'s in low level net code.
65  * 
66  * 5     11/30/98 1:07p Dave
67  * 16 bit conversion, first run.
68  * 
69  * 4     11/17/98 11:12a Dave
70  * Removed player identification by address. Now assign explicit id #'s.
71  * 
72  * 3     10/16/98 9:40a Andsager
73  * Remove ".h" files from model.h
74  * 
75  * 2     10/07/98 10:53a Dave
76  * Initial checkin.
77  * 
78  * 1     10/07/98 10:50a Dave
79  * 
80  * 85    6/09/98 10:31a Hoffoss
81  * Created index numbers for all xstr() references.  Any new xstr() stuff
82  * added from here on out should be added to the end if the list.  The
83  * current list count can be found in FreeSpace.cpp (search for
84  * XSTR_SIZE).
85  * 
86  * 84    5/08/98 7:52p Lawrance
87  * fix bug where wing slot icons were not getting loaded
88  * 
89  * 83    5/08/98 10:17a Lawrance
90  * don't play briefing slide-in animation if detail level is below high
91  * 
92  * 82    5/06/98 11:50p Lawrance
93  * Clean up help overlay code for loadout screens
94  * 
95  * 81    5/03/98 1:55a Lawrance
96  * Fix some sound problems with loadout screens
97  * 
98  * 80    4/30/98 6:03p Lawrance
99  * Make drag and drop work better.
100  * 
101  * 79    4/22/98 5:52p Dave
102  * Large reworking of endgame sequencing. Updated host options screen for
103  * new artwork. Put in checks to end game if host leaves or if team
104  * captains leave mid-game. 
105  * 
106  * 78    4/07/98 7:51p Hoffoss
107  * Implemented changed to options screen due to artwork changes.
108  * 
109  * 77    4/07/98 5:42p Dave
110  * Put in support for ui display of voice system status (recording,
111  * playing back, etc). Make sure main hall music is stopped before
112  * entering a multiplayer game via ingame join.
113  * 
114  * 76    4/02/98 11:40a Lawrance
115  * check for #ifdef DEMO instead of #ifdef DEMO_RELEASE
116  * 
117  * 75    4/01/98 11:19p Dave
118  * Put in auto-loading of xferred pilot pic files. Grey out background
119  * behind pinfo popup. Put a chatbox message in when players are kicked.
120  * Moved mission title down in briefing. Other ui fixes.
121  * 
122  * 74    4/01/98 9:21p John
123  * Made NDEBUG, optimized build with no warnings or errors.
124  * 
125  * 73    3/31/98 11:47p Lawrance
126  * Fix some bugs related to wingmen selection when doing a quick mission
127  * restart.
128  * 
129  * 72    3/31/98 5:31p Lawrance
130  * Fix sound bug that happenned when entering briefing
131  * 
132  * 71    3/30/98 5:16p Lawrance
133  * centralize a check for disabled loadout screens
134  * 
135  * 70    3/30/98 12:18a Lawrance
136  * change some DEMO_RELEASE code to not compile code rather than return
137  * early
138  * 
139  * 69    3/29/98 10:16p Allender
140  * scramble missions need to have ship/weapon selection disabled (this
141  * code was somehow lost)
142  * 
143  * 68    3/29/98 1:24p Dave
144  * Make chatbox not clear between multiplayer screens. Select player ship
145  * as default in mp team select and weapons select screens. Made create
146  * game mission list use 2 fixed size columns.
147  * 
148  * 67    3/29/98 12:55a Lawrance
149  * Get demo build working with limited set of data.
150  * 
151  * 66    3/25/98 8:43p Hoffoss
152  * Changed anim_play() to not be so damn complex when you try and call it.
153  * 
154  * 65    3/24/98 4:59p Dave
155  * Fixed several ui bugs. Put in pre and post voice stream playback sound
156  * fx. Put in error specific popups for clients getting dropped from games
157  * through actions other than their own.
158  * 
159  * 64    3/19/98 5:32p Lawrance
160  * Added music to the background of command brief screen.
161  * 
162  * 63    3/05/98 5:02p Dave
163  * More work on team vs. team support for multiplayer. Need to fix bugs in
164  * weapon select.
165  * 
166  * 62    3/03/98 8:55p Dave
167  * Finished pre-briefing team vs. team support.
168  * 
169  * 61    3/03/98 8:12p Lawrance
170  * Double timeout before flashing buttons
171  * 
172  * 60    3/02/98 3:27p Lawrance
173  * Don't call muti_ts_init() in single player
174  * 
175  * 59    3/01/98 3:26p Dave
176  * Fixed a few team select bugs. Put in multiplayer intertface sounds.
177  * Corrected how ships are disabled/enabled in team select/weapon select
178  * screens.
179  * 
180  * 58    2/27/98 4:55p Sandeep
181  * Fixed a signed/unsigned bug in the wss packet type
182  * 
183  * 57    2/26/98 4:59p Allender
184  * groundwork for team vs team briefings.  Moved weaponry pool into the
185  * Team_data structure.  Added team field into the p_info structure.
186  * Allow for mutliple structures in the briefing code.
187  * 
188  * 56    2/25/98 10:24a Lawrance
189  * Don't ask for confirmation when ESC is pressed.
190  * 
191  * 55    2/24/98 12:22a Lawrance
192  * New coords for revamped briefing graphics
193  * 
194  * 54    2/22/98 4:17p John
195  * More string externalization classification... 190 left to go!
196  * 
197  * 53    2/22/98 12:19p John
198  * Externalized some strings
199  * 
200  * 52    2/21/98 2:50p Lawrance
201  * Tell players that their campaign position will get saved if they return
202  * to main hall from loadout screens.
203  * 
204  * 51    2/19/98 6:26p Dave
205  * Fixed a few file xfer bugs. Tweaked mp team select screen. Put in
206  * initial support for player data uploading.
207  * 
208  * 50    2/18/98 3:56p Dave
209  * Several bugs fixed for mp team select screen. Put in standalone packet
210  * routing for team select.
211  * 
212  * 49    2/17/98 6:07p Dave
213  * Tore out old multiplayer team select screen, installed new one.
214  * 
215  * 48    2/13/98 3:46p Dave
216  * Put in dynamic chatbox sizing. Made multiplayer file lookups use cfile
217  * functions.
218  * 
219  * 47    2/10/98 8:40p Dave
220  * Fixed some debriefing bugs.
221  * 
222  * 46    2/04/98 11:06p Lawrance
223  * Fix a couple of bugs with save/restore of player weapon loadout.
224  * 
225  * 45    2/04/98 4:32p Allender
226  * support for multiple briefings and debriefings.  Changes to mission
227  * type (now a bitfield).  Bitfield defs for multiplayer modes
228  * 
229  * 44    1/30/98 10:40a Lawrance
230  * remove any binding references to hotkey screen
231  * 
232  * 43    1/20/98 5:52p Lawrance
233  * prompt user before returning to main hall (in single player)
234  * 
235  * 42    1/17/98 5:51p Dave
236  * Bug fixes for bugs generated by multiplayer testing.
237  * 
238  * 41    1/14/98 11:39a Dave
239  * Polished up a bunch of popup support items.
240  * 
241  * 40    1/13/98 5:35p Lawrance
242  * Show popup when trying to go to weapons loadout without any ships
243  * selected.
244  * 
245  * 39    1/10/98 5:48p Lawrance
246  * Don't allow Tab to go to ship/weapon loadout screen in training, play
247  * negative feedback sounds if user tries to.
248  * 
249  * 38    1/10/98 12:45a Lawrance
250  * Don't restore loadout if mission was modified.
251  * 
252  * 37    1/09/98 6:06p Dave
253  * Put in network sound support for multiplayer ship/weapon select
254  * screens. Made clients exit game correctly through warp effect. Fixed
255  * main hall menu help overlay bug.
256  * 
257  * 36    1/09/98 11:04a Lawrance
258  * Fix bug that prevented buttons from flashing in the loadout screens.
259  * 
260  * 35    1/07/98 6:45p Lawrance
261  * Play first briefing music if none specified.
262  * 
263  * 34    1/05/98 4:57p Lawrance
264  * reset flash timers when a button is pressed or a key is pressed
265  * 
266  * 33    12/30/97 5:46p Lawrance
267  * Rename rnd() to rand_alt().
268  * 
269  * 32    12/30/97 4:27p Lawrance
270  * Add new rnd() function that doesn't affect rand() sequence.
271  * 
272  * 31    12/29/97 4:21p Lawrance
273  * Flash buttons on briefing/ship select/weapons loadout when enough time
274  * has elapsed without activity.
275  * 
276  * 30    12/28/97 5:52p Lawrance
277  * Add support for debriefing success/fail music.
278  * 
279  * 29    12/24/97 8:54p Lawrance
280  * Integrating new popup code
281  * 
282  * 28    12/24/97 1:19p Lawrance
283  * fix some bugs with the multiplayer ship/weapons loadout
284  * 
285  * 27    12/23/97 11:58a Allender
286  * changes to ship/wespon selection for multplayer.  added sounds to some
287  * interface screens.  Update and modiied end-of-briefing packets -- yet
288  * to be tested.
289  *
290  * $NoKeywords: $
291  *
292  */
293
294 #include <limits.h>
295 #include "freespace.h"
296 #include "eventmusic.h"
297 #include "key.h"
298 #include "missionscreencommon.h"
299 #include "missionshipchoice.h"
300 #include "missionweaponchoice.h"
301 #include "missionbrief.h"
302 #include "multi.h"
303 #include "multimsgs.h"
304 #include "timer.h"
305 #include "sound.h"
306 #include "gamesequence.h"
307 #include "bmpman.h"
308 // #include "movie.h"
309 #include "gamesnd.h"
310 #include "palman.h"
311 #include "mouse.h"
312 #include "contexthelp.h"
313 #include "chatbox.h"
314 #include "time.h"
315 #include "joy.h"
316 #include "cmdline.h"
317 #include "linklist.h"
318 #include "staticrand.h" // for rand_alt()
319 #include "popup.h"
320 #include "multiutil.h"
321 #include "multiteamselect.h"
322 #include "hudwingmanstatus.h"
323 #include "multi_endgame.h"
324 #include "uidefs.h"
325 #include "animplay.h"
326
327 //////////////////////////////////////////////////////////////////
328 // Game Globals
329 //////////////////////////////////////////////////////////////////
330
331 int Common_select_inited = 0;
332
333 // Dependent on when mouse button goes up
334 int Drop_icon_mflag, Drop_on_wing_mflag, Brief_mouse_up_flag;
335
336 int Mouse_down_last_frame = 0;
337
338 // Timers used to flash buttons after timeouts
339 #define MSC_FLASH_AFTER_TIME    60000           //      time before flashing a button
340 #define MSC_FLASH_INTERVAL              200             // time between flashes
341 int Flash_timer;                                                                //      timestamp used to start flashing
342 int Flash_toggle;                                                               // timestamp used to toggle flashing
343 int Flash_bright;                                                               // state of button to flash
344
345 //////////////////////////////////////////////////////////////////
346 // Global to modulde
347 //////////////////////////////////////////////////////////////////
348 int Current_screen;
349 int Next_screen;
350 static int InterfacePaletteBitmap = -1; // PCX file that holds the interface palette
351
352 //////////////////////////////////////////////////////////////////
353 // UI 
354 //////////////////////////////////////////////////////////////////
355 UI_WINDOW       *Active_ui_window;
356
357 brief_common_buttons Common_buttons[3][GR_NUM_RESOLUTIONS][NUM_COMMON_BUTTONS] = {      
358 // icons for briefing, ship selection, weapon selection screens 
359         {       // UGH
360                 { // GR_640
361 #ifdef MAKE_FS1
362                         brief_common_buttons("CB_00",   0,              0,              -1,     -1,     0),     // briefing
363                         brief_common_buttons("CB_01",   0,              19,             -1,     -1,     1),     // ship selection
364                         brief_common_buttons("CB_02",   0,              33,             -1,     -1,     2),     // weapons loadout
365                         brief_common_buttons("CB_05",   562,    411,    -1,     -1,     5),     // commit
366                         brief_common_buttons("CB_06",   469,    424,    -1,     -1,     6),     // help
367                         brief_common_buttons("CB_07",   447,    452,    -1,     -1,     7),     // options
368 #else
369                         brief_common_buttons("CB_00",                   7,              3,              37,     7,              0),
370                         brief_common_buttons("CB_01",                   7,              19,     37,     23,     1),
371                         brief_common_buttons("CB_02",                   7,              35,     37,     39,     2),
372                         brief_common_buttons("CB_05",                   571,    425,    572,    413,    5),
373                         brief_common_buttons("CB_06",                   533,    425,    500,    440,    6),
374                         brief_common_buttons("CB_07",                   533,    455,    479,    464,    7),                     
375 #endif
376                 }, 
377                 { // GR_1024                    
378                         brief_common_buttons("2_CB_00",         12,     5,              59,     12,     0),
379                         brief_common_buttons("2_CB_01",         12,     31,     59,     37,     1),
380                         brief_common_buttons("2_CB_02",         12,     56,     59,     62,     2),
381                         brief_common_buttons("2_CB_05",         914,    681,    937,    671,    5),
382                         brief_common_buttons("2_CB_06",         854,    681,    822,    704,    6),
383                         brief_common_buttons("2_CB_07",         854,    724,    800,    743,    7),                     
384                 }
385         },      
386         {       // UGH
387                 { // GR_640
388 #ifdef MAKE_FS1
389                         brief_common_buttons("CB_00",   0,              0,              -1,     -1,     0),     // briefing
390                         brief_common_buttons("CB_01",   0,              19,             -1,     -1,     1),     // ship selection
391                         brief_common_buttons("CB_02",   0,              33,             -1,     -1,     2),     // weapons loadout
392                         brief_common_buttons("CB_05",   562,    411,    -1,     -1,     5),     // commit
393                         brief_common_buttons("CB_06",   469,    424,    -1,     -1,     6),     // help
394                         brief_common_buttons("CB_07",   447,    452,    -1,     -1,     7),     // options
395 #else
396                         brief_common_buttons("CB_00",                   7,              3,              37,     7,              0),
397                         brief_common_buttons("CB_01",                   7,              19,     37,     23,     1),
398                         brief_common_buttons("CB_02",                   7,              35,     37,     39,     2),
399                         brief_common_buttons("CB_05",                   571,    425,    572,    413,    5),
400                         brief_common_buttons("CB_06",                   533,    425,    500,    440,    6),
401                         brief_common_buttons("CB_07",                   533,    455,    479,    464,    7),                     
402 #endif
403                 }, 
404                 { // GR_1024                    
405                         brief_common_buttons("2_CB_00",         12,     5,              59,     12,     0),
406                         brief_common_buttons("2_CB_01",         12,     31,     59,     37,     1),
407                         brief_common_buttons("2_CB_02",         12,     56,     59,     62,     2),
408                         brief_common_buttons("2_CB_05",         914,    681,    937,    671,    5),
409                         brief_common_buttons("2_CB_06",         854,    681,    822,    704,    6),
410                         brief_common_buttons("2_CB_07",         854,    724,    800,    743,    7),                     
411                 }
412         },      
413         {       // UGH
414                 { // GR_640
415 #ifdef MAKE_FS1
416                         brief_common_buttons("CB_00",   0,              0,              -1,     -1,     0),     // briefing
417                         brief_common_buttons("CB_01",   0,              19,             -1,     -1,     1),     // ship selection
418                         brief_common_buttons("CB_02",   0,              33,             -1,     -1,     2),     // weapons loadout
419                         brief_common_buttons("CB_05",   562,    411,    -1,     -1,     5),     // commit
420                         brief_common_buttons("CB_06",   469,    424,    -1,     -1,     6),     // help
421                         brief_common_buttons("CB_07",   447,    452,    -1,     -1,     7),     // options
422 #else
423                         brief_common_buttons("CB_00",                   7,              3,              37,     7,              0),
424                         brief_common_buttons("CB_01",                   7,              19,     37,     23,     1),
425                         brief_common_buttons("CB_02",                   7,              35,     37,     39,     2),
426                         brief_common_buttons("CB_05",                   571,    425,    572,    413,    5),
427                         brief_common_buttons("CB_06",                   533,    425,    500,    440,    6),
428                         brief_common_buttons("CB_07",                   533,    455,    479,    464,    7),                     
429 #endif
430                 }, 
431                 { // GR_1024                    
432                         brief_common_buttons("2_CB_00",         12,     5,              59,     12,     0),
433                         brief_common_buttons("2_CB_01",         12,     31,     59,     37,     1),
434                         brief_common_buttons("2_CB_02",         12,     56,     59,     62,     2),
435                         brief_common_buttons("2_CB_05",         914,    681,    937,    671,    5),
436                         brief_common_buttons("2_CB_06",         854,    681,    822,    704,    6),
437                         brief_common_buttons("2_CB_07",         854,    724,    800,    743,    7),                     
438                 }
439         } 
440 };
441
442 #define COMMON_BRIEFING_BUTTON                                  0
443 #define COMMON_SS_BUTTON                                                        1
444 #define COMMON_WEAPON_BUTTON                                            2
445 #define COMMON_COMMIT_BUTTON                                            3
446 #define COMMON_HELP_BUTTON                                                      4
447 #define COMMON_OPTIONS_BUTTON                                           5
448
449 int Background_playing;                 // Flag to indicate background animation is playing
450 static anim *Background_anim;   // Ids for the anim data that is loaded
451
452 // value for which Team_data entry to use
453 int     Common_team;
454
455 // Ids for the instance of the anim that is playing
456 #ifdef MAKE_FS1
457 static anim_instance *Background_anim_instance;
458 #endif
459
460 int Wing_slot_empty_bitmap;
461 int Wing_slot_disabled_bitmap;
462
463 // prototypes
464 int wss_slots_all_empty();
465
466 // Display the no ships selected error
467 void common_show_no_ship_error()
468 {
469         popup(PF_USE_AFFIRMATIVE_ICON, 1, POPUP_OK, XSTR( "At least one ship must be selected before proceeding to weapons loadout", 460));
470 }
471
472 // Check the status of the buttons common to the loadout screens
473 void common_check_buttons()
474 {
475         int                     i;
476         UI_BUTTON       *b;
477
478         for ( i = 0; i < NUM_COMMON_BUTTONS; i++ ) {
479                 b = &Common_buttons[Current_screen-1][gr_screen.res][i].button;
480                 if ( b->pressed() ) {
481                         
482                         common_button_do(i);
483                 }
484         }
485
486 /*
487         // AL 11-23-97: let a joystick button press commit
488         if ( joy_down_count(0) || joy_down_count(1) ) {
489                 Commit_pressed = 1;
490         }
491 */
492
493 }
494
495 // -------------------------------------------------------------------
496 // common_redraw_pressed_buttons()
497 //
498 // Redraw any common buttons that are pressed down.  This function is needed
499 // since we sometimes need to draw pressed buttons last to ensure the entire
500 // button gets drawn (and not overlapped by other buttons)
501 //
502 void common_redraw_pressed_buttons()
503 {
504         int                     i;
505         UI_BUTTON       *b;
506
507         for ( i = 0; i < NUM_COMMON_BUTTONS; i++ ) {
508                 b = &Common_buttons[Current_screen-1][gr_screen.res][i].button;
509                 if ( b->button_down() ) {
510                         b->draw_forced(2);
511                 }
512         }
513 }
514
515 void common_buttons_maybe_reload(UI_WINDOW *ui_window)
516 {
517         UI_BUTTON       *b;
518         int                     i;
519
520         for ( i = 0; i < NUM_COMMON_BUTTONS; i++ ) {
521                 b = &Common_buttons[Current_screen-1][gr_screen.res][i].button;
522                 b->set_bmaps(Common_buttons[Current_screen-1][gr_screen.res][i].filename);
523         }
524 }
525
526 void common_buttons_init(UI_WINDOW *ui_window)
527 {
528         UI_BUTTON       *b;
529         int                     i;
530
531         for ( i = 0; i < NUM_COMMON_BUTTONS; i++ ) {
532                 b = &Common_buttons[Current_screen-1][gr_screen.res][i].button;
533                 b->create( ui_window, "", Common_buttons[Current_screen-1][gr_screen.res][i].x, Common_buttons[Current_screen-1][gr_screen.res][i].y,  60, 30, 0, 1);
534                 // set up callback for when a mouse first goes over a button
535                 b->set_highlight_action( common_play_highlight_sound );
536                 b->set_bmaps(Common_buttons[Current_screen-1][gr_screen.res][i].filename);
537                 b->link_hotspot(Common_buttons[Current_screen-1][gr_screen.res][i].hotspot);
538         }       
539
540 #ifndef MAKE_FS1
541         // add some text        
542         ui_window->add_XSTR("Briefing", 1504, Common_buttons[Current_screen-1][gr_screen.res][COMMON_BRIEFING_BUTTON].xt, Common_buttons[Current_screen-1][gr_screen.res][COMMON_BRIEFING_BUTTON].yt, &Common_buttons[Current_screen-1][gr_screen.res][COMMON_BRIEFING_BUTTON].button, UI_XSTR_COLOR_GREEN);
543         ui_window->add_XSTR("Ship Selection", 1067, Common_buttons[Current_screen-1][gr_screen.res][COMMON_SS_BUTTON].xt, Common_buttons[Current_screen-1][gr_screen.res][COMMON_SS_BUTTON].yt, &Common_buttons[Current_screen-1][gr_screen.res][COMMON_SS_BUTTON].button, UI_XSTR_COLOR_GREEN);
544         ui_window->add_XSTR("Weapon Loadout", 1068, Common_buttons[Current_screen-1][gr_screen.res][COMMON_WEAPON_BUTTON].xt, Common_buttons[Current_screen-1][gr_screen.res][COMMON_WEAPON_BUTTON].yt, &Common_buttons[Current_screen-1][gr_screen.res][COMMON_WEAPON_BUTTON].button, UI_XSTR_COLOR_GREEN);
545         ui_window->add_XSTR("Commit", 1062, Common_buttons[Current_screen-1][gr_screen.res][COMMON_COMMIT_BUTTON].xt, Common_buttons[Current_screen-1][gr_screen.res][COMMON_COMMIT_BUTTON].yt, &Common_buttons[Current_screen-1][gr_screen.res][COMMON_COMMIT_BUTTON].button, UI_XSTR_COLOR_PINK);
546         ui_window->add_XSTR("Help", 928, Common_buttons[Current_screen-1][gr_screen.res][COMMON_HELP_BUTTON].xt, Common_buttons[Current_screen-1][gr_screen.res][COMMON_HELP_BUTTON].yt, &Common_buttons[Current_screen-1][gr_screen.res][COMMON_HELP_BUTTON].button, UI_XSTR_COLOR_GREEN);
547         ui_window->add_XSTR("Options", 1036, Common_buttons[Current_screen-1][gr_screen.res][COMMON_OPTIONS_BUTTON].xt, Common_buttons[Current_screen-1][gr_screen.res][COMMON_OPTIONS_BUTTON].yt, &Common_buttons[Current_screen-1][gr_screen.res][COMMON_OPTIONS_BUTTON].button, UI_XSTR_COLOR_GREEN);
548 #endif
549
550         common_reset_buttons();
551
552         Common_buttons[Current_screen-1][gr_screen.res][COMMON_COMMIT_BUTTON].button.set_hotkey(KEY_CTRLED+KEY_ENTER);
553         Common_buttons[Current_screen-1][gr_screen.res][COMMON_HELP_BUTTON].button.set_hotkey(KEY_F1);
554         Common_buttons[Current_screen-1][gr_screen.res][COMMON_OPTIONS_BUTTON].button.set_hotkey(KEY_F2);
555
556         // for scramble or training missions, disable the ship/weapon selection regions
557         if ( brief_only_allow_briefing() ) {
558                 Common_buttons[Current_screen-1][gr_screen.res][COMMON_SS_REGION].button.disable();
559                 Common_buttons[Current_screen-1][gr_screen.res][COMMON_WEAPON_REGION].button.disable();
560         }
561
562         #ifdef DEMO // allow for FS2_DEMO
563                 Common_buttons[Current_screen-1][gr_screen.res][COMMON_SS_REGION].button.disable();
564                 Common_buttons[Current_screen-1][gr_screen.res][COMMON_WEAPON_REGION].button.disable();
565         #endif
566 }
567
568 void set_active_ui(UI_WINDOW *ui_window)
569 {
570         Active_ui_window = ui_window;
571 }
572
573 void common_music_init(int score_index)
574 {
575         if ( Cmdline_freespace_no_music ) {
576                 return;
577         }
578
579         if ( score_index >= NUM_SCORES ) {
580                 Int3();
581                 return;
582         }
583
584         if ( Mission_music[score_index] < 0 ) {
585                 if ( Num_music_files > 0 ) {
586                         Mission_music[score_index] = 0;
587                         nprintf(("Sound","No briefing music is selected, so play first briefing track: %s\n",Spooled_music[Mission_music[score_index]].name));
588                 } else {
589                         return;
590                 }
591         }
592
593         briefing_load_music( Spooled_music[Mission_music[score_index]].filename );
594         // Use this id to trigger the start of music playing on the briefing screen
595         Briefing_music_begin_timestamp = timestamp(BRIEFING_MUSIC_DELAY);
596 }
597
598 void common_music_do()
599 {
600         if ( Cmdline_freespace_no_music ) {
601                 return;
602         }
603
604         // Use this id to trigger the start of music playing on the briefing screen
605         if ( timestamp_elapsed( Briefing_music_begin_timestamp) ) {
606                 Briefing_music_begin_timestamp = 0;
607                 briefing_start_music();
608         }
609 }
610
611 void common_music_close()
612 {
613         if ( Cmdline_freespace_no_music ) {
614                 return;
615         }
616
617         if ( Num_music_files <= 0 )
618                 return;
619
620         briefing_stop_music();
621 }
622
623 // function that sets the current palette to the interface palette.  This function
624 // needs to be followed by common_free_interface_palette() to restore the game palette.
625 void common_set_interface_palette(char *filename)
626 {
627         static char buf[MAX_FILENAME_LEN + 1] = {0};
628
629         if (!filename)
630                 filename = NOX("palette01");
631
632         Assert(strlen(filename) <= MAX_FILENAME_LEN);
633         if ( (InterfacePaletteBitmap != -1) && !stricmp(filename, buf) )
634                 return;  // already set to this palette
635
636         strcpy(buf, filename);
637
638         // unload the interface bitmap from memory
639         if (InterfacePaletteBitmap != -1) {
640                 bm_unload(InterfacePaletteBitmap);
641                 InterfacePaletteBitmap = -1;
642         }
643
644         // ugh - we don't need this anymore
645 #ifdef MAKE_FS1
646         InterfacePaletteBitmap = bm_load(filename);
647         if (InterfacePaletteBitmap < 0) {
648                 Error(LOCATION, "Could not load in \"%s\"!", filename);
649         }
650 #endif
651
652 #ifndef HARDWARE_ONLY
653         palette_use_bm_palette(InterfacePaletteBitmap);
654 #endif
655 }
656
657 // release the interface palette .pcx file, and restore the game palette
658 void common_free_interface_palette()
659 {
660         // unload the interface bitmap from memory
661         if (InterfacePaletteBitmap != -1) {
662                 bm_unload(InterfacePaletteBitmap);
663                 InterfacePaletteBitmap = -1;
664         }
665
666         // restore the normal game palette
667         palette_restore_palette();
668 }
669
670 // Init timers used for flashing buttons
671 void common_flash_button_init()
672 {
673         Flash_timer = timestamp(MSC_FLASH_AFTER_TIME);
674         Flash_toggle = 1;
675         Flash_bright = 0;
676 }
677
678 // determine if we should draw a button as bright
679 int common_flash_bright()
680 {
681         if ( timestamp_elapsed(Flash_timer) ) {
682                 if ( timestamp_elapsed(Flash_toggle) ) {
683                         Flash_toggle = timestamp(MSC_FLASH_INTERVAL);
684                         Flash_bright ^= 1;
685                 }
686         }
687
688         return Flash_bright;
689 }
690
691 // common_select_init() will load in animations and bitmaps that are common to the 
692 // briefing/ship select/weapon select screens.  The global Common_select_inited is set
693 // after this function is called once, and is only cleared when common_select_close()
694 // is called.  This prevents multiple loadings of animations/bitmaps.
695 //
696 // This function also sets the palette based on the file palette01.pcx
697 void common_select_init()
698 {
699         if ( Common_select_inited ) {
700                 nprintf(("Alan","common_select_init() returning without doing anything\n"));
701                 return;
702         }
703
704         nprintf(("Alan","entering common_select_init()\n"));
705
706         // No anims are playing
707         Background_playing = 0;
708         Background_anim = NULL;
709
710         #ifndef DEMO // not for FS2_DEMO
711
712 #ifdef MAKE_FS1
713         if ( current_detail_level() >= (NUM_DEFAULT_DETAIL_LEVELS-2) ) {
714
715                 anim_play_struct aps;
716
717                 // Load in the background transition anim
718                 if ( Game_mode & GM_MULTIPLAYER )
719                         Background_anim = anim_load("BriefTransMulti", 1);      // 1 as last parm means file is mem-mapped
720                 else  {
721                         Background_anim = anim_load("BriefTrans", 1);   // 1 as last parm means file is mem-mapped
722                 }
723
724                 Assert( Background_anim != NULL );
725                 anim_play_init(&aps, Background_anim, 0, 0);
726                 aps.framerate_independent = 1;
727                 aps.skip_frames = 0;
728                 Background_anim_instance = anim_play(&aps);
729                 Background_playing = 1;         // start playing the Background anim
730         }
731 #endif
732
733         Current_screen = Next_screen = ON_BRIEFING_SELECT;
734
735         // load in the icons for the wing slots
736         load_wing_icons(NOX("iconwing01"));
737
738
739         #endif
740
741         Current_screen = Next_screen = ON_BRIEFING_SELECT;
742         
743         Commit_pressed = 0;
744
745         Common_select_inited = 1;
746
747         // this handles the case where the player played a multiplayer game but now is in single player (in one instance
748         // of Freespace)
749         if(!(Game_mode & GM_MULTIPLAYER)){
750                 chatbox_close();
751         }
752
753         // get the value of the team
754         Common_team = 0;                                                        // assume the first team -- we'll change this value if we need to
755         if ( (Game_mode & GM_MULTIPLAYER) && IS_MISSION_MULTI_TEAMS )
756                 Common_team = Net_player->p_info.team;
757
758         ship_select_common_init();      
759         weapon_select_common_init();
760         common_flash_button_init();
761
762         if ( Game_mode & GM_MULTIPLAYER ) {
763                 multi_ts_common_init();
764         }
765
766         // restore loadout from Player_loadout if this is the same mission as the one previously played
767         if ( !(Game_mode & GM_MULTIPLAYER) ) {
768                 if ( !stricmp(Player_loadout.filename, Game_current_mission_filename) ) {
769                         wss_restore_loadout();
770                         ss_synch_interface();
771                         wl_synch_interface();
772                 }
773         }
774         
775         Drop_icon_mflag = 0;
776         Drop_on_wing_mflag = 0;
777 }
778
779 void common_reset_buttons()
780 {
781         int                     i;
782         UI_BUTTON       *b;
783
784         for ( i = 0; i < NUM_COMMON_BUTTONS; i++ ) {
785                 b = &Common_buttons[Current_screen-1][gr_screen.res][i].button;
786                 b->reset_status();
787         }
788
789         switch(Current_screen) {
790         case ON_BRIEFING_SELECT:
791                 Common_buttons[Current_screen-1][gr_screen.res][COMMON_BRIEFING_REGION].button.skip_first_highlight_callback();
792                 break;
793         case ON_SHIP_SELECT:
794                 Common_buttons[Current_screen-1][gr_screen.res][COMMON_SS_REGION].button.skip_first_highlight_callback();
795                 break;
796         case ON_WEAPON_SELECT:
797                 Common_buttons[Current_screen-1][gr_screen.res][COMMON_WEAPON_REGION].button.skip_first_highlight_callback();
798                 break;
799         }
800 }
801
802 // common_select_do() is called once per loop in the interface screens and is used
803 // for drawing and changing the common animations and blitting common bitmaps.
804 int common_select_do(float frametime)
805 {
806         int     k, new_k;
807
808         // If the mouse went up, set flags.  We can't use mouse_up_count() more than once a frame,
809         // since the count gets zeroed after the call.
810         //
811         Drop_icon_mflag = 0;
812         Drop_on_wing_mflag = 0;
813         Brief_mouse_up_flag = 0;
814
815         if ( mouse_up_count(MOUSE_LEFT_BUTTON) ) {
816                 Drop_icon_mflag = 1;
817                 Drop_on_wing_mflag = 1;
818                 Brief_mouse_up_flag = 1;                
819         }
820
821         Mouse_down_last_frame = 0;
822         if ( mouse_down_count(MOUSE_LEFT_BUTTON) ) {
823                 Mouse_down_last_frame = 1;
824         }
825
826         if ( help_overlay_active(BR_OVERLAY) || help_overlay_active(SS_OVERLAY) || help_overlay_active(WL_OVERLAY) ) {
827                 Common_buttons[0][gr_screen.res][COMMON_HELP_BUTTON].button.reset_status();
828                 Common_buttons[1][gr_screen.res][COMMON_HELP_BUTTON].button.reset_status();
829                 Common_buttons[2][gr_screen.res][COMMON_HELP_BUTTON].button.reset_status();
830                 Active_ui_window->set_ignore_gadgets(1);
831         } else {
832                 Active_ui_window->set_ignore_gadgets(0);
833         }
834
835         k = chatbox_process();
836         if ( Game_mode & GM_NORMAL ) {
837                 new_k = Active_ui_window->process(k);
838         } else {
839                 new_k = Active_ui_window->process(k, 0);
840         }
841
842         if ( (k > 0) || (new_k > 0) || B1_JUST_RELEASED ) {
843                 if ( help_overlay_active(BR_OVERLAY) || help_overlay_active(SS_OVERLAY) || help_overlay_active(WL_OVERLAY) ) {
844                         help_overlay_set_state(BR_OVERLAY, 0);
845                         help_overlay_set_state(SS_OVERLAY, 0);
846                         help_overlay_set_state(WL_OVERLAY, 0);
847                         Active_ui_window->set_ignore_gadgets(0);
848                         k = 0;
849                         new_k = 0;
850                 }
851         }
852
853         // reset timers for flashing buttons if key pressed
854         if ( (k>0) || (new_k>0) ) {
855                 common_flash_button_init();
856         }
857
858         common_music_do();
859
860 #ifdef MAKE_FS1
861         if ( Background_playing ) {
862
863                 if ( Background_anim_instance->frame_num == BUTTON_SLIDE_IN_FRAME ) {
864                         gamesnd_play_iface(SND_BTN_SLIDE);
865                 }       
866         
867                 if ( Background_anim_instance->frame_num == Background_anim_instance->stop_at ) {
868                         // Free up the big honking background animation, since we won't be playing it again
869                         anim_release_render_instance(Background_anim_instance);
870                         anim_free(Background_anim);
871
872                         Background_playing = 0;         
873                         Current_screen = Next_screen = ON_BRIEFING_SELECT;
874                 }
875         }
876 #endif
877
878         if ( Current_screen != Next_screen ) {
879                 switch( Next_screen ) {
880                         case ON_BRIEFING_SELECT:
881                                 gameseq_post_event( GS_EVENT_START_BRIEFING );
882                                 break;
883
884                         case ON_SHIP_SELECT:
885                                 // go to the specialized multiplayer team/ship select screen
886                                 if(Game_mode & GM_MULTIPLAYER){
887                                         gameseq_post_event(GS_EVENT_TEAM_SELECT);
888                                 }
889                                 // go to the normal ship select screen
890                                 else {
891                                         gameseq_post_event(GS_EVENT_SHIP_SELECTION);
892                                 }
893                                 break;
894
895                         case ON_WEAPON_SELECT:
896                                 if ( !wss_slots_all_empty() ) {
897                                         gameseq_post_event(GS_EVENT_WEAPON_SELECTION);
898                                 } else {
899                                         common_show_no_ship_error();
900                                 }
901                                 break;
902                 } // end switch
903         }
904
905    return new_k;
906 }
907
908 // -------------------------------------------------------------------------------------
909 // common_render()
910 //
911 void common_render(float frametime)
912 {
913         if ( !Background_playing ) {
914                 gr_set_bitmap(Brief_background_bitmap);
915                 gr_bitmap(0, 0);
916         }
917
918         anim_render_all(0, frametime);
919         anim_render_all(ON_SHIP_SELECT, frametime);
920 }
921
922 // -------------------------------------------------------------------------------------
923 // common_render_selected_screen_button()
924 //
925 //      A very ugly piece of special purpose code.  This is used to draw the pressed button
926 // frame for whatever stage of the briefing/ship select/weapons loadout we are on. 
927 //
928 void common_render_selected_screen_button()
929 {
930         Common_buttons[Next_screen-1][gr_screen.res][Next_screen-1].button.draw_forced(2);
931 }
932
933 // -------------------------------------------------------------------------------------
934 // common_button_do() do the button action for the specified pressed button
935 //
936 void common_button_do(int i)
937 {
938         if ( i == COMMON_COMMIT_BUTTON ) {
939                 Commit_pressed = 1;
940                 return;
941         }
942
943         if ( Background_playing )
944                 return;
945
946         switch ( i ) {
947
948         case COMMON_BRIEFING_BUTTON:
949                 if ( Current_screen != ON_BRIEFING_SELECT ) {
950                         gamesnd_play_iface(SND_SCREEN_MODE_PRESSED);
951                         Next_screen = ON_BRIEFING_SELECT;
952                 }
953                 break;
954
955         case COMMON_WEAPON_BUTTON:
956                 if ( Current_screen != ON_WEAPON_SELECT ) {
957                         if ( !wss_slots_all_empty() ) {
958                                 gamesnd_play_iface(SND_SCREEN_MODE_PRESSED);
959                                 Next_screen = ON_WEAPON_SELECT;
960                         } else {
961                                 common_show_no_ship_error();
962                         }
963                 }
964                 break;
965
966         case COMMON_SS_BUTTON:
967                 if ( Current_screen != ON_SHIP_SELECT ) {
968                         gamesnd_play_iface(SND_SCREEN_MODE_PRESSED);
969                         Next_screen = ON_SHIP_SELECT;
970                 }
971                 break;
972
973         case COMMON_OPTIONS_BUTTON:
974                 gamesnd_play_iface(SND_SWITCH_SCREENS);
975                 gameseq_post_event( GS_EVENT_OPTIONS_MENU );
976                 break;
977
978         case COMMON_HELP_BUTTON:
979                 gamesnd_play_iface(SND_HELP_PRESSED);
980                 launch_context_help();
981                 break;
982
983         } // end switch
984 }
985
986 // common_check_keys() will check for keypresses common to all the interface screens.
987 void common_check_keys(int k)
988 {
989         switch (k) {
990
991                 case KEY_ESC: {
992
993                         if ( Current_screen == ON_BRIEFING_SELECT ) {
994                                 if ( brief_get_closeup_icon() != 0 ) {
995                                         brief_turn_off_closeup_icon();
996                                         break;
997                                 }
998                         }
999
1000                         // prompt the host of a multiplayer game
1001                         if(Game_mode & GM_MULTIPLAYER){
1002                                 multi_quit_game(PROMPT_ALL);
1003                         }
1004                         // go through the single player quit process
1005                         else {
1006                                 // return to the main menu
1007 /*
1008                                 int return_to_menu, pf_flags;
1009                                 pf_flags = PF_USE_AFFIRMATIVE_ICON|PF_USE_NEGATIVE_ICON;
1010                                 return_to_menu = popup(pf_flags, 2, POPUP_NO, POPUP_YES, XSTR( "Do you want to return to the Main Hall?\n(Your campaign position will be saved)", -1));
1011                                 if ( return_to_menu == 1 ) {
1012                                         gameseq_post_event(GS_EVENT_MAIN_MENU);
1013                                 }
1014 */
1015                                 gameseq_post_event(GS_EVENT_MAIN_MENU);
1016                         }                       
1017                         break;
1018                 }
1019
1020                 case KEY_CTRLED + KEY_ENTER:
1021                         Commit_pressed = 1;
1022                         break;
1023
1024                 case KEY_B:
1025                         if ( Current_screen != ON_BRIEFING_SELECT && !Background_playing ) {
1026                                 Next_screen = ON_BRIEFING_SELECT;
1027                         }
1028                         break;
1029
1030                 case KEY_W:
1031                         if ( brief_only_allow_briefing() ) {
1032                                 gamesnd_play_iface(SND_GENERAL_FAIL);
1033                                 break;
1034                         }
1035
1036                         #ifndef DEMO // not for FS2_DEMO
1037                                 if ( Current_screen != ON_WEAPON_SELECT && !Background_playing ) {
1038                                         if ( !wss_slots_all_empty() ) {
1039                                                 Next_screen = ON_WEAPON_SELECT;
1040                                         } else {
1041                                                 common_show_no_ship_error();
1042                                         }
1043                                 }
1044                         #else
1045                                 gamesnd_play_iface(SND_GENERAL_FAIL);
1046                         #endif
1047
1048                         break;
1049
1050                 case KEY_S:
1051
1052                         if ( brief_only_allow_briefing() ) {
1053                                 gamesnd_play_iface(SND_GENERAL_FAIL);
1054                                 break;
1055                         }
1056
1057                         #ifndef DEMO // not for FS2_DEMO
1058                                 if ( Current_screen != ON_SHIP_SELECT && !Background_playing ) {
1059                                         Next_screen = ON_SHIP_SELECT;
1060                                 }
1061                         #else
1062                                 gamesnd_play_iface(SND_GENERAL_FAIL);
1063                         #endif
1064
1065                         break;
1066
1067                 case KEY_SHIFTED+KEY_TAB:
1068
1069                         if ( brief_only_allow_briefing() ) {
1070                                 gamesnd_play_iface(SND_GENERAL_FAIL);
1071                                 break;
1072                         }
1073
1074                         #ifndef DEMO // not for FS2_DEMO
1075                                 if ( !Background_playing ) {
1076                                         switch ( Current_screen ) {
1077                                                 case ON_BRIEFING_SELECT:
1078                                                         if ( !wss_slots_all_empty() ) {
1079                                                                 Next_screen = ON_WEAPON_SELECT;
1080                                                         } else {
1081                                                                 common_show_no_ship_error();
1082                                                         }
1083                                                         break;
1084
1085                                                 case ON_SHIP_SELECT:
1086                                                         Next_screen = ON_BRIEFING_SELECT;
1087                                                         break;
1088
1089                                                 case ON_WEAPON_SELECT:
1090                                                         Next_screen = ON_SHIP_SELECT;
1091                                                         break;
1092                                                 default:
1093                                                         Int3();
1094                                                         break;
1095                                         }       // end switch
1096                                 }
1097                         #else
1098                                 gamesnd_play_iface(SND_GENERAL_FAIL);
1099                         #endif
1100
1101                         break;
1102
1103                 case KEY_TAB:
1104
1105                         if ( brief_only_allow_briefing() ) {
1106                                 gamesnd_play_iface(SND_GENERAL_FAIL);
1107                                 break;
1108                         }
1109
1110                         #ifndef DEMO // not for FS2_DEMO
1111                                 if ( !Background_playing ) {
1112                                         switch ( Current_screen ) {
1113                                                 case ON_BRIEFING_SELECT:
1114                                                         Next_screen = ON_SHIP_SELECT;
1115                                                         break;
1116
1117                                                 case ON_SHIP_SELECT:
1118                                                         if ( !wss_slots_all_empty() ) {
1119                                                                 Next_screen = ON_WEAPON_SELECT;
1120                                                         } else {
1121                                                                 common_show_no_ship_error();
1122                                                         }
1123                                                         break;
1124
1125                                                 case ON_WEAPON_SELECT:
1126                                                         Next_screen = ON_BRIEFING_SELECT;
1127                                                         break;
1128                                                 default:
1129                                                         Int3();
1130                                                         break;
1131                                         }       // end switch
1132                                 }
1133                         #else
1134                                 gamesnd_play_iface(SND_GENERAL_FAIL);
1135                         #endif
1136
1137                         break;
1138
1139                 case KEY_P:
1140                         if ( Anim_paused )
1141                                 Anim_paused = 0;
1142                         else
1143                                 Anim_paused = 1;
1144                         break;
1145         } // end switch
1146 }
1147
1148 // common_select_close() will release the memory for animations and bitmaps that
1149 // were loaded in common_select_init().  This function will abort if the Common_select_inited
1150 // flag is not set.  The last thing common_select_close() does in clear the Common_select_inited
1151 // flag.  
1152 //
1153 // weapon_select_close() and ship_select_close() are both called, since common_select_close()
1154 // is the function that is called the interface screens are finally exited.
1155 void common_select_close()
1156 {
1157         if ( !Common_select_inited ) {
1158                 nprintf(("Alan","common_select_close() returning without doing anything\n"));
1159                 return;
1160         }
1161
1162         nprintf(("Alan","entering common_select_close()\n"));
1163         
1164         // catch open anims that weapon_select_init_team() opened when not in weapon_select
1165         weapon_select_close_team();
1166
1167         weapon_select_close();
1168         if(Game_mode & GM_MULTIPLAYER){
1169                 multi_ts_close();
1170         } 
1171         ship_select_close();    
1172         brief_close();  
1173
1174         common_free_interface_palette();
1175
1176         // release the bitmpas that were previously extracted from anim files
1177         unload_wing_icons();
1178
1179         // Release any instances that may still exist
1180         anim_release_all_instances();
1181
1182         // free the anim's that were loaded into memory
1183 #ifdef MAKE_FS1
1184         if ( Background_anim ) {
1185                 anim_free(Background_anim);
1186                 Background_anim = NULL;
1187         }
1188 #endif
1189
1190         common_music_close();
1191         Common_select_inited = 0;
1192 }
1193
1194 // ------------------------------------------------------------------------
1195 //      load_wing_icons() creates the bitmaps for wing icons 
1196 //
1197 void load_wing_icons(char *filename)
1198 {
1199         int first_frame, num_frames;
1200
1201         first_frame = bm_load_animation(filename, &num_frames);
1202         if ( first_frame == -1 ) {
1203                 Error(LOCATION, "Could not load icons from %s\n", filename);
1204                 return;
1205         }
1206
1207         Wing_slot_disabled_bitmap = first_frame;
1208         Wing_slot_empty_bitmap = first_frame + 1;
1209 //      Wing_slot_player_empty_bitmap = first_frame + 2;
1210 }
1211
1212 // ------------------------------------------------------------------------
1213 //      common_scroll_up_pressed()
1214 //
1215 int common_scroll_up_pressed(int *start, int size, int max_show)
1216 {
1217         // check if we even need to scroll at all
1218         if ( size <= max_show ) {
1219                 return 0;
1220         }
1221
1222         if ( (size - *start) > max_show ) {
1223                 *start += 1;
1224                 return 1;
1225         }
1226         return 0;
1227 }
1228
1229 // ------------------------------------------------------------------------
1230 //      common_scroll_down_pressed()
1231 //
1232 int common_scroll_down_pressed(int *start, int size, int max_show)
1233 {
1234         // check if we even need to scroll at all
1235         if ( size <= max_show ) {
1236                 return 0;
1237         }
1238
1239         if ( *start > 0 ) {
1240                 *start -= 1;
1241                 return 1;
1242         }
1243         return 0;
1244 }
1245
1246 // NEWSTUFF BEGIN
1247
1248 loadout_data Player_loadout;    // what the ship and weapon loadout is... used since we want to use the 
1249                                                                                 // same loadout if the mission is played again
1250
1251 //wss_unit      Wss_slots[MAX_WSS_SLOTS];                               // slot data struct
1252 //int           Wl_pool[MAX_WEAPON_TYPES];                              // weapon pool 
1253 //int           Ss_pool[MAX_SHIP_TYPES];                                // ship pool
1254 //int           Wss_num_wings;                                                          // number of player wings
1255
1256 wss_unit        Wss_slots_teams[MAX_TEAMS][MAX_WSS_SLOTS];
1257 int             Wl_pool_teams[MAX_TEAMS][MAX_WEAPON_TYPES];
1258 int             Ss_pool_teams[MAX_TEAMS][MAX_SHIP_TYPES];
1259 int             Wss_num_wings_teams[MAX_TEAMS];
1260
1261 wss_unit        *Wss_slots;
1262 int             *Wl_pool;
1263 int             *Ss_pool;
1264 int             Wss_num_wings;
1265
1266 // save ship selection loadout to the Player_loadout struct
1267 void wss_save_loadout()
1268 {
1269         int i,j;
1270
1271         // save the ship pool
1272         for ( i = 0; i < MAX_SHIP_TYPES; i++ ) {
1273                 Player_loadout.ship_pool[i] = Ss_pool[i]; 
1274         }
1275
1276         // save the weapons pool
1277         for ( i = 0; i < MAX_WEAPON_TYPES; i++ ) {
1278                 Player_loadout.weapon_pool[i] = Wl_pool[i]; 
1279         }
1280
1281         // save the ship class / weapons for each slot
1282         for ( i = 0; i < MAX_WSS_SLOTS; i++ ) {
1283                 Player_loadout.unit_data[i].ship_class = Wss_slots[i].ship_class;
1284
1285                 for ( j = 0; j < MAX_WL_WEAPONS; j++ ) {
1286                         Player_loadout.unit_data[i].wep[j] = Wss_slots[i].wep[j];
1287                         Player_loadout.unit_data[i].wep_count[j] = Wss_slots[i].wep_count[j];
1288                 }
1289         }
1290 }
1291
1292 // restore ship/weapons loadout from the Player_loadout struct
1293 void wss_restore_loadout()
1294 {
1295         int i,j;
1296         wss_unit        *slot;
1297
1298         // only restore if mission hasn't changed
1299         if ( stricmp(Player_loadout.last_modified, The_mission.modified) ) {
1300                 return;
1301         }
1302
1303         // restore the ship pool
1304         for ( i = 0; i < MAX_SHIP_TYPES; i++ ) {
1305                 Ss_pool[i] = Player_loadout.ship_pool[i]; 
1306         }
1307
1308         // restore the weapons pool
1309         for ( i = 0; i < MAX_WEAPON_TYPES; i++ ) {
1310                 Wl_pool[i] = Player_loadout.weapon_pool[i]; 
1311         }
1312
1313         // restore the ship class / weapons for each slot
1314         for ( i = 0; i < MAX_WSS_SLOTS; i++ ) {
1315                 slot = &Player_loadout.unit_data[i];
1316                 Wss_slots[i].ship_class = slot->ship_class;
1317
1318                 for ( j = 0; j < MAX_WL_WEAPONS; j++ ) {
1319                         Wss_slots[i].wep[j]= slot->wep[j];
1320                         Wss_slots[i].wep_count[j] = slot->wep_count[j];
1321                 }
1322         }
1323 }
1324
1325 // Do a direct restore of the Player_loadout ship/weapon data to the wings
1326 void wss_direct_restore_loadout()
1327 {
1328         int                             i, j;
1329         wing                            *wp;
1330         wss_unit                        *slot;
1331
1332         // only restore if mission hasn't changed
1333         if ( stricmp(Player_loadout.last_modified, The_mission.modified) ) {
1334                 return;
1335         }
1336
1337         for ( i = 0; i < MAX_WING_BLOCKS; i++ ) {
1338
1339                 if ( Starting_wings[i] < 0 )
1340                         continue;
1341
1342                 wp = &Wings[Starting_wings[i]];
1343
1344                 // If this wing is still on the arrival list, then update the parse objects
1345                 if ( wp->ship_index[0] == -1 ) {
1346                         p_object *p_objp;
1347                         j=0;
1348                         for ( p_objp = GET_FIRST(&ship_arrival_list); p_objp != END_OF_LIST(&ship_arrival_list); p_objp = GET_NEXT(p_objp) ) {
1349                                 slot = &Player_loadout.unit_data[i*4+j];
1350                                 if ( p_objp->wingnum == WING_INDEX(wp) ) {
1351                                         p_objp->ship_class = slot->ship_class;
1352                                         wl_update_parse_object_weapons(p_objp, slot);
1353                                         j++;
1354                                 }
1355                         }
1356                 } else {
1357                         int     k;
1358                         int cleanup_ship_index[MAX_WING_SLOTS];
1359                         ship    *shipp;
1360
1361                         for ( k = 0; k < MAX_WING_SLOTS; k++ ) {
1362                                 cleanup_ship_index[k] = -1;
1363                         }
1364
1365                         // This wing is already created, so directly update the ships
1366                         for ( j = 0; j < MAX_WING_SLOTS; j++ ) {
1367                                 slot = &Player_loadout.unit_data[i*4+j];
1368                                 shipp = &Ships[wp->ship_index[j]];
1369                                 if ( shipp->ship_info_index != slot->ship_class ) {
1370
1371                                         if ( wp->ship_index[j] == -1 ) {
1372                                                 continue;
1373                                         }
1374
1375                                         if ( slot->ship_class == -1 ) {
1376                                                 cleanup_ship_index[j] = wp->ship_index[j];
1377                                                 ship_add_exited_ship( shipp, SEF_PLAYER_DELETED );
1378                                                 obj_delete(shipp->objnum);
1379                                                 hud_set_wingman_status_none( shipp->wing_status_wing_index, shipp->wing_status_wing_pos);
1380                                                 continue;
1381                                         } else {
1382                                                 change_ship_type(wp->ship_index[j], slot->ship_class);
1383                                         }
1384                                 }
1385                                 wl_bash_ship_weapons(&Ships[wp->ship_index[j]].weapons, slot);
1386                         }
1387
1388                         for ( k = 0; k < MAX_WING_SLOTS; k++ ) {
1389                                 if ( cleanup_ship_index[k] != -1 ) {
1390                                         ship_wing_cleanup( cleanup_ship_index[k], wp );
1391                                 }
1392                         }
1393
1394                 }
1395         } // end for 
1396 }
1397 int wss_slots_all_empty()
1398 {
1399         int i;
1400
1401         for ( i = 0; i < MAX_WSS_SLOTS; i++ ) {
1402                 if ( Wss_slots[i].ship_class >= 0 ) 
1403                         break;
1404         }
1405
1406         if ( i == MAX_WSS_SLOTS )
1407                 return 1;
1408         else
1409                 return 0;
1410 }
1411
1412 // determine the mode (WSS_...) based on slot/list index values
1413 int wss_get_mode(int from_slot, int from_list, int to_slot, int to_list, int wl_ship_slot)
1414 {
1415         int mode, to_slot_empty=0;
1416
1417         if ( wl_ship_slot >= 0 ) {
1418                 // weapons loadout
1419                 if ( to_slot >= 0 ) {
1420                         if ( Wss_slots[wl_ship_slot].wep_count[to_slot] == 0 ) {
1421                                 to_slot_empty = 1;
1422                         }
1423                 }
1424         } else {
1425                 // ship select
1426                 if ( to_slot >= 0 ) {
1427                         if ( Wss_slots[to_slot].ship_class == -1 ){
1428                                 to_slot_empty = 1;
1429                         }
1430                 }
1431         }
1432
1433         // determine mode
1434         if ( from_slot >= 0 && to_slot >= 0 ) {
1435                 mode = WSS_SWAP_SLOT_SLOT;
1436         } else if ( from_slot >= 0 && to_list >= 0 ) {
1437                 mode = WSS_DUMP_TO_LIST;
1438         } else if ( (from_list >= 0) && (to_slot >= 0) && (to_slot_empty) ) {
1439                 mode = WSS_GRAB_FROM_LIST;
1440         } else if ( (from_list >= 0) && (to_slot >= 0) && (!to_slot_empty) ) {
1441                 mode = WSS_SWAP_LIST_SLOT;
1442         } else {
1443                 mode = -1;      // no changes required
1444         }
1445
1446         return mode;
1447 }
1448
1449 // store all the unit data and pool data 
1450 int store_wss_data(ubyte *block, int max_size, int sound,int player_index)
1451 {
1452         int j, i,offset=0;      
1453         short player_id;        
1454         short ishort;
1455
1456         // write the ship pool 
1457         for ( i = 0; i < MAX_SHIP_TYPES; i++ ) {
1458                 if ( Ss_pool[i] > 0 ) { 
1459                         block[offset++] = (ubyte)i;
1460                         Assert( Ss_pool[i] < UCHAR_MAX );
1461                         
1462                         // take care of sign issues
1463                         if(Ss_pool[i] == -1){
1464                                 block[offset++] = 0xff;
1465                         } else {
1466                                 block[offset++] = (ubyte)Ss_pool[i];
1467                         }
1468                 }
1469         }
1470
1471         block[offset++] = 0xff; // signals start of weapons pool
1472
1473         // write the weapon pool
1474         for ( i = 0; i < MAX_WEAPON_TYPES; i++ ) {
1475                 if ( Wl_pool[i] > 0 ) {
1476                         block[offset++] = (ubyte)i;
1477                         ishort = (short)Wl_pool[i];
1478                         memcpy(block+offset, &ishort, sizeof(short));
1479                         offset += sizeof(short);
1480                 }
1481         }
1482
1483         // write the unit data
1484
1485         block[offset++] = 0xff; // signals start of unit data
1486
1487         for ( i=0; i<MAX_WSS_SLOTS; i++ ) {
1488                 Assert( Wss_slots[i].ship_class < UCHAR_MAX );
1489                 if(Wss_slots[i].ship_class == -1){
1490                         block[offset++] = 0xff;
1491                 } else {
1492                         block[offset++] = (ubyte)(Wss_slots[i].ship_class);
1493                 }
1494                 for ( j = 0; j < MAX_WL_WEAPONS; j++ ) {
1495                         // take care of sign issues
1496                         Assert( Wss_slots[i].wep[j] < UCHAR_MAX );                      
1497                         if(Wss_slots[i].wep[j] == -1){
1498                                 block[offset++] = 0xff;
1499                         } else {
1500                                 block[offset++] = (ubyte)(Wss_slots[i].wep[j]);
1501                         }
1502
1503                         Assert( Wss_slots[i].wep_count[j] < SHRT_MAX );
1504                         ishort = short(Wss_slots[i].wep_count[j]);
1505
1506                         memcpy(&(block[offset]), &(ishort), sizeof(short) );
1507                         offset += sizeof(short);
1508                 }
1509
1510                 // mwa -- old way below -- too much space
1511                 //memcpy(block+offset, &Wss_slots[i], sizeof(wss_unit));
1512                 //offset += sizeof(wss_unit);
1513         }
1514
1515         // any sound index
1516         if(sound == -1){
1517                 block[offset++] = 0xff;
1518         } else {
1519                 block[offset++] = (ubyte)sound;
1520         }
1521
1522         // add a netplayer address to identify who should play the sound
1523         player_id = -1;
1524         if(player_index != -1){
1525                 player_id = Net_players[player_index].player_id;                
1526         }
1527         memcpy(block+offset,&player_id,sizeof(player_id));
1528         offset += sizeof(player_id);
1529
1530         Assert( offset < max_size );
1531         return offset;
1532 }
1533
1534 int restore_wss_data(ubyte *block)
1535 {
1536         int     i, j, sanity, offset=0;
1537         ubyte   b1, b2,sound;   
1538         short ishort;
1539         short player_id;        
1540
1541         // restore ship pool
1542         sanity=0;
1543         memset(Ss_pool, 0, MAX_SHIP_TYPES*sizeof(int));
1544         for (;;) {
1545                 if ( sanity++ > MAX_SHIP_TYPES ) {
1546                         Int3();
1547                         break;
1548                 }
1549
1550                 b1 = block[offset++];
1551                 if ( b1 == 0xff ) {
1552                         break;
1553                 }
1554         
1555                 // take care of sign issues
1556                 b2 = block[offset++];
1557                 if(b2 == 0xff){
1558                         Ss_pool[b1] = -1;
1559                 } else {
1560                         Ss_pool[b1] = b2;
1561                 }
1562         }
1563
1564         // restore weapons pool
1565         sanity=0;
1566         memset(Wl_pool, 0, MAX_WEAPON_TYPES*sizeof(int));
1567         for (;;) {
1568                 if ( sanity++ > MAX_WEAPON_TYPES ) {
1569                         Int3();
1570                         break;
1571                 }
1572
1573                 b1 = block[offset++];
1574                 if ( b1 == 0xff ) {
1575                         break;
1576                 }
1577         
1578                 memcpy(&ishort, block+offset, sizeof(short));
1579                 offset += sizeof(short);
1580                 Wl_pool[b1] = ishort;
1581         }
1582
1583         for ( i=0; i<MAX_WSS_SLOTS; i++ ) {
1584                 if(block[offset] == 0xff){
1585                         Wss_slots[i].ship_class = -1;
1586                 } else {
1587                         Wss_slots[i].ship_class = block[offset];
1588                 }
1589                 offset++;               
1590                 for ( j = 0; j < MAX_WL_WEAPONS; j++ ) {
1591                         // take care of sign issues
1592                         if(block[offset] == 0xff){
1593                                 Wss_slots[i].wep[j] = -1;
1594                                 offset++;
1595                         } else {
1596                                 Wss_slots[i].wep[j] = (int)(block[offset++]);
1597                         }
1598                 
1599                         memcpy( &ishort, &(block[offset]), sizeof(short) );
1600                         Wss_slots[i].wep_count[j] = (int)ishort;
1601                         offset += sizeof(short);
1602                 }
1603
1604                 // mwa -- old way below
1605                 //memcpy(&Wss_slots[i], block+offset, sizeof(wss_unit));
1606                 //offset += sizeof(wss_unit);
1607         }
1608
1609         // read in the sound data
1610         sound = block[offset++];                                        // the sound index
1611
1612         // read in the player address
1613         memcpy(&player_id,block+offset,sizeof(player_id));
1614         offset += sizeof(short);
1615         
1616         // determine if I'm the guy who should be playing the sound
1617         if((Net_player != NULL) && (Net_player->player_id == player_id)){
1618                 // play the sound
1619                 if(sound != 0xff){
1620                         gamesnd_play_iface((int)sound);
1621                 }
1622         }
1623
1624         if(!(Game_mode & GM_MULTIPLAYER)){
1625                 ss_synch_interface();
1626         }       
1627         return offset;
1628 }
1629
1630 // NEWSTUFF END
1631