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