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