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;
745 typedef struct big_expl_flash {
746 float max_flash_intensity; // max intensity
747 float cur_flash_intensity; // cur intensity
748 int flash_start; // start time
751 #define FRAME_FILTER 16
753 #define DEFAULT_SKILL_LEVEL 1
754 int Game_skill_level = DEFAULT_SKILL_LEVEL;
756 #define VIEWER_ZOOM_DEFAULT 0.75f // Default viewer zoom, 0.625 as per multi-lateral agreement on 3/24/97
757 float Viewer_zoom = VIEWER_ZOOM_DEFAULT;
759 #define EXE_FNAME ("fs2.exe")
760 #define LAUNCHER_FNAME ("freespace2.exe")
763 // JAS: Code for warphole camera.
764 // Needs to be cleaned up.
765 vector Camera_pos = ZERO_VECTOR;
766 vector Camera_velocity = ZERO_VECTOR;
767 vector Camera_desired_velocity = ZERO_VECTOR;
768 matrix Camera_orient = IDENTITY_MATRIX;
769 float Camera_damping = 1.0f;
770 float Camera_time = 0.0f;
771 float Warpout_time = 0.0f;
772 int Warpout_forced = 0; // Set if this is a forced warpout that cannot be cancelled.
773 int Warpout_sound = -1;
775 int Use_joy_mouse = 0;
776 int Use_palette_flash = 1;
778 int Use_fullscreen_at_startup = 0;
780 int Show_area_effect = 0;
781 object *Last_view_target = NULL;
783 int dogfight_blown = 0;
786 float frametimes[FRAME_FILTER];
787 float frametotal = 0.0f;
791 int Show_framerate = 0;
793 int Show_framerate = 1;
796 int Framerate_cap = 120;
799 int Show_target_debug_info = 0;
800 int Show_target_weapons = 0;
804 static int Show_player_pos = 0; // debug console command to show player world pos on HUD
807 int Debug_octant = -1;
809 fix Game_time_compression = F1_0;
811 // if the ships.tbl the player has is valid
812 int Game_ships_tbl_valid = 0;
814 // if the weapons.tbl the player has is valid
815 int Game_weapons_tbl_valid = 0;
819 extern int Player_attacking_enabled;
823 int Pre_player_entry;
825 int Fred_running = 0;
826 char Game_current_mission_filename[MAX_FILENAME_LEN];
827 int game_single_step = 0;
828 int last_single_step=0;
830 extern int MSG_WINDOW_X_START; // used to position mission_time and shields output
831 extern int MSG_WINDOW_Y_START;
832 extern int MSG_WINDOW_HEIGHT;
834 int game_zbuffer = 1;
835 //static int Game_music_paused;
836 static int Game_paused;
840 #define EXPIRE_BAD_CHECKSUM 1
841 #define EXPIRE_BAD_TIME 2
843 extern void ssm_init();
844 extern void ssm_level_init();
845 extern void ssm_process();
847 // static variable to contain the time this version was built
848 // commented out for now until
849 // I figure out how to get the username into the file
850 //LOCAL char freespace_build_time[] = "Compiled on:"__DATE__" "__TIME__" by "__USER__;
852 // defines and variables used for dumping frame for making trailers.
854 int Debug_dump_frames = 0; // Set to 0 to not dump frames, else equal hz to dump. (15 or 30 probably)
855 int Debug_dump_trigger = 0;
856 int Debug_dump_frame_count;
857 int Debug_dump_frame_num = 0;
858 #define DUMP_BUFFER_NUM_FRAMES 1 // store every 15 frames
861 // amount of time to wait after the player has died before we display the death died popup
862 #define PLAYER_DIED_POPUP_WAIT 2500
863 int Player_died_popup_wait = -1;
864 int Player_multi_died_check = -1;
866 // builtin mission list stuff
868 int Game_builtin_mission_count = 6;
869 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
870 { "SPDemo-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
871 { "SPDemo-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
872 { "DemoTrain.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
873 { "Demo.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE) },
874 { "MPDemo-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
875 { "Demo-DOG-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
877 #elif defined(FS1_DEMO)
878 int Game_builtin_mission_count = 5;
879 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
880 { "btmdemo.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
881 { "demo.fsc", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE) },
882 { "demo01.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
883 { "demo02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
884 { "demo02b.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
886 #elif defined(PD_BUILD)
887 int Game_builtin_mission_count = 4;
888 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
889 { "sm1-01.fs2", (FSB_FROM_VOLITION) },
890 { "sm1-05.fs2", (FSB_FROM_VOLITION) },
891 { "sm1-01", (FSB_FROM_VOLITION) },
892 { "sm1-05", (FSB_FROM_VOLITION) },
894 #elif defined(MULTIPLAYER_BETA)
895 int Game_builtin_mission_count = 17;
896 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
898 { "md-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
899 { "md-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
900 { "md-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
901 { "md-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
902 { "md-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
903 { "md-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
904 { "md-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
905 { "mt-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
906 { "mt-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
907 { "m-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
908 { "m-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
909 { "m-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
910 { "templar-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
911 { "templar-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
912 { "templar-03a.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
913 { "templar-04a.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
914 { "templar.fc2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE) },
916 #elif defined(OEM_BUILD)
917 int Game_builtin_mission_count = 17;
918 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
919 // oem version - act 1 only
920 { "freespace2oem.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE) },
923 { "sm1-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
924 { "sm1-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
925 { "sm1-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
926 { "sm1-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
927 { "sm1-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
928 { "sm1-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
929 { "sm1-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
930 { "sm1-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
931 { "sm1-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
932 { "sm1-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
933 { "training-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
934 { "training-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
935 { "training-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
936 { "tsm-104.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
937 { "tsm-105.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
938 { "tsm-106.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) }
940 #elif defined(MAKE_FS1)
941 int Game_builtin_mission_count = 125;
942 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
943 // single player campaign
944 { "freespace.fsc", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE) },
947 { "sm1-01.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
948 { "sm1-02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
949 { "sm1-03a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
950 { "sm1-04a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
951 { "sm1-05a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
952 { "sm1-06a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
953 { "sm1-07a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
954 { "sm1-08a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
955 { "sm1-09a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
956 { "sm1-10a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
959 { "sm2-01a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
960 { "sm2-02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
961 { "sm2-03a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
962 { "sm2-04a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
963 { "sm2-05a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
964 { "sm2-06a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
965 { "sm2-07a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
966 { "sm2-08a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
967 { "sm2-09a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
968 { "sm2-10a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
971 { "sm3-01a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
972 { "sm3-02a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
973 { "sm3-03a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
974 { "sm3-04a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
975 { "sm3-05a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
976 { "sm3-06a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
977 { "sm3-07a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
978 { "sm3-08a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
979 { "sm3-09a.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
982 { "t-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
983 { "v-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
984 { "s-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
987 { "btm-01.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
988 { "btm-02.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
989 { "btm-03.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
990 { "btm-04.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
991 { "btm-05.fsm", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
994 { "m-hope.fsc", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE) },
995 { "m-altair.fsc", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE) },
997 { "m-v-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
998 { "m-va.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
999 { "m-unstoppable.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1000 { "m-t-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1001 { "m-s-gauntlet.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1002 { "m-rescue.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1003 { "m-pain.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1004 { "m-orecovery.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1005 { "mm3-01a.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1006 { "mm3-02a.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1007 { "mm3-03a.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1008 { "mm3-04a.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1009 { "mm3-05a.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1010 { "mm3-06a.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1011 { "m-guardduty.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1012 { "m-gate.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1013 { "m-duel.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1014 { "m-convoyassault.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1015 { "m-clash.fsm", (FSB_FROM_VOLITION | FSB_MULTI) },
1017 // SilentThreat missions
1018 // Main SilentThreat campaign
1019 { "SilentThreat.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN_FILE) },
1021 { "md-01.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1022 { "md-02.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1023 { "md-03.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1024 { "md-04.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1025 { "md-05.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1026 { "md-06.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1027 { "md-07.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1028 { "md-08.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1029 { "md-09.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1030 { "md-10.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1031 { "md-11.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1032 { "md-12.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_CAMPAIGN) },
1034 // SilentThreat Part 1 - multi-coop
1035 { "ST-Part1.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE) },
1037 { "stmm-01.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1038 { "stmm-02.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1039 { "stmm-03.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1041 // SilentThreat Part 2 - multi-coop
1042 { "ST-Part2.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE) },
1044 { "stmm-04.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1045 { "stmm-05.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1046 { "stmm-06.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1048 // SilentThreat Part 3 - multi-coop
1049 { "ST-Part3.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE) },
1051 { "stmm-07.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1052 { "stmm-08.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1053 { "stmm-09.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1055 // SilentThreat Part 4 - multi-coop
1056 { "ST-Part4.fsc", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN_FILE) },
1058 { "stmm-10.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1059 { "stmm-11.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1060 { "stmm-12.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI | FSB_CAMPAIGN) },
1062 // multiplayer missions
1063 { "mdmm-01.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI) },
1064 { "mdmm-02.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI) },
1065 { "mdmm-03.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI) },
1066 { "mdmm-04.fsm", (FSB_FROM_VOLITION | FSB_FROM_MDISK | FSB_MULTI) },
1067 // user supplied missions
1068 { "mdu-02.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1069 { "mdu-03.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1070 { "mdu-04.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1071 { "mdu-05.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1072 { "mdu-06.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1073 { "mdu-07.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1074 { "mdu-08.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1075 { "mdu-09.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1076 { "mdu-10.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1077 { "mdu-11.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1078 { "mdu-12.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1079 { "mdu-13.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1080 { "mdu-14.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1081 { "mdu-15.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1082 { "mdu-16.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1083 { "mdu-17.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1084 { "mdu-18.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1085 { "mdu-19.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1086 { "mdu-20.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1087 { "mdu-21.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1088 { "mdu-22.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1089 { "mdu-23.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1090 { "mdu-24.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1091 { "mdu-25.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1092 { "mdu-26.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1093 { "mdu-27.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1094 { "mdu-28.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1095 { "mdu-29.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1096 { "mdu-30.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1097 { "mdu-31.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1098 { "mdumm-01.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1099 { "mdumm-02.fsm", (FSB_FROM_MDISK | FSB_MULTI) },
1102 int Game_builtin_mission_count = 92;
1103 fs_builtin_mission Game_builtin_mission_list[MAX_BUILTIN_MISSIONS] = {
1104 // single player campaign
1105 { "freespace2.fc2", (FSB_FROM_VOLITION | FSB_CAMPAIGN_FILE) },
1108 { "sm1-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1109 { "sm1-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1110 { "sm1-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1111 { "sm1-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1112 { "sm1-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1113 { "sm1-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1114 { "sm1-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1115 { "sm1-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1116 { "sm1-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1117 { "sm1-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1118 { "loop1-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1119 { "loop1-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1120 { "loop1-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1121 { "training-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1122 { "training-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1123 { "training-3.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1124 { "tsm-104.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1125 { "tsm-105.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1126 { "tsm-106.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1129 { "sm2-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1130 { "sm2-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1131 { "sm2-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1132 { "sm2-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1133 { "sm2-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1134 { "sm2-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1135 { "sm2-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1136 { "sm2-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1137 { "sm2-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1138 { "sm2-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1141 { "sm3-01.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1142 { "sm3-02.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1143 { "sm3-03.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1144 { "sm3-04.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1145 { "sm3-05.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1146 { "sm3-06.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1147 { "sm3-07.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1148 { "sm3-08.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1149 { "sm3-09.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1150 { "sm3-10.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1151 { "loop2-1.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1152 { "loop2-2.fs2", (FSB_FROM_VOLITION | FSB_CAMPAIGN) },
1154 // multiplayer missions
1157 { "g-shi.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1158 { "g-ter.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1159 { "g-vas.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1162 { "m-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1163 { "m-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1164 { "m-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1165 { "m-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1168 { "mdh-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1169 { "mdh-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1170 { "mdh-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1171 { "mdh-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1172 { "mdh-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1173 { "mdh-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1174 { "mdh-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1175 { "mdh-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1176 { "mdh-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1177 { "mdl-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1178 { "mdl-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1179 { "mdl-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1180 { "mdl-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1181 { "mdl-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1182 { "mdl-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1183 { "mdl-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1184 { "mdl-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1185 { "mdl-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1186 { "mdm-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1187 { "mdm-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1188 { "mdm-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1189 { "mdm-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1190 { "mdm-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1191 { "mdm-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1192 { "mdm-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1193 { "mdm-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1194 { "mdm-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1195 { "osdog.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1198 { "mt-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1199 { "mt-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1200 { "mt-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1201 { "mt-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1202 { "mt-05.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1203 { "mt-06.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1204 { "mt-07.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1205 { "mt-08.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1206 { "mt-09.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1207 { "mt-10.fs2", (FSB_FROM_VOLITION | FSB_MULTI) },
1210 { "templar.fc2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN_FILE) },
1211 { "templar-01.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
1212 { "templar-02.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
1213 { "templar-03.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
1214 { "templar-04.fs2", (FSB_FROM_VOLITION | FSB_MULTI | FSB_CAMPAIGN) },
1219 // Internal function prototypes
1220 void game_maybe_draw_mouse(float frametime);
1221 void init_animating_pointer();
1222 void load_animating_pointer(const char *filename, int dx, int dy);
1223 void unload_animating_pointer();
1224 void game_do_training_checks();
1225 void game_shutdown(void);
1226 void game_show_event_debug(float frametime);
1227 void game_event_debug_init();
1229 void demo_upsell_show_screens();
1230 void game_start_subspace_ambient_sound();
1231 void game_stop_subspace_ambient_sound();
1232 void verify_ships_tbl();
1233 void verify_weapons_tbl();
1234 void display_title_screen();
1236 // loading background filenames
1237 static const char *Game_loading_bground_fname[GR_NUM_RESOLUTIONS] = {
1238 "LoadingBG", // GR_640
1239 "2_LoadingBG" // GR_1024
1243 static const char *Game_loading_ani_fname[GR_NUM_RESOLUTIONS] = {
1244 "Loading.ani", // GR_640
1245 "2_Loading.ani" // GR_1024
1248 #if defined(FS2_DEMO) || defined(FS1_DEMO)
1249 static const char *Game_demo_title_screen_fname[GR_NUM_RESOLUTIONS] = {
1257 #elif defined(OEM_BUILD)
1258 static const char *Game_demo_title_screen_fname[GR_NUM_RESOLUTIONS] = {
1267 // How much RAM is on this machine. Set in WinMain
1268 static int Freespace_total_ram = 0;
1271 float Game_flash_red = 0.0f;
1272 float Game_flash_green = 0.0f;
1273 float Game_flash_blue = 0.0f;
1274 float Sun_spot = 0.0f;
1275 big_expl_flash Big_expl_flash = {0.0f, 0.0f, 0};
1277 // game shudder stuff (in ms)
1278 int Game_shudder_time = -1;
1279 int Game_shudder_total = 0;
1280 float Game_shudder_intensity = 0.0f; // should be between 0.0 and 100.0
1283 sound_env Game_sound_env;
1284 //sound_env Game_default_sound_env = {SND_ENV_AUDITORIUM, 0.25f, 0.35f, 3.0f};
1285 sound_env Game_default_sound_env = {SND_ENV_GENERIC, 0.2F,0.2F,1.0F};
1287 int Game_sound_env_update_timestamp;
1289 // WARPIN CRAP BEGIN --------------------------------------------------------------------------------------------
1292 // WARPIN CRAP END --------------------------------------------------------------------------------------------
1294 fs_builtin_mission *game_find_builtin_mission(const char *filename)
1298 // look through all existing builtin missions
1299 for(idx=0; idx<Game_builtin_mission_count; idx++){
1300 if(!SDL_strcasecmp(Game_builtin_mission_list[idx].filename, filename)){
1301 return &Game_builtin_mission_list[idx];
1309 int game_get_default_skill_level()
1311 return DEFAULT_SKILL_LEVEL;
1315 void game_flash_reset()
1317 Game_flash_red = 0.0f;
1318 Game_flash_green = 0.0f;
1319 Game_flash_blue = 0.0f;
1321 Big_expl_flash.max_flash_intensity = 0.0f;
1322 Big_expl_flash.cur_flash_intensity = 0.0f;
1323 Big_expl_flash.flash_start = 0;
1326 float Gf_critical = -1.0f; // framerate we should be above on the average for this mission
1327 float Gf_critical_time = 0.0f; // how much time we've been at the critical framerate
1329 void game_framerate_check_init()
1331 // zero critical time
1332 Gf_critical_time = 0.0f;
1335 if(The_mission.flags & MISSION_FLAG_FULLNEB){
1336 Gf_critical = 15.0f;
1338 Gf_critical = 25.0f;
1342 extern float Framerate;
1343 void game_framerate_check()
1347 // if the current framerate is above the critical level, add frametime
1348 if(Framerate >= Gf_critical){
1349 Gf_critical_time += flFrametime;
1352 if(!Show_framerate){
1356 // display if we're above the critical framerate
1357 if(Framerate < Gf_critical){
1358 gr_set_color_fast(&Color_bright_red);
1359 gr_string(200, y_start, "Framerate warning");
1364 // display our current pct of good frametime
1365 if(f2fl(Missiontime) >= 0.0f){
1366 float pct = (Gf_critical_time / f2fl(Missiontime)) * 100.0f;
1369 gr_set_color_fast(&Color_bright_green);
1371 gr_set_color_fast(&Color_bright_red);
1374 gr_printf(200, y_start, "%d%%", (int)pct);
1379 // Adds a flash effect. These can be positive or negative.
1380 // The range will get capped at around -1 to 1, so stick
1381 // with a range like that.
1382 void game_flash( float r, float g, float b )
1384 Game_flash_red += r;
1385 Game_flash_green += g;
1386 Game_flash_blue += b;
1388 if ( Game_flash_red < -1.0f ) {
1389 Game_flash_red = -1.0f;
1390 } else if ( Game_flash_red > 1.0f ) {
1391 Game_flash_red = 1.0f;
1394 if ( Game_flash_green < -1.0f ) {
1395 Game_flash_green = -1.0f;
1396 } else if ( Game_flash_green > 1.0f ) {
1397 Game_flash_green = 1.0f;
1400 if ( Game_flash_blue < -1.0f ) {
1401 Game_flash_blue = -1.0f;
1402 } else if ( Game_flash_blue > 1.0f ) {
1403 Game_flash_blue = 1.0f;
1408 // Adds a flash for Big Ship explosions
1409 // cap range from 0 to 1
1410 void big_explosion_flash(float flash)
1412 Big_expl_flash.flash_start = timestamp(1);
1416 } else if (flash < 0.0f) {
1420 Big_expl_flash.max_flash_intensity = flash;
1421 Big_expl_flash.cur_flash_intensity = 0.0f;
1424 // Amount to diminish palette towards normal, per second.
1425 #define DIMINISH_RATE 0.75f
1426 #define SUN_DIMINISH_RATE 6.00f
1430 float sn_glare_scale = 1.7f;
1433 dc_get_arg(ARG_FLOAT);
1434 sn_glare_scale = Dc_arg_float;
1437 float Supernova_last_glare = 0.0f;
1438 void game_sunspot_process(float frametime)
1442 float Sun_spot_goal = 0.0f;
1445 sn_stage = supernova_active();
1447 // sunspot differently based on supernova stage
1449 // approaching. player still in control
1452 pct = (1.0f - (supernova_time_left() / SUPERNOVA_CUT_TIME));
1455 light_get_global_dir(&light_dir, 0);
1457 dot = vm_vec_dot( &light_dir, &Eye_matrix.v.fvec );
1460 // scale it some more
1461 dot = dot * (0.5f + (pct * 0.5f));
1464 Sun_spot_goal += (dot * sn_glare_scale);
1467 // draw the sun glow
1468 if ( !shipfx_eye_in_shadow( &Eye_position, Viewer_obj, 0 ) ) {
1469 // draw the glow for this sun
1470 stars_draw_sun_glow(0);
1473 Supernova_last_glare = Sun_spot_goal;
1476 // camera cut. player not in control. note : at this point camera starts out facing the sun. so we can go nice and bright
1479 Sun_spot_goal = 0.9f;
1480 Sun_spot_goal += (1.0f - (supernova_time_left() / SUPERNOVA_CUT_TIME)) * 0.1f;
1482 if(Sun_spot_goal > 1.0f){
1483 Sun_spot_goal = 1.0f;
1486 Sun_spot_goal *= sn_glare_scale;
1487 Supernova_last_glare = Sun_spot_goal;
1490 // fade to white. display dead popup
1493 Supernova_last_glare += (2.0f * flFrametime);
1494 if(Supernova_last_glare > 2.0f){
1495 Supernova_last_glare = 2.0f;
1498 Sun_spot_goal = Supernova_last_glare;
1505 // check sunspots for all suns
1506 n_lights = light_get_global_count();
1509 for(idx=0; idx<n_lights; idx++){
1510 //(vector *eye_pos, matrix *eye_orient)
1511 if ( !shipfx_eye_in_shadow( &Eye_position, Viewer_obj, idx ) ) {
1514 light_get_global_dir(&light_dir, idx);
1516 float dot = vm_vec_dot( &light_dir, &Eye_matrix.v.fvec )*0.5f+0.5f;
1518 Sun_spot_goal += (float)pow(dot,85.0f);
1520 // draw the glow for this sun
1521 stars_draw_sun_glow(idx);
1523 Sun_spot_goal = 0.0f;
1529 Sun_spot_goal = 0.0f;
1533 float dec_amount = frametime*SUN_DIMINISH_RATE;
1535 if ( Sun_spot < Sun_spot_goal ) {
1536 Sun_spot += dec_amount;
1537 if ( Sun_spot > Sun_spot_goal ) {
1538 Sun_spot = Sun_spot_goal;
1540 } else if ( Sun_spot > Sun_spot_goal ) {
1541 Sun_spot -= dec_amount;
1542 if ( Sun_spot < Sun_spot_goal ) {
1543 Sun_spot = Sun_spot_goal;
1549 // Call once a frame to diminish the
1550 // flash effect to 0.
1551 void game_flash_diminish(float frametime)
1553 float dec_amount = frametime*DIMINISH_RATE;
1555 if ( Game_flash_red > 0.0f ) {
1556 Game_flash_red -= dec_amount;
1557 if ( Game_flash_red < 0.0f )
1558 Game_flash_red = 0.0f;
1560 Game_flash_red += dec_amount;
1561 if ( Game_flash_red > 0.0f )
1562 Game_flash_red = 0.0f;
1565 if ( Game_flash_green > 0.0f ) {
1566 Game_flash_green -= dec_amount;
1567 if ( Game_flash_green < 0.0f )
1568 Game_flash_green = 0.0f;
1570 Game_flash_green += dec_amount;
1571 if ( Game_flash_green > 0.0f )
1572 Game_flash_green = 0.0f;
1575 if ( Game_flash_blue > 0.0f ) {
1576 Game_flash_blue -= dec_amount;
1577 if ( Game_flash_blue < 0.0f )
1578 Game_flash_blue = 0.0f;
1580 Game_flash_blue += dec_amount;
1581 if ( Game_flash_blue > 0.0f )
1582 Game_flash_blue = 0.0f;
1585 // update big_explosion_cur_flash
1586 #define TIME_UP 1500
1587 #define TIME_DOWN 2500
1588 int duration = TIME_UP + TIME_DOWN;
1589 int time = timestamp_until(Big_expl_flash.flash_start);
1590 if (time > -duration) {
1592 if (time < TIME_UP) {
1593 Big_expl_flash.cur_flash_intensity = Big_expl_flash.max_flash_intensity * time / (float) TIME_UP;
1596 Big_expl_flash.cur_flash_intensity = Big_expl_flash.max_flash_intensity * ((float) TIME_DOWN - time) / (float) TIME_DOWN;
1600 if ( Use_palette_flash ) {
1602 // static int or=0, og=0, ob=0;
1604 // Change the 200 to change the color range of colors.
1605 r = fl2i( Game_flash_red*128.0f );
1606 g = fl2i( Game_flash_green*128.0f );
1607 b = fl2i( Game_flash_blue*128.0f );
1609 if ( Sun_spot > 0.0f ) {
1610 r += fl2i(Sun_spot*128.0f);
1611 g += fl2i(Sun_spot*128.0f);
1612 b += fl2i(Sun_spot*128.0f);
1615 if ( Big_expl_flash.cur_flash_intensity > 0.0f ) {
1616 r += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1617 g += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1618 b += fl2i(Big_expl_flash.cur_flash_intensity*128.0f);
1621 if ( r < 0 ) r = 0; else if ( r > 255 ) r = 255;
1622 if ( g < 0 ) g = 0; else if ( g > 255 ) g = 255;
1623 if ( b < 0 ) b = 0; else if ( b > 255 ) b = 255;
1625 if ( (r!=0) || (g!=0) || (b!=0) ) {
1626 gr_flash( r, g, b );
1628 //mprintf(( "Flash! %d,%d,%d\n", r, g, b ));
1639 void game_level_close()
1641 // De-Initialize the game subsystems
1642 event_music_level_close();
1643 game_stop_looped_sounds();
1645 obj_snd_level_close(); // uninit object-linked persistant sounds
1646 gamesnd_unload_gameplay_sounds(); // unload gameplay sounds from memory
1647 anim_level_close(); // stop and clean up any anim instances
1648 message_mission_shutdown(); // called after anim_level_close() to make sure anim instances are free
1649 shockwave_level_close();
1650 fireball_level_close();
1652 mission_event_shutdown();
1653 asteroid_level_close();
1654 flak_level_close(); // unload flak stuff
1655 neb2_level_close(); // shutdown gaseous nebula stuff
1658 mflash_level_close();
1659 mission_brief_common_reset(); // close out parsed briefing/mission stuff
1661 audiostream_unpause_all();
1666 // intializes game stuff and loads the mission. Returns 0 on failure, 1 on success
1667 // input: seed => DEFAULT PARAMETER (value -1). Only set by demo playback code.
1668 void game_level_init(int seed)
1670 // seed the random number generator
1672 // if no seed was passed, seed the generator either from the time value, or from the
1673 // netgame security flags -- ensures that all players in multiplayer game will have the
1674 // same randon number sequence (with static rand functions)
1675 if ( Game_mode & GM_NORMAL ) {
1676 Game_level_seed = time(NULL);
1678 Game_level_seed = Netgame.security;
1681 // mwa 9/17/98 -- maybe this assert isn't needed????
1682 SDL_assert( !(Game_mode & GM_MULTIPLAYER) );
1683 Game_level_seed = seed;
1685 srand( Game_level_seed );
1687 // semirand function needs to get re-initted every time in multiplayer
1688 if ( Game_mode & GM_MULTIPLAYER ){
1694 Key_normal_game = (Game_mode & GM_NORMAL);
1697 Game_shudder_time = -1;
1699 // Initialize the game subsystems
1700 // timestamp_reset(); // Must be inited before everything else
1702 game_reset_time(); // resets time, and resets saved time too
1704 obj_init(); // Must be inited before the other systems
1705 model_free_all(); // Free all existing models
1706 mission_brief_common_init(); // Free all existing briefing/debriefing text
1707 weapon_level_init();
1708 ai_level_init(); // Call this before ship_init() because it reads ai.tbl.
1710 player_level_init();
1711 shipfx_flash_init(); // Init the ship gun flash system.
1712 game_flash_reset(); // Reset the flash effect
1713 particle_init(); // Reset the particle system
1717 shield_hit_init(); // Initialize system for showing shield hits
1718 radar_mission_init();
1719 mission_init_goals();
1722 obj_snd_level_init(); // init object-linked persistant sounds
1724 shockwave_level_init();
1725 afterburner_level_init();
1726 scoring_level_init( &Player->stats );
1728 asteroid_level_init();
1729 control_config_clear_used_status();
1730 collide_ship_ship_sounds_init();
1732 Pre_player_entry = 1; // Means the player has not yet entered.
1733 Entry_delay_time = 0; // Could get overwritten in mission read.
1734 fireball_preload(); // page in warphole bitmaps
1736 flak_level_init(); // initialize flak - bitmaps, etc
1737 ct_level_init(); // initialize ships contrails, etc
1738 awacs_level_init(); // initialize AWACS
1739 beam_level_init(); // initialize beam weapons
1740 mflash_level_init();
1742 supernova_level_init();
1744 // multiplayer dogfight hack
1747 shipfx_engine_wash_level_init();
1751 Last_view_target = NULL;
1756 // campaign wasn't ended
1757 Campaign_ended_in_mission = 0;
1760 // called when a mission is over -- does server specific stuff.
1761 void freespace_stop_mission()
1764 Game_mode &= ~GM_IN_MISSION;
1767 // called at frame interval to process networking stuff
1768 void game_do_networking()
1770 SDL_assert( Net_player != NULL );
1771 if (!(Game_mode & GM_MULTIPLAYER)){
1775 // see if this player should be reading/writing data. Bit is set when at join
1776 // screen onward until quits back to main menu.
1777 if ( !(Net_player->flags & NETINFO_FLAG_DO_NETWORKING) ){
1781 if(gameseq_get_state()!=GS_STATE_MULTI_PAUSED){
1784 multi_pause_do_frame();
1789 // Loads the best palette for this level, based
1790 // on nebula color and hud color. You could just call palette_load_table with
1791 // the appropriate filename, but who wants to do that.
1792 void game_load_palette()
1794 char palette_filename[1024];
1796 // We only use 3 hud colors right now
1798 SDL_assert( HUD_config.main_color >= 0 );
1799 SDL_assert( HUD_config.main_color <= 2 );
1802 SDL_assert( Mission_palette >= 0 );
1803 SDL_assert( Mission_palette <= 98 );
1806 if ( The_mission.flags & MISSION_FLAG_SUBSPACE ) {
1807 strcpy( palette_filename, NOX("gamepalette-subspace") );
1809 sprintf( palette_filename, NOX("gamepalette%d-%02d"), HUD_config.main_color+1, Mission_palette+1 );
1812 mprintf(( "Loading palette %s\n", palette_filename ));
1814 palette_load_table(palette_filename);
1816 strcpy( palette_filename, NOX("gamepalette-subspace") );
1818 mprintf(( "Loading palette %s\n", palette_filename ));
1822 void game_post_level_init()
1824 // Stuff which gets called after mission is loaded. Because player isn't created until
1825 // after mission loads, some things must get initted after the level loads
1827 model_level_post_init();
1830 hud_setup_escort_list();
1831 mission_hotkey_set_defaults(); // set up the default hotkeys (from mission file)
1837 game_event_debug_init();
1840 training_mission_init();
1841 asteroid_create_all();
1843 game_framerate_check_init();
1847 // An estimate as to how high the count passed to game_loading_callback will go.
1848 // This is just a guess, it seems to always be about the same. The count is
1849 // proportional to the code being executed, not the time, so this works good
1850 // for a bar, assuming the code does about the same thing each time you
1851 // load a level. You can find this value by looking at the return value
1852 // of game_busy_callback(NULL), which I conveniently print out to the
1853 // debug output window with the '=== ENDING LOAD ==' stuff.
1854 //#define COUNT_ESTIMATE 3706
1855 #define COUNT_ESTIMATE 1111
1857 int Game_loading_callback_inited = 0;
1859 int Game_loading_background = -1;
1860 anim * Game_loading_ani = NULL;
1861 anim_instance *Game_loading_ani_instance;
1862 int Game_loading_frame=-1;
1864 static int Game_loading_ani_coords[GR_NUM_RESOLUTIONS][2] = {
1866 #if defined(FS1_DEMO)
1868 #elif defined(MAKE_FS1)
1879 // This gets called 10x per second and count is the number of times
1880 // game_busy() has been called since the current callback function
1882 void game_loading_callback(int count)
1884 game_do_networking();
1886 SDL_assert( Game_loading_callback_inited==1 );
1887 SDL_assert( Game_loading_ani != NULL );
1889 int framenum = ((Game_loading_ani->total_frames*count) / COUNT_ESTIMATE)+1;
1890 if ( framenum > Game_loading_ani->total_frames-1 ) {
1891 framenum = Game_loading_ani->total_frames-1;
1892 } else if ( framenum < 0 ) {
1897 while ( Game_loading_frame < framenum ) {
1898 Game_loading_frame++;
1899 cbitmap = anim_get_next_frame(Game_loading_ani_instance);
1903 if ( cbitmap > -1 ) {
1904 if ( Game_loading_background > -1 ) {
1905 gr_set_bitmap( Game_loading_background, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1909 //mprintf(( "Showing frame %d/%d [ Bitmap=%d ]\n", Game_loading_frame , Game_loading_ani->total_frames, cbitmap ));
1910 gr_set_bitmap( cbitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
1911 gr_bitmap(Game_loading_ani_coords[gr_screen.res][0],Game_loading_ani_coords[gr_screen.res][1]);
1913 bm_release(cbitmap);
1919 void game_loading_callback_init()
1921 SDL_assert( Game_loading_callback_inited==0 );
1923 Game_loading_background = bm_load(Game_loading_bground_fname[gr_screen.res]);
1925 common_set_interface_palette("InterfacePalette"); // set the interface palette
1929 Game_loading_ani = anim_load( Game_loading_ani_fname[gr_screen.res]);
1930 SDL_assert( Game_loading_ani != NULL );
1931 Game_loading_ani_instance = init_anim_instance(Game_loading_ani, 16);
1932 SDL_assert( Game_loading_ani_instance != NULL );
1933 Game_loading_frame = -1;
1935 Game_loading_callback_inited = 1;
1937 game_busy_callback( game_loading_callback, (COUNT_ESTIMATE/Game_loading_ani->total_frames)+1 );
1942 void game_loading_callback_close()
1944 SDL_assert( Game_loading_callback_inited==1 );
1946 // Make sure bar shows all the way over.
1947 game_loading_callback(COUNT_ESTIMATE);
1949 int real_count = game_busy_callback( NULL );
1952 Game_loading_callback_inited = 0;
1955 mprintf(( "=================== ENDING LOAD ================\n" ));
1956 mprintf(( "Real count = %d, Estimated count = %d\n", real_count, COUNT_ESTIMATE ));
1957 mprintf(( "================================================\n" ));
1959 // to remove warnings in release build
1963 free_anim_instance(Game_loading_ani_instance);
1964 Game_loading_ani_instance = NULL;
1965 anim_free(Game_loading_ani);
1966 Game_loading_ani = NULL;
1968 bm_release( Game_loading_background );
1969 common_free_interface_palette(); // restore game palette
1970 Game_loading_background = -1;
1972 gr_set_font( FONT1 );
1975 // Update the sound environment (ie change EAX settings based on proximity to large ships)
1977 void game_maybe_update_sound_environment()
1979 // do nothing for now
1982 // Assign the sound environment for the game, based on the current mission
1984 void game_assign_sound_environment()
1987 if (The_mission.flags & MISSION_FLAG_SUBSPACE) {
1988 Game_sound_env.id = SND_ENV_DRUGGED;
1989 Game_sound_env.volume = 0.800f;
1990 Game_sound_env.damping = 1.188f;
1991 Game_sound_env.decay = 6.392f;
1993 } else if (Num_asteroids > 30) {
1994 Game_sound_env.id = SND_ENV_AUDITORIUM;
1995 Game_sound_env.volume = 0.603f;
1996 Game_sound_env.damping = 0.5f;
1997 Game_sound_env.decay = 4.279f;
2000 Game_sound_env = Game_default_sound_env;
2004 Game_sound_env = Game_default_sound_env;
2005 Game_sound_env_update_timestamp = timestamp(1);
2008 // function which gets called before actually entering the mission. It is broken down into a funciton
2009 // since it will get called in one place from a single player game and from another place for
2010 // a multiplayer game
2011 void freespace_mission_load_stuff()
2013 // called if we're not on a freespace dedicated (non rendering, no pilot) server
2014 // IE : we _don't_ want to load any sounds or bitmap/texture info on this machine.
2015 if(!(Game_mode & GM_STANDALONE_SERVER)){
2017 mprintf(( "=================== STARTING LEVEL DATA LOAD ==================\n" ));
2019 game_loading_callback_init();
2021 event_music_level_init(); // preloads the first 2 seconds for each event music track
2024 gamesnd_unload_interface_sounds(); // unload interface sounds from memory
2027 gamesnd_preload_common_sounds(); // load in sounds that are expected to play
2030 ship_assign_sound_all(); // assign engine sounds to ships
2031 game_assign_sound_environment(); // assign the sound environment for this mission
2034 // call function in missionparse.cpp to fixup player/ai stuff.
2035 mission_parse_fixup_players();
2038 // Load in all the bitmaps for this level
2043 game_loading_callback_close();
2045 // the only thing we need to call on the standalone for now.
2047 // call function in missionparse.cpp to fixup player/ai stuff.
2048 mission_parse_fixup_players();
2050 // Load in all the bitmaps for this level
2056 uint load_mission_load;
2057 uint load_post_level_init;
2058 uint load_mission_stuff;
2060 // tells the server to load the mission and initialize structures
2061 int game_start_mission()
2063 mprintf(( "=================== STARTING LEVEL LOAD ==================\n" ));
2065 load_gl_init = time(NULL);
2067 load_gl_init = time(NULL) - load_gl_init;
2069 if (Game_mode & GM_MULTIPLAYER) {
2070 Player->flags |= PLAYER_FLAGS_IS_MULTI;
2072 // clear multiplayer stats
2073 init_multiplayer_stats();
2076 load_mission_load = time(NULL);
2077 if (mission_load()) {
2078 if ( !(Game_mode & GM_MULTIPLAYER) ) {
2079 popup(PF_BODY_BIG, 1, POPUP_OK, XSTR( "Attempt to load the mission failed", 169));
2080 gameseq_post_event(GS_EVENT_MAIN_MENU);
2082 multi_quit_game(PROMPT_NONE, MULTI_END_NOTIFY_NONE, MULTI_END_ERROR_LOAD_FAIL);
2087 load_mission_load = time(NULL) - load_mission_load;
2089 // If this is a red alert mission in campaign mode, bash wingman status
2090 if ( (Game_mode & GM_CAMPAIGN_MODE) && red_alert_mission() ) {
2091 red_alert_bash_wingman_status();
2094 // the standalone server in multiplayer doesn't do any rendering, so we will not even bother loading the palette
2095 if ( !(Game_mode & GM_STANDALONE_SERVER) ) {
2096 mprintf(( "=================== LOADING GAME PALETTE ================\n" ));
2098 game_load_palette();
2102 load_post_level_init = time(NULL);
2103 game_post_level_init();
2104 load_post_level_init = time(NULL) - load_post_level_init;
2108 void Do_model_timings_test();
2109 Do_model_timings_test();
2113 load_mission_stuff = time(NULL);
2114 freespace_mission_load_stuff();
2115 load_mission_stuff = time(NULL) - load_mission_stuff;
2120 int Interface_framerate = 0;
2123 DCF_BOOL( mouse_control, Use_mouse_to_fly )
2124 DCF_BOOL( show_framerate, Show_framerate )
2125 DCF_BOOL( show_target_debug_info, Show_target_debug_info )
2126 DCF_BOOL( show_target_weapons, Show_target_weapons )
2127 DCF_BOOL( lead_target_cheat, Players[Player_num].lead_target_cheat )
2128 DCF_BOOL( sound, Sound_enabled )
2129 DCF_BOOL( zbuffer, game_zbuffer )
2130 DCF_BOOL( shield_system, New_shield_system )
2131 DCF_BOOL( show_shield_mesh, Show_shield_mesh)
2132 DCF_BOOL( player_attacking, Player_attacking_enabled )
2133 DCF_BOOL( show_waypoints, Show_waypoints )
2134 DCF_BOOL( show_area_effect, Show_area_effect )
2135 DCF_BOOL( show_net_stats, Show_net_stats )
2136 DCF_BOOL( log, Log_debug_output_to_file )
2137 DCF_BOOL( training_msg_method, Training_msg_method )
2138 DCF_BOOL( show_player_pos, Show_player_pos )
2139 DCF_BOOL(i_framerate, Interface_framerate )
2141 DCF(show_mem,"Toggles showing mem usage")
2144 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2145 if ( Dc_arg_type & ARG_TRUE ) Show_mem = 1;
2146 else if ( Dc_arg_type & ARG_FALSE ) Show_mem = 0;
2147 else if ( Dc_arg_type & ARG_NONE ) Show_mem ^= 1;
2153 if ( Dc_help ) dc_printf( "Usage: Show_mem\nSets show_mem to true or false. If nothing passed, then toggles it.\n" );
2155 dc_printf( "Show_mem is %s\n", (Show_mem?"TRUE":"FALSE") );
2156 dc_printf( "Show_cpu is %s\n", (Show_cpu?"TRUE":"FALSE") );
2160 DCF(show_cpu,"Toggles showing cpu usage")
2163 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2164 if ( Dc_arg_type & ARG_TRUE ) Show_cpu = 1;
2165 else if ( Dc_arg_type & ARG_FALSE ) Show_cpu = 0;
2166 else if ( Dc_arg_type & ARG_NONE ) Show_cpu ^= 1;
2172 if ( Dc_help ) dc_printf( "Usage: Show_cpu\nSets show_cpu to true or false. If nothing passed, then toggles it.\n" );
2174 dc_printf( "Show_mem is %s\n", (Show_mem?"TRUE":"FALSE") );
2175 dc_printf( "Show_cpu is %s\n", (Show_cpu?"TRUE":"FALSE") );
2182 // AL 4-8-98: always allow players to display their framerate
2185 DCF_BOOL( show_framerate, Show_framerate )
2192 DCF(use_joy_mouse,"Makes joystick move mouse cursor")
2195 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2196 if ( Dc_arg_type & ARG_TRUE ) Use_joy_mouse = 1;
2197 else if ( Dc_arg_type & ARG_FALSE ) Use_joy_mouse = 0;
2198 else if ( Dc_arg_type & ARG_NONE ) Use_joy_mouse ^= 1;
2200 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" );
2201 if ( Dc_status ) dc_printf( "use_joy_mouse is %s\n", (Use_joy_mouse?"TRUE":"FALSE") );
2203 os_config_write_uint( NULL, NOX("JoystickMovesCursor"), Use_joy_mouse );
2206 DCF(palette_flash,"Toggles palette flash effect on/off")
2209 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2210 if ( Dc_arg_type & ARG_TRUE ) Use_palette_flash = 1;
2211 else if ( Dc_arg_type & ARG_FALSE ) Use_palette_flash = 0;
2212 else if ( Dc_arg_type & ARG_NONE ) Use_palette_flash ^= 1;
2214 if ( Dc_help ) dc_printf( "Usage: palette_flash [bool]\nSets palette_flash to true or false. If nothing passed, then toggles it.\n" );
2215 if ( Dc_status ) dc_printf( "palette_flash is %s\n", (Use_palette_flash?"TRUE":"FALSE") );
2218 int Use_low_mem = 0;
2220 DCF(low_mem,"Uses low memory settings regardless of RAM")
2223 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2224 if ( Dc_arg_type & ARG_TRUE ) Use_low_mem = 1;
2225 else if ( Dc_arg_type & ARG_FALSE ) Use_low_mem = 0;
2226 else if ( Dc_arg_type & ARG_NONE ) Use_low_mem ^= 1;
2228 if ( Dc_help ) dc_printf( "Usage: low_mem [bool]\nSets low_mem to true or false. If nothing passed, then toggles it.\n" );
2229 if ( Dc_status ) dc_printf( "low_mem is %s\n", (Use_low_mem?"TRUE":"FALSE") );
2231 os_config_write_uint( NULL, NOX("LowMem"), Use_low_mem );
2237 DCF(force_fullscreen, "Forces game to startup in fullscreen mode")
2240 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2241 if ( Dc_arg_type & ARG_TRUE ) Use_fullscreen_at_startup = 1;
2242 else if ( Dc_arg_type & ARG_FALSE ) Use_fullscreen_at_startup = 0;
2243 else if ( Dc_arg_type & ARG_NONE ) Use_fullscreen_at_startup ^= 1;
2245 if ( Dc_help ) dc_printf( "Usage: force_fullscreen [bool]\nSets force_fullscreen to true or false. If nothing passed, then toggles it.\n" );
2246 if ( Dc_status ) dc_printf( "force_fullscreen is %s\n", (Use_fullscreen_at_startup?"TRUE":"FALSE") );
2247 os_config_write_uint( NULL, NOX("ForceFullscreen"), Use_fullscreen_at_startup );
2251 int Framerate_delay = 0;
2253 float Freespace_gamma = 1.0f;
2255 DCF(gamma,"Sets Gamma factor")
2258 dc_get_arg(ARG_FLOAT|ARG_NONE);
2259 if ( Dc_arg_type & ARG_FLOAT ) {
2260 Freespace_gamma = Dc_arg_float;
2262 dc_printf( "Gamma reset to 1.0f\n" );
2263 Freespace_gamma = 1.0f;
2265 if ( Freespace_gamma < 0.1f ) {
2266 Freespace_gamma = 0.1f;
2267 } else if ( Freespace_gamma > 5.0f ) {
2268 Freespace_gamma = 5.0f;
2270 gr_set_gamma(Freespace_gamma);
2272 char tmp_gamma_string[32];
2273 sprintf( tmp_gamma_string, NOX("%.2f"), Freespace_gamma );
2274 os_config_write_string( NULL, NOX("Gamma"), tmp_gamma_string );
2278 dc_printf( "Usage: gamma <float>\n" );
2279 dc_printf( "Sets gamma in range 1-3, no argument resets to default 1.2\n" );
2280 Dc_status = 0; // don't print status if help is printed. Too messy.
2284 dc_printf( "Gamma = %.2f\n", Freespace_gamma );
2292 Game_current_mission_filename[0] = 0;
2294 // seed the random number generator
2295 Game_init_seed = time(NULL);
2296 srand( Game_init_seed );
2298 Framerate_delay = 0;
2304 extern void bm_init();
2310 // Initialize the timer before the os
2316 //Initialize the libraries
2317 s1 = timer_get_milliseconds();
2318 if ( cfile_init() ) { // initialize before calling any cfopen stuff!!!
2321 e1 = timer_get_milliseconds();
2323 // time a bunch of cfopens
2325 s2 = timer_get_milliseconds();
2327 for(int idx=0; idx<10000; idx++){
2328 whee = cfopen("capital01.pof", "rb", CFILE_NORMAL, CF_TYPE_MODELS);
2333 //cf_exist("capital01.pof", CF_TYPE_MODELS);
2335 e2 = timer_get_milliseconds();
2338 if (Is_standalone) {
2339 std_init_standalone();
2341 os_init( Osreg_class_name, Osreg_app_name );
2342 os_set_title(Osreg_title);
2345 // initialize localization module. Make sure this is down AFTER initialzing OS.
2346 // int t1 = timer_get_milliseconds();
2347 lcl_init( detect_lang() );
2349 // mprintf(("LCL_INIT() TOOK %d MS\n", timer_get_milliseconds()-t1));
2351 // verify that he has a valid ships.tbl (will Game_ships_tbl_valid if so)
2354 // verify that he has a valid weapons.tbl
2355 verify_weapons_tbl();
2357 // Output version numbers to registry for auto patching purposes
2358 os_config_write_uint(NOX("Version"), NOX("Major"), FS_VERSION_MAJOR);
2359 os_config_write_uint(NOX("Version"), NOX("Minor"), FS_VERSION_MINOR);
2360 os_config_write_uint(NOX("Version"), NOX("Build"), FS_VERSION_BUILD);
2362 Use_joy_mouse = 0; //os_config_read_uint( NULL, NOX("JoystickMovesCursor"), 1 );
2363 //Use_palette_flash = os_config_read_uint( NULL, NOX("PaletteFlash"), 0 );
2364 Use_low_mem = os_config_read_uint( NULL, NOX("LowMem"), 0 );
2367 Use_fullscreen_at_startup = os_config_read_uint( NULL, NOX("ForceFullscreen"), 1 );
2370 #if defined (PLAT_UNIX) && defined(RELEASE_REAL)
2371 // show the FPS counter if the config file says so
2372 Show_framerate = os_config_read_uint( NULL, NOX("ShowFPS"), 0 );
2375 #if !(defined(FS2_DEMO) || defined(FS1_DEMO))
2376 Asteroids_enabled = 1;
2379 /////////////////////////////
2381 /////////////////////////////
2385 ptr = os_config_read_string(NULL, NOX("Soundcard"), NULL);
2386 mprintf(("soundcard = %s\n", ptr ? ptr : "<nothing>"));
2388 if (!SDL_strcasecmp(ptr, NOX("no sound"))) {
2389 Cmdline_freespace_no_sound = 1;
2390 } else if ( !SDL_strcasecmp(ptr, NOX("EAX")) || !SDL_strcasecmp(ptr, NOX("Aureal A3D")) ) {
2395 if (!Is_standalone) {
2398 /////////////////////////////
2400 /////////////////////////////
2402 ptr = os_config_read_string(NULL, NOX("Videocard"), NULL);
2405 MessageBox((HWND)os_get_window(), XSTR("Please configure your system in the Launcher before running FS2.\n\n The Launcher will now be started!", 1446), XSTR("Attention!", 1447), MB_OK);
2407 // fire up the UpdateLauncher executable
2409 PROCESS_INFORMATION pi;
2411 memset( &si, 0, sizeof(STARTUPINFO) );
2414 BOOL ret = CreateProcess( LAUNCHER_FNAME, // pointer to name of executable module
2415 NULL, // pointer to command line string
2416 NULL, // pointer to process security attributes
2417 NULL, // pointer to thread security attributes
2418 FALSE, // handle inheritance flag
2419 CREATE_DEFAULT_ERROR_MODE, // creation flags
2420 NULL, // pointer to new environment block
2421 NULL, // pointer to current directory name
2422 &si, // pointer to STARTUPINFO
2423 &pi // pointer to PROCESS_INFORMATION
2426 // If the Launcher could not be started up, let the user know
2428 MessageBox((HWND)os_get_window(), XSTR("The Launcher could not be restarted.", 1450), XSTR("Error", 1451), MB_OK);
2436 // check for hi res pack file
2437 int has_sparky_hi = 0;
2439 // check if sparky_hi exists -- access mode 0 means does file exist
2440 #ifndef MAKE_FS1 // shoudn't have it so don't check
2441 char sparky_path[MAX_PATH];
2442 SDL_snprintf(sparky_path, sizeof(sparky_path), "%s%s%s", Cfile_root_dir, DIR_SEPARATOR_STR, "sparky_hi_fs2.vp");
2444 if ( access(sparky_path, 0) == 0 ) {
2447 mprintf(("No sparky_hi_fs2.vp in directory %s\n", Cfile_root_dir));
2451 if ( !Is_standalone && ptr && strstr(ptr, NOX("OpenGL")) ) {
2452 if(has_sparky_hi && strstr(ptr, NOX("(1024x768)"))){
2453 gr_init(GR_1024, GR_OPENGL);
2455 gr_init(GR_640, GR_OPENGL);
2460 //gr_init(GR_640, GR_OPENGL);
2464 ptr = os_config_read_string(NULL,NOX("Gamma"),NOX("1.80"));
2465 Freespace_gamma = (float)atof(ptr);
2466 if ( Freespace_gamma == 0.0f ) {
2467 Freespace_gamma = 1.80f;
2468 } else if ( Freespace_gamma < 0.1f ) {
2469 Freespace_gamma = 0.1f;
2470 } else if ( Freespace_gamma > 5.0f ) {
2471 Freespace_gamma = 5.0f;
2473 char tmp_gamma_string[32];
2474 sprintf( tmp_gamma_string, NOX("%.2f"), Freespace_gamma );
2475 os_config_write_string( NULL, NOX("Gamma"), tmp_gamma_string );
2477 gr_set_gamma(Freespace_gamma);
2479 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
2482 display_title_screen();
2486 // attempt to load up master tracker registry info (login and password)
2487 Multi_tracker_id = -1;
2489 // pxo login and password
2490 ptr = os_config_read_string(NOX("PXO"),NOX("Login"),NULL);
2492 nprintf(("Network","Error reading in PXO login data\n"));
2493 strcpy(Multi_tracker_login,"");
2495 strcpy(Multi_tracker_login,ptr);
2497 ptr = os_config_read_string(NOX("PXO"),NOX("Password"),NULL);
2499 nprintf(("Network","Error reading PXO password\n"));
2500 strcpy(Multi_tracker_passwd,"");
2502 strcpy(Multi_tracker_passwd,ptr);
2505 // pxo squad name and password
2506 ptr = os_config_read_string(NOX("PXO"),NOX("SquadName"),NULL);
2508 nprintf(("Network","Error reading in PXO squad name\n"));
2509 strcpy(Multi_tracker_squad_name, "");
2511 strcpy(Multi_tracker_squad_name, ptr);
2514 // If less than 48MB of RAM, use low memory model.
2515 if ( (Freespace_total_ram < 48) || Use_low_mem ) {
2516 mprintf(( "Using normal memory settings...\n" ));
2517 bm_set_low_mem(1); // Use every other frame of bitmaps
2519 mprintf(( "Using high memory settings...\n" ));
2520 bm_set_low_mem(0); // Use all frames of bitmaps
2523 // load non-darkening pixel defs
2524 palman_load_pixels();
2526 // hud shield icon stuff
2527 hud_shield_game_init();
2529 control_config_common_init(); // sets up localization stuff in the control config
2535 gamesnd_parse_soundstbl();
2540 // standalone's don't use hte joystick and it seems to sometimes cause them to not get shutdown properly
2545 player_controls_init();
2548 //if(!Is_standalone){
2556 ship_init(); // read in ships.tbl
2558 mission_campaign_init(); // load in the default campaign
2560 // navmap_init(); // init the navigation map system
2561 context_help_init();
2562 techroom_intel_init(); // parse species.tbl, load intel info
2564 psnet_init( Multi_options_g.protocol, Multi_options_g.port ); // initialize the networking code
2565 init_animating_pointer();
2567 mission_brief_common_init(); // Mark all the briefing structures as empty.
2568 gr_font_init(); // loads up all fonts
2570 neb2_init(); // fullneb stuff
2574 player_tips_init(); // helpful tips
2577 // load the list of pilot pic filenames (for barracks and pilot select popup quick reference)
2578 pilot_load_pic_list();
2579 pilot_load_squad_pic_list();
2581 load_animating_pointer(NOX("cursor"), 0, 0);
2583 // initialize alpha colors
2584 alpha_colors_init();
2587 // Game_music_paused = 0;
2594 nprintf(("General", "Ships.tbl is : %s\n", Game_ships_tbl_valid ? "VALID" : "INVALID!!!!"));
2595 nprintf(("General", "Weapons.tbl is : %s\n", Game_weapons_tbl_valid ? "VALID" : "INVALID!!!!"));
2597 mprintf(("cfile_init() took %d\n", e1 - s1));
2598 // mprintf(("1000 cfopens() took %d\n", e2 - s2));
2601 char transfer_text[128];
2603 float Start_time = 0.0f;
2605 float Framerate = 0.0f;
2607 float Timing_total = 0.0f;
2608 float Timing_render2 = 0.0f;
2609 float Timing_render3 = 0.0f;
2610 float Timing_flip = 0.0f;
2611 float Timing_clear = 0.0f;
2613 MONITOR(NumPolysDrawn);
2619 void game_get_framerate()
2621 char text[128] = "";
2623 if ( frame_int == -1 ) {
2625 for (i=0; i<FRAME_FILTER; i++ ) {
2626 frametimes[i] = 0.0f;
2631 frametotal -= frametimes[frame_int];
2632 frametotal += flFrametime;
2633 frametimes[frame_int] = flFrametime;
2634 frame_int = (frame_int + 1 ) % FRAME_FILTER;
2636 if ( frametotal != 0.0 ) {
2637 if ( Framecount >= FRAME_FILTER )
2638 Framerate = FRAME_FILTER / frametotal;
2640 Framerate = Framecount / frametotal;
2641 sprintf( text, NOX("FPS: %.1f"), Framerate );
2643 sprintf( text, NOX("FPS: ?") );
2647 if (Show_framerate) {
2648 gr_set_color_fast(&HUD_color_debug);
2649 gr_string( 570, 2, text );
2653 void game_show_framerate()
2657 cur_time = f2fl(timer_get_approx_seconds());
2658 if (cur_time - Start_time > 30.0f) {
2659 mprintf(("%i frames executed in %7.3f seconds, %7.3f frames per second.\n", Framecount, cur_time - Start_time, Framecount/(cur_time - Start_time)));
2660 Start_time += 1000.0f;
2663 //mprintf(( "%s\n", text ));
2666 if ( Debug_dump_frames )
2670 // possibly show control checking info
2671 control_check_indicate();
2673 // int bitmaps_used_this_frame, bitmaps_new_this_frame;
2674 // bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
2675 // MONITOR_INC(BmpUsed, bitmaps_used_this_frame);
2676 // MONITOR_INC(BmpNew, bitmaps_new_this_frame);
2679 if ( Show_cpu == 1 ) {
2684 dy = gr_get_font_height() + 1;
2686 gr_set_color_fast(&HUD_color_debug);
2689 extern int Gr_textures_in;
2690 gr_printf( sx, sy, NOX("VRAM: %d KB\n"), Gr_textures_in/1024 );
2693 // gr_printf( sx, sy, "BPP: %d", gr_screen.bits_per_pixel );
2695 gr_printf( sx, sy, NOX("DMA: %s"), transfer_text );
2697 gr_printf( sx, sy, NOX("POLYP: %d"), modelstats_num_polys );
2699 gr_printf( sx, sy, NOX("POLYD: %d"), modelstats_num_polys_drawn );
2701 gr_printf( sx, sy, NOX("VERTS: %d"), modelstats_num_verts );
2706 extern int Num_pairs; // Number of object pairs that were checked.
2707 gr_printf( sx, sy, NOX("PAIRS: %d"), Num_pairs );
2710 extern int Num_pairs_checked; // What percent of object pairs were checked.
2711 gr_printf( sx, sy, NOX("FVI: %d"), Num_pairs_checked );
2713 Num_pairs_checked = 0;
2717 gr_printf( sx, sy, NOX("Snds: %d"), snd_num_playing() );
2720 if ( Timing_total > 0.01f ) {
2721 gr_printf( sx, sy, NOX("CLEAR: %.0f%%"), Timing_clear*100.0f/Timing_total );
2723 gr_printf( sx, sy, NOX("REND2D: %.0f%%"), Timing_render2*100.0f/Timing_total );
2725 gr_printf( sx, sy, NOX("REND3D: %.0f%%"), Timing_render3*100.0f/Timing_total );
2727 gr_printf( sx, sy, NOX("FLIP: %.0f%%"), Timing_flip*100.0f/Timing_total );
2729 gr_printf( sx, sy, NOX("GAME: %.0f%%"), (Timing_total-(Timing_render2+Timing_render3+Timing_flip+Timing_clear))*100.0f/Timing_total );
2738 dy = gr_get_font_height() + 1;
2740 gr_set_color_fast(&HUD_color_debug);
2743 extern int TotalRam;
2744 gr_printf( sx, sy, NOX("DYN: %d KB\n"), TotalRam/1024 );
2749 extern int Model_ram;
2750 gr_printf( sx, sy, NOX("POF: %d KB\n"), Model_ram/1024 );
2754 gr_printf( sx, sy, NOX("BMP: %d KB\n"), bm_texture_ram/1024 );
2756 gr_printf( sx, sy, NOX("S-SRAM: %d KB\n"), Snd_sram/1024 ); // mem used to store game sound
2760 extern int Gr_textures_in;
2761 gr_printf( sx, sy, NOX("VRAM: %d KB\n"), Gr_textures_in/1024 );
2766 if ( Show_player_pos ) {
2770 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));
2773 MONITOR_INC(NumPolys, modelstats_num_polys);
2774 MONITOR_INC(NumPolysDrawn, modelstats_num_polys_drawn );
2775 MONITOR_INC(NumVerts, modelstats_num_verts );
2777 modelstats_num_polys = 0;
2778 modelstats_num_polys_drawn = 0;
2779 modelstats_num_verts = 0;
2780 modelstats_num_sortnorms = 0;
2784 void game_show_standalone_framerate()
2786 float frame_rate=30.0f;
2787 if ( frame_int == -1 ) {
2789 for (i=0; i<FRAME_FILTER; i++ ) {
2790 frametimes[i] = 0.0f;
2795 frametotal -= frametimes[frame_int];
2796 frametotal += flFrametime;
2797 frametimes[frame_int] = flFrametime;
2798 frame_int = (frame_int + 1 ) % FRAME_FILTER;
2800 if ( frametotal != 0.0 ) {
2801 if ( Framecount >= FRAME_FILTER ){
2802 frame_rate = FRAME_FILTER / frametotal;
2804 frame_rate = Framecount / frametotal;
2807 std_set_standalone_fps(frame_rate);
2811 // function to show the time remaining in a mission. Used only when the end-mission sexpression is used
2812 void game_show_time_left()
2816 // mission_end_time is a global from missionparse.cpp that contains the mission time at which the
2817 // mission should end (in fixed seconds). There is code in missionparse.cpp which actually handles
2818 // checking how much time is left
2820 if ( Mission_end_time == -1 ){
2824 diff = f2i(Mission_end_time - Missiontime);
2825 // be sure to bash to 0. diff could be negative on frame that we quit mission
2830 hud_set_default_color();
2831 gr_printf( 5, 40, XSTR( "Mission time remaining: %d seconds", 179), diff );
2834 //========================================================================================
2835 //=================== NEW DEBUG CONSOLE COMMANDS TO REPLACE OLD DEBUG PAUSE MENU =========
2836 //========================================================================================
2840 DCF(ai_pause,"Pauses ai")
2843 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2844 if ( Dc_arg_type & ARG_TRUE ) ai_paused = 1;
2845 else if ( Dc_arg_type & ARG_FALSE ) ai_paused = 0;
2846 else if ( Dc_arg_type & ARG_NONE ) ai_paused = !ai_paused;
2849 obj_init_all_ships_physics();
2852 if ( Dc_help ) dc_printf( "Usage: ai_paused [bool]\nSets ai_paused to true or false. If nothing passed, then toggles it.\n" );
2853 if ( Dc_status ) dc_printf( "ai_paused is %s\n", (ai_paused?"TRUE":"FALSE") );
2856 DCF(single_step,"Single steps the game")
2859 dc_get_arg(ARG_TRUE|ARG_FALSE|ARG_NONE);
2860 if ( Dc_arg_type & ARG_TRUE ) game_single_step = 1;
2861 else if ( Dc_arg_type & ARG_FALSE ) game_single_step = 0;
2862 else if ( Dc_arg_type & ARG_NONE ) game_single_step = !game_single_step;
2864 last_single_step = 0; // Make so single step waits a frame before stepping
2867 if ( Dc_help ) dc_printf( "Usage: single_step [bool]\nSets single_step to true or false. If nothing passed, then toggles it.\n" );
2868 if ( Dc_status ) dc_printf( "single_step is %s\n", (game_single_step?"TRUE":"FALSE") );
2871 DCF_BOOL(physics_pause, physics_paused)
2872 DCF_BOOL(ai_rendering, Ai_render_debug_flag)
2873 DCF_BOOL(ai_firing, Ai_firing_enabled )
2875 // Create some simple aliases to these commands...
2876 debug_command dc_s("s","shortcut for single_step",dcf_single_step);
2877 debug_command dc_p("p","shortcut for physics_pause", dcf_physics_pause );
2878 debug_command dc_r("r","shortcut for ai_rendering", dcf_ai_rendering );
2879 debug_command dc_f("f","shortcut for ai_firing", dcf_ai_firing);
2880 debug_command dc_a("a","shortcut for ai_pause", dcf_ai_pause);
2883 //========================================================================================
2884 //========================================================================================
2887 void game_training_pause_do()
2891 key = game_check_key();
2893 gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
2900 void game_increase_skill_level()
2903 if (Game_skill_level >= NUM_SKILL_LEVELS){
2904 Game_skill_level = 0;
2908 int Player_died_time;
2910 int View_percent = 100;
2913 DCF(view, "Sets the percent of the 3d view to render.")
2916 dc_get_arg(ARG_INT);
2917 if ( (Dc_arg_int >= 5 ) || (Dc_arg_int <= 100) ) {
2918 View_percent = Dc_arg_int;
2920 dc_printf( "Illegal value for view. (Must be from 5-100) \n\n");
2926 dc_printf("Usage: view [n]\nwhere n is percent of view to show (5-100).\n");
2930 dc_printf("View is set to %d%%\n", View_percent );
2935 // Set the clip region for the 3d rendering window
2936 void game_set_view_clip()
2938 if ((Game_mode & GM_DEAD) || (supernova_active() >= 2)) {
2939 // Set the clip region for the letterbox "dead view"
2940 int yborder = gr_screen.max_h/4;
2942 // Numeric constants encouraged by J "pig farmer" S, who shall remain semi-anonymous.
2943 // J.S. I've changed my ways!! See the new "no constants" code!!!
2944 gr_set_clip(0, yborder, gr_screen.max_w, gr_screen.max_h - yborder*2 );
2946 // Set the clip region for normal view
2947 if ( View_percent >= 100 ) {
2950 int xborder, yborder;
2952 if ( View_percent < 5 ) {
2956 float fp = i2fl(View_percent)/100.0f;
2957 int fi = fl2i(fl_sqrt(fp)*100.0f);
2958 if ( fi > 100 ) fi=100;
2960 xborder = ( gr_screen.max_w*(100-fi) )/200;
2961 yborder = ( gr_screen.max_h*(100-fi) )/200;
2963 gr_set_clip(xborder, yborder, gr_screen.max_w-xborder*2,gr_screen.max_h-yborder*2 );
2969 void show_debug_stuff()
2972 int laser_count = 0, missile_count = 0;
2974 for (i=0; i<MAX_OBJECTS; i++) {
2975 if (Objects[i].type == OBJ_WEAPON){
2976 if (Weapon_info[Weapons[Objects[i].instance].weapon_info_index].subtype == WP_LASER){
2978 } else if (Weapon_info[Weapons[Objects[i].instance].weapon_info_index].subtype == WP_MISSILE){
2984 nprintf(("Mike", "Frame: %i Lasers: %4i, Missiles: %4i\n", Framecount, laser_count, missile_count));
2987 extern int Tool_enabled;
2992 int tst_bitmap = -1;
2994 float tst_offset, tst_offset_total;
2997 void game_tst_frame_pre()
3005 g3_rotate_vertex(&v, &tst_pos);
3006 g3_project_vertex(&v);
3009 if(!((v.sx >= 0) && (v.sx <= gr_screen.max_w) && (v.sy >= 0) && (v.sy <= gr_screen.max_h))){
3013 // big ship? always tst
3015 // within 3000 meters
3016 if( vm_vec_dist_quick(&tst_pos, &Eye_position) <= 3000.0f){
3020 // within 300 meters
3021 if( (vm_vec_dist_quick(&tst_pos, &Eye_position) <= 300.0f) && ((tst_time == 0) || ((time(NULL) - tst_time) >= 10)) ){
3028 void game_tst_frame()
3038 tst_time = time(NULL);
3040 // load the tst bitmap
3041 switch((int)frand_range(0.0f, 3.0)){
3043 tst_bitmap = bm_load("ig_jim");
3045 mprintf(("TST 0\n"));
3049 tst_bitmap = bm_load("ig_kan");
3051 mprintf(("TST 1\n"));
3055 tst_bitmap = bm_load("ig_jim");
3057 mprintf(("TST 2\n"));
3061 tst_bitmap = bm_load("ig_kan");
3063 mprintf(("TST 3\n"));
3072 // get the tst bitmap dimensions
3074 bm_get_info(tst_bitmap, &w, &h);
3077 tst_y = frand_range(0.0f, (float)gr_screen.max_h - h);
3079 snd_play(&Snds[SND_VASUDAN_BUP]);
3081 // tst x and direction
3085 tst_offset_total = (float)w;
3086 tst_offset = (float)w;
3088 tst_x = (float)gr_screen.max_w;
3089 tst_offset_total = (float)-w;
3090 tst_offset = (float)w;
3098 float diff = (tst_offset_total / 0.5f) * flFrametime;
3104 tst_offset -= fl_abs(diff);
3105 } else if(tst_mode == 2){
3108 tst_offset -= fl_abs(diff);
3112 gr_set_bitmap(tst_bitmap, GR_ALPHABLEND_NONE, GR_BITBLT_MODE_NORMAL, 1.0f, -1, -1);
3113 gr_bitmap((int)tst_x, (int)tst_y);
3116 if(timestamp_elapsed_safe(tst_stamp, 1100)){
3120 // if we passed the switch point
3121 if(tst_offset <= 0.0f){
3126 tst_stamp = timestamp(1000);
3127 tst_offset = fl_abs(tst_offset_total);
3138 void game_tst_mark(object *objp, ship *shipp)
3147 if((objp == NULL) || (shipp == NULL) || (shipp->ship_info_index < 0) || (shipp->ship_info_index >= Num_ship_types)){
3150 sip = &Ship_info[shipp->ship_info_index];
3157 tst_pos = objp->pos;
3158 if(sip->flags & (SIF_BIG_SHIP | SIF_HUGE_SHIP)){
3164 extern void render_shields();
3166 void player_repair_frame(float frametime)
3168 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
3170 for(idx=0;idx<MAX_PLAYERS;idx++){
3173 np = &Net_players[idx];
3175 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)){
3177 // don't rearm/repair if the player is dead or dying/departing
3178 if ( !NETPLAYER_IS_DEAD(np) && !(Ships[Objects[np->player->objnum].instance].flags & (SF_DYING|SF_DEPARTING)) ) {
3179 ai_do_repair_frame(&Objects[Net_players[idx].player->objnum],&Ai_info[Ships[Objects[Net_players[idx].player->objnum].instance].ai_index],frametime);
3184 if ( (Player_obj != NULL) && (Player_obj->type == OBJ_SHIP) && !(Game_mode & GM_STANDALONE_SERVER) && (Player_ship != NULL) && !(Player_ship->flags & SF_DYING) ) {
3185 ai_do_repair_frame(Player_obj, &Ai_info[Ships[Player_obj->instance].ai_index], frametime);
3191 #define NUM_FRAMES_TEST 300
3192 #define NUM_MIXED_SOUNDS 16
3193 void do_timing_test(float flFrametime)
3195 static int framecount = 0;
3196 static int test_running = 0;
3197 static float test_time = 0.0f;
3199 static int snds[NUM_MIXED_SOUNDS];
3202 if ( test_running ) {
3204 test_time += flFrametime;
3205 if ( framecount >= NUM_FRAMES_TEST ) {
3207 nprintf(("General", "%d frames took %.3f seconds\n", NUM_FRAMES_TEST, test_time));
3208 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3213 if ( Test_begin == 1 ) {
3219 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3222 // start looping digital sounds
3223 for ( i = 0; i < NUM_MIXED_SOUNDS; i++ )
3224 snds[i] = snd_play_looping( &Snds[i], 0.0f);
3231 DCF(dcf_fov, "Change the field of view")
3234 dc_get_arg(ARG_FLOAT|ARG_NONE);
3235 if ( Dc_arg_type & ARG_NONE ) {
3236 Viewer_zoom = VIEWER_ZOOM_DEFAULT;
3237 dc_printf( "Zoom factor reset\n" );
3239 if ( Dc_arg_type & ARG_FLOAT ) {
3240 if (Dc_arg_float < 0.25f) {
3241 Viewer_zoom = 0.25f;
3242 dc_printf("Zoom factor pinned at 0.25.\n");
3243 } else if (Dc_arg_float > 1.25f) {
3244 Viewer_zoom = 1.25f;
3245 dc_printf("Zoom factor pinned at 1.25.\n");
3247 Viewer_zoom = Dc_arg_float;
3253 dc_printf( "Usage: fov [factor]\nFactor is the zoom factor btwn .25 and 1.25\nNo parameter resets it to default.\n" );
3256 dc_printf("Zoom factor set to %6.3f (original = 0.5, John = 0.75)", Viewer_zoom);
3260 DCF(framerate_cap, "Sets the framerate cap")
3263 dc_get_arg(ARG_INT);
3264 if ( (Dc_arg_int >= 1 ) || (Dc_arg_int <= 120) ) {
3265 Framerate_cap = Dc_arg_int;
3267 dc_printf( "Illegal value for framerate cap. (Must be from 1-120) \n\n");
3273 dc_printf("Usage: framerate_cap [n]\nwhere n is the frames per second to cap framerate at.\n");
3274 dc_printf("If n is 0 or omitted, then the framerate cap is removed\n");
3275 dc_printf("[n] must be from 1 to 120.\n");
3279 if ( Framerate_cap )
3280 dc_printf("Framerate cap is set to %d fps\n", Framerate_cap );
3282 dc_printf("There is no framerate cap currently active.\n");
3286 #define MIN_DIST_TO_DEAD_CAMERA 50.0f
3287 int Show_viewing_from_self = 0;
3289 void say_view_target()
3291 object *view_target;
3293 if ((Viewer_mode & VM_OTHER_SHIP) && (Player_ai->target_objnum != -1))
3294 view_target = &Objects[Player_ai->target_objnum];
3296 view_target = Player_obj;
3298 if (Game_mode & GM_DEAD) {
3299 if (Player_ai->target_objnum != -1)
3300 view_target = &Objects[Player_ai->target_objnum];
3303 if (!(Game_mode & GM_DEAD_DIED) && ((Game_mode & (GM_DEAD_BLEW_UP)) || ((Last_view_target != NULL) && (Last_view_target != view_target)))) {
3304 if (view_target != Player_obj){
3306 char *view_target_name = NULL;
3307 switch(Objects[Player_ai->target_objnum].type) {
3309 view_target_name = Ships[Objects[Player_ai->target_objnum].instance].ship_name;
3312 view_target_name = Weapon_info[Weapons[Objects[Player_ai->target_objnum].instance].weapon_info_index].name;
3313 Viewer_mode &= ~VM_OTHER_SHIP;
3315 case OBJ_JUMP_NODE: {
3316 char jump_node_name[128];
3317 strcpy(jump_node_name, XSTR( "jump node", 184));
3318 view_target_name = jump_node_name;
3319 Viewer_mode &= ~VM_OTHER_SHIP;
3328 if ( view_target_name ) {
3329 HUD_fixed_printf(0.0f, XSTR( "Viewing %s%s\n", 185), (Viewer_mode & VM_OTHER_SHIP) ? XSTR( "from ", 186) : "", view_target_name);
3330 Show_viewing_from_self = 1;
3333 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER) && (Player_obj->type == OBJ_OBSERVER)){
3334 HUD_fixed_printf(2.0f,XSTR( "Viewing from observer\n", 187));
3335 Show_viewing_from_self = 1;
3337 if (Show_viewing_from_self)
3338 HUD_fixed_printf(2.0f, XSTR( "Viewing from self\n", 188));
3343 Last_view_target = view_target;
3347 float Game_hit_x = 0.0f;
3348 float Game_hit_y = 0.0f;
3350 // Reset at the beginning of each frame
3351 void game_whack_reset()
3357 // Apply a 2d whack to the player
3358 void game_whack_apply( float x, float y )
3360 // Do some force feedback
3361 joy_ff_play_dir_effect(x * 80.0f, y * 80.0f);
3367 // mprintf(( "WHACK = %.1f, %.1f\n", Game_hit_x, Game_hit_y ));
3370 // call to apply a "shudder"
3371 void game_shudder_apply(int time, float intensity)
3373 Game_shudder_time = timestamp(time);
3374 Game_shudder_total = time;
3375 Game_shudder_intensity = intensity;
3378 #define FF_SCALE 10000
3379 void apply_hud_shake(matrix *eye_orient)
3381 if (Viewer_obj == Player_obj) {
3382 physics_info *pi = &Player_obj->phys_info;
3390 // Make eye shake due to afterburner
3391 if ( !timestamp_elapsed(pi->afterburner_decay) ) {
3394 dtime = timestamp_until(pi->afterburner_decay);
3398 tangles.p += 0.07f * (float) (r1-MY_RAND_MAX/2)/MY_RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/ABURN_DECAY_TIME));
3399 tangles.h += 0.07f * (float) (r2-MY_RAND_MAX/2)/MY_RAND_MAX * (0.5f - fl_abs(0.5f - (float) dtime/ABURN_DECAY_TIME));
3402 // Make eye shake due to engine wash
3404 if (Player_obj->type == OBJ_SHIP && (Ships[Player_obj->instance].wash_intensity > 0) && Wash_on ) {
3407 tangles.p += 0.07f * Ships[Player_obj->instance].wash_intensity * (float) (r1-MY_RAND_MAX/2)/MY_RAND_MAX;
3408 tangles.h += 0.07f * Ships[Player_obj->instance].wash_intensity * (float) (r2-MY_RAND_MAX/2)/MY_RAND_MAX;
3410 // get the intensity
3411 float intensity = FF_SCALE * Ships[Player_obj->instance].wash_intensity;
3415 vm_vec_rand_vec_quick(&rand_vec);
3418 joy_ff_play_dir_effect(intensity*rand_vec.xyz.x, intensity*rand_vec.xyz.y);
3422 // make hud shake due to shuddering
3423 if(Game_shudder_time != -1){
3424 // if the timestamp has elapsed
3425 if(timestamp_elapsed(Game_shudder_time)){
3426 Game_shudder_time = -1;
3428 // otherwise apply some shudder
3432 dtime = timestamp_until(Game_shudder_time);
3436 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));
3437 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));
3442 vm_angles_2_matrix(&tm, &tangles);
3443 SDL_assert(vm_vec_mag(&tm.v.fvec) > 0.0f);
3444 SDL_assert(vm_vec_mag(&tm.v.rvec) > 0.0f);
3445 SDL_assert(vm_vec_mag(&tm.v.uvec) > 0.0f);
3446 vm_matrix_x_matrix(&tm2, eye_orient, &tm);
3451 extern void compute_slew_matrix(matrix *orient, angles *a); // TODO: move code to proper place and extern in header file
3453 // Player's velocity just before he blew up. Used to keep camera target moving.
3454 vector Dead_player_last_vel = { { { 1.0f, 1.0f, 1.0f } } };
3456 // Set eye_pos and eye_orient based on view mode.
3457 void game_render_frame_setup(vector *eye_pos, matrix *eye_orient)
3461 static int last_Viewer_mode = 0;
3462 static int last_Game_mode = 0;
3463 static int last_Viewer_objnum = -1;
3465 // This code is supposed to detect camera "cuts"... like going between
3468 // determine if we need to regenerate the nebula
3469 if( (!(last_Viewer_mode & VM_EXTERNAL) && (Viewer_mode & VM_EXTERNAL)) || // internal to external
3470 ((last_Viewer_mode & VM_EXTERNAL) && !(Viewer_mode & VM_EXTERNAL)) || // external to internal
3471 (!(last_Viewer_mode & VM_DEAD_VIEW) && (Viewer_mode & VM_DEAD_VIEW)) || // non dead-view to dead-view
3472 ((last_Viewer_mode & VM_DEAD_VIEW) && !(Viewer_mode & VM_DEAD_VIEW)) || // dead-view to non dead-view
3473 (!(last_Viewer_mode & VM_WARP_CHASE) && (Viewer_mode & VM_WARP_CHASE)) || // non warp-chase to warp-chase
3474 ((last_Viewer_mode & VM_WARP_CHASE) && !(Viewer_mode & VM_WARP_CHASE)) || // warp-chase to non warp-chase
3475 (!(last_Viewer_mode & VM_OTHER_SHIP) && (Viewer_mode & VM_OTHER_SHIP)) || // non other-ship to other-ship
3476 ((last_Viewer_mode & VM_OTHER_SHIP) && !(Viewer_mode & VM_OTHER_SHIP)) || // other-ship to non-other ship
3477 ((Viewer_mode & VM_OTHER_SHIP) && (last_Viewer_objnum != Player_ai->target_objnum)) // other ship mode, but targets changes
3480 // regenerate the nebula
3484 if ( (last_Viewer_mode != Viewer_mode) || (last_Game_mode != Game_mode) ) {
3485 //mprintf(( "************** Camera cut! ************\n" ));
3486 last_Viewer_mode = Viewer_mode;
3487 last_Game_mode = Game_mode;
3489 // Camera moved. Tell stars & debris to not do blurring.
3495 if ( Viewer_mode & VM_PADLOCK_ANY ) {
3496 player_display_packlock_view();
3499 game_set_view_clip();
3501 if (Game_mode & GM_DEAD) {
3502 vector vec_to_deader, view_pos;
3505 Viewer_mode |= VM_DEAD_VIEW;
3507 if (Player_ai->target_objnum != -1) {
3508 int view_from_player = 1;
3510 if (Viewer_mode & VM_OTHER_SHIP) {
3511 // View from target.
3512 Viewer_obj = &Objects[Player_ai->target_objnum];
3514 last_Viewer_objnum = Player_ai->target_objnum;
3516 if ( Viewer_obj->type == OBJ_SHIP ) {
3517 ship_get_eye( eye_pos, eye_orient, Viewer_obj );
3518 view_from_player = 0;
3521 last_Viewer_objnum = -1;
3524 if ( view_from_player ) {
3525 // View target from player ship.
3527 *eye_pos = Player_obj->pos;
3528 vm_vec_normalized_dir(&eye_dir, &Objects[Player_ai->target_objnum].pos, eye_pos);
3529 vm_vector_2_matrix(eye_orient, &eye_dir, NULL, NULL);
3532 dist = vm_vec_normalized_dir(&vec_to_deader, &Player_obj->pos, &Dead_camera_pos);
3534 if (dist < MIN_DIST_TO_DEAD_CAMERA)
3535 dist += flFrametime * 16.0f;
3537 vm_vec_scale(&vec_to_deader, -dist);
3538 vm_vec_add(&Dead_camera_pos, &Player_obj->pos, &vec_to_deader);
3540 view_pos = Player_obj->pos;
3542 if (!(Game_mode & GM_DEAD_BLEW_UP)) {
3543 Viewer_mode &= ~(VM_EXTERNAL | VM_CHASE);
3544 vm_vec_scale_add2(&Dead_camera_pos, &Original_vec_to_deader, 25.0f * flFrametime);
3545 Dead_player_last_vel = Player_obj->phys_info.vel;
3546 //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));
3547 } else if (Player_ai->target_objnum != -1) {
3548 view_pos = Objects[Player_ai->target_objnum].pos;
3550 // Make camera follow explosion, but gradually slow down.
3551 vm_vec_scale_add2(&Player_obj->pos, &Dead_player_last_vel, flFrametime);
3552 view_pos = Player_obj->pos;
3553 vm_vec_scale(&Dead_player_last_vel, 0.99f);
3554 vm_vec_scale_add2(&Dead_camera_pos, &Original_vec_to_deader, min(25.0f, vm_vec_mag_quick(&Dead_player_last_vel)) * flFrametime);
3557 *eye_pos = Dead_camera_pos;
3559 vm_vec_normalized_dir(&eye_dir, &Player_obj->pos, eye_pos);
3561 vm_vector_2_matrix(eye_orient, &eye_dir, NULL, NULL);
3566 // if supernova shockwave
3567 if(supernova_camera_cut()){
3571 // call it dead view
3572 Viewer_mode |= VM_DEAD_VIEW;
3574 // set eye pos and orient
3575 supernova_set_view(eye_pos, eye_orient);
3577 // If already blown up, these other modes can override.
3578 if (!(Game_mode & (GM_DEAD | GM_DEAD_BLEW_UP))) {
3579 Viewer_mode &= ~VM_DEAD_VIEW;
3581 Viewer_obj = Player_obj;
3583 if (Viewer_mode & VM_OTHER_SHIP) {
3584 if (Player_ai->target_objnum != -1){
3585 Viewer_obj = &Objects[Player_ai->target_objnum];
3586 last_Viewer_objnum = Player_ai->target_objnum;
3588 Viewer_mode &= ~VM_OTHER_SHIP;
3589 last_Viewer_objnum = -1;
3592 last_Viewer_objnum = -1;
3595 if (Viewer_mode & VM_EXTERNAL) {
3598 vm_angles_2_matrix(&tm2, &Viewer_external_info.angles);
3599 vm_matrix_x_matrix(&tm, &Viewer_obj->orient, &tm2);
3601 vm_vec_scale_add(eye_pos, &Viewer_obj->pos, &tm.v.fvec, 2.0f * Viewer_obj->radius + Viewer_external_info.distance);
3603 vm_vec_sub(&eye_dir, &Viewer_obj->pos, eye_pos);
3604 vm_vec_normalize(&eye_dir);
3605 vm_vector_2_matrix(eye_orient, &eye_dir, &Viewer_obj->orient.v.uvec, NULL);
3608 // Modify the orientation based on head orientation.
3609 compute_slew_matrix(eye_orient, &Viewer_slew_angles);
3611 } else if ( Viewer_mode & VM_CHASE ) {
3614 if ( Viewer_obj->phys_info.speed < 0.1 )
3615 move_dir = Viewer_obj->orient.v.fvec;
3617 move_dir = Viewer_obj->phys_info.vel;
3618 vm_vec_normalize(&move_dir);
3621 vm_vec_scale_add(eye_pos, &Viewer_obj->pos, &move_dir, -3.0f * Viewer_obj->radius - Viewer_chase_info.distance);
3622 vm_vec_scale_add2(eye_pos, &Viewer_obj->orient.v.uvec, 0.75f * Viewer_obj->radius);
3623 vm_vec_sub(&eye_dir, &Viewer_obj->pos, eye_pos);
3624 vm_vec_normalize(&eye_dir);
3626 // JAS: I added the following code because if you slew up using
3627 // Descent-style physics, eye_dir and Viewer_obj->orient.v.uvec are
3628 // equal, which causes a zero-length vector in the vm_vector_2_matrix
3629 // call because the up and the forward vector are the same. I fixed
3630 // it by adding in a fraction of the right vector all the time to the
3632 vector tmp_up = Viewer_obj->orient.v.uvec;
3633 vm_vec_scale_add2( &tmp_up, &Viewer_obj->orient.v.rvec, 0.00001f );
3635 vm_vector_2_matrix(eye_orient, &eye_dir, &tmp_up, NULL);
3638 // Modify the orientation based on head orientation.
3639 compute_slew_matrix(eye_orient, &Viewer_slew_angles);
3640 } else if ( Viewer_mode & VM_WARP_CHASE ) {
3641 *eye_pos = Camera_pos;
3643 ship * shipp = &Ships[Player_obj->instance];
3645 vm_vec_sub(&eye_dir, &shipp->warp_effect_pos, eye_pos);
3646 vm_vec_normalize(&eye_dir);
3647 vm_vector_2_matrix(eye_orient, &eye_dir, &Player_obj->orient.v.uvec, NULL);
3650 // get an eye position based upon the correct type of object
3651 switch(Viewer_obj->type){
3653 // make a call to get the eye point for the player object
3654 ship_get_eye( eye_pos, eye_orient, Viewer_obj );
3657 // make a call to get the eye point for the player object
3658 observer_get_eye( eye_pos, eye_orient, Viewer_obj );
3664 #ifdef JOHNS_DEBUG_CODE
3665 john_debug_stuff(&eye_pos, &eye_orient);
3671 apply_hud_shake(eye_orient);
3673 // setup neb2 rendering
3674 neb2_render_setup(eye_pos, eye_orient);
3678 extern void ai_debug_render_stuff();
3681 int Game_subspace_effect = 0;
3682 DCF_BOOL( subspace, Game_subspace_effect );
3684 // Does everything needed to render a frame
3685 void game_render_frame( vector * eye_pos, matrix * eye_orient )
3689 g3_start_frame(game_zbuffer);
3690 g3_set_view_matrix( eye_pos, eye_orient, Viewer_zoom );
3692 // maybe offset the HUD (jitter stuff)
3693 dont_offset = ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER));
3694 HUD_set_offsets(Viewer_obj, !dont_offset);
3696 // for multiplayer clients, call code in Shield.cpp to set up the Shield_hit array. Have to
3697 // do this becaues of the disjointed nature of this system (in terms of setup and execution).
3698 // must be done before ships are rendered
3699 if ( MULTIPLAYER_CLIENT ) {
3700 shield_point_multi_setup();
3703 if ( Game_subspace_effect ) {
3704 stars_draw(0,0,0,1);
3706 stars_draw(1,1,1,0);
3709 obj_render_all(obj_render);
3710 beam_render_all(); // render all beam weapons
3711 particle_render_all(); // render particles after everything else.
3712 trail_render_all(); // render missilie trails after everything else.
3713 mflash_render_all(); // render all muzzle flashes
3715 // Why do we not show the shield effect in these modes? Seems ok.
3716 //if (!(Viewer_mode & (VM_EXTERNAL | VM_SLEWED | VM_CHASE | VM_DEAD_VIEW))) {
3720 // render nebula lightning
3723 // render local player nebula
3724 neb2_render_player();
3727 ai_debug_render_stuff();
3730 #ifndef RELEASE_REAL
3731 // game_framerate_check();
3735 extern void snd_spew_debug_info();
3736 snd_spew_debug_info();
3739 //================ END OF 3D RENDERING STUFF ====================
3743 if( (Game_detail_flags & DETAIL_FLAG_HUD) && (!(Game_mode & GM_MULTIPLAYER) || ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER) )) ) {
3744 hud_maybe_clear_head_area();
3745 anim_render_all(0, flFrametime);
3748 extern int Multi_display_netinfo;
3749 if(Multi_display_netinfo){
3750 extern void multi_display_netinfo();
3751 multi_display_netinfo();
3754 game_tst_frame_pre();
3757 do_timing_test(flFrametime);
3761 extern int OO_update_index;
3762 multi_rate_display(OO_update_index, 375, 0);
3767 extern void oo_display();
3774 //#define JOHNS_DEBUG_CODE 1
3776 #ifdef JOHNS_DEBUG_CODE
3777 void john_debug_stuff(vector *eye_pos, matrix *eye_orient)
3779 //if ( key_pressed(SDLK_LSHIFT) )
3781 ship_subsys *tsys = Players[Player_num].targeted_subobject;
3783 model_subsystem *turret = tsys->system_info;
3785 if (turret->type == SUBSYSTEM_TURRET ) {
3786 vector v.fvec, v.uvec;
3787 object * tobj = &Objects[Players[Player_num].targeted_subobject_parent];
3789 ship_model_start(tobj);
3791 model_find_world_point(eye_pos, &turret->turret_firing_point[0], turret->model_num, turret->turret_gun_sobj, &tobj->orient, &tobj->pos );
3792 model_find_world_dir(&v.fvec, &turret->turret_matrix.v.fvec, turret->model_num, turret->turret_gun_sobj, &tobj->orient, NULL );
3793 model_find_world_dir(&v.uvec, &turret->turret_matrix.v.uvec, turret->model_num, turret->turret_gun_sobj, &tobj->orient, NULL );
3795 vm_vector_2_matrix( eye_orient, &v.fvec, &v.uvec, NULL );
3797 ship_model_stop(tobj);
3807 // following function for dumping frames for purposes of building trailers.
3810 // function to toggle state of dumping every frame into PCX when playing the game
3811 DCF(dump_frames, "Starts/stop frame dumping at 15 hz")
3815 if ( Debug_dump_frames == 0 ) {
3817 Debug_dump_frames = 15;
3818 Debug_dump_trigger = 0;
3819 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
3820 dc_printf( "Frame dumping at 15 hz is now ON\n" );
3823 Debug_dump_frames = 0;
3824 Debug_dump_trigger = 0;
3825 gr_dump_frame_stop();
3826 dc_printf( "Frame dumping is now OFF\n" );
3832 DCF(dump_frames_trigger, "Starts/stop frame dumping at 15 hz")
3836 if ( Debug_dump_frames == 0 ) {
3838 Debug_dump_frames = 15;
3839 Debug_dump_trigger = 1;
3840 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
3841 dc_printf( "Frame dumping at 15 hz is now ON\n" );
3844 Debug_dump_frames = 0;
3845 Debug_dump_trigger = 0;
3846 gr_dump_frame_stop();
3847 dc_printf( "Frame dumping is now OFF\n" );
3853 DCF(dump_frames30, "Starts/stop frame dumping at 30 hz")
3857 if ( Debug_dump_frames == 0 ) {
3859 Debug_dump_frames = 30;
3860 Debug_dump_trigger = 0;
3861 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
3862 dc_printf( "Frame dumping at 30 hz is now ON\n" );
3865 Debug_dump_frames = 0;
3866 Debug_dump_trigger = 0;
3867 gr_dump_frame_stop();
3868 dc_printf( "Frame dumping is now OFF\n" );
3874 DCF(dump_frames30_trigger, "Starts/stop frame dumping at 30 hz")
3878 if ( Debug_dump_frames == 0 ) {
3880 Debug_dump_frames = 30;
3881 Debug_dump_trigger = 1;
3882 gr_dump_frame_start( Debug_dump_frame_num, DUMP_BUFFER_NUM_FRAMES );
3883 dc_printf( "Triggered frame dumping at 30 hz is now ON\n" );
3886 Debug_dump_frames = 0;
3887 Debug_dump_trigger = 0;
3888 gr_dump_frame_stop();
3889 dc_printf( "Triggered frame dumping is now OFF\n" );
3895 void game_maybe_dump_frame()
3897 if ( !Debug_dump_frames ){
3901 if( Debug_dump_trigger && !key_pressed(SDLK_q) ){
3908 Debug_dump_frame_num++;
3914 extern int Player_dead_state;
3916 // Flip the page and time how long it took.
3917 void game_flip_page_and_time_it()
3922 t1 = timer_get_fixed_seconds();
3924 t2 = timer_get_fixed_seconds();
3927 t = (gr_screen.max_w*gr_screen.max_h*gr_screen.bytes_per_pixel)/1024;
3928 sprintf( transfer_text, NOX("%d MB/s"), fixmuldiv(t,65,d) );
3935 void game_simulation_frame()
3937 // blow ships up in multiplayer dogfight
3938 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){
3939 // blow up all non-player ships
3940 ship_obj *moveup = GET_FIRST(&Ship_obj_list);
3943 while((moveup != END_OF_LIST(&Ship_obj_list)) && (moveup != NULL)){
3945 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)){
3946 moveup = GET_NEXT(moveup);
3949 shipp = &Ships[Objects[moveup->objnum].instance];
3950 sip = &Ship_info[shipp->ship_info_index];
3952 // only blow up small ships
3953 if((sip->flags & SIF_SMALL_SHIP) && (multi_find_player_by_object(&Objects[moveup->objnum]) < 0) ){
3954 // function to simply explode a ship where it is currently at
3955 ship_self_destruct( &Objects[moveup->objnum] );
3958 moveup = GET_NEXT(moveup);
3964 // process AWACS stuff - do this first thing
3967 // single player, set Player hits_this_frame to 0
3968 if ( !(Game_mode & GM_MULTIPLAYER) && Player ) {
3969 Player->damage_this_burst -= (flFrametime * MAX_BURST_DAMAGE / (0.001f * BURST_DURATION));
3970 Player->damage_this_burst = max(Player->damage_this_burst, 0.0f);
3974 supernova_process();
3975 if(supernova_active() >= 5){
3979 // fire targeting lasers now so that
3980 // 1 - created this frame
3981 // 2 - collide this frame
3982 // 3 - render this frame
3983 // 4 - ignored and deleted next frame
3984 // the basic idea being that because it con be confusing to deal with them on a multi-frame basis, they are only valid for
3986 ship_process_targeting_lasers();
3988 // do this here so that it works for multiplayer
3990 // get viewer direction
3991 int viewer_direction = PHYSICS_VIEWER_REAR;
3993 if(Viewer_mode == 0){
3994 viewer_direction = PHYSICS_VIEWER_FRONT;
3996 if(Viewer_mode & VM_PADLOCK_UP){
3997 viewer_direction = PHYSICS_VIEWER_UP;
3999 else if(Viewer_mode & VM_PADLOCK_REAR){
4000 viewer_direction = PHYSICS_VIEWER_REAR;
4002 else if(Viewer_mode & VM_PADLOCK_LEFT){
4003 viewer_direction = PHYSICS_VIEWER_LEFT;
4005 else if(Viewer_mode & VM_PADLOCK_RIGHT){
4006 viewer_direction = PHYSICS_VIEWER_RIGHT;
4009 physics_set_viewer( &Viewer_obj->phys_info, viewer_direction );
4011 physics_set_viewer( NULL, PHYSICS_VIEWER_FRONT );
4014 #define VM_PADLOCK_UP (1 << 7)
4015 #define VM_PADLOCK_REAR (1 << 8)
4016 #define VM_PADLOCK_LEFT (1 << 9)
4017 #define VM_PADLOCK_RIGHT (1 << 10)
4019 // evaluate mission departures and arrivals before we process all objects.
4020 if ( !(Game_mode & GM_MULTIPLAYER) || ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER) && !multi_endgame_ending()) ) {
4022 // we don't want to evaluate mission stuff when any ingame joiner in multiplayer is receiving
4023 // ships/wing packets.
4024 if ( !((Game_mode & GM_MULTIPLAYER) && (Netgame.flags & NG_FLAG_INGAME_JOINING_CRITICAL)) && !(Game_mode & GM_DEMO_PLAYBACK)){
4025 mission_parse_eval_stuff();
4028 // if we're an observer, move ourselves seperately from the standard physics
4029 if((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_OBSERVER)){
4030 obj_observer_move(flFrametime);
4033 // move all the objects now
4034 obj_move_all(flFrametime);
4036 // check for cargo reveal (this has an internal timestamp, so only runs every N ms)
4037 // AL: 3-15-98: It was decided to not let AI ships inspect cargo
4038 // ship_check_cargo_all();
4039 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4040 mission_eval_goals();
4044 // always check training objectives, even in multiplayer missions. we need to do this so that the directives gauge works properly on clients
4045 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4046 training_check_objectives();
4049 // do all interpolation now
4050 if ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER) && !multi_endgame_ending() && !(Netgame.flags & NG_FLAG_SERVER_LOST)) {
4051 // client side processing of warping in effect stages
4052 multi_do_client_warp(flFrametime);
4054 // client side movement of an observer
4055 if((Net_player->flags & NETINFO_FLAG_OBSERVER) || (Player_obj->type == OBJ_OBSERVER)){
4056 obj_observer_move(flFrametime);
4059 // move all objects - does interpolation now as well
4060 obj_move_all(flFrametime);
4063 // only process the message queue when the player is "in" the game
4064 if ( !Pre_player_entry ){
4065 message_queue_process(); // process any messages send to the player
4068 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4069 message_maybe_distort(); // maybe distort incoming message if comms damaged
4070 player_repair_frame(flFrametime); // AI objects get repaired in ai_process, called from move code...deal with player.
4071 player_process_pending_praise(); // maybe send off a delayed praise message to the player
4072 player_maybe_play_all_alone_msg(); // mabye tell the player he is all alone
4075 if(!(Game_mode & GM_STANDALONE_SERVER)){
4076 // process some stuff every frame (before frame is rendered)
4077 emp_process_local();
4079 hud_update_frame(); // update hud systems
4081 if (!physics_paused) {
4082 // Move particle system
4083 particle_move_all(flFrametime);
4085 // Move missile trails
4086 trail_move_all(flFrametime);
4088 // process muzzle flashes
4089 mflash_process_all();
4091 // Flash the gun flashes
4092 shipfx_flash_do_frame(flFrametime);
4094 shockwave_move_all(flFrametime); // update all the shockwaves
4097 // subspace missile strikes
4100 obj_snd_do_frame(); // update the object-linked persistant sounds
4101 game_maybe_update_sound_environment();
4102 snd_update_listener(&View_position, &Player_obj->phys_info.vel, &Player_obj->orient);
4104 // AL: debug code used for testing ambient subspace sound (ie when enabling subspace through debug console)
4106 if ( Game_subspace_effect ) {
4107 game_start_subspace_ambient_sound();
4113 // Maybe render and process the dead-popup
4114 void game_maybe_do_dead_popup(float frametime)
4116 if ( popupdead_is_active() ) {
4118 int choice = popupdead_do_frame(frametime);
4120 if ( Game_mode & GM_NORMAL ) {
4123 gameseq_post_event(GS_EVENT_ENTER_GAME);
4127 gameseq_post_event(GS_EVENT_END_GAME);
4131 gameseq_post_event(GS_EVENT_START_GAME);
4134 // this should only happen during a red alert mission
4137 SDL_assert(The_mission.red_alert);
4138 if(!The_mission.red_alert){
4139 gameseq_post_event(GS_EVENT_START_GAME);
4143 // choose the previous mission
4144 mission_campaign_previous_mission();
4146 gameseq_post_event(GS_EVENT_START_GAME);
4156 case POPUPDEAD_DO_MAIN_HALL:
4157 multi_quit_game(PROMPT_NONE,-1);
4160 case POPUPDEAD_DO_RESPAWN:
4161 multi_respawn_normal();
4162 event_music_player_respawn();
4165 case POPUPDEAD_DO_OBSERVER:
4166 multi_respawn_observer();
4167 event_music_player_respawn_as_observer();
4176 if ( leave_popup ) {
4182 // returns true if player is actually in a game_play stats
4183 int game_actually_playing()
4187 state = gameseq_get_state();
4188 if ( (state != GS_STATE_GAME_PLAY) && (state != GS_STATE_DEATH_DIED) && (state != GS_STATE_DEATH_BLEW_UP) )
4194 // Draw the 2D HUD gauges
4195 void game_render_hud_2d()
4197 if ( !(Game_detail_flags & DETAIL_FLAG_HUD) ) {
4201 HUD_render_2d(flFrametime);
4205 // Draw the 3D-dependant HUD gauges
4206 void game_render_hud_3d(vector *eye_pos, matrix *eye_orient)
4208 g3_start_frame(0); // 0 = turn zbuffering off
4209 g3_set_view_matrix( eye_pos, eye_orient, Viewer_zoom );
4211 if ( (Game_detail_flags & DETAIL_FLAG_HUD) && (supernova_active() < 3)/* && !(Game_mode & GM_MULTIPLAYER) || ( (Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER) )*/ ) {
4212 HUD_render_3d(flFrametime);
4216 game_sunspot_process(flFrametime);
4218 // Diminish the palette effect
4219 game_flash_diminish(flFrametime);
4227 int actually_playing;
4228 fix total_time1, total_time2;
4229 fix render2_time1=0, render2_time2=0;
4230 fix render3_time1=0, render3_time2=0;
4231 fix flip_time1=0, flip_time2=0;
4232 fix clear_time1=0, clear_time2=0;
4238 if (Framerate_delay) {
4239 int start_time = timer_get_milliseconds();
4240 while (timer_get_milliseconds() < start_time + Framerate_delay)
4246 demo_do_frame_start();
4248 mprintf(("Error (%d) while processing demo!\n", Demo_error));
4253 // start timing frame
4254 timing_frame_start();
4256 total_time1 = timer_get_fixed_seconds();
4258 // var to hold which state we are in
4259 actually_playing = game_actually_playing();
4261 if ((!(Game_mode & GM_MULTIPLAYER)) || ((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER))) {
4262 if (!(Game_mode & GM_STANDALONE_SERVER)){
4263 SDL_assert( OBJ_INDEX(Player_obj) >= 0 );
4267 if (Missiontime > Entry_delay_time){
4268 Pre_player_entry = 0;
4270 ; //nprintf(("AI", "Framecount = %i, time = %7.3f\n", Framecount, f2fl(Missiontime)));
4273 // Note: These are done even before the player enters, else buffers can overflow.
4274 if (! (Game_mode & GM_STANDALONE_SERVER)){
4278 shield_frame_init();
4280 if ( Player->control_mode != PCM_NORMAL )
4283 if ( !Pre_player_entry && actually_playing ) {
4284 if (! (Game_mode & GM_STANDALONE_SERVER) ) {
4286 if( (!popup_running_state()) && (!popupdead_is_active()) ){
4287 game_process_keys();
4289 // don't read flying controls if we're playing a demo back
4290 if(!(Game_mode & GM_DEMO_PLAYBACK)){
4291 read_player_controls( Player_obj, flFrametime);
4295 // if we're not the master, we may have to send the server-critical ship status button_info bits
4296 if ((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER) && !(Net_player->flags & NETINFO_FLAG_OBSERVER)){
4297 multi_maybe_send_ship_status();
4302 // Reset the whack stuff
4305 // These two lines must be outside of Pre_player_entry code,
4306 // otherwise too many lights are added.
4309 if ((Game_mode & GM_MULTIPLAYER) && (Netgame.game_state == NETGAME_STATE_SERVER_TRANSFER)){
4313 game_simulation_frame();
4315 // if not actually in a game play state, then return. This condition could only be true in
4316 // a multiplayer game.
4317 if ( !actually_playing ) {
4318 SDL_assert( Game_mode & GM_MULTIPLAYER );
4322 if (!Pre_player_entry) {
4323 if (! (Game_mode & GM_STANDALONE_SERVER)) {
4324 clear_time1 = timer_get_fixed_seconds();
4325 // clear the screen to black
4327 if ( (Game_detail_flags & DETAIL_FLAG_CLEAR) ) {
4331 clear_time2 = timer_get_fixed_seconds();
4332 render3_time1 = timer_get_fixed_seconds();
4333 game_render_frame_setup(&eye_pos, &eye_orient);
4334 game_render_frame( &eye_pos, &eye_orient );
4336 // save the eye position and orientation
4337 if ( Game_mode & GM_MULTIPLAYER ) {
4338 Net_player->s_info.eye_pos = eye_pos;
4339 Net_player->s_info.eye_orient = eye_orient;
4342 hud_show_target_model();
4344 // check to see if we should display the death died popup
4345 if(Game_mode & GM_DEAD_BLEW_UP){
4346 if(Game_mode & GM_MULTIPLAYER){
4347 // catch the situation where we're supposed to be warping out on this transition
4348 if(Net_player->flags & NETINFO_FLAG_WARPING_OUT){
4349 gameseq_post_event(GS_EVENT_DEBRIEF);
4350 } else if((Player_died_popup_wait != -1) && (timestamp_elapsed(Player_died_popup_wait))){
4351 Player_died_popup_wait = -1;
4355 if((Player_died_popup_wait != -1) && (timestamp_elapsed(Player_died_popup_wait))){
4356 Player_died_popup_wait = -1;
4362 // hack - sometimes this seems to slip by in multiplayer. this should guarantee that we catch it
4363 if((Game_mode & GM_MULTIPLAYER) && (Player_multi_died_check != -1) && (Game_mode & GM_DEAD_BLEW_UP) ){
4364 if(fl_abs(time(NULL) - Player_multi_died_check) > 4){
4365 if(!popupdead_is_active()){
4369 Player_multi_died_check = -1;
4373 render3_time2 = timer_get_fixed_seconds();
4374 render2_time1 = timer_get_fixed_seconds();
4377 game_get_framerate();
4378 game_show_framerate();
4380 game_show_time_left();
4382 // Draw the 2D HUD gauges
4383 if(supernova_active() < 3){
4384 game_render_hud_2d();
4387 game_set_view_clip();
4389 // Draw 3D HUD gauges
4390 game_render_hud_3d(&eye_pos, &eye_orient);
4394 render2_time2 = timer_get_fixed_seconds();
4396 // maybe render and process the dead popup
4397 game_maybe_do_dead_popup(flFrametime);
4399 // start timing frame
4400 timing_frame_stop();
4401 // timing_display(30, 10);
4403 // If a regular popup is active, don't flip (popup code flips)
4404 if( !popup_running_state() ){
4405 flip_time1 = timer_get_fixed_seconds();
4406 game_flip_page_and_time_it();
4407 flip_time2 = timer_get_fixed_seconds();
4411 game_maybe_dump_frame(); // used to dump pcx files for building trailers
4414 game_show_standalone_framerate();
4418 game_do_training_checks();
4421 // process lightning (nebula only)
4424 total_time2 = timer_get_fixed_seconds();
4426 // Got some timing numbers
4427 Timing_total = f2fl( total_time2 - total_time1 ) * 1000.0f;
4428 Timing_clear = f2fl( clear_time2 - clear_time1 ) * 1000.0f;
4429 Timing_render2 = f2fl( render2_time2- render2_time1 ) * 1000.0f;
4430 Timing_render3 = f2fl( render3_time2- render3_time1 ) * 1000.0f;
4431 Timing_flip = f2fl( flip_time2 - flip_time1 ) * 1000.0f;
4434 demo_do_frame_end();
4436 mprintf(("Error (%d) while processing demo!\n", Demo_error));
4442 #define MAX_FRAMETIME (F1_0/4) // Frametime gets saturated at this. Changed by MK on 11/1/97.
4443 // Some bug was causing Frametime to always get saturated at 2.0 seconds after the player
4444 // died. This resulted in screwed up death sequences.
4446 fix Last_time = 0; // The absolute time of game at end of last frame (beginning of this frame)
4447 fix Last_delta_time = 0; // While game is paused, this keeps track of how much elapsed in the frame before paused.
4448 static int timer_paused=0;
4449 #if defined(TIMER_TEST) && !defined(NDEBUG)
4450 static int stop_count,start_count;
4451 static int time_stopped,time_started;
4453 int saved_timestamp_ticker = -1;
4455 void game_reset_time()
4457 if((Game_mode & GM_MULTIPLAYER) && (Netgame.game_state == NETGAME_STATE_SERVER_TRANSFER)){
4461 // Last_time = timer_get_fixed_seconds();
4467 void game_stop_time()
4469 if (timer_paused==0) {
4471 time = timer_get_fixed_seconds();
4472 // Save how much time progressed so far in the frame so we can
4473 // use it when we unpause.
4474 Last_delta_time = time - Last_time;
4476 //mprintf(("Last_time in game_stop_time = %7.3f\n", f2fl(Last_delta_time)));
4477 if (Last_delta_time < 0) {
4478 #if defined(TIMER_TEST) && !defined(NDEBUG)
4479 Int3(); //get Matt!!!!
4481 Last_delta_time = 0;
4483 #if defined(TIMER_TEST) && !defined(NDEBUG)
4484 time_stopped = time;
4487 // Stop the timer_tick stuff...
4488 // Normally, you should never access 'timestamp_ticker', consider this a low-level routine
4489 saved_timestamp_ticker = timestamp_ticker;
4493 #if defined(TIMER_TEST) && !defined(NDEBUG)
4498 void game_start_time()
4501 SDL_assert(timer_paused >= 0);
4502 if (timer_paused==0) {
4504 time = timer_get_fixed_seconds();
4505 #if defined(TIMER_TEST) && !defined(NDEBUG)
4507 Int3(); //get Matt!!!!
4510 // Take current time, and set it backwards to account for time
4511 // that the frame already executed, so that timer_get_fixed_seconds() - Last_time
4512 // will be correct when it goes to calculate the frametime next
4514 Last_time = time - Last_delta_time;
4515 #if defined(TIMER_TEST) && !defined(NDEBUG)
4516 time_started = time;
4519 // Restore the timer_tick stuff...
4520 // Normally, you should never access 'timestamp_ticker', consider this a low-level routine
4521 SDL_assert( saved_timestamp_ticker > -1 ); // Called out of order, get JAS
4522 timestamp_ticker = saved_timestamp_ticker;
4523 saved_timestamp_ticker = -1;
4526 #if defined(TIMER_TEST) && !defined(NDEBUG)
4532 void game_set_frametime(int state)
4535 float frame_cap_diff;
4537 thistime = timer_get_fixed_seconds();
4539 if ( Last_time == 0 )
4540 Frametime = F1_0 / 30;
4542 Frametime = thistime - Last_time;
4544 // Frametime = F1_0 / 30;
4546 fix debug_frametime = Frametime; // Just used to display frametime.
4548 // If player hasn't entered mission yet, make frame take 1/4 second.
4549 if ((Pre_player_entry) && (state == GS_STATE_GAME_PLAY))
4552 else if ((Debug_dump_frames) && (state == GS_STATE_GAME_PLAY)) { // note link to above if!!!!!
4554 fix frame_speed = F1_0 / Debug_dump_frames;
4556 if (Frametime > frame_speed ){
4557 nprintf(("warning","slow frame: %x\n",Frametime));
4560 thistime = timer_get_fixed_seconds();
4561 Frametime = thistime - Last_time;
4562 } while (Frametime < frame_speed );
4564 Frametime = frame_speed;
4568 SDL_assert( Framerate_cap > 0 );
4570 // Cap the framerate so it doesn't get too high.
4574 cap = F1_0/Framerate_cap;
4575 if (Frametime < cap) {
4576 thistime = cap - Frametime;
4577 //mprintf(("Sleeping for %6.3f seconds.\n", f2fl(thistime)));
4578 SDL_Delay( (f2fl(thistime) * 1000.0f) );
4580 thistime = timer_get_fixed_seconds();
4584 if((Game_mode & GM_STANDALONE_SERVER) &&
4585 (f2fl(Frametime) < ((float)1.0/(float)Multi_options_g.std_framecap))){
4587 frame_cap_diff = ((float)1.0/(float)Multi_options_g.std_framecap) - f2fl(Frametime);
4588 SDL_Delay((frame_cap_diff*1000));
4590 thistime += fl2f((frame_cap_diff));
4592 Frametime = thistime - Last_time;
4595 // If framerate is too low, cap it.
4596 if (Frametime > MAX_FRAMETIME) {
4598 mprintf(("Frame %2i too long!!: frametime = %.3f (%.3f)\n", Framecount, f2fl(Frametime), f2fl(debug_frametime)));
4600 // to remove warnings in release build
4601 debug_frametime = fl2f(flFrametime);
4603 Frametime = MAX_FRAMETIME;
4606 Frametime = fixmul(Frametime, Game_time_compression);
4608 Last_time = thistime;
4609 //mprintf(("Frame %i, Last_time = %7.3f\n", Framecount, f2fl(Last_time)));
4611 flFrametime = f2fl(Frametime);
4612 //if(!(Game_mode & GM_PLAYING_DEMO)){
4613 timestamp_inc(flFrametime);
4615 /* if ((Framecount > 0) && (Framecount < 10)) {
4616 mprintf(("Frame %2i: frametime = %.3f (%.3f)\n", Framecount, f2fl(Frametime), f2fl(debug_frametime)));
4621 // This is called from game_do_frame(), and from navmap_do_frame()
4622 void game_update_missiontime()
4624 // TODO JAS: Put in if and move this into game_set_frametime,
4625 // fix navmap to call game_stop/start_time
4626 //if ( !timer_paused )
4627 Missiontime += Frametime;
4630 void game_do_frame()
4632 game_set_frametime(GS_STATE_GAME_PLAY);
4633 game_update_missiontime();
4635 if (Game_mode & GM_STANDALONE_SERVER) {
4636 std_multi_set_standalone_missiontime(f2fl(Missiontime));
4639 if ( game_single_step && (last_single_step == game_single_step) ) {
4640 os_set_title( NOX("SINGLE STEP MODE (Pause exits, any other key steps)") );
4641 while( key_checkch() == 0 )
4643 os_set_title( XSTR( "FreeSpace", 171) );
4644 Last_time = timer_get_fixed_seconds();
4647 last_single_step = game_single_step;
4649 if ((gameseq_get_state() == GS_STATE_GAME_PLAY) && Use_mouse_to_fly){
4650 Keep_mouse_centered = 1; // force mouse to center of our window (so we don't hit movement limits)
4654 Keep_mouse_centered = 0;
4655 monitor_update(); // Update monitor variables
4658 void multi_maybe_do_frame()
4660 if ( (Game_mode & GM_MULTIPLAYER) && (Game_mode & GM_IN_MISSION) && !Multi_pause_status){
4665 int Joymouse_button_status = 0;
4667 // Flush all input devices
4675 Joymouse_button_status = 0;
4677 //mprintf(("Game flush!\n" ));
4680 // function for multiplayer only which calls game_do_state_common() when running the
4682 void game_do_dc_networking()
4684 SDL_assert( Game_mode & GM_MULTIPLAYER );
4686 game_do_state_common( gameseq_get_state() );
4689 // Call this whenever in a loop, or when you need to check for a keystroke.
4690 int game_check_key()
4696 // convert keypad enter to normal enter
4697 if ((k & KEY_MASK) == SDLK_KP_ENTER)
4698 k = (k & ~KEY_MASK) | SDLK_RETURN;
4703 #if defined(FS2_DEMO) || defined(FS1_DEMO)
4705 #define DEMO_TRAILER_TIMEOUT_MS 45000 // 45 seconds of no input, play trailer
4706 static int Demo_show_trailer_timestamp = 0;
4708 void demo_reset_trailer_timer()
4710 Demo_show_trailer_timestamp = timer_get_milliseconds();
4713 void demo_maybe_show_trailer(int k)
4716 // if key pressed, reset demo trailer timer
4718 demo_reset_trailer_timer();
4722 // if mouse moved, reset demo trailer timer
4725 mouse_get_delta(&dx, &dy);
4726 if ( (dx > 0) || (dy > 0) ) {
4727 demo_reset_trailer_timer();
4731 // if joystick has moved, reset demo trailer timer
4734 joy_get_delta(&dx, &dy);
4735 if ( (dx > 0) || (dy > 0) ) {
4736 demo_reset_trailer_timer();
4740 // NOTE: reseting the trailer timer on mouse/joystick presses is handled in
4741 // the low-level code. Ugly, I know... but was the simplest and most
4744 // if 30 seconds since last demo trailer time reset, launch movie
4745 if ( os_foreground() ) {
4746 int now = timer_get_milliseconds();
4747 if ( (now - Demo_show_trailer_timestamp) > DEMO_TRAILER_TIMEOUT_MS ) {
4748 // if ( (now - Demo_show_trailer_timestamp) > 10000 ) {
4750 movie_play( NOX("fstrailer2.mve") );
4751 demo_reset_trailer_timer();
4759 // same as game_check_key(), except this is used while actually in the game. Since there
4760 // generally are differences between game control keys and general UI keys, makes sense to
4761 // have seperate functions for each case. If you are not checking a game control while in a
4762 // mission, you should probably be using game_check_key() instead.
4767 if (!os_foreground()) {
4772 // If we're in a single player game, pause it.
4773 if (!(Game_mode & GM_MULTIPLAYER)){
4774 if ( (gameseq_get_state() == GS_STATE_GAME_PLAY) && (!popup_active()) && (!popupdead_is_active()) ) {
4775 game_process_pause_key();
4782 #if defined(FS2_DEMO) || defined(FS1_DEMO)
4783 demo_maybe_show_trailer(k);
4786 // Move the mouse cursor with the joystick.
4787 if (os_foreground() && (!Mouse_hidden) && (Use_joy_mouse) ) {
4788 // Move the mouse cursor with the joystick
4792 joy_get_pos( &jx, &jy, &jz, &jr );
4794 dx = fl2i(f2fl(jx)*flFrametime*500.0f);
4795 dy = fl2i(f2fl(jy)*flFrametime*500.0f);
4798 mouse_get_real_pos( &mx, &my );
4799 mouse_set_pos( mx+dx, my+dy );
4804 m = mouse_down(MOUSE_LEFT_BUTTON);
4806 if ( j != Joymouse_button_status ) {
4807 //mprintf(( "Joy went from %d to %d, mouse is %d\n", Joymouse_button_status, j, m ));
4808 Joymouse_button_status = j;
4810 mouse_mark_button( MOUSE_LEFT_BUTTON, 1 );
4811 } else if ( (!j) && (m) ) {
4812 mouse_mark_button( MOUSE_LEFT_BUTTON, 0 );
4817 // if we should be ignoring keys because of some multiplayer situations
4818 if((Game_mode & GM_MULTIPLAYER) && multi_ignore_controls(k)){
4822 // If a popup is running, don't process all the Fn keys
4823 if( popup_active() ) {
4827 state = gameseq_get_state();
4829 // if ( k ) nprintf(( "General", "Key = %x\n", k ));
4832 case KEY_DEBUGGED + SDLK_BACKSPACE:
4837 launch_context_help();
4842 // if (state != GS_STATE_INITIAL_PLAYER_SELECT) {
4844 // don't allow f2 while warping out in multiplayer
4845 if((Game_mode & GM_MULTIPLAYER) && (Net_player != NULL) && (Net_player->flags & NETINFO_FLAG_WARPING_OUT)){
4850 case GS_STATE_INITIAL_PLAYER_SELECT:
4851 case GS_STATE_OPTIONS_MENU:
4852 case GS_STATE_HUD_CONFIG:
4853 case GS_STATE_CONTROL_CONFIG:
4854 case GS_STATE_DEATH_DIED:
4855 case GS_STATE_DEATH_BLEW_UP:
4856 case GS_STATE_VIEW_MEDALS:
4860 gameseq_post_event(GS_EVENT_OPTIONS_MENU);
4867 // hotkey selection screen -- only valid from briefing and beyond.
4869 #if !(defined(FS2_DEMO) || defined(FS1_DEMO))
4870 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) ) {
4871 gameseq_post_event( GS_EVENT_HOTKEY_SCREEN );
4877 case KEY_DEBUGGED + SDLK_F3:
4878 gameseq_post_event( GS_EVENT_TOGGLE_FULLSCREEN );
4881 case KEY_DEBUGGED + SDLK_F4:
4882 gameseq_post_event( GS_EVENT_TOGGLE_GLIDE );
4886 if(Game_mode & GM_MULTIPLAYER){
4887 if((state == GS_STATE_GAME_PLAY) || (state == GS_STATE_MULTI_PAUSED)){
4888 gameseq_post_event( GS_EVENT_MISSION_LOG_SCROLLBACK );
4892 if ((state == GS_STATE_GAME_PLAY) || (state == GS_STATE_DEATH_DIED) || (state == GS_STATE_DEATH_BLEW_UP) || (state == GS_STATE_GAME_PAUSED) ) {
4893 gameseq_post_event( GS_EVENT_MISSION_LOG_SCROLLBACK );
4899 case SDLK_ESCAPE | KEY_SHIFTED:
4900 // make sure to quit properly out of multiplayer
4901 if(Game_mode & GM_MULTIPLAYER){
4902 multi_quit_game(PROMPT_NONE);
4905 gameseq_post_event( GS_EVENT_QUIT_GAME );
4910 case KEY_DEBUGGED + SDLK_p:
4913 case SDLK_PRINTSCREEN:
4915 static int counter = 0;
4920 sprintf( tmp_name, NOX("screen%02d"), counter );
4922 mprintf(( "Dumping screen to '%s'\n", tmp_name ));
4923 gr_print_screen(tmp_name);
4931 case KEY_SHIFTED | SDLK_RETURN: {
4933 #if !defined(NDEBUG)
4935 if ( Game_mode & GM_NORMAL ){
4939 // if we're in multiplayer mode, do some special networking
4940 if(Game_mode & GM_MULTIPLAYER){
4941 debug_console(game_do_dc_networking);
4948 if ( Game_mode & GM_NORMAL )
4962 gameseq_post_event(GS_EVENT_QUIT_GAME);
4965 void apply_physics( float damping, float desired_vel, float initial_vel, float t, float * new_vel, float * delta_pos );
4968 void camera_set_position( vector *pos )
4973 void camera_set_orient( matrix *orient )
4975 Camera_orient = *orient;
4978 void camera_set_velocity( vector *vel, int instantaneous )
4980 Camera_desired_velocity.xyz.x = 0.0f;
4981 Camera_desired_velocity.xyz.y = 0.0f;
4982 Camera_desired_velocity.xyz.z = 0.0f;
4984 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.rvec, vel->xyz.x );
4985 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.uvec, vel->xyz.y );
4986 vm_vec_scale_add2( &Camera_desired_velocity, &Camera_orient.v.fvec, vel->xyz.z );
4988 if ( instantaneous ) {
4989 Camera_velocity = Camera_desired_velocity;
4997 vector new_vel, delta_pos;
4999 apply_physics( Camera_damping, Camera_desired_velocity.xyz.x, Camera_velocity.xyz.x, flFrametime, &new_vel.xyz.x, &delta_pos.xyz.x );
5000 apply_physics( Camera_damping, Camera_desired_velocity.xyz.y, Camera_velocity.xyz.y, flFrametime, &new_vel.xyz.y, &delta_pos.xyz.y );
5001 apply_physics( Camera_damping, Camera_desired_velocity.xyz.z, Camera_velocity.xyz.z, flFrametime, &new_vel.xyz.z, &delta_pos.xyz.z );
5003 Camera_velocity = new_vel;
5005 // mprintf(( "Camera velocity = %.1f,%.1f, %.1f\n", Camera_velocity.xyz.x, Camera_velocity.xyz.y, Camera_velocity.xyz.z ));
5007 vm_vec_add2( &Camera_pos, &delta_pos );
5009 float ot = Camera_time+0.0f;
5011 Camera_time += flFrametime;
5013 if ( (ot < 0.667f) && ( Camera_time >= 0.667f ) ) {
5016 tmp.xyz.z = 4.739f; // always go this fast forward.
5018 // pick x and y velocities so they are always on a
5019 // circle with a 25 m radius.
5021 float tmp_angle = frand()*PI2;
5023 tmp.xyz.x = 22.0f * (float)sin(tmp_angle);
5024 tmp.xyz.y = -22.0f * (float)cos(tmp_angle);
5026 //mprintf(( "Angle = %.1f, vx=%.1f, vy=%.1f\n", tmp_angle, tmp.xyz.x, tmp.xyz.y ));
5028 //mprintf(( "Changing velocity!\n" ));
5029 camera_set_velocity( &tmp, 0 );
5032 if ( (ot < 3.0f ) && ( Camera_time >= 3.0f ) ) {
5033 vector tmp = ZERO_VECTOR;
5034 camera_set_velocity( &tmp, 0 );
5039 void end_demo_campaign_do()
5041 #if defined(FS2_DEMO) || defined(FS1_DEMO)
5042 // show upsell screens
5043 demo_upsell_show_screens();
5044 #elif defined(OEM_BUILD)
5045 // show oem upsell screens
5046 oem_upsell_show_screens();
5049 // drop into main hall
5050 gameseq_post_event( GS_EVENT_MAIN_MENU );
5053 // All code to process events. This is the only place
5054 // that you should change the state of the game.
5055 void game_process_event( int current_state, int event )
5057 mprintf(("Got event %s in state %s\n", GS_event_text[event], GS_state_text[current_state]));
5060 case GS_EVENT_SIMULATOR_ROOM:
5061 gameseq_set_state(GS_STATE_SIMULATOR_ROOM);
5064 case GS_EVENT_MAIN_MENU:
5065 gameseq_set_state(GS_STATE_MAIN_MENU);
5068 case GS_EVENT_OPTIONS_MENU:
5069 gameseq_push_state( GS_STATE_OPTIONS_MENU );
5072 case GS_EVENT_BARRACKS_MENU:
5073 gameseq_set_state(GS_STATE_BARRACKS_MENU);
5076 case GS_EVENT_TECH_MENU:
5077 gameseq_set_state(GS_STATE_TECH_MENU);
5080 case GS_EVENT_TRAINING_MENU:
5081 gameseq_set_state(GS_STATE_TRAINING_MENU);
5084 case GS_EVENT_START_GAME:
5085 Select_default_ship = 0;
5086 Player_multi_died_check = -1;
5087 gameseq_set_state(GS_STATE_CMD_BRIEF);
5090 case GS_EVENT_START_BRIEFING:
5091 gameseq_set_state(GS_STATE_BRIEFING);
5094 case GS_EVENT_DEBRIEF:
5095 // did we end the campaign in the main freespace 2 single player campaign?
5097 if(Campaign_ended_in_mission && (Game_mode & GM_CAMPAIGN_MODE) && !SDL_strcasecmp(Campaign.filename, "freespace")) {
5099 if(Campaign_ended_in_mission && (Game_mode & GM_CAMPAIGN_MODE) && !SDL_strcasecmp(Campaign.filename, "freespace2")) {
5101 gameseq_post_event(GS_EVENT_END_CAMPAIGN);
5103 gameseq_set_state(GS_STATE_DEBRIEF);
5106 Player_multi_died_check = -1;
5109 case GS_EVENT_SHIP_SELECTION:
5110 gameseq_set_state( GS_STATE_SHIP_SELECT );
5113 case GS_EVENT_WEAPON_SELECTION:
5114 gameseq_set_state( GS_STATE_WEAPON_SELECT );
5117 case GS_EVENT_ENTER_GAME:
5119 // maybe start recording a demo
5121 demo_start_record("test.fsd");
5125 if (Game_mode & GM_MULTIPLAYER) {
5126 // if we're respawning, make sure we change the view mode so that the hud shows up
5127 if (current_state == GS_STATE_DEATH_BLEW_UP) {
5131 gameseq_set_state(GS_STATE_GAME_PLAY);
5133 gameseq_set_state(GS_STATE_GAME_PLAY, 1);
5136 Player_multi_died_check = -1;
5138 // clear multiplayer button info
5139 extern button_info Multi_ship_status_bi;
5140 memset(&Multi_ship_status_bi, 0, sizeof(button_info));
5142 Start_time = f2fl(timer_get_approx_seconds());
5144 mprintf(("Entering game at time = %7.3f\n", Start_time));
5148 case GS_EVENT_START_GAME_QUICK:
5149 Select_default_ship = 1;
5150 gameseq_post_event(GS_EVENT_ENTER_GAME);
5154 case GS_EVENT_END_GAME:
5155 if ( (current_state == GS_STATE_GAME_PLAY) || (current_state == GS_STATE_DEATH_DIED) ||
5156 (current_state == GS_STATE_DEATH_BLEW_UP) || (current_state == GS_STATE_DEBRIEF) || (current_state == GS_STATE_MULTI_DOGFIGHT_DEBRIEF)) {
5157 gameseq_set_state(GS_STATE_MAIN_MENU);
5162 Player_multi_died_check = -1;
5165 case GS_EVENT_QUIT_GAME:
5166 main_hall_stop_music();
5167 main_hall_stop_ambient();
5168 gameseq_set_state(GS_STATE_QUIT_GAME);
5170 Player_multi_died_check = -1;
5173 case GS_EVENT_GAMEPLAY_HELP:
5174 gameseq_push_state( GS_STATE_GAMEPLAY_HELP );
5177 case GS_EVENT_PAUSE_GAME:
5178 gameseq_push_state(GS_STATE_GAME_PAUSED);
5181 case GS_EVENT_DEBUG_PAUSE_GAME:
5182 gameseq_push_state(GS_STATE_DEBUG_PAUSED);
5185 case GS_EVENT_TRAINING_PAUSE:
5186 gameseq_push_state(GS_STATE_TRAINING_PAUSED);
5189 case GS_EVENT_PREVIOUS_STATE:
5190 gameseq_pop_state();
5193 case GS_EVENT_TOGGLE_FULLSCREEN:
5194 gr_toggle_fullscreen();
5197 case GS_EVENT_TOGGLE_GLIDE:
5200 case GS_EVENT_LOAD_MISSION_MENU:
5201 gameseq_set_state(GS_STATE_LOAD_MISSION_MENU);
5204 case GS_EVENT_MISSION_LOG_SCROLLBACK:
5205 gameseq_push_state( GS_STATE_MISSION_LOG_SCROLLBACK );
5208 case GS_EVENT_HUD_CONFIG:
5209 gameseq_push_state( GS_STATE_HUD_CONFIG );
5212 case GS_EVENT_CONTROL_CONFIG:
5213 gameseq_push_state( GS_STATE_CONTROL_CONFIG );
5216 case GS_EVENT_DEATH_DIED:
5217 gameseq_set_state( GS_STATE_DEATH_DIED );
5220 case GS_EVENT_DEATH_BLEW_UP:
5221 if ( current_state == GS_STATE_DEATH_DIED ) {
5222 gameseq_set_state( GS_STATE_DEATH_BLEW_UP );
5223 event_music_player_death();
5225 // multiplayer clients set their extra check here
5226 if(Game_mode & GM_MULTIPLAYER){
5227 // set the multi died absolute last chance check
5228 Player_multi_died_check = time(NULL);
5231 mprintf(( "Ignoring GS_EVENT_DEATH_BLEW_UP because we're in state %d\n", current_state ));
5235 case GS_EVENT_NEW_CAMPAIGN:
5236 if (!mission_load_up_campaign()){
5237 readyroom_continue_campaign();
5240 Player_multi_died_check = -1;
5243 case GS_EVENT_CAMPAIGN_CHEAT:
5244 if (!mission_load_up_campaign()){
5246 // bash campaign value
5247 extern char Main_hall_campaign_cheat[512];
5250 // look for the mission
5251 for(idx=0; idx<Campaign.num_missions; idx++){
5252 if(!SDL_strcasecmp(Campaign.missions[idx].name, Main_hall_campaign_cheat)){
5253 Campaign.next_mission = idx;
5254 Campaign.prev_mission = idx - 1;
5261 readyroom_continue_campaign();
5264 Player_multi_died_check = -1;
5267 case GS_EVENT_CAMPAIGN_ROOM:
5268 gameseq_set_state(GS_STATE_CAMPAIGN_ROOM);
5271 case GS_EVENT_CMD_BRIEF:
5272 gameseq_set_state(GS_STATE_CMD_BRIEF);
5275 case GS_EVENT_RED_ALERT:
5276 gameseq_set_state(GS_STATE_RED_ALERT);
5279 case GS_EVENT_CREDITS:
5280 gameseq_set_state( GS_STATE_CREDITS );
5283 case GS_EVENT_VIEW_MEDALS:
5284 gameseq_push_state( GS_STATE_VIEW_MEDALS );
5287 case GS_EVENT_SHOW_GOALS:
5288 gameseq_push_state( GS_STATE_SHOW_GOALS ); // use push_state() since we might get to this screen through a variety of states
5291 case GS_EVENT_HOTKEY_SCREEN:
5292 gameseq_push_state( GS_STATE_HOTKEY_SCREEN ); // use push_state() since we might get to this screen through a variety of states
5295 // multiplayer stuff follow these comments
5297 case GS_EVENT_MULTI_JOIN_GAME:
5298 gameseq_set_state( GS_STATE_MULTI_JOIN_GAME );
5301 case GS_EVENT_MULTI_HOST_SETUP:
5302 gameseq_set_state( GS_STATE_MULTI_HOST_SETUP );
5305 case GS_EVENT_MULTI_CLIENT_SETUP:
5306 gameseq_set_state( GS_STATE_MULTI_CLIENT_SETUP );
5309 case GS_EVENT_GOTO_VIEW_CUTSCENES_SCREEN:
5310 gameseq_set_state(GS_STATE_VIEW_CUTSCENES);
5313 case GS_EVENT_MULTI_STD_WAIT:
5314 gameseq_set_state( GS_STATE_MULTI_STD_WAIT );
5317 case GS_EVENT_STANDALONE_MAIN:
5318 gameseq_set_state( GS_STATE_STANDALONE_MAIN );
5321 case GS_EVENT_MULTI_PAUSE:
5322 gameseq_push_state( GS_STATE_MULTI_PAUSED );
5325 case GS_EVENT_INGAME_PRE_JOIN:
5326 gameseq_set_state( GS_STATE_INGAME_PRE_JOIN );
5329 case GS_EVENT_EVENT_DEBUG:
5330 gameseq_push_state(GS_STATE_EVENT_DEBUG);
5333 // Start a warpout where player automatically goes 70 no matter what
5334 // and can't cancel out of it.
5335 case GS_EVENT_PLAYER_WARPOUT_START_FORCED:
5336 Warpout_forced = 1; // If non-zero, bash the player to speed and go through effect
5338 // Same code as in GS_EVENT_PLAYER_WARPOUT_START only ignores current mode
5339 Player->saved_viewer_mode = Viewer_mode;
5340 Player->control_mode = PCM_WARPOUT_STAGE1;
5341 Warpout_sound = snd_play(&Snds[SND_PLAYER_WARP_OUT]);
5342 Warpout_time = 0.0f; // Start timer!
5345 case GS_EVENT_PLAYER_WARPOUT_START:
5346 if ( Player->control_mode != PCM_NORMAL ) {
5347 mprintf(( "Player isn't in normal mode; cannot warp out.\n" ));
5349 Player->saved_viewer_mode = Viewer_mode;
5350 Player->control_mode = PCM_WARPOUT_STAGE1;
5351 Warpout_sound = snd_play(&Snds[SND_PLAYER_WARP_OUT]);
5352 Warpout_time = 0.0f; // Start timer!
5353 Warpout_forced = 0; // If non-zero, bash the player to speed and go through effect
5357 case GS_EVENT_PLAYER_WARPOUT_STOP:
5358 if ( Player->control_mode != PCM_NORMAL ) {
5359 if ( !Warpout_forced ) { // cannot cancel forced warpout
5360 Player->control_mode = PCM_NORMAL;
5361 Viewer_mode = Player->saved_viewer_mode;
5362 hud_subspace_notify_abort();
5363 mprintf(( "Player put back to normal mode.\n" ));
5364 if ( Warpout_sound > -1 ) {
5365 snd_stop( Warpout_sound );
5372 case GS_EVENT_PLAYER_WARPOUT_DONE_STAGE1: // player ship got up to speed
5373 if ( Player->control_mode != PCM_WARPOUT_STAGE1 ) {
5374 gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_STOP );
5375 mprintf(( "Player put back to normal mode, because of invalid sequence in stage1.\n" ));
5377 mprintf(( "Hit target speed. Starting warp effect and moving to stage 2!\n" ));
5378 shipfx_warpout_start( Player_obj );
5379 Player->control_mode = PCM_WARPOUT_STAGE2;
5380 Player->saved_viewer_mode = Viewer_mode;
5381 Viewer_mode |= VM_WARP_CHASE;
5383 vector tmp = Player_obj->pos;
5385 ship_get_eye( &tmp, &tmp_m, Player_obj );
5386 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.rvec, 0.0f );
5387 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.uvec, 0.952f );
5388 vm_vec_scale_add2( &tmp, &Player_obj->orient.v.fvec, -1.782f );
5390 camera_set_position( &tmp );
5391 camera_set_orient( &Player_obj->orient );
5392 vector tmp_vel = { { { 0.0f, 5.1919f, 14.7f } } };
5394 //mprintf(( "Rad = %.1f\n", Player_obj->radius ));
5395 camera_set_velocity( &tmp_vel, 1);
5399 case GS_EVENT_PLAYER_WARPOUT_DONE_STAGE2: // player ship got into the warp effect
5400 if ( Player->control_mode != PCM_WARPOUT_STAGE2 ) {
5401 gameseq_post_event( GS_EVENT_PLAYER_WARPOUT_STOP );
5402 mprintf(( "Player put back to normal mode, because of invalid sequence in stage2.\n" ));
5404 mprintf(( "Hit warp effect. Moving to stage 3!\n" ));
5405 Player->control_mode = PCM_WARPOUT_STAGE3;
5409 case GS_EVENT_PLAYER_WARPOUT_DONE: // player ship got through the warp effect
5410 mprintf(( "Player warped out. Going to debriefing!\n" ));
5411 Player->control_mode = PCM_NORMAL;
5412 Viewer_mode = Player->saved_viewer_mode;
5415 // we have a special debriefing screen for multiplayer furballs
5416 if((Game_mode & GM_MULTIPLAYER) && (The_mission.game_type & MISSION_TYPE_MULTI_DOGFIGHT)){
5417 gameseq_post_event(GS_EVENT_MULTI_DOGFIGHT_DEBRIEF);
5419 // do the normal debriefing for all other situations
5421 gameseq_post_event(GS_EVENT_DEBRIEF);
5425 case GS_EVENT_STANDALONE_POSTGAME:
5426 gameseq_set_state(GS_STATE_STANDALONE_POSTGAME);
5429 case GS_EVENT_INITIAL_PLAYER_SELECT:
5430 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5433 case GS_EVENT_GAME_INIT:
5434 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
5435 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5437 // see if the command line option has been set to use the last pilot, and act acoordingly
5438 if( player_select_get_last_pilot() ) {
5439 // always enter the main menu -- do the automatic network startup stuff elsewhere
5440 // so that we still have valid checks for networking modes, etc.
5441 gameseq_set_state(GS_STATE_MAIN_MENU);
5443 gameseq_set_state(GS_STATE_INITIAL_PLAYER_SELECT);
5448 case GS_EVENT_MULTI_MISSION_SYNC:
5449 gameseq_set_state(GS_STATE_MULTI_MISSION_SYNC);
5452 case GS_EVENT_MULTI_START_GAME:
5453 gameseq_set_state(GS_STATE_MULTI_START_GAME);
5456 case GS_EVENT_MULTI_HOST_OPTIONS:
5457 gameseq_set_state(GS_STATE_MULTI_HOST_OPTIONS);
5460 case GS_EVENT_MULTI_DOGFIGHT_DEBRIEF:
5461 gameseq_set_state(GS_STATE_MULTI_DOGFIGHT_DEBRIEF);
5464 case GS_EVENT_TEAM_SELECT:
5465 gameseq_set_state(GS_STATE_TEAM_SELECT);
5468 case GS_EVENT_END_CAMPAIGN:
5469 gameseq_set_state(GS_STATE_END_OF_CAMPAIGN);
5472 case GS_EVENT_END_DEMO:
5473 gameseq_set_state(GS_STATE_END_DEMO);
5476 case GS_EVENT_LOOP_BRIEF:
5477 gameseq_set_state(GS_STATE_LOOP_BRIEF);
5486 // Called when a state is being left.
5487 // The current state is still at old_state, but as soon as
5488 // this function leaves, then the current state will become
5489 // new state. You should never try to change the state
5490 // in here... if you think you need to, you probably really
5491 // need to post an event, not change the state.
5492 void game_leave_state( int old_state, int new_state )
5494 int end_mission = 1;
5496 switch (new_state) {
5497 case GS_STATE_GAME_PAUSED:
5498 case GS_STATE_DEBUG_PAUSED:
5499 case GS_STATE_OPTIONS_MENU:
5500 case GS_STATE_CONTROL_CONFIG:
5501 case GS_STATE_MISSION_LOG_SCROLLBACK:
5502 case GS_STATE_DEATH_DIED:
5503 case GS_STATE_SHOW_GOALS:
5504 case GS_STATE_HOTKEY_SCREEN:
5505 case GS_STATE_MULTI_PAUSED:
5506 case GS_STATE_TRAINING_PAUSED:
5507 case GS_STATE_EVENT_DEBUG:
5508 case GS_STATE_GAMEPLAY_HELP:
5509 end_mission = 0; // these events shouldn't end a mission
5513 switch (old_state) {
5514 case GS_STATE_BRIEFING:
5515 brief_stop_voices();
5516 if ( (new_state != GS_STATE_OPTIONS_MENU) && (new_state != GS_STATE_WEAPON_SELECT)
5517 && (new_state != GS_STATE_SHIP_SELECT) && (new_state != GS_STATE_HOTKEY_SCREEN)
5518 && (new_state != GS_STATE_TEAM_SELECT) ){
5519 common_select_close();
5520 if ( new_state == GS_STATE_MAIN_MENU ) {
5521 freespace_stop_mission();
5525 // COMMAND LINE OPTION
5526 if (Cmdline_multi_stream_chat_to_file){
5527 cfwrite_string(NOX("-------------------------------------------\n"),Multi_chat_stream);
5528 cfclose(Multi_chat_stream);
5532 case GS_STATE_DEBRIEF:
5533 if ( (new_state != GS_STATE_VIEW_MEDALS) && (new_state != GS_STATE_OPTIONS_MENU) ) {
5538 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
5539 multi_df_debrief_close();
5542 case GS_STATE_LOAD_MISSION_MENU:
5543 mission_load_menu_close();
5546 case GS_STATE_SIMULATOR_ROOM:
5550 case GS_STATE_CAMPAIGN_ROOM:
5551 campaign_room_close();
5554 case GS_STATE_CMD_BRIEF:
5555 if (new_state == GS_STATE_OPTIONS_MENU) {
5560 if (new_state == GS_STATE_MAIN_MENU)
5561 freespace_stop_mission();
5566 case GS_STATE_RED_ALERT:
5570 case GS_STATE_SHIP_SELECT:
5571 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_WEAPON_SELECT &&
5572 new_state != GS_STATE_HOTKEY_SCREEN &&
5573 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_TEAM_SELECT) {
5574 common_select_close();
5575 if ( new_state == GS_STATE_MAIN_MENU ) {
5576 freespace_stop_mission();
5581 case GS_STATE_WEAPON_SELECT:
5582 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_SHIP_SELECT &&
5583 new_state != GS_STATE_HOTKEY_SCREEN &&
5584 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_TEAM_SELECT) {
5585 common_select_close();
5586 if ( new_state == GS_STATE_MAIN_MENU ) {
5587 freespace_stop_mission();
5592 case GS_STATE_TEAM_SELECT:
5593 if ( new_state != GS_STATE_OPTIONS_MENU && new_state != GS_STATE_SHIP_SELECT &&
5594 new_state != GS_STATE_HOTKEY_SCREEN &&
5595 new_state != GS_STATE_BRIEFING && new_state != GS_STATE_WEAPON_SELECT) {
5596 common_select_close();
5597 if ( new_state == GS_STATE_MAIN_MENU ) {
5598 freespace_stop_mission();
5603 case GS_STATE_MAIN_MENU:
5604 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
5611 case GS_STATE_OPTIONS_MENU:
5612 //game_start_time();
5613 if(new_state == GS_STATE_MULTI_JOIN_GAME){
5614 multi_join_clear_game_list();
5616 options_menu_close();
5619 case GS_STATE_BARRACKS_MENU:
5620 if(new_state != GS_STATE_VIEW_MEDALS){
5625 case GS_STATE_MISSION_LOG_SCROLLBACK:
5626 hud_scrollback_close();
5629 case GS_STATE_TRAINING_MENU:
5630 training_menu_close();
5633 case GS_STATE_GAME_PLAY:
5634 if ( !(Game_mode & GM_STANDALONE_SERVER) ) {
5635 player_save_target_and_weapon_link_prefs();
5636 game_stop_looped_sounds();
5639 sound_env_disable();
5640 joy_ff_stop_effects();
5642 // stop game time under certain conditions
5643 if ( end_mission || (Game_mode & GM_NORMAL) || ((Game_mode & GM_MULTIPLAYER) && (new_state == GS_STATE_MULTI_PAUSED)) ){
5648 // shut down any recording or playing demos
5653 // when in multiplayer and going back to the main menu, send a leave game packet
5654 // right away (before calling stop mission). stop_mission was taking to long to
5655 // close mission down and I want people to get notified ASAP.
5656 if ( (Game_mode & GM_MULTIPLAYER) && (new_state == GS_STATE_MAIN_MENU) ){
5657 multi_quit_game(PROMPT_NONE);
5660 freespace_stop_mission();
5661 Game_time_compression = F1_0;
5665 case GS_STATE_TECH_MENU:
5669 case GS_STATE_TRAINING_PAUSED:
5670 Training_num_lines = 0;
5671 // fall through to GS_STATE_GAME_PAUSED
5673 case GS_STATE_GAME_PAUSED:
5675 if ( end_mission ) {
5680 case GS_STATE_DEBUG_PAUSED:
5683 pause_debug_close();
5687 case GS_STATE_HUD_CONFIG:
5691 // join/start a game
5692 case GS_STATE_MULTI_JOIN_GAME:
5693 if(new_state != GS_STATE_OPTIONS_MENU){
5694 multi_join_game_close();
5698 case GS_STATE_MULTI_HOST_SETUP:
5699 case GS_STATE_MULTI_CLIENT_SETUP:
5700 // if this is just the host going into the options screen, don't do anything
5701 if((new_state == GS_STATE_MULTI_HOST_OPTIONS) || (new_state == GS_STATE_OPTIONS_MENU)){
5705 // close down the proper state
5706 if(old_state == GS_STATE_MULTI_HOST_SETUP){
5707 multi_create_game_close();
5709 multi_game_client_setup_close();
5712 // COMMAND LINE OPTION
5713 if (Cmdline_multi_stream_chat_to_file){
5714 if( (new_state != GS_STATE_TEAM_SELECT) && (Multi_chat_stream!=NULL) ) {
5715 cfwrite_string(NOX("-------------------------------------------\n"),Multi_chat_stream);
5716 cfclose(Multi_chat_stream);
5721 case GS_STATE_CONTROL_CONFIG:
5722 control_config_close();
5725 case GS_STATE_DEATH_DIED:
5726 Game_mode &= ~GM_DEAD_DIED;
5728 // early end while respawning or blowing up in a multiplayer game
5729 if((Game_mode & GM_MULTIPLAYER) && ((new_state == GS_STATE_DEBRIEF) || (new_state == GS_STATE_MULTI_DOGFIGHT_DEBRIEF)) ){
5731 freespace_stop_mission();
5735 case GS_STATE_DEATH_BLEW_UP:
5736 Game_mode &= ~GM_DEAD_BLEW_UP;
5738 // for single player, we might reload mission, etc. For multiplayer, look at my new state
5739 // to determine if I should do anything.
5740 if ( !(Game_mode & GM_MULTIPLAYER) ) {
5742 freespace_stop_mission();
5745 // if we are not respawing as an observer or as a player, our new state will not
5746 // be gameplay state.
5747 if ( (new_state != GS_STATE_GAME_PLAY) && (new_state != GS_STATE_MULTI_PAUSED) ) {
5748 game_stop_time(); // hasn't been called yet!!
5749 freespace_stop_mission();
5755 case GS_STATE_CREDITS:
5759 case GS_STATE_VIEW_MEDALS:
5763 case GS_STATE_SHOW_GOALS:
5764 mission_show_goals_close();
5767 case GS_STATE_HOTKEY_SCREEN:
5768 if ( new_state != GS_STATE_OPTIONS_MENU ) {
5769 mission_hotkey_close();
5773 case GS_STATE_MULTI_MISSION_SYNC:
5774 // if we're moving into the options menu, don't do anything
5775 if(new_state == GS_STATE_OPTIONS_MENU){
5779 SDL_assert( Game_mode & GM_MULTIPLAYER );
5781 if ( new_state == GS_STATE_GAME_PLAY ){
5782 // palette_restore_palette();
5784 // change a couple of flags to indicate our state!!!
5785 Net_player->state = NETPLAYER_STATE_IN_MISSION;
5786 send_netplayer_update_packet();
5788 // set the game mode
5789 Game_mode |= GM_IN_MISSION;
5793 case GS_STATE_VIEW_CUTSCENES:
5794 cutscenes_screen_close();
5797 case GS_STATE_MULTI_STD_WAIT:
5798 multi_standalone_wait_close();
5801 case GS_STATE_STANDALONE_MAIN:
5802 standalone_main_close();
5803 if(new_state == GS_STATE_MULTI_STD_WAIT){
5804 init_multiplayer_stats();
5808 case GS_STATE_MULTI_PAUSED:
5809 // if ( end_mission ){
5814 case GS_STATE_INGAME_PRE_JOIN:
5815 multi_ingame_select_close();
5818 case GS_STATE_STANDALONE_POSTGAME:
5819 multi_standalone_postgame_close();
5822 case GS_STATE_INITIAL_PLAYER_SELECT:
5823 player_select_close();
5826 case GS_STATE_MULTI_START_GAME:
5827 multi_start_game_close();
5830 case GS_STATE_MULTI_HOST_OPTIONS:
5831 multi_host_options_close();
5834 case GS_STATE_END_OF_CAMPAIGN:
5835 mission_campaign_end_close();
5838 case GS_STATE_LOOP_BRIEF:
5844 // Called when a state is being entered.
5845 // The current state is set to the state we're entering at
5846 // this point, and old_state is set to the state we're coming
5847 // from. You should never try to change the state
5848 // in here... if you think you need to, you probably really
5849 // need to post an event, not change the state.
5851 void game_enter_state( int old_state, int new_state )
5853 switch (new_state) {
5854 case GS_STATE_MAIN_MENU:
5855 // in multiplayer mode, be sure that we are not doing networking anymore.
5856 if ( Game_mode & GM_MULTIPLAYER ) {
5857 SDL_assert( Net_player != NULL );
5858 Net_player->flags &= ~NETINFO_FLAG_DO_NETWORKING;
5861 Game_time_compression = F1_0;
5863 // determine which ship this guy is currently based on
5864 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
5867 if (Player->on_bastion) {
5875 case GS_STATE_BRIEFING:
5876 main_hall_stop_music();
5877 main_hall_stop_ambient();
5879 if (Game_mode & GM_NORMAL) {
5880 // AL: Don't call freespace_start_mission() if re-entering from ship or weapon select
5881 // MWA: or from options or hotkey screens
5882 // JH: or if the command brief state already did this
5883 if ( (old_state != GS_STATE_OPTIONS_MENU) && (old_state != GS_STATE_HOTKEY_SCREEN)
5884 && (old_state != GS_STATE_SHIP_SELECT) && (old_state != GS_STATE_WEAPON_SELECT)
5885 && (old_state != GS_STATE_CMD_BRIEF) ) {
5886 if ( !game_start_mission() ) // this should put us into a new state on failure!
5890 // maybe play a movie before the briefing. don't play if entering briefing screen from ship or weapon select.
5891 if ( (old_state == GS_STATE_DEBRIEF) || (old_state == GS_STATE_SIMULATOR_ROOM) || (old_state == GS_STATE_MAIN_MENU))
5892 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
5894 Game_time_compression = F1_0;
5896 if ( red_alert_mission() ) {
5897 gameseq_post_event(GS_EVENT_RED_ALERT);
5904 case GS_STATE_DEBRIEF:
5905 game_stop_looped_sounds();
5906 mission_goal_fail_incomplete(); // fail all incomplete goals before entering debriefing
5907 if ( (old_state != GS_STATE_VIEW_MEDALS) && (old_state != GS_STATE_OPTIONS_MENU) ){
5912 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
5913 multi_df_debrief_init();
5916 case GS_STATE_LOAD_MISSION_MENU:
5917 mission_load_menu_init();
5920 case GS_STATE_SIMULATOR_ROOM:
5924 case GS_STATE_CAMPAIGN_ROOM:
5925 campaign_room_init();
5928 case GS_STATE_RED_ALERT:
5929 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
5933 case GS_STATE_CMD_BRIEF: {
5934 int team_num = 0; // team number used as index for which cmd brief to use.
5936 if (old_state == GS_STATE_OPTIONS_MENU) {
5940 main_hall_stop_music();
5941 main_hall_stop_ambient();
5943 if (Game_mode & GM_NORMAL) {
5944 // AL: Don't call freespace_start_mission() if re-entering from ship or weapon select
5945 // MWA: or from options or hotkey screens
5946 // JH: or if the command brief state already did this
5947 if ( (old_state != GS_STATE_OPTIONS_MENU) && (old_state != GS_STATE_HOTKEY_SCREEN)
5948 && (old_state != GS_STATE_SHIP_SELECT) && (old_state != GS_STATE_WEAPON_SELECT) ) {
5949 if ( !game_start_mission() ) // this should put us into a new state on failure!
5954 // maybe play a movie before the briefing. don't play if entering briefing screen from ship or weapon select.
5955 if ( (old_state == GS_STATE_DEBRIEF) || (old_state == GS_STATE_SIMULATOR_ROOM) || (old_state == GS_STATE_MAIN_MENU))
5956 mission_campaign_maybe_play_movie(CAMPAIGN_MOVIE_PRE_MISSION);
5958 cmd_brief_init(team_num);
5964 case GS_STATE_SHIP_SELECT:
5968 case GS_STATE_WEAPON_SELECT:
5969 weapon_select_init();
5972 case GS_STATE_TEAM_SELECT:
5976 case GS_STATE_GAME_PAUSED:
5981 case GS_STATE_DEBUG_PAUSED:
5982 // game_stop_time();
5983 // os_set_title("FreeSpace - PAUSED");
5986 case GS_STATE_TRAINING_PAUSED:
5993 case GS_STATE_OPTIONS_MENU:
5995 options_menu_init();
5998 case GS_STATE_GAME_PLAY:
5999 // coming from the gameplay state or the main menu, we might need to load the mission
6000 if ( (Game_mode & GM_NORMAL) && ((old_state == GS_STATE_MAIN_MENU) || (old_state == GS_STATE_GAME_PLAY) || (old_state == GS_STATE_DEATH_BLEW_UP)) ) {
6001 if ( !game_start_mission() ) // this should put us into a new state.
6006 // if we are coming from the briefing, ship select, weapons loadout, or main menu (in the
6007 // case of quick start), then do bitmap loads, etc Don't do any of the loading stuff
6008 // if we are in multiplayer -- this stuff is all handled in the multi-wait section
6009 if ( !(Game_mode & GM_MULTIPLAYER) && ((old_state == GS_STATE_BRIEFING) || (old_state == GS_STATE_SHIP_SELECT) ||
6010 (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)) ) {
6011 // JAS: Used to do all paging here.
6015 HUD_printf("Skill level is set to ** %s **", Skill_level_names(Game_skill_level));
6019 main_hall_stop_music();
6020 main_hall_stop_ambient();
6021 event_music_first_pattern(); // start the first pattern
6024 // special code that restores player ship selection and weapons loadout when doing a quick start
6025 if ( !(Game_mode & GM_MULTIPLAYER) && ((old_state == GS_STATE_MAIN_MENU) || (old_state == GS_STATE_DEATH_BLEW_UP) || (old_state == GS_STATE_GAME_PLAY)) ) {
6026 if ( !SDL_strcasecmp(Player_loadout.filename, Game_current_mission_filename) ) {
6027 wss_direct_restore_loadout();
6031 // single-player, quick-start after just died... we need to set weapon linking and kick off the event music
6032 if (!(Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_DEATH_BLEW_UP) ) {
6033 event_music_first_pattern(); // start the first pattern
6036 if ( !(Game_mode & GM_STANDALONE_SERVER) && (old_state != GS_STATE_GAME_PAUSED) && (old_state != GS_STATE_MULTI_PAUSED) ) {
6037 event_music_first_pattern(); // start the first pattern
6039 player_restore_target_and_weapon_link_prefs();
6041 Game_mode |= GM_IN_MISSION;
6044 // required to truely make mouse deltas zeroed in debug mouse code
6045 void mouse_force_pos(int x, int y);
6046 if (!Is_standalone) {
6047 mouse_force_pos(gr_screen.max_w / 2, gr_screen.max_h / 2);
6053 // only start time if in single player, or coming from multi wait state
6056 (Game_mode & GM_NORMAL) &&
6057 (old_state != GS_STATE_VIEW_CUTSCENES)
6059 (Game_mode & GM_MULTIPLAYER) && (
6060 (old_state == GS_STATE_MULTI_PAUSED) ||
6061 (old_state == GS_STATE_MULTI_MISSION_SYNC)
6067 // when coming from the multi paused state, reset the timestamps
6068 if ( (Game_mode & GM_MULTIPLAYER) && (old_state == GS_STATE_MULTI_PAUSED) ){
6069 multi_reset_timestamps();
6072 if ((Game_mode & GM_MULTIPLAYER) && (old_state != GS_STATE_DEATH_BLEW_UP) ) {
6073 // initialize all object update details
6074 multi_oo_gameplay_init();
6077 // under certain circumstances, the server should reset the object update rate limiting stuff
6078 if( ((Game_mode & GM_MULTIPLAYER) && (Net_player->flags & NETINFO_FLAG_AM_MASTER)) &&
6079 ((old_state == GS_STATE_MULTI_PAUSED) || (old_state == GS_STATE_MULTI_MISSION_SYNC)) ){
6081 // reinitialize the rate limiting system for all clients
6082 multi_oo_rate_init_all();
6085 // multiplayer clients should always re-initialize their control info rate limiting system
6086 if((Game_mode & GM_MULTIPLAYER) && !(Net_player->flags & NETINFO_FLAG_AM_MASTER)){
6087 multi_oo_rate_init_all();
6091 if(Game_mode & GM_MULTIPLAYER){
6092 multi_ping_reset_players();
6095 Game_subspace_effect = 0;
6096 if (The_mission.flags & MISSION_FLAG_SUBSPACE) {
6097 Game_subspace_effect = 1;
6098 if( !(Game_mode & GM_STANDALONE_SERVER) ){
6099 game_start_subspace_ambient_sound();
6103 sound_env_set(&Game_sound_env);
6104 joy_ff_mission_init(Ship_info[Player_ship->ship_info_index].rotation_time);
6106 // clear multiplayer button info i
6107 extern button_info Multi_ship_status_bi;
6108 memset(&Multi_ship_status_bi, 0, sizeof(button_info));
6111 case GS_STATE_HUD_CONFIG:
6115 case GS_STATE_MULTI_JOIN_GAME:
6116 multi_join_clear_game_list();
6118 if (old_state != GS_STATE_OPTIONS_MENU) {
6119 multi_join_game_init();
6124 case GS_STATE_MULTI_HOST_SETUP:
6125 // don't reinitialize if we're coming back from the host options screen
6126 if ((old_state != GS_STATE_MULTI_HOST_OPTIONS) && (old_state != GS_STATE_OPTIONS_MENU)) {
6127 multi_create_game_init();
6132 case GS_STATE_MULTI_CLIENT_SETUP:
6133 if (old_state != GS_STATE_OPTIONS_MENU) {
6134 multi_game_client_setup_init();
6139 case GS_STATE_CONTROL_CONFIG:
6140 control_config_init();
6143 case GS_STATE_TECH_MENU:
6147 case GS_STATE_BARRACKS_MENU:
6148 if(old_state != GS_STATE_VIEW_MEDALS){
6153 case GS_STATE_MISSION_LOG_SCROLLBACK:
6154 hud_scrollback_init();
6157 case GS_STATE_DEATH_DIED:
6158 Player_died_time = timestamp(10);
6160 if(!(Game_mode & GM_MULTIPLAYER)){
6161 player_show_death_message();
6163 Game_mode |= GM_DEAD_DIED;
6166 case GS_STATE_DEATH_BLEW_UP:
6167 if ( !popupdead_is_active() ) {
6168 Player_ai->target_objnum = -1;
6171 // stop any local EMP effect
6174 Players[Player_num].flags &= ~PLAYER_FLAGS_AUTO_TARGETING; // Prevent immediate switch to a hostile ship.
6175 Game_mode |= GM_DEAD_BLEW_UP;
6176 Show_viewing_from_self = 0;
6178 // timestamp how long we should wait before displaying the died popup
6179 if ( !popupdead_is_active() ) {
6180 Player_died_popup_wait = timestamp(PLAYER_DIED_POPUP_WAIT);
6184 case GS_STATE_GAMEPLAY_HELP:
6185 gameplay_help_init();
6188 case GS_STATE_CREDITS:
6189 main_hall_stop_music();
6190 main_hall_stop_ambient();
6194 case GS_STATE_VIEW_MEDALS:
6195 medal_main_init(Player);
6198 case GS_STATE_SHOW_GOALS:
6199 mission_show_goals_init();
6202 case GS_STATE_HOTKEY_SCREEN:
6203 mission_hotkey_init();
6206 case GS_STATE_MULTI_MISSION_SYNC:
6207 // if we're coming from the options screen, don't do any
6208 if(old_state == GS_STATE_OPTIONS_MENU){
6212 switch(Multi_sync_mode){
6213 case MULTI_SYNC_PRE_BRIEFING:
6214 // if moving from game forming to the team select state
6217 case MULTI_SYNC_POST_BRIEFING:
6218 // if moving from briefing into the mission itself
6221 // tell everyone that we're now loading data
6222 Net_player->state = NETPLAYER_STATE_DATA_LOAD;
6223 send_netplayer_update_packet();
6225 // JAS: Used to do all paging here!!!!
6227 Net_player->state = NETPLAYER_STATE_WAITING;
6228 send_netplayer_update_packet();
6230 Game_time_compression = F1_0;
6232 case MULTI_SYNC_INGAME:
6238 case GS_STATE_VIEW_CUTSCENES:
6239 cutscenes_screen_init();
6242 case GS_STATE_MULTI_STD_WAIT:
6243 multi_standalone_wait_init();
6246 case GS_STATE_STANDALONE_MAIN:
6247 // don't initialize if we're coming from one of these 2 states unless there are no
6248 // players left (reset situation)
6249 if((old_state != GS_STATE_STANDALONE_POSTGAME) || multi_endgame_ending()){
6250 standalone_main_init();
6254 case GS_STATE_MULTI_PAUSED:
6258 case GS_STATE_INGAME_PRE_JOIN:
6259 multi_ingame_select_init();
6262 case GS_STATE_STANDALONE_POSTGAME:
6263 multi_standalone_postgame_init();
6266 case GS_STATE_INITIAL_PLAYER_SELECT:
6267 player_select_init();
6270 case GS_STATE_MULTI_START_GAME:
6271 multi_start_game_init();
6274 case GS_STATE_MULTI_HOST_OPTIONS:
6275 multi_host_options_init();
6278 case GS_STATE_END_OF_CAMPAIGN:
6279 mission_campaign_end_init();
6282 case GS_STATE_LOOP_BRIEF:
6289 // do stuff that may need to be done regardless of state
6290 void game_do_state_common(int state,int no_networking)
6292 game_maybe_draw_mouse(flFrametime); // determine if to draw the mouse this frame
6293 snd_do_frame(); // update sound system
6294 event_music_do_frame(); // music needs to play across many states
6296 multi_log_process();
6298 if (no_networking) {
6302 // maybe do a multiplayer frame based on game mode and state type
6303 if (Game_mode & GM_MULTIPLAYER) {
6305 case GS_STATE_OPTIONS_MENU:
6306 case GS_STATE_GAMEPLAY_HELP:
6307 case GS_STATE_HOTKEY_SCREEN:
6308 case GS_STATE_HUD_CONFIG:
6309 case GS_STATE_CONTROL_CONFIG:
6310 case GS_STATE_MISSION_LOG_SCROLLBACK:
6311 case GS_STATE_SHOW_GOALS:
6312 case GS_STATE_VIEW_CUTSCENES:
6313 case GS_STATE_EVENT_DEBUG:
6314 multi_maybe_do_frame();
6318 game_do_networking();
6322 // Called once a frame.
6323 // You should never try to change the state
6324 // in here... if you think you need to, you probably really
6325 // need to post an event, not change the state.
6326 int Game_do_state_should_skip = 0;
6327 void game_do_state(int state)
6329 // always lets the do_state_common() function determine if the state should be skipped
6330 Game_do_state_should_skip = 0;
6332 // legal to set the should skip state anywhere in this function
6333 game_do_state_common(state); // do stuff that may need to be done regardless of state
6335 if(Game_do_state_should_skip){
6340 case GS_STATE_MAIN_MENU:
6341 game_set_frametime(GS_STATE_MAIN_MENU);
6342 #if defined(PRESS_TOUR_BUILD) || defined(PD_BUILD)
6345 main_hall_do(flFrametime);
6349 case GS_STATE_OPTIONS_MENU:
6350 game_set_frametime(GS_STATE_OPTIONS_MENU);
6351 options_menu_do_frame(flFrametime);
6354 case GS_STATE_BARRACKS_MENU:
6355 game_set_frametime(GS_STATE_BARRACKS_MENU);
6356 barracks_do_frame(flFrametime);
6359 case GS_STATE_TRAINING_MENU:
6360 game_set_frametime(GS_STATE_TRAINING_MENU);
6361 training_menu_do_frame(flFrametime);
6364 case GS_STATE_TECH_MENU:
6365 game_set_frametime(GS_STATE_TECH_MENU);
6366 techroom_do_frame(flFrametime);
6369 case GS_STATE_GAMEPLAY_HELP:
6370 game_set_frametime(GS_STATE_GAMEPLAY_HELP);
6371 gameplay_help_do_frame(flFrametime);
6374 case GS_STATE_GAME_PLAY: // do stuff that should be done during gameplay
6378 case GS_STATE_GAME_PAUSED:
6382 case GS_STATE_DEBUG_PAUSED:
6384 game_set_frametime(GS_STATE_DEBUG_PAUSED);
6389 case GS_STATE_TRAINING_PAUSED:
6390 game_training_pause_do();
6393 case GS_STATE_LOAD_MISSION_MENU:
6394 game_set_frametime(GS_STATE_LOAD_MISSION_MENU);
6395 mission_load_menu_do();
6398 case GS_STATE_BRIEFING:
6399 game_set_frametime(GS_STATE_BRIEFING);
6400 brief_do_frame(flFrametime);
6403 case GS_STATE_DEBRIEF:
6404 game_set_frametime(GS_STATE_DEBRIEF);
6405 debrief_do_frame(flFrametime);
6408 case GS_STATE_MULTI_DOGFIGHT_DEBRIEF:
6409 game_set_frametime(GS_STATE_MULTI_DOGFIGHT_DEBRIEF);
6410 multi_df_debrief_do();
6413 case GS_STATE_SHIP_SELECT:
6414 game_set_frametime(GS_STATE_SHIP_SELECT);
6415 ship_select_do(flFrametime);
6418 case GS_STATE_WEAPON_SELECT:
6419 game_set_frametime(GS_STATE_WEAPON_SELECT);
6420 weapon_select_do(flFrametime);
6423 case GS_STATE_MISSION_LOG_SCROLLBACK:
6424 game_set_frametime(GS_STATE_MISSION_LOG_SCROLLBACK);
6425 hud_scrollback_do_frame(flFrametime);
6428 case GS_STATE_HUD_CONFIG:
6429 game_set_frametime(GS_STATE_HUD_CONFIG);
6430 hud_config_do_frame(flFrametime);
6433 case GS_STATE_MULTI_JOIN_GAME:
6434 game_set_frametime(GS_STATE_MULTI_JOIN_GAME);
6435 multi_join_game_do_frame();
6438 case GS_STATE_MULTI_HOST_SETUP:
6439 game_set_frametime(GS_STATE_MULTI_HOST_SETUP);
6440 multi_create_game_do();
6443 case GS_STATE_MULTI_CLIENT_SETUP:
6444 game_set_frametime(GS_STATE_MULTI_CLIENT_SETUP);
6445 multi_game_client_setup_do_frame();
6448 case GS_STATE_CONTROL_CONFIG:
6449 game_set_frametime(GS_STATE_CONTROL_CONFIG);
6450 control_config_do_frame(flFrametime);
6453 case GS_STATE_DEATH_DIED:
6457 case GS_STATE_DEATH_BLEW_UP:
6461 case GS_STATE_SIMULATOR_ROOM:
6462 game_set_frametime(GS_STATE_SIMULATOR_ROOM);
6463 sim_room_do_frame(flFrametime);
6466 case GS_STATE_CAMPAIGN_ROOM:
6467 game_set_frametime(GS_STATE_CAMPAIGN_ROOM);
6468 campaign_room_do_frame(flFrametime);
6471 case GS_STATE_RED_ALERT:
6472 game_set_frametime(GS_STATE_RED_ALERT);
6473 red_alert_do_frame(flFrametime);
6476 case GS_STATE_CMD_BRIEF:
6477 game_set_frametime(GS_STATE_CMD_BRIEF);
6478 cmd_brief_do_frame(flFrametime);
6481 case GS_STATE_CREDITS:
6482 game_set_frametime(GS_STATE_CREDITS);
6483 credits_do_frame(flFrametime);
6486 case GS_STATE_VIEW_MEDALS:
6487 game_set_frametime(GS_STATE_VIEW_MEDALS);
6491 case GS_STATE_SHOW_GOALS:
6492 game_set_frametime(GS_STATE_SHOW_GOALS);
6493 mission_show_goals_do_frame(flFrametime);
6496 case GS_STATE_HOTKEY_SCREEN:
6497 game_set_frametime(GS_STATE_HOTKEY_SCREEN);
6498 mission_hotkey_do_frame(flFrametime);
6501 case GS_STATE_VIEW_CUTSCENES:
6502 game_set_frametime(GS_STATE_VIEW_CUTSCENES);
6503 cutscenes_screen_do_frame();
6506 case GS_STATE_MULTI_STD_WAIT:
6507 game_set_frametime(GS_STATE_STANDALONE_MAIN);
6508 multi_standalone_wait_do();
6511 case GS_STATE_STANDALONE_MAIN:
6512 game_set_frametime(GS_STATE_STANDALONE_MAIN);
6513 standalone_main_do();
6516 case GS_STATE_MULTI_PAUSED:
6517 game_set_frametime(GS_STATE_MULTI_PAUSED);
6521 case GS_STATE_TEAM_SELECT:
6522 game_set_frametime(GS_STATE_TEAM_SELECT);
6526 case GS_STATE_INGAME_PRE_JOIN:
6527 game_set_frametime(GS_STATE_INGAME_PRE_JOIN);
6528 multi_ingame_select_do();
6531 case GS_STATE_EVENT_DEBUG:
6533 game_set_frametime(GS_STATE_EVENT_DEBUG);
6534 game_show_event_debug(flFrametime);
6538 case GS_STATE_STANDALONE_POSTGAME:
6539 game_set_frametime(GS_STATE_STANDALONE_POSTGAME);
6540 multi_standalone_postgame_do();
6543 case GS_STATE_INITIAL_PLAYER_SELECT:
6544 game_set_frametime(GS_STATE_INITIAL_PLAYER_SELECT);
6548 case GS_STATE_MULTI_MISSION_SYNC:
6549 game_set_frametime(GS_STATE_MULTI_MISSION_SYNC);
6553 case GS_STATE_MULTI_START_GAME:
6554 game_set_frametime(GS_STATE_MULTI_START_GAME);
6555 multi_start_game_do();
6558 case GS_STATE_MULTI_HOST_OPTIONS:
6559 game_set_frametime(GS_STATE_MULTI_HOST_OPTIONS);
6560 multi_host_options_do();
6563 case GS_STATE_END_OF_CAMPAIGN:
6564 mission_campaign_end_do();
6567 case GS_STATE_END_DEMO:
6568 game_set_frametime(GS_STATE_END_DEMO);
6569 end_demo_campaign_do();
6572 case GS_STATE_LOOP_BRIEF:
6573 game_set_frametime(GS_STATE_LOOP_BRIEF);
6577 } // end switch(gs_current_state)
6581 // return 0 if there is enough RAM to run FreeSpace, otherwise return -1
6582 int game_do_ram_check(int ram_in_mbytes)
6584 if ( ram_in_mbytes < 30 ) {
6585 int allowed_to_run = 1;
6586 if ( ram_in_mbytes < 25 ) {
6592 if ( allowed_to_run ) {
6593 SDL_MessageBoxData mboxd;
6594 SDL_MessageBoxButtonData mboxbuttons[2];
6597 // not a translated string, but it's too long and smartdrv isn't
6598 // really a thing for any OS we now support :p
6599 // 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);
6600 sprintf( tmp, "FreeSpace has detected that you only have %dMB of free memory.\n\nFreeSpace requires at least 32MB of memory to run.\n\nPress 'OK' to continue running with less than the minimum required memory.\n", ram_in_mbytes);
6602 mboxbuttons[0].buttonid = 0;
6603 mboxbuttons[0].text = XSTR("Ok", 503);
6604 mboxbuttons[0].flags = 0;
6606 mboxbuttons[1].buttonid = 1;
6607 mboxbuttons[1].text = XSTR("Cancel", 504);
6608 mboxbuttons[0].flags = SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT | SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT;
6610 mboxd.flags = SDL_MESSAGEBOX_ERROR;
6611 mboxd.title = XSTR( "Not Enough RAM", 194);
6612 mboxd.message = tmp;
6613 mboxd.numbuttons = 2;
6614 mboxd.buttons = mboxbuttons;
6615 mboxd.window = NULL;
6616 mboxd.colorScheme = NULL;
6618 SDL_ShowMessageBox(&mboxd, &msgbox_rval);
6620 if ( msgbox_rval == 1 ) {
6624 // not a translated string, but it's too long and smartdrv isn't
6625 // really a thing for any OS we now support :p
6626 // 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);
6627 sprintf( tmp, "FreeSpace has detected that you only have %dMB of free memory.\n\nFreeSpace requires at least 32MB of memory to run.\n", ram_in_mbytes);
6629 SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, XSTR( "Not Enough RAM", 194), tmp, NULL);
6638 // Check if there is a freespace.exe in the /update directory (relative to where fs.exe is installed).
6639 // If so, copy it over and remove the update directory.
6640 void game_maybe_update_launcher(char *exe_dir)
6643 char src_filename[MAX_PATH];
6644 char dest_filename[MAX_PATH];
6646 strcpy(src_filename, exe_dir);
6647 strcat(src_filename, NOX("\\update\\freespace.exe"));
6649 strcpy(dest_filename, exe_dir);
6650 strcat(dest_filename, NOX("\\freespace.exe"));
6652 // see if src_filename exists
6654 fp = fopen(src_filename, "rb");
6660 SetFileAttributes(dest_filename, FILE_ATTRIBUTE_NORMAL);
6662 // copy updated freespace.exe to freespace exe dir
6663 if ( CopyFile(src_filename, dest_filename, 0) == 0 ) {
6664 MessageBox( NULL, XSTR("Unable to copy freespace.exe from update directory to installed directory. You should copy freespace.exe from the update directory (located in your FreeSpace install directory) to your install directory", 988), NULL, MB_OK|MB_TASKMODAL|MB_SETFOREGROUND );
6668 // delete the file in the update directory
6669 DeleteFile(src_filename);
6671 // safe to assume directory is empty, since freespace.exe should only be the file ever in the update dir
6672 char update_dir[MAX_PATH];
6673 strcpy(update_dir, exe_dir);
6674 strcat(update_dir, NOX("\\update"));
6675 RemoveDirectory(update_dir);
6681 void game_spew_pof_info_sub(int model_num, polymodel *pm, int sm, CFILE *out, int *out_total, int *out_destroyed_total)
6685 int sub_total_destroyed = 0;
6689 // get the total for all his children
6690 for (i=pm->submodel[sm].first_child; i>-1; i = pm->submodel[i].next_sibling ) {
6691 game_spew_pof_info_sub(model_num, pm, i, out, &sub_total, &sub_total_destroyed);
6694 // find the # of faces for this _individual_ object
6695 total = submodel_get_num_polys(model_num, sm);
6696 if(strstr(pm->submodel[sm].name, "-destroyed")){
6697 sub_total_destroyed = total;
6701 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[sm].name, total);
6704 *out_total += total + sub_total;
6705 *out_destroyed_total += sub_total_destroyed;
6708 #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);
6709 void game_spew_pof_info()
6711 char *pof_list[1000];
6714 int idx, model_num, i, j;
6716 int total, root_total, model_total, destroyed_total, counted;
6720 num_files = cf_get_file_list(1000, pof_list, CF_TYPE_MODELS, "*.pof");
6722 // spew info on all the pofs
6728 out = cfopen("pofspew.txt", "wt", CFILE_NORMAL, CF_TYPE_DATA);
6733 for(idx=0; idx<num_files; idx++, counted++){
6734 sprintf(str, "%s.pof", pof_list[idx]);
6735 model_num = model_load(str, 0, NULL);
6737 pm = model_get(model_num);
6739 // if we have a real model
6744 // go through and print all raw submodels
6745 cfputs("RAW\n", out);
6748 for (i=0; i<pm->n_models; i++) {
6749 total = submodel_get_num_polys(model_num, i);
6751 model_total += total;
6752 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[i].name, total);
6755 sprintf(str, "Model total %d\n", model_total);
6758 // now go through and do it by LOD
6759 cfputs("BY LOD\n\n", out);
6760 for(i=0; i<pm->n_detail_levels; i++){
6761 sprintf(str, "LOD %d\n", i);
6765 root_total = submodel_get_num_polys(model_num, pm->detail[i] );
6767 destroyed_total = 0;
6768 for (j=pm->submodel[pm->detail[i]].first_child; j>-1; j = pm->submodel[j].next_sibling ) {
6769 game_spew_pof_info_sub(model_num, pm, j, out, &total, &destroyed_total);
6772 sprintf(str, "Submodel %s total : %d faces\n", pm->submodel[pm->detail[i]].name, root_total);
6775 sprintf(str, "TOTAL: %d\n", total + root_total);
6777 sprintf(str, "TOTAL not counting destroyed faces %d\n", (total + root_total) - destroyed_total);
6779 sprintf(str, "TOTAL destroyed faces %d\n\n", destroyed_total);
6782 cfputs("------------------------------------------------------------------------\n\n", out);
6786 if(counted >= MAX_POLYGON_MODELS - 5){
6799 game_spew_pof_info();
6802 int game_main(const char *szCmdLine)
6806 // Find out how much RAM is on this machine
6807 Freespace_total_ram = SDL_GetSystemRAM();
6809 if ( game_do_ram_check(Freespace_total_ram) == -1 ) {
6813 if (!vm_init(24*1024*1024)) {
6814 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);
6818 char *tmp_mem = (char *) malloc(16 * 1024 * 1024);
6820 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);
6829 extern void windebug_memwatch_init();
6830 windebug_memwatch_init();
6838 int cpu_cores = SDL_GetCPUCount();
6839 int le = (SDL_BYTEORDER == SDL_LIL_ENDIAN);
6841 mprintf(("Platform: %s\n", SDL_GetPlatform()));
6842 mprintf(("CPU: %d %s\n", cpu_cores, (cpu_cores == 1) ? "core" : "cores"));
6843 mprintf(("Memory: %dMB\n", Freespace_total_ram));
6844 mprintf(("Build: %d-bit, %s-endian\n", sizeof(void*) * 8, le ? "little" : "big"));
6846 parse_cmdline(szCmdLine);
6848 mprintf(("--------------------------------------------------------------------------------\n"));
6850 #ifdef STANDALONE_ONLY_BUILD
6852 nprintf(("Network", "Standalone running"));
6855 nprintf(("Network", "Standalone running"));
6862 // maybe spew pof stuff
6863 if(Cmdline_spew_pof_info){
6864 game_spew_pof_info();
6869 // non-demo, non-standalone, play the intro movie
6871 if ( !Is_standalone ) {
6873 // release -- movies always play
6876 // 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
6877 movie_play( NOX("intro.mve") );
6879 // debug version, movie will only play with -showmovies
6880 #elif !defined(NDEBUG)
6882 movie_play( NOX("intro.mve") );
6885 if ( Cmdline_show_movies )
6886 movie_play( NOX("intro.mve") );
6895 gameseq_post_event(GS_EVENT_STANDALONE_MAIN);
6897 gameseq_post_event(GS_EVENT_GAME_INIT); // start the game rolling -- check for default pilot, or go to the pilot select screen
6901 // only important for non THREADED mode
6904 state = gameseq_process_events();
6905 if ( state == GS_STATE_QUIT_GAME ){
6910 #if defined(FS2_DEMO) || defined(FS1_DEMO)
6912 demo_upsell_show_screens();
6914 #elif defined(OEM_BUILD)
6915 // show upsell screens on exit
6916 oem_upsell_show_screens();
6923 // launcher the fslauncher program on exit
6924 void game_launch_launcher_on_exit()
6928 PROCESS_INFORMATION pi;
6929 char cmd_line[2048];
6930 char original_path[1024] = "";
6932 memset( &si, 0, sizeof(STARTUPINFO) );
6936 _getcwd(original_path, 1023);
6938 // set up command line
6939 strcpy(cmd_line, original_path);
6940 strcat(cmd_line, "\\");
6941 strcat(cmd_line, LAUNCHER_FNAME);
6942 strcat(cmd_line, " -straight_to_update");
6944 BOOL ret = CreateProcess( NULL, // pointer to name of executable module
6945 cmd_line, // pointer to command line string
6946 NULL, // pointer to process security attributes
6947 NULL, // pointer to thread security attributes
6948 FALSE, // handle inheritance flag
6949 CREATE_DEFAULT_ERROR_MODE, // creation flags
6950 NULL, // pointer to new environment block
6951 NULL, // pointer to current directory name
6952 &si, // pointer to STARTUPINFO
6953 &pi // pointer to PROCESS_INFORMATION
6955 // to eliminate build warnings
6965 // This function is called when FreeSpace terminates normally.
6967 void game_shutdown(void)
6973 // don't ever flip a page on the standalone!
6974 if(!(Game_mode & GM_STANDALONE_SERVER)){
6980 // if the player has left the "player select" screen and quit the game without actually choosing
6981 // a player, Player will be NULL, in which case we shouldn't write the player file out!
6982 if (!(Game_mode & GM_STANDALONE_SERVER) && (Player!=NULL) && !Is_standalone){
6986 // load up common multiplayer icons
6987 multi_unload_common_icons();
6989 shockwave_close(); // release any memory used by shockwave system
6990 fireball_close(); // free fireball system
6991 ship_close(); // free any memory that was allocated for the ships
6992 weapon_close(); // free any memory that was allocated for the weapons
6993 hud_free_scrollback_list();// free space allocated to store hud messages in hud scrollback
6994 unload_animating_pointer();// frees the frames used for the animating mouse pointer
6995 bm_unload_all(); // free bitmaps
6996 mission_campaign_close(); // close out the campaign stuff
6997 mission_campaign_shutdown(); // get anything that mission_campaign_close can't do
6998 multi_voice_close(); // close down multiplayer voice (including freeing buffers, etc)
7000 #ifdef MULTI_USE_LAG
7004 // the menu close functions will unload the bitmaps if they were displayed during the game
7005 #if !defined(PRESS_TOUR_BUILD) && !defined(PD_BUILD)
7008 context_help_close(); // close out help system
7009 training_menu_close();
7010 lcl_close(); // be sure localization is closed out
7013 // free left-over memory from parsed tables
7014 cutscene_tbl_close();
7016 scoring_tbl_close();
7017 player_tips_close();
7019 extern void joy_close();
7022 audiostream_close();
7024 event_music_close();
7028 // HACKITY HACK HACK
7029 // if this flag is set, we should be firing up the launcher when exiting freespace
7030 extern int Multi_update_fireup_launcher_on_exit;
7031 if(Multi_update_fireup_launcher_on_exit){
7032 game_launch_launcher_on_exit();
7036 // game_stop_looped_sounds()
7038 // This function will call the appropriate stop looped sound functions for those
7039 // modules which use looping sounds. It is not enough just to stop a looping sound
7040 // at the DirectSound level, the game is keeping track of looping sounds, and this
7041 // function is used to inform the game that looping sounds are being halted.
7043 void game_stop_looped_sounds()
7045 hud_stop_looped_locking_sounds();
7046 hud_stop_looped_engine_sounds();
7047 afterburner_stop_sounds();
7048 player_stop_looped_sounds();
7049 obj_snd_stop_all(); // stop all object-linked persistant sounds
7050 game_stop_subspace_ambient_sound();
7051 snd_stop(Radar_static_looping);
7052 Radar_static_looping = -1;
7053 snd_stop(Target_static_looping);
7054 shipfx_stop_engine_wash_sound();
7055 Target_static_looping = -1;
7058 //////////////////////////////////////////////////////////////////////////
7060 // Code for supporting an animating mouse pointer
7063 //////////////////////////////////////////////////////////////////////////
7065 typedef struct animating_obj
7074 static animating_obj Animating_mouse;
7076 // ----------------------------------------------------------------------------
7077 // init_animating_pointer()
7079 // Called by load_animating_pointer() to ensure the Animating_mouse struct
7080 // gets properly initialized
7082 void init_animating_pointer()
7084 Animating_mouse.first_frame = -1;
7085 Animating_mouse.num_frames = 0;
7086 Animating_mouse.current_frame = -1;
7087 Animating_mouse.time = 0.0f;
7088 Animating_mouse.elapsed_time = 0.0f;
7091 // ----------------------------------------------------------------------------
7092 // load_animating_pointer()
7094 // Called at game init to load in the frames for the animating mouse pointer
7096 // input: filename => filename of animation file that holds the animation
7098 void load_animating_pointer(const char *filename, int dx, int dy)
7103 init_animating_pointer();
7105 am = &Animating_mouse;
7106 am->first_frame = bm_load_animation(filename, &am->num_frames, &fps);
7107 if ( am->first_frame == -1 )
7108 Error(LOCATION, "Could not load animation %s for the mouse pointer\n", filename);
7109 am->current_frame = 0;
7110 am->time = am->num_frames / i2fl(fps);
7113 // ----------------------------------------------------------------------------
7114 // unload_animating_pointer()
7116 // Called at game shutdown to free the memory used to store the animation frames
7118 void unload_animating_pointer()
7123 am = &Animating_mouse;
7124 for ( i = 0; i < am->num_frames; i++ ) {
7125 SDL_assert( (am->first_frame+i) >= 0 );
7126 bm_release(am->first_frame + i);
7129 am->first_frame = -1;
7131 am->current_frame = -1;
7134 // draw the correct frame of the game mouse... called from game_maybe_draw_mouse()
7135 void game_render_mouse(float frametime)
7140 // if animating cursor exists, play the next frame
7141 am = &Animating_mouse;
7142 if ( am->first_frame != -1 ) {
7143 mouse_get_pos(&mx, &my);
7144 am->elapsed_time += frametime;
7145 am->current_frame = fl2i( ( am->elapsed_time / am->time ) * (am->num_frames-1) );
7146 if ( am->current_frame >= am->num_frames ) {
7147 am->current_frame = 0;
7148 am->elapsed_time = 0.0f;
7150 gr_set_cursor_bitmap(am->first_frame + am->current_frame);
7154 // ----------------------------------------------------------------------------
7155 // game_maybe_draw_mouse()
7157 // determines whether to draw the mouse pointer at all, and what frame of
7158 // animation to use if the mouse is animating
7160 // Sets mouse.cpp globals Mouse_hidden and Mouse_moved based on the state of the game.
7162 // input: frametime => elapsed frame time in seconds since last call
7164 void game_maybe_draw_mouse(float frametime)
7168 game_state = gameseq_get_state();
7170 switch ( game_state ) {
7171 case GS_STATE_GAME_PAUSED:
7172 // case GS_STATE_MULTI_PAUSED:
7173 case GS_STATE_GAME_PLAY:
7174 case GS_STATE_DEATH_DIED:
7175 case GS_STATE_DEATH_BLEW_UP:
7176 if ( popup_active() || popupdead_is_active() ) {
7188 if ( !Mouse_hidden )
7189 game_render_mouse(frametime);
7193 void game_do_training_checks()
7197 waypoint_list *wplp;
7199 if (Training_context & TRAINING_CONTEXT_SPEED) {
7200 s = (int) Player_obj->phys_info.fspeed;
7201 if ((s >= Training_context_speed_min) && (s <= Training_context_speed_max)) {
7202 if (!Training_context_speed_set) {
7203 Training_context_speed_set = 1;
7204 Training_context_speed_timestamp = timestamp();
7208 Training_context_speed_set = 0;
7211 if (Training_context & TRAINING_CONTEXT_FLY_PATH) {
7212 wplp = &Waypoint_lists[Training_context_path];
7213 if (wplp->count > Training_context_goal_waypoint) {
7214 i = Training_context_goal_waypoint;
7216 d = vm_vec_dist(&wplp->waypoints[i], &Player_obj->pos);
7217 if (d <= Training_context_distance) {
7218 Training_context_at_waypoint = i;
7219 if (Training_context_goal_waypoint == i) {
7220 Training_context_goal_waypoint++;
7221 snd_play(&Snds[SND_CARGO_REVEAL], 0.0f);
7228 if (i == wplp->count)
7231 } while (i != Training_context_goal_waypoint);
7235 if ((Players_target == UNINITIALIZED) || (Player_ai->target_objnum != Players_target) || (Player_ai->targeted_subsys != Players_targeted_subsys)) {
7236 Players_target = Player_ai->target_objnum;
7237 Players_targeted_subsys = Player_ai->targeted_subsys;
7238 Players_target_timestamp = timestamp();
7242 /////////// Following is for event debug view screen
7246 #define EVENT_DEBUG_MAX 5000
7247 #define EVENT_DEBUG_EVENT 0x8000
7249 int Event_debug_index[EVENT_DEBUG_MAX];
7252 void game_add_event_debug_index(int n, int indent)
7254 if (ED_count < EVENT_DEBUG_MAX)
7255 Event_debug_index[ED_count++] = n | (indent << 16);
7258 void game_add_event_debug_sexp(int n, int indent)
7263 if (Sexp_nodes[n].first >= 0) {
7264 game_add_event_debug_sexp(Sexp_nodes[n].first, indent);
7265 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent);
7269 game_add_event_debug_index(n, indent);
7270 if (Sexp_nodes[n].subtype == SEXP_ATOM_OPERATOR)
7271 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent + 1);
7273 game_add_event_debug_sexp(Sexp_nodes[n].rest, indent);
7276 void game_event_debug_init()
7281 for (e=0; e<Num_mission_events; e++) {
7282 game_add_event_debug_index(e | EVENT_DEBUG_EVENT, 0);
7283 game_add_event_debug_sexp(Mission_events[e].formula, 1);
7287 void game_show_event_debug(float frametime)
7291 int font_height, font_width;
7293 static int scroll_offset = 0;
7295 k = game_check_key();
7301 if (scroll_offset < 0)
7311 scroll_offset -= 20;
7312 if (scroll_offset < 0)
7317 scroll_offset += 20; // not font-independent, hard-coded since I counted the lines!
7321 gameseq_post_event(GS_EVENT_PREVIOUS_STATE);
7327 gr_set_color_fast(&Color_bright);
7329 gr_printf(0x8000, 5, NOX("EVENT DEBUG VIEW"));
7331 gr_set_color_fast(&Color_normal);
7333 gr_get_string_size(&font_width, &font_height, NOX("test"));
7334 y_max = gr_screen.max_h - font_height - 5;
7338 while (k < ED_count) {
7339 if (y_index > y_max)
7342 z = Event_debug_index[k];
7343 if (z & EVENT_DEBUG_EVENT) {
7345 sprintf(buf, NOX("%s%s (%s) %s%d %d"), (Mission_events[z].flags & MEF_CURRENT) ? NOX("* ") : "",
7346 Mission_events[z].name, Mission_events[z].result ? NOX("True") : NOX("False"),
7347 (Mission_events[z].chain_delay < 0) ? "" : NOX("x "),
7348 Mission_events[z].repeat_count, Mission_events[z].interval);
7356 strcat(buf, Sexp_nodes[z & 0x7fff].text);
7357 switch (Sexp_nodes[z & 0x7fff].value) {
7359 strcat(buf, NOX(" (True)"));
7363 strcat(buf, NOX(" (False)"));
7366 case SEXP_KNOWN_TRUE:
7367 strcat(buf, NOX(" (Always true)"));
7370 case SEXP_KNOWN_FALSE:
7371 strcat(buf, NOX(" (Always false)"));
7374 case SEXP_CANT_EVAL:
7375 strcat(buf, NOX(" (Can't eval)"));
7379 case SEXP_NAN_FOREVER:
7380 strcat(buf, NOX(" (Not a number)"));
7385 gr_printf(10, y_index, buf);
7386 y_index += font_height;
7399 int Tmap_num_too_big = 0;
7400 int Num_models_needing_splitting = 0;
7402 void Time_model( int modelnum )
7404 // mprintf(( "Timing ship '%s'\n", si->name ));
7406 vector eye_pos, model_pos;
7407 matrix eye_orient, model_orient;
7409 polymodel *pm = model_get( modelnum );
7411 int l = strlen(pm->filename);
7413 if ( (l == '/') || (l=='\\') || (l==':')) {
7419 char *pof_file = &pm->filename[l];
7421 int model_needs_splitting = 0;
7423 //fprintf( Texture_fp, "Model: %s\n", pof_file );
7425 for (i=0; i<pm->n_textures; i++ ) {
7426 char filename[1024];
7429 int bmp_num = pm->original_textures[i];
7430 if ( bmp_num > -1 ) {
7431 bm_get_palette(pm->original_textures[i], pal, filename );
7433 bm_get_info( pm->original_textures[i],&w, &h );
7436 if ( (w > 512) || (h > 512) ) {
7437 fprintf( Texture_fp, "%s\t%s\t%d\t%d\n", pof_file, filename, w, h );
7439 model_needs_splitting++;
7442 //fprintf( Texture_fp, "\tTexture %d is bogus\n", i );
7446 if ( model_needs_splitting ) {
7447 Num_models_needing_splitting++;
7449 eye_orient = model_orient = vmd_identity_matrix;
7450 eye_pos = model_pos = vmd_zero_vector;
7452 eye_pos.xyz.z = -pm->rad*2.0f;
7454 vector eye_to_model;
7456 vm_vec_sub( &eye_to_model, &model_pos, &eye_pos );
7457 vm_vector_2_matrix( &eye_orient, &eye_to_model, NULL, NULL );
7459 fix t1 = timer_get_fixed_seconds();
7462 ta.p = ta.b = ta.h = 0.0f;
7465 int bitmaps_used_this_frame, bitmaps_new_this_frame;
7467 bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
7469 modelstats_num_polys = modelstats_num_verts = 0;
7471 while( ta.h < PI2 ) {
7474 vm_angles_2_matrix(&m1, &ta );
7475 vm_matrix_x_matrix( &model_orient, &vmd_identity_matrix, &m1 );
7482 g3_set_view_matrix( &eye_pos, &eye_orient, Viewer_zoom );
7484 model_clear_instance( modelnum );
7485 model_set_detail_level(0); // use highest detail level
7486 model_render( modelnum, &model_orient, &model_pos, MR_LOCK_DETAIL); //|MR_NO_POLYS );
7494 int k = key_inkey();
7495 if ( k == SDLK_ESCAPE ) {
7500 fix t2 = timer_get_fixed_seconds();
7502 if (framecount < 1) {
7506 bm_get_frame_usage(&bitmaps_used_this_frame,&bitmaps_new_this_frame);
7507 //bitmaps_used_this_frame /= framecount;
7509 modelstats_num_polys /= framecount;
7510 modelstats_num_verts /= framecount;
7512 mprintf(( "'%s' is %.2f FPS\n", pof_file, i2fl(framecount)/f2fl(t2-t1) ));
7513 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 );
7515 // 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 );
7521 int Time_models = 0;
7522 DCF_BOOL( time_models, Time_models );
7524 void Do_model_timings_test()
7528 if ( !Time_models ) return;
7530 mprintf(( "Timing models!\n" ));
7534 ubyte model_used[MAX_POLYGON_MODELS];
7535 int model_id[MAX_POLYGON_MODELS];
7536 for (i=0; i<MAX_POLYGON_MODELS; i++ ) {
7541 for (i=0; i<Num_ship_types; i++ ) {
7542 Ship_info[i].modelnum = model_load( Ship_info[i].pof_file, 0, NULL );
7544 model_used[Ship_info[i].modelnum%MAX_POLYGON_MODELS]++;
7545 model_id[Ship_info[i].modelnum%MAX_POLYGON_MODELS] = Ship_info[i].modelnum;
7548 Texture_fp = fopen( NOX("ShipTextures.txt"), "wt" );
7549 if ( !Texture_fp ) return;
7551 Time_fp = fopen( NOX("ShipTimings.txt"), "wt" );
7552 if ( !Time_fp ) return;
7554 fprintf( Time_fp, "Name\tFPS\tTRAM\tPolys\tVerts\tPixels\n" );
7555 // fprintf( Time_fp, "FPS\tTRAM\tPolys\tVerts\tPixels\n" );
7557 for (i=0; i<MAX_POLYGON_MODELS; i++ ) {
7558 if ( model_used[i] ) {
7559 Time_model( model_id[i] );
7563 fprintf( Texture_fp, "Number too big: %d\n", Tmap_num_too_big );
7564 fprintf( Texture_fp, "Number of models needing splitting: %d\n", Num_models_needing_splitting );
7573 // Call this function when you want to inform the player that a feature is not
7574 // enabled in the DEMO version of FreSpace
7575 void game_feature_not_in_demo_popup()
7577 popup(PF_USE_AFFIRMATIVE_ICON|PF_BODY_BIG, 1, POPUP_OK, XSTR( "Sorry, this feature is available only in the retail version", 200));
7580 // format the specified time (fixed point) into a nice string
7581 void game_format_time(fix m_time,char *time_str)
7584 int hours,minutes,seconds;
7587 mtime = f2fl(m_time);
7589 // get the hours, minutes and seconds
7590 hours = (int)(mtime / 3600.0f);
7592 mtime -= (3600.0f * (float)hours);
7594 seconds = (int)mtime%60;
7595 minutes = (int)mtime/60;
7597 // print the hour if necessary
7599 sprintf(time_str,XSTR( "%d:", 201),hours);
7600 // if there are less than 10 minutes, print a leading 0
7602 strcpy(tmp,NOX("0"));
7603 strcat(time_str,tmp);
7607 // print the minutes
7609 sprintf(tmp,XSTR( "%d:", 201),minutes);
7610 strcat(time_str,tmp);
7612 sprintf(time_str,XSTR( "%d:", 201),minutes);
7615 // print the seconds
7617 strcpy(tmp,NOX("0"));
7618 strcat(time_str,tmp);
7620 sprintf(tmp,"%d",seconds);
7621 strcat(time_str,tmp);
7624 // Stuff version string in *str.
7625 void get_version_string(char *str)
7628 if ( FS_VERSION_BUILD == 0 ) {
7629 sprintf(str,"v%d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR);
7631 sprintf(str,"v%d.%02d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR, FS_VERSION_BUILD );
7634 #if defined (FS2_DEMO) || defined(FS1_DEMO)
7636 #elif defined (OEM_BUILD)
7637 strcat(str, " (OEM)");
7643 char myname[_MAX_PATH];
7644 int namelen, major, minor, build, waste;
7645 unsigned int buf_size;
7651 // Find my EXE file name
7652 hMod = GetModuleHandle(NULL);
7653 namelen = GetModuleFileName( hMod, myname, _MAX_PATH );
7655 version_size = GetFileVersionInfoSize(myname, &bogus_handle );
7656 infop = (char *)malloc(version_size);
7657 result = GetFileVersionInfo( myname, 0, version_size, (LPVOID)infop );
7659 // get the product version
7660 result = VerQueryValue((LPVOID)infop, TEXT("\\StringFileInfo\\040904b0\\ProductVersion"), &bufp, &buf_size );
7661 sscanf( (char *)bufp, "%d, %d, %d, %d", &major, &minor, &build, &waste );
7663 sprintf(str,"Dv%d.%02d",major, minor);
7665 sprintf(str,"v%d.%02d",major, minor);
7670 void get_version_string_short(char *str)
7672 sprintf(str,"v%d.%02d",FS_VERSION_MAJOR, FS_VERSION_MINOR);
7675 // ----------------------------------------------------------------
7677 // OEM UPSELL SCREENS BEGIN
7679 // ----------------------------------------------------------------
7680 #if defined(OEM_BUILD)
7682 #define NUM_OEM_UPSELL_SCREENS 3
7683 #define OEM_UPSELL_SCREEN_DELAY 10000
7685 static int Oem_upsell_bitmaps_loaded = 0;
7686 static int Oem_upsell_bitmaps[GR_NUM_RESOLUTIONS][NUM_OEM_UPSELL_SCREENS];
7687 static int Oem_upsell_screen_number = 0;
7688 static int Oem_upsell_show_next_bitmap_time;
7691 static char *Oem_upsell_bitmap_filenames[GR_NUM_RESOLUTIONS][NUM_OEM_UPSELL_SCREENS] =
7704 static int Oem_normal_cursor = -1;
7705 static int Oem_web_cursor = -1;
7706 //#define OEM_UPSELL_URL "http://www.interplay-store.com/"
7707 #define OEM_UPSELL_URL "http://www.interplay.com/cgi-bin/oemlinks.pl/pid=483421&cid=18384"
7709 void oem_upsell_next_screen()
7711 Oem_upsell_screen_number++;
7712 if ( Oem_upsell_screen_number == (NUM_OEM_UPSELL_SCREENS-1) ) {
7713 // extra long delay, mouse shown on last upsell
7714 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY*2;
7718 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY;
7722 void oem_upsell_load_bitmaps()
7726 for ( i = 0; i < NUM_OEM_UPSELL_SCREENS; i++ ) {
7727 Oem_upsell_bitmaps[gr_screen.res][i] = bm_load(Oem_upsell_bitmap_filenames[gr_screen.res][i]);
7731 void oem_upsell_unload_bitmaps()
7735 for ( i = 0; i < NUM_OEM_UPSELL_SCREENS; i++ ) {
7736 if(Oem_upsell_bitmaps[gr_screen.res][i] >= 0){
7737 bm_unload(Oem_upsell_bitmaps[gr_screen.res][i]);
7742 Oem_upsell_bitmaps_loaded = 0;
7745 // clickable hotspot on 3rd OEM upsell screen
7746 static int Oem_upsell3_button_coords[GR_NUM_RESOLUTIONS][4] = {
7748 28, 350, 287, 96 // x, y, w, h
7751 45, 561, 460, 152 // x, y, w, h
7755 void oem_upsell_show_screens()
7757 int current_time, k;
7760 if ( !Oem_upsell_bitmaps_loaded ) {
7761 oem_upsell_load_bitmaps();
7762 Oem_upsell_bitmaps_loaded = 1;
7765 // may use upsell screens more than once
7766 Oem_upsell_show_next_bitmap_time = timer_get_milliseconds() + OEM_UPSELL_SCREEN_DELAY;
7767 Oem_upsell_screen_number = 0;
7773 int nframes; // used to pass, not really needed (should be 1)
7774 Oem_normal_cursor = gr_get_cursor_bitmap();
7775 Oem_web_cursor = bm_load_animation("cursorweb", &nframes);
7776 SDL_assert(Oem_web_cursor >= 0);
7777 if (Oem_web_cursor < 0) {
7778 Oem_web_cursor = Oem_normal_cursor;
7783 //oem_reset_trailer_timer();
7785 current_time = timer_get_milliseconds();
7790 // advance screen on keypress or timeout
7791 if (( k > 0 ) || (mouse_up_count(MOUSE_LEFT_BUTTON) > 0) || (current_time > Oem_upsell_show_next_bitmap_time)) {
7792 oem_upsell_next_screen();
7795 // check if we are done
7796 if ( Oem_upsell_screen_number >= NUM_OEM_UPSELL_SCREENS ) {
7797 Oem_upsell_screen_number--;
7800 if ( Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number] < 0 ) {
7805 // show me the upsell
7806 if ( Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number] >= 0 ) {
7807 gr_set_bitmap(Oem_upsell_bitmaps[gr_screen.res][Oem_upsell_screen_number]);
7811 // if this is the 3rd upsell, make it clickable, d00d
7812 if ( Oem_upsell_screen_number == NUM_OEM_UPSELL_SCREENS-1 ) {
7814 int button_state = mouse_get_pos(&mx, &my);
7815 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])
7816 && (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]) )
7819 gr_set_cursor_bitmap(Oem_web_cursor); //, GR_CURSOR_LOCK);
7822 if (button_state & MOUSE_LEFT_BUTTON) {
7824 multi_pxo_url(OEM_UPSELL_URL);
7828 // switch cursor back to normal one
7829 gr_set_cursor_bitmap(Oem_normal_cursor); //, GR_CURSOR_UNLOCK);
7834 if (gameseq_get_state() != GS_STATE_END_DEMO) {
7844 oem_upsell_unload_bitmaps();
7846 // switch cursor back to normal one
7847 gr_set_cursor_bitmap(Oem_normal_cursor); //, GR_CURSOR_UNLOCK);
7851 #endif // defined(OEM_BUILD)
7852 // ----------------------------------------------------------------
7854 // OEM UPSELL SCREENS END
7856 // ----------------------------------------------------------------
7860 // ----------------------------------------------------------------
7862 // DEMO UPSELL SCREENS BEGIN
7864 // ----------------------------------------------------------------
7866 #if defined(FS2_DEMO) || defined(FS1_DEMO)
7869 #define NUM_DEMO_UPSELL_SCREENS 2
7871 #define NUM_DEMO_UPSELL_SCREENS 4
7873 #define DEMO_UPSELL_SCREEN_DELAY 3000
7875 static int Demo_upsell_bitmaps_loaded = 0;
7876 static int Demo_upsell_bitmaps[GR_NUM_RESOLUTIONS][NUM_DEMO_UPSELL_SCREENS];
7877 static int Demo_upsell_screen_number = 0;
7878 static int Demo_upsell_show_next_bitmap_time;
7881 static char *Demo_upsell_bitmap_filenames[GR_NUM_RESOLUTIONS][NUM_DEMO_UPSELL_SCREENS] =
7907 void demo_upsell_next_screen()
7909 Demo_upsell_screen_number++;
7910 if ( Demo_upsell_screen_number == (NUM_DEMO_UPSELL_SCREENS-1) ) {
7911 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY*4;
7913 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY;
7917 void demo_upsell_load_bitmaps()
7921 for ( i = 0; i < NUM_DEMO_UPSELL_SCREENS; i++ ) {
7922 Demo_upsell_bitmaps[gr_screen.res][i] = bm_load(Demo_upsell_bitmap_filenames[gr_screen.res][i]);
7926 void demo_upsell_unload_bitmaps()
7930 for ( i = 0; i < NUM_DEMO_UPSELL_SCREENS; i++ ) {
7931 if(Demo_upsell_bitmaps[gr_screen.res][i] >= 0){
7932 bm_unload(Demo_upsell_bitmaps[gr_screen.res][i]);
7937 Demo_upsell_bitmaps_loaded = 0;
7940 void demo_upsell_show_screens()
7942 int current_time, k;
7945 if ( !Demo_upsell_bitmaps_loaded ) {
7946 demo_upsell_load_bitmaps();
7947 Demo_upsell_bitmaps_loaded = 1;
7950 // may use upsell screens more than once
7951 Demo_upsell_show_next_bitmap_time = timer_get_milliseconds() + DEMO_UPSELL_SCREEN_DELAY;
7952 Demo_upsell_screen_number = 0;
7959 demo_reset_trailer_timer();
7961 current_time = timer_get_milliseconds();
7968 // don't time out, wait for keypress
7970 if ( current_time > Demo_upsell_show_next_bitmap_time ) {
7971 demo_upsell_next_screen();
7976 demo_upsell_next_screen();
7979 if ( Demo_upsell_screen_number >= NUM_DEMO_UPSELL_SCREENS ) {
7980 Demo_upsell_screen_number--;
7983 if ( Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number] < 0 ) {
7988 if ( Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number] >= 0 ) {
7989 gr_set_bitmap(Demo_upsell_bitmaps[gr_screen.res][Demo_upsell_screen_number]);
7994 if (gameseq_get_state() != GS_STATE_END_DEMO) {
8004 demo_upsell_unload_bitmaps();
8009 // ----------------------------------------------------------------
8011 // DEMO UPSELL SCREENS END
8013 // ----------------------------------------------------------------
8016 // ----------------------------------------------------------------
8018 // Subspace Ambient Sound START
8020 // ----------------------------------------------------------------
8022 static int Subspace_ambient_left_channel = -1;
8023 static int Subspace_ambient_right_channel = -1;
8026 void game_start_subspace_ambient_sound()
8028 if ( Subspace_ambient_left_channel < 0 ) {
8029 Subspace_ambient_left_channel = snd_play_looping(&Snds[SND_SUBSPACE_LEFT_CHANNEL], -1.0f);
8032 if ( Subspace_ambient_right_channel < 0 ) {
8033 Subspace_ambient_right_channel = snd_play_looping(&Snds[SND_SUBSPACE_RIGHT_CHANNEL], 1.0f);
8037 void game_stop_subspace_ambient_sound()
8039 if ( Subspace_ambient_left_channel >= 0 ) {
8040 snd_stop(Subspace_ambient_left_channel);
8041 Subspace_ambient_left_channel = -1;
8044 if ( Subspace_ambient_right_channel >= 0 ) {
8045 snd_stop(Subspace_ambient_right_channel);
8046 Subspace_ambient_right_channel = -1;
8050 // ----------------------------------------------------------------
8052 // Subspace Ambient Sound END
8054 // ----------------------------------------------------------------
8056 // ----------------------------------------------------------------
8058 // Language Autodetection stuff
8061 // this layout order must match Lcl_languages in localize.cpp in order for the
8062 // correct language to be detected
8063 int Lang_auto_detect_checksums[LCL_NUM_LANGUAGES] = {
8065 1366105450, // English
8067 589986744, // English
8069 -1132430286, // German
8071 -1131728960, // Polish
8074 // default setting is "-1" to use config file with English as fall back
8075 // DO NOT change the default setting here or something uncouth might happen
8076 // in the localization code
8082 // try and open the file to verify
8083 CFILE *detect = cfopen("font01.vf", "rb");
8085 // will use default setting if something went wrong
8090 // get the long checksum of the file
8092 cfseek(detect, 0, SEEK_SET);
8093 cf_chksum_long(detect, &file_checksum);
8097 // now compare the checksum/filesize against known #'s
8098 for (idx=0; idx<LCL_NUM_LANGUAGES; idx++) {
8099 if (Lang_auto_detect_checksums[idx] == (int)file_checksum) {
8104 // notify if a match was not found, include detected checksum
8105 printf("ERROR: Unknown Language Checksum: %i\n", (int)file_checksum);
8106 printf("Using default language...\n\n");
8112 // End Auto Lang stuff
8114 // ----------------------------------------------------------------
8116 // ----------------------------------------------------------------
8117 // SHIPS TBL VERIFICATION STUFF
8120 // checksums, just keep a list of all valid ones, if it matches any of them, keep it
8121 #if defined(MAKE_FS1) && !defined(FS1_DEMO)
8122 #define NUM_SHIPS_TBL_CHECKSUMS 3
8124 #define NUM_SHIPS_TBL_CHECKSUMS 1
8128 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8129 1696074201, // FS2 demo
8132 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8133 1603375034, // FS1 DEMO
8136 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8137 -129679197, // FS1 Full 1.06 (US)
8138 7762567, // FS1 SilentThreat
8139 1555372475 // FS1 Full 1.06 (German)
8143 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8144 -463907578, // US - beta 1
8145 1696074201, // FS2 demo
8148 int Game_ships_tbl_checksums[NUM_SHIPS_TBL_CHECKSUMS] = {
8149 // -1022810006, // 1.0 FULL
8150 -1254285366 // 1.2 FULL (German)
8154 void verify_ships_tbl()
8158 Game_ships_tbl_valid = 1;
8164 // detect if the packfile exists
8165 CFILE *detect = cfopen("ships.tbl", "rb");
8166 Game_ships_tbl_valid = 0;
8170 Game_ships_tbl_valid = 0;
8174 // get the long checksum of the file
8176 cfseek(detect, 0, SEEK_SET);
8177 cf_chksum_long(detect, &file_checksum);
8181 // now compare the checksum/filesize against known #'s
8182 for(idx=0; idx<NUM_SHIPS_TBL_CHECKSUMS; idx++){
8183 if(Game_ships_tbl_checksums[idx] == (int)file_checksum){
8184 Game_ships_tbl_valid = 1;
8191 DCF(shipspew, "display the checksum for the current ships.tbl")
8194 CFILE *detect = cfopen("ships.tbl", "rb");
8195 // get the long checksum of the file
8197 cfseek(detect, 0, SEEK_SET);
8198 cf_chksum_long(detect, &file_checksum);
8201 dc_printf("%d", file_checksum);
8204 // ----------------------------------------------------------------
8205 // WEAPONS TBL VERIFICATION STUFF
8208 // checksums, just keep a list of all valid ones, if it matches any of them, keep it
8209 #if defined(MAKE_FS1) && !defined(FS1_DEMO)
8210 #define NUM_WEAPONS_TBL_CHECKSUMS 3
8212 #define NUM_WEAPONS_TBL_CHECKSUMS 1
8216 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
8217 -266420030, // demo 1
8220 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
8221 -1246928725, // FS1 DEMO
8224 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
8225 -834598107, // FS1 1.06 Full (US)
8226 -1652231417, // FS1 SilentThreat
8227 720209793 // FS1 1.06 Full (German)
8231 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
8232 141718090, // US - beta 1
8233 -266420030, // demo 1
8236 int Game_weapons_tbl_checksums[NUM_WEAPONS_TBL_CHECKSUMS] = {
8237 // 399297860, // 1.0 FULL
8238 -553984927 // 1.2 FULL (german)
8242 void verify_weapons_tbl()
8246 Game_weapons_tbl_valid = 1;
8252 // detect if the packfile exists
8253 CFILE *detect = cfopen("weapons.tbl", "rb");
8254 Game_weapons_tbl_valid = 0;
8258 Game_weapons_tbl_valid = 0;
8262 // get the long checksum of the file
8264 cfseek(detect, 0, SEEK_SET);
8265 cf_chksum_long(detect, &file_checksum);
8269 // now compare the checksum/filesize against known #'s
8270 for(idx=0; idx<NUM_WEAPONS_TBL_CHECKSUMS; idx++){
8271 if(Game_weapons_tbl_checksums[idx] == (int)file_checksum){
8272 Game_weapons_tbl_valid = 1;
8279 DCF(wepspew, "display the checksum for the current weapons.tbl")
8282 CFILE *detect = cfopen("weapons.tbl", "rb");
8283 // get the long checksum of the file
8285 cfseek(detect, 0, SEEK_SET);
8286 cf_chksum_long(detect, &file_checksum);
8289 dc_printf("%d", file_checksum);
8292 // if the game is running using hacked data
8293 int game_hacked_data()
8296 if(!Game_weapons_tbl_valid || !Game_ships_tbl_valid){
8304 void display_title_screen()
8306 #if defined(FS2_DEMO) || defined(OEM_BUILD) || defined(FS1_DEMO)
8307 ///int title_bitmap;
8310 int title_bitmap = bm_load(Game_demo_title_screen_fname[gr_screen.res]);
8311 if (title_bitmap == -1) {
8316 gr_set_bitmap(title_bitmap);
8324 bm_unload(title_bitmap);
8325 #endif // FS2_DEMO || OEM_BUILD || FS1_DEMO
8328 // return true if the game is running with "low memory", which is less than 48MB
8329 bool game_using_low_mem()
8331 if (Use_low_mem == 0) {