2 * Copyright (C) Volition, Inc. 1999. All rights reserved.
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
10 * $Logfile: /Freespace2/code/MenuUI/MainHallMenu.cpp $
15 * Header file for main-hall menu code
18 * Revision 1.6 2002/07/24 00:20:42 relnev
21 * Revision 1.5 2002/06/09 04:41:22 relnev
22 * added copyright header
24 * Revision 1.4 2002/06/01 03:32:00 relnev
25 * fix texture loading mistake.
27 * enable some d3d stuff for opengl also
29 * Revision 1.3 2002/05/30 16:55:44 theoddone33
30 * now gets to another screen
32 * Revision 1.2 2002/05/27 22:43:02 theoddone33
33 * Fix more glide symbols
35 * Revision 1.1.1.1 2002/05/03 03:28:09 root
39 * 62 10/28/99 2:04a Jefff
42 * 61 9/15/99 6:28p Dave
43 * No load mission button in RELEASE_REAL
45 * 60 9/13/99 4:52p Dave
48 * 59 9/13/99 11:30a Dave
49 * Added checkboxes and functionality for disabling PXO banners as well as
50 * disabling d3d zbuffer biasing.
52 * 58 9/07/99 6:55p Jefff
53 * added jump-to-campaign-mission cheat
55 * 57 9/07/99 4:01p Dave
56 * Fixed up a string.tbl paroblem (self destruct message). Make sure IPX
57 * does everything properly (setting up address when binding). Remove
58 * black rectangle background from UI_INPUTBOX.
60 * 56 9/06/99 6:38p Dave
61 * Improved CD detection code.
63 * 55 9/06/99 1:30a Dave
64 * Intermediate checkin. Started on enforcing CD-in-drive to play the
67 * 54 9/03/99 1:31a Dave
68 * CD checking by act. Added support to play 2 cutscenes in a row
69 * seamlessly. Fixed super low level cfile bug related to files in the
70 * root directory of a CD. Added cheat code to set campaign mission # in
73 * 53 9/01/99 11:02p Dave
74 * Made head guy look right when not animating.
76 * 52 8/27/99 12:04a Dave
77 * Campaign loop screen.
79 * 51 8/26/99 9:45a Dave
80 * First pass at easter eggs and cheats.
82 * 50 8/25/99 11:57a Jefff
83 * freespace -> freespace 2 in tooltip strings
85 * 49 8/25/99 10:50a Dave
86 * Added music to the mainhall.tbl
88 * 48 8/24/99 8:55p Dave
89 * Make sure nondimming pixels work properly in tech menu.
91 * 47 8/18/99 11:44a Jefff
94 * 46 8/10/99 4:45p Jefff
97 * 45 8/06/99 1:01p Andsager
98 * disable quick start (g) for demo
100 * 44 8/05/99 10:34a Jefff
101 * more mouseover sound fixes
103 * 43 8/04/99 9:12p Andsager
104 * Add campaign room popup allowing restart of campaign in demo.
106 * 42 8/04/99 5:36p Dave
107 * Make glide and D3D switch out properly.
109 * 41 8/04/99 4:35p Jefff
110 * fixed tech room & options sounds playing only once
112 * 40 8/03/99 5:41p Jefff
113 * made "f1 for help" draw after animations, and stop if help overlay
116 * 39 8/03/99 4:42p Jefff
119 * 38 8/03/99 3:48p Jefff
121 * 37 8/02/99 9:13p Dave
124 * 36 8/02/99 2:26p Jefff
125 * "press f1.." text reworked
127 * 35 8/02/99 12:19p Andsager
128 * disable "L" load screen
130 * 34 8/02/99 11:12a Jefff
131 * adjusted tooltip shader stuff for more a more pleasing effect.
133 * 33 7/30/99 6:05p Jefff
134 * added shader behind tooltip text
136 * 32 7/30/99 4:20p Andsager
137 * Added user click sounds to main hall
139 * 31 7/29/99 10:47p Dave
140 * Standardized D3D fogging using vertex fog. Shook out Savage 4 bugs.
142 * 30 7/27/99 6:53p Dave
143 * Hi-res main hall support.
145 * 29 7/16/99 1:49p Dave
146 * 8 bit aabitmaps. yay.
148 * 28 7/15/99 9:20a Andsager
149 * FS2_DEMO initial checkin
151 * 27 7/13/99 1:15p Dave
152 * 32 bit support. Whee!
154 * 26 6/25/99 2:51p Jasons
155 * Changed wording of network error message.
157 * 25 6/21/99 1:30p Alanl
158 * changed main menu music tag
160 * 24 6/19/99 3:56p Dave
161 * Moved main hall definitions into a table file. Whee!
163 * 23 6/11/99 11:13a Dave
164 * last minute changes before press tour build.
166 * 22 5/09/99 8:57p Dave
167 * Final E3 build preparations.
169 * 21 4/25/99 3:02p Dave
170 * Build defines for the E3 build.
172 * 20 4/12/99 10:07p Dave
173 * Made network startup more forgiving. Added checkmarks to dogfight
174 * screen for players who hit commit.
176 * 19 3/28/99 5:58p Dave
177 * Added early demo code. Make objects move. Nice and framerate
178 * independant, but not much else. Don't use yet unless you're me :)
180 * 18 3/25/99 5:47p Dave
183 * 17 3/19/99 9:51a Dave
184 * Checkin to repair massive source safe crash. Also added support for
185 * pof-style nebulae, and some new weapons code.
187 * 16 2/25/99 4:19p Dave
188 * Added multiplayer_beta defines. Added cd_check define. Fixed a few
189 * release build warnings. Added more data to the squad war request and
192 * 15 2/03/99 11:44a Dave
193 * Fixed d3d transparent textures.
195 * 14 1/30/99 5:08p Dave
196 * More new hi-res stuff.Support for nice D3D textures.
198 * 13 1/27/99 9:56a Dave
199 * Temporary checkin of beam weapons for Dan to make cool sounds.
201 * 12 12/31/98 11:23a Dave
202 * Put mini-indicators for status of ships.tbl and weapons.tbl in the
203 * lower left corner of the main hall.
205 * 11 12/18/98 1:13a Dave
206 * Rough 1024x768 support for Direct3D. Proper detection and usage through
209 * 10 11/30/98 1:07p Dave
210 * 16 bit conversion, first run.
212 * 9 11/20/98 4:08p Dave
213 * Fixed flak effect in multiplayer.
215 * 8 11/20/98 11:16a Dave
216 * Fixed up IPX support a bit. Making sure that switching modes and
217 * loading/saving pilot files maintains proper state.
219 * 7 11/19/98 4:57p Dave
220 * Ignore PXO option if IPX is selected.
222 * 6 11/19/98 4:19p Dave
223 * Put IPX sockets back in psnet. Consolidated all multiplayer config
226 * 5 11/05/98 5:55p Dave
227 * Big pass at reducing #includes
229 * 4 11/05/98 4:18p Dave
230 * First run nebula support. Beefed up localization a bit. Removed all
231 * conditional compiles for foreign versions. Modified mission file
234 * 3 10/13/98 9:28a Dave
235 * Started neatening up freespace.h. Many variables renamed and
236 * reorganized. Added AlphaColors.[h,cpp]
238 * 2 10/07/98 10:53a Dave
241 * 1 10/07/98 10:49a Dave
243 * 103 10/02/98 3:22p Allender
244 * fix up the -connect option and fix the -port option
246 * 102 8/20/98 5:31p Dave
247 * Put in handy multiplayer logfile system. Now need to put in useful
248 * applications of it all over the code.
250 * 101 8/07/98 10:40a Allender
251 * new command line flags for starting netgames. Only starting currently
252 * works, and PXO isn't implemented yet
254 * 100 7/13/98 10:46a Lawrance
255 * Index another localized string
257 * 99 7/10/98 1:13a Allender
258 * lots of small multiplayer update changes. Code in launcher to specify
259 * connection speed. A couple of small fixes regarding empty mission
260 * files. Time out players after 10 second when they don't connect on
261 * their reliable socket.
263 * 98 6/09/98 10:31a Hoffoss
264 * Created index numbers for all xstr() references. Any new xstr() stuff
265 * added from here on out should be added to the end if the list. The
266 * current list count can be found in FreeSpace.cpp (search for
269 * 97 6/05/98 9:50a Lawrance
272 * 96 6/01/98 11:43a John
273 * JAS & MK: Classified all strings for localization.
275 * 95 5/22/98 9:02p Allender
276 * remove G key from main hall
278 * 94 5/22/98 10:54a Allender
279 * new dialog information for networking to tell user if connection type
280 * doesn't match the setup specified type
282 * 93 5/15/98 5:15p Dave
283 * Fix a standalone resetting bug.Tweaked PXO interface. Display captaincy
284 * status for team vs. team. Put in asserts to check for invalid team vs.
287 * 92 5/13/98 12:23a Lawrance
288 * Don't init main hall if already inited... not needed now, but may be
289 * useful if we don't always want to call main_hall_close() when switching
292 * 91 5/12/98 2:46a Dave
293 * Rudimentary communication between Parallax Online and freespace. Can
294 * get and store channel lists.
296 * 90 5/08/98 5:33p Lawrance
297 * check for CD when trying to enter ready room in single player
304 #include "mainhallmenu.h"
308 #include "gamesequence.h"
309 #include "animplay.h"
313 #include "snazzyui.h"
315 #include "audiostr.h"
317 #include "eventmusic.h"
319 #include "contexthelp.h"
323 #include "multiutil.h"
327 #include "playermenu.h"
328 #include "freespace.h"
329 #include "multi_voice.h"
331 #include "alphacolors.h"
333 #include "fishtank.h"
335 // #include "movie.h"
337 // ----------------------------------------------------------------------------
338 // MAIN HALL DATA DEFINES
340 #define MAX_RANDOM_INTERCOM_SOUNDS 10
341 #define NUM_RANDOM_INTERCOM_SOUNDS_0 3
342 #define NUM_RANDOM_INTERCOM_SOUNDS_1 3
344 #define MAX_MISC_ANIMATIONS 10
345 #define NUM_MISC_ANIMATIONS_0 2
346 #define NUM_MISC_ANIMATIONS_1 4
348 #define MAX_DOOR_ANIMATIONS 10
349 #define NUM_DOOR_ANIMATIONS_0 6
350 #define NUM_DOOR_ANIMATIONS_1 6
352 #define MAX_DOOR_SOUNDS 10
353 #define NUM_DOOR_SOUNDS_0 6
354 #define NUM_DOOR_SOUNDS_1 6
356 #define MISC_ANIM_MODE_LOOP 0 // loop the animation
357 #define MISC_ANIM_MODE_HOLD 1 // play to the end and hold the animation
358 #define MISC_ANIM_MODE_TIMED 2 // uses timestamps to determine when a finished anim should be checked again
360 #define NUM_REGIONS 7 // (6 + 1 for multiplayer equivalent of campaign room)
361 typedef struct main_hall_defines {
363 char bitmap[MAX_FILENAME_LEN+1];
364 char mask[MAX_FILENAME_LEN+1];
367 char music[MAX_FILENAME_LEN+1];
369 // intercom defines -------------------
371 // # of intercom sounds
372 int num_random_intercom_sounds;
374 // random (min/max) delays between playing intercom sounds
375 int intercom_delay[MAX_RANDOM_INTERCOM_SOUNDS][2];
377 // intercom sounds themselves
378 int intercom_sounds[MAX_RANDOM_INTERCOM_SOUNDS];
380 // intercom sound pan values
381 float intercom_sound_pan[MAX_RANDOM_INTERCOM_SOUNDS];
384 // misc animations --------------------
386 // # of misc animations
387 int num_misc_animations;
389 // filenames of the misc animations
390 char misc_anim_name[MAX_MISC_ANIMATIONS][MAX_FILENAME_LEN+1];
392 // Time until we will next play a given misc animation, min delay, and max delay
393 int misc_anim_delay[MAX_MISC_ANIMATIONS][3];
395 // coords of where to play the misc anim
396 int misc_anim_coords[MAX_MISC_ANIMATIONS][2];
398 // misc anim play modes (see MISC_ANIM_MODE_* above)
399 int misc_anim_modes[MAX_MISC_ANIMATIONS];
401 // panning values for each of the misc anims
402 float misc_anim_sound_pan[MAX_MISC_ANIMATIONS];
404 // [N][0] == # of sounds, [N][1-9] sound index
405 int misc_anim_special_sounds[MAX_MISC_ANIMATIONS][10];
407 // [N][0] == # of triggers, [N][1-9] >= frame num
408 int misc_anim_special_trigger[MAX_MISC_ANIMATIONS][10];
410 // [N][0] == # of handles, [N][1-9] == sound handle num
411 int misc_anim_sound_handles[MAX_MISC_ANIMATIONS][10];
413 // [N][0] == # of handles, [N][1-9] == sound "should" be playing
414 int misc_anim_sound_flag[MAX_MISC_ANIMATIONS][10];
417 // door animations --------------------
419 // # of door animations
420 int num_door_animations;
422 // filenames of the door animations
423 char door_anim_name[MAX_DOOR_ANIMATIONS][MAX_FILENAME_LEN+1];
425 // first pair : coords of where to play a given door anim
426 // second pair : center of a given door anim in windowed mode
427 int door_anim_coords[MAX_DOOR_ANIMATIONS][4];
430 // door sounds ------------------------
435 // sounds for each region (open/close)
436 int door_sounds[MAX_DOOR_SOUNDS][2];
438 // pan values for the door sounds
439 float door_sound_pan[MAX_DOOR_SOUNDS];
442 // region descriptions ----------------
444 // text (tooltip) description
445 char *region_descript[NUM_REGIONS];
447 // y coord of where to draw tooltip text
453 // use main hall 0 by default
454 main_hall_defines Main_hall_defines[GR_NUM_RESOLUTIONS][NUM_MAIN_HALLS];
455 main_hall_defines *Main_hall = &Main_hall_defines[0][0];
457 int Vasudan_funny = 0;
458 int Vasudan_funny_plate = -1;
460 char Main_hall_campaign_cheat[512] = "";
462 // ----------------------------------------------------------------------------
463 // MISC interface data
465 // is the main hall inited (for reentrancy)
466 int Main_hall_inited = 0;
468 // handle to the playing music
469 int Main_hall_music_handle = -1;
471 // background bitmap handle
472 int Main_hall_bitmap;
474 // background bitmap mask handle
477 // variable used for automatic netgame starting/joining
478 int Main_hall_netgame_started = 0;
480 // bitmap struct for th background mask bitmap
481 bitmap *Main_hall_mask_bitmap;
483 // actual data for the background mask bitmap
484 ubyte *Main_hall_mask_data;
486 int Main_hall_mask_w, Main_hall_mask_h;
489 // ----------------------------------------------------------------------------
490 // MOUSE clicking stuff
492 // indicates whether a right click occured
493 int Main_hall_right_click;
495 // use this to cycle through the selectable regions instead of the mouse's current region
496 int Main_hall_last_clicked_region;
498 // use this to determine how long the cursor has to linger on a region before it starts playing
499 #define MAIN_HALL_REGION_LINGER 175 // in ms
500 int Main_hall_region_linger_stamp = -1;
502 // handle any right clicks which may have occured
503 void main_hall_handle_right_clicks();
506 // ----------------------------------------------------------------------------
507 // RANDOM intercom sounds
510 // next random intercom sound to play
511 int Main_hall_next_intercom_sound = 0;
513 // delay for the next intercom sound
514 int Main_hall_next_intercom_sound_stamp = -1;
516 // handle to any playing instance of a random intercom sound
517 int Main_hall_intercom_sound_handle = -1;
519 // handle any details related to random intercom sounds
520 void main_hall_handle_random_intercom_sounds();
523 // ----------------------------------------------------------------------------
527 // the misc animations themselves
528 anim *Main_hall_misc_anim[MAX_MISC_ANIMATIONS];
530 // the instance of a given misc animation
531 anim_instance *Main_hall_misc_anim_instance[MAX_MISC_ANIMATIONS];
533 // handle starting, stopping and randomizing misc animations
534 void main_hall_handle_misc_anims();
536 // cull any finished misc animation instances
537 void main_hall_cull_misc_anim_instances();
539 // render all playing misc animations
540 void main_hall_render_misc_anims(float frametime);
543 // ----------------------------------------------------------------------------
544 // DOOR animations (not all of these are doors anymore, but they're doorlike _regions_)
546 #define DOOR_TEXT_X 100
547 #define DOOR_TEXT_Y 450
549 // the door animations themselves
550 anim *Main_hall_door_anim[MAX_DOOR_ANIMATIONS];
552 // the instance of a given door animation
553 anim_instance *Main_hall_door_anim_instance[MAX_DOOR_ANIMATIONS];
555 // render all playing door animations
556 void main_hall_render_door_anims(float frametime);
559 // ----------------------------------------------------------------------------
562 #define NUM_MAIN_HALL_REGIONS 10
563 #define NUM_MAIN_HALL_MOUSE_REGIONS 6
565 // region mask #'s (identifiers)
566 #define EXIT_REGION 0
567 #define BARRACKS_REGION 1
568 #define READY_ROOM_REGION 2
569 #define TECH_ROOM_REGION 3
570 #define OPTIONS_REGION 4
571 #define CAMPAIGN_ROOM_REGION 5
572 #define MULTIPLAYER_REGION 10
573 #define LOAD_MISSION_REGION 11
574 #define QUICK_START_REGION 12
575 #define SKILL_LEVEL_REGION 13
577 // all the menu regions in the main hall
578 MENU_REGION Main_hall_region[NUM_MAIN_HALL_REGIONS];
580 // # of regions (options) on this screen. parsed from a table
581 int Main_hall_num_options;
583 // region over which the mouse is currently residing, or -1 if over no region
584 // NOTE : you should nevery change this directly. Always use main_hall_handle_mouse_location(int)
585 // to do this. Otherwise, the door opening and closing animations will get screwed up
586 int Main_hall_mouse_region;
588 // set this to skip a frame
589 int Main_hall_frame_skip;
591 // do any necessary processing based upon the mouse location
592 void main_hall_handle_mouse_location(int cur_region);
594 // if the mouse has moved off of the currently active region, handle the anim accordingly
595 void main_hall_mouse_release_region(int region);
597 // if the mouse has moved on this region, handle it accordingly
598 void main_hall_mouse_grab_region(int region);
601 // ----------------------------------------------------------------------------
602 // SOUND data / handlers
605 // toaster oven room sound idex
606 #define TOASTER_REGION 3
608 // everyone's favorite desk guardian
609 #define ALLENDER_REGION 4
611 // handles to the sound instances of the doors opening/closing
612 int Main_hall_door_sound_handles[MAX_DOOR_SOUNDS] = {
616 // sound handle for looping ambient sound
617 int Main_hall_ambient_loop = -1;
619 // cull any door sounds that have finished playing
620 void main_hall_cull_door_sounds();
622 // handle starting, stopping and reversing "door" animations
623 void main_hall_handle_region_anims();
626 // ----------------------------------------------------------------------------
627 // warning/notification messages
629 #define MAIN_HALL_NOTIFY_TIME 3500
631 // timestamp for the notification messages
632 int Main_hall_notify_stamp = -1;
634 // text to display as the current notification message
635 char Main_hall_notify_text[300]="";
637 // set the current notification string and the associated timestamp
638 void main_hall_set_notify_string(char *str);
640 // handle any drawing, culling, etc of notification messages
641 void main_hall_notify_do();
644 // ----------------------------------------------------------------------------
648 // upper _RIGHT_ corner for the version text
649 #define MAIN_HALL_VERSION_X 630
650 #define MAIN_HALL_VERSION_Y 467
652 // main hall help overlay ID
653 int Main_hall_overlay_id;
655 // blit the freespace version #
656 void main_hall_blit_version();
658 // blit any necessary tooltips
659 void main_hall_maybe_blit_tooltips();
661 // shader for behind tooltips
662 shader Main_hall_tooltip_shader;
664 // num pixels shader is above/below tooltip text
665 static int Main_hall_tooltip_padding[GR_NUM_RESOLUTIONS] = {
669 static int Main_hall_f1_text_frame = 0;
670 static int F1_text_done = 0;
672 // read in main hall table
673 void main_hall_read_table();
675 // "press f1" for help stuff
676 #define MAIN_HALL_HELP_TIME 5000
677 int Main_hall_help_stamp = -1;
678 void main_hall_process_help_stuff();
681 // ----------------------------------------------------------------------------
682 // VOICE RECORDING STUFF
685 // are we currently recording voice?
689 // called when multiplayer clicks on the ready room door. May pop up dialog depending on network
690 // connection status and errors
691 void main_hall_do_multi_ready()
695 error = psnet_get_network_status();
697 case NETWORK_ERROR_NO_TYPE:
698 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));
700 case NETWORK_ERROR_NO_WINSOCK:
701 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));
703 case NETWORK_ERROR_NO_PROTOCOL:
704 if(Multi_options_g.protocol == NET_TCP){
705 popup( PF_NO_NETWORKING, 1, POPUP_OK, XSTR( "TCP/IP protocol not found. This protocol is required for multiplayer FreeSpace.", 362));
707 Assert(Multi_options_g.protocol == NET_IPX);
708 popup( PF_NO_NETWORKING, 1, POPUP_OK, XSTR( "IPX protocol not found. This protocol is required for multiplayer FreeSpace.", 362));
711 case NETWORK_ERROR_CONNECT_TO_ISP:
712 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));
714 case NETWORK_ERROR_LAN_AND_RAS:
715 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));
718 case NETWORK_ERROR_NONE:
723 // if our selected protocol is not active
724 if((Multi_options_g.protocol == NET_TCP) && !Tcp_active){
725 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));
728 if((Multi_options_g.protocol == NET_IPX) && !Ipx_active){
729 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));
733 if ( error != NETWORK_ERROR_NONE ){
737 // 7/9/98 -- MWA. Deal with the connection speed issue. make a call to the multiplayer code to
738 // determine is a valid connection setting exists
739 if ( Multi_connection_speed == CONNECTION_SPEED_NONE ) {
740 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) );
744 // go to parallax online
745 #ifdef MULTIPLAYER_BETA_BUILD // do we want this for FS2_DEMO
746 Multi_options_g.pxo = 1;
747 Multi_options_g.protocol = NET_TCP;
748 gameseq_post_event( GS_EVENT_PXO );
751 // go to the regular join game screen
752 gameseq_post_event( GS_EVENT_MULTI_JOIN_GAME );
756 psnet_use_protocol(Multi_options_g.protocol);
759 // blit some small color indicators to show whether ships.tbl and weapons.tbl are valid
760 // green == valid, red == invalid.
761 // ships.tbl will be on the left, weapons.tbl on the right
762 int Mh_ship_table_status[GR_NUM_RESOLUTIONS][2] = {
766 int Mh_weapon_table_status[GR_NUM_RESOLUTIONS][2] = {
770 void main_hall_blit_table_status()
772 // blit ship table status
773 gr_set_color_fast(Game_ships_tbl_valid ? &Color_bright_green : &Color_bright_red);
774 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]);
776 // blit weapon table status
777 gr_set_color_fast(Game_weapons_tbl_valid ? &Color_bright_green : &Color_bright_red);
778 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]);
781 // bash the player to a specific mission in a campaign
782 void main_hall_campaign_cheat()
784 char *ret = popup_input(0, XSTR("Enter mission name.\n\n* This will destroy all legitimate progress in this campaign. *", -1));
788 // strcpy(Main_hall_campaign_cheat, ret);
789 mission_campaign_jump_to_mission(ret);
793 // -------------------------------------------------------------------------------------------------------------------
794 // FUNCTION DEFINITIONS BEGIN
797 // initialize the main hall proper
798 void main_hall_init(int main_hall_num)
800 if ( Main_hall_inited ) {
805 char temp[100], whee[100];
807 // read in the main hall table
808 main_hall_read_table();
810 // create the snazzy interface and load up the info from the table
812 read_menu_tbl(NOX("MAIN HALL"), temp, whee, Main_hall_region, &Main_hall_num_options, 0);
814 // assign the proper main hall data
815 Assert((main_hall_num >= 0) && (main_hall_num < NUM_MAIN_HALLS));
816 Main_hall = &Main_hall_defines[gr_screen.res][main_hall_num];
819 Main_hall->region_descript[0] = XSTR( "Exit FreeSpace 2", 353);
820 Main_hall->region_descript[1] = XSTR( "Barracks - Manage your FreeSpace 2 pilots", 354);
821 Main_hall->region_descript[2] = XSTR( "Ready room - Start or continue a campaign", 355);
822 Main_hall->region_descript[3] = XSTR( "Tech room - View specifications of FreeSpace 2 ships and weaponry", 356);
823 Main_hall->region_descript[4] = XSTR( "Options - Change your FreeSpace 2 options", 357);
824 Main_hall->region_descript[5] = XSTR( "Campaign Room - View all available campaigns", 358);
825 Main_hall->region_descript[6] = XSTR( "Multiplayer - Start or join a multiplayer game", 359);
827 // init tooltip shader
828 float gray_intensity = 0.02f; // nearly black
829 float c = (gr_screen.mode == GR_DIRECT3D || gr_screen.mode == GR_OPENGL) ? 0.11f : 0.07f; // adjust for renderer differences
830 gr_create_shader(&Main_hall_tooltip_shader, gray_intensity, gray_intensity, gray_intensity, c);
832 // load the background bitmap
833 Main_hall_bitmap = bm_load(Main_hall->bitmap);
834 if(Main_hall_bitmap < 0){
835 nprintf(("General","WARNING! Couldn't load main hall background bitmap %s\n", Main_hall->bitmap));
838 // remove any multiplayer flags from the game mode
839 Game_mode &= ~(GM_MULTIPLAYER);
841 // set the interface palette
842 #ifndef HARDWARE_ONLY
843 palette_use_bm_palette(Main_hall_bitmap);
846 Main_hall_mask_w = -1;
847 Main_hall_mask_h = -1;
850 Main_hall_mask = bm_load(Main_hall->mask);
851 if (Main_hall_mask < 0) {
852 Error(LOCATION,"Could not load in %s!", Main_hall->mask);
854 // get a pointer to bitmap by using bm_lock(), so we can feed it to he snazzy menu system
855 Main_hall_mask_bitmap = bm_lock(Main_hall_mask, 8, BMP_AABITMAP);
856 Main_hall_mask_data = (ubyte*)Main_hall_mask_bitmap->data;
857 bm_get_info(Main_hall_mask, &Main_hall_mask_w, &Main_hall_mask_h);
860 // load up the misc animations, and nullify all the delay timestamps for the misc animations
861 for(idx=0;idx<Main_hall->num_misc_animations;idx++) {
862 Main_hall_misc_anim[idx] = NULL;
863 Main_hall_misc_anim[idx] = anim_load(Main_hall->misc_anim_name[idx]);
864 if(Main_hall_misc_anim[idx] == NULL) {
865 nprintf(("General","WARNING!, Could not load misc %s anim in main hall\n",Main_hall->misc_anim_name));
868 // null out the animation instances
869 Main_hall_misc_anim_instance[idx] = NULL;
871 // null out the delay timestamps
872 Main_hall->misc_anim_delay[idx][0] = -1;
875 // load up the door animations
876 for(idx=0;idx<Main_hall->num_door_animations;idx++) {
877 Main_hall_door_anim[idx] = NULL;
878 Main_hall_door_anim[idx] = anim_load(Main_hall->door_anim_name[idx]);
879 if(Main_hall_door_anim[idx] == NULL){
880 nprintf(("General","WARNING!, Could not load door anim %s in main hall\n",Main_hall->door_anim_name[idx]));
883 // null out the animation instances
884 Main_hall_door_anim_instance[idx] = NULL;
887 // load in help overlay bitmap
888 if(Main_hall == &Main_hall_defines[gr_screen.res][0]) {
889 Main_hall_overlay_id = MH_OVERLAY;
891 Assert(Main_hall == &Main_hall_defines[gr_screen.res][1]);
892 Main_hall_overlay_id = MH2_OVERLAY;
894 help_overlay_load(Main_hall_overlay_id);
895 help_overlay_set_state(Main_hall_overlay_id,0);
897 // check to see if the "very first pilot" flag is set, and load the overlay if so
899 if (Main_hall_f1_text_frame == 0) {
900 Main_hall_help_stamp = timestamp(MAIN_HALL_HELP_TIME);
907 if(Player_select_very_first_pilot) {
908 Main_hall_help_stamp = timestamp(MAIN_HALL_HELP_TIME);
910 // don't display the "press f1" message more than once
911 Player_select_very_first_pilot = 0;
913 Main_hall_help_stamp = -1;
916 Main_hall_region_linger_stamp = -1;
918 strcpy(Main_hall_campaign_cheat, "");
920 // zero out the door sounds
921 for(idx=0;idx<Main_hall->num_door_sounds;idx++){
922 Main_hall_door_sound_handles[idx] = -1;
925 // zero out the misc anim sounds
926 for(idx=0;idx<Main_hall->num_misc_animations;idx++){
927 for(s_idx = 1;s_idx < 10;s_idx++){
928 Main_hall->misc_anim_sound_handles[idx][s_idx] = -1;
929 Main_hall->misc_anim_sound_flag[idx][s_idx] = 0;
933 // skip the first frame
934 Main_hall_frame_skip = 1;
936 // initialize the music
937 main_hall_start_music();
939 // initialize the main hall notify text
940 Main_hall_notify_stamp = 1;
942 // initialize the random intercom sound stuff
943 Main_hall_next_intercom_sound = 0;
944 Main_hall_next_intercom_sound_stamp = -1;
945 Main_hall_intercom_sound_handle = -1;
947 // set the placement of the mouse cursor (start at the ready room)
948 Main_hall_mouse_region = -1;
949 Main_hall_last_clicked_region = READY_ROOM_REGION;
950 mouse_set_pos(Main_hall->door_anim_coords[READY_ROOM_REGION][2],Main_hall->door_anim_coords[READY_ROOM_REGION][3]);
952 Main_hall_inited = 1;
954 // determine if we have a right click
955 Main_hall_right_click = mouse_down(MOUSE_RIGHT_BUTTON);
957 // set the game_mode based on the type of player
958 Assert( Player != NULL );
959 if ( Player->flags & PLAYER_FLAGS_IS_MULTI ){
960 Game_mode = GM_MULTIPLAYER;
962 Game_mode = GM_NORMAL;
965 if ( (Cmdline_start_netgame || (Cmdline_connect_addr != NULL)) && !Main_hall_netgame_started ) {
966 Main_hall_netgame_started = 1;
967 main_hall_do_multi_ready();
971 void main_hall_exit_game()
973 #if defined(NDEBUG) || defined(INTERPLAYQA)
977 main_hall_stop_music();
978 main_hall_stop_ambient();
979 choice = popup( PF_NO_NETWORKING | PF_BODY_BIG, 2, POPUP_NO, POPUP_YES, XSTR( "Exit Game?", 365));
981 gameseq_post_event(GS_EVENT_QUIT_GAME);
983 main_hall_start_music();
984 main_hall_start_ambient();
987 gameseq_post_event(GS_EVENT_QUIT_GAME);
992 // do a frame for the main hall
993 void main_hall_do(float frametime)
995 int code, key, snazzy_action;
997 // need to ensure ambient is playing, since it may be stopped by a playing movie
998 main_hall_start_ambient();
1000 // handle any animation details
1001 main_hall_handle_misc_anims();
1002 main_hall_handle_region_anims();
1004 // handle any random intercom sound details
1005 main_hall_handle_random_intercom_sounds();
1007 // handle any mouse clicks
1008 main_hall_handle_right_clicks();
1010 // handle any sound details
1011 main_hall_cull_door_sounds();
1013 // process any keypresses/mouse events
1015 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);
1018 extern void game_process_cheats(int k);
1019 game_process_cheats(key);
1023 snazzy_action = SNAZZY_CLICKED;
1026 #if 0 //#ifndef NDEBUG
1028 movie_play("endprt2b.mve", 0);
1031 movie_play_two("endprt2a.mve", "endprt2b.mve", 0);
1034 main_hall_campaign_cheat();
1036 case KEY_DEBUGGED + KEY_D:
1037 demo_start_playback("test.fsd");
1044 // do any processing based upon what happened to the snazzy menu
1045 switch (snazzy_action) {
1047 main_hall_handle_mouse_location(code);
1050 case SNAZZY_CLICKED:
1052 // clicked on the exit region
1054 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1055 main_hall_exit_game();
1058 // clicked on the readyroom region
1059 case READY_ROOM_REGION:
1060 #ifdef MULTIPLAYER_BETA_BUILD
1061 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1062 Player->flags |= PLAYER_FLAGS_IS_MULTI;
1063 main_hall_do_multi_ready();
1064 #elif defined(E3_BUILD) || defined(PRESS_TOUR_BUILD)
1065 gameseq_post_event(GS_EVENT_NEW_CAMPAIGN);
1067 if (Player->flags & PLAYER_FLAGS_IS_MULTI){
1068 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1069 main_hall_do_multi_ready();
1071 if(strlen(Main_hall_campaign_cheat)){
1072 gameseq_post_event(GS_EVENT_CAMPAIGN_CHEAT);
1074 gameseq_post_event(GS_EVENT_NEW_CAMPAIGN);
1076 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1081 // clicked on the tech room region
1082 case TECH_ROOM_REGION:
1083 #if defined(FS2_DEMO)
1084 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1085 game_feature_not_in_demo_popup();
1087 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1088 gameseq_post_event( GS_EVENT_TECH_MENU );
1092 // clicked on the options region
1093 case OPTIONS_REGION:
1094 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1095 gameseq_post_event(GS_EVENT_OPTIONS_MENU);
1098 // clicked on the campaign toom region
1099 case CAMPAIGN_ROOM_REGION:
1100 #if !defined(MULTIPLAYER_BETA_BUILD) && !defined(E3_BUILD) && !defined(PRESS_TOUR_BUILD)
1103 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1105 //game_feature_not_in_demo_popup();
1106 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.");
1107 if (reset_campaign == 1) {
1108 mission_campaign_savefile_delete(Campaign.filename);
1109 mission_campaign_load(Campaign.filename);
1110 mission_campaign_next_mission();
1115 if(Player->flags & PLAYER_FLAGS_IS_MULTI){
1116 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1117 main_hall_set_notify_string(XSTR( "Campaign Room not valid for multiplayer pilots", 366));
1119 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1120 gameseq_post_event(GS_EVENT_CAMPAIGN_ROOM);
1127 // clicked on the multiplayer region
1128 case MULTIPLAYER_REGION:
1129 #if defined(DEMO) || defined(OEM_BUILD) // not for FS2_DEMO
1130 game_feature_not_in_demo_popup();
1132 if (Player->flags & PLAYER_FLAGS_IS_MULTI){
1133 // NOTE : this isn't a great thing to be calling this anymore. But we'll leave it for now
1134 gameseq_post_event( GS_EVENT_MULTI_JOIN_GAME );
1136 main_hall_set_notify_string(XSTR( "Not a valid multiplayer pilot!!", 367));
1141 // load mission key was pressed
1142 case LOAD_MISSION_REGION:
1145 #if !(defined(MULTIPLAYER_BETA_BUILD) || defined(FS2_DEMO))
1146 //#if !defined(NDEBUG) || defined(INTERPLAYQA)
1147 if (Player->flags & PLAYER_FLAGS_IS_MULTI){
1148 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1149 main_hall_set_notify_string(XSTR( "Load Mission not valid for multiplayer pilots", 368));
1151 #ifdef GAME_CD_CHECK
1152 // if ( !game_do_cd_check() ) {
1156 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1157 gameseq_post_event( GS_EVENT_LOAD_MISSION_MENU );
1164 // quick start a game region
1165 case QUICK_START_REGION:
1166 #if !defined(NDEBUG) && !defined(FS2_DEMO)
1167 if (Player->flags & PLAYER_FLAGS_IS_MULTI){
1168 main_hall_set_notify_string(XSTR( "Quick Start not valid for multiplayer pilots", 369));
1171 if (Num_recent_missions > 0) {
1172 strncpy( Game_current_mission_filename, Recent_missions[0], MAX_FILENAME_LEN );
1174 mission_load_up_campaign();
1175 strncpy( Game_current_mission_filename, Campaign.missions[0].name, MAX_FILENAME_LEN );
1178 Campaign.current_mission = -1;
1179 gameseq_post_event(GS_EVENT_START_GAME_QUICK);
1184 // clicked on the barracks region
1185 case BARRACKS_REGION:
1186 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1187 gameseq_post_event( GS_EVENT_BARRACKS_MENU );
1190 // increate the skill level
1191 case SKILL_LEVEL_REGION:
1194 game_increase_skill_level();
1195 sprintf(temp, XSTR( "Skill level set to %s.", 370), Skill_level_names(Game_skill_level));
1196 main_hall_set_notify_string(temp);
1199 // escape was pressed
1201 // if there is a help overlay active, then don't quit the game - just kill the overlay
1202 if(!help_overlay_active(Main_hall_overlay_id)){
1203 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1204 main_hall_exit_game();
1208 help_overlay_set_state(Main_hall_overlay_id,0);
1213 // if the escape key wasn't pressed handle any mouse position related events
1214 if (code != ESC_PRESSED){
1215 main_hall_handle_mouse_location(code);
1220 main_hall_handle_mouse_location(-1);
1224 if ( mouse_down(MOUSE_LEFT_BUTTON) ) {
1225 help_overlay_set_state(Main_hall_overlay_id, 0);
1228 // draw the background bitmap
1230 GR_MAYBE_CLEAR_RES(Main_hall_bitmap);
1231 if(Main_hall_bitmap >= 0){
1232 gr_set_bitmap(Main_hall_bitmap);
1236 // draw any pending notification messages
1237 main_hall_notify_do();
1239 // render misc animations
1240 main_hall_render_misc_anims(frametime);
1242 // render door animtions
1243 main_hall_render_door_anims(frametime);
1245 // blit any appropriate tooltips
1246 main_hall_maybe_blit_tooltips();
1251 // process any help "hit f1" timestamps and display any messages if necessary
1252 if (!F1_text_done) {
1253 main_hall_process_help_stuff();
1256 // blit help overlay if active
1257 help_overlay_maybe_blit(Main_hall_overlay_id);
1259 // blit the freespace version #
1260 main_hall_blit_version();
1262 // blit ship and weapon table status
1263 main_hall_blit_table_status();
1265 // if we're in nice D3D texture format
1267 gr_set_color_fast(&Color_white);
1270 if(gr_screen.mode == GR_DIRECT3D){
1271 if(Bm_pixel_format == BM_PIXEL_FORMAT_ARGB_D3D){
1272 gr_string(320, gr_screen.max_h - 10, "D3D ARGB");
1274 extern int D3d_rendition_uvs;
1275 extern int D3D_32bit;
1276 extern int D3D_fog_mode;
1277 extern int D3D_zbias;
1278 if(D3d_rendition_uvs){
1279 gr_string(320, gr_screen.max_h - 20, "D3D rendition");
1282 gr_string(320, gr_screen.max_h - 30, "D3D 32bit");
1284 gr_printf(320, gr_screen.max_h - 40, "Fog : %d", D3D_fog_mode);
1285 gr_printf(320, gr_screen.max_h - 50, "Zbias : %d", D3D_zbias);
1286 // extern void d3d_test();
1288 } else if(gr_screen.mode == GR_GLIDE){
1290 extern int Glide_voodoo3;
1292 gr_string(320, gr_screen.max_h - 20, "VOODOO 3");
1300 // maybe run the player tips popup
1301 // #if defined(FS2_DEMO) && defined(NDEBUG)
1302 player_tips_popup();
1305 // if we were supposed to skip a frame, then stop doing it after 1 frame
1306 if(Main_hall_frame_skip){
1307 Main_hall_frame_skip = 0;
1311 // close the main hall proper
1312 void main_hall_close()
1316 if(!Main_hall_inited){
1320 // unload the main hall bitmap
1321 if(Main_hall_bitmap != -1){
1322 bm_unload(Main_hall_bitmap);
1325 // unload any bitmaps
1326 if(Main_hall_mask >= 0){
1327 // make sure we unlock the mask bitmap so it can be unloaded
1328 bm_unlock(Main_hall_mask);
1329 if(!bm_unload(Main_hall_mask)){
1330 nprintf(("General","WARNING! Couldn't unload main hall mask bitmap!\n"));
1334 // free up any (possibly) playing misc animation handles
1335 for(idx=0;idx<Main_hall->num_misc_animations;idx++){
1336 if(Main_hall_misc_anim_instance[idx]!=NULL){
1337 anim_stop_playing(Main_hall_misc_anim_instance[idx]);
1338 Main_hall_misc_anim_instance[idx] = NULL;
1342 // free up any (possibly) playing door animation handles
1343 for(idx=0;idx<Main_hall->num_door_animations;idx++){
1344 if(Main_hall_door_anim_instance[idx]!=NULL){
1345 anim_stop_playing(Main_hall_door_anim_instance[idx]);
1346 Main_hall_door_anim_instance[idx] = NULL;
1351 // free up any misc animations/instances
1352 for(idx=0;idx<Main_hall->num_misc_animations;idx++){
1353 if((Main_hall_misc_anim_instance[idx]!=NULL) && (anim_playing(Main_hall_misc_anim_instance[idx]))){
1354 Main_hall_misc_anim_instance[idx] = NULL;
1356 if(Main_hall_misc_anim[idx]!=NULL){
1357 if(anim_free(Main_hall_misc_anim[idx]) == -1){
1358 nprintf(("General","WARNING!, Could not free up misc anim %s in main hall\n",Main_hall->misc_anim_name[idx]));
1363 // free up any door animations/instances
1364 for(idx=0;idx<Main_hall->num_door_animations;idx++){
1365 if((Main_hall_door_anim_instance[idx]!=NULL) && (anim_playing(Main_hall_door_anim_instance[idx]))){
1366 Main_hall_door_anim_instance[idx] = NULL;
1368 if(Main_hall_door_anim[idx]!=NULL){
1369 if(anim_free(Main_hall_door_anim[idx]) == -1){
1370 nprintf(("General","WARNING!, Could not free up door anim %s in main hall\n",Main_hall->door_anim_name[idx]));
1375 // stop any playing door sounds
1376 for(idx=0;idx<Main_hall->num_door_sounds-2;idx++){ // don't cut off the glow sounds (requested by Dan)
1377 if((Main_hall_door_sound_handles[idx] != -1) && snd_is_playing(Main_hall_door_sound_handles[idx])){
1378 snd_stop(Main_hall_door_sound_handles[idx]);
1379 Main_hall_door_sound_handles[idx] = -1;
1383 // stop any playing misc animation sounds
1384 for(idx=0;idx<Main_hall->num_misc_animations;idx++){
1385 for(s_idx=1;s_idx<10;s_idx++){
1386 if(snd_is_playing(Main_hall->misc_anim_sound_handles[idx][s_idx])){
1387 snd_stop(Main_hall->misc_anim_sound_handles[idx][s_idx]);
1388 Main_hall->misc_anim_sound_handles[idx][s_idx] = -1;
1393 // unload the overlay bitmap
1394 help_overlay_unload(Main_hall_overlay_id);
1396 // close any snazzy menu details
1397 snazzy_menu_close();
1400 palette_restore_palette();
1405 // not inited anymore
1406 Main_hall_inited = 0;
1409 // start the main hall music playing
1410 void main_hall_start_music()
1412 // start a looping ambient sound
1413 main_hall_start_ambient();
1415 // if we have selected no music, then don't do this
1416 if ( Cmdline_freespace_no_music ) {
1420 int main_hall_spooled_music_index = event_music_get_spooled_music_index(Main_hall->music);
1422 if ((Main_hall_music_handle == -1) && (main_hall_spooled_music_index != -1)) {
1423 char *music_wavfile_name = Spooled_music[main_hall_spooled_music_index].filename;
1424 if (music_wavfile_name != NULL) {
1425 Main_hall_music_handle = audiostream_open( music_wavfile_name, ASF_EVENTMUSIC );
1426 if ( Main_hall_music_handle != -1 )
1427 audiostream_play(Main_hall_music_handle, Master_event_music_volume);
1430 nprintf(("Warning", "No music file exists to play music at the main menu!\n"));
1435 // stop the main hall music
1436 void main_hall_stop_music()
1438 if ( Main_hall_music_handle != -1 ) {
1439 audiostream_close_file(Main_hall_music_handle);
1440 Main_hall_music_handle = -1;
1444 // do any necessary instantiation of misc animations
1445 void main_hall_handle_misc_anims()
1449 if(Main_hall_frame_skip)
1452 for(idx=0;idx<Main_hall->num_misc_animations;idx++){
1453 // if the anim isn't playing
1454 if(Main_hall_misc_anim_instance[idx] == NULL){
1455 // if the timestamp is -1, then reset it to some random value (based on MIN and MAX) and continue
1456 if(Main_hall->misc_anim_delay[idx][0] == -1){
1457 Main_hall->misc_anim_delay[idx][0] = timestamp(Main_hall->misc_anim_delay[idx][1] +
1458 (int)(((float)rand()/(float)RAND_MAX) * (float)(Main_hall->misc_anim_delay[idx][2] - Main_hall->misc_anim_delay[idx][1])));
1460 // if the timestamp is not -1 and has popped, play the anim and make the timestap -1
1461 } else if (timestamp_elapsed(Main_hall->misc_anim_delay[idx][0]) && Main_hall_misc_anim[idx]) {
1462 anim_play_struct aps;
1464 anim_play_init(&aps, Main_hall_misc_anim[idx], Main_hall->misc_anim_coords[idx][0], Main_hall->misc_anim_coords[idx][1]);
1465 aps.screen_id = GS_STATE_MAIN_MENU;
1466 aps.framerate_independent = 1;
1468 Main_hall_misc_anim_instance[idx] = anim_play(&aps);
1470 // kill the timestamp
1471 Main_hall->misc_anim_delay[idx][0] = -1;
1473 // reset the "should be playing" flags
1474 for(s_idx=1;s_idx<10;s_idx++){
1475 Main_hall->misc_anim_sound_flag[idx][s_idx] = 0;
1479 // if the anim is playing
1481 // check to see if any special trigger points have been reached by the animation
1482 // since the frame triggers must be in ascending order, we will count down so that we don't trigger too many sounds
1483 for(s_idx=Main_hall->misc_anim_special_sounds[idx][0]; s_idx > 0; s_idx--){
1484 // if we've passed the trigger point, then play the sound and break out of the loop
1485 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]){
1486 Main_hall->misc_anim_sound_flag[idx][s_idx] = 1;
1488 // if the sound is already playing, then kill it. This is a pretty safe thing to do since we can assume that
1489 // by the time we get to this point again, the sound will have been long finished
1490 if(snd_is_playing(Main_hall->misc_anim_sound_handles[idx][s_idx])){
1491 snd_stop(Main_hall->misc_anim_sound_handles[idx][s_idx]);
1492 Main_hall->misc_anim_sound_handles[idx][s_idx] = -1;
1495 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]);
1500 // if the animation mode is MISC_ANIM_MODE_HOLD, pause it at the last frame
1501 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)){
1502 anim_pause(Main_hall_misc_anim_instance[idx]);
1503 Main_hall_misc_anim_instance[idx]->stop_now = FALSE;
1506 // if the animation mode is MISC_ANIM_MODE_LOOP, check to see if it should be looped
1507 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)){
1508 anim_release_render_instance(Main_hall_misc_anim_instance[idx]);
1510 // start it playing again
1511 anim_play_struct aps;
1513 anim_play_init(&aps, Main_hall_misc_anim[idx], Main_hall->misc_anim_coords[idx][0], Main_hall->misc_anim_coords[idx][1]);
1514 aps.screen_id = GS_STATE_MAIN_MENU;
1515 aps.framerate_independent = 1;
1517 Main_hall_misc_anim_instance[idx] = anim_play(&aps);
1519 // kill the timestamp
1520 Main_hall->misc_anim_delay[idx][0] = -1;
1522 // reset the "should be playing" flags
1523 for(s_idx=1;s_idx<10;s_idx++){
1524 Main_hall->misc_anim_sound_flag[idx][s_idx] = 0;
1528 // cull any misc animations which are marked as done (!is_playing)
1529 if(!anim_playing(Main_hall_misc_anim_instance[idx])){
1530 Main_hall_misc_anim_instance[idx] = NULL;
1536 // render all playing misc animations
1537 void main_hall_render_misc_anims(float frametime)
1541 // HACKETY HACK HACK - always render misc anim 3 first, if it is playing
1542 if(Main_hall_misc_anim_instance[2] != NULL){
1543 anim_render_one(GS_STATE_MAIN_MENU,Main_hall_misc_anim_instance[2],frametime);
1546 // render all other animations
1547 for(idx=0;idx<MAX_MISC_ANIMATIONS;idx++){
1548 // skip anim 3, which was previously rendered, if at all
1554 if(Main_hall_misc_anim_instance[idx] != NULL){
1555 anim_render_one(GS_STATE_MAIN_MENU,Main_hall_misc_anim_instance[idx],frametime);
1560 // render all playing door animations
1561 void main_hall_render_door_anims(float frametime)
1565 // render all door animations
1566 for(idx=0;idx<MAX_DOOR_ANIMATIONS;idx++){
1568 if(Main_hall_door_anim_instance[idx] != NULL){
1569 anim_render_one(GS_STATE_MAIN_MENU,Main_hall_door_anim_instance[idx],frametime);
1574 // handle starting, stopping and reversing "door" animations
1575 void main_hall_handle_region_anims()
1579 if(Main_hall_frame_skip)
1582 // make sure we make any finished door animations NULL
1583 for(idx=0;idx<Main_hall->num_door_animations;idx++){
1584 if((Main_hall_door_anim_instance[idx] != NULL) && !anim_playing(Main_hall_door_anim_instance[idx])){
1585 Main_hall_door_anim_instance[idx] = NULL;
1589 // go through each region animation
1590 for(idx=0;idx<Main_hall->num_door_animations;idx++){
1591 // if the instance is not null and the animation is playing
1592 if((Main_hall_door_anim_instance[idx] != NULL) && anim_playing(Main_hall_door_anim_instance[idx])){
1593 // check to see if we should hold a given door "open"
1594 if((Main_hall_mouse_region == idx) && (Main_hall_door_anim_instance[idx]->frame_num == Main_hall_door_anim_instance[idx]->stop_at)){
1595 anim_pause(Main_hall_door_anim_instance[idx]);
1596 Main_hall_door_anim_instance[idx]->stop_now = FALSE;
1598 // check to see if we should close a door being held open
1599 if((Main_hall_mouse_region != idx) && (Main_hall_door_anim_instance[idx]->paused)){
1600 anim_unpause(Main_hall_door_anim_instance[idx]);
1606 // do any necessary processing based upon the mouse location
1607 void main_hall_handle_mouse_location(int cur_region)
1609 if(Main_hall_frame_skip)
1612 if(cur_region > NUM_MAIN_HALL_MOUSE_REGIONS) {
1613 // MWA -- inserted return since Int3() was tripped when hitting L from main
1618 // if the mouse is now over a resgion
1619 if (cur_region != -1) {
1620 // if we're still over the same region we were last frame, check stuff
1621 if (cur_region == Main_hall_mouse_region) {
1622 // if we have a linger timestamp set and it has expired, then get moving
1623 if ((Main_hall_region_linger_stamp != -1) && timestamp_elapsed(Main_hall_region_linger_stamp)) {
1624 main_hall_mouse_grab_region(cur_region);
1626 // release the region linger stamp
1627 Main_hall_region_linger_stamp = -1;
1630 // if we're currently on another region, release it
1631 if ((Main_hall_mouse_region != -1) && (cur_region != Main_hall_mouse_region)) {
1632 main_hall_mouse_release_region(Main_hall_mouse_region);
1635 // set the linger time
1636 if (Main_hall_region_linger_stamp == -1) {
1637 Main_hall_mouse_region = cur_region;
1638 Main_hall_region_linger_stamp = timestamp(MAIN_HALL_REGION_LINGER);
1642 // if it was over a region but isn't anymore, release that region
1644 if (Main_hall_mouse_region != -1) {
1645 main_hall_mouse_release_region(Main_hall_mouse_region);
1646 Main_hall_mouse_region = -1;
1648 // release the region linger timestamp
1649 Main_hall_region_linger_stamp = -1;
1654 // if the mouse has moved off of the currently active region, handle the anim accordingly
1655 void main_hall_mouse_release_region(int region)
1657 if(Main_hall_frame_skip){
1661 // if the animation is currently playing in the forward direction, change direction and be done, otherwise don't do a thing
1662 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)){
1663 anim_reverse_direction(Main_hall_door_anim_instance[region]);
1666 // check for door sounds, ignoring the OPTIONS_REGION (which isn't a door)
1667 if ((Main_hall_door_anim_instance[region] != NULL)) {
1668 // don't stop the toaster oven or microwave regions from playing all the way through
1669 if (Main_hall_door_sound_handles[region] != -1) {
1670 snd_stop(Main_hall_door_sound_handles[region]);
1672 Main_hall_door_sound_handles[region] = snd_play(&Snds_iface[Main_hall->door_sounds[region][1]], Main_hall->door_sound_pan[region]);
1674 // make sure to set the sound to play from the right spot
1675 snd_set_pos(Main_hall_door_sound_handles[region], &Snds_iface[SND_MAIN_HALL_DOOR_CLOSE],
1676 (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);
1680 // if the mouse has moved on this region, handle it accordingly
1681 void main_hall_mouse_grab_region(int region)
1683 if (Main_hall_frame_skip) {
1687 // if the animation is not playing, start it playing
1688 if ( !Main_hall_door_anim_instance[region] ) {
1689 if ( Main_hall_door_anim[region] ) {
1690 anim_play_struct aps;
1692 anim_play_init(&aps, Main_hall_door_anim[region], Main_hall->door_anim_coords[region][0], Main_hall->door_anim_coords[region][1]);
1693 aps.screen_id = GS_STATE_MAIN_MENU;
1694 aps.framerate_independent = 1;
1696 Main_hall_door_anim_instance[region] = anim_play(&aps);
1699 // otherwise if its playing in the reverse direction, change it to the forward direction
1700 else if (Main_hall_door_anim_instance[region]->direction == ANIM_DIRECT_REVERSE) {
1701 anim_reverse_direction(Main_hall_door_anim_instance[region]);
1704 // check for opening/starting sounds
1705 // kill the currently playing sounds if necessary
1706 if(Main_hall_door_sound_handles[region] != -1){
1707 snd_stop(Main_hall_door_sound_handles[region]);
1709 Main_hall_door_sound_handles[region] = snd_play(&Snds_iface[Main_hall->door_sounds[region][0]],Main_hall->door_sound_pan[region]);
1711 // start the sound playing at the right spot relative to the completion of the animation
1712 if(Main_hall_door_anim_instance[region]->frame_num != -1){
1713 snd_set_pos(Main_hall_door_sound_handles[region],&Snds_iface[SND_MAIN_HALL_DOOR_OPEN],
1714 (float)Main_hall_door_anim_instance[region]->frame_num / (float)Main_hall_door_anim_instance[region]->parent->total_frames,1);
1718 // handle any right clicks which may have occured
1719 void main_hall_handle_right_clicks()
1723 if(Main_hall_frame_skip)
1726 // check to see if the button has been clicked
1727 if(!Main_hall_right_click){
1728 if(mouse_down(MOUSE_RIGHT_BUTTON)){
1729 // cycle through the available regions
1730 if(Main_hall_last_clicked_region == NUM_MAIN_HALL_MOUSE_REGIONS - 1){
1733 new_region = Main_hall_last_clicked_region + 1;
1735 // set the position of the mouse cursor and the newly clicked region
1736 mouse_set_pos(Main_hall->door_anim_coords[new_region][2],Main_hall->door_anim_coords[new_region][3]);
1738 main_hall_handle_mouse_location(new_region);
1739 Main_hall_last_clicked_region = new_region;
1741 // set the mouse as being clicked
1742 Main_hall_right_click = 1;
1745 // set the mouse as being unclicked
1746 else if(Main_hall_right_click && !(mouse_down(MOUSE_RIGHT_BUTTON))){
1747 Main_hall_right_click = 0;
1751 // cull any door sounds that have finished playing
1752 void main_hall_cull_door_sounds()
1755 // 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
1756 for(idx=0;idx<Main_hall->num_door_sounds;idx++){
1757 if((Main_hall_door_sound_handles[idx] != -1) && !snd_is_playing(Main_hall_door_sound_handles[idx])){
1758 Main_hall_door_sound_handles[idx] = -1;
1763 void main_hall_handle_random_intercom_sounds()
1765 // if we have no timestamp for the next random sound, then set on
1766 if((Main_hall_next_intercom_sound_stamp == -1) && (Main_hall_intercom_sound_handle == -1)){
1767 Main_hall_next_intercom_sound_stamp = timestamp((int)(((float)rand()/(float)RAND_MAX) *
1768 (float)(Main_hall->intercom_delay[Main_hall_next_intercom_sound][1]
1769 - Main_hall->intercom_delay[Main_hall_intercom_sound_handle][0])) );
1772 // if the there is no sound playing
1773 if(Main_hall_intercom_sound_handle == -1){
1774 // if the timestamp has popped, play a sound
1775 if((Main_hall_next_intercom_sound_stamp != -1) && (timestamp_elapsed(Main_hall_next_intercom_sound_stamp))){
1777 Main_hall_intercom_sound_handle = snd_play(&Snds_iface[Main_hall->intercom_sounds[Main_hall_next_intercom_sound]]);
1779 // unset the timestamp
1780 Main_hall_next_intercom_sound_stamp = -1;
1783 // if the sound is playing
1785 // if the sound has finished, set the timestamp and continue
1786 if(!snd_is_playing(Main_hall_intercom_sound_handle)){
1787 // increment the next sound
1788 if(Main_hall_next_intercom_sound >= (Main_hall->num_random_intercom_sounds-1)){
1789 Main_hall_next_intercom_sound = 0;
1791 Main_hall_next_intercom_sound++;
1794 // set the timestamp
1795 Main_hall_next_intercom_sound_stamp = timestamp((int)(((float)rand()/(float)RAND_MAX) *
1796 (float)(Main_hall->intercom_delay[Main_hall_next_intercom_sound][1]
1797 - Main_hall->intercom_delay[Main_hall_next_intercom_sound][0])) );
1799 // release the sound handle
1800 Main_hall_intercom_sound_handle = -1;
1805 // set the notification string with its decay timeout
1806 void main_hall_set_notify_string(char *str)
1808 strcpy(Main_hall_notify_text,str);
1809 Main_hall_notify_stamp = timestamp(MAIN_HALL_NOTIFY_TIME);
1812 void main_hall_notify_do()
1814 // check to see if we should try and do something
1815 if(Main_hall_notify_stamp != -1){
1816 // if the text time has expired
1817 if(timestamp_elapsed(Main_hall_notify_stamp)){
1818 strcpy(Main_hall_notify_text,"");
1819 Main_hall_notify_stamp = -1;
1822 gr_set_color_fast(&Color_bright);
1824 gr_get_string_size(&w,&h,Main_hall_notify_text);
1825 gr_printf((gr_screen.max_w - w)/2, gr_screen.max_h - 40, Main_hall_notify_text);
1830 // start a looping ambient sound for main hall
1831 void main_hall_start_ambient()
1833 int play_ambient_loop = 0;
1835 if ( Main_hall_ambient_loop == -1 ) {
1836 play_ambient_loop = 1;
1838 if ( !snd_is_playing(Main_hall_ambient_loop) ) {
1839 play_ambient_loop = 1;
1843 if ( play_ambient_loop ) {
1844 Main_hall_ambient_loop = snd_play_looping(&Snds_iface[SND_MAIN_HALL_AMBIENT]);
1848 // stop a looping ambient sound for the main hall
1849 void main_hall_stop_ambient()
1851 if ( Main_hall_ambient_loop != -1 ) {
1852 snd_stop(Main_hall_ambient_loop);
1853 Main_hall_ambient_loop = -1;
1857 // Reset the volume of the looping ambient sound. This is called from the options
1858 // screen when the looping ambient sound might be playing.
1859 void main_hall_reset_ambient_vol()
1861 if ( Main_hall_ambient_loop >= 0 ) {
1862 snd_set_volume(Main_hall_ambient_loop, Snds_iface[SND_MAIN_HALL_AMBIENT].default_volume);
1866 // blit the freespace version #
1867 void main_hall_blit_version()
1869 char version_string[100];
1872 // format the version string
1873 get_version_string(version_string);
1875 // get the length of the string
1876 gr_get_string_size(&w,NULL,version_string);
1878 // print the string out in the lower right corner
1879 gr_set_color_fast(&Color_white);
1880 gr_string(gr_screen.max_w - 55, gr_screen.max_h - 12, version_string);
1883 // blit any necessary tooltips
1884 void main_hall_maybe_blit_tooltips()
1889 // if we're over no region - don't blit anything
1890 if(Main_hall_mouse_region < 0) {
1894 // get the index of the proper text to be using
1895 if(Main_hall_mouse_region == READY_ROOM_REGION) {
1896 // if this is a multiplayer pilot, the ready room region becomes the multiplayer region
1897 if(Player->flags & PLAYER_FLAGS_IS_MULTI){
1898 text_index = NUM_REGIONS - 1;
1900 text_index = READY_ROOM_REGION;
1903 text_index = Main_hall_mouse_region;
1906 // set the color and blit the string
1907 if(!help_overlay_active(Main_hall_overlay_id)) {
1908 int shader_y = (Main_hall->region_yval) - Main_hall_tooltip_padding[gr_screen.res]; // subtract more to pull higher
1909 // get the width of the string
1910 gr_get_string_size(&w, NULL, Main_hall->region_descript[text_index]);
1912 gr_set_shader(&Main_hall_tooltip_shader);
1913 gr_shade(0, shader_y, gr_screen.clip_width, (gr_screen.clip_height - shader_y));
1915 gr_set_color_fast(&Color_bright_white);
1916 gr_string((gr_screen.max_w - w)/2, Main_hall->region_yval, Main_hall->region_descript[text_index]);
1921 void main_hall_process_help_stuff()
1926 // if the timestamp has popped, don't do anything
1927 if(Main_hall_help_stamp == -1) {
1931 // if the timestamp has popped, advance frame
1932 if(timestamp_elapsed(Main_hall_help_stamp)) {
1933 Main_hall_f1_text_frame++;
1936 // otherwise print out the message
1937 strcpy(str, XSTR( "Press F1 for help", 371));
1938 gr_get_string_size(&w, &h, str);
1940 int y_anim_offset = Main_hall_f1_text_frame;
1942 // if anim is off the screen finally, stop altogether
1943 if ( (y_anim_offset >= (2*Main_hall_tooltip_padding[gr_screen.res]) + h) || (help_overlay_active(Main_hall_overlay_id)) ) {
1944 Main_hall_f1_text_frame = -1;
1945 Main_hall_help_stamp = -1;
1950 // set the color and print out text and shader
1951 gr_set_color_fast(&Color_bright_white);
1952 gr_shade(0, 0, gr_screen.max_w, (2*Main_hall_tooltip_padding[gr_screen.res]) + h - y_anim_offset);
1953 gr_string((gr_screen.max_w - w)/2, Main_hall_tooltip_padding[gr_screen.res] - y_anim_offset, str);
1956 // what main hall we're on (should be 0 or 1)
1959 // only 1 of 2 main halls
1960 if(Main_hall == &Main_hall_defines[gr_screen.res][0]){
1967 // read in main hall table
1968 void main_hall_read_table()
1970 main_hall_defines *m, temp;
1971 int count, idx, s_idx, m_idx;
1974 read_file_text("mainhall.tbl");
1979 while(!optional_string("#end")){
1981 // read in 2 resolutions
1982 for(m_idx=0; m_idx<GR_NUM_RESOLUTIONS; m_idx++){
1983 // maybe use a temp main hall stuct
1984 if(count >= NUM_MAIN_HALLS){
1987 m = &Main_hall_defines[m_idx][count];
1991 required_string("$Main Hall");
1994 required_string("+Bitmap:");
1995 stuff_string(m->bitmap, F_NAME, NULL, MAX_FILENAME_LEN);
1996 required_string("+Mask:");
1997 stuff_string(m->mask, F_NAME, NULL, MAX_FILENAME_LEN);
1999 required_string("+Music:");
2000 stuff_string(m->music, F_NAME, NULL, MAX_FILENAME_LEN);
2004 required_string("+Num Intercom Sounds:");
2005 stuff_int(&m->num_random_intercom_sounds);
2006 for(idx=0; idx<m->num_random_intercom_sounds; idx++){
2008 required_string("+Intercom delay:");
2009 stuff_int(&m->intercom_delay[idx][0]);
2010 stuff_int(&m->intercom_delay[idx][1]);
2012 for(idx=0; idx<m->num_random_intercom_sounds; idx++){
2013 // intercom sound id
2014 required_string("+Intercom sound:");
2015 stuff_int(&m->intercom_sounds[idx]);
2017 for(idx=0; idx<m->num_random_intercom_sounds; idx++){
2019 required_string("+Intercom pan:");
2020 stuff_float(&m->intercom_sound_pan[idx]);
2024 required_string("+Num Misc Animations:");
2025 stuff_int(&m->num_misc_animations);
2026 for(idx=0; idx<m->num_misc_animations; idx++){
2028 required_string("+Misc anim:");
2029 stuff_string(m->misc_anim_name[idx], F_NAME, NULL);
2031 for(idx=0; idx<m->num_misc_animations; idx++){
2033 required_string("+Misc anim delay:");
2034 stuff_int(&m->misc_anim_delay[idx][0]);
2035 stuff_int(&m->misc_anim_delay[idx][1]);
2036 stuff_int(&m->misc_anim_delay[idx][2]);
2038 for(idx=0; idx<m->num_misc_animations; idx++){
2040 required_string("+Misc anim coords:");
2041 stuff_int(&m->misc_anim_coords[idx][0]);
2042 stuff_int(&m->misc_anim_coords[idx][1]);
2044 for(idx=0; idx<m->num_misc_animations; idx++){
2046 required_string("+Misc anim mode:");
2047 stuff_int(&m->misc_anim_modes[idx]);
2049 for(idx=0; idx<m->num_misc_animations; idx++){
2051 required_string("+Misc anim pan:");
2052 stuff_float(&m->misc_anim_sound_pan[idx]);
2054 for(idx=0; idx<m->num_misc_animations; idx++){
2056 required_string("+Misc anim sounds:");
2057 stuff_int(&m->misc_anim_special_sounds[idx][0]);
2058 for(s_idx=0; s_idx<m->misc_anim_special_sounds[idx][0]; s_idx++){
2059 stuff_int(&m->misc_anim_special_sounds[idx][s_idx + 1]);
2062 for(idx=0; idx<m->num_misc_animations; idx++){
2063 // anim sound triggers
2064 required_string("+Misc anim trigger:");
2065 stuff_int(&m->misc_anim_special_trigger[idx][0]);
2066 for(s_idx=0; s_idx<m->misc_anim_special_trigger[idx][0]; s_idx++){
2067 stuff_int(&m->misc_anim_special_trigger[idx][s_idx + 1]);
2070 for(idx=0; idx<m->num_misc_animations; idx++){
2071 // anim sound handles
2072 required_string("+Misc anim handles:");
2073 stuff_int(&m->misc_anim_sound_handles[idx][0]);
2075 for(idx=0; idx<m->num_misc_animations; idx++){
2077 required_string("+Misc anim flags:");
2078 stuff_int(&m->misc_anim_sound_flag[idx][0]);
2082 required_string("+Num Door Animations:");
2083 stuff_int(&m->num_door_animations);
2084 for(idx=0; idx<m->num_door_animations; idx++){
2086 required_string("+Door anim:");
2087 stuff_string(m->door_anim_name[idx], F_NAME, NULL);
2089 for(idx=0; idx<m->num_door_animations; idx++){
2091 required_string("+Door coords:");
2092 stuff_int(&m->door_anim_coords[idx][0]);
2093 stuff_int(&m->door_anim_coords[idx][1]);
2094 stuff_int(&m->door_anim_coords[idx][2]);
2095 stuff_int(&m->door_anim_coords[idx][3]);
2097 for(idx=0; idx<m->num_door_animations; idx++){
2098 // door open and close sounds
2099 required_string("+Door sounds:");
2100 stuff_int(&m->door_sounds[idx][0]);
2101 stuff_int(&m->door_sounds[idx][1]);
2103 for(idx=0; idx<m->num_door_animations; idx++){
2105 required_string("+Door pan:");
2106 stuff_float(&m->door_sound_pan[idx]);
2109 // tooltip y location
2110 required_string("+Tooltip Y:");
2111 stuff_int(&m->region_yval);
2112 for(idx=0; idx<NUM_REGIONS; idx++){
2113 m->region_descript[idx] = NULL;
2117 if(count < NUM_MAIN_HALLS){
2124 Main_hall_defines[GR_640][1].door_sounds[OPTIONS_REGION][0] = SND_VASUDAN_BUP;
2125 Main_hall_defines[GR_640][1].door_sounds[OPTIONS_REGION][1] = SND_VASUDAN_BUP;
2126 Main_hall_defines[GR_1024][1].door_sounds[OPTIONS_REGION][0] = SND_VASUDAN_BUP;
2127 Main_hall_defines[GR_1024][1].door_sounds[OPTIONS_REGION][1] = SND_VASUDAN_BUP;
2129 // set head anim. hehe
2130 strcpy(Main_hall_defines[GR_640][1].door_anim_name[OPTIONS_REGION], "vhallheads");
2131 strcpy(Main_hall_defines[GR_1024][1].door_anim_name[OPTIONS_REGION], "2_vhallheads");
2133 // set the background
2134 strcpy(Main_hall_defines[GR_640][1].bitmap, "vhallhead");
2135 strcpy(Main_hall_defines[GR_1024][1].bitmap, "2_vhallhead");
2139 // make the vasudan main hall funny
2140 void main_hall_vasudan_funny()
2159 vector sun_pos = vmd_zero_vector;
2163 argh = bm_load("sun01");
2164 bm_lock(argh, 16, BMP_TEX_XPARENT);
2169 g3_set_view_matrix(&vmd_zero_vector, &view, 0.5f);
2170 g3_rotate_vertex(&p1, &sun_pos);
2171 g3_project_vertex(&p1);
2172 gr_zbuffer_set(GR_ZBUFF_NONE);
2173 gr_set_bitmap( argh );
2174 g3_draw_bitmap(&p1, 0, 0.05f, TMAP_FLAG_TEXTURED | TMAP_FLAG_XPARENT);