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.38 2004/09/20 01:31:44 theoddone33
21 * Revision 1.37 2004/07/04 11:31:43 taylor
22 * amd64 support, compiler warning fixes, don't use software rendering
24 * Revision 1.36 2004/06/12 01:11:35 taylor
25 * x86 compile fixes for OSX patch
27 * Revision 1.35 2004/06/11 00:53:02 tigital
28 * OSX: .app name, casts for gcc
30 * Revision 1.34 2003/08/09 03:18:03 taylor
31 * fix tips popup not having any tips
33 * Revision 1.33 2003/08/03 15:57:00 taylor
34 * simpler mouse usage; default ini settings in os_init(); cleanup
36 * Revision 1.32 2003/06/19 11:51:41 taylor
37 * adjustments to memory leak fixes
39 * Revision 1.31 2003/06/11 18:30:32 taylor
42 * Revision 1.30 2003/06/03 04:00:39 taylor
43 * Polish language support (Janusz Dziemidowicz)
45 * Revision 1.29 2003/05/25 02:30:42 taylor
48 * Revision 1.28 2003/05/18 03:55:30 taylor
49 * automatic language selection support
51 * Revision 1.27 2003/03/03 04:54:44 theoddone33
52 * Commit Taylor's ShowFPS fix
54 * Revision 1.26 2003/02/20 17:41:07 theoddone33
55 * Userdir patch from Taylor Richards
57 * Revision 1.25 2003/01/30 19:54:10 relnev
58 * ini config option for the frames per second counter (Taylor Richards)
60 * Revision 1.24 2002/08/31 01:39:13 theoddone33
61 * Speed up the renderer a tad
63 * Revision 1.23 2002/08/04 02:31:00 relnev
64 * make numlock not overlap with pause
66 * Revision 1.22 2002/08/02 23:07:03 relnev
67 * don't access the mouse in standalone mode
69 * Revision 1.21 2002/07/28 05:05:08 relnev
70 * removed some old stuff
72 * Revision 1.20 2002/07/24 00:20:41 relnev
75 * Revision 1.19 2002/06/17 06:33:08 relnev
76 * ryan's struct patch for gcc 2.95
78 * Revision 1.18 2002/06/16 04:46:33 relnev
79 * set up correct checksums for demo
81 * Revision 1.17 2002/06/09 04:41:17 relnev
82 * added copyright header
84 * Revision 1.16 2002/06/09 03:16:04 relnev
87 * removed unneeded asm, old sdl 2d setup.
89 * fixed crash caused by opengl_get_region.
91 * Revision 1.15 2002/06/05 08:05:28 relnev
92 * stub/warning removal.
94 * reworked the sound code.
96 * Revision 1.14 2002/06/05 04:03:32 relnev
97 * finished cfilesystem.
99 * removed some old code.
101 * fixed mouse save off-by-one.
105 * Revision 1.13 2002/06/02 04:26:34 relnev
108 * Revision 1.12 2002/06/02 00:31:35 relnev
109 * implemented osregistry
111 * Revision 1.11 2002/06/01 09:00:34 relnev
112 * silly debug memmanager
114 * Revision 1.10 2002/06/01 07:12:32 relnev
115 * a few NDEBUG updates.
117 * removed a few warnings.
119 * Revision 1.9 2002/05/31 03:05:59 relnev
122 * Revision 1.8 2002/05/29 02:52:32 theoddone33
123 * Enable OpenGL renderer
125 * Revision 1.7 2002/05/28 08:52:03 relnev
126 * implemented two assembly stubs.
128 * cleaned up a few warnings.
130 * added a little demo hackery to make it progress a little farther.
132 * Revision 1.6 2002/05/28 06:28:20 theoddone33
133 * Filesystem mods, actually reads some data files now
135 * Revision 1.5 2002/05/28 04:07:28 theoddone33
136 * New graphics stubbing arrangement
138 * Revision 1.4 2002/05/27 22:46:52 theoddone33
139 * Remove more undefined symbols
141 * Revision 1.3 2002/05/26 23:31:18 relnev
142 * added a few files that needed to be compiled
144 * freespace.cpp: now compiles
146 * Revision 1.2 2002/05/07 03:16:44 theoddone33
147 * The Great Newline Fix
149 * Revision 1.1.1.1 2002/05/03 03:28:09 root
153 * 201 6/16/00 3:15p Jefff
154 * sim of the year dvd version changes, a few german soty localization
157 * 200 11/03/99 11:06a Jefff
160 * 199 10/26/99 5:07p Jamest
161 * fixed jeffs dumb debug code
163 * 198 10/25/99 5:53p Jefff
164 * call control_config_common_init() on startup
166 * 197 10/14/99 10:18a Daveb
167 * Fixed incorrect CD checking problem on standalone server.
169 * 196 10/13/99 9:22a Daveb
170 * Fixed Fred jumpnode placing bug. Fixed 1024 glide tiled texture problem
171 * related to movies. Fixed launcher spawning from PXO screen.
173 * 195 10/06/99 11:05a Jefff
174 * new oem upsell 3 hotspot coords
176 * 194 10/06/99 10:31a Jefff
179 * 193 10/01/99 9:10a Daveb
182 * 192 9/15/99 4:57a Dave
183 * Updated ships.tbl checksum
185 * 191 9/15/99 3:58a Dave
186 * Removed framerate warning at all times.
188 * 190 9/15/99 3:16a Dave
189 * Remove mt-011.fs2 from the builtin mission list.
191 * 189 9/15/99 1:45a Dave
192 * Don't init joystick on standalone. Fixed campaign mode on standalone.
193 * Fixed no-score-report problem in TvT
195 * 188 9/14/99 6:08a Dave
196 * Updated (final) single, multi, and campaign list.
198 * 187 9/14/99 3:26a Dave
199 * Fixed laser fogging problem in nebula (D3D)> Fixed multiplayer
200 * respawn-too-early problem. Made a few crash points safe.
202 * 186 9/13/99 4:52p Dave
205 * 185 9/12/99 8:09p Dave
206 * Fixed problem where skip-training button would cause mission messages
207 * not to get paged out for the current mission.
209 * 184 9/10/99 11:53a Dave
210 * Shutdown graphics before sound to eliminate apparent lockups when
211 * Directsound decides to be lame. Fix TOPMOST problem with D3D windows.
213 * 183 9/09/99 11:40p Dave
214 * Handle an Assert() in beam code. Added supernova sounds. Play the right
215 * 2 end movies properly, based upon what the player did in the mission.
217 * 182 9/08/99 10:29p Dave
218 * Make beam sound pausing and unpausing much safer.
220 * 181 9/08/99 10:01p Dave
221 * Make sure game won't run in a drive's root directory. Make sure
222 * standalone routes suqad war messages properly to the host.
224 * 180 9/08/99 3:22p Dave
225 * Updated builtin mission list.
227 * 179 9/08/99 12:01p Jefff
228 * fixed Game_builtin_mission_list typo on Training-2.fs2
230 * 178 9/08/99 9:48a Andsager
231 * Add force feedback for engine wash.
233 * 177 9/07/99 4:01p Dave
234 * Fixed up a string.tbl paroblem (self destruct message). Make sure IPX
235 * does everything properly (setting up address when binding). Remove
236 * black rectangle background from UI_INPUTBOX.
238 * 176 9/13/99 2:40a Dave
239 * Comment in full 80 minute CD check for RELEASE_REAL builds.
241 * 175 9/06/99 6:38p Dave
242 * Improved CD detection code.
244 * 174 9/06/99 1:30a Dave
245 * Intermediate checkin. Started on enforcing CD-in-drive to play the
248 * 173 9/06/99 1:16a Dave
249 * Make sure the user sees the intro movie.
251 * 172 9/04/99 8:00p Dave
252 * Fixed up 1024 and 32 bit movie support.
254 * 171 9/03/99 1:32a Dave
255 * CD checking by act. Added support to play 2 cutscenes in a row
256 * seamlessly. Fixed super low level cfile bug related to files in the
257 * root directory of a CD. Added cheat code to set campaign mission # in
260 * 170 9/01/99 10:49p Dave
261 * Added nice SquadWar checkbox to the client join wait screen.
263 * 169 9/01/99 10:14a Dave
266 * 168 8/29/99 4:51p Dave
267 * Fixed damaged checkin.
269 * 167 8/29/99 4:18p Andsager
270 * New "burst" limit for friendly damage. Also credit more damage done
271 * against large friendly ships.
273 * 166 8/27/99 6:38p Alanl
274 * crush the blasted repeating messages bug
276 * 164 8/26/99 9:09p Dave
277 * Force framerate check in everything but a RELEASE_REAL build.
279 * 163 8/26/99 9:45a Dave
280 * First pass at easter eggs and cheats.
282 * 162 8/24/99 8:55p Dave
283 * Make sure nondimming pixels work properly in tech menu.
285 * 161 8/24/99 1:49a Dave
286 * Fixed client-side afterburner stuttering. Added checkbox for no version
287 * checking on PXO join. Made button info passing more friendly between
290 * 160 8/22/99 5:53p Dave
291 * Scoring fixes. Added self destruct key. Put callsigns in the logfile
292 * instead of ship designations for multiplayer players.
294 * 159 8/22/99 1:19p Dave
295 * Fixed up http proxy code. Cleaned up scoring code. Reverse the order in
296 * which d3d cards are detected.
298 * 158 8/20/99 2:09p Dave
299 * PXO banner cycling.
301 * 157 8/19/99 10:59a Dave
302 * Packet loss detection.
304 * 156 8/19/99 10:12a Alanl
305 * preload mission-specific messages on machines greater than 48MB
307 * 155 8/16/99 4:04p Dave
308 * Big honking checkin.
310 * 154 8/11/99 5:54p Dave
311 * Fixed collision problem. Fixed standalone ghost problem.
313 * 153 8/10/99 7:59p Jefff
316 * 152 8/10/99 6:54p Dave
317 * Mad optimizations. Added paging to the nebula effect.
319 * 151 8/10/99 3:44p Jefff
320 * loads Intelligence information on startup
322 * 150 8/09/99 3:47p Dave
323 * Fixed incorrect nebula regeneration. Default HUD to low-contrast in
324 * non-nebula missions.
326 * 149 8/09/99 2:21p Andsager
327 * Fix patching from multiplayer direct to launcher update tab.
329 * 148 8/09/99 10:36a Dave
330 * Version info for game.
332 * 147 8/06/99 9:46p Dave
333 * Hopefully final changes for the demo.
335 * 146 8/06/99 3:34p Andsager
336 * Make title version info "(D)" -> "D" show up nicely
338 * 145 8/06/99 2:59p Adamp
339 * Fixed NT launcher/update problem.
341 * 144 8/06/99 1:52p Dave
342 * Bumped up MAX_BITMAPS for the demo.
344 * 143 8/06/99 12:17p Andsager
345 * Demo: down to just 1 demo dog
347 * 142 8/05/99 9:39p Dave
348 * Yet another new checksum.
350 * 141 8/05/99 6:19p Dave
351 * New demo checksums.
353 * 140 8/05/99 5:31p Andsager
354 * Up demo version 1.01
356 * 139 8/05/99 4:22p Andsager
357 * No time limit on upsell screens. Reverse order of display of upsell
360 * 138 8/05/99 4:17p Dave
361 * Tweaks to client interpolation.
363 * 137 8/05/99 3:52p Danw
365 * 136 8/05/99 3:01p Danw
367 * 135 8/05/99 2:43a Anoop
368 * removed duplicate definition.
370 * 134 8/05/99 2:13a Dave
373 * 133 8/05/99 2:05a Dave
376 * 132 8/05/99 1:22a Andsager
379 * 131 8/04/99 9:51p Andsager
380 * Add title screen to demo
382 * 130 8/04/99 6:47p Jefff
383 * fixed link error resulting from #ifdefs
385 * 129 8/04/99 6:26p Dave
386 * Updated ship tbl checksum.
388 * 128 8/04/99 5:40p Andsager
389 * Add multiple demo dogs
391 * 127 8/04/99 5:36p Andsager
392 * Show upsell screens at end of demo campaign before returning to main
395 * 126 8/04/99 11:42a Danw
396 * tone down EAX reverb
398 * 125 8/04/99 11:23a Dave
399 * Updated demo checksums.
401 * 124 8/03/99 11:02p Dave
402 * Maybe fixed sync problems in multiplayer.
404 * 123 8/03/99 6:21p Jefff
407 * 122 8/03/99 3:44p Andsager
408 * Launch laucher if trying to run FS without first having configured
411 * 121 8/03/99 12:45p Dave
414 * 120 8/02/99 9:13p Dave
417 * 119 7/30/99 10:31p Dave
418 * Added comm menu to the configurable hud files.
420 * 118 7/30/99 5:17p Andsager
421 * first fs2demo checksums
423 * 117 7/29/99 3:09p Anoop
425 * 116 7/29/99 12:05a Dave
426 * Nebula speed optimizations.
428 * 115 7/27/99 8:59a Andsager
429 * Make major, minor version consistent for all builds. Only show major
430 * and minor for launcher update window.
432 * 114 7/26/99 5:50p Dave
433 * Revised ingame join. Better? We'll see....
435 * 113 7/26/99 5:27p Andsager
436 * Add training mission as builtin to demo build
438 * 112 7/24/99 1:54p Dave
439 * Hud text flash gauge. Reworked dead popup to use 4 buttons in red-alert
442 * 111 7/22/99 4:00p Dave
443 * Fixed beam weapon muzzle glow rendering. Externalized hud shield info.
445 * 110 7/21/99 8:10p Dave
446 * First run of supernova effect.
448 * 109 7/20/99 1:49p Dave
449 * Peter Drake build. Fixed some release build warnings.
451 * 108 7/19/99 2:26p Andsager
452 * set demo multiplayer missions
454 * 107 7/18/99 5:19p Dave
455 * Jump node icon. Fixed debris fogging. Framerate warning stuff.
457 * 106 7/16/99 1:50p Dave
458 * 8 bit aabitmaps. yay.
460 * 105 7/15/99 3:07p Dave
461 * 32 bit detection support. Mouse coord commandline.
463 * 104 7/15/99 2:13p Dave
464 * Added 32 bit detection.
466 * 103 7/15/99 9:20a Andsager
467 * FS2_DEMO initial checkin
469 * 102 7/14/99 11:02a Dave
470 * Skill level default back to easy. Blech.
472 * 101 7/09/99 5:54p Dave
473 * Seperated cruiser types into individual types. Added tons of new
474 * briefing icons. Campaign screen.
476 * 100 7/08/99 4:43p Andsager
477 * New check for sparky_hi and print if not found.
479 * 99 7/08/99 10:53a Dave
480 * New multiplayer interpolation scheme. Not 100% done yet, but still
481 * better than the old way.
483 * 98 7/06/99 4:24p Dave
484 * Mid-level checkin. Starting on some potentially cool multiplayer
487 * 97 7/06/99 3:35p Andsager
488 * Allow movie to play before red alert mission.
490 * 96 7/03/99 5:50p Dave
491 * Make rotated bitmaps draw properly in padlock views.
493 * 95 7/02/99 9:55p Dave
494 * Player engine wash sound.
496 * 94 7/02/99 4:30p Dave
497 * Much more sophisticated lightning support.
499 * 93 6/29/99 7:52p Dave
500 * Put in exception handling in FS2.
502 * 92 6/22/99 9:37p Dave
503 * Put in pof spewing.
505 * 91 6/16/99 4:06p Dave
506 * New pilot info popup. Added new draw-bitmap-as-poly function.
508 * 90 6/15/99 1:56p Andsager
509 * For release builds, allow start up in high res only with
512 * 89 6/15/99 9:34a Dave
513 * Fixed key checking in single threaded version of the stamp notification
516 * 88 6/09/99 2:55p Andsager
517 * Allow multiple asteroid subtypes (of large, medium, small) and follow
520 * 87 6/08/99 1:14a Dave
521 * Multi colored hud test.
523 * 86 6/04/99 9:52a Dave
524 * Fixed some rendering problems.
526 * 85 6/03/99 10:15p Dave
527 * Put in temporary main hall screen.
529 * 84 6/02/99 6:18p Dave
530 * Fixed TNT lockup problems! Wheeeee!
532 * 83 6/01/99 3:52p Dave
533 * View footage screen. Fixed xstrings to not display the & symbol. Popup,
534 * dead popup, pxo find player popup, pxo private room popup.
536 * 82 5/26/99 1:28p Jasenw
537 * changed coords for loading ani
539 * 81 5/26/99 11:46a Dave
540 * Added ship-blasting lighting and made the randomization of lighting
541 * much more customizable.
543 * 80 5/24/99 5:45p Dave
544 * Added detail levels to the nebula, with a decent speedup. Split nebula
545 * lightning into its own section.
563 #include "systemvars.h"
568 #include "starfield.h"
569 #include "lighting.h"
574 #include "fireballs.h"
578 #include "floating.h"
579 #include "gamesequence.h"
581 #include "optionsmenu.h"
582 #include "playermenu.h"
583 #include "trainingmenu.h"
584 #include "techmenu.h"
587 #include "hudmessage.h"
589 #include "missiongoals.h"
590 #include "missionparse.h"
595 #include "multiutil.h"
596 #include "multimsgs.h"
600 #include "freespace.h"
601 #include "managepilot.h"
603 #include "contexthelp.h"
606 #include "missionbrief.h"
607 #include "missiondebrief.h"
609 #include "missionshipchoice.h"
611 #include "hudconfig.h"
612 #include "controlsconfig.h"
613 #include "missionmessage.h"
614 #include "missiontraining.h"
616 #include "hudtarget.h"
618 #include "eventmusic.h"
619 #include "animplay.h"
620 #include "missionweaponchoice.h"
621 #include "missionlog.h"
622 #include "audiostr.h"
624 #include "missioncampaign.h"
626 #include "missionhotkey.h"
627 #include "objectsnd.h"
628 #include "cmeasure.h"
630 #include "linklist.h"
631 #include "shockwave.h"
632 #include "afterburner.h"
637 #include "stand_gui.h"
638 #include "pcxutils.h"
639 #include "hudtargetbox.h"
640 #include "multi_xfer.h"
641 #include "hudescort.h"
642 #include "multiutil.h"
645 #include "multiteamselect.h"
648 #include "readyroom.h"
649 #include "mainhallmenu.h"
650 #include "multilag.h"
652 #include "particle.h"
654 #include "multi_ingame.h"
655 #include "snazzyui.h"
656 #include "asteroid.h"
657 #include "popupdead.h"
658 #include "multi_voice.h"
659 #include "missioncmdbrief.h"
660 #include "redalert.h"
661 #include "gameplayhelp.h"
662 #include "multilag.h"
663 #include "staticrand.h"
664 #include "multi_pmsg.h"
665 #include "levelpaging.h"
666 #include "observer.h"
667 #include "multi_pause.h"
668 #include "multi_endgame.h"
669 #include "cutscenes.h"
670 #include "multi_respawn.h"
672 #include "multi_obj.h"
673 #include "multi_log.h"
675 #include "localize.h"
676 #include "osregistry.h"
677 #include "barracks.h"
678 #include "missionpause.h"
680 #include "alphacolors.h"
681 #include "objcollide.h"
684 #include "neblightning.h"
685 #include "shipcontrails.h"
688 #include "multi_dogfight.h"
689 #include "multi_rate.h"
690 #include "muzzleflash.h"
694 #include "mainhalltemp.h"
695 #include "exceptionhandler.h"
699 #include "supernova.h"
700 #include "hudshield.h"
701 // #include "names.h"
703 #include "missionloopbrief.h"
707 #error macro FRED is defined when trying to build release Fred. Please undefine FRED macro in build settings
713 // 1.00.04 5/26/98 MWA -- going final (12 pm)
714 // 1.00.03 5/26/98 MWA -- going final (3 am)
715 // 1.00.02 5/25/98 MWA -- going final
716 // 1.00.01 5/25/98 MWA -- going final
717 // 0.90 5/21/98 MWA -- getting ready for final.
718 // 0.10 4/9/98. Set by MK.
720 // Demo version: (obsolete since DEMO codebase split from tree)
721 // 0.03 4/10/98 AL. Interplay rev
722 // 0.02 4/8/98 MK. Increased when this system was modified.
723 // 0.01 4/7/98? AL. First release to Interplay QA.
726 // 1.00 5/28/98 AL. First release to Interplay QA.
728 void game_level_init(int seed = -1);
729 void game_post_level_init();
730 void game_do_frame();
731 void game_update_missiontime(); // called from game_do_frame() and navmap_do_frame()
732 void game_reset_time();
733 void game_show_framerate(); // draws framerate in lower right corner
735 int Game_no_clear = 0;
737 int Pofview_running = 0;
738 int Nebedit_running = 0;
740 typedef struct big_expl_flash {
741 float max_flash_intensity; // max intensity
742 float cur_flash_intensity; // cur intensity
743 int flash_start; // start time
746 #define FRAME_FILTER 16
748 #define DEFAULT_SKILL_LEVEL 1
749 int Game_skill_level = DEFAULT_SKILL_LEVEL;
751 #define VIEWER_ZOOM_DEFAULT 0.75f // Default viewer zoom, 0.625 as per multi-lateral agreement on 3/24/97
752 float Viewer_zoom = VIEWER_ZOOM_DEFAULT;
755 #define EXE_FNAME ("fs2.exe")
756 #define LAUNCHER_FNAME ("freespace2.exe")
758 #define EXE_FNAME ("Freespace2demo.app")
759 #define LAUNCHER_FNAME ("Freespace2demo.app")
760 char app_path[] = "Freespace2demo.app/Contents/MacOS/Freespace2demo";
762 #define EXE_FNAME ("Freespace1demo.app")
763 #define LAUNCHER_FNAME ("Freespace1demo.app")
764 char app_path[] = "Freespace1demo.app/Contents/MacOS/Freespace1demo";
766 #define EXE_FNAME ("Freespace1.app")
767 #define LAUNCHER_FNAME ("Freespace1.app")
768 char app_path[] ="Freespace1.app/Contents/MacOS/Freespace1";
770 #define EXE_FNAME ("Freespace2.app")
771 #define LAUNCHER_FNAME ("Freespace2.app")
772 char app_path[] ="Freespace2.app/Contents/MacOS/Freespace2";
776 extern char full_path[1024];
779 // JAS: Code for warphole camera.
780 // Needs to be cleaned up.
781 vector Camera_pos = { 0.0f, 0.0f, 0.0f };
782 vector Camera_velocity = { 0.0f, 0.0f, 0.0f };
783 vector Camera_desired_velocity = { 0.0f, 0.0f, 0.0f };
784 matrix Camera_orient = IDENTITY_MATRIX;
785 float Camera_damping = 1.0f;
786 float Camera_time = 0.0f;
787 float Warpout_time = 0.0f;
788 int Warpout_forced = 0; // Set if this is a forced warpout that cannot be cancelled.
789 int Warpout_sound = -1;
791 int Use_joy_mouse = 0;
792 int Use_palette_flash = 1;
794 int Use_fullscreen_at_startup = 0;
796 int Show_area_effect = 0;
797 object *Last_view_target = NULL;
799 int dogfight_blown = 0;
802 float frametimes[FRAME_FILTER];
803 float frametotal = 0.0f;
807 int Show_framerate = 0;
809 int Show_framerate = 1;
812 int Framerate_cap = 120;
815 int Show_target_debug_info = 0;
816 int Show_target_weapons = 0;
820 static int Show_player_pos = 0; // debug console command to show player world pos on HUD
823 int Debug_octant = -1;
825 fix Game_time_compression = F1_0;
827 // if the ships.tbl the player has is valid
828 int Game_ships_tbl_valid = 0;
830 // if the weapons.tbl the player has is valid
831 int Game_weapons_tbl_valid = 0;
835 extern int Player_attacking_enabled;
839 int Pre_player_entry;
841 int Fred_running = 0;
842 char Game_current_mission_filename[MAX_FILENAME_LEN];
843 int game_single_step = 0;
844 int last_single_step=0;
846 extern int MSG_WINDOW_X_START; // used to position mission_time and shields output
847 extern int MSG_WINDOW_Y_START;
848 extern int MSG_WINDOW_HEIGHT;
850 int game_zbuffer = 1;
851 //static int Game_music_paused;
852 static int Game_paused;
856 #define EXPIRE_BAD_CHECKSUM 1
857 #define EXPIRE_BAD_TIME 2
859 extern void ssm_init();
860 extern void ssm_level_init();
861 extern void ssm_process();
863 // static variable to contain the time this version was built
864 // commented out for now until
865 // I figure out how to get the username into the file
866 //LOCAL char freespace_build_time[] = "Compiled on:"__DATE__" "__TIME__" by "__USER__;
868 // defines and variables used for dumping frame for making trailers.
870 int Debug_dump_frames = 0; // Set to 0 to not dump frames, else equal hz to dump. (15 or 30 probably)
871 int Debug_dump_trigger = 0;
872 int Debug_dump_frame_count;
873 int Debug_dump_frame_num = 0;
874 #define DUMP_BUFFER_NUM_FRAMES 1 // store every 15 frames
877 // amount of time to wait after the player has died before we display the death died popup
878 #define PLAYER_DIED_POPUP_WAIT 2500
879 int Player_died_popup_wait = -1;
880 int Player_multi_died_check = -1;
882 // builtin mission list stuff
884 int Game_builtin_mission_count = 6;
885 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
886 { "SPDemo-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
887 { "SPDemo-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
888 { "DemoTrain.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
889 { "Demo.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE), "" },
890 { "MPDemo-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
891 { "Demo-DOG-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
893 #elif defined(FS1_DEMO)
894 int Game_builtin_mission_count = 5;
895 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
896 { "btmdemo.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
897 { "demo.fsc", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE), "" },
898 { "demo01.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
899 { "demo02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
900 { "demo02b.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
902 #elif defined(PD_BUILD)
903 int Game_builtin_mission_count = 4;
904 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
905 { "sm1-01.fs2", (FSB_FROM_VOLITION), "" },
906 { "sm1-05.fs2", (FSB_FROM_VOLITION), "" },
907 { "sm1-01", (FSB_FROM_VOLITION), "" },
908 { "sm1-05", (FSB_FROM_VOLITION), "" },
910 #elif defined(MULTIPLAYER_BETA)
911 int Game_builtin_mission_count = 17;
912 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
914 { "md-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
915 { "md-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
916 { "md-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
917 { "md-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
918 { "md-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
919 { "md-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
920 { "md-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
921 { "mt-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
922 { "mt-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
923 { "m-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
924 { "m-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
925 { "m-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
926 { "templar-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
927 { "templar-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
928 { "templar-03a.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
929 { "templar-04a.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
930 { "templar.fc2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
932 #elif defined(OEM_BUILD)
933 int Game_builtin_mission_count = 17;
934 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
935 // oem version - act 1 only
936 { "freespace2oem.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE), "" },
939 { "sm1-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
940 { "sm1-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
941 { "sm1-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
942 { "sm1-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
943 { "sm1-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
944 { "sm1-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
945 { "sm1-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
946 { "sm1-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
947 { "sm1-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
948 { "sm1-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
949 { "training-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
950 { "training-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
951 { "training-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
952 { "tsm-104.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
953 { "tsm-105.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 },
954 { "tsm-106.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_1 }
956 #elif defined(MAKE_FS1)
957 int Game_builtin_mission_count = 125;
958 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
959 // single player campaign
960 { "freespace.fsc", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE), "" },
963 { "sm1-01.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
964 { "sm1-02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
965 { "sm1-03a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
966 { "sm1-04a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
967 { "sm1-05a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
968 { "sm1-06a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
969 { "sm1-07a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
970 { "sm1-08a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
971 { "sm1-09a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
972 { "sm1-10a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
975 { "sm2-01a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
976 { "sm2-02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
977 { "sm2-03a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
978 { "sm2-04a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
979 { "sm2-05a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
980 { "sm2-06a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
981 { "sm2-07a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
982 { "sm2-08a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
983 { "sm2-09a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
984 { "sm2-10a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
987 { "sm3-01a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
988 { "sm3-02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
989 { "sm3-03a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
990 { "sm3-04a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
991 { "sm3-05a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
992 { "sm3-06a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
993 { "sm3-07a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
994 { "sm3-08a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
995 { "sm3-09a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
998 { "t-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
999 { "v-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1000 { "s-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1003 { "btm-01.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
1004 { "btm-02.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
1005 { "btm-03.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
1006 { "btm-04.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
1007 { "btm-05.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN), "" },
1010 { "m-hope.fsc", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1011 { "m-altair.fsc", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1013 { "m-v-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1014 { "m-va.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1015 { "m-unstoppable.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1016 { "m-t-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1017 { "m-s-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1018 { "m-rescue.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1019 { "m-pain.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1020 { "m-orecovery.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1021 { "mm3-01a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1022 { "mm3-02a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1023 { "mm3-03a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1024 { "mm3-04a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1025 { "mm3-05a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1026 { "mm3-06a.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1027 { "m-guardduty.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1028 { "m-gate.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1029 { "m-duel.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1030 { "m-convoyassault.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1031 { "m-clash.fsm", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1033 // SilentThreat missions
1034 // Main SilentThreat campaign
1035 { "SilentThreat.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN_FILE), "" },
1037 { "md-01.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1038 { "md-02.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1039 { "md-03.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1040 { "md-04.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1041 { "md-05.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1042 { "md-06.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1043 { "md-07.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1044 { "md-08.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1045 { "md-09.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1046 { "md-10.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1047 { "md-11.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1048 { "md-12.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN), "" },
1050 // SilentThreat Part 1 - multi-coop
1051 { "ST-Part1.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1053 { "stmm-01.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1054 { "stmm-02.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1055 { "stmm-03.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1057 // SilentThreat Part 2 - multi-coop
1058 { "ST-Part2.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1060 { "stmm-04.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1061 { "stmm-05.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1062 { "stmm-06.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1064 // SilentThreat Part 3 - multi-coop
1065 { "ST-Part3.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1067 { "stmm-07.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1068 { "stmm-08.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1069 { "stmm-09.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1071 // SilentThreat Part 4 - multi-coop
1072 { "ST-Part4.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1074 { "stmm-10.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1075 { "stmm-11.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1076 { "stmm-12.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN), "" },
1078 // multiplayer missions
1079 { "mdmm-01.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI), "" },
1080 { "mdmm-02.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI), "" },
1081 { "mdmm-03.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI), "" },
1082 { "mdmm-04.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI), "" },
1083 // user supplied missions
1084 { "mdu-02.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1085 { "mdu-03.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1086 { "mdu-04.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1087 { "mdu-05.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1088 { "mdu-06.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1089 { "mdu-07.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1090 { "mdu-08.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1091 { "mdu-09.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1092 { "mdu-10.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1093 { "mdu-11.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1094 { "mdu-12.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1095 { "mdu-13.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1096 { "mdu-14.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1097 { "mdu-15.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1098 { "mdu-16.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1099 { "mdu-17.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1100 { "mdu-18.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1101 { "mdu-19.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1102 { "mdu-20.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1103 { "mdu-21.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1104 { "mdu-22.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1105 { "mdu-23.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1106 { "mdu-24.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1107 { "mdu-25.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1108 { "mdu-26.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1109 { "mdu-27.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1110 { "mdu-28.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1111 { "mdu-29.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1112 { "mdu-30.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1113 { "mdu-31.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1114 { "mdumm-01.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1115 { "mdumm-02.fsm", (FSB_FROM_MDISK | FSB_MULTI), "" },
1118 int Game_builtin_mission_count = 92;
1119 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
1120 // single player campaign
1121 { "freespace2.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE), "" },
1124 { "sm1-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1125 { "sm1-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1126 { "sm1-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1127 { "sm1-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1128 { "sm1-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1129 { "sm1-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1130 { "sm1-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1131 { "sm1-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1132 { "sm1-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1133 { "sm1-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1134 { "loop1-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1135 { "loop1-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1136 { "loop1-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1137 { "training-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1138 { "training-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1139 { "training-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1140 { "tsm-104.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1141 { "tsm-105.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1142 { "tsm-106.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_2 },
1145 { "sm2-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1146 { "sm2-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1147 { "sm2-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1148 { "sm2-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1149 { "sm2-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1150 { "sm2-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1151 { "sm2-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1152 { "sm2-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1153 { "sm2-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1154 { "sm2-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1157 { "sm3-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1158 { "sm3-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1159 { "sm3-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1160 { "sm3-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1161 { "sm3-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1162 { "sm3-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1163 { "sm3-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1164 { "sm3-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1165 { "sm3-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1166 { "sm3-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1167 { "loop2-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1168 { "loop2-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN), FS_CDROM_VOLUME_3 },
1170 // multiplayer missions
1173 { "g-shi.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1174 { "g-ter.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1175 { "g-vas.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1178 { "m-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1179 { "m-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1180 { "m-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1181 { "m-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1184 { "mdh-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1185 { "mdh-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1186 { "mdh-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1187 { "mdh-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1188 { "mdh-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1189 { "mdh-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1190 { "mdh-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1191 { "mdh-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1192 { "mdh-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1193 { "mdl-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1194 { "mdl-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1195 { "mdl-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1196 { "mdl-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1197 { "mdl-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1198 { "mdl-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1199 { "mdl-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1200 { "mdl-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1201 { "mdl-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1202 { "mdm-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1203 { "mdm-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1204 { "mdm-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1205 { "mdm-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1206 { "mdm-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1207 { "mdm-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1208 { "mdm-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1209 { "mdm-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1210 { "mdm-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1211 { "osdog.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1214 { "mt-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1215 { "mt-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1216 { "mt-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1217 { "mt-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1218 { "mt-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1219 { "mt-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1220 { "mt-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1221 { "mt-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1222 { "mt-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1223 { "mt-10.fs2", (FSB_FROM_VOLITION | FSB_MULTI), "" },
1226 { "templar.fc2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE), "" },
1227 { "templar-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
1228 { "templar-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
1229 { "templar-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
1230 { "templar-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN), "" },
1235 // Internal function prototypes
1236 void game_maybe_draw_mouse(float frametime);
1237 void init_animating_pointer();
1238 void load_animating_pointer(char *filename, int dx, int dy);
1239 void unload_animating_pointer();
1240 void game_do_training_checks();
1241 void game_shutdown(void);
1242 void game_show_event_debug(float frametime);
1243 void game_event_debug_init();
1245 void demo_upsell_show_screens();
1246 void game_start_subspace_ambient_sound();
1247 void game_stop_subspace_ambient_sound();
1248 void verify_ships_tbl();
1249 void verify_weapons_tbl();
1250 void display_title_screen();
1252 // loading background filenames
1253 static char *Game_loading_bground_fname[GR_NUM_RESOLUTIONS] = {
1254 "LoadingBG", // GR_640
1255 "2_LoadingBG" // GR_1024
1259 static char *Game_loading_ani_fname[GR_NUM_RESOLUTIONS] = {
1260 "Loading.ani", // GR_640
1261 "2_Loading.ani" // GR_1024
1264 #if defined(FS2_DEMO) || defined(FS1_DEMO)
1265 static char *Game_demo_title_screen_fname[GR_NUM_RESOLUTIONS] = {
1273 #elif defined(OEM_BUILD)
1274 static char *Game_demo_title_screen_fname[GR_NUM_RESOLUTIONS] = {
1284 char Game_CDROM_dir[MAX_PATH_LEN];
1287 // How much RAM is on this machine. Set in WinMain
1288 uint Freespace_total_ram = 0;
1291 float Game_flash_red = 0.0f;
1292 float Game_flash_green = 0.0f;
1293 float Game_flash_blue = 0.0f;
1294 float Sun_spot = 0.0f;
1295 big_expl_flash Big_expl_flash = {0.0f, 0.0f, 0};
1297 // game shudder stuff (in ms)
1298 int Game_shudder_time = -1;
1299 int Game_shudder_total = 0;
1300 float Game_shudder_intensity = 0.0f; // should be between 0.0 and 100.0
1303 sound_env Game_sound_env;
1304 //sound_env Game_default_sound_env = {SND_ENV_AUDITORIUM, 0.25f, 0.35f, 3.0f};
1305 sound_env Game_default_sound_env = {SND_ENV_GENERIC, 0.2F,0.2F,1.0F};
1307 int Game_sound_env_update_timestamp;
1309 // WARPIN CRAP BEGIN --------------------------------------------------------------------------------------------
1312 // WARPIN CRAP END --------------------------------------------------------------------------------------------
1314 fs_builtin_mission *game_find_builtin_mission(char *filename)
1318 // look through all existing builtin missions
1319 for(idx=0; idx<Game_builtin_mission_count; idx++){
1320 if(!stricmp(Game_builtin_mission_list[idx].filename, filename)){
1321 return &Game_builtin_mission_list[idx];
1329 int game_get_default_skill_level()
1331 return DEFAULT_SKILL_LEVEL;
1335 void game_flash_reset()
1337 Game_flash_red = 0.0f;
1338 Game_flash_green = 0.0f;
1339 Game_flash_blue = 0.0f;
1341 Big_expl_flash.max_flash_intensity = 0.0f;
1342 Big_expl_flash.cur_flash_intensity = 0.0f;
1343 Big_expl_flash.flash_start = 0;
1346 float Gf_critical = -1.0f; // framerate we should be above on the average for this mission
1347 float Gf_critical_time = 0.0f; // how much time we've been at the critical framerate
1349 void game_framerate_check_init()
1351 // zero critical time
1352 Gf_critical_time = 0.0f;
1355 if(The_mission.flags & MISSION_FLAG_FULLNEB){
1356 // if this is a glide card
1357 if(gr_screen.mode == GR_GLIDE){
1359 extern GrHwConfiguration hwconfig;
1362 if(hwconfig.SSTs[0].sstBoard.VoodooConfig.fbRam >= 4){
1363 Gf_critical = 15.0f;
1367 Gf_critical = 10.0f;
1372 Gf_critical = 15.0f;
1375 // d3d. only care about good cards here I guess (TNT)
1377 Gf_critical = 15.0f;
1380 // if this is a glide card
1381 if(gr_screen.mode == GR_GLIDE){
1383 extern GrHwConfiguration hwconfig;
1386 if(hwconfig.SSTs[0].sstBoard.VoodooConfig.fbRam >= 4){
1387 Gf_critical = 25.0f;
1391 Gf_critical = 20.0f;
1396 Gf_critical = 25.0f;
1399 // d3d. only care about good cards here I guess (TNT)
1401 Gf_critical = 25.0f;
1406 extern float Framerate;
1407 void game_framerate_check()
1411 // if the current framerate is above the critical level, add frametime
1412 if(Framerate >= Gf_critical){
1413 Gf_critical_time += flFrametime;
1416 if(!Show_framerate){
1420 // display if we're above the critical framerate
1421 if(Framerate < Gf_critical){
1422 gr_set_color_fast(&Color_bright_red);
1423 gr_string(200, y_start, "Framerate warning");
1428 // display our current pct of good frametime
1429 if(f2fl(Missiontime) >= 0.0f){
1430 float pct = (Gf_critical_time / f2fl(Missiontime)) * 100.0f;
1433 gr_set_color_fast(&Color_bright_green);
1435 gr_set_color_fast(&Color_bright_red);
1438 gr_printf(200, y_start, "%d%%", (int)pct);
1445 // Adds a flash effect. These can be positive or negative.
1446 // The range will get capped at around -1 to 1, so stick
1447 // with a range like that.
1448 void game_flash( float r, float g, float b )
1450 Game_flash_red += r;
1451 Game_flash_green += g;
1452 Game_flash_blue += b;
1454 if ( Game_flash_red < -1.0f ) {
1455 Game_flash_red = -1.0f;
1456 } else if ( Game_flash_red > 1.0f ) {
1457 Game_flash_red = 1.0f;
1460 if ( Game_flash_green < -1.0f ) {
1461 Game_flash_green = -1.0f;
1462 } else if ( Game_flash_green > 1.0f ) {
1463 Game_flash_green = 1.0f;
1466 if ( Game_flash_blue < -1.0f ) {
1467 Game_flash_blue = -1.0f;
1468 } else if ( Game_flash_blue > 1.0f ) {
1469 Game_flash_blue = 1.0f;
1474 // Adds a flash for Big Ship explosions
1475 // cap range from 0 to 1
1476 void big_explosion_flash(float flash)
1478 Big_expl_flash.flash_start = timestamp(1);
1482 } else if (flash < 0.0f) {
1486 Big_expl_flash.max_flash_intensity = flash;
1487 Big_expl_flash.cur_flash_intensity = 0.0f;
1490 // Amount to diminish palette towards normal, per second.
1491 #define DIMINISH_RATE 0.75f
1492 #define SUN_DIMINISH_RATE 6.00f
1496 float sn_glare_scale = 1.7f;
1499 dc_get_arg(ARG_FLOAT);
1500 sn_glare_scale = Dc_arg_float;
1503 float Supernova_last_glare = 0.0f;
1504 void game_sunspot_process(float frametime)
1508 float Sun_spot_goal = 0.0f;
1511 sn_stage = supernova_active();
1513 // sunspot differently based on supernova stage
1515 // approaching. player still in control
1518 pct = (1.0f - (supernova_time_left() / SUPERNOVA_CUT_TIME));
1521 light_get_global_dir(&light_dir, 0);
1523 dot = vm_vec_dot( &light_dir, &Eye_matrix.v.fvec );
1526 // scale it some more
1527 dot = dot * (0.5f + (pct * 0.5f));
1530 Sun_spot_goal += (dot * sn_glare_scale);
1533 // draw the sun glow
1534 if ( !shipfx_eye_in_shadow( &Eye_position, Viewer_obj, 0 ) ) {
1535 // draw the glow for this sun
1536 stars_draw_sun_glow(0);
1539 Supernova_last_glare = Sun_spot_goal;
1542 // camera cut. player not in control. note : at this point camera starts out facing the sun. so we can go nice and bright
1545 Sun_spot_goal = 0.9f;
1546 Sun_spot_goal += (1.0f - (supernova_time_left() / SUPERNOVA_CUT_TIME)) * 0.1f;
1548 if(Sun_spot_goal > 1.0f){
1549 Sun_spot_goal = 1.0f;
1552 Sun_spot_goal *= sn_glare_scale;
1553 Supernova_last_glare = Sun_spot_goal;
1556 // fade to white. display dead popup
1559 Supernova_last_glare += (2.0f * flFrametime);
1560 if(Supernova_last_glare > 2.0f){
1561 Supernova_last_glare = 2.0f;
1564 Sun_spot_goal = Supernova_last_glare;
1571 // check sunspots for all suns
1572 n_lights = light_get_global_count();
1575 for(idx=0; idx<n_lights; idx++){
1576 //(vector *eye_pos, matrix *eye_orient)
1577 if ( !shipfx_eye_in_shadow( &Eye_position, Viewer_obj, idx ) ) {
1580 light_get_global_dir(&light_dir, idx);
1582 float dot = vm_vec_dot( &light_dir, &Eye_matrix.v.fvec )*0.5f+0.5f;
1584 Sun_spot_goal += (float)pow(dot,85.0f);
1586 // draw the glow for this sun
1587 stars_draw_sun_glow(idx);
1589 Sun_spot_goal = 0.0f;
1595 Sun_spot_goal = 0.0f;
1599 float dec_amount = frametime*SUN_DIMINISH_RATE;
1601 if ( Sun_spot < Sun_spot_goal ) {
1602 Sun_spot += dec_amount;
1603 if ( Sun_spot > Sun_spot_goal ) {
1604 Sun_spot = Sun_spot_goal;
1606 } else if ( Sun_spot > Sun_spot_goal ) {
1607 Sun_spot -= dec_amount;
1608 if ( Sun_spot < Sun_spot_goal ) {
1609 Sun_spot = Sun_spot_goal;
1615 // Call once a frame to diminish the
1616 // flash effect to 0.
1617 void game_flash_diminish(float frametime)
1619 float dec_amount = frametime*DIMINISH_RATE;
1621 if ( Game_flash_red > 0.0f ) {
1622 Game_flash_red -= dec_amount;
1623 if ( Game_flash_red < 0.0f )
1624 Game_flash_red = 0.0f;
1626 Game_flash_red += dec_amount;
1627 if ( Game_flash_red > 0.0f )
1628 Game_flash_red = 0.0f;
1631 if ( Game_flash_green > 0.0f ) {
1632 Game_flash_green -= dec_amount;
1633 if ( Game_flash_green < 0.0f )
1634 Game_flash_green = 0.0f;
1636 Game_flash_green += dec_amount;
1637 if ( Game_flash_green > 0.0f )
1638 Game_flash_green = 0.0f;
1641 if ( Game_flash_blue > 0.0f ) {
1642 Game_flash_blue -= dec_amount;
1643 if ( Game_flash_blue < 0.0f )
1644 Game_flash_blue = 0.0f;
1646 Game_flash_blue += dec_amount;
1647 if ( Game_flash_blue > 0.0f )
1648 Game_flash_blue = 0.0f;
1651 // update big_explosion_cur_flash
1652 #define TIME_UP 1500
1653 #define TIME_DOWN 2500
1654 int duration = TIME_UP + TIME_DOWN;
1655 int time = timestamp_until(Big_expl_flash.flash_start);
1656 if (time > -duration) {
1658 if (time < TIME_UP) {
1659 Big_expl_flash.cur_flash_intensity = Big_expl_flash.max_flash_intensity * time / (float) TIME_UP;
1662 Big_expl_flash.cur_flash_intensity = Big_expl_flash.max_flash_intensity * ((float) TIME_DOWN - time) / (float) TIME_DOWN;
1666 if ( Use_palette_flash ) {
1668 // static int or=0, og=0, ob=0;
1670 // Change the 200 to change the color range of colors.
1671 r = fl2i( Game_flash_red*128.0f );
1672 g = fl2i( Game_flash_green*128.0f );
1673 b = fl2i( Game_flash_blue*128.0f );
1675 if ( Sun_spot > 0.0f ) {
1676 r += fl2i(Sun_spot*128.0f);
1677 g += fl2i(Sun_spot*128.0f);
1678 b += fl2i(Sun_spot*128.0f);
1681 if ( Big_expl_flash.cur_flash_intensity > 0.0f ) {
1682 r += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1683 g += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1684 b += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1687 if ( r < 0 ) r = 0; else if ( r > 255 ) r = 255;
1688 if ( g < 0 ) g = 0; else if ( g > 255 ) g = 255;
1689 if ( b < 0 ) b = 0; else if ( b > 255 ) b = 255;
1691 if ( (r!=0) || (g!=0) || (b!=0) ) {
1692 gr_flash( r, g, b );
1694 //mprintf(( "Flash! %d,%d,%d\n", r, g, b ));
1705 void game_level_close()
1707 // De-Initialize the game subsystems
1708 event_music_level_close();
1709 game_stop_looped_sounds();
1711 obj_snd_level_close(); // uninit object-linked persistant sounds
1712 gamesnd_unload_gameplay_sounds(); // unload gameplay sounds from memory
1713 anim_level_close(); // stop and clean up any anim instances
1714 message_mission_shutdown(); // called after anim_level_close() to make sure anim instances are free
1715 shockwave_level_close();
1716 fireball_level_close();
1718 mission_event_shutdown();
1719 asteroid_level_close();
1720 model_cache_reset(); // Reset/free all the model caching stuff
1721 flak_level_close(); // unload flak stuff
1722 neb2_level_close(); // shutdown gaseous nebula stuff
1725 mflash_level_close();
1726 mission_brief_common_reset(); // close out parsed briefing/mission stuff
1728 audiostream_unpause_all();
1733 // intializes game stuff and loads the mission. Returns 0 on failure, 1 on success
1734 // input: seed => DEFAULT PARAMETER (value -1). Only set by demo playback code.
1735 void game_level_init(int seed)
1737 // seed the random number generator
1739 // if no seed was passed, seed the generator either from the time value, or from the
1740 // netgame security flags -- ensures that all players in multiplayer game will have the
1741 // same randon number sequence (with static rand functions)
1742 if ( Game_mode & GM_NORMAL ) {
1743 Game_level_seed = time(NULL);
1745 Game_level_seed = Netgame.security;
1748 // mwa 9/17/98 -- maybe this assert isn't needed????
1749 Assert( !(Game_mode & GM_MULTIPLAYER) );
1750 Game_level_seed = seed;
1752 srand( Game_level_seed );
1754 // semirand function needs to get re-initted every time in multiplayer
1755 if ( Game_mode & GM_MULTIPLAYER ){
1761 Key_normal_game = (Game_mode & GM_NORMAL);
1764 Game_shudder_time = -1;
1766 // Initialize the game subsystems
1767 // timestamp_reset(); // Must be inited before everything else
1769 game_reset_time(); // resets time, and resets saved time too
1771 obj_init(); // Must be inited before the other systems
1772 model_free_all(); // Free all existing models
1773 mission_brief_common_init(); // Free all existing briefing/debriefing text
1774 weapon_level_init();
1775 ai_level_init(); // Call this before ship_init() because it reads ai.tbl.
1777 player_level_init();
1778 shipfx_flash_init(); // Init the ship gun flash system.
1779 game_flash_reset(); // Reset the flash effect
1780 particle_init(); // Reset the particle system
1784 shield_hit_init(); // Initialize system for showing shield hits
1785 radar_mission_init();
1786 mission_init_goals();
1789 obj_snd_level_init(); // init object-linked persistant sounds
1791 shockwave_level_init();
1792 afterburner_level_init();
1793 scoring_level_init( &Player->stats );
1795 asteroid_level_init();
1796 control_config_clear_used_status();
1797 collide_ship_ship_sounds_init();
1799 Pre_player_entry = 1; // Means the player has not yet entered.
1800 Entry_delay_time = 0; // Could get overwritten in mission read.
1801 fireball_preload(); // page in warphole bitmaps
1803 flak_level_init(); // initialize flak - bitmaps, etc
1804 ct_level_init(); // initialize ships contrails, etc
1805 awacs_level_init(); // initialize AWACS
1806 beam_level_init(); // initialize beam weapons
1807 mflash_level_init();
1809 supernova_level_init();
1811 // multiplayer dogfight hack
1814 shipfx_engine_wash_level_init();
1818 Last_view_target = NULL;
1823 // campaign wasn't ended
1824 Campaign_ended_in_mission = 0;
1827 // called when a mission is over -- does server specific stuff.
1828 void freespace_stop_mission()
1831 Game_mode &= ~GM_IN_MISSION;
1834 // called at frame interval to process networking stuff
1835 void game_do_networking()
1837 Assert( Net_player != NULL );
1838 if (!(Game_mode & GM_MULTIPLAYER)){
1842 // see if this player should be reading/writing data. Bit is set when at join
1843 // screen onward until quits back to main menu.
1844 if ( !(Net_player->flags & NETINFO_FLAG_DO_NETWORKING) ){
1848 if(gameseq_get_state()!=GS_STATE_MULTI_PAUSED){
1851 multi_pause_do_frame();
1856 // Loads the best palette for this level, based
1857 // on nebula color and hud color. You could just call palette_load_table with
1858 // the appropriate filename, but who wants to do that.
1859 void game_load_palette()
1861 char palette_filename[1024];
1863 // We only use 3 hud colors right now
1865 Assert( HUD_config.main_color >= 0 );
1866 Assert( HUD_config.main_color <= 2 );
1869 Assert( Mission_palette >= 0 );
1870 Assert( Mission_palette <= 98 );
1873 if ( The_mission.flags & MISSION_FLAG_SUBSPACE ) {
1874 strcpy( palette_filename, NOX("gamepalette-subspace") );
1876 sprintf( palette_filename, NOX("gamepalette%d-%02d"), HUD_config.main_color+1, Mission_palette+1 );
1879 mprintf(( "Loading palette %s\n", palette_filename ));
1881 palette_load_table(palette_filename);
1883 strcpy( palette_filename, NOX("gamepalette-subspace") );
1885 mprintf(( "Loading palette %s\n", palette_filename ));
1889 void game_post_level_init()
1891 // Stuff which gets called after mission is loaded. Because player isn't created until
1892 // after mission loads, some things must get initted after the level loads
1894 model_level_post_init();
1897 hud_setup_escort_list();
1898 mission_hotkey_set_defaults(); // set up the default hotkeys (from mission file)
1904 game_event_debug_init();
1907 training_mission_init();
1908 asteroid_create_all();
1910 game_framerate_check_init();
1914 // An estimate as to how high the count passed to game_loading_callback will go.
1915 // This is just a guess, it seems to always be about the same. The count is
1916 // proportional to the code being executed, not the time, so this works good
1917 // for a bar, assuming the code does about the same thing each time you
1918 // load a level. You can find this value by looking at the return value
1919 // of game_busy_callback(NULL), which I conveniently print out to the
1920 // debug output window with the '=== ENDING LOAD ==' stuff.
1921 //#define COUNT_ESTIMATE 3706
1922 #define COUNT_ESTIMATE 1111
1924 int Game_loading_callback_inited = 0;
1926 int Game_loading_background = -1;
1927 anim * Game_loading_ani = NULL;
1928 anim_instance *Game_loading_ani_instance;
1929 int Game_loading_frame=-1;
1931 static int Game_loading_ani_coords[GR_NUM_RESOLUTIONS][2] = {
1933 #if defined(FS1_DEMO)
1935 #elif defined(MAKE_FS1)
1946 // This gets called 10x per second and count is the number of times
1947 // game_busy() has been called since the current callback function
1949 void game_loading_callback(int count)
1951 game_do_networking();
1953 Assert( Game_loading_callback_inited==1 );
1954 Assert( Game_loading_ani != NULL );
1956 int framenum = ((Game_loading_ani->total_frames*count) / COUNT_ESTIMATE)+1;
1957 if ( framenum > Game_loading_ani->total_frames-1 ) {
1958 framenum = Game_loading_ani->total_frames-1;
1959 } else if ( framenum < 0 ) {
1964 while ( Game_loading_frame < framenum ) {
1965 Game_loading_frame++;
1966 cbitmap = anim_get_next_frame(Game_loading_ani_instance);
1970 if ( cbitmap > -1 ) {
1971 if ( Game_loading_background > -1 ) {
1972 gr_set_bitmap( Game_loading_background, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1976 //mprintf(( "Showing frame %d/%d [ Bitmap=%d ]\n", Game_loading_frame , Game_loading_ani->total_frames, cbitmap ));
1977 gr_set_bitmap( cbitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1978 gr_bitmap(Game_loading_ani_coords[gr_screen.res][0],Game_loading_ani_coords[gr_screen.res][1]);
1980 bm_release(cbitmap);
1986 void game_loading_callback_init()
1988 Assert( Game_loading_callback_inited==0 );
1990 Game_loading_background = bm_load(Game_loading_bground_fname[gr_screen.res]);
1992 common_set_interface_palette("InterfacePalette"); // set the interface palette
1996 Game_loading_ani = anim_load( Game_loading_ani_fname[gr_screen.res]);
1997 Assert( Game_loading_ani != NULL );
1998 Game_loading_ani_instance = init_anim_instance(Game_loading_ani, 16);
1999 Assert( Game_loading_ani_instance != NULL );
2000 Game_loading_frame = -1;
2002 Game_loading_callback_inited = 1;
2004 game_busy_callback( game_loading_callback, (COUNT_ESTIMATE/Game_loading_ani->total_frames)+1 );
2009 void game_loading_callback_close()
2011 Assert( Game_loading_callback_inited==1 );
2013 // Make sure bar shows all the way over.
2014 game_loading_callback(COUNT_ESTIMATE);
2016 int real_count = game_busy_callback( NULL );
2019 Game_loading_callback_inited = 0;
2022 mprintf(( "=================== ENDING LOAD ================\n" ));
2023 mprintf(( "Real count = %d, Estimated count = %d\n", real_count, COUNT_ESTIMATE ));
2024 mprintf(( "================================================\n" ));
2026 // to remove warnings in release build
2030 free_anim_instance(Game_loading_ani_instance);
2031 Game_loading_ani_instance = NULL;
2032 anim_free(Game_loading_ani);
2033 Game_loading_ani = NULL;
2035 bm_release( Game_loading_background );
2036 common_free_interface_palette(); // restore game palette
2037 Game_loading_background = -1;
2039 gr_set_font( FONT1 );
2042 // Update the sound environment (ie change EAX settings based on proximity to large ships)
2044 void game_maybe_update_sound_environment()
2046 // do nothing for now
2049 // Assign the sound environment for the game, based on the current mission
2051 void game_assign_sound_environment()
2054 if (The_mission.flags & MISSION_FLAG_SUBSPACE) {
2055 Game_sound_env.id = SND_ENV_DRUGGED;
2056 Game_sound_env.volume = 0.800f;
2057 Game_sound_env.damping = 1.188f;
2058 Game_sound_env.decay = 6.392f;
2060 } else if (Num_asteroids > 30) {
2061 Game_sound_env.id = SND_ENV_AUDITORIUM;
2062 Game_sound_env.volume = 0.603f;
2063 Game_sound_env.damping = 0.5f;
2064 Game_sound_env.decay = 4.279f;
2067 Game_sound_env = Game_default_sound_env;
2071 Game_sound_env = Game_default_sound_env;
2072 Game_sound_env_update_timestamp = timestamp(1);
2075 // function which gets called before actually entering the mission. It is broken down into a funciton
2076 // since it will get called in one place from a single player game and from another place for
2077 // a multiplayer game
2078 void freespace_mission_load_stuff()
2080 // called if we're not on a freespace dedicated (non rendering, no pilot) server
2081 // IE : we _don't_ want to load any sounds or bitmap/texture info on this machine.
2082 if(!(Game_mode & GM_STANDALONE_SERVER)){
2084 mprintf(( "=================== STARTING LEVEL DATA LOAD ==================\n" ));
2086 game_loading_callback_init();
2088 event_music_level_init(); // preloads the first 2 seconds for each event music track
2091 gamesnd_unload_interface_sounds(); // unload interface sounds from memory
2094 gamesnd_preload_common_sounds(); // load in sounds that are expected to play
2097 ship_assign_sound_all(); // assign engine sounds to ships
2098 game_assign_sound_environment(); // assign the sound environment for this mission
2101 // call function in missionparse.cpp to fixup player/ai stuff.
2102 mission_parse_fixup_players();
2105 // Load in all the bitmaps for this level
2110 game_loading_callback_close();
2112 // the only thing we need to call on the standalone for now.
2114 // call function in missionparse.cpp to fixup player/ai stuff.
2115 mission_parse_fixup_players();
2117 // Load in all the bitmaps for this level
2123 uint load_mission_load;
2124 uint load_post_level_init;
2125 uint load_mission_stuff;
2127 // tells the server to load the mission and initialize structures
2128 int game_start_mission()
2130 mprintf(( "=================== STARTING LEVEL LOAD ==================\n" ));
2132 load_gl_init = time(NULL);
2134 load_gl_init = time(NULL) - load_gl_init;
2136 if (Game_mode & GM_MULTIPLAYER) {
2137 Player->flags |= PLAYER_FLAGS_IS_MULTI;
2139 // clear multiplayer stats
2140 init_multiplayer_stats();
2143 load_mission_load = time(NULL);
2144 if (mission_load()) {
2145 if ( !(Game_mode & GM_MULTIPLAYER) ) {
2146 popup(PF_BODY_BIG, 1, POPUP_OK, XSTR( "Attempt to load the mission failed", 169));
2147 gameseq_post_event(GS_EVENT_MAIN_MENU);
2149 multi_quit_game(PROMPT_NONE, MULTI_END_NOTIFY_NONE, MULTI_END_ERROR_LOAD_FAIL);
2154 load_mission_load = time(NULL) - load_mission_load;
2156 // If this is a red alert mission in campaign mode, bash wingman status
2157 if ( (Game_mode & GM_CAMPAIGN_MODE) && red_alert_mission() ) {
2158 red_alert_bash_wingman_status();
2161 // the standalone server in multiplayer doesn't do any rendering, so we will not even bother loading the palette
2162 if ( !(Game_mode & GM_STANDALONE_SERVER) ) {
2163 mprintf(( "=================== LOADING GAME PALETTE ================\n" ));
2165 game_load_palette();
2169 load_post_level_init = time(NULL);
2170 game_post_level_init();
2171 load_post_level_init = time(NULL) - load_post_level_init;
2175 void Do_model_timings_test();
2176 Do_model_timings_test();
2180 load_mission_stuff = time(NULL);
2181 freespace_mission_load_stuff();
2182 load_mission_stuff = time(NULL) - load_mission_stuff;
2187 int Interface_framerate = 0;
2190 DCF_BOOL( mouse_control, Use_mouse_to_fly )
2191 DCF_BOOL( show_framerate, Show_framerate )
2192 DCF_BOOL( show_target_debug_info, Show_target_debug_info )
2193 DCF_BOOL( show_target_weapons, Show_target_weapons )
2194 DCF_BOOL( lead_target_cheat, Players[Player_num].lead_target_cheat )
2195 DCF_BOOL( sound, Sound_enabled )
2196 DCF_BOOL( zbuffer, game_zbuffer )
2197 DCF_BOOL( shield_system, New_shield_system )
2198 DCF_BOOL( show_shield_mesh, Show_shield_mesh)
2199 DCF_BOOL( player_attacking, Player_attacking_enabled )
2200 DCF_BOOL( show_waypoints, Show_waypoints )
2201 DCF_BOOL( show_area_effect, Show_area_effect )
2202 DCF_BOOL( show_net_stats, Show_net_stats )
2203 DCF_BOOL( log, Log_debug_output_to_file )
2204 DCF_BOOL( training_msg_method, Training_msg_method )
2205 DCF_BOOL( show_player_pos, Show_player_pos )
2206 DCF_BOOL(i_framerate, Interface_framerate )
2208 DCF(show_mem,"Toggles showing mem usage")
2211 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2212 if ( Dc_arg_type & ARG_TRUE ) Show_mem = 1;
2213 else if ( Dc_arg_type & ARG_FALSE ) Show_mem = 0;
2214 else if ( Dc_arg_type & ARG_NONE ) Show_mem ^= 1;
2220 if ( Dc_help ) dc_printf( "Usage: Show_mem\nSets show_mem to true or false. If nothing passed, then toggles it.\n" );
2222 dc_printf( "Show_mem is %s\n", (Show_mem?"TRUE":"FALSE") );
2223 dc_printf( "Show_cpu is %s\n", (Show_cpu?"TRUE":"FALSE") );
2227 DCF(show_cpu,"Toggles showing cpu usage")
2230 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2231 if ( Dc_arg_type & ARG_TRUE ) Show_cpu = 1;
2232 else if ( Dc_arg_type & ARG_FALSE ) Show_cpu = 0;
2233 else if ( Dc_arg_type & ARG_NONE ) Show_cpu ^= 1;
2239 if ( Dc_help ) dc_printf( "Usage: Show_cpu\nSets show_cpu to true or false. If nothing passed, then toggles it.\n" );
2241 dc_printf( "Show_mem is %s\n", (Show_mem?"TRUE":"FALSE") );
2242 dc_printf( "Show_cpu is %s\n", (Show_cpu?"TRUE":"FALSE") );
2249 // AL 4-8-98: always allow players to display their framerate
2252 DCF_BOOL( show_framerate, Show_framerate )
2259 DCF(use_joy_mouse,"Makes joystick move mouse cursor")
2262 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2263 if ( Dc_arg_type & ARG_TRUE ) Use_joy_mouse = 1;
2264 else if ( Dc_arg_type & ARG_FALSE ) Use_joy_mouse = 0;
2265 else if ( Dc_arg_type & ARG_NONE ) Use_joy_mouse ^= 1;
2267 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" );
2268 if ( Dc_status ) dc_printf( "use_joy_mouse is %s\n", (Use_joy_mouse?"TRUE":"FALSE") );
2270 os_config_write_uint( NULL, NOX("JoystickMovesCursor"), Use_joy_mouse );
2273 DCF(palette_flash,"Toggles palette flash effect on/off")
2276 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2277 if ( Dc_arg_type & ARG_TRUE ) Use_palette_flash = 1;
2278 else if ( Dc_arg_type & ARG_FALSE ) Use_palette_flash = 0;
2279 else if ( Dc_arg_type & ARG_NONE ) Use_palette_flash ^= 1;
2281 if ( Dc_help ) dc_printf( "Usage: palette_flash [bool]\nSets palette_flash to true or false. If nothing passed, then toggles it.\n" );
2282 if ( Dc_status ) dc_printf( "palette_flash is %s\n", (Use_palette_flash?"TRUE":"FALSE") );
2285 int Use_low_mem = 0;
2287 DCF(low_mem,"Uses low memory settings regardless of RAM")
2290 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2291 if ( Dc_arg_type & ARG_TRUE ) Use_low_mem = 1;
2292 else if ( Dc_arg_type & ARG_FALSE ) Use_low_mem = 0;
2293 else if ( Dc_arg_type & ARG_NONE ) Use_low_mem ^= 1;
2295 if ( Dc_help ) dc_printf( "Usage: low_mem [bool]\nSets low_mem to true or false. If nothing passed, then toggles it.\n" );
2296 if ( Dc_status ) dc_printf( "low_mem is %s\n", (Use_low_mem?"TRUE":"FALSE") );
2298 os_config_write_uint( NULL, NOX("LowMem"), Use_low_mem );
2304 DCF(force_fullscreen, "Forces game to startup in fullscreen mode")
2307 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2308 if ( Dc_arg_type & ARG_TRUE ) Use_fullscreen_at_startup = 1;
2309 else if ( Dc_arg_type & ARG_FALSE ) Use_fullscreen_at_startup = 0;
2310 else if ( Dc_arg_type & ARG_NONE ) Use_fullscreen_at_startup ^= 1;
2312 if ( Dc_help ) dc_printf( "Usage: force_fullscreen [bool]\nSets force_fullscreen to true or false. If nothing passed, then toggles it.\n" );
2313 if ( Dc_status ) dc_printf( "force_fullscreen is %s\n", (Use_fullscreen_at_startup?"TRUE":"FALSE") );
2314 os_config_write_uint( NULL, NOX("ForceFullscreen"), Use_fullscreen_at_startup );
2318 int Framerate_delay = 0;
2320 float Freespace_gamma = 1.0f;
2322 DCF(gamma,"Sets Gamma factor")
2325 dc_get_arg(ARG_FLOAT|ARG_NONE);
2326 if ( Dc_arg_type & ARG_FLOAT ) {
2327 Freespace_gamma = Dc_arg_float;
2329 dc_printf( "Gamma reset to 1.0f\n" );
2330 Freespace_gamma = 1.0f;
2332 if ( Freespace_gamma < 0.1f ) {
2333 Freespace_gamma = 0.1f;
2334 } else if ( Freespace_gamma > 5.0f ) {
2335 Freespace_gamma = 5.0f;
2337 gr_set_gamma(Freespace_gamma);
2339 char tmp_gamma_string[32];
2340 sprintf( tmp_gamma_string, NOX("%.2f"), Freespace_gamma );
2341 os_config_write_string( NULL, NOX("Gamma"), tmp_gamma_string );
2345 dc_printf( "Usage: gamma <float>\n" );
2346 dc_printf( "Sets gamma in range 1-3, no argument resets to default 1.2\n" );
2347 Dc_status = 0; // don't print status if help is printed. Too messy.
2351 dc_printf( "Gamma = %.2f\n", Freespace_gamma );
2360 Game_current_mission_filename[0] = 0;
2362 // seed the random number generator
2363 Game_init_seed = time(NULL);
2364 srand( Game_init_seed );
2366 Framerate_delay = 0;
2372 extern void bm_init();
2378 // Initialize the timer before the os
2386 GetCurrentDirectory(1024, whee);
2389 full_path[strlen(full_path) - strlen(app_path)] = '\0';
2390 strcpy( whee, full_path);
2392 getcwd (whee, 1024);
2395 strcat(whee, EXE_FNAME);
2397 //Initialize the libraries
2398 s1 = timer_get_milliseconds();
2399 if(cfile_init(whee, Game_CDROM_dir)){ // initialize before calling any cfopen stuff!!!
2402 e1 = timer_get_milliseconds();
2404 // time a bunch of cfopens
2406 s2 = timer_get_milliseconds();
2408 for(int idx=0; idx<10000; idx++){
2409 whee = cfopen("capital01.pof", "rb", CFILE_NORMAL, CF_TYPE_MODELS);
2414 //cf_exist("capital01.pof", CF_TYPE_MODELS);
2416 e2 = timer_get_milliseconds();
2419 if (Is_standalone) {
2420 std_init_standalone();
2422 os_init( Osreg_class_name, Osreg_app_name );
2423 os_set_title(Osreg_title);
2426 // initialize localization module. Make sure this is down AFTER initialzing OS.
2427 // int t1 = timer_get_milliseconds();
2428 lcl_init( detect_lang() );
2430 // mprintf(("LCL_INIT() TOOK %d MS\n", timer_get_milliseconds()-t1));
2432 // verify that he has a valid ships.tbl (will Game_ships_tbl_valid if so)
2435 // verify that he has a valid weapons.tbl
2436 verify_weapons_tbl();
2438 // Output version numbers to registry for auto patching purposes
2439 os_config_write_uint(NOX("Version"), NOX("Major"), FS_VERSION_MAJOR);
2440 os_config_write_uint(NOX("Version"), NOX("Minor"), FS_VERSION_MINOR);
2441 os_config_write_uint(NOX("Version"), NOX("Build"), FS_VERSION_BUILD);
2443 Use_joy_mouse = 0; //os_config_read_uint( NULL, NOX("JoystickMovesCursor"), 1 );
2444 //Use_palette_flash = os_config_read_uint( NULL, NOX("PaletteFlash"), 0 );
2445 Use_low_mem = os_config_read_uint( NULL, NOX("LowMem"), 0 );
2448 Use_fullscreen_at_startup = os_config_read_uint( NULL, NOX("ForceFullscreen"), 1 );
2451 #if defined (PLAT_UNIX) && defined(RELEASE_REAL)
2452 // show the FPS counter if the config file says so
2453 Show_framerate = os_config_read_uint( NULL, NOX("ShowFPS"), 0 );
2456 #if !(defined(FS2_DEMO) || defined(FS1_DEMO))
2457 Asteroids_enabled = 1;
2460 /////////////////////////////
2462 /////////////////////////////
2467 ptr = os_config_read_string(NULL, NOX("Soundcard"), NULL);
2468 mprintf(("soundcard = %s\n", ptr ? ptr : "<nothing>"));
2470 if (!stricmp(ptr, NOX("no sound"))) {
2471 Cmdline_freespace_no_sound = 1;
2473 } else if (!stricmp(ptr, NOX("Aureal A3D"))) {
2475 } else if (!stricmp(ptr, NOX("EAX"))) {
2480 if (!Is_standalone) {
2481 snd_init(use_a3d, use_eax);
2483 /////////////////////////////
2485 /////////////////////////////
2487 ptr = os_config_read_string(NULL, NOX("Videocard"), NULL);
2490 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);
2492 // fire up the UpdateLauncher executable
2494 PROCESS_INFORMATION pi;
2496 memset( &si, 0, sizeof(STARTUPINFO) );
2499 BOOL ret = CreateProcess( LAUNCHER_FNAME, // pointer to name of executable module
2500 NULL, // pointer to command line string
2501 NULL, // pointer to process security attributes
2502 NULL, // pointer to thread security attributes
2503 FALSE, // handle inheritance flag
2504 CREATE_DEFAULT_ERROR_MODE, // creation flags
2505 NULL, // pointer to new environment block
2506 NULL, // pointer to current directory name
2507 &si, // pointer to STARTUPINFO
2508 &pi // pointer to PROCESS_INFORMATION
2511 // If the Launcher could not be started up, let the user know
2513 MessageBox((HWND)os_get_window(), XSTR("The Launcher could not be restarted.", 1450), XSTR("Error", 1451), MB_OK);
2522 if(!stricmp(ptr, "Aucune accélération 3D") || !stricmp(ptr, "Keine 3D-Beschleunigerkarte") || !stricmp(ptr, "No 3D acceleration")){
2524 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);
2532 // check for hi res pack file
2533 int has_sparky_hi = 0;
2535 // check if sparky_hi exists -- access mode 0 means does file exist
2536 #ifndef MAKE_FS1 // shoudn't have it so don't check
2539 if ( _access("sparky_hi_fs2.vp", 0) == 0) {
2542 mprintf(("No sparky_hi_fs2.vp in directory %s\n", dir));
2546 // see if we've got 32 bit in the string
2547 if(strstr(ptr, "32 bit")){
2554 if (!Is_standalone && ptr && (strstr(ptr, NOX("3DFX Glide")))) {
2556 // always 640 for E3
2557 gr_init(GR_640, GR_GLIDE);
2559 // regular or hi-res ?
2561 if(has_sparky_hi && strstr(ptr, NOX("(1024x768)"))){
2563 if(strstr(ptr, NOX("(1024x768)"))){
2565 gr_init(GR_1024, GR_GLIDE);
2567 gr_init(GR_640, GR_GLIDE);
2570 } else if (!Is_standalone && ptr && (strstr(ptr, NOX("Direct 3D -") ))) {
2572 // always 640 for E3
2574 gr_init(GR_640, GR_DIRECT3D, depth);
2576 // regular or hi-res ?
2578 if(has_sparky_hi && strstr(ptr, NOX("(1024x768)"))){
2580 if(strstr(ptr, NOX("(1024x768)"))){
2584 gr_init(GR_1024, GR_DIRECT3D, depth);
2588 gr_init(GR_640, GR_DIRECT3D, depth);
2594 if ( Use_fullscreen_at_startup && !Is_standalone) {
2595 gr_init(GR_640, GR_DIRECTDRAW);
2597 gr_init(GR_640, GR_SOFTWARE);
2600 if ( !Is_standalone ) {
2601 gr_init(GR_640, GR_DIRECTDRAW);
2603 gr_init(GR_640, GR_SOFTWARE);
2608 if (!Is_standalone /* && ptr && (strstr(ptr, NOX("OpenGL"))) */) {
2609 if(has_sparky_hi && strstr(ptr, NOX("(1024x768)"))){
2610 gr_init(GR_1024, GR_OPENGL);
2612 gr_init(GR_640, GR_OPENGL);
2616 gr_init(GR_640, GR_SOFTWARE);
2618 #endif // !PLAT_UNIX
2621 extern int Gr_inited;
2622 if(trying_d3d && !Gr_inited){
2624 extern char Device_init_error[512];
2625 MessageBox( NULL, Device_init_error, "Error intializing Direct3D", MB_OK|MB_TASKMODAL|MB_SETFOREGROUND );
2634 ptr = os_config_read_string(NULL,NOX("Gamma"),NOX("1.80"));
2635 Freespace_gamma = (float)atof(ptr);
2636 if ( Freespace_gamma == 0.0f ) {
2637 Freespace_gamma = 1.80f;
2638 } else if ( Freespace_gamma < 0.1f ) {
2639 Freespace_gamma = 0.1f;
2640 } else if ( Freespace_gamma > 5.0f ) {
2641 Freespace_gamma = 5.0f;
2643 char tmp_gamma_string[32];
2644 sprintf( tmp_gamma_string, NOX("%.2f"), Freespace_gamma );
2645 os_config_write_string( NULL, NOX("Gamma"), tmp_gamma_string );
2647 gr_set_gamma(Freespace_gamma);
2649 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
2652 display_title_screen();
2656 // attempt to load up master tracker registry info (login and password)
2657 Multi_tracker_id = -1;
2659 // pxo login and password
2660 ptr = os_config_read_string(NOX("PXO"),NOX("Login"),NULL);
2662 nprintf(("Network","Error reading in PXO login data\n"));
2663 strcpy(Multi_tracker_login,"");
2665 strcpy(Multi_tracker_login,ptr);
2667 ptr = os_config_read_string(NOX("PXO"),NOX("Password"),NULL);
2669 nprintf(("Network","Error reading PXO password\n"));
2670 strcpy(Multi_tracker_passwd,"");
2672 strcpy(Multi_tracker_passwd,ptr);
2675 // pxo squad name and password
2676 ptr = os_config_read_string(NOX("PXO"),NOX("SquadName"),NULL);
2678 nprintf(("Network","Error reading in PXO squad name\n"));
2679 strcpy(Multi_tracker_squad_name, "");
2681 strcpy(Multi_tracker_squad_name, ptr);
2684 // If less than 48MB of RAM, use low memory model.
2687 (Freespace_total_ram < 48*1024*1024) ||
2690 mprintf(( "Using normal memory settings...\n" ));
2691 bm_set_low_mem(1); // Use every other frame of bitmaps
2693 mprintf(( "Using high memory settings...\n" ));
2694 bm_set_low_mem(0); // Use all frames of bitmaps
2697 // load non-darkening pixel defs
2698 palman_load_pixels();
2700 // hud shield icon stuff
2701 hud_shield_game_init();
2703 control_config_common_init(); // sets up localization stuff in the control config
2709 gamesnd_parse_soundstbl();
2714 // standalone's don't use hte joystick and it seems to sometimes cause them to not get shutdown properly
2719 player_controls_init();
2722 //if(!Is_standalone){
2730 ship_init(); // read in ships.tbl
2732 mission_campaign_init(); // load in the default campaign
2734 // navmap_init(); // init the navigation map system
2735 context_help_init();
2736 techroom_intel_init(); // parse species.tbl, load intel info
2738 psnet_init( Multi_options_g.protocol, Multi_options_g.port ); // initialize the networking code
2739 init_animating_pointer();
2741 mission_brief_common_init(); // Mark all the briefing structures as empty.
2742 gr_font_init(); // loads up all fonts
2744 neb2_init(); // fullneb stuff
2748 player_tips_init(); // helpful tips
2751 // load the list of pilot pic filenames (for barracks and pilot select popup quick reference)
2752 pilot_load_pic_list();
2753 pilot_load_squad_pic_list();
2755 load_animating_pointer(NOX("cursor"), 0, 0);
2757 // initialize alpha colors
2758 alpha_colors_init();
2761 // Game_music_paused = 0;
2768 nprintf(("General", "Ships.tbl is : %s\n", Game_ships_tbl_valid ? "VALID" : "INVALID!!!!"));
2769 nprintf(("General", "Weapons.tbl is : %s\n", Game_weapons_tbl_valid ? "VALID" : "INVALID!!!!"));
2771 mprintf(("cfile_init() took %d\n", e1 - s1));
2772 // mprintf(("1000 cfopens() took %d\n", e2 - s2));
2775 char transfer_text[128];
2777 float Start_time = 0.0f;
2779 float Framerate = 0.0f;
2781 float Timing_total = 0.0f;
2782 float Timing_render2 = 0.0f;
2783 float Timing_render3 = 0.0f;
2784 float Timing_flip = 0.0f;
2785 float Timing_clear = 0.0f;
2787 MONITOR(NumPolysDrawn);
2793 void game_get_framerate()
2795 char text[128] = "";
2797 if ( frame_int == -1 ) {
2799 for (i=0; i<FRAME_FILTER; i++ ) {
2800 frametimes[i] = 0.0f;
2805 frametotal -= frametimes[frame_int];
2806 frametotal += flFrametime;
2807 frametimes[frame_int] = flFrametime;
2808 frame_int = (frame_int + 1 ) % FRAME_FILTER;
2810 if ( frametotal != 0.0 ) {
2811 if ( Framecount >= FRAME_FILTER )
2812 Framerate = FRAME_FILTER / frametotal;
2814 Framerate = Framecount / frametotal;
2815 sprintf( text, NOX("FPS: %.1f"), Framerate );
2817 sprintf( text, NOX("FPS: ?") );
2821 if (Show_framerate) {
2822 gr_set_color_fast(&HUD_color_debug);
2823 gr_string( 570, 2, text );
2827 void game_show_framerate()
2831 cur_time = f2fl(timer_get_approx_seconds());
2832 if (cur_time - Start_time > 30.0f) {
2833 mprintf(("%i frames executed in %7.3f seconds, %7.3f frames per second.\n", Framecount, cur_time - Start_time, Framecount/(cur_time - Start_time)));
2834 Start_time += 1000.0f;
2837 //mprintf(( "%s\n", text ));
2840 if ( Debug_dump_frames )
2844 // possibly show control checking info
2845 control_check_indicate();
2847 // int bitmaps_used_this_frame, bitmaps_new_this_frame;
2848 // bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
2849 // MONITOR_INC(BmpUsed, bitmaps_used_this_frame);
2850 // MONITOR_INC(BmpNew, bitmaps_new_this_frame);
2853 if ( Show_cpu == 1 ) {
2858 dy = gr_get_font_height() + 1;
2860 gr_set_color_fast(&HUD_color_debug);
2864 extern int D3D_textures_in;
2865 extern int D3D_textures_in_frame;
2866 extern int Glide_textures_in;
2867 extern int Glide_textures_in_frame;
2868 extern int Glide_explosion_vram;
2869 gr_printf( sx, sy, NOX("VRAM: %d KB\n"), (D3D_textures_in+Glide_textures_in)/1024 );
2871 gr_printf( sx, sy, NOX("VRAM: +%d KB\n"), (Glide_textures_in_frame+D3D_textures_in_frame)/1024 );
2873 gr_printf( sx, sy, NOX("EXP VRAM: %dKB\n"), (Glide_explosion_vram)/1024 );
2877 // gr_printf( sx, sy, "BPP: %d", gr_screen.bits_per_pixel );
2879 gr_printf( sx, sy, NOX("DMA: %s"), transfer_text );
2881 gr_printf( sx, sy, NOX("POLYP: %d"), modelstats_num_polys );
2883 gr_printf( sx, sy, NOX("POLYD: %d"), modelstats_num_polys_drawn );
2885 gr_printf( sx, sy, NOX("VERTS: %d"), modelstats_num_verts );
2890 extern int Num_pairs; // Number of object pairs that were checked.
2891 gr_printf( sx, sy, NOX("PAIRS: %d"), Num_pairs );
2894 extern int Num_pairs_checked; // What percent of object pairs were checked.
2895 gr_printf( sx, sy, NOX("FVI: %d"), Num_pairs_checked );
2897 Num_pairs_checked = 0;
2901 gr_printf( sx, sy, NOX("Snds: %d"), snd_num_playing() );
2904 if ( Timing_total > 0.01f ) {
2905 gr_printf( sx, sy, NOX("CLEAR: %.0f%%"), Timing_clear*100.0f/Timing_total );
2907 gr_printf( sx, sy, NOX("REND2D: %.0f%%"), Timing_render2*100.0f/Timing_total );
2909 gr_printf( sx, sy, NOX("REND3D: %.0f%%"), Timing_render3*100.0f/Timing_total );
2911 gr_printf( sx, sy, NOX("FLIP: %.0f%%"), Timing_flip*100.0f/Timing_total );
2913 gr_printf( sx, sy, NOX("GAME: %.0f%%"), (Timing_total-(Timing_render2+Timing_render3+Timing_flip+Timing_clear))*100.0f/Timing_total );
2923 dy = gr_get_font_height() + 1;
2925 gr_set_color_fast(&HUD_color_debug);
2928 extern int TotalRam;
2929 gr_printf( sx, sy, NOX("DYN: %d KB\n"), TotalRam/1024 );
2934 extern int Model_ram;
2935 gr_printf( sx, sy, NOX("POF: %d KB\n"), Model_ram/1024 );
2939 gr_printf( sx, sy, NOX("BMP: %d KB\n"), bm_texture_ram/1024 );
2941 gr_printf( sx, sy, NOX("S-SRAM: %d KB\n"), Snd_sram/1024 ); // mem used to store game sound
2943 gr_printf( sx, sy, NOX("S-HRAM: %d KB\n"), Snd_hram/1024 ); // mem used to store game sound
2947 extern int D3D_textures_in;
2948 extern int Glide_textures_in;
2949 extern int Glide_textures_in_frame;
2950 extern int Glide_explosion_vram;
2951 gr_printf( sx, sy, NOX("VRAM: %d KB\n"), (D3D_textures_in+Glide_textures_in)/1024 );
2953 gr_printf( sx, sy, NOX("VRAM: +%d KB\n"), (Glide_textures_in_frame)/1024 );
2955 gr_printf( sx, sy, NOX("EXP VRAM: %dKB\n"), (Glide_explosion_vram)/1024 );
2962 if ( Show_player_pos ) {
2966 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));
2969 MONITOR_INC(NumPolys, modelstats_num_polys);
2970 MONITOR_INC(NumPolysDrawn, modelstats_num_polys_drawn );
2971 MONITOR_INC(NumVerts, modelstats_num_verts );
2973 modelstats_num_polys = 0;
2974 modelstats_num_polys_drawn = 0;
2975 modelstats_num_verts = 0;
2976 modelstats_num_sortnorms = 0;
2980 void game_show_standalone_framerate()
2982 float frame_rate=30.0f;
2983 if ( frame_int == -1 ) {
2985 for (i=0; i<FRAME_FILTER; i++ ) {
2986 frametimes[i] = 0.0f;
2991 frametotal -= frametimes[frame_int];
2992 frametotal += flFrametime;
2993 frametimes[frame_int] = flFrametime;
2994 frame_int = (frame_int + 1 ) % FRAME_FILTER;
2996 if ( frametotal != 0.0 ) {
2997 if ( Framecount >= FRAME_FILTER ){
2998 frame_rate = FRAME_FILTER / frametotal;
3000 frame_rate = Framecount / frametotal;
3003 std_set_standalone_fps(frame_rate);
3007 // function to show the time remaining in a mission. Used only when the end-mission sexpression is used
3008 void game_show_time_left()
3012 // mission_end_time is a global from missionparse.cpp that contains the mission time at which the
3013 // mission should end (in fixed seconds). There is code in missionparse.cpp which actually handles
3014 // checking how much time is left
3016 if ( Mission_end_time == -1 ){
3020 diff = f2i(Mission_end_time - Missiontime);
3021 // be sure to bash to 0. diff could be negative on frame that we quit mission
3026 hud_set_default_color();
3027 gr_printf( 5, 40, XSTR( "Mission time remaining: %d seconds", 179), diff );
3030 //========================================================================================
3031 //=================== NEW DEBUG CONSOLE COMMANDS TO REPLACE OLD DEBUG PAUSE MENU =========
3032 //========================================================================================
3036 DCF(ai_pause,"Pauses ai")
3039 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
3040 if ( Dc_arg_type & ARG_TRUE ) ai_paused = 1;
3041 else if ( Dc_arg_type & ARG_FALSE ) ai_paused = 0;
3042 else if ( Dc_arg_type & ARG_NONE ) ai_paused = !ai_paused;
3045 obj_init_all_ships_physics();
3048 if ( Dc_help ) dc_printf( "Usage: ai_paused [bool]\nSets ai_paused to true or false. If nothing passed, then toggles it.\n" );
3049 if ( Dc_status ) dc_printf( "ai_paused is %s\n", (ai_paused?"TRUE":"FALSE") );
3052 DCF(single_step,"Single steps the game")
3055 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
3056 if ( Dc_arg_type & ARG_TRUE ) game_single_step = 1;
3057 else if ( Dc_arg_type & ARG_FALSE ) game_single_step = 0;
3058 else if ( Dc_arg_type & ARG_NONE ) game_single_step = !game_single_step;
3060 last_single_step = 0; // Make so single step waits a frame before stepping
3063 if ( Dc_help ) dc_printf( "Usage: single_step [bool]\nSets single_step to true or false. If nothing passed, then toggles it.\n" );
3064 if ( Dc_status ) dc_printf( "single_step is %s\n", (game_single_step?"TRUE":"FALSE") );
3067 DCF_BOOL(physics_pause, physics_paused)
3068 DCF_BOOL(ai_rendering, Ai_render_debug_flag)
3069 DCF_BOOL(ai_firing, Ai_firing_enabled )
3071 // Create some simple aliases to these commands...
3072 debug_command dc_s("s","shortcut for single_step",dcf_single_step);
3073 debug_command dc_p("p","shortcut for physics_pause", dcf_physics_pause );
3074 debug_command dc_r("r","shortcut for ai_rendering", dcf_ai_rendering );
3075 debug_command dc_f("f","shortcut for ai_firing", dcf_ai_firing);
3076 debug_command dc_a("a","shortcut for ai_pause", dcf_ai_pause);
3079 //========================================================================================
3080 //========================================================================================
3083 void game_training_pause_do()
3087 key = game_check_key();
3089 gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
3096 void game_increase_skill_level()
3099 if (Game_skill_level >= NUM_SKILL_LEVELS){
3100 Game_skill_level = 0;
3104 int Player_died_time;
3106 int View_percent = 100;
3109 DCF(view, "Sets the percent of the 3d view to render.")
3112 dc_get_arg(ARG_INT);
3113 if ( (Dc_arg_int >= 5 ) || (Dc_arg_int <= 100) ) {
3114 View_percent = Dc_arg_int;
3116 dc_printf( "Illegal value for view. (Must be from 5-100) \n\n");
3122 dc_printf("Usage: view [n]\nwhere n is percent of view to show (5-100).\n");
3126 dc_printf("View is set to %d%%\n", View_percent );
3131 // Set the clip region for the 3d rendering window
3132 void game_set_view_clip()
3134 if ((Game_mode & GM_DEAD) || (supernova_active() >= 2)) {
3135 // Set the clip region for the letterbox "dead view"
3136 int yborder = gr_screen.max_h/4;
3138 // Numeric constants encouraged by J "pig farmer" S, who shall remain semi-anonymous.
3139 // J.S. I've changed my ways!! See the new "no constants" code!!!
3140 gr_set_clip(0, yborder, gr_screen.max_w, gr_screen.max_h - yborder*2 );
3142 // Set the clip region for normal view
3143 if ( View_percent >= 100 ) {
3146 int xborder, yborder;
3148 if ( View_percent < 5 ) {
3152 float fp = i2fl(View_percent)/100.0f;
3153 int fi = fl2i(fl_sqrt(fp)*100.0f);
3154 if ( fi > 100 ) fi=100;
3156 xborder = ( gr_screen.max_w*(100-fi) )/200;
3157 yborder = ( gr_screen.max_h*(100-fi) )/200;
3159 gr_set_clip(xborder, yborder, gr_screen.max_w-xborder*2,gr_screen.max_h-yborder*2 );
3165 void show_debug_stuff()
3168 int laser_count = 0, missile_count = 0;
3170 for (i=0; i<MAX_OBJECTS; i++) {
3171 if (Objects[i].type == OBJ_WEAPON){
3172 if (Weapon_info[Weapons[Objects[i].instance].weapon_info_index].subtype == WP_LASER){
3174 } else if (Weapon_info[Weapons[Objects[i].instance].weapon_info_index].subtype == WP_MISSILE){
3180 nprintf(("Mike", "Frame: %i Lasers: %4i, Missiles: %4i\n", Framecount, laser_count, missile_count));
3183 extern int Tool_enabled;
3188 int tst_bitmap = -1;
3190 float tst_offset, tst_offset_total;
3193 void game_tst_frame_pre()
3201 g3_rotate_vertex(&v, &tst_pos);
3202 g3_project_vertex(&v);
3205 if(!((v.sx >= 0) && (v.sx <= gr_screen.max_w) && (v.sy >= 0) && (v.sy <= gr_screen.max_h))){
3209 // big ship? always tst
3211 // within 3000 meters
3212 if( vm_vec_dist_quick(&tst_pos, &Eye_position) <= 3000.0f){
3216 // within 300 meters
3217 if( (vm_vec_dist_quick(&tst_pos, &Eye_position) <= 300.0f) && ((tst_time == 0) || ((time(NULL) - tst_time) >= 10)) ){
3224 void game_tst_frame()
3234 tst_time = time(NULL);
3236 // load the tst bitmap
3237 switch((int)frand_range(0.0f, 3.0)){
3239 tst_bitmap = bm_load("ig_jim");
3241 mprintf(("TST 0\n"));
3245 tst_bitmap = bm_load("ig_kan");
3247 mprintf(("TST 1\n"));
3251 tst_bitmap = bm_load("ig_jim");
3253 mprintf(("TST 2\n"));
3257 tst_bitmap = bm_load("ig_kan");
3259 mprintf(("TST 3\n"));
3268 // get the tst bitmap dimensions
3270 bm_get_info(tst_bitmap, &w, &h);
3273 tst_y = frand_range(0.0f, (float)gr_screen.max_h - h);
3275 snd_play(&Snds[SND_VASUDAN_BUP]);
3277 // tst x and direction
3281 tst_offset_total = (float)w;
3282 tst_offset = (float)w;
3284 tst_x = (float)gr_screen.max_w;
3285 tst_offset_total = (float)-w;
3286 tst_offset = (float)w;
3294 float diff = (tst_offset_total / 0.5f) * flFrametime;
3300 tst_offset -= fl_abs(diff);
3301 } else if(tst_mode == 2){
3304 tst_offset -= fl_abs(diff);
3308 gr_set_bitmap(tst_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
3309 gr_bitmap((int)tst_x, (int)tst_y);
3312 if(timestamp_elapsed_safe(tst_stamp, 1100)){
3316 // if we passed the switch point
3317 if(tst_offset <= 0.0f){
3322 tst_stamp = timestamp(1000);
3323 tst_offset = fl_abs(tst_offset_total);
3334 void game_tst_mark(object *objp, ship *shipp)
3343 if((objp == NULL) || (shipp == NULL) || (shipp->ship_info_index < 0) || (shipp->ship_info_index >= Num_ship_types)){
3346 sip = &Ship_info[shipp->ship_info_index];
3353 tst_pos = objp->pos;
3354 if(sip->flags & (SIF_BIG_SHIP | SIF_HUGE_SHIP)){
3360 extern void render_shields();
3362 void player_repair_frame(float frametime)
3364 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
3366 for(idx=0;idx<MAX_PLAYERS;idx++){
3369 np = &Net_players[idx];
3371 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)){
3373 // don't rearm/repair if the player is dead or dying/departing
3374 if ( !NETPLAYER_IS_DEAD(np) && !(Ships[Objects[np->player->objnum].instance].flags & (SF_DYING|SF_DEPARTING)) ) {
3375 ai_do_repair_frame(&Objects[Net_players[idx].player->objnum],&Ai_info[Ships[Objects[Net_players[idx].player->objnum].instance].ai_index],frametime);
3380 if ( (Player_obj != NULL) && (Player_obj->type == OBJ_SHIP) && !(Game_mode & GM_STANDALONE_SERVER) && (Player_ship != NULL) && !(Player_ship->flags & SF_DYING) ) {
3381 ai_do_repair_frame(Player_obj, &Ai_info[Ships[Player_obj->instance].ai_index], frametime);
3387 #define NUM_FRAMES_TEST 300
3388 #define NUM_MIXED_SOUNDS 16
3389 void do_timing_test(float flFrametime)
3391 static int framecount = 0;
3392 static int test_running = 0;
3393 static float test_time = 0.0f;
3395 static int snds[NUM_MIXED_SOUNDS];
3398 if ( test_running ) {
3400 test_time += flFrametime;
3401 if ( framecount >= NUM_FRAMES_TEST ) {
3403 nprintf(("General", "%d frames took %.3f seconds\n", NUM_FRAMES_TEST, test_time));
3404 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3409 if ( Test_begin == 1 ) {
3415 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3418 // start looping digital sounds
3419 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3420 snds[i] = snd_play_looping( &Snds[i], 0.0f, -1, -1);
3427 DCF(dcf_fov, "Change the field of view")
3430 dc_get_arg(ARG_FLOAT|ARG_NONE);
3431 if ( Dc_arg_type & ARG_NONE ) {
3432 Viewer_zoom = VIEWER_ZOOM_DEFAULT;
3433 dc_printf( "Zoom factor reset\n" );
3435 if ( Dc_arg_type & ARG_FLOAT ) {
3436 if (Dc_arg_float < 0.25f) {
3437 Viewer_zoom = 0.25f;
3438 dc_printf("Zoom factor pinned at 0.25.\n");
3439 } else if (Dc_arg_float > 1.25f) {
3440 Viewer_zoom = 1.25f;
3441 dc_printf("Zoom factor pinned at 1.25.\n");
3443 Viewer_zoom = Dc_arg_float;
3449 dc_printf( "Usage: fov [factor]\nFactor is the zoom factor btwn .25 and 1.25\nNo parameter resets it to default.\n" );
3452 dc_printf("Zoom factor set to %6.3f (original = 0.5, John = 0.75)", Viewer_zoom);
3456 DCF(framerate_cap, "Sets the framerate cap")
3459 dc_get_arg(ARG_INT);
3460 if ( (Dc_arg_int >= 1 ) || (Dc_arg_int <= 120) ) {
3461 Framerate_cap = Dc_arg_int;
3463 dc_printf( "Illegal value for framerate cap. (Must be from 1-120) \n\n");
3469 dc_printf("Usage: framerate_cap [n]\nwhere n is the frames per second to cap framerate at.\n");
3470 dc_printf("If n is 0 or omitted, then the framerate cap is removed\n");
3471 dc_printf("[n] must be from 1 to 120.\n");
3475 if ( Framerate_cap )
3476 dc_printf("Framerate cap is set to %d fps\n", Framerate_cap );
3478 dc_printf("There is no framerate cap currently active.\n");
3482 #define MIN_DIST_TO_DEAD_CAMERA 50.0f
3483 int Show_viewing_from_self = 0;
3485 void say_view_target()
3487 object *view_target;
3489 if ((Viewer_mode & VM_OTHER_SHIP) && (Player_ai->target_objnum != -1))
3490 view_target = &Objects[Player_ai->target_objnum];
3492 view_target = Player_obj;
3494 if (Game_mode & GM_DEAD) {
3495 if (Player_ai->target_objnum != -1)
3496 view_target = &Objects[Player_ai->target_objnum];
3499 if (!(Game_mode & GM_DEAD_DIED) && ((Game_mode & (GM_DEAD_BLEW_UP)) || ((Last_view_target != NULL) && (Last_view_target != view_target)))) {
3500 if (view_target != Player_obj){
3502 char *view_target_name = NULL;
3503 switch(Objects[Player_ai->target_objnum].type) {
3505 view_target_name = Ships[Objects[Player_ai->target_objnum].instance].ship_name;
3508 view_target_name = Weapon_info[Weapons[Objects[Player_ai->target_objnum].instance].weapon_info_index].name;
3509 Viewer_mode &= ~VM_OTHER_SHIP;
3511 case OBJ_JUMP_NODE: {
3512 char jump_node_name[128];
3513 strcpy(jump_node_name, XSTR( "jump node", 184));
3514 view_target_name = jump_node_name;
3515 Viewer_mode &= ~VM_OTHER_SHIP;
3524 if ( view_target_name ) {
3525 HUD_fixed_printf(0.0f, XSTR( "Viewing %s%s\n", 185), (Viewer_mode & VM_OTHER_SHIP) ? XSTR( "from ", 186) : "", view_target_name);
3526 Show_viewing_from_self = 1;
3529 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER) && (Player_obj->type == OBJ_OBSERVER)){
3530 HUD_fixed_printf(2.0f,XSTR( "Viewing from observer\n", 187));
3531 Show_viewing_from_self = 1;
3533 if (Show_viewing_from_self)
3534 HUD_fixed_printf(2.0f, XSTR( "Viewing from self\n", 188));
3539 Last_view_target = view_target;
3543 float Game_hit_x = 0.0f;
3544 float Game_hit_y = 0.0f;
3546 // Reset at the beginning of each frame
3547 void game_whack_reset()
3553 // Apply a 2d whack to the player
3554 void game_whack_apply( float x, float y )
3556 // Do some force feedback
3557 joy_ff_play_dir_effect(x * 80.0f, y * 80.0f);
3563 // mprintf(( "WHACK = %.1f, %.1f\n", Game_hit_x, Game_hit_y ));
3566 // call to apply a "shudder"
3567 void game_shudder_apply(int time, float intensity)
3569 Game_shudder_time = timestamp(time);
3570 Game_shudder_total = time;
3571 Game_shudder_intensity = intensity;
3574 #define FF_SCALE 10000
3575 void apply_hud_shake(matrix *eye_orient)
3577 if (Viewer_obj == Player_obj) {
3578 physics_info *pi = &Player_obj->phys_info;
3586 // Make eye shake due to afterburner
3587 if ( !timestamp_elapsed(pi->afterburner_decay) ) {
3590 dtime = timestamp_until(pi->afterburner_decay);
3594 tangles.p += 0.07f * (float) (r1-RAND_MAX/2)/RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/ABURN_DECAY_TIME));
3595 tangles.h += 0.07f * (float) (r2-RAND_MAX/2)/RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/ABURN_DECAY_TIME));
3598 // Make eye shake due to engine wash
3600 if (Player_obj->type == OBJ_SHIP && (Ships[Player_obj->instance].wash_intensity > 0) && Wash_on ) {
3603 tangles.p += 0.07f * Ships[Player_obj->instance].wash_intensity * (float) (r1-RAND_MAX/2)/RAND_MAX;
3604 tangles.h += 0.07f * Ships[Player_obj->instance].wash_intensity * (float) (r2-RAND_MAX/2)/RAND_MAX;
3606 // get the intensity
3607 float intensity = FF_SCALE * Ships[Player_obj->instance].wash_intensity;
3611 vm_vec_rand_vec_quick(&rand_vec);
3614 joy_ff_play_dir_effect(intensity*rand_vec.xyz.x, intensity*rand_vec.xyz.y);
3618 // make hud shake due to shuddering
3619 if(Game_shudder_time != -1){
3620 // if the timestamp has elapsed
3621 if(timestamp_elapsed(Game_shudder_time)){
3622 Game_shudder_time = -1;
3624 // otherwise apply some shudder
3628 dtime = timestamp_until(Game_shudder_time);
3632 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));
3633 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));
3638 vm_angles_2_matrix(&tm, &tangles);
3639 Assert(vm_vec_mag(&tm.v.fvec) > 0.0f);
3640 Assert(vm_vec_mag(&tm.v.rvec) > 0.0f);
3641 Assert(vm_vec_mag(&tm.v.uvec) > 0.0f);
3642 vm_matrix_x_matrix(&tm2, eye_orient, &tm);
3647 extern void compute_slew_matrix(matrix *orient, angles *a); // TODO: move code to proper place and extern in header file
3649 // Player's velocity just before he blew up. Used to keep camera target moving.
3650 vector Dead_player_last_vel = {1.0f, 1.0f, 1.0f};
3652 // Set eye_pos and eye_orient based on view mode.
3653 void game_render_frame_setup(vector *eye_pos, matrix *eye_orient)
3657 static int last_Viewer_mode = 0;
3658 static int last_Game_mode = 0;
3659 static int last_Viewer_objnum = -1;
3661 // This code is supposed to detect camera "cuts"... like going between
3664 // determine if we need to regenerate the nebula
3665 if( (!(last_Viewer_mode & VM_EXTERNAL) && (Viewer_mode & VM_EXTERNAL)) || // internal to external
3666 ((last_Viewer_mode & VM_EXTERNAL) && !(Viewer_mode & VM_EXTERNAL)) || // external to internal
3667 (!(last_Viewer_mode & VM_DEAD_VIEW) && (Viewer_mode & VM_DEAD_VIEW)) || // non dead-view to dead-view
3668 ((last_Viewer_mode & VM_DEAD_VIEW) && !(Viewer_mode & VM_DEAD_VIEW)) || // dead-view to non dead-view
3669 (!(last_Viewer_mode & VM_WARP_CHASE) && (Viewer_mode & VM_WARP_CHASE)) || // non warp-chase to warp-chase
3670 ((last_Viewer_mode & VM_WARP_CHASE) && !(Viewer_mode & VM_WARP_CHASE)) || // warp-chase to non warp-chase
3671 (!(last_Viewer_mode & VM_OTHER_SHIP) && (Viewer_mode & VM_OTHER_SHIP)) || // non other-ship to other-ship
3672 ((last_Viewer_mode & VM_OTHER_SHIP) && !(Viewer_mode & VM_OTHER_SHIP)) || // other-ship to non-other ship
3673 ((Viewer_mode & VM_OTHER_SHIP) && (last_Viewer_objnum != Player_ai->target_objnum)) // other ship mode, but targets changes
3676 // regenerate the nebula
3680 if ( (last_Viewer_mode != Viewer_mode) || (last_Game_mode != Game_mode) ) {
3681 //mprintf(( "************** Camera cut! ************\n" ));
3682 last_Viewer_mode = Viewer_mode;
3683 last_Game_mode = Game_mode;
3685 // Camera moved. Tell stars & debris to not do blurring.
3691 if ( Viewer_mode & VM_PADLOCK_ANY ) {
3692 player_display_packlock_view();
3695 game_set_view_clip();
3697 if (Game_mode & GM_DEAD) {
3698 vector vec_to_deader, view_pos;
3701 Viewer_mode |= VM_DEAD_VIEW;
3703 if (Player_ai->target_objnum != -1) {
3704 int view_from_player = 1;
3706 if (Viewer_mode & VM_OTHER_SHIP) {
3707 // View from target.
3708 Viewer_obj = &Objects[Player_ai->target_objnum];
3710 last_Viewer_objnum = Player_ai->target_objnum;
3712 if ( Viewer_obj->type == OBJ_SHIP ) {
3713 ship_get_eye( eye_pos, eye_orient, Viewer_obj );
3714 view_from_player = 0;
3717 last_Viewer_objnum = -1;
3720 if ( view_from_player ) {
3721 // View target from player ship.
3723 *eye_pos = Player_obj->pos;
3724 vm_vec_normalized_dir(&eye_dir, &Objects[Player_ai->target_objnum].pos, eye_pos);
3725 vm_vector_2_matrix(eye_orient, &eye_dir, NULL, NULL);
3728 dist = vm_vec_normalized_dir(&vec_to_deader, &Player_obj->pos, &Dead_camera_pos);
3730 if (dist < MIN_DIST_TO_DEAD_CAMERA)
3731 dist += flFrametime * 16.0f;
3733 vm_vec_scale(&vec_to_deader, -dist);
3734 vm_vec_add(&Dead_camera_pos, &Player_obj->pos, &vec_to_deader);
3736 view_pos = Player_obj->pos;
3738 if (!(Game_mode & GM_DEAD_BLEW_UP)) {
3739 Viewer_mode &= ~(VM_EXTERNAL | VM_CHASE);
3740 vm_vec_scale_add2(&Dead_camera_pos, &Original_vec_to_deader, 25.0f * flFrametime);
3741 Dead_player_last_vel = Player_obj->phys_info.vel;
3742 //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));
3743 } else if (Player_ai->target_objnum != -1) {
3744 view_pos = Objects[Player_ai->target_objnum].pos;
3746 // Make camera follow explosion, but gradually slow down.
3747 vm_vec_scale_add2(&Player_obj->pos, &Dead_player_last_vel, flFrametime);
3748 view_pos = Player_obj->pos;
3749 vm_vec_scale(&Dead_player_last_vel, 0.99f);
3750 vm_vec_scale_add2(&Dead_camera_pos, &Original_vec_to_deader, min(25.0f, vm_vec_mag_quick(&Dead_player_last_vel)) * flFrametime);
3753 *eye_pos = Dead_camera_pos;
3755 vm_vec_normalized_dir(&eye_dir, &Player_obj->pos, eye_pos);
3757 vm_vector_2_matrix(eye_orient, &eye_dir, NULL, NULL);
3762 // if supernova shockwave
3763 if(supernova_camera_cut()){
3767 // call it dead view
3768 Viewer_mode |= VM_DEAD_VIEW;
3770 // set eye pos and orient
3771 supernova_set_view(eye_pos, eye_orient);
3773 // If already blown up, these other modes can override.
3774 if (!(Game_mode & (GM_DEAD | GM_DEAD_BLEW_UP))) {
3775 Viewer_mode &= ~VM_DEAD_VIEW;
3777 Viewer_obj = Player_obj;
3779 if (Viewer_mode & VM_OTHER_SHIP) {
3780 if (Player_ai->target_objnum != -1){
3781 Viewer_obj = &Objects[Player_ai->target_objnum];
3782 last_Viewer_objnum = Player_ai->target_objnum;
3784 Viewer_mode &= ~VM_OTHER_SHIP;
3785 last_Viewer_objnum = -1;
3788 last_Viewer_objnum = -1;
3791 if (Viewer_mode & VM_EXTERNAL) {
3794 vm_angles_2_matrix(&tm2, &Viewer_external_info.angles);
3795 vm_matrix_x_matrix(&tm, &Viewer_obj->orient, &tm2);
3797 vm_vec_scale_add(eye_pos, &Viewer_obj->pos, &tm.v.fvec, 2.0f * Viewer_obj->radius + Viewer_external_info.distance);
3799 vm_vec_sub(&eye_dir, &Viewer_obj->pos, eye_pos);
3800 vm_vec_normalize(&eye_dir);
3801 vm_vector_2_matrix(eye_orient, &eye_dir, &Viewer_obj->orient.v.uvec, NULL);
3804 // Modify the orientation based on head orientation.
3805 compute_slew_matrix(eye_orient, &Viewer_slew_angles);
3807 } else if ( Viewer_mode & VM_CHASE ) {
3810 if ( Viewer_obj->phys_info.speed < 0.1 )
3811 move_dir = Viewer_obj->orient.v.fvec;
3813 move_dir = Viewer_obj->phys_info.vel;
3814 vm_vec_normalize(&move_dir);
3817 vm_vec_scale_add(eye_pos, &Viewer_obj->pos, &move_dir, -3.0f * Viewer_obj->radius - Viewer_chase_info.distance);
3818 vm_vec_scale_add2(eye_pos, &Viewer_obj->orient.v.uvec, 0.75f * Viewer_obj->radius);
3819 vm_vec_sub(&eye_dir, &Viewer_obj->pos, eye_pos);
3820 vm_vec_normalize(&eye_dir);
3822 // JAS: I added the following code because if you slew up using
3823 // Descent-style physics, eye_dir and Viewer_obj->orient.v.uvec are
3824 // equal, which causes a zero-length vector in the vm_vector_2_matrix
3825 // call because the up and the forward vector are the same. I fixed
3826 // it by adding in a fraction of the right vector all the time to the
3828 vector tmp_up = Viewer_obj->orient.v.uvec;
3829 vm_vec_scale_add2( &tmp_up, &Viewer_obj->orient.v.rvec, 0.00001f );
3831 vm_vector_2_matrix(eye_orient, &eye_dir, &tmp_up, NULL);
3834 // Modify the orientation based on head orientation.
3835 compute_slew_matrix(eye_orient, &Viewer_slew_angles);
3836 } else if ( Viewer_mode & VM_WARP_CHASE ) {
3837 *eye_pos = Camera_pos;
3839 ship * shipp = &Ships[Player_obj->instance];
3841 vm_vec_sub(&eye_dir, &shipp->warp_effect_pos, eye_pos);
3842 vm_vec_normalize(&eye_dir);
3843 vm_vector_2_matrix(eye_orient, &eye_dir, &Player_obj->orient.v.uvec, NULL);
3846 // get an eye position based upon the correct type of object
3847 switch(Viewer_obj->type){
3849 // make a call to get the eye point for the player object
3850 ship_get_eye( eye_pos, eye_orient, Viewer_obj );
3853 // make a call to get the eye point for the player object
3854 observer_get_eye( eye_pos, eye_orient, Viewer_obj );
3860 #ifdef JOHNS_DEBUG_CODE
3861 john_debug_stuff(&eye_pos, &eye_orient);
3867 apply_hud_shake(eye_orient);
3869 // setup neb2 rendering
3870 neb2_render_setup(eye_pos, eye_orient);
3874 extern void ai_debug_render_stuff();
3877 int Game_subspace_effect = 0;
3878 DCF_BOOL( subspace, Game_subspace_effect );
3880 // Does everything needed to render a frame
3881 void game_render_frame( vector * eye_pos, matrix * eye_orient )
3885 g3_start_frame(game_zbuffer);
3886 g3_set_view_matrix( eye_pos, eye_orient, Viewer_zoom );
3888 // maybe offset the HUD (jitter stuff)
3889 dont_offset = ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER));
3890 HUD_set_offsets(Viewer_obj, !dont_offset);
3892 // for multiplayer clients, call code in Shield.cpp to set up the Shield_hit array. Have to
3893 // do this becaues of the disjointed nature of this system (in terms of setup and execution).
3894 // must be done before ships are rendered
3895 if ( MULTIPLAYER_CLIENT ) {
3896 shield_point_multi_setup();
3899 if ( Game_subspace_effect ) {
3900 stars_draw(0,0,0,1);
3902 stars_draw(1,1,1,0);
3905 obj_render_all(obj_render);
3906 beam_render_all(); // render all beam weapons
3907 particle_render_all(); // render particles after everything else.
3908 trail_render_all(); // render missilie trails after everything else.
3909 mflash_render_all(); // render all muzzle flashes
3911 // Why do we not show the shield effect in these modes? Seems ok.
3912 //if (!(Viewer_mode & (VM_EXTERNAL | VM_SLEWED | VM_CHASE | VM_DEAD_VIEW))) {
3916 // render nebula lightning
3919 // render local player nebula
3920 neb2_render_player();
3923 ai_debug_render_stuff();
3926 #ifndef RELEASE_REAL
3927 // game_framerate_check();
3931 extern void snd_spew_debug_info();
3932 snd_spew_debug_info();
3935 //================ END OF 3D RENDERING STUFF ====================
3939 if( (Game_detail_flags & DETAIL_FLAG_HUD) && !(Game_mode & GM_MULTIPLAYER) || ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER) ) ) {
3940 hud_maybe_clear_head_area();
3941 anim_render_all(0, flFrametime);
3944 extern int Multi_display_netinfo;
3945 if(Multi_display_netinfo){
3946 extern void multi_display_netinfo();
3947 multi_display_netinfo();
3950 game_tst_frame_pre();
3953 do_timing_test(flFrametime);
3957 extern int OO_update_index;
3958 multi_rate_display(OO_update_index, 375, 0);
3963 extern void oo_display();
3970 //#define JOHNS_DEBUG_CODE 1
3972 #ifdef JOHNS_DEBUG_CODE
3973 void john_debug_stuff(vector *eye_pos, matrix *eye_orient)
3975 //if ( keyd_pressed[KEY_LSHIFT] )
3977 ship_subsys *tsys = Players[Player_num].targeted_subobject;
3979 model_subsystem *turret = tsys->system_info;
3981 if (turret->type == SUBSYSTEM_TURRET ) {
3982 vector v.fvec, v.uvec;
3983 object * tobj = &Objects[Players[Player_num].targeted_subobject_parent];
3985 ship_model_start(tobj);
3987 model_find_world_point(eye_pos, &turret->turret_firing_point[0], turret->model_num, turret->turret_gun_sobj, &tobj->orient, &tobj->pos );
3988 model_find_world_dir(&v.fvec, &turret->turret_matrix.v.fvec, turret->model_num, turret->turret_gun_sobj, &tobj->orient, NULL );
3989 model_find_world_dir(&v.uvec, &turret->turret_matrix.v.uvec, turret->model_num, turret->turret_gun_sobj, &tobj->orient, NULL );
3991 vm_vector_2_matrix( eye_orient, &v.fvec, &v.uvec, NULL );
3993 ship_model_stop(tobj);
4003 // following function for dumping frames for purposes of building trailers.
4006 // function to toggle state of dumping every frame into PCX when playing the game
4007 DCF(dump_frames, "Starts/stop frame dumping at 15 hz")
4011 if ( Debug_dump_frames == 0 ) {
4013 Debug_dump_frames = 15;
4014 Debug_dump_trigger = 0;
4015 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
4016 dc_printf( "Frame dumping at 15 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_frames_trigger, "Starts/stop frame dumping at 15 hz")
4032 if ( Debug_dump_frames == 0 ) {
4034 Debug_dump_frames = 15;
4035 Debug_dump_trigger = 1;
4036 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
4037 dc_printf( "Frame dumping at 15 hz is now ON\n" );
4040 Debug_dump_frames = 0;
4041 Debug_dump_trigger = 0;
4042 gr_dump_frame_stop();
4043 dc_printf( "Frame dumping is now OFF\n" );
4049 DCF(dump_frames30, "Starts/stop frame dumping at 30 hz")
4053 if ( Debug_dump_frames == 0 ) {
4055 Debug_dump_frames = 30;
4056 Debug_dump_trigger = 0;
4057 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
4058 dc_printf( "Frame dumping at 30 hz is now ON\n" );
4061 Debug_dump_frames = 0;
4062 Debug_dump_trigger = 0;
4063 gr_dump_frame_stop();
4064 dc_printf( "Frame dumping is now OFF\n" );
4070 DCF(dump_frames30_trigger, "Starts/stop frame dumping at 30 hz")
4074 if ( Debug_dump_frames == 0 ) {
4076 Debug_dump_frames = 30;
4077 Debug_dump_trigger = 1;
4078 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
4079 dc_printf( "Triggered frame dumping at 30 hz is now ON\n" );
4082 Debug_dump_frames = 0;
4083 Debug_dump_trigger = 0;
4084 gr_dump_frame_stop();
4085 dc_printf( "Triggered frame dumping is now OFF\n" );
4091 void game_maybe_dump_frame()
4093 if ( !Debug_dump_frames ){
4097 if( Debug_dump_trigger && !keyd_pressed[KEY_Q] ){
4104 Debug_dump_frame_num++;
4110 extern int Player_dead_state;
4112 // Flip the page and time how long it took.
4113 void game_flip_page_and_time_it()
4118 t1 = timer_get_fixed_seconds();
4120 t2 = timer_get_fixed_seconds();
4123 t = (gr_screen.max_w*gr_screen.max_h*gr_screen.bytes_per_pixel)/1024;
4124 sprintf( transfer_text, NOX("%ld MB/s"), fixmuldiv(t,65,d) );
4131 void game_simulation_frame()
4133 // blow ships up in multiplayer dogfight
4134 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){
4135 // blow up all non-player ships
4136 ship_obj *moveup = GET_FIRST(&Ship_obj_list);
4139 while((moveup != END_OF_LIST(&Ship_obj_list)) && (moveup != NULL)){
4141 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)){
4142 moveup = GET_NEXT(moveup);
4145 shipp = &Ships[Objects[moveup->objnum].instance];
4146 sip = &Ship_info[shipp->ship_info_index];
4148 // only blow up small ships
4149 if((sip->flags & SIF_SMALL_SHIP) && (multi_find_player_by_object(&Objects[moveup->objnum]) < 0) ){
4150 // function to simply explode a ship where it is currently at
4151 ship_self_destruct( &Objects[moveup->objnum] );
4154 moveup = GET_NEXT(moveup);
4160 // process AWACS stuff - do this first thing
4163 // single player, set Player hits_this_frame to 0
4164 if ( !(Game_mode & GM_MULTIPLAYER) && Player ) {
4165 Player->damage_this_burst -= (flFrametime * MAX_BURST_DAMAGE / (0.001f * BURST_DURATION));
4166 Player->damage_this_burst = max(Player->damage_this_burst, 0.0f);
4170 supernova_process();
4171 if(supernova_active() >= 5){
4175 // fire targeting lasers now so that
4176 // 1 - created this frame
4177 // 2 - collide this frame
4178 // 3 - render this frame
4179 // 4 - ignored and deleted next frame
4180 // the basic idea being that because it con be confusing to deal with them on a multi-frame basis, they are only valid for
4182 ship_process_targeting_lasers();
4184 // do this here so that it works for multiplayer
4186 // get viewer direction
4187 int viewer_direction = PHYSICS_VIEWER_REAR;
4189 if(Viewer_mode == 0){
4190 viewer_direction = PHYSICS_VIEWER_FRONT;
4192 if(Viewer_mode & VM_PADLOCK_UP){
4193 viewer_direction = PHYSICS_VIEWER_UP;
4195 else if(Viewer_mode & VM_PADLOCK_REAR){
4196 viewer_direction = PHYSICS_VIEWER_REAR;
4198 else if(Viewer_mode & VM_PADLOCK_LEFT){
4199 viewer_direction = PHYSICS_VIEWER_LEFT;
4201 else if(Viewer_mode & VM_PADLOCK_RIGHT){
4202 viewer_direction = PHYSICS_VIEWER_RIGHT;
4205 physics_set_viewer( &Viewer_obj->phys_info, viewer_direction );
4207 physics_set_viewer( NULL, PHYSICS_VIEWER_FRONT );
4210 #define VM_PADLOCK_UP (1 << 7)
4211 #define VM_PADLOCK_REAR (1 << 8)
4212 #define VM_PADLOCK_LEFT (1 << 9)
4213 #define VM_PADLOCK_RIGHT (1 << 10)
4215 // evaluate mission departures and arrivals before we process all objects.
4216 if ( !(Game_mode & GM_MULTIPLAYER) || ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER) && !multi_endgame_ending()) ) {
4218 // we don't want to evaluate mission stuff when any ingame joiner in multiplayer is receiving
4219 // ships/wing packets.
4220 if ( !((Game_mode & GM_MULTIPLAYER) && (Netgame.flags & NG_FLAG_INGAME_JOINING_CRITICAL)) && !(Game_mode & GM_DEMO_PLAYBACK)){
4221 mission_parse_eval_stuff();
4224 // if we're an observer, move ourselves seperately from the standard physics
4225 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER)){
4226 obj_observer_move(flFrametime);
4229 // move all the objects now
4230 obj_move_all(flFrametime);
4232 // check for cargo reveal (this has an internal timestamp, so only runs every N ms)
4233 // AL: 3-15-98: It was decided to not let AI ships inspect cargo
4234 // ship_check_cargo_all();
4235 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4236 mission_eval_goals();
4240 // always check training objectives, even in multiplayer missions. we need to do this so that the directives gauge works properly on clients
4241 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4242 training_check_objectives();
4245 // do all interpolation now
4246 if ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER) && !multi_endgame_ending() && !(Netgame.flags & NG_FLAG_SERVER_LOST)) {
4247 // client side processing of warping in effect stages
4248 multi_do_client_warp(flFrametime);
4250 // client side movement of an observer
4251 if((Net_player->flags & NETINFO_FLAG_OBSERVER) || (Player_obj->type == OBJ_OBSERVER)){
4252 obj_observer_move(flFrametime);
4255 // move all objects - does interpolation now as well
4256 obj_move_all(flFrametime);
4259 // only process the message queue when the player is "in" the game
4260 if ( !Pre_player_entry ){
4261 message_queue_process(); // process any messages send to the player
4264 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4265 message_maybe_distort(); // maybe distort incoming message if comms damaged
4266 player_repair_frame(flFrametime); // AI objects get repaired in ai_process, called from move code...deal with player.
4267 player_process_pending_praise(); // maybe send off a delayed praise message to the player
4268 player_maybe_play_all_alone_msg(); // mabye tell the player he is all alone
4271 if(!(Game_mode & GM_STANDALONE_SERVER)){
4272 // process some stuff every frame (before frame is rendered)
4273 emp_process_local();
4275 hud_update_frame(); // update hud systems
4277 if (!physics_paused) {
4278 // Move particle system
4279 particle_move_all(flFrametime);
4281 // Move missile trails
4282 trail_move_all(flFrametime);
4284 // process muzzle flashes
4285 mflash_process_all();
4287 // Flash the gun flashes
4288 shipfx_flash_do_frame(flFrametime);
4290 shockwave_move_all(flFrametime); // update all the shockwaves
4293 // subspace missile strikes
4296 obj_snd_do_frame(); // update the object-linked persistant sounds
4297 game_maybe_update_sound_environment();
4298 snd_update_listener(&View_position, &Player_obj->phys_info.vel, &Player_obj->orient);
4300 // AL: debug code used for testing ambient subspace sound (ie when enabling subspace through debug console)
4302 if ( Game_subspace_effect ) {
4303 game_start_subspace_ambient_sound();
4309 // Maybe render and process the dead-popup
4310 void game_maybe_do_dead_popup(float frametime)
4312 if ( popupdead_is_active() ) {
4314 int choice = popupdead_do_frame(frametime);
4316 if ( Game_mode & GM_NORMAL ) {
4320 if(game_do_cd_mission_check(Game_current_mission_filename)){
4321 gameseq_post_event(GS_EVENT_ENTER_GAME);
4323 gameseq_post_event(GS_EVENT_MAIN_MENU);
4328 gameseq_post_event(GS_EVENT_END_GAME);
4333 if(game_do_cd_mission_check(Game_current_mission_filename)){
4334 gameseq_post_event(GS_EVENT_START_GAME);
4336 gameseq_post_event(GS_EVENT_MAIN_MENU);
4340 // this should only happen during a red alert mission
4343 Assert(The_mission.red_alert);
4344 if(!The_mission.red_alert){
4346 if(game_do_cd_mission_check(Game_current_mission_filename)){
4347 gameseq_post_event(GS_EVENT_START_GAME);
4349 gameseq_post_event(GS_EVENT_MAIN_MENU);
4354 // choose the previous mission
4355 mission_campaign_previous_mission();
4357 if(game_do_cd_mission_check(Game_current_mission_filename)){
4358 gameseq_post_event(GS_EVENT_START_GAME);
4360 gameseq_post_event(GS_EVENT_MAIN_MENU);
4371 case POPUPDEAD_DO_MAIN_HALL:
4372 multi_quit_game(PROMPT_NONE,-1);
4375 case POPUPDEAD_DO_RESPAWN:
4376 multi_respawn_normal();
4377 event_music_player_respawn();
4380 case POPUPDEAD_DO_OBSERVER:
4381 multi_respawn_observer();
4382 event_music_player_respawn_as_observer();
4391 if ( leave_popup ) {
4397 // returns true if player is actually in a game_play stats
4398 int game_actually_playing()
4402 state = gameseq_get_state();
4403 if ( (state != GS_STATE_GAME_PLAY) && (state != GS_STATE_DEATH_DIED) && (state != GS_STATE_DEATH_BLEW_UP) )
4409 // Draw the 2D HUD gauges
4410 void game_render_hud_2d()
4412 if ( !(Game_detail_flags & DETAIL_FLAG_HUD) ) {
4416 HUD_render_2d(flFrametime);
4420 // Draw the 3D-dependant HUD gauges
4421 void game_render_hud_3d(vector *eye_pos, matrix *eye_orient)
4423 g3_start_frame(0); // 0 = turn zbuffering off
4424 g3_set_view_matrix( eye_pos, eye_orient, Viewer_zoom );
4426 if ( (Game_detail_flags & DETAIL_FLAG_HUD) && (supernova_active() < 3)/* && !(Game_mode & GM_MULTIPLAYER) || ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER) )*/ ) {
4427 HUD_render_3d(flFrametime);
4431 game_sunspot_process(flFrametime);
4433 // Diminish the palette effect
4434 game_flash_diminish(flFrametime);
4442 int actually_playing;
4443 fix total_time1, total_time2;
4444 fix render2_time1=0, render2_time2=0;
4445 fix render3_time1=0, render3_time2=0;
4446 fix flip_time1=0, flip_time2=0;
4447 fix clear_time1=0, clear_time2=0;
4453 if (Framerate_delay) {
4454 int start_time = timer_get_milliseconds();
4455 while (timer_get_milliseconds() < start_time + Framerate_delay)
4461 demo_do_frame_start();
4463 mprintf(("Error (%d) while processing demo!\n", Demo_error));
4468 // start timing frame
4469 timing_frame_start();
4471 total_time1 = timer_get_fixed_seconds();
4473 // var to hold which state we are in
4474 actually_playing = game_actually_playing();
4476 if ((!(Game_mode & GM_MULTIPLAYER)) || ((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER))) {
4477 if (!(Game_mode & GM_STANDALONE_SERVER)){
4478 Assert( OBJ_INDEX(Player_obj) >= 0 );
4482 if (Missiontime > Entry_delay_time){
4483 Pre_player_entry = 0;
4485 ; //nprintf(("AI", "Framecount = %i, time = %7.3f\n", Framecount, f2fl(Missiontime)));
4488 // Note: These are done even before the player enters, else buffers can overflow.
4489 if (! (Game_mode & GM_STANDALONE_SERVER)){
4493 shield_frame_init();
4495 if ( Player->control_mode != PCM_NORMAL )
4498 if ( !Pre_player_entry && actually_playing ) {
4499 if (! (Game_mode & GM_STANDALONE_SERVER) ) {
4501 if( (!popup_running_state()) && (!popupdead_is_active()) ){
4502 game_process_keys();
4504 // don't read flying controls if we're playing a demo back
4505 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4506 read_player_controls( Player_obj, flFrametime);
4510 // if we're not the master, we may have to send the server-critical ship status button_info bits
4511 if ((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER)){
4512 multi_maybe_send_ship_status();
4517 // Reset the whack stuff
4520 // These two lines must be outside of Pre_player_entry code,
4521 // otherwise too many lights are added.
4524 if ((Game_mode & GM_MULTIPLAYER) && (Netgame.game_state == NETGAME_STATE_SERVER_TRANSFER)){
4528 game_simulation_frame();
4530 // if not actually in a game play state, then return. This condition could only be true in
4531 // a multiplayer game.
4532 if ( !actually_playing ) {
4533 Assert( Game_mode & GM_MULTIPLAYER );
4537 if (!Pre_player_entry) {
4538 if (! (Game_mode & GM_STANDALONE_SERVER)) {
4539 clear_time1 = timer_get_fixed_seconds();
4540 // clear the screen to black
4542 if ( (Game_detail_flags & DETAIL_FLAG_CLEAR) ) {
4546 clear_time2 = timer_get_fixed_seconds();
4547 render3_time1 = timer_get_fixed_seconds();
4548 game_render_frame_setup(&eye_pos, &eye_orient);
4549 game_render_frame( &eye_pos, &eye_orient );
4551 // save the eye position and orientation
4552 if ( Game_mode & GM_MULTIPLAYER ) {
4553 Net_player->s_info.eye_pos = eye_pos;
4554 Net_player->s_info.eye_orient = eye_orient;
4557 hud_show_target_model();
4559 // check to see if we should display the death died popup
4560 if(Game_mode & GM_DEAD_BLEW_UP){
4561 if(Game_mode & GM_MULTIPLAYER){
4562 // catch the situation where we're supposed to be warping out on this transition
4563 if(Net_player->flags & NETINFO_FLAG_WARPING_OUT){
4564 gameseq_post_event(GS_EVENT_DEBRIEF);
4565 } else if((Player_died_popup_wait != -1) && (timestamp_elapsed(Player_died_popup_wait))){
4566 Player_died_popup_wait = -1;
4570 if((Player_died_popup_wait != -1) && (timestamp_elapsed(Player_died_popup_wait))){
4571 Player_died_popup_wait = -1;
4577 // hack - sometimes this seems to slip by in multiplayer. this should guarantee that we catch it
4578 if((Game_mode & GM_MULTIPLAYER) && (Player_multi_died_check != -1) && (Game_mode & GM_DEAD_BLEW_UP) ){
4579 if(fl_abs(time(NULL) - Player_multi_died_check) > 4){
4580 if(!popupdead_is_active()){
4584 Player_multi_died_check = -1;
4588 render3_time2 = timer_get_fixed_seconds();
4589 render2_time1 = timer_get_fixed_seconds();
4592 game_get_framerate();
4593 game_show_framerate();
4595 game_show_time_left();
4597 // Draw the 2D HUD gauges
4598 if(supernova_active() < 3){
4599 game_render_hud_2d();
4602 game_set_view_clip();
4604 // Draw 3D HUD gauges
4605 game_render_hud_3d(&eye_pos, &eye_orient);
4609 render2_time2 = timer_get_fixed_seconds();
4611 // maybe render and process the dead popup
4612 game_maybe_do_dead_popup(flFrametime);
4614 // start timing frame
4615 timing_frame_stop();
4616 // timing_display(30, 10);
4618 // If a regular popup is active, don't flip (popup code flips)
4619 if( !popup_running_state() ){
4620 flip_time1 = timer_get_fixed_seconds();
4621 game_flip_page_and_time_it();
4622 flip_time2 = timer_get_fixed_seconds();
4626 game_maybe_dump_frame(); // used to dump pcx files for building trailers
4629 game_show_standalone_framerate();
4633 game_do_training_checks();
4636 // process lightning (nebula only)
4639 total_time2 = timer_get_fixed_seconds();
4641 // Got some timing numbers
4642 Timing_total = f2fl( total_time2 - total_time1 ) * 1000.0f;
4643 Timing_clear = f2fl( clear_time2 - clear_time1 ) * 1000.0f;
4644 Timing_render2 = f2fl( render2_time2- render2_time1 ) * 1000.0f;
4645 Timing_render3 = f2fl( render3_time2- render3_time1 ) * 1000.0f;
4646 Timing_flip = f2fl( flip_time2 - flip_time1 ) * 1000.0f;
4649 demo_do_frame_end();
4651 mprintf(("Error (%d) while processing demo!\n", Demo_error));
4657 #define MAX_FRAMETIME (F1_0/4) // Frametime gets saturated at this. Changed by MK on 11/1/97.
4658 // Some bug was causing Frametime to always get saturated at 2.0 seconds after the player
4659 // died. This resulted in screwed up death sequences.
4661 fix Last_time = 0; // The absolute time of game at end of last frame (beginning of this frame)
4662 fix Last_delta_time = 0; // While game is paused, this keeps track of how much elapsed in the frame before paused.
4663 static int timer_paused=0;
4664 #if defined(TIMER_TEST) && !defined(NDEBUG)
4665 static int stop_count,start_count;
4666 static int time_stopped,time_started;
4668 int saved_timestamp_ticker = -1;
4670 void game_reset_time()
4672 if((Game_mode & GM_MULTIPLAYER) && (Netgame.game_state == NETGAME_STATE_SERVER_TRANSFER)){
4676 // Last_time = timer_get_fixed_seconds();
4682 void game_stop_time()
4684 if (timer_paused==0) {
4686 time = timer_get_fixed_seconds();
4687 // Save how much time progressed so far in the frame so we can
4688 // use it when we unpause.
4689 Last_delta_time = time - Last_time;
4691 //mprintf(("Last_time in game_stop_time = %7.3f\n", f2fl(Last_delta_time)));
4692 if (Last_delta_time < 0) {
4693 #if defined(TIMER_TEST) && !defined(NDEBUG)
4694 Int3(); //get Matt!!!!
4696 Last_delta_time = 0;
4698 #if defined(TIMER_TEST) && !defined(NDEBUG)
4699 time_stopped = time;
4702 // Stop the timer_tick stuff...
4703 // Normally, you should never access 'timestamp_ticker', consider this a low-level routine
4704 saved_timestamp_ticker = timestamp_ticker;
4708 #if defined(TIMER_TEST) && !defined(NDEBUG)
4713 void game_start_time()
4716 Assert(timer_paused >= 0);
4717 if (timer_paused==0) {
4719 time = timer_get_fixed_seconds();
4720 #if defined(TIMER_TEST) && !defined(NDEBUG)
4722 Int3(); //get Matt!!!!
4725 // Take current time, and set it backwards to account for time
4726 // that the frame already executed, so that timer_get_fixed_seconds() - Last_time
4727 // will be correct when it goes to calculate the frametime next
4729 Last_time = time - Last_delta_time;
4730 #if defined(TIMER_TEST) && !defined(NDEBUG)
4731 time_started = time;
4734 // Restore the timer_tick stuff...
4735 // Normally, you should never access 'timestamp_ticker', consider this a low-level routine
4736 Assert( saved_timestamp_ticker > -1 ); // Called out of order, get JAS
4737 timestamp_ticker = saved_timestamp_ticker;
4738 saved_timestamp_ticker = -1;
4741 #if defined(TIMER_TEST) && !defined(NDEBUG)
4747 void game_set_frametime(int state)
4750 float frame_cap_diff;
4752 thistime = timer_get_fixed_seconds();
4754 if ( Last_time == 0 )
4755 Frametime = F1_0 / 30;
4757 Frametime = thistime - Last_time;
4759 // Frametime = F1_0 / 30;
4761 fix debug_frametime = Frametime; // Just used to display frametime.
4763 // If player hasn't entered mission yet, make frame take 1/4 second.
4764 if ((Pre_player_entry) && (state == GS_STATE_GAME_PLAY))
4767 else if ((Debug_dump_frames) && (state == GS_STATE_GAME_PLAY)) { // note link to above if!!!!!
4769 fix frame_speed = F1_0 / Debug_dump_frames;
4771 if (Frametime > frame_speed ){
4772 nprintf(("warning","slow frame: %x\n",Frametime));
4775 thistime = timer_get_fixed_seconds();
4776 Frametime = thistime - Last_time;
4777 } while (Frametime < frame_speed );
4779 Frametime = frame_speed;
4783 Assert( Framerate_cap > 0 );
4785 // Cap the framerate so it doesn't get too high.
4789 cap = F1_0/Framerate_cap;
4790 if (Frametime < cap) {
4791 thistime = cap - Frametime;
4792 //mprintf(("Sleeping for %6.3f seconds.\n", f2fl(thistime)));
4793 Sleep( (DWORD)(f2fl(thistime) * 1000.0f) );
4795 thistime = timer_get_fixed_seconds();
4799 if((Game_mode & GM_STANDALONE_SERVER) &&
4800 (f2fl(Frametime) < ((float)1.0/(float)Multi_options_g.std_framecap))){
4802 frame_cap_diff = ((float)1.0/(float)Multi_options_g.std_framecap) - f2fl(Frametime);
4803 Sleep((DWORD)(frame_cap_diff*1000));
4805 thistime += fl2f((frame_cap_diff));
4807 Frametime = thistime - Last_time;
4810 // If framerate is too low, cap it.
4811 if (Frametime > MAX_FRAMETIME) {
4813 mprintf(("Frame %2i too long!!: frametime = %.3f (%.3f)\n", Framecount, f2fl(Frametime), f2fl(debug_frametime)));
4815 // to remove warnings in release build
4816 debug_frametime = fl2f(flFrametime);
4818 Frametime = MAX_FRAMETIME;
4821 Frametime = fixmul(Frametime, Game_time_compression);
4823 Last_time = thistime;
4824 //mprintf(("Frame %i, Last_time = %7.3f\n", Framecount, f2fl(Last_time)));
4826 flFrametime = f2fl(Frametime);
4827 //if(!(Game_mode & GM_PLAYING_DEMO)){
4828 timestamp_inc(flFrametime);
4830 /* if ((Framecount > 0) && (Framecount < 10)) {
4831 mprintf(("Frame %2i: frametime = %.3f (%.3f)\n", Framecount, f2fl(Frametime), f2fl(debug_frametime)));
4836 // This is called from game_do_frame(), and from navmap_do_frame()
4837 void game_update_missiontime()
4839 // TODO JAS: Put in if and move this into game_set_frametime,
4840 // fix navmap to call game_stop/start_time
4841 //if ( !timer_paused )
4842 Missiontime += Frametime;
4845 void game_do_frame()
4847 game_set_frametime(GS_STATE_GAME_PLAY);
4848 game_update_missiontime();
4850 if (Game_mode & GM_STANDALONE_SERVER) {
4851 std_multi_set_standalone_missiontime(f2fl(Missiontime));
4854 if ( game_single_step && (last_single_step == game_single_step) ) {
4855 os_set_title( NOX("SINGLE STEP MODE (Pause exits, any other key steps)") );
4856 while( key_checkch() == 0 )
4858 os_set_title( XSTR( "FreeSpace", 171) );
4859 Last_time = timer_get_fixed_seconds();
4862 last_single_step = game_single_step;
4864 if ((gameseq_get_state() == GS_STATE_GAME_PLAY) && Use_mouse_to_fly){
4865 Keep_mouse_centered = 1; // force mouse to center of our window (so we don't hit movement limits)
4869 Keep_mouse_centered = 0;
4870 monitor_update(); // Update monitor variables
4873 void multi_maybe_do_frame()
4875 if ( (Game_mode & GM_MULTIPLAYER) && (Game_mode & GM_IN_MISSION) && !Multi_pause_status){
4880 int Joymouse_button_status = 0;
4882 // Flush all input devices
4890 Joymouse_button_status = 0;
4892 //mprintf(("Game flush!\n" ));
4895 // function for multiplayer only which calls game_do_state_common() when running the
4897 void game_do_dc_networking()
4899 Assert( Game_mode & GM_MULTIPLAYER );
4901 game_do_state_common( gameseq_get_state() );
4904 // Call this whenever in a loop, or when you need to check for a keystroke.
4905 int game_check_key()
4911 // convert keypad enter to normal enter
4912 if ((k & KEY_MASK) == KEY_PADENTER)
4913 k = (k & ~KEY_MASK) | KEY_ENTER;
4918 #if defined(FS2_DEMO) || defined(FS1_DEMO)
4920 #define DEMO_TRAILER_TIMEOUT_MS 45000 // 45 seconds of no input, play trailer
4921 static int Demo_show_trailer_timestamp = 0;
4923 void demo_reset_trailer_timer()
4925 Demo_show_trailer_timestamp = timer_get_milliseconds();
4928 void demo_maybe_show_trailer(int k)
4931 // if key pressed, reset demo trailer timer
4933 demo_reset_trailer_timer();
4937 // if mouse moved, reset demo trailer timer
4940 mouse_get_delta(&dx, &dy);
4941 if ( (dx > 0) || (dy > 0) ) {
4942 demo_reset_trailer_timer();
4946 // if joystick has moved, reset demo trailer timer
4949 joy_get_delta(&dx, &dy);
4950 if ( (dx > 0) || (dy > 0) ) {
4951 demo_reset_trailer_timer();
4955 // NOTE: reseting the trailer timer on mouse/joystick presses is handled in
4956 // the low-level code. Ugly, I know... but was the simplest and most
4959 // if 30 seconds since last demo trailer time reset, launch movie
4960 if ( os_foreground() ) {
4961 int now = timer_get_milliseconds();
4962 if ( (now - Demo_show_trailer_timestamp) > DEMO_TRAILER_TIMEOUT_MS ) {
4963 // if ( (now - Demo_show_trailer_timestamp) > 10000 ) {
4965 movie_play( NOX("fstrailer2.mve") );
4966 demo_reset_trailer_timer();
4974 // same as game_check_key(), except this is used while actually in the game. Since there
4975 // generally are differences between game control keys and general UI keys, makes sense to
4976 // have seperate functions for each case. If you are not checking a game control while in a
4977 // mission, you should probably be using game_check_key() instead.
4982 if (!os_foreground()) {
4987 // If we're in a single player game, pause it.
4988 if (!(Game_mode & GM_MULTIPLAYER)){
4989 if ( (gameseq_get_state() == GS_STATE_GAME_PLAY) && (!popup_active()) && (!popupdead_is_active()) ) {
4990 game_process_pause_key();
4997 #if defined(FS2_DEMO) || defined(FS1_DEMO)
4998 demo_maybe_show_trailer(k);
5001 // Move the mouse cursor with the joystick.
5002 if (os_foreground() && (!Mouse_hidden) && (Use_joy_mouse) ) {
5003 // Move the mouse cursor with the joystick
5007 joy_get_pos( &jx, &jy, &jz, &jr );
5009 dx = fl2i(f2fl(jx)*flFrametime*500.0f);
5010 dy = fl2i(f2fl(jy)*flFrametime*500.0f);
5013 mouse_get_real_pos( &mx, &my );
5014 mouse_set_pos( mx+dx, my+dy );
5019 m = mouse_down(MOUSE_LEFT_BUTTON);
5021 if ( j != Joymouse_button_status ) {
5022 //mprintf(( "Joy went from %d to %d, mouse is %d\n", Joymouse_button_status, j, m ));
5023 Joymouse_button_status = j;
5025 mouse_mark_button( MOUSE_LEFT_BUTTON, 1 );
5026 } else if ( (!j) && (m) ) {
5027 mouse_mark_button( MOUSE_LEFT_BUTTON, 0 );
5032 // if we should be ignoring keys because of some multiplayer situations
5033 if((Game_mode & GM_MULTIPLAYER) && multi_ignore_controls(k)){
5037 // If a popup is running, don't process all the Fn keys
5038 if( popup_active() ) {
5042 state = gameseq_get_state();
5044 // if ( k ) nprintf(( "General", "Key = %x\n", k ));
5047 case KEY_DEBUGGED + KEY_BACKSP:
5052 launch_context_help();
5057 // if (state != GS_STATE_INITIAL_PLAYER_SELECT) {
5059 // don't allow f2 while warping out in multiplayer
5060 if((Game_mode & GM_MULTIPLAYER) && (Net_player != NULL) && (Net_player->flags & NETINFO_FLAG_WARPING_OUT)){
5065 case GS_STATE_INITIAL_PLAYER_SELECT:
5066 case GS_STATE_OPTIONS_MENU:
5067 case GS_STATE_HUD_CONFIG:
5068 case GS_STATE_CONTROL_CONFIG:
5069 case GS_STATE_DEATH_DIED:
5070 case GS_STATE_DEATH_BLEW_UP:
5071 case GS_STATE_VIEW_MEDALS:
5075 gameseq_post_event(GS_EVENT_OPTIONS_MENU);
5082 // hotkey selection screen -- only valid from briefing and beyond.
5084 #if !(defined(FS2_DEMO) || defined(FS1_DEMO))
5085 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) ) {
5086 gameseq_post_event( GS_EVENT_HOTKEY_SCREEN );
5092 case KEY_DEBUGGED + KEY_F3:
5093 gameseq_post_event( GS_EVENT_TOGGLE_FULLSCREEN );
5096 case KEY_DEBUGGED + KEY_F4:
5097 gameseq_post_event( GS_EVENT_TOGGLE_GLIDE );
5101 if(Game_mode & GM_MULTIPLAYER){
5102 if((state == GS_STATE_GAME_PLAY) || (state == GS_STATE_MULTI_PAUSED)){
5103 gameseq_post_event( GS_EVENT_MISSION_LOG_SCROLLBACK );
5107 if ((state == GS_STATE_GAME_PLAY) || (state == GS_STATE_DEATH_DIED) || (state == GS_STATE_DEATH_BLEW_UP) || (state == GS_STATE_GAME_PAUSED) ) {
5108 gameseq_post_event( GS_EVENT_MISSION_LOG_SCROLLBACK );
5114 case KEY_ESC | KEY_SHIFTED:
5115 // make sure to quit properly out of multiplayer
5116 if(Game_mode & GM_MULTIPLAYER){
5117 multi_quit_game(PROMPT_NONE);
5120 gameseq_post_event( GS_EVENT_QUIT_GAME );
5125 case KEY_DEBUGGED + KEY_P:
5128 case KEY_PRINT_SCRN:
5130 static int counter = 0;
5135 sprintf( tmp_name, NOX("screen%02d"), counter );
5137 mprintf(( "Dumping screen to '%s'\n", tmp_name ));
5138 gr_print_screen(tmp_name);
5146 case KEY_SHIFTED | KEY_ENTER: {
5148 #if !defined(NDEBUG)
5150 if ( Game_mode & GM_NORMAL ){
5154 // if we're in multiplayer mode, do some special networking
5155 if(Game_mode & GM_MULTIPLAYER){
5156 debug_console(game_do_dc_networking);
5163 if ( Game_mode & GM_NORMAL )
5177 gameseq_post_event(GS_EVENT_QUIT_GAME);
5180 void apply_physics( float damping, float desired_vel, float initial_vel, float t, float * new_vel, float * delta_pos );
5183 void camera_set_position( vector *pos )
5188 void camera_set_orient( matrix *orient )
5190 Camera_orient = *orient;
5193 void camera_set_velocity( vector *vel, int instantaneous )
5195 Camera_desired_velocity.xyz.x = 0.0f;
5196 Camera_desired_velocity.xyz.y = 0.0f;
5197 Camera_desired_velocity.xyz.z = 0.0f;
5199 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.rvec, vel->xyz.x );
5200 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.uvec, vel->xyz.y );
5201 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.fvec, vel->xyz.z );
5203 if ( instantaneous ) {
5204 Camera_velocity = Camera_desired_velocity;
5212 vector new_vel, delta_pos;
5214 apply_physics( Camera_damping, Camera_desired_velocity.xyz.x, Camera_velocity.xyz.x, flFrametime, &new_vel.xyz.x, &delta_pos.xyz.x );
5215 apply_physics( Camera_damping, Camera_desired_velocity.xyz.y, Camera_velocity.xyz.y, flFrametime, &new_vel.xyz.y, &delta_pos.xyz.y );
5216 apply_physics( Camera_damping, Camera_desired_velocity.xyz.z, Camera_velocity.xyz.z, flFrametime, &new_vel.xyz.z, &delta_pos.xyz.z );
5218 Camera_velocity = new_vel;
5220 // mprintf(( "Camera velocity = %.1f,%.1f, %.1f\n", Camera_velocity.xyz.x, Camera_velocity.xyz.y, Camera_velocity.xyz.z ));
5222 vm_vec_add2( &Camera_pos, &delta_pos );
5224 float ot = Camera_time+0.0f;
5226 Camera_time += flFrametime;
5228 if ( (ot < 0.667f) && ( Camera_time >= 0.667f ) ) {
5231 tmp.xyz.z = 4.739f; // always go this fast forward.
5233 // pick x and y velocities so they are always on a
5234 // circle with a 25 m radius.
5236 float tmp_angle = frand()*PI2;
5238 tmp.xyz.x = 22.0f * (float)sin(tmp_angle);
5239 tmp.xyz.y = -22.0f * (float)cos(tmp_angle);
5241 //mprintf(( "Angle = %.1f, vx=%.1f, vy=%.1f\n", tmp_angle, tmp.xyz.x, tmp.xyz.y ));
5243 //mprintf(( "Changing velocity!\n" ));
5244 camera_set_velocity( &tmp, 0 );
5247 if ( (ot < 3.0f ) && ( Camera_time >= 3.0f ) ) {
5248 vector tmp = { 0.0f, 0.0f, 0.0f };
5249 camera_set_velocity( &tmp, 0 );
5254 void end_demo_campaign_do()
5256 #if defined(FS2_DEMO) || defined(FS1_DEMO)
5257 // show upsell screens
5258 demo_upsell_show_screens();
5259 #elif defined(OEM_BUILD)
5260 // show oem upsell screens
5261 oem_upsell_show_screens();
5264 // drop into main hall
5265 gameseq_post_event( GS_EVENT_MAIN_MENU );
5268 // All code to process events. This is the only place
5269 // that you should change the state of the game.
5270 void game_process_event( int current_state, int event )
5272 mprintf(("Got event %s in state %s\n", GS_event_text[event], GS_state_text[current_state]));
5275 case GS_EVENT_SIMULATOR_ROOM:
5276 gameseq_set_state(GS_STATE_SIMULATOR_ROOM);
5279 case GS_EVENT_MAIN_MENU:
5280 gameseq_set_state(GS_STATE_MAIN_MENU);
5283 case GS_EVENT_OPTIONS_MENU:
5284 gameseq_push_state( GS_STATE_OPTIONS_MENU );
5287 case GS_EVENT_BARRACKS_MENU:
5288 gameseq_set_state(GS_STATE_BARRACKS_MENU);
5291 case GS_EVENT_TECH_MENU:
5292 gameseq_set_state(GS_STATE_TECH_MENU);
5295 case GS_EVENT_TRAINING_MENU:
5296 gameseq_set_state(GS_STATE_TRAINING_MENU);
5299 case GS_EVENT_START_GAME:
5300 Select_default_ship = 0;
5301 Player_multi_died_check = -1;
5302 gameseq_set_state(GS_STATE_CMD_BRIEF);
5305 case GS_EVENT_START_BRIEFING:
5306 gameseq_set_state(GS_STATE_BRIEFING);
5309 case GS_EVENT_DEBRIEF:
5310 // did we end the campaign in the main freespace 2 single player campaign?
5312 if(Campaign_ended_in_mission && (Game_mode & GM_CAMPAIGN_MODE) && !stricmp(Campaign.filename, "freespace")) {
5314 if(Campaign_ended_in_mission && (Game_mode & GM_CAMPAIGN_MODE) && !stricmp(Campaign.filename, "freespace2")) {
5316 gameseq_post_event(GS_EVENT_END_CAMPAIGN);
5318 gameseq_set_state(GS_STATE_DEBRIEF);
5321 Player_multi_died_check = -1;
5324 case GS_EVENT_SHIP_SELECTION:
5325 gameseq_set_state( GS_STATE_SHIP_SELECT );
5328 case GS_EVENT_WEAPON_SELECTION:
5329 gameseq_set_state( GS_STATE_WEAPON_SELECT );
5332 case GS_EVENT_ENTER_GAME:
5334 // maybe start recording a demo
5336 demo_start_record("test.fsd");
5340 if (Game_mode & GM_MULTIPLAYER) {
5341 // if we're respawning, make sure we change the view mode so that the hud shows up
5342 if (current_state == GS_STATE_DEATH_BLEW_UP) {
5346 gameseq_set_state(GS_STATE_GAME_PLAY);
5348 gameseq_set_state(GS_STATE_GAME_PLAY, 1);
5351 Player_multi_died_check = -1;
5353 // clear multiplayer button info
5354 extern button_info Multi_ship_status_bi;
5355 memset(&Multi_ship_status_bi, 0, sizeof(button_info));
5357 Start_time = f2fl(timer_get_approx_seconds());
5359 mprintf(("Entering game at time = %7.3f\n", Start_time));
5363 case GS_EVENT_START_GAME_QUICK:
5364 Select_default_ship = 1;
5365 gameseq_post_event(GS_EVENT_ENTER_GAME);
5369 case GS_EVENT_END_GAME:
5370 if ( (current_state == GS_STATE_GAME_PLAY) || (current_state == GS_STATE_DEATH_DIED) ||
5371 (current_state == GS_STATE_DEATH_BLEW_UP) || (current_state == GS_STATE_DEBRIEF) || (current_state == GS_STATE_MULTI_DOGFIGHT_DEBRIEF)) {
5372 gameseq_set_state(GS_STATE_MAIN_MENU);
5377 Player_multi_died_check = -1;
5380 case GS_EVENT_QUIT_GAME:
5381 main_hall_stop_music();
5382 main_hall_stop_ambient();
5383 gameseq_set_state(GS_STATE_QUIT_GAME);
5385 Player_multi_died_check = -1;
5388 case GS_EVENT_GAMEPLAY_HELP:
5389 gameseq_push_state( GS_STATE_GAMEPLAY_HELP );
5392 case GS_EVENT_PAUSE_GAME:
5393 gameseq_push_state(GS_STATE_GAME_PAUSED);
5396 case GS_EVENT_DEBUG_PAUSE_GAME:
5397 gameseq_push_state(GS_STATE_DEBUG_PAUSED);
5400 case GS_EVENT_TRAINING_PAUSE:
5401 gameseq_push_state(GS_STATE_TRAINING_PAUSED);
5404 case GS_EVENT_PREVIOUS_STATE:
5405 gameseq_pop_state();
5408 case GS_EVENT_TOGGLE_FULLSCREEN:
5409 #ifndef HARDWARE_ONLY
5411 if ( gr_screen.mode == GR_SOFTWARE ) {
5412 gr_init( GR_640, GR_DIRECTDRAW );
5413 } else if ( gr_screen.mode == GR_DIRECTDRAW ) {
5414 gr_init( GR_640, GR_SOFTWARE );
5420 case GS_EVENT_TOGGLE_GLIDE:
5422 if ( gr_screen.mode != GR_GLIDE ) {
5423 gr_init( GR_640, GR_GLIDE );
5425 gr_init( GR_640, GR_SOFTWARE );
5430 case GS_EVENT_LOAD_MISSION_MENU:
5431 gameseq_set_state(GS_STATE_LOAD_MISSION_MENU);
5434 case GS_EVENT_MISSION_LOG_SCROLLBACK:
5435 gameseq_push_state( GS_STATE_MISSION_LOG_SCROLLBACK );
5438 case GS_EVENT_HUD_CONFIG:
5439 gameseq_push_state( GS_STATE_HUD_CONFIG );
5442 case GS_EVENT_CONTROL_CONFIG:
5443 gameseq_push_state( GS_STATE_CONTROL_CONFIG );
5446 case GS_EVENT_DEATH_DIED:
5447 gameseq_set_state( GS_STATE_DEATH_DIED );
5450 case GS_EVENT_DEATH_BLEW_UP:
5451 if ( current_state == GS_STATE_DEATH_DIED ) {
5452 gameseq_set_state( GS_STATE_DEATH_BLEW_UP );
5453 event_music_player_death();
5455 // multiplayer clients set their extra check here
5456 if(Game_mode & GM_MULTIPLAYER){
5457 // set the multi died absolute last chance check
5458 Player_multi_died_check = time(NULL);
5461 mprintf(( "Ignoring GS_EVENT_DEATH_BLEW_UP because we're in state %d\n", current_state ));
5465 case GS_EVENT_NEW_CAMPAIGN:
5466 if (!mission_load_up_campaign()){
5467 readyroom_continue_campaign();
5470 Player_multi_died_check = -1;
5473 case GS_EVENT_CAMPAIGN_CHEAT:
5474 if (!mission_load_up_campaign()){
5476 // bash campaign value
5477 extern char Main_hall_campaign_cheat[512];
5480 // look for the mission
5481 for(idx=0; idx<Campaign.num_missions; idx++){
5482 if(!stricmp(Campaign.missions[idx].name, Main_hall_campaign_cheat)){
5483 Campaign.next_mission = idx;
5484 Campaign.prev_mission = idx - 1;
5491 readyroom_continue_campaign();
5494 Player_multi_died_check = -1;
5497 case GS_EVENT_CAMPAIGN_ROOM:
5498 gameseq_set_state(GS_STATE_CAMPAIGN_ROOM);
5501 case GS_EVENT_CMD_BRIEF:
5502 gameseq_set_state(GS_STATE_CMD_BRIEF);
5505 case GS_EVENT_RED_ALERT:
5506 gameseq_set_state(GS_STATE_RED_ALERT);
5509 case GS_EVENT_CREDITS:
5510 gameseq_set_state( GS_STATE_CREDITS );
5513 case GS_EVENT_VIEW_MEDALS:
5514 gameseq_push_state( GS_STATE_VIEW_MEDALS );
5517 case GS_EVENT_SHOW_GOALS:
5518 gameseq_push_state( GS_STATE_SHOW_GOALS ); // use push_state() since we might get to this screen through a variety of states
5521 case GS_EVENT_HOTKEY_SCREEN:
5522 gameseq_push_state( GS_STATE_HOTKEY_SCREEN ); // use push_state() since we might get to this screen through a variety of states
5525 // multiplayer stuff follow these comments
5527 case GS_EVENT_MULTI_JOIN_GAME:
5528 gameseq_set_state( GS_STATE_MULTI_JOIN_GAME );
5531 case GS_EVENT_MULTI_HOST_SETUP:
5532 gameseq_set_state( GS_STATE_MULTI_HOST_SETUP );
5535 case GS_EVENT_MULTI_CLIENT_SETUP:
5536 gameseq_set_state( GS_STATE_MULTI_CLIENT_SETUP );
5539 case GS_EVENT_GOTO_VIEW_CUTSCENES_SCREEN:
5540 gameseq_set_state(GS_STATE_VIEW_CUTSCENES);
5543 case GS_EVENT_MULTI_STD_WAIT:
5544 gameseq_set_state( GS_STATE_MULTI_STD_WAIT );
5547 case GS_EVENT_STANDALONE_MAIN:
5548 gameseq_set_state( GS_STATE_STANDALONE_MAIN );
5551 case GS_EVENT_MULTI_PAUSE:
5552 gameseq_push_state( GS_STATE_MULTI_PAUSED );
5555 case GS_EVENT_INGAME_PRE_JOIN:
5556 gameseq_set_state( GS_STATE_INGAME_PRE_JOIN );
5559 case GS_EVENT_EVENT_DEBUG:
5560 gameseq_push_state(GS_STATE_EVENT_DEBUG);
5563 // Start a warpout where player automatically goes 70 no matter what
5564 // and can't cancel out of it.
5565 case GS_EVENT_PLAYER_WARPOUT_START_FORCED:
5566 Warpout_forced = 1; // If non-zero, bash the player to speed and go through effect
5568 // Same code as in GS_EVENT_PLAYER_WARPOUT_START only ignores current mode
5569 Player->saved_viewer_mode = Viewer_mode;
5570 Player->control_mode = PCM_WARPOUT_STAGE1;
5571 Warpout_sound = snd_play(&Snds[SND_PLAYER_WARP_OUT]);
5572 Warpout_time = 0.0f; // Start timer!
5575 case GS_EVENT_PLAYER_WARPOUT_START:
5576 if ( Player->control_mode != PCM_NORMAL ) {
5577 mprintf(( "Player isn't in normal mode; cannot warp out.\n" ));
5579 Player->saved_viewer_mode = Viewer_mode;
5580 Player->control_mode = PCM_WARPOUT_STAGE1;
5581 Warpout_sound = snd_play(&Snds[SND_PLAYER_WARP_OUT]);
5582 Warpout_time = 0.0f; // Start timer!
5583 Warpout_forced = 0; // If non-zero, bash the player to speed and go through effect
5587 case GS_EVENT_PLAYER_WARPOUT_STOP:
5588 if ( Player->control_mode != PCM_NORMAL ) {
5589 if ( !Warpout_forced ) { // cannot cancel forced warpout
5590 Player->control_mode = PCM_NORMAL;
5591 Viewer_mode = Player->saved_viewer_mode;
5592 hud_subspace_notify_abort();
5593 mprintf(( "Player put back to normal mode.\n" ));
5594 if ( Warpout_sound > -1 ) {
5595 snd_stop( Warpout_sound );
5602 case GS_EVENT_PLAYER_WARPOUT_DONE_STAGE1: // player ship got up to speed
5603 if ( Player->control_mode != PCM_WARPOUT_STAGE1 ) {
5604 gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_STOP );
5605 mprintf(( "Player put back to normal mode, because of invalid sequence in stage1.\n" ));
5607 mprintf(( "Hit target speed. Starting warp effect and moving to stage 2!\n" ));
5608 shipfx_warpout_start( Player_obj );
5609 Player->control_mode = PCM_WARPOUT_STAGE2;
5610 Player->saved_viewer_mode = Viewer_mode;
5611 Viewer_mode |= VM_WARP_CHASE;
5613 vector tmp = Player_obj->pos;
5615 ship_get_eye( &tmp, &tmp_m, Player_obj );
5616 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.rvec, 0.0f );
5617 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.uvec, 0.952f );
5618 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.fvec, -1.782f );
5620 camera_set_position( &tmp );
5621 camera_set_orient( &Player_obj->orient );
5622 vector tmp_vel = { 0.0f, 5.1919f, 14.7f };
5624 //mprintf(( "Rad = %.1f\n", Player_obj->radius ));
5625 camera_set_velocity( &tmp_vel, 1);
5629 case GS_EVENT_PLAYER_WARPOUT_DONE_STAGE2: // player ship got into the warp effect
5630 if ( Player->control_mode != PCM_WARPOUT_STAGE2 ) {
5631 gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_STOP );
5632 mprintf(( "Player put back to normal mode, because of invalid sequence in stage2.\n" ));
5634 mprintf(( "Hit warp effect. Moving to stage 3!\n" ));
5635 Player->control_mode = PCM_WARPOUT_STAGE3;
5639 case GS_EVENT_PLAYER_WARPOUT_DONE: // player ship got through the warp effect
5640 mprintf(( "Player warped out. Going to debriefing!\n" ));
5641 Player->control_mode = PCM_NORMAL;
5642 Viewer_mode = Player->saved_viewer_mode;
5645 // we have a special debriefing screen for multiplayer furballs
5646 if((Game_mode & GM_MULTIPLAYER) && (The_mission.game_type & MISSION_TYPE_MULTI_DOGFIGHT)){
5647 gameseq_post_event(GS_EVENT_MULTI_DOGFIGHT_DEBRIEF);
5649 // do the normal debriefing for all other situations
5651 gameseq_post_event(GS_EVENT_DEBRIEF);
5655 case GS_EVENT_STANDALONE_POSTGAME:
5656 gameseq_set_state(GS_STATE_STANDALONE_POSTGAME);
5659 case GS_EVENT_INITIAL_PLAYER_SELECT:
5660 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5663 case GS_EVENT_GAME_INIT:
5664 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
5665 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5667 // see if the command line option has been set to use the last pilot, and act acoordingly
5668 if( player_select_get_last_pilot() ) {
5669 // always enter the main menu -- do the automatic network startup stuff elsewhere
5670 // so that we still have valid checks for networking modes, etc.
5671 gameseq_set_state(GS_STATE_MAIN_MENU);
5673 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5678 case GS_EVENT_MULTI_MISSION_SYNC:
5679 gameseq_set_state(GS_STATE_MULTI_MISSION_SYNC);
5682 case GS_EVENT_MULTI_START_GAME:
5683 gameseq_set_state(GS_STATE_MULTI_START_GAME);
5686 case GS_EVENT_MULTI_HOST_OPTIONS:
5687 gameseq_set_state(GS_STATE_MULTI_HOST_OPTIONS);
5690 case GS_EVENT_MULTI_DOGFIGHT_DEBRIEF:
5691 gameseq_set_state(GS_STATE_MULTI_DOGFIGHT_DEBRIEF);
5694 case GS_EVENT_TEAM_SELECT:
5695 gameseq_set_state(GS_STATE_TEAM_SELECT);
5698 case GS_EVENT_END_CAMPAIGN:
5699 gameseq_set_state(GS_STATE_END_OF_CAMPAIGN);
5702 case GS_EVENT_END_DEMO:
5703 gameseq_set_state(GS_STATE_END_DEMO);
5706 case GS_EVENT_LOOP_BRIEF:
5707 gameseq_set_state(GS_STATE_LOOP_BRIEF);
5716 // Called when a state is being left.
5717 // The current state is still at old_state, but as soon as
5718 // this function leaves, then the current state will become
5719 // new state. You should never try to change the state
5720 // in here... if you think you need to, you probably really
5721 // need to post an event, not change the state.
5722 void game_leave_state( int old_state, int new_state )
5724 int end_mission = 1;
5726 switch (new_state) {
5727 case GS_STATE_GAME_PAUSED:
5728 case GS_STATE_DEBUG_PAUSED:
5729 case GS_STATE_OPTIONS_MENU:
5730 case GS_STATE_CONTROL_CONFIG:
5731 case GS_STATE_MISSION_LOG_SCROLLBACK:
5732 case GS_STATE_DEATH_DIED:
5733 case GS_STATE_SHOW_GOALS:
5734 case GS_STATE_HOTKEY_SCREEN:
5735 case GS_STATE_MULTI_PAUSED:
5736 case GS_STATE_TRAINING_PAUSED:
5737 case GS_STATE_EVENT_DEBUG:
5738 case GS_STATE_GAMEPLAY_HELP:
5739 end_mission = 0; // these events shouldn't end a mission
5743 switch (old_state) {
5744 case GS_STATE_BRIEFING:
5745 brief_stop_voices();
5746 if ( (new_state != GS_STATE_OPTIONS_MENU) && (new_state != GS_STATE_WEAPON_SELECT)
5747 && (new_state != GS_STATE_SHIP_SELECT) && (new_state != GS_STATE_HOTKEY_SCREEN)
5748 && (new_state != GS_STATE_TEAM_SELECT) ){
5749 common_select_close();
5750 if ( new_state == GS_STATE_MAIN_MENU ) {
5751 freespace_stop_mission();
5755 // COMMAND LINE OPTION
5756 if (Cmdline_multi_stream_chat_to_file){
5757 cfwrite_string(NOX("-------------------------------------------\n"),Multi_chat_stream);
5758 cfclose(Multi_chat_stream);
5762 case GS_STATE_DEBRIEF:
5763 if ( (new_state != GS_STATE_VIEW_MEDALS) && (new_state != GS_STATE_OPTIONS_MENU) ) {
5768 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
5769 multi_df_debrief_close();
5772 case GS_STATE_LOAD_MISSION_MENU:
5773 mission_load_menu_close();
5776 case GS_STATE_SIMULATOR_ROOM:
5780 case GS_STATE_CAMPAIGN_ROOM:
5781 campaign_room_close();
5784 case GS_STATE_CMD_BRIEF:
5785 if (new_state == GS_STATE_OPTIONS_MENU) {
5790 if (new_state == GS_STATE_MAIN_MENU)
5791 freespace_stop_mission();
5796 case GS_STATE_RED_ALERT:
5800 case GS_STATE_SHIP_SELECT:
5801 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_WEAPON_SELECT &&
5802 new_state != GS_STATE_HOTKEY_SCREEN &&
5803 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_TEAM_SELECT) {
5804 common_select_close();
5805 if ( new_state == GS_STATE_MAIN_MENU ) {
5806 freespace_stop_mission();
5811 case GS_STATE_WEAPON_SELECT:
5812 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_SHIP_SELECT &&
5813 new_state != GS_STATE_HOTKEY_SCREEN &&
5814 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_TEAM_SELECT) {
5815 common_select_close();
5816 if ( new_state == GS_STATE_MAIN_MENU ) {
5817 freespace_stop_mission();
5822 case GS_STATE_TEAM_SELECT:
5823 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_SHIP_SELECT &&
5824 new_state != GS_STATE_HOTKEY_SCREEN &&
5825 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_WEAPON_SELECT) {
5826 common_select_close();
5827 if ( new_state == GS_STATE_MAIN_MENU ) {
5828 freespace_stop_mission();
5833 case GS_STATE_MAIN_MENU:
5834 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
5841 case GS_STATE_OPTIONS_MENU:
5842 //game_start_time();
5843 if(new_state == GS_STATE_MULTI_JOIN_GAME){
5844 multi_join_clear_game_list();
5846 options_menu_close();
5849 case GS_STATE_BARRACKS_MENU:
5850 if(new_state != GS_STATE_VIEW_MEDALS){
5855 case GS_STATE_MISSION_LOG_SCROLLBACK:
5856 hud_scrollback_close();
5859 case GS_STATE_TRAINING_MENU:
5860 training_menu_close();
5863 case GS_STATE_GAME_PLAY:
5864 if ( !(Game_mode & GM_STANDALONE_SERVER) ) {
5865 player_save_target_and_weapon_link_prefs();
5866 game_stop_looped_sounds();
5869 sound_env_disable();
5870 joy_ff_stop_effects();
5872 // stop game time under certain conditions
5873 if ( end_mission || (Game_mode & GM_NORMAL) || ((Game_mode & GM_MULTIPLAYER) && (new_state == GS_STATE_MULTI_PAUSED)) ){
5878 // shut down any recording or playing demos
5883 // when in multiplayer and going back to the main menu, send a leave game packet
5884 // right away (before calling stop mission). stop_mission was taking to long to
5885 // close mission down and I want people to get notified ASAP.
5886 if ( (Game_mode & GM_MULTIPLAYER) && (new_state == GS_STATE_MAIN_MENU) ){
5887 multi_quit_game(PROMPT_NONE);
5890 freespace_stop_mission();
5891 Game_time_compression = F1_0;
5895 case GS_STATE_TECH_MENU:
5899 case GS_STATE_TRAINING_PAUSED:
5900 Training_num_lines = 0;
5901 // fall through to GS_STATE_GAME_PAUSED
5903 case GS_STATE_GAME_PAUSED:
5905 if ( end_mission ) {
5910 case GS_STATE_DEBUG_PAUSED:
5913 pause_debug_close();
5917 case GS_STATE_HUD_CONFIG:
5921 // join/start a game
5922 case GS_STATE_MULTI_JOIN_GAME:
5923 if(new_state != GS_STATE_OPTIONS_MENU){
5924 multi_join_game_close();
5928 case GS_STATE_MULTI_HOST_SETUP:
5929 case GS_STATE_MULTI_CLIENT_SETUP:
5930 // if this is just the host going into the options screen, don't do anything
5931 if((new_state == GS_STATE_MULTI_HOST_OPTIONS) || (new_state == GS_STATE_OPTIONS_MENU)){
5935 // close down the proper state
5936 if(old_state == GS_STATE_MULTI_HOST_SETUP){
5937 multi_create_game_close();
5939 multi_game_client_setup_close();
5942 // COMMAND LINE OPTION
5943 if (Cmdline_multi_stream_chat_to_file){
5944 if( (new_state != GS_STATE_TEAM_SELECT) && (Multi_chat_stream!=NULL) ) {
5945 cfwrite_string(NOX("-------------------------------------------\n"),Multi_chat_stream);
5946 cfclose(Multi_chat_stream);
5951 case GS_STATE_CONTROL_CONFIG:
5952 control_config_close();
5955 case GS_STATE_DEATH_DIED:
5956 Game_mode &= ~GM_DEAD_DIED;
5958 // early end while respawning or blowing up in a multiplayer game
5959 if((Game_mode & GM_MULTIPLAYER) && ((new_state == GS_STATE_DEBRIEF) || (new_state == GS_STATE_MULTI_DOGFIGHT_DEBRIEF)) ){
5961 freespace_stop_mission();
5965 case GS_STATE_DEATH_BLEW_UP:
5966 Game_mode &= ~GM_DEAD_BLEW_UP;
5968 // for single player, we might reload mission, etc. For multiplayer, look at my new state
5969 // to determine if I should do anything.
5970 if ( !(Game_mode & GM_MULTIPLAYER) ) {
5972 freespace_stop_mission();
5975 // if we are not respawing as an observer or as a player, our new state will not
5976 // be gameplay state.
5977 if ( (new_state != GS_STATE_GAME_PLAY) && (new_state != GS_STATE_MULTI_PAUSED) ) {
5978 game_stop_time(); // hasn't been called yet!!
5979 freespace_stop_mission();
5985 case GS_STATE_CREDITS:
5989 case GS_STATE_VIEW_MEDALS:
5993 case GS_STATE_SHOW_GOALS:
5994 mission_show_goals_close();
5997 case GS_STATE_HOTKEY_SCREEN:
5998 if ( new_state != GS_STATE_OPTIONS_MENU ) {
5999 mission_hotkey_close();
6003 case GS_STATE_MULTI_MISSION_SYNC:
6004 // if we're moving into the options menu, don't do anything
6005 if(new_state == GS_STATE_OPTIONS_MENU){
6009 Assert( Game_mode & GM_MULTIPLAYER );
6011 if ( new_state == GS_STATE_GAME_PLAY ){
6012 // palette_restore_palette();
6014 // change a couple of flags to indicate our state!!!
6015 Net_player->state = NETPLAYER_STATE_IN_MISSION;
6016 send_netplayer_update_packet();
6018 // set the game mode
6019 Game_mode |= GM_IN_MISSION;
6023 case GS_STATE_VIEW_CUTSCENES:
6024 cutscenes_screen_close();
6027 case GS_STATE_MULTI_STD_WAIT:
6028 multi_standalone_wait_close();
6031 case GS_STATE_STANDALONE_MAIN:
6032 standalone_main_close();
6033 if(new_state == GS_STATE_MULTI_STD_WAIT){
6034 init_multiplayer_stats();
6038 case GS_STATE_MULTI_PAUSED:
6039 // if ( end_mission ){
6044 case GS_STATE_INGAME_PRE_JOIN:
6045 multi_ingame_select_close();
6048 case GS_STATE_STANDALONE_POSTGAME:
6049 multi_standalone_postgame_close();
6052 case GS_STATE_INITIAL_PLAYER_SELECT:
6053 player_select_close();
6056 case GS_STATE_MULTI_START_GAME:
6057 multi_start_game_close();
6060 case GS_STATE_MULTI_HOST_OPTIONS:
6061 multi_host_options_close();
6064 case GS_STATE_END_OF_CAMPAIGN:
6065 mission_campaign_end_close();
6068 case GS_STATE_LOOP_BRIEF:
6074 // Called when a state is being entered.
6075 // The current state is set to the state we're entering at
6076 // this point, and old_state is set to the state we're coming
6077 // from. You should never try to change the state
6078 // in here... if you think you need to, you probably really
6079 // need to post an event, not change the state.
6081 void game_enter_state( int old_state, int new_state )
6083 switch (new_state) {
6084 case GS_STATE_MAIN_MENU:
6085 // in multiplayer mode, be sure that we are not doing networking anymore.
6086 if ( Game_mode & GM_MULTIPLAYER ) {
6087 Assert( Net_player != NULL );
6088 Net_player->flags &= ~NETINFO_FLAG_DO_NETWORKING;
6091 Game_time_compression = F1_0;
6093 // determine which ship this guy is currently based on
6094 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
6097 if (Player->on_bastion) {
6105 case GS_STATE_BRIEFING:
6106 main_hall_stop_music();
6107 main_hall_stop_ambient();
6109 if (Game_mode & GM_NORMAL) {
6110 // AL: Don't call freespace_start_mission() if re-entering from ship or weapon select
6111 // MWA: or from options or hotkey screens
6112 // JH: or if the command brief state already did this
6113 if ( (old_state != GS_STATE_OPTIONS_MENU) && (old_state != GS_STATE_HOTKEY_SCREEN)
6114 && (old_state != GS_STATE_SHIP_SELECT) && (old_state != GS_STATE_WEAPON_SELECT)
6115 && (old_state != GS_STATE_CMD_BRIEF) ) {
6116 if ( !game_start_mission() ) // this should put us into a new state on failure!
6120 // maybe play a movie before the briefing. don't play if entering briefing screen from ship or weapon select.
6121 if ( (old_state == GS_STATE_DEBRIEF) || (old_state == GS_STATE_SIMULATOR_ROOM) || (old_state == GS_STATE_MAIN_MENU))
6122 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
6124 Game_time_compression = F1_0;
6126 if ( red_alert_mission() ) {
6127 gameseq_post_event(GS_EVENT_RED_ALERT);
6134 case GS_STATE_DEBRIEF:
6135 game_stop_looped_sounds();
6136 mission_goal_fail_incomplete(); // fail all incomplete goals before entering debriefing
6137 if ( (old_state != GS_STATE_VIEW_MEDALS) && (old_state != GS_STATE_OPTIONS_MENU) ){
6142 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
6143 multi_df_debrief_init();
6146 case GS_STATE_LOAD_MISSION_MENU:
6147 mission_load_menu_init();
6150 case GS_STATE_SIMULATOR_ROOM:
6154 case GS_STATE_CAMPAIGN_ROOM:
6155 campaign_room_init();
6158 case GS_STATE_RED_ALERT:
6159 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
6163 case GS_STATE_CMD_BRIEF: {
6164 int team_num = 0; // team number used as index for which cmd brief to use.
6166 if (old_state == GS_STATE_OPTIONS_MENU) {
6170 main_hall_stop_music();
6171 main_hall_stop_ambient();
6173 if (Game_mode & GM_NORMAL) {
6174 // AL: Don't call freespace_start_mission() if re-entering from ship or weapon select
6175 // MWA: or from options or hotkey screens
6176 // JH: or if the command brief state already did this
6177 if ( (old_state != GS_STATE_OPTIONS_MENU) && (old_state != GS_STATE_HOTKEY_SCREEN)
6178 && (old_state != GS_STATE_SHIP_SELECT) && (old_state != GS_STATE_WEAPON_SELECT) ) {
6179 if ( !game_start_mission() ) // this should put us into a new state on failure!
6184 // maybe play a movie before the briefing. don't play if entering briefing screen from ship or weapon select.
6185 if ( (old_state == GS_STATE_DEBRIEF) || (old_state == GS_STATE_SIMULATOR_ROOM) || (old_state == GS_STATE_MAIN_MENU))
6186 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
6188 cmd_brief_init(team_num);
6194 case GS_STATE_SHIP_SELECT:
6198 case GS_STATE_WEAPON_SELECT:
6199 weapon_select_init();
6202 case GS_STATE_TEAM_SELECT:
6206 case GS_STATE_GAME_PAUSED:
6211 case GS_STATE_DEBUG_PAUSED:
6212 // game_stop_time();
6213 // os_set_title("FreeSpace - PAUSED");
6216 case GS_STATE_TRAINING_PAUSED:
6223 case GS_STATE_OPTIONS_MENU:
6225 options_menu_init();
6228 case GS_STATE_GAME_PLAY:
6229 // coming from the gameplay state or the main menu, we might need to load the mission
6230 if ( (Game_mode & GM_NORMAL) && ((old_state == GS_STATE_MAIN_MENU) || (old_state == GS_STATE_GAME_PLAY) || (old_state == GS_STATE_DEATH_BLEW_UP)) ) {
6231 if ( !game_start_mission() ) // this should put us into a new state.
6236 // if we are coming from the briefing, ship select, weapons loadout, or main menu (in the
6237 // case of quick start), then do bitmap loads, etc Don't do any of the loading stuff
6238 // if we are in multiplayer -- this stuff is all handled in the multi-wait section
6239 if ( !(Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_BRIEFING) || (old_state == GS_STATE_SHIP_SELECT) ||
6240 (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) ) {
6241 // JAS: Used to do all paging here.
6245 HUD_printf("Skill level is set to ** %s **", Skill_level_names(Game_skill_level));
6249 main_hall_stop_music();
6250 main_hall_stop_ambient();
6251 event_music_first_pattern(); // start the first pattern
6254 // special code that restores player ship selection and weapons loadout when doing a quick start
6255 if ( !(Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_MAIN_MENU) || (old_state == GS_STATE_DEATH_BLEW_UP) || (old_state == GS_STATE_GAME_PLAY) ) {
6256 if ( !stricmp(Player_loadout.filename, Game_current_mission_filename) ) {
6257 wss_direct_restore_loadout();
6261 // single-player, quick-start after just died... we need to set weapon linking and kick off the event music
6262 if (!(Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_DEATH_BLEW_UP) ) {
6263 event_music_first_pattern(); // start the first pattern
6266 if ( !(Game_mode & GM_STANDALONE_SERVER) && (old_state != GS_STATE_GAME_PAUSED) && (old_state != GS_STATE_MULTI_PAUSED) ) {
6267 event_music_first_pattern(); // start the first pattern
6269 player_restore_target_and_weapon_link_prefs();
6271 Game_mode |= GM_IN_MISSION;
6274 // required to truely make mouse deltas zeroed in debug mouse code
6275 void mouse_force_pos(int x, int y);
6276 if (!Is_standalone) {
6277 mouse_force_pos(gr_screen.max_w / 2, gr_screen.max_h / 2);
6283 // only start time if in single player, or coming from multi wait state
6286 (Game_mode & GM_NORMAL) &&
6287 (old_state != GS_STATE_VIEW_CUTSCENES)
6289 (Game_mode & GM_MULTIPLAYER) && (
6290 (old_state == GS_STATE_MULTI_PAUSED) ||
6291 (old_state == GS_STATE_MULTI_MISSION_SYNC)
6297 // when coming from the multi paused state, reset the timestamps
6298 if ( (Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_MULTI_PAUSED) ){
6299 multi_reset_timestamps();
6302 if ((Game_mode & GM_MULTIPLAYER) && (old_state != GS_STATE_DEATH_BLEW_UP) ) {
6303 // initialize all object update details
6304 multi_oo_gameplay_init();
6307 // under certain circumstances, the server should reset the object update rate limiting stuff
6308 if( ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)) &&
6309 (old_state == GS_STATE_MULTI_PAUSED) || (old_state == GS_STATE_MULTI_MISSION_SYNC) ){
6311 // reinitialize the rate limiting system for all clients
6312 multi_oo_rate_init_all();
6315 // multiplayer clients should always re-initialize their control info rate limiting system
6316 if((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER)){
6317 multi_oo_rate_init_all();
6321 if(Game_mode & GM_MULTIPLAYER){
6322 multi_ping_reset_players();
6325 Game_subspace_effect = 0;
6326 if (The_mission.flags & MISSION_FLAG_SUBSPACE) {
6327 Game_subspace_effect = 1;
6328 if( !(Game_mode & GM_STANDALONE_SERVER) ){
6329 game_start_subspace_ambient_sound();
6333 sound_env_set(&Game_sound_env);
6334 joy_ff_mission_init(Ship_info[Player_ship->ship_info_index].rotation_time);
6336 // clear multiplayer button info i
6337 extern button_info Multi_ship_status_bi;
6338 memset(&Multi_ship_status_bi, 0, sizeof(button_info));
6341 case GS_STATE_HUD_CONFIG:
6345 case GS_STATE_MULTI_JOIN_GAME:
6346 multi_join_clear_game_list();
6348 if (old_state != GS_STATE_OPTIONS_MENU) {
6349 multi_join_game_init();
6354 case GS_STATE_MULTI_HOST_SETUP:
6355 // don't reinitialize if we're coming back from the host options screen
6356 if ((old_state != GS_STATE_MULTI_HOST_OPTIONS) && (old_state != GS_STATE_OPTIONS_MENU)) {
6357 multi_create_game_init();
6362 case GS_STATE_MULTI_CLIENT_SETUP:
6363 if (old_state != GS_STATE_OPTIONS_MENU) {
6364 multi_game_client_setup_init();
6369 case GS_STATE_CONTROL_CONFIG:
6370 control_config_init();
6373 case GS_STATE_TECH_MENU:
6377 case GS_STATE_BARRACKS_MENU:
6378 if(old_state != GS_STATE_VIEW_MEDALS){
6383 case GS_STATE_MISSION_LOG_SCROLLBACK:
6384 hud_scrollback_init();
6387 case GS_STATE_DEATH_DIED:
6388 Player_died_time = timestamp(10);
6390 if(!(Game_mode & GM_MULTIPLAYER)){
6391 player_show_death_message();
6393 Game_mode |= GM_DEAD_DIED;
6396 case GS_STATE_DEATH_BLEW_UP:
6397 if ( !popupdead_is_active() ) {
6398 Player_ai->target_objnum = -1;
6401 // stop any local EMP effect
6404 Players[Player_num].flags &= ~PLAYER_FLAGS_AUTO_TARGETING; // Prevent immediate switch to a hostile ship.
6405 Game_mode |= GM_DEAD_BLEW_UP;
6406 Show_viewing_from_self = 0;
6408 // timestamp how long we should wait before displaying the died popup
6409 if ( !popupdead_is_active() ) {
6410 Player_died_popup_wait = timestamp(PLAYER_DIED_POPUP_WAIT);
6414 case GS_STATE_GAMEPLAY_HELP:
6415 gameplay_help_init();
6418 case GS_STATE_CREDITS:
6419 main_hall_stop_music();
6420 main_hall_stop_ambient();
6424 case GS_STATE_VIEW_MEDALS:
6425 medal_main_init(Player);
6428 case GS_STATE_SHOW_GOALS:
6429 mission_show_goals_init();
6432 case GS_STATE_HOTKEY_SCREEN:
6433 mission_hotkey_init();
6436 case GS_STATE_MULTI_MISSION_SYNC:
6437 // if we're coming from the options screen, don't do any
6438 if(old_state == GS_STATE_OPTIONS_MENU){
6442 switch(Multi_sync_mode){
6443 case MULTI_SYNC_PRE_BRIEFING:
6444 // if moving from game forming to the team select state
6447 case MULTI_SYNC_POST_BRIEFING:
6448 // if moving from briefing into the mission itself
6451 // tell everyone that we're now loading data
6452 Net_player->state = NETPLAYER_STATE_DATA_LOAD;
6453 send_netplayer_update_packet();
6455 // JAS: Used to do all paging here!!!!
6457 Net_player->state = NETPLAYER_STATE_WAITING;
6458 send_netplayer_update_packet();
6460 Game_time_compression = F1_0;
6462 case MULTI_SYNC_INGAME:
6468 case GS_STATE_VIEW_CUTSCENES:
6469 cutscenes_screen_init();
6472 case GS_STATE_MULTI_STD_WAIT:
6473 multi_standalone_wait_init();
6476 case GS_STATE_STANDALONE_MAIN:
6477 // don't initialize if we're coming from one of these 2 states unless there are no
6478 // players left (reset situation)
6479 if((old_state != GS_STATE_STANDALONE_POSTGAME) || multi_endgame_ending()){
6480 standalone_main_init();
6484 case GS_STATE_MULTI_PAUSED:
6488 case GS_STATE_INGAME_PRE_JOIN:
6489 multi_ingame_select_init();
6492 case GS_STATE_STANDALONE_POSTGAME:
6493 multi_standalone_postgame_init();
6496 case GS_STATE_INITIAL_PLAYER_SELECT:
6497 player_select_init();
6500 case GS_STATE_MULTI_START_GAME:
6501 multi_start_game_init();
6504 case GS_STATE_MULTI_HOST_OPTIONS:
6505 multi_host_options_init();
6508 case GS_STATE_END_OF_CAMPAIGN:
6509 mission_campaign_end_init();
6512 case GS_STATE_LOOP_BRIEF:
6519 // do stuff that may need to be done regardless of state
6520 void game_do_state_common(int state,int no_networking)
6522 game_maybe_draw_mouse(flFrametime); // determine if to draw the mouse this frame
6523 snd_do_frame(); // update sound system
6524 event_music_do_frame(); // music needs to play across many states
6526 multi_log_process();
6528 if (no_networking) {
6532 // maybe do a multiplayer frame based on game mode and state type
6533 if (Game_mode & GM_MULTIPLAYER) {
6535 case GS_STATE_OPTIONS_MENU:
6536 case GS_STATE_GAMEPLAY_HELP:
6537 case GS_STATE_HOTKEY_SCREEN:
6538 case GS_STATE_HUD_CONFIG:
6539 case GS_STATE_CONTROL_CONFIG:
6540 case GS_STATE_MISSION_LOG_SCROLLBACK:
6541 case GS_STATE_SHOW_GOALS:
6542 case GS_STATE_VIEW_CUTSCENES:
6543 case GS_STATE_EVENT_DEBUG:
6544 multi_maybe_do_frame();
6548 game_do_networking();
6552 // Called once a frame.
6553 // You should never try to change the state
6554 // in here... if you think you need to, you probably really
6555 // need to post an event, not change the state.
6556 int Game_do_state_should_skip = 0;
6557 void game_do_state(int state)
6559 // always lets the do_state_common() function determine if the state should be skipped
6560 Game_do_state_should_skip = 0;
6562 // legal to set the should skip state anywhere in this function
6563 game_do_state_common(state); // do stuff that may need to be done regardless of state
6565 if(Game_do_state_should_skip){
6570 case GS_STATE_MAIN_MENU:
6571 game_set_frametime(GS_STATE_MAIN_MENU);
6572 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
6575 main_hall_do(flFrametime);
6579 case GS_STATE_OPTIONS_MENU:
6580 game_set_frametime(GS_STATE_OPTIONS_MENU);
6581 options_menu_do_frame(flFrametime);
6584 case GS_STATE_BARRACKS_MENU:
6585 game_set_frametime(GS_STATE_BARRACKS_MENU);
6586 barracks_do_frame(flFrametime);
6589 case GS_STATE_TRAINING_MENU:
6590 game_set_frametime(GS_STATE_TRAINING_MENU);
6591 training_menu_do_frame(flFrametime);
6594 case GS_STATE_TECH_MENU:
6595 game_set_frametime(GS_STATE_TECH_MENU);
6596 techroom_do_frame(flFrametime);
6599 case GS_STATE_GAMEPLAY_HELP:
6600 game_set_frametime(GS_STATE_GAMEPLAY_HELP);
6601 gameplay_help_do_frame(flFrametime);
6604 case GS_STATE_GAME_PLAY: // do stuff that should be done during gameplay
6608 case GS_STATE_GAME_PAUSED:
6612 case GS_STATE_DEBUG_PAUSED:
6614 game_set_frametime(GS_STATE_DEBUG_PAUSED);
6619 case GS_STATE_TRAINING_PAUSED:
6620 game_training_pause_do();
6623 case GS_STATE_LOAD_MISSION_MENU:
6624 game_set_frametime(GS_STATE_LOAD_MISSION_MENU);
6625 mission_load_menu_do();
6628 case GS_STATE_BRIEFING:
6629 game_set_frametime(GS_STATE_BRIEFING);
6630 brief_do_frame(flFrametime);
6633 case GS_STATE_DEBRIEF:
6634 game_set_frametime(GS_STATE_DEBRIEF);
6635 debrief_do_frame(flFrametime);
6638 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
6639 game_set_frametime(GS_STATE_MULTI_DOGFIGHT_DEBRIEF);
6640 multi_df_debrief_do();
6643 case GS_STATE_SHIP_SELECT:
6644 game_set_frametime(GS_STATE_SHIP_SELECT);
6645 ship_select_do(flFrametime);
6648 case GS_STATE_WEAPON_SELECT:
6649 game_set_frametime(GS_STATE_WEAPON_SELECT);
6650 weapon_select_do(flFrametime);
6653 case GS_STATE_MISSION_LOG_SCROLLBACK:
6654 game_set_frametime(GS_STATE_MISSION_LOG_SCROLLBACK);
6655 hud_scrollback_do_frame(flFrametime);
6658 case GS_STATE_HUD_CONFIG:
6659 game_set_frametime(GS_STATE_HUD_CONFIG);
6660 hud_config_do_frame(flFrametime);
6663 case GS_STATE_MULTI_JOIN_GAME:
6664 game_set_frametime(GS_STATE_MULTI_JOIN_GAME);
6665 multi_join_game_do_frame();
6668 case GS_STATE_MULTI_HOST_SETUP:
6669 game_set_frametime(GS_STATE_MULTI_HOST_SETUP);
6670 multi_create_game_do();
6673 case GS_STATE_MULTI_CLIENT_SETUP:
6674 game_set_frametime(GS_STATE_MULTI_CLIENT_SETUP);
6675 multi_game_client_setup_do_frame();
6678 case GS_STATE_CONTROL_CONFIG:
6679 game_set_frametime(GS_STATE_CONTROL_CONFIG);
6680 control_config_do_frame(flFrametime);
6683 case GS_STATE_DEATH_DIED:
6687 case GS_STATE_DEATH_BLEW_UP:
6691 case GS_STATE_SIMULATOR_ROOM:
6692 game_set_frametime(GS_STATE_SIMULATOR_ROOM);
6693 sim_room_do_frame(flFrametime);
6696 case GS_STATE_CAMPAIGN_ROOM:
6697 game_set_frametime(GS_STATE_CAMPAIGN_ROOM);
6698 campaign_room_do_frame(flFrametime);
6701 case GS_STATE_RED_ALERT:
6702 game_set_frametime(GS_STATE_RED_ALERT);
6703 red_alert_do_frame(flFrametime);
6706 case GS_STATE_CMD_BRIEF:
6707 game_set_frametime(GS_STATE_CMD_BRIEF);
6708 cmd_brief_do_frame(flFrametime);
6711 case GS_STATE_CREDITS:
6712 game_set_frametime(GS_STATE_CREDITS);
6713 credits_do_frame(flFrametime);
6716 case GS_STATE_VIEW_MEDALS:
6717 game_set_frametime(GS_STATE_VIEW_MEDALS);
6721 case GS_STATE_SHOW_GOALS:
6722 game_set_frametime(GS_STATE_SHOW_GOALS);
6723 mission_show_goals_do_frame(flFrametime);
6726 case GS_STATE_HOTKEY_SCREEN:
6727 game_set_frametime(GS_STATE_HOTKEY_SCREEN);
6728 mission_hotkey_do_frame(flFrametime);
6731 case GS_STATE_VIEW_CUTSCENES:
6732 game_set_frametime(GS_STATE_VIEW_CUTSCENES);
6733 cutscenes_screen_do_frame();
6736 case GS_STATE_MULTI_STD_WAIT:
6737 game_set_frametime(GS_STATE_STANDALONE_MAIN);
6738 multi_standalone_wait_do();
6741 case GS_STATE_STANDALONE_MAIN:
6742 game_set_frametime(GS_STATE_STANDALONE_MAIN);
6743 standalone_main_do();
6746 case GS_STATE_MULTI_PAUSED:
6747 game_set_frametime(GS_STATE_MULTI_PAUSED);
6751 case GS_STATE_TEAM_SELECT:
6752 game_set_frametime(GS_STATE_TEAM_SELECT);
6756 case GS_STATE_INGAME_PRE_JOIN:
6757 game_set_frametime(GS_STATE_INGAME_PRE_JOIN);
6758 multi_ingame_select_do();
6761 case GS_STATE_EVENT_DEBUG:
6763 game_set_frametime(GS_STATE_EVENT_DEBUG);
6764 game_show_event_debug(flFrametime);
6768 case GS_STATE_STANDALONE_POSTGAME:
6769 game_set_frametime(GS_STATE_STANDALONE_POSTGAME);
6770 multi_standalone_postgame_do();
6773 case GS_STATE_INITIAL_PLAYER_SELECT:
6774 game_set_frametime(GS_STATE_INITIAL_PLAYER_SELECT);
6778 case GS_STATE_MULTI_MISSION_SYNC:
6779 game_set_frametime(GS_STATE_MULTI_MISSION_SYNC);
6783 case GS_STATE_MULTI_START_GAME:
6784 game_set_frametime(GS_STATE_MULTI_START_GAME);
6785 multi_start_game_do();
6788 case GS_STATE_MULTI_HOST_OPTIONS:
6789 game_set_frametime(GS_STATE_MULTI_HOST_OPTIONS);
6790 multi_host_options_do();
6793 case GS_STATE_END_OF_CAMPAIGN:
6794 mission_campaign_end_do();
6797 case GS_STATE_END_DEMO:
6798 game_set_frametime(GS_STATE_END_DEMO);
6799 end_demo_campaign_do();
6802 case GS_STATE_LOOP_BRIEF:
6803 game_set_frametime(GS_STATE_LOOP_BRIEF);
6807 } // end switch(gs_current_state)
6811 // return 0 if there is enough RAM to run FreeSpace, otherwise return -1
6812 int game_do_ram_check(int ram_in_bytes)
6814 if ( ram_in_bytes < 30*1024*1024 ) {
6815 int allowed_to_run = 1;
6816 if ( ram_in_bytes < 25*1024*1024 ) {
6821 int Freespace_total_ram_MB;
6822 Freespace_total_ram_MB = fl2i(ram_in_bytes/(1024*1024));
6824 if ( allowed_to_run ) {
6826 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);
6831 msgbox_rval = MessageBox( NULL, tmp, XSTR( "Not Enough RAM", 194), MB_OKCANCEL );
6832 if ( msgbox_rval == IDCANCEL ) {
6839 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);
6841 MessageBox( NULL, tmp, XSTR( "Not Enough RAM", 194), MB_OK );
6852 // Check if there is a freespace.exe in the /update directory (relative to where fs.exe is installed).
6853 // If so, copy it over and remove the update directory.
6854 void game_maybe_update_launcher(char *exe_dir)
6857 char src_filename[MAX_PATH];
6858 char dest_filename[MAX_PATH];
6860 strcpy(src_filename, exe_dir);
6861 strcat(src_filename, NOX("\\update\\freespace.exe"));
6863 strcpy(dest_filename, exe_dir);
6864 strcat(dest_filename, NOX("\\freespace.exe"));
6866 // see if src_filename exists
6868 fp = fopen(src_filename, "rb");
6874 SetFileAttributes(dest_filename, FILE_ATTRIBUTE_NORMAL);
6876 // copy updated freespace.exe to freespace exe dir
6877 if ( CopyFile(src_filename, dest_filename, 0) == 0 ) {
6878 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 );
6882 // delete the file in the update directory
6883 DeleteFile(src_filename);
6885 // safe to assume directory is empty, since freespace.exe should only be the file ever in the update dir
6886 char update_dir[MAX_PATH];
6887 strcpy(update_dir, exe_dir);
6888 strcat(update_dir, NOX("\\update"));
6889 RemoveDirectory(update_dir);
6895 void game_spew_pof_info_sub(int model_num, polymodel *pm, int sm, CFILE *out, int *out_total, int *out_destroyed_total)
6899 int sub_total_destroyed = 0;
6903 // get the total for all his children
6904 for (i=pm->submodel[sm].first_child; i>-1; i = pm->submodel[i].next_sibling ) {
6905 game_spew_pof_info_sub(model_num, pm, i, out, &sub_total, &sub_total_destroyed);
6908 // find the # of faces for this _individual_ object
6909 total = submodel_get_num_polys(model_num, sm);
6910 if(strstr(pm->submodel[sm].name, "-destroyed")){
6911 sub_total_destroyed = total;
6915 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[sm].name, total);
6918 *out_total += total + sub_total;
6919 *out_destroyed_total += sub_total_destroyed;
6922 #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);
6923 void game_spew_pof_info()
6925 char *pof_list[1000];
6928 int idx, model_num, i, j;
6930 int total, root_total, model_total, destroyed_total, counted;
6934 num_files = cf_get_file_list(1000, pof_list, CF_TYPE_MODELS, "*.pof");
6936 // spew info on all the pofs
6942 out = cfopen("pofspew.txt", "wt", CFILE_NORMAL, CF_TYPE_DATA);
6947 for(idx=0; idx<num_files; idx++, counted++){
6948 sprintf(str, "%s.pof", pof_list[idx]);
6949 model_num = model_load(str, 0, NULL);
6951 pm = model_get(model_num);
6953 // if we have a real model
6958 // go through and print all raw submodels
6959 cfputs("RAW\n", out);
6962 for (i=0; i<pm->n_models; i++) {
6963 total = submodel_get_num_polys(model_num, i);
6965 model_total += total;
6966 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[i].name, total);
6969 sprintf(str, "Model total %d\n", model_total);
6972 // now go through and do it by LOD
6973 cfputs("BY LOD\n\n", out);
6974 for(i=0; i<pm->n_detail_levels; i++){
6975 sprintf(str, "LOD %d\n", i);
6979 root_total = submodel_get_num_polys(model_num, pm->detail[i] );
6981 destroyed_total = 0;
6982 for (j=pm->submodel[pm->detail[i]].first_child; j>-1; j = pm->submodel[j].next_sibling ) {
6983 game_spew_pof_info_sub(model_num, pm, j, out, &total, &destroyed_total);
6986 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[pm->detail[i]].name, root_total);
6989 sprintf(str, "TOTAL: %d\n", total + root_total);
6991 sprintf(str, "TOTAL not counting destroyed faces %d\n", (total + root_total) - destroyed_total);
6993 sprintf(str, "TOTAL destroyed faces %d\n\n", destroyed_total);
6996 cfputs("------------------------------------------------------------------------\n\n", out);
7000 if(counted >= MAX_POLYGON_MODELS - 5){
7013 game_spew_pof_info();
7016 int PASCAL WinMainSub(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow)
7021 // Don't let more than one instance of Freespace run.
7022 HWND hwnd = FindWindow( NOX( "FreeSpaceClass" ), NULL );
7024 SetForegroundWindow(hwnd);
7029 // Find out how much RAM is on this machine
7032 ms.dwLength = sizeof(MEMORYSTATUS);
7033 GlobalMemoryStatus(&ms);
7034 Freespace_total_ram = ms.dwTotalPhys;
7036 if ( game_do_ram_check(Freespace_total_ram) == -1 ) {
7040 if ( ms.dwTotalVirtual < 1024 ) {
7041 MessageBox( NULL, XSTR( "FreeSpace requires virtual memory to run.\r\n", 196), XSTR( "No Virtual Memory", 197), MB_OK );
7045 if (!vm_init(24*1024*1024)) {
7046 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 );
7050 char *tmp_mem = (char *) malloc(16 * 1024 * 1024);
7052 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);
7060 /* this code doesn't work, and we will hit an error about being unable to load the direct draw
7061 dll before we get here anyway if it's not installed (unless we load it manually, which doesn't
7062 seem worth bothering with.
7066 lResult = RegOpenKeyEx(
7067 HKEY_LOCAL_MACHINE, // Where it is
7068 "Software\\Microsoft\\DirectX", // name of key
7069 NULL, // DWORD reserved
7070 KEY_QUERY_VALUE, // Allows all changes
7071 &hKey // Location to store key
7074 if (lResult == ERROR_SUCCESS) {
7076 DWORD dwType, dwLen;
7079 lResult = RegQueryValueEx(
7080 hKey, // Handle to key
7081 "Version", // The values name
7082 NULL, // DWORD reserved
7083 &dwType, // What kind it is
7084 (ubyte *) version, // value to set
7085 &dwLen // How many bytes to set
7088 if (lResult == ERROR_SUCCESS) {
7089 dx_version = atoi(strstr(version, ".") + 1);
7093 DWORD dwType, dwLen;
7096 lResult = RegQueryValueEx(
7097 hKey, // Handle to key
7098 "InstalledVersion", // The values name
7099 NULL, // DWORD reserved
7100 &dwType, // What kind it is
7101 (ubyte *) &val, // value to set
7102 &dwLen // How many bytes to set
7105 if (lResult == ERROR_SUCCESS) {
7113 if (dx_version < 3) {
7114 MessageBox(NULL, "DirectX 3.0 or higher is required and wasn't detected. You can get the\n"
7115 "latest version of DirectX at:\n\n"
7116 "http://www.microsoft.com/msdownload/directx/dxf/enduser5.0/default.htm", "DirectX required", MB_OK);
7118 MessageBox(NULL, "DirectX 3.0 or higher is required and wasn't detected. You can install\n"
7119 "DirectX 5.2 by pressing the 'Install DirectX' button on the FreeSpace Launcher", "DirectX required", MB_OK);
7124 //=====================================================
7125 // Make sure we're running in the right directory.
7129 if ( GetModuleFileName( hInst, exe_dir, 1023 ) > 0 ) {
7130 char *p = exe_dir + strlen(exe_dir);
7132 // chop off the filename
7133 while( (p>exe_dir) && (*p!='\\') && (*p!='/') && (*p!=':') ) {
7139 if ( strlen(exe_dir) > 0 ) {
7140 SetCurrentDirectory(exe_dir);
7143 // check for updated freespace.exe
7144 game_maybe_update_launcher(exe_dir);
7152 extern void windebug_memwatch_init();
7153 windebug_memwatch_init();
7157 parse_cmdline(szCmdLine);
7159 #ifdef STANDALONE_ONLY_BUILD
7161 nprintf(("Network", "Standalone running"));
7164 nprintf(("Network", "Standalone running"));
7172 // maybe spew pof stuff
7173 if(Cmdline_spew_pof_info){
7174 game_spew_pof_info();
7179 // non-demo, non-standalone, play the intro movie
7185 // to avoid crashes on debug build
7186 for (i=0; i<5; i++) {
7190 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) ){
7192 #if defined(OEM_BUILD)
7193 game_do_cd_check_specific(FS_CDROM_VOLUME_1, 1);
7195 game_do_cd_check_specific(FS_CDROM_VOLUME_2, 2);
7196 #endif // defined(OEM_BUILD)
7199 for (int i=0; i<5; i++) {
7200 if (plist[i] != NULL) {
7205 #endif // RELEASE_REAL
7208 if ( !Is_standalone ) {
7210 // release -- movies always play
7213 // 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
7214 movie_play( NOX("intro.mve"), 0 );
7216 // debug version, movie will only play with -showmovies
7217 #elif !defined(NDEBUG)
7219 movie_play( NOX("intro.mve"), 0);
7222 if ( Cmdline_show_movies )
7223 movie_play( NOX("intro.mve"), 0 );
7232 gameseq_post_event(GS_EVENT_STANDALONE_MAIN);
7234 gameseq_post_event(GS_EVENT_GAME_INIT); // start the game rolling -- check for default pilot, or go to the pilot select screen
7238 // only important for non THREADED mode
7241 state = gameseq_process_events();
7242 if ( state == GS_STATE_QUIT_GAME ){
7247 #if defined(FS2_DEMO) || defined(FS1_DEMO)
7249 demo_upsell_show_screens();
7251 #elif defined(OEM_BUILD)
7252 // show upsell screens on exit
7253 oem_upsell_show_screens();
7260 int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int nCmdShow)
7266 result = WinMainSub(hInst, hPrev, szCmdLine, nCmdShow);
7268 __except(RecordExceptionInfo(GetExceptionInformation(), "Freespace 2 Main Thread"))
7270 // Do nothing here - RecordExceptionInfo() has already done
7271 // everything that is needed. Actually this code won't even
7272 // get called unless you return EXCEPTION_EXECUTE_HANDLER from
7273 // the __except clause.
7277 nprintf(("WinMain", "exceptions shall fall through"));
7279 result = WinMainSub(hInst, hPrev, szCmdLine, nCmdShow);
7285 // launcher the fslauncher program on exit
7286 void game_launch_launcher_on_exit()
7290 PROCESS_INFORMATION pi;
7291 char cmd_line[2048];
7292 char original_path[1024] = "";
7294 memset( &si, 0, sizeof(STARTUPINFO) );
7298 _getcwd(original_path, 1023);
7300 // set up command line
7301 strcpy(cmd_line, original_path);
7302 strcat(cmd_line, "\\");
7303 strcat(cmd_line, LAUNCHER_FNAME);
7304 strcat(cmd_line, " -straight_to_update");
7306 BOOL ret = CreateProcess( NULL, // pointer to name of executable module
7307 cmd_line, // pointer to command line string
7308 NULL, // pointer to process security attributes
7309 NULL, // pointer to thread security attributes
7310 FALSE, // handle inheritance flag
7311 CREATE_DEFAULT_ERROR_MODE, // creation flags
7312 NULL, // pointer to new environment block
7313 NULL, // pointer to current directory name
7314 &si, // pointer to STARTUPINFO
7315 &pi // pointer to PROCESS_INFORMATION
7317 // to eliminate build warnings
7327 // This function is called when FreeSpace terminates normally.
7329 void game_shutdown(void)
7335 // don't ever flip a page on the standalone!
7336 if(!(Game_mode & GM_STANDALONE_SERVER)){
7342 // if the player has left the "player select" screen and quit the game without actually choosing
7343 // a player, Player will be NULL, in which case we shouldn't write the player file out!
7344 if (!(Game_mode & GM_STANDALONE_SERVER) && (Player!=NULL) && !Is_standalone){
7348 // load up common multiplayer icons
7349 multi_unload_common_icons();
7351 shockwave_close(); // release any memory used by shockwave system
7352 fireball_close(); // free fireball system
7353 ship_close(); // free any memory that was allocated for the ships
7354 weapon_close(); // free any memory that was allocated for the weapons
7355 hud_free_scrollback_list();// free space allocated to store hud messages in hud scrollback
7356 unload_animating_pointer();// frees the frames used for the animating mouse pointer
7357 bm_unload_all(); // free bitmaps
7358 mission_campaign_close(); // close out the campaign stuff
7359 mission_campaign_shutdown(); // get anything that mission_campaign_close can't do
7360 multi_voice_close(); // close down multiplayer voice (including freeing buffers, etc)
7362 #ifdef MULTI_USE_LAG
7366 // the menu close functions will unload the bitmaps if they were displayed during the game
7367 #if !defined(PRESS_TOUR_BUILD) && !defined(PD_BUILD)
7370 context_help_close(); // close out help system
7371 training_menu_close();
7372 lcl_close(); // be sure localization is closed out
7375 // free left-over memory from parsed tables
7376 cutscene_tbl_close();
7378 scoring_tbl_close();
7379 player_tips_close();
7381 extern void joy_close();
7384 audiostream_close();
7386 event_music_close();
7390 // HACKITY HACK HACK
7391 // if this flag is set, we should be firing up the launcher when exiting freespace
7392 extern int Multi_update_fireup_launcher_on_exit;
7393 if(Multi_update_fireup_launcher_on_exit){
7394 game_launch_launcher_on_exit();
7398 // game_stop_looped_sounds()
7400 // This function will call the appropriate stop looped sound functions for those
7401 // modules which use looping sounds. It is not enough just to stop a looping sound
7402 // at the DirectSound level, the game is keeping track of looping sounds, and this
7403 // function is used to inform the game that looping sounds are being halted.
7405 void game_stop_looped_sounds()
7407 hud_stop_looped_locking_sounds();
7408 hud_stop_looped_engine_sounds();
7409 afterburner_stop_sounds();
7410 player_stop_looped_sounds();
7411 obj_snd_stop_all(); // stop all object-linked persistant sounds
7412 game_stop_subspace_ambient_sound();
7413 snd_stop(Radar_static_looping);
7414 Radar_static_looping = -1;
7415 snd_stop(Target_static_looping);
7416 shipfx_stop_engine_wash_sound();
7417 Target_static_looping = -1;
7420 //////////////////////////////////////////////////////////////////////////
7422 // Code for supporting an animating mouse pointer
7425 //////////////////////////////////////////////////////////////////////////
7427 typedef struct animating_obj
7436 static animating_obj Animating_mouse;
7438 // ----------------------------------------------------------------------------
7439 // init_animating_pointer()
7441 // Called by load_animating_pointer() to ensure the Animating_mouse struct
7442 // gets properly initialized
7444 void init_animating_pointer()
7446 Animating_mouse.first_frame = -1;
7447 Animating_mouse.num_frames = 0;
7448 Animating_mouse.current_frame = -1;
7449 Animating_mouse.time = 0.0f;
7450 Animating_mouse.elapsed_time = 0.0f;
7453 // ----------------------------------------------------------------------------
7454 // load_animating_pointer()
7456 // Called at game init to load in the frames for the animating mouse pointer
7458 // input: filename => filename of animation file that holds the animation
7460 void load_animating_pointer(char *filename, int dx, int dy)
7465 init_animating_pointer();
7467 am = &Animating_mouse;
7468 am->first_frame = bm_load_animation(filename, &am->num_frames, &fps);
7469 if ( am->first_frame == -1 )
7470 Error(LOCATION, "Could not load animation %s for the mouse pointer\n", filename);
7471 am->current_frame = 0;
7472 am->time = am->num_frames / i2fl(fps);
7475 // ----------------------------------------------------------------------------
7476 // unload_animating_pointer()
7478 // Called at game shutdown to free the memory used to store the animation frames
7480 void unload_animating_pointer()
7485 am = &Animating_mouse;
7486 for ( i = 0; i < am->num_frames; i++ ) {
7487 Assert( (am->first_frame+i) >= 0 );
7488 bm_release(am->first_frame + i);
7491 am->first_frame = -1;
7493 am->current_frame = -1;
7496 // draw the correct frame of the game mouse... called from game_maybe_draw_mouse()
7497 void game_render_mouse(float frametime)
7502 // if animating cursor exists, play the next frame
7503 am = &Animating_mouse;
7504 if ( am->first_frame != -1 ) {
7505 mouse_get_pos(&mx, &my);
7506 am->elapsed_time += frametime;
7507 am->current_frame = fl2i( ( am->elapsed_time / am->time ) * (am->num_frames-1) );
7508 if ( am->current_frame >= am->num_frames ) {
7509 am->current_frame = 0;
7510 am->elapsed_time = 0.0f;
7512 gr_set_cursor_bitmap(am->first_frame + am->current_frame);
7516 // ----------------------------------------------------------------------------
7517 // game_maybe_draw_mouse()
7519 // determines whether to draw the mouse pointer at all, and what frame of
7520 // animation to use if the mouse is animating
7522 // Sets mouse.cpp globals Mouse_hidden and Mouse_moved based on the state of the game.
7524 // input: frametime => elapsed frame time in seconds since last call
7526 void game_maybe_draw_mouse(float frametime)
7530 game_state = gameseq_get_state();
7532 switch ( game_state ) {
7533 case GS_STATE_GAME_PAUSED:
7534 // case GS_STATE_MULTI_PAUSED:
7535 case GS_STATE_GAME_PLAY:
7536 case GS_STATE_DEATH_DIED:
7537 case GS_STATE_DEATH_BLEW_UP:
7538 if ( popup_active() || popupdead_is_active() ) {
7550 if ( !Mouse_hidden )
7551 game_render_mouse(frametime);
7555 void game_do_training_checks()
7559 waypoint_list *wplp;
7561 if (Training_context & TRAINING_CONTEXT_SPEED) {
7562 s = (int) Player_obj->phys_info.fspeed;
7563 if ((s >= Training_context_speed_min) && (s <= Training_context_speed_max)) {
7564 if (!Training_context_speed_set) {
7565 Training_context_speed_set = 1;
7566 Training_context_speed_timestamp = timestamp();
7570 Training_context_speed_set = 0;
7573 if (Training_context & TRAINING_CONTEXT_FLY_PATH) {
7574 wplp = &Waypoint_lists[Training_context_path];
7575 if (wplp->count > Training_context_goal_waypoint) {
7576 i = Training_context_goal_waypoint;
7578 d = vm_vec_dist(&wplp->waypoints[i], &Player_obj->pos);
7579 if (d <= Training_context_distance) {
7580 Training_context_at_waypoint = i;
7581 if (Training_context_goal_waypoint == i) {
7582 Training_context_goal_waypoint++;
7583 snd_play(&Snds[SND_CARGO_REVEAL], 0.0f);
7590 if (i == wplp->count)
7593 } while (i != Training_context_goal_waypoint);
7597 if ((Players_target == UNINITIALIZED) || (Player_ai->target_objnum != Players_target) || (Player_ai->targeted_subsys != Players_targeted_subsys)) {
7598 Players_target = Player_ai->target_objnum;
7599 Players_targeted_subsys = Player_ai->targeted_subsys;
7600 Players_target_timestamp = timestamp();
7604 /////////// Following is for event debug view screen
7608 #define EVENT_DEBUG_MAX 5000
7609 #define EVENT_DEBUG_EVENT 0x8000
7611 int Event_debug_index[EVENT_DEBUG_MAX];
7614 void game_add_event_debug_index(int n, int indent)
7616 if (ED_count < EVENT_DEBUG_MAX)
7617 Event_debug_index[ED_count++] = n | (indent << 16);
7620 void game_add_event_debug_sexp(int n, int indent)
7625 if (Sexp_nodes[n].first >= 0) {
7626 game_add_event_debug_sexp(Sexp_nodes[n].first, indent);
7627 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent);
7631 game_add_event_debug_index(n, indent);
7632 if (Sexp_nodes[n].subtype == SEXP_ATOM_OPERATOR)
7633 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent + 1);
7635 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent);
7638 void game_event_debug_init()
7643 for (e=0; e<Num_mission_events; e++) {
7644 game_add_event_debug_index(e | EVENT_DEBUG_EVENT, 0);
7645 game_add_event_debug_sexp(Mission_events[e].formula, 1);
7649 void game_show_event_debug(float frametime)
7653 int font_height, font_width;
7655 static int scroll_offset = 0;
7657 k = game_check_key();
7663 if (scroll_offset < 0)
7673 scroll_offset -= 20;
7674 if (scroll_offset < 0)
7679 scroll_offset += 20; // not font-independent, hard-coded since I counted the lines!
7683 gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
7689 gr_set_color_fast(&Color_bright);
7691 gr_printf(0x8000, 5, NOX("EVENT DEBUG VIEW"));
7693 gr_set_color_fast(&Color_normal);
7695 gr_get_string_size(&font_width, &font_height, NOX("test"));
7696 y_max = gr_screen.max_h - font_height - 5;
7700 while (k < ED_count) {
7701 if (y_index > y_max)
7704 z = Event_debug_index[k];
7705 if (z & EVENT_DEBUG_EVENT) {
7707 sprintf(buf, NOX("%s%s (%s) %s%d %d"), (Mission_events[z].flags & MEF_CURRENT) ? NOX("* ") : "",
7708 Mission_events[z].name, Mission_events[z].result ? NOX("True") : NOX("False"),
7709 (Mission_events[z].chain_delay < 0) ? "" : NOX("x "),
7710 Mission_events[z].repeat_count, Mission_events[z].interval);
7718 strcat(buf, Sexp_nodes[z & 0x7fff].text);
7719 switch (Sexp_nodes[z & 0x7fff].value) {
7721 strcat(buf, NOX(" (True)"));
7725 strcat(buf, NOX(" (False)"));
7728 case SEXP_KNOWN_TRUE:
7729 strcat(buf, NOX(" (Always true)"));
7732 case SEXP_KNOWN_FALSE:
7733 strcat(buf, NOX(" (Always false)"));
7736 case SEXP_CANT_EVAL:
7737 strcat(buf, NOX(" (Can't eval)"));
7741 case SEXP_NAN_FOREVER:
7742 strcat(buf, NOX(" (Not a number)"));
7747 gr_printf(10, y_index, buf);
7748 y_index += font_height;
7762 extern int Tmap_npixels;
7765 int Tmap_num_too_big = 0;
7766 int Num_models_needing_splitting = 0;
7768 void Time_model( int modelnum )
7770 // mprintf(( "Timing ship '%s'\n", si->name ));
7772 vector eye_pos, model_pos;
7773 matrix eye_orient, model_orient;
7775 polymodel *pm = model_get( modelnum );
7777 int l = strlen(pm->filename);
7779 if ( (l == '/') || (l=='\\') || (l==':')) {
7785 char *pof_file = &pm->filename[l];
7787 int model_needs_splitting = 0;
7789 //fprintf( Texture_fp, "Model: %s\n", pof_file );
7791 for (i=0; i<pm->n_textures; i++ ) {
7792 char filename[1024];
7795 int bmp_num = pm->original_textures[i];
7796 if ( bmp_num > -1 ) {
7797 bm_get_palette(pm->original_textures[i], pal, filename );
7799 bm_get_info( pm->original_textures[i],&w, &h );
7802 if ( (w > 512) || (h > 512) ) {
7803 fprintf( Texture_fp, "%s\t%s\t%d\t%d\n", pof_file, filename, w, h );
7805 model_needs_splitting++;
7808 //fprintf( Texture_fp, "\tTexture %d is bogus\n", i );
7812 if ( model_needs_splitting ) {
7813 Num_models_needing_splitting++;
7815 eye_orient = model_orient = vmd_identity_matrix;
7816 eye_pos = model_pos = vmd_zero_vector;
7818 eye_pos.xyz.z = -pm->rad*2.0f;
7820 vector eye_to_model;
7822 vm_vec_sub( &eye_to_model, &model_pos, &eye_pos );
7823 vm_vector_2_matrix( &eye_orient, &eye_to_model, NULL, NULL );
7825 fix t1 = timer_get_fixed_seconds();
7828 ta.p = ta.b = ta.h = 0.0f;
7835 int bitmaps_used_this_frame, bitmaps_new_this_frame;
7837 bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
7839 modelstats_num_polys = modelstats_num_verts = 0;
7841 while( ta.h < PI2 ) {
7844 vm_angles_2_matrix(&m1, &ta );
7845 vm_matrix_x_matrix( &model_orient, &vmd_identity_matrix, &m1 );
7852 g3_set_view_matrix( &eye_pos, &eye_orient, Viewer_zoom );
7854 model_clear_instance( modelnum );
7855 model_set_detail_level(0); // use highest detail level
7856 model_render( modelnum, &model_orient, &model_pos, MR_LOCK_DETAIL); //|MR_NO_POLYS );
7864 int k = key_inkey();
7865 if ( k == KEY_ESC ) {
7870 fix t2 = timer_get_fixed_seconds();
7872 bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
7873 //bitmaps_used_this_frame /= framecount;
7875 modelstats_num_polys /= framecount;
7876 modelstats_num_verts /= framecount;
7879 Tmap_npixels /=framecount;
7882 mprintf(( "'%s' is %.2f FPS\n", pof_file, i2fl(framecount)/f2fl(t2-t1) ));
7884 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 );
7886 fprintf( Time_fp, "\"%s\"\t%.0f\t%d\t%d\t%d\n", pof_file, i2fl(framecount)/f2fl(t2-t1), bitmaps_used_this_frame, modelstats_num_polys, modelstats_num_verts );
7888 // 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 );
7894 int Time_models = 0;
7895 DCF_BOOL( time_models, Time_models );
7897 void Do_model_timings_test()
7901 if ( !Time_models ) return;
7903 mprintf(( "Timing models!\n" ));
7907 ubyte model_used[MAX_POLYGON_MODELS];
7908 int model_id[MAX_POLYGON_MODELS];
7909 for (i=0; i<MAX_POLYGON_MODELS; i++ ) {
7914 for (i=0; i<Num_ship_types; i++ ) {
7915 Ship_info[i].modelnum = model_load( Ship_info[i].pof_file, 0, NULL );
7917 model_used[Ship_info[i].modelnum%MAX_POLYGON_MODELS]++;
7918 model_id[Ship_info[i].modelnum%MAX_POLYGON_MODELS] = Ship_info[i].modelnum;
7921 Texture_fp = fopen( NOX("ShipTextures.txt"), "wt" );
7922 if ( !Texture_fp ) return;
7924 Time_fp = fopen( NOX("ShipTimings.txt"), "wt" );
7925 if ( !Time_fp ) return;
7927 fprintf( Time_fp, "Name\tFPS\tTRAM\tPolys\tVerts\tPixels\n" );
7928 // fprintf( Time_fp, "FPS\tTRAM\tPolys\tVerts\tPixels\n" );
7930 for (i=0; i<MAX_POLYGON_MODELS; i++ ) {
7931 if ( model_used[i] ) {
7932 Time_model( model_id[i] );
7936 fprintf( Texture_fp, "Number too big: %d\n", Tmap_num_too_big );
7937 fprintf( Texture_fp, "Number of models needing splitting: %d\n", Num_models_needing_splitting );
7946 // Call this function when you want to inform the player that a feature is not
7947 // enabled in the DEMO version of FreSpace
7948 void game_feature_not_in_demo_popup()
7950 popup(PF_USE_AFFIRMATIVE_ICON|PF_BODY_BIG, 1, POPUP_OK, XSTR( "Sorry, this feature is available only in the retail version", 200));
7953 // format the specified time (fixed point) into a nice string
7954 void game_format_time(fix m_time,char *time_str)
7957 int hours,minutes,seconds;
7960 mtime = f2fl(m_time);
7962 // get the hours, minutes and seconds
7963 hours = (int)(mtime / 3600.0f);
7965 mtime -= (3600.0f * (float)hours);
7967 seconds = (int)mtime%60;
7968 minutes = (int)mtime/60;
7970 // print the hour if necessary
7972 sprintf(time_str,XSTR( "%d:", 201),hours);
7973 // if there are less than 10 minutes, print a leading 0
7975 strcpy(tmp,NOX("0"));
7976 strcat(time_str,tmp);
7980 // print the minutes
7982 sprintf(tmp,XSTR( "%d:", 201),minutes);
7983 strcat(time_str,tmp);
7985 sprintf(time_str,XSTR( "%d:", 201),minutes);
7988 // print the seconds
7990 strcpy(tmp,NOX("0"));
7991 strcat(time_str,tmp);
7993 sprintf(tmp,"%d",seconds);
7994 strcat(time_str,tmp);
7997 // Stuff version string in *str.
7998 void get_version_string(char *str)
8001 if ( FS_VERSION_BUILD == 0 ) {
8002 sprintf(str,"v%d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR);
8004 sprintf(str,"v%d.%02d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR, FS_VERSION_BUILD );
8007 #if defined (FS2_DEMO) || defined(FS1_DEMO)
8009 #elif defined (OEM_BUILD)
8010 strcat(str, " (OEM)");
8016 char myname[_MAX_PATH];
8017 int namelen, major, minor, build, waste;
8018 unsigned int buf_size;
8024 // Find my EXE file name
8025 hMod = GetModuleHandle(NULL);
8026 namelen = GetModuleFileName( hMod, myname, _MAX_PATH );
8028 version_size = GetFileVersionInfoSize(myname, &bogus_handle );
8029 infop = (char *)malloc(version_size);
8030 result = GetFileVersionInfo( myname, 0, version_size, (LPVOID)infop );
8032 // get the product version
8033 result = VerQueryValue((LPVOID)infop, TEXT("\\StringFileInfo\\040904b0\\ProductVersion"), &bufp, &buf_size );
8034 sscanf( (char *)bufp, "%d, %d, %d, %d", &major, &minor, &build, &waste );
8036 sprintf(str,"Dv%d.%02d",major, minor);
8038 sprintf(str,"v%d.%02d",major, minor);
8043 void get_version_string_short(char *str)
8045 sprintf(str,"v%d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR);
8048 // ----------------------------------------------------------------
8050 // OEM UPSELL SCREENS BEGIN
8052 // ----------------------------------------------------------------
8053 #if defined(OEM_BUILD)
8055 #define NUM_OEM_UPSELL_SCREENS 3
8056 #define OEM_UPSELL_SCREEN_DELAY 10000
8058 static int Oem_upsell_bitmaps_loaded = 0;
8059 static int Oem_upsell_bitmaps[GR_NUM_RESOLUTIONS][NUM_OEM_UPSELL_SCREENS];
8060 static int Oem_upsell_screen_number = 0;
8061 static int Oem_upsell_show_next_bitmap_time;
8064 static char *Oem_upsell_bitmap_filenames[GR_NUM_RESOLUTIONS][NUM_OEM_UPSELL_SCREENS] =
8077 static int Oem_normal_cursor = -1;
8078 static int Oem_web_cursor = -1;
8079 //#define OEM_UPSELL_URL "http://www.interplay-store.com/"
8080 #define OEM_UPSELL_URL "http://www.interplay.com/cgi-bin/oemlinks.pl/pid=483421&cid=18384"
8082 void oem_upsell_next_screen()
8084 Oem_upsell_screen_number++;
8085 if ( Oem_upsell_screen_number == (NUM_OEM_UPSELL_SCREENS-1) ) {
8086 // extra long delay, mouse shown on last upsell
8087 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY*2;
8091 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY;
8095 void oem_upsell_load_bitmaps()
8099 for ( i = 0; i < NUM_OEM_UPSELL_SCREENS; i++ ) {
8100 Oem_upsell_bitmaps[gr_screen.res][i] = bm_load(Oem_upsell_bitmap_filenames[gr_screen.res][i]);
8104 void oem_upsell_unload_bitmaps()
8108 for ( i = 0; i < NUM_OEM_UPSELL_SCREENS; i++ ) {
8109 if(Oem_upsell_bitmaps[gr_screen.res][i] >= 0){
8110 bm_unload(Oem_upsell_bitmaps[gr_screen.res][i]);
8115 Oem_upsell_bitmaps_loaded = 0;
8118 // clickable hotspot on 3rd OEM upsell screen
8119 static int Oem_upsell3_button_coords[GR_NUM_RESOLUTIONS][4] = {
8121 28, 350, 287, 96 // x, y, w, h
8124 45, 561, 460, 152 // x, y, w, h
8128 void oem_upsell_show_screens()
8130 int current_time, k;
8133 if ( !Oem_upsell_bitmaps_loaded ) {
8134 oem_upsell_load_bitmaps();
8135 Oem_upsell_bitmaps_loaded = 1;
8138 // may use upsell screens more than once
8139 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY;
8140 Oem_upsell_screen_number = 0;
8146 int nframes; // used to pass, not really needed (should be 1)
8147 Oem_normal_cursor = gr_get_cursor_bitmap();
8148 Oem_web_cursor = bm_load_animation("cursorweb", &nframes);
8149 Assert(Oem_web_cursor >= 0);
8150 if (Oem_web_cursor < 0) {
8151 Oem_web_cursor = Oem_normal_cursor;
8156 //oem_reset_trailer_timer();
8158 current_time = timer_get_milliseconds();
8163 // advance screen on keypress or timeout
8164 if (( k > 0 ) || (mouse_up_count(MOUSE_LEFT_BUTTON) > 0) || (current_time > Oem_upsell_show_next_bitmap_time)) {
8165 oem_upsell_next_screen();
8168 // check if we are done
8169 if ( Oem_upsell_screen_number >= NUM_OEM_UPSELL_SCREENS ) {
8170 Oem_upsell_screen_number--;
8173 if ( Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number] < 0 ) {
8178 // show me the upsell
8179 if ( Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number] >= 0 ) {
8180 gr_set_bitmap(Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number]);
8184 // if this is the 3rd upsell, make it clickable, d00d
8185 if ( Oem_upsell_screen_number == NUM_OEM_UPSELL_SCREENS-1 ) {
8187 int button_state = mouse_get_pos(&mx, &my);
8188 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])
8189 && (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]) )
8192 gr_set_cursor_bitmap(Oem_web_cursor); //, GR_CURSOR_LOCK);
8195 if (button_state & MOUSE_LEFT_BUTTON) {
8197 multi_pxo_url(OEM_UPSELL_URL);
8201 // switch cursor back to normal one
8202 gr_set_cursor_bitmap(Oem_normal_cursor); //, GR_CURSOR_UNLOCK);
8207 if (gameseq_get_state() != GS_STATE_END_DEMO) {
8217 oem_upsell_unload_bitmaps();
8219 // switch cursor back to normal one
8220 gr_set_cursor_bitmap(Oem_normal_cursor); //, GR_CURSOR_UNLOCK);
8224 #endif // defined(OEM_BUILD)
8225 // ----------------------------------------------------------------
8227 // OEM UPSELL SCREENS END
8229 // ----------------------------------------------------------------
8233 // ----------------------------------------------------------------
8235 // DEMO UPSELL SCREENS BEGIN
8237 // ----------------------------------------------------------------
8239 #if defined(FS2_DEMO) || defined(FS1_DEMO)
8242 #define NUM_DEMO_UPSELL_SCREENS 2
8244 #define NUM_DEMO_UPSELL_SCREENS 4
8246 #define DEMO_UPSELL_SCREEN_DELAY 3000
8248 static int Demo_upsell_bitmaps_loaded = 0;
8249 static int Demo_upsell_bitmaps[GR_NUM_RESOLUTIONS][NUM_DEMO_UPSELL_SCREENS];
8250 static int Demo_upsell_screen_number = 0;
8251 static int Demo_upsell_show_next_bitmap_time;
8254 static char *Demo_upsell_bitmap_filenames[GR_NUM_RESOLUTIONS][NUM_DEMO_UPSELL_SCREENS] =
8280 void demo_upsell_next_screen()
8282 Demo_upsell_screen_number++;
8283 if ( Demo_upsell_screen_number == (NUM_DEMO_UPSELL_SCREENS-1) ) {
8284 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY*4;
8286 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY;
8290 if ( Demo_upsell_screen_number < NUM_DEMO_UPSELL_SCREENS ) {
8291 if ( Demo_upsell_bitmap_filenames[gr_screen.res][Demo_upsell_screen_number] >= 0 ) {
8292 #ifndef HARDWARE_ONLY
8293 palette_use_bm_palette(Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number]);
8300 void demo_upsell_load_bitmaps()
8304 for ( i = 0; i < NUM_DEMO_UPSELL_SCREENS; i++ ) {
8305 Demo_upsell_bitmaps[gr_screen.res][i] = bm_load(Demo_upsell_bitmap_filenames[gr_screen.res][i]);
8309 void demo_upsell_unload_bitmaps()
8313 for ( i = 0; i < NUM_DEMO_UPSELL_SCREENS; i++ ) {
8314 if(Demo_upsell_bitmaps[gr_screen.res][i] >= 0){
8315 bm_unload(Demo_upsell_bitmaps[gr_screen.res][i]);
8320 Demo_upsell_bitmaps_loaded = 0;
8323 void demo_upsell_show_screens()
8325 int current_time, k;
8328 if ( !Demo_upsell_bitmaps_loaded ) {
8329 demo_upsell_load_bitmaps();
8330 Demo_upsell_bitmaps_loaded = 1;
8333 // may use upsell screens more than once
8334 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY;
8335 Demo_upsell_screen_number = 0;
8342 demo_reset_trailer_timer();
8344 current_time = timer_get_milliseconds();
8351 // don't time out, wait for keypress
8353 if ( current_time > Demo_upsell_show_next_bitmap_time ) {
8354 demo_upsell_next_screen();
8359 demo_upsell_next_screen();
8362 if ( Demo_upsell_screen_number >= NUM_DEMO_UPSELL_SCREENS ) {
8363 Demo_upsell_screen_number--;
8366 if ( Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number] < 0 ) {
8371 if ( Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number] >= 0 ) {
8372 gr_set_bitmap(Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number]);
8377 if (gameseq_get_state() != GS_STATE_END_DEMO) {
8387 demo_upsell_unload_bitmaps();
8392 // ----------------------------------------------------------------
8394 // DEMO UPSELL SCREENS END
8396 // ----------------------------------------------------------------
8399 // ----------------------------------------------------------------
8401 // Subspace Ambient Sound START
8403 // ----------------------------------------------------------------
8405 static int Subspace_ambient_left_channel = -1;
8406 static int Subspace_ambient_right_channel = -1;
8409 void game_start_subspace_ambient_sound()
8411 if ( Subspace_ambient_left_channel < 0 ) {
8412 Subspace_ambient_left_channel = snd_play_looping(&Snds[SND_SUBSPACE_LEFT_CHANNEL], -1.0f);
8415 if ( Subspace_ambient_right_channel < 0 ) {
8416 Subspace_ambient_right_channel = snd_play_looping(&Snds[SND_SUBSPACE_RIGHT_CHANNEL], 1.0f);
8420 void game_stop_subspace_ambient_sound()
8422 if ( Subspace_ambient_left_channel >= 0 ) {
8423 snd_stop(Subspace_ambient_left_channel);
8424 Subspace_ambient_left_channel = -1;
8427 if ( Subspace_ambient_right_channel >= 0 ) {
8428 snd_stop(Subspace_ambient_right_channel);
8429 Subspace_ambient_right_channel = -1;
8433 // ----------------------------------------------------------------
8435 // Subspace Ambient Sound END
8437 // ----------------------------------------------------------------
8439 // ----------------------------------------------------------------
8441 // CDROM detection code START
8443 // ----------------------------------------------------------------
8445 #define CD_SIZE_72_MINUTE_MAX (697000000)
8447 uint game_get_cd_used_space(char *path)
8451 char use_path[512] = "";
8452 char sub_path[512] = "";
8453 WIN32_FIND_DATA find;
8456 // recurse through all files and directories
8457 strcpy(use_path, path);
8458 strcat(use_path, "*.*");
8459 find_handle = FindFirstFile(use_path, &find);
8462 if(find_handle == INVALID_HANDLE_VALUE){
8468 // subdirectory. make sure to ignore . and ..
8469 if((find.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) && stricmp(find.cFileName, ".") && stricmp(find.cFileName, "..")){
8471 strcpy(sub_path, path);
8472 strcat(sub_path, find.cFileName);
8473 strcat(sub_path, "\\");
8474 total += game_get_cd_used_space(sub_path);
8476 total += (uint)find.nFileSizeLow;
8478 } while(FindNextFile(find_handle, &find));
8481 FindClose(find_handle);
8493 // if volume_name is non-null, the CD name must match that
8494 int find_freespace_cd(char *volume_name)
8497 char oldpath[MAX_PATH];
8501 int volume_match = 0;
8505 GetCurrentDirectory(MAX_PATH, oldpath);
8507 for (i = 0; i < 26; i++)
8513 path[0] = (char)('A'+i);
8514 if (GetDriveType(path) == DRIVE_CDROM) {
8516 if ( GetVolumeInformation(path, volume, 256, NULL, NULL, NULL, NULL, 0) == TRUE ) {
8517 nprintf(("CD", "CD volume: %s\n", volume));
8519 // check for any CD volume
8520 int volume1_present = 0;
8521 int volume2_present = 0;
8522 int volume3_present = 0;
8524 char full_check[512] = "";
8526 // look for setup.exe
8527 strcpy(full_check, path);
8528 strcat(full_check, "setup.exe");
8529 find_handle = _findfirst(full_check, &find);
8530 if(find_handle != -1){
8531 volume1_present = 1;
8532 _findclose(find_handle);
8535 // look for intro.mve
8536 strcpy(full_check, path);
8537 strcat(full_check, "intro.mve");
8538 find_handle = _findfirst(full_check, &find);
8539 if(find_handle != -1){
8540 volume2_present = 1;
8541 _findclose(find_handle);
8544 // look for endpart1.mve
8545 strcpy(full_check, path);
8546 strcat(full_check, "endpart1.mve");
8547 find_handle = _findfirst(full_check, &find);
8548 if(find_handle != -1){
8549 volume3_present = 1;
8550 _findclose(find_handle);
8553 // see if we have the specific CD we're looking for
8554 if ( volume_name ) {
8556 if ( !stricmp(volume_name, FS_CDROM_VOLUME_1) && volume1_present) {
8560 if ( !stricmp(volume_name, FS_CDROM_VOLUME_2) && volume2_present) {
8564 if ( !stricmp(volume_name, FS_CDROM_VOLUME_3) && volume3_present) {
8568 if ( volume1_present || volume2_present || volume3_present ) {
8573 // 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
8574 if ( volume_match ){
8576 // 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
8577 if(volume2_present || volume3_present) {
8578 // first step - check to make sure its a cdrom
8579 if(GetDriveType(path) != DRIVE_CDROM){
8583 #if !defined(OEM_BUILD)
8584 // oem not on 80 min cds, so dont check tha size
8586 uint used_space = game_get_cd_used_space(path);
8587 if(used_space < CD_SIZE_72_MINUTE_MAX){
8590 #endif // !defined(OEM_BUILD)
8598 #endif // RELEASE_REAL
8604 SetCurrentDirectory(oldpath);
8613 int set_cdrom_path(int drive_num)
8617 if (drive_num < 0) { //no CD
8619 // strcpy(CDROM_dir,"j:\\FreeSpaceCD\\"); //set directory
8622 strcpy(Game_CDROM_dir,""); //set directory
8626 sprintf(Game_CDROM_dir,NOX("%c:\\"), 'a' + drive_num ); //set directory
8642 i = find_freespace_cd();
8644 rval = set_cdrom_path(i);
8648 nprintf(("CD", "Using %s for FreeSpace CD\n", CDROM_dir));
8650 nprintf(("CD", "FreeSpace CD not found\n"));
8658 int Last_cd_label_found = 0;
8659 char Last_cd_label[256];
8661 int game_cd_changed()
8668 if ( strlen(Game_CDROM_dir) == 0 ) {
8672 found = GetVolumeInformation(Game_CDROM_dir, label, 256, NULL, NULL, NULL, NULL, 0);
8674 if ( found != Last_cd_label_found ) {
8675 Last_cd_label_found = found;
8677 mprintf(( "CD '%s' was inserted\n", label ));
8680 mprintf(( "CD '%s' was removed\n", Last_cd_label ));
8684 if ( Last_cd_label_found ) {
8685 if ( !stricmp( Last_cd_label, label )) {
8686 //mprintf(( "CD didn't change\n" ));
8688 mprintf(( "CD was changed from '%s' to '%s'\n", Last_cd_label, label ));
8692 // none found before, none found now.
8693 //mprintf(( "still no CD...\n" ));
8697 Last_cd_label_found = found;
8699 strcpy( Last_cd_label, label );
8701 strcpy( Last_cd_label, "" );
8712 // check if _any_ FreeSpace2 CDs are in the drive
8713 // return: 1 => CD now in drive
8714 // 0 => Could not find CD, they refuse to put it in the drive
8715 int game_do_cd_check(char *volume_name)
8717 #if !defined(GAME_CD_CHECK)
8723 int num_attempts = 0;
8724 int refresh_files = 0;
8726 int path_set_ok, popup_rval;
8728 cd_drive_num = find_freespace_cd(volume_name);
8729 path_set_ok = set_cdrom_path(cd_drive_num);
8730 if ( path_set_ok ) {
8732 if ( refresh_files ) {
8744 // no CD found, so prompt user
8745 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR( "FreeSpace 2 CD not found\n\nInsert a FreeSpace 2 CD to continue", 202));
8747 if ( popup_rval != 1 ) {
8752 if ( num_attempts++ > 5 ) {
8763 // check if _any_ FreeSpace2 CDs are in the drive
8764 // return: 1 => CD now in drive
8765 // 0 => Could not find CD, they refuse to put it in the drive
8766 int game_do_cd_check_specific(char *volume_name, int cdnum)
8771 int num_attempts = 0;
8772 int refresh_files = 0;
8774 int path_set_ok, popup_rval;
8776 cd_drive_num = find_freespace_cd(volume_name);
8777 path_set_ok = set_cdrom_path(cd_drive_num);
8778 if ( path_set_ok ) {
8780 if ( refresh_files ) {
8791 // no CD found, so prompt user
8792 #if defined(DVD_MESSAGE_HACK)
8793 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR("Please insert DVD", 1468));
8795 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR("Please insert CD %d", 1468), cdnum);
8798 if ( popup_rval != 1 ) {
8803 if ( num_attempts++ > 5 ) {
8813 // only need to do this in RELEASE_REAL
8814 int game_do_cd_mission_check(char *filename)
8820 fs_builtin_mission *m = game_find_builtin_mission(filename);
8822 // check for changed CD
8823 if(game_cd_changed()){
8828 if((Game_mode & GM_MULTIPLAYER) || Is_standalone){
8832 // not builtin, so do a general check (any FS2 CD will do)
8834 return game_do_cd_check();
8837 // does not have any CD requirement, do a general check
8838 if(strlen(m->cd_volume) <= 0){
8839 return game_do_cd_check();
8843 if(!stricmp(m->cd_volume, FS_CDROM_VOLUME_1)){
8845 } else if(!stricmp(m->cd_volume, FS_CDROM_VOLUME_2)){
8848 } else if(!stricmp(m->cd_volume, FS_CDROM_VOLUME_3)){
8852 return game_do_cd_check();
8855 // did we find the cd?
8856 if(find_freespace_cd(m->cd_volume) >= 0){
8860 // make sure the volume exists
8861 int num_attempts = 0;
8862 int refresh_files = 0;
8864 int path_set_ok, popup_rval;
8866 cd_drive_num = find_freespace_cd(m->cd_volume);
8867 path_set_ok = set_cdrom_path(cd_drive_num);
8868 if ( path_set_ok ) {
8870 if ( refresh_files ) {
8877 // no CD found, so prompt user
8878 #if defined(DVD_MESSAGE_HACK)
8879 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR("Please insert DVD", 1468));
8881 popup_rval = popup(PF_BODY_BIG, 1, POPUP_OK, XSTR("Please insert CD %d", 1468), cd_num);
8885 if ( popup_rval != 1 ) {
8890 if ( num_attempts++ > 5 ) {
8902 // ----------------------------------------------------------------
8904 // CDROM detection code END
8906 // ----------------------------------------------------------------
8908 // ----------------------------------------------------------------
8910 // Language Autodetection stuff
8913 // this layout order must match Lcl_languages in localize.cpp in order for the
8914 // correct language to be detected
8915 int Lang_auto_detect_checksums[LCL_NUM_LANGUAGES] = {
8917 1366105450, // English
8919 589986744, // English
8921 -1132430286, // German
8923 -1131728960, // Polish
8926 // default setting is "-1" to use config file with English as fall back
8927 // DO NOT change the default setting here or something uncouth might happen
8928 // in the localization code
8934 // try and open the file to verify
8935 CFILE *detect = cfopen("font01.vf", "rb");
8937 // will use default setting if something went wrong
8942 // get the long checksum of the file
8944 cfseek(detect, 0, SEEK_SET);
8945 cf_chksum_long(detect, &file_checksum);
8949 // now compare the checksum/filesize against known #'s
8950 for (idx=0; idx<LCL_NUM_LANGUAGES; idx++) {
8951 if (Lang_auto_detect_checksums[idx] == (int)file_checksum) {
8956 // notify if a match was not found, include detected checksum
8957 printf("ERROR: Unknown Language Checksum: %i\n", (int)file_checksum);
8958 printf("Using default language...\n\n");
8964 // End Auto Lang stuff
8966 // ----------------------------------------------------------------
8968 // ----------------------------------------------------------------
8969 // SHIPS TBL VERIFICATION STUFF
8972 // checksums, just keep a list of all valid ones, if it matches any of them, keep it
8973 #if defined(MAKE_FS1) && !defined(FS1_DEMO)
8974 #define NUM_SHIPS_TBL_CHECKSUMS 3
8976 #define NUM_SHIPS_TBL_CHECKSUMS 1
8980 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8981 1696074201, // FS2 demo
8984 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8985 1603375034, // FS1 DEMO
8988 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8989 -129679197, // FS1 Full 1.06 (US)
8990 7762567, // FS1 SilentThreat
8991 1555372475 // FS1 Full 1.06 (German)
8995 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8996 -463907578, // US - beta 1
8997 1696074201, // FS2 demo
9000 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
9001 // -1022810006, // 1.0 FULL
9002 -1254285366 // 1.2 FULL (German)
9006 void verify_ships_tbl()
9010 Game_ships_tbl_valid = 1;
9016 // detect if the packfile exists
9017 CFILE *detect = cfopen("ships.tbl", "rb");
9018 Game_ships_tbl_valid = 0;
9022 Game_ships_tbl_valid = 0;
9026 // get the long checksum of the file
9028 cfseek(detect, 0, SEEK_SET);
9029 cf_chksum_long(detect, &file_checksum);
9033 // now compare the checksum/filesize against known #'s
9034 for(idx=0; idx<NUM_SHIPS_TBL_CHECKSUMS; idx++){
9035 if(Game_ships_tbl_checksums[idx] == (int)file_checksum){
9036 Game_ships_tbl_valid = 1;
9043 DCF(shipspew, "display the checksum for the current ships.tbl")
9046 CFILE *detect = cfopen("ships.tbl", "rb");
9047 // get the long checksum of the file
9049 cfseek(detect, 0, SEEK_SET);
9050 cf_chksum_long(detect, &file_checksum);
9053 dc_printf("%d", file_checksum);
9056 // ----------------------------------------------------------------
9057 // WEAPONS TBL VERIFICATION STUFF
9060 // checksums, just keep a list of all valid ones, if it matches any of them, keep it
9061 #if defined(MAKE_FS1) && !defined(FS1_DEMO)
9062 #define NUM_WEAPONS_TBL_CHECKSUMS 3
9064 #define NUM_WEAPONS_TBL_CHECKSUMS 1
9068 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
9069 -266420030, // demo 1
9072 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
9073 -1246928725, // FS1 DEMO
9076 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
9077 -834598107, // FS1 1.06 Full (US)
9078 -1652231417, // FS1 SilentThreat
9079 720209793 // FS1 1.06 Full (German)
9083 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
9084 141718090, // US - beta 1
9085 -266420030, // demo 1
9088 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
9089 // 399297860, // 1.0 FULL
9090 -553984927 // 1.2 FULL (german)
9094 void verify_weapons_tbl()
9098 Game_weapons_tbl_valid = 1;
9104 // detect if the packfile exists
9105 CFILE *detect = cfopen("weapons.tbl", "rb");
9106 Game_weapons_tbl_valid = 0;
9110 Game_weapons_tbl_valid = 0;
9114 // get the long checksum of the file
9116 cfseek(detect, 0, SEEK_SET);
9117 cf_chksum_long(detect, &file_checksum);
9121 // now compare the checksum/filesize against known #'s
9122 for(idx=0; idx<NUM_WEAPONS_TBL_CHECKSUMS; idx++){
9123 if(Game_weapons_tbl_checksums[idx] == (int)file_checksum){
9124 Game_weapons_tbl_valid = 1;
9131 DCF(wepspew, "display the checksum for the current weapons.tbl")
9134 CFILE *detect = cfopen("weapons.tbl", "rb");
9135 // get the long checksum of the file
9137 cfseek(detect, 0, SEEK_SET);
9138 cf_chksum_long(detect, &file_checksum);
9141 dc_printf("%d", file_checksum);
9144 // if the game is running using hacked data
9145 int game_hacked_data()
9148 if(!Game_weapons_tbl_valid || !Game_ships_tbl_valid){
9156 void display_title_screen()
9158 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
9159 ///int title_bitmap;
9162 int title_bitmap = bm_load(Game_demo_title_screen_fname[gr_screen.res]);
9163 if (title_bitmap == -1) {
9169 if((gr_screen.mode == GR_DIRECT3D) && (Gr_bitmap_poly)){
9170 extern void d3d_start_frame();
9176 gr_set_bitmap(title_bitmap);
9183 if((gr_screen.mode == GR_DIRECT3D) && (Gr_bitmap_poly)){
9184 extern void d3d_stop_frame();
9192 bm_unload(title_bitmap);
9193 #endif // FS2_DEMO || OEM_BUILD || FS1_DEMO
9196 // return true if the game is running with "low memory", which is less than 48MB
9197 bool game_using_low_mem()
9199 if (Use_low_mem == 0) {