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