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.40 2005/10/01 21:40:38 taylor
19 * deal with OS X apps a little better, sets the path only based on ".app" in the name rather than the name itself
20 * make sure a global cmdline.cfg file works with OS X when built as an app
22 * Revision 1.39 2005/08/12 08:57:20 taylor
23 * don't show hardware S-RAM value on HUD in debug
24 * do show in use GL texture memory
25 * have an actual fade effect for the credits screen artwork
27 * Revision 1.38 2004/09/20 01:31:44 theoddone33
30 * Revision 1.37 2004/07/04 11:31:43 taylor
31 * amd64 support, compiler warning fixes, don't use software rendering
33 * Revision 1.36 2004/06/12 01:11:35 taylor
34 * x86 compile fixes for OSX patch
36 * Revision 1.35 2004/06/11 00:53:02 tigital
37 * OSX: .app name, casts for gcc
39 * Revision 1.34 2003/08/09 03:18:03 taylor
40 * fix tips popup not having any tips
42 * Revision 1.33 2003/08/03 15:57:00 taylor
43 * simpler mouse usage; default ini settings in os_init(); cleanup
45 * Revision 1.32 2003/06/19 11:51:41 taylor
46 * adjustments to memory leak fixes
48 * Revision 1.31 2003/06/11 18:30:32 taylor
51 * Revision 1.30 2003/06/03 04:00:39 taylor
52 * Polish language support (Janusz Dziemidowicz)
54 * Revision 1.29 2003/05/25 02:30:42 taylor
57 * Revision 1.28 2003/05/18 03:55:30 taylor
58 * automatic language selection support
60 * Revision 1.27 2003/03/03 04:54:44 theoddone33
61 * Commit Taylor's ShowFPS fix
63 * Revision 1.26 2003/02/20 17:41:07 theoddone33
64 * Userdir patch from Taylor Richards
66 * Revision 1.25 2003/01/30 19:54:10 relnev
67 * ini config option for the frames per second counter (Taylor Richards)
69 * Revision 1.24 2002/08/31 01:39:13 theoddone33
70 * Speed up the renderer a tad
72 * Revision 1.23 2002/08/04 02:31:00 relnev
73 * make numlock not overlap with pause
75 * Revision 1.22 2002/08/02 23:07:03 relnev
76 * don't access the mouse in standalone mode
78 * Revision 1.21 2002/07/28 05:05:08 relnev
79 * removed some old stuff
81 * Revision 1.20 2002/07/24 00:20:41 relnev
84 * Revision 1.19 2002/06/17 06:33:08 relnev
85 * ryan's struct patch for gcc 2.95
87 * Revision 1.18 2002/06/16 04:46:33 relnev
88 * set up correct checksums for demo
90 * Revision 1.17 2002/06/09 04:41:17 relnev
91 * added copyright header
93 * Revision 1.16 2002/06/09 03:16:04 relnev
96 * removed unneeded asm, old sdl 2d setup.
98 * fixed crash caused by opengl_get_region.
100 * Revision 1.15 2002/06/05 08:05:28 relnev
101 * stub/warning removal.
103 * reworked the sound code.
105 * Revision 1.14 2002/06/05 04:03:32 relnev
106 * finished cfilesystem.
108 * removed some old code.
110 * fixed mouse save off-by-one.
114 * Revision 1.13 2002/06/02 04:26:34 relnev
117 * Revision 1.12 2002/06/02 00:31:35 relnev
118 * implemented osregistry
120 * Revision 1.11 2002/06/01 09:00:34 relnev
121 * silly debug memmanager
123 * Revision 1.10 2002/06/01 07:12:32 relnev
124 * a few NDEBUG updates.
126 * removed a few warnings.
128 * Revision 1.9 2002/05/31 03:05:59 relnev
131 * Revision 1.8 2002/05/29 02:52:32 theoddone33
132 * Enable OpenGL renderer
134 * Revision 1.7 2002/05/28 08:52:03 relnev
135 * implemented two assembly stubs.
137 * cleaned up a few warnings.
139 * added a little demo hackery to make it progress a little farther.
141 * Revision 1.6 2002/05/28 06:28:20 theoddone33
142 * Filesystem mods, actually reads some data files now
144 * Revision 1.5 2002/05/28 04:07:28 theoddone33
145 * New graphics stubbing arrangement
147 * Revision 1.4 2002/05/27 22:46:52 theoddone33
148 * Remove more undefined symbols
150 * Revision 1.3 2002/05/26 23:31:18 relnev
151 * added a few files that needed to be compiled
153 * freespace.cpp: now compiles
155 * Revision 1.2 2002/05/07 03:16:44 theoddone33
156 * The Great Newline Fix
158 * Revision 1.1.1.1 2002/05/03 03:28:09 root
162 * 201 6/16/00 3:15p Jefff
163 * sim of the year dvd version changes, a few german soty localization
166 * 200 11/03/99 11:06a Jefff
169 * 199 10/26/99 5:07p Jamest
170 * fixed jeffs dumb debug code
172 * 198 10/25/99 5:53p Jefff
173 * call control_config_common_init() on startup
175 * 197 10/14/99 10:18a Daveb
176 * Fixed incorrect CD checking problem on standalone server.
178 * 196 10/13/99 9:22a Daveb
179 * Fixed Fred jumpnode placing bug. Fixed 1024 glide tiled texture problem
180 * related to movies. Fixed launcher spawning from PXO screen.
182 * 195 10/06/99 11:05a Jefff
183 * new oem upsell 3 hotspot coords
185 * 194 10/06/99 10:31a Jefff
188 * 193 10/01/99 9:10a Daveb
191 * 192 9/15/99 4:57a Dave
192 * Updated ships.tbl checksum
194 * 191 9/15/99 3:58a Dave
195 * Removed framerate warning at all times.
197 * 190 9/15/99 3:16a Dave
198 * Remove mt-011.fs2 from the builtin mission list.
200 * 189 9/15/99 1:45a Dave
201 * Don't init joystick on standalone. Fixed campaign mode on standalone.
202 * Fixed no-score-report problem in TvT
204 * 188 9/14/99 6:08a Dave
205 * Updated (final) single, multi, and campaign list.
207 * 187 9/14/99 3:26a Dave
208 * Fixed laser fogging problem in nebula (D3D)> Fixed multiplayer
209 * respawn-too-early problem. Made a few crash points safe.
211 * 186 9/13/99 4:52p Dave
214 * 185 9/12/99 8:09p Dave
215 * Fixed problem where skip-training button would cause mission messages
216 * not to get paged out for the current mission.
218 * 184 9/10/99 11:53a Dave
219 * Shutdown graphics before sound to eliminate apparent lockups when
220 * Directsound decides to be lame. Fix TOPMOST problem with D3D windows.
222 * 183 9/09/99 11:40p Dave
223 * Handle an Assert() in beam code. Added supernova sounds. Play the right
224 * 2 end movies properly, based upon what the player did in the mission.
226 * 182 9/08/99 10:29p Dave
227 * Make beam sound pausing and unpausing much safer.
229 * 181 9/08/99 10:01p Dave
230 * Make sure game won't run in a drive's root directory. Make sure
231 * standalone routes suqad war messages properly to the host.
233 * 180 9/08/99 3:22p Dave
234 * Updated builtin mission list.
236 * 179 9/08/99 12:01p Jefff
237 * fixed Game_builtin_mission_list typo on Training-2.fs2
239 * 178 9/08/99 9:48a Andsager
240 * Add force feedback for engine wash.
242 * 177 9/07/99 4:01p Dave
243 * Fixed up a string.tbl paroblem (self destruct message). Make sure IPX
244 * does everything properly (setting up address when binding). Remove
245 * black rectangle background from UI_INPUTBOX.
247 * 176 9/13/99 2:40a Dave
248 * Comment in full 80 minute CD check for RELEASE_REAL builds.
250 * 175 9/06/99 6:38p Dave
251 * Improved CD detection code.
253 * 174 9/06/99 1:30a Dave
254 * Intermediate checkin. Started on enforcing CD-in-drive to play the
257 * 173 9/06/99 1:16a Dave
258 * Make sure the user sees the intro movie.
260 * 172 9/04/99 8:00p Dave
261 * Fixed up 1024 and 32 bit movie support.
263 * 171 9/03/99 1:32a Dave
264 * CD checking by act. Added support to play 2 cutscenes in a row
265 * seamlessly. Fixed super low level cfile bug related to files in the
266 * root directory of a CD. Added cheat code to set campaign mission # in
269 * 170 9/01/99 10:49p Dave
270 * Added nice SquadWar checkbox to the client join wait screen.
272 * 169 9/01/99 10:14a Dave
275 * 168 8/29/99 4:51p Dave
276 * Fixed damaged checkin.
278 * 167 8/29/99 4:18p Andsager
279 * New "burst" limit for friendly damage. Also credit more damage done
280 * against large friendly ships.
282 * 166 8/27/99 6:38p Alanl
283 * crush the blasted repeating messages bug
285 * 164 8/26/99 9:09p Dave
286 * Force framerate check in everything but a RELEASE_REAL build.
288 * 163 8/26/99 9:45a Dave
289 * First pass at easter eggs and cheats.
291 * 162 8/24/99 8:55p Dave
292 * Make sure nondimming pixels work properly in tech menu.
294 * 161 8/24/99 1:49a Dave
295 * Fixed client-side afterburner stuttering. Added checkbox for no version
296 * checking on PXO join. Made button info passing more friendly between
299 * 160 8/22/99 5:53p Dave
300 * Scoring fixes. Added self destruct key. Put callsigns in the logfile
301 * instead of ship designations for multiplayer players.
303 * 159 8/22/99 1:19p Dave
304 * Fixed up http proxy code. Cleaned up scoring code. Reverse the order in
305 * which d3d cards are detected.
307 * 158 8/20/99 2:09p Dave
308 * PXO banner cycling.
310 * 157 8/19/99 10:59a Dave
311 * Packet loss detection.
313 * 156 8/19/99 10:12a Alanl
314 * preload mission-specific messages on machines greater than 48MB
316 * 155 8/16/99 4:04p Dave
317 * Big honking checkin.
319 * 154 8/11/99 5:54p Dave
320 * Fixed collision problem. Fixed standalone ghost problem.
322 * 153 8/10/99 7:59p Jefff
325 * 152 8/10/99 6:54p Dave
326 * Mad optimizations. Added paging to the nebula effect.
328 * 151 8/10/99 3:44p Jefff
329 * loads Intelligence information on startup
331 * 150 8/09/99 3:47p Dave
332 * Fixed incorrect nebula regeneration. Default HUD to low-contrast in
333 * non-nebula missions.
335 * 149 8/09/99 2:21p Andsager
336 * Fix patching from multiplayer direct to launcher update tab.
338 * 148 8/09/99 10:36a Dave
339 * Version info for game.
341 * 147 8/06/99 9:46p Dave
342 * Hopefully final changes for the demo.
344 * 146 8/06/99 3:34p Andsager
345 * Make title version info "(D)" -> "D" show up nicely
347 * 145 8/06/99 2:59p Adamp
348 * Fixed NT launcher/update problem.
350 * 144 8/06/99 1:52p Dave
351 * Bumped up MAX_BITMAPS for the demo.
353 * 143 8/06/99 12:17p Andsager
354 * Demo: down to just 1 demo dog
356 * 142 8/05/99 9:39p Dave
357 * Yet another new checksum.
359 * 141 8/05/99 6:19p Dave
360 * New demo checksums.
362 * 140 8/05/99 5:31p Andsager
363 * Up demo version 1.01
365 * 139 8/05/99 4:22p Andsager
366 * No time limit on upsell screens. Reverse order of display of upsell
369 * 138 8/05/99 4:17p Dave
370 * Tweaks to client interpolation.
372 * 137 8/05/99 3:52p Danw
374 * 136 8/05/99 3:01p Danw
376 * 135 8/05/99 2:43a Anoop
377 * removed duplicate definition.
379 * 134 8/05/99 2:13a Dave
382 * 133 8/05/99 2:05a Dave
385 * 132 8/05/99 1:22a Andsager
388 * 131 8/04/99 9:51p Andsager
389 * Add title screen to demo
391 * 130 8/04/99 6:47p Jefff
392 * fixed link error resulting from #ifdefs
394 * 129 8/04/99 6:26p Dave
395 * Updated ship tbl checksum.
397 * 128 8/04/99 5:40p Andsager
398 * Add multiple demo dogs
400 * 127 8/04/99 5:36p Andsager
401 * Show upsell screens at end of demo campaign before returning to main
404 * 126 8/04/99 11:42a Danw
405 * tone down EAX reverb
407 * 125 8/04/99 11:23a Dave
408 * Updated demo checksums.
410 * 124 8/03/99 11:02p Dave
411 * Maybe fixed sync problems in multiplayer.
413 * 123 8/03/99 6:21p Jefff
416 * 122 8/03/99 3:44p Andsager
417 * Launch laucher if trying to run FS without first having configured
420 * 121 8/03/99 12:45p Dave
423 * 120 8/02/99 9:13p Dave
426 * 119 7/30/99 10:31p Dave
427 * Added comm menu to the configurable hud files.
429 * 118 7/30/99 5:17p Andsager
430 * first fs2demo checksums
432 * 117 7/29/99 3:09p Anoop
434 * 116 7/29/99 12:05a Dave
435 * Nebula speed optimizations.
437 * 115 7/27/99 8:59a Andsager
438 * Make major, minor version consistent for all builds. Only show major
439 * and minor for launcher update window.
441 * 114 7/26/99 5:50p Dave
442 * Revised ingame join. Better? We'll see....
444 * 113 7/26/99 5:27p Andsager
445 * Add training mission as builtin to demo build
447 * 112 7/24/99 1:54p Dave
448 * Hud text flash gauge. Reworked dead popup to use 4 buttons in red-alert
451 * 111 7/22/99 4:00p Dave
452 * Fixed beam weapon muzzle glow rendering. Externalized hud shield info.
454 * 110 7/21/99 8:10p Dave
455 * First run of supernova effect.
457 * 109 7/20/99 1:49p Dave
458 * Peter Drake build. Fixed some release build warnings.
460 * 108 7/19/99 2:26p Andsager
461 * set demo multiplayer missions
463 * 107 7/18/99 5:19p Dave
464 * Jump node icon. Fixed debris fogging. Framerate warning stuff.
466 * 106 7/16/99 1:50p Dave
467 * 8 bit aabitmaps. yay.
469 * 105 7/15/99 3:07p Dave
470 * 32 bit detection support. Mouse coord commandline.
472 * 104 7/15/99 2:13p Dave
473 * Added 32 bit detection.
475 * 103 7/15/99 9:20a Andsager
476 * FS2_DEMO initial checkin
478 * 102 7/14/99 11:02a Dave
479 * Skill level default back to easy. Blech.
481 * 101 7/09/99 5:54p Dave
482 * Seperated cruiser types into individual types. Added tons of new
483 * briefing icons. Campaign screen.
485 * 100 7/08/99 4:43p Andsager
486 * New check for sparky_hi and print if not found.
488 * 99 7/08/99 10:53a Dave
489 * New multiplayer interpolation scheme. Not 100% done yet, but still
490 * better than the old way.
492 * 98 7/06/99 4:24p Dave
493 * Mid-level checkin. Starting on some potentially cool multiplayer
496 * 97 7/06/99 3:35p Andsager
497 * Allow movie to play before red alert mission.
499 * 96 7/03/99 5:50p Dave
500 * Make rotated bitmaps draw properly in padlock views.
502 * 95 7/02/99 9:55p Dave
503 * Player engine wash sound.
505 * 94 7/02/99 4:30p Dave
506 * Much more sophisticated lightning support.
508 * 93 6/29/99 7:52p Dave
509 * Put in exception handling in FS2.
511 * 92 6/22/99 9:37p Dave
512 * Put in pof spewing.
514 * 91 6/16/99 4:06p Dave
515 * New pilot info popup. Added new draw-bitmap-as-poly function.
517 * 90 6/15/99 1:56p Andsager
518 * For release builds, allow start up in high res only with
521 * 89 6/15/99 9:34a Dave
522 * Fixed key checking in single threaded version of the stamp notification
525 * 88 6/09/99 2:55p Andsager
526 * Allow multiple asteroid subtypes (of large, medium, small) and follow
529 * 87 6/08/99 1:14a Dave
530 * Multi colored hud test.
532 * 86 6/04/99 9:52a Dave
533 * Fixed some rendering problems.
535 * 85 6/03/99 10:15p Dave
536 * Put in temporary main hall screen.
538 * 84 6/02/99 6:18p Dave
539 * Fixed TNT lockup problems! Wheeeee!
541 * 83 6/01/99 3:52p Dave
542 * View footage screen. Fixed xstrings to not display the & symbol. Popup,
543 * dead popup, pxo find player popup, pxo private room popup.
545 * 82 5/26/99 1:28p Jasenw
546 * changed coords for loading ani
548 * 81 5/26/99 11:46a Dave
549 * Added ship-blasting lighting and made the randomization of lighting
550 * much more customizable.
552 * 80 5/24/99 5:45p Dave
553 * Added detail levels to the nebula, with a decent speedup. Split nebula
554 * lightning into its own section.
572 #include "systemvars.h"
577 #include "starfield.h"
578 #include "lighting.h"
583 #include "fireballs.h"
587 #include "floating.h"
588 #include "gamesequence.h"
590 #include "optionsmenu.h"
591 #include "playermenu.h"
592 #include "trainingmenu.h"
593 #include "techmenu.h"
596 #include "hudmessage.h"
598 #include "missiongoals.h"
599 #include "missionparse.h"
604 #include "multiutil.h"
605 #include "multimsgs.h"
609 #include "freespace.h"
610 #include "managepilot.h"
612 #include "contexthelp.h"
615 #include "missionbrief.h"
616 #include "missiondebrief.h"
618 #include "missionshipchoice.h"
620 #include "hudconfig.h"
621 #include "controlsconfig.h"
622 #include "missionmessage.h"
623 #include "missiontraining.h"
625 #include "hudtarget.h"
627 #include "eventmusic.h"
628 #include "animplay.h"
629 #include "missionweaponchoice.h"
630 #include "missionlog.h"
631 #include "audiostr.h"
633 #include "missioncampaign.h"
635 #include "missionhotkey.h"
636 #include "objectsnd.h"
637 #include "cmeasure.h"
639 #include "linklist.h"
640 #include "shockwave.h"
641 #include "afterburner.h"
646 #include "stand_gui.h"
647 #include "pcxutils.h"
648 #include "hudtargetbox.h"
649 #include "multi_xfer.h"
650 #include "hudescort.h"
651 #include "multiutil.h"
654 #include "multiteamselect.h"
657 #include "readyroom.h"
658 #include "mainhallmenu.h"
659 #include "multilag.h"
661 #include "particle.h"
663 #include "multi_ingame.h"
664 #include "snazzyui.h"
665 #include "asteroid.h"
666 #include "popupdead.h"
667 #include "multi_voice.h"
668 #include "missioncmdbrief.h"
669 #include "redalert.h"
670 #include "gameplayhelp.h"
671 #include "multilag.h"
672 #include "staticrand.h"
673 #include "multi_pmsg.h"
674 #include "levelpaging.h"
675 #include "observer.h"
676 #include "multi_pause.h"
677 #include "multi_endgame.h"
678 #include "cutscenes.h"
679 #include "multi_respawn.h"
681 #include "multi_obj.h"
682 #include "multi_log.h"
684 #include "localize.h"
685 #include "osregistry.h"
686 #include "barracks.h"
687 #include "missionpause.h"
689 #include "alphacolors.h"
690 #include "objcollide.h"
693 #include "neblightning.h"
694 #include "shipcontrails.h"
697 #include "multi_dogfight.h"
698 #include "multi_rate.h"
699 #include "muzzleflash.h"
703 #include "mainhalltemp.h"
704 #include "exceptionhandler.h"
708 #include "supernova.h"
709 #include "hudshield.h"
710 // #include "names.h"
712 #include "missionloopbrief.h"
716 #error macro FRED is defined when trying to build release Fred. Please undefine FRED macro in build settings
722 // 1.00.04 5/26/98 MWA -- going final (12 pm)
723 // 1.00.03 5/26/98 MWA -- going final (3 am)
724 // 1.00.02 5/25/98 MWA -- going final
725 // 1.00.01 5/25/98 MWA -- going final
726 // 0.90 5/21/98 MWA -- getting ready for final.
727 // 0.10 4/9/98. Set by MK.
729 // Demo version: (obsolete since DEMO codebase split from tree)
730 // 0.03 4/10/98 AL. Interplay rev
731 // 0.02 4/8/98 MK. Increased when this system was modified.
732 // 0.01 4/7/98? AL. First release to Interplay QA.
735 // 1.00 5/28/98 AL. First release to Interplay QA.
737 void game_level_init(int seed = -1);
738 void game_post_level_init();
739 void game_do_frame();
740 void game_update_missiontime(); // called from game_do_frame() and navmap_do_frame()
741 void game_reset_time();
742 void game_show_framerate(); // draws framerate in lower right corner
744 int Game_no_clear = 0;
746 int Pofview_running = 0;
747 int Nebedit_running = 0;
749 typedef struct big_expl_flash {
750 float max_flash_intensity; // max intensity
751 float cur_flash_intensity; // cur intensity
752 int flash_start; // start time
755 #define FRAME_FILTER 16
757 #define DEFAULT_SKILL_LEVEL 1
758 int Game_skill_level = DEFAULT_SKILL_LEVEL;
760 #define VIEWER_ZOOM_DEFAULT 0.75f // Default viewer zoom, 0.625 as per multi-lateral agreement on 3/24/97
761 float Viewer_zoom = VIEWER_ZOOM_DEFAULT;
763 #define EXE_FNAME ("fs2.exe")
764 #define LAUNCHER_FNAME ("freespace2.exe")
767 // JAS: Code for warphole camera.
768 // Needs to be cleaned up.
769 vector Camera_pos = ZERO_VECTOR;
770 vector Camera_velocity = ZERO_VECTOR;
771 vector Camera_desired_velocity = ZERO_VECTOR;
772 matrix Camera_orient = IDENTITY_MATRIX;
773 float Camera_damping = 1.0f;
774 float Camera_time = 0.0f;
775 float Warpout_time = 0.0f;
776 int Warpout_forced = 0; // Set if this is a forced warpout that cannot be cancelled.
777 int Warpout_sound = -1;
779 int Use_joy_mouse = 0;
780 int Use_palette_flash = 1;
782 int Use_fullscreen_at_startup = 0;
784 int Show_area_effect = 0;
785 object *Last_view_target = NULL;
787 int dogfight_blown = 0;
790 float frametimes[FRAME_FILTER];
791 float frametotal = 0.0f;
795 int Show_framerate = 0;
797 int Show_framerate = 1;
800 int Framerate_cap = 120;
803 int Show_target_debug_info = 0;
804 int Show_target_weapons = 0;
808 static int Show_player_pos = 0; // debug console command to show player world pos on HUD
811 int Debug_octant = -1;
813 fix Game_time_compression = F1_0;
815 // if the ships.tbl the player has is valid
816 int Game_ships_tbl_valid = 0;
818 // if the weapons.tbl the player has is valid
819 int Game_weapons_tbl_valid = 0;
823 extern int Player_attacking_enabled;
827 int Pre_player_entry;
829 int Fred_running = 0;
830 char Game_current_mission_filename[MAX_FILENAME_LEN];
831 int game_single_step = 0;
832 int last_single_step=0;
834 extern int MSG_WINDOW_X_START; // used to position mission_time and shields output
835 extern int MSG_WINDOW_Y_START;
836 extern int MSG_WINDOW_HEIGHT;
838 int game_zbuffer = 1;
839 //static int Game_music_paused;
840 static int Game_paused;
844 #define EXPIRE_BAD_CHECKSUM 1
845 #define EXPIRE_BAD_TIME 2
847 extern void ssm_init();
848 extern void ssm_level_init();
849 extern void ssm_process();
851 // static variable to contain the time this version was built
852 // commented out for now until
853 // I figure out how to get the username into the file
854 //LOCAL char freespace_build_time[] = "Compiled on:"__DATE__" "__TIME__" by "__USER__;
856 // defines and variables used for dumping frame for making trailers.
858 int Debug_dump_frames = 0; // Set to 0 to not dump frames, else equal hz to dump. (15 or 30 probably)
859 int Debug_dump_trigger = 0;
860 int Debug_dump_frame_count;
861 int Debug_dump_frame_num = 0;
862 #define DUMP_BUFFER_NUM_FRAMES 1 // store every 15 frames
865 // amount of time to wait after the player has died before we display the death died popup
866 #define PLAYER_DIED_POPUP_WAIT 2500
867 int Player_died_popup_wait = -1;
868 int Player_multi_died_check = -1;
870 // builtin mission list stuff
872 int Game_builtin_mission_count = 6;
873 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
874 { "SPDemo-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
875 { "SPDemo-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
876 { "DemoTrain.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
877 { "Demo.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE) },
878 { "MPDemo-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
879 { "Demo-DOG-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
881 #elif defined(FS1_DEMO)
882 int Game_builtin_mission_count = 5;
883 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
884 { "btmdemo.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
885 { "demo.fsc", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE) },
886 { "demo01.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
887 { "demo02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
888 { "demo02b.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
890 #elif defined(PD_BUILD)
891 int Game_builtin_mission_count = 4;
892 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
893 { "sm1-01.fs2", (FSB_FROM_VOLITION) },
894 { "sm1-05.fs2", (FSB_FROM_VOLITION) },
895 { "sm1-01", (FSB_FROM_VOLITION) },
896 { "sm1-05", (FSB_FROM_VOLITION) },
898 #elif defined(MULTIPLAYER_BETA)
899 int Game_builtin_mission_count = 17;
900 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
902 { "md-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
903 { "md-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
904 { "md-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
905 { "md-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
906 { "md-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
907 { "md-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
908 { "md-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
909 { "mt-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
910 { "mt-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
911 { "m-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
912 { "m-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
913 { "m-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
914 { "templar-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
915 { "templar-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
916 { "templar-03a.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
917 { "templar-04a.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
918 { "templar.fc2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE) },
920 #elif defined(OEM_BUILD)
921 int Game_builtin_mission_count = 17;
922 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
923 // oem version - act 1 only
924 { "freespace2oem.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE) },
927 { "sm1-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
928 { "sm1-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
929 { "sm1-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
930 { "sm1-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
931 { "sm1-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
932 { "sm1-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
933 { "sm1-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
934 { "sm1-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
935 { "sm1-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
936 { "sm1-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
937 { "training-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
938 { "training-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
939 { "training-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
940 { "tsm-104.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
941 { "tsm-105.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
942 { "tsm-106.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) }
944 #elif defined(MAKE_FS1)
945 int Game_builtin_mission_count = 125;
946 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
947 // single player campaign
948 { "freespace.fsc", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE) },
951 { "sm1-01.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
952 { "sm1-02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
953 { "sm1-03a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
954 { "sm1-04a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
955 { "sm1-05a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
956 { "sm1-06a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
957 { "sm1-07a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
958 { "sm1-08a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
959 { "sm1-09a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
960 { "sm1-10a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
963 { "sm2-01a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
964 { "sm2-02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
965 { "sm2-03a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
966 { "sm2-04a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
967 { "sm2-05a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
968 { "sm2-06a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
969 { "sm2-07a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
970 { "sm2-08a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
971 { "sm2-09a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
972 { "sm2-10a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
975 { "sm3-01a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
976 { "sm3-02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
977 { "sm3-03a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
978 { "sm3-04a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
979 { "sm3-05a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
980 { "sm3-06a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
981 { "sm3-07a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
982 { "sm3-08a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
983 { "sm3-09a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
986 { "t-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
987 { "v-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
988 { "s-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
991 { "btm-01.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
992 { "btm-02.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
993 { "btm-03.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
994 { "btm-04.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
995 { "btm-05.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
998 { "m-hope.fsc", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE) },
999 { "m-altair.fsc", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE) },
1001 { "m-v-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1002 { "m-va.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1003 { "m-unstoppable.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1004 { "m-t-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1005 { "m-s-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1006 { "m-rescue.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1007 { "m-pain.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1008 { "m-orecovery.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1009 { "mm3-01a.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1010 { "mm3-02a.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1011 { "mm3-03a.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1012 { "mm3-04a.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1013 { "mm3-05a.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1014 { "mm3-06a.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1015 { "m-guardduty.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1016 { "m-gate.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1017 { "m-duel.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1018 { "m-convoyassault.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1019 { "m-clash.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1021 // SilentThreat missions
1022 // Main SilentThreat campaign
1023 { "SilentThreat.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN_FILE) },
1025 { "md-01.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1026 { "md-02.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1027 { "md-03.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1028 { "md-04.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1029 { "md-05.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1030 { "md-06.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1031 { "md-07.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1032 { "md-08.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1033 { "md-09.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1034 { "md-10.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1035 { "md-11.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1036 { "md-12.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1038 // SilentThreat Part 1 - multi-coop
1039 { "ST-Part1.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE) },
1041 { "stmm-01.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1042 { "stmm-02.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1043 { "stmm-03.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1045 // SilentThreat Part 2 - multi-coop
1046 { "ST-Part2.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE) },
1048 { "stmm-04.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1049 { "stmm-05.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1050 { "stmm-06.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1052 // SilentThreat Part 3 - multi-coop
1053 { "ST-Part3.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE) },
1055 { "stmm-07.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1056 { "stmm-08.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1057 { "stmm-09.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1059 // SilentThreat Part 4 - multi-coop
1060 { "ST-Part4.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE) },
1062 { "stmm-10.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1063 { "stmm-11.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1064 { "stmm-12.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1066 // multiplayer missions
1067 { "mdmm-01.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI) },
1068 { "mdmm-02.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI) },
1069 { "mdmm-03.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI) },
1070 { "mdmm-04.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI) },
1071 // user supplied missions
1072 { "mdu-02.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1073 { "mdu-03.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1074 { "mdu-04.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1075 { "mdu-05.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1076 { "mdu-06.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1077 { "mdu-07.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1078 { "mdu-08.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1079 { "mdu-09.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1080 { "mdu-10.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1081 { "mdu-11.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1082 { "mdu-12.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1083 { "mdu-13.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1084 { "mdu-14.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1085 { "mdu-15.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1086 { "mdu-16.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1087 { "mdu-17.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1088 { "mdu-18.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1089 { "mdu-19.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1090 { "mdu-20.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1091 { "mdu-21.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1092 { "mdu-22.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1093 { "mdu-23.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1094 { "mdu-24.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1095 { "mdu-25.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1096 { "mdu-26.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1097 { "mdu-27.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1098 { "mdu-28.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1099 { "mdu-29.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1100 { "mdu-30.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1101 { "mdu-31.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1102 { "mdumm-01.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1103 { "mdumm-02.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1106 int Game_builtin_mission_count = 92;
1107 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
1108 // single player campaign
1109 { "freespace2.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE) },
1112 { "sm1-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1113 { "sm1-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1114 { "sm1-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1115 { "sm1-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1116 { "sm1-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1117 { "sm1-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1118 { "sm1-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1119 { "sm1-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1120 { "sm1-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1121 { "sm1-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1122 { "loop1-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1123 { "loop1-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1124 { "loop1-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1125 { "training-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1126 { "training-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1127 { "training-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1128 { "tsm-104.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1129 { "tsm-105.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1130 { "tsm-106.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1133 { "sm2-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1134 { "sm2-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1135 { "sm2-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1136 { "sm2-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1137 { "sm2-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1138 { "sm2-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1139 { "sm2-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1140 { "sm2-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1141 { "sm2-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1142 { "sm2-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1145 { "sm3-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1146 { "sm3-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1147 { "sm3-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1148 { "sm3-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1149 { "sm3-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1150 { "sm3-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1151 { "sm3-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1152 { "sm3-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1153 { "sm3-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1154 { "sm3-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1155 { "loop2-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1156 { "loop2-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1158 // multiplayer missions
1161 { "g-shi.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1162 { "g-ter.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1163 { "g-vas.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1166 { "m-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1167 { "m-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1168 { "m-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1169 { "m-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1172 { "mdh-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1173 { "mdh-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1174 { "mdh-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1175 { "mdh-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1176 { "mdh-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1177 { "mdh-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1178 { "mdh-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1179 { "mdh-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1180 { "mdh-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1181 { "mdl-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1182 { "mdl-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1183 { "mdl-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1184 { "mdl-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1185 { "mdl-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1186 { "mdl-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1187 { "mdl-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1188 { "mdl-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1189 { "mdl-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1190 { "mdm-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1191 { "mdm-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1192 { "mdm-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1193 { "mdm-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1194 { "mdm-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1195 { "mdm-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1196 { "mdm-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1197 { "mdm-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1198 { "mdm-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1199 { "osdog.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1202 { "mt-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1203 { "mt-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1204 { "mt-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1205 { "mt-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1206 { "mt-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1207 { "mt-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1208 { "mt-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1209 { "mt-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1210 { "mt-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1211 { "mt-10.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1214 { "templar.fc2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE) },
1215 { "templar-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
1216 { "templar-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
1217 { "templar-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
1218 { "templar-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
1223 // Internal function prototypes
1224 void game_maybe_draw_mouse(float frametime);
1225 void init_animating_pointer();
1226 void load_animating_pointer(const char *filename, int dx, int dy);
1227 void unload_animating_pointer();
1228 void game_do_training_checks();
1229 void game_shutdown(void);
1230 void game_show_event_debug(float frametime);
1231 void game_event_debug_init();
1233 void demo_upsell_show_screens();
1234 void game_start_subspace_ambient_sound();
1235 void game_stop_subspace_ambient_sound();
1236 void verify_ships_tbl();
1237 void verify_weapons_tbl();
1238 void display_title_screen();
1240 // loading background filenames
1241 static const char *Game_loading_bground_fname[GR_NUM_RESOLUTIONS] = {
1242 "LoadingBG", // GR_640
1243 "2_LoadingBG" // GR_1024
1247 static const char *Game_loading_ani_fname[GR_NUM_RESOLUTIONS] = {
1248 "Loading.ani", // GR_640
1249 "2_Loading.ani" // GR_1024
1252 #if defined(FS2_DEMO) || defined(FS1_DEMO)
1253 static const char *Game_demo_title_screen_fname[GR_NUM_RESOLUTIONS] = {
1261 #elif defined(OEM_BUILD)
1262 static const char *Game_demo_title_screen_fname[GR_NUM_RESOLUTIONS] = {
1271 // How much RAM is on this machine. Set in WinMain
1272 static int Freespace_total_ram = 0;
1275 float Game_flash_red = 0.0f;
1276 float Game_flash_green = 0.0f;
1277 float Game_flash_blue = 0.0f;
1278 float Sun_spot = 0.0f;
1279 big_expl_flash Big_expl_flash = {0.0f, 0.0f, 0};
1281 // game shudder stuff (in ms)
1282 int Game_shudder_time = -1;
1283 int Game_shudder_total = 0;
1284 float Game_shudder_intensity = 0.0f; // should be between 0.0 and 100.0
1287 sound_env Game_sound_env;
1288 //sound_env Game_default_sound_env = {SND_ENV_AUDITORIUM, 0.25f, 0.35f, 3.0f};
1289 sound_env Game_default_sound_env = {SND_ENV_GENERIC, 0.2F,0.2F,1.0F};
1291 int Game_sound_env_update_timestamp;
1293 // WARPIN CRAP BEGIN --------------------------------------------------------------------------------------------
1296 // WARPIN CRAP END --------------------------------------------------------------------------------------------
1298 fs_builtin_mission *game_find_builtin_mission(const char *filename)
1302 // look through all existing builtin missions
1303 for(idx=0; idx<Game_builtin_mission_count; idx++){
1304 if(!stricmp(Game_builtin_mission_list[idx].filename, filename)){
1305 return &Game_builtin_mission_list[idx];
1313 int game_get_default_skill_level()
1315 return DEFAULT_SKILL_LEVEL;
1319 void game_flash_reset()
1321 Game_flash_red = 0.0f;
1322 Game_flash_green = 0.0f;
1323 Game_flash_blue = 0.0f;
1325 Big_expl_flash.max_flash_intensity = 0.0f;
1326 Big_expl_flash.cur_flash_intensity = 0.0f;
1327 Big_expl_flash.flash_start = 0;
1330 float Gf_critical = -1.0f; // framerate we should be above on the average for this mission
1331 float Gf_critical_time = 0.0f; // how much time we've been at the critical framerate
1333 void game_framerate_check_init()
1335 // zero critical time
1336 Gf_critical_time = 0.0f;
1339 if(The_mission.flags & MISSION_FLAG_FULLNEB){
1340 // if this is a glide card
1341 if(gr_screen.mode == GR_GLIDE){
1343 extern GrHwConfiguration hwconfig;
1346 if(hwconfig.SSTs[0].sstBoard.VoodooConfig.fbRam >= 4){
1347 Gf_critical = 15.0f;
1351 Gf_critical = 10.0f;
1356 Gf_critical = 15.0f;
1359 // d3d. only care about good cards here I guess (TNT)
1361 Gf_critical = 15.0f;
1364 // if this is a glide card
1365 if(gr_screen.mode == GR_GLIDE){
1367 extern GrHwConfiguration hwconfig;
1370 if(hwconfig.SSTs[0].sstBoard.VoodooConfig.fbRam >= 4){
1371 Gf_critical = 25.0f;
1375 Gf_critical = 20.0f;
1380 Gf_critical = 25.0f;
1383 // d3d. only care about good cards here I guess (TNT)
1385 Gf_critical = 25.0f;
1390 extern float Framerate;
1391 void game_framerate_check()
1395 // if the current framerate is above the critical level, add frametime
1396 if(Framerate >= Gf_critical){
1397 Gf_critical_time += flFrametime;
1400 if(!Show_framerate){
1404 // display if we're above the critical framerate
1405 if(Framerate < Gf_critical){
1406 gr_set_color_fast(&Color_bright_red);
1407 gr_string(200, y_start, "Framerate warning");
1412 // display our current pct of good frametime
1413 if(f2fl(Missiontime) >= 0.0f){
1414 float pct = (Gf_critical_time / f2fl(Missiontime)) * 100.0f;
1417 gr_set_color_fast(&Color_bright_green);
1419 gr_set_color_fast(&Color_bright_red);
1422 gr_printf(200, y_start, "%d%%", (int)pct);
1429 // Adds a flash effect. These can be positive or negative.
1430 // The range will get capped at around -1 to 1, so stick
1431 // with a range like that.
1432 void game_flash( float r, float g, float b )
1434 Game_flash_red += r;
1435 Game_flash_green += g;
1436 Game_flash_blue += b;
1438 if ( Game_flash_red < -1.0f ) {
1439 Game_flash_red = -1.0f;
1440 } else if ( Game_flash_red > 1.0f ) {
1441 Game_flash_red = 1.0f;
1444 if ( Game_flash_green < -1.0f ) {
1445 Game_flash_green = -1.0f;
1446 } else if ( Game_flash_green > 1.0f ) {
1447 Game_flash_green = 1.0f;
1450 if ( Game_flash_blue < -1.0f ) {
1451 Game_flash_blue = -1.0f;
1452 } else if ( Game_flash_blue > 1.0f ) {
1453 Game_flash_blue = 1.0f;
1458 // Adds a flash for Big Ship explosions
1459 // cap range from 0 to 1
1460 void big_explosion_flash(float flash)
1462 Big_expl_flash.flash_start = timestamp(1);
1466 } else if (flash < 0.0f) {
1470 Big_expl_flash.max_flash_intensity = flash;
1471 Big_expl_flash.cur_flash_intensity = 0.0f;
1474 // Amount to diminish palette towards normal, per second.
1475 #define DIMINISH_RATE 0.75f
1476 #define SUN_DIMINISH_RATE 6.00f
1480 float sn_glare_scale = 1.7f;
1483 dc_get_arg(ARG_FLOAT);
1484 sn_glare_scale = Dc_arg_float;
1487 float Supernova_last_glare = 0.0f;
1488 void game_sunspot_process(float frametime)
1492 float Sun_spot_goal = 0.0f;
1495 sn_stage = supernova_active();
1497 // sunspot differently based on supernova stage
1499 // approaching. player still in control
1502 pct = (1.0f - (supernova_time_left() / SUPERNOVA_CUT_TIME));
1505 light_get_global_dir(&light_dir, 0);
1507 dot = vm_vec_dot( &light_dir, &Eye_matrix.v.fvec );
1510 // scale it some more
1511 dot = dot * (0.5f + (pct * 0.5f));
1514 Sun_spot_goal += (dot * sn_glare_scale);
1517 // draw the sun glow
1518 if ( !shipfx_eye_in_shadow( &Eye_position, Viewer_obj, 0 ) ) {
1519 // draw the glow for this sun
1520 stars_draw_sun_glow(0);
1523 Supernova_last_glare = Sun_spot_goal;
1526 // camera cut. player not in control. note : at this point camera starts out facing the sun. so we can go nice and bright
1529 Sun_spot_goal = 0.9f;
1530 Sun_spot_goal += (1.0f - (supernova_time_left() / SUPERNOVA_CUT_TIME)) * 0.1f;
1532 if(Sun_spot_goal > 1.0f){
1533 Sun_spot_goal = 1.0f;
1536 Sun_spot_goal *= sn_glare_scale;
1537 Supernova_last_glare = Sun_spot_goal;
1540 // fade to white. display dead popup
1543 Supernova_last_glare += (2.0f * flFrametime);
1544 if(Supernova_last_glare > 2.0f){
1545 Supernova_last_glare = 2.0f;
1548 Sun_spot_goal = Supernova_last_glare;
1555 // check sunspots for all suns
1556 n_lights = light_get_global_count();
1559 for(idx=0; idx<n_lights; idx++){
1560 //(vector *eye_pos, matrix *eye_orient)
1561 if ( !shipfx_eye_in_shadow( &Eye_position, Viewer_obj, idx ) ) {
1564 light_get_global_dir(&light_dir, idx);
1566 float dot = vm_vec_dot( &light_dir, &Eye_matrix.v.fvec )*0.5f+0.5f;
1568 Sun_spot_goal += (float)pow(dot,85.0f);
1570 // draw the glow for this sun
1571 stars_draw_sun_glow(idx);
1573 Sun_spot_goal = 0.0f;
1579 Sun_spot_goal = 0.0f;
1583 float dec_amount = frametime*SUN_DIMINISH_RATE;
1585 if ( Sun_spot < Sun_spot_goal ) {
1586 Sun_spot += dec_amount;
1587 if ( Sun_spot > Sun_spot_goal ) {
1588 Sun_spot = Sun_spot_goal;
1590 } else if ( Sun_spot > Sun_spot_goal ) {
1591 Sun_spot -= dec_amount;
1592 if ( Sun_spot < Sun_spot_goal ) {
1593 Sun_spot = Sun_spot_goal;
1599 // Call once a frame to diminish the
1600 // flash effect to 0.
1601 void game_flash_diminish(float frametime)
1603 float dec_amount = frametime*DIMINISH_RATE;
1605 if ( Game_flash_red > 0.0f ) {
1606 Game_flash_red -= dec_amount;
1607 if ( Game_flash_red < 0.0f )
1608 Game_flash_red = 0.0f;
1610 Game_flash_red += dec_amount;
1611 if ( Game_flash_red > 0.0f )
1612 Game_flash_red = 0.0f;
1615 if ( Game_flash_green > 0.0f ) {
1616 Game_flash_green -= dec_amount;
1617 if ( Game_flash_green < 0.0f )
1618 Game_flash_green = 0.0f;
1620 Game_flash_green += dec_amount;
1621 if ( Game_flash_green > 0.0f )
1622 Game_flash_green = 0.0f;
1625 if ( Game_flash_blue > 0.0f ) {
1626 Game_flash_blue -= dec_amount;
1627 if ( Game_flash_blue < 0.0f )
1628 Game_flash_blue = 0.0f;
1630 Game_flash_blue += dec_amount;
1631 if ( Game_flash_blue > 0.0f )
1632 Game_flash_blue = 0.0f;
1635 // update big_explosion_cur_flash
1636 #define TIME_UP 1500
1637 #define TIME_DOWN 2500
1638 int duration = TIME_UP + TIME_DOWN;
1639 int time = timestamp_until(Big_expl_flash.flash_start);
1640 if (time > -duration) {
1642 if (time < TIME_UP) {
1643 Big_expl_flash.cur_flash_intensity = Big_expl_flash.max_flash_intensity * time / (float) TIME_UP;
1646 Big_expl_flash.cur_flash_intensity = Big_expl_flash.max_flash_intensity * ((float) TIME_DOWN - time) / (float) TIME_DOWN;
1650 if ( Use_palette_flash ) {
1652 // static int or=0, og=0, ob=0;
1654 // Change the 200 to change the color range of colors.
1655 r = fl2i( Game_flash_red*128.0f );
1656 g = fl2i( Game_flash_green*128.0f );
1657 b = fl2i( Game_flash_blue*128.0f );
1659 if ( Sun_spot > 0.0f ) {
1660 r += fl2i(Sun_spot*128.0f);
1661 g += fl2i(Sun_spot*128.0f);
1662 b += fl2i(Sun_spot*128.0f);
1665 if ( Big_expl_flash.cur_flash_intensity > 0.0f ) {
1666 r += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1667 g += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1668 b += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1671 if ( r < 0 ) r = 0; else if ( r > 255 ) r = 255;
1672 if ( g < 0 ) g = 0; else if ( g > 255 ) g = 255;
1673 if ( b < 0 ) b = 0; else if ( b > 255 ) b = 255;
1675 if ( (r!=0) || (g!=0) || (b!=0) ) {
1676 gr_flash( r, g, b );
1678 //mprintf(( "Flash! %d,%d,%d\n", r, g, b ));
1689 void game_level_close()
1691 // De-Initialize the game subsystems
1692 event_music_level_close();
1693 game_stop_looped_sounds();
1695 obj_snd_level_close(); // uninit object-linked persistant sounds
1696 gamesnd_unload_gameplay_sounds(); // unload gameplay sounds from memory
1697 anim_level_close(); // stop and clean up any anim instances
1698 message_mission_shutdown(); // called after anim_level_close() to make sure anim instances are free
1699 shockwave_level_close();
1700 fireball_level_close();
1702 mission_event_shutdown();
1703 asteroid_level_close();
1704 model_cache_reset(); // Reset/free all the model caching stuff
1705 flak_level_close(); // unload flak stuff
1706 neb2_level_close(); // shutdown gaseous nebula stuff
1709 mflash_level_close();
1710 mission_brief_common_reset(); // close out parsed briefing/mission stuff
1712 audiostream_unpause_all();
1717 // intializes game stuff and loads the mission. Returns 0 on failure, 1 on success
1718 // input: seed => DEFAULT PARAMETER (value -1). Only set by demo playback code.
1719 void game_level_init(int seed)
1721 // seed the random number generator
1723 // if no seed was passed, seed the generator either from the time value, or from the
1724 // netgame security flags -- ensures that all players in multiplayer game will have the
1725 // same randon number sequence (with static rand functions)
1726 if ( Game_mode & GM_NORMAL ) {
1727 Game_level_seed = time(NULL);
1729 Game_level_seed = Netgame.security;
1732 // mwa 9/17/98 -- maybe this assert isn't needed????
1733 Assert( !(Game_mode & GM_MULTIPLAYER) );
1734 Game_level_seed = seed;
1736 srand( Game_level_seed );
1738 // semirand function needs to get re-initted every time in multiplayer
1739 if ( Game_mode & GM_MULTIPLAYER ){
1745 Key_normal_game = (Game_mode & GM_NORMAL);
1748 Game_shudder_time = -1;
1750 // Initialize the game subsystems
1751 // timestamp_reset(); // Must be inited before everything else
1753 game_reset_time(); // resets time, and resets saved time too
1755 obj_init(); // Must be inited before the other systems
1756 model_free_all(); // Free all existing models
1757 mission_brief_common_init(); // Free all existing briefing/debriefing text
1758 weapon_level_init();
1759 ai_level_init(); // Call this before ship_init() because it reads ai.tbl.
1761 player_level_init();
1762 shipfx_flash_init(); // Init the ship gun flash system.
1763 game_flash_reset(); // Reset the flash effect
1764 particle_init(); // Reset the particle system
1768 shield_hit_init(); // Initialize system for showing shield hits
1769 radar_mission_init();
1770 mission_init_goals();
1773 obj_snd_level_init(); // init object-linked persistant sounds
1775 shockwave_level_init();
1776 afterburner_level_init();
1777 scoring_level_init( &Player->stats );
1779 asteroid_level_init();
1780 control_config_clear_used_status();
1781 collide_ship_ship_sounds_init();
1783 Pre_player_entry = 1; // Means the player has not yet entered.
1784 Entry_delay_time = 0; // Could get overwritten in mission read.
1785 fireball_preload(); // page in warphole bitmaps
1787 flak_level_init(); // initialize flak - bitmaps, etc
1788 ct_level_init(); // initialize ships contrails, etc
1789 awacs_level_init(); // initialize AWACS
1790 beam_level_init(); // initialize beam weapons
1791 mflash_level_init();
1793 supernova_level_init();
1795 // multiplayer dogfight hack
1798 shipfx_engine_wash_level_init();
1802 Last_view_target = NULL;
1807 // campaign wasn't ended
1808 Campaign_ended_in_mission = 0;
1811 // called when a mission is over -- does server specific stuff.
1812 void freespace_stop_mission()
1815 Game_mode &= ~GM_IN_MISSION;
1818 // called at frame interval to process networking stuff
1819 void game_do_networking()
1821 Assert( Net_player != NULL );
1822 if (!(Game_mode & GM_MULTIPLAYER)){
1826 // see if this player should be reading/writing data. Bit is set when at join
1827 // screen onward until quits back to main menu.
1828 if ( !(Net_player->flags & NETINFO_FLAG_DO_NETWORKING) ){
1832 if(gameseq_get_state()!=GS_STATE_MULTI_PAUSED){
1835 multi_pause_do_frame();
1840 // Loads the best palette for this level, based
1841 // on nebula color and hud color. You could just call palette_load_table with
1842 // the appropriate filename, but who wants to do that.
1843 void game_load_palette()
1845 char palette_filename[1024];
1847 // We only use 3 hud colors right now
1849 Assert( HUD_config.main_color >= 0 );
1850 Assert( HUD_config.main_color <= 2 );
1853 Assert( Mission_palette >= 0 );
1854 Assert( Mission_palette <= 98 );
1857 if ( The_mission.flags & MISSION_FLAG_SUBSPACE ) {
1858 strcpy( palette_filename, NOX("gamepalette-subspace") );
1860 sprintf( palette_filename, NOX("gamepalette%d-%02d"), HUD_config.main_color+1, Mission_palette+1 );
1863 mprintf(( "Loading palette %s\n", palette_filename ));
1865 palette_load_table(palette_filename);
1867 strcpy( palette_filename, NOX("gamepalette-subspace") );
1869 mprintf(( "Loading palette %s\n", palette_filename ));
1873 void game_post_level_init()
1875 // Stuff which gets called after mission is loaded. Because player isn't created until
1876 // after mission loads, some things must get initted after the level loads
1878 model_level_post_init();
1881 hud_setup_escort_list();
1882 mission_hotkey_set_defaults(); // set up the default hotkeys (from mission file)
1888 game_event_debug_init();
1891 training_mission_init();
1892 asteroid_create_all();
1894 game_framerate_check_init();
1898 // An estimate as to how high the count passed to game_loading_callback will go.
1899 // This is just a guess, it seems to always be about the same. The count is
1900 // proportional to the code being executed, not the time, so this works good
1901 // for a bar, assuming the code does about the same thing each time you
1902 // load a level. You can find this value by looking at the return value
1903 // of game_busy_callback(NULL), which I conveniently print out to the
1904 // debug output window with the '=== ENDING LOAD ==' stuff.
1905 //#define COUNT_ESTIMATE 3706
1906 #define COUNT_ESTIMATE 1111
1908 int Game_loading_callback_inited = 0;
1910 int Game_loading_background = -1;
1911 anim * Game_loading_ani = NULL;
1912 anim_instance *Game_loading_ani_instance;
1913 int Game_loading_frame=-1;
1915 static int Game_loading_ani_coords[GR_NUM_RESOLUTIONS][2] = {
1917 #if defined(FS1_DEMO)
1919 #elif defined(MAKE_FS1)
1930 // This gets called 10x per second and count is the number of times
1931 // game_busy() has been called since the current callback function
1933 void game_loading_callback(int count)
1935 game_do_networking();
1937 Assert( Game_loading_callback_inited==1 );
1938 Assert( Game_loading_ani != NULL );
1940 int framenum = ((Game_loading_ani->total_frames*count) / COUNT_ESTIMATE)+1;
1941 if ( framenum > Game_loading_ani->total_frames-1 ) {
1942 framenum = Game_loading_ani->total_frames-1;
1943 } else if ( framenum < 0 ) {
1948 while ( Game_loading_frame < framenum ) {
1949 Game_loading_frame++;
1950 cbitmap = anim_get_next_frame(Game_loading_ani_instance);
1954 if ( cbitmap > -1 ) {
1955 if ( Game_loading_background > -1 ) {
1956 gr_set_bitmap( Game_loading_background, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1960 //mprintf(( "Showing frame %d/%d [ Bitmap=%d ]\n", Game_loading_frame , Game_loading_ani->total_frames, cbitmap ));
1961 gr_set_bitmap( cbitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1962 gr_bitmap(Game_loading_ani_coords[gr_screen.res][0],Game_loading_ani_coords[gr_screen.res][1]);
1964 bm_release(cbitmap);
1970 void game_loading_callback_init()
1972 Assert( Game_loading_callback_inited==0 );
1974 Game_loading_background = bm_load(Game_loading_bground_fname[gr_screen.res]);
1976 common_set_interface_palette("InterfacePalette"); // set the interface palette
1980 Game_loading_ani = anim_load( Game_loading_ani_fname[gr_screen.res]);
1981 Assert( Game_loading_ani != NULL );
1982 Game_loading_ani_instance = init_anim_instance(Game_loading_ani, 16);
1983 Assert( Game_loading_ani_instance != NULL );
1984 Game_loading_frame = -1;
1986 Game_loading_callback_inited = 1;
1988 game_busy_callback( game_loading_callback, (COUNT_ESTIMATE/Game_loading_ani->total_frames)+1 );
1993 void game_loading_callback_close()
1995 Assert( Game_loading_callback_inited==1 );
1997 // Make sure bar shows all the way over.
1998 game_loading_callback(COUNT_ESTIMATE);
2000 int real_count = game_busy_callback( NULL );
2003 Game_loading_callback_inited = 0;
2006 mprintf(( "=================== ENDING LOAD ================\n" ));
2007 mprintf(( "Real count = %d, Estimated count = %d\n", real_count, COUNT_ESTIMATE ));
2008 mprintf(( "================================================\n" ));
2010 // to remove warnings in release build
2014 free_anim_instance(Game_loading_ani_instance);
2015 Game_loading_ani_instance = NULL;
2016 anim_free(Game_loading_ani);
2017 Game_loading_ani = NULL;
2019 bm_release( Game_loading_background );
2020 common_free_interface_palette(); // restore game palette
2021 Game_loading_background = -1;
2023 gr_set_font( FONT1 );
2026 // Update the sound environment (ie change EAX settings based on proximity to large ships)
2028 void game_maybe_update_sound_environment()
2030 // do nothing for now
2033 // Assign the sound environment for the game, based on the current mission
2035 void game_assign_sound_environment()
2038 if (The_mission.flags & MISSION_FLAG_SUBSPACE) {
2039 Game_sound_env.id = SND_ENV_DRUGGED;
2040 Game_sound_env.volume = 0.800f;
2041 Game_sound_env.damping = 1.188f;
2042 Game_sound_env.decay = 6.392f;
2044 } else if (Num_asteroids > 30) {
2045 Game_sound_env.id = SND_ENV_AUDITORIUM;
2046 Game_sound_env.volume = 0.603f;
2047 Game_sound_env.damping = 0.5f;
2048 Game_sound_env.decay = 4.279f;
2051 Game_sound_env = Game_default_sound_env;
2055 Game_sound_env = Game_default_sound_env;
2056 Game_sound_env_update_timestamp = timestamp(1);
2059 // function which gets called before actually entering the mission. It is broken down into a funciton
2060 // since it will get called in one place from a single player game and from another place for
2061 // a multiplayer game
2062 void freespace_mission_load_stuff()
2064 // called if we're not on a freespace dedicated (non rendering, no pilot) server
2065 // IE : we _don't_ want to load any sounds or bitmap/texture info on this machine.
2066 if(!(Game_mode & GM_STANDALONE_SERVER)){
2068 mprintf(( "=================== STARTING LEVEL DATA LOAD ==================\n" ));
2070 game_loading_callback_init();
2072 event_music_level_init(); // preloads the first 2 seconds for each event music track
2075 gamesnd_unload_interface_sounds(); // unload interface sounds from memory
2078 gamesnd_preload_common_sounds(); // load in sounds that are expected to play
2081 ship_assign_sound_all(); // assign engine sounds to ships
2082 game_assign_sound_environment(); // assign the sound environment for this mission
2085 // call function in missionparse.cpp to fixup player/ai stuff.
2086 mission_parse_fixup_players();
2089 // Load in all the bitmaps for this level
2094 game_loading_callback_close();
2096 // the only thing we need to call on the standalone for now.
2098 // call function in missionparse.cpp to fixup player/ai stuff.
2099 mission_parse_fixup_players();
2101 // Load in all the bitmaps for this level
2107 uint load_mission_load;
2108 uint load_post_level_init;
2109 uint load_mission_stuff;
2111 // tells the server to load the mission and initialize structures
2112 int game_start_mission()
2114 mprintf(( "=================== STARTING LEVEL LOAD ==================\n" ));
2116 load_gl_init = time(NULL);
2118 load_gl_init = time(NULL) - load_gl_init;
2120 if (Game_mode & GM_MULTIPLAYER) {
2121 Player->flags |= PLAYER_FLAGS_IS_MULTI;
2123 // clear multiplayer stats
2124 init_multiplayer_stats();
2127 load_mission_load = time(NULL);
2128 if (mission_load()) {
2129 if ( !(Game_mode & GM_MULTIPLAYER) ) {
2130 popup(PF_BODY_BIG, 1, POPUP_OK, XSTR( "Attempt to load the mission failed", 169));
2131 gameseq_post_event(GS_EVENT_MAIN_MENU);
2133 multi_quit_game(PROMPT_NONE, MULTI_END_NOTIFY_NONE, MULTI_END_ERROR_LOAD_FAIL);
2138 load_mission_load = time(NULL) - load_mission_load;
2140 // If this is a red alert mission in campaign mode, bash wingman status
2141 if ( (Game_mode & GM_CAMPAIGN_MODE) && red_alert_mission() ) {
2142 red_alert_bash_wingman_status();
2145 // the standalone server in multiplayer doesn't do any rendering, so we will not even bother loading the palette
2146 if ( !(Game_mode & GM_STANDALONE_SERVER) ) {
2147 mprintf(( "=================== LOADING GAME PALETTE ================\n" ));
2149 game_load_palette();
2153 load_post_level_init = time(NULL);
2154 game_post_level_init();
2155 load_post_level_init = time(NULL) - load_post_level_init;
2159 void Do_model_timings_test();
2160 Do_model_timings_test();
2164 load_mission_stuff = time(NULL);
2165 freespace_mission_load_stuff();
2166 load_mission_stuff = time(NULL) - load_mission_stuff;
2171 int Interface_framerate = 0;
2174 DCF_BOOL( mouse_control, Use_mouse_to_fly )
2175 DCF_BOOL( show_framerate, Show_framerate )
2176 DCF_BOOL( show_target_debug_info, Show_target_debug_info )
2177 DCF_BOOL( show_target_weapons, Show_target_weapons )
2178 DCF_BOOL( lead_target_cheat, Players[Player_num].lead_target_cheat )
2179 DCF_BOOL( sound, Sound_enabled )
2180 DCF_BOOL( zbuffer, game_zbuffer )
2181 DCF_BOOL( shield_system, New_shield_system )
2182 DCF_BOOL( show_shield_mesh, Show_shield_mesh)
2183 DCF_BOOL( player_attacking, Player_attacking_enabled )
2184 DCF_BOOL( show_waypoints, Show_waypoints )
2185 DCF_BOOL( show_area_effect, Show_area_effect )
2186 DCF_BOOL( show_net_stats, Show_net_stats )
2187 DCF_BOOL( log, Log_debug_output_to_file )
2188 DCF_BOOL( training_msg_method, Training_msg_method )
2189 DCF_BOOL( show_player_pos, Show_player_pos )
2190 DCF_BOOL(i_framerate, Interface_framerate )
2192 DCF(show_mem,"Toggles showing mem usage")
2195 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2196 if ( Dc_arg_type & ARG_TRUE ) Show_mem = 1;
2197 else if ( Dc_arg_type & ARG_FALSE ) Show_mem = 0;
2198 else if ( Dc_arg_type & ARG_NONE ) Show_mem ^= 1;
2204 if ( Dc_help ) dc_printf( "Usage: Show_mem\nSets show_mem to true or false. If nothing passed, then toggles it.\n" );
2206 dc_printf( "Show_mem is %s\n", (Show_mem?"TRUE":"FALSE") );
2207 dc_printf( "Show_cpu is %s\n", (Show_cpu?"TRUE":"FALSE") );
2211 DCF(show_cpu,"Toggles showing cpu usage")
2214 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2215 if ( Dc_arg_type & ARG_TRUE ) Show_cpu = 1;
2216 else if ( Dc_arg_type & ARG_FALSE ) Show_cpu = 0;
2217 else if ( Dc_arg_type & ARG_NONE ) Show_cpu ^= 1;
2223 if ( Dc_help ) dc_printf( "Usage: Show_cpu\nSets show_cpu to true or false. If nothing passed, then toggles it.\n" );
2225 dc_printf( "Show_mem is %s\n", (Show_mem?"TRUE":"FALSE") );
2226 dc_printf( "Show_cpu is %s\n", (Show_cpu?"TRUE":"FALSE") );
2233 // AL 4-8-98: always allow players to display their framerate
2236 DCF_BOOL( show_framerate, Show_framerate )
2243 DCF(use_joy_mouse,"Makes joystick move mouse cursor")
2246 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2247 if ( Dc_arg_type & ARG_TRUE ) Use_joy_mouse = 1;
2248 else if ( Dc_arg_type & ARG_FALSE ) Use_joy_mouse = 0;
2249 else if ( Dc_arg_type & ARG_NONE ) Use_joy_mouse ^= 1;
2251 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" );
2252 if ( Dc_status ) dc_printf( "use_joy_mouse is %s\n", (Use_joy_mouse?"TRUE":"FALSE") );
2254 os_config_write_uint( NULL, NOX("JoystickMovesCursor"), Use_joy_mouse );
2257 DCF(palette_flash,"Toggles palette flash effect on/off")
2260 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2261 if ( Dc_arg_type & ARG_TRUE ) Use_palette_flash = 1;
2262 else if ( Dc_arg_type & ARG_FALSE ) Use_palette_flash = 0;
2263 else if ( Dc_arg_type & ARG_NONE ) Use_palette_flash ^= 1;
2265 if ( Dc_help ) dc_printf( "Usage: palette_flash [bool]\nSets palette_flash to true or false. If nothing passed, then toggles it.\n" );
2266 if ( Dc_status ) dc_printf( "palette_flash is %s\n", (Use_palette_flash?"TRUE":"FALSE") );
2269 int Use_low_mem = 0;
2271 DCF(low_mem,"Uses low memory settings regardless of RAM")
2274 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2275 if ( Dc_arg_type & ARG_TRUE ) Use_low_mem = 1;
2276 else if ( Dc_arg_type & ARG_FALSE ) Use_low_mem = 0;
2277 else if ( Dc_arg_type & ARG_NONE ) Use_low_mem ^= 1;
2279 if ( Dc_help ) dc_printf( "Usage: low_mem [bool]\nSets low_mem to true or false. If nothing passed, then toggles it.\n" );
2280 if ( Dc_status ) dc_printf( "low_mem is %s\n", (Use_low_mem?"TRUE":"FALSE") );
2282 os_config_write_uint( NULL, NOX("LowMem"), Use_low_mem );
2288 DCF(force_fullscreen, "Forces game to startup in fullscreen mode")
2291 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2292 if ( Dc_arg_type & ARG_TRUE ) Use_fullscreen_at_startup = 1;
2293 else if ( Dc_arg_type & ARG_FALSE ) Use_fullscreen_at_startup = 0;
2294 else if ( Dc_arg_type & ARG_NONE ) Use_fullscreen_at_startup ^= 1;
2296 if ( Dc_help ) dc_printf( "Usage: force_fullscreen [bool]\nSets force_fullscreen to true or false. If nothing passed, then toggles it.\n" );
2297 if ( Dc_status ) dc_printf( "force_fullscreen is %s\n", (Use_fullscreen_at_startup?"TRUE":"FALSE") );
2298 os_config_write_uint( NULL, NOX("ForceFullscreen"), Use_fullscreen_at_startup );
2302 int Framerate_delay = 0;
2304 float Freespace_gamma = 1.0f;
2306 DCF(gamma,"Sets Gamma factor")
2309 dc_get_arg(ARG_FLOAT|ARG_NONE);
2310 if ( Dc_arg_type & ARG_FLOAT ) {
2311 Freespace_gamma = Dc_arg_float;
2313 dc_printf( "Gamma reset to 1.0f\n" );
2314 Freespace_gamma = 1.0f;
2316 if ( Freespace_gamma < 0.1f ) {
2317 Freespace_gamma = 0.1f;
2318 } else if ( Freespace_gamma > 5.0f ) {
2319 Freespace_gamma = 5.0f;
2321 gr_set_gamma(Freespace_gamma);
2323 char tmp_gamma_string[32];
2324 sprintf( tmp_gamma_string, NOX("%.2f"), Freespace_gamma );
2325 os_config_write_string( NULL, NOX("Gamma"), tmp_gamma_string );
2329 dc_printf( "Usage: gamma <float>\n" );
2330 dc_printf( "Sets gamma in range 1-3, no argument resets to default 1.2\n" );
2331 Dc_status = 0; // don't print status if help is printed. Too messy.
2335 dc_printf( "Gamma = %.2f\n", Freespace_gamma );
2344 Game_current_mission_filename[0] = 0;
2346 // seed the random number generator
2347 Game_init_seed = time(NULL);
2348 srand( Game_init_seed );
2350 Framerate_delay = 0;
2356 extern void bm_init();
2362 // Initialize the timer before the os
2368 //Initialize the libraries
2369 s1 = timer_get_milliseconds();
2370 if ( cfile_init() ) { // initialize before calling any cfopen stuff!!!
2373 e1 = timer_get_milliseconds();
2375 // time a bunch of cfopens
2377 s2 = timer_get_milliseconds();
2379 for(int idx=0; idx<10000; idx++){
2380 whee = cfopen("capital01.pof", "rb", CFILE_NORMAL, CF_TYPE_MODELS);
2385 //cf_exist("capital01.pof", CF_TYPE_MODELS);
2387 e2 = timer_get_milliseconds();
2390 if (Is_standalone) {
2391 std_init_standalone();
2393 os_init( Osreg_class_name, Osreg_app_name );
2394 os_set_title(Osreg_title);
2397 // initialize localization module. Make sure this is down AFTER initialzing OS.
2398 // int t1 = timer_get_milliseconds();
2399 lcl_init( detect_lang() );
2401 // mprintf(("LCL_INIT() TOOK %d MS\n", timer_get_milliseconds()-t1));
2403 // verify that he has a valid ships.tbl (will Game_ships_tbl_valid if so)
2406 // verify that he has a valid weapons.tbl
2407 verify_weapons_tbl();
2409 // Output version numbers to registry for auto patching purposes
2410 os_config_write_uint(NOX("Version"), NOX("Major"), FS_VERSION_MAJOR);
2411 os_config_write_uint(NOX("Version"), NOX("Minor"), FS_VERSION_MINOR);
2412 os_config_write_uint(NOX("Version"), NOX("Build"), FS_VERSION_BUILD);
2414 Use_joy_mouse = 0; //os_config_read_uint( NULL, NOX("JoystickMovesCursor"), 1 );
2415 //Use_palette_flash = os_config_read_uint( NULL, NOX("PaletteFlash"), 0 );
2416 Use_low_mem = os_config_read_uint( NULL, NOX("LowMem"), 0 );
2419 Use_fullscreen_at_startup = os_config_read_uint( NULL, NOX("ForceFullscreen"), 1 );
2422 #if defined (PLAT_UNIX) && defined(RELEASE_REAL)
2423 // show the FPS counter if the config file says so
2424 Show_framerate = os_config_read_uint( NULL, NOX("ShowFPS"), 0 );
2427 #if !(defined(FS2_DEMO) || defined(FS1_DEMO))
2428 Asteroids_enabled = 1;
2431 /////////////////////////////
2433 /////////////////////////////
2438 ptr = os_config_read_string(NULL, NOX("Soundcard"), NULL);
2439 mprintf(("soundcard = %s\n", ptr ? ptr : "<nothing>"));
2441 if (!stricmp(ptr, NOX("no sound"))) {
2442 Cmdline_freespace_no_sound = 1;
2444 } else if (!stricmp(ptr, NOX("Aureal A3D"))) {
2446 } else if (!stricmp(ptr, NOX("EAX"))) {
2451 if (!Is_standalone) {
2452 snd_init(use_a3d, use_eax);
2454 /////////////////////////////
2456 /////////////////////////////
2458 ptr = os_config_read_string(NULL, NOX("Videocard"), NULL);
2461 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);
2463 // fire up the UpdateLauncher executable
2465 PROCESS_INFORMATION pi;
2467 memset( &si, 0, sizeof(STARTUPINFO) );
2470 BOOL ret = CreateProcess( LAUNCHER_FNAME, // pointer to name of executable module
2471 NULL, // pointer to command line string
2472 NULL, // pointer to process security attributes
2473 NULL, // pointer to thread security attributes
2474 FALSE, // handle inheritance flag
2475 CREATE_DEFAULT_ERROR_MODE, // creation flags
2476 NULL, // pointer to new environment block
2477 NULL, // pointer to current directory name
2478 &si, // pointer to STARTUPINFO
2479 &pi // pointer to PROCESS_INFORMATION
2482 // If the Launcher could not be started up, let the user know
2484 MessageBox((HWND)os_get_window(), XSTR("The Launcher could not be restarted.", 1450), XSTR("Error", 1451), MB_OK);
2493 if(!stricmp(ptr, "Aucune acc�l�ration 3D") || !stricmp(ptr, "Keine 3D-Beschleunigerkarte") || !stricmp(ptr, "No 3D acceleration")){
2495 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);
2503 // check for hi res pack file
2504 int has_sparky_hi = 0;
2506 // check if sparky_hi exists -- access mode 0 means does file exist
2507 #ifndef MAKE_FS1 // shoudn't have it so don't check
2510 if ( _access("sparky_hi_fs2.vp", 0) == 0) {
2513 mprintf(("No sparky_hi_fs2.vp in directory %s\n", dir));
2517 // see if we've got 32 bit in the string
2518 if(strstr(ptr, "32 bit")){
2525 if (!Is_standalone && ptr && (strstr(ptr, NOX("3DFX Glide")))) {
2527 // always 640 for E3
2528 gr_init(GR_640, GR_GLIDE);
2530 // regular or hi-res ?
2532 if(has_sparky_hi && strstr(ptr, NOX("(1024x768)"))){
2534 if(strstr(ptr, NOX("(1024x768)"))){
2536 gr_init(GR_1024, GR_GLIDE);
2538 gr_init(GR_640, GR_GLIDE);
2541 } else if (!Is_standalone && ptr && (strstr(ptr, NOX("Direct 3D -") ))) {
2543 // always 640 for E3
2545 gr_init(GR_640, GR_DIRECT3D, depth);
2547 // regular or hi-res ?
2549 if(has_sparky_hi && strstr(ptr, NOX("(1024x768)"))){
2551 if(strstr(ptr, NOX("(1024x768)"))){
2555 gr_init(GR_1024, GR_DIRECT3D, depth);
2559 gr_init(GR_640, GR_DIRECT3D, depth);
2565 if ( Use_fullscreen_at_startup && !Is_standalone) {
2566 gr_init(GR_640, GR_DIRECTDRAW);
2568 gr_init(GR_640, GR_SOFTWARE);
2571 if ( !Is_standalone ) {
2572 gr_init(GR_640, GR_DIRECTDRAW);
2574 gr_init(GR_640, GR_SOFTWARE);
2579 if (!Is_standalone /* && ptr && (strstr(ptr, NOX("OpenGL"))) */) {
2580 if(has_sparky_hi && strstr(ptr, NOX("(1024x768)"))){
2581 gr_init(GR_1024, GR_OPENGL);
2583 gr_init(GR_640, GR_OPENGL);
2587 gr_init(GR_640, GR_SOFTWARE);
2589 #endif // !PLAT_UNIX
2592 extern int Gr_inited;
2593 if(trying_d3d && !Gr_inited){
2595 extern char Device_init_error[512];
2596 MessageBox( NULL, Device_init_error, "Error intializing Direct3D", MB_OK|MB_TASKMODAL|MB_SETFOREGROUND );
2605 ptr = os_config_read_string(NULL,NOX("Gamma"),NOX("1.80"));
2606 Freespace_gamma = (float)atof(ptr);
2607 if ( Freespace_gamma == 0.0f ) {
2608 Freespace_gamma = 1.80f;
2609 } else if ( Freespace_gamma < 0.1f ) {
2610 Freespace_gamma = 0.1f;
2611 } else if ( Freespace_gamma > 5.0f ) {
2612 Freespace_gamma = 5.0f;
2614 char tmp_gamma_string[32];
2615 sprintf( tmp_gamma_string, NOX("%.2f"), Freespace_gamma );
2616 os_config_write_string( NULL, NOX("Gamma"), tmp_gamma_string );
2618 gr_set_gamma(Freespace_gamma);
2620 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
2623 display_title_screen();
2627 // attempt to load up master tracker registry info (login and password)
2628 Multi_tracker_id = -1;
2630 // pxo login and password
2631 ptr = os_config_read_string(NOX("PXO"),NOX("Login"),NULL);
2633 nprintf(("Network","Error reading in PXO login data\n"));
2634 strcpy(Multi_tracker_login,"");
2636 strcpy(Multi_tracker_login,ptr);
2638 ptr = os_config_read_string(NOX("PXO"),NOX("Password"),NULL);
2640 nprintf(("Network","Error reading PXO password\n"));
2641 strcpy(Multi_tracker_passwd,"");
2643 strcpy(Multi_tracker_passwd,ptr);
2646 // pxo squad name and password
2647 ptr = os_config_read_string(NOX("PXO"),NOX("SquadName"),NULL);
2649 nprintf(("Network","Error reading in PXO squad name\n"));
2650 strcpy(Multi_tracker_squad_name, "");
2652 strcpy(Multi_tracker_squad_name, ptr);
2655 // If less than 48MB of RAM, use low memory model.
2656 if ( (Freespace_total_ram < 48) || Use_low_mem ) {
2657 mprintf(( "Using normal memory settings...\n" ));
2658 bm_set_low_mem(1); // Use every other frame of bitmaps
2660 mprintf(( "Using high memory settings...\n" ));
2661 bm_set_low_mem(0); // Use all frames of bitmaps
2664 // load non-darkening pixel defs
2665 palman_load_pixels();
2667 // hud shield icon stuff
2668 hud_shield_game_init();
2670 control_config_common_init(); // sets up localization stuff in the control config
2676 gamesnd_parse_soundstbl();
2681 // standalone's don't use hte joystick and it seems to sometimes cause them to not get shutdown properly
2686 player_controls_init();
2689 //if(!Is_standalone){
2697 ship_init(); // read in ships.tbl
2699 mission_campaign_init(); // load in the default campaign
2701 // navmap_init(); // init the navigation map system
2702 context_help_init();
2703 techroom_intel_init(); // parse species.tbl, load intel info
2705 psnet_init( Multi_options_g.protocol, Multi_options_g.port ); // initialize the networking code
2706 init_animating_pointer();
2708 mission_brief_common_init(); // Mark all the briefing structures as empty.
2709 gr_font_init(); // loads up all fonts
2711 neb2_init(); // fullneb stuff
2715 player_tips_init(); // helpful tips
2718 // load the list of pilot pic filenames (for barracks and pilot select popup quick reference)
2719 pilot_load_pic_list();
2720 pilot_load_squad_pic_list();
2722 load_animating_pointer(NOX("cursor"), 0, 0);
2724 // initialize alpha colors
2725 alpha_colors_init();
2728 // Game_music_paused = 0;
2735 nprintf(("General", "Ships.tbl is : %s\n", Game_ships_tbl_valid ? "VALID" : "INVALID!!!!"));
2736 nprintf(("General", "Weapons.tbl is : %s\n", Game_weapons_tbl_valid ? "VALID" : "INVALID!!!!"));
2738 mprintf(("cfile_init() took %d\n", e1 - s1));
2739 // mprintf(("1000 cfopens() took %d\n", e2 - s2));
2742 char transfer_text[128];
2744 float Start_time = 0.0f;
2746 float Framerate = 0.0f;
2748 float Timing_total = 0.0f;
2749 float Timing_render2 = 0.0f;
2750 float Timing_render3 = 0.0f;
2751 float Timing_flip = 0.0f;
2752 float Timing_clear = 0.0f;
2754 MONITOR(NumPolysDrawn);
2760 void game_get_framerate()
2762 char text[128] = "";
2764 if ( frame_int == -1 ) {
2766 for (i=0; i<FRAME_FILTER; i++ ) {
2767 frametimes[i] = 0.0f;
2772 frametotal -= frametimes[frame_int];
2773 frametotal += flFrametime;
2774 frametimes[frame_int] = flFrametime;
2775 frame_int = (frame_int + 1 ) % FRAME_FILTER;
2777 if ( frametotal != 0.0 ) {
2778 if ( Framecount >= FRAME_FILTER )
2779 Framerate = FRAME_FILTER / frametotal;
2781 Framerate = Framecount / frametotal;
2782 sprintf( text, NOX("FPS: %.1f"), Framerate );
2784 sprintf( text, NOX("FPS: ?") );
2788 if (Show_framerate) {
2789 gr_set_color_fast(&HUD_color_debug);
2790 gr_string( 570, 2, text );
2794 void game_show_framerate()
2798 cur_time = f2fl(timer_get_approx_seconds());
2799 if (cur_time - Start_time > 30.0f) {
2800 mprintf(("%i frames executed in %7.3f seconds, %7.3f frames per second.\n", Framecount, cur_time - Start_time, Framecount/(cur_time - Start_time)));
2801 Start_time += 1000.0f;
2804 //mprintf(( "%s\n", text ));
2807 if ( Debug_dump_frames )
2811 // possibly show control checking info
2812 control_check_indicate();
2814 // int bitmaps_used_this_frame, bitmaps_new_this_frame;
2815 // bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
2816 // MONITOR_INC(BmpUsed, bitmaps_used_this_frame);
2817 // MONITOR_INC(BmpNew, bitmaps_new_this_frame);
2820 if ( Show_cpu == 1 ) {
2825 dy = gr_get_font_height() + 1;
2827 gr_set_color_fast(&HUD_color_debug);
2831 extern int D3D_textures_in;
2832 extern int D3D_textures_in_frame;
2833 extern int Glide_textures_in;
2834 extern int Glide_textures_in_frame;
2835 extern int Glide_explosion_vram;
2836 gr_printf( sx, sy, NOX("VRAM: %d KB\n"), (D3D_textures_in+Glide_textures_in)/1024 );
2838 gr_printf( sx, sy, NOX("VRAM: +%d KB\n"), (Glide_textures_in_frame+D3D_textures_in_frame)/1024 );
2840 gr_printf( sx, sy, NOX("EXP VRAM: %dKB\n"), (Glide_explosion_vram)/1024 );
2844 // gr_printf( sx, sy, "BPP: %d", gr_screen.bits_per_pixel );
2846 gr_printf( sx, sy, NOX("DMA: %s"), transfer_text );
2848 gr_printf( sx, sy, NOX("POLYP: %d"), modelstats_num_polys );
2850 gr_printf( sx, sy, NOX("POLYD: %d"), modelstats_num_polys_drawn );
2852 gr_printf( sx, sy, NOX("VERTS: %d"), modelstats_num_verts );
2857 extern int Num_pairs; // Number of object pairs that were checked.
2858 gr_printf( sx, sy, NOX("PAIRS: %d"), Num_pairs );
2861 extern int Num_pairs_checked; // What percent of object pairs were checked.
2862 gr_printf( sx, sy, NOX("FVI: %d"), Num_pairs_checked );
2864 Num_pairs_checked = 0;
2868 gr_printf( sx, sy, NOX("Snds: %d"), snd_num_playing() );
2871 if ( Timing_total > 0.01f ) {
2872 gr_printf( sx, sy, NOX("CLEAR: %.0f%%"), Timing_clear*100.0f/Timing_total );
2874 gr_printf( sx, sy, NOX("REND2D: %.0f%%"), Timing_render2*100.0f/Timing_total );
2876 gr_printf( sx, sy, NOX("REND3D: %.0f%%"), Timing_render3*100.0f/Timing_total );
2878 gr_printf( sx, sy, NOX("FLIP: %.0f%%"), Timing_flip*100.0f/Timing_total );
2880 gr_printf( sx, sy, NOX("GAME: %.0f%%"), (Timing_total-(Timing_render2+Timing_render3+Timing_flip+Timing_clear))*100.0f/Timing_total );
2890 dy = gr_get_font_height() + 1;
2892 gr_set_color_fast(&HUD_color_debug);
2895 extern int TotalRam;
2896 gr_printf( sx, sy, NOX("DYN: %d KB\n"), TotalRam/1024 );
2901 extern int Model_ram;
2902 gr_printf( sx, sy, NOX("POF: %d KB\n"), Model_ram/1024 );
2906 gr_printf( sx, sy, NOX("BMP: %d KB\n"), bm_texture_ram/1024 );
2908 gr_printf( sx, sy, NOX("S-SRAM: %d KB\n"), Snd_sram/1024 ); // mem used to store game sound
2911 gr_printf( sx, sy, NOX("S-HRAM: %d KB\n"), Snd_hram/1024 ); // mem used to store game sound
2914 extern int D3D_textures_in;
2915 extern int Glide_textures_in;
2916 extern int Glide_textures_in_frame;
2917 extern int Glide_explosion_vram;
2918 gr_printf( sx, sy, NOX("VRAM: %d KB\n"), (D3D_textures_in+Glide_textures_in)/1024 );
2920 gr_printf( sx, sy, NOX("VRAM: +%d KB\n"), (Glide_textures_in_frame)/1024 );
2922 gr_printf( sx, sy, NOX("EXP VRAM: %dKB\n"), (Glide_explosion_vram)/1024 );
2926 extern int GL_textures_in;
2927 gr_printf( sx, sy, NOX("VRAM: %d KB\n"), (GL_textures_in)/1024 );
2934 if ( Show_player_pos ) {
2938 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));
2941 MONITOR_INC(NumPolys, modelstats_num_polys);
2942 MONITOR_INC(NumPolysDrawn, modelstats_num_polys_drawn );
2943 MONITOR_INC(NumVerts, modelstats_num_verts );
2945 modelstats_num_polys = 0;
2946 modelstats_num_polys_drawn = 0;
2947 modelstats_num_verts = 0;
2948 modelstats_num_sortnorms = 0;
2952 void game_show_standalone_framerate()
2954 float frame_rate=30.0f;
2955 if ( frame_int == -1 ) {
2957 for (i=0; i<FRAME_FILTER; i++ ) {
2958 frametimes[i] = 0.0f;
2963 frametotal -= frametimes[frame_int];
2964 frametotal += flFrametime;
2965 frametimes[frame_int] = flFrametime;
2966 frame_int = (frame_int + 1 ) % FRAME_FILTER;
2968 if ( frametotal != 0.0 ) {
2969 if ( Framecount >= FRAME_FILTER ){
2970 frame_rate = FRAME_FILTER / frametotal;
2972 frame_rate = Framecount / frametotal;
2975 std_set_standalone_fps(frame_rate);
2979 // function to show the time remaining in a mission. Used only when the end-mission sexpression is used
2980 void game_show_time_left()
2984 // mission_end_time is a global from missionparse.cpp that contains the mission time at which the
2985 // mission should end (in fixed seconds). There is code in missionparse.cpp which actually handles
2986 // checking how much time is left
2988 if ( Mission_end_time == -1 ){
2992 diff = f2i(Mission_end_time - Missiontime);
2993 // be sure to bash to 0. diff could be negative on frame that we quit mission
2998 hud_set_default_color();
2999 gr_printf( 5, 40, XSTR( "Mission time remaining: %d seconds", 179), diff );
3002 //========================================================================================
3003 //=================== NEW DEBUG CONSOLE COMMANDS TO REPLACE OLD DEBUG PAUSE MENU =========
3004 //========================================================================================
3008 DCF(ai_pause,"Pauses ai")
3011 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
3012 if ( Dc_arg_type & ARG_TRUE ) ai_paused = 1;
3013 else if ( Dc_arg_type & ARG_FALSE ) ai_paused = 0;
3014 else if ( Dc_arg_type & ARG_NONE ) ai_paused = !ai_paused;
3017 obj_init_all_ships_physics();
3020 if ( Dc_help ) dc_printf( "Usage: ai_paused [bool]\nSets ai_paused to true or false. If nothing passed, then toggles it.\n" );
3021 if ( Dc_status ) dc_printf( "ai_paused is %s\n", (ai_paused?"TRUE":"FALSE") );
3024 DCF(single_step,"Single steps the game")
3027 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
3028 if ( Dc_arg_type & ARG_TRUE ) game_single_step = 1;
3029 else if ( Dc_arg_type & ARG_FALSE ) game_single_step = 0;
3030 else if ( Dc_arg_type & ARG_NONE ) game_single_step = !game_single_step;
3032 last_single_step = 0; // Make so single step waits a frame before stepping
3035 if ( Dc_help ) dc_printf( "Usage: single_step [bool]\nSets single_step to true or false. If nothing passed, then toggles it.\n" );
3036 if ( Dc_status ) dc_printf( "single_step is %s\n", (game_single_step?"TRUE":"FALSE") );
3039 DCF_BOOL(physics_pause, physics_paused)
3040 DCF_BOOL(ai_rendering, Ai_render_debug_flag)
3041 DCF_BOOL(ai_firing, Ai_firing_enabled )
3043 // Create some simple aliases to these commands...
3044 debug_command dc_s("s","shortcut for single_step",dcf_single_step);
3045 debug_command dc_p("p","shortcut for physics_pause", dcf_physics_pause );
3046 debug_command dc_r("r","shortcut for ai_rendering", dcf_ai_rendering );
3047 debug_command dc_f("f","shortcut for ai_firing", dcf_ai_firing);
3048 debug_command dc_a("a","shortcut for ai_pause", dcf_ai_pause);
3051 //========================================================================================
3052 //========================================================================================
3055 void game_training_pause_do()
3059 key = game_check_key();
3061 gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
3068 void game_increase_skill_level()
3071 if (Game_skill_level >= NUM_SKILL_LEVELS){
3072 Game_skill_level = 0;
3076 int Player_died_time;
3078 int View_percent = 100;
3081 DCF(view, "Sets the percent of the 3d view to render.")
3084 dc_get_arg(ARG_INT);
3085 if ( (Dc_arg_int >= 5 ) || (Dc_arg_int <= 100) ) {
3086 View_percent = Dc_arg_int;
3088 dc_printf( "Illegal value for view. (Must be from 5-100) \n\n");
3094 dc_printf("Usage: view [n]\nwhere n is percent of view to show (5-100).\n");
3098 dc_printf("View is set to %d%%\n", View_percent );
3103 // Set the clip region for the 3d rendering window
3104 void game_set_view_clip()
3106 if ((Game_mode & GM_DEAD) || (supernova_active() >= 2)) {
3107 // Set the clip region for the letterbox "dead view"
3108 int yborder = gr_screen.max_h/4;
3110 // Numeric constants encouraged by J "pig farmer" S, who shall remain semi-anonymous.
3111 // J.S. I've changed my ways!! See the new "no constants" code!!!
3112 gr_set_clip(0, yborder, gr_screen.max_w, gr_screen.max_h - yborder*2 );
3114 // Set the clip region for normal view
3115 if ( View_percent >= 100 ) {
3118 int xborder, yborder;
3120 if ( View_percent < 5 ) {
3124 float fp = i2fl(View_percent)/100.0f;
3125 int fi = fl2i(fl_sqrt(fp)*100.0f);
3126 if ( fi > 100 ) fi=100;
3128 xborder = ( gr_screen.max_w*(100-fi) )/200;
3129 yborder = ( gr_screen.max_h*(100-fi) )/200;
3131 gr_set_clip(xborder, yborder, gr_screen.max_w-xborder*2,gr_screen.max_h-yborder*2 );
3137 void show_debug_stuff()
3140 int laser_count = 0, missile_count = 0;
3142 for (i=0; i<MAX_OBJECTS; i++) {
3143 if (Objects[i].type == OBJ_WEAPON){
3144 if (Weapon_info[Weapons[Objects[i].instance].weapon_info_index].subtype == WP_LASER){
3146 } else if (Weapon_info[Weapons[Objects[i].instance].weapon_info_index].subtype == WP_MISSILE){
3152 nprintf(("Mike", "Frame: %i Lasers: %4i, Missiles: %4i\n", Framecount, laser_count, missile_count));
3155 extern int Tool_enabled;
3160 int tst_bitmap = -1;
3162 float tst_offset, tst_offset_total;
3165 void game_tst_frame_pre()
3173 g3_rotate_vertex(&v, &tst_pos);
3174 g3_project_vertex(&v);
3177 if(!((v.sx >= 0) && (v.sx <= gr_screen.max_w) && (v.sy >= 0) && (v.sy <= gr_screen.max_h))){
3181 // big ship? always tst
3183 // within 3000 meters
3184 if( vm_vec_dist_quick(&tst_pos, &Eye_position) <= 3000.0f){
3188 // within 300 meters
3189 if( (vm_vec_dist_quick(&tst_pos, &Eye_position) <= 300.0f) && ((tst_time == 0) || ((time(NULL) - tst_time) >= 10)) ){
3196 void game_tst_frame()
3206 tst_time = time(NULL);
3208 // load the tst bitmap
3209 switch((int)frand_range(0.0f, 3.0)){
3211 tst_bitmap = bm_load("ig_jim");
3213 mprintf(("TST 0\n"));
3217 tst_bitmap = bm_load("ig_kan");
3219 mprintf(("TST 1\n"));
3223 tst_bitmap = bm_load("ig_jim");
3225 mprintf(("TST 2\n"));
3229 tst_bitmap = bm_load("ig_kan");
3231 mprintf(("TST 3\n"));
3240 // get the tst bitmap dimensions
3242 bm_get_info(tst_bitmap, &w, &h);
3245 tst_y = frand_range(0.0f, (float)gr_screen.max_h - h);
3247 snd_play(&Snds[SND_VASUDAN_BUP]);
3249 // tst x and direction
3253 tst_offset_total = (float)w;
3254 tst_offset = (float)w;
3256 tst_x = (float)gr_screen.max_w;
3257 tst_offset_total = (float)-w;
3258 tst_offset = (float)w;
3266 float diff = (tst_offset_total / 0.5f) * flFrametime;
3272 tst_offset -= fl_abs(diff);
3273 } else if(tst_mode == 2){
3276 tst_offset -= fl_abs(diff);
3280 gr_set_bitmap(tst_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
3281 gr_bitmap((int)tst_x, (int)tst_y);
3284 if(timestamp_elapsed_safe(tst_stamp, 1100)){
3288 // if we passed the switch point
3289 if(tst_offset <= 0.0f){
3294 tst_stamp = timestamp(1000);
3295 tst_offset = fl_abs(tst_offset_total);
3306 void game_tst_mark(object *objp, ship *shipp)
3315 if((objp == NULL) || (shipp == NULL) || (shipp->ship_info_index < 0) || (shipp->ship_info_index >= Num_ship_types)){
3318 sip = &Ship_info[shipp->ship_info_index];
3325 tst_pos = objp->pos;
3326 if(sip->flags & (SIF_BIG_SHIP | SIF_HUGE_SHIP)){
3332 extern void render_shields();
3334 void player_repair_frame(float frametime)
3336 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
3338 for(idx=0;idx<MAX_PLAYERS;idx++){
3341 np = &Net_players[idx];
3343 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)){
3345 // don't rearm/repair if the player is dead or dying/departing
3346 if ( !NETPLAYER_IS_DEAD(np) && !(Ships[Objects[np->player->objnum].instance].flags & (SF_DYING|SF_DEPARTING)) ) {
3347 ai_do_repair_frame(&Objects[Net_players[idx].player->objnum],&Ai_info[Ships[Objects[Net_players[idx].player->objnum].instance].ai_index],frametime);
3352 if ( (Player_obj != NULL) && (Player_obj->type == OBJ_SHIP) && !(Game_mode & GM_STANDALONE_SERVER) && (Player_ship != NULL) && !(Player_ship->flags & SF_DYING) ) {
3353 ai_do_repair_frame(Player_obj, &Ai_info[Ships[Player_obj->instance].ai_index], frametime);
3359 #define NUM_FRAMES_TEST 300
3360 #define NUM_MIXED_SOUNDS 16
3361 void do_timing_test(float flFrametime)
3363 static int framecount = 0;
3364 static int test_running = 0;
3365 static float test_time = 0.0f;
3367 static int snds[NUM_MIXED_SOUNDS];
3370 if ( test_running ) {
3372 test_time += flFrametime;
3373 if ( framecount >= NUM_FRAMES_TEST ) {
3375 nprintf(("General", "%d frames took %.3f seconds\n", NUM_FRAMES_TEST, test_time));
3376 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3381 if ( Test_begin == 1 ) {
3387 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3390 // start looping digital sounds
3391 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3392 snds[i] = snd_play_looping( &Snds[i], 0.0f, -1, -1);
3399 DCF(dcf_fov, "Change the field of view")
3402 dc_get_arg(ARG_FLOAT|ARG_NONE);
3403 if ( Dc_arg_type & ARG_NONE ) {
3404 Viewer_zoom = VIEWER_ZOOM_DEFAULT;
3405 dc_printf( "Zoom factor reset\n" );
3407 if ( Dc_arg_type & ARG_FLOAT ) {
3408 if (Dc_arg_float < 0.25f) {
3409 Viewer_zoom = 0.25f;
3410 dc_printf("Zoom factor pinned at 0.25.\n");
3411 } else if (Dc_arg_float > 1.25f) {
3412 Viewer_zoom = 1.25f;
3413 dc_printf("Zoom factor pinned at 1.25.\n");
3415 Viewer_zoom = Dc_arg_float;
3421 dc_printf( "Usage: fov [factor]\nFactor is the zoom factor btwn .25 and 1.25\nNo parameter resets it to default.\n" );
3424 dc_printf("Zoom factor set to %6.3f (original = 0.5, John = 0.75)", Viewer_zoom);
3428 DCF(framerate_cap, "Sets the framerate cap")
3431 dc_get_arg(ARG_INT);
3432 if ( (Dc_arg_int >= 1 ) || (Dc_arg_int <= 120) ) {
3433 Framerate_cap = Dc_arg_int;
3435 dc_printf( "Illegal value for framerate cap. (Must be from 1-120) \n\n");
3441 dc_printf("Usage: framerate_cap [n]\nwhere n is the frames per second to cap framerate at.\n");
3442 dc_printf("If n is 0 or omitted, then the framerate cap is removed\n");
3443 dc_printf("[n] must be from 1 to 120.\n");
3447 if ( Framerate_cap )
3448 dc_printf("Framerate cap is set to %d fps\n", Framerate_cap );
3450 dc_printf("There is no framerate cap currently active.\n");
3454 #define MIN_DIST_TO_DEAD_CAMERA 50.0f
3455 int Show_viewing_from_self = 0;
3457 void say_view_target()
3459 object *view_target;
3461 if ((Viewer_mode & VM_OTHER_SHIP) && (Player_ai->target_objnum != -1))
3462 view_target = &Objects[Player_ai->target_objnum];
3464 view_target = Player_obj;
3466 if (Game_mode & GM_DEAD) {
3467 if (Player_ai->target_objnum != -1)
3468 view_target = &Objects[Player_ai->target_objnum];
3471 if (!(Game_mode & GM_DEAD_DIED) && ((Game_mode & (GM_DEAD_BLEW_UP)) || ((Last_view_target != NULL) && (Last_view_target != view_target)))) {
3472 if (view_target != Player_obj){
3474 char *view_target_name = NULL;
3475 switch(Objects[Player_ai->target_objnum].type) {
3477 view_target_name = Ships[Objects[Player_ai->target_objnum].instance].ship_name;
3480 view_target_name = Weapon_info[Weapons[Objects[Player_ai->target_objnum].instance].weapon_info_index].name;
3481 Viewer_mode &= ~VM_OTHER_SHIP;
3483 case OBJ_JUMP_NODE: {
3484 char jump_node_name[128];
3485 strcpy(jump_node_name, XSTR( "jump node", 184));
3486 view_target_name = jump_node_name;
3487 Viewer_mode &= ~VM_OTHER_SHIP;
3496 if ( view_target_name ) {
3497 HUD_fixed_printf(0.0f, XSTR( "Viewing %s%s\n", 185), (Viewer_mode & VM_OTHER_SHIP) ? XSTR( "from ", 186) : "", view_target_name);
3498 Show_viewing_from_self = 1;
3501 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER) && (Player_obj->type == OBJ_OBSERVER)){
3502 HUD_fixed_printf(2.0f,XSTR( "Viewing from observer\n", 187));
3503 Show_viewing_from_self = 1;
3505 if (Show_viewing_from_self)
3506 HUD_fixed_printf(2.0f, XSTR( "Viewing from self\n", 188));
3511 Last_view_target = view_target;
3515 float Game_hit_x = 0.0f;
3516 float Game_hit_y = 0.0f;
3518 // Reset at the beginning of each frame
3519 void game_whack_reset()
3525 // Apply a 2d whack to the player
3526 void game_whack_apply( float x, float y )
3528 // Do some force feedback
3529 joy_ff_play_dir_effect(x * 80.0f, y * 80.0f);
3535 // mprintf(( "WHACK = %.1f, %.1f\n", Game_hit_x, Game_hit_y ));
3538 // call to apply a "shudder"
3539 void game_shudder_apply(int time, float intensity)
3541 Game_shudder_time = timestamp(time);
3542 Game_shudder_total = time;
3543 Game_shudder_intensity = intensity;
3546 #define FF_SCALE 10000
3547 void apply_hud_shake(matrix *eye_orient)
3549 if (Viewer_obj == Player_obj) {
3550 physics_info *pi = &Player_obj->phys_info;
3558 // Make eye shake due to afterburner
3559 if ( !timestamp_elapsed(pi->afterburner_decay) ) {
3562 dtime = timestamp_until(pi->afterburner_decay);
3566 tangles.p += 0.07f * (float) (r1-MY_RAND_MAX/2)/MY_RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/ABURN_DECAY_TIME));
3567 tangles.h += 0.07f * (float) (r2-MY_RAND_MAX/2)/MY_RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/ABURN_DECAY_TIME));
3570 // Make eye shake due to engine wash
3572 if (Player_obj->type == OBJ_SHIP && (Ships[Player_obj->instance].wash_intensity > 0) && Wash_on ) {
3575 tangles.p += 0.07f * Ships[Player_obj->instance].wash_intensity * (float) (r1-MY_RAND_MAX/2)/MY_RAND_MAX;
3576 tangles.h += 0.07f * Ships[Player_obj->instance].wash_intensity * (float) (r2-MY_RAND_MAX/2)/MY_RAND_MAX;
3578 // get the intensity
3579 float intensity = FF_SCALE * Ships[Player_obj->instance].wash_intensity;
3583 vm_vec_rand_vec_quick(&rand_vec);
3586 joy_ff_play_dir_effect(intensity*rand_vec.xyz.x, intensity*rand_vec.xyz.y);
3590 // make hud shake due to shuddering
3591 if(Game_shudder_time != -1){
3592 // if the timestamp has elapsed
3593 if(timestamp_elapsed(Game_shudder_time)){
3594 Game_shudder_time = -1;
3596 // otherwise apply some shudder
3600 dtime = timestamp_until(Game_shudder_time);
3604 tangles.p += (Game_shudder_intensity / 200.0f) * (float) (r1-MY_RAND_MAX/2)/MY_RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/(float)Game_shudder_total));
3605 tangles.h += (Game_shudder_intensity / 200.0f) * (float) (r2-MY_RAND_MAX/2)/MY_RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/(float)Game_shudder_total));
3610 vm_angles_2_matrix(&tm, &tangles);
3611 Assert(vm_vec_mag(&tm.v.fvec) > 0.0f);
3612 Assert(vm_vec_mag(&tm.v.rvec) > 0.0f);
3613 Assert(vm_vec_mag(&tm.v.uvec) > 0.0f);
3614 vm_matrix_x_matrix(&tm2, eye_orient, &tm);
3619 extern void compute_slew_matrix(matrix *orient, angles *a); // TODO: move code to proper place and extern in header file
3621 // Player's velocity just before he blew up. Used to keep camera target moving.
3622 vector Dead_player_last_vel = { { { 1.0f, 1.0f, 1.0f } } };
3624 // Set eye_pos and eye_orient based on view mode.
3625 void game_render_frame_setup(vector *eye_pos, matrix *eye_orient)
3629 static int last_Viewer_mode = 0;
3630 static int last_Game_mode = 0;
3631 static int last_Viewer_objnum = -1;
3633 // This code is supposed to detect camera "cuts"... like going between
3636 // determine if we need to regenerate the nebula
3637 if( (!(last_Viewer_mode & VM_EXTERNAL) && (Viewer_mode & VM_EXTERNAL)) || // internal to external
3638 ((last_Viewer_mode & VM_EXTERNAL) && !(Viewer_mode & VM_EXTERNAL)) || // external to internal
3639 (!(last_Viewer_mode & VM_DEAD_VIEW) && (Viewer_mode & VM_DEAD_VIEW)) || // non dead-view to dead-view
3640 ((last_Viewer_mode & VM_DEAD_VIEW) && !(Viewer_mode & VM_DEAD_VIEW)) || // dead-view to non dead-view
3641 (!(last_Viewer_mode & VM_WARP_CHASE) && (Viewer_mode & VM_WARP_CHASE)) || // non warp-chase to warp-chase
3642 ((last_Viewer_mode & VM_WARP_CHASE) && !(Viewer_mode & VM_WARP_CHASE)) || // warp-chase to non warp-chase
3643 (!(last_Viewer_mode & VM_OTHER_SHIP) && (Viewer_mode & VM_OTHER_SHIP)) || // non other-ship to other-ship
3644 ((last_Viewer_mode & VM_OTHER_SHIP) && !(Viewer_mode & VM_OTHER_SHIP)) || // other-ship to non-other ship
3645 ((Viewer_mode & VM_OTHER_SHIP) && (last_Viewer_objnum != Player_ai->target_objnum)) // other ship mode, but targets changes
3648 // regenerate the nebula
3652 if ( (last_Viewer_mode != Viewer_mode) || (last_Game_mode != Game_mode) ) {
3653 //mprintf(( "************** Camera cut! ************\n" ));
3654 last_Viewer_mode = Viewer_mode;
3655 last_Game_mode = Game_mode;
3657 // Camera moved. Tell stars & debris to not do blurring.
3663 if ( Viewer_mode & VM_PADLOCK_ANY ) {
3664 player_display_packlock_view();
3667 game_set_view_clip();
3669 if (Game_mode & GM_DEAD) {
3670 vector vec_to_deader, view_pos;
3673 Viewer_mode |= VM_DEAD_VIEW;
3675 if (Player_ai->target_objnum != -1) {
3676 int view_from_player = 1;
3678 if (Viewer_mode & VM_OTHER_SHIP) {
3679 // View from target.
3680 Viewer_obj = &Objects[Player_ai->target_objnum];
3682 last_Viewer_objnum = Player_ai->target_objnum;
3684 if ( Viewer_obj->type == OBJ_SHIP ) {
3685 ship_get_eye( eye_pos, eye_orient, Viewer_obj );
3686 view_from_player = 0;
3689 last_Viewer_objnum = -1;
3692 if ( view_from_player ) {
3693 // View target from player ship.
3695 *eye_pos = Player_obj->pos;
3696 vm_vec_normalized_dir(&eye_dir, &Objects[Player_ai->target_objnum].pos, eye_pos);
3697 vm_vector_2_matrix(eye_orient, &eye_dir, NULL, NULL);
3700 dist = vm_vec_normalized_dir(&vec_to_deader, &Player_obj->pos, &Dead_camera_pos);
3702 if (dist < MIN_DIST_TO_DEAD_CAMERA)
3703 dist += flFrametime * 16.0f;
3705 vm_vec_scale(&vec_to_deader, -dist);
3706 vm_vec_add(&Dead_camera_pos, &Player_obj->pos, &vec_to_deader);
3708 view_pos = Player_obj->pos;
3710 if (!(Game_mode & GM_DEAD_BLEW_UP)) {
3711 Viewer_mode &= ~(VM_EXTERNAL | VM_CHASE);
3712 vm_vec_scale_add2(&Dead_camera_pos, &Original_vec_to_deader, 25.0f * flFrametime);
3713 Dead_player_last_vel = Player_obj->phys_info.vel;
3714 //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));
3715 } else if (Player_ai->target_objnum != -1) {
3716 view_pos = Objects[Player_ai->target_objnum].pos;
3718 // Make camera follow explosion, but gradually slow down.
3719 vm_vec_scale_add2(&Player_obj->pos, &Dead_player_last_vel, flFrametime);
3720 view_pos = Player_obj->pos;
3721 vm_vec_scale(&Dead_player_last_vel, 0.99f);
3722 vm_vec_scale_add2(&Dead_camera_pos, &Original_vec_to_deader, min(25.0f, vm_vec_mag_quick(&Dead_player_last_vel)) * flFrametime);
3725 *eye_pos = Dead_camera_pos;
3727 vm_vec_normalized_dir(&eye_dir, &Player_obj->pos, eye_pos);
3729 vm_vector_2_matrix(eye_orient, &eye_dir, NULL, NULL);
3734 // if supernova shockwave
3735 if(supernova_camera_cut()){
3739 // call it dead view
3740 Viewer_mode |= VM_DEAD_VIEW;
3742 // set eye pos and orient
3743 supernova_set_view(eye_pos, eye_orient);
3745 // If already blown up, these other modes can override.
3746 if (!(Game_mode & (GM_DEAD | GM_DEAD_BLEW_UP))) {
3747 Viewer_mode &= ~VM_DEAD_VIEW;
3749 Viewer_obj = Player_obj;
3751 if (Viewer_mode & VM_OTHER_SHIP) {
3752 if (Player_ai->target_objnum != -1){
3753 Viewer_obj = &Objects[Player_ai->target_objnum];
3754 last_Viewer_objnum = Player_ai->target_objnum;
3756 Viewer_mode &= ~VM_OTHER_SHIP;
3757 last_Viewer_objnum = -1;
3760 last_Viewer_objnum = -1;
3763 if (Viewer_mode & VM_EXTERNAL) {
3766 vm_angles_2_matrix(&tm2, &Viewer_external_info.angles);
3767 vm_matrix_x_matrix(&tm, &Viewer_obj->orient, &tm2);
3769 vm_vec_scale_add(eye_pos, &Viewer_obj->pos, &tm.v.fvec, 2.0f * Viewer_obj->radius + Viewer_external_info.distance);
3771 vm_vec_sub(&eye_dir, &Viewer_obj->pos, eye_pos);
3772 vm_vec_normalize(&eye_dir);
3773 vm_vector_2_matrix(eye_orient, &eye_dir, &Viewer_obj->orient.v.uvec, NULL);
3776 // Modify the orientation based on head orientation.
3777 compute_slew_matrix(eye_orient, &Viewer_slew_angles);
3779 } else if ( Viewer_mode & VM_CHASE ) {
3782 if ( Viewer_obj->phys_info.speed < 0.1 )
3783 move_dir = Viewer_obj->orient.v.fvec;
3785 move_dir = Viewer_obj->phys_info.vel;
3786 vm_vec_normalize(&move_dir);
3789 vm_vec_scale_add(eye_pos, &Viewer_obj->pos, &move_dir, -3.0f * Viewer_obj->radius - Viewer_chase_info.distance);
3790 vm_vec_scale_add2(eye_pos, &Viewer_obj->orient.v.uvec, 0.75f * Viewer_obj->radius);
3791 vm_vec_sub(&eye_dir, &Viewer_obj->pos, eye_pos);
3792 vm_vec_normalize(&eye_dir);
3794 // JAS: I added the following code because if you slew up using
3795 // Descent-style physics, eye_dir and Viewer_obj->orient.v.uvec are
3796 // equal, which causes a zero-length vector in the vm_vector_2_matrix
3797 // call because the up and the forward vector are the same. I fixed
3798 // it by adding in a fraction of the right vector all the time to the
3800 vector tmp_up = Viewer_obj->orient.v.uvec;
3801 vm_vec_scale_add2( &tmp_up, &Viewer_obj->orient.v.rvec, 0.00001f );
3803 vm_vector_2_matrix(eye_orient, &eye_dir, &tmp_up, NULL);
3806 // Modify the orientation based on head orientation.
3807 compute_slew_matrix(eye_orient, &Viewer_slew_angles);
3808 } else if ( Viewer_mode & VM_WARP_CHASE ) {
3809 *eye_pos = Camera_pos;
3811 ship * shipp = &Ships[Player_obj->instance];
3813 vm_vec_sub(&eye_dir, &shipp->warp_effect_pos, eye_pos);
3814 vm_vec_normalize(&eye_dir);
3815 vm_vector_2_matrix(eye_orient, &eye_dir, &Player_obj->orient.v.uvec, NULL);
3818 // get an eye position based upon the correct type of object
3819 switch(Viewer_obj->type){
3821 // make a call to get the eye point for the player object
3822 ship_get_eye( eye_pos, eye_orient, Viewer_obj );
3825 // make a call to get the eye point for the player object
3826 observer_get_eye( eye_pos, eye_orient, Viewer_obj );
3832 #ifdef JOHNS_DEBUG_CODE
3833 john_debug_stuff(&eye_pos, &eye_orient);
3839 apply_hud_shake(eye_orient);
3841 // setup neb2 rendering
3842 neb2_render_setup(eye_pos, eye_orient);
3846 extern void ai_debug_render_stuff();
3849 int Game_subspace_effect = 0;
3850 DCF_BOOL( subspace, Game_subspace_effect );
3852 // Does everything needed to render a frame
3853 void game_render_frame( vector * eye_pos, matrix * eye_orient )
3857 g3_start_frame(game_zbuffer);
3858 g3_set_view_matrix( eye_pos, eye_orient, Viewer_zoom );
3860 // maybe offset the HUD (jitter stuff)
3861 dont_offset = ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER));
3862 HUD_set_offsets(Viewer_obj, !dont_offset);
3864 // for multiplayer clients, call code in Shield.cpp to set up the Shield_hit array. Have to
3865 // do this becaues of the disjointed nature of this system (in terms of setup and execution).
3866 // must be done before ships are rendered
3867 if ( MULTIPLAYER_CLIENT ) {
3868 shield_point_multi_setup();
3871 if ( Game_subspace_effect ) {
3872 stars_draw(0,0,0,1);
3874 stars_draw(1,1,1,0);
3877 obj_render_all(obj_render);
3878 beam_render_all(); // render all beam weapons
3879 particle_render_all(); // render particles after everything else.
3880 trail_render_all(); // render missilie trails after everything else.
3881 mflash_render_all(); // render all muzzle flashes
3883 // Why do we not show the shield effect in these modes? Seems ok.
3884 //if (!(Viewer_mode & (VM_EXTERNAL | VM_SLEWED | VM_CHASE | VM_DEAD_VIEW))) {
3888 // render nebula lightning
3891 // render local player nebula
3892 neb2_render_player();
3895 ai_debug_render_stuff();
3898 #ifndef RELEASE_REAL
3899 // game_framerate_check();
3903 extern void snd_spew_debug_info();
3904 snd_spew_debug_info();
3907 //================ END OF 3D RENDERING STUFF ====================
3911 if( (Game_detail_flags & DETAIL_FLAG_HUD) && (!(Game_mode & GM_MULTIPLAYER) || ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER) )) ) {
3912 hud_maybe_clear_head_area();
3913 anim_render_all(0, flFrametime);
3916 extern int Multi_display_netinfo;
3917 if(Multi_display_netinfo){
3918 extern void multi_display_netinfo();
3919 multi_display_netinfo();
3922 game_tst_frame_pre();
3925 do_timing_test(flFrametime);
3929 extern int OO_update_index;
3930 multi_rate_display(OO_update_index, 375, 0);
3935 extern void oo_display();
3942 //#define JOHNS_DEBUG_CODE 1
3944 #ifdef JOHNS_DEBUG_CODE
3945 void john_debug_stuff(vector *eye_pos, matrix *eye_orient)
3947 //if ( key_pressed(SDLK_LSHIFT) )
3949 ship_subsys *tsys = Players[Player_num].targeted_subobject;
3951 model_subsystem *turret = tsys->system_info;
3953 if (turret->type == SUBSYSTEM_TURRET ) {
3954 vector v.fvec, v.uvec;
3955 object * tobj = &Objects[Players[Player_num].targeted_subobject_parent];
3957 ship_model_start(tobj);
3959 model_find_world_point(eye_pos, &turret->turret_firing_point[0], turret->model_num, turret->turret_gun_sobj, &tobj->orient, &tobj->pos );
3960 model_find_world_dir(&v.fvec, &turret->turret_matrix.v.fvec, turret->model_num, turret->turret_gun_sobj, &tobj->orient, NULL );
3961 model_find_world_dir(&v.uvec, &turret->turret_matrix.v.uvec, turret->model_num, turret->turret_gun_sobj, &tobj->orient, NULL );
3963 vm_vector_2_matrix( eye_orient, &v.fvec, &v.uvec, NULL );
3965 ship_model_stop(tobj);
3975 // following function for dumping frames for purposes of building trailers.
3978 // function to toggle state of dumping every frame into PCX when playing the game
3979 DCF(dump_frames, "Starts/stop frame dumping at 15 hz")
3983 if ( Debug_dump_frames == 0 ) {
3985 Debug_dump_frames = 15;
3986 Debug_dump_trigger = 0;
3987 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
3988 dc_printf( "Frame dumping at 15 hz is now ON\n" );
3991 Debug_dump_frames = 0;
3992 Debug_dump_trigger = 0;
3993 gr_dump_frame_stop();
3994 dc_printf( "Frame dumping is now OFF\n" );
4000 DCF(dump_frames_trigger, "Starts/stop frame dumping at 15 hz")
4004 if ( Debug_dump_frames == 0 ) {
4006 Debug_dump_frames = 15;
4007 Debug_dump_trigger = 1;
4008 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
4009 dc_printf( "Frame dumping at 15 hz is now ON\n" );
4012 Debug_dump_frames = 0;
4013 Debug_dump_trigger = 0;
4014 gr_dump_frame_stop();
4015 dc_printf( "Frame dumping is now OFF\n" );
4021 DCF(dump_frames30, "Starts/stop frame dumping at 30 hz")
4025 if ( Debug_dump_frames == 0 ) {
4027 Debug_dump_frames = 30;
4028 Debug_dump_trigger = 0;
4029 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
4030 dc_printf( "Frame dumping at 30 hz is now ON\n" );
4033 Debug_dump_frames = 0;
4034 Debug_dump_trigger = 0;
4035 gr_dump_frame_stop();
4036 dc_printf( "Frame dumping is now OFF\n" );
4042 DCF(dump_frames30_trigger, "Starts/stop frame dumping at 30 hz")
4046 if ( Debug_dump_frames == 0 ) {
4048 Debug_dump_frames = 30;
4049 Debug_dump_trigger = 1;
4050 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
4051 dc_printf( "Triggered frame dumping at 30 hz is now ON\n" );
4054 Debug_dump_frames = 0;
4055 Debug_dump_trigger = 0;
4056 gr_dump_frame_stop();
4057 dc_printf( "Triggered frame dumping is now OFF\n" );
4063 void game_maybe_dump_frame()
4065 if ( !Debug_dump_frames ){
4069 if( Debug_dump_trigger && !key_pressed(SDLK_q) ){
4076 Debug_dump_frame_num++;
4082 extern int Player_dead_state;
4084 // Flip the page and time how long it took.
4085 void game_flip_page_and_time_it()
4090 t1 = timer_get_fixed_seconds();
4092 t2 = timer_get_fixed_seconds();
4095 t = (gr_screen.max_w*gr_screen.max_h*gr_screen.bytes_per_pixel)/1024;
4096 sprintf( transfer_text, NOX("%ld MB/s"), fixmuldiv(t,65,d) );
4103 void game_simulation_frame()
4105 // blow ships up in multiplayer dogfight
4106 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){
4107 // blow up all non-player ships
4108 ship_obj *moveup = GET_FIRST(&Ship_obj_list);
4111 while((moveup != END_OF_LIST(&Ship_obj_list)) && (moveup != NULL)){
4113 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)){
4114 moveup = GET_NEXT(moveup);
4117 shipp = &Ships[Objects[moveup->objnum].instance];
4118 sip = &Ship_info[shipp->ship_info_index];
4120 // only blow up small ships
4121 if((sip->flags & SIF_SMALL_SHIP) && (multi_find_player_by_object(&Objects[moveup->objnum]) < 0) ){
4122 // function to simply explode a ship where it is currently at
4123 ship_self_destruct( &Objects[moveup->objnum] );
4126 moveup = GET_NEXT(moveup);
4132 // process AWACS stuff - do this first thing
4135 // single player, set Player hits_this_frame to 0
4136 if ( !(Game_mode & GM_MULTIPLAYER) && Player ) {
4137 Player->damage_this_burst -= (flFrametime * MAX_BURST_DAMAGE / (0.001f * BURST_DURATION));
4138 Player->damage_this_burst = max(Player->damage_this_burst, 0.0f);
4142 supernova_process();
4143 if(supernova_active() >= 5){
4147 // fire targeting lasers now so that
4148 // 1 - created this frame
4149 // 2 - collide this frame
4150 // 3 - render this frame
4151 // 4 - ignored and deleted next frame
4152 // the basic idea being that because it con be confusing to deal with them on a multi-frame basis, they are only valid for
4154 ship_process_targeting_lasers();
4156 // do this here so that it works for multiplayer
4158 // get viewer direction
4159 int viewer_direction = PHYSICS_VIEWER_REAR;
4161 if(Viewer_mode == 0){
4162 viewer_direction = PHYSICS_VIEWER_FRONT;
4164 if(Viewer_mode & VM_PADLOCK_UP){
4165 viewer_direction = PHYSICS_VIEWER_UP;
4167 else if(Viewer_mode & VM_PADLOCK_REAR){
4168 viewer_direction = PHYSICS_VIEWER_REAR;
4170 else if(Viewer_mode & VM_PADLOCK_LEFT){
4171 viewer_direction = PHYSICS_VIEWER_LEFT;
4173 else if(Viewer_mode & VM_PADLOCK_RIGHT){
4174 viewer_direction = PHYSICS_VIEWER_RIGHT;
4177 physics_set_viewer( &Viewer_obj->phys_info, viewer_direction );
4179 physics_set_viewer( NULL, PHYSICS_VIEWER_FRONT );
4182 #define VM_PADLOCK_UP (1 << 7)
4183 #define VM_PADLOCK_REAR (1 << 8)
4184 #define VM_PADLOCK_LEFT (1 << 9)
4185 #define VM_PADLOCK_RIGHT (1 << 10)
4187 // evaluate mission departures and arrivals before we process all objects.
4188 if ( !(Game_mode & GM_MULTIPLAYER) || ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER) && !multi_endgame_ending()) ) {
4190 // we don't want to evaluate mission stuff when any ingame joiner in multiplayer is receiving
4191 // ships/wing packets.
4192 if ( !((Game_mode & GM_MULTIPLAYER) && (Netgame.flags & NG_FLAG_INGAME_JOINING_CRITICAL)) && !(Game_mode & GM_DEMO_PLAYBACK)){
4193 mission_parse_eval_stuff();
4196 // if we're an observer, move ourselves seperately from the standard physics
4197 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER)){
4198 obj_observer_move(flFrametime);
4201 // move all the objects now
4202 obj_move_all(flFrametime);
4204 // check for cargo reveal (this has an internal timestamp, so only runs every N ms)
4205 // AL: 3-15-98: It was decided to not let AI ships inspect cargo
4206 // ship_check_cargo_all();
4207 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4208 mission_eval_goals();
4212 // always check training objectives, even in multiplayer missions. we need to do this so that the directives gauge works properly on clients
4213 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4214 training_check_objectives();
4217 // do all interpolation now
4218 if ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER) && !multi_endgame_ending() && !(Netgame.flags & NG_FLAG_SERVER_LOST)) {
4219 // client side processing of warping in effect stages
4220 multi_do_client_warp(flFrametime);
4222 // client side movement of an observer
4223 if((Net_player->flags & NETINFO_FLAG_OBSERVER) || (Player_obj->type == OBJ_OBSERVER)){
4224 obj_observer_move(flFrametime);
4227 // move all objects - does interpolation now as well
4228 obj_move_all(flFrametime);
4231 // only process the message queue when the player is "in" the game
4232 if ( !Pre_player_entry ){
4233 message_queue_process(); // process any messages send to the player
4236 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4237 message_maybe_distort(); // maybe distort incoming message if comms damaged
4238 player_repair_frame(flFrametime); // AI objects get repaired in ai_process, called from move code...deal with player.
4239 player_process_pending_praise(); // maybe send off a delayed praise message to the player
4240 player_maybe_play_all_alone_msg(); // mabye tell the player he is all alone
4243 if(!(Game_mode & GM_STANDALONE_SERVER)){
4244 // process some stuff every frame (before frame is rendered)
4245 emp_process_local();
4247 hud_update_frame(); // update hud systems
4249 if (!physics_paused) {
4250 // Move particle system
4251 particle_move_all(flFrametime);
4253 // Move missile trails
4254 trail_move_all(flFrametime);
4256 // process muzzle flashes
4257 mflash_process_all();
4259 // Flash the gun flashes
4260 shipfx_flash_do_frame(flFrametime);
4262 shockwave_move_all(flFrametime); // update all the shockwaves
4265 // subspace missile strikes
4268 obj_snd_do_frame(); // update the object-linked persistant sounds
4269 game_maybe_update_sound_environment();
4270 snd_update_listener(&View_position, &Player_obj->phys_info.vel, &Player_obj->orient);
4272 // AL: debug code used for testing ambient subspace sound (ie when enabling subspace through debug console)
4274 if ( Game_subspace_effect ) {
4275 game_start_subspace_ambient_sound();
4281 // Maybe render and process the dead-popup
4282 void game_maybe_do_dead_popup(float frametime)
4284 if ( popupdead_is_active() ) {
4286 int choice = popupdead_do_frame(frametime);
4288 if ( Game_mode & GM_NORMAL ) {
4291 gameseq_post_event(GS_EVENT_ENTER_GAME);
4295 gameseq_post_event(GS_EVENT_END_GAME);
4299 gameseq_post_event(GS_EVENT_START_GAME);
4302 // this should only happen during a red alert mission
4305 Assert(The_mission.red_alert);
4306 if(!The_mission.red_alert){
4307 gameseq_post_event(GS_EVENT_START_GAME);
4311 // choose the previous mission
4312 mission_campaign_previous_mission();
4314 gameseq_post_event(GS_EVENT_START_GAME);
4324 case POPUPDEAD_DO_MAIN_HALL:
4325 multi_quit_game(PROMPT_NONE,-1);
4328 case POPUPDEAD_DO_RESPAWN:
4329 multi_respawn_normal();
4330 event_music_player_respawn();
4333 case POPUPDEAD_DO_OBSERVER:
4334 multi_respawn_observer();
4335 event_music_player_respawn_as_observer();
4344 if ( leave_popup ) {
4350 // returns true if player is actually in a game_play stats
4351 int game_actually_playing()
4355 state = gameseq_get_state();
4356 if ( (state != GS_STATE_GAME_PLAY) && (state != GS_STATE_DEATH_DIED) && (state != GS_STATE_DEATH_BLEW_UP) )
4362 // Draw the 2D HUD gauges
4363 void game_render_hud_2d()
4365 if ( !(Game_detail_flags & DETAIL_FLAG_HUD) ) {
4369 HUD_render_2d(flFrametime);
4373 // Draw the 3D-dependant HUD gauges
4374 void game_render_hud_3d(vector *eye_pos, matrix *eye_orient)
4376 g3_start_frame(0); // 0 = turn zbuffering off
4377 g3_set_view_matrix( eye_pos, eye_orient, Viewer_zoom );
4379 if ( (Game_detail_flags & DETAIL_FLAG_HUD) && (supernova_active() < 3)/* && !(Game_mode & GM_MULTIPLAYER) || ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER) )*/ ) {
4380 HUD_render_3d(flFrametime);
4384 game_sunspot_process(flFrametime);
4386 // Diminish the palette effect
4387 game_flash_diminish(flFrametime);
4395 int actually_playing;
4396 fix total_time1, total_time2;
4397 fix render2_time1=0, render2_time2=0;
4398 fix render3_time1=0, render3_time2=0;
4399 fix flip_time1=0, flip_time2=0;
4400 fix clear_time1=0, clear_time2=0;
4406 if (Framerate_delay) {
4407 int start_time = timer_get_milliseconds();
4408 while (timer_get_milliseconds() < start_time + Framerate_delay)
4414 demo_do_frame_start();
4416 mprintf(("Error (%d) while processing demo!\n", Demo_error));
4421 // start timing frame
4422 timing_frame_start();
4424 total_time1 = timer_get_fixed_seconds();
4426 // var to hold which state we are in
4427 actually_playing = game_actually_playing();
4429 if ((!(Game_mode & GM_MULTIPLAYER)) || ((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER))) {
4430 if (!(Game_mode & GM_STANDALONE_SERVER)){
4431 Assert( OBJ_INDEX(Player_obj) >= 0 );
4435 if (Missiontime > Entry_delay_time){
4436 Pre_player_entry = 0;
4438 ; //nprintf(("AI", "Framecount = %i, time = %7.3f\n", Framecount, f2fl(Missiontime)));
4441 // Note: These are done even before the player enters, else buffers can overflow.
4442 if (! (Game_mode & GM_STANDALONE_SERVER)){
4446 shield_frame_init();
4448 if ( Player->control_mode != PCM_NORMAL )
4451 if ( !Pre_player_entry && actually_playing ) {
4452 if (! (Game_mode & GM_STANDALONE_SERVER) ) {
4454 if( (!popup_running_state()) && (!popupdead_is_active()) ){
4455 game_process_keys();
4457 // don't read flying controls if we're playing a demo back
4458 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4459 read_player_controls( Player_obj, flFrametime);
4463 // if we're not the master, we may have to send the server-critical ship status button_info bits
4464 if ((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER)){
4465 multi_maybe_send_ship_status();
4470 // Reset the whack stuff
4473 // These two lines must be outside of Pre_player_entry code,
4474 // otherwise too many lights are added.
4477 if ((Game_mode & GM_MULTIPLAYER) && (Netgame.game_state == NETGAME_STATE_SERVER_TRANSFER)){
4481 game_simulation_frame();
4483 // if not actually in a game play state, then return. This condition could only be true in
4484 // a multiplayer game.
4485 if ( !actually_playing ) {
4486 Assert( Game_mode & GM_MULTIPLAYER );
4490 if (!Pre_player_entry) {
4491 if (! (Game_mode & GM_STANDALONE_SERVER)) {
4492 clear_time1 = timer_get_fixed_seconds();
4493 // clear the screen to black
4495 if ( (Game_detail_flags & DETAIL_FLAG_CLEAR) ) {
4499 clear_time2 = timer_get_fixed_seconds();
4500 render3_time1 = timer_get_fixed_seconds();
4501 game_render_frame_setup(&eye_pos, &eye_orient);
4502 game_render_frame( &eye_pos, &eye_orient );
4504 // save the eye position and orientation
4505 if ( Game_mode & GM_MULTIPLAYER ) {
4506 Net_player->s_info.eye_pos = eye_pos;
4507 Net_player->s_info.eye_orient = eye_orient;
4510 hud_show_target_model();
4512 // check to see if we should display the death died popup
4513 if(Game_mode & GM_DEAD_BLEW_UP){
4514 if(Game_mode & GM_MULTIPLAYER){
4515 // catch the situation where we're supposed to be warping out on this transition
4516 if(Net_player->flags & NETINFO_FLAG_WARPING_OUT){
4517 gameseq_post_event(GS_EVENT_DEBRIEF);
4518 } else if((Player_died_popup_wait != -1) && (timestamp_elapsed(Player_died_popup_wait))){
4519 Player_died_popup_wait = -1;
4523 if((Player_died_popup_wait != -1) && (timestamp_elapsed(Player_died_popup_wait))){
4524 Player_died_popup_wait = -1;
4530 // hack - sometimes this seems to slip by in multiplayer. this should guarantee that we catch it
4531 if((Game_mode & GM_MULTIPLAYER) && (Player_multi_died_check != -1) && (Game_mode & GM_DEAD_BLEW_UP) ){
4532 if(fl_abs(time(NULL) - Player_multi_died_check) > 4){
4533 if(!popupdead_is_active()){
4537 Player_multi_died_check = -1;
4541 render3_time2 = timer_get_fixed_seconds();
4542 render2_time1 = timer_get_fixed_seconds();
4545 game_get_framerate();
4546 game_show_framerate();
4548 game_show_time_left();
4550 // Draw the 2D HUD gauges
4551 if(supernova_active() < 3){
4552 game_render_hud_2d();
4555 game_set_view_clip();
4557 // Draw 3D HUD gauges
4558 game_render_hud_3d(&eye_pos, &eye_orient);
4562 render2_time2 = timer_get_fixed_seconds();
4564 // maybe render and process the dead popup
4565 game_maybe_do_dead_popup(flFrametime);
4567 // start timing frame
4568 timing_frame_stop();
4569 // timing_display(30, 10);
4571 // If a regular popup is active, don't flip (popup code flips)
4572 if( !popup_running_state() ){
4573 flip_time1 = timer_get_fixed_seconds();
4574 game_flip_page_and_time_it();
4575 flip_time2 = timer_get_fixed_seconds();
4579 game_maybe_dump_frame(); // used to dump pcx files for building trailers
4582 game_show_standalone_framerate();
4586 game_do_training_checks();
4589 // process lightning (nebula only)
4592 total_time2 = timer_get_fixed_seconds();
4594 // Got some timing numbers
4595 Timing_total = f2fl( total_time2 - total_time1 ) * 1000.0f;
4596 Timing_clear = f2fl( clear_time2 - clear_time1 ) * 1000.0f;
4597 Timing_render2 = f2fl( render2_time2- render2_time1 ) * 1000.0f;
4598 Timing_render3 = f2fl( render3_time2- render3_time1 ) * 1000.0f;
4599 Timing_flip = f2fl( flip_time2 - flip_time1 ) * 1000.0f;
4602 demo_do_frame_end();
4604 mprintf(("Error (%d) while processing demo!\n", Demo_error));
4610 #define MAX_FRAMETIME (F1_0/4) // Frametime gets saturated at this. Changed by MK on 11/1/97.
4611 // Some bug was causing Frametime to always get saturated at 2.0 seconds after the player
4612 // died. This resulted in screwed up death sequences.
4614 fix Last_time = 0; // The absolute time of game at end of last frame (beginning of this frame)
4615 fix Last_delta_time = 0; // While game is paused, this keeps track of how much elapsed in the frame before paused.
4616 static int timer_paused=0;
4617 #if defined(TIMER_TEST) && !defined(NDEBUG)
4618 static int stop_count,start_count;
4619 static int time_stopped,time_started;
4621 int saved_timestamp_ticker = -1;
4623 void game_reset_time()
4625 if((Game_mode & GM_MULTIPLAYER) && (Netgame.game_state == NETGAME_STATE_SERVER_TRANSFER)){
4629 // Last_time = timer_get_fixed_seconds();
4635 void game_stop_time()
4637 if (timer_paused==0) {
4639 time = timer_get_fixed_seconds();
4640 // Save how much time progressed so far in the frame so we can
4641 // use it when we unpause.
4642 Last_delta_time = time - Last_time;
4644 //mprintf(("Last_time in game_stop_time = %7.3f\n", f2fl(Last_delta_time)));
4645 if (Last_delta_time < 0) {
4646 #if defined(TIMER_TEST) && !defined(NDEBUG)
4647 Int3(); //get Matt!!!!
4649 Last_delta_time = 0;
4651 #if defined(TIMER_TEST) && !defined(NDEBUG)
4652 time_stopped = time;
4655 // Stop the timer_tick stuff...
4656 // Normally, you should never access 'timestamp_ticker', consider this a low-level routine
4657 saved_timestamp_ticker = timestamp_ticker;
4661 #if defined(TIMER_TEST) && !defined(NDEBUG)
4666 void game_start_time()
4669 Assert(timer_paused >= 0);
4670 if (timer_paused==0) {
4672 time = timer_get_fixed_seconds();
4673 #if defined(TIMER_TEST) && !defined(NDEBUG)
4675 Int3(); //get Matt!!!!
4678 // Take current time, and set it backwards to account for time
4679 // that the frame already executed, so that timer_get_fixed_seconds() - Last_time
4680 // will be correct when it goes to calculate the frametime next
4682 Last_time = time - Last_delta_time;
4683 #if defined(TIMER_TEST) && !defined(NDEBUG)
4684 time_started = time;
4687 // Restore the timer_tick stuff...
4688 // Normally, you should never access 'timestamp_ticker', consider this a low-level routine
4689 Assert( saved_timestamp_ticker > -1 ); // Called out of order, get JAS
4690 timestamp_ticker = saved_timestamp_ticker;
4691 saved_timestamp_ticker = -1;
4694 #if defined(TIMER_TEST) && !defined(NDEBUG)
4700 void game_set_frametime(int state)
4703 float frame_cap_diff;
4705 thistime = timer_get_fixed_seconds();
4707 if ( Last_time == 0 )
4708 Frametime = F1_0 / 30;
4710 Frametime = thistime - Last_time;
4712 // Frametime = F1_0 / 30;
4714 fix debug_frametime = Frametime; // Just used to display frametime.
4716 // If player hasn't entered mission yet, make frame take 1/4 second.
4717 if ((Pre_player_entry) && (state == GS_STATE_GAME_PLAY))
4720 else if ((Debug_dump_frames) && (state == GS_STATE_GAME_PLAY)) { // note link to above if!!!!!
4722 fix frame_speed = F1_0 / Debug_dump_frames;
4724 if (Frametime > frame_speed ){
4725 nprintf(("warning","slow frame: %x\n",Frametime));
4728 thistime = timer_get_fixed_seconds();
4729 Frametime = thistime - Last_time;
4730 } while (Frametime < frame_speed );
4732 Frametime = frame_speed;
4736 Assert( Framerate_cap > 0 );
4738 // Cap the framerate so it doesn't get too high.
4742 cap = F1_0/Framerate_cap;
4743 if (Frametime < cap) {
4744 thistime = cap - Frametime;
4745 //mprintf(("Sleeping for %6.3f seconds.\n", f2fl(thistime)));
4746 Sleep( (DWORD)(f2fl(thistime) * 1000.0f) );
4748 thistime = timer_get_fixed_seconds();
4752 if((Game_mode & GM_STANDALONE_SERVER) &&
4753 (f2fl(Frametime) < ((float)1.0/(float)Multi_options_g.std_framecap))){
4755 frame_cap_diff = ((float)1.0/(float)Multi_options_g.std_framecap) - f2fl(Frametime);
4756 Sleep((DWORD)(frame_cap_diff*1000));
4758 thistime += fl2f((frame_cap_diff));
4760 Frametime = thistime - Last_time;
4763 // If framerate is too low, cap it.
4764 if (Frametime > MAX_FRAMETIME) {
4766 mprintf(("Frame %2i too long!!: frametime = %.3f (%.3f)\n", Framecount, f2fl(Frametime), f2fl(debug_frametime)));
4768 // to remove warnings in release build
4769 debug_frametime = fl2f(flFrametime);
4771 Frametime = MAX_FRAMETIME;
4774 Frametime = fixmul(Frametime, Game_time_compression);
4776 Last_time = thistime;
4777 //mprintf(("Frame %i, Last_time = %7.3f\n", Framecount, f2fl(Last_time)));
4779 flFrametime = f2fl(Frametime);
4780 //if(!(Game_mode & GM_PLAYING_DEMO)){
4781 timestamp_inc(flFrametime);
4783 /* if ((Framecount > 0) && (Framecount < 10)) {
4784 mprintf(("Frame %2i: frametime = %.3f (%.3f)\n", Framecount, f2fl(Frametime), f2fl(debug_frametime)));
4789 // This is called from game_do_frame(), and from navmap_do_frame()
4790 void game_update_missiontime()
4792 // TODO JAS: Put in if and move this into game_set_frametime,
4793 // fix navmap to call game_stop/start_time
4794 //if ( !timer_paused )
4795 Missiontime += Frametime;
4798 void game_do_frame()
4800 game_set_frametime(GS_STATE_GAME_PLAY);
4801 game_update_missiontime();
4803 if (Game_mode & GM_STANDALONE_SERVER) {
4804 std_multi_set_standalone_missiontime(f2fl(Missiontime));
4807 if ( game_single_step && (last_single_step == game_single_step) ) {
4808 os_set_title( NOX("SINGLE STEP MODE (Pause exits, any other key steps)") );
4809 while( key_checkch() == 0 )
4811 os_set_title( XSTR( "FreeSpace", 171) );
4812 Last_time = timer_get_fixed_seconds();
4815 last_single_step = game_single_step;
4817 if ((gameseq_get_state() == GS_STATE_GAME_PLAY) && Use_mouse_to_fly){
4818 Keep_mouse_centered = 1; // force mouse to center of our window (so we don't hit movement limits)
4822 Keep_mouse_centered = 0;
4823 monitor_update(); // Update monitor variables
4826 void multi_maybe_do_frame()
4828 if ( (Game_mode & GM_MULTIPLAYER) && (Game_mode & GM_IN_MISSION) && !Multi_pause_status){
4833 int Joymouse_button_status = 0;
4835 // Flush all input devices
4843 Joymouse_button_status = 0;
4845 //mprintf(("Game flush!\n" ));
4848 // function for multiplayer only which calls game_do_state_common() when running the
4850 void game_do_dc_networking()
4852 Assert( Game_mode & GM_MULTIPLAYER );
4854 game_do_state_common( gameseq_get_state() );
4857 // Call this whenever in a loop, or when you need to check for a keystroke.
4858 int game_check_key()
4864 // convert keypad enter to normal enter
4865 if ((k & KEY_MASK) == SDLK_KP_ENTER)
4866 k = (k & ~KEY_MASK) | SDLK_RETURN;
4871 #if defined(FS2_DEMO) || defined(FS1_DEMO)
4873 #define DEMO_TRAILER_TIMEOUT_MS 45000 // 45 seconds of no input, play trailer
4874 static int Demo_show_trailer_timestamp = 0;
4876 void demo_reset_trailer_timer()
4878 Demo_show_trailer_timestamp = timer_get_milliseconds();
4881 void demo_maybe_show_trailer(int k)
4884 // if key pressed, reset demo trailer timer
4886 demo_reset_trailer_timer();
4890 // if mouse moved, reset demo trailer timer
4893 mouse_get_delta(&dx, &dy);
4894 if ( (dx > 0) || (dy > 0) ) {
4895 demo_reset_trailer_timer();
4899 // if joystick has moved, reset demo trailer timer
4902 joy_get_delta(&dx, &dy);
4903 if ( (dx > 0) || (dy > 0) ) {
4904 demo_reset_trailer_timer();
4908 // NOTE: reseting the trailer timer on mouse/joystick presses is handled in
4909 // the low-level code. Ugly, I know... but was the simplest and most
4912 // if 30 seconds since last demo trailer time reset, launch movie
4913 if ( os_foreground() ) {
4914 int now = timer_get_milliseconds();
4915 if ( (now - Demo_show_trailer_timestamp) > DEMO_TRAILER_TIMEOUT_MS ) {
4916 // if ( (now - Demo_show_trailer_timestamp) > 10000 ) {
4918 movie_play( NOX("fstrailer2.mve") );
4919 demo_reset_trailer_timer();
4927 // same as game_check_key(), except this is used while actually in the game. Since there
4928 // generally are differences between game control keys and general UI keys, makes sense to
4929 // have seperate functions for each case. If you are not checking a game control while in a
4930 // mission, you should probably be using game_check_key() instead.
4935 if (!os_foreground()) {
4940 // If we're in a single player game, pause it.
4941 if (!(Game_mode & GM_MULTIPLAYER)){
4942 if ( (gameseq_get_state() == GS_STATE_GAME_PLAY) && (!popup_active()) && (!popupdead_is_active()) ) {
4943 game_process_pause_key();
4950 #if defined(FS2_DEMO) || defined(FS1_DEMO)
4951 demo_maybe_show_trailer(k);
4954 // Move the mouse cursor with the joystick.
4955 if (os_foreground() && (!Mouse_hidden) && (Use_joy_mouse) ) {
4956 // Move the mouse cursor with the joystick
4960 joy_get_pos( &jx, &jy, &jz, &jr );
4962 dx = fl2i(f2fl(jx)*flFrametime*500.0f);
4963 dy = fl2i(f2fl(jy)*flFrametime*500.0f);
4966 mouse_get_real_pos( &mx, &my );
4967 mouse_set_pos( mx+dx, my+dy );
4972 m = mouse_down(MOUSE_LEFT_BUTTON);
4974 if ( j != Joymouse_button_status ) {
4975 //mprintf(( "Joy went from %d to %d, mouse is %d\n", Joymouse_button_status, j, m ));
4976 Joymouse_button_status = j;
4978 mouse_mark_button( MOUSE_LEFT_BUTTON, 1 );
4979 } else if ( (!j) && (m) ) {
4980 mouse_mark_button( MOUSE_LEFT_BUTTON, 0 );
4985 // if we should be ignoring keys because of some multiplayer situations
4986 if((Game_mode & GM_MULTIPLAYER) && multi_ignore_controls(k)){
4990 // If a popup is running, don't process all the Fn keys
4991 if( popup_active() ) {
4995 state = gameseq_get_state();
4997 // if ( k ) nprintf(( "General", "Key = %x\n", k ));
5000 case KEY_DEBUGGED + SDLK_BACKSPACE:
5005 launch_context_help();
5010 // if (state != GS_STATE_INITIAL_PLAYER_SELECT) {
5012 // don't allow f2 while warping out in multiplayer
5013 if((Game_mode & GM_MULTIPLAYER) && (Net_player != NULL) && (Net_player->flags & NETINFO_FLAG_WARPING_OUT)){
5018 case GS_STATE_INITIAL_PLAYER_SELECT:
5019 case GS_STATE_OPTIONS_MENU:
5020 case GS_STATE_HUD_CONFIG:
5021 case GS_STATE_CONTROL_CONFIG:
5022 case GS_STATE_DEATH_DIED:
5023 case GS_STATE_DEATH_BLEW_UP:
5024 case GS_STATE_VIEW_MEDALS:
5028 gameseq_post_event(GS_EVENT_OPTIONS_MENU);
5035 // hotkey selection screen -- only valid from briefing and beyond.
5037 #if !(defined(FS2_DEMO) || defined(FS1_DEMO))
5038 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) ) {
5039 gameseq_post_event( GS_EVENT_HOTKEY_SCREEN );
5045 case KEY_DEBUGGED + SDLK_F3:
5046 gameseq_post_event( GS_EVENT_TOGGLE_FULLSCREEN );
5049 case KEY_DEBUGGED + SDLK_F4:
5050 gameseq_post_event( GS_EVENT_TOGGLE_GLIDE );
5054 if(Game_mode & GM_MULTIPLAYER){
5055 if((state == GS_STATE_GAME_PLAY) || (state == GS_STATE_MULTI_PAUSED)){
5056 gameseq_post_event( GS_EVENT_MISSION_LOG_SCROLLBACK );
5060 if ((state == GS_STATE_GAME_PLAY) || (state == GS_STATE_DEATH_DIED) || (state == GS_STATE_DEATH_BLEW_UP) || (state == GS_STATE_GAME_PAUSED) ) {
5061 gameseq_post_event( GS_EVENT_MISSION_LOG_SCROLLBACK );
5067 case SDLK_ESCAPE | KEY_SHIFTED:
5068 // make sure to quit properly out of multiplayer
5069 if(Game_mode & GM_MULTIPLAYER){
5070 multi_quit_game(PROMPT_NONE);
5073 gameseq_post_event( GS_EVENT_QUIT_GAME );
5078 case KEY_DEBUGGED + SDLK_p:
5081 case SDLK_PRINTSCREEN:
5083 static int counter = 0;
5088 sprintf( tmp_name, NOX("screen%02d"), counter );
5090 mprintf(( "Dumping screen to '%s'\n", tmp_name ));
5091 gr_print_screen(tmp_name);
5099 case KEY_SHIFTED | SDLK_RETURN: {
5101 #if !defined(NDEBUG)
5103 if ( Game_mode & GM_NORMAL ){
5107 // if we're in multiplayer mode, do some special networking
5108 if(Game_mode & GM_MULTIPLAYER){
5109 debug_console(game_do_dc_networking);
5116 if ( Game_mode & GM_NORMAL )
5130 gameseq_post_event(GS_EVENT_QUIT_GAME);
5133 void apply_physics( float damping, float desired_vel, float initial_vel, float t, float * new_vel, float * delta_pos );
5136 void camera_set_position( vector *pos )
5141 void camera_set_orient( matrix *orient )
5143 Camera_orient = *orient;
5146 void camera_set_velocity( vector *vel, int instantaneous )
5148 Camera_desired_velocity.xyz.x = 0.0f;
5149 Camera_desired_velocity.xyz.y = 0.0f;
5150 Camera_desired_velocity.xyz.z = 0.0f;
5152 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.rvec, vel->xyz.x );
5153 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.uvec, vel->xyz.y );
5154 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.fvec, vel->xyz.z );
5156 if ( instantaneous ) {
5157 Camera_velocity = Camera_desired_velocity;
5165 vector new_vel, delta_pos;
5167 apply_physics( Camera_damping, Camera_desired_velocity.xyz.x, Camera_velocity.xyz.x, flFrametime, &new_vel.xyz.x, &delta_pos.xyz.x );
5168 apply_physics( Camera_damping, Camera_desired_velocity.xyz.y, Camera_velocity.xyz.y, flFrametime, &new_vel.xyz.y, &delta_pos.xyz.y );
5169 apply_physics( Camera_damping, Camera_desired_velocity.xyz.z, Camera_velocity.xyz.z, flFrametime, &new_vel.xyz.z, &delta_pos.xyz.z );
5171 Camera_velocity = new_vel;
5173 // mprintf(( "Camera velocity = %.1f,%.1f, %.1f\n", Camera_velocity.xyz.x, Camera_velocity.xyz.y, Camera_velocity.xyz.z ));
5175 vm_vec_add2( &Camera_pos, &delta_pos );
5177 float ot = Camera_time+0.0f;
5179 Camera_time += flFrametime;
5181 if ( (ot < 0.667f) && ( Camera_time >= 0.667f ) ) {
5184 tmp.xyz.z = 4.739f; // always go this fast forward.
5186 // pick x and y velocities so they are always on a
5187 // circle with a 25 m radius.
5189 float tmp_angle = frand()*PI2;
5191 tmp.xyz.x = 22.0f * (float)sin(tmp_angle);
5192 tmp.xyz.y = -22.0f * (float)cos(tmp_angle);
5194 //mprintf(( "Angle = %.1f, vx=%.1f, vy=%.1f\n", tmp_angle, tmp.xyz.x, tmp.xyz.y ));
5196 //mprintf(( "Changing velocity!\n" ));
5197 camera_set_velocity( &tmp, 0 );
5200 if ( (ot < 3.0f ) && ( Camera_time >= 3.0f ) ) {
5201 vector tmp = ZERO_VECTOR;
5202 camera_set_velocity( &tmp, 0 );
5207 void end_demo_campaign_do()
5209 #if defined(FS2_DEMO) || defined(FS1_DEMO)
5210 // show upsell screens
5211 demo_upsell_show_screens();
5212 #elif defined(OEM_BUILD)
5213 // show oem upsell screens
5214 oem_upsell_show_screens();
5217 // drop into main hall
5218 gameseq_post_event( GS_EVENT_MAIN_MENU );
5221 // All code to process events. This is the only place
5222 // that you should change the state of the game.
5223 void game_process_event( int current_state, int event )
5225 mprintf(("Got event %s in state %s\n", GS_event_text[event], GS_state_text[current_state]));
5228 case GS_EVENT_SIMULATOR_ROOM:
5229 gameseq_set_state(GS_STATE_SIMULATOR_ROOM);
5232 case GS_EVENT_MAIN_MENU:
5233 gameseq_set_state(GS_STATE_MAIN_MENU);
5236 case GS_EVENT_OPTIONS_MENU:
5237 gameseq_push_state( GS_STATE_OPTIONS_MENU );
5240 case GS_EVENT_BARRACKS_MENU:
5241 gameseq_set_state(GS_STATE_BARRACKS_MENU);
5244 case GS_EVENT_TECH_MENU:
5245 gameseq_set_state(GS_STATE_TECH_MENU);
5248 case GS_EVENT_TRAINING_MENU:
5249 gameseq_set_state(GS_STATE_TRAINING_MENU);
5252 case GS_EVENT_START_GAME:
5253 Select_default_ship = 0;
5254 Player_multi_died_check = -1;
5255 gameseq_set_state(GS_STATE_CMD_BRIEF);
5258 case GS_EVENT_START_BRIEFING:
5259 gameseq_set_state(GS_STATE_BRIEFING);
5262 case GS_EVENT_DEBRIEF:
5263 // did we end the campaign in the main freespace 2 single player campaign?
5265 if(Campaign_ended_in_mission && (Game_mode & GM_CAMPAIGN_MODE) && !stricmp(Campaign.filename, "freespace")) {
5267 if(Campaign_ended_in_mission && (Game_mode & GM_CAMPAIGN_MODE) && !stricmp(Campaign.filename, "freespace2")) {
5269 gameseq_post_event(GS_EVENT_END_CAMPAIGN);
5271 gameseq_set_state(GS_STATE_DEBRIEF);
5274 Player_multi_died_check = -1;
5277 case GS_EVENT_SHIP_SELECTION:
5278 gameseq_set_state( GS_STATE_SHIP_SELECT );
5281 case GS_EVENT_WEAPON_SELECTION:
5282 gameseq_set_state( GS_STATE_WEAPON_SELECT );
5285 case GS_EVENT_ENTER_GAME:
5287 // maybe start recording a demo
5289 demo_start_record("test.fsd");
5293 if (Game_mode & GM_MULTIPLAYER) {
5294 // if we're respawning, make sure we change the view mode so that the hud shows up
5295 if (current_state == GS_STATE_DEATH_BLEW_UP) {
5299 gameseq_set_state(GS_STATE_GAME_PLAY);
5301 gameseq_set_state(GS_STATE_GAME_PLAY, 1);
5304 Player_multi_died_check = -1;
5306 // clear multiplayer button info
5307 extern button_info Multi_ship_status_bi;
5308 memset(&Multi_ship_status_bi, 0, sizeof(button_info));
5310 Start_time = f2fl(timer_get_approx_seconds());
5312 mprintf(("Entering game at time = %7.3f\n", Start_time));
5316 case GS_EVENT_START_GAME_QUICK:
5317 Select_default_ship = 1;
5318 gameseq_post_event(GS_EVENT_ENTER_GAME);
5322 case GS_EVENT_END_GAME:
5323 if ( (current_state == GS_STATE_GAME_PLAY) || (current_state == GS_STATE_DEATH_DIED) ||
5324 (current_state == GS_STATE_DEATH_BLEW_UP) || (current_state == GS_STATE_DEBRIEF) || (current_state == GS_STATE_MULTI_DOGFIGHT_DEBRIEF)) {
5325 gameseq_set_state(GS_STATE_MAIN_MENU);
5330 Player_multi_died_check = -1;
5333 case GS_EVENT_QUIT_GAME:
5334 main_hall_stop_music();
5335 main_hall_stop_ambient();
5336 gameseq_set_state(GS_STATE_QUIT_GAME);
5338 Player_multi_died_check = -1;
5341 case GS_EVENT_GAMEPLAY_HELP:
5342 gameseq_push_state( GS_STATE_GAMEPLAY_HELP );
5345 case GS_EVENT_PAUSE_GAME:
5346 gameseq_push_state(GS_STATE_GAME_PAUSED);
5349 case GS_EVENT_DEBUG_PAUSE_GAME:
5350 gameseq_push_state(GS_STATE_DEBUG_PAUSED);
5353 case GS_EVENT_TRAINING_PAUSE:
5354 gameseq_push_state(GS_STATE_TRAINING_PAUSED);
5357 case GS_EVENT_PREVIOUS_STATE:
5358 gameseq_pop_state();
5361 case GS_EVENT_TOGGLE_FULLSCREEN:
5362 #ifndef HARDWARE_ONLY
5364 if ( gr_screen.mode == GR_SOFTWARE ) {
5365 gr_init( GR_640, GR_DIRECTDRAW );
5366 } else if ( gr_screen.mode == GR_DIRECTDRAW ) {
5367 gr_init( GR_640, GR_SOFTWARE );
5373 case GS_EVENT_TOGGLE_GLIDE:
5375 if ( gr_screen.mode != GR_GLIDE ) {
5376 gr_init( GR_640, GR_GLIDE );
5378 gr_init( GR_640, GR_SOFTWARE );
5383 case GS_EVENT_LOAD_MISSION_MENU:
5384 gameseq_set_state(GS_STATE_LOAD_MISSION_MENU);
5387 case GS_EVENT_MISSION_LOG_SCROLLBACK:
5388 gameseq_push_state( GS_STATE_MISSION_LOG_SCROLLBACK );
5391 case GS_EVENT_HUD_CONFIG:
5392 gameseq_push_state( GS_STATE_HUD_CONFIG );
5395 case GS_EVENT_CONTROL_CONFIG:
5396 gameseq_push_state( GS_STATE_CONTROL_CONFIG );
5399 case GS_EVENT_DEATH_DIED:
5400 gameseq_set_state( GS_STATE_DEATH_DIED );
5403 case GS_EVENT_DEATH_BLEW_UP:
5404 if ( current_state == GS_STATE_DEATH_DIED ) {
5405 gameseq_set_state( GS_STATE_DEATH_BLEW_UP );
5406 event_music_player_death();
5408 // multiplayer clients set their extra check here
5409 if(Game_mode & GM_MULTIPLAYER){
5410 // set the multi died absolute last chance check
5411 Player_multi_died_check = time(NULL);
5414 mprintf(( "Ignoring GS_EVENT_DEATH_BLEW_UP because we're in state %d\n", current_state ));
5418 case GS_EVENT_NEW_CAMPAIGN:
5419 if (!mission_load_up_campaign()){
5420 readyroom_continue_campaign();
5423 Player_multi_died_check = -1;
5426 case GS_EVENT_CAMPAIGN_CHEAT:
5427 if (!mission_load_up_campaign()){
5429 // bash campaign value
5430 extern char Main_hall_campaign_cheat[512];
5433 // look for the mission
5434 for(idx=0; idx<Campaign.num_missions; idx++){
5435 if(!stricmp(Campaign.missions[idx].name, Main_hall_campaign_cheat)){
5436 Campaign.next_mission = idx;
5437 Campaign.prev_mission = idx - 1;
5444 readyroom_continue_campaign();
5447 Player_multi_died_check = -1;
5450 case GS_EVENT_CAMPAIGN_ROOM:
5451 gameseq_set_state(GS_STATE_CAMPAIGN_ROOM);
5454 case GS_EVENT_CMD_BRIEF:
5455 gameseq_set_state(GS_STATE_CMD_BRIEF);
5458 case GS_EVENT_RED_ALERT:
5459 gameseq_set_state(GS_STATE_RED_ALERT);
5462 case GS_EVENT_CREDITS:
5463 gameseq_set_state( GS_STATE_CREDITS );
5466 case GS_EVENT_VIEW_MEDALS:
5467 gameseq_push_state( GS_STATE_VIEW_MEDALS );
5470 case GS_EVENT_SHOW_GOALS:
5471 gameseq_push_state( GS_STATE_SHOW_GOALS ); // use push_state() since we might get to this screen through a variety of states
5474 case GS_EVENT_HOTKEY_SCREEN:
5475 gameseq_push_state( GS_STATE_HOTKEY_SCREEN ); // use push_state() since we might get to this screen through a variety of states
5478 // multiplayer stuff follow these comments
5480 case GS_EVENT_MULTI_JOIN_GAME:
5481 gameseq_set_state( GS_STATE_MULTI_JOIN_GAME );
5484 case GS_EVENT_MULTI_HOST_SETUP:
5485 gameseq_set_state( GS_STATE_MULTI_HOST_SETUP );
5488 case GS_EVENT_MULTI_CLIENT_SETUP:
5489 gameseq_set_state( GS_STATE_MULTI_CLIENT_SETUP );
5492 case GS_EVENT_GOTO_VIEW_CUTSCENES_SCREEN:
5493 gameseq_set_state(GS_STATE_VIEW_CUTSCENES);
5496 case GS_EVENT_MULTI_STD_WAIT:
5497 gameseq_set_state( GS_STATE_MULTI_STD_WAIT );
5500 case GS_EVENT_STANDALONE_MAIN:
5501 gameseq_set_state( GS_STATE_STANDALONE_MAIN );
5504 case GS_EVENT_MULTI_PAUSE:
5505 gameseq_push_state( GS_STATE_MULTI_PAUSED );
5508 case GS_EVENT_INGAME_PRE_JOIN:
5509 gameseq_set_state( GS_STATE_INGAME_PRE_JOIN );
5512 case GS_EVENT_EVENT_DEBUG:
5513 gameseq_push_state(GS_STATE_EVENT_DEBUG);
5516 // Start a warpout where player automatically goes 70 no matter what
5517 // and can't cancel out of it.
5518 case GS_EVENT_PLAYER_WARPOUT_START_FORCED:
5519 Warpout_forced = 1; // If non-zero, bash the player to speed and go through effect
5521 // Same code as in GS_EVENT_PLAYER_WARPOUT_START only ignores current mode
5522 Player->saved_viewer_mode = Viewer_mode;
5523 Player->control_mode = PCM_WARPOUT_STAGE1;
5524 Warpout_sound = snd_play(&Snds[SND_PLAYER_WARP_OUT]);
5525 Warpout_time = 0.0f; // Start timer!
5528 case GS_EVENT_PLAYER_WARPOUT_START:
5529 if ( Player->control_mode != PCM_NORMAL ) {
5530 mprintf(( "Player isn't in normal mode; cannot warp out.\n" ));
5532 Player->saved_viewer_mode = Viewer_mode;
5533 Player->control_mode = PCM_WARPOUT_STAGE1;
5534 Warpout_sound = snd_play(&Snds[SND_PLAYER_WARP_OUT]);
5535 Warpout_time = 0.0f; // Start timer!
5536 Warpout_forced = 0; // If non-zero, bash the player to speed and go through effect
5540 case GS_EVENT_PLAYER_WARPOUT_STOP:
5541 if ( Player->control_mode != PCM_NORMAL ) {
5542 if ( !Warpout_forced ) { // cannot cancel forced warpout
5543 Player->control_mode = PCM_NORMAL;
5544 Viewer_mode = Player->saved_viewer_mode;
5545 hud_subspace_notify_abort();
5546 mprintf(( "Player put back to normal mode.\n" ));
5547 if ( Warpout_sound > -1 ) {
5548 snd_stop( Warpout_sound );
5555 case GS_EVENT_PLAYER_WARPOUT_DONE_STAGE1: // player ship got up to speed
5556 if ( Player->control_mode != PCM_WARPOUT_STAGE1 ) {
5557 gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_STOP );
5558 mprintf(( "Player put back to normal mode, because of invalid sequence in stage1.\n" ));
5560 mprintf(( "Hit target speed. Starting warp effect and moving to stage 2!\n" ));
5561 shipfx_warpout_start( Player_obj );
5562 Player->control_mode = PCM_WARPOUT_STAGE2;
5563 Player->saved_viewer_mode = Viewer_mode;
5564 Viewer_mode |= VM_WARP_CHASE;
5566 vector tmp = Player_obj->pos;
5568 ship_get_eye( &tmp, &tmp_m, Player_obj );
5569 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.rvec, 0.0f );
5570 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.uvec, 0.952f );
5571 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.fvec, -1.782f );
5573 camera_set_position( &tmp );
5574 camera_set_orient( &Player_obj->orient );
5575 vector tmp_vel = { { { 0.0f, 5.1919f, 14.7f } } };
5577 //mprintf(( "Rad = %.1f\n", Player_obj->radius ));
5578 camera_set_velocity( &tmp_vel, 1);
5582 case GS_EVENT_PLAYER_WARPOUT_DONE_STAGE2: // player ship got into the warp effect
5583 if ( Player->control_mode != PCM_WARPOUT_STAGE2 ) {
5584 gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_STOP );
5585 mprintf(( "Player put back to normal mode, because of invalid sequence in stage2.\n" ));
5587 mprintf(( "Hit warp effect. Moving to stage 3!\n" ));
5588 Player->control_mode = PCM_WARPOUT_STAGE3;
5592 case GS_EVENT_PLAYER_WARPOUT_DONE: // player ship got through the warp effect
5593 mprintf(( "Player warped out. Going to debriefing!\n" ));
5594 Player->control_mode = PCM_NORMAL;
5595 Viewer_mode = Player->saved_viewer_mode;
5598 // we have a special debriefing screen for multiplayer furballs
5599 if((Game_mode & GM_MULTIPLAYER) && (The_mission.game_type & MISSION_TYPE_MULTI_DOGFIGHT)){
5600 gameseq_post_event(GS_EVENT_MULTI_DOGFIGHT_DEBRIEF);
5602 // do the normal debriefing for all other situations
5604 gameseq_post_event(GS_EVENT_DEBRIEF);
5608 case GS_EVENT_STANDALONE_POSTGAME:
5609 gameseq_set_state(GS_STATE_STANDALONE_POSTGAME);
5612 case GS_EVENT_INITIAL_PLAYER_SELECT:
5613 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5616 case GS_EVENT_GAME_INIT:
5617 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
5618 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5620 // see if the command line option has been set to use the last pilot, and act acoordingly
5621 if( player_select_get_last_pilot() ) {
5622 // always enter the main menu -- do the automatic network startup stuff elsewhere
5623 // so that we still have valid checks for networking modes, etc.
5624 gameseq_set_state(GS_STATE_MAIN_MENU);
5626 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5631 case GS_EVENT_MULTI_MISSION_SYNC:
5632 gameseq_set_state(GS_STATE_MULTI_MISSION_SYNC);
5635 case GS_EVENT_MULTI_START_GAME:
5636 gameseq_set_state(GS_STATE_MULTI_START_GAME);
5639 case GS_EVENT_MULTI_HOST_OPTIONS:
5640 gameseq_set_state(GS_STATE_MULTI_HOST_OPTIONS);
5643 case GS_EVENT_MULTI_DOGFIGHT_DEBRIEF:
5644 gameseq_set_state(GS_STATE_MULTI_DOGFIGHT_DEBRIEF);
5647 case GS_EVENT_TEAM_SELECT:
5648 gameseq_set_state(GS_STATE_TEAM_SELECT);
5651 case GS_EVENT_END_CAMPAIGN:
5652 gameseq_set_state(GS_STATE_END_OF_CAMPAIGN);
5655 case GS_EVENT_END_DEMO:
5656 gameseq_set_state(GS_STATE_END_DEMO);
5659 case GS_EVENT_LOOP_BRIEF:
5660 gameseq_set_state(GS_STATE_LOOP_BRIEF);
5669 // Called when a state is being left.
5670 // The current state is still at old_state, but as soon as
5671 // this function leaves, then the current state will become
5672 // new state. You should never try to change the state
5673 // in here... if you think you need to, you probably really
5674 // need to post an event, not change the state.
5675 void game_leave_state( int old_state, int new_state )
5677 int end_mission = 1;
5679 switch (new_state) {
5680 case GS_STATE_GAME_PAUSED:
5681 case GS_STATE_DEBUG_PAUSED:
5682 case GS_STATE_OPTIONS_MENU:
5683 case GS_STATE_CONTROL_CONFIG:
5684 case GS_STATE_MISSION_LOG_SCROLLBACK:
5685 case GS_STATE_DEATH_DIED:
5686 case GS_STATE_SHOW_GOALS:
5687 case GS_STATE_HOTKEY_SCREEN:
5688 case GS_STATE_MULTI_PAUSED:
5689 case GS_STATE_TRAINING_PAUSED:
5690 case GS_STATE_EVENT_DEBUG:
5691 case GS_STATE_GAMEPLAY_HELP:
5692 end_mission = 0; // these events shouldn't end a mission
5696 switch (old_state) {
5697 case GS_STATE_BRIEFING:
5698 brief_stop_voices();
5699 if ( (new_state != GS_STATE_OPTIONS_MENU) && (new_state != GS_STATE_WEAPON_SELECT)
5700 && (new_state != GS_STATE_SHIP_SELECT) && (new_state != GS_STATE_HOTKEY_SCREEN)
5701 && (new_state != GS_STATE_TEAM_SELECT) ){
5702 common_select_close();
5703 if ( new_state == GS_STATE_MAIN_MENU ) {
5704 freespace_stop_mission();
5708 // COMMAND LINE OPTION
5709 if (Cmdline_multi_stream_chat_to_file){
5710 cfwrite_string(NOX("-------------------------------------------\n"),Multi_chat_stream);
5711 cfclose(Multi_chat_stream);
5715 case GS_STATE_DEBRIEF:
5716 if ( (new_state != GS_STATE_VIEW_MEDALS) && (new_state != GS_STATE_OPTIONS_MENU) ) {
5721 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
5722 multi_df_debrief_close();
5725 case GS_STATE_LOAD_MISSION_MENU:
5726 mission_load_menu_close();
5729 case GS_STATE_SIMULATOR_ROOM:
5733 case GS_STATE_CAMPAIGN_ROOM:
5734 campaign_room_close();
5737 case GS_STATE_CMD_BRIEF:
5738 if (new_state == GS_STATE_OPTIONS_MENU) {
5743 if (new_state == GS_STATE_MAIN_MENU)
5744 freespace_stop_mission();
5749 case GS_STATE_RED_ALERT:
5753 case GS_STATE_SHIP_SELECT:
5754 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_WEAPON_SELECT &&
5755 new_state != GS_STATE_HOTKEY_SCREEN &&
5756 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_TEAM_SELECT) {
5757 common_select_close();
5758 if ( new_state == GS_STATE_MAIN_MENU ) {
5759 freespace_stop_mission();
5764 case GS_STATE_WEAPON_SELECT:
5765 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_SHIP_SELECT &&
5766 new_state != GS_STATE_HOTKEY_SCREEN &&
5767 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_TEAM_SELECT) {
5768 common_select_close();
5769 if ( new_state == GS_STATE_MAIN_MENU ) {
5770 freespace_stop_mission();
5775 case GS_STATE_TEAM_SELECT:
5776 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_SHIP_SELECT &&
5777 new_state != GS_STATE_HOTKEY_SCREEN &&
5778 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_WEAPON_SELECT) {
5779 common_select_close();
5780 if ( new_state == GS_STATE_MAIN_MENU ) {
5781 freespace_stop_mission();
5786 case GS_STATE_MAIN_MENU:
5787 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
5794 case GS_STATE_OPTIONS_MENU:
5795 //game_start_time();
5796 if(new_state == GS_STATE_MULTI_JOIN_GAME){
5797 multi_join_clear_game_list();
5799 options_menu_close();
5802 case GS_STATE_BARRACKS_MENU:
5803 if(new_state != GS_STATE_VIEW_MEDALS){
5808 case GS_STATE_MISSION_LOG_SCROLLBACK:
5809 hud_scrollback_close();
5812 case GS_STATE_TRAINING_MENU:
5813 training_menu_close();
5816 case GS_STATE_GAME_PLAY:
5817 if ( !(Game_mode & GM_STANDALONE_SERVER) ) {
5818 player_save_target_and_weapon_link_prefs();
5819 game_stop_looped_sounds();
5822 sound_env_disable();
5823 joy_ff_stop_effects();
5825 // stop game time under certain conditions
5826 if ( end_mission || (Game_mode & GM_NORMAL) || ((Game_mode & GM_MULTIPLAYER) && (new_state == GS_STATE_MULTI_PAUSED)) ){
5831 // shut down any recording or playing demos
5836 // when in multiplayer and going back to the main menu, send a leave game packet
5837 // right away (before calling stop mission). stop_mission was taking to long to
5838 // close mission down and I want people to get notified ASAP.
5839 if ( (Game_mode & GM_MULTIPLAYER) && (new_state == GS_STATE_MAIN_MENU) ){
5840 multi_quit_game(PROMPT_NONE);
5843 freespace_stop_mission();
5844 Game_time_compression = F1_0;
5848 case GS_STATE_TECH_MENU:
5852 case GS_STATE_TRAINING_PAUSED:
5853 Training_num_lines = 0;
5854 // fall through to GS_STATE_GAME_PAUSED
5856 case GS_STATE_GAME_PAUSED:
5858 if ( end_mission ) {
5863 case GS_STATE_DEBUG_PAUSED:
5866 pause_debug_close();
5870 case GS_STATE_HUD_CONFIG:
5874 // join/start a game
5875 case GS_STATE_MULTI_JOIN_GAME:
5876 if(new_state != GS_STATE_OPTIONS_MENU){
5877 multi_join_game_close();
5881 case GS_STATE_MULTI_HOST_SETUP:
5882 case GS_STATE_MULTI_CLIENT_SETUP:
5883 // if this is just the host going into the options screen, don't do anything
5884 if((new_state == GS_STATE_MULTI_HOST_OPTIONS) || (new_state == GS_STATE_OPTIONS_MENU)){
5888 // close down the proper state
5889 if(old_state == GS_STATE_MULTI_HOST_SETUP){
5890 multi_create_game_close();
5892 multi_game_client_setup_close();
5895 // COMMAND LINE OPTION
5896 if (Cmdline_multi_stream_chat_to_file){
5897 if( (new_state != GS_STATE_TEAM_SELECT) && (Multi_chat_stream!=NULL) ) {
5898 cfwrite_string(NOX("-------------------------------------------\n"),Multi_chat_stream);
5899 cfclose(Multi_chat_stream);
5904 case GS_STATE_CONTROL_CONFIG:
5905 control_config_close();
5908 case GS_STATE_DEATH_DIED:
5909 Game_mode &= ~GM_DEAD_DIED;
5911 // early end while respawning or blowing up in a multiplayer game
5912 if((Game_mode & GM_MULTIPLAYER) && ((new_state == GS_STATE_DEBRIEF) || (new_state == GS_STATE_MULTI_DOGFIGHT_DEBRIEF)) ){
5914 freespace_stop_mission();
5918 case GS_STATE_DEATH_BLEW_UP:
5919 Game_mode &= ~GM_DEAD_BLEW_UP;
5921 // for single player, we might reload mission, etc. For multiplayer, look at my new state
5922 // to determine if I should do anything.
5923 if ( !(Game_mode & GM_MULTIPLAYER) ) {
5925 freespace_stop_mission();
5928 // if we are not respawing as an observer or as a player, our new state will not
5929 // be gameplay state.
5930 if ( (new_state != GS_STATE_GAME_PLAY) && (new_state != GS_STATE_MULTI_PAUSED) ) {
5931 game_stop_time(); // hasn't been called yet!!
5932 freespace_stop_mission();
5938 case GS_STATE_CREDITS:
5942 case GS_STATE_VIEW_MEDALS:
5946 case GS_STATE_SHOW_GOALS:
5947 mission_show_goals_close();
5950 case GS_STATE_HOTKEY_SCREEN:
5951 if ( new_state != GS_STATE_OPTIONS_MENU ) {
5952 mission_hotkey_close();
5956 case GS_STATE_MULTI_MISSION_SYNC:
5957 // if we're moving into the options menu, don't do anything
5958 if(new_state == GS_STATE_OPTIONS_MENU){
5962 Assert( Game_mode & GM_MULTIPLAYER );
5964 if ( new_state == GS_STATE_GAME_PLAY ){
5965 // palette_restore_palette();
5967 // change a couple of flags to indicate our state!!!
5968 Net_player->state = NETPLAYER_STATE_IN_MISSION;
5969 send_netplayer_update_packet();
5971 // set the game mode
5972 Game_mode |= GM_IN_MISSION;
5976 case GS_STATE_VIEW_CUTSCENES:
5977 cutscenes_screen_close();
5980 case GS_STATE_MULTI_STD_WAIT:
5981 multi_standalone_wait_close();
5984 case GS_STATE_STANDALONE_MAIN:
5985 standalone_main_close();
5986 if(new_state == GS_STATE_MULTI_STD_WAIT){
5987 init_multiplayer_stats();
5991 case GS_STATE_MULTI_PAUSED:
5992 // if ( end_mission ){
5997 case GS_STATE_INGAME_PRE_JOIN:
5998 multi_ingame_select_close();
6001 case GS_STATE_STANDALONE_POSTGAME:
6002 multi_standalone_postgame_close();
6005 case GS_STATE_INITIAL_PLAYER_SELECT:
6006 player_select_close();
6009 case GS_STATE_MULTI_START_GAME:
6010 multi_start_game_close();
6013 case GS_STATE_MULTI_HOST_OPTIONS:
6014 multi_host_options_close();
6017 case GS_STATE_END_OF_CAMPAIGN:
6018 mission_campaign_end_close();
6021 case GS_STATE_LOOP_BRIEF:
6027 // Called when a state is being entered.
6028 // The current state is set to the state we're entering at
6029 // this point, and old_state is set to the state we're coming
6030 // from. You should never try to change the state
6031 // in here... if you think you need to, you probably really
6032 // need to post an event, not change the state.
6034 void game_enter_state( int old_state, int new_state )
6036 switch (new_state) {
6037 case GS_STATE_MAIN_MENU:
6038 // in multiplayer mode, be sure that we are not doing networking anymore.
6039 if ( Game_mode & GM_MULTIPLAYER ) {
6040 Assert( Net_player != NULL );
6041 Net_player->flags &= ~NETINFO_FLAG_DO_NETWORKING;
6044 Game_time_compression = F1_0;
6046 // determine which ship this guy is currently based on
6047 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
6050 if (Player->on_bastion) {
6058 case GS_STATE_BRIEFING:
6059 main_hall_stop_music();
6060 main_hall_stop_ambient();
6062 if (Game_mode & GM_NORMAL) {
6063 // AL: Don't call freespace_start_mission() if re-entering from ship or weapon select
6064 // MWA: or from options or hotkey screens
6065 // JH: or if the command brief state already did this
6066 if ( (old_state != GS_STATE_OPTIONS_MENU) && (old_state != GS_STATE_HOTKEY_SCREEN)
6067 && (old_state != GS_STATE_SHIP_SELECT) && (old_state != GS_STATE_WEAPON_SELECT)
6068 && (old_state != GS_STATE_CMD_BRIEF) ) {
6069 if ( !game_start_mission() ) // this should put us into a new state on failure!
6073 // maybe play a movie before the briefing. don't play if entering briefing screen from ship or weapon select.
6074 if ( (old_state == GS_STATE_DEBRIEF) || (old_state == GS_STATE_SIMULATOR_ROOM) || (old_state == GS_STATE_MAIN_MENU))
6075 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
6077 Game_time_compression = F1_0;
6079 if ( red_alert_mission() ) {
6080 gameseq_post_event(GS_EVENT_RED_ALERT);
6087 case GS_STATE_DEBRIEF:
6088 game_stop_looped_sounds();
6089 mission_goal_fail_incomplete(); // fail all incomplete goals before entering debriefing
6090 if ( (old_state != GS_STATE_VIEW_MEDALS) && (old_state != GS_STATE_OPTIONS_MENU) ){
6095 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
6096 multi_df_debrief_init();
6099 case GS_STATE_LOAD_MISSION_MENU:
6100 mission_load_menu_init();
6103 case GS_STATE_SIMULATOR_ROOM:
6107 case GS_STATE_CAMPAIGN_ROOM:
6108 campaign_room_init();
6111 case GS_STATE_RED_ALERT:
6112 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
6116 case GS_STATE_CMD_BRIEF: {
6117 int team_num = 0; // team number used as index for which cmd brief to use.
6119 if (old_state == GS_STATE_OPTIONS_MENU) {
6123 main_hall_stop_music();
6124 main_hall_stop_ambient();
6126 if (Game_mode & GM_NORMAL) {
6127 // AL: Don't call freespace_start_mission() if re-entering from ship or weapon select
6128 // MWA: or from options or hotkey screens
6129 // JH: or if the command brief state already did this
6130 if ( (old_state != GS_STATE_OPTIONS_MENU) && (old_state != GS_STATE_HOTKEY_SCREEN)
6131 && (old_state != GS_STATE_SHIP_SELECT) && (old_state != GS_STATE_WEAPON_SELECT) ) {
6132 if ( !game_start_mission() ) // this should put us into a new state on failure!
6137 // maybe play a movie before the briefing. don't play if entering briefing screen from ship or weapon select.
6138 if ( (old_state == GS_STATE_DEBRIEF) || (old_state == GS_STATE_SIMULATOR_ROOM) || (old_state == GS_STATE_MAIN_MENU))
6139 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
6141 cmd_brief_init(team_num);
6147 case GS_STATE_SHIP_SELECT:
6151 case GS_STATE_WEAPON_SELECT:
6152 weapon_select_init();
6155 case GS_STATE_TEAM_SELECT:
6159 case GS_STATE_GAME_PAUSED:
6164 case GS_STATE_DEBUG_PAUSED:
6165 // game_stop_time();
6166 // os_set_title("FreeSpace - PAUSED");
6169 case GS_STATE_TRAINING_PAUSED:
6176 case GS_STATE_OPTIONS_MENU:
6178 options_menu_init();
6181 case GS_STATE_GAME_PLAY:
6182 // coming from the gameplay state or the main menu, we might need to load the mission
6183 if ( (Game_mode & GM_NORMAL) && ((old_state == GS_STATE_MAIN_MENU) || (old_state == GS_STATE_GAME_PLAY) || (old_state == GS_STATE_DEATH_BLEW_UP)) ) {
6184 if ( !game_start_mission() ) // this should put us into a new state.
6189 // if we are coming from the briefing, ship select, weapons loadout, or main menu (in the
6190 // case of quick start), then do bitmap loads, etc Don't do any of the loading stuff
6191 // if we are in multiplayer -- this stuff is all handled in the multi-wait section
6192 if ( !(Game_mode & GM_MULTIPLAYER) && ((old_state == GS_STATE_BRIEFING) || (old_state == GS_STATE_SHIP_SELECT) ||
6193 (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)) ) {
6194 // JAS: Used to do all paging here.
6198 HUD_printf("Skill level is set to ** %s **", Skill_level_names(Game_skill_level));
6202 main_hall_stop_music();
6203 main_hall_stop_ambient();
6204 event_music_first_pattern(); // start the first pattern
6207 // special code that restores player ship selection and weapons loadout when doing a quick start
6208 if ( !(Game_mode & GM_MULTIPLAYER) && ((old_state == GS_STATE_MAIN_MENU) || (old_state == GS_STATE_DEATH_BLEW_UP) || (old_state == GS_STATE_GAME_PLAY)) ) {
6209 if ( !stricmp(Player_loadout.filename, Game_current_mission_filename) ) {
6210 wss_direct_restore_loadout();
6214 // single-player, quick-start after just died... we need to set weapon linking and kick off the event music
6215 if (!(Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_DEATH_BLEW_UP) ) {
6216 event_music_first_pattern(); // start the first pattern
6219 if ( !(Game_mode & GM_STANDALONE_SERVER) && (old_state != GS_STATE_GAME_PAUSED) && (old_state != GS_STATE_MULTI_PAUSED) ) {
6220 event_music_first_pattern(); // start the first pattern
6222 player_restore_target_and_weapon_link_prefs();
6224 Game_mode |= GM_IN_MISSION;
6227 // required to truely make mouse deltas zeroed in debug mouse code
6228 void mouse_force_pos(int x, int y);
6229 if (!Is_standalone) {
6230 mouse_force_pos(gr_screen.max_w / 2, gr_screen.max_h / 2);
6236 // only start time if in single player, or coming from multi wait state
6239 (Game_mode & GM_NORMAL) &&
6240 (old_state != GS_STATE_VIEW_CUTSCENES)
6242 (Game_mode & GM_MULTIPLAYER) && (
6243 (old_state == GS_STATE_MULTI_PAUSED) ||
6244 (old_state == GS_STATE_MULTI_MISSION_SYNC)
6250 // when coming from the multi paused state, reset the timestamps
6251 if ( (Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_MULTI_PAUSED) ){
6252 multi_reset_timestamps();
6255 if ((Game_mode & GM_MULTIPLAYER) && (old_state != GS_STATE_DEATH_BLEW_UP) ) {
6256 // initialize all object update details
6257 multi_oo_gameplay_init();
6260 // under certain circumstances, the server should reset the object update rate limiting stuff
6261 if( ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)) &&
6262 ((old_state == GS_STATE_MULTI_PAUSED) || (old_state == GS_STATE_MULTI_MISSION_SYNC)) ){
6264 // reinitialize the rate limiting system for all clients
6265 multi_oo_rate_init_all();
6268 // multiplayer clients should always re-initialize their control info rate limiting system
6269 if((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER)){
6270 multi_oo_rate_init_all();
6274 if(Game_mode & GM_MULTIPLAYER){
6275 multi_ping_reset_players();
6278 Game_subspace_effect = 0;
6279 if (The_mission.flags & MISSION_FLAG_SUBSPACE) {
6280 Game_subspace_effect = 1;
6281 if( !(Game_mode & GM_STANDALONE_SERVER) ){
6282 game_start_subspace_ambient_sound();
6286 sound_env_set(&Game_sound_env);
6287 joy_ff_mission_init(Ship_info[Player_ship->ship_info_index].rotation_time);
6289 // clear multiplayer button info i
6290 extern button_info Multi_ship_status_bi;
6291 memset(&Multi_ship_status_bi, 0, sizeof(button_info));
6294 case GS_STATE_HUD_CONFIG:
6298 case GS_STATE_MULTI_JOIN_GAME:
6299 multi_join_clear_game_list();
6301 if (old_state != GS_STATE_OPTIONS_MENU) {
6302 multi_join_game_init();
6307 case GS_STATE_MULTI_HOST_SETUP:
6308 // don't reinitialize if we're coming back from the host options screen
6309 if ((old_state != GS_STATE_MULTI_HOST_OPTIONS) && (old_state != GS_STATE_OPTIONS_MENU)) {
6310 multi_create_game_init();
6315 case GS_STATE_MULTI_CLIENT_SETUP:
6316 if (old_state != GS_STATE_OPTIONS_MENU) {
6317 multi_game_client_setup_init();
6322 case GS_STATE_CONTROL_CONFIG:
6323 control_config_init();
6326 case GS_STATE_TECH_MENU:
6330 case GS_STATE_BARRACKS_MENU:
6331 if(old_state != GS_STATE_VIEW_MEDALS){
6336 case GS_STATE_MISSION_LOG_SCROLLBACK:
6337 hud_scrollback_init();
6340 case GS_STATE_DEATH_DIED:
6341 Player_died_time = timestamp(10);
6343 if(!(Game_mode & GM_MULTIPLAYER)){
6344 player_show_death_message();
6346 Game_mode |= GM_DEAD_DIED;
6349 case GS_STATE_DEATH_BLEW_UP:
6350 if ( !popupdead_is_active() ) {
6351 Player_ai->target_objnum = -1;
6354 // stop any local EMP effect
6357 Players[Player_num].flags &= ~PLAYER_FLAGS_AUTO_TARGETING; // Prevent immediate switch to a hostile ship.
6358 Game_mode |= GM_DEAD_BLEW_UP;
6359 Show_viewing_from_self = 0;
6361 // timestamp how long we should wait before displaying the died popup
6362 if ( !popupdead_is_active() ) {
6363 Player_died_popup_wait = timestamp(PLAYER_DIED_POPUP_WAIT);
6367 case GS_STATE_GAMEPLAY_HELP:
6368 gameplay_help_init();
6371 case GS_STATE_CREDITS:
6372 main_hall_stop_music();
6373 main_hall_stop_ambient();
6377 case GS_STATE_VIEW_MEDALS:
6378 medal_main_init(Player);
6381 case GS_STATE_SHOW_GOALS:
6382 mission_show_goals_init();
6385 case GS_STATE_HOTKEY_SCREEN:
6386 mission_hotkey_init();
6389 case GS_STATE_MULTI_MISSION_SYNC:
6390 // if we're coming from the options screen, don't do any
6391 if(old_state == GS_STATE_OPTIONS_MENU){
6395 switch(Multi_sync_mode){
6396 case MULTI_SYNC_PRE_BRIEFING:
6397 // if moving from game forming to the team select state
6400 case MULTI_SYNC_POST_BRIEFING:
6401 // if moving from briefing into the mission itself
6404 // tell everyone that we're now loading data
6405 Net_player->state = NETPLAYER_STATE_DATA_LOAD;
6406 send_netplayer_update_packet();
6408 // JAS: Used to do all paging here!!!!
6410 Net_player->state = NETPLAYER_STATE_WAITING;
6411 send_netplayer_update_packet();
6413 Game_time_compression = F1_0;
6415 case MULTI_SYNC_INGAME:
6421 case GS_STATE_VIEW_CUTSCENES:
6422 cutscenes_screen_init();
6425 case GS_STATE_MULTI_STD_WAIT:
6426 multi_standalone_wait_init();
6429 case GS_STATE_STANDALONE_MAIN:
6430 // don't initialize if we're coming from one of these 2 states unless there are no
6431 // players left (reset situation)
6432 if((old_state != GS_STATE_STANDALONE_POSTGAME) || multi_endgame_ending()){
6433 standalone_main_init();
6437 case GS_STATE_MULTI_PAUSED:
6441 case GS_STATE_INGAME_PRE_JOIN:
6442 multi_ingame_select_init();
6445 case GS_STATE_STANDALONE_POSTGAME:
6446 multi_standalone_postgame_init();
6449 case GS_STATE_INITIAL_PLAYER_SELECT:
6450 player_select_init();
6453 case GS_STATE_MULTI_START_GAME:
6454 multi_start_game_init();
6457 case GS_STATE_MULTI_HOST_OPTIONS:
6458 multi_host_options_init();
6461 case GS_STATE_END_OF_CAMPAIGN:
6462 mission_campaign_end_init();
6465 case GS_STATE_LOOP_BRIEF:
6472 // do stuff that may need to be done regardless of state
6473 void game_do_state_common(int state,int no_networking)
6475 game_maybe_draw_mouse(flFrametime); // determine if to draw the mouse this frame
6476 snd_do_frame(); // update sound system
6477 event_music_do_frame(); // music needs to play across many states
6479 multi_log_process();
6481 if (no_networking) {
6485 // maybe do a multiplayer frame based on game mode and state type
6486 if (Game_mode & GM_MULTIPLAYER) {
6488 case GS_STATE_OPTIONS_MENU:
6489 case GS_STATE_GAMEPLAY_HELP:
6490 case GS_STATE_HOTKEY_SCREEN:
6491 case GS_STATE_HUD_CONFIG:
6492 case GS_STATE_CONTROL_CONFIG:
6493 case GS_STATE_MISSION_LOG_SCROLLBACK:
6494 case GS_STATE_SHOW_GOALS:
6495 case GS_STATE_VIEW_CUTSCENES:
6496 case GS_STATE_EVENT_DEBUG:
6497 multi_maybe_do_frame();
6501 game_do_networking();
6505 // Called once a frame.
6506 // You should never try to change the state
6507 // in here... if you think you need to, you probably really
6508 // need to post an event, not change the state.
6509 int Game_do_state_should_skip = 0;
6510 void game_do_state(int state)
6512 // always lets the do_state_common() function determine if the state should be skipped
6513 Game_do_state_should_skip = 0;
6515 // legal to set the should skip state anywhere in this function
6516 game_do_state_common(state); // do stuff that may need to be done regardless of state
6518 if(Game_do_state_should_skip){
6523 case GS_STATE_MAIN_MENU:
6524 game_set_frametime(GS_STATE_MAIN_MENU);
6525 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
6528 main_hall_do(flFrametime);
6532 case GS_STATE_OPTIONS_MENU:
6533 game_set_frametime(GS_STATE_OPTIONS_MENU);
6534 options_menu_do_frame(flFrametime);
6537 case GS_STATE_BARRACKS_MENU:
6538 game_set_frametime(GS_STATE_BARRACKS_MENU);
6539 barracks_do_frame(flFrametime);
6542 case GS_STATE_TRAINING_MENU:
6543 game_set_frametime(GS_STATE_TRAINING_MENU);
6544 training_menu_do_frame(flFrametime);
6547 case GS_STATE_TECH_MENU:
6548 game_set_frametime(GS_STATE_TECH_MENU);
6549 techroom_do_frame(flFrametime);
6552 case GS_STATE_GAMEPLAY_HELP:
6553 game_set_frametime(GS_STATE_GAMEPLAY_HELP);
6554 gameplay_help_do_frame(flFrametime);
6557 case GS_STATE_GAME_PLAY: // do stuff that should be done during gameplay
6561 case GS_STATE_GAME_PAUSED:
6565 case GS_STATE_DEBUG_PAUSED:
6567 game_set_frametime(GS_STATE_DEBUG_PAUSED);
6572 case GS_STATE_TRAINING_PAUSED:
6573 game_training_pause_do();
6576 case GS_STATE_LOAD_MISSION_MENU:
6577 game_set_frametime(GS_STATE_LOAD_MISSION_MENU);
6578 mission_load_menu_do();
6581 case GS_STATE_BRIEFING:
6582 game_set_frametime(GS_STATE_BRIEFING);
6583 brief_do_frame(flFrametime);
6586 case GS_STATE_DEBRIEF:
6587 game_set_frametime(GS_STATE_DEBRIEF);
6588 debrief_do_frame(flFrametime);
6591 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
6592 game_set_frametime(GS_STATE_MULTI_DOGFIGHT_DEBRIEF);
6593 multi_df_debrief_do();
6596 case GS_STATE_SHIP_SELECT:
6597 game_set_frametime(GS_STATE_SHIP_SELECT);
6598 ship_select_do(flFrametime);
6601 case GS_STATE_WEAPON_SELECT:
6602 game_set_frametime(GS_STATE_WEAPON_SELECT);
6603 weapon_select_do(flFrametime);
6606 case GS_STATE_MISSION_LOG_SCROLLBACK:
6607 game_set_frametime(GS_STATE_MISSION_LOG_SCROLLBACK);
6608 hud_scrollback_do_frame(flFrametime);
6611 case GS_STATE_HUD_CONFIG:
6612 game_set_frametime(GS_STATE_HUD_CONFIG);
6613 hud_config_do_frame(flFrametime);
6616 case GS_STATE_MULTI_JOIN_GAME:
6617 game_set_frametime(GS_STATE_MULTI_JOIN_GAME);
6618 multi_join_game_do_frame();
6621 case GS_STATE_MULTI_HOST_SETUP:
6622 game_set_frametime(GS_STATE_MULTI_HOST_SETUP);
6623 multi_create_game_do();
6626 case GS_STATE_MULTI_CLIENT_SETUP:
6627 game_set_frametime(GS_STATE_MULTI_CLIENT_SETUP);
6628 multi_game_client_setup_do_frame();
6631 case GS_STATE_CONTROL_CONFIG:
6632 game_set_frametime(GS_STATE_CONTROL_CONFIG);
6633 control_config_do_frame(flFrametime);
6636 case GS_STATE_DEATH_DIED:
6640 case GS_STATE_DEATH_BLEW_UP:
6644 case GS_STATE_SIMULATOR_ROOM:
6645 game_set_frametime(GS_STATE_SIMULATOR_ROOM);
6646 sim_room_do_frame(flFrametime);
6649 case GS_STATE_CAMPAIGN_ROOM:
6650 game_set_frametime(GS_STATE_CAMPAIGN_ROOM);
6651 campaign_room_do_frame(flFrametime);
6654 case GS_STATE_RED_ALERT:
6655 game_set_frametime(GS_STATE_RED_ALERT);
6656 red_alert_do_frame(flFrametime);
6659 case GS_STATE_CMD_BRIEF:
6660 game_set_frametime(GS_STATE_CMD_BRIEF);
6661 cmd_brief_do_frame(flFrametime);
6664 case GS_STATE_CREDITS:
6665 game_set_frametime(GS_STATE_CREDITS);
6666 credits_do_frame(flFrametime);
6669 case GS_STATE_VIEW_MEDALS:
6670 game_set_frametime(GS_STATE_VIEW_MEDALS);
6674 case GS_STATE_SHOW_GOALS:
6675 game_set_frametime(GS_STATE_SHOW_GOALS);
6676 mission_show_goals_do_frame(flFrametime);
6679 case GS_STATE_HOTKEY_SCREEN:
6680 game_set_frametime(GS_STATE_HOTKEY_SCREEN);
6681 mission_hotkey_do_frame(flFrametime);
6684 case GS_STATE_VIEW_CUTSCENES:
6685 game_set_frametime(GS_STATE_VIEW_CUTSCENES);
6686 cutscenes_screen_do_frame();
6689 case GS_STATE_MULTI_STD_WAIT:
6690 game_set_frametime(GS_STATE_STANDALONE_MAIN);
6691 multi_standalone_wait_do();
6694 case GS_STATE_STANDALONE_MAIN:
6695 game_set_frametime(GS_STATE_STANDALONE_MAIN);
6696 standalone_main_do();
6699 case GS_STATE_MULTI_PAUSED:
6700 game_set_frametime(GS_STATE_MULTI_PAUSED);
6704 case GS_STATE_TEAM_SELECT:
6705 game_set_frametime(GS_STATE_TEAM_SELECT);
6709 case GS_STATE_INGAME_PRE_JOIN:
6710 game_set_frametime(GS_STATE_INGAME_PRE_JOIN);
6711 multi_ingame_select_do();
6714 case GS_STATE_EVENT_DEBUG:
6716 game_set_frametime(GS_STATE_EVENT_DEBUG);
6717 game_show_event_debug(flFrametime);
6721 case GS_STATE_STANDALONE_POSTGAME:
6722 game_set_frametime(GS_STATE_STANDALONE_POSTGAME);
6723 multi_standalone_postgame_do();
6726 case GS_STATE_INITIAL_PLAYER_SELECT:
6727 game_set_frametime(GS_STATE_INITIAL_PLAYER_SELECT);
6731 case GS_STATE_MULTI_MISSION_SYNC:
6732 game_set_frametime(GS_STATE_MULTI_MISSION_SYNC);
6736 case GS_STATE_MULTI_START_GAME:
6737 game_set_frametime(GS_STATE_MULTI_START_GAME);
6738 multi_start_game_do();
6741 case GS_STATE_MULTI_HOST_OPTIONS:
6742 game_set_frametime(GS_STATE_MULTI_HOST_OPTIONS);
6743 multi_host_options_do();
6746 case GS_STATE_END_OF_CAMPAIGN:
6747 mission_campaign_end_do();
6750 case GS_STATE_END_DEMO:
6751 game_set_frametime(GS_STATE_END_DEMO);
6752 end_demo_campaign_do();
6755 case GS_STATE_LOOP_BRIEF:
6756 game_set_frametime(GS_STATE_LOOP_BRIEF);
6760 } // end switch(gs_current_state)
6764 // return 0 if there is enough RAM to run FreeSpace, otherwise return -1
6765 int game_do_ram_check(int ram_in_mbytes)
6767 if ( ram_in_mbytes < 30 ) {
6768 int allowed_to_run = 1;
6769 if ( ram_in_mbytes < 25 ) {
6775 if ( allowed_to_run ) {
6776 SDL_MessageBoxData mboxd;
6777 SDL_MessageBoxButtonData mboxbuttons[2];
6780 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), ram_in_mbytes, ram_in_mbytes);
6782 mboxbuttons[0].buttonid = 0;
6783 mboxbuttons[0].text = XSTR("Ok", 503);
6784 mboxbuttons[0].flags = 0;
6786 mboxbuttons[1].buttonid = 1;
6787 mboxbuttons[1].text = XSTR("Cancel", 504);
6788 mboxbuttons[0].flags = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT | SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT;
6790 mboxd.flags = SDL_MESSAGEBOX_ERROR;
6791 mboxd.title = XSTR( "Not Enough RAM", 194);
6792 mboxd.message = tmp;
6793 mboxd.numbuttons = 2;
6794 mboxd.buttons = mboxbuttons;
6795 mboxd.window = NULL;
6796 mboxd.colorScheme = NULL;
6798 SDL_ShowMessageBox(&mboxd, &msgbox_rval);
6800 if ( msgbox_rval == 1 ) {
6804 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), ram_in_mbytes, ram_in_mbytes);
6806 SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, XSTR( "Not Enough RAM", 194), tmp, NULL);
6815 // Check if there is a freespace.exe in the /update directory (relative to where fs.exe is installed).
6816 // If so, copy it over and remove the update directory.
6817 void game_maybe_update_launcher(char *exe_dir)
6820 char src_filename[MAX_PATH];
6821 char dest_filename[MAX_PATH];
6823 strcpy(src_filename, exe_dir);
6824 strcat(src_filename, NOX("\\update\\freespace.exe"));
6826 strcpy(dest_filename, exe_dir);
6827 strcat(dest_filename, NOX("\\freespace.exe"));
6829 // see if src_filename exists
6831 fp = fopen(src_filename, "rb");
6837 SetFileAttributes(dest_filename, FILE_ATTRIBUTE_NORMAL);
6839 // copy updated freespace.exe to freespace exe dir
6840 if ( CopyFile(src_filename, dest_filename, 0) == 0 ) {
6841 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 );
6845 // delete the file in the update directory
6846 DeleteFile(src_filename);
6848 // safe to assume directory is empty, since freespace.exe should only be the file ever in the update dir
6849 char update_dir[MAX_PATH];
6850 strcpy(update_dir, exe_dir);
6851 strcat(update_dir, NOX("\\update"));
6852 RemoveDirectory(update_dir);
6858 void game_spew_pof_info_sub(int model_num, polymodel *pm, int sm, CFILE *out, int *out_total, int *out_destroyed_total)
6862 int sub_total_destroyed = 0;
6866 // get the total for all his children
6867 for (i=pm->submodel[sm].first_child; i>-1; i = pm->submodel[i].next_sibling ) {
6868 game_spew_pof_info_sub(model_num, pm, i, out, &sub_total, &sub_total_destroyed);
6871 // find the # of faces for this _individual_ object
6872 total = submodel_get_num_polys(model_num, sm);
6873 if(strstr(pm->submodel[sm].name, "-destroyed")){
6874 sub_total_destroyed = total;
6878 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[sm].name, total);
6881 *out_total += total + sub_total;
6882 *out_destroyed_total += sub_total_destroyed;
6885 #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);
6886 void game_spew_pof_info()
6888 char *pof_list[1000];
6891 int idx, model_num, i, j;
6893 int total, root_total, model_total, destroyed_total, counted;
6897 num_files = cf_get_file_list(1000, pof_list, CF_TYPE_MODELS, "*.pof");
6899 // spew info on all the pofs
6905 out = cfopen("pofspew.txt", "wt", CFILE_NORMAL, CF_TYPE_DATA);
6910 for(idx=0; idx<num_files; idx++, counted++){
6911 sprintf(str, "%s.pof", pof_list[idx]);
6912 model_num = model_load(str, 0, NULL);
6914 pm = model_get(model_num);
6916 // if we have a real model
6921 // go through and print all raw submodels
6922 cfputs("RAW\n", out);
6925 for (i=0; i<pm->n_models; i++) {
6926 total = submodel_get_num_polys(model_num, i);
6928 model_total += total;
6929 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[i].name, total);
6932 sprintf(str, "Model total %d\n", model_total);
6935 // now go through and do it by LOD
6936 cfputs("BY LOD\n\n", out);
6937 for(i=0; i<pm->n_detail_levels; i++){
6938 sprintf(str, "LOD %d\n", i);
6942 root_total = submodel_get_num_polys(model_num, pm->detail[i] );
6944 destroyed_total = 0;
6945 for (j=pm->submodel[pm->detail[i]].first_child; j>-1; j = pm->submodel[j].next_sibling ) {
6946 game_spew_pof_info_sub(model_num, pm, j, out, &total, &destroyed_total);
6949 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[pm->detail[i]].name, root_total);
6952 sprintf(str, "TOTAL: %d\n", total + root_total);
6954 sprintf(str, "TOTAL not counting destroyed faces %d\n", (total + root_total) - destroyed_total);
6956 sprintf(str, "TOTAL destroyed faces %d\n\n", destroyed_total);
6959 cfputs("------------------------------------------------------------------------\n\n", out);
6963 if(counted >= MAX_POLYGON_MODELS - 5){
6976 game_spew_pof_info();
6979 int game_main(const char *szCmdLine)
6984 // Don't let more than one instance of Freespace run.
6985 HWND hwnd = FindWindow( NOX( "FreeSpaceClass" ), NULL );
6987 SetForegroundWindow(hwnd);
6992 // Find out how much RAM is on this machine
6993 Freespace_total_ram = SDL_GetSystemRAM();
6995 if ( game_do_ram_check(Freespace_total_ram) == -1 ) {
6999 if (!vm_init(24*1024*1024)) {
7000 SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, XSTR( "Not Enough Memory", 199), XSTR( "Not enough memory to run Freespace.\r\nTry closing down some other applications.\r\n", 198), NULL);
7004 char *tmp_mem = (char *) malloc(16 * 1024 * 1024);
7006 SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, XSTR( "Not Enough Memory", 199), XSTR( "Not enough memory to run Freespace.\r\nTry closing down some other applications.\r\n", 198), NULL);
7013 /* this code doesn't work, and we will hit an error about being unable to load the direct draw
7014 dll before we get here anyway if it's not installed (unless we load it manually, which doesn't
7015 seem worth bothering with.
7019 lResult = RegOpenKeyEx(
7020 HKEY_LOCAL_MACHINE, // Where it is
7021 "Software\\Microsoft\\DirectX", // name of key
7022 NULL, // DWORD reserved
7023 KEY_QUERY_VALUE, // Allows all changes
7024 &hKey // Location to store key
7027 if (lResult == ERROR_SUCCESS) {
7029 DWORD dwType, dwLen;
7032 lResult = RegQueryValueEx(
7033 hKey, // Handle to key
7034 "Version", // The values name
7035 NULL, // DWORD reserved
7036 &dwType, // What kind it is
7037 (ubyte *) version, // value to set
7038 &dwLen // How many bytes to set
7041 if (lResult == ERROR_SUCCESS) {
7042 dx_version = atoi(strstr(version, ".") + 1);
7046 DWORD dwType, dwLen;
7049 lResult = RegQueryValueEx(
7050 hKey, // Handle to key
7051 "InstalledVersion", // The values name
7052 NULL, // DWORD reserved
7053 &dwType, // What kind it is
7054 (ubyte *) &val, // value to set
7055 &dwLen // How many bytes to set
7058 if (lResult == ERROR_SUCCESS) {
7066 if (dx_version < 3) {
7067 MessageBox(NULL, "DirectX 3.0 or higher is required and wasn't detected. You can get the\n"
7068 "latest version of DirectX at:\n\n"
7069 "http://www.microsoft.com/msdownload/directx/dxf/enduser5.0/default.htm", "DirectX required", MB_OK);
7071 MessageBox(NULL, "DirectX 3.0 or higher is required and wasn't detected. You can install\n"
7072 "DirectX 5.2 by pressing the 'Install DirectX' button on the FreeSpace Launcher", "DirectX required", MB_OK);
7080 extern void windebug_memwatch_init();
7081 windebug_memwatch_init();
7089 mprintf(("Total RAM: %dMB\n", Freespace_total_ram));
7090 mprintf(("Command line: %s\n", szCmdLine));
7091 mprintf(("Platform: %s\n", SDL_GetPlatform()));
7093 parse_cmdline(szCmdLine);
7095 #ifdef STANDALONE_ONLY_BUILD
7097 nprintf(("Network", "Standalone running"));
7100 nprintf(("Network", "Standalone running"));
7107 // maybe spew pof stuff
7108 if(Cmdline_spew_pof_info){
7109 game_spew_pof_info();
7114 // non-demo, non-standalone, play the intro movie
7116 if ( !Is_standalone ) {
7118 // release -- movies always play
7121 // 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
7122 movie_play( NOX("intro.mve"), 0 );
7124 // debug version, movie will only play with -showmovies
7125 #elif !defined(NDEBUG)
7127 movie_play( NOX("intro.mve"), 0);
7130 if ( Cmdline_show_movies )
7131 movie_play( NOX("intro.mve"), 0 );
7140 gameseq_post_event(GS_EVENT_STANDALONE_MAIN);
7142 gameseq_post_event(GS_EVENT_GAME_INIT); // start the game rolling -- check for default pilot, or go to the pilot select screen
7146 // only important for non THREADED mode
7149 state = gameseq_process_events();
7150 if ( state == GS_STATE_QUIT_GAME ){
7155 #if defined(FS2_DEMO) || defined(FS1_DEMO)
7157 demo_upsell_show_screens();
7159 #elif defined(OEM_BUILD)
7160 // show upsell screens on exit
7161 oem_upsell_show_screens();
7168 // launcher the fslauncher program on exit
7169 void game_launch_launcher_on_exit()
7173 PROCESS_INFORMATION pi;
7174 char cmd_line[2048];
7175 char original_path[1024] = "";
7177 memset( &si, 0, sizeof(STARTUPINFO) );
7181 _getcwd(original_path, 1023);
7183 // set up command line
7184 strcpy(cmd_line, original_path);
7185 strcat(cmd_line, "\\");
7186 strcat(cmd_line, LAUNCHER_FNAME);
7187 strcat(cmd_line, " -straight_to_update");
7189 BOOL ret = CreateProcess( NULL, // pointer to name of executable module
7190 cmd_line, // pointer to command line string
7191 NULL, // pointer to process security attributes
7192 NULL, // pointer to thread security attributes
7193 FALSE, // handle inheritance flag
7194 CREATE_DEFAULT_ERROR_MODE, // creation flags
7195 NULL, // pointer to new environment block
7196 NULL, // pointer to current directory name
7197 &si, // pointer to STARTUPINFO
7198 &pi // pointer to PROCESS_INFORMATION
7200 // to eliminate build warnings
7210 // This function is called when FreeSpace terminates normally.
7212 void game_shutdown(void)
7218 // don't ever flip a page on the standalone!
7219 if(!(Game_mode & GM_STANDALONE_SERVER)){
7225 // if the player has left the "player select" screen and quit the game without actually choosing
7226 // a player, Player will be NULL, in which case we shouldn't write the player file out!
7227 if (!(Game_mode & GM_STANDALONE_SERVER) && (Player!=NULL) && !Is_standalone){
7231 // load up common multiplayer icons
7232 multi_unload_common_icons();
7234 shockwave_close(); // release any memory used by shockwave system
7235 fireball_close(); // free fireball system
7236 ship_close(); // free any memory that was allocated for the ships
7237 weapon_close(); // free any memory that was allocated for the weapons
7238 hud_free_scrollback_list();// free space allocated to store hud messages in hud scrollback
7239 unload_animating_pointer();// frees the frames used for the animating mouse pointer
7240 bm_unload_all(); // free bitmaps
7241 mission_campaign_close(); // close out the campaign stuff
7242 mission_campaign_shutdown(); // get anything that mission_campaign_close can't do
7243 multi_voice_close(); // close down multiplayer voice (including freeing buffers, etc)
7245 #ifdef MULTI_USE_LAG
7249 // the menu close functions will unload the bitmaps if they were displayed during the game
7250 #if !defined(PRESS_TOUR_BUILD) && !defined(PD_BUILD)
7253 context_help_close(); // close out help system
7254 training_menu_close();
7255 lcl_close(); // be sure localization is closed out
7258 // free left-over memory from parsed tables
7259 cutscene_tbl_close();
7261 scoring_tbl_close();
7262 player_tips_close();
7264 extern void joy_close();
7267 audiostream_close();
7269 event_music_close();
7273 // HACKITY HACK HACK
7274 // if this flag is set, we should be firing up the launcher when exiting freespace
7275 extern int Multi_update_fireup_launcher_on_exit;
7276 if(Multi_update_fireup_launcher_on_exit){
7277 game_launch_launcher_on_exit();
7281 // game_stop_looped_sounds()
7283 // This function will call the appropriate stop looped sound functions for those
7284 // modules which use looping sounds. It is not enough just to stop a looping sound
7285 // at the DirectSound level, the game is keeping track of looping sounds, and this
7286 // function is used to inform the game that looping sounds are being halted.
7288 void game_stop_looped_sounds()
7290 hud_stop_looped_locking_sounds();
7291 hud_stop_looped_engine_sounds();
7292 afterburner_stop_sounds();
7293 player_stop_looped_sounds();
7294 obj_snd_stop_all(); // stop all object-linked persistant sounds
7295 game_stop_subspace_ambient_sound();
7296 snd_stop(Radar_static_looping);
7297 Radar_static_looping = -1;
7298 snd_stop(Target_static_looping);
7299 shipfx_stop_engine_wash_sound();
7300 Target_static_looping = -1;
7303 //////////////////////////////////////////////////////////////////////////
7305 // Code for supporting an animating mouse pointer
7308 //////////////////////////////////////////////////////////////////////////
7310 typedef struct animating_obj
7319 static animating_obj Animating_mouse;
7321 // ----------------------------------------------------------------------------
7322 // init_animating_pointer()
7324 // Called by load_animating_pointer() to ensure the Animating_mouse struct
7325 // gets properly initialized
7327 void init_animating_pointer()
7329 Animating_mouse.first_frame = -1;
7330 Animating_mouse.num_frames = 0;
7331 Animating_mouse.current_frame = -1;
7332 Animating_mouse.time = 0.0f;
7333 Animating_mouse.elapsed_time = 0.0f;
7336 // ----------------------------------------------------------------------------
7337 // load_animating_pointer()
7339 // Called at game init to load in the frames for the animating mouse pointer
7341 // input: filename => filename of animation file that holds the animation
7343 void load_animating_pointer(const char *filename, int dx, int dy)
7348 init_animating_pointer();
7350 am = &Animating_mouse;
7351 am->first_frame = bm_load_animation(filename, &am->num_frames, &fps);
7352 if ( am->first_frame == -1 )
7353 Error(LOCATION, "Could not load animation %s for the mouse pointer\n", filename);
7354 am->current_frame = 0;
7355 am->time = am->num_frames / i2fl(fps);
7358 // ----------------------------------------------------------------------------
7359 // unload_animating_pointer()
7361 // Called at game shutdown to free the memory used to store the animation frames
7363 void unload_animating_pointer()
7368 am = &Animating_mouse;
7369 for ( i = 0; i < am->num_frames; i++ ) {
7370 Assert( (am->first_frame+i) >= 0 );
7371 bm_release(am->first_frame + i);
7374 am->first_frame = -1;
7376 am->current_frame = -1;
7379 // draw the correct frame of the game mouse... called from game_maybe_draw_mouse()
7380 void game_render_mouse(float frametime)
7385 // if animating cursor exists, play the next frame
7386 am = &Animating_mouse;
7387 if ( am->first_frame != -1 ) {
7388 mouse_get_pos(&mx, &my);
7389 am->elapsed_time += frametime;
7390 am->current_frame = fl2i( ( am->elapsed_time / am->time ) * (am->num_frames-1) );
7391 if ( am->current_frame >= am->num_frames ) {
7392 am->current_frame = 0;
7393 am->elapsed_time = 0.0f;
7395 gr_set_cursor_bitmap(am->first_frame + am->current_frame);
7399 // ----------------------------------------------------------------------------
7400 // game_maybe_draw_mouse()
7402 // determines whether to draw the mouse pointer at all, and what frame of
7403 // animation to use if the mouse is animating
7405 // Sets mouse.cpp globals Mouse_hidden and Mouse_moved based on the state of the game.
7407 // input: frametime => elapsed frame time in seconds since last call
7409 void game_maybe_draw_mouse(float frametime)
7413 game_state = gameseq_get_state();
7415 switch ( game_state ) {
7416 case GS_STATE_GAME_PAUSED:
7417 // case GS_STATE_MULTI_PAUSED:
7418 case GS_STATE_GAME_PLAY:
7419 case GS_STATE_DEATH_DIED:
7420 case GS_STATE_DEATH_BLEW_UP:
7421 if ( popup_active() || popupdead_is_active() ) {
7433 if ( !Mouse_hidden )
7434 game_render_mouse(frametime);
7438 void game_do_training_checks()
7442 waypoint_list *wplp;
7444 if (Training_context & TRAINING_CONTEXT_SPEED) {
7445 s = (int) Player_obj->phys_info.fspeed;
7446 if ((s >= Training_context_speed_min) && (s <= Training_context_speed_max)) {
7447 if (!Training_context_speed_set) {
7448 Training_context_speed_set = 1;
7449 Training_context_speed_timestamp = timestamp();
7453 Training_context_speed_set = 0;
7456 if (Training_context & TRAINING_CONTEXT_FLY_PATH) {
7457 wplp = &Waypoint_lists[Training_context_path];
7458 if (wplp->count > Training_context_goal_waypoint) {
7459 i = Training_context_goal_waypoint;
7461 d = vm_vec_dist(&wplp->waypoints[i], &Player_obj->pos);
7462 if (d <= Training_context_distance) {
7463 Training_context_at_waypoint = i;
7464 if (Training_context_goal_waypoint == i) {
7465 Training_context_goal_waypoint++;
7466 snd_play(&Snds[SND_CARGO_REVEAL], 0.0f);
7473 if (i == wplp->count)
7476 } while (i != Training_context_goal_waypoint);
7480 if ((Players_target == UNINITIALIZED) || (Player_ai->target_objnum != Players_target) || (Player_ai->targeted_subsys != Players_targeted_subsys)) {
7481 Players_target = Player_ai->target_objnum;
7482 Players_targeted_subsys = Player_ai->targeted_subsys;
7483 Players_target_timestamp = timestamp();
7487 /////////// Following is for event debug view screen
7491 #define EVENT_DEBUG_MAX 5000
7492 #define EVENT_DEBUG_EVENT 0x8000
7494 int Event_debug_index[EVENT_DEBUG_MAX];
7497 void game_add_event_debug_index(int n, int indent)
7499 if (ED_count < EVENT_DEBUG_MAX)
7500 Event_debug_index[ED_count++] = n | (indent << 16);
7503 void game_add_event_debug_sexp(int n, int indent)
7508 if (Sexp_nodes[n].first >= 0) {
7509 game_add_event_debug_sexp(Sexp_nodes[n].first, indent);
7510 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent);
7514 game_add_event_debug_index(n, indent);
7515 if (Sexp_nodes[n].subtype == SEXP_ATOM_OPERATOR)
7516 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent + 1);
7518 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent);
7521 void game_event_debug_init()
7526 for (e=0; e<Num_mission_events; e++) {
7527 game_add_event_debug_index(e | EVENT_DEBUG_EVENT, 0);
7528 game_add_event_debug_sexp(Mission_events[e].formula, 1);
7532 void game_show_event_debug(float frametime)
7536 int font_height, font_width;
7538 static int scroll_offset = 0;
7540 k = game_check_key();
7546 if (scroll_offset < 0)
7556 scroll_offset -= 20;
7557 if (scroll_offset < 0)
7562 scroll_offset += 20; // not font-independent, hard-coded since I counted the lines!
7566 gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
7572 gr_set_color_fast(&Color_bright);
7574 gr_printf(0x8000, 5, NOX("EVENT DEBUG VIEW"));
7576 gr_set_color_fast(&Color_normal);
7578 gr_get_string_size(&font_width, &font_height, NOX("test"));
7579 y_max = gr_screen.max_h - font_height - 5;
7583 while (k < ED_count) {
7584 if (y_index > y_max)
7587 z = Event_debug_index[k];
7588 if (z & EVENT_DEBUG_EVENT) {
7590 sprintf(buf, NOX("%s%s (%s) %s%d %d"), (Mission_events[z].flags & MEF_CURRENT) ? NOX("* ") : "",
7591 Mission_events[z].name, Mission_events[z].result ? NOX("True") : NOX("False"),
7592 (Mission_events[z].chain_delay < 0) ? "" : NOX("x "),
7593 Mission_events[z].repeat_count, Mission_events[z].interval);
7601 strcat(buf, Sexp_nodes[z & 0x7fff].text);
7602 switch (Sexp_nodes[z & 0x7fff].value) {
7604 strcat(buf, NOX(" (True)"));
7608 strcat(buf, NOX(" (False)"));
7611 case SEXP_KNOWN_TRUE:
7612 strcat(buf, NOX(" (Always true)"));
7615 case SEXP_KNOWN_FALSE:
7616 strcat(buf, NOX(" (Always false)"));
7619 case SEXP_CANT_EVAL:
7620 strcat(buf, NOX(" (Can't eval)"));
7624 case SEXP_NAN_FOREVER:
7625 strcat(buf, NOX(" (Not a number)"));
7630 gr_printf(10, y_index, buf);
7631 y_index += font_height;
7645 extern int Tmap_npixels;
7648 int Tmap_num_too_big = 0;
7649 int Num_models_needing_splitting = 0;
7651 void Time_model( int modelnum )
7653 // mprintf(( "Timing ship '%s'\n", si->name ));
7655 vector eye_pos, model_pos;
7656 matrix eye_orient, model_orient;
7658 polymodel *pm = model_get( modelnum );
7660 int l = strlen(pm->filename);
7662 if ( (l == '/') || (l=='\\') || (l==':')) {
7668 char *pof_file = &pm->filename[l];
7670 int model_needs_splitting = 0;
7672 //fprintf( Texture_fp, "Model: %s\n", pof_file );
7674 for (i=0; i<pm->n_textures; i++ ) {
7675 char filename[1024];
7678 int bmp_num = pm->original_textures[i];
7679 if ( bmp_num > -1 ) {
7680 bm_get_palette(pm->original_textures[i], pal, filename );
7682 bm_get_info( pm->original_textures[i],&w, &h );
7685 if ( (w > 512) || (h > 512) ) {
7686 fprintf( Texture_fp, "%s\t%s\t%d\t%d\n", pof_file, filename, w, h );
7688 model_needs_splitting++;
7691 //fprintf( Texture_fp, "\tTexture %d is bogus\n", i );
7695 if ( model_needs_splitting ) {
7696 Num_models_needing_splitting++;
7698 eye_orient = model_orient = vmd_identity_matrix;
7699 eye_pos = model_pos = vmd_zero_vector;
7701 eye_pos.xyz.z = -pm->rad*2.0f;
7703 vector eye_to_model;
7705 vm_vec_sub( &eye_to_model, &model_pos, &eye_pos );
7706 vm_vector_2_matrix( &eye_orient, &eye_to_model, NULL, NULL );
7708 fix t1 = timer_get_fixed_seconds();
7711 ta.p = ta.b = ta.h = 0.0f;
7718 int bitmaps_used_this_frame, bitmaps_new_this_frame;
7720 bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
7722 modelstats_num_polys = modelstats_num_verts = 0;
7724 while( ta.h < PI2 ) {
7727 vm_angles_2_matrix(&m1, &ta );
7728 vm_matrix_x_matrix( &model_orient, &vmd_identity_matrix, &m1 );
7735 g3_set_view_matrix( &eye_pos, &eye_orient, Viewer_zoom );
7737 model_clear_instance( modelnum );
7738 model_set_detail_level(0); // use highest detail level
7739 model_render( modelnum, &model_orient, &model_pos, MR_LOCK_DETAIL); //|MR_NO_POLYS );
7747 int k = key_inkey();
7748 if ( k == SDLK_ESCAPE ) {
7753 fix t2 = timer_get_fixed_seconds();
7755 bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
7756 //bitmaps_used_this_frame /= framecount;
7758 modelstats_num_polys /= framecount;
7759 modelstats_num_verts /= framecount;
7762 Tmap_npixels /=framecount;
7765 mprintf(( "'%s' is %.2f FPS\n", pof_file, i2fl(framecount)/f2fl(t2-t1) ));
7767 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 );
7769 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 );
7771 // 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 );
7777 int Time_models = 0;
7778 DCF_BOOL( time_models, Time_models );
7780 void Do_model_timings_test()
7784 if ( !Time_models ) return;
7786 mprintf(( "Timing models!\n" ));
7790 ubyte model_used[MAX_POLYGON_MODELS];
7791 int model_id[MAX_POLYGON_MODELS];
7792 for (i=0; i<MAX_POLYGON_MODELS; i++ ) {
7797 for (i=0; i<Num_ship_types; i++ ) {
7798 Ship_info[i].modelnum = model_load( Ship_info[i].pof_file, 0, NULL );
7800 model_used[Ship_info[i].modelnum%MAX_POLYGON_MODELS]++;
7801 model_id[Ship_info[i].modelnum%MAX_POLYGON_MODELS] = Ship_info[i].modelnum;
7804 Texture_fp = fopen( NOX("ShipTextures.txt"), "wt" );
7805 if ( !Texture_fp ) return;
7807 Time_fp = fopen( NOX("ShipTimings.txt"), "wt" );
7808 if ( !Time_fp ) return;
7810 fprintf( Time_fp, "Name\tFPS\tTRAM\tPolys\tVerts\tPixels\n" );
7811 // fprintf( Time_fp, "FPS\tTRAM\tPolys\tVerts\tPixels\n" );
7813 for (i=0; i<MAX_POLYGON_MODELS; i++ ) {
7814 if ( model_used[i] ) {
7815 Time_model( model_id[i] );
7819 fprintf( Texture_fp, "Number too big: %d\n", Tmap_num_too_big );
7820 fprintf( Texture_fp, "Number of models needing splitting: %d\n", Num_models_needing_splitting );
7829 // Call this function when you want to inform the player that a feature is not
7830 // enabled in the DEMO version of FreSpace
7831 void game_feature_not_in_demo_popup()
7833 popup(PF_USE_AFFIRMATIVE_ICON|PF_BODY_BIG, 1, POPUP_OK, XSTR( "Sorry, this feature is available only in the retail version", 200));
7836 // format the specified time (fixed point) into a nice string
7837 void game_format_time(fix m_time,char *time_str)
7840 int hours,minutes,seconds;
7843 mtime = f2fl(m_time);
7845 // get the hours, minutes and seconds
7846 hours = (int)(mtime / 3600.0f);
7848 mtime -= (3600.0f * (float)hours);
7850 seconds = (int)mtime%60;
7851 minutes = (int)mtime/60;
7853 // print the hour if necessary
7855 sprintf(time_str,XSTR( "%d:", 201),hours);
7856 // if there are less than 10 minutes, print a leading 0
7858 strcpy(tmp,NOX("0"));
7859 strcat(time_str,tmp);
7863 // print the minutes
7865 sprintf(tmp,XSTR( "%d:", 201),minutes);
7866 strcat(time_str,tmp);
7868 sprintf(time_str,XSTR( "%d:", 201),minutes);
7871 // print the seconds
7873 strcpy(tmp,NOX("0"));
7874 strcat(time_str,tmp);
7876 sprintf(tmp,"%d",seconds);
7877 strcat(time_str,tmp);
7880 // Stuff version string in *str.
7881 void get_version_string(char *str)
7884 if ( FS_VERSION_BUILD == 0 ) {
7885 sprintf(str,"v%d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR);
7887 sprintf(str,"v%d.%02d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR, FS_VERSION_BUILD );
7890 #if defined (FS2_DEMO) || defined(FS1_DEMO)
7892 #elif defined (OEM_BUILD)
7893 strcat(str, " (OEM)");
7899 char myname[_MAX_PATH];
7900 int namelen, major, minor, build, waste;
7901 unsigned int buf_size;
7907 // Find my EXE file name
7908 hMod = GetModuleHandle(NULL);
7909 namelen = GetModuleFileName( hMod, myname, _MAX_PATH );
7911 version_size = GetFileVersionInfoSize(myname, &bogus_handle );
7912 infop = (char *)malloc(version_size);
7913 result = GetFileVersionInfo( myname, 0, version_size, (LPVOID)infop );
7915 // get the product version
7916 result = VerQueryValue((LPVOID)infop, TEXT("\\StringFileInfo\\040904b0\\ProductVersion"), &bufp, &buf_size );
7917 sscanf( (char *)bufp, "%d, %d, %d, %d", &major, &minor, &build, &waste );
7919 sprintf(str,"Dv%d.%02d",major, minor);
7921 sprintf(str,"v%d.%02d",major, minor);
7926 void get_version_string_short(char *str)
7928 sprintf(str,"v%d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR);
7931 // ----------------------------------------------------------------
7933 // OEM UPSELL SCREENS BEGIN
7935 // ----------------------------------------------------------------
7936 #if defined(OEM_BUILD)
7938 #define NUM_OEM_UPSELL_SCREENS 3
7939 #define OEM_UPSELL_SCREEN_DELAY 10000
7941 static int Oem_upsell_bitmaps_loaded = 0;
7942 static int Oem_upsell_bitmaps[GR_NUM_RESOLUTIONS][NUM_OEM_UPSELL_SCREENS];
7943 static int Oem_upsell_screen_number = 0;
7944 static int Oem_upsell_show_next_bitmap_time;
7947 static char *Oem_upsell_bitmap_filenames[GR_NUM_RESOLUTIONS][NUM_OEM_UPSELL_SCREENS] =
7960 static int Oem_normal_cursor = -1;
7961 static int Oem_web_cursor = -1;
7962 //#define OEM_UPSELL_URL "http://www.interplay-store.com/"
7963 #define OEM_UPSELL_URL "http://www.interplay.com/cgi-bin/oemlinks.pl/pid=483421&cid=18384"
7965 void oem_upsell_next_screen()
7967 Oem_upsell_screen_number++;
7968 if ( Oem_upsell_screen_number == (NUM_OEM_UPSELL_SCREENS-1) ) {
7969 // extra long delay, mouse shown on last upsell
7970 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY*2;
7974 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY;
7978 void oem_upsell_load_bitmaps()
7982 for ( i = 0; i < NUM_OEM_UPSELL_SCREENS; i++ ) {
7983 Oem_upsell_bitmaps[gr_screen.res][i] = bm_load(Oem_upsell_bitmap_filenames[gr_screen.res][i]);
7987 void oem_upsell_unload_bitmaps()
7991 for ( i = 0; i < NUM_OEM_UPSELL_SCREENS; i++ ) {
7992 if(Oem_upsell_bitmaps[gr_screen.res][i] >= 0){
7993 bm_unload(Oem_upsell_bitmaps[gr_screen.res][i]);
7998 Oem_upsell_bitmaps_loaded = 0;
8001 // clickable hotspot on 3rd OEM upsell screen
8002 static int Oem_upsell3_button_coords[GR_NUM_RESOLUTIONS][4] = {
8004 28, 350, 287, 96 // x, y, w, h
8007 45, 561, 460, 152 // x, y, w, h
8011 void oem_upsell_show_screens()
8013 int current_time, k;
8016 if ( !Oem_upsell_bitmaps_loaded ) {
8017 oem_upsell_load_bitmaps();
8018 Oem_upsell_bitmaps_loaded = 1;
8021 // may use upsell screens more than once
8022 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY;
8023 Oem_upsell_screen_number = 0;
8029 int nframes; // used to pass, not really needed (should be 1)
8030 Oem_normal_cursor = gr_get_cursor_bitmap();
8031 Oem_web_cursor = bm_load_animation("cursorweb", &nframes);
8032 Assert(Oem_web_cursor >= 0);
8033 if (Oem_web_cursor < 0) {
8034 Oem_web_cursor = Oem_normal_cursor;
8039 //oem_reset_trailer_timer();
8041 current_time = timer_get_milliseconds();
8046 // advance screen on keypress or timeout
8047 if (( k > 0 ) || (mouse_up_count(MOUSE_LEFT_BUTTON) > 0) || (current_time > Oem_upsell_show_next_bitmap_time)) {
8048 oem_upsell_next_screen();
8051 // check if we are done
8052 if ( Oem_upsell_screen_number >= NUM_OEM_UPSELL_SCREENS ) {
8053 Oem_upsell_screen_number--;
8056 if ( Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number] < 0 ) {
8061 // show me the upsell
8062 if ( Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number] >= 0 ) {
8063 gr_set_bitmap(Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number]);
8067 // if this is the 3rd upsell, make it clickable, d00d
8068 if ( Oem_upsell_screen_number == NUM_OEM_UPSELL_SCREENS-1 ) {
8070 int button_state = mouse_get_pos(&mx, &my);
8071 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])
8072 && (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]) )
8075 gr_set_cursor_bitmap(Oem_web_cursor); //, GR_CURSOR_LOCK);
8078 if (button_state & MOUSE_LEFT_BUTTON) {
8080 multi_pxo_url(OEM_UPSELL_URL);
8084 // switch cursor back to normal one
8085 gr_set_cursor_bitmap(Oem_normal_cursor); //, GR_CURSOR_UNLOCK);
8090 if (gameseq_get_state() != GS_STATE_END_DEMO) {
8100 oem_upsell_unload_bitmaps();
8102 // switch cursor back to normal one
8103 gr_set_cursor_bitmap(Oem_normal_cursor); //, GR_CURSOR_UNLOCK);
8107 #endif // defined(OEM_BUILD)
8108 // ----------------------------------------------------------------
8110 // OEM UPSELL SCREENS END
8112 // ----------------------------------------------------------------
8116 // ----------------------------------------------------------------
8118 // DEMO UPSELL SCREENS BEGIN
8120 // ----------------------------------------------------------------
8122 #if defined(FS2_DEMO) || defined(FS1_DEMO)
8125 #define NUM_DEMO_UPSELL_SCREENS 2
8127 #define NUM_DEMO_UPSELL_SCREENS 4
8129 #define DEMO_UPSELL_SCREEN_DELAY 3000
8131 static int Demo_upsell_bitmaps_loaded = 0;
8132 static int Demo_upsell_bitmaps[GR_NUM_RESOLUTIONS][NUM_DEMO_UPSELL_SCREENS];
8133 static int Demo_upsell_screen_number = 0;
8134 static int Demo_upsell_show_next_bitmap_time;
8137 static char *Demo_upsell_bitmap_filenames[GR_NUM_RESOLUTIONS][NUM_DEMO_UPSELL_SCREENS] =
8163 void demo_upsell_next_screen()
8165 Demo_upsell_screen_number++;
8166 if ( Demo_upsell_screen_number == (NUM_DEMO_UPSELL_SCREENS-1) ) {
8167 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY*4;
8169 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY;
8173 if ( Demo_upsell_screen_number < NUM_DEMO_UPSELL_SCREENS ) {
8174 if ( Demo_upsell_bitmap_filenames[gr_screen.res][Demo_upsell_screen_number] >= 0 ) {
8175 #ifndef HARDWARE_ONLY
8176 palette_use_bm_palette(Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number]);
8183 void demo_upsell_load_bitmaps()
8187 for ( i = 0; i < NUM_DEMO_UPSELL_SCREENS; i++ ) {
8188 Demo_upsell_bitmaps[gr_screen.res][i] = bm_load(Demo_upsell_bitmap_filenames[gr_screen.res][i]);
8192 void demo_upsell_unload_bitmaps()
8196 for ( i = 0; i < NUM_DEMO_UPSELL_SCREENS; i++ ) {
8197 if(Demo_upsell_bitmaps[gr_screen.res][i] >= 0){
8198 bm_unload(Demo_upsell_bitmaps[gr_screen.res][i]);
8203 Demo_upsell_bitmaps_loaded = 0;
8206 void demo_upsell_show_screens()
8208 int current_time, k;
8211 if ( !Demo_upsell_bitmaps_loaded ) {
8212 demo_upsell_load_bitmaps();
8213 Demo_upsell_bitmaps_loaded = 1;
8216 // may use upsell screens more than once
8217 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY;
8218 Demo_upsell_screen_number = 0;
8225 demo_reset_trailer_timer();
8227 current_time = timer_get_milliseconds();
8234 // don't time out, wait for keypress
8236 if ( current_time > Demo_upsell_show_next_bitmap_time ) {
8237 demo_upsell_next_screen();
8242 demo_upsell_next_screen();
8245 if ( Demo_upsell_screen_number >= NUM_DEMO_UPSELL_SCREENS ) {
8246 Demo_upsell_screen_number--;
8249 if ( Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number] < 0 ) {
8254 if ( Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number] >= 0 ) {
8255 gr_set_bitmap(Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number]);
8260 if (gameseq_get_state() != GS_STATE_END_DEMO) {
8270 demo_upsell_unload_bitmaps();
8275 // ----------------------------------------------------------------
8277 // DEMO UPSELL SCREENS END
8279 // ----------------------------------------------------------------
8282 // ----------------------------------------------------------------
8284 // Subspace Ambient Sound START
8286 // ----------------------------------------------------------------
8288 static int Subspace_ambient_left_channel = -1;
8289 static int Subspace_ambient_right_channel = -1;
8292 void game_start_subspace_ambient_sound()
8294 if ( Subspace_ambient_left_channel < 0 ) {
8295 Subspace_ambient_left_channel = snd_play_looping(&Snds[SND_SUBSPACE_LEFT_CHANNEL], -1.0f);
8298 if ( Subspace_ambient_right_channel < 0 ) {
8299 Subspace_ambient_right_channel = snd_play_looping(&Snds[SND_SUBSPACE_RIGHT_CHANNEL], 1.0f);
8303 void game_stop_subspace_ambient_sound()
8305 if ( Subspace_ambient_left_channel >= 0 ) {
8306 snd_stop(Subspace_ambient_left_channel);
8307 Subspace_ambient_left_channel = -1;
8310 if ( Subspace_ambient_right_channel >= 0 ) {
8311 snd_stop(Subspace_ambient_right_channel);
8312 Subspace_ambient_right_channel = -1;
8316 // ----------------------------------------------------------------
8318 // Subspace Ambient Sound END
8320 // ----------------------------------------------------------------
8322 // ----------------------------------------------------------------
8324 // Language Autodetection stuff
8327 // this layout order must match Lcl_languages in localize.cpp in order for the
8328 // correct language to be detected
8329 int Lang_auto_detect_checksums[LCL_NUM_LANGUAGES] = {
8331 1366105450, // English
8333 589986744, // English
8335 -1132430286, // German
8337 -1131728960, // Polish
8340 // default setting is "-1" to use config file with English as fall back
8341 // DO NOT change the default setting here or something uncouth might happen
8342 // in the localization code
8348 // try and open the file to verify
8349 CFILE *detect = cfopen("font01.vf", "rb");
8351 // will use default setting if something went wrong
8356 // get the long checksum of the file
8358 cfseek(detect, 0, SEEK_SET);
8359 cf_chksum_long(detect, &file_checksum);
8363 // now compare the checksum/filesize against known #'s
8364 for (idx=0; idx<LCL_NUM_LANGUAGES; idx++) {
8365 if (Lang_auto_detect_checksums[idx] == (int)file_checksum) {
8370 // notify if a match was not found, include detected checksum
8371 printf("ERROR: Unknown Language Checksum: %i\n", (int)file_checksum);
8372 printf("Using default language...\n\n");
8378 // End Auto Lang stuff
8380 // ----------------------------------------------------------------
8382 // ----------------------------------------------------------------
8383 // SHIPS TBL VERIFICATION STUFF
8386 // checksums, just keep a list of all valid ones, if it matches any of them, keep it
8387 #if defined(MAKE_FS1) && !defined(FS1_DEMO)
8388 #define NUM_SHIPS_TBL_CHECKSUMS 3
8390 #define NUM_SHIPS_TBL_CHECKSUMS 1
8394 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8395 1696074201, // FS2 demo
8398 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8399 1603375034, // FS1 DEMO
8402 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8403 -129679197, // FS1 Full 1.06 (US)
8404 7762567, // FS1 SilentThreat
8405 1555372475 // FS1 Full 1.06 (German)
8409 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8410 -463907578, // US - beta 1
8411 1696074201, // FS2 demo
8414 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8415 // -1022810006, // 1.0 FULL
8416 -1254285366 // 1.2 FULL (German)
8420 void verify_ships_tbl()
8424 Game_ships_tbl_valid = 1;
8430 // detect if the packfile exists
8431 CFILE *detect = cfopen("ships.tbl", "rb");
8432 Game_ships_tbl_valid = 0;
8436 Game_ships_tbl_valid = 0;
8440 // get the long checksum of the file
8442 cfseek(detect, 0, SEEK_SET);
8443 cf_chksum_long(detect, &file_checksum);
8447 // now compare the checksum/filesize against known #'s
8448 for(idx=0; idx<NUM_SHIPS_TBL_CHECKSUMS; idx++){
8449 if(Game_ships_tbl_checksums[idx] == (int)file_checksum){
8450 Game_ships_tbl_valid = 1;
8457 DCF(shipspew, "display the checksum for the current ships.tbl")
8460 CFILE *detect = cfopen("ships.tbl", "rb");
8461 // get the long checksum of the file
8463 cfseek(detect, 0, SEEK_SET);
8464 cf_chksum_long(detect, &file_checksum);
8467 dc_printf("%d", file_checksum);
8470 // ----------------------------------------------------------------
8471 // WEAPONS TBL VERIFICATION STUFF
8474 // checksums, just keep a list of all valid ones, if it matches any of them, keep it
8475 #if defined(MAKE_FS1) && !defined(FS1_DEMO)
8476 #define NUM_WEAPONS_TBL_CHECKSUMS 3
8478 #define NUM_WEAPONS_TBL_CHECKSUMS 1
8482 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
8483 -266420030, // demo 1
8486 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
8487 -1246928725, // FS1 DEMO
8490 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
8491 -834598107, // FS1 1.06 Full (US)
8492 -1652231417, // FS1 SilentThreat
8493 720209793 // FS1 1.06 Full (German)
8497 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
8498 141718090, // US - beta 1
8499 -266420030, // demo 1
8502 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
8503 // 399297860, // 1.0 FULL
8504 -553984927 // 1.2 FULL (german)
8508 void verify_weapons_tbl()
8512 Game_weapons_tbl_valid = 1;
8518 // detect if the packfile exists
8519 CFILE *detect = cfopen("weapons.tbl", "rb");
8520 Game_weapons_tbl_valid = 0;
8524 Game_weapons_tbl_valid = 0;
8528 // get the long checksum of the file
8530 cfseek(detect, 0, SEEK_SET);
8531 cf_chksum_long(detect, &file_checksum);
8535 // now compare the checksum/filesize against known #'s
8536 for(idx=0; idx<NUM_WEAPONS_TBL_CHECKSUMS; idx++){
8537 if(Game_weapons_tbl_checksums[idx] == (int)file_checksum){
8538 Game_weapons_tbl_valid = 1;
8545 DCF(wepspew, "display the checksum for the current weapons.tbl")
8548 CFILE *detect = cfopen("weapons.tbl", "rb");
8549 // get the long checksum of the file
8551 cfseek(detect, 0, SEEK_SET);
8552 cf_chksum_long(detect, &file_checksum);
8555 dc_printf("%d", file_checksum);
8558 // if the game is running using hacked data
8559 int game_hacked_data()
8562 if(!Game_weapons_tbl_valid || !Game_ships_tbl_valid){
8570 void display_title_screen()
8572 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
8573 ///int title_bitmap;
8576 int title_bitmap = bm_load(Game_demo_title_screen_fname[gr_screen.res]);
8577 if (title_bitmap == -1) {
8583 if((gr_screen.mode == GR_DIRECT3D) && (Gr_bitmap_poly)){
8584 extern void d3d_start_frame();
8590 gr_set_bitmap(title_bitmap);
8597 if((gr_screen.mode == GR_DIRECT3D) && (Gr_bitmap_poly)){
8598 extern void d3d_stop_frame();
8606 bm_unload(title_bitmap);
8607 #endif // FS2_DEMO || OEM_BUILD || FS1_DEMO
8610 // return true if the game is running with "low memory", which is less than 48MB
8611 bool game_using_low_mem()
8613 if (Use_low_mem == 0) {