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/Freespace2/FreeSpace.cpp $
18 * Revision 1.31 2003/06/11 18:30:32 taylor
21 * Revision 1.30 2003/06/03 04:00:39 taylor
22 * Polish language support (Janusz Dziemidowicz)
24 * Revision 1.29 2003/05/25 02:30:42 taylor
27 * Revision 1.28 2003/05/18 03:55:30 taylor
28 * automatic language selection support
30 * Revision 1.27 2003/03/03 04:54:44 theoddone33
31 * Commit Taylor's ShowFPS fix
33 * Revision 1.26 2003/02/20 17:41:07 theoddone33
34 * Userdir patch from Taylor Richards
36 * Revision 1.25 2003/01/30 19:54:10 relnev
37 * ini config option for the frames per second counter (Taylor Richards)
39 * Revision 1.24 2002/08/31 01:39:13 theoddone33
40 * Speed up the renderer a tad
42 * Revision 1.23 2002/08/04 02:31:00 relnev
43 * make numlock not overlap with pause
45 * Revision 1.22 2002/08/02 23:07:03 relnev
46 * don't access the mouse in standalone mode
48 * Revision 1.21 2002/07/28 05:05:08 relnev
49 * removed some old stuff
51 * Revision 1.20 2002/07/24 00:20:41 relnev
54 * Revision 1.19 2002/06/17 06:33:08 relnev
55 * ryan's struct patch for gcc 2.95
57 * Revision 1.18 2002/06/16 04:46:33 relnev
58 * set up correct checksums for demo
60 * Revision 1.17 2002/06/09 04:41:17 relnev
61 * added copyright header
63 * Revision 1.16 2002/06/09 03:16:04 relnev
66 * removed unneeded asm, old sdl 2d setup.
68 * fixed crash caused by opengl_get_region.
70 * Revision 1.15 2002/06/05 08:05:28 relnev
71 * stub/warning removal.
73 * reworked the sound code.
75 * Revision 1.14 2002/06/05 04:03:32 relnev
76 * finished cfilesystem.
78 * removed some old code.
80 * fixed mouse save off-by-one.
84 * Revision 1.13 2002/06/02 04:26:34 relnev
87 * Revision 1.12 2002/06/02 00:31:35 relnev
88 * implemented osregistry
90 * Revision 1.11 2002/06/01 09:00:34 relnev
91 * silly debug memmanager
93 * Revision 1.10 2002/06/01 07:12:32 relnev
94 * a few NDEBUG updates.
96 * removed a few warnings.
98 * Revision 1.9 2002/05/31 03:05:59 relnev
101 * Revision 1.8 2002/05/29 02:52:32 theoddone33
102 * Enable OpenGL renderer
104 * Revision 1.7 2002/05/28 08:52:03 relnev
105 * implemented two assembly stubs.
107 * cleaned up a few warnings.
109 * added a little demo hackery to make it progress a little farther.
111 * Revision 1.6 2002/05/28 06:28:20 theoddone33
112 * Filesystem mods, actually reads some data files now
114 * Revision 1.5 2002/05/28 04:07:28 theoddone33
115 * New graphics stubbing arrangement
117 * Revision 1.4 2002/05/27 22:46:52 theoddone33
118 * Remove more undefined symbols
120 * Revision 1.3 2002/05/26 23:31:18 relnev
121 * added a few files that needed to be compiled
123 * freespace.cpp: now compiles
125 * Revision 1.2 2002/05/07 03:16:44 theoddone33
126 * The Great Newline Fix
128 * Revision 1.1.1.1 2002/05/03 03:28:09 root
132 * 201 6/16/00 3:15p Jefff
133 * sim of the year dvd version changes, a few german soty localization
136 * 200 11/03/99 11:06a Jefff
139 * 199 10/26/99 5:07p Jamest
140 * fixed jeffs dumb debug code
142 * 198 10/25/99 5:53p Jefff
143 * call control_config_common_init() on startup
145 * 197 10/14/99 10:18a Daveb
146 * Fixed incorrect CD checking problem on standalone server.
148 * 196 10/13/99 9:22a Daveb
149 * Fixed Fred jumpnode placing bug. Fixed 1024 glide tiled texture problem
150 * related to movies. Fixed launcher spawning from PXO screen.
152 * 195 10/06/99 11:05a Jefff
153 * new oem upsell 3 hotspot coords
155 * 194 10/06/99 10:31a Jefff
158 * 193 10/01/99 9:10a Daveb
161 * 192 9/15/99 4:57a Dave
162 * Updated ships.tbl checksum
164 * 191 9/15/99 3:58a Dave
165 * Removed framerate warning at all times.
167 * 190 9/15/99 3:16a Dave
168 * Remove mt-011.fs2 from the builtin mission list.
170 * 189 9/15/99 1:45a Dave
171 * Don't init joystick on standalone. Fixed campaign mode on standalone.
172 * Fixed no-score-report problem in TvT
174 * 188 9/14/99 6:08a Dave
175 * Updated (final) single, multi, and campaign list.
177 * 187 9/14/99 3:26a Dave
178 * Fixed laser fogging problem in nebula (D3D)> Fixed multiplayer
179 * respawn-too-early problem. Made a few crash points safe.
181 * 186 9/13/99 4:52p Dave
184 * 185 9/12/99 8:09p Dave
185 * Fixed problem where skip-training button would cause mission messages
186 * not to get paged out for the current mission.
188 * 184 9/10/99 11:53a Dave
189 * Shutdown graphics before sound to eliminate apparent lockups when
190 * Directsound decides to be lame. Fix TOPMOST problem with D3D windows.
192 * 183 9/09/99 11:40p Dave
193 * Handle an Assert() in beam code. Added supernova sounds. Play the right
194 * 2 end movies properly, based upon what the player did in the mission.
196 * 182 9/08/99 10:29p Dave
197 * Make beam sound pausing and unpausing much safer.
199 * 181 9/08/99 10:01p Dave
200 * Make sure game won't run in a drive's root directory. Make sure
201 * standalone routes suqad war messages properly to the host.
203 * 180 9/08/99 3:22p Dave
204 * Updated builtin mission list.
206 * 179 9/08/99 12:01p Jefff
207 * fixed Game_builtin_mission_list typo on Training-2.fs2
209 * 178 9/08/99 9:48a Andsager
210 * Add force feedback for engine wash.
212 * 177 9/07/99 4:01p Dave
213 * Fixed up a string.tbl paroblem (self destruct message). Make sure IPX
214 * does everything properly (setting up address when binding). Remove
215 * black rectangle background from UI_INPUTBOX.
217 * 176 9/13/99 2:40a Dave
218 * Comment in full 80 minute CD check for RELEASE_REAL builds.
220 * 175 9/06/99 6:38p Dave
221 * Improved CD detection code.
223 * 174 9/06/99 1:30a Dave
224 * Intermediate checkin. Started on enforcing CD-in-drive to play the
227 * 173 9/06/99 1:16a Dave
228 * Make sure the user sees the intro movie.
230 * 172 9/04/99 8:00p Dave
231 * Fixed up 1024 and 32 bit movie support.
233 * 171 9/03/99 1:32a Dave
234 * CD checking by act. Added support to play 2 cutscenes in a row
235 * seamlessly. Fixed super low level cfile bug related to files in the
236 * root directory of a CD. Added cheat code to set campaign mission # in
239 * 170 9/01/99 10:49p Dave
240 * Added nice SquadWar checkbox to the client join wait screen.
242 * 169 9/01/99 10:14a Dave
245 * 168 8/29/99 4:51p Dave
246 * Fixed damaged checkin.
248 * 167 8/29/99 4:18p Andsager
249 * New "burst" limit for friendly damage. Also credit more damage done
250 * against large friendly ships.
252 * 166 8/27/99 6:38p Alanl
253 * crush the blasted repeating messages bug
255 * 164 8/26/99 9:09p Dave
256 * Force framerate check in everything but a RELEASE_REAL build.
258 * 163 8/26/99 9:45a Dave
259 * First pass at easter eggs and cheats.
261 * 162 8/24/99 8:55p Dave
262 * Make sure nondimming pixels work properly in tech menu.
264 * 161 8/24/99 1:49a Dave
265 * Fixed client-side afterburner stuttering. Added checkbox for no version
266 * checking on PXO join. Made button info passing more friendly between
269 * 160 8/22/99 5:53p Dave
270 * Scoring fixes. Added self destruct key. Put callsigns in the logfile
271 * instead of ship designations for multiplayer players.
273 * 159 8/22/99 1:19p Dave
274 * Fixed up http proxy code. Cleaned up scoring code. Reverse the order in
275 * which d3d cards are detected.
277 * 158 8/20/99 2:09p Dave
278 * PXO banner cycling.
280 * 157 8/19/99 10:59a Dave
281 * Packet loss detection.
283 * 156 8/19/99 10:12a Alanl
284 * preload mission-specific messages on machines greater than 48MB
286 * 155 8/16/99 4:04p Dave
287 * Big honking checkin.
289 * 154 8/11/99 5:54p Dave
290 * Fixed collision problem. Fixed standalone ghost problem.
292 * 153 8/10/99 7:59p Jefff
295 * 152 8/10/99 6:54p Dave
296 * Mad optimizations. Added paging to the nebula effect.
298 * 151 8/10/99 3:44p Jefff
299 * loads Intelligence information on startup
301 * 150 8/09/99 3:47p Dave
302 * Fixed incorrect nebula regeneration. Default HUD to low-contrast in
303 * non-nebula missions.
305 * 149 8/09/99 2:21p Andsager
306 * Fix patching from multiplayer direct to launcher update tab.
308 * 148 8/09/99 10:36a Dave
309 * Version info for game.
311 * 147 8/06/99 9:46p Dave
312 * Hopefully final changes for the demo.
314 * 146 8/06/99 3:34p Andsager
315 * Make title version info "(D)" -> "D" show up nicely
317 * 145 8/06/99 2:59p Adamp
318 * Fixed NT launcher/update problem.
320 * 144 8/06/99 1:52p Dave
321 * Bumped up MAX_BITMAPS for the demo.
323 * 143 8/06/99 12:17p Andsager
324 * Demo: down to just 1 demo dog
326 * 142 8/05/99 9:39p Dave
327 * Yet another new checksum.
329 * 141 8/05/99 6:19p Dave
330 * New demo checksums.
332 * 140 8/05/99 5:31p Andsager
333 * Up demo version 1.01
335 * 139 8/05/99 4:22p Andsager
336 * No time limit on upsell screens. Reverse order of display of upsell
339 * 138 8/05/99 4:17p Dave
340 * Tweaks to client interpolation.
342 * 137 8/05/99 3:52p Danw
344 * 136 8/05/99 3:01p Danw
346 * 135 8/05/99 2:43a Anoop
347 * removed duplicate definition.
349 * 134 8/05/99 2:13a Dave
352 * 133 8/05/99 2:05a Dave
355 * 132 8/05/99 1:22a Andsager
358 * 131 8/04/99 9:51p Andsager
359 * Add title screen to demo
361 * 130 8/04/99 6:47p Jefff
362 * fixed link error resulting from #ifdefs
364 * 129 8/04/99 6:26p Dave
365 * Updated ship tbl checksum.
367 * 128 8/04/99 5:40p Andsager
368 * Add multiple demo dogs
370 * 127 8/04/99 5:36p Andsager
371 * Show upsell screens at end of demo campaign before returning to main
374 * 126 8/04/99 11:42a Danw
375 * tone down EAX reverb
377 * 125 8/04/99 11:23a Dave
378 * Updated demo checksums.
380 * 124 8/03/99 11:02p Dave
381 * Maybe fixed sync problems in multiplayer.
383 * 123 8/03/99 6:21p Jefff
386 * 122 8/03/99 3:44p Andsager
387 * Launch laucher if trying to run FS without first having configured
390 * 121 8/03/99 12:45p Dave
393 * 120 8/02/99 9:13p Dave
396 * 119 7/30/99 10:31p Dave
397 * Added comm menu to the configurable hud files.
399 * 118 7/30/99 5:17p Andsager
400 * first fs2demo checksums
402 * 117 7/29/99 3:09p Anoop
404 * 116 7/29/99 12:05a Dave
405 * Nebula speed optimizations.
407 * 115 7/27/99 8:59a Andsager
408 * Make major, minor version consistent for all builds. Only show major
409 * and minor for launcher update window.
411 * 114 7/26/99 5:50p Dave
412 * Revised ingame join. Better? We'll see....
414 * 113 7/26/99 5:27p Andsager
415 * Add training mission as builtin to demo build
417 * 112 7/24/99 1:54p Dave
418 * Hud text flash gauge. Reworked dead popup to use 4 buttons in red-alert
421 * 111 7/22/99 4:00p Dave
422 * Fixed beam weapon muzzle glow rendering. Externalized hud shield info.
424 * 110 7/21/99 8:10p Dave
425 * First run of supernova effect.
427 * 109 7/20/99 1:49p Dave
428 * Peter Drake build. Fixed some release build warnings.
430 * 108 7/19/99 2:26p Andsager
431 * set demo multiplayer missions
433 * 107 7/18/99 5:19p Dave
434 * Jump node icon. Fixed debris fogging. Framerate warning stuff.
436 * 106 7/16/99 1:50p Dave
437 * 8 bit aabitmaps. yay.
439 * 105 7/15/99 3:07p Dave
440 * 32 bit detection support. Mouse coord commandline.
442 * 104 7/15/99 2:13p Dave
443 * Added 32 bit detection.
445 * 103 7/15/99 9:20a Andsager
446 * FS2_DEMO initial checkin
448 * 102 7/14/99 11:02a Dave
449 * Skill level default back to easy. Blech.
451 * 101 7/09/99 5:54p Dave
452 * Seperated cruiser types into individual types. Added tons of new
453 * briefing icons. Campaign screen.
455 * 100 7/08/99 4:43p Andsager
456 * New check for sparky_hi and print if not found.
458 * 99 7/08/99 10:53a Dave
459 * New multiplayer interpolation scheme. Not 100% done yet, but still
460 * better than the old way.
462 * 98 7/06/99 4:24p Dave
463 * Mid-level checkin. Starting on some potentially cool multiplayer
466 * 97 7/06/99 3:35p Andsager
467 * Allow movie to play before red alert mission.
469 * 96 7/03/99 5:50p Dave
470 * Make rotated bitmaps draw properly in padlock views.
472 * 95 7/02/99 9:55p Dave
473 * Player engine wash sound.
475 * 94 7/02/99 4:30p Dave
476 * Much more sophisticated lightning support.
478 * 93 6/29/99 7:52p Dave
479 * Put in exception handling in FS2.
481 * 92 6/22/99 9:37p Dave
482 * Put in pof spewing.
484 * 91 6/16/99 4:06p Dave
485 * New pilot info popup. Added new draw-bitmap-as-poly function.
487 * 90 6/15/99 1:56p Andsager
488 * For release builds, allow start up in high res only with
491 * 89 6/15/99 9:34a Dave
492 * Fixed key checking in single threaded version of the stamp notification
495 * 88 6/09/99 2:55p Andsager
496 * Allow multiple asteroid subtypes (of large, medium, small) and follow
499 * 87 6/08/99 1:14a Dave
500 * Multi colored hud test.
502 * 86 6/04/99 9:52a Dave
503 * Fixed some rendering problems.
505 * 85 6/03/99 10:15p Dave
506 * Put in temporary main hall screen.
508 * 84 6/02/99 6:18p Dave
509 * Fixed TNT lockup problems! Wheeeee!
511 * 83 6/01/99 3:52p Dave
512 * View footage screen. Fixed xstrings to not display the & symbol. Popup,
513 * dead popup, pxo find player popup, pxo private room popup.
515 * 82 5/26/99 1:28p Jasenw
516 * changed coords for loading ani
518 * 81 5/26/99 11:46a Dave
519 * Added ship-blasting lighting and made the randomization of lighting
520 * much more customizable.
522 * 80 5/24/99 5:45p Dave
523 * Added detail levels to the nebula, with a decent speedup. Split nebula
524 * lightning into its own section.
542 #include "systemvars.h"
547 #include "starfield.h"
548 #include "lighting.h"
553 #include "fireballs.h"
557 #include "floating.h"
558 #include "gamesequence.h"
560 #include "optionsmenu.h"
561 #include "playermenu.h"
562 #include "trainingmenu.h"
563 #include "techmenu.h"
566 #include "hudmessage.h"
568 #include "missiongoals.h"
569 #include "missionparse.h"
574 #include "multiutil.h"
575 #include "multimsgs.h"
579 #include "freespace.h"
580 #include "managepilot.h"
582 #include "contexthelp.h"
585 #include "missionbrief.h"
586 #include "missiondebrief.h"
588 #include "missionshipchoice.h"
590 #include "hudconfig.h"
591 #include "controlsconfig.h"
592 #include "missionmessage.h"
593 #include "missiontraining.h"
595 #include "hudtarget.h"
597 #include "eventmusic.h"
598 #include "animplay.h"
599 #include "missionweaponchoice.h"
600 #include "missionlog.h"
601 #include "audiostr.h"
603 #include "missioncampaign.h"
605 #include "missionhotkey.h"
606 #include "objectsnd.h"
607 #include "cmeasure.h"
609 #include "linklist.h"
610 #include "shockwave.h"
611 #include "afterburner.h"
616 #include "stand_gui.h"
617 #include "pcxutils.h"
618 #include "hudtargetbox.h"
619 #include "multi_xfer.h"
620 #include "hudescort.h"
621 #include "multiutil.h"
624 #include "multiteamselect.h"
627 #include "readyroom.h"
628 #include "mainhallmenu.h"
629 #include "multilag.h"
631 #include "particle.h"
633 #include "multi_ingame.h"
634 #include "snazzyui.h"
635 #include "asteroid.h"
636 #include "popupdead.h"
637 #include "multi_voice.h"
638 #include "missioncmdbrief.h"
639 #include "redalert.h"
640 #include "gameplayhelp.h"
641 #include "multilag.h"
642 #include "staticrand.h"
643 #include "multi_pmsg.h"
644 #include "levelpaging.h"
645 #include "observer.h"
646 #include "multi_pause.h"
647 #include "multi_endgame.h"
648 #include "cutscenes.h"
649 #include "multi_respawn.h"
651 #include "multi_obj.h"
652 #include "multi_log.h"
654 #include "localize.h"
655 #include "osregistry.h"
656 #include "barracks.h"
657 #include "missionpause.h"
659 #include "alphacolors.h"
660 #include "objcollide.h"
663 #include "neblightning.h"
664 #include "shipcontrails.h"
667 #include "multi_dogfight.h"
668 #include "multi_rate.h"
669 #include "muzzleflash.h"
673 #include "mainhalltemp.h"
674 #include "exceptionhandler.h"
678 #include "supernova.h"
679 #include "hudshield.h"
680 // #include "names.h"
682 #include "missionloopbrief.h"
686 #error macro FRED is defined when trying to build release Fred. Please undefine FRED macro in build settings
692 // 1.00.04 5/26/98 MWA -- going final (12 pm)
693 // 1.00.03 5/26/98 MWA -- going final (3 am)
694 // 1.00.02 5/25/98 MWA -- going final
695 // 1.00.01 5/25/98 MWA -- going final
696 // 0.90 5/21/98 MWA -- getting ready for final.
697 // 0.10 4/9/98. Set by MK.
699 // Demo version: (obsolete since DEMO codebase split from tree)
700 // 0.03 4/10/98 AL. Interplay rev
701 // 0.02 4/8/98 MK. Increased when this system was modified.
702 // 0.01 4/7/98? AL. First release to Interplay QA.
705 // 1.00 5/28/98 AL. First release to Interplay QA.
707 void game_level_init(int seed = -1);
708 void game_post_level_init();
709 void game_do_frame();
710 void game_update_missiontime(); // called from game_do_frame() and navmap_do_frame()
711 void game_reset_time();
712 void game_show_framerate(); // draws framerate in lower right corner
714 int Game_no_clear = 0;
716 int Pofview_running = 0;
717 int Nebedit_running = 0;
719 typedef struct big_expl_flash {
720 float max_flash_intensity; // max intensity
721 float cur_flash_intensity; // cur intensity
722 int flash_start; // start time
725 #define FRAME_FILTER 16
727 #define DEFAULT_SKILL_LEVEL 1
728 int Game_skill_level = DEFAULT_SKILL_LEVEL;
730 #define VIEWER_ZOOM_DEFAULT 0.75f // Default viewer zoom, 0.625 as per multi-lateral agreement on 3/24/97
731 float Viewer_zoom = VIEWER_ZOOM_DEFAULT;
733 #define EXE_FNAME ("fs2.exe")
734 #define LAUNCHER_FNAME ("freespace2.exe")
736 // JAS: Code for warphole camera.
737 // Needs to be cleaned up.
738 vector Camera_pos = { 0.0f, 0.0f, 0.0f };
739 vector Camera_velocity = { 0.0f, 0.0f, 0.0f };
740 vector Camera_desired_velocity = { 0.0f, 0.0f, 0.0f };
741 matrix Camera_orient = IDENTITY_MATRIX;
742 float Camera_damping = 1.0f;
743 float Camera_time = 0.0f;
744 float Warpout_time = 0.0f;
745 int Warpout_forced = 0; // Set if this is a forced warpout that cannot be cancelled.
746 int Warpout_sound = -1;
748 int Use_joy_mouse = 0;
749 int Use_palette_flash = 1;
751 int Use_fullscreen_at_startup = 0;
753 int Show_area_effect = 0;
754 object *Last_view_target = NULL;
756 int dogfight_blown = 0;
759 float frametimes[FRAME_FILTER];
760 float frametotal = 0.0f;
764 int Show_framerate = 0;
766 int Show_framerate = 1;
769 int Framerate_cap = 120;
772 int Show_target_debug_info = 0;
773 int Show_target_weapons = 0;
777 static int Show_player_pos = 0; // debug console command to show player world pos on HUD
780 int Debug_octant = -1;
782 fix Game_time_compression = F1_0;
784 // if the ships.tbl the player has is valid
785 int Game_ships_tbl_valid = 0;
787 // if the weapons.tbl the player has is valid
788 int Game_weapons_tbl_valid = 0;
792 extern int Player_attacking_enabled;
796 int Pre_player_entry;
798 int Fred_running = 0;
799 char Game_current_mission_filename[MAX_FILENAME_LEN];
800 int game_single_step = 0;
801 int last_single_step=0;
803 extern int MSG_WINDOW_X_START; // used to position mission_time and shields output
804 extern int MSG_WINDOW_Y_START;
805 extern int MSG_WINDOW_HEIGHT;
807 int game_zbuffer = 1;
808 //static int Game_music_paused;
809 static int Game_paused;
813 #define EXPIRE_BAD_CHECKSUM 1
814 #define EXPIRE_BAD_TIME 2
816 extern void ssm_init();
817 extern void ssm_level_init();
818 extern void ssm_process();
820 // static variable to contain the time this version was built
821 // commented out for now until
822 // I figure out how to get the username into the file
823 //LOCAL char freespace_build_time[] = "Compiled on:"__DATE__" "__TIME__" by "__USER__;
825 // defines and variables used for dumping frame for making trailers.
827 int Debug_dump_frames = 0; // Set to 0 to not dump frames, else equal hz to dump. (15 or 30 probably)
828 int Debug_dump_trigger = 0;
829 int Debug_dump_frame_count;
830 int Debug_dump_frame_num = 0;
831 #define DUMP_BUFFER_NUM_FRAMES 1 // store every 15 frames
834 // amount of time to wait after the player has died before we display the death died popup
835 #define PLAYER_DIED_POPUP_WAIT 2500
836 int Player_died_popup_wait = -1;
837 int Player_multi_died_check = -1;
839 // builtin mission list stuff
841 int Game_builtin_mission_count = 6;
842 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
843 { "SPDemo-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
844 { "SPDemo-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
845 { "DemoTrain.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
846 { "Demo.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE), "" },
847 { "MPDemo-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
848 { "Demo-DOG-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
850 #elif defined(FS1_DEMO)
851 int Game_builtin_mission_count = 5;
852 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
853 { "btmdemo.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
854 { "demo.fsc", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE), "" },
855 { "demo01.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
856 { "demo02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
857 { "demo02b.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
859 #elif defined(PD_BUILD)
860 int Game_builtin_mission_count = 4;
861 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
862 { "sm1-01.fs2", (FSB_FROM_VOLITION), "" },
863 { "sm1-05.fs2", (FSB_FROM_VOLITION), "" },
864 { "sm1-01", (FSB_FROM_VOLITION), "" },
865 { "sm1-05", (FSB_FROM_VOLITION), "" },
867 #elif defined(MULTIPLAYER_BETA)
868 int Game_builtin_mission_count = 17;
869 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
871 { "md-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
872 { "md-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
873 { "md-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
874 { "md-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
875 { "md-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
876 { "md-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
877 { "md-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
878 { "mt-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
879 { "mt-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
880 { "m-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
881 { "m-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
882 { "m-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
883 { "templar-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
884 { "templar-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
885 { "templar-03a.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
886 { "templar-04a.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
887 { "templar.fc2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
889 #elif defined(OEM_BUILD)
890 int Game_builtin_mission_count = 17;
891 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
892 // oem version - act 1 only
893 { "freespace2oem.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE), "" },
896 { "sm1-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
897 { "sm1-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
898 { "sm1-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
899 { "sm1-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
900 { "sm1-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
901 { "sm1-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
902 { "sm1-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
903 { "sm1-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
904 { "sm1-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
905 { "sm1-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
906 { "training-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
907 { "training-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
908 { "training-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
909 { "tsm-104.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
910 { "tsm-105.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
911 { "tsm-106.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 }
913 #elif defined(MAKE_FS1)
914 int Game_builtin_mission_count = 125;
915 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
916 // single player campaign
917 { "freespace.fsc", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE), "" },
920 { "sm1-01.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
921 { "sm1-02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
922 { "sm1-03a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
923 { "sm1-04a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
924 { "sm1-05a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
925 { "sm1-06a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
926 { "sm1-07a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
927 { "sm1-08a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
928 { "sm1-09a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
929 { "sm1-10a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
932 { "sm2-01a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
933 { "sm2-02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
934 { "sm2-03a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
935 { "sm2-04a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
936 { "sm2-05a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
937 { "sm2-06a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
938 { "sm2-07a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
939 { "sm2-08a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
940 { "sm2-09a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
941 { "sm2-10a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
944 { "sm3-01a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
945 { "sm3-02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
946 { "sm3-03a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
947 { "sm3-04a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
948 { "sm3-05a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
949 { "sm3-06a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
950 { "sm3-07a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
951 { "sm3-08a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
952 { "sm3-09a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
955 { "t-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
956 { "v-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
957 { "s-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
960 { "btm-01.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
961 { "btm-02.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
962 { "btm-03.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
963 { "btm-04.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
964 { "btm-05.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
967 { "m-hope.fsc", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
968 { "m-altair.fsc", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
970 { "m-v-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
971 { "m-va.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
972 { "m-unstoppable.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
973 { "m-t-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
974 { "m-s-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
975 { "m-rescue.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
976 { "m-pain.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
977 { "m-orecovery.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
978 { "mm3-01a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
979 { "mm3-02a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
980 { "mm3-03a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
981 { "mm3-04a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
982 { "mm3-05a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
983 { "mm3-06a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
984 { "m-guardduty.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
985 { "m-gate.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
986 { "m-duel.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
987 { "m-convoyassault.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
988 { "m-clash.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
990 // SilentThreat missions
991 // Main SilentThreat campaign
992 { "SilentThreat.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN_FILE), "" },
994 { "md-01.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
995 { "md-02.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
996 { "md-03.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
997 { "md-04.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
998 { "md-05.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
999 { "md-06.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1000 { "md-07.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1001 { "md-08.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1002 { "md-09.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1003 { "md-10.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1004 { "md-11.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1005 { "md-12.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1007 // SilentThreat Part 1 - multi-coop
1008 { "ST-Part1.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1010 { "stmm-01.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1011 { "stmm-02.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1012 { "stmm-03.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1014 // SilentThreat Part 2 - multi-coop
1015 { "ST-Part2.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1017 { "stmm-04.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1018 { "stmm-05.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1019 { "stmm-06.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1021 // SilentThreat Part 3 - multi-coop
1022 { "ST-Part3.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1024 { "stmm-07.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1025 { "stmm-08.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1026 { "stmm-09.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1028 // SilentThreat Part 4 - multi-coop
1029 { "ST-Part4.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1031 { "stmm-10.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1032 { "stmm-11.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1033 { "stmm-12.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1035 // multiplayer missions
1036 { "mdmm-01.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI), "" },
1037 { "mdmm-02.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI), "" },
1038 { "mdmm-03.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI), "" },
1039 { "mdmm-04.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI), "" },
1040 // user supplied missions
1041 { "mdu-02.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1042 { "mdu-03.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1043 { "mdu-04.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1044 { "mdu-05.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1045 { "mdu-06.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1046 { "mdu-07.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1047 { "mdu-08.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1048 { "mdu-09.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1049 { "mdu-10.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1050 { "mdu-11.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1051 { "mdu-12.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1052 { "mdu-13.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1053 { "mdu-14.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1054 { "mdu-15.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1055 { "mdu-16.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1056 { "mdu-17.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1057 { "mdu-18.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1058 { "mdu-19.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1059 { "mdu-20.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1060 { "mdu-21.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1061 { "mdu-22.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1062 { "mdu-23.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1063 { "mdu-24.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1064 { "mdu-25.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1065 { "mdu-26.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1066 { "mdu-27.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1067 { "mdu-28.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1068 { "mdu-29.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1069 { "mdu-30.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1070 { "mdu-31.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1071 { "mdumm-01.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1072 { "mdumm-02.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1075 int Game_builtin_mission_count = 92;
1076 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
1077 // single player campaign
1078 { "freespace2.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE), "" },
1081 { "sm1-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1082 { "sm1-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1083 { "sm1-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1084 { "sm1-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1085 { "sm1-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1086 { "sm1-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1087 { "sm1-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1088 { "sm1-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1089 { "sm1-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1090 { "sm1-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1091 { "loop1-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1092 { "loop1-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1093 { "loop1-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1094 { "training-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1095 { "training-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1096 { "training-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1097 { "tsm-104.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1098 { "tsm-105.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1099 { "tsm-106.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1102 { "sm2-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1103 { "sm2-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1104 { "sm2-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1105 { "sm2-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1106 { "sm2-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1107 { "sm2-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1108 { "sm2-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1109 { "sm2-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1110 { "sm2-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1111 { "sm2-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1114 { "sm3-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1115 { "sm3-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1116 { "sm3-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1117 { "sm3-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1118 { "sm3-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1119 { "sm3-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1120 { "sm3-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1121 { "sm3-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1122 { "sm3-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1123 { "sm3-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1124 { "loop2-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1125 { "loop2-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1127 // multiplayer missions
1130 { "g-shi.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1131 { "g-ter.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1132 { "g-vas.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1135 { "m-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1136 { "m-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1137 { "m-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1138 { "m-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1141 { "mdh-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1142 { "mdh-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1143 { "mdh-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1144 { "mdh-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1145 { "mdh-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1146 { "mdh-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1147 { "mdh-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1148 { "mdh-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1149 { "mdh-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1150 { "mdl-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1151 { "mdl-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1152 { "mdl-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1153 { "mdl-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1154 { "mdl-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1155 { "mdl-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1156 { "mdl-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1157 { "mdl-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1158 { "mdl-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1159 { "mdm-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1160 { "mdm-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1161 { "mdm-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1162 { "mdm-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1163 { "mdm-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1164 { "mdm-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1165 { "mdm-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1166 { "mdm-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1167 { "mdm-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1168 { "osdog.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1171 { "mt-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1172 { "mt-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1173 { "mt-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1174 { "mt-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1175 { "mt-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1176 { "mt-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1177 { "mt-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1178 { "mt-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1179 { "mt-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1180 { "mt-10.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1183 { "templar.fc2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1184 { "templar-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
1185 { "templar-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
1186 { "templar-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
1187 { "templar-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
1192 // Internal function prototypes
1193 void game_maybe_draw_mouse(float frametime);
1194 void init_animating_pointer();
1195 void load_animating_pointer(char *filename, int dx, int dy);
1196 void unload_animating_pointer();
1197 void game_do_training_checks();
1198 void game_shutdown(void);
1199 void game_show_event_debug(float frametime);
1200 void game_event_debug_init();
1202 void demo_upsell_show_screens();
1203 void game_start_subspace_ambient_sound();
1204 void game_stop_subspace_ambient_sound();
1205 void verify_ships_tbl();
1206 void verify_weapons_tbl();
1207 void display_title_screen();
1209 // loading background filenames
1210 static char *Game_loading_bground_fname[GR_NUM_RESOLUTIONS] = {
1211 "LoadingBG", // GR_640
1212 "2_LoadingBG" // GR_1024
1216 static char *Game_loading_ani_fname[GR_NUM_RESOLUTIONS] = {
1217 "Loading.ani", // GR_640
1218 "2_Loading.ani" // GR_1024
1221 #if defined(FS2_DEMO) || defined(FS1_DEMO)
1222 static char *Game_demo_title_screen_fname[GR_NUM_RESOLUTIONS] = {
1230 #elif defined(OEM_BUILD)
1231 static char *Game_demo_title_screen_fname[GR_NUM_RESOLUTIONS] = {
1241 char Game_CDROM_dir[MAX_PATH_LEN];
1244 // How much RAM is on this machine. Set in WinMain
1245 uint Freespace_total_ram = 0;
1248 float Game_flash_red = 0.0f;
1249 float Game_flash_green = 0.0f;
1250 float Game_flash_blue = 0.0f;
1251 float Sun_spot = 0.0f;
1252 big_expl_flash Big_expl_flash = {0.0f, 0.0f, 0};
1254 // game shudder stuff (in ms)
1255 int Game_shudder_time = -1;
1256 int Game_shudder_total = 0;
1257 float Game_shudder_intensity = 0.0f; // should be between 0.0 and 100.0
1260 sound_env Game_sound_env;
1261 //sound_env Game_default_sound_env = {SND_ENV_AUDITORIUM, 0.25f, 0.35f, 3.0f};
1262 sound_env Game_default_sound_env = {SND_ENV_GENERIC, 0.2F,0.2F,1.0F};
1264 int Game_sound_env_update_timestamp;
1266 // WARPIN CRAP BEGIN --------------------------------------------------------------------------------------------
1269 // WARPIN CRAP END --------------------------------------------------------------------------------------------
1271 fs_builtin_mission *game_find_builtin_mission(char *filename)
1275 // look through all existing builtin missions
1276 for(idx=0; idx<Game_builtin_mission_count; idx++){
1277 if(!stricmp(Game_builtin_mission_list[idx].filename, filename)){
1278 return &Game_builtin_mission_list[idx];
1286 int game_get_default_skill_level()
1288 return DEFAULT_SKILL_LEVEL;
1292 void game_flash_reset()
1294 Game_flash_red = 0.0f;
1295 Game_flash_green = 0.0f;
1296 Game_flash_blue = 0.0f;
1298 Big_expl_flash.max_flash_intensity = 0.0f;
1299 Big_expl_flash.cur_flash_intensity = 0.0f;
1300 Big_expl_flash.flash_start = 0;
1303 float Gf_critical = -1.0f; // framerate we should be above on the average for this mission
1304 float Gf_critical_time = 0.0f; // how much time we've been at the critical framerate
1306 void game_framerate_check_init()
1308 // zero critical time
1309 Gf_critical_time = 0.0f;
1312 if(The_mission.flags & MISSION_FLAG_FULLNEB){
1313 // if this is a glide card
1314 if(gr_screen.mode == GR_GLIDE){
1316 extern GrHwConfiguration hwconfig;
1319 if(hwconfig.SSTs[0].sstBoard.VoodooConfig.fbRam >= 4){
1320 Gf_critical = 15.0f;
1324 Gf_critical = 10.0f;
1329 Gf_critical = 15.0f;
1332 // d3d. only care about good cards here I guess (TNT)
1334 Gf_critical = 15.0f;
1337 // if this is a glide card
1338 if(gr_screen.mode == GR_GLIDE){
1340 extern GrHwConfiguration hwconfig;
1343 if(hwconfig.SSTs[0].sstBoard.VoodooConfig.fbRam >= 4){
1344 Gf_critical = 25.0f;
1348 Gf_critical = 20.0f;
1353 Gf_critical = 25.0f;
1356 // d3d. only care about good cards here I guess (TNT)
1358 Gf_critical = 25.0f;
1363 extern float Framerate;
1364 void game_framerate_check()
1368 // if the current framerate is above the critical level, add frametime
1369 if(Framerate >= Gf_critical){
1370 Gf_critical_time += flFrametime;
1373 if(!Show_framerate){
1377 // display if we're above the critical framerate
1378 if(Framerate < Gf_critical){
1379 gr_set_color_fast(&Color_bright_red);
1380 gr_string(200, y_start, "Framerate warning");
1385 // display our current pct of good frametime
1386 if(f2fl(Missiontime) >= 0.0f){
1387 float pct = (Gf_critical_time / f2fl(Missiontime)) * 100.0f;
1390 gr_set_color_fast(&Color_bright_green);
1392 gr_set_color_fast(&Color_bright_red);
1395 gr_printf(200, y_start, "%d%%", (int)pct);
1402 // Adds a flash effect. These can be positive or negative.
1403 // The range will get capped at around -1 to 1, so stick
1404 // with a range like that.
1405 void game_flash( float r, float g, float b )
1407 Game_flash_red += r;
1408 Game_flash_green += g;
1409 Game_flash_blue += b;
1411 if ( Game_flash_red < -1.0f ) {
1412 Game_flash_red = -1.0f;
1413 } else if ( Game_flash_red > 1.0f ) {
1414 Game_flash_red = 1.0f;
1417 if ( Game_flash_green < -1.0f ) {
1418 Game_flash_green = -1.0f;
1419 } else if ( Game_flash_green > 1.0f ) {
1420 Game_flash_green = 1.0f;
1423 if ( Game_flash_blue < -1.0f ) {
1424 Game_flash_blue = -1.0f;
1425 } else if ( Game_flash_blue > 1.0f ) {
1426 Game_flash_blue = 1.0f;
1431 // Adds a flash for Big Ship explosions
1432 // cap range from 0 to 1
1433 void big_explosion_flash(float flash)
1435 Big_expl_flash.flash_start = timestamp(1);
1439 } else if (flash < 0.0f) {
1443 Big_expl_flash.max_flash_intensity = flash;
1444 Big_expl_flash.cur_flash_intensity = 0.0f;
1447 // Amount to diminish palette towards normal, per second.
1448 #define DIMINISH_RATE 0.75f
1449 #define SUN_DIMINISH_RATE 6.00f
1453 float sn_glare_scale = 1.7f;
1456 dc_get_arg(ARG_FLOAT);
1457 sn_glare_scale = Dc_arg_float;
1460 float Supernova_last_glare = 0.0f;
1461 void game_sunspot_process(float frametime)
1465 float Sun_spot_goal = 0.0f;
1468 sn_stage = supernova_active();
1470 // sunspot differently based on supernova stage
1472 // approaching. player still in control
1475 pct = (1.0f - (supernova_time_left() / SUPERNOVA_CUT_TIME));
1478 light_get_global_dir(&light_dir, 0);
1480 dot = vm_vec_dot( &light_dir, &Eye_matrix.v.fvec );
1483 // scale it some more
1484 dot = dot * (0.5f + (pct * 0.5f));
1487 Sun_spot_goal += (dot * sn_glare_scale);
1490 // draw the sun glow
1491 if ( !shipfx_eye_in_shadow( &Eye_position, Viewer_obj, 0 ) ) {
1492 // draw the glow for this sun
1493 stars_draw_sun_glow(0);
1496 Supernova_last_glare = Sun_spot_goal;
1499 // camera cut. player not in control. note : at this point camera starts out facing the sun. so we can go nice and bright
1502 Sun_spot_goal = 0.9f;
1503 Sun_spot_goal += (1.0f - (supernova_time_left() / SUPERNOVA_CUT_TIME)) * 0.1f;
1505 if(Sun_spot_goal > 1.0f){
1506 Sun_spot_goal = 1.0f;
1509 Sun_spot_goal *= sn_glare_scale;
1510 Supernova_last_glare = Sun_spot_goal;
1513 // fade to white. display dead popup
1516 Supernova_last_glare += (2.0f * flFrametime);
1517 if(Supernova_last_glare > 2.0f){
1518 Supernova_last_glare = 2.0f;
1521 Sun_spot_goal = Supernova_last_glare;
1528 // check sunspots for all suns
1529 n_lights = light_get_global_count();
1532 for(idx=0; idx<n_lights; idx++){
1533 //(vector *eye_pos, matrix *eye_orient)
1534 if ( !shipfx_eye_in_shadow( &Eye_position, Viewer_obj, idx ) ) {
1537 light_get_global_dir(&light_dir, idx);
1539 float dot = vm_vec_dot( &light_dir, &Eye_matrix.v.fvec )*0.5f+0.5f;
1541 Sun_spot_goal += (float)pow(dot,85.0f);
1543 // draw the glow for this sun
1544 stars_draw_sun_glow(idx);
1546 Sun_spot_goal = 0.0f;
1552 Sun_spot_goal = 0.0f;
1556 float dec_amount = frametime*SUN_DIMINISH_RATE;
1558 if ( Sun_spot < Sun_spot_goal ) {
1559 Sun_spot += dec_amount;
1560 if ( Sun_spot > Sun_spot_goal ) {
1561 Sun_spot = Sun_spot_goal;
1563 } else if ( Sun_spot > Sun_spot_goal ) {
1564 Sun_spot -= dec_amount;
1565 if ( Sun_spot < Sun_spot_goal ) {
1566 Sun_spot = Sun_spot_goal;
1572 // Call once a frame to diminish the
1573 // flash effect to 0.
1574 void game_flash_diminish(float frametime)
1576 float dec_amount = frametime*DIMINISH_RATE;
1578 if ( Game_flash_red > 0.0f ) {
1579 Game_flash_red -= dec_amount;
1580 if ( Game_flash_red < 0.0f )
1581 Game_flash_red = 0.0f;
1583 Game_flash_red += dec_amount;
1584 if ( Game_flash_red > 0.0f )
1585 Game_flash_red = 0.0f;
1588 if ( Game_flash_green > 0.0f ) {
1589 Game_flash_green -= dec_amount;
1590 if ( Game_flash_green < 0.0f )
1591 Game_flash_green = 0.0f;
1593 Game_flash_green += dec_amount;
1594 if ( Game_flash_green > 0.0f )
1595 Game_flash_green = 0.0f;
1598 if ( Game_flash_blue > 0.0f ) {
1599 Game_flash_blue -= dec_amount;
1600 if ( Game_flash_blue < 0.0f )
1601 Game_flash_blue = 0.0f;
1603 Game_flash_blue += dec_amount;
1604 if ( Game_flash_blue > 0.0f )
1605 Game_flash_blue = 0.0f;
1608 // update big_explosion_cur_flash
1609 #define TIME_UP 1500
1610 #define TIME_DOWN 2500
1611 int duration = TIME_UP + TIME_DOWN;
1612 int time = timestamp_until(Big_expl_flash.flash_start);
1613 if (time > -duration) {
1615 if (time < TIME_UP) {
1616 Big_expl_flash.cur_flash_intensity = Big_expl_flash.max_flash_intensity * time / (float) TIME_UP;
1619 Big_expl_flash.cur_flash_intensity = Big_expl_flash.max_flash_intensity * ((float) TIME_DOWN - time) / (float) TIME_DOWN;
1623 if ( Use_palette_flash ) {
1625 // static int or=0, og=0, ob=0;
1627 // Change the 200 to change the color range of colors.
1628 r = fl2i( Game_flash_red*128.0f );
1629 g = fl2i( Game_flash_green*128.0f );
1630 b = fl2i( Game_flash_blue*128.0f );
1632 if ( Sun_spot > 0.0f ) {
1633 r += fl2i(Sun_spot*128.0f);
1634 g += fl2i(Sun_spot*128.0f);
1635 b += fl2i(Sun_spot*128.0f);
1638 if ( Big_expl_flash.cur_flash_intensity > 0.0f ) {
1639 r += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1640 g += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1641 b += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1644 if ( r < 0 ) r = 0; else if ( r > 255 ) r = 255;
1645 if ( g < 0 ) g = 0; else if ( g > 255 ) g = 255;
1646 if ( b < 0 ) b = 0; else if ( b > 255 ) b = 255;
1648 if ( (r!=0) || (g!=0) || (b!=0) ) {
1649 gr_flash( r, g, b );
1651 //mprintf(( "Flash! %d,%d,%d\n", r, g, b ));
1662 void game_level_close()
1664 // De-Initialize the game subsystems
1665 event_music_level_close();
1666 game_stop_looped_sounds();
1668 obj_snd_level_close(); // uninit object-linked persistant sounds
1669 gamesnd_unload_gameplay_sounds(); // unload gameplay sounds from memory
1670 anim_level_close(); // stop and clean up any anim instances
1671 message_mission_shutdown(); // called after anim_level_close() to make sure anim instances are free
1672 shockwave_level_close();
1673 fireball_level_close();
1675 mission_event_shutdown();
1676 asteroid_level_close();
1677 model_cache_reset(); // Reset/free all the model caching stuff
1678 flak_level_close(); // unload flak stuff
1679 neb2_level_close(); // shutdown gaseous nebula stuff
1682 mflash_level_close();
1684 audiostream_unpause_all();
1689 // intializes game stuff and loads the mission. Returns 0 on failure, 1 on success
1690 // input: seed => DEFAULT PARAMETER (value -1). Only set by demo playback code.
1691 void game_level_init(int seed)
1693 // seed the random number generator
1695 // if no seed was passed, seed the generator either from the time value, or from the
1696 // netgame security flags -- ensures that all players in multiplayer game will have the
1697 // same randon number sequence (with static rand functions)
1698 if ( Game_mode & GM_NORMAL ) {
1699 Game_level_seed = time(NULL);
1701 Game_level_seed = Netgame.security;
1704 // mwa 9/17/98 -- maybe this assert isn't needed????
1705 Assert( !(Game_mode & GM_MULTIPLAYER) );
1706 Game_level_seed = seed;
1708 srand( Game_level_seed );
1710 // semirand function needs to get re-initted every time in multiplayer
1711 if ( Game_mode & GM_MULTIPLAYER ){
1717 Key_normal_game = (Game_mode & GM_NORMAL);
1720 Game_shudder_time = -1;
1722 // Initialize the game subsystems
1723 // timestamp_reset(); // Must be inited before everything else
1725 game_reset_time(); // resets time, and resets saved time too
1727 obj_init(); // Must be inited before the other systems
1728 model_free_all(); // Free all existing models
1729 mission_brief_common_init(); // Free all existing briefing/debriefing text
1730 weapon_level_init();
1731 ai_level_init(); // Call this before ship_init() because it reads ai.tbl.
1733 player_level_init();
1734 shipfx_flash_init(); // Init the ship gun flash system.
1735 game_flash_reset(); // Reset the flash effect
1736 particle_init(); // Reset the particle system
1740 shield_hit_init(); // Initialize system for showing shield hits
1741 radar_mission_init();
1742 mission_init_goals();
1745 obj_snd_level_init(); // init object-linked persistant sounds
1747 shockwave_level_init();
1748 afterburner_level_init();
1749 scoring_level_init( &Player->stats );
1751 asteroid_level_init();
1752 control_config_clear_used_status();
1753 collide_ship_ship_sounds_init();
1755 Pre_player_entry = 1; // Means the player has not yet entered.
1756 Entry_delay_time = 0; // Could get overwritten in mission read.
1757 fireball_preload(); // page in warphole bitmaps
1759 flak_level_init(); // initialize flak - bitmaps, etc
1760 ct_level_init(); // initialize ships contrails, etc
1761 awacs_level_init(); // initialize AWACS
1762 beam_level_init(); // initialize beam weapons
1763 mflash_level_init();
1765 supernova_level_init();
1767 // multiplayer dogfight hack
1770 shipfx_engine_wash_level_init();
1774 Last_view_target = NULL;
1779 // campaign wasn't ended
1780 Campaign_ended_in_mission = 0;
1783 // called when a mission is over -- does server specific stuff.
1784 void freespace_stop_mission()
1787 Game_mode &= ~GM_IN_MISSION;
1790 // called at frame interval to process networking stuff
1791 void game_do_networking()
1793 Assert( Net_player != NULL );
1794 if (!(Game_mode & GM_MULTIPLAYER)){
1798 // see if this player should be reading/writing data. Bit is set when at join
1799 // screen onward until quits back to main menu.
1800 if ( !(Net_player->flags & NETINFO_FLAG_DO_NETWORKING) ){
1804 if(gameseq_get_state()!=GS_STATE_MULTI_PAUSED){
1807 multi_pause_do_frame();
1812 // Loads the best palette for this level, based
1813 // on nebula color and hud color. You could just call palette_load_table with
1814 // the appropriate filename, but who wants to do that.
1815 void game_load_palette()
1817 char palette_filename[1024];
1819 // We only use 3 hud colors right now
1821 Assert( HUD_config.main_color >= 0 );
1822 Assert( HUD_config.main_color <= 2 );
1825 Assert( Mission_palette >= 0 );
1826 Assert( Mission_palette <= 98 );
1829 if ( The_mission.flags & MISSION_FLAG_SUBSPACE ) {
1830 strcpy( palette_filename, NOX("gamepalette-subspace") );
1832 sprintf( palette_filename, NOX("gamepalette%d-%02d"), HUD_config.main_color+1, Mission_palette+1 );
1835 mprintf(( "Loading palette %s\n", palette_filename ));
1837 palette_load_table(palette_filename);
1839 strcpy( palette_filename, NOX("gamepalette-subspace") );
1841 mprintf(( "Loading palette %s\n", palette_filename ));
1845 void game_post_level_init()
1847 // Stuff which gets called after mission is loaded. Because player isn't created until
1848 // after mission loads, some things must get initted after the level loads
1850 model_level_post_init();
1853 hud_setup_escort_list();
1854 mission_hotkey_set_defaults(); // set up the default hotkeys (from mission file)
1860 game_event_debug_init();
1863 training_mission_init();
1864 asteroid_create_all();
1866 game_framerate_check_init();
1870 // An estimate as to how high the count passed to game_loading_callback will go.
1871 // This is just a guess, it seems to always be about the same. The count is
1872 // proportional to the code being executed, not the time, so this works good
1873 // for a bar, assuming the code does about the same thing each time you
1874 // load a level. You can find this value by looking at the return value
1875 // of game_busy_callback(NULL), which I conveniently print out to the
1876 // debug output window with the '=== ENDING LOAD ==' stuff.
1877 //#define COUNT_ESTIMATE 3706
1878 #define COUNT_ESTIMATE 1111
1880 int Game_loading_callback_inited = 0;
1882 int Game_loading_background = -1;
1883 anim * Game_loading_ani = NULL;
1884 anim_instance *Game_loading_ani_instance;
1885 int Game_loading_frame=-1;
1887 static int Game_loading_ani_coords[GR_NUM_RESOLUTIONS][2] = {
1889 #if defined(FS1_DEMO)
1891 #elif defined(MAKE_FS1)
1902 // This gets called 10x per second and count is the number of times
1903 // game_busy() has been called since the current callback function
1905 void game_loading_callback(int count)
1907 game_do_networking();
1909 Assert( Game_loading_callback_inited==1 );
1910 Assert( Game_loading_ani != NULL );
1912 int framenum = ((Game_loading_ani->total_frames*count) / COUNT_ESTIMATE)+1;
1913 if ( framenum > Game_loading_ani->total_frames-1 ) {
1914 framenum = Game_loading_ani->total_frames-1;
1915 } else if ( framenum < 0 ) {
1920 while ( Game_loading_frame < framenum ) {
1921 Game_loading_frame++;
1922 cbitmap = anim_get_next_frame(Game_loading_ani_instance);
1926 if ( cbitmap > -1 ) {
1927 if ( Game_loading_background > -1 ) {
1928 gr_set_bitmap( Game_loading_background );
1932 //mprintf(( "Showing frame %d/%d [ Bitmap=%d ]\n", Game_loading_frame , Game_loading_ani->total_frames, cbitmap ));
1933 gr_set_bitmap( cbitmap );
1934 gr_bitmap(Game_loading_ani_coords[gr_screen.res][0],Game_loading_ani_coords[gr_screen.res][1]);
1936 bm_release(cbitmap);
1942 void game_loading_callback_init()
1944 Assert( Game_loading_callback_inited==0 );
1946 Game_loading_background = bm_load(Game_loading_bground_fname[gr_screen.res]);
1948 common_set_interface_palette("InterfacePalette"); // set the interface palette
1952 Game_loading_ani = anim_load( Game_loading_ani_fname[gr_screen.res]);
1953 Assert( Game_loading_ani != NULL );
1954 Game_loading_ani_instance = init_anim_instance(Game_loading_ani, 16);
1955 Assert( Game_loading_ani_instance != NULL );
1956 Game_loading_frame = -1;
1958 Game_loading_callback_inited = 1;
1960 game_busy_callback( game_loading_callback, (COUNT_ESTIMATE/Game_loading_ani->total_frames)+1 );
1965 void game_loading_callback_close()
1967 Assert( Game_loading_callback_inited==1 );
1969 // Make sure bar shows all the way over.
1970 game_loading_callback(COUNT_ESTIMATE);
1972 int real_count = game_busy_callback( NULL );
1975 Game_loading_callback_inited = 0;
1978 mprintf(( "=================== ENDING LOAD ================\n" ));
1979 mprintf(( "Real count = %d, Estimated count = %d\n", real_count, COUNT_ESTIMATE ));
1980 mprintf(( "================================================\n" ));
1982 // to remove warnings in release build
1986 free_anim_instance(Game_loading_ani_instance);
1987 Game_loading_ani_instance = NULL;
1988 anim_free(Game_loading_ani);
1989 Game_loading_ani = NULL;
1991 bm_release( Game_loading_background );
1992 common_free_interface_palette(); // restore game palette
1993 Game_loading_background = -1;
1995 gr_set_font( FONT1 );
1998 // Update the sound environment (ie change EAX settings based on proximity to large ships)
2000 void game_maybe_update_sound_environment()
2002 // do nothing for now
2005 // Assign the sound environment for the game, based on the current mission
2007 void game_assign_sound_environment()
2010 if (The_mission.flags & MISSION_FLAG_SUBSPACE) {
2011 Game_sound_env.id = SND_ENV_DRUGGED;
2012 Game_sound_env.volume = 0.800f;
2013 Game_sound_env.damping = 1.188f;
2014 Game_sound_env.decay = 6.392f;
2016 } else if (Num_asteroids > 30) {
2017 Game_sound_env.id = SND_ENV_AUDITORIUM;
2018 Game_sound_env.volume = 0.603f;
2019 Game_sound_env.damping = 0.5f;
2020 Game_sound_env.decay = 4.279f;
2023 Game_sound_env = Game_default_sound_env;
2027 Game_sound_env = Game_default_sound_env;
2028 Game_sound_env_update_timestamp = timestamp(1);
2031 // function which gets called before actually entering the mission. It is broken down into a funciton
2032 // since it will get called in one place from a single player game and from another place for
2033 // a multiplayer game
2034 void freespace_mission_load_stuff()
2036 // called if we're not on a freespace dedicated (non rendering, no pilot) server
2037 // IE : we _don't_ want to load any sounds or bitmap/texture info on this machine.
2038 if(!(Game_mode & GM_STANDALONE_SERVER)){
2040 mprintf(( "=================== STARTING LEVEL DATA LOAD ==================\n" ));
2042 game_loading_callback_init();
2044 event_music_level_init(); // preloads the first 2 seconds for each event music track
2047 gamesnd_unload_interface_sounds(); // unload interface sounds from memory
2050 gamesnd_preload_common_sounds(); // load in sounds that are expected to play
2053 ship_assign_sound_all(); // assign engine sounds to ships
2054 game_assign_sound_environment(); // assign the sound environment for this mission
2057 // call function in missionparse.cpp to fixup player/ai stuff.
2058 mission_parse_fixup_players();
2061 // Load in all the bitmaps for this level
2066 game_loading_callback_close();
2068 // the only thing we need to call on the standalone for now.
2070 // call function in missionparse.cpp to fixup player/ai stuff.
2071 mission_parse_fixup_players();
2073 // Load in all the bitmaps for this level
2079 uint load_mission_load;
2080 uint load_post_level_init;
2081 uint load_mission_stuff;
2083 // tells the server to load the mission and initialize structures
2084 int game_start_mission()
2086 mprintf(( "=================== STARTING LEVEL LOAD ==================\n" ));
2088 load_gl_init = time(NULL);
2090 load_gl_init = time(NULL) - load_gl_init;
2092 if (Game_mode & GM_MULTIPLAYER) {
2093 Player->flags |= PLAYER_FLAGS_IS_MULTI;
2095 // clear multiplayer stats
2096 init_multiplayer_stats();
2099 load_mission_load = time(NULL);
2100 if (mission_load()) {
2101 if ( !(Game_mode & GM_MULTIPLAYER) ) {
2102 popup(PF_BODY_BIG, 1, POPUP_OK, XSTR( "Attempt to load the mission failed", 169));
2103 gameseq_post_event(GS_EVENT_MAIN_MENU);
2105 multi_quit_game(PROMPT_NONE, MULTI_END_NOTIFY_NONE, MULTI_END_ERROR_LOAD_FAIL);
2110 load_mission_load = time(NULL) - load_mission_load;
2112 // If this is a red alert mission in campaign mode, bash wingman status
2113 if ( (Game_mode & GM_CAMPAIGN_MODE) && red_alert_mission() ) {
2114 red_alert_bash_wingman_status();
2117 // the standalone server in multiplayer doesn't do any rendering, so we will not even bother loading the palette
2118 if ( !(Game_mode & GM_STANDALONE_SERVER) ) {
2119 mprintf(( "=================== LOADING GAME PALETTE ================\n" ));
2121 game_load_palette();
2125 load_post_level_init = time(NULL);
2126 game_post_level_init();
2127 load_post_level_init = time(NULL) - load_post_level_init;
2131 void Do_model_timings_test();
2132 Do_model_timings_test();
2136 load_mission_stuff = time(NULL);
2137 freespace_mission_load_stuff();
2138 load_mission_stuff = time(NULL) - load_mission_stuff;
2143 int Interface_framerate = 0;
2146 DCF_BOOL( mouse_control, Use_mouse_to_fly )
2147 DCF_BOOL( show_framerate, Show_framerate )
2148 DCF_BOOL( show_target_debug_info, Show_target_debug_info )
2149 DCF_BOOL( show_target_weapons, Show_target_weapons )
2150 DCF_BOOL( lead_target_cheat, Players[Player_num].lead_target_cheat )
2151 DCF_BOOL( sound, Sound_enabled )
2152 DCF_BOOL( zbuffer, game_zbuffer )
2153 DCF_BOOL( shield_system, New_shield_system )
2154 DCF_BOOL( show_shield_mesh, Show_shield_mesh)
2155 DCF_BOOL( player_attacking, Player_attacking_enabled )
2156 DCF_BOOL( show_waypoints, Show_waypoints )
2157 DCF_BOOL( show_area_effect, Show_area_effect )
2158 DCF_BOOL( show_net_stats, Show_net_stats )
2159 DCF_BOOL( log, Log_debug_output_to_file )
2160 DCF_BOOL( training_msg_method, Training_msg_method )
2161 DCF_BOOL( show_player_pos, Show_player_pos )
2162 DCF_BOOL(i_framerate, Interface_framerate )
2164 DCF(show_mem,"Toggles showing mem usage")
2167 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2168 if ( Dc_arg_type & ARG_TRUE ) Show_mem = 1;
2169 else if ( Dc_arg_type & ARG_FALSE ) Show_mem = 0;
2170 else if ( Dc_arg_type & ARG_NONE ) Show_mem ^= 1;
2176 if ( Dc_help ) dc_printf( "Usage: Show_mem\nSets show_mem to true or false. If nothing passed, then toggles it.\n" );
2178 dc_printf( "Show_mem is %s\n", (Show_mem?"TRUE":"FALSE") );
2179 dc_printf( "Show_cpu is %s\n", (Show_cpu?"TRUE":"FALSE") );
2183 DCF(show_cpu,"Toggles showing cpu usage")
2186 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2187 if ( Dc_arg_type & ARG_TRUE ) Show_cpu = 1;
2188 else if ( Dc_arg_type & ARG_FALSE ) Show_cpu = 0;
2189 else if ( Dc_arg_type & ARG_NONE ) Show_cpu ^= 1;
2195 if ( Dc_help ) dc_printf( "Usage: Show_cpu\nSets show_cpu to true or false. If nothing passed, then toggles it.\n" );
2197 dc_printf( "Show_mem is %s\n", (Show_mem?"TRUE":"FALSE") );
2198 dc_printf( "Show_cpu is %s\n", (Show_cpu?"TRUE":"FALSE") );
2205 // AL 4-8-98: always allow players to display their framerate
2208 DCF_BOOL( show_framerate, Show_framerate )
2215 DCF(use_joy_mouse,"Makes joystick move mouse cursor")
2218 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2219 if ( Dc_arg_type & ARG_TRUE ) Use_joy_mouse = 1;
2220 else if ( Dc_arg_type & ARG_FALSE ) Use_joy_mouse = 0;
2221 else if ( Dc_arg_type & ARG_NONE ) Use_joy_mouse ^= 1;
2223 if ( Dc_help ) dc_printf( "Usage: use_joy_mouse [bool]\nSets use_joy_mouse to true or false. If nothing passed, then toggles it.\n" );
2224 if ( Dc_status ) dc_printf( "use_joy_mouse is %s\n", (Use_joy_mouse?"TRUE":"FALSE") );
2226 os_config_write_uint( NULL, NOX("JoystickMovesCursor"), Use_joy_mouse );
2229 DCF(palette_flash,"Toggles palette flash effect on/off")
2232 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2233 if ( Dc_arg_type & ARG_TRUE ) Use_palette_flash = 1;
2234 else if ( Dc_arg_type & ARG_FALSE ) Use_palette_flash = 0;
2235 else if ( Dc_arg_type & ARG_NONE ) Use_palette_flash ^= 1;
2237 if ( Dc_help ) dc_printf( "Usage: palette_flash [bool]\nSets palette_flash to true or false. If nothing passed, then toggles it.\n" );
2238 if ( Dc_status ) dc_printf( "palette_flash is %s\n", (Use_palette_flash?"TRUE":"FALSE") );
2241 int Use_low_mem = 0;
2243 DCF(low_mem,"Uses low memory settings regardless of RAM")
2246 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2247 if ( Dc_arg_type & ARG_TRUE ) Use_low_mem = 1;
2248 else if ( Dc_arg_type & ARG_FALSE ) Use_low_mem = 0;
2249 else if ( Dc_arg_type & ARG_NONE ) Use_low_mem ^= 1;
2251 if ( Dc_help ) dc_printf( "Usage: low_mem [bool]\nSets low_mem to true or false. If nothing passed, then toggles it.\n" );
2252 if ( Dc_status ) dc_printf( "low_mem is %s\n", (Use_low_mem?"TRUE":"FALSE") );
2254 os_config_write_uint( NULL, NOX("LowMem"), Use_low_mem );
2260 DCF(force_fullscreen, "Forces game to startup in fullscreen mode")
2263 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2264 if ( Dc_arg_type & ARG_TRUE ) Use_fullscreen_at_startup = 1;
2265 else if ( Dc_arg_type & ARG_FALSE ) Use_fullscreen_at_startup = 0;
2266 else if ( Dc_arg_type & ARG_NONE ) Use_fullscreen_at_startup ^= 1;
2268 if ( Dc_help ) dc_printf( "Usage: force_fullscreen [bool]\nSets force_fullscreen to true or false. If nothing passed, then toggles it.\n" );
2269 if ( Dc_status ) dc_printf( "force_fullscreen is %s\n", (Use_fullscreen_at_startup?"TRUE":"FALSE") );
2270 os_config_write_uint( NULL, NOX("ForceFullscreen"), Use_fullscreen_at_startup );
2274 int Framerate_delay = 0;
2276 float Freespace_gamma = 1.0f;
2278 DCF(gamma,"Sets Gamma factor")
2281 dc_get_arg(ARG_FLOAT|ARG_NONE);
2282 if ( Dc_arg_type & ARG_FLOAT ) {
2283 Freespace_gamma = Dc_arg_float;
2285 dc_printf( "Gamma reset to 1.0f\n" );
2286 Freespace_gamma = 1.0f;
2288 if ( Freespace_gamma < 0.1f ) {
2289 Freespace_gamma = 0.1f;
2290 } else if ( Freespace_gamma > 5.0f ) {
2291 Freespace_gamma = 5.0f;
2293 gr_set_gamma(Freespace_gamma);
2295 char tmp_gamma_string[32];
2296 sprintf( tmp_gamma_string, NOX("%.2f"), Freespace_gamma );
2297 os_config_write_string( NULL, NOX("Gamma"), tmp_gamma_string );
2301 dc_printf( "Usage: gamma <float>\n" );
2302 dc_printf( "Sets gamma in range 1-3, no argument resets to default 1.2\n" );
2303 Dc_status = 0; // don't print status if help is printed. Too messy.
2307 dc_printf( "Gamma = %.2f\n", Freespace_gamma );
2316 Game_current_mission_filename[0] = 0;
2318 // seed the random number generator
2319 Game_init_seed = time(NULL);
2320 srand( Game_init_seed );
2322 Framerate_delay = 0;
2328 extern void bm_init();
2334 // Initialize the timer before the os
2342 GetCurrentDirectory(1024, whee);
2345 getcwd (whee, 1024);
2348 strcat(whee, EXE_FNAME);
2350 //Initialize the libraries
2351 s1 = timer_get_milliseconds();
2352 if(cfile_init(whee, Game_CDROM_dir)){ // initialize before calling any cfopen stuff!!!
2355 e1 = timer_get_milliseconds();
2357 // time a bunch of cfopens
2359 s2 = timer_get_milliseconds();
2361 for(int idx=0; idx<10000; idx++){
2362 whee = cfopen("capital01.pof", "rb", CFILE_NORMAL, CF_TYPE_MODELS);
2367 //cf_exist("capital01.pof", CF_TYPE_MODELS);
2369 e2 = timer_get_milliseconds();
2372 if (Is_standalone) {
2373 std_init_standalone();
2375 os_init( Osreg_class_name, Osreg_app_name );
2376 os_set_title(Osreg_title);
2379 // initialize localization module. Make sure this is down AFTER initialzing OS.
2380 // int t1 = timer_get_milliseconds();
2381 lcl_init( detect_lang() );
2383 // mprintf(("LCL_INIT() TOOK %d MS\n", timer_get_milliseconds()-t1));
2385 // verify that he has a valid ships.tbl (will Game_ships_tbl_valid if so)
2388 // verify that he has a valid weapons.tbl
2389 verify_weapons_tbl();
2392 // setup the default osreg values if they don't exist
2396 // Output version numbers to registry for auto patching purposes
2397 os_config_write_uint(NOX("Version"), NOX("Major"), FS_VERSION_MAJOR);
2398 os_config_write_uint(NOX("Version"), NOX("Minor"), FS_VERSION_MINOR);
2399 os_config_write_uint(NOX("Version"), NOX("Build"), FS_VERSION_BUILD);
2401 Use_joy_mouse = 0; //os_config_read_uint( NULL, NOX("JoystickMovesCursor"), 1 );
2402 //Use_palette_flash = os_config_read_uint( NULL, NOX("PaletteFlash"), 0 );
2403 Use_low_mem = os_config_read_uint( NULL, NOX("LowMem"), 0 );
2406 Use_fullscreen_at_startup = os_config_read_uint( NULL, NOX("ForceFullscreen"), 1 );
2409 #if defined (PLAT_UNIX) && defined(RELEASE_REAL)
2410 // show the FPS counter if the config file says so
2411 Show_framerate = os_config_read_uint( NULL, NOX("ShowFPS"), 0 );
2414 #if !(defined(FS2_DEMO) || defined(FS1_DEMO))
2415 Asteroids_enabled = 1;
2418 /////////////////////////////
2420 /////////////////////////////
2425 ptr = os_config_read_string(NULL, NOX("Soundcard"), NULL);
2426 mprintf(("soundcard = %s\n", ptr ? ptr : "<nothing>"));
2428 if (!stricmp(ptr, NOX("no sound"))) {
2429 Cmdline_freespace_no_sound = 1;
2431 } else if (!stricmp(ptr, NOX("Aureal A3D"))) {
2433 } else if (!stricmp(ptr, NOX("EAX"))) {
2438 if (!Is_standalone) {
2439 snd_init(use_a3d, use_eax);
2441 /////////////////////////////
2443 /////////////////////////////
2445 ptr = os_config_read_string(NULL, NOX("Videocard"), NULL);
2448 MessageBox((HWND)os_get_window(), XSTR("Please configure your system in the Launcher before running FS2.\n\n The Launcher will now be started!", 1446), XSTR("Attention!", 1447), MB_OK);
2450 // fire up the UpdateLauncher executable
2452 PROCESS_INFORMATION pi;
2454 memset( &si, 0, sizeof(STARTUPINFO) );
2457 BOOL ret = CreateProcess( LAUNCHER_FNAME, // pointer to name of executable module
2458 NULL, // pointer to command line string
2459 NULL, // pointer to process security attributes
2460 NULL, // pointer to thread security attributes
2461 FALSE, // handle inheritance flag
2462 CREATE_DEFAULT_ERROR_MODE, // creation flags
2463 NULL, // pointer to new environment block
2464 NULL, // pointer to current directory name
2465 &si, // pointer to STARTUPINFO
2466 &pi // pointer to PROCESS_INFORMATION
2469 // If the Launcher could not be started up, let the user know
2471 MessageBox((HWND)os_get_window(), XSTR("The Launcher could not be restarted.", 1450), XSTR("Error", 1451), MB_OK);
2480 if(!stricmp(ptr, "Aucune accélération 3D") || !stricmp(ptr, "Keine 3D-Beschleunigerkarte") || !stricmp(ptr, "No 3D acceleration")){
2482 MessageBox((HWND)os_get_window(), XSTR("Warning, Freespace 2 requires Glide or Direct3D hardware accleration. You will not be able to run Freespace 2 without it.", 1448), XSTR("Warning", 1449), MB_OK);
2490 // check for hi res pack file
2491 int has_sparky_hi = 0;
2493 // check if sparky_hi exists -- access mode 0 means does file exist
2494 #ifndef MAKE_FS1 // shoudn't have it so don't check
2497 if ( _access("sparky_hi_fs2.vp", 0) == 0) {
2500 mprintf(("No sparky_hi_fs2.vp in directory %s\n", dir));
2504 // see if we've got 32 bit in the string
2505 if(strstr(ptr, "32 bit")){
2512 if (!Is_standalone && ptr && (strstr(ptr, NOX("3DFX Glide")))) {
2514 // always 640 for E3
2515 gr_init(GR_640, GR_GLIDE);
2517 // regular or hi-res ?
2519 if(has_sparky_hi && strstr(ptr, NOX("(1024x768)"))){
2521 if(strstr(ptr, NOX("(1024x768)"))){
2523 gr_init(GR_1024, GR_GLIDE);
2525 gr_init(GR_640, GR_GLIDE);
2528 } else if (!Is_standalone && ptr && (strstr(ptr, NOX("Direct 3D -") ))) {
2530 // always 640 for E3
2532 gr_init(GR_640, GR_DIRECT3D, depth);
2534 // regular or hi-res ?
2536 if(has_sparky_hi && strstr(ptr, NOX("(1024x768)"))){
2538 if(strstr(ptr, NOX("(1024x768)"))){
2542 gr_init(GR_1024, GR_DIRECT3D, depth);
2546 gr_init(GR_640, GR_DIRECT3D, depth);
2552 if ( Use_fullscreen_at_startup && !Is_standalone) {
2553 gr_init(GR_640, GR_DIRECTDRAW);
2555 gr_init(GR_640, GR_SOFTWARE);
2558 if ( !Is_standalone ) {
2559 gr_init(GR_640, GR_DIRECTDRAW);
2561 gr_init(GR_640, GR_SOFTWARE);
2566 if (!Is_standalone /* && ptr && (strstr(ptr, NOX("OpenGL"))) */) {
2567 if(has_sparky_hi && strstr(ptr, NOX("(1024x768)"))){
2568 gr_init(GR_1024, GR_OPENGL);
2570 gr_init(GR_640, GR_OPENGL);
2574 gr_init(GR_640, GR_SOFTWARE);
2579 extern int Gr_inited;
2580 if(trying_d3d && !Gr_inited){
2582 extern char Device_init_error[512];
2583 MessageBox( NULL, Device_init_error, "Error intializing Direct3D", MB_OK|MB_TASKMODAL|MB_SETFOREGROUND );
2592 ptr = os_config_read_string(NULL,NOX("Gamma"),NOX("1.80"));
2593 Freespace_gamma = (float)atof(ptr);
2594 if ( Freespace_gamma == 0.0f ) {
2595 Freespace_gamma = 1.80f;
2596 } else if ( Freespace_gamma < 0.1f ) {
2597 Freespace_gamma = 0.1f;
2598 } else if ( Freespace_gamma > 5.0f ) {
2599 Freespace_gamma = 5.0f;
2601 char tmp_gamma_string[32];
2602 sprintf( tmp_gamma_string, NOX("%.2f"), Freespace_gamma );
2603 os_config_write_string( NULL, NOX("Gamma"), tmp_gamma_string );
2605 gr_set_gamma(Freespace_gamma);
2607 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
2610 display_title_screen();
2614 // attempt to load up master tracker registry info (login and password)
2615 Multi_tracker_id = -1;
2617 // pxo login and password
2618 ptr = os_config_read_string(NOX("PXO"),NOX("Login"),NULL);
2620 nprintf(("Network","Error reading in PXO login data\n"));
2621 strcpy(Multi_tracker_login,"");
2623 strcpy(Multi_tracker_login,ptr);
2625 ptr = os_config_read_string(NOX("PXO"),NOX("Password"),NULL);
2627 nprintf(("Network","Error reading PXO password\n"));
2628 strcpy(Multi_tracker_passwd,"");
2630 strcpy(Multi_tracker_passwd,ptr);
2633 // pxo squad name and password
2634 ptr = os_config_read_string(NOX("PXO"),NOX("SquadName"),NULL);
2636 nprintf(("Network","Error reading in PXO squad name\n"));
2637 strcpy(Multi_tracker_squad_name, "");
2639 strcpy(Multi_tracker_squad_name, ptr);
2642 // If less than 48MB of RAM, use low memory model.
2645 (Freespace_total_ram < 48*1024*1024) ||
2648 mprintf(( "Using normal memory settings...\n" ));
2649 bm_set_low_mem(1); // Use every other frame of bitmaps
2651 mprintf(( "Using high memory settings...\n" ));
2652 bm_set_low_mem(0); // Use all frames of bitmaps
2655 // load non-darkening pixel defs
2656 palman_load_pixels();
2658 // hud shield icon stuff
2659 hud_shield_game_init();
2661 control_config_common_init(); // sets up localization stuff in the control config
2667 gamesnd_parse_soundstbl();
2672 // standalone's don't use hte joystick and it seems to sometimes cause them to not get shutdown properly
2677 player_controls_init();
2680 //if(!Is_standalone){
2688 ship_init(); // read in ships.tbl
2690 mission_campaign_init(); // load in the default campaign
2692 // navmap_init(); // init the navigation map system
2693 context_help_init();
2694 techroom_intel_init(); // parse species.tbl, load intel info
2696 psnet_init( Multi_options_g.protocol, Multi_options_g.port ); // initialize the networking code
2697 init_animating_pointer();
2699 mission_brief_common_init(); // Mark all the briefing structures as empty.
2700 gr_font_init(); // loads up all fonts
2702 neb2_init(); // fullneb stuff
2706 player_tips_init(); // helpful tips
2709 // load the list of pilot pic filenames (for barracks and pilot select popup quick reference)
2710 pilot_load_pic_list();
2711 pilot_load_squad_pic_list();
2713 load_animating_pointer(NOX("cursor"), 0, 0);
2715 // initialize alpha colors
2716 alpha_colors_init();
2719 // Game_music_paused = 0;
2726 nprintf(("General", "Ships.tbl is : %s\n", Game_ships_tbl_valid ? "VALID" : "INVALID!!!!"));
2727 nprintf(("General", "Weapons.tbl is : %s\n", Game_weapons_tbl_valid ? "VALID" : "INVALID!!!!"));
2729 mprintf(("cfile_init() took %d\n", e1 - s1));
2730 // mprintf(("1000 cfopens() took %d\n", e2 - s2));
2733 char transfer_text[128];
2735 float Start_time = 0.0f;
2737 float Framerate = 0.0f;
2739 float Timing_total = 0.0f;
2740 float Timing_render2 = 0.0f;
2741 float Timing_render3 = 0.0f;
2742 float Timing_flip = 0.0f;
2743 float Timing_clear = 0.0f;
2745 MONITOR(NumPolysDrawn);
2751 void game_get_framerate()
2753 char text[128] = "";
2755 if ( frame_int == -1 ) {
2757 for (i=0; i<FRAME_FILTER; i++ ) {
2758 frametimes[i] = 0.0f;
2763 frametotal -= frametimes[frame_int];
2764 frametotal += flFrametime;
2765 frametimes[frame_int] = flFrametime;
2766 frame_int = (frame_int + 1 ) % FRAME_FILTER;
2768 if ( frametotal != 0.0 ) {
2769 if ( Framecount >= FRAME_FILTER )
2770 Framerate = FRAME_FILTER / frametotal;
2772 Framerate = Framecount / frametotal;
2773 sprintf( text, NOX("FPS: %.1f"), Framerate );
2775 sprintf( text, NOX("FPS: ?") );
2779 if (Show_framerate) {
2780 gr_set_color_fast(&HUD_color_debug);
2781 gr_string( 570, 2, text );
2785 void game_show_framerate()
2789 cur_time = f2fl(timer_get_approx_seconds());
2790 if (cur_time - Start_time > 30.0f) {
2791 mprintf(("%i frames executed in %7.3f seconds, %7.3f frames per second.\n", Framecount, cur_time - Start_time, Framecount/(cur_time - Start_time)));
2792 Start_time += 1000.0f;
2795 //mprintf(( "%s\n", text ));
2798 if ( Debug_dump_frames )
2802 // possibly show control checking info
2803 control_check_indicate();
2805 // int bitmaps_used_this_frame, bitmaps_new_this_frame;
2806 // bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
2807 // MONITOR_INC(BmpUsed, bitmaps_used_this_frame);
2808 // MONITOR_INC(BmpNew, bitmaps_new_this_frame);
2811 if ( Show_cpu == 1 ) {
2816 dy = gr_get_font_height() + 1;
2818 gr_set_color_fast(&HUD_color_debug);
2822 extern int D3D_textures_in;
2823 extern int D3D_textures_in_frame;
2824 extern int Glide_textures_in;
2825 extern int Glide_textures_in_frame;
2826 extern int Glide_explosion_vram;
2827 gr_printf( sx, sy, NOX("VRAM: %d KB\n"), (D3D_textures_in+Glide_textures_in)/1024 );
2829 gr_printf( sx, sy, NOX("VRAM: +%d KB\n"), (Glide_textures_in_frame+D3D_textures_in_frame)/1024 );
2831 gr_printf( sx, sy, NOX("EXP VRAM: %dKB\n"), (Glide_explosion_vram)/1024 );
2835 // gr_printf( sx, sy, "BPP: %d", gr_screen.bits_per_pixel );
2837 gr_printf( sx, sy, NOX("DMA: %s"), transfer_text );
2839 gr_printf( sx, sy, NOX("POLYP: %d"), modelstats_num_polys );
2841 gr_printf( sx, sy, NOX("POLYD: %d"), modelstats_num_polys_drawn );
2843 gr_printf( sx, sy, NOX("VERTS: %d"), modelstats_num_verts );
2848 extern int Num_pairs; // Number of object pairs that were checked.
2849 gr_printf( sx, sy, NOX("PAIRS: %d"), Num_pairs );
2852 extern int Num_pairs_checked; // What percent of object pairs were checked.
2853 gr_printf( sx, sy, NOX("FVI: %d"), Num_pairs_checked );
2855 Num_pairs_checked = 0;
2859 gr_printf( sx, sy, NOX("Snds: %d"), snd_num_playing() );
2862 if ( Timing_total > 0.01f ) {
2863 gr_printf( sx, sy, NOX("CLEAR: %.0f%%"), Timing_clear*100.0f/Timing_total );
2865 gr_printf( sx, sy, NOX("REND2D: %.0f%%"), Timing_render2*100.0f/Timing_total );
2867 gr_printf( sx, sy, NOX("REND3D: %.0f%%"), Timing_render3*100.0f/Timing_total );
2869 gr_printf( sx, sy, NOX("FLIP: %.0f%%"), Timing_flip*100.0f/Timing_total );
2871 gr_printf( sx, sy, NOX("GAME: %.0f%%"), (Timing_total-(Timing_render2+Timing_render3+Timing_flip+Timing_clear))*100.0f/Timing_total );
2881 dy = gr_get_font_height() + 1;
2883 gr_set_color_fast(&HUD_color_debug);
2886 extern int TotalRam;
2887 gr_printf( sx, sy, NOX("DYN: %d KB\n"), TotalRam/1024 );
2892 extern int Model_ram;
2893 gr_printf( sx, sy, NOX("POF: %d KB\n"), Model_ram/1024 );
2897 gr_printf( sx, sy, NOX("BMP: %d KB\n"), bm_texture_ram/1024 );
2899 gr_printf( sx, sy, NOX("S-SRAM: %d KB\n"), Snd_sram/1024 ); // mem used to store game sound
2901 gr_printf( sx, sy, NOX("S-HRAM: %d KB\n"), Snd_hram/1024 ); // mem used to store game sound
2905 extern int D3D_textures_in;
2906 extern int Glide_textures_in;
2907 extern int Glide_textures_in_frame;
2908 extern int Glide_explosion_vram;
2909 gr_printf( sx, sy, NOX("VRAM: %d KB\n"), (D3D_textures_in+Glide_textures_in)/1024 );
2911 gr_printf( sx, sy, NOX("VRAM: +%d KB\n"), (Glide_textures_in_frame)/1024 );
2913 gr_printf( sx, sy, NOX("EXP VRAM: %dKB\n"), (Glide_explosion_vram)/1024 );
2920 if ( Show_player_pos ) {
2924 gr_printf(sx, sy, NOX("Player Pos: (%d,%d,%d)"), fl2i(Player_obj->pos.xyz.x), fl2i(Player_obj->pos.xyz.y), fl2i(Player_obj->pos.xyz.z));
2927 MONITOR_INC(NumPolys, modelstats_num_polys);
2928 MONITOR_INC(NumPolysDrawn, modelstats_num_polys_drawn );
2929 MONITOR_INC(NumVerts, modelstats_num_verts );
2931 modelstats_num_polys = 0;
2932 modelstats_num_polys_drawn = 0;
2933 modelstats_num_verts = 0;
2934 modelstats_num_sortnorms = 0;
2938 void game_show_standalone_framerate()
2940 float frame_rate=30.0f;
2941 if ( frame_int == -1 ) {
2943 for (i=0; i<FRAME_FILTER; i++ ) {
2944 frametimes[i] = 0.0f;
2949 frametotal -= frametimes[frame_int];
2950 frametotal += flFrametime;
2951 frametimes[frame_int] = flFrametime;
2952 frame_int = (frame_int + 1 ) % FRAME_FILTER;
2954 if ( frametotal != 0.0 ) {
2955 if ( Framecount >= FRAME_FILTER ){
2956 frame_rate = FRAME_FILTER / frametotal;
2958 frame_rate = Framecount / frametotal;
2961 std_set_standalone_fps(frame_rate);
2965 // function to show the time remaining in a mission. Used only when the end-mission sexpression is used
2966 void game_show_time_left()
2970 // mission_end_time is a global from missionparse.cpp that contains the mission time at which the
2971 // mission should end (in fixed seconds). There is code in missionparse.cpp which actually handles
2972 // checking how much time is left
2974 if ( Mission_end_time == -1 ){
2978 diff = f2i(Mission_end_time - Missiontime);
2979 // be sure to bash to 0. diff could be negative on frame that we quit mission
2984 hud_set_default_color();
2985 gr_printf( 5, 40, XSTR( "Mission time remaining: %d seconds", 179), diff );
2988 //========================================================================================
2989 //=================== NEW DEBUG CONSOLE COMMANDS TO REPLACE OLD DEBUG PAUSE MENU =========
2990 //========================================================================================
2994 DCF(ai_pause,"Pauses ai")
2997 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2998 if ( Dc_arg_type & ARG_TRUE ) ai_paused = 1;
2999 else if ( Dc_arg_type & ARG_FALSE ) ai_paused = 0;
3000 else if ( Dc_arg_type & ARG_NONE ) ai_paused = !ai_paused;
3003 obj_init_all_ships_physics();
3006 if ( Dc_help ) dc_printf( "Usage: ai_paused [bool]\nSets ai_paused to true or false. If nothing passed, then toggles it.\n" );
3007 if ( Dc_status ) dc_printf( "ai_paused is %s\n", (ai_paused?"TRUE":"FALSE") );
3010 DCF(single_step,"Single steps the game")
3013 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
3014 if ( Dc_arg_type & ARG_TRUE ) game_single_step = 1;
3015 else if ( Dc_arg_type & ARG_FALSE ) game_single_step = 0;
3016 else if ( Dc_arg_type & ARG_NONE ) game_single_step = !game_single_step;
3018 last_single_step = 0; // Make so single step waits a frame before stepping
3021 if ( Dc_help ) dc_printf( "Usage: single_step [bool]\nSets single_step to true or false. If nothing passed, then toggles it.\n" );
3022 if ( Dc_status ) dc_printf( "single_step is %s\n", (game_single_step?"TRUE":"FALSE") );
3025 DCF_BOOL(physics_pause, physics_paused)
3026 DCF_BOOL(ai_rendering, Ai_render_debug_flag)
3027 DCF_BOOL(ai_firing, Ai_firing_enabled )
3029 // Create some simple aliases to these commands...
3030 debug_command dc_s("s","shortcut for single_step",dcf_single_step);
3031 debug_command dc_p("p","shortcut for physics_pause", dcf_physics_pause );
3032 debug_command dc_r("r","shortcut for ai_rendering", dcf_ai_rendering );
3033 debug_command dc_f("f","shortcut for ai_firing", dcf_ai_firing);
3034 debug_command dc_a("a","shortcut for ai_pause", dcf_ai_pause);
3037 //========================================================================================
3038 //========================================================================================
3041 void game_training_pause_do()
3045 key = game_check_key();
3047 gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
3054 void game_increase_skill_level()
3057 if (Game_skill_level >= NUM_SKILL_LEVELS){
3058 Game_skill_level = 0;
3062 int Player_died_time;
3064 int View_percent = 100;
3067 DCF(view, "Sets the percent of the 3d view to render.")
3070 dc_get_arg(ARG_INT);
3071 if ( (Dc_arg_int >= 5 ) || (Dc_arg_int <= 100) ) {
3072 View_percent = Dc_arg_int;
3074 dc_printf( "Illegal value for view. (Must be from 5-100) \n\n");
3080 dc_printf("Usage: view [n]\nwhere n is percent of view to show (5-100).\n");
3084 dc_printf("View is set to %d%%\n", View_percent );
3089 // Set the clip region for the 3d rendering window
3090 void game_set_view_clip()
3092 if ((Game_mode & GM_DEAD) || (supernova_active() >= 2)) {
3093 // Set the clip region for the letterbox "dead view"
3094 int yborder = gr_screen.max_h/4;
3096 // Numeric constants encouraged by J "pig farmer" S, who shall remain semi-anonymous.
3097 // J.S. I've changed my ways!! See the new "no constants" code!!!
3098 gr_set_clip(0, yborder, gr_screen.max_w, gr_screen.max_h - yborder*2 );
3100 // Set the clip region for normal view
3101 if ( View_percent >= 100 ) {
3104 int xborder, yborder;
3106 if ( View_percent < 5 ) {
3110 float fp = i2fl(View_percent)/100.0f;
3111 int fi = fl2i(fl_sqrt(fp)*100.0f);
3112 if ( fi > 100 ) fi=100;
3114 xborder = ( gr_screen.max_w*(100-fi) )/200;
3115 yborder = ( gr_screen.max_h*(100-fi) )/200;
3117 gr_set_clip(xborder, yborder, gr_screen.max_w-xborder*2,gr_screen.max_h-yborder*2 );
3123 void show_debug_stuff()
3126 int laser_count = 0, missile_count = 0;
3128 for (i=0; i<MAX_OBJECTS; i++) {
3129 if (Objects[i].type == OBJ_WEAPON){
3130 if (Weapon_info[Weapons[Objects[i].instance].weapon_info_index].subtype == WP_LASER){
3132 } else if (Weapon_info[Weapons[Objects[i].instance].weapon_info_index].subtype == WP_MISSILE){
3138 nprintf(("Mike", "Frame: %i Lasers: %4i, Missiles: %4i\n", Framecount, laser_count, missile_count));
3141 extern int Tool_enabled;
3146 int tst_bitmap = -1;
3148 float tst_offset, tst_offset_total;
3151 void game_tst_frame_pre()
3159 g3_rotate_vertex(&v, &tst_pos);
3160 g3_project_vertex(&v);
3163 if(!((v.sx >= 0) && (v.sx <= gr_screen.max_w) && (v.sy >= 0) && (v.sy <= gr_screen.max_h))){
3167 // big ship? always tst
3169 // within 3000 meters
3170 if( vm_vec_dist_quick(&tst_pos, &Eye_position) <= 3000.0f){
3174 // within 300 meters
3175 if( (vm_vec_dist_quick(&tst_pos, &Eye_position) <= 300.0f) && ((tst_time == 0) || ((time(NULL) - tst_time) >= 10)) ){
3182 void game_tst_frame()
3192 tst_time = time(NULL);
3194 // load the tst bitmap
3195 switch((int)frand_range(0.0f, 3.0)){
3197 tst_bitmap = bm_load("ig_jim");
3199 mprintf(("TST 0\n"));
3203 tst_bitmap = bm_load("ig_kan");
3205 mprintf(("TST 1\n"));
3209 tst_bitmap = bm_load("ig_jim");
3211 mprintf(("TST 2\n"));
3215 tst_bitmap = bm_load("ig_kan");
3217 mprintf(("TST 3\n"));
3226 // get the tst bitmap dimensions
3228 bm_get_info(tst_bitmap, &w, &h);
3231 tst_y = frand_range(0.0f, (float)gr_screen.max_h - h);
3233 snd_play(&Snds[SND_VASUDAN_BUP]);
3235 // tst x and direction
3239 tst_offset_total = (float)w;
3240 tst_offset = (float)w;
3242 tst_x = (float)gr_screen.max_w;
3243 tst_offset_total = (float)-w;
3244 tst_offset = (float)w;
3252 float diff = (tst_offset_total / 0.5f) * flFrametime;
3258 tst_offset -= fl_abs(diff);
3259 } else if(tst_mode == 2){
3262 tst_offset -= fl_abs(diff);
3266 gr_set_bitmap(tst_bitmap);
3267 gr_bitmap((int)tst_x, (int)tst_y);
3270 if(timestamp_elapsed_safe(tst_stamp, 1100)){
3274 // if we passed the switch point
3275 if(tst_offset <= 0.0f){
3280 tst_stamp = timestamp(1000);
3281 tst_offset = fl_abs(tst_offset_total);
3292 void game_tst_mark(object *objp, ship *shipp)
3301 if((objp == NULL) || (shipp == NULL) || (shipp->ship_info_index < 0) || (shipp->ship_info_index >= Num_ship_types)){
3304 sip = &Ship_info[shipp->ship_info_index];
3311 tst_pos = objp->pos;
3312 if(sip->flags & (SIF_BIG_SHIP | SIF_HUGE_SHIP)){
3318 extern void render_shields();
3320 void player_repair_frame(float frametime)
3322 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
3324 for(idx=0;idx<MAX_PLAYERS;idx++){
3327 np = &Net_players[idx];
3329 if(MULTI_CONNECTED(Net_players[idx]) && (Net_player != NULL) && (Net_player->player_id != Net_players[idx].player_id) && (Net_players[idx].player != NULL) && (Net_players[idx].player->objnum >= 0) && (Net_players[idx].player->objnum < MAX_OBJECTS)){
3331 // don't rearm/repair if the player is dead or dying/departing
3332 if ( !NETPLAYER_IS_DEAD(np) && !(Ships[Objects[np->player->objnum].instance].flags & (SF_DYING|SF_DEPARTING)) ) {
3333 ai_do_repair_frame(&Objects[Net_players[idx].player->objnum],&Ai_info[Ships[Objects[Net_players[idx].player->objnum].instance].ai_index],frametime);
3338 if ( (Player_obj != NULL) && (Player_obj->type == OBJ_SHIP) && !(Game_mode & GM_STANDALONE_SERVER) && (Player_ship != NULL) && !(Player_ship->flags & SF_DYING) ) {
3339 ai_do_repair_frame(Player_obj, &Ai_info[Ships[Player_obj->instance].ai_index], frametime);
3345 #define NUM_FRAMES_TEST 300
3346 #define NUM_MIXED_SOUNDS 16
3347 void do_timing_test(float flFrametime)
3349 static int framecount = 0;
3350 static int test_running = 0;
3351 static float test_time = 0.0f;
3353 static int snds[NUM_MIXED_SOUNDS];
3356 if ( test_running ) {
3358 test_time += flFrametime;
3359 if ( framecount >= NUM_FRAMES_TEST ) {
3361 nprintf(("General", "%d frames took %.3f seconds\n", NUM_FRAMES_TEST, test_time));
3362 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3367 if ( Test_begin == 1 ) {
3373 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3376 // start looping digital sounds
3377 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3378 snds[i] = snd_play_looping( &Snds[i], 0.0f, -1, -1);
3385 DCF(dcf_fov, "Change the field of view")
3388 dc_get_arg(ARG_FLOAT|ARG_NONE);
3389 if ( Dc_arg_type & ARG_NONE ) {
3390 Viewer_zoom = VIEWER_ZOOM_DEFAULT;
3391 dc_printf( "Zoom factor reset\n" );
3393 if ( Dc_arg_type & ARG_FLOAT ) {
3394 if (Dc_arg_float < 0.25f) {
3395 Viewer_zoom = 0.25f;
3396 dc_printf("Zoom factor pinned at 0.25.\n");
3397 } else if (Dc_arg_float > 1.25f) {
3398 Viewer_zoom = 1.25f;
3399 dc_printf("Zoom factor pinned at 1.25.\n");
3401 Viewer_zoom = Dc_arg_float;
3407 dc_printf( "Usage: fov [factor]\nFactor is the zoom factor btwn .25 and 1.25\nNo parameter resets it to default.\n" );
3410 dc_printf("Zoom factor set to %6.3f (original = 0.5, John = 0.75)", Viewer_zoom);
3414 DCF(framerate_cap, "Sets the framerate cap")
3417 dc_get_arg(ARG_INT);
3418 if ( (Dc_arg_int >= 1 ) || (Dc_arg_int <= 120) ) {
3419 Framerate_cap = Dc_arg_int;
3421 dc_printf( "Illegal value for framerate cap. (Must be from 1-120) \n\n");
3427 dc_printf("Usage: framerate_cap [n]\nwhere n is the frames per second to cap framerate at.\n");
3428 dc_printf("If n is 0 or omitted, then the framerate cap is removed\n");
3429 dc_printf("[n] must be from 1 to 120.\n");
3433 if ( Framerate_cap )
3434 dc_printf("Framerate cap is set to %d fps\n", Framerate_cap );
3436 dc_printf("There is no framerate cap currently active.\n");
3440 #define MIN_DIST_TO_DEAD_CAMERA 50.0f
3441 int Show_viewing_from_self = 0;
3443 void say_view_target()
3445 object *view_target;
3447 if ((Viewer_mode & VM_OTHER_SHIP) && (Player_ai->target_objnum != -1))
3448 view_target = &Objects[Player_ai->target_objnum];
3450 view_target = Player_obj;
3452 if (Game_mode & GM_DEAD) {
3453 if (Player_ai->target_objnum != -1)
3454 view_target = &Objects[Player_ai->target_objnum];
3457 if (!(Game_mode & GM_DEAD_DIED) && ((Game_mode & (GM_DEAD_BLEW_UP)) || ((Last_view_target != NULL) && (Last_view_target != view_target)))) {
3458 if (view_target != Player_obj){
3460 char *view_target_name = NULL;
3461 switch(Objects[Player_ai->target_objnum].type) {
3463 view_target_name = Ships[Objects[Player_ai->target_objnum].instance].ship_name;
3466 view_target_name = Weapon_info[Weapons[Objects[Player_ai->target_objnum].instance].weapon_info_index].name;
3467 Viewer_mode &= ~VM_OTHER_SHIP;
3469 case OBJ_JUMP_NODE: {
3470 char jump_node_name[128];
3471 strcpy(jump_node_name, XSTR( "jump node", 184));
3472 view_target_name = jump_node_name;
3473 Viewer_mode &= ~VM_OTHER_SHIP;
3482 if ( view_target_name ) {
3483 HUD_fixed_printf(0.0f, XSTR( "Viewing %s%s\n", 185), (Viewer_mode & VM_OTHER_SHIP) ? XSTR( "from ", 186) : "", view_target_name);
3484 Show_viewing_from_self = 1;
3487 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER) && (Player_obj->type == OBJ_OBSERVER)){
3488 HUD_fixed_printf(2.0f,XSTR( "Viewing from observer\n", 187));
3489 Show_viewing_from_self = 1;
3491 if (Show_viewing_from_self)
3492 HUD_fixed_printf(2.0f, XSTR( "Viewing from self\n", 188));
3497 Last_view_target = view_target;
3501 float Game_hit_x = 0.0f;
3502 float Game_hit_y = 0.0f;
3504 // Reset at the beginning of each frame
3505 void game_whack_reset()
3511 // Apply a 2d whack to the player
3512 void game_whack_apply( float x, float y )
3514 // Do some force feedback
3515 joy_ff_play_dir_effect(x * 80.0f, y * 80.0f);
3521 // mprintf(( "WHACK = %.1f, %.1f\n", Game_hit_x, Game_hit_y ));
3524 // call to apply a "shudder"
3525 void game_shudder_apply(int time, float intensity)
3527 Game_shudder_time = timestamp(time);
3528 Game_shudder_total = time;
3529 Game_shudder_intensity = intensity;
3532 #define FF_SCALE 10000
3533 void apply_hud_shake(matrix *eye_orient)
3535 if (Viewer_obj == Player_obj) {
3536 physics_info *pi = &Player_obj->phys_info;
3544 // Make eye shake due to afterburner
3545 if ( !timestamp_elapsed(pi->afterburner_decay) ) {
3548 dtime = timestamp_until(pi->afterburner_decay);
3552 tangles.p += 0.07f * (float) (r1-RAND_MAX/2)/RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/ABURN_DECAY_TIME));
3553 tangles.h += 0.07f * (float) (r2-RAND_MAX/2)/RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/ABURN_DECAY_TIME));
3556 // Make eye shake due to engine wash
3558 if (Player_obj->type == OBJ_SHIP && (Ships[Player_obj->instance].wash_intensity > 0) && Wash_on ) {
3561 tangles.p += 0.07f * Ships[Player_obj->instance].wash_intensity * (float) (r1-RAND_MAX/2)/RAND_MAX;
3562 tangles.h += 0.07f * Ships[Player_obj->instance].wash_intensity * (float) (r2-RAND_MAX/2)/RAND_MAX;
3564 // get the intensity
3565 float intensity = FF_SCALE * Ships[Player_obj->instance].wash_intensity;
3569 vm_vec_rand_vec_quick(&rand_vec);
3572 joy_ff_play_dir_effect(intensity*rand_vec.xyz.x, intensity*rand_vec.xyz.y);
3576 // make hud shake due to shuddering
3577 if(Game_shudder_time != -1){
3578 // if the timestamp has elapsed
3579 if(timestamp_elapsed(Game_shudder_time)){
3580 Game_shudder_time = -1;
3582 // otherwise apply some shudder
3586 dtime = timestamp_until(Game_shudder_time);
3590 tangles.p += (Game_shudder_intensity / 200.0f) * (float) (r1-RAND_MAX/2)/RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/(float)Game_shudder_total));
3591 tangles.h += (Game_shudder_intensity / 200.0f) * (float) (r2-RAND_MAX/2)/RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/(float)Game_shudder_total));
3596 vm_angles_2_matrix(&tm, &tangles);
3597 Assert(vm_vec_mag(&tm.v.fvec) > 0.0f);
3598 Assert(vm_vec_mag(&tm.v.rvec) > 0.0f);
3599 Assert(vm_vec_mag(&tm.v.uvec) > 0.0f);
3600 vm_matrix_x_matrix(&tm2, eye_orient, &tm);
3605 extern void compute_slew_matrix(matrix *orient, angles *a); // TODO: move code to proper place and extern in header file
3607 // Player's velocity just before he blew up. Used to keep camera target moving.
3608 vector Dead_player_last_vel = {1.0f, 1.0f, 1.0f};
3610 // Set eye_pos and eye_orient based on view mode.
3611 void game_render_frame_setup(vector *eye_pos, matrix *eye_orient)
3615 static int last_Viewer_mode = 0;
3616 static int last_Game_mode = 0;
3617 static int last_Viewer_objnum = -1;
3619 // This code is supposed to detect camera "cuts"... like going between
3622 // determine if we need to regenerate the nebula
3623 if( (!(last_Viewer_mode & VM_EXTERNAL) && (Viewer_mode & VM_EXTERNAL)) || // internal to external
3624 ((last_Viewer_mode & VM_EXTERNAL) && !(Viewer_mode & VM_EXTERNAL)) || // external to internal
3625 (!(last_Viewer_mode & VM_DEAD_VIEW) && (Viewer_mode & VM_DEAD_VIEW)) || // non dead-view to dead-view
3626 ((last_Viewer_mode & VM_DEAD_VIEW) && !(Viewer_mode & VM_DEAD_VIEW)) || // dead-view to non dead-view
3627 (!(last_Viewer_mode & VM_WARP_CHASE) && (Viewer_mode & VM_WARP_CHASE)) || // non warp-chase to warp-chase
3628 ((last_Viewer_mode & VM_WARP_CHASE) && !(Viewer_mode & VM_WARP_CHASE)) || // warp-chase to non warp-chase
3629 (!(last_Viewer_mode & VM_OTHER_SHIP) && (Viewer_mode & VM_OTHER_SHIP)) || // non other-ship to other-ship
3630 ((last_Viewer_mode & VM_OTHER_SHIP) && !(Viewer_mode & VM_OTHER_SHIP)) || // other-ship to non-other ship
3631 ((Viewer_mode & VM_OTHER_SHIP) && (last_Viewer_objnum != Player_ai->target_objnum)) // other ship mode, but targets changes
3634 // regenerate the nebula
3638 if ( (last_Viewer_mode != Viewer_mode) || (last_Game_mode != Game_mode) ) {
3639 //mprintf(( "************** Camera cut! ************\n" ));
3640 last_Viewer_mode = Viewer_mode;
3641 last_Game_mode = Game_mode;
3643 // Camera moved. Tell stars & debris to not do blurring.
3649 if ( Viewer_mode & VM_PADLOCK_ANY ) {
3650 player_display_packlock_view();
3653 game_set_view_clip();
3655 if (Game_mode & GM_DEAD) {
3656 vector vec_to_deader, view_pos;
3659 Viewer_mode |= VM_DEAD_VIEW;
3661 if (Player_ai->target_objnum != -1) {
3662 int view_from_player = 1;
3664 if (Viewer_mode & VM_OTHER_SHIP) {
3665 // View from target.
3666 Viewer_obj = &Objects[Player_ai->target_objnum];
3668 last_Viewer_objnum = Player_ai->target_objnum;
3670 if ( Viewer_obj->type == OBJ_SHIP ) {
3671 ship_get_eye( eye_pos, eye_orient, Viewer_obj );
3672 view_from_player = 0;
3675 last_Viewer_objnum = -1;
3678 if ( view_from_player ) {
3679 // View target from player ship.
3681 *eye_pos = Player_obj->pos;
3682 vm_vec_normalized_dir(&eye_dir, &Objects[Player_ai->target_objnum].pos, eye_pos);
3683 vm_vector_2_matrix(eye_orient, &eye_dir, NULL, NULL);
3686 dist = vm_vec_normalized_dir(&vec_to_deader, &Player_obj->pos, &Dead_camera_pos);
3688 if (dist < MIN_DIST_TO_DEAD_CAMERA)
3689 dist += flFrametime * 16.0f;
3691 vm_vec_scale(&vec_to_deader, -dist);
3692 vm_vec_add(&Dead_camera_pos, &Player_obj->pos, &vec_to_deader);
3694 view_pos = Player_obj->pos;
3696 if (!(Game_mode & GM_DEAD_BLEW_UP)) {
3697 Viewer_mode &= ~(VM_EXTERNAL | VM_CHASE);
3698 vm_vec_scale_add2(&Dead_camera_pos, &Original_vec_to_deader, 25.0f * flFrametime);
3699 Dead_player_last_vel = Player_obj->phys_info.vel;
3700 //nprintf(("AI", "Player death roll vel = %7.3f %7.3f %7.3f\n", Player_obj->phys_info.vel.xyz.x, Player_obj->phys_info.vel.xyz.y, Player_obj->phys_info.vel.xyz.z));
3701 } else if (Player_ai->target_objnum != -1) {
3702 view_pos = Objects[Player_ai->target_objnum].pos;
3704 // Make camera follow explosion, but gradually slow down.
3705 vm_vec_scale_add2(&Player_obj->pos, &Dead_player_last_vel, flFrametime);
3706 view_pos = Player_obj->pos;
3707 vm_vec_scale(&Dead_player_last_vel, 0.99f);
3708 vm_vec_scale_add2(&Dead_camera_pos, &Original_vec_to_deader, min(25.0f, vm_vec_mag_quick(&Dead_player_last_vel)) * flFrametime);
3711 *eye_pos = Dead_camera_pos;
3713 vm_vec_normalized_dir(&eye_dir, &Player_obj->pos, eye_pos);
3715 vm_vector_2_matrix(eye_orient, &eye_dir, NULL, NULL);
3720 // if supernova shockwave
3721 if(supernova_camera_cut()){
3725 // call it dead view
3726 Viewer_mode |= VM_DEAD_VIEW;
3728 // set eye pos and orient
3729 supernova_set_view(eye_pos, eye_orient);
3731 // If already blown up, these other modes can override.
3732 if (!(Game_mode & (GM_DEAD | GM_DEAD_BLEW_UP))) {
3733 Viewer_mode &= ~VM_DEAD_VIEW;
3735 Viewer_obj = Player_obj;
3737 if (Viewer_mode & VM_OTHER_SHIP) {
3738 if (Player_ai->target_objnum != -1){
3739 Viewer_obj = &Objects[Player_ai->target_objnum];
3740 last_Viewer_objnum = Player_ai->target_objnum;
3742 Viewer_mode &= ~VM_OTHER_SHIP;
3743 last_Viewer_objnum = -1;
3746 last_Viewer_objnum = -1;
3749 if (Viewer_mode & VM_EXTERNAL) {
3752 vm_angles_2_matrix(&tm2, &Viewer_external_info.angles);
3753 vm_matrix_x_matrix(&tm, &Viewer_obj->orient, &tm2);
3755 vm_vec_scale_add(eye_pos, &Viewer_obj->pos, &tm.v.fvec, 2.0f * Viewer_obj->radius + Viewer_external_info.distance);
3757 vm_vec_sub(&eye_dir, &Viewer_obj->pos, eye_pos);
3758 vm_vec_normalize(&eye_dir);
3759 vm_vector_2_matrix(eye_orient, &eye_dir, &Viewer_obj->orient.v.uvec, NULL);
3762 // Modify the orientation based on head orientation.
3763 compute_slew_matrix(eye_orient, &Viewer_slew_angles);
3765 } else if ( Viewer_mode & VM_CHASE ) {
3768 if ( Viewer_obj->phys_info.speed < 0.1 )
3769 move_dir = Viewer_obj->orient.v.fvec;
3771 move_dir = Viewer_obj->phys_info.vel;
3772 vm_vec_normalize(&move_dir);
3775 vm_vec_scale_add(eye_pos, &Viewer_obj->pos, &move_dir, -3.0f * Viewer_obj->radius - Viewer_chase_info.distance);
3776 vm_vec_scale_add2(eye_pos, &Viewer_obj->orient.v.uvec, 0.75f * Viewer_obj->radius);
3777 vm_vec_sub(&eye_dir, &Viewer_obj->pos, eye_pos);
3778 vm_vec_normalize(&eye_dir);
3780 // JAS: I added the following code because if you slew up using
3781 // Descent-style physics, eye_dir and Viewer_obj->orient.v.uvec are
3782 // equal, which causes a zero-length vector in the vm_vector_2_matrix
3783 // call because the up and the forward vector are the same. I fixed
3784 // it by adding in a fraction of the right vector all the time to the
3786 vector tmp_up = Viewer_obj->orient.v.uvec;
3787 vm_vec_scale_add2( &tmp_up, &Viewer_obj->orient.v.rvec, 0.00001f );
3789 vm_vector_2_matrix(eye_orient, &eye_dir, &tmp_up, NULL);
3792 // Modify the orientation based on head orientation.
3793 compute_slew_matrix(eye_orient, &Viewer_slew_angles);
3794 } else if ( Viewer_mode & VM_WARP_CHASE ) {
3795 *eye_pos = Camera_pos;
3797 ship * shipp = &Ships[Player_obj->instance];
3799 vm_vec_sub(&eye_dir, &shipp->warp_effect_pos, eye_pos);
3800 vm_vec_normalize(&eye_dir);
3801 vm_vector_2_matrix(eye_orient, &eye_dir, &Player_obj->orient.v.uvec, NULL);
3804 // get an eye position based upon the correct type of object
3805 switch(Viewer_obj->type){
3807 // make a call to get the eye point for the player object
3808 ship_get_eye( eye_pos, eye_orient, Viewer_obj );
3811 // make a call to get the eye point for the player object
3812 observer_get_eye( eye_pos, eye_orient, Viewer_obj );
3818 #ifdef JOHNS_DEBUG_CODE
3819 john_debug_stuff(&eye_pos, &eye_orient);
3825 apply_hud_shake(eye_orient);
3827 // setup neb2 rendering
3828 neb2_render_setup(eye_pos, eye_orient);
3832 extern void ai_debug_render_stuff();
3835 int Game_subspace_effect = 0;
3836 DCF_BOOL( subspace, Game_subspace_effect );
3838 // Does everything needed to render a frame
3839 void game_render_frame( vector * eye_pos, matrix * eye_orient )
3843 g3_start_frame(game_zbuffer);
3844 g3_set_view_matrix( eye_pos, eye_orient, Viewer_zoom );
3846 // maybe offset the HUD (jitter stuff)
3847 dont_offset = ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER));
3848 HUD_set_offsets(Viewer_obj, !dont_offset);
3850 // for multiplayer clients, call code in Shield.cpp to set up the Shield_hit array. Have to
3851 // do this becaues of the disjointed nature of this system (in terms of setup and execution).
3852 // must be done before ships are rendered
3853 if ( MULTIPLAYER_CLIENT ) {
3854 shield_point_multi_setup();
3857 if ( Game_subspace_effect ) {
3858 stars_draw(0,0,0,1);
3860 stars_draw(1,1,1,0);
3863 obj_render_all(obj_render);
3864 beam_render_all(); // render all beam weapons
3865 particle_render_all(); // render particles after everything else.
3866 trail_render_all(); // render missilie trails after everything else.
3867 mflash_render_all(); // render all muzzle flashes
3869 // Why do we not show the shield effect in these modes? Seems ok.
3870 //if (!(Viewer_mode & (VM_EXTERNAL | VM_SLEWED | VM_CHASE | VM_DEAD_VIEW))) {
3874 // render nebula lightning
3877 // render local player nebula
3878 neb2_render_player();
3881 ai_debug_render_stuff();
3884 #ifndef RELEASE_REAL
3885 // game_framerate_check();
3889 extern void snd_spew_debug_info();
3890 snd_spew_debug_info();
3893 //================ END OF 3D RENDERING STUFF ====================
3897 if( (Game_detail_flags & DETAIL_FLAG_HUD) && !(Game_mode & GM_MULTIPLAYER) || ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER) ) ) {
3898 hud_maybe_clear_head_area();
3899 anim_render_all(0, flFrametime);
3902 extern int Multi_display_netinfo;
3903 if(Multi_display_netinfo){
3904 extern void multi_display_netinfo();
3905 multi_display_netinfo();
3908 game_tst_frame_pre();
3911 do_timing_test(flFrametime);
3915 extern int OO_update_index;
3916 multi_rate_display(OO_update_index, 375, 0);
3921 extern void oo_display();
3928 //#define JOHNS_DEBUG_CODE 1
3930 #ifdef JOHNS_DEBUG_CODE
3931 void john_debug_stuff(vector *eye_pos, matrix *eye_orient)
3933 //if ( keyd_pressed[KEY_LSHIFT] )
3935 ship_subsys *tsys = Players[Player_num].targeted_subobject;
3937 model_subsystem *turret = tsys->system_info;
3939 if (turret->type == SUBSYSTEM_TURRET ) {
3940 vector v.fvec, v.uvec;
3941 object * tobj = &Objects[Players[Player_num].targeted_subobject_parent];
3943 ship_model_start(tobj);
3945 model_find_world_point(eye_pos, &turret->turret_firing_point[0], turret->model_num, turret->turret_gun_sobj, &tobj->orient, &tobj->pos );
3946 model_find_world_dir(&v.fvec, &turret->turret_matrix.v.fvec, turret->model_num, turret->turret_gun_sobj, &tobj->orient, NULL );
3947 model_find_world_dir(&v.uvec, &turret->turret_matrix.v.uvec, turret->model_num, turret->turret_gun_sobj, &tobj->orient, NULL );
3949 vm_vector_2_matrix( eye_orient, &v.fvec, &v.uvec, NULL );
3951 ship_model_stop(tobj);
3961 // following function for dumping frames for purposes of building trailers.
3964 // function to toggle state of dumping every frame into PCX when playing the game
3965 DCF(dump_frames, "Starts/stop frame dumping at 15 hz")
3969 if ( Debug_dump_frames == 0 ) {
3971 Debug_dump_frames = 15;
3972 Debug_dump_trigger = 0;
3973 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
3974 dc_printf( "Frame dumping at 15 hz is now ON\n" );
3977 Debug_dump_frames = 0;
3978 Debug_dump_trigger = 0;
3979 gr_dump_frame_stop();
3980 dc_printf( "Frame dumping is now OFF\n" );
3986 DCF(dump_frames_trigger, "Starts/stop frame dumping at 15 hz")
3990 if ( Debug_dump_frames == 0 ) {
3992 Debug_dump_frames = 15;
3993 Debug_dump_trigger = 1;
3994 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
3995 dc_printf( "Frame dumping at 15 hz is now ON\n" );
3998 Debug_dump_frames = 0;
3999 Debug_dump_trigger = 0;
4000 gr_dump_frame_stop();
4001 dc_printf( "Frame dumping is now OFF\n" );
4007 DCF(dump_frames30, "Starts/stop frame dumping at 30 hz")
4011 if ( Debug_dump_frames == 0 ) {
4013 Debug_dump_frames = 30;
4014 Debug_dump_trigger = 0;
4015 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
4016 dc_printf( "Frame dumping at 30 hz is now ON\n" );
4019 Debug_dump_frames = 0;
4020 Debug_dump_trigger = 0;
4021 gr_dump_frame_stop();
4022 dc_printf( "Frame dumping is now OFF\n" );
4028 DCF(dump_frames30_trigger, "Starts/stop frame dumping at 30 hz")
4032 if ( Debug_dump_frames == 0 ) {
4034 Debug_dump_frames = 30;
4035 Debug_dump_trigger = 1;
4036 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
4037 dc_printf( "Triggered frame dumping at 30 hz is now ON\n" );
4040 Debug_dump_frames = 0;
4041 Debug_dump_trigger = 0;
4042 gr_dump_frame_stop();
4043 dc_printf( "Triggered frame dumping is now OFF\n" );
4049 void game_maybe_dump_frame()
4051 if ( !Debug_dump_frames ){
4055 if( Debug_dump_trigger && !keyd_pressed[KEY_Q] ){
4062 Debug_dump_frame_num++;
4068 extern int Player_dead_state;
4070 // Flip the page and time how long it took.
4071 void game_flip_page_and_time_it()
4076 t1 = timer_get_fixed_seconds();
4078 t2 = timer_get_fixed_seconds();
4081 t = (gr_screen.max_w*gr_screen.max_h*gr_screen.bytes_per_pixel)/1024;
4082 sprintf( transfer_text, NOX("%ld MB/s"), fixmuldiv(t,65,d) );
4089 void game_simulation_frame()
4091 // blow ships up in multiplayer dogfight
4092 if((Game_mode & GM_MULTIPLAYER) && (Net_player != NULL) && (Net_player->flags & NETINFO_FLAG_AM_MASTER) && (Netgame.type_flags & NG_TYPE_DOGFIGHT) && (f2fl(Missiontime) >= 2.0f) && !dogfight_blown){
4093 // blow up all non-player ships
4094 ship_obj *moveup = GET_FIRST(&Ship_obj_list);
4097 while((moveup != END_OF_LIST(&Ship_obj_list)) && (moveup != NULL)){
4099 if((moveup->objnum < 0) || (moveup->objnum >= MAX_OBJECTS) || (Objects[moveup->objnum].type != OBJ_SHIP) || (Objects[moveup->objnum].instance < 0) || (Objects[moveup->objnum].instance >= MAX_SHIPS) || (Ships[Objects[moveup->objnum].instance].ship_info_index < 0) || (Ships[Objects[moveup->objnum].instance].ship_info_index >= Num_ship_types)){
4100 moveup = GET_NEXT(moveup);
4103 shipp = &Ships[Objects[moveup->objnum].instance];
4104 sip = &Ship_info[shipp->ship_info_index];
4106 // only blow up small ships
4107 if((sip->flags & SIF_SMALL_SHIP) && (multi_find_player_by_object(&Objects[moveup->objnum]) < 0) ){
4108 // function to simply explode a ship where it is currently at
4109 ship_self_destruct( &Objects[moveup->objnum] );
4112 moveup = GET_NEXT(moveup);
4118 // process AWACS stuff - do this first thing
4121 // single player, set Player hits_this_frame to 0
4122 if ( !(Game_mode & GM_MULTIPLAYER) && Player ) {
4123 Player->damage_this_burst -= (flFrametime * MAX_BURST_DAMAGE / (0.001f * BURST_DURATION));
4124 Player->damage_this_burst = max(Player->damage_this_burst, 0.0f);
4128 supernova_process();
4129 if(supernova_active() >= 5){
4133 // fire targeting lasers now so that
4134 // 1 - created this frame
4135 // 2 - collide this frame
4136 // 3 - render this frame
4137 // 4 - ignored and deleted next frame
4138 // the basic idea being that because it con be confusing to deal with them on a multi-frame basis, they are only valid for
4140 ship_process_targeting_lasers();
4142 // do this here so that it works for multiplayer
4144 // get viewer direction
4145 int viewer_direction = PHYSICS_VIEWER_REAR;
4147 if(Viewer_mode == 0){
4148 viewer_direction = PHYSICS_VIEWER_FRONT;
4150 if(Viewer_mode & VM_PADLOCK_UP){
4151 viewer_direction = PHYSICS_VIEWER_UP;
4153 else if(Viewer_mode & VM_PADLOCK_REAR){
4154 viewer_direction = PHYSICS_VIEWER_REAR;
4156 else if(Viewer_mode & VM_PADLOCK_LEFT){
4157 viewer_direction = PHYSICS_VIEWER_LEFT;
4159 else if(Viewer_mode & VM_PADLOCK_RIGHT){
4160 viewer_direction = PHYSICS_VIEWER_RIGHT;
4163 physics_set_viewer( &Viewer_obj->phys_info, viewer_direction );
4165 physics_set_viewer( NULL, PHYSICS_VIEWER_FRONT );
4168 #define VM_PADLOCK_UP (1 << 7)
4169 #define VM_PADLOCK_REAR (1 << 8)
4170 #define VM_PADLOCK_LEFT (1 << 9)
4171 #define VM_PADLOCK_RIGHT (1 << 10)
4173 // evaluate mission departures and arrivals before we process all objects.
4174 if ( !(Game_mode & GM_MULTIPLAYER) || ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER) && !multi_endgame_ending()) ) {
4176 // we don't want to evaluate mission stuff when any ingame joiner in multiplayer is receiving
4177 // ships/wing packets.
4178 if ( !((Game_mode & GM_MULTIPLAYER) && (Netgame.flags & NG_FLAG_INGAME_JOINING_CRITICAL)) && !(Game_mode & GM_DEMO_PLAYBACK)){
4179 mission_parse_eval_stuff();
4182 // if we're an observer, move ourselves seperately from the standard physics
4183 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER)){
4184 obj_observer_move(flFrametime);
4187 // move all the objects now
4188 obj_move_all(flFrametime);
4190 // check for cargo reveal (this has an internal timestamp, so only runs every N ms)
4191 // AL: 3-15-98: It was decided to not let AI ships inspect cargo
4192 // ship_check_cargo_all();
4193 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4194 mission_eval_goals();
4198 // always check training objectives, even in multiplayer missions. we need to do this so that the directives gauge works properly on clients
4199 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4200 training_check_objectives();
4203 // do all interpolation now
4204 if ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER) && !multi_endgame_ending() && !(Netgame.flags & NG_FLAG_SERVER_LOST)) {
4205 // client side processing of warping in effect stages
4206 multi_do_client_warp(flFrametime);
4208 // client side movement of an observer
4209 if((Net_player->flags & NETINFO_FLAG_OBSERVER) || (Player_obj->type == OBJ_OBSERVER)){
4210 obj_observer_move(flFrametime);
4213 // move all objects - does interpolation now as well
4214 obj_move_all(flFrametime);
4217 // only process the message queue when the player is "in" the game
4218 if ( !Pre_player_entry ){
4219 message_queue_process(); // process any messages send to the player
4222 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4223 message_maybe_distort(); // maybe distort incoming message if comms damaged
4224 player_repair_frame(flFrametime); // AI objects get repaired in ai_process, called from move code...deal with player.
4225 player_process_pending_praise(); // maybe send off a delayed praise message to the player
4226 player_maybe_play_all_alone_msg(); // mabye tell the player he is all alone
4229 if(!(Game_mode & GM_STANDALONE_SERVER)){
4230 // process some stuff every frame (before frame is rendered)
4231 emp_process_local();
4233 hud_update_frame(); // update hud systems
4235 if (!physics_paused) {
4236 // Move particle system
4237 particle_move_all(flFrametime);
4239 // Move missile trails
4240 trail_move_all(flFrametime);
4242 // process muzzle flashes
4243 mflash_process_all();
4245 // Flash the gun flashes
4246 shipfx_flash_do_frame(flFrametime);
4248 shockwave_move_all(flFrametime); // update all the shockwaves
4251 // subspace missile strikes
4254 obj_snd_do_frame(); // update the object-linked persistant sounds
4255 game_maybe_update_sound_environment();
4256 snd_update_listener(&View_position, &Player_obj->phys_info.vel, &Player_obj->orient);
4258 // AL: debug code used for testing ambient subspace sound (ie when enabling subspace through debug console)
4260 if ( Game_subspace_effect ) {
4261 game_start_subspace_ambient_sound();
4267 // Maybe render and process the dead-popup
4268 void game_maybe_do_dead_popup(float frametime)
4270 if ( popupdead_is_active() ) {
4272 int choice = popupdead_do_frame(frametime);
4274 if ( Game_mode & GM_NORMAL ) {
4278 if(game_do_cd_mission_check(Game_current_mission_filename)){
4279 gameseq_post_event(GS_EVENT_ENTER_GAME);
4281 gameseq_post_event(GS_EVENT_MAIN_MENU);
4286 gameseq_post_event(GS_EVENT_END_GAME);
4291 if(game_do_cd_mission_check(Game_current_mission_filename)){
4292 gameseq_post_event(GS_EVENT_START_GAME);
4294 gameseq_post_event(GS_EVENT_MAIN_MENU);
4298 // this should only happen during a red alert mission
4301 Assert(The_mission.red_alert);
4302 if(!The_mission.red_alert){
4304 if(game_do_cd_mission_check(Game_current_mission_filename)){
4305 gameseq_post_event(GS_EVENT_START_GAME);
4307 gameseq_post_event(GS_EVENT_MAIN_MENU);
4312 // choose the previous mission
4313 mission_campaign_previous_mission();
4315 if(game_do_cd_mission_check(Game_current_mission_filename)){
4316 gameseq_post_event(GS_EVENT_START_GAME);
4318 gameseq_post_event(GS_EVENT_MAIN_MENU);
4329 case POPUPDEAD_DO_MAIN_HALL:
4330 multi_quit_game(PROMPT_NONE,-1);
4333 case POPUPDEAD_DO_RESPAWN:
4334 multi_respawn_normal();
4335 event_music_player_respawn();
4338 case POPUPDEAD_DO_OBSERVER:
4339 multi_respawn_observer();
4340 event_music_player_respawn_as_observer();
4349 if ( leave_popup ) {
4355 // returns true if player is actually in a game_play stats
4356 int game_actually_playing()
4360 state = gameseq_get_state();
4361 if ( (state != GS_STATE_GAME_PLAY) && (state != GS_STATE_DEATH_DIED) && (state != GS_STATE_DEATH_BLEW_UP) )
4367 // Draw the 2D HUD gauges
4368 void game_render_hud_2d()
4370 if ( !(Game_detail_flags & DETAIL_FLAG_HUD) ) {
4374 HUD_render_2d(flFrametime);
4378 // Draw the 3D-dependant HUD gauges
4379 void game_render_hud_3d(vector *eye_pos, matrix *eye_orient)
4381 g3_start_frame(0); // 0 = turn zbuffering off
4382 g3_set_view_matrix( eye_pos, eye_orient, Viewer_zoom );
4384 if ( (Game_detail_flags & DETAIL_FLAG_HUD) && (supernova_active() < 3)/* && !(Game_mode & GM_MULTIPLAYER) || ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER) )*/ ) {
4385 HUD_render_3d(flFrametime);
4389 game_sunspot_process(flFrametime);
4391 // Diminish the palette effect
4392 game_flash_diminish(flFrametime);
4400 int actually_playing;
4401 fix total_time1, total_time2;
4402 fix render2_time1=0, render2_time2=0;
4403 fix render3_time1=0, render3_time2=0;
4404 fix flip_time1=0, flip_time2=0;
4405 fix clear_time1=0, clear_time2=0;
4411 if (Framerate_delay) {
4412 int start_time = timer_get_milliseconds();
4413 while (timer_get_milliseconds() < start_time + Framerate_delay)
4419 demo_do_frame_start();
4421 mprintf(("Error (%d) while processing demo!\n", Demo_error));
4426 // start timing frame
4427 timing_frame_start();
4429 total_time1 = timer_get_fixed_seconds();
4431 // var to hold which state we are in
4432 actually_playing = game_actually_playing();
4434 if ((!(Game_mode & GM_MULTIPLAYER)) || ((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER))) {
4435 if (!(Game_mode & GM_STANDALONE_SERVER)){
4436 Assert( OBJ_INDEX(Player_obj) >= 0 );
4440 if (Missiontime > Entry_delay_time){
4441 Pre_player_entry = 0;
4443 ; //nprintf(("AI", "Framecount = %i, time = %7.3f\n", Framecount, f2fl(Missiontime)));
4446 // Note: These are done even before the player enters, else buffers can overflow.
4447 if (! (Game_mode & GM_STANDALONE_SERVER)){
4451 shield_frame_init();
4453 if ( Player->control_mode != PCM_NORMAL )
4456 if ( !Pre_player_entry && actually_playing ) {
4457 if (! (Game_mode & GM_STANDALONE_SERVER) ) {
4459 if( (!popup_running_state()) && (!popupdead_is_active()) ){
4460 game_process_keys();
4462 // don't read flying controls if we're playing a demo back
4463 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4464 read_player_controls( Player_obj, flFrametime);
4468 // if we're not the master, we may have to send the server-critical ship status button_info bits
4469 if ((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER)){
4470 multi_maybe_send_ship_status();
4475 // Reset the whack stuff
4478 // These two lines must be outside of Pre_player_entry code,
4479 // otherwise too many lights are added.
4482 if ((Game_mode & GM_MULTIPLAYER) && (Netgame.game_state == NETGAME_STATE_SERVER_TRANSFER)){
4486 game_simulation_frame();
4488 // if not actually in a game play state, then return. This condition could only be true in
4489 // a multiplayer game.
4490 if ( !actually_playing ) {
4491 Assert( Game_mode & GM_MULTIPLAYER );
4495 if (!Pre_player_entry) {
4496 if (! (Game_mode & GM_STANDALONE_SERVER)) {
4497 clear_time1 = timer_get_fixed_seconds();
4498 // clear the screen to black
4500 if ( (Game_detail_flags & DETAIL_FLAG_CLEAR) ) {
4504 clear_time2 = timer_get_fixed_seconds();
4505 render3_time1 = timer_get_fixed_seconds();
4506 game_render_frame_setup(&eye_pos, &eye_orient);
4507 game_render_frame( &eye_pos, &eye_orient );
4509 // save the eye position and orientation
4510 if ( Game_mode & GM_MULTIPLAYER ) {
4511 Net_player->s_info.eye_pos = eye_pos;
4512 Net_player->s_info.eye_orient = eye_orient;
4515 hud_show_target_model();
4517 // check to see if we should display the death died popup
4518 if(Game_mode & GM_DEAD_BLEW_UP){
4519 if(Game_mode & GM_MULTIPLAYER){
4520 // catch the situation where we're supposed to be warping out on this transition
4521 if(Net_player->flags & NETINFO_FLAG_WARPING_OUT){
4522 gameseq_post_event(GS_EVENT_DEBRIEF);
4523 } else if((Player_died_popup_wait != -1) && (timestamp_elapsed(Player_died_popup_wait))){
4524 Player_died_popup_wait = -1;
4528 if((Player_died_popup_wait != -1) && (timestamp_elapsed(Player_died_popup_wait))){
4529 Player_died_popup_wait = -1;
4535 // hack - sometimes this seems to slip by in multiplayer. this should guarantee that we catch it
4536 if((Game_mode & GM_MULTIPLAYER) && (Player_multi_died_check != -1) && (Game_mode & GM_DEAD_BLEW_UP) ){
4537 if(fl_abs(time(NULL) - Player_multi_died_check) > 4){
4538 if(!popupdead_is_active()){
4542 Player_multi_died_check = -1;
4546 render3_time2 = timer_get_fixed_seconds();
4547 render2_time1 = timer_get_fixed_seconds();
4550 game_get_framerate();
4551 game_show_framerate();
4553 game_show_time_left();
4555 // Draw the 2D HUD gauges
4556 if(supernova_active() < 3){
4557 game_render_hud_2d();
4560 game_set_view_clip();
4562 // Draw 3D HUD gauges
4563 game_render_hud_3d(&eye_pos, &eye_orient);
4567 render2_time2 = timer_get_fixed_seconds();
4569 // maybe render and process the dead popup
4570 game_maybe_do_dead_popup(flFrametime);
4572 // start timing frame
4573 timing_frame_stop();
4574 // timing_display(30, 10);
4576 // If a regular popup is active, don't flip (popup code flips)
4577 if( !popup_running_state() ){
4578 flip_time1 = timer_get_fixed_seconds();
4579 game_flip_page_and_time_it();
4580 flip_time2 = timer_get_fixed_seconds();
4584 game_maybe_dump_frame(); // used to dump pcx files for building trailers
4587 game_show_standalone_framerate();
4591 game_do_training_checks();
4594 // process lightning (nebula only)
4597 total_time2 = timer_get_fixed_seconds();
4599 // Got some timing numbers
4600 Timing_total = f2fl( total_time2 - total_time1 ) * 1000.0f;
4601 Timing_clear = f2fl( clear_time2 - clear_time1 ) * 1000.0f;
4602 Timing_render2 = f2fl( render2_time2- render2_time1 ) * 1000.0f;
4603 Timing_render3 = f2fl( render3_time2- render3_time1 ) * 1000.0f;
4604 Timing_flip = f2fl( flip_time2 - flip_time1 ) * 1000.0f;
4607 demo_do_frame_end();
4609 mprintf(("Error (%d) while processing demo!\n", Demo_error));
4615 #define MAX_FRAMETIME (F1_0/4) // Frametime gets saturated at this. Changed by MK on 11/1/97.
4616 // Some bug was causing Frametime to always get saturated at 2.0 seconds after the player
4617 // died. This resulted in screwed up death sequences.
4619 fix Last_time = 0; // The absolute time of game at end of last frame (beginning of this frame)
4620 fix Last_delta_time = 0; // While game is paused, this keeps track of how much elapsed in the frame before paused.
4621 static int timer_paused=0;
4622 #if defined(TIMER_TEST) && !defined(NDEBUG)
4623 static int stop_count,start_count;
4624 static int time_stopped,time_started;
4626 int saved_timestamp_ticker = -1;
4628 void game_reset_time()
4630 if((Game_mode & GM_MULTIPLAYER) && (Netgame.game_state == NETGAME_STATE_SERVER_TRANSFER)){
4634 // Last_time = timer_get_fixed_seconds();
4640 void game_stop_time()
4642 if (timer_paused==0) {
4644 time = timer_get_fixed_seconds();
4645 // Save how much time progressed so far in the frame so we can
4646 // use it when we unpause.
4647 Last_delta_time = time - Last_time;
4649 //mprintf(("Last_time in game_stop_time = %7.3f\n", f2fl(Last_delta_time)));
4650 if (Last_delta_time < 0) {
4651 #if defined(TIMER_TEST) && !defined(NDEBUG)
4652 Int3(); //get Matt!!!!
4654 Last_delta_time = 0;
4656 #if defined(TIMER_TEST) && !defined(NDEBUG)
4657 time_stopped = time;
4660 // Stop the timer_tick stuff...
4661 // Normally, you should never access 'timestamp_ticker', consider this a low-level routine
4662 saved_timestamp_ticker = timestamp_ticker;
4666 #if defined(TIMER_TEST) && !defined(NDEBUG)
4671 void game_start_time()
4674 Assert(timer_paused >= 0);
4675 if (timer_paused==0) {
4677 time = timer_get_fixed_seconds();
4678 #if defined(TIMER_TEST) && !defined(NDEBUG)
4680 Int3(); //get Matt!!!!
4683 // Take current time, and set it backwards to account for time
4684 // that the frame already executed, so that timer_get_fixed_seconds() - Last_time
4685 // will be correct when it goes to calculate the frametime next
4687 Last_time = time - Last_delta_time;
4688 #if defined(TIMER_TEST) && !defined(NDEBUG)
4689 time_started = time;
4692 // Restore the timer_tick stuff...
4693 // Normally, you should never access 'timestamp_ticker', consider this a low-level routine
4694 Assert( saved_timestamp_ticker > -1 ); // Called out of order, get JAS
4695 timestamp_ticker = saved_timestamp_ticker;
4696 saved_timestamp_ticker = -1;
4699 #if defined(TIMER_TEST) && !defined(NDEBUG)
4705 void game_set_frametime(int state)
4708 float frame_cap_diff;
4710 thistime = timer_get_fixed_seconds();
4712 if ( Last_time == 0 )
4713 Frametime = F1_0 / 30;
4715 Frametime = thistime - Last_time;
4717 // Frametime = F1_0 / 30;
4719 fix debug_frametime = Frametime; // Just used to display frametime.
4721 // If player hasn't entered mission yet, make frame take 1/4 second.
4722 if ((Pre_player_entry) && (state == GS_STATE_GAME_PLAY))
4725 else if ((Debug_dump_frames) && (state == GS_STATE_GAME_PLAY)) { // note link to above if!!!!!
4727 fix frame_speed = F1_0 / Debug_dump_frames;
4729 if (Frametime > frame_speed ){
4730 nprintf(("warning","slow frame: %x\n",Frametime));
4733 thistime = timer_get_fixed_seconds();
4734 Frametime = thistime - Last_time;
4735 } while (Frametime < frame_speed );
4737 Frametime = frame_speed;
4741 Assert( Framerate_cap > 0 );
4743 // Cap the framerate so it doesn't get too high.
4747 cap = F1_0/Framerate_cap;
4748 if (Frametime < cap) {
4749 thistime = cap - Frametime;
4750 //mprintf(("Sleeping for %6.3f seconds.\n", f2fl(thistime)));
4751 Sleep( DWORD(f2fl(thistime) * 1000.0f) );
4753 thistime = timer_get_fixed_seconds();
4757 if((Game_mode & GM_STANDALONE_SERVER) &&
4758 (f2fl(Frametime) < ((float)1.0/(float)Multi_options_g.std_framecap))){
4760 frame_cap_diff = ((float)1.0/(float)Multi_options_g.std_framecap) - f2fl(Frametime);
4761 Sleep((DWORD)(frame_cap_diff*1000));
4763 thistime += fl2f((frame_cap_diff));
4765 Frametime = thistime - Last_time;
4768 // If framerate is too low, cap it.
4769 if (Frametime > MAX_FRAMETIME) {
4771 mprintf(("Frame %2i too long!!: frametime = %.3f (%.3f)\n", Framecount, f2fl(Frametime), f2fl(debug_frametime)));
4773 // to remove warnings in release build
4774 debug_frametime = fl2f(flFrametime);
4776 Frametime = MAX_FRAMETIME;
4779 Frametime = fixmul(Frametime, Game_time_compression);
4781 Last_time = thistime;
4782 //mprintf(("Frame %i, Last_time = %7.3f\n", Framecount, f2fl(Last_time)));
4784 flFrametime = f2fl(Frametime);
4785 //if(!(Game_mode & GM_PLAYING_DEMO)){
4786 timestamp_inc(flFrametime);
4788 /* if ((Framecount > 0) && (Framecount < 10)) {
4789 mprintf(("Frame %2i: frametime = %.3f (%.3f)\n", Framecount, f2fl(Frametime), f2fl(debug_frametime)));
4794 // This is called from game_do_frame(), and from navmap_do_frame()
4795 void game_update_missiontime()
4797 // TODO JAS: Put in if and move this into game_set_frametime,
4798 // fix navmap to call game_stop/start_time
4799 //if ( !timer_paused )
4800 Missiontime += Frametime;
4803 void game_do_frame()
4805 game_set_frametime(GS_STATE_GAME_PLAY);
4806 game_update_missiontime();
4808 if (Game_mode & GM_STANDALONE_SERVER) {
4809 std_multi_set_standalone_missiontime(f2fl(Missiontime));
4812 if ( game_single_step && (last_single_step == game_single_step) ) {
4813 os_set_title( NOX("SINGLE STEP MODE (Pause exits, any other key steps)") );
4814 while( key_checkch() == 0 )
4816 os_set_title( XSTR( "FreeSpace", 171) );
4817 Last_time = timer_get_fixed_seconds();
4820 last_single_step = game_single_step;
4822 if ((gameseq_get_state() == GS_STATE_GAME_PLAY) && Use_mouse_to_fly){
4823 Keep_mouse_centered = 1; // force mouse to center of our window (so we don't hit movement limits)
4827 Keep_mouse_centered = 0;
4828 monitor_update(); // Update monitor variables
4831 void multi_maybe_do_frame()
4833 if ( (Game_mode & GM_MULTIPLAYER) && (Game_mode & GM_IN_MISSION) && !Multi_pause_status){
4838 int Joymouse_button_status = 0;
4840 // Flush all input devices
4848 Joymouse_button_status = 0;
4850 //mprintf(("Game flush!\n" ));
4853 // function for multiplayer only which calls game_do_state_common() when running the
4855 void game_do_dc_networking()
4857 Assert( Game_mode & GM_MULTIPLAYER );
4859 game_do_state_common( gameseq_get_state() );
4862 // Call this whenever in a loop, or when you need to check for a keystroke.
4863 int game_check_key()
4869 // convert keypad enter to normal enter
4870 if ((k & KEY_MASK) == KEY_PADENTER)
4871 k = (k & ~KEY_MASK) | KEY_ENTER;
4876 #if defined(FS2_DEMO) || defined(FS1_DEMO)
4878 #define DEMO_TRAILER_TIMEOUT_MS 45000 // 45 seconds of no input, play trailer
4879 static int Demo_show_trailer_timestamp = 0;
4881 void demo_reset_trailer_timer()
4883 Demo_show_trailer_timestamp = timer_get_milliseconds();
4886 void demo_maybe_show_trailer(int k)
4889 // if key pressed, reset demo trailer timer
4891 demo_reset_trailer_timer();
4895 // if mouse moved, reset demo trailer timer
4898 mouse_get_delta(&dx, &dy);
4899 if ( (dx > 0) || (dy > 0) ) {
4900 demo_reset_trailer_timer();
4904 // if joystick has moved, reset demo trailer timer
4907 joy_get_delta(&dx, &dy);
4908 if ( (dx > 0) || (dy > 0) ) {
4909 demo_reset_trailer_timer();
4913 // NOTE: reseting the trailer timer on mouse/joystick presses is handled in
4914 // the low-level code. Ugly, I know... but was the simplest and most
4917 // if 30 seconds since last demo trailer time reset, launch movie
4918 if ( os_foreground() ) {
4919 int now = timer_get_milliseconds();
4920 if ( (now - Demo_show_trailer_timestamp) > DEMO_TRAILER_TIMEOUT_MS ) {
4921 // if ( (now - Demo_show_trailer_timestamp) > 10000 ) {
4923 movie_play( NOX("fstrailer2.mve") );
4924 demo_reset_trailer_timer();
4932 // same as game_check_key(), except this is used while actually in the game. Since there
4933 // generally are differences between game control keys and general UI keys, makes sense to
4934 // have seperate functions for each case. If you are not checking a game control while in a
4935 // mission, you should probably be using game_check_key() instead.
4940 if (!os_foreground()) {
4945 // If we're in a single player game, pause it.
4946 if (!(Game_mode & GM_MULTIPLAYER)){
4947 if ( (gameseq_get_state() == GS_STATE_GAME_PLAY) && (!popup_active()) && (!popupdead_is_active()) ) {
4948 game_process_pause_key();
4955 #if defined(FS2_DEMO) || defined(FS1_DEMO)
4956 demo_maybe_show_trailer(k);
4959 // Move the mouse cursor with the joystick.
4960 if (os_foreground() && (!Mouse_hidden) && (Use_joy_mouse) ) {
4961 // Move the mouse cursor with the joystick
4965 joy_get_pos( &jx, &jy, &jz, &jr );
4967 dx = fl2i(f2fl(jx)*flFrametime*500.0f);
4968 dy = fl2i(f2fl(jy)*flFrametime*500.0f);
4971 mouse_get_real_pos( &mx, &my );
4972 mouse_set_pos( mx+dx, my+dy );
4977 m = mouse_down(MOUSE_LEFT_BUTTON);
4979 if ( j != Joymouse_button_status ) {
4980 //mprintf(( "Joy went from %d to %d, mouse is %d\n", Joymouse_button_status, j, m ));
4981 Joymouse_button_status = j;
4983 mouse_mark_button( MOUSE_LEFT_BUTTON, 1 );
4984 } else if ( (!j) && (m) ) {
4985 mouse_mark_button( MOUSE_LEFT_BUTTON, 0 );
4990 // if we should be ignoring keys because of some multiplayer situations
4991 if((Game_mode & GM_MULTIPLAYER) && multi_ignore_controls(k)){
4995 // If a popup is running, don't process all the Fn keys
4996 if( popup_active() ) {
5000 state = gameseq_get_state();
5002 // if ( k ) nprintf(( "General", "Key = %x\n", k ));
5005 case KEY_DEBUGGED + KEY_BACKSP:
5010 launch_context_help();
5015 // if (state != GS_STATE_INITIAL_PLAYER_SELECT) {
5017 // don't allow f2 while warping out in multiplayer
5018 if((Game_mode & GM_MULTIPLAYER) && (Net_player != NULL) && (Net_player->flags & NETINFO_FLAG_WARPING_OUT)){
5023 case GS_STATE_INITIAL_PLAYER_SELECT:
5024 case GS_STATE_OPTIONS_MENU:
5025 case GS_STATE_HUD_CONFIG:
5026 case GS_STATE_CONTROL_CONFIG:
5027 case GS_STATE_DEATH_DIED:
5028 case GS_STATE_DEATH_BLEW_UP:
5029 case GS_STATE_VIEW_MEDALS:
5033 gameseq_post_event(GS_EVENT_OPTIONS_MENU);
5040 // hotkey selection screen -- only valid from briefing and beyond.
5042 #if !(defined(FS2_DEMO) || defined(FS1_DEMO))
5043 if ( (state == GS_STATE_TEAM_SELECT) || (state == GS_STATE_BRIEFING) || (state == GS_STATE_SHIP_SELECT) || (state == GS_STATE_WEAPON_SELECT) || (state == GS_STATE_GAME_PLAY) || (state == GS_STATE_GAME_PAUSED) ) {
5044 gameseq_post_event( GS_EVENT_HOTKEY_SCREEN );
5050 case KEY_DEBUGGED + KEY_F3:
5051 gameseq_post_event( GS_EVENT_TOGGLE_FULLSCREEN );
5054 case KEY_DEBUGGED + KEY_F4:
5055 gameseq_post_event( GS_EVENT_TOGGLE_GLIDE );
5059 if(Game_mode & GM_MULTIPLAYER){
5060 if((state == GS_STATE_GAME_PLAY) || (state == GS_STATE_MULTI_PAUSED)){
5061 gameseq_post_event( GS_EVENT_MISSION_LOG_SCROLLBACK );
5065 if ((state == GS_STATE_GAME_PLAY) || (state == GS_STATE_DEATH_DIED) || (state == GS_STATE_DEATH_BLEW_UP) || (state == GS_STATE_GAME_PAUSED) ) {
5066 gameseq_post_event( GS_EVENT_MISSION_LOG_SCROLLBACK );
5072 case KEY_ESC | KEY_SHIFTED:
5073 // make sure to quit properly out of multiplayer
5074 if(Game_mode & GM_MULTIPLAYER){
5075 multi_quit_game(PROMPT_NONE);
5078 gameseq_post_event( GS_EVENT_QUIT_GAME );
5083 case KEY_DEBUGGED + KEY_P:
5086 case KEY_PRINT_SCRN:
5088 static int counter = 0;
5093 sprintf( tmp_name, NOX("screen%02d"), counter );
5095 mprintf(( "Dumping screen to '%s'\n", tmp_name ));
5096 gr_print_screen(tmp_name);
5104 case KEY_SHIFTED | KEY_ENTER: {
5106 #if !defined(NDEBUG)
5108 if ( Game_mode & GM_NORMAL ){
5112 // if we're in multiplayer mode, do some special networking
5113 if(Game_mode & GM_MULTIPLAYER){
5114 debug_console(game_do_dc_networking);
5121 if ( Game_mode & GM_NORMAL )
5135 gameseq_post_event(GS_EVENT_QUIT_GAME);
5138 void apply_physics( float damping, float desired_vel, float initial_vel, float t, float * new_vel, float * delta_pos );
5141 void camera_set_position( vector *pos )
5146 void camera_set_orient( matrix *orient )
5148 Camera_orient = *orient;
5151 void camera_set_velocity( vector *vel, int instantaneous )
5153 Camera_desired_velocity.xyz.x = 0.0f;
5154 Camera_desired_velocity.xyz.y = 0.0f;
5155 Camera_desired_velocity.xyz.z = 0.0f;
5157 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.rvec, vel->xyz.x );
5158 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.uvec, vel->xyz.y );
5159 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.fvec, vel->xyz.z );
5161 if ( instantaneous ) {
5162 Camera_velocity = Camera_desired_velocity;
5170 vector new_vel, delta_pos;
5172 apply_physics( Camera_damping, Camera_desired_velocity.xyz.x, Camera_velocity.xyz.x, flFrametime, &new_vel.xyz.x, &delta_pos.xyz.x );
5173 apply_physics( Camera_damping, Camera_desired_velocity.xyz.y, Camera_velocity.xyz.y, flFrametime, &new_vel.xyz.y, &delta_pos.xyz.y );
5174 apply_physics( Camera_damping, Camera_desired_velocity.xyz.z, Camera_velocity.xyz.z, flFrametime, &new_vel.xyz.z, &delta_pos.xyz.z );
5176 Camera_velocity = new_vel;
5178 // mprintf(( "Camera velocity = %.1f,%.1f, %.1f\n", Camera_velocity.xyz.x, Camera_velocity.xyz.y, Camera_velocity.xyz.z ));
5180 vm_vec_add2( &Camera_pos, &delta_pos );
5182 float ot = Camera_time+0.0f;
5184 Camera_time += flFrametime;
5186 if ( (ot < 0.667f) && ( Camera_time >= 0.667f ) ) {
5189 tmp.xyz.z = 4.739f; // always go this fast forward.
5191 // pick x and y velocities so they are always on a
5192 // circle with a 25 m radius.
5194 float tmp_angle = frand()*PI2;
5196 tmp.xyz.x = 22.0f * (float)sin(tmp_angle);
5197 tmp.xyz.y = -22.0f * (float)cos(tmp_angle);
5199 //mprintf(( "Angle = %.1f, vx=%.1f, vy=%.1f\n", tmp_angle, tmp.xyz.x, tmp.xyz.y ));
5201 //mprintf(( "Changing velocity!\n" ));
5202 camera_set_velocity( &tmp, 0 );
5205 if ( (ot < 3.0f ) && ( Camera_time >= 3.0f ) ) {
5206 vector tmp = { 0.0f, 0.0f, 0.0f };
5207 camera_set_velocity( &tmp, 0 );
5212 void end_demo_campaign_do()
5214 #if defined(FS2_DEMO) || defined(FS1_DEMO)
5215 // show upsell screens
5216 demo_upsell_show_screens();
5217 #elif defined(OEM_BUILD)
5218 // show oem upsell screens
5219 oem_upsell_show_screens();
5222 // drop into main hall
5223 gameseq_post_event( GS_EVENT_MAIN_MENU );
5226 // All code to process events. This is the only place
5227 // that you should change the state of the game.
5228 void game_process_event( int current_state, int event )
5230 mprintf(("Got event %s in state %s\n", GS_event_text[event], GS_state_text[current_state]));
5233 case GS_EVENT_SIMULATOR_ROOM:
5234 gameseq_set_state(GS_STATE_SIMULATOR_ROOM);
5237 case GS_EVENT_MAIN_MENU:
5238 gameseq_set_state(GS_STATE_MAIN_MENU);
5241 case GS_EVENT_OPTIONS_MENU:
5242 gameseq_push_state( GS_STATE_OPTIONS_MENU );
5245 case GS_EVENT_BARRACKS_MENU:
5246 gameseq_set_state(GS_STATE_BARRACKS_MENU);
5249 case GS_EVENT_TECH_MENU:
5250 gameseq_set_state(GS_STATE_TECH_MENU);
5253 case GS_EVENT_TRAINING_MENU:
5254 gameseq_set_state(GS_STATE_TRAINING_MENU);
5257 case GS_EVENT_START_GAME:
5258 Select_default_ship = 0;
5259 Player_multi_died_check = -1;
5260 gameseq_set_state(GS_STATE_CMD_BRIEF);
5263 case GS_EVENT_START_BRIEFING:
5264 gameseq_set_state(GS_STATE_BRIEFING);
5267 case GS_EVENT_DEBRIEF:
5268 // did we end the campaign in the main freespace 2 single player campaign?
5270 if(Campaign_ended_in_mission && (Game_mode & GM_CAMPAIGN_MODE) && !stricmp(Campaign.filename, "freespace")) {
5272 if(Campaign_ended_in_mission && (Game_mode & GM_CAMPAIGN_MODE) && !stricmp(Campaign.filename, "freespace2")) {
5274 gameseq_post_event(GS_EVENT_END_CAMPAIGN);
5276 gameseq_set_state(GS_STATE_DEBRIEF);
5279 Player_multi_died_check = -1;
5282 case GS_EVENT_SHIP_SELECTION:
5283 gameseq_set_state( GS_STATE_SHIP_SELECT );
5286 case GS_EVENT_WEAPON_SELECTION:
5287 gameseq_set_state( GS_STATE_WEAPON_SELECT );
5290 case GS_EVENT_ENTER_GAME:
5292 // maybe start recording a demo
5294 demo_start_record("test.fsd");
5298 if (Game_mode & GM_MULTIPLAYER) {
5299 // if we're respawning, make sure we change the view mode so that the hud shows up
5300 if (current_state == GS_STATE_DEATH_BLEW_UP) {
5304 gameseq_set_state(GS_STATE_GAME_PLAY);
5306 gameseq_set_state(GS_STATE_GAME_PLAY, 1);
5309 Player_multi_died_check = -1;
5311 // clear multiplayer button info
5312 extern button_info Multi_ship_status_bi;
5313 memset(&Multi_ship_status_bi, 0, sizeof(button_info));
5315 Start_time = f2fl(timer_get_approx_seconds());
5317 mprintf(("Entering game at time = %7.3f\n", Start_time));
5321 case GS_EVENT_START_GAME_QUICK:
5322 Select_default_ship = 1;
5323 gameseq_post_event(GS_EVENT_ENTER_GAME);
5327 case GS_EVENT_END_GAME:
5328 if ( (current_state == GS_STATE_GAME_PLAY) || (current_state == GS_STATE_DEATH_DIED) ||
5329 (current_state == GS_STATE_DEATH_BLEW_UP) || (current_state == GS_STATE_DEBRIEF) || (current_state == GS_STATE_MULTI_DOGFIGHT_DEBRIEF)) {
5330 gameseq_set_state(GS_STATE_MAIN_MENU);
5335 Player_multi_died_check = -1;
5338 case GS_EVENT_QUIT_GAME:
5339 main_hall_stop_music();
5340 main_hall_stop_ambient();
5341 gameseq_set_state(GS_STATE_QUIT_GAME);
5343 Player_multi_died_check = -1;
5346 case GS_EVENT_GAMEPLAY_HELP:
5347 gameseq_push_state( GS_STATE_GAMEPLAY_HELP );
5350 case GS_EVENT_PAUSE_GAME:
5351 gameseq_push_state(GS_STATE_GAME_PAUSED);
5354 case GS_EVENT_DEBUG_PAUSE_GAME:
5355 gameseq_push_state(GS_STATE_DEBUG_PAUSED);
5358 case GS_EVENT_TRAINING_PAUSE:
5359 gameseq_push_state(GS_STATE_TRAINING_PAUSED);
5362 case GS_EVENT_PREVIOUS_STATE:
5363 gameseq_pop_state();
5366 case GS_EVENT_TOGGLE_FULLSCREEN:
5367 #ifndef HARDWARE_ONLY
5369 if ( gr_screen.mode == GR_SOFTWARE ) {
5370 gr_init( GR_640, GR_DIRECTDRAW );
5371 } else if ( gr_screen.mode == GR_DIRECTDRAW ) {
5372 gr_init( GR_640, GR_SOFTWARE );
5378 case GS_EVENT_TOGGLE_GLIDE:
5380 if ( gr_screen.mode != GR_GLIDE ) {
5381 gr_init( GR_640, GR_GLIDE );
5383 gr_init( GR_640, GR_SOFTWARE );
5388 case GS_EVENT_LOAD_MISSION_MENU:
5389 gameseq_set_state(GS_STATE_LOAD_MISSION_MENU);
5392 case GS_EVENT_MISSION_LOG_SCROLLBACK:
5393 gameseq_push_state( GS_STATE_MISSION_LOG_SCROLLBACK );
5396 case GS_EVENT_HUD_CONFIG:
5397 gameseq_push_state( GS_STATE_HUD_CONFIG );
5400 case GS_EVENT_CONTROL_CONFIG:
5401 gameseq_push_state( GS_STATE_CONTROL_CONFIG );
5404 case GS_EVENT_DEATH_DIED:
5405 gameseq_set_state( GS_STATE_DEATH_DIED );
5408 case GS_EVENT_DEATH_BLEW_UP:
5409 if ( current_state == GS_STATE_DEATH_DIED ) {
5410 gameseq_set_state( GS_STATE_DEATH_BLEW_UP );
5411 event_music_player_death();
5413 // multiplayer clients set their extra check here
5414 if(Game_mode & GM_MULTIPLAYER){
5415 // set the multi died absolute last chance check
5416 Player_multi_died_check = time(NULL);
5419 mprintf(( "Ignoring GS_EVENT_DEATH_BLEW_UP because we're in state %d\n", current_state ));
5423 case GS_EVENT_NEW_CAMPAIGN:
5424 if (!mission_load_up_campaign()){
5425 readyroom_continue_campaign();
5428 Player_multi_died_check = -1;
5431 case GS_EVENT_CAMPAIGN_CHEAT:
5432 if (!mission_load_up_campaign()){
5434 // bash campaign value
5435 extern char Main_hall_campaign_cheat[512];
5438 // look for the mission
5439 for(idx=0; idx<Campaign.num_missions; idx++){
5440 if(!stricmp(Campaign.missions[idx].name, Main_hall_campaign_cheat)){
5441 Campaign.next_mission = idx;
5442 Campaign.prev_mission = idx - 1;
5449 readyroom_continue_campaign();
5452 Player_multi_died_check = -1;
5455 case GS_EVENT_CAMPAIGN_ROOM:
5456 gameseq_set_state(GS_STATE_CAMPAIGN_ROOM);
5459 case GS_EVENT_CMD_BRIEF:
5460 gameseq_set_state(GS_STATE_CMD_BRIEF);
5463 case GS_EVENT_RED_ALERT:
5464 gameseq_set_state(GS_STATE_RED_ALERT);
5467 case GS_EVENT_CREDITS:
5468 gameseq_set_state( GS_STATE_CREDITS );
5471 case GS_EVENT_VIEW_MEDALS:
5472 gameseq_push_state( GS_STATE_VIEW_MEDALS );
5475 case GS_EVENT_SHOW_GOALS:
5476 gameseq_push_state( GS_STATE_SHOW_GOALS ); // use push_state() since we might get to this screen through a variety of states
5479 case GS_EVENT_HOTKEY_SCREEN:
5480 gameseq_push_state( GS_STATE_HOTKEY_SCREEN ); // use push_state() since we might get to this screen through a variety of states
5483 // multiplayer stuff follow these comments
5485 case GS_EVENT_MULTI_JOIN_GAME:
5486 gameseq_set_state( GS_STATE_MULTI_JOIN_GAME );
5489 case GS_EVENT_MULTI_HOST_SETUP:
5490 gameseq_set_state( GS_STATE_MULTI_HOST_SETUP );
5493 case GS_EVENT_MULTI_CLIENT_SETUP:
5494 gameseq_set_state( GS_STATE_MULTI_CLIENT_SETUP );
5497 case GS_EVENT_GOTO_VIEW_CUTSCENES_SCREEN:
5498 gameseq_set_state(GS_STATE_VIEW_CUTSCENES);
5501 case GS_EVENT_MULTI_STD_WAIT:
5502 gameseq_set_state( GS_STATE_MULTI_STD_WAIT );
5505 case GS_EVENT_STANDALONE_MAIN:
5506 gameseq_set_state( GS_STATE_STANDALONE_MAIN );
5509 case GS_EVENT_MULTI_PAUSE:
5510 gameseq_push_state( GS_STATE_MULTI_PAUSED );
5513 case GS_EVENT_INGAME_PRE_JOIN:
5514 gameseq_set_state( GS_STATE_INGAME_PRE_JOIN );
5517 case GS_EVENT_EVENT_DEBUG:
5518 gameseq_push_state(GS_STATE_EVENT_DEBUG);
5521 // Start a warpout where player automatically goes 70 no matter what
5522 // and can't cancel out of it.
5523 case GS_EVENT_PLAYER_WARPOUT_START_FORCED:
5524 Warpout_forced = 1; // If non-zero, bash the player to speed and go through effect
5526 // Same code as in GS_EVENT_PLAYER_WARPOUT_START only ignores current mode
5527 Player->saved_viewer_mode = Viewer_mode;
5528 Player->control_mode = PCM_WARPOUT_STAGE1;
5529 Warpout_sound = snd_play(&Snds[SND_PLAYER_WARP_OUT]);
5530 Warpout_time = 0.0f; // Start timer!
5533 case GS_EVENT_PLAYER_WARPOUT_START:
5534 if ( Player->control_mode != PCM_NORMAL ) {
5535 mprintf(( "Player isn't in normal mode; cannot warp out.\n" ));
5537 Player->saved_viewer_mode = Viewer_mode;
5538 Player->control_mode = PCM_WARPOUT_STAGE1;
5539 Warpout_sound = snd_play(&Snds[SND_PLAYER_WARP_OUT]);
5540 Warpout_time = 0.0f; // Start timer!
5541 Warpout_forced = 0; // If non-zero, bash the player to speed and go through effect
5545 case GS_EVENT_PLAYER_WARPOUT_STOP:
5546 if ( Player->control_mode != PCM_NORMAL ) {
5547 if ( !Warpout_forced ) { // cannot cancel forced warpout
5548 Player->control_mode = PCM_NORMAL;
5549 Viewer_mode = Player->saved_viewer_mode;
5550 hud_subspace_notify_abort();
5551 mprintf(( "Player put back to normal mode.\n" ));
5552 if ( Warpout_sound > -1 ) {
5553 snd_stop( Warpout_sound );
5560 case GS_EVENT_PLAYER_WARPOUT_DONE_STAGE1: // player ship got up to speed
5561 if ( Player->control_mode != PCM_WARPOUT_STAGE1 ) {
5562 gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_STOP );
5563 mprintf(( "Player put back to normal mode, because of invalid sequence in stage1.\n" ));
5565 mprintf(( "Hit target speed. Starting warp effect and moving to stage 2!\n" ));
5566 shipfx_warpout_start( Player_obj );
5567 Player->control_mode = PCM_WARPOUT_STAGE2;
5568 Player->saved_viewer_mode = Viewer_mode;
5569 Viewer_mode |= VM_WARP_CHASE;
5571 vector tmp = Player_obj->pos;
5573 ship_get_eye( &tmp, &tmp_m, Player_obj );
5574 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.rvec, 0.0f );
5575 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.uvec, 0.952f );
5576 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.fvec, -1.782f );
5578 camera_set_position( &tmp );
5579 camera_set_orient( &Player_obj->orient );
5580 vector tmp_vel = { 0.0f, 5.1919f, 14.7f };
5582 //mprintf(( "Rad = %.1f\n", Player_obj->radius ));
5583 camera_set_velocity( &tmp_vel, 1);
5587 case GS_EVENT_PLAYER_WARPOUT_DONE_STAGE2: // player ship got into the warp effect
5588 if ( Player->control_mode != PCM_WARPOUT_STAGE2 ) {
5589 gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_STOP );
5590 mprintf(( "Player put back to normal mode, because of invalid sequence in stage2.\n" ));
5592 mprintf(( "Hit warp effect. Moving to stage 3!\n" ));
5593 Player->control_mode = PCM_WARPOUT_STAGE3;
5597 case GS_EVENT_PLAYER_WARPOUT_DONE: // player ship got through the warp effect
5598 mprintf(( "Player warped out. Going to debriefing!\n" ));
5599 Player->control_mode = PCM_NORMAL;
5600 Viewer_mode = Player->saved_viewer_mode;
5603 // we have a special debriefing screen for multiplayer furballs
5604 if((Game_mode & GM_MULTIPLAYER) && (The_mission.game_type & MISSION_TYPE_MULTI_DOGFIGHT)){
5605 gameseq_post_event(GS_EVENT_MULTI_DOGFIGHT_DEBRIEF);
5607 // do the normal debriefing for all other situations
5609 gameseq_post_event(GS_EVENT_DEBRIEF);
5613 case GS_EVENT_STANDALONE_POSTGAME:
5614 gameseq_set_state(GS_STATE_STANDALONE_POSTGAME);
5617 case GS_EVENT_INITIAL_PLAYER_SELECT:
5618 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5621 case GS_EVENT_GAME_INIT:
5622 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
5623 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5625 // see if the command line option has been set to use the last pilot, and act acoordingly
5626 if( player_select_get_last_pilot() ) {
5627 // always enter the main menu -- do the automatic network startup stuff elsewhere
5628 // so that we still have valid checks for networking modes, etc.
5629 gameseq_set_state(GS_STATE_MAIN_MENU);
5631 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5636 case GS_EVENT_MULTI_MISSION_SYNC:
5637 gameseq_set_state(GS_STATE_MULTI_MISSION_SYNC);
5640 case GS_EVENT_MULTI_START_GAME:
5641 gameseq_set_state(GS_STATE_MULTI_START_GAME);
5644 case GS_EVENT_MULTI_HOST_OPTIONS:
5645 gameseq_set_state(GS_STATE_MULTI_HOST_OPTIONS);
5648 case GS_EVENT_MULTI_DOGFIGHT_DEBRIEF:
5649 gameseq_set_state(GS_STATE_MULTI_DOGFIGHT_DEBRIEF);
5652 case GS_EVENT_TEAM_SELECT:
5653 gameseq_set_state(GS_STATE_TEAM_SELECT);
5656 case GS_EVENT_END_CAMPAIGN:
5657 gameseq_set_state(GS_STATE_END_OF_CAMPAIGN);
5660 case GS_EVENT_END_DEMO:
5661 gameseq_set_state(GS_STATE_END_DEMO);
5664 case GS_EVENT_LOOP_BRIEF:
5665 gameseq_set_state(GS_STATE_LOOP_BRIEF);
5674 // Called when a state is being left.
5675 // The current state is still at old_state, but as soon as
5676 // this function leaves, then the current state will become
5677 // new state. You should never try to change the state
5678 // in here... if you think you need to, you probably really
5679 // need to post an event, not change the state.
5680 void game_leave_state( int old_state, int new_state )
5682 int end_mission = 1;
5684 switch (new_state) {
5685 case GS_STATE_GAME_PAUSED:
5686 case GS_STATE_DEBUG_PAUSED:
5687 case GS_STATE_OPTIONS_MENU:
5688 case GS_STATE_CONTROL_CONFIG:
5689 case GS_STATE_MISSION_LOG_SCROLLBACK:
5690 case GS_STATE_DEATH_DIED:
5691 case GS_STATE_SHOW_GOALS:
5692 case GS_STATE_HOTKEY_SCREEN:
5693 case GS_STATE_MULTI_PAUSED:
5694 case GS_STATE_TRAINING_PAUSED:
5695 case GS_STATE_EVENT_DEBUG:
5696 case GS_STATE_GAMEPLAY_HELP:
5697 end_mission = 0; // these events shouldn't end a mission
5701 switch (old_state) {
5702 case GS_STATE_BRIEFING:
5703 brief_stop_voices();
5704 if ( (new_state != GS_STATE_OPTIONS_MENU) && (new_state != GS_STATE_WEAPON_SELECT)
5705 && (new_state != GS_STATE_SHIP_SELECT) && (new_state != GS_STATE_HOTKEY_SCREEN)
5706 && (new_state != GS_STATE_TEAM_SELECT) ){
5707 common_select_close();
5708 if ( new_state == GS_STATE_MAIN_MENU ) {
5709 freespace_stop_mission();
5713 // COMMAND LINE OPTION
5714 if (Cmdline_multi_stream_chat_to_file){
5715 cfwrite_string(NOX("-------------------------------------------\n"),Multi_chat_stream);
5716 cfclose(Multi_chat_stream);
5720 case GS_STATE_DEBRIEF:
5721 if ( (new_state != GS_STATE_VIEW_MEDALS) && (new_state != GS_STATE_OPTIONS_MENU) ) {
5726 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
5727 multi_df_debrief_close();
5730 case GS_STATE_LOAD_MISSION_MENU:
5731 mission_load_menu_close();
5734 case GS_STATE_SIMULATOR_ROOM:
5738 case GS_STATE_CAMPAIGN_ROOM:
5739 campaign_room_close();
5742 case GS_STATE_CMD_BRIEF:
5743 if (new_state == GS_STATE_OPTIONS_MENU) {
5748 if (new_state == GS_STATE_MAIN_MENU)
5749 freespace_stop_mission();
5754 case GS_STATE_RED_ALERT:
5758 case GS_STATE_SHIP_SELECT:
5759 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_WEAPON_SELECT &&
5760 new_state != GS_STATE_HOTKEY_SCREEN &&
5761 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_TEAM_SELECT) {
5762 common_select_close();
5763 if ( new_state == GS_STATE_MAIN_MENU ) {
5764 freespace_stop_mission();
5769 case GS_STATE_WEAPON_SELECT:
5770 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_SHIP_SELECT &&
5771 new_state != GS_STATE_HOTKEY_SCREEN &&
5772 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_TEAM_SELECT) {
5773 common_select_close();
5774 if ( new_state == GS_STATE_MAIN_MENU ) {
5775 freespace_stop_mission();
5780 case GS_STATE_TEAM_SELECT:
5781 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_SHIP_SELECT &&
5782 new_state != GS_STATE_HOTKEY_SCREEN &&
5783 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_WEAPON_SELECT) {
5784 common_select_close();
5785 if ( new_state == GS_STATE_MAIN_MENU ) {
5786 freespace_stop_mission();
5791 case GS_STATE_MAIN_MENU:
5792 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
5799 case GS_STATE_OPTIONS_MENU:
5800 //game_start_time();
5801 if(new_state == GS_STATE_MULTI_JOIN_GAME){
5802 multi_join_clear_game_list();
5804 options_menu_close();
5807 case GS_STATE_BARRACKS_MENU:
5808 if(new_state != GS_STATE_VIEW_MEDALS){
5813 case GS_STATE_MISSION_LOG_SCROLLBACK:
5814 hud_scrollback_close();
5817 case GS_STATE_TRAINING_MENU:
5818 training_menu_close();
5821 case GS_STATE_GAME_PLAY:
5822 if ( !(Game_mode & GM_STANDALONE_SERVER) ) {
5823 player_save_target_and_weapon_link_prefs();
5824 game_stop_looped_sounds();
5827 sound_env_disable();
5828 joy_ff_stop_effects();
5830 // stop game time under certain conditions
5831 if ( end_mission || (Game_mode & GM_NORMAL) || ((Game_mode & GM_MULTIPLAYER) && (new_state == GS_STATE_MULTI_PAUSED)) ){
5836 // shut down any recording or playing demos
5841 // when in multiplayer and going back to the main menu, send a leave game packet
5842 // right away (before calling stop mission). stop_mission was taking to long to
5843 // close mission down and I want people to get notified ASAP.
5844 if ( (Game_mode & GM_MULTIPLAYER) && (new_state == GS_STATE_MAIN_MENU) ){
5845 multi_quit_game(PROMPT_NONE);
5848 freespace_stop_mission();
5849 Game_time_compression = F1_0;
5853 case GS_STATE_TECH_MENU:
5857 case GS_STATE_TRAINING_PAUSED:
5858 Training_num_lines = 0;
5859 // fall through to GS_STATE_GAME_PAUSED
5861 case GS_STATE_GAME_PAUSED:
5863 if ( end_mission ) {
5868 case GS_STATE_DEBUG_PAUSED:
5871 pause_debug_close();
5875 case GS_STATE_HUD_CONFIG:
5879 // join/start a game
5880 case GS_STATE_MULTI_JOIN_GAME:
5881 if(new_state != GS_STATE_OPTIONS_MENU){
5882 multi_join_game_close();
5886 case GS_STATE_MULTI_HOST_SETUP:
5887 case GS_STATE_MULTI_CLIENT_SETUP:
5888 // if this is just the host going into the options screen, don't do anything
5889 if((new_state == GS_STATE_MULTI_HOST_OPTIONS) || (new_state == GS_STATE_OPTIONS_MENU)){
5893 // close down the proper state
5894 if(old_state == GS_STATE_MULTI_HOST_SETUP){
5895 multi_create_game_close();
5897 multi_game_client_setup_close();
5900 // COMMAND LINE OPTION
5901 if (Cmdline_multi_stream_chat_to_file){
5902 if( (new_state != GS_STATE_TEAM_SELECT) && (Multi_chat_stream!=NULL) ) {
5903 cfwrite_string(NOX("-------------------------------------------\n"),Multi_chat_stream);
5904 cfclose(Multi_chat_stream);
5909 case GS_STATE_CONTROL_CONFIG:
5910 control_config_close();
5913 case GS_STATE_DEATH_DIED:
5914 Game_mode &= ~GM_DEAD_DIED;
5916 // early end while respawning or blowing up in a multiplayer game
5917 if((Game_mode & GM_MULTIPLAYER) && ((new_state == GS_STATE_DEBRIEF) || (new_state == GS_STATE_MULTI_DOGFIGHT_DEBRIEF)) ){
5919 freespace_stop_mission();
5923 case GS_STATE_DEATH_BLEW_UP:
5924 Game_mode &= ~GM_DEAD_BLEW_UP;
5926 // for single player, we might reload mission, etc. For multiplayer, look at my new state
5927 // to determine if I should do anything.
5928 if ( !(Game_mode & GM_MULTIPLAYER) ) {
5930 freespace_stop_mission();
5933 // if we are not respawing as an observer or as a player, our new state will not
5934 // be gameplay state.
5935 if ( (new_state != GS_STATE_GAME_PLAY) && (new_state != GS_STATE_MULTI_PAUSED) ) {
5936 game_stop_time(); // hasn't been called yet!!
5937 freespace_stop_mission();
5943 case GS_STATE_CREDITS:
5947 case GS_STATE_VIEW_MEDALS:
5951 case GS_STATE_SHOW_GOALS:
5952 mission_show_goals_close();
5955 case GS_STATE_HOTKEY_SCREEN:
5956 if ( new_state != GS_STATE_OPTIONS_MENU ) {
5957 mission_hotkey_close();
5961 case GS_STATE_MULTI_MISSION_SYNC:
5962 // if we're moving into the options menu, don't do anything
5963 if(new_state == GS_STATE_OPTIONS_MENU){
5967 Assert( Game_mode & GM_MULTIPLAYER );
5969 if ( new_state == GS_STATE_GAME_PLAY ){
5970 // palette_restore_palette();
5972 // change a couple of flags to indicate our state!!!
5973 Net_player->state = NETPLAYER_STATE_IN_MISSION;
5974 send_netplayer_update_packet();
5976 // set the game mode
5977 Game_mode |= GM_IN_MISSION;
5981 case GS_STATE_VIEW_CUTSCENES:
5982 cutscenes_screen_close();
5985 case GS_STATE_MULTI_STD_WAIT:
5986 multi_standalone_wait_close();
5989 case GS_STATE_STANDALONE_MAIN:
5990 standalone_main_close();
5991 if(new_state == GS_STATE_MULTI_STD_WAIT){
5992 init_multiplayer_stats();
5996 case GS_STATE_MULTI_PAUSED:
5997 // if ( end_mission ){
6002 case GS_STATE_INGAME_PRE_JOIN:
6003 multi_ingame_select_close();
6006 case GS_STATE_STANDALONE_POSTGAME:
6007 multi_standalone_postgame_close();
6010 case GS_STATE_INITIAL_PLAYER_SELECT:
6011 player_select_close();
6014 case GS_STATE_MULTI_START_GAME:
6015 multi_start_game_close();
6018 case GS_STATE_MULTI_HOST_OPTIONS:
6019 multi_host_options_close();
6022 case GS_STATE_END_OF_CAMPAIGN:
6023 mission_campaign_end_close();
6026 case GS_STATE_LOOP_BRIEF:
6032 // Called when a state is being entered.
6033 // The current state is set to the state we're entering at
6034 // this point, and old_state is set to the state we're coming
6035 // from. You should never try to change the state
6036 // in here... if you think you need to, you probably really
6037 // need to post an event, not change the state.
6039 void game_enter_state( int old_state, int new_state )
6041 switch (new_state) {
6042 case GS_STATE_MAIN_MENU:
6043 // in multiplayer mode, be sure that we are not doing networking anymore.
6044 if ( Game_mode & GM_MULTIPLAYER ) {
6045 Assert( Net_player != NULL );
6046 Net_player->flags &= ~NETINFO_FLAG_DO_NETWORKING;
6049 Game_time_compression = F1_0;
6051 // determine which ship this guy is currently based on
6052 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
6055 if (Player->on_bastion) {
6063 case GS_STATE_BRIEFING:
6064 main_hall_stop_music();
6065 main_hall_stop_ambient();
6067 if (Game_mode & GM_NORMAL) {
6068 // AL: Don't call freespace_start_mission() if re-entering from ship or weapon select
6069 // MWA: or from options or hotkey screens
6070 // JH: or if the command brief state already did this
6071 if ( (old_state != GS_STATE_OPTIONS_MENU) && (old_state != GS_STATE_HOTKEY_SCREEN)
6072 && (old_state != GS_STATE_SHIP_SELECT) && (old_state != GS_STATE_WEAPON_SELECT)
6073 && (old_state != GS_STATE_CMD_BRIEF) ) {
6074 if ( !game_start_mission() ) // this should put us into a new state on failure!
6078 // maybe play a movie before the briefing. don't play if entering briefing screen from ship or weapon select.
6079 if ( (old_state == GS_STATE_DEBRIEF) || (old_state == GS_STATE_SIMULATOR_ROOM) || (old_state == GS_STATE_MAIN_MENU))
6080 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
6082 Game_time_compression = F1_0;
6084 if ( red_alert_mission() ) {
6085 gameseq_post_event(GS_EVENT_RED_ALERT);
6092 case GS_STATE_DEBRIEF:
6093 game_stop_looped_sounds();
6094 mission_goal_fail_incomplete(); // fail all incomplete goals before entering debriefing
6095 if ( (old_state != GS_STATE_VIEW_MEDALS) && (old_state != GS_STATE_OPTIONS_MENU) ){
6100 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
6101 multi_df_debrief_init();
6104 case GS_STATE_LOAD_MISSION_MENU:
6105 mission_load_menu_init();
6108 case GS_STATE_SIMULATOR_ROOM:
6112 case GS_STATE_CAMPAIGN_ROOM:
6113 campaign_room_init();
6116 case GS_STATE_RED_ALERT:
6117 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
6121 case GS_STATE_CMD_BRIEF: {
6122 int team_num = 0; // team number used as index for which cmd brief to use.
6124 if (old_state == GS_STATE_OPTIONS_MENU) {
6128 main_hall_stop_music();
6129 main_hall_stop_ambient();
6131 if (Game_mode & GM_NORMAL) {
6132 // AL: Don't call freespace_start_mission() if re-entering from ship or weapon select
6133 // MWA: or from options or hotkey screens
6134 // JH: or if the command brief state already did this
6135 if ( (old_state != GS_STATE_OPTIONS_MENU) && (old_state != GS_STATE_HOTKEY_SCREEN)
6136 && (old_state != GS_STATE_SHIP_SELECT) && (old_state != GS_STATE_WEAPON_SELECT) ) {
6137 if ( !game_start_mission() ) // this should put us into a new state on failure!
6142 // maybe play a movie before the briefing. don't play if entering briefing screen from ship or weapon select.
6143 if ( (old_state == GS_STATE_DEBRIEF) || (old_state == GS_STATE_SIMULATOR_ROOM) || (old_state == GS_STATE_MAIN_MENU))
6144 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
6146 cmd_brief_init(team_num);
6152 case GS_STATE_SHIP_SELECT:
6156 case GS_STATE_WEAPON_SELECT:
6157 weapon_select_init();
6160 case GS_STATE_TEAM_SELECT:
6164 case GS_STATE_GAME_PAUSED:
6169 case GS_STATE_DEBUG_PAUSED:
6170 // game_stop_time();
6171 // os_set_title("FreeSpace - PAUSED");
6174 case GS_STATE_TRAINING_PAUSED:
6181 case GS_STATE_OPTIONS_MENU:
6183 options_menu_init();
6186 case GS_STATE_GAME_PLAY:
6187 // coming from the gameplay state or the main menu, we might need to load the mission
6188 if ( (Game_mode & GM_NORMAL) && ((old_state == GS_STATE_MAIN_MENU) || (old_state == GS_STATE_GAME_PLAY) || (old_state == GS_STATE_DEATH_BLEW_UP)) ) {
6189 if ( !game_start_mission() ) // this should put us into a new state.
6194 // if we are coming from the briefing, ship select, weapons loadout, or main menu (in the
6195 // case of quick start), then do bitmap loads, etc Don't do any of the loading stuff
6196 // if we are in multiplayer -- this stuff is all handled in the multi-wait section
6197 if ( !(Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_BRIEFING) || (old_state == GS_STATE_SHIP_SELECT) ||
6198 (old_state == GS_STATE_WEAPON_SELECT) || (old_state == GS_STATE_MAIN_MENU) || (old_state == GS_STATE_MULTI_STD_WAIT) || (old_state == GS_STATE_SIMULATOR_ROOM) ) {
6199 // JAS: Used to do all paging here.
6203 HUD_printf("Skill level is set to ** %s **", Skill_level_names(Game_skill_level));
6207 main_hall_stop_music();
6208 main_hall_stop_ambient();
6209 event_music_first_pattern(); // start the first pattern
6212 // special code that restores player ship selection and weapons loadout when doing a quick start
6213 if ( !(Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_MAIN_MENU) || (old_state == GS_STATE_DEATH_BLEW_UP) || (old_state == GS_STATE_GAME_PLAY) ) {
6214 if ( !stricmp(Player_loadout.filename, Game_current_mission_filename) ) {
6215 wss_direct_restore_loadout();
6219 // single-player, quick-start after just died... we need to set weapon linking and kick off the event music
6220 if (!(Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_DEATH_BLEW_UP) ) {
6221 event_music_first_pattern(); // start the first pattern
6224 if ( !(Game_mode & GM_STANDALONE_SERVER) && (old_state != GS_STATE_GAME_PAUSED) && (old_state != GS_STATE_MULTI_PAUSED) ) {
6225 event_music_first_pattern(); // start the first pattern
6227 player_restore_target_and_weapon_link_prefs();
6229 Game_mode |= GM_IN_MISSION;
6232 // required to truely make mouse deltas zeroed in debug mouse code
6233 void mouse_force_pos(int x, int y);
6234 if (!Is_standalone) {
6235 mouse_force_pos(gr_screen.max_w / 2, gr_screen.max_h / 2);
6241 // only start time if in single player, or coming from multi wait state
6244 (Game_mode & GM_NORMAL) &&
6245 (old_state != GS_STATE_VIEW_CUTSCENES)
6247 (Game_mode & GM_MULTIPLAYER) && (
6248 (old_state == GS_STATE_MULTI_PAUSED) ||
6249 (old_state == GS_STATE_MULTI_MISSION_SYNC)
6255 // when coming from the multi paused state, reset the timestamps
6256 if ( (Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_MULTI_PAUSED) ){
6257 multi_reset_timestamps();
6260 if ((Game_mode & GM_MULTIPLAYER) && (old_state != GS_STATE_DEATH_BLEW_UP) ) {
6261 // initialize all object update details
6262 multi_oo_gameplay_init();
6265 // under certain circumstances, the server should reset the object update rate limiting stuff
6266 if( ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)) &&
6267 (old_state == GS_STATE_MULTI_PAUSED) || (old_state == GS_STATE_MULTI_MISSION_SYNC) ){
6269 // reinitialize the rate limiting system for all clients
6270 multi_oo_rate_init_all();
6273 // multiplayer clients should always re-initialize their control info rate limiting system
6274 if((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER)){
6275 multi_oo_rate_init_all();
6279 if(Game_mode & GM_MULTIPLAYER){
6280 multi_ping_reset_players();
6283 Game_subspace_effect = 0;
6284 if (The_mission.flags & MISSION_FLAG_SUBSPACE) {
6285 Game_subspace_effect = 1;
6286 if( !(Game_mode & GM_STANDALONE_SERVER) ){
6287 game_start_subspace_ambient_sound();
6291 sound_env_set(&Game_sound_env);
6292 joy_ff_mission_init(Ship_info[Player_ship->ship_info_index].rotation_time);
6294 // clear multiplayer button info i
6295 extern button_info Multi_ship_status_bi;
6296 memset(&Multi_ship_status_bi, 0, sizeof(button_info));
6299 case GS_STATE_HUD_CONFIG:
6303 case GS_STATE_MULTI_JOIN_GAME:
6304 multi_join_clear_game_list();
6306 if (old_state != GS_STATE_OPTIONS_MENU) {
6307 multi_join_game_init();
6312 case GS_STATE_MULTI_HOST_SETUP:
6313 // don't reinitialize if we're coming back from the host options screen
6314 if ((old_state != GS_STATE_MULTI_HOST_OPTIONS) && (old_state != GS_STATE_OPTIONS_MENU)) {
6315 multi_create_game_init();
6320 case GS_STATE_MULTI_CLIENT_SETUP:
6321 if (old_state != GS_STATE_OPTIONS_MENU) {
6322 multi_game_client_setup_init();
6327 case GS_STATE_CONTROL_CONFIG:
6328 control_config_init();
6331 case GS_STATE_TECH_MENU:
6335 case GS_STATE_BARRACKS_MENU:
6336 if(old_state != GS_STATE_VIEW_MEDALS){
6341 case GS_STATE_MISSION_LOG_SCROLLBACK:
6342 hud_scrollback_init();
6345 case GS_STATE_DEATH_DIED:
6346 Player_died_time = timestamp(10);
6348 if(!(Game_mode & GM_MULTIPLAYER)){
6349 player_show_death_message();
6351 Game_mode |= GM_DEAD_DIED;
6354 case GS_STATE_DEATH_BLEW_UP:
6355 if ( !popupdead_is_active() ) {
6356 Player_ai->target_objnum = -1;
6359 // stop any local EMP effect
6362 Players[Player_num].flags &= ~PLAYER_FLAGS_AUTO_TARGETING; // Prevent immediate switch to a hostile ship.
6363 Game_mode |= GM_DEAD_BLEW_UP;
6364 Show_viewing_from_self = 0;
6366 // timestamp how long we should wait before displaying the died popup
6367 if ( !popupdead_is_active() ) {
6368 Player_died_popup_wait = timestamp(PLAYER_DIED_POPUP_WAIT);
6372 case GS_STATE_GAMEPLAY_HELP:
6373 gameplay_help_init();
6376 case GS_STATE_CREDITS:
6377 main_hall_stop_music();
6378 main_hall_stop_ambient();
6382 case GS_STATE_VIEW_MEDALS:
6383 medal_main_init(Player);
6386 case GS_STATE_SHOW_GOALS:
6387 mission_show_goals_init();
6390 case GS_STATE_HOTKEY_SCREEN:
6391 mission_hotkey_init();
6394 case GS_STATE_MULTI_MISSION_SYNC:
6395 // if we're coming from the options screen, don't do any
6396 if(old_state == GS_STATE_OPTIONS_MENU){
6400 switch(Multi_sync_mode){
6401 case MULTI_SYNC_PRE_BRIEFING:
6402 // if moving from game forming to the team select state
6405 case MULTI_SYNC_POST_BRIEFING:
6406 // if moving from briefing into the mission itself
6409 // tell everyone that we're now loading data
6410 Net_player->state = NETPLAYER_STATE_DATA_LOAD;
6411 send_netplayer_update_packet();
6413 // JAS: Used to do all paging here!!!!
6415 Net_player->state = NETPLAYER_STATE_WAITING;
6416 send_netplayer_update_packet();
6418 Game_time_compression = F1_0;
6420 case MULTI_SYNC_INGAME:
6426 case GS_STATE_VIEW_CUTSCENES:
6427 cutscenes_screen_init();
6430 case GS_STATE_MULTI_STD_WAIT:
6431 multi_standalone_wait_init();
6434 case GS_STATE_STANDALONE_MAIN:
6435 // don't initialize if we're coming from one of these 2 states unless there are no
6436 // players left (reset situation)
6437 if((old_state != GS_STATE_STANDALONE_POSTGAME) || multi_endgame_ending()){
6438 standalone_main_init();
6442 case GS_STATE_MULTI_PAUSED:
6446 case GS_STATE_INGAME_PRE_JOIN:
6447 multi_ingame_select_init();
6450 case GS_STATE_STANDALONE_POSTGAME:
6451 multi_standalone_postgame_init();
6454 case GS_STATE_INITIAL_PLAYER_SELECT:
6455 player_select_init();
6458 case GS_STATE_MULTI_START_GAME:
6459 multi_start_game_init();
6462 case GS_STATE_MULTI_HOST_OPTIONS:
6463 multi_host_options_init();
6466 case GS_STATE_END_OF_CAMPAIGN:
6467 mission_campaign_end_init();
6470 case GS_STATE_LOOP_BRIEF:
6477 // do stuff that may need to be done regardless of state
6478 void game_do_state_common(int state,int no_networking)
6480 game_maybe_draw_mouse(flFrametime); // determine if to draw the mouse this frame
6481 snd_do_frame(); // update sound system
6482 event_music_do_frame(); // music needs to play across many states
6484 multi_log_process();
6486 if (no_networking) {
6490 // maybe do a multiplayer frame based on game mode and state type
6491 if (Game_mode & GM_MULTIPLAYER) {
6493 case GS_STATE_OPTIONS_MENU:
6494 case GS_STATE_GAMEPLAY_HELP:
6495 case GS_STATE_HOTKEY_SCREEN:
6496 case GS_STATE_HUD_CONFIG:
6497 case GS_STATE_CONTROL_CONFIG:
6498 case GS_STATE_MISSION_LOG_SCROLLBACK:
6499 case GS_STATE_SHOW_GOALS:
6500 case GS_STATE_VIEW_CUTSCENES:
6501 case GS_STATE_EVENT_DEBUG:
6502 multi_maybe_do_frame();
6506 game_do_networking();
6510 // Called once a frame.
6511 // You should never try to change the state
6512 // in here... if you think you need to, you probably really
6513 // need to post an event, not change the state.
6514 int Game_do_state_should_skip = 0;
6515 void game_do_state(int state)
6517 // always lets the do_state_common() function determine if the state should be skipped
6518 Game_do_state_should_skip = 0;
6520 // legal to set the should skip state anywhere in this function
6521 game_do_state_common(state); // do stuff that may need to be done regardless of state
6523 if(Game_do_state_should_skip){
6528 case GS_STATE_MAIN_MENU:
6529 game_set_frametime(GS_STATE_MAIN_MENU);
6530 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
6533 main_hall_do(flFrametime);
6537 case GS_STATE_OPTIONS_MENU:
6538 game_set_frametime(GS_STATE_OPTIONS_MENU);
6539 options_menu_do_frame(flFrametime);
6542 case GS_STATE_BARRACKS_MENU:
6543 game_set_frametime(GS_STATE_BARRACKS_MENU);
6544 barracks_do_frame(flFrametime);
6547 case GS_STATE_TRAINING_MENU:
6548 game_set_frametime(GS_STATE_TRAINING_MENU);
6549 training_menu_do_frame(flFrametime);
6552 case GS_STATE_TECH_MENU:
6553 game_set_frametime(GS_STATE_TECH_MENU);
6554 techroom_do_frame(flFrametime);
6557 case GS_STATE_GAMEPLAY_HELP:
6558 game_set_frametime(GS_STATE_GAMEPLAY_HELP);
6559 gameplay_help_do_frame(flFrametime);
6562 case GS_STATE_GAME_PLAY: // do stuff that should be done during gameplay
6566 case GS_STATE_GAME_PAUSED:
6570 case GS_STATE_DEBUG_PAUSED:
6572 game_set_frametime(GS_STATE_DEBUG_PAUSED);
6577 case GS_STATE_TRAINING_PAUSED:
6578 game_training_pause_do();
6581 case GS_STATE_LOAD_MISSION_MENU:
6582 game_set_frametime(GS_STATE_LOAD_MISSION_MENU);
6583 mission_load_menu_do();
6586 case GS_STATE_BRIEFING:
6587 game_set_frametime(GS_STATE_BRIEFING);
6588 brief_do_frame(flFrametime);
6591 case GS_STATE_DEBRIEF:
6592 game_set_frametime(GS_STATE_DEBRIEF);
6593 debrief_do_frame(flFrametime);
6596 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
6597 game_set_frametime(GS_STATE_MULTI_DOGFIGHT_DEBRIEF);
6598 multi_df_debrief_do();
6601 case GS_STATE_SHIP_SELECT:
6602 game_set_frametime(GS_STATE_SHIP_SELECT);
6603 ship_select_do(flFrametime);
6606 case GS_STATE_WEAPON_SELECT:
6607 game_set_frametime(GS_STATE_WEAPON_SELECT);
6608 weapon_select_do(flFrametime);
6611 case GS_STATE_MISSION_LOG_SCROLLBACK:
6612 game_set_frametime(GS_STATE_MISSION_LOG_SCROLLBACK);
6613 hud_scrollback_do_frame(flFrametime);
6616 case GS_STATE_HUD_CONFIG:
6617 game_set_frametime(GS_STATE_HUD_CONFIG);
6618 hud_config_do_frame(flFrametime);
6621 case GS_STATE_MULTI_JOIN_GAME:
6622 game_set_frametime(GS_STATE_MULTI_JOIN_GAME);
6623 multi_join_game_do_frame();
6626 case GS_STATE_MULTI_HOST_SETUP:
6627 game_set_frametime(GS_STATE_MULTI_HOST_SETUP);
6628 multi_create_game_do();
6631 case GS_STATE_MULTI_CLIENT_SETUP:
6632 game_set_frametime(GS_STATE_MULTI_CLIENT_SETUP);
6633 multi_game_client_setup_do_frame();
6636 case GS_STATE_CONTROL_CONFIG:
6637 game_set_frametime(GS_STATE_CONTROL_CONFIG);
6638 control_config_do_frame(flFrametime);
6641 case GS_STATE_DEATH_DIED:
6645 case GS_STATE_DEATH_BLEW_UP:
6649 case GS_STATE_SIMULATOR_ROOM:
6650 game_set_frametime(GS_STATE_SIMULATOR_ROOM);
6651 sim_room_do_frame(flFrametime);
6654 case GS_STATE_CAMPAIGN_ROOM:
6655 game_set_frametime(GS_STATE_CAMPAIGN_ROOM);
6656 campaign_room_do_frame(flFrametime);
6659 case GS_STATE_RED_ALERT:
6660 game_set_frametime(GS_STATE_RED_ALERT);
6661 red_alert_do_frame(flFrametime);
6664 case GS_STATE_CMD_BRIEF:
6665 game_set_frametime(GS_STATE_CMD_BRIEF);
6666 cmd_brief_do_frame(flFrametime);
6669 case GS_STATE_CREDITS:
6670 game_set_frametime(GS_STATE_CREDITS);
6671 credits_do_frame(flFrametime);
6674 case GS_STATE_VIEW_MEDALS:
6675 game_set_frametime(GS_STATE_VIEW_MEDALS);
6679 case GS_STATE_SHOW_GOALS:
6680 game_set_frametime(GS_STATE_SHOW_GOALS);
6681 mission_show_goals_do_frame(flFrametime);
6684 case GS_STATE_HOTKEY_SCREEN:
6685 game_set_frametime(GS_STATE_HOTKEY_SCREEN);
6686 mission_hotkey_do_frame(flFrametime);
6689 case GS_STATE_VIEW_CUTSCENES:
6690 game_set_frametime(GS_STATE_VIEW_CUTSCENES);
6691 cutscenes_screen_do_frame();
6694 case GS_STATE_MULTI_STD_WAIT:
6695 game_set_frametime(GS_STATE_STANDALONE_MAIN);
6696 multi_standalone_wait_do();
6699 case GS_STATE_STANDALONE_MAIN:
6700 game_set_frametime(GS_STATE_STANDALONE_MAIN);
6701 standalone_main_do();
6704 case GS_STATE_MULTI_PAUSED:
6705 game_set_frametime(GS_STATE_MULTI_PAUSED);
6709 case GS_STATE_TEAM_SELECT:
6710 game_set_frametime(GS_STATE_TEAM_SELECT);
6714 case GS_STATE_INGAME_PRE_JOIN:
6715 game_set_frametime(GS_STATE_INGAME_PRE_JOIN);
6716 multi_ingame_select_do();
6719 case GS_STATE_EVENT_DEBUG:
6721 game_set_frametime(GS_STATE_EVENT_DEBUG);
6722 game_show_event_debug(flFrametime);
6726 case GS_STATE_STANDALONE_POSTGAME:
6727 game_set_frametime(GS_STATE_STANDALONE_POSTGAME);
6728 multi_standalone_postgame_do();
6731 case GS_STATE_INITIAL_PLAYER_SELECT:
6732 game_set_frametime(GS_STATE_INITIAL_PLAYER_SELECT);
6736 case GS_STATE_MULTI_MISSION_SYNC:
6737 game_set_frametime(GS_STATE_MULTI_MISSION_SYNC);
6741 case GS_STATE_MULTI_START_GAME:
6742 game_set_frametime(GS_STATE_MULTI_START_GAME);
6743 multi_start_game_do();
6746 case GS_STATE_MULTI_HOST_OPTIONS:
6747 game_set_frametime(GS_STATE_MULTI_HOST_OPTIONS);
6748 multi_host_options_do();
6751 case GS_STATE_END_OF_CAMPAIGN:
6752 mission_campaign_end_do();
6755 case GS_STATE_END_DEMO:
6756 game_set_frametime(GS_STATE_END_DEMO);
6757 end_demo_campaign_do();
6760 case GS_STATE_LOOP_BRIEF:
6761 game_set_frametime(GS_STATE_LOOP_BRIEF);
6765 } // end switch(gs_current_state)
6769 // return 0 if there is enough RAM to run FreeSpace, otherwise return -1
6770 int game_do_ram_check(int ram_in_bytes)
6772 if ( ram_in_bytes < 30*1024*1024 ) {
6773 int allowed_to_run = 1;
6774 if ( ram_in_bytes < 25*1024*1024 ) {
6779 int Freespace_total_ram_MB;
6780 Freespace_total_ram_MB = fl2i(ram_in_bytes/(1024*1024));
6782 if ( allowed_to_run ) {
6784 sprintf( tmp, XSTR( "FreeSpace has detected that you only have %dMB of free memory.\n\nFreeSpace requires at least 32MB of memory to run. If you think you have more than %dMB of physical memory, ensure that you aren't running SmartDrive (SMARTDRV.EXE). Any memory allocated to SmartDrive is not usable by applications\n\nPress 'OK' to continue running with less than the minimum required memory\n", 193), Freespace_total_ram_MB, Freespace_total_ram_MB);
6789 msgbox_rval = MessageBox( NULL, tmp, XSTR( "Not Enough RAM", 194), MB_OKCANCEL );
6790 if ( msgbox_rval == IDCANCEL ) {
6797 sprintf( tmp, XSTR( "FreeSpace has detected that you only have %dMB of free memory.\n\nFreeSpace requires at least 32MB of memory to run. If you think you have more than %dMB of physical memory, ensure that you aren't running SmartDrive (SMARTDRV.EXE). Any memory allocated to SmartDrive is not usable by applications\n", 195), Freespace_total_ram_MB, Freespace_total_ram_MB);
6799 MessageBox( NULL, tmp, XSTR( "Not Enough RAM", 194), MB_OK );
6810 // Check if there is a freespace.exe in the /update directory (relative to where fs.exe is installed).
6811 // If so, copy it over and remove the update directory.
6812 void game_maybe_update_launcher(char *exe_dir)
6815 char src_filename[MAX_PATH];
6816 char dest_filename[MAX_PATH];
6818 strcpy(src_filename, exe_dir);
6819 strcat(src_filename, NOX("\\update\\freespace.exe"));
6821 strcpy(dest_filename, exe_dir);
6822 strcat(dest_filename, NOX("\\freespace.exe"));
6824 // see if src_filename exists
6826 fp = fopen(src_filename, "rb");
6832 SetFileAttributes(dest_filename, FILE_ATTRIBUTE_NORMAL);
6834 // copy updated freespace.exe to freespace exe dir
6835 if ( CopyFile(src_filename, dest_filename, 0) == 0 ) {
6836 MessageBox( NULL, XSTR("Unable to copy freespace.exe from update directory to installed directory. You should copy freespace.exe from the update directory (located in your FreeSpace install directory) to your install directory", 988), NULL, MB_OK|MB_TASKMODAL|MB_SETFOREGROUND );
6840 // delete the file in the update directory
6841 DeleteFile(src_filename);
6843 // safe to assume directory is empty, since freespace.exe should only be the file ever in the update dir
6844 char update_dir[MAX_PATH];
6845 strcpy(update_dir, exe_dir);
6846 strcat(update_dir, NOX("\\update"));
6847 RemoveDirectory(update_dir);
6853 void game_spew_pof_info_sub(int model_num, polymodel *pm, int sm, CFILE *out, int *out_total, int *out_destroyed_total)
6857 int sub_total_destroyed = 0;
6861 // get the total for all his children
6862 for (i=pm->submodel[sm].first_child; i>-1; i = pm->submodel[i].next_sibling ) {
6863 game_spew_pof_info_sub(model_num, pm, i, out, &sub_total, &sub_total_destroyed);
6866 // find the # of faces for this _individual_ object
6867 total = submodel_get_num_polys(model_num, sm);
6868 if(strstr(pm->submodel[sm].name, "-destroyed")){
6869 sub_total_destroyed = total;
6873 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[sm].name, total);
6876 *out_total += total + sub_total;
6877 *out_destroyed_total += sub_total_destroyed;
6880 #define BAIL() do { int idx; for(idx=0; idx<num_files; idx++){ if(pof_list[idx] != NULL){free(pof_list[idx]); pof_list[idx] = NULL;}} return;} while(0);
6881 void game_spew_pof_info()
6883 char *pof_list[1000];
6886 int idx, model_num, i, j;
6888 int total, root_total, model_total, destroyed_total, counted;
6892 num_files = cf_get_file_list(1000, pof_list, CF_TYPE_MODELS, "*.pof");
6894 // spew info on all the pofs
6900 out = cfopen("pofspew.txt", "wt", CFILE_NORMAL, CF_TYPE_DATA);
6905 for(idx=0; idx<num_files; idx++, counted++){
6906 sprintf(str, "%s.pof", pof_list[idx]);
6907 model_num = model_load(str, 0, NULL);
6909 pm = model_get(model_num);
6911 // if we have a real model
6916 // go through and print all raw submodels
6917 cfputs("RAW\n", out);
6920 for (i=0; i<pm->n_models; i++) {
6921 total = submodel_get_num_polys(model_num, i);
6923 model_total += total;
6924 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[i].name, total);
6927 sprintf(str, "Model total %d\n", model_total);
6930 // now go through and do it by LOD
6931 cfputs("BY LOD\n\n", out);
6932 for(i=0; i<pm->n_detail_levels; i++){
6933 sprintf(str, "LOD %d\n", i);
6937 root_total = submodel_get_num_polys(model_num, pm->detail[i] );
6939 destroyed_total = 0;
6940 for (j=pm->submodel[pm->detail[i]].first_child; j>-1; j = pm->submodel[j].next_sibling ) {
6941 game_spew_pof_info_sub(model_num, pm, j, out, &total, &destroyed_total);
6944 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[pm->detail[i]].name, root_total);
6947 sprintf(str, "TOTAL: %d\n", total + root_total);
6949 sprintf(str, "TOTAL not counting destroyed faces %d\n", (total + root_total) - destroyed_total);
6951 sprintf(str, "TOTAL destroyed faces %d\n\n", destroyed_total);
6954 cfputs("------------------------------------------------------------------------\n\n", out);
6958 if(counted >= MAX_POLYGON_MODELS - 5){
6971 game_spew_pof_info();
6974 int PASCAL WinMainSub(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow)
6979 // Don't let more than one instance of Freespace run.
6980 HWND hwnd = FindWindow( NOX( "FreeSpaceClass" ), NULL );
6982 SetForegroundWindow(hwnd);
6987 // Find out how much RAM is on this machine
6990 ms.dwLength = sizeof(MEMORYSTATUS);
6991 GlobalMemoryStatus(&ms);
6992 Freespace_total_ram = ms.dwTotalPhys;
6994 if ( game_do_ram_check(Freespace_total_ram) == -1 ) {
6998 if ( ms.dwTotalVirtual < 1024 ) {
6999 MessageBox( NULL, XSTR( "FreeSpace requires virtual memory to run.\r\n", 196), XSTR( "No Virtual Memory", 197), MB_OK );
7003 if (!vm_init(24*1024*1024)) {
7004 MessageBox( NULL, XSTR( "Not enough memory to run Freespace.\r\nTry closing down some other applications.\r\n", 198), XSTR( "Not Enough Memory", 199), MB_OK );
7008 char *tmp_mem = (char *) malloc(16 * 1024 * 1024);
7010 MessageBox(NULL, XSTR( "Not enough memory to run Freespace.\r\nTry closing down some other applications.\r\n", 198), XSTR( "Not Enough Memory", 199), MB_OK);
7018 /* this code doesn't work, and we will hit an error about being unable to load the direct draw
7019 dll before we get here anyway if it's not installed (unless we load it manually, which doesn't
7020 seem worth bothering with.
7024 lResult = RegOpenKeyEx(
7025 HKEY_LOCAL_MACHINE, // Where it is
7026 "Software\\Microsoft\\DirectX", // name of key
7027 NULL, // DWORD reserved
7028 KEY_QUERY_VALUE, // Allows all changes
7029 &hKey // Location to store key
7032 if (lResult == ERROR_SUCCESS) {
7034 DWORD dwType, dwLen;
7037 lResult = RegQueryValueEx(
7038 hKey, // Handle to key
7039 "Version", // The values name
7040 NULL, // DWORD reserved
7041 &dwType, // What kind it is
7042 (ubyte *) version, // value to set
7043 &dwLen // How many bytes to set
7046 if (lResult == ERROR_SUCCESS) {
7047 dx_version = atoi(strstr(version, ".") + 1);
7051 DWORD dwType, dwLen;
7054 lResult = RegQueryValueEx(
7055 hKey, // Handle to key
7056 "InstalledVersion", // The values name
7057 NULL, // DWORD reserved
7058 &dwType, // What kind it is
7059 (ubyte *) &val, // value to set
7060 &dwLen // How many bytes to set
7063 if (lResult == ERROR_SUCCESS) {
7071 if (dx_version < 3) {
7072 MessageBox(NULL, "DirectX 3.0 or higher is required and wasn't detected. You can get the\n"
7073 "latest version of DirectX at:\n\n"
7074 "http://www.microsoft.com/msdownload/directx/dxf/enduser5.0/default.htm", "DirectX required", MB_OK);
7076 MessageBox(NULL, "DirectX 3.0 or higher is required and wasn't detected. You can install\n"
7077 "DirectX 5.2 by pressing the 'Install DirectX' button on the FreeSpace Launcher", "DirectX required", MB_OK);
7082 //=====================================================
7083 // Make sure we're running in the right directory.
7087 if ( GetModuleFileName( hInst, exe_dir, 1023 ) > 0 ) {
7088 char *p = exe_dir + strlen(exe_dir);
7090 // chop off the filename
7091 while( (p>exe_dir) && (*p!='\\') && (*p!='/') && (*p!=':') ) {
7097 if ( strlen(exe_dir) > 0 ) {
7098 SetCurrentDirectory(exe_dir);
7101 // check for updated freespace.exe
7102 game_maybe_update_launcher(exe_dir);
7110 extern void windebug_memwatch_init();
7111 windebug_memwatch_init();
7115 parse_cmdline(szCmdLine);
7117 #ifdef STANDALONE_ONLY_BUILD
7119 nprintf(("Network", "Standalone running"));
7122 nprintf(("Network", "Standalone running"));
7130 // maybe spew pof stuff
7131 if(Cmdline_spew_pof_info){
7132 game_spew_pof_info();
7137 // non-demo, non-standalone, play the intro movie
7143 // to avoid crashes on debug build
7144 for (i=0; i<5; i++) {
7148 if( (cf_get_file_list(2, plist, CF_TYPE_MULTI_PLAYERS, NOX("*.plr")) <= 0) && (cf_get_file_list(2, plist, CF_TYPE_SINGLE_PLAYERS, NOX("*.plr")) <= 0) ){
7150 #if defined(OEM_BUILD)
7151 game_do_cd_check_specific(FS_CDROM_VOLUME_1, 1);
7153 game_do_cd_check_specific(FS_CDROM_VOLUME_2, 2);
7154 #endif // defined(OEM_BUILD)
7157 for (int i=0; i<2; i++) {
7158 if (plist[i] != NULL) {
7166 if ( !Is_standalone ) {
7168 // release -- movies always play
7171 // in RELEASE_REAL builds make the user stick in CD2 if there are no pilots on disk so that we guarantee he plays the movie
7172 movie_play( NOX("intro.mve"), 0 );
7174 // debug version, movie will only play with -showmovies
7175 #elif !defined(NDEBUG)
7177 movie_play( NOX("intro.mve"), 0);
7180 if ( Cmdline_show_movies )
7181 movie_play( NOX("intro.mve"), 0 );
7190 gameseq_post_event(GS_EVENT_STANDALONE_MAIN);
7192 gameseq_post_event(GS_EVENT_GAME_INIT); // start the game rolling -- check for default pilot, or go to the pilot select screen
7196 // only important for non THREADED mode
7199 state = gameseq_process_events();
7200 if ( state == GS_STATE_QUIT_GAME ){
7205 #if defined(FS2_DEMO) || defined(FS1_DEMO)
7207 demo_upsell_show_screens();
7209 #elif defined(OEM_BUILD)
7210 // show upsell screens on exit
7211 oem_upsell_show_screens();
7218 int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow)
7224 result = WinMainSub(hInst, hPrev, szCmdLine, nCmdShow);
7226 __except(RecordExceptionInfo(GetExceptionInformation(), "Freespace 2 Main Thread"))
7228 // Do nothing here - RecordExceptionInfo() has already done
7229 // everything that is needed. Actually this code won't even
7230 // get called unless you return EXCEPTION_EXECUTE_HANDLER from
7231 // the __except clause.
7235 nprintf(("WinMain", "exceptions shall fall through"));
7237 result = WinMainSub(hInst, hPrev, szCmdLine, nCmdShow);
7243 // launcher the fslauncher program on exit
7244 void game_launch_launcher_on_exit()
7248 PROCESS_INFORMATION pi;
7249 char cmd_line[2048];
7250 char original_path[1024] = "";
7252 memset( &si, 0, sizeof(STARTUPINFO) );
7256 _getcwd(original_path, 1023);
7258 // set up command line
7259 strcpy(cmd_line, original_path);
7260 strcat(cmd_line, "\\");
7261 strcat(cmd_line, LAUNCHER_FNAME);
7262 strcat(cmd_line, " -straight_to_update");
7264 BOOL ret = CreateProcess( NULL, // pointer to name of executable module
7265 cmd_line, // pointer to command line string
7266 NULL, // pointer to process security attributes
7267 NULL, // pointer to thread security attributes
7268 FALSE, // handle inheritance flag
7269 CREATE_DEFAULT_ERROR_MODE, // creation flags
7270 NULL, // pointer to new environment block
7271 NULL, // pointer to current directory name
7272 &si, // pointer to STARTUPINFO
7273 &pi // pointer to PROCESS_INFORMATION
7275 // to eliminate build warnings
7285 // This function is called when FreeSpace terminates normally.
7287 void game_shutdown(void)
7293 // don't ever flip a page on the standalone!
7294 if(!(Game_mode & GM_STANDALONE_SERVER)){
7300 // if the player has left the "player select" screen and quit the game without actually choosing
7301 // a player, Player will be NULL, in which case we shouldn't write the player file out!
7302 if (!(Game_mode & GM_STANDALONE_SERVER) && (Player!=NULL) && !Is_standalone){
7306 // load up common multiplayer icons
7307 multi_unload_common_icons();
7309 shockwave_close(); // release any memory used by shockwave system
7310 fireball_close(); // free fireball system
7311 ship_close(); // free any memory that was allocated for the ships
7312 weapon_close(); // free any memory that was allocated for the weapons
7313 hud_free_scrollback_list();// free space allocated to store hud messages in hud scrollback
7314 unload_animating_pointer();// frees the frames used for the animating mouse pointer
7315 bm_unload_all(); // free bitmaps
7316 mission_campaign_close(); // close out the campaign stuff
7317 mission_campaign_shutdown(); // get anything that mission_campaign_close can't do
7318 multi_voice_close(); // close down multiplayer voice (including freeing buffers, etc)
7320 #ifdef MULTI_USE_LAG
7324 // the menu close functions will unload the bitmaps if they were displayed during the game
7325 #if !defined(PRESS_TOUR_BUILD) && !defined(PD_BUILD)
7328 context_help_close(); // close out help system
7329 training_menu_close();
7330 lcl_close(); // be sure localization is closed out
7333 // free left-over memory from parsed tables
7334 cutscene_tbl_close();
7336 scoring_tbl_close();
7338 extern void joy_close();
7341 audiostream_close();
7343 event_music_close();
7347 // HACKITY HACK HACK
7348 // if this flag is set, we should be firing up the launcher when exiting freespace
7349 extern int Multi_update_fireup_launcher_on_exit;
7350 if(Multi_update_fireup_launcher_on_exit){
7351 game_launch_launcher_on_exit();
7355 // game_stop_looped_sounds()
7357 // This function will call the appropriate stop looped sound functions for those
7358 // modules which use looping sounds. It is not enough just to stop a looping sound
7359 // at the DirectSound level, the game is keeping track of looping sounds, and this
7360 // function is used to inform the game that looping sounds are being halted.
7362 void game_stop_looped_sounds()
7364 hud_stop_looped_locking_sounds();
7365 hud_stop_looped_engine_sounds();
7366 afterburner_stop_sounds();
7367 player_stop_looped_sounds();
7368 obj_snd_stop_all(); // stop all object-linked persistant sounds
7369 game_stop_subspace_ambient_sound();
7370 snd_stop(Radar_static_looping);
7371 Radar_static_looping = -1;
7372 snd_stop(Target_static_looping);
7373 shipfx_stop_engine_wash_sound();
7374 Target_static_looping = -1;
7377 //////////////////////////////////////////////////////////////////////////
7379 // Code for supporting an animating mouse pointer
7382 //////////////////////////////////////////////////////////////////////////
7384 typedef struct animating_obj
7393 static animating_obj Animating_mouse;
7395 // ----------------------------------------------------------------------------
7396 // init_animating_pointer()
7398 // Called by load_animating_pointer() to ensure the Animating_mouse struct
7399 // gets properly initialized
7401 void init_animating_pointer()
7403 Animating_mouse.first_frame = -1;
7404 Animating_mouse.num_frames = 0;
7405 Animating_mouse.current_frame = -1;
7406 Animating_mouse.time = 0.0f;
7407 Animating_mouse.elapsed_time = 0.0f;
7410 // ----------------------------------------------------------------------------
7411 // load_animating_pointer()
7413 // Called at game init to load in the frames for the animating mouse pointer
7415 // input: filename => filename of animation file that holds the animation
7417 void load_animating_pointer(char *filename, int dx, int dy)
7422 init_animating_pointer();
7424 am = &Animating_mouse;
7425 am->first_frame = bm_load_animation(filename, &am->num_frames, &fps);
7426 if ( am->first_frame == -1 )
7427 Error(LOCATION, "Could not load animation %s for the mouse pointer\n", filename);
7428 am->current_frame = 0;
7429 am->time = am->num_frames / i2fl(fps);
7432 // ----------------------------------------------------------------------------
7433 // unload_animating_pointer()
7435 // Called at game shutdown to free the memory used to store the animation frames
7437 void unload_animating_pointer()
7442 am = &Animating_mouse;
7443 for ( i = 0; i < am->num_frames; i++ ) {
7444 Assert( (am->first_frame+i) >= 0 );
7445 bm_release(am->first_frame + i);
7448 am->first_frame = -1;
7450 am->current_frame = -1;
7453 // draw the correct frame of the game mouse... called from game_maybe_draw_mouse()
7454 void game_render_mouse(float frametime)
7459 // if animating cursor exists, play the next frame
7460 am = &Animating_mouse;
7461 if ( am->first_frame != -1 ) {
7462 mouse_get_pos(&mx, &my);
7463 am->elapsed_time += frametime;
7464 am->current_frame = fl2i( ( am->elapsed_time / am->time ) * (am->num_frames-1) );
7465 if ( am->current_frame >= am->num_frames ) {
7466 am->current_frame = 0;
7467 am->elapsed_time = 0.0f;
7469 gr_set_cursor_bitmap(am->first_frame + am->current_frame);
7473 // ----------------------------------------------------------------------------
7474 // game_maybe_draw_mouse()
7476 // determines whether to draw the mouse pointer at all, and what frame of
7477 // animation to use if the mouse is animating
7479 // Sets mouse.cpp globals Mouse_hidden and Mouse_moved based on the state of the game.
7481 // input: frametime => elapsed frame time in seconds since last call
7483 void game_maybe_draw_mouse(float frametime)
7487 game_state = gameseq_get_state();
7489 switch ( game_state ) {
7490 case GS_STATE_GAME_PAUSED:
7491 // case GS_STATE_MULTI_PAUSED:
7492 case GS_STATE_GAME_PLAY:
7493 case GS_STATE_DEATH_DIED:
7494 case GS_STATE_DEATH_BLEW_UP:
7495 if ( popup_active() || popupdead_is_active() ) {
7507 if ( !Mouse_hidden )
7508 game_render_mouse(frametime);
7512 void game_do_training_checks()
7516 waypoint_list *wplp;
7518 if (Training_context & TRAINING_CONTEXT_SPEED) {
7519 s = (int) Player_obj->phys_info.fspeed;
7520 if ((s >= Training_context_speed_min) && (s <= Training_context_speed_max)) {
7521 if (!Training_context_speed_set) {
7522 Training_context_speed_set = 1;
7523 Training_context_speed_timestamp = timestamp();
7527 Training_context_speed_set = 0;
7530 if (Training_context & TRAINING_CONTEXT_FLY_PATH) {
7531 wplp = &Waypoint_lists[Training_context_path];
7532 if (wplp->count > Training_context_goal_waypoint) {
7533 i = Training_context_goal_waypoint;
7535 d = vm_vec_dist(&wplp->waypoints[i], &Player_obj->pos);
7536 if (d <= Training_context_distance) {
7537 Training_context_at_waypoint = i;
7538 if (Training_context_goal_waypoint == i) {
7539 Training_context_goal_waypoint++;
7540 snd_play(&Snds[SND_CARGO_REVEAL], 0.0f);
7547 if (i == wplp->count)
7550 } while (i != Training_context_goal_waypoint);
7554 if ((Players_target == UNINITIALIZED) || (Player_ai->target_objnum != Players_target) || (Player_ai->targeted_subsys != Players_targeted_subsys)) {
7555 Players_target = Player_ai->target_objnum;
7556 Players_targeted_subsys = Player_ai->targeted_subsys;
7557 Players_target_timestamp = timestamp();
7561 /////////// Following is for event debug view screen
7565 #define EVENT_DEBUG_MAX 5000
7566 #define EVENT_DEBUG_EVENT 0x8000
7568 int Event_debug_index[EVENT_DEBUG_MAX];
7571 void game_add_event_debug_index(int n, int indent)
7573 if (ED_count < EVENT_DEBUG_MAX)
7574 Event_debug_index[ED_count++] = n | (indent << 16);
7577 void game_add_event_debug_sexp(int n, int indent)
7582 if (Sexp_nodes[n].first >= 0) {
7583 game_add_event_debug_sexp(Sexp_nodes[n].first, indent);
7584 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent);
7588 game_add_event_debug_index(n, indent);
7589 if (Sexp_nodes[n].subtype == SEXP_ATOM_OPERATOR)
7590 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent + 1);
7592 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent);
7595 void game_event_debug_init()
7600 for (e=0; e<Num_mission_events; e++) {
7601 game_add_event_debug_index(e | EVENT_DEBUG_EVENT, 0);
7602 game_add_event_debug_sexp(Mission_events[e].formula, 1);
7606 void game_show_event_debug(float frametime)
7610 int font_height, font_width;
7612 static int scroll_offset = 0;
7614 k = game_check_key();
7620 if (scroll_offset < 0)
7630 scroll_offset -= 20;
7631 if (scroll_offset < 0)
7636 scroll_offset += 20; // not font-independent, hard-coded since I counted the lines!
7640 gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
7646 gr_set_color_fast(&Color_bright);
7648 gr_printf(0x8000, 5, NOX("EVENT DEBUG VIEW"));
7650 gr_set_color_fast(&Color_normal);
7652 gr_get_string_size(&font_width, &font_height, NOX("test"));
7653 y_max = gr_screen.max_h - font_height - 5;
7657 while (k < ED_count) {
7658 if (y_index > y_max)
7661 z = Event_debug_index[k];
7662 if (z & EVENT_DEBUG_EVENT) {
7664 sprintf(buf, NOX("%s%s (%s) %s%d %d"), (Mission_events[z].flags & MEF_CURRENT) ? NOX("* ") : "",
7665 Mission_events[z].name, Mission_events[z].result ? NOX("True") : NOX("False"),
7666 (Mission_events[z].chain_delay < 0) ? "" : NOX("x "),
7667 Mission_events[z].repeat_count, Mission_events[z].interval);
7675 strcat(buf, Sexp_nodes[z & 0x7fff].text);
7676 switch (Sexp_nodes[z & 0x7fff].value) {
7678 strcat(buf, NOX(" (True)"));
7682 strcat(buf, NOX(" (False)"));
7685 case SEXP_KNOWN_TRUE:
7686 strcat(buf, NOX(" (Always true)"));
7689 case SEXP_KNOWN_FALSE:
7690 strcat(buf, NOX(" (Always false)"));
7693 case SEXP_CANT_EVAL:
7694 strcat(buf, NOX(" (Can't eval)"));
7698 case SEXP_NAN_FOREVER:
7699 strcat(buf, NOX(" (Not a number)"));
7704 gr_printf(10, y_index, buf);
7705 y_index += font_height;
7718 extern int Tmap_npixels;
7720 int Tmap_num_too_big = 0;
7721 int Num_models_needing_splitting = 0;
7723 void Time_model( int modelnum )
7725 // mprintf(( "Timing ship '%s'\n", si->name ));
7727 vector eye_pos, model_pos;
7728 matrix eye_orient, model_orient;
7730 polymodel *pm = model_get( modelnum );
7732 int l = strlen(pm->filename);
7734 if ( (l == '/') || (l=='\\') || (l==':')) {
7740 char *pof_file = &pm->filename[l];
7742 int model_needs_splitting = 0;
7744 //fprintf( Texture_fp, "Model: %s\n", pof_file );
7746 for (i=0; i<pm->n_textures; i++ ) {
7747 char filename[1024];
7750 int bmp_num = pm->original_textures[i];
7751 if ( bmp_num > -1 ) {
7752 bm_get_palette(pm->original_textures[i], pal, filename );
7754 bm_get_info( pm->original_textures[i],&w, &h );
7757 if ( (w > 512) || (h > 512) ) {
7758 fprintf( Texture_fp, "%s\t%s\t%d\t%d\n", pof_file, filename, w, h );
7760 model_needs_splitting++;
7763 //fprintf( Texture_fp, "\tTexture %d is bogus\n", i );
7767 if ( model_needs_splitting ) {
7768 Num_models_needing_splitting++;
7770 eye_orient = model_orient = vmd_identity_matrix;
7771 eye_pos = model_pos = vmd_zero_vector;
7773 eye_pos.xyz.z = -pm->rad*2.0f;
7775 vector eye_to_model;
7777 vm_vec_sub( &eye_to_model, &model_pos, &eye_pos );
7778 vm_vector_2_matrix( &eye_orient, &eye_to_model, NULL, NULL );
7780 fix t1 = timer_get_fixed_seconds();
7783 ta.p = ta.b = ta.h = 0.0f;
7788 int bitmaps_used_this_frame, bitmaps_new_this_frame;
7790 bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
7792 modelstats_num_polys = modelstats_num_verts = 0;
7794 while( ta.h < PI2 ) {
7797 vm_angles_2_matrix(&m1, &ta );
7798 vm_matrix_x_matrix( &model_orient, &vmd_identity_matrix, &m1 );
7805 g3_set_view_matrix( &eye_pos, &eye_orient, Viewer_zoom );
7807 model_clear_instance( modelnum );
7808 model_set_detail_level(0); // use highest detail level
7809 model_render( modelnum, &model_orient, &model_pos, MR_LOCK_DETAIL); //|MR_NO_POLYS );
7817 int k = key_inkey();
7818 if ( k == KEY_ESC ) {
7823 fix t2 = timer_get_fixed_seconds();
7825 bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
7826 //bitmaps_used_this_frame /= framecount;
7828 modelstats_num_polys /= framecount;
7829 modelstats_num_verts /= framecount;
7831 Tmap_npixels /=framecount;
7834 mprintf(( "'%s' is %.2f FPS\n", pof_file, i2fl(framecount)/f2fl(t2-t1) ));
7835 fprintf( Time_fp, "\"%s\"\t%.0f\t%d\t%d\t%d\t%d\n", pof_file, i2fl(framecount)/f2fl(t2-t1), bitmaps_used_this_frame, modelstats_num_polys, modelstats_num_verts, Tmap_npixels );
7836 // fprintf( Time_fp, "%.0f\t%d\t%d\t%d\t%d\n", i2fl(framecount)/f2fl(t2-t1), bitmaps_used_this_frame, modelstats_num_polys, modelstats_num_verts, Tmap_npixels );
7842 int Time_models = 0;
7843 DCF_BOOL( time_models, Time_models );
7845 void Do_model_timings_test()
7849 if ( !Time_models ) return;
7851 mprintf(( "Timing models!\n" ));
7855 ubyte model_used[MAX_POLYGON_MODELS];
7856 int model_id[MAX_POLYGON_MODELS];
7857 for (i=0; i<MAX_POLYGON_MODELS; i++ ) {
7862 for (i=0; i<Num_ship_types; i++ ) {
7863 Ship_info[i].modelnum = model_load( Ship_info[i].pof_file, 0, NULL );
7865 model_used[Ship_info[i].modelnum%MAX_POLYGON_MODELS]++;
7866 model_id[Ship_info[i].modelnum%MAX_POLYGON_MODELS] = Ship_info[i].modelnum;
7869 Texture_fp = fopen( NOX("ShipTextures.txt"), "wt" );
7870 if ( !Texture_fp ) return;
7872 Time_fp = fopen( NOX("ShipTimings.txt"), "wt" );
7873 if ( !Time_fp ) return;
7875 fprintf( Time_fp, "Name\tFPS\tTRAM\tPolys\tVerts\tPixels\n" );
7876 // fprintf( Time_fp, "FPS\tTRAM\tPolys\tVerts\tPixels\n" );
7878 for (i=0; i<MAX_POLYGON_MODELS; i++ ) {
7879 if ( model_used[i] ) {
7880 Time_model( model_id[i] );
7884 fprintf( Texture_fp, "Number too big: %d\n", Tmap_num_too_big );
7885 fprintf( Texture_fp, "Number of models needing splitting: %d\n", Num_models_needing_splitting );
7894 // Call this function when you want to inform the player that a feature is not
7895 // enabled in the DEMO version of FreSpace
7896 void game_feature_not_in_demo_popup()
7898 popup(PF_USE_AFFIRMATIVE_ICON|PF_BODY_BIG, 1, POPUP_OK, XSTR( "Sorry, this feature is available only in the retail version", 200));
7901 // format the specified time (fixed point) into a nice string
7902 void game_format_time(fix m_time,char *time_str)
7905 int hours,minutes,seconds;
7908 mtime = f2fl(m_time);
7910 // get the hours, minutes and seconds
7911 hours = (int)(mtime / 3600.0f);
7913 mtime -= (3600.0f * (float)hours);
7915 seconds = (int)mtime%60;
7916 minutes = (int)mtime/60;
7918 // print the hour if necessary
7920 sprintf(time_str,XSTR( "%d:", 201),hours);
7921 // if there are less than 10 minutes, print a leading 0
7923 strcpy(tmp,NOX("0"));
7924 strcat(time_str,tmp);
7928 // print the minutes
7930 sprintf(tmp,XSTR( "%d:", 201),minutes);
7931 strcat(time_str,tmp);
7933 sprintf(time_str,XSTR( "%d:", 201),minutes);
7936 // print the seconds
7938 strcpy(tmp,NOX("0"));
7939 strcat(time_str,tmp);
7941 sprintf(tmp,"%d",seconds);
7942 strcat(time_str,tmp);
7945 // Stuff version string in *str.
7946 void get_version_string(char *str)
7949 if ( FS_VERSION_BUILD == 0 ) {
7950 sprintf(str,"v%d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR);
7952 sprintf(str,"v%d.%02d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR, FS_VERSION_BUILD );
7955 #if defined (FS2_DEMO) || defined(FS1_DEMO)
7957 #elif defined (OEM_BUILD)
7958 strcat(str, " (OEM)");
7964 char myname[_MAX_PATH];
7965 int namelen, major, minor, build, waste;
7966 unsigned int buf_size;
7972 // Find my EXE file name
7973 hMod = GetModuleHandle(NULL);
7974 namelen = GetModuleFileName( hMod, myname, _MAX_PATH );
7976 version_size = GetFileVersionInfoSize(myname, &bogus_handle );
7977 infop = (char *)malloc(version_size);
7978 result = GetFileVersionInfo( myname, 0, version_size, (LPVOID)infop );
7980 // get the product version
7981 result = VerQueryValue((LPVOID)infop, TEXT("\\StringFileInfo\\040904b0\\ProductVersion"), &bufp, &buf_size );
7982 sscanf( (char *)bufp, "%d, %d, %d, %d", &major, &minor, &build, &waste );
7984 sprintf(str,"Dv%d.%02d",major, minor);
7986 sprintf(str,"v%d.%02d",major, minor);
7991 void get_version_string_short(char *str)
7993 sprintf(str,"v%d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR);
7996 // ----------------------------------------------------------------
7998 // OEM UPSELL SCREENS BEGIN
8000 // ----------------------------------------------------------------
8001 #if defined(OEM_BUILD)
8003 #define NUM_OEM_UPSELL_SCREENS 3
8004 #define OEM_UPSELL_SCREEN_DELAY 10000
8006 static int Oem_upsell_bitmaps_loaded = 0;
8007 static int Oem_upsell_bitmaps[GR_NUM_RESOLUTIONS][NUM_OEM_UPSELL_SCREENS];
8008 static int Oem_upsell_screen_number = 0;
8009 static int Oem_upsell_show_next_bitmap_time;
8012 static char *Oem_upsell_bitmap_filenames[GR_NUM_RESOLUTIONS][NUM_OEM_UPSELL_SCREENS] =
8025 static int Oem_normal_cursor = -1;
8026 static int Oem_web_cursor = -1;
8027 //#define OEM_UPSELL_URL "http://www.interplay-store.com/"
8028 #define OEM_UPSELL_URL "http://www.interplay.com/cgi-bin/oemlinks.pl/pid=483421&cid=18384"
8030 void oem_upsell_next_screen()
8032 Oem_upsell_screen_number++;
8033 if ( Oem_upsell_screen_number == (NUM_OEM_UPSELL_SCREENS-1) ) {
8034 // extra long delay, mouse shown on last upsell
8035 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY*2;
8039 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY;
8043 void oem_upsell_load_bitmaps()
8047 for ( i = 0; i < NUM_OEM_UPSELL_SCREENS; i++ ) {
8048 Oem_upsell_bitmaps[gr_screen.res][i] = bm_load(Oem_upsell_bitmap_filenames[gr_screen.res][i]);
8052 void oem_upsell_unload_bitmaps()
8056 for ( i = 0; i < NUM_OEM_UPSELL_SCREENS; i++ ) {
8057 if(Oem_upsell_bitmaps[gr_screen.res][i] >= 0){
8058 bm_unload(Oem_upsell_bitmaps[gr_screen.res][i]);
8063 Oem_upsell_bitmaps_loaded = 0;
8066 // clickable hotspot on 3rd OEM upsell screen
8067 static int Oem_upsell3_button_coords[GR_NUM_RESOLUTIONS][4] = {
8069 28, 350, 287, 96 // x, y, w, h
8072 45, 561, 460, 152 // x, y, w, h
8076 void oem_upsell_show_screens()
8078 int current_time, k;
8081 if ( !Oem_upsell_bitmaps_loaded ) {
8082 oem_upsell_load_bitmaps();
8083 Oem_upsell_bitmaps_loaded = 1;
8086 // may use upsell screens more than once
8087 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY;
8088 Oem_upsell_screen_number = 0;
8094 int nframes; // used to pass, not really needed (should be 1)
8095 Oem_normal_cursor = gr_get_cursor_bitmap();
8096 Oem_web_cursor = bm_load_animation("cursorweb", &nframes);
8097 Assert(Oem_web_cursor >= 0);
8098 if (Oem_web_cursor < 0) {
8099 Oem_web_cursor = Oem_normal_cursor;
8104 //oem_reset_trailer_timer();
8106 current_time = timer_get_milliseconds();
8111 // advance screen on keypress or timeout
8112 if (( k > 0 ) || (mouse_up_count(MOUSE_LEFT_BUTTON) > 0) || (current_time > Oem_upsell_show_next_bitmap_time)) {
8113 oem_upsell_next_screen();
8116 // check if we are done
8117 if ( Oem_upsell_screen_number >= NUM_OEM_UPSELL_SCREENS ) {
8118 Oem_upsell_screen_number--;
8121 if ( Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number] < 0 ) {
8126 // show me the upsell
8127 if ( Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number] >= 0 ) {
8128 gr_set_bitmap(Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number]);
8132 // if this is the 3rd upsell, make it clickable, d00d
8133 if ( Oem_upsell_screen_number == NUM_OEM_UPSELL_SCREENS-1 ) {
8135 int button_state = mouse_get_pos(&mx, &my);
8136 if ( (mx >= Oem_upsell3_button_coords[gr_screen.res][0]) && (mx <= Oem_upsell3_button_coords[gr_screen.res][0] + Oem_upsell3_button_coords[gr_screen.res][2])
8137 && (my >= Oem_upsell3_button_coords[gr_screen.res][1]) && (my <= Oem_upsell3_button_coords[gr_screen.res][1] + Oem_upsell3_button_coords[gr_screen.res][3]) )
8140 gr_set_cursor_bitmap(Oem_web_cursor); //, GR_CURSOR_LOCK);
8143 if (button_state & MOUSE_LEFT_BUTTON) {
8145 multi_pxo_url(OEM_UPSELL_URL);
8149 // switch cursor back to normal one
8150 gr_set_cursor_bitmap(Oem_normal_cursor); //, GR_CURSOR_UNLOCK);
8155 if (gameseq_get_state() != GS_STATE_END_DEMO) {
8165 oem_upsell_unload_bitmaps();
8167 // switch cursor back to normal one
8168 gr_set_cursor_bitmap(Oem_normal_cursor); //, GR_CURSOR_UNLOCK);
8172 #endif // defined(OEM_BUILD)
8173 // ----------------------------------------------------------------
8175 // OEM UPSELL SCREENS END
8177 // ----------------------------------------------------------------
8181 // ----------------------------------------------------------------
8183 // DEMO UPSELL SCREENS BEGIN
8185 // ----------------------------------------------------------------
8187 #if defined(FS2_DEMO) || defined(FS1_DEMO)
8190 #define NUM_DEMO_UPSELL_SCREENS 2
8192 #define NUM_DEMO_UPSELL_SCREENS 4
8194 #define DEMO_UPSELL_SCREEN_DELAY 3000
8196 static int Demo_upsell_bitmaps_loaded = 0;
8197 static int Demo_upsell_bitmaps[GR_NUM_RESOLUTIONS][NUM_DEMO_UPSELL_SCREENS];
8198 static int Demo_upsell_screen_number = 0;
8199 static int Demo_upsell_show_next_bitmap_time;
8202 static char *Demo_upsell_bitmap_filenames[GR_NUM_RESOLUTIONS][NUM_DEMO_UPSELL_SCREENS] =
8228 void demo_upsell_next_screen()
8230 Demo_upsell_screen_number++;
8231 if ( Demo_upsell_screen_number == (NUM_DEMO_UPSELL_SCREENS-1) ) {
8232 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY*4;
8234 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY;
8238 if ( Demo_upsell_screen_number < NUM_DEMO_UPSELL_SCREENS ) {
8239 if ( Demo_upsell_bitmap_filenames[gr_screen.res][Demo_upsell_screen_number] >= 0 ) {
8240 #ifndef HARDWARE_ONLY
8241 palette_use_bm_palette(Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number]);
8248 void demo_upsell_load_bitmaps()
8252 for ( i = 0; i < NUM_DEMO_UPSELL_SCREENS; i++ ) {
8253 Demo_upsell_bitmaps[gr_screen.res][i] = bm_load(Demo_upsell_bitmap_filenames[gr_screen.res][i]);
8257 void demo_upsell_unload_bitmaps()
8261 for ( i = 0; i < NUM_DEMO_UPSELL_SCREENS; i++ ) {
8262 if(Demo_upsell_bitmaps[gr_screen.res][i] >= 0){
8263 bm_unload(Demo_upsell_bitmaps[gr_screen.res][i]);
8268 Demo_upsell_bitmaps_loaded = 0;
8271 void demo_upsell_show_screens()
8273 int current_time, k;
8276 if ( !Demo_upsell_bitmaps_loaded ) {
8277 demo_upsell_load_bitmaps();
8278 Demo_upsell_bitmaps_loaded = 1;
8281 // may use upsell screens more than once
8282 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY;
8283 Demo_upsell_screen_number = 0;
8290 demo_reset_trailer_timer();
8292 current_time = timer_get_milliseconds();
8299 // don't time out, wait for keypress
8301 if ( current_time > Demo_upsell_show_next_bitmap_time ) {
8302 demo_upsell_next_screen();
8307 demo_upsell_next_screen();
8310 if ( Demo_upsell_screen_number >= NUM_DEMO_UPSELL_SCREENS ) {
8311 Demo_upsell_screen_number--;
8314 if ( Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number] < 0 ) {
8319 if ( Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number] >= 0 ) {
8320 gr_set_bitmap(Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number]);
8325 if (gameseq_get_state() != GS_STATE_END_DEMO) {
8335 demo_upsell_unload_bitmaps();
8340 // ----------------------------------------------------------------
8342 // DEMO UPSELL SCREENS END
8344 // ----------------------------------------------------------------
8347 // ----------------------------------------------------------------
8349 // Subspace Ambient Sound START
8351 // ----------------------------------------------------------------
8353 static int Subspace_ambient_left_channel = -1;
8354 static int Subspace_ambient_right_channel = -1;
8357 void game_start_subspace_ambient_sound()
8359 if ( Subspace_ambient_left_channel < 0 ) {
8360 Subspace_ambient_left_channel = snd_play_looping(&Snds[SND_SUBSPACE_LEFT_CHANNEL], -1.0f);
8363 if ( Subspace_ambient_right_channel < 0 ) {
8364 Subspace_ambient_right_channel = snd_play_looping(&Snds[SND_SUBSPACE_RIGHT_CHANNEL], 1.0f);
8368 void game_stop_subspace_ambient_sound()
8370 if ( Subspace_ambient_left_channel >= 0 ) {
8371 snd_stop(Subspace_ambient_left_channel);
8372 Subspace_ambient_left_channel = -1;
8375 if ( Subspace_ambient_right_channel >= 0 ) {
8376 snd_stop(Subspace_ambient_right_channel);
8377 Subspace_ambient_right_channel = -1;
8381 // ----------------------------------------------------------------
8383 // Subspace Ambient Sound END
8385 // ----------------------------------------------------------------
8387 // ----------------------------------------------------------------
8389 // CDROM detection code START
8391 // ----------------------------------------------------------------
8393 #define CD_SIZE_72_MINUTE_MAX (697000000)
8395 uint game_get_cd_used_space(char *path)
8399 char use_path[512] = "";
8400 char sub_path[512] = "";
8401 WIN32_FIND_DATA find;
8404 // recurse through all files and directories
8405 strcpy(use_path, path);
8406 strcat(use_path, "*.*");
8407 find_handle = FindFirstFile(use_path, &find);
8410 if(find_handle == INVALID_HANDLE_VALUE){
8416 // subdirectory. make sure to ignore . and ..
8417 if((find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && stricmp(find.cFileName, ".") && stricmp(find.cFileName, "..")){
8419 strcpy(sub_path, path);
8420 strcat(sub_path, find.cFileName);
8421 strcat(sub_path, "\\");
8422 total += game_get_cd_used_space(sub_path);
8424 total += (uint)find.nFileSizeLow;
8426 } while(FindNextFile(find_handle, &find));
8429 FindClose(find_handle);
8441 // if volume_name is non-null, the CD name must match that
8442 int find_freespace_cd(char *volume_name)
8445 char oldpath[MAX_PATH];
8449 int volume_match = 0;
8453 GetCurrentDirectory(MAX_PATH, oldpath);
8455 for (i = 0; i < 26; i++)
8461 path[0] = (char)('A'+i);
8462 if (GetDriveType(path) == DRIVE_CDROM) {
8464 if ( GetVolumeInformation(path, volume, 256, NULL, NULL, NULL, NULL, 0) == TRUE ) {
8465 nprintf(("CD", "CD volume: %s\n", volume));
8467 // check for any CD volume
8468 int volume1_present = 0;
8469 int volume2_present = 0;
8470 int volume3_present = 0;
8472 char full_check[512] = "";
8474 // look for setup.exe
8475 strcpy(full_check, path);
8476 strcat(full_check, "setup.exe");
8477 find_handle = _findfirst(full_check, &find);
8478 if(find_handle != -1){
8479 volume1_present = 1;
8480 _findclose(find_handle);
8483 // look for intro.mve
8484 strcpy(full_check, path);
8485 strcat(full_check, "intro.mve");
8486 find_handle = _findfirst(full_check, &find);
8487 if(find_handle != -1){
8488 volume2_present = 1;
8489 _findclose(find_handle);
8492 // look for endpart1.mve
8493 strcpy(full_check, path);
8494 strcat(full_check, "endpart1.mve");
8495 find_handle = _findfirst(full_check, &find);
8496 if(find_handle != -1){
8497 volume3_present = 1;
8498 _findclose(find_handle);
8501 // see if we have the specific CD we're looking for
8502 if ( volume_name ) {
8504 if ( !stricmp(volume_name, FS_CDROM_VOLUME_1) && volume1_present) {
8508 if ( !stricmp(volume_name, FS_CDROM_VOLUME_2) && volume2_present) {
8512 if ( !stricmp(volume_name, FS_CDROM_VOLUME_3) && volume3_present) {
8516 if ( volume1_present || volume2_present || volume3_present ) {
8521 // here's where we make sure that CD's 2 and 3 are not just ripped - check to make sure its capacity is > 697,000,000 bytes
8522 if ( volume_match ){
8524 // we don't care about CD1 though. let it be whatever size it wants, since the game will demand CD's 2 and 3 at the proper time
8525 if(volume2_present || volume3_present) {
8526 // first step - check to make sure its a cdrom
8527 if(GetDriveType(path) != DRIVE_CDROM){
8531 #if !defined(OEM_BUILD)
8532 // oem not on 80 min cds, so dont check tha size
8534 uint used_space = game_get_cd_used_space(path);
8535 if(used_space < CD_SIZE_72_MINUTE_MAX){
8538 #endif // !defined(OEM_BUILD)
8546 #endif // RELEASE_REAL
8552 SetCurrentDirectory(oldpath);
8561 int set_cdrom_path(int drive_num)
8565 if (drive_num < 0) { //no CD
8567 // strcpy(CDROM_dir,"j:\\FreeSpaceCD\\"); //set directory
8570 strcpy(Game_CDROM_dir,""); //set directory
8574 sprintf(Game_CDROM_dir,NOX("%c:\\"), 'a' + drive_num ); //set directory
8590 i = find_freespace_cd();
8592 rval = set_cdrom_path(i);
8596 nprintf(("CD", "Using %s for FreeSpace CD\n", CDROM_dir));
8598 nprintf(("CD", "FreeSpace CD not found\n"));
8606 int Last_cd_label_found = 0;
8607 char Last_cd_label[256];
8609 int game_cd_changed()
8616 if ( strlen(Game_CDROM_dir) == 0 ) {
8620 found = GetVolumeInformation(Game_CDROM_dir, label, 256, NULL, NULL, NULL, NULL, 0);
8622 if ( found != Last_cd_label_found ) {
8623 Last_cd_label_found = found;
8625 mprintf(( "CD '%s' was inserted\n", label ));
8628 mprintf(( "CD '%s' was removed\n", Last_cd_label ));
8632 if ( Last_cd_label_found ) {
8633 if ( !stricmp( Last_cd_label, label )) {
8634 //mprintf(( "CD didn't change\n" ));
8636 mprintf(( "CD was changed from '%s' to '%s'\n", Last_cd_label, label ));
8640 // none found before, none found now.
8641 //mprintf(( "still no CD...\n" ));
8645 Last_cd_label_found = found;
8647 strcpy( Last_cd_label, label );
8649 strcpy( Last_cd_label, "" );
8660 // check if _any_ FreeSpace2 CDs are in the drive
8661 // return: 1 => CD now in drive
8662 // 0 => Could not find CD, they refuse to put it in the drive
8663 int game_do_cd_check(char *volume_name)
8665 #if !defined(GAME_CD_CHECK)
8671 int num_attempts = 0;
8672 int refresh_files = 0;
8674 int path_set_ok, popup_rval;
8676 cd_drive_num = find_freespace_cd(volume_name);
8677 path_set_ok = set_cdrom_path(cd_drive_num);
8678 if ( path_set_ok ) {
8680 if ( refresh_files ) {
8692 // no CD found, so prompt user
8693 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR( "FreeSpace 2 CD not found\n\nInsert a FreeSpace 2 CD to continue", 202));
8695 if ( popup_rval != 1 ) {
8700 if ( num_attempts++ > 5 ) {
8711 // check if _any_ FreeSpace2 CDs are in the drive
8712 // return: 1 => CD now in drive
8713 // 0 => Could not find CD, they refuse to put it in the drive
8714 int game_do_cd_check_specific(char *volume_name, int cdnum)
8719 int num_attempts = 0;
8720 int refresh_files = 0;
8722 int path_set_ok, popup_rval;
8724 cd_drive_num = find_freespace_cd(volume_name);
8725 path_set_ok = set_cdrom_path(cd_drive_num);
8726 if ( path_set_ok ) {
8728 if ( refresh_files ) {
8739 // no CD found, so prompt user
8740 #if defined(DVD_MESSAGE_HACK)
8741 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR("Please insert DVD", 1468));
8743 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR("Please insert CD %d", 1468), cdnum);
8746 if ( popup_rval != 1 ) {
8751 if ( num_attempts++ > 5 ) {
8761 // only need to do this in RELEASE_REAL
8762 int game_do_cd_mission_check(char *filename)
8768 fs_builtin_mission *m = game_find_builtin_mission(filename);
8770 // check for changed CD
8771 if(game_cd_changed()){
8776 if((Game_mode & GM_MULTIPLAYER) || Is_standalone){
8780 // not builtin, so do a general check (any FS2 CD will do)
8782 return game_do_cd_check();
8785 // does not have any CD requirement, do a general check
8786 if(strlen(m->cd_volume) <= 0){
8787 return game_do_cd_check();
8791 if(!stricmp(m->cd_volume, FS_CDROM_VOLUME_1)){
8793 } else if(!stricmp(m->cd_volume, FS_CDROM_VOLUME_2)){
8796 } else if(!stricmp(m->cd_volume, FS_CDROM_VOLUME_3)){
8800 return game_do_cd_check();
8803 // did we find the cd?
8804 if(find_freespace_cd(m->cd_volume) >= 0){
8808 // make sure the volume exists
8809 int num_attempts = 0;
8810 int refresh_files = 0;
8812 int path_set_ok, popup_rval;
8814 cd_drive_num = find_freespace_cd(m->cd_volume);
8815 path_set_ok = set_cdrom_path(cd_drive_num);
8816 if ( path_set_ok ) {
8818 if ( refresh_files ) {
8825 // no CD found, so prompt user
8826 #if defined(DVD_MESSAGE_HACK)
8827 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR("Please insert DVD", 1468));
8829 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR("Please insert CD %d", 1468), cd_num);
8833 if ( popup_rval != 1 ) {
8838 if ( num_attempts++ > 5 ) {
8850 // ----------------------------------------------------------------
8852 // CDROM detection code END
8854 // ----------------------------------------------------------------
8856 // ----------------------------------------------------------------
8858 // Language Autodetection stuff
8861 // this layout order must match Lcl_languages in localize.cpp in order for the
8862 // correct language to be detected
8863 int Lang_auto_detect_checksums[LCL_NUM_LANGUAGES] = {
8865 1366105450, // English
8867 589986744, // English
8869 -1132430286, // German
8871 -1131728960, // Polish
8874 // default setting is "-1" to use config file with English as fall back
8875 // DO NOT change the default setting here or something uncouth might happen
8876 // in the localization code
8882 // try and open the file to verify
8883 CFILE *detect = cfopen("font01.vf", "rb");
8885 // will use default setting if something went wrong
8890 // get the long checksum of the file
8892 cfseek(detect, 0, SEEK_SET);
8893 cf_chksum_long(detect, &file_checksum);
8897 // now compare the checksum/filesize against known #'s
8898 for (idx=0; idx<LCL_NUM_LANGUAGES; idx++) {
8899 if (Lang_auto_detect_checksums[idx] == (int)file_checksum) {
8904 // notify if a match was not found, include detected checksum
8905 printf("ERROR: Unknown Language Checksum: %i\n", (int)file_checksum);
8906 printf("Using default language...\n\n");
8912 // End Auto Lang stuff
8914 // ----------------------------------------------------------------
8916 // ----------------------------------------------------------------
8917 // SHIPS TBL VERIFICATION STUFF
8920 // checksums, just keep a list of all valid ones, if it matches any of them, keep it
8921 #if defined(MAKE_FS1) && !defined(FS1_DEMO)
8922 #define NUM_SHIPS_TBL_CHECKSUMS 3
8924 #define NUM_SHIPS_TBL_CHECKSUMS 1
8928 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8929 1696074201, // FS2 demo
8932 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8933 1603375034, // FS1 DEMO
8936 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8937 -129679197, // FS1 Full 1.06 (US)
8938 7762567, // FS1 SilentThreat
8939 1555372475 // FS1 Full 1.06 (German)
8943 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8944 -463907578, // US - beta 1
8945 1696074201, // FS2 demo
8948 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8949 // -1022810006, // 1.0 FULL
8950 -1254285366 // 1.2 FULL (German)
8954 void verify_ships_tbl()
8958 Game_ships_tbl_valid = 1;
8964 // detect if the packfile exists
8965 CFILE *detect = cfopen("ships.tbl", "rb");
8966 Game_ships_tbl_valid = 0;
8970 Game_ships_tbl_valid = 0;
8974 // get the long checksum of the file
8976 cfseek(detect, 0, SEEK_SET);
8977 cf_chksum_long(detect, &file_checksum);
8981 // now compare the checksum/filesize against known #'s
8982 for(idx=0; idx<NUM_SHIPS_TBL_CHECKSUMS; idx++){
8983 if(Game_ships_tbl_checksums[idx] == (int)file_checksum){
8984 Game_ships_tbl_valid = 1;
8991 DCF(shipspew, "display the checksum for the current ships.tbl")
8994 CFILE *detect = cfopen("ships.tbl", "rb");
8995 // get the long checksum of the file
8997 cfseek(detect, 0, SEEK_SET);
8998 cf_chksum_long(detect, &file_checksum);
9001 dc_printf("%d", file_checksum);
9004 // ----------------------------------------------------------------
9005 // WEAPONS TBL VERIFICATION STUFF
9008 // checksums, just keep a list of all valid ones, if it matches any of them, keep it
9009 #if defined(MAKE_FS1) && !defined(FS1_DEMO)
9010 #define NUM_WEAPONS_TBL_CHECKSUMS 3
9012 #define NUM_WEAPONS_TBL_CHECKSUMS 1
9016 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
9017 -266420030, // demo 1
9020 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
9021 -1246928725, // FS1 DEMO
9024 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
9025 -834598107, // FS1 1.06 Full (US)
9026 -1652231417, // FS1 SilentThreat
9027 720209793 // FS1 1.06 Full (German)
9031 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
9032 141718090, // US - beta 1
9033 -266420030, // demo 1
9036 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
9037 // 399297860, // 1.0 FULL
9038 -553984927 // 1.2 FULL (german)
9042 void verify_weapons_tbl()
9046 Game_weapons_tbl_valid = 1;
9052 // detect if the packfile exists
9053 CFILE *detect = cfopen("weapons.tbl", "rb");
9054 Game_weapons_tbl_valid = 0;
9058 Game_weapons_tbl_valid = 0;
9062 // get the long checksum of the file
9064 cfseek(detect, 0, SEEK_SET);
9065 cf_chksum_long(detect, &file_checksum);
9069 // now compare the checksum/filesize against known #'s
9070 for(idx=0; idx<NUM_WEAPONS_TBL_CHECKSUMS; idx++){
9071 if(Game_weapons_tbl_checksums[idx] == (int)file_checksum){
9072 Game_weapons_tbl_valid = 1;
9079 DCF(wepspew, "display the checksum for the current weapons.tbl")
9082 CFILE *detect = cfopen("weapons.tbl", "rb");
9083 // get the long checksum of the file
9085 cfseek(detect, 0, SEEK_SET);
9086 cf_chksum_long(detect, &file_checksum);
9089 dc_printf("%d", file_checksum);
9092 // if the game is running using hacked data
9093 int game_hacked_data()
9096 if(!Game_weapons_tbl_valid || !Game_ships_tbl_valid){
9104 void display_title_screen()
9106 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
9107 ///int title_bitmap;
9110 int title_bitmap = bm_load(Game_demo_title_screen_fname[gr_screen.res]);
9111 if (title_bitmap == -1) {
9117 if((gr_screen.mode == GR_DIRECT3D) && (Gr_bitmap_poly)){
9118 extern void d3d_start_frame();
9124 gr_set_bitmap(title_bitmap);
9131 if((gr_screen.mode == GR_DIRECT3D) && (Gr_bitmap_poly)){
9132 extern void d3d_stop_frame();
9140 bm_unload(title_bitmap);
9141 #endif // FS2_DEMO || OEM_BUILD || FS1_DEMO
9144 // return true if the game is running with "low memory", which is less than 48MB
9145 bool game_using_low_mem()
9147 if (Use_low_mem == 0) {