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.5 2002/06/09 04:41:22 relnev
19 * added copyright header
21 * Revision 1.4 2002/06/01 03:32:00 relnev
22 * fix texture loading mistake.
24 * enable some d3d stuff for opengl also
26 * Revision 1.3 2002/05/30 16:55:44 theoddone33
27 * now gets to another screen
29 * Revision 1.2 2002/05/27 22:43:02 theoddone33
30 * Fix more glide symbols
32 * Revision 1.1.1.1 2002/05/03 03:28:09 root
36 * 62 10/28/99 2:04a Jefff
39 * 61 9/15/99 6:28p Dave
40 * No load mission button in RELEASE_REAL
42 * 60 9/13/99 4:52p Dave
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.
49 * 58 9/07/99 6:55p Jefff
50 * added jump-to-campaign-mission cheat
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.
57 * 56 9/06/99 6:38p Dave
58 * Improved CD detection code.
60 * 55 9/06/99 1:30a Dave
61 * Intermediate checkin. Started on enforcing CD-in-drive to play the
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
70 * 53 9/01/99 11:02p Dave
71 * Made head guy look right when not animating.
73 * 52 8/27/99 12:04a Dave
74 * Campaign loop screen.
76 * 51 8/26/99 9:45a Dave
77 * First pass at easter eggs and cheats.
79 * 50 8/25/99 11:57a Jefff
80 * freespace -> freespace 2 in tooltip strings
82 * 49 8/25/99 10:50a Dave
83 * Added music to the mainhall.tbl
85 * 48 8/24/99 8:55p Dave
86 * Make sure nondimming pixels work properly in tech menu.
88 * 47 8/18/99 11:44a Jefff
91 * 46 8/10/99 4:45p Jefff
94 * 45 8/06/99 1:01p Andsager
95 * disable quick start (g) for demo
97 * 44 8/05/99 10:34a Jefff
98 * more mouseover sound fixes
100 * 43 8/04/99 9:12p Andsager
101 * Add campaign room popup allowing restart of campaign in demo.
103 * 42 8/04/99 5:36p Dave
104 * Make glide and D3D switch out properly.
106 * 41 8/04/99 4:35p Jefff
107 * fixed tech room & options sounds playing only once
109 * 40 8/03/99 5:41p Jefff
110 * made "f1 for help" draw after animations, and stop if help overlay
113 * 39 8/03/99 4:42p Jefff
116 * 38 8/03/99 3:48p Jefff
118 * 37 8/02/99 9:13p Dave
121 * 36 8/02/99 2:26p Jefff
122 * "press f1.." text reworked
124 * 35 8/02/99 12:19p Andsager
125 * disable "L" load screen
127 * 34 8/02/99 11:12a Jefff
128 * adjusted tooltip shader stuff for more a more pleasing effect.
130 * 33 7/30/99 6:05p Jefff
131 * added shader behind tooltip text
133 * 32 7/30/99 4:20p Andsager
134 * Added user click sounds to main hall
136 * 31 7/29/99 10:47p Dave
137 * Standardized D3D fogging using vertex fog. Shook out Savage 4 bugs.
139 * 30 7/27/99 6:53p Dave
140 * Hi-res main hall support.
142 * 29 7/16/99 1:49p Dave
143 * 8 bit aabitmaps. yay.
145 * 28 7/15/99 9:20a Andsager
146 * FS2_DEMO initial checkin
148 * 27 7/13/99 1:15p Dave
149 * 32 bit support. Whee!
151 * 26 6/25/99 2:51p Jasons
152 * Changed wording of network error message.
154 * 25 6/21/99 1:30p Alanl
155 * changed main menu music tag
157 * 24 6/19/99 3:56p Dave
158 * Moved main hall definitions into a table file. Whee!
160 * 23 6/11/99 11:13a Dave
161 * last minute changes before press tour build.
163 * 22 5/09/99 8:57p Dave
164 * Final E3 build preparations.
166 * 21 4/25/99 3:02p Dave
167 * Build defines for the E3 build.
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.
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 :)
177 * 18 3/25/99 5:47p Dave
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.
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
189 * 15 2/03/99 11:44a Dave
190 * Fixed d3d transparent textures.
192 * 14 1/30/99 5:08p Dave
193 * More new hi-res stuff.Support for nice D3D textures.
195 * 13 1/27/99 9:56a Dave
196 * Temporary checkin of beam weapons for Dan to make cool sounds.
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.
202 * 11 12/18/98 1:13a Dave
203 * Rough 1024x768 support for Direct3D. Proper detection and usage through
206 * 10 11/30/98 1:07p Dave
207 * 16 bit conversion, first run.
209 * 9 11/20/98 4:08p Dave
210 * Fixed flak effect in multiplayer.
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.
216 * 7 11/19/98 4:57p Dave
217 * Ignore PXO option if IPX is selected.
219 * 6 11/19/98 4:19p Dave
220 * Put IPX sockets back in psnet. Consolidated all multiplayer config
223 * 5 11/05/98 5:55p Dave
224 * Big pass at reducing #includes
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
231 * 3 10/13/98 9:28a Dave
232 * Started neatening up freespace.h. Many variables renamed and
233 * reorganized. Added AlphaColors.[h,cpp]
235 * 2 10/07/98 10:53a Dave
238 * 1 10/07/98 10:49a Dave
240 * 103 10/02/98 3:22p Allender
241 * fix up the -connect option and fix the -port option
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.
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
251 * 100 7/13/98 10:46a Lawrance
252 * Index another localized string
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.
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
266 * 97 6/05/98 9:50a Lawrance
269 * 96 6/01/98 11:43a John
270 * JAS & MK: Classified all strings for localization.
272 * 95 5/22/98 9:02p Allender
273 * remove G key from main hall
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
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.
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
289 * 91 5/12/98 2:46a Dave
290 * Rudimentary communication between Parallax Online and freespace. Can
291 * get and store channel lists.
293 * 90 5/08/98 5:33p Lawrance
294 * check for CD when trying to enter ready room in single player
301 #include "mainhallmenu.h"
305 #include "gamesequence.h"
306 #include "animplay.h"
310 #include "snazzyui.h"
312 #include "audiostr.h"
314 #include "eventmusic.h"
316 #include "contexthelp.h"
320 #include "multiutil.h"
324 #include "playermenu.h"
325 #include "freespace.h"
326 #include "multi_voice.h"
328 #include "alphacolors.h"
330 #include "fishtank.h"
332 // #include "movie.h"
334 // ----------------------------------------------------------------------------
335 // MAIN HALL DATA DEFINES
337 #define MAX_RANDOM_INTERCOM_SOUNDS 10
338 #define NUM_RANDOM_INTERCOM_SOUNDS_0 3
339 #define NUM_RANDOM_INTERCOM_SOUNDS_1 3
341 #define MAX_MISC_ANIMATIONS 10
342 #define NUM_MISC_ANIMATIONS_0 2
343 #define NUM_MISC_ANIMATIONS_1 4
345 #define MAX_DOOR_ANIMATIONS 10
346 #define NUM_DOOR_ANIMATIONS_0 6
347 #define NUM_DOOR_ANIMATIONS_1 6
349 #define MAX_DOOR_SOUNDS 10
350 #define NUM_DOOR_SOUNDS_0 6
351 #define NUM_DOOR_SOUNDS_1 6
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
357 #define NUM_REGIONS 7 // (6 + 1 for multiplayer equivalent of campaign room)
358 typedef struct main_hall_defines {
360 char bitmap[MAX_FILENAME_LEN+1];
361 char mask[MAX_FILENAME_LEN+1];
364 char music[MAX_FILENAME_LEN+1];
366 // intercom defines -------------------
368 // # of intercom sounds
369 int num_random_intercom_sounds;
371 // random (min/max) delays between playing intercom sounds
372 int intercom_delay[MAX_RANDOM_INTERCOM_SOUNDS][2];
374 // intercom sounds themselves
375 int intercom_sounds[MAX_RANDOM_INTERCOM_SOUNDS];
377 // intercom sound pan values
378 float intercom_sound_pan[MAX_RANDOM_INTERCOM_SOUNDS];
381 // misc animations --------------------
383 // # of misc animations
384 int num_misc_animations;
386 // filenames of the misc animations
387 char misc_anim_name[MAX_MISC_ANIMATIONS][MAX_FILENAME_LEN+1];
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];
392 // coords of where to play the misc anim
393 int misc_anim_coords[MAX_MISC_ANIMATIONS][2];
395 // misc anim play modes (see MISC_ANIM_MODE_* above)
396 int misc_anim_modes[MAX_MISC_ANIMATIONS];
398 // panning values for each of the misc anims
399 float misc_anim_sound_pan[MAX_MISC_ANIMATIONS];
401 // [N][0] == # of sounds, [N][1-9] sound index
402 int misc_anim_special_sounds[MAX_MISC_ANIMATIONS][10];
404 // [N][0] == # of triggers, [N][1-9] >= frame num
405 int misc_anim_special_trigger[MAX_MISC_ANIMATIONS][10];
407 // [N][0] == # of handles, [N][1-9] == sound handle num
408 int misc_anim_sound_handles[MAX_MISC_ANIMATIONS][10];
410 // [N][0] == # of handles, [N][1-9] == sound "should" be playing
411 int misc_anim_sound_flag[MAX_MISC_ANIMATIONS][10];
414 // door animations --------------------
416 // # of door animations
417 int num_door_animations;
419 // filenames of the door animations
420 char door_anim_name[MAX_DOOR_ANIMATIONS][MAX_FILENAME_LEN+1];
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];
427 // door sounds ------------------------
432 // sounds for each region (open/close)
433 int door_sounds[MAX_DOOR_SOUNDS][2];
435 // pan values for the door sounds
436 float door_sound_pan[MAX_DOOR_SOUNDS];
439 // region descriptions ----------------
441 // text (tooltip) description
442 char *region_descript[NUM_REGIONS];
444 // y coord of where to draw tooltip text
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];
454 int Vasudan_funny = 0;
455 int Vasudan_funny_plate = -1;
457 char Main_hall_campaign_cheat[512] = "";
459 // ----------------------------------------------------------------------------
460 // MISC interface data
462 // is the main hall inited (for reentrancy)
463 int Main_hall_inited = 0;
465 // handle to the playing music
466 int Main_hall_music_handle = -1;
468 // background bitmap handle
469 int Main_hall_bitmap;
471 // background bitmap mask handle
474 // variable used for automatic netgame starting/joining
475 int Main_hall_netgame_started = 0;
477 // bitmap struct for th background mask bitmap
478 bitmap *Main_hall_mask_bitmap;
480 // actual data for the background mask bitmap
481 ubyte *Main_hall_mask_data;
483 int Main_hall_mask_w, Main_hall_mask_h;
486 // ----------------------------------------------------------------------------
487 // MOUSE clicking stuff
489 // indicates whether a right click occured
490 int Main_hall_right_click;
492 // use this to cycle through the selectable regions instead of the mouse's current region
493 int Main_hall_last_clicked_region;
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;
499 // handle any right clicks which may have occured
500 void main_hall_handle_right_clicks();
503 // ----------------------------------------------------------------------------
504 // RANDOM intercom sounds
507 // next random intercom sound to play
508 int Main_hall_next_intercom_sound = 0;
510 // delay for the next intercom sound
511 int Main_hall_next_intercom_sound_stamp = -1;
513 // handle to any playing instance of a random intercom sound
514 int Main_hall_intercom_sound_handle = -1;
516 // handle any details related to random intercom sounds
517 void main_hall_handle_random_intercom_sounds();
520 // ----------------------------------------------------------------------------
524 // the misc animations themselves
525 anim *Main_hall_misc_anim[MAX_MISC_ANIMATIONS];
527 // the instance of a given misc animation
528 anim_instance *Main_hall_misc_anim_instance[MAX_MISC_ANIMATIONS];
530 // handle starting, stopping and randomizing misc animations
531 void main_hall_handle_misc_anims();
533 // cull any finished misc animation instances
534 void main_hall_cull_misc_anim_instances();
536 // render all playing misc animations
537 void main_hall_render_misc_anims(float frametime);
540 // ----------------------------------------------------------------------------
541 // DOOR animations (not all of these are doors anymore, but they're doorlike _regions_)
543 #define DOOR_TEXT_X 100
544 #define DOOR_TEXT_Y 450
546 // the door animations themselves
547 anim *Main_hall_door_anim[MAX_DOOR_ANIMATIONS];
549 // the instance of a given door animation
550 anim_instance *Main_hall_door_anim_instance[MAX_DOOR_ANIMATIONS];
552 // render all playing door animations
553 void main_hall_render_door_anims(float frametime);
556 // ----------------------------------------------------------------------------
559 #define NUM_MAIN_HALL_REGIONS 10
560 #define NUM_MAIN_HALL_MOUSE_REGIONS 6
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
574 // all the menu regions in the main hall
575 MENU_REGION Main_hall_region[NUM_MAIN_HALL_REGIONS];
577 // # of regions (options) on this screen. parsed from a table
578 int Main_hall_num_options;
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;
585 // set this to skip a frame
586 int Main_hall_frame_skip;
588 // do any necessary processing based upon the mouse location
589 void main_hall_handle_mouse_location(int cur_region);
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);
594 // if the mouse has moved on this region, handle it accordingly
595 void main_hall_mouse_grab_region(int region);
598 // ----------------------------------------------------------------------------
599 // SOUND data / handlers
602 // toaster oven room sound idex
603 #define TOASTER_REGION 3
605 // everyone's favorite desk guardian
606 #define ALLENDER_REGION 4
608 // handles to the sound instances of the doors opening/closing
609 int Main_hall_door_sound_handles[MAX_DOOR_SOUNDS] = {
613 // sound handle for looping ambient sound
614 int Main_hall_ambient_loop = -1;
616 // cull any door sounds that have finished playing
617 void main_hall_cull_door_sounds();
619 // handle starting, stopping and reversing "door" animations
620 void main_hall_handle_region_anims();
623 // ----------------------------------------------------------------------------
624 // warning/notification messages
626 #define MAIN_HALL_NOTIFY_TIME 3500
628 // timestamp for the notification messages
629 int Main_hall_notify_stamp = -1;
631 // text to display as the current notification message
632 char Main_hall_notify_text[300]="";
634 // set the current notification string and the associated timestamp
635 void main_hall_set_notify_string(char *str);
637 // handle any drawing, culling, etc of notification messages
638 void main_hall_notify_do();
641 // ----------------------------------------------------------------------------
645 // upper _RIGHT_ corner for the version text
646 #define MAIN_HALL_VERSION_X 630
647 #define MAIN_HALL_VERSION_Y 467
649 // main hall help overlay ID
650 int Main_hall_overlay_id;
652 // blit the freespace version #
653 void main_hall_blit_version();
655 // blit any necessary tooltips
656 void main_hall_maybe_blit_tooltips();
658 // shader for behind tooltips
659 shader Main_hall_tooltip_shader;
661 // num pixels shader is above/below tooltip text
662 static int Main_hall_tooltip_padding[GR_NUM_RESOLUTIONS] = {
666 static int Main_hall_f1_text_frame = 0;
667 static int F1_text_done = 0;
669 // read in main hall table
670 void main_hall_read_table();
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();
678 // ----------------------------------------------------------------------------
679 // VOICE RECORDING STUFF
682 // are we currently recording voice?
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()
692 error = psnet_get_network_status();
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));
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));
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));
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));
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));
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));
715 case NETWORK_ERROR_NONE:
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));
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));
730 if ( error != NETWORK_ERROR_NONE ){
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) );
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 );
748 // go to the regular join game screen
749 gameseq_post_event( GS_EVENT_MULTI_JOIN_GAME );
753 psnet_use_protocol(Multi_options_g.protocol);
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] = {
763 int Mh_weapon_table_status[GR_NUM_RESOLUTIONS][2] = {
767 void main_hall_blit_table_status()
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]);
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]);
778 // bash the player to a specific mission in a campaign
779 void main_hall_campaign_cheat()
781 char *ret = popup_input(0, XSTR("Enter mission name.\n\n* This will destroy all legitimate progress in this campaign. *", -1));
785 // strcpy(Main_hall_campaign_cheat, ret);
786 mission_campaign_jump_to_mission(ret);
790 // -------------------------------------------------------------------------------------------------------------------
791 // FUNCTION DEFINITIONS BEGIN
794 // initialize the main hall proper
795 void main_hall_init(int main_hall_num)
797 if ( Main_hall_inited ) {
802 char temp[100], whee[100];
804 // read in the main hall table
805 main_hall_read_table();
807 // create the snazzy interface and load up the info from the table
809 read_menu_tbl(NOX("MAIN HALL"), temp, whee, Main_hall_region, &Main_hall_num_options, 0);
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];
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);
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);
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));
835 // remove any multiplayer flags from the game mode
836 Game_mode &= ~(GM_MULTIPLAYER);
838 // set the interface palette
839 #ifndef HARDWARE_ONLY
840 palette_use_bm_palette(Main_hall_bitmap);
843 Main_hall_mask_w = -1;
844 Main_hall_mask_h = -1;
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);
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);
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));
865 // null out the animation instances
866 Main_hall_misc_anim_instance[idx] = NULL;
868 // null out the delay timestamps
869 Main_hall->misc_anim_delay[idx][0] = -1;
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]));
880 // null out the animation instances
881 Main_hall_door_anim_instance[idx] = NULL;
884 // load in help overlay bitmap
885 if(Main_hall == &Main_hall_defines[gr_screen.res][0]) {
886 Main_hall_overlay_id = MH_OVERLAY;
888 Assert(Main_hall == &Main_hall_defines[gr_screen.res][1]);
889 Main_hall_overlay_id = MH2_OVERLAY;
891 help_overlay_load(Main_hall_overlay_id);
892 help_overlay_set_state(Main_hall_overlay_id,0);
894 // check to see if the "very first pilot" flag is set, and load the overlay if so
896 if (Main_hall_f1_text_frame == 0) {
897 Main_hall_help_stamp = timestamp(MAIN_HALL_HELP_TIME);
904 if(Player_select_very_first_pilot) {
905 Main_hall_help_stamp = timestamp(MAIN_HALL_HELP_TIME);
907 // don't display the "press f1" message more than once
908 Player_select_very_first_pilot = 0;
910 Main_hall_help_stamp = -1;
913 Main_hall_region_linger_stamp = -1;
915 strcpy(Main_hall_campaign_cheat, "");
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;
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;
930 // skip the first frame
931 Main_hall_frame_skip = 1;
933 // initialize the music
934 main_hall_start_music();
936 // initialize the main hall notify text
937 Main_hall_notify_stamp = 1;
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;
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]);
949 Main_hall_inited = 1;
951 // determine if we have a right click
952 Main_hall_right_click = mouse_down(MOUSE_RIGHT_BUTTON);
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;
959 Game_mode = GM_NORMAL;
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();
968 void main_hall_exit_game()
970 #if defined(NDEBUG) || defined(INTERPLAYQA)
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));
978 gameseq_post_event(GS_EVENT_QUIT_GAME);
980 main_hall_start_music();
981 main_hall_start_ambient();
984 gameseq_post_event(GS_EVENT_QUIT_GAME);
989 // do a frame for the main hall
990 void main_hall_do(float frametime)
992 int code, key, snazzy_action;
994 // need to ensure ambient is playing, since it may be stopped by a playing movie
995 main_hall_start_ambient();
997 // handle any animation details
998 main_hall_handle_misc_anims();
999 main_hall_handle_region_anims();
1001 // handle any random intercom sound details
1002 main_hall_handle_random_intercom_sounds();
1004 // handle any mouse clicks
1005 main_hall_handle_right_clicks();
1007 // handle any sound details
1008 main_hall_cull_door_sounds();
1010 // process any keypresses/mouse events
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);
1015 extern void game_process_cheats(int k);
1016 game_process_cheats(key);
1020 snazzy_action = SNAZZY_CLICKED;
1026 // movie_play("endprt2b.mve", 0);
1030 // movie_play_two("endprt2a.mve", "endprt2b.mve", 0);
1033 main_hall_campaign_cheat();
1035 case KEY_DEBUGGED + KEY_D:
1036 demo_start_playback("test.fsd");
1043 // do any processing based upon what happened to the snazzy menu
1044 switch (snazzy_action) {
1046 main_hall_handle_mouse_location(code);
1049 case SNAZZY_CLICKED:
1051 // clicked on the exit region
1053 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1054 main_hall_exit_game();
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);
1066 if (Player->flags & PLAYER_FLAGS_IS_MULTI){
1067 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1068 main_hall_do_multi_ready();
1070 if(strlen(Main_hall_campaign_cheat)){
1071 gameseq_post_event(GS_EVENT_CAMPAIGN_CHEAT);
1073 gameseq_post_event(GS_EVENT_NEW_CAMPAIGN);
1075 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
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();
1086 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1087 gameseq_post_event( GS_EVENT_TECH_MENU );
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);
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)
1102 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
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();
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));
1118 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1119 gameseq_post_event(GS_EVENT_CAMPAIGN_ROOM);
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();
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 );
1135 main_hall_set_notify_string(XSTR( "Not a valid multiplayer pilot!!", 367));
1140 // load mission key was pressed
1141 case LOAD_MISSION_REGION:
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));
1150 #ifdef GAME_CD_CHECK
1151 // if ( !game_do_cd_check() ) {
1155 gamesnd_play_iface(SND_IFACE_MOUSE_CLICK);
1156 gameseq_post_event( GS_EVENT_LOAD_MISSION_MENU );
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));
1170 if (Num_recent_missions > 0) {
1171 strncpy( Game_current_mission_filename, Recent_missions[0], MAX_FILENAME_LEN );
1173 mission_load_up_campaign();
1174 strncpy( Game_current_mission_filename, Campaign.missions[0].name, MAX_FILENAME_LEN );
1177 Campaign.current_mission = -1;
1178 gameseq_post_event(GS_EVENT_START_GAME_QUICK);
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 );
1189 // increate the skill level
1190 case SKILL_LEVEL_REGION:
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);
1198 // escape was 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();
1207 help_overlay_set_state(Main_hall_overlay_id,0);
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);
1219 main_hall_handle_mouse_location(-1);
1223 if ( mouse_down(MOUSE_LEFT_BUTTON) ) {
1224 help_overlay_set_state(Main_hall_overlay_id, 0);
1227 // draw the background bitmap
1229 GR_MAYBE_CLEAR_RES(Main_hall_bitmap);
1230 if(Main_hall_bitmap >= 0){
1231 gr_set_bitmap(Main_hall_bitmap);
1235 // draw any pending notification messages
1236 main_hall_notify_do();
1238 // render misc animations
1239 main_hall_render_misc_anims(frametime);
1241 // render door animtions
1242 main_hall_render_door_anims(frametime);
1244 // blit any appropriate tooltips
1245 main_hall_maybe_blit_tooltips();
1250 // process any help "hit f1" timestamps and display any messages if necessary
1251 if (!F1_text_done) {
1252 main_hall_process_help_stuff();
1255 // blit help overlay if active
1256 help_overlay_maybe_blit(Main_hall_overlay_id);
1258 // blit the freespace version #
1259 main_hall_blit_version();
1261 // blit ship and weapon table status
1262 main_hall_blit_table_status();
1264 // if we're in nice D3D texture format
1266 gr_set_color_fast(&Color_white);
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");
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");
1281 gr_string(320, gr_screen.max_h - 30, "D3D 32bit");
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();
1287 } else if(gr_screen.mode == GR_GLIDE){
1289 extern int Glide_voodoo3;
1291 gr_string(320, gr_screen.max_h - 20, "VOODOO 3");
1299 // maybe run the player tips popup
1300 // #if defined(FS2_DEMO) && defined(NDEBUG)
1301 player_tips_popup();
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;
1310 // close the main hall proper
1311 void main_hall_close()
1315 if(!Main_hall_inited){
1319 // unload the main hall bitmap
1320 if(Main_hall_bitmap != -1){
1321 bm_unload(Main_hall_bitmap);
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"));
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;
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;
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;
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]));
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;
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]));
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;
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;
1392 // unload the overlay bitmap
1393 help_overlay_unload(Main_hall_overlay_id);
1395 // close any snazzy menu details
1396 snazzy_menu_close();
1399 palette_restore_palette();
1404 // not inited anymore
1405 Main_hall_inited = 0;
1408 // start the main hall music playing
1409 void main_hall_start_music()
1411 // start a looping ambient sound
1412 main_hall_start_ambient();
1414 // if we have selected no music, then don't do this
1415 if ( Cmdline_freespace_no_music ) {
1419 int main_hall_spooled_music_index = event_music_get_spooled_music_index(Main_hall->music);
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);
1429 nprintf(("Warning", "No music file exists to play music at the main menu!\n"));
1434 // stop the main hall music
1435 void main_hall_stop_music()
1437 if ( Main_hall_music_handle != -1 ) {
1438 audiostream_close_file(Main_hall_music_handle);
1439 Main_hall_music_handle = -1;
1443 // do any necessary instantiation of misc animations
1444 void main_hall_handle_misc_anims()
1448 if(Main_hall_frame_skip)
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])));
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;
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;
1467 Main_hall_misc_anim_instance[idx] = anim_play(&aps);
1469 // kill the timestamp
1470 Main_hall->misc_anim_delay[idx][0] = -1;
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;
1478 // if the anim is playing
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;
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;
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]);
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;
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]);
1509 // start it playing again
1510 anim_play_struct aps;
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;
1516 Main_hall_misc_anim_instance[idx] = anim_play(&aps);
1518 // kill the timestamp
1519 Main_hall->misc_anim_delay[idx][0] = -1;
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;
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;
1535 // render all playing misc animations
1536 void main_hall_render_misc_anims(float frametime)
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);
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
1553 if(Main_hall_misc_anim_instance[idx] != NULL){
1554 anim_render_one(GS_STATE_MAIN_MENU,Main_hall_misc_anim_instance[idx],frametime);
1559 // render all playing door animations
1560 void main_hall_render_door_anims(float frametime)
1564 // render all door animations
1565 for(idx=0;idx<MAX_DOOR_ANIMATIONS;idx++){
1567 if(Main_hall_door_anim_instance[idx] != NULL){
1568 anim_render_one(GS_STATE_MAIN_MENU,Main_hall_door_anim_instance[idx],frametime);
1573 // handle starting, stopping and reversing "door" animations
1574 void main_hall_handle_region_anims()
1578 if(Main_hall_frame_skip)
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;
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;
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]);
1605 // do any necessary processing based upon the mouse location
1606 void main_hall_handle_mouse_location(int cur_region)
1608 if(Main_hall_frame_skip)
1611 if(cur_region > NUM_MAIN_HALL_MOUSE_REGIONS) {
1612 // MWA -- inserted return since Int3() was tripped when hitting L from main
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);
1625 // release the region linger stamp
1626 Main_hall_region_linger_stamp = -1;
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);
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);
1641 // if it was over a region but isn't anymore, release that region
1643 if (Main_hall_mouse_region != -1) {
1644 main_hall_mouse_release_region(Main_hall_mouse_region);
1645 Main_hall_mouse_region = -1;
1647 // release the region linger timestamp
1648 Main_hall_region_linger_stamp = -1;
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)
1656 if(Main_hall_frame_skip){
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]);
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]);
1671 Main_hall_door_sound_handles[region] = snd_play(&Snds_iface[Main_hall->door_sounds[region][1]], Main_hall->door_sound_pan[region]);
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);
1679 // if the mouse has moved on this region, handle it accordingly
1680 void main_hall_mouse_grab_region(int region)
1682 if (Main_hall_frame_skip) {
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;
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;
1695 Main_hall_door_anim_instance[region] = anim_play(&aps);
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]);
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]);
1708 Main_hall_door_sound_handles[region] = snd_play(&Snds_iface[Main_hall->door_sounds[region][0]],Main_hall->door_sound_pan[region]);
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);
1717 // handle any right clicks which may have occured
1718 void main_hall_handle_right_clicks()
1722 if(Main_hall_frame_skip)
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){
1732 new_region = Main_hall_last_clicked_region + 1;
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]);
1737 main_hall_handle_mouse_location(new_region);
1738 Main_hall_last_clicked_region = new_region;
1740 // set the mouse as being clicked
1741 Main_hall_right_click = 1;
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;
1750 // cull any door sounds that have finished playing
1751 void main_hall_cull_door_sounds()
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;
1762 void main_hall_handle_random_intercom_sounds()
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])) );
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))){
1776 Main_hall_intercom_sound_handle = snd_play(&Snds_iface[Main_hall->intercom_sounds[Main_hall_next_intercom_sound]]);
1778 // unset the timestamp
1779 Main_hall_next_intercom_sound_stamp = -1;
1782 // if the sound is playing
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;
1790 Main_hall_next_intercom_sound++;
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])) );
1798 // release the sound handle
1799 Main_hall_intercom_sound_handle = -1;
1804 // set the notification string with its decay timeout
1805 void main_hall_set_notify_string(char *str)
1807 strcpy(Main_hall_notify_text,str);
1808 Main_hall_notify_stamp = timestamp(MAIN_HALL_NOTIFY_TIME);
1811 void main_hall_notify_do()
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;
1821 gr_set_color_fast(&Color_bright);
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);
1829 // start a looping ambient sound for main hall
1830 void main_hall_start_ambient()
1832 int play_ambient_loop = 0;
1834 if ( Main_hall_ambient_loop == -1 ) {
1835 play_ambient_loop = 1;
1837 if ( !snd_is_playing(Main_hall_ambient_loop) ) {
1838 play_ambient_loop = 1;
1842 if ( play_ambient_loop ) {
1843 Main_hall_ambient_loop = snd_play_looping(&Snds_iface[SND_MAIN_HALL_AMBIENT]);
1847 // stop a looping ambient sound for the main hall
1848 void main_hall_stop_ambient()
1850 if ( Main_hall_ambient_loop != -1 ) {
1851 snd_stop(Main_hall_ambient_loop);
1852 Main_hall_ambient_loop = -1;
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()
1860 if ( Main_hall_ambient_loop >= 0 ) {
1861 snd_set_volume(Main_hall_ambient_loop, Snds_iface[SND_MAIN_HALL_AMBIENT].default_volume);
1865 // blit the freespace version #
1866 void main_hall_blit_version()
1868 char version_string[100];
1871 // format the version string
1872 get_version_string(version_string);
1874 // get the length of the string
1875 gr_get_string_size(&w,NULL,version_string);
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);
1882 // blit any necessary tooltips
1883 void main_hall_maybe_blit_tooltips()
1888 // if we're over no region - don't blit anything
1889 if(Main_hall_mouse_region < 0) {
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;
1899 text_index = READY_ROOM_REGION;
1902 text_index = Main_hall_mouse_region;
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]);
1911 gr_set_shader(&Main_hall_tooltip_shader);
1912 gr_shade(0, shader_y, gr_screen.clip_width, (gr_screen.clip_height - shader_y));
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]);
1920 void main_hall_process_help_stuff()
1925 // if the timestamp has popped, don't do anything
1926 if(Main_hall_help_stamp == -1) {
1930 // if the timestamp has popped, advance frame
1931 if(timestamp_elapsed(Main_hall_help_stamp)) {
1932 Main_hall_f1_text_frame++;
1935 // otherwise print out the message
1936 strcpy(str, XSTR( "Press F1 for help", 371));
1937 gr_get_string_size(&w, &h, str);
1939 int y_anim_offset = Main_hall_f1_text_frame;
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;
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);
1955 // what main hall we're on (should be 0 or 1)
1958 // only 1 of 2 main halls
1959 if(Main_hall == &Main_hall_defines[gr_screen.res][0]){
1966 // read in main hall table
1967 void main_hall_read_table()
1969 main_hall_defines *m, temp;
1970 int count, idx, s_idx, m_idx;
1973 read_file_text("mainhall.tbl");
1978 while(!optional_string("#end")){
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){
1986 m = &Main_hall_defines[m_idx][count];
1990 required_string("$Main Hall");
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);
1998 required_string("+Music:");
1999 stuff_string(m->music, F_NAME, NULL, MAX_FILENAME_LEN);
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++){
2007 required_string("+Intercom delay:");
2008 stuff_int(&m->intercom_delay[idx][0]);
2009 stuff_int(&m->intercom_delay[idx][1]);
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]);
2016 for(idx=0; idx<m->num_random_intercom_sounds; idx++){
2018 required_string("+Intercom pan:");
2019 stuff_float(&m->intercom_sound_pan[idx]);
2023 required_string("+Num Misc Animations:");
2024 stuff_int(&m->num_misc_animations);
2025 for(idx=0; idx<m->num_misc_animations; idx++){
2027 required_string("+Misc anim:");
2028 stuff_string(m->misc_anim_name[idx], F_NAME, NULL);
2030 for(idx=0; idx<m->num_misc_animations; idx++){
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]);
2037 for(idx=0; idx<m->num_misc_animations; idx++){
2039 required_string("+Misc anim coords:");
2040 stuff_int(&m->misc_anim_coords[idx][0]);
2041 stuff_int(&m->misc_anim_coords[idx][1]);
2043 for(idx=0; idx<m->num_misc_animations; idx++){
2045 required_string("+Misc anim mode:");
2046 stuff_int(&m->misc_anim_modes[idx]);
2048 for(idx=0; idx<m->num_misc_animations; idx++){
2050 required_string("+Misc anim pan:");
2051 stuff_float(&m->misc_anim_sound_pan[idx]);
2053 for(idx=0; idx<m->num_misc_animations; idx++){
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]);
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]);
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]);
2074 for(idx=0; idx<m->num_misc_animations; idx++){
2076 required_string("+Misc anim flags:");
2077 stuff_int(&m->misc_anim_sound_flag[idx][0]);
2081 required_string("+Num Door Animations:");
2082 stuff_int(&m->num_door_animations);
2083 for(idx=0; idx<m->num_door_animations; idx++){
2085 required_string("+Door anim:");
2086 stuff_string(m->door_anim_name[idx], F_NAME, NULL);
2088 for(idx=0; idx<m->num_door_animations; idx++){
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]);
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]);
2102 for(idx=0; idx<m->num_door_animations; idx++){
2104 required_string("+Door pan:");
2105 stuff_float(&m->door_sound_pan[idx]);
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;
2116 if(count < NUM_MAIN_HALLS){
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;
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");
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");
2138 // make the vasudan main hall funny
2139 void main_hall_vasudan_funny()
2158 vector sun_pos = vmd_zero_vector;
2162 argh = bm_load("sun01");
2163 bm_lock(argh, 16, BMP_TEX_XPARENT);
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);