]> icculus.org git repositories - taylor/freespace2.git/blob - src/menuui/mainhallmenu.cpp
added copyright header
[taylor/freespace2.git] / src / menuui / mainhallmenu.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/MenuUI/MainHallMenu.cpp $
11  * $Revision$
12  * $Date$
13  * $Author$
14  *
15  * Header file for main-hall menu code
16  *
17  * $Log$
18  * Revision 1.5  2002/06/09 04:41:22  relnev
19  * added copyright header
20  *
21  * Revision 1.4  2002/06/01 03:32:00  relnev
22  * fix texture loading mistake.
23  *
24  * enable some d3d stuff for opengl also
25  *
26  * Revision 1.3  2002/05/30 16:55:44  theoddone33
27  * now gets to another screen
28  *
29  * Revision 1.2  2002/05/27 22:43:02  theoddone33
30  * Fix more glide symbols
31  *
32  * Revision 1.1.1.1  2002/05/03 03:28:09  root
33  * Initial import.
34  *
35  * 
36  * 62    10/28/99 2:04a Jefff
37  * fixed a string
38  * 
39  * 61    9/15/99 6:28p Dave
40  * No load mission button in RELEASE_REAL
41  * 
42  * 60    9/13/99 4:52p Dave
43  * RESPAWN FIX
44  * 
45  * 59    9/13/99 11:30a Dave
46  * Added checkboxes and functionality for disabling PXO banners as well as
47  * disabling d3d zbuffer biasing.
48  * 
49  * 58    9/07/99 6:55p Jefff
50  * added jump-to-campaign-mission cheat
51  * 
52  * 57    9/07/99 4:01p Dave
53  * Fixed up a string.tbl paroblem (self destruct message). Make sure IPX
54  * does everything properly (setting up address when binding). Remove
55  * black rectangle background from UI_INPUTBOX.
56  * 
57  * 56    9/06/99 6:38p Dave
58  * Improved CD detection code.
59  * 
60  * 55    9/06/99 1:30a Dave
61  * Intermediate checkin. Started on enforcing CD-in-drive to play the
62  * game.
63  * 
64  * 54    9/03/99 1:31a Dave
65  * CD checking by act. Added support to play 2 cutscenes in a row
66  * seamlessly. Fixed super low level cfile bug related to files in the
67  * root directory of a CD. Added cheat code to set campaign mission # in
68  * main hall.
69  * 
70  * 53    9/01/99 11:02p Dave
71  * Made head guy look right when not animating.
72  * 
73  * 52    8/27/99 12:04a Dave
74  * Campaign loop screen.
75  * 
76  * 51    8/26/99 9:45a Dave
77  * First pass at easter eggs and cheats.
78  * 
79  * 50    8/25/99 11:57a Jefff
80  * freespace -> freespace 2 in tooltip strings
81  * 
82  * 49    8/25/99 10:50a Dave
83  * Added music to the mainhall.tbl
84  * 
85  * 48    8/24/99 8:55p Dave
86  * Make sure nondimming pixels work properly in tech menu.
87  * 
88  * 47    8/18/99 11:44a Jefff
89  * minor string fixes
90  * 
91  * 46    8/10/99 4:45p Jefff
92  * changed a string
93  * 
94  * 45    8/06/99 1:01p Andsager
95  * disable quick start (g) for demo
96  * 
97  * 44    8/05/99 10:34a Jefff
98  * more mouseover sound fixes
99  * 
100  * 43    8/04/99 9:12p Andsager
101  * Add campaign room popup allowing restart of campaign in demo.
102  * 
103  * 42    8/04/99 5:36p Dave
104  * Make glide and D3D switch out properly.
105  * 
106  * 41    8/04/99 4:35p Jefff
107  * fixed tech room & options sounds playing only once
108  * 
109  * 40    8/03/99 5:41p Jefff
110  * made "f1 for help" draw after animations, and stop if help overlay
111  * active
112  * 
113  * 39    8/03/99 4:42p Jefff
114  * small f1 text fix
115  * 
116  * 38    8/03/99 3:48p Jefff
117  * 
118  * 37    8/02/99 9:13p Dave
119  * Added popup tips.
120  * 
121  * 36    8/02/99 2:26p Jefff
122  * "press f1.." text reworked
123  * 
124  * 35    8/02/99 12:19p Andsager
125  * disable "L" load screen
126  * 
127  * 34    8/02/99 11:12a Jefff
128  * adjusted tooltip shader stuff for more a more pleasing effect.
129  * 
130  * 33    7/30/99 6:05p Jefff
131  * added shader behind tooltip text
132  * 
133  * 32    7/30/99 4:20p Andsager
134  * Added user click sounds to main hall
135  * 
136  * 31    7/29/99 10:47p Dave
137  * Standardized D3D fogging using vertex fog. Shook out Savage 4 bugs.
138  * 
139  * 30    7/27/99 6:53p Dave
140  * Hi-res main hall support.
141  * 
142  * 29    7/16/99 1:49p Dave
143  * 8 bit aabitmaps. yay.
144  * 
145  * 28    7/15/99 9:20a Andsager
146  * FS2_DEMO initial checkin
147  * 
148  * 27    7/13/99 1:15p Dave
149  * 32 bit support. Whee!
150  * 
151  * 26    6/25/99 2:51p Jasons
152  * Changed wording of network error message.
153  * 
154  * 25    6/21/99 1:30p Alanl
155  * changed main menu music tag
156  * 
157  * 24    6/19/99 3:56p Dave
158  * Moved main hall definitions into a table file. Whee!
159  * 
160  * 23    6/11/99 11:13a Dave
161  * last minute changes before press tour build.
162  * 
163  * 22    5/09/99 8:57p Dave
164  * Final E3 build preparations.
165  * 
166  * 21    4/25/99 3:02p Dave
167  * Build defines for the E3 build.
168  * 
169  * 20    4/12/99 10:07p Dave
170  * Made network startup more forgiving. Added checkmarks to dogfight
171  * screen for players who hit commit.
172  * 
173  * 19    3/28/99 5:58p Dave
174  * Added early demo code. Make objects move. Nice and framerate
175  * independant, but not much else. Don't use yet unless you're me :)
176  * 
177  * 18    3/25/99 5:47p Dave
178  * Removed the whee
179  * 
180  * 17    3/19/99 9:51a Dave
181  * Checkin to repair massive source safe crash. Also added support for
182  * pof-style nebulae, and some new weapons code.
183  * 
184  * 16    2/25/99 4:19p Dave
185  * Added multiplayer_beta defines. Added cd_check define. Fixed a few
186  * release build warnings. Added more data to the squad war request and
187  * response packets.
188  * 
189  * 15    2/03/99 11:44a Dave
190  * Fixed d3d transparent textures.
191  * 
192  * 14    1/30/99 5:08p Dave
193  * More new hi-res stuff.Support for nice D3D textures.
194  * 
195  * 13    1/27/99 9:56a Dave
196  * Temporary checkin of beam weapons for Dan to make cool sounds.
197  * 
198  * 12    12/31/98 11:23a Dave
199  * Put mini-indicators for status of ships.tbl and weapons.tbl in the
200  * lower left corner of the main hall.
201  * 
202  * 11    12/18/98 1:13a Dave
203  * Rough 1024x768 support for Direct3D. Proper detection and usage through
204  * the launcher.
205  * 
206  * 10    11/30/98 1:07p Dave
207  * 16 bit conversion, first run.
208  * 
209  * 9     11/20/98 4:08p Dave
210  * Fixed flak effect in multiplayer.
211  * 
212  * 8     11/20/98 11:16a Dave
213  * Fixed up IPX support a bit. Making sure that switching modes and
214  * loading/saving pilot files maintains proper state.
215  * 
216  * 7     11/19/98 4:57p Dave
217  * Ignore PXO option if IPX is selected.
218  * 
219  * 6     11/19/98 4:19p Dave
220  * Put IPX sockets back in psnet. Consolidated all multiplayer config
221  * files into one.
222  * 
223  * 5     11/05/98 5:55p Dave
224  * Big pass at reducing #includes
225  * 
226  * 4     11/05/98 4:18p Dave
227  * First run nebula support. Beefed up localization a bit. Removed all
228  * conditional compiles for foreign versions. Modified mission file
229  * format.
230  * 
231  * 3     10/13/98 9:28a Dave
232  * Started neatening up freespace.h. Many variables renamed and
233  * reorganized. Added AlphaColors.[h,cpp]
234  * 
235  * 2     10/07/98 10:53a Dave
236  * Initial checkin.
237  * 
238  * 1     10/07/98 10:49a Dave
239  * 
240  * 103   10/02/98 3:22p Allender
241  * fix up the -connect option and fix the -port option
242  * 
243  * 102   8/20/98 5:31p Dave
244  * Put in handy multiplayer logfile system. Now need to put in useful
245  * applications of it all over the code.
246  * 
247  * 101   8/07/98 10:40a Allender
248  * new command line flags for starting netgames.  Only starting currently
249  * works, and PXO isn't implemented yet
250  * 
251  * 100   7/13/98 10:46a Lawrance
252  * Index another localized string
253  * 
254  * 99    7/10/98 1:13a Allender
255  * lots of small multiplayer update changes.  Code in launcher to specify
256  * connection speed.  A couple of small fixes regarding empty mission
257  * files.  Time out players after 10 second when they don't connect on
258  * their reliable socket.
259  * 
260  * 98    6/09/98 10:31a Hoffoss
261  * Created index numbers for all xstr() references.  Any new xstr() stuff
262  * added from here on out should be added to the end if the list.  The
263  * current list count can be found in FreeSpace.cpp (search for
264  * XSTR_SIZE).
265  * 
266  * 97    6/05/98 9:50a Lawrance
267  * OEM changes
268  * 
269  * 96    6/01/98 11:43a John
270  * JAS & MK:  Classified all strings for localization.
271  * 
272  * 95    5/22/98 9:02p Allender
273  * remove G key from main hall
274  * 
275  * 94    5/22/98 10:54a Allender
276  * new dialog information for networking to tell user if connection type
277  * doesn't match the setup specified type
278  * 
279  * 93    5/15/98 5:15p Dave
280  * Fix a standalone resetting bug.Tweaked PXO interface. Display captaincy
281  * status for team vs. team. Put in asserts to check for invalid team vs.
282  * team situations.
283  * 
284  * 92    5/13/98 12:23a Lawrance
285  * Don't init main hall if already inited... not needed now, but may be
286  * useful if we don't always want to call main_hall_close() when switching
287  * states
288  * 
289  * 91    5/12/98 2:46a Dave
290  * Rudimentary communication between Parallax Online and freespace. Can
291  * get and store channel lists.
292  * 
293  * 90    5/08/98 5:33p Lawrance
294  * check for CD when trying to enter ready room in single player
295  *  
296  * 
297  * $NoKeywords: $
298  *
299  */
300
301 #include "mainhallmenu.h"
302 #include "palman.h"
303 #include "bmpman.h"
304 #include "2d.h"
305 #include "gamesequence.h"
306 #include "animplay.h"
307 #include "key.h"
308 #include "timer.h"
309 #include "ui.h"
310 #include "snazzyui.h"
311 #include "player.h"
312 #include "audiostr.h"
313 #include "gamesnd.h"
314 #include "eventmusic.h"
315 #include "mouse.h"
316 #include "contexthelp.h"
317 #include "cmdline.h"
318 #include "psnet.h"
319 #include "multiui.h"
320 #include "multiutil.h"
321 #include "popup.h"
322 #include "rtvoice.h"
323 #include "osapi.h"
324 #include "playermenu.h"
325 #include "freespace.h"
326 #include "multi_voice.h"
327 #include "multi.h"
328 #include "alphacolors.h"
329 #include "demo.h"
330 #include "fishtank.h"
331
332 // #include "movie.h"
333
334 // ----------------------------------------------------------------------------
335 // MAIN HALL DATA DEFINES
336 //
337 #define MAX_RANDOM_INTERCOM_SOUNDS                              10
338 #define NUM_RANDOM_INTERCOM_SOUNDS_0                    3
339 #define NUM_RANDOM_INTERCOM_SOUNDS_1                    3
340
341 #define MAX_MISC_ANIMATIONS                                             10
342 #define NUM_MISC_ANIMATIONS_0                                           2
343 #define NUM_MISC_ANIMATIONS_1                                           4
344
345 #define MAX_DOOR_ANIMATIONS                                             10
346 #define NUM_DOOR_ANIMATIONS_0                                           6
347 #define NUM_DOOR_ANIMATIONS_1                                           6
348
349 #define MAX_DOOR_SOUNDS                                                         10
350 #define NUM_DOOR_SOUNDS_0                                                       6
351 #define NUM_DOOR_SOUNDS_1                                                       6
352
353 #define MISC_ANIM_MODE_LOOP                                             0                               // loop the animation
354 #define MISC_ANIM_MODE_HOLD                                             1                               // play to the end and hold the animation
355 #define MISC_ANIM_MODE_TIMED                                            2                               // uses timestamps to determine when a finished anim should be checked again
356
357 #define NUM_REGIONS                                                                     7                               // (6 + 1 for multiplayer equivalent of campaign room)
358 typedef struct main_hall_defines {
359         // bitmap and mask
360         char bitmap[MAX_FILENAME_LEN+1];
361         char mask[MAX_FILENAME_LEN+1];
362
363         // music
364         char music[MAX_FILENAME_LEN+1];
365
366         // intercom defines -------------------
367         
368         // # of intercom sounds
369         int num_random_intercom_sounds;
370         
371         // random (min/max) delays between playing intercom sounds
372         int intercom_delay[MAX_RANDOM_INTERCOM_SOUNDS][2];
373         
374         // intercom sounds themselves
375         int intercom_sounds[MAX_RANDOM_INTERCOM_SOUNDS];
376
377         // intercom sound pan values
378         float intercom_sound_pan[MAX_RANDOM_INTERCOM_SOUNDS];
379
380
381         // misc animations --------------------
382
383         // # of misc animations
384         int num_misc_animations;
385
386         // filenames of the misc animations
387         char misc_anim_name[MAX_MISC_ANIMATIONS][MAX_FILENAME_LEN+1];
388
389         // Time until we will next play a given misc animation, min delay, and max delay
390         int misc_anim_delay[MAX_MISC_ANIMATIONS][3];
391
392         //      coords of where to play the misc anim
393         int misc_anim_coords[MAX_MISC_ANIMATIONS][2];
394         
395         // misc anim play modes (see MISC_ANIM_MODE_* above)
396         int misc_anim_modes[MAX_MISC_ANIMATIONS];
397
398         // panning values for each of the misc anims
399         float misc_anim_sound_pan[MAX_MISC_ANIMATIONS];
400
401         // [N][0] == # of sounds, [N][1-9] sound index
402         int misc_anim_special_sounds[MAX_MISC_ANIMATIONS][10];
403
404         // [N][0] == # of triggers, [N][1-9] >= frame num
405         int misc_anim_special_trigger[MAX_MISC_ANIMATIONS][10];
406
407         // [N][0] == # of handles, [N][1-9] == sound handle num
408         int misc_anim_sound_handles[MAX_MISC_ANIMATIONS][10];
409
410         // [N][0] == # of handles, [N][1-9] == sound "should" be playing
411         int misc_anim_sound_flag[MAX_MISC_ANIMATIONS][10];      
412
413
414         // door animations --------------------
415
416         // # of door animations
417         int num_door_animations;
418         
419         // filenames of the door animations
420         char door_anim_name[MAX_DOOR_ANIMATIONS][MAX_FILENAME_LEN+1];   
421
422         // first pair : coords of where to play a given door anim
423         // second pair : center of a given door anim in windowed mode
424         int door_anim_coords[MAX_DOOR_ANIMATIONS][4];
425         
426
427         // door sounds ------------------------
428
429         // # of door sounds
430         int num_door_sounds;
431
432         // sounds for each region (open/close)
433         int door_sounds[MAX_DOOR_SOUNDS][2];
434
435         // pan values for the door sounds
436         float door_sound_pan[MAX_DOOR_SOUNDS];
437
438         
439         // region descriptions ----------------
440         
441         // text (tooltip) description
442         char *region_descript[NUM_REGIONS];
443
444         // y coord of where to draw tooltip text
445         int region_yval;
446
447 } main_hall_defines;
448
449
450 // use main hall 0 by default
451 main_hall_defines Main_hall_defines[GR_NUM_RESOLUTIONS][NUM_MAIN_HALLS];
452 main_hall_defines *Main_hall = &Main_hall_defines[0][0];
453
454 int Vasudan_funny = 0;
455 int Vasudan_funny_plate = -1;
456
457 char Main_hall_campaign_cheat[512] = "";
458         
459 // ----------------------------------------------------------------------------
460 // MISC interface data
461 //
462 // is the main hall inited (for reentrancy)
463 int Main_hall_inited = 0;
464
465 // handle to the playing music
466 int Main_hall_music_handle = -1;
467
468 // background bitmap handle
469 int Main_hall_bitmap;
470
471 // background bitmap mask handle
472 int Main_hall_mask;
473
474 // variable used for automatic netgame starting/joining
475 int Main_hall_netgame_started = 0;
476
477 // bitmap struct for th background mask bitmap
478 bitmap *Main_hall_mask_bitmap;
479
480 // actual data for the background mask bitmap
481 ubyte *Main_hall_mask_data;
482
483 int Main_hall_mask_w, Main_hall_mask_h;
484
485
486 // ----------------------------------------------------------------------------
487 // MOUSE clicking stuff
488 //
489 // indicates whether a right click occured
490 int Main_hall_right_click;
491
492 // use this to cycle through the selectable regions instead of the mouse's current region
493 int Main_hall_last_clicked_region;
494
495 // use this to determine how long the cursor has to linger on a region before it starts playing
496 #define MAIN_HALL_REGION_LINGER                         175                             // in ms
497 int Main_hall_region_linger_stamp = -1;
498
499 // handle any right clicks which may have occured
500 void main_hall_handle_right_clicks();
501
502
503 // ----------------------------------------------------------------------------
504 // RANDOM intercom sounds
505 //
506
507 // next random intercom sound to play
508 int Main_hall_next_intercom_sound = 0;  
509
510 // delay for the next intercom sound
511 int Main_hall_next_intercom_sound_stamp = -1;
512
513 // handle to any playing instance of a random intercom sound
514 int Main_hall_intercom_sound_handle = -1;
515
516 // handle any details related to random intercom sounds
517 void main_hall_handle_random_intercom_sounds();
518
519
520 // ----------------------------------------------------------------------------
521 // MISC animations
522 //
523
524 // the misc animations themselves
525 anim *Main_hall_misc_anim[MAX_MISC_ANIMATIONS];                                                 
526
527 // the instance of a given misc animation
528 anim_instance *Main_hall_misc_anim_instance[MAX_MISC_ANIMATIONS];       
529
530 // handle starting, stopping and randomizing misc animations
531 void main_hall_handle_misc_anims();                                                                     
532
533 // cull any finished misc animation instances
534 void main_hall_cull_misc_anim_instances();                                                              
535
536 // render all playing misc animations
537 void main_hall_render_misc_anims(float frametime);
538
539
540 // ----------------------------------------------------------------------------
541 // DOOR animations (not all of these are doors anymore, but they're doorlike _regions_)
542 //
543 #define DOOR_TEXT_X 100
544 #define DOOR_TEXT_Y 450
545
546 // the door animations themselves
547 anim *Main_hall_door_anim[MAX_DOOR_ANIMATIONS];                                                 
548
549 // the instance of a given door animation
550 anim_instance *Main_hall_door_anim_instance[MAX_DOOR_ANIMATIONS];       
551
552 // render all playing door animations
553 void main_hall_render_door_anims(float frametime);
554
555
556 // ----------------------------------------------------------------------------
557 // SNAZZY MENU stuff
558 //
559 #define NUM_MAIN_HALL_REGIONS 10
560 #define NUM_MAIN_HALL_MOUSE_REGIONS 6
561
562 // region mask #'s (identifiers)
563 #define EXIT_REGION                              0
564 #define BARRACKS_REGION                  1
565 #define READY_ROOM_REGION                2
566 #define TECH_ROOM_REGION                 3
567 #define OPTIONS_REGION                   4
568 #define CAMPAIGN_ROOM_REGION     5
569 #define MULTIPLAYER_REGION     10
570 #define LOAD_MISSION_REGION    11
571 #define QUICK_START_REGION     12
572 #define SKILL_LEVEL_REGION     13
573
574 // all the menu regions in the main hall
575 MENU_REGION Main_hall_region[NUM_MAIN_HALL_REGIONS];
576
577 // # of regions (options) on this screen. parsed from a table
578 int Main_hall_num_options;
579
580 // region over which the mouse is currently residing, or -1 if over no region
581 // NOTE : you should nevery change this directly. Always use main_hall_handle_mouse_location(int)
582 //        to do this. Otherwise, the door opening and closing animations will get screwed up
583 int Main_hall_mouse_region;     
584
585 // set this to skip a frame
586 int Main_hall_frame_skip;
587
588 // do any necessary processing based upon the mouse location
589 void main_hall_handle_mouse_location(int cur_region);
590
591 // if the mouse has moved off of the currently active region, handle the anim accordingly
592 void main_hall_mouse_release_region(int region);                                
593
594 // if the mouse has moved on this region, handle it accordingly
595 void main_hall_mouse_grab_region(int region);                                   
596
597
598 // ----------------------------------------------------------------------------
599 // SOUND data / handlers
600 // -
601
602 // toaster oven room sound idex
603 #define TOASTER_REGION          3
604
605 // everyone's favorite desk guardian
606 #define ALLENDER_REGION         4
607
608 // handles to the sound instances of the doors opening/closing
609 int Main_hall_door_sound_handles[MAX_DOOR_SOUNDS] = {           
610         -1,-1,-1,-1,-1,-1
611 };
612
613 // sound handle for looping ambient sound
614 int Main_hall_ambient_loop = -1;                        
615
616 // cull any door sounds that have finished playing
617 void main_hall_cull_door_sounds();
618
619 // handle starting, stopping and reversing "door" animations
620 void main_hall_handle_region_anims();                                                           
621
622
623 // ----------------------------------------------------------------------------
624 // warning/notification messages
625 //
626 #define MAIN_HALL_NOTIFY_TIME  3500
627
628 // timestamp for the notification messages
629 int Main_hall_notify_stamp = -1;
630
631 // text to display as the current notification message
632 char Main_hall_notify_text[300]="";
633
634 // set the current notification string and the associated timestamp
635 void main_hall_set_notify_string(char *str);
636
637 // handle any drawing, culling, etc of notification messages
638 void main_hall_notify_do();
639
640
641 // ----------------------------------------------------------------------------
642 // MISC functions
643 //
644
645 // upper _RIGHT_ corner for the version text
646 #define MAIN_HALL_VERSION_X             630                     
647 #define MAIN_HALL_VERSION_Y             467
648
649 // main hall help overlay ID
650 int Main_hall_overlay_id;
651
652 // blit the freespace version #
653 void main_hall_blit_version();
654
655 // blit any necessary tooltips
656 void main_hall_maybe_blit_tooltips();
657
658 // shader for behind tooltips
659 shader Main_hall_tooltip_shader;
660
661 // num pixels shader is above/below tooltip text
662 static int Main_hall_tooltip_padding[GR_NUM_RESOLUTIONS] = {
663         4,              // GR_640
664         7,              // GR_1024
665 };
666 static int Main_hall_f1_text_frame = 0;
667 static int F1_text_done = 0;
668
669 // read in main hall table
670 void main_hall_read_table();
671
672 // "press f1" for help stuff
673 #define MAIN_HALL_HELP_TIME             5000
674 int Main_hall_help_stamp = -1;
675 void main_hall_process_help_stuff();
676
677
678 // ----------------------------------------------------------------------------
679 // VOICE RECORDING STUFF
680 //
681
682 // are we currently recording voice?
683 int Recording = 0;
684
685
686 // called when multiplayer clicks on the ready room door.  May pop up dialog depending on network
687 // connection status and errors
688 void main_hall_do_multi_ready()
689 {
690         int error;
691
692         error = psnet_get_network_status();
693         switch( error ) {
694         case NETWORK_ERROR_NO_TYPE:
695                 popup( PF_NO_NETWORKING, 1, POPUP_OK, XSTR( "You have not defined your type of Internet connection.  Please run the Launcher, hit the setup button, and go to the Network tab and choose your connection type.", 360));
696                 break;
697         case NETWORK_ERROR_NO_WINSOCK:
698                 popup( PF_NO_NETWORKING, 1, POPUP_OK, XSTR( "Winsock is not installed.  You must have TCP/IP and Winsock installed to play multiplayer FreeSpace.", 361));
699                 break;
700         case NETWORK_ERROR_NO_PROTOCOL:
701                 if(Multi_options_g.protocol == NET_TCP){
702                         popup( PF_NO_NETWORKING, 1, POPUP_OK, XSTR( "TCP/IP protocol not found.  This protocol is required for multiplayer FreeSpace.", 362));
703                 } else {
704                         Assert(Multi_options_g.protocol == NET_IPX);
705                         popup( PF_NO_NETWORKING, 1, POPUP_OK, XSTR( "IPX protocol not found.  This protocol is required for multiplayer FreeSpace.", 362));
706                 }
707                 break;
708         case NETWORK_ERROR_CONNECT_TO_ISP:
709                 popup( PF_NO_NETWORKING, 1, POPUP_OK, XSTR( "You have selected Dial Up Networking as your type of connection to the Internet.  You are not currently connected.  You must connect to your ISP before continuing on past this point.", 363));
710                 break;
711         case NETWORK_ERROR_LAN_AND_RAS:
712                 popup( PF_NO_NETWORKING, 1, POPUP_OK, XSTR( "You have indicated that you use a LAN for networking.  You also appear to be dialed into your ISP.  Please disconnect from your service provider, or choose Dial Up Networking.", 364));
713                 break;
714
715         case NETWORK_ERROR_NONE:
716         default:
717                 break;
718         }
719
720         // if our selected protocol is not active
721         if((Multi_options_g.protocol == NET_TCP) && !Tcp_active){
722                 popup( PF_NO_NETWORKING, 1, POPUP_OK, XSTR( "You have selected TCP/IP for multiplayer Freespace, but the TCP/IP protocol was not detected on your machine.", 362));
723                 return;
724         } 
725         if((Multi_options_g.protocol == NET_IPX) && !Ipx_active){               
726                 popup( PF_NO_NETWORKING, 1, POPUP_OK, XSTR( "You have selected IPX for multiplayer Freespace, but the IPX protocol was not detected on your machine.", 1402));
727                 return;
728         } 
729
730         if ( error != NETWORK_ERROR_NONE ){
731                 return;
732         }
733
734         // 7/9/98 -- MWA.  Deal with the connection speed issue.  make a call to the multiplayer code to
735         // determine is a valid connection setting exists
736         if ( Multi_connection_speed == CONNECTION_SPEED_NONE ) {
737                 popup( PF_NO_NETWORKING, 1, POPUP_OK, XSTR( "You must define your connection speed.  Please run the Launcher, hit the setup button, and go to the Network tab and choose your connection speed.", 986) );
738                 return;
739         }
740
741         // go to parallax online
742 #ifdef MULTIPLAYER_BETA_BUILD // do we want this for FS2_DEMO
743         Multi_options_g.pxo = 1;
744         Multi_options_g.protocol = NET_TCP;     
745         gameseq_post_event( GS_EVENT_PXO );
746 #else
747         
748         // go to the regular join game screen   
749         gameseq_post_event( GS_EVENT_MULTI_JOIN_GAME ); 
750 #endif  
751
752         // select protocol
753         psnet_use_protocol(Multi_options_g.protocol);
754 }
755
756 // blit some small color indicators to show whether ships.tbl and weapons.tbl are valid
757 // green == valid, red == invalid.
758 // ships.tbl will be on the left, weapons.tbl on the right
759 int Mh_ship_table_status[GR_NUM_RESOLUTIONS][2] = {
760         { 1, 479 },
761         { 1, 767 }
762 };
763 int Mh_weapon_table_status[GR_NUM_RESOLUTIONS][2] = {
764         { 3, 479 },
765         { 3, 767 }
766 };
767 void main_hall_blit_table_status()
768 {
769         // blit ship table status
770         gr_set_color_fast(Game_ships_tbl_valid ? &Color_bright_green : &Color_bright_red);
771         gr_line(Mh_ship_table_status[gr_screen.res][0], Mh_ship_table_status[gr_screen.res][1], Mh_ship_table_status[gr_screen.res][0], Mh_ship_table_status[gr_screen.res][1]);
772
773         // blit weapon table status
774         gr_set_color_fast(Game_weapons_tbl_valid ? &Color_bright_green : &Color_bright_red);
775         gr_line(Mh_weapon_table_status[gr_screen.res][0], Mh_weapon_table_status[gr_screen.res][1], Mh_weapon_table_status[gr_screen.res][0], Mh_ship_table_status[gr_screen.res][1]);
776 }
777
778 // bash the player to a specific mission in a campaign
779 void main_hall_campaign_cheat()
780 {
781         char *ret = popup_input(0, XSTR("Enter mission name.\n\n* This will destroy all legitimate progress in this campaign. *", -1));
782
783         // yay
784         if(ret != NULL) {
785                 // strcpy(Main_hall_campaign_cheat, ret);               
786                 mission_campaign_jump_to_mission(ret);
787         }
788 }
789
790 // -------------------------------------------------------------------------------------------------------------------
791 // FUNCTION DEFINITIONS BEGIN
792 //
793
794 // initialize the main hall proper 
795 void main_hall_init(int main_hall_num)
796 {
797         if ( Main_hall_inited ) {
798                 return;
799         }       
800
801         int idx,s_idx;
802         char temp[100], whee[100];      
803
804         // read in the main hall table
805         main_hall_read_table();
806
807         // create the snazzy interface and load up the info from the table
808         snazzy_menu_init();
809         read_menu_tbl(NOX("MAIN HALL"), temp, whee, Main_hall_region, &Main_hall_num_options, 0);
810
811         // assign the proper main hall data
812         Assert((main_hall_num >= 0) && (main_hall_num < NUM_MAIN_HALLS));
813         Main_hall = &Main_hall_defines[gr_screen.res][main_hall_num];   
814
815         // tooltip strings
816         Main_hall->region_descript[0] = XSTR( "Exit FreeSpace 2", 353);
817         Main_hall->region_descript[1] = XSTR( "Barracks - Manage your FreeSpace 2 pilots", 354);
818         Main_hall->region_descript[2] = XSTR( "Ready room - Start or continue a campaign", 355);
819         Main_hall->region_descript[3] = XSTR( "Tech room - View specifications of FreeSpace 2 ships and weaponry", 356);
820         Main_hall->region_descript[4] = XSTR( "Options - Change your FreeSpace 2 options", 357);
821         Main_hall->region_descript[5] = XSTR( "Campaign Room - View all available campaigns", 358);
822         Main_hall->region_descript[6] = XSTR( "Multiplayer - Start or join a multiplayer game", 359);
823         
824         // init tooltip shader
825         float gray_intensity = 0.02f;                                                                                                   // nearly black
826         float c = (gr_screen.mode == GR_DIRECT3D || gr_screen.mode == GR_OPENGL) ? 0.11f : 0.07f;                       // adjust for renderer differences
827         gr_create_shader(&Main_hall_tooltip_shader, gray_intensity, gray_intensity, gray_intensity, c);
828
829         // load the background bitmap
830         Main_hall_bitmap = bm_load(Main_hall->bitmap);
831         if(Main_hall_bitmap < 0){
832                 nprintf(("General","WARNING! Couldn't load main hall background bitmap %s\n", Main_hall->bitmap));
833         }       
834
835         // remove any multiplayer flags from the game mode
836         Game_mode &= ~(GM_MULTIPLAYER);
837
838         // set the interface palette 
839 #ifndef HARDWARE_ONLY
840         palette_use_bm_palette(Main_hall_bitmap);       
841 #endif
842
843         Main_hall_mask_w = -1;
844         Main_hall_mask_h = -1;
845                 
846         // load the mask
847         Main_hall_mask = bm_load(Main_hall->mask);
848         if (Main_hall_mask < 0) {
849                 Error(LOCATION,"Could not load in %s!", Main_hall->mask);
850         } else {
851                 // get a pointer to bitmap by using bm_lock(), so we can feed it to he snazzy menu system
852                 Main_hall_mask_bitmap = bm_lock(Main_hall_mask, 8, BMP_AABITMAP);
853                 Main_hall_mask_data = (ubyte*)Main_hall_mask_bitmap->data;
854                 bm_get_info(Main_hall_mask, &Main_hall_mask_w, &Main_hall_mask_h);
855         }
856
857         // load up the misc animations, and nullify all the delay timestamps for the misc animations    
858         for(idx=0;idx<Main_hall->num_misc_animations;idx++) {
859                 Main_hall_misc_anim[idx] = NULL;
860                 Main_hall_misc_anim[idx] = anim_load(Main_hall->misc_anim_name[idx]);
861                 if(Main_hall_misc_anim[idx] == NULL) {
862                         nprintf(("General","WARNING!, Could not load misc %s anim in main hall\n",Main_hall->misc_anim_name));
863                 }
864
865                 // null out the animation instances
866                 Main_hall_misc_anim_instance[idx] = NULL;
867                 
868                 // null out the delay timestamps
869                 Main_hall->misc_anim_delay[idx][0] = -1;
870         }       
871
872         // load up the door animations
873         for(idx=0;idx<Main_hall->num_door_animations;idx++) {
874                 Main_hall_door_anim[idx] = NULL;
875                 Main_hall_door_anim[idx] = anim_load(Main_hall->door_anim_name[idx]);
876                 if(Main_hall_door_anim[idx] == NULL){
877                         nprintf(("General","WARNING!, Could not load door anim %s in main hall\n",Main_hall->door_anim_name[idx]));
878                 }
879
880                 // null out the animation instances
881                 Main_hall_door_anim_instance[idx] = NULL;
882         }       
883
884         // load in help overlay bitmap          
885         if(Main_hall == &Main_hall_defines[gr_screen.res][0]) {
886                 Main_hall_overlay_id = MH_OVERLAY;
887         } else {
888                 Assert(Main_hall == &Main_hall_defines[gr_screen.res][1]);
889                 Main_hall_overlay_id = MH2_OVERLAY;
890         }
891         help_overlay_load(Main_hall_overlay_id);
892         help_overlay_set_state(Main_hall_overlay_id,0);         
893
894         // check to see if the "very first pilot" flag is set, and load the overlay if so
895         if (!F1_text_done) {
896                 if (Main_hall_f1_text_frame == 0) {
897                         Main_hall_help_stamp = timestamp(MAIN_HALL_HELP_TIME);
898                 } else {
899                         F1_text_done = 1;
900                 }
901         }
902
903 /*
904         if(Player_select_very_first_pilot) {                            
905                 Main_hall_help_stamp = timestamp(MAIN_HALL_HELP_TIME);
906                 
907                 // don't display the "press f1" message more than once
908                 Player_select_very_first_pilot = 0;
909         } else {
910                 Main_hall_help_stamp = -1;
911         }
912 */
913         Main_hall_region_linger_stamp = -1;
914
915         strcpy(Main_hall_campaign_cheat, "");
916
917         // zero out the door sounds
918         for(idx=0;idx<Main_hall->num_door_sounds;idx++){
919                 Main_hall_door_sound_handles[idx] = -1;
920         }
921
922         // zero out the misc anim sounds
923         for(idx=0;idx<Main_hall->num_misc_animations;idx++){
924                 for(s_idx = 1;s_idx < 10;s_idx++){
925                         Main_hall->misc_anim_sound_handles[idx][s_idx] = -1;
926                         Main_hall->misc_anim_sound_flag[idx][s_idx] = 0;
927                 }
928         }
929
930         // skip the first frame
931         Main_hall_frame_skip = 1;
932
933         // initialize the music
934         main_hall_start_music();
935
936         // initialize the main hall notify text
937         Main_hall_notify_stamp = 1;
938
939         // initialize the random intercom sound stuff
940         Main_hall_next_intercom_sound = 0;              
941         Main_hall_next_intercom_sound_stamp = -1;
942         Main_hall_intercom_sound_handle = -1;
943
944         // set the placement of the mouse cursor (start at the ready room)
945         Main_hall_mouse_region = -1;
946         Main_hall_last_clicked_region = READY_ROOM_REGION;      
947         mouse_set_pos(Main_hall->door_anim_coords[READY_ROOM_REGION][2],Main_hall->door_anim_coords[READY_ROOM_REGION][3]);     
948
949         Main_hall_inited = 1;
950
951         // determine if we have a right click
952         Main_hall_right_click = mouse_down(MOUSE_RIGHT_BUTTON);
953
954         // set the game_mode based on the type of player
955         Assert( Player != NULL );
956         if ( Player->flags & PLAYER_FLAGS_IS_MULTI ){
957                 Game_mode = GM_MULTIPLAYER;
958         } else {
959                 Game_mode = GM_NORMAL;
960         }
961
962         if ( (Cmdline_start_netgame || (Cmdline_connect_addr != NULL)) && !Main_hall_netgame_started ) {
963                 Main_hall_netgame_started = 1;
964                 main_hall_do_multi_ready();
965         }
966 }
967
968 void main_hall_exit_game()
969 {
970 #if defined(NDEBUG) || defined(INTERPLAYQA)
971         int choice;
972
973         // stop music first
974         main_hall_stop_music();
975         main_hall_stop_ambient();
976         choice = popup( PF_NO_NETWORKING | PF_BODY_BIG, 2, POPUP_NO, POPUP_YES, XSTR( "Exit Game?", 365));
977         if ( choice == 1 ) {
978                 gameseq_post_event(GS_EVENT_QUIT_GAME);
979         } else {
980                 main_hall_start_music();
981                 main_hall_start_ambient();
982         }
983 #else
984         gameseq_post_event(GS_EVENT_QUIT_GAME);
985 #endif
986 }
987
988
989 // do a frame for the main hall
990 void main_hall_do(float frametime)
991 {
992         int code, key, snazzy_action;   
993
994         // need to ensure ambient is playing, since it may be stopped by a playing movie
995         main_hall_start_ambient();
996
997         // handle any animation details 
998         main_hall_handle_misc_anims();
999         main_hall_handle_region_anims();
1000
1001         // handle any random intercom sound details
1002         main_hall_handle_random_intercom_sounds();
1003
1004         // handle any mouse clicks
1005         main_hall_handle_right_clicks();        
1006
1007         // handle any sound details
1008         main_hall_cull_door_sounds();   
1009
1010         // process any keypresses/mouse events
1011         snazzy_action = -1;
1012         code = snazzy_menu_do(Main_hall_mask_data, Main_hall_mask_w, Main_hall_mask_h, Main_hall_num_options, Main_hall_region, &snazzy_action, 1, &key);
1013
1014         if(key){
1015                 extern void game_process_cheats(int k);
1016                 game_process_cheats(key);
1017         }
1018         switch(key){
1019         case KEY_ENTER:
1020                 snazzy_action = SNAZZY_CLICKED; 
1021                 break;
1022         
1023 #ifndef NDEBUG  
1024         case KEY_1:             
1025                 // no soup for you!
1026                 // movie_play("endprt2b.mve", 0);
1027                 break;
1028         case KEY_2:             
1029                 // no soup for you!
1030                 // movie_play_two("endprt2a.mve", "endprt2b.mve", 0);
1031                 break;
1032         case KEY_3:             
1033                 main_hall_campaign_cheat();     
1034                 break;  
1035         case KEY_DEBUGGED + KEY_D:
1036                 demo_start_playback("test.fsd");
1037                 break;
1038         }
1039 #else 
1040         }
1041 #endif
1042
1043         // do any processing based upon what happened to the snazzy menu
1044         switch (snazzy_action) {
1045         case SNAZZY_OVER:
1046                 main_hall_handle_mouse_location(code);
1047                 break;
1048
1049         case SNAZZY_CLICKED:
1050                 switch (code) {
1051                 // clicked on the exit region
1052                 case EXIT_REGION:
1053                         gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1054                         main_hall_exit_game();
1055                         break;
1056
1057                 // clicked on the readyroom region
1058                 case READY_ROOM_REGION:
1059 #ifdef MULTIPLAYER_BETA_BUILD
1060                         gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1061                         Player->flags |= PLAYER_FLAGS_IS_MULTI;
1062                         main_hall_do_multi_ready();
1063 #elif defined(E3_BUILD) || defined(PRESS_TOUR_BUILD)                                                                    
1064                         gameseq_post_event(GS_EVENT_NEW_CAMPAIGN);                      
1065 #else
1066                         if (Player->flags & PLAYER_FLAGS_IS_MULTI){
1067                                 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1068                                 main_hall_do_multi_ready();
1069                         } else {                                
1070                                 if(strlen(Main_hall_campaign_cheat)){
1071                                         gameseq_post_event(GS_EVENT_CAMPAIGN_CHEAT);
1072                                 } else {
1073                                         gameseq_post_event(GS_EVENT_NEW_CAMPAIGN);                              
1074                                 }
1075                                 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);                              
1076                         }
1077 #endif
1078                         break;
1079
1080                 // clicked on the tech room region
1081                 case TECH_ROOM_REGION:
1082 #if defined(FS2_DEMO)
1083                         gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1084                         game_feature_not_in_demo_popup();
1085 #else
1086                         gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1087                         gameseq_post_event( GS_EVENT_TECH_MENU );
1088 #endif
1089                         break;
1090
1091                 // clicked on the options region
1092                 case OPTIONS_REGION:
1093                         gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1094                         gameseq_post_event(GS_EVENT_OPTIONS_MENU);
1095                         break;
1096
1097                 // clicked on the campaign toom region
1098                 case CAMPAIGN_ROOM_REGION:
1099 #if !defined(MULTIPLAYER_BETA_BUILD) && !defined(E3_BUILD) && !defined(PRESS_TOUR_BUILD)
1100
1101 #ifdef FS2_DEMO
1102                         gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1103                         {
1104                         //game_feature_not_in_demo_popup();
1105                         int reset_campaign = popup(PF_USE_AFFIRMATIVE_ICON|PF_BODY_BIG, 2, "Exit", "Restart Campaign", "Campaign Room only available in full version. However, you may restart the campaign.");
1106                         if (reset_campaign == 1) {
1107                                 mission_campaign_savefile_delete(Campaign.filename);
1108                                 mission_campaign_load(Campaign.filename);
1109                                 mission_campaign_next_mission();
1110                         }
1111                         }
1112
1113 #else
1114                         if(Player->flags & PLAYER_FLAGS_IS_MULTI){
1115                                 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1116                                 main_hall_set_notify_string(XSTR( "Campaign Room not valid for multiplayer pilots", 366));
1117                         } else {
1118                                 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1119                                 gameseq_post_event(GS_EVENT_CAMPAIGN_ROOM);                     
1120                         }
1121 #endif
1122
1123 #endif
1124                         break;
1125
1126                 // clicked on the multiplayer region
1127                 case MULTIPLAYER_REGION:
1128 #if defined(DEMO) || defined(OEM_BUILD) // not for FS2_DEMO
1129                         game_feature_not_in_demo_popup();
1130 #else
1131                         if (Player->flags & PLAYER_FLAGS_IS_MULTI){
1132                                 // NOTE : this isn't a great thing to be calling this anymore. But we'll leave it for now
1133                                 gameseq_post_event( GS_EVENT_MULTI_JOIN_GAME );
1134                         } else {
1135                                 main_hall_set_notify_string(XSTR( "Not a valid multiplayer pilot!!", 367));
1136                         }
1137 #endif
1138                         break;
1139
1140                 // load mission key was pressed
1141                 case LOAD_MISSION_REGION:
1142 #ifdef RELEASE_REAL
1143 #else
1144         #if !(defined(MULTIPLAYER_BETA_BUILD) || defined(FS2_DEMO))
1145         //#if !defined(NDEBUG) || defined(INTERPLAYQA)
1146                                 if (Player->flags & PLAYER_FLAGS_IS_MULTI){
1147                                         gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1148                                         main_hall_set_notify_string(XSTR( "Load Mission not valid for multiplayer pilots", 368));
1149                                 } else {
1150         #ifdef GAME_CD_CHECK
1151                                         // if ( !game_do_cd_check() ) {
1152                                                 // break;
1153                                         // }
1154         #endif
1155                                         gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1156                                         gameseq_post_event( GS_EVENT_LOAD_MISSION_MENU );
1157                                 }
1158         //#endif
1159         #endif
1160 #endif
1161                         break;
1162
1163                 // quick start a game region
1164                 case QUICK_START_REGION:
1165 #if !defined(NDEBUG) && !defined(FS2_DEMO)
1166                         if (Player->flags & PLAYER_FLAGS_IS_MULTI){
1167                                 main_hall_set_notify_string(XSTR( "Quick Start not valid for multiplayer pilots", 369));
1168                         } else {
1169
1170                                 if (Num_recent_missions > 0)    {
1171                                         strncpy( Game_current_mission_filename, Recent_missions[0], MAX_FILENAME_LEN );
1172                                 } else {
1173                                         mission_load_up_campaign();
1174                                         strncpy( Game_current_mission_filename, Campaign.missions[0].name, MAX_FILENAME_LEN );
1175                                 }
1176
1177                                 Campaign.current_mission = -1;
1178                                 gameseq_post_event(GS_EVENT_START_GAME_QUICK);
1179                         }
1180 #endif
1181                         break;
1182
1183                 // clicked on the barracks region
1184                 case BARRACKS_REGION:                   
1185                         gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1186                         gameseq_post_event( GS_EVENT_BARRACKS_MENU );
1187                         break;
1188
1189                 // increate the skill level
1190                 case SKILL_LEVEL_REGION: 
1191                         char temp[100];
1192
1193                         game_increase_skill_level();
1194                         sprintf(temp, XSTR( "Skill level set to %s.", 370), Skill_level_names(Game_skill_level));
1195                         main_hall_set_notify_string(temp);
1196                         break;                          
1197
1198                 // escape was pressed
1199                 case ESC_PRESSED:
1200                         // if there is a help overlay active, then don't quit the game - just kill the overlay
1201                         if(!help_overlay_active(Main_hall_overlay_id)){
1202                                 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1203                                 main_hall_exit_game();
1204                         }
1205                         // kill the overlay
1206                         else {
1207                                 help_overlay_set_state(Main_hall_overlay_id,0);
1208                         }
1209                         break;
1210                 }
1211
1212                 // if the escape key wasn't pressed handle any mouse position related events
1213                 if (code != ESC_PRESSED){
1214                         main_hall_handle_mouse_location(code);
1215                 }
1216                 break;
1217
1218                 default:
1219                         main_hall_handle_mouse_location(-1);
1220                         break;
1221         }
1222
1223         if ( mouse_down(MOUSE_LEFT_BUTTON) ) {
1224                 help_overlay_set_state(Main_hall_overlay_id, 0);
1225         }
1226
1227         // draw the background bitmap   
1228         gr_reset_clip();        
1229         GR_MAYBE_CLEAR_RES(Main_hall_bitmap);
1230         if(Main_hall_bitmap >= 0){
1231                 gr_set_bitmap(Main_hall_bitmap);
1232                 gr_bitmap(0, 0);
1233         }
1234
1235         // draw any pending notification messages
1236         main_hall_notify_do();                  
1237
1238         // render misc animations
1239         main_hall_render_misc_anims(frametime);
1240
1241         // render door animtions
1242         main_hall_render_door_anims(frametime); 
1243
1244         // blit any appropriate tooltips
1245         main_hall_maybe_blit_tooltips();
1246
1247         // fishtank
1248         fishtank_process();
1249
1250         // process any help "hit f1" timestamps and display any messages if necessary
1251         if (!F1_text_done) {
1252                 main_hall_process_help_stuff();
1253         }
1254
1255         // blit help overlay if active
1256         help_overlay_maybe_blit(Main_hall_overlay_id);
1257
1258         // blit the freespace version #
1259         main_hall_blit_version();
1260
1261         // blit ship and weapon table status
1262         main_hall_blit_table_status();
1263
1264         // if we're in nice D3D texture format
1265 #ifndef NDEBUG
1266         gr_set_color_fast(&Color_white);
1267
1268         // d3d
1269         if(gr_screen.mode == GR_DIRECT3D){
1270                 if(Bm_pixel_format == BM_PIXEL_FORMAT_ARGB_D3D){                
1271                         gr_string(320, gr_screen.max_h - 10, "D3D ARGB");
1272                 }
1273                 extern int D3d_rendition_uvs;
1274                 extern int D3D_32bit;
1275                 extern int D3D_fog_mode;        
1276                 extern int D3D_zbias;
1277                 if(D3d_rendition_uvs){
1278                         gr_string(320, gr_screen.max_h - 20, "D3D rendition");
1279                 }
1280                 if(D3D_32bit){
1281                         gr_string(320, gr_screen.max_h - 30, "D3D 32bit");
1282                 }
1283                 gr_printf(320, gr_screen.max_h - 40, "Fog : %d", D3D_fog_mode);
1284                 gr_printf(320, gr_screen.max_h - 50, "Zbias : %d", D3D_zbias);
1285                 // extern void d3d_test();
1286                 // d3d_test();
1287         } else if(gr_screen.mode == GR_GLIDE){
1288 #ifndef PLAT_UNIX
1289                 extern int Glide_voodoo3;
1290                 if(Glide_voodoo3){
1291                         gr_string(320, gr_screen.max_h - 20, "VOODOO 3");
1292                 }
1293 #endif
1294         }
1295 #endif  
1296
1297         gr_flip();
1298
1299         // maybe run the player tips popup
1300 // #if defined(FS2_DEMO) && defined(NDEBUG)
1301         player_tips_popup();
1302 // #endif
1303
1304         // if we were supposed to skip a frame, then stop doing it after 1 frame
1305         if(Main_hall_frame_skip){
1306                 Main_hall_frame_skip = 0;
1307         }
1308 }
1309
1310 // close the main hall proper
1311 void main_hall_close()
1312 {
1313         int idx,s_idx;
1314
1315         if(!Main_hall_inited){
1316                 return;
1317         }       
1318
1319         // unload the main hall bitmap
1320         if(Main_hall_bitmap != -1){
1321                 bm_unload(Main_hall_bitmap);
1322         }
1323
1324         // unload any bitmaps
1325         if(Main_hall_mask >= 0){                
1326                 // make sure we unlock the mask bitmap so it can be unloaded
1327                 bm_unlock(Main_hall_mask);
1328                 if(!bm_unload(Main_hall_mask)){
1329                         nprintf(("General","WARNING! Couldn't unload main hall mask bitmap!\n"));
1330                 }
1331         }
1332
1333         // free up any (possibly) playing misc animation handles
1334         for(idx=0;idx<Main_hall->num_misc_animations;idx++){
1335                 if(Main_hall_misc_anim_instance[idx]!=NULL){
1336                         anim_stop_playing(Main_hall_misc_anim_instance[idx]);
1337                         Main_hall_misc_anim_instance[idx] = NULL;
1338                 }
1339         }
1340         
1341         // free up any (possibly) playing door animation handles
1342         for(idx=0;idx<Main_hall->num_door_animations;idx++){
1343                 if(Main_hall_door_anim_instance[idx]!=NULL){
1344                         anim_stop_playing(Main_hall_door_anim_instance[idx]);
1345                         Main_hall_door_anim_instance[idx] = NULL;
1346                 }
1347         }
1348         
1349
1350         // free up any misc animations/instances        
1351         for(idx=0;idx<Main_hall->num_misc_animations;idx++){
1352                 if((Main_hall_misc_anim_instance[idx]!=NULL) && (anim_playing(Main_hall_misc_anim_instance[idx]))){             
1353                         Main_hall_misc_anim_instance[idx] = NULL;
1354                 }
1355                 if(Main_hall_misc_anim[idx]!=NULL){
1356                         if(anim_free(Main_hall_misc_anim[idx]) == -1){
1357                                 nprintf(("General","WARNING!, Could not free up misc anim %s in main hall\n",Main_hall->misc_anim_name[idx]));
1358                         }
1359                 }       
1360         }
1361
1362         // free up any door animations/instances
1363         for(idx=0;idx<Main_hall->num_door_animations;idx++){
1364                 if((Main_hall_door_anim_instance[idx]!=NULL) && (anim_playing(Main_hall_door_anim_instance[idx]))){
1365                         Main_hall_door_anim_instance[idx] = NULL;                       
1366                 }
1367                 if(Main_hall_door_anim[idx]!=NULL){
1368                         if(anim_free(Main_hall_door_anim[idx]) == -1){
1369                                 nprintf(("General","WARNING!, Could not free up door anim %s in main hall\n",Main_hall->door_anim_name[idx]));
1370                         }
1371                 }               
1372         }       
1373
1374         // stop any playing door sounds
1375         for(idx=0;idx<Main_hall->num_door_sounds-2;idx++){      // don't cut off the glow sounds (requested by Dan)
1376                 if((Main_hall_door_sound_handles[idx] != -1) && snd_is_playing(Main_hall_door_sound_handles[idx])){
1377                         snd_stop(Main_hall_door_sound_handles[idx]);
1378                         Main_hall_door_sound_handles[idx] = -1;
1379                 }
1380         }       
1381
1382         // stop any playing misc animation sounds
1383         for(idx=0;idx<Main_hall->num_misc_animations;idx++){
1384                 for(s_idx=1;s_idx<10;s_idx++){
1385                         if(snd_is_playing(Main_hall->misc_anim_sound_handles[idx][s_idx])){
1386                                 snd_stop(Main_hall->misc_anim_sound_handles[idx][s_idx]);
1387                                 Main_hall->misc_anim_sound_handles[idx][s_idx] = -1;
1388                         }
1389                 }
1390         }
1391
1392         // unload the overlay bitmap
1393         help_overlay_unload(Main_hall_overlay_id);
1394
1395         // close any snazzy menu details
1396         snazzy_menu_close();
1397
1398         // restore
1399         palette_restore_palette();
1400
1401         // no fish
1402         fishtank_stop();        
1403
1404         // not inited anymore
1405         Main_hall_inited = 0;
1406 }
1407
1408 // start the main hall music playing
1409 void main_hall_start_music()
1410 {
1411         // start a looping ambient sound
1412         main_hall_start_ambient();
1413
1414         // if we have selected no music, then don't do this
1415         if ( Cmdline_freespace_no_music ) {
1416                 return;
1417         }
1418
1419         int main_hall_spooled_music_index = event_music_get_spooled_music_index(Main_hall->music);
1420         
1421         if ((Main_hall_music_handle == -1) && (main_hall_spooled_music_index != -1)) {
1422                 char *music_wavfile_name = Spooled_music[main_hall_spooled_music_index].filename;
1423                 if (music_wavfile_name != NULL) {
1424                                 Main_hall_music_handle = audiostream_open( music_wavfile_name, ASF_EVENTMUSIC );
1425                                 if ( Main_hall_music_handle != -1 )
1426                                         audiostream_play(Main_hall_music_handle, Master_event_music_volume);
1427                 }
1428                 else {
1429                         nprintf(("Warning", "No music file exists to play music at the main menu!\n"));
1430                 }
1431         }
1432 }
1433
1434 // stop the main hall music
1435 void main_hall_stop_music()
1436 {
1437         if ( Main_hall_music_handle != -1 ) {
1438                 audiostream_close_file(Main_hall_music_handle);
1439                 Main_hall_music_handle = -1;
1440         }
1441 }
1442
1443 // do any necessary instantiation of misc animations
1444 void main_hall_handle_misc_anims()
1445 {
1446         int idx,s_idx;
1447
1448         if(Main_hall_frame_skip)
1449                 return;
1450         
1451         for(idx=0;idx<Main_hall->num_misc_animations;idx++){
1452                 // if the anim isn't playing
1453                 if(Main_hall_misc_anim_instance[idx] == NULL){
1454                         // if the timestamp is -1, then reset it to some random value (based on MIN and MAX) and continue
1455                         if(Main_hall->misc_anim_delay[idx][0] == -1){
1456                                 Main_hall->misc_anim_delay[idx][0] = timestamp(Main_hall->misc_anim_delay[idx][1] + 
1457                                                                                                                       (int)(((float)rand()/(float)RAND_MAX) * (float)(Main_hall->misc_anim_delay[idx][2] - Main_hall->misc_anim_delay[idx][1])));
1458
1459                         // if the timestamp is not -1 and has popped, play the anim and make the timestap -1
1460                         } else if (timestamp_elapsed(Main_hall->misc_anim_delay[idx][0]) && Main_hall_misc_anim[idx]) {
1461                                 anim_play_struct aps;
1462
1463                                 anim_play_init(&aps, Main_hall_misc_anim[idx], Main_hall->misc_anim_coords[idx][0], Main_hall->misc_anim_coords[idx][1]);
1464                                 aps.screen_id = GS_STATE_MAIN_MENU;
1465                                 aps.framerate_independent = 1;
1466                                 
1467                                 Main_hall_misc_anim_instance[idx] = anim_play(&aps);                            
1468                                 
1469                                 // kill the timestamp   
1470                                 Main_hall->misc_anim_delay[idx][0] = -1;                                
1471
1472                                 // reset the "should be playing" flags
1473                                 for(s_idx=1;s_idx<10;s_idx++){
1474                                         Main_hall->misc_anim_sound_flag[idx][s_idx] = 0;
1475                                 }
1476                         }
1477                 }               
1478                 // if the anim is playing
1479                 else {
1480                         // check to see if any special trigger points have been reached by the animation
1481                         // since the frame triggers must be in ascending order, we will count down so that we don't trigger too many sounds
1482                         for(s_idx=Main_hall->misc_anim_special_sounds[idx][0]; s_idx > 0; s_idx--){
1483                                 // if we've passed the trigger point, then play the sound and break out of the loop
1484                                 if((Main_hall_misc_anim_instance[idx]->frame_num >= Main_hall->misc_anim_special_trigger[idx][s_idx]) && !Main_hall->misc_anim_sound_flag[idx][s_idx]){                                 
1485                                         Main_hall->misc_anim_sound_flag[idx][s_idx] = 1;
1486
1487                                         // if the sound is already playing, then kill it. This is a pretty safe thing to do since we can assume that
1488                                         // by the time we get to this point again, the sound will have been long finished
1489                                         if(snd_is_playing(Main_hall->misc_anim_sound_handles[idx][s_idx])){
1490                                                 snd_stop(Main_hall->misc_anim_sound_handles[idx][s_idx]);
1491                                                 Main_hall->misc_anim_sound_handles[idx][s_idx] = -1;
1492                                         }
1493                                         // play the sound
1494                                         Main_hall->misc_anim_sound_handles[idx][s_idx] = snd_play(&Snds_iface[Main_hall->misc_anim_special_sounds[idx][s_idx]],Main_hall->misc_anim_sound_pan[idx]);                                    
1495                                         break;
1496                                 }
1497                         }
1498
1499                         // if the animation mode is MISC_ANIM_MODE_HOLD, pause it at the last frame
1500                         if((Main_hall->misc_anim_modes[idx] == MISC_ANIM_MODE_HOLD) && (Main_hall_misc_anim_instance[idx]->frame_num == Main_hall_misc_anim_instance[idx]->stop_at)){                           
1501                                 anim_pause(Main_hall_misc_anim_instance[idx]);
1502                                 Main_hall_misc_anim_instance[idx]->stop_now = FALSE;
1503                         }                       
1504
1505                         // if the animation mode is MISC_ANIM_MODE_LOOP, check to see if it should be looped
1506                         if((Main_hall->misc_anim_modes[idx] == MISC_ANIM_MODE_LOOP) && (Main_hall_misc_anim_instance[idx]->frame_num == Main_hall_misc_anim_instance[idx]->stop_at)){                           
1507                                 anim_release_render_instance(Main_hall_misc_anim_instance[idx]);
1508
1509                                 // start it playing again
1510                                 anim_play_struct aps;
1511
1512                                 anim_play_init(&aps, Main_hall_misc_anim[idx], Main_hall->misc_anim_coords[idx][0], Main_hall->misc_anim_coords[idx][1]);
1513                                 aps.screen_id = GS_STATE_MAIN_MENU;
1514                                 aps.framerate_independent = 1;
1515                                 
1516                                 Main_hall_misc_anim_instance[idx] = anim_play(&aps);                            
1517                                 
1518                                 // kill the timestamp   
1519                                 Main_hall->misc_anim_delay[idx][0] = -1;                                
1520
1521                                 // reset the "should be playing" flags
1522                                 for(s_idx=1;s_idx<10;s_idx++){
1523                                         Main_hall->misc_anim_sound_flag[idx][s_idx] = 0;
1524                                 }
1525                         }                       
1526
1527                         // cull any misc animations which are marked as done (!is_playing)                              
1528                         if(!anim_playing(Main_hall_misc_anim_instance[idx])){                   
1529                                 Main_hall_misc_anim_instance[idx] = NULL;                               
1530                         }
1531                 }                       
1532         }       
1533 }
1534
1535 // render all playing misc animations
1536 void main_hall_render_misc_anims(float frametime)
1537 {
1538         int idx;
1539         
1540         // HACKETY HACK HACK - always render misc anim 3 first, if it is playing
1541         if(Main_hall_misc_anim_instance[2] != NULL){
1542                 anim_render_one(GS_STATE_MAIN_MENU,Main_hall_misc_anim_instance[2],frametime);
1543         }
1544
1545         // render all other animations
1546         for(idx=0;idx<MAX_MISC_ANIMATIONS;idx++){
1547                 // skip anim 3, which was previously rendered, if at all
1548                 if(idx == 2){
1549                         continue;
1550                 }
1551
1552                 // render it
1553                 if(Main_hall_misc_anim_instance[idx] != NULL){
1554                         anim_render_one(GS_STATE_MAIN_MENU,Main_hall_misc_anim_instance[idx],frametime);
1555                 }
1556         }
1557 }
1558
1559 // render all playing door animations
1560 void main_hall_render_door_anims(float frametime)
1561 {
1562         int idx;        
1563
1564         // render all door animations
1565         for(idx=0;idx<MAX_DOOR_ANIMATIONS;idx++){               
1566                 // render it
1567                 if(Main_hall_door_anim_instance[idx] != NULL){
1568                         anim_render_one(GS_STATE_MAIN_MENU,Main_hall_door_anim_instance[idx],frametime);
1569                 }
1570         }
1571 }
1572
1573 // handle starting, stopping and reversing "door" animations
1574 void main_hall_handle_region_anims()
1575 {
1576         int idx;
1577
1578         if(Main_hall_frame_skip)
1579                 return;
1580         
1581         // make sure we make any finished door animations NULL
1582         for(idx=0;idx<Main_hall->num_door_animations;idx++){
1583                 if((Main_hall_door_anim_instance[idx] != NULL) && !anim_playing(Main_hall_door_anim_instance[idx])){
1584                         Main_hall_door_anim_instance[idx] = NULL;
1585                 }
1586         }
1587         
1588         // go through each region animation
1589         for(idx=0;idx<Main_hall->num_door_animations;idx++){
1590                 // if the instance is not null and the animation is playing
1591                 if((Main_hall_door_anim_instance[idx] != NULL) && anim_playing(Main_hall_door_anim_instance[idx])){
1592                         // check to see if we should hold a given door "open"
1593                         if((Main_hall_mouse_region == idx) && (Main_hall_door_anim_instance[idx]->frame_num == Main_hall_door_anim_instance[idx]->stop_at)){
1594                                 anim_pause(Main_hall_door_anim_instance[idx]);
1595                                 Main_hall_door_anim_instance[idx]->stop_now = FALSE;
1596                         }
1597                         // check to see if we should close a door being held open
1598                         if((Main_hall_mouse_region != idx) && (Main_hall_door_anim_instance[idx]->paused)){
1599                                 anim_unpause(Main_hall_door_anim_instance[idx]);
1600                         }
1601                 }               
1602         }       
1603 }
1604
1605 // do any necessary processing based upon the mouse location
1606 void main_hall_handle_mouse_location(int cur_region)
1607 {
1608    if(Main_hall_frame_skip)
1609                 return;
1610
1611         if(cur_region > NUM_MAIN_HALL_MOUSE_REGIONS) {
1612                 // MWA -- inserted return since Int3() was tripped when hitting L from main
1613                 // menu.
1614                 return;         
1615         }
1616
1617         // if the mouse is now over a resgion
1618         if (cur_region != -1) {
1619                 // if we're still over the same region we were last frame, check stuff
1620                 if (cur_region == Main_hall_mouse_region) {
1621                         // if we have a linger timestamp set and it has expired, then get moving                        
1622                         if ((Main_hall_region_linger_stamp != -1) && timestamp_elapsed(Main_hall_region_linger_stamp)) {
1623                                 main_hall_mouse_grab_region(cur_region);                                
1624
1625                                 // release the region linger stamp
1626                                 Main_hall_region_linger_stamp = -1;
1627                         }
1628                 } else {
1629                         // if we're currently on another region, release it
1630                         if ((Main_hall_mouse_region != -1) && (cur_region != Main_hall_mouse_region)) {
1631                                 main_hall_mouse_release_region(Main_hall_mouse_region);
1632                         }
1633                 
1634                         // set the linger time
1635                         if (Main_hall_region_linger_stamp == -1) {
1636                                 Main_hall_mouse_region = cur_region;
1637                                 Main_hall_region_linger_stamp = timestamp(MAIN_HALL_REGION_LINGER);
1638                         }                       
1639                 }
1640         }
1641         // if it was over a region but isn't anymore, release that region
1642         else {
1643                 if (Main_hall_mouse_region != -1) {
1644                         main_hall_mouse_release_region(Main_hall_mouse_region);
1645                         Main_hall_mouse_region = -1;
1646
1647                         // release the region linger timestamp
1648                         Main_hall_region_linger_stamp = -1;
1649                 }
1650         }
1651 }
1652
1653 // if the mouse has moved off of the currently active region, handle the anim accordingly
1654 void main_hall_mouse_release_region(int region)
1655 {
1656         if(Main_hall_frame_skip){
1657                 return;
1658         }
1659
1660         // if the animation is currently playing in the forward direction, change direction and be done, otherwise don't do a thing
1661         if ( (Main_hall_door_anim_instance[region] != NULL) && anim_playing(Main_hall_door_anim_instance[region]) && (Main_hall_door_anim_instance[region]->direction == ANIM_DIRECT_FORWARD)){
1662                 anim_reverse_direction(Main_hall_door_anim_instance[region]);
1663         }
1664
1665         // check for door sounds, ignoring the OPTIONS_REGION (which isn't a door)
1666         if ((Main_hall_door_anim_instance[region] != NULL)) {
1667                 // don't stop the toaster oven or microwave regions from playing all the way through
1668                 if (Main_hall_door_sound_handles[region] != -1) {
1669                         snd_stop(Main_hall_door_sound_handles[region]);
1670                 }
1671                 Main_hall_door_sound_handles[region] = snd_play(&Snds_iface[Main_hall->door_sounds[region][1]], Main_hall->door_sound_pan[region]);
1672
1673                 // make sure to set the sound to play from the right spot
1674                 snd_set_pos(Main_hall_door_sound_handles[region], &Snds_iface[SND_MAIN_HALL_DOOR_CLOSE],
1675                                                 (float)(Main_hall_door_anim_instance[region]->start_at - Main_hall_door_anim_instance[region]->frame_num) / (float)Main_hall_door_anim_instance[region]->parent->total_frames, 1);                      
1676         }
1677 }
1678
1679 // if the mouse has moved on this region, handle it accordingly
1680 void main_hall_mouse_grab_region(int region)
1681 {
1682         if (Main_hall_frame_skip) {
1683                 return;
1684         }
1685
1686         // if the animation is not playing, start it playing
1687         if ( !Main_hall_door_anim_instance[region] ) {
1688                 if ( Main_hall_door_anim[region] ) {
1689                         anim_play_struct aps;
1690
1691                         anim_play_init(&aps, Main_hall_door_anim[region], Main_hall->door_anim_coords[region][0], Main_hall->door_anim_coords[region][1]);
1692                         aps.screen_id = GS_STATE_MAIN_MENU;
1693                         aps.framerate_independent = 1;
1694
1695                         Main_hall_door_anim_instance[region] = anim_play(&aps);
1696                 }
1697         } 
1698         // otherwise if its playing in the reverse direction, change it to the forward direction
1699         else if (Main_hall_door_anim_instance[region]->direction == ANIM_DIRECT_REVERSE) {
1700                 anim_reverse_direction(Main_hall_door_anim_instance[region]);
1701         }
1702
1703         // check for opening/starting sounds
1704         // kill the currently playing sounds if necessary
1705         if(Main_hall_door_sound_handles[region] != -1){                 
1706                 snd_stop(Main_hall_door_sound_handles[region]);
1707         }       
1708         Main_hall_door_sound_handles[region] = snd_play(&Snds_iface[Main_hall->door_sounds[region][0]],Main_hall->door_sound_pan[region]);                              
1709
1710         // start the sound playing at the right spot relative to the completion of the animation                
1711         if(Main_hall_door_anim_instance[region]->frame_num != -1){                      
1712                         snd_set_pos(Main_hall_door_sound_handles[region],&Snds_iface[SND_MAIN_HALL_DOOR_OPEN],
1713                                                         (float)Main_hall_door_anim_instance[region]->frame_num / (float)Main_hall_door_anim_instance[region]->parent->total_frames,1);
1714         }                               
1715 }
1716
1717 // handle any right clicks which may have occured
1718 void main_hall_handle_right_clicks()
1719 {
1720         int new_region;
1721
1722         if(Main_hall_frame_skip)
1723                 return;
1724
1725         // check to see if the button has been clicked
1726         if(!Main_hall_right_click){
1727                 if(mouse_down(MOUSE_RIGHT_BUTTON)){
1728                         // cycle through the available regions
1729                         if(Main_hall_last_clicked_region == NUM_MAIN_HALL_MOUSE_REGIONS - 1){
1730                                 new_region = 0;
1731                         } else
1732                                 new_region = Main_hall_last_clicked_region + 1;
1733
1734                         // set the position of the mouse cursor and the newly clicked region                    
1735                         mouse_set_pos(Main_hall->door_anim_coords[new_region][2],Main_hall->door_anim_coords[new_region][3]);                   
1736
1737                         main_hall_handle_mouse_location(new_region);
1738                         Main_hall_last_clicked_region = new_region;
1739                         
1740                         // set the mouse as being clicked
1741                         Main_hall_right_click = 1;
1742                 }
1743         } 
1744         // set the mouse as being unclicked
1745         else if(Main_hall_right_click && !(mouse_down(MOUSE_RIGHT_BUTTON))){
1746                 Main_hall_right_click = 0;
1747         }
1748 }
1749
1750 // cull any door sounds that have finished playing
1751 void main_hall_cull_door_sounds()
1752 {
1753         int idx;
1754         // basically just set the handle of any finished sound to be -1, so that we know its free any where else in the code we may need it
1755         for(idx=0;idx<Main_hall->num_door_sounds;idx++){
1756                 if((Main_hall_door_sound_handles[idx] != -1) && !snd_is_playing(Main_hall_door_sound_handles[idx])){                    
1757                         Main_hall_door_sound_handles[idx] = -1;
1758                 }
1759         }
1760 }
1761
1762 void main_hall_handle_random_intercom_sounds()
1763 {
1764         // if we have no timestamp for the next random sound, then set on
1765         if((Main_hall_next_intercom_sound_stamp == -1) && (Main_hall_intercom_sound_handle == -1)){
1766                 Main_hall_next_intercom_sound_stamp = timestamp((int)(((float)rand()/(float)RAND_MAX) * 
1767                                                                     (float)(Main_hall->intercom_delay[Main_hall_next_intercom_sound][1]
1768                                                                                                                                           - Main_hall->intercom_delay[Main_hall_intercom_sound_handle][0])) );          
1769         }
1770
1771         // if the there is no sound playing
1772         if(Main_hall_intercom_sound_handle == -1){
1773                 // if the timestamp has popped, play a sound
1774                 if((Main_hall_next_intercom_sound_stamp != -1) && (timestamp_elapsed(Main_hall_next_intercom_sound_stamp))){
1775                         // play the sound
1776                         Main_hall_intercom_sound_handle = snd_play(&Snds_iface[Main_hall->intercom_sounds[Main_hall_next_intercom_sound]]);                     
1777                         
1778                         // unset the timestamp
1779                         Main_hall_next_intercom_sound_stamp = -1;
1780                 }
1781         }
1782         // if the sound is playing
1783         else {
1784                 // if the sound has finished, set the timestamp and continue
1785                 if(!snd_is_playing(Main_hall_intercom_sound_handle)){
1786                         // increment the next sound
1787                         if(Main_hall_next_intercom_sound >= (Main_hall->num_random_intercom_sounds-1)){
1788                                 Main_hall_next_intercom_sound = 0;
1789                         } else {
1790                                 Main_hall_next_intercom_sound++;
1791                         }
1792
1793                         // set the timestamp
1794                         Main_hall_next_intercom_sound_stamp = timestamp((int)(((float)rand()/(float)RAND_MAX) * 
1795                                                                     (float)(Main_hall->intercom_delay[Main_hall_next_intercom_sound][1]
1796                                                                                                                                           - Main_hall->intercom_delay[Main_hall_next_intercom_sound][0])) );
1797
1798                         // release the sound handle
1799                         Main_hall_intercom_sound_handle = -1;
1800                 }
1801         }
1802 }
1803
1804 // set the notification string with its decay timeout
1805 void main_hall_set_notify_string(char *str)
1806 {
1807         strcpy(Main_hall_notify_text,str);
1808         Main_hall_notify_stamp = timestamp(MAIN_HALL_NOTIFY_TIME);
1809 }
1810
1811 void main_hall_notify_do()
1812 {
1813         // check to see if we should try and do something
1814         if(Main_hall_notify_stamp != -1){
1815            // if the text time has expired
1816                 if(timestamp_elapsed(Main_hall_notify_stamp)){
1817                         strcpy(Main_hall_notify_text,"");
1818                         Main_hall_notify_stamp = -1;
1819                 } else {
1820                         int w,h;
1821                         gr_set_color_fast(&Color_bright);
1822
1823                         gr_get_string_size(&w,&h,Main_hall_notify_text);
1824                         gr_printf((gr_screen.max_w - w)/2, gr_screen.max_h - 40, Main_hall_notify_text);
1825                 }
1826         }
1827 }
1828
1829 // start a looping ambient sound for main hall
1830 void main_hall_start_ambient()
1831 {
1832         int play_ambient_loop = 0;
1833
1834         if ( Main_hall_ambient_loop == -1 ) {
1835                 play_ambient_loop = 1;
1836         } else {
1837                 if ( !snd_is_playing(Main_hall_ambient_loop) ) {
1838                         play_ambient_loop = 1;
1839                 }
1840         }
1841
1842         if ( play_ambient_loop ) {
1843                 Main_hall_ambient_loop = snd_play_looping(&Snds_iface[SND_MAIN_HALL_AMBIENT]);
1844         }
1845 }
1846
1847 // stop a looping ambient sound for the main hall
1848 void main_hall_stop_ambient()
1849 {
1850         if ( Main_hall_ambient_loop != -1 ) {
1851                 snd_stop(Main_hall_ambient_loop);
1852                 Main_hall_ambient_loop = -1;
1853         }
1854 }
1855
1856 // Reset the volume of the looping ambient sound.  This is called from the options 
1857 // screen when the looping ambient sound might be playing.
1858 void main_hall_reset_ambient_vol()
1859 {
1860         if ( Main_hall_ambient_loop >= 0 ) {
1861                 snd_set_volume(Main_hall_ambient_loop, Snds_iface[SND_MAIN_HALL_AMBIENT].default_volume);
1862         }
1863 }
1864
1865 // blit the freespace version #
1866 void main_hall_blit_version()
1867 {
1868         char version_string[100];
1869         int w;
1870
1871         // format the version string
1872         get_version_string(version_string);
1873
1874         // get the length of the string
1875         gr_get_string_size(&w,NULL,version_string);
1876
1877         // print the string out in the lower right corner
1878         gr_set_color_fast(&Color_white);
1879         gr_string(gr_screen.max_w - 55, gr_screen.max_h - 12, version_string);
1880 }
1881
1882 // blit any necessary tooltips
1883 void main_hall_maybe_blit_tooltips()
1884 {
1885         int w;
1886         int text_index;
1887
1888         // if we're over no region - don't blit anything
1889         if(Main_hall_mouse_region < 0) {
1890                 return;
1891         }
1892
1893         // get the index of the proper text to be using
1894         if(Main_hall_mouse_region == READY_ROOM_REGION) {
1895                 // if this is a multiplayer pilot, the ready room region becomes the multiplayer region
1896                 if(Player->flags & PLAYER_FLAGS_IS_MULTI){
1897                         text_index = NUM_REGIONS - 1;
1898                 } else {
1899                         text_index = READY_ROOM_REGION;
1900                 }
1901         } else {
1902                 text_index = Main_hall_mouse_region;
1903         }
1904
1905         // set the color and blit the string
1906         if(!help_overlay_active(Main_hall_overlay_id)) {
1907                 int shader_y = (Main_hall->region_yval) - Main_hall_tooltip_padding[gr_screen.res];     // subtract more to pull higher
1908                 // get the width of the string
1909                 gr_get_string_size(&w, NULL, Main_hall->region_descript[text_index]);
1910
1911                 gr_set_shader(&Main_hall_tooltip_shader);
1912                 gr_shade(0, shader_y, gr_screen.clip_width, (gr_screen.clip_height - shader_y));
1913
1914                 gr_set_color_fast(&Color_bright_white);
1915                 gr_string((gr_screen.max_w - w)/2, Main_hall->region_yval, Main_hall->region_descript[text_index]);
1916         }
1917 }
1918
1919
1920 void main_hall_process_help_stuff()
1921 {
1922         int w, h;
1923         char str[255];
1924         
1925         // if the timestamp has popped, don't do anything
1926         if(Main_hall_help_stamp == -1) {
1927                 return;
1928         }
1929
1930         // if the timestamp has popped, advance frame
1931         if(timestamp_elapsed(Main_hall_help_stamp)) {
1932                 Main_hall_f1_text_frame++;
1933         }
1934
1935         // otherwise print out the message
1936         strcpy(str, XSTR( "Press F1 for help", 371));
1937         gr_get_string_size(&w, &h, str);
1938
1939         int y_anim_offset = Main_hall_f1_text_frame;
1940
1941         // if anim is off the screen finally, stop altogether
1942         if ( (y_anim_offset >= (2*Main_hall_tooltip_padding[gr_screen.res]) + h) || (help_overlay_active(Main_hall_overlay_id)) ) {
1943                 Main_hall_f1_text_frame = -1;
1944                 Main_hall_help_stamp = -1;
1945                 F1_text_done = 1;
1946                 return;
1947         }
1948
1949         // set the color and print out text and shader
1950         gr_set_color_fast(&Color_bright_white);
1951         gr_shade(0, 0, gr_screen.max_w, (2*Main_hall_tooltip_padding[gr_screen.res]) + h - y_anim_offset);
1952         gr_string((gr_screen.max_w - w)/2, Main_hall_tooltip_padding[gr_screen.res] - y_anim_offset, str);
1953 }
1954
1955 // what main hall we're on (should be 0 or 1)
1956 int main_hall_id()
1957 {       
1958         // only 1 of 2 main halls
1959         if(Main_hall == &Main_hall_defines[gr_screen.res][0]){
1960                 return 0;
1961         }
1962
1963         return 1;
1964
1965
1966 // read in main hall table
1967 void main_hall_read_table()
1968 {
1969         main_hall_defines *m, temp;
1970         int count, idx, s_idx, m_idx;
1971
1972         // read the file in
1973         read_file_text("mainhall.tbl");
1974         reset_parse();
1975
1976         // go for it
1977         count = 0;
1978         while(!optional_string("#end")){
1979
1980                 // read in 2 resolutions
1981                 for(m_idx=0; m_idx<GR_NUM_RESOLUTIONS; m_idx++){
1982                         // maybe use a temp main hall stuct
1983                         if(count >= NUM_MAIN_HALLS){
1984                                 m = &temp;
1985                         } else {
1986                                 m = &Main_hall_defines[m_idx][count];
1987                         }
1988
1989                         // ready
1990                         required_string("$Main Hall");
1991
1992                         // bitmap and mask
1993                         required_string("+Bitmap:");
1994                         stuff_string(m->bitmap, F_NAME, NULL, MAX_FILENAME_LEN);
1995                         required_string("+Mask:");
1996                         stuff_string(m->mask, F_NAME, NULL, MAX_FILENAME_LEN);
1997 #ifndef FS2_DEMO
1998                         required_string("+Music:");
1999                         stuff_string(m->music, F_NAME, NULL, MAX_FILENAME_LEN);
2000 #endif
2001
2002                         // intercom sounds
2003                         required_string("+Num Intercom Sounds:");
2004                         stuff_int(&m->num_random_intercom_sounds);              
2005                         for(idx=0; idx<m->num_random_intercom_sounds; idx++){                   
2006                                 // intercom delay
2007                                 required_string("+Intercom delay:");
2008                                 stuff_int(&m->intercom_delay[idx][0]);
2009                                 stuff_int(&m->intercom_delay[idx][1]);
2010                         }
2011                         for(idx=0; idx<m->num_random_intercom_sounds; idx++){                   
2012                                 // intercom sound id
2013                                 required_string("+Intercom sound:");
2014                                 stuff_int(&m->intercom_sounds[idx]);                    
2015                         }                       
2016                         for(idx=0; idx<m->num_random_intercom_sounds; idx++){                   
2017                                 // intercom pan
2018                                 required_string("+Intercom pan:");
2019                                 stuff_float(&m->intercom_sound_pan[idx]);                       
2020                         }                       
2021
2022                         // misc animations
2023                         required_string("+Num Misc Animations:");
2024                         stuff_int(&m->num_misc_animations);
2025                         for(idx=0; idx<m->num_misc_animations; idx++){
2026                                 // anim names
2027                                 required_string("+Misc anim:");
2028                                 stuff_string(m->misc_anim_name[idx], F_NAME, NULL);
2029                         }
2030                         for(idx=0; idx<m->num_misc_animations; idx++){
2031                                 // anim delay
2032                                 required_string("+Misc anim delay:");
2033                                 stuff_int(&m->misc_anim_delay[idx][0]);
2034                                 stuff_int(&m->misc_anim_delay[idx][1]);
2035                                 stuff_int(&m->misc_anim_delay[idx][2]);
2036                         }
2037                         for(idx=0; idx<m->num_misc_animations; idx++){
2038                                 // anim coords
2039                                 required_string("+Misc anim coords:");
2040                                 stuff_int(&m->misc_anim_coords[idx][0]);
2041                                 stuff_int(&m->misc_anim_coords[idx][1]);
2042                         }
2043                         for(idx=0; idx<m->num_misc_animations; idx++){
2044                                 // anim mode
2045                                 required_string("+Misc anim mode:");
2046                                 stuff_int(&m->misc_anim_modes[idx]);                    
2047                         }
2048                         for(idx=0; idx<m->num_misc_animations; idx++){
2049                                 // anim pan
2050                                 required_string("+Misc anim pan:");
2051                                 stuff_float(&m->misc_anim_sound_pan[idx]);
2052                         }
2053                         for(idx=0; idx<m->num_misc_animations; idx++){
2054                                 // anim sound id
2055                                 required_string("+Misc anim sounds:");
2056                                 stuff_int(&m->misc_anim_special_sounds[idx][0]);
2057                                 for(s_idx=0; s_idx<m->misc_anim_special_sounds[idx][0]; s_idx++){
2058                                         stuff_int(&m->misc_anim_special_sounds[idx][s_idx + 1]);
2059                                 }
2060                         }
2061                         for(idx=0; idx<m->num_misc_animations; idx++){
2062                                 // anim sound triggers
2063                                 required_string("+Misc anim trigger:");
2064                                 stuff_int(&m->misc_anim_special_trigger[idx][0]);
2065                                 for(s_idx=0; s_idx<m->misc_anim_special_trigger[idx][0]; s_idx++){
2066                                         stuff_int(&m->misc_anim_special_trigger[idx][s_idx + 1]);
2067                                 }
2068                         }
2069                         for(idx=0; idx<m->num_misc_animations; idx++){
2070                                 // anim sound handles
2071                                 required_string("+Misc anim handles:");
2072                                 stuff_int(&m->misc_anim_sound_handles[idx][0]);                 
2073                         }
2074                         for(idx=0; idx<m->num_misc_animations; idx++){
2075                                 // anim sound flags
2076                                 required_string("+Misc anim flags:");
2077                                 stuff_int(&m->misc_anim_sound_flag[idx][0]);                    
2078                         }
2079
2080                         // door animations
2081                         required_string("+Num Door Animations:");
2082                         stuff_int(&m->num_door_animations);
2083                         for(idx=0; idx<m->num_door_animations; idx++){
2084                                 // door name
2085                                 required_string("+Door anim:");
2086                                 stuff_string(m->door_anim_name[idx], F_NAME, NULL);
2087                         }
2088                         for(idx=0; idx<m->num_door_animations; idx++){
2089                                 // door coords
2090                                 required_string("+Door coords:");
2091                                 stuff_int(&m->door_anim_coords[idx][0]);
2092                                 stuff_int(&m->door_anim_coords[idx][1]);
2093                                 stuff_int(&m->door_anim_coords[idx][2]);
2094                                 stuff_int(&m->door_anim_coords[idx][3]);
2095                         }
2096                         for(idx=0; idx<m->num_door_animations; idx++){
2097                                 // door open and close sounds
2098                                 required_string("+Door sounds:");
2099                                 stuff_int(&m->door_sounds[idx][0]);
2100                                 stuff_int(&m->door_sounds[idx][1]);                     
2101                         }
2102                         for(idx=0; idx<m->num_door_animations; idx++){
2103                                 // door pan value
2104                                 required_string("+Door pan:");
2105                                 stuff_float(&m->door_sound_pan[idx]);                   
2106                         }
2107
2108                         // tooltip y location
2109                         required_string("+Tooltip Y:");
2110                         stuff_int(&m->region_yval);
2111                         for(idx=0; idx<NUM_REGIONS; idx++){
2112                                 m->region_descript[idx] = NULL;
2113                         }
2114                 }
2115
2116                 if(count < NUM_MAIN_HALLS){
2117                         count++;
2118                 }
2119         }
2120
2121         // are we funny?
2122         if(Vasudan_funny){
2123                 Main_hall_defines[GR_640][1].door_sounds[OPTIONS_REGION][0] = SND_VASUDAN_BUP;
2124                 Main_hall_defines[GR_640][1].door_sounds[OPTIONS_REGION][1] = SND_VASUDAN_BUP;
2125                 Main_hall_defines[GR_1024][1].door_sounds[OPTIONS_REGION][0] = SND_VASUDAN_BUP;
2126                 Main_hall_defines[GR_1024][1].door_sounds[OPTIONS_REGION][1] = SND_VASUDAN_BUP;
2127
2128                 // set head anim. hehe
2129                 strcpy(Main_hall_defines[GR_640][1].door_anim_name[OPTIONS_REGION], "vhallheads");
2130                 strcpy(Main_hall_defines[GR_1024][1].door_anim_name[OPTIONS_REGION], "2_vhallheads");
2131
2132                 // set the background
2133                 strcpy(Main_hall_defines[GR_640][1].bitmap, "vhallhead");
2134                 strcpy(Main_hall_defines[GR_1024][1].bitmap, "2_vhallhead");            
2135         }
2136 }
2137
2138 // make the vasudan main hall funny
2139 void main_hall_vasudan_funny()
2140 {
2141         Vasudan_funny = 1;
2142 }
2143
2144
2145 /*
2146 #include "3d.h"
2147 int argh = -1;
2148 matrix view = {
2149         0.0f, 0.0f, 0.0f,
2150         0.0f, 0.0f, 0.0f,
2151         0.0f, 0.0f, 1.0f
2152 };
2153 */
2154 void d3d_test()
2155 {
2156         /*      
2157         vertex p1;
2158         vector sun_pos = vmd_zero_vector;
2159         sun_pos.z = 1.0f;
2160
2161         if(argh == -1){
2162                 argh = bm_load("sun01");
2163                 bm_lock(argh, 16, BMP_TEX_XPARENT);
2164                 bm_unlock(argh);
2165         }
2166         
2167         g3_start_frame(1);
2168         g3_set_view_matrix(&vmd_zero_vector, &view, 0.5f);      
2169         g3_rotate_vertex(&p1, &sun_pos);
2170         g3_project_vertex(&p1);
2171         gr_zbuffer_set(GR_ZBUFF_NONE);
2172         gr_set_bitmap( argh );
2173         g3_draw_bitmap(&p1, 0, 0.05f, TMAP_FLAG_TEXTURED | TMAP_FLAG_XPARENT);          
2174         g3_end_frame();
2175         */
2176 }
2177