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"
704 #include "supernova.h"
705 #include "hudshield.h"
706 // #include "names.h"
708 #include "missionloopbrief.h"
712 #error macro FRED is defined when trying to build release Fred. Please undefine FRED macro in build settings
718 // 1.00.04 5/26/98 MWA -- going final (12 pm)
719 // 1.00.03 5/26/98 MWA -- going final (3 am)
720 // 1.00.02 5/25/98 MWA -- going final
721 // 1.00.01 5/25/98 MWA -- going final
722 // 0.90 5/21/98 MWA -- getting ready for final.
723 // 0.10 4/9/98. Set by MK.
725 // Demo version: (obsolete since DEMO codebase split from tree)
726 // 0.03 4/10/98 AL. Interplay rev
727 // 0.02 4/8/98 MK. Increased when this system was modified.
728 // 0.01 4/7/98? AL. First release to Interplay QA.
731 // 1.00 5/28/98 AL. First release to Interplay QA.
733 void game_level_init(int seed = -1);
734 void game_post_level_init();
735 void game_do_frame();
736 void game_update_missiontime(); // called from game_do_frame() and navmap_do_frame()
737 void game_reset_time();
738 void game_show_framerate(); // draws framerate in lower right corner
740 int Game_no_clear = 0;
742 int Pofview_running = 0;
743 int Nebedit_running = 0;
744 int Fonttool_running = 0;
746 typedef struct big_expl_flash {
747 float max_flash_intensity; // max intensity
748 float cur_flash_intensity; // cur intensity
749 int flash_start; // start time
752 #define FRAME_FILTER 16
754 #define DEFAULT_SKILL_LEVEL 1
755 int Game_skill_level = DEFAULT_SKILL_LEVEL;
757 #define VIEWER_ZOOM_DEFAULT 0.75f // Default viewer zoom, 0.625 as per multi-lateral agreement on 3/24/97
758 float Viewer_zoom = VIEWER_ZOOM_DEFAULT;
760 #define EXE_FNAME ("fs2.exe")
761 #define LAUNCHER_FNAME ("freespace2.exe")
764 // JAS: Code for warphole camera.
765 // Needs to be cleaned up.
766 vector Camera_pos = ZERO_VECTOR;
767 vector Camera_velocity = ZERO_VECTOR;
768 vector Camera_desired_velocity = ZERO_VECTOR;
769 matrix Camera_orient = IDENTITY_MATRIX;
770 float Camera_damping = 1.0f;
771 float Camera_time = 0.0f;
772 float Warpout_time = 0.0f;
773 int Warpout_forced = 0; // Set if this is a forced warpout that cannot be cancelled.
774 int Warpout_sound = -1;
776 int Use_joy_mouse = 0;
777 int Use_palette_flash = 1;
778 int Show_area_effect = 0;
779 object *Last_view_target = NULL;
781 int dogfight_blown = 0;
784 float frametimes[FRAME_FILTER];
785 float frametotal = 0.0f;
789 int Show_framerate = 0;
791 int Show_framerate = 1;
794 int Framerate_cap = 120;
797 int Show_target_debug_info = 0;
798 int Show_target_weapons = 0;
802 static int Show_player_pos = 0; // debug console command to show player world pos on HUD
805 int Debug_octant = -1;
807 fix Game_time_compression = F1_0;
809 // if the ships.tbl the player has is valid
810 int Game_ships_tbl_valid = 0;
812 // if the weapons.tbl the player has is valid
813 int Game_weapons_tbl_valid = 0;
817 extern int Player_attacking_enabled;
821 int Pre_player_entry;
823 int Fred_running = 0;
824 char Game_current_mission_filename[MAX_FILENAME_LEN];
825 int game_single_step = 0;
826 int last_single_step=0;
828 extern int MSG_WINDOW_X_START; // used to position mission_time and shields output
829 extern int MSG_WINDOW_Y_START;
830 extern int MSG_WINDOW_HEIGHT;
832 int game_zbuffer = 1;
833 //static int Game_music_paused;
834 static int Game_paused;
838 #define EXPIRE_BAD_CHECKSUM 1
839 #define EXPIRE_BAD_TIME 2
841 extern void ssm_init();
842 extern void ssm_level_init();
843 extern void ssm_process();
845 // static variable to contain the time this version was built
846 // commented out for now until
847 // I figure out how to get the username into the file
848 //static char freespace_build_time[] = "Compiled on:"__DATE__" "__TIME__" by "__USER__;
850 // defines and variables used for dumping frame for making trailers.
852 int Debug_dump_frames = 0; // Set to 0 to not dump frames, else equal hz to dump. (15 or 30 probably)
853 int Debug_dump_trigger = 0;
854 int Debug_dump_frame_count;
855 int Debug_dump_frame_num = 0;
856 #define DUMP_BUFFER_NUM_FRAMES 1 // store every 15 frames
859 // amount of time to wait after the player has died before we display the death died popup
860 #define PLAYER_DIED_POPUP_WAIT 2500
861 int Player_died_popup_wait = -1;
862 time_t Player_multi_died_check = -1;
864 // builtin mission list stuff
866 int Game_builtin_mission_count = 6;
867 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
868 { "SPDemo-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
869 { "SPDemo-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
870 { "DemoTrain.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
871 { "Demo.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE) },
872 { "MPDemo-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
873 { "Demo-DOG-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
875 #elif defined(FS1_DEMO)
876 int Game_builtin_mission_count = 5;
877 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
878 { "btmdemo.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
879 { "demo.fsc", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE) },
880 { "demo01.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
881 { "demo02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
882 { "demo02b.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
884 #elif defined(PD_BUILD)
885 int Game_builtin_mission_count = 4;
886 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
887 { "sm1-01.fs2", (FSB_FROM_VOLITION) },
888 { "sm1-05.fs2", (FSB_FROM_VOLITION) },
889 { "sm1-01", (FSB_FROM_VOLITION) },
890 { "sm1-05", (FSB_FROM_VOLITION) },
892 #elif defined(MULTIPLAYER_BETA)
893 int Game_builtin_mission_count = 17;
894 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
896 { "md-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
897 { "md-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
898 { "md-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
899 { "md-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
900 { "md-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
901 { "md-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
902 { "md-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
903 { "mt-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
904 { "mt-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
905 { "m-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
906 { "m-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
907 { "m-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
908 { "templar-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
909 { "templar-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
910 { "templar-03a.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
911 { "templar-04a.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
912 { "templar.fc2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE) },
914 #elif defined(OEM_BUILD)
915 int Game_builtin_mission_count = 17;
916 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
917 // oem version - act 1 only
918 { "freespace2oem.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE) },
921 { "sm1-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
922 { "sm1-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
923 { "sm1-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
924 { "sm1-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
925 { "sm1-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
926 { "sm1-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
927 { "sm1-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
928 { "sm1-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
929 { "sm1-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
930 { "sm1-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
931 { "training-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
932 { "training-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
933 { "training-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
934 { "tsm-104.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
935 { "tsm-105.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
936 { "tsm-106.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) }
938 #elif defined(MAKE_FS1)
939 int Game_builtin_mission_count = 125;
940 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
941 // single player campaign
942 { "freespace.fsc", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE) },
945 { "sm1-01.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
946 { "sm1-02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
947 { "sm1-03a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
948 { "sm1-04a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
949 { "sm1-05a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
950 { "sm1-06a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
951 { "sm1-07a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
952 { "sm1-08a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
953 { "sm1-09a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
954 { "sm1-10a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
957 { "sm2-01a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
958 { "sm2-02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
959 { "sm2-03a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
960 { "sm2-04a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
961 { "sm2-05a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
962 { "sm2-06a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
963 { "sm2-07a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
964 { "sm2-08a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
965 { "sm2-09a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
966 { "sm2-10a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
969 { "sm3-01a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
970 { "sm3-02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
971 { "sm3-03a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
972 { "sm3-04a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
973 { "sm3-05a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
974 { "sm3-06a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
975 { "sm3-07a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
976 { "sm3-08a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
977 { "sm3-09a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
980 { "t-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
981 { "v-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
982 { "s-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
985 { "btm-01.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
986 { "btm-02.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
987 { "btm-03.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
988 { "btm-04.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
989 { "btm-05.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
992 { "m-hope.fsc", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE) },
993 { "m-altair.fsc", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE) },
995 { "m-v-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
996 { "m-va.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
997 { "m-unstoppable.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
998 { "m-t-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
999 { "m-s-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1000 { "m-rescue.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1001 { "m-pain.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1002 { "m-orecovery.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1003 { "mm3-01a.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1004 { "mm3-02a.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1005 { "mm3-03a.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1006 { "mm3-04a.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1007 { "mm3-05a.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1008 { "mm3-06a.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1009 { "m-guardduty.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1010 { "m-gate.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1011 { "m-duel.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1012 { "m-convoyassault.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1013 { "m-clash.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1015 // SilentThreat missions
1016 // Main SilentThreat campaign
1017 { "SilentThreat.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN_FILE) },
1019 { "md-01.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1020 { "md-02.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1021 { "md-03.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1022 { "md-04.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1023 { "md-05.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1024 { "md-06.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1025 { "md-07.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1026 { "md-08.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1027 { "md-09.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1028 { "md-10.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1029 { "md-11.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1030 { "md-12.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1032 // SilentThreat Part 1 - multi-coop
1033 { "ST-Part1.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE) },
1035 { "stmm-01.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1036 { "stmm-02.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1037 { "stmm-03.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1039 // SilentThreat Part 2 - multi-coop
1040 { "ST-Part2.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE) },
1042 { "stmm-04.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1043 { "stmm-05.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1044 { "stmm-06.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1046 // SilentThreat Part 3 - multi-coop
1047 { "ST-Part3.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE) },
1049 { "stmm-07.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1050 { "stmm-08.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1051 { "stmm-09.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1053 // SilentThreat Part 4 - multi-coop
1054 { "ST-Part4.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE) },
1056 { "stmm-10.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1057 { "stmm-11.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1058 { "stmm-12.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1060 // multiplayer missions
1061 { "mdmm-01.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI) },
1062 { "mdmm-02.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI) },
1063 { "mdmm-03.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI) },
1064 { "mdmm-04.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI) },
1065 // user supplied missions
1066 { "mdu-02.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1067 { "mdu-03.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1068 { "mdu-04.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1069 { "mdu-05.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1070 { "mdu-06.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1071 { "mdu-07.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1072 { "mdu-08.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1073 { "mdu-09.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1074 { "mdu-10.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1075 { "mdu-11.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1076 { "mdu-12.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1077 { "mdu-13.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1078 { "mdu-14.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1079 { "mdu-15.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1080 { "mdu-16.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1081 { "mdu-17.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1082 { "mdu-18.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1083 { "mdu-19.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1084 { "mdu-20.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1085 { "mdu-21.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1086 { "mdu-22.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1087 { "mdu-23.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1088 { "mdu-24.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1089 { "mdu-25.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1090 { "mdu-26.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1091 { "mdu-27.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1092 { "mdu-28.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1093 { "mdu-29.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1094 { "mdu-30.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1095 { "mdu-31.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1096 { "mdumm-01.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1097 { "mdumm-02.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1100 int Game_builtin_mission_count = 92;
1101 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
1102 // single player campaign
1103 { "freespace2.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE) },
1106 { "sm1-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1107 { "sm1-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1108 { "sm1-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1109 { "sm1-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1110 { "sm1-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1111 { "sm1-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1112 { "sm1-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1113 { "sm1-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1114 { "sm1-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1115 { "sm1-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1116 { "loop1-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1117 { "loop1-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1118 { "loop1-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1119 { "training-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1120 { "training-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1121 { "training-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1122 { "tsm-104.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1123 { "tsm-105.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1124 { "tsm-106.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1127 { "sm2-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1128 { "sm2-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1129 { "sm2-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1130 { "sm2-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1131 { "sm2-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1132 { "sm2-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1133 { "sm2-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1134 { "sm2-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1135 { "sm2-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1136 { "sm2-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1139 { "sm3-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1140 { "sm3-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1141 { "sm3-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1142 { "sm3-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1143 { "sm3-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1144 { "sm3-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1145 { "sm3-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1146 { "sm3-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1147 { "sm3-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1148 { "sm3-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1149 { "loop2-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1150 { "loop2-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1152 // multiplayer missions
1155 { "g-shi.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1156 { "g-ter.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1157 { "g-vas.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1160 { "m-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1161 { "m-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1162 { "m-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1163 { "m-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1166 { "mdh-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1167 { "mdh-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1168 { "mdh-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1169 { "mdh-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1170 { "mdh-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1171 { "mdh-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1172 { "mdh-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1173 { "mdh-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1174 { "mdh-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1175 { "mdl-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1176 { "mdl-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1177 { "mdl-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1178 { "mdl-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1179 { "mdl-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1180 { "mdl-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1181 { "mdl-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1182 { "mdl-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1183 { "mdl-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1184 { "mdm-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1185 { "mdm-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1186 { "mdm-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1187 { "mdm-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1188 { "mdm-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1189 { "mdm-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1190 { "mdm-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1191 { "mdm-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1192 { "mdm-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1193 { "osdog.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1196 { "mt-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1197 { "mt-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1198 { "mt-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1199 { "mt-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1200 { "mt-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1201 { "mt-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1202 { "mt-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1203 { "mt-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1204 { "mt-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1205 { "mt-10.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1208 { "templar.fc2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE) },
1209 { "templar-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
1210 { "templar-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
1211 { "templar-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
1212 { "templar-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
1217 // Internal function prototypes
1218 void game_maybe_draw_mouse(float frametime);
1219 void init_animating_pointer();
1220 void load_animating_pointer(const char *filename, int dx, int dy);
1221 void unload_animating_pointer();
1222 void game_do_training_checks();
1223 void game_shutdown(void);
1224 void game_show_event_debug(float frametime);
1225 void game_event_debug_init();
1227 void demo_upsell_show_screens();
1228 void game_start_subspace_ambient_sound();
1229 void game_stop_subspace_ambient_sound();
1230 void verify_ships_tbl();
1231 void verify_weapons_tbl();
1232 void display_title_screen();
1234 // loading background filenames
1235 static const char *Game_loading_bground_fname[GR_NUM_RESOLUTIONS] = {
1236 "LoadingBG", // GR_640
1237 "2_LoadingBG" // GR_1024
1241 static const char *Game_loading_ani_fname[GR_NUM_RESOLUTIONS] = {
1242 "Loading.ani", // GR_640
1243 "2_Loading.ani" // GR_1024
1246 #if defined(FS2_DEMO) || defined(FS1_DEMO)
1247 static const char *Game_demo_title_screen_fname[GR_NUM_RESOLUTIONS] = {
1255 #elif defined(OEM_BUILD)
1256 static const char *Game_demo_title_screen_fname[GR_NUM_RESOLUTIONS] = {
1265 // How much RAM is on this machine. Set in WinMain
1266 static int Freespace_total_ram = 0;
1269 float Game_flash_red = 0.0f;
1270 float Game_flash_green = 0.0f;
1271 float Game_flash_blue = 0.0f;
1272 float Sun_spot = 0.0f;
1273 big_expl_flash Big_expl_flash = {0.0f, 0.0f, 0};
1275 // game shudder stuff (in ms)
1276 int Game_shudder_time = -1;
1277 int Game_shudder_total = 0;
1278 float Game_shudder_intensity = 0.0f; // should be between 0.0 and 100.0
1281 sound_env Game_sound_env;
1282 //sound_env Game_default_sound_env = {SND_ENV_AUDITORIUM, 0.25f, 0.35f, 3.0f};
1283 sound_env Game_default_sound_env = {SND_ENV_GENERIC, 0.2F,0.2F,1.0F};
1285 int Game_sound_env_update_timestamp;
1287 // WARPIN CRAP BEGIN --------------------------------------------------------------------------------------------
1290 // WARPIN CRAP END --------------------------------------------------------------------------------------------
1292 fs_builtin_mission *game_find_builtin_mission(const char *filename)
1296 // look through all existing builtin missions
1297 for(idx=0; idx<Game_builtin_mission_count; idx++){
1298 if(!SDL_strcasecmp(Game_builtin_mission_list[idx].filename, filename)){
1299 return &Game_builtin_mission_list[idx];
1307 int game_get_default_skill_level()
1309 return DEFAULT_SKILL_LEVEL;
1313 void game_flash_reset()
1315 Game_flash_red = 0.0f;
1316 Game_flash_green = 0.0f;
1317 Game_flash_blue = 0.0f;
1319 Big_expl_flash.max_flash_intensity = 0.0f;
1320 Big_expl_flash.cur_flash_intensity = 0.0f;
1321 Big_expl_flash.flash_start = 0;
1324 float Gf_critical = -1.0f; // framerate we should be above on the average for this mission
1325 float Gf_critical_time = 0.0f; // how much time we've been at the critical framerate
1327 void game_framerate_check_init()
1329 // zero critical time
1330 Gf_critical_time = 0.0f;
1333 if(The_mission.flags & MISSION_FLAG_FULLNEB){
1334 Gf_critical = 15.0f;
1336 Gf_critical = 25.0f;
1340 extern float Framerate;
1341 void game_framerate_check()
1345 // if the current framerate is above the critical level, add frametime
1346 if(Framerate >= Gf_critical){
1347 Gf_critical_time += flFrametime;
1350 if(!Show_framerate){
1354 // display if we're above the critical framerate
1355 if(Framerate < Gf_critical){
1356 gr_set_color_fast(&Color_bright_red);
1357 gr_string(200, y_start, "Framerate warning");
1362 // display our current pct of good frametime
1363 if(f2fl(Missiontime) >= 0.0f){
1364 float pct = (Gf_critical_time / f2fl(Missiontime)) * 100.0f;
1367 gr_set_color_fast(&Color_bright_green);
1369 gr_set_color_fast(&Color_bright_red);
1372 gr_printf(200, y_start, "%d%%", (int)pct);
1377 // Adds a flash effect. These can be positive or negative.
1378 // The range will get capped at around -1 to 1, so stick
1379 // with a range like that.
1380 void game_flash( float r, float g, float b )
1382 Game_flash_red += r;
1383 Game_flash_green += g;
1384 Game_flash_blue += b;
1386 if ( Game_flash_red < -1.0f ) {
1387 Game_flash_red = -1.0f;
1388 } else if ( Game_flash_red > 1.0f ) {
1389 Game_flash_red = 1.0f;
1392 if ( Game_flash_green < -1.0f ) {
1393 Game_flash_green = -1.0f;
1394 } else if ( Game_flash_green > 1.0f ) {
1395 Game_flash_green = 1.0f;
1398 if ( Game_flash_blue < -1.0f ) {
1399 Game_flash_blue = -1.0f;
1400 } else if ( Game_flash_blue > 1.0f ) {
1401 Game_flash_blue = 1.0f;
1406 // Adds a flash for Big Ship explosions
1407 // cap range from 0 to 1
1408 void big_explosion_flash(float flash)
1410 Big_expl_flash.flash_start = timestamp(1);
1414 } else if (flash < 0.0f) {
1418 Big_expl_flash.max_flash_intensity = flash;
1419 Big_expl_flash.cur_flash_intensity = 0.0f;
1422 // Amount to diminish palette towards normal, per second.
1423 #define DIMINISH_RATE 0.75f
1424 #define SUN_DIMINISH_RATE 6.00f
1428 float sn_glare_scale = 1.7f;
1431 dc_get_arg(ARG_FLOAT);
1432 sn_glare_scale = Dc_arg_float;
1435 float Supernova_last_glare = 0.0f;
1436 void game_sunspot_process(float frametime)
1440 float Sun_spot_goal = 0.0f;
1443 sn_stage = supernova_active();
1445 // sunspot differently based on supernova stage
1447 // approaching. player still in control
1450 pct = (1.0f - (supernova_time_left() / SUPERNOVA_CUT_TIME));
1453 light_get_global_dir(&light_dir, 0);
1455 dot = vm_vec_dot( &light_dir, &Eye_matrix.v.fvec );
1458 // scale it some more
1459 dot = dot * (0.5f + (pct * 0.5f));
1462 Sun_spot_goal += (dot * sn_glare_scale);
1465 // draw the sun glow
1466 if ( !shipfx_eye_in_shadow( &Eye_position, Viewer_obj, 0 ) ) {
1467 // draw the glow for this sun
1468 stars_draw_sun_glow(0);
1471 Supernova_last_glare = Sun_spot_goal;
1474 // camera cut. player not in control. note : at this point camera starts out facing the sun. so we can go nice and bright
1477 Sun_spot_goal = 0.9f;
1478 Sun_spot_goal += (1.0f - (supernova_time_left() / SUPERNOVA_CUT_TIME)) * 0.1f;
1480 if(Sun_spot_goal > 1.0f){
1481 Sun_spot_goal = 1.0f;
1484 Sun_spot_goal *= sn_glare_scale;
1485 Supernova_last_glare = Sun_spot_goal;
1488 // fade to white. display dead popup
1491 Supernova_last_glare += (2.0f * flFrametime);
1492 if(Supernova_last_glare > 2.0f){
1493 Supernova_last_glare = 2.0f;
1496 Sun_spot_goal = Supernova_last_glare;
1503 // check sunspots for all suns
1504 n_lights = light_get_global_count();
1507 for(idx=0; idx<n_lights; idx++){
1508 //(vector *eye_pos, matrix *eye_orient)
1509 if ( !shipfx_eye_in_shadow( &Eye_position, Viewer_obj, idx ) ) {
1512 light_get_global_dir(&light_dir, idx);
1514 float dot = vm_vec_dot( &light_dir, &Eye_matrix.v.fvec )*0.5f+0.5f;
1516 Sun_spot_goal += (float)pow(dot,85.0f);
1518 // draw the glow for this sun
1519 stars_draw_sun_glow(idx);
1521 Sun_spot_goal = 0.0f;
1527 Sun_spot_goal = 0.0f;
1531 float dec_amount = frametime*SUN_DIMINISH_RATE;
1533 if ( Sun_spot < Sun_spot_goal ) {
1534 Sun_spot += dec_amount;
1535 if ( Sun_spot > Sun_spot_goal ) {
1536 Sun_spot = Sun_spot_goal;
1538 } else if ( Sun_spot > Sun_spot_goal ) {
1539 Sun_spot -= dec_amount;
1540 if ( Sun_spot < Sun_spot_goal ) {
1541 Sun_spot = Sun_spot_goal;
1547 // Call once a frame to diminish the
1548 // flash effect to 0.
1549 void game_flash_diminish(float frametime)
1551 float dec_amount = frametime*DIMINISH_RATE;
1553 if ( Game_flash_red > 0.0f ) {
1554 Game_flash_red -= dec_amount;
1555 if ( Game_flash_red < 0.0f )
1556 Game_flash_red = 0.0f;
1558 Game_flash_red += dec_amount;
1559 if ( Game_flash_red > 0.0f )
1560 Game_flash_red = 0.0f;
1563 if ( Game_flash_green > 0.0f ) {
1564 Game_flash_green -= dec_amount;
1565 if ( Game_flash_green < 0.0f )
1566 Game_flash_green = 0.0f;
1568 Game_flash_green += dec_amount;
1569 if ( Game_flash_green > 0.0f )
1570 Game_flash_green = 0.0f;
1573 if ( Game_flash_blue > 0.0f ) {
1574 Game_flash_blue -= dec_amount;
1575 if ( Game_flash_blue < 0.0f )
1576 Game_flash_blue = 0.0f;
1578 Game_flash_blue += dec_amount;
1579 if ( Game_flash_blue > 0.0f )
1580 Game_flash_blue = 0.0f;
1583 // update big_explosion_cur_flash
1584 #define TIME_UP 1500
1585 #define TIME_DOWN 2500
1586 int duration = TIME_UP + TIME_DOWN;
1587 int time = timestamp_until(Big_expl_flash.flash_start);
1588 if (time > -duration) {
1590 if (time < TIME_UP) {
1591 Big_expl_flash.cur_flash_intensity = Big_expl_flash.max_flash_intensity * time / (float) TIME_UP;
1594 Big_expl_flash.cur_flash_intensity = Big_expl_flash.max_flash_intensity * ((float) TIME_DOWN - time) / (float) TIME_DOWN;
1598 if ( Use_palette_flash ) {
1600 // static int or=0, og=0, ob=0;
1602 // Change the 200 to change the color range of colors.
1603 r = fl2i( Game_flash_red*128.0f );
1604 g = fl2i( Game_flash_green*128.0f );
1605 b = fl2i( Game_flash_blue*128.0f );
1607 if ( Sun_spot > 0.0f ) {
1608 r += fl2i(Sun_spot*128.0f);
1609 g += fl2i(Sun_spot*128.0f);
1610 b += fl2i(Sun_spot*128.0f);
1613 if ( Big_expl_flash.cur_flash_intensity > 0.0f ) {
1614 r += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1615 g += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1616 b += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1619 if ( r < 0 ) r = 0; else if ( r > 255 ) r = 255;
1620 if ( g < 0 ) g = 0; else if ( g > 255 ) g = 255;
1621 if ( b < 0 ) b = 0; else if ( b > 255 ) b = 255;
1623 if ( (r!=0) || (g!=0) || (b!=0) ) {
1624 gr_flash( r, g, b );
1626 //mprintf(( "Flash! %d,%d,%d\n", r, g, b ));
1637 void game_level_close()
1639 // De-Initialize the game subsystems
1640 event_music_level_close();
1641 game_stop_looped_sounds();
1643 obj_snd_level_close(); // uninit object-linked persistant sounds
1644 gamesnd_unload_gameplay_sounds(); // unload gameplay sounds from memory
1645 anim_level_close(); // stop and clean up any anim instances
1646 message_mission_shutdown(); // called after anim_level_close() to make sure anim instances are free
1647 shockwave_level_close();
1648 fireball_level_close();
1650 mission_event_shutdown();
1651 asteroid_level_close();
1652 flak_level_close(); // unload flak stuff
1653 neb2_level_close(); // shutdown gaseous nebula stuff
1656 mflash_level_close();
1657 mission_brief_common_reset(); // close out parsed briefing/mission stuff
1659 audiostream_unpause_all();
1664 // intializes game stuff and loads the mission. Returns 0 on failure, 1 on success
1665 // input: seed => DEFAULT PARAMETER (value -1). Only set by demo playback code.
1666 void game_level_init(int seed)
1668 // seed the random number generator
1670 // if no seed was passed, seed the generator either from the time value, or from the
1671 // netgame security flags -- ensures that all players in multiplayer game will have the
1672 // same randon number sequence (with static rand functions)
1673 if ( Game_mode & GM_NORMAL ) {
1674 Game_level_seed = (int)time(NULL);
1676 Game_level_seed = Netgame.security;
1679 // mwa 9/17/98 -- maybe this assert isn't needed????
1680 SDL_assert( !(Game_mode & GM_MULTIPLAYER) );
1681 Game_level_seed = seed;
1683 srand( Game_level_seed );
1685 // semirand function needs to get re-initted every time in multiplayer
1686 if ( Game_mode & GM_MULTIPLAYER ){
1692 Key_normal_game = (Game_mode & GM_NORMAL);
1695 Game_shudder_time = -1;
1697 // Initialize the game subsystems
1698 // timestamp_reset(); // Must be inited before everything else
1700 game_reset_time(); // resets time, and resets saved time too
1702 obj_init(); // Must be inited before the other systems
1703 model_free_all(); // Free all existing models
1704 mission_brief_common_init(); // Free all existing briefing/debriefing text
1705 weapon_level_init();
1706 ai_level_init(); // Call this before ship_init() because it reads ai.tbl.
1708 player_level_init();
1709 shipfx_flash_init(); // Init the ship gun flash system.
1710 game_flash_reset(); // Reset the flash effect
1711 particle_init(); // Reset the particle system
1715 shield_hit_init(); // Initialize system for showing shield hits
1716 radar_mission_init();
1717 mission_init_goals();
1720 obj_snd_level_init(); // init object-linked persistant sounds
1722 shockwave_level_init();
1723 afterburner_level_init();
1724 scoring_level_init( &Player->stats );
1726 asteroid_level_init();
1727 control_config_clear_used_status();
1728 collide_ship_ship_sounds_init();
1730 Pre_player_entry = 1; // Means the player has not yet entered.
1731 Entry_delay_time = 0; // Could get overwritten in mission read.
1732 fireball_preload(); // page in warphole bitmaps
1734 flak_level_init(); // initialize flak - bitmaps, etc
1735 ct_level_init(); // initialize ships contrails, etc
1736 awacs_level_init(); // initialize AWACS
1737 beam_level_init(); // initialize beam weapons
1738 mflash_level_init();
1740 supernova_level_init();
1742 // multiplayer dogfight hack
1745 shipfx_engine_wash_level_init();
1749 Last_view_target = NULL;
1754 // campaign wasn't ended
1755 Campaign_ended_in_mission = 0;
1758 // called when a mission is over -- does server specific stuff.
1759 void freespace_stop_mission()
1762 Game_mode &= ~GM_IN_MISSION;
1765 // called at frame interval to process networking stuff
1766 void game_do_networking()
1768 SDL_assert( Net_player != NULL );
1769 if (!(Game_mode & GM_MULTIPLAYER)){
1773 // see if this player should be reading/writing data. Bit is set when at join
1774 // screen onward until quits back to main menu.
1775 if ( !(Net_player->flags & NETINFO_FLAG_DO_NETWORKING) ){
1779 if(gameseq_get_state()!=GS_STATE_MULTI_PAUSED){
1782 multi_pause_do_frame();
1787 // Loads the best palette for this level, based
1788 // on nebula color and hud color. You could just call palette_load_table with
1789 // the appropriate filename, but who wants to do that.
1790 void game_load_palette()
1792 char palette_filename[1024];
1794 // We only use 3 hud colors right now
1796 SDL_assert( HUD_config.main_color >= 0 );
1797 SDL_assert( HUD_config.main_color <= 2 );
1800 SDL_assert( Mission_palette >= 0 );
1801 SDL_assert( Mission_palette <= 98 );
1804 if ( The_mission.flags & MISSION_FLAG_SUBSPACE ) {
1805 SDL_strlcpy( palette_filename, NOX("gamepalette-subspace"), sizeof(palette_filename) );
1807 SDL_snprintf( palette_filename, sizeof(palette_filename), NOX("gamepalette%d-%02d"), HUD_config.main_color+1, Mission_palette+1 );
1810 mprintf(( "Loading palette %s\n", palette_filename ));
1812 palette_load_table(palette_filename);
1814 SDL_strlcpy( palette_filename, NOX("gamepalette-subspace"), sizeof(palette_filename) );
1816 mprintf(( "Loading palette %s\n", palette_filename ));
1820 void game_post_level_init()
1822 // Stuff which gets called after mission is loaded. Because player isn't created until
1823 // after mission loads, some things must get initted after the level loads
1825 model_level_post_init();
1828 hud_setup_escort_list();
1829 mission_hotkey_set_defaults(); // set up the default hotkeys (from mission file)
1835 game_event_debug_init();
1838 training_mission_init();
1839 asteroid_create_all();
1841 game_framerate_check_init();
1845 // An estimate as to how high the count passed to game_loading_callback will go.
1846 // This is just a guess, it seems to always be about the same. The count is
1847 // proportional to the code being executed, not the time, so this works good
1848 // for a bar, assuming the code does about the same thing each time you
1849 // load a level. You can find this value by looking at the return value
1850 // of game_busy_callback(NULL), which I conveniently print out to the
1851 // debug output window with the '=== ENDING LOAD ==' stuff.
1852 //#define COUNT_ESTIMATE 3706
1853 #define COUNT_ESTIMATE 1111
1855 int Game_loading_callback_inited = 0;
1857 int Game_loading_background = -1;
1858 anim * Game_loading_ani = NULL;
1859 anim_instance *Game_loading_ani_instance;
1860 int Game_loading_frame=-1;
1862 static int Game_loading_ani_coords[GR_NUM_RESOLUTIONS][2] = {
1864 #if defined(FS1_DEMO)
1866 #elif defined(MAKE_FS1)
1877 // This gets called 10x per second and count is the number of times
1878 // game_busy() has been called since the current callback function
1880 void game_loading_callback(int count)
1882 game_do_networking();
1884 SDL_assert( Game_loading_callback_inited==1 );
1885 SDL_assert( Game_loading_ani != NULL );
1887 int framenum = ((Game_loading_ani->total_frames*count) / COUNT_ESTIMATE)+1;
1888 if ( framenum > Game_loading_ani->total_frames-1 ) {
1889 framenum = Game_loading_ani->total_frames-1;
1890 } else if ( framenum < 0 ) {
1895 while ( Game_loading_frame < framenum ) {
1896 Game_loading_frame++;
1897 cbitmap = anim_get_next_frame(Game_loading_ani_instance);
1901 if ( cbitmap > -1 ) {
1902 if ( Game_loading_background > -1 ) {
1903 gr_set_bitmap( Game_loading_background, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1907 //mprintf(( "Showing frame %d/%d [ Bitmap=%d ]\n", Game_loading_frame , Game_loading_ani->total_frames, cbitmap ));
1908 gr_set_bitmap( cbitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1909 gr_bitmap(Game_loading_ani_coords[gr_screen.res][0],Game_loading_ani_coords[gr_screen.res][1]);
1911 bm_release(cbitmap);
1917 void game_loading_callback_init()
1919 SDL_assert( Game_loading_callback_inited==0 );
1921 Game_loading_background = bm_load(Game_loading_bground_fname[gr_screen.res]);
1923 common_set_interface_palette("InterfacePalette"); // set the interface palette
1927 Game_loading_ani = anim_load( Game_loading_ani_fname[gr_screen.res]);
1928 SDL_assert( Game_loading_ani != NULL );
1929 Game_loading_ani_instance = init_anim_instance(Game_loading_ani, 16);
1930 SDL_assert( Game_loading_ani_instance != NULL );
1931 Game_loading_frame = -1;
1933 Game_loading_callback_inited = 1;
1935 game_busy_callback( game_loading_callback, (COUNT_ESTIMATE/Game_loading_ani->total_frames)+1 );
1940 void game_loading_callback_close()
1942 SDL_assert( Game_loading_callback_inited==1 );
1944 // Make sure bar shows all the way over.
1945 game_loading_callback(COUNT_ESTIMATE);
1947 int real_count = game_busy_callback( NULL );
1950 Game_loading_callback_inited = 0;
1953 mprintf(( "=================== ENDING LOAD ================\n" ));
1954 mprintf(( "Real count = %d, Estimated count = %d\n", real_count, COUNT_ESTIMATE ));
1955 mprintf(( "================================================\n" ));
1957 // to remove warnings in release build
1961 free_anim_instance(Game_loading_ani_instance);
1962 Game_loading_ani_instance = NULL;
1963 anim_free(Game_loading_ani);
1964 Game_loading_ani = NULL;
1966 bm_release( Game_loading_background );
1967 common_free_interface_palette(); // restore game palette
1968 Game_loading_background = -1;
1970 gr_set_font( FONT1 );
1973 // Update the sound environment (ie change EAX settings based on proximity to large ships)
1975 void game_maybe_update_sound_environment()
1977 // do nothing for now
1980 // Assign the sound environment for the game, based on the current mission
1982 void game_assign_sound_environment()
1985 if (The_mission.flags & MISSION_FLAG_SUBSPACE) {
1986 Game_sound_env.id = SND_ENV_DRUGGED;
1987 Game_sound_env.volume = 0.800f;
1988 Game_sound_env.damping = 1.188f;
1989 Game_sound_env.decay = 6.392f;
1991 } else if (Num_asteroids > 30) {
1992 Game_sound_env.id = SND_ENV_AUDITORIUM;
1993 Game_sound_env.volume = 0.603f;
1994 Game_sound_env.damping = 0.5f;
1995 Game_sound_env.decay = 4.279f;
1998 Game_sound_env = Game_default_sound_env;
2002 Game_sound_env = Game_default_sound_env;
2003 Game_sound_env_update_timestamp = timestamp(1);
2006 // function which gets called before actually entering the mission. It is broken down into a funciton
2007 // since it will get called in one place from a single player game and from another place for
2008 // a multiplayer game
2009 void freespace_mission_load_stuff()
2011 // called if we're not on a freespace dedicated (non rendering, no pilot) server
2012 // IE : we _don't_ want to load any sounds or bitmap/texture info on this machine.
2013 if(!(Game_mode & GM_STANDALONE_SERVER)){
2015 mprintf(( "=================== STARTING LEVEL DATA LOAD ==================\n" ));
2017 game_loading_callback_init();
2019 event_music_level_init(); // preloads the first 2 seconds for each event music track
2022 gamesnd_unload_interface_sounds(); // unload interface sounds from memory
2025 gamesnd_preload_common_sounds(); // load in sounds that are expected to play
2028 ship_assign_sound_all(); // assign engine sounds to ships
2029 game_assign_sound_environment(); // assign the sound environment for this mission
2032 // call function in missionparse.cpp to fixup player/ai stuff.
2033 mission_parse_fixup_players();
2036 // Load in all the bitmaps for this level
2041 game_loading_callback_close();
2043 // the only thing we need to call on the standalone for now.
2045 // call function in missionparse.cpp to fixup player/ai stuff.
2046 mission_parse_fixup_players();
2048 // Load in all the bitmaps for this level
2053 time_t load_gl_init;
2054 time_t load_mission_load;
2055 time_t load_post_level_init;
2056 time_t load_mission_stuff;
2058 // tells the server to load the mission and initialize structures
2059 int game_start_mission()
2061 mprintf(( "=================== STARTING LEVEL LOAD ==================\n" ));
2063 load_gl_init = time(NULL);
2065 load_gl_init = time(NULL) - load_gl_init;
2067 if (Game_mode & GM_MULTIPLAYER) {
2068 Player->flags |= PLAYER_FLAGS_IS_MULTI;
2070 // clear multiplayer stats
2071 init_multiplayer_stats();
2074 load_mission_load = time(NULL);
2075 if (mission_load()) {
2076 if ( !(Game_mode & GM_MULTIPLAYER) ) {
2077 popup(PF_BODY_BIG, 1, POPUP_OK, XSTR( "Attempt to load the mission failed", 169));
2078 gameseq_post_event(GS_EVENT_MAIN_MENU);
2080 multi_quit_game(PROMPT_NONE, MULTI_END_NOTIFY_NONE, MULTI_END_ERROR_LOAD_FAIL);
2085 load_mission_load = time(NULL) - load_mission_load;
2087 // If this is a red alert mission in campaign mode, bash wingman status
2088 if ( (Game_mode & GM_CAMPAIGN_MODE) && red_alert_mission() ) {
2089 red_alert_bash_wingman_status();
2092 // the standalone server in multiplayer doesn't do any rendering, so we will not even bother loading the palette
2093 if ( !(Game_mode & GM_STANDALONE_SERVER) ) {
2094 mprintf(( "=================== LOADING GAME PALETTE ================\n" ));
2096 game_load_palette();
2100 load_post_level_init = time(NULL);
2101 game_post_level_init();
2102 load_post_level_init = time(NULL) - load_post_level_init;
2106 void Do_model_timings_test();
2107 Do_model_timings_test();
2111 load_mission_stuff = time(NULL);
2112 freespace_mission_load_stuff();
2113 load_mission_stuff = time(NULL) - load_mission_stuff;
2118 int Interface_framerate = 0;
2121 DCF_BOOL( mouse_control, Use_mouse_to_fly )
2122 DCF_BOOL( show_framerate, Show_framerate )
2123 DCF_BOOL( show_target_debug_info, Show_target_debug_info )
2124 DCF_BOOL( show_target_weapons, Show_target_weapons )
2125 DCF_BOOL( lead_target_cheat, Players[Player_num].lead_target_cheat )
2126 DCF_BOOL( sound, Sound_enabled )
2127 DCF_BOOL( zbuffer, game_zbuffer )
2128 DCF_BOOL( shield_system, New_shield_system )
2129 DCF_BOOL( show_shield_mesh, Show_shield_mesh)
2130 DCF_BOOL( player_attacking, Player_attacking_enabled )
2131 DCF_BOOL( show_waypoints, Show_waypoints )
2132 DCF_BOOL( show_area_effect, Show_area_effect )
2133 DCF_BOOL( show_net_stats, Show_net_stats )
2134 DCF_BOOL( log, Log_debug_output_to_file )
2135 DCF_BOOL( training_msg_method, Training_msg_method )
2136 DCF_BOOL( show_player_pos, Show_player_pos )
2137 DCF_BOOL(i_framerate, Interface_framerate )
2139 DCF(show_mem,"Toggles showing mem usage")
2142 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2143 if ( Dc_arg_type & ARG_TRUE ) Show_mem = 1;
2144 else if ( Dc_arg_type & ARG_FALSE ) Show_mem = 0;
2145 else if ( Dc_arg_type & ARG_NONE ) Show_mem ^= 1;
2151 if ( Dc_help ) dc_printf( "Usage: Show_mem\nSets show_mem to true or false. If nothing passed, then toggles it.\n" );
2153 dc_printf( "Show_mem is %s\n", (Show_mem?"TRUE":"FALSE") );
2154 dc_printf( "Show_cpu is %s\n", (Show_cpu?"TRUE":"FALSE") );
2158 DCF(show_cpu,"Toggles showing cpu usage")
2161 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2162 if ( Dc_arg_type & ARG_TRUE ) Show_cpu = 1;
2163 else if ( Dc_arg_type & ARG_FALSE ) Show_cpu = 0;
2164 else if ( Dc_arg_type & ARG_NONE ) Show_cpu ^= 1;
2170 if ( Dc_help ) dc_printf( "Usage: Show_cpu\nSets show_cpu to true or false. If nothing passed, then toggles it.\n" );
2172 dc_printf( "Show_mem is %s\n", (Show_mem?"TRUE":"FALSE") );
2173 dc_printf( "Show_cpu is %s\n", (Show_cpu?"TRUE":"FALSE") );
2180 // AL 4-8-98: always allow players to display their framerate
2183 DCF_BOOL( show_framerate, Show_framerate )
2190 DCF(use_joy_mouse,"Makes joystick move mouse cursor")
2193 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2194 if ( Dc_arg_type & ARG_TRUE ) Use_joy_mouse = 1;
2195 else if ( Dc_arg_type & ARG_FALSE ) Use_joy_mouse = 0;
2196 else if ( Dc_arg_type & ARG_NONE ) Use_joy_mouse ^= 1;
2198 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" );
2199 if ( Dc_status ) dc_printf( "use_joy_mouse is %s\n", (Use_joy_mouse?"TRUE":"FALSE") );
2201 os_config_write_uint( NULL, NOX("JoystickMovesCursor"), Use_joy_mouse );
2204 DCF(palette_flash,"Toggles palette flash effect on/off")
2207 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2208 if ( Dc_arg_type & ARG_TRUE ) Use_palette_flash = 1;
2209 else if ( Dc_arg_type & ARG_FALSE ) Use_palette_flash = 0;
2210 else if ( Dc_arg_type & ARG_NONE ) Use_palette_flash ^= 1;
2212 if ( Dc_help ) dc_printf( "Usage: palette_flash [bool]\nSets palette_flash to true or false. If nothing passed, then toggles it.\n" );
2213 if ( Dc_status ) dc_printf( "palette_flash is %s\n", (Use_palette_flash?"TRUE":"FALSE") );
2216 int Use_low_mem = 0;
2218 DCF(low_mem,"Uses low memory settings regardless of RAM")
2221 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2222 if ( Dc_arg_type & ARG_TRUE ) Use_low_mem = 1;
2223 else if ( Dc_arg_type & ARG_FALSE ) Use_low_mem = 0;
2224 else if ( Dc_arg_type & ARG_NONE ) Use_low_mem ^= 1;
2226 if ( Dc_help ) dc_printf( "Usage: low_mem [bool]\nSets low_mem to true or false. If nothing passed, then toggles it.\n" );
2227 if ( Dc_status ) dc_printf( "low_mem is %s\n", (Use_low_mem?"TRUE":"FALSE") );
2229 os_config_write_uint( NULL, NOX("LowMem"), Use_low_mem );
2233 int Framerate_delay = 0;
2235 float Freespace_gamma = 1.8f;
2237 DCF(gamma,"Sets Gamma factor")
2240 dc_get_arg(ARG_FLOAT|ARG_NONE);
2241 if ( Dc_arg_type & ARG_FLOAT ) {
2242 Freespace_gamma = Dc_arg_float;
2244 dc_printf( "Gamma reset to 1.0f\n" );
2245 Freespace_gamma = 1.0f;
2247 if ( Freespace_gamma < 0.1f ) {
2248 Freespace_gamma = 0.1f;
2249 } else if ( Freespace_gamma > 5.0f ) {
2250 Freespace_gamma = 5.0f;
2252 gr_set_gamma(Freespace_gamma);
2254 char tmp_gamma_string[32];
2255 SDL_snprintf( tmp_gamma_string, sizeof(tmp_gamma_string), NOX("%.2f"), Freespace_gamma );
2256 os_config_write_string( NULL, NOX("Gamma"), tmp_gamma_string );
2260 dc_printf( "Usage: gamma <float>\n" );
2261 dc_printf( "Sets gamma in range 1-3, no argument resets to default 1.2\n" );
2262 Dc_status = 0; // don't print status if help is printed. Too messy.
2266 dc_printf( "Gamma = %.2f\n", Freespace_gamma );
2272 Game_current_mission_filename[0] = 0;
2274 // seed the random number generator
2275 Game_init_seed = (int)time(NULL);
2276 srand( Game_init_seed );
2278 Framerate_delay = 0;
2284 extern void bm_init();
2290 // Initialize the timer before the os
2296 //Initialize the libraries
2297 s1 = timer_get_milliseconds();
2298 if ( cfile_init() ) { // initialize before calling any cfopen stuff!!!
2301 e1 = timer_get_milliseconds();
2303 // time a bunch of cfopens
2305 s2 = timer_get_milliseconds();
2307 for(int idx=0; idx<10000; idx++){
2308 whee = cfopen("capital01.pof", "rb", CFILE_NORMAL, CF_TYPE_MODELS);
2313 //cf_exist("capital01.pof", CF_TYPE_MODELS);
2315 e2 = timer_get_milliseconds();
2318 if (Is_standalone) {
2319 std_init_standalone();
2321 os_init( Osreg_class_name, Osreg_app_name );
2322 os_set_title(Osreg_title);
2325 // initialize localization module. Make sure this is down AFTER initialzing OS.
2326 // int t1 = timer_get_milliseconds();
2327 lcl_init( detect_lang() );
2329 // mprintf(("LCL_INIT() TOOK %d MS\n", timer_get_milliseconds()-t1));
2331 // verify that he has a valid ships.tbl (will Game_ships_tbl_valid if so)
2334 // verify that he has a valid weapons.tbl
2335 verify_weapons_tbl();
2337 // Output version numbers to registry for auto patching purposes
2338 os_config_write_uint(NOX("Version"), NOX("Major"), FS_VERSION_MAJOR);
2339 os_config_write_uint(NOX("Version"), NOX("Minor"), FS_VERSION_MINOR);
2340 os_config_write_uint(NOX("Version"), NOX("Build"), FS_VERSION_BUILD);
2342 Use_joy_mouse = 0; //os_config_read_uint( NULL, NOX("JoystickMovesCursor"), 1 );
2343 //Use_palette_flash = os_config_read_uint( NULL, NOX("PaletteFlash"), 0 );
2344 Use_low_mem = os_config_read_uint( NULL, NOX("LowMem"), 0 );
2346 // show the FPS counter if the config file says so
2347 Show_framerate = os_config_read_uint( "Video", "ShowFPS", Show_framerate );
2349 #if !(defined(FS2_DEMO) || defined(FS1_DEMO))
2350 Asteroids_enabled = 1;
2353 /////////////////////////////
2355 /////////////////////////////
2357 if (!Is_standalone) {
2361 /////////////////////////////
2363 /////////////////////////////
2365 if ( !Is_standalone ) {
2373 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
2376 display_title_screen();
2380 // If less than 48MB of RAM, use low memory model.
2381 if ( (Freespace_total_ram < 48) || Use_low_mem ) {
2382 mprintf(( "Using normal memory settings...\n" ));
2383 bm_set_low_mem(1); // Use every other frame of bitmaps
2385 mprintf(( "Using high memory settings...\n" ));
2386 bm_set_low_mem(0); // Use all frames of bitmaps
2389 // load non-darkening pixel defs
2390 palman_load_pixels();
2392 // hud shield icon stuff
2393 hud_shield_game_init();
2395 control_config_common_init(); // sets up localization stuff in the control config
2401 gamesnd_parse_soundstbl();
2406 // standalone's don't use hte joystick and it seems to sometimes cause them to not get shutdown properly
2411 player_controls_init();
2414 //if(!Is_standalone){
2422 ship_init(); // read in ships.tbl
2424 mission_campaign_init(); // load in the default campaign
2426 // navmap_init(); // init the navigation map system
2427 context_help_init();
2428 techroom_intel_init(); // parse species.tbl, load intel info
2430 psnet_init( Multi_options_g.protocol, Multi_options_g.port ); // initialize the networking code
2431 init_animating_pointer();
2433 mission_brief_common_init(); // Mark all the briefing structures as empty.
2434 gr_font_init(); // loads up all fonts
2436 neb2_init(); // fullneb stuff
2440 player_tips_init(); // helpful tips
2443 // load the list of pilot pic filenames (for barracks and pilot select popup quick reference)
2444 pilot_load_pic_list();
2445 pilot_load_squad_pic_list();
2447 load_animating_pointer(NOX("cursor"), 0, 0);
2449 // initialize alpha colors
2450 alpha_colors_init();
2453 // Game_music_paused = 0;
2457 nprintf(("General", "Ships.tbl is : %s\n", Game_ships_tbl_valid ? "VALID" : "INVALID!!!!"));
2458 nprintf(("General", "Weapons.tbl is : %s\n", Game_weapons_tbl_valid ? "VALID" : "INVALID!!!!"));
2460 mprintf(("cfile_init() took %d\n", e1 - s1));
2461 // mprintf(("1000 cfopens() took %d\n", e2 - s2));
2464 char transfer_text[128];
2466 float Start_time = 0.0f;
2468 float Framerate = 0.0f;
2470 float Timing_total = 0.0f;
2471 float Timing_render2 = 0.0f;
2472 float Timing_render3 = 0.0f;
2473 float Timing_flip = 0.0f;
2474 float Timing_clear = 0.0f;
2476 MONITOR(NumPolysDrawn);
2482 void game_get_framerate()
2484 char text[128] = "";
2486 if ( frame_int == -1 ) {
2488 for (i=0; i<FRAME_FILTER; i++ ) {
2489 frametimes[i] = 0.0f;
2494 frametotal -= frametimes[frame_int];
2495 frametotal += flFrametime;
2496 frametimes[frame_int] = flFrametime;
2497 frame_int = (frame_int + 1 ) % FRAME_FILTER;
2499 if ( frametotal != 0.0 ) {
2500 if ( Framecount >= FRAME_FILTER )
2501 Framerate = FRAME_FILTER / frametotal;
2503 Framerate = Framecount / frametotal;
2504 SDL_snprintf( text, sizeof(text), NOX("FPS: %.1f"), Framerate );
2506 SDL_snprintf( text, sizeof(text), NOX("FPS: ?") );
2510 if (Show_framerate) {
2511 gr_set_color_fast(&HUD_color_debug);
2512 gr_string( 570, 2, text );
2516 void game_show_framerate()
2520 cur_time = f2fl(timer_get_approx_seconds());
2521 if (cur_time - Start_time > 30.0f) {
2522 mprintf(("%i frames executed in %7.3f seconds, %7.3f frames per second.\n", Framecount, cur_time - Start_time, Framecount/(cur_time - Start_time)));
2523 Start_time += 1000.0f;
2526 //mprintf(( "%s\n", text ));
2529 if ( Debug_dump_frames )
2533 // possibly show control checking info
2534 control_check_indicate();
2536 // int bitmaps_used_this_frame, bitmaps_new_this_frame;
2537 // bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
2538 // MONITOR_INC(BmpUsed, bitmaps_used_this_frame);
2539 // MONITOR_INC(BmpNew, bitmaps_new_this_frame);
2542 if ( Show_cpu == 1 ) {
2547 dy = gr_get_font_height() + 1;
2549 gr_set_color_fast(&HUD_color_debug);
2552 extern int Gr_textures_in;
2553 gr_printf( sx, sy, NOX("VRAM: %d KB\n"), Gr_textures_in/1024 );
2556 // gr_printf( sx, sy, "BPP: %d", gr_screen.bits_per_pixel );
2558 gr_printf( sx, sy, NOX("DMA: %s"), transfer_text );
2560 gr_printf( sx, sy, NOX("POLYP: %d"), modelstats_num_polys );
2562 gr_printf( sx, sy, NOX("POLYD: %d"), modelstats_num_polys_drawn );
2564 gr_printf( sx, sy, NOX("VERTS: %d"), modelstats_num_verts );
2569 extern int Num_pairs; // Number of object pairs that were checked.
2570 gr_printf( sx, sy, NOX("PAIRS: %d"), Num_pairs );
2573 extern int Num_pairs_checked; // What percent of object pairs were checked.
2574 gr_printf( sx, sy, NOX("FVI: %d"), Num_pairs_checked );
2576 Num_pairs_checked = 0;
2580 gr_printf( sx, sy, NOX("Snds: %d"), snd_num_playing() );
2583 if ( Timing_total > 0.01f ) {
2584 gr_printf( sx, sy, NOX("CLEAR: %.0f%%"), Timing_clear*100.0f/Timing_total );
2586 gr_printf( sx, sy, NOX("REND2D: %.0f%%"), Timing_render2*100.0f/Timing_total );
2588 gr_printf( sx, sy, NOX("REND3D: %.0f%%"), Timing_render3*100.0f/Timing_total );
2590 gr_printf( sx, sy, NOX("FLIP: %.0f%%"), Timing_flip*100.0f/Timing_total );
2592 gr_printf( sx, sy, NOX("GAME: %.0f%%"), (Timing_total-(Timing_render2+Timing_render3+Timing_flip+Timing_clear))*100.0f/Timing_total );
2601 dy = gr_get_font_height() + 1;
2603 gr_set_color_fast(&HUD_color_debug);
2606 extern int TotalRam;
2607 gr_printf( sx, sy, NOX("DYN: %d KB\n"), TotalRam/1024 );
2612 extern int Model_ram;
2613 gr_printf( sx, sy, NOX("POF: %d KB\n"), Model_ram/1024 );
2617 gr_printf( sx, sy, NOX("BMP: %d KB\n"), bm_texture_ram/1024 );
2619 gr_printf( sx, sy, NOX("S-SRAM: %d KB\n"), Snd_sram/1024 ); // mem used to store game sound
2623 extern int Gr_textures_in;
2624 gr_printf( sx, sy, NOX("VRAM: %d KB\n"), Gr_textures_in/1024 );
2629 if ( Show_player_pos ) {
2633 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));
2636 MONITOR_INC(NumPolys, modelstats_num_polys);
2637 MONITOR_INC(NumPolysDrawn, modelstats_num_polys_drawn );
2638 MONITOR_INC(NumVerts, modelstats_num_verts );
2640 modelstats_num_polys = 0;
2641 modelstats_num_polys_drawn = 0;
2642 modelstats_num_verts = 0;
2643 modelstats_num_sortnorms = 0;
2647 void game_show_standalone_framerate()
2649 float frame_rate=30.0f;
2650 if ( frame_int == -1 ) {
2652 for (i=0; i<FRAME_FILTER; i++ ) {
2653 frametimes[i] = 0.0f;
2658 frametotal -= frametimes[frame_int];
2659 frametotal += flFrametime;
2660 frametimes[frame_int] = flFrametime;
2661 frame_int = (frame_int + 1 ) % FRAME_FILTER;
2663 if ( frametotal != 0.0 ) {
2664 if ( Framecount >= FRAME_FILTER ){
2665 frame_rate = FRAME_FILTER / frametotal;
2667 frame_rate = Framecount / frametotal;
2670 std_set_standalone_fps(frame_rate);
2674 // function to show the time remaining in a mission. Used only when the end-mission sexpression is used
2675 void game_show_time_left()
2679 // mission_end_time is a global from missionparse.cpp that contains the mission time at which the
2680 // mission should end (in fixed seconds). There is code in missionparse.cpp which actually handles
2681 // checking how much time is left
2683 if ( Mission_end_time == -1 ){
2687 diff = f2i(Mission_end_time - Missiontime);
2688 // be sure to bash to 0. diff could be negative on frame that we quit mission
2693 hud_set_default_color();
2694 gr_printf( 5, 40, XSTR( "Mission time remaining: %d seconds", 179), diff );
2697 //========================================================================================
2698 //=================== NEW DEBUG CONSOLE COMMANDS TO REPLACE OLD DEBUG PAUSE MENU =========
2699 //========================================================================================
2703 DCF(ai_pause,"Pauses ai")
2706 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2707 if ( Dc_arg_type & ARG_TRUE ) ai_paused = 1;
2708 else if ( Dc_arg_type & ARG_FALSE ) ai_paused = 0;
2709 else if ( Dc_arg_type & ARG_NONE ) ai_paused = !ai_paused;
2712 obj_init_all_ships_physics();
2715 if ( Dc_help ) dc_printf( "Usage: ai_paused [bool]\nSets ai_paused to true or false. If nothing passed, then toggles it.\n" );
2716 if ( Dc_status ) dc_printf( "ai_paused is %s\n", (ai_paused?"TRUE":"FALSE") );
2719 DCF(single_step,"Single steps the game")
2722 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2723 if ( Dc_arg_type & ARG_TRUE ) game_single_step = 1;
2724 else if ( Dc_arg_type & ARG_FALSE ) game_single_step = 0;
2725 else if ( Dc_arg_type & ARG_NONE ) game_single_step = !game_single_step;
2727 last_single_step = 0; // Make so single step waits a frame before stepping
2730 if ( Dc_help ) dc_printf( "Usage: single_step [bool]\nSets single_step to true or false. If nothing passed, then toggles it.\n" );
2731 if ( Dc_status ) dc_printf( "single_step is %s\n", (game_single_step?"TRUE":"FALSE") );
2734 DCF_BOOL(physics_pause, physics_paused)
2735 DCF_BOOL(ai_rendering, Ai_render_debug_flag)
2736 DCF_BOOL(ai_firing, Ai_firing_enabled )
2738 // Create some simple aliases to these commands...
2739 debug_command dc_s("s","shortcut for single_step",dcf_single_step);
2740 debug_command dc_p("p","shortcut for physics_pause", dcf_physics_pause );
2741 debug_command dc_r("r","shortcut for ai_rendering", dcf_ai_rendering );
2742 debug_command dc_f("f","shortcut for ai_firing", dcf_ai_firing);
2743 debug_command dc_a("a","shortcut for ai_pause", dcf_ai_pause);
2746 //========================================================================================
2747 //========================================================================================
2750 void game_training_pause_do()
2754 key = game_check_key();
2756 gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
2763 void game_increase_skill_level()
2766 if (Game_skill_level >= NUM_SKILL_LEVELS){
2767 Game_skill_level = 0;
2771 int Player_died_time;
2773 int View_percent = 100;
2776 DCF(view, "Sets the percent of the 3d view to render.")
2779 dc_get_arg(ARG_INT);
2780 if ( (Dc_arg_int >= 5 ) || (Dc_arg_int <= 100) ) {
2781 View_percent = Dc_arg_int;
2783 dc_printf( "Illegal value for view. (Must be from 5-100) \n\n");
2789 dc_printf("Usage: view [n]\nwhere n is percent of view to show (5-100).\n");
2793 dc_printf("View is set to %d%%\n", View_percent );
2798 // Set the clip region for the 3d rendering window
2799 void game_set_view_clip()
2801 if ((Game_mode & GM_DEAD) || (supernova_active() >= 2)) {
2802 // Set the clip region for the letterbox "dead view"
2803 int yborder = gr_screen.max_h/4;
2805 // Numeric constants encouraged by J "pig farmer" S, who shall remain semi-anonymous.
2806 // J.S. I've changed my ways!! See the new "no constants" code!!!
2807 gr_set_clip(0, yborder, gr_screen.max_w, gr_screen.max_h - yborder*2 );
2809 // Set the clip region for normal view
2810 if ( View_percent >= 100 ) {
2813 int xborder, yborder;
2815 if ( View_percent < 5 ) {
2819 float fp = i2fl(View_percent)/100.0f;
2820 int fi = fl2i(fl_sqrt(fp)*100.0f);
2821 if ( fi > 100 ) fi=100;
2823 xborder = ( gr_screen.max_w*(100-fi) )/200;
2824 yborder = ( gr_screen.max_h*(100-fi) )/200;
2826 gr_set_clip(xborder, yborder, gr_screen.max_w-xborder*2,gr_screen.max_h-yborder*2 );
2832 void show_debug_stuff()
2835 int laser_count = 0, missile_count = 0;
2837 for (i=0; i<MAX_OBJECTS; i++) {
2838 if (Objects[i].type == OBJ_WEAPON){
2839 if (Weapon_info[Weapons[Objects[i].instance].weapon_info_index].subtype == WP_LASER){
2841 } else if (Weapon_info[Weapons[Objects[i].instance].weapon_info_index].subtype == WP_MISSILE){
2847 nprintf(("Mike", "Frame: %i Lasers: %4i, Missiles: %4i\n", Framecount, laser_count, missile_count));
2850 extern int Tool_enabled;
2852 time_t tst_time = 0;
2855 int tst_bitmap = -1;
2857 float tst_offset, tst_offset_total;
2860 void game_tst_frame_pre()
2868 g3_rotate_vertex(&v, &tst_pos);
2869 g3_project_vertex(&v);
2872 if(!((v.sx >= 0) && (v.sx <= gr_screen.max_w) && (v.sy >= 0) && (v.sy <= gr_screen.max_h))){
2876 // big ship? always tst
2878 // within 3000 meters
2879 if( vm_vec_dist_quick(&tst_pos, &Eye_position) <= 3000.0f){
2883 // within 300 meters
2884 if( (vm_vec_dist_quick(&tst_pos, &Eye_position) <= 300.0f) && ((tst_time == 0) || ((time(NULL) - tst_time) >= 10)) ){
2891 void game_tst_frame()
2901 tst_time = time(NULL);
2903 // load the tst bitmap
2904 switch((int)frand_range(0.0f, 3.0)){
2906 tst_bitmap = bm_load("ig_jim");
2908 mprintf(("TST 0\n"));
2912 tst_bitmap = bm_load("ig_kan");
2914 mprintf(("TST 1\n"));
2918 tst_bitmap = bm_load("ig_jim");
2920 mprintf(("TST 2\n"));
2924 tst_bitmap = bm_load("ig_kan");
2926 mprintf(("TST 3\n"));
2935 // get the tst bitmap dimensions
2937 bm_get_info(tst_bitmap, &w, &h);
2940 tst_y = frand_range(0.0f, (float)gr_screen.max_h - h);
2942 snd_play(&Snds[SND_VASUDAN_BUP]);
2944 // tst x and direction
2948 tst_offset_total = (float)w;
2949 tst_offset = (float)w;
2951 tst_x = (float)gr_screen.max_w;
2952 tst_offset_total = (float)-w;
2953 tst_offset = (float)w;
2961 float diff = (tst_offset_total / 0.5f) * flFrametime;
2967 tst_offset -= fl_abs(diff);
2968 } else if(tst_mode == 2){
2971 tst_offset -= fl_abs(diff);
2975 gr_set_bitmap(tst_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
2976 gr_bitmap((int)tst_x, (int)tst_y);
2979 if(timestamp_elapsed_safe(tst_stamp, 1100)){
2983 // if we passed the switch point
2984 if(tst_offset <= 0.0f){
2989 tst_stamp = timestamp(1000);
2990 tst_offset = fl_abs(tst_offset_total);
3001 void game_tst_mark(object *objp, ship *shipp)
3010 if((objp == NULL) || (shipp == NULL) || (shipp->ship_info_index < 0) || (shipp->ship_info_index >= Num_ship_types)){
3013 sip = &Ship_info[shipp->ship_info_index];
3020 tst_pos = objp->pos;
3021 if(sip->flags & (SIF_BIG_SHIP | SIF_HUGE_SHIP)){
3027 extern void render_shields();
3029 void player_repair_frame(float frametime)
3031 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
3033 for(idx=0;idx<MAX_PLAYERS;idx++){
3036 np = &Net_players[idx];
3038 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)){
3040 // don't rearm/repair if the player is dead or dying/departing
3041 if ( !NETPLAYER_IS_DEAD(np) && !(Ships[Objects[np->player->objnum].instance].flags & (SF_DYING|SF_DEPARTING)) ) {
3042 ai_do_repair_frame(&Objects[Net_players[idx].player->objnum],&Ai_info[Ships[Objects[Net_players[idx].player->objnum].instance].ai_index],frametime);
3047 if ( (Player_obj != NULL) && (Player_obj->type == OBJ_SHIP) && !(Game_mode & GM_STANDALONE_SERVER) && (Player_ship != NULL) && !(Player_ship->flags & SF_DYING) ) {
3048 ai_do_repair_frame(Player_obj, &Ai_info[Ships[Player_obj->instance].ai_index], frametime);
3054 #define NUM_FRAMES_TEST 300
3055 #define NUM_MIXED_SOUNDS 16
3056 void do_timing_test(float flFrametime)
3058 static int framecount = 0;
3059 static int test_running = 0;
3060 static float test_time = 0.0f;
3062 static int snds[NUM_MIXED_SOUNDS];
3065 if ( test_running ) {
3067 test_time += flFrametime;
3068 if ( framecount >= NUM_FRAMES_TEST ) {
3070 nprintf(("General", "%d frames took %.3f seconds\n", NUM_FRAMES_TEST, test_time));
3071 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3076 if ( Test_begin == 1 ) {
3082 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3085 // start looping digital sounds
3086 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3087 snds[i] = snd_play_looping( &Snds[i], 0.0f);
3094 DCF(dcf_fov, "Change the field of view")
3097 dc_get_arg(ARG_FLOAT|ARG_NONE);
3098 if ( Dc_arg_type & ARG_NONE ) {
3099 Viewer_zoom = VIEWER_ZOOM_DEFAULT;
3100 dc_printf( "Zoom factor reset\n" );
3102 if ( Dc_arg_type & ARG_FLOAT ) {
3103 if (Dc_arg_float < 0.25f) {
3104 Viewer_zoom = 0.25f;
3105 dc_printf("Zoom factor pinned at 0.25.\n");
3106 } else if (Dc_arg_float > 1.25f) {
3107 Viewer_zoom = 1.25f;
3108 dc_printf("Zoom factor pinned at 1.25.\n");
3110 Viewer_zoom = Dc_arg_float;
3116 dc_printf( "Usage: fov [factor]\nFactor is the zoom factor btwn .25 and 1.25\nNo parameter resets it to default.\n" );
3119 dc_printf("Zoom factor set to %6.3f (original = 0.5, John = 0.75)", Viewer_zoom);
3123 DCF(framerate_cap, "Sets the framerate cap")
3126 dc_get_arg(ARG_INT);
3127 if ( (Dc_arg_int >= 1 ) || (Dc_arg_int <= 120) ) {
3128 Framerate_cap = Dc_arg_int;
3130 dc_printf( "Illegal value for framerate cap. (Must be from 1-120) \n\n");
3136 dc_printf("Usage: framerate_cap [n]\nwhere n is the frames per second to cap framerate at.\n");
3137 dc_printf("If n is 0 or omitted, then the framerate cap is removed\n");
3138 dc_printf("[n] must be from 1 to 120.\n");
3142 if ( Framerate_cap )
3143 dc_printf("Framerate cap is set to %d fps\n", Framerate_cap );
3145 dc_printf("There is no framerate cap currently active.\n");
3149 #define MIN_DIST_TO_DEAD_CAMERA 50.0f
3150 int Show_viewing_from_self = 0;
3152 void say_view_target()
3154 object *view_target;
3156 if ((Viewer_mode & VM_OTHER_SHIP) && (Player_ai->target_objnum != -1))
3157 view_target = &Objects[Player_ai->target_objnum];
3159 view_target = Player_obj;
3161 if (Game_mode & GM_DEAD) {
3162 if (Player_ai->target_objnum != -1)
3163 view_target = &Objects[Player_ai->target_objnum];
3166 if (!(Game_mode & GM_DEAD_DIED) && ((Game_mode & (GM_DEAD_BLEW_UP)) || ((Last_view_target != NULL) && (Last_view_target != view_target)))) {
3167 if (view_target != Player_obj){
3169 char *view_target_name = NULL;
3170 switch(Objects[Player_ai->target_objnum].type) {
3172 view_target_name = Ships[Objects[Player_ai->target_objnum].instance].ship_name;
3175 view_target_name = Weapon_info[Weapons[Objects[Player_ai->target_objnum].instance].weapon_info_index].name;
3176 Viewer_mode &= ~VM_OTHER_SHIP;
3178 case OBJ_JUMP_NODE: {
3179 char jump_node_name[128];
3180 SDL_strlcpy(jump_node_name, XSTR( "jump node", 184), sizeof(jump_node_name));
3181 view_target_name = jump_node_name;
3182 Viewer_mode &= ~VM_OTHER_SHIP;
3191 if ( view_target_name ) {
3192 HUD_fixed_printf(0.0f, XSTR( "Viewing %s%s\n", 185), (Viewer_mode & VM_OTHER_SHIP) ? XSTR( "from ", 186) : "", view_target_name);
3193 Show_viewing_from_self = 1;
3196 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER) && (Player_obj->type == OBJ_OBSERVER)){
3197 HUD_fixed_printf(2.0f,XSTR( "Viewing from observer\n", 187));
3198 Show_viewing_from_self = 1;
3200 if (Show_viewing_from_self)
3201 HUD_fixed_printf(2.0f, XSTR( "Viewing from self\n", 188));
3206 Last_view_target = view_target;
3210 float Game_hit_x = 0.0f;
3211 float Game_hit_y = 0.0f;
3213 // Reset at the beginning of each frame
3214 void game_whack_reset()
3220 // Apply a 2d whack to the player
3221 void game_whack_apply( float x, float y )
3223 // Do some force feedback
3224 joy_ff_play_dir_effect(x * 80.0f, y * 80.0f);
3230 // mprintf(( "WHACK = %.1f, %.1f\n", Game_hit_x, Game_hit_y ));
3233 // call to apply a "shudder"
3234 void game_shudder_apply(int time, float intensity)
3236 Game_shudder_time = timestamp(time);
3237 Game_shudder_total = time;
3238 Game_shudder_intensity = intensity;
3241 #define FF_SCALE 10000
3242 void apply_hud_shake(matrix *eye_orient)
3244 if (Viewer_obj == Player_obj) {
3245 physics_info *pi = &Player_obj->phys_info;
3253 // Make eye shake due to afterburner
3254 if ( !timestamp_elapsed(pi->afterburner_decay) ) {
3257 dtime = timestamp_until(pi->afterburner_decay);
3261 tangles.p += 0.07f * (float) (r1-MY_RAND_MAX/2)/MY_RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/ABURN_DECAY_TIME));
3262 tangles.h += 0.07f * (float) (r2-MY_RAND_MAX/2)/MY_RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/ABURN_DECAY_TIME));
3265 // Make eye shake due to engine wash
3267 if (Player_obj->type == OBJ_SHIP && (Ships[Player_obj->instance].wash_intensity > 0) && Wash_on ) {
3270 tangles.p += 0.07f * Ships[Player_obj->instance].wash_intensity * (float) (r1-MY_RAND_MAX/2)/MY_RAND_MAX;
3271 tangles.h += 0.07f * Ships[Player_obj->instance].wash_intensity * (float) (r2-MY_RAND_MAX/2)/MY_RAND_MAX;
3273 // get the intensity
3274 float intensity = FF_SCALE * Ships[Player_obj->instance].wash_intensity;
3278 vm_vec_rand_vec_quick(&rand_vec);
3281 joy_ff_play_dir_effect(intensity*rand_vec.xyz.x, intensity*rand_vec.xyz.y);
3285 // make hud shake due to shuddering
3286 if(Game_shudder_time != -1){
3287 // if the timestamp has elapsed
3288 if(timestamp_elapsed(Game_shudder_time)){
3289 Game_shudder_time = -1;
3291 // otherwise apply some shudder
3295 dtime = timestamp_until(Game_shudder_time);
3299 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));
3300 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));
3305 vm_angles_2_matrix(&tm, &tangles);
3306 SDL_assert(vm_vec_mag(&tm.v.fvec) > 0.0f);
3307 SDL_assert(vm_vec_mag(&tm.v.rvec) > 0.0f);
3308 SDL_assert(vm_vec_mag(&tm.v.uvec) > 0.0f);
3309 vm_matrix_x_matrix(&tm2, eye_orient, &tm);
3314 extern void compute_slew_matrix(matrix *orient, angles *a); // TODO: move code to proper place and extern in header file
3316 // Player's velocity just before he blew up. Used to keep camera target moving.
3317 vector Dead_player_last_vel = { { { 1.0f, 1.0f, 1.0f } } };
3319 // Set eye_pos and eye_orient based on view mode.
3320 void game_render_frame_setup(vector *eye_pos, matrix *eye_orient)
3324 static int last_Viewer_mode = 0;
3325 static int last_Game_mode = 0;
3326 static int last_Viewer_objnum = -1;
3328 // This code is supposed to detect camera "cuts"... like going between
3331 // determine if we need to regenerate the nebula
3332 if( (!(last_Viewer_mode & VM_EXTERNAL) && (Viewer_mode & VM_EXTERNAL)) || // internal to external
3333 ((last_Viewer_mode & VM_EXTERNAL) && !(Viewer_mode & VM_EXTERNAL)) || // external to internal
3334 (!(last_Viewer_mode & VM_DEAD_VIEW) && (Viewer_mode & VM_DEAD_VIEW)) || // non dead-view to dead-view
3335 ((last_Viewer_mode & VM_DEAD_VIEW) && !(Viewer_mode & VM_DEAD_VIEW)) || // dead-view to non dead-view
3336 (!(last_Viewer_mode & VM_WARP_CHASE) && (Viewer_mode & VM_WARP_CHASE)) || // non warp-chase to warp-chase
3337 ((last_Viewer_mode & VM_WARP_CHASE) && !(Viewer_mode & VM_WARP_CHASE)) || // warp-chase to non warp-chase
3338 (!(last_Viewer_mode & VM_OTHER_SHIP) && (Viewer_mode & VM_OTHER_SHIP)) || // non other-ship to other-ship
3339 ((last_Viewer_mode & VM_OTHER_SHIP) && !(Viewer_mode & VM_OTHER_SHIP)) || // other-ship to non-other ship
3340 ((Viewer_mode & VM_OTHER_SHIP) && (last_Viewer_objnum != Player_ai->target_objnum)) // other ship mode, but targets changes
3343 // regenerate the nebula
3347 if ( (last_Viewer_mode != Viewer_mode) || (last_Game_mode != Game_mode) ) {
3348 //mprintf(( "************** Camera cut! ************\n" ));
3349 last_Viewer_mode = Viewer_mode;
3350 last_Game_mode = Game_mode;
3352 // Camera moved. Tell stars & debris to not do blurring.
3358 if ( Viewer_mode & VM_PADLOCK_ANY ) {
3359 player_display_packlock_view();
3362 game_set_view_clip();
3364 if (Game_mode & GM_DEAD) {
3365 vector vec_to_deader, view_pos;
3368 Viewer_mode |= VM_DEAD_VIEW;
3370 if (Player_ai->target_objnum != -1) {
3371 int view_from_player = 1;
3373 if (Viewer_mode & VM_OTHER_SHIP) {
3374 // View from target.
3375 Viewer_obj = &Objects[Player_ai->target_objnum];
3377 last_Viewer_objnum = Player_ai->target_objnum;
3379 if ( Viewer_obj->type == OBJ_SHIP ) {
3380 ship_get_eye( eye_pos, eye_orient, Viewer_obj );
3381 view_from_player = 0;
3384 last_Viewer_objnum = -1;
3387 if ( view_from_player ) {
3388 // View target from player ship.
3390 *eye_pos = Player_obj->pos;
3391 vm_vec_normalized_dir(&eye_dir, &Objects[Player_ai->target_objnum].pos, eye_pos);
3392 vm_vector_2_matrix(eye_orient, &eye_dir, NULL, NULL);
3395 dist = vm_vec_normalized_dir(&vec_to_deader, &Player_obj->pos, &Dead_camera_pos);
3397 if (dist < MIN_DIST_TO_DEAD_CAMERA)
3398 dist += flFrametime * 16.0f;
3400 vm_vec_scale(&vec_to_deader, -dist);
3401 vm_vec_add(&Dead_camera_pos, &Player_obj->pos, &vec_to_deader);
3403 view_pos = Player_obj->pos;
3405 if (!(Game_mode & GM_DEAD_BLEW_UP)) {
3406 Viewer_mode &= ~(VM_EXTERNAL | VM_CHASE);
3407 vm_vec_scale_add2(&Dead_camera_pos, &Original_vec_to_deader, 25.0f * flFrametime);
3408 Dead_player_last_vel = Player_obj->phys_info.vel;
3409 //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));
3410 } else if (Player_ai->target_objnum != -1) {
3411 view_pos = Objects[Player_ai->target_objnum].pos;
3413 // Make camera follow explosion, but gradually slow down.
3414 vm_vec_scale_add2(&Player_obj->pos, &Dead_player_last_vel, flFrametime);
3415 view_pos = Player_obj->pos;
3416 vm_vec_scale(&Dead_player_last_vel, 0.99f);
3417 vm_vec_scale_add2(&Dead_camera_pos, &Original_vec_to_deader, min(25.0f, vm_vec_mag_quick(&Dead_player_last_vel)) * flFrametime);
3420 *eye_pos = Dead_camera_pos;
3422 vm_vec_normalized_dir(&eye_dir, &Player_obj->pos, eye_pos);
3424 vm_vector_2_matrix(eye_orient, &eye_dir, NULL, NULL);
3429 // if supernova shockwave
3430 if(supernova_camera_cut()){
3434 // call it dead view
3435 Viewer_mode |= VM_DEAD_VIEW;
3437 // set eye pos and orient
3438 supernova_set_view(eye_pos, eye_orient);
3440 // If already blown up, these other modes can override.
3441 if (!(Game_mode & (GM_DEAD | GM_DEAD_BLEW_UP))) {
3442 Viewer_mode &= ~VM_DEAD_VIEW;
3444 Viewer_obj = Player_obj;
3446 if (Viewer_mode & VM_OTHER_SHIP) {
3447 if (Player_ai->target_objnum != -1){
3448 Viewer_obj = &Objects[Player_ai->target_objnum];
3449 last_Viewer_objnum = Player_ai->target_objnum;
3451 Viewer_mode &= ~VM_OTHER_SHIP;
3452 last_Viewer_objnum = -1;
3455 last_Viewer_objnum = -1;
3458 if (Viewer_mode & VM_EXTERNAL) {
3461 vm_angles_2_matrix(&tm2, &Viewer_external_info.angles);
3462 vm_matrix_x_matrix(&tm, &Viewer_obj->orient, &tm2);
3464 vm_vec_scale_add(eye_pos, &Viewer_obj->pos, &tm.v.fvec, 2.0f * Viewer_obj->radius + Viewer_external_info.distance);
3466 vm_vec_sub(&eye_dir, &Viewer_obj->pos, eye_pos);
3467 vm_vec_normalize(&eye_dir);
3468 vm_vector_2_matrix(eye_orient, &eye_dir, &Viewer_obj->orient.v.uvec, NULL);
3471 // Modify the orientation based on head orientation.
3472 compute_slew_matrix(eye_orient, &Viewer_slew_angles);
3474 } else if ( Viewer_mode & VM_CHASE ) {
3477 if ( Viewer_obj->phys_info.speed < 0.1 )
3478 move_dir = Viewer_obj->orient.v.fvec;
3480 move_dir = Viewer_obj->phys_info.vel;
3481 vm_vec_normalize(&move_dir);
3484 vm_vec_scale_add(eye_pos, &Viewer_obj->pos, &move_dir, -3.0f * Viewer_obj->radius - Viewer_chase_info.distance);
3485 vm_vec_scale_add2(eye_pos, &Viewer_obj->orient.v.uvec, 0.75f * Viewer_obj->radius);
3486 vm_vec_sub(&eye_dir, &Viewer_obj->pos, eye_pos);
3487 vm_vec_normalize(&eye_dir);
3489 // JAS: I added the following code because if you slew up using
3490 // Descent-style physics, eye_dir and Viewer_obj->orient.v.uvec are
3491 // equal, which causes a zero-length vector in the vm_vector_2_matrix
3492 // call because the up and the forward vector are the same. I fixed
3493 // it by adding in a fraction of the right vector all the time to the
3495 vector tmp_up = Viewer_obj->orient.v.uvec;
3496 vm_vec_scale_add2( &tmp_up, &Viewer_obj->orient.v.rvec, 0.00001f );
3498 vm_vector_2_matrix(eye_orient, &eye_dir, &tmp_up, NULL);
3501 // Modify the orientation based on head orientation.
3502 compute_slew_matrix(eye_orient, &Viewer_slew_angles);
3503 } else if ( Viewer_mode & VM_WARP_CHASE ) {
3504 *eye_pos = Camera_pos;
3506 ship * shipp = &Ships[Player_obj->instance];
3508 vm_vec_sub(&eye_dir, &shipp->warp_effect_pos, eye_pos);
3509 vm_vec_normalize(&eye_dir);
3510 vm_vector_2_matrix(eye_orient, &eye_dir, &Player_obj->orient.v.uvec, NULL);
3513 // get an eye position based upon the correct type of object
3514 switch(Viewer_obj->type){
3516 // make a call to get the eye point for the player object
3517 ship_get_eye( eye_pos, eye_orient, Viewer_obj );
3520 // make a call to get the eye point for the player object
3521 observer_get_eye( eye_pos, eye_orient, Viewer_obj );
3527 #ifdef JOHNS_DEBUG_CODE
3528 john_debug_stuff(&eye_pos, &eye_orient);
3534 apply_hud_shake(eye_orient);
3536 // setup neb2 rendering
3537 neb2_render_setup(eye_pos, eye_orient);
3541 extern void ai_debug_render_stuff();
3544 int Game_subspace_effect = 0;
3545 DCF_BOOL( subspace, Game_subspace_effect );
3547 // Does everything needed to render a frame
3548 void game_render_frame( vector * eye_pos, matrix * eye_orient )
3552 g3_start_frame(game_zbuffer);
3553 g3_set_view_matrix( eye_pos, eye_orient, Viewer_zoom );
3555 // maybe offset the HUD (jitter stuff)
3556 dont_offset = ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER));
3557 HUD_set_offsets(Viewer_obj, !dont_offset);
3559 // for multiplayer clients, call code in Shield.cpp to set up the Shield_hit array. Have to
3560 // do this becaues of the disjointed nature of this system (in terms of setup and execution).
3561 // must be done before ships are rendered
3562 if ( MULTIPLAYER_CLIENT ) {
3563 shield_point_multi_setup();
3566 if ( Game_subspace_effect ) {
3567 stars_draw(0,0,0,1);
3569 stars_draw(1,1,1,0);
3572 obj_render_all(obj_render);
3573 beam_render_all(); // render all beam weapons
3574 particle_render_all(); // render particles after everything else.
3575 trail_render_all(); // render missilie trails after everything else.
3576 mflash_render_all(); // render all muzzle flashes
3578 // Why do we not show the shield effect in these modes? Seems ok.
3579 //if (!(Viewer_mode & (VM_EXTERNAL | VM_SLEWED | VM_CHASE | VM_DEAD_VIEW))) {
3583 // render nebula lightning
3586 // render local player nebula
3587 neb2_render_player();
3590 ai_debug_render_stuff();
3593 #ifndef RELEASE_REAL
3594 // game_framerate_check();
3598 extern void snd_spew_debug_info();
3599 snd_spew_debug_info();
3602 //================ END OF 3D RENDERING STUFF ====================
3606 if( (Game_detail_flags & DETAIL_FLAG_HUD) && (!(Game_mode & GM_MULTIPLAYER) || ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER) )) ) {
3607 hud_maybe_clear_head_area();
3608 anim_render_all(0, flFrametime);
3611 extern int Multi_display_netinfo;
3612 if(Multi_display_netinfo){
3613 extern void multi_display_netinfo();
3614 multi_display_netinfo();
3617 game_tst_frame_pre();
3620 do_timing_test(flFrametime);
3624 extern int OO_update_index;
3625 multi_rate_display(OO_update_index, 375, 0);
3630 extern void oo_display();
3637 //#define JOHNS_DEBUG_CODE 1
3639 #ifdef JOHNS_DEBUG_CODE
3640 void john_debug_stuff(vector *eye_pos, matrix *eye_orient)
3642 //if ( key_pressed(SDLK_LSHIFT) )
3644 ship_subsys *tsys = Players[Player_num].targeted_subobject;
3646 model_subsystem *turret = tsys->system_info;
3648 if (turret->type == SUBSYSTEM_TURRET ) {
3649 vector v.fvec, v.uvec;
3650 object * tobj = &Objects[Players[Player_num].targeted_subobject_parent];
3652 ship_model_start(tobj);
3654 model_find_world_point(eye_pos, &turret->turret_firing_point[0], turret->model_num, turret->turret_gun_sobj, &tobj->orient, &tobj->pos );
3655 model_find_world_dir(&v.fvec, &turret->turret_matrix.v.fvec, turret->model_num, turret->turret_gun_sobj, &tobj->orient, NULL );
3656 model_find_world_dir(&v.uvec, &turret->turret_matrix.v.uvec, turret->model_num, turret->turret_gun_sobj, &tobj->orient, NULL );
3658 vm_vector_2_matrix( eye_orient, &v.fvec, &v.uvec, NULL );
3660 ship_model_stop(tobj);
3670 // following function for dumping frames for purposes of building trailers.
3673 // function to toggle state of dumping every frame into PCX when playing the game
3674 DCF(dump_frames, "Starts/stop frame dumping at 15 hz")
3678 if ( Debug_dump_frames == 0 ) {
3680 Debug_dump_frames = 15;
3681 Debug_dump_trigger = 0;
3682 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
3683 dc_printf( "Frame dumping at 15 hz is now ON\n" );
3686 Debug_dump_frames = 0;
3687 Debug_dump_trigger = 0;
3688 gr_dump_frame_stop();
3689 dc_printf( "Frame dumping is now OFF\n" );
3695 DCF(dump_frames_trigger, "Starts/stop frame dumping at 15 hz")
3699 if ( Debug_dump_frames == 0 ) {
3701 Debug_dump_frames = 15;
3702 Debug_dump_trigger = 1;
3703 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
3704 dc_printf( "Frame dumping at 15 hz is now ON\n" );
3707 Debug_dump_frames = 0;
3708 Debug_dump_trigger = 0;
3709 gr_dump_frame_stop();
3710 dc_printf( "Frame dumping is now OFF\n" );
3716 DCF(dump_frames30, "Starts/stop frame dumping at 30 hz")
3720 if ( Debug_dump_frames == 0 ) {
3722 Debug_dump_frames = 30;
3723 Debug_dump_trigger = 0;
3724 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
3725 dc_printf( "Frame dumping at 30 hz is now ON\n" );
3728 Debug_dump_frames = 0;
3729 Debug_dump_trigger = 0;
3730 gr_dump_frame_stop();
3731 dc_printf( "Frame dumping is now OFF\n" );
3737 DCF(dump_frames30_trigger, "Starts/stop frame dumping at 30 hz")
3741 if ( Debug_dump_frames == 0 ) {
3743 Debug_dump_frames = 30;
3744 Debug_dump_trigger = 1;
3745 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
3746 dc_printf( "Triggered frame dumping at 30 hz is now ON\n" );
3749 Debug_dump_frames = 0;
3750 Debug_dump_trigger = 0;
3751 gr_dump_frame_stop();
3752 dc_printf( "Triggered frame dumping is now OFF\n" );
3758 void game_maybe_dump_frame()
3760 if ( !Debug_dump_frames ){
3764 if( Debug_dump_trigger && !key_pressed(SDLK_q) ){
3771 Debug_dump_frame_num++;
3777 extern int Player_dead_state;
3779 // Flip the page and time how long it took.
3780 void game_flip_page_and_time_it()
3785 t1 = timer_get_fixed_seconds();
3787 t2 = timer_get_fixed_seconds();
3790 t = (gr_screen.max_w*gr_screen.max_h*gr_screen.bytes_per_pixel)/1024;
3791 SDL_snprintf( transfer_text, sizeof(transfer_text), NOX("%d MB/s"), fixmuldiv(t,65,d) );
3798 void game_simulation_frame()
3800 // blow ships up in multiplayer dogfight
3801 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){
3802 // blow up all non-player ships
3803 ship_obj *moveup = GET_FIRST(&Ship_obj_list);
3806 while((moveup != END_OF_LIST(&Ship_obj_list)) && (moveup != NULL)){
3808 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)){
3809 moveup = GET_NEXT(moveup);
3812 shipp = &Ships[Objects[moveup->objnum].instance];
3813 sip = &Ship_info[shipp->ship_info_index];
3815 // only blow up small ships
3816 if((sip->flags & SIF_SMALL_SHIP) && (multi_find_player_by_object(&Objects[moveup->objnum]) < 0) ){
3817 // function to simply explode a ship where it is currently at
3818 ship_self_destruct( &Objects[moveup->objnum] );
3821 moveup = GET_NEXT(moveup);
3827 // process AWACS stuff - do this first thing
3830 // single player, set Player hits_this_frame to 0
3831 if ( !(Game_mode & GM_MULTIPLAYER) && Player ) {
3832 Player->damage_this_burst -= (flFrametime * MAX_BURST_DAMAGE / (0.001f * BURST_DURATION));
3833 Player->damage_this_burst = max(Player->damage_this_burst, 0.0f);
3837 supernova_process();
3838 if(supernova_active() >= 5){
3842 // fire targeting lasers now so that
3843 // 1 - created this frame
3844 // 2 - collide this frame
3845 // 3 - render this frame
3846 // 4 - ignored and deleted next frame
3847 // the basic idea being that because it con be confusing to deal with them on a multi-frame basis, they are only valid for
3849 ship_process_targeting_lasers();
3851 // do this here so that it works for multiplayer
3853 // get viewer direction
3854 int viewer_direction = PHYSICS_VIEWER_REAR;
3856 if(Viewer_mode == 0){
3857 viewer_direction = PHYSICS_VIEWER_FRONT;
3859 if(Viewer_mode & VM_PADLOCK_UP){
3860 viewer_direction = PHYSICS_VIEWER_UP;
3862 else if(Viewer_mode & VM_PADLOCK_REAR){
3863 viewer_direction = PHYSICS_VIEWER_REAR;
3865 else if(Viewer_mode & VM_PADLOCK_LEFT){
3866 viewer_direction = PHYSICS_VIEWER_LEFT;
3868 else if(Viewer_mode & VM_PADLOCK_RIGHT){
3869 viewer_direction = PHYSICS_VIEWER_RIGHT;
3872 physics_set_viewer( &Viewer_obj->phys_info, viewer_direction );
3874 physics_set_viewer( NULL, PHYSICS_VIEWER_FRONT );
3877 #define VM_PADLOCK_UP (1 << 7)
3878 #define VM_PADLOCK_REAR (1 << 8)
3879 #define VM_PADLOCK_LEFT (1 << 9)
3880 #define VM_PADLOCK_RIGHT (1 << 10)
3882 // evaluate mission departures and arrivals before we process all objects.
3883 if ( !(Game_mode & GM_MULTIPLAYER) || ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER) && !multi_endgame_ending()) ) {
3885 // we don't want to evaluate mission stuff when any ingame joiner in multiplayer is receiving
3886 // ships/wing packets.
3887 if ( !((Game_mode & GM_MULTIPLAYER) && (Netgame.flags & NG_FLAG_INGAME_JOINING_CRITICAL)) && !(Game_mode & GM_DEMO_PLAYBACK)){
3888 mission_parse_eval_stuff();
3891 // if we're an observer, move ourselves seperately from the standard physics
3892 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER)){
3893 obj_observer_move(flFrametime);
3896 // move all the objects now
3897 obj_move_all(flFrametime);
3899 // check for cargo reveal (this has an internal timestamp, so only runs every N ms)
3900 // AL: 3-15-98: It was decided to not let AI ships inspect cargo
3901 // ship_check_cargo_all();
3902 if(!(Game_mode & GM_DEMO_PLAYBACK)){
3903 mission_eval_goals();
3907 // always check training objectives, even in multiplayer missions. we need to do this so that the directives gauge works properly on clients
3908 if(!(Game_mode & GM_DEMO_PLAYBACK)){
3909 training_check_objectives();
3912 // do all interpolation now
3913 if ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER) && !multi_endgame_ending() && !(Netgame.flags & NG_FLAG_SERVER_LOST)) {
3914 // client side processing of warping in effect stages
3915 multi_do_client_warp(flFrametime);
3917 // client side movement of an observer
3918 if((Net_player->flags & NETINFO_FLAG_OBSERVER) || (Player_obj->type == OBJ_OBSERVER)){
3919 obj_observer_move(flFrametime);
3922 // move all objects - does interpolation now as well
3923 obj_move_all(flFrametime);
3926 // only process the message queue when the player is "in" the game
3927 if ( !Pre_player_entry ){
3928 message_queue_process(); // process any messages send to the player
3931 if(!(Game_mode & GM_DEMO_PLAYBACK)){
3932 message_maybe_distort(); // maybe distort incoming message if comms damaged
3933 player_repair_frame(flFrametime); // AI objects get repaired in ai_process, called from move code...deal with player.
3934 player_process_pending_praise(); // maybe send off a delayed praise message to the player
3935 player_maybe_play_all_alone_msg(); // mabye tell the player he is all alone
3938 if(!(Game_mode & GM_STANDALONE_SERVER)){
3939 // process some stuff every frame (before frame is rendered)
3940 emp_process_local();
3942 hud_update_frame(); // update hud systems
3944 if (!physics_paused) {
3945 // Move particle system
3946 particle_move_all(flFrametime);
3948 // Move missile trails
3949 trail_move_all(flFrametime);
3951 // process muzzle flashes
3952 mflash_process_all();
3954 // Flash the gun flashes
3955 shipfx_flash_do_frame(flFrametime);
3957 shockwave_move_all(flFrametime); // update all the shockwaves
3960 // subspace missile strikes
3963 obj_snd_do_frame(); // update the object-linked persistant sounds
3964 game_maybe_update_sound_environment();
3965 snd_update_listener(&View_position, &Player_obj->phys_info.vel, &Player_obj->orient);
3967 // AL: debug code used for testing ambient subspace sound (ie when enabling subspace through debug console)
3969 if ( Game_subspace_effect ) {
3970 game_start_subspace_ambient_sound();
3976 // Maybe render and process the dead-popup
3977 void game_maybe_do_dead_popup(float frametime)
3979 if ( popupdead_is_active() ) {
3981 int choice = popupdead_do_frame(frametime);
3983 if ( Game_mode & GM_NORMAL ) {
3986 gameseq_post_event(GS_EVENT_ENTER_GAME);
3990 gameseq_post_event(GS_EVENT_END_GAME);
3994 gameseq_post_event(GS_EVENT_START_GAME);
3997 // this should only happen during a red alert mission
4000 SDL_assert(The_mission.red_alert);
4001 if(!The_mission.red_alert){
4002 gameseq_post_event(GS_EVENT_START_GAME);
4006 // choose the previous mission
4007 mission_campaign_previous_mission();
4009 gameseq_post_event(GS_EVENT_START_GAME);
4019 case POPUPDEAD_DO_MAIN_HALL:
4020 multi_quit_game(PROMPT_NONE,-1);
4023 case POPUPDEAD_DO_RESPAWN:
4024 multi_respawn_normal();
4025 event_music_player_respawn();
4028 case POPUPDEAD_DO_OBSERVER:
4029 multi_respawn_observer();
4030 event_music_player_respawn_as_observer();
4039 if ( leave_popup ) {
4045 // returns true if player is actually in a game_play stats
4046 int game_actually_playing()
4050 state = gameseq_get_state();
4051 if ( (state != GS_STATE_GAME_PLAY) && (state != GS_STATE_DEATH_DIED) && (state != GS_STATE_DEATH_BLEW_UP) )
4057 // Draw the 2D HUD gauges
4058 void game_render_hud_2d()
4060 if ( !(Game_detail_flags & DETAIL_FLAG_HUD) ) {
4064 HUD_render_2d(flFrametime);
4068 // Draw the 3D-dependant HUD gauges
4069 void game_render_hud_3d(vector *eye_pos, matrix *eye_orient)
4071 g3_start_frame(0); // 0 = turn zbuffering off
4072 g3_set_view_matrix( eye_pos, eye_orient, Viewer_zoom );
4074 if ( (Game_detail_flags & DETAIL_FLAG_HUD) && (supernova_active() < 3)/* && !(Game_mode & GM_MULTIPLAYER) || ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER) )*/ ) {
4075 HUD_render_3d(flFrametime);
4079 game_sunspot_process(flFrametime);
4081 // Diminish the palette effect
4082 game_flash_diminish(flFrametime);
4090 int actually_playing;
4091 fix total_time1, total_time2;
4092 fix render2_time1=0, render2_time2=0;
4093 fix render3_time1=0, render3_time2=0;
4094 fix flip_time1=0, flip_time2=0;
4095 fix clear_time1=0, clear_time2=0;
4101 if (Framerate_delay) {
4102 int start_time = timer_get_milliseconds();
4103 while (timer_get_milliseconds() < start_time + Framerate_delay)
4109 demo_do_frame_start();
4111 mprintf(("Error (%d) while processing demo!\n", Demo_error));
4116 // start timing frame
4117 timing_frame_start();
4119 total_time1 = timer_get_fixed_seconds();
4121 // var to hold which state we are in
4122 actually_playing = game_actually_playing();
4124 if ((!(Game_mode & GM_MULTIPLAYER)) || ((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER))) {
4125 if (!(Game_mode & GM_STANDALONE_SERVER)){
4126 SDL_assert( OBJ_INDEX(Player_obj) >= 0 );
4130 if (Missiontime > Entry_delay_time){
4131 Pre_player_entry = 0;
4133 ; //nprintf(("AI", "Framecount = %i, time = %7.3f\n", Framecount, f2fl(Missiontime)));
4136 // Note: These are done even before the player enters, else buffers can overflow.
4137 if (! (Game_mode & GM_STANDALONE_SERVER)){
4141 shield_frame_init();
4143 if ( Player->control_mode != PCM_NORMAL )
4146 if ( !Pre_player_entry && actually_playing ) {
4147 if (! (Game_mode & GM_STANDALONE_SERVER) ) {
4149 if( (!popup_running_state()) && (!popupdead_is_active()) ){
4150 game_process_keys();
4152 // don't read flying controls if we're playing a demo back
4153 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4154 read_player_controls( Player_obj, flFrametime);
4158 // if we're not the master, we may have to send the server-critical ship status button_info bits
4159 if ((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER)){
4160 multi_maybe_send_ship_status();
4165 // Reset the whack stuff
4168 // These two lines must be outside of Pre_player_entry code,
4169 // otherwise too many lights are added.
4172 if ((Game_mode & GM_MULTIPLAYER) && (Netgame.game_state == NETGAME_STATE_SERVER_TRANSFER)){
4176 game_simulation_frame();
4178 // if not actually in a game play state, then return. This condition could only be true in
4179 // a multiplayer game.
4180 if ( !actually_playing ) {
4181 SDL_assert( Game_mode & GM_MULTIPLAYER );
4185 if (!Pre_player_entry) {
4186 if (! (Game_mode & GM_STANDALONE_SERVER)) {
4187 clear_time1 = timer_get_fixed_seconds();
4188 // clear the screen to black
4190 if ( (Game_detail_flags & DETAIL_FLAG_CLEAR) ) {
4194 clear_time2 = timer_get_fixed_seconds();
4195 render3_time1 = timer_get_fixed_seconds();
4196 game_render_frame_setup(&eye_pos, &eye_orient);
4197 game_render_frame( &eye_pos, &eye_orient );
4199 // save the eye position and orientation
4200 if ( Game_mode & GM_MULTIPLAYER ) {
4201 Net_player->s_info.eye_pos = eye_pos;
4202 Net_player->s_info.eye_orient = eye_orient;
4205 hud_show_target_model();
4207 // check to see if we should display the death died popup
4208 if(Game_mode & GM_DEAD_BLEW_UP){
4209 if(Game_mode & GM_MULTIPLAYER){
4210 // catch the situation where we're supposed to be warping out on this transition
4211 if(Net_player->flags & NETINFO_FLAG_WARPING_OUT){
4212 gameseq_post_event(GS_EVENT_DEBRIEF);
4213 } else if((Player_died_popup_wait != -1) && (timestamp_elapsed(Player_died_popup_wait))){
4214 Player_died_popup_wait = -1;
4218 if((Player_died_popup_wait != -1) && (timestamp_elapsed(Player_died_popup_wait))){
4219 Player_died_popup_wait = -1;
4225 // hack - sometimes this seems to slip by in multiplayer. this should guarantee that we catch it
4226 if((Game_mode & GM_MULTIPLAYER) && (Player_multi_died_check != -1) && (Game_mode & GM_DEAD_BLEW_UP) ){
4227 if(fl_abs(time(NULL) - Player_multi_died_check) > 4){
4228 if(!popupdead_is_active()){
4232 Player_multi_died_check = -1;
4236 render3_time2 = timer_get_fixed_seconds();
4237 render2_time1 = timer_get_fixed_seconds();
4240 game_get_framerate();
4241 game_show_framerate();
4243 game_show_time_left();
4245 // Draw the 2D HUD gauges
4246 if(supernova_active() < 3){
4247 game_render_hud_2d();
4250 game_set_view_clip();
4252 // Draw 3D HUD gauges
4253 game_render_hud_3d(&eye_pos, &eye_orient);
4257 render2_time2 = timer_get_fixed_seconds();
4259 // maybe render and process the dead popup
4260 game_maybe_do_dead_popup(flFrametime);
4262 // start timing frame
4263 timing_frame_stop();
4264 // timing_display(30, 10);
4266 // If a regular popup is active, don't flip (popup code flips)
4267 if( !popup_running_state() ){
4268 flip_time1 = timer_get_fixed_seconds();
4269 game_flip_page_and_time_it();
4270 flip_time2 = timer_get_fixed_seconds();
4274 game_maybe_dump_frame(); // used to dump pcx files for building trailers
4277 game_show_standalone_framerate();
4281 game_do_training_checks();
4284 // process lightning (nebula only)
4287 total_time2 = timer_get_fixed_seconds();
4289 // Got some timing numbers
4290 Timing_total = f2fl( total_time2 - total_time1 ) * 1000.0f;
4291 Timing_clear = f2fl( clear_time2 - clear_time1 ) * 1000.0f;
4292 Timing_render2 = f2fl( render2_time2- render2_time1 ) * 1000.0f;
4293 Timing_render3 = f2fl( render3_time2- render3_time1 ) * 1000.0f;
4294 Timing_flip = f2fl( flip_time2 - flip_time1 ) * 1000.0f;
4297 demo_do_frame_end();
4299 mprintf(("Error (%d) while processing demo!\n", Demo_error));
4305 #define MAX_FRAMETIME (F1_0/4) // Frametime gets saturated at this. Changed by MK on 11/1/97.
4306 // Some bug was causing Frametime to always get saturated at 2.0 seconds after the player
4307 // died. This resulted in screwed up death sequences.
4309 fix Last_time = 0; // The absolute time of game at end of last frame (beginning of this frame)
4310 fix Last_delta_time = 0; // While game is paused, this keeps track of how much elapsed in the frame before paused.
4311 static int timer_paused=0;
4312 #if defined(TIMER_TEST) && !defined(NDEBUG)
4313 static int stop_count,start_count;
4314 static int time_stopped,time_started;
4316 int saved_timestamp_ticker = -1;
4318 void game_reset_time()
4320 if((Game_mode & GM_MULTIPLAYER) && (Netgame.game_state == NETGAME_STATE_SERVER_TRANSFER)){
4324 // Last_time = timer_get_fixed_seconds();
4330 void game_stop_time()
4332 if (timer_paused==0) {
4334 time = timer_get_fixed_seconds();
4335 // Save how much time progressed so far in the frame so we can
4336 // use it when we unpause.
4337 Last_delta_time = time - Last_time;
4339 //mprintf(("Last_time in game_stop_time = %7.3f\n", f2fl(Last_delta_time)));
4340 if (Last_delta_time < 0) {
4341 #if defined(TIMER_TEST) && !defined(NDEBUG)
4342 Int3(); //get Matt!!!!
4344 Last_delta_time = 0;
4346 #if defined(TIMER_TEST) && !defined(NDEBUG)
4347 time_stopped = time;
4350 // Stop the timer_tick stuff...
4351 // Normally, you should never access 'timestamp_ticker', consider this a low-level routine
4352 saved_timestamp_ticker = timestamp_ticker;
4356 #if defined(TIMER_TEST) && !defined(NDEBUG)
4361 void game_start_time()
4364 SDL_assert(timer_paused >= 0);
4365 if (timer_paused==0) {
4367 time = timer_get_fixed_seconds();
4368 #if defined(TIMER_TEST) && !defined(NDEBUG)
4370 Int3(); //get Matt!!!!
4373 // Take current time, and set it backwards to account for time
4374 // that the frame already executed, so that timer_get_fixed_seconds() - Last_time
4375 // will be correct when it goes to calculate the frametime next
4377 Last_time = time - Last_delta_time;
4378 #if defined(TIMER_TEST) && !defined(NDEBUG)
4379 time_started = time;
4382 // Restore the timer_tick stuff...
4383 // Normally, you should never access 'timestamp_ticker', consider this a low-level routine
4384 SDL_assert( saved_timestamp_ticker > -1 ); // Called out of order, get JAS
4385 timestamp_ticker = saved_timestamp_ticker;
4386 saved_timestamp_ticker = -1;
4389 #if defined(TIMER_TEST) && !defined(NDEBUG)
4395 void game_set_frametime(int state)
4398 float frame_cap_diff;
4400 thistime = timer_get_fixed_seconds();
4402 if ( Last_time == 0 )
4403 Frametime = F1_0 / 30;
4405 Frametime = thistime - Last_time;
4407 // Frametime = F1_0 / 30;
4409 fix debug_frametime = Frametime; // Just used to display frametime.
4411 // If player hasn't entered mission yet, make frame take 1/4 second.
4412 if ((Pre_player_entry) && (state == GS_STATE_GAME_PLAY))
4415 else if ((Debug_dump_frames) && (state == GS_STATE_GAME_PLAY)) { // note link to above if!!!!!
4417 fix frame_speed = F1_0 / Debug_dump_frames;
4419 if (Frametime > frame_speed ){
4420 nprintf(("warning","slow frame: %x\n",Frametime));
4423 thistime = timer_get_fixed_seconds();
4424 Frametime = thistime - Last_time;
4425 } while (Frametime < frame_speed );
4427 Frametime = frame_speed;
4431 SDL_assert( Framerate_cap > 0 );
4433 // Cap the framerate so it doesn't get too high.
4437 cap = F1_0/Framerate_cap;
4438 if (Frametime < cap) {
4439 thistime = cap - Frametime;
4440 //mprintf(("Sleeping for %6.3f seconds.\n", f2fl(thistime)));
4441 SDL_Delay( fl2i(f2fl(thistime) * 1000.0f) );
4443 thistime = timer_get_fixed_seconds();
4447 if((Game_mode & GM_STANDALONE_SERVER) &&
4448 (f2fl(Frametime) < (1.0f/(float)Multi_options_g.std_framecap))){
4450 frame_cap_diff = (1.0f/(float)Multi_options_g.std_framecap) - f2fl(Frametime);
4451 SDL_Delay( fl2i(frame_cap_diff * 1000.0f) );
4453 thistime += fl2f((frame_cap_diff));
4455 Frametime = thistime - Last_time;
4458 // If framerate is too low, cap it.
4459 if (Frametime > MAX_FRAMETIME) {
4461 mprintf(("Frame %2i too long!!: frametime = %.3f (%.3f)\n", Framecount, f2fl(Frametime), f2fl(debug_frametime)));
4463 // to remove warnings in release build
4464 debug_frametime = fl2f(flFrametime);
4466 Frametime = MAX_FRAMETIME;
4469 Frametime = fixmul(Frametime, Game_time_compression);
4471 Last_time = thistime;
4472 //mprintf(("Frame %i, Last_time = %7.3f\n", Framecount, f2fl(Last_time)));
4474 flFrametime = f2fl(Frametime);
4475 //if(!(Game_mode & GM_PLAYING_DEMO)){
4476 timestamp_inc(flFrametime);
4478 /* if ((Framecount > 0) && (Framecount < 10)) {
4479 mprintf(("Frame %2i: frametime = %.3f (%.3f)\n", Framecount, f2fl(Frametime), f2fl(debug_frametime)));
4484 // This is called from game_do_frame(), and from navmap_do_frame()
4485 void game_update_missiontime()
4487 // TODO JAS: Put in if and move this into game_set_frametime,
4488 // fix navmap to call game_stop/start_time
4489 //if ( !timer_paused )
4490 Missiontime += Frametime;
4493 void game_do_frame()
4495 game_set_frametime(GS_STATE_GAME_PLAY);
4496 game_update_missiontime();
4498 if (Game_mode & GM_STANDALONE_SERVER) {
4499 std_multi_set_standalone_missiontime(f2fl(Missiontime));
4502 if ( game_single_step && (last_single_step == game_single_step) ) {
4503 os_set_title( NOX("SINGLE STEP MODE (Pause exits, any other key steps)") );
4504 while( key_checkch() == 0 )
4506 os_set_title( XSTR( "FreeSpace", 171) );
4507 Last_time = timer_get_fixed_seconds();
4510 last_single_step = game_single_step;
4512 if ((gameseq_get_state() == GS_STATE_GAME_PLAY) && Use_mouse_to_fly){
4513 Keep_mouse_centered = 1; // force mouse to center of our window (so we don't hit movement limits)
4517 Keep_mouse_centered = 0;
4518 monitor_update(); // Update monitor variables
4521 void multi_maybe_do_frame()
4523 if ( (Game_mode & GM_MULTIPLAYER) && (Game_mode & GM_IN_MISSION) && !Multi_pause_status){
4528 int Joymouse_button_status = 0;
4530 // Flush all input devices
4538 Joymouse_button_status = 0;
4540 //mprintf(("Game flush!\n" ));
4543 // function for multiplayer only which calls game_do_state_common() when running the
4545 void game_do_dc_networking()
4547 SDL_assert( Game_mode & GM_MULTIPLAYER );
4549 game_do_state_common( gameseq_get_state() );
4552 // Call this whenever in a loop, or when you need to check for a keystroke.
4553 int game_check_key()
4559 // convert keypad enter to normal enter
4560 if ((k & KEY_MASK) == SDLK_KP_ENTER)
4561 k = (k & ~KEY_MASK) | SDLK_RETURN;
4566 #if defined(FS2_DEMO) || defined(FS1_DEMO)
4568 #define DEMO_TRAILER_TIMEOUT_MS 45000 // 45 seconds of no input, play trailer
4569 static int Demo_show_trailer_timestamp = 0;
4571 void demo_reset_trailer_timer()
4573 Demo_show_trailer_timestamp = timer_get_milliseconds();
4576 void demo_maybe_show_trailer(int k)
4579 // if key pressed, reset demo trailer timer
4581 demo_reset_trailer_timer();
4585 // if mouse moved, reset demo trailer timer
4588 mouse_get_delta(&dx, &dy);
4589 if ( (dx > 0) || (dy > 0) ) {
4590 demo_reset_trailer_timer();
4594 // if joystick has moved, reset demo trailer timer
4597 joy_get_delta(&dx, &dy);
4598 if ( (dx > 0) || (dy > 0) ) {
4599 demo_reset_trailer_timer();
4603 // NOTE: reseting the trailer timer on mouse/joystick presses is handled in
4604 // the low-level code. Ugly, I know... but was the simplest and most
4607 // if 30 seconds since last demo trailer time reset, launch movie
4608 if ( os_foreground() ) {
4609 int now = timer_get_milliseconds();
4610 if ( (now - Demo_show_trailer_timestamp) > DEMO_TRAILER_TIMEOUT_MS ) {
4611 // if ( (now - Demo_show_trailer_timestamp) > 10000 ) {
4613 movie_play( NOX("fstrailer2.mve") );
4614 demo_reset_trailer_timer();
4622 // same as game_check_key(), except this is used while actually in the game. Since there
4623 // generally are differences between game control keys and general UI keys, makes sense to
4624 // have seperate functions for each case. If you are not checking a game control while in a
4625 // mission, you should probably be using game_check_key() instead.
4630 if (!os_foreground()) {
4635 // If we're in a single player game, pause it.
4636 if (!(Game_mode & GM_MULTIPLAYER)){
4637 if ( (gameseq_get_state() == GS_STATE_GAME_PLAY) && (!popup_active()) && (!popupdead_is_active()) ) {
4638 game_process_pause_key();
4645 #if defined(FS2_DEMO) || defined(FS1_DEMO)
4646 demo_maybe_show_trailer(k);
4649 // Move the mouse cursor with the joystick.
4650 if (os_foreground() && (!Mouse_hidden) && (Use_joy_mouse) ) {
4651 // Move the mouse cursor with the joystick
4655 joy_get_pos( &jx, &jy, &jz, &jr );
4657 dx = fl2i(f2fl(jx)*flFrametime*500.0f);
4658 dy = fl2i(f2fl(jy)*flFrametime*500.0f);
4661 mouse_get_real_pos( &mx, &my );
4662 mouse_set_pos( mx+dx, my+dy );
4667 m = mouse_down(MOUSE_LEFT_BUTTON);
4669 if ( j != Joymouse_button_status ) {
4670 //mprintf(( "Joy went from %d to %d, mouse is %d\n", Joymouse_button_status, j, m ));
4671 Joymouse_button_status = j;
4673 mouse_mark_button( MOUSE_LEFT_BUTTON, 1 );
4674 } else if ( (!j) && (m) ) {
4675 mouse_mark_button( MOUSE_LEFT_BUTTON, 0 );
4680 // if we should be ignoring keys because of some multiplayer situations
4681 if((Game_mode & GM_MULTIPLAYER) && multi_ignore_controls(k)){
4685 // If a popup is running, don't process all the Fn keys
4686 if( popup_active() ) {
4690 state = gameseq_get_state();
4692 // if ( k ) nprintf(( "General", "Key = %x\n", k ));
4695 case KEY_DEBUGGED + SDLK_BACKSPACE:
4700 launch_context_help();
4705 // if (state != GS_STATE_INITIAL_PLAYER_SELECT) {
4707 // don't allow f2 while warping out in multiplayer
4708 if((Game_mode & GM_MULTIPLAYER) && (Net_player != NULL) && (Net_player->flags & NETINFO_FLAG_WARPING_OUT)){
4713 case GS_STATE_INITIAL_PLAYER_SELECT:
4714 case GS_STATE_OPTIONS_MENU:
4715 case GS_STATE_HUD_CONFIG:
4716 case GS_STATE_CONTROL_CONFIG:
4717 case GS_STATE_DEATH_DIED:
4718 case GS_STATE_DEATH_BLEW_UP:
4719 case GS_STATE_VIEW_MEDALS:
4723 gameseq_post_event(GS_EVENT_OPTIONS_MENU);
4730 // hotkey selection screen -- only valid from briefing and beyond.
4732 #if !(defined(FS2_DEMO) || defined(FS1_DEMO))
4733 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) ) {
4734 gameseq_post_event( GS_EVENT_HOTKEY_SCREEN );
4740 case KEY_DEBUGGED + SDLK_F3:
4741 gameseq_post_event( GS_EVENT_TOGGLE_FULLSCREEN );
4744 case KEY_DEBUGGED + SDLK_F4:
4745 gameseq_post_event( GS_EVENT_TOGGLE_GLIDE );
4749 if(Game_mode & GM_MULTIPLAYER){
4750 if((state == GS_STATE_GAME_PLAY) || (state == GS_STATE_MULTI_PAUSED)){
4751 gameseq_post_event( GS_EVENT_MISSION_LOG_SCROLLBACK );
4755 if ((state == GS_STATE_GAME_PLAY) || (state == GS_STATE_DEATH_DIED) || (state == GS_STATE_DEATH_BLEW_UP) || (state == GS_STATE_GAME_PAUSED) ) {
4756 gameseq_post_event( GS_EVENT_MISSION_LOG_SCROLLBACK );
4762 case SDLK_ESCAPE | KEY_SHIFTED:
4763 // make sure to quit properly out of multiplayer
4764 if(Game_mode & GM_MULTIPLAYER){
4765 multi_quit_game(PROMPT_NONE);
4768 gameseq_post_event( GS_EVENT_QUIT_GAME );
4773 case KEY_DEBUGGED + SDLK_p:
4776 case SDLK_PRINTSCREEN:
4778 static int counter = 0;
4783 SDL_snprintf( tmp_name, sizeof(tmp_name), NOX("screen%02d"), counter );
4785 mprintf(( "Dumping screen to '%s'\n", tmp_name ));
4786 gr_print_screen(tmp_name);
4794 case KEY_SHIFTED | SDLK_RETURN: {
4796 #if !defined(NDEBUG)
4798 if ( Game_mode & GM_NORMAL ){
4802 // if we're in multiplayer mode, do some special networking
4803 if(Game_mode & GM_MULTIPLAYER){
4804 debug_console(game_do_dc_networking);
4811 if ( Game_mode & GM_NORMAL )
4825 gameseq_post_event(GS_EVENT_QUIT_GAME);
4828 void apply_physics( float damping, float desired_vel, float initial_vel, float t, float * new_vel, float * delta_pos );
4831 void camera_set_position( vector *pos )
4836 void camera_set_orient( matrix *orient )
4838 Camera_orient = *orient;
4841 void camera_set_velocity( vector *vel, int instantaneous )
4843 Camera_desired_velocity.xyz.x = 0.0f;
4844 Camera_desired_velocity.xyz.y = 0.0f;
4845 Camera_desired_velocity.xyz.z = 0.0f;
4847 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.rvec, vel->xyz.x );
4848 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.uvec, vel->xyz.y );
4849 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.fvec, vel->xyz.z );
4851 if ( instantaneous ) {
4852 Camera_velocity = Camera_desired_velocity;
4860 vector new_vel, delta_pos;
4862 apply_physics( Camera_damping, Camera_desired_velocity.xyz.x, Camera_velocity.xyz.x, flFrametime, &new_vel.xyz.x, &delta_pos.xyz.x );
4863 apply_physics( Camera_damping, Camera_desired_velocity.xyz.y, Camera_velocity.xyz.y, flFrametime, &new_vel.xyz.y, &delta_pos.xyz.y );
4864 apply_physics( Camera_damping, Camera_desired_velocity.xyz.z, Camera_velocity.xyz.z, flFrametime, &new_vel.xyz.z, &delta_pos.xyz.z );
4866 Camera_velocity = new_vel;
4868 // mprintf(( "Camera velocity = %.1f,%.1f, %.1f\n", Camera_velocity.xyz.x, Camera_velocity.xyz.y, Camera_velocity.xyz.z ));
4870 vm_vec_add2( &Camera_pos, &delta_pos );
4872 float ot = Camera_time+0.0f;
4874 Camera_time += flFrametime;
4876 if ( (ot < 0.667f) && ( Camera_time >= 0.667f ) ) {
4879 tmp.xyz.z = 4.739f; // always go this fast forward.
4881 // pick x and y velocities so they are always on a
4882 // circle with a 25 m radius.
4884 float tmp_angle = frand()*PI2;
4886 tmp.xyz.x = 22.0f * (float)sin(tmp_angle);
4887 tmp.xyz.y = -22.0f * (float)cos(tmp_angle);
4889 //mprintf(( "Angle = %.1f, vx=%.1f, vy=%.1f\n", tmp_angle, tmp.xyz.x, tmp.xyz.y ));
4891 //mprintf(( "Changing velocity!\n" ));
4892 camera_set_velocity( &tmp, 0 );
4895 if ( (ot < 3.0f ) && ( Camera_time >= 3.0f ) ) {
4896 vector tmp = ZERO_VECTOR;
4897 camera_set_velocity( &tmp, 0 );
4902 void end_demo_campaign_do()
4904 #if defined(FS2_DEMO) || defined(FS1_DEMO)
4905 // show upsell screens
4906 demo_upsell_show_screens();
4907 #elif defined(OEM_BUILD)
4908 // show oem upsell screens
4909 oem_upsell_show_screens();
4912 // drop into main hall
4913 gameseq_post_event( GS_EVENT_MAIN_MENU );
4916 // All code to process events. This is the only place
4917 // that you should change the state of the game.
4918 void game_process_event( int current_state, int event )
4920 mprintf(("Got event %s in state %s\n", GS_event_text[event], GS_state_text[current_state]));
4923 case GS_EVENT_SIMULATOR_ROOM:
4924 gameseq_set_state(GS_STATE_SIMULATOR_ROOM);
4927 case GS_EVENT_MAIN_MENU:
4928 gameseq_set_state(GS_STATE_MAIN_MENU);
4931 case GS_EVENT_OPTIONS_MENU:
4932 gameseq_push_state( GS_STATE_OPTIONS_MENU );
4935 case GS_EVENT_BARRACKS_MENU:
4936 gameseq_set_state(GS_STATE_BARRACKS_MENU);
4939 case GS_EVENT_TECH_MENU:
4940 gameseq_set_state(GS_STATE_TECH_MENU);
4943 case GS_EVENT_TRAINING_MENU:
4944 gameseq_set_state(GS_STATE_TRAINING_MENU);
4947 case GS_EVENT_START_GAME:
4948 Select_default_ship = 0;
4949 Player_multi_died_check = -1;
4950 gameseq_set_state(GS_STATE_CMD_BRIEF);
4953 case GS_EVENT_START_BRIEFING:
4954 gameseq_set_state(GS_STATE_BRIEFING);
4957 case GS_EVENT_DEBRIEF:
4958 // did we end the campaign in the main freespace 2 single player campaign?
4960 if(Campaign_ended_in_mission && (Game_mode & GM_CAMPAIGN_MODE) && !SDL_strcasecmp(Campaign.filename, "freespace")) {
4962 if(Campaign_ended_in_mission && (Game_mode & GM_CAMPAIGN_MODE) && !SDL_strcasecmp(Campaign.filename, "freespace2")) {
4964 gameseq_post_event(GS_EVENT_END_CAMPAIGN);
4966 gameseq_set_state(GS_STATE_DEBRIEF);
4969 Player_multi_died_check = -1;
4972 case GS_EVENT_SHIP_SELECTION:
4973 gameseq_set_state( GS_STATE_SHIP_SELECT );
4976 case GS_EVENT_WEAPON_SELECTION:
4977 gameseq_set_state( GS_STATE_WEAPON_SELECT );
4980 case GS_EVENT_ENTER_GAME:
4982 // maybe start recording a demo
4984 demo_start_record("test.fsd");
4988 if (Game_mode & GM_MULTIPLAYER) {
4989 // if we're respawning, make sure we change the view mode so that the hud shows up
4990 if (current_state == GS_STATE_DEATH_BLEW_UP) {
4994 gameseq_set_state(GS_STATE_GAME_PLAY);
4996 gameseq_set_state(GS_STATE_GAME_PLAY, 1);
4999 Player_multi_died_check = -1;
5001 // clear multiplayer button info
5002 extern button_info Multi_ship_status_bi;
5003 memset(&Multi_ship_status_bi, 0, sizeof(button_info));
5005 Start_time = f2fl(timer_get_approx_seconds());
5007 mprintf(("Entering game at time = %7.3f\n", Start_time));
5011 case GS_EVENT_START_GAME_QUICK:
5012 Select_default_ship = 1;
5013 gameseq_post_event(GS_EVENT_ENTER_GAME);
5017 case GS_EVENT_END_GAME:
5018 if ( (current_state == GS_STATE_GAME_PLAY) || (current_state == GS_STATE_DEATH_DIED) ||
5019 (current_state == GS_STATE_DEATH_BLEW_UP) || (current_state == GS_STATE_DEBRIEF) || (current_state == GS_STATE_MULTI_DOGFIGHT_DEBRIEF)) {
5020 gameseq_set_state(GS_STATE_MAIN_MENU);
5025 Player_multi_died_check = -1;
5028 case GS_EVENT_QUIT_GAME:
5029 main_hall_stop_music();
5030 main_hall_stop_ambient();
5031 gameseq_set_state(GS_STATE_QUIT_GAME);
5033 Player_multi_died_check = -1;
5036 case GS_EVENT_GAMEPLAY_HELP:
5037 gameseq_push_state( GS_STATE_GAMEPLAY_HELP );
5040 case GS_EVENT_PAUSE_GAME:
5041 gameseq_push_state(GS_STATE_GAME_PAUSED);
5044 case GS_EVENT_DEBUG_PAUSE_GAME:
5045 gameseq_push_state(GS_STATE_DEBUG_PAUSED);
5048 case GS_EVENT_TRAINING_PAUSE:
5049 gameseq_push_state(GS_STATE_TRAINING_PAUSED);
5052 case GS_EVENT_PREVIOUS_STATE:
5053 gameseq_pop_state();
5056 case GS_EVENT_TOGGLE_FULLSCREEN:
5057 gr_toggle_fullscreen();
5060 case GS_EVENT_TOGGLE_GLIDE:
5063 case GS_EVENT_LOAD_MISSION_MENU:
5066 case GS_EVENT_MISSION_LOG_SCROLLBACK:
5067 gameseq_push_state( GS_STATE_MISSION_LOG_SCROLLBACK );
5070 case GS_EVENT_HUD_CONFIG:
5071 gameseq_push_state( GS_STATE_HUD_CONFIG );
5074 case GS_EVENT_CONTROL_CONFIG:
5075 gameseq_push_state( GS_STATE_CONTROL_CONFIG );
5078 case GS_EVENT_DEATH_DIED:
5079 gameseq_set_state( GS_STATE_DEATH_DIED );
5082 case GS_EVENT_DEATH_BLEW_UP:
5083 if ( current_state == GS_STATE_DEATH_DIED ) {
5084 gameseq_set_state( GS_STATE_DEATH_BLEW_UP );
5085 event_music_player_death();
5087 // multiplayer clients set their extra check here
5088 if(Game_mode & GM_MULTIPLAYER){
5089 // set the multi died absolute last chance check
5090 Player_multi_died_check = time(NULL);
5093 mprintf(( "Ignoring GS_EVENT_DEATH_BLEW_UP because we're in state %d\n", current_state ));
5097 case GS_EVENT_NEW_CAMPAIGN:
5098 if (!mission_load_up_campaign()){
5099 readyroom_continue_campaign();
5102 Player_multi_died_check = -1;
5105 case GS_EVENT_CAMPAIGN_CHEAT:
5106 if (!mission_load_up_campaign()){
5108 // bash campaign value
5109 extern char Main_hall_campaign_cheat[512];
5112 // look for the mission
5113 for(idx=0; idx<Campaign.num_missions; idx++){
5114 if(!SDL_strcasecmp(Campaign.missions[idx].name, Main_hall_campaign_cheat)){
5115 Campaign.next_mission = idx;
5116 Campaign.prev_mission = idx - 1;
5123 readyroom_continue_campaign();
5126 Player_multi_died_check = -1;
5129 case GS_EVENT_CAMPAIGN_ROOM:
5130 gameseq_set_state(GS_STATE_CAMPAIGN_ROOM);
5133 case GS_EVENT_CMD_BRIEF:
5134 gameseq_set_state(GS_STATE_CMD_BRIEF);
5137 case GS_EVENT_RED_ALERT:
5138 gameseq_set_state(GS_STATE_RED_ALERT);
5141 case GS_EVENT_CREDITS:
5142 gameseq_set_state( GS_STATE_CREDITS );
5145 case GS_EVENT_VIEW_MEDALS:
5146 gameseq_push_state( GS_STATE_VIEW_MEDALS );
5149 case GS_EVENT_SHOW_GOALS:
5150 gameseq_push_state( GS_STATE_SHOW_GOALS ); // use push_state() since we might get to this screen through a variety of states
5153 case GS_EVENT_HOTKEY_SCREEN:
5154 gameseq_push_state( GS_STATE_HOTKEY_SCREEN ); // use push_state() since we might get to this screen through a variety of states
5157 // multiplayer stuff follow these comments
5159 case GS_EVENT_MULTI_JOIN_GAME:
5160 gameseq_set_state( GS_STATE_MULTI_JOIN_GAME );
5163 case GS_EVENT_MULTI_HOST_SETUP:
5164 gameseq_set_state( GS_STATE_MULTI_HOST_SETUP );
5167 case GS_EVENT_MULTI_CLIENT_SETUP:
5168 gameseq_set_state( GS_STATE_MULTI_CLIENT_SETUP );
5171 case GS_EVENT_GOTO_VIEW_CUTSCENES_SCREEN:
5172 gameseq_set_state(GS_STATE_VIEW_CUTSCENES);
5175 case GS_EVENT_MULTI_STD_WAIT:
5176 gameseq_set_state( GS_STATE_MULTI_STD_WAIT );
5179 case GS_EVENT_STANDALONE_MAIN:
5180 gameseq_set_state( GS_STATE_STANDALONE_MAIN );
5183 case GS_EVENT_MULTI_PAUSE:
5184 gameseq_push_state( GS_STATE_MULTI_PAUSED );
5187 case GS_EVENT_INGAME_PRE_JOIN:
5188 gameseq_set_state( GS_STATE_INGAME_PRE_JOIN );
5191 case GS_EVENT_EVENT_DEBUG:
5192 gameseq_push_state(GS_STATE_EVENT_DEBUG);
5195 // Start a warpout where player automatically goes 70 no matter what
5196 // and can't cancel out of it.
5197 case GS_EVENT_PLAYER_WARPOUT_START_FORCED:
5198 Warpout_forced = 1; // If non-zero, bash the player to speed and go through effect
5200 // Same code as in GS_EVENT_PLAYER_WARPOUT_START only ignores current mode
5201 Player->saved_viewer_mode = Viewer_mode;
5202 Player->control_mode = PCM_WARPOUT_STAGE1;
5203 Warpout_sound = snd_play(&Snds[SND_PLAYER_WARP_OUT]);
5204 Warpout_time = 0.0f; // Start timer!
5207 case GS_EVENT_PLAYER_WARPOUT_START:
5208 if ( Player->control_mode != PCM_NORMAL ) {
5209 mprintf(( "Player isn't in normal mode; cannot warp out.\n" ));
5211 Player->saved_viewer_mode = Viewer_mode;
5212 Player->control_mode = PCM_WARPOUT_STAGE1;
5213 Warpout_sound = snd_play(&Snds[SND_PLAYER_WARP_OUT]);
5214 Warpout_time = 0.0f; // Start timer!
5215 Warpout_forced = 0; // If non-zero, bash the player to speed and go through effect
5219 case GS_EVENT_PLAYER_WARPOUT_STOP:
5220 if ( Player->control_mode != PCM_NORMAL ) {
5221 if ( !Warpout_forced ) { // cannot cancel forced warpout
5222 Player->control_mode = PCM_NORMAL;
5223 Viewer_mode = Player->saved_viewer_mode;
5224 hud_subspace_notify_abort();
5225 mprintf(( "Player put back to normal mode.\n" ));
5226 if ( Warpout_sound > -1 ) {
5227 snd_stop( Warpout_sound );
5234 case GS_EVENT_PLAYER_WARPOUT_DONE_STAGE1: // player ship got up to speed
5235 if ( Player->control_mode != PCM_WARPOUT_STAGE1 ) {
5236 gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_STOP );
5237 mprintf(( "Player put back to normal mode, because of invalid sequence in stage1.\n" ));
5239 mprintf(( "Hit target speed. Starting warp effect and moving to stage 2!\n" ));
5240 shipfx_warpout_start( Player_obj );
5241 Player->control_mode = PCM_WARPOUT_STAGE2;
5242 Player->saved_viewer_mode = Viewer_mode;
5243 Viewer_mode |= VM_WARP_CHASE;
5245 vector tmp = Player_obj->pos;
5247 ship_get_eye( &tmp, &tmp_m, Player_obj );
5248 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.rvec, 0.0f );
5249 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.uvec, 0.952f );
5250 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.fvec, -1.782f );
5252 camera_set_position( &tmp );
5253 camera_set_orient( &Player_obj->orient );
5254 vector tmp_vel = { { { 0.0f, 5.1919f, 14.7f } } };
5256 //mprintf(( "Rad = %.1f\n", Player_obj->radius ));
5257 camera_set_velocity( &tmp_vel, 1);
5261 case GS_EVENT_PLAYER_WARPOUT_DONE_STAGE2: // player ship got into the warp effect
5262 if ( Player->control_mode != PCM_WARPOUT_STAGE2 ) {
5263 gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_STOP );
5264 mprintf(( "Player put back to normal mode, because of invalid sequence in stage2.\n" ));
5266 mprintf(( "Hit warp effect. Moving to stage 3!\n" ));
5267 Player->control_mode = PCM_WARPOUT_STAGE3;
5271 case GS_EVENT_PLAYER_WARPOUT_DONE: // player ship got through the warp effect
5272 mprintf(( "Player warped out. Going to debriefing!\n" ));
5273 Player->control_mode = PCM_NORMAL;
5274 Viewer_mode = Player->saved_viewer_mode;
5277 // we have a special debriefing screen for multiplayer furballs
5278 if((Game_mode & GM_MULTIPLAYER) && (The_mission.game_type & MISSION_TYPE_MULTI_DOGFIGHT)){
5279 gameseq_post_event(GS_EVENT_MULTI_DOGFIGHT_DEBRIEF);
5281 // do the normal debriefing for all other situations
5283 gameseq_post_event(GS_EVENT_DEBRIEF);
5287 case GS_EVENT_STANDALONE_POSTGAME:
5288 gameseq_set_state(GS_STATE_STANDALONE_POSTGAME);
5291 case GS_EVENT_INITIAL_PLAYER_SELECT:
5292 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5295 case GS_EVENT_GAME_INIT:
5296 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
5297 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5299 // see if the command line option has been set to use the last pilot, and act acoordingly
5300 if( player_select_get_last_pilot() ) {
5301 // always enter the main menu -- do the automatic network startup stuff elsewhere
5302 // so that we still have valid checks for networking modes, etc.
5303 gameseq_set_state(GS_STATE_MAIN_MENU);
5305 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5310 case GS_EVENT_MULTI_MISSION_SYNC:
5311 gameseq_set_state(GS_STATE_MULTI_MISSION_SYNC);
5314 case GS_EVENT_MULTI_START_GAME:
5315 gameseq_set_state(GS_STATE_MULTI_START_GAME);
5318 case GS_EVENT_MULTI_HOST_OPTIONS:
5319 gameseq_set_state(GS_STATE_MULTI_HOST_OPTIONS);
5322 case GS_EVENT_MULTI_DOGFIGHT_DEBRIEF:
5323 gameseq_set_state(GS_STATE_MULTI_DOGFIGHT_DEBRIEF);
5326 case GS_EVENT_TEAM_SELECT:
5327 gameseq_set_state(GS_STATE_TEAM_SELECT);
5330 case GS_EVENT_END_CAMPAIGN:
5331 gameseq_set_state(GS_STATE_END_OF_CAMPAIGN);
5334 case GS_EVENT_END_DEMO:
5335 gameseq_set_state(GS_STATE_END_DEMO);
5338 case GS_EVENT_LOOP_BRIEF:
5339 gameseq_set_state(GS_STATE_LOOP_BRIEF);
5348 // Called when a state is being left.
5349 // The current state is still at old_state, but as soon as
5350 // this function leaves, then the current state will become
5351 // new state. You should never try to change the state
5352 // in here... if you think you need to, you probably really
5353 // need to post an event, not change the state.
5354 void game_leave_state( int old_state, int new_state )
5356 int end_mission = 1;
5358 switch (new_state) {
5359 case GS_STATE_GAME_PAUSED:
5360 case GS_STATE_DEBUG_PAUSED:
5361 case GS_STATE_OPTIONS_MENU:
5362 case GS_STATE_CONTROL_CONFIG:
5363 case GS_STATE_MISSION_LOG_SCROLLBACK:
5364 case GS_STATE_DEATH_DIED:
5365 case GS_STATE_SHOW_GOALS:
5366 case GS_STATE_HOTKEY_SCREEN:
5367 case GS_STATE_MULTI_PAUSED:
5368 case GS_STATE_TRAINING_PAUSED:
5369 case GS_STATE_EVENT_DEBUG:
5370 case GS_STATE_GAMEPLAY_HELP:
5371 end_mission = 0; // these events shouldn't end a mission
5375 switch (old_state) {
5376 case GS_STATE_BRIEFING:
5377 brief_stop_voices();
5378 if ( (new_state != GS_STATE_OPTIONS_MENU) && (new_state != GS_STATE_WEAPON_SELECT)
5379 && (new_state != GS_STATE_SHIP_SELECT) && (new_state != GS_STATE_HOTKEY_SCREEN)
5380 && (new_state != GS_STATE_TEAM_SELECT) ){
5381 common_select_close();
5382 if ( new_state == GS_STATE_MAIN_MENU ) {
5383 freespace_stop_mission();
5387 // COMMAND LINE OPTION
5388 if (Cmdline_multi_stream_chat_to_file){
5389 cfwrite_string(NOX("-------------------------------------------\n"),Multi_chat_stream);
5390 cfclose(Multi_chat_stream);
5394 case GS_STATE_DEBRIEF:
5395 if ( (new_state != GS_STATE_VIEW_MEDALS) && (new_state != GS_STATE_OPTIONS_MENU) ) {
5400 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
5401 multi_df_debrief_close();
5404 case GS_STATE_LOAD_MISSION_MENU:
5407 case GS_STATE_SIMULATOR_ROOM:
5411 case GS_STATE_CAMPAIGN_ROOM:
5412 campaign_room_close();
5415 case GS_STATE_CMD_BRIEF:
5416 if (new_state == GS_STATE_OPTIONS_MENU) {
5421 if (new_state == GS_STATE_MAIN_MENU)
5422 freespace_stop_mission();
5427 case GS_STATE_RED_ALERT:
5431 case GS_STATE_SHIP_SELECT:
5432 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_WEAPON_SELECT &&
5433 new_state != GS_STATE_HOTKEY_SCREEN &&
5434 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_TEAM_SELECT) {
5435 common_select_close();
5436 if ( new_state == GS_STATE_MAIN_MENU ) {
5437 freespace_stop_mission();
5442 case GS_STATE_WEAPON_SELECT:
5443 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_SHIP_SELECT &&
5444 new_state != GS_STATE_HOTKEY_SCREEN &&
5445 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_TEAM_SELECT) {
5446 common_select_close();
5447 if ( new_state == GS_STATE_MAIN_MENU ) {
5448 freespace_stop_mission();
5453 case GS_STATE_TEAM_SELECT:
5454 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_SHIP_SELECT &&
5455 new_state != GS_STATE_HOTKEY_SCREEN &&
5456 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_WEAPON_SELECT) {
5457 common_select_close();
5458 if ( new_state == GS_STATE_MAIN_MENU ) {
5459 freespace_stop_mission();
5464 case GS_STATE_MAIN_MENU:
5465 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
5472 case GS_STATE_OPTIONS_MENU:
5473 //game_start_time();
5474 if(new_state == GS_STATE_MULTI_JOIN_GAME){
5475 multi_join_clear_game_list();
5477 options_menu_close();
5480 case GS_STATE_BARRACKS_MENU:
5481 if(new_state != GS_STATE_VIEW_MEDALS){
5486 case GS_STATE_MISSION_LOG_SCROLLBACK:
5487 hud_scrollback_close();
5490 case GS_STATE_TRAINING_MENU:
5491 training_menu_close();
5494 case GS_STATE_GAME_PLAY:
5495 if ( !(Game_mode & GM_STANDALONE_SERVER) ) {
5496 player_save_target_and_weapon_link_prefs();
5497 game_stop_looped_sounds();
5500 sound_env_disable();
5501 joy_ff_stop_effects();
5503 // stop game time under certain conditions
5504 if ( end_mission || (Game_mode & GM_NORMAL) || ((Game_mode & GM_MULTIPLAYER) && (new_state == GS_STATE_MULTI_PAUSED)) ){
5509 // shut down any recording or playing demos
5514 // when in multiplayer and going back to the main menu, send a leave game packet
5515 // right away (before calling stop mission). stop_mission was taking to long to
5516 // close mission down and I want people to get notified ASAP.
5517 if ( (Game_mode & GM_MULTIPLAYER) && (new_state == GS_STATE_MAIN_MENU) ){
5518 multi_quit_game(PROMPT_NONE);
5521 freespace_stop_mission();
5522 Game_time_compression = F1_0;
5526 case GS_STATE_TECH_MENU:
5530 case GS_STATE_TRAINING_PAUSED:
5531 Training_num_lines = 0;
5532 // fall through to GS_STATE_GAME_PAUSED
5534 case GS_STATE_GAME_PAUSED:
5536 if ( end_mission ) {
5541 case GS_STATE_DEBUG_PAUSED:
5544 pause_debug_close();
5548 case GS_STATE_HUD_CONFIG:
5552 // join/start a game
5553 case GS_STATE_MULTI_JOIN_GAME:
5554 if(new_state != GS_STATE_OPTIONS_MENU){
5555 multi_join_game_close();
5559 case GS_STATE_MULTI_HOST_SETUP:
5560 case GS_STATE_MULTI_CLIENT_SETUP:
5561 // if this is just the host going into the options screen, don't do anything
5562 if((new_state == GS_STATE_MULTI_HOST_OPTIONS) || (new_state == GS_STATE_OPTIONS_MENU)){
5566 // close down the proper state
5567 if(old_state == GS_STATE_MULTI_HOST_SETUP){
5568 multi_create_game_close();
5570 multi_game_client_setup_close();
5573 // COMMAND LINE OPTION
5574 if (Cmdline_multi_stream_chat_to_file){
5575 if( (new_state != GS_STATE_TEAM_SELECT) && (Multi_chat_stream!=NULL) ) {
5576 cfwrite_string(NOX("-------------------------------------------\n"),Multi_chat_stream);
5577 cfclose(Multi_chat_stream);
5582 case GS_STATE_CONTROL_CONFIG:
5583 control_config_close();
5586 case GS_STATE_DEATH_DIED:
5587 Game_mode &= ~GM_DEAD_DIED;
5589 // early end while respawning or blowing up in a multiplayer game
5590 if((Game_mode & GM_MULTIPLAYER) && ((new_state == GS_STATE_DEBRIEF) || (new_state == GS_STATE_MULTI_DOGFIGHT_DEBRIEF)) ){
5592 freespace_stop_mission();
5596 case GS_STATE_DEATH_BLEW_UP:
5597 Game_mode &= ~GM_DEAD_BLEW_UP;
5599 // for single player, we might reload mission, etc. For multiplayer, look at my new state
5600 // to determine if I should do anything.
5601 if ( !(Game_mode & GM_MULTIPLAYER) ) {
5603 freespace_stop_mission();
5606 // if we are not respawing as an observer or as a player, our new state will not
5607 // be gameplay state.
5608 if ( (new_state != GS_STATE_GAME_PLAY) && (new_state != GS_STATE_MULTI_PAUSED) ) {
5609 game_stop_time(); // hasn't been called yet!!
5610 freespace_stop_mission();
5616 case GS_STATE_CREDITS:
5620 case GS_STATE_VIEW_MEDALS:
5624 case GS_STATE_SHOW_GOALS:
5625 mission_show_goals_close();
5628 case GS_STATE_HOTKEY_SCREEN:
5629 if ( new_state != GS_STATE_OPTIONS_MENU ) {
5630 mission_hotkey_close();
5634 case GS_STATE_MULTI_MISSION_SYNC:
5635 // if we're moving into the options menu, don't do anything
5636 if(new_state == GS_STATE_OPTIONS_MENU){
5640 SDL_assert( Game_mode & GM_MULTIPLAYER );
5642 if ( new_state == GS_STATE_GAME_PLAY ){
5643 // palette_restore_palette();
5645 // change a couple of flags to indicate our state!!!
5646 Net_player->state = NETPLAYER_STATE_IN_MISSION;
5647 send_netplayer_update_packet();
5649 // set the game mode
5650 Game_mode |= GM_IN_MISSION;
5654 case GS_STATE_VIEW_CUTSCENES:
5655 cutscenes_screen_close();
5658 case GS_STATE_MULTI_STD_WAIT:
5659 multi_standalone_wait_close();
5662 case GS_STATE_STANDALONE_MAIN:
5663 standalone_main_close();
5664 if(new_state == GS_STATE_MULTI_STD_WAIT){
5665 init_multiplayer_stats();
5669 case GS_STATE_MULTI_PAUSED:
5670 // if ( end_mission ){
5675 case GS_STATE_INGAME_PRE_JOIN:
5676 multi_ingame_select_close();
5679 case GS_STATE_STANDALONE_POSTGAME:
5680 multi_standalone_postgame_close();
5683 case GS_STATE_INITIAL_PLAYER_SELECT:
5684 player_select_close();
5687 case GS_STATE_MULTI_START_GAME:
5688 multi_start_game_close();
5691 case GS_STATE_MULTI_HOST_OPTIONS:
5692 multi_host_options_close();
5695 case GS_STATE_END_OF_CAMPAIGN:
5696 mission_campaign_end_close();
5699 case GS_STATE_LOOP_BRIEF:
5705 // Called when a state is being entered.
5706 // The current state is set to the state we're entering at
5707 // this point, and old_state is set to the state we're coming
5708 // from. You should never try to change the state
5709 // in here... if you think you need to, you probably really
5710 // need to post an event, not change the state.
5712 void game_enter_state( int old_state, int new_state )
5714 switch (new_state) {
5715 case GS_STATE_MAIN_MENU:
5716 // in multiplayer mode, be sure that we are not doing networking anymore.
5717 if ( Game_mode & GM_MULTIPLAYER ) {
5718 SDL_assert( Net_player != NULL );
5719 Net_player->flags &= ~NETINFO_FLAG_DO_NETWORKING;
5722 Game_time_compression = F1_0;
5724 // determine which ship this guy is currently based on
5725 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
5728 if (Player->on_bastion) {
5736 case GS_STATE_BRIEFING:
5737 main_hall_stop_music();
5738 main_hall_stop_ambient();
5740 if (Game_mode & GM_NORMAL) {
5741 // AL: Don't call freespace_start_mission() if re-entering from ship or weapon select
5742 // MWA: or from options or hotkey screens
5743 // JH: or if the command brief state already did this
5744 if ( (old_state != GS_STATE_OPTIONS_MENU) && (old_state != GS_STATE_HOTKEY_SCREEN)
5745 && (old_state != GS_STATE_SHIP_SELECT) && (old_state != GS_STATE_WEAPON_SELECT)
5746 && (old_state != GS_STATE_CMD_BRIEF) ) {
5747 if ( !game_start_mission() ) // this should put us into a new state on failure!
5751 // maybe play a movie before the briefing. don't play if entering briefing screen from ship or weapon select.
5752 if ( (old_state == GS_STATE_DEBRIEF) || (old_state == GS_STATE_SIMULATOR_ROOM) || (old_state == GS_STATE_MAIN_MENU))
5753 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
5755 Game_time_compression = F1_0;
5757 if ( red_alert_mission() ) {
5758 gameseq_post_event(GS_EVENT_RED_ALERT);
5765 case GS_STATE_DEBRIEF:
5766 game_stop_looped_sounds();
5767 mission_goal_fail_incomplete(); // fail all incomplete goals before entering debriefing
5768 if ( (old_state != GS_STATE_VIEW_MEDALS) && (old_state != GS_STATE_OPTIONS_MENU) ){
5773 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
5774 multi_df_debrief_init();
5777 case GS_STATE_LOAD_MISSION_MENU:
5780 case GS_STATE_SIMULATOR_ROOM:
5784 case GS_STATE_CAMPAIGN_ROOM:
5785 campaign_room_init();
5788 case GS_STATE_RED_ALERT:
5789 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
5793 case GS_STATE_CMD_BRIEF: {
5794 int team_num = 0; // team number used as index for which cmd brief to use.
5796 if (old_state == GS_STATE_OPTIONS_MENU) {
5800 main_hall_stop_music();
5801 main_hall_stop_ambient();
5803 if (Game_mode & GM_NORMAL) {
5804 // AL: Don't call freespace_start_mission() if re-entering from ship or weapon select
5805 // MWA: or from options or hotkey screens
5806 // JH: or if the command brief state already did this
5807 if ( (old_state != GS_STATE_OPTIONS_MENU) && (old_state != GS_STATE_HOTKEY_SCREEN)
5808 && (old_state != GS_STATE_SHIP_SELECT) && (old_state != GS_STATE_WEAPON_SELECT) ) {
5809 if ( !game_start_mission() ) // this should put us into a new state on failure!
5814 // maybe play a movie before the briefing. don't play if entering briefing screen from ship or weapon select.
5815 if ( (old_state == GS_STATE_DEBRIEF) || (old_state == GS_STATE_SIMULATOR_ROOM) || (old_state == GS_STATE_MAIN_MENU))
5816 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
5818 cmd_brief_init(team_num);
5824 case GS_STATE_SHIP_SELECT:
5828 case GS_STATE_WEAPON_SELECT:
5829 weapon_select_init();
5832 case GS_STATE_TEAM_SELECT:
5836 case GS_STATE_GAME_PAUSED:
5841 case GS_STATE_DEBUG_PAUSED:
5842 // game_stop_time();
5843 // os_set_title("FreeSpace - PAUSED");
5846 case GS_STATE_TRAINING_PAUSED:
5853 case GS_STATE_OPTIONS_MENU:
5855 options_menu_init();
5858 case GS_STATE_GAME_PLAY:
5859 // coming from the gameplay state or the main menu, we might need to load the mission
5860 if ( (Game_mode & GM_NORMAL) && ((old_state == GS_STATE_MAIN_MENU) || (old_state == GS_STATE_GAME_PLAY) || (old_state == GS_STATE_DEATH_BLEW_UP)) ) {
5861 if ( !game_start_mission() ) // this should put us into a new state.
5866 // if we are coming from the briefing, ship select, weapons loadout, or main menu (in the
5867 // case of quick start), then do bitmap loads, etc Don't do any of the loading stuff
5868 // if we are in multiplayer -- this stuff is all handled in the multi-wait section
5869 if ( !(Game_mode & GM_MULTIPLAYER) && ((old_state == GS_STATE_BRIEFING) || (old_state == GS_STATE_SHIP_SELECT) ||
5870 (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)) ) {
5871 // JAS: Used to do all paging here.
5875 HUD_printf("Skill level is set to ** %s **", Skill_level_names(Game_skill_level));
5879 main_hall_stop_music();
5880 main_hall_stop_ambient();
5881 event_music_first_pattern(); // start the first pattern
5884 // special code that restores player ship selection and weapons loadout when doing a quick start
5885 if ( !(Game_mode & GM_MULTIPLAYER) && ((old_state == GS_STATE_MAIN_MENU) || (old_state == GS_STATE_DEATH_BLEW_UP) || (old_state == GS_STATE_GAME_PLAY)) ) {
5886 if ( !SDL_strcasecmp(Player_loadout.filename, Game_current_mission_filename) ) {
5887 wss_direct_restore_loadout();
5891 // single-player, quick-start after just died... we need to set weapon linking and kick off the event music
5892 if (!(Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_DEATH_BLEW_UP) ) {
5893 event_music_first_pattern(); // start the first pattern
5896 if ( !(Game_mode & GM_STANDALONE_SERVER) && (old_state != GS_STATE_GAME_PAUSED) && (old_state != GS_STATE_MULTI_PAUSED) ) {
5897 event_music_first_pattern(); // start the first pattern
5899 player_restore_target_and_weapon_link_prefs();
5901 Game_mode |= GM_IN_MISSION;
5904 // required to truely make mouse deltas zeroed in debug mouse code
5905 void mouse_force_pos(int x, int y);
5906 if (!Is_standalone) {
5907 mouse_force_pos(gr_screen.max_w / 2, gr_screen.max_h / 2);
5913 // only start time if in single player, or coming from multi wait state
5916 (Game_mode & GM_NORMAL) &&
5917 (old_state != GS_STATE_VIEW_CUTSCENES)
5919 (Game_mode & GM_MULTIPLAYER) && (
5920 (old_state == GS_STATE_MULTI_PAUSED) ||
5921 (old_state == GS_STATE_MULTI_MISSION_SYNC)
5927 // when coming from the multi paused state, reset the timestamps
5928 if ( (Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_MULTI_PAUSED) ){
5929 multi_reset_timestamps();
5932 if ((Game_mode & GM_MULTIPLAYER) && (old_state != GS_STATE_DEATH_BLEW_UP) ) {
5933 // initialize all object update details
5934 multi_oo_gameplay_init();
5937 // under certain circumstances, the server should reset the object update rate limiting stuff
5938 if( ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)) &&
5939 ((old_state == GS_STATE_MULTI_PAUSED) || (old_state == GS_STATE_MULTI_MISSION_SYNC)) ){
5941 // reinitialize the rate limiting system for all clients
5942 multi_oo_rate_init_all();
5945 // multiplayer clients should always re-initialize their control info rate limiting system
5946 if((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER)){
5947 multi_oo_rate_init_all();
5951 if(Game_mode & GM_MULTIPLAYER){
5952 multi_ping_reset_players();
5955 Game_subspace_effect = 0;
5956 if (The_mission.flags & MISSION_FLAG_SUBSPACE) {
5957 Game_subspace_effect = 1;
5958 if( !(Game_mode & GM_STANDALONE_SERVER) ){
5959 game_start_subspace_ambient_sound();
5963 sound_env_set(&Game_sound_env);
5964 joy_ff_mission_init(Ship_info[Player_ship->ship_info_index].rotation_time);
5966 // clear multiplayer button info i
5967 extern button_info Multi_ship_status_bi;
5968 memset(&Multi_ship_status_bi, 0, sizeof(button_info));
5971 case GS_STATE_HUD_CONFIG:
5975 case GS_STATE_MULTI_JOIN_GAME:
5976 multi_join_clear_game_list();
5978 if (old_state != GS_STATE_OPTIONS_MENU) {
5979 multi_join_game_init();
5984 case GS_STATE_MULTI_HOST_SETUP:
5985 // don't reinitialize if we're coming back from the host options screen
5986 if ((old_state != GS_STATE_MULTI_HOST_OPTIONS) && (old_state != GS_STATE_OPTIONS_MENU)) {
5987 multi_create_game_init();
5992 case GS_STATE_MULTI_CLIENT_SETUP:
5993 if (old_state != GS_STATE_OPTIONS_MENU) {
5994 multi_game_client_setup_init();
5999 case GS_STATE_CONTROL_CONFIG:
6000 control_config_init();
6003 case GS_STATE_TECH_MENU:
6007 case GS_STATE_BARRACKS_MENU:
6008 if(old_state != GS_STATE_VIEW_MEDALS){
6013 case GS_STATE_MISSION_LOG_SCROLLBACK:
6014 hud_scrollback_init();
6017 case GS_STATE_DEATH_DIED:
6018 Player_died_time = timestamp(10);
6020 if(!(Game_mode & GM_MULTIPLAYER)){
6021 player_show_death_message();
6023 Game_mode |= GM_DEAD_DIED;
6026 case GS_STATE_DEATH_BLEW_UP:
6027 if ( !popupdead_is_active() ) {
6028 Player_ai->target_objnum = -1;
6031 // stop any local EMP effect
6034 Players[Player_num].flags &= ~PLAYER_FLAGS_AUTO_TARGETING; // Prevent immediate switch to a hostile ship.
6035 Game_mode |= GM_DEAD_BLEW_UP;
6036 Show_viewing_from_self = 0;
6038 // timestamp how long we should wait before displaying the died popup
6039 if ( !popupdead_is_active() ) {
6040 Player_died_popup_wait = timestamp(PLAYER_DIED_POPUP_WAIT);
6044 case GS_STATE_GAMEPLAY_HELP:
6045 gameplay_help_init();
6048 case GS_STATE_CREDITS:
6049 main_hall_stop_music();
6050 main_hall_stop_ambient();
6054 case GS_STATE_VIEW_MEDALS:
6055 medal_main_init(Player);
6058 case GS_STATE_SHOW_GOALS:
6059 mission_show_goals_init();
6062 case GS_STATE_HOTKEY_SCREEN:
6063 mission_hotkey_init();
6066 case GS_STATE_MULTI_MISSION_SYNC:
6067 // if we're coming from the options screen, don't do any
6068 if(old_state == GS_STATE_OPTIONS_MENU){
6072 switch(Multi_sync_mode){
6073 case MULTI_SYNC_PRE_BRIEFING:
6074 // if moving from game forming to the team select state
6077 case MULTI_SYNC_POST_BRIEFING:
6078 // if moving from briefing into the mission itself
6081 // tell everyone that we're now loading data
6082 Net_player->state = NETPLAYER_STATE_DATA_LOAD;
6083 send_netplayer_update_packet();
6085 // JAS: Used to do all paging here!!!!
6087 Net_player->state = NETPLAYER_STATE_WAITING;
6088 send_netplayer_update_packet();
6090 Game_time_compression = F1_0;
6092 case MULTI_SYNC_INGAME:
6098 case GS_STATE_VIEW_CUTSCENES:
6099 cutscenes_screen_init();
6102 case GS_STATE_MULTI_STD_WAIT:
6103 multi_standalone_wait_init();
6106 case GS_STATE_STANDALONE_MAIN:
6107 // don't initialize if we're coming from one of these 2 states unless there are no
6108 // players left (reset situation)
6109 if((old_state != GS_STATE_STANDALONE_POSTGAME) || multi_endgame_ending()){
6110 standalone_main_init();
6114 case GS_STATE_MULTI_PAUSED:
6118 case GS_STATE_INGAME_PRE_JOIN:
6119 multi_ingame_select_init();
6122 case GS_STATE_STANDALONE_POSTGAME:
6123 multi_standalone_postgame_init();
6126 case GS_STATE_INITIAL_PLAYER_SELECT:
6127 player_select_init();
6130 case GS_STATE_MULTI_START_GAME:
6131 multi_start_game_init();
6134 case GS_STATE_MULTI_HOST_OPTIONS:
6135 multi_host_options_init();
6138 case GS_STATE_END_OF_CAMPAIGN:
6139 mission_campaign_end_init();
6142 case GS_STATE_LOOP_BRIEF:
6149 // do stuff that may need to be done regardless of state
6150 void game_do_state_common(int state,int no_networking)
6152 game_maybe_draw_mouse(flFrametime); // determine if to draw the mouse this frame
6153 snd_do_frame(); // update sound system
6154 event_music_do_frame(); // music needs to play across many states
6156 multi_log_process();
6158 if (no_networking) {
6162 // maybe do a multiplayer frame based on game mode and state type
6163 if (Game_mode & GM_MULTIPLAYER) {
6165 case GS_STATE_OPTIONS_MENU:
6166 case GS_STATE_GAMEPLAY_HELP:
6167 case GS_STATE_HOTKEY_SCREEN:
6168 case GS_STATE_HUD_CONFIG:
6169 case GS_STATE_CONTROL_CONFIG:
6170 case GS_STATE_MISSION_LOG_SCROLLBACK:
6171 case GS_STATE_SHOW_GOALS:
6172 case GS_STATE_VIEW_CUTSCENES:
6173 case GS_STATE_EVENT_DEBUG:
6174 multi_maybe_do_frame();
6178 game_do_networking();
6182 // Called once a frame.
6183 // You should never try to change the state
6184 // in here... if you think you need to, you probably really
6185 // need to post an event, not change the state.
6186 int Game_do_state_should_skip = 0;
6187 void game_do_state(int state)
6189 // always lets the do_state_common() function determine if the state should be skipped
6190 Game_do_state_should_skip = 0;
6192 // legal to set the should skip state anywhere in this function
6193 game_do_state_common(state); // do stuff that may need to be done regardless of state
6195 if(Game_do_state_should_skip){
6200 case GS_STATE_MAIN_MENU:
6201 game_set_frametime(GS_STATE_MAIN_MENU);
6202 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
6205 main_hall_do(flFrametime);
6209 case GS_STATE_OPTIONS_MENU:
6210 game_set_frametime(GS_STATE_OPTIONS_MENU);
6211 options_menu_do_frame(flFrametime);
6214 case GS_STATE_BARRACKS_MENU:
6215 game_set_frametime(GS_STATE_BARRACKS_MENU);
6216 barracks_do_frame(flFrametime);
6219 case GS_STATE_TRAINING_MENU:
6220 game_set_frametime(GS_STATE_TRAINING_MENU);
6221 training_menu_do_frame(flFrametime);
6224 case GS_STATE_TECH_MENU:
6225 game_set_frametime(GS_STATE_TECH_MENU);
6226 techroom_do_frame(flFrametime);
6229 case GS_STATE_GAMEPLAY_HELP:
6230 game_set_frametime(GS_STATE_GAMEPLAY_HELP);
6231 gameplay_help_do_frame(flFrametime);
6234 case GS_STATE_GAME_PLAY: // do stuff that should be done during gameplay
6238 case GS_STATE_GAME_PAUSED:
6242 case GS_STATE_DEBUG_PAUSED:
6244 game_set_frametime(GS_STATE_DEBUG_PAUSED);
6249 case GS_STATE_TRAINING_PAUSED:
6250 game_training_pause_do();
6253 case GS_STATE_LOAD_MISSION_MENU:
6257 case GS_STATE_BRIEFING:
6258 game_set_frametime(GS_STATE_BRIEFING);
6259 brief_do_frame(flFrametime);
6262 case GS_STATE_DEBRIEF:
6263 game_set_frametime(GS_STATE_DEBRIEF);
6264 debrief_do_frame(flFrametime);
6267 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
6268 game_set_frametime(GS_STATE_MULTI_DOGFIGHT_DEBRIEF);
6269 multi_df_debrief_do();
6272 case GS_STATE_SHIP_SELECT:
6273 game_set_frametime(GS_STATE_SHIP_SELECT);
6274 ship_select_do(flFrametime);
6277 case GS_STATE_WEAPON_SELECT:
6278 game_set_frametime(GS_STATE_WEAPON_SELECT);
6279 weapon_select_do(flFrametime);
6282 case GS_STATE_MISSION_LOG_SCROLLBACK:
6283 game_set_frametime(GS_STATE_MISSION_LOG_SCROLLBACK);
6284 hud_scrollback_do_frame(flFrametime);
6287 case GS_STATE_HUD_CONFIG:
6288 game_set_frametime(GS_STATE_HUD_CONFIG);
6289 hud_config_do_frame(flFrametime);
6292 case GS_STATE_MULTI_JOIN_GAME:
6293 game_set_frametime(GS_STATE_MULTI_JOIN_GAME);
6294 multi_join_game_do_frame();
6297 case GS_STATE_MULTI_HOST_SETUP:
6298 game_set_frametime(GS_STATE_MULTI_HOST_SETUP);
6299 multi_create_game_do();
6302 case GS_STATE_MULTI_CLIENT_SETUP:
6303 game_set_frametime(GS_STATE_MULTI_CLIENT_SETUP);
6304 multi_game_client_setup_do_frame();
6307 case GS_STATE_CONTROL_CONFIG:
6308 game_set_frametime(GS_STATE_CONTROL_CONFIG);
6309 control_config_do_frame(flFrametime);
6312 case GS_STATE_DEATH_DIED:
6316 case GS_STATE_DEATH_BLEW_UP:
6320 case GS_STATE_SIMULATOR_ROOM:
6321 game_set_frametime(GS_STATE_SIMULATOR_ROOM);
6322 sim_room_do_frame(flFrametime);
6325 case GS_STATE_CAMPAIGN_ROOM:
6326 game_set_frametime(GS_STATE_CAMPAIGN_ROOM);
6327 campaign_room_do_frame(flFrametime);
6330 case GS_STATE_RED_ALERT:
6331 game_set_frametime(GS_STATE_RED_ALERT);
6332 red_alert_do_frame(flFrametime);
6335 case GS_STATE_CMD_BRIEF:
6336 game_set_frametime(GS_STATE_CMD_BRIEF);
6337 cmd_brief_do_frame(flFrametime);
6340 case GS_STATE_CREDITS:
6341 game_set_frametime(GS_STATE_CREDITS);
6342 credits_do_frame(flFrametime);
6345 case GS_STATE_VIEW_MEDALS:
6346 game_set_frametime(GS_STATE_VIEW_MEDALS);
6350 case GS_STATE_SHOW_GOALS:
6351 game_set_frametime(GS_STATE_SHOW_GOALS);
6352 mission_show_goals_do_frame(flFrametime);
6355 case GS_STATE_HOTKEY_SCREEN:
6356 game_set_frametime(GS_STATE_HOTKEY_SCREEN);
6357 mission_hotkey_do_frame(flFrametime);
6360 case GS_STATE_VIEW_CUTSCENES:
6361 game_set_frametime(GS_STATE_VIEW_CUTSCENES);
6362 cutscenes_screen_do_frame();
6365 case GS_STATE_MULTI_STD_WAIT:
6366 game_set_frametime(GS_STATE_STANDALONE_MAIN);
6367 multi_standalone_wait_do();
6370 case GS_STATE_STANDALONE_MAIN:
6371 game_set_frametime(GS_STATE_STANDALONE_MAIN);
6372 standalone_main_do();
6375 case GS_STATE_MULTI_PAUSED:
6376 game_set_frametime(GS_STATE_MULTI_PAUSED);
6380 case GS_STATE_TEAM_SELECT:
6381 game_set_frametime(GS_STATE_TEAM_SELECT);
6385 case GS_STATE_INGAME_PRE_JOIN:
6386 game_set_frametime(GS_STATE_INGAME_PRE_JOIN);
6387 multi_ingame_select_do();
6390 case GS_STATE_EVENT_DEBUG:
6392 game_set_frametime(GS_STATE_EVENT_DEBUG);
6393 game_show_event_debug(flFrametime);
6397 case GS_STATE_STANDALONE_POSTGAME:
6398 game_set_frametime(GS_STATE_STANDALONE_POSTGAME);
6399 multi_standalone_postgame_do();
6402 case GS_STATE_INITIAL_PLAYER_SELECT:
6403 game_set_frametime(GS_STATE_INITIAL_PLAYER_SELECT);
6407 case GS_STATE_MULTI_MISSION_SYNC:
6408 game_set_frametime(GS_STATE_MULTI_MISSION_SYNC);
6412 case GS_STATE_MULTI_START_GAME:
6413 game_set_frametime(GS_STATE_MULTI_START_GAME);
6414 multi_start_game_do();
6417 case GS_STATE_MULTI_HOST_OPTIONS:
6418 game_set_frametime(GS_STATE_MULTI_HOST_OPTIONS);
6419 multi_host_options_do();
6422 case GS_STATE_END_OF_CAMPAIGN:
6423 mission_campaign_end_do();
6426 case GS_STATE_END_DEMO:
6427 game_set_frametime(GS_STATE_END_DEMO);
6428 end_demo_campaign_do();
6431 case GS_STATE_LOOP_BRIEF:
6432 game_set_frametime(GS_STATE_LOOP_BRIEF);
6436 } // end switch(gs_current_state)
6440 // return 0 if there is enough RAM to run FreeSpace, otherwise return -1
6441 int game_do_ram_check(int ram_in_mbytes)
6443 if ( ram_in_mbytes < 30 ) {
6444 int allowed_to_run = 1;
6445 if ( ram_in_mbytes < 25 ) {
6451 if ( allowed_to_run ) {
6452 SDL_MessageBoxData mboxd;
6453 SDL_MessageBoxButtonData mboxbuttons[2];
6456 // not a translated string, but it's too long and smartdrv isn't
6457 // really a thing for any OS we now support :p
6458 // 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);
6459 SDL_snprintf( tmp, sizeof(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);
6461 mboxbuttons[0].buttonid = 0;
6462 mboxbuttons[0].text = XSTR("Ok", 503);
6463 mboxbuttons[0].flags = 0;
6465 mboxbuttons[1].buttonid = 1;
6466 mboxbuttons[1].text = XSTR("Cancel", 504);
6467 mboxbuttons[0].flags = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT | SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT;
6469 mboxd.flags = SDL_MESSAGEBOX_ERROR;
6470 mboxd.title = XSTR( "Not Enough RAM", 194);
6471 mboxd.message = tmp;
6472 mboxd.numbuttons = 2;
6473 mboxd.buttons = mboxbuttons;
6474 mboxd.window = NULL;
6475 mboxd.colorScheme = NULL;
6477 SDL_ShowMessageBox(&mboxd, &msgbox_rval);
6479 if ( msgbox_rval == 1 ) {
6483 // not a translated string, but it's too long and smartdrv isn't
6484 // really a thing for any OS we now support :p
6485 // 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);
6486 SDL_snprintf( tmp, sizeof(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);
6488 SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, XSTR( "Not Enough RAM", 194), tmp, NULL);
6497 // Check if there is a freespace.exe in the /update directory (relative to where fs.exe is installed).
6498 // If so, copy it over and remove the update directory.
6499 void game_maybe_update_launcher(char *exe_dir)
6504 void game_spew_pof_info_sub(int model_num, polymodel *pm, int sm, CFILE *out, int *out_total, int *out_destroyed_total)
6508 int sub_total_destroyed = 0;
6512 // get the total for all his children
6513 for (i=pm->submodel[sm].first_child; i>-1; i = pm->submodel[i].next_sibling ) {
6514 game_spew_pof_info_sub(model_num, pm, i, out, &sub_total, &sub_total_destroyed);
6517 // find the # of faces for this _individual_ object
6518 total = submodel_get_num_polys(model_num, sm);
6519 if(strstr(pm->submodel[sm].name, "-destroyed")){
6520 sub_total_destroyed = total;
6524 SDL_snprintf(str, sizeof(str), "Submodel %s total : %d faces\n", pm->submodel[sm].name, total);
6527 *out_total += total + sub_total;
6528 *out_destroyed_total += sub_total_destroyed;
6531 #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);
6532 void game_spew_pof_info()
6534 char *pof_list[1000];
6537 int idx, model_num, i, j;
6539 int total, root_total, model_total, destroyed_total, counted;
6543 num_files = cf_get_file_list(1000, pof_list, CF_TYPE_MODELS, "*.pof");
6545 // spew info on all the pofs
6551 out = cfopen("pofspew.txt", "wt", CFILE_NORMAL, CF_TYPE_DATA);
6556 for(idx=0; idx<num_files; idx++, counted++){
6557 SDL_snprintf(str, sizeof(str), "%s.pof", pof_list[idx]);
6558 model_num = model_load(str, 0, NULL);
6560 pm = model_get(model_num);
6562 // if we have a real model
6567 // go through and print all raw submodels
6568 cfputs("RAW\n", out);
6571 for (i=0; i<pm->n_models; i++) {
6572 total = submodel_get_num_polys(model_num, i);
6574 model_total += total;
6575 SDL_snprintf(str, sizeof(str), "Submodel %s total : %d faces\n", pm->submodel[i].name, total);
6578 SDL_snprintf(str, sizeof(str), "Model total %d\n", model_total);
6581 // now go through and do it by LOD
6582 cfputs("BY LOD\n\n", out);
6583 for(i=0; i<pm->n_detail_levels; i++){
6584 SDL_snprintf(str, sizeof(str), "LOD %d\n", i);
6588 root_total = submodel_get_num_polys(model_num, pm->detail[i] );
6590 destroyed_total = 0;
6591 for (j=pm->submodel[pm->detail[i]].first_child; j>-1; j = pm->submodel[j].next_sibling ) {
6592 game_spew_pof_info_sub(model_num, pm, j, out, &total, &destroyed_total);
6595 SDL_snprintf(str, sizeof(str), "Submodel %s total : %d faces\n", pm->submodel[pm->detail[i]].name, root_total);
6598 SDL_snprintf(str, sizeof(str), "TOTAL: %d\n", total + root_total);
6600 SDL_snprintf(str, sizeof(str), "TOTAL not counting destroyed faces %d\n", (total + root_total) - destroyed_total);
6602 SDL_snprintf(str, sizeof(str), "TOTAL destroyed faces %d\n\n", destroyed_total);
6605 cfputs("------------------------------------------------------------------------\n\n", out);
6609 if(counted >= MAX_POLYGON_MODELS - 5){
6622 game_spew_pof_info();
6625 int game_main(const char *szCmdLine)
6629 // Find out how much RAM is on this machine
6630 Freespace_total_ram = SDL_GetSystemRAM();
6632 if ( game_do_ram_check(Freespace_total_ram) == -1 ) {
6636 if (!vm_init(24*1024*1024)) {
6637 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);
6641 char *tmp_mem = (char *) malloc(16 * 1024 * 1024);
6643 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);
6652 extern void windebug_memwatch_init();
6653 windebug_memwatch_init();
6661 int cpu_cores = SDL_GetCPUCount();
6662 int le = (SDL_BYTEORDER == SDL_LIL_ENDIAN);
6664 mprintf(("Platform: %s\n", SDL_GetPlatform()));
6665 mprintf(("CPU: %d %s\n", cpu_cores, (cpu_cores == 1) ? "core" : "cores"));
6666 mprintf(("Memory: %dMB\n", Freespace_total_ram));
6667 mprintf(("Build: %d-bit, %s-endian\n", sizeof(void*) * 8, le ? "little" : "big"));
6669 parse_cmdline(szCmdLine);
6671 mprintf(("--------------------------------------------------------------------------------\n"));
6673 #ifdef STANDALONE_ONLY_BUILD
6675 nprintf(("Network", "Standalone running"));
6678 nprintf(("Network", "Standalone running"));
6685 // maybe spew pof stuff
6686 if(Cmdline_spew_pof_info){
6687 game_spew_pof_info();
6692 // non-demo, non-standalone, play the intro movie
6694 if ( !Is_standalone ) {
6696 // release -- movies always play
6699 // 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
6700 movie_play( NOX("intro.mve") );
6702 // debug version, movie will only play with -showmovies
6703 #elif !defined(NDEBUG)
6705 movie_play( NOX("intro.mve") );
6708 if ( Cmdline_show_movies )
6709 movie_play( NOX("intro.mve") );
6718 gameseq_post_event(GS_EVENT_STANDALONE_MAIN);
6720 gameseq_post_event(GS_EVENT_GAME_INIT); // start the game rolling -- check for default pilot, or go to the pilot select screen
6724 // only important for non THREADED mode
6727 state = gameseq_process_events();
6728 if ( state == GS_STATE_QUIT_GAME ){
6733 #if defined(FS2_DEMO) || defined(FS1_DEMO)
6735 demo_upsell_show_screens();
6737 #elif defined(OEM_BUILD)
6738 // show upsell screens on exit
6739 oem_upsell_show_screens();
6746 // launcher the fslauncher program on exit
6747 void game_launch_launcher_on_exit()
6755 // This function is called when FreeSpace terminates normally.
6757 void game_shutdown(void)
6759 // don't ever flip a page on the standalone!
6760 if(!(Game_mode & GM_STANDALONE_SERVER)){
6766 // if the player has left the "player select" screen and quit the game without actually choosing
6767 // a player, Player will be NULL, in which case we shouldn't write the player file out!
6768 if (!(Game_mode & GM_STANDALONE_SERVER) && (Player!=NULL) && !Is_standalone){
6772 // load up common multiplayer icons
6773 multi_unload_common_icons();
6775 shockwave_close(); // release any memory used by shockwave system
6776 fireball_close(); // free fireball system
6777 ship_close(); // free any memory that was allocated for the ships
6778 weapon_close(); // free any memory that was allocated for the weapons
6779 hud_free_scrollback_list();// free space allocated to store hud messages in hud scrollback
6780 unload_animating_pointer();// frees the frames used for the animating mouse pointer
6781 bm_unload_all(); // free bitmaps
6782 mission_campaign_close(); // close out the campaign stuff
6783 mission_campaign_shutdown(); // get anything that mission_campaign_close can't do
6784 multi_voice_close(); // close down multiplayer voice (including freeing buffers, etc)
6786 #ifdef MULTI_USE_LAG
6790 // the menu close functions will unload the bitmaps if they were displayed during the game
6791 #if !defined(PRESS_TOUR_BUILD) && !defined(PD_BUILD)
6794 context_help_close(); // close out help system
6795 training_menu_close();
6796 lcl_close(); // be sure localization is closed out
6799 // free left-over memory from parsed tables
6800 cutscene_tbl_close();
6802 scoring_tbl_close();
6803 player_tips_close();
6805 extern void joy_close();
6808 audiostream_close();
6810 event_music_close();
6814 // HACKITY HACK HACK
6815 // if this flag is set, we should be firing up the launcher when exiting freespace
6816 extern int Multi_update_fireup_launcher_on_exit;
6817 if(Multi_update_fireup_launcher_on_exit){
6818 game_launch_launcher_on_exit();
6822 // game_stop_looped_sounds()
6824 // This function will call the appropriate stop looped sound functions for those
6825 // modules which use looping sounds. It is not enough just to stop a looping sound
6826 // at the DirectSound level, the game is keeping track of looping sounds, and this
6827 // function is used to inform the game that looping sounds are being halted.
6829 void game_stop_looped_sounds()
6831 hud_stop_looped_locking_sounds();
6832 hud_stop_looped_engine_sounds();
6833 afterburner_stop_sounds();
6834 player_stop_looped_sounds();
6835 obj_snd_stop_all(); // stop all object-linked persistant sounds
6836 game_stop_subspace_ambient_sound();
6837 snd_stop(Radar_static_looping);
6838 Radar_static_looping = -1;
6839 snd_stop(Target_static_looping);
6840 shipfx_stop_engine_wash_sound();
6841 Target_static_looping = -1;
6844 //////////////////////////////////////////////////////////////////////////
6846 // Code for supporting an animating mouse pointer
6849 //////////////////////////////////////////////////////////////////////////
6851 typedef struct animating_obj
6860 static animating_obj Animating_mouse;
6862 // ----------------------------------------------------------------------------
6863 // init_animating_pointer()
6865 // Called by load_animating_pointer() to ensure the Animating_mouse struct
6866 // gets properly initialized
6868 void init_animating_pointer()
6870 Animating_mouse.first_frame = -1;
6871 Animating_mouse.num_frames = 0;
6872 Animating_mouse.current_frame = -1;
6873 Animating_mouse.time = 0.0f;
6874 Animating_mouse.elapsed_time = 0.0f;
6877 // ----------------------------------------------------------------------------
6878 // load_animating_pointer()
6880 // Called at game init to load in the frames for the animating mouse pointer
6882 // input: filename => filename of animation file that holds the animation
6884 void load_animating_pointer(const char *filename, int dx, int dy)
6889 init_animating_pointer();
6891 am = &Animating_mouse;
6892 am->first_frame = bm_load_animation(filename, &am->num_frames, &fps);
6893 if ( am->first_frame == -1 )
6894 Error(LOCATION, "Could not load animation %s for the mouse pointer\n", filename);
6895 am->current_frame = 0;
6896 am->time = am->num_frames / i2fl(fps);
6899 // ----------------------------------------------------------------------------
6900 // unload_animating_pointer()
6902 // Called at game shutdown to free the memory used to store the animation frames
6904 void unload_animating_pointer()
6909 am = &Animating_mouse;
6910 for ( i = 0; i < am->num_frames; i++ ) {
6911 SDL_assert( (am->first_frame+i) >= 0 );
6912 bm_release(am->first_frame + i);
6915 am->first_frame = -1;
6917 am->current_frame = -1;
6920 // draw the correct frame of the game mouse... called from game_maybe_draw_mouse()
6921 void game_render_mouse(float frametime)
6926 // if animating cursor exists, play the next frame
6927 am = &Animating_mouse;
6928 if ( am->first_frame != -1 ) {
6929 mouse_get_pos(&mx, &my);
6930 am->elapsed_time += frametime;
6931 am->current_frame = fl2i( ( am->elapsed_time / am->time ) * (am->num_frames-1) );
6932 if ( am->current_frame >= am->num_frames ) {
6933 am->current_frame = 0;
6934 am->elapsed_time = 0.0f;
6936 gr_set_cursor_bitmap(am->first_frame + am->current_frame);
6940 // ----------------------------------------------------------------------------
6941 // game_maybe_draw_mouse()
6943 // determines whether to draw the mouse pointer at all, and what frame of
6944 // animation to use if the mouse is animating
6946 // Sets mouse.cpp globals Mouse_hidden and Mouse_moved based on the state of the game.
6948 // input: frametime => elapsed frame time in seconds since last call
6950 void game_maybe_draw_mouse(float frametime)
6954 game_state = gameseq_get_state();
6956 switch ( game_state ) {
6957 case GS_STATE_GAME_PAUSED:
6958 // case GS_STATE_MULTI_PAUSED:
6959 case GS_STATE_GAME_PLAY:
6960 case GS_STATE_DEATH_DIED:
6961 case GS_STATE_DEATH_BLEW_UP:
6962 if ( popup_active() || popupdead_is_active() ) {
6974 if ( !Mouse_hidden )
6975 game_render_mouse(frametime);
6979 void game_do_training_checks()
6983 waypoint_list *wplp;
6985 if (Training_context & TRAINING_CONTEXT_SPEED) {
6986 s = (int) Player_obj->phys_info.fspeed;
6987 if ((s >= Training_context_speed_min) && (s <= Training_context_speed_max)) {
6988 if (!Training_context_speed_set) {
6989 Training_context_speed_set = 1;
6990 Training_context_speed_timestamp = timestamp();
6994 Training_context_speed_set = 0;
6997 if (Training_context & TRAINING_CONTEXT_FLY_PATH) {
6998 wplp = &Waypoint_lists[Training_context_path];
6999 if (wplp->count > Training_context_goal_waypoint) {
7000 i = Training_context_goal_waypoint;
7002 d = vm_vec_dist(&wplp->waypoints[i], &Player_obj->pos);
7003 if (d <= Training_context_distance) {
7004 Training_context_at_waypoint = i;
7005 if (Training_context_goal_waypoint == i) {
7006 Training_context_goal_waypoint++;
7007 snd_play(&Snds[SND_CARGO_REVEAL], 0.0f);
7014 if (i == wplp->count)
7017 } while (i != Training_context_goal_waypoint);
7021 if ((Players_target == UNINITIALIZED) || (Player_ai->target_objnum != Players_target) || (Player_ai->targeted_subsys != Players_targeted_subsys)) {
7022 Players_target = Player_ai->target_objnum;
7023 Players_targeted_subsys = Player_ai->targeted_subsys;
7024 Players_target_timestamp = timestamp();
7028 /////////// Following is for event debug view screen
7032 #define EVENT_DEBUG_MAX 5000
7033 #define EVENT_DEBUG_EVENT 0x8000
7035 int Event_debug_index[EVENT_DEBUG_MAX];
7038 void game_add_event_debug_index(int n, int indent)
7040 if (ED_count < EVENT_DEBUG_MAX)
7041 Event_debug_index[ED_count++] = n | (indent << 16);
7044 void game_add_event_debug_sexp(int n, int indent)
7049 if (Sexp_nodes[n].first >= 0) {
7050 game_add_event_debug_sexp(Sexp_nodes[n].first, indent);
7051 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent);
7055 game_add_event_debug_index(n, indent);
7056 if (Sexp_nodes[n].subtype == SEXP_ATOM_OPERATOR)
7057 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent + 1);
7059 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent);
7062 void game_event_debug_init()
7067 for (e=0; e<Num_mission_events; e++) {
7068 game_add_event_debug_index(e | EVENT_DEBUG_EVENT, 0);
7069 game_add_event_debug_sexp(Mission_events[e].formula, 1);
7073 void game_show_event_debug(float frametime)
7077 int font_height, font_width;
7079 static int scroll_offset = 0;
7081 k = game_check_key();
7087 if (scroll_offset < 0)
7097 scroll_offset -= 20;
7098 if (scroll_offset < 0)
7103 scroll_offset += 20; // not font-independent, hard-coded since I counted the lines!
7107 gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
7113 gr_set_color_fast(&Color_bright);
7115 gr_printf(0x8000, 5, NOX("EVENT DEBUG VIEW"));
7117 gr_set_color_fast(&Color_normal);
7119 gr_get_string_size(&font_width, &font_height, NOX("test"));
7120 y_max = gr_screen.max_h - font_height - 5;
7124 while (k < ED_count) {
7125 if (y_index > y_max)
7128 z = Event_debug_index[k];
7129 if (z & EVENT_DEBUG_EVENT) {
7131 SDL_snprintf(buf, sizeof(buf), NOX("%s%s (%s) %s%d %d"), (Mission_events[z].flags & MEF_CURRENT) ? NOX("* ") : "",
7132 Mission_events[z].name, Mission_events[z].result ? NOX("True") : NOX("False"),
7133 (Mission_events[z].chain_delay < 0) ? "" : NOX("x "),
7134 Mission_events[z].repeat_count, Mission_events[z].interval);
7142 SDL_strlcat(buf, Sexp_nodes[z & 0x7fff].text, sizeof(buf));
7143 switch (Sexp_nodes[z & 0x7fff].value) {
7145 SDL_strlcat(buf, NOX(" (True)"), sizeof(buf));
7149 SDL_strlcat(buf, NOX(" (False)"), sizeof(buf));
7152 case SEXP_KNOWN_TRUE:
7153 SDL_strlcat(buf, NOX(" (Always true)"), sizeof(buf));
7156 case SEXP_KNOWN_FALSE:
7157 SDL_strlcat(buf, NOX(" (Always false)"), sizeof(buf));
7160 case SEXP_CANT_EVAL:
7161 SDL_strlcat(buf, NOX(" (Can't eval)"), sizeof(buf));
7165 case SEXP_NAN_FOREVER:
7166 SDL_strlcat(buf, NOX(" (Not a number)"), sizeof(buf));
7171 gr_printf(10, y_index, buf);
7172 y_index += font_height;
7185 int Tmap_num_too_big = 0;
7186 int Num_models_needing_splitting = 0;
7188 void Time_model( int modelnum )
7190 // mprintf(( "Timing ship '%s'\n", si->name ));
7192 vector eye_pos, model_pos;
7193 matrix eye_orient, model_orient;
7195 polymodel *pm = model_get( modelnum );
7197 int l = strlen(pm->filename);
7199 if ( (l == '/') || (l=='\\') || (l==':')) {
7205 char *pof_file = &pm->filename[l];
7207 int model_needs_splitting = 0;
7209 //fprintf( Texture_fp, "Model: %s\n", pof_file );
7211 for (i=0; i<pm->n_textures; i++ ) {
7212 char filename[1024];
7215 int bmp_num = pm->original_textures[i];
7216 if ( bmp_num > -1 ) {
7217 bm_get_palette(pm->original_textures[i], pal, filename, sizeof(filename) );
7219 bm_get_info( pm->original_textures[i],&w, &h );
7222 if ( (w > 512) || (h > 512) ) {
7223 fprintf( Texture_fp, "%s\t%s\t%d\t%d\n", pof_file, filename, w, h );
7225 model_needs_splitting++;
7228 //fprintf( Texture_fp, "\tTexture %d is bogus\n", i );
7232 if ( model_needs_splitting ) {
7233 Num_models_needing_splitting++;
7235 eye_orient = model_orient = vmd_identity_matrix;
7236 eye_pos = model_pos = vmd_zero_vector;
7238 eye_pos.xyz.z = -pm->rad*2.0f;
7240 vector eye_to_model;
7242 vm_vec_sub( &eye_to_model, &model_pos, &eye_pos );
7243 vm_vector_2_matrix( &eye_orient, &eye_to_model, NULL, NULL );
7245 fix t1 = timer_get_fixed_seconds();
7248 ta.p = ta.b = ta.h = 0.0f;
7251 int bitmaps_used_this_frame, bitmaps_new_this_frame;
7253 bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
7255 modelstats_num_polys = modelstats_num_verts = 0;
7257 while( ta.h < PI2 ) {
7260 vm_angles_2_matrix(&m1, &ta );
7261 vm_matrix_x_matrix( &model_orient, &vmd_identity_matrix, &m1 );
7268 g3_set_view_matrix( &eye_pos, &eye_orient, Viewer_zoom );
7270 model_clear_instance( modelnum );
7271 model_set_detail_level(0); // use highest detail level
7272 model_render( modelnum, &model_orient, &model_pos, MR_LOCK_DETAIL); //|MR_NO_POLYS );
7280 int k = key_inkey();
7281 if ( k == SDLK_ESCAPE ) {
7286 fix t2 = timer_get_fixed_seconds();
7288 if (framecount < 1) {
7292 bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
7293 //bitmaps_used_this_frame /= framecount;
7295 modelstats_num_polys /= framecount;
7296 modelstats_num_verts /= framecount;
7298 mprintf(( "'%s' is %.2f FPS\n", pof_file, i2fl(framecount)/f2fl(t2-t1) ));
7299 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 );
7301 // fprintf( Time_fp, "%.0f\t%d\t%d\t%d\n", i2fl(framecount)/f2fl(t2-t1), bitmaps_used_this_frame, modelstats_num_polys, modelstats_num_verts );
7307 int Time_models = 0;
7308 DCF_BOOL( time_models, Time_models );
7310 void Do_model_timings_test()
7314 if ( !Time_models ) return;
7316 mprintf(( "Timing models!\n" ));
7320 ubyte model_used[MAX_POLYGON_MODELS];
7321 int model_id[MAX_POLYGON_MODELS];
7322 for (i=0; i<MAX_POLYGON_MODELS; i++ ) {
7327 for (i=0; i<Num_ship_types; i++ ) {
7328 Ship_info[i].modelnum = model_load( Ship_info[i].pof_file, 0, NULL );
7330 model_used[Ship_info[i].modelnum%MAX_POLYGON_MODELS]++;
7331 model_id[Ship_info[i].modelnum%MAX_POLYGON_MODELS] = Ship_info[i].modelnum;
7334 Texture_fp = fopen( NOX("ShipTextures.txt"), "wt" );
7335 if ( !Texture_fp ) return;
7337 Time_fp = fopen( NOX("ShipTimings.txt"), "wt" );
7338 if ( !Time_fp ) return;
7340 fprintf( Time_fp, "Name\tFPS\tTRAM\tPolys\tVerts\tPixels\n" );
7341 // fprintf( Time_fp, "FPS\tTRAM\tPolys\tVerts\tPixels\n" );
7343 for (i=0; i<MAX_POLYGON_MODELS; i++ ) {
7344 if ( model_used[i] ) {
7345 Time_model( model_id[i] );
7349 fprintf( Texture_fp, "Number too big: %d\n", Tmap_num_too_big );
7350 fprintf( Texture_fp, "Number of models needing splitting: %d\n", Num_models_needing_splitting );
7359 // Call this function when you want to inform the player that a feature is not
7360 // enabled in the DEMO version of FreSpace
7361 void game_feature_not_in_demo_popup()
7363 popup(PF_USE_AFFIRMATIVE_ICON|PF_BODY_BIG, 1, POPUP_OK, XSTR( "Sorry, this feature is available only in the retail version", 200));
7366 // format the specified time (fixed point) into a nice string
7367 void game_format_time(fix m_time, char *time_str, const int time_str_len)
7370 int hours,minutes,seconds;
7372 mtime = f2fl(m_time);
7374 // get the hours, minutes and seconds
7375 hours = (int)(mtime / 3600.0f);
7377 mtime -= (3600.0f * (float)hours);
7379 seconds = (int)mtime%60;
7380 minutes = (int)mtime/60;
7383 SDL_snprintf(time_str, time_str_len, "%d:%02d:%02d", hours, minutes, seconds);
7385 SDL_snprintf(time_str, time_str_len, "%d:%02d", minutes, seconds);
7389 // Stuff version string in *str.
7390 void get_version_string(char *str, const int str_len)
7393 if ( FS_VERSION_BUILD == 0 ) {
7394 SDL_snprintf(str, str_len, "v%d.%02d", FS_VERSION_MAJOR, FS_VERSION_MINOR);
7396 SDL_snprintf(str, str_len, "v%d.%02d.%02d", FS_VERSION_MAJOR, FS_VERSION_MINOR, FS_VERSION_BUILD );
7399 #if defined (FS2_DEMO) || defined(FS1_DEMO)
7400 SDL_strlcat(str, " D", str_len);
7401 #elif defined (OEM_BUILD)
7402 SDL_strlcat(str, " (OEM)", str_len);
7408 char myname[_MAX_PATH];
7409 int namelen, major, minor, build, waste;
7410 unsigned int buf_size;
7416 // Find my EXE file name
7417 hMod = GetModuleHandle(NULL);
7418 namelen = GetModuleFileName( hMod, myname, _MAX_PATH );
7420 version_size = GetFileVersionInfoSize(myname, &bogus_handle );
7421 infop = (char *)malloc(version_size);
7422 result = GetFileVersionInfo( myname, 0, version_size, (LPVOID)infop );
7424 // get the product version
7425 result = VerQueryValue((LPVOID)infop, TEXT("\\StringFileInfo\\040904b0\\ProductVersion"), &bufp, &buf_size );
7426 sscanf( (char *)bufp, "%d, %d, %d, %d", &major, &minor, &build, &waste );
7428 sprintf(str,"Dv%d.%02d",major, minor);
7430 sprintf(str,"v%d.%02d",major, minor);
7435 void get_version_string_short(char *str, const int str_len)
7437 SDL_snprintf(str, str_len, "v%d.%02d", FS_VERSION_MAJOR, FS_VERSION_MINOR);
7440 // ----------------------------------------------------------------
7442 // OEM UPSELL SCREENS BEGIN
7444 // ----------------------------------------------------------------
7445 #if defined(OEM_BUILD)
7447 #define NUM_OEM_UPSELL_SCREENS 3
7448 #define OEM_UPSELL_SCREEN_DELAY 10000
7450 static int Oem_upsell_bitmaps_loaded = 0;
7451 static int Oem_upsell_bitmaps[GR_NUM_RESOLUTIONS][NUM_OEM_UPSELL_SCREENS];
7452 static int Oem_upsell_screen_number = 0;
7453 static int Oem_upsell_show_next_bitmap_time;
7456 static char *Oem_upsell_bitmap_filenames[GR_NUM_RESOLUTIONS][NUM_OEM_UPSELL_SCREENS] =
7469 static int Oem_normal_cursor = -1;
7470 static int Oem_web_cursor = -1;
7471 //#define OEM_UPSELL_URL "http://www.interplay-store.com/"
7472 #define OEM_UPSELL_URL "http://www.interplay.com/cgi-bin/oemlinks.pl/pid=483421&cid=18384"
7474 void oem_upsell_next_screen()
7476 Oem_upsell_screen_number++;
7477 if ( Oem_upsell_screen_number == (NUM_OEM_UPSELL_SCREENS-1) ) {
7478 // extra long delay, mouse shown on last upsell
7479 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY*2;
7483 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY;
7487 void oem_upsell_load_bitmaps()
7491 for ( i = 0; i < NUM_OEM_UPSELL_SCREENS; i++ ) {
7492 Oem_upsell_bitmaps[gr_screen.res][i] = bm_load(Oem_upsell_bitmap_filenames[gr_screen.res][i]);
7496 void oem_upsell_unload_bitmaps()
7500 for ( i = 0; i < NUM_OEM_UPSELL_SCREENS; i++ ) {
7501 if(Oem_upsell_bitmaps[gr_screen.res][i] >= 0){
7502 bm_unload(Oem_upsell_bitmaps[gr_screen.res][i]);
7507 Oem_upsell_bitmaps_loaded = 0;
7510 // clickable hotspot on 3rd OEM upsell screen
7511 static int Oem_upsell3_button_coords[GR_NUM_RESOLUTIONS][4] = {
7513 28, 350, 287, 96 // x, y, w, h
7516 45, 561, 460, 152 // x, y, w, h
7520 void oem_upsell_show_screens()
7522 int current_time, k;
7525 if ( !Oem_upsell_bitmaps_loaded ) {
7526 oem_upsell_load_bitmaps();
7527 Oem_upsell_bitmaps_loaded = 1;
7530 // may use upsell screens more than once
7531 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY;
7532 Oem_upsell_screen_number = 0;
7538 int nframes; // used to pass, not really needed (should be 1)
7539 Oem_normal_cursor = gr_get_cursor_bitmap();
7540 Oem_web_cursor = bm_load_animation("cursorweb", &nframes);
7541 SDL_assert(Oem_web_cursor >= 0);
7542 if (Oem_web_cursor < 0) {
7543 Oem_web_cursor = Oem_normal_cursor;
7548 //oem_reset_trailer_timer();
7550 current_time = timer_get_milliseconds();
7555 // advance screen on keypress or timeout
7556 if (( k > 0 ) || (mouse_up_count(MOUSE_LEFT_BUTTON) > 0) || (current_time > Oem_upsell_show_next_bitmap_time)) {
7557 oem_upsell_next_screen();
7560 // check if we are done
7561 if ( Oem_upsell_screen_number >= NUM_OEM_UPSELL_SCREENS ) {
7562 Oem_upsell_screen_number--;
7565 if ( Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number] < 0 ) {
7570 // show me the upsell
7571 if ( Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number] >= 0 ) {
7572 gr_set_bitmap(Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number]);
7576 // if this is the 3rd upsell, make it clickable, d00d
7577 if ( Oem_upsell_screen_number == NUM_OEM_UPSELL_SCREENS-1 ) {
7579 int button_state = mouse_get_pos(&mx, &my);
7580 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])
7581 && (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]) )
7584 gr_set_cursor_bitmap(Oem_web_cursor); //, GR_CURSOR_LOCK);
7587 if (button_state & MOUSE_LEFT_BUTTON) {
7589 multi_pxo_url(OEM_UPSELL_URL);
7593 // switch cursor back to normal one
7594 gr_set_cursor_bitmap(Oem_normal_cursor); //, GR_CURSOR_UNLOCK);
7599 if (gameseq_get_state() != GS_STATE_END_DEMO) {
7609 oem_upsell_unload_bitmaps();
7611 // switch cursor back to normal one
7612 gr_set_cursor_bitmap(Oem_normal_cursor); //, GR_CURSOR_UNLOCK);
7616 #endif // defined(OEM_BUILD)
7617 // ----------------------------------------------------------------
7619 // OEM UPSELL SCREENS END
7621 // ----------------------------------------------------------------
7625 // ----------------------------------------------------------------
7627 // DEMO UPSELL SCREENS BEGIN
7629 // ----------------------------------------------------------------
7631 #if defined(FS2_DEMO) || defined(FS1_DEMO)
7634 #define NUM_DEMO_UPSELL_SCREENS 2
7636 #define NUM_DEMO_UPSELL_SCREENS 4
7638 #define DEMO_UPSELL_SCREEN_DELAY 3000
7640 static int Demo_upsell_bitmaps_loaded = 0;
7641 static int Demo_upsell_bitmaps[GR_NUM_RESOLUTIONS][NUM_DEMO_UPSELL_SCREENS];
7642 static int Demo_upsell_screen_number = 0;
7643 static int Demo_upsell_show_next_bitmap_time;
7646 static char *Demo_upsell_bitmap_filenames[GR_NUM_RESOLUTIONS][NUM_DEMO_UPSELL_SCREENS] =
7672 void demo_upsell_next_screen()
7674 Demo_upsell_screen_number++;
7675 if ( Demo_upsell_screen_number == (NUM_DEMO_UPSELL_SCREENS-1) ) {
7676 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY*4;
7678 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY;
7682 void demo_upsell_load_bitmaps()
7686 for ( i = 0; i < NUM_DEMO_UPSELL_SCREENS; i++ ) {
7687 Demo_upsell_bitmaps[gr_screen.res][i] = bm_load(Demo_upsell_bitmap_filenames[gr_screen.res][i]);
7691 void demo_upsell_unload_bitmaps()
7695 for ( i = 0; i < NUM_DEMO_UPSELL_SCREENS; i++ ) {
7696 if(Demo_upsell_bitmaps[gr_screen.res][i] >= 0){
7697 bm_unload(Demo_upsell_bitmaps[gr_screen.res][i]);
7702 Demo_upsell_bitmaps_loaded = 0;
7705 void demo_upsell_show_screens()
7707 int current_time, k;
7710 if ( !Demo_upsell_bitmaps_loaded ) {
7711 demo_upsell_load_bitmaps();
7712 Demo_upsell_bitmaps_loaded = 1;
7715 // may use upsell screens more than once
7716 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY;
7717 Demo_upsell_screen_number = 0;
7724 demo_reset_trailer_timer();
7726 current_time = timer_get_milliseconds();
7733 // don't time out, wait for keypress
7735 if ( current_time > Demo_upsell_show_next_bitmap_time ) {
7736 demo_upsell_next_screen();
7741 demo_upsell_next_screen();
7744 if ( Demo_upsell_screen_number >= NUM_DEMO_UPSELL_SCREENS ) {
7745 Demo_upsell_screen_number--;
7748 if ( Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number] < 0 ) {
7753 if ( Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number] >= 0 ) {
7754 gr_set_bitmap(Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number]);
7759 if (gameseq_get_state() != GS_STATE_END_DEMO) {
7769 demo_upsell_unload_bitmaps();
7774 // ----------------------------------------------------------------
7776 // DEMO UPSELL SCREENS END
7778 // ----------------------------------------------------------------
7781 // ----------------------------------------------------------------
7783 // Subspace Ambient Sound START
7785 // ----------------------------------------------------------------
7787 static int Subspace_ambient_left_channel = -1;
7788 static int Subspace_ambient_right_channel = -1;
7791 void game_start_subspace_ambient_sound()
7793 if ( Subspace_ambient_left_channel < 0 ) {
7794 Subspace_ambient_left_channel = snd_play_looping(&Snds[SND_SUBSPACE_LEFT_CHANNEL], -1.0f);
7797 if ( Subspace_ambient_right_channel < 0 ) {
7798 Subspace_ambient_right_channel = snd_play_looping(&Snds[SND_SUBSPACE_RIGHT_CHANNEL], 1.0f);
7802 void game_stop_subspace_ambient_sound()
7804 if ( Subspace_ambient_left_channel >= 0 ) {
7805 snd_stop(Subspace_ambient_left_channel);
7806 Subspace_ambient_left_channel = -1;
7809 if ( Subspace_ambient_right_channel >= 0 ) {
7810 snd_stop(Subspace_ambient_right_channel);
7811 Subspace_ambient_right_channel = -1;
7815 // ----------------------------------------------------------------
7817 // Subspace Ambient Sound END
7819 // ----------------------------------------------------------------
7821 // ----------------------------------------------------------------
7823 // Language Autodetection stuff
7826 // this layout order must match Lcl_languages in localize.cpp in order for the
7827 // correct language to be detected
7828 int Lang_auto_detect_checksums[LCL_NUM_LANGUAGES] = {
7830 1366105450, // English
7832 589986744, // English
7834 -1132430286, // German
7836 -1131728960, // Polish
7839 // default setting is "-1" to use config file with English as fall back
7840 // DO NOT change the default setting here or something uncouth might happen
7841 // in the localization code
7847 // try and open the file to verify
7848 CFILE *detect = cfopen("font01.vf", "rb");
7850 // will use default setting if something went wrong
7855 // get the long checksum of the file
7857 cfseek(detect, 0, SEEK_SET);
7858 cf_chksum_long(detect, &file_checksum);
7862 // now compare the checksum/filesize against known #'s
7863 for (idx=0; idx<LCL_NUM_LANGUAGES; idx++) {
7864 if (Lang_auto_detect_checksums[idx] == (int)file_checksum) {
7869 // notify if a match was not found, include detected checksum
7870 printf("ERROR: Unknown Language Checksum: %i\n", (int)file_checksum);
7871 printf("Using default language...\n\n");
7877 // End Auto Lang stuff
7879 // ----------------------------------------------------------------
7881 // ----------------------------------------------------------------
7882 // SHIPS TBL VERIFICATION STUFF
7885 // checksums, just keep a list of all valid ones, if it matches any of them, keep it
7886 #if defined(MAKE_FS1) && !defined(FS1_DEMO)
7887 #define NUM_SHIPS_TBL_CHECKSUMS 3
7889 #define NUM_SHIPS_TBL_CHECKSUMS 1
7893 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
7894 1696074201, // FS2 demo
7897 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
7898 1603375034, // FS1 DEMO
7901 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
7902 -129679197, // FS1 Full 1.06 (US)
7903 7762567, // FS1 SilentThreat
7904 1555372475 // FS1 Full 1.06 (German)
7908 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
7909 -463907578, // US - beta 1
7910 1696074201, // FS2 demo
7913 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
7914 // -1022810006, // 1.0 FULL
7915 -1254285366 // 1.2 FULL (German)
7919 void verify_ships_tbl()
7923 Game_ships_tbl_valid = 1;
7929 // detect if the packfile exists
7930 CFILE *detect = cfopen("ships.tbl", "rb");
7931 Game_ships_tbl_valid = 0;
7935 Game_ships_tbl_valid = 0;
7939 // get the long checksum of the file
7941 cfseek(detect, 0, SEEK_SET);
7942 cf_chksum_long(detect, &file_checksum);
7946 // now compare the checksum/filesize against known #'s
7947 for(idx=0; idx<NUM_SHIPS_TBL_CHECKSUMS; idx++){
7948 if(Game_ships_tbl_checksums[idx] == (int)file_checksum){
7949 Game_ships_tbl_valid = 1;
7956 DCF(shipspew, "display the checksum for the current ships.tbl")
7959 CFILE *detect = cfopen("ships.tbl", "rb");
7960 // get the long checksum of the file
7962 cfseek(detect, 0, SEEK_SET);
7963 cf_chksum_long(detect, &file_checksum);
7966 dc_printf("%d", file_checksum);
7969 // ----------------------------------------------------------------
7970 // WEAPONS TBL VERIFICATION STUFF
7973 // checksums, just keep a list of all valid ones, if it matches any of them, keep it
7974 #if defined(MAKE_FS1) && !defined(FS1_DEMO)
7975 #define NUM_WEAPONS_TBL_CHECKSUMS 3
7977 #define NUM_WEAPONS_TBL_CHECKSUMS 1
7981 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
7982 -266420030, // demo 1
7985 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
7986 -1246928725, // FS1 DEMO
7989 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
7990 -834598107, // FS1 1.06 Full (US)
7991 -1652231417, // FS1 SilentThreat
7992 720209793 // FS1 1.06 Full (German)
7996 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
7997 141718090, // US - beta 1
7998 -266420030, // demo 1
8001 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
8002 // 399297860, // 1.0 FULL
8003 -553984927 // 1.2 FULL (german)
8007 void verify_weapons_tbl()
8011 Game_weapons_tbl_valid = 1;
8017 // detect if the packfile exists
8018 CFILE *detect = cfopen("weapons.tbl", "rb");
8019 Game_weapons_tbl_valid = 0;
8023 Game_weapons_tbl_valid = 0;
8027 // get the long checksum of the file
8029 cfseek(detect, 0, SEEK_SET);
8030 cf_chksum_long(detect, &file_checksum);
8034 // now compare the checksum/filesize against known #'s
8035 for(idx=0; idx<NUM_WEAPONS_TBL_CHECKSUMS; idx++){
8036 if(Game_weapons_tbl_checksums[idx] == (int)file_checksum){
8037 Game_weapons_tbl_valid = 1;
8044 DCF(wepspew, "display the checksum for the current weapons.tbl")
8047 CFILE *detect = cfopen("weapons.tbl", "rb");
8048 // get the long checksum of the file
8050 cfseek(detect, 0, SEEK_SET);
8051 cf_chksum_long(detect, &file_checksum);
8054 dc_printf("%d", file_checksum);
8057 // if the game is running using hacked data
8058 int game_hacked_data()
8061 if(!Game_weapons_tbl_valid || !Game_ships_tbl_valid){
8069 void display_title_screen()
8071 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
8072 ///int title_bitmap;
8075 int title_bitmap = bm_load(Game_demo_title_screen_fname[gr_screen.res]);
8076 if (title_bitmap == -1) {
8081 gr_set_bitmap(title_bitmap);
8089 bm_unload(title_bitmap);
8090 #endif // FS2_DEMO || OEM_BUILD || FS1_DEMO
8093 // return true if the game is running with "low memory", which is less than 48MB
8094 bool game_using_low_mem()
8096 if (Use_low_mem == 0) {