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 SDL_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"
656 #include "readyroom.h"
657 #include "mainhallmenu.h"
658 #include "multilag.h"
660 #include "particle.h"
662 #include "multi_ingame.h"
663 #include "snazzyui.h"
664 #include "asteroid.h"
665 #include "popupdead.h"
666 #include "multi_voice.h"
667 #include "missioncmdbrief.h"
668 #include "redalert.h"
669 #include "gameplayhelp.h"
670 #include "multilag.h"
671 #include "staticrand.h"
672 #include "multi_pmsg.h"
673 #include "levelpaging.h"
674 #include "observer.h"
675 #include "multi_pause.h"
676 #include "multi_endgame.h"
677 #include "cutscenes.h"
678 #include "multi_respawn.h"
680 #include "multi_obj.h"
681 #include "multi_log.h"
683 #include "localize.h"
684 #include "osregistry.h"
685 #include "barracks.h"
686 #include "missionpause.h"
688 #include "alphacolors.h"
689 #include "objcollide.h"
692 #include "neblightning.h"
693 #include "shipcontrails.h"
696 #include "multi_dogfight.h"
697 #include "multi_rate.h"
698 #include "muzzleflash.h"
702 #include "mainhalltemp.h"
703 #include "exceptionhandler.h"
707 #include "supernova.h"
708 #include "hudshield.h"
709 // #include "names.h"
711 #include "missionloopbrief.h"
715 #error macro FRED is defined when trying to build release Fred. Please undefine FRED macro in build settings
721 // 1.00.04 5/26/98 MWA -- going final (12 pm)
722 // 1.00.03 5/26/98 MWA -- going final (3 am)
723 // 1.00.02 5/25/98 MWA -- going final
724 // 1.00.01 5/25/98 MWA -- going final
725 // 0.90 5/21/98 MWA -- getting ready for final.
726 // 0.10 4/9/98. Set by MK.
728 // Demo version: (obsolete since DEMO codebase split from tree)
729 // 0.03 4/10/98 AL. Interplay rev
730 // 0.02 4/8/98 MK. Increased when this system was modified.
731 // 0.01 4/7/98? AL. First release to Interplay QA.
734 // 1.00 5/28/98 AL. First release to Interplay QA.
736 void game_level_init(int seed = -1);
737 void game_post_level_init();
738 void game_do_frame();
739 void game_update_missiontime(); // called from game_do_frame() and navmap_do_frame()
740 void game_reset_time();
741 void game_show_framerate(); // draws framerate in lower right corner
743 int Game_no_clear = 0;
745 int Pofview_running = 0;
746 int Nebedit_running = 0;
748 typedef struct big_expl_flash {
749 float max_flash_intensity; // max intensity
750 float cur_flash_intensity; // cur intensity
751 int flash_start; // start time
754 #define FRAME_FILTER 16
756 #define DEFAULT_SKILL_LEVEL 1
757 int Game_skill_level = DEFAULT_SKILL_LEVEL;
759 #define VIEWER_ZOOM_DEFAULT 0.75f // Default viewer zoom, 0.625 as per multi-lateral agreement on 3/24/97
760 float Viewer_zoom = VIEWER_ZOOM_DEFAULT;
762 #define EXE_FNAME ("fs2.exe")
763 #define LAUNCHER_FNAME ("freespace2.exe")
766 // JAS: Code for warphole camera.
767 // Needs to be cleaned up.
768 vector Camera_pos = ZERO_VECTOR;
769 vector Camera_velocity = ZERO_VECTOR;
770 vector Camera_desired_velocity = ZERO_VECTOR;
771 matrix Camera_orient = IDENTITY_MATRIX;
772 float Camera_damping = 1.0f;
773 float Camera_time = 0.0f;
774 float Warpout_time = 0.0f;
775 int Warpout_forced = 0; // Set if this is a forced warpout that cannot be cancelled.
776 int Warpout_sound = -1;
778 int Use_joy_mouse = 0;
779 int Use_palette_flash = 1;
781 int Use_fullscreen_at_startup = 0;
783 int Show_area_effect = 0;
784 object *Last_view_target = NULL;
786 int dogfight_blown = 0;
789 float frametimes[FRAME_FILTER];
790 float frametotal = 0.0f;
794 int Show_framerate = 0;
796 int Show_framerate = 1;
799 int Framerate_cap = 120;
802 int Show_target_debug_info = 0;
803 int Show_target_weapons = 0;
807 static int Show_player_pos = 0; // debug console command to show player world pos on HUD
810 int Debug_octant = -1;
812 fix Game_time_compression = F1_0;
814 // if the ships.tbl the player has is valid
815 int Game_ships_tbl_valid = 0;
817 // if the weapons.tbl the player has is valid
818 int Game_weapons_tbl_valid = 0;
822 extern int Player_attacking_enabled;
826 int Pre_player_entry;
828 int Fred_running = 0;
829 char Game_current_mission_filename[MAX_FILENAME_LEN];
830 int game_single_step = 0;
831 int last_single_step=0;
833 extern int MSG_WINDOW_X_START; // used to position mission_time and shields output
834 extern int MSG_WINDOW_Y_START;
835 extern int MSG_WINDOW_HEIGHT;
837 int game_zbuffer = 1;
838 //static int Game_music_paused;
839 static int Game_paused;
843 #define EXPIRE_BAD_CHECKSUM 1
844 #define EXPIRE_BAD_TIME 2
846 extern void ssm_init();
847 extern void ssm_level_init();
848 extern void ssm_process();
850 // static variable to contain the time this version was built
851 // commented out for now until
852 // I figure out how to get the username into the file
853 //LOCAL char freespace_build_time[] = "Compiled on:"__DATE__" "__TIME__" by "__USER__;
855 // defines and variables used for dumping frame for making trailers.
857 int Debug_dump_frames = 0; // Set to 0 to not dump frames, else equal hz to dump. (15 or 30 probably)
858 int Debug_dump_trigger = 0;
859 int Debug_dump_frame_count;
860 int Debug_dump_frame_num = 0;
861 #define DUMP_BUFFER_NUM_FRAMES 1 // store every 15 frames
864 // amount of time to wait after the player has died before we display the death died popup
865 #define PLAYER_DIED_POPUP_WAIT 2500
866 int Player_died_popup_wait = -1;
867 int Player_multi_died_check = -1;
869 // builtin mission list stuff
871 int Game_builtin_mission_count = 6;
872 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
873 { "SPDemo-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
874 { "SPDemo-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
875 { "DemoTrain.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
876 { "Demo.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE) },
877 { "MPDemo-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
878 { "Demo-DOG-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
880 #elif defined(FS1_DEMO)
881 int Game_builtin_mission_count = 5;
882 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
883 { "btmdemo.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
884 { "demo.fsc", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE) },
885 { "demo01.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
886 { "demo02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
887 { "demo02b.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
889 #elif defined(PD_BUILD)
890 int Game_builtin_mission_count = 4;
891 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
892 { "sm1-01.fs2", (FSB_FROM_VOLITION) },
893 { "sm1-05.fs2", (FSB_FROM_VOLITION) },
894 { "sm1-01", (FSB_FROM_VOLITION) },
895 { "sm1-05", (FSB_FROM_VOLITION) },
897 #elif defined(MULTIPLAYER_BETA)
898 int Game_builtin_mission_count = 17;
899 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
901 { "md-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
902 { "md-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
903 { "md-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
904 { "md-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
905 { "md-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
906 { "md-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
907 { "md-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
908 { "mt-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
909 { "mt-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
910 { "m-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
911 { "m-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
912 { "m-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
913 { "templar-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
914 { "templar-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
915 { "templar-03a.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
916 { "templar-04a.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
917 { "templar.fc2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE) },
919 #elif defined(OEM_BUILD)
920 int Game_builtin_mission_count = 17;
921 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
922 // oem version - act 1 only
923 { "freespace2oem.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE) },
926 { "sm1-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
927 { "sm1-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
928 { "sm1-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
929 { "sm1-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
930 { "sm1-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
931 { "sm1-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
932 { "sm1-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
933 { "sm1-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
934 { "sm1-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
935 { "sm1-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
936 { "training-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
937 { "training-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
938 { "training-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
939 { "tsm-104.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
940 { "tsm-105.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
941 { "tsm-106.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) }
943 #elif defined(MAKE_FS1)
944 int Game_builtin_mission_count = 125;
945 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
946 // single player campaign
947 { "freespace.fsc", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE) },
950 { "sm1-01.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
951 { "sm1-02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
952 { "sm1-03a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
953 { "sm1-04a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
954 { "sm1-05a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
955 { "sm1-06a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
956 { "sm1-07a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
957 { "sm1-08a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
958 { "sm1-09a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
959 { "sm1-10a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
962 { "sm2-01a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
963 { "sm2-02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
964 { "sm2-03a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
965 { "sm2-04a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
966 { "sm2-05a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
967 { "sm2-06a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
968 { "sm2-07a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
969 { "sm2-08a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
970 { "sm2-09a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
971 { "sm2-10a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
974 { "sm3-01a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
975 { "sm3-02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
976 { "sm3-03a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
977 { "sm3-04a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
978 { "sm3-05a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
979 { "sm3-06a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
980 { "sm3-07a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
981 { "sm3-08a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
982 { "sm3-09a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
985 { "t-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
986 { "v-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
987 { "s-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
990 { "btm-01.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
991 { "btm-02.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
992 { "btm-03.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
993 { "btm-04.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
994 { "btm-05.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
997 { "m-hope.fsc", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE) },
998 { "m-altair.fsc", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE) },
1000 { "m-v-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1001 { "m-va.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1002 { "m-unstoppable.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1003 { "m-t-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1004 { "m-s-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1005 { "m-rescue.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1006 { "m-pain.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1007 { "m-orecovery.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1008 { "mm3-01a.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1009 { "mm3-02a.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1010 { "mm3-03a.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1011 { "mm3-04a.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1012 { "mm3-05a.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1013 { "mm3-06a.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1014 { "m-guardduty.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1015 { "m-gate.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1016 { "m-duel.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1017 { "m-convoyassault.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1018 { "m-clash.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1020 // SilentThreat missions
1021 // Main SilentThreat campaign
1022 { "SilentThreat.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN_FILE) },
1024 { "md-01.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1025 { "md-02.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1026 { "md-03.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1027 { "md-04.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1028 { "md-05.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1029 { "md-06.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1030 { "md-07.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1031 { "md-08.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1032 { "md-09.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1033 { "md-10.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1034 { "md-11.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1035 { "md-12.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1037 // SilentThreat Part 1 - multi-coop
1038 { "ST-Part1.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE) },
1040 { "stmm-01.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1041 { "stmm-02.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1042 { "stmm-03.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1044 // SilentThreat Part 2 - multi-coop
1045 { "ST-Part2.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE) },
1047 { "stmm-04.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1048 { "stmm-05.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1049 { "stmm-06.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1051 // SilentThreat Part 3 - multi-coop
1052 { "ST-Part3.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE) },
1054 { "stmm-07.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1055 { "stmm-08.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1056 { "stmm-09.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1058 // SilentThreat Part 4 - multi-coop
1059 { "ST-Part4.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE) },
1061 { "stmm-10.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1062 { "stmm-11.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1063 { "stmm-12.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1065 // multiplayer missions
1066 { "mdmm-01.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI) },
1067 { "mdmm-02.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI) },
1068 { "mdmm-03.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI) },
1069 { "mdmm-04.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI) },
1070 // user supplied missions
1071 { "mdu-02.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1072 { "mdu-03.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1073 { "mdu-04.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1074 { "mdu-05.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1075 { "mdu-06.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1076 { "mdu-07.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1077 { "mdu-08.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1078 { "mdu-09.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1079 { "mdu-10.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1080 { "mdu-11.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1081 { "mdu-12.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1082 { "mdu-13.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1083 { "mdu-14.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1084 { "mdu-15.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1085 { "mdu-16.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1086 { "mdu-17.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1087 { "mdu-18.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1088 { "mdu-19.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1089 { "mdu-20.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1090 { "mdu-21.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1091 { "mdu-22.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1092 { "mdu-23.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1093 { "mdu-24.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1094 { "mdu-25.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1095 { "mdu-26.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1096 { "mdu-27.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1097 { "mdu-28.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1098 { "mdu-29.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1099 { "mdu-30.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1100 { "mdu-31.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1101 { "mdumm-01.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1102 { "mdumm-02.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1105 int Game_builtin_mission_count = 92;
1106 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
1107 // single player campaign
1108 { "freespace2.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE) },
1111 { "sm1-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1112 { "sm1-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1113 { "sm1-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1114 { "sm1-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1115 { "sm1-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1116 { "sm1-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1117 { "sm1-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1118 { "sm1-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1119 { "sm1-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1120 { "sm1-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1121 { "loop1-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1122 { "loop1-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1123 { "loop1-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1124 { "training-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1125 { "training-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1126 { "training-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1127 { "tsm-104.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1128 { "tsm-105.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1129 { "tsm-106.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1132 { "sm2-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1133 { "sm2-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1134 { "sm2-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1135 { "sm2-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1136 { "sm2-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1137 { "sm2-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1138 { "sm2-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1139 { "sm2-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1140 { "sm2-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1141 { "sm2-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1144 { "sm3-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1145 { "sm3-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1146 { "sm3-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1147 { "sm3-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1148 { "sm3-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1149 { "sm3-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1150 { "sm3-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1151 { "sm3-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1152 { "sm3-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1153 { "sm3-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1154 { "loop2-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1155 { "loop2-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1157 // multiplayer missions
1160 { "g-shi.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1161 { "g-ter.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1162 { "g-vas.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1165 { "m-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1166 { "m-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1167 { "m-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1168 { "m-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1171 { "mdh-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1172 { "mdh-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1173 { "mdh-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1174 { "mdh-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1175 { "mdh-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1176 { "mdh-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1177 { "mdh-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1178 { "mdh-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1179 { "mdh-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1180 { "mdl-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1181 { "mdl-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1182 { "mdl-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1183 { "mdl-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1184 { "mdl-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1185 { "mdl-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1186 { "mdl-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1187 { "mdl-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1188 { "mdl-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1189 { "mdm-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1190 { "mdm-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1191 { "mdm-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1192 { "mdm-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1193 { "mdm-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1194 { "mdm-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1195 { "mdm-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1196 { "mdm-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1197 { "mdm-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1198 { "osdog.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1201 { "mt-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1202 { "mt-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1203 { "mt-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1204 { "mt-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1205 { "mt-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1206 { "mt-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1207 { "mt-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1208 { "mt-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1209 { "mt-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1210 { "mt-10.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1213 { "templar.fc2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE) },
1214 { "templar-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
1215 { "templar-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
1216 { "templar-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
1217 { "templar-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
1222 // Internal function prototypes
1223 void game_maybe_draw_mouse(float frametime);
1224 void init_animating_pointer();
1225 void load_animating_pointer(const char *filename, int dx, int dy);
1226 void unload_animating_pointer();
1227 void game_do_training_checks();
1228 void game_shutdown(void);
1229 void game_show_event_debug(float frametime);
1230 void game_event_debug_init();
1232 void demo_upsell_show_screens();
1233 void game_start_subspace_ambient_sound();
1234 void game_stop_subspace_ambient_sound();
1235 void verify_ships_tbl();
1236 void verify_weapons_tbl();
1237 void display_title_screen();
1239 // loading background filenames
1240 static const char *Game_loading_bground_fname[GR_NUM_RESOLUTIONS] = {
1241 "LoadingBG", // GR_640
1242 "2_LoadingBG" // GR_1024
1246 static const char *Game_loading_ani_fname[GR_NUM_RESOLUTIONS] = {
1247 "Loading.ani", // GR_640
1248 "2_Loading.ani" // GR_1024
1251 #if defined(FS2_DEMO) || defined(FS1_DEMO)
1252 static const char *Game_demo_title_screen_fname[GR_NUM_RESOLUTIONS] = {
1260 #elif defined(OEM_BUILD)
1261 static const char *Game_demo_title_screen_fname[GR_NUM_RESOLUTIONS] = {
1270 // How much RAM is on this machine. Set in WinMain
1271 static int Freespace_total_ram = 0;
1274 float Game_flash_red = 0.0f;
1275 float Game_flash_green = 0.0f;
1276 float Game_flash_blue = 0.0f;
1277 float Sun_spot = 0.0f;
1278 big_expl_flash Big_expl_flash = {0.0f, 0.0f, 0};
1280 // game shudder stuff (in ms)
1281 int Game_shudder_time = -1;
1282 int Game_shudder_total = 0;
1283 float Game_shudder_intensity = 0.0f; // should be between 0.0 and 100.0
1286 sound_env Game_sound_env;
1287 //sound_env Game_default_sound_env = {SND_ENV_AUDITORIUM, 0.25f, 0.35f, 3.0f};
1288 sound_env Game_default_sound_env = {SND_ENV_GENERIC, 0.2F,0.2F,1.0F};
1290 int Game_sound_env_update_timestamp;
1292 // WARPIN CRAP BEGIN --------------------------------------------------------------------------------------------
1295 // WARPIN CRAP END --------------------------------------------------------------------------------------------
1297 fs_builtin_mission *game_find_builtin_mission(const char *filename)
1301 // look through all existing builtin missions
1302 for(idx=0; idx<Game_builtin_mission_count; idx++){
1303 if(!SDL_strcasecmp(Game_builtin_mission_list[idx].filename, filename)){
1304 return &Game_builtin_mission_list[idx];
1312 int game_get_default_skill_level()
1314 return DEFAULT_SKILL_LEVEL;
1318 void game_flash_reset()
1320 Game_flash_red = 0.0f;
1321 Game_flash_green = 0.0f;
1322 Game_flash_blue = 0.0f;
1324 Big_expl_flash.max_flash_intensity = 0.0f;
1325 Big_expl_flash.cur_flash_intensity = 0.0f;
1326 Big_expl_flash.flash_start = 0;
1329 float Gf_critical = -1.0f; // framerate we should be above on the average for this mission
1330 float Gf_critical_time = 0.0f; // how much time we've been at the critical framerate
1332 void game_framerate_check_init()
1334 // zero critical time
1335 Gf_critical_time = 0.0f;
1338 if(The_mission.flags & MISSION_FLAG_FULLNEB){
1339 Gf_critical = 15.0f;
1341 Gf_critical = 25.0f;
1345 extern float Framerate;
1346 void game_framerate_check()
1350 // if the current framerate is above the critical level, add frametime
1351 if(Framerate >= Gf_critical){
1352 Gf_critical_time += flFrametime;
1355 if(!Show_framerate){
1359 // display if we're above the critical framerate
1360 if(Framerate < Gf_critical){
1361 gr_set_color_fast(&Color_bright_red);
1362 gr_string(200, y_start, "Framerate warning");
1367 // display our current pct of good frametime
1368 if(f2fl(Missiontime) >= 0.0f){
1369 float pct = (Gf_critical_time / f2fl(Missiontime)) * 100.0f;
1372 gr_set_color_fast(&Color_bright_green);
1374 gr_set_color_fast(&Color_bright_red);
1377 gr_printf(200, y_start, "%d%%", (int)pct);
1384 // Adds a flash effect. These can be positive or negative.
1385 // The range will get capped at around -1 to 1, so stick
1386 // with a range like that.
1387 void game_flash( float r, float g, float b )
1389 Game_flash_red += r;
1390 Game_flash_green += g;
1391 Game_flash_blue += b;
1393 if ( Game_flash_red < -1.0f ) {
1394 Game_flash_red = -1.0f;
1395 } else if ( Game_flash_red > 1.0f ) {
1396 Game_flash_red = 1.0f;
1399 if ( Game_flash_green < -1.0f ) {
1400 Game_flash_green = -1.0f;
1401 } else if ( Game_flash_green > 1.0f ) {
1402 Game_flash_green = 1.0f;
1405 if ( Game_flash_blue < -1.0f ) {
1406 Game_flash_blue = -1.0f;
1407 } else if ( Game_flash_blue > 1.0f ) {
1408 Game_flash_blue = 1.0f;
1413 // Adds a flash for Big Ship explosions
1414 // cap range from 0 to 1
1415 void big_explosion_flash(float flash)
1417 Big_expl_flash.flash_start = timestamp(1);
1421 } else if (flash < 0.0f) {
1425 Big_expl_flash.max_flash_intensity = flash;
1426 Big_expl_flash.cur_flash_intensity = 0.0f;
1429 // Amount to diminish palette towards normal, per second.
1430 #define DIMINISH_RATE 0.75f
1431 #define SUN_DIMINISH_RATE 6.00f
1435 float sn_glare_scale = 1.7f;
1438 dc_get_arg(ARG_FLOAT);
1439 sn_glare_scale = Dc_arg_float;
1442 float Supernova_last_glare = 0.0f;
1443 void game_sunspot_process(float frametime)
1447 float Sun_spot_goal = 0.0f;
1450 sn_stage = supernova_active();
1452 // sunspot differently based on supernova stage
1454 // approaching. player still in control
1457 pct = (1.0f - (supernova_time_left() / SUPERNOVA_CUT_TIME));
1460 light_get_global_dir(&light_dir, 0);
1462 dot = vm_vec_dot( &light_dir, &Eye_matrix.v.fvec );
1465 // scale it some more
1466 dot = dot * (0.5f + (pct * 0.5f));
1469 Sun_spot_goal += (dot * sn_glare_scale);
1472 // draw the sun glow
1473 if ( !shipfx_eye_in_shadow( &Eye_position, Viewer_obj, 0 ) ) {
1474 // draw the glow for this sun
1475 stars_draw_sun_glow(0);
1478 Supernova_last_glare = Sun_spot_goal;
1481 // camera cut. player not in control. note : at this point camera starts out facing the sun. so we can go nice and bright
1484 Sun_spot_goal = 0.9f;
1485 Sun_spot_goal += (1.0f - (supernova_time_left() / SUPERNOVA_CUT_TIME)) * 0.1f;
1487 if(Sun_spot_goal > 1.0f){
1488 Sun_spot_goal = 1.0f;
1491 Sun_spot_goal *= sn_glare_scale;
1492 Supernova_last_glare = Sun_spot_goal;
1495 // fade to white. display dead popup
1498 Supernova_last_glare += (2.0f * flFrametime);
1499 if(Supernova_last_glare > 2.0f){
1500 Supernova_last_glare = 2.0f;
1503 Sun_spot_goal = Supernova_last_glare;
1510 // check sunspots for all suns
1511 n_lights = light_get_global_count();
1514 for(idx=0; idx<n_lights; idx++){
1515 //(vector *eye_pos, matrix *eye_orient)
1516 if ( !shipfx_eye_in_shadow( &Eye_position, Viewer_obj, idx ) ) {
1519 light_get_global_dir(&light_dir, idx);
1521 float dot = vm_vec_dot( &light_dir, &Eye_matrix.v.fvec )*0.5f+0.5f;
1523 Sun_spot_goal += (float)pow(dot,85.0f);
1525 // draw the glow for this sun
1526 stars_draw_sun_glow(idx);
1528 Sun_spot_goal = 0.0f;
1534 Sun_spot_goal = 0.0f;
1538 float dec_amount = frametime*SUN_DIMINISH_RATE;
1540 if ( Sun_spot < Sun_spot_goal ) {
1541 Sun_spot += dec_amount;
1542 if ( Sun_spot > Sun_spot_goal ) {
1543 Sun_spot = Sun_spot_goal;
1545 } else if ( Sun_spot > Sun_spot_goal ) {
1546 Sun_spot -= dec_amount;
1547 if ( Sun_spot < Sun_spot_goal ) {
1548 Sun_spot = Sun_spot_goal;
1554 // Call once a frame to diminish the
1555 // flash effect to 0.
1556 void game_flash_diminish(float frametime)
1558 float dec_amount = frametime*DIMINISH_RATE;
1560 if ( Game_flash_red > 0.0f ) {
1561 Game_flash_red -= dec_amount;
1562 if ( Game_flash_red < 0.0f )
1563 Game_flash_red = 0.0f;
1565 Game_flash_red += dec_amount;
1566 if ( Game_flash_red > 0.0f )
1567 Game_flash_red = 0.0f;
1570 if ( Game_flash_green > 0.0f ) {
1571 Game_flash_green -= dec_amount;
1572 if ( Game_flash_green < 0.0f )
1573 Game_flash_green = 0.0f;
1575 Game_flash_green += dec_amount;
1576 if ( Game_flash_green > 0.0f )
1577 Game_flash_green = 0.0f;
1580 if ( Game_flash_blue > 0.0f ) {
1581 Game_flash_blue -= dec_amount;
1582 if ( Game_flash_blue < 0.0f )
1583 Game_flash_blue = 0.0f;
1585 Game_flash_blue += dec_amount;
1586 if ( Game_flash_blue > 0.0f )
1587 Game_flash_blue = 0.0f;
1590 // update big_explosion_cur_flash
1591 #define TIME_UP 1500
1592 #define TIME_DOWN 2500
1593 int duration = TIME_UP + TIME_DOWN;
1594 int time = timestamp_until(Big_expl_flash.flash_start);
1595 if (time > -duration) {
1597 if (time < TIME_UP) {
1598 Big_expl_flash.cur_flash_intensity = Big_expl_flash.max_flash_intensity * time / (float) TIME_UP;
1601 Big_expl_flash.cur_flash_intensity = Big_expl_flash.max_flash_intensity * ((float) TIME_DOWN - time) / (float) TIME_DOWN;
1605 if ( Use_palette_flash ) {
1607 // static int or=0, og=0, ob=0;
1609 // Change the 200 to change the color range of colors.
1610 r = fl2i( Game_flash_red*128.0f );
1611 g = fl2i( Game_flash_green*128.0f );
1612 b = fl2i( Game_flash_blue*128.0f );
1614 if ( Sun_spot > 0.0f ) {
1615 r += fl2i(Sun_spot*128.0f);
1616 g += fl2i(Sun_spot*128.0f);
1617 b += fl2i(Sun_spot*128.0f);
1620 if ( Big_expl_flash.cur_flash_intensity > 0.0f ) {
1621 r += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1622 g += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1623 b += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1626 if ( r < 0 ) r = 0; else if ( r > 255 ) r = 255;
1627 if ( g < 0 ) g = 0; else if ( g > 255 ) g = 255;
1628 if ( b < 0 ) b = 0; else if ( b > 255 ) b = 255;
1630 if ( (r!=0) || (g!=0) || (b!=0) ) {
1631 gr_flash( r, g, b );
1633 //mprintf(( "Flash! %d,%d,%d\n", r, g, b ));
1644 void game_level_close()
1646 // De-Initialize the game subsystems
1647 event_music_level_close();
1648 game_stop_looped_sounds();
1650 obj_snd_level_close(); // uninit object-linked persistant sounds
1651 gamesnd_unload_gameplay_sounds(); // unload gameplay sounds from memory
1652 anim_level_close(); // stop and clean up any anim instances
1653 message_mission_shutdown(); // called after anim_level_close() to make sure anim instances are free
1654 shockwave_level_close();
1655 fireball_level_close();
1657 mission_event_shutdown();
1658 asteroid_level_close();
1659 model_cache_reset(); // Reset/free all the model caching stuff
1660 flak_level_close(); // unload flak stuff
1661 neb2_level_close(); // shutdown gaseous nebula stuff
1664 mflash_level_close();
1665 mission_brief_common_reset(); // close out parsed briefing/mission stuff
1667 audiostream_unpause_all();
1672 // intializes game stuff and loads the mission. Returns 0 on failure, 1 on success
1673 // input: seed => DEFAULT PARAMETER (value -1). Only set by demo playback code.
1674 void game_level_init(int seed)
1676 // seed the random number generator
1678 // if no seed was passed, seed the generator either from the time value, or from the
1679 // netgame security flags -- ensures that all players in multiplayer game will have the
1680 // same randon number sequence (with static rand functions)
1681 if ( Game_mode & GM_NORMAL ) {
1682 Game_level_seed = time(NULL);
1684 Game_level_seed = Netgame.security;
1687 // mwa 9/17/98 -- maybe this assert isn't needed????
1688 SDL_assert( !(Game_mode & GM_MULTIPLAYER) );
1689 Game_level_seed = seed;
1691 srand( Game_level_seed );
1693 // semirand function needs to get re-initted every time in multiplayer
1694 if ( Game_mode & GM_MULTIPLAYER ){
1700 Key_normal_game = (Game_mode & GM_NORMAL);
1703 Game_shudder_time = -1;
1705 // Initialize the game subsystems
1706 // timestamp_reset(); // Must be inited before everything else
1708 game_reset_time(); // resets time, and resets saved time too
1710 obj_init(); // Must be inited before the other systems
1711 model_free_all(); // Free all existing models
1712 mission_brief_common_init(); // Free all existing briefing/debriefing text
1713 weapon_level_init();
1714 ai_level_init(); // Call this before ship_init() because it reads ai.tbl.
1716 player_level_init();
1717 shipfx_flash_init(); // Init the ship gun flash system.
1718 game_flash_reset(); // Reset the flash effect
1719 particle_init(); // Reset the particle system
1723 shield_hit_init(); // Initialize system for showing shield hits
1724 radar_mission_init();
1725 mission_init_goals();
1728 obj_snd_level_init(); // init object-linked persistant sounds
1730 shockwave_level_init();
1731 afterburner_level_init();
1732 scoring_level_init( &Player->stats );
1734 asteroid_level_init();
1735 control_config_clear_used_status();
1736 collide_ship_ship_sounds_init();
1738 Pre_player_entry = 1; // Means the player has not yet entered.
1739 Entry_delay_time = 0; // Could get overwritten in mission read.
1740 fireball_preload(); // page in warphole bitmaps
1742 flak_level_init(); // initialize flak - bitmaps, etc
1743 ct_level_init(); // initialize ships contrails, etc
1744 awacs_level_init(); // initialize AWACS
1745 beam_level_init(); // initialize beam weapons
1746 mflash_level_init();
1748 supernova_level_init();
1750 // multiplayer dogfight hack
1753 shipfx_engine_wash_level_init();
1757 Last_view_target = NULL;
1762 // campaign wasn't ended
1763 Campaign_ended_in_mission = 0;
1766 // called when a mission is over -- does server specific stuff.
1767 void freespace_stop_mission()
1770 Game_mode &= ~GM_IN_MISSION;
1773 // called at frame interval to process networking stuff
1774 void game_do_networking()
1776 SDL_assert( Net_player != NULL );
1777 if (!(Game_mode & GM_MULTIPLAYER)){
1781 // see if this player should be reading/writing data. Bit is set when at join
1782 // screen onward until quits back to main menu.
1783 if ( !(Net_player->flags & NETINFO_FLAG_DO_NETWORKING) ){
1787 if(gameseq_get_state()!=GS_STATE_MULTI_PAUSED){
1790 multi_pause_do_frame();
1795 // Loads the best palette for this level, based
1796 // on nebula color and hud color. You could just call palette_load_table with
1797 // the appropriate filename, but who wants to do that.
1798 void game_load_palette()
1800 char palette_filename[1024];
1802 // We only use 3 hud colors right now
1804 SDL_assert( HUD_config.main_color >= 0 );
1805 SDL_assert( HUD_config.main_color <= 2 );
1808 SDL_assert( Mission_palette >= 0 );
1809 SDL_assert( Mission_palette <= 98 );
1812 if ( The_mission.flags & MISSION_FLAG_SUBSPACE ) {
1813 strcpy( palette_filename, NOX("gamepalette-subspace") );
1815 sprintf( palette_filename, NOX("gamepalette%d-%02d"), HUD_config.main_color+1, Mission_palette+1 );
1818 mprintf(( "Loading palette %s\n", palette_filename ));
1820 palette_load_table(palette_filename);
1822 strcpy( palette_filename, NOX("gamepalette-subspace") );
1824 mprintf(( "Loading palette %s\n", palette_filename ));
1828 void game_post_level_init()
1830 // Stuff which gets called after mission is loaded. Because player isn't created until
1831 // after mission loads, some things must get initted after the level loads
1833 model_level_post_init();
1836 hud_setup_escort_list();
1837 mission_hotkey_set_defaults(); // set up the default hotkeys (from mission file)
1843 game_event_debug_init();
1846 training_mission_init();
1847 asteroid_create_all();
1849 game_framerate_check_init();
1853 // An estimate as to how high the count passed to game_loading_callback will go.
1854 // This is just a guess, it seems to always be about the same. The count is
1855 // proportional to the code being executed, not the time, so this works good
1856 // for a bar, assuming the code does about the same thing each time you
1857 // load a level. You can find this value by looking at the return value
1858 // of game_busy_callback(NULL), which I conveniently print out to the
1859 // debug output window with the '=== ENDING LOAD ==' stuff.
1860 //#define COUNT_ESTIMATE 3706
1861 #define COUNT_ESTIMATE 1111
1863 int Game_loading_callback_inited = 0;
1865 int Game_loading_background = -1;
1866 anim * Game_loading_ani = NULL;
1867 anim_instance *Game_loading_ani_instance;
1868 int Game_loading_frame=-1;
1870 static int Game_loading_ani_coords[GR_NUM_RESOLUTIONS][2] = {
1872 #if defined(FS1_DEMO)
1874 #elif defined(MAKE_FS1)
1885 // This gets called 10x per second and count is the number of times
1886 // game_busy() has been called since the current callback function
1888 void game_loading_callback(int count)
1890 game_do_networking();
1892 SDL_assert( Game_loading_callback_inited==1 );
1893 SDL_assert( Game_loading_ani != NULL );
1895 int framenum = ((Game_loading_ani->total_frames*count) / COUNT_ESTIMATE)+1;
1896 if ( framenum > Game_loading_ani->total_frames-1 ) {
1897 framenum = Game_loading_ani->total_frames-1;
1898 } else if ( framenum < 0 ) {
1903 while ( Game_loading_frame < framenum ) {
1904 Game_loading_frame++;
1905 cbitmap = anim_get_next_frame(Game_loading_ani_instance);
1909 if ( cbitmap > -1 ) {
1910 if ( Game_loading_background > -1 ) {
1911 gr_set_bitmap( Game_loading_background, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1915 //mprintf(( "Showing frame %d/%d [ Bitmap=%d ]\n", Game_loading_frame , Game_loading_ani->total_frames, cbitmap ));
1916 gr_set_bitmap( cbitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1917 gr_bitmap(Game_loading_ani_coords[gr_screen.res][0],Game_loading_ani_coords[gr_screen.res][1]);
1919 bm_release(cbitmap);
1925 void game_loading_callback_init()
1927 SDL_assert( Game_loading_callback_inited==0 );
1929 Game_loading_background = bm_load(Game_loading_bground_fname[gr_screen.res]);
1931 common_set_interface_palette("InterfacePalette"); // set the interface palette
1935 Game_loading_ani = anim_load( Game_loading_ani_fname[gr_screen.res]);
1936 SDL_assert( Game_loading_ani != NULL );
1937 Game_loading_ani_instance = init_anim_instance(Game_loading_ani, 16);
1938 SDL_assert( Game_loading_ani_instance != NULL );
1939 Game_loading_frame = -1;
1941 Game_loading_callback_inited = 1;
1943 game_busy_callback( game_loading_callback, (COUNT_ESTIMATE/Game_loading_ani->total_frames)+1 );
1948 void game_loading_callback_close()
1950 SDL_assert( Game_loading_callback_inited==1 );
1952 // Make sure bar shows all the way over.
1953 game_loading_callback(COUNT_ESTIMATE);
1955 int real_count = game_busy_callback( NULL );
1958 Game_loading_callback_inited = 0;
1961 mprintf(( "=================== ENDING LOAD ================\n" ));
1962 mprintf(( "Real count = %d, Estimated count = %d\n", real_count, COUNT_ESTIMATE ));
1963 mprintf(( "================================================\n" ));
1965 // to remove warnings in release build
1969 free_anim_instance(Game_loading_ani_instance);
1970 Game_loading_ani_instance = NULL;
1971 anim_free(Game_loading_ani);
1972 Game_loading_ani = NULL;
1974 bm_release( Game_loading_background );
1975 common_free_interface_palette(); // restore game palette
1976 Game_loading_background = -1;
1978 gr_set_font( FONT1 );
1981 // Update the sound environment (ie change EAX settings based on proximity to large ships)
1983 void game_maybe_update_sound_environment()
1985 // do nothing for now
1988 // Assign the sound environment for the game, based on the current mission
1990 void game_assign_sound_environment()
1993 if (The_mission.flags & MISSION_FLAG_SUBSPACE) {
1994 Game_sound_env.id = SND_ENV_DRUGGED;
1995 Game_sound_env.volume = 0.800f;
1996 Game_sound_env.damping = 1.188f;
1997 Game_sound_env.decay = 6.392f;
1999 } else if (Num_asteroids > 30) {
2000 Game_sound_env.id = SND_ENV_AUDITORIUM;
2001 Game_sound_env.volume = 0.603f;
2002 Game_sound_env.damping = 0.5f;
2003 Game_sound_env.decay = 4.279f;
2006 Game_sound_env = Game_default_sound_env;
2010 Game_sound_env = Game_default_sound_env;
2011 Game_sound_env_update_timestamp = timestamp(1);
2014 // function which gets called before actually entering the mission. It is broken down into a funciton
2015 // since it will get called in one place from a single player game and from another place for
2016 // a multiplayer game
2017 void freespace_mission_load_stuff()
2019 // called if we're not on a freespace dedicated (non rendering, no pilot) server
2020 // IE : we _don't_ want to load any sounds or bitmap/texture info on this machine.
2021 if(!(Game_mode & GM_STANDALONE_SERVER)){
2023 mprintf(( "=================== STARTING LEVEL DATA LOAD ==================\n" ));
2025 game_loading_callback_init();
2027 event_music_level_init(); // preloads the first 2 seconds for each event music track
2030 gamesnd_unload_interface_sounds(); // unload interface sounds from memory
2033 gamesnd_preload_common_sounds(); // load in sounds that are expected to play
2036 ship_assign_sound_all(); // assign engine sounds to ships
2037 game_assign_sound_environment(); // assign the sound environment for this mission
2040 // call function in missionparse.cpp to fixup player/ai stuff.
2041 mission_parse_fixup_players();
2044 // Load in all the bitmaps for this level
2049 game_loading_callback_close();
2051 // the only thing we need to call on the standalone for now.
2053 // call function in missionparse.cpp to fixup player/ai stuff.
2054 mission_parse_fixup_players();
2056 // Load in all the bitmaps for this level
2062 uint load_mission_load;
2063 uint load_post_level_init;
2064 uint load_mission_stuff;
2066 // tells the server to load the mission and initialize structures
2067 int game_start_mission()
2069 mprintf(( "=================== STARTING LEVEL LOAD ==================\n" ));
2071 load_gl_init = time(NULL);
2073 load_gl_init = time(NULL) - load_gl_init;
2075 if (Game_mode & GM_MULTIPLAYER) {
2076 Player->flags |= PLAYER_FLAGS_IS_MULTI;
2078 // clear multiplayer stats
2079 init_multiplayer_stats();
2082 load_mission_load = time(NULL);
2083 if (mission_load()) {
2084 if ( !(Game_mode & GM_MULTIPLAYER) ) {
2085 popup(PF_BODY_BIG, 1, POPUP_OK, XSTR( "Attempt to load the mission failed", 169));
2086 gameseq_post_event(GS_EVENT_MAIN_MENU);
2088 multi_quit_game(PROMPT_NONE, MULTI_END_NOTIFY_NONE, MULTI_END_ERROR_LOAD_FAIL);
2093 load_mission_load = time(NULL) - load_mission_load;
2095 // If this is a red alert mission in campaign mode, bash wingman status
2096 if ( (Game_mode & GM_CAMPAIGN_MODE) && red_alert_mission() ) {
2097 red_alert_bash_wingman_status();
2100 // the standalone server in multiplayer doesn't do any rendering, so we will not even bother loading the palette
2101 if ( !(Game_mode & GM_STANDALONE_SERVER) ) {
2102 mprintf(( "=================== LOADING GAME PALETTE ================\n" ));
2104 game_load_palette();
2108 load_post_level_init = time(NULL);
2109 game_post_level_init();
2110 load_post_level_init = time(NULL) - load_post_level_init;
2114 void Do_model_timings_test();
2115 Do_model_timings_test();
2119 load_mission_stuff = time(NULL);
2120 freespace_mission_load_stuff();
2121 load_mission_stuff = time(NULL) - load_mission_stuff;
2126 int Interface_framerate = 0;
2129 DCF_BOOL( mouse_control, Use_mouse_to_fly )
2130 DCF_BOOL( show_framerate, Show_framerate )
2131 DCF_BOOL( show_target_debug_info, Show_target_debug_info )
2132 DCF_BOOL( show_target_weapons, Show_target_weapons )
2133 DCF_BOOL( lead_target_cheat, Players[Player_num].lead_target_cheat )
2134 DCF_BOOL( sound, Sound_enabled )
2135 DCF_BOOL( zbuffer, game_zbuffer )
2136 DCF_BOOL( shield_system, New_shield_system )
2137 DCF_BOOL( show_shield_mesh, Show_shield_mesh)
2138 DCF_BOOL( player_attacking, Player_attacking_enabled )
2139 DCF_BOOL( show_waypoints, Show_waypoints )
2140 DCF_BOOL( show_area_effect, Show_area_effect )
2141 DCF_BOOL( show_net_stats, Show_net_stats )
2142 DCF_BOOL( log, Log_debug_output_to_file )
2143 DCF_BOOL( training_msg_method, Training_msg_method )
2144 DCF_BOOL( show_player_pos, Show_player_pos )
2145 DCF_BOOL(i_framerate, Interface_framerate )
2147 DCF(show_mem,"Toggles showing mem usage")
2150 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2151 if ( Dc_arg_type & ARG_TRUE ) Show_mem = 1;
2152 else if ( Dc_arg_type & ARG_FALSE ) Show_mem = 0;
2153 else if ( Dc_arg_type & ARG_NONE ) Show_mem ^= 1;
2159 if ( Dc_help ) dc_printf( "Usage: Show_mem\nSets show_mem to true or false. If nothing passed, then toggles it.\n" );
2161 dc_printf( "Show_mem is %s\n", (Show_mem?"TRUE":"FALSE") );
2162 dc_printf( "Show_cpu is %s\n", (Show_cpu?"TRUE":"FALSE") );
2166 DCF(show_cpu,"Toggles showing cpu usage")
2169 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2170 if ( Dc_arg_type & ARG_TRUE ) Show_cpu = 1;
2171 else if ( Dc_arg_type & ARG_FALSE ) Show_cpu = 0;
2172 else if ( Dc_arg_type & ARG_NONE ) Show_cpu ^= 1;
2178 if ( Dc_help ) dc_printf( "Usage: Show_cpu\nSets show_cpu to true or false. If nothing passed, then toggles it.\n" );
2180 dc_printf( "Show_mem is %s\n", (Show_mem?"TRUE":"FALSE") );
2181 dc_printf( "Show_cpu is %s\n", (Show_cpu?"TRUE":"FALSE") );
2188 // AL 4-8-98: always allow players to display their framerate
2191 DCF_BOOL( show_framerate, Show_framerate )
2198 DCF(use_joy_mouse,"Makes joystick move mouse cursor")
2201 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2202 if ( Dc_arg_type & ARG_TRUE ) Use_joy_mouse = 1;
2203 else if ( Dc_arg_type & ARG_FALSE ) Use_joy_mouse = 0;
2204 else if ( Dc_arg_type & ARG_NONE ) Use_joy_mouse ^= 1;
2206 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" );
2207 if ( Dc_status ) dc_printf( "use_joy_mouse is %s\n", (Use_joy_mouse?"TRUE":"FALSE") );
2209 os_config_write_uint( NULL, NOX("JoystickMovesCursor"), Use_joy_mouse );
2212 DCF(palette_flash,"Toggles palette flash effect on/off")
2215 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2216 if ( Dc_arg_type & ARG_TRUE ) Use_palette_flash = 1;
2217 else if ( Dc_arg_type & ARG_FALSE ) Use_palette_flash = 0;
2218 else if ( Dc_arg_type & ARG_NONE ) Use_palette_flash ^= 1;
2220 if ( Dc_help ) dc_printf( "Usage: palette_flash [bool]\nSets palette_flash to true or false. If nothing passed, then toggles it.\n" );
2221 if ( Dc_status ) dc_printf( "palette_flash is %s\n", (Use_palette_flash?"TRUE":"FALSE") );
2224 int Use_low_mem = 0;
2226 DCF(low_mem,"Uses low memory settings regardless of RAM")
2229 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2230 if ( Dc_arg_type & ARG_TRUE ) Use_low_mem = 1;
2231 else if ( Dc_arg_type & ARG_FALSE ) Use_low_mem = 0;
2232 else if ( Dc_arg_type & ARG_NONE ) Use_low_mem ^= 1;
2234 if ( Dc_help ) dc_printf( "Usage: low_mem [bool]\nSets low_mem to true or false. If nothing passed, then toggles it.\n" );
2235 if ( Dc_status ) dc_printf( "low_mem is %s\n", (Use_low_mem?"TRUE":"FALSE") );
2237 os_config_write_uint( NULL, NOX("LowMem"), Use_low_mem );
2243 DCF(force_fullscreen, "Forces game to startup in fullscreen mode")
2246 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2247 if ( Dc_arg_type & ARG_TRUE ) Use_fullscreen_at_startup = 1;
2248 else if ( Dc_arg_type & ARG_FALSE ) Use_fullscreen_at_startup = 0;
2249 else if ( Dc_arg_type & ARG_NONE ) Use_fullscreen_at_startup ^= 1;
2251 if ( Dc_help ) dc_printf( "Usage: force_fullscreen [bool]\nSets force_fullscreen to true or false. If nothing passed, then toggles it.\n" );
2252 if ( Dc_status ) dc_printf( "force_fullscreen is %s\n", (Use_fullscreen_at_startup?"TRUE":"FALSE") );
2253 os_config_write_uint( NULL, NOX("ForceFullscreen"), Use_fullscreen_at_startup );
2257 int Framerate_delay = 0;
2259 float Freespace_gamma = 1.0f;
2261 DCF(gamma,"Sets Gamma factor")
2264 dc_get_arg(ARG_FLOAT|ARG_NONE);
2265 if ( Dc_arg_type & ARG_FLOAT ) {
2266 Freespace_gamma = Dc_arg_float;
2268 dc_printf( "Gamma reset to 1.0f\n" );
2269 Freespace_gamma = 1.0f;
2271 if ( Freespace_gamma < 0.1f ) {
2272 Freespace_gamma = 0.1f;
2273 } else if ( Freespace_gamma > 5.0f ) {
2274 Freespace_gamma = 5.0f;
2276 gr_set_gamma(Freespace_gamma);
2278 char tmp_gamma_string[32];
2279 sprintf( tmp_gamma_string, NOX("%.2f"), Freespace_gamma );
2280 os_config_write_string( NULL, NOX("Gamma"), tmp_gamma_string );
2284 dc_printf( "Usage: gamma <float>\n" );
2285 dc_printf( "Sets gamma in range 1-3, no argument resets to default 1.2\n" );
2286 Dc_status = 0; // don't print status if help is printed. Too messy.
2290 dc_printf( "Gamma = %.2f\n", Freespace_gamma );
2299 Game_current_mission_filename[0] = 0;
2301 // seed the random number generator
2302 Game_init_seed = time(NULL);
2303 srand( Game_init_seed );
2305 Framerate_delay = 0;
2311 extern void bm_init();
2317 // Initialize the timer before the os
2323 //Initialize the libraries
2324 s1 = timer_get_milliseconds();
2325 if ( cfile_init() ) { // initialize before calling any cfopen stuff!!!
2328 e1 = timer_get_milliseconds();
2330 // time a bunch of cfopens
2332 s2 = timer_get_milliseconds();
2334 for(int idx=0; idx<10000; idx++){
2335 whee = cfopen("capital01.pof", "rb", CFILE_NORMAL, CF_TYPE_MODELS);
2340 //cf_exist("capital01.pof", CF_TYPE_MODELS);
2342 e2 = timer_get_milliseconds();
2345 if (Is_standalone) {
2346 std_init_standalone();
2348 os_init( Osreg_class_name, Osreg_app_name );
2349 os_set_title(Osreg_title);
2352 // initialize localization module. Make sure this is down AFTER initialzing OS.
2353 // int t1 = timer_get_milliseconds();
2354 lcl_init( detect_lang() );
2356 // mprintf(("LCL_INIT() TOOK %d MS\n", timer_get_milliseconds()-t1));
2358 // verify that he has a valid ships.tbl (will Game_ships_tbl_valid if so)
2361 // verify that he has a valid weapons.tbl
2362 verify_weapons_tbl();
2364 // Output version numbers to registry for auto patching purposes
2365 os_config_write_uint(NOX("Version"), NOX("Major"), FS_VERSION_MAJOR);
2366 os_config_write_uint(NOX("Version"), NOX("Minor"), FS_VERSION_MINOR);
2367 os_config_write_uint(NOX("Version"), NOX("Build"), FS_VERSION_BUILD);
2369 Use_joy_mouse = 0; //os_config_read_uint( NULL, NOX("JoystickMovesCursor"), 1 );
2370 //Use_palette_flash = os_config_read_uint( NULL, NOX("PaletteFlash"), 0 );
2371 Use_low_mem = os_config_read_uint( NULL, NOX("LowMem"), 0 );
2374 Use_fullscreen_at_startup = os_config_read_uint( NULL, NOX("ForceFullscreen"), 1 );
2377 #if defined (PLAT_UNIX) && defined(RELEASE_REAL)
2378 // show the FPS counter if the config file says so
2379 Show_framerate = os_config_read_uint( NULL, NOX("ShowFPS"), 0 );
2382 #if !(defined(FS2_DEMO) || defined(FS1_DEMO))
2383 Asteroids_enabled = 1;
2386 /////////////////////////////
2388 /////////////////////////////
2392 ptr = os_config_read_string(NULL, NOX("Soundcard"), NULL);
2393 mprintf(("soundcard = %s\n", ptr ? ptr : "<nothing>"));
2395 if (!SDL_strcasecmp(ptr, NOX("no sound"))) {
2396 Cmdline_freespace_no_sound = 1;
2397 } else if ( !SDL_strcasecmp(ptr, NOX("EAX")) || !SDL_strcasecmp(ptr, NOX("Aureal A3D")) ) {
2402 if (!Is_standalone) {
2405 /////////////////////////////
2407 /////////////////////////////
2409 ptr = os_config_read_string(NULL, NOX("Videocard"), NULL);
2412 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);
2414 // fire up the UpdateLauncher executable
2416 PROCESS_INFORMATION pi;
2418 memset( &si, 0, sizeof(STARTUPINFO) );
2421 BOOL ret = CreateProcess( LAUNCHER_FNAME, // pointer to name of executable module
2422 NULL, // pointer to command line string
2423 NULL, // pointer to process security attributes
2424 NULL, // pointer to thread security attributes
2425 FALSE, // handle inheritance flag
2426 CREATE_DEFAULT_ERROR_MODE, // creation flags
2427 NULL, // pointer to new environment block
2428 NULL, // pointer to current directory name
2429 &si, // pointer to STARTUPINFO
2430 &pi // pointer to PROCESS_INFORMATION
2433 // If the Launcher could not be started up, let the user know
2435 MessageBox((HWND)os_get_window(), XSTR("The Launcher could not be restarted.", 1450), XSTR("Error", 1451), MB_OK);
2444 if(!SDL_strcasecmp(ptr, "Aucune acc�l�ration 3D") || !SDL_strcasecmp(ptr, "Keine 3D-Beschleunigerkarte") || !SDL_strcasecmp(ptr, "No 3D acceleration")){
2446 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);
2454 // check for hi res pack file
2455 int has_sparky_hi = 0;
2457 // check if sparky_hi exists -- access mode 0 means does file exist
2458 #ifndef MAKE_FS1 // shoudn't have it so don't check
2461 if ( _access("sparky_hi_fs2.vp", 0) == 0) {
2464 mprintf(("No sparky_hi_fs2.vp in directory %s\n", dir));
2468 // see if we've got 32 bit in the string
2469 if(strstr(ptr, "32 bit")){
2476 if (!Is_standalone && ptr && (strstr(ptr, NOX("3DFX Glide")))) {
2478 // always 640 for E3
2479 gr_init(GR_640, GR_GLIDE);
2481 // regular or hi-res ?
2483 if(has_sparky_hi && strstr(ptr, NOX("(1024x768)"))){
2485 if(strstr(ptr, NOX("(1024x768)"))){
2487 gr_init(GR_1024, GR_GLIDE);
2489 gr_init(GR_640, GR_GLIDE);
2492 } else if (!Is_standalone && ptr && (strstr(ptr, NOX("Direct 3D -") ))) {
2494 // always 640 for E3
2496 gr_init(GR_640, GR_DIRECT3D, depth);
2498 // regular or hi-res ?
2500 if(has_sparky_hi && strstr(ptr, NOX("(1024x768)"))){
2502 if(strstr(ptr, NOX("(1024x768)"))){
2506 gr_init(GR_1024, GR_DIRECT3D, depth);
2510 gr_init(GR_640, GR_DIRECT3D, depth);
2516 if ( Use_fullscreen_at_startup && !Is_standalone) {
2517 gr_init(GR_640, GR_DIRECTDRAW);
2519 gr_init(GR_640, GR_SOFTWARE);
2522 if ( !Is_standalone ) {
2523 gr_init(GR_640, GR_DIRECTDRAW);
2525 gr_init(GR_640, GR_SOFTWARE);
2530 if (!Is_standalone /* && ptr && (strstr(ptr, NOX("OpenGL"))) */) {
2531 if(has_sparky_hi && strstr(ptr, NOX("(1024x768)"))){
2532 gr_init(GR_1024, GR_OPENGL);
2534 gr_init(GR_640, GR_OPENGL);
2538 gr_init(GR_640, GR_SDL);
2540 #endif // !PLAT_UNIX
2543 extern int Gr_inited;
2544 if(trying_d3d && !Gr_inited){
2546 extern char Device_init_error[512];
2547 MessageBox( NULL, Device_init_error, "Error intializing Direct3D", MB_OK|MB_TASKMODAL|MB_SETFOREGROUND );
2556 ptr = os_config_read_string(NULL,NOX("Gamma"),NOX("1.80"));
2557 Freespace_gamma = (float)atof(ptr);
2558 if ( Freespace_gamma == 0.0f ) {
2559 Freespace_gamma = 1.80f;
2560 } else if ( Freespace_gamma < 0.1f ) {
2561 Freespace_gamma = 0.1f;
2562 } else if ( Freespace_gamma > 5.0f ) {
2563 Freespace_gamma = 5.0f;
2565 char tmp_gamma_string[32];
2566 sprintf( tmp_gamma_string, NOX("%.2f"), Freespace_gamma );
2567 os_config_write_string( NULL, NOX("Gamma"), tmp_gamma_string );
2569 gr_set_gamma(Freespace_gamma);
2571 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
2574 display_title_screen();
2578 // attempt to load up master tracker registry info (login and password)
2579 Multi_tracker_id = -1;
2581 // pxo login and password
2582 ptr = os_config_read_string(NOX("PXO"),NOX("Login"),NULL);
2584 nprintf(("Network","Error reading in PXO login data\n"));
2585 strcpy(Multi_tracker_login,"");
2587 strcpy(Multi_tracker_login,ptr);
2589 ptr = os_config_read_string(NOX("PXO"),NOX("Password"),NULL);
2591 nprintf(("Network","Error reading PXO password\n"));
2592 strcpy(Multi_tracker_passwd,"");
2594 strcpy(Multi_tracker_passwd,ptr);
2597 // pxo squad name and password
2598 ptr = os_config_read_string(NOX("PXO"),NOX("SquadName"),NULL);
2600 nprintf(("Network","Error reading in PXO squad name\n"));
2601 strcpy(Multi_tracker_squad_name, "");
2603 strcpy(Multi_tracker_squad_name, ptr);
2606 // If less than 48MB of RAM, use low memory model.
2607 if ( (Freespace_total_ram < 48) || Use_low_mem ) {
2608 mprintf(( "Using normal memory settings...\n" ));
2609 bm_set_low_mem(1); // Use every other frame of bitmaps
2611 mprintf(( "Using high memory settings...\n" ));
2612 bm_set_low_mem(0); // Use all frames of bitmaps
2615 // load non-darkening pixel defs
2616 palman_load_pixels();
2618 // hud shield icon stuff
2619 hud_shield_game_init();
2621 control_config_common_init(); // sets up localization stuff in the control config
2627 gamesnd_parse_soundstbl();
2632 // standalone's don't use hte joystick and it seems to sometimes cause them to not get shutdown properly
2637 player_controls_init();
2640 //if(!Is_standalone){
2648 ship_init(); // read in ships.tbl
2650 mission_campaign_init(); // load in the default campaign
2652 // navmap_init(); // init the navigation map system
2653 context_help_init();
2654 techroom_intel_init(); // parse species.tbl, load intel info
2656 psnet_init( Multi_options_g.protocol, Multi_options_g.port ); // initialize the networking code
2657 init_animating_pointer();
2659 mission_brief_common_init(); // Mark all the briefing structures as empty.
2660 gr_font_init(); // loads up all fonts
2662 neb2_init(); // fullneb stuff
2666 player_tips_init(); // helpful tips
2669 // load the list of pilot pic filenames (for barracks and pilot select popup quick reference)
2670 pilot_load_pic_list();
2671 pilot_load_squad_pic_list();
2673 load_animating_pointer(NOX("cursor"), 0, 0);
2675 // initialize alpha colors
2676 alpha_colors_init();
2679 // Game_music_paused = 0;
2686 nprintf(("General", "Ships.tbl is : %s\n", Game_ships_tbl_valid ? "VALID" : "INVALID!!!!"));
2687 nprintf(("General", "Weapons.tbl is : %s\n", Game_weapons_tbl_valid ? "VALID" : "INVALID!!!!"));
2689 mprintf(("cfile_init() took %d\n", e1 - s1));
2690 // mprintf(("1000 cfopens() took %d\n", e2 - s2));
2693 char transfer_text[128];
2695 float Start_time = 0.0f;
2697 float Framerate = 0.0f;
2699 float Timing_total = 0.0f;
2700 float Timing_render2 = 0.0f;
2701 float Timing_render3 = 0.0f;
2702 float Timing_flip = 0.0f;
2703 float Timing_clear = 0.0f;
2705 MONITOR(NumPolysDrawn);
2711 void game_get_framerate()
2713 char text[128] = "";
2715 if ( frame_int == -1 ) {
2717 for (i=0; i<FRAME_FILTER; i++ ) {
2718 frametimes[i] = 0.0f;
2723 frametotal -= frametimes[frame_int];
2724 frametotal += flFrametime;
2725 frametimes[frame_int] = flFrametime;
2726 frame_int = (frame_int + 1 ) % FRAME_FILTER;
2728 if ( frametotal != 0.0 ) {
2729 if ( Framecount >= FRAME_FILTER )
2730 Framerate = FRAME_FILTER / frametotal;
2732 Framerate = Framecount / frametotal;
2733 sprintf( text, NOX("FPS: %.1f"), Framerate );
2735 sprintf( text, NOX("FPS: ?") );
2739 if (Show_framerate) {
2740 gr_set_color_fast(&HUD_color_debug);
2741 gr_string( 570, 2, text );
2745 void game_show_framerate()
2749 cur_time = f2fl(timer_get_approx_seconds());
2750 if (cur_time - Start_time > 30.0f) {
2751 mprintf(("%i frames executed in %7.3f seconds, %7.3f frames per second.\n", Framecount, cur_time - Start_time, Framecount/(cur_time - Start_time)));
2752 Start_time += 1000.0f;
2755 //mprintf(( "%s\n", text ));
2758 if ( Debug_dump_frames )
2762 // possibly show control checking info
2763 control_check_indicate();
2765 // int bitmaps_used_this_frame, bitmaps_new_this_frame;
2766 // bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
2767 // MONITOR_INC(BmpUsed, bitmaps_used_this_frame);
2768 // MONITOR_INC(BmpNew, bitmaps_new_this_frame);
2771 if ( Show_cpu == 1 ) {
2776 dy = gr_get_font_height() + 1;
2778 gr_set_color_fast(&HUD_color_debug);
2782 extern int D3D_textures_in;
2783 extern int D3D_textures_in_frame;
2784 extern int Glide_textures_in;
2785 extern int Glide_textures_in_frame;
2786 extern int Glide_explosion_vram;
2787 gr_printf( sx, sy, NOX("VRAM: %d KB\n"), (D3D_textures_in+Glide_textures_in)/1024 );
2789 gr_printf( sx, sy, NOX("VRAM: +%d KB\n"), (Glide_textures_in_frame+D3D_textures_in_frame)/1024 );
2791 gr_printf( sx, sy, NOX("EXP VRAM: %dKB\n"), (Glide_explosion_vram)/1024 );
2795 // gr_printf( sx, sy, "BPP: %d", gr_screen.bits_per_pixel );
2797 gr_printf( sx, sy, NOX("DMA: %s"), transfer_text );
2799 gr_printf( sx, sy, NOX("POLYP: %d"), modelstats_num_polys );
2801 gr_printf( sx, sy, NOX("POLYD: %d"), modelstats_num_polys_drawn );
2803 gr_printf( sx, sy, NOX("VERTS: %d"), modelstats_num_verts );
2808 extern int Num_pairs; // Number of object pairs that were checked.
2809 gr_printf( sx, sy, NOX("PAIRS: %d"), Num_pairs );
2812 extern int Num_pairs_checked; // What percent of object pairs were checked.
2813 gr_printf( sx, sy, NOX("FVI: %d"), Num_pairs_checked );
2815 Num_pairs_checked = 0;
2819 gr_printf( sx, sy, NOX("Snds: %d"), snd_num_playing() );
2822 if ( Timing_total > 0.01f ) {
2823 gr_printf( sx, sy, NOX("CLEAR: %.0f%%"), Timing_clear*100.0f/Timing_total );
2825 gr_printf( sx, sy, NOX("REND2D: %.0f%%"), Timing_render2*100.0f/Timing_total );
2827 gr_printf( sx, sy, NOX("REND3D: %.0f%%"), Timing_render3*100.0f/Timing_total );
2829 gr_printf( sx, sy, NOX("FLIP: %.0f%%"), Timing_flip*100.0f/Timing_total );
2831 gr_printf( sx, sy, NOX("GAME: %.0f%%"), (Timing_total-(Timing_render2+Timing_render3+Timing_flip+Timing_clear))*100.0f/Timing_total );
2841 dy = gr_get_font_height() + 1;
2843 gr_set_color_fast(&HUD_color_debug);
2846 extern int TotalRam;
2847 gr_printf( sx, sy, NOX("DYN: %d KB\n"), TotalRam/1024 );
2852 extern int Model_ram;
2853 gr_printf( sx, sy, NOX("POF: %d KB\n"), Model_ram/1024 );
2857 gr_printf( sx, sy, NOX("BMP: %d KB\n"), bm_texture_ram/1024 );
2859 gr_printf( sx, sy, NOX("S-SRAM: %d KB\n"), Snd_sram/1024 ); // mem used to store game sound
2862 gr_printf( sx, sy, NOX("S-HRAM: %d KB\n"), Snd_hram/1024 ); // mem used to store game sound
2865 extern int D3D_textures_in;
2866 extern int Glide_textures_in;
2867 extern int Glide_textures_in_frame;
2868 extern int Glide_explosion_vram;
2869 gr_printf( sx, sy, NOX("VRAM: %d KB\n"), (D3D_textures_in+Glide_textures_in)/1024 );
2871 gr_printf( sx, sy, NOX("VRAM: +%d KB\n"), (Glide_textures_in_frame)/1024 );
2873 gr_printf( sx, sy, NOX("EXP VRAM: %dKB\n"), (Glide_explosion_vram)/1024 );
2877 extern int GL_textures_in;
2878 gr_printf( sx, sy, NOX("VRAM: %d KB\n"), (GL_textures_in)/1024 );
2885 if ( Show_player_pos ) {
2889 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));
2892 MONITOR_INC(NumPolys, modelstats_num_polys);
2893 MONITOR_INC(NumPolysDrawn, modelstats_num_polys_drawn );
2894 MONITOR_INC(NumVerts, modelstats_num_verts );
2896 modelstats_num_polys = 0;
2897 modelstats_num_polys_drawn = 0;
2898 modelstats_num_verts = 0;
2899 modelstats_num_sortnorms = 0;
2903 void game_show_standalone_framerate()
2905 float frame_rate=30.0f;
2906 if ( frame_int == -1 ) {
2908 for (i=0; i<FRAME_FILTER; i++ ) {
2909 frametimes[i] = 0.0f;
2914 frametotal -= frametimes[frame_int];
2915 frametotal += flFrametime;
2916 frametimes[frame_int] = flFrametime;
2917 frame_int = (frame_int + 1 ) % FRAME_FILTER;
2919 if ( frametotal != 0.0 ) {
2920 if ( Framecount >= FRAME_FILTER ){
2921 frame_rate = FRAME_FILTER / frametotal;
2923 frame_rate = Framecount / frametotal;
2926 std_set_standalone_fps(frame_rate);
2930 // function to show the time remaining in a mission. Used only when the end-mission sexpression is used
2931 void game_show_time_left()
2935 // mission_end_time is a global from missionparse.cpp that contains the mission time at which the
2936 // mission should end (in fixed seconds). There is code in missionparse.cpp which actually handles
2937 // checking how much time is left
2939 if ( Mission_end_time == -1 ){
2943 diff = f2i(Mission_end_time - Missiontime);
2944 // be sure to bash to 0. diff could be negative on frame that we quit mission
2949 hud_set_default_color();
2950 gr_printf( 5, 40, XSTR( "Mission time remaining: %d seconds", 179), diff );
2953 //========================================================================================
2954 //=================== NEW DEBUG CONSOLE COMMANDS TO REPLACE OLD DEBUG PAUSE MENU =========
2955 //========================================================================================
2959 DCF(ai_pause,"Pauses ai")
2962 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2963 if ( Dc_arg_type & ARG_TRUE ) ai_paused = 1;
2964 else if ( Dc_arg_type & ARG_FALSE ) ai_paused = 0;
2965 else if ( Dc_arg_type & ARG_NONE ) ai_paused = !ai_paused;
2968 obj_init_all_ships_physics();
2971 if ( Dc_help ) dc_printf( "Usage: ai_paused [bool]\nSets ai_paused to true or false. If nothing passed, then toggles it.\n" );
2972 if ( Dc_status ) dc_printf( "ai_paused is %s\n", (ai_paused?"TRUE":"FALSE") );
2975 DCF(single_step,"Single steps the game")
2978 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2979 if ( Dc_arg_type & ARG_TRUE ) game_single_step = 1;
2980 else if ( Dc_arg_type & ARG_FALSE ) game_single_step = 0;
2981 else if ( Dc_arg_type & ARG_NONE ) game_single_step = !game_single_step;
2983 last_single_step = 0; // Make so single step waits a frame before stepping
2986 if ( Dc_help ) dc_printf( "Usage: single_step [bool]\nSets single_step to true or false. If nothing passed, then toggles it.\n" );
2987 if ( Dc_status ) dc_printf( "single_step is %s\n", (game_single_step?"TRUE":"FALSE") );
2990 DCF_BOOL(physics_pause, physics_paused)
2991 DCF_BOOL(ai_rendering, Ai_render_debug_flag)
2992 DCF_BOOL(ai_firing, Ai_firing_enabled )
2994 // Create some simple aliases to these commands...
2995 debug_command dc_s("s","shortcut for single_step",dcf_single_step);
2996 debug_command dc_p("p","shortcut for physics_pause", dcf_physics_pause );
2997 debug_command dc_r("r","shortcut for ai_rendering", dcf_ai_rendering );
2998 debug_command dc_f("f","shortcut for ai_firing", dcf_ai_firing);
2999 debug_command dc_a("a","shortcut for ai_pause", dcf_ai_pause);
3002 //========================================================================================
3003 //========================================================================================
3006 void game_training_pause_do()
3010 key = game_check_key();
3012 gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
3019 void game_increase_skill_level()
3022 if (Game_skill_level >= NUM_SKILL_LEVELS){
3023 Game_skill_level = 0;
3027 int Player_died_time;
3029 int View_percent = 100;
3032 DCF(view, "Sets the percent of the 3d view to render.")
3035 dc_get_arg(ARG_INT);
3036 if ( (Dc_arg_int >= 5 ) || (Dc_arg_int <= 100) ) {
3037 View_percent = Dc_arg_int;
3039 dc_printf( "Illegal value for view. (Must be from 5-100) \n\n");
3045 dc_printf("Usage: view [n]\nwhere n is percent of view to show (5-100).\n");
3049 dc_printf("View is set to %d%%\n", View_percent );
3054 // Set the clip region for the 3d rendering window
3055 void game_set_view_clip()
3057 if ((Game_mode & GM_DEAD) || (supernova_active() >= 2)) {
3058 // Set the clip region for the letterbox "dead view"
3059 int yborder = gr_screen.max_h/4;
3061 // Numeric constants encouraged by J "pig farmer" S, who shall remain semi-anonymous.
3062 // J.S. I've changed my ways!! See the new "no constants" code!!!
3063 gr_set_clip(0, yborder, gr_screen.max_w, gr_screen.max_h - yborder*2 );
3065 // Set the clip region for normal view
3066 if ( View_percent >= 100 ) {
3069 int xborder, yborder;
3071 if ( View_percent < 5 ) {
3075 float fp = i2fl(View_percent)/100.0f;
3076 int fi = fl2i(fl_sqrt(fp)*100.0f);
3077 if ( fi > 100 ) fi=100;
3079 xborder = ( gr_screen.max_w*(100-fi) )/200;
3080 yborder = ( gr_screen.max_h*(100-fi) )/200;
3082 gr_set_clip(xborder, yborder, gr_screen.max_w-xborder*2,gr_screen.max_h-yborder*2 );
3088 void show_debug_stuff()
3091 int laser_count = 0, missile_count = 0;
3093 for (i=0; i<MAX_OBJECTS; i++) {
3094 if (Objects[i].type == OBJ_WEAPON){
3095 if (Weapon_info[Weapons[Objects[i].instance].weapon_info_index].subtype == WP_LASER){
3097 } else if (Weapon_info[Weapons[Objects[i].instance].weapon_info_index].subtype == WP_MISSILE){
3103 nprintf(("Mike", "Frame: %i Lasers: %4i, Missiles: %4i\n", Framecount, laser_count, missile_count));
3106 extern int Tool_enabled;
3111 int tst_bitmap = -1;
3113 float tst_offset, tst_offset_total;
3116 void game_tst_frame_pre()
3124 g3_rotate_vertex(&v, &tst_pos);
3125 g3_project_vertex(&v);
3128 if(!((v.sx >= 0) && (v.sx <= gr_screen.max_w) && (v.sy >= 0) && (v.sy <= gr_screen.max_h))){
3132 // big ship? always tst
3134 // within 3000 meters
3135 if( vm_vec_dist_quick(&tst_pos, &Eye_position) <= 3000.0f){
3139 // within 300 meters
3140 if( (vm_vec_dist_quick(&tst_pos, &Eye_position) <= 300.0f) && ((tst_time == 0) || ((time(NULL) - tst_time) >= 10)) ){
3147 void game_tst_frame()
3157 tst_time = time(NULL);
3159 // load the tst bitmap
3160 switch((int)frand_range(0.0f, 3.0)){
3162 tst_bitmap = bm_load("ig_jim");
3164 mprintf(("TST 0\n"));
3168 tst_bitmap = bm_load("ig_kan");
3170 mprintf(("TST 1\n"));
3174 tst_bitmap = bm_load("ig_jim");
3176 mprintf(("TST 2\n"));
3180 tst_bitmap = bm_load("ig_kan");
3182 mprintf(("TST 3\n"));
3191 // get the tst bitmap dimensions
3193 bm_get_info(tst_bitmap, &w, &h);
3196 tst_y = frand_range(0.0f, (float)gr_screen.max_h - h);
3198 snd_play(&Snds[SND_VASUDAN_BUP]);
3200 // tst x and direction
3204 tst_offset_total = (float)w;
3205 tst_offset = (float)w;
3207 tst_x = (float)gr_screen.max_w;
3208 tst_offset_total = (float)-w;
3209 tst_offset = (float)w;
3217 float diff = (tst_offset_total / 0.5f) * flFrametime;
3223 tst_offset -= fl_abs(diff);
3224 } else if(tst_mode == 2){
3227 tst_offset -= fl_abs(diff);
3231 gr_set_bitmap(tst_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
3232 gr_bitmap((int)tst_x, (int)tst_y);
3235 if(timestamp_elapsed_safe(tst_stamp, 1100)){
3239 // if we passed the switch point
3240 if(tst_offset <= 0.0f){
3245 tst_stamp = timestamp(1000);
3246 tst_offset = fl_abs(tst_offset_total);
3257 void game_tst_mark(object *objp, ship *shipp)
3266 if((objp == NULL) || (shipp == NULL) || (shipp->ship_info_index < 0) || (shipp->ship_info_index >= Num_ship_types)){
3269 sip = &Ship_info[shipp->ship_info_index];
3276 tst_pos = objp->pos;
3277 if(sip->flags & (SIF_BIG_SHIP | SIF_HUGE_SHIP)){
3283 extern void render_shields();
3285 void player_repair_frame(float frametime)
3287 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
3289 for(idx=0;idx<MAX_PLAYERS;idx++){
3292 np = &Net_players[idx];
3294 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)){
3296 // don't rearm/repair if the player is dead or dying/departing
3297 if ( !NETPLAYER_IS_DEAD(np) && !(Ships[Objects[np->player->objnum].instance].flags & (SF_DYING|SF_DEPARTING)) ) {
3298 ai_do_repair_frame(&Objects[Net_players[idx].player->objnum],&Ai_info[Ships[Objects[Net_players[idx].player->objnum].instance].ai_index],frametime);
3303 if ( (Player_obj != NULL) && (Player_obj->type == OBJ_SHIP) && !(Game_mode & GM_STANDALONE_SERVER) && (Player_ship != NULL) && !(Player_ship->flags & SF_DYING) ) {
3304 ai_do_repair_frame(Player_obj, &Ai_info[Ships[Player_obj->instance].ai_index], frametime);
3310 #define NUM_FRAMES_TEST 300
3311 #define NUM_MIXED_SOUNDS 16
3312 void do_timing_test(float flFrametime)
3314 static int framecount = 0;
3315 static int test_running = 0;
3316 static float test_time = 0.0f;
3318 static int snds[NUM_MIXED_SOUNDS];
3321 if ( test_running ) {
3323 test_time += flFrametime;
3324 if ( framecount >= NUM_FRAMES_TEST ) {
3326 nprintf(("General", "%d frames took %.3f seconds\n", NUM_FRAMES_TEST, test_time));
3327 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3332 if ( Test_begin == 1 ) {
3338 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3341 // start looping digital sounds
3342 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3343 snds[i] = snd_play_looping( &Snds[i], 0.0f);
3350 DCF(dcf_fov, "Change the field of view")
3353 dc_get_arg(ARG_FLOAT|ARG_NONE);
3354 if ( Dc_arg_type & ARG_NONE ) {
3355 Viewer_zoom = VIEWER_ZOOM_DEFAULT;
3356 dc_printf( "Zoom factor reset\n" );
3358 if ( Dc_arg_type & ARG_FLOAT ) {
3359 if (Dc_arg_float < 0.25f) {
3360 Viewer_zoom = 0.25f;
3361 dc_printf("Zoom factor pinned at 0.25.\n");
3362 } else if (Dc_arg_float > 1.25f) {
3363 Viewer_zoom = 1.25f;
3364 dc_printf("Zoom factor pinned at 1.25.\n");
3366 Viewer_zoom = Dc_arg_float;
3372 dc_printf( "Usage: fov [factor]\nFactor is the zoom factor btwn .25 and 1.25\nNo parameter resets it to default.\n" );
3375 dc_printf("Zoom factor set to %6.3f (original = 0.5, John = 0.75)", Viewer_zoom);
3379 DCF(framerate_cap, "Sets the framerate cap")
3382 dc_get_arg(ARG_INT);
3383 if ( (Dc_arg_int >= 1 ) || (Dc_arg_int <= 120) ) {
3384 Framerate_cap = Dc_arg_int;
3386 dc_printf( "Illegal value for framerate cap. (Must be from 1-120) \n\n");
3392 dc_printf("Usage: framerate_cap [n]\nwhere n is the frames per second to cap framerate at.\n");
3393 dc_printf("If n is 0 or omitted, then the framerate cap is removed\n");
3394 dc_printf("[n] must be from 1 to 120.\n");
3398 if ( Framerate_cap )
3399 dc_printf("Framerate cap is set to %d fps\n", Framerate_cap );
3401 dc_printf("There is no framerate cap currently active.\n");
3405 #define MIN_DIST_TO_DEAD_CAMERA 50.0f
3406 int Show_viewing_from_self = 0;
3408 void say_view_target()
3410 object *view_target;
3412 if ((Viewer_mode & VM_OTHER_SHIP) && (Player_ai->target_objnum != -1))
3413 view_target = &Objects[Player_ai->target_objnum];
3415 view_target = Player_obj;
3417 if (Game_mode & GM_DEAD) {
3418 if (Player_ai->target_objnum != -1)
3419 view_target = &Objects[Player_ai->target_objnum];
3422 if (!(Game_mode & GM_DEAD_DIED) && ((Game_mode & (GM_DEAD_BLEW_UP)) || ((Last_view_target != NULL) && (Last_view_target != view_target)))) {
3423 if (view_target != Player_obj){
3425 char *view_target_name = NULL;
3426 switch(Objects[Player_ai->target_objnum].type) {
3428 view_target_name = Ships[Objects[Player_ai->target_objnum].instance].ship_name;
3431 view_target_name = Weapon_info[Weapons[Objects[Player_ai->target_objnum].instance].weapon_info_index].name;
3432 Viewer_mode &= ~VM_OTHER_SHIP;
3434 case OBJ_JUMP_NODE: {
3435 char jump_node_name[128];
3436 strcpy(jump_node_name, XSTR( "jump node", 184));
3437 view_target_name = jump_node_name;
3438 Viewer_mode &= ~VM_OTHER_SHIP;
3447 if ( view_target_name ) {
3448 HUD_fixed_printf(0.0f, XSTR( "Viewing %s%s\n", 185), (Viewer_mode & VM_OTHER_SHIP) ? XSTR( "from ", 186) : "", view_target_name);
3449 Show_viewing_from_self = 1;
3452 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER) && (Player_obj->type == OBJ_OBSERVER)){
3453 HUD_fixed_printf(2.0f,XSTR( "Viewing from observer\n", 187));
3454 Show_viewing_from_self = 1;
3456 if (Show_viewing_from_self)
3457 HUD_fixed_printf(2.0f, XSTR( "Viewing from self\n", 188));
3462 Last_view_target = view_target;
3466 float Game_hit_x = 0.0f;
3467 float Game_hit_y = 0.0f;
3469 // Reset at the beginning of each frame
3470 void game_whack_reset()
3476 // Apply a 2d whack to the player
3477 void game_whack_apply( float x, float y )
3479 // Do some force feedback
3480 joy_ff_play_dir_effect(x * 80.0f, y * 80.0f);
3486 // mprintf(( "WHACK = %.1f, %.1f\n", Game_hit_x, Game_hit_y ));
3489 // call to apply a "shudder"
3490 void game_shudder_apply(int time, float intensity)
3492 Game_shudder_time = timestamp(time);
3493 Game_shudder_total = time;
3494 Game_shudder_intensity = intensity;
3497 #define FF_SCALE 10000
3498 void apply_hud_shake(matrix *eye_orient)
3500 if (Viewer_obj == Player_obj) {
3501 physics_info *pi = &Player_obj->phys_info;
3509 // Make eye shake due to afterburner
3510 if ( !timestamp_elapsed(pi->afterburner_decay) ) {
3513 dtime = timestamp_until(pi->afterburner_decay);
3517 tangles.p += 0.07f * (float) (r1-MY_RAND_MAX/2)/MY_RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/ABURN_DECAY_TIME));
3518 tangles.h += 0.07f * (float) (r2-MY_RAND_MAX/2)/MY_RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/ABURN_DECAY_TIME));
3521 // Make eye shake due to engine wash
3523 if (Player_obj->type == OBJ_SHIP && (Ships[Player_obj->instance].wash_intensity > 0) && Wash_on ) {
3526 tangles.p += 0.07f * Ships[Player_obj->instance].wash_intensity * (float) (r1-MY_RAND_MAX/2)/MY_RAND_MAX;
3527 tangles.h += 0.07f * Ships[Player_obj->instance].wash_intensity * (float) (r2-MY_RAND_MAX/2)/MY_RAND_MAX;
3529 // get the intensity
3530 float intensity = FF_SCALE * Ships[Player_obj->instance].wash_intensity;
3534 vm_vec_rand_vec_quick(&rand_vec);
3537 joy_ff_play_dir_effect(intensity*rand_vec.xyz.x, intensity*rand_vec.xyz.y);
3541 // make hud shake due to shuddering
3542 if(Game_shudder_time != -1){
3543 // if the timestamp has elapsed
3544 if(timestamp_elapsed(Game_shudder_time)){
3545 Game_shudder_time = -1;
3547 // otherwise apply some shudder
3551 dtime = timestamp_until(Game_shudder_time);
3555 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));
3556 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));
3561 vm_angles_2_matrix(&tm, &tangles);
3562 SDL_assert(vm_vec_mag(&tm.v.fvec) > 0.0f);
3563 SDL_assert(vm_vec_mag(&tm.v.rvec) > 0.0f);
3564 SDL_assert(vm_vec_mag(&tm.v.uvec) > 0.0f);
3565 vm_matrix_x_matrix(&tm2, eye_orient, &tm);
3570 extern void compute_slew_matrix(matrix *orient, angles *a); // TODO: move code to proper place and extern in header file
3572 // Player's velocity just before he blew up. Used to keep camera target moving.
3573 vector Dead_player_last_vel = { { { 1.0f, 1.0f, 1.0f } } };
3575 // Set eye_pos and eye_orient based on view mode.
3576 void game_render_frame_setup(vector *eye_pos, matrix *eye_orient)
3580 static int last_Viewer_mode = 0;
3581 static int last_Game_mode = 0;
3582 static int last_Viewer_objnum = -1;
3584 // This code is supposed to detect camera "cuts"... like going between
3587 // determine if we need to regenerate the nebula
3588 if( (!(last_Viewer_mode & VM_EXTERNAL) && (Viewer_mode & VM_EXTERNAL)) || // internal to external
3589 ((last_Viewer_mode & VM_EXTERNAL) && !(Viewer_mode & VM_EXTERNAL)) || // external to internal
3590 (!(last_Viewer_mode & VM_DEAD_VIEW) && (Viewer_mode & VM_DEAD_VIEW)) || // non dead-view to dead-view
3591 ((last_Viewer_mode & VM_DEAD_VIEW) && !(Viewer_mode & VM_DEAD_VIEW)) || // dead-view to non dead-view
3592 (!(last_Viewer_mode & VM_WARP_CHASE) && (Viewer_mode & VM_WARP_CHASE)) || // non warp-chase to warp-chase
3593 ((last_Viewer_mode & VM_WARP_CHASE) && !(Viewer_mode & VM_WARP_CHASE)) || // warp-chase to non warp-chase
3594 (!(last_Viewer_mode & VM_OTHER_SHIP) && (Viewer_mode & VM_OTHER_SHIP)) || // non other-ship to other-ship
3595 ((last_Viewer_mode & VM_OTHER_SHIP) && !(Viewer_mode & VM_OTHER_SHIP)) || // other-ship to non-other ship
3596 ((Viewer_mode & VM_OTHER_SHIP) && (last_Viewer_objnum != Player_ai->target_objnum)) // other ship mode, but targets changes
3599 // regenerate the nebula
3603 if ( (last_Viewer_mode != Viewer_mode) || (last_Game_mode != Game_mode) ) {
3604 //mprintf(( "************** Camera cut! ************\n" ));
3605 last_Viewer_mode = Viewer_mode;
3606 last_Game_mode = Game_mode;
3608 // Camera moved. Tell stars & debris to not do blurring.
3614 if ( Viewer_mode & VM_PADLOCK_ANY ) {
3615 player_display_packlock_view();
3618 game_set_view_clip();
3620 if (Game_mode & GM_DEAD) {
3621 vector vec_to_deader, view_pos;
3624 Viewer_mode |= VM_DEAD_VIEW;
3626 if (Player_ai->target_objnum != -1) {
3627 int view_from_player = 1;
3629 if (Viewer_mode & VM_OTHER_SHIP) {
3630 // View from target.
3631 Viewer_obj = &Objects[Player_ai->target_objnum];
3633 last_Viewer_objnum = Player_ai->target_objnum;
3635 if ( Viewer_obj->type == OBJ_SHIP ) {
3636 ship_get_eye( eye_pos, eye_orient, Viewer_obj );
3637 view_from_player = 0;
3640 last_Viewer_objnum = -1;
3643 if ( view_from_player ) {
3644 // View target from player ship.
3646 *eye_pos = Player_obj->pos;
3647 vm_vec_normalized_dir(&eye_dir, &Objects[Player_ai->target_objnum].pos, eye_pos);
3648 vm_vector_2_matrix(eye_orient, &eye_dir, NULL, NULL);
3651 dist = vm_vec_normalized_dir(&vec_to_deader, &Player_obj->pos, &Dead_camera_pos);
3653 if (dist < MIN_DIST_TO_DEAD_CAMERA)
3654 dist += flFrametime * 16.0f;
3656 vm_vec_scale(&vec_to_deader, -dist);
3657 vm_vec_add(&Dead_camera_pos, &Player_obj->pos, &vec_to_deader);
3659 view_pos = Player_obj->pos;
3661 if (!(Game_mode & GM_DEAD_BLEW_UP)) {
3662 Viewer_mode &= ~(VM_EXTERNAL | VM_CHASE);
3663 vm_vec_scale_add2(&Dead_camera_pos, &Original_vec_to_deader, 25.0f * flFrametime);
3664 Dead_player_last_vel = Player_obj->phys_info.vel;
3665 //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));
3666 } else if (Player_ai->target_objnum != -1) {
3667 view_pos = Objects[Player_ai->target_objnum].pos;
3669 // Make camera follow explosion, but gradually slow down.
3670 vm_vec_scale_add2(&Player_obj->pos, &Dead_player_last_vel, flFrametime);
3671 view_pos = Player_obj->pos;
3672 vm_vec_scale(&Dead_player_last_vel, 0.99f);
3673 vm_vec_scale_add2(&Dead_camera_pos, &Original_vec_to_deader, min(25.0f, vm_vec_mag_quick(&Dead_player_last_vel)) * flFrametime);
3676 *eye_pos = Dead_camera_pos;
3678 vm_vec_normalized_dir(&eye_dir, &Player_obj->pos, eye_pos);
3680 vm_vector_2_matrix(eye_orient, &eye_dir, NULL, NULL);
3685 // if supernova shockwave
3686 if(supernova_camera_cut()){
3690 // call it dead view
3691 Viewer_mode |= VM_DEAD_VIEW;
3693 // set eye pos and orient
3694 supernova_set_view(eye_pos, eye_orient);
3696 // If already blown up, these other modes can override.
3697 if (!(Game_mode & (GM_DEAD | GM_DEAD_BLEW_UP))) {
3698 Viewer_mode &= ~VM_DEAD_VIEW;
3700 Viewer_obj = Player_obj;
3702 if (Viewer_mode & VM_OTHER_SHIP) {
3703 if (Player_ai->target_objnum != -1){
3704 Viewer_obj = &Objects[Player_ai->target_objnum];
3705 last_Viewer_objnum = Player_ai->target_objnum;
3707 Viewer_mode &= ~VM_OTHER_SHIP;
3708 last_Viewer_objnum = -1;
3711 last_Viewer_objnum = -1;
3714 if (Viewer_mode & VM_EXTERNAL) {
3717 vm_angles_2_matrix(&tm2, &Viewer_external_info.angles);
3718 vm_matrix_x_matrix(&tm, &Viewer_obj->orient, &tm2);
3720 vm_vec_scale_add(eye_pos, &Viewer_obj->pos, &tm.v.fvec, 2.0f * Viewer_obj->radius + Viewer_external_info.distance);
3722 vm_vec_sub(&eye_dir, &Viewer_obj->pos, eye_pos);
3723 vm_vec_normalize(&eye_dir);
3724 vm_vector_2_matrix(eye_orient, &eye_dir, &Viewer_obj->orient.v.uvec, NULL);
3727 // Modify the orientation based on head orientation.
3728 compute_slew_matrix(eye_orient, &Viewer_slew_angles);
3730 } else if ( Viewer_mode & VM_CHASE ) {
3733 if ( Viewer_obj->phys_info.speed < 0.1 )
3734 move_dir = Viewer_obj->orient.v.fvec;
3736 move_dir = Viewer_obj->phys_info.vel;
3737 vm_vec_normalize(&move_dir);
3740 vm_vec_scale_add(eye_pos, &Viewer_obj->pos, &move_dir, -3.0f * Viewer_obj->radius - Viewer_chase_info.distance);
3741 vm_vec_scale_add2(eye_pos, &Viewer_obj->orient.v.uvec, 0.75f * Viewer_obj->radius);
3742 vm_vec_sub(&eye_dir, &Viewer_obj->pos, eye_pos);
3743 vm_vec_normalize(&eye_dir);
3745 // JAS: I added the following code because if you slew up using
3746 // Descent-style physics, eye_dir and Viewer_obj->orient.v.uvec are
3747 // equal, which causes a zero-length vector in the vm_vector_2_matrix
3748 // call because the up and the forward vector are the same. I fixed
3749 // it by adding in a fraction of the right vector all the time to the
3751 vector tmp_up = Viewer_obj->orient.v.uvec;
3752 vm_vec_scale_add2( &tmp_up, &Viewer_obj->orient.v.rvec, 0.00001f );
3754 vm_vector_2_matrix(eye_orient, &eye_dir, &tmp_up, NULL);
3757 // Modify the orientation based on head orientation.
3758 compute_slew_matrix(eye_orient, &Viewer_slew_angles);
3759 } else if ( Viewer_mode & VM_WARP_CHASE ) {
3760 *eye_pos = Camera_pos;
3762 ship * shipp = &Ships[Player_obj->instance];
3764 vm_vec_sub(&eye_dir, &shipp->warp_effect_pos, eye_pos);
3765 vm_vec_normalize(&eye_dir);
3766 vm_vector_2_matrix(eye_orient, &eye_dir, &Player_obj->orient.v.uvec, NULL);
3769 // get an eye position based upon the correct type of object
3770 switch(Viewer_obj->type){
3772 // make a call to get the eye point for the player object
3773 ship_get_eye( eye_pos, eye_orient, Viewer_obj );
3776 // make a call to get the eye point for the player object
3777 observer_get_eye( eye_pos, eye_orient, Viewer_obj );
3783 #ifdef JOHNS_DEBUG_CODE
3784 john_debug_stuff(&eye_pos, &eye_orient);
3790 apply_hud_shake(eye_orient);
3792 // setup neb2 rendering
3793 neb2_render_setup(eye_pos, eye_orient);
3797 extern void ai_debug_render_stuff();
3800 int Game_subspace_effect = 0;
3801 DCF_BOOL( subspace, Game_subspace_effect );
3803 // Does everything needed to render a frame
3804 void game_render_frame( vector * eye_pos, matrix * eye_orient )
3808 g3_start_frame(game_zbuffer);
3809 g3_set_view_matrix( eye_pos, eye_orient, Viewer_zoom );
3811 // maybe offset the HUD (jitter stuff)
3812 dont_offset = ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER));
3813 HUD_set_offsets(Viewer_obj, !dont_offset);
3815 // for multiplayer clients, call code in Shield.cpp to set up the Shield_hit array. Have to
3816 // do this becaues of the disjointed nature of this system (in terms of setup and execution).
3817 // must be done before ships are rendered
3818 if ( MULTIPLAYER_CLIENT ) {
3819 shield_point_multi_setup();
3822 if ( Game_subspace_effect ) {
3823 stars_draw(0,0,0,1);
3825 stars_draw(1,1,1,0);
3828 obj_render_all(obj_render);
3829 beam_render_all(); // render all beam weapons
3830 particle_render_all(); // render particles after everything else.
3831 trail_render_all(); // render missilie trails after everything else.
3832 mflash_render_all(); // render all muzzle flashes
3834 // Why do we not show the shield effect in these modes? Seems ok.
3835 //if (!(Viewer_mode & (VM_EXTERNAL | VM_SLEWED | VM_CHASE | VM_DEAD_VIEW))) {
3839 // render nebula lightning
3842 // render local player nebula
3843 neb2_render_player();
3846 ai_debug_render_stuff();
3849 #ifndef RELEASE_REAL
3850 // game_framerate_check();
3854 extern void snd_spew_debug_info();
3855 snd_spew_debug_info();
3858 //================ END OF 3D RENDERING STUFF ====================
3862 if( (Game_detail_flags & DETAIL_FLAG_HUD) && (!(Game_mode & GM_MULTIPLAYER) || ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER) )) ) {
3863 hud_maybe_clear_head_area();
3864 anim_render_all(0, flFrametime);
3867 extern int Multi_display_netinfo;
3868 if(Multi_display_netinfo){
3869 extern void multi_display_netinfo();
3870 multi_display_netinfo();
3873 game_tst_frame_pre();
3876 do_timing_test(flFrametime);
3880 extern int OO_update_index;
3881 multi_rate_display(OO_update_index, 375, 0);
3886 extern void oo_display();
3893 //#define JOHNS_DEBUG_CODE 1
3895 #ifdef JOHNS_DEBUG_CODE
3896 void john_debug_stuff(vector *eye_pos, matrix *eye_orient)
3898 //if ( key_pressed(SDLK_LSHIFT) )
3900 ship_subsys *tsys = Players[Player_num].targeted_subobject;
3902 model_subsystem *turret = tsys->system_info;
3904 if (turret->type == SUBSYSTEM_TURRET ) {
3905 vector v.fvec, v.uvec;
3906 object * tobj = &Objects[Players[Player_num].targeted_subobject_parent];
3908 ship_model_start(tobj);
3910 model_find_world_point(eye_pos, &turret->turret_firing_point[0], turret->model_num, turret->turret_gun_sobj, &tobj->orient, &tobj->pos );
3911 model_find_world_dir(&v.fvec, &turret->turret_matrix.v.fvec, turret->model_num, turret->turret_gun_sobj, &tobj->orient, NULL );
3912 model_find_world_dir(&v.uvec, &turret->turret_matrix.v.uvec, turret->model_num, turret->turret_gun_sobj, &tobj->orient, NULL );
3914 vm_vector_2_matrix( eye_orient, &v.fvec, &v.uvec, NULL );
3916 ship_model_stop(tobj);
3926 // following function for dumping frames for purposes of building trailers.
3929 // function to toggle state of dumping every frame into PCX when playing the game
3930 DCF(dump_frames, "Starts/stop frame dumping at 15 hz")
3934 if ( Debug_dump_frames == 0 ) {
3936 Debug_dump_frames = 15;
3937 Debug_dump_trigger = 0;
3938 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
3939 dc_printf( "Frame dumping at 15 hz is now ON\n" );
3942 Debug_dump_frames = 0;
3943 Debug_dump_trigger = 0;
3944 gr_dump_frame_stop();
3945 dc_printf( "Frame dumping is now OFF\n" );
3951 DCF(dump_frames_trigger, "Starts/stop frame dumping at 15 hz")
3955 if ( Debug_dump_frames == 0 ) {
3957 Debug_dump_frames = 15;
3958 Debug_dump_trigger = 1;
3959 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
3960 dc_printf( "Frame dumping at 15 hz is now ON\n" );
3963 Debug_dump_frames = 0;
3964 Debug_dump_trigger = 0;
3965 gr_dump_frame_stop();
3966 dc_printf( "Frame dumping is now OFF\n" );
3972 DCF(dump_frames30, "Starts/stop frame dumping at 30 hz")
3976 if ( Debug_dump_frames == 0 ) {
3978 Debug_dump_frames = 30;
3979 Debug_dump_trigger = 0;
3980 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
3981 dc_printf( "Frame dumping at 30 hz is now ON\n" );
3984 Debug_dump_frames = 0;
3985 Debug_dump_trigger = 0;
3986 gr_dump_frame_stop();
3987 dc_printf( "Frame dumping is now OFF\n" );
3993 DCF(dump_frames30_trigger, "Starts/stop frame dumping at 30 hz")
3997 if ( Debug_dump_frames == 0 ) {
3999 Debug_dump_frames = 30;
4000 Debug_dump_trigger = 1;
4001 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
4002 dc_printf( "Triggered frame dumping at 30 hz is now ON\n" );
4005 Debug_dump_frames = 0;
4006 Debug_dump_trigger = 0;
4007 gr_dump_frame_stop();
4008 dc_printf( "Triggered frame dumping is now OFF\n" );
4014 void game_maybe_dump_frame()
4016 if ( !Debug_dump_frames ){
4020 if( Debug_dump_trigger && !key_pressed(SDLK_q) ){
4027 Debug_dump_frame_num++;
4033 extern int Player_dead_state;
4035 // Flip the page and time how long it took.
4036 void game_flip_page_and_time_it()
4041 t1 = timer_get_fixed_seconds();
4043 t2 = timer_get_fixed_seconds();
4046 t = (gr_screen.max_w*gr_screen.max_h*gr_screen.bytes_per_pixel)/1024;
4047 sprintf( transfer_text, NOX("%d MB/s"), fixmuldiv(t,65,d) );
4054 void game_simulation_frame()
4056 // blow ships up in multiplayer dogfight
4057 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){
4058 // blow up all non-player ships
4059 ship_obj *moveup = GET_FIRST(&Ship_obj_list);
4062 while((moveup != END_OF_LIST(&Ship_obj_list)) && (moveup != NULL)){
4064 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)){
4065 moveup = GET_NEXT(moveup);
4068 shipp = &Ships[Objects[moveup->objnum].instance];
4069 sip = &Ship_info[shipp->ship_info_index];
4071 // only blow up small ships
4072 if((sip->flags & SIF_SMALL_SHIP) && (multi_find_player_by_object(&Objects[moveup->objnum]) < 0) ){
4073 // function to simply explode a ship where it is currently at
4074 ship_self_destruct( &Objects[moveup->objnum] );
4077 moveup = GET_NEXT(moveup);
4083 // process AWACS stuff - do this first thing
4086 // single player, set Player hits_this_frame to 0
4087 if ( !(Game_mode & GM_MULTIPLAYER) && Player ) {
4088 Player->damage_this_burst -= (flFrametime * MAX_BURST_DAMAGE / (0.001f * BURST_DURATION));
4089 Player->damage_this_burst = max(Player->damage_this_burst, 0.0f);
4093 supernova_process();
4094 if(supernova_active() >= 5){
4098 // fire targeting lasers now so that
4099 // 1 - created this frame
4100 // 2 - collide this frame
4101 // 3 - render this frame
4102 // 4 - ignored and deleted next frame
4103 // the basic idea being that because it con be confusing to deal with them on a multi-frame basis, they are only valid for
4105 ship_process_targeting_lasers();
4107 // do this here so that it works for multiplayer
4109 // get viewer direction
4110 int viewer_direction = PHYSICS_VIEWER_REAR;
4112 if(Viewer_mode == 0){
4113 viewer_direction = PHYSICS_VIEWER_FRONT;
4115 if(Viewer_mode & VM_PADLOCK_UP){
4116 viewer_direction = PHYSICS_VIEWER_UP;
4118 else if(Viewer_mode & VM_PADLOCK_REAR){
4119 viewer_direction = PHYSICS_VIEWER_REAR;
4121 else if(Viewer_mode & VM_PADLOCK_LEFT){
4122 viewer_direction = PHYSICS_VIEWER_LEFT;
4124 else if(Viewer_mode & VM_PADLOCK_RIGHT){
4125 viewer_direction = PHYSICS_VIEWER_RIGHT;
4128 physics_set_viewer( &Viewer_obj->phys_info, viewer_direction );
4130 physics_set_viewer( NULL, PHYSICS_VIEWER_FRONT );
4133 #define VM_PADLOCK_UP (1 << 7)
4134 #define VM_PADLOCK_REAR (1 << 8)
4135 #define VM_PADLOCK_LEFT (1 << 9)
4136 #define VM_PADLOCK_RIGHT (1 << 10)
4138 // evaluate mission departures and arrivals before we process all objects.
4139 if ( !(Game_mode & GM_MULTIPLAYER) || ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER) && !multi_endgame_ending()) ) {
4141 // we don't want to evaluate mission stuff when any ingame joiner in multiplayer is receiving
4142 // ships/wing packets.
4143 if ( !((Game_mode & GM_MULTIPLAYER) && (Netgame.flags & NG_FLAG_INGAME_JOINING_CRITICAL)) && !(Game_mode & GM_DEMO_PLAYBACK)){
4144 mission_parse_eval_stuff();
4147 // if we're an observer, move ourselves seperately from the standard physics
4148 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER)){
4149 obj_observer_move(flFrametime);
4152 // move all the objects now
4153 obj_move_all(flFrametime);
4155 // check for cargo reveal (this has an internal timestamp, so only runs every N ms)
4156 // AL: 3-15-98: It was decided to not let AI ships inspect cargo
4157 // ship_check_cargo_all();
4158 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4159 mission_eval_goals();
4163 // always check training objectives, even in multiplayer missions. we need to do this so that the directives gauge works properly on clients
4164 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4165 training_check_objectives();
4168 // do all interpolation now
4169 if ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER) && !multi_endgame_ending() && !(Netgame.flags & NG_FLAG_SERVER_LOST)) {
4170 // client side processing of warping in effect stages
4171 multi_do_client_warp(flFrametime);
4173 // client side movement of an observer
4174 if((Net_player->flags & NETINFO_FLAG_OBSERVER) || (Player_obj->type == OBJ_OBSERVER)){
4175 obj_observer_move(flFrametime);
4178 // move all objects - does interpolation now as well
4179 obj_move_all(flFrametime);
4182 // only process the message queue when the player is "in" the game
4183 if ( !Pre_player_entry ){
4184 message_queue_process(); // process any messages send to the player
4187 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4188 message_maybe_distort(); // maybe distort incoming message if comms damaged
4189 player_repair_frame(flFrametime); // AI objects get repaired in ai_process, called from move code...deal with player.
4190 player_process_pending_praise(); // maybe send off a delayed praise message to the player
4191 player_maybe_play_all_alone_msg(); // mabye tell the player he is all alone
4194 if(!(Game_mode & GM_STANDALONE_SERVER)){
4195 // process some stuff every frame (before frame is rendered)
4196 emp_process_local();
4198 hud_update_frame(); // update hud systems
4200 if (!physics_paused) {
4201 // Move particle system
4202 particle_move_all(flFrametime);
4204 // Move missile trails
4205 trail_move_all(flFrametime);
4207 // process muzzle flashes
4208 mflash_process_all();
4210 // Flash the gun flashes
4211 shipfx_flash_do_frame(flFrametime);
4213 shockwave_move_all(flFrametime); // update all the shockwaves
4216 // subspace missile strikes
4219 obj_snd_do_frame(); // update the object-linked persistant sounds
4220 game_maybe_update_sound_environment();
4221 snd_update_listener(&View_position, &Player_obj->phys_info.vel, &Player_obj->orient);
4223 // AL: debug code used for testing ambient subspace sound (ie when enabling subspace through debug console)
4225 if ( Game_subspace_effect ) {
4226 game_start_subspace_ambient_sound();
4232 // Maybe render and process the dead-popup
4233 void game_maybe_do_dead_popup(float frametime)
4235 if ( popupdead_is_active() ) {
4237 int choice = popupdead_do_frame(frametime);
4239 if ( Game_mode & GM_NORMAL ) {
4242 gameseq_post_event(GS_EVENT_ENTER_GAME);
4246 gameseq_post_event(GS_EVENT_END_GAME);
4250 gameseq_post_event(GS_EVENT_START_GAME);
4253 // this should only happen during a red alert mission
4256 SDL_assert(The_mission.red_alert);
4257 if(!The_mission.red_alert){
4258 gameseq_post_event(GS_EVENT_START_GAME);
4262 // choose the previous mission
4263 mission_campaign_previous_mission();
4265 gameseq_post_event(GS_EVENT_START_GAME);
4275 case POPUPDEAD_DO_MAIN_HALL:
4276 multi_quit_game(PROMPT_NONE,-1);
4279 case POPUPDEAD_DO_RESPAWN:
4280 multi_respawn_normal();
4281 event_music_player_respawn();
4284 case POPUPDEAD_DO_OBSERVER:
4285 multi_respawn_observer();
4286 event_music_player_respawn_as_observer();
4295 if ( leave_popup ) {
4301 // returns true if player is actually in a game_play stats
4302 int game_actually_playing()
4306 state = gameseq_get_state();
4307 if ( (state != GS_STATE_GAME_PLAY) && (state != GS_STATE_DEATH_DIED) && (state != GS_STATE_DEATH_BLEW_UP) )
4313 // Draw the 2D HUD gauges
4314 void game_render_hud_2d()
4316 if ( !(Game_detail_flags & DETAIL_FLAG_HUD) ) {
4320 HUD_render_2d(flFrametime);
4324 // Draw the 3D-dependant HUD gauges
4325 void game_render_hud_3d(vector *eye_pos, matrix *eye_orient)
4327 g3_start_frame(0); // 0 = turn zbuffering off
4328 g3_set_view_matrix( eye_pos, eye_orient, Viewer_zoom );
4330 if ( (Game_detail_flags & DETAIL_FLAG_HUD) && (supernova_active() < 3)/* && !(Game_mode & GM_MULTIPLAYER) || ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER) )*/ ) {
4331 HUD_render_3d(flFrametime);
4335 game_sunspot_process(flFrametime);
4337 // Diminish the palette effect
4338 game_flash_diminish(flFrametime);
4346 int actually_playing;
4347 fix total_time1, total_time2;
4348 fix render2_time1=0, render2_time2=0;
4349 fix render3_time1=0, render3_time2=0;
4350 fix flip_time1=0, flip_time2=0;
4351 fix clear_time1=0, clear_time2=0;
4357 if (Framerate_delay) {
4358 int start_time = timer_get_milliseconds();
4359 while (timer_get_milliseconds() < start_time + Framerate_delay)
4365 demo_do_frame_start();
4367 mprintf(("Error (%d) while processing demo!\n", Demo_error));
4372 // start timing frame
4373 timing_frame_start();
4375 total_time1 = timer_get_fixed_seconds();
4377 // var to hold which state we are in
4378 actually_playing = game_actually_playing();
4380 if ((!(Game_mode & GM_MULTIPLAYER)) || ((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER))) {
4381 if (!(Game_mode & GM_STANDALONE_SERVER)){
4382 SDL_assert( OBJ_INDEX(Player_obj) >= 0 );
4386 if (Missiontime > Entry_delay_time){
4387 Pre_player_entry = 0;
4389 ; //nprintf(("AI", "Framecount = %i, time = %7.3f\n", Framecount, f2fl(Missiontime)));
4392 // Note: These are done even before the player enters, else buffers can overflow.
4393 if (! (Game_mode & GM_STANDALONE_SERVER)){
4397 shield_frame_init();
4399 if ( Player->control_mode != PCM_NORMAL )
4402 if ( !Pre_player_entry && actually_playing ) {
4403 if (! (Game_mode & GM_STANDALONE_SERVER) ) {
4405 if( (!popup_running_state()) && (!popupdead_is_active()) ){
4406 game_process_keys();
4408 // don't read flying controls if we're playing a demo back
4409 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4410 read_player_controls( Player_obj, flFrametime);
4414 // if we're not the master, we may have to send the server-critical ship status button_info bits
4415 if ((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER)){
4416 multi_maybe_send_ship_status();
4421 // Reset the whack stuff
4424 // These two lines must be outside of Pre_player_entry code,
4425 // otherwise too many lights are added.
4428 if ((Game_mode & GM_MULTIPLAYER) && (Netgame.game_state == NETGAME_STATE_SERVER_TRANSFER)){
4432 game_simulation_frame();
4434 // if not actually in a game play state, then return. This condition could only be true in
4435 // a multiplayer game.
4436 if ( !actually_playing ) {
4437 SDL_assert( Game_mode & GM_MULTIPLAYER );
4441 if (!Pre_player_entry) {
4442 if (! (Game_mode & GM_STANDALONE_SERVER)) {
4443 clear_time1 = timer_get_fixed_seconds();
4444 // clear the screen to black
4446 if ( (Game_detail_flags & DETAIL_FLAG_CLEAR) ) {
4450 clear_time2 = timer_get_fixed_seconds();
4451 render3_time1 = timer_get_fixed_seconds();
4452 game_render_frame_setup(&eye_pos, &eye_orient);
4453 game_render_frame( &eye_pos, &eye_orient );
4455 // save the eye position and orientation
4456 if ( Game_mode & GM_MULTIPLAYER ) {
4457 Net_player->s_info.eye_pos = eye_pos;
4458 Net_player->s_info.eye_orient = eye_orient;
4461 hud_show_target_model();
4463 // check to see if we should display the death died popup
4464 if(Game_mode & GM_DEAD_BLEW_UP){
4465 if(Game_mode & GM_MULTIPLAYER){
4466 // catch the situation where we're supposed to be warping out on this transition
4467 if(Net_player->flags & NETINFO_FLAG_WARPING_OUT){
4468 gameseq_post_event(GS_EVENT_DEBRIEF);
4469 } else if((Player_died_popup_wait != -1) && (timestamp_elapsed(Player_died_popup_wait))){
4470 Player_died_popup_wait = -1;
4474 if((Player_died_popup_wait != -1) && (timestamp_elapsed(Player_died_popup_wait))){
4475 Player_died_popup_wait = -1;
4481 // hack - sometimes this seems to slip by in multiplayer. this should guarantee that we catch it
4482 if((Game_mode & GM_MULTIPLAYER) && (Player_multi_died_check != -1) && (Game_mode & GM_DEAD_BLEW_UP) ){
4483 if(fl_abs(time(NULL) - Player_multi_died_check) > 4){
4484 if(!popupdead_is_active()){
4488 Player_multi_died_check = -1;
4492 render3_time2 = timer_get_fixed_seconds();
4493 render2_time1 = timer_get_fixed_seconds();
4496 game_get_framerate();
4497 game_show_framerate();
4499 game_show_time_left();
4501 // Draw the 2D HUD gauges
4502 if(supernova_active() < 3){
4503 game_render_hud_2d();
4506 game_set_view_clip();
4508 // Draw 3D HUD gauges
4509 game_render_hud_3d(&eye_pos, &eye_orient);
4513 render2_time2 = timer_get_fixed_seconds();
4515 // maybe render and process the dead popup
4516 game_maybe_do_dead_popup(flFrametime);
4518 // start timing frame
4519 timing_frame_stop();
4520 // timing_display(30, 10);
4522 // If a regular popup is active, don't flip (popup code flips)
4523 if( !popup_running_state() ){
4524 flip_time1 = timer_get_fixed_seconds();
4525 game_flip_page_and_time_it();
4526 flip_time2 = timer_get_fixed_seconds();
4530 game_maybe_dump_frame(); // used to dump pcx files for building trailers
4533 game_show_standalone_framerate();
4537 game_do_training_checks();
4540 // process lightning (nebula only)
4543 total_time2 = timer_get_fixed_seconds();
4545 // Got some timing numbers
4546 Timing_total = f2fl( total_time2 - total_time1 ) * 1000.0f;
4547 Timing_clear = f2fl( clear_time2 - clear_time1 ) * 1000.0f;
4548 Timing_render2 = f2fl( render2_time2- render2_time1 ) * 1000.0f;
4549 Timing_render3 = f2fl( render3_time2- render3_time1 ) * 1000.0f;
4550 Timing_flip = f2fl( flip_time2 - flip_time1 ) * 1000.0f;
4553 demo_do_frame_end();
4555 mprintf(("Error (%d) while processing demo!\n", Demo_error));
4561 #define MAX_FRAMETIME (F1_0/4) // Frametime gets saturated at this. Changed by MK on 11/1/97.
4562 // Some bug was causing Frametime to always get saturated at 2.0 seconds after the player
4563 // died. This resulted in screwed up death sequences.
4565 fix Last_time = 0; // The absolute time of game at end of last frame (beginning of this frame)
4566 fix Last_delta_time = 0; // While game is paused, this keeps track of how much elapsed in the frame before paused.
4567 static int timer_paused=0;
4568 #if defined(TIMER_TEST) && !defined(NDEBUG)
4569 static int stop_count,start_count;
4570 static int time_stopped,time_started;
4572 int saved_timestamp_ticker = -1;
4574 void game_reset_time()
4576 if((Game_mode & GM_MULTIPLAYER) && (Netgame.game_state == NETGAME_STATE_SERVER_TRANSFER)){
4580 // Last_time = timer_get_fixed_seconds();
4586 void game_stop_time()
4588 if (timer_paused==0) {
4590 time = timer_get_fixed_seconds();
4591 // Save how much time progressed so far in the frame so we can
4592 // use it when we unpause.
4593 Last_delta_time = time - Last_time;
4595 //mprintf(("Last_time in game_stop_time = %7.3f\n", f2fl(Last_delta_time)));
4596 if (Last_delta_time < 0) {
4597 #if defined(TIMER_TEST) && !defined(NDEBUG)
4598 Int3(); //get Matt!!!!
4600 Last_delta_time = 0;
4602 #if defined(TIMER_TEST) && !defined(NDEBUG)
4603 time_stopped = time;
4606 // Stop the timer_tick stuff...
4607 // Normally, you should never access 'timestamp_ticker', consider this a low-level routine
4608 saved_timestamp_ticker = timestamp_ticker;
4612 #if defined(TIMER_TEST) && !defined(NDEBUG)
4617 void game_start_time()
4620 SDL_assert(timer_paused >= 0);
4621 if (timer_paused==0) {
4623 time = timer_get_fixed_seconds();
4624 #if defined(TIMER_TEST) && !defined(NDEBUG)
4626 Int3(); //get Matt!!!!
4629 // Take current time, and set it backwards to account for time
4630 // that the frame already executed, so that timer_get_fixed_seconds() - Last_time
4631 // will be correct when it goes to calculate the frametime next
4633 Last_time = time - Last_delta_time;
4634 #if defined(TIMER_TEST) && !defined(NDEBUG)
4635 time_started = time;
4638 // Restore the timer_tick stuff...
4639 // Normally, you should never access 'timestamp_ticker', consider this a low-level routine
4640 SDL_assert( saved_timestamp_ticker > -1 ); // Called out of order, get JAS
4641 timestamp_ticker = saved_timestamp_ticker;
4642 saved_timestamp_ticker = -1;
4645 #if defined(TIMER_TEST) && !defined(NDEBUG)
4651 void game_set_frametime(int state)
4654 float frame_cap_diff;
4656 thistime = timer_get_fixed_seconds();
4658 if ( Last_time == 0 )
4659 Frametime = F1_0 / 30;
4661 Frametime = thistime - Last_time;
4663 // Frametime = F1_0 / 30;
4665 fix debug_frametime = Frametime; // Just used to display frametime.
4667 // If player hasn't entered mission yet, make frame take 1/4 second.
4668 if ((Pre_player_entry) && (state == GS_STATE_GAME_PLAY))
4671 else if ((Debug_dump_frames) && (state == GS_STATE_GAME_PLAY)) { // note link to above if!!!!!
4673 fix frame_speed = F1_0 / Debug_dump_frames;
4675 if (Frametime > frame_speed ){
4676 nprintf(("warning","slow frame: %x\n",Frametime));
4679 thistime = timer_get_fixed_seconds();
4680 Frametime = thistime - Last_time;
4681 } while (Frametime < frame_speed );
4683 Frametime = frame_speed;
4687 SDL_assert( Framerate_cap > 0 );
4689 // Cap the framerate so it doesn't get too high.
4693 cap = F1_0/Framerate_cap;
4694 if (Frametime < cap) {
4695 thistime = cap - Frametime;
4696 //mprintf(("Sleeping for %6.3f seconds.\n", f2fl(thistime)));
4697 SDL_Delay( (f2fl(thistime) * 1000.0f) );
4699 thistime = timer_get_fixed_seconds();
4703 if((Game_mode & GM_STANDALONE_SERVER) &&
4704 (f2fl(Frametime) < ((float)1.0/(float)Multi_options_g.std_framecap))){
4706 frame_cap_diff = ((float)1.0/(float)Multi_options_g.std_framecap) - f2fl(Frametime);
4707 SDL_Delay((frame_cap_diff*1000));
4709 thistime += fl2f((frame_cap_diff));
4711 Frametime = thistime - Last_time;
4714 // If framerate is too low, cap it.
4715 if (Frametime > MAX_FRAMETIME) {
4717 mprintf(("Frame %2i too long!!: frametime = %.3f (%.3f)\n", Framecount, f2fl(Frametime), f2fl(debug_frametime)));
4719 // to remove warnings in release build
4720 debug_frametime = fl2f(flFrametime);
4722 Frametime = MAX_FRAMETIME;
4725 Frametime = fixmul(Frametime, Game_time_compression);
4727 Last_time = thistime;
4728 //mprintf(("Frame %i, Last_time = %7.3f\n", Framecount, f2fl(Last_time)));
4730 flFrametime = f2fl(Frametime);
4731 //if(!(Game_mode & GM_PLAYING_DEMO)){
4732 timestamp_inc(flFrametime);
4734 /* if ((Framecount > 0) && (Framecount < 10)) {
4735 mprintf(("Frame %2i: frametime = %.3f (%.3f)\n", Framecount, f2fl(Frametime), f2fl(debug_frametime)));
4740 // This is called from game_do_frame(), and from navmap_do_frame()
4741 void game_update_missiontime()
4743 // TODO JAS: Put in if and move this into game_set_frametime,
4744 // fix navmap to call game_stop/start_time
4745 //if ( !timer_paused )
4746 Missiontime += Frametime;
4749 void game_do_frame()
4751 game_set_frametime(GS_STATE_GAME_PLAY);
4752 game_update_missiontime();
4754 if (Game_mode & GM_STANDALONE_SERVER) {
4755 std_multi_set_standalone_missiontime(f2fl(Missiontime));
4758 if ( game_single_step && (last_single_step == game_single_step) ) {
4759 os_set_title( NOX("SINGLE STEP MODE (Pause exits, any other key steps)") );
4760 while( key_checkch() == 0 )
4762 os_set_title( XSTR( "FreeSpace", 171) );
4763 Last_time = timer_get_fixed_seconds();
4766 last_single_step = game_single_step;
4768 if ((gameseq_get_state() == GS_STATE_GAME_PLAY) && Use_mouse_to_fly){
4769 Keep_mouse_centered = 1; // force mouse to center of our window (so we don't hit movement limits)
4773 Keep_mouse_centered = 0;
4774 monitor_update(); // Update monitor variables
4777 void multi_maybe_do_frame()
4779 if ( (Game_mode & GM_MULTIPLAYER) && (Game_mode & GM_IN_MISSION) && !Multi_pause_status){
4784 int Joymouse_button_status = 0;
4786 // Flush all input devices
4794 Joymouse_button_status = 0;
4796 //mprintf(("Game flush!\n" ));
4799 // function for multiplayer only which calls game_do_state_common() when running the
4801 void game_do_dc_networking()
4803 SDL_assert( Game_mode & GM_MULTIPLAYER );
4805 game_do_state_common( gameseq_get_state() );
4808 // Call this whenever in a loop, or when you need to check for a keystroke.
4809 int game_check_key()
4815 // convert keypad enter to normal enter
4816 if ((k & KEY_MASK) == SDLK_KP_ENTER)
4817 k = (k & ~KEY_MASK) | SDLK_RETURN;
4822 #if defined(FS2_DEMO) || defined(FS1_DEMO)
4824 #define DEMO_TRAILER_TIMEOUT_MS 45000 // 45 seconds of no input, play trailer
4825 static int Demo_show_trailer_timestamp = 0;
4827 void demo_reset_trailer_timer()
4829 Demo_show_trailer_timestamp = timer_get_milliseconds();
4832 void demo_maybe_show_trailer(int k)
4835 // if key pressed, reset demo trailer timer
4837 demo_reset_trailer_timer();
4841 // if mouse moved, reset demo trailer timer
4844 mouse_get_delta(&dx, &dy);
4845 if ( (dx > 0) || (dy > 0) ) {
4846 demo_reset_trailer_timer();
4850 // if joystick has moved, reset demo trailer timer
4853 joy_get_delta(&dx, &dy);
4854 if ( (dx > 0) || (dy > 0) ) {
4855 demo_reset_trailer_timer();
4859 // NOTE: reseting the trailer timer on mouse/joystick presses is handled in
4860 // the low-level code. Ugly, I know... but was the simplest and most
4863 // if 30 seconds since last demo trailer time reset, launch movie
4864 if ( os_foreground() ) {
4865 int now = timer_get_milliseconds();
4866 if ( (now - Demo_show_trailer_timestamp) > DEMO_TRAILER_TIMEOUT_MS ) {
4867 // if ( (now - Demo_show_trailer_timestamp) > 10000 ) {
4869 movie_play( NOX("fstrailer2.mve") );
4870 demo_reset_trailer_timer();
4878 // same as game_check_key(), except this is used while actually in the game. Since there
4879 // generally are differences between game control keys and general UI keys, makes sense to
4880 // have seperate functions for each case. If you are not checking a game control while in a
4881 // mission, you should probably be using game_check_key() instead.
4886 if (!os_foreground()) {
4891 // If we're in a single player game, pause it.
4892 if (!(Game_mode & GM_MULTIPLAYER)){
4893 if ( (gameseq_get_state() == GS_STATE_GAME_PLAY) && (!popup_active()) && (!popupdead_is_active()) ) {
4894 game_process_pause_key();
4901 #if defined(FS2_DEMO) || defined(FS1_DEMO)
4902 demo_maybe_show_trailer(k);
4905 // Move the mouse cursor with the joystick.
4906 if (os_foreground() && (!Mouse_hidden) && (Use_joy_mouse) ) {
4907 // Move the mouse cursor with the joystick
4911 joy_get_pos( &jx, &jy, &jz, &jr );
4913 dx = fl2i(f2fl(jx)*flFrametime*500.0f);
4914 dy = fl2i(f2fl(jy)*flFrametime*500.0f);
4917 mouse_get_real_pos( &mx, &my );
4918 mouse_set_pos( mx+dx, my+dy );
4923 m = mouse_down(MOUSE_LEFT_BUTTON);
4925 if ( j != Joymouse_button_status ) {
4926 //mprintf(( "Joy went from %d to %d, mouse is %d\n", Joymouse_button_status, j, m ));
4927 Joymouse_button_status = j;
4929 mouse_mark_button( MOUSE_LEFT_BUTTON, 1 );
4930 } else if ( (!j) && (m) ) {
4931 mouse_mark_button( MOUSE_LEFT_BUTTON, 0 );
4936 // if we should be ignoring keys because of some multiplayer situations
4937 if((Game_mode & GM_MULTIPLAYER) && multi_ignore_controls(k)){
4941 // If a popup is running, don't process all the Fn keys
4942 if( popup_active() ) {
4946 state = gameseq_get_state();
4948 // if ( k ) nprintf(( "General", "Key = %x\n", k ));
4951 case KEY_DEBUGGED + SDLK_BACKSPACE:
4956 launch_context_help();
4961 // if (state != GS_STATE_INITIAL_PLAYER_SELECT) {
4963 // don't allow f2 while warping out in multiplayer
4964 if((Game_mode & GM_MULTIPLAYER) && (Net_player != NULL) && (Net_player->flags & NETINFO_FLAG_WARPING_OUT)){
4969 case GS_STATE_INITIAL_PLAYER_SELECT:
4970 case GS_STATE_OPTIONS_MENU:
4971 case GS_STATE_HUD_CONFIG:
4972 case GS_STATE_CONTROL_CONFIG:
4973 case GS_STATE_DEATH_DIED:
4974 case GS_STATE_DEATH_BLEW_UP:
4975 case GS_STATE_VIEW_MEDALS:
4979 gameseq_post_event(GS_EVENT_OPTIONS_MENU);
4986 // hotkey selection screen -- only valid from briefing and beyond.
4988 #if !(defined(FS2_DEMO) || defined(FS1_DEMO))
4989 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) ) {
4990 gameseq_post_event( GS_EVENT_HOTKEY_SCREEN );
4996 case KEY_DEBUGGED + SDLK_F3:
4997 gameseq_post_event( GS_EVENT_TOGGLE_FULLSCREEN );
5000 case KEY_DEBUGGED + SDLK_F4:
5001 gameseq_post_event( GS_EVENT_TOGGLE_GLIDE );
5005 if(Game_mode & GM_MULTIPLAYER){
5006 if((state == GS_STATE_GAME_PLAY) || (state == GS_STATE_MULTI_PAUSED)){
5007 gameseq_post_event( GS_EVENT_MISSION_LOG_SCROLLBACK );
5011 if ((state == GS_STATE_GAME_PLAY) || (state == GS_STATE_DEATH_DIED) || (state == GS_STATE_DEATH_BLEW_UP) || (state == GS_STATE_GAME_PAUSED) ) {
5012 gameseq_post_event( GS_EVENT_MISSION_LOG_SCROLLBACK );
5018 case SDLK_ESCAPE | KEY_SHIFTED:
5019 // make sure to quit properly out of multiplayer
5020 if(Game_mode & GM_MULTIPLAYER){
5021 multi_quit_game(PROMPT_NONE);
5024 gameseq_post_event( GS_EVENT_QUIT_GAME );
5029 case KEY_DEBUGGED + SDLK_p:
5032 case SDLK_PRINTSCREEN:
5034 static int counter = 0;
5039 sprintf( tmp_name, NOX("screen%02d"), counter );
5041 mprintf(( "Dumping screen to '%s'\n", tmp_name ));
5042 gr_print_screen(tmp_name);
5050 case KEY_SHIFTED | SDLK_RETURN: {
5052 #if !defined(NDEBUG)
5054 if ( Game_mode & GM_NORMAL ){
5058 // if we're in multiplayer mode, do some special networking
5059 if(Game_mode & GM_MULTIPLAYER){
5060 debug_console(game_do_dc_networking);
5067 if ( Game_mode & GM_NORMAL )
5081 gameseq_post_event(GS_EVENT_QUIT_GAME);
5084 void apply_physics( float damping, float desired_vel, float initial_vel, float t, float * new_vel, float * delta_pos );
5087 void camera_set_position( vector *pos )
5092 void camera_set_orient( matrix *orient )
5094 Camera_orient = *orient;
5097 void camera_set_velocity( vector *vel, int instantaneous )
5099 Camera_desired_velocity.xyz.x = 0.0f;
5100 Camera_desired_velocity.xyz.y = 0.0f;
5101 Camera_desired_velocity.xyz.z = 0.0f;
5103 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.rvec, vel->xyz.x );
5104 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.uvec, vel->xyz.y );
5105 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.fvec, vel->xyz.z );
5107 if ( instantaneous ) {
5108 Camera_velocity = Camera_desired_velocity;
5116 vector new_vel, delta_pos;
5118 apply_physics( Camera_damping, Camera_desired_velocity.xyz.x, Camera_velocity.xyz.x, flFrametime, &new_vel.xyz.x, &delta_pos.xyz.x );
5119 apply_physics( Camera_damping, Camera_desired_velocity.xyz.y, Camera_velocity.xyz.y, flFrametime, &new_vel.xyz.y, &delta_pos.xyz.y );
5120 apply_physics( Camera_damping, Camera_desired_velocity.xyz.z, Camera_velocity.xyz.z, flFrametime, &new_vel.xyz.z, &delta_pos.xyz.z );
5122 Camera_velocity = new_vel;
5124 // mprintf(( "Camera velocity = %.1f,%.1f, %.1f\n", Camera_velocity.xyz.x, Camera_velocity.xyz.y, Camera_velocity.xyz.z ));
5126 vm_vec_add2( &Camera_pos, &delta_pos );
5128 float ot = Camera_time+0.0f;
5130 Camera_time += flFrametime;
5132 if ( (ot < 0.667f) && ( Camera_time >= 0.667f ) ) {
5135 tmp.xyz.z = 4.739f; // always go this fast forward.
5137 // pick x and y velocities so they are always on a
5138 // circle with a 25 m radius.
5140 float tmp_angle = frand()*PI2;
5142 tmp.xyz.x = 22.0f * (float)sin(tmp_angle);
5143 tmp.xyz.y = -22.0f * (float)cos(tmp_angle);
5145 //mprintf(( "Angle = %.1f, vx=%.1f, vy=%.1f\n", tmp_angle, tmp.xyz.x, tmp.xyz.y ));
5147 //mprintf(( "Changing velocity!\n" ));
5148 camera_set_velocity( &tmp, 0 );
5151 if ( (ot < 3.0f ) && ( Camera_time >= 3.0f ) ) {
5152 vector tmp = ZERO_VECTOR;
5153 camera_set_velocity( &tmp, 0 );
5158 void end_demo_campaign_do()
5160 #if defined(FS2_DEMO) || defined(FS1_DEMO)
5161 // show upsell screens
5162 demo_upsell_show_screens();
5163 #elif defined(OEM_BUILD)
5164 // show oem upsell screens
5165 oem_upsell_show_screens();
5168 // drop into main hall
5169 gameseq_post_event( GS_EVENT_MAIN_MENU );
5172 // All code to process events. This is the only place
5173 // that you should change the state of the game.
5174 void game_process_event( int current_state, int event )
5176 mprintf(("Got event %s in state %s\n", GS_event_text[event], GS_state_text[current_state]));
5179 case GS_EVENT_SIMULATOR_ROOM:
5180 gameseq_set_state(GS_STATE_SIMULATOR_ROOM);
5183 case GS_EVENT_MAIN_MENU:
5184 gameseq_set_state(GS_STATE_MAIN_MENU);
5187 case GS_EVENT_OPTIONS_MENU:
5188 gameseq_push_state( GS_STATE_OPTIONS_MENU );
5191 case GS_EVENT_BARRACKS_MENU:
5192 gameseq_set_state(GS_STATE_BARRACKS_MENU);
5195 case GS_EVENT_TECH_MENU:
5196 gameseq_set_state(GS_STATE_TECH_MENU);
5199 case GS_EVENT_TRAINING_MENU:
5200 gameseq_set_state(GS_STATE_TRAINING_MENU);
5203 case GS_EVENT_START_GAME:
5204 Select_default_ship = 0;
5205 Player_multi_died_check = -1;
5206 gameseq_set_state(GS_STATE_CMD_BRIEF);
5209 case GS_EVENT_START_BRIEFING:
5210 gameseq_set_state(GS_STATE_BRIEFING);
5213 case GS_EVENT_DEBRIEF:
5214 // did we end the campaign in the main freespace 2 single player campaign?
5216 if(Campaign_ended_in_mission && (Game_mode & GM_CAMPAIGN_MODE) && !SDL_strcasecmp(Campaign.filename, "freespace")) {
5218 if(Campaign_ended_in_mission && (Game_mode & GM_CAMPAIGN_MODE) && !SDL_strcasecmp(Campaign.filename, "freespace2")) {
5220 gameseq_post_event(GS_EVENT_END_CAMPAIGN);
5222 gameseq_set_state(GS_STATE_DEBRIEF);
5225 Player_multi_died_check = -1;
5228 case GS_EVENT_SHIP_SELECTION:
5229 gameseq_set_state( GS_STATE_SHIP_SELECT );
5232 case GS_EVENT_WEAPON_SELECTION:
5233 gameseq_set_state( GS_STATE_WEAPON_SELECT );
5236 case GS_EVENT_ENTER_GAME:
5238 // maybe start recording a demo
5240 demo_start_record("test.fsd");
5244 if (Game_mode & GM_MULTIPLAYER) {
5245 // if we're respawning, make sure we change the view mode so that the hud shows up
5246 if (current_state == GS_STATE_DEATH_BLEW_UP) {
5250 gameseq_set_state(GS_STATE_GAME_PLAY);
5252 gameseq_set_state(GS_STATE_GAME_PLAY, 1);
5255 Player_multi_died_check = -1;
5257 // clear multiplayer button info
5258 extern button_info Multi_ship_status_bi;
5259 memset(&Multi_ship_status_bi, 0, sizeof(button_info));
5261 Start_time = f2fl(timer_get_approx_seconds());
5263 mprintf(("Entering game at time = %7.3f\n", Start_time));
5267 case GS_EVENT_START_GAME_QUICK:
5268 Select_default_ship = 1;
5269 gameseq_post_event(GS_EVENT_ENTER_GAME);
5273 case GS_EVENT_END_GAME:
5274 if ( (current_state == GS_STATE_GAME_PLAY) || (current_state == GS_STATE_DEATH_DIED) ||
5275 (current_state == GS_STATE_DEATH_BLEW_UP) || (current_state == GS_STATE_DEBRIEF) || (current_state == GS_STATE_MULTI_DOGFIGHT_DEBRIEF)) {
5276 gameseq_set_state(GS_STATE_MAIN_MENU);
5281 Player_multi_died_check = -1;
5284 case GS_EVENT_QUIT_GAME:
5285 main_hall_stop_music();
5286 main_hall_stop_ambient();
5287 gameseq_set_state(GS_STATE_QUIT_GAME);
5289 Player_multi_died_check = -1;
5292 case GS_EVENT_GAMEPLAY_HELP:
5293 gameseq_push_state( GS_STATE_GAMEPLAY_HELP );
5296 case GS_EVENT_PAUSE_GAME:
5297 gameseq_push_state(GS_STATE_GAME_PAUSED);
5300 case GS_EVENT_DEBUG_PAUSE_GAME:
5301 gameseq_push_state(GS_STATE_DEBUG_PAUSED);
5304 case GS_EVENT_TRAINING_PAUSE:
5305 gameseq_push_state(GS_STATE_TRAINING_PAUSED);
5308 case GS_EVENT_PREVIOUS_STATE:
5309 gameseq_pop_state();
5312 case GS_EVENT_TOGGLE_FULLSCREEN:
5313 #ifndef HARDWARE_ONLY
5315 if ( gr_screen.mode == GR_SOFTWARE ) {
5316 gr_init( GR_640, GR_DIRECTDRAW );
5317 } else if ( gr_screen.mode == GR_DIRECTDRAW ) {
5318 gr_init( GR_640, GR_SOFTWARE );
5324 case GS_EVENT_TOGGLE_GLIDE:
5327 case GS_EVENT_LOAD_MISSION_MENU:
5328 gameseq_set_state(GS_STATE_LOAD_MISSION_MENU);
5331 case GS_EVENT_MISSION_LOG_SCROLLBACK:
5332 gameseq_push_state( GS_STATE_MISSION_LOG_SCROLLBACK );
5335 case GS_EVENT_HUD_CONFIG:
5336 gameseq_push_state( GS_STATE_HUD_CONFIG );
5339 case GS_EVENT_CONTROL_CONFIG:
5340 gameseq_push_state( GS_STATE_CONTROL_CONFIG );
5343 case GS_EVENT_DEATH_DIED:
5344 gameseq_set_state( GS_STATE_DEATH_DIED );
5347 case GS_EVENT_DEATH_BLEW_UP:
5348 if ( current_state == GS_STATE_DEATH_DIED ) {
5349 gameseq_set_state( GS_STATE_DEATH_BLEW_UP );
5350 event_music_player_death();
5352 // multiplayer clients set their extra check here
5353 if(Game_mode & GM_MULTIPLAYER){
5354 // set the multi died absolute last chance check
5355 Player_multi_died_check = time(NULL);
5358 mprintf(( "Ignoring GS_EVENT_DEATH_BLEW_UP because we're in state %d\n", current_state ));
5362 case GS_EVENT_NEW_CAMPAIGN:
5363 if (!mission_load_up_campaign()){
5364 readyroom_continue_campaign();
5367 Player_multi_died_check = -1;
5370 case GS_EVENT_CAMPAIGN_CHEAT:
5371 if (!mission_load_up_campaign()){
5373 // bash campaign value
5374 extern char Main_hall_campaign_cheat[512];
5377 // look for the mission
5378 for(idx=0; idx<Campaign.num_missions; idx++){
5379 if(!SDL_strcasecmp(Campaign.missions[idx].name, Main_hall_campaign_cheat)){
5380 Campaign.next_mission = idx;
5381 Campaign.prev_mission = idx - 1;
5388 readyroom_continue_campaign();
5391 Player_multi_died_check = -1;
5394 case GS_EVENT_CAMPAIGN_ROOM:
5395 gameseq_set_state(GS_STATE_CAMPAIGN_ROOM);
5398 case GS_EVENT_CMD_BRIEF:
5399 gameseq_set_state(GS_STATE_CMD_BRIEF);
5402 case GS_EVENT_RED_ALERT:
5403 gameseq_set_state(GS_STATE_RED_ALERT);
5406 case GS_EVENT_CREDITS:
5407 gameseq_set_state( GS_STATE_CREDITS );
5410 case GS_EVENT_VIEW_MEDALS:
5411 gameseq_push_state( GS_STATE_VIEW_MEDALS );
5414 case GS_EVENT_SHOW_GOALS:
5415 gameseq_push_state( GS_STATE_SHOW_GOALS ); // use push_state() since we might get to this screen through a variety of states
5418 case GS_EVENT_HOTKEY_SCREEN:
5419 gameseq_push_state( GS_STATE_HOTKEY_SCREEN ); // use push_state() since we might get to this screen through a variety of states
5422 // multiplayer stuff follow these comments
5424 case GS_EVENT_MULTI_JOIN_GAME:
5425 gameseq_set_state( GS_STATE_MULTI_JOIN_GAME );
5428 case GS_EVENT_MULTI_HOST_SETUP:
5429 gameseq_set_state( GS_STATE_MULTI_HOST_SETUP );
5432 case GS_EVENT_MULTI_CLIENT_SETUP:
5433 gameseq_set_state( GS_STATE_MULTI_CLIENT_SETUP );
5436 case GS_EVENT_GOTO_VIEW_CUTSCENES_SCREEN:
5437 gameseq_set_state(GS_STATE_VIEW_CUTSCENES);
5440 case GS_EVENT_MULTI_STD_WAIT:
5441 gameseq_set_state( GS_STATE_MULTI_STD_WAIT );
5444 case GS_EVENT_STANDALONE_MAIN:
5445 gameseq_set_state( GS_STATE_STANDALONE_MAIN );
5448 case GS_EVENT_MULTI_PAUSE:
5449 gameseq_push_state( GS_STATE_MULTI_PAUSED );
5452 case GS_EVENT_INGAME_PRE_JOIN:
5453 gameseq_set_state( GS_STATE_INGAME_PRE_JOIN );
5456 case GS_EVENT_EVENT_DEBUG:
5457 gameseq_push_state(GS_STATE_EVENT_DEBUG);
5460 // Start a warpout where player automatically goes 70 no matter what
5461 // and can't cancel out of it.
5462 case GS_EVENT_PLAYER_WARPOUT_START_FORCED:
5463 Warpout_forced = 1; // If non-zero, bash the player to speed and go through effect
5465 // Same code as in GS_EVENT_PLAYER_WARPOUT_START only ignores current mode
5466 Player->saved_viewer_mode = Viewer_mode;
5467 Player->control_mode = PCM_WARPOUT_STAGE1;
5468 Warpout_sound = snd_play(&Snds[SND_PLAYER_WARP_OUT]);
5469 Warpout_time = 0.0f; // Start timer!
5472 case GS_EVENT_PLAYER_WARPOUT_START:
5473 if ( Player->control_mode != PCM_NORMAL ) {
5474 mprintf(( "Player isn't in normal mode; cannot warp out.\n" ));
5476 Player->saved_viewer_mode = Viewer_mode;
5477 Player->control_mode = PCM_WARPOUT_STAGE1;
5478 Warpout_sound = snd_play(&Snds[SND_PLAYER_WARP_OUT]);
5479 Warpout_time = 0.0f; // Start timer!
5480 Warpout_forced = 0; // If non-zero, bash the player to speed and go through effect
5484 case GS_EVENT_PLAYER_WARPOUT_STOP:
5485 if ( Player->control_mode != PCM_NORMAL ) {
5486 if ( !Warpout_forced ) { // cannot cancel forced warpout
5487 Player->control_mode = PCM_NORMAL;
5488 Viewer_mode = Player->saved_viewer_mode;
5489 hud_subspace_notify_abort();
5490 mprintf(( "Player put back to normal mode.\n" ));
5491 if ( Warpout_sound > -1 ) {
5492 snd_stop( Warpout_sound );
5499 case GS_EVENT_PLAYER_WARPOUT_DONE_STAGE1: // player ship got up to speed
5500 if ( Player->control_mode != PCM_WARPOUT_STAGE1 ) {
5501 gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_STOP );
5502 mprintf(( "Player put back to normal mode, because of invalid sequence in stage1.\n" ));
5504 mprintf(( "Hit target speed. Starting warp effect and moving to stage 2!\n" ));
5505 shipfx_warpout_start( Player_obj );
5506 Player->control_mode = PCM_WARPOUT_STAGE2;
5507 Player->saved_viewer_mode = Viewer_mode;
5508 Viewer_mode |= VM_WARP_CHASE;
5510 vector tmp = Player_obj->pos;
5512 ship_get_eye( &tmp, &tmp_m, Player_obj );
5513 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.rvec, 0.0f );
5514 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.uvec, 0.952f );
5515 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.fvec, -1.782f );
5517 camera_set_position( &tmp );
5518 camera_set_orient( &Player_obj->orient );
5519 vector tmp_vel = { { { 0.0f, 5.1919f, 14.7f } } };
5521 //mprintf(( "Rad = %.1f\n", Player_obj->radius ));
5522 camera_set_velocity( &tmp_vel, 1);
5526 case GS_EVENT_PLAYER_WARPOUT_DONE_STAGE2: // player ship got into the warp effect
5527 if ( Player->control_mode != PCM_WARPOUT_STAGE2 ) {
5528 gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_STOP );
5529 mprintf(( "Player put back to normal mode, because of invalid sequence in stage2.\n" ));
5531 mprintf(( "Hit warp effect. Moving to stage 3!\n" ));
5532 Player->control_mode = PCM_WARPOUT_STAGE3;
5536 case GS_EVENT_PLAYER_WARPOUT_DONE: // player ship got through the warp effect
5537 mprintf(( "Player warped out. Going to debriefing!\n" ));
5538 Player->control_mode = PCM_NORMAL;
5539 Viewer_mode = Player->saved_viewer_mode;
5542 // we have a special debriefing screen for multiplayer furballs
5543 if((Game_mode & GM_MULTIPLAYER) && (The_mission.game_type & MISSION_TYPE_MULTI_DOGFIGHT)){
5544 gameseq_post_event(GS_EVENT_MULTI_DOGFIGHT_DEBRIEF);
5546 // do the normal debriefing for all other situations
5548 gameseq_post_event(GS_EVENT_DEBRIEF);
5552 case GS_EVENT_STANDALONE_POSTGAME:
5553 gameseq_set_state(GS_STATE_STANDALONE_POSTGAME);
5556 case GS_EVENT_INITIAL_PLAYER_SELECT:
5557 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5560 case GS_EVENT_GAME_INIT:
5561 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
5562 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5564 // see if the command line option has been set to use the last pilot, and act acoordingly
5565 if( player_select_get_last_pilot() ) {
5566 // always enter the main menu -- do the automatic network startup stuff elsewhere
5567 // so that we still have valid checks for networking modes, etc.
5568 gameseq_set_state(GS_STATE_MAIN_MENU);
5570 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5575 case GS_EVENT_MULTI_MISSION_SYNC:
5576 gameseq_set_state(GS_STATE_MULTI_MISSION_SYNC);
5579 case GS_EVENT_MULTI_START_GAME:
5580 gameseq_set_state(GS_STATE_MULTI_START_GAME);
5583 case GS_EVENT_MULTI_HOST_OPTIONS:
5584 gameseq_set_state(GS_STATE_MULTI_HOST_OPTIONS);
5587 case GS_EVENT_MULTI_DOGFIGHT_DEBRIEF:
5588 gameseq_set_state(GS_STATE_MULTI_DOGFIGHT_DEBRIEF);
5591 case GS_EVENT_TEAM_SELECT:
5592 gameseq_set_state(GS_STATE_TEAM_SELECT);
5595 case GS_EVENT_END_CAMPAIGN:
5596 gameseq_set_state(GS_STATE_END_OF_CAMPAIGN);
5599 case GS_EVENT_END_DEMO:
5600 gameseq_set_state(GS_STATE_END_DEMO);
5603 case GS_EVENT_LOOP_BRIEF:
5604 gameseq_set_state(GS_STATE_LOOP_BRIEF);
5613 // Called when a state is being left.
5614 // The current state is still at old_state, but as soon as
5615 // this function leaves, then the current state will become
5616 // new state. You should never try to change the state
5617 // in here... if you think you need to, you probably really
5618 // need to post an event, not change the state.
5619 void game_leave_state( int old_state, int new_state )
5621 int end_mission = 1;
5623 switch (new_state) {
5624 case GS_STATE_GAME_PAUSED:
5625 case GS_STATE_DEBUG_PAUSED:
5626 case GS_STATE_OPTIONS_MENU:
5627 case GS_STATE_CONTROL_CONFIG:
5628 case GS_STATE_MISSION_LOG_SCROLLBACK:
5629 case GS_STATE_DEATH_DIED:
5630 case GS_STATE_SHOW_GOALS:
5631 case GS_STATE_HOTKEY_SCREEN:
5632 case GS_STATE_MULTI_PAUSED:
5633 case GS_STATE_TRAINING_PAUSED:
5634 case GS_STATE_EVENT_DEBUG:
5635 case GS_STATE_GAMEPLAY_HELP:
5636 end_mission = 0; // these events shouldn't end a mission
5640 switch (old_state) {
5641 case GS_STATE_BRIEFING:
5642 brief_stop_voices();
5643 if ( (new_state != GS_STATE_OPTIONS_MENU) && (new_state != GS_STATE_WEAPON_SELECT)
5644 && (new_state != GS_STATE_SHIP_SELECT) && (new_state != GS_STATE_HOTKEY_SCREEN)
5645 && (new_state != GS_STATE_TEAM_SELECT) ){
5646 common_select_close();
5647 if ( new_state == GS_STATE_MAIN_MENU ) {
5648 freespace_stop_mission();
5652 // COMMAND LINE OPTION
5653 if (Cmdline_multi_stream_chat_to_file){
5654 cfwrite_string(NOX("-------------------------------------------\n"),Multi_chat_stream);
5655 cfclose(Multi_chat_stream);
5659 case GS_STATE_DEBRIEF:
5660 if ( (new_state != GS_STATE_VIEW_MEDALS) && (new_state != GS_STATE_OPTIONS_MENU) ) {
5665 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
5666 multi_df_debrief_close();
5669 case GS_STATE_LOAD_MISSION_MENU:
5670 mission_load_menu_close();
5673 case GS_STATE_SIMULATOR_ROOM:
5677 case GS_STATE_CAMPAIGN_ROOM:
5678 campaign_room_close();
5681 case GS_STATE_CMD_BRIEF:
5682 if (new_state == GS_STATE_OPTIONS_MENU) {
5687 if (new_state == GS_STATE_MAIN_MENU)
5688 freespace_stop_mission();
5693 case GS_STATE_RED_ALERT:
5697 case GS_STATE_SHIP_SELECT:
5698 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_WEAPON_SELECT &&
5699 new_state != GS_STATE_HOTKEY_SCREEN &&
5700 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_TEAM_SELECT) {
5701 common_select_close();
5702 if ( new_state == GS_STATE_MAIN_MENU ) {
5703 freespace_stop_mission();
5708 case GS_STATE_WEAPON_SELECT:
5709 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_SHIP_SELECT &&
5710 new_state != GS_STATE_HOTKEY_SCREEN &&
5711 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_TEAM_SELECT) {
5712 common_select_close();
5713 if ( new_state == GS_STATE_MAIN_MENU ) {
5714 freespace_stop_mission();
5719 case GS_STATE_TEAM_SELECT:
5720 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_SHIP_SELECT &&
5721 new_state != GS_STATE_HOTKEY_SCREEN &&
5722 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_WEAPON_SELECT) {
5723 common_select_close();
5724 if ( new_state == GS_STATE_MAIN_MENU ) {
5725 freespace_stop_mission();
5730 case GS_STATE_MAIN_MENU:
5731 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
5738 case GS_STATE_OPTIONS_MENU:
5739 //game_start_time();
5740 if(new_state == GS_STATE_MULTI_JOIN_GAME){
5741 multi_join_clear_game_list();
5743 options_menu_close();
5746 case GS_STATE_BARRACKS_MENU:
5747 if(new_state != GS_STATE_VIEW_MEDALS){
5752 case GS_STATE_MISSION_LOG_SCROLLBACK:
5753 hud_scrollback_close();
5756 case GS_STATE_TRAINING_MENU:
5757 training_menu_close();
5760 case GS_STATE_GAME_PLAY:
5761 if ( !(Game_mode & GM_STANDALONE_SERVER) ) {
5762 player_save_target_and_weapon_link_prefs();
5763 game_stop_looped_sounds();
5766 sound_env_disable();
5767 joy_ff_stop_effects();
5769 // stop game time under certain conditions
5770 if ( end_mission || (Game_mode & GM_NORMAL) || ((Game_mode & GM_MULTIPLAYER) && (new_state == GS_STATE_MULTI_PAUSED)) ){
5775 // shut down any recording or playing demos
5780 // when in multiplayer and going back to the main menu, send a leave game packet
5781 // right away (before calling stop mission). stop_mission was taking to long to
5782 // close mission down and I want people to get notified ASAP.
5783 if ( (Game_mode & GM_MULTIPLAYER) && (new_state == GS_STATE_MAIN_MENU) ){
5784 multi_quit_game(PROMPT_NONE);
5787 freespace_stop_mission();
5788 Game_time_compression = F1_0;
5792 case GS_STATE_TECH_MENU:
5796 case GS_STATE_TRAINING_PAUSED:
5797 Training_num_lines = 0;
5798 // fall through to GS_STATE_GAME_PAUSED
5800 case GS_STATE_GAME_PAUSED:
5802 if ( end_mission ) {
5807 case GS_STATE_DEBUG_PAUSED:
5810 pause_debug_close();
5814 case GS_STATE_HUD_CONFIG:
5818 // join/start a game
5819 case GS_STATE_MULTI_JOIN_GAME:
5820 if(new_state != GS_STATE_OPTIONS_MENU){
5821 multi_join_game_close();
5825 case GS_STATE_MULTI_HOST_SETUP:
5826 case GS_STATE_MULTI_CLIENT_SETUP:
5827 // if this is just the host going into the options screen, don't do anything
5828 if((new_state == GS_STATE_MULTI_HOST_OPTIONS) || (new_state == GS_STATE_OPTIONS_MENU)){
5832 // close down the proper state
5833 if(old_state == GS_STATE_MULTI_HOST_SETUP){
5834 multi_create_game_close();
5836 multi_game_client_setup_close();
5839 // COMMAND LINE OPTION
5840 if (Cmdline_multi_stream_chat_to_file){
5841 if( (new_state != GS_STATE_TEAM_SELECT) && (Multi_chat_stream!=NULL) ) {
5842 cfwrite_string(NOX("-------------------------------------------\n"),Multi_chat_stream);
5843 cfclose(Multi_chat_stream);
5848 case GS_STATE_CONTROL_CONFIG:
5849 control_config_close();
5852 case GS_STATE_DEATH_DIED:
5853 Game_mode &= ~GM_DEAD_DIED;
5855 // early end while respawning or blowing up in a multiplayer game
5856 if((Game_mode & GM_MULTIPLAYER) && ((new_state == GS_STATE_DEBRIEF) || (new_state == GS_STATE_MULTI_DOGFIGHT_DEBRIEF)) ){
5858 freespace_stop_mission();
5862 case GS_STATE_DEATH_BLEW_UP:
5863 Game_mode &= ~GM_DEAD_BLEW_UP;
5865 // for single player, we might reload mission, etc. For multiplayer, look at my new state
5866 // to determine if I should do anything.
5867 if ( !(Game_mode & GM_MULTIPLAYER) ) {
5869 freespace_stop_mission();
5872 // if we are not respawing as an observer or as a player, our new state will not
5873 // be gameplay state.
5874 if ( (new_state != GS_STATE_GAME_PLAY) && (new_state != GS_STATE_MULTI_PAUSED) ) {
5875 game_stop_time(); // hasn't been called yet!!
5876 freespace_stop_mission();
5882 case GS_STATE_CREDITS:
5886 case GS_STATE_VIEW_MEDALS:
5890 case GS_STATE_SHOW_GOALS:
5891 mission_show_goals_close();
5894 case GS_STATE_HOTKEY_SCREEN:
5895 if ( new_state != GS_STATE_OPTIONS_MENU ) {
5896 mission_hotkey_close();
5900 case GS_STATE_MULTI_MISSION_SYNC:
5901 // if we're moving into the options menu, don't do anything
5902 if(new_state == GS_STATE_OPTIONS_MENU){
5906 SDL_assert( Game_mode & GM_MULTIPLAYER );
5908 if ( new_state == GS_STATE_GAME_PLAY ){
5909 // palette_restore_palette();
5911 // change a couple of flags to indicate our state!!!
5912 Net_player->state = NETPLAYER_STATE_IN_MISSION;
5913 send_netplayer_update_packet();
5915 // set the game mode
5916 Game_mode |= GM_IN_MISSION;
5920 case GS_STATE_VIEW_CUTSCENES:
5921 cutscenes_screen_close();
5924 case GS_STATE_MULTI_STD_WAIT:
5925 multi_standalone_wait_close();
5928 case GS_STATE_STANDALONE_MAIN:
5929 standalone_main_close();
5930 if(new_state == GS_STATE_MULTI_STD_WAIT){
5931 init_multiplayer_stats();
5935 case GS_STATE_MULTI_PAUSED:
5936 // if ( end_mission ){
5941 case GS_STATE_INGAME_PRE_JOIN:
5942 multi_ingame_select_close();
5945 case GS_STATE_STANDALONE_POSTGAME:
5946 multi_standalone_postgame_close();
5949 case GS_STATE_INITIAL_PLAYER_SELECT:
5950 player_select_close();
5953 case GS_STATE_MULTI_START_GAME:
5954 multi_start_game_close();
5957 case GS_STATE_MULTI_HOST_OPTIONS:
5958 multi_host_options_close();
5961 case GS_STATE_END_OF_CAMPAIGN:
5962 mission_campaign_end_close();
5965 case GS_STATE_LOOP_BRIEF:
5971 // Called when a state is being entered.
5972 // The current state is set to the state we're entering at
5973 // this point, and old_state is set to the state we're coming
5974 // from. You should never try to change the state
5975 // in here... if you think you need to, you probably really
5976 // need to post an event, not change the state.
5978 void game_enter_state( int old_state, int new_state )
5980 switch (new_state) {
5981 case GS_STATE_MAIN_MENU:
5982 // in multiplayer mode, be sure that we are not doing networking anymore.
5983 if ( Game_mode & GM_MULTIPLAYER ) {
5984 SDL_assert( Net_player != NULL );
5985 Net_player->flags &= ~NETINFO_FLAG_DO_NETWORKING;
5988 Game_time_compression = F1_0;
5990 // determine which ship this guy is currently based on
5991 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
5994 if (Player->on_bastion) {
6002 case GS_STATE_BRIEFING:
6003 main_hall_stop_music();
6004 main_hall_stop_ambient();
6006 if (Game_mode & GM_NORMAL) {
6007 // AL: Don't call freespace_start_mission() if re-entering from ship or weapon select
6008 // MWA: or from options or hotkey screens
6009 // JH: or if the command brief state already did this
6010 if ( (old_state != GS_STATE_OPTIONS_MENU) && (old_state != GS_STATE_HOTKEY_SCREEN)
6011 && (old_state != GS_STATE_SHIP_SELECT) && (old_state != GS_STATE_WEAPON_SELECT)
6012 && (old_state != GS_STATE_CMD_BRIEF) ) {
6013 if ( !game_start_mission() ) // this should put us into a new state on failure!
6017 // maybe play a movie before the briefing. don't play if entering briefing screen from ship or weapon select.
6018 if ( (old_state == GS_STATE_DEBRIEF) || (old_state == GS_STATE_SIMULATOR_ROOM) || (old_state == GS_STATE_MAIN_MENU))
6019 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
6021 Game_time_compression = F1_0;
6023 if ( red_alert_mission() ) {
6024 gameseq_post_event(GS_EVENT_RED_ALERT);
6031 case GS_STATE_DEBRIEF:
6032 game_stop_looped_sounds();
6033 mission_goal_fail_incomplete(); // fail all incomplete goals before entering debriefing
6034 if ( (old_state != GS_STATE_VIEW_MEDALS) && (old_state != GS_STATE_OPTIONS_MENU) ){
6039 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
6040 multi_df_debrief_init();
6043 case GS_STATE_LOAD_MISSION_MENU:
6044 mission_load_menu_init();
6047 case GS_STATE_SIMULATOR_ROOM:
6051 case GS_STATE_CAMPAIGN_ROOM:
6052 campaign_room_init();
6055 case GS_STATE_RED_ALERT:
6056 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
6060 case GS_STATE_CMD_BRIEF: {
6061 int team_num = 0; // team number used as index for which cmd brief to use.
6063 if (old_state == GS_STATE_OPTIONS_MENU) {
6067 main_hall_stop_music();
6068 main_hall_stop_ambient();
6070 if (Game_mode & GM_NORMAL) {
6071 // AL: Don't call freespace_start_mission() if re-entering from ship or weapon select
6072 // MWA: or from options or hotkey screens
6073 // JH: or if the command brief state already did this
6074 if ( (old_state != GS_STATE_OPTIONS_MENU) && (old_state != GS_STATE_HOTKEY_SCREEN)
6075 && (old_state != GS_STATE_SHIP_SELECT) && (old_state != GS_STATE_WEAPON_SELECT) ) {
6076 if ( !game_start_mission() ) // this should put us into a new state on failure!
6081 // maybe play a movie before the briefing. don't play if entering briefing screen from ship or weapon select.
6082 if ( (old_state == GS_STATE_DEBRIEF) || (old_state == GS_STATE_SIMULATOR_ROOM) || (old_state == GS_STATE_MAIN_MENU))
6083 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
6085 cmd_brief_init(team_num);
6091 case GS_STATE_SHIP_SELECT:
6095 case GS_STATE_WEAPON_SELECT:
6096 weapon_select_init();
6099 case GS_STATE_TEAM_SELECT:
6103 case GS_STATE_GAME_PAUSED:
6108 case GS_STATE_DEBUG_PAUSED:
6109 // game_stop_time();
6110 // os_set_title("FreeSpace - PAUSED");
6113 case GS_STATE_TRAINING_PAUSED:
6120 case GS_STATE_OPTIONS_MENU:
6122 options_menu_init();
6125 case GS_STATE_GAME_PLAY:
6126 // coming from the gameplay state or the main menu, we might need to load the mission
6127 if ( (Game_mode & GM_NORMAL) && ((old_state == GS_STATE_MAIN_MENU) || (old_state == GS_STATE_GAME_PLAY) || (old_state == GS_STATE_DEATH_BLEW_UP)) ) {
6128 if ( !game_start_mission() ) // this should put us into a new state.
6133 // if we are coming from the briefing, ship select, weapons loadout, or main menu (in the
6134 // case of quick start), then do bitmap loads, etc Don't do any of the loading stuff
6135 // if we are in multiplayer -- this stuff is all handled in the multi-wait section
6136 if ( !(Game_mode & GM_MULTIPLAYER) && ((old_state == GS_STATE_BRIEFING) || (old_state == GS_STATE_SHIP_SELECT) ||
6137 (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)) ) {
6138 // JAS: Used to do all paging here.
6142 HUD_printf("Skill level is set to ** %s **", Skill_level_names(Game_skill_level));
6146 main_hall_stop_music();
6147 main_hall_stop_ambient();
6148 event_music_first_pattern(); // start the first pattern
6151 // special code that restores player ship selection and weapons loadout when doing a quick start
6152 if ( !(Game_mode & GM_MULTIPLAYER) && ((old_state == GS_STATE_MAIN_MENU) || (old_state == GS_STATE_DEATH_BLEW_UP) || (old_state == GS_STATE_GAME_PLAY)) ) {
6153 if ( !SDL_strcasecmp(Player_loadout.filename, Game_current_mission_filename) ) {
6154 wss_direct_restore_loadout();
6158 // single-player, quick-start after just died... we need to set weapon linking and kick off the event music
6159 if (!(Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_DEATH_BLEW_UP) ) {
6160 event_music_first_pattern(); // start the first pattern
6163 if ( !(Game_mode & GM_STANDALONE_SERVER) && (old_state != GS_STATE_GAME_PAUSED) && (old_state != GS_STATE_MULTI_PAUSED) ) {
6164 event_music_first_pattern(); // start the first pattern
6166 player_restore_target_and_weapon_link_prefs();
6168 Game_mode |= GM_IN_MISSION;
6171 // required to truely make mouse deltas zeroed in debug mouse code
6172 void mouse_force_pos(int x, int y);
6173 if (!Is_standalone) {
6174 mouse_force_pos(gr_screen.max_w / 2, gr_screen.max_h / 2);
6180 // only start time if in single player, or coming from multi wait state
6183 (Game_mode & GM_NORMAL) &&
6184 (old_state != GS_STATE_VIEW_CUTSCENES)
6186 (Game_mode & GM_MULTIPLAYER) && (
6187 (old_state == GS_STATE_MULTI_PAUSED) ||
6188 (old_state == GS_STATE_MULTI_MISSION_SYNC)
6194 // when coming from the multi paused state, reset the timestamps
6195 if ( (Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_MULTI_PAUSED) ){
6196 multi_reset_timestamps();
6199 if ((Game_mode & GM_MULTIPLAYER) && (old_state != GS_STATE_DEATH_BLEW_UP) ) {
6200 // initialize all object update details
6201 multi_oo_gameplay_init();
6204 // under certain circumstances, the server should reset the object update rate limiting stuff
6205 if( ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)) &&
6206 ((old_state == GS_STATE_MULTI_PAUSED) || (old_state == GS_STATE_MULTI_MISSION_SYNC)) ){
6208 // reinitialize the rate limiting system for all clients
6209 multi_oo_rate_init_all();
6212 // multiplayer clients should always re-initialize their control info rate limiting system
6213 if((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER)){
6214 multi_oo_rate_init_all();
6218 if(Game_mode & GM_MULTIPLAYER){
6219 multi_ping_reset_players();
6222 Game_subspace_effect = 0;
6223 if (The_mission.flags & MISSION_FLAG_SUBSPACE) {
6224 Game_subspace_effect = 1;
6225 if( !(Game_mode & GM_STANDALONE_SERVER) ){
6226 game_start_subspace_ambient_sound();
6230 sound_env_set(&Game_sound_env);
6231 joy_ff_mission_init(Ship_info[Player_ship->ship_info_index].rotation_time);
6233 // clear multiplayer button info i
6234 extern button_info Multi_ship_status_bi;
6235 memset(&Multi_ship_status_bi, 0, sizeof(button_info));
6238 case GS_STATE_HUD_CONFIG:
6242 case GS_STATE_MULTI_JOIN_GAME:
6243 multi_join_clear_game_list();
6245 if (old_state != GS_STATE_OPTIONS_MENU) {
6246 multi_join_game_init();
6251 case GS_STATE_MULTI_HOST_SETUP:
6252 // don't reinitialize if we're coming back from the host options screen
6253 if ((old_state != GS_STATE_MULTI_HOST_OPTIONS) && (old_state != GS_STATE_OPTIONS_MENU)) {
6254 multi_create_game_init();
6259 case GS_STATE_MULTI_CLIENT_SETUP:
6260 if (old_state != GS_STATE_OPTIONS_MENU) {
6261 multi_game_client_setup_init();
6266 case GS_STATE_CONTROL_CONFIG:
6267 control_config_init();
6270 case GS_STATE_TECH_MENU:
6274 case GS_STATE_BARRACKS_MENU:
6275 if(old_state != GS_STATE_VIEW_MEDALS){
6280 case GS_STATE_MISSION_LOG_SCROLLBACK:
6281 hud_scrollback_init();
6284 case GS_STATE_DEATH_DIED:
6285 Player_died_time = timestamp(10);
6287 if(!(Game_mode & GM_MULTIPLAYER)){
6288 player_show_death_message();
6290 Game_mode |= GM_DEAD_DIED;
6293 case GS_STATE_DEATH_BLEW_UP:
6294 if ( !popupdead_is_active() ) {
6295 Player_ai->target_objnum = -1;
6298 // stop any local EMP effect
6301 Players[Player_num].flags &= ~PLAYER_FLAGS_AUTO_TARGETING; // Prevent immediate switch to a hostile ship.
6302 Game_mode |= GM_DEAD_BLEW_UP;
6303 Show_viewing_from_self = 0;
6305 // timestamp how long we should wait before displaying the died popup
6306 if ( !popupdead_is_active() ) {
6307 Player_died_popup_wait = timestamp(PLAYER_DIED_POPUP_WAIT);
6311 case GS_STATE_GAMEPLAY_HELP:
6312 gameplay_help_init();
6315 case GS_STATE_CREDITS:
6316 main_hall_stop_music();
6317 main_hall_stop_ambient();
6321 case GS_STATE_VIEW_MEDALS:
6322 medal_main_init(Player);
6325 case GS_STATE_SHOW_GOALS:
6326 mission_show_goals_init();
6329 case GS_STATE_HOTKEY_SCREEN:
6330 mission_hotkey_init();
6333 case GS_STATE_MULTI_MISSION_SYNC:
6334 // if we're coming from the options screen, don't do any
6335 if(old_state == GS_STATE_OPTIONS_MENU){
6339 switch(Multi_sync_mode){
6340 case MULTI_SYNC_PRE_BRIEFING:
6341 // if moving from game forming to the team select state
6344 case MULTI_SYNC_POST_BRIEFING:
6345 // if moving from briefing into the mission itself
6348 // tell everyone that we're now loading data
6349 Net_player->state = NETPLAYER_STATE_DATA_LOAD;
6350 send_netplayer_update_packet();
6352 // JAS: Used to do all paging here!!!!
6354 Net_player->state = NETPLAYER_STATE_WAITING;
6355 send_netplayer_update_packet();
6357 Game_time_compression = F1_0;
6359 case MULTI_SYNC_INGAME:
6365 case GS_STATE_VIEW_CUTSCENES:
6366 cutscenes_screen_init();
6369 case GS_STATE_MULTI_STD_WAIT:
6370 multi_standalone_wait_init();
6373 case GS_STATE_STANDALONE_MAIN:
6374 // don't initialize if we're coming from one of these 2 states unless there are no
6375 // players left (reset situation)
6376 if((old_state != GS_STATE_STANDALONE_POSTGAME) || multi_endgame_ending()){
6377 standalone_main_init();
6381 case GS_STATE_MULTI_PAUSED:
6385 case GS_STATE_INGAME_PRE_JOIN:
6386 multi_ingame_select_init();
6389 case GS_STATE_STANDALONE_POSTGAME:
6390 multi_standalone_postgame_init();
6393 case GS_STATE_INITIAL_PLAYER_SELECT:
6394 player_select_init();
6397 case GS_STATE_MULTI_START_GAME:
6398 multi_start_game_init();
6401 case GS_STATE_MULTI_HOST_OPTIONS:
6402 multi_host_options_init();
6405 case GS_STATE_END_OF_CAMPAIGN:
6406 mission_campaign_end_init();
6409 case GS_STATE_LOOP_BRIEF:
6416 // do stuff that may need to be done regardless of state
6417 void game_do_state_common(int state,int no_networking)
6419 game_maybe_draw_mouse(flFrametime); // determine if to draw the mouse this frame
6420 snd_do_frame(); // update sound system
6421 event_music_do_frame(); // music needs to play across many states
6423 multi_log_process();
6425 if (no_networking) {
6429 // maybe do a multiplayer frame based on game mode and state type
6430 if (Game_mode & GM_MULTIPLAYER) {
6432 case GS_STATE_OPTIONS_MENU:
6433 case GS_STATE_GAMEPLAY_HELP:
6434 case GS_STATE_HOTKEY_SCREEN:
6435 case GS_STATE_HUD_CONFIG:
6436 case GS_STATE_CONTROL_CONFIG:
6437 case GS_STATE_MISSION_LOG_SCROLLBACK:
6438 case GS_STATE_SHOW_GOALS:
6439 case GS_STATE_VIEW_CUTSCENES:
6440 case GS_STATE_EVENT_DEBUG:
6441 multi_maybe_do_frame();
6445 game_do_networking();
6449 // Called once a frame.
6450 // You should never try to change the state
6451 // in here... if you think you need to, you probably really
6452 // need to post an event, not change the state.
6453 int Game_do_state_should_skip = 0;
6454 void game_do_state(int state)
6456 // always lets the do_state_common() function determine if the state should be skipped
6457 Game_do_state_should_skip = 0;
6459 // legal to set the should skip state anywhere in this function
6460 game_do_state_common(state); // do stuff that may need to be done regardless of state
6462 if(Game_do_state_should_skip){
6467 case GS_STATE_MAIN_MENU:
6468 game_set_frametime(GS_STATE_MAIN_MENU);
6469 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
6472 main_hall_do(flFrametime);
6476 case GS_STATE_OPTIONS_MENU:
6477 game_set_frametime(GS_STATE_OPTIONS_MENU);
6478 options_menu_do_frame(flFrametime);
6481 case GS_STATE_BARRACKS_MENU:
6482 game_set_frametime(GS_STATE_BARRACKS_MENU);
6483 barracks_do_frame(flFrametime);
6486 case GS_STATE_TRAINING_MENU:
6487 game_set_frametime(GS_STATE_TRAINING_MENU);
6488 training_menu_do_frame(flFrametime);
6491 case GS_STATE_TECH_MENU:
6492 game_set_frametime(GS_STATE_TECH_MENU);
6493 techroom_do_frame(flFrametime);
6496 case GS_STATE_GAMEPLAY_HELP:
6497 game_set_frametime(GS_STATE_GAMEPLAY_HELP);
6498 gameplay_help_do_frame(flFrametime);
6501 case GS_STATE_GAME_PLAY: // do stuff that should be done during gameplay
6505 case GS_STATE_GAME_PAUSED:
6509 case GS_STATE_DEBUG_PAUSED:
6511 game_set_frametime(GS_STATE_DEBUG_PAUSED);
6516 case GS_STATE_TRAINING_PAUSED:
6517 game_training_pause_do();
6520 case GS_STATE_LOAD_MISSION_MENU:
6521 game_set_frametime(GS_STATE_LOAD_MISSION_MENU);
6522 mission_load_menu_do();
6525 case GS_STATE_BRIEFING:
6526 game_set_frametime(GS_STATE_BRIEFING);
6527 brief_do_frame(flFrametime);
6530 case GS_STATE_DEBRIEF:
6531 game_set_frametime(GS_STATE_DEBRIEF);
6532 debrief_do_frame(flFrametime);
6535 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
6536 game_set_frametime(GS_STATE_MULTI_DOGFIGHT_DEBRIEF);
6537 multi_df_debrief_do();
6540 case GS_STATE_SHIP_SELECT:
6541 game_set_frametime(GS_STATE_SHIP_SELECT);
6542 ship_select_do(flFrametime);
6545 case GS_STATE_WEAPON_SELECT:
6546 game_set_frametime(GS_STATE_WEAPON_SELECT);
6547 weapon_select_do(flFrametime);
6550 case GS_STATE_MISSION_LOG_SCROLLBACK:
6551 game_set_frametime(GS_STATE_MISSION_LOG_SCROLLBACK);
6552 hud_scrollback_do_frame(flFrametime);
6555 case GS_STATE_HUD_CONFIG:
6556 game_set_frametime(GS_STATE_HUD_CONFIG);
6557 hud_config_do_frame(flFrametime);
6560 case GS_STATE_MULTI_JOIN_GAME:
6561 game_set_frametime(GS_STATE_MULTI_JOIN_GAME);
6562 multi_join_game_do_frame();
6565 case GS_STATE_MULTI_HOST_SETUP:
6566 game_set_frametime(GS_STATE_MULTI_HOST_SETUP);
6567 multi_create_game_do();
6570 case GS_STATE_MULTI_CLIENT_SETUP:
6571 game_set_frametime(GS_STATE_MULTI_CLIENT_SETUP);
6572 multi_game_client_setup_do_frame();
6575 case GS_STATE_CONTROL_CONFIG:
6576 game_set_frametime(GS_STATE_CONTROL_CONFIG);
6577 control_config_do_frame(flFrametime);
6580 case GS_STATE_DEATH_DIED:
6584 case GS_STATE_DEATH_BLEW_UP:
6588 case GS_STATE_SIMULATOR_ROOM:
6589 game_set_frametime(GS_STATE_SIMULATOR_ROOM);
6590 sim_room_do_frame(flFrametime);
6593 case GS_STATE_CAMPAIGN_ROOM:
6594 game_set_frametime(GS_STATE_CAMPAIGN_ROOM);
6595 campaign_room_do_frame(flFrametime);
6598 case GS_STATE_RED_ALERT:
6599 game_set_frametime(GS_STATE_RED_ALERT);
6600 red_alert_do_frame(flFrametime);
6603 case GS_STATE_CMD_BRIEF:
6604 game_set_frametime(GS_STATE_CMD_BRIEF);
6605 cmd_brief_do_frame(flFrametime);
6608 case GS_STATE_CREDITS:
6609 game_set_frametime(GS_STATE_CREDITS);
6610 credits_do_frame(flFrametime);
6613 case GS_STATE_VIEW_MEDALS:
6614 game_set_frametime(GS_STATE_VIEW_MEDALS);
6618 case GS_STATE_SHOW_GOALS:
6619 game_set_frametime(GS_STATE_SHOW_GOALS);
6620 mission_show_goals_do_frame(flFrametime);
6623 case GS_STATE_HOTKEY_SCREEN:
6624 game_set_frametime(GS_STATE_HOTKEY_SCREEN);
6625 mission_hotkey_do_frame(flFrametime);
6628 case GS_STATE_VIEW_CUTSCENES:
6629 game_set_frametime(GS_STATE_VIEW_CUTSCENES);
6630 cutscenes_screen_do_frame();
6633 case GS_STATE_MULTI_STD_WAIT:
6634 game_set_frametime(GS_STATE_STANDALONE_MAIN);
6635 multi_standalone_wait_do();
6638 case GS_STATE_STANDALONE_MAIN:
6639 game_set_frametime(GS_STATE_STANDALONE_MAIN);
6640 standalone_main_do();
6643 case GS_STATE_MULTI_PAUSED:
6644 game_set_frametime(GS_STATE_MULTI_PAUSED);
6648 case GS_STATE_TEAM_SELECT:
6649 game_set_frametime(GS_STATE_TEAM_SELECT);
6653 case GS_STATE_INGAME_PRE_JOIN:
6654 game_set_frametime(GS_STATE_INGAME_PRE_JOIN);
6655 multi_ingame_select_do();
6658 case GS_STATE_EVENT_DEBUG:
6660 game_set_frametime(GS_STATE_EVENT_DEBUG);
6661 game_show_event_debug(flFrametime);
6665 case GS_STATE_STANDALONE_POSTGAME:
6666 game_set_frametime(GS_STATE_STANDALONE_POSTGAME);
6667 multi_standalone_postgame_do();
6670 case GS_STATE_INITIAL_PLAYER_SELECT:
6671 game_set_frametime(GS_STATE_INITIAL_PLAYER_SELECT);
6675 case GS_STATE_MULTI_MISSION_SYNC:
6676 game_set_frametime(GS_STATE_MULTI_MISSION_SYNC);
6680 case GS_STATE_MULTI_START_GAME:
6681 game_set_frametime(GS_STATE_MULTI_START_GAME);
6682 multi_start_game_do();
6685 case GS_STATE_MULTI_HOST_OPTIONS:
6686 game_set_frametime(GS_STATE_MULTI_HOST_OPTIONS);
6687 multi_host_options_do();
6690 case GS_STATE_END_OF_CAMPAIGN:
6691 mission_campaign_end_do();
6694 case GS_STATE_END_DEMO:
6695 game_set_frametime(GS_STATE_END_DEMO);
6696 end_demo_campaign_do();
6699 case GS_STATE_LOOP_BRIEF:
6700 game_set_frametime(GS_STATE_LOOP_BRIEF);
6704 } // end switch(gs_current_state)
6708 // return 0 if there is enough RAM to run FreeSpace, otherwise return -1
6709 int game_do_ram_check(int ram_in_mbytes)
6711 if ( ram_in_mbytes < 30 ) {
6712 int allowed_to_run = 1;
6713 if ( ram_in_mbytes < 25 ) {
6719 if ( allowed_to_run ) {
6720 SDL_MessageBoxData mboxd;
6721 SDL_MessageBoxButtonData mboxbuttons[2];
6724 // not a translated string, but it's too long and smartdrv isn't
6725 // really a thing for any OS we now support :p
6726 // 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);
6727 sprintf( tmp, "FreeSpace has detected that you only have %dMB of free memory.\n\nFreeSpace requires at least 32MB of memory to run.\n\nPress 'OK' to continue running with less than the minimum required memory.\n", ram_in_mbytes);
6729 mboxbuttons[0].buttonid = 0;
6730 mboxbuttons[0].text = XSTR("Ok", 503);
6731 mboxbuttons[0].flags = 0;
6733 mboxbuttons[1].buttonid = 1;
6734 mboxbuttons[1].text = XSTR("Cancel", 504);
6735 mboxbuttons[0].flags = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT | SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT;
6737 mboxd.flags = SDL_MESSAGEBOX_ERROR;
6738 mboxd.title = XSTR( "Not Enough RAM", 194);
6739 mboxd.message = tmp;
6740 mboxd.numbuttons = 2;
6741 mboxd.buttons = mboxbuttons;
6742 mboxd.window = NULL;
6743 mboxd.colorScheme = NULL;
6745 SDL_ShowMessageBox(&mboxd, &msgbox_rval);
6747 if ( msgbox_rval == 1 ) {
6751 // not a translated string, but it's too long and smartdrv isn't
6752 // really a thing for any OS we now support :p
6753 // 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);
6754 sprintf( tmp, "FreeSpace has detected that you only have %dMB of free memory.\n\nFreeSpace requires at least 32MB of memory to run.\n", ram_in_mbytes);
6756 SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, XSTR( "Not Enough RAM", 194), tmp, NULL);
6765 // Check if there is a freespace.exe in the /update directory (relative to where fs.exe is installed).
6766 // If so, copy it over and remove the update directory.
6767 void game_maybe_update_launcher(char *exe_dir)
6770 char src_filename[MAX_PATH];
6771 char dest_filename[MAX_PATH];
6773 strcpy(src_filename, exe_dir);
6774 strcat(src_filename, NOX("\\update\\freespace.exe"));
6776 strcpy(dest_filename, exe_dir);
6777 strcat(dest_filename, NOX("\\freespace.exe"));
6779 // see if src_filename exists
6781 fp = fopen(src_filename, "rb");
6787 SetFileAttributes(dest_filename, FILE_ATTRIBUTE_NORMAL);
6789 // copy updated freespace.exe to freespace exe dir
6790 if ( CopyFile(src_filename, dest_filename, 0) == 0 ) {
6791 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 );
6795 // delete the file in the update directory
6796 DeleteFile(src_filename);
6798 // safe to assume directory is empty, since freespace.exe should only be the file ever in the update dir
6799 char update_dir[MAX_PATH];
6800 strcpy(update_dir, exe_dir);
6801 strcat(update_dir, NOX("\\update"));
6802 RemoveDirectory(update_dir);
6808 void game_spew_pof_info_sub(int model_num, polymodel *pm, int sm, CFILE *out, int *out_total, int *out_destroyed_total)
6812 int sub_total_destroyed = 0;
6816 // get the total for all his children
6817 for (i=pm->submodel[sm].first_child; i>-1; i = pm->submodel[i].next_sibling ) {
6818 game_spew_pof_info_sub(model_num, pm, i, out, &sub_total, &sub_total_destroyed);
6821 // find the # of faces for this _individual_ object
6822 total = submodel_get_num_polys(model_num, sm);
6823 if(strstr(pm->submodel[sm].name, "-destroyed")){
6824 sub_total_destroyed = total;
6828 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[sm].name, total);
6831 *out_total += total + sub_total;
6832 *out_destroyed_total += sub_total_destroyed;
6835 #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);
6836 void game_spew_pof_info()
6838 char *pof_list[1000];
6841 int idx, model_num, i, j;
6843 int total, root_total, model_total, destroyed_total, counted;
6847 num_files = cf_get_file_list(1000, pof_list, CF_TYPE_MODELS, "*.pof");
6849 // spew info on all the pofs
6855 out = cfopen("pofspew.txt", "wt", CFILE_NORMAL, CF_TYPE_DATA);
6860 for(idx=0; idx<num_files; idx++, counted++){
6861 sprintf(str, "%s.pof", pof_list[idx]);
6862 model_num = model_load(str, 0, NULL);
6864 pm = model_get(model_num);
6866 // if we have a real model
6871 // go through and print all raw submodels
6872 cfputs("RAW\n", out);
6875 for (i=0; i<pm->n_models; i++) {
6876 total = submodel_get_num_polys(model_num, i);
6878 model_total += total;
6879 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[i].name, total);
6882 sprintf(str, "Model total %d\n", model_total);
6885 // now go through and do it by LOD
6886 cfputs("BY LOD\n\n", out);
6887 for(i=0; i<pm->n_detail_levels; i++){
6888 sprintf(str, "LOD %d\n", i);
6892 root_total = submodel_get_num_polys(model_num, pm->detail[i] );
6894 destroyed_total = 0;
6895 for (j=pm->submodel[pm->detail[i]].first_child; j>-1; j = pm->submodel[j].next_sibling ) {
6896 game_spew_pof_info_sub(model_num, pm, j, out, &total, &destroyed_total);
6899 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[pm->detail[i]].name, root_total);
6902 sprintf(str, "TOTAL: %d\n", total + root_total);
6904 sprintf(str, "TOTAL not counting destroyed faces %d\n", (total + root_total) - destroyed_total);
6906 sprintf(str, "TOTAL destroyed faces %d\n\n", destroyed_total);
6909 cfputs("------------------------------------------------------------------------\n\n", out);
6913 if(counted >= MAX_POLYGON_MODELS - 5){
6926 game_spew_pof_info();
6929 int game_main(const char *szCmdLine)
6933 // Find out how much RAM is on this machine
6934 Freespace_total_ram = SDL_GetSystemRAM();
6936 if ( game_do_ram_check(Freespace_total_ram) == -1 ) {
6940 if (!vm_init(24*1024*1024)) {
6941 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);
6945 char *tmp_mem = (char *) malloc(16 * 1024 * 1024);
6947 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);
6954 /* this code doesn't work, and we will hit an error about being unable to load the direct draw
6955 dll before we get here anyway if it's not installed (unless we load it manually, which doesn't
6956 seem worth bothering with.
6960 lResult = RegOpenKeyEx(
6961 HKEY_LOCAL_MACHINE, // Where it is
6962 "Software\\Microsoft\\DirectX", // name of key
6963 NULL, // DWORD reserved
6964 KEY_QUERY_VALUE, // Allows all changes
6965 &hKey // Location to store key
6968 if (lResult == ERROR_SUCCESS) {
6970 DWORD dwType, dwLen;
6973 lResult = RegQueryValueEx(
6974 hKey, // Handle to key
6975 "Version", // The values name
6976 NULL, // DWORD reserved
6977 &dwType, // What kind it is
6978 (ubyte *) version, // value to set
6979 &dwLen // How many bytes to set
6982 if (lResult == ERROR_SUCCESS) {
6983 dx_version = atoi(strstr(version, ".") + 1);
6987 DWORD dwType, dwLen;
6990 lResult = RegQueryValueEx(
6991 hKey, // Handle to key
6992 "InstalledVersion", // The values name
6993 NULL, // DWORD reserved
6994 &dwType, // What kind it is
6995 (ubyte *) &val, // value to set
6996 &dwLen // How many bytes to set
6999 if (lResult == ERROR_SUCCESS) {
7007 if (dx_version < 3) {
7008 MessageBox(NULL, "DirectX 3.0 or higher is required and wasn't detected. You can get the\n"
7009 "latest version of DirectX at:\n\n"
7010 "http://www.microsoft.com/msdownload/directx/dxf/enduser5.0/default.htm", "DirectX required", MB_OK);
7012 MessageBox(NULL, "DirectX 3.0 or higher is required and wasn't detected. You can install\n"
7013 "DirectX 5.2 by pressing the 'Install DirectX' button on the FreeSpace Launcher", "DirectX required", MB_OK);
7021 extern void windebug_memwatch_init();
7022 windebug_memwatch_init();
7030 mprintf(("Total RAM: %dMB\n", Freespace_total_ram));
7031 mprintf(("Platform: %s\n", SDL_GetPlatform()));
7033 parse_cmdline(szCmdLine);
7035 #ifdef STANDALONE_ONLY_BUILD
7037 nprintf(("Network", "Standalone running"));
7040 nprintf(("Network", "Standalone running"));
7047 // maybe spew pof stuff
7048 if(Cmdline_spew_pof_info){
7049 game_spew_pof_info();
7054 // non-demo, non-standalone, play the intro movie
7056 if ( !Is_standalone ) {
7058 // release -- movies always play
7061 // 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
7062 movie_play( NOX("intro.mve") );
7064 // debug version, movie will only play with -showmovies
7065 #elif !defined(NDEBUG)
7067 movie_play( NOX("intro.mve") );
7070 if ( Cmdline_show_movies )
7071 movie_play( NOX("intro.mve") );
7080 gameseq_post_event(GS_EVENT_STANDALONE_MAIN);
7082 gameseq_post_event(GS_EVENT_GAME_INIT); // start the game rolling -- check for default pilot, or go to the pilot select screen
7086 // only important for non THREADED mode
7089 state = gameseq_process_events();
7090 if ( state == GS_STATE_QUIT_GAME ){
7095 #if defined(FS2_DEMO) || defined(FS1_DEMO)
7097 demo_upsell_show_screens();
7099 #elif defined(OEM_BUILD)
7100 // show upsell screens on exit
7101 oem_upsell_show_screens();
7108 // launcher the fslauncher program on exit
7109 void game_launch_launcher_on_exit()
7113 PROCESS_INFORMATION pi;
7114 char cmd_line[2048];
7115 char original_path[1024] = "";
7117 memset( &si, 0, sizeof(STARTUPINFO) );
7121 _getcwd(original_path, 1023);
7123 // set up command line
7124 strcpy(cmd_line, original_path);
7125 strcat(cmd_line, "\\");
7126 strcat(cmd_line, LAUNCHER_FNAME);
7127 strcat(cmd_line, " -straight_to_update");
7129 BOOL ret = CreateProcess( NULL, // pointer to name of executable module
7130 cmd_line, // pointer to command line string
7131 NULL, // pointer to process security attributes
7132 NULL, // pointer to thread security attributes
7133 FALSE, // handle inheritance flag
7134 CREATE_DEFAULT_ERROR_MODE, // creation flags
7135 NULL, // pointer to new environment block
7136 NULL, // pointer to current directory name
7137 &si, // pointer to STARTUPINFO
7138 &pi // pointer to PROCESS_INFORMATION
7140 // to eliminate build warnings
7150 // This function is called when FreeSpace terminates normally.
7152 void game_shutdown(void)
7158 // don't ever flip a page on the standalone!
7159 if(!(Game_mode & GM_STANDALONE_SERVER)){
7165 // if the player has left the "player select" screen and quit the game without actually choosing
7166 // a player, Player will be NULL, in which case we shouldn't write the player file out!
7167 if (!(Game_mode & GM_STANDALONE_SERVER) && (Player!=NULL) && !Is_standalone){
7171 // load up common multiplayer icons
7172 multi_unload_common_icons();
7174 shockwave_close(); // release any memory used by shockwave system
7175 fireball_close(); // free fireball system
7176 ship_close(); // free any memory that was allocated for the ships
7177 weapon_close(); // free any memory that was allocated for the weapons
7178 hud_free_scrollback_list();// free space allocated to store hud messages in hud scrollback
7179 unload_animating_pointer();// frees the frames used for the animating mouse pointer
7180 bm_unload_all(); // free bitmaps
7181 mission_campaign_close(); // close out the campaign stuff
7182 mission_campaign_shutdown(); // get anything that mission_campaign_close can't do
7183 multi_voice_close(); // close down multiplayer voice (including freeing buffers, etc)
7185 #ifdef MULTI_USE_LAG
7189 // the menu close functions will unload the bitmaps if they were displayed during the game
7190 #if !defined(PRESS_TOUR_BUILD) && !defined(PD_BUILD)
7193 context_help_close(); // close out help system
7194 training_menu_close();
7195 lcl_close(); // be sure localization is closed out
7198 // free left-over memory from parsed tables
7199 cutscene_tbl_close();
7201 scoring_tbl_close();
7202 player_tips_close();
7204 extern void joy_close();
7207 audiostream_close();
7209 event_music_close();
7213 // HACKITY HACK HACK
7214 // if this flag is set, we should be firing up the launcher when exiting freespace
7215 extern int Multi_update_fireup_launcher_on_exit;
7216 if(Multi_update_fireup_launcher_on_exit){
7217 game_launch_launcher_on_exit();
7221 // game_stop_looped_sounds()
7223 // This function will call the appropriate stop looped sound functions for those
7224 // modules which use looping sounds. It is not enough just to stop a looping sound
7225 // at the DirectSound level, the game is keeping track of looping sounds, and this
7226 // function is used to inform the game that looping sounds are being halted.
7228 void game_stop_looped_sounds()
7230 hud_stop_looped_locking_sounds();
7231 hud_stop_looped_engine_sounds();
7232 afterburner_stop_sounds();
7233 player_stop_looped_sounds();
7234 obj_snd_stop_all(); // stop all object-linked persistant sounds
7235 game_stop_subspace_ambient_sound();
7236 snd_stop(Radar_static_looping);
7237 Radar_static_looping = -1;
7238 snd_stop(Target_static_looping);
7239 shipfx_stop_engine_wash_sound();
7240 Target_static_looping = -1;
7243 //////////////////////////////////////////////////////////////////////////
7245 // Code for supporting an animating mouse pointer
7248 //////////////////////////////////////////////////////////////////////////
7250 typedef struct animating_obj
7259 static animating_obj Animating_mouse;
7261 // ----------------------------------------------------------------------------
7262 // init_animating_pointer()
7264 // Called by load_animating_pointer() to ensure the Animating_mouse struct
7265 // gets properly initialized
7267 void init_animating_pointer()
7269 Animating_mouse.first_frame = -1;
7270 Animating_mouse.num_frames = 0;
7271 Animating_mouse.current_frame = -1;
7272 Animating_mouse.time = 0.0f;
7273 Animating_mouse.elapsed_time = 0.0f;
7276 // ----------------------------------------------------------------------------
7277 // load_animating_pointer()
7279 // Called at game init to load in the frames for the animating mouse pointer
7281 // input: filename => filename of animation file that holds the animation
7283 void load_animating_pointer(const char *filename, int dx, int dy)
7288 init_animating_pointer();
7290 am = &Animating_mouse;
7291 am->first_frame = bm_load_animation(filename, &am->num_frames, &fps);
7292 if ( am->first_frame == -1 )
7293 Error(LOCATION, "Could not load animation %s for the mouse pointer\n", filename);
7294 am->current_frame = 0;
7295 am->time = am->num_frames / i2fl(fps);
7298 // ----------------------------------------------------------------------------
7299 // unload_animating_pointer()
7301 // Called at game shutdown to free the memory used to store the animation frames
7303 void unload_animating_pointer()
7308 am = &Animating_mouse;
7309 for ( i = 0; i < am->num_frames; i++ ) {
7310 SDL_assert( (am->first_frame+i) >= 0 );
7311 bm_release(am->first_frame + i);
7314 am->first_frame = -1;
7316 am->current_frame = -1;
7319 // draw the correct frame of the game mouse... called from game_maybe_draw_mouse()
7320 void game_render_mouse(float frametime)
7325 // if animating cursor exists, play the next frame
7326 am = &Animating_mouse;
7327 if ( am->first_frame != -1 ) {
7328 mouse_get_pos(&mx, &my);
7329 am->elapsed_time += frametime;
7330 am->current_frame = fl2i( ( am->elapsed_time / am->time ) * (am->num_frames-1) );
7331 if ( am->current_frame >= am->num_frames ) {
7332 am->current_frame = 0;
7333 am->elapsed_time = 0.0f;
7335 gr_set_cursor_bitmap(am->first_frame + am->current_frame);
7339 // ----------------------------------------------------------------------------
7340 // game_maybe_draw_mouse()
7342 // determines whether to draw the mouse pointer at all, and what frame of
7343 // animation to use if the mouse is animating
7345 // Sets mouse.cpp globals Mouse_hidden and Mouse_moved based on the state of the game.
7347 // input: frametime => elapsed frame time in seconds since last call
7349 void game_maybe_draw_mouse(float frametime)
7353 game_state = gameseq_get_state();
7355 switch ( game_state ) {
7356 case GS_STATE_GAME_PAUSED:
7357 // case GS_STATE_MULTI_PAUSED:
7358 case GS_STATE_GAME_PLAY:
7359 case GS_STATE_DEATH_DIED:
7360 case GS_STATE_DEATH_BLEW_UP:
7361 if ( popup_active() || popupdead_is_active() ) {
7373 if ( !Mouse_hidden )
7374 game_render_mouse(frametime);
7378 void game_do_training_checks()
7382 waypoint_list *wplp;
7384 if (Training_context & TRAINING_CONTEXT_SPEED) {
7385 s = (int) Player_obj->phys_info.fspeed;
7386 if ((s >= Training_context_speed_min) && (s <= Training_context_speed_max)) {
7387 if (!Training_context_speed_set) {
7388 Training_context_speed_set = 1;
7389 Training_context_speed_timestamp = timestamp();
7393 Training_context_speed_set = 0;
7396 if (Training_context & TRAINING_CONTEXT_FLY_PATH) {
7397 wplp = &Waypoint_lists[Training_context_path];
7398 if (wplp->count > Training_context_goal_waypoint) {
7399 i = Training_context_goal_waypoint;
7401 d = vm_vec_dist(&wplp->waypoints[i], &Player_obj->pos);
7402 if (d <= Training_context_distance) {
7403 Training_context_at_waypoint = i;
7404 if (Training_context_goal_waypoint == i) {
7405 Training_context_goal_waypoint++;
7406 snd_play(&Snds[SND_CARGO_REVEAL], 0.0f);
7413 if (i == wplp->count)
7416 } while (i != Training_context_goal_waypoint);
7420 if ((Players_target == UNINITIALIZED) || (Player_ai->target_objnum != Players_target) || (Player_ai->targeted_subsys != Players_targeted_subsys)) {
7421 Players_target = Player_ai->target_objnum;
7422 Players_targeted_subsys = Player_ai->targeted_subsys;
7423 Players_target_timestamp = timestamp();
7427 /////////// Following is for event debug view screen
7431 #define EVENT_DEBUG_MAX 5000
7432 #define EVENT_DEBUG_EVENT 0x8000
7434 int Event_debug_index[EVENT_DEBUG_MAX];
7437 void game_add_event_debug_index(int n, int indent)
7439 if (ED_count < EVENT_DEBUG_MAX)
7440 Event_debug_index[ED_count++] = n | (indent << 16);
7443 void game_add_event_debug_sexp(int n, int indent)
7448 if (Sexp_nodes[n].first >= 0) {
7449 game_add_event_debug_sexp(Sexp_nodes[n].first, indent);
7450 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent);
7454 game_add_event_debug_index(n, indent);
7455 if (Sexp_nodes[n].subtype == SEXP_ATOM_OPERATOR)
7456 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent + 1);
7458 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent);
7461 void game_event_debug_init()
7466 for (e=0; e<Num_mission_events; e++) {
7467 game_add_event_debug_index(e | EVENT_DEBUG_EVENT, 0);
7468 game_add_event_debug_sexp(Mission_events[e].formula, 1);
7472 void game_show_event_debug(float frametime)
7476 int font_height, font_width;
7478 static int scroll_offset = 0;
7480 k = game_check_key();
7486 if (scroll_offset < 0)
7496 scroll_offset -= 20;
7497 if (scroll_offset < 0)
7502 scroll_offset += 20; // not font-independent, hard-coded since I counted the lines!
7506 gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
7512 gr_set_color_fast(&Color_bright);
7514 gr_printf(0x8000, 5, NOX("EVENT DEBUG VIEW"));
7516 gr_set_color_fast(&Color_normal);
7518 gr_get_string_size(&font_width, &font_height, NOX("test"));
7519 y_max = gr_screen.max_h - font_height - 5;
7523 while (k < ED_count) {
7524 if (y_index > y_max)
7527 z = Event_debug_index[k];
7528 if (z & EVENT_DEBUG_EVENT) {
7530 sprintf(buf, NOX("%s%s (%s) %s%d %d"), (Mission_events[z].flags & MEF_CURRENT) ? NOX("* ") : "",
7531 Mission_events[z].name, Mission_events[z].result ? NOX("True") : NOX("False"),
7532 (Mission_events[z].chain_delay < 0) ? "" : NOX("x "),
7533 Mission_events[z].repeat_count, Mission_events[z].interval);
7541 strcat(buf, Sexp_nodes[z & 0x7fff].text);
7542 switch (Sexp_nodes[z & 0x7fff].value) {
7544 strcat(buf, NOX(" (True)"));
7548 strcat(buf, NOX(" (False)"));
7551 case SEXP_KNOWN_TRUE:
7552 strcat(buf, NOX(" (Always true)"));
7555 case SEXP_KNOWN_FALSE:
7556 strcat(buf, NOX(" (Always false)"));
7559 case SEXP_CANT_EVAL:
7560 strcat(buf, NOX(" (Can't eval)"));
7564 case SEXP_NAN_FOREVER:
7565 strcat(buf, NOX(" (Not a number)"));
7570 gr_printf(10, y_index, buf);
7571 y_index += font_height;
7585 extern int Tmap_npixels;
7588 int Tmap_num_too_big = 0;
7589 int Num_models_needing_splitting = 0;
7591 void Time_model( int modelnum )
7593 // mprintf(( "Timing ship '%s'\n", si->name ));
7595 vector eye_pos, model_pos;
7596 matrix eye_orient, model_orient;
7598 polymodel *pm = model_get( modelnum );
7600 int l = strlen(pm->filename);
7602 if ( (l == '/') || (l=='\\') || (l==':')) {
7608 char *pof_file = &pm->filename[l];
7610 int model_needs_splitting = 0;
7612 //fprintf( Texture_fp, "Model: %s\n", pof_file );
7614 for (i=0; i<pm->n_textures; i++ ) {
7615 char filename[1024];
7618 int bmp_num = pm->original_textures[i];
7619 if ( bmp_num > -1 ) {
7620 bm_get_palette(pm->original_textures[i], pal, filename );
7622 bm_get_info( pm->original_textures[i],&w, &h );
7625 if ( (w > 512) || (h > 512) ) {
7626 fprintf( Texture_fp, "%s\t%s\t%d\t%d\n", pof_file, filename, w, h );
7628 model_needs_splitting++;
7631 //fprintf( Texture_fp, "\tTexture %d is bogus\n", i );
7635 if ( model_needs_splitting ) {
7636 Num_models_needing_splitting++;
7638 eye_orient = model_orient = vmd_identity_matrix;
7639 eye_pos = model_pos = vmd_zero_vector;
7641 eye_pos.xyz.z = -pm->rad*2.0f;
7643 vector eye_to_model;
7645 vm_vec_sub( &eye_to_model, &model_pos, &eye_pos );
7646 vm_vector_2_matrix( &eye_orient, &eye_to_model, NULL, NULL );
7648 fix t1 = timer_get_fixed_seconds();
7651 ta.p = ta.b = ta.h = 0.0f;
7658 int bitmaps_used_this_frame, bitmaps_new_this_frame;
7660 bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
7662 modelstats_num_polys = modelstats_num_verts = 0;
7664 while( ta.h < PI2 ) {
7667 vm_angles_2_matrix(&m1, &ta );
7668 vm_matrix_x_matrix( &model_orient, &vmd_identity_matrix, &m1 );
7675 g3_set_view_matrix( &eye_pos, &eye_orient, Viewer_zoom );
7677 model_clear_instance( modelnum );
7678 model_set_detail_level(0); // use highest detail level
7679 model_render( modelnum, &model_orient, &model_pos, MR_LOCK_DETAIL); //|MR_NO_POLYS );
7687 int k = key_inkey();
7688 if ( k == SDLK_ESCAPE ) {
7693 fix t2 = timer_get_fixed_seconds();
7695 bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
7696 //bitmaps_used_this_frame /= framecount;
7698 modelstats_num_polys /= framecount;
7699 modelstats_num_verts /= framecount;
7702 Tmap_npixels /=framecount;
7705 mprintf(( "'%s' is %.2f FPS\n", pof_file, i2fl(framecount)/f2fl(t2-t1) ));
7707 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 );
7709 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 );
7711 // 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 );
7717 int Time_models = 0;
7718 DCF_BOOL( time_models, Time_models );
7720 void Do_model_timings_test()
7724 if ( !Time_models ) return;
7726 mprintf(( "Timing models!\n" ));
7730 ubyte model_used[MAX_POLYGON_MODELS];
7731 int model_id[MAX_POLYGON_MODELS];
7732 for (i=0; i<MAX_POLYGON_MODELS; i++ ) {
7737 for (i=0; i<Num_ship_types; i++ ) {
7738 Ship_info[i].modelnum = model_load( Ship_info[i].pof_file, 0, NULL );
7740 model_used[Ship_info[i].modelnum%MAX_POLYGON_MODELS]++;
7741 model_id[Ship_info[i].modelnum%MAX_POLYGON_MODELS] = Ship_info[i].modelnum;
7744 Texture_fp = fopen( NOX("ShipTextures.txt"), "wt" );
7745 if ( !Texture_fp ) return;
7747 Time_fp = fopen( NOX("ShipTimings.txt"), "wt" );
7748 if ( !Time_fp ) return;
7750 fprintf( Time_fp, "Name\tFPS\tTRAM\tPolys\tVerts\tPixels\n" );
7751 // fprintf( Time_fp, "FPS\tTRAM\tPolys\tVerts\tPixels\n" );
7753 for (i=0; i<MAX_POLYGON_MODELS; i++ ) {
7754 if ( model_used[i] ) {
7755 Time_model( model_id[i] );
7759 fprintf( Texture_fp, "Number too big: %d\n", Tmap_num_too_big );
7760 fprintf( Texture_fp, "Number of models needing splitting: %d\n", Num_models_needing_splitting );
7769 // Call this function when you want to inform the player that a feature is not
7770 // enabled in the DEMO version of FreSpace
7771 void game_feature_not_in_demo_popup()
7773 popup(PF_USE_AFFIRMATIVE_ICON|PF_BODY_BIG, 1, POPUP_OK, XSTR( "Sorry, this feature is available only in the retail version", 200));
7776 // format the specified time (fixed point) into a nice string
7777 void game_format_time(fix m_time,char *time_str)
7780 int hours,minutes,seconds;
7783 mtime = f2fl(m_time);
7785 // get the hours, minutes and seconds
7786 hours = (int)(mtime / 3600.0f);
7788 mtime -= (3600.0f * (float)hours);
7790 seconds = (int)mtime%60;
7791 minutes = (int)mtime/60;
7793 // print the hour if necessary
7795 sprintf(time_str,XSTR( "%d:", 201),hours);
7796 // if there are less than 10 minutes, print a leading 0
7798 strcpy(tmp,NOX("0"));
7799 strcat(time_str,tmp);
7803 // print the minutes
7805 sprintf(tmp,XSTR( "%d:", 201),minutes);
7806 strcat(time_str,tmp);
7808 sprintf(time_str,XSTR( "%d:", 201),minutes);
7811 // print the seconds
7813 strcpy(tmp,NOX("0"));
7814 strcat(time_str,tmp);
7816 sprintf(tmp,"%d",seconds);
7817 strcat(time_str,tmp);
7820 // Stuff version string in *str.
7821 void get_version_string(char *str)
7824 if ( FS_VERSION_BUILD == 0 ) {
7825 sprintf(str,"v%d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR);
7827 sprintf(str,"v%d.%02d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR, FS_VERSION_BUILD );
7830 #if defined (FS2_DEMO) || defined(FS1_DEMO)
7832 #elif defined (OEM_BUILD)
7833 strcat(str, " (OEM)");
7839 char myname[_MAX_PATH];
7840 int namelen, major, minor, build, waste;
7841 unsigned int buf_size;
7847 // Find my EXE file name
7848 hMod = GetModuleHandle(NULL);
7849 namelen = GetModuleFileName( hMod, myname, _MAX_PATH );
7851 version_size = GetFileVersionInfoSize(myname, &bogus_handle );
7852 infop = (char *)malloc(version_size);
7853 result = GetFileVersionInfo( myname, 0, version_size, (LPVOID)infop );
7855 // get the product version
7856 result = VerQueryValue((LPVOID)infop, TEXT("\\StringFileInfo\\040904b0\\ProductVersion"), &bufp, &buf_size );
7857 sscanf( (char *)bufp, "%d, %d, %d, %d", &major, &minor, &build, &waste );
7859 sprintf(str,"Dv%d.%02d",major, minor);
7861 sprintf(str,"v%d.%02d",major, minor);
7866 void get_version_string_short(char *str)
7868 sprintf(str,"v%d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR);
7871 // ----------------------------------------------------------------
7873 // OEM UPSELL SCREENS BEGIN
7875 // ----------------------------------------------------------------
7876 #if defined(OEM_BUILD)
7878 #define NUM_OEM_UPSELL_SCREENS 3
7879 #define OEM_UPSELL_SCREEN_DELAY 10000
7881 static int Oem_upsell_bitmaps_loaded = 0;
7882 static int Oem_upsell_bitmaps[GR_NUM_RESOLUTIONS][NUM_OEM_UPSELL_SCREENS];
7883 static int Oem_upsell_screen_number = 0;
7884 static int Oem_upsell_show_next_bitmap_time;
7887 static char *Oem_upsell_bitmap_filenames[GR_NUM_RESOLUTIONS][NUM_OEM_UPSELL_SCREENS] =
7900 static int Oem_normal_cursor = -1;
7901 static int Oem_web_cursor = -1;
7902 //#define OEM_UPSELL_URL "http://www.interplay-store.com/"
7903 #define OEM_UPSELL_URL "http://www.interplay.com/cgi-bin/oemlinks.pl/pid=483421&cid=18384"
7905 void oem_upsell_next_screen()
7907 Oem_upsell_screen_number++;
7908 if ( Oem_upsell_screen_number == (NUM_OEM_UPSELL_SCREENS-1) ) {
7909 // extra long delay, mouse shown on last upsell
7910 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY*2;
7914 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY;
7918 void oem_upsell_load_bitmaps()
7922 for ( i = 0; i < NUM_OEM_UPSELL_SCREENS; i++ ) {
7923 Oem_upsell_bitmaps[gr_screen.res][i] = bm_load(Oem_upsell_bitmap_filenames[gr_screen.res][i]);
7927 void oem_upsell_unload_bitmaps()
7931 for ( i = 0; i < NUM_OEM_UPSELL_SCREENS; i++ ) {
7932 if(Oem_upsell_bitmaps[gr_screen.res][i] >= 0){
7933 bm_unload(Oem_upsell_bitmaps[gr_screen.res][i]);
7938 Oem_upsell_bitmaps_loaded = 0;
7941 // clickable hotspot on 3rd OEM upsell screen
7942 static int Oem_upsell3_button_coords[GR_NUM_RESOLUTIONS][4] = {
7944 28, 350, 287, 96 // x, y, w, h
7947 45, 561, 460, 152 // x, y, w, h
7951 void oem_upsell_show_screens()
7953 int current_time, k;
7956 if ( !Oem_upsell_bitmaps_loaded ) {
7957 oem_upsell_load_bitmaps();
7958 Oem_upsell_bitmaps_loaded = 1;
7961 // may use upsell screens more than once
7962 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY;
7963 Oem_upsell_screen_number = 0;
7969 int nframes; // used to pass, not really needed (should be 1)
7970 Oem_normal_cursor = gr_get_cursor_bitmap();
7971 Oem_web_cursor = bm_load_animation("cursorweb", &nframes);
7972 SDL_assert(Oem_web_cursor >= 0);
7973 if (Oem_web_cursor < 0) {
7974 Oem_web_cursor = Oem_normal_cursor;
7979 //oem_reset_trailer_timer();
7981 current_time = timer_get_milliseconds();
7986 // advance screen on keypress or timeout
7987 if (( k > 0 ) || (mouse_up_count(MOUSE_LEFT_BUTTON) > 0) || (current_time > Oem_upsell_show_next_bitmap_time)) {
7988 oem_upsell_next_screen();
7991 // check if we are done
7992 if ( Oem_upsell_screen_number >= NUM_OEM_UPSELL_SCREENS ) {
7993 Oem_upsell_screen_number--;
7996 if ( Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number] < 0 ) {
8001 // show me the upsell
8002 if ( Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number] >= 0 ) {
8003 gr_set_bitmap(Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number]);
8007 // if this is the 3rd upsell, make it clickable, d00d
8008 if ( Oem_upsell_screen_number == NUM_OEM_UPSELL_SCREENS-1 ) {
8010 int button_state = mouse_get_pos(&mx, &my);
8011 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])
8012 && (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]) )
8015 gr_set_cursor_bitmap(Oem_web_cursor); //, GR_CURSOR_LOCK);
8018 if (button_state & MOUSE_LEFT_BUTTON) {
8020 multi_pxo_url(OEM_UPSELL_URL);
8024 // switch cursor back to normal one
8025 gr_set_cursor_bitmap(Oem_normal_cursor); //, GR_CURSOR_UNLOCK);
8030 if (gameseq_get_state() != GS_STATE_END_DEMO) {
8040 oem_upsell_unload_bitmaps();
8042 // switch cursor back to normal one
8043 gr_set_cursor_bitmap(Oem_normal_cursor); //, GR_CURSOR_UNLOCK);
8047 #endif // defined(OEM_BUILD)
8048 // ----------------------------------------------------------------
8050 // OEM UPSELL SCREENS END
8052 // ----------------------------------------------------------------
8056 // ----------------------------------------------------------------
8058 // DEMO UPSELL SCREENS BEGIN
8060 // ----------------------------------------------------------------
8062 #if defined(FS2_DEMO) || defined(FS1_DEMO)
8065 #define NUM_DEMO_UPSELL_SCREENS 2
8067 #define NUM_DEMO_UPSELL_SCREENS 4
8069 #define DEMO_UPSELL_SCREEN_DELAY 3000
8071 static int Demo_upsell_bitmaps_loaded = 0;
8072 static int Demo_upsell_bitmaps[GR_NUM_RESOLUTIONS][NUM_DEMO_UPSELL_SCREENS];
8073 static int Demo_upsell_screen_number = 0;
8074 static int Demo_upsell_show_next_bitmap_time;
8077 static char *Demo_upsell_bitmap_filenames[GR_NUM_RESOLUTIONS][NUM_DEMO_UPSELL_SCREENS] =
8103 void demo_upsell_next_screen()
8105 Demo_upsell_screen_number++;
8106 if ( Demo_upsell_screen_number == (NUM_DEMO_UPSELL_SCREENS-1) ) {
8107 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY*4;
8109 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY;
8113 if ( Demo_upsell_screen_number < NUM_DEMO_UPSELL_SCREENS ) {
8114 if ( Demo_upsell_bitmap_filenames[gr_screen.res][Demo_upsell_screen_number] >= 0 ) {
8115 #ifndef HARDWARE_ONLY
8116 palette_use_bm_palette(Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number]);
8123 void demo_upsell_load_bitmaps()
8127 for ( i = 0; i < NUM_DEMO_UPSELL_SCREENS; i++ ) {
8128 Demo_upsell_bitmaps[gr_screen.res][i] = bm_load(Demo_upsell_bitmap_filenames[gr_screen.res][i]);
8132 void demo_upsell_unload_bitmaps()
8136 for ( i = 0; i < NUM_DEMO_UPSELL_SCREENS; i++ ) {
8137 if(Demo_upsell_bitmaps[gr_screen.res][i] >= 0){
8138 bm_unload(Demo_upsell_bitmaps[gr_screen.res][i]);
8143 Demo_upsell_bitmaps_loaded = 0;
8146 void demo_upsell_show_screens()
8148 int current_time, k;
8151 if ( !Demo_upsell_bitmaps_loaded ) {
8152 demo_upsell_load_bitmaps();
8153 Demo_upsell_bitmaps_loaded = 1;
8156 // may use upsell screens more than once
8157 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY;
8158 Demo_upsell_screen_number = 0;
8165 demo_reset_trailer_timer();
8167 current_time = timer_get_milliseconds();
8174 // don't time out, wait for keypress
8176 if ( current_time > Demo_upsell_show_next_bitmap_time ) {
8177 demo_upsell_next_screen();
8182 demo_upsell_next_screen();
8185 if ( Demo_upsell_screen_number >= NUM_DEMO_UPSELL_SCREENS ) {
8186 Demo_upsell_screen_number--;
8189 if ( Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number] < 0 ) {
8194 if ( Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number] >= 0 ) {
8195 gr_set_bitmap(Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number]);
8200 if (gameseq_get_state() != GS_STATE_END_DEMO) {
8210 demo_upsell_unload_bitmaps();
8215 // ----------------------------------------------------------------
8217 // DEMO UPSELL SCREENS END
8219 // ----------------------------------------------------------------
8222 // ----------------------------------------------------------------
8224 // Subspace Ambient Sound START
8226 // ----------------------------------------------------------------
8228 static int Subspace_ambient_left_channel = -1;
8229 static int Subspace_ambient_right_channel = -1;
8232 void game_start_subspace_ambient_sound()
8234 if ( Subspace_ambient_left_channel < 0 ) {
8235 Subspace_ambient_left_channel = snd_play_looping(&Snds[SND_SUBSPACE_LEFT_CHANNEL], -1.0f);
8238 if ( Subspace_ambient_right_channel < 0 ) {
8239 Subspace_ambient_right_channel = snd_play_looping(&Snds[SND_SUBSPACE_RIGHT_CHANNEL], 1.0f);
8243 void game_stop_subspace_ambient_sound()
8245 if ( Subspace_ambient_left_channel >= 0 ) {
8246 snd_stop(Subspace_ambient_left_channel);
8247 Subspace_ambient_left_channel = -1;
8250 if ( Subspace_ambient_right_channel >= 0 ) {
8251 snd_stop(Subspace_ambient_right_channel);
8252 Subspace_ambient_right_channel = -1;
8256 // ----------------------------------------------------------------
8258 // Subspace Ambient Sound END
8260 // ----------------------------------------------------------------
8262 // ----------------------------------------------------------------
8264 // Language Autodetection stuff
8267 // this layout order must match Lcl_languages in localize.cpp in order for the
8268 // correct language to be detected
8269 int Lang_auto_detect_checksums[LCL_NUM_LANGUAGES] = {
8271 1366105450, // English
8273 589986744, // English
8275 -1132430286, // German
8277 -1131728960, // Polish
8280 // default setting is "-1" to use config file with English as fall back
8281 // DO NOT change the default setting here or something uncouth might happen
8282 // in the localization code
8288 // try and open the file to verify
8289 CFILE *detect = cfopen("font01.vf", "rb");
8291 // will use default setting if something went wrong
8296 // get the long checksum of the file
8298 cfseek(detect, 0, SEEK_SET);
8299 cf_chksum_long(detect, &file_checksum);
8303 // now compare the checksum/filesize against known #'s
8304 for (idx=0; idx<LCL_NUM_LANGUAGES; idx++) {
8305 if (Lang_auto_detect_checksums[idx] == (int)file_checksum) {
8310 // notify if a match was not found, include detected checksum
8311 printf("ERROR: Unknown Language Checksum: %i\n", (int)file_checksum);
8312 printf("Using default language...\n\n");
8318 // End Auto Lang stuff
8320 // ----------------------------------------------------------------
8322 // ----------------------------------------------------------------
8323 // SHIPS TBL VERIFICATION STUFF
8326 // checksums, just keep a list of all valid ones, if it matches any of them, keep it
8327 #if defined(MAKE_FS1) && !defined(FS1_DEMO)
8328 #define NUM_SHIPS_TBL_CHECKSUMS 3
8330 #define NUM_SHIPS_TBL_CHECKSUMS 1
8334 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8335 1696074201, // FS2 demo
8338 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8339 1603375034, // FS1 DEMO
8342 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8343 -129679197, // FS1 Full 1.06 (US)
8344 7762567, // FS1 SilentThreat
8345 1555372475 // FS1 Full 1.06 (German)
8349 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8350 -463907578, // US - beta 1
8351 1696074201, // FS2 demo
8354 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8355 // -1022810006, // 1.0 FULL
8356 -1254285366 // 1.2 FULL (German)
8360 void verify_ships_tbl()
8364 Game_ships_tbl_valid = 1;
8370 // detect if the packfile exists
8371 CFILE *detect = cfopen("ships.tbl", "rb");
8372 Game_ships_tbl_valid = 0;
8376 Game_ships_tbl_valid = 0;
8380 // get the long checksum of the file
8382 cfseek(detect, 0, SEEK_SET);
8383 cf_chksum_long(detect, &file_checksum);
8387 // now compare the checksum/filesize against known #'s
8388 for(idx=0; idx<NUM_SHIPS_TBL_CHECKSUMS; idx++){
8389 if(Game_ships_tbl_checksums[idx] == (int)file_checksum){
8390 Game_ships_tbl_valid = 1;
8397 DCF(shipspew, "display the checksum for the current ships.tbl")
8400 CFILE *detect = cfopen("ships.tbl", "rb");
8401 // get the long checksum of the file
8403 cfseek(detect, 0, SEEK_SET);
8404 cf_chksum_long(detect, &file_checksum);
8407 dc_printf("%d", file_checksum);
8410 // ----------------------------------------------------------------
8411 // WEAPONS TBL VERIFICATION STUFF
8414 // checksums, just keep a list of all valid ones, if it matches any of them, keep it
8415 #if defined(MAKE_FS1) && !defined(FS1_DEMO)
8416 #define NUM_WEAPONS_TBL_CHECKSUMS 3
8418 #define NUM_WEAPONS_TBL_CHECKSUMS 1
8422 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
8423 -266420030, // demo 1
8426 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
8427 -1246928725, // FS1 DEMO
8430 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
8431 -834598107, // FS1 1.06 Full (US)
8432 -1652231417, // FS1 SilentThreat
8433 720209793 // FS1 1.06 Full (German)
8437 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
8438 141718090, // US - beta 1
8439 -266420030, // demo 1
8442 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
8443 // 399297860, // 1.0 FULL
8444 -553984927 // 1.2 FULL (german)
8448 void verify_weapons_tbl()
8452 Game_weapons_tbl_valid = 1;
8458 // detect if the packfile exists
8459 CFILE *detect = cfopen("weapons.tbl", "rb");
8460 Game_weapons_tbl_valid = 0;
8464 Game_weapons_tbl_valid = 0;
8468 // get the long checksum of the file
8470 cfseek(detect, 0, SEEK_SET);
8471 cf_chksum_long(detect, &file_checksum);
8475 // now compare the checksum/filesize against known #'s
8476 for(idx=0; idx<NUM_WEAPONS_TBL_CHECKSUMS; idx++){
8477 if(Game_weapons_tbl_checksums[idx] == (int)file_checksum){
8478 Game_weapons_tbl_valid = 1;
8485 DCF(wepspew, "display the checksum for the current weapons.tbl")
8488 CFILE *detect = cfopen("weapons.tbl", "rb");
8489 // get the long checksum of the file
8491 cfseek(detect, 0, SEEK_SET);
8492 cf_chksum_long(detect, &file_checksum);
8495 dc_printf("%d", file_checksum);
8498 // if the game is running using hacked data
8499 int game_hacked_data()
8502 if(!Game_weapons_tbl_valid || !Game_ships_tbl_valid){
8510 void display_title_screen()
8512 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
8513 ///int title_bitmap;
8516 int title_bitmap = bm_load(Game_demo_title_screen_fname[gr_screen.res]);
8517 if (title_bitmap == -1) {
8523 if((gr_screen.mode == GR_DIRECT3D) && (Gr_bitmap_poly)){
8524 extern void d3d_start_frame();
8530 gr_set_bitmap(title_bitmap);
8537 if((gr_screen.mode == GR_DIRECT3D) && (Gr_bitmap_poly)){
8538 extern void d3d_stop_frame();
8546 bm_unload(title_bitmap);
8547 #endif // FS2_DEMO || OEM_BUILD || FS1_DEMO
8550 // return true if the game is running with "low memory", which is less than 48MB
8551 bool game_using_low_mem()
8553 if (Use_low_mem == 0) {