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