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