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 );
2298 Game_current_mission_filename[0] = 0;
2300 // seed the random number generator
2301 Game_init_seed = time(NULL);
2302 srand( Game_init_seed );
2304 Framerate_delay = 0;
2310 extern void bm_init();
2316 // Initialize the timer before the os
2322 //Initialize the libraries
2323 s1 = timer_get_milliseconds();
2324 if ( cfile_init() ) { // initialize before calling any cfopen stuff!!!
2327 e1 = timer_get_milliseconds();
2329 // time a bunch of cfopens
2331 s2 = timer_get_milliseconds();
2333 for(int idx=0; idx<10000; idx++){
2334 whee = cfopen("capital01.pof", "rb", CFILE_NORMAL, CF_TYPE_MODELS);
2339 //cf_exist("capital01.pof", CF_TYPE_MODELS);
2341 e2 = timer_get_milliseconds();
2344 if (Is_standalone) {
2345 std_init_standalone();
2347 os_init( Osreg_class_name, Osreg_app_name );
2348 os_set_title(Osreg_title);
2351 // initialize localization module. Make sure this is down AFTER initialzing OS.
2352 // int t1 = timer_get_milliseconds();
2353 lcl_init( detect_lang() );
2355 // mprintf(("LCL_INIT() TOOK %d MS\n", timer_get_milliseconds()-t1));
2357 // verify that he has a valid ships.tbl (will Game_ships_tbl_valid if so)
2360 // verify that he has a valid weapons.tbl
2361 verify_weapons_tbl();
2363 // Output version numbers to registry for auto patching purposes
2364 os_config_write_uint(NOX("Version"), NOX("Major"), FS_VERSION_MAJOR);
2365 os_config_write_uint(NOX("Version"), NOX("Minor"), FS_VERSION_MINOR);
2366 os_config_write_uint(NOX("Version"), NOX("Build"), FS_VERSION_BUILD);
2368 Use_joy_mouse = 0; //os_config_read_uint( NULL, NOX("JoystickMovesCursor"), 1 );
2369 //Use_palette_flash = os_config_read_uint( NULL, NOX("PaletteFlash"), 0 );
2370 Use_low_mem = os_config_read_uint( NULL, NOX("LowMem"), 0 );
2373 Use_fullscreen_at_startup = os_config_read_uint( NULL, NOX("ForceFullscreen"), 1 );
2376 #if defined (PLAT_UNIX) && defined(RELEASE_REAL)
2377 // show the FPS counter if the config file says so
2378 Show_framerate = os_config_read_uint( NULL, NOX("ShowFPS"), 0 );
2381 #if !(defined(FS2_DEMO) || defined(FS1_DEMO))
2382 Asteroids_enabled = 1;
2385 /////////////////////////////
2387 /////////////////////////////
2391 ptr = os_config_read_string(NULL, NOX("Soundcard"), NULL);
2392 mprintf(("soundcard = %s\n", ptr ? ptr : "<nothing>"));
2394 if (!SDL_strcasecmp(ptr, NOX("no sound"))) {
2395 Cmdline_freespace_no_sound = 1;
2396 } else if ( !SDL_strcasecmp(ptr, NOX("EAX")) || !SDL_strcasecmp(ptr, NOX("Aureal A3D")) ) {
2401 if (!Is_standalone) {
2404 /////////////////////////////
2406 /////////////////////////////
2408 ptr = os_config_read_string(NULL, NOX("Videocard"), NULL);
2411 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);
2413 // fire up the UpdateLauncher executable
2415 PROCESS_INFORMATION pi;
2417 memset( &si, 0, sizeof(STARTUPINFO) );
2420 BOOL ret = CreateProcess( LAUNCHER_FNAME, // pointer to name of executable module
2421 NULL, // pointer to command line string
2422 NULL, // pointer to process security attributes
2423 NULL, // pointer to thread security attributes
2424 FALSE, // handle inheritance flag
2425 CREATE_DEFAULT_ERROR_MODE, // creation flags
2426 NULL, // pointer to new environment block
2427 NULL, // pointer to current directory name
2428 &si, // pointer to STARTUPINFO
2429 &pi // pointer to PROCESS_INFORMATION
2432 // If the Launcher could not be started up, let the user know
2434 MessageBox((HWND)os_get_window(), XSTR("The Launcher could not be restarted.", 1450), XSTR("Error", 1451), MB_OK);
2443 if(!SDL_strcasecmp(ptr, "Aucune acc�l�ration 3D") || !SDL_strcasecmp(ptr, "Keine 3D-Beschleunigerkarte") || !SDL_strcasecmp(ptr, "No 3D acceleration")){
2445 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);
2453 // check for hi res pack file
2454 int has_sparky_hi = 0;
2456 // check if sparky_hi exists -- access mode 0 means does file exist
2457 #ifndef MAKE_FS1 // shoudn't have it so don't check
2460 if ( _access("sparky_hi_fs2.vp", 0) == 0) {
2463 mprintf(("No sparky_hi_fs2.vp in directory %s\n", dir));
2468 if (!Is_standalone && ptr && (strstr(ptr, NOX("3DFX Glide")))) {
2470 // always 640 for E3
2471 gr_init(GR_640, GR_GLIDE);
2473 // regular or hi-res ?
2475 if(has_sparky_hi && strstr(ptr, NOX("(1024x768)"))){
2477 if(strstr(ptr, NOX("(1024x768)"))){
2479 gr_init(GR_1024, GR_GLIDE);
2481 gr_init(GR_640, GR_GLIDE);
2484 } else if (!Is_standalone && ptr && (strstr(ptr, NOX("Direct 3D -") ))) {
2486 // always 640 for E3
2488 gr_init(GR_640, GR_DIRECT3D, depth);
2490 // regular or hi-res ?
2492 if(has_sparky_hi && strstr(ptr, NOX("(1024x768)"))){
2494 if(strstr(ptr, NOX("(1024x768)"))){
2498 gr_init(GR_1024, GR_DIRECT3D, depth);
2502 gr_init(GR_640, GR_DIRECT3D, depth);
2508 if ( Use_fullscreen_at_startup && !Is_standalone) {
2509 gr_init(GR_640, GR_DIRECTDRAW);
2511 gr_init(GR_640, GR_SOFTWARE);
2514 if ( !Is_standalone ) {
2515 gr_init(GR_640, GR_DIRECTDRAW);
2517 gr_init(GR_640, GR_SOFTWARE);
2522 if (!Is_standalone /* && ptr && (strstr(ptr, NOX("OpenGL"))) */) {
2523 if(has_sparky_hi && strstr(ptr, NOX("(1024x768)"))){
2524 gr_init(GR_1024, GR_OPENGL);
2526 gr_init(GR_640, GR_OPENGL);
2530 gr_init(GR_640, GR_SDL);
2532 #endif // !PLAT_UNIX
2535 ptr = os_config_read_string(NULL,NOX("Gamma"),NOX("1.80"));
2536 Freespace_gamma = (float)atof(ptr);
2537 if ( Freespace_gamma == 0.0f ) {
2538 Freespace_gamma = 1.80f;
2539 } else if ( Freespace_gamma < 0.1f ) {
2540 Freespace_gamma = 0.1f;
2541 } else if ( Freespace_gamma > 5.0f ) {
2542 Freespace_gamma = 5.0f;
2544 char tmp_gamma_string[32];
2545 sprintf( tmp_gamma_string, NOX("%.2f"), Freespace_gamma );
2546 os_config_write_string( NULL, NOX("Gamma"), tmp_gamma_string );
2548 gr_set_gamma(Freespace_gamma);
2550 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
2553 display_title_screen();
2557 // attempt to load up master tracker registry info (login and password)
2558 Multi_tracker_id = -1;
2560 // pxo login and password
2561 ptr = os_config_read_string(NOX("PXO"),NOX("Login"),NULL);
2563 nprintf(("Network","Error reading in PXO login data\n"));
2564 strcpy(Multi_tracker_login,"");
2566 strcpy(Multi_tracker_login,ptr);
2568 ptr = os_config_read_string(NOX("PXO"),NOX("Password"),NULL);
2570 nprintf(("Network","Error reading PXO password\n"));
2571 strcpy(Multi_tracker_passwd,"");
2573 strcpy(Multi_tracker_passwd,ptr);
2576 // pxo squad name and password
2577 ptr = os_config_read_string(NOX("PXO"),NOX("SquadName"),NULL);
2579 nprintf(("Network","Error reading in PXO squad name\n"));
2580 strcpy(Multi_tracker_squad_name, "");
2582 strcpy(Multi_tracker_squad_name, ptr);
2585 // If less than 48MB of RAM, use low memory model.
2586 if ( (Freespace_total_ram < 48) || Use_low_mem ) {
2587 mprintf(( "Using normal memory settings...\n" ));
2588 bm_set_low_mem(1); // Use every other frame of bitmaps
2590 mprintf(( "Using high memory settings...\n" ));
2591 bm_set_low_mem(0); // Use all frames of bitmaps
2594 // load non-darkening pixel defs
2595 palman_load_pixels();
2597 // hud shield icon stuff
2598 hud_shield_game_init();
2600 control_config_common_init(); // sets up localization stuff in the control config
2606 gamesnd_parse_soundstbl();
2611 // standalone's don't use hte joystick and it seems to sometimes cause them to not get shutdown properly
2616 player_controls_init();
2619 //if(!Is_standalone){
2627 ship_init(); // read in ships.tbl
2629 mission_campaign_init(); // load in the default campaign
2631 // navmap_init(); // init the navigation map system
2632 context_help_init();
2633 techroom_intel_init(); // parse species.tbl, load intel info
2635 psnet_init( Multi_options_g.protocol, Multi_options_g.port ); // initialize the networking code
2636 init_animating_pointer();
2638 mission_brief_common_init(); // Mark all the briefing structures as empty.
2639 gr_font_init(); // loads up all fonts
2641 neb2_init(); // fullneb stuff
2645 player_tips_init(); // helpful tips
2648 // load the list of pilot pic filenames (for barracks and pilot select popup quick reference)
2649 pilot_load_pic_list();
2650 pilot_load_squad_pic_list();
2652 load_animating_pointer(NOX("cursor"), 0, 0);
2654 // initialize alpha colors
2655 alpha_colors_init();
2658 // Game_music_paused = 0;
2665 nprintf(("General", "Ships.tbl is : %s\n", Game_ships_tbl_valid ? "VALID" : "INVALID!!!!"));
2666 nprintf(("General", "Weapons.tbl is : %s\n", Game_weapons_tbl_valid ? "VALID" : "INVALID!!!!"));
2668 mprintf(("cfile_init() took %d\n", e1 - s1));
2669 // mprintf(("1000 cfopens() took %d\n", e2 - s2));
2672 char transfer_text[128];
2674 float Start_time = 0.0f;
2676 float Framerate = 0.0f;
2678 float Timing_total = 0.0f;
2679 float Timing_render2 = 0.0f;
2680 float Timing_render3 = 0.0f;
2681 float Timing_flip = 0.0f;
2682 float Timing_clear = 0.0f;
2684 MONITOR(NumPolysDrawn);
2690 void game_get_framerate()
2692 char text[128] = "";
2694 if ( frame_int == -1 ) {
2696 for (i=0; i<FRAME_FILTER; i++ ) {
2697 frametimes[i] = 0.0f;
2702 frametotal -= frametimes[frame_int];
2703 frametotal += flFrametime;
2704 frametimes[frame_int] = flFrametime;
2705 frame_int = (frame_int + 1 ) % FRAME_FILTER;
2707 if ( frametotal != 0.0 ) {
2708 if ( Framecount >= FRAME_FILTER )
2709 Framerate = FRAME_FILTER / frametotal;
2711 Framerate = Framecount / frametotal;
2712 sprintf( text, NOX("FPS: %.1f"), Framerate );
2714 sprintf( text, NOX("FPS: ?") );
2718 if (Show_framerate) {
2719 gr_set_color_fast(&HUD_color_debug);
2720 gr_string( 570, 2, text );
2724 void game_show_framerate()
2728 cur_time = f2fl(timer_get_approx_seconds());
2729 if (cur_time - Start_time > 30.0f) {
2730 mprintf(("%i frames executed in %7.3f seconds, %7.3f frames per second.\n", Framecount, cur_time - Start_time, Framecount/(cur_time - Start_time)));
2731 Start_time += 1000.0f;
2734 //mprintf(( "%s\n", text ));
2737 if ( Debug_dump_frames )
2741 // possibly show control checking info
2742 control_check_indicate();
2744 // int bitmaps_used_this_frame, bitmaps_new_this_frame;
2745 // bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
2746 // MONITOR_INC(BmpUsed, bitmaps_used_this_frame);
2747 // MONITOR_INC(BmpNew, bitmaps_new_this_frame);
2750 if ( Show_cpu == 1 ) {
2755 dy = gr_get_font_height() + 1;
2757 gr_set_color_fast(&HUD_color_debug);
2761 extern int D3D_textures_in;
2762 extern int D3D_textures_in_frame;
2763 extern int Glide_textures_in;
2764 extern int Glide_textures_in_frame;
2765 extern int Glide_explosion_vram;
2766 gr_printf( sx, sy, NOX("VRAM: %d KB\n"), (D3D_textures_in+Glide_textures_in)/1024 );
2768 gr_printf( sx, sy, NOX("VRAM: +%d KB\n"), (Glide_textures_in_frame+D3D_textures_in_frame)/1024 );
2770 gr_printf( sx, sy, NOX("EXP VRAM: %dKB\n"), (Glide_explosion_vram)/1024 );
2774 // gr_printf( sx, sy, "BPP: %d", gr_screen.bits_per_pixel );
2776 gr_printf( sx, sy, NOX("DMA: %s"), transfer_text );
2778 gr_printf( sx, sy, NOX("POLYP: %d"), modelstats_num_polys );
2780 gr_printf( sx, sy, NOX("POLYD: %d"), modelstats_num_polys_drawn );
2782 gr_printf( sx, sy, NOX("VERTS: %d"), modelstats_num_verts );
2787 extern int Num_pairs; // Number of object pairs that were checked.
2788 gr_printf( sx, sy, NOX("PAIRS: %d"), Num_pairs );
2791 extern int Num_pairs_checked; // What percent of object pairs were checked.
2792 gr_printf( sx, sy, NOX("FVI: %d"), Num_pairs_checked );
2794 Num_pairs_checked = 0;
2798 gr_printf( sx, sy, NOX("Snds: %d"), snd_num_playing() );
2801 if ( Timing_total > 0.01f ) {
2802 gr_printf( sx, sy, NOX("CLEAR: %.0f%%"), Timing_clear*100.0f/Timing_total );
2804 gr_printf( sx, sy, NOX("REND2D: %.0f%%"), Timing_render2*100.0f/Timing_total );
2806 gr_printf( sx, sy, NOX("REND3D: %.0f%%"), Timing_render3*100.0f/Timing_total );
2808 gr_printf( sx, sy, NOX("FLIP: %.0f%%"), Timing_flip*100.0f/Timing_total );
2810 gr_printf( sx, sy, NOX("GAME: %.0f%%"), (Timing_total-(Timing_render2+Timing_render3+Timing_flip+Timing_clear))*100.0f/Timing_total );
2820 dy = gr_get_font_height() + 1;
2822 gr_set_color_fast(&HUD_color_debug);
2825 extern int TotalRam;
2826 gr_printf( sx, sy, NOX("DYN: %d KB\n"), TotalRam/1024 );
2831 extern int Model_ram;
2832 gr_printf( sx, sy, NOX("POF: %d KB\n"), Model_ram/1024 );
2836 gr_printf( sx, sy, NOX("BMP: %d KB\n"), bm_texture_ram/1024 );
2838 gr_printf( sx, sy, NOX("S-SRAM: %d KB\n"), Snd_sram/1024 ); // mem used to store game sound
2841 gr_printf( sx, sy, NOX("S-HRAM: %d KB\n"), Snd_hram/1024 ); // mem used to store game sound
2844 extern int D3D_textures_in;
2845 extern int Glide_textures_in;
2846 extern int Glide_textures_in_frame;
2847 extern int Glide_explosion_vram;
2848 gr_printf( sx, sy, NOX("VRAM: %d KB\n"), (D3D_textures_in+Glide_textures_in)/1024 );
2850 gr_printf( sx, sy, NOX("VRAM: +%d KB\n"), (Glide_textures_in_frame)/1024 );
2852 gr_printf( sx, sy, NOX("EXP VRAM: %dKB\n"), (Glide_explosion_vram)/1024 );
2856 extern int GL_textures_in;
2857 gr_printf( sx, sy, NOX("VRAM: %d KB\n"), (GL_textures_in)/1024 );
2864 if ( Show_player_pos ) {
2868 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));
2871 MONITOR_INC(NumPolys, modelstats_num_polys);
2872 MONITOR_INC(NumPolysDrawn, modelstats_num_polys_drawn );
2873 MONITOR_INC(NumVerts, modelstats_num_verts );
2875 modelstats_num_polys = 0;
2876 modelstats_num_polys_drawn = 0;
2877 modelstats_num_verts = 0;
2878 modelstats_num_sortnorms = 0;
2882 void game_show_standalone_framerate()
2884 float frame_rate=30.0f;
2885 if ( frame_int == -1 ) {
2887 for (i=0; i<FRAME_FILTER; i++ ) {
2888 frametimes[i] = 0.0f;
2893 frametotal -= frametimes[frame_int];
2894 frametotal += flFrametime;
2895 frametimes[frame_int] = flFrametime;
2896 frame_int = (frame_int + 1 ) % FRAME_FILTER;
2898 if ( frametotal != 0.0 ) {
2899 if ( Framecount >= FRAME_FILTER ){
2900 frame_rate = FRAME_FILTER / frametotal;
2902 frame_rate = Framecount / frametotal;
2905 std_set_standalone_fps(frame_rate);
2909 // function to show the time remaining in a mission. Used only when the end-mission sexpression is used
2910 void game_show_time_left()
2914 // mission_end_time is a global from missionparse.cpp that contains the mission time at which the
2915 // mission should end (in fixed seconds). There is code in missionparse.cpp which actually handles
2916 // checking how much time is left
2918 if ( Mission_end_time == -1 ){
2922 diff = f2i(Mission_end_time - Missiontime);
2923 // be sure to bash to 0. diff could be negative on frame that we quit mission
2928 hud_set_default_color();
2929 gr_printf( 5, 40, XSTR( "Mission time remaining: %d seconds", 179), diff );
2932 //========================================================================================
2933 //=================== NEW DEBUG CONSOLE COMMANDS TO REPLACE OLD DEBUG PAUSE MENU =========
2934 //========================================================================================
2938 DCF(ai_pause,"Pauses ai")
2941 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2942 if ( Dc_arg_type & ARG_TRUE ) ai_paused = 1;
2943 else if ( Dc_arg_type & ARG_FALSE ) ai_paused = 0;
2944 else if ( Dc_arg_type & ARG_NONE ) ai_paused = !ai_paused;
2947 obj_init_all_ships_physics();
2950 if ( Dc_help ) dc_printf( "Usage: ai_paused [bool]\nSets ai_paused to true or false. If nothing passed, then toggles it.\n" );
2951 if ( Dc_status ) dc_printf( "ai_paused is %s\n", (ai_paused?"TRUE":"FALSE") );
2954 DCF(single_step,"Single steps the game")
2957 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2958 if ( Dc_arg_type & ARG_TRUE ) game_single_step = 1;
2959 else if ( Dc_arg_type & ARG_FALSE ) game_single_step = 0;
2960 else if ( Dc_arg_type & ARG_NONE ) game_single_step = !game_single_step;
2962 last_single_step = 0; // Make so single step waits a frame before stepping
2965 if ( Dc_help ) dc_printf( "Usage: single_step [bool]\nSets single_step to true or false. If nothing passed, then toggles it.\n" );
2966 if ( Dc_status ) dc_printf( "single_step is %s\n", (game_single_step?"TRUE":"FALSE") );
2969 DCF_BOOL(physics_pause, physics_paused)
2970 DCF_BOOL(ai_rendering, Ai_render_debug_flag)
2971 DCF_BOOL(ai_firing, Ai_firing_enabled )
2973 // Create some simple aliases to these commands...
2974 debug_command dc_s("s","shortcut for single_step",dcf_single_step);
2975 debug_command dc_p("p","shortcut for physics_pause", dcf_physics_pause );
2976 debug_command dc_r("r","shortcut for ai_rendering", dcf_ai_rendering );
2977 debug_command dc_f("f","shortcut for ai_firing", dcf_ai_firing);
2978 debug_command dc_a("a","shortcut for ai_pause", dcf_ai_pause);
2981 //========================================================================================
2982 //========================================================================================
2985 void game_training_pause_do()
2989 key = game_check_key();
2991 gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
2998 void game_increase_skill_level()
3001 if (Game_skill_level >= NUM_SKILL_LEVELS){
3002 Game_skill_level = 0;
3006 int Player_died_time;
3008 int View_percent = 100;
3011 DCF(view, "Sets the percent of the 3d view to render.")
3014 dc_get_arg(ARG_INT);
3015 if ( (Dc_arg_int >= 5 ) || (Dc_arg_int <= 100) ) {
3016 View_percent = Dc_arg_int;
3018 dc_printf( "Illegal value for view. (Must be from 5-100) \n\n");
3024 dc_printf("Usage: view [n]\nwhere n is percent of view to show (5-100).\n");
3028 dc_printf("View is set to %d%%\n", View_percent );
3033 // Set the clip region for the 3d rendering window
3034 void game_set_view_clip()
3036 if ((Game_mode & GM_DEAD) || (supernova_active() >= 2)) {
3037 // Set the clip region for the letterbox "dead view"
3038 int yborder = gr_screen.max_h/4;
3040 // Numeric constants encouraged by J "pig farmer" S, who shall remain semi-anonymous.
3041 // J.S. I've changed my ways!! See the new "no constants" code!!!
3042 gr_set_clip(0, yborder, gr_screen.max_w, gr_screen.max_h - yborder*2 );
3044 // Set the clip region for normal view
3045 if ( View_percent >= 100 ) {
3048 int xborder, yborder;
3050 if ( View_percent < 5 ) {
3054 float fp = i2fl(View_percent)/100.0f;
3055 int fi = fl2i(fl_sqrt(fp)*100.0f);
3056 if ( fi > 100 ) fi=100;
3058 xborder = ( gr_screen.max_w*(100-fi) )/200;
3059 yborder = ( gr_screen.max_h*(100-fi) )/200;
3061 gr_set_clip(xborder, yborder, gr_screen.max_w-xborder*2,gr_screen.max_h-yborder*2 );
3067 void show_debug_stuff()
3070 int laser_count = 0, missile_count = 0;
3072 for (i=0; i<MAX_OBJECTS; i++) {
3073 if (Objects[i].type == OBJ_WEAPON){
3074 if (Weapon_info[Weapons[Objects[i].instance].weapon_info_index].subtype == WP_LASER){
3076 } else if (Weapon_info[Weapons[Objects[i].instance].weapon_info_index].subtype == WP_MISSILE){
3082 nprintf(("Mike", "Frame: %i Lasers: %4i, Missiles: %4i\n", Framecount, laser_count, missile_count));
3085 extern int Tool_enabled;
3090 int tst_bitmap = -1;
3092 float tst_offset, tst_offset_total;
3095 void game_tst_frame_pre()
3103 g3_rotate_vertex(&v, &tst_pos);
3104 g3_project_vertex(&v);
3107 if(!((v.sx >= 0) && (v.sx <= gr_screen.max_w) && (v.sy >= 0) && (v.sy <= gr_screen.max_h))){
3111 // big ship? always tst
3113 // within 3000 meters
3114 if( vm_vec_dist_quick(&tst_pos, &Eye_position) <= 3000.0f){
3118 // within 300 meters
3119 if( (vm_vec_dist_quick(&tst_pos, &Eye_position) <= 300.0f) && ((tst_time == 0) || ((time(NULL) - tst_time) >= 10)) ){
3126 void game_tst_frame()
3136 tst_time = time(NULL);
3138 // load the tst bitmap
3139 switch((int)frand_range(0.0f, 3.0)){
3141 tst_bitmap = bm_load("ig_jim");
3143 mprintf(("TST 0\n"));
3147 tst_bitmap = bm_load("ig_kan");
3149 mprintf(("TST 1\n"));
3153 tst_bitmap = bm_load("ig_jim");
3155 mprintf(("TST 2\n"));
3159 tst_bitmap = bm_load("ig_kan");
3161 mprintf(("TST 3\n"));
3170 // get the tst bitmap dimensions
3172 bm_get_info(tst_bitmap, &w, &h);
3175 tst_y = frand_range(0.0f, (float)gr_screen.max_h - h);
3177 snd_play(&Snds[SND_VASUDAN_BUP]);
3179 // tst x and direction
3183 tst_offset_total = (float)w;
3184 tst_offset = (float)w;
3186 tst_x = (float)gr_screen.max_w;
3187 tst_offset_total = (float)-w;
3188 tst_offset = (float)w;
3196 float diff = (tst_offset_total / 0.5f) * flFrametime;
3202 tst_offset -= fl_abs(diff);
3203 } else if(tst_mode == 2){
3206 tst_offset -= fl_abs(diff);
3210 gr_set_bitmap(tst_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
3211 gr_bitmap((int)tst_x, (int)tst_y);
3214 if(timestamp_elapsed_safe(tst_stamp, 1100)){
3218 // if we passed the switch point
3219 if(tst_offset <= 0.0f){
3224 tst_stamp = timestamp(1000);
3225 tst_offset = fl_abs(tst_offset_total);
3236 void game_tst_mark(object *objp, ship *shipp)
3245 if((objp == NULL) || (shipp == NULL) || (shipp->ship_info_index < 0) || (shipp->ship_info_index >= Num_ship_types)){
3248 sip = &Ship_info[shipp->ship_info_index];
3255 tst_pos = objp->pos;
3256 if(sip->flags & (SIF_BIG_SHIP | SIF_HUGE_SHIP)){
3262 extern void render_shields();
3264 void player_repair_frame(float frametime)
3266 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
3268 for(idx=0;idx<MAX_PLAYERS;idx++){
3271 np = &Net_players[idx];
3273 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)){
3275 // don't rearm/repair if the player is dead or dying/departing
3276 if ( !NETPLAYER_IS_DEAD(np) && !(Ships[Objects[np->player->objnum].instance].flags & (SF_DYING|SF_DEPARTING)) ) {
3277 ai_do_repair_frame(&Objects[Net_players[idx].player->objnum],&Ai_info[Ships[Objects[Net_players[idx].player->objnum].instance].ai_index],frametime);
3282 if ( (Player_obj != NULL) && (Player_obj->type == OBJ_SHIP) && !(Game_mode & GM_STANDALONE_SERVER) && (Player_ship != NULL) && !(Player_ship->flags & SF_DYING) ) {
3283 ai_do_repair_frame(Player_obj, &Ai_info[Ships[Player_obj->instance].ai_index], frametime);
3289 #define NUM_FRAMES_TEST 300
3290 #define NUM_MIXED_SOUNDS 16
3291 void do_timing_test(float flFrametime)
3293 static int framecount = 0;
3294 static int test_running = 0;
3295 static float test_time = 0.0f;
3297 static int snds[NUM_MIXED_SOUNDS];
3300 if ( test_running ) {
3302 test_time += flFrametime;
3303 if ( framecount >= NUM_FRAMES_TEST ) {
3305 nprintf(("General", "%d frames took %.3f seconds\n", NUM_FRAMES_TEST, test_time));
3306 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3311 if ( Test_begin == 1 ) {
3317 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3320 // start looping digital sounds
3321 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3322 snds[i] = snd_play_looping( &Snds[i], 0.0f);
3329 DCF(dcf_fov, "Change the field of view")
3332 dc_get_arg(ARG_FLOAT|ARG_NONE);
3333 if ( Dc_arg_type & ARG_NONE ) {
3334 Viewer_zoom = VIEWER_ZOOM_DEFAULT;
3335 dc_printf( "Zoom factor reset\n" );
3337 if ( Dc_arg_type & ARG_FLOAT ) {
3338 if (Dc_arg_float < 0.25f) {
3339 Viewer_zoom = 0.25f;
3340 dc_printf("Zoom factor pinned at 0.25.\n");
3341 } else if (Dc_arg_float > 1.25f) {
3342 Viewer_zoom = 1.25f;
3343 dc_printf("Zoom factor pinned at 1.25.\n");
3345 Viewer_zoom = Dc_arg_float;
3351 dc_printf( "Usage: fov [factor]\nFactor is the zoom factor btwn .25 and 1.25\nNo parameter resets it to default.\n" );
3354 dc_printf("Zoom factor set to %6.3f (original = 0.5, John = 0.75)", Viewer_zoom);
3358 DCF(framerate_cap, "Sets the framerate cap")
3361 dc_get_arg(ARG_INT);
3362 if ( (Dc_arg_int >= 1 ) || (Dc_arg_int <= 120) ) {
3363 Framerate_cap = Dc_arg_int;
3365 dc_printf( "Illegal value for framerate cap. (Must be from 1-120) \n\n");
3371 dc_printf("Usage: framerate_cap [n]\nwhere n is the frames per second to cap framerate at.\n");
3372 dc_printf("If n is 0 or omitted, then the framerate cap is removed\n");
3373 dc_printf("[n] must be from 1 to 120.\n");
3377 if ( Framerate_cap )
3378 dc_printf("Framerate cap is set to %d fps\n", Framerate_cap );
3380 dc_printf("There is no framerate cap currently active.\n");
3384 #define MIN_DIST_TO_DEAD_CAMERA 50.0f
3385 int Show_viewing_from_self = 0;
3387 void say_view_target()
3389 object *view_target;
3391 if ((Viewer_mode & VM_OTHER_SHIP) && (Player_ai->target_objnum != -1))
3392 view_target = &Objects[Player_ai->target_objnum];
3394 view_target = Player_obj;
3396 if (Game_mode & GM_DEAD) {
3397 if (Player_ai->target_objnum != -1)
3398 view_target = &Objects[Player_ai->target_objnum];
3401 if (!(Game_mode & GM_DEAD_DIED) && ((Game_mode & (GM_DEAD_BLEW_UP)) || ((Last_view_target != NULL) && (Last_view_target != view_target)))) {
3402 if (view_target != Player_obj){
3404 char *view_target_name = NULL;
3405 switch(Objects[Player_ai->target_objnum].type) {
3407 view_target_name = Ships[Objects[Player_ai->target_objnum].instance].ship_name;
3410 view_target_name = Weapon_info[Weapons[Objects[Player_ai->target_objnum].instance].weapon_info_index].name;
3411 Viewer_mode &= ~VM_OTHER_SHIP;
3413 case OBJ_JUMP_NODE: {
3414 char jump_node_name[128];
3415 strcpy(jump_node_name, XSTR( "jump node", 184));
3416 view_target_name = jump_node_name;
3417 Viewer_mode &= ~VM_OTHER_SHIP;
3426 if ( view_target_name ) {
3427 HUD_fixed_printf(0.0f, XSTR( "Viewing %s%s\n", 185), (Viewer_mode & VM_OTHER_SHIP) ? XSTR( "from ", 186) : "", view_target_name);
3428 Show_viewing_from_self = 1;
3431 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER) && (Player_obj->type == OBJ_OBSERVER)){
3432 HUD_fixed_printf(2.0f,XSTR( "Viewing from observer\n", 187));
3433 Show_viewing_from_self = 1;
3435 if (Show_viewing_from_self)
3436 HUD_fixed_printf(2.0f, XSTR( "Viewing from self\n", 188));
3441 Last_view_target = view_target;
3445 float Game_hit_x = 0.0f;
3446 float Game_hit_y = 0.0f;
3448 // Reset at the beginning of each frame
3449 void game_whack_reset()
3455 // Apply a 2d whack to the player
3456 void game_whack_apply( float x, float y )
3458 // Do some force feedback
3459 joy_ff_play_dir_effect(x * 80.0f, y * 80.0f);
3465 // mprintf(( "WHACK = %.1f, %.1f\n", Game_hit_x, Game_hit_y ));
3468 // call to apply a "shudder"
3469 void game_shudder_apply(int time, float intensity)
3471 Game_shudder_time = timestamp(time);
3472 Game_shudder_total = time;
3473 Game_shudder_intensity = intensity;
3476 #define FF_SCALE 10000
3477 void apply_hud_shake(matrix *eye_orient)
3479 if (Viewer_obj == Player_obj) {
3480 physics_info *pi = &Player_obj->phys_info;
3488 // Make eye shake due to afterburner
3489 if ( !timestamp_elapsed(pi->afterburner_decay) ) {
3492 dtime = timestamp_until(pi->afterburner_decay);
3496 tangles.p += 0.07f * (float) (r1-MY_RAND_MAX/2)/MY_RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/ABURN_DECAY_TIME));
3497 tangles.h += 0.07f * (float) (r2-MY_RAND_MAX/2)/MY_RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/ABURN_DECAY_TIME));
3500 // Make eye shake due to engine wash
3502 if (Player_obj->type == OBJ_SHIP && (Ships[Player_obj->instance].wash_intensity > 0) && Wash_on ) {
3505 tangles.p += 0.07f * Ships[Player_obj->instance].wash_intensity * (float) (r1-MY_RAND_MAX/2)/MY_RAND_MAX;
3506 tangles.h += 0.07f * Ships[Player_obj->instance].wash_intensity * (float) (r2-MY_RAND_MAX/2)/MY_RAND_MAX;
3508 // get the intensity
3509 float intensity = FF_SCALE * Ships[Player_obj->instance].wash_intensity;
3513 vm_vec_rand_vec_quick(&rand_vec);
3516 joy_ff_play_dir_effect(intensity*rand_vec.xyz.x, intensity*rand_vec.xyz.y);
3520 // make hud shake due to shuddering
3521 if(Game_shudder_time != -1){
3522 // if the timestamp has elapsed
3523 if(timestamp_elapsed(Game_shudder_time)){
3524 Game_shudder_time = -1;
3526 // otherwise apply some shudder
3530 dtime = timestamp_until(Game_shudder_time);
3534 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));
3535 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));
3540 vm_angles_2_matrix(&tm, &tangles);
3541 SDL_assert(vm_vec_mag(&tm.v.fvec) > 0.0f);
3542 SDL_assert(vm_vec_mag(&tm.v.rvec) > 0.0f);
3543 SDL_assert(vm_vec_mag(&tm.v.uvec) > 0.0f);
3544 vm_matrix_x_matrix(&tm2, eye_orient, &tm);
3549 extern void compute_slew_matrix(matrix *orient, angles *a); // TODO: move code to proper place and extern in header file
3551 // Player's velocity just before he blew up. Used to keep camera target moving.
3552 vector Dead_player_last_vel = { { { 1.0f, 1.0f, 1.0f } } };
3554 // Set eye_pos and eye_orient based on view mode.
3555 void game_render_frame_setup(vector *eye_pos, matrix *eye_orient)
3559 static int last_Viewer_mode = 0;
3560 static int last_Game_mode = 0;
3561 static int last_Viewer_objnum = -1;
3563 // This code is supposed to detect camera "cuts"... like going between
3566 // determine if we need to regenerate the nebula
3567 if( (!(last_Viewer_mode & VM_EXTERNAL) && (Viewer_mode & VM_EXTERNAL)) || // internal to external
3568 ((last_Viewer_mode & VM_EXTERNAL) && !(Viewer_mode & VM_EXTERNAL)) || // external to internal
3569 (!(last_Viewer_mode & VM_DEAD_VIEW) && (Viewer_mode & VM_DEAD_VIEW)) || // non dead-view to dead-view
3570 ((last_Viewer_mode & VM_DEAD_VIEW) && !(Viewer_mode & VM_DEAD_VIEW)) || // dead-view to non dead-view
3571 (!(last_Viewer_mode & VM_WARP_CHASE) && (Viewer_mode & VM_WARP_CHASE)) || // non warp-chase to warp-chase
3572 ((last_Viewer_mode & VM_WARP_CHASE) && !(Viewer_mode & VM_WARP_CHASE)) || // warp-chase to non warp-chase
3573 (!(last_Viewer_mode & VM_OTHER_SHIP) && (Viewer_mode & VM_OTHER_SHIP)) || // non other-ship to other-ship
3574 ((last_Viewer_mode & VM_OTHER_SHIP) && !(Viewer_mode & VM_OTHER_SHIP)) || // other-ship to non-other ship
3575 ((Viewer_mode & VM_OTHER_SHIP) && (last_Viewer_objnum != Player_ai->target_objnum)) // other ship mode, but targets changes
3578 // regenerate the nebula
3582 if ( (last_Viewer_mode != Viewer_mode) || (last_Game_mode != Game_mode) ) {
3583 //mprintf(( "************** Camera cut! ************\n" ));
3584 last_Viewer_mode = Viewer_mode;
3585 last_Game_mode = Game_mode;
3587 // Camera moved. Tell stars & debris to not do blurring.
3593 if ( Viewer_mode & VM_PADLOCK_ANY ) {
3594 player_display_packlock_view();
3597 game_set_view_clip();
3599 if (Game_mode & GM_DEAD) {
3600 vector vec_to_deader, view_pos;
3603 Viewer_mode |= VM_DEAD_VIEW;
3605 if (Player_ai->target_objnum != -1) {
3606 int view_from_player = 1;
3608 if (Viewer_mode & VM_OTHER_SHIP) {
3609 // View from target.
3610 Viewer_obj = &Objects[Player_ai->target_objnum];
3612 last_Viewer_objnum = Player_ai->target_objnum;
3614 if ( Viewer_obj->type == OBJ_SHIP ) {
3615 ship_get_eye( eye_pos, eye_orient, Viewer_obj );
3616 view_from_player = 0;
3619 last_Viewer_objnum = -1;
3622 if ( view_from_player ) {
3623 // View target from player ship.
3625 *eye_pos = Player_obj->pos;
3626 vm_vec_normalized_dir(&eye_dir, &Objects[Player_ai->target_objnum].pos, eye_pos);
3627 vm_vector_2_matrix(eye_orient, &eye_dir, NULL, NULL);
3630 dist = vm_vec_normalized_dir(&vec_to_deader, &Player_obj->pos, &Dead_camera_pos);
3632 if (dist < MIN_DIST_TO_DEAD_CAMERA)
3633 dist += flFrametime * 16.0f;
3635 vm_vec_scale(&vec_to_deader, -dist);
3636 vm_vec_add(&Dead_camera_pos, &Player_obj->pos, &vec_to_deader);
3638 view_pos = Player_obj->pos;
3640 if (!(Game_mode & GM_DEAD_BLEW_UP)) {
3641 Viewer_mode &= ~(VM_EXTERNAL | VM_CHASE);
3642 vm_vec_scale_add2(&Dead_camera_pos, &Original_vec_to_deader, 25.0f * flFrametime);
3643 Dead_player_last_vel = Player_obj->phys_info.vel;
3644 //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));
3645 } else if (Player_ai->target_objnum != -1) {
3646 view_pos = Objects[Player_ai->target_objnum].pos;
3648 // Make camera follow explosion, but gradually slow down.
3649 vm_vec_scale_add2(&Player_obj->pos, &Dead_player_last_vel, flFrametime);
3650 view_pos = Player_obj->pos;
3651 vm_vec_scale(&Dead_player_last_vel, 0.99f);
3652 vm_vec_scale_add2(&Dead_camera_pos, &Original_vec_to_deader, min(25.0f, vm_vec_mag_quick(&Dead_player_last_vel)) * flFrametime);
3655 *eye_pos = Dead_camera_pos;
3657 vm_vec_normalized_dir(&eye_dir, &Player_obj->pos, eye_pos);
3659 vm_vector_2_matrix(eye_orient, &eye_dir, NULL, NULL);
3664 // if supernova shockwave
3665 if(supernova_camera_cut()){
3669 // call it dead view
3670 Viewer_mode |= VM_DEAD_VIEW;
3672 // set eye pos and orient
3673 supernova_set_view(eye_pos, eye_orient);
3675 // If already blown up, these other modes can override.
3676 if (!(Game_mode & (GM_DEAD | GM_DEAD_BLEW_UP))) {
3677 Viewer_mode &= ~VM_DEAD_VIEW;
3679 Viewer_obj = Player_obj;
3681 if (Viewer_mode & VM_OTHER_SHIP) {
3682 if (Player_ai->target_objnum != -1){
3683 Viewer_obj = &Objects[Player_ai->target_objnum];
3684 last_Viewer_objnum = Player_ai->target_objnum;
3686 Viewer_mode &= ~VM_OTHER_SHIP;
3687 last_Viewer_objnum = -1;
3690 last_Viewer_objnum = -1;
3693 if (Viewer_mode & VM_EXTERNAL) {
3696 vm_angles_2_matrix(&tm2, &Viewer_external_info.angles);
3697 vm_matrix_x_matrix(&tm, &Viewer_obj->orient, &tm2);
3699 vm_vec_scale_add(eye_pos, &Viewer_obj->pos, &tm.v.fvec, 2.0f * Viewer_obj->radius + Viewer_external_info.distance);
3701 vm_vec_sub(&eye_dir, &Viewer_obj->pos, eye_pos);
3702 vm_vec_normalize(&eye_dir);
3703 vm_vector_2_matrix(eye_orient, &eye_dir, &Viewer_obj->orient.v.uvec, NULL);
3706 // Modify the orientation based on head orientation.
3707 compute_slew_matrix(eye_orient, &Viewer_slew_angles);
3709 } else if ( Viewer_mode & VM_CHASE ) {
3712 if ( Viewer_obj->phys_info.speed < 0.1 )
3713 move_dir = Viewer_obj->orient.v.fvec;
3715 move_dir = Viewer_obj->phys_info.vel;
3716 vm_vec_normalize(&move_dir);
3719 vm_vec_scale_add(eye_pos, &Viewer_obj->pos, &move_dir, -3.0f * Viewer_obj->radius - Viewer_chase_info.distance);
3720 vm_vec_scale_add2(eye_pos, &Viewer_obj->orient.v.uvec, 0.75f * Viewer_obj->radius);
3721 vm_vec_sub(&eye_dir, &Viewer_obj->pos, eye_pos);
3722 vm_vec_normalize(&eye_dir);
3724 // JAS: I added the following code because if you slew up using
3725 // Descent-style physics, eye_dir and Viewer_obj->orient.v.uvec are
3726 // equal, which causes a zero-length vector in the vm_vector_2_matrix
3727 // call because the up and the forward vector are the same. I fixed
3728 // it by adding in a fraction of the right vector all the time to the
3730 vector tmp_up = Viewer_obj->orient.v.uvec;
3731 vm_vec_scale_add2( &tmp_up, &Viewer_obj->orient.v.rvec, 0.00001f );
3733 vm_vector_2_matrix(eye_orient, &eye_dir, &tmp_up, NULL);
3736 // Modify the orientation based on head orientation.
3737 compute_slew_matrix(eye_orient, &Viewer_slew_angles);
3738 } else if ( Viewer_mode & VM_WARP_CHASE ) {
3739 *eye_pos = Camera_pos;
3741 ship * shipp = &Ships[Player_obj->instance];
3743 vm_vec_sub(&eye_dir, &shipp->warp_effect_pos, eye_pos);
3744 vm_vec_normalize(&eye_dir);
3745 vm_vector_2_matrix(eye_orient, &eye_dir, &Player_obj->orient.v.uvec, NULL);
3748 // get an eye position based upon the correct type of object
3749 switch(Viewer_obj->type){
3751 // make a call to get the eye point for the player object
3752 ship_get_eye( eye_pos, eye_orient, Viewer_obj );
3755 // make a call to get the eye point for the player object
3756 observer_get_eye( eye_pos, eye_orient, Viewer_obj );
3762 #ifdef JOHNS_DEBUG_CODE
3763 john_debug_stuff(&eye_pos, &eye_orient);
3769 apply_hud_shake(eye_orient);
3771 // setup neb2 rendering
3772 neb2_render_setup(eye_pos, eye_orient);
3776 extern void ai_debug_render_stuff();
3779 int Game_subspace_effect = 0;
3780 DCF_BOOL( subspace, Game_subspace_effect );
3782 // Does everything needed to render a frame
3783 void game_render_frame( vector * eye_pos, matrix * eye_orient )
3787 g3_start_frame(game_zbuffer);
3788 g3_set_view_matrix( eye_pos, eye_orient, Viewer_zoom );
3790 // maybe offset the HUD (jitter stuff)
3791 dont_offset = ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER));
3792 HUD_set_offsets(Viewer_obj, !dont_offset);
3794 // for multiplayer clients, call code in Shield.cpp to set up the Shield_hit array. Have to
3795 // do this becaues of the disjointed nature of this system (in terms of setup and execution).
3796 // must be done before ships are rendered
3797 if ( MULTIPLAYER_CLIENT ) {
3798 shield_point_multi_setup();
3801 if ( Game_subspace_effect ) {
3802 stars_draw(0,0,0,1);
3804 stars_draw(1,1,1,0);
3807 obj_render_all(obj_render);
3808 beam_render_all(); // render all beam weapons
3809 particle_render_all(); // render particles after everything else.
3810 trail_render_all(); // render missilie trails after everything else.
3811 mflash_render_all(); // render all muzzle flashes
3813 // Why do we not show the shield effect in these modes? Seems ok.
3814 //if (!(Viewer_mode & (VM_EXTERNAL | VM_SLEWED | VM_CHASE | VM_DEAD_VIEW))) {
3818 // render nebula lightning
3821 // render local player nebula
3822 neb2_render_player();
3825 ai_debug_render_stuff();
3828 #ifndef RELEASE_REAL
3829 // game_framerate_check();
3833 extern void snd_spew_debug_info();
3834 snd_spew_debug_info();
3837 //================ END OF 3D RENDERING STUFF ====================
3841 if( (Game_detail_flags & DETAIL_FLAG_HUD) && (!(Game_mode & GM_MULTIPLAYER) || ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER) )) ) {
3842 hud_maybe_clear_head_area();
3843 anim_render_all(0, flFrametime);
3846 extern int Multi_display_netinfo;
3847 if(Multi_display_netinfo){
3848 extern void multi_display_netinfo();
3849 multi_display_netinfo();
3852 game_tst_frame_pre();
3855 do_timing_test(flFrametime);
3859 extern int OO_update_index;
3860 multi_rate_display(OO_update_index, 375, 0);
3865 extern void oo_display();
3872 //#define JOHNS_DEBUG_CODE 1
3874 #ifdef JOHNS_DEBUG_CODE
3875 void john_debug_stuff(vector *eye_pos, matrix *eye_orient)
3877 //if ( key_pressed(SDLK_LSHIFT) )
3879 ship_subsys *tsys = Players[Player_num].targeted_subobject;
3881 model_subsystem *turret = tsys->system_info;
3883 if (turret->type == SUBSYSTEM_TURRET ) {
3884 vector v.fvec, v.uvec;
3885 object * tobj = &Objects[Players[Player_num].targeted_subobject_parent];
3887 ship_model_start(tobj);
3889 model_find_world_point(eye_pos, &turret->turret_firing_point[0], turret->model_num, turret->turret_gun_sobj, &tobj->orient, &tobj->pos );
3890 model_find_world_dir(&v.fvec, &turret->turret_matrix.v.fvec, turret->model_num, turret->turret_gun_sobj, &tobj->orient, NULL );
3891 model_find_world_dir(&v.uvec, &turret->turret_matrix.v.uvec, turret->model_num, turret->turret_gun_sobj, &tobj->orient, NULL );
3893 vm_vector_2_matrix( eye_orient, &v.fvec, &v.uvec, NULL );
3895 ship_model_stop(tobj);
3905 // following function for dumping frames for purposes of building trailers.
3908 // function to toggle state of dumping every frame into PCX when playing the game
3909 DCF(dump_frames, "Starts/stop frame dumping at 15 hz")
3913 if ( Debug_dump_frames == 0 ) {
3915 Debug_dump_frames = 15;
3916 Debug_dump_trigger = 0;
3917 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
3918 dc_printf( "Frame dumping at 15 hz is now ON\n" );
3921 Debug_dump_frames = 0;
3922 Debug_dump_trigger = 0;
3923 gr_dump_frame_stop();
3924 dc_printf( "Frame dumping is now OFF\n" );
3930 DCF(dump_frames_trigger, "Starts/stop frame dumping at 15 hz")
3934 if ( Debug_dump_frames == 0 ) {
3936 Debug_dump_frames = 15;
3937 Debug_dump_trigger = 1;
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_frames30, "Starts/stop frame dumping at 30 hz")
3955 if ( Debug_dump_frames == 0 ) {
3957 Debug_dump_frames = 30;
3958 Debug_dump_trigger = 0;
3959 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
3960 dc_printf( "Frame dumping at 30 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_trigger, "Starts/stop frame dumping at 30 hz")
3976 if ( Debug_dump_frames == 0 ) {
3978 Debug_dump_frames = 30;
3979 Debug_dump_trigger = 1;
3980 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
3981 dc_printf( "Triggered 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( "Triggered frame dumping is now OFF\n" );
3993 void game_maybe_dump_frame()
3995 if ( !Debug_dump_frames ){
3999 if( Debug_dump_trigger && !key_pressed(SDLK_q) ){
4006 Debug_dump_frame_num++;
4012 extern int Player_dead_state;
4014 // Flip the page and time how long it took.
4015 void game_flip_page_and_time_it()
4020 t1 = timer_get_fixed_seconds();
4022 t2 = timer_get_fixed_seconds();
4025 t = (gr_screen.max_w*gr_screen.max_h*gr_screen.bytes_per_pixel)/1024;
4026 sprintf( transfer_text, NOX("%d MB/s"), fixmuldiv(t,65,d) );
4033 void game_simulation_frame()
4035 // blow ships up in multiplayer dogfight
4036 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){
4037 // blow up all non-player ships
4038 ship_obj *moveup = GET_FIRST(&Ship_obj_list);
4041 while((moveup != END_OF_LIST(&Ship_obj_list)) && (moveup != NULL)){
4043 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)){
4044 moveup = GET_NEXT(moveup);
4047 shipp = &Ships[Objects[moveup->objnum].instance];
4048 sip = &Ship_info[shipp->ship_info_index];
4050 // only blow up small ships
4051 if((sip->flags & SIF_SMALL_SHIP) && (multi_find_player_by_object(&Objects[moveup->objnum]) < 0) ){
4052 // function to simply explode a ship where it is currently at
4053 ship_self_destruct( &Objects[moveup->objnum] );
4056 moveup = GET_NEXT(moveup);
4062 // process AWACS stuff - do this first thing
4065 // single player, set Player hits_this_frame to 0
4066 if ( !(Game_mode & GM_MULTIPLAYER) && Player ) {
4067 Player->damage_this_burst -= (flFrametime * MAX_BURST_DAMAGE / (0.001f * BURST_DURATION));
4068 Player->damage_this_burst = max(Player->damage_this_burst, 0.0f);
4072 supernova_process();
4073 if(supernova_active() >= 5){
4077 // fire targeting lasers now so that
4078 // 1 - created this frame
4079 // 2 - collide this frame
4080 // 3 - render this frame
4081 // 4 - ignored and deleted next frame
4082 // the basic idea being that because it con be confusing to deal with them on a multi-frame basis, they are only valid for
4084 ship_process_targeting_lasers();
4086 // do this here so that it works for multiplayer
4088 // get viewer direction
4089 int viewer_direction = PHYSICS_VIEWER_REAR;
4091 if(Viewer_mode == 0){
4092 viewer_direction = PHYSICS_VIEWER_FRONT;
4094 if(Viewer_mode & VM_PADLOCK_UP){
4095 viewer_direction = PHYSICS_VIEWER_UP;
4097 else if(Viewer_mode & VM_PADLOCK_REAR){
4098 viewer_direction = PHYSICS_VIEWER_REAR;
4100 else if(Viewer_mode & VM_PADLOCK_LEFT){
4101 viewer_direction = PHYSICS_VIEWER_LEFT;
4103 else if(Viewer_mode & VM_PADLOCK_RIGHT){
4104 viewer_direction = PHYSICS_VIEWER_RIGHT;
4107 physics_set_viewer( &Viewer_obj->phys_info, viewer_direction );
4109 physics_set_viewer( NULL, PHYSICS_VIEWER_FRONT );
4112 #define VM_PADLOCK_UP (1 << 7)
4113 #define VM_PADLOCK_REAR (1 << 8)
4114 #define VM_PADLOCK_LEFT (1 << 9)
4115 #define VM_PADLOCK_RIGHT (1 << 10)
4117 // evaluate mission departures and arrivals before we process all objects.
4118 if ( !(Game_mode & GM_MULTIPLAYER) || ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER) && !multi_endgame_ending()) ) {
4120 // we don't want to evaluate mission stuff when any ingame joiner in multiplayer is receiving
4121 // ships/wing packets.
4122 if ( !((Game_mode & GM_MULTIPLAYER) && (Netgame.flags & NG_FLAG_INGAME_JOINING_CRITICAL)) && !(Game_mode & GM_DEMO_PLAYBACK)){
4123 mission_parse_eval_stuff();
4126 // if we're an observer, move ourselves seperately from the standard physics
4127 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER)){
4128 obj_observer_move(flFrametime);
4131 // move all the objects now
4132 obj_move_all(flFrametime);
4134 // check for cargo reveal (this has an internal timestamp, so only runs every N ms)
4135 // AL: 3-15-98: It was decided to not let AI ships inspect cargo
4136 // ship_check_cargo_all();
4137 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4138 mission_eval_goals();
4142 // always check training objectives, even in multiplayer missions. we need to do this so that the directives gauge works properly on clients
4143 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4144 training_check_objectives();
4147 // do all interpolation now
4148 if ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER) && !multi_endgame_ending() && !(Netgame.flags & NG_FLAG_SERVER_LOST)) {
4149 // client side processing of warping in effect stages
4150 multi_do_client_warp(flFrametime);
4152 // client side movement of an observer
4153 if((Net_player->flags & NETINFO_FLAG_OBSERVER) || (Player_obj->type == OBJ_OBSERVER)){
4154 obj_observer_move(flFrametime);
4157 // move all objects - does interpolation now as well
4158 obj_move_all(flFrametime);
4161 // only process the message queue when the player is "in" the game
4162 if ( !Pre_player_entry ){
4163 message_queue_process(); // process any messages send to the player
4166 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4167 message_maybe_distort(); // maybe distort incoming message if comms damaged
4168 player_repair_frame(flFrametime); // AI objects get repaired in ai_process, called from move code...deal with player.
4169 player_process_pending_praise(); // maybe send off a delayed praise message to the player
4170 player_maybe_play_all_alone_msg(); // mabye tell the player he is all alone
4173 if(!(Game_mode & GM_STANDALONE_SERVER)){
4174 // process some stuff every frame (before frame is rendered)
4175 emp_process_local();
4177 hud_update_frame(); // update hud systems
4179 if (!physics_paused) {
4180 // Move particle system
4181 particle_move_all(flFrametime);
4183 // Move missile trails
4184 trail_move_all(flFrametime);
4186 // process muzzle flashes
4187 mflash_process_all();
4189 // Flash the gun flashes
4190 shipfx_flash_do_frame(flFrametime);
4192 shockwave_move_all(flFrametime); // update all the shockwaves
4195 // subspace missile strikes
4198 obj_snd_do_frame(); // update the object-linked persistant sounds
4199 game_maybe_update_sound_environment();
4200 snd_update_listener(&View_position, &Player_obj->phys_info.vel, &Player_obj->orient);
4202 // AL: debug code used for testing ambient subspace sound (ie when enabling subspace through debug console)
4204 if ( Game_subspace_effect ) {
4205 game_start_subspace_ambient_sound();
4211 // Maybe render and process the dead-popup
4212 void game_maybe_do_dead_popup(float frametime)
4214 if ( popupdead_is_active() ) {
4216 int choice = popupdead_do_frame(frametime);
4218 if ( Game_mode & GM_NORMAL ) {
4221 gameseq_post_event(GS_EVENT_ENTER_GAME);
4225 gameseq_post_event(GS_EVENT_END_GAME);
4229 gameseq_post_event(GS_EVENT_START_GAME);
4232 // this should only happen during a red alert mission
4235 SDL_assert(The_mission.red_alert);
4236 if(!The_mission.red_alert){
4237 gameseq_post_event(GS_EVENT_START_GAME);
4241 // choose the previous mission
4242 mission_campaign_previous_mission();
4244 gameseq_post_event(GS_EVENT_START_GAME);
4254 case POPUPDEAD_DO_MAIN_HALL:
4255 multi_quit_game(PROMPT_NONE,-1);
4258 case POPUPDEAD_DO_RESPAWN:
4259 multi_respawn_normal();
4260 event_music_player_respawn();
4263 case POPUPDEAD_DO_OBSERVER:
4264 multi_respawn_observer();
4265 event_music_player_respawn_as_observer();
4274 if ( leave_popup ) {
4280 // returns true if player is actually in a game_play stats
4281 int game_actually_playing()
4285 state = gameseq_get_state();
4286 if ( (state != GS_STATE_GAME_PLAY) && (state != GS_STATE_DEATH_DIED) && (state != GS_STATE_DEATH_BLEW_UP) )
4292 // Draw the 2D HUD gauges
4293 void game_render_hud_2d()
4295 if ( !(Game_detail_flags & DETAIL_FLAG_HUD) ) {
4299 HUD_render_2d(flFrametime);
4303 // Draw the 3D-dependant HUD gauges
4304 void game_render_hud_3d(vector *eye_pos, matrix *eye_orient)
4306 g3_start_frame(0); // 0 = turn zbuffering off
4307 g3_set_view_matrix( eye_pos, eye_orient, Viewer_zoom );
4309 if ( (Game_detail_flags & DETAIL_FLAG_HUD) && (supernova_active() < 3)/* && !(Game_mode & GM_MULTIPLAYER) || ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER) )*/ ) {
4310 HUD_render_3d(flFrametime);
4314 game_sunspot_process(flFrametime);
4316 // Diminish the palette effect
4317 game_flash_diminish(flFrametime);
4325 int actually_playing;
4326 fix total_time1, total_time2;
4327 fix render2_time1=0, render2_time2=0;
4328 fix render3_time1=0, render3_time2=0;
4329 fix flip_time1=0, flip_time2=0;
4330 fix clear_time1=0, clear_time2=0;
4336 if (Framerate_delay) {
4337 int start_time = timer_get_milliseconds();
4338 while (timer_get_milliseconds() < start_time + Framerate_delay)
4344 demo_do_frame_start();
4346 mprintf(("Error (%d) while processing demo!\n", Demo_error));
4351 // start timing frame
4352 timing_frame_start();
4354 total_time1 = timer_get_fixed_seconds();
4356 // var to hold which state we are in
4357 actually_playing = game_actually_playing();
4359 if ((!(Game_mode & GM_MULTIPLAYER)) || ((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER))) {
4360 if (!(Game_mode & GM_STANDALONE_SERVER)){
4361 SDL_assert( OBJ_INDEX(Player_obj) >= 0 );
4365 if (Missiontime > Entry_delay_time){
4366 Pre_player_entry = 0;
4368 ; //nprintf(("AI", "Framecount = %i, time = %7.3f\n", Framecount, f2fl(Missiontime)));
4371 // Note: These are done even before the player enters, else buffers can overflow.
4372 if (! (Game_mode & GM_STANDALONE_SERVER)){
4376 shield_frame_init();
4378 if ( Player->control_mode != PCM_NORMAL )
4381 if ( !Pre_player_entry && actually_playing ) {
4382 if (! (Game_mode & GM_STANDALONE_SERVER) ) {
4384 if( (!popup_running_state()) && (!popupdead_is_active()) ){
4385 game_process_keys();
4387 // don't read flying controls if we're playing a demo back
4388 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4389 read_player_controls( Player_obj, flFrametime);
4393 // if we're not the master, we may have to send the server-critical ship status button_info bits
4394 if ((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER)){
4395 multi_maybe_send_ship_status();
4400 // Reset the whack stuff
4403 // These two lines must be outside of Pre_player_entry code,
4404 // otherwise too many lights are added.
4407 if ((Game_mode & GM_MULTIPLAYER) && (Netgame.game_state == NETGAME_STATE_SERVER_TRANSFER)){
4411 game_simulation_frame();
4413 // if not actually in a game play state, then return. This condition could only be true in
4414 // a multiplayer game.
4415 if ( !actually_playing ) {
4416 SDL_assert( Game_mode & GM_MULTIPLAYER );
4420 if (!Pre_player_entry) {
4421 if (! (Game_mode & GM_STANDALONE_SERVER)) {
4422 clear_time1 = timer_get_fixed_seconds();
4423 // clear the screen to black
4425 if ( (Game_detail_flags & DETAIL_FLAG_CLEAR) ) {
4429 clear_time2 = timer_get_fixed_seconds();
4430 render3_time1 = timer_get_fixed_seconds();
4431 game_render_frame_setup(&eye_pos, &eye_orient);
4432 game_render_frame( &eye_pos, &eye_orient );
4434 // save the eye position and orientation
4435 if ( Game_mode & GM_MULTIPLAYER ) {
4436 Net_player->s_info.eye_pos = eye_pos;
4437 Net_player->s_info.eye_orient = eye_orient;
4440 hud_show_target_model();
4442 // check to see if we should display the death died popup
4443 if(Game_mode & GM_DEAD_BLEW_UP){
4444 if(Game_mode & GM_MULTIPLAYER){
4445 // catch the situation where we're supposed to be warping out on this transition
4446 if(Net_player->flags & NETINFO_FLAG_WARPING_OUT){
4447 gameseq_post_event(GS_EVENT_DEBRIEF);
4448 } else if((Player_died_popup_wait != -1) && (timestamp_elapsed(Player_died_popup_wait))){
4449 Player_died_popup_wait = -1;
4453 if((Player_died_popup_wait != -1) && (timestamp_elapsed(Player_died_popup_wait))){
4454 Player_died_popup_wait = -1;
4460 // hack - sometimes this seems to slip by in multiplayer. this should guarantee that we catch it
4461 if((Game_mode & GM_MULTIPLAYER) && (Player_multi_died_check != -1) && (Game_mode & GM_DEAD_BLEW_UP) ){
4462 if(fl_abs(time(NULL) - Player_multi_died_check) > 4){
4463 if(!popupdead_is_active()){
4467 Player_multi_died_check = -1;
4471 render3_time2 = timer_get_fixed_seconds();
4472 render2_time1 = timer_get_fixed_seconds();
4475 game_get_framerate();
4476 game_show_framerate();
4478 game_show_time_left();
4480 // Draw the 2D HUD gauges
4481 if(supernova_active() < 3){
4482 game_render_hud_2d();
4485 game_set_view_clip();
4487 // Draw 3D HUD gauges
4488 game_render_hud_3d(&eye_pos, &eye_orient);
4492 render2_time2 = timer_get_fixed_seconds();
4494 // maybe render and process the dead popup
4495 game_maybe_do_dead_popup(flFrametime);
4497 // start timing frame
4498 timing_frame_stop();
4499 // timing_display(30, 10);
4501 // If a regular popup is active, don't flip (popup code flips)
4502 if( !popup_running_state() ){
4503 flip_time1 = timer_get_fixed_seconds();
4504 game_flip_page_and_time_it();
4505 flip_time2 = timer_get_fixed_seconds();
4509 game_maybe_dump_frame(); // used to dump pcx files for building trailers
4512 game_show_standalone_framerate();
4516 game_do_training_checks();
4519 // process lightning (nebula only)
4522 total_time2 = timer_get_fixed_seconds();
4524 // Got some timing numbers
4525 Timing_total = f2fl( total_time2 - total_time1 ) * 1000.0f;
4526 Timing_clear = f2fl( clear_time2 - clear_time1 ) * 1000.0f;
4527 Timing_render2 = f2fl( render2_time2- render2_time1 ) * 1000.0f;
4528 Timing_render3 = f2fl( render3_time2- render3_time1 ) * 1000.0f;
4529 Timing_flip = f2fl( flip_time2 - flip_time1 ) * 1000.0f;
4532 demo_do_frame_end();
4534 mprintf(("Error (%d) while processing demo!\n", Demo_error));
4540 #define MAX_FRAMETIME (F1_0/4) // Frametime gets saturated at this. Changed by MK on 11/1/97.
4541 // Some bug was causing Frametime to always get saturated at 2.0 seconds after the player
4542 // died. This resulted in screwed up death sequences.
4544 fix Last_time = 0; // The absolute time of game at end of last frame (beginning of this frame)
4545 fix Last_delta_time = 0; // While game is paused, this keeps track of how much elapsed in the frame before paused.
4546 static int timer_paused=0;
4547 #if defined(TIMER_TEST) && !defined(NDEBUG)
4548 static int stop_count,start_count;
4549 static int time_stopped,time_started;
4551 int saved_timestamp_ticker = -1;
4553 void game_reset_time()
4555 if((Game_mode & GM_MULTIPLAYER) && (Netgame.game_state == NETGAME_STATE_SERVER_TRANSFER)){
4559 // Last_time = timer_get_fixed_seconds();
4565 void game_stop_time()
4567 if (timer_paused==0) {
4569 time = timer_get_fixed_seconds();
4570 // Save how much time progressed so far in the frame so we can
4571 // use it when we unpause.
4572 Last_delta_time = time - Last_time;
4574 //mprintf(("Last_time in game_stop_time = %7.3f\n", f2fl(Last_delta_time)));
4575 if (Last_delta_time < 0) {
4576 #if defined(TIMER_TEST) && !defined(NDEBUG)
4577 Int3(); //get Matt!!!!
4579 Last_delta_time = 0;
4581 #if defined(TIMER_TEST) && !defined(NDEBUG)
4582 time_stopped = time;
4585 // Stop the timer_tick stuff...
4586 // Normally, you should never access 'timestamp_ticker', consider this a low-level routine
4587 saved_timestamp_ticker = timestamp_ticker;
4591 #if defined(TIMER_TEST) && !defined(NDEBUG)
4596 void game_start_time()
4599 SDL_assert(timer_paused >= 0);
4600 if (timer_paused==0) {
4602 time = timer_get_fixed_seconds();
4603 #if defined(TIMER_TEST) && !defined(NDEBUG)
4605 Int3(); //get Matt!!!!
4608 // Take current time, and set it backwards to account for time
4609 // that the frame already executed, so that timer_get_fixed_seconds() - Last_time
4610 // will be correct when it goes to calculate the frametime next
4612 Last_time = time - Last_delta_time;
4613 #if defined(TIMER_TEST) && !defined(NDEBUG)
4614 time_started = time;
4617 // Restore the timer_tick stuff...
4618 // Normally, you should never access 'timestamp_ticker', consider this a low-level routine
4619 SDL_assert( saved_timestamp_ticker > -1 ); // Called out of order, get JAS
4620 timestamp_ticker = saved_timestamp_ticker;
4621 saved_timestamp_ticker = -1;
4624 #if defined(TIMER_TEST) && !defined(NDEBUG)
4630 void game_set_frametime(int state)
4633 float frame_cap_diff;
4635 thistime = timer_get_fixed_seconds();
4637 if ( Last_time == 0 )
4638 Frametime = F1_0 / 30;
4640 Frametime = thistime - Last_time;
4642 // Frametime = F1_0 / 30;
4644 fix debug_frametime = Frametime; // Just used to display frametime.
4646 // If player hasn't entered mission yet, make frame take 1/4 second.
4647 if ((Pre_player_entry) && (state == GS_STATE_GAME_PLAY))
4650 else if ((Debug_dump_frames) && (state == GS_STATE_GAME_PLAY)) { // note link to above if!!!!!
4652 fix frame_speed = F1_0 / Debug_dump_frames;
4654 if (Frametime > frame_speed ){
4655 nprintf(("warning","slow frame: %x\n",Frametime));
4658 thistime = timer_get_fixed_seconds();
4659 Frametime = thistime - Last_time;
4660 } while (Frametime < frame_speed );
4662 Frametime = frame_speed;
4666 SDL_assert( Framerate_cap > 0 );
4668 // Cap the framerate so it doesn't get too high.
4672 cap = F1_0/Framerate_cap;
4673 if (Frametime < cap) {
4674 thistime = cap - Frametime;
4675 //mprintf(("Sleeping for %6.3f seconds.\n", f2fl(thistime)));
4676 SDL_Delay( (f2fl(thistime) * 1000.0f) );
4678 thistime = timer_get_fixed_seconds();
4682 if((Game_mode & GM_STANDALONE_SERVER) &&
4683 (f2fl(Frametime) < ((float)1.0/(float)Multi_options_g.std_framecap))){
4685 frame_cap_diff = ((float)1.0/(float)Multi_options_g.std_framecap) - f2fl(Frametime);
4686 SDL_Delay((frame_cap_diff*1000));
4688 thistime += fl2f((frame_cap_diff));
4690 Frametime = thistime - Last_time;
4693 // If framerate is too low, cap it.
4694 if (Frametime > MAX_FRAMETIME) {
4696 mprintf(("Frame %2i too long!!: frametime = %.3f (%.3f)\n", Framecount, f2fl(Frametime), f2fl(debug_frametime)));
4698 // to remove warnings in release build
4699 debug_frametime = fl2f(flFrametime);
4701 Frametime = MAX_FRAMETIME;
4704 Frametime = fixmul(Frametime, Game_time_compression);
4706 Last_time = thistime;
4707 //mprintf(("Frame %i, Last_time = %7.3f\n", Framecount, f2fl(Last_time)));
4709 flFrametime = f2fl(Frametime);
4710 //if(!(Game_mode & GM_PLAYING_DEMO)){
4711 timestamp_inc(flFrametime);
4713 /* if ((Framecount > 0) && (Framecount < 10)) {
4714 mprintf(("Frame %2i: frametime = %.3f (%.3f)\n", Framecount, f2fl(Frametime), f2fl(debug_frametime)));
4719 // This is called from game_do_frame(), and from navmap_do_frame()
4720 void game_update_missiontime()
4722 // TODO JAS: Put in if and move this into game_set_frametime,
4723 // fix navmap to call game_stop/start_time
4724 //if ( !timer_paused )
4725 Missiontime += Frametime;
4728 void game_do_frame()
4730 game_set_frametime(GS_STATE_GAME_PLAY);
4731 game_update_missiontime();
4733 if (Game_mode & GM_STANDALONE_SERVER) {
4734 std_multi_set_standalone_missiontime(f2fl(Missiontime));
4737 if ( game_single_step && (last_single_step == game_single_step) ) {
4738 os_set_title( NOX("SINGLE STEP MODE (Pause exits, any other key steps)") );
4739 while( key_checkch() == 0 )
4741 os_set_title( XSTR( "FreeSpace", 171) );
4742 Last_time = timer_get_fixed_seconds();
4745 last_single_step = game_single_step;
4747 if ((gameseq_get_state() == GS_STATE_GAME_PLAY) && Use_mouse_to_fly){
4748 Keep_mouse_centered = 1; // force mouse to center of our window (so we don't hit movement limits)
4752 Keep_mouse_centered = 0;
4753 monitor_update(); // Update monitor variables
4756 void multi_maybe_do_frame()
4758 if ( (Game_mode & GM_MULTIPLAYER) && (Game_mode & GM_IN_MISSION) && !Multi_pause_status){
4763 int Joymouse_button_status = 0;
4765 // Flush all input devices
4773 Joymouse_button_status = 0;
4775 //mprintf(("Game flush!\n" ));
4778 // function for multiplayer only which calls game_do_state_common() when running the
4780 void game_do_dc_networking()
4782 SDL_assert( Game_mode & GM_MULTIPLAYER );
4784 game_do_state_common( gameseq_get_state() );
4787 // Call this whenever in a loop, or when you need to check for a keystroke.
4788 int game_check_key()
4794 // convert keypad enter to normal enter
4795 if ((k & KEY_MASK) == SDLK_KP_ENTER)
4796 k = (k & ~KEY_MASK) | SDLK_RETURN;
4801 #if defined(FS2_DEMO) || defined(FS1_DEMO)
4803 #define DEMO_TRAILER_TIMEOUT_MS 45000 // 45 seconds of no input, play trailer
4804 static int Demo_show_trailer_timestamp = 0;
4806 void demo_reset_trailer_timer()
4808 Demo_show_trailer_timestamp = timer_get_milliseconds();
4811 void demo_maybe_show_trailer(int k)
4814 // if key pressed, reset demo trailer timer
4816 demo_reset_trailer_timer();
4820 // if mouse moved, reset demo trailer timer
4823 mouse_get_delta(&dx, &dy);
4824 if ( (dx > 0) || (dy > 0) ) {
4825 demo_reset_trailer_timer();
4829 // if joystick has moved, reset demo trailer timer
4832 joy_get_delta(&dx, &dy);
4833 if ( (dx > 0) || (dy > 0) ) {
4834 demo_reset_trailer_timer();
4838 // NOTE: reseting the trailer timer on mouse/joystick presses is handled in
4839 // the low-level code. Ugly, I know... but was the simplest and most
4842 // if 30 seconds since last demo trailer time reset, launch movie
4843 if ( os_foreground() ) {
4844 int now = timer_get_milliseconds();
4845 if ( (now - Demo_show_trailer_timestamp) > DEMO_TRAILER_TIMEOUT_MS ) {
4846 // if ( (now - Demo_show_trailer_timestamp) > 10000 ) {
4848 movie_play( NOX("fstrailer2.mve") );
4849 demo_reset_trailer_timer();
4857 // same as game_check_key(), except this is used while actually in the game. Since there
4858 // generally are differences between game control keys and general UI keys, makes sense to
4859 // have seperate functions for each case. If you are not checking a game control while in a
4860 // mission, you should probably be using game_check_key() instead.
4865 if (!os_foreground()) {
4870 // If we're in a single player game, pause it.
4871 if (!(Game_mode & GM_MULTIPLAYER)){
4872 if ( (gameseq_get_state() == GS_STATE_GAME_PLAY) && (!popup_active()) && (!popupdead_is_active()) ) {
4873 game_process_pause_key();
4880 #if defined(FS2_DEMO) || defined(FS1_DEMO)
4881 demo_maybe_show_trailer(k);
4884 // Move the mouse cursor with the joystick.
4885 if (os_foreground() && (!Mouse_hidden) && (Use_joy_mouse) ) {
4886 // Move the mouse cursor with the joystick
4890 joy_get_pos( &jx, &jy, &jz, &jr );
4892 dx = fl2i(f2fl(jx)*flFrametime*500.0f);
4893 dy = fl2i(f2fl(jy)*flFrametime*500.0f);
4896 mouse_get_real_pos( &mx, &my );
4897 mouse_set_pos( mx+dx, my+dy );
4902 m = mouse_down(MOUSE_LEFT_BUTTON);
4904 if ( j != Joymouse_button_status ) {
4905 //mprintf(( "Joy went from %d to %d, mouse is %d\n", Joymouse_button_status, j, m ));
4906 Joymouse_button_status = j;
4908 mouse_mark_button( MOUSE_LEFT_BUTTON, 1 );
4909 } else if ( (!j) && (m) ) {
4910 mouse_mark_button( MOUSE_LEFT_BUTTON, 0 );
4915 // if we should be ignoring keys because of some multiplayer situations
4916 if((Game_mode & GM_MULTIPLAYER) && multi_ignore_controls(k)){
4920 // If a popup is running, don't process all the Fn keys
4921 if( popup_active() ) {
4925 state = gameseq_get_state();
4927 // if ( k ) nprintf(( "General", "Key = %x\n", k ));
4930 case KEY_DEBUGGED + SDLK_BACKSPACE:
4935 launch_context_help();
4940 // if (state != GS_STATE_INITIAL_PLAYER_SELECT) {
4942 // don't allow f2 while warping out in multiplayer
4943 if((Game_mode & GM_MULTIPLAYER) && (Net_player != NULL) && (Net_player->flags & NETINFO_FLAG_WARPING_OUT)){
4948 case GS_STATE_INITIAL_PLAYER_SELECT:
4949 case GS_STATE_OPTIONS_MENU:
4950 case GS_STATE_HUD_CONFIG:
4951 case GS_STATE_CONTROL_CONFIG:
4952 case GS_STATE_DEATH_DIED:
4953 case GS_STATE_DEATH_BLEW_UP:
4954 case GS_STATE_VIEW_MEDALS:
4958 gameseq_post_event(GS_EVENT_OPTIONS_MENU);
4965 // hotkey selection screen -- only valid from briefing and beyond.
4967 #if !(defined(FS2_DEMO) || defined(FS1_DEMO))
4968 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) ) {
4969 gameseq_post_event( GS_EVENT_HOTKEY_SCREEN );
4975 case KEY_DEBUGGED + SDLK_F3:
4976 gameseq_post_event( GS_EVENT_TOGGLE_FULLSCREEN );
4979 case KEY_DEBUGGED + SDLK_F4:
4980 gameseq_post_event( GS_EVENT_TOGGLE_GLIDE );
4984 if(Game_mode & GM_MULTIPLAYER){
4985 if((state == GS_STATE_GAME_PLAY) || (state == GS_STATE_MULTI_PAUSED)){
4986 gameseq_post_event( GS_EVENT_MISSION_LOG_SCROLLBACK );
4990 if ((state == GS_STATE_GAME_PLAY) || (state == GS_STATE_DEATH_DIED) || (state == GS_STATE_DEATH_BLEW_UP) || (state == GS_STATE_GAME_PAUSED) ) {
4991 gameseq_post_event( GS_EVENT_MISSION_LOG_SCROLLBACK );
4997 case SDLK_ESCAPE | KEY_SHIFTED:
4998 // make sure to quit properly out of multiplayer
4999 if(Game_mode & GM_MULTIPLAYER){
5000 multi_quit_game(PROMPT_NONE);
5003 gameseq_post_event( GS_EVENT_QUIT_GAME );
5008 case KEY_DEBUGGED + SDLK_p:
5011 case SDLK_PRINTSCREEN:
5013 static int counter = 0;
5018 sprintf( tmp_name, NOX("screen%02d"), counter );
5020 mprintf(( "Dumping screen to '%s'\n", tmp_name ));
5021 gr_print_screen(tmp_name);
5029 case KEY_SHIFTED | SDLK_RETURN: {
5031 #if !defined(NDEBUG)
5033 if ( Game_mode & GM_NORMAL ){
5037 // if we're in multiplayer mode, do some special networking
5038 if(Game_mode & GM_MULTIPLAYER){
5039 debug_console(game_do_dc_networking);
5046 if ( Game_mode & GM_NORMAL )
5060 gameseq_post_event(GS_EVENT_QUIT_GAME);
5063 void apply_physics( float damping, float desired_vel, float initial_vel, float t, float * new_vel, float * delta_pos );
5066 void camera_set_position( vector *pos )
5071 void camera_set_orient( matrix *orient )
5073 Camera_orient = *orient;
5076 void camera_set_velocity( vector *vel, int instantaneous )
5078 Camera_desired_velocity.xyz.x = 0.0f;
5079 Camera_desired_velocity.xyz.y = 0.0f;
5080 Camera_desired_velocity.xyz.z = 0.0f;
5082 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.rvec, vel->xyz.x );
5083 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.uvec, vel->xyz.y );
5084 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.fvec, vel->xyz.z );
5086 if ( instantaneous ) {
5087 Camera_velocity = Camera_desired_velocity;
5095 vector new_vel, delta_pos;
5097 apply_physics( Camera_damping, Camera_desired_velocity.xyz.x, Camera_velocity.xyz.x, flFrametime, &new_vel.xyz.x, &delta_pos.xyz.x );
5098 apply_physics( Camera_damping, Camera_desired_velocity.xyz.y, Camera_velocity.xyz.y, flFrametime, &new_vel.xyz.y, &delta_pos.xyz.y );
5099 apply_physics( Camera_damping, Camera_desired_velocity.xyz.z, Camera_velocity.xyz.z, flFrametime, &new_vel.xyz.z, &delta_pos.xyz.z );
5101 Camera_velocity = new_vel;
5103 // mprintf(( "Camera velocity = %.1f,%.1f, %.1f\n", Camera_velocity.xyz.x, Camera_velocity.xyz.y, Camera_velocity.xyz.z ));
5105 vm_vec_add2( &Camera_pos, &delta_pos );
5107 float ot = Camera_time+0.0f;
5109 Camera_time += flFrametime;
5111 if ( (ot < 0.667f) && ( Camera_time >= 0.667f ) ) {
5114 tmp.xyz.z = 4.739f; // always go this fast forward.
5116 // pick x and y velocities so they are always on a
5117 // circle with a 25 m radius.
5119 float tmp_angle = frand()*PI2;
5121 tmp.xyz.x = 22.0f * (float)sin(tmp_angle);
5122 tmp.xyz.y = -22.0f * (float)cos(tmp_angle);
5124 //mprintf(( "Angle = %.1f, vx=%.1f, vy=%.1f\n", tmp_angle, tmp.xyz.x, tmp.xyz.y ));
5126 //mprintf(( "Changing velocity!\n" ));
5127 camera_set_velocity( &tmp, 0 );
5130 if ( (ot < 3.0f ) && ( Camera_time >= 3.0f ) ) {
5131 vector tmp = ZERO_VECTOR;
5132 camera_set_velocity( &tmp, 0 );
5137 void end_demo_campaign_do()
5139 #if defined(FS2_DEMO) || defined(FS1_DEMO)
5140 // show upsell screens
5141 demo_upsell_show_screens();
5142 #elif defined(OEM_BUILD)
5143 // show oem upsell screens
5144 oem_upsell_show_screens();
5147 // drop into main hall
5148 gameseq_post_event( GS_EVENT_MAIN_MENU );
5151 // All code to process events. This is the only place
5152 // that you should change the state of the game.
5153 void game_process_event( int current_state, int event )
5155 mprintf(("Got event %s in state %s\n", GS_event_text[event], GS_state_text[current_state]));
5158 case GS_EVENT_SIMULATOR_ROOM:
5159 gameseq_set_state(GS_STATE_SIMULATOR_ROOM);
5162 case GS_EVENT_MAIN_MENU:
5163 gameseq_set_state(GS_STATE_MAIN_MENU);
5166 case GS_EVENT_OPTIONS_MENU:
5167 gameseq_push_state( GS_STATE_OPTIONS_MENU );
5170 case GS_EVENT_BARRACKS_MENU:
5171 gameseq_set_state(GS_STATE_BARRACKS_MENU);
5174 case GS_EVENT_TECH_MENU:
5175 gameseq_set_state(GS_STATE_TECH_MENU);
5178 case GS_EVENT_TRAINING_MENU:
5179 gameseq_set_state(GS_STATE_TRAINING_MENU);
5182 case GS_EVENT_START_GAME:
5183 Select_default_ship = 0;
5184 Player_multi_died_check = -1;
5185 gameseq_set_state(GS_STATE_CMD_BRIEF);
5188 case GS_EVENT_START_BRIEFING:
5189 gameseq_set_state(GS_STATE_BRIEFING);
5192 case GS_EVENT_DEBRIEF:
5193 // did we end the campaign in the main freespace 2 single player campaign?
5195 if(Campaign_ended_in_mission && (Game_mode & GM_CAMPAIGN_MODE) && !SDL_strcasecmp(Campaign.filename, "freespace")) {
5197 if(Campaign_ended_in_mission && (Game_mode & GM_CAMPAIGN_MODE) && !SDL_strcasecmp(Campaign.filename, "freespace2")) {
5199 gameseq_post_event(GS_EVENT_END_CAMPAIGN);
5201 gameseq_set_state(GS_STATE_DEBRIEF);
5204 Player_multi_died_check = -1;
5207 case GS_EVENT_SHIP_SELECTION:
5208 gameseq_set_state( GS_STATE_SHIP_SELECT );
5211 case GS_EVENT_WEAPON_SELECTION:
5212 gameseq_set_state( GS_STATE_WEAPON_SELECT );
5215 case GS_EVENT_ENTER_GAME:
5217 // maybe start recording a demo
5219 demo_start_record("test.fsd");
5223 if (Game_mode & GM_MULTIPLAYER) {
5224 // if we're respawning, make sure we change the view mode so that the hud shows up
5225 if (current_state == GS_STATE_DEATH_BLEW_UP) {
5229 gameseq_set_state(GS_STATE_GAME_PLAY);
5231 gameseq_set_state(GS_STATE_GAME_PLAY, 1);
5234 Player_multi_died_check = -1;
5236 // clear multiplayer button info
5237 extern button_info Multi_ship_status_bi;
5238 memset(&Multi_ship_status_bi, 0, sizeof(button_info));
5240 Start_time = f2fl(timer_get_approx_seconds());
5242 mprintf(("Entering game at time = %7.3f\n", Start_time));
5246 case GS_EVENT_START_GAME_QUICK:
5247 Select_default_ship = 1;
5248 gameseq_post_event(GS_EVENT_ENTER_GAME);
5252 case GS_EVENT_END_GAME:
5253 if ( (current_state == GS_STATE_GAME_PLAY) || (current_state == GS_STATE_DEATH_DIED) ||
5254 (current_state == GS_STATE_DEATH_BLEW_UP) || (current_state == GS_STATE_DEBRIEF) || (current_state == GS_STATE_MULTI_DOGFIGHT_DEBRIEF)) {
5255 gameseq_set_state(GS_STATE_MAIN_MENU);
5260 Player_multi_died_check = -1;
5263 case GS_EVENT_QUIT_GAME:
5264 main_hall_stop_music();
5265 main_hall_stop_ambient();
5266 gameseq_set_state(GS_STATE_QUIT_GAME);
5268 Player_multi_died_check = -1;
5271 case GS_EVENT_GAMEPLAY_HELP:
5272 gameseq_push_state( GS_STATE_GAMEPLAY_HELP );
5275 case GS_EVENT_PAUSE_GAME:
5276 gameseq_push_state(GS_STATE_GAME_PAUSED);
5279 case GS_EVENT_DEBUG_PAUSE_GAME:
5280 gameseq_push_state(GS_STATE_DEBUG_PAUSED);
5283 case GS_EVENT_TRAINING_PAUSE:
5284 gameseq_push_state(GS_STATE_TRAINING_PAUSED);
5287 case GS_EVENT_PREVIOUS_STATE:
5288 gameseq_pop_state();
5291 case GS_EVENT_TOGGLE_FULLSCREEN:
5292 #ifndef HARDWARE_ONLY
5294 if ( gr_screen.mode == GR_SOFTWARE ) {
5295 gr_init( GR_640, GR_DIRECTDRAW );
5296 } else if ( gr_screen.mode == GR_DIRECTDRAW ) {
5297 gr_init( GR_640, GR_SOFTWARE );
5303 case GS_EVENT_TOGGLE_GLIDE:
5306 case GS_EVENT_LOAD_MISSION_MENU:
5307 gameseq_set_state(GS_STATE_LOAD_MISSION_MENU);
5310 case GS_EVENT_MISSION_LOG_SCROLLBACK:
5311 gameseq_push_state( GS_STATE_MISSION_LOG_SCROLLBACK );
5314 case GS_EVENT_HUD_CONFIG:
5315 gameseq_push_state( GS_STATE_HUD_CONFIG );
5318 case GS_EVENT_CONTROL_CONFIG:
5319 gameseq_push_state( GS_STATE_CONTROL_CONFIG );
5322 case GS_EVENT_DEATH_DIED:
5323 gameseq_set_state( GS_STATE_DEATH_DIED );
5326 case GS_EVENT_DEATH_BLEW_UP:
5327 if ( current_state == GS_STATE_DEATH_DIED ) {
5328 gameseq_set_state( GS_STATE_DEATH_BLEW_UP );
5329 event_music_player_death();
5331 // multiplayer clients set their extra check here
5332 if(Game_mode & GM_MULTIPLAYER){
5333 // set the multi died absolute last chance check
5334 Player_multi_died_check = time(NULL);
5337 mprintf(( "Ignoring GS_EVENT_DEATH_BLEW_UP because we're in state %d\n", current_state ));
5341 case GS_EVENT_NEW_CAMPAIGN:
5342 if (!mission_load_up_campaign()){
5343 readyroom_continue_campaign();
5346 Player_multi_died_check = -1;
5349 case GS_EVENT_CAMPAIGN_CHEAT:
5350 if (!mission_load_up_campaign()){
5352 // bash campaign value
5353 extern char Main_hall_campaign_cheat[512];
5356 // look for the mission
5357 for(idx=0; idx<Campaign.num_missions; idx++){
5358 if(!SDL_strcasecmp(Campaign.missions[idx].name, Main_hall_campaign_cheat)){
5359 Campaign.next_mission = idx;
5360 Campaign.prev_mission = idx - 1;
5367 readyroom_continue_campaign();
5370 Player_multi_died_check = -1;
5373 case GS_EVENT_CAMPAIGN_ROOM:
5374 gameseq_set_state(GS_STATE_CAMPAIGN_ROOM);
5377 case GS_EVENT_CMD_BRIEF:
5378 gameseq_set_state(GS_STATE_CMD_BRIEF);
5381 case GS_EVENT_RED_ALERT:
5382 gameseq_set_state(GS_STATE_RED_ALERT);
5385 case GS_EVENT_CREDITS:
5386 gameseq_set_state( GS_STATE_CREDITS );
5389 case GS_EVENT_VIEW_MEDALS:
5390 gameseq_push_state( GS_STATE_VIEW_MEDALS );
5393 case GS_EVENT_SHOW_GOALS:
5394 gameseq_push_state( GS_STATE_SHOW_GOALS ); // use push_state() since we might get to this screen through a variety of states
5397 case GS_EVENT_HOTKEY_SCREEN:
5398 gameseq_push_state( GS_STATE_HOTKEY_SCREEN ); // use push_state() since we might get to this screen through a variety of states
5401 // multiplayer stuff follow these comments
5403 case GS_EVENT_MULTI_JOIN_GAME:
5404 gameseq_set_state( GS_STATE_MULTI_JOIN_GAME );
5407 case GS_EVENT_MULTI_HOST_SETUP:
5408 gameseq_set_state( GS_STATE_MULTI_HOST_SETUP );
5411 case GS_EVENT_MULTI_CLIENT_SETUP:
5412 gameseq_set_state( GS_STATE_MULTI_CLIENT_SETUP );
5415 case GS_EVENT_GOTO_VIEW_CUTSCENES_SCREEN:
5416 gameseq_set_state(GS_STATE_VIEW_CUTSCENES);
5419 case GS_EVENT_MULTI_STD_WAIT:
5420 gameseq_set_state( GS_STATE_MULTI_STD_WAIT );
5423 case GS_EVENT_STANDALONE_MAIN:
5424 gameseq_set_state( GS_STATE_STANDALONE_MAIN );
5427 case GS_EVENT_MULTI_PAUSE:
5428 gameseq_push_state( GS_STATE_MULTI_PAUSED );
5431 case GS_EVENT_INGAME_PRE_JOIN:
5432 gameseq_set_state( GS_STATE_INGAME_PRE_JOIN );
5435 case GS_EVENT_EVENT_DEBUG:
5436 gameseq_push_state(GS_STATE_EVENT_DEBUG);
5439 // Start a warpout where player automatically goes 70 no matter what
5440 // and can't cancel out of it.
5441 case GS_EVENT_PLAYER_WARPOUT_START_FORCED:
5442 Warpout_forced = 1; // If non-zero, bash the player to speed and go through effect
5444 // Same code as in GS_EVENT_PLAYER_WARPOUT_START only ignores current mode
5445 Player->saved_viewer_mode = Viewer_mode;
5446 Player->control_mode = PCM_WARPOUT_STAGE1;
5447 Warpout_sound = snd_play(&Snds[SND_PLAYER_WARP_OUT]);
5448 Warpout_time = 0.0f; // Start timer!
5451 case GS_EVENT_PLAYER_WARPOUT_START:
5452 if ( Player->control_mode != PCM_NORMAL ) {
5453 mprintf(( "Player isn't in normal mode; cannot warp out.\n" ));
5455 Player->saved_viewer_mode = Viewer_mode;
5456 Player->control_mode = PCM_WARPOUT_STAGE1;
5457 Warpout_sound = snd_play(&Snds[SND_PLAYER_WARP_OUT]);
5458 Warpout_time = 0.0f; // Start timer!
5459 Warpout_forced = 0; // If non-zero, bash the player to speed and go through effect
5463 case GS_EVENT_PLAYER_WARPOUT_STOP:
5464 if ( Player->control_mode != PCM_NORMAL ) {
5465 if ( !Warpout_forced ) { // cannot cancel forced warpout
5466 Player->control_mode = PCM_NORMAL;
5467 Viewer_mode = Player->saved_viewer_mode;
5468 hud_subspace_notify_abort();
5469 mprintf(( "Player put back to normal mode.\n" ));
5470 if ( Warpout_sound > -1 ) {
5471 snd_stop( Warpout_sound );
5478 case GS_EVENT_PLAYER_WARPOUT_DONE_STAGE1: // player ship got up to speed
5479 if ( Player->control_mode != PCM_WARPOUT_STAGE1 ) {
5480 gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_STOP );
5481 mprintf(( "Player put back to normal mode, because of invalid sequence in stage1.\n" ));
5483 mprintf(( "Hit target speed. Starting warp effect and moving to stage 2!\n" ));
5484 shipfx_warpout_start( Player_obj );
5485 Player->control_mode = PCM_WARPOUT_STAGE2;
5486 Player->saved_viewer_mode = Viewer_mode;
5487 Viewer_mode |= VM_WARP_CHASE;
5489 vector tmp = Player_obj->pos;
5491 ship_get_eye( &tmp, &tmp_m, Player_obj );
5492 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.rvec, 0.0f );
5493 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.uvec, 0.952f );
5494 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.fvec, -1.782f );
5496 camera_set_position( &tmp );
5497 camera_set_orient( &Player_obj->orient );
5498 vector tmp_vel = { { { 0.0f, 5.1919f, 14.7f } } };
5500 //mprintf(( "Rad = %.1f\n", Player_obj->radius ));
5501 camera_set_velocity( &tmp_vel, 1);
5505 case GS_EVENT_PLAYER_WARPOUT_DONE_STAGE2: // player ship got into the warp effect
5506 if ( Player->control_mode != PCM_WARPOUT_STAGE2 ) {
5507 gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_STOP );
5508 mprintf(( "Player put back to normal mode, because of invalid sequence in stage2.\n" ));
5510 mprintf(( "Hit warp effect. Moving to stage 3!\n" ));
5511 Player->control_mode = PCM_WARPOUT_STAGE3;
5515 case GS_EVENT_PLAYER_WARPOUT_DONE: // player ship got through the warp effect
5516 mprintf(( "Player warped out. Going to debriefing!\n" ));
5517 Player->control_mode = PCM_NORMAL;
5518 Viewer_mode = Player->saved_viewer_mode;
5521 // we have a special debriefing screen for multiplayer furballs
5522 if((Game_mode & GM_MULTIPLAYER) && (The_mission.game_type & MISSION_TYPE_MULTI_DOGFIGHT)){
5523 gameseq_post_event(GS_EVENT_MULTI_DOGFIGHT_DEBRIEF);
5525 // do the normal debriefing for all other situations
5527 gameseq_post_event(GS_EVENT_DEBRIEF);
5531 case GS_EVENT_STANDALONE_POSTGAME:
5532 gameseq_set_state(GS_STATE_STANDALONE_POSTGAME);
5535 case GS_EVENT_INITIAL_PLAYER_SELECT:
5536 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5539 case GS_EVENT_GAME_INIT:
5540 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
5541 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5543 // see if the command line option has been set to use the last pilot, and act acoordingly
5544 if( player_select_get_last_pilot() ) {
5545 // always enter the main menu -- do the automatic network startup stuff elsewhere
5546 // so that we still have valid checks for networking modes, etc.
5547 gameseq_set_state(GS_STATE_MAIN_MENU);
5549 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5554 case GS_EVENT_MULTI_MISSION_SYNC:
5555 gameseq_set_state(GS_STATE_MULTI_MISSION_SYNC);
5558 case GS_EVENT_MULTI_START_GAME:
5559 gameseq_set_state(GS_STATE_MULTI_START_GAME);
5562 case GS_EVENT_MULTI_HOST_OPTIONS:
5563 gameseq_set_state(GS_STATE_MULTI_HOST_OPTIONS);
5566 case GS_EVENT_MULTI_DOGFIGHT_DEBRIEF:
5567 gameseq_set_state(GS_STATE_MULTI_DOGFIGHT_DEBRIEF);
5570 case GS_EVENT_TEAM_SELECT:
5571 gameseq_set_state(GS_STATE_TEAM_SELECT);
5574 case GS_EVENT_END_CAMPAIGN:
5575 gameseq_set_state(GS_STATE_END_OF_CAMPAIGN);
5578 case GS_EVENT_END_DEMO:
5579 gameseq_set_state(GS_STATE_END_DEMO);
5582 case GS_EVENT_LOOP_BRIEF:
5583 gameseq_set_state(GS_STATE_LOOP_BRIEF);
5592 // Called when a state is being left.
5593 // The current state is still at old_state, but as soon as
5594 // this function leaves, then the current state will become
5595 // new state. You should never try to change the state
5596 // in here... if you think you need to, you probably really
5597 // need to post an event, not change the state.
5598 void game_leave_state( int old_state, int new_state )
5600 int end_mission = 1;
5602 switch (new_state) {
5603 case GS_STATE_GAME_PAUSED:
5604 case GS_STATE_DEBUG_PAUSED:
5605 case GS_STATE_OPTIONS_MENU:
5606 case GS_STATE_CONTROL_CONFIG:
5607 case GS_STATE_MISSION_LOG_SCROLLBACK:
5608 case GS_STATE_DEATH_DIED:
5609 case GS_STATE_SHOW_GOALS:
5610 case GS_STATE_HOTKEY_SCREEN:
5611 case GS_STATE_MULTI_PAUSED:
5612 case GS_STATE_TRAINING_PAUSED:
5613 case GS_STATE_EVENT_DEBUG:
5614 case GS_STATE_GAMEPLAY_HELP:
5615 end_mission = 0; // these events shouldn't end a mission
5619 switch (old_state) {
5620 case GS_STATE_BRIEFING:
5621 brief_stop_voices();
5622 if ( (new_state != GS_STATE_OPTIONS_MENU) && (new_state != GS_STATE_WEAPON_SELECT)
5623 && (new_state != GS_STATE_SHIP_SELECT) && (new_state != GS_STATE_HOTKEY_SCREEN)
5624 && (new_state != GS_STATE_TEAM_SELECT) ){
5625 common_select_close();
5626 if ( new_state == GS_STATE_MAIN_MENU ) {
5627 freespace_stop_mission();
5631 // COMMAND LINE OPTION
5632 if (Cmdline_multi_stream_chat_to_file){
5633 cfwrite_string(NOX("-------------------------------------------\n"),Multi_chat_stream);
5634 cfclose(Multi_chat_stream);
5638 case GS_STATE_DEBRIEF:
5639 if ( (new_state != GS_STATE_VIEW_MEDALS) && (new_state != GS_STATE_OPTIONS_MENU) ) {
5644 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
5645 multi_df_debrief_close();
5648 case GS_STATE_LOAD_MISSION_MENU:
5649 mission_load_menu_close();
5652 case GS_STATE_SIMULATOR_ROOM:
5656 case GS_STATE_CAMPAIGN_ROOM:
5657 campaign_room_close();
5660 case GS_STATE_CMD_BRIEF:
5661 if (new_state == GS_STATE_OPTIONS_MENU) {
5666 if (new_state == GS_STATE_MAIN_MENU)
5667 freespace_stop_mission();
5672 case GS_STATE_RED_ALERT:
5676 case GS_STATE_SHIP_SELECT:
5677 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_WEAPON_SELECT &&
5678 new_state != GS_STATE_HOTKEY_SCREEN &&
5679 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_TEAM_SELECT) {
5680 common_select_close();
5681 if ( new_state == GS_STATE_MAIN_MENU ) {
5682 freespace_stop_mission();
5687 case GS_STATE_WEAPON_SELECT:
5688 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_SHIP_SELECT &&
5689 new_state != GS_STATE_HOTKEY_SCREEN &&
5690 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_TEAM_SELECT) {
5691 common_select_close();
5692 if ( new_state == GS_STATE_MAIN_MENU ) {
5693 freespace_stop_mission();
5698 case GS_STATE_TEAM_SELECT:
5699 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_SHIP_SELECT &&
5700 new_state != GS_STATE_HOTKEY_SCREEN &&
5701 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_WEAPON_SELECT) {
5702 common_select_close();
5703 if ( new_state == GS_STATE_MAIN_MENU ) {
5704 freespace_stop_mission();
5709 case GS_STATE_MAIN_MENU:
5710 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
5717 case GS_STATE_OPTIONS_MENU:
5718 //game_start_time();
5719 if(new_state == GS_STATE_MULTI_JOIN_GAME){
5720 multi_join_clear_game_list();
5722 options_menu_close();
5725 case GS_STATE_BARRACKS_MENU:
5726 if(new_state != GS_STATE_VIEW_MEDALS){
5731 case GS_STATE_MISSION_LOG_SCROLLBACK:
5732 hud_scrollback_close();
5735 case GS_STATE_TRAINING_MENU:
5736 training_menu_close();
5739 case GS_STATE_GAME_PLAY:
5740 if ( !(Game_mode & GM_STANDALONE_SERVER) ) {
5741 player_save_target_and_weapon_link_prefs();
5742 game_stop_looped_sounds();
5745 sound_env_disable();
5746 joy_ff_stop_effects();
5748 // stop game time under certain conditions
5749 if ( end_mission || (Game_mode & GM_NORMAL) || ((Game_mode & GM_MULTIPLAYER) && (new_state == GS_STATE_MULTI_PAUSED)) ){
5754 // shut down any recording or playing demos
5759 // when in multiplayer and going back to the main menu, send a leave game packet
5760 // right away (before calling stop mission). stop_mission was taking to long to
5761 // close mission down and I want people to get notified ASAP.
5762 if ( (Game_mode & GM_MULTIPLAYER) && (new_state == GS_STATE_MAIN_MENU) ){
5763 multi_quit_game(PROMPT_NONE);
5766 freespace_stop_mission();
5767 Game_time_compression = F1_0;
5771 case GS_STATE_TECH_MENU:
5775 case GS_STATE_TRAINING_PAUSED:
5776 Training_num_lines = 0;
5777 // fall through to GS_STATE_GAME_PAUSED
5779 case GS_STATE_GAME_PAUSED:
5781 if ( end_mission ) {
5786 case GS_STATE_DEBUG_PAUSED:
5789 pause_debug_close();
5793 case GS_STATE_HUD_CONFIG:
5797 // join/start a game
5798 case GS_STATE_MULTI_JOIN_GAME:
5799 if(new_state != GS_STATE_OPTIONS_MENU){
5800 multi_join_game_close();
5804 case GS_STATE_MULTI_HOST_SETUP:
5805 case GS_STATE_MULTI_CLIENT_SETUP:
5806 // if this is just the host going into the options screen, don't do anything
5807 if((new_state == GS_STATE_MULTI_HOST_OPTIONS) || (new_state == GS_STATE_OPTIONS_MENU)){
5811 // close down the proper state
5812 if(old_state == GS_STATE_MULTI_HOST_SETUP){
5813 multi_create_game_close();
5815 multi_game_client_setup_close();
5818 // COMMAND LINE OPTION
5819 if (Cmdline_multi_stream_chat_to_file){
5820 if( (new_state != GS_STATE_TEAM_SELECT) && (Multi_chat_stream!=NULL) ) {
5821 cfwrite_string(NOX("-------------------------------------------\n"),Multi_chat_stream);
5822 cfclose(Multi_chat_stream);
5827 case GS_STATE_CONTROL_CONFIG:
5828 control_config_close();
5831 case GS_STATE_DEATH_DIED:
5832 Game_mode &= ~GM_DEAD_DIED;
5834 // early end while respawning or blowing up in a multiplayer game
5835 if((Game_mode & GM_MULTIPLAYER) && ((new_state == GS_STATE_DEBRIEF) || (new_state == GS_STATE_MULTI_DOGFIGHT_DEBRIEF)) ){
5837 freespace_stop_mission();
5841 case GS_STATE_DEATH_BLEW_UP:
5842 Game_mode &= ~GM_DEAD_BLEW_UP;
5844 // for single player, we might reload mission, etc. For multiplayer, look at my new state
5845 // to determine if I should do anything.
5846 if ( !(Game_mode & GM_MULTIPLAYER) ) {
5848 freespace_stop_mission();
5851 // if we are not respawing as an observer or as a player, our new state will not
5852 // be gameplay state.
5853 if ( (new_state != GS_STATE_GAME_PLAY) && (new_state != GS_STATE_MULTI_PAUSED) ) {
5854 game_stop_time(); // hasn't been called yet!!
5855 freespace_stop_mission();
5861 case GS_STATE_CREDITS:
5865 case GS_STATE_VIEW_MEDALS:
5869 case GS_STATE_SHOW_GOALS:
5870 mission_show_goals_close();
5873 case GS_STATE_HOTKEY_SCREEN:
5874 if ( new_state != GS_STATE_OPTIONS_MENU ) {
5875 mission_hotkey_close();
5879 case GS_STATE_MULTI_MISSION_SYNC:
5880 // if we're moving into the options menu, don't do anything
5881 if(new_state == GS_STATE_OPTIONS_MENU){
5885 SDL_assert( Game_mode & GM_MULTIPLAYER );
5887 if ( new_state == GS_STATE_GAME_PLAY ){
5888 // palette_restore_palette();
5890 // change a couple of flags to indicate our state!!!
5891 Net_player->state = NETPLAYER_STATE_IN_MISSION;
5892 send_netplayer_update_packet();
5894 // set the game mode
5895 Game_mode |= GM_IN_MISSION;
5899 case GS_STATE_VIEW_CUTSCENES:
5900 cutscenes_screen_close();
5903 case GS_STATE_MULTI_STD_WAIT:
5904 multi_standalone_wait_close();
5907 case GS_STATE_STANDALONE_MAIN:
5908 standalone_main_close();
5909 if(new_state == GS_STATE_MULTI_STD_WAIT){
5910 init_multiplayer_stats();
5914 case GS_STATE_MULTI_PAUSED:
5915 // if ( end_mission ){
5920 case GS_STATE_INGAME_PRE_JOIN:
5921 multi_ingame_select_close();
5924 case GS_STATE_STANDALONE_POSTGAME:
5925 multi_standalone_postgame_close();
5928 case GS_STATE_INITIAL_PLAYER_SELECT:
5929 player_select_close();
5932 case GS_STATE_MULTI_START_GAME:
5933 multi_start_game_close();
5936 case GS_STATE_MULTI_HOST_OPTIONS:
5937 multi_host_options_close();
5940 case GS_STATE_END_OF_CAMPAIGN:
5941 mission_campaign_end_close();
5944 case GS_STATE_LOOP_BRIEF:
5950 // Called when a state is being entered.
5951 // The current state is set to the state we're entering at
5952 // this point, and old_state is set to the state we're coming
5953 // from. You should never try to change the state
5954 // in here... if you think you need to, you probably really
5955 // need to post an event, not change the state.
5957 void game_enter_state( int old_state, int new_state )
5959 switch (new_state) {
5960 case GS_STATE_MAIN_MENU:
5961 // in multiplayer mode, be sure that we are not doing networking anymore.
5962 if ( Game_mode & GM_MULTIPLAYER ) {
5963 SDL_assert( Net_player != NULL );
5964 Net_player->flags &= ~NETINFO_FLAG_DO_NETWORKING;
5967 Game_time_compression = F1_0;
5969 // determine which ship this guy is currently based on
5970 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
5973 if (Player->on_bastion) {
5981 case GS_STATE_BRIEFING:
5982 main_hall_stop_music();
5983 main_hall_stop_ambient();
5985 if (Game_mode & GM_NORMAL) {
5986 // AL: Don't call freespace_start_mission() if re-entering from ship or weapon select
5987 // MWA: or from options or hotkey screens
5988 // JH: or if the command brief state already did this
5989 if ( (old_state != GS_STATE_OPTIONS_MENU) && (old_state != GS_STATE_HOTKEY_SCREEN)
5990 && (old_state != GS_STATE_SHIP_SELECT) && (old_state != GS_STATE_WEAPON_SELECT)
5991 && (old_state != GS_STATE_CMD_BRIEF) ) {
5992 if ( !game_start_mission() ) // this should put us into a new state on failure!
5996 // maybe play a movie before the briefing. don't play if entering briefing screen from ship or weapon select.
5997 if ( (old_state == GS_STATE_DEBRIEF) || (old_state == GS_STATE_SIMULATOR_ROOM) || (old_state == GS_STATE_MAIN_MENU))
5998 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
6000 Game_time_compression = F1_0;
6002 if ( red_alert_mission() ) {
6003 gameseq_post_event(GS_EVENT_RED_ALERT);
6010 case GS_STATE_DEBRIEF:
6011 game_stop_looped_sounds();
6012 mission_goal_fail_incomplete(); // fail all incomplete goals before entering debriefing
6013 if ( (old_state != GS_STATE_VIEW_MEDALS) && (old_state != GS_STATE_OPTIONS_MENU) ){
6018 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
6019 multi_df_debrief_init();
6022 case GS_STATE_LOAD_MISSION_MENU:
6023 mission_load_menu_init();
6026 case GS_STATE_SIMULATOR_ROOM:
6030 case GS_STATE_CAMPAIGN_ROOM:
6031 campaign_room_init();
6034 case GS_STATE_RED_ALERT:
6035 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
6039 case GS_STATE_CMD_BRIEF: {
6040 int team_num = 0; // team number used as index for which cmd brief to use.
6042 if (old_state == GS_STATE_OPTIONS_MENU) {
6046 main_hall_stop_music();
6047 main_hall_stop_ambient();
6049 if (Game_mode & GM_NORMAL) {
6050 // AL: Don't call freespace_start_mission() if re-entering from ship or weapon select
6051 // MWA: or from options or hotkey screens
6052 // JH: or if the command brief state already did this
6053 if ( (old_state != GS_STATE_OPTIONS_MENU) && (old_state != GS_STATE_HOTKEY_SCREEN)
6054 && (old_state != GS_STATE_SHIP_SELECT) && (old_state != GS_STATE_WEAPON_SELECT) ) {
6055 if ( !game_start_mission() ) // this should put us into a new state on failure!
6060 // maybe play a movie before the briefing. don't play if entering briefing screen from ship or weapon select.
6061 if ( (old_state == GS_STATE_DEBRIEF) || (old_state == GS_STATE_SIMULATOR_ROOM) || (old_state == GS_STATE_MAIN_MENU))
6062 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
6064 cmd_brief_init(team_num);
6070 case GS_STATE_SHIP_SELECT:
6074 case GS_STATE_WEAPON_SELECT:
6075 weapon_select_init();
6078 case GS_STATE_TEAM_SELECT:
6082 case GS_STATE_GAME_PAUSED:
6087 case GS_STATE_DEBUG_PAUSED:
6088 // game_stop_time();
6089 // os_set_title("FreeSpace - PAUSED");
6092 case GS_STATE_TRAINING_PAUSED:
6099 case GS_STATE_OPTIONS_MENU:
6101 options_menu_init();
6104 case GS_STATE_GAME_PLAY:
6105 // coming from the gameplay state or the main menu, we might need to load the mission
6106 if ( (Game_mode & GM_NORMAL) && ((old_state == GS_STATE_MAIN_MENU) || (old_state == GS_STATE_GAME_PLAY) || (old_state == GS_STATE_DEATH_BLEW_UP)) ) {
6107 if ( !game_start_mission() ) // this should put us into a new state.
6112 // if we are coming from the briefing, ship select, weapons loadout, or main menu (in the
6113 // case of quick start), then do bitmap loads, etc Don't do any of the loading stuff
6114 // if we are in multiplayer -- this stuff is all handled in the multi-wait section
6115 if ( !(Game_mode & GM_MULTIPLAYER) && ((old_state == GS_STATE_BRIEFING) || (old_state == GS_STATE_SHIP_SELECT) ||
6116 (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)) ) {
6117 // JAS: Used to do all paging here.
6121 HUD_printf("Skill level is set to ** %s **", Skill_level_names(Game_skill_level));
6125 main_hall_stop_music();
6126 main_hall_stop_ambient();
6127 event_music_first_pattern(); // start the first pattern
6130 // special code that restores player ship selection and weapons loadout when doing a quick start
6131 if ( !(Game_mode & GM_MULTIPLAYER) && ((old_state == GS_STATE_MAIN_MENU) || (old_state == GS_STATE_DEATH_BLEW_UP) || (old_state == GS_STATE_GAME_PLAY)) ) {
6132 if ( !SDL_strcasecmp(Player_loadout.filename, Game_current_mission_filename) ) {
6133 wss_direct_restore_loadout();
6137 // single-player, quick-start after just died... we need to set weapon linking and kick off the event music
6138 if (!(Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_DEATH_BLEW_UP) ) {
6139 event_music_first_pattern(); // start the first pattern
6142 if ( !(Game_mode & GM_STANDALONE_SERVER) && (old_state != GS_STATE_GAME_PAUSED) && (old_state != GS_STATE_MULTI_PAUSED) ) {
6143 event_music_first_pattern(); // start the first pattern
6145 player_restore_target_and_weapon_link_prefs();
6147 Game_mode |= GM_IN_MISSION;
6150 // required to truely make mouse deltas zeroed in debug mouse code
6151 void mouse_force_pos(int x, int y);
6152 if (!Is_standalone) {
6153 mouse_force_pos(gr_screen.max_w / 2, gr_screen.max_h / 2);
6159 // only start time if in single player, or coming from multi wait state
6162 (Game_mode & GM_NORMAL) &&
6163 (old_state != GS_STATE_VIEW_CUTSCENES)
6165 (Game_mode & GM_MULTIPLAYER) && (
6166 (old_state == GS_STATE_MULTI_PAUSED) ||
6167 (old_state == GS_STATE_MULTI_MISSION_SYNC)
6173 // when coming from the multi paused state, reset the timestamps
6174 if ( (Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_MULTI_PAUSED) ){
6175 multi_reset_timestamps();
6178 if ((Game_mode & GM_MULTIPLAYER) && (old_state != GS_STATE_DEATH_BLEW_UP) ) {
6179 // initialize all object update details
6180 multi_oo_gameplay_init();
6183 // under certain circumstances, the server should reset the object update rate limiting stuff
6184 if( ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)) &&
6185 ((old_state == GS_STATE_MULTI_PAUSED) || (old_state == GS_STATE_MULTI_MISSION_SYNC)) ){
6187 // reinitialize the rate limiting system for all clients
6188 multi_oo_rate_init_all();
6191 // multiplayer clients should always re-initialize their control info rate limiting system
6192 if((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER)){
6193 multi_oo_rate_init_all();
6197 if(Game_mode & GM_MULTIPLAYER){
6198 multi_ping_reset_players();
6201 Game_subspace_effect = 0;
6202 if (The_mission.flags & MISSION_FLAG_SUBSPACE) {
6203 Game_subspace_effect = 1;
6204 if( !(Game_mode & GM_STANDALONE_SERVER) ){
6205 game_start_subspace_ambient_sound();
6209 sound_env_set(&Game_sound_env);
6210 joy_ff_mission_init(Ship_info[Player_ship->ship_info_index].rotation_time);
6212 // clear multiplayer button info i
6213 extern button_info Multi_ship_status_bi;
6214 memset(&Multi_ship_status_bi, 0, sizeof(button_info));
6217 case GS_STATE_HUD_CONFIG:
6221 case GS_STATE_MULTI_JOIN_GAME:
6222 multi_join_clear_game_list();
6224 if (old_state != GS_STATE_OPTIONS_MENU) {
6225 multi_join_game_init();
6230 case GS_STATE_MULTI_HOST_SETUP:
6231 // don't reinitialize if we're coming back from the host options screen
6232 if ((old_state != GS_STATE_MULTI_HOST_OPTIONS) && (old_state != GS_STATE_OPTIONS_MENU)) {
6233 multi_create_game_init();
6238 case GS_STATE_MULTI_CLIENT_SETUP:
6239 if (old_state != GS_STATE_OPTIONS_MENU) {
6240 multi_game_client_setup_init();
6245 case GS_STATE_CONTROL_CONFIG:
6246 control_config_init();
6249 case GS_STATE_TECH_MENU:
6253 case GS_STATE_BARRACKS_MENU:
6254 if(old_state != GS_STATE_VIEW_MEDALS){
6259 case GS_STATE_MISSION_LOG_SCROLLBACK:
6260 hud_scrollback_init();
6263 case GS_STATE_DEATH_DIED:
6264 Player_died_time = timestamp(10);
6266 if(!(Game_mode & GM_MULTIPLAYER)){
6267 player_show_death_message();
6269 Game_mode |= GM_DEAD_DIED;
6272 case GS_STATE_DEATH_BLEW_UP:
6273 if ( !popupdead_is_active() ) {
6274 Player_ai->target_objnum = -1;
6277 // stop any local EMP effect
6280 Players[Player_num].flags &= ~PLAYER_FLAGS_AUTO_TARGETING; // Prevent immediate switch to a hostile ship.
6281 Game_mode |= GM_DEAD_BLEW_UP;
6282 Show_viewing_from_self = 0;
6284 // timestamp how long we should wait before displaying the died popup
6285 if ( !popupdead_is_active() ) {
6286 Player_died_popup_wait = timestamp(PLAYER_DIED_POPUP_WAIT);
6290 case GS_STATE_GAMEPLAY_HELP:
6291 gameplay_help_init();
6294 case GS_STATE_CREDITS:
6295 main_hall_stop_music();
6296 main_hall_stop_ambient();
6300 case GS_STATE_VIEW_MEDALS:
6301 medal_main_init(Player);
6304 case GS_STATE_SHOW_GOALS:
6305 mission_show_goals_init();
6308 case GS_STATE_HOTKEY_SCREEN:
6309 mission_hotkey_init();
6312 case GS_STATE_MULTI_MISSION_SYNC:
6313 // if we're coming from the options screen, don't do any
6314 if(old_state == GS_STATE_OPTIONS_MENU){
6318 switch(Multi_sync_mode){
6319 case MULTI_SYNC_PRE_BRIEFING:
6320 // if moving from game forming to the team select state
6323 case MULTI_SYNC_POST_BRIEFING:
6324 // if moving from briefing into the mission itself
6327 // tell everyone that we're now loading data
6328 Net_player->state = NETPLAYER_STATE_DATA_LOAD;
6329 send_netplayer_update_packet();
6331 // JAS: Used to do all paging here!!!!
6333 Net_player->state = NETPLAYER_STATE_WAITING;
6334 send_netplayer_update_packet();
6336 Game_time_compression = F1_0;
6338 case MULTI_SYNC_INGAME:
6344 case GS_STATE_VIEW_CUTSCENES:
6345 cutscenes_screen_init();
6348 case GS_STATE_MULTI_STD_WAIT:
6349 multi_standalone_wait_init();
6352 case GS_STATE_STANDALONE_MAIN:
6353 // don't initialize if we're coming from one of these 2 states unless there are no
6354 // players left (reset situation)
6355 if((old_state != GS_STATE_STANDALONE_POSTGAME) || multi_endgame_ending()){
6356 standalone_main_init();
6360 case GS_STATE_MULTI_PAUSED:
6364 case GS_STATE_INGAME_PRE_JOIN:
6365 multi_ingame_select_init();
6368 case GS_STATE_STANDALONE_POSTGAME:
6369 multi_standalone_postgame_init();
6372 case GS_STATE_INITIAL_PLAYER_SELECT:
6373 player_select_init();
6376 case GS_STATE_MULTI_START_GAME:
6377 multi_start_game_init();
6380 case GS_STATE_MULTI_HOST_OPTIONS:
6381 multi_host_options_init();
6384 case GS_STATE_END_OF_CAMPAIGN:
6385 mission_campaign_end_init();
6388 case GS_STATE_LOOP_BRIEF:
6395 // do stuff that may need to be done regardless of state
6396 void game_do_state_common(int state,int no_networking)
6398 game_maybe_draw_mouse(flFrametime); // determine if to draw the mouse this frame
6399 snd_do_frame(); // update sound system
6400 event_music_do_frame(); // music needs to play across many states
6402 multi_log_process();
6404 if (no_networking) {
6408 // maybe do a multiplayer frame based on game mode and state type
6409 if (Game_mode & GM_MULTIPLAYER) {
6411 case GS_STATE_OPTIONS_MENU:
6412 case GS_STATE_GAMEPLAY_HELP:
6413 case GS_STATE_HOTKEY_SCREEN:
6414 case GS_STATE_HUD_CONFIG:
6415 case GS_STATE_CONTROL_CONFIG:
6416 case GS_STATE_MISSION_LOG_SCROLLBACK:
6417 case GS_STATE_SHOW_GOALS:
6418 case GS_STATE_VIEW_CUTSCENES:
6419 case GS_STATE_EVENT_DEBUG:
6420 multi_maybe_do_frame();
6424 game_do_networking();
6428 // Called once a frame.
6429 // You should never try to change the state
6430 // in here... if you think you need to, you probably really
6431 // need to post an event, not change the state.
6432 int Game_do_state_should_skip = 0;
6433 void game_do_state(int state)
6435 // always lets the do_state_common() function determine if the state should be skipped
6436 Game_do_state_should_skip = 0;
6438 // legal to set the should skip state anywhere in this function
6439 game_do_state_common(state); // do stuff that may need to be done regardless of state
6441 if(Game_do_state_should_skip){
6446 case GS_STATE_MAIN_MENU:
6447 game_set_frametime(GS_STATE_MAIN_MENU);
6448 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
6451 main_hall_do(flFrametime);
6455 case GS_STATE_OPTIONS_MENU:
6456 game_set_frametime(GS_STATE_OPTIONS_MENU);
6457 options_menu_do_frame(flFrametime);
6460 case GS_STATE_BARRACKS_MENU:
6461 game_set_frametime(GS_STATE_BARRACKS_MENU);
6462 barracks_do_frame(flFrametime);
6465 case GS_STATE_TRAINING_MENU:
6466 game_set_frametime(GS_STATE_TRAINING_MENU);
6467 training_menu_do_frame(flFrametime);
6470 case GS_STATE_TECH_MENU:
6471 game_set_frametime(GS_STATE_TECH_MENU);
6472 techroom_do_frame(flFrametime);
6475 case GS_STATE_GAMEPLAY_HELP:
6476 game_set_frametime(GS_STATE_GAMEPLAY_HELP);
6477 gameplay_help_do_frame(flFrametime);
6480 case GS_STATE_GAME_PLAY: // do stuff that should be done during gameplay
6484 case GS_STATE_GAME_PAUSED:
6488 case GS_STATE_DEBUG_PAUSED:
6490 game_set_frametime(GS_STATE_DEBUG_PAUSED);
6495 case GS_STATE_TRAINING_PAUSED:
6496 game_training_pause_do();
6499 case GS_STATE_LOAD_MISSION_MENU:
6500 game_set_frametime(GS_STATE_LOAD_MISSION_MENU);
6501 mission_load_menu_do();
6504 case GS_STATE_BRIEFING:
6505 game_set_frametime(GS_STATE_BRIEFING);
6506 brief_do_frame(flFrametime);
6509 case GS_STATE_DEBRIEF:
6510 game_set_frametime(GS_STATE_DEBRIEF);
6511 debrief_do_frame(flFrametime);
6514 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
6515 game_set_frametime(GS_STATE_MULTI_DOGFIGHT_DEBRIEF);
6516 multi_df_debrief_do();
6519 case GS_STATE_SHIP_SELECT:
6520 game_set_frametime(GS_STATE_SHIP_SELECT);
6521 ship_select_do(flFrametime);
6524 case GS_STATE_WEAPON_SELECT:
6525 game_set_frametime(GS_STATE_WEAPON_SELECT);
6526 weapon_select_do(flFrametime);
6529 case GS_STATE_MISSION_LOG_SCROLLBACK:
6530 game_set_frametime(GS_STATE_MISSION_LOG_SCROLLBACK);
6531 hud_scrollback_do_frame(flFrametime);
6534 case GS_STATE_HUD_CONFIG:
6535 game_set_frametime(GS_STATE_HUD_CONFIG);
6536 hud_config_do_frame(flFrametime);
6539 case GS_STATE_MULTI_JOIN_GAME:
6540 game_set_frametime(GS_STATE_MULTI_JOIN_GAME);
6541 multi_join_game_do_frame();
6544 case GS_STATE_MULTI_HOST_SETUP:
6545 game_set_frametime(GS_STATE_MULTI_HOST_SETUP);
6546 multi_create_game_do();
6549 case GS_STATE_MULTI_CLIENT_SETUP:
6550 game_set_frametime(GS_STATE_MULTI_CLIENT_SETUP);
6551 multi_game_client_setup_do_frame();
6554 case GS_STATE_CONTROL_CONFIG:
6555 game_set_frametime(GS_STATE_CONTROL_CONFIG);
6556 control_config_do_frame(flFrametime);
6559 case GS_STATE_DEATH_DIED:
6563 case GS_STATE_DEATH_BLEW_UP:
6567 case GS_STATE_SIMULATOR_ROOM:
6568 game_set_frametime(GS_STATE_SIMULATOR_ROOM);
6569 sim_room_do_frame(flFrametime);
6572 case GS_STATE_CAMPAIGN_ROOM:
6573 game_set_frametime(GS_STATE_CAMPAIGN_ROOM);
6574 campaign_room_do_frame(flFrametime);
6577 case GS_STATE_RED_ALERT:
6578 game_set_frametime(GS_STATE_RED_ALERT);
6579 red_alert_do_frame(flFrametime);
6582 case GS_STATE_CMD_BRIEF:
6583 game_set_frametime(GS_STATE_CMD_BRIEF);
6584 cmd_brief_do_frame(flFrametime);
6587 case GS_STATE_CREDITS:
6588 game_set_frametime(GS_STATE_CREDITS);
6589 credits_do_frame(flFrametime);
6592 case GS_STATE_VIEW_MEDALS:
6593 game_set_frametime(GS_STATE_VIEW_MEDALS);
6597 case GS_STATE_SHOW_GOALS:
6598 game_set_frametime(GS_STATE_SHOW_GOALS);
6599 mission_show_goals_do_frame(flFrametime);
6602 case GS_STATE_HOTKEY_SCREEN:
6603 game_set_frametime(GS_STATE_HOTKEY_SCREEN);
6604 mission_hotkey_do_frame(flFrametime);
6607 case GS_STATE_VIEW_CUTSCENES:
6608 game_set_frametime(GS_STATE_VIEW_CUTSCENES);
6609 cutscenes_screen_do_frame();
6612 case GS_STATE_MULTI_STD_WAIT:
6613 game_set_frametime(GS_STATE_STANDALONE_MAIN);
6614 multi_standalone_wait_do();
6617 case GS_STATE_STANDALONE_MAIN:
6618 game_set_frametime(GS_STATE_STANDALONE_MAIN);
6619 standalone_main_do();
6622 case GS_STATE_MULTI_PAUSED:
6623 game_set_frametime(GS_STATE_MULTI_PAUSED);
6627 case GS_STATE_TEAM_SELECT:
6628 game_set_frametime(GS_STATE_TEAM_SELECT);
6632 case GS_STATE_INGAME_PRE_JOIN:
6633 game_set_frametime(GS_STATE_INGAME_PRE_JOIN);
6634 multi_ingame_select_do();
6637 case GS_STATE_EVENT_DEBUG:
6639 game_set_frametime(GS_STATE_EVENT_DEBUG);
6640 game_show_event_debug(flFrametime);
6644 case GS_STATE_STANDALONE_POSTGAME:
6645 game_set_frametime(GS_STATE_STANDALONE_POSTGAME);
6646 multi_standalone_postgame_do();
6649 case GS_STATE_INITIAL_PLAYER_SELECT:
6650 game_set_frametime(GS_STATE_INITIAL_PLAYER_SELECT);
6654 case GS_STATE_MULTI_MISSION_SYNC:
6655 game_set_frametime(GS_STATE_MULTI_MISSION_SYNC);
6659 case GS_STATE_MULTI_START_GAME:
6660 game_set_frametime(GS_STATE_MULTI_START_GAME);
6661 multi_start_game_do();
6664 case GS_STATE_MULTI_HOST_OPTIONS:
6665 game_set_frametime(GS_STATE_MULTI_HOST_OPTIONS);
6666 multi_host_options_do();
6669 case GS_STATE_END_OF_CAMPAIGN:
6670 mission_campaign_end_do();
6673 case GS_STATE_END_DEMO:
6674 game_set_frametime(GS_STATE_END_DEMO);
6675 end_demo_campaign_do();
6678 case GS_STATE_LOOP_BRIEF:
6679 game_set_frametime(GS_STATE_LOOP_BRIEF);
6683 } // end switch(gs_current_state)
6687 // return 0 if there is enough RAM to run FreeSpace, otherwise return -1
6688 int game_do_ram_check(int ram_in_mbytes)
6690 if ( ram_in_mbytes < 30 ) {
6691 int allowed_to_run = 1;
6692 if ( ram_in_mbytes < 25 ) {
6698 if ( allowed_to_run ) {
6699 SDL_MessageBoxData mboxd;
6700 SDL_MessageBoxButtonData mboxbuttons[2];
6703 // not a translated string, but it's too long and smartdrv isn't
6704 // really a thing for any OS we now support :p
6705 // 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);
6706 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);
6708 mboxbuttons[0].buttonid = 0;
6709 mboxbuttons[0].text = XSTR("Ok", 503);
6710 mboxbuttons[0].flags = 0;
6712 mboxbuttons[1].buttonid = 1;
6713 mboxbuttons[1].text = XSTR("Cancel", 504);
6714 mboxbuttons[0].flags = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT | SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT;
6716 mboxd.flags = SDL_MESSAGEBOX_ERROR;
6717 mboxd.title = XSTR( "Not Enough RAM", 194);
6718 mboxd.message = tmp;
6719 mboxd.numbuttons = 2;
6720 mboxd.buttons = mboxbuttons;
6721 mboxd.window = NULL;
6722 mboxd.colorScheme = NULL;
6724 SDL_ShowMessageBox(&mboxd, &msgbox_rval);
6726 if ( msgbox_rval == 1 ) {
6730 // not a translated string, but it's too long and smartdrv isn't
6731 // really a thing for any OS we now support :p
6732 // 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);
6733 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);
6735 SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, XSTR( "Not Enough RAM", 194), tmp, NULL);
6744 // Check if there is a freespace.exe in the /update directory (relative to where fs.exe is installed).
6745 // If so, copy it over and remove the update directory.
6746 void game_maybe_update_launcher(char *exe_dir)
6749 char src_filename[MAX_PATH];
6750 char dest_filename[MAX_PATH];
6752 strcpy(src_filename, exe_dir);
6753 strcat(src_filename, NOX("\\update\\freespace.exe"));
6755 strcpy(dest_filename, exe_dir);
6756 strcat(dest_filename, NOX("\\freespace.exe"));
6758 // see if src_filename exists
6760 fp = fopen(src_filename, "rb");
6766 SetFileAttributes(dest_filename, FILE_ATTRIBUTE_NORMAL);
6768 // copy updated freespace.exe to freespace exe dir
6769 if ( CopyFile(src_filename, dest_filename, 0) == 0 ) {
6770 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 );
6774 // delete the file in the update directory
6775 DeleteFile(src_filename);
6777 // safe to assume directory is empty, since freespace.exe should only be the file ever in the update dir
6778 char update_dir[MAX_PATH];
6779 strcpy(update_dir, exe_dir);
6780 strcat(update_dir, NOX("\\update"));
6781 RemoveDirectory(update_dir);
6787 void game_spew_pof_info_sub(int model_num, polymodel *pm, int sm, CFILE *out, int *out_total, int *out_destroyed_total)
6791 int sub_total_destroyed = 0;
6795 // get the total for all his children
6796 for (i=pm->submodel[sm].first_child; i>-1; i = pm->submodel[i].next_sibling ) {
6797 game_spew_pof_info_sub(model_num, pm, i, out, &sub_total, &sub_total_destroyed);
6800 // find the # of faces for this _individual_ object
6801 total = submodel_get_num_polys(model_num, sm);
6802 if(strstr(pm->submodel[sm].name, "-destroyed")){
6803 sub_total_destroyed = total;
6807 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[sm].name, total);
6810 *out_total += total + sub_total;
6811 *out_destroyed_total += sub_total_destroyed;
6814 #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);
6815 void game_spew_pof_info()
6817 char *pof_list[1000];
6820 int idx, model_num, i, j;
6822 int total, root_total, model_total, destroyed_total, counted;
6826 num_files = cf_get_file_list(1000, pof_list, CF_TYPE_MODELS, "*.pof");
6828 // spew info on all the pofs
6834 out = cfopen("pofspew.txt", "wt", CFILE_NORMAL, CF_TYPE_DATA);
6839 for(idx=0; idx<num_files; idx++, counted++){
6840 sprintf(str, "%s.pof", pof_list[idx]);
6841 model_num = model_load(str, 0, NULL);
6843 pm = model_get(model_num);
6845 // if we have a real model
6850 // go through and print all raw submodels
6851 cfputs("RAW\n", out);
6854 for (i=0; i<pm->n_models; i++) {
6855 total = submodel_get_num_polys(model_num, i);
6857 model_total += total;
6858 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[i].name, total);
6861 sprintf(str, "Model total %d\n", model_total);
6864 // now go through and do it by LOD
6865 cfputs("BY LOD\n\n", out);
6866 for(i=0; i<pm->n_detail_levels; i++){
6867 sprintf(str, "LOD %d\n", i);
6871 root_total = submodel_get_num_polys(model_num, pm->detail[i] );
6873 destroyed_total = 0;
6874 for (j=pm->submodel[pm->detail[i]].first_child; j>-1; j = pm->submodel[j].next_sibling ) {
6875 game_spew_pof_info_sub(model_num, pm, j, out, &total, &destroyed_total);
6878 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[pm->detail[i]].name, root_total);
6881 sprintf(str, "TOTAL: %d\n", total + root_total);
6883 sprintf(str, "TOTAL not counting destroyed faces %d\n", (total + root_total) - destroyed_total);
6885 sprintf(str, "TOTAL destroyed faces %d\n\n", destroyed_total);
6888 cfputs("------------------------------------------------------------------------\n\n", out);
6892 if(counted >= MAX_POLYGON_MODELS - 5){
6905 game_spew_pof_info();
6908 int game_main(const char *szCmdLine)
6912 // Find out how much RAM is on this machine
6913 Freespace_total_ram = SDL_GetSystemRAM();
6915 if ( game_do_ram_check(Freespace_total_ram) == -1 ) {
6919 if (!vm_init(24*1024*1024)) {
6920 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);
6924 char *tmp_mem = (char *) malloc(16 * 1024 * 1024);
6926 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);
6935 extern void windebug_memwatch_init();
6936 windebug_memwatch_init();
6944 int cpu_cores = SDL_GetCPUCount();
6945 int le = (SDL_BYTEORDER == SDL_LIL_ENDIAN);
6947 mprintf(("Platform: %s\n", SDL_GetPlatform()));
6948 mprintf(("CPU: %d %s\n", cpu_cores, (cpu_cores == 1) ? "core" : "cores"));
6949 mprintf(("Memory: %dMB\n", Freespace_total_ram));
6950 mprintf(("Build: %d-bit, %s-endian\n", sizeof(void*) * 8, le ? "little" : "big"));
6952 parse_cmdline(szCmdLine);
6954 mprintf(("--------------------------------------------------------------------------------\n"));
6956 #ifdef STANDALONE_ONLY_BUILD
6958 nprintf(("Network", "Standalone running"));
6961 nprintf(("Network", "Standalone running"));
6968 // maybe spew pof stuff
6969 if(Cmdline_spew_pof_info){
6970 game_spew_pof_info();
6975 // non-demo, non-standalone, play the intro movie
6977 if ( !Is_standalone ) {
6979 // release -- movies always play
6982 // 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
6983 movie_play( NOX("intro.mve") );
6985 // debug version, movie will only play with -showmovies
6986 #elif !defined(NDEBUG)
6988 movie_play( NOX("intro.mve") );
6991 if ( Cmdline_show_movies )
6992 movie_play( NOX("intro.mve") );
7001 gameseq_post_event(GS_EVENT_STANDALONE_MAIN);
7003 gameseq_post_event(GS_EVENT_GAME_INIT); // start the game rolling -- check for default pilot, or go to the pilot select screen
7007 // only important for non THREADED mode
7010 state = gameseq_process_events();
7011 if ( state == GS_STATE_QUIT_GAME ){
7016 #if defined(FS2_DEMO) || defined(FS1_DEMO)
7018 demo_upsell_show_screens();
7020 #elif defined(OEM_BUILD)
7021 // show upsell screens on exit
7022 oem_upsell_show_screens();
7029 // launcher the fslauncher program on exit
7030 void game_launch_launcher_on_exit()
7034 PROCESS_INFORMATION pi;
7035 char cmd_line[2048];
7036 char original_path[1024] = "";
7038 memset( &si, 0, sizeof(STARTUPINFO) );
7042 _getcwd(original_path, 1023);
7044 // set up command line
7045 strcpy(cmd_line, original_path);
7046 strcat(cmd_line, "\\");
7047 strcat(cmd_line, LAUNCHER_FNAME);
7048 strcat(cmd_line, " -straight_to_update");
7050 BOOL ret = CreateProcess( NULL, // pointer to name of executable module
7051 cmd_line, // pointer to command line string
7052 NULL, // pointer to process security attributes
7053 NULL, // pointer to thread security attributes
7054 FALSE, // handle inheritance flag
7055 CREATE_DEFAULT_ERROR_MODE, // creation flags
7056 NULL, // pointer to new environment block
7057 NULL, // pointer to current directory name
7058 &si, // pointer to STARTUPINFO
7059 &pi // pointer to PROCESS_INFORMATION
7061 // to eliminate build warnings
7071 // This function is called when FreeSpace terminates normally.
7073 void game_shutdown(void)
7079 // don't ever flip a page on the standalone!
7080 if(!(Game_mode & GM_STANDALONE_SERVER)){
7086 // if the player has left the "player select" screen and quit the game without actually choosing
7087 // a player, Player will be NULL, in which case we shouldn't write the player file out!
7088 if (!(Game_mode & GM_STANDALONE_SERVER) && (Player!=NULL) && !Is_standalone){
7092 // load up common multiplayer icons
7093 multi_unload_common_icons();
7095 shockwave_close(); // release any memory used by shockwave system
7096 fireball_close(); // free fireball system
7097 ship_close(); // free any memory that was allocated for the ships
7098 weapon_close(); // free any memory that was allocated for the weapons
7099 hud_free_scrollback_list();// free space allocated to store hud messages in hud scrollback
7100 unload_animating_pointer();// frees the frames used for the animating mouse pointer
7101 bm_unload_all(); // free bitmaps
7102 mission_campaign_close(); // close out the campaign stuff
7103 mission_campaign_shutdown(); // get anything that mission_campaign_close can't do
7104 multi_voice_close(); // close down multiplayer voice (including freeing buffers, etc)
7106 #ifdef MULTI_USE_LAG
7110 // the menu close functions will unload the bitmaps if they were displayed during the game
7111 #if !defined(PRESS_TOUR_BUILD) && !defined(PD_BUILD)
7114 context_help_close(); // close out help system
7115 training_menu_close();
7116 lcl_close(); // be sure localization is closed out
7119 // free left-over memory from parsed tables
7120 cutscene_tbl_close();
7122 scoring_tbl_close();
7123 player_tips_close();
7125 extern void joy_close();
7128 audiostream_close();
7130 event_music_close();
7134 // HACKITY HACK HACK
7135 // if this flag is set, we should be firing up the launcher when exiting freespace
7136 extern int Multi_update_fireup_launcher_on_exit;
7137 if(Multi_update_fireup_launcher_on_exit){
7138 game_launch_launcher_on_exit();
7142 // game_stop_looped_sounds()
7144 // This function will call the appropriate stop looped sound functions for those
7145 // modules which use looping sounds. It is not enough just to stop a looping sound
7146 // at the DirectSound level, the game is keeping track of looping sounds, and this
7147 // function is used to inform the game that looping sounds are being halted.
7149 void game_stop_looped_sounds()
7151 hud_stop_looped_locking_sounds();
7152 hud_stop_looped_engine_sounds();
7153 afterburner_stop_sounds();
7154 player_stop_looped_sounds();
7155 obj_snd_stop_all(); // stop all object-linked persistant sounds
7156 game_stop_subspace_ambient_sound();
7157 snd_stop(Radar_static_looping);
7158 Radar_static_looping = -1;
7159 snd_stop(Target_static_looping);
7160 shipfx_stop_engine_wash_sound();
7161 Target_static_looping = -1;
7164 //////////////////////////////////////////////////////////////////////////
7166 // Code for supporting an animating mouse pointer
7169 //////////////////////////////////////////////////////////////////////////
7171 typedef struct animating_obj
7180 static animating_obj Animating_mouse;
7182 // ----------------------------------------------------------------------------
7183 // init_animating_pointer()
7185 // Called by load_animating_pointer() to ensure the Animating_mouse struct
7186 // gets properly initialized
7188 void init_animating_pointer()
7190 Animating_mouse.first_frame = -1;
7191 Animating_mouse.num_frames = 0;
7192 Animating_mouse.current_frame = -1;
7193 Animating_mouse.time = 0.0f;
7194 Animating_mouse.elapsed_time = 0.0f;
7197 // ----------------------------------------------------------------------------
7198 // load_animating_pointer()
7200 // Called at game init to load in the frames for the animating mouse pointer
7202 // input: filename => filename of animation file that holds the animation
7204 void load_animating_pointer(const char *filename, int dx, int dy)
7209 init_animating_pointer();
7211 am = &Animating_mouse;
7212 am->first_frame = bm_load_animation(filename, &am->num_frames, &fps);
7213 if ( am->first_frame == -1 )
7214 Error(LOCATION, "Could not load animation %s for the mouse pointer\n", filename);
7215 am->current_frame = 0;
7216 am->time = am->num_frames / i2fl(fps);
7219 // ----------------------------------------------------------------------------
7220 // unload_animating_pointer()
7222 // Called at game shutdown to free the memory used to store the animation frames
7224 void unload_animating_pointer()
7229 am = &Animating_mouse;
7230 for ( i = 0; i < am->num_frames; i++ ) {
7231 SDL_assert( (am->first_frame+i) >= 0 );
7232 bm_release(am->first_frame + i);
7235 am->first_frame = -1;
7237 am->current_frame = -1;
7240 // draw the correct frame of the game mouse... called from game_maybe_draw_mouse()
7241 void game_render_mouse(float frametime)
7246 // if animating cursor exists, play the next frame
7247 am = &Animating_mouse;
7248 if ( am->first_frame != -1 ) {
7249 mouse_get_pos(&mx, &my);
7250 am->elapsed_time += frametime;
7251 am->current_frame = fl2i( ( am->elapsed_time / am->time ) * (am->num_frames-1) );
7252 if ( am->current_frame >= am->num_frames ) {
7253 am->current_frame = 0;
7254 am->elapsed_time = 0.0f;
7256 gr_set_cursor_bitmap(am->first_frame + am->current_frame);
7260 // ----------------------------------------------------------------------------
7261 // game_maybe_draw_mouse()
7263 // determines whether to draw the mouse pointer at all, and what frame of
7264 // animation to use if the mouse is animating
7266 // Sets mouse.cpp globals Mouse_hidden and Mouse_moved based on the state of the game.
7268 // input: frametime => elapsed frame time in seconds since last call
7270 void game_maybe_draw_mouse(float frametime)
7274 game_state = gameseq_get_state();
7276 switch ( game_state ) {
7277 case GS_STATE_GAME_PAUSED:
7278 // case GS_STATE_MULTI_PAUSED:
7279 case GS_STATE_GAME_PLAY:
7280 case GS_STATE_DEATH_DIED:
7281 case GS_STATE_DEATH_BLEW_UP:
7282 if ( popup_active() || popupdead_is_active() ) {
7294 if ( !Mouse_hidden )
7295 game_render_mouse(frametime);
7299 void game_do_training_checks()
7303 waypoint_list *wplp;
7305 if (Training_context & TRAINING_CONTEXT_SPEED) {
7306 s = (int) Player_obj->phys_info.fspeed;
7307 if ((s >= Training_context_speed_min) && (s <= Training_context_speed_max)) {
7308 if (!Training_context_speed_set) {
7309 Training_context_speed_set = 1;
7310 Training_context_speed_timestamp = timestamp();
7314 Training_context_speed_set = 0;
7317 if (Training_context & TRAINING_CONTEXT_FLY_PATH) {
7318 wplp = &Waypoint_lists[Training_context_path];
7319 if (wplp->count > Training_context_goal_waypoint) {
7320 i = Training_context_goal_waypoint;
7322 d = vm_vec_dist(&wplp->waypoints[i], &Player_obj->pos);
7323 if (d <= Training_context_distance) {
7324 Training_context_at_waypoint = i;
7325 if (Training_context_goal_waypoint == i) {
7326 Training_context_goal_waypoint++;
7327 snd_play(&Snds[SND_CARGO_REVEAL], 0.0f);
7334 if (i == wplp->count)
7337 } while (i != Training_context_goal_waypoint);
7341 if ((Players_target == UNINITIALIZED) || (Player_ai->target_objnum != Players_target) || (Player_ai->targeted_subsys != Players_targeted_subsys)) {
7342 Players_target = Player_ai->target_objnum;
7343 Players_targeted_subsys = Player_ai->targeted_subsys;
7344 Players_target_timestamp = timestamp();
7348 /////////// Following is for event debug view screen
7352 #define EVENT_DEBUG_MAX 5000
7353 #define EVENT_DEBUG_EVENT 0x8000
7355 int Event_debug_index[EVENT_DEBUG_MAX];
7358 void game_add_event_debug_index(int n, int indent)
7360 if (ED_count < EVENT_DEBUG_MAX)
7361 Event_debug_index[ED_count++] = n | (indent << 16);
7364 void game_add_event_debug_sexp(int n, int indent)
7369 if (Sexp_nodes[n].first >= 0) {
7370 game_add_event_debug_sexp(Sexp_nodes[n].first, indent);
7371 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent);
7375 game_add_event_debug_index(n, indent);
7376 if (Sexp_nodes[n].subtype == SEXP_ATOM_OPERATOR)
7377 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent + 1);
7379 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent);
7382 void game_event_debug_init()
7387 for (e=0; e<Num_mission_events; e++) {
7388 game_add_event_debug_index(e | EVENT_DEBUG_EVENT, 0);
7389 game_add_event_debug_sexp(Mission_events[e].formula, 1);
7393 void game_show_event_debug(float frametime)
7397 int font_height, font_width;
7399 static int scroll_offset = 0;
7401 k = game_check_key();
7407 if (scroll_offset < 0)
7417 scroll_offset -= 20;
7418 if (scroll_offset < 0)
7423 scroll_offset += 20; // not font-independent, hard-coded since I counted the lines!
7427 gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
7433 gr_set_color_fast(&Color_bright);
7435 gr_printf(0x8000, 5, NOX("EVENT DEBUG VIEW"));
7437 gr_set_color_fast(&Color_normal);
7439 gr_get_string_size(&font_width, &font_height, NOX("test"));
7440 y_max = gr_screen.max_h - font_height - 5;
7444 while (k < ED_count) {
7445 if (y_index > y_max)
7448 z = Event_debug_index[k];
7449 if (z & EVENT_DEBUG_EVENT) {
7451 sprintf(buf, NOX("%s%s (%s) %s%d %d"), (Mission_events[z].flags & MEF_CURRENT) ? NOX("* ") : "",
7452 Mission_events[z].name, Mission_events[z].result ? NOX("True") : NOX("False"),
7453 (Mission_events[z].chain_delay < 0) ? "" : NOX("x "),
7454 Mission_events[z].repeat_count, Mission_events[z].interval);
7462 strcat(buf, Sexp_nodes[z & 0x7fff].text);
7463 switch (Sexp_nodes[z & 0x7fff].value) {
7465 strcat(buf, NOX(" (True)"));
7469 strcat(buf, NOX(" (False)"));
7472 case SEXP_KNOWN_TRUE:
7473 strcat(buf, NOX(" (Always true)"));
7476 case SEXP_KNOWN_FALSE:
7477 strcat(buf, NOX(" (Always false)"));
7480 case SEXP_CANT_EVAL:
7481 strcat(buf, NOX(" (Can't eval)"));
7485 case SEXP_NAN_FOREVER:
7486 strcat(buf, NOX(" (Not a number)"));
7491 gr_printf(10, y_index, buf);
7492 y_index += font_height;
7506 extern int Tmap_npixels;
7509 int Tmap_num_too_big = 0;
7510 int Num_models_needing_splitting = 0;
7512 void Time_model( int modelnum )
7514 // mprintf(( "Timing ship '%s'\n", si->name ));
7516 vector eye_pos, model_pos;
7517 matrix eye_orient, model_orient;
7519 polymodel *pm = model_get( modelnum );
7521 int l = strlen(pm->filename);
7523 if ( (l == '/') || (l=='\\') || (l==':')) {
7529 char *pof_file = &pm->filename[l];
7531 int model_needs_splitting = 0;
7533 //fprintf( Texture_fp, "Model: %s\n", pof_file );
7535 for (i=0; i<pm->n_textures; i++ ) {
7536 char filename[1024];
7539 int bmp_num = pm->original_textures[i];
7540 if ( bmp_num > -1 ) {
7541 bm_get_palette(pm->original_textures[i], pal, filename );
7543 bm_get_info( pm->original_textures[i],&w, &h );
7546 if ( (w > 512) || (h > 512) ) {
7547 fprintf( Texture_fp, "%s\t%s\t%d\t%d\n", pof_file, filename, w, h );
7549 model_needs_splitting++;
7552 //fprintf( Texture_fp, "\tTexture %d is bogus\n", i );
7556 if ( model_needs_splitting ) {
7557 Num_models_needing_splitting++;
7559 eye_orient = model_orient = vmd_identity_matrix;
7560 eye_pos = model_pos = vmd_zero_vector;
7562 eye_pos.xyz.z = -pm->rad*2.0f;
7564 vector eye_to_model;
7566 vm_vec_sub( &eye_to_model, &model_pos, &eye_pos );
7567 vm_vector_2_matrix( &eye_orient, &eye_to_model, NULL, NULL );
7569 fix t1 = timer_get_fixed_seconds();
7572 ta.p = ta.b = ta.h = 0.0f;
7579 int bitmaps_used_this_frame, bitmaps_new_this_frame;
7581 bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
7583 modelstats_num_polys = modelstats_num_verts = 0;
7585 while( ta.h < PI2 ) {
7588 vm_angles_2_matrix(&m1, &ta );
7589 vm_matrix_x_matrix( &model_orient, &vmd_identity_matrix, &m1 );
7596 g3_set_view_matrix( &eye_pos, &eye_orient, Viewer_zoom );
7598 model_clear_instance( modelnum );
7599 model_set_detail_level(0); // use highest detail level
7600 model_render( modelnum, &model_orient, &model_pos, MR_LOCK_DETAIL); //|MR_NO_POLYS );
7608 int k = key_inkey();
7609 if ( k == SDLK_ESCAPE ) {
7614 fix t2 = timer_get_fixed_seconds();
7616 bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
7617 //bitmaps_used_this_frame /= framecount;
7619 modelstats_num_polys /= framecount;
7620 modelstats_num_verts /= framecount;
7623 Tmap_npixels /=framecount;
7626 mprintf(( "'%s' is %.2f FPS\n", pof_file, i2fl(framecount)/f2fl(t2-t1) ));
7628 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 );
7630 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 );
7632 // 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 );
7638 int Time_models = 0;
7639 DCF_BOOL( time_models, Time_models );
7641 void Do_model_timings_test()
7645 if ( !Time_models ) return;
7647 mprintf(( "Timing models!\n" ));
7651 ubyte model_used[MAX_POLYGON_MODELS];
7652 int model_id[MAX_POLYGON_MODELS];
7653 for (i=0; i<MAX_POLYGON_MODELS; i++ ) {
7658 for (i=0; i<Num_ship_types; i++ ) {
7659 Ship_info[i].modelnum = model_load( Ship_info[i].pof_file, 0, NULL );
7661 model_used[Ship_info[i].modelnum%MAX_POLYGON_MODELS]++;
7662 model_id[Ship_info[i].modelnum%MAX_POLYGON_MODELS] = Ship_info[i].modelnum;
7665 Texture_fp = fopen( NOX("ShipTextures.txt"), "wt" );
7666 if ( !Texture_fp ) return;
7668 Time_fp = fopen( NOX("ShipTimings.txt"), "wt" );
7669 if ( !Time_fp ) return;
7671 fprintf( Time_fp, "Name\tFPS\tTRAM\tPolys\tVerts\tPixels\n" );
7672 // fprintf( Time_fp, "FPS\tTRAM\tPolys\tVerts\tPixels\n" );
7674 for (i=0; i<MAX_POLYGON_MODELS; i++ ) {
7675 if ( model_used[i] ) {
7676 Time_model( model_id[i] );
7680 fprintf( Texture_fp, "Number too big: %d\n", Tmap_num_too_big );
7681 fprintf( Texture_fp, "Number of models needing splitting: %d\n", Num_models_needing_splitting );
7690 // Call this function when you want to inform the player that a feature is not
7691 // enabled in the DEMO version of FreSpace
7692 void game_feature_not_in_demo_popup()
7694 popup(PF_USE_AFFIRMATIVE_ICON|PF_BODY_BIG, 1, POPUP_OK, XSTR( "Sorry, this feature is available only in the retail version", 200));
7697 // format the specified time (fixed point) into a nice string
7698 void game_format_time(fix m_time,char *time_str)
7701 int hours,minutes,seconds;
7704 mtime = f2fl(m_time);
7706 // get the hours, minutes and seconds
7707 hours = (int)(mtime / 3600.0f);
7709 mtime -= (3600.0f * (float)hours);
7711 seconds = (int)mtime%60;
7712 minutes = (int)mtime/60;
7714 // print the hour if necessary
7716 sprintf(time_str,XSTR( "%d:", 201),hours);
7717 // if there are less than 10 minutes, print a leading 0
7719 strcpy(tmp,NOX("0"));
7720 strcat(time_str,tmp);
7724 // print the minutes
7726 sprintf(tmp,XSTR( "%d:", 201),minutes);
7727 strcat(time_str,tmp);
7729 sprintf(time_str,XSTR( "%d:", 201),minutes);
7732 // print the seconds
7734 strcpy(tmp,NOX("0"));
7735 strcat(time_str,tmp);
7737 sprintf(tmp,"%d",seconds);
7738 strcat(time_str,tmp);
7741 // Stuff version string in *str.
7742 void get_version_string(char *str)
7745 if ( FS_VERSION_BUILD == 0 ) {
7746 sprintf(str,"v%d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR);
7748 sprintf(str,"v%d.%02d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR, FS_VERSION_BUILD );
7751 #if defined (FS2_DEMO) || defined(FS1_DEMO)
7753 #elif defined (OEM_BUILD)
7754 strcat(str, " (OEM)");
7760 char myname[_MAX_PATH];
7761 int namelen, major, minor, build, waste;
7762 unsigned int buf_size;
7768 // Find my EXE file name
7769 hMod = GetModuleHandle(NULL);
7770 namelen = GetModuleFileName( hMod, myname, _MAX_PATH );
7772 version_size = GetFileVersionInfoSize(myname, &bogus_handle );
7773 infop = (char *)malloc(version_size);
7774 result = GetFileVersionInfo( myname, 0, version_size, (LPVOID)infop );
7776 // get the product version
7777 result = VerQueryValue((LPVOID)infop, TEXT("\\StringFileInfo\\040904b0\\ProductVersion"), &bufp, &buf_size );
7778 sscanf( (char *)bufp, "%d, %d, %d, %d", &major, &minor, &build, &waste );
7780 sprintf(str,"Dv%d.%02d",major, minor);
7782 sprintf(str,"v%d.%02d",major, minor);
7787 void get_version_string_short(char *str)
7789 sprintf(str,"v%d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR);
7792 // ----------------------------------------------------------------
7794 // OEM UPSELL SCREENS BEGIN
7796 // ----------------------------------------------------------------
7797 #if defined(OEM_BUILD)
7799 #define NUM_OEM_UPSELL_SCREENS 3
7800 #define OEM_UPSELL_SCREEN_DELAY 10000
7802 static int Oem_upsell_bitmaps_loaded = 0;
7803 static int Oem_upsell_bitmaps[GR_NUM_RESOLUTIONS][NUM_OEM_UPSELL_SCREENS];
7804 static int Oem_upsell_screen_number = 0;
7805 static int Oem_upsell_show_next_bitmap_time;
7808 static char *Oem_upsell_bitmap_filenames[GR_NUM_RESOLUTIONS][NUM_OEM_UPSELL_SCREENS] =
7821 static int Oem_normal_cursor = -1;
7822 static int Oem_web_cursor = -1;
7823 //#define OEM_UPSELL_URL "http://www.interplay-store.com/"
7824 #define OEM_UPSELL_URL "http://www.interplay.com/cgi-bin/oemlinks.pl/pid=483421&cid=18384"
7826 void oem_upsell_next_screen()
7828 Oem_upsell_screen_number++;
7829 if ( Oem_upsell_screen_number == (NUM_OEM_UPSELL_SCREENS-1) ) {
7830 // extra long delay, mouse shown on last upsell
7831 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY*2;
7835 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY;
7839 void oem_upsell_load_bitmaps()
7843 for ( i = 0; i < NUM_OEM_UPSELL_SCREENS; i++ ) {
7844 Oem_upsell_bitmaps[gr_screen.res][i] = bm_load(Oem_upsell_bitmap_filenames[gr_screen.res][i]);
7848 void oem_upsell_unload_bitmaps()
7852 for ( i = 0; i < NUM_OEM_UPSELL_SCREENS; i++ ) {
7853 if(Oem_upsell_bitmaps[gr_screen.res][i] >= 0){
7854 bm_unload(Oem_upsell_bitmaps[gr_screen.res][i]);
7859 Oem_upsell_bitmaps_loaded = 0;
7862 // clickable hotspot on 3rd OEM upsell screen
7863 static int Oem_upsell3_button_coords[GR_NUM_RESOLUTIONS][4] = {
7865 28, 350, 287, 96 // x, y, w, h
7868 45, 561, 460, 152 // x, y, w, h
7872 void oem_upsell_show_screens()
7874 int current_time, k;
7877 if ( !Oem_upsell_bitmaps_loaded ) {
7878 oem_upsell_load_bitmaps();
7879 Oem_upsell_bitmaps_loaded = 1;
7882 // may use upsell screens more than once
7883 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY;
7884 Oem_upsell_screen_number = 0;
7890 int nframes; // used to pass, not really needed (should be 1)
7891 Oem_normal_cursor = gr_get_cursor_bitmap();
7892 Oem_web_cursor = bm_load_animation("cursorweb", &nframes);
7893 SDL_assert(Oem_web_cursor >= 0);
7894 if (Oem_web_cursor < 0) {
7895 Oem_web_cursor = Oem_normal_cursor;
7900 //oem_reset_trailer_timer();
7902 current_time = timer_get_milliseconds();
7907 // advance screen on keypress or timeout
7908 if (( k > 0 ) || (mouse_up_count(MOUSE_LEFT_BUTTON) > 0) || (current_time > Oem_upsell_show_next_bitmap_time)) {
7909 oem_upsell_next_screen();
7912 // check if we are done
7913 if ( Oem_upsell_screen_number >= NUM_OEM_UPSELL_SCREENS ) {
7914 Oem_upsell_screen_number--;
7917 if ( Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number] < 0 ) {
7922 // show me the upsell
7923 if ( Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number] >= 0 ) {
7924 gr_set_bitmap(Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number]);
7928 // if this is the 3rd upsell, make it clickable, d00d
7929 if ( Oem_upsell_screen_number == NUM_OEM_UPSELL_SCREENS-1 ) {
7931 int button_state = mouse_get_pos(&mx, &my);
7932 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])
7933 && (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]) )
7936 gr_set_cursor_bitmap(Oem_web_cursor); //, GR_CURSOR_LOCK);
7939 if (button_state & MOUSE_LEFT_BUTTON) {
7941 multi_pxo_url(OEM_UPSELL_URL);
7945 // switch cursor back to normal one
7946 gr_set_cursor_bitmap(Oem_normal_cursor); //, GR_CURSOR_UNLOCK);
7951 if (gameseq_get_state() != GS_STATE_END_DEMO) {
7961 oem_upsell_unload_bitmaps();
7963 // switch cursor back to normal one
7964 gr_set_cursor_bitmap(Oem_normal_cursor); //, GR_CURSOR_UNLOCK);
7968 #endif // defined(OEM_BUILD)
7969 // ----------------------------------------------------------------
7971 // OEM UPSELL SCREENS END
7973 // ----------------------------------------------------------------
7977 // ----------------------------------------------------------------
7979 // DEMO UPSELL SCREENS BEGIN
7981 // ----------------------------------------------------------------
7983 #if defined(FS2_DEMO) || defined(FS1_DEMO)
7986 #define NUM_DEMO_UPSELL_SCREENS 2
7988 #define NUM_DEMO_UPSELL_SCREENS 4
7990 #define DEMO_UPSELL_SCREEN_DELAY 3000
7992 static int Demo_upsell_bitmaps_loaded = 0;
7993 static int Demo_upsell_bitmaps[GR_NUM_RESOLUTIONS][NUM_DEMO_UPSELL_SCREENS];
7994 static int Demo_upsell_screen_number = 0;
7995 static int Demo_upsell_show_next_bitmap_time;
7998 static char *Demo_upsell_bitmap_filenames[GR_NUM_RESOLUTIONS][NUM_DEMO_UPSELL_SCREENS] =
8024 void demo_upsell_next_screen()
8026 Demo_upsell_screen_number++;
8027 if ( Demo_upsell_screen_number == (NUM_DEMO_UPSELL_SCREENS-1) ) {
8028 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY*4;
8030 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY;
8034 if ( Demo_upsell_screen_number < NUM_DEMO_UPSELL_SCREENS ) {
8035 if ( Demo_upsell_bitmap_filenames[gr_screen.res][Demo_upsell_screen_number] >= 0 ) {
8036 #ifndef HARDWARE_ONLY
8037 palette_use_bm_palette(Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number]);
8044 void demo_upsell_load_bitmaps()
8048 for ( i = 0; i < NUM_DEMO_UPSELL_SCREENS; i++ ) {
8049 Demo_upsell_bitmaps[gr_screen.res][i] = bm_load(Demo_upsell_bitmap_filenames[gr_screen.res][i]);
8053 void demo_upsell_unload_bitmaps()
8057 for ( i = 0; i < NUM_DEMO_UPSELL_SCREENS; i++ ) {
8058 if(Demo_upsell_bitmaps[gr_screen.res][i] >= 0){
8059 bm_unload(Demo_upsell_bitmaps[gr_screen.res][i]);
8064 Demo_upsell_bitmaps_loaded = 0;
8067 void demo_upsell_show_screens()
8069 int current_time, k;
8072 if ( !Demo_upsell_bitmaps_loaded ) {
8073 demo_upsell_load_bitmaps();
8074 Demo_upsell_bitmaps_loaded = 1;
8077 // may use upsell screens more than once
8078 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY;
8079 Demo_upsell_screen_number = 0;
8086 demo_reset_trailer_timer();
8088 current_time = timer_get_milliseconds();
8095 // don't time out, wait for keypress
8097 if ( current_time > Demo_upsell_show_next_bitmap_time ) {
8098 demo_upsell_next_screen();
8103 demo_upsell_next_screen();
8106 if ( Demo_upsell_screen_number >= NUM_DEMO_UPSELL_SCREENS ) {
8107 Demo_upsell_screen_number--;
8110 if ( Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number] < 0 ) {
8115 if ( Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number] >= 0 ) {
8116 gr_set_bitmap(Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number]);
8121 if (gameseq_get_state() != GS_STATE_END_DEMO) {
8131 demo_upsell_unload_bitmaps();
8136 // ----------------------------------------------------------------
8138 // DEMO UPSELL SCREENS END
8140 // ----------------------------------------------------------------
8143 // ----------------------------------------------------------------
8145 // Subspace Ambient Sound START
8147 // ----------------------------------------------------------------
8149 static int Subspace_ambient_left_channel = -1;
8150 static int Subspace_ambient_right_channel = -1;
8153 void game_start_subspace_ambient_sound()
8155 if ( Subspace_ambient_left_channel < 0 ) {
8156 Subspace_ambient_left_channel = snd_play_looping(&Snds[SND_SUBSPACE_LEFT_CHANNEL], -1.0f);
8159 if ( Subspace_ambient_right_channel < 0 ) {
8160 Subspace_ambient_right_channel = snd_play_looping(&Snds[SND_SUBSPACE_RIGHT_CHANNEL], 1.0f);
8164 void game_stop_subspace_ambient_sound()
8166 if ( Subspace_ambient_left_channel >= 0 ) {
8167 snd_stop(Subspace_ambient_left_channel);
8168 Subspace_ambient_left_channel = -1;
8171 if ( Subspace_ambient_right_channel >= 0 ) {
8172 snd_stop(Subspace_ambient_right_channel);
8173 Subspace_ambient_right_channel = -1;
8177 // ----------------------------------------------------------------
8179 // Subspace Ambient Sound END
8181 // ----------------------------------------------------------------
8183 // ----------------------------------------------------------------
8185 // Language Autodetection stuff
8188 // this layout order must match Lcl_languages in localize.cpp in order for the
8189 // correct language to be detected
8190 int Lang_auto_detect_checksums[LCL_NUM_LANGUAGES] = {
8192 1366105450, // English
8194 589986744, // English
8196 -1132430286, // German
8198 -1131728960, // Polish
8201 // default setting is "-1" to use config file with English as fall back
8202 // DO NOT change the default setting here or something uncouth might happen
8203 // in the localization code
8209 // try and open the file to verify
8210 CFILE *detect = cfopen("font01.vf", "rb");
8212 // will use default setting if something went wrong
8217 // get the long checksum of the file
8219 cfseek(detect, 0, SEEK_SET);
8220 cf_chksum_long(detect, &file_checksum);
8224 // now compare the checksum/filesize against known #'s
8225 for (idx=0; idx<LCL_NUM_LANGUAGES; idx++) {
8226 if (Lang_auto_detect_checksums[idx] == (int)file_checksum) {
8231 // notify if a match was not found, include detected checksum
8232 printf("ERROR: Unknown Language Checksum: %i\n", (int)file_checksum);
8233 printf("Using default language...\n\n");
8239 // End Auto Lang stuff
8241 // ----------------------------------------------------------------
8243 // ----------------------------------------------------------------
8244 // SHIPS TBL VERIFICATION STUFF
8247 // checksums, just keep a list of all valid ones, if it matches any of them, keep it
8248 #if defined(MAKE_FS1) && !defined(FS1_DEMO)
8249 #define NUM_SHIPS_TBL_CHECKSUMS 3
8251 #define NUM_SHIPS_TBL_CHECKSUMS 1
8255 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8256 1696074201, // FS2 demo
8259 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8260 1603375034, // FS1 DEMO
8263 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8264 -129679197, // FS1 Full 1.06 (US)
8265 7762567, // FS1 SilentThreat
8266 1555372475 // FS1 Full 1.06 (German)
8270 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8271 -463907578, // US - beta 1
8272 1696074201, // FS2 demo
8275 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8276 // -1022810006, // 1.0 FULL
8277 -1254285366 // 1.2 FULL (German)
8281 void verify_ships_tbl()
8285 Game_ships_tbl_valid = 1;
8291 // detect if the packfile exists
8292 CFILE *detect = cfopen("ships.tbl", "rb");
8293 Game_ships_tbl_valid = 0;
8297 Game_ships_tbl_valid = 0;
8301 // get the long checksum of the file
8303 cfseek(detect, 0, SEEK_SET);
8304 cf_chksum_long(detect, &file_checksum);
8308 // now compare the checksum/filesize against known #'s
8309 for(idx=0; idx<NUM_SHIPS_TBL_CHECKSUMS; idx++){
8310 if(Game_ships_tbl_checksums[idx] == (int)file_checksum){
8311 Game_ships_tbl_valid = 1;
8318 DCF(shipspew, "display the checksum for the current ships.tbl")
8321 CFILE *detect = cfopen("ships.tbl", "rb");
8322 // get the long checksum of the file
8324 cfseek(detect, 0, SEEK_SET);
8325 cf_chksum_long(detect, &file_checksum);
8328 dc_printf("%d", file_checksum);
8331 // ----------------------------------------------------------------
8332 // WEAPONS TBL VERIFICATION STUFF
8335 // checksums, just keep a list of all valid ones, if it matches any of them, keep it
8336 #if defined(MAKE_FS1) && !defined(FS1_DEMO)
8337 #define NUM_WEAPONS_TBL_CHECKSUMS 3
8339 #define NUM_WEAPONS_TBL_CHECKSUMS 1
8343 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
8344 -266420030, // demo 1
8347 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
8348 -1246928725, // FS1 DEMO
8351 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
8352 -834598107, // FS1 1.06 Full (US)
8353 -1652231417, // FS1 SilentThreat
8354 720209793 // FS1 1.06 Full (German)
8358 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
8359 141718090, // US - beta 1
8360 -266420030, // demo 1
8363 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
8364 // 399297860, // 1.0 FULL
8365 -553984927 // 1.2 FULL (german)
8369 void verify_weapons_tbl()
8373 Game_weapons_tbl_valid = 1;
8379 // detect if the packfile exists
8380 CFILE *detect = cfopen("weapons.tbl", "rb");
8381 Game_weapons_tbl_valid = 0;
8385 Game_weapons_tbl_valid = 0;
8389 // get the long checksum of the file
8391 cfseek(detect, 0, SEEK_SET);
8392 cf_chksum_long(detect, &file_checksum);
8396 // now compare the checksum/filesize against known #'s
8397 for(idx=0; idx<NUM_WEAPONS_TBL_CHECKSUMS; idx++){
8398 if(Game_weapons_tbl_checksums[idx] == (int)file_checksum){
8399 Game_weapons_tbl_valid = 1;
8406 DCF(wepspew, "display the checksum for the current weapons.tbl")
8409 CFILE *detect = cfopen("weapons.tbl", "rb");
8410 // get the long checksum of the file
8412 cfseek(detect, 0, SEEK_SET);
8413 cf_chksum_long(detect, &file_checksum);
8416 dc_printf("%d", file_checksum);
8419 // if the game is running using hacked data
8420 int game_hacked_data()
8423 if(!Game_weapons_tbl_valid || !Game_ships_tbl_valid){
8431 void display_title_screen()
8433 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
8434 ///int title_bitmap;
8437 int title_bitmap = bm_load(Game_demo_title_screen_fname[gr_screen.res]);
8438 if (title_bitmap == -1) {
8443 gr_set_bitmap(title_bitmap);
8451 bm_unload(title_bitmap);
8452 #endif // FS2_DEMO || OEM_BUILD || FS1_DEMO
8455 // return true if the game is running with "low memory", which is less than 48MB
8456 bool game_using_low_mem()
8458 if (Use_low_mem == 0) {